diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..be3ac26 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,66 @@ +PLIB was originally written by Steve Baker as a solo project - but +has subsequently been greatly enhanced and expanded by a 'cast of +thousands'. + +Most important of all - the 'official' PLIB developers: + + Alex Perry + Curtis Olson + Ben Woodhead + Dave McClurg + Gerard Decatrel + Gil Carter + Giancarlo Niccolai + James Jones + John Fay ("Mr. PUI") + Juergen Marquardt + Mark Vallevand + Marten Stromberg + Nathan Matias + Norman Vine + Per Liedman + Sam Stickland + Sebastian Ude + Steve Baker <--- Hmmm - must sort this list by SECOND name! + Will Lachance + Wolfram Kuss + +Then, the non-registered contributors: + + (Apologies to anyone I've left + out - please let me know who + you are and I'll add you in.) + + Andrew Ross + Christopher St.John + Christian Mayer + Darrell Walisser + Dave Heil + Erik Hofman + Kevin Thompson + Karl Kremer + Negative0 <---- Who? Some kind of 1's complement arithmetic fanatic? + Mark Danks + Michael Kurth + Sean Palmer + Simon Britnell + Themie Gouthas + Tony Knienieder + Trent Gamblin + +Special mention must go to: + + Daryll Strauss (GLIDE port to Linux) + David Bucciarelli (Mesa -> GLIDE interface) + Brian Paul (Mesa) + Curtis Olson (FlightGear guru and all-round "Mr Nice Guy", + who nagged me into writing most of this stuff!) + Vasily Lewis (Tireless maintainer and sysadmin at Woodsoup + where PLIB was first hosted) + Toru Egashira (Who wrote a program called 'NSPmod' which was + the original basis of the SL 'MOD' player - + although the original code has been almost + entirely rewritten in the process of merging + it with SL. + Everyone at OPENGL-GAMEDEV-L + diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..018efbc --- /dev/null +++ b/COPYING @@ -0,0 +1,496 @@ + +SPECIAL NOTICE: + + As a special exception Steve Baker gives permission to link these + libraries with proprietary software and distribute the resulting + executable without including that proprietary code in any distribution + as the LGPL would normally dictate. + + This exception is ONLY granted in the case of an embedded system in + which there is no possibility of an end user re-linking or recompiling + against new versions of this library that may appear in the future. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..233558b --- /dev/null +++ b/ChangeLog @@ -0,0 +1,1102 @@ + +PLIB Change Log. +================ + + +PLIB v1.8.5 (Oct 2006) +~~~~~~~~~~~~~~~~~~~~~~ + + + * removed several widgets from pui/, which were declared + obsolete since a long time. Most of them are now available + in puAux/ + + * several fixes and improvements to puAuxList + + * puInputText scrolling fixed. + + * Improved DirectX loader. + + * Check ownership before deleting in ssgSimpleList. + + * Fixed netSocket. + + * Fixed mem leak in ssgVertSplitter. + + * Fixed pw window sizes on win32. + + * Added pview ssg-example. + + * Fix clock delta in first call. + + * Made colour of listbox changable. + + * Fixed text with negative coordinates + + * Fixed misc bugs in puAuxLargeInput + + * Allow the user to activate a widget with custom mouse button. + + * Made material loading from wavefront models more robust. + + * Handle linux joysticks with a lot of axes. + + * Avoid specular anomalies in 3ds files. + + * Added a demo for ssgaShapes. + + * Fixed the diameter of ssgaSphere. + + * Fixed inability to add colour to the ssgaTeapot. + + * Remove scale dep in ssgaFire + + + +PLIB v1.8.4 (Jan 2005) +~~~~~~~~~~~~~~~~~ + + * Added a way to get SSG intersection tests to work with + backfacing polygons. + + * Added ssgaScreenDepthDump into ssgAux. + + * Several fixes for FreeBSD included. + + * Added exporter for OpenInventor. + + * Implemented im- and exporter for ASC files. + + * Optimisations. + + * Various (minor) improvements to ASE, MDL, PCX and X loading and ASE saving. + + * Implemented ssgAnimTransforms. + + * AC loader now reads "crease" lines and creates much smaller and + cleaner scene graphs. + + * Joystick code adapted to current OS versions (especially Linux). + + +PLIB v1.8.3 (April 8th 2004) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + * NET now allows a NULL argument to netSocket::accept + + * Added #include to all top level header files + in order to ensure that NULL is defined. + + * Added ssgaScreenDump into ssgAux.dsp + + * Cleaned up some warnings from MSVC. + + * Added Christos Dimitrakakis' fixes to SL to prevent + crackling in certain envelope conditions. + + * Added pwAutoRepeatKey to control keyboard auto-repeat. + + * Fixed a horrific bug in the sgDistToLineSegment routines. + + +PLIB v1.8.2 (March 26th 2004) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + * PW now runs on Mac and MacOSX. + + * Uppercase keystrokes now work in PW for Windows. + + * Version number in ul.h now set correctly. + + * Package now builds correctly under MSVC. + +PLIB v1.8.1 (March 21th 2004) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + * puAux library wouldn't build without GLUT being + installed...that's fixed. + + * the NET library examples needed some love and + attention. They are much more useful now! + +PLIB v1.8.0 (March 19th 2004) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + * puAux library added to provide a place for the + more obscure PUI widgets. + + * PW (PLIB Windowing) library added to provide a + built-in alternative to windowing libraries such + as GLUT and SDL. Applications that only need a + single window, mouse and keyboard (and no other + features of GLUT) can now have no dependencies + whatever outside of PLIB and OpenGL. + + * PLIB is now completely independent of GLUT. You + can even build it without GLUT being installed. + Modules to allow PUI to work with GLUT, freeglut, + SDL, FLTK and our own PW windowing library are + provided. + + * ssgAux now includes a relatively simple sky model + kindly donated by the SimGear project. Now you + can have sun, moon, stars and clouds with just + a handful of function calls. + + * PSL - a C-like interpreted scripting language + is now bundled into PLIB. It's a byte-code + interpreter - and it has some useful properties + for games and other interactive packages in + that it allows the application much finer control + over the running of the script(s) than traditional + scripting engines. + + * In the demos area, we added the 'simon' package + which provides a simple framework for PSL scripts + to be loaded - and they may in turn load 3D models, + move them around, etc. Astropong.psl (a simple 3D + 'Pong' game in PSL) is provided as a demo. + +And of course, many bugs have been slain and numerous +other smaller features have been added. + + +PLIB v1.6.0 (Sept 2nd 2002) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It's been over a year since the last PLIB release +and we have been somewhat lax about maintaining a +list of changes. + +Some highlights are: + + * Significant improvements and cleanup throughout PLIB, + especially in PUI. + + * ssgAux library added - includes handy classes for + more sophisticated effects layered on top of SSG. + + + Standard shapes like cubes, spheres, + cylinders and teapots. + + + Water waves. + + + Fire. + + + Particle Systems + + + Lens Flare. + + * More example programs. + + * P-Guide GUI builder for PUI. + + * JS promoted to a full library. + +PLIB v1.5.1 (July 21st 2001) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + * Added ssgTween and ssgTweenController + + * Added puFileSelector - henceforth puFilePicker is deprecated. + + * Added ulList + + * Added VRML loader (this one works!) + + * Numerous bug fixes in other loaders. + + * Added TopHat support to JS + + * Added support for >3 simultaneous sounds in SL. + (You have to explicitly enable that though - it's not + the default) + + * Fixed bugs in util's directory handling. + + * puInput and puListBox now cope better with text that + is too big for the widget + + * puListBox (and hence puFileSelector and puFilePicker) + works with both large and small font sizes. + + * puDial changed to be derived from puSlider - many + consequences of that change will be visible in the + application. (eg output range is 0..1 and not 0..360) + + * PUI widgets are now 'sticky' so that if you are + dragging a slider along a puSlider and your mouse + slips off the edge of it, it'll still have "focus". + + * Added sgLerpAnglesVec3 to linearly interpolate + angles allowing for the nasty wrap-around-360 + problem. + + * Added sgLineSegment3ToLine3, sgDistSquaredToLineVec3 + sgDistSquaredToLineSegmentVec3, sgDistToLineVec3 and + sgDistToLineSegmentVec3. Also sgLine3 and sgLineSegment3 + structures. + + * Added a 'Gallery' page to the documentation to show + potential developers the range of applications that use + PLIB - and also to promote things our developers have done. + To save download time and CVS space, the actual images + are not in the PLIB tarball. + +PLIB v1.4.2 (July 21st 2001) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + * Changes in NET to allow compilation under RedHat 7.1 + + * Fixed a small bug in ssgaSphere + + * Fixes a small bug in puFilePicker + +PLIB v1.4.1 (June 25th 2001) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + * Converted MSVC project files to 'BINARY' in the CVS archive + because some versions of MSVC don't line UNIX-style line endings. + + * Many improvements and bug fixes to puFileSelector and puListBox. + + * Minor fix to NET to accomodate Solaris users. + + * Fixed puMenuBar so it highlights as you drag the mouse across it. + + * Fixed ulOpenDir so it returns NULL on error on non-MSVC systems + + * Changed colour of text on buttons in documentation to make them + easier to read by colour-blind users. + +PLIB v1.5.0 (June 20th 2001) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + * Just a 'place holder' - actually identical to 1.4.0. + +PLIB v1.4.0 (June 20th 2001) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + * Fixed example programs so they don't use the obsolete _SSG_TYPE + tags. + + * Removed multiplie tags on web pages. + + * Updated 'AUTHORS' file. + + * Added 'demos' to the CVS repository. + +PLIB v1.3.3 (June 18th 2001) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + * Various warnings cleaned up under MSVC. + + * Fixed function prototypes for the Quaternion functions in SG + + * Fixed bug in sgEulerToQuat where the angles were not being + converted from degrees to radians. + + * Changed PUI to make sliders and dial widgets grab a hold + of the mouse focus and not release it until the button is + released. This is a subtle but important behavioural change. + + * puDial's are now derived from puSlider's - one side-effect of + that is that they now return 0..1 rather than 0..360 and no + longer support the maximum and minimum range functions. + +PLIB v1.3.2 (June 13th 2001) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + * This CHANGES file has regrettably not been well maintained, + hence there a numerous changes not listed here. + + * File loaders now require app to pass 'ssgLoaderOptions' + rather than other ad-hoc callback function hooks. + + * Added Active Widget Implementation (pui) + + * Added puFilePicker + + * Added Ref Counting to ssgState + + * Added puBiSlider and puTriSlider + + * Added some missing 'AUTHORS' entries. + + * puDial widget (was actually in 1.3.1 but got + missed in the 'CHANGES' file) + + * Fixed a problem in the configure.in that prevented + ssgAux from building. + + * Moved the 'name' and 'user_data' (with associated + set/get member functions) from ssgEntity down into + ssgBase so that these functions will work with ssgState + and ssgTexture objects. This is needed for PrettyPoly. + +PLIB v1.3.1 (Sept 15th 2000) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + * Changed License conditions to specifically permit + use of PLIB outside of LGPL for embedded applications. + + * There is now a task and bug tracking system for PLIB + on Sourceforge. + + * Configuration/Install tool changed to support CygWin + better than in the past. + + * PLIB examples' data files consolidated into a single + 'examples/data' directory. + + * PLIB's documentation is now under CVS. + + * Added 'SSGAUX' library - include + and link to /usr/lib/libplibssgaux.a + + * Aux library has 'ssga' classes to add high level + shapes such as cylinders, cubes and spheres (two + different kinds). + + * Lots of new example programs. + + New PUI 'complex' uses multiple windows. + + Cute 'waving flag' demo + + Working Quaternions versus Eulers demo + + Model viewer (this is actually a useful + program - as well as a demo). + + * More const-correctness throughout library. + + * OPTIONAL support for PNG image loading (you have + to compile PLIB specially to get this because it + introduces an additional dependancy). + + * PLIB now checks that a valid OpenGL rendering + context exists when the various ssgInit/puInit/etc + routines are called. + + * PUI hasi: + + better support for multiple windows, + + a new function to allow the deletion of an object + within one of it's own callbacks. + + the ability to operate in a separate OpenGL + coordinate space. + + puFilePicker and puListBox + + enhancements to puSlider + + * SL has a completely new audio driver for SGI's IRIX. + Unfortunately, we don't think it fixes the long-standing + timing problems for audio under IRIX. + + * SSG's ssgVtxArray and ssgIndexArray now use 'short's for + indices - which is more efficient on most OpenGL's. + + * Several bugs fixed in SSG - also some changes to make it + more suited to embedded use in game consoles and such. + + * Many improvements to SSG's post-processing tools that are + typically applied to scene graph fragments after loading + from disk. + + * SSG now permits you to disable MIPmapping for selected + textures. + + * SSG's print() functions now work for more classes and + produce more useful output. + + * Code for ssgVtxArray streamlined. + + * Added a 'Lookat' function for SSG's camera model. + + * ssgSelectors can now have more than 32 kids. + + * ssgContext had incorrect defaults for the camera + orientation. + + * Some loaders were not sharing ssgState's between + polygons - that's fixed. + + * 3DS loader has had numerous improvements...but the + limitations of this format are becoming evident. + + * All error/warning handling is now done through a + centralized handler that can be redirected (eg to + send errors to a popup window or something) + + * Some bugs fixed in ASE loader. It now uses + ssgVtxArray primitives. + + * Added a loader for the Quake 'MD2' format. It + seems to work amazingly well. + + * Added 'UL' library. Applications MUST link to + -lplibul (/usr/lib/libplibul.a) - and should + include and call ulInit() before + making UL calls. + + If you use automake/autoconf, then it's easy + to make applications that will compile and link + under both PLIB 1.2 and 1.3/1.4, just add this: + + AC_CHECK_LIB(plibul, ulInit,,,) + + libplibul currently contains: + + + Fast, portable clock/timer routines. + + Low level networking code. + + Some directory searching routines. + + * Documents and Examples are now under CVS. + + * Added Tools and Auxlibs folders for future + work. + + +PLIB v1.3.0 (July 1st 2000) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + * Unstable version of 1.2.0, no significant code + changes. + +PLIB v1.2.0 (July 1st 2000) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + * Stable version of 1.1.12, no significant code + changes. + +PLIB v1.1.12 (June 24th 2000) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Fixed some compilation problems for Macintosh/Codewarrior + which treats 'xor' and 'or' as reserved words!! Yikes! + Thanks to Darrell Walisser for that piece of nasty news. + + * Fixed some problems in slMODinst.cxx that were causing + compilation warnings under windoze (thanks to Bram Stolk) + + * Changed SL to open audio devices with O_NONBLOCK - + thanks to Trent Gamblin for spotting this one. + + * Added configure.in check for libdl to cover bug in ld.so + under Linux. Application programs under Linux need to + link to libdl.so in order to work around this. + Ben Woodhead added this. + + * Added Borland project files, thanks to Dave Heil for + contributing these. + + * Swapped order of multiplication in sgMultMat4. Thanks to + Lucas Ackerman for spotting this one. + + * Added a unique ID field to every node in the scene graph. + This helps out some picking algorithms in PPE. + + * Added some more ifdefs to make PLIB Audio/JS components + to make them work under NetBSD. (They already work with + FreeBSD and OpenBSD). Many thanks to Rene Hexel! + + * Fixed a ref() problem with ssgVtxTable::clone - thanks + to Will Weisser for catching that one! + + * Added checks to ensure that a valid OpenGL rendering + context exists before ssgInit/puiInit/fnt-loaders are + called. + + * Added Dave McClurg's ASE loader and matching writer. + If you use the new 'ssgLoad()/ssgSave()' functions, + it'll "just work" - if you prefer you can call + ssgLoadASE/ssgSaveASE analogously to all the other + loaders. + + * Several fixes to the quaternion code in SG were + contributed by "Negative0" + (Who was that masked man?) + +PLIB v1.1.11 (Feb 9th 2000) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Fixed a tiny problem with double-sided polygons. + +PLIB v1.1.10 (Feb 9th 2000) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Added ssgLoad and ssgSave that look at the + filename extension and call the appropriate + lower level load/save routine. + + * Added a 'clone' function for all SSG classes. + + * PLIB now managed under CVS at SourceForge. + + http://sourceforge.net/project/?group_id=382 + + * Added a collection of line/plane, plane/plane + and line/line intersection routines to SG. + Thanks to Norman Vine for most of them. + + * Fixed a bug in SSG file loader that would + prevent recognition of obsolete SSG file + types. + +PLIB v1.1.9 (Jan 28th 2000) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Fixed bug that caused the ref counts of the + various vertex arrays in an ssgVtxTable to + be incorrectly set to zero when that VtxTable + is loaded from an '.ssg' format file. + This tended to crash SSG with an assertion + failure whenever you deleted an object + loaded from a '.ssg' file. + + * Added the current texture map filename to + ssgSimpleState and ssgStateSelector - which + means that... + + * The SSG file format finally works correctly. + Note that any SSG files you might have created + before this release won't work anymore...but + then they didn't work correctly before. + +PLIB v1.1.8 (Jan 23rd 2000) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Added ssgContext. This makes it a lot easier + to write programs that need to render multiple + eyepoints in quick succession. + + * Added functionality to ssgVtxTable to enable + applications to construct a vertex table and + then add the vertex arrays instead of doing + it all in one step. + +PLIB v1.1.7 (Jan 20th 2000) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Ooops! 1.1.6 accidentally went out set up to + REQUIRE the 'freeglut' library instead of the + original GLUT. That's fixed now - it'll pick + up on whichever you have installed and use + freeglut if you have both. (This only really + selects which header PLIB will use - you can + still link your application against either + GLUT) + + freeglut is here: + http://freeglut.sourceforge.net + +PLIB v1.1.6 (Jan 19th 2000) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Changed ssgSaveSSG and ssgSaveAC to return + TRUE on success, FALSE otherwise. Neither + function is really working well enough for + 'primetime' use. + + * Added an optimisation to sgInvertMat4 (thanks + to Norman Vine). + + * Changed all Makefile.am's to refer to top_srcdir + rather than top_builddir - I have no idea why that + matters - but Steve Lamont + says it matters - so I fixed it! + + * Fixed a bug in PUI's default colour scheme picker + that caused text on dark coloured backgrounds to + be black instead of white. + +PLIB v1.1.5 (Dec 20th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Optimised sgMakeNormal (thanks to Klaus Hartmann!) + * Added 'Orthographic' rendering modes to SSG...this + is a work in progress - so no documentation yet - sorry! + +PLIB v1.1.4 (Dec 3rd 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Moved pre- and post-draw callbacks from ssgLeaf + to all ssgEntities. + * Changed user-data - all userdata must be derived + from ssgBase so that it can be ref-counted and + automatically deleted when no longer referenced. + * Added some specialised highlighting code for + the PPE tool. + +PLIB v1.1.3 (Nov 28th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Added some missing 'get' functions to SSG. + * Added a way to load the current view frustum + and modelview matrices into OpenGL. + * Removed dependancy of SSG on GLUT. + * Added ssgVtxTable - which will ultimately + replace ssgVTable. The main difference is + that ssgVtxTables don't support indexing and + add reference counted vertex data tables. + * ssgLoadAC changed to use the new ssgVtxTable. + * Added pre- and post-draw callbacks to ssgLeaf. + +PLIB v1.1.2 (Nov 8th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Fixed double declaration of sgdTransposeNegateMat4 + that prevented SG from compiling under Windoze. + * Split examples and documentation off into a + separate tarball. + +PLIB v1.1.1 (Nov 6th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Added routines to SG to interconvert sgd and sg + data types. + * Matrix inversion routines added to SG. + * Attempt to work around possible compiler + error in ssgLoad3Ds - this shows up in some + versions of CygWin under Windoze and exhibits + itself as an out-of-memory error when loading + 3DStudio models. + +PLIB v1.1.0 (Oct 29th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * This is actually identical to 1.0.20 except + that it installs its headers in /usr/include/plib + and its libraries in /usr/lib. To avoid name-space + pollution in /usr/lib, the libraries are renamed + as follows: + + libssg.a --> libplibssg.a + libsg.a --> libplibsg.a + libfnt.a --> libplibfnt.a + + ...you get the idea I'm sure. + + * With this release, I'm going to the even-number-stable, + odd-number-experimental numbering scheme. Hence, + I'll be adding bug fixes only to the 1.0.xx series. + When 1.1.xx has been enhanced - and is again stable, + it'll become 1.2.0 and 1.3.0 will be the experimental + version. + +PLIB v1.0.20 (Oct 29th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Fixed problem with memory leakage in SSG, the + ref count of branch nodes was including the + parent nodes as well as the children. Revised + instructions on deleting nodes added to manual. + + * Added sgDistanceSquaredVec2/3/4 to SG. (Christian + Mayer asked *so* nicely). + + * Added Per Liedman's latest 3D studio file loader. + This is a truly awesomely useful thing. Thanks Per! + + * This will be the last version to install in + /usr/local/plib. + +PLIB v1.0.19 (Oct 16th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Added bunches of missing 'const' directives to SG and + parts of SSG. Thanks to Christian Mayer for this one. + + * Fixed a bug in FNT that should allow more than two + lines of text to be output with a single call to + puFont::drawString. Thanks to Sylvan Clebsch for this one. + + * Added a 'saturation' limit to js.h - intended for those + joysticks that don't generate a full range of output. + Thanks again to Sylvan Clebsch! + + * Keiji Kato provided a patch to SL for the Windoze + platform that fixes some kind of a slowdown problem + when playing sounds on WinNT-4 machines. + +PLIB v1.0.18 (Oct 3rd 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Removed GIF files from all the Web pages. Rassin-frassin + Unisys...grumble >:-( + + * Fixed a problem that caused too many joystick axes to be + reported by JS. Thanks to Paolo Leoncini - good catch! + + * Added new Quaternion interpolation routines and reduced + complexity of quaternion multiplication routines. Thanks + to Sylvan Clebsch. + + * ssgEntity (and hence most SSG classes) didn't make a copy + of strings passed to setName() - hence there was a tendancy + to leak name memory as objects were deleted. That's fixed + but be aware that 'name' is now copied. + + * As requested by Christian Mayer, sgAddScaleVec functions + have been added into SG. + + * Fixed up some compilation warnings in ssgStateSelector.cxx, + fnt.cxx and ssgSaveAC.cxx. (Thanks to Sylvan Clebsch for those) + + * Fixed a potential problem in ssgModelPath/ssgTexturePath that + would blow up if you ever passed a local string variable to + them. Be sure not to call either function before ssgInit() - OK! + +PLIB v1.0.17 (Aug 23rd 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Added new ssgState derivitive "ssgStateSelector". + Check out SSG documents for details. + + * Stopped warning about unused variable 'ww' in FNT and SSG. + + * Fixed bug in puValue::setValue(char*) that prevented empty + strings from changing the current string state for the puValue. + (Thanks to Sylvan Clebsch for finding that one) + + * Removed the 'test' program for PUI (it was never meant to + be in the release). + + * Added error return to Font loaders (Thanks to Norman Vine). + +PLIB v1.0.16 (Aug 13th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Fixed compiler warning in slMODfile.cxx + + * Fixed a bunch of compile errors in slScheduler.cxx due to + some default arguments that got left in place by mistake. + +PLIB v1.0.15 (Aug 12th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Minor fix to SL to make it compile under CygWin. + Thanks to Norman Vine for that one. + + * MacOS port of SL is now complete! Many thanks to + Darrell Walisser + + * Fixed a problem with const correctness when compiling with + gcc 2.95. + + * Moved a lot of SL functions from inline to non-inline... + they had grown over time from one liners into 10 liners. + + * In SM, changed 'not_working' to 'notWorking' to make it + look more like SL. + + * Fixed bug that caused SL to crash if you played MOD music + without a sound card (Thanks to Daryll Strauss for finding + that one). + + * Fixed bug in puButton constructor that makes menus come + out with irregular height. + + * Fixed recurrent crashing problem with the PUI 'complex' + demo program. + +PLIB v1.0.14 (Aug 4th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * The use of PROXY textures seems to break both nVidia and G200 + Mesa ports for Linux - so I have temporarily commented out + that code. If you need it, find the code in src/ssg/ssgImageLoader.cxx + and src/fnt/fntTXF.cxx and re-instate the code that's ifdef'ed out + using #ifdef PROXY_TEXTURES_ARE_NOT_BROKEN + + * Significant fixes to SL to make it work with /dev/audio under + SOLARIS. Thanks to Steve Brown for his patch. + + * Somehow the FNT documentation became corrupted in 1.0.13, + it's fixed now though. + + * FNT and PUI now allow '\n' characters inside strings to + signify carriage-return + line-feed. Thanks to Shane Arnott + for this one. + + * Added parameters to FNT routines to allow the application + to pick which OpenGL texture filtering to apply. + + * Fixed some minor name-space pollution in PUI. + + * Fixed a bug in ssgBaseTransform that causes ssgGetLastTransform + to mess up on the first call. + + * Fixed a bug in measuring the bounding box of text containing + space characters in the FNT component. Thanks to Alexander A. + Babichev for this one. + + * Lots of minor syntax changes for MSVC, + +PLIB v1.0.13 (July 8th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Included a JS patch from Karl Heinz Kremer that + adds support for the latest Linux joystick driver. For those + who have the latest driver, this will increase the number of + joystick axes from 2 to 6.Beware though that the detection of + which kind of driver is present is currently done at compile + time which could be a problem for binary distributed code. + + * Added a simple terrain demo (examples/ssg/majik)- originally + put together to give the good people in the Majik group + something to play with. + Check out *their* good stuff at: http://majik.netti.fi + + * Improved state handling in SSG. Also added ssgForceBasicState(). + + * JS library should work with FreeBSD. (Thanks to Stephen Montgomery-Smith) + + * Texture loaders in SSG and FNT changed to use GL_PROXY texture + tests instead of being hard-coded to crappy 256x256 limits. + + * Since puiAlone is sadly outdated, I have ceased to distribute it. + If you need it, the last version is with plib-1.0.12 on the PLIB + homepage. + + * Changed definition of SG_PI to be a 'float', fixed the precision + of SGD_PI to be double. + + * Removed strncasecmp - because it's not universally implemented. + + * Changed an ifdef in SL to allow it to compile under FreeBSD. + + * Added an 'puArrowButton' call - just like a puButton - but + shaped like an arrow. + + * Added an 'ssgGetVersion' call. + + * Deleted ssgAnimation class (it was never completely + implemented anyway). + + * Added ssgTimedSelector (which takes over the functions + I'd planned to add to ssgAnimation). + + * I didn't rename the file ssgAnimation.cxx to ssgTimedSelector.cxx + because I couldn't stand to change all the MSVC project thingies. + + * Numerous fixes for the Mac: + + * Fixed a byte-swapping problem with the BMP + texture loader. + + * Changed some arrays from local to 'new/delete' because + the Mac CodeWarrior compiler can't cope with more than + 32Kb of local memory in a single function or class. + + * Provided conditional compilation for Mac file naming + conventions in a couple of places. It's not enough though. + +PLIB v1.0.12 (June 3rd 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Added a set of MSVC project files. + + * More portability issues resolved. + + * Lots more actually. + + * Official Acronym "IBFITNR" (It'll Be Fixed In The Next Release) + now adopted. + +PLIB v1.0.11 (May 30th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Fixed a problem with LoadAC creating 2-point tstrips. + + * Fixed an assert in SSG's deRef. + + * The tables inside an ssgVTable are now 'protected' rather + than 'private'. + + * Added new code to slScheduler to allow applications to + replay MOD files. + + * Reorganized slSamplePlayer to be derived from a new + abstract base class slPlayer. Added new private class + slMODPlayer for replaying MOD files. + + * Added a demo program for the new SL MOD player. + + * Added ssgRangeSelector class to allow level-of-detail + management. This isn't well tested yet - but it's + really simple code - so it should be OK. + +PLIB v1.0.10 (May 10th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Ooops! A fatal error in my strcasecmp code. + 1.0.9 and 1.0.10 should have *died* on most + machines! + +PLIB v1.0.9 (May 9th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Error in SGI version of slSample.cxx cleared up (Thanks Devrim!) + + * Made some changes for MSVC. + +PLIB v1.0.8 (May 3rd 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~ + * A couple of warnings eliminated from SL when compiled + under CygWin. + + * Added a contribution from Simon Britnell + to allow programs to search the SSG scene graph by name or + path. (Thanks Simon!) + + * Fixed a bug in sgIdentityQuat (Thanks Kevin!) + + * Following the first release of Tux-aqfh, I was snowed under with + little fixes. + + + strcasecmp should be stricmp on some machines...but alas, not + on others. The heck with it - I'll just write my own! + + + fntFont wasn't pushing/popping GL state correctly. + + + More minor hacks to make for clean compiles under IRIX. + + + puInterface's destructor was only deleting half of it's + child node. + + + Missing contructor functions for various SG classes. + + + SSG culling functions were not testing for empty + bounding spheres. + + + Minor compilation warnings for slSample.cxx + + + example/sl/example.cxx used M_PI - which is a no-no under + Windoze. + + +PLIB v1.0.7 (May 3rd 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Removed a bunch of redundant NOTICE, CHANGES + and REAME files. All that stuff is now maintained + in the top level directory. + + * SG used to be set up so you could compile it + in double precision with the drop of an option. + However, some applications need both float and + double support - so SG now has duplicate functions + for double-precision that start 'sgd'. + + * Changed the structure of the FNT library to move + font sizes from the fntFont/fntTexFont class into + the fntRenderer class. This corrects a poor design + decision because it was hard to create fonts in + multiple point sizes and slants without using + multiple identical texture maps (BAD!). RTFM. + + * Added a bunch of TXF fonts into examples/fnt/data + and changed the fnt_test program to cycle through + them whenever you press a key. + + * PUI can now use FNT fonts - which is good news + because now you can use TXF fonts for better + variety and speed compared to GLUT fonts. + This means that PUI programs now need to + link with -lpui -lfnt -lsg + + * The PUI 'complex' example program now uses + the sorority font. + + * I added a 'rendering callback' to some + PUI widgets as suggested by Eero Pajarre. The + idea is to allow you to do arbitary OpenGL + rendering onto a PUI widget...however, I'm + not convinced that this is a good idea. In + any case, you can put icons on widgets more + easily by defining custom fonts using FNT. + + +PLIB v1.0.6 (May 1st 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Added a complete new component library called + FNT that allows texturemapped fonts to be + loaded and rendered nicely. + + * More small configure/compile problems fixed. + + * Added Quaternions to the SG library thanks + to a fine contribution from Kevin Thompson + + + * Fixed a bug in JS under Windoze that made + three axis sticks return garbage in the + third axis and swapped the order of the + third and fourth axes for >3 axis sticks. + + +PLIB v1.0.5 (April 21st 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Fixed another IRIX compile problem in pu.h + + * Found that configure script was not enabling + full warning levels...as a result, fixed a + dozen minor warnings in SSG. + + * SSG's image loader now loads 8 bit and 24 bit + uncompressed BMP files. This seems to work + for RGB images - but I can't seem to build + BMP images with Alpha planes using any of + the tools I have. + + +PLIB v1.0.4 (April 20th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Restructured SSG texture image loader to permit + use of other file formats than SGI. + + * In the event that a texture doesn't load, SSG will + now insert a red and white chequerboard. + + * Another round of changes to configure.in should + solve the CygWin issues. + + * Added in some *ancient* fixes to PUI - that kind + people donated and I somehow forgot all about (oops!) + + +PLIB v1.0.3 (April 18th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Fixed to compile cleanly under IRIX 6.2 using the + official SGI C++ compiler. + + * More fixes for MSVC under Windoze. + + * OpenGL logo added to HTML documents following + request from opengl.org + + +PLIB v1.0.2 (April 14th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Yet more minor build tweaks - CygWin wasn't defining WIN32, + that should work now. + + * JS should now work with Windoze - and with sticks with + up to 6 axes. Under Linux, the presence of the joystick + driver (or at least it's header files) is now mandatory, + PLIB won't build without it. + + * The JS demo program has been fixed to display all of the + axes of all of the joysticks. + + * PUI now supports valuators - this is where the value of + a widget is set using the address of one of the application's + variables. Once the valuator is set, the PUI widget's display + will always the same as the valuator - and any changes to the + widget will also change the value stored at that address. + This saves you from creating a bunch of callbacks when buttons + and sliders have no side-effects apart from changing some + global variable. + + +PLIB v1.0.1 (April 11th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Some minor portability issues cleared up. + + * More minor build process errors corrected. + + +PLIB v1.0 (April 1st 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~ + * All the separate libraries that I support in the + public domain are now rolled into a single tarball + under the new name 'PLIB'. + + * Although this is the first release of PLIB. The sub- + libraries: SL, JS and PUI had previous releases - this + is the first Beta of SG and SSG. + + * Directory layouts for all of the component libraries + have been somewhat rationalized. + + * I have shifted from a completely open license to + LGPL on the advice of several OpenSource authors. + Any earlier releases of these libraries that you + may happen to have remain free of LGPL restrictions. + If any contributors to the earlier code have objections + to this arrangement, please let me know and I'll arrange + to remove their code from subsequent copies. + + * With help from Curtis Olson, we now have proper 'configure' + scripts to streamline the build process. + diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..e048404 --- /dev/null +++ b/INSTALL @@ -0,0 +1,218 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +OpenGL Configure +================ + +Configure is not able to find the OpenGL headers and libraries. In this +case please add + +./configure --with-GL=PREFIX + +Examples + +./configure --with-GL=/usr/local + +This will look in the /usr/local/include for headers (GL/ is not needed) +and /usr/local/lib for the libraries. + + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Compiling for Windows with MSVC +=============================== + +You can easily compile plib with MSVC 6. First, you have to set some paths +in tools\options\directories. In "include" set the plib path itself (and, +if needed the parent). Then, in "library paths" add the plib path itself again +so that packages that use plib will find it. The building process will copy +the finished *.lib files and any header files that are visible to projects +using plib into the plib path. + +There is a workspace (*.dsw file) for plib, for examples, for tools +(including only af2rgb) and for each of the demos: exposer, p-guide +and ttt3d. Simply open one of them (starting with plib itself, of course) +in MSVC, choose what you want to compile (build/set active configuration) +and then compile (F7). if you want to compile or even create a project +that uses plib, please note that the plib workspaces have "multi threading" +enabled. Either enable this as well in your project or disable it for +plib. A missmatch leads to errors. + + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/KNOWN_BUGS b/KNOWN_BUGS new file mode 100644 index 0000000..b104b96 --- /dev/null +++ b/KNOWN_BUGS @@ -0,0 +1,25 @@ +Known bugs and limitations in PLIB version 1.8.x + +More in depth stuff can be found in TODO_AFTER135. + + * ssgLOS is really broken. + + * ssgStripify and ssgFlatten might well have bugs in them. + A known bug of ssgStripify is that : since it rearranges and + merges leaf nodes, ssgSelectors are messed up + + * Sometimes cr*p values appear in 3D files, for example .ac files. + The reason seems to be that sometimes the loader handles colours + differently than the writer. + + * Several, general smalish .MDL loader bugs are known; Look in TODO_AFTER135 + + * Scaling does not work (intentionally). Uniform scaling may be + enabled by uncommenting "radius *= sgLengthVec3(m[0])" in + sgSphere::orthoXform. It is currently disabled because that extra + calculation would degrade performance on non-scaled matrices. + Scaling really makes a mess of SSG bounding sphere tests + + * .ssg files should not be used for long term storage. It will probably + change in incompatible ways. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..9ce5486 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,7 @@ +SUBDIRS = src + +EXTRA_DIST = KNOWN_BUGS NOTICE README README.GLUT \ + README.win32 README.mac TODO-1.6 TODO-2.0 \ + TODO_AFTER135 autogen.sh missing \ + plib.dsp plib.dsw transferCvs2WebSite + diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..2f86bd4 --- /dev/null +++ b/NEWS @@ -0,0 +1,4 @@ +Fri Oct 13 16:54:04 CEST 2006 +Moved from SF CVS to SF SVN. +To grab a copy from svn, use this command: +$ svn co https://svn.sf.net/svnroot/plib/trunk plib diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..bfc5b0c --- /dev/null +++ b/NOTICE @@ -0,0 +1,23 @@ +NOTICE: The PLIB Portable Interactive Applications Library distribution +contains source code that is released as OpenSource under the GNU +Library Public License. These programs are thus freely distributable +without licensing fees. These programs are provided without guarantee +or warrantee expressed or implied. + +If you use PLIB in a commercial or shareware product, it would be nice +if you gave credit where it is due. If you make any neat modifications +or improvements to PLIB, I would greatly appreciate a copy of the +improved code or at least a source patch. + +Note that PLIB uses an addition to the LGPL: + + As a special exception Steve Baker gives permission to link these + libraries with proprietary software and distribute the resulting + executable without including that proprietary code in any distribution + as the LGPL would normally dictate. + + This exception is ONLY granted in the case of an embedded system in + which there is no possibility of an end user re-linking or recompiling + against new versions of this library that may appear in the future." + + diff --git a/README b/README new file mode 100644 index 0000000..a7e6411 --- /dev/null +++ b/README @@ -0,0 +1,182 @@ + +Portability Libraries. +====================== + by Steve Baker. + +All the documentation and installation instructions +are now online at: + + http://plib.sourceforge.net + +They are also downloadable - along with example +programs and demos from the same site. + + +SUPPORT: + +Please don't email me (Steve Baker) directly - I +get *WAY* too much mail as it is! Instead, please +sign up to the PLIB user's mailing list. Instructions +can be found here: + + http://plib.sourceforge.net + + +LICENSING: + +These libraries are offered as OpenSource freeware +under the provisions of the GNU Library Public +License (LGPL). Those terms and conditions are +detailed in the file 'LICENSE' in this directory. + +I have added a short preamble to LGPL that removes +no rights from ordinary users but offers special +dispensation to allow PLIB to be used under certain +commercial conditions (such as Games Consoles) where +the constraints of LGPL are impossible to meet. + +| As a special exception Steve Baker gives permission to link these +| libraries with proprietary software and distribute the resulting +| executable without including that proprietary code in any distribution +| as the LGPL would normally dictate. +| +| This exception is ONLY granted in the case of an embedded system in +| which there is no possibility of an end user re-linking or recompiling +| against new versions of this library that may appear in the future. + + +REQUIREMENTS: + +In addition to the libraries that I provide, you +will also need OpenGL (OpenGL 1.1 or later - +Mesa 3.0 or later) and GLUT (The OpenGL utilities +toolkit - version 3.7 or later) and a hardware 3D +graphics accellerator that supports OpenGL. + + +WHAT DO YOU GET? + +The following libraries are provided: + +JS -- A Joystick interface. +PUI -- A simple GUI built on top of OpenGL. +SG -- Some Standard Geometry functions (vector and + matrix math, spheres, boxes, frustra, etc) +SL -- A Games-oriented Sound Library. +FNT -- OpenGL texture-mapped font Library. +PW -- A minimalist windowing library. +PSL -- A C-like scripting language. +SSG -- A Simple Scene Graph API built on top of OpenGL. +NET -- Some Networking functions for games. +UTIL-- Utilities - things that your OS would normally + handle - but these functions are portable. + +SSGAUX -- Some optional additional high level features for SSG +PUIAUX -- Some optional additional high level features for PUI + + +DIRECTORY STRUCTURE: + +PLIB expects to be installed in one standard place: + + /usr/lib + +...with header files at: + + /usr/include/plib + + +PORTABILITY and DEPENDANCIES: + +Although all these libraries are designed to be easily +portable (and more importantly so that programs using +them can be UTTERLY portable), some of them have not +yet been ported to all operating systems. + +JS -- Currently Linux/Windows/BSD only. + +UL -- Should be portable to POSIX-compliant + OS's ... and Windows. + +SG -- Totally portable, no dependancies. + +PUI -- Requires OpenGL also FNT and SG. + PUI also requires some kind of windowing + library - which could be PW - or GLUT, + freeglut, SDL, FLTK - or others. + +PSL -- Requires UL. + +PW -- Requires UL. + +NET -- Should be portable to POSIX-compliant + OS's. + +FNT and SSG -- Require OpenGL, SG and UL. + +SSGAUX -- Requires SSG - and hence OpenGL, SG and UL. +PUIAUX -- Requires PUI - and hence FNT and SG. + +SL -- This has now been ported onto: + + Linux + FreeBSD + OpenBSD + M$ Windows (NT,95,98 - so far) + MacOS + SGI IRIX + Sun Solaris + Any operating system that supports OSS (The + Open Sound System). + + NOTE: SL has a subsidiary library 'SM' that + can be used to control the audio mixer - but + that is not portable beyond Linux. You might + get it to work under OSS-based sound systems + too. Don't use SM if you want to write portable + code. + + No other requirements. + + +AUX LIBRARIES AND TOOLS: + +The 'tools' directory contains a number of useful tools +and utility programs that are either built using PLIB or +which are specifically useful when writing PLIB programs. + + +COMPILING/LINKING WITH PLIB + +In your source code, add any combination of: + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + +Add any of these to your link line: + + -lplibjs -lplibssgaux -lplibssg -lplibsl -lplibpu + -lplibpuaux -lplibpw -lplibpsl -lplibfnt -lplibnet + -lplibsg -lplibul + +Under UNIX/Linux, you'll also need: + + -lGLU -lGL -L/usr/X11/lib -lX11 -lXext -lXmu -lm + +...and perhaps a -l for whatever windowing library +you're using - unless it's the built-in PW library. + + Steve Baker. + + http://www.sjbaker.org + diff --git a/README.GLUT b/README.GLUT new file mode 100644 index 0000000..2d3d208 --- /dev/null +++ b/README.GLUT @@ -0,0 +1,3 @@ + +PUI no longer depends on GLUT or freeglut. + diff --git a/README.JOYSTICKS.FREEBSD b/README.JOYSTICKS.FREEBSD new file mode 100644 index 0000000..49ddfe5 --- /dev/null +++ b/README.JOYSTICKS.FREEBSD @@ -0,0 +1,96 @@ +FreeBSD joystick support +------------------------ + +FreeBSD supports two flavors of joysticks: analog and USB. By default, +non-root users do not have access to these devices on FreeBSD, and the +required devices may not even be created yet. Please browse the below +notes before writing to the plib mailing list. + +Contents of this file: +----------- + Analog joysticks + USB joysticks + Testing the joysticks + Compiling and linking + +Analog joysticks +---------------- + +Plib uses the joy(4) interface to analog joysticks. You will need to +make sure the device files exist: + ls -l /dev/joy* + +If they do not yet exist, create them (logged in as root): + cd /dev + sh MAKEDEV joy + +By default, they will have permissions that do not allow unprivileged +users access to them: + crw-r----- 1 root operator 51, 0 Aug 30 16:59 joy0 + crw-r----- 1 root operator 51, 1 Aug 30 16:59 joy1 + +You may wish to consider making the devices world read/writable: + chmod a+rw /dev/joy* + +Users of xdm(1) or any of its more modern successors may wish to look +into GiveConsole and TakeConsole or its equivalent. + +If you do not have a joystick driver compiled into you kernel, you can +load one dynamically with the command + kldload joy +When in doubt, check the FreeBSD handbook about making sure this driver +is loaded every time you reboot. + + +USB joysticks +------------- + +Plib uses the usbhid(3) interface to USB joysticks. Joysticks will show +up as generic USB Human Interface Devices (uhid). Because the USB design +allows an almost unlimited number of USB buses and USB devices, you should +make sure you have enough devices in /dev to deal with your devices. +When in doubt, create a few extra to make sure. If you have insufficient +USB or uhid devices, your joystick may not appear at all, or it may +disappear if you connect your USB devices in a different order. +Fortunately, device nodes are free. For example, you might see this: + ls -al /dev/usb* /dev/uhid* + crw-rw---- 1 root operator 108, 255 Apr 12 01:44 /dev/usb + crw-rw---- 1 root operator 108, 0 Apr 12 01:44 /dev/usb0 + crw-rw---- 1 root operator 122, 0 Apr 12 01:44 /dev/uhid0 + +This shows you have one usb interface (/dev/usb itself doesn't count), and +one uhid device. Make a few extra with + cd /dev + sh MAKEDEV usb0 usb1 usb2 usb3 uhid0 uhid1 uhid2 uhid3 +(you can leave out the devices that exist already). + +Next, you'll have to think about permissions. Both the /dev/usb0..3 +(but not /dev/usb) have to be world readable, as well as the uhid devices. +This command will take care of it: + chmod a+r /dev/usb?* /dev/uhid* +(yes, the "?*" after /dev/usb is intentional). + +Obviously, any permission change you make is at your own risk! XDM users +may use the GiveConsole/TakeConsole mechanism as an alternative. + +Plib will complain if /dev/uhid* or /dev/usb* exist but are +unreadable with your current privileges. + + +Testing the joysticks +--------------------- + +Users of FlightGear can quickly test their joysticks with the js_demo +program. + + +Compiling and linking +--------------------- + +Compile plib on FreeBSD with the same compiler options as used for the +other libraries you may use. In particular, if you use pthreads anywhere +in your application, you should compile Plib with + g++ -pthread + +Applications linking to recent Plib's -ljs should add -lusbhid to the +link command line in the Makefile. diff --git a/README.mac b/README.mac new file mode 100644 index 0000000..136b9c2 --- /dev/null +++ b/README.mac @@ -0,0 +1,19 @@ + +PLIB Project files for CodeWarrior +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +NOTE from Steve: + It seems that the CodeWarrior project files for + PLIB are considerably larger than the entire source + distribution (450Kb!) + + Hence, since Mac/CodeWarrior users are not exactly + commonplace, I'm not going to include the project + files into the distro and cause everyone else prolonged + download times. + + I suggest you contact Darrell Walisser + should you need to build PLIB in this setting. + + Sorry! + diff --git a/README.win32 b/README.win32 new file mode 100644 index 0000000..d189e19 --- /dev/null +++ b/README.win32 @@ -0,0 +1,52 @@ + +PLIB for Windoze. +~~~~~~~~~~~~~~~~~ + +Let me first say that I (Steve Baker) don't own a copy +of Windoze - so I have little or no ability to help +Windoze owners with PLIB problems. It's especially +important therefore that you direct problems and +queries to the PLIB mailing lists. Subscription +information is on the PLIB homepage: + + http://plib.sourceforge.net + + +CygWin: +~~~~~~~ +The simplest way to build PLIB for Windoze is to +use the CygWin compiler and toolset. Since that +environment is pretty close to UNIX/Linux, the + + ./configure + make + make install + +...mechanism works perfectly. + + +MingW32: +~~~~~~~~ +A couple of people have asked about doing a MingW32 port - but +as far as I can tell, the "configure/make/make install" approach +*should* work. + + +Microsoft Visual C++: +~~~~~~~~~~~~~~~~~~~~~ +All you need to do is open the workspace "plib.dsw" in MSVC++, +select the "plib" project (using Set Active Project in the Project +menu), and build it (using "Rebuild All" in the Build menu). + +In the examples folder, open the workspace "plib_examples.dsw". +Each example has a seperate project in the workspace. Select +the one you want and build it. Then you should be able to hit +the Go icon on the toolbar and try it out. + +For your own application, please note that the plib workspace +leaves all the necessary includes (*.h) and libraries (*.lib) +in the plib root directory (same as workspace). The debug +libraries are given a '_d' suffix. Where ever you put those +files, make sure #include works so your code is +more portable. + diff --git a/TODO-1.6 b/TODO-1.6 new file mode 100644 index 0000000..d2001dd --- /dev/null +++ b/TODO-1.6 @@ -0,0 +1,69 @@ +NEW FEATURES: + +Structure section + +* SSG needs RTTI to replace the rapidly vanishing SSG_TYPE bits resource. + +* I'd like to see the FGFS sky model moved into ssgAux so everyone can use + it. We got part of the way towards that - but it was never finished. + +* I'd like to have a ROAM engine built into ssgAux for terrain rendering. + (maybe not *literally* ROAM - but something very like it). + +SSG section + +* Support for bump maps, cubic environment maps, etc, etc on hardware + that supports it. + +* Support for multi-texture. + +* Import some kind of Skin & Bones animation into ssgAux (using the + ExPoser code - or something even better). + + +Loader section + +* MORE file readers and writer. +For example, a reader/loader for WWII Fighters would be nice. + +* No file writers for about 2/3rds of the file formats we support. + +* I want the PPE material editor's file format built into SSG so we can + load and save material lists. + +* Model formats + * VRML + * XML version of ssg + * WWII (I think thats the name) + +SG section + +* function to get the angle between two vectors + +* plot points on a vector (walking in a straight line) + +* Expand SG with more intersection and distance-measuring tricks. + + +PUI section + +* PUI should also be implemented with RTTI as well. + +* Movable widgets + +* PUI is still somewhat tied to GLUT...that should go. It'll need a + way to get the window dimensions - and at least one built-in font + before we can do that. + +SL section + +* Re-implement SL on top of OpenAL. + +* Write players for more modern MOD-like music formats. + +Examples section + +* More example programs - more complete demo games and tools. + +* More documentation for all the new features. + diff --git a/TODO-2.0 b/TODO-2.0 new file mode 100644 index 0000000..d2ee294 --- /dev/null +++ b/TODO-2.0 @@ -0,0 +1,28 @@ +[ Put in tasks here that probably won't get done before PLIB 2.0 or change + the API in a way that could break existing applications ] + +PUI section + +* Remove deprecated puFilePicker widget + +* Remove deprecated old label and legend places + +* Remove deprecated PUSTYLE_RADIO + +* Remove deprecated 'int puValue::getValue ( void )' function + (Application developers: Use 'puValue::getIntegerValue' instead) + +* Remove deprecated 'int puObject::getDefaultValue ( void )' function + (Application developers: Use 'puValue::getDefaultIntegerValue' instead) + +* Line up widget constructors (explicit size vs. max coordinates issue) + +* Change function parameters taking a 0/1 FALSE/TRUE value from 'int' + to 'bool' + +* In puDeactivateWidget (), invoke the active widget's down callback + (Can't be realized prior to 2.0 since it could break existing programs + relying on the old behaviour) + +* Implement puiAUX for complex widgets [ unclear ] + diff --git a/TODO_AFTER135 b/TODO_AFTER135 new file mode 100644 index 0000000..4ddea6a --- /dev/null +++ b/TODO_AFTER135 @@ -0,0 +1,138 @@ + ++============+ +| TO BE DONE | ++============+ + +A tasks and bugs are now being tracked by sourceforge. Please +goto: http://sourceforge.net/projects/plib/ + + * Have a look into known_bugs and fix them. + + * Lines in ASCII files are terminated... + + With '\n' under UNIX/Linux + With '\r' under MacOS + With BOTH under Windoze. + + Hence, UNIX/Linux does no conversions of either '\r' or '\n'. + and MAC swaps '\r' and '\n' on input. + and Windoze dumps '\r' if it follows a '\n'. + + This is a mess - so I'm changing all the ASCII I/O code + to allow either or both '\n' or '\r' and I'm reading the + ASCII files in BINARY mode. + + * Array deletion requires '[]' after 'delete' on Mac. + + * Some of the MSVC-project files for plib_examples seem to be + broken, for example some miss a "winmm.lib". + + * Check whether the new ssgStripify works with TuxKart + See Steves post from 11.12.2000 15:12 for a problem description + + + +The abbreviation NIV14 means not in Version 1.4. + + + + + + +Bugs: +===== + +- When creating fgfsTux, sometimes .ac, .dxf, + .ase and .obj saved zero objects, although + there were objects. For example, PLIB + created this .ac file: + ----------- snip ------------ + AC3Db + OBJECT world + kids 0 + OBJECT group + kids 0 + ----------- snip ------------ + This seems to happen after ssgFlatten. +- WK: Create a sphere in ppe. Save it as .ASE. See that values like + diffuse colour are cr*p. Try to load it. It crashes. This could be + one or - probably - two bugs. I don't think this is a ppe problem. + The loader complains that number of faces is -2. + The problem seems to be the writer. + + *new remark*: About the diffuse values: I think it has to do with + colour material, a loader (.ASE?) loading colours into a colour + list and writing colours from the ssgSimpleState where they are + undefined. I think the same bug is in .AC + +- WK: I have a crash in ssgFlatten if I load .ac files with + unused materials (not reproducable?) +- Loading and saving lines in .OBJ doesn't work. Maybe NIV14. +- Sam wrote: + Has anyone here debugged with plib under Windoze 2000 and MSVC++? + I get a whole bunch of + "Free Heap block modifed after it was free" + warnings with the ssgFlatten and ssgStripify. + I'll try and hunt this one down. + ... + I think it may be because I'm using MFC which (if I remember + correctly) enables a bunch more memory checks. Also I'm doing + #ifdef _WIN32 + #ifdef _DEBUG + #define new DEBUG_NEW + #endif + #endif +- Not all loaders use ssgLoaderOptions::begin. Don't all have to? + +- Search for todo, fix, fixme, kludge. + + + +Misc: +===== + +- Look whether scaling works. [see current discussion] + If not and if we can't/don't want to make it work, for example + because of performance issues we need a warning in the docs and + IMHO PLIB should "write out" a warning if an unallowed matrix is + sent to it. + Update: Scaling does not work (intentionally). Uniform scaling may be + enabled by uncommenting "radius *= sgLengthVec3(m[0])" in + sgSphere::orthoXform. It is currently disabled because that extra + calculation would degrade performance on non-scaled matrices. +- Reduce lint warnings. Lint is an error checking tool that gives warnings + where things *could be* wrong as opposed to the compiler that tells + you where they are wrong. + +- It would be great if we had one or even two working native .ssg + file formats. Currently (16.12.2001) the format work most of the time, but not all + entities are implemented. +- We should write the GetWrapU/GetWrapV function, since + loading /writing .ssg files can't work 100% without it. +- When saving, there is often a warning that "ref count doesn't + tally with parent count" +- Go through the mailing list for unfinished business. +- Someone, preferably a native english speaker with ssg-knowledge, + should go through the new ssg-doc and fix any mistakes. It should be + fairly complete by now. +- Add Per's new Formats to the doc? +- For the other parts of plib, people should bring the doc up to + date. +- There is a bug in the 3Dfx driver for Linux (tdfx_dri-4.0.1-1) that + causes the "complex" example program to crash in "fxSetupBlend". + This is fixed in more recent DRI snapshots (requires kernel 2.4.x). + + +Probably after 1.4.0: +===================== +- In fgfsTux, not a large object, you get a DList overflow + with the standard values for its size. Can we make its + size dynamic? +- Look at handling of normals. For example, loaders, + stripify etc should only recalculate missing normals. + Have *one* function that recalculates normals. + + + +It would be nice if people would volunteer for tasks. + diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..02a1eb9 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +OSTYPE=`uname -s` + +AMFLAGS="--add-missing" +if test "$OSTYPE" = "IRIX" -o "$OSTYPE" = "IRIX64"; then + AMFLAGS=$AMFLAGS" --include-deps"; +fi + +echo "Running aclocal" +aclocal +echo "Running automake" +automake $AMFLAGS +echo "Running autoconf" +autoconf + +echo "======================================" +echo "Now you are ready to run './configure'" +echo "======================================" diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..0d119cd --- /dev/null +++ b/configure.in @@ -0,0 +1,426 @@ +dnl Process this file with autoconf to produce a configure script. + +AC_INIT(src/js/js.h) + +# **WARNING**WARNING**WARNING**WARNING**WARNING**WARNING** +# +# When you make a new release, there are TWO places where you +# have to change the version number: +# 1) Right below this comment. +# 2) In 'ul.h' where PLIB_VERSION is created. +# +# **WARNING**WARNING**WARNING**WARNING**WARNING**WARNING** + +AM_INIT_AUTOMAKE(plib, 1.8.5) + +# This AC_PREFIX_DEFAULT will place the library files +# into /usr/lib - but will put the include files into +# /usr/include - when /usr/include/plib would be less +# polluting to the filename space. +# +# There is probably a better way to do this. + +AC_PREFIX_DEFAULT(/usr) + +if echo $includedir | egrep "plib$" > /dev/null; then + echo "includedir is" $includedir "libdir is" $libdir +else + includedir="${includedir}/plib" + echo "includedir changed to" $includedir "libdir is" $libdir +fi + + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_CPP +AC_PROG_CXX +AC_PROG_CXXCPP +AC_PROG_INSTALL +AC_PROG_RANLIB + +dnl Command line arguments + +dnl Don't use AC_HELP_STRING here as old versions of autoconf do not +dnl understand it. +AC_ARG_WITH(GL, +[ --with-GL=DIR set the prefix directory where GL resides], +GL_PREFIX=$withval, GL_PREFIX=auto) + +AC_ARG_ENABLE(fnt, +[ --enable-fnt build FNT library (OpenGL needed) default: yes],, +enable_fnt=yes) + +AC_ARG_ENABLE(js, +[ --enable-js build JS library default: yes],, +enable_js=yes) + +AC_ARG_ENABLE(pw, +[ --enable-pw build PW library default: yes],, +enable_pw=yes) + +AC_ARG_ENABLE(net, +[ --enable-net build NET library default: yes],, +enable_net=yes) + +AC_ARG_ENABLE(pui, +[ --enable-pui build PUI library (OpenGL needed) default: yes],, +enable_pui=yes) + +AC_ARG_ENABLE(sg, +[ --enable-sg build SG library default: yes],, +enable_sg=yes) + +AC_ARG_ENABLE(psl, +[ --enable-psl build PSL library default: yes],, +enable_psl=yes) + +AC_ARG_ENABLE(sl, +[ --enable-sl build SL library default: yes],, +enable_sl=yes) + +AC_ARG_ENABLE(ssg, +[ --enable-ssg build SSG library (OpenGL needed) default: yes],, +enable_ssg=yes) + +AC_ARG_ENABLE(puaux, +[ --enable-puaux build puAux library (OpenGL needed) default: yes],, +enable_puaux=yes) + +AC_ARG_ENABLE(ssgaux, +[ --enable-ssgaux build ssgAux library (OpenGL needed) default: yes],, +enable_ssgaux=yes) + +AC_ARG_ENABLE(ul, +[ --enable-ul build UTIL library default: yes],, +enable_ul=yes) + + +dnl Dependancy checking + +if test "x$enable_fnt" = "xyes"; then + need_opengl=yes + + if test "x$enable_sg" = "xno"; then + AC_MSG_WARN([cannot build FNT library without SG library enabled]) + dependancy_problem=yes + fi + if test "x$enable_ul" = "xno"; then + AC_MSG_WARN([cannot build FNT library without UL library enabled]) + dependancy_problem=yes + fi +fi + +if test "x$enable_pw" = "xyes"; then + if test "x$enable_ul" = "xno"; then + AC_MSG_WARN([cannot build PW library without UL library enabled]) + dependancy_problem=yes + fi +fi + +if test "x$enable_js" = "xyes"; then + if test "x$enable_ul" = "xno"; then + AC_MSG_WARN([cannot build JS library without UL library enabled]) + dependancy_problem=yes + fi +fi + +if test "x$enable_net" = "xyes"; then + if test "x$enable_ul" = "xno"; then + AC_MSG_WARN([cannot build NET library without UL library enabled]) + dependancy_problem=yes + fi +fi + +if test "x$enable_pui" = "xyes"; then + need_opengl=yes + + if test "x$enable_fnt" = "xno"; then + AC_MSG_WARN([cannot build PUI library without FNT library enabled]) + dependancy_problem=yes + fi + if test "x$enable_sg" = "xno"; then + AC_MSG_WARN([cannot build PUI library without SG library enabled]) + dependancy_problem=yes + fi + if test "x$enable_ul" = "xno"; then + AC_MSG_WARN([cannot build PUI library without UL library enabled]) + dependancy_problem=yes + fi +fi + +if test "x$enable_sg" = "xyes"; then + if test "x$enable_ul" = "xno"; then + AC_MSG_WARN([cannot build SG library without UL library enabled]) + dependancy_problem=yes + fi +fi + +if test "x$enable_psl" = "xyes"; then + if test "x$enable_ul" = "xno"; then + AC_MSG_WARN([cannot build PSL library without UL library enabled]) + dependancy_problem=yes + fi +fi + +if test "x$enable_sl" = "xyes"; then + if test "x$enable_ul" = "xno"; then + AC_MSG_WARN([cannot build SL library without UL library enabled]) + dependancy_problem=yes + fi +fi + +if test "x$enable_ssg" = "xyes"; then + need_opengl=yes + + if test "x$enable_sg" = "xno"; then + AC_MSG_WARN([cannot build SSG library without SG library enabled]) + dependancy_problem=yes + fi + if test "x$enable_ul" = "xno"; then + AC_MSG_WARN([cannot build SSG library without UL library enabled]) + dependancy_problem=yes + fi +fi + +if test "x$enable_puaux" = "xyes"; then + need_opengl=yes + + if test "x$enable_pui" = "xno"; then + AC_MSG_WARN([cannot build puAux library without PUI library enabled]) + dependancy_problem=yes + fi + if test "x$enable_sg" = "xno"; then + AC_MSG_WARN([cannot build puAux library without SG library enabled]) + dependancy_problem=yes + fi + if test "x$enable_ul" = "xno"; then + AC_MSG_WARN([cannot build puAux library without UL library enabled]) + dependancy_problem=yes + fi +fi + +if test "x$enable_ssgaux" = "xyes"; then + need_opengl=yes + + if test "x$enable_ssg" = "xno"; then + AC_MSG_WARN([cannot build ssgAux library without SSG library enabled]) + dependancy_problem=yes + fi + if test "x$enable_sg" = "xno"; then + AC_MSG_WARN([cannot build ssgAux library without SG library enabled]) + dependancy_problem=yes + fi + if test "x$enable_ul" = "xno"; then + AC_MSG_WARN([cannot build ssgAux library without UL library enabled]) + dependancy_problem=yes + fi +fi + +if test "x$dependancy_problem" = "xyes"; then + AC_MSG_ERROR([dependancy problems detected]) +fi + + +AM_CONDITIONAL(BUILD_FNT, test "x$enable_fnt" = "xyes") +AM_CONDITIONAL(BUILD_JS, test "x$enable_js" = "xyes") +AM_CONDITIONAL(BUILD_PW, test "x$enable_pw" = "xyes") +AM_CONDITIONAL(BUILD_NET, test "x$enable_net" = "xyes") +AM_CONDITIONAL(BUILD_PUI, test "x$enable_pui" = "xyes") +AM_CONDITIONAL(BUILD_PUAUX, test "x$enable_puaux" = "xyes") +AM_CONDITIONAL(BUILD_SG, test "x$enable_sg" = "xyes") +AM_CONDITIONAL(BUILD_PSL, test "x$enable_psl" = "xyes") +AM_CONDITIONAL(BUILD_SL, test "x$enable_sl" = "xyes") +AM_CONDITIONAL(BUILD_SSG, test "x$enable_ssg" = "xyes") +AM_CONDITIONAL(BUILD_SSGAUX, test "x$enable_ssgaux" = "xyes") +AM_CONDITIONAL(BUILD_UL, test "x$enable_ul" = "xyes") + +if test "x$need_opengl" = "xyes" && test "x$GL_PREFIX" != "xauto"; then + LDFLAGS="$LDFLAGS -L$GL_PREFIX/lib" + CPPFLAGS="$CPPFLAGS -I$GL_PREFIX/include" +fi + + +dnl Checks for library functions. +dnl check for OpenGL related libraries + +AC_CANONICAL_HOST + +case "${host}" in +*-*-cygwin* | *-*-mingw32*) + dnl CygWin under Windoze. + + dnl Multimedia library + LIBS="$LIBS -lwinmm" + + if test "x$need_opengl" = "xyes"; then + dnl OpenGL libraries + LIBS="$LIBS -lopengl32" + fi + ;; +*-apple-darwin*) + dnl Mac OS X + + if test "x$need_opengl" = "xyes"; then + dnl OpenGL libraries + LIBS="$LIBS -framework OpenGL" + fi + + dnl Sound libraries + LIBS="$LIBS -framework Carbon" + ;; +*) + if test "x$need_opengl" = "xyes"; then + dnl Check for X11 + + AC_PATH_XTRA + + LDFLAGS="$LDFLAGS $X_LIBS" + + LIBS="$LIBS $X_PRE_LIBS $X_LIBS $X_EXTRA_LIBS -lm" + +dnl ========================================================= +dnl if test "x$x_includes" != "x"; then +dnl CPPFLAGS="$CPPFLAGS -I$x_includes" +dnl fi +dnl ========================================================= + + dnl Reasonable stuff non-windoze variants ... :-) + + AC_CHECK_LIB(pthread, pthread_create) + AC_CHECK_LIB(GL, glNewList) + if test "x$ac_cv_lib_GL_glNewList" = "xno" ; then + dnl if no GL, check for MesaGL + AC_CHECK_LIB(MesaGL, glNewList,, + AC_MSG_ERROR([could not find working GL library])) + fi + + fi + + AC_CHECK_LIB(dl, dlclose) + + dnl Check SGI audio library + AC_CHECK_LIB(audio, ALopenport) + ;; +esac + + +dnl Checks for header files. + +AC_HEADER_STDC + +AC_CHECK_HEADER(windows.h, AC_DEFINE(WIN32)) + +if test "x$need_opengl" = "xyes"; then + dnl Check for OpenGl header files + + case "${host}" in + *-*-cygwin* | *-*-mingw32*) + dnl CygWin under Windoze. + + AC_CHECK_HEADER(GL/gl.h,, + AC_MSG_ERROR([OpenGL header file not found])) + ;; + *-apple-darwin*) + dnl Mac OS X + + AC_CHECK_HEADER(OpenGL/gl.h,, + AC_MSG_ERROR([OpenGL header file not found])) + ;; + *) + AC_CHECK_HEADER(GL/gl.h,, + AC_MSG_ERROR([OpenGL header file not found])) + ;; + esac +fi + + +dnl Warning flags +WFLAG="-Wall" +case "$host" in +mips-sgi-irix*) + if test "x$CXX" = "xCC"; then + WFLAG="-fullwarn"; + fi + ;; +*) + if test "x$CXX" = "xicpc" || test "x$CXX" = "xicc"; then + WFLAG="-w1" + fi + if test "x$GCC" != xyes; then + # if the compiler is not GCC we reset WFLAG to null for safety + WFLAG="" + fi + ;; +esac + +CFLAGS="$CFLAGS $WFLAG" +CXXFLAGS="$CXXFLAGS $WFLAG" + +dnl FreeBSD requires the -pthread switch to enable pthreads. Look for this +dnl weirdness. +save_CXXFLAGS="$CXXFLAGS" +save_CFLAGS="$CFLAGS" +save_LIBS=$LIBS +CXXFLAGS="-pthread $CXXFLAGS" +CFLAGS="-pthread $CFLAGS" +AC_CHECK_LIB(c_r, pthread_exit) +if test "x$ac_cv_lib_c_r_pthread_exit" != "xyes"; then + CFLAGS=$save_CFLAGS + CXXFLAGS=$save_CXXFLAGS +fi +LIBS=$save_LIBS + +dnl Checks for typedefs, structures, and compiler characteristics. + +dnl check for socklen_t (in Unix98) +AC_MSG_CHECKING(for socklen_t) +AC_TRY_COMPILE([ +#include +#include +socklen_t apa; +],[],[ +AC_MSG_RESULT(yes)],[ +AC_TRY_COMPILE([ +#include +#include +int accept (int, struct sockaddr *, size_t *); +],[],[ +AC_MSG_RESULT(size_t) +AC_DEFINE(socklen_t,size_t)], [ +AC_MSG_RESULT(int) +AC_DEFINE(socklen_t,int)])]) + + +AC_OUTPUT( \ + Makefile \ + src/Makefile \ + src/js/Makefile \ + src/util/Makefile \ + src/sg/Makefile \ + src/sl/Makefile \ + src/psl/Makefile \ + src/ssg/Makefile \ + src/ssgAux/Makefile \ + src/fnt/Makefile \ + src/pui/Makefile \ + src/puAux/Makefile \ + src/pw/Makefile \ + src/net/Makefile ) + +AC_MSG_RESULT( +[PLIB configuration information: + + Building FNT library: $enable_fnt + Building JS library: $enable_js + Building NET library: $enable_net + Building PUI library: $enable_pui + Building puAux library: $enable_puaux + Building SG library: $enable_sg + Building PSL library: $enable_psl + Building SL library: $enable_sl + Building SSG library: $enable_ssg + Building ssgAux library: $enable_ssgaux + Building PW library: $enable_pw + Building UTIL library: $enable_ul +]) + diff --git a/demos/README b/demos/README new file mode 100644 index 0000000..f80384f --- /dev/null +++ b/demos/README @@ -0,0 +1,16 @@ + +PLIB Demonstration Programs and other Utilities. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The programs released under this directory are +fully complete programs written either as demonstrations +of PLIB or as useful utility programs. Each one +has it's own licensing rules (although all are OpenSourced +in some way) and each has it's own build mechanism and +documentation. + +You can build all of the demo's (on UNIX-like OS's) +by running the 'build_all_demos' script. + +Enjoy! + diff --git a/demos/build_all_demos b/demos/build_all_demos new file mode 100755 index 0000000..eef78b9 --- /dev/null +++ b/demos/build_all_demos @@ -0,0 +1,22 @@ + +echo "Building ExPoser..." +cd exposer +./autogen.sh +./configure +make +cd .. + +echo "Building P-Guide..." +cd p-guide +./autogen.sh +./configure +make +cd .. + +echo "Building 3D TicTacToe..." +cd ttt3d +./autogen.sh +./configure +make +cd .. + diff --git a/demos/exposer/AUTHORS b/demos/exposer/AUTHORS new file mode 100644 index 0000000..a199f12 --- /dev/null +++ b/demos/exposer/AUTHORS @@ -0,0 +1,2 @@ +Exposer was written by Steve Baker. + diff --git a/demos/exposer/COPYING b/demos/exposer/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/demos/exposer/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/demos/exposer/ChangeLog b/demos/exposer/ChangeLog new file mode 100644 index 0000000..7c9e971 --- /dev/null +++ b/demos/exposer/ChangeLog @@ -0,0 +1,16 @@ + +ExPoser Change Log. +=================== + +ExPoser v0.0.1 (July 21st 2001) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Most bugs now removed. + + * Can load in 'scenery' + + * Better example models. + +ExPoser v0.0.0 (June 17th 2001) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * First release. + diff --git a/demos/exposer/INSTALL b/demos/exposer/INSTALL new file mode 100644 index 0000000..b42a17a --- /dev/null +++ b/demos/exposer/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/demos/exposer/Makefile.am b/demos/exposer/Makefile.am new file mode 100644 index 0000000..066b287 --- /dev/null +++ b/demos/exposer/Makefile.am @@ -0,0 +1,4 @@ +SUBDIRS = src data doc + +EXTRA_DIST = autogen.sh README exposer.dsw + diff --git a/demos/exposer/NEWS b/demos/exposer/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/demos/exposer/README b/demos/exposer/README new file mode 100644 index 0000000..3cc971e --- /dev/null +++ b/demos/exposer/README @@ -0,0 +1,44 @@ + +ExPoser 3D. +~~~~~~~~~~~ + by Steve Baker + + +INSTALLATION: + +Installation instructions are pretty basic, +and are covered in the documentation directory 'doc'. + + OpenGL (or Mesa) + GLUT (the GL Utility Toolkit) + PLIB (which can be obtained from one of: + http://plib.sourceforge.net + +Once that is done, it should be a simple matter of changing +to the directory where all this stuff is unpacked and type: + + ./configure + make + make install + +However, you might want to check the full documentation - +especially if you need to install Mesa/GLIDE/GLUT before +you can start. + +All documents are in HTML - so view them with your web browser. + +LICENSE: + +This software is released under the provisions of +the GNU General Public License (GPL) which can be +found in the file 'COPYING' in the current directory. + +DIRECTORY STRUCTURE: + +src -- Where the source code lives. + +data -- This contains all kinds of miscellaneous data + files to test with. + +doc -- Documentation - all in HTML + diff --git a/demos/exposer/autogen.sh b/demos/exposer/autogen.sh new file mode 100755 index 0000000..02a1eb9 --- /dev/null +++ b/demos/exposer/autogen.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +OSTYPE=`uname -s` + +AMFLAGS="--add-missing" +if test "$OSTYPE" = "IRIX" -o "$OSTYPE" = "IRIX64"; then + AMFLAGS=$AMFLAGS" --include-deps"; +fi + +echo "Running aclocal" +aclocal +echo "Running automake" +automake $AMFLAGS +echo "Running autoconf" +autoconf + +echo "======================================" +echo "Now you are ready to run './configure'" +echo "======================================" diff --git a/demos/exposer/configure.in b/demos/exposer/configure.in new file mode 100644 index 0000000..67ee3ce --- /dev/null +++ b/demos/exposer/configure.in @@ -0,0 +1,167 @@ +dnl Process this file with autoconf to produce a configure script. + +AC_INIT(src/exposer.cxx) +AM_INIT_AUTOMAKE(exposer, 0.2.0) + + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_CPP +AC_PROG_CXX +AC_PROG_CXXCPP +AC_PROG_INSTALL + +plib_suffix="-lplibjs -lplibsl -lplibssgaux -lplibssg -lplibpuaux -lplibpu -lplibfnt -lplibsg -lplibul" + +AC_LANG_CPLUSPLUS + + +dnl Command line arguments. + +dnl Don't use AC_HELP_STRING here as old versions of autoconf do not +dnl understand it. +AC_ARG_WITH(GL, +[ --with-GL=DIR set the prefix directory where GL resides], +GL_PREFIX=$withval, GL_PREFIX=auto) + +if test "x$GL_PREFIX" != "xauto"; then + LDFLAGS="$LDFLAGS -L$GL_PREFIX/lib" + CPPFLAGS="$CPPFLAGS -I$GL_PREFIX/include" +fi + + +dnl Checks for library functions. +dnl check for OpenGL related libraries + +AC_CANONICAL_HOST + +case "${host}" in +*-*-cygwin* | *-*-mingw32*) + dnl CygWin under Windoze. + + LIBS="$LIBS -lwinmm -lglut32 -lglu32 -lopengl32 -luser32 -lgdi32" + ;; +*-apple-darwin*) + dnl Mac OS X + + LIBS="$LIBS -framework GLUT -lobjc -framework OpenGL -framework Carbon" + ;; +*) + dnl Check for X11 + + AC_PATH_XTRA + + LDFLAGS="$LDFLAGS $X_LIBS" + + LIBS="$LIBS $X_PRE_LIBS -lXi -lXmu -lXext -lX11 $X_EXTRA_LIBS -lm" + +dnl ========================================================= +dnl if test "x$x_includes" != "x"; then +dnl CPPFLAGS="$CPPFLAGS -I$x_includes" +dnl fi +dnl ========================================================= + + dnl Reasonable stuff non-windoze variants ... :-) + + AC_CHECK_LIB(GL, glNewList) + if test "x$ac_cv_lib_GL_glNewList" = "xno" ; then + dnl if no GL, check for MesaGL + AC_CHECK_LIB(MesaGL, glNewList,, + AC_MSG_ERROR([could not find working GL library])) + fi + + AC_CHECK_LIB(GLU, gluLookAt) + if test "x$ac_cv_lib_GLU_gluLookAt" = "xno" ; then + dnl if no GLU, check for MesaGLU + AC_CHECK_LIB(MesaGLU, gluLookAt,, + AC_MSG_ERROR([could not find working GLU library])) + fi + + dnl check for glut...or freeglut + AC_CHECK_LIB(freeglut, glutGetModifiers) + if test "x$ac_cv_lib_freeglut_glutGetModifiers" = "xno" ; then + dnl if no freeglut, check for Real GLUT + AC_CHECK_LIB(glut, glutGetModifiers,, + AC_MSG_ERROR([could not find working GLUT library])) + fi + + AC_CHECK_LIB(dl, dlclose) + + dnl Check SGI audio library + AC_CHECK_LIB(audio, ALopenport, SND_LIBS="-laudio") + ;; +esac + +dnl Check PLIB library +AC_CHECK_LIB(plibul, ulInit, true, +AC_MSG_ERROR([there seems to be a problem with the PLIB libraries])) + +LIBS="$plib_suffix $LIBS" + + +dnl Checks for header files. + +AC_HEADER_STDC +AC_CHECK_HEADER(windows.h, AC_DEFINE(WIN32)) + +case "${host}" in +*-*-cygwin* | *-*-mingw32*) + dnl CygWin under Windoze. + + AC_CHECK_HEADERS(GL/gl.h GL/glu.h,, + AC_MSG_ERROR([OpenGL header files not found])) + + AC_CHECK_HEADER(GL/glut.h, AC_DEFINE(GLUT_IS_PRESENT), + AC_MSG_ERROR([GLUT header file not found])) + ;; +*-apple-darwin*) + dnl Mac OS X + + AC_CHECK_HEADERS(OpenGL/gl.h OpenGL/glu.h,, + AC_MSG_ERROR([OpenGL header files not found])) + + AC_CHECK_HEADER(GLUT/glut.h, AC_DEFINE(GLUT_IS_PRESENT), + AC_MSG_ERROR([GLUT header file not found])) + ;; +*) + AC_CHECK_HEADERS(GL/gl.h GL/glu.h,, + AC_MSG_ERROR([OpenGL header files not found])) + + if test "x$ac_cv_lib_freeglut_glutGetModifiers" = "xyes"; then + AC_CHECK_HEADER(GL/freeglut.h, AC_DEFINE(FREEGLUT_IS_PRESENT), + AC_MSG_ERROR([freeglut header file not found])) + else + AC_CHECK_HEADER(GL/glut.h, AC_DEFINE(GLUT_IS_PRESENT), + AC_MSG_ERROR([GLUT header file not found])) + fi + ;; +esac + +AC_CHECK_HEADER(plib/ul.h,, AC_MSG_ERROR([PLIB header files not found])) + + +dnl Warning flags +WFLAG="-Wall" +case "$host" in +mips-sgi-irix*) + if test "x$CXX" = "xCC"; then + WFLAG="-fullwarn"; + fi + ;; +*) + if test "x$CXX" = "xicpc" || test "x$CXX" = "xicc"; then + WFLAG="-w1" + fi + ;; +esac + +CFLAGS="$CFLAGS $WFLAG" +CXXFLAGS="$CXXFLAGS $WFLAG" + + +AC_OUTPUT( Makefile \ + data/Makefile \ + doc/Makefile \ + src/Makefile \ + ) + diff --git a/demos/exposer/data/Makefile.am b/demos/exposer/data/Makefile.am new file mode 100644 index 0000000..b29ffd2 --- /dev/null +++ b/demos/exposer/data/Makefile.am @@ -0,0 +1,7 @@ + +pkgdatadir = $(datadir)/games/@PACKAGE@/data + +pkgdata_DATA = $(wildcard *.rgb *.ac *.bones) + +EXTRA_DIST = $(pkgdata_DATA) + diff --git a/demos/exposer/data/dog.ac b/demos/exposer/data/dog.ac new file mode 100644 index 0000000..545c68f --- /dev/null +++ b/demos/exposer/data/dog.ac @@ -0,0 +1,1539 @@ +AC3Db +MATERIAL "ac3dmat3" rgb 1 0 0 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "ac3dmat5" rgb 1 1 0 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "ac3dmat6" rgb 0 1 0 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "ac3dmat9" rgb 0 0 1 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "" rgb 0 0 0 amb 0 0 0 emis 0 0 0 spec 0 0 0 shi 0 trans 0 +MATERIAL "" rgb 1 1 1 amb 1 1 1 emis 1 1 1 spec 0.502 0.502 0.502 shi 0 trans 0 +MATERIAL "" rgb 0.561 0.404 0.251 amb 0.702 0.475 0.2 emis 0 0 0 spec 0 0 0 shi 0 trans 0 +OBJECT world +kids 12 +OBJECT poly +name "nose" +loc -0.725253 0.226588 -0.122592 +numvert 6 +0.70885 0.640855 -1.10242 +0.63385 0.72076 -1.00242 +0.78385 0.72076 -1.00242 +0.70885 0.681685 -1.11637 +0.654175 0.72493 -1.06597 +0.763525 0.72493 -1.06597 +numsurf 5 +SURF 0x10 +mat 4 +refs 3 +0 0 0 +1 0 0 +2 0 0 +SURF 0x10 +mat 4 +refs 3 +5 0 0 +4 0 0 +3 0 0 +SURF 0x0 +mat 4 +refs 4 +0 0 0 +3 0 0 +4 0 0 +1 0 0 +SURF 0x0 +mat 4 +refs 4 +1 0 0 +4 0 0 +5 0 0 +2 0 0 +SURF 0x0 +mat 4 +refs 4 +2 0 0 +5 0 0 +3 0 0 +0 0 0 +kids 0 +OBJECT poly +name "body" +loc 0.586292 -0.0392416 -0.122191 +numvert 26 +-0.453097 0.85581 -0.403335 +-0.528095 0.98571 -0.403335 +-0.453097 0.965615 -0.203335 +-0.303097 0.70581 -0.203335 +-0.403097 1.05222 0.146665 +-0.203097 0.70581 0.146665 +-0.54331 0.86584 0.472749 +-0.353097 0.70581 0.446664 +-0.603095 0.762285 0.52058 +-0.678095 0.98571 -0.403335 +-0.753095 0.965615 -0.203335 +-0.803095 1.05222 0.146665 +-0.662885 0.86584 0.472749 +-0.603095 1.04208 0.870785 +-0.753095 0.85581 -0.403335 +-0.903095 0.70581 -0.203335 +-1.0031 0.70581 0.146665 +-0.853095 0.70581 0.446664 +-0.678095 0.725905 -0.403335 +-0.753095 0.446 -0.203335 +-0.803095 0.359398 0.146665 +-0.728095 0.489301 0.446664 +-0.528095 0.725905 -0.403335 +-0.453097 0.446 -0.203335 +-0.403097 0.359398 0.146665 +-0.478097 0.489301 0.446664 +numsurf 26 +SURF 0x10 +mat 6 +refs 4 +0 0 0 +1 0 0 +2 0 0 +3 0 0 +SURF 0x10 +mat 6 +refs 4 +3 0 0 +2 0 0 +4 0 0 +5 0 0 +SURF 0x10 +mat 6 +refs 4 +5 0 0 +4 0 0 +6 0 0 +7 0 0 +SURF 0x10 +mat 6 +refs 3 +7 0 0 +6 0 0 +8 0 0 +SURF 0x10 +mat 6 +refs 4 +1 0 0 +9 0 0 +10 0 0 +2 0 0 +SURF 0x10 +mat 6 +refs 4 +2 0 0 +10 0 0 +11 0 0 +4 0 0 +SURF 0x10 +mat 6 +refs 4 +4 0 0 +11 0 0 +12 0 0 +6 0 0 +SURF 0x10 +mat 6 +refs 3 +6 0 0 +12 0 0 +13 0 0 +SURF 0x10 +mat 6 +refs 3 +12 0 0 +8 0 0 +13 0 0 +SURF 0x10 +mat 6 +refs 3 +8 0 0 +6 0 0 +13 0 0 +SURF 0x10 +mat 6 +refs 4 +9 0 0 +14 0 0 +15 0 0 +10 0 0 +SURF 0x10 +mat 6 +refs 4 +10 0 0 +15 0 0 +16 0 0 +11 0 0 +SURF 0x10 +mat 6 +refs 4 +11 0 0 +16 0 0 +17 0 0 +12 0 0 +SURF 0x10 +mat 6 +refs 3 +12 0 0 +17 0 0 +8 0 0 +SURF 0x10 +mat 6 +refs 4 +14 0 0 +18 0 0 +19 0 0 +15 0 0 +SURF 0x10 +mat 6 +refs 4 +15 0 0 +19 0 0 +20 0 0 +16 0 0 +SURF 0x10 +mat 6 +refs 4 +16 0 0 +20 0 0 +21 0 0 +17 0 0 +SURF 0x10 +mat 6 +refs 3 +17 0 0 +21 0 0 +8 0 0 +SURF 0x10 +mat 6 +refs 4 +18 0 0 +22 0 0 +23 0 0 +19 0 0 +SURF 0x10 +mat 6 +refs 4 +19 0 0 +23 0 0 +24 0 0 +20 0 0 +SURF 0x10 +mat 6 +refs 4 +20 0 0 +24 0 0 +25 0 0 +21 0 0 +SURF 0x10 +mat 6 +refs 3 +21 0 0 +25 0 0 +8 0 0 +SURF 0x10 +mat 6 +refs 4 +22 0 0 +0 0 0 +3 0 0 +23 0 0 +SURF 0x10 +mat 6 +refs 4 +23 0 0 +3 0 0 +5 0 0 +24 0 0 +SURF 0x10 +mat 6 +refs 4 +24 0 0 +5 0 0 +7 0 0 +25 0 0 +SURF 0x10 +mat 6 +refs 3 +25 0 0 +7 0 0 +8 0 0 +kids 0 +OBJECT poly +name "head" +loc -0.300768 0.330614 -0.122191 +numvert 7 +0.385963 0.759545 -0.605295 +0.408963 0.65246 -0.703335 +0.365838 0.699325 -0.64344 +0.283963 0.688305 -0.68395 +0.184782 0.75935 -0.60292 +0.198369 0.699325 -0.64344 +0.158963 0.65246 -0.703335 +numsurf 6 +SURF 0x10 +mat 5 +refs 3 +0 0 0 +1 0 0 +2 0 0 +SURF 0x10 +mat 4 +refs 3 +1 0 0 +3 0 0 +2 0 0 +SURF 0x10 +mat 5 +refs 3 +3 0 0 +0 0 0 +2 0 0 +SURF 0x10 +mat 5 +refs 3 +4 0 0 +3 0 0 +5 0 0 +SURF 0x10 +mat 4 +refs 3 +3 0 0 +6 0 0 +5 0 0 +SURF 0x10 +mat 5 +refs 3 +6 0 0 +4 0 0 +5 0 0 +kids 0 +OBJECT poly +name "head" +loc -0.400768 0.139108 -0.122191 +numvert 32 +0.533965 0.67746 -1.00333 +0.458963 0.80736 -1.00333 +0.508965 0.843965 -0.703335 +0.633965 0.67746 -0.803335 +0.485964 0.95105 -0.605295 +0.583965 0.67746 -0.603335 +0.453348 0.92959 -0.50328 +0.533965 0.67746 -0.503335 +0.458963 0.80736 -0.403335 +0.533965 0.67746 -0.403335 +0.308963 0.80736 -1.00333 +0.258963 0.843965 -0.703335 +0.315133 0.92218 -0.50144 +0.308963 0.80736 -0.403335 +0.233963 0.67746 -1.00333 +0.133963 0.67746 -0.803335 +0.183963 0.67746 -0.603335 +0.284783 0.950855 -0.60292 +0.233963 0.67746 -0.503335 +0.233963 0.67746 -0.403335 +0.303331 0.564205 -1.00138 +0.258963 0.460952 -0.803335 +0.283963 0.504255 -0.603335 +0.308963 0.547555 -0.503335 +0.308963 0.547555 -0.403335 +0.453331 0.564205 -1.00138 +0.508965 0.460952 -0.803335 +0.483963 0.504255 -0.603335 +0.458963 0.547555 -0.503335 +0.458963 0.547555 -0.403335 +0.383963 0.72746 -1.10333 +0.383963 0.879815 -0.68395 +numsurf 30 +SURF 0x10 +mat 6 +refs 4 +0 0 0 +1 0 0 +2 0 0 +3 0 0 +SURF 0x10 +mat 6 +refs 4 +3 0 0 +2 0 0 +4 0 0 +5 0 0 +SURF 0x10 +mat 6 +refs 4 +5 0 0 +4 0 0 +6 0 0 +7 0 0 +SURF 0x10 +mat 6 +refs 4 +7 0 0 +6 0 0 +8 0 0 +9 0 0 +SURF 0x10 +mat 6 +refs 4 +1 0 0 +10 0 0 +11 0 0 +2 0 0 +SURF 0x10 +mat 6 +refs 4 +6 0 0 +12 0 0 +13 0 0 +8 0 0 +SURF 0x10 +mat 6 +refs 4 +10 0 0 +14 0 0 +15 0 0 +11 0 0 +SURF 0x10 +mat 6 +refs 4 +11 0 0 +15 0 0 +16 0 0 +17 0 0 +SURF 0x10 +mat 6 +refs 4 +17 0 0 +16 0 0 +18 0 0 +12 0 0 +SURF 0x10 +mat 6 +refs 4 +12 0 0 +18 0 0 +19 0 0 +13 0 0 +SURF 0x10 +mat 6 +refs 4 +14 0 0 +20 0 0 +21 0 0 +15 0 0 +SURF 0x10 +mat 6 +refs 4 +15 0 0 +21 0 0 +22 0 0 +16 0 0 +SURF 0x10 +mat 6 +refs 4 +16 0 0 +22 0 0 +23 0 0 +18 0 0 +SURF 0x10 +mat 6 +refs 4 +18 0 0 +23 0 0 +24 0 0 +19 0 0 +SURF 0x10 +mat 6 +refs 4 +20 0 0 +25 0 0 +26 0 0 +21 0 0 +SURF 0x10 +mat 6 +refs 4 +21 0 0 +26 0 0 +27 0 0 +22 0 0 +SURF 0x10 +mat 6 +refs 4 +22 0 0 +27 0 0 +28 0 0 +23 0 0 +SURF 0x10 +mat 6 +refs 4 +23 0 0 +28 0 0 +29 0 0 +24 0 0 +SURF 0x10 +mat 6 +refs 4 +25 0 0 +0 0 0 +3 0 0 +26 0 0 +SURF 0x10 +mat 6 +refs 4 +26 0 0 +3 0 0 +5 0 0 +27 0 0 +SURF 0x10 +mat 6 +refs 4 +27 0 0 +5 0 0 +7 0 0 +28 0 0 +SURF 0x10 +mat 6 +refs 4 +28 0 0 +7 0 0 +9 0 0 +29 0 0 +SURF 0x10 +mat 6 +refs 3 +30 0 0 +20 0 0 +14 0 0 +SURF 0x10 +mat 6 +refs 3 +30 0 0 +25 0 0 +20 0 0 +SURF 0x10 +mat 6 +refs 3 +30 0 0 +0 0 0 +25 0 0 +SURF 0x10 +mat 6 +refs 3 +30 0 0 +1 0 0 +0 0 0 +SURF 0x10 +mat 6 +refs 3 +30 0 0 +14 0 0 +10 0 0 +SURF 0x10 +mat 6 +refs 4 +4 0 0 +17 0 0 +12 0 0 +6 0 0 +SURF 0x10 +mat 6 +refs 3 +2 0 0 +11 0 0 +31 0 0 +SURF 0x10 +mat 6 +refs 3 +17 0 0 +4 0 0 +31 0 0 +kids 0 +OBJECT poly +name "l_hind_leg" +loc 0.704382 -0.340368 0.250812 +numvert 16 +-1.02078 1.07199 0.104938 +-1.06371 0.935195 -0.193764 +-1.06657 0.62464 0.00429365 +-1.09876 0.391723 -0.0382313 +-1.10781 0.363491 -0.189256 +-1.15356 0.314084 -0.242758 +-1.01939 0.299968 0.108566 +-1.05766 0.645815 0.0681295 +-0.963235 1.03401 0.181203 +-0.95813 1.11164 0.0775365 +-0.9622 0.62464 -0.0236723 +-0.95559 0.391723 -0.0765935 +-1.02327 0.363491 -0.211908 +-1.01039 0.314084 -0.281121 +-0.95092 0.299968 0.0902175 +-0.956215 0.645815 0.0356551 +numsurf 29 +SURF 0x10 +mat 6 +refs 3 +0 0.784615 1 +1 0.153846 0.782609 +2 0.569231 0.4 +SURF 0x10 +mat 6 +refs 3 +3 0.461538 0.113043 +4 0.138462 0.0782608 +5 0 0.0173913 +SURF 0x10 +mat 6 +refs 3 +3 0.461538 0.113043 +5 0 0.0173913 +6 0.815385 0 +SURF 0x10 +mat 6 +refs 3 +2 0.569231 0.4 +3 0.461538 0.113043 +6 0.815385 0 +SURF 0x10 +mat 6 +refs 3 +0 0.784615 1 +2 0.569231 0.4 +6 0.815385 0 +SURF 0x10 +mat 6 +refs 3 +0 0.784615 1 +6 0.815385 0 +7 0.815385 0.426087 +SURF 0x10 +mat 6 +refs 3 +0 0.784615 1 +7 0.815385 0.426087 +8 1 0.904348 +SURF 0x10 +mat 6 +refs 3 +10 0 0 +1 0 0 +9 0 0 +SURF 0x10 +mat 6 +refs 3 +13 0 0 +12 0 0 +11 0 0 +SURF 0x10 +mat 6 +refs 3 +14 0 0 +13 0 0 +11 0 0 +SURF 0x10 +mat 6 +refs 3 +14 0 0 +11 0 0 +10 0 0 +SURF 0x10 +mat 6 +refs 3 +14 0 0 +10 0 0 +9 0 0 +SURF 0x10 +mat 6 +refs 3 +15 0 0 +14 0 0 +9 0 0 +SURF 0x10 +mat 6 +refs 3 +8 0 0 +15 0 0 +9 0 0 +SURF 0x10 +mat 6 +refs 3 +0 0 0 +9 0 0 +1 0 0 +SURF 0x10 +mat 6 +refs 3 +1 0 0 +10 0 0 +2 0 0 +SURF 0x10 +mat 6 +refs 4 +2 0 0 +10 0 0 +9 0 0 +0 0 0 +SURF 0x10 +mat 6 +refs 4 +3 0 0 +11 0 0 +12 0 0 +4 0 0 +SURF 0x10 +mat 6 +refs 4 +4 0 0 +12 0 0 +13 0 0 +5 0 0 +SURF 0x10 +mat 6 +refs 4 +5 0 0 +13 0 0 +11 0 0 +3 0 0 +SURF 0x10 +mat 6 +refs 4 +5 0 0 +13 0 0 +14 0 0 +6 0 0 +SURF 0x10 +mat 6 +refs 4 +6 0 0 +14 0 0 +11 0 0 +3 0 0 +SURF 0x10 +mat 6 +refs 4 +2 0 0 +10 0 0 +11 0 0 +3 0 0 +SURF 0x10 +mat 6 +refs 4 +6 0 0 +14 0 0 +10 0 0 +2 0 0 +SURF 0x10 +mat 6 +refs 4 +6 0 0 +14 0 0 +9 0 0 +0 0 0 +SURF 0x10 +mat 6 +refs 4 +6 0 0 +14 0 0 +15 0 0 +7 0 0 +SURF 0x10 +mat 6 +refs 4 +7 0 0 +15 0 0 +9 0 0 +0 0 0 +SURF 0x10 +mat 6 +refs 3 +7 0 0 +15 0 0 +8 0 0 +SURF 0x10 +mat 6 +refs 3 +8 0 0 +9 0 0 +0 0 0 +kids 0 +OBJECT poly +name "r_hind_leg" +loc 0.676152 -0.340368 -0.454996 +numvert 16 +-0.349655 1.07199 0.782515 +-0.306731 0.935195 0.483811 +-0.303869 0.62464 0.68187 +-0.271681 0.391723 0.639345 +-0.262634 0.363491 0.48832 +-0.216879 0.314084 0.434817 +-0.351043 0.299968 0.78614 +-0.312778 0.645815 0.745705 +-0.407203 1.03401 0.85878 +-0.412307 1.11164 0.75511 +-0.408239 0.62464 0.653905 +-0.414851 0.391723 0.60098 +-0.347174 0.363491 0.465667 +-0.360048 0.314084 0.396455 +-0.41952 0.299968 0.767795 +-0.414223 0.645815 0.71323 +numsurf 29 +SURF 0x10 +mat 6 +refs 3 +2 0.569231 0.4 +1 0.153846 0.782609 +0 0.784615 1 +SURF 0x10 +mat 6 +refs 3 +5 0 0.0173913 +4 0.138462 0.0782608 +3 0.461538 0.113043 +SURF 0x10 +mat 6 +refs 3 +6 0.815385 0 +5 0 0.0173913 +3 0.461538 0.113043 +SURF 0x10 +mat 6 +refs 3 +6 0.815385 0 +3 0.461538 0.113043 +2 0.569231 0.4 +SURF 0x10 +mat 6 +refs 3 +6 0.815385 0 +2 0.569231 0.4 +0 0.784615 1 +SURF 0x10 +mat 6 +refs 3 +7 0.815385 0.426087 +6 0.815385 0 +0 0.784615 1 +SURF 0x10 +mat 6 +refs 3 +8 1 0.904348 +7 0.815385 0.426087 +0 0.784615 1 +SURF 0x10 +mat 6 +refs 3 +9 0 0 +1 0 0 +10 0 0 +SURF 0x10 +mat 6 +refs 3 +11 0 0 +12 0 0 +13 0 0 +SURF 0x10 +mat 6 +refs 3 +11 0 0 +13 0 0 +14 0 0 +SURF 0x10 +mat 6 +refs 3 +10 0 0 +11 0 0 +14 0 0 +SURF 0x10 +mat 6 +refs 3 +9 0 0 +10 0 0 +14 0 0 +SURF 0x10 +mat 6 +refs 3 +9 0 0 +14 0 0 +15 0 0 +SURF 0x10 +mat 6 +refs 3 +9 0 0 +15 0 0 +8 0 0 +SURF 0x10 +mat 6 +refs 3 +1 0 0 +9 0 0 +0 0 0 +SURF 0x10 +mat 6 +refs 3 +2 0 0 +10 0 0 +1 0 0 +SURF 0x10 +mat 6 +refs 4 +0 0 0 +9 0 0 +10 0 0 +2 0 0 +SURF 0x10 +mat 6 +refs 4 +4 0 0 +12 0 0 +11 0 0 +3 0 0 +SURF 0x10 +mat 6 +refs 4 +5 0 0 +13 0 0 +12 0 0 +4 0 0 +SURF 0x10 +mat 6 +refs 4 +3 0 0 +11 0 0 +13 0 0 +5 0 0 +SURF 0x10 +mat 6 +refs 4 +6 0 0 +14 0 0 +13 0 0 +5 0 0 +SURF 0x10 +mat 6 +refs 4 +3 0 0 +11 0 0 +14 0 0 +6 0 0 +SURF 0x10 +mat 6 +refs 4 +3 0 0 +11 0 0 +10 0 0 +2 0 0 +SURF 0x10 +mat 6 +refs 4 +2 0 0 +10 0 0 +14 0 0 +6 0 0 +SURF 0x10 +mat 6 +refs 4 +0 0 0 +9 0 0 +14 0 0 +6 0 0 +SURF 0x10 +mat 6 +refs 4 +7 0 0 +15 0 0 +14 0 0 +6 0 0 +SURF 0x10 +mat 6 +refs 4 +0 0 0 +9 0 0 +15 0 0 +7 0 0 +SURF 0x10 +mat 6 +refs 3 +8 0 0 +15 0 0 +7 0 0 +SURF 0x10 +mat 6 +refs 3 +0 0 0 +9 0 0 +8 0 0 +kids 0 +OBJECT poly +name "l_front_leg" +loc 0.140728 -0.396832 0.230312 +numvert 15 +-0.44984 1.03401 -0.534705 +-0.481804 0.66699 -0.65257 +-0.510035 0.44113 -0.546695 +-0.510035 0.398781 -0.701975 +-0.601015 0.363491 -0.737265 +-0.601015 0.363491 -0.454942 +-0.510035 0.66699 -0.52552 +-0.488201 1.00577 -0.391536 +-0.393375 1.03401 -0.534705 +-0.453571 0.44113 -0.546695 +-0.453571 0.398781 -0.701975 +-0.453571 0.363491 -0.737265 +-0.453571 0.363491 -0.454942 +-0.453571 0.66699 -0.52552 +-0.431737 1.00577 -0.391536 +numsurf 25 +SURF 0x10 +mat 6 +refs 3 +0 0.571429 1 +1 0.244898 0.44086 +2 0.55102 0.11828 +SURF 0x10 +mat 6 +refs 3 +2 0.55102 0.11828 +3 0.102041 0.0752688 +4 0 0.0215054 +SURF 0x10 +mat 6 +refs 3 +2 0.55102 0.11828 +4 0 0.0215054 +5 0.816326 0 +SURF 0x10 +mat 6 +refs 3 +2 0.55102 0.11828 +5 0.816326 0 +6 0.612245 0.44086 +SURF 0x10 +mat 6 +refs 3 +0 0.571429 1 +2 0.55102 0.11828 +6 0.612245 0.44086 +SURF 0x10 +mat 6 +refs 3 +0 0.571429 1 +6 0.612245 0.44086 +7 1 0.956989 +SURF 0x10 +mat 6 +refs 3 +9 0 0 +1 0 0 +8 0 0 +SURF 0x10 +mat 6 +refs 3 +11 0 0 +10 0 0 +9 0 0 +SURF 0x10 +mat 6 +refs 3 +12 0 0 +11 0 0 +9 0 0 +SURF 0x10 +mat 6 +refs 3 +13 0 0 +12 0 0 +9 0 0 +SURF 0x10 +mat 6 +refs 3 +13 0 0 +9 0 0 +8 0 0 +SURF 0x10 +mat 6 +refs 3 +14 0 0 +13 0 0 +8 0 0 +SURF 0x10 +mat 6 +refs 3 +0 0 0 +8 0 0 +1 0 0 +SURF 0x10 +mat 6 +refs 3 +1 0 0 +9 0 0 +2 0 0 +SURF 0x10 +mat 6 +refs 4 +2 0 0 +9 0 0 +8 0 0 +0 0 0 +SURF 0x10 +mat 6 +refs 4 +2 0 0 +9 0 0 +10 0 0 +3 0 0 +SURF 0x10 +mat 6 +refs 4 +3 0 0 +10 0 0 +11 0 0 +4 0 0 +SURF 0x10 +mat 6 +refs 4 +4 0 0 +11 0 0 +9 0 0 +2 0 0 +SURF 0x10 +mat 6 +refs 4 +4 0 0 +11 0 0 +12 0 0 +5 0 0 +SURF 0x10 +mat 6 +refs 4 +5 0 0 +12 0 0 +9 0 0 +2 0 0 +SURF 0x10 +mat 6 +refs 4 +5 0 0 +12 0 0 +13 0 0 +6 0 0 +SURF 0x10 +mat 6 +refs 4 +6 0 0 +13 0 0 +9 0 0 +2 0 0 +SURF 0x10 +mat 6 +refs 4 +6 0 0 +13 0 0 +8 0 0 +0 0 0 +SURF 0x10 +mat 6 +refs 4 +6 0 0 +13 0 0 +14 0 0 +7 0 0 +SURF 0x10 +mat 6 +refs 4 +7 0 0 +14 0 0 +8 0 0 +0 0 0 +kids 0 +OBJECT poly +name "r_front_leg" +loc 0.13367 -0.396832 -0.426089 +numvert 15 +0.118907 1.03401 0.114638 +0.150872 0.66699 -0.00322455 +0.179104 0.44113 0.102646 +0.179104 0.398781 -0.052631 +0.270085 0.363491 -0.0879215 +0.270085 0.363491 0.194402 +0.179104 0.66699 0.123821 +0.15727 1.00577 0.257807 +0.062443 1.03401 0.114638 +0.12264 0.44113 0.102646 +0.12264 0.398781 -0.052631 +0.12264 0.363491 -0.0879215 +0.12264 0.363491 0.194402 +0.12264 0.66699 0.123821 +0.100805 1.00577 0.257807 +numsurf 25 +SURF 0x10 +mat 6 +refs 3 +2 0.55102 0.11828 +1 0.244898 0.44086 +0 0.571429 1 +SURF 0x10 +mat 6 +refs 3 +4 0 0.0215054 +3 0.102041 0.0752688 +2 0.55102 0.11828 +SURF 0x10 +mat 6 +refs 3 +5 0.816326 0 +4 0 0.0215054 +2 0.55102 0.11828 +SURF 0x10 +mat 6 +refs 3 +6 0.612245 0.44086 +5 0.816326 0 +2 0.55102 0.11828 +SURF 0x10 +mat 6 +refs 3 +6 0.612245 0.44086 +2 0.55102 0.11828 +0 0.571429 1 +SURF 0x10 +mat 6 +refs 3 +7 1 0.956989 +6 0.612245 0.44086 +0 0.571429 1 +SURF 0x10 +mat 6 +refs 3 +8 0 0 +1 0 0 +9 0 0 +SURF 0x10 +mat 6 +refs 3 +9 0 0 +10 0 0 +11 0 0 +SURF 0x10 +mat 6 +refs 3 +9 0 0 +11 0 0 +12 0 0 +SURF 0x10 +mat 6 +refs 3 +9 0 0 +12 0 0 +13 0 0 +SURF 0x10 +mat 6 +refs 3 +8 0 0 +9 0 0 +13 0 0 +SURF 0x10 +mat 6 +refs 3 +8 0 0 +13 0 0 +14 0 0 +SURF 0x10 +mat 6 +refs 3 +1 0 0 +8 0 0 +0 0 0 +SURF 0x10 +mat 6 +refs 3 +2 0 0 +9 0 0 +1 0 0 +SURF 0x10 +mat 6 +refs 4 +0 0 0 +8 0 0 +9 0 0 +2 0 0 +SURF 0x10 +mat 6 +refs 4 +3 0 0 +10 0 0 +9 0 0 +2 0 0 +SURF 0x10 +mat 6 +refs 4 +4 0 0 +11 0 0 +10 0 0 +3 0 0 +SURF 0x10 +mat 6 +refs 4 +2 0 0 +9 0 0 +11 0 0 +4 0 0 +SURF 0x10 +mat 6 +refs 4 +5 0 0 +12 0 0 +11 0 0 +4 0 0 +SURF 0x10 +mat 6 +refs 4 +2 0 0 +9 0 0 +12 0 0 +5 0 0 +SURF 0x10 +mat 6 +refs 4 +6 0 0 +13 0 0 +12 0 0 +5 0 0 +SURF 0x10 +mat 6 +refs 4 +2 0 0 +9 0 0 +13 0 0 +6 0 0 +SURF 0x10 +mat 6 +refs 4 +0 0 0 +8 0 0 +13 0 0 +6 0 0 +SURF 0x10 +mat 6 +refs 4 +7 0 0 +14 0 0 +13 0 0 +6 0 0 +SURF 0x10 +mat 6 +refs 4 +0 0 0 +8 0 0 +14 0 0 +7 0 0 +kids 0 +OBJECT poly +name "right_ear" +loc 0.229869 1.07982 -0.695912 +numvert 5 +-0.144673 0.0103428 -0.0315753 +0.0925925 -0.098678 -0.076712 +0.155331 -0.130047 -0.0273054 +0.0714185 -0.098678 0.0503335 +-0.17729 -0.0111147 0.070438 +numsurf 6 +SURF 0x10 +mat 6 +refs 3 +0 0.117647 0.25 +1 0.764706 0 +2 1 0.35 +SURF 0x10 +mat 6 +refs 3 +0 0.117647 0.25 +2 1 0.35 +3 0.705882 0.9 +SURF 0x10 +mat 6 +refs 3 +0 0.117647 0.25 +3 0.705882 0.9 +4 0 1 +SURF 0x10 +mat 6 +refs 3 +4 0 1 +3 0.705882 0.9 +2 1 0.35 +SURF 0x10 +mat 6 +refs 3 +4 0 1 +2 1 0.35 +1 0.764706 0 +SURF 0x10 +mat 6 +refs 3 +4 0 1 +1 0.764706 0 +0 0.117647 0.25 +kids 0 +OBJECT poly +name "left_ear" +loc -0.261382 1.07611 -0.693597 +numvert 5 +0.145397 0.013855 -0.0315158 +-0.09105 -0.0949725 -0.0762386 +-0.175747 -0.113794 -0.0205581 +-0.069876 -0.0949725 0.050807 +0.175747 -0.0148195 0.0699645 +numsurf 6 +SURF 0x10 +mat 6 +refs 3 +4 0 1 +3 0.705882 0.9 +2 1 0.35 +SURF 0x10 +mat 6 +refs 3 +4 0 1 +2 1 0.35 +1 0.764706 0 +SURF 0x10 +mat 6 +refs 3 +4 0 1 +1 0.764706 0 +0 0.117647 0.25 +SURF 0x10 +mat 6 +refs 3 +0 0.117647 0.25 +1 0.764706 0 +2 1 0.35 +SURF 0x10 +mat 6 +refs 3 +0 0.117647 0.25 +2 1 0.35 +3 0.705882 0.9 +SURF 0x10 +mat 6 +refs 3 +0 0.117647 0.25 +3 0.705882 0.9 +4 0 1 +kids 0 +OBJECT poly +name "tongue" +loc -0.0252535 0.611636 -1.12259 +numvert 4 +-0.072184 0.0916755 -0.000977755 +-0.025 -0.1 -0.0999999 +0.025 -0.1 -0.0999999 +0.077816 0.0916755 -0.000977755 +numsurf 1 +SURF 0x30 +mat 0 +refs 4 +3 1 1 +2 0.666667 0 +1 0.333333 0 +0 0 1 +kids 0 +OBJECT poly +name "line" +loc -0.0252535 0.484011 -0.247592 +numvert 29 +0.0250001 0.277625 -0.875 +0.0250001 0.027625 -0.975 +0.0250001 0.0776249 -0.075 +0.0250001 0.327625 -0.075 +0.0250001 0.277625 -0.875 +0.025 0.427625 -0.375 +0.0250001 0.327625 0.575 +0.0250001 0.477625 0.975 +-0.425 0.527625 -0.475 +0.425 0.527625 -0.475 +-0.275 0.127625 0.0250001 +0.0250001 0.327625 0.075 +0.275 0.127625 0.0250001 +-0.275 0.127625 0.425 +0.325 0.127625 0.425 +-0.305 -0.224875 -0.1575 +-0.338 -0.467125 -0.0565 +-0.338 -0.527625 -0.2985 +0.275 0.127625 0.0250001 +0.3 -0.224875 -0.1575 +0.3275 -0.467125 -0.0565 +0.3275 -0.527625 -0.2985 +-0.305 -0.169875 0.5575 +-0.338 -0.467125 0.5485 +-0.338 -0.527625 0.246 +0.325 0.127625 0.425 +0.355 -0.169875 0.5575 +0.388 -0.467125 0.5485 +0.388 -0.527625 0.246 +numsurf 10 +SURF 0x22 +mat 3 +refs 2 +0 1 1 +1 0 0 +SURF 0x22 +mat 0 +refs 2 +2 0 0 +3 0 1 +SURF 0x22 +mat 2 +refs 5 +4 0 0.333333 +5 0.342105 0.333333 +3 0.447368 0 +6 0.789474 0 +7 1 1 +SURF 0x22 +mat 3 +refs 3 +8 0 0.5 +5 0.529412 0 +9 1 1 +SURF 0x22 +mat 1 +refs 3 +10 0 1 +11 0.545455 0 +12 1 1 +SURF 0x22 +mat 1 +refs 3 +13 0 1 +6 0.5 0 +14 1 1 +SURF 0x22 +mat 1 +refs 4 +10 1 1 +15 0.4 0.461538 +16 0.8 0.0769231 +17 0 0 +SURF 0x22 +mat 1 +refs 4 +18 1 1 +19 0.4 0.461538 +20 0.8 0.0769231 +21 0 0 +SURF 0x22 +mat 1 +refs 4 +13 1 1 +22 1 0.466667 +23 0.833333 0.0666667 +24 0 0 +SURF 0x22 +mat 1 +refs 4 +25 1 1 +26 1 0.466667 +27 0.833333 0.0666667 +28 0 0 +kids 0 diff --git a/demos/exposer/data/dog.bones b/demos/exposer/data/dog.bones new file mode 100644 index 0000000..720e86a --- /dev/null +++ b/demos/exposer/data/dog.bones @@ -0,0 +1,150 @@ +NUMBONES=24 NUMEVENTS=5 MAXTIME=3.392857 Z_OFFSET=0 SPEED=0 +BONE "Tongue" HP. +BONE "WholeDog" H.. +BONE "Nose" ... +BONE "Head" HPR +BONE "Body" H.. +BONE "Tail" HP. +BONE "LeftEar" ..R +BONE "RightEar" ..R +BONE "FrLfShoulder" ... +BONE "FrRtShoulder" ... +BONE "BkLfHip" ... +BONE "BkRtHip" ... +BONE "FrLfLeg" .P. +BONE "FrLfKnee" .P. +BONE "FrLfFoot" HP. +BONE "FrRtLeg" .P. +BONE "FrRtKnee" .P. +BONE "FrRtFoot" HP. +BONE "BkLfLeg" .P. +BONE "BkLfKnee" .P. +BONE "BkLfFoot" .P. +BONE "BkRtLeg" HPR +BONE "BkRtKnee" .P. +BONE "BkRtFoot" .P. +EVENT 0.000000 24 (0,0,0) + (0,0,0) + (0,0,0) + (-8,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,14,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) +EVENT 0.502870 24 (0,0,0) + (0,0,0) + (0,0,0) + (-8,0,0) + (11,-23,0) + (0,0,0) + (-28,-10,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,14,0) + (0,-24,0) + (21,-18,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) +EVENT 1.005740 24 (0,0,0) + (0,0,0) + (0,0,0) + (-8,0,0) + (0,-30,0) + (0,0,0) + (-52,-10,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,14,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) +EVENT 2.005421 24 (0,0,0) + (0,0,0) + (0,0,0) + (-8,0,0) + (51,0,0) + (0,0,0) + (51,-10,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,14,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) +EVENT 3.000000 24 (0,0,0) + (0,0,0) + (0,0,0) + (-8,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,14,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) diff --git a/demos/exposer/data/human.ac b/demos/exposer/data/human.ac new file mode 100644 index 0000000..b53f360 --- /dev/null +++ b/demos/exposer/data/human.ac @@ -0,0 +1,1556 @@ +AC3Db +MATERIAL "ac3dmat1" rgb 1 1 1 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "ac3dmat3" rgb 1 0 0 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "ac3dmat5" rgb 1 1 0 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +OBJECT world +kids 3 +OBJECT poly +name "backOfHead" +loc 0.0024697 1.87326 -0.000320375 +texture "teeshirt_human.rgb" +texrep -1 1 +texoff 0.09 0 +numvert 17 +0.0285838 -0.119611 0.00298071 +0.0463477 -0.119611 -0.0971166 +0.0752035 -0.0501754 -0.112326 +0.0464781 -0.0501754 0.0530327 +-0.0464782 -0.0501754 0.0530327 +-0.0289011 -0.119611 0.00298071 +-0.046665 -0.119611 -0.0971166 +-0.0752035 -0.0501754 -0.112326 +0.0752035 0.0299871 -0.112326 +0.0464781 0.0299871 0.0530327 +-0.0464782 0.0299871 0.0530327 +-0.0752035 0.0299871 -0.112326 +0.0511259 0.0948387 -0.0948688 +0.0287249 0.0948387 0.00732839 +-0.0287252 0.0948387 0.00732839 +-0.051126 0.0948387 -0.0948688 +-1.00816e-07 0.119611 -0.0666221 +numsurf 21 +SURF 0x10 +mat 0 +refs 3 +0 0.506483 0.879793 +1 0.516778 0.879793 +2 0.533502 0.914684 +SURF 0x10 +mat 0 +refs 3 +2 0.533502 0.914684 +3 0.516854 0.914684 +0 0.506483 0.879793 +SURF 0x10 +mat 0 +refs 3 +0 0.506483 0.879793 +3 0.516854 0.914684 +4 0.46298 0.914684 +SURF 0x10 +mat 0 +refs 3 +4 0.46298 0.914684 +5 0.473167 0.879793 +0 0.506483 0.879793 +SURF 0x10 +mat 0 +refs 3 +6 0.462872 0.879793 +5 0.473167 0.879793 +4 0.46298 0.914684 +SURF 0x10 +mat 0 +refs 3 +4 0.46298 0.914684 +7 0.446332 0.914684 +6 0.462872 0.879793 +SURF 0x10 +mat 0 +refs 3 +2 0.533502 0.914684 +8 0.533502 0.954965 +9 0.516854 0.954965 +SURF 0x10 +mat 0 +refs 3 +9 0.516854 0.954965 +3 0.516854 0.914684 +2 0.533502 0.914684 +SURF 0x10 +mat 0 +refs 3 +4 0.46298 0.914684 +3 0.516854 0.914684 +9 0.516854 0.954965 +SURF 0x10 +mat 0 +refs 3 +9 0.516854 0.954965 +10 0.46298 0.954965 +4 0.46298 0.914684 +SURF 0x10 +mat 0 +refs 3 +4 0.46298 0.914684 +10 0.46298 0.954965 +11 0.446332 0.954965 +SURF 0x10 +mat 0 +refs 3 +11 0.446332 0.954965 +7 0.446332 0.914684 +4 0.46298 0.914684 +SURF 0x10 +mat 0 +refs 3 +9 0.516854 0.954965 +8 0.533502 0.954965 +12 0.519547 0.987552 +SURF 0x10 +mat 0 +refs 3 +12 0.519547 0.987552 +13 0.506565 0.987552 +9 0.516854 0.954965 +SURF 0x10 +mat 0 +refs 3 +9 0.516854 0.954965 +13 0.506565 0.987552 +14 0.473269 0.987552 +SURF 0x10 +mat 0 +refs 3 +14 0.473269 0.987552 +10 0.46298 0.954965 +9 0.516854 0.954965 +SURF 0x10 +mat 0 +refs 3 +11 0.446332 0.954965 +10 0.46298 0.954965 +14 0.473269 0.987552 +SURF 0x10 +mat 0 +refs 3 +14 0.473269 0.987552 +15 0.460286 0.987552 +11 0.446332 0.954965 +SURF 0x10 +mat 0 +refs 3 +16 0.489917 1 +13 0.506565 0.987552 +12 0.519547 0.987552 +SURF 0x10 +mat 0 +refs 3 +16 0.489917 1 +14 0.473269 0.987552 +13 0.506565 0.987552 +SURF 0x10 +mat 0 +refs 3 +16 0.489917 1 +15 0.460286 0.987552 +14 0.473269 0.987552 +kids 0 +OBJECT poly +name "cylinder" +loc 0.0198678 0.997829 -0.0567626 +texture "teeshirt_human.rgb" +texrep -1 1 +numvert 137 +0.0289497 0.755816 -0.0406743 +0.0164419 0.71337 0.0566146 +0.0227837 0.710298 -0.0910033 +0.0111858 0.755816 0.0594229 +-0.0383992 0.71337 0.0582384 +-0.0462992 0.755816 0.0594229 +-0.0455715 0.710298 -0.0931686 +-0.064063 0.755816 -0.0406743 +-0.0103786 0.701213 -0.114082 +-0.0175567 0.755816 -0.102538 +-0.0173982 0.845283 -0.15173 +0.0578054 0.825252 -0.0558837 +-0.0926016 0.825252 -0.0558838 +-0.0173982 0.930159 -0.119973 +0.0578054 0.905414 -0.0558837 +-0.0926016 0.905414 -0.0558838 +-0.0173982 0.970266 -0.101588 +0.0337278 0.970266 -0.0384265 +-0.0685241 0.970266 -0.0384265 +-0.0173982 0.995038 -0.0101799 +0.721375 0.599141 -0.0752391 +0.721375 0.678966 -0.0752391 +0.850837 0.701735 -0.0100079 +0.862726 0.596113 -0.0100079 +0.850837 0.701735 0.0523306 +0.862726 0.596113 0.0523306 +0.721375 0.678966 0.00307237 +0.721375 0.599141 0.00307237 +0.428545 0.65929 -0.0775772 +0.428545 0.65929 0.000229806 +0.436648 0.623394 -0.116481 +0.721375 0.638611 -0.0758877 +0.424493 0.5875 -0.0775772 +0.424493 0.5875 0.000229806 +0.436648 0.623394 0.0391333 +0.721375 0.638611 0.00288412 +0.212256 0.704764 -0.0854696 +0.212256 0.704764 0.0133027 +0.199367 0.640677 -0.142779 +0.201946 0.566164 -0.0853052 +0.201946 0.566164 0.0131383 +0.211269 0.676988 0.0792123 +0.187895 -0.420728 0.016965 +0.182152 0.00920123 -0.0531171 +0.18185 0.008591 0.0661881 +0.187895 -0.420728 -0.0714491 +0.195435 0.0043382 -0.12528 +0.131938 -0.431623 -0.115656 +-0.00667014 -0.0552303 -0.153251 +0.0759816 -0.442518 -0.0714491 +-0.0111928 -0.0415102 0.0924745 +0.0759816 -0.442518 0.016965 +0.147871 -0.00582391 0.12347 +0.131938 -0.431623 0.0611721 +0.209488 -0.909576 0.0195732 +0.209488 -0.922156 -0.0674977 +0.174265 -0.922345 -0.0952882 +0.141767 -0.917753 -0.0908897 +0.141767 -0.898883 0.0397166 +0.174265 -0.901966 0.0457666 +-0.00923719 0.701911 0.0839428 +-0.00820317 0.234595 -0.103266 +-0.00949695 0.65369 -0.167939 +0.0831915 0.239069 -0.103388 +0.142893 0.239069 -0.0877754 +0.135309 0.239069 0.0171247 +0.135035 0.239069 -0.0459313 +0.112774 0.239069 0.0506644 +0.083244 0.239069 0.0757644 +0.185319 0.630283 0.0957721 +-0.00949695 0.65369 0.0957721 +-0.00820281 0.234595 0.0753487 +0.0984038 0.0481983 -0.142285 +0.12876 0.0427306 0.160877 +-0.721375 0.599141 0.0324727 +-0.721375 0.678966 0.0324727 +-0.850837 0.701735 -0.0327586 +-0.862726 0.596113 -0.0327586 +-0.850837 0.701735 -0.0950972 +-0.862726 0.596113 -0.0950972 +-0.721375 0.678966 -0.0458388 +-0.721375 0.599141 -0.0458388 +-0.221465 -0.993297 0.0392883 +-0.205063 -0.89973 0.0457203 +-0.221465 -0.951063 -0.234999 +-0.221465 -0.994626 -0.240268 +-0.127518 -0.944565 -0.234999 +-0.127518 -0.988128 -0.240268 +-0.126265 -0.895398 0.0457203 +-0.127518 -0.986799 0.0392883 +-0.428545 0.65929 0.0348106 +-0.428545 0.65929 -0.0429963 +-0.436648 0.623394 0.0737138 +-0.721375 0.638611 0.0331213 +-0.424493 0.5875 0.0348106 +-0.424493 0.5875 -0.0429963 +-0.436648 0.623394 -0.0818998 +-0.721375 0.638611 -0.0456505 +-0.212256 0.704764 0.0427032 +-0.212256 0.704764 -0.0560693 +-0.199367 0.640677 0.100013 +-0.201946 0.566164 0.0425387 +-0.201946 0.566164 -0.0559048 +-0.211269 0.676988 -0.121978 +-0.188669 -0.415884 -0.0597315 +-0.182926 0.0140458 0.0770654 +-0.182624 0.0134358 -0.0422398 +-0.188669 -0.415884 0.0286826 +-0.196209 0.00918311 0.149229 +-0.132712 -0.426778 0.0728899 +-0.0767553 -0.437673 0.0286826 +-0.0767553 -0.437673 -0.0597315 +-0.148645 -0.000979066 -0.0995216 +-0.132712 -0.426778 -0.103939 +-0.210262 -0.915718 -0.0569848 +-0.210262 -0.903138 0.030086 +-0.175039 -0.895527 0.0562793 +-0.142541 -0.892445 0.0502294 +-0.142541 -0.911315 -0.080377 +-0.175039 -0.915907 -0.0847754 +-0.0831915 0.239069 0.0987987 +-0.142893 0.239069 0.0831867 +-0.135309 0.239069 -0.0217138 +-0.135035 0.239069 0.0413422 +-0.112774 0.239069 -0.0552535 +-0.083244 0.239069 -0.0803539 +-0.185319 0.630283 -0.138538 +-0.14526 0.0412554 0.166288 +-0.113906 0.0548714 -0.139786 +0.143549 -0.993709 0.0451747 +0.141884 -0.900248 0.0302683 +0.143549 -0.951475 -0.229112 +0.143549 -0.995038 -0.234381 +0.227687 -0.992871 -0.234381 +0.227687 -0.949309 -0.229112 +0.211284 -0.897099 0.0520636 +0.227687 -0.991543 0.0451747 +numsurf 187 +SURF 0x10 +mat 0 +refs 3 +0 0.516778 0.879793 +1 0.509529 0.858464 +2 0.513205 0.85692 +SURF 0x10 +mat 0 +refs 3 +0 0.516778 0.879793 +3 0.506483 0.879793 +1 0.509529 0.858464 +SURF 0x10 +mat 0 +refs 3 +3 0.506483 0.879793 +4 0.477745 0.858464 +1 0.509529 0.858464 +SURF 0x10 +mat 0 +refs 3 +3 0.506483 0.879793 +5 0.473167 0.879793 +4 0.477745 0.858464 +SURF 0x10 +mat 0 +refs 3 +5 0.473167 0.879793 +6 0.473589 0.85692 +4 0.477745 0.858464 +SURF 0x10 +mat 0 +refs 3 +5 0.473167 0.879793 +7 0.462872 0.879793 +6 0.473589 0.85692 +SURF 0x10 +mat 0 +refs 3 +7 0.462872 0.879793 +8 0.493985 0.852355 +6 0.473589 0.85692 +SURF 0x10 +mat 0 +refs 3 +7 0.462872 0.879793 +9 0.489825 0.879793 +8 0.493985 0.852355 +SURF 0x10 +mat 0 +refs 3 +9 0.489825 0.879793 +2 0.513205 0.85692 +8 0.493985 0.852355 +SURF 0x10 +mat 0 +refs 3 +9 0.489825 0.879793 +0 0.516778 0.879793 +2 0.513205 0.85692 +SURF 0x10 +mat 0 +refs 3 +9 0.489825 0.879793 +10 0.489917 0.924749 +11 0.533502 0.914684 +SURF 0x10 +mat 0 +refs 3 +11 0.533502 0.914684 +0 0.516778 0.879793 +9 0.489825 0.879793 +SURF 0x10 +mat 0 +refs 3 +7 0.462872 0.879793 +12 0.446332 0.914684 +10 0.489917 0.924749 +SURF 0x10 +mat 0 +refs 3 +10 0.489917 0.924749 +9 0.489825 0.879793 +7 0.462872 0.879793 +SURF 0x10 +mat 0 +refs 3 +11 0.533502 0.914684 +10 0.489917 0.924749 +13 0.489917 0.967399 +SURF 0x10 +mat 0 +refs 3 +13 0.489917 0.967399 +14 0.533502 0.954965 +11 0.533502 0.914684 +SURF 0x10 +mat 0 +refs 3 +10 0.489917 0.924749 +12 0.446332 0.914684 +15 0.446332 0.954965 +SURF 0x10 +mat 0 +refs 3 +15 0.446332 0.954965 +13 0.489917 0.967399 +10 0.489917 0.924749 +SURF 0x10 +mat 0 +refs 3 +13 0.489917 0.967399 +16 0.489917 0.987552 +17 0.519547 0.987552 +SURF 0x10 +mat 0 +refs 3 +17 0.519547 0.987552 +14 0.533502 0.954965 +13 0.489917 0.967399 +SURF 0x10 +mat 0 +refs 3 +15 0.446332 0.954965 +18 0.460286 0.987552 +16 0.489917 0.987552 +SURF 0x10 +mat 0 +refs 3 +16 0.489917 0.987552 +13 0.489917 0.967399 +15 0.446332 0.954965 +SURF 0x10 +mat 0 +refs 3 +19 0.489917 1 +17 0.519547 0.987552 +16 0.489917 0.987552 +SURF 0x10 +mat 0 +refs 3 +19 0.489917 1 +16 0.489917 0.987552 +18 0.460286 0.987552 +SURF 0x10 +mat 0 +refs 4 +20 0.918079 0.801065 +21 0.918079 0.841176 +22 0.99311 0.852617 +23 1 0.799543 +SURF 0x10 +mat 0 +refs 4 +24 0.99311 0.852617 +25 1 0.799543 +23 1 0.799543 +22 0.99311 0.852617 +SURF 0x10 +mat 0 +refs 4 +25 1 0.799543 +24 0.99311 0.852617 +26 0.918079 0.841176 +27 0.918079 0.801065 +SURF 0x10 +mat 0 +refs 4 +27 0.918079 0.801065 +26 0.918079 0.841176 +21 0.918079 0.841176 +20 0.918079 0.801065 +SURF 0x10 +mat 0 +refs 4 +21 0.918079 0.841176 +26 0.918079 0.841176 +24 0.99311 0.852617 +22 0.99311 0.852617 +SURF 0x10 +mat 0 +refs 4 +27 0.918079 0.801065 +20 0.918079 0.801065 +23 1 0.799543 +25 1 0.799543 +SURF 0x10 +mat 0 +refs 3 +26 0.918079 0.841176 +28 0.748367 0.831289 +29 0.748367 0.831289 +SURF 0x10 +mat 0 +refs 3 +26 0.918079 0.841176 +21 0.918079 0.841176 +28 0.748367 0.831289 +SURF 0x10 +mat 0 +refs 3 +21 0.918079 0.841176 +30 0.753063 0.813252 +28 0.748367 0.831289 +SURF 0x10 +mat 0 +refs 3 +21 0.918079 0.841176 +31 0.918079 0.820898 +30 0.753063 0.813252 +SURF 0x10 +mat 0 +refs 3 +31 0.918079 0.820898 +32 0.746018 0.795215 +30 0.753063 0.813252 +SURF 0x10 +mat 0 +refs 3 +31 0.918079 0.820898 +20 0.918079 0.801065 +32 0.746018 0.795215 +SURF 0x10 +mat 0 +refs 3 +20 0.918079 0.801065 +33 0.746018 0.795215 +32 0.746018 0.795215 +SURF 0x10 +mat 0 +refs 3 +20 0.918079 0.801065 +27 0.918079 0.801065 +33 0.746018 0.795215 +SURF 0x10 +mat 0 +refs 3 +27 0.918079 0.801065 +34 0.753063 0.813252 +33 0.746018 0.795215 +SURF 0x10 +mat 0 +refs 3 +27 0.918079 0.801065 +35 0.918079 0.820898 +34 0.753063 0.813252 +SURF 0x10 +mat 0 +refs 3 +35 0.918079 0.820898 +29 0.748367 0.831289 +34 0.753063 0.813252 +SURF 0x10 +mat 0 +refs 3 +35 0.918079 0.820898 +26 0.918079 0.841176 +29 0.748367 0.831289 +SURF 0x10 +mat 0 +refs 3 +29 0.748367 0.831289 +36 0.623015 0.85414 +37 0.623015 0.85414 +SURF 0x10 +mat 0 +refs 3 +29 0.748367 0.831289 +28 0.748367 0.831289 +36 0.623015 0.85414 +SURF 0x10 +mat 0 +refs 3 +28 0.748367 0.831289 +38 0.615545 0.821936 +36 0.623015 0.85414 +SURF 0x10 +mat 0 +refs 3 +28 0.748367 0.831289 +30 0.753063 0.813252 +38 0.615545 0.821936 +SURF 0x10 +mat 0 +refs 3 +30 0.753063 0.813252 +39 0.61704 0.784494 +38 0.615545 0.821936 +SURF 0x10 +mat 0 +refs 3 +30 0.753063 0.813252 +32 0.746018 0.795215 +39 0.61704 0.784494 +SURF 0x10 +mat 0 +refs 3 +32 0.746018 0.795215 +40 0.61704 0.784494 +39 0.61704 0.784494 +SURF 0x10 +mat 0 +refs 3 +32 0.746018 0.795215 +33 0.746018 0.795215 +40 0.61704 0.784494 +SURF 0x10 +mat 0 +refs 3 +33 0.746018 0.795215 +41 0.622443 0.840182 +40 0.61704 0.784494 +SURF 0x10 +mat 0 +refs 3 +33 0.746018 0.795215 +34 0.753063 0.813252 +41 0.622443 0.840182 +SURF 0x10 +mat 0 +refs 3 +34 0.753063 0.813252 +37 0.623015 0.85414 +41 0.622443 0.840182 +SURF 0x10 +mat 0 +refs 3 +34 0.753063 0.813252 +29 0.748367 0.831289 +37 0.623015 0.85414 +SURF 0x10 +mat 0 +refs 3 +42 0.608896 0.288587 +43 0.605568 0.504624 +44 0.605393 0.504317 +SURF 0x10 +mat 0 +refs 3 +42 0.608896 0.288587 +45 0.608896 0.288587 +43 0.605568 0.504624 +SURF 0x10 +mat 0 +refs 3 +45 0.608896 0.288587 +46 0.613266 0.50218 +43 0.605568 0.504624 +SURF 0x10 +mat 0 +refs 3 +45 0.608896 0.288587 +47 0.576466 0.283112 +46 0.613266 0.50218 +SURF 0x10 +mat 0 +refs 3 +47 0.576466 0.283112 +48 0.496134 0.472247 +46 0.613266 0.50218 +SURF 0x10 +mat 0 +refs 3 +47 0.576466 0.283112 +49 0.544036 0.277638 +48 0.496134 0.472247 +SURF 0x10 +mat 0 +refs 3 +49 0.544036 0.277638 +50 0.493513 0.479141 +48 0.496134 0.472247 +SURF 0x10 +mat 0 +refs 3 +49 0.544036 0.277638 +51 0.544036 0.277638 +50 0.493513 0.479141 +SURF 0x10 +mat 0 +refs 3 +51 0.544036 0.277638 +52 0.5857 0.497074 +50 0.493513 0.479141 +SURF 0x10 +mat 0 +refs 3 +51 0.544036 0.277638 +53 0.576466 0.283112 +52 0.5857 0.497074 +SURF 0x10 +mat 0 +refs 3 +53 0.576466 0.283112 +44 0.605393 0.504317 +52 0.5857 0.497074 +SURF 0x10 +mat 0 +refs 3 +53 0.576466 0.283112 +42 0.608896 0.288587 +44 0.605393 0.504317 +SURF 0x10 +mat 0 +refs 3 +54 0.621411 0.0429441 +45 0.608896 0.288587 +42 0.608896 0.288587 +SURF 0x10 +mat 0 +refs 3 +54 0.621411 0.0429441 +55 0.621411 0.0366228 +45 0.608896 0.288587 +SURF 0x10 +mat 0 +refs 3 +55 0.621411 0.0366228 +47 0.576466 0.283112 +45 0.608896 0.288587 +SURF 0x10 +mat 0 +refs 3 +55 0.621411 0.0366228 +56 0.600997 0.0365278 +47 0.576466 0.283112 +SURF 0x10 +mat 0 +refs 3 +56 0.600997 0.0365278 +49 0.544036 0.277638 +47 0.576466 0.283112 +SURF 0x10 +mat 0 +refs 3 +56 0.600997 0.0365278 +57 0.582162 0.0388352 +49 0.544036 0.277638 +SURF 0x10 +mat 0 +refs 3 +57 0.582162 0.0388352 +51 0.544036 0.277638 +49 0.544036 0.277638 +SURF 0x10 +mat 0 +refs 3 +57 0.582162 0.0388352 +58 0.582162 0.0483173 +51 0.544036 0.277638 +SURF 0x10 +mat 0 +refs 3 +58 0.582162 0.0483173 +53 0.576466 0.283112 +51 0.544036 0.277638 +SURF 0x10 +mat 0 +refs 3 +58 0.582162 0.0483173 +59 0.600997 0.0467681 +53 0.576466 0.283112 +SURF 0x10 +mat 0 +refs 3 +59 0.600997 0.0467681 +42 0.608896 0.288587 +53 0.576466 0.283112 +SURF 0x10 +mat 0 +refs 3 +59 0.600997 0.0467681 +54 0.621411 0.0429441 +42 0.608896 0.288587 +SURF 0x10 +mat 0 +refs 4 +2 0.513205 0.85692 +1 0.509529 0.858464 +37 0.623015 0.85414 +36 0.623015 0.85414 +SURF 0x10 +mat 0 +refs 4 +60 0.494647 0.852706 +41 0.622443 0.840182 +37 0.623015 0.85414 +1 0.509529 0.858464 +SURF 0x10 +mat 0 +refs 4 +38 0.615545 0.821936 +8 0.493985 0.852355 +2 0.513205 0.85692 +36 0.623015 0.85414 +SURF 0x10 +mat 0 +refs 4 +61 0.495246 0.617883 +62 0.494496 0.828475 +38 0.615545 0.821936 +63 0.548214 0.620131 +SURF 0x10 +mat 0 +refs 3 +8 0.493985 0.852355 +38 0.615545 0.821936 +62 0.494496 0.828475 +SURF 0x10 +mat 0 +refs 3 +38 0.615545 0.821936 +64 0.582815 0.620131 +63 0.548214 0.620131 +SURF 0x10 +mat 0 +refs 4 +40 0.61704 0.784494 +65 0.578419 0.620131 +66 0.578261 0.620131 +39 0.61704 0.784494 +SURF 0x10 +mat 0 +refs 4 +41 0.622443 0.840182 +67 0.565359 0.620131 +65 0.578419 0.620131 +40 0.61704 0.784494 +SURF 0x10 +mat 0 +refs 4 +64 0.582815 0.620131 +38 0.615545 0.821936 +39 0.61704 0.784494 +66 0.578261 0.620131 +SURF 0x10 +mat 0 +refs 4 +68 0.548245 0.620131 +69 0.607403 0.816713 +70 0.494496 0.828475 +71 0.495246 0.617883 +SURF 0x10 +mat 0 +refs 4 +67 0.565359 0.620131 +41 0.622443 0.840182 +69 0.607403 0.816713 +68 0.548245 0.620131 +SURF 0x10 +mat 0 +refs 4 +41 0.622443 0.840182 +60 0.494647 0.852706 +70 0.494496 0.828475 +69 0.607403 0.816713 +SURF 0x10 +mat 0 +refs 4 +48 0.496134 0.472247 +61 0.495246 0.617883 +63 0.548214 0.620131 +72 0.557031 0.524219 +SURF 0x10 +mat 0 +refs 4 +64 0.582815 0.620131 +46 0.613266 0.50218 +72 0.557031 0.524219 +63 0.548214 0.620131 +SURF 0x10 +mat 0 +refs 3 +46 0.613266 0.50218 +48 0.496134 0.472247 +72 0.557031 0.524219 +SURF 0x10 +mat 0 +refs 4 +65 0.578419 0.620131 +44 0.605393 0.504317 +43 0.605568 0.504624 +66 0.578261 0.620131 +SURF 0x10 +mat 0 +refs 4 +67 0.565359 0.620131 +52 0.5857 0.497074 +44 0.605393 0.504317 +65 0.578419 0.620131 +SURF 0x10 +mat 0 +refs 4 +46 0.613266 0.50218 +64 0.582815 0.620131 +66 0.578261 0.620131 +43 0.605568 0.504624 +SURF 0x10 +mat 0 +refs 4 +73 0.574624 0.521472 +68 0.548245 0.620131 +71 0.495246 0.617883 +50 0.493513 0.479141 +SURF 0x10 +mat 0 +refs 4 +52 0.5857 0.497074 +67 0.565359 0.620131 +68 0.548245 0.620131 +73 0.574624 0.521472 +SURF 0x10 +mat 0 +refs 3 +50 0.493513 0.479141 +52 0.5857 0.497074 +73 0.574624 0.521472 +SURF 0x10 +mat 0 +refs 4 +74 0.0819211 0.801065 +75 0.0819211 0.841176 +76 0.00689036 0.852617 +77 0 0.799543 +SURF 0x10 +mat 0 +refs 4 +78 0.00689036 0.852617 +79 0 0.799543 +77 0 0.799543 +76 0.00689036 0.852617 +SURF 0x10 +mat 0 +refs 4 +79 0 0.799543 +78 0.00689036 0.852617 +80 0.0819211 0.841176 +81 0.0819211 0.801065 +SURF 0x10 +mat 0 +refs 4 +81 0.0819211 0.801065 +80 0.0819211 0.841176 +75 0.0819211 0.841176 +74 0.0819211 0.801065 +SURF 0x10 +mat 0 +refs 4 +75 0.0819211 0.841176 +80 0.0819211 0.841176 +78 0.00689036 0.852617 +76 0.00689036 0.852617 +SURF 0x10 +mat 0 +refs 4 +81 0.0819211 0.801065 +74 0.0819211 0.801065 +77 0 0.799543 +79 0 0.799543 +SURF 0x10 +mat 0 +refs 4 +82 0.371648 0.000874867 +83 0.381154 0.0478917 +84 0.371648 0.0220972 +85 0.371648 0.000207051 +SURF 0x10 +mat 0 +refs 4 +86 0.426096 0.0253624 +87 0.426096 0.00347224 +85 0.371648 0.000207051 +84 0.371648 0.0220972 +SURF 0x10 +mat 0 +refs 4 +87 0.426096 0.00347224 +86 0.426096 0.0253624 +88 0.426822 0.0500685 +89 0.426096 0.00414006 +SURF 0x10 +mat 0 +refs 4 +89 0.426096 0.00414006 +88 0.426822 0.0500685 +83 0.381154 0.0478917 +82 0.371648 0.000874867 +SURF 0x10 +mat 0 +refs 4 +83 0.381154 0.0478917 +88 0.426822 0.0500685 +86 0.426096 0.0253624 +84 0.371648 0.0220972 +SURF 0x10 +mat 0 +refs 4 +89 0.426096 0.00414006 +82 0.371648 0.000874867 +85 0.371648 0.000207051 +87 0.426096 0.00347224 +SURF 0x10 +mat 0 +refs 3 +80 0.0819211 0.841176 +90 0.251633 0.831289 +91 0.251633 0.831289 +SURF 0x10 +mat 0 +refs 3 +80 0.0819211 0.841176 +75 0.0819211 0.841176 +90 0.251633 0.831289 +SURF 0x10 +mat 0 +refs 3 +75 0.0819211 0.841176 +92 0.246937 0.813252 +90 0.251633 0.831289 +SURF 0x10 +mat 0 +refs 3 +75 0.0819211 0.841176 +93 0.0819211 0.820898 +92 0.246937 0.813252 +SURF 0x10 +mat 0 +refs 3 +93 0.0819211 0.820898 +94 0.253982 0.795215 +92 0.246937 0.813252 +SURF 0x10 +mat 0 +refs 3 +93 0.0819211 0.820898 +74 0.0819211 0.801065 +94 0.253982 0.795215 +SURF 0x10 +mat 0 +refs 3 +74 0.0819211 0.801065 +95 0.253982 0.795215 +94 0.253982 0.795215 +SURF 0x10 +mat 0 +refs 3 +74 0.0819211 0.801065 +81 0.0819211 0.801065 +95 0.253982 0.795215 +SURF 0x10 +mat 0 +refs 3 +81 0.0819211 0.801065 +96 0.246937 0.813252 +95 0.253982 0.795215 +SURF 0x10 +mat 0 +refs 3 +81 0.0819211 0.801065 +97 0.0819211 0.820898 +96 0.246937 0.813252 +SURF 0x10 +mat 0 +refs 3 +97 0.0819211 0.820898 +91 0.251633 0.831289 +96 0.246937 0.813252 +SURF 0x10 +mat 0 +refs 3 +97 0.0819211 0.820898 +80 0.0819211 0.841176 +91 0.251633 0.831289 +SURF 0x10 +mat 0 +refs 3 +91 0.251633 0.831289 +98 0.376985 0.85414 +99 0.376985 0.85414 +SURF 0x10 +mat 0 +refs 3 +91 0.251633 0.831289 +90 0.251633 0.831289 +98 0.376985 0.85414 +SURF 0x10 +mat 0 +refs 3 +90 0.251633 0.831289 +100 0.384455 0.821936 +98 0.376985 0.85414 +SURF 0x10 +mat 0 +refs 3 +90 0.251633 0.831289 +92 0.246937 0.813252 +100 0.384455 0.821936 +SURF 0x10 +mat 0 +refs 3 +92 0.246937 0.813252 +101 0.382961 0.784494 +100 0.384455 0.821936 +SURF 0x10 +mat 0 +refs 3 +92 0.246937 0.813252 +94 0.253982 0.795215 +101 0.382961 0.784494 +SURF 0x10 +mat 0 +refs 3 +94 0.253982 0.795215 +102 0.382961 0.784494 +101 0.382961 0.784494 +SURF 0x10 +mat 0 +refs 3 +94 0.253982 0.795215 +95 0.253982 0.795215 +102 0.382961 0.784494 +SURF 0x10 +mat 0 +refs 3 +95 0.253982 0.795215 +103 0.377557 0.840182 +102 0.382961 0.784494 +SURF 0x10 +mat 0 +refs 3 +95 0.253982 0.795215 +96 0.246937 0.813252 +103 0.377557 0.840182 +SURF 0x10 +mat 0 +refs 3 +96 0.246937 0.813252 +99 0.376985 0.85414 +103 0.377557 0.840182 +SURF 0x10 +mat 0 +refs 3 +96 0.246937 0.813252 +91 0.251633 0.831289 +99 0.376985 0.85414 +SURF 0x10 +mat 0 +refs 3 +104 0.390655 0.291021 +105 0.393984 0.507058 +106 0.394159 0.506751 +SURF 0x10 +mat 0 +refs 3 +104 0.390655 0.291021 +107 0.390655 0.291021 +105 0.393984 0.507058 +SURF 0x10 +mat 0 +refs 3 +107 0.390655 0.291021 +108 0.386285 0.504614 +105 0.393984 0.507058 +SURF 0x10 +mat 0 +refs 3 +107 0.390655 0.291021 +109 0.423086 0.285547 +108 0.386285 0.504614 +SURF 0x10 +mat 0 +refs 3 +109 0.423086 0.285547 +50 0.493513 0.479141 +108 0.386285 0.504614 +SURF 0x10 +mat 0 +refs 3 +109 0.423086 0.285547 +110 0.455516 0.280072 +50 0.493513 0.479141 +SURF 0x10 +mat 0 +refs 3 +110 0.455516 0.280072 +48 0.496134 0.472247 +50 0.493513 0.479141 +SURF 0x10 +mat 0 +refs 3 +110 0.455516 0.280072 +111 0.455516 0.280072 +48 0.496134 0.472247 +SURF 0x10 +mat 0 +refs 3 +111 0.455516 0.280072 +112 0.413852 0.499508 +48 0.496134 0.472247 +SURF 0x10 +mat 0 +refs 3 +111 0.455516 0.280072 +113 0.423086 0.285547 +112 0.413852 0.499508 +SURF 0x10 +mat 0 +refs 3 +113 0.423086 0.285547 +106 0.394159 0.506751 +112 0.413852 0.499508 +SURF 0x10 +mat 0 +refs 3 +113 0.423086 0.285547 +104 0.390655 0.291021 +106 0.394159 0.506751 +SURF 0x10 +mat 0 +refs 3 +114 0.378141 0.0398578 +107 0.390655 0.291021 +104 0.390655 0.291021 +SURF 0x10 +mat 0 +refs 3 +114 0.378141 0.0398578 +115 0.378141 0.0461792 +107 0.390655 0.291021 +SURF 0x10 +mat 0 +refs 3 +115 0.378141 0.0461792 +109 0.423086 0.285547 +107 0.390655 0.291021 +SURF 0x10 +mat 0 +refs 3 +115 0.378141 0.0461792 +116 0.398555 0.0500036 +109 0.423086 0.285547 +SURF 0x10 +mat 0 +refs 3 +116 0.398555 0.0500036 +110 0.455516 0.280072 +109 0.423086 0.285547 +SURF 0x10 +mat 0 +refs 3 +116 0.398555 0.0500036 +117 0.417389 0.0515523 +110 0.455516 0.280072 +SURF 0x10 +mat 0 +refs 3 +117 0.417389 0.0515523 +111 0.455516 0.280072 +110 0.455516 0.280072 +SURF 0x10 +mat 0 +refs 3 +117 0.417389 0.0515523 +118 0.417389 0.0420703 +111 0.455516 0.280072 +SURF 0x10 +mat 0 +refs 3 +118 0.417389 0.0420703 +113 0.423086 0.285547 +111 0.455516 0.280072 +SURF 0x10 +mat 0 +refs 3 +118 0.417389 0.0420703 +119 0.398555 0.0397628 +113 0.423086 0.285547 +SURF 0x10 +mat 0 +refs 3 +119 0.398555 0.0397628 +104 0.390655 0.291021 +113 0.423086 0.285547 +SURF 0x10 +mat 0 +refs 3 +119 0.398555 0.0397628 +114 0.378141 0.0398578 +104 0.390655 0.291021 +SURF 0x10 +mat 0 +refs 4 +4 0.477745 0.858464 +6 0.473589 0.85692 +99 0.376985 0.85414 +98 0.376985 0.85414 +SURF 0x10 +mat 0 +refs 4 +8 0.493985 0.852355 +103 0.377557 0.840182 +99 0.376985 0.85414 +6 0.473589 0.85692 +SURF 0x10 +mat 0 +refs 4 +100 0.384455 0.821936 +60 0.494647 0.852706 +4 0.477745 0.858464 +98 0.376985 0.85414 +SURF 0x10 +mat 0 +refs 4 +71 0.495246 0.617883 +70 0.494496 0.828475 +100 0.384455 0.821936 +120 0.451786 0.620131 +SURF 0x10 +mat 0 +refs 3 +60 0.494647 0.852706 +100 0.384455 0.821936 +70 0.494496 0.828475 +SURF 0x10 +mat 0 +refs 3 +100 0.384455 0.821936 +121 0.417185 0.620131 +120 0.451786 0.620131 +SURF 0x10 +mat 0 +refs 4 +102 0.382961 0.784494 +122 0.421581 0.620131 +123 0.421739 0.620131 +101 0.382961 0.784494 +SURF 0x10 +mat 0 +refs 4 +103 0.377557 0.840182 +124 0.434641 0.620131 +122 0.421581 0.620131 +102 0.382961 0.784494 +SURF 0x10 +mat 0 +refs 4 +121 0.417185 0.620131 +100 0.384455 0.821936 +101 0.382961 0.784494 +123 0.421739 0.620131 +SURF 0x10 +mat 0 +refs 4 +125 0.451755 0.620131 +126 0.392597 0.816713 +62 0.494496 0.828475 +61 0.495246 0.617883 +SURF 0x10 +mat 0 +refs 4 +124 0.434641 0.620131 +103 0.377557 0.840182 +126 0.392597 0.816713 +125 0.451755 0.620131 +SURF 0x10 +mat 0 +refs 4 +103 0.377557 0.840182 +8 0.493985 0.852355 +62 0.494496 0.828475 +126 0.392597 0.816713 +SURF 0x10 +mat 0 +refs 4 +50 0.493513 0.479141 +71 0.495246 0.617883 +120 0.451786 0.620131 +127 0.415813 0.520731 +SURF 0x10 +mat 0 +refs 4 +121 0.417185 0.620131 +108 0.386285 0.504614 +127 0.415813 0.520731 +120 0.451786 0.620131 +SURF 0x10 +mat 0 +refs 3 +108 0.386285 0.504614 +50 0.493513 0.479141 +127 0.415813 0.520731 +SURF 0x10 +mat 0 +refs 4 +122 0.421581 0.620131 +106 0.394159 0.506751 +105 0.393984 0.507058 +123 0.421739 0.620131 +SURF 0x10 +mat 0 +refs 4 +124 0.434641 0.620131 +112 0.413852 0.499508 +106 0.394159 0.506751 +122 0.421581 0.620131 +SURF 0x10 +mat 0 +refs 4 +108 0.386285 0.504614 +121 0.417185 0.620131 +123 0.421739 0.620131 +105 0.393984 0.507058 +SURF 0x10 +mat 0 +refs 4 +128 0.433985 0.527573 +125 0.451755 0.620131 +61 0.495246 0.617883 +48 0.496134 0.472247 +SURF 0x10 +mat 0 +refs 4 +112 0.413852 0.499508 +124 0.434641 0.620131 +125 0.451755 0.620131 +128 0.433985 0.527573 +SURF 0x10 +mat 0 +refs 3 +48 0.496134 0.472247 +112 0.413852 0.499508 +128 0.433985 0.527573 +SURF 0x10 +mat 0 +refs 4 +129 0.583195 0.000667816 +130 0.58223 0.0476314 +131 0.583195 0.0218901 +132 0.583195 0 +SURF 0x10 +mat 0 +refs 4 +133 0.631958 0.00108893 +134 0.631958 0.0229785 +135 0.622451 0.0492137 +136 0.631958 0.00175623 +SURF 0x10 +mat 0 +refs 4 +136 0.631958 0.00175623 +135 0.622451 0.0492137 +130 0.58223 0.0476314 +129 0.583195 0.000667816 +SURF 0x10 +mat 0 +refs 4 +136 0.631958 0.00175623 +129 0.583195 0.000667816 +132 0.583195 0 +133 0.631958 0.00108893 +SURF 0x10 +mat 0 +refs 4 +134 0.631958 0.0229785 +133 0.631958 0.00108893 +132 0.583195 0 +131 0.583195 0.0218901 +SURF 0x10 +mat 0 +refs 4 +130 0.58223 0.0476314 +135 0.622451 0.0492137 +134 0.631958 0.0229785 +131 0.583195 0.0218901 +SURF 0x10 +mat 0 +refs 3 +1 0.509529 0.858464 +4 0.477745 0.858464 +60 0.494647 0.852706 +kids 0 +OBJECT poly +name "bones" +loc 0.0111648 0.99798 -0.104503 +texture "teeshirt_human.rgb" +texrep -1 1 +numvert 19 +-0.00128026 0.22656 0.0769265 +-0.000640289 0.645104 0.0567337 +0.195822 0.645104 0.0116575 +0.424459 0.631817 0.0116575 +0.721283 0.649533 0.0116575 +0.853658 0.653962 0.0116575 +-0.195822 0.645104 0.0116575 +-0.42446 0.631817 0.0116575 +-0.721284 0.649533 0.0116575 +-0.853658 0.653962 0.0116575 +-0.00274499 0.735167 0.0377699 +-0.00274499 0.978763 0.0377699 +-0.00836541 0.00157213 0.0811241 +-0.154718 -0.404162 0.0760983 +-0.17926 -0.924128 0.0313503 +-0.166858 -0.966894 -0.195497 +0.1631 -0.405691 0.0760983 +0.187642 -0.925658 0.0313499 +0.183449 -0.968423 -0.167834 +numsurf 7 +SURF 0x32 +mat 1 +refs 2 +0 0.49925 0.613698 +1 0.499625 0.828646 +SURF 0x32 +mat 2 +refs 5 +1 0.499625 0.828646 +2 0.614696 0.828646 +3 0.748612 0.821822 +4 0.922466 0.83092 +5 1 0.833195 +SURF 0x32 +mat 2 +refs 5 +1 0.499625 0.828646 +6 0.385304 0.828646 +7 0.251388 0.821822 +8 0.0775334 0.83092 +9 0 0.833195 +SURF 0x32 +mat 2 +refs 3 +1 0.499625 0.828646 +10 0.498392 0.874898 +11 0.498392 1 +SURF 0x32 +mat 2 +refs 2 +0 0.49925 0.613698 +12 0.4951 0.498152 +SURF 0x32 +mat 2 +refs 4 +12 0.4951 0.498152 +13 0.409379 0.289783 +14 0.395005 0.0227482 +15 0.402269 0.000785255 +SURF 0x32 +mat 2 +refs 4 +12 0.4951 0.498152 +16 0.59553 0.288998 +17 0.609905 0.0219625 +18 0.607449 0 +kids 0 diff --git a/demos/exposer/data/human.bones b/demos/exposer/data/human.bones new file mode 100644 index 0000000..aced27c --- /dev/null +++ b/demos/exposer/data/human.bones @@ -0,0 +1,38 @@ +NUMBONES=18 NUMEVENTS=1 MAXTIME=10.000000 Z_OFFSET=-0.002791 SPEED=0.000000 +BONE "Human" HPR +BONE "RtShoulder" HPR +BONE "RtArm" HPR +BONE "RtElbow" HPR +BONE "RtWrist" HPR +BONE "LfShoulder" HPR +BONE "LfArm" HPR +BONE "LfElbow" HPR +BONE "LfWrist" HPR +BONE "Neck" HPR +BONE "Head" HPR +BONE "Waist" HPR +BONE "RtHip" .P. +BONE "RtKnee" .P. +BONE "RtAnkle" .P. +BONE "LfHip" .P. +BONE "LfKnee" .P. +BONE "LfAnkle" .P. +EVENT 0.000000 18 (0.000000,0.000000,0.000000) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) diff --git a/demos/exposer/data/human_die.bones b/demos/exposer/data/human_die.bones new file mode 100644 index 0000000..71837b3 --- /dev/null +++ b/demos/exposer/data/human_die.bones @@ -0,0 +1,133 @@ +NUMBONES=18 NUMEVENTS=6 MAXTIME=1.474031 Z_OFFSET=-0.002791 SPEED=0.000000 +BONE "Human" HPR +BONE "RtShoulder" ... +BONE "RtArm" HPR +BONE "RtElbow" HPR +BONE "RtWrist" HPR +BONE "LfShoulder" ... +BONE "LfArm" HPR +BONE "LfElbow" HPR +BONE "LfWrist" HPR +BONE "Neck" HPR +BONE "Head" HPR +BONE "Waist" HPR +BONE "RtHip" HP. +BONE "RtKnee" .P. +BONE "RtAnkle" .P. +BONE "LfHip" .P. +BONE "LfKnee" .P. +BONE "LfAnkle" .P. +EVENT 0.000000 18 (0.000000,0.000000,0.000000) + (0,0,0) + (0,0,0) + (0,0,71) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,-64) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) +EVENT 0.150392 18 (0.000000,-0.462963,0.000000) + (0,-11,0) + (0,0,0) + (0,38,68) + (31,0,-4) + (0,0,0) + (0,0,0) + (0,32,-52) + (0,-2,-57) + (0,0,0) + (0,0,0) + (0,-34,0) + (0,30,0) + (0,18,0) + (0,0,0) + (0,-21,0) + (0,15,0) + (0,0,0) + (0,-17,0) +EVENT 0.299477 18 (0.000000,-0.648148,-0.462963) + (0,41,0) + (0,0,0) + (0,22,28) + (75,0,-4) + (87,0,-3) + (0,0,0) + (0,71,-32) + (0,22,-15) + (0,0,0) + (0,0,0) + (0,20,0) + (0,10,0) + (0,0,0) + (0,0,0) + (0,-21,0) + (0,4,0) + (0,0,0) + (0,-17,0) +EVENT 0.451177 18 (0.000000,-0.787037,-1.157408) + (0,90,0) + (0,0,0) + (40,-43,22) + (135,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,11,0) + (0,-19,0) + (0,-45,0) + (0,4,0) + (0,0,0) + (0,-17,0) +EVENT 0.681740 18 (0.000000,-0.787037,-1.157408) + (0,90,0) + (0,0,0) + (15,-59,22) + (19,-21,0) + (0,0,0) + (0,0,0) + (0,-42,0) + (0,0,0) + (0,-41,0) + (0,0,0) + (30,-20,0) + (0,0,0) + (0,16,0) + (0,-19,0) + (0,-45,0) + (0,8,0) + (0,-4,0) + (0,-17,0) +EVENT 0.994971 18 (0.000000,-0.787037,-1.157408) + (0,90,0) + (0,0,0) + (15,-59,22) + (19,-21,0) + (0,0,0) + (0,0,0) + (0,-42,0) + (0,0,0) + (0,-41,0) + (0,0,0) + (61,-20,0) + (0,0,0) + (25,0,0) + (0,0,0) + (0,-21,0) + (0,0,0) + (0,0,0) + (0,-12,0) diff --git a/demos/exposer/data/human_walk.bones b/demos/exposer/data/human_walk.bones new file mode 100644 index 0000000..16ec55b --- /dev/null +++ b/demos/exposer/data/human_walk.bones @@ -0,0 +1,171 @@ +NUMBONES=18 NUMEVENTS=8 MAXTIME=1.402956 Z_OFFSET=-0.002791 SPEED=1.400000 +BONE "Human" HPR +BONE "RtShoulder" ... +BONE "RtArm" HPR +BONE "RtElbow" HPR +BONE "RtWrist" HPR +BONE "LfShoulder" ... +BONE "LfArm" HPR +BONE "LfElbow" HPR +BONE "LfWrist" HPR +BONE "Neck" HPR +BONE "Head" HPR +BONE "Waist" HPR +BONE "RtHip" .P. +BONE "RtKnee" .P. +BONE "RtAnkle" .P. +BONE "LfHip" .P. +BONE "LfKnee" .P. +BONE "LfAnkle" .P. +EVENT 0.000000 18 (0.000000,0.000000,0.000000) + (0,0,0) + (0,0,0) + (0,-24,69) + (19,0,0) + (18,0,0) + (0,0,0) + (0,14,-73) + (-21,0,-4) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,-28,0) + (0,0,0) + (0,10,0) + (0,26,0) + (0,-20,0) + (0,0,0) +EVENT 0.195412 18 (0.000000,0.000000,0.000000) + (0,0,0) + (0,0,0) + (0,-11,69) + (19,0,0) + (18,0,0) + (0,0,0) + (0,-11,-73) + (-21,0,-4) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,5,0) + (0,-57,0) + (0,-21,0) + (0,11,0) + (0,0,0) + (0,0,0) +EVENT 0.400845 18 (0.000000,0.000000,0.000000) + (0,0,0) + (0,0,0) + (0,9,69) + (19,0,0) + (18,0,0) + (0,0,0) + (0,-30,-73) + (-21,0,-4) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,29,0) + (0,-60,0) + (0,-4,0) + (0,-4,0) + (0,-9,0) + (0,14,0) +EVENT 0.598762 18 (0.000000,0.000000,0.000000) + (0,0,0) + (0,0,0) + (0,18,69) + (34,-5,0) + (18,0,0) + (0,0,0) + (0,-45,-73) + (-21,0,-4) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,22,0) + (0,0,0) + (0,0,0) + (0,-24,0) + (0,-9,0) + (0,5,0) +EVENT 0.801689 18 (0.000000,0.000000,0.000000) + (0,0,0) + (0,0,0) + (0,9,69) + (23,-5,0) + (21,0,0) + (0,0,0) + (0,-33,-73) + (-21,0,-4) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,10,0) + (0,-9,0) + (0,-45,0) + (0,-16,0) +EVENT 1.004617 18 (0.000000,0.000000,0.000000) + (0,0,0) + (0,0,0) + (0,-8,69) + (23,-5,0) + (21,0,0) + (0,0,0) + (0,-23,-73) + (-21,0,-4) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,-16,0) + (0,0,0) + (0,25,0) + (0,38,0) + (0,-53,0) + (0,18,0) +EVENT 1.200028 18 (0.000000,0.000000,0.000000) + (0,0,0) + (0,0,0) + (0,-12,69) + (0,5,0) + (15,0,0) + (0,0,0) + (0,0,-73) + (-21,0,-4) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,-23,0) + (0,0,0) + (0,9,0) + (0,20,0) + (0,0,0) + (0,-8,0) +EVENT 1.402956 18 (0.000000,0.000000,0.000000) + (0,0,0) + (0,0,0) + (0,-24,69) + (19,0,0) + (18,0,0) + (0,0,0) + (0,15,-73) + (-21,0,-4) + (0,0,0) + (0,0,0) + (0,0,0) + (0,0,0) + (0,-28,0) + (0,0,0) + (0,10,0) + (0,26,0) + (0,-19,0) + (0,0,0) diff --git a/demos/exposer/data/teeshirt_human.rgb b/demos/exposer/data/teeshirt_human.rgb new file mode 100644 index 0000000..998ea4f Binary files /dev/null and b/demos/exposer/data/teeshirt_human.rgb differ diff --git a/demos/exposer/doc/Makefile.am b/demos/exposer/doc/Makefile.am new file mode 100644 index 0000000..b307f82 --- /dev/null +++ b/demos/exposer/doc/Makefile.am @@ -0,0 +1,7 @@ + +pkgdatadir = $(datadir)/games/@PACKAGE@/doc + +pkgdata_DATA = $(wildcard *.*) + +EXTRA_DIST = $(pkgdata_DATA) + diff --git a/demos/exposer/doc/bone.png b/demos/exposer/doc/bone.png new file mode 100644 index 0000000..127d7d4 Binary files /dev/null and b/demos/exposer/doc/bone.png differ diff --git a/demos/exposer/doc/exposer.png b/demos/exposer/doc/exposer.png new file mode 100644 index 0000000..5cc1f26 Binary files /dev/null and b/demos/exposer/doc/exposer.png differ diff --git a/demos/exposer/doc/exposer_logo.png b/demos/exposer/doc/exposer_logo.png new file mode 100644 index 0000000..71258fd Binary files /dev/null and b/demos/exposer/doc/exposer_logo.png differ diff --git a/demos/exposer/doc/index.html b/demos/exposer/doc/index.html new file mode 100644 index 0000000..4233d66 --- /dev/null +++ b/demos/exposer/doc/index.html @@ -0,0 +1,451 @@ + + + + + Exposer Home Page + + + + + + + + + +
+Exposer Logo +
+
+
+

+ EXPOSER: + A + TOOL FOR + ANIMATING + PLIB + CRITTERS. +

+
+
+
    + The foot bone's connected to the leg bone,
    + The leg bone's connected to the knee bone,
    + The knee bone's connected to the thigh bone,
    + The thigh bone's connected to the back bone,
    + The back bone's connected to the neck bone,
    + The neck bone's connected to the head bone,
    + Oh, hear the word of the Lord!
    +
    +-- Unknown (but incompetent) anatomist. +
+
+ +Sourceforge Logo +
+
+ +

Introduction.

+Exposer is a tool to allow you to perform fairly complex animations +of complex creatures with relative ease using the + PLIB Scene Graph API. Naturally, +Exposer is written using PLIB and generates output in several forms +that PLIB programs will find useful. +

+Exposer is totally unrelated to the Windows program 'poser'. The +name 'exposer' relates to the fact that this program used to be +called 'poser' until I heard of the existance of a Windows program +of the same name. This is therefore the ex-Poser program. +

+Exposer has a complex (but very powerful) GUI - you WILL need to +read this manual in order to take advantage of it. +

Licensing.

+Exposer is OpenSource software, issued under the terms of the +GNU Public License (GPL). +

Installing and Running Exposer

+Download ExPoser from the PLIB site: + +http://plib.sf.net/dist/exposer-0.0.1.tar.gz +

+Next, unpack the tarball containing the Exposer sources: +

+
+   tar xzvf exposer-0.0.1.tar.gz
+
+
+Then run the usual: +
+
+   ./configure ; make
+
+
+(And you can optionally run 'make install' if you wish to fully +install the program rather than running it out of the installation +directory). +

+Then to run the program (without installing it) you could type +something like: +

+
+  src/exposer
+
+
+The program will prompt you to enter a 3D model file - the +ones in data with the extension '.ac' will do for starters. +

+Exposer can read any format that the PLIB library supports +that can contain both line and polygon objects. + +

So What Does It Do.

+Well, right now, not a lot. The idea is that you can take an +arbitary polygonal model (typically of a person or animal of +some kind) and with minimal additional modelling effort be able +to animate it in your game or other interactive application. +

+The technique that exposer uses is 'skin and bones' animation +where the polygons of the model form the creatures 'skin' and +you model a set of line primitives inside the creature to make +a crude skeleton (the 'bones') much like the armature that a +sculptor would use. +

+Exposer therefore separates out the polygons and the lines in the +model you load (because your game will only be using the polygons) +and uses the lines to form a hierarchical structure of matrix +transformations. Exposer then assigns each vertex in the +skin to one of the bones (possibly more than one in the future) +according to distance - and then moves each vertex in accordance +with the matrix of the bone to which it's attached. +

+Exposer can optionally display each bone as a coloured cuboid and +provides a Heading/Pitch/Roll dial for each of them - but typically, +you'll only want to view the 'skin' - and that's the default. +By playing +with the coloured dials, you can move the bones in any way you like and +the skin will try to follow that movement as smoothly as possible. +

+One important issue is how the lines are assembled into a bone +heirarchy. Firstly, exactly ONE of the lines in the original +model must be painted RED. This bone is special because it's +the root of the bone hierarchy. Typically, this will be a +bone in the spine of a human or other mammal - but you might +choose it to be something else. You can "Make the Tail Wag +the Dog" by making the tailbone be the red one! +

+Once the program has found that red 'root' bone, it looks +for other lines that have one or other of their vertices +touching the root bone. Other lines can connect to the +root somewhere other than at the ends of that red line, +but your non-root bones MUST connect to it at their ends. +

+The program allows a 1% tolerance on this positioning so +bones don't have to be EXACTLY touching - but they do have +to be VERY close. +

+So, now we have the root bone and some other bones connected +to it - and now the program proceeds to expand out the +skeleton by treating all of the newly connected bones as +'root' and proceeding recursively from there. +

+In a sense, it's like reading the lines of the song at +the top of this page backwards: +

+   The back bone's...the RED bone,
+   The thigh bone's connected to the back bone,
+   The knee bone's connected to the thigh bone,
+   The leg bone's connected to the knee bone,
+   The foot bone's connected to the leg bone
+
+...although if it were me, I'd want a pelvis-bone and for +the sake of graphics, there wouldn't need to be a knee bone. +

+So, that's more or less it. + +

Controls.

+Having loaded your first model, you'll see something like this: +
+
ExPoser screenshot
+
+The rather nice shade of green is my favorite colour. If +you prefer shock-pink...bad luck - that's what source code +is for! The 3D model sits in the middle of the screen with +the GUI widgets floating in front of it. +

+There is an optional black and white chequerboard 'floor'. +

+Let's go through the GUI controls piece by piece: + +

The Menu Bar.

+In the top-left, there is a pretty standard menu bar, +
+
Menu Bar
+
+The 'File' menu allows you to replace the model you are +working on with another, it also allows you to load +and save 'bone' files - which contain everything you +create in Exposer. Generally, these Bone files have +the same filename as the 3D model but with the extension +".bones". Exposer will fill that filename into the +file selector box - so you probably only have to hit "OK" +to load and save. +

+The 'View' menu lets you zoom into and out of the 'timeline' +which we'll come to later. The 'Time' menu has other +'timeline' operations. + +

The Bone Dials

+To the left of the window are the bone dials - each coloured +row of GUI widgets represents one of the bones in your model. +
+
Bone Dials
+
+The button marked 'X' resets all of the angles of the bone +to zero - which will always be how your model was posed when +you created it. The 'H', 'P' and 'R' buttons let you freeze +and hide any of the three dials that you don't want to use +for that particular bone. This is useful for joints like +your elbow that can only flex in one degree of freedom. +

+The three dials represent the heading, pitch and roll +angles of the joint at the end of that bone nearest the +top of the bone connection hierarchy. +

+The rectangular area above the 'X/H/P/R' buttons can +be used to enter a short text string to identify the +bone. These strings are saved when you write out the +bone data and your application program might want to +read them to help identify what's what. +

+If you have more bones than will conveniently fit on the +screen, the scroll-bar to the left of the bone widgets +will allow you to scroll them up and down. + +

The Body Translators

+Just below the meny bar, there are three sliders with +text display/entry areas that allow you to bodily +translate your model. +
+
Body Translators
+
+You should generally use this +for things like adding 'bounce' to a character's walk +sequence - it's not advisable to try to position your +character within it's world using this feature. + +

View Control

+In the bottom-left corner of the screen are some +view controls. These can be used anytime to change +the view you have of the model - but they don't change +any actual data in the model or it's bones. +
+
View Controls
+
+You can also use the 'Zoom' slider to move the model +closer or further away, and there are buttons marked +'Skin', 'Bones' and 'Floor' that let you toggle the display of +each of those things - so you can see just the skin, +just the bones or both (Or neither if you are +particularly perverse!) - with or without the floor +plane. The initial default is to show just the skin. +

+The 'Pan' and 'Tilt' dials allow you to move your +eyepoint around the model to view it from all sides +as it animates. + +

VCR Controls

+In the bottom-right corner of the screen, there +are some VCR-like controls to play the animation, +pause it, play in reverse and to play at triple-speed +in forward or reverse. +
+
VCR Controls
+
+You cannot adjust any joint angles in the model when +the animation is playing - so be sure to press the +downward arrow (STOP!) when you want to do editing. +

+There is a control to make the ground translate +along at a specified speed (in OpenGL-units-per-second). +This is useful if (for example) you want to animate +a running character that's you'll be moving at two +meters per second in your game. You need to move +the legs so that the feet move along at the same +speed as the ground or else it'll look like +'moonwalking'. Set the VCR's ground speed to match +the speed in the game and you'll be able to see if +the animation is going to work. + +

The TimeLine

+This is a large rectangle taking up most of the bottom +edge of the screen: +
+
TimeLine
+
+It has a number of functions, it starts up as a view +of a 10 second animation. Seconds are indicated by +the long tickmarks, tenth seconds by the short ones. +You can zoom into or out of the view or reset to seeing +the entire timeline using the 'View' menu in the menubar. +

+If you are zoomed into the timeline, a slider will appear +to allow you to scroll it left and right. +

+Magenta lines that extend across the full height of +the timeline indicate "events" - each event is a point +in time at which you have set the bone joint angles. +You can add an event by selecting 'Add an Event' in +the 'Time' menu and then clicking somewhere onto the +timeline to position it. One they are positioned, you +can click and drag events up and down the timeline to +change when they happen. +

+To change an event, click on it and it'll flash to +indicate that you have it selected. Then you can +adjust it using the bone dials. A common problem +is to try to edit a position without selecting it +first - make sure that the event is flashing on +the timeline. +

+Various operations on the 'selected' event are +available from the 'Time' menu. +

+You can also select a 'region' by left-clicking +on one end and right-clicking on the other. The +current region is highlighted in yellow. There +are operations that operate on the current region +in the 'Time' menu. +

+Wherever you click the left button on the timeline, +the model will move to that position - and the bone +dials will follow. You can drag the mouse up and +down the timeline to replay the animation at whatever +speed you move the mouse. However, to get a 'realistic' +playback speed, use the single arrows on the VCR +menu. +

+Remember though that you can only EDIT the position +of the model on a selected event. + +

Menu Operations on the Timeline.

+The 'Time' menu allows you to add an event, +delete the selected event, delete ALL the events +in the 'region' that you have highlighted, +or delete the section of time in the 'region' - +compressing up the rest of the timeline to fit. +Finally, you can add more time to the timeline +so that you can create animations that are longer +than the ten seconds initially provided. + +

The Exposer ".bones" file format.

+This is a very simple ASCII text file - however +the parser for it is VERY crude at this stage. +

+The first line of the file is: +

+
+  NUMBONES=17 NUMEVENTS=7 MAXTIME=10.0000 Z_OFFSET=1.3 SPEED=0.3
+
+
+So there are 17 bones, 7 events - and the +duration of the animation is ten seconds. +

+The Z_OFFSET is advice to the application about the +height of the origin of the model above the lowest +point on the model in it's default pose. +

+SPEED is the speed set on the VCR 'Ground Speed' +control - which the application can use to tell +at what speed the character should move forwards +in order to make the animation look right. +

+Then follows the bones - one per line: +

+
+  BONE "bone-name" HPR
+
+
+The 'bone-name' is the string you entered beside the +bone dials. The 'HPR' part sets which axes are frozen. +(in this case, none of them...the frozen axis letters +are replaced by dots). +

+After all the bones come the events. For each event +there is a header line: +

+
+  EVENT 3.0000 17 (0.000,0.000,0.000)
+
+
+The first number is the time (in seconds) at which the +event occurred, the second number is the number of bones +that are affected by this event. Currently this must be +the same as 'NUMBONES'. The coordinate in parentheses is +the body-translation of the model from the origin at this +moment in time. +

+After the event header, there is one line per bone +containing the three joint angles in degrees for +that bone at that time: +

+
+  (90,45,37)
+
+
+That's it! However, as I said - the parser is 'brittle' +and very intolerant of errors - edit the file at your +own peril! + +

Support Programs.

+ +In the ExPoser directory, you'll also find a short +program called 'merge_bones' - this takes a number +of '.bones' files (listed in order on the command line) +and concatenates them end-to-end - placing the results +in the file 'out.bones'. +

+On stdout, it lists the header from each of the component +files. It is (of course) necessary that the '.bones' +files originated from the same 3D model - merge_bones +checks that things are consistant and warns of errors. + + +

Some Advice

+Bones don't necessarily have to be placed where the +bones would be in an anatomically correct version of +the critter. In the example 'dog.ac' file, there is +a tongue-bone and two ear-bones - and there are no ribs, +spinal vertibrae, etc. +

+You'll also probably need to hop back and forth between +your modeller and exposer to position the bones how you +want them. You'll find on occasions that the algorithm +that causes exposer to attach a skin vertex to the nearest +bone will sometimes result in part of a character's stomach +being attached to their hand or something. If that happens +then you might try adding some lateral bones +in the stomach to ensure that there is always one attached +to the spine that's closer to the skin than the hand is. +

+Artists should be encouraged to model the character in +a position with their legs wide apart and their arms +fully outstretched to minimise this kind of problem. +

+It is normal to model the character facing down the +positive Y axis - facing away from the camera. +

+Using the axis freeze buttons to isolate only those +axes through which a real joint can rotate is very +useful. A human elbow joint can really only +rotate through one axis and turning off the other two is +helpful. +

+You can also use Exposer for things other than animals. +You could model plants bending in a heavy wind - or +even flexible things like flags or clothing. + +


+
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+ + diff --git a/demos/exposer/doc/menu.png b/demos/exposer/doc/menu.png new file mode 100644 index 0000000..ef104ee Binary files /dev/null and b/demos/exposer/doc/menu.png differ diff --git a/demos/exposer/doc/timeline.png b/demos/exposer/doc/timeline.png new file mode 100644 index 0000000..9ecf7cc Binary files /dev/null and b/demos/exposer/doc/timeline.png differ diff --git a/demos/exposer/doc/translate.png b/demos/exposer/doc/translate.png new file mode 100644 index 0000000..3940beb Binary files /dev/null and b/demos/exposer/doc/translate.png differ diff --git a/demos/exposer/doc/vcr.png b/demos/exposer/doc/vcr.png new file mode 100644 index 0000000..ed330ad Binary files /dev/null and b/demos/exposer/doc/vcr.png differ diff --git a/demos/exposer/doc/viewer.png b/demos/exposer/doc/viewer.png new file mode 100644 index 0000000..0e1a2e4 Binary files /dev/null and b/demos/exposer/doc/viewer.png differ diff --git a/demos/exposer/exposer.dsw b/demos/exposer/exposer.dsw new file mode 100644 index 0000000..3a90ff9 --- /dev/null +++ b/demos/exposer/exposer.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "exposer"=.\src\exposer.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/demos/exposer/src/Makefile.am b/demos/exposer/src/Makefile.am new file mode 100644 index 0000000..83e9ec2 --- /dev/null +++ b/demos/exposer/src/Makefile.am @@ -0,0 +1,22 @@ +# src/ + +bindir=$(prefix)/games + +bin_PROGRAMS = exposer merge_tweens + +exposer_SOURCES = \ + exposer.cxx exposer.h \ + floor.cxx floor.h \ + vertices.cxx vertices.h \ + boneGUI.cxx boneGUI.h \ + load_save.cxx load_save.h \ + timebox.cxx timebox.h \ + bones.cxx bones.h \ + event.cxx event.h \ + model.cxx model.h + +merge_tweens_SOURCES = \ + merge_tweens.cxx merge_tweens.h + +EXTRA_DIST = exposer.dsp + diff --git a/demos/exposer/src/boneGUI.cxx b/demos/exposer/src/boneGUI.cxx new file mode 100644 index 0000000..ae784f6 --- /dev/null +++ b/demos/exposer/src/boneGUI.cxx @@ -0,0 +1,305 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: boneGUI.cxx 2100 2006-11-03 22:31:54Z fayjf $ +*/ + + +#include "exposer.h" + +static puSlider *XtranslateSlider ; +static puSlider *YtranslateSlider ; +static puSlider *ZtranslateSlider ; +static puInput *XtranslateInput ; +static puInput *YtranslateInput ; +static puInput *ZtranslateInput ; + + +static void jointHeadingCB ( puObject *ob ) +{ + Bone *bone = (Bone *) (ob->getUserData()) ; + float a ; ob -> getValue ( & a ) ; + + bone->setAngle ( 0, a * 360.0f - 180.0f ) ; + setShowAngle ( a * 360.0f - 180.0f ) ; +} + + +static void jointPitchCB ( puObject *ob ) +{ + Bone *bone = (Bone *) (ob->getUserData()) ; + float a ; ob -> getValue ( & a ) ; + + bone->setAngle ( 1, a * 360.0f - 180.0f ) ; + setShowAngle ( a * 360.0f - 180.0f ) ; +} + + +static void jointRollCB ( puObject *ob ) +{ + Bone *bone = (Bone *) (ob->getUserData()) ; + float a ; ob -> getValue ( & a ) ; + + bone->setAngle ( 2, a * 360.0f - 180.0f ) ; + setShowAngle ( a * 360.0f - 180.0f ) ; +} + + +void hide_headingCB ( puObject *ob ) +{ + Bone *bone = (Bone *) (ob->getUserData()) ; + + if ( ob -> getValue () ) + bone -> sh -> hide () ; + else + bone -> sh -> reveal () ; +} + + +void hide_pitchCB ( puObject *ob ) +{ + Bone *bone = (Bone *) (ob->getUserData()) ; + + if ( ob -> getValue () ) + bone -> sp -> hide () ; + else + bone -> sp -> reveal () ; +} + +void hide_rollCB ( puObject *ob ) +{ + Bone *bone = (Bone *) (ob->getUserData()) ; + + if ( ob -> getValue () ) + bone -> sr -> hide () ; + else + bone -> sr -> reveal () ; +} + + +static void resetCB ( puObject *ob ) +{ + Bone *bone = (Bone *) (ob->getUserData()) ; + + bone -> setAngles ( 0, 0, 0 ) ; +} + + +void syncTranslators ( sgVec3 trans ) +{ + XtranslateSlider -> setValue ( trans [ 0 ] / 5.0f + 0.5f ) ; + YtranslateSlider -> setValue ( trans [ 1 ] / 5.0f + 0.5f ) ; + ZtranslateSlider -> setValue ( trans [ 2 ] / 5.0f + 0.5f ) ; + + if ( ! XtranslateInput -> isAcceptingInput () ) + XtranslateInput -> setValue ( trans [ 0 ] ) ; + if ( ! YtranslateInput -> isAcceptingInput () ) + YtranslateInput -> setValue ( trans [ 1 ] ) ; + if ( ! ZtranslateInput -> isAcceptingInput () ) + ZtranslateInput -> setValue ( trans [ 2 ] ) ; + +} + + +static void currTranslateTxtXCB ( puObject *sl ) +{ + float v = sl -> getFloatValue () ; + + if ( eventList->getCurrentEvent() == NULL ) return ; + + sgVec3 xyz ; + + eventList->getCurrentEvent() -> getTranslate ( xyz ) ; + xyz [ 0 ] = v ; + eventList->getCurrentEvent() -> setTranslate ( xyz ) ; + + syncTranslators ( xyz ) ; +} + + + +static void currTranslateTxtYCB ( puObject *sl ) +{ + float v = sl -> getFloatValue () ; + + if ( eventList->getCurrentEvent() == NULL ) return ; + + sgVec3 xyz ; + + eventList->getCurrentEvent() -> getTranslate ( xyz ) ; + xyz [ 1 ] = v ; + eventList->getCurrentEvent() -> setTranslate ( xyz ) ; + + syncTranslators ( xyz ) ; +} + + + +static void currTranslateTxtZCB ( puObject *sl ) +{ + float v = sl -> getFloatValue () ; + + if ( eventList->getCurrentEvent() == NULL ) return ; + + sgVec3 xyz ; + + eventList->getCurrentEvent() -> getTranslate ( xyz ) ; + xyz [ 2 ] = v ; + eventList->getCurrentEvent() -> setTranslate ( xyz ) ; + + syncTranslators ( xyz ) ; +} + + + + +static void currTranslateXCB ( puObject *sl ) +{ + float v = (((puSlider *)sl) -> getFloatValue () - 0.5f ) * 5.0f ; + + if ( eventList->getCurrentEvent() == NULL ) return ; + + sgVec3 xyz ; + + eventList->getCurrentEvent() -> getTranslate ( xyz ) ; + xyz [ 0 ] = v ; + eventList->getCurrentEvent() -> setTranslate ( xyz ) ; + + syncTranslators ( xyz ) ; +} + + + +static void currTranslateYCB ( puObject *sl ) +{ + float v = (((puSlider *)sl) -> getFloatValue () - 0.5f ) * 5.0f ; + + if ( eventList->getCurrentEvent() == NULL ) return ; + + sgVec3 xyz ; + + eventList->getCurrentEvent() -> getTranslate ( xyz ) ; + xyz [ 1 ] = v ; + eventList->getCurrentEvent() -> setTranslate ( xyz ) ; + + syncTranslators ( xyz ) ; +} + + + +static void currTranslateZCB ( puObject *sl ) +{ + float v = (((puSlider *)sl) -> getFloatValue () - 0.5f ) * 5.0f ; + + if ( eventList->getCurrentEvent() == NULL ) return ; + + sgVec3 xyz ; + + eventList->getCurrentEvent() -> getTranslate ( xyz ) ; + xyz [ 2 ] = v ; + eventList->getCurrentEvent() -> setTranslate ( xyz ) ; + + syncTranslators ( xyz ) ; +} + + +void initBoneGUI () +{ + puText *message ; + + ZtranslateInput = new puInput ( 5, 485, 80, 505 ) ; + ZtranslateInput -> setCallback ( currTranslateTxtZCB ) ; + + ZtranslateSlider = new puSlider ( 80, 485, 120, FALSE ) ; + ZtranslateSlider -> setCBMode ( PUSLIDER_DELTA ) ; + ZtranslateSlider -> setDelta ( 0.01f ) ; + ZtranslateSlider -> setCallback ( currTranslateZCB ) ; + message = new puText ( 205,485 ) ; message->setLabel ( "Z" ) ; + + YtranslateInput = new puInput ( 5, 505, 80, 525 ) ; + YtranslateInput -> setCallback ( currTranslateTxtYCB ) ; + + YtranslateSlider = new puSlider ( 80, 505, 120, FALSE ) ; + YtranslateSlider -> setCBMode ( PUSLIDER_DELTA ) ; + YtranslateSlider -> setDelta ( 0.01f ) ; + YtranslateSlider -> setCallback ( currTranslateYCB ) ; + message = new puText ( 205,505 ) ; message->setLabel ( "Y" ) ; + + XtranslateInput = new puInput ( 5, 525, 80, 545 ) ; + XtranslateInput -> setCallback ( currTranslateTxtXCB ) ; + + XtranslateSlider = new puSlider ( 80, 525, 120, FALSE ) ; + XtranslateSlider -> setCBMode ( PUSLIDER_DELTA ) ; + XtranslateSlider -> setDelta ( 0.01f ) ; + XtranslateSlider -> setCallback ( currTranslateXCB ) ; + message = new puText ( 205,525 ) ; message->setLabel ( "X" ) ; +} + + +void Bone::createJoint () +{ + widget = new puGroup ( 0, 0 ) ; + rs = new puOneShot ( 0, 0, "x" ) ; + hb = new puButton (20, 0, "H" ) ; + pb = new puButton (40, 0, "P" ) ; + rb = new puButton (60, 0, "R" ) ; + sh = new puDial ( 80, 0, 40 ) ; + sp = new puDial ( 120, 0, 40 ) ; + sr = new puDial ( 160, 0, 40 ) ; + na = new puInput ( 0,20,80,40 ) ; + + na->setUserData ( this ) ; + na->setColourScheme ( colour[0], colour[1], colour[2], 0.5f ) ; + + rs->setUserData ( this ) ; + rs->setCallback ( resetCB ) ; + rs->setColourScheme ( colour[0], colour[1], colour[2], 0.5f ) ; + + hb->setUserData ( this ) ; + hb->setCallback ( hide_headingCB ) ; + hb->setColourScheme ( colour[0], colour[1], colour[2], 0.5f ) ; + + pb->setUserData ( this ) ; + pb->setCallback ( hide_pitchCB ) ; + pb->setColourScheme ( colour[0], colour[1], colour[2], 0.5f ) ; + + rb->setUserData ( this ) ; + rb->setCallback ( hide_rollCB ) ; + rb->setColourScheme ( colour[0], colour[1], colour[2], 0.5f ) ; + + sh->setUserData ( this ) ; + sh->setValue ( 0.5f ) ; + sh->setCallback ( jointHeadingCB ) ; + sh->setColourScheme ( colour[0], colour[1], colour[2], 0.5f ) ; + + sp->setUserData ( this ) ; + sp->setValue ( 0.5f ) ; + sp->setCallback ( jointPitchCB ) ; + sp->setColourScheme ( colour[0], colour[1], colour[2], 0.5f ) ; + + sr->setUserData ( this ) ; + sr->setValue ( 0.5f ) ; + sr->setCallback ( jointRollCB ) ; + sr->setColourScheme ( colour[0], colour[1], colour[2], 0.5f ) ; + + widget -> close () ; + widget -> hide () ; +} + diff --git a/demos/exposer/src/boneGUI.h b/demos/exposer/src/boneGUI.h new file mode 100644 index 0000000..2763718 --- /dev/null +++ b/demos/exposer/src/boneGUI.h @@ -0,0 +1,32 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: boneGUI.h 1425 2002-08-17 23:58:38Z ude $ +*/ + + +void hide_headingCB ( puObject *ob ) ; +void hide_pitchCB ( puObject *ob ) ; +void hide_rollCB ( puObject *ob ) ; + +void syncTranslators ( sgVec3 trans ) ; +void initBoneGUI () ; + + diff --git a/demos/exposer/src/bones.cxx b/demos/exposer/src/bones.cxx new file mode 100644 index 0000000..dc56724 --- /dev/null +++ b/demos/exposer/src/bones.cxx @@ -0,0 +1,278 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: bones.cxx 2100 2006-11-03 22:31:54Z fayjf $ +*/ + + +#include "exposer.h" + +static sgVec3 curr_translate = { 0.0f, 0.0f, 0.0f } ; + +static ssgSimpleState *boneState = NULL ; +static Bone *bone = NULL ; + +ssgSimpleState *getBoneState () { return boneState ; } +float *getCurrTranslate () { return curr_translate ; } +Bone *getBone ( int i ) { return & ( bone [ i ] ) ; } + + +void init_bones () +{ + if ( bone == NULL ) + bone = new Bone [ 1000 ] ; + + sgZeroVec3 ( curr_translate ) ; +} + + +Bone::Bone () +{ + parent = -1 ; +} + + +void Bone::read ( FILE *fd ) +{ + char name [ PUSTRING_MAX ] ; + char shb, spb, srb ; + + fscanf ( fd, "BONE \"%s %c%c%c\n", + name, & shb, & spb, & srb ) ; + + if ( name[strlen(name)-1] == '\"' ) + name[strlen(name)-1] = '\0' ; + + na -> setValue ( name ) ; + hb -> setValue ( (shb == 'H') ? 0 : 1 ) ; + pb -> setValue ( (spb == 'P') ? 0 : 1 ) ; + rb -> setValue ( (srb == 'R') ? 0 : 1 ) ; + + hide_headingCB ( hb ) ; + hide_pitchCB ( pb ) ; + hide_rollCB ( rb ) ; +} + + +void Bone::write ( FILE *fd ) +{ + fprintf ( fd, "BONE \"%s\" %c%c%c\n", + na->getStringValue(), + hb->getValue() ? '.' : 'H', + pb->getValue() ? '.' : 'P', + rb->getValue() ? '.' : 'R' ) ; +} + + +void Bone::setAngles ( float h, float p, float r ) +{ + sgVec3 hpr ; + sgSetVec3 ( hpr, h, p, r ) ; + setAngles ( hpr ) ; +} + + +void Bone::setAngle ( int which, float a ) +{ + getXForm() -> hpr [ which ] = a ; + setAngles ( getXForm() -> hpr ) ; +} + + +void Bone::setAngles ( sgVec3 src ) +{ + sgCopyVec3 ( getXForm() -> hpr, src ) ; +} + + +float *Bone::getDialAngles () +{ + static sgVec3 dst ; + dst[0] = sh -> getFloatValue () * 360.0f - 180.0f ; + dst[1] = sp -> getFloatValue () * 360.0f - 180.0f ; + dst[2] = sr -> getFloatValue () * 360.0f - 180.0f ; + return dst ; +} + + +sgCoord *Bone::getXForm ( Event *prev, Event *next, float lerptime ) +{ + static sgCoord c ; + + sgCoord *coord0 = prev->getBoneCoord ( id ) ; + sgCoord *coord1 = next->getBoneCoord ( id ) ; + + sgCopyVec3 ( c.xyz, xlate ) ; + + sgLerpAnglesVec3 ( c.hpr, coord0->hpr, coord1->hpr, lerptime ) ; + + sh -> setValue ( (c.hpr[0] + 180.0f) / 360.0f ) ; + sp -> setValue ( (c.hpr[1] + 180.0f) / 360.0f ) ; + sr -> setValue ( (c.hpr[2] + 180.0f) / 360.0f ) ; + + return & c ; +} + + +sgCoord *Bone::getXForm () +{ + if ( eventList->getCurrentEvent() != NULL ) + { + sgCoord *coord = eventList->getCurrentEvent()->getBoneCoord ( id ) ; + sgCopyVec3 ( coord->xyz, xlate ) ; + return coord ; + } + + static sgCoord coord ; + sgZeroCoord ( & coord ) ; + sgCopyVec3 ( coord.xyz, xlate ) ; + return &coord ; +} + + +void Bone::computeTransform ( Event *prev, Event *next, float t ) +{ + effector -> setTransform ( getXForm( prev, next, t ) ) ; +} + + +void Bone::transform ( sgVec3 dst, sgVec3 src ) +{ + sgXformPnt3 ( dst, src, netMatrix ) ; + sgAddVec3 ( dst, curr_translate ) ; +} + + +void Bone::swapEnds() +{ + sgVec3 tmp ; + + /* Swap vertices so that vx0 is always the root. */ + + sgCopyVec3 ( tmp, vx[0] ) ; + sgCopyVec3 ( vx[0], vx[1] ) ; + sgCopyVec3 ( vx[1], tmp ) ; + + sgCopyVec3 ( tmp, orig_vx[0] ) ; + sgCopyVec3 ( orig_vx[0], orig_vx[1] ) ; + sgCopyVec3 ( orig_vx[1], tmp ) ; +} + + +void Bone::init ( ssgLeaf *l, sgMat4 newmat, short vv[2], int ident ) +{ + parent = -1 ; + sgCopyVec3 ( vx [ 0 ], l -> getVertex ( vv[0] ) ) ; + sgCopyVec3 ( vx [ 1 ], l -> getVertex ( vv[1] ) ) ; + sgXformPnt3 ( vx [ 0 ], newmat ) ; + sgXformPnt3 ( vx [ 1 ], newmat ) ; + + sgCopyVec3 ( orig_vx [ 0 ], vx [ 0 ] ) ; + sgCopyVec3 ( orig_vx [ 1 ], vx [ 1 ] ) ; + + id = ident ; + if ( sgEqualVec3 ( vx [ 0 ], vx [ 1 ] ) ) + fprintf ( stderr, "exposer: Zero length bone found.\n" ) ; +} + + +void Bone::print ( FILE *fd, int which ) +{ + fprintf ( fd, "Bone %d: vx (%f,%f,%f) -> (%f,%f,%f) Parent = %d\n", + which, + vx[0][0],vx[0][1],vx[0][2], + vx[1][0],vx[1][1],vx[1][2], + parent ) ; +} + + +#define NUM_COLOURS 13 + +static sgVec4 colourTable [] = +{ + { 1, 0, 0, 0.3f }, { 0, 1, 0, 0.3f }, { 0, 0, 1, 0.3f }, + { 1, 1, 0, 0.3f }, { 1, 0, 1, 0.3f }, { 0, 1, 1, 0.3f }, + + { 0.5f, 0.5f, 0.5f, 0.3f }, + + { 1, 0.5f, 0.5f, 0.3f }, { 0.5f, 1 , 0.5f, 0.3f }, { 0.5f, 0.5f, 1, 0.3f }, + { 1, 1 , 0.5f, 0.3f }, { 1 , 0.5f, 1 , 0.3f }, { 0.5f, 1, 1, 0.3f } +} ; + + +ssgBranch *Bone::generateGeometry ( int root ) +{ + static int nextColIndex = 0 ; + + ssgTransform *b = new ssgTransform ; + + b -> setUserData ( this ) ; + effector = b ; + sgZeroVec3 ( getXForm()->hpr ) ; + sgCopyVec3 ( xlate, vx[0] ) ; + sgZeroVec3 ( vx[0] ) ; + sgSubVec3 ( vx[1], xlate ) ; + + sgMat4 mat ; + sgMakeCoordMat4 ( mat, getXForm() ) ; + b -> setTransform ( mat ) ; + + offsetChildBones ( root, xlate ) ; + + sgCopyVec4 ( colour, colourTable[nextColIndex] ) ; + + createJoint () ; + + ssgaCube *shape = new ssgaCube () ; + sgVec3 org ; sgCopyVec3 ( org, vx[1] ) ; + sgVec3 siz ; sgCopyVec3 ( siz, vx[1] ) ; + + sgScaleVec3 ( org, 0.5 ) ; + + siz[0] = (float)fabs ( siz[0] ) ; if ( siz[0] <= 0.1f ) siz [ 0 ] = 0.1f ; + siz[1] = (float)fabs ( siz[1] ) ; if ( siz[1] <= 0.1f ) siz [ 1 ] = 0.1f ; + siz[2] = (float)fabs ( siz[2] ) ; if ( siz[2] <= 0.1f ) siz [ 2 ] = 0.1f ; + + if ( boneState == NULL ) + { + boneState = new ssgSimpleState () ; + boneState -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + boneState -> setMaterial ( GL_SPECULAR, 0, 0, 0, 1 ) ; + boneState -> setMaterial ( GL_EMISSION, 0, 0, 0, 1 ) ; + boneState -> enable ( GL_BLEND ) ; + } + + shape -> setCenter ( org ) ; + shape -> setSize ( siz ) ; + shape -> setColour ( colourTable[nextColIndex] ) ; + shape -> setKidState ( boneState ) ; + + nextColIndex = ( nextColIndex + 1 ) % NUM_COLOURS ; + + b -> addKid ( shape ) ; + + for ( int i = 0 ; i < getNumBones() ; i++ ) + if ( i != root && getBone(i)->parent == root ) + b -> addKid ( getBone(i)->generateGeometry ( i ) ) ; + + return b ; +} + + diff --git a/demos/exposer/src/bones.h b/demos/exposer/src/bones.h new file mode 100644 index 0000000..f3b294f --- /dev/null +++ b/demos/exposer/src/bones.h @@ -0,0 +1,84 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: bones.h 1425 2002-08-17 23:58:38Z ude $ +*/ + + +#define ROOT_BONE 9999 + +class Bone : public ssgBase +{ +public: + int id ; + int parent ; + ssgTransform *effector ; + + sgVec3 xlate ; + sgMat4 netMatrix ; + + sgVec3 vx [ 2 ] ; /* Relative to joint */ + sgVec3 orig_vx [ 2 ] ; /* Absolute */ + + puGroup *widget ; + puOneShot *rs ; + puButton *hb ; + puButton *pb ; + puButton *rb ; + puDial *sh ; + puDial *sp ; + puDial *sr ; + puInput *na ; + sgVec4 colour ; + Bone () ; + + void read ( FILE *fd ) ; + void write ( FILE *fd ) ; + void createJoint () ; + + void computeTransform ( Event *prev, Event *next, float tim ) ; + + void setAngle ( int which, float a ) ; + void setAngles ( float h, float p, float r ) ; + void setAngles ( sgVec3 a ) ; + + float *getXYZ () { return xlate ; } + + float *getDialAngles () ; + + sgCoord *getXForm ( Event *prev, Event *next, float tim ) ; + sgCoord *getXForm () ; + + void transform ( sgVec3 dst, sgVec3 src ) ; + void swapEnds() ; + void init ( ssgLeaf *l, sgMat4 newmat, short vv[2], int id ) ; + void print ( FILE *fd, int which ) ; + ssgBranch *generateGeometry ( int root ) ; +} ; + + +void init_bones () ; +void setShowAngle ( float a ) ; + +float *getCurrTranslate () ; +Bone *getBone ( int i ) ; + +ssgSimpleState *getBoneState () ; + diff --git a/demos/exposer/src/event.cxx b/demos/exposer/src/event.cxx new file mode 100644 index 0000000..6be7b1e --- /dev/null +++ b/demos/exposer/src/event.cxx @@ -0,0 +1,300 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: event.cxx 2100 2006-11-03 22:31:54Z fayjf $ +*/ + + +#include "exposer.h" + + +void EventList::read ( int nevents, FILE *fd ) +{ + for ( int i = 0 ; i < nevents ; i++ ) + { + Event *e = new Event ( getNumBones(), (float) i ) ; + e -> read ( fd ) ; + addEvent ( e ) ; + } +} + + +void EventList::write ( FILE *fd ) +{ + for ( int i = 0 ; i < getNumEvents () ; i++ ) + getEvent ( i ) -> write ( fd ) ; +} + + +void EventList::moveEvent ( Event *e, float new_time ) +{ + removeEvent ( e ) ; + e -> setTime ( new_time ) ; + addEvent ( e ) ; +} + + +void EventList::newEvent ( float t ) +{ + if ( getNumBones () <= 0 ) + return ; + + setCurrentEvent ( new Event ( getNumBones (), t ) ) ; + addEvent ( getCurrentEvent () ) ; +} + + +void EventList::deleteEvent ( Event *e ) +{ + if ( e == NULL ) + return ; + + if ( e == curr_event ) + curr_event = NULL ; + + removeEvent ( e ) ; + delete e ; +} + + +void EventList::compressEventsBetween ( float t1, float t2 ) +{ + deleteEventsBetween ( t1, t2 ) ; + + for ( int i = 0 ; i < getNumEvents() ; i++ ) + { + Event *ev = getEvent ( i ) ; + + float t = ev -> getTime () ; + + if ( t > t1 || t > t2 ) + ev -> setTime ( t - (float)fabs(t1-t2) ) ; + } +} + + +int EventList::getNumEventsBetween ( float t1, float t2 ) +{ + int nevents = 0 ; + + for ( int i = 0 ; i < getNumEvents() ; i++ ) + { + float t = getEvent ( i ) -> getTime () ; + + if ( ( t1 < t2 && t >= t1 && t <= t2 ) || + ( t2 < t1 && t >= t2 && t <= t1 ) ) + nevents++ ; + } + + return nevents ; +} + + +int EventList::getEventsBetween ( float t1, float t2, Event ***elist ) +{ + int nevents = getNumEventsBetween ( t1, t2 ) ; + + if ( nevents == 0 ) + { + elist = NULL ; + return 0 ; + } + + /* Make a list of the events */ + + *elist = new Event* [ nevents ] ; + + nevents = 0 ; + + for ( int i = 0 ; i < getNumEvents() ; i++ ) + { + Event *ev = getEvent ( i ) ; + float t = ev -> getTime () ; + + if ( ( t1 < t2 && t >= t1 && t <= t2 ) || + ( t2 < t1 && t >= t2 && t <= t1 ) ) + (*elist) [ nevents++ ] = ev ; + } + + return nevents ; +} + + +void EventList::deleteEventsBetween ( float t1, float t2 ) +{ + int found_one = FALSE ; + + do + { + found_one = FALSE ; + + for ( int i = 0 ; i < getNumEvents() && ! found_one ; i++ ) + { + Event *ev = getEvent ( i ) ; + + float t = ev -> getTime () ; + + if ( ( t1 < t2 && t >= t1 && t <= t2 ) || + ( t2 < t1 && t >= t2 && t <= t1 ) ) + { + deleteEvent ( ev ) ; + found_one = TRUE ; + } + } + + } while ( found_one ) ; +} + + +void EventList::reverseEventsBetween ( float t1, float t2 ) +{ + /* Make a list of the events */ + + Event **elist ; + int nevents = getEventsBetween ( t1, t2, &elist ) ; + + if ( nevents == 0 ) + return ; + + /* Reverse their order */ + + for ( int i = 0 ; i < nevents ; i++ ) + { + Event *ev = elist [ i ] ; + + removeEvent ( ev ) ; + + float t = ev -> getTime () ; + + if ( t1 > t2 ) + t = t1 - ( t - t2 ) ; + else + t = t2 - ( t - t1 ) ; + + ev -> setTime ( t ) ; + + addEvent ( ev ) ; + } + + delete [] elist ; +} + + +void EventList::addEvent ( Event *e ) +{ + /* + Keep list in time-increasing order. + */ + + for ( int i = 0 ; i < getNumEvents() ; i++ ) + if ( e -> getTime() < getEvent(i)->getTime() ) + { + addEntityBefore ( i, e ) ; + return ; + } + + addEntity ( e ) ; +} + + + +Event *EventList::findNearestEvent ( float t, float tolerance ) +{ + int nearest = -1 ; + float min = FLT_MAX ; + + for ( int i = 0 ; i < getNumEvents() ; i++ ) + { + float t2 = getEvent(i)->getTime() ; + float diff = (float) fabs ( t - t2 ) ; + + if ( diff < min ) + { + min = diff ; + nearest = i ; + } + } + + return ( nearest >= 0 && min < tolerance ) ? getEvent ( nearest ) : NULL ; +} + + +void EventList::deleteAll () +{ + while ( getNumEvents() > 0 ) + deleteEvent ( getEvent ( 0 ) ) ; +} + + +EventList::EventList () +{ + curr_event = NULL ; +} + + + +Event::Event ( int n, float t ) +{ + time = t ; + nbones = n ; + bone_angles = new sgCoord [ n ] ; + + sgCopyVec3 ( translate, getCurrTranslate() ) ; + + for ( int i = 0 ; i < n ; i++ ) + { + sgCopyVec3 ( bone_angles [ i ] . hpr, getBone(i)->getDialAngles() ) ; + sgCopyVec3 ( bone_angles [ i ] . xyz, getBone(i)->getXYZ() ) ; + } +} + + +void Event::read ( FILE *fd ) +{ + fscanf ( fd, "EVENT %f %d (%f,%f,%f)\n", &time, &nbones, + &translate[0], &translate[1], &translate[2] ) ; + + for ( int i = 0 ; i < nbones ; i++ ) + { + int ssh, ssp, ssr ; + + fscanf ( fd, " (%d,%d,%d)\n", & ssh, & ssp, & ssr ) ; + + sgSetVec3 ( bone_angles [ i ] . hpr, (float)ssh, (float)ssp, (float)ssr ) ; + sgCopyVec3 ( bone_angles [ i ] . xyz, getBone(i)->getXYZ() ) ; + } +} + + +void Event::write ( FILE *fd ) +{ + fprintf ( fd, "EVENT %f %d (%f,%f,%f)\n", time, nbones, + translate[0], translate[1], translate[2] ) ; + + for ( int i = 0 ; i < nbones ; i++ ) + { + fprintf ( fd, " (%d,%d,%d)\n", + (int) bone_angles [ i ] . hpr[0], + (int) bone_angles [ i ] . hpr[1], + (int) bone_angles [ i ] . hpr[2] ) ; + } +} + + diff --git a/demos/exposer/src/event.h b/demos/exposer/src/event.h new file mode 100644 index 0000000..c444c64 --- /dev/null +++ b/demos/exposer/src/event.h @@ -0,0 +1,102 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: event.h 1425 2002-08-17 23:58:38Z ude $ +*/ + + +class Event +{ + float time ; + int nbones ; + sgCoord *bone_angles ; + sgVec3 translate ; + +public: + + Event ( int n, float t ) ; + ~Event () { delete [] bone_angles ; } + + void read ( FILE *fd ) ; + void write ( FILE *fd ) ; + + void setTranslate ( sgVec3 tra ) { sgCopyVec3 ( translate, tra ) ; } + void getTranslate ( sgVec3 tra ) { sgCopyVec3 ( tra, translate ) ; } + + void setBoneAngles ( int n, sgVec3 angles ) + { + if ( n < nbones ) + sgCopyVec3 ( bone_angles[n].hpr, angles ) ; + } + + void getBoneAngles ( int n, sgVec3 angles ) + { + if ( n < nbones ) + sgCopyVec3 ( angles, bone_angles[n].hpr ) ; + else + sgZeroVec3 ( angles ) ; + } + + sgCoord *getBoneCoord ( int n ) { return & ( bone_angles [ n ] ) ; } + + void setTime ( float t ) { time = t ; } + float getTime () { return time ; } +} ; + + + + + +class EventList : public ulList +{ + Event *curr_event ; + +public: + + EventList () ; + + int getNumEvents () { return getNumEntities () ; } + + void addEvent ( Event *e ) ; + void newEvent ( float t ) ; + Event *findNearestEvent ( float t, float tolerance ) ; + + void moveEvent ( Event *e, float new_time ) ; + void removeEvent ( Event *e ) { removeEntity ( e ) ; } + void setCurrentEvent ( Event *ev ) { curr_event = ev ; } + Event *getEvent ( int i ) { return (Event *) getEntity ( i ) ; } + void deleteEvent ( Event *e ) ; + void deleteAll () ; + + Event *getCurrentEvent () { return curr_event ; } + void deleteCurrentEvent() { deleteEvent ( curr_event ) ; } + + int getNumEventsBetween ( float t1, float t2 ) ; + int getEventsBetween ( float t1, float t2, Event ***elist ) ; + void reverseEventsBetween ( float t1, float t2 ) ; + void deleteEventsBetween ( float t1, float t2 ) ; + void compressEventsBetween( float t1, float t2 ) ; + + void write ( FILE *fd ) ; + void read ( int nevents, FILE *fd ) ; +} ; + + + diff --git a/demos/exposer/src/exposer.cxx b/demos/exposer/src/exposer.cxx new file mode 100644 index 0000000..7707666 --- /dev/null +++ b/demos/exposer/src/exposer.cxx @@ -0,0 +1,480 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: exposer.cxx 2100 2006-11-03 22:31:54Z fayjf $ +*/ + + +#include "exposer.h" + +static int curr_button = 0 ; +static int scroll_controllers = 0 ; + +EventList * eventList = NULL ; +TimeBox * timebox = NULL ; +Floor * ground = NULL ; +ssgRoot * skinScene = NULL ; +ssgRoot *tweenScene = NULL ; +ssgRoot * boneScene = NULL ; +ssgRoot *sceneScene = NULL ; + +static puText *message ; +static puButton *hideBones ; +static puButton *hideSkin ; +static puButton *hideGround ; +static puButton *hideScene ; +static puSlider *scroller ; +static puMenuBar *menuBar ; + +static puSlider *rangeSlider ; +static puDial * panSlider ; +static puDial * tiltSlider ; + +static puInput *show_angle ; + +static void save_60th_CB ( puObject * ) { setTweenInterval ( 1.0f/60.0f ) ; } +static void save_30th_CB ( puObject * ) { setTweenInterval ( 1.0f/30.0f ) ; } +static void save_20th_CB ( puObject * ) { setTweenInterval ( 1.0f/20.0f ) ; } +static void save_15th_CB ( puObject * ) { setTweenInterval ( 1.0f/15.0f ) ; } +static void save_10th_CB ( puObject * ) { setTweenInterval ( 1.0f/10.0f ) ; } +static void save_8th_CB ( puObject * ) { setTweenInterval ( 1.0f/ 8.0f ) ; } +static void save_4th_CB ( puObject * ) { setTweenInterval ( 1.0f/ 4.0f ) ; } +static void save_2th_CB ( puObject * ) { setTweenInterval ( 1.0f/ 2.0f ) ; } +static void save_1th_CB ( puObject * ) { setTweenInterval ( 1.0f ) ; } + +void setShowAngle ( float a ) +{ + show_angle -> setValue ( a ) ; + show_angle -> rejectInput () ; +} + + +static void update_eye_motion () +{ + float r ; rangeSlider -> getValue ( & r ) ; r *= 100.0f ; r += 2.0f ; + float h ; panSlider -> getValue ( & h ) ; h *= 360.0f ; h += 180.0f ; + float p ; tiltSlider -> getValue ( & p ) ; p *= 360.0f ; p += 180.0f ; + + sgMat4 mat ; + sgVec3 vec ; + + sgMakeCoordMat4 ( mat, 0, 0, 0, h, p, 0 ) ; + sgSetVec3 ( vec, 0, r * 20, 0 ) ; + sgXformPnt3 ( vec, mat ) ; + sgNegateVec3 ( vec ) ; + sgCopyVec3 ( mat[3], vec ) ; + ssgSetCamera ( mat ) ; + transformModel ( boneScene, timebox->getCursorTime () ) ; +} + + +static void reshape ( int w, int h ) +{ + glViewport ( 0, 0, w, h ) ; + ssgSetFOV ( 60.0f, 60.0f * (float) h / (float) w ) ; +} + + + +static void specialfn ( int key, int, int ) +{ + puKeyboard ( key + PU_KEY_GLUT_SPECIAL_OFFSET, PU_DOWN ) ; +} + + +static void keyfn ( unsigned char key, int, int ) +{ + puKeyboard ( key, PU_DOWN ) ; +} + + +static void passmotionfn ( int x, int y ) +{ + puMouse ( x, y ) ; +} + + +static void motionfn ( int x, int y ) +{ + puMouse ( x, y ) ; + timebox->updateEventQueue ( curr_button, x, y, FALSE ) ; +} + + +static void mousefn ( int button, int updown, int x, int y ) +{ + puMouse ( button, updown, x, y ) ; + + curr_button = button ; + timebox->updateEventQueue ( curr_button, x, y, updown == PU_DOWN ) ; +} + + +static void scrollerCB ( puObject *ob ) +{ + scroll_controllers = (int)(((float)getNumBones()) * ob -> getFloatValue ()) ; +} + + + +static void exitCB ( puObject *ob ) +{ + if ( ob -> getValue () ) + exit ( 1 ) ; +} + + + +/* + CALLBACK FUNCTIONS FOR GUI. +*/ + +static void deleteEventCB ( puObject * ) { timebox -> deleteEvent () ; } +static void addNewEventCB ( puObject * ) { timebox -> addNewEvent () ; } +static void reverseRegionCB ( puObject * ) { timebox -> reverseRegion () ; } +// static void deleteAllCB ( puObject * ) { timebox -> deleteAll () ; } +static void deleteRegionCB ( puObject * ) { timebox -> deleteRegion () ; } +static void deleteRegionAndCompressCB ( puObject * ) + { timebox -> deleteRegionAndCompress () ; } + +static void zoom_nrm_CB ( puObject * ) { timebox -> setZoom ( 1.0f ) ; } +static void zoom_in_CB ( puObject * ) { timebox -> setZoom ( + timebox -> getZoom () * 1.5f ) ; } +static void zoom_out_CB ( puObject * ) { float scale = timebox->getZoom() / 1.5f ; + timebox -> setZoom ( ( scale <= 1.0f ) ? 1.0f : scale ) ; } + +static void add_1_CB ( puObject * ) {timebox->setMaxTime(timebox->getMaxTime()+1.0f);} +static void add_2_CB ( puObject * ) {timebox->setMaxTime(timebox->getMaxTime()+2.0f);} +static void add_5_CB ( puObject * ) {timebox->setMaxTime(timebox->getMaxTime()+5.0f);} + +static void opaqueBones () +{ + if ( getBoneState() != NULL ) + getBoneState() -> disable ( GL_BLEND ) ; +} + + +static void blendBones () +{ + if ( getBoneState() != NULL ) + getBoneState() -> enable ( GL_BLEND ) ; +} + + +/* GLUT callbacks */ + +static void redraw () +{ + int i ; + + timebox->updateVCR () ; + + update_eye_motion () ; + + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + glEnable ( GL_DEPTH_TEST ) ; + + if ( ! hideScene -> getValue () && sceneScene != NULL ) + ssgCullAndDraw ( sceneScene ) ; + + if ( ! hideGround -> getValue () ) + ground -> draw () ; + + if ( ! hideSkin -> getValue () ) + { + ssgCullAndDraw ( skinScene ) ; + blendBones () ; + } + else + opaqueBones () ; + + if ( ! hideBones -> getValue () ) + { + glClear ( GL_DEPTH_BUFFER_BIT ) ; + ssgCullAndDraw ( boneScene ) ; + } + + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; + glAlphaFunc ( GL_GREATER, 0.1f ) ; + glEnable ( GL_BLEND ) ; + glDisable ( GL_DEPTH_TEST ) ; + + for ( i = 0 ; i < getNumBones() ; i++ ) + getBone ( i ) -> widget -> hide () ; + + for ( i = 0 ; i < 10 && i+scroll_controllers < getNumBones() ; i++ ) + { + getBone ( i + scroll_controllers ) -> widget -> setPosition ( 24, 70+i*40); + + if ( eventList -> getCurrentEvent() == NULL ) + { + getBone ( i + scroll_controllers ) -> widget -> reveal () ; + getBone ( i + scroll_controllers ) -> widget -> greyOut () ; + } + else + { + getBone ( i + scroll_controllers ) -> widget -> reveal () ; + getBone ( i + scroll_controllers ) -> widget -> activate () ; + } + } + + puDisplay () ; + + timebox -> draw () ; + + glutPostRedisplay () ; + glutSwapBuffers () ; +} + + +/* Menu bar entries: */ + +static char *file_submenu [] = { "Exit", + "------------", + "Save Tweened Model As...", + "Save Bones As...", + "Load Bones", + "Load Scenery", + "Load Model", + NULL } ; + +static puCallback file_submenu_cb [] = { exitCB, + NULL, + twsaveCB, + bnsaveCB, + bnloadCB, + scloadCB, + loadCB, + NULL } ; + +static char *view_submenu [] = { "Zoom Timeline In", + "Zoom Timeline Out", + "Zoom Timeline 1:1", + NULL } ; + +static puCallback view_submenu_cb [] = { zoom_in_CB, + zoom_out_CB, + zoom_nrm_CB, + NULL } ; + +static char *pref_submenu [] = { "1/60th second", + "1/30th second", + "1/20th second", + "1/15th second", + "1/10th second", + "eighth second", + "quarter second", + "half second", + "second", + "Save a tween bank every...", + NULL } ; + +static puCallback pref_submenu_cb [] = { save_60th_CB, + save_30th_CB, + save_20th_CB, + save_15th_CB, + save_10th_CB, + save_8th_CB, + save_4th_CB, + save_2th_CB, + save_1th_CB, + NULL, + NULL } ; + +static char *time_submenu [] = { "Add 5 seconds", + "Add 2 seconds", + "Add 1 second", + "------------", + "Reverse region", + "Delete region & compress", + "Delete region", + "Delete selected event", + "Add new event", + NULL } ; + +static puCallback time_submenu_cb [] = { add_5_CB, + add_2_CB, + add_1_CB, + NULL, + reverseRegionCB, + deleteRegionAndCompressCB, + deleteRegionCB, + deleteEventCB, + addNewEventCB, + NULL } ; + + +static void init_graphics () +{ + int fake_argc = 1 ; + char *fake_argv[3] ; + + fake_argv[0] = "ExPoser" ; + fake_argv[1] = "ExPoser - Skin and Bones animation for PLIB." ; + fake_argv[2] = NULL ; + + /* Initialise GLUT */ + + glutInitWindowPosition ( 0, 0 ) ; + glutInitWindowSize ( 800, 600 ) ; + glutInit ( &fake_argc, fake_argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + glutCreateWindow ( fake_argv[1] ) ; + glutDisplayFunc ( redraw ) ; + glutReshapeFunc ( reshape ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; + glutPassiveMotionFunc ( passmotionfn ) ; + + /* Initialise SSG & PUI */ + + ssgInit () ; + puInit () ; + puSetDefaultStyle ( PUSTYLE_SMALL_SHADED ) ; + puSetDefaultFonts ( PUFONT_HELVETICA_10, PUFONT_HELVETICA_10 ) ; + + /* Some basic OpenGL setup */ + + glClearColor ( 0.2f, 0.5f, 0.2f, 1.0f ) ; + ssgSetFOV ( 60.0f, 0.0f ) ; + ssgSetNearFar ( 0.1f, 700.0f ) ; + + /* Set up the Sun. */ + + sgVec3 sunposn ; + sgSetVec3 ( sunposn, 0.2f, 0.5f, 0.5f ) ; + ssgGetLight ( 0 ) -> setPosition ( sunposn ) ; + + /* GUI setup. */ + + timebox = new TimeBox ( eventList ) ; + ground = new Floor () ; + + menuBar = new puMenuBar () ; + { + menuBar -> add_submenu ( "File", file_submenu, file_submenu_cb ) ; + menuBar -> add_submenu ( "View", view_submenu, view_submenu_cb ) ; + menuBar -> add_submenu ( "Time", time_submenu, time_submenu_cb ) ; + menuBar -> add_submenu ( "SavePrefs", pref_submenu, pref_submenu_cb ) ; + } + menuBar -> close () ; + + show_angle = new puInput ( 5, 560, 80, 580 ) ; + show_angle -> setValue ( "" ) ; + show_angle -> rejectInput () ; + message = new puText ( 80, 560 ) ; + message -> setLabel ( "Angle" ) ; + + scroller = new puSlider ( 5, 70, 400, TRUE ) ; + scroller -> setCBMode ( PUSLIDER_DELTA ) ; + scroller -> setDelta ( 0.01f ) ; + scroller -> setCallback ( scrollerCB ) ; + + panSlider = new puDial ( 0, 0, 40 ) ; + panSlider -> setCBMode ( PUSLIDER_DELTA ) ; + panSlider -> setDelta ( 0.01f ) ; + panSlider -> setValue ( 0.5f ) ; + message = new puText ( 0, 40 ) ; + message -> setColour ( PUCOL_LABEL, 0.7f,0.65f,0.26f,1 ) ; + message -> setLabel ( "Pan" ) ; + + tiltSlider = new puDial ( 40, 0, 40 ) ; + tiltSlider -> setCBMode ( PUSLIDER_DELTA ) ; + tiltSlider -> setDelta ( 0.01f ) ; + tiltSlider -> setValue ( 0.5f ) ; + message = new puText ( 40, 40 ) ; + message -> setColour ( PUCOL_LABEL, 0.7f,0.65f,0.26f,1 ) ; + message -> setLabel ( "Tilt" ) ; + + hideBones = new puButton ( 80, 0, "Bones" ) ; + hideBones -> setValue ( TRUE ) ; + hideSkin = new puButton ( 119, 0, "Skin" ) ; + hideSkin -> setValue ( FALSE ) ; + hideGround = new puButton ( 149, 0, "Floor" ) ; + hideGround -> setValue ( FALSE ) ; + hideScene = new puButton ( 183, 0, "Scene" ) ; + hideScene -> setValue ( FALSE ) ; + + rangeSlider = new puSlider ( 80, 20, 141, FALSE ) ; + rangeSlider -> setCBMode ( PUSLIDER_DELTA ) ; + rangeSlider -> setDelta ( 0.01f ) ; + message = new puText ( 80, 40 ) ; + message -> setColour ( PUCOL_LABEL, 0.7f,0.65f,0.26f,1 ) ; + message -> setLabel ( "Zoom" ) ; +} + + +static void init_database () +{ + skinScene = new ssgRoot ; + boneScene = new ssgRoot ; +} + + +static void help () +{ + fprintf ( stderr, "\n" ) ; + fprintf ( stderr, "exposer: Interactive Usage -\n" ) ; + fprintf ( stderr, " exposer\n\n" ) ; + fprintf ( stderr, " ...or...\n\n" ) ; + fprintf ( stderr, "exposer: Batch Tweenfile generation Usage -\n" ) ; + fprintf ( stderr, " exposer -f framerate modelfile bonefile tweenfile\n" ); + fprintf ( stderr, "\n" ) ; +} + + +int main ( int argc, char **argv ) +{ + eventList = new EventList ; + + init_graphics () ; + init_database () ; + init_bones () ; + initBoneGUI () ; + + /* Interactive? */ + + if ( argc <= 1 ) + { + loadCB ( NULL ) ; + + glutPostRedisplay () ; + glutMainLoop () ; + return 0 ; + } + + if ( argc != 6 || strcmp ( argv [ 1 ], "-f" ) != 0 || + atof ( argv [ 2 ] ) > 100.0f || atof ( argv[2] ) < 0.1f ) + { + help () ; + return 1 ; + } + + setTweenInterval ( 1.0f / (float)atof ( argv [ 2 ] ) ) ; + loadFile ( argv [ 3 ], FALSE ) ; + loadBoneFile ( argv [ 4 ], FALSE ) ; + saveTweenFile ( argv [ 5 ], FALSE ) ; + return 0 ; +} + + + diff --git a/demos/exposer/src/exposer.dsp b/demos/exposer/src/exposer.dsp new file mode 100644 index 0000000..70cfbf0 --- /dev/null +++ b/demos/exposer/src/exposer.dsp @@ -0,0 +1,156 @@ +# Microsoft Developer Studio Project File - Name="exposer" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=exposer - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "exposer.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "exposer.mak" CFG="exposer - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "exposer - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "exposer - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "exposer - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sg.lib ssg.lib ssgAux.lib fnt.lib pui.lib puAux.lib ul.lib opengl32.lib glu32.lib glut32.lib Winmm.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\.." + +!ELSEIF "$(CFG)" == "exposer - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sg_d.lib ssg_d.lib ssgAux_d.lib fnt_d.lib pui_d.lib puAux_d.lib ul_d.lib opengl32.lib glu32.lib glut32.lib Winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\.." + +!ENDIF + +# Begin Target + +# Name "exposer - Win32 Release" +# Name "exposer - Win32 Debug" +# Begin Source File + +SOURCE=.\boneGUI.cxx +# End Source File +# Begin Source File + +SOURCE=.\boneGUI.h +# End Source File +# Begin Source File + +SOURCE=.\bones.cxx +# End Source File +# Begin Source File + +SOURCE=.\bones.h +# End Source File +# Begin Source File + +SOURCE=.\event.cxx +# End Source File +# Begin Source File + +SOURCE=.\event.h +# End Source File +# Begin Source File + +SOURCE=.\exposer.cxx +# End Source File +# Begin Source File + +SOURCE=.\exposer.h +# End Source File +# Begin Source File + +SOURCE=.\floor.cxx +# End Source File +# Begin Source File + +SOURCE=.\floor.h +# End Source File +# Begin Source File + +SOURCE=.\load_save.cxx +# End Source File +# Begin Source File + +SOURCE=.\load_save.h +# End Source File +# Begin Source File + +SOURCE=.\model.cxx +# End Source File +# Begin Source File + +SOURCE=.\model.h +# End Source File +# Begin Source File + +SOURCE=.\timebox.cxx +# End Source File +# Begin Source File + +SOURCE=.\timebox.h +# End Source File +# Begin Source File + +SOURCE=.\vertices.cxx +# End Source File +# Begin Source File + +SOURCE=.\vertices.h +# End Source File +# End Target +# End Project diff --git a/demos/exposer/src/exposer.h b/demos/exposer/src/exposer.h new file mode 100644 index 0000000..e5bcf6c --- /dev/null +++ b/demos/exposer/src/exposer.h @@ -0,0 +1,65 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: exposer.h 1528 2002-09-01 07:10:09Z ude $ +*/ + + +#include +#include +#include +#include +#ifdef WIN32 +#include +#else +#include +#endif +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#include +#include + +#include "event.h" +#include "model.h" +#include "bones.h" +#include "boneGUI.h" +#include "vertices.h" +#include "timebox.h" +#include "floor.h" +#include "load_save.h" + +extern EventList * eventList ; +extern TimeBox * timebox ; +extern Floor * ground ; +extern ssgRoot * skinScene ; +extern ssgRoot *tweenScene ; +extern ssgRoot * boneScene ; +extern ssgRoot *sceneScene ; + diff --git a/demos/exposer/src/floor.cxx b/demos/exposer/src/floor.cxx new file mode 100644 index 0000000..a5d75b8 --- /dev/null +++ b/demos/exposer/src/floor.cxx @@ -0,0 +1,108 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: floor.cxx 1425 2002-08-17 23:58:38Z ude $ +*/ + + +#include "exposer.h" + +static unsigned char Texture0 [] = +{ + 0, 0, 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, 255, 255, + 255, 255, 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, 0, 0 +} ; + +static unsigned char Texture1 [] = +{ + 0, 0, 255, 255, + 0, 0, 255, 255, + 255, 255, 0, 0, + 255, 255, 0, 0 +} ; + +static unsigned char Texture2 [] = +{ + 0, 255, + 255, 0 +} ; + +static unsigned char Texture3 [] = +{ + 127 +} ; + + +void Floor::draw () +{ + glMatrixMode ( GL_PROJECTION) ; _ssgCurrentContext->loadProjectionMatrix() ; + glMatrixMode ( GL_MODELVIEW ) ; _ssgCurrentContext->loadModelviewMatrix () ; + + glDisable ( GL_LIGHTING ) ; + glEnable ( GL_TEXTURE_2D ) ; + glEnable ( GL_CULL_FACE ) ; + glBindTexture ( GL_TEXTURE_2D, texhandle ) ; + glColor4f ( 1.0f, 1.0f, 1.0f, 1.0f ) ; + + glBegin ( GL_QUADS ) ; + glTexCoord2f ( -30.0f, timebox->getGroundPosition() - 30.0f ) ; + glVertex3f ( -30.0f, -30.0f, z_coord ) ; + glTexCoord2f ( 30.0f, timebox->getGroundPosition() - 30.0f ) ; + glVertex3f ( 30.0f, -30.0f, z_coord ) ; + glTexCoord2f ( 30.0f, timebox->getGroundPosition() + 30.0f ) ; + glVertex3f ( 30.0f, 30.0f, z_coord ) ; + glTexCoord2f ( -30.0f, timebox->getGroundPosition() + 30.0f ) ; + glVertex3f ( -30.0f, 30.0f, z_coord ) ; + glEnd () ; + + glDisable ( GL_TEXTURE_2D ) ; + glEnable ( GL_LIGHTING ) ; +} + + +Floor::Floor () +{ + glGenTextures ( 1, & texhandle ) ; + + glBindTexture ( GL_TEXTURE_2D, texhandle ) ; + glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ; + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ) ; + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_LINEAR ) ; + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ) ; + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ) ; + glTexImage2D ( GL_TEXTURE_2D, 0, 1, 8, 8, + FALSE, GL_LUMINANCE, GL_UNSIGNED_BYTE, Texture0 ) ; + glTexImage2D ( GL_TEXTURE_2D, 1, 1, 4, 4, + FALSE, GL_LUMINANCE, GL_UNSIGNED_BYTE, Texture1 ) ; + glTexImage2D ( GL_TEXTURE_2D, 2, 1, 2, 2, + FALSE, GL_LUMINANCE, GL_UNSIGNED_BYTE, Texture2 ) ; + glTexImage2D ( GL_TEXTURE_2D, 3, 1, 1, 1, + FALSE, GL_LUMINANCE, GL_UNSIGNED_BYTE, Texture3 ) ; + glBindTexture ( GL_TEXTURE_2D, 0 ) ; +} + + diff --git a/demos/exposer/src/floor.h b/demos/exposer/src/floor.h new file mode 100644 index 0000000..9de867f --- /dev/null +++ b/demos/exposer/src/floor.h @@ -0,0 +1,39 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: floor.h 1425 2002-08-17 23:58:38Z ude $ +*/ + + +class Floor +{ + unsigned int texhandle ; + float z_coord ; + +public: + + void setZcoord ( float z ) { z_coord = z ; } + float getZcoord () { return z_coord ; } + + void draw () ; + Floor () ; +} ; + + diff --git a/demos/exposer/src/load_save.cxx b/demos/exposer/src/load_save.cxx new file mode 100644 index 0000000..7898fe0 --- /dev/null +++ b/demos/exposer/src/load_save.cxx @@ -0,0 +1,621 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: load_save.cxx 2078 2006-04-13 16:22:38Z bram $ +*/ + +#include + +#include "exposer.h" + +#define FILE_SELECTOR_ARGS (640-320)/2,(480-270)/2,320,270,1 + + +static float tweeninterval = 1.0f/8.0f ; + +void setTweenInterval ( float t ) { tweeninterval = t ; } +float getTweenInterval () { return tweeninterval ; } + + +static puaFileSelector *file_selector = NULL ; + + +static char lastModelFilePath [ PUSTRING_MAX ] ; +static char lastModelFileName [ PUSTRING_MAX ] ; + +static void dismissDialogCB ( puObject * ) ; + +static puButton *dialog_button = NULL ; + + +static void initDialog () +{ + if ( dialog_button != NULL ) + return ; + + dialog_button = new puButton ( 250, 240, "" ) ; + dialog_button -> setSize ( 400, 40 ) ; + dialog_button -> setLegendFont ( PUFONT_TIMES_ROMAN_24 ) ; + dialog_button -> setCallback ( dismissDialogCB ) ; + dialog_button -> setColorScheme ( 1, 1, 0, 1 ) ; + dialog_button -> hide () ; +} + + +static void dismissDialogCB ( puObject * ) +{ + initDialog () ; + dialog_button -> hide () ; +} + + +static void dialog ( const char *msg, float r, float g, float b ) +{ + initDialog () ; + dialog_button -> setLegend ( msg ) ; + dialog_button -> setColorScheme ( r, g, b, 1 ) ; + dialog_button -> reveal () ; +} + + +static void twsavepickfn ( puObject * ) +{ + char path [ PUSTRING_MAX ] ; + + file_selector -> getValue ( path ) ; + + if ( path [ 0 ] == '\0' ) + { + puDeleteObject ( file_selector ) ; + file_selector = NULL ; + + dialog ( "FAILED TO SAVE TWEENED MODEL!", 1, 0, 0 ) ; + return ; + } + + saveTweenFile ( path, TRUE ) ; +} + + +void saveTweenFile ( char *path, int interactive ) +{ + char orig_path [ PUSTRING_MAX ] ; + char fname [ PUSTRING_MAX ] ; + char *p = NULL ; + int i ; + + strcpy ( orig_path, path ) ; + + for ( i = strlen(path) ; i >= 0 ; i-- ) + if ( path[i] == '/' || path[i] == '\\' ) + { + p = & ( path[i+1] ) ; + path[i] = '\0' ; + break ; + } + + if ( p == NULL ) + { + ssgModelPath ( "." ) ; + if ( getenv ( "EXPOSER_TEXTURE_PATH" ) != NULL ) + ssgTexturePath ( getenv ( "EXPOSER_TEXTURE_PATH" ) ) ; + else + ssgTexturePath ( "." ) ; + strcpy ( fname, path ) ; + } + else + { + ssgModelPath ( path ) ; + if ( getenv ( "EXPOSER_TEXTURE_PATH" ) != NULL ) + ssgTexturePath ( getenv ( "EXPOSER_TEXTURE_PATH" ) ) ; + else + ssgTexturePath ( path ) ; + strcpy ( fname, p ) ; + } + + /* SAVE THE TWEENED MODEL */ + + if ( orig_path[0] == '\0' ) + { + if ( interactive ) + { + puDeleteObject ( file_selector ) ; + file_selector = NULL ; + dialog ( "FAILED TO SAVE TWEENED MODEL!", 1, 0, 0 ) ; + return ; + } + else + { + perror ( "saveTween:" ) ; + exit ( 1 ) ; + } + } + + tweenScene = (ssgRoot *) makeTweenCopy ( skinScene ) ; + + for ( i = 0 ; i <= (int)( timebox->getMaxTime() / tweeninterval ) ; i++ ) + { + if ( i != 0 ) + addTweenBank ( tweenScene ) ; + + transformModel ( boneScene, (float) i * tweeninterval ) ; + makeTweenCopy ( tweenScene, skinScene ) ; + } + + if ( ! ssgSave ( orig_path, tweenScene ) ) + { + if ( interactive ) + { + puDeleteObject ( file_selector ) ; + file_selector = NULL ; + dialog ( "FAILED TO SAVE TWEENED MODEL!", 1, 0, 0 ) ; + return ; + } + else + { + perror ( "saveTween:" ) ; + exit ( 1 ) ; + } + } + + if ( interactive ) + { + puDeleteObject ( file_selector ) ; + file_selector = NULL ; + dialog ( "TWEENED MODEL WAS SAVED OK.", 1, 1, 0 ) ; + } +} + + +static void bnsavepickfn ( puObject * ) +{ + char path [ PUSTRING_MAX ] ; + char fname [ PUSTRING_MAX ] ; + + file_selector -> getValue ( path ) ; + + if ( path [ 0 ] == '\0' ) + { + puDeleteObject ( file_selector ) ; + file_selector = NULL ; + + dialog ( "FAILED TO SAVE BONES!", 1, 0, 0 ) ; + return ; + } + + char *p = NULL ; + int i ; + + for ( i = strlen(path) ; i >= 0 ; i-- ) + if ( path[i] == '/' || path[i] == '\\' ) + { + p = & ( path[i+1] ) ; + path[i] = '\0' ; + break ; + } + + if ( p == NULL ) + { + ssgModelPath ( "." ) ; + if ( getenv ( "EXPOSER_TEXTURE_PATH" ) != NULL ) + ssgTexturePath ( getenv ( "EXPOSER_TEXTURE_PATH" ) ) ; + else + ssgTexturePath ( "." ) ; + strcpy ( fname, path ) ; + } + else + { + ssgModelPath ( path ) ; + if ( getenv ( "EXPOSER_TEXTURE_PATH" ) != NULL ) + ssgTexturePath ( getenv ( "EXPOSER_TEXTURE_PATH" ) ) ; + else + ssgTexturePath ( path ) ; + strcpy ( fname, p ) ; + } + + /* SAVE THE BONES */ + + if ( file_selector->getStringValue()[0] == '\0' ) + { + puDeleteObject ( file_selector ) ; + file_selector = NULL ; + dialog ( "FAILED TO SAVE BONES!", 1, 0, 0 ) ; + return ; + } + + FILE *fd = fopen ( file_selector->getStringValue(), "wa" ) ; + + puDeleteObject ( file_selector ) ; + file_selector = NULL ; + + if ( fd == NULL ) + { + dialog ( "FAILED TO SAVE BONES!", 1, 0, 0 ) ; + return ; + } + + fprintf ( fd, "NUMBONES=%d NUMEVENTS=%d MAXTIME=%f Z_OFFSET=%f SPEED=%f\n", + getNumBones(), eventList->getNumEvents(), timebox->getMaxTime (), + -ground->getZcoord(), timebox->getGroundSpeed() ) ; + + for ( i = 0 ; i < getNumBones () ; i++ ) + getBone ( i ) -> write ( fd ) ; + + eventList -> write ( fd ) ; + + fclose ( fd ) ; + dialog ( "BONES WERE SAVED OK.", 1, 1, 0 ) ; +} + + +static void bnpickfn ( puObject * ) +{ + char path [ PUSTRING_MAX ] ; + + file_selector -> getValue ( path ) ; + + if ( path [ 0 ] == '\0' ) + { + puDeleteObject ( file_selector ) ; + file_selector = NULL ; + return ; + } + + loadBoneFile ( path, TRUE ) ; +} + +void loadBoneFile ( char *path, int interactive ) +{ + char orig_path [ PUSTRING_MAX ] ; + char fname [ PUSTRING_MAX ] ; + char *p = NULL ; + int i ; + + strcpy ( orig_path, path ) ; + + for ( i = strlen(path) ; i >= 0 ; i-- ) + if ( path[i] == '/' || path[i] == '\\' ) + { + p = & ( path[i+1] ) ; + path[i] = '\0' ; + break ; + } + + if ( p == NULL ) + { + ssgModelPath ( "." ) ; + if ( getenv ( "EXPOSER_TEXTURE_PATH" ) != NULL ) + ssgTexturePath ( getenv ( "EXPOSER_TEXTURE_PATH" ) ) ; + else + ssgTexturePath ( "." ) ; + strcpy ( fname, path ) ; + } + else + { + ssgModelPath ( path ) ; + if ( getenv ( "EXPOSER_TEXTURE_PATH" ) != NULL ) + ssgTexturePath ( getenv ( "EXPOSER_TEXTURE_PATH" ) ) ; + else + ssgTexturePath ( path ) ; + strcpy ( fname, p ) ; + } + + /* LOAD THE BONES */ + + if ( orig_path[0] == '\0' ) + { + if ( interactive ) + { + puDeleteObject ( file_selector ) ; + file_selector = NULL ; + return ; + } + else + { + perror ( "loadBones:" ) ; + exit ( 1 ) ; + } + } + + FILE *fd = fopen ( orig_path, "ra" ) ; + + if ( fd == NULL ) + { + if ( interactive ) + { + puDeleteObject ( file_selector ) ; + file_selector = NULL ; + return ; + } + else + { + perror ( "loadBones:" ) ; + exit ( 1 ) ; + } + } + + timebox->deleteAll () ; + + int numbones, numevents ; + float floor_z_coord, maxtime, new_ground_speed ; + + fscanf ( fd, + "NUMBONES=%d NUMEVENTS=%d MAXTIME=%f Z_OFFSET=%f SPEED=%f\n", + &numbones, &numevents, + &maxtime, &floor_z_coord, &new_ground_speed ) ; + + + /* Don't use the floor_z_coord from the file. */ + /* ground -> setZcoord ( floor_z_coord ) ; */ + + timebox->setMaxTime ( maxtime ) ; + timebox->setGroundSpeed ( new_ground_speed ) ; + + if ( numbones != getNumBones () ) + { + fprintf ( stderr, + "Number of bones in model (%d) doesn't agree with number in bones file (%d)!\n", getNumBones (), numbones ) ; + exit ( 1 ) ; + } + + for ( i = 0 ; i < getNumBones () ; i++ ) + getBone ( i ) -> read ( fd ) ; + + eventList -> read ( numevents, fd ) ; + + fclose ( fd ) ; + + if ( interactive ) + { + puDeleteObject ( file_selector ) ; + file_selector = NULL ; + } +} + + + +static void scpickfn ( puObject * ) +{ + char path [ PUSTRING_MAX ] ; + char fname [ PUSTRING_MAX ] ; + + file_selector -> getValue ( path ) ; + + puDeleteObject ( file_selector ) ; + file_selector = NULL ; + + if ( path [ 0 ] == '\0' ) + return ; + + if ( strlen ( path ) >= 6 && strcmp(&path[strlen(path)-6], ".bones" ) == 0 ) + { + fprintf ( stderr, "I think you tried to load a BONES file as 3D model.\n"); + fprintf ( stderr, "Try again!\n"); + scloadCB ( NULL ) ; + return ; + } + + char *p = NULL ; + + for ( int i = strlen(path) ; i >= 0 ; i-- ) + if ( path[i] == '/' || path[i] == '\\' ) + { + p = & ( path[i+1] ) ; + path[i] = '\0' ; + break ; + } + + if ( p == NULL ) + { + ssgModelPath ( "." ) ; + + if ( getenv ( "EXPOSER_TEXTURE_PATH" ) != NULL ) + ssgTexturePath ( getenv ( "EXPOSER_TEXTURE_PATH" ) ) ; + else + ssgTexturePath ( "." ) ; + strcpy ( fname, path ) ; + } + else + { + ssgModelPath ( path ) ; + + if ( getenv ( "EXPOSER_TEXTURE_PATH" ) != NULL ) + ssgTexturePath ( getenv ( "EXPOSER_TEXTURE_PATH" ) ) ; + else + ssgTexturePath ( path ) ; + + strcpy ( fname, p ) ; + } + + delete sceneScene ; + sceneScene = new ssgRoot ; + sceneScene -> addKid ( ssgLoad ( fname, NULL ) ) ; +} + + +static void pickfn ( puObject * ) +{ + char path [ PUSTRING_MAX ] ; + + file_selector -> getValue ( path ) ; + + puDeleteObject ( file_selector ) ; + file_selector = NULL ; + + if ( path [ 0 ] == '\0' ) + return ; + + if ( strlen ( path ) >= 6 && strcmp(&path[strlen(path)-6], ".bones" ) == 0 ) + { + fprintf ( stderr, "I think you tried to load a BONES file as 3D model.\n"); + fprintf ( stderr, "Try again!\n"); + loadCB ( NULL ) ; + return ; + } + + loadFile ( path, TRUE ) ; +} + +void loadFile ( char *path, int interactive ) +{ + char fname [ PUSTRING_MAX ] ; + char *p = NULL ; + + for ( int i = strlen(path) ; i >= 0 ; i-- ) + if ( path[i] == '/' || path[i] == '\\' ) + { + p = & ( path[i+1] ) ; + path[i] = '\0' ; + break ; + } + + if ( p == NULL ) + { + ssgModelPath ( "." ) ; + if ( getenv ( "EXPOSER_TEXTURE_PATH" ) != NULL ) + ssgTexturePath ( getenv ( "EXPOSER_TEXTURE_PATH" ) ) ; + else + ssgTexturePath ( "." ) ; + strcpy ( fname, path ) ; + } + else + { + ssgModelPath ( path ) ; + if ( getenv ( "EXPOSER_TEXTURE_PATH" ) != NULL ) + ssgTexturePath ( getenv ( "EXPOSER_TEXTURE_PATH" ) ) ; + else + ssgTexturePath ( path ) ; + strcpy ( fname, p ) ; + } + + strcpy ( lastModelFilePath, path ) ; + strcpy ( lastModelFileName, fname ) ; + + skinScene -> addKid ( ssgLoad ( fname, NULL ) ) ; + ssgFlatten ( skinScene -> getKid ( 0 ) ) ; + ssgStripify ( skinScene -> getKid ( 0 ) ) ; + boneScene -> addKid ( extractBones ( skinScene ) ) ; + + extractVertices ( skinScene ) ; + timebox->deleteAll () ; + + eventList -> newEvent ( 0.0f ) ; + + ground -> setZcoord ( getLowestVertexZ () ) ; +} + + +void twsaveCB ( puObject * ) +{ + if ( file_selector == NULL ) + { + file_selector = new puaFileSelector ( FILE_SELECTOR_ARGS, + lastModelFilePath, "Save Tweened Model As..." ) ; + file_selector -> setCallback ( twsavepickfn ) ; + + char guess_fname [ PUSTRING_MAX ] ; + strcpy ( guess_fname, lastModelFileName ) ; + + for ( int i = strlen ( guess_fname ) ; i >= 0 ; i-- ) + if ( guess_fname [ i ] == '.' ) + { + guess_fname[i] = '\0' ; + break ; + } + + strcat ( guess_fname, "_tweened.ssg" ) ; + file_selector -> setInitialValue ( guess_fname ) ; + } +} + + +void bnsaveCB ( puObject * ) +{ + if ( file_selector == NULL ) + { + file_selector = new puaFileSelector ( FILE_SELECTOR_ARGS, + lastModelFilePath, "Save Bones As..." ) ; + file_selector -> setCallback ( bnsavepickfn ) ; + + char guess_fname [ PUSTRING_MAX ] ; + strcpy ( guess_fname, lastModelFileName ) ; + + for ( int i = strlen ( guess_fname ) ; i >= 0 ; i-- ) + if ( guess_fname [ i ] == '.' ) + { + guess_fname[i] = '\0' ; + break ; + } + + strcat ( guess_fname, ".bones" ) ; + file_selector -> setInitialValue ( guess_fname ) ; + } +} + + +void bnloadCB ( puObject * ) +{ + if ( file_selector == NULL ) + { + file_selector = new puaFileSelector ( FILE_SELECTOR_ARGS, + lastModelFilePath, "Load Bones from..." ) ; + file_selector -> setCallback ( bnpickfn ) ; + + /* Guess an initial filename from the model filename */ + + char guess_fname [ PUSTRING_MAX ] ; + strcpy ( guess_fname, lastModelFileName ) ; + + for ( int i = strlen ( guess_fname ) ; i >= 0 ; i-- ) + if ( guess_fname [ i ] == '.' ) + { + guess_fname[i] = '\0' ; + break ; + } + + strcat ( guess_fname, ".bones" ) ; + file_selector -> setInitialValue ( guess_fname ) ; + } +} + + + +void scloadCB ( puObject * ) +{ + if ( file_selector == NULL ) + { + file_selector = new puaFileSelector ( FILE_SELECTOR_ARGS, + "", "Load Scenery from..." ) ; + file_selector -> setCallback ( scpickfn ) ; + } +} + + +void loadCB ( puObject * ) +{ + if ( file_selector == NULL ) + { + file_selector = new puaFileSelector ( FILE_SELECTOR_ARGS, + "", "Load Model from..." ) ; + file_selector -> setCallback ( pickfn ) ; + } +} + + diff --git a/demos/exposer/src/load_save.h b/demos/exposer/src/load_save.h new file mode 100644 index 0000000..56384b0 --- /dev/null +++ b/demos/exposer/src/load_save.h @@ -0,0 +1,36 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: load_save.h 1425 2002-08-17 23:58:38Z ude $ +*/ + + +void loadCB ( puObject * ) ; +void scloadCB ( puObject * ) ; +void bnloadCB ( puObject * ) ; +void bnsaveCB ( puObject * ) ; +void twsaveCB ( puObject * ) ; + +void loadFile ( char *fname, int interactive ) ; +void loadBoneFile ( char *fname, int interactive ) ; +void saveTweenFile ( char *fname, int interactive ) ; + +void setTweenInterval ( float t ) ; + diff --git a/demos/exposer/src/merge_tweens.cxx b/demos/exposer/src/merge_tweens.cxx new file mode 100644 index 0000000..d0026ef --- /dev/null +++ b/demos/exposer/src/merge_tweens.cxx @@ -0,0 +1,179 @@ +/* + merge_tweens - Merges multiple '.bones' files written from ExPoser + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: merge_tweens.cxx 1425 2002-08-17 23:58:38Z ude $ +*/ + + +#include "merge_tweens.h" + +static void help () +{ + fprintf ( stderr, "\n\n" ) ; + fprintf ( stderr, "merge_tweens: Usage -\n\n" ) ; + fprintf ( stderr, " merge_tweens file.bones ...\n" ) ; + fprintf ( stderr, "\n" ) ; + fprintf ( stderr, "Merges multiple '.bones' files written from ExPoser\n" ) ; + fprintf ( stderr, "into a single animation sequence (stored in 'out.bones').\n" ) ; + fprintf ( stderr, "\n" ) ; + fprintf ( stderr, "Bones files must be compatible (same number of joints\n" ); + fprintf ( stderr, "in same order, etc).\n" ) ; + fprintf ( stderr, "\n" ) ; +} + + +static int numBones = 0 ; +static int totalEvents = 0 ; +static float totalTime = 0.0f ; +static float floor_z = 0.0f ; +static float ground_speed = 0.0f ; + +int main ( int argc, char **argv ) +{ + if ( argc < 2 ) + { + help () ; + exit ( 1 ) ; + } + + /* + First Pass - add up times - do error checking. + */ + + totalEvents = 0 ; + totalTime = 0.0f ; + + int i ; + + for ( i = 1 ; i < argc ; i++ ) + { + FILE *fd = fopen ( argv[i], "ra" ) ; + + int bones, numevents ; + float new_floor_z, maxtime, new_ground_speed ; + + fscanf ( fd, "NUMBONES=%d NUMEVENTS=%d MAXTIME=%f Z_OFFSET=%f SPEED=%f\n", + &bones, &numevents, &maxtime, &new_floor_z, &new_ground_speed ) ; + + printf ( + "%2d) %s: NUMBONES=%d NUMEVENTS=%d MAXTIME=%f Z_OFFSET=%f SPEED=%f\n", + i, argv[i], bones, numevents, maxtime, new_floor_z, new_ground_speed ) ; + + totalEvents += numevents ; + totalTime += maxtime ; + + if ( i == 1 ) + { + numBones = bones ; + floor_z = new_floor_z ; + ground_speed = new_ground_speed ; + } + else + { + if ( numBones != bones ) + { + fprintf ( stderr, + "merge_bones: FATAL - Number of bones must be the same across files.\n" ) ; + exit ( 1 ) ; + } + + if ( floor_z != new_floor_z ) + { + fprintf ( stderr, + "merge_bones: WARNING - Floor Z is not the same across files.\n" ) ; + } + + if ( ground_speed != new_ground_speed ) + { + fprintf ( stderr, + "merge_bones: WARNING - Ground speed is not the same across files.\n"); + } + } + + fclose ( fd ) ; + } + + /* + Pass TWO : Write out composite file. + */ + + FILE *out_fd = fopen ( "out.bones", "wa" ) ; + + float nextTime = 0.0f ; + + for ( i = 1 ; i < argc ; i++ ) + { + FILE *fd = fopen ( argv[i], "ra" ) ; + + int bones, numevents ; + float new_floor_z, maxtime, new_ground_speed ; + + fscanf ( fd, "NUMBONES=%d NUMEVENTS=%d MAXTIME=%f Z_OFFSET=%f SPEED=%f\n", + &bones, &numevents, &maxtime, &new_floor_z, &new_ground_speed ) ; + + if ( i == 1 ) + { + fprintf ( out_fd, + "NUMBONES=%d NUMEVENTS=%d MAXTIME=%f Z_OFFSET=%f SPEED=%f\n", + numBones, totalEvents, totalTime, floor_z, ground_speed ) ; + + for ( int j = 0 ; j < numBones ; j++ ) + { + char s [ 1000 ] ; + fgets ( s, 1000, fd ) ; + fprintf ( out_fd, "%s", s ) ; + } + } + else + { + for ( int j = 0 ; j < numBones ; j++ ) + { + char s [ 1000 ] ; + fgets ( s, 1000, fd ) ; + } + } + + for ( int j = 0 ; j < numevents ; j++ ) + { + float t, x, y, z ; + int nb ; + + fscanf ( fd, "EVENT %f %d (%f,%f,%f)\n", &t, &nb, &x, &y, &z ) ; + fprintf ( out_fd, "EVENT %f %d (%f,%f,%f)\n", t+nextTime, nb, x, y, z ) ; + + for ( int k = 0 ; k < nb ; k++ ) + { + int xx, yy, zz ; + fscanf ( fd, " (%d,%d,%d)\n", &xx, &yy, &zz ) ; + fprintf ( out_fd, " (%d,%d,%d)\n", xx, yy, zz ) ; + } + } + + nextTime += maxtime ; + fclose ( fd ) ; + } + + fclose ( out_fd ) ; + + return 0 ; +} + + + diff --git a/demos/exposer/src/merge_tweens.dsp b/demos/exposer/src/merge_tweens.dsp new file mode 100644 index 0000000..fb0f641 --- /dev/null +++ b/demos/exposer/src/merge_tweens.dsp @@ -0,0 +1,92 @@ +# Microsoft Developer Studio Project File - Name="merge_tweens" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=merge_tweens - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "merge_tweens.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "merge_tweens.mak" CFG="exposer - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "merge_tweens - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "merge_tweens - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "merge_tweens - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "merge_tweens - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\.." + +!ENDIF + +# Begin Target + +# Name "merge_tweens - Win32 Release" +# Name "merge_tweens - Win32 Debug" +# Begin Source File + +SOURCE=.\merge_tweens.cxx +# End Source File +# Begin Source File + +SOURCE=.\merge_tweens.h +# End Source File +# Begin Source File + +# End Project diff --git a/demos/exposer/src/merge_tweens.h b/demos/exposer/src/merge_tweens.h new file mode 100644 index 0000000..310170e --- /dev/null +++ b/demos/exposer/src/merge_tweens.h @@ -0,0 +1,12 @@ + +#include +#include +#include +#include +#ifdef WIN32 +#include +#else +#include +#endif +#include + diff --git a/demos/exposer/src/model.cxx b/demos/exposer/src/model.cxx new file mode 100644 index 0000000..1b292da --- /dev/null +++ b/demos/exposer/src/model.cxx @@ -0,0 +1,465 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: model.cxx 1425 2002-08-17 23:58:38Z ude $ +*/ + + +#include "exposer.h" + +static int rootBone = -1 ; +static int nextBone = 0 ; + +int getNumBones () { return nextBone ; } + +static void findChildBones ( int root ) +{ + float *v0 = getBone ( root ) -> vx[0] ; + float *v1 = getBone ( root ) -> vx[1] ; + + /* + Compute parametric equation. + */ + + sgVec3 vec ; + float len ; + int i ; + + sgSubVec3 ( vec, v1, v0 ) ; + len = sgLengthVec3 ( vec ) ; + sgScaleVec3 ( vec, 1.0f/len ) ; + + for ( i = 0 ; i < getNumBones() ; i++ ) + { + /******************************* + If this bone already has a parent + then we are done. + ********************************/ + + if ( getBone(i)->parent >= 0 ) + continue ; + + /******************************* + Test vertex zero of the daughter + bone against the parent bone. + ********************************/ + + float *vi0 = getBone(i)-> vx[0] ; + float *vi1 = getBone(i)-> vx[1] ; + sgVec3 vec_i ; + float len_i ; + + sgSubVec3 ( vec_i, vi0, v0 ) ; + len_i = sgLengthVec3 ( vec_i ) ; + + if ( len_i <= 0.01 ) /* Close to vertex 0 of parent? */ + { + getBone(i)-> parent = root ; + continue ; + } + + sgScaleVec3 ( vec_i, 1.0f/len_i ) ; + + /* Somewhere between vertex 0 and vertex 1 of parent? */ + + if ( sgDistanceSquaredVec3 ( vec, vec_i ) <= 0.001 && len_i <= len * 1.01 ) + { + getBone(i)-> parent = root ; + continue ; + } + + /******************************* + Test vertex one of the daughter + bone against the parent bone. + ********************************/ + + sgSubVec3 ( vec_i, vi1, v0 ) ; + len_i = sgLengthVec3 ( vec_i ) ; + + if ( len_i <= 0.01 ) /* Close to vertex 0 of parent? */ + { + getBone(i)->parent = root ; + getBone(i)->swapEnds () ; + continue ; + } + + sgScaleVec3 ( vec_i, 1.0f/len_i ) ; + + /* Somewhere between vertex 0 and vertex 1 of parent? */ + + if ( sgDistanceSquaredVec3 ( vec, vec_i ) <= 0.001 && len_i <= len * 1.01 ) + { + getBone(i)->parent = root ; + getBone(i)->swapEnds () ; + continue ; + } + } + + /**************************************************** + Recursively search any new child nodes we found. + ****************************************************/ + + for ( i = 0 ; i < getNumBones() ; i++ ) + if ( i != root && getBone(i)->parent == root ) /* If Parented by this root node */ + findChildBones ( i ) ; /* Recurse downwards. */ +} + + +void addTweenBank ( ssgBranch *root ) +{ + if ( root == NULL ) + return ; + + for ( int i = 0 ; i < root -> getNumKids () ; i++ ) + { + ssgEntity *e = root -> getKid ( i ) ; + + if ( e -> isAKindOf ( ssgTypeBranch() ) ) + addTweenBank ( (ssgBranch *)e ) ; + else + if ( e -> isAKindOf ( ssgTypeTween() ) ) + { + ssgTween *tween = (ssgTween *) e ; + + ssgVertexArray *v1 = new ssgVertexArray ; + + for ( int ii = 0 ; ii < tween -> getNumVertices () ; ii++ ) + v1 -> add ( tween -> getVertex ( ii ) ) ; + + tween -> newBank ( v1, NULL, NULL, NULL ) ; + } + } +} + + +void makeTweenCopy ( ssgBranch *dst, ssgBranch *src ) +{ + for ( int i = 0 ; i < src -> getNumKids () ; i++ ) + { + ssgEntity *s = src -> getKid ( i ) ; + ssgEntity *d = dst -> getKid ( i ) ; + + if ( s -> isAKindOf ( ssgTypeBranch() ) ) + makeTweenCopy ( (ssgBranch *)d, (ssgBranch *)s ) ; + else + { + ssgLeaf *ls = (ssgLeaf *) s ; + ssgLeaf *ld = (ssgLeaf *) d ; + + for ( int ii = 0 ; ii < ls -> getNumVertices () ; ii++ ) + sgCopyVec3 ( ld->getVertex(ii), ls->getVertex(ii) ) ; + } + } +} + + +static void tweenify ( ssgBranch *root ) +{ + for ( int i = 0 ; i < root -> getNumKids () ; i++ ) + { + ssgEntity *e = root -> getKid ( i ) ; + + if ( e -> isAKindOf ( ssgTypeBranch() ) ) + tweenify ( (ssgBranch *)e ) ; + else + { + ssgLeaf *l = (ssgLeaf *) e ; + + ssgVertexArray *v0 = new ssgVertexArray ; + ssgNormalArray *n0 = new ssgNormalArray ; + ssgTexCoordArray *t0 = new ssgTexCoordArray ; + ssgColourArray *c0 = new ssgColourArray ; + + for ( int ii = 0 ; ii < l -> getNumVertices () ; ii++ ) + { + v0 -> add ( l -> getVertex ( ii ) ) ; + n0 -> add ( l -> getNormal ( ii ) ) ; + t0 -> add ( l -> getTexCoord ( ii ) ) ; + c0 -> add ( l -> getColour ( ii ) ) ; + } + + ssgTween *tween = new ssgTween ( l -> getPrimitiveType () ) ; + + tween -> setState ( l -> getState () ) ; + tween -> newBank ( v0, n0, t0, c0 ) ; + + root -> replaceKid ( l, tween ) ; + } + } +} + + + +ssgEntity *makeTweenCopy ( ssgEntity *root ) +{ + if ( root == NULL ) + return NULL ; + + ssgEntity *res = (ssgEntity *) ( root -> clone ( SSG_CLONE_RECURSIVE | + SSG_CLONE_GEOMETRY ) ) ; + tweenify ( (ssgBranch *) res ) ; + + return res ; +} + + +static void walkBones ( ssgBranch *root, sgMat4 mat ) +{ + if ( root == NULL ) + return ; + + sgMat4 newmat ; + + if ( root -> isAKindOf ( ssgTypeTransform() ) ) + { + sgMat4 tmp ; + + ((ssgTransform *)root)-> getTransform ( tmp ) ; + sgMultMat4 ( newmat, mat, tmp ) ; + } + else + sgCopyMat4 ( newmat, mat ) ; + + for ( int i = 0 ; i < root -> getNumKids () ; i++ ) + { + ssgEntity *e = root -> getKid ( i ) ; + + if ( e -> isAKindOf ( ssgTypeBranch() ) ) + walkBones ( (ssgBranch *)e, newmat ) ; + else + { + ssgLeaf *l = (ssgLeaf *) e ; + + if ( l -> getPrimitiveType () == GL_LINES || + l -> getPrimitiveType () == GL_LINE_LOOP || + l -> getPrimitiveType () == GL_LINE_STRIP ) + { + for ( int ll = 0 ; ll < l->getNumLines() ; ll++ ) + { + short vv [ 2 ] ; + + l -> getLine ( ll, & vv[0], & vv[1] ) ; + + getBone ( getNumBones() ) -> init ( l, newmat, vv, + getNumBones() ) ; + + /* + Is this line red? + If so, it's the 'root' line. + */ + + float *col = l -> getColour ( vv[0] ) ; + + if ( l -> getState () != NULL && + l -> getState () -> isAKindOf ( ssgTypeSimpleState () ) ) + { + ssgSimpleState *ss = (ssgSimpleState *)( l -> getState () ) ; + + if ( ss -> getColourMaterial () != GL_DIFFUSE && + ss -> getColourMaterial () != GL_AMBIENT_AND_DIFFUSE ) + { + col = ss -> getMaterial ( GL_DIFFUSE ) ; + } + } + + if ( col [ 0 ] > 0.75 && col [ 1 ] < 0.25 && col [ 2 ] < 0.25 ) + { + if ( rootBone != -1 ) + rootBone = -2 ; + else + rootBone = getNumBones() ; + } + + nextBone++ ; + } + + root -> removeKid ( e ) ; + i-- ; + } + } + } +} + + + +void offsetChildBones ( int root, sgVec3 v ) +{ + for ( int i = 0 ; i < getNumBones() ; i++ ) + if ( getBone(i)->parent == root ) + { + sgSubVec3 ( getBone(i)->vx[0], v ) ; + sgSubVec3 ( getBone(i)->vx[1], v ) ; + offsetChildBones ( i, v ) ; + } +} + + +ssgBranch *extractBones ( ssgBranch *root ) +{ + sgMat4 mat ; + + nextBone = 0 ; + rootBone = -1 ; + + sgMakeIdentMat4 ( mat ) ; + walkBones ( root, mat ) ; + + if ( rootBone == -1 ) + { + fprintf ( stderr, "exposer: ERROR - No 'root' bone found?!?\n" ) ; + fprintf ( stderr, "exposer: (Exactly one 'bone' line should be RED).\n" ) ; + exit ( 1 ) ; + } + + if ( rootBone == -2 ) + { + fprintf ( stderr, "exposer: ERROR - Multiple 'root' bones found?!?\n" ) ; + fprintf ( stderr, "exposer: (Only one 'bone' line should be RED).\n" ) ; + exit ( 1 ) ; + } + + fprintf ( stderr, "exposer: %d bones found, rootBone is number %d.\n", + getNumBones(), rootBone ) ; + + getBone(rootBone)->parent = ROOT_BONE ; + + findChildBones ( rootBone ) ; + + int disconnected = 0 ; + + for ( int i = 0 ; i < getNumBones() ; i++ ) + if ( getBone(i)->parent < 0 ) + disconnected++ ; + + if ( disconnected > 0 ) + { + fprintf ( stderr, + "exposer: ERROR - %d bones are not connected to the 'root' bone.\n", + disconnected ) ; + fprintf ( stderr, + "exposer: (The root bone line should be RED. All other bones\n" ) ; + fprintf ( stderr, + "exposer: should either touch the root bone - or touch some\n" ) ; + fprintf ( stderr, + "exposer: other bone that is connected to the root bone so that\n"); + fprintf ( stderr, + "exposer: all the bones form one continuously connected\n" ) ; + fprintf ( stderr, + "exposer: skeleton.)\n" ) ; + exit ( 1 ) ; + } + + + ssgBranch *res = getBone ( rootBone ) -> generateGeometry ( rootBone ) ; + + return res ; +} + + +static void walkTransforms ( ssgBranch *root, sgMat4 mat ) +{ + if ( root == NULL ) + return ; + + sgMat4 newmat ; + + if ( root -> isAKindOf ( ssgTypeTransform() ) ) + { + sgMat4 tmp ; + + ((ssgTransform *)root)-> getTransform ( tmp ) ; + sgMultMat4 ( newmat, mat, tmp ) ; + + Bone *bo = (Bone *)(((ssgTransform *)root)-> getUserData ()) ; + sgCopyMat4 ( bo -> netMatrix, newmat ) ; + } + else + sgCopyMat4 ( newmat, mat ) ; + + for ( int i = 0 ; i < root -> getNumKids () ; i++ ) + { + ssgEntity *e = root -> getKid ( i ) ; + + if ( e -> isAKindOf ( ssgTypeBranch () ) ) + walkTransforms ( (ssgBranch *) e, newmat ) ; + } +} + + +void transformModel ( ssgBranch *boneRoot, float tim ) +{ + if ( eventList->getNumEvents () < 1 ) + return ; + + Event *prev = eventList->getEvent ( 0 ) ; + Event *next = prev ; + + if ( eventList->getCurrentEvent() != NULL ) + { + prev = next = eventList->getCurrentEvent() ; + tim = eventList->getCurrentEvent() -> getTime () ; + } + else + { + for ( int i = 1 ; i < eventList->getNumEvents () ; i++ ) + { + Event *ev = eventList->getEvent ( i ) ; + float t = ev -> getTime () ; + + if ( t < tim ) + next = prev = ev ; + else + { + next = ev ; + break ; + } + } + } + + float lerptime = 0.0f ; + + if ( next->getTime() - prev->getTime() >= 0.01 ) + { + lerptime = tim - prev->getTime() ; + lerptime /= (next->getTime() - prev->getTime()) ; + } + + sgVec3 ptra ; prev->getTranslate(ptra) ; + sgVec3 ntra ; next->getTranslate(ntra) ; + + sgLerpVec3 ( getCurrTranslate(), ptra, ntra, lerptime ) ; + + syncTranslators ( getCurrTranslate() ) ; + + int i ; + + for ( i = 0 ; i < getNumBones () ; i++ ) + getBone ( i ) -> computeTransform ( prev, next, lerptime ) ; + + sgMat4 mat ; + + sgMakeIdentMat4 ( mat ) ; + + walkTransforms ( (ssgBranch *) boneRoot, mat ) ; + + transformVertices () ; +} + + diff --git a/demos/exposer/src/model.h b/demos/exposer/src/model.h new file mode 100644 index 0000000..323d620 --- /dev/null +++ b/demos/exposer/src/model.h @@ -0,0 +1,36 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: model.h 1425 2002-08-17 23:58:38Z ude $ +*/ + + +ssgBranch *extractBones ( ssgBranch *root ) ; +ssgEntity *makeTweenCopy ( ssgEntity *root ) ; +void extractVertices ( ssgBranch *root ) ; +void transformModel ( ssgBranch *boneRoot, float tim ) ; +void makeTweenCopy ( ssgBranch *dest, ssgBranch *src ) ; +void addTweenBank ( ssgBranch *root ) ; +void offsetChildBones ( int root, sgVec3 v ) ; + +float getLowestVertexZ () ; + +int getNumBones () ; + diff --git a/demos/exposer/src/timebox.cxx b/demos/exposer/src/timebox.cxx new file mode 100644 index 0000000..e8c8b9a --- /dev/null +++ b/demos/exposer/src/timebox.cxx @@ -0,0 +1,386 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: timebox.cxx 2100 2006-11-03 22:31:54Z fayjf $ +*/ + + +#include "exposer.h" + +#define MODE_ADD 0 +#define MODE_SELECT 1 + +#define TIMEBOX_LEFT 230.0f +#define TIMEBOX_RIGHT 790.0f +#define TIMEBOX_TOP 100.0f +#define TIMEBOX_BOTTOM 10.0f +#define TIMEBOX_WIDTH (TIMEBOX_RIGHT-TIMEBOX_LEFT) +#define TIMEBOX_INITIAL_DURATION 10.0f /* Seconds */ + +/* GUI callback functions. */ + +static void vcr_fastReverse ( puObject *ob ) +{ + TimeBox *timebox = (TimeBox *) ob -> getUserData () ; + timebox -> setReplaySpeed (-3.0f); +} + +static void vcr_reverse ( puObject *ob ) +{ + TimeBox *timebox = (TimeBox *) ob -> getUserData () ; + timebox -> setReplaySpeed (-1.0f); +} + +static void vcr_stop ( puObject *ob ) +{ + TimeBox *timebox = (TimeBox *) ob -> getUserData () ; + timebox -> setReplaySpeed ( 0.0f); +} + +static void vcr_play ( puObject *ob ) +{ + TimeBox *timebox = (TimeBox *) ob -> getUserData () ; + timebox -> setReplaySpeed ( 1.0f); +} + +static void vcr_fastPlay ( puObject *ob ) +{ + TimeBox *timebox = (TimeBox *) ob -> getUserData () ; + timebox -> setReplaySpeed ( 3.0f); +} + +static void vcr_groundSpeed ( puObject *ob ) +{ + TimeBox *timebox = (TimeBox *) ob -> getUserData () ; + timebox -> setGroundSpeed ( ob -> getFloatValue () ) ; +} + + +static void timescrollerCB ( puObject *ob ) +{ + TimeBox *timebox = (TimeBox *) ob -> getUserData () ; + + timebox -> setScroll ( ob -> getFloatValue () * + ( timebox -> getMaxTime() - + TIMEBOX_WIDTH / timebox -> second () ) ) ; +} + + +float TimeBox::second () +{ + return scale * TIMEBOX_WIDTH / maxtime ; +} + + +void TimeBox::deleteRegionAndCompress () +{ + eventList -> compressEventsBetween ( lcursor, rcursor ) ; + + maxtime -= (float)fabs(lcursor-rcursor) ; + + if ( lcursor > rcursor ) + lcursor = rcursor ; + else + rcursor = lcursor ; +} + + +void TimeBox::addNewEvent () +{ + if ( getNumBones() <= 0 ) + return ; + + eventList->setCurrentEvent ( NULL ) ; + event_mode = MODE_ADD ; +} + + +void TimeBox::updateVCR () +{ + static ulClock timer ; + + timer.update () ; + + if ( replay_speed != 0.0f ) + { + float delta_t = replay_speed * (float)timer.getDeltaTime () ; + + lcursor += delta_t ; + + if ( lcursor < 0.0f ) + lcursor = maxtime ; + + if ( lcursor > maxtime ) + lcursor = 0.0f ; + } + + ground_position = lcursor * ground_speed ; +} + + +void TimeBox::draw () +{ + int w = puGetWindowWidth () ; + int h = puGetWindowHeight () ; + + glPushAttrib ( GL_ENABLE_BIT | GL_TRANSFORM_BIT | GL_LIGHTING_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 () ; + + glColor4f ( 0.8f, 0.8f, 0.8f, 1.0f ) ; + glBegin ( GL_LINE_LOOP ) ; + glVertex2f ( TIMEBOX_LEFT , TIMEBOX_BOTTOM ) ; + glVertex2f ( TIMEBOX_RIGHT, TIMEBOX_BOTTOM ) ; + glVertex2f ( TIMEBOX_RIGHT, TIMEBOX_TOP ) ; + glVertex2f ( TIMEBOX_LEFT , TIMEBOX_TOP ) ; + glEnd () ; + + int nseconds = (int)floor(TIMEBOX_WIDTH / second () ) ; + int ntenthseconds = (int)floor(TIMEBOX_WIDTH*10.0f / second () ) ; + int tenthsecondoffset = (int)( (start*10.0f - + floor(start*10.0f)) + * second () / 10.0f ) ; + int secondoffset = (int)( (start - + floor(start)) + * second () ) ; + int i ; + + glBegin ( GL_LINES ) ; + + for ( i = 0 ; i < ntenthseconds ; i++ ) + { + float x = TIMEBOX_LEFT + tenthsecondoffset + + (float) i * second () / 10.0f ; + + glVertex2f ( x, TIMEBOX_BOTTOM ) ; + glVertex2f ( x, TIMEBOX_TOP/3.0f ) ; + } + + for ( i = 0 ; i < nseconds ; i++ ) + { + float x = TIMEBOX_LEFT + secondoffset + + (float) i * second () ; + + glVertex2f ( x, TIMEBOX_BOTTOM ) ; + glVertex2f ( x, TIMEBOX_TOP/2.0f ) ; + } + + glEnd () ; + + float tlcursor = ( lcursor - start ) * second () ; + float trcursor = ( rcursor - start ) * second () ; + + tlcursor = (tlcursor < 0.0f ) ? 0.0f : + (tlcursor > TIMEBOX_WIDTH) ? TIMEBOX_WIDTH : tlcursor ; + + trcursor = (trcursor < 0.0f ) ? 0.0f : + (trcursor > TIMEBOX_WIDTH) ? TIMEBOX_WIDTH : trcursor ; + + if ( tlcursor != trcursor ) + { + glColor4f ( 1.0f, 1.0f, 0.0f, 0.2f ) ; + glBegin ( GL_QUADS ) ; + glVertex2f ( TIMEBOX_LEFT + tlcursor, TIMEBOX_BOTTOM ) ; + glVertex2f ( TIMEBOX_LEFT + tlcursor, TIMEBOX_TOP ) ; + glVertex2f ( TIMEBOX_LEFT + trcursor, TIMEBOX_TOP ) ; + glVertex2f ( TIMEBOX_LEFT + trcursor, TIMEBOX_BOTTOM ) ; + glEnd () ; + } + + glColor4f ( 0.0f, 0.0f, 0.0f, 1.0f ) ; + + glBegin ( GL_LINES ) ; + glVertex2f ( TIMEBOX_LEFT + trcursor, TIMEBOX_BOTTOM ) ; + glVertex2f ( TIMEBOX_LEFT + trcursor, TIMEBOX_TOP ) ; + glEnd () ; + + glColor4f ( 1.0f, 0.0f, 0.0f, 1.0f ) ; + + glBegin ( GL_LINES ) ; + glVertex2f ( TIMEBOX_LEFT + tlcursor, TIMEBOX_BOTTOM ) ; + glVertex2f ( TIMEBOX_LEFT + tlcursor, TIMEBOX_TOP ) ; + glEnd () ; + + float t ; + + glColor4f ( 1.0f, 0.0f, 1.0f, 1.0f ) ; + + glBegin ( GL_LINES ) ; + + for ( i = 0 ; i < eventList->getNumEvents() ; i++ ) + { + t = eventList->getEvent(i) -> getTime () ; + + t = ( t - start ) * second () ; + + if ( t >= 0.0f && t <= TIMEBOX_WIDTH ) + { + glVertex2f ( TIMEBOX_LEFT + t, TIMEBOX_TOP/3.0f ) ; + glVertex2f ( TIMEBOX_LEFT + t, TIMEBOX_TOP ) ; + } + } + glEnd () ; + + if ( eventList->getCurrentEvent() != NULL ) + { + t = eventList->getCurrentEvent() -> getTime () ; + + t = ( t - start ) * second () ; + + if ( t >= 0.0f && t <= TIMEBOX_WIDTH ) + { + static ulClock flasher ; + flasher.update () ; + + if ( (int)(flasher.getAbsTime()*3.0f) & 1 ) + glColor4f ( 1.0f, 0.0f, 1.0f, 1.0f ) ; + else + glColor4f ( 0.0f, 1.0f, 0.0f, 1.0f ) ; + glBegin ( GL_LINES ) ; + glVertex2f ( TIMEBOX_LEFT + t, TIMEBOX_TOP/3.0f ) ; + glVertex2f ( TIMEBOX_LEFT + t, TIMEBOX_TOP ) ; + glEnd () ; + } + } + + glMatrixMode ( GL_PROJECTION ) ; + glPopMatrix () ; + glMatrixMode ( GL_MODELVIEW ) ; + glPopMatrix () ; + glPopAttrib () ; +} + + + + +void TimeBox::updateEventQueue ( int button, int x, int y, int new_click ) +{ + y = puGetWindowHeight () - y ; + + /* + Allow user to click a little outside the box so + we can make it easier to get the ends exactly. + */ + + if ( x > TIMEBOX_LEFT - 20 && x < TIMEBOX_RIGHT + 20 && + y > TIMEBOX_BOTTOM && y < TIMEBOX_TOP ) + { + float c = (float)(x - TIMEBOX_LEFT) ; + + if ( c < 0.0f ) c = 0.0f ; + if ( c > TIMEBOX_WIDTH ) c = TIMEBOX_WIDTH ; + + c /= second () ; + c += start ; + + if ( button == PU_RIGHT_BUTTON ) + rcursor = c ; + else + if ( button == PU_LEFT_BUTTON ) + { + rcursor = lcursor = c ; + + if ( new_click ) + { + if ( event_mode == MODE_ADD ) + eventList -> newEvent ( lcursor ) ; + else + eventList -> setCurrentEvent ( + eventList -> findNearestEvent ( lcursor, 10.0f/second () ) ) ; + + event_mode = MODE_SELECT ; + } + else + if ( eventList->getCurrentEvent() != NULL ) + eventList->moveEvent ( eventList->getCurrentEvent(), lcursor ) ; + } + } +} + + +void TimeBox::init () +{ + event_mode = MODE_SELECT ; + + maxtime = TIMEBOX_INITIAL_DURATION ; + scale = 1.0f ; + start = 0.0f ; + + lcursor = 0.0f ; + rcursor = 0.0f ; + + replay_speed = 0.0f ; + ground_speed = 0.0f ; + ground_position = 0.0f ; + + timescroller = new puSlider ( (int)TIMEBOX_LEFT, (int)TIMEBOX_TOP+5, + 570-(int)TIMEBOX_LEFT, FALSE ) ; + timescroller -> setCBMode ( PUSLIDER_DELTA ) ; + timescroller -> setDelta ( 0.01f ) ; + timescroller -> setCallback ( timescrollerCB ) ; + timescroller -> setUserData ( this ) ; + timescroller -> hide () ; + + puText *message ; + puOneShot *oneshot ; + puGroup *vcr = new puGroup ( 579, (int)TIMEBOX_TOP + 5 ) ; + + oneshot = new puArrowButton ( 0, 0, 30, 30, PUARROW_FASTLEFT ) ; + oneshot -> setCallback ( vcr_fastReverse ) ; + oneshot -> setUserData ( this ) ; + oneshot = new puArrowButton ( 30, 0, 60, 30, PUARROW_LEFT ) ; + oneshot -> setCallback ( vcr_reverse ) ; + oneshot -> setUserData ( this ) ; + oneshot = new puArrowButton ( 60, 0, 90, 30, PUARROW_DOWN ) ; + oneshot -> setCallback ( vcr_stop ) ; + oneshot -> setUserData ( this ) ; + oneshot = new puArrowButton ( 90, 0,120, 30, PUARROW_RIGHT ) ; + oneshot -> setCallback ( vcr_play ) ; + oneshot -> setUserData ( this ) ; + oneshot = new puArrowButton (120, 0,150, 30, PUARROW_FASTRIGHT ) ; + oneshot -> setCallback ( vcr_fastPlay ) ; + oneshot -> setUserData ( this ) ; + + ground_speed_input = new puInput ( 150, 0, 200, 20 ) ; + ground_speed_input -> setCallback ( vcr_groundSpeed ) ; + ground_speed_input -> setValue ( "0.0" ) ; + ground_speed_input -> setUserData ( this ) ; + + message = new puText ( 150, 20 ) ; + message -> setColour ( PUCOL_LABEL, 0.7f,0.65f,0.26f,1 ) ; + message -> setLabel ( "GrndSpeed" ) ; + + vcr -> close () ; +} + + diff --git a/demos/exposer/src/timebox.h b/demos/exposer/src/timebox.h new file mode 100644 index 0000000..2234874 --- /dev/null +++ b/demos/exposer/src/timebox.h @@ -0,0 +1,117 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: timebox.h 1425 2002-08-17 23:58:38Z ude $ +*/ + + +class TimeBox +{ + int event_mode ; + + float maxtime ; + float scale ; + float start ; + float lcursor ; + float rcursor ; + + EventList *eventList ; + puSlider *timescroller ; + puInput *ground_speed_input ; + + float replay_speed ; + float ground_speed ; + float ground_position ; + + void init () ; + +public: + + void setReplaySpeed ( float spd ) + { + replay_speed = spd ; + eventList->setCurrentEvent ( NULL ) ; + } + + void draw () ; + + void updateEventQueue ( int button, int x, int y, int new_click ) ; + void updateVCR () ; + + TimeBox ( EventList *el ) { eventList = el ; init () ; } + + float second () ; + + float getCursorTime () { return lcursor ; } + + void setMaxTime ( float t ) { maxtime = t ; } + float getMaxTime () { return maxtime ; } + + + void setGroundSpeed ( float t ) + { + ground_speed = t ; + ground_speed_input -> setValue ( ground_speed ) ; + } + float getGroundSpeed () { return ground_speed ; } + + void setGroundPosition ( float t ) { ground_position = t ; } + float getGroundPosition () { return ground_position ; } + + void setScroll ( float z ) { start = z ; } + float getScroll () { return start ; } + + void setZoom ( float z ) + { + scale = z ; + + if ( scale == 1.0f ) + timescroller -> hide () ; + else + timescroller -> reveal () ; + } + float getZoom () { return scale ; } + + void reverseRegion () + { + eventList -> reverseEventsBetween ( lcursor, rcursor ) ; + } + + void deleteAll () + { + eventList -> deleteAll () ; + lcursor = rcursor = 0.0f ; + } + + void deleteRegion () + { + eventList -> deleteEventsBetween ( lcursor, rcursor ) ; + } + + void deleteEvent () + { + eventList -> deleteCurrentEvent () ; + } + + void deleteRegionAndCompress () ; + void addNewEvent () ; +} ; + + diff --git a/demos/exposer/src/vertices.cxx b/demos/exposer/src/vertices.cxx new file mode 100644 index 0000000..0d879d9 --- /dev/null +++ b/demos/exposer/src/vertices.cxx @@ -0,0 +1,189 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: vertices.cxx 1425 2002-08-17 23:58:38Z ude $ +*/ + + +#include "exposer.h" + + +class Vertex +{ +public: + + int boneID ; + sgVec3 rel_vx ; + float *vx ; + + int getBoneID () { return boneID ; } +} ; + + +static int nextVertex = 0 ; + +#define MAX_VERTICES (64*1024) + +static Vertex vertex [ MAX_VERTICES ] ; + + + +static int getNumVertices () { return nextVertex ; } + + +static void addVertex ( sgVec3 v ) +{ + vertex [ nextVertex ] . vx = v ; + sgCopyVec3 ( vertex [ nextVertex ] . rel_vx, v ) ; + + nextVertex++ ; +} + + +static void initVertices () +{ + nextVertex = 0 ; +} + + +static void walkVertices ( ssgBranch *root, sgMat4 mat ) +{ + if ( root == NULL ) + return ; + + sgMat4 newmat ; + + if ( root -> isAKindOf ( ssgTypeTransform() ) ) + { + sgMat4 tmp ; + + ((ssgTransform *)root)-> getTransform ( tmp ) ; + sgMultMat4 ( newmat, mat, tmp ) ; + + sgMakeIdentMat4 ( tmp ) ; + ((ssgTransform *)root)-> setTransform ( tmp ) ; + } + else + sgCopyMat4 ( newmat, mat ) ; + + for ( int i = 0 ; i < root -> getNumKids () ; i++ ) + { + ssgEntity *e = root -> getKid ( i ) ; + + if ( e -> isAKindOf ( ssgTypeBranch() ) ) + walkVertices ( (ssgBranch *)e, newmat ) ; + else + { + ssgLeaf *l = (ssgLeaf *) e ; + + for ( int ll = 0 ; ll < l->getNumVertices() ; ll++ ) + { + float *v = l -> getVertex ( ll ) ; + int vv = -1 ; + + for ( int j = 0 ; j < getNumVertices() ; j++ ) + if ( v == vertex [ j ] . vx ) + { + vv = j ; + break ; + } + + if ( vv < 0 ) + { + sgXformPnt3 ( v, mat ) ; + addVertex ( v ) ; + } + } + } + } +} + + +void extractVertices ( ssgBranch *root ) +{ + sgMat4 mat ; + + initVertices () ; + + /* + Walk the model - making a list of all of the + unique vertices - flattening the model's transforms + as we go. + */ + + sgMakeIdentMat4 ( mat ) ; + walkVertices ( root, mat ) ; + + /* + Now find the nearest bone to each vertex and + compute it's position relative to the root of + that bone. + */ + + for ( int i = 0 ; i < getNumVertices() ; i++ ) + { + float min = FLT_MAX ; + + for ( int j = 0 ; j < getNumBones() ; j++ ) + { + sgLineSegment3 ls ; + sgCopyVec3 ( ls.a, getBone(j)->orig_vx[0] ) ; + sgCopyVec3 ( ls.b, getBone(j)->orig_vx[1] ) ; + + float d = sgDistSquaredToLineSegmentVec3 ( ls, vertex[i].vx ) ; + + if ( d < min ) + { + min = d ; + vertex[i].boneID = j ; + } + } + + sgSubVec3 ( vertex[i].rel_vx, + vertex[i].vx, + getBone(vertex[i].boneID)->orig_vx[0] ) ; + } +} + + +float getLowestVertexZ () +{ + float lowest = FLT_MAX ; + + for ( int i = 0 ; i < getNumVertices() ; i++ ) + { + float v = vertex[i].vx [ 2 ] ; + + if ( v < lowest ) + lowest = v ; + } + + return lowest ; +} + + +void transformVertices () +{ + for ( int i = 0 ; i < getNumVertices () ; i++ ) + getBone ( vertex[i].getBoneID() ) -> transform ( vertex[i].vx, + vertex[i].rel_vx ) ; +} + + diff --git a/demos/exposer/src/vertices.h b/demos/exposer/src/vertices.h new file mode 100644 index 0000000..05d65b6 --- /dev/null +++ b/demos/exposer/src/vertices.h @@ -0,0 +1,28 @@ +/* + This file is part of ExPoser - A Tool for Animating PLIB Critters. + Copyright (C) 2001 Steve Baker + + ExPoser 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. + + ExPoser 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 ExPoser; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: vertices.h 1425 2002-08-17 23:58:38Z ude $ +*/ + + +void extractVertices ( ssgBranch *root ) ; +float getLowestVertexZ () ; +void transformVertices () ; + diff --git a/demos/p-guide/AUTHORS b/demos/p-guide/AUTHORS new file mode 100644 index 0000000..dee669c --- /dev/null +++ b/demos/p-guide/AUTHORS @@ -0,0 +1,3 @@ +P-GUIDE was written by John F. Fay. +Significant improvements were made by James 'J.C.' Jones + diff --git a/demos/p-guide/COPYING b/demos/p-guide/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/demos/p-guide/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/demos/p-guide/ChangeLog b/demos/p-guide/ChangeLog new file mode 100644 index 0000000..6857348 --- /dev/null +++ b/demos/p-guide/ChangeLog @@ -0,0 +1 @@ +July, 2002 -- P-Guide functionality increased dramatically -- James 'J.C.' Jones diff --git a/demos/p-guide/INSTALL b/demos/p-guide/INSTALL new file mode 100644 index 0000000..b42a17a --- /dev/null +++ b/demos/p-guide/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/demos/p-guide/Makefile.am b/demos/p-guide/Makefile.am new file mode 100644 index 0000000..62fbcb9 --- /dev/null +++ b/demos/p-guide/Makefile.am @@ -0,0 +1,4 @@ +SUBDIRS = src + +EXTRA_DIRS = autogen.sh README TODO pGuide.dsw + diff --git a/demos/p-guide/NEWS b/demos/p-guide/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/demos/p-guide/README b/demos/p-guide/README new file mode 100644 index 0000000..11f436b --- /dev/null +++ b/demos/p-guide/README @@ -0,0 +1,34 @@ + +PUI-based Graphical User Interface Designer +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + by John F. Fay + +REQUIREMENTS: + + OpenGL (or Mesa) + GLUT (the GL Utility Toolkit) + PLIB + + +INSTALLATION: + +Installation instructions are pretty basic: + + ./configure + make + make install + + +LICENSE: + +This software is released under the provisions of +the GNU General Public License (GPL) which can be +found in the file 'COPYING' in the current directory. + + +DIRECTORY STRUCTURE: + +src -- Where the source code lives. + +doc -- Documentation - in HTML + diff --git a/demos/p-guide/TODO b/demos/p-guide/TODO new file mode 100644 index 0000000..c11eb61 --- /dev/null +++ b/demos/p-guide/TODO @@ -0,0 +1,30 @@ +Planned Bug Fixes or Upgrades to P-GUIDE: + +Bug Fixes: + +1. When the user has selected CTRL-widget, have the button value set back to zero when the selected_widget_type (or whatever it is) gets deselected or changed (eg when he presses on another widget button in the Widget window or presses another widget anywhere else), not just when he presses Escape. + +2. Make the Active widget's black line go all the way around it. + +3. puFileSelector needs options + +4. puScrollBar needs to be added + +5. Menus (Vert and normal) need a method to populate submenus. + +Upgrades: + +1. Improve layer support. + +2. Make widgets added to window the real widgets, rather than Frames. + +3. Multiple Window support + +4. Makefile building? + +5. Font viewing / selecting (a font browser and such) + +6. Copy / Cut / Paste + +7. Widget class changes + diff --git a/demos/p-guide/autogen.sh b/demos/p-guide/autogen.sh new file mode 100755 index 0000000..02a1eb9 --- /dev/null +++ b/demos/p-guide/autogen.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +OSTYPE=`uname -s` + +AMFLAGS="--add-missing" +if test "$OSTYPE" = "IRIX" -o "$OSTYPE" = "IRIX64"; then + AMFLAGS=$AMFLAGS" --include-deps"; +fi + +echo "Running aclocal" +aclocal +echo "Running automake" +automake $AMFLAGS +echo "Running autoconf" +autoconf + +echo "======================================" +echo "Now you are ready to run './configure'" +echo "======================================" diff --git a/demos/p-guide/configure.in b/demos/p-guide/configure.in new file mode 100644 index 0000000..4b065f2 --- /dev/null +++ b/demos/p-guide/configure.in @@ -0,0 +1,162 @@ +dnl Process this file with autoconf to produce a configure script. + +AC_INIT(src/pGuide.cxx) +AM_INIT_AUTOMAKE(pguide, 0.0.1) + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_CPP +AC_PROG_CXX +AC_PROG_CXXCPP +AC_PROG_INSTALL + +plib_suffix="-lplibpu -lplibfnt -lplibsg -lplibul" + +AC_LANG_CPLUSPLUS + + +dnl Command line arguments. + +dnl Don't use AC_HELP_STRING here as old versions of autoconf do not +dnl understand it. +AC_ARG_WITH(GL, +[ --with-GL=DIR set the prefix directory where GL resides], +GL_PREFIX=$withval, GL_PREFIX=auto) + +if test "x$GL_PREFIX" != "xauto"; then + LDFLAGS="$LDFLAGS -L$GL_PREFIX/lib" + CPPFLAGS="$CPPFLAGS -I$GL_PREFIX/include" +fi + + +dnl Checks for library functions. +dnl check for OpenGL related libraries + +AC_CANONICAL_HOST + +case "${host}" in +*-*-cygwin* | *-*-mingw32*) + dnl CygWin under Windoze. + + dnl OpenGL libraries + LIBS="$LIBS -lwinmm -lglut32 -lglu32 -lopengl32 -luser32 -lgdi32" + ;; +*-apple-darwin*) + dnl Mac OS X + + LIBS="$LIBS -framework GLUT -lobjc -framework OpenGL" + ;; +*) + dnl Check for X11 + + AC_PATH_XTRA + + LDFLAGS="$LDFLAGS $X_LIBS" + + LIBS="$LIBS $X_PRE_LIBS -lXi -lXmu -lXext -lX11 $X_EXTRA_LIBS -lm" + +dnl ========================================================= +dnl if test "x$x_includes" != "x"; then +dnl CPPFLAGS="$CPPFLAGS -I$x_includes" +dnl fi +dnl ========================================================= + + dnl Reasonable stuff non-windoze variants ... :-) + + AC_CHECK_LIB(GL, glNewList) + if test "x$ac_cv_lib_GL_glNewList" = "xno" ; then + dnl if no GL, check for MesaGL + AC_CHECK_LIB(MesaGL, glNewList,, + AC_MSG_ERROR([could not find working GL library])) + fi + + AC_CHECK_LIB(GLU, gluLookAt) + if test "x$ac_cv_lib_GLU_gluLookAt" = "xno" ; then + dnl if no GLU, check for MesaGLU + AC_CHECK_LIB(MesaGLU, gluLookAt,, + AC_MSG_ERROR([could not find working GLU library])) + fi + + dnl check for glut...or freeglut + AC_CHECK_LIB(freeglut, glutGetModifiers) + if test "x$ac_cv_lib_freeglut_glutGetModifiers" = "xno" ; then + dnl if no freeglut, check for Real GLUT + AC_CHECK_LIB(glut, glutGetModifiers,, + AC_MSG_ERROR([could not find working GLUT library])) + fi + + AC_CHECK_LIB(dl, dlclose) + ;; +esac + +dnl Check PLIB library +AC_CHECK_LIB(plibul, ulInit, true, +AC_MSG_ERROR([there seems to be a problem with the PLIB libraries])) + +LIBS="$plib_suffix $LIBS" + + +dnl Checks for header files. + +AC_HEADER_STDC +AC_CHECK_HEADER(windows.h, AC_DEFINE(WIN32)) + +case "${host}" in +*-*-cygwin* | *-*-mingw32*) + dnl CygWin under Windoze. + + AC_CHECK_HEADERS(GL/gl.h GL/glu.h,, + AC_MSG_ERROR([OpenGL header files not found])) + + AC_CHECK_HEADER(GL/glut.h, AC_DEFINE(GLUT_IS_PRESENT), + AC_MSG_ERROR([GLUT header file not found])) + ;; +*-apple-darwin*) + dnl Mac OS X + + AC_CHECK_HEADERS(OpenGL/gl.h OpenGL/glu.h,, + AC_MSG_ERROR([OpenGL header files not found])) + + AC_CHECK_HEADER(GLUT/glut.h, AC_DEFINE(GLUT_IS_PRESENT), + AC_MSG_ERROR([GLUT header file not found])) + ;; +*) + AC_CHECK_HEADERS(GL/gl.h GL/glu.h,, + AC_MSG_ERROR([OpenGL header files not found])) + + if test "x$ac_cv_lib_freeglut_glutGetModifiers" = "xyes"; then + AC_CHECK_HEADER(GL/freeglut.h, AC_DEFINE(FREEGLUT_IS_PRESENT), + AC_MSG_ERROR([freeglut header file not found])) + else + AC_CHECK_HEADER(GL/glut.h, AC_DEFINE(GLUT_IS_PRESENT), + AC_MSG_ERROR([GLUT header file not found])) + fi + ;; +esac + +AC_CHECK_HEADER(plib/ul.h,, AC_MSG_ERROR([PLIB header files not found])) + + +dnl Warning flags +WFLAG="-Wall" +case "$host" in +mips-sgi-irix*) + if test "x$CXX" = "xCC"; then + WFLAG="-fullwarn"; + fi + ;; +*) + if test "x$CXX" = "xicpc" || test "x$CXX" = "xicc"; then + WFLAG="-w1" + fi + ;; +esac + +CFLAGS="$CFLAGS $WFLAG" +CXXFLAGS="$CXXFLAGS $WFLAG" + + +AC_OUTPUT( Makefile \ + src/Makefile \ + ) + diff --git a/demos/p-guide/doc/p-guide.html b/demos/p-guide/doc/p-guide.html new file mode 100644 index 0000000..07d0bfe --- /dev/null +++ b/demos/p-guide/doc/p-guide.html @@ -0,0 +1,146 @@ + + + + + + + PUI-Based GUI Designer (P-GUIDE) Documentation + + + +

+P-GUIDE Documentation

+ +

+PUI-Based Graphical User Interface Designer

+P-GUIDE comes up in three OpenGL windows.  The first window is the +Main window in which the user arranges the widgets of his graphical user +interface.  The second window is the Widget window which contains +one button for each PUI widget class.  The third window is the Status +window which allows the user to see and control various widget and window +parameters in the main window. +
The basic concept of P-GUIDE is that the user will click on a button +in the Widget window and then click in the Main window to create a widget +for his GUI.  He will then use the Status window to modify the settings +of that widget.  The Main window reflects the changes he makes in +real time.  When the user has created as many widgets as he likes, +he clicks on the "Write Window Code" button in the Status window and P-GUIDE +will write a file of C++ code which implements the GUI using OpenGL, GLUT, +and PUI. +
P-GUIDE is offered to the PLIB community under a GNU Public License +(GPL).  Users are free to modify the source code as they see fit but +must offer their changes back to the community. +

+GUI Window Control

+The user may size, position, color, and name his window by using the input +box widgets at the top of the Status window.  All the changes except +the window position are reflected immediately in the Main window. +
The user may also change the size of his window by clicking on an edge +of the window and dragging on it.  Any widgets which the user has +already defined and placed in the window will remain stationary while the +window is being resized; this means that if the user drags the left-hand +edge of the window to change its width, the x-coordinates of the widgets +will change.  (The user is cautioned against moving his mouse off +one side of the window, dragging it around the outside of the window, and +clicking on the opposite side of the window from the outside.  Due +to a limitation in the windowing system this will reposition the widgets +in the window incorrectly.) +

+Placing Widgets

+To place a widget in the GUI, the user clicks on that widget's button in +the Widget window and then clicks in the Main window.  The new widget +will be placed in the Main window with its lower left-hand corner at the +mouse position.  The widget will have an initial size of 90 pixels +wide by 20 pixels high. +
If the user wants to place more than one widget of the same type in +his GUI, he can press the Control key when he clicks on that widget's button +in the Widget window.  He will then click in the Main window once +for each widget of the given type that he wants to create.  Pressing +the Escape key or clicking on another widget's button in the Widget window +will deactivate the button. +
A widget which has just been placed or has just been clicked on by +the mouse is called the Active widget.  It is surrounded by a black +line. +

+Widget Settings

+The user can control the following settings of his widget from controls +in the Status window: +
    +
  • +Name (the name of the variable which is the pointer to the widget in the +program)
  • + +
  • +Position
  • + +
  • +Size
  • + +
  • +Legend text and position
  • + +
  • +Label text and position
  • + +
  • +Callbacks
  • +
+ +The user may also modify the size and position of his widgets directly +in the Main window.  To change the size, he clicks inside the widget +within five pixels of the edge and then drags the mouse to extend the widget.  +To change the position he clicks inside the widget away from the edges +and drags the mouse. +
The user may also move the Active widget one pixel at a time by pressing +the four arrow keys.  Holding the Control key while pressing the arrow +keys will move the Active widget ten pixels at a time. +

+Widget Visibility

+There are obviously times when the user will want to draw more than one +widget in the same place in the GUI and only show them one at a time.  +To allow this capability the Status window has a button box which controls +whether the widget in the Main window is visible or not.  To hide +a widget the user simply clicks on the "Visible" button box.  If he +then clicks on the "Visible" button box again the Active widget will reappear.  +If the user selects another Active widget, there is no simple and direct +way to make the single hidden widget reappear in the main window. +
To allow the user to make widgets reappear, the Status window has a +one-shot button labelled "Reveal All Widgets".  This makes all the +widgets in the Main window visible again.  The user can then select +the widgets he wishes to hide again and make them invisible. +
When the program writes the C++ code to create the GUI, the widgets +which are not visible in the Main window are hidden by default. +

+Widget Layers

+Many times the order in which widgets are drawn is of vital importance.  +For example, the user may want to fill a window with a frame widget to +provide a pleasing background for the actual widgets of the GUI.  +In order to allow this the program assigns each widget in the Main window +a layer number.  These layer numbers start at zero and increase.  +When the Main window is being drawn, the widgets in lower-numbered layers +are drawn first and the widgets with larger layer numbers are drawn after +(and therefore on top of) them.  When the C++ code to create the GUI +is being written, the widgets in the lower-numbered layers are created +first. +

+Program Controls

+Basic program control is provided by the three buttons at the bottom of +the Status window.  Clicking on the "Write Window Code" button will +cause a file selector widget to pop up for the user to enter a file name +into which the code is to be written.  An entire file is written which +contains the necessary include, window data, a default font definition, +widget variable definitions, GLUT window callbacks, widget callbacks for +each widget, and a complete main program that creates and manages the GLUT +window, initializes PUI, creates the widgets, and calls the GLUT main loop.  +(At the moment the widget definition calls are somewhat lacking and the +user will need to modify them before he can compile the code.) +
If the user clicks on the "Clear" button, all the widgets in the Main +window will be erased.  If the user has changed the window at all +since the last time he wrote code or cleared the Main window, the program +will pop up a box asking if he is sure. +
If the user clicks on the "Quit" button, the program will stop.  +Again, if there have been changes since the last code writing or clearing, +the program will ask if he is sure. + + + diff --git a/demos/p-guide/pGuide.dsw b/demos/p-guide/pGuide.dsw new file mode 100644 index 0000000..b798382 --- /dev/null +++ b/demos/p-guide/pGuide.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "pGuide"=.\src\pGuide.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/demos/p-guide/src/LoadSave.cxx b/demos/p-guide/src/LoadSave.cxx new file mode 100644 index 0000000..6e88ecb --- /dev/null +++ b/demos/p-guide/src/LoadSave.cxx @@ -0,0 +1,756 @@ +/* + This file is part of P-GUIDE - + PUI-based Graphical User Interface Designer. + Copyright (C) 2002, 2006 John F. Fay + + P-GUIDE 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. + + P-GUIDE 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 P-GUIDE; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + $Id: LoadSave.cxx 2100 2006-11-03 22:31:54Z fayjf $ +*/ + + +#include + +#include "WidgetList.h" + +#define TAG_SAVEFILE 0x00000001 +#define TAG_WINDOW 0x00000002 +#define TAG_OBJECT 0x00000004 +#define TAG_WIDGET 0x00000008 +#define TAG_SIZE 0x00000010 +#define TAG_POSITION 0x00000020 +#define TAG_COLOR 0x00000040 +#define TAG_LEGEND 0x00000080 +#define TAG_LABEL 0x00000100 +#define TAG_DATA 0x00000120 + +#define CALLBACK_UP 0x00000001 +#define CALLBACK_ACTIVE 0x00000002 +#define CALLBACK_DOWN 0x00000004 + +#ifdef WIN32 + #define PATH_SEPARATOR '\\' +#else + #define PATH_SEPARATOR '/' +#endif + +// From the Main Window: + +extern WidgetList *widgets ; +extern int max_layer ; + +extern int main_window_width ; +extern int main_window_height ; + +extern char main_window_name [ PUSTRING_MAX ] ; + +extern int main_window_x ; +extern int main_window_y ; + +extern int widget_number ; + +extern bool main_window_changed ; +extern bool currently_loading ; /* Var for the Reshape function to not do its thing */ +extern char pguide_current_directory [ PUSTRING_MAX ] ; + +extern bool autolock ; + + +extern float main_window_color_r, main_window_color_g, + main_window_color_b, main_window_color_a ; + +// From the Status Window + +extern void setStatusWidgets ( WidgetList *wid ); +extern int status_window ; +extern int main_window ; +extern puaFileSelector *file_selector ; + +// Duplication checking +static void chk_dupname ( WidgetList *new_wid ) ; +static puInput *dup_newname = (puInput *)NULL ; +static puDialogBox *dup_dialog = (puDialogBox *)NULL ; +static WidgetList *nextwid ; + +// Now our turn + +void saveProject ( puObject *ob ) { + char* filename ; + file_selector -> getValue ( &filename ) ; + if (filename[0] == '\0') + { + puDeleteObject ( file_selector ) ; + file_selector = (puaFileSelector *)NULL ; + glutHideWindow () ; + glutSetWindow ( status_window ) ; + return ; + } + + /* Save the new current directory */ + strcpy(pguide_current_directory, filename) ; + int i = strlen(pguide_current_directory); + while (pguide_current_directory[i] != PATH_SEPARATOR) { + if (i>0) i-- ; + else break ; + } + pguide_current_directory[i+1] = '\0' ; + + /* If they didn't give an extension, then tack ".xml" onto the end. */ + if(!strstr(filename, ".")) + sprintf(filename, "%s.xml", filename); + + FILE *out = fopen ( filename, "wt" ) ; + if ( !out ) + printf ( "ERROR opening file <%s> for writing\n", filename ) ; + + puDeleteObject ( file_selector ) ; + file_selector = (puaFileSelector *)NULL ; + glutHideWindow () ; + glutSetWindow ( status_window ) ; + + if ( !out ) return ; + + /* Begin writing the XML */ + + const char *autolock_text; + + if ( !autolock ) + autolock_text="FALSE"; + else + autolock_text="TRUE"; + + char projectname [] = "Test Project"; + + fprintf ( out, "\n\n\n\n" ) ; + fprintf ( out, "VERSION\n") ; + fprintf ( out, "%s\n", projectname) ; + fprintf ( out, "%s\n", autolock_text) ; + fprintf ( out, "\n\t%s\n", main_window_name) ; + fprintf ( out, "\t\n\t\t%d\n", main_window_width) ; + fprintf ( out, "\t\t%d\n\t\n", main_window_height) ; + fprintf ( out, "\t\n\t\t%d\n", main_window_x) ; + fprintf ( out, "\t\t%d\n\t\n", main_window_y) ; + fprintf ( out, "\t\n\t\t%f\n\t\t%f\n\t\t%f\n", main_window_color_r, main_window_color_g, main_window_color_b) ; + fprintf ( out, "\t\t%f\n\t\n\n\n", main_window_color_a) ; + fprintf ( out, "\n") ; + /* Now begin spitting out the actual widget data. */ + + WidgetList *wid = widgets ; + const char *place_name [] = { "PUPLACE_TOP_LEFT", "PUPLACE_TOP_CENTERED", "PUPLACE_TOP_RIGHT", + "PUPLACE_CENTERED_LEFT", "PUPLACE_CENTERED_RIGHT", + "PUPLACE_BOTTOM_LEFT", "PUPLACE_BOTTOM_CENTERED", "PUPLACE_BOTTOM_RIGHT", + "PUPLACE_CENTERED_CENTERED", + "PUPLACE_ABOVE_LEFT", "PUPLACE_ABOVE_RIGHT", + "PUPLACE_BELOW_LEFT", "PUPLACE_BELOW_RIGHT", + "PUPLACE_UPPER_LEFT", "PUPLACE_UPPER_RIGHT", + "PUPLACE_LOWER_LEFT", "PUPLACE_LOWER_RIGHT" } ; + + + while ( wid ) + { + puObject *obj = wid->obj ; + int x, y, w, h ; + const char *hidden ; + const char *locked ; + const char *bool_one ; + const char *bool_two ; + const char *bool_three ; + obj->getPosition ( &x, &y ) ; + obj->getSize ( &w, &h ) ; + + fprintf ( out, "\t\n\t\t%s\n", wid->object_name) ; + if (wid->legend_text != NULL) + fprintf ( out, "\t\t\n\t\t\t%s\n\t\t\t%s\n\t\t\n", wid->legend_text, place_name [ obj->getLegendPlace () ] ) ; + + if (wid->label_text != NULL) + fprintf ( out, "\t\t\n", wid->label_text, place_name [ obj->getLabelPlace () ] ) ; + + fprintf ( out, "\t\t%s\n", wid->object_type_name) ; + + if ( !wid->visible ) + hidden="FALSE"; + else + hidden="TRUE"; + + if ( !wid->locked ) + locked="FALSE"; + else + locked="TRUE"; + + if ( wid->callbacks & CALLBACK_UP ) // Up-callback defined + fprintf ( out, "\t\tUp\n") ; + if ( wid->callbacks & CALLBACK_ACTIVE ) // Active callback defined + fprintf ( out, "\t\tActive\n") ; + if ( wid->callbacks & CALLBACK_DOWN ) // Down-callback defined + fprintf ( out, "\t\tDown\n") ; + if ( wid->callbacks == 0 ) + fprintf ( out, "\t\t\n") ; + + fprintf ( out, "\t\t%d\n", wid->layer) ; + + fprintf ( out, "\t\t%s\n", hidden) ; + fprintf ( out, "\t\t%s\n", locked) ; + fprintf ( out, "\t\t\n\t\t\t%d\n\t\t\t%d\n\t\t\n", w, h) ; + fprintf ( out, "\t\t\n\t\t\t%d\n\t\t\t%d\n\t\t\n", x, y) ; + + fprintf ( out, "\t\t\n\t\t\t%d\n\t\t\t%d\n", wid->intval1, wid->intval2) ; + if ( wid->boolval1 ) + bool_one = "TRUE"; + else + bool_one = "FALSE"; + + if ( wid->boolval2 ) + bool_two = "TRUE"; + else + bool_two = "FALSE"; + + if ( wid->boolval3 ) + bool_three = "TRUE"; + else + bool_three = "FALSE"; + + fprintf ( out, "\t\t\t%s\n\t\t\t%s\n\t\t\t%s\n", bool_one, bool_two, bool_three) ; + + fprintf ( out, "\t\t\t%f\n\t\t\t%f\n", wid->floatval1, wid->floatval2) ; + fprintf ( out, "\t\t\t%f\n\t\t\t%f\n", wid->floatval3, wid->floatval4) ; + fprintf ( out, "\t\t\t%f\n\t\t\t%f\n", wid->floatval5, wid->floatval6) ; + + if (wid->allowed) + fprintf ( out, "\t\t\t%s\n", wid->allowed) ; + + /* Walk through the list of items, and make a seperate entry for each line in the string */ + if (wid->items) + { + char *temp_items = wid->items ; + char *cr = strchr(temp_items, '\n'); + while ( cr != '\0' ) + { + *cr = '\0'; + fprintf ( out, "\t\t\t%s\n", temp_items); + *cr = '\n'; + temp_items = cr + 1; + cr = strchr(temp_items, '\n'); + } + if (wid->object_type == PUCLASS_ARROW) + { + fprintf ( out, "\t\t\t%s\n", temp_items); + } + } + + fprintf ( out, "\t\t\n\t\n") ; + wid = wid->next ; + } + + fprintf ( out, "\n\n") ; /* XML output done */ + fclose (out) ; +} + +/*static void gotoNextLine( char* buffer ) +{ + while (buffer != "\n") + buffer++ ; +}*/ + +void loadProject ( puObject *ob ) { + extern puInput *window_name ; + extern puInput *window_size_x ; + extern puInput *window_size_y ; + extern puInput *window_position_x ; + extern puInput *window_position_y ; + + extern puaSpinBox *window_color_r ; + extern puaSpinBox *window_color_g ; + extern puaSpinBox *window_color_b ; + extern puaSpinBox *window_color_a ; + + char* filename ; + file_selector -> getValue ( &filename ) ; + if (filename[0] == '\0') + { + puDeleteObject ( file_selector ) ; + file_selector = (puaFileSelector *)NULL ; + glutHideWindow () ; + glutSetWindow ( status_window ) ; + return ; + } + + /* Save the new current directory */ + strcpy(pguide_current_directory, filename) ; + int i = strlen(pguide_current_directory); + while (pguide_current_directory[i] != PATH_SEPARATOR) { + if (i>0) i-- ; + else break ; + } + pguide_current_directory[i+1] = '\0' ; + + FILE *in = fopen ( filename, "rt" ) ; + if ( !in ) + printf ( "ERROR opening file <%s> for reading\n", filename ) ; + + puDeleteObject ( file_selector ) ; + file_selector = (puaFileSelector *)NULL ; + glutHideWindow () ; + glutSetWindow ( status_window ) ; + + if ( !in ) return ; + + char rawbuffer[2048]; + // Verify file is XML + + float tver = 0.0f ; + char encversion[PUSTRING_MAX]; + fgets( rawbuffer, sizeof(rawbuffer), in) ; + sscanf(rawbuffer,"", &tver, encversion) ; + if (!tver) { + printf ("File does not contain proper XML headings.\n"); + return ; + } + + // Verify file is P-Guide + char tag[PUSTRING_MAX] ; + char tagvalue[PUSTRING_MAX] ; + fgets( rawbuffer, sizeof(rawbuffer), in) ; + + if (!sscanf(rawbuffer,"", tag)) { + printf ("File, though XML, does not contain P-Guide information (or has damaged header information).\n"); + return ; + } + + // Start reading XML + main_window_changed = true ; + currently_loading = true ; + int groupid = 0 ; + puObject *new_obj = NULL; + WidgetList *new_wid = NULL ; + /* Dandy little variables */ + int wid_val_y = 0, wid_val_x = 0, val_object_width = 20, val_object_height = 20, val_label_place = 4, val_legend_place = 8; + int intval1 = 0, intval2 = 0 ; + bool boolval1 = false, boolval2 = false, boolval3 = false ; + float floatval1 = 0.0f, floatval2 = 0.0f, floatval3 = 0.0f, floatval4 = 0.0f, floatval5 = 0.0f, floatval6 = 0.0f; + + while(fgets( rawbuffer, sizeof(rawbuffer), in)) + { + /**************************************************************/ + /* Key for Groups in our XML file located at top of this file */ + /**************************************************************/ + + *tag = '\0'; + *tagvalue = '\0'; + char *buffer = rawbuffer; + + /* From here on we walk, line by line, through the XML and parse any tags we come to. */ + while (*buffer == '\t' || *buffer == ' ') /* Ignore the tabs and spaces */ + buffer++ ; + sscanf(buffer,"<%[^>]>", tag); /* Get the tag */ + + while (*buffer !='>') buffer++; + + sscanf(buffer,">%[a-zA-Z_!@#$^&*0123456789-+/\\{}()=~`,. ]setValue(tagvalue) ; + strcpy(main_window_name, tagvalue); + } + if (groupid & TAG_SIZE) + { + if ( strstr(tag,"width") ) + window_size_x->setValue(tagvalue) ; + if ( strstr(tag,"height") ) + window_size_y->setValue(tagvalue) ; + } + if (groupid & TAG_POSITION) + { + if ( strstr(tag,"x") ) + window_position_x->setValue(tagvalue) ; + if ( strstr(tag,"y") ) + window_position_y->setValue(tagvalue) ; + } + if (groupid & TAG_COLOR) + { + if ( strstr(tag,"r") ) + window_color_r->setValue(tagvalue) ; + if ( strstr(tag,"g") ) + window_color_g->setValue(tagvalue) ; + if ( strstr(tag,"b") ) + window_color_b->setValue(tagvalue) ; + if ( strstr(tag,"a") ) + window_color_a->setValue(tagvalue) ; + } + } + if (groupid & TAG_OBJECT) + { + if ( strstr(tag,"/widget") ) + { + extern WidgetList *widgets ; + /* Create a new frame in the viewing window (for manipulation). */ + new_obj = new puFrame ( 0, 0, val_object_width, val_object_height ) ; + new_obj->setWindow( main_window ) ; + /* Set the representative widget's position */ + new_obj->setPosition ( wid_val_x, wid_val_y ) ; + new_obj->setLegend ( new_wid->object_type_name ) ; + new_obj->setLegendPlace ( val_legend_place ) ; + if (new_wid->label_text) + { + new_obj->setLabel ( new_wid->label_text ) ; + new_obj->setLabelPlace ( val_label_place ) ; /**/ + } + + new_wid->boolval1 = boolval1; + new_wid->boolval2 = boolval2; + new_wid->boolval3 = boolval3; + new_wid->intval1 = intval1; + new_wid->intval2 = intval2; + new_wid->floatval1 = floatval1; + new_wid->floatval2 = floatval2; + new_wid->floatval3 = floatval3; + new_wid->floatval4 = floatval4; + new_wid->floatval5 = floatval5; + new_wid->floatval6 = floatval6; + + intval1 = intval2 = 0 ; + boolval1 = boolval2 = boolval3 = false ; + floatval1 = floatval2 = floatval3 = floatval4 = floatval5 = floatval6 = 0.0f; + new_wid->obj = new_obj ; + new_wid->next = widgets ; + widgets = new_wid ; + + } else if ( strstr(tag,"widget") ) { + /* Add the new object to the list of widgets (for the builder itself) */ + new_wid = new WidgetList ; + + /* Set those dandy variables */ + wid_val_y = 0; wid_val_x = 0; + val_object_width = 20; val_object_height = 20; + val_label_place = 4; val_legend_place = 8; + new_wid->callbacks = 0; + new_wid->allowed = (char *)NULL ; + new_wid->items = (char *)NULL ; + new_wid->locked = false; + new_wid->legend_text = NULL ; + new_wid->label_text = NULL ; + } + + + if (groupid & TAG_WIDGET) + { + if ( strstr(tag,"name") ) + { + strcpy(new_wid->object_name, tagvalue) ; + /* As names are copied, look for defaults (widget0..9999), */ + /* and if it's higher than the current widget_number, set */ + /* widget_number to it. */ + int tmp_wid_num = 0; + sscanf(tagvalue, "widget%d", &tmp_wid_num) ; + if (tmp_wid_num >= widget_number) widget_number = tmp_wid_num + 1; + } + if ( strstr(tag,"type") ) + { + new_wid->object_type = 0 ; + new_wid->object_type_name = new char [strlen(tagvalue)+1] ; + strcpy(new_wid->object_type_name, tagvalue) ; + /* BEWARE: Popup[menu], BiSlider[WithEnds], and Button[box] want to be each other! Don't let them! */ + + if ( strstr(new_wid->object_type_name, "puaList")) new_wid->object_type |= PUCLASS_LIST ; + if ( strstr(new_wid->object_type_name, "puaChooser")) new_wid->object_type |= PUCLASS_CHOOSER ; + if ( strstr(new_wid->object_type_name, "puaSliderWithInput")) new_wid->object_type |= PUCLASS_SLIDERWITHINPUT ; + if ( strstr(new_wid->object_type_name, "puaBiSliderWithEnds")) new_wid->object_type |= PUCLASS_BISLIDERWITHENDS ; + else if ( strstr(new_wid->object_type_name, "puaBiSlider")) new_wid->object_type |= PUCLASS_BISLIDER ; + if ( strstr(new_wid->object_type_name, "puaScrollBar")) new_wid->object_type |= PUCLASS_SCROLLBAR ; + if ( strstr(new_wid->object_type_name, "puaSpinBox")) new_wid->object_type |= PUCLASS_SPINBOX ; /**/ + if ( strstr(new_wid->object_type_name, "puaSelectBox")) new_wid->object_type |= PUCLASS_SELECTBOX ; + if ( strstr(new_wid->object_type_name, "puaComboBox")) new_wid->object_type |= PUCLASS_COMBOBOX ; + if ( strstr(new_wid->object_type_name, "puaLargeInput")) new_wid->object_type |= PUCLASS_LARGEINPUT ; + if ( strstr(new_wid->object_type_name, "puaVerticalMenu")) new_wid->object_type |= PUCLASS_VERTMENU ; + if ( strstr(new_wid->object_type_name, "puaTriSlider")) new_wid->object_type |= PUCLASS_TRISLIDER ; + if ( strstr(new_wid->object_type_name, "puaFileSelector")) new_wid->object_type |= PUCLASS_FILESELECTOR ; + if ( strstr(new_wid->object_type_name, "puDial")) new_wid->object_type |= PUCLASS_DIAL ; + if ( strstr(new_wid->object_type_name, "puListBox")) new_wid->object_type |= PUCLASS_LISTBOX ; + if ( strstr(new_wid->object_type_name, "puArrowButton")) new_wid->object_type |= PUCLASS_ARROW ; + if ( strstr(new_wid->object_type_name, "puDialogBox")) new_wid->object_type |= PUCLASS_DIALOGBOX ; /**/ + if ( strstr(new_wid->object_type_name, "puSlider")) new_wid->object_type |= PUCLASS_SLIDER ; + if ( strstr(new_wid->object_type_name, "puButtonBox")) new_wid->object_type |= PUCLASS_BUTTONBOX ; + else if ( strstr(new_wid->object_type_name, "puButton")) new_wid->object_type |= PUCLASS_BUTTON ; /* See above for why the elses' */ + if ( strstr(new_wid->object_type_name, "puInput")) new_wid->object_type |= PUCLASS_INPUT ; + if ( strstr(new_wid->object_type_name, "puMenuBar")) new_wid->object_type |= PUCLASS_MENUBAR ; + if ( strstr(new_wid->object_type_name, "puPopupMenu")) new_wid->object_type |= PUCLASS_POPUPMENU ; /**/ + else if ( strstr(new_wid->object_type_name, "puPopup")) new_wid->object_type |= PUCLASS_POPUP ; /**/ + if ( strstr(new_wid->object_type_name, "puOneShot")) new_wid->object_type |= PUCLASS_ONESHOT ; + if ( strstr(new_wid->object_type_name, "puText")) new_wid->object_type |= PUCLASS_TEXT ; + if ( strstr(new_wid->object_type_name, "puFrame")) new_wid->object_type |= PUCLASS_FRAME ; + } + if ( strstr(tag,"callbacks") ) + { + /* Update callback's bit set */ + if (strstr(tagvalue, "Up")) new_wid->callbacks |= CALLBACK_UP ; + if (strstr(tagvalue, "Down")) new_wid->callbacks |= CALLBACK_DOWN ; + if (strstr(tagvalue, "Active")) new_wid->callbacks |= CALLBACK_ACTIVE ; + } + if ( strstr(tag,"layer") ) + { + new_wid->layer = atoi(tagvalue) ; + if ( max_layer <= new_wid->layer ) max_layer = new_wid->layer + 1 ; + } + if ( strstr(tag,"visible") ) + { + if (strstr(tagvalue, "TRUE")) + new_wid->visible = true ; + else + new_wid->visible = false ; + } + if ( strstr(tag,"locked") ) + { + if (strstr(tagvalue, "TRUE")) + new_wid->locked = true ; + else + new_wid->locked = false ; + } + if (groupid & TAG_LEGEND) + { + if ( strstr(tag,"text") ) + { + delete new_wid->legend_text; + new_wid->legend_text = new char [strlen(tagvalue)+1] ; + strcpy(new_wid->legend_text, tagvalue) ; + } + if ( strstr(tag,"pos") ) + { + if (strstr(tagvalue, "PUPLACE_TOP_LEFT")) val_legend_place = PUPLACE_TOP_LEFT ; + if (strstr(tagvalue, "PUPLACE_TOP_CENTERED")) val_legend_place = PUPLACE_TOP_CENTERED ; + if (strstr(tagvalue, "PUPLACE_TOP_RIGHT")) val_legend_place = PUPLACE_TOP_RIGHT ; + if (strstr(tagvalue, "PUPLACE_CENTERED_LEFT")) val_legend_place = PUPLACE_CENTERED_LEFT ; + if (strstr(tagvalue, "PUPLACE_CENTERED_RIGHT")) val_legend_place = PUPLACE_CENTERED_RIGHT ; + if (strstr(tagvalue, "PUPLACE_BOTTOM_LEFT")) val_legend_place = PUPLACE_BOTTOM_LEFT ; + if (strstr(tagvalue, "PUPLACE_BOTTOM_CENTERED")) val_legend_place = PUPLACE_BOTTOM_CENTERED ; + if (strstr(tagvalue, "PUPLACE_BOTTOM_RIGHT")) val_legend_place = PUPLACE_BOTTOM_RIGHT ; + if (strstr(tagvalue, "PUPLACE_CENTERED_CENTERED")) val_legend_place = PUPLACE_CENTERED_CENTERED ; + } + } + if (groupid & TAG_LABEL) + { + if ( strstr(tag,"text") ) + { + delete new_wid->label_text; + new_wid->label_text = new char [strlen(tagvalue)+1] ; + strcpy(new_wid->label_text, tagvalue) ; + } + if ( strstr(tag,"pos") ) + { + if (strstr(tagvalue, "PUPLACE_TOP_LEFT")) val_label_place = PUPLACE_TOP_LEFT ; + if (strstr(tagvalue, "PUPLACE_TOP_CENTERED")) val_label_place = PUPLACE_TOP_CENTERED ; + if (strstr(tagvalue, "PUPLACE_TOP_RIGHT")) val_label_place = PUPLACE_TOP_RIGHT ; + if (strstr(tagvalue, "PUPLACE_CENTERED_LEFT")) val_label_place = PUPLACE_CENTERED_LEFT ; + if (strstr(tagvalue, "PUPLACE_CENTERED_RIGHT")) val_label_place = PUPLACE_CENTERED_RIGHT ; + if (strstr(tagvalue, "PUPLACE_BOTTOM_LEFT")) val_label_place = PUPLACE_BOTTOM_LEFT ; + if (strstr(tagvalue, "PUPLACE_BOTTOM_CENTERED")) val_label_place = PUPLACE_BOTTOM_CENTERED ; + if (strstr(tagvalue, "PUPLACE_BOTTOM_RIGHT")) val_label_place = PUPLACE_BOTTOM_RIGHT ; + if (strstr(tagvalue, "PUPLACE_ABOVE_LEFT")) val_label_place = PUPLACE_ABOVE_LEFT ; + if (strstr(tagvalue, "PUPLACE_ABOVE_RIGHT")) val_label_place = PUPLACE_ABOVE_RIGHT ; + if (strstr(tagvalue, "PUPLACE_BELOW_LEFT")) val_label_place = PUPLACE_BELOW_LEFT ; + if (strstr(tagvalue, "PUPLACE_BELOW_RIGHT")) val_label_place = PUPLACE_BELOW_RIGHT ; + if (strstr(tagvalue, "PUPLACE_UPPER_LEFT")) val_label_place = PUPLACE_UPPER_LEFT ; + if (strstr(tagvalue, "PUPLACE_UPPER_RIGHT")) val_label_place = PUPLACE_UPPER_RIGHT ; + if (strstr(tagvalue, "PUPLACE_LOWER_LEFT")) val_label_place = PUPLACE_LOWER_LEFT ; + if (strstr(tagvalue, "PUPLACE_LOWER_RIGHT")) val_label_place = PUPLACE_LOWER_RIGHT ; + } + } + if (groupid & TAG_SIZE) + { + if ( strstr(tag,"width") ) + val_object_width = atoi(tagvalue) ; + if ( strstr(tag,"height") ) + val_object_height = atoi(tagvalue) ; + } + if (groupid & TAG_POSITION) + { + if ( strstr(tag,"x") ) + wid_val_x = atoi(tagvalue) ; + if ( strstr(tag,"y") ) + wid_val_y = atoi(tagvalue) ; + } + if (groupid & TAG_DATA) + { + if ( strstr(tag,"int1") ) + intval1 = atoi (tagvalue) ; + if ( strstr(tag,"int2") ) + intval2 = atoi (tagvalue) ; + if ( strstr(tag,"bool1") ) + { + if (strstr(tagvalue, "TRUE")) + boolval1 = true ; + else + boolval1 = false ; + } + if ( strstr(tag,"bool2") ) + { + if (strstr(tagvalue, "TRUE")) + boolval2 = true ; + else + boolval2 = false ; + } + if ( strstr(tag,"bool3") ) + { + if (strstr(tagvalue, "TRUE")) + boolval3 = true ; + else + boolval3 = false ; + } + if ( strstr(tag,"float1") ) + floatval1 = (float)atof (tagvalue) ; + if ( strstr(tag,"float2") ) + floatval2 = (float)atof (tagvalue) ; + if ( strstr(tag,"float3") ) + floatval3 = (float)atof (tagvalue) ; + if ( strstr(tag,"float4") ) + floatval4 = (float)atof (tagvalue) ; + if ( strstr(tag,"float5") ) + floatval5 = (float)atof (tagvalue) ; + if ( strstr(tag,"float6") ) + floatval6 = (float)atof (tagvalue) ; + + if ( strstr(tag,"allowed") ) + { + new_wid->allowed = new char [strlen(tagvalue)+1] ; + strcpy(new_wid->allowed, tagvalue) ; + } + + if ( strstr(tag,"item") ) + { + strcat(tagvalue, "\n"); + if (!new_wid->items) + { + new_wid->items = new char [1024] ; + strcpy(new_wid->items, tagvalue) ; + } + else + strcat(new_wid->items, tagvalue) ; + } + } + } + } + } + + if (strstr(tag, "/savefile")) + { + static int mouse_x ; + static int mouse_y ; + setStatusWidgets( new_wid ); + glutSetWindow ( main_window ) ; + glutSetWindowTitle ( window_name->getStringValue() ) ; + /* Fake out the Reshape parts that determine whether to move widgets around or not. */ + mouse_x = 999 ; + mouse_y = 999 ; + glutReshapeWindow ( window_size_x->getValue(), window_size_y->getValue() ) ; + glutSetWindow ( status_window ) ; + } + + buffer[0] = '\0'; + } + fclose (in); + WidgetList *wid = widgets; + /* Check name for duplication */ + nextwid = wid; /* Note: Yes, this is inelegant, but if we loop here, we end up making many copies of the same dialog box in the same memory space. This is a Bad Thing. */ + chk_dupname(nextwid); + /* Done checking name for duplication */ +} + +static void chk_dupname_ok_cb ( puObject *ob ) +{ + /* The user's new name from the dialog has already been set to the object_name*/ + /* Close dialogbox and update main window ...*/ + puDeleteObject ( dup_dialog ) ; + dup_dialog = (puDialogBox *)NULL ; + dup_newname = (puInput *)NULL ; + /*but force a recheck afterwards to ensure it's an okay substitution. */ + nextwid = nextwid->next ; + chk_dupname(nextwid); +} + +static void chk_dupname ( WidgetList *new_wid ) +{ + if (!new_wid) + return; + WidgetList *wid = widgets ; + while ( wid ) + { + if ( (strcmp(new_wid->object_name,wid->object_name) == 0) && (new_wid != wid) ) + { + /* Popup a dialog telling user something's bad! */ + dup_dialog = new puDialogBox ( 20, 20 ) ; + new puFrame ( 0, 0, 460, 120 ) ; + puText *text = new puText ( 80, 85 ) ; + text->setLabel ( "ERROR: Name already used." ) ; + text->setLabelFont(PUFONT_TIMES_ROMAN_24); + puText *directions = new puText ( 90, 65 ) ; + directions->setLabel ( "Please type in a new, unique name to continue." ) ; + directions->setLabelFont(PUFONT_HELVETICA_12); + dup_newname = new puInput (20,40,440,60) ; + dup_newname->setValuator(new_wid->object_name); + dup_newname->setValidData("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_012345679"); + puOneShot *ok = new puOneShot ( 200, 10, "Accept" ) ; + ok->setCallback ( chk_dupname_ok_cb ) ; + dup_dialog->close () ; + dup_dialog->reveal () ; + break ; + } + wid = wid->next ; + } +} + + diff --git a/demos/p-guide/src/Makefile.am b/demos/p-guide/src/Makefile.am new file mode 100644 index 0000000..ecc73d2 --- /dev/null +++ b/demos/p-guide/src/Makefile.am @@ -0,0 +1,9 @@ +bin_PROGRAMS = pguide + +pguide_SOURCES = pGuide.cxx StatusWindow.cxx WidgetList.h \ + WidgetWindow.cxx WriteCode.cxx LoadSave.cxx PropertiesWindow.cxx + +pguide_LDADD = -lplibpuaux + +EXTRA_DIST = pGuide.dsp + diff --git a/demos/p-guide/src/PropertiesWindow.cxx b/demos/p-guide/src/PropertiesWindow.cxx new file mode 100644 index 0000000..ac4a5e3 --- /dev/null +++ b/demos/p-guide/src/PropertiesWindow.cxx @@ -0,0 +1,610 @@ +/* + This file is part of P-GUIDE - + PUI-based Graphical User Interface Designer. + Copyright (C) 2002, 2006 John F. Fay + + P-GUIDE 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. + + P-GUIDE 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 P-GUIDE; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + $Id: PropertiesWindow.cxx 2100 2006-11-03 22:31:54Z fayjf $ +*/ + +// Status Window + +#include + +#include "WidgetList.h" + +// From the Main Window: + +extern int max_layer ; + +extern WidgetList *active_widget ; +extern puObject *active_object ; + +extern char pguide_current_directory [ PUSTRING_MAX ] ; + +extern bool main_window_changed ; + +// Status window parameters +int properties_window = 0 ; // Window handle +extern int main_window ; + +// Status window widgets +puGroup *properties_group ; + +// Function to set the widgets from the active object + + +// GLUT Status Window Callbacks + +static void properties_window_specialfn ( int key, int, int ) +{ + puKeyboard ( key + PU_KEY_GLUT_SPECIAL_OFFSET, PU_DOWN ) ; + + glutPostRedisplay () ; +} + +static void properties_window_keyfn ( unsigned char key, int, int ) +{ + puKeyboard ( key, PU_DOWN ) ; + + glutPostRedisplay () ; +} + +static void properties_window_motionfn ( int x, int y ) +{ + puMouse ( x, y ) ; + + glutPostRedisplay () ; +} + +static void properties_window_mousefn ( int button, int updown, int x, int y ) +{ + puMouse ( button, updown, x, y ) ; + + glutPostRedisplay () ; +} + +static void properties_window_displayfn ( void ) +{ + glutSetWindow ( properties_window ) ; + + /* Clear the screen */ + + glClearColor ( 0.1f, 0.1f, 0.1f, 1.0f ) ; + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + puDisplay () ; + + /* Update GLUT */ + + glutSwapBuffers () ; + glutPostRedisplay () ; +} + +// PUI Callback Functions: + +static void cb_properties_close (puObject *obj) +{ + /* Save the changes ... Needed? */ + if ( puActiveWidget() ) + puActiveWidget() -> invokeDownCallback () ; /* Just make sure the last widget saves ... */ + /* Delete the widgets */ + puDeleteObject( properties_group ); + /* Destroy the window */ + glutDestroyWindow( properties_window ); + properties_window = 0; + glutSetWindow( main_window ); +} + +// Data setting standard callbacks + +static void cb_items (puObject *obj) +{ + /*Set the Items*/ + if (active_widget) + { + delete active_widget->items; + active_widget->items = new char [strlen(obj->getStringValue())+1] ; + strcpy(active_widget->items, obj->getStringValue()); + } + +} + +static void cb_allowed (puObject *obj) +{ + /*Set the Allowed string*/ + if (active_widget) + { + delete active_widget->allowed; + active_widget->allowed = new char [strlen(obj->getStringValue())+1] ; + strcpy(active_widget->allowed, obj->getStringValue()); + } +} +static void cb_int1 (puObject *obj) +{ + /*Set the first integer storage value */ + if (active_widget) + active_widget->intval1 = obj->getIntegerValue(); +} +static void cb_int2 (puObject *obj) +{ + /*Set the second integer storage value */ + if (active_widget) + active_widget->intval2 = obj->getIntegerValue(); +} +static void cb_bool1 (puObject *obj) +{ + /*Set the first boolean storage value */ + if (active_widget) + { + if (obj->getIntegerValue() == 1) + active_widget->boolval1 = true ; + else + active_widget->boolval1 = false ; + } +} +static void cb_bool2 (puObject *obj) +{ + /*Set the second boolean storage value */ + if (active_widget) + { + if (obj->getIntegerValue() == 1) + active_widget->boolval2 = true ; + else + active_widget->boolval2 = false ; + } +} +static void cb_bool3 (puObject *obj) +{ + /*Set the second boolean storage value */ + if (active_widget) + { + if (obj->getIntegerValue() == 1) + active_widget->boolval3 = true ; + else + active_widget->boolval3 = false ; + } +} +static void cb_float1 (puObject *obj) +{ + /*Set the first floating storage value */ + if (active_widget) + active_widget->floatval1 = obj->getFloatValue(); +} +static void cb_float2 (puObject *obj) +{ + /*Set the first floating storage value */ + if (active_widget) + active_widget->floatval2 = obj->getFloatValue(); +} +static void cb_float3 (puObject *obj) +{ + /*Set the first floating storage value */ + if (active_widget) + active_widget->floatval3 = obj->getFloatValue(); +} +static void cb_float4 (puObject *obj) +{ + /*Set the first floating storage value */ + if (active_widget) + active_widget->floatval4 = obj->getFloatValue(); +} +static void cb_float5 (puObject *obj) +{ + /*Set the first floating storage value */ + if (active_widget) + active_widget->floatval5 = obj->getFloatValue(); +} +static void cb_float6 (puObject *obj) +{ + /*Set the first floating storage value */ + if (active_widget) + active_widget->floatval6 = obj->getFloatValue(); +} + +// Function to define the window + +int define_properties_window () +{ + properties_window = glutCreateWindow ( "Properties" ) ; + + glutPositionWindow ( 400, 200 ) ; + glutReshapeWindow ( 500, 250 ) ; + glutDisplayFunc ( properties_window_displayfn ) ; + glutKeyboardFunc ( properties_window_keyfn ) ; + glutSpecialFunc ( properties_window_specialfn ) ; + glutMotionFunc ( properties_window_motionfn ) ; + glutMouseFunc ( properties_window_mousefn ) ; + + // Set up the widgets + + properties_group = new puGroup ( 0, 0 ) ; + new puFrame ( 0, 0, 500, 250 ) ; + + puText *properties_instructions = new puText ( 250, 230 ); + properties_instructions->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_instructions->setLabel("Here are the extended options for your"); + + puText *properties_typelabel = new puText ( 250, 215 ); + properties_typelabel->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_typelabel->setLabel(active_widget->object_type_name); + + puOneShot *properties_close = new puOneShot ( 370, 10, 490, 30 ) ; + properties_close->setLegend("Accept"); + properties_close->setCallback(cb_properties_close); + + /* puStyle stuff here*/ + + /* Now customize the display based on the widget currently selected */ + if (active_widget->object_type == PUCLASS_FRAME) + { + puText *properties_nooptions = new puText (25, 100 ); + properties_nooptions->setLabelPlace(PUPLACE_CENTERED_RIGHT); + properties_nooptions->setLabel("There are no options for a puFrame."); + } if (active_widget->object_type == PUCLASS_TEXT) + { + /* Add in font properties? */ + puText *properties_nooptions = new puText (25, 100 ); + properties_nooptions->setLabelPlace(PUPLACE_CENTERED_RIGHT); + properties_nooptions->setLabel("There are no options for puText."); + } if (active_widget->object_type == PUCLASS_BUTTON) + { + puText *properties_nooptions = new puText (25, 100 ); + properties_nooptions->setLabelPlace(PUPLACE_CENTERED_RIGHT); + properties_nooptions->setLabel("There are no options for puButton."); + } if (active_widget->object_type == PUCLASS_ONESHOT) + { + puText *properties_nooptions = new puText (25, 100 ); + properties_nooptions->setLabelPlace(PUPLACE_CENTERED_RIGHT); + properties_nooptions->setLabel("There are no options for puOneShot."); + } if ( (active_widget->object_type == PUCLASS_POPUPMENU) || + (active_widget->object_type == PUCLASS_MENUBAR) || + (active_widget->object_type == PUCLASS_VERTMENU) || + (active_widget->object_type == PUCLASS_LISTBOX) || + (active_widget->object_type == PUCLASS_COMBOBOX) || + (active_widget->object_type == PUCLASS_SELECTBOX) || + (active_widget->object_type == PUCLASS_BUTTONBOX) || + (active_widget->object_type == PUCLASS_LIST) ) + { + /* List */ + puaLargeInput *properties_list_items = new puaLargeInput(10,10,300,195,0,5); + properties_list_items->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_list_items->setLabel("Enter items, each on a new line."); + properties_list_items->setValidData("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_012345679 :;.,\n"); + properties_list_items->setCallback(cb_items); + properties_list_items->setDownCallback(cb_items); + properties_list_items->setValue(active_widget->items); + + puText *properties_list_note = new puText(400,190); + properties_list_note->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_list_note->setLabel("Each line will become"); + + puText *properties_list_note2 = new puText(400,175); + properties_list_note2->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_list_note2->setLabel("a selection option."); + + } if (active_widget->object_type == PUCLASS_POPUPMENU) + { + /* Allow a list of menu items, and remember to point out these are hidden when created, and must be reveal()ed. */ + /* NOT CURRENTLY IMPLEMENTED */ + puText *properties_popupmenu_warning = new puText(400,150); + properties_popupmenu_warning->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_popupmenu_warning->setLabel("WARNING: Popup Menus are hidden by \ + default when created. You must use \ + reveal() to make them appear."); + + } if (active_widget->object_type == PUCLASS_MENUBAR) + { + /* Allow a list of menu items */ + + } if (active_widget->object_type == PUCLASS_VERTMENU) + { + /* Allow a list of menu items */ + + } if (active_widget->object_type == PUCLASS_LISTBOX) + { + /* Allow a list of items */ + + } if (active_widget->object_type == PUCLASS_COMBOBOX) + { + /* List and a setCurrentItem, and if editable */ + puaSpinBox *properties_combobox_currentitem = new puaSpinBox(320,135,480,155); + properties_combobox_currentitem->setLabel("Initial Selection:"); + properties_combobox_currentitem->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_combobox_currentitem->setMinValue(0.0f); + properties_combobox_currentitem->setMaxValue(30.0f); + properties_combobox_currentitem->setCallback(cb_int1); + properties_combobox_currentitem->setValue(active_widget->intval1); + + static char *properties_combobox_editable_callback_entries [] = { "No", "Yes", NULL } ; + puButtonBox *properties_combobox_editable = new puButtonBox(320, 50, 480, 120, properties_combobox_editable_callback_entries, TRUE); + properties_combobox_editable->setLabel("Editable?"); + properties_combobox_editable->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_combobox_editable->setCallback(cb_bool1); + properties_combobox_editable->setValue(active_widget->boolval1); + + } if (active_widget->object_type == PUCLASS_SELECTBOX) + { + /* List and a setCurrentItem */ + puaSpinBox *properties_selectbox_currentitem = new puaSpinBox(320,135,480,155); + properties_selectbox_currentitem->setLabel("Initial Selection:"); + properties_selectbox_currentitem->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_selectbox_currentitem->setMinValue(0.0f); + properties_selectbox_currentitem->setMaxValue(30.0f); + properties_selectbox_currentitem->setCallback(cb_int1); + properties_selectbox_currentitem->setValue(active_widget->intval1); + + } if (active_widget->object_type == PUCLASS_BUTTONBOX) + { + /* Allow a list of menu items, and if multiple can be selected at once */ + puText *properties_buttonbox_label = new puText(400,135); + properties_buttonbox_label->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_buttonbox_label->setLabel("Allow multiple"); + + static char *properties_buttonbox_multiselect_callback_entries [] = { "No", "Yes", NULL } ; + puButtonBox *properties_buttonbox_multiselect = new puButtonBox(320, 50, 480, 120, properties_buttonbox_multiselect_callback_entries, TRUE); + properties_buttonbox_multiselect->setLabel("selections?"); + properties_buttonbox_multiselect->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_buttonbox_multiselect->setCallback(cb_bool1); + properties_buttonbox_multiselect->setValue(active_widget->boolval1); + + } if ( (active_widget->object_type == PUCLASS_SLIDER ) || + (active_widget->object_type == PUCLASS_BISLIDER ) || + (active_widget->object_type == PUCLASS_TRISLIDER ) || + (active_widget->object_type == PUCLASS_DIAL ) || + (active_widget->object_type == PUCLASS_SPINBOX ) || + (active_widget->object_type == PUCLASS_SCROLLBAR ) || + (active_widget->object_type == PUCLASS_SLIDERWITHINPUT ) || + (active_widget->object_type == PUCLASS_BISLIDERWITHENDS )) + { + /* int minx, int miny, int sz, {TRUE|FALSE}, int width */ + puaSpinBox *properties_range_setmaxvalue = new puaSpinBox(30,150,110,170); + properties_range_setmaxvalue->setLabel("Maximum Value:"); + properties_range_setmaxvalue->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_range_setmaxvalue->setMinValue(-5000.0f); + properties_range_setmaxvalue->setMaxValue(5000.0f); + properties_range_setmaxvalue->setCallback(cb_float1); + properties_range_setmaxvalue->setValue(active_widget->floatval1); + + puaSpinBox *properties_range_setminvalue = new puaSpinBox(230,150,310,170); + properties_range_setminvalue->setLabel("Minimum Value:"); + properties_range_setminvalue->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_range_setminvalue->setMinValue(-5000.0f); + properties_range_setminvalue->setMaxValue(5000.0f); + properties_range_setminvalue->setCallback(cb_float2); + properties_range_setminvalue->setValue(active_widget->floatval2); + + puaSpinBox *properties_range_setstepvalue = new puaSpinBox(400,150,480,170); + properties_range_setstepvalue->setLabel("Step Size:"); + properties_range_setstepvalue->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_range_setstepvalue->setMinValue(0.0f); + properties_range_setstepvalue->setMaxValue(5000.0f); + properties_range_setstepvalue->setCallback(cb_float3); + properties_range_setstepvalue->setValue(active_widget->floatval3); + + static char *properties_range_cbmode_callback_entries [] = { "On Click", "Always", NULL } ; + puButtonBox *properties_range_cbmode = new puButtonBox(20, 80, 170, 130, properties_range_cbmode_callback_entries, TRUE); + properties_range_cbmode->setLabel("Callback Mode:"); + properties_range_cbmode->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_range_cbmode->setCallback(cb_bool1); + properties_range_cbmode->setValue(active_widget->boolval1); + + } if ( (active_widget->object_type == PUCLASS_SLIDER ) || + (active_widget->object_type == PUCLASS_BISLIDER ) || + (active_widget->object_type == PUCLASS_TRISLIDER ) || + (active_widget->object_type == PUCLASS_SCROLLBAR ) ) + { + static char *properties_range_vertical_callback_entries [] = { "Horizontal", "Vertical", NULL } ; + puButtonBox *properties_range_vertical = new puButtonBox(20, 10, 170, 60, properties_range_vertical_callback_entries, TRUE); + properties_range_vertical->setLabel("Orientation:"); + properties_range_vertical->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_range_vertical->setValue(active_widget->boolval2); + properties_range_vertical->setCallback(cb_bool2); + + } if (active_widget->object_type == PUCLASS_SLIDER) + { + puaSpinBox *properties_slider_value = new puaSpinBox(230,110,310,130); + properties_slider_value->setLabel("Starting Value:"); + properties_slider_value->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_slider_value->setMinValue(-5000.0f); + properties_slider_value->setMaxValue(5000.0f); + properties_slider_value->setValue(active_widget->floatval4); + properties_slider_value->setStepSize(0.1f); + properties_slider_value->setCallback(cb_float4); + + } if ((active_widget->object_type == PUCLASS_BISLIDER) || + (active_widget->object_type == PUCLASS_BISLIDERWITHENDS)) + { + puaSpinBox *properties_bislider_topvalue = new puaSpinBox(230,110,310,130); + properties_bislider_topvalue->setLabel("Top Slider Value:"); + properties_bislider_topvalue->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_bislider_topvalue->setMinValue(-5000.0f); + properties_bislider_topvalue->setMaxValue(5000.0f); + properties_bislider_topvalue->setValue(active_widget->floatval4); + properties_bislider_topvalue->setStepSize(0.1f); + properties_bislider_topvalue->setCallback(cb_float4); + + puaSpinBox *properties_bislider_botvalue = new puaSpinBox(230,40,310,60); + properties_bislider_botvalue->setLabel("Bottom Slider Value:"); + properties_bislider_botvalue->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_bislider_botvalue->setMinValue(-5000.0f); + properties_bislider_botvalue->setMaxValue(5000.0f); + properties_bislider_botvalue->setValue(active_widget->floatval5); + properties_bislider_botvalue->setStepSize(0.1f); + properties_bislider_botvalue->setCallback(cb_float5); + + } if (active_widget->object_type == PUCLASS_TRISLIDER) + { + puaSpinBox *properties_trislider_topvalue = new puaSpinBox(230,110,310,130); + properties_trislider_topvalue->setLabel("Top Slider Value:"); + properties_trislider_topvalue->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_trislider_topvalue->setMinValue(-5000.0f); + properties_trislider_topvalue->setMaxValue(5000.0f); + properties_trislider_topvalue->setValue(active_widget->floatval4); + properties_trislider_topvalue->setStepSize(0.1f); + properties_trislider_topvalue->setCallback(cb_float4); + + puaSpinBox *properties_trislider_centvalue = new puaSpinBox(230,60,310,80); + properties_trislider_centvalue->setLabel("Center Slider Value:"); + properties_trislider_centvalue->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_trislider_centvalue->setMinValue(-5000.0f); + properties_trislider_centvalue->setMaxValue(5000.0f); + properties_trislider_centvalue->setValue(active_widget->floatval6); + properties_trislider_centvalue->setStepSize(0.1f); + properties_trislider_centvalue->setCallback(cb_float6); + + puaSpinBox *properties_trislider_botvalue = new puaSpinBox(230,10,310,30); + properties_trislider_botvalue->setLabel("Bottom Slider Value:"); + properties_trislider_botvalue->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_trislider_botvalue->setMinValue(-5000.0f); + properties_trislider_botvalue->setMaxValue(5000.0f); + properties_trislider_botvalue->setValue(active_widget->floatval5); + properties_trislider_botvalue->setStepSize(0.1f); + properties_trislider_botvalue->setCallback(cb_float5); + + static char *properties_trislider_lock_callback_entries [] = { "No", "Yes", NULL } ; + puButtonBox *properties_trislider_lock = new puButtonBox(380, 80, 480, 130, properties_trislider_lock_callback_entries, TRUE); + properties_trislider_lock->setLabel("Lock End Sliders:"); + properties_trislider_lock->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_trislider_lock->setValue(active_widget->boolval3); + properties_trislider_lock->setCallback(cb_bool3); + + } if (active_widget->object_type == PUCLASS_DIAL) + { + /* Wrap Mode */ + static char *properties_dial_wrap_callback_entries [] = { "No", "Yes", NULL } ; + puButtonBox *properties_dial_wrap = new puButtonBox(20, 10, 170, 60, properties_dial_wrap_callback_entries, TRUE); + properties_dial_wrap->setLabel("Allow Dial Wrapping:"); + properties_dial_wrap->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_dial_wrap->setValue(active_widget->boolval2); + properties_dial_wrap->setCallback(cb_bool2); + + } if (active_widget->object_type == PUCLASS_SPINBOX) + { + /* Arrow position and height */ + static char *properties_spinbox_arrow_callback_entries [] = { "Left", "Right", NULL } ; + puButtonBox *properties_spinbox_arrow = new puButtonBox(20, 10, 170, 60, properties_spinbox_arrow_callback_entries, TRUE); + properties_spinbox_arrow->setLabel("Arrow Position"); + properties_spinbox_arrow->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_spinbox_arrow->setValue(active_widget->boolval2); + properties_spinbox_arrow->setCallback(cb_bool2); + + puaSpinBox *properties_spinbox_arrowheight = new puaSpinBox(230,110,310,130); + properties_spinbox_arrowheight->setLabel("Arrow Height:"); + properties_spinbox_arrowheight->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_spinbox_arrowheight->setMinValue(0.0f); + properties_spinbox_arrowheight->setMaxValue(20.0f); + properties_spinbox_arrowheight->setValue(active_widget->floatval4); + properties_spinbox_arrowheight->setStepSize(0.05f); + properties_spinbox_arrowheight->setCallback(cb_float4); + + puText *properties_spinbox_arrowextra = new puText ( 310, 90 ); + properties_spinbox_arrowextra->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_spinbox_arrowextra->setLabel("(as porportion of spinbox height)"); + + } if (active_widget->object_type == PUCLASS_DIALOGBOX) + { + /* Not yet implemented as a class */ + + } if (active_widget->object_type == PUCLASS_ARROW) + { + static char *properties_arrow_arrowtype_options [] = { "Up", "Down", "Left", "Right", + "Double-Up", "Double-Down", "Double-Left", + "Double-Right", NULL } ; + + puaComboBox *properties_arrow_arrowtype = new puaComboBox ( 120,10,310,30, properties_arrow_arrowtype_options, FALSE ) ; + properties_arrow_arrowtype->setLabel ( "Arrow Type:" ) ; + properties_arrow_arrowtype->setLabelPlace ( PUPLACE_LOWER_LEFT ) ; + properties_arrow_arrowtype->setCallback(cb_items); + + int num = 0; + + if (active_widget->items) + { + if (strstr(active_widget->items,"Double-Up")) + num = 4; + else if (strstr(active_widget->items,"Double-Down")) + num = 5; + else if (strstr(active_widget->items,"Double-Left")) + num = 6; + else if (strstr(active_widget->items,"Double-Right")) + num = 7; + else if (strstr(active_widget->items,"Up")) + num = 0; + else if (strstr(active_widget->items,"Down")) + num = 1; + else if (strstr(active_widget->items,"Left")) + num = 2; + else if (strstr(active_widget->items,"Right")) + num = 3; + } + + properties_arrow_arrowtype->setCurrentItem(num); + + } if ( (active_widget->object_type == PUCLASS_INPUT ) || + (active_widget->object_type == PUCLASS_LARGEINPUT ) ) + { + /*int minx, int miny, int maxx, int maxy */ + /* Disabled, and Valid Data list */ + puInput *properties_input_validdata = new puInput(20, 150, 260, 170); + properties_input_validdata->setLabel("Allowed Characters for Input:"); + properties_input_validdata->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_input_validdata->setCallback(cb_allowed); + properties_input_validdata->setDownCallback(cb_allowed); + properties_input_validdata->setValue(active_widget->allowed); + + static char *properties_input_enabled_callback_entries [] = { "Yes", NULL } ; + puButtonBox *properties_input_enabled = new puButtonBox(300, 140, 450, 170, properties_input_enabled_callback_entries, FALSE); + properties_input_enabled->setLabel("Input Allowed? (enabled)"); + properties_input_enabled->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_input_enabled->setValue(active_widget->boolval1); + properties_input_enabled->setCallback(cb_bool1); + + } if ((active_widget->object_type == PUCLASS_LARGEINPUT) || + (active_widget->object_type == PUCLASS_SCROLLBAR) ) + { + /*Arrows*/ + static char *properties_largeinput_arrows_callback_entries [] = { "None", "Normal", "Normal and Fast", NULL } ; + puButtonBox *properties_largeinput_arrows = new puButtonBox(20, 10, 200, 130, properties_largeinput_arrows_callback_entries, TRUE); + properties_largeinput_arrows->setLabel("Which Arrow Buttons:"); + properties_largeinput_arrows->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_largeinput_arrows->setValue(active_widget->intval1); + properties_largeinput_arrows->setCallback(cb_int1); + + } if (active_widget->object_type == PUCLASS_LARGEINPUT) + { + /*Slider Size*/ + puaSpinBox *properties_largeinput_sliderwidth = new puaSpinBox(300,90,400,110); + properties_largeinput_sliderwidth->setLabel("Slider Width:"); + properties_largeinput_sliderwidth->setLabelPlace(PUPLACE_TOP_CENTERED); + properties_largeinput_sliderwidth->setMinValue(0.0f); + properties_largeinput_sliderwidth->setMaxValue(150.0f); + properties_largeinput_sliderwidth->setValue(active_widget->intval2); + properties_largeinput_sliderwidth->setStepSize(1.0f); + properties_largeinput_sliderwidth->setCallback(cb_int2); + } + + /* TODO: + * puaSliderWithInput: is input above or below slider? + * puaList: can we add the transparency field? + */ + properties_group->close () ; + + return 0 ; +} + + + diff --git a/demos/p-guide/src/StatusWindow.cxx b/demos/p-guide/src/StatusWindow.cxx new file mode 100644 index 0000000..13f46f7 --- /dev/null +++ b/demos/p-guide/src/StatusWindow.cxx @@ -0,0 +1,1146 @@ +/* + This file is part of P-GUIDE - + PUI-based Graphical User Interface Designer. + Copyright (C) 2002, 2006 John F. Fay + + P-GUIDE 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. + + P-GUIDE 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 P-GUIDE; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + $Id: StatusWindow.cxx 2100 2006-11-03 22:31:54Z fayjf $ +*/ + +// Status Window + +#include "WidgetList.h" + +// From the Main Window: + +extern int max_layer ; + +extern WidgetList *active_widget ; +extern puObject *active_object ; + +extern char pguide_current_directory [ PUSTRING_MAX ] ; + +extern bool main_window_changed ; + +extern char main_window_name [ PUSTRING_MAX ] ; + +extern bool autolock ; + +// Status window parameters +int status_window = 0 ; // Window handle +extern int main_window ; + +// Status window widgets + +puInput *object_size_x ; +puInput *object_size_y ; +puInput *object_position_x ; +puInput *object_position_y ; + +static puFrame *widget_section_frame ; + +static puInput *object_label ; +static puaComboBox *object_vert_label_place ; +static puaComboBox *object_horz_label_place ; +static puInput *object_legend ; +static puaComboBox *object_vert_legend_place ; +static puaComboBox *object_horz_legend_place ; + +static puInput *object_name ; +static puButtonBox *object_callbacks ; + +static puFrame *layer_manipulation_frame ; +static puButtonBox *object_visible ; +static puOneShot *reveal_all_objects ; +static puOneShot *hide_all_objects ; + +static puOneShot *reveal_all_layer ; +static puOneShot *hide_all_layer ; + +static puaSpinBox *layer_to_act_on ; +static puaSpinBox *object_layer ; + +static puText *object_layer_text ; +static puFrame *layer_to_act_on_frame ; +static puFrame *layer_all_frame ; + +puInput *window_name ; +puInput *window_size_x ; +puInput *window_size_y ; +puInput *window_position_x ; +puInput *window_position_y ; + +static puText *window_color_label ; +puaSpinBox *window_color_r ; +puaSpinBox *window_color_g ; +puaSpinBox *window_color_b ; +puaSpinBox *window_color_a ; + +static puButtonBox *autolock_toggle ; + +static puDialogBox *dialog = (puDialogBox *)NULL ; +static puInput *newname = (puInput *)NULL ; + +static puMenuBar *menubar ; + +// Saving Window Parameters + +puaFileSelector *file_selector ; + +static int write_window = 0 ; + +// Extra needed prototyping +static void dupname_ok_cb ( puObject *ob ) ; + +// Function to set the widgets from the active object + +static void setHorizontalPlaceWidget ( puaComboBox *ob, int place ) +{ + switch ( place ) + { + case PUPLACE_TOP_LEFT : + case PUPLACE_ABOVE_LEFT : + case PUPLACE_UPPER_LEFT : + case PUPLACE_CENTERED_LEFT : + case PUPLACE_LOWER_LEFT : + case PUPLACE_BELOW_LEFT : + case PUPLACE_BOTTOM_LEFT : ob->setValue ( "Left" ) ; break ; + case PUPLACE_TOP_CENTERED : + case PUPLACE_CENTERED_CENTERED : + case PUPLACE_BOTTOM_CENTERED : ob->setValue ( "Center" ) ; break ; + case PUPLACE_TOP_RIGHT : + case PUPLACE_ABOVE_RIGHT : + case PUPLACE_UPPER_RIGHT : + case PUPLACE_CENTERED_RIGHT : + case PUPLACE_LOWER_RIGHT : + case PUPLACE_BELOW_RIGHT : + case PUPLACE_BOTTOM_RIGHT : ob->setValue ( "Right" ) ; break ; + } +} + +static void setVerticalPlaceWidget ( puaComboBox *ob, int place ) +{ + switch ( place ) + { + case PUPLACE_TOP_LEFT : + case PUPLACE_TOP_CENTERED : + case PUPLACE_TOP_RIGHT : ob->setValue ( "Top" ) ; break ; + case PUPLACE_ABOVE_LEFT : + case PUPLACE_ABOVE_RIGHT : ob->setValue ( "Above" ) ; break ; + case PUPLACE_UPPER_LEFT : + case PUPLACE_UPPER_RIGHT : ob->setValue ( "Upper" ) ; break ; + case PUPLACE_CENTERED_LEFT : + case PUPLACE_CENTERED_CENTERED : + case PUPLACE_CENTERED_RIGHT : ob->setValue ( "Center" ) ; break ; + case PUPLACE_LOWER_LEFT : + case PUPLACE_LOWER_RIGHT : ob->setValue ( "Lower" ) ; break ; + case PUPLACE_BELOW_LEFT : + case PUPLACE_BELOW_RIGHT : ob->setValue ( "Below" ) ; break ; + case PUPLACE_BOTTOM_LEFT : + case PUPLACE_BOTTOM_CENTERED : + case PUPLACE_BOTTOM_RIGHT : ob->setValue ( "Bottom" ) ; break ; + } +} + +void setStatusWidgets ( WidgetList *wid ) +{ + if ( wid ) + { + puObject *ob = wid->obj ; + + int a, b ; + ob->getSize ( &a, &b ) ; + object_size_x->setValue ( a ) ; + object_size_y->setValue ( b ) ; + + ob->getPosition ( &a, &b ) ; + object_position_x->setValue ( a ) ; + object_position_y->setValue ( b ) ; + + if ( wid->label_text ) + object_label->setValue ( wid->label_text ) ; + else + object_label->clrValue () ; + + setHorizontalPlaceWidget ( object_horz_label_place, ob->getLabelPlace () ) ; + setVerticalPlaceWidget ( object_vert_label_place, ob->getLabelPlace () ) ; + + if ( wid->legend_text ) + object_legend->setValue ( wid->legend_text ) ; + else + object_legend->clrValue () ; + + setHorizontalPlaceWidget ( object_horz_legend_place, ob->getLegendPlace () ) ; + setVerticalPlaceWidget ( object_vert_legend_place, ob->getLegendPlace () ) ; + + object_name->setValue ( wid->object_name ) ; + object_callbacks->setValue ( wid->callbacks ) ; + + object_visible->setValue ( wid->visible ? 1 : 0 ) ; + autolock_toggle->setValue ( autolock ); + object_layer->setValue ( (int) wid->layer ) ; + } + else + { + object_size_x->setValue ( 0 ) ; + object_size_y->setValue ( 0 ) ; + + object_position_x->setValue ( 0 ) ; + object_position_y->setValue ( 0 ) ; + + object_label->setValue ( "" ) ; + setHorizontalPlaceWidget ( object_horz_label_place, PUPLACE_CENTERED_LEFT ) ; + setVerticalPlaceWidget ( object_vert_label_place, PUPLACE_CENTERED_LEFT ) ; + + object_legend->setValue ( "" ) ; + setHorizontalPlaceWidget ( object_horz_legend_place, PUPLACE_CENTERED_LEFT ) ; + setVerticalPlaceWidget ( object_vert_legend_place, PUPLACE_CENTERED_LEFT ) ; + + object_name->setValue ( "" ) ; + object_callbacks->setValue ( 0 ) ; + + object_visible->setValue ( 0 ) ; + autolock_toggle->setValue ( autolock ); + object_layer->setValue ( 0 ) ; + } +} + +// GLUT Status Window Callbacks + +static void status_window_specialfn ( int key, int, int ) +{ + puKeyboard ( key + PU_KEY_GLUT_SPECIAL_OFFSET, PU_DOWN ) ; + + glutPostRedisplay () ; +} + +static void status_window_keyfn ( unsigned char key, int, int ) +{ + puKeyboard ( key, PU_DOWN ) ; + + glutPostRedisplay () ; +} + +static void status_window_motionfn ( int x, int y ) +{ + puMouse ( x, y ) ; + + glutPostRedisplay () ; +} + +static void status_window_mousefn ( int button, int updown, int x, int y ) +{ + puMouse ( button, updown, x, y ) ; + + glutPostRedisplay () ; +} + + +static void status_window_displayfn ( void ) +{ + glutSetWindow ( status_window ) ; + + /* Clear the screen */ + + glClearColor ( 0.1f, 0.1f, 0.1f, 1.0f ) ; + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + puDisplay () ; + + /* Update GLUT */ + + glutSwapBuffers () ; + glutPostRedisplay () ; +} + +static void selection_window_displayfn ( void ) +{ + glutSetWindow ( write_window ) ; + + /* Clear the screen */ + + glClearColor ( 0.1f, 0.1f, 0.1f, 1.0f ) ; + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + puDisplay () ; + + /* Update GLUT */ + + glutSwapBuffers () ; + glutPostRedisplay () ; +} + +// PUI Callback Functions: + +extern void write_code ( puObject *ob ) ; + +extern void saveProject ( puObject *ob ) ; + +extern void loadProject ( puObject *ob ) ; + +static void write_window_reshapefn ( int w, int h ) +{ + file_selector->setSize ( w, h ) ; +} + +// Clear Objects callbacks + +static void window_wiper ( puObject *ob ) +{ + + // Prepare to clear the properties window + extern int properties_window ; + // Clear the widget list + extern WidgetList *widgets ; + + WidgetList *wid = widgets ; + + while ( wid ) + { + widgets = wid->next ; + delete wid->object_type_name ; + delete wid->legend_text ; + delete wid->label_text ; + delete wid->obj ; + delete wid ; + wid = widgets ; + } + + active_widget = (WidgetList *)NULL ; + active_object = (puObject *)NULL ; + window_color_r->setValue(1.0f) ; + window_color_g->setValue(1.0f) ; + window_color_b->setValue(1.0f) ; + window_color_a->setValue(1.0f) ; + window_name->setValue("PUI GUI Builder"); + window_size_x->setValue(600) ; + window_size_y->setValue(600) ; + window_position_x->setValue(0) ; + window_position_y->setValue(0) ; + main_window_changed = false ; + autolock = false ; + autolock_toggle->setValue(0); + + glutSetWindow ( main_window ) ; + glutReshapeWindow ( 600, 600 ) ; + + if (properties_window) + { + extern puGroup *properties_group; + /* Delete the widgets */ + puDeleteObject( properties_group ); + glutDestroyWindow( properties_window ); + properties_window = 0; + } + + glutSetWindow ( status_window ) ; + + setStatusWidgets ( active_widget ) ; +} + +static void write_code_cb ( puObject *ob ) +{ + int w = 320, h = 270 ; + if ( write_window ) + { + glutSetWindow ( write_window ) ; + glutSetWindowTitle( "Writing " ); + } + else + { + write_window = glutCreateWindow ( "Writing " ) ; + glutDisplayFunc ( selection_window_displayfn ) ; + glutKeyboardFunc ( status_window_keyfn ) ; + glutSpecialFunc ( status_window_specialfn ) ; + glutMouseFunc ( status_window_mousefn ) ; + glutMotionFunc ( status_window_motionfn ) ; + glutPassiveMotionFunc ( status_window_motionfn ) ; + glutIdleFunc ( selection_window_displayfn ) ; + glutReshapeFunc ( write_window_reshapefn ) ; + } + + glutShowWindow () ; + glutReshapeWindow ( w, h ) ; + glutPositionWindow ( ( 640 - w ) / 2, ( 480 - h ) / 2 ) ; + + file_selector = new puaFileSelector ( 0, 0, w, h, 1, pguide_current_directory, "Pick File to Write To" ) ; + file_selector -> setCallback ( write_code ) ; + file_selector->setChildStyle ( PUCLASS_ONESHOT, PUSTYLE_BOXED ) ; + file_selector->setChildBorderThickness ( PUCLASS_ONESHOT, 5 ) ; + file_selector->setChildColour ( PUCLASS_SLIDER, 0, 0.5, 0.5, 0.5 ) ; +} + +static void saveProject_cb ( puObject *ob ) +{ + int w = 320, h = 270 ; + if ( write_window ) + { + glutSetWindow ( write_window ) ; + glutSetWindowTitle( "Saving " ); + } + else + { + write_window = glutCreateWindow ( "Saving " ) ; + glutDisplayFunc ( selection_window_displayfn ) ; + glutKeyboardFunc ( status_window_keyfn ) ; + glutSpecialFunc ( status_window_specialfn ) ; + glutMouseFunc ( status_window_mousefn ) ; + glutMotionFunc ( status_window_motionfn ) ; + glutPassiveMotionFunc ( status_window_motionfn ) ; + glutIdleFunc ( selection_window_displayfn ) ; + glutReshapeFunc ( write_window_reshapefn ) ; + } + + glutShowWindow () ; + glutReshapeWindow ( w, h ) ; + glutPositionWindow ( ( 640 - w ) / 2, ( 480 - h ) / 2 ) ; + + file_selector = new puaFileSelector ( 0, 0, w, h, 1, pguide_current_directory, "Pick .XML File to Save To" ) ; + file_selector -> setCallback ( saveProject ) ; + file_selector->setChildStyle ( PUCLASS_ONESHOT, PUSTYLE_BOXED ) ; + file_selector->setChildBorderThickness ( PUCLASS_ONESHOT, 5 ) ; + file_selector->setInitialValue(".xml"); + file_selector->setChildColour ( PUCLASS_SLIDER, 0, 0.5, 0.5, 0.5 ) ; +} + +static void loadProject_ok_cb ( puObject *ob ) +{ + puDeleteObject ( dialog ) ; // Delete the dialog box + dialog = (puDialogBox *)NULL ; + + window_wiper( ob ); + + int w = 320, h = 270 ; + if ( write_window ) + { + glutSetWindow ( write_window ) ; + glutSetWindowTitle( "Loading " ); + } + else + { + write_window = glutCreateWindow ( "Loading " ) ; + glutDisplayFunc ( selection_window_displayfn ) ; + glutKeyboardFunc ( status_window_keyfn ) ; + glutSpecialFunc ( status_window_specialfn ) ; + glutMouseFunc ( status_window_mousefn ) ; + glutMotionFunc ( status_window_motionfn ) ; + glutPassiveMotionFunc ( status_window_motionfn ) ; + glutIdleFunc ( selection_window_displayfn ) ; + glutReshapeFunc ( write_window_reshapefn ) ; + } + + glutShowWindow () ; + glutReshapeWindow ( w, h ) ; + glutPositionWindow ( ( 640 - w ) / 2, ( 480 - h ) / 2 ) ; + + file_selector = new puaFileSelector ( 0, 0, w, h, 1, pguide_current_directory, "Pick P-Guide .XML File to load" ) ; + file_selector -> setCallback ( loadProject ) ; + file_selector->setChildStyle ( PUCLASS_ONESHOT, PUSTYLE_BOXED ) ; + file_selector->setChildBorderThickness ( PUCLASS_ONESHOT, 5 ) ; + file_selector->setInitialValue("*.xml"); + file_selector->setChildColour ( PUCLASS_SLIDER, 0, 0.5, 0.5, 0.5 ) ; +} + +static void clear_ok_cb ( puObject *ob ) +{ + window_wiper( ob ); + puDeleteObject ( dialog ) ; // Delete the dialog box + dialog = (puDialogBox *)NULL ; +} + +static void cancel_cb ( puObject *ob ) +{ + // Don't do whatever you were planning to do (clear the widget list or quit) + // but do delete the dialog box. + puDeleteObject ( dialog ) ; + dialog = (puDialogBox *)NULL ; +} + +static void clear_cb ( puObject *ob ) +{ + if ( main_window_changed ) + { + dialog = new puDialogBox ( 50, 300 ) ; + new puFrame ( 0, 0, 125, 70 ) ; + puText *text = new puText ( 10, 40 ) ; + text->setLabel ( "Are you sure?" ) ; + puOneShot *ok = new puOneShot ( 10, 10, "Yes" ) ; + ok->setCallback ( clear_ok_cb ) ; + puOneShot *cancel = new puOneShot ( 60, 10, "Cancel" ) ; + cancel->setCallback ( cancel_cb ) ; + dialog->close () ; + dialog->reveal () ; + } + else + clear_ok_cb ( (puObject *)NULL ) ; +} + +static void loadProject_cb ( puObject *ob ) +{ + if ( main_window_changed ) + { + dialog = new puDialogBox ( 50, 300 ) ; + new puFrame ( 0, 0, 125, 70 ) ; + puText *text = new puText ( 10, 40 ) ; + text->setLabel ( "Are you sure?" ) ; + puOneShot *ok = new puOneShot ( 10, 10, "Yes" ) ; + ok->setCallback ( loadProject_ok_cb ) ; + puOneShot *cancel = new puOneShot ( 60, 10, "Cancel" ) ; + cancel->setCallback ( cancel_cb ) ; + dialog->close () ; + dialog->reveal () ; + } + else + loadProject_ok_cb ( (puObject *)NULL ) ; +} + +static void quit_ok_cb ( puObject *ob ) +{ + exit ( 0 ) ; +} + +static void quit_cb ( puObject *ob ) +{ + if ( main_window_changed ) + { + dialog = new puDialogBox ( 50, 300 ) ; + new puFrame ( 0, 0, 125, 70 ) ; + puText *text = new puText ( 10, 40 ) ; + text->setLabel ( "Are you sure?" ) ; + puOneShot *ok = new puOneShot ( 10, 10, "Yes" ) ; + ok->setCallback ( quit_ok_cb ) ; + puOneShot *cancel = new puOneShot ( 60, 10, "Cancel" ) ; + cancel->setCallback ( cancel_cb ) ; + dialog->close () ; + dialog->reveal () ; + } + else + quit_ok_cb ( (puObject *)NULL ) ; +} + +static void object_size_cb ( puObject *ob ) +{ + if ( active_object ) + { + int w, h ; + active_object->getSize ( &w, &h ) ; + if ( ob == object_size_x ) + { + w = ob->getIntegerValue () ; + if ( w < 1 ) w = 1 ; + ob->setValue ( w ) ; + } + else + { + h = ob->getIntegerValue () ; + if ( h < 1 ) h = 1 ; + ob->setValue ( h ) ; + } + + active_object->setSize ( w, h ) ; + } +} + +static void object_position_cb ( puObject *ob ) +{ + if ( active_object ) + { + int x, y ; + active_object->getPosition ( &x, &y ) ; + if ( ob == object_position_x ) + x = ob->getIntegerValue () ; + else + y = ob->getIntegerValue () ; + + ob->setValue ( ob->getIntegerValue () ) ; + active_object->setPosition ( x, y ) ; + } +} + +static void window_size_cb ( puObject *ob ) +{ + extern int main_window_width ; + extern int main_window_height ; + + extern int main_window ; + + glutSetWindow ( main_window ) ; + if ( ob == window_size_x ) + main_window_width = ob->getIntegerValue () ; + else + main_window_height = ob->getIntegerValue () ; + + ob->setValue ( ob->getIntegerValue () ) ; + glutReshapeWindow ( main_window_width, main_window_height ) ; + + glutSetWindow ( status_window ) ; +} + +static void window_name_cb ( puObject *ob ) +{ + extern int main_window ; + + glutSetWindow ( main_window ) ; + strcpy ( main_window_name, ob->getStringValue () ) ; + glutSetWindowTitle ( main_window_name ) ; + glutSetWindow ( status_window ) ; +} + +static void label_cb ( puObject *ob ) +{ + if ( active_widget ) + { + if (active_widget->label_text) + delete active_widget->label_text ; + active_widget->label_text = new char [ strlen ( ob->getStringValue () ) + 1 ] ; + strcpy ( active_widget->label_text, ob->getStringValue () ) ; + active_widget->obj->setLabel ( active_widget->label_text ) ; + } +} + +static void label_place_cb ( puObject *ob ) +{ + if ( active_object ) + { + int horz = object_horz_label_place->getCurrentItem () ; + int vert = object_vert_label_place->getCurrentItem () ; + + switch ( horz ) + { + case 0 : // Left + switch ( vert ) + { + case 0 : // Top + active_object->setLabelPlace ( PUPLACE_TOP_LEFT ) ; break ; + case 1 : // Above + active_object->setLabelPlace ( PUPLACE_ABOVE_LEFT ) ; break ; + case 2 : // Upper + active_object->setLabelPlace ( PUPLACE_UPPER_LEFT ) ; break ; + case 3 : // Center + active_object->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; break ; + case 4 : // Lower + active_object->setLabelPlace ( PUPLACE_LOWER_LEFT ) ; break ; + case 5 : // Below + active_object->setLabelPlace ( PUPLACE_BELOW_LEFT ) ; break ; + case 6 : // Bottom + active_object->setLabelPlace ( PUPLACE_BOTTOM_LEFT ) ; break ; + } + + break ; + + case 1 : // Center + switch ( vert ) + { + case 0 : // Top + active_object->setLabelPlace ( PUPLACE_TOP_CENTERED ) ; break ; + case 1 : // Above -- not allowed + case 2 : // Upper -- not allowed + case 3 : // Center -- not allowed + case 4 : // Lower -- not allowed + case 5 : // Below -- not allowed + if ( ob == object_horz_label_place ) + { + ob->setValue ( "Left" ) ; // Left + active_object->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; + } + else + { + ob->setValue ( "Top" ) ; // Top + active_object->setLabelPlace ( PUPLACE_TOP_CENTERED ) ; + } + + break ; + case 6 : // Bottom + active_object->setLabelPlace ( PUPLACE_BOTTOM_CENTERED ) ; break ; + } + + break ; + + case 2 : // Right + switch ( vert ) + { + case 0 : // Top + active_object->setLabelPlace ( PUPLACE_TOP_RIGHT ) ; break ; + case 1 : // Above + active_object->setLabelPlace ( PUPLACE_ABOVE_RIGHT ) ; break ; + case 2 : // Upper + active_object->setLabelPlace ( PUPLACE_UPPER_RIGHT ) ; break ; + case 3 : // Center + active_object->setLabelPlace ( PUPLACE_CENTERED_RIGHT ) ; break ; + case 4 : // Lower + active_object->setLabelPlace ( PUPLACE_LOWER_RIGHT ) ; break ; + case 5 : // Below + active_object->setLabelPlace ( PUPLACE_BELOW_RIGHT ) ; break ; + case 6 : // Bottom + active_object->setLabelPlace ( PUPLACE_BOTTOM_RIGHT ) ; break ; + } + + break ; + } + } +} + +static void legend_cb ( puObject *ob ) +{ + if ( active_widget ) + { + if (active_widget->legend_text) + delete active_widget->legend_text ; + active_widget->legend_text = new char [ strlen ( ob->getStringValue () ) + 1 ] ; + strcpy ( active_widget->legend_text, ob->getStringValue () ) ; + } +} + +static void legend_place_cb ( puObject *ob ) +{ + if ( active_object ) + { + int horz = object_horz_legend_place->getCurrentItem () ; + int vert = object_vert_legend_place->getCurrentItem () ; + + switch ( horz ) + { + case 0 : // Left + switch ( vert ) + { + case 0 : // Top + active_object->setLegendPlace ( PUPLACE_TOP_LEFT ) ; break ; + case 1 : // Above -- not allowed + case 2 : // Upper -- not allowed + object_vert_legend_place->setValue ( "Top" ) ; + active_object->setLegendPlace ( PUPLACE_TOP_LEFT ) ; break ; + case 3 : // Center + active_object->setLegendPlace ( PUPLACE_CENTERED_LEFT ) ; break ; + case 4 : // Lower -- not allowed + case 5 : // Below -- not allowed + object_vert_legend_place->setValue ( "Bottom" ) ; + active_object->setLegendPlace ( PUPLACE_BOTTOM_LEFT ) ; break ; + case 6 : // Bottom + active_object->setLegendPlace ( PUPLACE_BOTTOM_LEFT ) ; break ; + } + + break ; + + case 1 : // Center + switch ( vert ) + { + case 0 : // Top + active_object->setLegendPlace ( PUPLACE_TOP_CENTERED ) ; break ; + case 1 : // Above -- not allowed + case 2 : // Upper -- not allowed + object_vert_legend_place->setValue ( "Top" ) ; + active_object->setLegendPlace ( PUPLACE_TOP_CENTERED ) ; break ; + case 3 : // Center + active_object->setLegendPlace ( PUPLACE_CENTERED_CENTERED ) ; break ; + case 4 : // Lower -- not allowed + case 5 : // Below -- not allowed + object_vert_legend_place->setValue ( "Bottom" ) ; + active_object->setLegendPlace ( PUPLACE_BOTTOM_CENTERED ) ; break ; + case 6 : // Bottom + active_object->setLegendPlace ( PUPLACE_BOTTOM_CENTERED ) ; break ; + } + + break ; + + case 2 : // Right + switch ( vert ) + { + case 0 : // Top + active_object->setLegendPlace ( PUPLACE_TOP_RIGHT ) ; break ; + case 1 : // Above -- not allowed + case 2 : // Upper -- not allowed + object_vert_legend_place->setValue ( "Top" ) ; + active_object->setLegendPlace ( PUPLACE_TOP_RIGHT ) ; break ; + case 3 : // Center + active_object->setLegendPlace ( PUPLACE_CENTERED_RIGHT ) ; break ; + case 4 : // Lower -- not allowed + case 5 : // Below -- not allowed + object_vert_legend_place->setValue ( "Bottom" ) ; + active_object->setLegendPlace ( PUPLACE_BOTTOM_RIGHT ) ; break ; + case 6 : // Bottom + active_object->setLegendPlace ( PUPLACE_BOTTOM_RIGHT ) ; break ; + } + + break ; + } + } +} + +static void name_cb ( puObject *ob ) +{ + if ( active_widget ) + { + //strcpy ( active_widget->object_name, ob->getStringValue () ) ; + strcpy ( active_widget->object_name, object_name->getStringValue () ) ;/* Because ob is not _always_ the right puInput! */ + + // Remove spaces from the widget name + char *spc = strchr ( active_widget->object_name, ' ' ) ; + while ( spc ) + { + *spc = '_' ; + spc = strchr ( active_widget->object_name, ' ' ) ; + } + /* Make sure the widget's name doesn't already exist. If so, prompt user */ + /* This really should be made to use the chk_dupname function from LoadSave.cxx */ + extern WidgetList *widgets ; + WidgetList *wid = widgets ; + while ( wid ) + { + if ( (strcmp(active_widget->object_name,wid->object_name) == 0) && (active_widget != wid) ) + { + /* Popup a dialog telling user something's bad! */ + dialog = new puDialogBox ( 20, 20 ) ; + new puFrame ( 0, 0, 460, 120 ) ; + puText *text = new puText ( 80, 85 ) ; + text->setLabel ( "ERROR: Name already used." ) ; + text->setLabelFont(PUFONT_TIMES_ROMAN_24); + puText *directions = new puText ( 90, 65 ) ; + directions->setLabel ( "Please type in a new, unique name to continue." ) ; + directions->setLabelFont(PUFONT_HELVETICA_12); + puInput *newname = new puInput (20,40,440,60) ; + newname->setValuator(active_widget->object_name); + newname->setValidData("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_012345679"); + puOneShot *ok = new puOneShot ( 200, 10, "Accept" ) ; + ok->setCallback ( dupname_ok_cb ) ; + dialog->close () ; + dialog->reveal () ; + break ; + } + wid = wid->next ; + } + ob->setValue(active_widget->object_name); + } +} + +static void dupname_ok_cb ( puObject *ob ) +{ + /* The user's new name from the dialog has already been set to the object_name*/ + /* Close dialogbox and update main window ...*/ + puDeleteObject ( dialog ) ; + dialog = (puDialogBox *)NULL ; + newname = (puInput *)NULL ; + setStatusWidgets(active_widget); + /*but force a recheck afterwards to ensure it's an okay substitution. */ + name_cb(ob); +} + +static void callback_cb ( puObject *ob ) +{ + if ( active_widget ) active_widget->callbacks = ob->getIntegerValue () ; +} + +static void reveal_all_cb ( puObject *ob ) +{ + extern WidgetList *widgets ; + WidgetList *wid = widgets ; + while ( wid ) + { + wid->visible = true ; + wid = wid->next ; + } +} + +static void hide_all_cb ( puObject *ob ) +{ + extern WidgetList *widgets ; + WidgetList *wid = widgets ; + while ( wid ) + { + wid->visible = false ; + wid = wid->next ; + } +} + +static void hide_all_layer_cb ( puObject *ob ) +{ + extern WidgetList *widgets ; + WidgetList *wid = widgets ; + while ( wid ) + { + if ( wid->layer == layer_to_act_on->getIntegerValue() ) + wid->visible = false ; + wid = wid->next; + } +} + +static void reveal_all_layer_cb ( puObject *ob ) +{ + extern WidgetList *widgets ; + WidgetList *wid = widgets ; + while ( wid ) + { + if ( wid->layer == layer_to_act_on->getIntegerValue() ) + wid->visible = true ; + wid = wid->next; + } +} + +static void visible_cb ( puObject *ob ) +{ + if ( active_widget ) active_widget->visible = ( ob->getIntegerValue () != 0 ) ; +} + +static void layer_cb ( puObject *ob ) +{ + if ( ob->getIntegerValue () < 0 ) ob->setValue ( 0 ) ; + if ( active_widget ) + { + active_widget->layer = ob->getIntegerValue () ; + if ( max_layer <= active_widget->layer ) max_layer = active_widget->layer + 1 ; + } +} + +static void autolock_cb ( puObject *ob ) +{ + if ( ob->getIntegerValue () == 1 ) + autolock = true ; + else + autolock = false ; +} + +// Setup Menubar + +static char *file_submenu [] = { "Exit", "------------", "Export Code", "------------", "Save Project", "Load Project", "New Project", NULL } ; +static puCallback file_submenu_cb [] = { quit_cb, NULL, write_code_cb, NULL, saveProject_cb, loadProject_cb, clear_cb, NULL } ; + +// Function to define the window + +int define_status_window () +{ + status_window = glutCreateWindow ( "Status Window" ) ; + + int total_screen_width = glutGet( GLUT_SCREEN_WIDTH ) ; + + glutPositionWindow ( total_screen_width-520, 266 ) ; + glutReshapeWindow ( 500, 380 ) ; + glutDisplayFunc ( status_window_displayfn ) ; + glutKeyboardFunc ( status_window_keyfn ) ; + glutSpecialFunc ( status_window_specialfn ) ; + glutMotionFunc ( status_window_motionfn ) ; + glutMouseFunc ( status_window_mousefn ) ; + + // Set up the widgets + + puGroup *status_group = new puGroup ( 0, 0 ) ; + new puFrame ( 0, 0, 500, 380 ) ; + + menubar = new puMenuBar () ; + { + menubar -> add_submenu ( "File", file_submenu, file_submenu_cb ) ; + } + menubar -> close() ; + + widget_section_frame = new puFrame ( 0, 1, 500, 250 ) ; + widget_section_frame->setLegendFont ( PUFONT_HELVETICA_18 ) ; + widget_section_frame->setLegend ( "Widget Options:" ) ; + widget_section_frame->setLegendPlace ( PUPLACE_TOP_LEFT ) ; + + object_size_x = new puInput ( 380, 10, 430, 30 ) ; + object_size_x->setLabel ( "Object Size:" ) ; + object_size_x->setLabelPlace ( PUPLACE_LEFT ) ; + object_size_x->setCallback ( object_size_cb ) ; + object_size_x->setDownCallback ( object_size_cb ) ; + + object_size_y = new puInput ( 430, 10, 480, 30 ) ; + object_size_y->setCallback ( object_size_cb ) ; + object_size_y->setDownCallback ( object_size_cb ) ; + + object_position_x = new puInput ( 160, 10, 210, 30 ) ; + object_position_x->setLabel ( "Object Position:" ) ; + object_position_x->setLabelPlace ( PUPLACE_LEFT ) ; + object_position_x->setCallback ( object_position_cb ) ; + object_position_x->setDownCallback ( object_position_cb ) ; + + object_position_y = new puInput ( 210, 10, 260, 30 ) ; + object_position_y->setCallback ( object_position_cb ) ; + object_position_y->setDownCallback ( object_position_cb ) ; + + + static char *vert_place_entries [] = { "Top", "Above", "Upper", "Center", + "Lower", "Below", "Bottom", NULL } ; + + static char *horz_place_entries [] = { "Left", "Center", "Right", NULL } ; + + object_label = new puInput ( 65, 40, 260, 60 ) ; + object_label->setLabel ( "Label:" ) ; + object_label->setLabelPlace ( PUPLACE_LEFT ) ; + object_label->setCallback ( label_cb ) ; + object_label->setDownCallback ( label_cb ) ; + + object_vert_label_place = new puaComboBox ( 310, 40, 400, 60, vert_place_entries, FALSE ) ; + object_vert_label_place->setLabel ( "Place" ) ; + object_vert_label_place->setLabelPlace ( PUPLACE_LEFT ) ; + object_vert_label_place->setCallback ( label_place_cb ) ; + + object_horz_label_place = new puaComboBox ( 400, 40, 490, 60, horz_place_entries, FALSE ) ; + object_horz_label_place->setCallback ( label_place_cb ) ; + + object_legend = new puInput ( 65, 70, 260, 90 ) ; + object_legend->setLabel ( "Legend:" ) ; + object_legend->setLabelPlace ( PUPLACE_LEFT ) ; + object_legend->setCallback ( legend_cb ) ; + object_legend->setDownCallback ( legend_cb ) ; + + object_vert_legend_place = new puaComboBox ( 310, 70, 400, 90, vert_place_entries, FALSE ) ; + object_vert_legend_place->setLabel ( "Place" ) ; + object_vert_legend_place->setLabelPlace ( PUPLACE_LEFT ) ; + object_vert_legend_place->setCallback ( legend_place_cb ) ; + + object_horz_legend_place = new puaComboBox ( 400, 70, 490, 90, horz_place_entries, FALSE ) ; + object_horz_legend_place->setCallback ( legend_place_cb ) ; + + object_name = new puInput ( 65, 195, 260, 215 ) ; + object_name->setLabel ( "Name:" ) ; + object_name->setValidData("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_0123456789"); + object_name->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; + object_name->setCallback ( name_cb ) ; + object_name->setDownCallback ( name_cb ) ; + + static char *callback_entries [] = { "Up", "Active", "Down", NULL } ; + object_callbacks = new puButtonBox ( 120, 100, 260, 170, callback_entries, FALSE ) ; + object_callbacks->setLabel ( "Widget Callbacks:" ) ; + object_callbacks->setLabelPlace ( PUPLACE_TOP_LEFT ) ; + object_callbacks->setCallback ( callback_cb ) ; + + static char *visible_entries [] = { "Visible", NULL } ; + object_visible = new puButtonBox ( 10, 140, 115, 170, visible_entries, FALSE ) ; + object_visible->setCallback ( visible_cb ) ; + + object_layer = new puaSpinBox ( 65, 100, 115, 120) ; + object_layer->setMinValue(0.0); + object_layer->setMaxValue(999.0); + object_layer->setStepSize(1.00f); + object_layer->setValue(0.0f); + object_layer->setCallback ( layer_cb ) ; + object_layer->setDownCallback ( layer_cb ) ; + + object_layer_text = new puText( 65, 112 ); + object_layer_text->setLabel ( "Layer:" ) ; + object_layer_text->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; + + static char *autolock_entries [] = { "Autolock", NULL } ; + autolock_toggle = new puButtonBox ( 370, 252, 490, 282, autolock_entries, FALSE ) ; + autolock_toggle->setCallback ( autolock_cb ) ; + + layer_manipulation_frame = new puFrame (300, 120, 495, 215) ; + layer_manipulation_frame->setLegend ( "Layer Manipulation" ); + layer_manipulation_frame->setLegendFont ( PUFONT_HELVETICA_12 ) ; + layer_manipulation_frame->setLegendPlace ( PUPLACE_TOP_CENTERED ); + + layer_to_act_on_frame = new puFrame ( 300, 145, 495, 190 ); + layer_to_act_on_frame->setLegend ( "Affect Single Layer:" ) ; + layer_to_act_on_frame->setLegendPlace ( PUPLACE_TOP_CENTERED ) ; + + layer_all_frame = new puFrame ( 300, 121, 495, 148 ); + + hide_all_objects = new puOneShot ( 360, 124, 420, 144 ) ; + hide_all_objects->setLegend ( "Hide" ) ; + hide_all_objects->setLabel ( "All:" ) ; + hide_all_objects->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; + hide_all_objects->setCallback ( hide_all_cb ) ; + + reveal_all_objects = new puOneShot ( 425, 124, 485, 144 ) ; + reveal_all_objects->setLegend ( "Reveal" ) ; + reveal_all_objects->setCallback ( reveal_all_cb ) ; + + layer_to_act_on = new puaSpinBox ( 310, 150, 355, 170 ) ; + layer_to_act_on->setMinValue(0.0); + layer_to_act_on->setMaxValue(999.0); + layer_to_act_on->setStepSize(1.00f); + layer_to_act_on->setValue(0.0f); + + hide_all_layer = new puOneShot ( 360, 150, 420, 170 ) ; + hide_all_layer->setLegend ( "Hide" ) ; + hide_all_layer->setCallback ( hide_all_layer_cb ) ; + + reveal_all_layer = new puOneShot ( 425, 150, 485, 170 ) ; + reveal_all_layer->setLegend ( "Reveal" ) ; + reveal_all_layer->setCallback ( reveal_all_layer_cb ) ; + + window_name = new puInput ( 130, 340, 430, 360 ) ; + window_name->setValue( main_window_name ); + window_name->setLabel ( "Window Name:" ) ; + window_name->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; + window_name->setCallback ( window_name_cb ) ; + window_name->setDownCallback ( window_name_cb ) ; + + window_size_x = new puInput ( 130, 310, 180, 330 ) ; + window_size_x->setLabel ( "Window Size:" ) ; + window_size_x->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; + window_size_x->setCallback ( window_size_cb ) ; + window_size_x->setDownCallback ( window_size_cb ) ; + + window_size_y = new puInput ( 180, 310, 230, 330 ) ; + window_size_y->setCallback ( window_size_cb ) ; + window_size_y->setDownCallback ( window_size_cb ) ; + + extern int main_window_x, main_window_y ; + + window_position_x = new puInput ( 130, 285, 180 , 305 ) ; + window_position_x->setLabel ( "Position:" ) ; + window_position_x->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; + window_position_x->setValuator ( &main_window_x ) ; + + window_position_y = new puInput ( 180, 285, 230, 305 ) ; + window_position_y->setValuator ( &main_window_y ) ; + + extern float main_window_color_r, main_window_color_g, + main_window_color_b, main_window_color_a ; + + window_color_label = new puText (340, 320) ; + window_color_label->setLabel ( "Color:" ) ; + + window_color_r = new puaSpinBox ( 270, 285, 320, 305 ) ; + window_color_r->setMinValue(0.0); + window_color_r->setMaxValue(1.0); + window_color_r->setStepSize(0.05f); + window_color_r->setLabel ( "Red" ) ; + window_color_r->setLabelPlace ( PUPLACE_TOP_CENTERED ) ; + window_color_r->setValuator ( &main_window_color_r ) ; + window_color_r->setValue(1.0f); + + window_color_g = new puaSpinBox ( 320, 285, 370, 305 ) ; + window_color_g->setMinValue(0.0); + window_color_g->setMaxValue(1.0); + window_color_g->setStepSize(0.05f); + window_color_g->setLabel ( "Green" ) ; + window_color_g->setLabelPlace ( PUPLACE_TOP_CENTERED ) ; + window_color_g->setValuator ( &main_window_color_g ) ; + window_color_g->setValue(1.0f); + + window_color_b = new puaSpinBox ( 370, 285, 420, 305 ) ; + window_color_b->setMinValue(0.0); + window_color_b->setMaxValue(1.0); + window_color_b->setStepSize(0.05f); + window_color_b->setLabel ( "Blue" ) ; + window_color_b->setLabelPlace ( PUPLACE_TOP_CENTERED ) ; + window_color_b->setValuator ( &main_window_color_b ) ; + window_color_b->setValue(1.0f); + + window_color_a = new puaSpinBox ( 420, 285, 470, 305 ) ; + window_color_a->setMinValue(0.0); + window_color_a->setMaxValue(1.0); + window_color_a->setStepSize(0.05f); + window_color_a->setLabel ( "Alpha" ) ; + window_color_a->setLabelPlace ( PUPLACE_TOP_CENTERED ) ; + window_color_a->setValuator ( &main_window_color_a ) ; + window_color_a->setValue(1.0f); + + status_group->close () ; + + return 0 ; +} + diff --git a/demos/p-guide/src/WidgetList.h b/demos/p-guide/src/WidgetList.h new file mode 100644 index 0000000..f7a8f76 --- /dev/null +++ b/demos/p-guide/src/WidgetList.h @@ -0,0 +1,75 @@ +/* + This file is part of P-GUIDE - + PUI-based Graphical User Interface Designer. + Copyright (C) 2002, 2006 John F. Fay + + P-GUIDE 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. + + P-GUIDE 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 P-GUIDE; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + $Id: WidgetList.h 2083 2006-05-01 13:14:50Z bram $ +*/ + +// Data Structure Definition + +#ifndef WIDGET_LIST_H +#define WIDGET_LIST_H + +#include +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + + +// PUI Widget List for Main Window + +struct WidgetList +{ + puObject *obj ; + char *object_type_name ; + int object_type ; + char *label_text ; + char *legend_text ; + short callbacks ; + char object_name [ PUSTRING_MAX ] ; + bool visible ; + bool locked ; + int layer ; // GUI layer: 0 - in back, positive nubmers - greater in front of lesser + WidgetList *next ; + /* Additional data for the extended properties of widgets */ + char *items ; + char *allowed ; + int intval1 ; + int intval2 ; + bool boolval1 ; + bool boolval2 ; + bool boolval3 ; + float floatval1 ; + float floatval2 ; + float floatval3 ; + float floatval4 ; + float floatval5 ; + float floatval6 ; +} ; + + +#endif // WIDGET_LIST_H + diff --git a/demos/p-guide/src/WidgetWindow.cxx b/demos/p-guide/src/WidgetWindow.cxx new file mode 100644 index 0000000..fb9edea --- /dev/null +++ b/demos/p-guide/src/WidgetWindow.cxx @@ -0,0 +1,460 @@ +/* + This file is part of P-GUIDE - + PUI-based Graphical User Interface Designer. + Copyright (C) 2002, 2006 John F. Fay + + P-GUIDE 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. + + P-GUIDE 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 P-GUIDE; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + $Id: WidgetWindow.cxx 2100 2006-11-03 22:31:54Z fayjf $ +*/ + +// Widget Window + +#include + +#include +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +// Widget Window Data + +bool selected_object_sticky = false ; +int selected_object_type ; +char *selected_type_string ; +puButton *active_button = (puButton *)NULL ; + +// Widget window parameters +static int widget_window = 0 ; // Window handle + +// GLUT Widget Window Callbacks + +static void widget_window_specialfn ( int key, int, int ) +{ + glutPostRedisplay () ; +} + +static void widget_window_keyfn ( unsigned char key, int, int ) +{ + if ( selected_object_type ) + { + if ( key == 27 ) // Escape key, deactivate the selected button + { + selected_object_type = 0 ; + active_button->setValue ( 0 ) ; + } + } + + glutPostRedisplay () ; +} + +static void widget_window_motionfn ( int x, int y ) +{ + puMouse ( x, y ) ; + + glutPostRedisplay () ; +} + +static void widget_window_mousefn ( int button, int updown, int x, int y ) +{ + if ( ! puMouse ( button, updown, x, y ) ) + { + // PUI didn't absorb the mouse click; deactivate the selected object type + if ( selected_object_type ) + { + selected_object_type = 0 ; + active_button->setValue ( 0 ) ; + } + } + + glutPostRedisplay () ; +} + + +static void widget_window_displayfn ( void ) +{ + glutSetWindow ( widget_window ) ; + + /* Clear the screen */ + + glClearColor ( 0.1f, 0.1f, 0.1f, 1.0f ) ; + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + puDisplay () ; + + /* Update GLUT */ + + glutSwapBuffers () ; + glutPostRedisplay () ; +} + +// PUI Callback Functions: + +static void frame_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_FRAME ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void text_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_TEXT ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void menu_bar_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_MENUBAR ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void vertical_menu_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_VERTMENU ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void spin_box_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_SPINBOX ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void list_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_LIST ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + + + + +static void input_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_INPUT ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void large_input_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_LARGEINPUT ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void select_box_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_SELECTBOX ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void file_selector_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_FILESELECTOR ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void list_box_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_LISTBOX ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void scroll_bar_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_SCROLLBAR ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + + + + +static void button_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_BUTTON ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void one_shot_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_ONESHOT ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void arrow_button_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_ARROW ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void button_box_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_BUTTONBOX ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void combo_box_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_COMBOBOX ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void chooser_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_CHOOSER ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + + + + +static void dial_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_DIAL ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void slider_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_SLIDER ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void bislider_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_BISLIDER ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void trislider_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_TRISLIDER ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void slider_with_input_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_SLIDERWITHINPUT ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +static void bislider_with_ends_cb ( puObject *ob ) +{ + selected_object_sticky = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ? 1 : 0 ; + selected_object_type = PUCLASS_BISLIDERWITHENDS ; + strcpy ( selected_type_string, ob->getLegend () ) ; + active_button = (puButton *)ob ; +} + +// Function to define the window +// The widgets are arranged in a rectangle: +// Frame Input Button Dial +// Text Large Input One Shot Slider +// Menu Bar Select Box Arrow Button Bi-Slider +// Vertical Menu File Selector Button Box Tri-Slider +// Spin Box List Box Combo Box Slider with Input +// List Scroll Bar Chooser Bi-Slider with Ends +// +// The following widgets are not offered: +// Group Interface Popup Popup Menu +// Dialog Box + +int define_widget_window () +{ + widget_window = glutCreateWindow ( "Widget List" ) ; + int ln = 120 ; // Button length + int ht = 20 ; // Button height + int sp = 10 ; // Button spacing + int total_screen_width = glutGet( GLUT_SCREEN_WIDTH ) ; + + glutReshapeWindow ( 4 * ln + 5 * sp, 6 * ht + 7 * sp ) ; + glutPositionWindow ( total_screen_width - (4 * ln + 5 * sp) - 20, 20 ) ; + glutDisplayFunc ( widget_window_displayfn ) ; + glutKeyboardFunc ( widget_window_keyfn ) ; + glutSpecialFunc ( widget_window_specialfn ) ; + glutMotionFunc ( widget_window_motionfn ) ; + glutMouseFunc ( widget_window_mousefn ) ; + + // Global variable initialization (type string) + selected_type_string = new char [ PUSTRING_MAX ] ; + + // Set up the widgets + + puGroup *widget_group = new puGroup ( 0, 0 ) ; + + new puFrame ( 0, 0, 4 * ln + 5 * sp, 6 * ht + 7 * sp ) ; + + puButton *button = (puButton *)NULL ; + button = new puButton ( sp, 6*sp+5*ht, sp+ln, 6*sp+6*ht ) ; + button->setLegend ( "puFrame" ) ; + button->setCallback ( frame_cb ) ; + + button = new puButton ( sp, 5*sp+4*ht, sp+ln, 5*sp+5*ht ) ; + button->setLegend ( "puText" ) ; + button->setCallback ( text_cb ) ; + + button = new puButton ( sp, 4*sp+3*ht, sp+ln, 4*sp+4*ht ) ; + button->setLegend ( "puMenuBar" ) ; + button->setCallback ( menu_bar_cb ) ; + + button = new puButton ( sp, 3*sp+2*ht, sp+ln, 3*sp+3*ht ) ; + button->setLegend ( "puaVerticalMenu" ) ; + button->setCallback ( vertical_menu_cb ) ; + + button = new puButton ( sp, 2*sp+ht, sp+ln, 2*sp+2*ht ) ; + button->setLegend ( "puaSpinBox" ) ; + button->setCallback ( spin_box_cb ) ; + + button = new puButton ( sp, sp, sp+ln, sp+ht ) ; + button->setLegend ( "puaList" ) ; + button->setCallback ( list_cb ) ; + + + + button = new puButton ( 2*sp+ln, 6*sp+5*ht, 2*sp+2*ln, 6*sp+6*ht ) ; + button->setLegend ( "puInput" ) ; + button->setCallback ( input_cb ) ; + + button = new puButton ( 2*sp+ln, 5*sp+4*ht, 2*sp+2*ln, 5*sp+5*ht ) ; + button->setLegend ( "puaLargeInput" ) ; + button->setCallback ( large_input_cb ) ; + + button = new puButton ( 2*sp+ln, 4*sp+3*ht, 2*sp+2*ln, 4*sp+4*ht ) ; + button->setLegend ( "puaSelectBox" ) ; + button->setCallback ( select_box_cb ) ; + + button = new puButton ( 2*sp+ln, 3*sp+2*ht, 2*sp+2*ln, 3*sp+3*ht ) ; + button->setLegend ( "puaFileSelector" ) ; + button->setCallback ( file_selector_cb ) ; + + button = new puButton ( 2*sp+ln, 2*sp+ht, 2*sp+2*ln, 2*sp+2*ht ) ; + button->setLegend ( "puListBox" ) ; + button->setCallback ( list_box_cb ) ; + + button = new puButton ( 2*sp+ln, sp, 2*sp+2*ln, sp+ht ) ; + button->setLegend ( "puaScrollBar" ) ; + button->setCallback ( scroll_bar_cb ) ; + + + + button = new puButton ( 3*sp+2*ln, 6*sp+5*ht, 3*sp+3*ln, 6*sp+6*ht ) ; + button->setLegend ( "puButton" ) ; + button->setCallback ( button_cb ) ; + + button = new puButton ( 3*sp+2*ln, 5*sp+4*ht, 3*sp+3*ln, 5*sp+5*ht ) ; + button->setLegend ( "puOneShot" ) ; + button->setCallback ( one_shot_cb ) ; + + button = new puButton ( 3*sp+2*ln, 4*sp+3*ht, 3*sp+3*ln, 4*sp+4*ht ) ; + button->setLegend ( "puArrowButton" ) ; + button->setCallback ( arrow_button_cb ) ; + + button = new puButton ( 3*sp+2*ln, 3*sp+2*ht, 3*sp+3*ln, 3*sp+3*ht ) ; + button->setLegend ( "puButtonBox" ) ; + button->setCallback ( button_box_cb ) ; + + button = new puButton ( 3*sp+2*ln, 2*sp+ht, 3*sp+3*ln, 2*sp+2*ht ) ; + button->setLegend ( "puaComboBox" ) ; + button->setCallback ( combo_box_cb ) ; + + button = new puButton ( 3*sp+2*ln, sp, 3*sp+3*ln, sp+ht ) ; + button->setLegend ( "puaChooser" ) ; + button->setCallback ( chooser_cb ) ; + // TODO: It appears that the "puaChooser" file is not in the puAux library yet. + button->hide (); + + + button = new puButton ( 4*sp+3*ln, 6*sp+5*ht, 4*sp+4*ln, 6*sp+6*ht ) ; + button->setLegend ( "puDial" ) ; + button->setCallback ( dial_cb ) ; + + button = new puButton ( 4*sp+3*ln, 5*sp+4*ht, 4*sp+4*ln, 5*sp+5*ht ) ; + button->setLegend ( "puSlider" ) ; + button->setCallback ( slider_cb ) ; + + button = new puButton ( 4*sp+3*ln, 4*sp+3*ht, 4*sp+4*ln, 4*sp+4*ht ) ; + button->setLegend ( "puaBiSlider" ) ; + button->setCallback ( bislider_cb ) ; + + button = new puButton ( 4*sp+3*ln, 3*sp+2*ht, 4*sp+4*ln, 3*sp+3*ht ) ; + button->setLegend ( "puaTriSlider" ) ; + button->setCallback ( trislider_cb ) ; + + button = new puButton ( 4*sp+3*ln, 2*sp+ht, 4*sp+4*ln, 2*sp+2*ht ) ; + button->setLegend ( "puaSliderWithInput" ) ; + button->setCallback ( slider_with_input_cb ) ; + + button = new puButton ( 4*sp+3*ln, sp, 4*sp+4*ln, sp+ht ) ; + button->setLegend ( "puaBiSliderWithEnds" ) ; + button->setCallback ( bislider_with_ends_cb ) ; + + widget_group->close () ; + + return 0 ; +} + diff --git a/demos/p-guide/src/WriteCode.cxx b/demos/p-guide/src/WriteCode.cxx new file mode 100644 index 0000000..631db86 --- /dev/null +++ b/demos/p-guide/src/WriteCode.cxx @@ -0,0 +1,616 @@ +/* + This file is part of P-GUIDE - + PUI-based Graphical User Interface Designer. + Copyright (C) 2002, 2006 John F. Fay + + P-GUIDE 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. + + P-GUIDE 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 P-GUIDE; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + $Id: WriteCode.cxx 2100 2006-11-03 22:31:54Z fayjf $ +*/ + +// Function to write the actual code + +#include + +#include "WidgetList.h" + +#ifdef WIN32 + #define PATH_SEPARATOR '\\' +#else + #define PATH_SEPARATOR '/' +#endif + +// From the Main Window: + +extern WidgetList *widgets ; +extern int max_layer ; + +extern int main_window_width ; +extern int main_window_height ; + +extern char main_window_name [ PUSTRING_MAX ] ; +extern char pguide_current_directory [ PUSTRING_MAX ] ; + +extern int main_window_x ; +extern int main_window_y ; + +extern bool main_window_changed ; + +extern float main_window_color_r, main_window_color_g, + main_window_color_b, main_window_color_a ; + +// From the Status Window + +extern int status_window ; +extern puaFileSelector *file_selector ; + +const char* trueOrFalse(bool tf) +{ + if (tf) return "TRUE"; + else return "FALSE"; +} + +// The function itself + +void write_code ( puObject *ob ) +{ + // Get the file name and open the file + char* filename ; + file_selector -> getValue ( &filename ) ; + if (filename[0] == '\0') + { + puDeleteObject ( file_selector ) ; + file_selector = (puaFileSelector *)NULL ; + glutHideWindow () ; + glutSetWindow ( status_window ) ; + return ; + } + + /* Save the new current directory */ + strcpy(pguide_current_directory, filename) ; + int i = strlen(pguide_current_directory); + while (pguide_current_directory[i] != PATH_SEPARATOR) { + if (i>0) i-- ; + else break ; + } + pguide_current_directory[i+1] = '\0' ; + + /* If they didn't give an extension, then tack ".cxx" onto the end. */ + if(!strstr(filename, ".")) + sprintf(filename, "%s.cxx", filename); + + FILE *out = fopen ( filename, "wt" ) ; + if ( !out ) + printf ( "ERROR opening file <%s> for writing\n", filename ) ; + + puDeleteObject ( file_selector ) ; + file_selector = (puaFileSelector *)NULL ; + glutHideWindow () ; + glutSetWindow ( status_window ) ; + + if ( !out ) return ; + + // Start writing code: + + fprintf ( out, "// TODO: Initial documentation\n" ) ; + fprintf ( out, "// TODO: Configuration Management system flags\n\n" ) ; + + fprintf ( out, "// TODO: Any additional includes you may need\n\n" ) ; + + fprintf ( out, "#include \n\n" ) ; + fprintf ( out, "#include \n\n" ) ; + fprintf ( out, "#include // TODO: Decide if you really need this\n\n" ) ; + + fprintf ( out, "// GLUT Window Handle\n" ) ; + fprintf ( out, "int window_handle ;\n\n" ) ; + + WidgetList *wid = widgets ; + fprintf ( out, "// PUI Widget Handles:\n" ) ; + + while ( wid ) + { + fprintf ( out, "%s *%s = (%s *)NULL ;\n", wid->object_type_name, wid->object_name, + wid->object_type_name ) ; + wid = wid->next ; + } + + fprintf ( out, "\n" ) ; + + // GLUT Callbacks: + + fprintf ( out, "// GLUT Callbacks:\n" ) ; + fprintf ( out, "static void specialfn ( int key, int x, int y )\n" ) ; + fprintf ( out, "{\n" ) ; + fprintf ( out, " // TODO: Put any of your own special-key functionality in here\n" ) ; + fprintf ( out, " puKeyboard ( key + PU_KEY_GLUT_SPECIAL_OFFSET, PU_DOWN ) ;\n" ) ; + fprintf ( out, " glutPostRedisplay () ;\n" ) ; + fprintf ( out, "}\n\n" ) ; + + fprintf ( out, "static void keyfn ( unsigned char key, int x, int y )\n" ) ; + fprintf ( out, "{\n" ) ; + fprintf ( out, " // TODO: Put any of your own keyboard functionality in here\n" ) ; + fprintf ( out, " puKeyboard ( key, PU_DOWN ) ;\n" ) ; + fprintf ( out, " glutPostRedisplay () ;\n" ) ; + fprintf ( out, "}\n\n" ) ; + + fprintf ( out, "static void motionfn ( int x, int y )\n" ) ; + fprintf ( out, "{\n" ) ; + fprintf ( out, " // TODO: Put any of your own mouse motion functionality in here\n" ) ; + fprintf ( out, " puMouse ( x, y ) ;\n" ) ; + fprintf ( out, " glutPostRedisplay () ;\n" ) ; + fprintf ( out, "}\n\n" ) ; + + fprintf ( out, "static void mousefn ( int button, int updown, int x, int y )\n" ) ; + fprintf ( out, "{\n" ) ; + fprintf ( out, " // TODO: Put any of your own mouse click functionality in here\n" ) ; + fprintf ( out, " puMouse ( button, updown, x, y ) ;\n" ) ; + fprintf ( out, " glutPostRedisplay () ;\n" ) ; + fprintf ( out, "}\n\n" ) ; + + fprintf ( out, "static void displayfn ( void )\n" ) ; + fprintf ( out, "{\n" ) ; + fprintf ( out, " // Clear the screen\n\n" ) ; + fprintf ( out, " glClearColor ( %f, %f, %f, %f ) ;\n", main_window_color_r, main_window_color_g, + main_window_color_b, main_window_color_a ) ; + fprintf ( out, " glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;\n\n" ) ; + + fprintf ( out, " // TODO: Put any of your own window display in here\n\n" ) ; + + fprintf ( out, " // Make PUI display\n" ) ; + fprintf ( out, " puDisplay () ;\n\n" ) ; + + fprintf ( out, " glutSwapBuffers () ;\n" ) ; + fprintf ( out, " glutPostRedisplay () ;\n" ) ; + fprintf ( out, "}\n\n" ) ; + + fprintf ( out, "// TODO: Put any of your own additional GLUT callbacks in here\n\n" ) ; + + // PUI Callbacks + + fprintf ( out, "// PUI Callbacks:\n\n" ) ; + + wid = widgets ; + + while ( wid ) + { + if ( wid->callbacks & 0x01 ) // Up-callback defined + { + fprintf ( out, "void %s_cb ( puObject *ob )\n", wid->object_name ) ; + fprintf ( out, "{\n" ) ; + fprintf ( out, " // TODO: Put your up-callback functionality in here\n" ) ; + fprintf ( out, "}\n\n" ) ; + } + + if ( wid->callbacks & 0x02 ) // Active callback defined + { + fprintf ( out, "void %s_active_cb ( puObject *ob )\n", wid->object_name ) ; + fprintf ( out, "{\n" ) ; + fprintf ( out, " // TODO: Put your active callback functionality in here\n" ) ; + fprintf ( out, "}\n\n" ) ; + } + + if ( wid->callbacks & 0x04 ) // Down-callback defined + { + fprintf ( out, "void %s_down_cb ( puObject *ob )\n", wid->object_name ) ; + fprintf ( out, "{\n" ) ; + fprintf ( out, " // TODO: Put your down-callback functionality in here\n" ) ; + fprintf ( out, "}\n\n" ) ; + } + + wid = wid->next ; + } + + fprintf ( out, "\n\n" ) ; + + // The Main Program + + fprintf ( out, "//**********************************************************\n" ) ; + fprintf ( out, "//* The Main Program *\n" ) ; + fprintf ( out, "//**********************************************************\n\n" ) ; + + fprintf ( out, "int main ( int argc, char *argv[] )\n" ) ; + fprintf ( out, "{\n" ) ; + fprintf ( out, " // TODO: Add any non-GLUT functionality you want to\n\n" ) ; + + fprintf ( out, " // Create the GLUT window:\n" ) ; + fprintf ( out, " glutInitWindowPosition( %d, %d ) ;\n", main_window_x, main_window_y ) ; + fprintf ( out, " glutInitWindowSize ( %d, %d ) ;\n", main_window_width, main_window_height ) ; + fprintf ( out, " glutInit ( &argc, argv ) ;\n" ) ; + fprintf ( out, " glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ;\n" ) ; + fprintf ( out, " window_handle = glutCreateWindow ( \"%s\" ) ;\n\n", main_window_name ) ; + + fprintf ( out, " // GLUT Windowing Callbacks:\n" ) ; + fprintf ( out, " glutDisplayFunc ( displayfn ) ;\n" ) ; + fprintf ( out, " glutKeyboardFunc ( keyfn ) ;\n" ) ; + fprintf ( out, " glutSpecialFunc ( specialfn ) ;\n" ) ; + fprintf ( out, " glutMouseFunc ( mousefn ) ;\n" ) ; + fprintf ( out, " glutMotionFunc ( motionfn ) ;\n" ) ; + fprintf ( out, " glutPassiveMotionFunc ( motionfn ) ;\n" ) ; + fprintf ( out, " glutIdleFunc ( displayfn ) ;\n" ) ; + fprintf ( out, " // TODO: Add any additional GLUT callbacks that you defined earlier\n\n" ) ; + + fprintf ( out, " // Initialize PUI:\n" ) ; + fprintf ( out, " puInit () ;\n\n" ) ; + + // TO DO: Allow the user to select his own default fonts, style, and colour scheme + + fprintf ( out, " // PUI Default Style, and Colors:\n" ) ; + fprintf ( out, " puSetDefaultStyle ( PUSTYLE_SMALL_SHADED ) ;\n" ) ; + fprintf ( out, " puSetDefaultColourScheme ( 0.3f, 0.4f, 0.6f, 1.0f ) ;\n" ) ; + fprintf ( out, " // TODO: Customize this as you like\n\n" ) ; + + fprintf ( out, " // Define the widgets:\n\n" ) ; + + fprintf ( out, " puGroup *window_group = new puGroup ( 0, 0 ) ;\n\n" ) ; + + int layer ; + for ( layer = 0; layer < max_layer; layer++ ) + { + wid = widgets ; + while ( wid ) + { + if ( layer == wid->layer ) + { + puObject *ob = wid->obj ; + int x, y, w, h ; + ob->getPosition ( &x, &y ) ; + ob->getSize ( &w, &h ) ; + + /* Customize widget's constructor and extra details */ + /* fprintf ( out, " %s = new %s ( %d, %d, %d, %d ) ;\n", wid->object_name, + wid->object_type_name, x, y, x+w, y+h ) ; */ + + /* General minx, miny, maxx, maxy constructor */ + if ( (wid->object_type == PUCLASS_FRAME ) || + (wid->object_type == PUCLASS_BUTTON ) || + (wid->object_type == PUCLASS_INPUT ) || + (wid->object_type == PUCLASS_BISLIDERWITHENDS)) + { + fprintf ( out, " %s = new %s (%d, %d, %d, %d ) ;\n", wid->object_name, wid->object_type_name, x, y, x+w, y+h) ; + } + + /* General minx, miny constructor */ + if (wid->object_type == PUCLASS_TEXT) + { + /* Add in font properties? */ + fprintf ( out, " %s = new %s (%d, %d ) ;\n", wid->object_name, wid->object_type_name, x, y) ; + } + + if (wid->object_type == PUCLASS_ONESHOT) + { + /* + Add support for both constructors! + puButton::puButton ( int minx, int miny, const char *legend ) ; + puButton::puButton ( int minx, int miny, int maxx, int maxy ) ; + + */ + fprintf ( out, " %s = new %s (%d, %d, %d, %d ) ;\n", wid->object_name, wid->object_type_name, x, y, x+w, y+h) ; + } + + if ( (wid->object_type == PUCLASS_MENUBAR) || + (wid->object_type == PUCLASS_VERTMENU) ) { + + if (wid->items) + { + char *temp_items = wid->items ; + char *cr = strchr(temp_items, '\n'); + while ( cr != '\0' ) + { + char *spc = strchr ( temp_items, ' ' ) ; + while ( spc ) + { + *spc = '_' ; + spc = strchr ( temp_items, ' ' ) ; + } + spc = strchr ( temp_items, ':' ) ; + while ( spc ) + { + *spc = '_' ; + spc = strchr ( temp_items, ':' ) ; + } + spc = strchr ( temp_items, ';' ) ; + while ( spc ) + { + *spc = '_' ; + spc = strchr ( temp_items, ';' ) ; + } + spc = strchr ( temp_items, ',' ) ; + while ( spc ) + { + *spc = '_' ; + spc = strchr ( temp_items, ',' ) ; + } + spc = strchr ( temp_items, '.' ) ; + while ( spc ) + { + *spc = '_' ; + spc = strchr ( temp_items, '.' ) ; + } + *cr = '\0'; + fprintf ( out, " static char *%s_%s_submenu [] = { \"Filler\", NULL } ;\n", wid->object_name, temp_items) ; + fprintf ( out, " /* TODO: You need to create your own callbacks here, such as { \"exit_cb\",\"delete_cb\",NULL } */ \n") ; + fprintf ( out, " puCallback %s_%s_submenu_cb [] = { NULL, NULL } ;\n\n", wid->object_name, temp_items) ; + *cr = '\n'; + temp_items = cr + 1; + cr = strchr(temp_items, '\n'); + } + } + + if (wid->object_type == PUCLASS_MENUBAR) { + /* TODO: add in "height" support */ + fprintf ( out, " %s = new %s ( ) ;\n", wid->object_name, wid->object_type_name) ; + } + + if (wid->object_type == PUCLASS_VERTMENU) { + /* TODO: add in "lock to corner" support */ + fprintf ( out, " %s = new %s (%d, %d ) ;\n", wid->object_name, wid->object_type_name, x, y) ; + } + + if (wid->items) + { + char *temp_items = wid->items ; + char unspaced_items[PUSTRING_MAX]; + char *cr = strchr(temp_items, '\n'); + fprintf ( out, " {\n") ; + while ( cr != '\0' ) + { + *cr = '\0'; + strcpy(unspaced_items, temp_items); + /* Put back the space */ + char *spc = strchr ( temp_items, '_' ) ; + while ( spc ) + { + *spc = ' ' ; + spc = strchr ( temp_items, '_' ) ; + } + /* Now "unspaced_items" writes "I_have_no_spaces" while temp_items writes "I have no spaces" (AND LIES!) */ + fprintf ( out, " %s->add_submenu (\"%s\", %s_%s_submenu, %s_%s_submenu_cb ) ;\n", wid->object_name, temp_items, wid->object_name, unspaced_items, wid->object_name, unspaced_items ) ; + *cr = '\n'; + temp_items = cr + 1; + cr = strchr(temp_items, '\n'); + } + fprintf ( out, " }\n") ; + } + fprintf ( out, " %s->close() ;\n", wid->object_name) ; + } + + if ( (wid->object_type == PUCLASS_LISTBOX) || + (wid->object_type == PUCLASS_COMBOBOX) || + (wid->object_type == PUCLASS_SELECTBOX) || + (wid->object_type == PUCLASS_BUTTONBOX) || + (wid->object_type == PUCLASS_LIST)) + { + char data[1024]; + char onedata[PUSTRING_MAX]; + + if (wid->items) + { + char *temp_items = wid->items ; + char *cr = strchr(temp_items, '\n'); + sprintf ( data, " "); + while ( cr != '\0' ) + { + *cr = '\0'; + sprintf ( onedata, "\"%s\",", temp_items); + *cr = '\n'; + temp_items = cr + 1; + cr = strchr(temp_items, '\n'); + strcat(data, onedata); + } + } + + fprintf ( out, " static char *%s_entries [] = { %s NULL } ;\n", wid->object_name, data) ; + if ( (wid->object_type == PUCLASS_LISTBOX) || + (wid->object_type == PUCLASS_LIST) ) + fprintf ( out, " %s = new %s (%d, %d, %d, %d, %s_entries ) ;\n", wid->object_name, wid->object_type_name, x, y, x+w, y+h, wid->object_name) ; + if (wid->object_type == PUCLASS_BUTTONBOX) + fprintf ( out, " %s = new %s (%d, %d, %d, %d, %s_entries, %s ) ;\n", wid->object_name, wid->object_type_name, x, y, x+w, y+h, wid->object_name, trueOrFalse(wid->boolval1)) ; + if (wid->object_type == PUCLASS_COMBOBOX) + { + fprintf ( out, " %s = new %s (%d, %d, %d, %d, %s_entries, %s ) ;\n", wid->object_name, wid->object_type_name, x, y, x+w, y+h, wid->object_name, trueOrFalse(wid->boolval1)) ; + fprintf ( out, " %s->setCurrentItem(%d) ;\n", wid->object_name, wid->intval1) ; + } + if (wid->object_type == PUCLASS_SELECTBOX) + { + fprintf ( out, " %s = new %s (%d, %d, %d, %d, %s_entries ) ;\n", wid->object_name, wid->object_type_name, x, y, x+w, y+h, wid->object_name) ; + fprintf ( out, " %s->setCurrentItem(%d) ;\n", wid->object_name, wid->intval1) ; + } + } + + if (wid->object_type == PUCLASS_POPUPMENU) + { + /* Allow a list of menu items, and remember to point out these are hidden when created, and must be reveal()ed. */ + /* NOT CURRENTLY IMPLEMENTED */ + } + + /* puRange */ + if ( (wid->object_type == PUCLASS_SLIDER ) || + (wid->object_type == PUCLASS_BISLIDER ) || + (wid->object_type == PUCLASS_TRISLIDER ) || + (wid->object_type == PUCLASS_DIAL ) || + (wid->object_type == PUCLASS_SPINBOX ) || + (wid->object_type == PUCLASS_SCROLLBAR ) ) + { + + /* Constructors */ + if ( (wid->object_type == PUCLASS_SLIDER ) || + (wid->object_type == PUCLASS_BISLIDER ) || + (wid->object_type == PUCLASS_TRISLIDER )) + { + /* Sliders */ + fprintf ( out, " %s = new %s (%d, %d, %d, %s, %d ) ;\n", wid->object_name, wid->object_type_name, x, y, (wid->boolval2==1)?h:w, trueOrFalse(wid->boolval2), (wid->boolval2==1)?w:h) ; + /* Slider value options */ + if (wid->object_type == PUCLASS_SLIDER ) + fprintf ( out, " %s->setValue(%ff) ;\n", wid->object_name, wid->floatval4) ; + if ( (wid->object_type == PUCLASS_BISLIDER ) || (wid->object_type == PUCLASS_TRISLIDER ) ) + { + fprintf ( out, " %s->setCurrentMax(%ff) ;\n", wid->object_name, wid->floatval4) ; + fprintf ( out, " %s->setCurrentMin(%ff) ;\n", wid->object_name, wid->floatval5) ; + if (wid->object_type == PUCLASS_TRISLIDER ) + { + if (!wid->boolval3) + fprintf ( out, " %s->setFreezeEnds(FALSE) ;\n", wid->object_name ) ; + fprintf ( out, " %s->setValue(%ff) ;\n", wid->object_name, wid->floatval6) ; + fprintf ( out, " %s->setSliderFraction(0.1f) ;\n", wid->object_name) ; + /*Allow setting the slider fraction?*/ + } + } + } else if (wid->object_type == PUCLASS_DIAL ) + { + fprintf ( out, " %s = new %s (%d, %d, %d ) ;\n", wid->object_name, wid->object_type_name, x, y, (h+w)/2) ; + fprintf ( out, " %s->setWrap(%s) ;\n", wid->object_name, trueOrFalse(wid->boolval2)) ; + + } else if (wid->object_type == PUCLASS_SPINBOX ) + { + fprintf ( out, " %s = new %s (%d, %d, %d, %d, %s ) ;\n", wid->object_name, wid->object_type_name, x, y, x+w, y+h, trueOrFalse(wid->boolval2) ) ; + fprintf ( out, " %s->setArrowHeight(%ff) ;\n", wid->object_name, wid->floatval4 ) ; + + } else if (wid->object_type == PUCLASS_SCROLLBAR ) + { + fprintf ( out, " %s = new %s (%d, %d, %d, %d, %d, %s ) ;\n", wid->object_name, wid->object_type_name, x, y, x+w, y+h, wid->intval1, trueOrFalse(wid->boolval2) ) ; + fprintf ( out, " %s->setArrowHeight(%ff) ;\n", wid->object_name, wid->floatval4 ) ; + } + /* All puRange options */ + fprintf ( out, " %s->setMaxValue (%ff) ;\n", wid->object_name, wid->floatval1 ) ; + fprintf ( out, " %s->setMinValue (%ff) ;\n", wid->object_name, wid->floatval2 ) ; + fprintf ( out, " %s->setStepSize (%ff) ;\n", wid->object_name, wid->floatval3 ) ; + char cbmodetext[20] = "PUSLIDER_ALWAYS"; + if (wid->boolval1) + strcpy(cbmodetext,"PUSLIDER_ALWAYS"); + else + strcpy(cbmodetext,"PUSLIDER_CLICK"); + fprintf ( out, " %s->setCBMode (%s) ;\n", wid->object_name, cbmodetext) ; + } + + if (wid->object_type == PUCLASS_DIALOGBOX) + { + /* Not yet implemented as a class */ + } + + if (wid->object_type == PUCLASS_ARROW) + { + char arr_name[20] = "PUARROW_UP"; + if (wid->items) + { + if (strstr(wid->items,"Double-Up")) + strcpy(arr_name, "PUARROW_FASTUP"); + else if (strstr(wid->items,"Double-Down")) + strcpy(arr_name, "PUARROW_FASTDOWN"); + else if (strstr(wid->items,"Double-Left")) + strcpy(arr_name, "PUARROW_FASTLEFT"); + else if (strstr(wid->items,"Double-Right")) + strcpy(arr_name, "PUARROW_FASTRIGHT"); + else if (strstr(wid->items,"Up")) + strcpy(arr_name, "PUARROW_UP"); + else if (strstr(wid->items,"Down")) + strcpy(arr_name, "PUARROW_DOWN"); + else if (strstr(wid->items,"Left")) + strcpy(arr_name, "PUARROW_LEFT"); + else if (strstr(wid->items,"Right")) + strcpy(arr_name, "PUARROW_RIGHT"); + } + fprintf ( out, " %s = new puArrowButton (%d, %d, %d, %d, %s ) ;\n", wid->object_name, x, y, x+w, y+h, arr_name) ; + } + + if (wid->object_type == PUCLASS_CHOOSER) + { + // Just give it a dummy legend; set the legend later on + fprintf ( out, " %s = new %s (%d, %d, %d, %d, "" ) ;\n", wid->object_name, wid->object_type_name, x, y, x+w, y+h) ; + } + + if (wid->object_type == PUCLASS_SLIDERWITHINPUT) + { + // Extra argument for input box being on the bottom of the slider + fprintf ( out, " %s = new %s (%d, %d, %d, %d, 0 ) ;\n", wid->object_name, wid->object_type_name, x, y, x+w, y+h) ; + } + + if (wid->object_type == PUCLASS_INPUT ) + { + /*Already had its constructor defined by the general -- look up*/ + if (wid->boolval1 == false) + fprintf ( out, " %s->rejectInput() ;\n", wid->object_name ) ; + if ( wid->allowed) + fprintf ( out, " %s->setValidData(\"%s\") ;\n", wid->object_name, wid->allowed ) ; + } + + if ( wid->object_type == PUCLASS_LARGEINPUT ) + { + fprintf ( out, " %s = new %s (%d, %d, %d, %d, %d, %d ) ;\n", wid->object_name, wid->object_type_name, x, y, w, h, wid->intval1, wid->intval2 ) ; + if (wid->boolval1 == false) + fprintf ( out, " %s->rejectInput() ;\n", wid->object_name ) ; + if ( wid->allowed) + fprintf ( out, " %s->setValidData(\"%s\") ;\n", wid->object_name, wid->allowed ) ; + + } + /* Done custom constructor and extra details */ + + if ( wid->callbacks & 0x01 ) // Up-callback defined + fprintf ( out, " %s->setCallback ( %s_cb ) ;\n", wid->object_name, wid->object_name ) ; + + if ( wid->callbacks & 0x02 ) // Active callback defined + fprintf ( out, " %s->setActiveCallback ( %s_active_cb ) ;\n", wid->object_name, wid->object_name ) ; + + if ( wid->callbacks & 0x04 ) // Down-callback defined + fprintf ( out, " %s->setDownCallback ( %s_down_cb ) ;\n", wid->object_name, wid->object_name ) ; + + // TO DO: Allow the user to customize colour and style + + const char *place_name [] = { "PUPLACE_TOP_LEFT", "PUPLACE_TOP_CENTERED", "PUPLACE_TOP_RIGHT", + "PUPLACE_CENTERED_LEFT", "PUPLACE_CENTERED_RIGHT", + "PUPLACE_BOTTOM_LEFT", "PUPLACE_BOTTOM_CENTERED", "PUPLACE_BOTTOM_RIGHT", + "PUPLACE_CENTERED_CENTERED", + "PUPLACE_ABOVE_LEFT", "PUPLACE_ABOVE_RIGHT", + "PUPLACE_BELOW_LEFT", "PUPLACE_BELOW_RIGHT", + "PUPLACE_UPPER_LEFT", "PUPLACE_UPPER_RIGHT", + "PUPLACE_LOWER_LEFT", "PUPLACE_LOWER_RIGHT" } ; + + if ( wid->label_text ) + { + fprintf ( out, " %s->setLabel ( \"%s\" ) ;\n", wid->object_name, wid->label_text ) ; + fprintf ( out, " %s->setLabelPlace ( %s ) ;\n", wid->object_name, place_name [ ob->getLabelPlace () ] ) ; + // TO DO: Check for label font and print it + } + + if ( wid->legend_text ) + { + fprintf ( out, " %s->setLegend ( \"%s\" ) ;\n", wid->object_name, wid->legend_text ) ; + fprintf ( out, " %s->setLegendPlace ( %s ) ;\n", wid->object_name, place_name [ ob->getLegendPlace () ] ) ; + // TO DO: Check for legend font and print it + } + + if( !wid->visible ) + fprintf ( out, " %s->hide () ;\n", wid->object_name ) ; + + fprintf ( out, " \n" ) ; + + } + wid = wid->next ; + } + } + + fprintf ( out, "\n\n" ) ; + + fprintf ( out, " window_group->close () ;\n\n\n" ) ; + + fprintf ( out, " // GLUT Main Loop\n" ) ; + fprintf ( out, " glutMainLoop () ;\n" ) ; + fprintf ( out, " return 0;\n" ) ; + fprintf ( out, "}\n\n" ) ; + + // Close up shop + fclose ( out ) ; + main_window_changed = false ; +} + diff --git a/demos/p-guide/src/example.xml b/demos/p-guide/src/example.xml new file mode 100644 index 0000000..9d0d744 --- /dev/null +++ b/demos/p-guide/src/example.xml @@ -0,0 +1,504 @@ + + + + +VERSION +Test Project +TRUE + + Sample P-Guide File + + 600 + 400 + + + 0 + 0 + + + 0.750000 + 0.550000 + 0.650000 + 1.000000 + + + + + + left_arrow + puArrowButton + Up + 1 + TRUE + TRUE + + 24 + 101 + + + 93 + 96 + + + 0 + 0 + FALSE + FALSE + FALSE + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + Double-Left + + + + right_arrow + puArrowButton + Up + 1 + TRUE + TRUE + + 25 + 101 + + + 127 + 96 + + + 0 + 0 + FALSE + FALSE + FALSE + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + Double-Right + + + + combo + puComboBox + Up + 1 + TRUE + TRUE + + 166 + 70 + + + 89 + 20 + + + 2 + 0 + FALSE + FALSE + FALSE + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + Option 1 + Option 2 + Option 3 + Final + + + + oneshot3 + + Run Away + PUPLACE_CENTERED_CENTERED + + puOneShot + Up + 1 + TRUE + TRUE + + 90 + 20 + + + 154 + 127 + + + 0 + 0 + FALSE + FALSE + FALSE + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + + + + oneshot2 + + Shoot + PUPLACE_CENTERED_CENTERED + + puOneShot + Up + 1 + TRUE + TRUE + + 90 + 20 + + + 154 + 152 + + + 0 + 0 + FALSE + FALSE + FALSE + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + + + + oneshot1 + + Execute + PUPLACE_CENTERED_CENTERED + + puOneShot + Up + 1 + TRUE + TRUE + + 90 + 20 + + + 154 + 177 + + + 0 + 0 + FALSE + FALSE + FALSE + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + + + + dizzy + puSpinBox + Up + 1 + TRUE + TRUE + + 166 + 40 + + + 89 + 205 + + + 0 + 0 + TRUE + TRUE + FALSE + 20.000000 + 0.000000 + 1.000000 + 0.500000 + 0.000000 + 0.000000 + + + + libris + + puLargeInput + Up + 1 + TRUE + TRUE + + 334 + 232 + + + 258 + 13 + + + 2 + 5 + TRUE + FALSE + FALSE + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + + + + + dial2 + puDial + Up + 0 + TRUE + TRUE + + 50 + 50 + + + 88 + 255 + + + 0 + 0 + TRUE + TRUE + FALSE + 5.000000 + 0.000000 + 1.000000 + 0.000000 + 0.000000 + 0.000000 + + + + dial1 + puDial + Up + 0 + TRUE + FALSE + + 50 + 50 + + + 87 + 309 + + + 0 + 0 + TRUE + TRUE + FALSE + 1.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + + + + slider + puSlider + Up + 0 + TRUE + TRUE + + 35 + 356 + + + 50 + 7 + + + 0 + 0 + TRUE + TRUE + FALSE + 10.000000 + 0.000000 + 0.000000 + 0.500000 + 0.000000 + 0.000000 + + + + trislider + puTriSlider + Up + 0 + TRUE + FALSE + + 47 + 356 + + + 1 + 7 + + + 0 + 0 + TRUE + TRUE + FALSE + 17.000000 + -5.000000 + 2.000000 + 16.000000 + -0.500000 + 0.500000 + + + + menu_bar + puMenuBar + Up + 0 + TRUE + TRUE + + 120 + 30 + + + 0 + 367 + + + 0 + 0 + FALSE + FALSE + FALSE + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + File + Edit + View + Project + Build + Debug + Tools + Options + Window + Bookmarks + Help + + + + buttonbox + puButtonBox + Up + 1 + TRUE + TRUE + + 163 + 134 + + + 428 + 249 + + + 0 + 0 + FALSE + FALSE + FALSE + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + On + Off + Automatic + + + + widget1 + + puText + Up + 1 + TRUE + TRUE + + 5 + 20 + + + 173 + 360 + + + 0 + 0 + FALSE + FALSE + FALSE + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + 0.000000 + + + + diff --git a/demos/p-guide/src/pGuide.cxx b/demos/p-guide/src/pGuide.cxx new file mode 100644 index 0000000..b8a0d51 --- /dev/null +++ b/demos/p-guide/src/pGuide.cxx @@ -0,0 +1,916 @@ +/* + This file is part of P-GUIDE - + PUI-based Graphical User Interface Designer. + Copyright (C) 2002, 2006 John F. Fay + + P-GUIDE 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. + + P-GUIDE 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 P-GUIDE; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + $Id: pGuide.cxx 2083 2006-05-01 13:14:50Z bram $ +*/ + +#ifdef VERSION +#undef VERSION +#endif + +#define VERSION = "0.1a" + +// Program to allow the user to build a PUI Graphical User Interface + +#include "WidgetList.h" + +WidgetList *widgets = (WidgetList *)NULL ; +int max_layer = 1 ; + +puObject *active_object = (puObject *)NULL ; +WidgetList *active_widget = (WidgetList *)NULL ; +static short activity_flag = 0 ; // 0 - inactive; 1 - moving; 2 - resizing xmin, 3 - resizing ymin, 4 - resizing xmax, 5 - resizing ymax +static int resize_symmetric = 1 ; +static int resize_corner = 0 ; + +static int mouse_x_position_in_object = 0 ; +static int mouse_y_position_in_object = 0 ; + +static int pguide_last_buttons = 0 ; // Because puMouse isn't called, we have to do our own last_buttons checking + +// Main window parameters +int main_window = 0 ; // Main window handle +int main_window_width = 600 ; +int main_window_height = 600 ; +char main_window_name [ PUSTRING_MAX ] ; +int main_window_x = 0, main_window_y = 0 ; + +float main_window_color_r = 1.0, main_window_color_g = 1.0, + main_window_color_b = 1.0, main_window_color_a = 1.0 ; + +bool main_window_changed = false ; +static bool done_first_setup = false ; +bool currently_loading = false ; + +static int ctrl_key_down = 0 ; + +static int mouse_x = 0 ; +static int mouse_y = 0 ; + +char pguide_current_directory [ PUSTRING_MAX ] ; + +// Widget count +int widget_number = 0 ; + +// Upon creation of new widgets, should they automatically be made "locked"? +bool autolock = false ; + +// Properties popup +static puPopupMenu *context_menu; + +// From the status window: +extern void setStatusWidgets ( WidgetList *wid ) ; + +// From the properties window: +extern int properties_window; + +// Definitions +#define RESIZING_BORDER_WIDTH 5 +#define RESIZING_CORNER_BORDER_WIDTH 4 + /** 4 seems to be the best number for this define... this makes sure * + * that the default widget size allows you to still resize along the * + * X axis without difficulty - 23 Jan 03 JCJ **/ + + +// Properties Callback + +static void cb_edit_properties ( puObject *ob ) +{ + if (properties_window) + { + extern puGroup *properties_group; + /* Delete the widgets */ + puDeleteObject( properties_group ); + glutDestroyWindow( properties_window ); + properties_window = 0; + glutSetWindow( main_window ); + } + extern int define_properties_window () ; + // Open the properties menu + define_properties_window(); +} + +static void cb_lock_toggle ( puObject *ob ) +{ + WidgetList *wid = widgets ; + while ( wid ) + { + if ( wid->obj == active_object ) + { + if (wid->locked == false) + wid->locked = true ; + else + wid->locked = false ; + } + wid = wid->next ; + } +} + +static void cb_popup_delete ( puObject *ob ) +{ + WidgetList *wid = widgets ; + WidgetList *prv = (WidgetList *)NULL ; + while ( wid ) + { + if ( wid->obj == active_object ) + { + if ( prv ) // Remove the widget from the linked list + prv->next = wid->next ; + else + widgets = wid->next ; + + delete wid->object_type_name ; // Delete the widget + delete wid->legend_text ; + delete wid->label_text ; + delete wid->obj ; + delete wid->allowed ; + delete wid->items ; + delete wid ; + active_widget = (WidgetList *)NULL ; + active_object = (puObject *)NULL ; + wid = (WidgetList *)NULL ; + if (properties_window) + { + extern puGroup *properties_group; + /* Delete the widgets */ + puDeleteObject( properties_group ); + glutDestroyWindow( properties_window ); + properties_window = 0; + glutSetWindow( main_window ); + } + } + else + { + prv = wid ; + wid = wid->next ; + } + } +} + + +// GLUT Main Window Callbacks + +static void process_key ( int key ) +{ + extern int selected_object_type ; + extern puButton *active_button ; + + ctrl_key_down = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ; +#define NUDGE_DISTANCE 1 +#define LARGE_NUDGE_DISTANCE 10 + + if ( active_object ) // Active object; check the keys + { + main_window_changed = true ; + + int xo, yo ; + active_object->getPosition ( &xo, &yo ) ; + int dist = ctrl_key_down ? LARGE_NUDGE_DISTANCE : NUDGE_DISTANCE ; + + if ( key == GLUT_KEY_LEFT ) + active_object->setPosition ( xo-dist, yo ) ; + else if ( key == GLUT_KEY_RIGHT ) + active_object->setPosition ( xo+dist, yo ) ; + else if ( key == GLUT_KEY_UP ) + active_object->setPosition ( xo, yo+dist ) ; + else if ( key == GLUT_KEY_DOWN ) + active_object->setPosition ( xo, yo-dist ) ; + else if ( ( key == 127 ) || ( key == 8 ) ) // Delete or Backspace + { + WidgetList *wid = widgets ; + WidgetList *prv = (WidgetList *)NULL ; + while ( wid ) + { + if ( wid->obj == active_object ) + { + if ( prv ) // Remove the widget from the linked list + prv->next = wid->next ; + else + widgets = wid->next ; + + delete wid->object_type_name ; // Delete the widget + delete wid->legend_text ; + delete wid->label_text ; + delete wid->obj ; + delete wid->allowed ; + delete wid->items ; + delete wid ; + active_widget = (WidgetList *)NULL ; + active_object = (puObject *)NULL ; + wid = (WidgetList *)NULL ; + } + else + { + prv = wid ; + wid = wid->next ; + } + } + } + else if ( key == 27 ) // Escape key, deactivate the object + { + active_widget = (WidgetList *)NULL ; + active_object = (puObject *)NULL ; + } + + setStatusWidgets ( active_widget ) ; + } + + if ( selected_object_type ) + { + if ( key == 27 ) // Escape key, deactivate the selected button + { + selected_object_type = 0 ; + active_button->setValue ( 0 ) ; + } + } + + glutPostRedisplay () ; +} + +static void main_window_specialfn ( int key, int, int ) +{ + process_key ( key ) ; +} + +static void main_window_keyfn ( unsigned char key, int, int ) +{ + process_key ( key ) ; +} + +static void main_window_motionfn ( int x, int yy ) +{ + int y = main_window_height - yy ; + + mouse_x = x ; + mouse_y = y ; + + // Dragging the mouse: If there is an active object, slide it around + if ( ( active_object ) && ( pguide_last_buttons != 4 ) ) + { + WidgetList *wid = widgets ; + while ( wid ) + { + if ( wid->obj == active_object ) + { + if (wid->locked == false) + { + extern puInput *object_position_x ; + extern puInput *object_position_y ; + extern puInput *object_size_x ; + extern puInput *object_size_y ; + + main_window_changed = true ; + + int dist ; + int xo, yo ; + active_object->getPosition ( &xo, &yo ) ; + int w, h ; + active_object->getSize ( &w, &h ) ; + + if (resize_corner == 1) + { + switch ( activity_flag ) + { + case 2 : // Resize top-right + case 3 : + activity_flag = 6; + break ; + + case 4 : // Resize bottom_left + case 5 : + activity_flag = 7; + break ; + } + } + + switch ( activity_flag ) + { + case 1 : // Moving the object + active_object->setPosition ( x - mouse_x_position_in_object, + y - mouse_y_position_in_object ) ; + break ; + + case 2 : // Resizing on x-min + dist = x - xo ; + if (w - dist < 5) break ; + if ( resize_symmetric * dist > w ) dist = w / resize_symmetric - 1 ; + active_object->setPosition ( x, yo ) ; + active_object->setSize ( w - resize_symmetric * dist, h ) ; + break ; + + case 3 : // Resizing on y-min + dist = y - yo ; + if (h - dist < 5) break ; + if ( resize_symmetric * dist > h ) dist = h / resize_symmetric - 1 ; + active_object->setPosition ( xo, y ) ; + active_object->setSize ( w, h - resize_symmetric * dist ) ; + break ; + + case 4 : // Resizing on x-max + dist = x - xo - w ; + if (w + dist < 5) break ; + if ( resize_symmetric * dist < -w ) dist = 1 - w / resize_symmetric ; + active_object->setSize ( w + resize_symmetric * dist, h ) ; + if ( resize_symmetric == 2 ) active_object->setPosition ( xo - dist, yo ) ; + break ; + + case 5 : // Resizing on y-max + dist = y - yo - h ; + if (h + dist < 5) break ; + if ( resize_symmetric * dist < -h ) dist = 1 - h / resize_symmetric ; + active_object->setSize ( w, h + resize_symmetric * dist ) ; + if ( resize_symmetric == 2 ) active_object->setPosition ( xo, yo - dist ) ; + break ; + + case 6 : // Resizing bottom-left + if ( yo - y > xo - x ) + dist = yo - y; + else + dist = xo - x; + if ( (w + dist < 5) || (h + dist < 5) ) break ; + active_object->setPosition ( xo - dist, yo - dist ) ; + active_object->setSize ( w + dist, h + dist ) ; + break ; + + case 7 : // Resizing top-right + if (y-yo-h>x-xo-w) + dist = y - yo - h ; + else + dist = x - xo - w ; + if ( (w + dist < 5) || (h + dist < 5) ) break ; + active_object->setSize ( w + dist, h + dist ) ; + break ; + + case 8 : // Resizing top-left + if (y-yo-h>x-xo-w) + dist = y - yo - h ; + else + dist = xo - x ; + if ( (w + dist < 5) || (h + dist < 5) ) break ; + active_object->setPosition ( xo - dist, yo ) ; + active_object->setSize ( w + dist, h + dist ) ; + break ; + + case 9 : // Resizing bottom-right + if (y-yo-h>x-xo-w) + dist = yo - y ; + else + dist = x - xo - w ; + if ( (w + dist < 5) || (h + dist < 5) ) break ; + active_object->setPosition ( xo , yo - dist ) ; + active_object->setSize ( w + dist, h + dist ) ; + break ; + } + + int a, b ; + active_object->getPosition ( &a, &b ) ; + object_position_x->setValue ( a ) ; + object_position_y->setValue ( b ) ; + + active_object->getSize ( &a, &b ) ; + object_size_x->setValue ( a ) ; + object_size_y->setValue ( b ) ; + } + } + wid = wid->next ; + } + } + glutPostRedisplay () ; +} + +static void main_window_passivefn ( int x, int yy ) +{ + int y = main_window_height - yy ; + + // Dragging the mouse without a button down: save the mouse coordinates + mouse_x = x ; + mouse_y = y ; + /*if (context_menu->isVisible() == 1) + { + puBox *cont_box = context_menu->getABox(); + if ( ( x >= cont_box->min[0] ) && ( x <= cont_box->max[0] ) && + ( y >= cont_box->min[1] ) && ( y <= cont_box->max[1] ) ) + { + context_menu->checkHit(-1, 0, mouse_x, mouse_y); + } + }*/ +} + +static void main_window_mousefn ( int button, int updown, int x, int yy ) +{ + int y = main_window_height - yy ; + + mouse_x = x ; + mouse_y = y ; + + if ( updown == PU_DOWN ) + pguide_last_buttons |= ( 1 << button ) ; + else + pguide_last_buttons &= ~( 1 << button ) ; + + if ( button == PU_RIGHT_BUTTON ) + { + /* Pressed the right mouse button -- popup the manipulation window. */ + WidgetList *wid = widgets ; + while ( wid ) + { + puBox *box = wid->obj->getABox () ; + if ( wid->visible && ( x >= box->min[0] ) && ( x <= box->max[0] ) && + ( y >= box->min[1] ) && ( y <= box->max[1] ) ) + { + + active_widget = wid ; + active_object = wid->obj ; + /* We can modify mouse_x and mouse_y, because theyre not used again if we're in the right mouse function */ + /* If we're real close to the right of the screen, modify the X position ...*/ + if (mouse_x > main_window_width - 110 ) mouse_x = main_window_width - 110 ; + /* If we're real close to the top of the screen, modify the Y position...*/ + if (mouse_y > main_window_height - 140) mouse_y = main_window_height - 140 ; + + context_menu->setPosition(mouse_x, mouse_y) ; + context_menu->reveal() ; + //puSetActiveWidget(context_menu, mouse_x, mouse_y) ; + break ; + } + wid = wid->next ; + } + + } else { + if ( puActiveWidget() && ( active_object != puActiveWidget() ) ) + { + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + ctrl_key_down = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ; + + if ( ( context_menu->isVisible() == 1) && ( active_widget ) ) + { + puBox *cont_box = context_menu->getABox(); + if ( ( x >= cont_box->min[0] ) && ( x <= cont_box->max[0] ) && + ( y >= cont_box->min[1] ) && ( y <= cont_box->max[1] ) ) + { + context_menu->checkHit(button, updown, mouse_x, mouse_y); + } else { + context_menu->hide(); + } + } else /*if ( context_menu->isVisible() == 1) { context_menu->hide(); } * The user did something funny, so hide the menu since they've been naughty */ + { + // Downclick: Place a new widget, activate an existing widget, deactivate widget, or select from menu. + if ( updown == GLUT_DOWN ) + { + // If there is a selected object, create a new one of that type. + // extern puObject *createWidget ( int type ) ; + extern int selected_object_type ; + + if ( selected_object_type ) + { + extern bool selected_object_sticky ; + extern char *selected_type_string ; + extern puButton *active_button ; + + main_window_changed = true ; + + // puObject *new_obj = createWidget ( selected_object->getType () ) ; + puObject *new_obj = new puFrame ( 0, 0, 90, 20 ) ; + char *object_type_name = new char [ PUSTRING_MAX ] ; + strcpy ( object_type_name, selected_type_string ) ; + new_obj->setLegend ( object_type_name ) ; + + // Add the new object to the list of widgets + WidgetList *new_wid = new WidgetList ; + new_wid->obj = new_obj ; + new_wid->label_text = (char *)NULL ; + new_wid->legend_text = (char *)NULL ; + new_wid->allowed = (char *)NULL ; + new_wid->items = (char *)NULL ; + new_wid->object_type_name = object_type_name ; + new_wid->object_type = selected_object_type ; + new_wid->callbacks = 1 ; // Default: up callback enabled, others disabled + sprintf ( new_wid->object_name, "widget%d", widget_number++ ) ; + new_wid->visible = true ; + new_wid->locked = autolock ; /* Set it to the autolock var (true or false ) */ + new_wid->layer = max_layer - 1 ; + new_wid->next = widgets ; + widgets = new_wid ; + + // Set the new widget's position + new_obj->setPosition ( x, y ) ; + + mouse_x_position_in_object = 0 ; + mouse_y_position_in_object = 0 ; + + + /* Set up the widget's default data values */ + new_wid->intval1 = 0; + new_wid->intval2 = 0; + new_wid->boolval1 = false; + new_wid->boolval2 = false; + new_wid->boolval3 = false; + new_wid->floatval1 = 0.0f; + new_wid->floatval2 = 0.0f; + new_wid->floatval3 = 0.0f; + new_wid->floatval4 = 0.0f; + new_wid->floatval5 = 0.0f; + new_wid->floatval6 = 0.0f; + + if (new_wid->object_type == PUCLASS_TEXT) + { + new_obj->setSize(5,20); + } + if (new_wid->object_type == PUCLASS_COMBOBOX) + { + new_wid->intval1 = 1; + new_wid->boolval1 = true; + } + + if (new_wid->object_type == PUCLASS_SELECTBOX) + { + new_wid->intval1 = 1; + } + + if (new_wid->object_type == PUCLASS_BUTTONBOX) + { + new_wid->boolval1 = true; + } + + if (new_wid->object_type == PUCLASS_COMBOBOX) + { + new_wid->intval1 = 1; + new_wid->boolval1 = true; + } + + if ( (new_wid->object_type == PUCLASS_SLIDER ) || + (new_wid->object_type == PUCLASS_BISLIDER ) || + (new_wid->object_type == PUCLASS_TRISLIDER ) || + (new_wid->object_type == PUCLASS_DIAL ) || + (new_wid->object_type == PUCLASS_SPINBOX ) || + (new_wid->object_type == PUCLASS_SCROLLBAR ) ) + { + new_wid->floatval1 = 1.0f; + new_wid->floatval2 = 0.0f; + new_wid->floatval3 = 0.0f; + new_wid->boolval1 = true; + } + + if ( (new_wid->object_type == PUCLASS_SLIDER ) || + (new_wid->object_type == PUCLASS_BISLIDER ) || + (new_wid->object_type == PUCLASS_TRISLIDER ) ) + { + new_wid->boolval2 = true; + } + + if (new_wid->object_type == PUCLASS_SLIDER) + { + new_wid->floatval4 = 0.5f; + } + + if (new_wid->object_type == PUCLASS_BISLIDER) + { + new_wid->floatval4 = 1.0f; + new_wid->floatval5 = 0.0f; + } + + if (new_wid->object_type == PUCLASS_TRISLIDER) + { + new_wid->floatval4 = 1.0f; + new_wid->floatval5 = 0.0f; + new_wid->floatval6 = 0.5f; + new_wid->boolval3 = false; + } + + if (new_wid->object_type == PUCLASS_DIAL) + { + new_obj->setSize(50,50); + new_wid->boolval2 = true; + } + + if (new_wid->object_type == PUCLASS_SPINBOX) + { + new_wid->boolval2 = true; + new_wid->floatval4 = 0.5f; + } + + if (new_wid->object_type == PUCLASS_SCROLLBAR) + { + /* Not Yet Implemented */ + } + + if (new_wid->object_type == PUCLASS_SPINBOX) + { + new_wid->boolval2 = true; + new_wid->floatval4 = 0.5f; + } + + if (new_wid->object_type == PUCLASS_INPUT) + { + new_wid->boolval1 = true; + } + + if (new_wid->object_type == PUCLASS_LARGEINPUT) + { + new_wid->boolval1 = true; + new_wid->intval1 = 1; + new_wid->intval2 = 5; + } + + if (new_wid->object_type == PUCLASS_MENUBAR) + { + new_obj->setSize( 120, 30) ; + new_obj->setPosition( 0, puGetWindowHeight()-30) ; + new_wid->locked = true ; + } + + if (new_wid->object_type == PUCLASS_VERTMENU) + { + new_obj->setSize( 45, 120) ; + new_obj->setPosition( 0, puGetWindowHeight()-120) ; + new_obj->setLegend(""); + new_obj->setLabelPlace(PUPLACE_BOTTOM_LEFT); + new_obj->setLabel("puVerticalMenu"); + new_wid->locked = true ; + } + + // Make the new widget the active widget + active_object = new_obj ; + active_widget = new_wid ; + + // If the "sticky" flag is not set, reset the selected object + if ( !selected_object_sticky ) + { + selected_object_type = 0 ; + active_button->setValue ( 0 ) ; + } + } + else + { + // Clicking on a widget in the main widget list activates it + WidgetList *wid = widgets ; + while ( wid ) + { + puBox *box = wid->obj->getABox () ; + if ( wid->visible && ( x >= box->min[0] ) && ( x <= box->max[0] ) && + ( y >= box->min[1] ) && ( y <= box->max[1] ) ) + { + active_widget = wid ; + active_object = wid->obj ; + if ( abs ( x - box->min[0] ) < RESIZING_BORDER_WIDTH ) + activity_flag = 2 ; // Resizing on x-min + else if ( abs ( x - box->max[0] ) < RESIZING_BORDER_WIDTH ) + activity_flag = 4 ; // Resizing on x-max + else if ( abs ( y - box->min[1] ) < RESIZING_BORDER_WIDTH ) + activity_flag = 3 ; // Resizing on y-min + else if ( abs ( y - box->max[1] ) < RESIZING_BORDER_WIDTH ) + activity_flag = 5 ; // Resizing on y-max + else + activity_flag = 1 ; // Away from edges, we're moving it + + /* Now we check and see if we're clicking on a corner - the sensitivity for + the determiniation of whether we're clicking a corner or not is held by the + definition of "RESIZING_CORNER_BORDER_WIDTH" which is at the top of this file */ + + int corner_resize_width = RESIZING_CORNER_BORDER_WIDTH + (((box->max[0] - box->min[0]) + (box->max[1] - box->min[1]) / 2 ) / 50 ) * 2 ; + + if ( activity_flag != 1 ) + { + // Bottom Right Corner + if ( ( abs( y - box->min[1] ) < corner_resize_width ) && (abs ( x - box->max[0] ) < corner_resize_width ) ) + activity_flag = 9; + + // Bottom Left Corner + if ( ( abs( y - box->min[1] ) < corner_resize_width ) && (abs ( x - box->min[0] ) < corner_resize_width ) ) + activity_flag = 6; + + // Top Right Corner + if ( ( abs( y - box->max[1] ) < corner_resize_width ) && (abs ( x - box->max[0] ) < corner_resize_width ) ) + activity_flag = 7; + + // Top Left Corner + if ( ( abs( y - box->max[1] ) < corner_resize_width ) && (abs ( x - box->min[0] ) < corner_resize_width ) ) + activity_flag = 8; + } + + /* If CTRL is held down, symmetric resize is forced. */ + + resize_symmetric = ctrl_key_down ? 2 : 1 ; + + if (active_widget->object_type == PUCLASS_DIAL) + resize_corner = 1 ; + else + resize_corner = 0; + + int object_x, object_y ; + active_object->getPosition ( &object_x, &object_y ) ; + mouse_x_position_in_object = x - object_x ; + mouse_y_position_in_object = y - object_y ; + + break ; + } + + wid = wid->next ; + } + + if ( ( !wid ) && ( context_menu->isVisible()==0 ) ) // Ran through the entire list, deactivate any active widget + { + active_widget = (WidgetList *)NULL ; + active_object = (puObject *)NULL ; + } + } +} + + setStatusWidgets ( active_widget ) ; + } + } + glutPostRedisplay () ; +} + + +static void main_window_reshapefn ( int w, int h ) +{ + extern puInput *window_size_x ; + extern puInput *window_size_y ; + + if (done_first_setup) + main_window_changed = true ; + else + done_first_setup = true ; + + if ( ( !currently_loading ) && ( + ( mouse_x < main_window_width/2 ) || // Grabbed the left edge ... + ( mouse_y < main_window_height/2 ) ) ) // or the bottom edge, move the widgets + { + WidgetList *wid = widgets ; + int deltax = 0 ; + int deltay = 0 ; + + if ( mouse_x < main_window_width/2 ) deltax = w - main_window_width ; + if ( mouse_y < main_window_height/2 ) deltay = h - main_window_height ; + + while ( wid ) + { + int x, y ; + wid->obj->getPosition ( &x, &y ) ; + wid->obj->setPosition ( x + deltax, y + deltay ) ; + + wid = wid->next ; + } + } + + main_window_width = w ; + main_window_height = h ; + + window_size_x->setValue ( w ) ; + window_size_y->setValue ( h ) ; + + currently_loading = false ; +} + +static void main_window_displayfn ( void ) +{ + /* Clear the screen */ + glutSetWindow ( main_window ) ; + + glClearColor ( main_window_color_r, main_window_color_g, main_window_color_b, main_window_color_a ) ; + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + // Set the OpenGL to draw PUI widgets + + int w = puGetWindowWidth () ; + int h = puGetWindowHeight () ; + + glPushAttrib ( GL_ENABLE_BIT | GL_TRANSFORM_BIT | GL_LIGHTING_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 () ; + + // Draw the widgets + int layer ; + for ( layer = 0; layer < max_layer; layer++ ) + { + WidgetList *wid = widgets ; + while ( wid ) + { + if ( wid->visible && ( wid->layer == layer ) ) wid->obj->draw ( 0, 0 ) ; + wid = wid->next ; + } + } + + if ( active_object ) + { + puBox *box = active_object->getBBox () ; + glColor4f ( 0.0f, 0.0f, 0.0f, 1.0f ) ; + glLineWidth ( 3.0f ) ; + glBegin ( GL_LINES ) ; + glVertex2i ( box->min[0]-1, box->min[1]-1 ) ; + glVertex2i ( box->max[0]+1, box->min[1]-1 ) ; + glVertex2i ( box->max[0]+1, box->max[1]+1 ) ; + glVertex2i ( box->min[0]-1, box->max[1]+1 ) ; + glVertex2i ( box->min[0]-1, box->min[1]-1 ) ; + glEnd () ; + } + + context_menu->draw(0,0); + + /* Update GLUT */ + + glutSwapBuffers () ; + glutPostRedisplay () ; + +} + +int main ( int argc, char **argv ) +{ + extern int define_widget_window () ; + extern int define_status_window () ; + int i = 0; + + strcpy ( main_window_name, "PUI GUI Builder" ) ; + + glutInitWindowPosition( 100, 0 ) ; + glutInitWindowSize ( main_window_width, main_window_height ) ; + glutInit ( &argc, argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + main_window = glutCreateWindow ( main_window_name ) ; + glutDisplayFunc ( main_window_displayfn ) ; + glutKeyboardFunc ( main_window_keyfn ) ; + glutSpecialFunc ( main_window_specialfn ) ; + glutMouseFunc ( main_window_mousefn ) ; + glutMotionFunc ( main_window_motionfn ) ; + glutPassiveMotionFunc ( main_window_passivefn ) ; + glutReshapeFunc ( main_window_reshapefn ) ; + glutIdleFunc ( main_window_displayfn ) ; + +// If we're using windows, ignore the C: or whatnot + +#ifdef WIN32 + #define PATH_SEPARATOR '\\' + strcpy (pguide_current_directory, argv[0]+2); +#else + #define PATH_SEPARATOR '/' + strcpy (pguide_current_directory, argv[0]); +#endif + i = strlen(pguide_current_directory); + + + while (pguide_current_directory[i] != PATH_SEPARATOR) { + if (i>0) i-- ; + else break ; + } + pguide_current_directory[i+1] = '\0'; + + puInit () ; + +#ifdef VOODOO + puShowCursor () ; +#endif + + puSetDefaultStyle ( PUSTYLE_SMALL_SHADED ) ; + puSetDefaultColourScheme ( 0.8f, 0.8f, 0.8f, 1.0f ) ; + + // Add the properties context menu + context_menu = new puPopupMenu( 0, 0 ) ; + context_menu->add_item("Properties", cb_edit_properties) ; + context_menu->add_item("Lock/Unlock", cb_lock_toggle) ; + context_menu->add_item("Delete", cb_popup_delete) ; + context_menu->add_item("Cut", NULL) ; + context_menu->add_item("Copy", NULL) ; + context_menu->add_item("Change Class", NULL) ; + context_menu->close() ; + + // Set up the other windows + define_widget_window () ; + define_status_window () ; + + glutMainLoop () ; + return 0 ; +} + diff --git a/demos/p-guide/src/pGuide.dsp b/demos/p-guide/src/pGuide.dsp new file mode 100644 index 0000000..5d869a5 --- /dev/null +++ b/demos/p-guide/src/pGuide.dsp @@ -0,0 +1,128 @@ +# Microsoft Developer Studio Project File - Name="pGuide" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=pGuide - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "pGuide.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "pGuide.mak" CFG="pGuide - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "pGuide - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "pGuide - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +F90=df.exe +RSC=rc.exe + +!IF "$(CFG)" == "pGuide - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "FREEGLUT_STATIC" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 pui.lib puAux.lib sg.lib fnt.lib ul.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "pGuide - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "pGuide___Win32_Debug" +# PROP BASE Intermediate_Dir "pGuide___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "pGuide___Win32_Debug" +# PROP Intermediate_Dir "pGuide___Win32_Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "FREEGLUT_STATIC" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 pui_d.lib puAux_d.lib sg_d.lib fnt_d.lib ul_d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"LIBCMTD" /pdbtype:sept /libpath:"..\..\..\..\plib" +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "pGuide - Win32 Release" +# Name "pGuide - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\LoadSave.cxx +# End Source File +# Begin Source File + +SOURCE=.\pGuide.cxx +# End Source File +# Begin Source File + +SOURCE=.\PropertiesWindow.cxx +# End Source File +# Begin Source File + +SOURCE=.\StatusWindow.cxx +# End Source File +# Begin Source File + +SOURCE=.\WidgetWindow.cxx +# End Source File +# Begin Source File + +SOURCE=.\WriteCode.cxx +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\WidgetList.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/demos/simon/AUTHORS b/demos/simon/AUTHORS new file mode 100644 index 0000000..d7afed4 --- /dev/null +++ b/demos/simon/AUTHORS @@ -0,0 +1,3 @@ +SIMON was written by Steve Baker. +AstroPong was written by Oliver Baker. + diff --git a/demos/simon/COPYING b/demos/simon/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/demos/simon/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/demos/simon/Makefile b/demos/simon/Makefile new file mode 100644 index 0000000..5af4d27 --- /dev/null +++ b/demos/simon/Makefile @@ -0,0 +1,13 @@ + +all: + (cd src ; make) + +install: + (cd src ; make install) + +uninstall: + (cd src ; make uninstall) + +clean: + (cd src ; make clean) + diff --git a/demos/simon/README b/demos/simon/README new file mode 100644 index 0000000..8f34edc --- /dev/null +++ b/demos/simon/README @@ -0,0 +1,60 @@ + +WELCOME TO S.I.M.O.N +==================== + +Which stands for: + + Simple + Interface for + Making + Oliver's programs + Nice. + +This is a simple set of functions that hide much of the nastiness +of 3D programming to make it possible for someone with only the +very minimum of programming experience to write simple 3D applications. + + + +INSTALLATION +============ + +Right now, you build SIMON by running 'make' and install it by +running 'make install' as root. You must already have PLIB installed. + +Simon installs into /usr/local/simon/libsimon.a /usr/local/simon/simon.h +and places an executable into /usr/local/bin/simon + + + +RUNNING SIMON +============= + +There are two ways to write SIMON programs: + + 1) Write your code in C++ and link it to libsimon + (the LIBRARY version of SIMON). + + 2) Write your code in PSL (The PLIB Scripting Language) + and use the 'simon' program to run it. + +Documentation for both methods are in the 'doc' directory. + + + +DEMO'S +====== + +AstroPong is my son's first ever game (his first ever program actually). +It was originally written in C++ using libsimon - but has subsequently +been converted into PSL for use as a demonstration program. + +Once you've done a 'make install', you can change directory down into +the 'simon' directory and run: + + simon astropong.psl + +...move your paddle using the joystick - don't let the herring +escape from the ice cube! + + diff --git a/demos/simon/astropong/astropong.psl b/demos/simon/astropong/astropong.psl new file mode 100644 index 0000000..8844689 --- /dev/null +++ b/demos/simon/astropong/astropong.psl @@ -0,0 +1,249 @@ +/* + AstroPong - A 3D Pong Game + Copyright (C) 2002 Oliver Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: astropong.psl 1699 2002-09-22 15:22:21Z sjbaker $ +*/ + + +#define ARENA_SIZE 8.0 /* meters */ +#define ARENA_LENGTH 10.0 /* meters */ +#define BALL_SIZE 2.5 /* meters */ + +#define BOUNCE (ARENA_SIZE/2.0 - BALL_SIZE/2.0) +#define BOUNCEY (ARENA_LENGTH/2.0 - BALL_SIZE/2.0) + +#define BAT_SIZE (1.0 + BALL_SIZE/2.0) /* From the center to the sides */ + +int arena ; +int shadow ; +int difficulty ; +int scoreBoardR ; +int scoreBoardB ; +int ball ; +int bPaddle ; +int rPaddle ; +int camera ; +int scoreR ; +int scoreB ; + +float Blue_batspeed = .34; +float scoreSpinR ; +float scoreSpinB ; +float ballSpinH ; +float ballSpinSH ; +float ballSpinP ; +float ballSpinSP ; +float ballSpinR ; +float ballSpinSR ; +float ballX ; +float ballY ; +float ballZ ; +float ballSX ; +float ballSY ; +float ballSZ ; +float bpaddleX ; +float bpaddleZ ; +float rpaddleX ; +float rpaddleZ ; +float userX ; +float userZ ; +int frameno = 0 ; + +int main() +{ + camera = 0 ; + arena = siLoad ( "arena2.ac") ; + ball = siLoad ( "ball3.ac") ; + bPaddle = siLoad ( "bluepaddle2.ac"); + rPaddle = siLoad ( "redpaddle2.ac") ; + scoreBoardR = siLoad ( "Scoreboard.ac") ; + scoreBoardB = siLoad ( "Scoreboard.ac") ; + shadow = siLoad ( "shadow2.ac") ; + + scoreSpinR = 0 ; + scoreSpinB = 0 ; + ballSX = 0.166 ; + ballSY = 0.155 ; + ballSZ = 0.016 ; + ballSpinSH = 4 ; + ballSpinSP = 4 ; + ballSpinSR = 4 ; + + difficulty = 1 ; + + if ( difficulty == 1 ) { Blue_batspeed = .275 ; } + else { Blue_batspeed = .34 ; } + + while ( 1 ) + { + frameno = frameno + 1 ; + + /* Read the joystick */ + + userX = siJoystickLR(); + userZ = siJoystickUD(); + + /* Move the ball */ + + ballX += ballSX ; + ballY += ballSY ; + ballZ += ballSZ ; + ballSpinH += ballSpinSH ; + ballSpinP += ballSpinSP ; + ballSpinR += ballSpinSR ; + + /* Bounce off the sides? */ + + if ( ballX > BOUNCE || ballX < -BOUNCE ) + { + ballSX = -ballSX ; + } + + /* Bounce off the top and bottom? */ + + if ( ballZ > BOUNCE || ballZ < -BOUNCE ) + { + ballSZ = -ballSZ ; + } + + + + /* What happens at the ends? */ + + if ( ballY > BOUNCEY ) /* Passed the blue paddle? */ + { + /* Is the blue bat there? */ + + if (ballX > bpaddleX - BAT_SIZE && ballX < bpaddleX + BAT_SIZE && + ballZ > bpaddleZ - BAT_SIZE && ballZ < bpaddleZ + BAT_SIZE ) + { + float hitX = ballX - bpaddleX ; + float hitZ = ballZ - bpaddleZ ; + + if ( ballSX > 0 ) + ballSX = fabs ( hitX / 2.0 ) ; + else + ballSX = -fabs ( hitX / 2.0 ) ; + + if ( ballSZ > 0 ) + ballSZ = fabs ( hitZ / 2.0 ) ; + else + ballSZ = -fabs ( hitZ / 2.0 ) ; + + ballSY = -ballSY ; + } + else + { + scoreR++ ; + + print ("The score is Red:", scoreR, " Blue:", scoreB, "\n" ) ; + + ballSX = 0.1 ; + ballSY = 0.1 ; + ballSZ = 0.1; + ballSY = -ballSY ; + ballX = 0.0 ; + ballY = 0.0 ; + ballZ = 0.0; + for ( int i = 0 ; i < 60 ; i++ ) pause ; + } + } + + + if ( ballY < -BOUNCEY ) /* Passed the red paddle? */ + { + /* Was the red bat there? */ + + if (ballX > rpaddleX - BAT_SIZE && ballX < rpaddleX + BAT_SIZE && + ballZ > rpaddleZ - BAT_SIZE && ballZ < rpaddleZ + BAT_SIZE ) + { + float hitX = ballX - rpaddleX ; + float hitZ = ballZ - rpaddleZ ; + + if ( ballSX > 0 ) + ballSX = fabs ( hitX / 2.0 ) ; + else + ballSX = -fabs ( hitX / 2.0 ) ; + + if ( ballSZ > 0 ) + ballSZ = fabs ( hitZ / 2.0 ) ; + else + ballSZ = -fabs ( hitZ / 2.0 ) ; + + ballSY = -ballSY ; + } + else + { + scoreB++ ; + print ("The score is Red:", scoreR, " Blue:", scoreB, "\n" ) ; + ballSX = .1 ; + ballSY = .1 ; + ballSZ = .1; + ballSY = -ballSY ; + ballX = 0.0 ; + ballY = 0.0 ; + ballZ = 0.0; + for ( int i = 0 ; i < 60 ; i++ ) pause ; + } + } + + /* Update the scoreboard */ + + scoreSpinR = scoreR * -36.0 ; + scoreSpinB = scoreB * -36.0 ; + + /* How should the computer move the paddle? */ + + if ( ballZ > bpaddleZ ) { bpaddleZ += Blue_batspeed ; } + else { bpaddleZ -= Blue_batspeed ; } + + if ( ballX > bpaddleX ) { bpaddleX += Blue_batspeed ; } + else { bpaddleX -= Blue_batspeed ; } + + /* How did the player move the paddle? */ + + rpaddleX += userX * -.5; + rpaddleZ += userZ * .5; + + /* Did the paddle move off the edge of the screen? */ + + if ( rpaddleX > BOUNCE ) rpaddleX = BOUNCE ; + if ( rpaddleX < -BOUNCE ) rpaddleX = -BOUNCE ; + if ( rpaddleZ > BOUNCE ) rpaddleZ = BOUNCE ; + if ( rpaddleZ < -BOUNCE ) rpaddleZ = -BOUNCE ; + + /* Tell SIMON where to position the paddle, ball and camera */ + + /* MODEL X, Y, Z, H, P, R */ + siPosition ( scoreBoardR, 1, 0, 0, 0, scoreSpinR, 0 ) ; + siPosition ( scoreBoardB, -1, 0, 0, 0, scoreSpinB, 0 ) ; + siPosition ( bPaddle , bpaddleX, 5, bpaddleZ, 0, 0 , 0 ) ; + siPosition ( rPaddle , rpaddleX, -5, rpaddleZ, 0, 0 , 0 ) ; + siPosition ( ball , ballX, ballY, ballZ, + ballSpinH,ballSpinP,ballSpinR); + siPosition ( arena , 0, 0, 0, 0, 0 , 0 ) ; + siPosition ( shadow , ballX, ballY, -4, 0, 0 , 0 ) ; + siPosition ( camera , 0, -10, 0, 0, 0 , 0 ) ; + + pause ; + } +} + + diff --git a/demos/simon/astropong/data/Penguin_beak.rgb b/demos/simon/astropong/data/Penguin_beak.rgb new file mode 100644 index 0000000..b1e0e79 Binary files /dev/null and b/demos/simon/astropong/data/Penguin_beak.rgb differ diff --git a/demos/simon/astropong/data/Penguin_body.rgb b/demos/simon/astropong/data/Penguin_body.rgb new file mode 100644 index 0000000..1ba0f4b Binary files /dev/null and b/demos/simon/astropong/data/Penguin_body.rgb differ diff --git a/demos/simon/astropong/data/Penguin_body2.rgb b/demos/simon/astropong/data/Penguin_body2.rgb new file mode 100644 index 0000000..208e6ef Binary files /dev/null and b/demos/simon/astropong/data/Penguin_body2.rgb differ diff --git a/demos/simon/astropong/data/Penguin_foot.rgba b/demos/simon/astropong/data/Penguin_foot.rgba new file mode 100644 index 0000000..e7caaa7 Binary files /dev/null and b/demos/simon/astropong/data/Penguin_foot.rgba differ diff --git a/demos/simon/astropong/data/Scoreboard.ac b/demos/simon/astropong/data/Scoreboard.ac new file mode 100644 index 0000000..cb68697 --- /dev/null +++ b/demos/simon/astropong/data/Scoreboard.ac @@ -0,0 +1,2294 @@ +AC3Db +MATERIAL "ac3dmat0" rgb 0 0 0 amb 0 0 0 emis 0 0 0 spec 0 0 0 shi 128 trans 0 +MATERIAL "ac3dmat1" rgb 1 1 1 amb 0.2 0.2 0.2 emis 1 1 1 spec 0.502 0.502 0.502 shi 10 trans 0 +OBJECT world +kids 3 +OBJECT poly +name "cylinder" +loc -2.5332e-07 0.000827358 0.00013657 +texture "Scoreboard.rgb" +numvert 162 +0.5 -1.41445 0.499339 +0.5 -1.3715 0.607445 +0.5 -1.3203 0.7119 +0.5 -1.26117 0.812075 +0.5 -1.19445 0.90736 +0.5 -1.12054 0.997195 +0.5 -1.0399 1.08103 +0.5 -0.952995 1.15836 +0.5 -0.860365 1.22873 +0.5 -0.76256 1.29171 +0.5 -0.66017 1.34692 +0.5 -0.55381 1.39402 +0.5 -0.444117 1.43274 +0.5 -0.331755 1.46285 +0.5 -0.217397 1.48416 +0.5 -0.101732 1.49654 +0.5 0.0145443 1.49993 +0.5 0.130734 1.49429 +0.5 0.246137 1.47967 +0.5 0.36006 1.45615 +0.5 0.471817 1.42386 +0.5 0.580735 1.38302 +0.5 0.686165 1.33386 +0.5 0.787465 1.27667 +0.5 0.88403 1.21181 +0.5 0.97528 1.13967 +0.5 1.06066 1.06066 +0.5 1.13967 0.975275 +0.5 1.21181 0.88403 +0.5 1.27667 0.787465 +0.5 1.33386 0.686165 +0.5 1.38302 0.580735 +0.5 1.42386 0.471817 +0.5 1.45615 0.360059 +0.5 1.47967 0.246137 +0.5 1.49429 0.130734 +0.5 1.49993 0.0145439 +0.5 1.49654 -0.101733 +0.5 1.48416 -0.217398 +0.5 1.46285 -0.331755 +0.5 1.43274 -0.444118 +0.5 1.39402 -0.55381 +0.5 1.34692 -0.66017 +0.5 1.29171 -0.76256 +0.5 1.22873 -0.860365 +0.5 1.15836 -0.952995 +0.5 1.08103 -1.0399 +0.5 0.997195 -1.12054 +0.5 0.90736 -1.19445 +0.5 0.812075 -1.26117 +0.5 0.7119 -1.3203 +0.5 0.607445 -1.3715 +0.5 0.499339 -1.41445 +0.5 0.388229 -1.44889 +0.5 0.274784 -1.47461 +0.5 0.159687 -1.49147 +0.5 0.0436284 -1.49936 +0.5 -0.072692 -1.49824 +0.5 -0.188575 -1.4881 +0.5 -0.303324 -1.46901 +0.5 -0.416249 -1.44109 +0.5 -0.52667 -1.4045 +0.5 -0.633925 -1.35947 +0.5 -0.737365 -1.30625 +0.5 -0.836375 -1.24519 +0.5 -0.93035 -1.17663 +0.5 -1.01873 -1.10099 +0.5 -1.10099 -1.01874 +0.5 -1.17662 -0.930355 +0.5 -1.24518 -0.83638 +0.5 -1.30624 -0.737375 +0.5 -1.35946 -0.633935 +0.5 -1.4045 -0.52668 +0.5 -1.44108 -0.416258 +0.5 -1.46901 -0.303333 +0.5 -1.4881 -0.188585 +0.5 -1.49823 -0.0727015 +0.5 -1.49936 0.0436186 +0.5 -1.49147 0.159677 +0.5 -1.47462 0.274774 +0.5 -1.44889 0.38822 +-0.5 -1.41445 0.499339 +-0.5 -1.3715 0.607445 +-0.5 -1.3203 0.7119 +-0.5 -1.26117 0.812075 +-0.5 -1.19445 0.90736 +-0.5 -1.12054 0.997195 +-0.5 -1.0399 1.08103 +-0.5 -0.952995 1.15836 +-0.5 -0.860365 1.22873 +-0.5 -0.76256 1.29171 +-0.5 -0.66017 1.34692 +-0.5 -0.55381 1.39402 +-0.5 -0.444117 1.43274 +-0.5 -0.331755 1.46285 +-0.5 -0.217397 1.48416 +-0.5 -0.101732 1.49654 +-0.5 0.0145443 1.49993 +-0.5 0.130734 1.49429 +-0.5 0.246137 1.47967 +-0.5 0.36006 1.45615 +-0.5 0.471817 1.42386 +-0.5 0.580735 1.38302 +-0.5 0.686165 1.33386 +-0.5 0.787465 1.27667 +-0.5 0.88403 1.21181 +-0.5 0.97528 1.13967 +-0.5 1.06066 1.06066 +-0.5 1.13967 0.975275 +-0.5 1.21181 0.88403 +-0.5 1.27667 0.787465 +-0.5 1.33386 0.686165 +-0.5 1.38302 0.580735 +-0.5 1.42386 0.471817 +-0.5 1.45615 0.360059 +-0.5 1.47967 0.246137 +-0.5 1.49429 0.130734 +-0.5 1.49993 0.0145439 +-0.5 1.49654 -0.101733 +-0.5 1.48416 -0.217398 +-0.5 1.46285 -0.331755 +-0.5 1.43274 -0.444118 +-0.5 1.39402 -0.55381 +-0.5 1.34692 -0.66017 +-0.5 1.29171 -0.76256 +-0.5 1.22873 -0.860365 +-0.5 1.15836 -0.952995 +-0.5 1.08103 -1.0399 +-0.5 0.997195 -1.12054 +-0.5 0.90736 -1.19445 +-0.5 0.812075 -1.26117 +-0.5 0.7119 -1.3203 +-0.5 0.607445 -1.3715 +-0.5 0.499339 -1.41445 +-0.5 0.388229 -1.44889 +-0.5 0.274784 -1.47461 +-0.5 0.159687 -1.49147 +-0.5 0.0436284 -1.49936 +-0.5 -0.072692 -1.49824 +-0.5 -0.188575 -1.4881 +-0.5 -0.303324 -1.46901 +-0.5 -0.416249 -1.44109 +-0.5 -0.52667 -1.4045 +-0.5 -0.633925 -1.35947 +-0.5 -0.737365 -1.30625 +-0.5 -0.836375 -1.24519 +-0.5 -0.93035 -1.17663 +-0.5 -1.01873 -1.10099 +-0.5 -1.10099 -1.01874 +-0.5 -1.17662 -0.930355 +-0.5 -1.24518 -0.83638 +-0.5 -1.30624 -0.737375 +-0.5 -1.35946 -0.633935 +-0.5 -1.4045 -0.52668 +-0.5 -1.44108 -0.416258 +-0.5 -1.46901 -0.303333 +-0.5 -1.4881 -0.188585 +-0.5 -1.49823 -0.0727015 +-0.5 -1.49936 0.0436186 +-0.5 -1.49147 0.159677 +-0.5 -1.47462 0.274774 +-0.5 -1.44889 0.38822 +numsurf 162 +SURF 0x30 +mat 1 +refs 3 +0 1 0.538754 +82 0 0.577274 +81 0 0.538754 +SURF 0x30 +mat 1 +refs 3 +0 1 0.538754 +1 1 0.577274 +82 0 0.577274 +SURF 0x30 +mat 1 +refs 3 +1 1 0.577274 +83 0 0.61533 +82 0 0.577274 +SURF 0x30 +mat 1 +refs 3 +1 1 0.577274 +2 1 0.61533 +83 0 0.61533 +SURF 0x30 +mat 1 +refs 3 +2 1 0.61533 +84 0 0.652692 +83 0 0.61533 +SURF 0x30 +mat 1 +refs 3 +2 1 0.61533 +3 1 0.652692 +84 0 0.652692 +SURF 0x30 +mat 1 +refs 3 +3 1 0.652692 +85 0 0.689135 +84 0 0.652692 +SURF 0x30 +mat 1 +refs 3 +3 1 0.652692 +4 1 0.689135 +85 0 0.689135 +SURF 0x30 +mat 1 +refs 3 +4 1 0.689135 +86 0 0.724442 +85 0 0.689135 +SURF 0x30 +mat 1 +refs 3 +4 1 0.689135 +5 1 0.724442 +86 0 0.724442 +SURF 0x30 +mat 1 +refs 3 +5 1 0.724442 +87 0 0.758398 +86 0 0.724442 +SURF 0x30 +mat 1 +refs 3 +5 1 0.724442 +6 1 0.758398 +87 0 0.758398 +SURF 0x30 +mat 1 +refs 3 +6 1 0.758398 +88 0 0.790801 +87 0 0.758398 +SURF 0x30 +mat 1 +refs 3 +6 1 0.758398 +7 1 0.790801 +88 0 0.790801 +SURF 0x30 +mat 1 +refs 3 +7 1 0.790801 +89 0 0.821454 +88 0 0.790801 +SURF 0x30 +mat 1 +refs 3 +7 1 0.790801 +8 1 0.821454 +89 0 0.821454 +SURF 0x30 +mat 1 +refs 3 +8 1 0.821454 +90 0 0.850175 +89 0 0.821454 +SURF 0x30 +mat 1 +refs 3 +8 1 0.821454 +9 1 0.850175 +90 0 0.850175 +SURF 0x30 +mat 1 +refs 3 +9 1 0.850175 +91 0 0.876789 +90 0 0.850175 +SURF 0x30 +mat 1 +refs 3 +9 1 0.850175 +10 1 0.876789 +91 0 0.876789 +SURF 0x30 +mat 1 +refs 3 +10 1 0.876789 +92 0 0.901137 +91 0 0.876789 +SURF 0x30 +mat 1 +refs 3 +10 1 0.876789 +11 1 0.901137 +92 0 0.901137 +SURF 0x30 +mat 1 +refs 3 +11 1 0.901137 +93 0 0.923073 +92 0 0.901137 +SURF 0x30 +mat 1 +refs 3 +11 1 0.901137 +12 1 0.923073 +93 0 0.923073 +SURF 0x30 +mat 1 +refs 3 +12 1 0.923073 +94 0 0.942464 +93 0 0.923073 +SURF 0x30 +mat 1 +refs 3 +12 1 0.923073 +13 1 0.942464 +94 0 0.942464 +SURF 0x30 +mat 1 +refs 3 +13 1 0.942464 +95 0 0.959194 +94 0 0.942464 +SURF 0x30 +mat 1 +refs 3 +13 1 0.942464 +14 1 0.959194 +95 0 0.959194 +SURF 0x30 +mat 1 +refs 3 +14 1 0.959194 +96 0 0.973163 +95 0 0.959194 +SURF 0x30 +mat 1 +refs 3 +14 1 0.959194 +15 1 0.973163 +96 0 0.973163 +SURF 0x30 +mat 1 +refs 3 +15 1 0.973163 +97 0 0.984286 +96 0 0.973163 +SURF 0x30 +mat 1 +refs 3 +15 1 0.973163 +16 1 0.984286 +97 0 0.984286 +SURF 0x30 +mat 1 +refs 3 +16 1 0.984286 +98 0 0.992496 +97 0 0.984286 +SURF 0x30 +mat 1 +refs 3 +16 1 0.984286 +17 1 0.992496 +98 0 0.992496 +SURF 0x30 +mat 1 +refs 3 +17 1 0.992496 +99 0 0.997745 +98 0 0.992496 +SURF 0x30 +mat 1 +refs 3 +17 1 0.992496 +18 1 0.997745 +99 0 0.997745 +SURF 0x30 +mat 1 +refs 3 +18 1 0.997745 +100 0 1 +99 0 0.997745 +SURF 0x30 +mat 1 +refs 3 +18 1 0.997745 +19 1 1 +100 0 1 +SURF 0x30 +mat 1 +refs 3 +19 1 1 +101 0 0.999248 +100 0 1 +SURF 0x30 +mat 1 +refs 3 +19 1 1 +20 1 0.999248 +101 0 0.999248 +SURF 0x30 +mat 0 +refs 3 +20 1 0.999248 +102 0 0.995493 +101 0 0.999248 +SURF 0x30 +mat 0 +refs 3 +20 1 0.999248 +21 1 0.995493 +102 0 0.995493 +SURF 0x30 +mat 0 +refs 3 +21 1 0.995493 +103 0 0.988759 +102 0 0.995493 +SURF 0x30 +mat 0 +refs 3 +21 1 0.995493 +22 1 0.988759 +103 0 0.988759 +SURF 0x30 +mat 0 +refs 3 +22 1 0.988759 +104 0 0.979085 +103 0 0.988759 +SURF 0x30 +mat 0 +refs 3 +22 1 0.988759 +23 1 0.979085 +104 0 0.979085 +SURF 0x30 +mat 0 +refs 3 +23 1 0.979085 +105 0 0.96653 +104 0 0.979085 +SURF 0x30 +mat 0 +refs 3 +23 1 0.979085 +24 1 0.96653 +105 0 0.96653 +SURF 0x30 +mat 0 +refs 3 +24 1 0.96653 +106 0 0.951169 +105 0 0.96653 +SURF 0x30 +mat 0 +refs 3 +24 1 0.96653 +25 1 0.951169 +106 0 0.951169 +SURF 0x30 +mat 0 +refs 3 +25 1 0.951169 +107 0 0.933094 +106 0 0.951169 +SURF 0x30 +mat 0 +refs 3 +25 1 0.951169 +26 1 0.933094 +107 0 0.933094 +SURF 0x30 +mat 0 +refs 3 +26 1 0.933094 +108 0 0.912415 +107 0 0.933094 +SURF 0x30 +mat 0 +refs 3 +26 1 0.933094 +27 1 0.912415 +108 0 0.912415 +SURF 0x30 +mat 0 +refs 3 +27 1 0.912415 +109 0 0.889256 +108 0 0.912415 +SURF 0x30 +mat 0 +refs 3 +27 1 0.912415 +28 1 0.889256 +109 0 0.889256 +SURF 0x30 +mat 0 +refs 3 +28 1 0.889256 +110 0 0.863755 +109 0 0.889256 +SURF 0x30 +mat 0 +refs 3 +28 1 0.889256 +29 1 0.863755 +110 0 0.863755 +SURF 0x30 +mat 0 +refs 3 +29 1 0.863755 +111 0 0.836067 +110 0 0.863755 +SURF 0x30 +mat 0 +refs 3 +29 1 0.863755 +30 1 0.836067 +111 0 0.836067 +SURF 0x30 +mat 0 +refs 3 +30 1 0.836067 +112 0 0.806358 +111 0 0.836067 +SURF 0x30 +mat 0 +refs 3 +30 1 0.836067 +31 1 0.806358 +112 0 0.806358 +SURF 0x30 +mat 0 +refs 3 +31 1 0.806358 +113 0 0.774806 +112 0 0.806358 +SURF 0x30 +mat 0 +refs 3 +31 1 0.806358 +32 1 0.774806 +113 0 0.774806 +SURF 0x30 +mat 0 +refs 3 +32 1 0.774806 +114 0 0.741602 +113 0 0.774806 +SURF 0x30 +mat 0 +refs 3 +32 1 0.774806 +33 1 0.741602 +114 0 0.741602 +SURF 0x30 +mat 0 +refs 3 +33 1 0.741602 +115 0 0.706944 +114 0 0.741602 +SURF 0x30 +mat 0 +refs 3 +33 1 0.741602 +34 1 0.706944 +115 0 0.706944 +SURF 0x30 +mat 0 +refs 3 +34 1 0.706944 +116 0 0.671042 +115 0 0.706944 +SURF 0x30 +mat 0 +refs 3 +34 1 0.706944 +35 1 0.671042 +116 0 0.671042 +SURF 0x30 +mat 0 +refs 3 +35 1 0.671042 +117 0 0.634111 +116 0 0.671042 +SURF 0x30 +mat 0 +refs 3 +35 1 0.671042 +36 1 0.634111 +117 0 0.634111 +SURF 0x30 +mat 0 +refs 3 +36 1 0.634111 +118 0 0.596374 +117 0 0.634111 +SURF 0x30 +mat 0 +refs 3 +36 1 0.634111 +37 1 0.596374 +118 0 0.596374 +SURF 0x30 +mat 0 +refs 3 +37 1 0.596374 +119 0 0.558057 +118 0 0.596374 +SURF 0x30 +mat 0 +refs 3 +37 1 0.596374 +38 1 0.558057 +119 0 0.558057 +SURF 0x30 +mat 0 +refs 3 +38 1 0.558057 +120 0 0.519391 +119 0 0.558057 +SURF 0x30 +mat 0 +refs 3 +38 1 0.558057 +39 1 0.519391 +120 0 0.519391 +SURF 0x30 +mat 0 +refs 3 +39 1 0.519391 +121 0 0.480609 +120 0 0.519391 +SURF 0x30 +mat 0 +refs 3 +39 1 0.519391 +40 1 0.480609 +121 0 0.480609 +SURF 0x30 +mat 0 +refs 3 +40 1 0.480609 +122 0 0.441943 +121 0 0.480609 +SURF 0x30 +mat 0 +refs 3 +40 1 0.480609 +41 1 0.441943 +122 0 0.441943 +SURF 0x30 +mat 0 +refs 3 +41 1 0.441943 +123 0 0.403626 +122 0 0.441943 +SURF 0x30 +mat 0 +refs 3 +41 1 0.441943 +42 1 0.403626 +123 0 0.403626 +SURF 0x30 +mat 0 +refs 3 +42 1 0.403626 +124 0 0.365888 +123 0 0.403626 +SURF 0x30 +mat 0 +refs 3 +42 1 0.403626 +43 1 0.365888 +124 0 0.365888 +SURF 0x30 +mat 0 +refs 3 +43 1 0.365888 +125 0 0.328958 +124 0 0.365888 +SURF 0x30 +mat 0 +refs 3 +43 1 0.365888 +44 1 0.328958 +125 0 0.328958 +SURF 0x30 +mat 0 +refs 3 +44 1 0.328958 +126 0 0.293056 +125 0 0.328958 +SURF 0x30 +mat 0 +refs 3 +44 1 0.328958 +45 1 0.293056 +126 0 0.293056 +SURF 0x30 +mat 0 +refs 3 +45 1 0.293056 +127 0 0.258398 +126 0 0.293056 +SURF 0x30 +mat 0 +refs 3 +45 1 0.293056 +46 1 0.258398 +127 0 0.258398 +SURF 0x30 +mat 0 +refs 3 +46 1 0.258398 +128 0 0.225194 +127 0 0.258398 +SURF 0x30 +mat 0 +refs 3 +46 1 0.258398 +47 1 0.225194 +128 0 0.225194 +SURF 0x30 +mat 0 +refs 3 +47 1 0.225194 +129 0 0.193642 +128 0 0.225194 +SURF 0x30 +mat 0 +refs 3 +47 1 0.225194 +48 1 0.193642 +129 0 0.193642 +SURF 0x30 +mat 0 +refs 3 +48 1 0.193642 +130 0 0.163933 +129 0 0.193642 +SURF 0x30 +mat 0 +refs 3 +48 1 0.193642 +49 1 0.163933 +130 0 0.163933 +SURF 0x30 +mat 0 +refs 3 +49 1 0.163933 +131 0 0.136245 +130 0 0.163933 +SURF 0x30 +mat 0 +refs 3 +49 1 0.163933 +50 1 0.136245 +131 0 0.136245 +SURF 0x30 +mat 0 +refs 3 +50 1 0.136245 +132 0 0.110744 +131 0 0.136245 +SURF 0x30 +mat 0 +refs 3 +50 1 0.136245 +51 1 0.110744 +132 0 0.110744 +SURF 0x30 +mat 0 +refs 3 +51 1 0.110744 +133 0 0.0875849 +132 0 0.110744 +SURF 0x30 +mat 0 +refs 3 +51 1 0.110744 +52 1 0.0875849 +133 0 0.0875849 +SURF 0x30 +mat 0 +refs 3 +52 1 0.0875849 +134 0 0.0669059 +133 0 0.0875849 +SURF 0x30 +mat 0 +refs 3 +52 1 0.0875849 +53 1 0.0669059 +134 0 0.0669059 +SURF 0x30 +mat 0 +refs 3 +53 1 0.0669059 +135 0 0.0488315 +134 0 0.0669059 +SURF 0x30 +mat 0 +refs 3 +53 1 0.0669059 +54 1 0.0488315 +135 0 0.0488315 +SURF 0x30 +mat 0 +refs 3 +54 1 0.0488315 +136 0 0.0334705 +135 0 0.0488315 +SURF 0x30 +mat 0 +refs 3 +54 1 0.0488315 +55 1 0.0334705 +136 0 0.0334705 +SURF 0x30 +mat 0 +refs 3 +55 1 0.0334705 +137 0 0.0209153 +136 0 0.0334705 +SURF 0x30 +mat 0 +refs 3 +55 1 0.0334705 +56 1 0.0209153 +137 0 0.0209153 +SURF 0x30 +mat 0 +refs 3 +56 1 0.0209153 +138 0 0.0112412 +137 0 0.0209153 +SURF 0x30 +mat 0 +refs 3 +56 1 0.0209153 +57 1 0.0112412 +138 0 0.0112412 +SURF 0x30 +mat 0 +refs 3 +57 1 0.0112412 +139 0 0.00450672 +138 0 0.0112412 +SURF 0x30 +mat 0 +refs 3 +57 1 0.0112412 +58 1 0.00450672 +139 0 0.00450672 +SURF 0x30 +mat 0 +refs 3 +58 1 0.00450672 +140 0 0.000752114 +139 0 0.00450672 +SURF 0x30 +mat 0 +refs 3 +58 1 0.00450672 +59 1 0.000752114 +140 0 0.000752114 +SURF 0x30 +mat 1 +refs 3 +59 1 0.000752114 +141 0 0 +140 0 0.000752114 +SURF 0x30 +mat 1 +refs 3 +59 1 0.000752114 +60 1 0 +141 0 0 +SURF 0x30 +mat 1 +refs 3 +60 1 0 +142 0 0.00225491 +141 0 0 +SURF 0x30 +mat 1 +refs 3 +60 1 0 +61 1 0.00225491 +142 0 0.00225491 +SURF 0x30 +mat 1 +refs 3 +61 1 0.00225491 +143 0 0.00750333 +142 0 0.00225491 +SURF 0x30 +mat 1 +refs 3 +61 1 0.00225491 +62 1 0.00750333 +143 0 0.00750333 +SURF 0x30 +mat 1 +refs 3 +62 1 0.00750333 +144 0 0.0157136 +143 0 0.00750333 +SURF 0x30 +mat 1 +refs 3 +62 1 0.00750333 +63 1 0.0157136 +144 0 0.0157136 +SURF 0x30 +mat 1 +refs 3 +63 1 0.0157136 +145 0 0.0268365 +144 0 0.0157136 +SURF 0x30 +mat 1 +refs 3 +63 1 0.0157136 +64 1 0.0268365 +145 0 0.0268365 +SURF 0x30 +mat 1 +refs 3 +64 1 0.0268365 +146 0 0.040805 +145 0 0.0268365 +SURF 0x30 +mat 1 +refs 3 +64 1 0.0268365 +65 1 0.040805 +146 0 0.040805 +SURF 0x30 +mat 1 +refs 3 +65 1 0.040805 +147 0 0.0575352 +146 0 0.040805 +SURF 0x30 +mat 1 +refs 3 +65 1 0.040805 +66 1 0.0575352 +147 0 0.0575352 +SURF 0x30 +mat 1 +refs 3 +66 1 0.0575352 +148 0 0.0769264 +147 0 0.0575352 +SURF 0x30 +mat 1 +refs 3 +66 1 0.0575352 +67 1 0.0769264 +148 0 0.0769264 +SURF 0x30 +mat 1 +refs 3 +67 1 0.0769264 +149 0 0.0988619 +148 0 0.0769264 +SURF 0x30 +mat 1 +refs 3 +67 1 0.0769264 +68 1 0.0988619 +149 0 0.0988619 +SURF 0x30 +mat 1 +refs 3 +68 1 0.0988619 +150 0 0.12321 +149 0 0.0988619 +SURF 0x30 +mat 1 +refs 3 +68 1 0.0988619 +69 1 0.12321 +150 0 0.12321 +SURF 0x30 +mat 1 +refs 3 +69 1 0.12321 +151 0 0.149824 +150 0 0.12321 +SURF 0x30 +mat 1 +refs 3 +69 1 0.12321 +70 1 0.149824 +151 0 0.149824 +SURF 0x30 +mat 1 +refs 3 +70 1 0.149824 +152 0 0.178544 +151 0 0.149824 +SURF 0x30 +mat 1 +refs 3 +70 1 0.149824 +71 1 0.178544 +152 0 0.178544 +SURF 0x30 +mat 1 +refs 3 +71 1 0.178544 +153 0 0.209197 +152 0 0.178544 +SURF 0x30 +mat 1 +refs 3 +71 1 0.178544 +72 1 0.209197 +153 0 0.209197 +SURF 0x30 +mat 1 +refs 3 +72 1 0.209197 +154 0 0.2416 +153 0 0.209197 +SURF 0x30 +mat 1 +refs 3 +72 1 0.209197 +73 1 0.2416 +154 0 0.2416 +SURF 0x30 +mat 1 +refs 3 +73 1 0.2416 +155 0 0.275556 +154 0 0.2416 +SURF 0x30 +mat 1 +refs 3 +73 1 0.2416 +74 1 0.275556 +155 0 0.275556 +SURF 0x30 +mat 1 +refs 3 +74 1 0.275556 +156 0 0.310862 +155 0 0.275556 +SURF 0x30 +mat 1 +refs 3 +74 1 0.275556 +75 1 0.310862 +156 0 0.310862 +SURF 0x30 +mat 1 +refs 3 +75 1 0.310862 +157 0 0.347306 +156 0 0.310862 +SURF 0x30 +mat 1 +refs 3 +75 1 0.310862 +76 1 0.347306 +157 0 0.347306 +SURF 0x30 +mat 1 +refs 3 +76 1 0.347306 +158 0 0.384668 +157 0 0.347306 +SURF 0x30 +mat 1 +refs 3 +76 1 0.347306 +77 1 0.384668 +158 0 0.384668 +SURF 0x30 +mat 1 +refs 3 +77 1 0.384668 +159 0 0.422723 +158 0 0.384668 +SURF 0x30 +mat 1 +refs 3 +77 1 0.384668 +78 1 0.422723 +159 0 0.422723 +SURF 0x30 +mat 1 +refs 3 +78 1 0.422723 +160 0 0.461243 +159 0 0.422723 +SURF 0x30 +mat 1 +refs 3 +78 1 0.422723 +79 1 0.461243 +160 0 0.461243 +SURF 0x30 +mat 1 +refs 3 +79 1 0.461243 +161 0 0.499997 +160 0 0.461243 +SURF 0x30 +mat 1 +refs 3 +79 1 0.461243 +80 1 0.499997 +161 0 0.499997 +SURF 0x30 +mat 1 +refs 3 +80 1 0.499997 +81 0 0.538754 +161 0 0.499997 +SURF 0x30 +mat 1 +refs 3 +80 1 0.499997 +0 1 0.538754 +81 0 0.538754 +kids 0 +OBJECT poly +name "disk" +loc -0.5 0.000827358 0.00013657 +numvert 82 +0 -1.44889 0.388229 +0 -1.41445 0.499339 +0 -1.3715 0.607445 +0 -1.3203 0.7119 +0 -1.26117 0.812075 +0 -1.19445 0.90736 +0 -1.12054 0.997195 +0 -1.0399 1.08103 +0 -0.952995 1.15836 +0 -0.860365 1.22873 +0 -0.76256 1.29171 +0 -0.66017 1.34692 +0 -0.55381 1.39402 +0 -0.444118 1.43274 +0 -0.331755 1.46285 +0 -0.217397 1.48416 +0 -0.101732 1.49654 +0 0.0145442 1.49993 +0 0.130734 1.49429 +0 0.246137 1.47967 +0 0.360059 1.45615 +0 0.471817 1.42386 +0 0.580735 1.38302 +0 0.686165 1.33386 +0 0.787465 1.27667 +0 0.88403 1.21181 +0 0.97528 1.13967 +0 1.06066 1.06066 +0 1.13967 0.975275 +0 1.21181 0.88403 +0 1.27667 0.787465 +0 1.33386 0.686165 +0 1.38302 0.580735 +0 1.42386 0.471817 +0 1.45615 0.360059 +0 1.47967 0.246137 +0 1.49429 0.130734 +0 1.49993 0.0145441 +0 1.49654 -0.101733 +0 1.48416 -0.217398 +0 1.46285 -0.331755 +0 1.43274 -0.444118 +0 1.39402 -0.55381 +0 1.34692 -0.66017 +0 1.29171 -0.76256 +0 1.22873 -0.860365 +0 1.15836 -0.952995 +0 1.08103 -1.0399 +0 0.997195 -1.12054 +0 0.90736 -1.19445 +0 0.812075 -1.26117 +0 0.7119 -1.3203 +0 0.607445 -1.3715 +0 0.499339 -1.41445 +0 0.388229 -1.44889 +0 0.274783 -1.47461 +0 0.159685 -1.49147 +0 0.0436268 -1.49936 +0 -0.072694 -1.49824 +0 -0.188578 -1.4881 +0 -0.303326 -1.46901 +0 -0.416252 -1.44109 +0 -0.526675 -1.4045 +0 -0.63393 -1.35946 +0 -0.73737 -1.30625 +0 -0.836375 -1.24518 +0 -0.930355 -1.17663 +0 -1.01874 -1.10099 +0 -1.10099 -1.01874 +0 -1.17663 -0.930355 +0 -1.24518 -0.836375 +0 -1.30625 -0.73737 +0 -1.35946 -0.633925 +0 -1.4045 -0.526675 +0 -1.44109 -0.416251 +0 -1.46901 -0.303326 +0 -1.4881 -0.188577 +0 -1.49823 -0.072693 +0 -1.49936 0.0436274 +0 -1.49147 0.159686 +0 -1.47461 0.274783 +0 0 0 +numsurf 81 +SURF 0x20 +mat 1 +refs 3 +0 1 0.5 +1 0.998496 0.538754 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +1 0.998496 0.538754 +2 0.993993 0.577274 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +2 0.993993 0.577274 +3 0.986517 0.61533 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +3 0.986517 0.61533 +4 0.976115 0.652692 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +4 0.976115 0.652692 +5 0.962848 0.689135 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +5 0.962848 0.689135 +6 0.946796 0.724442 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +6 0.946796 0.724442 +7 0.928056 0.758398 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +7 0.928056 0.758398 +8 0.906741 0.790801 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +8 0.906741 0.790801 +9 0.882978 0.821454 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +9 0.882978 0.821454 +10 0.856911 0.850175 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +10 0.856911 0.850175 +11 0.828696 0.876789 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +11 0.828696 0.876789 +12 0.798504 0.901137 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +12 0.798504 0.901137 +13 0.766514 0.923073 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +13 0.766514 0.923073 +14 0.732921 0.942464 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +14 0.732921 0.942464 +15 0.697926 0.959194 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +15 0.697926 0.959194 +16 0.66174 0.973163 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +16 0.66174 0.973163 +17 0.624579 0.984286 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +17 0.624579 0.984286 +18 0.586669 0.992496 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +18 0.586669 0.992496 +19 0.548236 0.997745 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +19 0.548236 0.997745 +20 0.509511 1 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +20 0.509511 1 +21 0.470729 0.999248 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +21 0.470729 0.999248 +22 0.432121 0.995493 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +22 0.432121 0.995493 +23 0.39392 0.988759 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +23 0.39392 0.988759 +24 0.356356 0.979085 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +24 0.356356 0.979085 +25 0.319655 0.96653 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +25 0.319655 0.96653 +26 0.284038 0.951169 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +26 0.284038 0.951169 +27 0.249718 0.933094 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +27 0.249718 0.933094 +28 0.216902 0.912415 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +28 0.216902 0.912415 +29 0.185788 0.889256 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +29 0.185788 0.889256 +30 0.156562 0.863755 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +30 0.156562 0.863755 +31 0.129401 0.836067 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +31 0.129401 0.836067 +32 0.104467 0.806358 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +32 0.104467 0.806358 +33 0.0819109 0.774806 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +33 0.0819109 0.774806 +34 0.0618681 0.741602 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +34 0.0618681 0.741602 +35 0.0444592 0.706944 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +35 0.0444592 0.706944 +36 0.0297888 0.671042 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +36 0.0297888 0.671042 +37 0.0179453 0.634111 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +37 0.0179453 0.634111 +38 0.00899967 0.596374 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +38 0.00899967 0.596374 +39 0.00300592 0.558057 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +39 0.00300592 0.558057 +40 0 0.519391 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +40 0 0.519391 +41 0 0.480609 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +41 0 0.480609 +42 0.00300592 0.441943 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +42 0.00300592 0.441943 +43 0.00899971 0.403626 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +43 0.00899971 0.403626 +44 0.0179453 0.365888 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +44 0.0179453 0.365888 +45 0.0297889 0.328958 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +45 0.0297889 0.328958 +46 0.0444593 0.293056 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +46 0.0444593 0.293056 +47 0.0618682 0.258398 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +47 0.0618682 0.258398 +48 0.0819109 0.225194 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +48 0.0819109 0.225194 +49 0.104467 0.193642 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +49 0.104467 0.193642 +50 0.129401 0.163933 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +50 0.129401 0.163933 +51 0.156562 0.136245 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +51 0.156562 0.136245 +52 0.185788 0.110744 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +52 0.185788 0.110744 +53 0.216902 0.0875849 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +53 0.216902 0.0875849 +54 0.249718 0.0669058 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +54 0.249718 0.0669058 +55 0.284038 0.0488314 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +55 0.284038 0.0488314 +56 0.319655 0.0334704 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +56 0.319655 0.0334704 +57 0.356356 0.0209151 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +57 0.356356 0.0209151 +58 0.39392 0.0112411 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +58 0.39392 0.0112411 +59 0.432121 0.0045066 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +59 0.432121 0.0045066 +60 0.470729 0.000752034 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +60 0.470729 0.000752034 +61 0.509511 0 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +61 0.509511 0 +62 0.548236 0.00225503 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +62 0.548236 0.00225503 +63 0.586669 0.00750353 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +63 0.586669 0.00750353 +64 0.62458 0.015714 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +64 0.62458 0.015714 +65 0.66174 0.026837 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +65 0.66174 0.026837 +66 0.697926 0.0408057 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +66 0.697926 0.0408057 +67 0.732921 0.057536 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +67 0.732921 0.057536 +68 0.766515 0.0769273 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +68 0.766515 0.0769273 +69 0.798504 0.098863 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +69 0.798504 0.098863 +70 0.828696 0.123211 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +70 0.828696 0.123211 +71 0.856911 0.149826 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +71 0.856911 0.149826 +72 0.882978 0.178546 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +72 0.882978 0.178546 +73 0.906741 0.209199 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +73 0.906741 0.209199 +74 0.928057 0.241602 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +74 0.928057 0.241602 +75 0.946796 0.275558 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +75 0.946796 0.275558 +76 0.962848 0.310865 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +76 0.962848 0.310865 +77 0.976115 0.347308 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +77 0.976115 0.347308 +78 0.986517 0.384671 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +78 0.986517 0.384671 +79 0.993993 0.422726 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +79 0.993993 0.422726 +80 0.998496 0.461247 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +80 0.998496 0.461247 +0 1 0.5 +81 0.499812 0.5 +kids 0 +OBJECT poly +name "disk" +loc 0.5 0.000827343 0.000136574 +numvert 82 +0 -1.44889 0.388229 +0 -1.41445 0.499339 +0 -1.3715 0.607445 +0 -1.3203 0.7119 +0 -1.26117 0.812075 +0 -1.19445 0.90736 +0 -1.12054 0.997195 +0 -1.0399 1.08103 +0 -0.952995 1.15836 +0 -0.860365 1.22873 +0 -0.76256 1.29171 +0 -0.66017 1.34692 +0 -0.55381 1.39402 +0 -0.444118 1.43274 +0 -0.331755 1.46285 +0 -0.217397 1.48416 +0 -0.101732 1.49654 +0 0.0145442 1.49993 +0 0.130734 1.49429 +0 0.246137 1.47967 +0 0.360059 1.45615 +0 0.471817 1.42386 +0 0.580735 1.38302 +0 0.686165 1.33386 +0 0.787465 1.27667 +0 0.88403 1.21181 +0 0.97528 1.13967 +0 1.06066 1.06066 +0 1.13967 0.975275 +0 1.21181 0.88403 +0 1.27667 0.787465 +0 1.33386 0.686165 +0 1.38302 0.580735 +0 1.42386 0.471817 +0 1.45615 0.360059 +0 1.47967 0.246137 +0 1.49429 0.130734 +0 1.49993 0.0145441 +0 1.49654 -0.101733 +0 1.48416 -0.217398 +0 1.46285 -0.331755 +0 1.43274 -0.444118 +0 1.39402 -0.55381 +0 1.34692 -0.66017 +0 1.29171 -0.76256 +0 1.22873 -0.860365 +0 1.15836 -0.952995 +0 1.08103 -1.0399 +0 0.997195 -1.12054 +0 0.90736 -1.19445 +0 0.812075 -1.26117 +0 0.7119 -1.3203 +0 0.607445 -1.3715 +0 0.499339 -1.41445 +0 0.388229 -1.44889 +0 0.274783 -1.47461 +0 0.159685 -1.49147 +0 0.0436268 -1.49936 +0 -0.072694 -1.49824 +0 -0.188578 -1.4881 +0 -0.303326 -1.46901 +0 -0.416252 -1.44109 +0 -0.526675 -1.4045 +0 -0.63393 -1.35946 +0 -0.73737 -1.30625 +0 -0.836375 -1.24518 +0 -0.930355 -1.17663 +0 -1.01874 -1.10099 +0 -1.10099 -1.01874 +0 -1.17663 -0.930355 +0 -1.24518 -0.836375 +0 -1.30625 -0.73737 +0 -1.35946 -0.633925 +0 -1.4045 -0.526675 +0 -1.44109 -0.416251 +0 -1.46901 -0.303326 +0 -1.4881 -0.188577 +0 -1.49823 -0.072693 +0 -1.49936 0.0436274 +0 -1.49147 0.159686 +0 -1.47461 0.274783 +0 0 0 +numsurf 81 +SURF 0x20 +mat 1 +refs 3 +0 1 0.5 +1 0.998496 0.538754 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +1 0.998496 0.538754 +2 0.993993 0.577274 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +2 0.993993 0.577274 +3 0.986517 0.61533 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +3 0.986517 0.61533 +4 0.976115 0.652692 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +4 0.976115 0.652692 +5 0.962848 0.689135 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +5 0.962848 0.689135 +6 0.946796 0.724442 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +6 0.946796 0.724442 +7 0.928056 0.758398 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +7 0.928056 0.758398 +8 0.906741 0.790801 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +8 0.906741 0.790801 +9 0.882978 0.821454 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +9 0.882978 0.821454 +10 0.856911 0.850175 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +10 0.856911 0.850175 +11 0.828696 0.876789 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +11 0.828696 0.876789 +12 0.798504 0.901137 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +12 0.798504 0.901137 +13 0.766514 0.923073 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +13 0.766514 0.923073 +14 0.732921 0.942464 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +14 0.732921 0.942464 +15 0.697926 0.959194 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +15 0.697926 0.959194 +16 0.66174 0.973163 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +16 0.66174 0.973163 +17 0.624579 0.984286 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +17 0.624579 0.984286 +18 0.586669 0.992496 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +18 0.586669 0.992496 +19 0.548236 0.997745 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +19 0.548236 0.997745 +20 0.509511 1 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +20 0.509511 1 +21 0.470729 0.999248 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +21 0.470729 0.999248 +22 0.432121 0.995493 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +22 0.432121 0.995493 +23 0.39392 0.988759 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +23 0.39392 0.988759 +24 0.356356 0.979085 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +24 0.356356 0.979085 +25 0.319655 0.96653 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +25 0.319655 0.96653 +26 0.284038 0.951169 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +26 0.284038 0.951169 +27 0.249718 0.933094 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +27 0.249718 0.933094 +28 0.216902 0.912415 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +28 0.216902 0.912415 +29 0.185788 0.889256 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +29 0.185788 0.889256 +30 0.156562 0.863755 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +30 0.156562 0.863755 +31 0.129401 0.836067 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +31 0.129401 0.836067 +32 0.104467 0.806358 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +32 0.104467 0.806358 +33 0.0819109 0.774806 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +33 0.0819109 0.774806 +34 0.0618681 0.741602 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +34 0.0618681 0.741602 +35 0.0444592 0.706944 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +35 0.0444592 0.706944 +36 0.0297888 0.671042 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +36 0.0297888 0.671042 +37 0.0179453 0.634111 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +37 0.0179453 0.634111 +38 0.00899967 0.596374 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +38 0.00899967 0.596374 +39 0.00300592 0.558057 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +39 0.00300592 0.558057 +40 0 0.519391 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +40 0 0.519391 +41 0 0.480609 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +41 0 0.480609 +42 0.00300592 0.441943 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +42 0.00300592 0.441943 +43 0.00899971 0.403626 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +43 0.00899971 0.403626 +44 0.0179453 0.365888 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +44 0.0179453 0.365888 +45 0.0297889 0.328958 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +45 0.0297889 0.328958 +46 0.0444593 0.293056 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +46 0.0444593 0.293056 +47 0.0618682 0.258398 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +47 0.0618682 0.258398 +48 0.0819109 0.225194 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +48 0.0819109 0.225194 +49 0.104467 0.193642 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +49 0.104467 0.193642 +50 0.129401 0.163933 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +50 0.129401 0.163933 +51 0.156562 0.136245 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +51 0.156562 0.136245 +52 0.185788 0.110744 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +52 0.185788 0.110744 +53 0.216902 0.0875849 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +53 0.216902 0.0875849 +54 0.249718 0.0669058 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +54 0.249718 0.0669058 +55 0.284038 0.0488314 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +55 0.284038 0.0488314 +56 0.319655 0.0334704 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +56 0.319655 0.0334704 +57 0.356356 0.0209151 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +57 0.356356 0.0209151 +58 0.39392 0.0112411 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +58 0.39392 0.0112411 +59 0.432121 0.0045066 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +59 0.432121 0.0045066 +60 0.470729 0.000752034 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +60 0.470729 0.000752034 +61 0.509511 0 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +61 0.509511 0 +62 0.548236 0.00225503 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +62 0.548236 0.00225503 +63 0.586669 0.00750353 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +63 0.586669 0.00750353 +64 0.62458 0.015714 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +64 0.62458 0.015714 +65 0.66174 0.026837 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +65 0.66174 0.026837 +66 0.697926 0.0408057 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +66 0.697926 0.0408057 +67 0.732921 0.057536 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +67 0.732921 0.057536 +68 0.766515 0.0769273 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +68 0.766515 0.0769273 +69 0.798504 0.098863 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +69 0.798504 0.098863 +70 0.828696 0.123211 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +70 0.828696 0.123211 +71 0.856911 0.149826 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +71 0.856911 0.149826 +72 0.882978 0.178546 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +72 0.882978 0.178546 +73 0.906741 0.209199 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +73 0.906741 0.209199 +74 0.928057 0.241602 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +74 0.928057 0.241602 +75 0.946796 0.275558 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +75 0.946796 0.275558 +76 0.962848 0.310865 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +76 0.962848 0.310865 +77 0.976115 0.347308 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +77 0.976115 0.347308 +78 0.986517 0.384671 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +78 0.986517 0.384671 +79 0.993993 0.422726 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +79 0.993993 0.422726 +80 0.998496 0.461247 +81 0.499812 0.5 +SURF 0x20 +mat 1 +refs 3 +80 0.998496 0.461247 +0 1 0.5 +81 0.499812 0.5 +kids 0 diff --git a/demos/simon/astropong/data/Scoreboard.rgb b/demos/simon/astropong/data/Scoreboard.rgb new file mode 100644 index 0000000..2710893 Binary files /dev/null and b/demos/simon/astropong/data/Scoreboard.rgb differ diff --git a/demos/simon/astropong/data/arena2.ac b/demos/simon/astropong/data/arena2.ac new file mode 100644 index 0000000..e13a6fa --- /dev/null +++ b/demos/simon/astropong/data/arena2.ac @@ -0,0 +1,272 @@ +AC3Db +MATERIAL "ac3dmat8" rgb 0.627 0.753 0.878 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.502 0.502 0.502 shi 10 trans 0.655 +OBJECT world +kids 1 +OBJECT poly +numvert 96 +4.975 -4.975 -4.975 +4.975 -4.975 4.975 +4 -5 5 +4 -5 -5 +4.975 4.975 -4.975 +4 5 -5 +4 5 5 +4.975 4.975 4.975 +4 5 -5 +4 -5 -5 +4 -5 5 +4 5 5 +4.975 4.975 4.975 +4.975 -4.975 4.975 +4.975 -4.975 -4.975 +4.975 4.975 -4.975 +4.975 4.975 -4.975 +4.975 -4.975 -4.975 +4 -5 -5 +4 5 -5 +4 5 5 +4 -5 5 +4.975 -4.975 4.975 +4.975 4.975 4.975 +-4 -5 -5 +-4 -5 5 +-4.975 -4.975 4.975 +-4.975 -4.975 -4.975 +-4 5 -5 +-4.975 4.975 -4.975 +-4.975 4.975 4.975 +-4 5 5 +-4.975 4.975 -4.975 +-4.975 -4.975 -4.975 +-4.975 -4.975 4.975 +-4.975 4.975 4.975 +-4 5 5 +-4 -5 5 +-4 -5 -5 +-4 5 -5 +-4 5 -5 +-4 -5 -5 +-4.975 -4.975 -4.975 +-4.975 4.975 -4.975 +-4.975 4.975 4.975 +-4.975 -4.975 4.975 +-4 -5 5 +-4 5 5 +4.95 -3.96 -4.95 +4.95 -3.96 4.95 +4.975 -4.975 4.975 +4.975 -4.975 -4.975 +-4.95 -3.96 -4.95 +-4.975 -4.975 -4.975 +-4.975 -4.975 4.975 +-4.95 -3.96 4.95 +-4.975 -4.975 -4.975 +4.975 -4.975 -4.975 +4.975 -4.975 4.975 +-4.975 -4.975 4.975 +-4.95 -3.96 4.95 +4.95 -3.96 4.95 +4.95 -3.96 -4.95 +-4.95 -3.96 -4.95 +-4.95 -3.96 -4.95 +4.95 -3.96 -4.95 +4.975 -4.975 -4.975 +-4.975 -4.975 -4.975 +-4.975 -4.975 4.975 +4.975 -4.975 4.975 +4.95 -3.96 4.95 +-4.95 -3.96 4.95 +4.975 4.975 -4.975 +4.975 4.975 4.975 +4.95 3.96 4.95 +4.95 3.96 -4.95 +-4.975 4.975 -4.975 +-4.95 3.96 -4.95 +-4.95 3.96 4.95 +-4.975 4.975 4.975 +-4.95 3.96 -4.95 +4.95 3.96 -4.95 +4.95 3.96 4.95 +-4.95 3.96 4.95 +-4.975 4.975 4.975 +4.975 4.975 4.975 +4.975 4.975 -4.975 +-4.975 4.975 -4.975 +-4.975 4.975 -4.975 +4.975 4.975 -4.975 +4.95 3.96 -4.95 +-4.95 3.96 -4.95 +-4.95 3.96 4.95 +4.95 3.96 4.95 +4.975 4.975 4.975 +-4.975 4.975 4.975 +numsurf 24 +SURF 0x30 +mat 0 +refs 4 +0 0 0 +1 1 0 +2 1 1 +3 0 1 +SURF 0x30 +mat 0 +refs 4 +4 0 0 +5 1 0 +6 1 1 +7 0 1 +SURF 0x30 +mat 0 +refs 4 +8 0 0 +9 1 0 +10 1 1 +11 0 1 +SURF 0x30 +mat 0 +refs 4 +12 0 0 +13 1 0 +14 1 1 +15 0 1 +SURF 0x30 +mat 0 +refs 4 +16 0 0 +17 1 0 +18 1 1 +19 0 1 +SURF 0x30 +mat 0 +refs 4 +20 0 0 +21 1 0 +22 1 1 +23 0 1 +SURF 0x30 +mat 0 +refs 4 +24 0 0 +25 1 0 +26 1 1 +27 0 1 +SURF 0x30 +mat 0 +refs 4 +28 0 0 +29 1 0 +30 1 1 +31 0 1 +SURF 0x30 +mat 0 +refs 4 +32 0 0 +33 1 0 +34 1 1 +35 0 1 +SURF 0x30 +mat 0 +refs 4 +36 0 0 +37 1 0 +38 1 1 +39 0 1 +SURF 0x30 +mat 0 +refs 4 +40 0 0 +41 1 0 +42 1 1 +43 0 1 +SURF 0x30 +mat 0 +refs 4 +44 0 0 +45 1 0 +46 1 1 +47 0 1 +SURF 0x30 +mat 0 +refs 4 +48 0 0 +49 1 0 +50 1 1 +51 0 1 +SURF 0x30 +mat 0 +refs 4 +52 0 0 +53 1 0 +54 1 1 +55 0 1 +SURF 0x30 +mat 0 +refs 4 +56 0 0 +57 1 0 +58 1 1 +59 0 1 +SURF 0x30 +mat 0 +refs 4 +60 0 0 +61 1 0 +62 1 1 +63 0 1 +SURF 0x30 +mat 0 +refs 4 +64 0 0 +65 1 0 +66 1 1 +67 0 1 +SURF 0x30 +mat 0 +refs 4 +68 0 0 +69 1 0 +70 1 1 +71 0 1 +SURF 0x30 +mat 0 +refs 4 +72 0 0 +73 1 0 +74 1 1 +75 0 1 +SURF 0x30 +mat 0 +refs 4 +76 0 0 +77 1 0 +78 1 1 +79 0 1 +SURF 0x30 +mat 0 +refs 4 +80 0 0 +81 1 0 +82 1 1 +83 0 1 +SURF 0x30 +mat 0 +refs 4 +84 0 0 +85 1 0 +86 1 1 +87 0 1 +SURF 0x30 +mat 0 +refs 4 +88 0 0 +89 1 0 +90 1 1 +91 0 1 +SURF 0x30 +mat 0 +refs 4 +92 0 0 +93 1 0 +94 1 1 +95 0 1 +kids 0 diff --git a/demos/simon/astropong/data/ball3.ac b/demos/simon/astropong/data/ball3.ac new file mode 100644 index 0000000..90a5b45 --- /dev/null +++ b/demos/simon/astropong/data/ball3.ac @@ -0,0 +1,2474 @@ +AC3Db +MATERIAL "ac3dmat1" rgb 1 1 1 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +OBJECT world +kids 2 +OBJECT poly +name "mesh" +loc -0.010227 -0.145106 0.116565 +texture "embossed_herring.rgb" +texrep 0.8 0.55 +texoff 0.09 0.22 +numvert 176 +0 0.245586 -1.12778 +0 0.279383 -1.06301 +0 0.30642 -0.972671 +0 0.333458 -0.856768 +0 0.407809 -0.669279 +0 0.455123 -0.481792 +0 0.482161 -0.294301 +0 0.468643 -0.106812 +0 0.428085 0.0806772 +0 0.380771 0.268166 +0 0.333458 0.455657 +0 0.279383 0.643146 +0 0.238827 0.764159 +0 0.238827 0.828929 +0 0.342617 0.92949 +-0.000522226 0.671901 1.08663 +0 0.219226 -1.14823 +0.145902 0.261358 -1.1666 +0.145902 0.280885 -1.06623 +0.145902 0.297407 -0.937449 +0.145902 0.363499 -0.729124 +0 0.380094 -0.481792 +0.145902 0.441605 -0.312481 +0.145902 0.429588 -0.104161 +0.145902 0.391285 0.104161 +0.145902 0.342468 0.312484 +0.145902 0.300411 0.520803 +0.145902 0.256101 0.729125 +0.145902 0.228313 0.863592 +0.145902 0.235823 0.93555 +0.176019 0.451131 1.04355 +-0.000522226 0.570512 1.08663 +0 0.192864 -1.1738 +0.238747 0.222304 -1.1666 +0.238747 0.231317 -1.06623 +0.238747 0.234321 -0.937449 +0.238747 0.283889 -0.729124 +0.238747 0.328951 -0.520803 +0.238747 0.357489 -0.312481 +0.238747 0.348478 -0.104161 +0.238747 0.316934 0.104161 +0.238747 0.271872 0.312484 +0.238747 0.240329 0.520803 +0.238747 0.21179 0.729125 +0.238747 0.201276 0.863592 +0.145902 0.216296 0.93555 +0.176019 0.373109 1.04355 +-0.000522226 0.469123 1.08663 +0 0.166503 -1.2417 +0.238747 0.183251 -1.1987 +0.313357 0.181749 -1.06623 +0.313357 0.171235 -0.937449 +0.313357 0.20428 -0.729124 +0.313357 0.245586 -0.520803 +0.313357 0.273374 -0.312481 +0.313357 0.267366 -0.104161 +0.313357 0.242582 0.104161 +0.313357 0.201276 0.312484 +0.313357 0.180247 0.520803 +0.313357 0.167479 0.729125 +0.313357 0.174239 0.863592 +0.238747 0.196769 0.93555 +0.176019 0.295083 1.04355 +-0.000522226 0.367734 1.08663 +0 0.140142 -1.25704 +0.238747 0.144197 -1.1987 +0.313357 0.132181 -1.06623 +0.313357 0.108148 -0.937449 +0.313357 0.124671 -0.729124 +0.313357 0.162222 -0.520803 +0.313357 0.189259 -0.312481 +0.313357 0.186255 -0.104161 +0.313357 0.168231 0.104161 +0.313357 0.130679 0.312484 +0.313357 0.120165 0.520803 +0.313357 0.123169 0.729125 +0.313357 0.147202 0.863592 +0.238747 0.177243 0.93555 +0.176019 0.21706 1.04355 +-0.000522226 0.266345 1.08663 +0 0.113781 -1.25704 +0.238747 0.105144 -1.1987 +0.313357 0.0826132 -1.06623 +0.313357 0.0450616 -0.937449 +0.313357 0.0450619 -0.729124 +0.313357 0.078858 -0.520803 +0.313357 0.105144 -0.312481 +0.313357 0.105144 -0.104161 +0.313357 0.0938787 0.104161 +0.313357 0.0600822 0.312484 +0.313357 0.0600822 0.520803 +0.313357 0.078858 0.729125 +0.313357 0.120165 0.863592 +0.238747 0.157716 0.93555 +0.176019 0.139036 1.04355 +-0.000522226 0.164956 1.08663 +0 0.0874197 -1.25704 +0.238747 0.0660905 -1.1987 +0.313357 0.0330454 -1.06623 +0.313357 -0.0180247 -0.937449 +0.313357 -0.0345474 -0.729124 +0.313357 -0.00450608 -0.520803 +0.313357 0.0210288 -0.312481 +0.313357 0.024033 -0.104161 +0.313357 0.0195268 0.104161 +0.313357 -0.0105143 0.312484 +0.313357 0 0.520803 +0.313357 0.0345472 0.729125 +0.313357 0.0931276 0.863592 +0.238747 0.138189 0.93555 +0.176019 0.0610128 1.04355 +-0.000522226 0.0635669 1.08663 +0 0.0610584 -1.2417 +0.238747 0.027037 -1.1987 +0.313357 -0.0165227 -1.06623 +0.313357 -0.0811111 -0.937449 +0.313357 -0.114156 -0.729124 +0.313357 -0.0878704 -0.520803 +0.313357 -0.0630863 -0.312481 +0.313357 -0.0570781 -0.104161 +0.313357 -0.054825 0.104161 +0.313357 -0.0811111 0.312484 +0.313357 -0.0600822 0.520803 +0.313357 -0.00976336 0.729125 +0.313357 0.0660905 0.863592 +0.238747 0.118662 0.93555 +0.176019 -0.0170108 1.04355 +-0.000522226 -0.0378221 1.08663 +0 0.0346975 -1.20591 +0.238747 -0.0120165 -1.1666 +0.238747 -0.0660905 -1.06623 +0.238747 -0.144197 -0.937449 +0.238747 -0.193765 -0.729124 +0.238747 -0.171235 -0.520803 +0.238747 -0.147202 -0.312481 +0.238747 -0.138189 -0.104161 +0.238747 -0.129177 0.104161 +0.238747 -0.151708 0.312484 +0.238747 -0.120164 0.520803 +0.238747 -0.054074 0.729125 +0.238747 0.0390537 0.863592 +0.145902 0.0991359 0.93555 +0.176019 -0.0950344 1.04355 +-0.000522226 -0.139211 1.08663 +0 0.00833648 -1.14823 +0.145902 -0.0510698 -1.1666 +0.145902 -0.115658 -1.06623 +0.145902 -0.207284 -0.937449 +0.145902 -0.273374 -0.729124 +0.145902 -0.254599 -0.520803 +0.145902 -0.231317 -0.312481 +0.238747 -0.2193 -0.104161 +0.238747 -0.203529 0.104161 +0.145902 -0.222304 0.312484 +0.145902 -0.180247 0.520803 +0.145902 -0.0983849 0.729125 +0.145902 0.0120165 0.863592 +0.145902 0.0796091 0.93555 +0.176019 -0.173058 1.04355 +-0.000522226 -0.2406 1.08663 +0 -0.0180247 -1.12778 +0 -0.0720987 -1.06301 +0 -0.139691 -0.972671 +0 -0.234321 -0.856768 +0 -0.308673 -0.669279 +0 -0.295154 -0.481792 +0 -0.274876 -0.294301 +0 -0.261358 -0.106812 +0 -0.24108 0.0806772 +0 -0.254599 0.268166 +0 -0.207284 0.455657 +0 -0.119413 0.643146 +0 -0.00450611 0.764159 +0 0.0630864 0.828929 +0 -0.0744983 0.92949 +-0.000522226 -0.341988 1.08663 +numsurf 150 +SURF 0x30 +mat 0 +refs 4 +0 0.0420975 0.700855 +16 0.0332349 0.667521 +17 0.0449697 0.663818 +1 0.0701625 0.74359 +SURF 0x30 +mat 0 +refs 4 +1 0.0701625 0.74359 +17 0.0449697 0.663818 +18 0.0687675 0.745489 +2 0.109306 0.777778 +SURF 0x30 +mat 0 +refs 4 +2 0.109306 0.777778 +18 0.0687675 0.745489 +19 0.124569 0.766382 +3 0.159527 0.811966 +SURF 0x30 +mat 0 +refs 4 +3 0.159527 0.811966 +19 0.124569 0.766382 +20 0.214837 0.849953 +4 0.240768 0.905983 +SURF 0x30 +mat 0 +refs 4 +4 0.240768 0.905983 +20 0.214837 0.849953 +21 0.322009 0.87094 +5 0.322009 0.965812 +SURF 0x30 +mat 0 +refs 4 +5 0.322009 0.965812 +21 0.322009 0.87094 +22 0.395372 0.948718 +6 0.40325 1 +SURF 0x30 +mat 0 +refs 4 +6 0.40325 1 +22 0.395372 0.948718 +23 0.485639 0.933523 +7 0.48449 0.982906 +SURF 0x30 +mat 0 +refs 4 +7 0.48449 0.982906 +23 0.485639 0.933523 +24 0.575907 0.88509 +8 0.565731 0.931624 +SURF 0x30 +mat 0 +refs 4 +8 0.565731 0.931624 +24 0.575907 0.88509 +25 0.666174 0.823362 +9 0.646972 0.871795 +SURF 0x30 +mat 0 +refs 4 +9 0.646972 0.871795 +25 0.666174 0.823362 +26 0.756442 0.77018 +10 0.728213 0.811966 +SURF 0x30 +mat 0 +refs 4 +10 0.728213 0.811966 +26 0.756442 0.77018 +27 0.846709 0.71415 +11 0.809453 0.74359 +SURF 0x30 +mat 0 +refs 4 +11 0.809453 0.74359 +27 0.846709 0.71415 +28 0.904973 0.679012 +12 0.861891 0.692308 +SURF 0x30 +mat 0 +refs 4 +12 0.861891 0.692308 +28 0.904973 0.679012 +29 0.936156 0.688509 +13 0.889956 0.692308 +SURF 0x30 +mat 0 +refs 4 +13 0.889956 0.692308 +29 0.936156 0.688509 +30 0.984572 0.800418 +14 0.93353 0.823547 +SURF 0x30 +mat 0 +refs 4 +14 0.93353 0.823547 +30 0.984572 0.800418 +31 1 0.890085 +15 1 0.966239 +SURF 0x30 +mat 0 +refs 4 +16 0.0332349 0.667521 +32 0.0221565 0.634188 +33 0.0252749 0.671415 +17 0.0449697 0.663818 +SURF 0x30 +mat 0 +refs 4 +17 0.0449697 0.663818 +33 0.0252749 0.671415 +34 0.0687675 0.682811 +18 0.0687675 0.745489 +SURF 0x30 +mat 0 +refs 4 +18 0.0687675 0.745489 +34 0.0687675 0.682811 +35 0.124569 0.68661 +19 0.124569 0.766382 +SURF 0x30 +mat 0 +refs 4 +19 0.124569 0.766382 +35 0.124569 0.68661 +36 0.214837 0.749288 +20 0.214837 0.849953 +SURF 0x30 +mat 0 +refs 4 +20 0.214837 0.849953 +36 0.214837 0.749288 +37 0.305104 0.806268 +21 0.322009 0.87094 +SURF 0x30 +mat 0 +refs 4 +21 0.322009 0.87094 +37 0.305104 0.806268 +38 0.395372 0.842355 +22 0.395372 0.948718 +SURF 0x30 +mat 0 +refs 4 +22 0.395372 0.948718 +38 0.395372 0.842355 +39 0.485639 0.830959 +23 0.485639 0.933523 +SURF 0x30 +mat 0 +refs 4 +23 0.485639 0.933523 +39 0.485639 0.830959 +40 0.575907 0.791073 +24 0.575907 0.88509 +SURF 0x30 +mat 0 +refs 4 +24 0.575907 0.88509 +40 0.575907 0.791073 +41 0.666174 0.734093 +25 0.666174 0.823362 +SURF 0x30 +mat 0 +refs 4 +25 0.666174 0.823362 +41 0.666174 0.734093 +42 0.756442 0.694207 +26 0.756442 0.77018 +SURF 0x30 +mat 0 +refs 4 +26 0.756442 0.77018 +42 0.756442 0.694207 +43 0.846709 0.65812 +27 0.846709 0.71415 +SURF 0x30 +mat 0 +refs 4 +27 0.846709 0.71415 +43 0.846709 0.65812 +44 0.904973 0.644824 +28 0.904973 0.679012 +SURF 0x30 +mat 0 +refs 4 +28 0.904973 0.679012 +44 0.904973 0.644824 +45 0.936156 0.663818 +29 0.936156 0.688509 +SURF 0x30 +mat 0 +refs 4 +29 0.936156 0.688509 +45 0.936156 0.663818 +46 0.984572 0.741814 +30 0.984572 0.800418 +SURF 0x30 +mat 0 +refs 4 +30 0.984572 0.800418 +46 0.984572 0.741814 +47 1 0.813932 +31 1 0.890085 +SURF 0x30 +mat 0 +refs 4 +32 0.0221565 0.634188 +48 0.00664694 0.600855 +49 0.0252749 0.622032 +33 0.0252749 0.671415 +SURF 0x30 +mat 0 +refs 4 +33 0.0252749 0.671415 +49 0.0252749 0.622032 +50 0.0687675 0.620133 +34 0.0687675 0.682811 +SURF 0x30 +mat 0 +refs 4 +34 0.0687675 0.682811 +50 0.0687675 0.620133 +51 0.124569 0.606838 +35 0.124569 0.68661 +SURF 0x30 +mat 0 +refs 4 +35 0.124569 0.68661 +51 0.124569 0.606838 +52 0.214837 0.648623 +36 0.214837 0.749288 +SURF 0x30 +mat 0 +refs 4 +36 0.214837 0.749288 +52 0.214837 0.648623 +53 0.305104 0.700855 +37 0.305104 0.806268 +SURF 0x30 +mat 0 +refs 4 +37 0.305104 0.806268 +53 0.305104 0.700855 +54 0.395372 0.735992 +38 0.395372 0.842355 +SURF 0x30 +mat 0 +refs 4 +38 0.395372 0.842355 +54 0.395372 0.735992 +55 0.485639 0.728395 +39 0.485639 0.830959 +SURF 0x30 +mat 0 +refs 4 +39 0.485639 0.830959 +55 0.485639 0.728395 +56 0.575907 0.697056 +40 0.575907 0.791073 +SURF 0x30 +mat 0 +refs 4 +40 0.575907 0.791073 +56 0.575907 0.697056 +57 0.666174 0.644824 +41 0.666174 0.734093 +SURF 0x30 +mat 0 +refs 4 +41 0.666174 0.734093 +57 0.666174 0.644824 +58 0.756442 0.618234 +42 0.756442 0.694207 +SURF 0x30 +mat 0 +refs 4 +42 0.756442 0.694207 +58 0.756442 0.618234 +59 0.846709 0.602089 +43 0.846709 0.65812 +SURF 0x30 +mat 0 +refs 4 +43 0.846709 0.65812 +59 0.846709 0.602089 +60 0.904973 0.610636 +44 0.904973 0.644824 +SURF 0x30 +mat 0 +refs 4 +44 0.904973 0.644824 +60 0.904973 0.610636 +61 0.936156 0.639126 +45 0.936156 0.663818 +SURF 0x30 +mat 0 +refs 4 +45 0.936156 0.663818 +61 0.936156 0.639126 +62 0.984572 0.68321 +46 0.984572 0.741814 +SURF 0x30 +mat 0 +refs 4 +46 0.984572 0.741814 +62 0.984572 0.68321 +63 1 0.737778 +47 1 0.813932 +SURF 0x30 +mat 0 +refs 4 +48 0.00664694 0.600855 +64 0 0.567521 +65 0.0252749 0.57265 +49 0.0252749 0.622032 +SURF 0x30 +mat 0 +refs 4 +49 0.0252749 0.622032 +65 0.0252749 0.57265 +66 0.0687675 0.557455 +50 0.0687675 0.620133 +SURF 0x30 +mat 0 +refs 4 +50 0.0687675 0.620133 +66 0.0687675 0.557455 +67 0.124569 0.527066 +51 0.124569 0.606838 +SURF 0x30 +mat 0 +refs 4 +51 0.124569 0.606838 +67 0.124569 0.527066 +68 0.214837 0.547958 +52 0.214837 0.648623 +SURF 0x30 +mat 0 +refs 4 +52 0.214837 0.648623 +68 0.214837 0.547958 +69 0.305104 0.595442 +53 0.305104 0.700855 +SURF 0x30 +mat 0 +refs 4 +53 0.305104 0.700855 +69 0.305104 0.595442 +70 0.395372 0.62963 +54 0.395372 0.735992 +SURF 0x30 +mat 0 +refs 4 +54 0.395372 0.735992 +70 0.395372 0.62963 +71 0.485639 0.625831 +55 0.485639 0.728395 +SURF 0x30 +mat 0 +refs 4 +55 0.485639 0.728395 +71 0.485639 0.625831 +72 0.575907 0.603039 +56 0.575907 0.697056 +SURF 0x30 +mat 0 +refs 4 +56 0.575907 0.697056 +72 0.575907 0.603039 +73 0.666174 0.555556 +57 0.666174 0.644824 +SURF 0x30 +mat 0 +refs 4 +57 0.666174 0.644824 +73 0.666174 0.555556 +74 0.756442 0.54226 +58 0.756442 0.618234 +SURF 0x30 +mat 0 +refs 4 +58 0.756442 0.618234 +74 0.756442 0.54226 +75 0.846709 0.546059 +59 0.846709 0.602089 +SURF 0x30 +mat 0 +refs 4 +59 0.846709 0.602089 +75 0.846709 0.546059 +76 0.904973 0.576448 +60 0.904973 0.610636 +SURF 0x30 +mat 0 +refs 4 +60 0.904973 0.610636 +76 0.904973 0.576448 +77 0.936156 0.614435 +61 0.936156 0.639126 +SURF 0x30 +mat 0 +refs 4 +61 0.936156 0.639126 +77 0.936156 0.614435 +78 0.984572 0.624606 +62 0.984572 0.68321 +SURF 0x30 +mat 0 +refs 4 +62 0.984572 0.68321 +78 0.984572 0.624606 +79 1 0.661624 +63 1 0.737778 +SURF 0x30 +mat 0 +refs 4 +64 0 0.567521 +80 0 0.534188 +81 0.0252749 0.523267 +65 0.0252749 0.57265 +SURF 0x30 +mat 0 +refs 4 +65 0.0252749 0.57265 +81 0.0252749 0.523267 +82 0.0687675 0.494777 +66 0.0687675 0.557455 +SURF 0x30 +mat 0 +refs 4 +66 0.0687675 0.557455 +82 0.0687675 0.494777 +83 0.124569 0.447293 +67 0.124569 0.527066 +SURF 0x30 +mat 0 +refs 4 +67 0.124569 0.527066 +83 0.124569 0.447293 +84 0.214837 0.447293 +68 0.214837 0.547958 +SURF 0x30 +mat 0 +refs 4 +68 0.214837 0.547958 +84 0.214837 0.447293 +85 0.305104 0.490029 +69 0.305104 0.595442 +SURF 0x30 +mat 0 +refs 4 +69 0.305104 0.595442 +85 0.305104 0.490029 +86 0.395372 0.523267 +70 0.395372 0.62963 +SURF 0x30 +mat 0 +refs 4 +70 0.395372 0.62963 +86 0.395372 0.523267 +87 0.485639 0.523267 +71 0.485639 0.625831 +SURF 0x30 +mat 0 +refs 4 +71 0.485639 0.625831 +87 0.485639 0.523267 +88 0.575907 0.509022 +72 0.575907 0.603039 +SURF 0x30 +mat 0 +refs 4 +72 0.575907 0.603039 +88 0.575907 0.509022 +89 0.666174 0.466287 +73 0.666174 0.555556 +SURF 0x30 +mat 0 +refs 4 +73 0.666174 0.555556 +89 0.666174 0.466287 +90 0.756442 0.466287 +74 0.756442 0.54226 +SURF 0x30 +mat 0 +refs 4 +74 0.756442 0.54226 +90 0.756442 0.466287 +91 0.846709 0.490028 +75 0.846709 0.546059 +SURF 0x30 +mat 0 +refs 4 +75 0.846709 0.546059 +91 0.846709 0.490028 +92 0.904973 0.54226 +76 0.904973 0.576448 +SURF 0x30 +mat 0 +refs 4 +76 0.904973 0.576448 +92 0.904973 0.54226 +93 0.936156 0.589744 +77 0.936156 0.614435 +SURF 0x30 +mat 0 +refs 4 +77 0.936156 0.614435 +93 0.936156 0.589744 +94 0.984572 0.566002 +78 0.984572 0.624606 +SURF 0x30 +mat 0 +refs 4 +78 0.984572 0.624606 +94 0.984572 0.566002 +95 1 0.58547 +79 1 0.661624 +SURF 0x30 +mat 0 +refs 4 +80 0 0.534188 +96 0 0.500855 +97 0.0252749 0.473884 +81 0.0252749 0.523267 +SURF 0x30 +mat 0 +refs 4 +81 0.0252749 0.523267 +97 0.0252749 0.473884 +98 0.0687675 0.432099 +82 0.0687675 0.494777 +SURF 0x30 +mat 0 +refs 4 +82 0.0687675 0.494777 +98 0.0687675 0.432099 +99 0.124569 0.367521 +83 0.124569 0.447293 +SURF 0x30 +mat 0 +refs 4 +83 0.124569 0.447293 +99 0.124569 0.367521 +100 0.214837 0.346629 +84 0.214837 0.447293 +SURF 0x30 +mat 0 +refs 4 +84 0.214837 0.447293 +100 0.214837 0.346629 +101 0.305104 0.384615 +85 0.305104 0.490029 +SURF 0x30 +mat 0 +refs 4 +85 0.305104 0.490029 +101 0.305104 0.384615 +102 0.395372 0.416904 +86 0.395372 0.523267 +SURF 0x30 +mat 0 +refs 4 +86 0.395372 0.523267 +102 0.395372 0.416904 +103 0.485639 0.420703 +87 0.485639 0.523267 +SURF 0x30 +mat 0 +refs 4 +87 0.485639 0.523267 +103 0.485639 0.420703 +104 0.575907 0.415005 +88 0.575907 0.509022 +SURF 0x30 +mat 0 +refs 4 +88 0.575907 0.509022 +104 0.575907 0.415005 +105 0.666174 0.377018 +89 0.666174 0.466287 +SURF 0x30 +mat 0 +refs 4 +89 0.666174 0.466287 +105 0.666174 0.377018 +106 0.756442 0.390313 +90 0.756442 0.466287 +SURF 0x30 +mat 0 +refs 4 +90 0.756442 0.466287 +106 0.756442 0.390313 +107 0.846709 0.433998 +91 0.846709 0.490028 +SURF 0x30 +mat 0 +refs 4 +91 0.846709 0.490028 +107 0.846709 0.433998 +108 0.904973 0.508072 +92 0.904973 0.54226 +SURF 0x30 +mat 0 +refs 4 +92 0.904973 0.54226 +108 0.904973 0.508072 +109 0.936156 0.565052 +93 0.936156 0.589744 +SURF 0x30 +mat 0 +refs 4 +93 0.936156 0.589744 +109 0.936156 0.565052 +110 0.984572 0.507398 +94 0.984572 0.566002 +SURF 0x30 +mat 0 +refs 4 +94 0.984572 0.566002 +110 0.984572 0.507398 +111 1 0.509316 +95 1 0.58547 +SURF 0x30 +mat 0 +refs 4 +96 0 0.500855 +112 0.00664694 0.467521 +113 0.0252749 0.424501 +97 0.0252749 0.473884 +SURF 0x30 +mat 0 +refs 4 +97 0.0252749 0.473884 +113 0.0252749 0.424501 +114 0.0687675 0.369421 +98 0.0687675 0.432099 +SURF 0x30 +mat 0 +refs 4 +98 0.0687675 0.432099 +114 0.0687675 0.369421 +115 0.124569 0.287749 +99 0.124569 0.367521 +SURF 0x30 +mat 0 +refs 4 +99 0.124569 0.367521 +115 0.124569 0.287749 +116 0.214837 0.245964 +100 0.214837 0.346629 +SURF 0x30 +mat 0 +refs 4 +100 0.214837 0.346629 +116 0.214837 0.245964 +117 0.305104 0.279202 +101 0.305104 0.384615 +SURF 0x30 +mat 0 +refs 4 +101 0.305104 0.384615 +117 0.305104 0.279202 +118 0.395372 0.310541 +102 0.395372 0.416904 +SURF 0x30 +mat 0 +refs 4 +102 0.395372 0.416904 +118 0.395372 0.310541 +119 0.485639 0.318139 +103 0.485639 0.420703 +SURF 0x30 +mat 0 +refs 4 +103 0.485639 0.420703 +119 0.485639 0.318139 +120 0.575907 0.320988 +104 0.575907 0.415005 +SURF 0x30 +mat 0 +refs 4 +104 0.575907 0.415005 +120 0.575907 0.320988 +121 0.666174 0.287749 +105 0.666174 0.377018 +SURF 0x30 +mat 0 +refs 4 +105 0.666174 0.377018 +121 0.666174 0.287749 +122 0.756442 0.31434 +106 0.756442 0.390313 +SURF 0x30 +mat 0 +refs 4 +106 0.756442 0.390313 +122 0.756442 0.31434 +123 0.846709 0.377968 +107 0.846709 0.433998 +SURF 0x30 +mat 0 +refs 4 +107 0.846709 0.433998 +123 0.846709 0.377968 +124 0.904973 0.473884 +108 0.904973 0.508072 +SURF 0x30 +mat 0 +refs 4 +108 0.904973 0.508072 +124 0.904973 0.473884 +125 0.936156 0.540361 +109 0.936156 0.565052 +SURF 0x30 +mat 0 +refs 4 +109 0.936156 0.565052 +125 0.936156 0.540361 +126 0.984572 0.448794 +110 0.984572 0.507398 +SURF 0x30 +mat 0 +refs 4 +110 0.984572 0.507398 +126 0.984572 0.448794 +127 1 0.433162 +111 1 0.509316 +SURF 0x30 +mat 0 +refs 4 +112 0.00664694 0.467521 +128 0.0221565 0.434188 +129 0.0252749 0.375119 +113 0.0252749 0.424501 +SURF 0x30 +mat 0 +refs 4 +113 0.0252749 0.424501 +129 0.0252749 0.375119 +130 0.0687675 0.306743 +114 0.0687675 0.369421 +SURF 0x30 +mat 0 +refs 4 +114 0.0687675 0.369421 +130 0.0687675 0.306743 +131 0.124569 0.207977 +115 0.124569 0.287749 +SURF 0x30 +mat 0 +refs 4 +115 0.124569 0.287749 +131 0.124569 0.207977 +132 0.214837 0.145299 +116 0.214837 0.245964 +SURF 0x30 +mat 0 +refs 4 +116 0.214837 0.245964 +132 0.214837 0.145299 +133 0.305104 0.173789 +117 0.305104 0.279202 +SURF 0x30 +mat 0 +refs 4 +117 0.305104 0.279202 +133 0.305104 0.173789 +134 0.395372 0.204179 +118 0.395372 0.310541 +SURF 0x30 +mat 0 +refs 4 +118 0.395372 0.310541 +134 0.395372 0.204179 +135 0.485639 0.215575 +119 0.485639 0.318139 +SURF 0x30 +mat 0 +refs 4 +119 0.485639 0.318139 +135 0.485639 0.215575 +136 0.575907 0.226971 +120 0.575907 0.320988 +SURF 0x30 +mat 0 +refs 4 +120 0.575907 0.320988 +136 0.575907 0.226971 +137 0.666174 0.198481 +121 0.666174 0.287749 +SURF 0x30 +mat 0 +refs 4 +121 0.666174 0.287749 +137 0.666174 0.198481 +138 0.756442 0.238367 +122 0.756442 0.31434 +SURF 0x30 +mat 0 +refs 4 +122 0.756442 0.31434 +138 0.756442 0.238367 +139 0.846709 0.321937 +123 0.846709 0.377968 +SURF 0x30 +mat 0 +refs 4 +123 0.846709 0.377968 +139 0.846709 0.321937 +140 0.904973 0.439696 +124 0.904973 0.473884 +SURF 0x30 +mat 0 +refs 4 +124 0.904973 0.473884 +140 0.904973 0.439696 +141 0.936156 0.515669 +125 0.936156 0.540361 +SURF 0x30 +mat 0 +refs 4 +125 0.936156 0.540361 +141 0.936156 0.515669 +142 0.984572 0.39019 +126 0.984572 0.448794 +SURF 0x30 +mat 0 +refs 4 +126 0.984572 0.448794 +142 0.984572 0.39019 +143 1 0.357008 +127 1 0.433162 +SURF 0x30 +mat 0 +refs 4 +128 0.0221565 0.434188 +144 0.0332349 0.400855 +145 0.0252749 0.325736 +129 0.0252749 0.375119 +SURF 0x30 +mat 0 +refs 4 +129 0.0252749 0.375119 +145 0.0252749 0.325736 +146 0.0687675 0.244065 +130 0.0687675 0.306743 +SURF 0x30 +mat 0 +refs 4 +130 0.0687675 0.306743 +146 0.0687675 0.244065 +147 0.124569 0.128205 +131 0.124569 0.207977 +SURF 0x30 +mat 0 +refs 4 +131 0.124569 0.207977 +147 0.124569 0.128205 +148 0.214837 0.0446344 +132 0.214837 0.145299 +SURF 0x30 +mat 0 +refs 4 +132 0.214837 0.145299 +148 0.214837 0.0446344 +149 0.305104 0.068376 +133 0.305104 0.173789 +SURF 0x30 +mat 0 +refs 4 +133 0.305104 0.173789 +149 0.305104 0.068376 +150 0.395372 0.0978157 +134 0.395372 0.204179 +SURF 0x30 +mat 0 +refs 4 +134 0.395372 0.204179 +150 0.395372 0.0978157 +151 0.485639 0.11301 +135 0.485639 0.215575 +SURF 0x30 +mat 0 +refs 4 +135 0.485639 0.215575 +151 0.485639 0.11301 +152 0.575907 0.132953 +136 0.575907 0.226971 +SURF 0x30 +mat 0 +refs 4 +136 0.575907 0.226971 +152 0.575907 0.132953 +153 0.666174 0.109212 +137 0.666174 0.198481 +SURF 0x30 +mat 0 +refs 4 +137 0.666174 0.198481 +153 0.666174 0.109212 +154 0.756442 0.162393 +138 0.756442 0.238367 +SURF 0x30 +mat 0 +refs 4 +138 0.756442 0.238367 +154 0.756442 0.162393 +155 0.846709 0.265907 +139 0.846709 0.321937 +SURF 0x30 +mat 0 +refs 4 +139 0.846709 0.321937 +155 0.846709 0.265907 +156 0.904973 0.405508 +140 0.904973 0.439696 +SURF 0x30 +mat 0 +refs 4 +140 0.904973 0.439696 +156 0.904973 0.405508 +157 0.936156 0.490978 +141 0.936156 0.515669 +SURF 0x30 +mat 0 +refs 4 +141 0.936156 0.515669 +157 0.936156 0.490978 +158 0.984572 0.331586 +142 0.984572 0.39019 +SURF 0x30 +mat 0 +refs 4 +142 0.984572 0.39019 +158 0.984572 0.331586 +159 1 0.280855 +143 1 0.357008 +SURF 0x30 +mat 0 +refs 4 +144 0.0332349 0.400855 +160 0.0420975 0.367521 +161 0.0701625 0.299145 +145 0.0252749 0.325736 +SURF 0x30 +mat 0 +refs 4 +145 0.0252749 0.325736 +161 0.0701625 0.299145 +162 0.109306 0.213675 +146 0.0687675 0.244065 +SURF 0x30 +mat 0 +refs 4 +146 0.0687675 0.244065 +162 0.109306 0.213675 +163 0.159527 0.0940171 +147 0.124569 0.128205 +SURF 0x30 +mat 0 +refs 4 +147 0.124569 0.128205 +163 0.159527 0.0940171 +164 0.240768 0 +148 0.214837 0.0446344 +SURF 0x30 +mat 0 +refs 4 +148 0.214837 0.0446344 +164 0.240768 0 +165 0.322009 0.017094 +149 0.305104 0.068376 +SURF 0x30 +mat 0 +refs 4 +149 0.305104 0.068376 +165 0.322009 0.017094 +166 0.40325 0.042735 +150 0.395372 0.0978157 +SURF 0x30 +mat 0 +refs 4 +150 0.395372 0.0978157 +166 0.40325 0.042735 +167 0.48449 0.059829 +151 0.485639 0.11301 +SURF 0x30 +mat 0 +refs 4 +151 0.485639 0.11301 +167 0.48449 0.059829 +168 0.565731 0.0854701 +152 0.575907 0.132953 +SURF 0x30 +mat 0 +refs 4 +152 0.575907 0.132953 +168 0.565731 0.0854701 +169 0.646972 0.0683761 +153 0.666174 0.109212 +SURF 0x30 +mat 0 +refs 4 +153 0.666174 0.109212 +169 0.646972 0.0683761 +170 0.728213 0.128205 +154 0.756442 0.162393 +SURF 0x30 +mat 0 +refs 4 +154 0.756442 0.162393 +170 0.728213 0.128205 +171 0.809453 0.239316 +155 0.846709 0.265907 +SURF 0x30 +mat 0 +refs 4 +155 0.846709 0.265907 +171 0.809453 0.239316 +172 0.861891 0.384615 +156 0.904973 0.405508 +SURF 0x30 +mat 0 +refs 4 +156 0.904973 0.405508 +172 0.861891 0.384615 +173 0.889956 0.470085 +157 0.936156 0.490978 +SURF 0x30 +mat 0 +refs 4 +157 0.936156 0.490978 +173 0.889956 0.470085 +174 0.93353 0.296111 +158 0.984572 0.331586 +SURF 0x30 +mat 0 +refs 4 +158 0.984572 0.331586 +174 0.93353 0.296111 +175 1 0.204701 +159 1 0.280855 +kids 0 +OBJECT poly +name "mesh" +loc -0.31861 -0.145106 0.116565 +texture "embossed_herring.rgb" +texrep 0.8 0.55 +texoff 0.09 0.22 +numvert 176 +0.308383 0.245586 -1.12778 +0.308383 0.279383 -1.06301 +0.308383 0.30642 -0.972671 +0.308383 0.333458 -0.856768 +0.308383 0.407809 -0.669279 +0.308383 0.455123 -0.481792 +0.308383 0.482161 -0.294301 +0.308383 0.468643 -0.106812 +0.308383 0.428085 0.0806772 +0.308383 0.380771 0.268166 +0.308383 0.333458 0.455657 +0.308383 0.279383 0.643146 +0.308383 0.238827 0.764159 +0.308383 0.238827 0.828929 +0.308383 0.342617 0.92949 +0.307861 0.671901 1.08663 +0.308383 0.219226 -1.14823 +0.167455 0.261358 -1.1666 +0.167455 0.280885 -1.06623 +0.167455 0.297407 -0.937449 +0.167455 0.363499 -0.729124 +0.308383 0.380094 -0.481792 +0.167455 0.441605 -0.312481 +0.167455 0.429588 -0.104161 +0.167455 0.391285 0.104161 +0.167455 0.342468 0.312484 +0.167455 0.300411 0.520803 +0.167455 0.256101 0.729125 +0.167455 0.228313 0.863592 +0.167455 0.235823 0.93555 +0.137338 0.451131 1.04355 +0.307861 0.570512 1.08663 +0.308383 0.192864 -1.1738 +0.0746084 0.222304 -1.1666 +0.0746084 0.231317 -1.06623 +0.0746084 0.234321 -0.937449 +0.0746084 0.283889 -0.729124 +0.0746084 0.328951 -0.520803 +0.0746084 0.357489 -0.312481 +0.0746084 0.348478 -0.104161 +0.0746084 0.316934 0.104161 +0.0746084 0.271872 0.312484 +0.0746084 0.240329 0.520803 +0.0746084 0.21179 0.729125 +0.0746084 0.201276 0.863592 +0.167455 0.216296 0.93555 +0.137338 0.373109 1.04355 +0.307861 0.469123 1.08663 +0.308383 0.166503 -1.2417 +0.0746084 0.183251 -1.1987 +0 0.181749 -1.06623 +0 0.171235 -0.937449 +0 0.20428 -0.729124 +0 0.245586 -0.520803 +0 0.273374 -0.312481 +0 0.267366 -0.104161 +0 0.242582 0.104161 +0 0.201276 0.312484 +0 0.180247 0.520803 +0 0.167479 0.729125 +0 0.174239 0.863592 +0.0746084 0.196769 0.93555 +0.137338 0.295083 1.04355 +0.307861 0.367734 1.08663 +0.308383 0.140142 -1.25704 +0.0746084 0.144197 -1.1987 +0 0.132181 -1.06623 +0 0.108148 -0.937449 +0 0.124671 -0.729124 +0 0.162222 -0.520803 +0 0.189259 -0.312481 +0 0.186255 -0.104161 +0 0.168231 0.104161 +0 0.130679 0.312484 +0 0.120165 0.520803 +0 0.123169 0.729125 +0 0.147202 0.863592 +0.0746084 0.177243 0.93555 +0.137338 0.21706 1.04355 +0.307861 0.266345 1.08663 +0.308383 0.113781 -1.25704 +0.0746084 0.105144 -1.1987 +0 0.0826132 -1.06623 +0 0.0450616 -0.937449 +0 0.0450619 -0.729124 +0 0.078858 -0.520803 +0 0.105144 -0.312481 +0 0.105144 -0.104161 +0 0.0938787 0.104161 +0 0.0600822 0.312484 +0 0.0600822 0.520803 +0 0.078858 0.729125 +0 0.120165 0.863592 +0.0746084 0.157716 0.93555 +0.137338 0.139036 1.04355 +0.307861 0.164956 1.08663 +0.308383 0.0874197 -1.25704 +0.0746084 0.0660905 -1.1987 +0 0.0330454 -1.06623 +0 -0.0180247 -0.937449 +0 -0.0345474 -0.729124 +0 -0.00450608 -0.520803 +0 0.0210288 -0.312481 +0 0.024033 -0.104161 +0 0.0195268 0.104161 +0 -0.0105143 0.312484 +0 0 0.520803 +0 0.0345472 0.729125 +0 0.0931276 0.863592 +0.0746084 0.138189 0.93555 +0.137338 0.0610128 1.04355 +0.307861 0.0635669 1.08663 +0.308383 0.0610584 -1.2417 +0.0746084 0.027037 -1.1987 +0 -0.0165227 -1.06623 +0 -0.0811111 -0.937449 +0 -0.114156 -0.729124 +0 -0.0878704 -0.520803 +0 -0.0630863 -0.312481 +0 -0.0570781 -0.104161 +0 -0.054825 0.104161 +0 -0.0811111 0.312484 +0 -0.0600822 0.520803 +0 -0.00976336 0.729125 +0 0.0660905 0.863592 +0.0746084 0.118662 0.93555 +0.137338 -0.0170108 1.04355 +0.307861 -0.0378221 1.08663 +0.308383 0.0346975 -1.20591 +0.0746084 -0.0120165 -1.1666 +0.0746084 -0.0660905 -1.06623 +0.0746084 -0.144197 -0.937449 +0.0746084 -0.193765 -0.729124 +0.0746084 -0.171235 -0.520803 +0.0746084 -0.147202 -0.312481 +0.0746084 -0.138189 -0.104161 +0.0746084 -0.129177 0.104161 +0.0746084 -0.151708 0.312484 +0.0746084 -0.120164 0.520803 +0.0746084 -0.054074 0.729125 +0.0746084 0.0390537 0.863592 +0.167455 0.0991359 0.93555 +0.137338 -0.0950344 1.04355 +0.307861 -0.139211 1.08663 +0.308383 0.00833648 -1.14823 +0.167455 -0.0510698 -1.1666 +0.167455 -0.115658 -1.06623 +0.167455 -0.207284 -0.937449 +0.167455 -0.273374 -0.729124 +0.167455 -0.254599 -0.520803 +0.167455 -0.231317 -0.312481 +0.0746084 -0.2193 -0.104161 +0.0746084 -0.203529 0.104161 +0.167455 -0.222304 0.312484 +0.167455 -0.180247 0.520803 +0.167455 -0.0983849 0.729125 +0.167455 0.0120165 0.863592 +0.167455 0.0796091 0.93555 +0.137338 -0.173058 1.04355 +0.307861 -0.2406 1.08663 +0.308383 -0.0180247 -1.12778 +0.308383 -0.0720987 -1.06301 +0.308383 -0.139691 -0.972671 +0.308383 -0.234321 -0.856768 +0.308383 -0.308673 -0.669279 +0.308383 -0.295154 -0.481792 +0.308383 -0.274876 -0.294301 +0.308383 -0.261358 -0.106812 +0.308383 -0.24108 0.0806772 +0.308383 -0.254599 0.268166 +0.308383 -0.207284 0.455657 +0.308383 -0.119413 0.643146 +0.308383 -0.00450611 0.764159 +0.308383 0.0630864 0.828929 +0.308383 -0.0744983 0.92949 +0.307861 -0.341988 1.08663 +numsurf 150 +SURF 0x30 +mat 0 +refs 4 +1 0.0701625 0.74359 +17 0.0449697 0.663818 +16 0.0332349 0.667521 +0 0.0420975 0.700855 +SURF 0x30 +mat 0 +refs 4 +2 0.109306 0.777778 +18 0.0687675 0.745489 +17 0.0449697 0.663818 +1 0.0701625 0.74359 +SURF 0x30 +mat 0 +refs 4 +3 0.159527 0.811966 +19 0.124569 0.766382 +18 0.0687675 0.745489 +2 0.109306 0.777778 +SURF 0x30 +mat 0 +refs 4 +4 0.240768 0.905983 +20 0.214837 0.849953 +19 0.124569 0.766382 +3 0.159527 0.811966 +SURF 0x30 +mat 0 +refs 4 +5 0.322009 0.965812 +21 0.322009 0.87094 +20 0.214837 0.849953 +4 0.240768 0.905983 +SURF 0x30 +mat 0 +refs 4 +6 0.40325 1 +22 0.395372 0.948718 +21 0.322009 0.87094 +5 0.322009 0.965812 +SURF 0x30 +mat 0 +refs 4 +7 0.48449 0.982906 +23 0.485639 0.933523 +22 0.395372 0.948718 +6 0.40325 1 +SURF 0x30 +mat 0 +refs 4 +8 0.565731 0.931624 +24 0.575907 0.88509 +23 0.485639 0.933523 +7 0.48449 0.982906 +SURF 0x30 +mat 0 +refs 4 +9 0.646972 0.871795 +25 0.666174 0.823362 +24 0.575907 0.88509 +8 0.565731 0.931624 +SURF 0x30 +mat 0 +refs 4 +10 0.728213 0.811966 +26 0.756442 0.77018 +25 0.666174 0.823362 +9 0.646972 0.871795 +SURF 0x30 +mat 0 +refs 4 +11 0.809453 0.74359 +27 0.846709 0.71415 +26 0.756442 0.77018 +10 0.728213 0.811966 +SURF 0x30 +mat 0 +refs 4 +12 0.861891 0.692308 +28 0.904973 0.679012 +27 0.846709 0.71415 +11 0.809453 0.74359 +SURF 0x30 +mat 0 +refs 4 +13 0.889956 0.692308 +29 0.936156 0.688509 +28 0.904973 0.679012 +12 0.861891 0.692308 +SURF 0x30 +mat 0 +refs 4 +14 0.93353 0.823547 +30 0.984572 0.800418 +29 0.936156 0.688509 +13 0.889956 0.692308 +SURF 0x30 +mat 0 +refs 4 +15 1 0.966239 +31 1 0.890085 +30 0.984572 0.800418 +14 0.93353 0.823547 +SURF 0x30 +mat 0 +refs 4 +17 0.0449697 0.663818 +33 0.0252749 0.671415 +32 0.0221565 0.634188 +16 0.0332349 0.667521 +SURF 0x30 +mat 0 +refs 4 +18 0.0687675 0.745489 +34 0.0687675 0.682811 +33 0.0252749 0.671415 +17 0.0449697 0.663818 +SURF 0x30 +mat 0 +refs 4 +19 0.124569 0.766382 +35 0.124569 0.68661 +34 0.0687675 0.682811 +18 0.0687675 0.745489 +SURF 0x30 +mat 0 +refs 4 +20 0.214837 0.849953 +36 0.214837 0.749288 +35 0.124569 0.68661 +19 0.124569 0.766382 +SURF 0x30 +mat 0 +refs 4 +21 0.322009 0.87094 +37 0.305104 0.806268 +36 0.214837 0.749288 +20 0.214837 0.849953 +SURF 0x30 +mat 0 +refs 4 +22 0.395372 0.948718 +38 0.395372 0.842355 +37 0.305104 0.806268 +21 0.322009 0.87094 +SURF 0x30 +mat 0 +refs 4 +23 0.485639 0.933523 +39 0.485639 0.830959 +38 0.395372 0.842355 +22 0.395372 0.948718 +SURF 0x30 +mat 0 +refs 4 +24 0.575907 0.88509 +40 0.575907 0.791073 +39 0.485639 0.830959 +23 0.485639 0.933523 +SURF 0x30 +mat 0 +refs 4 +25 0.666174 0.823362 +41 0.666174 0.734093 +40 0.575907 0.791073 +24 0.575907 0.88509 +SURF 0x30 +mat 0 +refs 4 +26 0.756442 0.77018 +42 0.756442 0.694207 +41 0.666174 0.734093 +25 0.666174 0.823362 +SURF 0x30 +mat 0 +refs 4 +27 0.846709 0.71415 +43 0.846709 0.65812 +42 0.756442 0.694207 +26 0.756442 0.77018 +SURF 0x30 +mat 0 +refs 4 +28 0.904973 0.679012 +44 0.904973 0.644824 +43 0.846709 0.65812 +27 0.846709 0.71415 +SURF 0x30 +mat 0 +refs 4 +29 0.936156 0.688509 +45 0.936156 0.663818 +44 0.904973 0.644824 +28 0.904973 0.679012 +SURF 0x30 +mat 0 +refs 4 +30 0.984572 0.800418 +46 0.984572 0.741814 +45 0.936156 0.663818 +29 0.936156 0.688509 +SURF 0x30 +mat 0 +refs 4 +31 1 0.890085 +47 1 0.813932 +46 0.984572 0.741814 +30 0.984572 0.800418 +SURF 0x30 +mat 0 +refs 4 +33 0.0252749 0.671415 +49 0.0252749 0.622032 +48 0.00664694 0.600855 +32 0.0221565 0.634188 +SURF 0x30 +mat 0 +refs 4 +34 0.0687675 0.682811 +50 0.0687675 0.620133 +49 0.0252749 0.622032 +33 0.0252749 0.671415 +SURF 0x30 +mat 0 +refs 4 +35 0.124569 0.68661 +51 0.124569 0.606838 +50 0.0687675 0.620133 +34 0.0687675 0.682811 +SURF 0x30 +mat 0 +refs 4 +36 0.214837 0.749288 +52 0.214837 0.648623 +51 0.124569 0.606838 +35 0.124569 0.68661 +SURF 0x30 +mat 0 +refs 4 +37 0.305104 0.806268 +53 0.305104 0.700855 +52 0.214837 0.648623 +36 0.214837 0.749288 +SURF 0x30 +mat 0 +refs 4 +38 0.395372 0.842355 +54 0.395372 0.735992 +53 0.305104 0.700855 +37 0.305104 0.806268 +SURF 0x30 +mat 0 +refs 4 +39 0.485639 0.830959 +55 0.485639 0.728395 +54 0.395372 0.735992 +38 0.395372 0.842355 +SURF 0x30 +mat 0 +refs 4 +40 0.575907 0.791073 +56 0.575907 0.697056 +55 0.485639 0.728395 +39 0.485639 0.830959 +SURF 0x30 +mat 0 +refs 4 +41 0.666174 0.734093 +57 0.666174 0.644824 +56 0.575907 0.697056 +40 0.575907 0.791073 +SURF 0x30 +mat 0 +refs 4 +42 0.756442 0.694207 +58 0.756442 0.618234 +57 0.666174 0.644824 +41 0.666174 0.734093 +SURF 0x30 +mat 0 +refs 4 +43 0.846709 0.65812 +59 0.846709 0.602089 +58 0.756442 0.618234 +42 0.756442 0.694207 +SURF 0x30 +mat 0 +refs 4 +44 0.904973 0.644824 +60 0.904973 0.610636 +59 0.846709 0.602089 +43 0.846709 0.65812 +SURF 0x30 +mat 0 +refs 4 +45 0.936156 0.663818 +61 0.936156 0.639126 +60 0.904973 0.610636 +44 0.904973 0.644824 +SURF 0x30 +mat 0 +refs 4 +46 0.984572 0.741814 +62 0.984572 0.68321 +61 0.936156 0.639126 +45 0.936156 0.663818 +SURF 0x30 +mat 0 +refs 4 +47 1 0.813932 +63 1 0.737778 +62 0.984572 0.68321 +46 0.984572 0.741814 +SURF 0x30 +mat 0 +refs 4 +49 0.0252749 0.622032 +65 0.0252749 0.57265 +64 0 0.567521 +48 0.00664694 0.600855 +SURF 0x30 +mat 0 +refs 4 +50 0.0687675 0.620133 +66 0.0687675 0.557455 +65 0.0252749 0.57265 +49 0.0252749 0.622032 +SURF 0x30 +mat 0 +refs 4 +51 0.124569 0.606838 +67 0.124569 0.527066 +66 0.0687675 0.557455 +50 0.0687675 0.620133 +SURF 0x30 +mat 0 +refs 4 +52 0.214837 0.648623 +68 0.214837 0.547958 +67 0.124569 0.527066 +51 0.124569 0.606838 +SURF 0x30 +mat 0 +refs 4 +53 0.305104 0.700855 +69 0.305104 0.595442 +68 0.214837 0.547958 +52 0.214837 0.648623 +SURF 0x30 +mat 0 +refs 4 +54 0.395372 0.735992 +70 0.395372 0.62963 +69 0.305104 0.595442 +53 0.305104 0.700855 +SURF 0x30 +mat 0 +refs 4 +55 0.485639 0.728395 +71 0.485639 0.625831 +70 0.395372 0.62963 +54 0.395372 0.735992 +SURF 0x30 +mat 0 +refs 4 +56 0.575907 0.697056 +72 0.575907 0.603039 +71 0.485639 0.625831 +55 0.485639 0.728395 +SURF 0x30 +mat 0 +refs 4 +57 0.666174 0.644824 +73 0.666174 0.555556 +72 0.575907 0.603039 +56 0.575907 0.697056 +SURF 0x30 +mat 0 +refs 4 +58 0.756442 0.618234 +74 0.756442 0.54226 +73 0.666174 0.555556 +57 0.666174 0.644824 +SURF 0x30 +mat 0 +refs 4 +59 0.846709 0.602089 +75 0.846709 0.546059 +74 0.756442 0.54226 +58 0.756442 0.618234 +SURF 0x30 +mat 0 +refs 4 +60 0.904973 0.610636 +76 0.904973 0.576448 +75 0.846709 0.546059 +59 0.846709 0.602089 +SURF 0x30 +mat 0 +refs 4 +61 0.936156 0.639126 +77 0.936156 0.614435 +76 0.904973 0.576448 +60 0.904973 0.610636 +SURF 0x30 +mat 0 +refs 4 +62 0.984572 0.68321 +78 0.984572 0.624606 +77 0.936156 0.614435 +61 0.936156 0.639126 +SURF 0x30 +mat 0 +refs 4 +63 1 0.737778 +79 1 0.661624 +78 0.984572 0.624606 +62 0.984572 0.68321 +SURF 0x30 +mat 0 +refs 4 +65 0.0252749 0.57265 +81 0.0252749 0.523267 +80 0 0.534188 +64 0 0.567521 +SURF 0x30 +mat 0 +refs 4 +66 0.0687675 0.557455 +82 0.0687675 0.494777 +81 0.0252749 0.523267 +65 0.0252749 0.57265 +SURF 0x30 +mat 0 +refs 4 +67 0.124569 0.527066 +83 0.124569 0.447293 +82 0.0687675 0.494777 +66 0.0687675 0.557455 +SURF 0x30 +mat 0 +refs 4 +68 0.214837 0.547958 +84 0.214837 0.447293 +83 0.124569 0.447293 +67 0.124569 0.527066 +SURF 0x30 +mat 0 +refs 4 +69 0.305104 0.595442 +85 0.305104 0.490029 +84 0.214837 0.447293 +68 0.214837 0.547958 +SURF 0x30 +mat 0 +refs 4 +70 0.395372 0.62963 +86 0.395372 0.523267 +85 0.305104 0.490029 +69 0.305104 0.595442 +SURF 0x30 +mat 0 +refs 4 +71 0.485639 0.625831 +87 0.485639 0.523267 +86 0.395372 0.523267 +70 0.395372 0.62963 +SURF 0x30 +mat 0 +refs 4 +72 0.575907 0.603039 +88 0.575907 0.509022 +87 0.485639 0.523267 +71 0.485639 0.625831 +SURF 0x30 +mat 0 +refs 4 +73 0.666174 0.555556 +89 0.666174 0.466287 +88 0.575907 0.509022 +72 0.575907 0.603039 +SURF 0x30 +mat 0 +refs 4 +74 0.756442 0.54226 +90 0.756442 0.466287 +89 0.666174 0.466287 +73 0.666174 0.555556 +SURF 0x30 +mat 0 +refs 4 +75 0.846709 0.546059 +91 0.846709 0.490028 +90 0.756442 0.466287 +74 0.756442 0.54226 +SURF 0x30 +mat 0 +refs 4 +76 0.904973 0.576448 +92 0.904973 0.54226 +91 0.846709 0.490028 +75 0.846709 0.546059 +SURF 0x30 +mat 0 +refs 4 +77 0.936156 0.614435 +93 0.936156 0.589744 +92 0.904973 0.54226 +76 0.904973 0.576448 +SURF 0x30 +mat 0 +refs 4 +78 0.984572 0.624606 +94 0.984572 0.566002 +93 0.936156 0.589744 +77 0.936156 0.614435 +SURF 0x30 +mat 0 +refs 4 +79 1 0.661624 +95 1 0.58547 +94 0.984572 0.566002 +78 0.984572 0.624606 +SURF 0x30 +mat 0 +refs 4 +81 0.0252749 0.523267 +97 0.0252749 0.473884 +96 0 0.500855 +80 0 0.534188 +SURF 0x30 +mat 0 +refs 4 +82 0.0687675 0.494777 +98 0.0687675 0.432099 +97 0.0252749 0.473884 +81 0.0252749 0.523267 +SURF 0x30 +mat 0 +refs 4 +83 0.124569 0.447293 +99 0.124569 0.367521 +98 0.0687675 0.432099 +82 0.0687675 0.494777 +SURF 0x30 +mat 0 +refs 4 +84 0.214837 0.447293 +100 0.214837 0.346629 +99 0.124569 0.367521 +83 0.124569 0.447293 +SURF 0x30 +mat 0 +refs 4 +85 0.305104 0.490029 +101 0.305104 0.384615 +100 0.214837 0.346629 +84 0.214837 0.447293 +SURF 0x30 +mat 0 +refs 4 +86 0.395372 0.523267 +102 0.395372 0.416904 +101 0.305104 0.384615 +85 0.305104 0.490029 +SURF 0x30 +mat 0 +refs 4 +87 0.485639 0.523267 +103 0.485639 0.420703 +102 0.395372 0.416904 +86 0.395372 0.523267 +SURF 0x30 +mat 0 +refs 4 +88 0.575907 0.509022 +104 0.575907 0.415005 +103 0.485639 0.420703 +87 0.485639 0.523267 +SURF 0x30 +mat 0 +refs 4 +89 0.666174 0.466287 +105 0.666174 0.377018 +104 0.575907 0.415005 +88 0.575907 0.509022 +SURF 0x30 +mat 0 +refs 4 +90 0.756442 0.466287 +106 0.756442 0.390313 +105 0.666174 0.377018 +89 0.666174 0.466287 +SURF 0x30 +mat 0 +refs 4 +91 0.846709 0.490028 +107 0.846709 0.433998 +106 0.756442 0.390313 +90 0.756442 0.466287 +SURF 0x30 +mat 0 +refs 4 +92 0.904973 0.54226 +108 0.904973 0.508072 +107 0.846709 0.433998 +91 0.846709 0.490028 +SURF 0x30 +mat 0 +refs 4 +93 0.936156 0.589744 +109 0.936156 0.565052 +108 0.904973 0.508072 +92 0.904973 0.54226 +SURF 0x30 +mat 0 +refs 4 +94 0.984572 0.566002 +110 0.984572 0.507398 +109 0.936156 0.565052 +93 0.936156 0.589744 +SURF 0x30 +mat 0 +refs 4 +95 1 0.58547 +111 1 0.509316 +110 0.984572 0.507398 +94 0.984572 0.566002 +SURF 0x30 +mat 0 +refs 4 +97 0.0252749 0.473884 +113 0.0252749 0.424501 +112 0.00664694 0.467521 +96 0 0.500855 +SURF 0x30 +mat 0 +refs 4 +98 0.0687675 0.432099 +114 0.0687675 0.369421 +113 0.0252749 0.424501 +97 0.0252749 0.473884 +SURF 0x30 +mat 0 +refs 4 +99 0.124569 0.367521 +115 0.124569 0.287749 +114 0.0687675 0.369421 +98 0.0687675 0.432099 +SURF 0x30 +mat 0 +refs 4 +100 0.214837 0.346629 +116 0.214837 0.245964 +115 0.124569 0.287749 +99 0.124569 0.367521 +SURF 0x30 +mat 0 +refs 4 +101 0.305104 0.384615 +117 0.305104 0.279202 +116 0.214837 0.245964 +100 0.214837 0.346629 +SURF 0x30 +mat 0 +refs 4 +102 0.395372 0.416904 +118 0.395372 0.310541 +117 0.305104 0.279202 +101 0.305104 0.384615 +SURF 0x30 +mat 0 +refs 4 +103 0.485639 0.420703 +119 0.485639 0.318139 +118 0.395372 0.310541 +102 0.395372 0.416904 +SURF 0x30 +mat 0 +refs 4 +104 0.575907 0.415005 +120 0.575907 0.320988 +119 0.485639 0.318139 +103 0.485639 0.420703 +SURF 0x30 +mat 0 +refs 4 +105 0.666174 0.377018 +121 0.666174 0.287749 +120 0.575907 0.320988 +104 0.575907 0.415005 +SURF 0x30 +mat 0 +refs 4 +106 0.756442 0.390313 +122 0.756442 0.31434 +121 0.666174 0.287749 +105 0.666174 0.377018 +SURF 0x30 +mat 0 +refs 4 +107 0.846709 0.433998 +123 0.846709 0.377968 +122 0.756442 0.31434 +106 0.756442 0.390313 +SURF 0x30 +mat 0 +refs 4 +108 0.904973 0.508072 +124 0.904973 0.473884 +123 0.846709 0.377968 +107 0.846709 0.433998 +SURF 0x30 +mat 0 +refs 4 +109 0.936156 0.565052 +125 0.936156 0.540361 +124 0.904973 0.473884 +108 0.904973 0.508072 +SURF 0x30 +mat 0 +refs 4 +110 0.984572 0.507398 +126 0.984572 0.448794 +125 0.936156 0.540361 +109 0.936156 0.565052 +SURF 0x30 +mat 0 +refs 4 +111 1 0.509316 +127 1 0.433162 +126 0.984572 0.448794 +110 0.984572 0.507398 +SURF 0x30 +mat 0 +refs 4 +113 0.0252749 0.424501 +129 0.0252749 0.375119 +128 0.0221565 0.434188 +112 0.00664694 0.467521 +SURF 0x30 +mat 0 +refs 4 +114 0.0687675 0.369421 +130 0.0687675 0.306743 +129 0.0252749 0.375119 +113 0.0252749 0.424501 +SURF 0x30 +mat 0 +refs 4 +115 0.124569 0.287749 +131 0.124569 0.207977 +130 0.0687675 0.306743 +114 0.0687675 0.369421 +SURF 0x30 +mat 0 +refs 4 +116 0.214837 0.245964 +132 0.214837 0.145299 +131 0.124569 0.207977 +115 0.124569 0.287749 +SURF 0x30 +mat 0 +refs 4 +117 0.305104 0.279202 +133 0.305104 0.173789 +132 0.214837 0.145299 +116 0.214837 0.245964 +SURF 0x30 +mat 0 +refs 4 +118 0.395372 0.310541 +134 0.395372 0.204179 +133 0.305104 0.173789 +117 0.305104 0.279202 +SURF 0x30 +mat 0 +refs 4 +119 0.485639 0.318139 +135 0.485639 0.215575 +134 0.395372 0.204179 +118 0.395372 0.310541 +SURF 0x30 +mat 0 +refs 4 +120 0.575907 0.320988 +136 0.575907 0.226971 +135 0.485639 0.215575 +119 0.485639 0.318139 +SURF 0x30 +mat 0 +refs 4 +121 0.666174 0.287749 +137 0.666174 0.198481 +136 0.575907 0.226971 +120 0.575907 0.320988 +SURF 0x30 +mat 0 +refs 4 +122 0.756442 0.31434 +138 0.756442 0.238367 +137 0.666174 0.198481 +121 0.666174 0.287749 +SURF 0x30 +mat 0 +refs 4 +123 0.846709 0.377968 +139 0.846709 0.321937 +138 0.756442 0.238367 +122 0.756442 0.31434 +SURF 0x30 +mat 0 +refs 4 +124 0.904973 0.473884 +140 0.904973 0.439696 +139 0.846709 0.321937 +123 0.846709 0.377968 +SURF 0x30 +mat 0 +refs 4 +125 0.936156 0.540361 +141 0.936156 0.515669 +140 0.904973 0.439696 +124 0.904973 0.473884 +SURF 0x30 +mat 0 +refs 4 +126 0.984572 0.448794 +142 0.984572 0.39019 +141 0.936156 0.515669 +125 0.936156 0.540361 +SURF 0x30 +mat 0 +refs 4 +127 1 0.433162 +143 1 0.357008 +142 0.984572 0.39019 +126 0.984572 0.448794 +SURF 0x30 +mat 0 +refs 4 +129 0.0252749 0.375119 +145 0.0252749 0.325736 +144 0.0332349 0.400855 +128 0.0221565 0.434188 +SURF 0x30 +mat 0 +refs 4 +130 0.0687675 0.306743 +146 0.0687675 0.244065 +145 0.0252749 0.325736 +129 0.0252749 0.375119 +SURF 0x30 +mat 0 +refs 4 +131 0.124569 0.207977 +147 0.124569 0.128205 +146 0.0687675 0.244065 +130 0.0687675 0.306743 +SURF 0x30 +mat 0 +refs 4 +132 0.214837 0.145299 +148 0.214837 0.0446344 +147 0.124569 0.128205 +131 0.124569 0.207977 +SURF 0x30 +mat 0 +refs 4 +133 0.305104 0.173789 +149 0.305104 0.068376 +148 0.214837 0.0446344 +132 0.214837 0.145299 +SURF 0x30 +mat 0 +refs 4 +134 0.395372 0.204179 +150 0.395372 0.0978157 +149 0.305104 0.068376 +133 0.305104 0.173789 +SURF 0x30 +mat 0 +refs 4 +135 0.485639 0.215575 +151 0.485639 0.11301 +150 0.395372 0.0978157 +134 0.395372 0.204179 +SURF 0x30 +mat 0 +refs 4 +136 0.575907 0.226971 +152 0.575907 0.132953 +151 0.485639 0.11301 +135 0.485639 0.215575 +SURF 0x30 +mat 0 +refs 4 +137 0.666174 0.198481 +153 0.666174 0.109212 +152 0.575907 0.132953 +136 0.575907 0.226971 +SURF 0x30 +mat 0 +refs 4 +138 0.756442 0.238367 +154 0.756442 0.162393 +153 0.666174 0.109212 +137 0.666174 0.198481 +SURF 0x30 +mat 0 +refs 4 +139 0.846709 0.321937 +155 0.846709 0.265907 +154 0.756442 0.162393 +138 0.756442 0.238367 +SURF 0x30 +mat 0 +refs 4 +140 0.904973 0.439696 +156 0.904973 0.405508 +155 0.846709 0.265907 +139 0.846709 0.321937 +SURF 0x30 +mat 0 +refs 4 +141 0.936156 0.515669 +157 0.936156 0.490978 +156 0.904973 0.405508 +140 0.904973 0.439696 +SURF 0x30 +mat 0 +refs 4 +142 0.984572 0.39019 +158 0.984572 0.331586 +157 0.936156 0.490978 +141 0.936156 0.515669 +SURF 0x30 +mat 0 +refs 4 +143 1 0.357008 +159 1 0.280855 +158 0.984572 0.331586 +142 0.984572 0.39019 +SURF 0x30 +mat 0 +refs 4 +145 0.0252749 0.325736 +161 0.0701625 0.299145 +160 0.0420975 0.367521 +144 0.0332349 0.400855 +SURF 0x30 +mat 0 +refs 4 +146 0.0687675 0.244065 +162 0.109306 0.213675 +161 0.0701625 0.299145 +145 0.0252749 0.325736 +SURF 0x30 +mat 0 +refs 4 +147 0.124569 0.128205 +163 0.159527 0.0940171 +162 0.109306 0.213675 +146 0.0687675 0.244065 +SURF 0x30 +mat 0 +refs 4 +148 0.214837 0.0446344 +164 0.240768 0 +163 0.159527 0.0940171 +147 0.124569 0.128205 +SURF 0x30 +mat 0 +refs 4 +149 0.305104 0.068376 +165 0.322009 0.017094 +164 0.240768 0 +148 0.214837 0.0446344 +SURF 0x30 +mat 0 +refs 4 +150 0.395372 0.0978157 +166 0.40325 0.042735 +165 0.322009 0.017094 +149 0.305104 0.068376 +SURF 0x30 +mat 0 +refs 4 +151 0.485639 0.11301 +167 0.48449 0.059829 +166 0.40325 0.042735 +150 0.395372 0.0978157 +SURF 0x30 +mat 0 +refs 4 +152 0.575907 0.132953 +168 0.565731 0.0854701 +167 0.48449 0.059829 +151 0.485639 0.11301 +SURF 0x30 +mat 0 +refs 4 +153 0.666174 0.109212 +169 0.646972 0.0683761 +168 0.565731 0.0854701 +152 0.575907 0.132953 +SURF 0x30 +mat 0 +refs 4 +154 0.756442 0.162393 +170 0.728213 0.128205 +169 0.646972 0.0683761 +153 0.666174 0.109212 +SURF 0x30 +mat 0 +refs 4 +155 0.846709 0.265907 +171 0.809453 0.239316 +170 0.728213 0.128205 +154 0.756442 0.162393 +SURF 0x30 +mat 0 +refs 4 +156 0.904973 0.405508 +172 0.861891 0.384615 +171 0.809453 0.239316 +155 0.846709 0.265907 +SURF 0x30 +mat 0 +refs 4 +157 0.936156 0.490978 +173 0.889956 0.470085 +172 0.861891 0.384615 +156 0.904973 0.405508 +SURF 0x30 +mat 0 +refs 4 +158 0.984572 0.331586 +174 0.93353 0.296111 +173 0.889956 0.470085 +157 0.936156 0.490978 +SURF 0x30 +mat 0 +refs 4 +159 1 0.280855 +175 1 0.204701 +174 0.93353 0.296111 +158 0.984572 0.331586 +kids 0 diff --git a/demos/simon/astropong/data/bluepaddle2.ac b/demos/simon/astropong/data/bluepaddle2.ac new file mode 100644 index 0000000..1e8ba6b --- /dev/null +++ b/demos/simon/astropong/data/bluepaddle2.ac @@ -0,0 +1,12964 @@ +AC3Db +MATERIAL "ac3dmat0" rgb 0 0 0 amb 0 0 0 emis 0 0 0 spec 0 0 0 shi 128 trans 0.22 +MATERIAL "ac3dmat8" rgb 0.478 0.502 1 amb 0.2 0.2 1 emis 0 0 0 spec 0.502 0.502 1 shi 10 trans 0.22 +OBJECT world +kids 6 +OBJECT poly +name "noname" +loc -0.579657 -0.559209 0.472312 +texture "Penguin_foot.rgba" +numvert 7 +0.207207 -0.401817 -0.0439492 +-0.359605 -0.121745 0.0313728 +0.0993607 -0.405379 -0.0423633 +-0.115831 0.281581 0.116401 +0.195658 -0.318231 -0.134527 +0.359605 -0.221492 -0.00689447 +0.319485 0.405379 0.134527 +numsurf 7 +SURF 0x10 +mat 1 +refs 3 +0 0.546875 -0.0625 +1 -0.078125 0.65625 +2 0.40625 0 +SURF 0x10 +mat 1 +refs 3 +3 0.390625 1.03125 +1 -0.078125 0.65625 +0 0.546875 -0.0625 +SURF 0x10 +mat 1 +refs 3 +2 0.40625 0 +1 -0.078125 0.65625 +4 0.546875 -0.0625 +SURF 0x10 +mat 1 +refs 3 +4 0.546875 -0.0625 +1 -0.078125 0.65625 +3 0.390625 1.03125 +SURF 0x10 +mat 1 +refs 3 +5 0.8125 0.078125 +3 0.390625 1.03125 +0 0.546875 -0.0625 +SURF 0x10 +mat 1 +refs 3 +6 1 0.921875 +3 0.390625 1.03125 +5 0.8125 0.078125 +SURF 0x10 +mat 1 +refs 3 +4 0.546875 -0.0625 +3 0.390625 1.03125 +5 0.8125 0.078125 +kids 0 +OBJECT poly +name "noname" +loc 0.637738 -0.580393 0.435709 +texture "Penguin_foot.rgba" +numvert 7 +-0.241534 -0.39612 -0.0439492 +0.362262 -0.225299 0.0313728 +0.18785 0.217057 0.116401 +-0.362262 -0.190307 -0.00689435 +-0.220704 0.419607 0.134527 +-0.216556 -0.315947 -0.134527 +-0.135902 -0.419607 -0.0423632 +numsurf 7 +SURF 0x10 +mat 1 +refs 3 +0 0.546875 -0.0625 +1 -0.078125 0.65625 +2 0.390625 1.03125 +SURF 0x10 +mat 1 +refs 3 +0 0.546875 -0.0625 +2 0.390625 1.03125 +3 0.8125 0.078125 +SURF 0x10 +mat 1 +refs 3 +3 0.8125 0.078125 +2 0.390625 1.03125 +4 1 0.921875 +SURF 0x10 +mat 1 +refs 3 +2 0.390625 1.03125 +1 -0.078125 0.65625 +5 0.546875 -0.0625 +SURF 0x10 +mat 1 +refs 3 +3 0.8125 0.078125 +2 0.390625 1.03125 +5 0.546875 -0.0625 +SURF 0x10 +mat 1 +refs 3 +6 0.40625 0 +1 -0.078125 0.65625 +0 0.546875 -0.0625 +SURF 0x10 +mat 1 +refs 3 +5 0.546875 -0.0625 +1 -0.078125 0.65625 +6 0.40625 0 +kids 0 +OBJECT poly +name "NoName" +loc -0.736599 -0.206815 -0.0147271 +texture "Penguin_body.rgb" +numvert 7 +-0.105532 -2.98023e-07 -0.1153 +0.104039 0.226555 0.132028 +0.105475 0.226555 -0.132028 +-0.105532 -2.98023e-07 0.107671 +0.261965 0.280667 0.132028 +0.263401 0.280667 -0.132028 +-0.263401 -0.280667 5.96046e-08 +numsurf 5 +SURF 0x20 +mat 1 +refs 3 +0 0 0 +1 0.1 0 +2 0.1 0.1 +SURF 0x20 +mat 1 +refs 3 +1 0 0 +0 0.1 0 +3 0.1 0.1 +SURF 0x20 +mat 1 +refs 3 +2 0 0 +4 0.1 0 +5 0.1 0.1 +SURF 0x20 +mat 1 +refs 3 +4 0 0 +2 0.1 0 +1 0.1 0.1 +SURF 0x20 +mat 1 +refs 3 +6 0 0 +3 0.1 0 +0 0.1 0.1 +kids 0 +OBJECT poly +name "NoName" +loc 0.713164 -0.207557 -0.0213335 +texture "Penguin_body.rgb" +numvert 7 +-0.105476 0.226552 0.132028 +-0.261967 0.280666 -0.132028 +-0.263402 0.280666 0.132028 +-0.10404 0.226552 -0.132028 +0.105533 1.01328e-06 0.1153 +0.105533 1.01328e-06 -0.107671 +0.263403 -0.280666 0 +numsurf 5 +SURF 0x20 +mat 1 +refs 3 +0 0 0 +1 0.1 0 +2 0.1 0.1 +SURF 0x20 +mat 1 +refs 3 +1 0 0 +0 0.1 0 +3 0.1 0.1 +SURF 0x20 +mat 1 +refs 3 +4 0 0 +3 0.1 0 +0 0.1 0.1 +SURF 0x20 +mat 1 +refs 3 +3 0 0 +4 0.1 0 +5 0.1 0.1 +SURF 0x20 +mat 1 +refs 3 +6 0 0 +5 0.1 0 +4 0.1 0.1 +kids 0 +OBJECT poly +name "NoName" +loc 0.0335439 0.365538 0.353373 +texture "Penguin_beak.rgb" +numvert 34 +-0.214757 -0.0291858 -0.14112 +0.213031 0.0598249 -0.1649 +-0.214008 -0.0299873 -0.141178 +-0.105266 -0.157939 0.135966 +0.0156704 -0.142478 0.16279 +-0.108276 -0.134234 0.139683 +0.0104105 -0.17073 0.125129 +0.109332 -0.138958 0.122135 +0.117104 -0.117466 0.123031 +-0.214563 -0.0305809 -0.137304 +-0.171346 -0.0904827 -0.154263 +-0.00316417 -0.17894 -0.180282 +0.214878 -0.0267632 -0.174816 +0.21408 0.0594168 -0.167228 +0.112322 -0.100851 0.127501 +0.0290792 0.0442213 0.145975 +0.0173992 -0.0725842 0.180282 +0.113502 -0.0373889 0.139437 +-0.0556487 0.0217681 0.152538 +-0.106616 -0.071278 0.156485 +0.169051 0.0891278 -0.165485 +0.214404 0.0605794 -0.163949 +-0.000404596 0.17894 -0.15236 +-0.16986 0.0891278 -0.139236 +-0.214878 -0.0287287 -0.140497 +-0.107834 -0.134771 0.139034 +0.112077 -0.101252 0.126935 +0.213527 0.0586234 -0.167518 +-0.214438 -0.0310948 -0.137892 +0.0159515 -0.142599 0.162206 +0.213846 0.0598249 -0.164296 +0.0177337 -0.0732908 0.180239 +-0.106115 -0.0716867 0.156429 +0.113312 -0.0380067 0.139434 +numsurf 40 +SURF 0x10 +mat 1 +refs 3 +0 0 0 +1 0 0 +2 0 0 +SURF 0x10 +mat 1 +refs 3 +3 0.179286 0.236445 +4 0.328444 0.27802 +5 0.171928 0.303494 +SURF 0x10 +mat 1 +refs 3 +6 0.325093 0.178494 +4 0.328444 0.27802 +3 0.179286 0.236445 +SURF 0x10 +mat 1 +refs 3 +7 0.649815 0.29012 +4 0.328444 0.27802 +6 0.325093 0.178494 +SURF 0x10 +mat 1 +refs 3 +8 0.763049 0.377184 +4 0.328444 0.27802 +7 0.649815 0.29012 +SURF 0x10 +mat 1 +refs 3 +5 0.171928 0.303494 +9 0 0.419942 +3 0.179286 0.236445 +SURF 0x10 +mat 1 +refs 3 +10 0.0978096 0.25 +3 0.179286 0.236445 +9 0 0.419942 +SURF 0x10 +mat 1 +refs 3 +3 0.179286 0.236445 +10 0.0978096 0.25 +6 0.325093 0.178494 +SURF 0x10 +mat 1 +refs 3 +11 0.469834 0 +6 0.325093 0.178494 +10 0.0978096 0.25 +SURF 0x10 +mat 1 +refs 3 +6 0.325093 0.178494 +11 0.469834 0 +7 0.649815 0.29012 +SURF 0x10 +mat 1 +refs 3 +12 1 0.43559 +7 0.649815 0.29012 +11 0.469834 0 +SURF 0x10 +mat 1 +refs 3 +7 0.649815 0.29012 +12 1 0.43559 +8 0.763049 0.377184 +SURF 0x10 +mat 1 +refs 3 +8 0.763049 0.377184 +13 0.984563 0.672853 +14 0.655176 0.397835 +SURF 0x10 +mat 1 +refs 3 +13 0.984563 0.672853 +8 0.763049 0.377184 +12 1 0.43559 +SURF 0x10 +mat 1 +refs 3 +14 0.655176 0.397835 +4 0.328444 0.27802 +8 0.763049 0.377184 +SURF 0x10 +mat 1 +refs 3 +15 0.469834 0.625 +16 0.328444 0.27802 +17 0.655176 0.397835 +SURF 0x10 +mat 1 +refs 3 +18 0.283822 0.5625 +16 0.328444 0.27802 +15 0.469834 0.625 +SURF 0x10 +mat 1 +refs 3 +19 0.171928 0.303494 +16 0.328444 0.27802 +18 0.283822 0.5625 +SURF 0x10 +mat 1 +refs 3 +20 0.841857 0.75 +17 0.655176 0.397835 +21 0.984563 0.672853 +SURF 0x10 +mat 1 +refs 3 +17 0.655176 0.397835 +20 0.841857 0.75 +15 0.469834 0.625 +SURF 0x10 +mat 1 +refs 3 +22 0.469834 1 +15 0.469834 0.625 +20 0.841857 0.75 +SURF 0x10 +mat 1 +refs 3 +15 0.469834 0.625 +22 0.469834 1 +18 0.283822 0.5625 +SURF 0x10 +mat 1 +refs 3 +23 0.0978096 0.75 +18 0.283822 0.5625 +22 0.469834 1 +SURF 0x10 +mat 1 +refs 3 +18 0.283822 0.5625 +23 0.0978096 0.75 +19 0.171928 0.303494 +SURF 0x10 +mat 1 +refs 3 +24 0 0.419942 +19 0.171928 0.303494 +23 0.0978096 0.75 +SURF 0x10 +mat 1 +refs 3 +25 0 0 +26 0 0 +27 0 0 +SURF 0x10 +mat 1 +refs 3 +28 0 0 +25 0 0 +27 0 0 +SURF 0x10 +mat 1 +refs 3 +29 0 0 +28 0 0 +27 0 0 +SURF 0x10 +mat 1 +refs 3 +26 0 0 +29 0 0 +27 0 0 +SURF 0x10 +mat 1 +refs 3 +25 0 0 +28 0 0 +29 0 0 +SURF 0x10 +mat 1 +refs 3 +26 0 0 +25 0 0 +29 0 0 +SURF 0x10 +mat 1 +refs 3 +1 0 0 +30 0 0 +31 0 0 +SURF 0x10 +mat 1 +refs 3 +1 0 0 +31 0 0 +2 0 0 +SURF 0x10 +mat 1 +refs 3 +32 0 0 +0 0 0 +2 0 0 +SURF 0x10 +mat 1 +refs 3 +31 0 0 +32 0 0 +2 0 0 +SURF 0x10 +mat 1 +refs 3 +30 0 0 +1 0 0 +32 0 0 +SURF 0x10 +mat 1 +refs 3 +33 0 0 +30 0 0 +32 0 0 +SURF 0x10 +mat 1 +refs 3 +31 0 0 +33 0 0 +32 0 0 +SURF 0x10 +mat 1 +refs 3 +1 0 0 +0 0 0 +32 0 0 +SURF 0x10 +mat 1 +refs 3 +30 0 0 +33 0 0 +31 0 0 +kids 0 +OBJECT poly +name "line" +loc 0.0202649 0.00977969 -0.119476 +texture "Penguin_body2.rgb" +texoff -0.01 0 +numvert 1627 +-0.0370831 0.99022 0.0537628 +-0.0370378 0.99022 0.0548956 +-0.0972236 0.980316 0.0587064 +-0.0974223 0.980316 0.0537628 +-0.148151 0.960511 0.0619308 +-0.148481 0.960511 0.0537628 +-0.263891 0.896146 0.0692588 +-0.264515 0.896146 0.0537628 +-0.296297 0.851587 0.0713108 +-0.297007 0.851587 0.0537628 +-0.324077 0.757518 0.0730696 +-0.324854 0.757518 0.0537628 +-0.347225 0.36143 0.0745352 +-0.348061 0.36143 0.0537628 +-0.375004 0.267359 0.076294 +-0.375912 0.267359 0.0537628 +-0.472223 0.108924 0.0824496 +-0.473384 0.108924 0.0537628 +-0.558498 -0.049511 0.0879116 +-0.559877 -0.049511 0.0537628 +-0.616077 -0.222799 0.0938816 +-0.617649 -0.222799 0.0537628 +-0.670095 -0.376283 0.0973988 +-0.671808 -0.376283 0.0537628 +-0.66109 -0.50006 0.0968128 +-0.66278 -0.50006 0.0537628 +-0.643084 -0.643644 0.0956404 +-0.644729 -0.643644 0.0537628 +-0.58907 -0.782273 0.0921224 +-0.590575 -0.782273 0.0537628 +-0.449527 -0.881297 0.0830356 +-0.450675 -0.881297 0.0537628 +-0.318989 -0.950611 0.0745352 +-0.319802 -0.950611 0.0537628 +-0.125428 -0.990221 0.0619308 +-0.125749 -0.990221 0.0537628 +-0.00839078 -0.990221 0.0543092 +-0.00841343 -0.990221 0.0537628 +-0.0369022 0.99022 0.0560228 +-0.0966271 0.980316 0.0636244 +-0.147161 0.960511 0.0700568 +-0.26202 0.896146 0.084676 +-0.294178 0.851587 0.0887692 +-0.321745 0.757518 0.0922776 +-0.344713 0.36143 0.0952016 +-0.37228 0.267359 0.09871 +-0.468757 0.108924 0.11099 +-0.554369 -0.049511 0.121887 +-0.611364 -0.222799 0.133796 +-0.664967 -0.376283 0.140813 +-0.656034 -0.50006 0.139643 +-0.638168 -0.643644 0.137304 +-0.584561 -0.782273 0.130287 +-0.446088 -0.881297 0.11216 +-0.316549 -0.950611 0.0952016 +-0.12447 -0.990221 0.0700568 +-0.0083276 -0.990221 0.0548532 +-0.0366718 0.99022 0.0571384 +-0.095633 0.980316 0.0684924 +-0.145521 0.960511 0.0781 +-0.258907 0.896146 0.0999356 +-0.290658 0.851587 0.106049 +-0.317868 0.757518 0.11129 +-0.340546 0.36143 0.115657 +-0.367757 0.267359 0.120897 +-0.463001 0.108924 0.139239 +-0.547519 -0.049511 0.155515 +-0.603534 -0.222799 0.173302 +-0.656454 -0.376283 0.183783 +-0.647634 -0.50006 0.182036 +-0.629994 -0.643644 0.178542 +-0.577078 -0.782273 0.168062 +-0.440377 -0.881297 0.140986 +-0.312492 -0.950611 0.115657 +-0.122875 -0.990221 0.0781 +-0.00822353 -0.990221 0.0553916 +-0.0363555 0.99022 0.0582364 +-0.0942504 0.980316 0.0732856 +-0.143239 0.960511 0.0860192 +-0.254578 0.896146 0.11496 +-0.285751 0.851587 0.123063 +-0.312473 0.757518 0.130009 +-0.33474 0.36143 0.135797 +-0.361458 0.267359 0.142742 +-0.454981 0.108924 0.167052 +-0.537971 -0.049511 0.188624 +-0.592631 -0.222799 0.212199 +-0.644593 -0.376283 0.226091 +-0.635931 -0.50006 0.223776 +-0.618612 -0.643644 0.219145 +-0.56665 -0.782273 0.205254 +-0.43242 -0.881297 0.169368 +-0.306848 -0.950611 0.135797 +-0.120656 -0.990221 0.0860192 +-0.00807452 -0.990221 0.0559212 +-0.0359533 0.99022 0.059312 +-0.0924882 0.980316 0.0779792 +-0.140325 0.960511 0.0937744 +-0.249043 0.896146 0.129672 +-0.279489 0.851587 0.139724 +-0.305578 0.757518 0.148339 +-0.327326 0.36143 0.155519 +-0.353415 0.267359 0.164134 +-0.444742 0.108924 0.194288 +-0.52578 -0.049511 0.221046 +-0.578709 -0.222799 0.250289 +-0.629447 -0.376283 0.26752 +-0.620993 -0.50006 0.264648 +-0.604076 -0.643644 0.258905 +-0.553338 -0.782273 0.241674 +-0.422258 -0.881297 0.19716 +-0.299636 -0.950611 0.155519 +-0.117819 -0.990221 0.0937744 +-0.00788474 -0.990221 0.0564404 +-0.0354608 0.99022 0.0603596 +-0.090351 0.980316 0.0825492 +-0.136792 0.960511 0.101325 +-0.242343 0.896146 0.143998 +-0.271898 0.851587 0.155946 +-0.297228 0.757518 0.166188 +-0.318338 0.36143 0.174722 +-0.343673 0.267359 0.184964 +-0.432334 0.108924 0.220808 +-0.51101 -0.049511 0.252616 +-0.561833 -0.222799 0.287378 +-0.611098 -0.376283 0.30786 +-0.602888 -0.50006 0.304447 +-0.586468 -0.643644 0.297619 +-0.537203 -0.782273 0.277136 +-0.40995 -0.881297 0.224222 +-0.290902 -0.950611 0.174722 +-0.114385 -0.990221 0.101325 +-0.00765431 -0.990221 0.0569456 +-0.0348871 0.99022 0.0613732 +-0.0878478 0.980316 0.0869728 +-0.132657 0.960511 0.108634 +-0.234503 0.896146 0.157864 +-0.263019 0.851587 0.171648 +-0.287459 0.757518 0.183463 +-0.307828 0.36143 0.193309 +-0.332273 0.267359 0.205124 +-0.417821 0.108924 0.246477 +-0.493731 -0.049511 0.283172 +-0.542101 -0.222799 0.323276 +-0.589631 -0.376283 0.346906 +-0.58171 -0.50006 0.342968 +-0.565863 -0.643644 0.335091 +-0.518334 -0.782273 0.31146 +-0.39555 -0.881297 0.250416 +-0.280682 -0.950611 0.193309 +-0.110368 -0.990221 0.108634 +-0.00738323 -0.990221 0.0574348 +-0.0342363 0.99022 0.062348 +-0.0849967 0.980316 0.0912268 +-0.127949 0.960511 0.115663 +-0.225566 0.896146 0.171199 +-0.252898 0.851587 0.186749 +-0.276326 0.757518 0.200078 +-0.29585 0.36143 0.211185 +-0.319278 0.267359 0.224514 +-0.401275 0.108924 0.271164 +-0.474035 -0.049511 0.31256 +-0.519599 -0.222799 0.3578 +-0.565159 -0.376283 0.384458 +-0.557568 -0.50006 0.380015 +-0.542381 -0.643644 0.371129 +-0.496822 -0.782273 0.344472 +-0.379134 -0.881297 0.275607 +-0.269033 -0.950611 0.211185 +-0.105786 -0.990221 0.115663 +-0.00708055 -0.990221 0.0579052 +-0.0335044 0.99022 0.0632792 +-0.0818112 0.980316 0.09529 +-0.12268 0.960511 0.122376 +-0.215575 0.896146 0.183936 +-0.241583 0.851587 0.201172 +-0.263878 0.757518 0.215947 +-0.282457 0.36143 0.228258 +-0.304751 0.267359 0.243033 +-0.38278 0.108924 0.294743 +-0.452021 -0.049511 0.340628 +-0.494454 -0.222799 0.390776 +-0.537808 -0.376283 0.420324 +-0.530583 -0.50006 0.4154 +-0.516133 -0.643644 0.405552 +-0.472779 -0.782273 0.376001 +-0.360785 -0.881297 0.299668 +-0.256015 -0.950611 0.228258 +-0.100667 -0.990221 0.122376 +-0.00673711 -0.990221 0.0583544 +-0.0327002 0.99022 0.064162 +-0.0783048 0.980316 0.0991416 +-0.116888 0.960511 0.12874 +-0.204582 0.896146 0.196009 +-0.22914 0.851587 0.214845 +-0.250187 0.757518 0.230989 +-0.267723 0.36143 0.244443 +-0.28877 0.267359 0.260588 +-0.362434 0.108924 0.317094 +-0.427802 -0.049511 0.367235 +-0.466788 -0.222799 0.422032 +-0.507716 -0.376283 0.454324 +-0.500897 -0.50006 0.44894 +-0.487252 -0.643644 0.43818 +-0.446328 -0.782273 0.405888 +-0.340596 -0.881297 0.322475 +-0.241692 -0.950611 0.244443 +-0.0950366 -0.990221 0.12874 +-0.00635743 -0.990221 0.0587804 +-0.0318282 0.99022 0.0649912 +-0.0744958 0.980316 0.102762 +-0.110598 0.960511 0.134722 +-0.192649 0.896146 0.207358 +-0.21562 0.851587 0.227696 +-0.235316 0.757518 0.245129 +-0.251723 0.36143 0.259656 +-0.271419 0.267359 0.277089 +-0.340339 0.108924 0.338103 +-0.4015 -0.049511 0.392244 +-0.436744 -0.222799 0.451416 +-0.475038 -0.376283 0.48628 +-0.468658 -0.50006 0.480468 +-0.455893 -0.643644 0.468848 +-0.4176 -0.782273 0.433984 +-0.318677 -0.881297 0.343914 +-0.226135 -0.950611 0.259656 +-0.0889187 -0.990221 0.134722 +-0.00595093 -0.990221 0.0591804 +-0.0308927 0.99022 0.065764 +-0.0704066 0.980316 0.106133 +-0.103839 0.960511 0.140291 +-0.17983 0.896146 0.217924 +-0.201107 0.851587 0.239661 +-0.219344 0.757518 0.258293 +-0.234539 0.36143 0.27382 +-0.252776 0.267359 0.292452 +-0.316608 0.108924 0.357663 +-0.373247 -0.049511 0.415528 +-0.404474 -0.222799 0.478768 +-0.439939 -0.376283 0.516032 +-0.434029 -0.50006 0.509824 +-0.422208 -0.643644 0.4974 +-0.386743 -0.782273 0.460136 +-0.295127 -0.881297 0.363874 +-0.209426 -0.950611 0.27382 +-0.0823488 -0.990221 0.140291 +-0.00550807 -0.990221 0.0595532 +-0.0298941 0.99022 0.0664752 +-0.0660553 0.980316 0.109237 +-0.0966542 0.960511 0.14542 +-0.166189 0.896146 0.227654 +-0.185663 0.851587 0.250679 +-0.20235 0.757518 0.270415 +-0.216258 0.36143 0.286862 +-0.232949 0.267359 0.306598 +-0.291359 0.108924 0.375674 +-0.343194 -0.049511 0.436972 +-0.370142 -0.222799 0.50396 +-0.402598 -0.376283 0.543432 +-0.39719 -0.50006 0.536852 +-0.386373 -0.643644 0.523696 +-0.353917 -0.782273 0.484224 +-0.270081 -0.881297 0.382253 +-0.19165 -0.950611 0.286862 +-0.0753587 -0.990221 0.14542 +-0.00504267 -0.990221 0.0598964 +-0.0288413 0.99022 0.0671216 +-0.0614646 0.980316 0.112058 +-0.0890678 0.960511 0.150081 +-0.151802 0.896146 0.236497 +-0.16937 0.851587 0.260694 +-0.184425 0.757518 0.281433 +-0.196973 0.36143 0.298716 +-0.212028 0.267359 0.319456 +-0.264722 0.108924 0.392046 +-0.311484 -0.049511 0.45646 +-0.333927 -0.222799 0.526856 +-0.363207 -0.376283 0.568332 +-0.358327 -0.50006 0.56142 +-0.348567 -0.643644 0.547596 +-0.319287 -0.782273 0.506116 +-0.243653 -0.881297 0.398959 +-0.172899 -0.950611 0.298716 +-0.0679846 -0.990221 0.150081 +-0.00455022 -0.990221 0.0602084 +-0.0277432 0.99022 0.0677 +-0.0566615 0.980316 0.114582 +-0.0811288 0.960511 0.154252 +-0.136737 0.896146 0.244409 +-0.152308 0.851587 0.269653 +-0.165655 0.757518 0.291291 +-0.17678 0.36143 0.309323 +-0.190127 0.267359 0.33096 +-0.236839 0.108924 0.406692 +-0.278291 -0.049511 0.473896 +-0.296008 -0.222799 0.54734 +-0.321962 -0.376283 0.590616 +-0.317638 -0.50006 0.5834 +-0.308985 -0.643644 0.568976 +-0.283031 -0.782273 0.5257 +-0.215986 -0.881297 0.413904 +-0.153266 -0.950611 0.309323 +-0.0602626 -0.990221 0.154252 +-0.00403059 -0.990221 0.0604876 +-0.0265958 0.99022 0.0682076 +-0.051664 0.980316 0.116796 +-0.0728736 0.960511 0.15791 +-0.121076 0.896146 0.25135 +-0.134573 0.851587 0.277513 +-0.14614 0.757518 0.299939 +-0.155783 0.36143 0.318627 +-0.16735 0.267359 0.341052 +-0.207844 0.108924 0.41954 +-0.24377 -0.049511 0.489192 +-0.25658 -0.222799 0.565308 +-0.279078 -0.376283 0.61016 +-0.275327 -0.50006 0.602684 +-0.267831 -0.643644 0.587732 +-0.245334 -0.782273 0.542884 +-0.187217 -0.881297 0.427016 +-0.132851 -0.950611 0.318627 +-0.0522379 -0.990221 0.15791 +-0.00349283 -0.990221 0.0607324 +-0.0254118 0.99022 0.0686412 +-0.0464994 0.980316 0.118689 +-0.0643427 0.960511 0.161038 +-0.104896 0.896146 0.257284 +-0.116246 0.851587 0.284233 +-0.125979 0.757518 0.307332 +-0.13409 0.36143 0.326581 +-0.143822 0.267359 0.34968 +-0.177887 0.108924 0.430528 +-0.208111 -0.049511 0.502268 +-0.215846 -0.222799 0.580672 +-0.23477 -0.376283 0.626868 +-0.231616 -0.50006 0.619168 +-0.225308 -0.643644 0.603768 +-0.206385 -0.782273 0.557572 +-0.157495 -0.881297 0.438228 +-0.111759 -0.950611 0.326581 +-0.0439465 -0.990221 0.161038 +-0.00294161 -0.990221 0.0609416 +-0.0242009 0.99022 0.0689992 +-0.0411994 0.980316 0.120252 +-0.0555816 0.960511 0.163619 +-0.0882725 0.896146 0.26218 +-0.0974269 0.851587 0.289778 +-0.105275 0.757518 0.313433 +-0.111814 0.36143 0.333145 +-0.119658 0.267359 0.3568 +-0.147121 0.108924 0.439592 +-0.171484 -0.049511 0.513056 +-0.17401 -0.222799 0.593348 +-0.189269 -0.376283 0.640656 +-0.186725 -0.50006 0.632772 +-0.181642 -0.643644 0.617004 +-0.166383 -0.782273 0.569692 +-0.126968 -0.881297 0.447476 +-0.090098 -0.950611 0.333145 +-0.0354293 -0.990221 0.163619 +-0.00237226 -0.990221 0.0611144 +-0.0229583 0.99022 0.0692796 +-0.0357861 0.980316 0.121475 +-0.046635 0.960511 0.16564 +-0.0713012 0.896146 0.266015 +-0.0782099 0.851587 0.29412 +-0.0841291 0.757518 0.31821 +-0.0890633 0.36143 0.338286 +-0.0949824 0.267359 0.362376 +-0.115699 0.108924 0.446692 +-0.134085 -0.049511 0.521508 +-0.131293 -0.222799 0.603276 +-0.142801 -0.376283 0.651456 +-0.140885 -0.50006 0.643428 +-0.137045 -0.643644 0.627368 +-0.125536 -0.782273 0.579188 +-0.0957958 -0.881297 0.45472 +-0.0679802 -0.950611 0.338286 +-0.0267311 -0.990221 0.16564 +-0.00178945 -0.990221 0.0612496 +-0.0216978 0.99022 0.0694808 +-0.0302873 0.980316 0.122353 +-0.0375529 0.960511 0.167091 +-0.0540633 0.896146 0.268768 +-0.0586902 0.851587 0.297238 +-0.0626529 0.757518 0.32164 +-0.0659558 0.36143 0.341976 +-0.0699185 0.267359 0.366378 +-0.0837902 0.108924 0.451788 +-0.0960985 -0.049511 0.527576 +-0.0879021 -0.222799 0.610404 +-0.095606 -0.376283 0.659208 +-0.0943227 -0.50006 0.651076 +-0.0917517 -0.643644 0.634808 +-0.0840478 -0.782273 0.586 +-0.064135 -0.881297 0.45992 +-0.0455099 -0.950611 0.341976 +-0.0178932 -0.990221 0.167091 +-0.00119746 -0.990221 0.0613468 +-0.0204235 0.99022 0.069602 +-0.0247295 0.980316 0.122882 +-0.0283715 0.960511 0.167965 +-0.0366492 0.896146 0.270426 +-0.0389672 0.851587 0.299115 +-0.0409554 0.757518 0.323706 +-0.0426091 0.36143 0.344198 +-0.0445973 0.267359 0.368788 +-0.0515512 0.108924 0.454856 +-0.0577187 -0.049511 0.531228 +-0.044064 -0.222799 0.614696 +-0.0479273 -0.376283 0.663876 +-0.0472812 -0.50006 0.65568 +-0.0459934 -0.643644 0.639284 +-0.0421301 -0.782273 0.590104 +-0.0321489 -0.881297 0.463052 +-0.0228137 -0.950611 0.344198 +-0.00896931 -0.990221 0.167965 +-0.000600934 -0.990221 0.0614052 +-0.0191448 0.99022 0.0696424 +-0.0191448 0.980316 0.123058 +-0.0191448 0.960511 0.168256 +-0.0191448 0.896146 0.270979 +-0.0191448 0.851587 0.299742 +-0.0191448 0.757518 0.324395 +-0.0191448 0.36143 0.34494 +-0.0191448 0.267359 0.369593 +-0.0191448 0.108924 0.45588 +-0.0191448 -0.049511 0.532448 +0 -0.222799 0.616128 +0 -0.376283 0.665436 +0 -0.50006 0.657216 +0 -0.643644 0.64078 +0 -0.782273 0.591476 +0 -0.881297 0.4641 +0 -0.950611 0.34494 +0 -0.990221 0.168256 +0 -0.990221 0.0614248 +-0.0178661 0.99022 0.069602 +-0.0135599 0.980316 0.122882 +-0.00991809 0.960511 0.167965 +-0.00164032 0.896146 0.270426 +0.000677705 0.851587 0.299115 +0.00266576 0.757518 0.323706 +0.00431955 0.36143 0.344198 +0.00630772 0.267359 0.368788 +0.0132616 0.108924 0.454856 +0.0194292 -0.049511 0.531228 +0.0440639 -0.222799 0.614696 +0.047927 -0.376283 0.663876 +0.0472809 -0.50006 0.65568 +0.0459932 -0.643644 0.639284 +0.0421299 -0.782273 0.590104 +0.0321531 -0.881297 0.463052 +0.0228137 -0.950611 0.344198 +0.0089736 -0.990221 0.167965 +0.000600815 -0.990221 0.0614052 +-0.0165918 0.99022 0.0694808 +-0.00800681 0.980316 0.122353 +-0.000741124 0.960511 0.167091 +0.0157738 0.896146 0.268768 +0.0203961 0.851587 0.297238 +0.0243634 0.757518 0.32164 +0.0276664 0.36143 0.341976 +0.031629 0.267359 0.366378 +0.0455006 0.108924 0.451788 +0.057809 -0.049511 0.527576 +0.0879018 -0.222799 0.610404 +0.0956103 -0.376283 0.659208 +0.0943226 -0.50006 0.651076 +0.091756 -0.643644 0.634808 +0.0840474 -0.782273 0.586 +0.0641394 -0.881297 0.45992 +0.0455141 -0.950611 0.341976 +0.0178975 -0.990221 0.167091 +0.00119734 -0.990221 0.0613468 +-0.0153311 0.99022 0.0692796 +-0.00250793 0.980316 0.121475 +0.00834548 0.960511 0.16564 +0.0330116 0.896146 0.266015 +0.0399159 0.851587 0.29412 +0.0458395 0.757518 0.31821 +0.0507691 0.36143 0.338286 +0.0566884 0.267359 0.362376 +0.0774099 0.108924 0.446692 +0.0957955 -0.049511 0.521508 +0.131292 -0.222799 0.603276 +0.142806 -0.376283 0.651456 +0.140885 -0.50006 0.643428 +0.137049 -0.643644 0.627368 +0.125536 -0.782273 0.579188 +0.0958 -0.881297 0.45472 +0.0679799 -0.950611 0.338286 +0.0267311 -0.990221 0.16564 +0.00178921 -0.990221 0.0612496 +-0.0140932 0.99022 0.0689992 +0.00290978 0.980316 0.120252 +0.0172921 0.960511 0.163619 +0.0499829 0.896146 0.26218 +0.0591373 0.851587 0.289778 +0.0669814 0.757518 0.313433 +0.0735196 0.36143 0.333145 +0.0813682 0.267359 0.3568 +0.108827 0.108924 0.439592 +0.133195 -0.049511 0.51306 +0.174014 -0.222799 0.593348 +0.189269 -0.376283 0.640656 +0.186729 -0.50006 0.632772 +0.181641 -0.643644 0.617004 +0.166383 -0.782273 0.569692 +0.126973 -0.881297 0.447476 +0.0900978 -0.950611 0.333145 +0.0354291 -0.990221 0.163619 +0.00237215 -0.990221 0.0611144 +-0.0128776 0.99022 0.0686412 +0.00820994 0.980316 0.118689 +0.0260534 0.960511 0.161038 +0.0666019 0.896146 0.257284 +0.0779567 0.851587 0.284233 +0.0876895 0.757518 0.307332 +0.0958 0.36143 0.326581 +0.105533 0.267359 0.34968 +0.139593 0.108924 0.430528 +0.169821 -0.049511 0.502268 +0.215846 -0.222799 0.580672 +0.234774 -0.376283 0.626868 +0.23162 -0.50006 0.619168 +0.225312 -0.643644 0.603768 +0.206384 -0.782273 0.557572 +0.157495 -0.881297 0.438228 +0.111759 -0.950611 0.326581 +0.0439464 -0.990221 0.161038 +0.00294149 -0.990221 0.0609416 +-0.0116938 0.99022 0.0682076 +0.01337 0.980316 0.116796 +0.0345796 0.960511 0.15791 +0.0827869 0.896146 0.25135 +0.0962834 0.851587 0.277513 +0.107851 0.757518 0.299939 +0.117493 0.36143 0.318627 +0.12906 0.267359 0.341052 +0.16955 0.108924 0.41954 +0.205481 -0.049511 0.489192 +0.256585 -0.222799 0.565308 +0.279077 -0.376283 0.61016 +0.275332 -0.50006 0.602684 +0.267831 -0.643644 0.587732 +0.245334 -0.782273 0.542884 +0.187217 -0.881297 0.427016 +0.132851 -0.950611 0.318627 +0.0522376 -0.990221 0.15791 +0.00349724 -0.990221 0.0607324 +-0.0105507 0.99022 0.0677 +0.0183674 0.980316 0.114582 +0.0428392 0.960511 0.154252 +0.0984478 0.896146 0.244409 +0.114019 0.851587 0.269653 +0.127366 0.757518 0.291291 +0.138486 0.36143 0.309323 +0.151833 0.267359 0.33096 +0.19855 0.108924 0.406692 +0.239997 -0.049511 0.473896 +0.296008 -0.222799 0.54734 +0.321962 -0.376283 0.590616 +0.317638 -0.50006 0.5834 +0.308985 -0.643644 0.568976 +0.283031 -0.782273 0.5257 +0.215986 -0.881297 0.413904 +0.153266 -0.950611 0.309323 +0.060267 -0.990221 0.154252 +0.00403488 -0.990221 0.0604876 +-0.00944829 0.99022 0.0671216 +0.0231749 0.980316 0.112058 +0.0507783 0.960511 0.150081 +0.113512 0.896146 0.236497 +0.131076 0.851587 0.260694 +0.146136 0.757518 0.281433 +0.158679 0.36143 0.298716 +0.173739 0.267359 0.319456 +0.226433 0.108924 0.392046 +0.273194 -0.049511 0.45646 +0.333927 -0.222799 0.526856 +0.363206 -0.376283 0.568336 +0.358326 -0.50006 0.56142 +0.348567 -0.643644 0.547596 +0.319292 -0.782273 0.506116 +0.243653 -0.881297 0.398959 +0.172898 -0.950611 0.298716 +0.0679845 -0.990221 0.150081 +0.00454998 -0.990221 0.0602084 +-0.00839531 0.99022 0.0664752 +0.027766 0.980316 0.109237 +0.0583601 0.960511 0.14542 +0.127899 0.896146 0.227654 +0.147369 0.851587 0.250679 +0.16406 0.757518 0.270415 +0.177968 0.36143 0.286862 +0.194655 0.267359 0.306598 +0.253069 0.108924 0.375675 +0.3049 -0.049511 0.436972 +0.370147 -0.222799 0.50396 +0.402598 -0.376283 0.543432 +0.397189 -0.50006 0.536852 +0.386372 -0.643644 0.523696 +0.353921 -0.782273 0.484224 +0.270081 -0.881297 0.382253 +0.19165 -0.950611 0.286862 +0.0753586 -0.990221 0.14542 +0.00504255 -0.990221 0.0598964 +-0.00739682 0.99022 0.065764 +0.0321171 0.980316 0.106133 +0.065549 0.960511 0.140291 +0.14154 0.896146 0.217924 +0.162813 0.851587 0.239661 +0.18105 0.757518 0.258293 +0.19625 0.36143 0.27382 +0.214486 0.267359 0.292452 +0.278318 0.108924 0.357663 +0.334957 -0.049511 0.415528 +0.404478 -0.222799 0.478768 +0.439939 -0.376283 0.516032 +0.434029 -0.50006 0.509824 +0.422208 -0.643644 0.4974 +0.386743 -0.782273 0.46014 +0.295131 -0.881297 0.363874 +0.209425 -0.950611 0.27382 +0.0823486 -0.990221 0.140292 +0.00551236 -0.990221 0.0595532 +-0.00646138 0.99022 0.0649916 +0.0362062 0.980316 0.102762 +0.0723085 0.960511 0.134722 +0.154359 0.896146 0.207358 +0.177331 0.851587 0.227696 +0.197022 0.757518 0.245129 +0.213433 0.36143 0.259656 +0.233125 0.267359 0.277089 +0.302049 0.108924 0.338103 +0.363206 -0.049511 0.392244 +0.436749 -0.222799 0.451416 +0.475038 -0.376283 0.48628 +0.468658 -0.50006 0.480468 +0.455893 -0.643644 0.468848 +0.4176 -0.782273 0.433984 +0.318677 -0.881297 0.343914 +0.226135 -0.950611 0.259656 +0.0889184 -0.990221 0.134722 +0.00595081 -0.990221 0.0591804 +-0.00558937 0.99022 0.064162 +0.0400108 0.980316 0.0991416 +0.0785983 0.960511 0.12874 +0.166292 0.896146 0.196009 +0.190846 0.851587 0.214845 +0.211892 0.757518 0.230989 +0.229433 0.36143 0.244443 +0.25048 0.267359 0.260588 +0.324144 0.108924 0.317094 +0.389508 -0.049511 0.367235 +0.466792 -0.222799 0.422032 +0.50772 -0.376283 0.454324 +0.500897 -0.50006 0.44894 +0.487256 -0.643644 0.43818 +0.446328 -0.782273 0.405888 +0.3406 -0.881297 0.322476 +0.241692 -0.950611 0.244443 +0.0950364 -0.990221 0.12874 +0.00636184 -0.990221 0.0587804 +-0.00478506 0.99022 0.0632792 +0.043517 0.980316 0.09529 +0.0843909 0.960511 0.122376 +0.177286 0.896146 0.183936 +0.203294 0.851587 0.201172 +0.225588 0.757518 0.215947 +0.244168 0.36143 0.228259 +0.266462 0.267359 0.243033 +0.344491 0.108924 0.294743 +0.413732 -0.049511 0.340628 +0.494458 -0.222799 0.390776 +0.537808 -0.376283 0.420324 +0.530583 -0.50006 0.4154 +0.516133 -0.643644 0.405552 +0.472779 -0.782273 0.376001 +0.360785 -0.881297 0.299668 +0.256015 -0.950611 0.228258 +0.100666 -0.990221 0.122376 +0.00673699 -0.990221 0.0583544 +-0.00405312 0.99022 0.062348 +0.046707 0.980316 0.0912268 +0.089655 0.960511 0.115663 +0.187271 0.896146 0.171199 +0.214604 0.851587 0.186749 +0.238036 0.757518 0.200078 +0.257556 0.36143 0.211185 +0.280984 0.267359 0.224514 +0.362985 0.108924 0.271164 +0.435746 -0.049511 0.31256 +0.519603 -0.222799 0.3578 +0.565158 -0.376283 0.384458 +0.557567 -0.50006 0.380015 +0.542381 -0.643644 0.371129 +0.496826 -0.782273 0.344472 +0.379134 -0.881297 0.275607 +0.269037 -0.950611 0.211185 +0.10579 -0.990221 0.115663 +0.00708044 -0.990221 0.0579052 +-0.00340247 0.99022 0.0613732 +0.0495582 0.980316 0.0869728 +0.0943677 0.960511 0.108634 +0.196209 0.896146 0.157864 +0.224725 0.851587 0.171648 +0.24917 0.757518 0.183463 +0.269539 0.36143 0.193309 +0.293979 0.267359 0.205124 +0.379527 0.108924 0.246477 +0.455441 -0.049511 0.283172 +0.542101 -0.222799 0.323276 +0.58963 -0.376283 0.346906 +0.581709 -0.50006 0.342968 +0.565868 -0.643644 0.335091 +0.518334 -0.782273 0.311461 +0.395549 -0.881297 0.250416 +0.280686 -0.950611 0.193309 +0.110368 -0.990221 0.108634 +0.00738752 -0.990221 0.0574348 +-0.0028286 0.99022 0.0603596 +0.0520568 0.980316 0.0825492 +0.098502 0.960511 0.101325 +0.204053 0.896146 0.143998 +0.233604 0.851587 0.155946 +0.258939 0.757518 0.166188 +0.280049 0.36143 0.174722 +0.305379 0.267359 0.184964 +0.394045 0.108924 0.220808 +0.47272 -0.049511 0.252616 +0.561837 -0.222799 0.287378 +0.611097 -0.376283 0.307861 +0.602888 -0.50006 0.304447 +0.586467 -0.643644 0.297619 +0.537207 -0.782273 0.277136 +0.40995 -0.881297 0.224222 +0.290902 -0.950611 0.174722 +0.114384 -0.990221 0.101325 +0.00765419 -0.990221 0.0569456 +-0.00234056 0.99022 0.0593124 +0.0541942 0.980316 0.0779792 +0.102036 0.960511 0.0937744 +0.210754 0.896146 0.129672 +0.241195 0.851587 0.139724 +0.267289 0.757518 0.148339 +0.289032 0.36143 0.155519 +0.315126 0.267359 0.164134 +0.406452 0.108924 0.194288 +0.487491 -0.049511 0.221046 +0.578709 -0.222799 0.250289 +0.629452 -0.376283 0.26752 +0.620993 -0.50006 0.264648 +0.60408 -0.643644 0.258905 +0.553338 -0.782273 0.241674 +0.422263 -0.881297 0.19716 +0.299641 -0.950611 0.155519 +0.117823 -0.990221 0.0937744 +0.0078845 -0.990221 0.0564404 +-0.00193393 0.99022 0.0582368 +0.0559609 0.980316 0.0732856 +0.10495 0.960511 0.0860196 +0.216284 0.896146 0.11496 +0.247462 0.851587 0.123063 +0.274179 0.757518 0.130009 +0.296446 0.36143 0.135797 +0.323168 0.267359 0.142742 +0.416691 0.108924 0.167052 +0.499682 -0.049511 0.188624 +0.592635 -0.222799 0.2122 +0.644593 -0.376283 0.226091 +0.635935 -0.50006 0.223776 +0.618612 -0.643644 0.219145 +0.566654 -0.782273 0.205254 +0.43242 -0.881297 0.169368 +0.306848 -0.950611 0.135797 +0.120656 -0.990221 0.0860196 +0.00807428 -0.990221 0.0559212 +-0.00161767 0.99022 0.0571384 +0.0573435 0.980316 0.0684928 +0.107232 0.960511 0.0781004 +0.220618 0.896146 0.0999356 +0.252364 0.851587 0.10605 +0.279579 0.757518 0.11129 +0.302257 0.36143 0.115657 +0.329467 0.267359 0.120898 +0.424712 0.108924 0.139239 +0.509225 -0.049511 0.155515 +0.603538 -0.222799 0.173302 +0.656454 -0.376283 0.183783 +0.647634 -0.50006 0.182036 +0.629994 -0.643644 0.178543 +0.577078 -0.782273 0.168062 +0.440377 -0.881297 0.140986 +0.312496 -0.950611 0.115657 +0.122874 -0.990221 0.0781 +0.00822353 -0.990221 0.0553916 +-0.00139177 0.99022 0.0560228 +0.0583332 0.980316 0.0636248 +0.108872 0.960511 0.0700568 +0.223726 0.896146 0.084676 +0.255889 0.851587 0.0887692 +0.283451 0.757518 0.092278 +0.306423 0.36143 0.0952016 +0.33399 0.267359 0.0987104 +0.430468 0.108924 0.11099 +0.516079 -0.049511 0.121887 +0.611364 -0.222799 0.133796 +0.664971 -0.376283 0.140813 +0.656033 -0.50006 0.139643 +0.638168 -0.643644 0.137304 +0.584565 -0.782273 0.130287 +0.446088 -0.881297 0.11216 +0.316549 -0.950611 0.0952016 +0.12447 -0.990221 0.0700568 +0.00833189 -0.990221 0.0548532 +-0.0012517 0.99022 0.0548956 +0.0589341 0.980316 0.0587064 +0.109857 0.960511 0.0619308 +0.225601 0.896146 0.0692588 +0.258008 0.851587 0.0713108 +0.285787 0.757518 0.0730696 +0.308935 0.36143 0.0745352 +0.33671 0.267359 0.076294 +0.433934 0.108924 0.0824496 +0.520204 -0.049511 0.087912 +0.616077 -0.222799 0.0938816 +0.670095 -0.376283 0.0973992 +0.661094 -0.50006 0.0968128 +0.643088 -0.643644 0.0956404 +0.58907 -0.782273 0.0921228 +0.449527 -0.881297 0.083036 +0.318989 -0.950611 0.0745352 +0.125432 -0.990221 0.0619308 +0.0083952 -0.990221 0.0543092 +-0.0012064 0.99022 0.0537628 +0.0591328 0.980316 0.0537628 +0.110187 0.960511 0.0537628 +0.226225 0.896146 0.0537628 +0.258717 0.851587 0.0537628 +0.286564 0.757518 0.0537628 +0.309771 0.36143 0.0537628 +0.337623 0.267359 0.0537628 +0.435091 0.108924 0.0537628 +0.521582 -0.049511 0.0537628 +0.617654 -0.222799 0.0537628 +0.671807 -0.376283 0.0537628 +0.662779 -0.50006 0.0537628 +0.644728 -0.643644 0.0537628 +0.590575 -0.782273 0.0537628 +0.450679 -0.881297 0.0537628 +0.319802 -0.950611 0.0537628 +0.125748 -0.990221 0.0537628 +0.00841784 -0.990221 0.0537628 +-0.0012517 0.99022 0.05263 +0.0589341 0.980316 0.0488192 +0.109857 0.960511 0.0455948 +0.225601 0.896146 0.0382668 +0.258008 0.851587 0.0362148 +0.285787 0.757518 0.034456 +0.308935 0.36143 0.0329903 +0.33671 0.267359 0.0312315 +0.433934 0.108924 0.025076 +0.520204 -0.049511 0.019614 +0.616077 -0.222799 0.013644 +0.670095 -0.376283 0.0101268 +0.661094 -0.50006 0.0107127 +0.643088 -0.643644 0.0118852 +0.58907 -0.782273 0.0154028 +0.449527 -0.881297 0.02449 +0.318989 -0.950611 0.0329903 +0.125432 -0.990221 0.0455948 +0.0083952 -0.990221 0.053216 +-0.00139177 0.99022 0.0515028 +0.0583332 0.980316 0.0439012 +0.108872 0.960511 0.0374688 +0.223726 0.896146 0.0228496 +0.255889 0.851587 0.0187564 +0.283451 0.757518 0.0152479 +0.306423 0.36143 0.012324 +0.33399 0.267359 0.00881553 +0.430468 0.108924 -0.00346446 +0.516079 -0.049511 -0.0143592 +0.611364 -0.222799 -0.0262712 +0.664971 -0.376283 -0.0332872 +0.656033 -0.50006 -0.0321193 +0.638168 -0.643644 -0.0297792 +0.584565 -0.782273 -0.0227633 +0.446088 -0.881297 -0.00463402 +0.316549 -0.950611 0.012324 +0.12447 -0.990221 0.0374688 +0.00833189 -0.990221 0.0526724 +-0.00161767 0.99022 0.0503872 +0.0573435 0.980316 0.0390328 +0.107232 0.960511 0.0294256 +0.220618 0.896146 0.00758994 +0.252364 0.851587 0.00147635 +0.279579 0.757518 -0.00376445 +0.302257 0.36143 -0.00813127 +0.329467 0.267359 -0.0133716 +0.424712 0.108924 -0.0317153 +0.509225 -0.049511 -0.0479872 +0.603538 -0.222799 -0.0657752 +0.656454 -0.376283 -0.0762592 +0.647634 -0.50006 -0.0745112 +0.629994 -0.643644 -0.0710152 +0.577078 -0.782273 -0.0605352 +0.440377 -0.881297 -0.0334592 +0.312496 -0.950611 -0.00813127 +0.122874 -0.990221 0.0294251 +0.00822353 -0.990221 0.052134 +-0.00193393 0.99022 0.0492888 +0.0559609 0.980316 0.0342399 +0.10495 0.960511 0.0215064 +0.216284 0.896146 -0.007434 +0.247462 0.851587 -0.0155392 +0.274179 0.757518 -0.0224832 +0.296446 0.36143 -0.0282712 +0.323168 0.267359 -0.0352153 +0.416691 0.108924 -0.0595272 +0.499682 -0.049511 -0.0810992 +0.592635 -0.222799 -0.104675 +0.644593 -0.376283 -0.118563 +0.635935 -0.50006 -0.116251 +0.618612 -0.643644 -0.111619 +0.566654 -0.782273 -0.0977272 +0.43242 -0.881297 -0.0618432 +0.306848 -0.950611 -0.0282712 +0.120656 -0.990221 0.0215064 +0.00807428 -0.990221 0.051604 +-0.00234056 0.99022 0.0482136 +0.0541942 0.980316 0.0295464 +0.102036 0.960511 0.0137511 +0.210754 0.896146 -0.0221472 +0.241195 0.851587 -0.0321993 +0.267289 0.757518 -0.0408152 +0.289032 0.36143 -0.0479912 +0.315126 0.267359 -0.0566072 +0.406452 0.108924 -0.0867632 +0.487491 -0.049511 -0.113519 +0.578709 -0.222799 -0.142763 +0.629452 -0.376283 -0.159995 +0.620993 -0.50006 -0.157123 +0.60408 -0.643644 -0.151379 +0.553338 -0.782273 -0.134147 +0.422263 -0.881297 -0.0896352 +0.299641 -0.950611 -0.0479912 +0.117823 -0.990221 0.0137511 +0.0078845 -0.990221 0.0510852 +-0.0028286 0.99022 0.047166 +0.0520568 0.980316 0.0249764 +0.098502 0.960511 0.00620037 +0.204053 0.896146 -0.0364712 +0.233604 0.851587 -0.0484192 +0.258939 0.757518 -0.0586632 +0.280049 0.36143 -0.0671952 +0.305379 0.267359 -0.0774392 +0.394045 0.108924 -0.113283 +0.47272 -0.049511 -0.145091 +0.561837 -0.222799 -0.179851 +0.611097 -0.376283 -0.200335 +0.602888 -0.50006 -0.196919 +0.586467 -0.643644 -0.190095 +0.537207 -0.782273 -0.169611 +0.40995 -0.881297 -0.116695 +0.290902 -0.950611 -0.0671952 +0.114389 -0.990221 0.00620037 +0.00765419 -0.990221 0.05058 +-0.00340247 0.99022 0.0461524 +0.0495582 0.980316 0.0205528 +0.0943677 0.960511 -0.00110805 +0.196209 0.896146 -0.0503392 +0.224725 0.851587 -0.0641232 +0.24917 0.757518 -0.0759392 +0.269539 0.36143 -0.0857832 +0.293979 0.267359 -0.0975992 +0.379527 0.108924 -0.138951 +0.455441 -0.049511 -0.175647 +0.542101 -0.222799 -0.215751 +0.58963 -0.376283 -0.239379 +0.581709 -0.50006 -0.235443 +0.565868 -0.643644 -0.227567 +0.518338 -0.782273 -0.203935 +0.395549 -0.881297 -0.142891 +0.280686 -0.950611 -0.0857832 +0.110368 -0.990221 -0.00110805 +0.00738752 -0.990221 0.0500908 +-0.00405312 0.99022 0.0451776 +0.046707 0.980316 0.0162988 +0.089655 0.960511 -0.00813723 +0.187271 0.896146 -0.0636752 +0.214604 0.851587 -0.0792232 +0.238036 0.757518 -0.0925512 +0.257556 0.36143 -0.103659 +0.280984 0.267359 -0.116987 +0.362985 0.108924 -0.163639 +0.435746 -0.049511 -0.205035 +0.519603 -0.222799 -0.250275 +0.565158 -0.376283 -0.276931 +0.557567 -0.50006 -0.272491 +0.542381 -0.643644 -0.263603 +0.496826 -0.782273 -0.236947 +0.379134 -0.881297 -0.168083 +0.269037 -0.950611 -0.103659 +0.10579 -0.990221 -0.00813723 +0.00708044 -0.990221 0.0496204 +-0.00478506 0.99022 0.0442464 +0.043517 0.980316 0.0122355 +0.0843909 0.960511 -0.0148512 +0.177286 0.896146 -0.0764112 +0.203294 0.851587 -0.0936472 +0.225588 0.757518 -0.108419 +0.244168 0.36143 -0.120731 +0.266462 0.267359 -0.135507 +0.344491 0.108924 -0.187219 +0.413732 -0.049511 -0.233103 +0.494458 -0.222799 -0.283251 +0.537808 -0.376283 -0.312799 +0.530583 -0.50006 -0.307875 +0.516133 -0.643644 -0.298023 +0.472779 -0.782273 -0.268475 +0.360785 -0.881297 -0.192143 +0.256015 -0.950611 -0.120731 +0.100666 -0.990221 -0.0148512 +0.00673699 -0.990221 0.0491712 +-0.00558937 0.99022 0.0433636 +0.0400108 0.980316 0.00838357 +0.0785983 0.960511 -0.0212152 +0.166292 0.896146 -0.0884832 +0.19085 0.851587 -0.107319 +0.211892 0.757518 -0.123463 +0.229433 0.36143 -0.136919 +0.25048 0.267359 -0.153063 +0.324144 0.108924 -0.209567 +0.389508 -0.049511 -0.259711 +0.466792 -0.222799 -0.314507 +0.50772 -0.376283 -0.346799 +0.500897 -0.50006 -0.341415 +0.487256 -0.643644 -0.330651 +0.446328 -0.782273 -0.298363 +0.3406 -0.881297 -0.214951 +0.241692 -0.950611 -0.136919 +0.0950364 -0.990221 -0.0212152 +0.00636184 -0.990221 0.0487452 +-0.00646138 0.99022 0.042534 +0.0362062 0.980316 0.0047636 +0.0723085 0.960511 -0.0271952 +0.154359 0.896146 -0.0998312 +0.177331 0.851587 -0.120171 +0.197022 0.757518 -0.137603 +0.213433 0.36143 -0.152131 +0.233125 0.267359 -0.169563 +0.302049 0.108924 -0.230579 +0.363206 -0.049511 -0.284719 +0.436749 -0.222799 -0.343891 +0.475038 -0.376283 -0.378755 +0.468658 -0.50006 -0.372943 +0.455893 -0.643644 -0.361323 +0.4176 -0.782273 -0.326455 +0.318677 -0.881297 -0.236387 +0.226135 -0.950611 -0.152131 +0.0889184 -0.990221 -0.0271952 +0.00595081 -0.990221 0.0483452 +-0.00739682 0.99022 0.0417616 +0.0321171 0.980316 0.00139272 +0.065549 0.960511 -0.0327672 +0.14154 0.896146 -0.110399 +0.162813 0.851587 -0.132135 +0.181054 0.757518 -0.150767 +0.19625 0.36143 -0.166295 +0.214486 0.267359 -0.184927 +0.278318 0.108924 -0.250139 +0.334957 -0.049511 -0.308003 +0.404478 -0.222799 -0.371243 +0.439939 -0.376283 -0.408508 +0.434029 -0.50006 -0.4023 +0.422208 -0.643644 -0.389875 +0.386743 -0.782273 -0.352611 +0.295131 -0.881297 -0.256347 +0.209425 -0.950611 -0.166295 +0.0823486 -0.990221 -0.0327672 +0.00551236 -0.990221 0.047972 +-0.00839531 0.99022 0.0410504 +0.027766 0.980316 -0.00171125 +0.0583601 0.960511 -0.0378952 +0.127899 0.896146 -0.120127 +0.147369 0.851587 -0.143155 +0.16406 0.757518 -0.162891 +0.177968 0.36143 -0.179335 +0.194655 0.267359 -0.199071 +0.253069 0.108924 -0.268147 +0.3049 -0.049511 -0.329443 +0.370147 -0.222799 -0.396435 +0.402598 -0.376283 -0.435908 +0.397189 -0.50006 -0.429328 +0.386372 -0.643644 -0.416172 +0.353921 -0.782273 -0.376699 +0.270081 -0.881297 -0.274727 +0.19165 -0.950611 -0.179335 +0.0753586 -0.990221 -0.0378952 +0.00504255 -0.990221 0.0476292 +-0.00944829 0.99022 0.040404 +0.0231749 0.980316 -0.00453246 +0.0507783 0.960511 -0.0425552 +0.113512 0.896146 -0.128971 +0.131076 0.851587 -0.153167 +0.146136 0.757518 -0.173907 +0.158679 0.36143 -0.191191 +0.173739 0.267359 -0.211931 +0.226433 0.108924 -0.284519 +0.273194 -0.049511 -0.348931 +0.333927 -0.222799 -0.419328 +0.363206 -0.376283 -0.460808 +0.358326 -0.50006 -0.453896 +0.348567 -0.643644 -0.440068 +0.319292 -0.782273 -0.398587 +0.243653 -0.881297 -0.291435 +0.172898 -0.950611 -0.191191 +0.0679845 -0.990221 -0.0425552 +0.00454998 -0.990221 0.0473172 +-0.0105507 0.99022 0.0398256 +0.0183674 0.980316 -0.00705647 +0.0428392 0.960511 -0.0467272 +0.0984478 0.896146 -0.136883 +0.114019 0.851587 -0.162127 +0.127366 0.757518 -0.183767 +0.138486 0.36143 -0.201795 +0.151833 0.267359 -0.223435 +0.19855 0.108924 -0.299167 +0.239997 -0.049511 -0.366371 +0.296008 -0.222799 -0.439816 +0.321962 -0.376283 -0.483088 +0.317638 -0.50006 -0.475876 +0.308985 -0.643644 -0.461452 +0.283031 -0.782273 -0.418176 +0.215986 -0.881297 -0.306379 +0.153266 -0.950611 -0.201799 +0.060267 -0.990221 -0.0467272 +0.00403488 -0.990221 0.047038 +-0.0116938 0.99022 0.039318 +0.01337 0.980316 -0.00927085 +0.0345796 0.960511 -0.0503832 +0.0827869 0.896146 -0.143823 +0.0962834 0.851587 -0.169987 +0.107851 0.757518 -0.192411 +0.117493 0.36143 -0.211099 +0.12906 0.267359 -0.233527 +0.16955 0.108924 -0.312015 +0.205481 -0.049511 -0.381663 +0.256585 -0.222799 -0.457784 +0.279077 -0.376283 -0.502636 +0.275332 -0.50006 -0.49516 +0.267831 -0.643644 -0.480208 +0.245334 -0.782273 -0.435356 +0.187217 -0.881297 -0.319491 +0.132851 -0.950611 -0.211099 +0.0522376 -0.990221 -0.0503832 +0.00349724 -0.990221 0.0467932 +-0.0128776 0.99022 0.0388844 +0.00820994 0.980316 -0.0111637 +0.0260534 0.960511 -0.0535112 +0.0666019 0.896146 -0.149759 +0.0779567 0.851587 -0.176707 +0.0876895 0.757518 -0.199807 +0.0958 0.36143 -0.219055 +0.105533 0.267359 -0.242155 +0.139593 0.108924 -0.323003 +0.169821 -0.049511 -0.394743 +0.215846 -0.222799 -0.473148 +0.234774 -0.376283 -0.519344 +0.23162 -0.50006 -0.511644 +0.225312 -0.643644 -0.496244 +0.206384 -0.782273 -0.450048 +-0.103463 -0.887389 -0.665436 +0.111759 -0.950611 -0.219055 +0.0439464 -0.990221 -0.0535112 +0.00294149 -0.990221 0.046584 +-0.0140932 0.99022 0.0385264 +0.00290978 0.980316 -0.0127261 +0.0172921 0.960511 -0.0560912 +0.0499829 0.896146 -0.154655 +0.0591373 0.851587 -0.182251 +0.0669814 0.757518 -0.205907 +0.0735196 0.36143 -0.225619 +0.0813682 0.267359 -0.249275 +0.108827 0.108924 -0.332067 +0.133195 -0.049511 -0.405532 +0.174014 -0.222799 -0.485824 +0.189269 -0.376283 -0.533132 +0.186729 -0.50006 -0.525248 +0.181641 -0.643644 -0.50948 +0.0900978 -0.950611 -0.225619 +0.0354291 -0.990221 -0.0560912 +0.00237215 -0.990221 0.0464112 +-0.0153311 0.99022 0.0382459 +-0.00250793 0.980316 -0.0139512 +0.00834548 0.960511 -0.0581152 +0.0330116 0.896146 -0.158491 +0.0399204 0.851587 -0.186595 +0.0458395 0.757518 -0.210683 +0.0507691 0.36143 -0.230759 +0.0566928 0.267359 -0.254851 +0.0774099 0.108924 -0.339167 +0.0957955 -0.049511 -0.413984 +0.131292 -0.222799 -0.495752 +0.142806 -0.376283 -0.543932 +0.0679799 -0.950611 -0.230759 +0.0267311 -0.990221 -0.0581152 +0.00178921 -0.990221 0.046276 +-0.0165918 0.99022 0.0380448 +-0.00800681 0.980316 -0.0148273 +-0.000741124 0.960511 -0.0595672 +0.0157738 0.896146 -0.161243 +0.0203961 0.851587 -0.189711 +0.0243634 0.757518 -0.214115 +0.0276664 0.36143 -0.234451 +0.031629 0.267359 -0.258851 +0.0455006 0.108924 -0.344263 +0.057809 -0.049511 -0.420052 +0.0879018 -0.222799 -0.50288 +0.0956103 -0.376283 -0.551684 +0.0455141 -0.950611 -0.234451 +0.0178975 -0.990221 -0.0595672 +0.00119734 -0.990221 0.0461788 +-0.0178661 0.99022 0.0379236 +-0.0135599 0.980316 -0.0153552 +-0.00991809 0.960511 -0.0604392 +-0.00164032 0.896146 -0.162899 +0.000677705 0.851587 -0.191591 +0.00266576 0.757518 -0.216179 +0.00431955 0.36143 -0.236671 +0.00630772 0.267359 -0.261263 +0.0132616 0.108924 -0.347331 +0.0194292 -0.049511 -0.423704 +0.0440639 -0.222799 -0.507172 +0.047927 -0.376283 -0.556352 +0.0228137 -0.950611 -0.236671 +0.0089736 -0.990221 -0.0604392 +0.000600815 -0.990221 0.0461204 +-0.0191448 0.99022 0.0378832 +-0.0191448 0.980316 -0.0155312 +-0.0191448 0.960511 -0.0607312 +-0.0191448 0.896146 -0.163455 +-0.0191448 0.851587 -0.192215 +-0.0191448 0.757518 -0.216871 +-0.0191448 0.36143 -0.237415 +-0.0191448 0.267359 -0.262067 +-0.0191448 0.108924 -0.348355 +-0.0191448 -0.049511 -0.424924 +0 -0.222799 -0.508604 +0 -0.376283 -0.557912 +0 -0.950611 -0.237415 +0 -0.990221 -0.0607312 +0 -0.990221 0.0461008 +-0.0204235 0.99022 0.0379236 +-0.0247295 0.980316 -0.0153552 +-0.0283715 0.960511 -0.0604392 +-0.0366492 0.896146 -0.162899 +-0.0389672 0.851587 -0.191591 +-0.0409554 0.757518 -0.216179 +-0.0426091 0.36143 -0.236671 +-0.0445973 0.267359 -0.261263 +-0.0515512 0.108924 -0.347331 +-0.0577187 -0.049511 -0.423704 +-0.044064 -0.222799 -0.507172 +-0.0479273 -0.376283 -0.556352 +-0.0228137 -0.950611 -0.236671 +-0.00896931 -0.990221 -0.0604392 +-0.000600934 -0.990221 0.0461204 +-0.0216978 0.99022 0.0380448 +-0.0302873 0.980316 -0.0148273 +-0.0375529 0.960511 -0.0595672 +-0.0540633 0.896146 -0.161243 +-0.0586902 0.851587 -0.189711 +-0.0626529 0.757518 -0.214115 +-0.0659558 0.36143 -0.234451 +-0.0699185 0.267359 -0.258851 +-0.0837902 0.108924 -0.344263 +-0.0960985 -0.049511 -0.420052 +-0.0879021 -0.222799 -0.50288 +-0.095606 -0.376283 -0.551684 +-0.0455099 -0.950611 -0.234451 +-0.0178932 -0.990221 -0.0595672 +-0.00119746 -0.990221 0.0461788 +-0.0229583 0.99022 0.0382459 +-0.0357861 0.980316 -0.0139512 +-0.046635 0.960511 -0.0581152 +-0.0713012 0.896146 -0.158491 +-0.0782099 0.851587 -0.186595 +-0.0841291 0.757518 -0.210683 +-0.0890633 0.36143 -0.230759 +-0.0949824 0.267359 -0.254851 +-0.115699 0.108924 -0.339167 +-0.134085 -0.049511 -0.413984 +-0.131288 -0.222799 -0.495752 +-0.142801 -0.376283 -0.543932 +-0.0679802 -0.950611 -0.230759 +-0.0267311 -0.990221 -0.0581152 +-0.00178945 -0.990221 0.046276 +-0.0242009 0.99022 0.0385264 +-0.0411994 0.980316 -0.0127261 +-0.0555816 0.960511 -0.0560912 +-0.0882725 0.896146 -0.154655 +-0.0974269 0.851587 -0.182251 +-0.105275 0.757518 -0.205907 +-0.111814 0.36143 -0.225619 +-0.119658 0.267359 -0.249275 +-0.147121 0.108924 -0.332067 +-0.171484 -0.049511 -0.405532 +-0.17401 -0.222799 -0.485824 +-0.189269 -0.376283 -0.533132 +-0.090098 -0.950611 -0.225619 +-0.0354293 -0.990221 -0.0560912 +-0.00237226 -0.990221 0.0464112 +-0.0254118 0.99022 0.0388844 +-0.0464994 0.980316 -0.0111637 +-0.0643427 0.960511 -0.0535112 +-0.104891 0.896146 -0.149759 +-0.116246 0.851587 -0.176707 +-0.125979 0.757518 -0.199807 +-0.13409 0.36143 -0.219055 +-0.143822 0.267359 -0.242155 +-0.177887 0.108924 -0.323003 +-0.208111 -0.049511 -0.394743 +-0.215846 -0.222799 -0.473148 +-0.23477 -0.376283 -0.519344 +-0.111759 -0.950611 -0.219055 +-0.0439465 -0.990221 -0.0535112 +-0.00294161 -0.990221 0.046584 +-0.0265958 0.99022 0.039318 +-0.051664 0.980316 -0.00927085 +-0.0728736 0.960511 -0.0503832 +-0.121076 0.896146 -0.143823 +-0.134573 0.851587 -0.169987 +-0.14614 0.757518 -0.192411 +-0.155783 0.36143 -0.211099 +-0.16735 0.267359 -0.233527 +-0.207844 0.108924 -0.312015 +-0.24377 -0.049511 -0.381663 +-0.25658 -0.222799 -0.457784 +-0.279078 -0.376283 -0.502636 +-0.132851 -0.950611 -0.211099 +-0.0522379 -0.990221 -0.0503832 +-0.00349283 -0.990221 0.0467932 +-0.0277432 0.99022 0.0398256 +-0.0566615 0.980316 -0.00705647 +-0.0811288 0.960511 -0.0467272 +-0.136737 0.896146 -0.136883 +-0.152308 0.851587 -0.162127 +-0.165655 0.757518 -0.183767 +-0.17678 0.36143 -0.201795 +-0.190123 0.267359 -0.223435 +-0.236839 0.108924 -0.299167 +-0.278291 -0.049511 -0.366371 +-0.296008 -0.222799 -0.439816 +-0.321962 -0.376283 -0.483088 +-0.317638 -0.50006 -0.475876 +-0.308985 -0.643644 -0.461452 +-0.283031 -0.782273 -0.418176 +-0.153266 -0.950611 -0.201799 +-0.0602626 -0.990221 -0.0467272 +-0.00403059 -0.990221 0.047038 +-0.0288413 0.99022 0.040404 +-0.0614646 0.980316 -0.00453246 +-0.0890678 0.960511 -0.0425552 +-0.151802 0.896146 -0.128971 +-0.16937 0.851587 -0.153167 +-0.184425 0.757518 -0.173907 +-0.196973 0.36143 -0.191191 +-0.212028 0.267359 -0.211931 +-0.264722 0.108924 -0.284519 +-0.311484 -0.049511 -0.348935 +-0.333927 -0.222799 -0.419328 +-0.363207 -0.376283 -0.460808 +-0.358327 -0.50006 -0.453896 +-0.348567 -0.643644 -0.440068 +-0.319287 -0.782273 -0.398591 +-0.172899 -0.950611 -0.191191 +-0.0679846 -0.990221 -0.0425552 +-0.00455022 -0.990221 0.0473172 +-0.0298941 0.99022 0.0410504 +-0.0660553 0.980316 -0.00171125 +-0.0966497 0.960511 -0.0378952 +-0.166189 0.896146 -0.120127 +-0.185663 0.851587 -0.143155 +-0.20235 0.757518 -0.162891 +-0.216258 0.36143 -0.179335 +-0.232949 0.267359 -0.199071 +-0.291359 0.108924 -0.268147 +-0.34319 -0.049511 -0.329443 +-0.370142 -0.222799 -0.396435 +-0.402598 -0.376283 -0.435908 +-0.39719 -0.50006 -0.429328 +-0.386373 -0.643644 -0.416172 +-0.353917 -0.782273 -0.376699 +-0.19165 -0.950611 -0.179335 +-0.0753587 -0.990221 -0.0378952 +-0.00504267 -0.990221 0.0476292 +-0.0308927 0.99022 0.0417616 +-0.0704066 0.980316 0.00139272 +-0.103839 0.960511 -0.0327672 +-0.17983 0.896146 -0.110399 +-0.201107 0.851587 -0.132135 +-0.219344 0.757518 -0.150767 +-0.234539 0.36143 -0.166295 +-0.252776 0.267359 -0.184927 +-0.316608 0.108924 -0.250139 +-0.373247 -0.049511 -0.308003 +-0.404474 -0.222799 -0.371243 +-0.439939 -0.376283 -0.408508 +-0.434029 -0.50006 -0.4023 +-0.422208 -0.643644 -0.389875 +-0.386743 -0.782273 -0.352611 +-0.295127 -0.881297 -0.256347 +-0.209426 -0.950611 -0.166295 +-0.0823488 -0.990221 -0.0327672 +-0.00550807 -0.990221 0.047972 +-0.0318282 0.99022 0.042534 +-0.0744958 0.980316 0.00476313 +-0.110598 0.960511 -0.0271952 +-0.192649 0.896146 -0.0998312 +-0.21562 0.851587 -0.120171 +-0.235316 0.757518 -0.137603 +-0.251723 0.36143 -0.152131 +-0.271419 0.267359 -0.169563 +-0.340339 0.108924 -0.230579 +-0.4015 -0.049511 -0.284719 +-0.436744 -0.222799 -0.343891 +-0.475038 -0.376283 -0.378755 +-0.468654 -0.50006 -0.372943 +-0.455893 -0.643644 -0.361323 +-0.4176 -0.782273 -0.326455 +-0.318677 -0.881297 -0.236387 +-0.226135 -0.950611 -0.152131 +-0.0889187 -0.990221 -0.0271952 +-0.00595093 -0.990221 0.0483448 +-0.0327002 0.99022 0.0433636 +-0.0783048 0.980316 0.00838357 +-0.116888 0.960511 -0.0212152 +-0.204582 0.896146 -0.0884832 +-0.22914 0.851587 -0.107319 +-0.250187 0.757518 -0.123463 +-0.267723 0.36143 -0.136919 +-0.28877 0.267359 -0.153063 +-0.362434 0.108924 -0.209567 +-0.427802 -0.049511 -0.259711 +-0.466788 -0.222799 -0.314507 +-0.507716 -0.376283 -0.346799 +-0.500897 -0.50006 -0.341415 +-0.487252 -0.643644 -0.330651 +-0.446323 -0.782273 -0.298363 +-0.340596 -0.881297 -0.214951 +-0.241692 -0.950611 -0.136919 +-0.0950366 -0.990221 -0.0212152 +-0.00635743 -0.990221 0.0487452 +-0.0335044 0.99022 0.0442464 +-0.0818112 0.980316 0.0122352 +-0.12268 0.960511 -0.0148512 +-0.215575 0.896146 -0.0764112 +-0.241583 0.851587 -0.0936472 +-0.263878 0.757518 -0.108423 +-0.282457 0.36143 -0.120735 +-0.304751 0.267359 -0.135507 +-0.38278 0.108924 -0.187219 +-0.452021 -0.049511 -0.233103 +-0.494454 -0.222799 -0.283251 +-0.537808 -0.376283 -0.312799 +-0.530583 -0.50006 -0.307875 +-0.516133 -0.643644 -0.298023 +-0.472779 -0.782273 -0.268475 +-0.360785 -0.881297 -0.192143 +-0.256015 -0.950611 -0.120735 +-0.100667 -0.990221 -0.0148512 +-0.00673711 -0.990221 0.0491712 +-0.0342363 0.99022 0.0451776 +-0.0849967 0.980316 0.0162988 +-0.127949 0.960511 -0.00813723 +-0.225566 0.896146 -0.0636752 +-0.252898 0.851587 -0.0792232 +-0.276326 0.757518 -0.0925512 +-0.29585 0.36143 -0.103659 +-0.319274 0.267359 -0.116987 +-0.401275 0.108924 -0.163639 +-0.474035 -0.049511 -0.205035 +-0.519599 -0.222799 -0.250275 +-0.565159 -0.376283 -0.276931 +-0.557568 -0.50006 -0.272491 +-0.542381 -0.643644 -0.263603 +-0.496822 -0.782273 -0.236947 +-0.379134 -0.881297 -0.168083 +-0.269033 -0.950611 -0.103659 +-0.105786 -0.990221 -0.00813723 +-0.00708055 -0.990221 0.0496204 +-0.0348871 0.99022 0.0461524 +-0.0878478 0.980316 0.0205528 +-0.132657 0.960511 -0.00110841 +-0.234503 0.896146 -0.0503392 +-0.263019 0.851587 -0.0641232 +-0.287459 0.757518 -0.0759392 +-0.307828 0.36143 -0.0857832 +-0.332273 0.267359 -0.0975992 +-0.417821 0.108924 -0.138951 +-0.493731 -0.049511 -0.175647 +-0.542101 -0.222799 -0.215751 +-0.589631 -0.376283 -0.239379 +-0.58171 -0.50006 -0.235443 +-0.565863 -0.643644 -0.227567 +-0.518334 -0.782273 -0.203935 +-0.39555 -0.881297 -0.142891 +-0.280682 -0.950611 -0.0857832 +-0.110368 -0.990221 -0.00110841 +-0.00738323 -0.990221 0.0500908 +-0.0354608 0.99022 0.047166 +-0.090351 0.980316 0.0249764 +-0.136792 0.960511 0.00620037 +-0.242343 0.896146 -0.0364712 +-0.271898 0.851587 -0.0484192 +-0.297228 0.757518 -0.0586632 +-0.318338 0.36143 -0.0671952 +-0.343673 0.267359 -0.0774392 +-0.432334 0.108924 -0.113283 +-0.51101 -0.049511 -0.145091 +-0.561833 -0.222799 -0.179851 +-0.611098 -0.376283 -0.200335 +-0.602888 -0.50006 -0.196923 +-0.586463 -0.643644 -0.190095 +-0.537203 -0.782273 -0.169611 +-0.40995 -0.881297 -0.116695 +-0.290902 -0.950611 -0.0671952 +-0.114385 -0.990221 0.00620037 +-0.00765431 -0.990221 0.0505796 +-0.0359533 0.99022 0.0482132 +-0.0924882 0.980316 0.0295464 +-0.140325 0.960511 0.0137511 +-0.249043 0.896146 -0.0221472 +-0.279489 0.851587 -0.0321993 +-0.305578 0.757518 -0.0408152 +-0.327326 0.36143 -0.0479952 +-0.353415 0.267359 -0.0566072 +-0.444742 0.108924 -0.0867632 +-0.52578 -0.049511 -0.113519 +-0.578709 -0.222799 -0.142763 +-0.629447 -0.376283 -0.159995 +-0.620993 -0.50006 -0.157123 +-0.604076 -0.643644 -0.151379 +-0.553338 -0.782273 -0.134147 +-0.422258 -0.881297 -0.0896352 +-0.299636 -0.950611 -0.0479952 +-0.117819 -0.990221 0.0137511 +-0.00788474 -0.990221 0.0510852 +-0.0363555 0.99022 0.0492888 +-0.0942504 0.980316 0.0342399 +-0.143239 0.960511 0.021506 +-0.254578 0.896146 -0.00743444 +-0.285751 0.851587 -0.0155392 +-0.312473 0.757518 -0.0224832 +-0.33474 0.36143 -0.0282712 +-0.361458 0.267359 -0.0352153 +-0.454981 0.108924 -0.0595272 +-0.537971 -0.049511 -0.0810992 +-0.592631 -0.222799 -0.104675 +-0.644593 -0.376283 -0.118567 +-0.635931 -0.50006 -0.116251 +-0.618612 -0.643644 -0.111619 +-0.56665 -0.782273 -0.0977272 +-0.43242 -0.881297 -0.0618432 +-0.306848 -0.950611 -0.0282712 +-0.120656 -0.990221 0.021506 +-0.00807452 -0.990221 0.051604 +-0.0366718 0.99022 0.0503872 +-0.095633 0.980316 0.0390328 +-0.145521 0.960511 0.0294251 +-0.258907 0.896146 0.00758994 +-0.290658 0.851587 0.00147593 +-0.317868 0.757518 -0.00376445 +-0.340546 0.36143 -0.00813162 +-0.367757 0.267359 -0.0133721 +-0.463001 0.108924 -0.0317153 +-0.547519 -0.049511 -0.0479912 +-0.603534 -0.222799 -0.0657752 +-0.656454 -0.376283 -0.0762592 +-0.647634 -0.50006 -0.0745112 +-0.629994 -0.643644 -0.0710192 +-0.577078 -0.782273 -0.0605352 +-0.440377 -0.881297 -0.0334592 +-0.312492 -0.950611 -0.00813162 +-0.122875 -0.990221 0.0294251 +-0.00822353 -0.990221 0.052134 +-0.0369022 0.99022 0.0515028 +-0.0966271 0.980316 0.0439008 +-0.147161 0.960511 0.0374683 +-0.26202 0.896146 0.0228496 +-0.294178 0.851587 0.0187564 +-0.321745 0.757518 0.0152476 +-0.344713 0.36143 0.012324 +-0.37228 0.267359 0.00881517 +-0.468757 0.108924 -0.00346446 +-0.554369 -0.049511 -0.0143632 +-0.611364 -0.222799 -0.0262712 +-0.664967 -0.376283 -0.0332872 +-0.656034 -0.50006 -0.0321193 +-0.638168 -0.643644 -0.0297792 +-0.584561 -0.782273 -0.0227633 +-0.446088 -0.881297 -0.00463402 +-0.316549 -0.950611 0.012324 +-0.12447 -0.990221 0.0374683 +-0.0083276 -0.990221 0.0526724 +-0.0370378 0.99022 0.05263 +-0.0972236 0.980316 0.0488192 +-0.148151 0.960511 0.0455948 +-0.263891 0.896146 0.0382668 +-0.296297 0.851587 0.0362148 +-0.324077 0.757518 0.034456 +-0.347225 0.36143 0.0329903 +-0.375004 0.267359 0.0312315 +-0.472223 0.108924 0.025076 +-0.558498 -0.049511 0.0196136 +-0.616077 -0.222799 0.013644 +-0.670095 -0.376283 0.0101264 +-0.66109 -0.50006 0.0107127 +-0.643084 -0.643644 0.0118852 +-0.58907 -0.782273 0.0154028 +-0.449527 -0.881297 0.0244895 +-0.318989 -0.950611 0.0329903 +-0.125428 -0.990221 0.0455948 +-0.00839078 -0.990221 0.053216 +numsurf 1553 +SURF 0x30 +mat 1 +refs 4 +0 0.472401 1 +1 0.472434 1 +2 0.42764 0.994999 +3 0.427492 0.994999 +SURF 0x30 +mat 1 +refs 4 +3 0.427492 0.994999 +2 0.42764 0.994999 +4 0.389737 0.984998 +5 0.389492 0.984998 +SURF 0x30 +mat 1 +refs 4 +5 0.389492 0.984998 +4 0.389737 0.984998 +6 0.303596 0.952498 +7 0.303132 0.952498 +SURF 0x30 +mat 1 +refs 4 +7 0.303132 0.952498 +6 0.303596 0.952498 +8 0.279478 0.929999 +9 0.27895 0.929999 +SURF 0x30 +mat 1 +refs 4 +9 0.27895 0.929999 +8 0.279478 0.929999 +10 0.258802 0.8825 +11 0.258224 0.8825 +SURF 0x30 +mat 1 +refs 4 +11 0.258224 0.8825 +10 0.258802 0.8825 +12 0.241574 0.6825 +13 0.240952 0.6825 +SURF 0x30 +mat 1 +refs 4 +13 0.240952 0.6825 +12 0.241574 0.6825 +14 0.220899 0.635 +15 0.220223 0.635 +SURF 0x30 +mat 1 +refs 4 +15 0.220223 0.635 +14 0.220899 0.635 +16 0.148543 0.555 +17 0.147679 0.555 +SURF 0x30 +mat 1 +refs 4 +17 0.147679 0.555 +16 0.148543 0.555 +18 0.0843316 0.475 +19 0.0833059 0.475 +SURF 0x30 +mat 1 +refs 4 +19 0.0833059 0.475 +18 0.0843316 0.475 +20 0.0414781 0.3875 +21 0.0403078 0.3875 +SURF 0x30 +mat 1 +refs 4 +21 0.0403078 0.3875 +20 0.0414781 0.3875 +22 0.00127453 0.31 +23 0 0.31 +SURF 0x30 +mat 1 +refs 4 +23 0 0.31 +22 0.00127453 0.31 +24 0.0079768 0.247501 +25 0.00671911 0.247501 +SURF 0x30 +mat 1 +refs 4 +25 0.00671911 0.247501 +24 0.0079768 0.247501 +26 0.021378 0.175 +27 0.0201539 0.175 +SURF 0x30 +mat 1 +refs 4 +27 0.0201539 0.175 +26 0.021378 0.175 +28 0.0615781 0.105001 +29 0.0604583 0.105001 +SURF 0x30 +mat 1 +refs 4 +29 0.0604583 0.105001 +28 0.0615781 0.105001 +30 0.165435 0.0549999 +31 0.164581 0.0549999 +SURF 0x30 +mat 1 +refs 4 +31 0.164581 0.0549999 +30 0.165435 0.0549999 +32 0.262589 0.0200004 +33 0.261984 0.0200004 +SURF 0x30 +mat 1 +refs 4 +33 0.261984 0.0200004 +32 0.262589 0.0200004 +34 0.406649 0 +35 0.40641 0 +SURF 0x30 +mat 1 +refs 4 +35 0.40641 0 +34 0.406649 0 +36 0.493755 0 +37 0.493738 0 +SURF 0x30 +mat 1 +refs 4 +1 0.472434 1 +38 0.472535 1 +39 0.428084 0.994999 +2 0.42764 0.994999 +SURF 0x30 +mat 1 +refs 4 +2 0.42764 0.994999 +39 0.428084 0.994999 +40 0.390474 0.984998 +4 0.389737 0.984998 +SURF 0x30 +mat 1 +refs 4 +4 0.389737 0.984998 +40 0.390474 0.984998 +41 0.304989 0.952498 +6 0.303596 0.952498 +SURF 0x30 +mat 1 +refs 4 +6 0.303596 0.952498 +41 0.304989 0.952498 +42 0.281055 0.929999 +8 0.279478 0.929999 +SURF 0x30 +mat 1 +refs 4 +8 0.279478 0.929999 +42 0.281055 0.929999 +43 0.260538 0.8825 +10 0.258802 0.8825 +SURF 0x30 +mat 1 +refs 4 +10 0.258802 0.8825 +43 0.260538 0.8825 +44 0.243444 0.6825 +12 0.241574 0.6825 +SURF 0x30 +mat 1 +refs 4 +12 0.241574 0.6825 +44 0.243444 0.6825 +45 0.222927 0.635 +14 0.220899 0.635 +SURF 0x30 +mat 1 +refs 4 +14 0.220899 0.635 +45 0.222927 0.635 +46 0.151122 0.555 +16 0.148543 0.555 +SURF 0x30 +mat 1 +refs 4 +16 0.148543 0.555 +46 0.151122 0.555 +47 0.0874052 0.475 +18 0.0843316 0.475 +SURF 0x30 +mat 1 +refs 4 +18 0.0843316 0.475 +47 0.0874052 0.475 +48 0.0449856 0.3875 +20 0.0414781 0.3875 +SURF 0x30 +mat 1 +refs 4 +20 0.0414781 0.3875 +48 0.0449856 0.3875 +49 0.0050915 0.31 +22 0.00127453 0.31 +SURF 0x30 +mat 1 +refs 4 +22 0.00127453 0.31 +49 0.0050915 0.31 +50 0.0117399 0.247501 +24 0.0079768 0.247501 +SURF 0x30 +mat 1 +refs 4 +24 0.0079768 0.247501 +50 0.0117399 0.247501 +51 0.0250368 0.175 +26 0.021378 0.175 +SURF 0x30 +mat 1 +refs 4 +26 0.021378 0.175 +51 0.0250368 0.175 +52 0.0649344 0.105001 +28 0.0615781 0.105001 +SURF 0x30 +mat 1 +refs 4 +28 0.0615781 0.105001 +52 0.0649344 0.105001 +53 0.167994 0.0549999 +30 0.165435 0.0549999 +SURF 0x30 +mat 1 +refs 4 +30 0.165435 0.0549999 +53 0.167994 0.0549999 +54 0.264405 0.0200004 +32 0.262589 0.0200004 +SURF 0x30 +mat 1 +refs 4 +32 0.262589 0.0200004 +54 0.264405 0.0200004 +55 0.407362 0 +34 0.406649 0 +SURF 0x30 +mat 1 +refs 4 +34 0.406649 0 +55 0.407362 0 +56 0.493802 0 +36 0.493755 0 +SURF 0x30 +mat 1 +refs 4 +38 0.472535 1 +57 0.472707 1 +58 0.428824 0.994999 +39 0.428084 0.994999 +SURF 0x30 +mat 1 +refs 4 +39 0.428084 0.994999 +58 0.428824 0.994999 +59 0.391694 0.984998 +40 0.390474 0.984998 +SURF 0x30 +mat 1 +refs 4 +40 0.390474 0.984998 +59 0.391694 0.984998 +60 0.307306 0.952498 +41 0.304989 0.952498 +SURF 0x30 +mat 1 +refs 4 +41 0.304989 0.952498 +60 0.307306 0.952498 +61 0.283674 0.929999 +42 0.281055 0.929999 +SURF 0x30 +mat 1 +refs 4 +42 0.281055 0.929999 +61 0.283674 0.929999 +62 0.263423 0.8825 +43 0.260538 0.8825 +SURF 0x30 +mat 1 +refs 4 +43 0.260538 0.8825 +62 0.263423 0.8825 +63 0.246545 0.6825 +44 0.243444 0.6825 +SURF 0x30 +mat 1 +refs 4 +44 0.243444 0.6825 +63 0.246545 0.6825 +64 0.226293 0.635 +45 0.222927 0.635 +SURF 0x30 +mat 1 +refs 4 +45 0.222927 0.635 +64 0.226293 0.635 +65 0.155407 0.555 +46 0.151122 0.555 +SURF 0x30 +mat 1 +refs 4 +46 0.151122 0.555 +65 0.155407 0.555 +66 0.0925034 0.475 +47 0.0874052 0.475 +SURF 0x30 +mat 1 +refs 4 +47 0.0874052 0.475 +66 0.0925034 0.475 +67 0.0508135 0.3875 +48 0.0449856 0.3875 +SURF 0x30 +mat 1 +refs 4 +48 0.0449856 0.3875 +67 0.0508135 0.3875 +68 0.0114272 0.31 +49 0.0050915 0.31 +SURF 0x30 +mat 1 +refs 4 +49 0.0050915 0.31 +68 0.0114272 0.31 +69 0.0179915 0.247501 +50 0.0117399 0.247501 +SURF 0x30 +mat 1 +refs 4 +50 0.0117399 0.247501 +69 0.0179915 0.247501 +70 0.0311203 0.175 +51 0.0250368 0.175 +SURF 0x30 +mat 1 +refs 4 +51 0.0250368 0.175 +70 0.0311203 0.175 +71 0.0705033 0.105001 +52 0.0649344 0.105001 +SURF 0x30 +mat 1 +refs 4 +52 0.0649344 0.105001 +71 0.0705033 0.105001 +72 0.172245 0.0549999 +53 0.167994 0.0549999 +SURF 0x30 +mat 1 +refs 4 +53 0.167994 0.0549999 +72 0.172245 0.0549999 +73 0.267425 0.0200004 +54 0.264405 0.0200004 +SURF 0x30 +mat 1 +refs 4 +54 0.264405 0.0200004 +73 0.267425 0.0200004 +74 0.408549 0 +55 0.407362 0 +SURF 0x30 +mat 1 +refs 4 +55 0.407362 0 +74 0.408549 0 +75 0.49388 0 +56 0.493802 0 +SURF 0x30 +mat 1 +refs 4 +57 0.472707 1 +76 0.472942 1 +77 0.429853 0.994999 +58 0.428824 0.994999 +SURF 0x30 +mat 1 +refs 4 +58 0.428824 0.994999 +77 0.429853 0.994999 +78 0.393393 0.984998 +59 0.391694 0.984998 +SURF 0x30 +mat 1 +refs 4 +59 0.391694 0.984998 +78 0.393393 0.984998 +79 0.310527 0.952498 +60 0.307306 0.952498 +SURF 0x30 +mat 1 +refs 4 +60 0.307306 0.952498 +79 0.310527 0.952498 +80 0.287327 0.929999 +61 0.283674 0.929999 +SURF 0x30 +mat 1 +refs 4 +61 0.283674 0.929999 +80 0.287327 0.929999 +81 0.267438 0.8825 +62 0.263423 0.8825 +SURF 0x30 +mat 1 +refs 4 +62 0.263423 0.8825 +81 0.267438 0.8825 +82 0.250866 0.6825 +63 0.246545 0.6825 +SURF 0x30 +mat 1 +refs 4 +63 0.246545 0.6825 +82 0.250866 0.6825 +83 0.230981 0.635 +64 0.226293 0.635 +SURF 0x30 +mat 1 +refs 4 +64 0.226293 0.635 +83 0.230981 0.635 +84 0.161376 0.555 +65 0.155407 0.555 +SURF 0x30 +mat 1 +refs 4 +65 0.155407 0.555 +84 0.161376 0.555 +85 0.0996092 0.475 +66 0.0925034 0.475 +SURF 0x30 +mat 1 +refs 4 +66 0.0925034 0.475 +85 0.0996092 0.475 +86 0.0589282 0.3875 +67 0.0508135 0.3875 +SURF 0x30 +mat 1 +refs 4 +67 0.0508135 0.3875 +86 0.0589282 0.3875 +87 0.0202548 0.31 +68 0.0114272 0.31 +SURF 0x30 +mat 1 +refs 4 +68 0.0114272 0.31 +87 0.0202548 0.31 +88 0.0267014 0.247501 +69 0.0179915 0.247501 +SURF 0x30 +mat 1 +refs 4 +69 0.0179915 0.247501 +88 0.0267014 0.247501 +89 0.0395915 0.175 +70 0.0311203 0.175 +SURF 0x30 +mat 1 +refs 4 +70 0.0311203 0.175 +89 0.0395915 0.175 +90 0.0782649 0.105001 +71 0.0705033 0.105001 +SURF 0x30 +mat 1 +refs 4 +71 0.0705033 0.105001 +90 0.0782649 0.105001 +91 0.178167 0.0549999 +72 0.172245 0.0549999 +SURF 0x30 +mat 1 +refs 4 +72 0.172245 0.0549999 +91 0.178167 0.0549999 +92 0.271625 0.0200004 +73 0.267425 0.0200004 +SURF 0x30 +mat 1 +refs 4 +73 0.267425 0.0200004 +92 0.271625 0.0200004 +93 0.4102 0 +74 0.408549 0 +SURF 0x30 +mat 1 +refs 4 +74 0.408549 0 +93 0.4102 0 +94 0.493991 0 +75 0.49388 0 +SURF 0x30 +mat 1 +refs 4 +76 0.472942 1 +95 0.473241 1 +96 0.431165 0.994999 +77 0.429853 0.994999 +SURF 0x30 +mat 1 +refs 4 +77 0.429853 0.994999 +96 0.431165 0.994999 +97 0.395562 0.984998 +78 0.393393 0.984998 +SURF 0x30 +mat 1 +refs 4 +78 0.393393 0.984998 +97 0.395562 0.984998 +98 0.314647 0.952498 +79 0.310527 0.952498 +SURF 0x30 +mat 1 +refs 4 +79 0.310527 0.952498 +98 0.314647 0.952498 +99 0.291988 0.929999 +80 0.287327 0.929999 +SURF 0x30 +mat 1 +refs 4 +80 0.287327 0.929999 +99 0.291988 0.929999 +100 0.27257 0.8825 +81 0.267438 0.8825 +SURF 0x30 +mat 1 +refs 4 +81 0.267438 0.8825 +100 0.27257 0.8825 +101 0.256385 0.6825 +82 0.250866 0.6825 +SURF 0x30 +mat 1 +refs 4 +82 0.250866 0.6825 +101 0.256385 0.6825 +102 0.236967 0.635 +83 0.230981 0.635 +SURF 0x30 +mat 1 +refs 4 +83 0.230981 0.635 +102 0.236967 0.635 +103 0.168996 0.555 +84 0.161376 0.555 +SURF 0x30 +mat 1 +refs 4 +84 0.161376 0.555 +103 0.168996 0.555 +104 0.108682 0.475 +85 0.0996092 0.475 +SURF 0x30 +mat 1 +refs 4 +85 0.0996092 0.475 +104 0.108682 0.475 +105 0.0692893 0.3875 +86 0.0589282 0.3875 +SURF 0x30 +mat 1 +refs 4 +86 0.0589282 0.3875 +105 0.0692893 0.3875 +106 0.0315273 0.31 +87 0.0202548 0.31 +SURF 0x30 +mat 1 +refs 4 +87 0.0202548 0.31 +106 0.0315273 0.31 +107 0.0378192 0.247501 +88 0.0267014 0.247501 +SURF 0x30 +mat 1 +refs 4 +88 0.0267014 0.247501 +107 0.0378192 0.247501 +108 0.0504099 0.175 +89 0.0395915 0.175 +SURF 0x30 +mat 1 +refs 4 +89 0.0395915 0.175 +108 0.0504099 0.175 +109 0.088172 0.105001 +90 0.0782649 0.105001 +SURF 0x30 +mat 1 +refs 4 +90 0.0782649 0.105001 +109 0.088172 0.105001 +110 0.18573 0.0549999 +91 0.178167 0.0549999 +SURF 0x30 +mat 1 +refs 4 +91 0.178167 0.0549999 +110 0.18573 0.0549999 +111 0.276992 0.0200004 +92 0.271625 0.0200004 +SURF 0x30 +mat 1 +refs 4 +92 0.271625 0.0200004 +111 0.276992 0.0200004 +112 0.412312 0 +93 0.4102 0 +SURF 0x30 +mat 1 +refs 4 +93 0.4102 0 +112 0.412312 0 +113 0.494132 0 +94 0.493991 0 +SURF 0x30 +mat 1 +refs 4 +95 0.473241 1 +114 0.473608 1 +115 0.432755 0.994999 +96 0.431165 0.994999 +SURF 0x30 +mat 1 +refs 4 +96 0.431165 0.994999 +115 0.432755 0.994999 +116 0.398191 0.984998 +97 0.395562 0.984998 +SURF 0x30 +mat 1 +refs 4 +97 0.395562 0.984998 +116 0.398191 0.984998 +117 0.319634 0.952498 +98 0.314647 0.952498 +SURF 0x30 +mat 1 +refs 4 +98 0.314647 0.952498 +117 0.319634 0.952498 +118 0.297637 0.929999 +99 0.291988 0.929999 +SURF 0x30 +mat 1 +refs 4 +99 0.291988 0.929999 +118 0.297637 0.929999 +119 0.278785 0.8825 +100 0.27257 0.8825 +SURF 0x30 +mat 1 +refs 4 +100 0.27257 0.8825 +119 0.278785 0.8825 +120 0.263073 0.6825 +101 0.256385 0.6825 +SURF 0x30 +mat 1 +refs 4 +101 0.256385 0.6825 +120 0.263073 0.6825 +121 0.244218 0.635 +102 0.236967 0.635 +SURF 0x30 +mat 1 +refs 4 +102 0.236967 0.635 +121 0.244218 0.635 +122 0.178231 0.555 +103 0.168996 0.555 +SURF 0x30 +mat 1 +refs 4 +103 0.168996 0.555 +122 0.178231 0.555 +123 0.119676 0.475 +104 0.108682 0.475 +SURF 0x30 +mat 1 +refs 4 +104 0.108682 0.475 +123 0.119676 0.475 +124 0.0818498 0.3875 +105 0.0692893 0.3875 +SURF 0x30 +mat 1 +refs 4 +105 0.0692893 0.3875 +124 0.0818498 0.3875 +125 0.045184 0.31 +106 0.0315273 0.31 +SURF 0x30 +mat 1 +refs 4 +106 0.0315273 0.31 +125 0.045184 0.31 +126 0.0512944 0.247501 +107 0.0378192 0.247501 +SURF 0x30 +mat 1 +refs 4 +107 0.0378192 0.247501 +126 0.0512944 0.247501 +127 0.0635152 0.175 +108 0.0504099 0.175 +SURF 0x30 +mat 1 +refs 4 +108 0.0504099 0.175 +127 0.0635152 0.175 +128 0.100181 0.105001 +109 0.088172 0.105001 +SURF 0x30 +mat 1 +refs 4 +109 0.088172 0.105001 +128 0.100181 0.105001 +129 0.19489 0.0549999 +110 0.18573 0.0549999 +SURF 0x30 +mat 1 +refs 4 +110 0.18573 0.0549999 +129 0.19489 0.0549999 +130 0.283493 0.0200004 +111 0.276992 0.0200004 +SURF 0x30 +mat 1 +refs 4 +111 0.276992 0.0200004 +130 0.283493 0.0200004 +131 0.414868 0 +112 0.412312 0 +SURF 0x30 +mat 1 +refs 4 +112 0.412312 0 +131 0.414868 0 +132 0.494303 0 +113 0.494132 0 +SURF 0x30 +mat 1 +refs 4 +114 0.473608 1 +133 0.474035 1 +134 0.434618 0.994999 +115 0.432755 0.994999 +SURF 0x30 +mat 1 +refs 4 +115 0.432755 0.994999 +134 0.434618 0.994999 +135 0.401268 0.984998 +116 0.398191 0.984998 +SURF 0x30 +mat 1 +refs 4 +116 0.398191 0.984998 +135 0.401268 0.984998 +136 0.325469 0.952498 +117 0.319634 0.952498 +SURF 0x30 +mat 1 +refs 4 +117 0.319634 0.952498 +136 0.325469 0.952498 +137 0.304245 0.929999 +118 0.297637 0.929999 +SURF 0x30 +mat 1 +refs 4 +118 0.297637 0.929999 +137 0.304245 0.929999 +138 0.286055 0.8825 +119 0.278785 0.8825 +SURF 0x30 +mat 1 +refs 4 +119 0.278785 0.8825 +138 0.286055 0.8825 +139 0.270895 0.6825 +120 0.263073 0.6825 +SURF 0x30 +mat 1 +refs 4 +120 0.263073 0.6825 +139 0.270895 0.6825 +140 0.252702 0.635 +121 0.244218 0.635 +SURF 0x30 +mat 1 +refs 4 +121 0.244218 0.635 +140 0.252702 0.635 +141 0.189032 0.555 +122 0.178231 0.555 +SURF 0x30 +mat 1 +refs 4 +122 0.178231 0.555 +141 0.189032 0.555 +142 0.132535 0.475 +123 0.119676 0.475 +SURF 0x30 +mat 1 +refs 4 +123 0.119676 0.475 +142 0.132535 0.475 +143 0.0965356 0.3875 +124 0.0818498 0.3875 +SURF 0x30 +mat 1 +refs 4 +124 0.0818498 0.3875 +143 0.0965356 0.3875 +144 0.0611612 0.31 +125 0.045184 0.31 +SURF 0x30 +mat 1 +refs 4 +125 0.045184 0.31 +144 0.0611612 0.31 +145 0.0670564 0.247501 +126 0.0512944 0.247501 +SURF 0x30 +mat 1 +refs 4 +126 0.0512944 0.247501 +145 0.0670564 0.247501 +146 0.07885 0.175 +127 0.0635152 0.175 +SURF 0x30 +mat 1 +refs 4 +127 0.0635152 0.175 +146 0.07885 0.175 +147 0.114224 0.105001 +128 0.100181 0.105001 +SURF 0x30 +mat 1 +refs 4 +128 0.100181 0.105001 +147 0.114224 0.105001 +148 0.205608 0.0549999 +129 0.19489 0.0549999 +SURF 0x30 +mat 1 +refs 4 +129 0.19489 0.0549999 +148 0.205608 0.0549999 +149 0.2911 0.0200004 +130 0.283493 0.0200004 +SURF 0x30 +mat 1 +refs 4 +130 0.283493 0.0200004 +149 0.2911 0.0200004 +150 0.417858 0 +131 0.414868 0 +SURF 0x30 +mat 1 +refs 4 +131 0.414868 0 +150 0.417858 0 +151 0.494505 0 +132 0.494303 0 +SURF 0x30 +mat 1 +refs 4 +133 0.474035 1 +152 0.474519 1 +153 0.43674 0.994999 +134 0.434618 0.994999 +SURF 0x30 +mat 1 +refs 4 +134 0.434618 0.994999 +153 0.43674 0.994999 +154 0.404773 0.984998 +135 0.401268 0.984998 +SURF 0x30 +mat 1 +refs 4 +135 0.401268 0.984998 +154 0.404773 0.984998 +155 0.33212 0.952498 +136 0.325469 0.952498 +SURF 0x30 +mat 1 +refs 4 +136 0.325469 0.952498 +155 0.33212 0.952498 +156 0.311778 0.929999 +137 0.304245 0.929999 +SURF 0x30 +mat 1 +refs 4 +137 0.304245 0.929999 +156 0.311778 0.929999 +157 0.294342 0.8825 +138 0.286055 0.8825 +SURF 0x30 +mat 1 +refs 4 +138 0.286055 0.8825 +157 0.294342 0.8825 +158 0.279811 0.6825 +139 0.270895 0.6825 +SURF 0x30 +mat 1 +refs 4 +139 0.270895 0.6825 +158 0.279811 0.6825 +159 0.262374 0.635 +140 0.252702 0.635 +SURF 0x30 +mat 1 +refs 4 +140 0.252702 0.635 +159 0.262374 0.635 +160 0.201347 0.555 +141 0.189032 0.555 +SURF 0x30 +mat 1 +refs 4 +141 0.189032 0.555 +160 0.201347 0.555 +161 0.147194 0.475 +142 0.132535 0.475 +SURF 0x30 +mat 1 +refs 4 +142 0.132535 0.475 +161 0.147194 0.475 +162 0.113283 0.3875 +143 0.0965356 0.3875 +SURF 0x30 +mat 1 +refs 4 +143 0.0965356 0.3875 +162 0.113283 0.3875 +163 0.0793746 0.31 +144 0.0611612 0.31 +SURF 0x30 +mat 1 +refs 4 +144 0.0611612 0.31 +163 0.0793746 0.31 +164 0.0850243 0.247501 +145 0.0670564 0.247501 +SURF 0x30 +mat 1 +refs 4 +145 0.0670564 0.247501 +164 0.0850243 0.247501 +165 0.096327 0.175 +146 0.07885 0.175 +SURF 0x30 +mat 1 +refs 4 +146 0.07885 0.175 +165 0.096327 0.175 +166 0.130235 0.105001 +147 0.114224 0.105001 +SURF 0x30 +mat 1 +refs 4 +147 0.114224 0.105001 +166 0.130235 0.105001 +167 0.217825 0.0549999 +148 0.205608 0.0549999 +SURF 0x30 +mat 1 +refs 4 +148 0.205608 0.0549999 +167 0.217825 0.0549999 +168 0.299769 0.0200004 +149 0.2911 0.0200004 +SURF 0x30 +mat 1 +refs 4 +149 0.2911 0.0200004 +168 0.299769 0.0200004 +169 0.421268 0 +150 0.417858 0 +SURF 0x30 +mat 1 +refs 4 +150 0.417858 0 +169 0.421268 0 +170 0.49473 0 +151 0.494505 0 +SURF 0x30 +mat 1 +refs 4 +152 0.474519 1 +171 0.475064 1 +172 0.439111 0.994999 +153 0.43674 0.994999 +SURF 0x30 +mat 1 +refs 4 +153 0.43674 0.994999 +172 0.439111 0.994999 +173 0.408694 0.984998 +154 0.404773 0.984998 +SURF 0x30 +mat 1 +refs 4 +154 0.404773 0.984998 +173 0.408694 0.984998 +174 0.339556 0.952498 +155 0.33212 0.952498 +SURF 0x30 +mat 1 +refs 4 +155 0.33212 0.952498 +174 0.339556 0.952498 +175 0.320199 0.929999 +156 0.311778 0.929999 +SURF 0x30 +mat 1 +refs 4 +156 0.311778 0.929999 +175 0.320199 0.929999 +176 0.303606 0.8825 +157 0.294342 0.8825 +SURF 0x30 +mat 1 +refs 4 +157 0.294342 0.8825 +176 0.303606 0.8825 +177 0.289778 0.6825 +158 0.279811 0.6825 +SURF 0x30 +mat 1 +refs 4 +158 0.279811 0.6825 +177 0.289778 0.6825 +178 0.273186 0.635 +159 0.262374 0.635 +SURF 0x30 +mat 1 +refs 4 +159 0.262374 0.635 +178 0.273186 0.635 +179 0.215112 0.555 +160 0.201347 0.555 +SURF 0x30 +mat 1 +refs 4 +160 0.201347 0.555 +179 0.215112 0.555 +180 0.163578 0.475 +161 0.147194 0.475 +SURF 0x30 +mat 1 +refs 4 +161 0.147194 0.475 +180 0.163578 0.475 +181 0.131997 0.3875 +162 0.113283 0.3875 +SURF 0x30 +mat 1 +refs 4 +162 0.113283 0.3875 +181 0.131997 0.3875 +182 0.0997303 0.31 +163 0.0793746 0.31 +SURF 0x30 +mat 1 +refs 4 +163 0.0793746 0.31 +182 0.0997303 0.31 +183 0.105108 0.247501 +164 0.0850243 0.247501 +SURF 0x30 +mat 1 +refs 4 +164 0.0850243 0.247501 +183 0.105108 0.247501 +184 0.115862 0.175 +165 0.096327 0.175 +SURF 0x30 +mat 1 +refs 4 +165 0.096327 0.175 +184 0.115862 0.175 +185 0.148129 0.105001 +166 0.130235 0.105001 +SURF 0x30 +mat 1 +refs 4 +166 0.130235 0.105001 +185 0.148129 0.105001 +186 0.231482 0.0549999 +167 0.217825 0.0549999 +SURF 0x30 +mat 1 +refs 4 +167 0.217825 0.0549999 +186 0.231482 0.0549999 +187 0.309458 0.0200004 +168 0.299769 0.0200004 +SURF 0x30 +mat 1 +refs 4 +168 0.299769 0.0200004 +187 0.309458 0.0200004 +188 0.425078 0 +169 0.421268 0 +SURF 0x30 +mat 1 +refs 4 +169 0.421268 0 +188 0.425078 0 +189 0.494986 0 +170 0.49473 0 +SURF 0x30 +mat 1 +refs 4 +171 0.475064 1 +190 0.475663 1 +191 0.441721 0.994999 +172 0.439111 0.994999 +SURF 0x30 +mat 1 +refs 4 +172 0.439111 0.994999 +191 0.441721 0.994999 +192 0.413005 0.984998 +173 0.408694 0.984998 +SURF 0x30 +mat 1 +refs 4 +173 0.408694 0.984998 +192 0.413005 0.984998 +193 0.347738 0.952498 +174 0.339556 0.952498 +SURF 0x30 +mat 1 +refs 4 +174 0.339556 0.952498 +193 0.347738 0.952498 +194 0.32946 0.929999 +175 0.320199 0.929999 +SURF 0x30 +mat 1 +refs 4 +175 0.320199 0.929999 +194 0.32946 0.929999 +195 0.313796 0.8825 +176 0.303606 0.8825 +SURF 0x30 +mat 1 +refs 4 +176 0.303606 0.8825 +195 0.313796 0.8825 +196 0.300745 0.6825 +177 0.289778 0.6825 +SURF 0x30 +mat 1 +refs 4 +177 0.289778 0.6825 +196 0.300745 0.6825 +197 0.28508 0.635 +178 0.273186 0.635 +SURF 0x30 +mat 1 +refs 4 +178 0.273186 0.635 +197 0.28508 0.635 +198 0.230255 0.555 +179 0.215112 0.555 +SURF 0x30 +mat 1 +refs 4 +179 0.215112 0.555 +198 0.230255 0.555 +199 0.181604 0.475 +180 0.163578 0.475 +SURF 0x30 +mat 1 +refs 4 +180 0.163578 0.475 +199 0.181604 0.475 +200 0.152588 0.3875 +181 0.131997 0.3875 +SURF 0x30 +mat 1 +refs 4 +181 0.131997 0.3875 +200 0.152588 0.3875 +201 0.122127 0.31 +182 0.0997303 0.31 +SURF 0x30 +mat 1 +refs 4 +182 0.0997303 0.31 +201 0.122127 0.31 +202 0.127202 0.247501 +183 0.105108 0.247501 +SURF 0x30 +mat 1 +refs 4 +183 0.105108 0.247501 +202 0.127202 0.247501 +203 0.137358 0.175 +184 0.115862 0.175 +SURF 0x30 +mat 1 +refs 4 +184 0.115862 0.175 +203 0.137358 0.175 +204 0.167816 0.105001 +185 0.148129 0.105001 +SURF 0x30 +mat 1 +refs 4 +185 0.148129 0.105001 +204 0.167816 0.105001 +205 0.246508 0.0549999 +186 0.231482 0.0549999 +SURF 0x30 +mat 1 +refs 4 +186 0.231482 0.0549999 +205 0.246508 0.0549999 +206 0.320118 0.0200004 +187 0.309458 0.0200004 +SURF 0x30 +mat 1 +refs 4 +187 0.309458 0.0200004 +206 0.320118 0.0200004 +207 0.429268 0 +188 0.425078 0 +SURF 0x30 +mat 1 +refs 4 +188 0.425078 0 +207 0.429268 0 +208 0.495268 0 +189 0.494986 0 +SURF 0x30 +mat 1 +refs 4 +190 0.475663 1 +209 0.476312 1 +210 0.444556 0.994999 +191 0.441721 0.994999 +SURF 0x30 +mat 1 +refs 4 +191 0.441721 0.994999 +210 0.444556 0.994999 +211 0.417686 0.984998 +192 0.413005 0.984998 +SURF 0x30 +mat 1 +refs 4 +192 0.413005 0.984998 +211 0.417686 0.984998 +212 0.356619 0.952498 +193 0.347738 0.952498 +SURF 0x30 +mat 1 +refs 4 +193 0.347738 0.952498 +212 0.356619 0.952498 +213 0.339522 0.929999 +194 0.32946 0.929999 +SURF 0x30 +mat 1 +refs 4 +194 0.32946 0.929999 +213 0.339522 0.929999 +214 0.324863 0.8825 +195 0.313796 0.8825 +SURF 0x30 +mat 1 +refs 4 +195 0.313796 0.8825 +214 0.324863 0.8825 +215 0.312653 0.6825 +196 0.300745 0.6825 +SURF 0x30 +mat 1 +refs 4 +196 0.300745 0.6825 +215 0.312653 0.6825 +216 0.297994 0.635 +197 0.28508 0.635 +SURF 0x30 +mat 1 +refs 4 +197 0.28508 0.635 +216 0.297994 0.635 +217 0.246699 0.555 +198 0.230255 0.555 +SURF 0x30 +mat 1 +refs 4 +198 0.230255 0.555 +217 0.246699 0.555 +218 0.201179 0.475 +199 0.181604 0.475 +SURF 0x30 +mat 1 +refs 4 +199 0.181604 0.475 +218 0.201179 0.475 +219 0.174948 0.3875 +200 0.152588 0.3875 +SURF 0x30 +mat 1 +refs 4 +200 0.152588 0.3875 +219 0.174948 0.3875 +220 0.146448 0.31 +201 0.122127 0.31 +SURF 0x30 +mat 1 +refs 4 +201 0.122127 0.31 +220 0.146448 0.31 +221 0.151196 0.247501 +202 0.127202 0.247501 +SURF 0x30 +mat 1 +refs 4 +202 0.127202 0.247501 +221 0.151196 0.247501 +222 0.160696 0.175 +203 0.137358 0.175 +SURF 0x30 +mat 1 +refs 4 +203 0.137358 0.175 +222 0.160696 0.175 +223 0.189197 0.105001 +204 0.167816 0.105001 +SURF 0x30 +mat 1 +refs 4 +204 0.167816 0.105001 +223 0.189197 0.105001 +224 0.262821 0.0549999 +205 0.246508 0.0549999 +SURF 0x30 +mat 1 +refs 4 +205 0.246508 0.0549999 +224 0.262821 0.0549999 +225 0.331697 0.0200004 +206 0.320118 0.0200004 +SURF 0x30 +mat 1 +refs 4 +206 0.320118 0.0200004 +225 0.331697 0.0200004 +226 0.433821 0 +207 0.429268 0 +SURF 0x30 +mat 1 +refs 4 +207 0.429268 0 +226 0.433821 0 +227 0.495571 0 +208 0.495268 0 +SURF 0x30 +mat 1 +refs 4 +209 0.476312 1 +228 0.477008 1 +229 0.447599 0.994999 +210 0.444556 0.994999 +SURF 0x30 +mat 1 +refs 4 +210 0.444556 0.994999 +229 0.447599 0.994999 +230 0.422717 0.984998 +211 0.417686 0.984998 +SURF 0x30 +mat 1 +refs 4 +211 0.417686 0.984998 +230 0.422717 0.984998 +231 0.36616 0.952498 +212 0.356619 0.952498 +SURF 0x30 +mat 1 +refs 4 +212 0.356619 0.952498 +231 0.36616 0.952498 +232 0.350324 0.929999 +213 0.339522 0.929999 +SURF 0x30 +mat 1 +refs 4 +213 0.339522 0.929999 +232 0.350324 0.929999 +233 0.336751 0.8825 +214 0.324863 0.8825 +SURF 0x30 +mat 1 +refs 4 +214 0.324863 0.8825 +233 0.336751 0.8825 +234 0.325442 0.6825 +215 0.312653 0.6825 +SURF 0x30 +mat 1 +refs 4 +215 0.312653 0.6825 +234 0.325442 0.6825 +235 0.311869 0.635 +216 0.297994 0.635 +SURF 0x30 +mat 1 +refs 4 +216 0.297994 0.635 +235 0.311869 0.635 +236 0.264361 0.555 +217 0.246699 0.555 +SURF 0x30 +mat 1 +refs 4 +217 0.246699 0.555 +236 0.264361 0.555 +237 0.222207 0.475 +218 0.201179 0.475 +SURF 0x30 +mat 1 +refs 4 +218 0.201179 0.475 +237 0.222207 0.475 +238 0.198966 0.3875 +219 0.174948 0.3875 +SURF 0x30 +mat 1 +refs 4 +219 0.174948 0.3875 +238 0.198966 0.3875 +239 0.172571 0.31 +220 0.146448 0.31 +SURF 0x30 +mat 1 +refs 4 +220 0.146448 0.31 +239 0.172571 0.31 +240 0.17697 0.247501 +221 0.151196 0.247501 +SURF 0x30 +mat 1 +refs 4 +221 0.151196 0.247501 +240 0.17697 0.247501 +241 0.185767 0.175 +222 0.160696 0.175 +SURF 0x30 +mat 1 +refs 4 +222 0.160696 0.175 +241 0.185767 0.175 +242 0.212162 0.105001 +223 0.189197 0.105001 +SURF 0x30 +mat 1 +refs 4 +223 0.189197 0.105001 +242 0.212162 0.105001 +243 0.280349 0.0549999 +224 0.262821 0.0549999 +SURF 0x30 +mat 1 +refs 4 +224 0.262821 0.0549999 +243 0.280349 0.0549999 +244 0.344133 0.0200004 +225 0.331697 0.0200004 +SURF 0x30 +mat 1 +refs 4 +225 0.331697 0.0200004 +244 0.344133 0.0200004 +245 0.438711 0 +226 0.433821 0 +SURF 0x30 +mat 1 +refs 4 +226 0.433821 0 +245 0.438711 0 +246 0.495901 0 +227 0.495571 0 +SURF 0x30 +mat 1 +refs 4 +228 0.477008 1 +247 0.477751 1 +248 0.450838 0.994999 +229 0.447599 0.994999 +SURF 0x30 +mat 1 +refs 4 +229 0.447599 0.994999 +248 0.450838 0.994999 +249 0.428064 0.984998 +230 0.422717 0.984998 +SURF 0x30 +mat 1 +refs 4 +230 0.422717 0.984998 +249 0.428064 0.984998 +250 0.376312 0.952498 +231 0.36616 0.952498 +SURF 0x30 +mat 1 +refs 4 +231 0.36616 0.952498 +250 0.376312 0.952498 +251 0.361818 0.929999 +232 0.350324 0.929999 +SURF 0x30 +mat 1 +refs 4 +232 0.350324 0.929999 +251 0.361818 0.929999 +252 0.349399 0.8825 +233 0.336751 0.8825 +SURF 0x30 +mat 1 +refs 4 +233 0.336751 0.8825 +252 0.349399 0.8825 +253 0.339048 0.6825 +234 0.325442 0.6825 +SURF 0x30 +mat 1 +refs 4 +234 0.325442 0.6825 +253 0.339048 0.6825 +254 0.326625 0.635 +235 0.311869 0.635 +SURF 0x30 +mat 1 +refs 4 +235 0.311869 0.635 +254 0.326625 0.635 +255 0.283153 0.555 +236 0.264361 0.555 +SURF 0x30 +mat 1 +refs 4 +236 0.264361 0.555 +255 0.283153 0.555 +256 0.244574 0.475 +237 0.222207 0.475 +SURF 0x30 +mat 1 +refs 4 +237 0.222207 0.475 +256 0.244574 0.475 +257 0.224518 0.3875 +238 0.198966 0.3875 +SURF 0x30 +mat 1 +refs 4 +238 0.198966 0.3875 +257 0.224518 0.3875 +258 0.200362 0.31 +239 0.172571 0.31 +SURF 0x30 +mat 1 +refs 4 +239 0.172571 0.31 +258 0.200362 0.31 +259 0.204387 0.247501 +240 0.17697 0.247501 +SURF 0x30 +mat 1 +refs 4 +240 0.17697 0.247501 +259 0.204387 0.247501 +260 0.212438 0.175 +241 0.185767 0.175 +SURF 0x30 +mat 1 +refs 4 +241 0.185767 0.175 +260 0.212438 0.175 +261 0.236594 0.105001 +242 0.212162 0.105001 +SURF 0x30 +mat 1 +refs 4 +242 0.212162 0.105001 +261 0.236594 0.105001 +262 0.298989 0.0549999 +243 0.280349 0.0549999 +SURF 0x30 +mat 1 +refs 4 +243 0.280349 0.0549999 +262 0.298989 0.0549999 +263 0.357362 0.0200004 +244 0.344133 0.0200004 +SURF 0x30 +mat 1 +refs 4 +244 0.344133 0.0200004 +263 0.357362 0.0200004 +264 0.443914 0 +245 0.438711 0 +SURF 0x30 +mat 1 +refs 4 +245 0.438711 0 +264 0.443914 0 +265 0.496247 0 +246 0.495901 0 +SURF 0x30 +mat 1 +refs 4 +247 0.477751 1 +266 0.478535 1 +267 0.454254 0.994999 +248 0.450838 0.994999 +SURF 0x30 +mat 1 +refs 4 +248 0.450838 0.994999 +267 0.454254 0.994999 +268 0.43371 0.984998 +249 0.428064 0.984998 +SURF 0x30 +mat 1 +refs 4 +249 0.428064 0.984998 +268 0.43371 0.984998 +269 0.38702 0.952498 +250 0.376312 0.952498 +SURF 0x30 +mat 1 +refs 4 +250 0.376312 0.952498 +269 0.38702 0.952498 +270 0.373945 0.929999 +251 0.361818 0.929999 +SURF 0x30 +mat 1 +refs 4 +251 0.361818 0.929999 +270 0.373945 0.929999 +271 0.36274 0.8825 +252 0.349399 0.8825 +SURF 0x30 +mat 1 +refs 4 +252 0.349399 0.8825 +271 0.36274 0.8825 +272 0.353401 0.6825 +253 0.339048 0.6825 +SURF 0x30 +mat 1 +refs 4 +253 0.339048 0.6825 +272 0.353401 0.6825 +273 0.342196 0.635 +254 0.326625 0.635 +SURF 0x30 +mat 1 +refs 4 +254 0.326625 0.635 +273 0.342196 0.635 +274 0.302978 0.555 +255 0.283153 0.555 +SURF 0x30 +mat 1 +refs 4 +255 0.283153 0.555 +274 0.302978 0.555 +275 0.268175 0.475 +256 0.244574 0.475 +SURF 0x30 +mat 1 +refs 4 +256 0.244574 0.475 +275 0.268175 0.475 +276 0.251471 0.3875 +257 0.224518 0.3875 +SURF 0x30 +mat 1 +refs 4 +257 0.224518 0.3875 +276 0.251471 0.3875 +277 0.22968 0.31 +258 0.200362 0.31 +SURF 0x30 +mat 1 +refs 4 +258 0.200362 0.31 +277 0.22968 0.31 +278 0.233312 0.247501 +259 0.204387 0.247501 +SURF 0x30 +mat 1 +refs 4 +259 0.204387 0.247501 +278 0.233312 0.247501 +279 0.240575 0.175 +260 0.212438 0.175 +SURF 0x30 +mat 1 +refs 4 +260 0.212438 0.175 +279 0.240575 0.175 +280 0.262367 0.105001 +261 0.236594 0.105001 +SURF 0x30 +mat 1 +refs 4 +261 0.236594 0.105001 +280 0.262367 0.105001 +281 0.318659 0.0549999 +262 0.298989 0.0549999 +SURF 0x30 +mat 1 +refs 4 +262 0.298989 0.0549999 +281 0.318659 0.0549999 +282 0.371318 0.0200004 +263 0.357362 0.0200004 +SURF 0x30 +mat 1 +refs 4 +263 0.357362 0.0200004 +282 0.371318 0.0200004 +283 0.449402 0 +264 0.443914 0 +SURF 0x30 +mat 1 +refs 4 +264 0.443914 0 +283 0.449402 0 +284 0.496614 0 +265 0.496247 0 +SURF 0x30 +mat 1 +refs 4 +266 0.478535 1 +285 0.479352 1 +286 0.457829 0.994999 +267 0.454254 0.994999 +SURF 0x30 +mat 1 +refs 4 +267 0.454254 0.994999 +286 0.457829 0.994999 +287 0.439619 0.984998 +268 0.43371 0.984998 +SURF 0x30 +mat 1 +refs 4 +268 0.43371 0.984998 +287 0.439619 0.984998 +288 0.398232 0.952498 +269 0.38702 0.952498 +SURF 0x30 +mat 1 +refs 4 +269 0.38702 0.952498 +288 0.398232 0.952498 +289 0.386643 0.929999 +270 0.373945 0.929999 +SURF 0x30 +mat 1 +refs 4 +270 0.373945 0.929999 +289 0.386643 0.929999 +290 0.376709 0.8825 +271 0.36274 0.8825 +SURF 0x30 +mat 1 +refs 4 +271 0.36274 0.8825 +290 0.376709 0.8825 +291 0.36843 0.6825 +272 0.353401 0.6825 +SURF 0x30 +mat 1 +refs 4 +272 0.353401 0.6825 +291 0.36843 0.6825 +292 0.358496 0.635 +273 0.342196 0.635 +SURF 0x30 +mat 1 +refs 4 +273 0.342196 0.635 +292 0.358496 0.635 +293 0.32373 0.555 +274 0.302978 0.555 +SURF 0x30 +mat 1 +refs 4 +274 0.302978 0.555 +293 0.32373 0.555 +294 0.292879 0.475 +275 0.268175 0.475 +SURF 0x30 +mat 1 +refs 4 +275 0.268175 0.475 +294 0.292879 0.475 +295 0.279693 0.3875 +276 0.251471 0.3875 +SURF 0x30 +mat 1 +refs 4 +276 0.251471 0.3875 +295 0.279693 0.3875 +296 0.260376 0.31 +277 0.22968 0.31 +SURF 0x30 +mat 1 +refs 4 +277 0.22968 0.31 +296 0.260376 0.31 +297 0.263595 0.247501 +278 0.233312 0.247501 +SURF 0x30 +mat 1 +refs 4 +278 0.233312 0.247501 +297 0.263595 0.247501 +298 0.270035 0.175 +279 0.240575 0.175 +SURF 0x30 +mat 1 +refs 4 +279 0.240575 0.175 +298 0.270035 0.175 +299 0.289351 0.105001 +280 0.262367 0.105001 +SURF 0x30 +mat 1 +refs 4 +280 0.262367 0.105001 +299 0.289351 0.105001 +300 0.33925 0.0549999 +281 0.318659 0.0549999 +SURF 0x30 +mat 1 +refs 4 +281 0.318659 0.0549999 +300 0.33925 0.0549999 +301 0.38593 0.0200004 +282 0.371318 0.0200004 +SURF 0x30 +mat 1 +refs 4 +282 0.371318 0.0200004 +301 0.38593 0.0200004 +302 0.455149 0 +283 0.449402 0 +SURF 0x30 +mat 1 +refs 4 +283 0.449402 0 +302 0.455149 0 +303 0.497 0 +284 0.496614 0 +SURF 0x30 +mat 1 +refs 4 +285 0.479352 1 +304 0.480206 1 +305 0.461549 0.994999 +286 0.457829 0.994999 +SURF 0x30 +mat 1 +refs 4 +286 0.457829 0.994999 +305 0.461549 0.994999 +306 0.445763 0.984998 +287 0.439619 0.984998 +SURF 0x30 +mat 1 +refs 4 +287 0.439619 0.984998 +306 0.445763 0.984998 +307 0.409888 0.952498 +288 0.398232 0.952498 +SURF 0x30 +mat 1 +refs 4 +288 0.398232 0.952498 +307 0.409888 0.952498 +308 0.399843 0.929999 +289 0.386643 0.929999 +SURF 0x30 +mat 1 +refs 4 +289 0.386643 0.929999 +308 0.399843 0.929999 +309 0.391234 0.8825 +290 0.376709 0.8825 +SURF 0x30 +mat 1 +refs 4 +290 0.376709 0.8825 +309 0.391234 0.8825 +310 0.384057 0.6825 +291 0.36843 0.6825 +SURF 0x30 +mat 1 +refs 4 +291 0.36843 0.6825 +310 0.384057 0.6825 +311 0.375448 0.635 +292 0.358496 0.635 +SURF 0x30 +mat 1 +refs 4 +292 0.358496 0.635 +311 0.375448 0.635 +312 0.34531 0.555 +293 0.32373 0.555 +SURF 0x30 +mat 1 +refs 4 +293 0.32373 0.555 +312 0.34531 0.555 +313 0.318571 0.475 +294 0.292879 0.475 +SURF 0x30 +mat 1 +refs 4 +294 0.292879 0.475 +313 0.318571 0.475 +314 0.309037 0.3875 +295 0.279693 0.3875 +SURF 0x30 +mat 1 +refs 4 +295 0.279693 0.3875 +314 0.309037 0.3875 +315 0.292294 0.31 +296 0.260376 0.31 +SURF 0x30 +mat 1 +refs 4 +296 0.260376 0.31 +315 0.292294 0.31 +316 0.295085 0.247501 +297 0.263595 0.247501 +SURF 0x30 +mat 1 +refs 4 +297 0.263595 0.247501 +316 0.295085 0.247501 +317 0.300664 0.175 +298 0.270035 0.175 +SURF 0x30 +mat 1 +refs 4 +298 0.270035 0.175 +317 0.300664 0.175 +318 0.317408 0.105001 +299 0.289351 0.105001 +SURF 0x30 +mat 1 +refs 4 +299 0.289351 0.105001 +318 0.317408 0.105001 +319 0.360661 0.0549999 +300 0.33925 0.0549999 +SURF 0x30 +mat 1 +refs 4 +300 0.33925 0.0549999 +319 0.360661 0.0549999 +320 0.401124 0.0200004 +301 0.38593 0.0200004 +SURF 0x30 +mat 1 +refs 4 +301 0.38593 0.0200004 +320 0.401124 0.0200004 +321 0.461121 0 +302 0.455149 0 +SURF 0x30 +mat 1 +refs 4 +302 0.455149 0 +321 0.461121 0 +322 0.4974 0 +303 0.497 0 +SURF 0x30 +mat 1 +refs 4 +304 0.480206 1 +323 0.481087 1 +324 0.465392 0.994999 +305 0.461549 0.994999 +SURF 0x30 +mat 1 +refs 4 +305 0.461549 0.994999 +324 0.465392 0.994999 +325 0.452112 0.984998 +306 0.445763 0.984998 +SURF 0x30 +mat 1 +refs 4 +306 0.445763 0.984998 +325 0.452112 0.984998 +326 0.42193 0.952498 +307 0.409888 0.952498 +SURF 0x30 +mat 1 +refs 4 +307 0.409888 0.952498 +326 0.42193 0.952498 +327 0.413483 0.929999 +308 0.399843 0.929999 +SURF 0x30 +mat 1 +refs 4 +308 0.399843 0.929999 +327 0.413483 0.929999 +328 0.406239 0.8825 +309 0.391234 0.8825 +SURF 0x30 +mat 1 +refs 4 +309 0.391234 0.8825 +328 0.406239 0.8825 +329 0.400202 0.6825 +310 0.384057 0.6825 +SURF 0x30 +mat 1 +refs 4 +310 0.384057 0.6825 +329 0.400202 0.6825 +330 0.392959 0.635 +311 0.375448 0.635 +SURF 0x30 +mat 1 +refs 4 +311 0.375448 0.635 +330 0.392959 0.635 +331 0.367606 0.555 +312 0.34531 0.555 +SURF 0x30 +mat 1 +refs 4 +312 0.34531 0.555 +331 0.367606 0.555 +332 0.345111 0.475 +313 0.318571 0.475 +SURF 0x30 +mat 1 +refs 4 +313 0.318571 0.475 +332 0.345111 0.475 +333 0.339354 0.3875 +314 0.309037 0.3875 +SURF 0x30 +mat 1 +refs 4 +314 0.309037 0.3875 +333 0.339354 0.3875 +334 0.32527 0.31 +315 0.292294 0.31 +SURF 0x30 +mat 1 +refs 4 +315 0.292294 0.31 +334 0.32527 0.31 +335 0.327618 0.247501 +316 0.295085 0.247501 +SURF 0x30 +mat 1 +refs 4 +316 0.295085 0.247501 +335 0.327618 0.247501 +336 0.332312 0.175 +317 0.300664 0.175 +SURF 0x30 +mat 1 +refs 4 +317 0.300664 0.175 +336 0.332312 0.175 +337 0.346396 0.105001 +318 0.317408 0.105001 +SURF 0x30 +mat 1 +refs 4 +318 0.317408 0.105001 +337 0.346396 0.105001 +338 0.382783 0.0549999 +319 0.360661 0.0549999 +SURF 0x30 +mat 1 +refs 4 +319 0.360661 0.0549999 +338 0.382783 0.0549999 +339 0.416822 0.0200004 +320 0.401124 0.0200004 +SURF 0x30 +mat 1 +refs 4 +320 0.401124 0.0200004 +339 0.416822 0.0200004 +340 0.467292 0 +321 0.461121 0 +SURF 0x30 +mat 1 +refs 4 +321 0.461121 0 +340 0.467292 0 +341 0.497811 0 +322 0.4974 0 +SURF 0x30 +mat 1 +refs 4 +323 0.481087 1 +342 0.481988 1 +343 0.469337 0.994999 +324 0.465392 0.994999 +SURF 0x30 +mat 1 +refs 4 +324 0.465392 0.994999 +343 0.469337 0.994999 +344 0.458633 0.984998 +325 0.452112 0.984998 +SURF 0x30 +mat 1 +refs 4 +325 0.452112 0.984998 +344 0.458633 0.984998 +345 0.434302 0.952498 +326 0.42193 0.952498 +SURF 0x30 +mat 1 +refs 4 +326 0.42193 0.952498 +345 0.434302 0.952498 +346 0.427489 0.929999 +327 0.413483 0.929999 +SURF 0x30 +mat 1 +refs 4 +327 0.413483 0.929999 +346 0.427489 0.929999 +347 0.421648 0.8825 +328 0.406239 0.8825 +SURF 0x30 +mat 1 +refs 4 +328 0.406239 0.8825 +347 0.421648 0.8825 +348 0.416782 0.6825 +329 0.400202 0.6825 +SURF 0x30 +mat 1 +refs 4 +329 0.400202 0.6825 +348 0.416782 0.6825 +349 0.410944 0.635 +330 0.392959 0.635 +SURF 0x30 +mat 1 +refs 4 +330 0.392959 0.635 +349 0.410944 0.635 +350 0.390504 0.555 +331 0.367606 0.555 +SURF 0x30 +mat 1 +refs 4 +331 0.367606 0.555 +350 0.390504 0.555 +351 0.372371 0.475 +332 0.345111 0.475 +SURF 0x30 +mat 1 +refs 4 +332 0.345111 0.475 +351 0.372371 0.475 +352 0.370491 0.3875 +333 0.339354 0.3875 +SURF 0x30 +mat 1 +refs 4 +333 0.339354 0.3875 +352 0.370491 0.3875 +353 0.359135 0.31 +334 0.32527 0.31 +SURF 0x30 +mat 1 +refs 4 +334 0.32527 0.31 +353 0.359135 0.31 +354 0.361028 0.247501 +335 0.327618 0.247501 +SURF 0x30 +mat 1 +refs 4 +335 0.327618 0.247501 +354 0.361028 0.247501 +355 0.364811 0.175 +336 0.332312 0.175 +SURF 0x30 +mat 1 +refs 4 +336 0.332312 0.175 +355 0.364811 0.175 +356 0.376168 0.105001 +337 0.346396 0.105001 +SURF 0x30 +mat 1 +refs 4 +337 0.346396 0.105001 +356 0.376168 0.105001 +357 0.405502 0.0549999 +338 0.382783 0.0549999 +SURF 0x30 +mat 1 +refs 4 +338 0.382783 0.0549999 +357 0.405502 0.0549999 +358 0.432944 0.0200004 +339 0.416822 0.0200004 +SURF 0x30 +mat 1 +refs 4 +339 0.416822 0.0200004 +358 0.432944 0.0200004 +359 0.473631 0 +340 0.467292 0 +SURF 0x30 +mat 1 +refs 4 +340 0.467292 0 +359 0.473631 0 +360 0.498235 0 +341 0.497811 0 +SURF 0x30 +mat 1 +refs 4 +342 0.481988 1 +361 0.482913 1 +362 0.473366 0.994999 +343 0.469337 0.994999 +SURF 0x30 +mat 1 +refs 4 +343 0.469337 0.994999 +362 0.473366 0.994999 +363 0.465291 0.984998 +344 0.458633 0.984998 +SURF 0x30 +mat 1 +refs 4 +344 0.458633 0.984998 +363 0.465291 0.984998 +364 0.446933 0.952498 +345 0.434302 0.952498 +SURF 0x30 +mat 1 +refs 4 +345 0.434302 0.952498 +364 0.446933 0.952498 +365 0.441792 0.929999 +346 0.427489 0.929999 +SURF 0x30 +mat 1 +refs 4 +346 0.427489 0.929999 +365 0.441792 0.929999 +366 0.437386 0.8825 +347 0.421648 0.8825 +SURF 0x30 +mat 1 +refs 4 +347 0.421648 0.8825 +366 0.437386 0.8825 +367 0.433714 0.6825 +348 0.416782 0.6825 +SURF 0x30 +mat 1 +refs 4 +348 0.416782 0.6825 +367 0.433714 0.6825 +368 0.429308 0.635 +349 0.410944 0.635 +SURF 0x30 +mat 1 +refs 4 +349 0.410944 0.635 +368 0.429308 0.635 +369 0.413889 0.555 +350 0.390504 0.555 +SURF 0x30 +mat 1 +refs 4 +350 0.390504 0.555 +369 0.413889 0.555 +370 0.400206 0.475 +351 0.372371 0.475 +SURF 0x30 +mat 1 +refs 4 +351 0.372371 0.475 +370 0.400206 0.475 +371 0.402284 0.3875 +352 0.370491 0.3875 +SURF 0x30 +mat 1 +refs 4 +352 0.370491 0.3875 +371 0.402284 0.3875 +372 0.393719 0.31 +353 0.359135 0.31 +SURF 0x30 +mat 1 +refs 4 +353 0.359135 0.31 +372 0.393719 0.31 +373 0.395145 0.247501 +354 0.361028 0.247501 +SURF 0x30 +mat 1 +refs 4 +354 0.361028 0.247501 +373 0.395145 0.247501 +374 0.398003 0.175 +355 0.364811 0.175 +SURF 0x30 +mat 1 +refs 4 +355 0.364811 0.175 +374 0.398003 0.175 +375 0.406568 0.105001 +356 0.376168 0.105001 +SURF 0x30 +mat 1 +refs 4 +356 0.376168 0.105001 +375 0.406568 0.105001 +376 0.428703 0.0549999 +357 0.405502 0.0549999 +SURF 0x30 +mat 1 +refs 4 +357 0.405502 0.0549999 +376 0.428703 0.0549999 +377 0.449405 0.0200004 +358 0.432944 0.0200004 +SURF 0x30 +mat 1 +refs 4 +358 0.432944 0.0200004 +377 0.449405 0.0200004 +378 0.480105 0 +359 0.473631 0 +SURF 0x30 +mat 1 +refs 4 +359 0.473631 0 +378 0.480105 0 +379 0.498668 0 +360 0.498235 0 +SURF 0x30 +mat 1 +refs 4 +361 0.482913 1 +380 0.483851 1 +381 0.477458 0.994999 +362 0.473366 0.994999 +SURF 0x30 +mat 1 +refs 4 +362 0.473366 0.994999 +381 0.477458 0.994999 +382 0.472051 0.984998 +363 0.465291 0.984998 +SURF 0x30 +mat 1 +refs 4 +363 0.465291 0.984998 +382 0.472051 0.984998 +383 0.459763 0.952498 +364 0.446933 0.952498 +SURF 0x30 +mat 1 +refs 4 +364 0.446933 0.952498 +383 0.459763 0.952498 +384 0.456319 0.929999 +365 0.441792 0.929999 +SURF 0x30 +mat 1 +refs 4 +365 0.441792 0.929999 +384 0.456319 0.929999 +385 0.45337 0.8825 +366 0.437386 0.8825 +SURF 0x30 +mat 1 +refs 4 +366 0.437386 0.8825 +385 0.45337 0.8825 +386 0.450912 0.6825 +367 0.433714 0.6825 +SURF 0x30 +mat 1 +refs 4 +367 0.433714 0.6825 +386 0.450912 0.6825 +387 0.447962 0.635 +368 0.429308 0.635 +SURF 0x30 +mat 1 +refs 4 +368 0.429308 0.635 +387 0.447962 0.635 +388 0.437638 0.555 +369 0.413889 0.555 +SURF 0x30 +mat 1 +refs 4 +369 0.413889 0.555 +388 0.437638 0.555 +389 0.428478 0.475 +370 0.400206 0.475 +SURF 0x30 +mat 1 +refs 4 +370 0.400206 0.475 +389 0.428478 0.475 +390 0.434578 0.3875 +371 0.402284 0.3875 +SURF 0x30 +mat 1 +refs 4 +371 0.402284 0.3875 +390 0.434578 0.3875 +391 0.428844 0.31 +372 0.393719 0.31 +SURF 0x30 +mat 1 +refs 4 +372 0.393719 0.31 +391 0.428844 0.31 +392 0.429799 0.247501 +373 0.395145 0.247501 +SURF 0x30 +mat 1 +refs 4 +373 0.395145 0.247501 +392 0.429799 0.247501 +393 0.431713 0.175 +374 0.398003 0.175 +SURF 0x30 +mat 1 +refs 4 +374 0.398003 0.175 +393 0.431713 0.175 +394 0.437447 0.105001 +375 0.406568 0.105001 +SURF 0x30 +mat 1 +refs 4 +375 0.406568 0.105001 +394 0.437447 0.105001 +395 0.452267 0.0549999 +376 0.428703 0.0549999 +SURF 0x30 +mat 1 +refs 4 +376 0.428703 0.0549999 +395 0.452267 0.0549999 +396 0.466129 0.0200004 +377 0.449405 0.0200004 +SURF 0x30 +mat 1 +refs 4 +377 0.449405 0.0200004 +396 0.466129 0.0200004 +397 0.486683 0 +378 0.480105 0 +SURF 0x30 +mat 1 +refs 4 +378 0.480105 0 +397 0.486683 0 +398 0.499109 0 +379 0.498668 0 +SURF 0x30 +mat 1 +refs 4 +380 0.483851 1 +399 0.4848 1 +400 0.481595 0.994999 +381 0.477458 0.994999 +SURF 0x30 +mat 1 +refs 4 +381 0.477458 0.994999 +400 0.481595 0.994999 +401 0.478884 0.984998 +382 0.472051 0.984998 +SURF 0x30 +mat 1 +refs 4 +382 0.472051 0.984998 +401 0.478884 0.984998 +402 0.472724 0.952498 +383 0.459763 0.952498 +SURF 0x30 +mat 1 +refs 4 +383 0.459763 0.952498 +402 0.472724 0.952498 +403 0.470998 0.929999 +384 0.456319 0.929999 +SURF 0x30 +mat 1 +refs 4 +384 0.456319 0.929999 +403 0.470998 0.929999 +404 0.469519 0.8825 +385 0.45337 0.8825 +SURF 0x30 +mat 1 +refs 4 +385 0.45337 0.8825 +404 0.469519 0.8825 +405 0.468288 0.6825 +386 0.450912 0.6825 +SURF 0x30 +mat 1 +refs 4 +386 0.450912 0.6825 +405 0.468288 0.6825 +406 0.466808 0.635 +387 0.447962 0.635 +SURF 0x30 +mat 1 +refs 4 +387 0.447962 0.635 +406 0.466808 0.635 +407 0.461633 0.555 +388 0.437638 0.555 +SURF 0x30 +mat 1 +refs 4 +388 0.437638 0.555 +407 0.461633 0.555 +408 0.457042 0.475 +389 0.428478 0.475 +SURF 0x30 +mat 1 +refs 4 +389 0.428478 0.475 +408 0.457042 0.475 +409 0.467205 0.3875 +390 0.434578 0.3875 +SURF 0x30 +mat 1 +refs 4 +390 0.434578 0.3875 +409 0.467205 0.3875 +410 0.46433 0.31 +391 0.428844 0.31 +SURF 0x30 +mat 1 +refs 4 +391 0.428844 0.31 +410 0.46433 0.31 +411 0.464811 0.247501 +392 0.429799 0.247501 +SURF 0x30 +mat 1 +refs 4 +392 0.429799 0.247501 +411 0.464811 0.247501 +412 0.465769 0.175 +393 0.431713 0.175 +SURF 0x30 +mat 1 +refs 4 +393 0.431713 0.175 +412 0.465769 0.175 +413 0.468644 0.105001 +394 0.437447 0.105001 +SURF 0x30 +mat 1 +refs 4 +394 0.437447 0.105001 +413 0.468644 0.105001 +414 0.476073 0.0549999 +395 0.452267 0.0549999 +SURF 0x30 +mat 1 +refs 4 +395 0.452267 0.0549999 +414 0.476073 0.0549999 +415 0.483021 0.0200004 +396 0.466129 0.0200004 +SURF 0x30 +mat 1 +refs 4 +396 0.466129 0.0200004 +415 0.483021 0.0200004 +416 0.493325 0 +397 0.486683 0 +SURF 0x30 +mat 1 +refs 4 +397 0.486683 0 +416 0.493325 0 +417 0.499553 0 +398 0.499109 0 +SURF 0x30 +mat 1 +refs 4 +399 0.4848 1 +418 0.485751 1 +419 0.485751 0.994999 +400 0.481595 0.994999 +SURF 0x30 +mat 1 +refs 4 +400 0.481595 0.994999 +419 0.485751 0.994999 +420 0.485751 0.984998 +401 0.478884 0.984998 +SURF 0x30 +mat 1 +refs 4 +401 0.478884 0.984998 +420 0.485751 0.984998 +421 0.485751 0.952498 +402 0.472724 0.952498 +SURF 0x30 +mat 1 +refs 4 +402 0.472724 0.952498 +421 0.485751 0.952498 +422 0.485751 0.929999 +403 0.470998 0.929999 +SURF 0x30 +mat 1 +refs 4 +403 0.470998 0.929999 +422 0.485751 0.929999 +423 0.485751 0.8825 +404 0.469519 0.8825 +SURF 0x30 +mat 1 +refs 4 +404 0.469519 0.8825 +423 0.485751 0.8825 +424 0.485751 0.6825 +405 0.468288 0.6825 +SURF 0x30 +mat 1 +refs 4 +405 0.468288 0.6825 +424 0.485751 0.6825 +425 0.485751 0.635 +406 0.466808 0.635 +SURF 0x30 +mat 1 +refs 4 +406 0.466808 0.635 +425 0.485751 0.635 +426 0.485751 0.555 +407 0.461633 0.555 +SURF 0x30 +mat 1 +refs 4 +407 0.461633 0.555 +426 0.485751 0.555 +427 0.485751 0.475 +408 0.457042 0.475 +SURF 0x30 +mat 1 +refs 4 +408 0.457042 0.475 +427 0.485751 0.475 +428 0.5 0.3875 +409 0.467205 0.3875 +SURF 0x30 +mat 1 +refs 4 +409 0.467205 0.3875 +428 0.5 0.3875 +429 0.5 0.31 +410 0.46433 0.31 +SURF 0x30 +mat 1 +refs 4 +410 0.46433 0.31 +429 0.5 0.31 +430 0.5 0.247501 +411 0.464811 0.247501 +SURF 0x30 +mat 1 +refs 4 +411 0.464811 0.247501 +430 0.5 0.247501 +431 0.5 0.175 +412 0.465769 0.175 +SURF 0x30 +mat 1 +refs 4 +412 0.465769 0.175 +431 0.5 0.175 +432 0.5 0.105001 +413 0.468644 0.105001 +SURF 0x30 +mat 1 +refs 4 +413 0.468644 0.105001 +432 0.5 0.105001 +433 0.5 0.0549999 +414 0.476073 0.0549999 +SURF 0x30 +mat 1 +refs 4 +414 0.476073 0.0549999 +433 0.5 0.0549999 +434 0.5 0.0200004 +415 0.483021 0.0200004 +SURF 0x30 +mat 1 +refs 4 +415 0.483021 0.0200004 +434 0.5 0.0200004 +435 0.5 0 +416 0.493325 0 +SURF 0x30 +mat 1 +refs 4 +416 0.493325 0 +435 0.5 0 +436 0.5 0 +417 0.499553 0 +SURF 0x30 +mat 1 +refs 4 +418 0.485751 1 +437 0.486703 1 +438 0.489908 0.994999 +419 0.485751 0.994999 +SURF 0x30 +mat 1 +refs 4 +419 0.485751 0.994999 +438 0.489908 0.994999 +439 0.492618 0.984998 +420 0.485751 0.984998 +SURF 0x30 +mat 1 +refs 4 +420 0.485751 0.984998 +439 0.492618 0.984998 +440 0.498779 0.952498 +421 0.485751 0.952498 +SURF 0x30 +mat 1 +refs 4 +421 0.485751 0.952498 +440 0.498779 0.952498 +441 0.500504 0.929999 +422 0.485751 0.929999 +SURF 0x30 +mat 1 +refs 4 +422 0.485751 0.929999 +441 0.500504 0.929999 +442 0.501984 0.8825 +423 0.485751 0.8825 +SURF 0x30 +mat 1 +refs 4 +423 0.485751 0.8825 +442 0.501984 0.8825 +443 0.503215 0.6825 +424 0.485751 0.6825 +SURF 0x30 +mat 1 +refs 4 +424 0.485751 0.6825 +443 0.503215 0.6825 +444 0.504695 0.635 +425 0.485751 0.635 +SURF 0x30 +mat 1 +refs 4 +425 0.485751 0.635 +444 0.504695 0.635 +445 0.50987 0.555 +426 0.485751 0.555 +SURF 0x30 +mat 1 +refs 4 +426 0.485751 0.555 +445 0.50987 0.555 +446 0.514461 0.475 +427 0.485751 0.475 +SURF 0x30 +mat 1 +refs 4 +427 0.485751 0.475 +446 0.514461 0.475 +447 0.532795 0.3875 +428 0.5 0.3875 +SURF 0x30 +mat 1 +refs 4 +428 0.5 0.3875 +447 0.532795 0.3875 +448 0.53567 0.31 +429 0.5 0.31 +SURF 0x30 +mat 1 +refs 4 +429 0.5 0.31 +448 0.53567 0.31 +449 0.535189 0.247501 +430 0.5 0.247501 +SURF 0x30 +mat 1 +refs 4 +430 0.5 0.247501 +449 0.535189 0.247501 +450 0.534231 0.175 +431 0.5 0.175 +SURF 0x30 +mat 1 +refs 4 +431 0.5 0.175 +450 0.534231 0.175 +451 0.531356 0.105001 +432 0.5 0.105001 +SURF 0x30 +mat 1 +refs 4 +432 0.5 0.105001 +451 0.531356 0.105001 +452 0.52393 0.0549999 +433 0.5 0.0549999 +SURF 0x30 +mat 1 +refs 4 +433 0.5 0.0549999 +452 0.52393 0.0549999 +453 0.516979 0.0200004 +434 0.5 0.0200004 +SURF 0x30 +mat 1 +refs 4 +434 0.5 0.0200004 +453 0.516979 0.0200004 +454 0.506679 0 +435 0.5 0 +SURF 0x30 +mat 1 +refs 4 +435 0.5 0 +454 0.506679 0 +455 0.500447 0 +436 0.5 0 +SURF 0x30 +mat 1 +refs 4 +437 0.486703 1 +456 0.487651 1 +457 0.494041 0.994999 +438 0.489908 0.994999 +SURF 0x30 +mat 1 +refs 4 +438 0.489908 0.994999 +457 0.494041 0.994999 +458 0.499449 0.984998 +439 0.492618 0.984998 +SURF 0x30 +mat 1 +refs 4 +439 0.492618 0.984998 +458 0.499449 0.984998 +459 0.51174 0.952498 +440 0.498779 0.952498 +SURF 0x30 +mat 1 +refs 4 +440 0.498779 0.952498 +459 0.51174 0.952498 +460 0.51518 0.929999 +441 0.500504 0.929999 +SURF 0x30 +mat 1 +refs 4 +441 0.500504 0.929999 +460 0.51518 0.929999 +461 0.518133 0.8825 +442 0.501984 0.8825 +SURF 0x30 +mat 1 +refs 4 +442 0.501984 0.8825 +461 0.518133 0.8825 +462 0.520591 0.6825 +443 0.503215 0.6825 +SURF 0x30 +mat 1 +refs 4 +443 0.503215 0.6825 +462 0.520591 0.6825 +463 0.52354 0.635 +444 0.504695 0.635 +SURF 0x30 +mat 1 +refs 4 +444 0.504695 0.635 +463 0.52354 0.635 +464 0.533864 0.555 +445 0.50987 0.555 +SURF 0x30 +mat 1 +refs 4 +445 0.50987 0.555 +464 0.533864 0.555 +465 0.543025 0.475 +446 0.514461 0.475 +SURF 0x30 +mat 1 +refs 4 +446 0.514461 0.475 +465 0.543025 0.475 +466 0.565422 0.3875 +447 0.532795 0.3875 +SURF 0x30 +mat 1 +refs 4 +447 0.532795 0.3875 +466 0.565422 0.3875 +467 0.571159 0.31 +448 0.53567 0.31 +SURF 0x30 +mat 1 +refs 4 +448 0.53567 0.31 +467 0.571159 0.31 +468 0.570201 0.247501 +449 0.535189 0.247501 +SURF 0x30 +mat 1 +refs 4 +449 0.535189 0.247501 +468 0.570201 0.247501 +469 0.568291 0.175 +450 0.534231 0.175 +SURF 0x30 +mat 1 +refs 4 +450 0.534231 0.175 +469 0.568291 0.175 +470 0.562553 0.105001 +451 0.531356 0.105001 +SURF 0x30 +mat 1 +refs 4 +451 0.531356 0.105001 +470 0.562553 0.105001 +471 0.547736 0.0549999 +452 0.52393 0.0549999 +SURF 0x30 +mat 1 +refs 4 +452 0.52393 0.0549999 +471 0.547736 0.0549999 +472 0.533875 0.0200004 +453 0.516979 0.0200004 +SURF 0x30 +mat 1 +refs 4 +453 0.516979 0.0200004 +472 0.533875 0.0200004 +473 0.513321 0 +454 0.506679 0 +SURF 0x30 +mat 1 +refs 4 +454 0.506679 0 +473 0.513321 0 +474 0.500891 0 +455 0.500447 0 +SURF 0x30 +mat 1 +refs 4 +456 0.487651 1 +475 0.48859 1 +476 0.498134 0.994999 +457 0.494041 0.994999 +SURF 0x30 +mat 1 +refs 4 +457 0.494041 0.994999 +476 0.498134 0.994999 +477 0.506211 0.984998 +458 0.499449 0.984998 +SURF 0x30 +mat 1 +refs 4 +458 0.499449 0.984998 +477 0.506211 0.984998 +478 0.524569 0.952498 +459 0.51174 0.952498 +SURF 0x30 +mat 1 +refs 4 +459 0.51174 0.952498 +478 0.524569 0.952498 +479 0.529708 0.929999 +460 0.51518 0.929999 +SURF 0x30 +mat 1 +refs 4 +460 0.51518 0.929999 +479 0.529708 0.929999 +480 0.534117 0.8825 +461 0.518133 0.8825 +SURF 0x30 +mat 1 +refs 4 +461 0.518133 0.8825 +480 0.534117 0.8825 +481 0.537786 0.6825 +462 0.520591 0.6825 +SURF 0x30 +mat 1 +refs 4 +462 0.520591 0.6825 +481 0.537786 0.6825 +482 0.542191 0.635 +463 0.52354 0.635 +SURF 0x30 +mat 1 +refs 4 +463 0.52354 0.635 +482 0.542191 0.635 +483 0.557613 0.555 +464 0.533864 0.555 +SURF 0x30 +mat 1 +refs 4 +464 0.533864 0.555 +483 0.557613 0.555 +484 0.571297 0.475 +465 0.543025 0.475 +SURF 0x30 +mat 1 +refs 4 +465 0.543025 0.475 +484 0.571297 0.475 +485 0.597716 0.3875 +466 0.565422 0.3875 +SURF 0x30 +mat 1 +refs 4 +466 0.565422 0.3875 +485 0.597716 0.3875 +486 0.606285 0.31 +467 0.571159 0.31 +SURF 0x30 +mat 1 +refs 4 +467 0.571159 0.31 +486 0.606285 0.31 +487 0.604855 0.247501 +468 0.570201 0.247501 +SURF 0x30 +mat 1 +refs 4 +468 0.570201 0.247501 +487 0.604855 0.247501 +488 0.602 0.175 +469 0.568291 0.175 +SURF 0x30 +mat 1 +refs 4 +469 0.568291 0.175 +488 0.602 0.175 +489 0.593432 0.105001 +470 0.562553 0.105001 +SURF 0x30 +mat 1 +refs 4 +470 0.562553 0.105001 +489 0.593432 0.105001 +490 0.5713 0.0549999 +471 0.547736 0.0549999 +SURF 0x30 +mat 1 +refs 4 +471 0.547736 0.0549999 +490 0.5713 0.0549999 +491 0.550595 0.0200004 +472 0.533875 0.0200004 +SURF 0x30 +mat 1 +refs 4 +472 0.533875 0.0200004 +491 0.550595 0.0200004 +492 0.519895 0 +473 0.513321 0 +SURF 0x30 +mat 1 +refs 4 +473 0.513321 0 +492 0.519895 0 +493 0.501332 0 +474 0.500891 0 +SURF 0x30 +mat 1 +refs 4 +475 0.48859 1 +494 0.489511 1 +495 0.502166 0.994999 +476 0.498134 0.994999 +SURF 0x30 +mat 1 +refs 4 +476 0.498134 0.994999 +495 0.502166 0.994999 +496 0.51287 0.984998 +477 0.506211 0.984998 +SURF 0x30 +mat 1 +refs 4 +477 0.506211 0.984998 +496 0.51287 0.984998 +497 0.537201 0.952498 +478 0.524569 0.952498 +SURF 0x30 +mat 1 +refs 4 +478 0.524569 0.952498 +497 0.537201 0.952498 +498 0.544014 0.929999 +479 0.529708 0.929999 +SURF 0x30 +mat 1 +refs 4 +479 0.529708 0.929999 +498 0.544014 0.929999 +499 0.549852 0.8825 +480 0.534117 0.8825 +SURF 0x30 +mat 1 +refs 4 +480 0.534117 0.8825 +499 0.549852 0.8825 +500 0.554718 0.6825 +481 0.537786 0.6825 +SURF 0x30 +mat 1 +refs 4 +481 0.537786 0.6825 +500 0.554718 0.6825 +501 0.560559 0.635 +482 0.542191 0.635 +SURF 0x30 +mat 1 +refs 4 +482 0.542191 0.635 +501 0.560559 0.635 +502 0.580996 0.555 +483 0.557613 0.555 +SURF 0x30 +mat 1 +refs 4 +483 0.557613 0.555 +502 0.580996 0.555 +503 0.599132 0.475 +484 0.571297 0.475 +SURF 0x30 +mat 1 +refs 4 +484 0.571297 0.475 +503 0.599132 0.475 +504 0.629512 0.3875 +485 0.597716 0.3875 +SURF 0x30 +mat 1 +refs 4 +485 0.597716 0.3875 +504 0.629512 0.3875 +505 0.640865 0.31 +486 0.606285 0.31 +SURF 0x30 +mat 1 +refs 4 +486 0.606285 0.31 +505 0.640865 0.31 +506 0.638975 0.247501 +487 0.604855 0.247501 +SURF 0x30 +mat 1 +refs 4 +487 0.604855 0.247501 +506 0.638975 0.247501 +507 0.635189 0.175 +488 0.602 0.175 +SURF 0x30 +mat 1 +refs 4 +488 0.602 0.175 +507 0.635189 0.175 +508 0.623832 0.105001 +489 0.593432 0.105001 +SURF 0x30 +mat 1 +refs 4 +489 0.593432 0.105001 +508 0.623832 0.105001 +509 0.594501 0.0549999 +490 0.5713 0.0549999 +SURF 0x30 +mat 1 +refs 4 +490 0.5713 0.0549999 +509 0.594501 0.0549999 +510 0.567056 0.0200004 +491 0.550595 0.0200004 +SURF 0x30 +mat 1 +refs 4 +491 0.550595 0.0200004 +510 0.567056 0.0200004 +511 0.526369 0 +492 0.519895 0 +SURF 0x30 +mat 1 +refs 4 +492 0.519895 0 +511 0.526369 0 +512 0.501766 0 +493 0.501332 0 +SURF 0x30 +mat 1 +refs 4 +494 0.489511 1 +513 0.490416 1 +514 0.50611 0.994999 +495 0.502166 0.994999 +SURF 0x30 +mat 1 +refs 4 +495 0.502166 0.994999 +514 0.50611 0.994999 +515 0.519391 0.984998 +496 0.51287 0.984998 +SURF 0x30 +mat 1 +refs 4 +496 0.51287 0.984998 +515 0.519391 0.984998 +516 0.549569 0.952498 +497 0.537201 0.952498 +SURF 0x30 +mat 1 +refs 4 +497 0.537201 0.952498 +516 0.549569 0.952498 +517 0.55802 0.929999 +498 0.544014 0.929999 +SURF 0x30 +mat 1 +refs 4 +498 0.544014 0.929999 +517 0.55802 0.929999 +518 0.565264 0.8825 +499 0.549852 0.8825 +SURF 0x30 +mat 1 +refs 4 +499 0.549852 0.8825 +518 0.565264 0.8825 +519 0.5713 0.6825 +500 0.554718 0.6825 +SURF 0x30 +mat 1 +refs 4 +500 0.554718 0.6825 +519 0.5713 0.6825 +520 0.578544 0.635 +501 0.560559 0.635 +SURF 0x30 +mat 1 +refs 4 +501 0.560559 0.635 +520 0.578544 0.635 +521 0.603894 0.555 +502 0.580996 0.555 +SURF 0x30 +mat 1 +refs 4 +502 0.580996 0.555 +521 0.603894 0.555 +522 0.626391 0.475 +503 0.599132 0.475 +SURF 0x30 +mat 1 +refs 4 +503 0.599132 0.475 +522 0.626391 0.475 +523 0.660646 0.3875 +504 0.629512 0.3875 +SURF 0x30 +mat 1 +refs 4 +504 0.629512 0.3875 +523 0.660646 0.3875 +524 0.674733 0.31 +505 0.640865 0.31 +SURF 0x30 +mat 1 +refs 4 +505 0.640865 0.31 +524 0.674733 0.31 +525 0.672386 0.247501 +506 0.638975 0.247501 +SURF 0x30 +mat 1 +refs 4 +506 0.638975 0.247501 +525 0.672386 0.247501 +526 0.667691 0.175 +507 0.635189 0.175 +SURF 0x30 +mat 1 +refs 4 +507 0.635189 0.175 +526 0.667691 0.175 +527 0.653604 0.105001 +508 0.623832 0.105001 +SURF 0x30 +mat 1 +refs 4 +508 0.623832 0.105001 +527 0.653604 0.105001 +528 0.617217 0.0549999 +509 0.594501 0.0549999 +SURF 0x30 +mat 1 +refs 4 +509 0.594501 0.0549999 +528 0.617217 0.0549999 +529 0.583178 0.0200004 +510 0.567056 0.0200004 +SURF 0x30 +mat 1 +refs 4 +510 0.567056 0.0200004 +529 0.583178 0.0200004 +530 0.532708 0 +511 0.526369 0 +SURF 0x30 +mat 1 +refs 4 +511 0.526369 0 +530 0.532708 0 +531 0.502189 0 +512 0.501766 0 +SURF 0x30 +mat 1 +refs 4 +513 0.490416 1 +532 0.491297 1 +533 0.509951 0.994999 +514 0.50611 0.994999 +SURF 0x30 +mat 1 +refs 4 +514 0.50611 0.994999 +533 0.509951 0.994999 +534 0.525736 0.984998 +515 0.519391 0.984998 +SURF 0x30 +mat 1 +refs 4 +515 0.519391 0.984998 +534 0.525736 0.984998 +535 0.561615 0.952498 +516 0.549569 0.952498 +SURF 0x30 +mat 1 +refs 4 +516 0.549569 0.952498 +535 0.561615 0.952498 +536 0.57166 0.929999 +517 0.55802 0.929999 +SURF 0x30 +mat 1 +refs 4 +517 0.55802 0.929999 +536 0.57166 0.929999 +537 0.580269 0.8825 +518 0.565264 0.8825 +SURF 0x30 +mat 1 +refs 4 +518 0.565264 0.8825 +537 0.580269 0.8825 +538 0.587446 0.6825 +519 0.5713 0.6825 +SURF 0x30 +mat 1 +refs 4 +519 0.5713 0.6825 +538 0.587446 0.6825 +539 0.596055 0.635 +520 0.578544 0.635 +SURF 0x30 +mat 1 +refs 4 +520 0.578544 0.635 +539 0.596055 0.635 +540 0.62619 0.555 +521 0.603894 0.555 +SURF 0x30 +mat 1 +refs 4 +521 0.603894 0.555 +540 0.62619 0.555 +541 0.652931 0.475 +522 0.626391 0.475 +SURF 0x30 +mat 1 +refs 4 +522 0.626391 0.475 +541 0.652931 0.475 +542 0.690966 0.3875 +523 0.660646 0.3875 +SURF 0x30 +mat 1 +refs 4 +523 0.660646 0.3875 +542 0.690966 0.3875 +543 0.707707 0.31 +524 0.674733 0.31 +SURF 0x30 +mat 1 +refs 4 +524 0.674733 0.31 +543 0.707707 0.31 +544 0.704919 0.247501 +525 0.672386 0.247501 +SURF 0x30 +mat 1 +refs 4 +525 0.672386 0.247501 +544 0.704919 0.247501 +545 0.699336 0.175 +526 0.667691 0.175 +SURF 0x30 +mat 1 +refs 4 +526 0.667691 0.175 +545 0.699336 0.175 +546 0.682592 0.105001 +527 0.653604 0.105001 +SURF 0x30 +mat 1 +refs 4 +527 0.653604 0.105001 +546 0.682592 0.105001 +547 0.639339 0.0549999 +528 0.617217 0.0549999 +SURF 0x30 +mat 1 +refs 4 +528 0.617217 0.0549999 +547 0.639339 0.0549999 +548 0.598876 0.0200004 +529 0.583178 0.0200004 +SURF 0x30 +mat 1 +refs 4 +529 0.583178 0.0200004 +548 0.598876 0.0200004 +549 0.538879 0 +530 0.532708 0 +SURF 0x30 +mat 1 +refs 4 +530 0.532708 0 +549 0.538879 0 +550 0.502603 0 +531 0.502189 0 +SURF 0x30 +mat 1 +refs 4 +532 0.491297 1 +551 0.492148 1 +552 0.51367 0.994999 +533 0.509951 0.994999 +SURF 0x30 +mat 1 +refs 4 +533 0.509951 0.994999 +552 0.51367 0.994999 +553 0.531884 0.984998 +534 0.525736 0.984998 +SURF 0x30 +mat 1 +refs 4 +534 0.525736 0.984998 +553 0.531884 0.984998 +554 0.573271 0.952498 +535 0.561615 0.952498 +SURF 0x30 +mat 1 +refs 4 +535 0.561615 0.952498 +554 0.573271 0.952498 +555 0.58486 0.929999 +536 0.57166 0.929999 +SURF 0x30 +mat 1 +refs 4 +536 0.57166 0.929999 +555 0.58486 0.929999 +556 0.594794 0.8825 +537 0.580269 0.8825 +SURF 0x30 +mat 1 +refs 4 +537 0.580269 0.8825 +556 0.594794 0.8825 +557 0.60307 0.6825 +538 0.587446 0.6825 +SURF 0x30 +mat 1 +refs 4 +538 0.587446 0.6825 +557 0.60307 0.6825 +558 0.613004 0.635 +539 0.596055 0.635 +SURF 0x30 +mat 1 +refs 4 +539 0.596055 0.635 +558 0.613004 0.635 +559 0.647773 0.555 +540 0.62619 0.555 +SURF 0x30 +mat 1 +refs 4 +540 0.62619 0.555 +559 0.647773 0.555 +560 0.678621 0.475 +541 0.652931 0.475 +SURF 0x30 +mat 1 +refs 4 +541 0.652931 0.475 +560 0.678621 0.475 +561 0.720307 0.3875 +542 0.690966 0.3875 +SURF 0x30 +mat 1 +refs 4 +542 0.690966 0.3875 +561 0.720307 0.3875 +562 0.739624 0.31 +543 0.707707 0.31 +SURF 0x30 +mat 1 +refs 4 +543 0.707707 0.31 +562 0.739624 0.31 +563 0.736405 0.247501 +544 0.704919 0.247501 +SURF 0x30 +mat 1 +refs 4 +544 0.704919 0.247501 +563 0.736405 0.247501 +564 0.729965 0.175 +545 0.699336 0.175 +SURF 0x30 +mat 1 +refs 4 +545 0.699336 0.175 +564 0.729965 0.175 +565 0.710649 0.105001 +546 0.682592 0.105001 +SURF 0x30 +mat 1 +refs 4 +546 0.682592 0.105001 +565 0.710649 0.105001 +566 0.66075 0.0549999 +547 0.639339 0.0549999 +SURF 0x30 +mat 1 +refs 4 +547 0.639339 0.0549999 +566 0.66075 0.0549999 +567 0.61407 0.0200004 +548 0.598876 0.0200004 +SURF 0x30 +mat 1 +refs 4 +548 0.598876 0.0200004 +567 0.61407 0.0200004 +568 0.544854 0 +549 0.538879 0 +SURF 0x30 +mat 1 +refs 4 +549 0.538879 0 +568 0.544854 0 +569 0.503003 0 +550 0.502603 0 +SURF 0x30 +mat 1 +refs 4 +551 0.492148 1 +570 0.492968 1 +571 0.517248 0.994999 +552 0.51367 0.994999 +SURF 0x30 +mat 1 +refs 4 +552 0.51367 0.994999 +571 0.517248 0.994999 +572 0.537792 0.984998 +553 0.531884 0.984998 +SURF 0x30 +mat 1 +refs 4 +553 0.531884 0.984998 +572 0.537792 0.984998 +573 0.584483 0.952498 +554 0.573271 0.952498 +SURF 0x30 +mat 1 +refs 4 +554 0.573271 0.952498 +573 0.584483 0.952498 +574 0.597555 0.929999 +555 0.58486 0.929999 +SURF 0x30 +mat 1 +refs 4 +555 0.58486 0.929999 +574 0.597555 0.929999 +575 0.608763 0.8825 +556 0.594794 0.8825 +SURF 0x30 +mat 1 +refs 4 +556 0.594794 0.8825 +575 0.608763 0.8825 +576 0.618098 0.6825 +557 0.60307 0.6825 +SURF 0x30 +mat 1 +refs 4 +557 0.60307 0.6825 +576 0.618098 0.6825 +577 0.629307 0.635 +558 0.613004 0.635 +SURF 0x30 +mat 1 +refs 4 +558 0.613004 0.635 +577 0.629307 0.635 +578 0.668525 0.555 +559 0.647773 0.555 +SURF 0x30 +mat 1 +refs 4 +559 0.647773 0.555 +578 0.668525 0.555 +579 0.703328 0.475 +560 0.678621 0.475 +SURF 0x30 +mat 1 +refs 4 +560 0.678621 0.475 +579 0.703328 0.475 +580 0.748529 0.3875 +561 0.720307 0.3875 +SURF 0x30 +mat 1 +refs 4 +561 0.720307 0.3875 +580 0.748529 0.3875 +581 0.77032 0.31 +562 0.739624 0.31 +SURF 0x30 +mat 1 +refs 4 +562 0.739624 0.31 +581 0.77032 0.31 +582 0.766688 0.247501 +563 0.736405 0.247501 +SURF 0x30 +mat 1 +refs 4 +563 0.736405 0.247501 +582 0.766688 0.247501 +583 0.759425 0.175 +564 0.729965 0.175 +SURF 0x30 +mat 1 +refs 4 +564 0.729965 0.175 +583 0.759425 0.175 +584 0.737636 0.105001 +565 0.710649 0.105001 +SURF 0x30 +mat 1 +refs 4 +565 0.710649 0.105001 +584 0.737636 0.105001 +585 0.681341 0.0549999 +566 0.66075 0.0549999 +SURF 0x30 +mat 1 +refs 4 +566 0.66075 0.0549999 +585 0.681341 0.0549999 +586 0.628682 0.0200004 +567 0.61407 0.0200004 +SURF 0x30 +mat 1 +refs 4 +567 0.61407 0.0200004 +586 0.628682 0.0200004 +587 0.550598 0 +568 0.544854 0 +SURF 0x30 +mat 1 +refs 4 +568 0.544854 0 +587 0.550598 0 +588 0.503386 0 +569 0.503003 0 +SURF 0x30 +mat 1 +refs 4 +570 0.492968 1 +589 0.493752 1 +590 0.520665 0.994999 +571 0.517248 0.994999 +SURF 0x30 +mat 1 +refs 4 +571 0.517248 0.994999 +590 0.520665 0.994999 +591 0.543435 0.984998 +572 0.537792 0.984998 +SURF 0x30 +mat 1 +refs 4 +572 0.537792 0.984998 +591 0.543435 0.984998 +592 0.59519 0.952498 +573 0.584483 0.952498 +SURF 0x30 +mat 1 +refs 4 +573 0.584483 0.952498 +592 0.59519 0.952498 +593 0.609681 0.929999 +574 0.597555 0.929999 +SURF 0x30 +mat 1 +refs 4 +574 0.597555 0.929999 +593 0.609681 0.929999 +594 0.622104 0.8825 +575 0.608763 0.8825 +SURF 0x30 +mat 1 +refs 4 +575 0.608763 0.8825 +594 0.622104 0.8825 +595 0.632455 0.6825 +576 0.618098 0.6825 +SURF 0x30 +mat 1 +refs 4 +576 0.618098 0.6825 +595 0.632455 0.6825 +596 0.644874 0.635 +577 0.629307 0.635 +SURF 0x30 +mat 1 +refs 4 +577 0.629307 0.635 +596 0.644874 0.635 +597 0.68835 0.555 +578 0.668525 0.555 +SURF 0x30 +mat 1 +refs 4 +578 0.668525 0.555 +597 0.68835 0.555 +598 0.726925 0.475 +579 0.703328 0.475 +SURF 0x30 +mat 1 +refs 4 +579 0.703328 0.475 +598 0.726925 0.475 +599 0.775486 0.3875 +580 0.748529 0.3875 +SURF 0x30 +mat 1 +refs 4 +580 0.748529 0.3875 +599 0.775486 0.3875 +600 0.799638 0.31 +581 0.77032 0.31 +SURF 0x30 +mat 1 +refs 4 +581 0.77032 0.31 +600 0.799638 0.31 +601 0.795613 0.247501 +582 0.766688 0.247501 +SURF 0x30 +mat 1 +refs 4 +582 0.766688 0.247501 +601 0.795613 0.247501 +602 0.787562 0.175 +583 0.759425 0.175 +SURF 0x30 +mat 1 +refs 4 +583 0.759425 0.175 +602 0.787562 0.175 +603 0.76341 0.105001 +584 0.737636 0.105001 +SURF 0x30 +mat 1 +refs 4 +584 0.737636 0.105001 +603 0.76341 0.105001 +604 0.701011 0.0549999 +585 0.681341 0.0549999 +SURF 0x30 +mat 1 +refs 4 +585 0.681341 0.0549999 +604 0.701011 0.0549999 +605 0.642638 0.0200004 +586 0.628682 0.0200004 +SURF 0x30 +mat 1 +refs 4 +586 0.628682 0.0200004 +605 0.642638 0.0200004 +606 0.556087 0 +587 0.550598 0 +SURF 0x30 +mat 1 +refs 4 +587 0.550598 0 +606 0.556087 0 +607 0.503753 0 +588 0.503386 0 +SURF 0x30 +mat 1 +refs 4 +589 0.493752 1 +608 0.494495 1 +609 0.523904 0.994999 +590 0.520665 0.994999 +SURF 0x30 +mat 1 +refs 4 +590 0.520665 0.994999 +609 0.523904 0.994999 +610 0.548786 0.984998 +591 0.543435 0.984998 +SURF 0x30 +mat 1 +refs 4 +591 0.543435 0.984998 +610 0.548786 0.984998 +611 0.605343 0.952498 +592 0.59519 0.952498 +SURF 0x30 +mat 1 +refs 4 +592 0.59519 0.952498 +611 0.605343 0.952498 +612 0.621176 0.929999 +593 0.609681 0.929999 +SURF 0x30 +mat 1 +refs 4 +593 0.609681 0.929999 +612 0.621176 0.929999 +613 0.634748 0.8825 +594 0.622104 0.8825 +SURF 0x30 +mat 1 +refs 4 +594 0.622104 0.8825 +613 0.634748 0.8825 +614 0.646061 0.6825 +595 0.632455 0.6825 +SURF 0x30 +mat 1 +refs 4 +595 0.632455 0.6825 +614 0.646061 0.6825 +615 0.659634 0.635 +596 0.644874 0.635 +SURF 0x30 +mat 1 +refs 4 +596 0.644874 0.635 +615 0.659634 0.635 +616 0.707142 0.555 +597 0.68835 0.555 +SURF 0x30 +mat 1 +refs 4 +597 0.68835 0.555 +616 0.707142 0.555 +617 0.749295 0.475 +598 0.726925 0.475 +SURF 0x30 +mat 1 +refs 4 +598 0.726925 0.475 +617 0.749295 0.475 +618 0.801037 0.3875 +599 0.775486 0.3875 +SURF 0x30 +mat 1 +refs 4 +599 0.775486 0.3875 +618 0.801037 0.3875 +619 0.827429 0.31 +600 0.799638 0.31 +SURF 0x30 +mat 1 +refs 4 +600 0.799638 0.31 +619 0.827429 0.31 +620 0.823031 0.247501 +601 0.795613 0.247501 +SURF 0x30 +mat 1 +refs 4 +601 0.795613 0.247501 +620 0.823031 0.247501 +621 0.814233 0.175 +602 0.787562 0.175 +SURF 0x30 +mat 1 +refs 4 +602 0.787562 0.175 +621 0.814233 0.175 +622 0.787838 0.105001 +603 0.76341 0.105001 +SURF 0x30 +mat 1 +refs 4 +603 0.76341 0.105001 +622 0.787838 0.105001 +623 0.719655 0.0549999 +604 0.701011 0.0549999 +SURF 0x30 +mat 1 +refs 4 +604 0.701011 0.0549999 +623 0.719655 0.0549999 +624 0.655867 0.0200004 +605 0.642638 0.0200004 +SURF 0x30 +mat 1 +refs 4 +605 0.642638 0.0200004 +624 0.655867 0.0200004 +625 0.561289 0 +606 0.556087 0 +SURF 0x30 +mat 1 +refs 4 +606 0.556087 0 +625 0.561289 0 +626 0.504103 0 +607 0.503753 0 +SURF 0x30 +mat 1 +refs 4 +608 0.494495 1 +627 0.495191 1 +628 0.526947 0.994999 +609 0.523904 0.994999 +SURF 0x30 +mat 1 +refs 4 +609 0.523904 0.994999 +628 0.526947 0.994999 +629 0.553817 0.984998 +610 0.548786 0.984998 +SURF 0x30 +mat 1 +refs 4 +610 0.548786 0.984998 +629 0.553817 0.984998 +630 0.614884 0.952498 +611 0.605343 0.952498 +SURF 0x30 +mat 1 +refs 4 +611 0.605343 0.952498 +630 0.614884 0.952498 +631 0.631981 0.929999 +612 0.621176 0.929999 +SURF 0x30 +mat 1 +refs 4 +612 0.621176 0.929999 +631 0.631981 0.929999 +632 0.646636 0.8825 +613 0.634748 0.8825 +SURF 0x30 +mat 1 +refs 4 +613 0.634748 0.8825 +632 0.646636 0.8825 +633 0.65885 0.6825 +614 0.646061 0.6825 +SURF 0x30 +mat 1 +refs 4 +614 0.646061 0.6825 +633 0.65885 0.6825 +634 0.673506 0.635 +615 0.659634 0.635 +SURF 0x30 +mat 1 +refs 4 +615 0.659634 0.635 +634 0.673506 0.635 +635 0.724803 0.555 +616 0.707142 0.555 +SURF 0x30 +mat 1 +refs 4 +616 0.707142 0.555 +635 0.724803 0.555 +636 0.77032 0.475 +617 0.749295 0.475 +SURF 0x30 +mat 1 +refs 4 +617 0.749295 0.475 +636 0.77032 0.475 +637 0.825055 0.3875 +618 0.801037 0.3875 +SURF 0x30 +mat 1 +refs 4 +618 0.801037 0.3875 +637 0.825055 0.3875 +638 0.853552 0.31 +619 0.827429 0.31 +SURF 0x30 +mat 1 +refs 4 +619 0.827429 0.31 +638 0.853552 0.31 +639 0.848804 0.247501 +620 0.823031 0.247501 +SURF 0x30 +mat 1 +refs 4 +620 0.823031 0.247501 +639 0.848804 0.247501 +640 0.839304 0.175 +621 0.814233 0.175 +SURF 0x30 +mat 1 +refs 4 +621 0.814233 0.175 +640 0.839304 0.175 +641 0.810803 0.105001 +622 0.787838 0.105001 +SURF 0x30 +mat 1 +refs 4 +622 0.787838 0.105001 +641 0.810803 0.105001 +642 0.737179 0.0549999 +623 0.719655 0.0549999 +SURF 0x30 +mat 1 +refs 4 +623 0.719655 0.0549999 +642 0.737179 0.0549999 +643 0.668303 0.0200004 +624 0.655867 0.0200004 +SURF 0x30 +mat 1 +refs 4 +624 0.655867 0.0200004 +643 0.668303 0.0200004 +644 0.566179 0 +625 0.561289 0 +SURF 0x30 +mat 1 +refs 4 +625 0.561289 0 +644 0.566179 0 +645 0.504429 0 +626 0.504103 0 +SURF 0x30 +mat 1 +refs 4 +627 0.495191 1 +646 0.49584 1 +647 0.529779 0.994999 +628 0.526947 0.994999 +SURF 0x30 +mat 1 +refs 4 +628 0.526947 0.994999 +647 0.529779 0.994999 +648 0.558498 0.984998 +629 0.553817 0.984998 +SURF 0x30 +mat 1 +refs 4 +629 0.553817 0.984998 +648 0.558498 0.984998 +649 0.623765 0.952498 +630 0.614884 0.952498 +SURF 0x30 +mat 1 +refs 4 +630 0.614884 0.952498 +649 0.623765 0.952498 +650 0.642039 0.929999 +631 0.631981 0.929999 +SURF 0x30 +mat 1 +refs 4 +631 0.631981 0.929999 +650 0.642039 0.929999 +651 0.657703 0.8825 +632 0.646636 0.8825 +SURF 0x30 +mat 1 +refs 4 +632 0.646636 0.8825 +651 0.657703 0.8825 +652 0.670758 0.6825 +633 0.65885 0.6825 +SURF 0x30 +mat 1 +refs 4 +633 0.65885 0.6825 +652 0.670758 0.6825 +653 0.686423 0.635 +634 0.673506 0.635 +SURF 0x30 +mat 1 +refs 4 +634 0.673506 0.635 +653 0.686423 0.635 +654 0.741248 0.555 +635 0.724803 0.555 +SURF 0x30 +mat 1 +refs 4 +635 0.724803 0.555 +654 0.741248 0.555 +655 0.789896 0.475 +636 0.77032 0.475 +SURF 0x30 +mat 1 +refs 4 +636 0.77032 0.475 +655 0.789896 0.475 +656 0.847415 0.3875 +637 0.825055 0.3875 +SURF 0x30 +mat 1 +refs 4 +637 0.825055 0.3875 +656 0.847415 0.3875 +657 0.877876 0.31 +638 0.853552 0.31 +SURF 0x30 +mat 1 +refs 4 +638 0.853552 0.31 +657 0.877876 0.31 +658 0.872798 0.247501 +639 0.848804 0.247501 +SURF 0x30 +mat 1 +refs 4 +639 0.848804 0.247501 +658 0.872798 0.247501 +659 0.862646 0.175 +640 0.839304 0.175 +SURF 0x30 +mat 1 +refs 4 +640 0.839304 0.175 +659 0.862646 0.175 +660 0.832184 0.105001 +641 0.810803 0.105001 +SURF 0x30 +mat 1 +refs 4 +641 0.810803 0.105001 +660 0.832184 0.105001 +661 0.753496 0.0549999 +642 0.737179 0.0549999 +SURF 0x30 +mat 1 +refs 4 +642 0.737179 0.0549999 +661 0.753496 0.0549999 +662 0.679882 0.0200004 +643 0.668303 0.0200004 +SURF 0x30 +mat 1 +refs 4 +643 0.668303 0.0200004 +662 0.679882 0.0200004 +663 0.570732 0 +644 0.566179 0 +SURF 0x30 +mat 1 +refs 4 +644 0.566179 0 +663 0.570732 0 +664 0.504735 0 +645 0.504429 0 +SURF 0x30 +mat 1 +refs 4 +646 0.49584 1 +665 0.496439 1 +666 0.532388 0.994999 +647 0.529779 0.994999 +SURF 0x30 +mat 1 +refs 4 +647 0.529779 0.994999 +666 0.532388 0.994999 +667 0.562809 0.984998 +648 0.558498 0.984998 +SURF 0x30 +mat 1 +refs 4 +648 0.558498 0.984998 +667 0.562809 0.984998 +668 0.631947 0.952498 +649 0.623765 0.952498 +SURF 0x30 +mat 1 +refs 4 +649 0.623765 0.952498 +668 0.631947 0.952498 +669 0.651304 0.929999 +650 0.642039 0.929999 +SURF 0x30 +mat 1 +refs 4 +650 0.642039 0.929999 +669 0.651304 0.929999 +670 0.667896 0.8825 +651 0.657703 0.8825 +SURF 0x30 +mat 1 +refs 4 +651 0.657703 0.8825 +670 0.667896 0.8825 +671 0.681725 0.6825 +652 0.670758 0.6825 +SURF 0x30 +mat 1 +refs 4 +652 0.670758 0.6825 +671 0.681725 0.6825 +672 0.698317 0.635 +653 0.686423 0.635 +SURF 0x30 +mat 1 +refs 4 +653 0.686423 0.635 +672 0.698317 0.635 +673 0.756391 0.555 +654 0.741248 0.555 +SURF 0x30 +mat 1 +refs 4 +654 0.741248 0.555 +673 0.756391 0.555 +674 0.807924 0.475 +655 0.789896 0.475 +SURF 0x30 +mat 1 +refs 4 +655 0.789896 0.475 +674 0.807924 0.475 +675 0.868006 0.3875 +656 0.847415 0.3875 +SURF 0x30 +mat 1 +refs 4 +656 0.847415 0.3875 +675 0.868006 0.3875 +676 0.90027 0.31 +657 0.877876 0.31 +SURF 0x30 +mat 1 +refs 4 +657 0.877876 0.31 +676 0.90027 0.31 +677 0.894892 0.247501 +658 0.872798 0.247501 +SURF 0x30 +mat 1 +refs 4 +658 0.872798 0.247501 +677 0.894892 0.247501 +678 0.884138 0.175 +659 0.862646 0.175 +SURF 0x30 +mat 1 +refs 4 +659 0.862646 0.175 +678 0.884138 0.175 +679 0.851871 0.105001 +660 0.832184 0.105001 +SURF 0x30 +mat 1 +refs 4 +660 0.832184 0.105001 +679 0.851871 0.105001 +680 0.768518 0.0549999 +661 0.753496 0.0549999 +SURF 0x30 +mat 1 +refs 4 +661 0.753496 0.0549999 +680 0.768518 0.0549999 +681 0.690542 0.0200004 +662 0.679882 0.0200004 +SURF 0x30 +mat 1 +refs 4 +662 0.679882 0.0200004 +681 0.690542 0.0200004 +682 0.574922 0 +663 0.570732 0 +SURF 0x30 +mat 1 +refs 4 +663 0.570732 0 +682 0.574922 0 +683 0.505014 0 +664 0.504735 0 +SURF 0x30 +mat 1 +refs 4 +665 0.496439 1 +684 0.496983 1 +685 0.534762 0.994999 +666 0.532388 0.994999 +SURF 0x30 +mat 1 +refs 4 +666 0.532388 0.994999 +685 0.534762 0.994999 +686 0.566727 0.984998 +667 0.562809 0.984998 +SURF 0x30 +mat 1 +refs 4 +667 0.562809 0.984998 +686 0.566727 0.984998 +687 0.639379 0.952498 +668 0.631947 0.952498 +SURF 0x30 +mat 1 +refs 4 +668 0.631947 0.952498 +687 0.639379 0.952498 +688 0.659721 0.929999 +669 0.651304 0.929999 +SURF 0x30 +mat 1 +refs 4 +669 0.651304 0.929999 +688 0.659721 0.929999 +689 0.677161 0.8825 +670 0.667896 0.8825 +SURF 0x30 +mat 1 +refs 4 +670 0.667896 0.8825 +689 0.677161 0.8825 +690 0.691689 0.6825 +671 0.681725 0.6825 +SURF 0x30 +mat 1 +refs 4 +671 0.681725 0.6825 +690 0.691689 0.6825 +691 0.709126 0.635 +672 0.698317 0.635 +SURF 0x30 +mat 1 +refs 4 +672 0.698317 0.635 +691 0.709126 0.635 +692 0.770156 0.555 +673 0.756391 0.555 +SURF 0x30 +mat 1 +refs 4 +673 0.756391 0.555 +692 0.770156 0.555 +693 0.824308 0.475 +674 0.807924 0.475 +SURF 0x30 +mat 1 +refs 4 +674 0.807924 0.475 +693 0.824308 0.475 +694 0.886721 0.3875 +675 0.868006 0.3875 +SURF 0x30 +mat 1 +refs 4 +675 0.868006 0.3875 +694 0.886721 0.3875 +695 0.920625 0.31 +676 0.90027 0.31 +SURF 0x30 +mat 1 +refs 4 +676 0.90027 0.31 +695 0.920625 0.31 +696 0.914976 0.247501 +677 0.894892 0.247501 +SURF 0x30 +mat 1 +refs 4 +677 0.894892 0.247501 +696 0.914976 0.247501 +697 0.903673 0.175 +678 0.884138 0.175 +SURF 0x30 +mat 1 +refs 4 +678 0.884138 0.175 +697 0.903673 0.175 +698 0.869768 0.105001 +679 0.851871 0.105001 +SURF 0x30 +mat 1 +refs 4 +679 0.851871 0.105001 +698 0.869768 0.105001 +699 0.782175 0.0549999 +680 0.768518 0.0549999 +SURF 0x30 +mat 1 +refs 4 +680 0.768518 0.0549999 +699 0.782175 0.0549999 +700 0.700234 0.0200004 +681 0.690542 0.0200004 +SURF 0x30 +mat 1 +refs 4 +681 0.690542 0.0200004 +700 0.700234 0.0200004 +701 0.578736 0 +682 0.574922 0 +SURF 0x30 +mat 1 +refs 4 +682 0.574922 0 +701 0.578736 0 +702 0.50527 0 +683 0.505014 0 +SURF 0x30 +mat 1 +refs 4 +684 0.496983 1 +703 0.497468 1 +704 0.536884 0.994999 +685 0.534762 0.994999 +SURF 0x30 +mat 1 +refs 4 +685 0.534762 0.994999 +704 0.536884 0.994999 +705 0.570234 0.984998 +686 0.566727 0.984998 +SURF 0x30 +mat 1 +refs 4 +686 0.566727 0.984998 +705 0.570234 0.984998 +706 0.646031 0.952498 +687 0.639379 0.952498 +SURF 0x30 +mat 1 +refs 4 +687 0.639379 0.952498 +706 0.646031 0.952498 +707 0.667254 0.929999 +688 0.659721 0.929999 +SURF 0x30 +mat 1 +refs 4 +688 0.659721 0.929999 +707 0.667254 0.929999 +708 0.685447 0.8825 +689 0.677161 0.8825 +SURF 0x30 +mat 1 +refs 4 +689 0.677161 0.8825 +708 0.685447 0.8825 +709 0.700607 0.6825 +690 0.691689 0.6825 +SURF 0x30 +mat 1 +refs 4 +690 0.691689 0.6825 +709 0.700607 0.6825 +710 0.718797 0.635 +691 0.709126 0.635 +SURF 0x30 +mat 1 +refs 4 +691 0.709126 0.635 +710 0.718797 0.635 +711 0.782467 0.555 +692 0.770156 0.555 +SURF 0x30 +mat 1 +refs 4 +692 0.770156 0.555 +711 0.782467 0.555 +712 0.838967 0.475 +693 0.824308 0.475 +SURF 0x30 +mat 1 +refs 4 +693 0.824308 0.475 +712 0.838967 0.475 +713 0.903464 0.3875 +694 0.886721 0.3875 +SURF 0x30 +mat 1 +refs 4 +694 0.886721 0.3875 +713 0.903464 0.3875 +714 0.938839 0.31 +695 0.920625 0.31 +SURF 0x30 +mat 1 +refs 4 +695 0.920625 0.31 +714 0.938839 0.31 +715 0.932944 0.247501 +696 0.914976 0.247501 +SURF 0x30 +mat 1 +refs 4 +696 0.914976 0.247501 +715 0.932944 0.247501 +716 0.921153 0.175 +697 0.903673 0.175 +SURF 0x30 +mat 1 +refs 4 +697 0.903673 0.175 +716 0.921153 0.175 +717 0.885776 0.105001 +698 0.869768 0.105001 +SURF 0x30 +mat 1 +refs 4 +698 0.869768 0.105001 +717 0.885776 0.105001 +718 0.794392 0.0549999 +699 0.782175 0.0549999 +SURF 0x30 +mat 1 +refs 4 +699 0.782175 0.0549999 +718 0.794392 0.0549999 +719 0.708904 0.0200004 +700 0.700234 0.0200004 +SURF 0x30 +mat 1 +refs 4 +700 0.700234 0.0200004 +719 0.708904 0.0200004 +720 0.582142 0 +701 0.578736 0 +SURF 0x30 +mat 1 +refs 4 +701 0.578736 0 +720 0.582142 0 +721 0.505498 0 +702 0.50527 0 +SURF 0x30 +mat 1 +refs 4 +703 0.497468 1 +722 0.497895 1 +723 0.538744 0.994999 +704 0.536884 0.994999 +SURF 0x30 +mat 1 +refs 4 +704 0.536884 0.994999 +723 0.538744 0.994999 +724 0.573311 0.984998 +705 0.570234 0.984998 +SURF 0x30 +mat 1 +refs 4 +705 0.570234 0.984998 +724 0.573311 0.984998 +725 0.651869 0.952498 +706 0.646031 0.952498 +SURF 0x30 +mat 1 +refs 4 +706 0.646031 0.952498 +725 0.651869 0.952498 +726 0.673862 0.929999 +707 0.667254 0.929999 +SURF 0x30 +mat 1 +refs 4 +707 0.667254 0.929999 +726 0.673862 0.929999 +727 0.692718 0.8825 +708 0.685447 0.8825 +SURF 0x30 +mat 1 +refs 4 +708 0.685447 0.8825 +727 0.692718 0.8825 +728 0.70843 0.6825 +709 0.700607 0.6825 +SURF 0x30 +mat 1 +refs 4 +709 0.700607 0.6825 +728 0.70843 0.6825 +729 0.727282 0.635 +710 0.718797 0.635 +SURF 0x30 +mat 1 +refs 4 +710 0.718797 0.635 +729 0.727282 0.635 +730 0.793272 0.555 +711 0.782467 0.555 +SURF 0x30 +mat 1 +refs 4 +711 0.782467 0.555 +730 0.793272 0.555 +731 0.851827 0.475 +712 0.838967 0.475 +SURF 0x30 +mat 1 +refs 4 +712 0.838967 0.475 +731 0.851827 0.475 +732 0.918154 0.3875 +713 0.903464 0.3875 +SURF 0x30 +mat 1 +refs 4 +713 0.903464 0.3875 +732 0.918154 0.3875 +733 0.954816 0.31 +714 0.938839 0.31 +SURF 0x30 +mat 1 +refs 4 +714 0.938839 0.31 +733 0.954816 0.31 +734 0.948706 0.247501 +715 0.932944 0.247501 +SURF 0x30 +mat 1 +refs 4 +715 0.932944 0.247501 +734 0.948706 0.247501 +735 0.936485 0.175 +716 0.921153 0.175 +SURF 0x30 +mat 1 +refs 4 +716 0.921153 0.175 +735 0.936485 0.175 +736 0.899823 0.105001 +717 0.885776 0.105001 +SURF 0x30 +mat 1 +refs 4 +717 0.885776 0.105001 +736 0.899823 0.105001 +737 0.80511 0.0549999 +718 0.794392 0.0549999 +SURF 0x30 +mat 1 +refs 4 +718 0.794392 0.0549999 +737 0.80511 0.0549999 +738 0.716507 0.0200004 +719 0.708904 0.0200004 +SURF 0x30 +mat 1 +refs 4 +719 0.708904 0.0200004 +738 0.716507 0.0200004 +739 0.585132 0 +720 0.582142 0 +SURF 0x30 +mat 1 +refs 4 +720 0.582142 0 +739 0.585132 0 +740 0.505697 0 +721 0.505498 0 +SURF 0x30 +mat 1 +refs 4 +722 0.497895 1 +741 0.498258 1 +742 0.540335 0.994999 +723 0.538744 0.994999 +SURF 0x30 +mat 1 +refs 4 +723 0.538744 0.994999 +742 0.540335 0.994999 +743 0.575941 0.984998 +724 0.573311 0.984998 +SURF 0x30 +mat 1 +refs 4 +724 0.573311 0.984998 +743 0.575941 0.984998 +744 0.656856 0.952498 +725 0.651869 0.952498 +SURF 0x30 +mat 1 +refs 4 +725 0.651869 0.952498 +744 0.656856 0.952498 +745 0.679512 0.929999 +726 0.673862 0.929999 +SURF 0x30 +mat 1 +refs 4 +726 0.673862 0.929999 +745 0.679512 0.929999 +746 0.698933 0.8825 +727 0.692718 0.8825 +SURF 0x30 +mat 1 +refs 4 +727 0.692718 0.8825 +746 0.698933 0.8825 +747 0.715115 0.6825 +728 0.70843 0.6825 +SURF 0x30 +mat 1 +refs 4 +728 0.70843 0.6825 +747 0.715115 0.6825 +748 0.734536 0.635 +729 0.727282 0.635 +SURF 0x30 +mat 1 +refs 4 +729 0.727282 0.635 +748 0.734536 0.635 +749 0.802507 0.555 +730 0.793272 0.555 +SURF 0x30 +mat 1 +refs 4 +730 0.793272 0.555 +749 0.802507 0.555 +750 0.86282 0.475 +731 0.851827 0.475 +SURF 0x30 +mat 1 +refs 4 +731 0.851827 0.475 +750 0.86282 0.475 +751 0.930711 0.3875 +732 0.918154 0.3875 +SURF 0x30 +mat 1 +refs 4 +732 0.918154 0.3875 +751 0.930711 0.3875 +752 0.968476 0.31 +733 0.954816 0.31 +SURF 0x30 +mat 1 +refs 4 +733 0.954816 0.31 +752 0.968476 0.31 +753 0.962181 0.247501 +734 0.948706 0.247501 +SURF 0x30 +mat 1 +refs 4 +734 0.948706 0.247501 +753 0.962181 0.247501 +754 0.949593 0.175 +735 0.936485 0.175 +SURF 0x30 +mat 1 +refs 4 +735 0.936485 0.175 +754 0.949593 0.175 +755 0.911828 0.105001 +736 0.899823 0.105001 +SURF 0x30 +mat 1 +refs 4 +736 0.899823 0.105001 +755 0.911828 0.105001 +756 0.814274 0.0549999 +737 0.80511 0.0549999 +SURF 0x30 +mat 1 +refs 4 +737 0.80511 0.0549999 +756 0.814274 0.0549999 +757 0.723011 0.0200004 +738 0.716507 0.0200004 +SURF 0x30 +mat 1 +refs 4 +738 0.716507 0.0200004 +757 0.723011 0.0200004 +758 0.587691 0 +739 0.585132 0 +SURF 0x30 +mat 1 +refs 4 +739 0.585132 0 +758 0.587691 0 +759 0.505868 0 +740 0.505697 0 +SURF 0x30 +mat 1 +refs 4 +741 0.498258 1 +760 0.498561 1 +761 0.54165 0.994999 +742 0.540335 0.994999 +SURF 0x30 +mat 1 +refs 4 +742 0.540335 0.994999 +761 0.54165 0.994999 +762 0.57811 0.984998 +743 0.575941 0.984998 +SURF 0x30 +mat 1 +refs 4 +743 0.575941 0.984998 +762 0.57811 0.984998 +763 0.660972 0.952498 +744 0.656856 0.952498 +SURF 0x30 +mat 1 +refs 4 +744 0.656856 0.952498 +763 0.660972 0.952498 +764 0.684176 0.929999 +745 0.679512 0.929999 +SURF 0x30 +mat 1 +refs 4 +745 0.679512 0.929999 +764 0.684176 0.929999 +765 0.704061 0.8825 +746 0.698933 0.8825 +SURF 0x30 +mat 1 +refs 4 +746 0.698933 0.8825 +765 0.704061 0.8825 +766 0.720633 0.6825 +747 0.715115 0.6825 +SURF 0x30 +mat 1 +refs 4 +747 0.715115 0.6825 +766 0.720633 0.6825 +767 0.740522 0.635 +748 0.734536 0.635 +SURF 0x30 +mat 1 +refs 4 +748 0.734536 0.635 +767 0.740522 0.635 +768 0.810127 0.555 +749 0.802507 0.555 +SURF 0x30 +mat 1 +refs 4 +749 0.802507 0.555 +768 0.810127 0.555 +769 0.871894 0.475 +750 0.86282 0.475 +SURF 0x30 +mat 1 +refs 4 +750 0.86282 0.475 +769 0.871894 0.475 +770 0.941075 0.3875 +751 0.930711 0.3875 +SURF 0x30 +mat 1 +refs 4 +751 0.930711 0.3875 +770 0.941075 0.3875 +771 0.979745 0.31 +752 0.968476 0.31 +SURF 0x30 +mat 1 +refs 4 +752 0.968476 0.31 +771 0.979745 0.31 +772 0.973302 0.247501 +753 0.962181 0.247501 +SURF 0x30 +mat 1 +refs 4 +753 0.962181 0.247501 +772 0.973302 0.247501 +773 0.960409 0.175 +754 0.949593 0.175 +SURF 0x30 +mat 1 +refs 4 +754 0.949593 0.175 +773 0.960409 0.175 +774 0.921739 0.105001 +755 0.911828 0.105001 +SURF 0x30 +mat 1 +refs 4 +755 0.911828 0.105001 +774 0.921739 0.105001 +775 0.821833 0.0549999 +756 0.814274 0.0549999 +SURF 0x30 +mat 1 +refs 4 +756 0.814274 0.0549999 +775 0.821833 0.0549999 +776 0.728375 0.0200004 +757 0.723011 0.0200004 +SURF 0x30 +mat 1 +refs 4 +757 0.723011 0.0200004 +776 0.728375 0.0200004 +777 0.5898 0 +758 0.587691 0 +SURF 0x30 +mat 1 +refs 4 +758 0.587691 0 +777 0.5898 0 +778 0.506009 0 +759 0.505868 0 +SURF 0x30 +mat 1 +refs 4 +760 0.498561 1 +779 0.498796 1 +780 0.542679 0.994999 +761 0.54165 0.994999 +SURF 0x30 +mat 1 +refs 4 +761 0.54165 0.994999 +780 0.542679 0.994999 +781 0.579808 0.984998 +762 0.57811 0.984998 +SURF 0x30 +mat 1 +refs 4 +762 0.57811 0.984998 +781 0.579808 0.984998 +782 0.664197 0.952498 +763 0.660972 0.952498 +SURF 0x30 +mat 1 +refs 4 +763 0.660972 0.952498 +782 0.664197 0.952498 +783 0.687825 0.929999 +764 0.684176 0.929999 +SURF 0x30 +mat 1 +refs 4 +764 0.684176 0.929999 +783 0.687825 0.929999 +784 0.70808 0.8825 +765 0.704061 0.8825 +SURF 0x30 +mat 1 +refs 4 +765 0.704061 0.8825 +784 0.70808 0.8825 +785 0.724958 0.6825 +766 0.720633 0.6825 +SURF 0x30 +mat 1 +refs 4 +766 0.720633 0.6825 +785 0.724958 0.6825 +786 0.74521 0.635 +767 0.740522 0.635 +SURF 0x30 +mat 1 +refs 4 +767 0.740522 0.635 +786 0.74521 0.635 +787 0.816096 0.555 +768 0.810127 0.555 +SURF 0x30 +mat 1 +refs 4 +768 0.810127 0.555 +787 0.816096 0.555 +788 0.878996 0.475 +769 0.871894 0.475 +SURF 0x30 +mat 1 +refs 4 +769 0.871894 0.475 +788 0.878996 0.475 +789 0.94919 0.3875 +770 0.941075 0.3875 +SURF 0x30 +mat 1 +refs 4 +770 0.941075 0.3875 +789 0.94919 0.3875 +790 0.988573 0.31 +771 0.979745 0.31 +SURF 0x30 +mat 1 +refs 4 +771 0.979745 0.31 +790 0.988573 0.31 +791 0.982008 0.247501 +772 0.973302 0.247501 +SURF 0x30 +mat 1 +refs 4 +772 0.973302 0.247501 +791 0.982008 0.247501 +792 0.96888 0.175 +773 0.960409 0.175 +SURF 0x30 +mat 1 +refs 4 +773 0.960409 0.175 +792 0.96888 0.175 +793 0.929497 0.105001 +774 0.921739 0.105001 +SURF 0x30 +mat 1 +refs 4 +774 0.921739 0.105001 +793 0.929497 0.105001 +794 0.827755 0.0549999 +775 0.821833 0.0549999 +SURF 0x30 +mat 1 +refs 4 +775 0.821833 0.0549999 +794 0.827755 0.0549999 +795 0.732578 0.0200004 +776 0.728375 0.0200004 +SURF 0x30 +mat 1 +refs 4 +776 0.728375 0.0200004 +795 0.732578 0.0200004 +796 0.591451 0 +777 0.5898 0 +SURF 0x30 +mat 1 +refs 4 +777 0.5898 0 +796 0.591451 0 +797 0.506121 0 +778 0.506009 0 +SURF 0x30 +mat 1 +refs 4 +779 0.498796 1 +798 0.498964 1 +799 0.543415 0.994999 +780 0.542679 0.994999 +SURF 0x30 +mat 1 +refs 4 +780 0.542679 0.994999 +799 0.543415 0.994999 +800 0.581029 0.984998 +781 0.579808 0.984998 +SURF 0x30 +mat 1 +refs 4 +781 0.579808 0.984998 +800 0.581029 0.984998 +801 0.666511 0.952498 +782 0.664197 0.952498 +SURF 0x30 +mat 1 +refs 4 +782 0.664197 0.952498 +801 0.666511 0.952498 +802 0.690448 0.929999 +783 0.687825 0.929999 +SURF 0x30 +mat 1 +refs 4 +783 0.687825 0.929999 +802 0.690448 0.929999 +803 0.710962 0.8825 +784 0.70808 0.8825 +SURF 0x30 +mat 1 +refs 4 +784 0.70808 0.8825 +803 0.710962 0.8825 +804 0.728059 0.6825 +785 0.724958 0.6825 +SURF 0x30 +mat 1 +refs 4 +785 0.724958 0.6825 +804 0.728059 0.6825 +805 0.748576 0.635 +786 0.74521 0.635 +SURF 0x30 +mat 1 +refs 4 +786 0.74521 0.635 +805 0.748576 0.635 +806 0.82038 0.555 +787 0.816096 0.555 +SURF 0x30 +mat 1 +refs 4 +787 0.816096 0.555 +806 0.82038 0.555 +807 0.884097 0.475 +788 0.878996 0.475 +SURF 0x30 +mat 1 +refs 4 +788 0.878996 0.475 +807 0.884097 0.475 +808 0.955014 0.3875 +789 0.94919 0.3875 +SURF 0x30 +mat 1 +refs 4 +789 0.94919 0.3875 +808 0.955014 0.3875 +809 0.994912 0.31 +790 0.988573 0.31 +SURF 0x30 +mat 1 +refs 4 +790 0.988573 0.31 +809 0.994912 0.31 +810 0.98826 0.247501 +791 0.982008 0.247501 +SURF 0x30 +mat 1 +refs 4 +791 0.982008 0.247501 +810 0.98826 0.247501 +811 0.974963 0.175 +792 0.96888 0.175 +SURF 0x30 +mat 1 +refs 4 +792 0.96888 0.175 +811 0.974963 0.175 +812 0.935069 0.105001 +793 0.929497 0.105001 +SURF 0x30 +mat 1 +refs 4 +793 0.929497 0.105001 +812 0.935069 0.105001 +813 0.832006 0.0549999 +794 0.827755 0.0549999 +SURF 0x30 +mat 1 +refs 4 +794 0.827755 0.0549999 +813 0.832006 0.0549999 +814 0.735595 0.0200004 +795 0.732578 0.0200004 +SURF 0x30 +mat 1 +refs 4 +795 0.732578 0.0200004 +814 0.735595 0.0200004 +815 0.592638 0 +796 0.591451 0 +SURF 0x30 +mat 1 +refs 4 +796 0.591451 0 +815 0.592638 0 +816 0.506201 0 +797 0.506121 0 +SURF 0x30 +mat 1 +refs 4 +798 0.498964 1 +817 0.499068 1 +818 0.543862 0.994999 +799 0.543415 0.994999 +SURF 0x30 +mat 1 +refs 4 +799 0.543415 0.994999 +818 0.543862 0.994999 +819 0.581762 0.984998 +800 0.581029 0.984998 +SURF 0x30 +mat 1 +refs 4 +800 0.581029 0.984998 +819 0.581762 0.984998 +820 0.667906 0.952498 +801 0.666511 0.952498 +SURF 0x30 +mat 1 +refs 4 +801 0.666511 0.952498 +820 0.667906 0.952498 +821 0.692025 0.929999 +802 0.690448 0.929999 +SURF 0x30 +mat 1 +refs 4 +802 0.690448 0.929999 +821 0.692025 0.929999 +822 0.7127 0.8825 +803 0.710962 0.8825 +SURF 0x30 +mat 1 +refs 4 +803 0.710962 0.8825 +822 0.7127 0.8825 +823 0.729928 0.6825 +804 0.728059 0.6825 +SURF 0x30 +mat 1 +refs 4 +804 0.728059 0.6825 +823 0.729928 0.6825 +824 0.7506 0.635 +805 0.748576 0.635 +SURF 0x30 +mat 1 +refs 4 +805 0.748576 0.635 +824 0.7506 0.635 +825 0.82296 0.555 +806 0.82038 0.555 +SURF 0x30 +mat 1 +refs 4 +806 0.82038 0.555 +825 0.82296 0.555 +826 0.887168 0.475 +807 0.884097 0.475 +SURF 0x30 +mat 1 +refs 4 +807 0.884097 0.475 +826 0.887168 0.475 +827 0.958522 0.3875 +808 0.955014 0.3875 +SURF 0x30 +mat 1 +refs 4 +808 0.955014 0.3875 +827 0.958522 0.3875 +828 0.998726 0.31 +809 0.994912 0.31 +SURF 0x30 +mat 1 +refs 4 +809 0.994912 0.31 +828 0.998726 0.31 +829 0.992027 0.247501 +810 0.98826 0.247501 +SURF 0x30 +mat 1 +refs 4 +810 0.98826 0.247501 +829 0.992027 0.247501 +830 0.978625 0.175 +811 0.974963 0.175 +SURF 0x30 +mat 1 +refs 4 +811 0.974963 0.175 +830 0.978625 0.175 +831 0.938422 0.105001 +812 0.935069 0.105001 +SURF 0x30 +mat 1 +refs 4 +812 0.935069 0.105001 +831 0.938422 0.105001 +832 0.834565 0.0549999 +813 0.832006 0.0549999 +SURF 0x30 +mat 1 +refs 4 +813 0.832006 0.0549999 +832 0.834565 0.0549999 +833 0.737411 0.0200004 +814 0.735595 0.0200004 +SURF 0x30 +mat 1 +refs 4 +814 0.735595 0.0200004 +833 0.737411 0.0200004 +834 0.593354 0 +815 0.592638 0 +SURF 0x30 +mat 1 +refs 4 +815 0.592638 0 +834 0.593354 0 +835 0.506248 0 +816 0.506201 0 +SURF 0x30 +mat 1 +refs 4 +817 0.499068 1 +836 0.499102 1 +837 0.54401 0.994999 +818 0.543862 0.994999 +SURF 0x30 +mat 1 +refs 4 +818 0.543862 0.994999 +837 0.54401 0.994999 +838 0.582008 0.984998 +819 0.581762 0.984998 +SURF 0x30 +mat 1 +refs 4 +819 0.581762 0.984998 +838 0.582008 0.984998 +839 0.66837 0.952498 +820 0.667906 0.952498 +SURF 0x30 +mat 1 +refs 4 +820 0.667906 0.952498 +839 0.66837 0.952498 +840 0.692553 0.929999 +821 0.692025 0.929999 +SURF 0x30 +mat 1 +refs 4 +821 0.692025 0.929999 +840 0.692553 0.929999 +841 0.713279 0.8825 +822 0.7127 0.8825 +SURF 0x30 +mat 1 +refs 4 +822 0.7127 0.8825 +841 0.713279 0.8825 +842 0.730551 0.6825 +823 0.729928 0.6825 +SURF 0x30 +mat 1 +refs 4 +823 0.729928 0.6825 +842 0.730551 0.6825 +843 0.75128 0.635 +824 0.7506 0.635 +SURF 0x30 +mat 1 +refs 4 +824 0.7506 0.635 +843 0.75128 0.635 +844 0.823821 0.555 +825 0.82296 0.555 +SURF 0x30 +mat 1 +refs 4 +825 0.82296 0.555 +844 0.823821 0.555 +845 0.888194 0.475 +826 0.887168 0.475 +SURF 0x30 +mat 1 +refs 4 +826 0.887168 0.475 +845 0.888194 0.475 +846 0.959696 0.3875 +827 0.958522 0.3875 +SURF 0x30 +mat 1 +refs 4 +827 0.958522 0.3875 +846 0.959696 0.3875 +847 1 0.31 +828 0.998726 0.31 +SURF 0x30 +mat 1 +refs 4 +828 0.998726 0.31 +847 1 0.31 +848 0.993281 0.247501 +829 0.992027 0.247501 +SURF 0x30 +mat 1 +refs 4 +829 0.992027 0.247501 +848 0.993281 0.247501 +849 0.979846 0.175 +830 0.978625 0.175 +SURF 0x30 +mat 1 +refs 4 +830 0.978625 0.175 +849 0.979846 0.175 +850 0.939542 0.105001 +831 0.938422 0.105001 +SURF 0x30 +mat 1 +refs 4 +831 0.938422 0.105001 +850 0.939542 0.105001 +851 0.835423 0.0549999 +832 0.834565 0.0549999 +SURF 0x30 +mat 1 +refs 4 +832 0.834565 0.0549999 +851 0.835423 0.0549999 +852 0.738016 0.0200004 +833 0.737411 0.0200004 +SURF 0x30 +mat 1 +refs 4 +833 0.737411 0.0200004 +852 0.738016 0.0200004 +853 0.59359 0 +834 0.593354 0 +SURF 0x30 +mat 1 +refs 4 +834 0.593354 0 +853 0.59359 0 +854 0.506265 0 +835 0.506248 0 +SURF 0x30 +mat 1 +refs 4 +836 0.499102 1 +855 0.499068 1 +856 0.543862 0.994999 +837 0.54401 0.994999 +SURF 0x30 +mat 1 +refs 4 +837 0.54401 0.994999 +856 0.543862 0.994999 +857 0.581762 0.984998 +838 0.582008 0.984998 +SURF 0x30 +mat 1 +refs 4 +838 0.582008 0.984998 +857 0.581762 0.984998 +858 0.667906 0.952498 +839 0.66837 0.952498 +SURF 0x30 +mat 1 +refs 4 +839 0.66837 0.952498 +858 0.667906 0.952498 +859 0.692025 0.929999 +840 0.692553 0.929999 +SURF 0x30 +mat 1 +refs 4 +840 0.692553 0.929999 +859 0.692025 0.929999 +860 0.7127 0.8825 +841 0.713279 0.8825 +SURF 0x30 +mat 1 +refs 4 +841 0.713279 0.8825 +860 0.7127 0.8825 +861 0.729928 0.6825 +842 0.730551 0.6825 +SURF 0x30 +mat 1 +refs 4 +842 0.730551 0.6825 +861 0.729928 0.6825 +862 0.7506 0.635 +843 0.75128 0.635 +SURF 0x30 +mat 1 +refs 4 +843 0.75128 0.635 +862 0.7506 0.635 +863 0.82296 0.555 +844 0.823821 0.555 +SURF 0x30 +mat 1 +refs 4 +844 0.823821 0.555 +863 0.82296 0.555 +864 0.887168 0.475 +845 0.888194 0.475 +SURF 0x30 +mat 1 +refs 4 +845 0.888194 0.475 +864 0.887168 0.475 +865 0.958522 0.3875 +846 0.959696 0.3875 +SURF 0x30 +mat 1 +refs 4 +846 0.959696 0.3875 +865 0.958522 0.3875 +866 0.998726 0.31 +847 1 0.31 +SURF 0x30 +mat 1 +refs 4 +847 1 0.31 +866 0.998726 0.31 +867 0.992027 0.247501 +848 0.993281 0.247501 +SURF 0x30 +mat 1 +refs 4 +848 0.993281 0.247501 +867 0.992027 0.247501 +868 0.978625 0.175 +849 0.979846 0.175 +SURF 0x30 +mat 1 +refs 4 +849 0.979846 0.175 +868 0.978625 0.175 +869 0.938422 0.105001 +850 0.939542 0.105001 +SURF 0x30 +mat 1 +refs 4 +850 0.939542 0.105001 +869 0.938422 0.105001 +870 0.834565 0.0549999 +851 0.835423 0.0549999 +SURF 0x30 +mat 1 +refs 4 +851 0.835423 0.0549999 +870 0.834565 0.0549999 +871 0.737411 0.0200004 +852 0.738016 0.0200004 +SURF 0x30 +mat 1 +refs 4 +852 0.738016 0.0200004 +871 0.737411 0.0200004 +872 0.593354 0 +853 0.59359 0 +SURF 0x30 +mat 1 +refs 4 +853 0.59359 0 +872 0.593354 0 +873 0.506248 0 +854 0.506265 0 +SURF 0x30 +mat 1 +refs 4 +855 0.499068 1 +874 0.498964 1 +875 0.543415 0.994999 +856 0.543862 0.994999 +SURF 0x30 +mat 1 +refs 4 +856 0.543862 0.994999 +875 0.543415 0.994999 +876 0.581029 0.984998 +857 0.581762 0.984998 +SURF 0x30 +mat 1 +refs 4 +857 0.581762 0.984998 +876 0.581029 0.984998 +877 0.666511 0.952498 +858 0.667906 0.952498 +SURF 0x30 +mat 1 +refs 4 +858 0.667906 0.952498 +877 0.666511 0.952498 +878 0.690448 0.929999 +859 0.692025 0.929999 +SURF 0x30 +mat 1 +refs 4 +859 0.692025 0.929999 +878 0.690448 0.929999 +879 0.710962 0.8825 +860 0.7127 0.8825 +SURF 0x30 +mat 0 +refs 4 +860 0.7127 0.8825 +879 0.710962 0.8825 +880 0.728059 0.6825 +861 0.729928 0.6825 +SURF 0x30 +mat 0 +refs 4 +861 0.729928 0.6825 +880 0.728059 0.6825 +881 0.748576 0.635 +862 0.7506 0.635 +SURF 0x30 +mat 0 +refs 4 +862 0.7506 0.635 +881 0.748576 0.635 +882 0.82038 0.555 +863 0.82296 0.555 +SURF 0x30 +mat 0 +refs 4 +863 0.82296 0.555 +882 0.82038 0.555 +883 0.884097 0.475 +864 0.887168 0.475 +SURF 0x30 +mat 0 +refs 4 +864 0.887168 0.475 +883 0.884097 0.475 +884 0.955014 0.3875 +865 0.958522 0.3875 +SURF 0x30 +mat 0 +refs 4 +865 0.958522 0.3875 +884 0.955014 0.3875 +885 0.994912 0.31 +866 0.998726 0.31 +SURF 0x30 +mat 0 +refs 4 +866 0.998726 0.31 +885 0.994912 0.31 +886 0.98826 0.247501 +867 0.992027 0.247501 +SURF 0x30 +mat 0 +refs 4 +867 0.992027 0.247501 +886 0.98826 0.247501 +887 0.974963 0.175 +868 0.978625 0.175 +SURF 0x30 +mat 0 +refs 4 +868 0.978625 0.175 +887 0.974963 0.175 +888 0.935069 0.105001 +869 0.938422 0.105001 +SURF 0x30 +mat 0 +refs 4 +869 0.938422 0.105001 +888 0.935069 0.105001 +889 0.832006 0.0549999 +870 0.834565 0.0549999 +SURF 0x30 +mat 0 +refs 4 +870 0.834565 0.0549999 +889 0.832006 0.0549999 +890 0.735595 0.0200004 +871 0.737411 0.0200004 +SURF 0x30 +mat 1 +refs 4 +871 0.737411 0.0200004 +890 0.735595 0.0200004 +891 0.592638 0 +872 0.593354 0 +SURF 0x30 +mat 1 +refs 4 +872 0.593354 0 +891 0.592638 0 +892 0.506201 0 +873 0.506248 0 +SURF 0x30 +mat 1 +refs 4 +874 0.498964 1 +893 0.498796 1 +894 0.542679 0.994999 +875 0.543415 0.994999 +SURF 0x30 +mat 1 +refs 4 +875 0.543415 0.994999 +894 0.542679 0.994999 +895 0.579808 0.984998 +876 0.581029 0.984998 +SURF 0x30 +mat 1 +refs 4 +876 0.581029 0.984998 +895 0.579808 0.984998 +896 0.664197 0.952498 +877 0.666511 0.952498 +SURF 0x30 +mat 0 +refs 4 +877 0.666511 0.952498 +896 0.664197 0.952498 +897 0.687825 0.929999 +878 0.690448 0.929999 +SURF 0x30 +mat 0 +refs 4 +878 0.690448 0.929999 +897 0.687825 0.929999 +898 0.70808 0.8825 +879 0.710962 0.8825 +SURF 0x30 +mat 0 +refs 4 +879 0.710962 0.8825 +898 0.70808 0.8825 +899 0.724958 0.6825 +880 0.728059 0.6825 +SURF 0x30 +mat 0 +refs 4 +880 0.728059 0.6825 +899 0.724958 0.6825 +900 0.74521 0.635 +881 0.748576 0.635 +SURF 0x30 +mat 0 +refs 4 +881 0.748576 0.635 +900 0.74521 0.635 +901 0.816096 0.555 +882 0.82038 0.555 +SURF 0x30 +mat 0 +refs 4 +882 0.82038 0.555 +901 0.816096 0.555 +902 0.878996 0.475 +883 0.884097 0.475 +SURF 0x30 +mat 0 +refs 4 +883 0.884097 0.475 +902 0.878996 0.475 +903 0.94919 0.3875 +884 0.955014 0.3875 +SURF 0x30 +mat 0 +refs 4 +884 0.955014 0.3875 +903 0.94919 0.3875 +904 0.988573 0.31 +885 0.994912 0.31 +SURF 0x30 +mat 0 +refs 4 +885 0.994912 0.31 +904 0.988573 0.31 +905 0.982008 0.247501 +886 0.98826 0.247501 +SURF 0x30 +mat 0 +refs 4 +886 0.98826 0.247501 +905 0.982008 0.247501 +906 0.96888 0.175 +887 0.974963 0.175 +SURF 0x30 +mat 0 +refs 4 +887 0.974963 0.175 +906 0.96888 0.175 +907 0.929497 0.105001 +888 0.935069 0.105001 +SURF 0x30 +mat 0 +refs 4 +888 0.935069 0.105001 +907 0.929497 0.105001 +908 0.827755 0.0549999 +889 0.832006 0.0549999 +SURF 0x30 +mat 0 +refs 4 +889 0.832006 0.0549999 +908 0.827755 0.0549999 +909 0.732578 0.0200004 +890 0.735595 0.0200004 +SURF 0x30 +mat 1 +refs 4 +890 0.735595 0.0200004 +909 0.732578 0.0200004 +910 0.591451 0 +891 0.592638 0 +SURF 0x30 +mat 1 +refs 4 +891 0.592638 0 +910 0.591451 0 +911 0.506121 0 +892 0.506201 0 +SURF 0x30 +mat 1 +refs 4 +893 0.498796 1 +912 0.498561 1 +913 0.54165 0.994999 +894 0.542679 0.994999 +SURF 0x30 +mat 1 +refs 4 +894 0.542679 0.994999 +913 0.54165 0.994999 +914 0.57811 0.984998 +895 0.579808 0.984998 +SURF 0x30 +mat 0 +refs 4 +895 0.579808 0.984998 +914 0.57811 0.984998 +915 0.660972 0.952498 +896 0.664197 0.952498 +SURF 0x30 +mat 0 +refs 4 +896 0.664197 0.952498 +915 0.660972 0.952498 +916 0.684176 0.929999 +897 0.687825 0.929999 +SURF 0x30 +mat 0 +refs 4 +897 0.687825 0.929999 +916 0.684176 0.929999 +917 0.704061 0.8825 +898 0.70808 0.8825 +SURF 0x30 +mat 0 +refs 4 +898 0.70808 0.8825 +917 0.704061 0.8825 +918 0.720633 0.6825 +899 0.724958 0.6825 +SURF 0x30 +mat 0 +refs 4 +899 0.724958 0.6825 +918 0.720633 0.6825 +919 0.740522 0.635 +900 0.74521 0.635 +SURF 0x30 +mat 0 +refs 4 +900 0.74521 0.635 +919 0.740522 0.635 +920 0.810127 0.555 +901 0.816096 0.555 +SURF 0x30 +mat 0 +refs 4 +901 0.816096 0.555 +920 0.810127 0.555 +921 0.871894 0.475 +902 0.878996 0.475 +SURF 0x30 +mat 0 +refs 4 +902 0.878996 0.475 +921 0.871894 0.475 +922 0.941075 0.3875 +903 0.94919 0.3875 +SURF 0x30 +mat 0 +refs 4 +903 0.94919 0.3875 +922 0.941075 0.3875 +923 0.979745 0.31 +904 0.988573 0.31 +SURF 0x30 +mat 0 +refs 4 +904 0.988573 0.31 +923 0.979745 0.31 +924 0.973302 0.247501 +905 0.982008 0.247501 +SURF 0x30 +mat 0 +refs 4 +905 0.982008 0.247501 +924 0.973302 0.247501 +925 0.960409 0.175 +906 0.96888 0.175 +SURF 0x30 +mat 0 +refs 4 +906 0.96888 0.175 +925 0.960409 0.175 +926 0.921739 0.105001 +907 0.929497 0.105001 +SURF 0x30 +mat 0 +refs 4 +907 0.929497 0.105001 +926 0.921739 0.105001 +927 0.821833 0.0549999 +908 0.827755 0.0549999 +SURF 0x30 +mat 0 +refs 4 +908 0.827755 0.0549999 +927 0.821833 0.0549999 +928 0.728375 0.0200004 +909 0.732578 0.0200004 +SURF 0x30 +mat 0 +refs 4 +909 0.732578 0.0200004 +928 0.728375 0.0200004 +929 0.5898 0 +910 0.591451 0 +SURF 0x30 +mat 1 +refs 4 +910 0.591451 0 +929 0.5898 0 +930 0.506009 0 +911 0.506121 0 +SURF 0x30 +mat 1 +refs 4 +912 0.498561 1 +931 0.498258 1 +932 0.540335 0.994999 +913 0.54165 0.994999 +SURF 0x30 +mat 0 +refs 4 +913 0.54165 0.994999 +932 0.540335 0.994999 +933 0.575941 0.984998 +914 0.57811 0.984998 +SURF 0x30 +mat 0 +refs 4 +914 0.57811 0.984998 +933 0.575941 0.984998 +934 0.656856 0.952498 +915 0.660972 0.952498 +SURF 0x30 +mat 0 +refs 4 +915 0.660972 0.952498 +934 0.656856 0.952498 +935 0.679512 0.929999 +916 0.684176 0.929999 +SURF 0x30 +mat 0 +refs 4 +916 0.684176 0.929999 +935 0.679512 0.929999 +936 0.698933 0.8825 +917 0.704061 0.8825 +SURF 0x30 +mat 0 +refs 4 +917 0.704061 0.8825 +936 0.698933 0.8825 +937 0.715115 0.6825 +918 0.720633 0.6825 +SURF 0x30 +mat 0 +refs 4 +918 0.720633 0.6825 +937 0.715115 0.6825 +938 0.734536 0.635 +919 0.740522 0.635 +SURF 0x30 +mat 0 +refs 4 +919 0.740522 0.635 +938 0.734536 0.635 +939 0.802507 0.555 +920 0.810127 0.555 +SURF 0x30 +mat 0 +refs 4 +920 0.810127 0.555 +939 0.802507 0.555 +940 0.86282 0.475 +921 0.871894 0.475 +SURF 0x30 +mat 0 +refs 4 +921 0.871894 0.475 +940 0.86282 0.475 +941 0.930711 0.3875 +922 0.941075 0.3875 +SURF 0x30 +mat 0 +refs 4 +922 0.941075 0.3875 +941 0.930711 0.3875 +942 0.968476 0.31 +923 0.979745 0.31 +SURF 0x30 +mat 0 +refs 4 +923 0.979745 0.31 +942 0.968476 0.31 +943 0.962181 0.247501 +924 0.973302 0.247501 +SURF 0x30 +mat 0 +refs 4 +924 0.973302 0.247501 +943 0.962181 0.247501 +944 0.949593 0.175 +925 0.960409 0.175 +SURF 0x30 +mat 0 +refs 4 +925 0.960409 0.175 +944 0.949593 0.175 +945 0.911828 0.105001 +926 0.921739 0.105001 +SURF 0x30 +mat 0 +refs 4 +926 0.921739 0.105001 +945 0.911828 0.105001 +946 0.814274 0.0549999 +927 0.821833 0.0549999 +SURF 0x30 +mat 0 +refs 4 +927 0.821833 0.0549999 +946 0.814274 0.0549999 +947 0.723011 0.0200004 +928 0.728375 0.0200004 +SURF 0x30 +mat 0 +refs 4 +928 0.728375 0.0200004 +947 0.723011 0.0200004 +948 0.587691 0 +929 0.5898 0 +SURF 0x30 +mat 1 +refs 4 +929 0.5898 0 +948 0.587691 0 +949 0.505868 0 +930 0.506009 0 +SURF 0x30 +mat 1 +refs 4 +931 0.498258 1 +950 0.497895 1 +951 0.538744 0.994999 +932 0.540335 0.994999 +SURF 0x30 +mat 0 +refs 4 +932 0.540335 0.994999 +951 0.538744 0.994999 +952 0.573311 0.984998 +933 0.575941 0.984998 +SURF 0x30 +mat 0 +refs 4 +933 0.575941 0.984998 +952 0.573311 0.984998 +953 0.651869 0.952498 +934 0.656856 0.952498 +SURF 0x30 +mat 0 +refs 4 +934 0.656856 0.952498 +953 0.651869 0.952498 +954 0.673862 0.929999 +935 0.679512 0.929999 +SURF 0x30 +mat 0 +refs 4 +935 0.679512 0.929999 +954 0.673862 0.929999 +955 0.692718 0.8825 +936 0.698933 0.8825 +SURF 0x30 +mat 0 +refs 4 +936 0.698933 0.8825 +955 0.692718 0.8825 +956 0.70843 0.6825 +937 0.715115 0.6825 +SURF 0x30 +mat 0 +refs 4 +937 0.715115 0.6825 +956 0.70843 0.6825 +957 0.727282 0.635 +938 0.734536 0.635 +SURF 0x30 +mat 0 +refs 4 +938 0.734536 0.635 +957 0.727282 0.635 +958 0.793272 0.555 +939 0.802507 0.555 +SURF 0x30 +mat 0 +refs 4 +939 0.802507 0.555 +958 0.793272 0.555 +959 0.851827 0.475 +940 0.86282 0.475 +SURF 0x30 +mat 0 +refs 4 +940 0.86282 0.475 +959 0.851827 0.475 +960 0.918154 0.3875 +941 0.930711 0.3875 +SURF 0x30 +mat 0 +refs 4 +941 0.930711 0.3875 +960 0.918154 0.3875 +961 0.954816 0.31 +942 0.968476 0.31 +SURF 0x30 +mat 0 +refs 4 +942 0.968476 0.31 +961 0.954816 0.31 +962 0.948706 0.247501 +943 0.962181 0.247501 +SURF 0x30 +mat 0 +refs 4 +943 0.962181 0.247501 +962 0.948706 0.247501 +963 0.936485 0.175 +944 0.949593 0.175 +SURF 0x30 +mat 0 +refs 4 +944 0.949593 0.175 +963 0.936485 0.175 +964 0.899823 0.105001 +945 0.911828 0.105001 +SURF 0x30 +mat 0 +refs 4 +945 0.911828 0.105001 +964 0.899823 0.105001 +965 0.80511 0.0549999 +946 0.814274 0.0549999 +SURF 0x30 +mat 0 +refs 4 +946 0.814274 0.0549999 +965 0.80511 0.0549999 +966 0.716507 0.0200004 +947 0.723011 0.0200004 +SURF 0x30 +mat 0 +refs 4 +947 0.723011 0.0200004 +966 0.716507 0.0200004 +967 0.585135 0 +948 0.587691 0 +SURF 0x30 +mat 1 +refs 4 +948 0.587691 0 +967 0.585135 0 +968 0.505697 0 +949 0.505868 0 +SURF 0x30 +mat 1 +refs 4 +950 0.497895 1 +969 0.497468 1 +970 0.536884 0.994999 +951 0.538744 0.994999 +SURF 0x30 +mat 0 +refs 4 +951 0.538744 0.994999 +970 0.536884 0.994999 +971 0.570234 0.984998 +952 0.573311 0.984998 +SURF 0x30 +mat 0 +refs 4 +952 0.573311 0.984998 +971 0.570234 0.984998 +972 0.646031 0.952498 +953 0.651869 0.952498 +SURF 0x30 +mat 0 +refs 4 +953 0.651869 0.952498 +972 0.646031 0.952498 +973 0.667254 0.929999 +954 0.673862 0.929999 +SURF 0x30 +mat 0 +refs 4 +954 0.673862 0.929999 +973 0.667254 0.929999 +974 0.685447 0.8825 +955 0.692718 0.8825 +SURF 0x30 +mat 0 +refs 4 +955 0.692718 0.8825 +974 0.685447 0.8825 +975 0.700607 0.6825 +956 0.70843 0.6825 +SURF 0x30 +mat 0 +refs 4 +956 0.70843 0.6825 +975 0.700607 0.6825 +976 0.718797 0.635 +957 0.727282 0.635 +SURF 0x30 +mat 0 +refs 4 +957 0.727282 0.635 +976 0.718797 0.635 +977 0.782467 0.555 +958 0.793272 0.555 +SURF 0x30 +mat 0 +refs 4 +958 0.793272 0.555 +977 0.782467 0.555 +978 0.838967 0.475 +959 0.851827 0.475 +SURF 0x30 +mat 0 +refs 4 +959 0.851827 0.475 +978 0.838967 0.475 +979 0.903464 0.3875 +960 0.918154 0.3875 +SURF 0x30 +mat 0 +refs 4 +960 0.918154 0.3875 +979 0.903464 0.3875 +980 0.938839 0.31 +961 0.954816 0.31 +SURF 0x30 +mat 0 +refs 4 +961 0.954816 0.31 +980 0.938839 0.31 +981 0.932944 0.247501 +962 0.948706 0.247501 +SURF 0x30 +mat 0 +refs 4 +962 0.948706 0.247501 +981 0.932944 0.247501 +982 0.921153 0.175 +963 0.936485 0.175 +SURF 0x30 +mat 0 +refs 4 +963 0.936485 0.175 +982 0.921153 0.175 +983 0.885779 0.105001 +964 0.899823 0.105001 +SURF 0x30 +mat 0 +refs 4 +964 0.899823 0.105001 +983 0.885779 0.105001 +984 0.794392 0.0549999 +965 0.80511 0.0549999 +SURF 0x30 +mat 0 +refs 4 +965 0.80511 0.0549999 +984 0.794392 0.0549999 +985 0.708904 0.0200004 +966 0.716507 0.0200004 +SURF 0x30 +mat 0 +refs 4 +966 0.716507 0.0200004 +985 0.708904 0.0200004 +986 0.582142 0 +967 0.585135 0 +SURF 0x30 +mat 1 +refs 4 +967 0.585135 0 +986 0.582142 0 +987 0.505498 0 +968 0.505697 0 +SURF 0x30 +mat 1 +refs 4 +969 0.497468 1 +988 0.496983 1 +989 0.534762 0.994999 +970 0.536884 0.994999 +SURF 0x30 +mat 0 +refs 4 +970 0.536884 0.994999 +989 0.534762 0.994999 +990 0.566727 0.984998 +971 0.570234 0.984998 +SURF 0x30 +mat 0 +refs 4 +971 0.570234 0.984998 +990 0.566727 0.984998 +991 0.639379 0.952498 +972 0.646031 0.952498 +SURF 0x30 +mat 0 +refs 4 +972 0.646031 0.952498 +991 0.639379 0.952498 +992 0.659721 0.929999 +973 0.667254 0.929999 +SURF 0x30 +mat 0 +refs 4 +973 0.667254 0.929999 +992 0.659721 0.929999 +993 0.677161 0.8825 +974 0.685447 0.8825 +SURF 0x30 +mat 0 +refs 4 +974 0.685447 0.8825 +993 0.677161 0.8825 +994 0.691689 0.6825 +975 0.700607 0.6825 +SURF 0x30 +mat 0 +refs 4 +975 0.700607 0.6825 +994 0.691689 0.6825 +995 0.709126 0.635 +976 0.718797 0.635 +SURF 0x30 +mat 0 +refs 4 +976 0.718797 0.635 +995 0.709126 0.635 +996 0.770156 0.555 +977 0.782467 0.555 +SURF 0x30 +mat 0 +refs 4 +977 0.782467 0.555 +996 0.770156 0.555 +997 0.824308 0.475 +978 0.838967 0.475 +SURF 0x30 +mat 0 +refs 4 +978 0.838967 0.475 +997 0.824308 0.475 +998 0.886721 0.3875 +979 0.903464 0.3875 +SURF 0x30 +mat 0 +refs 4 +979 0.903464 0.3875 +998 0.886721 0.3875 +999 0.920625 0.31 +980 0.938839 0.31 +SURF 0x30 +mat 0 +refs 4 +980 0.938839 0.31 +999 0.920625 0.31 +1000 0.914976 0.247501 +981 0.932944 0.247501 +SURF 0x30 +mat 0 +refs 4 +981 0.932944 0.247501 +1000 0.914976 0.247501 +1001 0.903673 0.175 +982 0.921153 0.175 +SURF 0x30 +mat 0 +refs 4 +982 0.921153 0.175 +1001 0.903673 0.175 +1002 0.869768 0.105001 +983 0.885779 0.105001 +SURF 0x30 +mat 0 +refs 4 +983 0.885779 0.105001 +1002 0.869768 0.105001 +1003 0.782175 0.0549999 +984 0.794392 0.0549999 +SURF 0x30 +mat 0 +refs 4 +984 0.794392 0.0549999 +1003 0.782175 0.0549999 +1004 0.700234 0.0200004 +985 0.708904 0.0200004 +SURF 0x30 +mat 0 +refs 4 +985 0.708904 0.0200004 +1004 0.700234 0.0200004 +1005 0.578736 0 +986 0.582142 0 +SURF 0x30 +mat 1 +refs 4 +986 0.582142 0 +1005 0.578736 0 +1006 0.50527 0 +987 0.505498 0 +SURF 0x30 +mat 1 +refs 4 +988 0.496983 1 +1007 0.496439 1 +1008 0.532388 0.994999 +989 0.534762 0.994999 +SURF 0x30 +mat 0 +refs 4 +989 0.534762 0.994999 +1008 0.532388 0.994999 +1009 0.562809 0.984998 +990 0.566727 0.984998 +SURF 0x30 +mat 0 +refs 4 +990 0.566727 0.984998 +1009 0.562809 0.984998 +1010 0.631947 0.952498 +991 0.639379 0.952498 +SURF 0x30 +mat 0 +refs 4 +991 0.639379 0.952498 +1010 0.631947 0.952498 +1011 0.651304 0.929999 +992 0.659721 0.929999 +SURF 0x30 +mat 0 +refs 4 +992 0.659721 0.929999 +1011 0.651304 0.929999 +1012 0.667896 0.8825 +993 0.677161 0.8825 +SURF 0x30 +mat 0 +refs 4 +993 0.677161 0.8825 +1012 0.667896 0.8825 +1013 0.681725 0.6825 +994 0.691689 0.6825 +SURF 0x30 +mat 0 +refs 4 +994 0.691689 0.6825 +1013 0.681725 0.6825 +1014 0.698317 0.635 +995 0.709126 0.635 +SURF 0x30 +mat 0 +refs 4 +995 0.709126 0.635 +1014 0.698317 0.635 +1015 0.756391 0.555 +996 0.770156 0.555 +SURF 0x30 +mat 0 +refs 4 +996 0.770156 0.555 +1015 0.756391 0.555 +1016 0.807924 0.475 +997 0.824308 0.475 +SURF 0x30 +mat 0 +refs 4 +997 0.824308 0.475 +1016 0.807924 0.475 +1017 0.868006 0.3875 +998 0.886721 0.3875 +SURF 0x30 +mat 0 +refs 4 +998 0.886721 0.3875 +1017 0.868006 0.3875 +1018 0.90027 0.31 +999 0.920625 0.31 +SURF 0x30 +mat 0 +refs 4 +999 0.920625 0.31 +1018 0.90027 0.31 +1019 0.894892 0.247501 +1000 0.914976 0.247501 +SURF 0x30 +mat 0 +refs 4 +1000 0.914976 0.247501 +1019 0.894892 0.247501 +1020 0.884138 0.175 +1001 0.903673 0.175 +SURF 0x30 +mat 0 +refs 4 +1001 0.903673 0.175 +1020 0.884138 0.175 +1021 0.851871 0.105001 +1002 0.869768 0.105001 +SURF 0x30 +mat 0 +refs 4 +1002 0.869768 0.105001 +1021 0.851871 0.105001 +1022 0.768518 0.0549999 +1003 0.782175 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1003 0.782175 0.0549999 +1022 0.768518 0.0549999 +1023 0.690542 0.0200004 +1004 0.700234 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1004 0.700234 0.0200004 +1023 0.690542 0.0200004 +1024 0.574922 0 +1005 0.578736 0 +SURF 0x30 +mat 1 +refs 4 +1005 0.578736 0 +1024 0.574922 0 +1025 0.505014 0 +1006 0.50527 0 +SURF 0x30 +mat 1 +refs 4 +1007 0.496439 1 +1026 0.49584 1 +1027 0.529779 0.994999 +1008 0.532388 0.994999 +SURF 0x30 +mat 0 +refs 4 +1008 0.532388 0.994999 +1027 0.529779 0.994999 +1028 0.558498 0.984998 +1009 0.562809 0.984998 +SURF 0x30 +mat 0 +refs 4 +1009 0.562809 0.984998 +1028 0.558498 0.984998 +1029 0.623765 0.952498 +1010 0.631947 0.952498 +SURF 0x30 +mat 0 +refs 4 +1010 0.631947 0.952498 +1029 0.623765 0.952498 +1030 0.642042 0.929999 +1011 0.651304 0.929999 +SURF 0x30 +mat 0 +refs 4 +1011 0.651304 0.929999 +1030 0.642042 0.929999 +1031 0.657703 0.8825 +1012 0.667896 0.8825 +SURF 0x30 +mat 0 +refs 4 +1012 0.667896 0.8825 +1031 0.657703 0.8825 +1032 0.670758 0.6825 +1013 0.681725 0.6825 +SURF 0x30 +mat 0 +refs 4 +1013 0.681725 0.6825 +1032 0.670758 0.6825 +1033 0.686423 0.635 +1014 0.698317 0.635 +SURF 0x30 +mat 0 +refs 4 +1014 0.698317 0.635 +1033 0.686423 0.635 +1034 0.741248 0.555 +1015 0.756391 0.555 +SURF 0x30 +mat 0 +refs 4 +1015 0.756391 0.555 +1034 0.741248 0.555 +1035 0.789896 0.475 +1016 0.807924 0.475 +SURF 0x30 +mat 0 +refs 4 +1016 0.807924 0.475 +1035 0.789896 0.475 +1036 0.847415 0.3875 +1017 0.868006 0.3875 +SURF 0x30 +mat 0 +refs 4 +1017 0.868006 0.3875 +1036 0.847415 0.3875 +1037 0.877876 0.31 +1018 0.90027 0.31 +SURF 0x30 +mat 0 +refs 4 +1018 0.90027 0.31 +1037 0.877876 0.31 +1038 0.872798 0.247501 +1019 0.894892 0.247501 +SURF 0x30 +mat 0 +refs 4 +1019 0.894892 0.247501 +1038 0.872798 0.247501 +1039 0.862646 0.175 +1020 0.884138 0.175 +SURF 0x30 +mat 0 +refs 4 +1020 0.884138 0.175 +1039 0.862646 0.175 +1040 0.832184 0.105001 +1021 0.851871 0.105001 +SURF 0x30 +mat 0 +refs 4 +1021 0.851871 0.105001 +1040 0.832184 0.105001 +1041 0.753496 0.0549999 +1022 0.768518 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1022 0.768518 0.0549999 +1041 0.753496 0.0549999 +1042 0.679882 0.0200004 +1023 0.690542 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1023 0.690542 0.0200004 +1042 0.679882 0.0200004 +1043 0.570732 0 +1024 0.574922 0 +SURF 0x30 +mat 1 +refs 4 +1024 0.574922 0 +1043 0.570732 0 +1044 0.504735 0 +1025 0.505014 0 +SURF 0x30 +mat 1 +refs 4 +1026 0.49584 1 +1045 0.495191 1 +1046 0.526947 0.994999 +1027 0.529779 0.994999 +SURF 0x30 +mat 0 +refs 4 +1027 0.529779 0.994999 +1046 0.526947 0.994999 +1047 0.553817 0.984998 +1028 0.558498 0.984998 +SURF 0x30 +mat 0 +refs 4 +1028 0.558498 0.984998 +1047 0.553817 0.984998 +1048 0.614884 0.952498 +1029 0.623765 0.952498 +SURF 0x30 +mat 0 +refs 4 +1029 0.623765 0.952498 +1048 0.614884 0.952498 +1049 0.631981 0.929999 +1030 0.642042 0.929999 +SURF 0x30 +mat 0 +refs 4 +1030 0.642042 0.929999 +1049 0.631981 0.929999 +1050 0.646636 0.8825 +1031 0.657703 0.8825 +SURF 0x30 +mat 0 +refs 4 +1031 0.657703 0.8825 +1050 0.646636 0.8825 +1051 0.65885 0.6825 +1032 0.670758 0.6825 +SURF 0x30 +mat 0 +refs 4 +1032 0.670758 0.6825 +1051 0.65885 0.6825 +1052 0.673506 0.635 +1033 0.686423 0.635 +SURF 0x30 +mat 0 +refs 4 +1033 0.686423 0.635 +1052 0.673506 0.635 +1053 0.724803 0.555 +1034 0.741248 0.555 +SURF 0x30 +mat 0 +refs 4 +1034 0.741248 0.555 +1053 0.724803 0.555 +1054 0.77032 0.475 +1035 0.789896 0.475 +SURF 0x30 +mat 0 +refs 4 +1035 0.789896 0.475 +1054 0.77032 0.475 +1055 0.825055 0.3875 +1036 0.847415 0.3875 +SURF 0x30 +mat 0 +refs 4 +1036 0.847415 0.3875 +1055 0.825055 0.3875 +1056 0.853552 0.31 +1037 0.877876 0.31 +SURF 0x30 +mat 0 +refs 4 +1037 0.877876 0.31 +1056 0.853552 0.31 +1057 0.848804 0.247501 +1038 0.872798 0.247501 +SURF 0x30 +mat 0 +refs 4 +1038 0.872798 0.247501 +1057 0.848804 0.247501 +1058 0.839304 0.175 +1039 0.862646 0.175 +SURF 0x30 +mat 0 +refs 4 +1039 0.862646 0.175 +1058 0.839304 0.175 +1059 0.810803 0.105001 +1040 0.832184 0.105001 +SURF 0x30 +mat 0 +refs 4 +1040 0.832184 0.105001 +1059 0.810803 0.105001 +1060 0.737179 0.0549999 +1041 0.753496 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1041 0.753496 0.0549999 +1060 0.737179 0.0549999 +1061 0.668303 0.0200004 +1042 0.679882 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1042 0.679882 0.0200004 +1061 0.668303 0.0200004 +1062 0.566179 0 +1043 0.570732 0 +SURF 0x30 +mat 1 +refs 4 +1043 0.570732 0 +1062 0.566179 0 +1063 0.504429 0 +1044 0.504735 0 +SURF 0x30 +mat 1 +refs 4 +1045 0.495191 1 +1064 0.494495 1 +1065 0.523904 0.994999 +1046 0.526947 0.994999 +SURF 0x30 +mat 0 +refs 4 +1046 0.526947 0.994999 +1065 0.523904 0.994999 +1066 0.548786 0.984998 +1047 0.553817 0.984998 +SURF 0x30 +mat 0 +refs 4 +1047 0.553817 0.984998 +1066 0.548786 0.984998 +1067 0.605343 0.952498 +1048 0.614884 0.952498 +SURF 0x30 +mat 0 +refs 4 +1048 0.614884 0.952498 +1067 0.605343 0.952498 +1068 0.621176 0.929999 +1049 0.631981 0.929999 +SURF 0x30 +mat 0 +refs 4 +1049 0.631981 0.929999 +1068 0.621176 0.929999 +1069 0.634752 0.8825 +1050 0.646636 0.8825 +SURF 0x30 +mat 0 +refs 4 +1050 0.646636 0.8825 +1069 0.634752 0.8825 +1070 0.646061 0.6825 +1051 0.65885 0.6825 +SURF 0x30 +mat 0 +refs 4 +1051 0.65885 0.6825 +1070 0.646061 0.6825 +1071 0.659634 0.635 +1052 0.673506 0.635 +SURF 0x30 +mat 0 +refs 4 +1052 0.673506 0.635 +1071 0.659634 0.635 +1072 0.707142 0.555 +1053 0.724803 0.555 +SURF 0x30 +mat 0 +refs 4 +1053 0.724803 0.555 +1072 0.707142 0.555 +1073 0.749295 0.475 +1054 0.77032 0.475 +SURF 0x30 +mat 0 +refs 4 +1054 0.77032 0.475 +1073 0.749295 0.475 +1074 0.801037 0.3875 +1055 0.825055 0.3875 +SURF 0x30 +mat 0 +refs 4 +1055 0.825055 0.3875 +1074 0.801037 0.3875 +1075 0.827429 0.31 +1056 0.853552 0.31 +SURF 0x30 +mat 0 +refs 4 +1056 0.853552 0.31 +1075 0.827429 0.31 +1076 0.823031 0.247501 +1057 0.848804 0.247501 +SURF 0x30 +mat 0 +refs 4 +1057 0.848804 0.247501 +1076 0.823031 0.247501 +1077 0.814233 0.175 +1058 0.839304 0.175 +SURF 0x30 +mat 0 +refs 4 +1058 0.839304 0.175 +1077 0.814233 0.175 +1078 0.787838 0.105001 +1059 0.810803 0.105001 +SURF 0x30 +mat 0 +refs 4 +1059 0.810803 0.105001 +1078 0.787838 0.105001 +1079 0.719655 0.0549999 +1060 0.737179 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1060 0.737179 0.0549999 +1079 0.719655 0.0549999 +1080 0.655867 0.0200004 +1061 0.668303 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1061 0.668303 0.0200004 +1080 0.655867 0.0200004 +1081 0.561289 0 +1062 0.566179 0 +SURF 0x30 +mat 1 +refs 4 +1062 0.566179 0 +1081 0.561289 0 +1082 0.504103 0 +1063 0.504429 0 +SURF 0x30 +mat 1 +refs 4 +1064 0.494495 1 +1083 0.493752 1 +1084 0.520665 0.994999 +1065 0.523904 0.994999 +SURF 0x30 +mat 0 +refs 4 +1065 0.523904 0.994999 +1084 0.520665 0.994999 +1085 0.543435 0.984998 +1066 0.548786 0.984998 +SURF 0x30 +mat 0 +refs 4 +1066 0.548786 0.984998 +1085 0.543435 0.984998 +1086 0.59519 0.952498 +1067 0.605343 0.952498 +SURF 0x30 +mat 0 +refs 4 +1067 0.605343 0.952498 +1086 0.59519 0.952498 +1087 0.609681 0.929999 +1068 0.621176 0.929999 +SURF 0x30 +mat 0 +refs 4 +1068 0.621176 0.929999 +1087 0.609681 0.929999 +1088 0.622104 0.8825 +1069 0.634752 0.8825 +SURF 0x30 +mat 0 +refs 4 +1069 0.634752 0.8825 +1088 0.622104 0.8825 +1089 0.632455 0.6825 +1070 0.646061 0.6825 +SURF 0x30 +mat 0 +refs 4 +1070 0.646061 0.6825 +1089 0.632455 0.6825 +1090 0.644874 0.635 +1071 0.659634 0.635 +SURF 0x30 +mat 0 +refs 4 +1071 0.659634 0.635 +1090 0.644874 0.635 +1091 0.68835 0.555 +1072 0.707142 0.555 +SURF 0x30 +mat 0 +refs 4 +1072 0.707142 0.555 +1091 0.68835 0.555 +1092 0.726925 0.475 +1073 0.749295 0.475 +SURF 0x30 +mat 0 +refs 4 +1073 0.749295 0.475 +1092 0.726925 0.475 +1093 0.775486 0.3875 +1074 0.801037 0.3875 +SURF 0x30 +mat 0 +refs 4 +1074 0.801037 0.3875 +1093 0.775486 0.3875 +1094 0.799638 0.31 +1075 0.827429 0.31 +SURF 0x30 +mat 0 +refs 4 +1075 0.827429 0.31 +1094 0.799638 0.31 +1095 0.795613 0.247501 +1076 0.823031 0.247501 +SURF 0x30 +mat 0 +refs 4 +1076 0.823031 0.247501 +1095 0.795613 0.247501 +1096 0.787562 0.175 +1077 0.814233 0.175 +SURF 0x30 +mat 0 +refs 4 +1077 0.814233 0.175 +1096 0.787562 0.175 +1097 0.76341 0.105001 +1078 0.787838 0.105001 +SURF 0x30 +mat 0 +refs 4 +1078 0.787838 0.105001 +1097 0.76341 0.105001 +1098 0.701011 0.0549999 +1079 0.719655 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1079 0.719655 0.0549999 +1098 0.701011 0.0549999 +1099 0.642638 0.0200004 +1080 0.655867 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1080 0.655867 0.0200004 +1099 0.642638 0.0200004 +1100 0.556087 0 +1081 0.561289 0 +SURF 0x30 +mat 1 +refs 4 +1081 0.561289 0 +1100 0.556087 0 +1101 0.503753 0 +1082 0.504103 0 +SURF 0x30 +mat 1 +refs 4 +1083 0.493752 1 +1102 0.492968 1 +1103 0.517248 0.994999 +1084 0.520665 0.994999 +SURF 0x30 +mat 0 +refs 4 +1084 0.520665 0.994999 +1103 0.517248 0.994999 +1104 0.537792 0.984998 +1085 0.543435 0.984998 +SURF 0x30 +mat 0 +refs 4 +1085 0.543435 0.984998 +1104 0.537792 0.984998 +1105 0.584483 0.952498 +1086 0.59519 0.952498 +SURF 0x30 +mat 0 +refs 4 +1086 0.59519 0.952498 +1105 0.584483 0.952498 +1106 0.597555 0.929999 +1087 0.609681 0.929999 +SURF 0x30 +mat 0 +refs 4 +1087 0.609681 0.929999 +1106 0.597555 0.929999 +1107 0.608763 0.8825 +1088 0.622104 0.8825 +SURF 0x30 +mat 0 +refs 4 +1088 0.622104 0.8825 +1107 0.608763 0.8825 +1108 0.618098 0.6825 +1089 0.632455 0.6825 +SURF 0x30 +mat 0 +refs 4 +1089 0.632455 0.6825 +1108 0.618098 0.6825 +1109 0.629307 0.635 +1090 0.644874 0.635 +SURF 0x30 +mat 0 +refs 4 +1090 0.644874 0.635 +1109 0.629307 0.635 +1110 0.668525 0.555 +1091 0.68835 0.555 +SURF 0x30 +mat 0 +refs 4 +1091 0.68835 0.555 +1110 0.668525 0.555 +1111 0.703328 0.475 +1092 0.726925 0.475 +SURF 0x30 +mat 0 +refs 4 +1092 0.726925 0.475 +1111 0.703328 0.475 +1112 0.748529 0.3875 +1093 0.775486 0.3875 +SURF 0x30 +mat 0 +refs 4 +1093 0.775486 0.3875 +1112 0.748529 0.3875 +1113 0.77032 0.31 +1094 0.799638 0.31 +SURF 0x30 +mat 0 +refs 4 +1094 0.799638 0.31 +1113 0.77032 0.31 +1114 0.766688 0.247501 +1095 0.795613 0.247501 +SURF 0x30 +mat 0 +refs 4 +1095 0.795613 0.247501 +1114 0.766688 0.247501 +1115 0.759425 0.175 +1096 0.787562 0.175 +SURF 0x30 +mat 0 +refs 4 +1096 0.787562 0.175 +1115 0.759425 0.175 +1116 0.737636 0.105001 +1097 0.76341 0.105001 +SURF 0x30 +mat 0 +refs 4 +1097 0.76341 0.105001 +1116 0.737636 0.105001 +1117 0.681341 0.0549999 +1098 0.701011 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1098 0.701011 0.0549999 +1117 0.681341 0.0549999 +1118 0.628682 0.0200004 +1099 0.642638 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1099 0.642638 0.0200004 +1118 0.628682 0.0200004 +1119 0.550598 0 +1100 0.556087 0 +SURF 0x30 +mat 1 +refs 4 +1100 0.556087 0 +1119 0.550598 0 +1120 0.503386 0 +1101 0.503753 0 +SURF 0x30 +mat 1 +refs 4 +1102 0.492968 1 +1121 0.492148 1 +1122 0.51367 0.994999 +1103 0.517248 0.994999 +SURF 0x30 +mat 0 +refs 4 +1103 0.517248 0.994999 +1122 0.51367 0.994999 +1123 0.531884 0.984998 +1104 0.537792 0.984998 +SURF 0x30 +mat 0 +refs 4 +1104 0.537792 0.984998 +1123 0.531884 0.984998 +1124 0.573271 0.952498 +1105 0.584483 0.952498 +SURF 0x30 +mat 0 +refs 4 +1105 0.584483 0.952498 +1124 0.573271 0.952498 +1125 0.58486 0.929999 +1106 0.597555 0.929999 +SURF 0x30 +mat 0 +refs 4 +1106 0.597555 0.929999 +1125 0.58486 0.929999 +1126 0.594794 0.8825 +1107 0.608763 0.8825 +SURF 0x30 +mat 0 +refs 4 +1107 0.608763 0.8825 +1126 0.594794 0.8825 +1127 0.60307 0.6825 +1108 0.618098 0.6825 +SURF 0x30 +mat 0 +refs 4 +1108 0.618098 0.6825 +1127 0.60307 0.6825 +1128 0.613004 0.635 +1109 0.629307 0.635 +SURF 0x30 +mat 0 +refs 4 +1109 0.629307 0.635 +1128 0.613004 0.635 +1129 0.647773 0.555 +1110 0.668525 0.555 +SURF 0x30 +mat 0 +refs 4 +1110 0.668525 0.555 +1129 0.647773 0.555 +1130 0.678621 0.475 +1111 0.703328 0.475 +SURF 0x30 +mat 0 +refs 4 +1111 0.703328 0.475 +1130 0.678621 0.475 +1131 0.720307 0.3875 +1112 0.748529 0.3875 +SURF 0x30 +mat 0 +refs 4 +1112 0.748529 0.3875 +1131 0.720307 0.3875 +1132 0.739624 0.31 +1113 0.77032 0.31 +SURF 0x30 +mat 0 +refs 4 +1113 0.77032 0.31 +1132 0.739624 0.31 +1133 0.736405 0.247501 +1114 0.766688 0.247501 +SURF 0x30 +mat 0 +refs 4 +1114 0.766688 0.247501 +1133 0.736405 0.247501 +1134 0.729965 0.175 +1115 0.759425 0.175 +SURF 0x30 +mat 0 +refs 4 +1115 0.759425 0.175 +1134 0.729965 0.175 +1135 0.710649 0.105001 +1116 0.737636 0.105001 +SURF 0x30 +mat 0 +refs 4 +1116 0.737636 0.105001 +1135 0.710649 0.105001 +1136 0.66075 0.0549999 +1117 0.681341 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1117 0.681341 0.0549999 +1136 0.66075 0.0549999 +1137 0.61407 0.0200004 +1118 0.628682 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1118 0.628682 0.0200004 +1137 0.61407 0.0200004 +1138 0.544854 0 +1119 0.550598 0 +SURF 0x30 +mat 1 +refs 4 +1119 0.550598 0 +1138 0.544854 0 +1139 0.503003 0 +1120 0.503386 0 +SURF 0x30 +mat 1 +refs 4 +1121 0.492148 1 +1140 0.491297 1 +1141 0.509951 0.994999 +1122 0.51367 0.994999 +SURF 0x30 +mat 0 +refs 4 +1122 0.51367 0.994999 +1141 0.509951 0.994999 +1142 0.525736 0.984998 +1123 0.531884 0.984998 +SURF 0x30 +mat 0 +refs 4 +1123 0.531884 0.984998 +1142 0.525736 0.984998 +1143 0.561615 0.952498 +1124 0.573271 0.952498 +SURF 0x30 +mat 0 +refs 4 +1124 0.573271 0.952498 +1143 0.561615 0.952498 +1144 0.57166 0.929999 +1125 0.58486 0.929999 +SURF 0x30 +mat 0 +refs 4 +1125 0.58486 0.929999 +1144 0.57166 0.929999 +1145 0.580269 0.8825 +1126 0.594794 0.8825 +SURF 0x30 +mat 0 +refs 4 +1126 0.594794 0.8825 +1145 0.580269 0.8825 +1146 0.587446 0.6825 +1127 0.60307 0.6825 +SURF 0x30 +mat 0 +refs 4 +1127 0.60307 0.6825 +1146 0.587446 0.6825 +1147 0.596055 0.635 +1128 0.613004 0.635 +SURF 0x30 +mat 0 +refs 4 +1128 0.613004 0.635 +1147 0.596055 0.635 +1148 0.62619 0.555 +1129 0.647773 0.555 +SURF 0x30 +mat 0 +refs 4 +1129 0.647773 0.555 +1148 0.62619 0.555 +1149 0.652931 0.475 +1130 0.678621 0.475 +SURF 0x30 +mat 0 +refs 4 +1130 0.678621 0.475 +1149 0.652931 0.475 +1150 0.690966 0.3875 +1131 0.720307 0.3875 +SURF 0x30 +mat 0 +refs 4 +1131 0.720307 0.3875 +1150 0.690966 0.3875 +1151 0.707707 0.31 +1132 0.739624 0.31 +SURF 0x30 +mat 0 +refs 4 +1132 0.739624 0.31 +1151 0.707707 0.31 +1152 0.704919 0.247501 +1133 0.736405 0.247501 +SURF 0x30 +mat 0 +refs 4 +1133 0.736405 0.247501 +1152 0.704919 0.247501 +1153 0.699336 0.175 +1134 0.729965 0.175 +SURF 0x30 +mat 0 +refs 4 +1134 0.729965 0.175 +1153 0.699336 0.175 +1154 0.682592 0.105001 +1135 0.710649 0.105001 +SURF 0x30 +mat 0 +refs 4 +1135 0.710649 0.105001 +1154 0.682592 0.105001 +1155 0.639339 0.0549999 +1136 0.66075 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1136 0.66075 0.0549999 +1155 0.639339 0.0549999 +1156 0.598876 0.0200004 +1137 0.61407 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1137 0.61407 0.0200004 +1156 0.598876 0.0200004 +1157 0.538879 0 +1138 0.544854 0 +SURF 0x30 +mat 1 +refs 4 +1138 0.544854 0 +1157 0.538879 0 +1158 0.502603 0 +1139 0.503003 0 +SURF 0x30 +mat 1 +refs 4 +1140 0.491297 1 +1159 0.490416 1 +1160 0.50611 0.994999 +1141 0.509951 0.994999 +SURF 0x30 +mat 0 +refs 4 +1141 0.509951 0.994999 +1160 0.50611 0.994999 +1161 0.519391 0.984998 +1142 0.525736 0.984998 +SURF 0x30 +mat 0 +refs 4 +1142 0.525736 0.984998 +1161 0.519391 0.984998 +1162 0.549569 0.952498 +1143 0.561615 0.952498 +SURF 0x30 +mat 0 +refs 4 +1143 0.561615 0.952498 +1162 0.549569 0.952498 +1163 0.55802 0.929999 +1144 0.57166 0.929999 +SURF 0x30 +mat 0 +refs 4 +1144 0.57166 0.929999 +1163 0.55802 0.929999 +1164 0.565264 0.8825 +1145 0.580269 0.8825 +SURF 0x30 +mat 0 +refs 4 +1145 0.580269 0.8825 +1164 0.565264 0.8825 +1165 0.5713 0.6825 +1146 0.587446 0.6825 +SURF 0x30 +mat 0 +refs 4 +1146 0.587446 0.6825 +1165 0.5713 0.6825 +1166 0.578544 0.635 +1147 0.596055 0.635 +SURF 0x30 +mat 0 +refs 4 +1147 0.596055 0.635 +1166 0.578544 0.635 +1167 0.603894 0.555 +1148 0.62619 0.555 +SURF 0x30 +mat 0 +refs 4 +1148 0.62619 0.555 +1167 0.603894 0.555 +1168 0.626391 0.475 +1149 0.652931 0.475 +SURF 0x30 +mat 0 +refs 4 +1149 0.652931 0.475 +1168 0.626391 0.475 +1169 0.660646 0.3875 +1150 0.690966 0.3875 +SURF 0x30 +mat 0 +refs 4 +1150 0.690966 0.3875 +1169 0.660646 0.3875 +1170 0.674733 0.31 +1151 0.707707 0.31 +SURF 0x30 +mat 0 +refs 4 +1151 0.707707 0.31 +1170 0.674733 0.31 +1171 0.672386 0.247501 +1152 0.704919 0.247501 +SURF 0x30 +mat 0 +refs 4 +1152 0.704919 0.247501 +1171 0.672386 0.247501 +1172 0.667691 0.175 +1153 0.699336 0.175 +SURF 0x30 +mat 0 +refs 4 +1153 0.699336 0.175 +1172 0.667691 0.175 +1173 0.653604 0.105001 +1154 0.682592 0.105001 +SURF 0x30 +mat 0 +refs 4 +1154 0.682592 0.105001 +1173 0.653604 0.105001 +1174 0.422996 0.0519236 +1155 0.639339 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1155 0.639339 0.0549999 +1174 0.422996 0.0519236 +1175 0.583178 0.0200004 +1156 0.598876 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1156 0.598876 0.0200004 +1175 0.583178 0.0200004 +1176 0.532708 0 +1157 0.538879 0 +SURF 0x30 +mat 1 +refs 4 +1157 0.538879 0 +1176 0.532708 0 +1177 0.502189 0 +1158 0.502603 0 +SURF 0x30 +mat 1 +refs 4 +1159 0.490416 1 +1178 0.489511 1 +1179 0.502166 0.994999 +1160 0.50611 0.994999 +SURF 0x30 +mat 0 +refs 4 +1160 0.50611 0.994999 +1179 0.502166 0.994999 +1180 0.51287 0.984998 +1161 0.519391 0.984998 +SURF 0x30 +mat 0 +refs 4 +1161 0.519391 0.984998 +1180 0.51287 0.984998 +1181 0.537201 0.952498 +1162 0.549569 0.952498 +SURF 0x30 +mat 0 +refs 4 +1162 0.549569 0.952498 +1181 0.537201 0.952498 +1182 0.544014 0.929999 +1163 0.55802 0.929999 +SURF 0x30 +mat 0 +refs 4 +1163 0.55802 0.929999 +1182 0.544014 0.929999 +1183 0.549852 0.8825 +1164 0.565264 0.8825 +SURF 0x30 +mat 0 +refs 4 +1164 0.565264 0.8825 +1183 0.549852 0.8825 +1184 0.554718 0.6825 +1165 0.5713 0.6825 +SURF 0x30 +mat 0 +refs 4 +1165 0.5713 0.6825 +1184 0.554718 0.6825 +1185 0.560559 0.635 +1166 0.578544 0.635 +SURF 0x30 +mat 0 +refs 4 +1166 0.578544 0.635 +1185 0.560559 0.635 +1186 0.580996 0.555 +1167 0.603894 0.555 +SURF 0x30 +mat 0 +refs 4 +1167 0.603894 0.555 +1186 0.580996 0.555 +1187 0.599132 0.475 +1168 0.626391 0.475 +SURF 0x30 +mat 0 +refs 4 +1168 0.626391 0.475 +1187 0.599132 0.475 +1188 0.629512 0.3875 +1169 0.660646 0.3875 +SURF 0x30 +mat 0 +refs 4 +1169 0.660646 0.3875 +1188 0.629512 0.3875 +1189 0.640865 0.31 +1170 0.674733 0.31 +SURF 0x30 +mat 0 +refs 4 +1170 0.674733 0.31 +1189 0.640865 0.31 +1190 0.638975 0.247501 +1171 0.672386 0.247501 +SURF 0x30 +mat 0 +refs 4 +1171 0.672386 0.247501 +1190 0.638975 0.247501 +1191 0.635189 0.175 +1172 0.667691 0.175 +SURF 0x30 +mat 0 +refs 4 +1172 0.667691 0.175 +1191 0.635189 0.175 +1174 0.422996 0.0519236 +1173 0.653604 0.105001 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1192 0.567056 0.0200004 +1175 0.583178 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1175 0.583178 0.0200004 +1192 0.567056 0.0200004 +1193 0.526369 0 +1176 0.532708 0 +SURF 0x30 +mat 1 +refs 4 +1176 0.532708 0 +1193 0.526369 0 +1194 0.501766 0 +1177 0.502189 0 +SURF 0x30 +mat 1 +refs 4 +1178 0.489511 1 +1195 0.48859 1 +1196 0.498134 0.994999 +1179 0.502166 0.994999 +SURF 0x30 +mat 0 +refs 4 +1179 0.502166 0.994999 +1196 0.498134 0.994999 +1197 0.506211 0.984998 +1180 0.51287 0.984998 +SURF 0x30 +mat 0 +refs 4 +1180 0.51287 0.984998 +1197 0.506211 0.984998 +1198 0.524569 0.952498 +1181 0.537201 0.952498 +SURF 0x30 +mat 0 +refs 4 +1181 0.537201 0.952498 +1198 0.524569 0.952498 +1199 0.529711 0.929999 +1182 0.544014 0.929999 +SURF 0x30 +mat 0 +refs 4 +1182 0.544014 0.929999 +1199 0.529711 0.929999 +1200 0.534117 0.8825 +1183 0.549852 0.8825 +SURF 0x30 +mat 0 +refs 4 +1183 0.549852 0.8825 +1200 0.534117 0.8825 +1201 0.537786 0.6825 +1184 0.554718 0.6825 +SURF 0x30 +mat 0 +refs 4 +1184 0.554718 0.6825 +1201 0.537786 0.6825 +1202 0.542194 0.635 +1185 0.560559 0.635 +SURF 0x30 +mat 0 +refs 4 +1185 0.560559 0.635 +1202 0.542194 0.635 +1203 0.557613 0.555 +1186 0.580996 0.555 +SURF 0x30 +mat 0 +refs 4 +1186 0.580996 0.555 +1203 0.557613 0.555 +1204 0.571297 0.475 +1187 0.599132 0.475 +SURF 0x30 +mat 0 +refs 4 +1187 0.599132 0.475 +1204 0.571297 0.475 +1205 0.597716 0.3875 +1188 0.629512 0.3875 +SURF 0x30 +mat 0 +refs 4 +1188 0.629512 0.3875 +1205 0.597716 0.3875 +1206 0.606285 0.31 +1189 0.640865 0.31 +SURF 0x30 +mat 0 +refs 4 +1189 0.640865 0.31 +1206 0.606285 0.31 +1174 0.422996 0.0519236 +1190 0.638975 0.247501 +SURF 0x30 +mat 0 +refs 3 +1190 0.638975 0.247501 +1174 0.422996 0.0519236 +1191 0.635189 0.175 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1207 0.550595 0.0200004 +1192 0.567056 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1192 0.567056 0.0200004 +1207 0.550595 0.0200004 +1208 0.519895 0 +1193 0.526369 0 +SURF 0x30 +mat 1 +refs 4 +1193 0.526369 0 +1208 0.519895 0 +1209 0.501332 0 +1194 0.501766 0 +SURF 0x30 +mat 1 +refs 4 +1195 0.48859 1 +1210 0.487651 1 +1211 0.494041 0.994999 +1196 0.498134 0.994999 +SURF 0x30 +mat 0 +refs 4 +1196 0.498134 0.994999 +1211 0.494041 0.994999 +1212 0.499449 0.984998 +1197 0.506211 0.984998 +SURF 0x30 +mat 0 +refs 4 +1197 0.506211 0.984998 +1212 0.499449 0.984998 +1213 0.51174 0.952498 +1198 0.524569 0.952498 +SURF 0x30 +mat 0 +refs 4 +1198 0.524569 0.952498 +1213 0.51174 0.952498 +1214 0.51518 0.929999 +1199 0.529711 0.929999 +SURF 0x30 +mat 0 +refs 4 +1199 0.529711 0.929999 +1214 0.51518 0.929999 +1215 0.518133 0.8825 +1200 0.534117 0.8825 +SURF 0x30 +mat 0 +refs 4 +1200 0.534117 0.8825 +1215 0.518133 0.8825 +1216 0.520591 0.6825 +1201 0.537786 0.6825 +SURF 0x30 +mat 0 +refs 4 +1201 0.537786 0.6825 +1216 0.520591 0.6825 +1217 0.52354 0.635 +1202 0.542194 0.635 +SURF 0x30 +mat 0 +refs 4 +1202 0.542194 0.635 +1217 0.52354 0.635 +1218 0.533864 0.555 +1203 0.557613 0.555 +SURF 0x30 +mat 0 +refs 4 +1203 0.557613 0.555 +1218 0.533864 0.555 +1219 0.543025 0.475 +1204 0.571297 0.475 +SURF 0x30 +mat 0 +refs 4 +1204 0.571297 0.475 +1219 0.543025 0.475 +1220 0.565422 0.3875 +1205 0.597716 0.3875 +SURF 0x30 +mat 0 +refs 4 +1205 0.597716 0.3875 +1220 0.565422 0.3875 +1221 0.571159 0.31 +1206 0.606285 0.31 +SURF 0x30 +mat 0 +refs 3 +1206 0.606285 0.31 +1221 0.571159 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1222 0.533875 0.0200004 +1207 0.550595 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1207 0.550595 0.0200004 +1222 0.533875 0.0200004 +1223 0.513321 0 +1208 0.519895 0 +SURF 0x30 +mat 1 +refs 4 +1208 0.519895 0 +1223 0.513321 0 +1224 0.500891 0 +1209 0.501332 0 +SURF 0x30 +mat 1 +refs 4 +1210 0.487651 1 +1225 0.486703 1 +1226 0.489908 0.994999 +1211 0.494041 0.994999 +SURF 0x30 +mat 0 +refs 4 +1211 0.494041 0.994999 +1226 0.489908 0.994999 +1227 0.492618 0.984998 +1212 0.499449 0.984998 +SURF 0x30 +mat 0 +refs 4 +1212 0.499449 0.984998 +1227 0.492618 0.984998 +1228 0.498779 0.952498 +1213 0.51174 0.952498 +SURF 0x30 +mat 0 +refs 4 +1213 0.51174 0.952498 +1228 0.498779 0.952498 +1229 0.500504 0.929999 +1214 0.51518 0.929999 +SURF 0x30 +mat 0 +refs 4 +1214 0.51518 0.929999 +1229 0.500504 0.929999 +1230 0.501984 0.8825 +1215 0.518133 0.8825 +SURF 0x30 +mat 0 +refs 4 +1215 0.518133 0.8825 +1230 0.501984 0.8825 +1231 0.503215 0.6825 +1216 0.520591 0.6825 +SURF 0x30 +mat 0 +refs 4 +1216 0.520591 0.6825 +1231 0.503215 0.6825 +1232 0.504695 0.635 +1217 0.52354 0.635 +SURF 0x30 +mat 0 +refs 4 +1217 0.52354 0.635 +1232 0.504695 0.635 +1233 0.50987 0.555 +1218 0.533864 0.555 +SURF 0x30 +mat 0 +refs 4 +1218 0.533864 0.555 +1233 0.50987 0.555 +1234 0.514461 0.475 +1219 0.543025 0.475 +SURF 0x30 +mat 0 +refs 4 +1219 0.543025 0.475 +1234 0.514461 0.475 +1235 0.532795 0.3875 +1220 0.565422 0.3875 +SURF 0x30 +mat 0 +refs 4 +1220 0.565422 0.3875 +1235 0.532795 0.3875 +1236 0.53567 0.31 +1221 0.571159 0.31 +SURF 0x30 +mat 0 +refs 3 +1221 0.571159 0.31 +1236 0.53567 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1237 0.516979 0.0200004 +1222 0.533875 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1222 0.533875 0.0200004 +1237 0.516979 0.0200004 +1238 0.506679 0 +1223 0.513321 0 +SURF 0x30 +mat 1 +refs 4 +1223 0.513321 0 +1238 0.506679 0 +1239 0.500447 0 +1224 0.500891 0 +SURF 0x30 +mat 1 +refs 4 +1225 0.486703 1 +1240 0.485751 1 +1241 0.485751 0.994999 +1226 0.489908 0.994999 +SURF 0x30 +mat 0 +refs 4 +1226 0.489908 0.994999 +1241 0.485751 0.994999 +1242 0.485751 0.984998 +1227 0.492618 0.984998 +SURF 0x30 +mat 0 +refs 4 +1227 0.492618 0.984998 +1242 0.485751 0.984998 +1243 0.485751 0.952498 +1228 0.498779 0.952498 +SURF 0x30 +mat 0 +refs 4 +1228 0.498779 0.952498 +1243 0.485751 0.952498 +1244 0.485751 0.929999 +1229 0.500504 0.929999 +SURF 0x30 +mat 0 +refs 4 +1229 0.500504 0.929999 +1244 0.485751 0.929999 +1245 0.485751 0.8825 +1230 0.501984 0.8825 +SURF 0x30 +mat 0 +refs 4 +1230 0.501984 0.8825 +1245 0.485751 0.8825 +1246 0.485751 0.6825 +1231 0.503215 0.6825 +SURF 0x30 +mat 0 +refs 4 +1231 0.503215 0.6825 +1246 0.485751 0.6825 +1247 0.485751 0.635 +1232 0.504695 0.635 +SURF 0x30 +mat 0 +refs 4 +1232 0.504695 0.635 +1247 0.485751 0.635 +1248 0.485751 0.555 +1233 0.50987 0.555 +SURF 0x30 +mat 0 +refs 4 +1233 0.50987 0.555 +1248 0.485751 0.555 +1249 0.485751 0.475 +1234 0.514461 0.475 +SURF 0x30 +mat 0 +refs 4 +1234 0.514461 0.475 +1249 0.485751 0.475 +1250 0.5 0.3875 +1235 0.532795 0.3875 +SURF 0x30 +mat 0 +refs 4 +1235 0.532795 0.3875 +1250 0.5 0.3875 +1251 0.5 0.31 +1236 0.53567 0.31 +SURF 0x30 +mat 0 +refs 3 +1236 0.53567 0.31 +1251 0.5 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1252 0.5 0.0200004 +1237 0.516979 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1237 0.516979 0.0200004 +1252 0.5 0.0200004 +1253 0.5 0 +1238 0.506679 0 +SURF 0x30 +mat 1 +refs 4 +1238 0.506679 0 +1253 0.5 0 +1254 0.5 0 +1239 0.500447 0 +SURF 0x30 +mat 1 +refs 4 +1240 0.485751 1 +1255 0.4848 1 +1256 0.481595 0.994999 +1241 0.485751 0.994999 +SURF 0x30 +mat 0 +refs 4 +1241 0.485751 0.994999 +1256 0.481595 0.994999 +1257 0.478884 0.984998 +1242 0.485751 0.984998 +SURF 0x30 +mat 0 +refs 4 +1242 0.485751 0.984998 +1257 0.478884 0.984998 +1258 0.472724 0.952498 +1243 0.485751 0.952498 +SURF 0x30 +mat 0 +refs 4 +1243 0.485751 0.952498 +1258 0.472724 0.952498 +1259 0.470998 0.929999 +1244 0.485751 0.929999 +SURF 0x30 +mat 0 +refs 4 +1244 0.485751 0.929999 +1259 0.470998 0.929999 +1260 0.469519 0.8825 +1245 0.485751 0.8825 +SURF 0x30 +mat 0 +refs 4 +1245 0.485751 0.8825 +1260 0.469519 0.8825 +1261 0.468288 0.6825 +1246 0.485751 0.6825 +SURF 0x30 +mat 0 +refs 4 +1246 0.485751 0.6825 +1261 0.468288 0.6825 +1262 0.466808 0.635 +1247 0.485751 0.635 +SURF 0x30 +mat 0 +refs 4 +1247 0.485751 0.635 +1262 0.466808 0.635 +1263 0.461633 0.555 +1248 0.485751 0.555 +SURF 0x30 +mat 0 +refs 4 +1248 0.485751 0.555 +1263 0.461633 0.555 +1264 0.457042 0.475 +1249 0.485751 0.475 +SURF 0x30 +mat 0 +refs 4 +1249 0.485751 0.475 +1264 0.457042 0.475 +1265 0.467205 0.3875 +1250 0.5 0.3875 +SURF 0x30 +mat 0 +refs 4 +1250 0.5 0.3875 +1265 0.467205 0.3875 +1266 0.46433 0.31 +1251 0.5 0.31 +SURF 0x30 +mat 0 +refs 3 +1251 0.5 0.31 +1266 0.46433 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1267 0.483021 0.0200004 +1252 0.5 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1252 0.5 0.0200004 +1267 0.483021 0.0200004 +1268 0.493325 0 +1253 0.5 0 +SURF 0x30 +mat 1 +refs 4 +1253 0.5 0 +1268 0.493325 0 +1269 0.499553 0 +1254 0.5 0 +SURF 0x30 +mat 1 +refs 4 +1255 0.4848 1 +1270 0.483851 1 +1271 0.477458 0.994999 +1256 0.481595 0.994999 +SURF 0x30 +mat 0 +refs 4 +1256 0.481595 0.994999 +1271 0.477458 0.994999 +1272 0.472051 0.984998 +1257 0.478884 0.984998 +SURF 0x30 +mat 0 +refs 4 +1257 0.478884 0.984998 +1272 0.472051 0.984998 +1273 0.459763 0.952498 +1258 0.472724 0.952498 +SURF 0x30 +mat 0 +refs 4 +1258 0.472724 0.952498 +1273 0.459763 0.952498 +1274 0.456319 0.929999 +1259 0.470998 0.929999 +SURF 0x30 +mat 0 +refs 4 +1259 0.470998 0.929999 +1274 0.456319 0.929999 +1275 0.45337 0.8825 +1260 0.469519 0.8825 +SURF 0x30 +mat 0 +refs 4 +1260 0.469519 0.8825 +1275 0.45337 0.8825 +1276 0.450912 0.6825 +1261 0.468288 0.6825 +SURF 0x30 +mat 0 +refs 4 +1261 0.468288 0.6825 +1276 0.450912 0.6825 +1277 0.447962 0.635 +1262 0.466808 0.635 +SURF 0x30 +mat 0 +refs 4 +1262 0.466808 0.635 +1277 0.447962 0.635 +1278 0.437638 0.555 +1263 0.461633 0.555 +SURF 0x30 +mat 0 +refs 4 +1263 0.461633 0.555 +1278 0.437638 0.555 +1279 0.428478 0.475 +1264 0.457042 0.475 +SURF 0x30 +mat 0 +refs 4 +1264 0.457042 0.475 +1279 0.428478 0.475 +1280 0.434578 0.3875 +1265 0.467205 0.3875 +SURF 0x30 +mat 0 +refs 4 +1265 0.467205 0.3875 +1280 0.434578 0.3875 +1281 0.428844 0.31 +1266 0.46433 0.31 +SURF 0x30 +mat 0 +refs 3 +1266 0.46433 0.31 +1281 0.428844 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1282 0.466129 0.0200004 +1267 0.483021 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1267 0.483021 0.0200004 +1282 0.466129 0.0200004 +1283 0.486683 0 +1268 0.493325 0 +SURF 0x30 +mat 1 +refs 4 +1268 0.493325 0 +1283 0.486683 0 +1284 0.499109 0 +1269 0.499553 0 +SURF 0x30 +mat 1 +refs 4 +1270 0.483851 1 +1285 0.482913 1 +1286 0.473366 0.994999 +1271 0.477458 0.994999 +SURF 0x30 +mat 0 +refs 4 +1271 0.477458 0.994999 +1286 0.473366 0.994999 +1287 0.465291 0.984998 +1272 0.472051 0.984998 +SURF 0x30 +mat 0 +refs 4 +1272 0.472051 0.984998 +1287 0.465291 0.984998 +1288 0.446933 0.952498 +1273 0.459763 0.952498 +SURF 0x30 +mat 0 +refs 4 +1273 0.459763 0.952498 +1288 0.446933 0.952498 +1289 0.441792 0.929999 +1274 0.456319 0.929999 +SURF 0x30 +mat 0 +refs 4 +1274 0.456319 0.929999 +1289 0.441792 0.929999 +1290 0.437386 0.8825 +1275 0.45337 0.8825 +SURF 0x30 +mat 0 +refs 4 +1275 0.45337 0.8825 +1290 0.437386 0.8825 +1291 0.433714 0.6825 +1276 0.450912 0.6825 +SURF 0x30 +mat 0 +refs 4 +1276 0.450912 0.6825 +1291 0.433714 0.6825 +1292 0.429308 0.635 +1277 0.447962 0.635 +SURF 0x30 +mat 0 +refs 4 +1277 0.447962 0.635 +1292 0.429308 0.635 +1293 0.413889 0.555 +1278 0.437638 0.555 +SURF 0x30 +mat 0 +refs 4 +1278 0.437638 0.555 +1293 0.413889 0.555 +1294 0.400206 0.475 +1279 0.428478 0.475 +SURF 0x30 +mat 0 +refs 4 +1279 0.428478 0.475 +1294 0.400206 0.475 +1295 0.402287 0.3875 +1280 0.434578 0.3875 +SURF 0x30 +mat 0 +refs 4 +1280 0.434578 0.3875 +1295 0.402287 0.3875 +1296 0.393719 0.31 +1281 0.428844 0.31 +SURF 0x30 +mat 0 +refs 3 +1281 0.428844 0.31 +1296 0.393719 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1297 0.449405 0.0200004 +1282 0.466129 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1282 0.466129 0.0200004 +1297 0.449405 0.0200004 +1298 0.480105 0 +1283 0.486683 0 +SURF 0x30 +mat 1 +refs 4 +1283 0.486683 0 +1298 0.480105 0 +1299 0.498668 0 +1284 0.499109 0 +SURF 0x30 +mat 1 +refs 4 +1285 0.482913 1 +1300 0.481988 1 +1301 0.469337 0.994999 +1286 0.473366 0.994999 +SURF 0x30 +mat 0 +refs 4 +1286 0.473366 0.994999 +1301 0.469337 0.994999 +1302 0.458633 0.984998 +1287 0.465291 0.984998 +SURF 0x30 +mat 0 +refs 4 +1287 0.465291 0.984998 +1302 0.458633 0.984998 +1303 0.434302 0.952498 +1288 0.446933 0.952498 +SURF 0x30 +mat 0 +refs 4 +1288 0.446933 0.952498 +1303 0.434302 0.952498 +1304 0.427489 0.929999 +1289 0.441792 0.929999 +SURF 0x30 +mat 0 +refs 4 +1289 0.441792 0.929999 +1304 0.427489 0.929999 +1305 0.421648 0.8825 +1290 0.437386 0.8825 +SURF 0x30 +mat 0 +refs 4 +1290 0.437386 0.8825 +1305 0.421648 0.8825 +1306 0.416782 0.6825 +1291 0.433714 0.6825 +SURF 0x30 +mat 0 +refs 4 +1291 0.433714 0.6825 +1306 0.416782 0.6825 +1307 0.410944 0.635 +1292 0.429308 0.635 +SURF 0x30 +mat 0 +refs 4 +1292 0.429308 0.635 +1307 0.410944 0.635 +1308 0.390504 0.555 +1293 0.413889 0.555 +SURF 0x30 +mat 0 +refs 4 +1293 0.413889 0.555 +1308 0.390504 0.555 +1309 0.372371 0.475 +1294 0.400206 0.475 +SURF 0x30 +mat 0 +refs 4 +1294 0.400206 0.475 +1309 0.372371 0.475 +1310 0.370491 0.3875 +1295 0.402287 0.3875 +SURF 0x30 +mat 0 +refs 4 +1295 0.402287 0.3875 +1310 0.370491 0.3875 +1311 0.359135 0.31 +1296 0.393719 0.31 +SURF 0x30 +mat 0 +refs 3 +1296 0.393719 0.31 +1311 0.359135 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1312 0.432944 0.0200004 +1297 0.449405 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1297 0.449405 0.0200004 +1312 0.432944 0.0200004 +1313 0.473631 0 +1298 0.480105 0 +SURF 0x30 +mat 1 +refs 4 +1298 0.480105 0 +1313 0.473631 0 +1314 0.498235 0 +1299 0.498668 0 +SURF 0x30 +mat 1 +refs 4 +1300 0.481988 1 +1315 0.481087 1 +1316 0.465392 0.994999 +1301 0.469337 0.994999 +SURF 0x30 +mat 0 +refs 4 +1301 0.469337 0.994999 +1316 0.465392 0.994999 +1317 0.452112 0.984998 +1302 0.458633 0.984998 +SURF 0x30 +mat 0 +refs 4 +1302 0.458633 0.984998 +1317 0.452112 0.984998 +1318 0.421934 0.952498 +1303 0.434302 0.952498 +SURF 0x30 +mat 0 +refs 4 +1303 0.434302 0.952498 +1318 0.421934 0.952498 +1319 0.413483 0.929999 +1304 0.427489 0.929999 +SURF 0x30 +mat 0 +refs 4 +1304 0.427489 0.929999 +1319 0.413483 0.929999 +1320 0.406239 0.8825 +1305 0.421648 0.8825 +SURF 0x30 +mat 0 +refs 4 +1305 0.421648 0.8825 +1320 0.406239 0.8825 +1321 0.400202 0.6825 +1306 0.416782 0.6825 +SURF 0x30 +mat 0 +refs 4 +1306 0.416782 0.6825 +1321 0.400202 0.6825 +1322 0.392959 0.635 +1307 0.410944 0.635 +SURF 0x30 +mat 0 +refs 4 +1307 0.410944 0.635 +1322 0.392959 0.635 +1323 0.367606 0.555 +1308 0.390504 0.555 +SURF 0x30 +mat 0 +refs 4 +1308 0.390504 0.555 +1323 0.367606 0.555 +1324 0.345111 0.475 +1309 0.372371 0.475 +SURF 0x30 +mat 0 +refs 4 +1309 0.372371 0.475 +1324 0.345111 0.475 +1325 0.339354 0.3875 +1310 0.370491 0.3875 +SURF 0x30 +mat 0 +refs 4 +1310 0.370491 0.3875 +1325 0.339354 0.3875 +1326 0.32527 0.31 +1311 0.359135 0.31 +SURF 0x30 +mat 0 +refs 3 +1311 0.359135 0.31 +1326 0.32527 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1327 0.416822 0.0200004 +1312 0.432944 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1312 0.432944 0.0200004 +1327 0.416822 0.0200004 +1328 0.467292 0 +1313 0.473631 0 +SURF 0x30 +mat 1 +refs 4 +1313 0.473631 0 +1328 0.467292 0 +1329 0.497811 0 +1314 0.498235 0 +SURF 0x30 +mat 1 +refs 4 +1315 0.481087 1 +1330 0.480206 1 +1331 0.461549 0.994999 +1316 0.465392 0.994999 +SURF 0x30 +mat 0 +refs 4 +1316 0.465392 0.994999 +1331 0.461549 0.994999 +1332 0.445763 0.984998 +1317 0.452112 0.984998 +SURF 0x30 +mat 0 +refs 4 +1317 0.452112 0.984998 +1332 0.445763 0.984998 +1333 0.409888 0.952498 +1318 0.421934 0.952498 +SURF 0x30 +mat 0 +refs 4 +1318 0.421934 0.952498 +1333 0.409888 0.952498 +1334 0.399843 0.929999 +1319 0.413483 0.929999 +SURF 0x30 +mat 0 +refs 4 +1319 0.413483 0.929999 +1334 0.399843 0.929999 +1335 0.391234 0.8825 +1320 0.406239 0.8825 +SURF 0x30 +mat 0 +refs 4 +1320 0.406239 0.8825 +1335 0.391234 0.8825 +1336 0.384057 0.6825 +1321 0.400202 0.6825 +SURF 0x30 +mat 0 +refs 4 +1321 0.400202 0.6825 +1336 0.384057 0.6825 +1337 0.375448 0.635 +1322 0.392959 0.635 +SURF 0x30 +mat 0 +refs 4 +1322 0.392959 0.635 +1337 0.375448 0.635 +1338 0.34531 0.555 +1323 0.367606 0.555 +SURF 0x30 +mat 0 +refs 4 +1323 0.367606 0.555 +1338 0.34531 0.555 +1339 0.318571 0.475 +1324 0.345111 0.475 +SURF 0x30 +mat 0 +refs 4 +1324 0.345111 0.475 +1339 0.318571 0.475 +1340 0.309037 0.3875 +1325 0.339354 0.3875 +SURF 0x30 +mat 0 +refs 4 +1325 0.339354 0.3875 +1340 0.309037 0.3875 +1341 0.292294 0.31 +1326 0.32527 0.31 +SURF 0x30 +mat 0 +refs 3 +1326 0.32527 0.31 +1341 0.292294 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1342 0.401124 0.0200004 +1327 0.416822 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1327 0.416822 0.0200004 +1342 0.401124 0.0200004 +1343 0.461121 0 +1328 0.467292 0 +SURF 0x30 +mat 1 +refs 4 +1328 0.467292 0 +1343 0.461121 0 +1344 0.4974 0 +1329 0.497811 0 +SURF 0x30 +mat 1 +refs 4 +1330 0.480206 1 +1345 0.479352 1 +1346 0.457829 0.994999 +1331 0.461549 0.994999 +SURF 0x30 +mat 0 +refs 4 +1331 0.461549 0.994999 +1346 0.457829 0.994999 +1347 0.439619 0.984998 +1332 0.445763 0.984998 +SURF 0x30 +mat 0 +refs 4 +1332 0.445763 0.984998 +1347 0.439619 0.984998 +1348 0.398232 0.952498 +1333 0.409888 0.952498 +SURF 0x30 +mat 0 +refs 4 +1333 0.409888 0.952498 +1348 0.398232 0.952498 +1349 0.386643 0.929999 +1334 0.399843 0.929999 +SURF 0x30 +mat 0 +refs 4 +1334 0.399843 0.929999 +1349 0.386643 0.929999 +1350 0.376709 0.8825 +1335 0.391234 0.8825 +SURF 0x30 +mat 0 +refs 4 +1335 0.391234 0.8825 +1350 0.376709 0.8825 +1351 0.36843 0.6825 +1336 0.384057 0.6825 +SURF 0x30 +mat 0 +refs 4 +1336 0.384057 0.6825 +1351 0.36843 0.6825 +1352 0.358499 0.635 +1337 0.375448 0.635 +SURF 0x30 +mat 0 +refs 4 +1337 0.375448 0.635 +1352 0.358499 0.635 +1353 0.32373 0.555 +1338 0.34531 0.555 +SURF 0x30 +mat 0 +refs 4 +1338 0.34531 0.555 +1353 0.32373 0.555 +1354 0.292879 0.475 +1339 0.318571 0.475 +SURF 0x30 +mat 0 +refs 4 +1339 0.318571 0.475 +1354 0.292879 0.475 +1355 0.279693 0.3875 +1340 0.309037 0.3875 +SURF 0x30 +mat 0 +refs 4 +1340 0.309037 0.3875 +1355 0.279693 0.3875 +1356 0.260376 0.31 +1341 0.292294 0.31 +SURF 0x30 +mat 0 +refs 4 +1341 0.292294 0.31 +1356 0.260376 0.31 +1357 0.263595 0.247501 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1357 0.263595 0.247501 +1358 0.270035 0.175 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1358 0.270035 0.175 +1359 0.289351 0.105001 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1360 0.38593 0.0200004 +1342 0.401124 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1342 0.401124 0.0200004 +1360 0.38593 0.0200004 +1361 0.455149 0 +1343 0.461121 0 +SURF 0x30 +mat 1 +refs 4 +1343 0.461121 0 +1361 0.455149 0 +1362 0.497 0 +1344 0.4974 0 +SURF 0x30 +mat 1 +refs 4 +1345 0.479352 1 +1363 0.478535 1 +1364 0.454254 0.994999 +1346 0.457829 0.994999 +SURF 0x30 +mat 0 +refs 4 +1346 0.457829 0.994999 +1364 0.454254 0.994999 +1365 0.43371 0.984998 +1347 0.439619 0.984998 +SURF 0x30 +mat 0 +refs 4 +1347 0.439619 0.984998 +1365 0.43371 0.984998 +1366 0.38702 0.952498 +1348 0.398232 0.952498 +SURF 0x30 +mat 0 +refs 4 +1348 0.398232 0.952498 +1366 0.38702 0.952498 +1367 0.373945 0.929999 +1349 0.386643 0.929999 +SURF 0x30 +mat 0 +refs 4 +1349 0.386643 0.929999 +1367 0.373945 0.929999 +1368 0.36274 0.8825 +1350 0.376709 0.8825 +SURF 0x30 +mat 0 +refs 4 +1350 0.376709 0.8825 +1368 0.36274 0.8825 +1369 0.353401 0.6825 +1351 0.36843 0.6825 +SURF 0x30 +mat 0 +refs 4 +1351 0.36843 0.6825 +1369 0.353401 0.6825 +1370 0.342196 0.635 +1352 0.358499 0.635 +SURF 0x30 +mat 0 +refs 4 +1352 0.358499 0.635 +1370 0.342196 0.635 +1371 0.302978 0.555 +1353 0.32373 0.555 +SURF 0x30 +mat 0 +refs 4 +1353 0.32373 0.555 +1371 0.302978 0.555 +1372 0.268175 0.475 +1354 0.292879 0.475 +SURF 0x30 +mat 0 +refs 4 +1354 0.292879 0.475 +1372 0.268175 0.475 +1373 0.251471 0.3875 +1355 0.279693 0.3875 +SURF 0x30 +mat 0 +refs 4 +1355 0.279693 0.3875 +1373 0.251471 0.3875 +1374 0.22968 0.31 +1356 0.260376 0.31 +SURF 0x30 +mat 0 +refs 4 +1356 0.260376 0.31 +1374 0.22968 0.31 +1375 0.233312 0.247501 +1357 0.263595 0.247501 +SURF 0x30 +mat 0 +refs 4 +1357 0.263595 0.247501 +1375 0.233312 0.247501 +1376 0.240575 0.175 +1358 0.270035 0.175 +SURF 0x30 +mat 0 +refs 4 +1358 0.270035 0.175 +1376 0.240575 0.175 +1377 0.262367 0.105001 +1359 0.289351 0.105001 +SURF 0x30 +mat 0 +refs 3 +1359 0.289351 0.105001 +1377 0.262367 0.105001 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1378 0.371318 0.0200004 +1360 0.38593 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1360 0.38593 0.0200004 +1378 0.371318 0.0200004 +1379 0.449402 0 +1361 0.455149 0 +SURF 0x30 +mat 1 +refs 4 +1361 0.455149 0 +1379 0.449402 0 +1380 0.496614 0 +1362 0.497 0 +SURF 0x30 +mat 1 +refs 4 +1363 0.478535 1 +1381 0.477751 1 +1382 0.450838 0.994999 +1364 0.454254 0.994999 +SURF 0x30 +mat 0 +refs 4 +1364 0.454254 0.994999 +1382 0.450838 0.994999 +1383 0.428067 0.984998 +1365 0.43371 0.984998 +SURF 0x30 +mat 0 +refs 4 +1365 0.43371 0.984998 +1383 0.428067 0.984998 +1384 0.376312 0.952498 +1366 0.38702 0.952498 +SURF 0x30 +mat 0 +refs 4 +1366 0.38702 0.952498 +1384 0.376312 0.952498 +1385 0.361818 0.929999 +1367 0.373945 0.929999 +SURF 0x30 +mat 0 +refs 4 +1367 0.373945 0.929999 +1385 0.361818 0.929999 +1386 0.349399 0.8825 +1368 0.36274 0.8825 +SURF 0x30 +mat 0 +refs 4 +1368 0.36274 0.8825 +1386 0.349399 0.8825 +1387 0.339048 0.6825 +1369 0.353401 0.6825 +SURF 0x30 +mat 0 +refs 4 +1369 0.353401 0.6825 +1387 0.339048 0.6825 +1388 0.326625 0.635 +1370 0.342196 0.635 +SURF 0x30 +mat 0 +refs 4 +1370 0.342196 0.635 +1388 0.326625 0.635 +1389 0.283153 0.555 +1371 0.302978 0.555 +SURF 0x30 +mat 0 +refs 4 +1371 0.302978 0.555 +1389 0.283153 0.555 +1390 0.244577 0.475 +1372 0.268175 0.475 +SURF 0x30 +mat 0 +refs 4 +1372 0.268175 0.475 +1390 0.244577 0.475 +1391 0.224518 0.3875 +1373 0.251471 0.3875 +SURF 0x30 +mat 0 +refs 4 +1373 0.251471 0.3875 +1391 0.224518 0.3875 +1392 0.200362 0.31 +1374 0.22968 0.31 +SURF 0x30 +mat 0 +refs 4 +1374 0.22968 0.31 +1392 0.200362 0.31 +1393 0.204387 0.247501 +1375 0.233312 0.247501 +SURF 0x30 +mat 0 +refs 4 +1375 0.233312 0.247501 +1393 0.204387 0.247501 +1394 0.212438 0.175 +1376 0.240575 0.175 +SURF 0x30 +mat 0 +refs 4 +1376 0.240575 0.175 +1394 0.212438 0.175 +1395 0.236594 0.105001 +1377 0.262367 0.105001 +SURF 0x30 +mat 0 +refs 3 +1377 0.262367 0.105001 +1395 0.236594 0.105001 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1396 0.357362 0.0200004 +1378 0.371318 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1378 0.371318 0.0200004 +1396 0.357362 0.0200004 +1397 0.443914 0 +1379 0.449402 0 +SURF 0x30 +mat 1 +refs 4 +1379 0.449402 0 +1397 0.443914 0 +1398 0.496247 0 +1380 0.496614 0 +SURF 0x30 +mat 1 +refs 4 +1381 0.477751 1 +1399 0.477008 1 +1400 0.447599 0.994999 +1382 0.450838 0.994999 +SURF 0x30 +mat 0 +refs 4 +1382 0.450838 0.994999 +1400 0.447599 0.994999 +1401 0.422717 0.984998 +1383 0.428067 0.984998 +SURF 0x30 +mat 0 +refs 4 +1383 0.428067 0.984998 +1401 0.422717 0.984998 +1402 0.36616 0.952498 +1384 0.376312 0.952498 +SURF 0x30 +mat 0 +refs 4 +1384 0.376312 0.952498 +1402 0.36616 0.952498 +1403 0.350324 0.929999 +1385 0.361818 0.929999 +SURF 0x30 +mat 0 +refs 4 +1385 0.361818 0.929999 +1403 0.350324 0.929999 +1404 0.336751 0.8825 +1386 0.349399 0.8825 +SURF 0x30 +mat 0 +refs 4 +1386 0.349399 0.8825 +1404 0.336751 0.8825 +1405 0.325442 0.6825 +1387 0.339048 0.6825 +SURF 0x30 +mat 0 +refs 4 +1387 0.339048 0.6825 +1405 0.325442 0.6825 +1406 0.311869 0.635 +1388 0.326625 0.635 +SURF 0x30 +mat 0 +refs 4 +1388 0.326625 0.635 +1406 0.311869 0.635 +1407 0.264361 0.555 +1389 0.283153 0.555 +SURF 0x30 +mat 0 +refs 4 +1389 0.283153 0.555 +1407 0.264361 0.555 +1408 0.222207 0.475 +1390 0.244577 0.475 +SURF 0x30 +mat 0 +refs 4 +1390 0.244577 0.475 +1408 0.222207 0.475 +1409 0.198966 0.3875 +1391 0.224518 0.3875 +SURF 0x30 +mat 0 +refs 4 +1391 0.224518 0.3875 +1409 0.198966 0.3875 +1410 0.172571 0.31 +1392 0.200362 0.31 +SURF 0x30 +mat 0 +refs 4 +1392 0.200362 0.31 +1410 0.172571 0.31 +1411 0.17697 0.247501 +1393 0.204387 0.247501 +SURF 0x30 +mat 0 +refs 4 +1393 0.204387 0.247501 +1411 0.17697 0.247501 +1412 0.185767 0.175 +1394 0.212438 0.175 +SURF 0x30 +mat 0 +refs 4 +1394 0.212438 0.175 +1412 0.185767 0.175 +1413 0.212162 0.105001 +1395 0.236594 0.105001 +SURF 0x30 +mat 0 +refs 4 +1395 0.236594 0.105001 +1413 0.212162 0.105001 +1414 0.280349 0.0549999 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 4 +1174 0.422996 0.0519236 +1414 0.280349 0.0549999 +1415 0.344133 0.0200004 +1396 0.357362 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1396 0.357362 0.0200004 +1415 0.344133 0.0200004 +1416 0.438711 0 +1397 0.443914 0 +SURF 0x30 +mat 1 +refs 4 +1397 0.443914 0 +1416 0.438711 0 +1417 0.495901 0 +1398 0.496247 0 +SURF 0x30 +mat 1 +refs 4 +1399 0.477008 1 +1418 0.476312 1 +1419 0.444556 0.994999 +1400 0.447599 0.994999 +SURF 0x30 +mat 0 +refs 4 +1400 0.447599 0.994999 +1419 0.444556 0.994999 +1420 0.417686 0.984998 +1401 0.422717 0.984998 +SURF 0x30 +mat 0 +refs 4 +1401 0.422717 0.984998 +1420 0.417686 0.984998 +1421 0.356619 0.952498 +1402 0.36616 0.952498 +SURF 0x30 +mat 0 +refs 4 +1402 0.36616 0.952498 +1421 0.356619 0.952498 +1422 0.339522 0.929999 +1403 0.350324 0.929999 +SURF 0x30 +mat 0 +refs 4 +1403 0.350324 0.929999 +1422 0.339522 0.929999 +1423 0.324863 0.8825 +1404 0.336751 0.8825 +SURF 0x30 +mat 0 +refs 4 +1404 0.336751 0.8825 +1423 0.324863 0.8825 +1424 0.312653 0.6825 +1405 0.325442 0.6825 +SURF 0x30 +mat 0 +refs 4 +1405 0.325442 0.6825 +1424 0.312653 0.6825 +1425 0.297994 0.635 +1406 0.311869 0.635 +SURF 0x30 +mat 0 +refs 4 +1406 0.311869 0.635 +1425 0.297994 0.635 +1426 0.246699 0.555 +1407 0.264361 0.555 +SURF 0x30 +mat 0 +refs 4 +1407 0.264361 0.555 +1426 0.246699 0.555 +1427 0.201179 0.475 +1408 0.222207 0.475 +SURF 0x30 +mat 0 +refs 4 +1408 0.222207 0.475 +1427 0.201179 0.475 +1428 0.174948 0.3875 +1409 0.198966 0.3875 +SURF 0x30 +mat 0 +refs 4 +1409 0.198966 0.3875 +1428 0.174948 0.3875 +1429 0.146448 0.31 +1410 0.172571 0.31 +SURF 0x30 +mat 0 +refs 4 +1410 0.172571 0.31 +1429 0.146448 0.31 +1430 0.1512 0.247501 +1411 0.17697 0.247501 +SURF 0x30 +mat 0 +refs 4 +1411 0.17697 0.247501 +1430 0.1512 0.247501 +1431 0.160696 0.175 +1412 0.185767 0.175 +SURF 0x30 +mat 0 +refs 4 +1412 0.185767 0.175 +1431 0.160696 0.175 +1432 0.189197 0.105001 +1413 0.212162 0.105001 +SURF 0x30 +mat 0 +refs 4 +1413 0.212162 0.105001 +1432 0.189197 0.105001 +1433 0.262821 0.0549999 +1414 0.280349 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1414 0.280349 0.0549999 +1433 0.262821 0.0549999 +1434 0.331697 0.0200004 +1415 0.344133 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1415 0.344133 0.0200004 +1434 0.331697 0.0200004 +1435 0.433821 0 +1416 0.438711 0 +SURF 0x30 +mat 1 +refs 4 +1416 0.438711 0 +1435 0.433821 0 +1436 0.495571 0 +1417 0.495901 0 +SURF 0x30 +mat 1 +refs 4 +1418 0.476312 1 +1437 0.475663 1 +1438 0.441721 0.994999 +1419 0.444556 0.994999 +SURF 0x30 +mat 0 +refs 4 +1419 0.444556 0.994999 +1438 0.441721 0.994999 +1439 0.413005 0.984998 +1420 0.417686 0.984998 +SURF 0x30 +mat 0 +refs 4 +1420 0.417686 0.984998 +1439 0.413005 0.984998 +1440 0.347738 0.952498 +1421 0.356619 0.952498 +SURF 0x30 +mat 0 +refs 4 +1421 0.356619 0.952498 +1440 0.347738 0.952498 +1441 0.32946 0.929999 +1422 0.339522 0.929999 +SURF 0x30 +mat 0 +refs 4 +1422 0.339522 0.929999 +1441 0.32946 0.929999 +1442 0.313796 0.8825 +1423 0.324863 0.8825 +SURF 0x30 +mat 0 +refs 4 +1423 0.324863 0.8825 +1442 0.313796 0.8825 +1443 0.300745 0.6825 +1424 0.312653 0.6825 +SURF 0x30 +mat 0 +refs 4 +1424 0.312653 0.6825 +1443 0.300745 0.6825 +1444 0.28508 0.635 +1425 0.297994 0.635 +SURF 0x30 +mat 0 +refs 4 +1425 0.297994 0.635 +1444 0.28508 0.635 +1445 0.230255 0.555 +1426 0.246699 0.555 +SURF 0x30 +mat 0 +refs 4 +1426 0.246699 0.555 +1445 0.230255 0.555 +1446 0.181604 0.475 +1427 0.201179 0.475 +SURF 0x30 +mat 0 +refs 4 +1427 0.201179 0.475 +1446 0.181604 0.475 +1447 0.152588 0.3875 +1428 0.174948 0.3875 +SURF 0x30 +mat 0 +refs 4 +1428 0.174948 0.3875 +1447 0.152588 0.3875 +1448 0.122127 0.31 +1429 0.146448 0.31 +SURF 0x30 +mat 0 +refs 4 +1429 0.146448 0.31 +1448 0.122127 0.31 +1449 0.127202 0.247501 +1430 0.1512 0.247501 +SURF 0x30 +mat 0 +refs 4 +1430 0.1512 0.247501 +1449 0.127202 0.247501 +1450 0.137358 0.175 +1431 0.160696 0.175 +SURF 0x30 +mat 0 +refs 4 +1431 0.160696 0.175 +1450 0.137358 0.175 +1451 0.167819 0.105001 +1432 0.189197 0.105001 +SURF 0x30 +mat 0 +refs 4 +1432 0.189197 0.105001 +1451 0.167819 0.105001 +1452 0.246508 0.0549999 +1433 0.262821 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1433 0.262821 0.0549999 +1452 0.246508 0.0549999 +1453 0.320118 0.0200004 +1434 0.331697 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1434 0.331697 0.0200004 +1453 0.320118 0.0200004 +1454 0.429268 0 +1435 0.433821 0 +SURF 0x30 +mat 1 +refs 4 +1435 0.433821 0 +1454 0.429268 0 +1455 0.495268 0 +1436 0.495571 0 +SURF 0x30 +mat 1 +refs 4 +1437 0.475663 1 +1456 0.475064 1 +1457 0.439111 0.994999 +1438 0.441721 0.994999 +SURF 0x30 +mat 0 +refs 4 +1438 0.441721 0.994999 +1457 0.439111 0.994999 +1458 0.408694 0.984998 +1439 0.413005 0.984998 +SURF 0x30 +mat 0 +refs 4 +1439 0.413005 0.984998 +1458 0.408694 0.984998 +1459 0.339556 0.952498 +1440 0.347738 0.952498 +SURF 0x30 +mat 0 +refs 4 +1440 0.347738 0.952498 +1459 0.339556 0.952498 +1460 0.320199 0.929999 +1441 0.32946 0.929999 +SURF 0x30 +mat 0 +refs 4 +1441 0.32946 0.929999 +1460 0.320199 0.929999 +1461 0.303606 0.8825 +1442 0.313796 0.8825 +SURF 0x30 +mat 0 +refs 4 +1442 0.313796 0.8825 +1461 0.303606 0.8825 +1462 0.289778 0.6825 +1443 0.300745 0.6825 +SURF 0x30 +mat 0 +refs 4 +1443 0.300745 0.6825 +1462 0.289778 0.6825 +1463 0.273186 0.635 +1444 0.28508 0.635 +SURF 0x30 +mat 0 +refs 4 +1444 0.28508 0.635 +1463 0.273186 0.635 +1464 0.215112 0.555 +1445 0.230255 0.555 +SURF 0x30 +mat 0 +refs 4 +1445 0.230255 0.555 +1464 0.215112 0.555 +1465 0.163578 0.475 +1446 0.181604 0.475 +SURF 0x30 +mat 0 +refs 4 +1446 0.181604 0.475 +1465 0.163578 0.475 +1466 0.131997 0.3875 +1447 0.152588 0.3875 +SURF 0x30 +mat 0 +refs 4 +1447 0.152588 0.3875 +1466 0.131997 0.3875 +1467 0.0997303 0.31 +1448 0.122127 0.31 +SURF 0x30 +mat 0 +refs 4 +1448 0.122127 0.31 +1467 0.0997303 0.31 +1468 0.105108 0.247501 +1449 0.127202 0.247501 +SURF 0x30 +mat 0 +refs 4 +1449 0.127202 0.247501 +1468 0.105108 0.247501 +1469 0.115862 0.175 +1450 0.137358 0.175 +SURF 0x30 +mat 0 +refs 4 +1450 0.137358 0.175 +1469 0.115862 0.175 +1470 0.148129 0.105001 +1451 0.167819 0.105001 +SURF 0x30 +mat 0 +refs 4 +1451 0.167819 0.105001 +1470 0.148129 0.105001 +1471 0.231482 0.0549999 +1452 0.246508 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1452 0.246508 0.0549999 +1471 0.231482 0.0549999 +1472 0.309458 0.0200004 +1453 0.320118 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1453 0.320118 0.0200004 +1472 0.309458 0.0200004 +1473 0.425078 0 +1454 0.429268 0 +SURF 0x30 +mat 1 +refs 4 +1454 0.429268 0 +1473 0.425078 0 +1474 0.494986 0 +1455 0.495268 0 +SURF 0x30 +mat 1 +refs 4 +1456 0.475064 1 +1475 0.474519 1 +1476 0.43674 0.994999 +1457 0.439111 0.994999 +SURF 0x30 +mat 0 +refs 4 +1457 0.439111 0.994999 +1476 0.43674 0.994999 +1477 0.404773 0.984998 +1458 0.408694 0.984998 +SURF 0x30 +mat 0 +refs 4 +1458 0.408694 0.984998 +1477 0.404773 0.984998 +1478 0.33212 0.952498 +1459 0.339556 0.952498 +SURF 0x30 +mat 0 +refs 4 +1459 0.339556 0.952498 +1478 0.33212 0.952498 +1479 0.311778 0.929999 +1460 0.320199 0.929999 +SURF 0x30 +mat 0 +refs 4 +1460 0.320199 0.929999 +1479 0.311778 0.929999 +1480 0.294342 0.8825 +1461 0.303606 0.8825 +SURF 0x30 +mat 0 +refs 4 +1461 0.303606 0.8825 +1480 0.294342 0.8825 +1481 0.279811 0.6825 +1462 0.289778 0.6825 +SURF 0x30 +mat 0 +refs 4 +1462 0.289778 0.6825 +1481 0.279811 0.6825 +1482 0.262377 0.635 +1463 0.273186 0.635 +SURF 0x30 +mat 0 +refs 4 +1463 0.273186 0.635 +1482 0.262377 0.635 +1483 0.201347 0.555 +1464 0.215112 0.555 +SURF 0x30 +mat 0 +refs 4 +1464 0.215112 0.555 +1483 0.201347 0.555 +1484 0.147194 0.475 +1465 0.163578 0.475 +SURF 0x30 +mat 0 +refs 4 +1465 0.163578 0.475 +1484 0.147194 0.475 +1485 0.113283 0.3875 +1466 0.131997 0.3875 +SURF 0x30 +mat 0 +refs 4 +1466 0.131997 0.3875 +1485 0.113283 0.3875 +1486 0.0793746 0.31 +1467 0.0997303 0.31 +SURF 0x30 +mat 0 +refs 4 +1467 0.0997303 0.31 +1486 0.0793746 0.31 +1487 0.0850243 0.247501 +1468 0.105108 0.247501 +SURF 0x30 +mat 0 +refs 4 +1468 0.105108 0.247501 +1487 0.0850243 0.247501 +1488 0.096327 0.175 +1469 0.115862 0.175 +SURF 0x30 +mat 0 +refs 4 +1469 0.115862 0.175 +1488 0.096327 0.175 +1489 0.130235 0.105001 +1470 0.148129 0.105001 +SURF 0x30 +mat 0 +refs 4 +1470 0.148129 0.105001 +1489 0.130235 0.105001 +1490 0.217825 0.0549999 +1471 0.231482 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1471 0.231482 0.0549999 +1490 0.217825 0.0549999 +1491 0.299769 0.0200004 +1472 0.309458 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1472 0.309458 0.0200004 +1491 0.299769 0.0200004 +1492 0.421268 0 +1473 0.425078 0 +SURF 0x30 +mat 1 +refs 4 +1473 0.425078 0 +1492 0.421268 0 +1493 0.49473 0 +1474 0.494986 0 +SURF 0x30 +mat 1 +refs 4 +1475 0.474519 1 +1494 0.474035 1 +1495 0.434618 0.994999 +1476 0.43674 0.994999 +SURF 0x30 +mat 0 +refs 4 +1476 0.43674 0.994999 +1495 0.434618 0.994999 +1496 0.401268 0.984998 +1477 0.404773 0.984998 +SURF 0x30 +mat 0 +refs 4 +1477 0.404773 0.984998 +1496 0.401268 0.984998 +1497 0.325469 0.952498 +1478 0.33212 0.952498 +SURF 0x30 +mat 0 +refs 4 +1478 0.33212 0.952498 +1497 0.325469 0.952498 +1498 0.304245 0.929999 +1479 0.311778 0.929999 +SURF 0x30 +mat 0 +refs 4 +1479 0.311778 0.929999 +1498 0.304245 0.929999 +1499 0.286055 0.8825 +1480 0.294342 0.8825 +SURF 0x30 +mat 0 +refs 4 +1480 0.294342 0.8825 +1499 0.286055 0.8825 +1500 0.270895 0.6825 +1481 0.279811 0.6825 +SURF 0x30 +mat 0 +refs 4 +1481 0.279811 0.6825 +1500 0.270895 0.6825 +1501 0.252702 0.635 +1482 0.262377 0.635 +SURF 0x30 +mat 0 +refs 4 +1482 0.262377 0.635 +1501 0.252702 0.635 +1502 0.189032 0.555 +1483 0.201347 0.555 +SURF 0x30 +mat 0 +refs 4 +1483 0.201347 0.555 +1502 0.189032 0.555 +1503 0.132535 0.475 +1484 0.147194 0.475 +SURF 0x30 +mat 0 +refs 4 +1484 0.147194 0.475 +1503 0.132535 0.475 +1504 0.0965356 0.3875 +1485 0.113283 0.3875 +SURF 0x30 +mat 0 +refs 4 +1485 0.113283 0.3875 +1504 0.0965356 0.3875 +1505 0.0611612 0.31 +1486 0.0793746 0.31 +SURF 0x30 +mat 0 +refs 4 +1486 0.0793746 0.31 +1505 0.0611612 0.31 +1506 0.0670564 0.247501 +1487 0.0850243 0.247501 +SURF 0x30 +mat 0 +refs 4 +1487 0.0850243 0.247501 +1506 0.0670564 0.247501 +1507 0.07885 0.175 +1488 0.096327 0.175 +SURF 0x30 +mat 0 +refs 4 +1488 0.096327 0.175 +1507 0.07885 0.175 +1508 0.114224 0.105001 +1489 0.130235 0.105001 +SURF 0x30 +mat 0 +refs 4 +1489 0.130235 0.105001 +1508 0.114224 0.105001 +1509 0.205608 0.0549999 +1490 0.217825 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1490 0.217825 0.0549999 +1509 0.205608 0.0549999 +1510 0.2911 0.0200004 +1491 0.299769 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1491 0.299769 0.0200004 +1510 0.2911 0.0200004 +1511 0.417858 0 +1492 0.421268 0 +SURF 0x30 +mat 1 +refs 4 +1492 0.421268 0 +1511 0.417858 0 +1512 0.494505 0 +1493 0.49473 0 +SURF 0x30 +mat 1 +refs 4 +1494 0.474035 1 +1513 0.473608 1 +1514 0.432755 0.994999 +1495 0.434618 0.994999 +SURF 0x30 +mat 0 +refs 4 +1495 0.434618 0.994999 +1514 0.432755 0.994999 +1515 0.398191 0.984998 +1496 0.401268 0.984998 +SURF 0x30 +mat 0 +refs 4 +1496 0.401268 0.984998 +1515 0.398191 0.984998 +1516 0.319634 0.952498 +1497 0.325469 0.952498 +SURF 0x30 +mat 0 +refs 4 +1497 0.325469 0.952498 +1516 0.319634 0.952498 +1517 0.297637 0.929999 +1498 0.304245 0.929999 +SURF 0x30 +mat 0 +refs 4 +1498 0.304245 0.929999 +1517 0.297637 0.929999 +1518 0.278785 0.8825 +1499 0.286055 0.8825 +SURF 0x30 +mat 0 +refs 4 +1499 0.286055 0.8825 +1518 0.278785 0.8825 +1519 0.263073 0.6825 +1500 0.270895 0.6825 +SURF 0x30 +mat 0 +refs 4 +1500 0.270895 0.6825 +1519 0.263073 0.6825 +1520 0.244218 0.635 +1501 0.252702 0.635 +SURF 0x30 +mat 0 +refs 4 +1501 0.252702 0.635 +1520 0.244218 0.635 +1521 0.178231 0.555 +1502 0.189032 0.555 +SURF 0x30 +mat 0 +refs 4 +1502 0.189032 0.555 +1521 0.178231 0.555 +1522 0.119676 0.475 +1503 0.132535 0.475 +SURF 0x30 +mat 0 +refs 4 +1503 0.132535 0.475 +1522 0.119676 0.475 +1523 0.0818498 0.3875 +1504 0.0965356 0.3875 +SURF 0x30 +mat 0 +refs 4 +1504 0.0965356 0.3875 +1523 0.0818498 0.3875 +1524 0.045184 0.31 +1505 0.0611612 0.31 +SURF 0x30 +mat 0 +refs 4 +1505 0.0611612 0.31 +1524 0.045184 0.31 +1525 0.0512944 0.247501 +1506 0.0670564 0.247501 +SURF 0x30 +mat 0 +refs 4 +1506 0.0670564 0.247501 +1525 0.0512944 0.247501 +1526 0.0635185 0.175 +1507 0.07885 0.175 +SURF 0x30 +mat 0 +refs 4 +1507 0.07885 0.175 +1526 0.0635185 0.175 +1527 0.100181 0.105001 +1508 0.114224 0.105001 +SURF 0x30 +mat 0 +refs 4 +1508 0.114224 0.105001 +1527 0.100181 0.105001 +1528 0.19489 0.0549999 +1509 0.205608 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1509 0.205608 0.0549999 +1528 0.19489 0.0549999 +1529 0.283493 0.0200004 +1510 0.2911 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1510 0.2911 0.0200004 +1529 0.283493 0.0200004 +1530 0.414868 0 +1511 0.417858 0 +SURF 0x30 +mat 1 +refs 4 +1511 0.417858 0 +1530 0.414868 0 +1531 0.494303 0 +1512 0.494505 0 +SURF 0x30 +mat 1 +refs 4 +1513 0.473608 1 +1532 0.473241 1 +1533 0.431165 0.994999 +1514 0.432755 0.994999 +SURF 0x30 +mat 0 +refs 4 +1514 0.432755 0.994999 +1533 0.431165 0.994999 +1534 0.395562 0.984998 +1515 0.398191 0.984998 +SURF 0x30 +mat 0 +refs 4 +1515 0.398191 0.984998 +1534 0.395562 0.984998 +1535 0.314647 0.952498 +1516 0.319634 0.952498 +SURF 0x30 +mat 0 +refs 4 +1516 0.319634 0.952498 +1535 0.314647 0.952498 +1536 0.291988 0.929999 +1517 0.297637 0.929999 +SURF 0x30 +mat 0 +refs 4 +1517 0.297637 0.929999 +1536 0.291988 0.929999 +1537 0.27257 0.8825 +1518 0.278785 0.8825 +SURF 0x30 +mat 0 +refs 4 +1518 0.278785 0.8825 +1537 0.27257 0.8825 +1538 0.256385 0.6825 +1519 0.263073 0.6825 +SURF 0x30 +mat 0 +refs 4 +1519 0.263073 0.6825 +1538 0.256385 0.6825 +1539 0.236967 0.635 +1520 0.244218 0.635 +SURF 0x30 +mat 0 +refs 4 +1520 0.244218 0.635 +1539 0.236967 0.635 +1540 0.168996 0.555 +1521 0.178231 0.555 +SURF 0x30 +mat 0 +refs 4 +1521 0.178231 0.555 +1540 0.168996 0.555 +1541 0.108682 0.475 +1522 0.119676 0.475 +SURF 0x30 +mat 0 +refs 4 +1522 0.119676 0.475 +1541 0.108682 0.475 +1542 0.0692893 0.3875 +1523 0.0818498 0.3875 +SURF 0x30 +mat 0 +refs 4 +1523 0.0818498 0.3875 +1542 0.0692893 0.3875 +1543 0.0315273 0.31 +1524 0.045184 0.31 +SURF 0x30 +mat 0 +refs 4 +1524 0.045184 0.31 +1543 0.0315273 0.31 +1544 0.0378192 0.247501 +1525 0.0512944 0.247501 +SURF 0x30 +mat 0 +refs 4 +1525 0.0512944 0.247501 +1544 0.0378192 0.247501 +1545 0.0504099 0.175 +1526 0.0635185 0.175 +SURF 0x30 +mat 0 +refs 4 +1526 0.0635185 0.175 +1545 0.0504099 0.175 +1546 0.088172 0.105001 +1527 0.100181 0.105001 +SURF 0x30 +mat 0 +refs 4 +1527 0.100181 0.105001 +1546 0.088172 0.105001 +1547 0.18573 0.0549999 +1528 0.19489 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1528 0.19489 0.0549999 +1547 0.18573 0.0549999 +1548 0.276992 0.0200004 +1529 0.283493 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1529 0.283493 0.0200004 +1548 0.276992 0.0200004 +1549 0.412312 0 +1530 0.414868 0 +SURF 0x30 +mat 1 +refs 4 +1530 0.414868 0 +1549 0.412312 0 +1550 0.494132 0 +1531 0.494303 0 +SURF 0x30 +mat 1 +refs 4 +1532 0.473241 1 +1551 0.472942 1 +1552 0.429853 0.994999 +1533 0.431165 0.994999 +SURF 0x30 +mat 0 +refs 4 +1533 0.431165 0.994999 +1552 0.429853 0.994999 +1553 0.393393 0.984998 +1534 0.395562 0.984998 +SURF 0x30 +mat 0 +refs 4 +1534 0.395562 0.984998 +1553 0.393393 0.984998 +1554 0.310527 0.952498 +1535 0.314647 0.952498 +SURF 0x30 +mat 0 +refs 4 +1535 0.314647 0.952498 +1554 0.310527 0.952498 +1555 0.287327 0.929999 +1536 0.291988 0.929999 +SURF 0x30 +mat 0 +refs 4 +1536 0.291988 0.929999 +1555 0.287327 0.929999 +1556 0.267438 0.8825 +1537 0.27257 0.8825 +SURF 0x30 +mat 0 +refs 4 +1537 0.27257 0.8825 +1556 0.267438 0.8825 +1557 0.250866 0.6825 +1538 0.256385 0.6825 +SURF 0x30 +mat 0 +refs 4 +1538 0.256385 0.6825 +1557 0.250866 0.6825 +1558 0.230981 0.635 +1539 0.236967 0.635 +SURF 0x30 +mat 0 +refs 4 +1539 0.236967 0.635 +1558 0.230981 0.635 +1559 0.161376 0.555 +1540 0.168996 0.555 +SURF 0x30 +mat 0 +refs 4 +1540 0.168996 0.555 +1559 0.161376 0.555 +1560 0.0996092 0.475 +1541 0.108682 0.475 +SURF 0x30 +mat 0 +refs 4 +1541 0.108682 0.475 +1560 0.0996092 0.475 +1561 0.0589282 0.3875 +1542 0.0692893 0.3875 +SURF 0x30 +mat 0 +refs 4 +1542 0.0692893 0.3875 +1561 0.0589282 0.3875 +1562 0.0202548 0.31 +1543 0.0315273 0.31 +SURF 0x30 +mat 0 +refs 4 +1543 0.0315273 0.31 +1562 0.0202548 0.31 +1563 0.0267014 0.247501 +1544 0.0378192 0.247501 +SURF 0x30 +mat 0 +refs 4 +1544 0.0378192 0.247501 +1563 0.0267014 0.247501 +1564 0.0395915 0.175 +1545 0.0504099 0.175 +SURF 0x30 +mat 0 +refs 4 +1545 0.0504099 0.175 +1564 0.0395915 0.175 +1565 0.0782649 0.105001 +1546 0.088172 0.105001 +SURF 0x30 +mat 0 +refs 4 +1546 0.088172 0.105001 +1565 0.0782649 0.105001 +1566 0.178167 0.0549999 +1547 0.18573 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1547 0.18573 0.0549999 +1566 0.178167 0.0549999 +1567 0.271625 0.0200004 +1548 0.276992 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1548 0.276992 0.0200004 +1567 0.271625 0.0200004 +1568 0.4102 0 +1549 0.412312 0 +SURF 0x30 +mat 1 +refs 4 +1549 0.412312 0 +1568 0.4102 0 +1569 0.493991 0 +1550 0.494132 0 +SURF 0x30 +mat 1 +refs 4 +1551 0.472942 1 +1570 0.472707 1 +1571 0.428824 0.994999 +1552 0.429853 0.994999 +SURF 0x30 +mat 1 +refs 4 +1552 0.429853 0.994999 +1571 0.428824 0.994999 +1572 0.391694 0.984998 +1553 0.393393 0.984998 +SURF 0x30 +mat 0 +refs 4 +1553 0.393393 0.984998 +1572 0.391694 0.984998 +1573 0.307306 0.952498 +1554 0.310527 0.952498 +SURF 0x30 +mat 0 +refs 4 +1554 0.310527 0.952498 +1573 0.307306 0.952498 +1574 0.283674 0.929999 +1555 0.287327 0.929999 +SURF 0x30 +mat 0 +refs 4 +1555 0.287327 0.929999 +1574 0.283674 0.929999 +1575 0.263423 0.8825 +1556 0.267438 0.8825 +SURF 0x30 +mat 0 +refs 4 +1556 0.267438 0.8825 +1575 0.263423 0.8825 +1576 0.246545 0.6825 +1557 0.250866 0.6825 +SURF 0x30 +mat 0 +refs 4 +1557 0.250866 0.6825 +1576 0.246545 0.6825 +1577 0.226293 0.635 +1558 0.230981 0.635 +SURF 0x30 +mat 0 +refs 4 +1558 0.230981 0.635 +1577 0.226293 0.635 +1578 0.155407 0.555 +1559 0.161376 0.555 +SURF 0x30 +mat 0 +refs 4 +1559 0.161376 0.555 +1578 0.155407 0.555 +1579 0.0925034 0.475 +1560 0.0996092 0.475 +SURF 0x30 +mat 0 +refs 4 +1560 0.0996092 0.475 +1579 0.0925034 0.475 +1580 0.0508135 0.3875 +1561 0.0589282 0.3875 +SURF 0x30 +mat 0 +refs 4 +1561 0.0589282 0.3875 +1580 0.0508135 0.3875 +1581 0.0114272 0.31 +1562 0.0202548 0.31 +SURF 0x30 +mat 0 +refs 4 +1562 0.0202548 0.31 +1581 0.0114272 0.31 +1582 0.0179915 0.247501 +1563 0.0267014 0.247501 +SURF 0x30 +mat 0 +refs 4 +1563 0.0267014 0.247501 +1582 0.0179915 0.247501 +1583 0.0311203 0.175 +1564 0.0395915 0.175 +SURF 0x30 +mat 0 +refs 4 +1564 0.0395915 0.175 +1583 0.0311203 0.175 +1584 0.0705033 0.105001 +1565 0.0782649 0.105001 +SURF 0x30 +mat 0 +refs 4 +1565 0.0782649 0.105001 +1584 0.0705033 0.105001 +1585 0.172245 0.0549999 +1566 0.178167 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1566 0.178167 0.0549999 +1585 0.172245 0.0549999 +1586 0.267425 0.0200004 +1567 0.271625 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1567 0.271625 0.0200004 +1586 0.267425 0.0200004 +1587 0.408549 0 +1568 0.4102 0 +SURF 0x30 +mat 1 +refs 4 +1568 0.4102 0 +1587 0.408549 0 +1588 0.49388 0 +1569 0.493991 0 +SURF 0x30 +mat 1 +refs 4 +1570 0.472707 1 +1589 0.472535 1 +1590 0.428084 0.994999 +1571 0.428824 0.994999 +SURF 0x30 +mat 1 +refs 4 +1571 0.428824 0.994999 +1590 0.428084 0.994999 +1591 0.390474 0.984998 +1572 0.391694 0.984998 +SURF 0x30 +mat 1 +refs 4 +1572 0.391694 0.984998 +1591 0.390474 0.984998 +1592 0.304989 0.952498 +1573 0.307306 0.952498 +SURF 0x30 +mat 0 +refs 4 +1573 0.307306 0.952498 +1592 0.304989 0.952498 +1593 0.281055 0.929999 +1574 0.283674 0.929999 +SURF 0x30 +mat 0 +refs 4 +1574 0.283674 0.929999 +1593 0.281055 0.929999 +1594 0.260538 0.8825 +1575 0.263423 0.8825 +SURF 0x30 +mat 0 +refs 4 +1575 0.263423 0.8825 +1594 0.260538 0.8825 +1595 0.243444 0.6825 +1576 0.246545 0.6825 +SURF 0x30 +mat 0 +refs 4 +1576 0.246545 0.6825 +1595 0.243444 0.6825 +1596 0.222927 0.635 +1577 0.226293 0.635 +SURF 0x30 +mat 0 +refs 4 +1577 0.226293 0.635 +1596 0.222927 0.635 +1597 0.151122 0.555 +1578 0.155407 0.555 +SURF 0x30 +mat 0 +refs 4 +1578 0.155407 0.555 +1597 0.151122 0.555 +1598 0.0874052 0.475 +1579 0.0925034 0.475 +SURF 0x30 +mat 0 +refs 4 +1579 0.0925034 0.475 +1598 0.0874052 0.475 +1599 0.0449856 0.3875 +1580 0.0508135 0.3875 +SURF 0x30 +mat 0 +refs 4 +1580 0.0508135 0.3875 +1599 0.0449856 0.3875 +1600 0.0050915 0.31 +1581 0.0114272 0.31 +SURF 0x30 +mat 0 +refs 4 +1581 0.0114272 0.31 +1600 0.0050915 0.31 +1601 0.0117399 0.247501 +1582 0.0179915 0.247501 +SURF 0x30 +mat 0 +refs 4 +1582 0.0179915 0.247501 +1601 0.0117399 0.247501 +1602 0.0250368 0.175 +1583 0.0311203 0.175 +SURF 0x30 +mat 0 +refs 4 +1583 0.0311203 0.175 +1602 0.0250368 0.175 +1603 0.0649344 0.105001 +1584 0.0705033 0.105001 +SURF 0x30 +mat 0 +refs 4 +1584 0.0705033 0.105001 +1603 0.0649344 0.105001 +1604 0.167994 0.0549999 +1585 0.172245 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1585 0.172245 0.0549999 +1604 0.167994 0.0549999 +1605 0.264405 0.0200004 +1586 0.267425 0.0200004 +SURF 0x30 +mat 1 +refs 4 +1586 0.267425 0.0200004 +1605 0.264405 0.0200004 +1606 0.407362 0 +1587 0.408549 0 +SURF 0x30 +mat 1 +refs 4 +1587 0.408549 0 +1606 0.407362 0 +1607 0.493802 0 +1588 0.49388 0 +SURF 0x30 +mat 1 +refs 4 +1589 0.472535 1 +1608 0.472434 1 +1609 0.42764 0.994999 +1590 0.428084 0.994999 +SURF 0x30 +mat 1 +refs 4 +1590 0.428084 0.994999 +1609 0.42764 0.994999 +1610 0.389737 0.984998 +1591 0.390474 0.984998 +SURF 0x30 +mat 1 +refs 4 +1591 0.390474 0.984998 +1610 0.389737 0.984998 +1611 0.303596 0.952498 +1592 0.304989 0.952498 +SURF 0x30 +mat 1 +refs 4 +1592 0.304989 0.952498 +1611 0.303596 0.952498 +1612 0.279478 0.929999 +1593 0.281055 0.929999 +SURF 0x30 +mat 1 +refs 4 +1593 0.281055 0.929999 +1612 0.279478 0.929999 +1613 0.258802 0.8825 +1594 0.260538 0.8825 +SURF 0x30 +mat 0 +refs 4 +1594 0.260538 0.8825 +1613 0.258802 0.8825 +1614 0.241574 0.6825 +1595 0.243444 0.6825 +SURF 0x30 +mat 0 +refs 4 +1595 0.243444 0.6825 +1614 0.241574 0.6825 +1615 0.220899 0.635 +1596 0.222927 0.635 +SURF 0x30 +mat 0 +refs 4 +1596 0.222927 0.635 +1615 0.220899 0.635 +1616 0.148543 0.555 +1597 0.151122 0.555 +SURF 0x30 +mat 0 +refs 4 +1597 0.151122 0.555 +1616 0.148543 0.555 +1617 0.0843316 0.475 +1598 0.0874052 0.475 +SURF 0x30 +mat 0 +refs 4 +1598 0.0874052 0.475 +1617 0.0843316 0.475 +1618 0.0414781 0.3875 +1599 0.0449856 0.3875 +SURF 0x30 +mat 0 +refs 4 +1599 0.0449856 0.3875 +1618 0.0414781 0.3875 +1619 0.00127453 0.31 +1600 0.0050915 0.31 +SURF 0x30 +mat 0 +refs 4 +1600 0.0050915 0.31 +1619 0.00127453 0.31 +1620 0.0079768 0.247501 +1601 0.0117399 0.247501 +SURF 0x30 +mat 0 +refs 4 +1601 0.0117399 0.247501 +1620 0.0079768 0.247501 +1621 0.021378 0.175 +1602 0.0250368 0.175 +SURF 0x30 +mat 0 +refs 4 +1602 0.0250368 0.175 +1621 0.021378 0.175 +1622 0.0615781 0.105001 +1603 0.0649344 0.105001 +SURF 0x30 +mat 0 +refs 4 +1603 0.0649344 0.105001 +1622 0.0615781 0.105001 +1623 0.165435 0.0549999 +1604 0.167994 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1604 0.167994 0.0549999 +1623 0.165435 0.0549999 +1624 0.262589 0.0200004 +1605 0.264405 0.0200004 +SURF 0x30 +mat 1 +refs 4 +1605 0.264405 0.0200004 +1624 0.262589 0.0200004 +1625 0.406649 0 +1606 0.407362 0 +SURF 0x30 +mat 1 +refs 4 +1606 0.407362 0 +1625 0.406649 0 +1626 0.493755 0 +1607 0.493802 0 +SURF 0x30 +mat 1 +refs 4 +1608 0.472434 1 +0 0.472401 1 +3 0.427492 0.994999 +1609 0.42764 0.994999 +SURF 0x30 +mat 1 +refs 4 +1609 0.42764 0.994999 +3 0.427492 0.994999 +5 0.389492 0.984998 +1610 0.389737 0.984998 +SURF 0x30 +mat 1 +refs 4 +1610 0.389737 0.984998 +5 0.389492 0.984998 +7 0.303132 0.952498 +1611 0.303596 0.952498 +SURF 0x30 +mat 1 +refs 4 +1611 0.303596 0.952498 +7 0.303132 0.952498 +9 0.27895 0.929999 +1612 0.279478 0.929999 +SURF 0x30 +mat 1 +refs 4 +1612 0.279478 0.929999 +9 0.27895 0.929999 +11 0.258224 0.8825 +1613 0.258802 0.8825 +SURF 0x30 +mat 1 +refs 4 +1613 0.258802 0.8825 +11 0.258224 0.8825 +13 0.240952 0.6825 +1614 0.241574 0.6825 +SURF 0x30 +mat 1 +refs 4 +1614 0.241574 0.6825 +13 0.240952 0.6825 +15 0.220223 0.635 +1615 0.220899 0.635 +SURF 0x30 +mat 1 +refs 4 +1615 0.220899 0.635 +15 0.220223 0.635 +17 0.147679 0.555 +1616 0.148543 0.555 +SURF 0x30 +mat 1 +refs 4 +1616 0.148543 0.555 +17 0.147679 0.555 +19 0.0833059 0.475 +1617 0.0843316 0.475 +SURF 0x30 +mat 1 +refs 4 +1617 0.0843316 0.475 +19 0.0833059 0.475 +21 0.0403078 0.3875 +1618 0.0414781 0.3875 +SURF 0x30 +mat 1 +refs 4 +1618 0.0414781 0.3875 +21 0.0403078 0.3875 +23 0 0.31 +1619 0.00127453 0.31 +SURF 0x30 +mat 1 +refs 4 +1619 0.00127453 0.31 +23 0 0.31 +25 0.00671911 0.247501 +1620 0.0079768 0.247501 +SURF 0x30 +mat 1 +refs 4 +1620 0.0079768 0.247501 +25 0.00671911 0.247501 +27 0.0201539 0.175 +1621 0.021378 0.175 +SURF 0x30 +mat 1 +refs 4 +1621 0.021378 0.175 +27 0.0201539 0.175 +29 0.0604583 0.105001 +1622 0.0615781 0.105001 +SURF 0x30 +mat 1 +refs 4 +1622 0.0615781 0.105001 +29 0.0604583 0.105001 +31 0.164581 0.0549999 +1623 0.165435 0.0549999 +SURF 0x30 +mat 1 +refs 4 +1623 0.165435 0.0549999 +31 0.164581 0.0549999 +33 0.261984 0.0200004 +1624 0.262589 0.0200004 +SURF 0x30 +mat 1 +refs 4 +1624 0.262589 0.0200004 +33 0.261984 0.0200004 +35 0.40641 0 +1625 0.406649 0 +SURF 0x30 +mat 1 +refs 4 +1625 0.406649 0 +35 0.40641 0 +37 0.493738 0 +1626 0.493755 0 +kids 0 diff --git a/demos/simon/astropong/data/embossed_herring.rgb b/demos/simon/astropong/data/embossed_herring.rgb new file mode 100644 index 0000000..a87aceb Binary files /dev/null and b/demos/simon/astropong/data/embossed_herring.rgb differ diff --git a/demos/simon/astropong/data/redpaddle2.ac b/demos/simon/astropong/data/redpaddle2.ac new file mode 100644 index 0000000..f79073b --- /dev/null +++ b/demos/simon/astropong/data/redpaddle2.ac @@ -0,0 +1,12965 @@ +AC3Db +MATERIAL "ac3dmat0" rgb 0 0 0 amb 0 0 0 emis 0 0 0 spec 0 0 0 shi 128 trans 0.22 +MATERIAL "ac3dmat8" rgb 0.478 0.502 1 amb 0.2 0.2 1 emis 0 0 0 spec 0.502 0.502 1 shi 10 trans 0.22 +MATERIAL "ac3dmat3" rgb 1 0 0 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.502 0.502 0.502 shi 10 trans 0.22 +OBJECT world +kids 6 +OBJECT poly +name "noname" +loc -0.514814 -0.559209 1.17231 +texture "Penguin_foot.rgba" +numvert 7 +0.198701 -0.401817 -1.07875 +-0.344844 -0.121745 -1.15407 +0.0952821 -0.405379 -1.08033 +-0.111076 0.281581 -1.2391 +0.187626 -0.318231 -0.98817 +0.344844 -0.221492 -1.1158 +0.306371 0.405379 -1.25722 +numsurf 7 +SURF 0x10 +mat 2 +refs 3 +0 0.546875 -0.0625 +1 -0.078125 0.65625 +2 0.40625 0 +SURF 0x10 +mat 2 +refs 3 +3 0.390625 1.03125 +1 -0.078125 0.65625 +0 0.546875 -0.0625 +SURF 0x10 +mat 2 +refs 3 +2 0.40625 0 +1 -0.078125 0.65625 +4 0.546875 -0.0625 +SURF 0x10 +mat 2 +refs 3 +4 0.546875 -0.0625 +1 -0.078125 0.65625 +3 0.390625 1.03125 +SURF 0x10 +mat 2 +refs 3 +5 0.8125 0.078125 +3 0.390625 1.03125 +0 0.546875 -0.0625 +SURF 0x10 +mat 2 +refs 3 +6 1 0.921875 +3 0.390625 1.03125 +5 0.8125 0.078125 +SURF 0x10 +mat 2 +refs 3 +4 0.546875 -0.0625 +3 0.390625 1.03125 +5 0.8125 0.078125 +kids 0 +OBJECT poly +name "noname" +loc 0.652608 -0.580393 1.13571 +texture "Penguin_foot.rgba" +numvert 7 +-0.231619 -0.39612 -1.00554 +0.347392 -0.225299 -1.08086 +0.180139 0.217057 -1.16589 +-0.347392 -0.190307 -1.0426 +-0.211644 0.419607 -1.18402 +-0.207667 -0.315947 -0.914964 +-0.130323 -0.419607 -1.00713 +numsurf 7 +SURF 0x10 +mat 2 +refs 3 +0 0.546875 -0.0625 +1 -0.078125 0.65625 +2 0.390625 1.03125 +SURF 0x10 +mat 2 +refs 3 +0 0.546875 -0.0625 +2 0.390625 1.03125 +3 0.8125 0.078125 +SURF 0x10 +mat 2 +refs 3 +3 0.8125 0.078125 +2 0.390625 1.03125 +4 1 0.921875 +SURF 0x10 +mat 2 +refs 3 +2 0.390625 1.03125 +1 -0.078125 0.65625 +5 0.546875 -0.0625 +SURF 0x10 +mat 2 +refs 3 +3 0.8125 0.078125 +2 0.390625 1.03125 +5 0.546875 -0.0625 +SURF 0x10 +mat 2 +refs 3 +6 0.40625 0 +1 -0.078125 0.65625 +0 0.546875 -0.0625 +SURF 0x10 +mat 2 +refs 3 +5 0.546875 -0.0625 +1 -0.078125 0.65625 +6 0.40625 0 +kids 0 +OBJECT poly +name "NoName" +loc -0.665314 -0.206815 0.685273 +texture "Penguin_body.rgb" +numvert 7 +-0.1012 -2.38419e-07 -0.0333188 +0.099768 0.226555 -0.280647 +0.101146 0.226555 -0.0165908 +-0.1012 -2.38419e-07 -0.25629 +0.251211 0.280667 -0.280647 +0.252588 0.280667 -0.0165908 +-0.252588 -0.280667 -0.148619 +numsurf 5 +SURF 0x20 +mat 0 +refs 3 +0 0 0 +1 0.1 0 +2 0.1 0.1 +SURF 0x20 +mat 0 +refs 3 +1 0 0 +0 0.1 0 +3 0.1 0.1 +SURF 0x20 +mat 0 +refs 3 +2 0 0 +4 0.1 0 +5 0.1 0.1 +SURF 0x20 +mat 0 +refs 3 +4 0 0 +2 0.1 0 +1 0.1 0.1 +SURF 0x20 +mat 0 +refs 3 +6 0 0 +3 0.1 0 +0 0.1 0.1 +kids 0 +OBJECT poly +name "NoName" +loc 0.724938 -0.207557 0.678666 +texture "Penguin_body.rgb" +numvert 7 +-0.101147 0.226553 -0.267434 +-0.251213 0.280666 -0.00337803 +-0.25259 0.280666 -0.267434 +-0.0997691 0.226553 -0.00337803 +0.101201 1.01328e-06 -0.250706 +0.101201 1.01328e-06 -0.027735 +0.25259 -0.280666 -0.135406 +numsurf 5 +SURF 0x20 +mat 0 +refs 3 +0 0 0 +1 0.1 0 +2 0.1 0.1 +SURF 0x20 +mat 0 +refs 3 +1 0 0 +0 0.1 0 +3 0.1 0.1 +SURF 0x20 +mat 0 +refs 3 +4 0 0 +3 0.1 0 +0 0.1 0.1 +SURF 0x20 +mat 0 +refs 3 +3 0 0 +4 0.1 0 +5 0.1 0.1 +SURF 0x20 +mat 0 +refs 3 +6 0 0 +5 0.1 0 +4 0.1 0.1 +kids 0 +OBJECT poly +name "NoName" +loc 0.0732157 0.365538 1.05337 +texture "Penguin_beak.rgb" +numvert 34 +-0.205941 -0.0291858 -0.743699 +0.204287 0.0598249 -0.719919 +-0.205223 -0.0299875 -0.743641 +-0.100945 -0.157938 -1.02078 +0.015027 -0.142478 -1.04761 +-0.103832 -0.134234 -1.0245 +0.0099833 -0.17073 -1.00995 +0.104844 -0.138958 -1.00695 +0.112297 -0.117466 -1.00785 +-0.205755 -0.030581 -0.747515 +-0.164313 -0.0904827 -0.730556 +-0.00303435 -0.17894 -0.704537 +0.206058 -0.0267631 -0.710003 +0.205292 0.0594168 -0.717591 +0.107712 -0.100851 -1.01232 +0.0278854 0.0442213 -1.03079 +0.016685 -0.0725842 -1.0651 +0.108843 -0.0373889 -1.02426 +-0.0533645 0.0217681 -1.03736 +-0.10224 -0.071278 -1.0413 +0.162112 0.0891278 -0.719334 +0.205602 0.0605793 -0.72087 +-0.000388145 0.17894 -0.732459 +-0.162888 0.0891278 -0.745583 +-0.206057 -0.0287286 -0.744322 +-0.103407 -0.134771 -1.02385 +0.107476 -0.101252 -1.01175 +0.204762 0.0586234 -0.717301 +-0.205635 -0.0310948 -0.746927 +0.0152967 -0.142599 -1.04703 +0.205067 0.0598249 -0.720523 +0.0170057 -0.0732907 -1.06506 +-0.101759 -0.0716867 -1.04125 +0.108661 -0.0380067 -1.02425 +numsurf 40 +SURF 0x10 +mat 2 +refs 3 +0 0 0 +1 0 0 +2 0 0 +SURF 0x10 +mat 2 +refs 3 +3 0.179286 0.236445 +4 0.328444 0.27802 +5 0.171928 0.303494 +SURF 0x10 +mat 2 +refs 3 +6 0.325093 0.178494 +4 0.328444 0.27802 +3 0.179286 0.236445 +SURF 0x10 +mat 2 +refs 3 +7 0.649815 0.29012 +4 0.328444 0.27802 +6 0.325093 0.178494 +SURF 0x10 +mat 2 +refs 3 +8 0.763049 0.377184 +4 0.328444 0.27802 +7 0.649815 0.29012 +SURF 0x10 +mat 2 +refs 3 +5 0.171928 0.303494 +9 0 0.419942 +3 0.179286 0.236445 +SURF 0x10 +mat 2 +refs 3 +10 0.0978096 0.25 +3 0.179286 0.236445 +9 0 0.419942 +SURF 0x10 +mat 2 +refs 3 +3 0.179286 0.236445 +10 0.0978096 0.25 +6 0.325093 0.178494 +SURF 0x10 +mat 2 +refs 3 +11 0.469834 0 +6 0.325093 0.178494 +10 0.0978096 0.25 +SURF 0x10 +mat 2 +refs 3 +6 0.325093 0.178494 +11 0.469834 0 +7 0.649815 0.29012 +SURF 0x10 +mat 2 +refs 3 +12 1 0.43559 +7 0.649815 0.29012 +11 0.469834 0 +SURF 0x10 +mat 2 +refs 3 +7 0.649815 0.29012 +12 1 0.43559 +8 0.763049 0.377184 +SURF 0x10 +mat 2 +refs 3 +8 0.763049 0.377184 +13 0.984563 0.672853 +14 0.655176 0.397835 +SURF 0x10 +mat 2 +refs 3 +13 0.984563 0.672853 +8 0.763049 0.377184 +12 1 0.43559 +SURF 0x10 +mat 2 +refs 3 +14 0.655176 0.397835 +4 0.328444 0.27802 +8 0.763049 0.377184 +SURF 0x10 +mat 2 +refs 3 +15 0.469834 0.625 +16 0.328444 0.27802 +17 0.655176 0.397835 +SURF 0x10 +mat 2 +refs 3 +18 0.283822 0.5625 +16 0.328444 0.27802 +15 0.469834 0.625 +SURF 0x10 +mat 2 +refs 3 +19 0.171928 0.303494 +16 0.328444 0.27802 +18 0.283822 0.5625 +SURF 0x10 +mat 2 +refs 3 +20 0.841857 0.75 +17 0.655176 0.397835 +21 0.984563 0.672853 +SURF 0x10 +mat 2 +refs 3 +17 0.655176 0.397835 +20 0.841857 0.75 +15 0.469834 0.625 +SURF 0x10 +mat 2 +refs 3 +22 0.469834 1 +15 0.469834 0.625 +20 0.841857 0.75 +SURF 0x10 +mat 2 +refs 3 +15 0.469834 0.625 +22 0.469834 1 +18 0.283822 0.5625 +SURF 0x10 +mat 2 +refs 3 +23 0.0978096 0.75 +18 0.283822 0.5625 +22 0.469834 1 +SURF 0x10 +mat 2 +refs 3 +18 0.283822 0.5625 +23 0.0978096 0.75 +19 0.171928 0.303494 +SURF 0x10 +mat 2 +refs 3 +24 0 0.419942 +19 0.171928 0.303494 +23 0.0978096 0.75 +SURF 0x10 +mat 2 +refs 3 +25 0 0 +26 0 0 +27 0 0 +SURF 0x10 +mat 2 +refs 3 +28 0 0 +25 0 0 +27 0 0 +SURF 0x10 +mat 2 +refs 3 +29 0 0 +28 0 0 +27 0 0 +SURF 0x10 +mat 2 +refs 3 +26 0 0 +29 0 0 +27 0 0 +SURF 0x10 +mat 2 +refs 3 +25 0 0 +28 0 0 +29 0 0 +SURF 0x10 +mat 2 +refs 3 +26 0 0 +25 0 0 +29 0 0 +SURF 0x10 +mat 2 +refs 3 +1 0 0 +30 0 0 +31 0 0 +SURF 0x10 +mat 2 +refs 3 +1 0 0 +31 0 0 +2 0 0 +SURF 0x10 +mat 2 +refs 3 +32 0 0 +0 0 0 +2 0 0 +SURF 0x10 +mat 2 +refs 3 +31 0 0 +32 0 0 +2 0 0 +SURF 0x10 +mat 2 +refs 3 +30 0 0 +1 0 0 +32 0 0 +SURF 0x10 +mat 2 +refs 3 +33 0 0 +30 0 0 +32 0 0 +SURF 0x10 +mat 2 +refs 3 +31 0 0 +33 0 0 +32 0 0 +SURF 0x10 +mat 2 +refs 3 +1 0 0 +0 0 0 +32 0 0 +SURF 0x10 +mat 2 +refs 3 +30 0 0 +33 0 0 +31 0 0 +kids 0 +OBJECT poly +name "line" +loc 0.0604815 0.00977969 0.580524 +texture "Penguin_body2.rgb" +texoff -0.01 0 +numvert 1627 +-0.0355607 0.990221 0.0071162 +-0.0355172 0.990221 0.00598335 +-0.0932325 0.980316 0.00217259 +-0.0934231 0.980316 0.0071162 +-0.142069 0.960511 -0.00105178 +-0.142386 0.960511 0.0071162 +-0.253058 0.896146 -0.00837982 +-0.253656 0.896146 0.0071162 +-0.284135 0.851587 -0.0104318 +-0.284815 0.851587 0.0071162 +-0.310774 0.757518 -0.0121907 +-0.311519 0.757518 0.0071162 +-0.332972 0.36143 -0.0136563 +-0.333773 0.36143 0.0071162 +-0.359611 0.267359 -0.015415 +-0.360482 0.267359 0.0071162 +-0.452839 0.108924 -0.0215706 +-0.453952 0.108924 0.0071162 +-0.535573 -0.049511 -0.0270326 +-0.536894 -0.049511 0.0071162 +-0.590788 -0.222799 -0.0330026 +-0.592296 -0.222799 0.0071162 +-0.642588 -0.376283 -0.0365198 +-0.64423 -0.376283 0.0071162 +-0.633953 -0.50006 -0.0359339 +-0.635573 -0.50006 0.0071162 +-0.616686 -0.643644 -0.0347614 +-0.618263 -0.643644 0.0071162 +-0.564889 -0.782273 -0.0312434 +-0.566332 -0.782273 0.0071162 +-0.431074 -0.881297 -0.0221567 +-0.432175 -0.881297 0.0071162 +-0.305895 -0.950611 -0.0136563 +-0.306675 -0.950611 0.0071162 +-0.120279 -0.990221 -0.00105178 +-0.120587 -0.990221 0.0071162 +-0.00804627 -0.990221 0.00656974 +-0.00806785 -0.990221 0.0071162 +-0.0353873 0.990221 0.00485623 +-0.0926605 0.980316 -0.00274539 +-0.14112 0.960511 -0.0091778 +-0.251265 0.896146 -0.023797 +-0.282102 0.851587 -0.0278902 +-0.308538 0.757518 -0.0313987 +-0.330562 0.36143 -0.0343225 +-0.356998 0.267359 -0.0378309 +-0.449515 0.108924 -0.0501111 +-0.531612 -0.049511 -0.0610081 +-0.586268 -0.222799 -0.0729171 +-0.63767 -0.376283 -0.079934 +-0.629104 -0.50006 -0.078764 +-0.611972 -0.643644 -0.076425 +-0.560565 -0.782273 -0.0694081 +-0.427777 -0.881297 -0.0512811 +-0.303555 -0.950611 -0.0343225 +-0.11936 -0.990221 -0.0091778 +-0.00798559 -0.990221 0.00602579 +-0.0351663 0.990221 0.00374055 +-0.0917073 0.980316 -0.00761342 +-0.139548 0.960511 -0.0172211 +-0.248279 0.896146 -0.0390567 +-0.278727 0.851587 -0.0451699 +-0.30482 0.757518 -0.0504111 +-0.326567 0.36143 -0.0547781 +-0.35266 0.267359 -0.0600181 +-0.443995 0.108924 -0.07836 +-0.525043 -0.049511 -0.0946359 +-0.578759 -0.222799 -0.112423 +-0.629507 -0.376283 -0.122904 +-0.621049 -0.50006 -0.121157 +-0.604133 -0.643644 -0.117663 +-0.55339 -0.782273 -0.107183 +-0.4223 -0.881297 -0.0801071 +-0.299664 -0.950611 -0.0547781 +-0.117831 -0.990221 -0.0172211 +-0.00788593 -0.990221 0.00548744 +-0.034863 0.990221 0.00264263 +-0.0903814 0.980316 -0.0124067 +-0.137359 0.960511 -0.0251402 +-0.244128 0.896146 -0.054081 +-0.274021 0.851587 -0.0621841 +-0.299647 0.757518 -0.0691299 +-0.321 0.36143 -0.074918 +-0.34662 0.267359 -0.081863 +-0.436304 0.108924 -0.106173 +-0.515888 -0.049511 -0.127745 +-0.568304 -0.222799 -0.15132 +-0.618133 -0.376283 -0.165212 +-0.609827 -0.50006 -0.162897 +-0.593218 -0.643644 -0.158266 +-0.543389 -0.782273 -0.144375 +-0.41467 -0.881297 -0.108489 +-0.294252 -0.950611 -0.074918 +-0.115703 -0.990221 -0.0251402 +-0.00774288 -0.990221 0.0049578 +-0.0344775 0.990221 0.00156701 +-0.0886915 0.980316 -0.0171002 +-0.134565 0.960511 -0.0328954 +-0.23882 0.896146 -0.0687931 +-0.268016 0.851587 -0.0788449 +-0.293034 0.757518 -0.08746 +-0.313889 0.36143 -0.09464 +-0.338908 0.267359 -0.103255 +-0.426486 0.108924 -0.133409 +-0.504198 -0.049511 -0.160167 +-0.554954 -0.222799 -0.18941 +-0.603609 -0.376283 -0.206641 +-0.595502 -0.50006 -0.203769 +-0.579279 -0.643644 -0.198026 +-0.530624 -0.782273 -0.180795 +-0.404925 -0.881297 -0.136281 +-0.287337 -0.950611 -0.09464 +-0.112982 -0.990221 -0.0328954 +-0.00756097 -0.990221 0.00443864 +-0.034005 0.990221 0.000519395 +-0.0866421 0.980316 -0.0216701 +-0.131176 0.960511 -0.040446 +-0.232395 0.896146 -0.0831191 +-0.260737 0.851587 -0.0950669 +-0.285027 0.757518 -0.105309 +-0.305271 0.36143 -0.113843 +-0.329566 0.267359 -0.124085 +-0.414587 0.108924 -0.159929 +-0.490033 -0.049511 -0.191737 +-0.53877 -0.222799 -0.226499 +-0.586013 -0.376283 -0.246981 +-0.57814 -0.50006 -0.243568 +-0.562394 -0.643644 -0.23674 +-0.515151 -0.782273 -0.216257 +-0.393122 -0.881297 -0.163343 +-0.278961 -0.950611 -0.113843 +-0.109689 -0.990221 -0.040446 +-0.00733995 -0.990221 0.00393343 +-0.0334549 0.990221 -0.000494242 +-0.0842416 0.980316 -0.0260938 +-0.127212 0.960511 -0.047755 +-0.224877 0.896146 -0.0969851 +-0.252222 0.851587 -0.110769 +-0.275659 0.757518 -0.122584 +-0.295192 0.36143 -0.13243 +-0.318634 0.267359 -0.144245 +-0.40067 0.108924 -0.185598 +-0.473464 -0.049511 -0.222293 +-0.519848 -0.222799 -0.262397 +-0.565427 -0.376283 -0.286027 +-0.557831 -0.50006 -0.282089 +-0.542635 -0.643644 -0.274212 +-0.497057 -0.782273 -0.250581 +-0.379313 -0.881297 -0.189537 +-0.26916 -0.950611 -0.13243 +-0.105837 -0.990221 -0.047755 +-0.00707996 -0.990221 0.00344419 +-0.0328308 0.990221 -0.00146902 +-0.0815075 0.980316 -0.0303477 +-0.122697 0.960511 -0.0547841 +-0.216306 0.896146 -0.11032 +-0.242516 0.851587 -0.12587 +-0.264983 0.757518 -0.139199 +-0.283706 0.36143 -0.150306 +-0.306172 0.267359 -0.163635 +-0.384803 0.108924 -0.210285 +-0.454576 -0.049511 -0.251681 +-0.49827 -0.222799 -0.296921 +-0.541959 -0.376283 -0.323579 +-0.53468 -0.50006 -0.319136 +-0.520117 -0.643644 -0.31025 +-0.476427 -0.782273 -0.283593 +-0.363571 -0.881297 -0.214728 +-0.257989 -0.950611 -0.150306 +-0.101443 -0.990221 -0.0547841 +-0.00678968 -0.990221 0.00297379 +-0.0321288 0.990221 -0.00240016 +-0.0784528 0.980316 -0.034411 +-0.117644 0.960511 -0.0614971 +-0.206726 0.896146 -0.123057 +-0.231667 0.851587 -0.140293 +-0.253046 0.757518 -0.155068 +-0.270863 0.36143 -0.167379 +-0.292242 0.267359 -0.182154 +-0.367068 0.108924 -0.233864 +-0.433466 -0.049511 -0.279749 +-0.474157 -0.222799 -0.329897 +-0.515732 -0.376283 -0.359445 +-0.508803 -0.50006 -0.354521 +-0.494947 -0.643644 -0.344673 +-0.453372 -0.782273 -0.315122 +-0.345975 -0.881297 -0.238789 +-0.245506 -0.950611 -0.167379 +-0.0965342 -0.990221 -0.0614971 +-0.00646043 -0.990221 0.00252461 +-0.0313578 0.990221 -0.00328302 +-0.0750903 0.980316 -0.0382626 +-0.11209 0.960511 -0.067861 +-0.196184 0.896146 -0.13513 +-0.219734 0.851587 -0.153966 +-0.239917 0.757518 -0.17011 +-0.256733 0.36143 -0.183564 +-0.276916 0.267359 -0.199709 +-0.347556 0.108924 -0.256215 +-0.410241 -0.049511 -0.306356 +-0.447626 -0.222799 -0.361153 +-0.486874 -0.376283 -0.393445 +-0.480336 -0.50006 -0.388061 +-0.46725 -0.643644 -0.377301 +-0.428007 -0.782273 -0.345009 +-0.326615 -0.881297 -0.261596 +-0.231771 -0.950611 -0.183564 +-0.0911353 -0.990221 -0.067861 +-0.00609636 -0.990221 0.00209856 +-0.0305214 0.990221 -0.00411224 +-0.0714377 0.980316 -0.0418831 +-0.106058 0.960511 -0.073843 +-0.18474 0.896146 -0.146479 +-0.206769 0.851587 -0.166817 +-0.225657 0.757518 -0.18425 +-0.24139 0.36143 -0.198777 +-0.260277 0.267359 -0.21621 +-0.326368 0.108924 -0.277224 +-0.385019 -0.049511 -0.331365 +-0.418816 -0.222799 -0.390537 +-0.455538 -0.376283 -0.425401 +-0.44942 -0.50006 -0.419589 +-0.437179 -0.643644 -0.407969 +-0.400458 -0.782273 -0.373105 +-0.305596 -0.881297 -0.283035 +-0.216852 -0.950611 -0.198777 +-0.0852685 -0.990221 -0.073843 +-0.00570643 -0.990221 0.00169861 +-0.0296245 0.990221 -0.00488496 +-0.0675163 0.980316 -0.0452541 +-0.0995759 0.960511 -0.0794121 +-0.172448 0.896146 -0.157045 +-0.192852 0.851587 -0.178782 +-0.21034 0.757518 -0.197414 +-0.224912 0.36143 -0.212941 +-0.242399 0.267359 -0.231573 +-0.303611 0.108924 -0.296784 +-0.357925 -0.049511 -0.354649 +-0.38787 -0.222799 -0.417889 +-0.42188 -0.376283 -0.455153 +-0.416212 -0.50006 -0.448945 +-0.404877 -0.643644 -0.436521 +-0.370868 -0.782273 -0.399257 +-0.283012 -0.881297 -0.302995 +-0.200829 -0.950611 -0.212941 +-0.0789683 -0.990221 -0.0794121 +-0.00528181 -0.990221 0.00132585 +-0.0286669 0.990221 -0.00559616 +-0.0633436 0.980316 -0.048358 +-0.0926865 0.960511 -0.0845409 +-0.159367 0.896146 -0.166775 +-0.178042 0.851587 -0.1898 +-0.194043 0.757518 -0.209536 +-0.20738 0.36143 -0.225983 +-0.223386 0.267359 -0.245719 +-0.279399 0.108924 -0.314795 +-0.329106 -0.049511 -0.376093 +-0.354948 -0.222799 -0.443081 +-0.386072 -0.376283 -0.482553 +-0.380885 -0.50006 -0.475973 +-0.370512 -0.643644 -0.462817 +-0.339389 -0.782273 -0.423345 +-0.258995 -0.881297 -0.321374 +-0.183783 -0.950611 -0.225983 +-0.0722652 -0.990221 -0.0845409 +-0.00483561 -0.990221 0.000982642 +-0.0276573 0.990221 -0.00624263 +-0.0589414 0.980316 -0.0511791 +-0.0854115 0.960511 -0.089202 +-0.14557 0.896146 -0.175618 +-0.162417 0.851587 -0.199815 +-0.176854 0.757518 -0.220554 +-0.188887 0.36143 -0.237837 +-0.203325 0.267359 -0.258577 +-0.253856 0.108924 -0.331167 +-0.298698 -0.049511 -0.395581 +-0.32022 -0.222799 -0.465977 +-0.348297 -0.376283 -0.507453 +-0.343618 -0.50006 -0.500541 +-0.334258 -0.643644 -0.486717 +-0.306181 -0.782273 -0.445237 +-0.233651 -0.881297 -0.33808 +-0.165801 -0.950611 -0.237837 +-0.0651938 -0.990221 -0.089202 +-0.0043633 -0.990221 0.000670552 +-0.0266043 0.990221 -0.00682104 +-0.0543354 0.980316 -0.053703 +-0.0777984 0.960511 -0.0933729 +-0.131124 0.896146 -0.18353 +-0.146056 0.851587 -0.208774 +-0.158855 0.757518 -0.230412 +-0.169523 0.36143 -0.248444 +-0.182323 0.267359 -0.270081 +-0.227117 0.108924 -0.345813 +-0.266868 -0.049511 -0.413017 +-0.283857 -0.222799 -0.486461 +-0.308746 -0.376283 -0.529737 +-0.304599 -0.50006 -0.522521 +-0.296302 -0.643644 -0.508097 +-0.271413 -0.782273 -0.464821 +-0.20712 -0.881297 -0.353025 +-0.146974 -0.950611 -0.248444 +-0.0577888 -0.990221 -0.0933729 +-0.003865 -0.990221 0.000391364 +-0.0255039 0.990221 -0.00732863 +-0.0495431 0.980316 -0.0559169 +-0.0698821 0.960511 -0.0970311 +-0.116106 0.896146 -0.190471 +-0.129049 0.851587 -0.216634 +-0.140141 0.757518 -0.23906 +-0.149388 0.36143 -0.257748 +-0.16048 0.267359 -0.280173 +-0.199312 0.108924 -0.358661 +-0.233764 -0.049511 -0.428313 +-0.246048 -0.222799 -0.504429 +-0.267622 -0.376283 -0.549281 +-0.264025 -0.50006 -0.541805 +-0.256837 -0.643644 -0.526853 +-0.235263 -0.782273 -0.482005 +-0.179532 -0.881297 -0.366137 +-0.127398 -0.950611 -0.257748 +-0.0500934 -0.990221 -0.0970311 +-0.0033493 -0.990221 0.000146627 +-0.0243685 0.990221 -0.00776219 +-0.0445905 0.980316 -0.0578099 +-0.0617015 0.960511 -0.100159 +-0.10059 0.896146 -0.196405 +-0.111474 0.851587 -0.223354 +-0.120808 0.757518 -0.246453 +-0.128585 0.36143 -0.265702 +-0.137918 0.267359 -0.288801 +-0.170585 0.108924 -0.369649 +-0.199568 -0.049511 -0.441389 +-0.206986 -0.222799 -0.519793 +-0.225132 -0.376283 -0.565989 +-0.222108 -0.50006 -0.558289 +-0.216059 -0.643644 -0.542889 +-0.197913 -0.782273 -0.496693 +-0.15103 -0.881297 -0.377349 +-0.107172 -0.950611 -0.265702 +-0.0421424 -0.990221 -0.100159 +-0.00282073 -0.990221 -6.25849e-05 +-0.0232074 0.990221 -0.00812018 +-0.0395081 0.980316 -0.0593729 +-0.0532999 0.960511 -0.10274 +-0.0846488 0.896146 -0.201301 +-0.0934275 0.851587 -0.228899 +-0.100954 0.757518 -0.252554 +-0.107224 0.36143 -0.272266 +-0.114746 0.267359 -0.295921 +-0.141082 0.108924 -0.378713 +-0.164445 -0.049511 -0.452177 +-0.166867 -0.222799 -0.532469 +-0.181499 -0.376283 -0.579777 +-0.17906 -0.50006 -0.571893 +-0.174185 -0.643644 -0.556125 +-0.159553 -0.782273 -0.508813 +-0.121756 -0.881297 -0.386597 +-0.0863994 -0.950611 -0.272266 +-0.0339749 -0.990221 -0.10274 +-0.00227475 -0.990221 -0.000235438 +-0.0220158 0.990221 -0.00840056 +-0.034317 0.980316 -0.0605961 +-0.0447205 0.960511 -0.104761 +-0.0683743 0.896146 -0.205136 +-0.0749993 0.851587 -0.233241 +-0.0806755 0.757518 -0.257331 +-0.0854072 0.36143 -0.277407 +-0.0910833 0.267359 -0.301497 +-0.11095 0.108924 -0.385813 +-0.128581 -0.049511 -0.460629 +-0.125903 -0.222799 -0.542397 +-0.136939 -0.376283 -0.590577 +-0.135102 -0.50006 -0.582549 +-0.131419 -0.643644 -0.566489 +-0.120383 -0.782273 -0.518309 +-0.0918633 -0.881297 -0.393841 +-0.0651895 -0.950611 -0.277407 +-0.0256337 -0.990221 -0.104761 +-0.0017159 -0.990221 -0.000370622 +-0.0208069 0.990221 -0.00860178 +-0.0290439 0.980316 -0.061474 +-0.0360112 0.960511 -0.106212 +-0.0518439 0.896146 -0.207889 +-0.0562809 0.851587 -0.236359 +-0.060081 0.757518 -0.260761 +-0.0632483 0.36143 -0.281097 +-0.0670483 0.267359 -0.305499 +-0.0803505 0.108924 -0.390909 +-0.0921536 -0.049511 -0.466697 +-0.0842936 -0.222799 -0.549525 +-0.0916813 -0.376283 -0.598329 +-0.0904507 -0.50006 -0.590197 +-0.0879853 -0.643644 -0.573929 +-0.0805976 -0.782273 -0.525121 +-0.0615022 -0.881297 -0.399041 +-0.0436416 -0.950611 -0.281097 +-0.0171585 -0.990221 -0.106212 +-0.00114822 -0.990221 -0.000467777 +-0.0195849 0.990221 -0.00872302 +-0.0237143 0.980316 -0.062003 +-0.0272067 0.960511 -0.107086 +-0.0351446 0.896146 -0.209547 +-0.0373676 0.851587 -0.238236 +-0.039274 0.757518 -0.262827 +-0.0408599 0.36143 -0.283319 +-0.0427665 0.267359 -0.307909 +-0.0494349 0.108924 -0.393977 +-0.0553493 -0.049511 -0.470349 +-0.042255 -0.222799 -0.553817 +-0.0459597 -0.376283 -0.602997 +-0.0453402 -0.50006 -0.594801 +-0.0441053 -0.643644 -0.578405 +-0.0404005 -0.782273 -0.529225 +-0.030829 -0.881297 -0.402173 +-0.0218772 -0.950611 -0.283319 +-0.00860095 -0.990221 -0.107086 +-0.000576258 -0.990221 -0.00052619 +-0.0183587 0.990221 -0.00876343 +-0.0183587 0.980316 -0.0621791 +-0.0183587 0.960511 -0.107377 +-0.0183587 0.896146 -0.2101 +-0.0183587 0.851587 -0.238863 +-0.0183587 0.757518 -0.263516 +-0.0183587 0.36143 -0.284061 +-0.0183587 0.267359 -0.308714 +-0.0183587 0.108924 -0.395001 +-0.0183587 -0.049511 -0.471569 +1.19209e-07 -0.222799 -0.555249 +1.19209e-07 -0.376283 -0.604557 +1.19209e-07 -0.50006 -0.596337 +1.19209e-07 -0.643644 -0.579901 +1.19209e-07 -0.782273 -0.530597 +1.19209e-07 -0.881297 -0.403221 +1.19209e-07 -0.950611 -0.284061 +1.19209e-07 -0.990221 -0.107377 +1.19209e-07 -0.990221 -0.000545859 +-0.0171325 0.990221 -0.00872302 +-0.0130031 0.980316 -0.062003 +-0.00951076 0.960511 -0.107086 +-0.00157285 0.896146 -0.209547 +0.000650048 0.851587 -0.238236 +0.00255656 0.757518 -0.262827 +0.0041424 0.36143 -0.283319 +0.00604892 0.267359 -0.307909 +0.0127172 0.108924 -0.393977 +0.0186319 -0.049511 -0.470349 +0.0422552 -0.222799 -0.553817 +0.0459599 -0.376283 -0.602997 +0.0453403 -0.50006 -0.594801 +0.0441053 -0.643644 -0.578405 +0.0404007 -0.782273 -0.529225 +0.0308335 -0.881297 -0.402173 +0.0218773 -0.950611 -0.283319 +0.00860536 -0.990221 -0.107086 +0.000576258 -0.990221 -0.00052619 +-0.0159106 0.990221 -0.00860178 +-0.00767803 0.980316 -0.061474 +-0.000710487 0.960511 -0.106212 +0.0151265 0.896146 -0.207889 +0.019559 0.851587 -0.236359 +0.0233634 0.757518 -0.260761 +0.026531 0.36143 -0.281097 +0.0303309 0.267359 -0.305499 +0.043633 0.108924 -0.390909 +0.0554361 -0.049511 -0.466697 +0.0842936 -0.222799 -0.549525 +0.0916858 -0.376283 -0.598329 +0.0904508 -0.50006 -0.590197 +0.0879898 -0.643644 -0.573929 +0.0805976 -0.782273 -0.525121 +0.0615065 -0.881297 -0.399041 +0.0436461 -0.950611 -0.281097 +0.017163 -0.990221 -0.106212 +0.00114834 -0.990221 -0.000467777 +-0.0147016 0.990221 -0.00840056 +-0.00240469 0.980316 -0.0605961 +0.00800312 0.960511 -0.104761 +0.0316567 0.896146 -0.205136 +0.0382776 0.851587 -0.233241 +0.0439579 0.757518 -0.257331 +0.0486853 0.36143 -0.277407 +0.0543616 0.267359 -0.301497 +0.0742326 0.108924 -0.385813 +0.0918634 -0.049511 -0.460629 +0.125903 -0.222799 -0.542397 +0.136944 -0.376283 -0.590577 +0.135102 -0.50006 -0.582549 +0.131423 -0.643644 -0.566489 +0.120383 -0.782273 -0.518309 +0.0918677 -0.881297 -0.393841 +0.0651896 -0.950611 -0.277407 +0.0256341 -0.990221 -0.104761 +0.0017159 -0.990221 -0.000370622 +-0.0135145 0.990221 -0.00812018 +0.00279045 0.980316 -0.0593729 +0.0165825 0.960511 -0.10274 +0.0479314 0.896146 -0.201301 +0.05671 0.851587 -0.228899 +0.0642321 0.757518 -0.252554 +0.0705018 0.36143 -0.272266 +0.0780282 0.267359 -0.295921 +0.10436 0.108924 -0.378713 +0.127728 -0.049511 -0.452181 +0.166871 -0.222799 -0.532469 +0.181499 -0.376283 -0.579777 +0.179065 -0.50006 -0.571893 +0.174186 -0.643644 -0.556125 +0.159553 -0.782273 -0.508813 +0.121761 -0.881297 -0.386597 +0.0863996 -0.950611 -0.272266 +0.0339749 -0.990221 -0.10274 +0.00227487 -0.990221 -0.000235438 +-0.0123489 0.990221 -0.00776219 +0.00787306 0.980316 -0.0578099 +0.0249841 0.960511 -0.100159 +0.063868 0.896146 -0.196405 +0.0747569 0.851587 -0.223354 +0.08409 0.757518 -0.246453 +0.0918677 0.36143 -0.265702 +0.101201 0.267359 -0.288801 +0.133863 0.108924 -0.369649 +0.16285 -0.049511 -0.441389 +0.206986 -0.222799 -0.519793 +0.225137 -0.376283 -0.565989 +0.222112 -0.50006 -0.558289 +0.216064 -0.643644 -0.542889 +0.197913 -0.782273 -0.496693 +0.15103 -0.881297 -0.377349 +0.107172 -0.950611 -0.265702 +0.0421426 -0.990221 -0.100159 +0.00282085 -0.990221 -6.25849e-05 +-0.0112137 0.990221 -0.00732863 +0.0128213 0.980316 -0.0559169 +0.0331602 0.960511 -0.0970311 +0.0793889 0.896146 -0.190471 +0.0923314 0.851587 -0.216634 +0.103424 0.757518 -0.23906 +0.11267 0.36143 -0.257748 +0.123763 0.267359 -0.280173 +0.162591 0.108924 -0.358661 +0.197046 -0.049511 -0.428313 +0.246052 -0.222799 -0.504429 +0.267622 -0.376283 -0.549281 +0.26403 -0.50006 -0.541805 +0.256837 -0.643644 -0.526853 +0.235263 -0.782273 -0.482005 +0.179533 -0.881297 -0.366137 +0.127398 -0.950611 -0.257748 +0.0500937 -0.990221 -0.0970311 +0.00335383 -0.990221 0.000146627 +-0.0101175 0.990221 -0.00682104 +0.0176135 0.980316 -0.053703 +0.041081 0.960511 -0.0933729 +0.0944068 0.896146 -0.18353 +0.109338 0.851587 -0.208774 +0.122138 0.757518 -0.230412 +0.132801 0.36143 -0.248444 +0.145601 0.267359 -0.270081 +0.190399 0.108924 -0.345813 +0.230146 -0.049511 -0.413017 +0.283857 -0.222799 -0.486461 +0.308746 -0.376283 -0.529737 +0.304599 -0.50006 -0.522521 +0.296302 -0.643644 -0.508097 +0.271413 -0.782273 -0.464821 +0.20712 -0.881297 -0.353025 +0.146975 -0.950611 -0.248444 +0.0577931 -0.990221 -0.0933729 +0.00386941 -0.990221 0.000391364 +-0.00906026 0.990221 -0.00624263 +0.0222237 0.980316 -0.0511791 +0.0486939 0.960511 -0.089202 +0.108853 0.896146 -0.175618 +0.125695 0.851587 -0.199815 +0.140137 0.757518 -0.220554 +0.152165 0.36143 -0.237837 +0.166607 0.267359 -0.258577 +0.217138 0.108924 -0.331167 +0.26198 -0.049511 -0.395581 +0.32022 -0.222799 -0.465977 +0.348297 -0.376283 -0.507457 +0.343618 -0.50006 -0.500541 +0.334259 -0.643644 -0.486717 +0.306185 -0.782273 -0.445237 +0.233651 -0.881297 -0.33808 +0.165801 -0.950611 -0.237837 +0.0651939 -0.990221 -0.089202 +0.00436342 -0.990221 0.000670552 +-0.00805056 0.990221 -0.00559616 +0.0266263 0.980316 -0.048358 +0.0559647 0.960511 -0.0845409 +0.122649 0.896146 -0.166775 +0.14132 0.851587 -0.1898 +0.157326 0.757518 -0.209536 +0.170663 0.36143 -0.225983 +0.186664 0.267359 -0.245719 +0.242681 0.108924 -0.314796 +0.292385 -0.049511 -0.376093 +0.354953 -0.222799 -0.443081 +0.386072 -0.376283 -0.482553 +0.380886 -0.50006 -0.475973 +0.370512 -0.643644 -0.462817 +0.339393 -0.782273 -0.423345 +0.258995 -0.881297 -0.321374 +0.183783 -0.950611 -0.225983 +0.0722654 -0.990221 -0.0845409 +0.00483561 -0.990221 0.000982642 +-0.00709295 0.990221 -0.00488496 +0.0307989 0.980316 -0.0452541 +0.0628586 0.960511 -0.0794121 +0.135731 0.896146 -0.157045 +0.15613 0.851587 -0.178782 +0.173618 0.757518 -0.197414 +0.188194 0.36143 -0.212941 +0.205682 0.267359 -0.231573 +0.266894 0.108924 -0.296784 +0.321208 -0.049511 -0.354649 +0.387875 -0.222799 -0.417889 +0.42188 -0.376283 -0.455153 +0.416212 -0.50006 -0.448945 +0.404877 -0.643644 -0.436521 +0.370868 -0.782273 -0.399261 +0.283017 -0.881297 -0.302995 +0.200829 -0.950611 -0.212941 +0.0789685 -0.990221 -0.0794131 +0.00528622 -0.990221 0.00132585 +-0.00619602 0.990221 -0.0041126 +0.0347202 0.980316 -0.0418831 +0.0693405 0.960511 -0.073843 +0.148023 0.896146 -0.146479 +0.170052 0.851587 -0.166817 +0.188935 0.757518 -0.18425 +0.204672 0.36143 -0.198777 +0.223556 0.267359 -0.21621 +0.28965 0.108924 -0.277224 +0.348297 -0.049511 -0.331365 +0.418821 -0.222799 -0.390537 +0.455538 -0.376283 -0.425401 +0.44942 -0.50006 -0.419589 +0.43718 -0.643644 -0.407969 +0.400458 -0.782273 -0.373105 +0.305596 -0.881297 -0.283035 +0.216852 -0.950611 -0.198777 +0.0852687 -0.990221 -0.073843 +0.00570655 -0.990221 0.00169861 +-0.00535989 0.990221 -0.00328302 +0.0383685 0.980316 -0.0382626 +0.075372 0.960511 -0.067861 +0.159467 0.896146 -0.13513 +0.183012 0.851587 -0.153966 +0.203195 0.757518 -0.17011 +0.220016 0.36143 -0.183564 +0.240198 0.267359 -0.199709 +0.310839 0.108924 -0.256215 +0.37352 -0.049511 -0.306356 +0.447631 -0.222799 -0.361153 +0.486879 -0.376283 -0.393445 +0.480336 -0.50006 -0.388061 +0.467255 -0.643644 -0.377301 +0.428007 -0.782273 -0.345009 +0.326619 -0.881297 -0.261597 +0.231771 -0.950611 -0.183564 +0.0911355 -0.990221 -0.067861 +0.00610089 -0.990221 0.00209856 +-0.00458848 0.990221 -0.00240016 +0.0417309 0.980316 -0.034411 +0.0809269 0.960511 -0.0614971 +0.170009 0.896146 -0.123057 +0.194949 0.851587 -0.140293 +0.216328 0.757518 -0.155068 +0.234145 0.36143 -0.16738 +0.255524 0.267359 -0.182154 +0.33035 0.108924 -0.233864 +0.396749 -0.049511 -0.279749 +0.474161 -0.222799 -0.329897 +0.515732 -0.376283 -0.359445 +0.508804 -0.50006 -0.354521 +0.494947 -0.643644 -0.344673 +0.453372 -0.782273 -0.315122 +0.345975 -0.881297 -0.238789 +0.245506 -0.950611 -0.167379 +0.0965343 -0.990221 -0.0614971 +0.00646055 -0.990221 0.00252461 +-0.0038867 0.990221 -0.00146902 +0.04479 0.980316 -0.0303477 +0.0859749 0.960511 -0.0547841 +0.179584 0.896146 -0.11032 +0.205795 0.851587 -0.12587 +0.228265 0.757518 -0.139199 +0.246984 0.36143 -0.150306 +0.26945 0.267359 -0.163635 +0.348085 0.108924 -0.210285 +0.417859 -0.049511 -0.251681 +0.498275 -0.222799 -0.296921 +0.54196 -0.376283 -0.323579 +0.53468 -0.50006 -0.319136 +0.520117 -0.643644 -0.31025 +0.476432 -0.782273 -0.283593 +0.363571 -0.881297 -0.214728 +0.257994 -0.950611 -0.150306 +0.101448 -0.990221 -0.0547841 +0.00678992 -0.990221 0.00297379 +-0.00326276 0.990221 -0.000494242 +0.047524 0.980316 -0.0260938 +0.0904942 0.960511 -0.047755 +0.188155 0.896146 -0.0969851 +0.2155 0.851587 -0.110769 +0.238942 0.757518 -0.122584 +0.258475 0.36143 -0.13243 +0.281912 0.267359 -0.144245 +0.363948 0.108924 -0.185598 +0.436746 -0.049511 -0.222293 +0.519848 -0.222799 -0.262397 +0.565427 -0.376283 -0.286027 +0.557831 -0.50006 -0.282089 +0.54264 -0.643644 -0.274212 +0.497057 -0.782273 -0.250582 +0.379313 -0.881297 -0.189537 +0.269164 -0.950611 -0.13243 +0.105837 -0.990221 -0.047755 +0.00708437 -0.990221 0.00344419 +-0.00271225 0.990221 0.000519395 +0.0499201 0.980316 -0.0216701 +0.0944588 0.960511 -0.040446 +0.195677 0.896146 -0.0831191 +0.224015 0.851587 -0.0950669 +0.24831 0.757518 -0.105309 +0.268553 0.36143 -0.113843 +0.292844 0.267359 -0.124085 +0.37787 0.108924 -0.159929 +0.453315 -0.049511 -0.191737 +0.538775 -0.222799 -0.226499 +0.586013 -0.376283 -0.246982 +0.57814 -0.50006 -0.243568 +0.562394 -0.643644 -0.23674 +0.515156 -0.782273 -0.216257 +0.393122 -0.881297 -0.163343 +0.278961 -0.950611 -0.113843 +0.109689 -0.990221 -0.040446 +0.00734019 -0.990221 0.00393343 +-0.00224435 0.990221 0.00156665 +0.0519698 0.980316 -0.0171002 +0.0978472 0.960511 -0.0328954 +0.202103 0.896146 -0.0687931 +0.231294 0.851587 -0.0788449 +0.256317 0.757518 -0.08746 +0.277167 0.36143 -0.09464 +0.30219 0.267359 -0.103255 +0.389768 0.108924 -0.133409 +0.46748 -0.049511 -0.160167 +0.554954 -0.222799 -0.18941 +0.603613 -0.376283 -0.206641 +0.595502 -0.50006 -0.203769 +0.579284 -0.643644 -0.198026 +0.530624 -0.782273 -0.180795 +0.404929 -0.881297 -0.136281 +0.287341 -0.950611 -0.09464 +0.112987 -0.990221 -0.0328954 +0.00756109 -0.990221 0.00443864 +-0.00185442 0.990221 0.00264215 +0.053664 0.980316 -0.0124067 +0.100642 0.960511 -0.0251406 +0.207406 0.896146 -0.054081 +0.237304 0.851587 -0.0621841 +0.262925 0.757518 -0.0691299 +0.284278 0.36143 -0.074918 +0.309903 0.267359 -0.081863 +0.399587 0.108924 -0.106173 +0.47917 -0.049511 -0.127745 +0.568308 -0.222799 -0.151321 +0.618133 -0.376283 -0.165212 +0.609831 -0.50006 -0.162897 +0.593219 -0.643644 -0.158266 +0.543394 -0.782273 -0.144375 +0.41467 -0.881297 -0.108489 +0.294252 -0.950611 -0.074918 +0.115703 -0.990221 -0.0251406 +0.007743 -0.990221 0.0049578 +-0.00155115 0.990221 0.00374055 +0.0549898 0.980316 -0.00761378 +0.10283 0.960511 -0.0172215 +0.211562 0.896146 -0.0390567 +0.242005 0.851587 -0.0451709 +0.268103 0.757518 -0.0504111 +0.28985 0.36143 -0.0547781 +0.315943 0.267359 -0.060019 +0.407278 0.108924 -0.07836 +0.488322 -0.049511 -0.0946359 +0.578764 -0.222799 -0.112423 +0.629507 -0.376283 -0.122904 +0.621049 -0.50006 -0.121157 +0.604133 -0.643644 -0.117664 +0.55339 -0.782273 -0.107183 +0.4223 -0.881297 -0.0801071 +0.299668 -0.950611 -0.0547781 +0.117831 -0.990221 -0.0172211 +0.00788617 -0.990221 0.00548744 +-0.00133443 0.990221 0.00485623 +0.0559387 0.980316 -0.00274575 +0.104403 0.960511 -0.0091778 +0.214543 0.896146 -0.023797 +0.245385 0.851587 -0.0278902 +0.271816 0.757518 -0.031399 +0.293845 0.36143 -0.0343225 +0.32028 0.267359 -0.0378313 +0.412798 0.108924 -0.0501111 +0.494895 -0.049511 -0.0610081 +0.586268 -0.222799 -0.0729171 +0.637675 -0.376283 -0.079934 +0.629104 -0.50006 -0.078764 +0.611972 -0.643644 -0.076425 +0.56057 -0.782273 -0.0694081 +0.427777 -0.881297 -0.0512811 +0.303555 -0.950611 -0.0343225 +0.11936 -0.990221 -0.0091778 +0.00799012 -0.990221 0.00602579 +-0.0012002 0.990221 0.00598335 +0.056515 0.980316 0.00217259 +0.105348 0.960511 -0.00105178 +0.216341 0.896146 -0.00837982 +0.247417 0.851587 -0.0104318 +0.274056 0.757518 -0.0121907 +0.296254 0.36143 -0.0136563 +0.322889 0.267359 -0.015415 +0.416121 0.108924 -0.0215706 +0.498851 -0.049511 -0.0270331 +0.590788 -0.222799 -0.0330026 +0.642588 -0.376283 -0.0365202 +0.633957 -0.50006 -0.0359339 +0.61669 -0.643644 -0.0347614 +0.56489 -0.782273 -0.0312438 +0.431074 -0.881297 -0.022157 +0.305895 -0.950611 -0.0136563 +0.120283 -0.990221 -0.00105178 +0.00805068 -0.990221 0.00656974 +-0.00115681 0.990221 0.0071162 +0.0567057 0.980316 0.0071162 +0.105664 0.960511 0.0071162 +0.216939 0.896146 0.0071162 +0.248097 0.851587 0.0071162 +0.274801 0.757518 0.0071162 +0.297056 0.36143 0.0071162 +0.323764 0.267359 0.0071162 +0.417231 0.108924 0.0071162 +0.500172 -0.049511 0.0071162 +0.5923 -0.222799 0.0071162 +0.644231 -0.376283 0.0071162 +0.635573 -0.50006 0.0071162 +0.618263 -0.643644 0.0071162 +0.566332 -0.782273 0.0071162 +0.432179 -0.881297 0.0071162 +0.306675 -0.950611 0.0071162 +0.120587 -0.990221 0.0071162 +0.00807238 -0.990221 0.0071162 +-0.0012002 0.990221 0.00824904 +0.056515 0.980316 0.0120597 +0.105348 0.960511 0.0152843 +0.216341 0.896146 0.0226121 +0.247417 0.851587 0.0246642 +0.274056 0.757518 0.0264231 +0.296254 0.36143 0.0278887 +0.322889 0.267359 0.0296475 +0.416121 0.108924 0.035803 +0.498851 -0.049511 0.0412649 +0.590788 -0.222799 0.0472349 +0.642588 -0.376283 0.0507522 +0.633957 -0.50006 0.0501662 +0.61669 -0.643644 0.0489937 +0.56489 -0.782273 0.0454762 +0.431074 -0.881297 0.036389 +0.305895 -0.950611 0.0278887 +0.120283 -0.990221 0.0152843 +0.00805068 -0.990221 0.00766301 +-0.00133443 0.990221 0.00937617 +0.0559387 0.980316 0.0169779 +0.104403 0.960511 0.0234102 +0.214543 0.896146 0.0380294 +0.245385 0.851587 0.0421226 +0.271816 0.757518 0.0456311 +0.293845 0.36143 0.0485549 +0.32028 0.267359 0.0520635 +0.412798 0.108924 0.0643435 +0.494895 -0.049511 0.0752381 +0.586268 -0.222799 0.0871501 +0.637675 -0.376283 0.0941662 +0.629104 -0.50006 0.0929983 +0.611972 -0.643644 0.0906583 +0.56057 -0.782273 0.0836422 +0.427777 -0.881297 0.065513 +0.303555 -0.950611 0.0485549 +0.11936 -0.990221 0.0234102 +0.00799012 -0.990221 0.00820661 +-0.00155115 0.990221 0.0104918 +0.0549898 0.980316 0.0218463 +0.10283 0.960511 0.0314534 +0.211562 0.896146 0.0532891 +0.242005 0.851587 0.0594027 +0.268103 0.757518 0.0646435 +0.28985 0.36143 0.0690103 +0.315943 0.267359 0.0742507 +0.407278 0.108924 0.0925943 +0.488322 -0.049511 0.108866 +0.578764 -0.222799 0.126654 +0.629507 -0.376283 0.137138 +0.621049 -0.50006 0.13539 +0.604133 -0.643644 0.131894 +0.55339 -0.782273 0.121414 +0.4223 -0.881297 0.0943383 +0.299668 -0.950611 0.0690103 +0.117831 -0.990221 0.0314538 +0.00788617 -0.990221 0.00874496 +-0.00185442 0.990221 0.0115902 +0.053664 0.980316 0.0266391 +0.100642 0.960511 0.0393726 +0.207406 0.896146 0.068313 +0.237304 0.851587 0.0764182 +0.262925 0.757518 0.0833621 +0.284278 0.36143 0.0891502 +0.309903 0.267359 0.0960943 +0.399587 0.108924 0.120406 +0.47917 -0.049511 0.141978 +0.568308 -0.222799 0.165554 +0.618133 -0.376283 0.179442 +0.609831 -0.50006 0.17713 +0.593219 -0.643644 0.172498 +0.543394 -0.782273 0.158606 +0.41467 -0.881297 0.122722 +0.294252 -0.950611 0.0891502 +0.115703 -0.990221 0.0393726 +0.007743 -0.990221 0.00927496 +-0.00224435 0.990221 0.0126654 +0.0519698 0.980316 0.0313325 +0.0978472 0.960511 0.0471278 +0.202103 0.896146 0.0830262 +0.231294 0.851587 0.0930783 +0.256317 0.757518 0.101694 +0.277167 0.36143 0.10887 +0.30219 0.267359 0.117486 +0.389768 0.108924 0.147642 +0.46748 -0.049511 0.174398 +0.554954 -0.222799 0.203642 +0.603613 -0.376283 0.220874 +0.595502 -0.50006 0.218002 +0.579284 -0.643644 0.212258 +0.530624 -0.782273 0.195026 +0.404929 -0.881297 0.150514 +0.287341 -0.950611 0.10887 +0.112987 -0.990221 0.0471278 +0.00756109 -0.990221 0.00979376 +-0.00271225 0.990221 0.013713 +0.0499201 0.980316 0.0359025 +0.0944588 0.960511 0.0546787 +0.195677 0.896146 0.0973502 +0.224015 0.851587 0.109298 +0.24831 0.757518 0.119542 +0.268553 0.36143 0.128074 +0.292844 0.267359 0.138318 +0.37787 0.108924 0.174162 +0.453315 -0.049511 0.20597 +0.538775 -0.222799 0.24073 +0.586013 -0.376283 0.261214 +0.57814 -0.50006 0.257798 +0.562394 -0.643644 0.250974 +0.515156 -0.782273 0.23049 +0.393122 -0.881297 0.177574 +0.278961 -0.950611 0.128074 +0.109694 -0.990221 0.0546787 +0.00734019 -0.990221 0.010299 +-0.00326276 0.990221 0.0147266 +0.047524 0.980316 0.0403262 +0.0904942 0.960511 0.061987 +0.188155 0.896146 0.111218 +0.2155 0.851587 0.125002 +0.238942 0.757518 0.136818 +0.258475 0.36143 0.146662 +0.281912 0.267359 0.158478 +0.363948 0.108924 0.19983 +0.436746 -0.049511 0.236526 +0.519848 -0.222799 0.27663 +0.565427 -0.376283 0.300258 +0.557831 -0.50006 0.296322 +0.54264 -0.643644 0.288446 +0.497061 -0.782273 0.264814 +0.379313 -0.881297 0.20377 +0.269164 -0.950611 0.146662 +0.105837 -0.990221 0.061987 +0.00708437 -0.990221 0.0107882 +-0.0038867 0.990221 0.0157013 +0.04479 0.980316 0.0445801 +0.0859749 0.960511 0.0690162 +0.179584 0.896146 0.124554 +0.205795 0.851587 0.140102 +0.228265 0.757518 0.15343 +0.246984 0.36143 0.164538 +0.26945 0.267359 0.177866 +0.348085 0.108924 0.224518 +0.417859 -0.049511 0.265914 +0.498275 -0.222799 0.311154 +0.54196 -0.376283 0.33781 +0.53468 -0.50006 0.33337 +0.520117 -0.643644 0.324482 +0.476432 -0.782273 0.297826 +0.363571 -0.881297 0.228962 +0.257994 -0.950611 0.164538 +0.101448 -0.990221 0.0690162 +0.00678992 -0.990221 0.0112586 +-0.00458848 0.990221 0.0166326 +0.0417309 0.980316 0.0486435 +0.0809269 0.960511 0.0757302 +0.170009 0.896146 0.13729 +0.194949 0.851587 0.154526 +0.216328 0.757518 0.169298 +0.234145 0.36143 0.18161 +0.255524 0.267359 0.196386 +0.33035 0.108924 0.248098 +0.396749 -0.049511 0.293982 +0.474161 -0.222799 0.34413 +0.515732 -0.376283 0.373678 +0.508804 -0.50006 0.368754 +0.494947 -0.643644 0.358902 +0.453372 -0.782273 0.329354 +0.345975 -0.881297 0.253022 +0.245506 -0.950611 0.18161 +0.0965343 -0.990221 0.0757302 +0.00646055 -0.990221 0.0117079 +-0.00535989 0.990221 0.0175153 +0.0383685 0.980316 0.0524955 +0.075372 0.960511 0.0820942 +0.159467 0.896146 0.149362 +0.183016 0.851587 0.168198 +0.203195 0.757518 0.184342 +0.220016 0.36143 0.197798 +0.240198 0.267359 0.213942 +0.310839 0.108924 0.270446 +0.37352 -0.049511 0.32059 +0.447631 -0.222799 0.375386 +0.486879 -0.376283 0.407678 +0.480336 -0.50006 0.402294 +0.467255 -0.643644 0.39153 +0.428007 -0.782273 0.359242 +0.326619 -0.881297 0.27583 +0.231771 -0.950611 0.197798 +0.0911355 -0.990221 0.0820942 +0.00610089 -0.990221 0.0121338 +-0.00619602 0.990221 0.018345 +0.0347202 0.980316 0.0561154 +0.0693405 0.960511 0.0880742 +0.148023 0.896146 0.16071 +0.170052 0.851587 0.18105 +0.188935 0.757518 0.198482 +0.204672 0.36143 0.21301 +0.223556 0.267359 0.230442 +0.28965 0.108924 0.291458 +0.348297 -0.049511 0.345598 +0.418821 -0.222799 0.40477 +0.455538 -0.376283 0.439634 +0.44942 -0.50006 0.433822 +0.43718 -0.643644 0.422202 +0.400458 -0.782273 0.387334 +0.305596 -0.881297 0.297266 +0.216852 -0.950611 0.21301 +0.0852687 -0.990221 0.0880742 +0.00570655 -0.990221 0.0125339 +-0.00709295 0.990221 0.0191174 +0.0307989 0.980316 0.0594863 +0.0628586 0.960511 0.0936462 +0.135731 0.896146 0.171278 +0.15613 0.851587 0.193014 +0.173622 0.757518 0.211646 +0.188194 0.36143 0.227174 +0.205682 0.267359 0.245806 +0.266894 0.108924 0.311018 +0.321208 -0.049511 0.368882 +0.387875 -0.222799 0.432122 +0.42188 -0.376283 0.469387 +0.416212 -0.50006 0.463179 +0.404877 -0.643644 0.450754 +0.370868 -0.782273 0.41349 +0.283017 -0.881297 0.317226 +0.200829 -0.950611 0.227174 +0.0789685 -0.990221 0.0936462 +0.00528622 -0.990221 0.0129069 +-0.00805056 0.990221 0.0198286 +0.0266263 0.980316 0.0625902 +0.0559647 0.960511 0.0987742 +0.122649 0.896146 0.181006 +0.14132 0.851587 0.204034 +0.157326 0.757518 0.22377 +0.170663 0.36143 0.240214 +0.186664 0.267359 0.25995 +0.242681 0.108924 0.329026 +0.292385 -0.049511 0.390322 +0.354953 -0.222799 0.457314 +0.386072 -0.376283 0.496787 +0.380886 -0.50006 0.490207 +0.370512 -0.643644 0.477051 +0.339393 -0.782273 0.437578 +0.258995 -0.881297 0.335606 +0.183783 -0.950611 0.240214 +0.0722654 -0.990221 0.0987742 +0.00483561 -0.990221 0.0132498 +-0.00906026 0.990221 0.0204749 +0.0222237 0.980316 0.0654114 +0.0486939 0.960511 0.103434 +0.108853 0.896146 0.18985 +0.125695 0.851587 0.214046 +0.140137 0.757518 0.234786 +0.152165 0.36143 0.25207 +0.166607 0.267359 0.27281 +0.217138 0.108924 0.345398 +0.26198 -0.049511 0.40981 +0.32022 -0.222799 0.480207 +0.348297 -0.376283 0.521687 +0.343618 -0.50006 0.514775 +0.334259 -0.643644 0.500947 +0.306185 -0.782273 0.459466 +0.233651 -0.881297 0.352314 +0.165801 -0.950611 0.25207 +0.0651939 -0.990221 0.103434 +0.00436342 -0.990221 0.0135618 +-0.0101175 0.990221 0.0210534 +0.0176135 0.980316 0.0679355 +0.041081 0.960511 0.107606 +0.0944068 0.896146 0.197762 +0.109338 0.851587 0.223006 +0.122138 0.757518 0.244646 +0.132801 0.36143 0.262674 +0.145601 0.267359 0.284314 +0.190399 0.108924 0.360046 +0.230146 -0.049511 0.42725 +0.283857 -0.222799 0.500695 +0.308746 -0.376283 0.543967 +0.304599 -0.50006 0.536755 +0.296302 -0.643644 0.522331 +0.271413 -0.782273 0.479055 +0.20712 -0.881297 0.367258 +0.146975 -0.950611 0.262678 +0.0577931 -0.990221 0.107606 +0.00386941 -0.990221 0.013841 +-0.0112137 0.990221 0.0215609 +0.0128213 0.980316 0.0701499 +0.0331602 0.960511 0.111262 +0.0793889 0.896146 0.204702 +0.0923314 0.851587 0.230866 +0.103424 0.757518 0.25329 +0.11267 0.36143 0.271978 +0.123763 0.267359 0.294406 +0.162591 0.108924 0.372894 +0.197046 -0.049511 0.442542 +0.246052 -0.222799 0.518663 +0.267622 -0.376283 0.563515 +0.26403 -0.50006 0.556039 +0.256837 -0.643644 0.541087 +0.235263 -0.782273 0.496235 +0.179533 -0.881297 0.38037 +0.127398 -0.950611 0.271978 +0.0500937 -0.990221 0.111262 +0.00335383 -0.990221 0.0140858 +-0.0123489 0.990221 0.0219946 +0.00787306 0.980316 0.0720427 +0.0249841 0.960511 0.11439 +0.063868 0.896146 0.210638 +0.0747569 0.851587 0.237586 +0.08409 0.757518 0.260686 +0.0918677 0.36143 0.279934 +0.101201 0.267359 0.303034 +0.133863 0.108924 0.383882 +0.16285 -0.049511 0.455622 +0.206986 -0.222799 0.534027 +0.225137 -0.376283 0.580223 +0.222112 -0.50006 0.572523 +0.216064 -0.643644 0.557123 +0.197913 -0.782273 0.510927 +-0.0992163 -0.887389 0.726315 +0.107172 -0.950611 0.279934 +0.0421426 -0.990221 0.11439 +0.00282085 -0.990221 0.0142951 +-0.0135145 0.990221 0.0223527 +0.00279045 0.980316 0.0736051 +0.0165825 0.960511 0.11697 +0.0479314 0.896146 0.215534 +0.05671 0.851587 0.24313 +0.0642321 0.757518 0.266786 +0.0705018 0.36143 0.286498 +0.0780282 0.267359 0.310154 +0.10436 0.108924 0.392946 +0.127728 -0.049511 0.466411 +0.166871 -0.222799 0.546703 +0.181499 -0.376283 0.594011 +0.179065 -0.50006 0.586127 +0.174186 -0.643644 0.570359 +0.0863996 -0.950611 0.286498 +0.0339749 -0.990221 0.11697 +0.00227487 -0.990221 0.0144678 +-0.0147016 0.990221 0.0226332 +-0.00240469 0.980316 0.0748303 +0.00800312 0.960511 0.118994 +0.0316567 0.896146 0.21937 +0.0382819 0.851587 0.247474 +0.0439579 0.757518 0.271562 +0.0486853 0.36143 0.291638 +0.0543659 0.267359 0.31573 +0.0742326 0.108924 0.400046 +0.0918634 -0.049511 0.474863 +0.125903 -0.222799 0.556631 +0.136944 -0.376283 0.604811 +0.0651896 -0.950611 0.291638 +0.0256341 -0.990221 0.118994 +0.0017159 -0.990221 0.0146029 +-0.0159106 0.990221 0.0228343 +-0.00767803 0.980316 0.0757062 +-0.000710487 0.960511 0.120446 +0.0151265 0.896146 0.222122 +0.019559 0.851587 0.25059 +0.0233634 0.757518 0.274994 +0.026531 0.36143 0.29533 +0.0303309 0.267359 0.31973 +0.043633 0.108924 0.405142 +0.0554361 -0.049511 0.480931 +0.0842936 -0.222799 0.563759 +0.0916858 -0.376283 0.612563 +0.0436461 -0.950611 0.29533 +0.017163 -0.990221 0.120446 +0.00114834 -0.990221 0.0147003 +-0.0171325 0.990221 0.0229553 +-0.0130031 0.980316 0.0762341 +-0.00951076 0.960511 0.121318 +-0.00157285 0.896146 0.223778 +0.000650048 0.851587 0.25247 +0.00255656 0.757518 0.277058 +0.0041424 0.36143 0.29755 +0.00604892 0.267359 0.322142 +0.0127172 0.108924 0.40821 +0.0186319 -0.049511 0.484583 +0.0422552 -0.222799 0.568051 +0.0459599 -0.376283 0.617231 +0.0218773 -0.950611 0.29755 +0.00860536 -0.990221 0.121318 +0.000576258 -0.990221 0.0147587 +-0.0183587 0.990221 0.0229957 +-0.0183587 0.980316 0.0764103 +-0.0183587 0.960511 0.12161 +-0.0183587 0.896146 0.224334 +-0.0183587 0.851587 0.253094 +-0.0183587 0.757518 0.27775 +-0.0183587 0.36143 0.298294 +-0.0183587 0.267359 0.322946 +-0.0183587 0.108924 0.409234 +-0.0183587 -0.049511 0.485803 +1.19209e-07 -0.222799 0.569483 +1.19209e-07 -0.376283 0.618791 +1.19209e-07 -0.950611 0.298294 +1.19209e-07 -0.990221 0.12161 +1.19209e-07 -0.990221 0.0147781 +-0.0195849 0.990221 0.0229553 +-0.0237143 0.980316 0.0762341 +-0.0272067 0.960511 0.121318 +-0.0351446 0.896146 0.223778 +-0.0373676 0.851587 0.25247 +-0.039274 0.757518 0.277058 +-0.0408599 0.36143 0.29755 +-0.0427665 0.267359 0.322142 +-0.0494349 0.108924 0.40821 +-0.0553493 -0.049511 0.484583 +-0.042255 -0.222799 0.568051 +-0.0459597 -0.376283 0.617231 +-0.0218772 -0.950611 0.29755 +-0.00860095 -0.990221 0.121318 +-0.000576258 -0.990221 0.0147587 +-0.0208069 0.990221 0.0228343 +-0.0290439 0.980316 0.0757062 +-0.0360112 0.960511 0.120446 +-0.0518439 0.896146 0.222122 +-0.0562809 0.851587 0.25059 +-0.060081 0.757518 0.274994 +-0.0632483 0.36143 0.29533 +-0.0670483 0.267359 0.31973 +-0.0803505 0.108924 0.405142 +-0.0921536 -0.049511 0.480931 +-0.0842936 -0.222799 0.563759 +-0.0916813 -0.376283 0.612563 +-0.0436416 -0.950611 0.29533 +-0.0171585 -0.990221 0.120446 +-0.00114822 -0.990221 0.0147003 +-0.0220158 0.990221 0.0226332 +-0.034317 0.980316 0.0748303 +-0.0447205 0.960511 0.118994 +-0.0683743 0.896146 0.21937 +-0.0749993 0.851587 0.247474 +-0.0806755 0.757518 0.271562 +-0.0854072 0.36143 0.291638 +-0.0910833 0.267359 0.31573 +-0.11095 0.108924 0.400046 +-0.128581 -0.049511 0.474863 +-0.125899 -0.222799 0.556631 +-0.136939 -0.376283 0.604811 +-0.0651895 -0.950611 0.291638 +-0.0256337 -0.990221 0.118994 +-0.0017159 -0.990221 0.0146029 +-0.0232074 0.990221 0.0223527 +-0.0395081 0.980316 0.0736051 +-0.0532999 0.960511 0.11697 +-0.0846488 0.896146 0.215534 +-0.0934275 0.851587 0.24313 +-0.100954 0.757518 0.266786 +-0.107224 0.36143 0.286498 +-0.114746 0.267359 0.310154 +-0.141082 0.108924 0.392946 +-0.164445 -0.049511 0.466411 +-0.166867 -0.222799 0.546703 +-0.181499 -0.376283 0.594011 +-0.0863994 -0.950611 0.286498 +-0.0339749 -0.990221 0.11697 +-0.00227475 -0.990221 0.0144678 +-0.0243685 0.990221 0.0219946 +-0.0445905 0.980316 0.0720427 +-0.0617015 0.960511 0.11439 +-0.100586 0.896146 0.210638 +-0.111474 0.851587 0.237586 +-0.120808 0.757518 0.260686 +-0.128585 0.36143 0.279934 +-0.137918 0.267359 0.303034 +-0.170585 0.108924 0.383882 +-0.199568 -0.049511 0.455622 +-0.206986 -0.222799 0.534027 +-0.225132 -0.376283 0.580223 +-0.107172 -0.950611 0.279934 +-0.0421424 -0.990221 0.11439 +-0.00282073 -0.990221 0.0142951 +-0.0255039 0.990221 0.0215609 +-0.0495431 0.980316 0.0701499 +-0.0698821 0.960511 0.111262 +-0.116106 0.896146 0.204702 +-0.129049 0.851587 0.230866 +-0.140141 0.757518 0.25329 +-0.149388 0.36143 0.271978 +-0.16048 0.267359 0.294406 +-0.199312 0.108924 0.372894 +-0.233764 -0.049511 0.442542 +-0.246048 -0.222799 0.518663 +-0.267622 -0.376283 0.563515 +-0.127398 -0.950611 0.271978 +-0.0500934 -0.990221 0.111262 +-0.0033493 -0.990221 0.0140858 +-0.0266043 0.990221 0.0210534 +-0.0543354 0.980316 0.0679355 +-0.0777984 0.960511 0.107606 +-0.131124 0.896146 0.197762 +-0.146056 0.851587 0.223006 +-0.158855 0.757518 0.244646 +-0.169523 0.36143 0.262674 +-0.182318 0.267359 0.284314 +-0.227117 0.108924 0.360046 +-0.266868 -0.049511 0.42725 +-0.283857 -0.222799 0.500695 +-0.308746 -0.376283 0.543967 +-0.304599 -0.50006 0.536755 +-0.296302 -0.643644 0.522331 +-0.271413 -0.782273 0.479055 +-0.146974 -0.950611 0.262678 +-0.0577888 -0.990221 0.107606 +-0.003865 -0.990221 0.013841 +-0.0276573 0.990221 0.0204749 +-0.0589414 0.980316 0.0654114 +-0.0854115 0.960511 0.103434 +-0.14557 0.896146 0.18985 +-0.162417 0.851587 0.214046 +-0.176854 0.757518 0.234786 +-0.188887 0.36143 0.25207 +-0.203325 0.267359 0.27281 +-0.253856 0.108924 0.345398 +-0.298698 -0.049511 0.409814 +-0.32022 -0.222799 0.480207 +-0.348297 -0.376283 0.521687 +-0.343618 -0.50006 0.514775 +-0.334258 -0.643644 0.500947 +-0.306181 -0.782273 0.45947 +-0.165801 -0.950611 0.25207 +-0.0651938 -0.990221 0.103434 +-0.0043633 -0.990221 0.0135618 +-0.0286669 0.990221 0.0198286 +-0.0633436 0.980316 0.0625902 +-0.0926822 0.960511 0.0987742 +-0.159367 0.896146 0.181006 +-0.178042 0.851587 0.204034 +-0.194043 0.757518 0.22377 +-0.20738 0.36143 0.240214 +-0.223386 0.267359 0.25995 +-0.279399 0.108924 0.329026 +-0.329102 -0.049511 0.390322 +-0.354948 -0.222799 0.457314 +-0.386072 -0.376283 0.496787 +-0.380885 -0.50006 0.490207 +-0.370512 -0.643644 0.477051 +-0.339389 -0.782273 0.437578 +-0.183783 -0.950611 0.240214 +-0.0722652 -0.990221 0.0987742 +-0.00483561 -0.990221 0.0132498 +-0.0296245 0.990221 0.0191174 +-0.0675163 0.980316 0.0594863 +-0.0995759 0.960511 0.0936462 +-0.172448 0.896146 0.171278 +-0.192852 0.851587 0.193014 +-0.21034 0.757518 0.211646 +-0.224912 0.36143 0.227174 +-0.242399 0.267359 0.245806 +-0.303611 0.108924 0.311018 +-0.357925 -0.049511 0.368882 +-0.38787 -0.222799 0.432122 +-0.42188 -0.376283 0.469387 +-0.416212 -0.50006 0.463179 +-0.404877 -0.643644 0.450754 +-0.370868 -0.782273 0.41349 +-0.283012 -0.881297 0.317226 +-0.200829 -0.950611 0.227174 +-0.0789683 -0.990221 0.0936462 +-0.00528181 -0.990221 0.0129069 +-0.0305214 0.990221 0.018345 +-0.0714377 0.980316 0.0561159 +-0.106058 0.960511 0.0880742 +-0.18474 0.896146 0.16071 +-0.206769 0.851587 0.18105 +-0.225657 0.757518 0.198482 +-0.24139 0.36143 0.21301 +-0.260277 0.267359 0.230442 +-0.326368 0.108924 0.291458 +-0.385019 -0.049511 0.345598 +-0.418816 -0.222799 0.40477 +-0.455538 -0.376283 0.439634 +-0.449416 -0.50006 0.433822 +-0.437179 -0.643644 0.422202 +-0.400458 -0.782273 0.387334 +-0.305596 -0.881297 0.297266 +-0.216852 -0.950611 0.21301 +-0.0852685 -0.990221 0.0880742 +-0.00570643 -0.990221 0.0125341 +-0.0313578 0.990221 0.0175153 +-0.0750903 0.980316 0.0524955 +-0.11209 0.960511 0.0820942 +-0.196184 0.896146 0.149362 +-0.219734 0.851587 0.168198 +-0.239917 0.757518 0.184342 +-0.256733 0.36143 0.197798 +-0.276916 0.267359 0.213942 +-0.347556 0.108924 0.270446 +-0.410241 -0.049511 0.32059 +-0.447626 -0.222799 0.375386 +-0.486874 -0.376283 0.407678 +-0.480336 -0.50006 0.402294 +-0.46725 -0.643644 0.39153 +-0.428002 -0.782273 0.359242 +-0.326615 -0.881297 0.27583 +-0.231771 -0.950611 0.197798 +-0.0911353 -0.990221 0.0820942 +-0.00609636 -0.990221 0.0121338 +-0.0321288 0.990221 0.0166326 +-0.0784528 0.980316 0.0486437 +-0.117644 0.960511 0.0757302 +-0.206726 0.896146 0.13729 +-0.231667 0.851587 0.154526 +-0.253046 0.757518 0.169302 +-0.270863 0.36143 0.181614 +-0.292242 0.267359 0.196386 +-0.367068 0.108924 0.248098 +-0.433466 -0.049511 0.293982 +-0.474157 -0.222799 0.34413 +-0.515732 -0.376283 0.373678 +-0.508803 -0.50006 0.368754 +-0.494947 -0.643644 0.358902 +-0.453372 -0.782273 0.329354 +-0.345975 -0.881297 0.253022 +-0.245506 -0.950611 0.181614 +-0.0965342 -0.990221 0.0757302 +-0.00646043 -0.990221 0.0117079 +-0.0328308 0.990221 0.0157013 +-0.0815075 0.980316 0.0445801 +-0.122697 0.960511 0.0690162 +-0.216306 0.896146 0.124554 +-0.242516 0.851587 0.140102 +-0.264983 0.757518 0.15343 +-0.283706 0.36143 0.164538 +-0.306168 0.267359 0.177866 +-0.384803 0.108924 0.224518 +-0.454576 -0.049511 0.265914 +-0.49827 -0.222799 0.311154 +-0.541959 -0.376283 0.33781 +-0.53468 -0.50006 0.33337 +-0.520117 -0.643644 0.324482 +-0.476427 -0.782273 0.297826 +-0.363571 -0.881297 0.228962 +-0.257989 -0.950611 0.164538 +-0.101443 -0.990221 0.0690162 +-0.00678968 -0.990221 0.0112586 +-0.0334549 0.990221 0.0147266 +-0.0842416 0.980316 0.0403262 +-0.127212 0.960511 0.0619874 +-0.224877 0.896146 0.111218 +-0.252222 0.851587 0.125002 +-0.275659 0.757518 0.136818 +-0.295192 0.36143 0.146662 +-0.318634 0.267359 0.158478 +-0.40067 0.108924 0.19983 +-0.473464 -0.049511 0.236526 +-0.519848 -0.222799 0.27663 +-0.565427 -0.376283 0.300258 +-0.557831 -0.50006 0.296322 +-0.542635 -0.643644 0.288446 +-0.497057 -0.782273 0.264814 +-0.379313 -0.881297 0.20377 +-0.26916 -0.950611 0.146662 +-0.105837 -0.990221 0.0619874 +-0.00707996 -0.990221 0.0107882 +-0.034005 0.990221 0.013713 +-0.0866421 0.980316 0.0359025 +-0.131176 0.960511 0.0546787 +-0.232395 0.896146 0.0973502 +-0.260737 0.851587 0.109298 +-0.285027 0.757518 0.119542 +-0.305271 0.36143 0.128074 +-0.329566 0.267359 0.138318 +-0.414587 0.108924 0.174162 +-0.490033 -0.049511 0.20597 +-0.53877 -0.222799 0.24073 +-0.586013 -0.376283 0.261214 +-0.57814 -0.50006 0.257802 +-0.562389 -0.643644 0.250974 +-0.515151 -0.782273 0.23049 +-0.393122 -0.881297 0.177574 +-0.278961 -0.950611 0.128074 +-0.109689 -0.990221 0.0546787 +-0.00733995 -0.990221 0.0102994 +-0.0344775 0.990221 0.0126657 +-0.0886915 0.980316 0.0313325 +-0.134565 0.960511 0.0471278 +-0.23882 0.896146 0.0830262 +-0.268016 0.851587 0.0930783 +-0.293034 0.757518 0.101694 +-0.313889 0.36143 0.108874 +-0.338908 0.267359 0.117486 +-0.426486 0.108924 0.147642 +-0.504198 -0.049511 0.174398 +-0.554954 -0.222799 0.203642 +-0.603609 -0.376283 0.220874 +-0.595502 -0.50006 0.218002 +-0.579279 -0.643644 0.212258 +-0.530624 -0.782273 0.195026 +-0.404925 -0.881297 0.150514 +-0.287337 -0.950611 0.108874 +-0.112982 -0.990221 0.0471278 +-0.00756097 -0.990221 0.00979376 +-0.034863 0.990221 0.0115902 +-0.0903814 0.980316 0.0266391 +-0.137359 0.960511 0.039373 +-0.244128 0.896146 0.0683135 +-0.274021 0.851587 0.0764182 +-0.299647 0.757518 0.0833621 +-0.321 0.36143 0.0891502 +-0.34662 0.267359 0.0960943 +-0.436304 0.108924 0.120406 +-0.515888 -0.049511 0.141978 +-0.568304 -0.222799 0.165554 +-0.618133 -0.376283 0.179446 +-0.609827 -0.50006 0.17713 +-0.593218 -0.643644 0.172498 +-0.543389 -0.782273 0.158606 +-0.41467 -0.881297 0.122722 +-0.294252 -0.950611 0.0891502 +-0.115703 -0.990221 0.039373 +-0.00774288 -0.990221 0.00927496 +-0.0351663 0.990221 0.0104918 +-0.0917073 0.980316 0.0218463 +-0.139548 0.960511 0.0314538 +-0.248279 0.896146 0.0532891 +-0.278727 0.851587 0.0594031 +-0.30482 0.757518 0.0646435 +-0.326567 0.36143 0.0690106 +-0.35266 0.267359 0.0742511 +-0.443995 0.108924 0.0925943 +-0.525043 -0.049511 0.10887 +-0.578759 -0.222799 0.126654 +-0.629507 -0.376283 0.137138 +-0.621049 -0.50006 0.13539 +-0.604133 -0.643644 0.131898 +-0.55339 -0.782273 0.121414 +-0.4223 -0.881297 0.0943383 +-0.299664 -0.950611 0.0690106 +-0.117831 -0.990221 0.0314538 +-0.00788593 -0.990221 0.00874496 +-0.0353873 0.990221 0.00937617 +-0.0926605 0.980316 0.0169781 +-0.14112 0.960511 0.0234108 +-0.251265 0.896146 0.0380294 +-0.282102 0.851587 0.0421226 +-0.308538 0.757518 0.0456313 +-0.330562 0.36143 0.0485549 +-0.356998 0.267359 0.0520638 +-0.449515 0.108924 0.0643435 +-0.531612 -0.049511 0.0752422 +-0.586268 -0.222799 0.0871501 +-0.63767 -0.376283 0.0941662 +-0.629104 -0.50006 0.0929983 +-0.611972 -0.643644 0.0906583 +-0.560565 -0.782273 0.0836422 +-0.427777 -0.881297 0.065513 +-0.303555 -0.950611 0.0485549 +-0.11936 -0.990221 0.0234108 +-0.00798559 -0.990221 0.00820661 +-0.0355172 0.990221 0.00824904 +-0.0932325 0.980316 0.0120597 +-0.142069 0.960511 0.0152843 +-0.253058 0.896146 0.0226121 +-0.284135 0.851587 0.0246642 +-0.310774 0.757518 0.0264231 +-0.332972 0.36143 0.0278887 +-0.359611 0.267359 0.0296475 +-0.452839 0.108924 0.035803 +-0.535573 -0.049511 0.0412654 +-0.590788 -0.222799 0.0472349 +-0.642588 -0.376283 0.0507526 +-0.633953 -0.50006 0.0501662 +-0.616686 -0.643644 0.0489937 +-0.564889 -0.782273 0.0454762 +-0.431074 -0.881297 0.0363895 +-0.305895 -0.950611 0.0278887 +-0.120279 -0.990221 0.0152843 +-0.00804627 -0.990221 0.00766301 +numsurf 1553 +SURF 0x30 +mat 2 +refs 4 +0 0.472401 1 +1 0.472434 1 +2 0.42764 0.994999 +3 0.427492 0.994999 +SURF 0x30 +mat 2 +refs 4 +3 0.427492 0.994999 +2 0.42764 0.994999 +4 0.389737 0.984998 +5 0.389492 0.984998 +SURF 0x30 +mat 2 +refs 4 +5 0.389492 0.984998 +4 0.389737 0.984998 +6 0.303596 0.952498 +7 0.303132 0.952498 +SURF 0x30 +mat 2 +refs 4 +7 0.303132 0.952498 +6 0.303596 0.952498 +8 0.279478 0.929999 +9 0.27895 0.929999 +SURF 0x30 +mat 2 +refs 4 +9 0.27895 0.929999 +8 0.279478 0.929999 +10 0.258802 0.8825 +11 0.258224 0.8825 +SURF 0x30 +mat 2 +refs 4 +11 0.258224 0.8825 +10 0.258802 0.8825 +12 0.241574 0.6825 +13 0.240952 0.6825 +SURF 0x30 +mat 2 +refs 4 +13 0.240952 0.6825 +12 0.241574 0.6825 +14 0.220899 0.635 +15 0.220223 0.635 +SURF 0x30 +mat 2 +refs 4 +15 0.220223 0.635 +14 0.220899 0.635 +16 0.148543 0.555 +17 0.147679 0.555 +SURF 0x30 +mat 2 +refs 4 +17 0.147679 0.555 +16 0.148543 0.555 +18 0.0843316 0.475 +19 0.0833059 0.475 +SURF 0x30 +mat 2 +refs 4 +19 0.0833059 0.475 +18 0.0843316 0.475 +20 0.0414781 0.3875 +21 0.0403078 0.3875 +SURF 0x30 +mat 2 +refs 4 +21 0.0403078 0.3875 +20 0.0414781 0.3875 +22 0.00127453 0.31 +23 0 0.31 +SURF 0x30 +mat 2 +refs 4 +23 0 0.31 +22 0.00127453 0.31 +24 0.0079768 0.247501 +25 0.00671911 0.247501 +SURF 0x30 +mat 2 +refs 4 +25 0.00671911 0.247501 +24 0.0079768 0.247501 +26 0.021378 0.175 +27 0.0201539 0.175 +SURF 0x30 +mat 2 +refs 4 +27 0.0201539 0.175 +26 0.021378 0.175 +28 0.0615781 0.105001 +29 0.0604583 0.105001 +SURF 0x30 +mat 2 +refs 4 +29 0.0604583 0.105001 +28 0.0615781 0.105001 +30 0.165435 0.0549999 +31 0.164581 0.0549999 +SURF 0x30 +mat 2 +refs 4 +31 0.164581 0.0549999 +30 0.165435 0.0549999 +32 0.262589 0.0200004 +33 0.261984 0.0200004 +SURF 0x30 +mat 2 +refs 4 +33 0.261984 0.0200004 +32 0.262589 0.0200004 +34 0.406649 0 +35 0.40641 0 +SURF 0x30 +mat 2 +refs 4 +35 0.40641 0 +34 0.406649 0 +36 0.493755 0 +37 0.493738 0 +SURF 0x30 +mat 2 +refs 4 +1 0.472434 1 +38 0.472535 1 +39 0.428084 0.994999 +2 0.42764 0.994999 +SURF 0x30 +mat 2 +refs 4 +2 0.42764 0.994999 +39 0.428084 0.994999 +40 0.390474 0.984998 +4 0.389737 0.984998 +SURF 0x30 +mat 2 +refs 4 +4 0.389737 0.984998 +40 0.390474 0.984998 +41 0.304989 0.952498 +6 0.303596 0.952498 +SURF 0x30 +mat 2 +refs 4 +6 0.303596 0.952498 +41 0.304989 0.952498 +42 0.281055 0.929999 +8 0.279478 0.929999 +SURF 0x30 +mat 2 +refs 4 +8 0.279478 0.929999 +42 0.281055 0.929999 +43 0.260538 0.8825 +10 0.258802 0.8825 +SURF 0x30 +mat 2 +refs 4 +10 0.258802 0.8825 +43 0.260538 0.8825 +44 0.243444 0.6825 +12 0.241574 0.6825 +SURF 0x30 +mat 2 +refs 4 +12 0.241574 0.6825 +44 0.243444 0.6825 +45 0.222927 0.635 +14 0.220899 0.635 +SURF 0x30 +mat 2 +refs 4 +14 0.220899 0.635 +45 0.222927 0.635 +46 0.151122 0.555 +16 0.148543 0.555 +SURF 0x30 +mat 2 +refs 4 +16 0.148543 0.555 +46 0.151122 0.555 +47 0.0874052 0.475 +18 0.0843316 0.475 +SURF 0x30 +mat 2 +refs 4 +18 0.0843316 0.475 +47 0.0874052 0.475 +48 0.0449856 0.3875 +20 0.0414781 0.3875 +SURF 0x30 +mat 2 +refs 4 +20 0.0414781 0.3875 +48 0.0449856 0.3875 +49 0.0050915 0.31 +22 0.00127453 0.31 +SURF 0x30 +mat 2 +refs 4 +22 0.00127453 0.31 +49 0.0050915 0.31 +50 0.0117399 0.247501 +24 0.0079768 0.247501 +SURF 0x30 +mat 2 +refs 4 +24 0.0079768 0.247501 +50 0.0117399 0.247501 +51 0.0250368 0.175 +26 0.021378 0.175 +SURF 0x30 +mat 2 +refs 4 +26 0.021378 0.175 +51 0.0250368 0.175 +52 0.0649344 0.105001 +28 0.0615781 0.105001 +SURF 0x30 +mat 2 +refs 4 +28 0.0615781 0.105001 +52 0.0649344 0.105001 +53 0.167994 0.0549999 +30 0.165435 0.0549999 +SURF 0x30 +mat 2 +refs 4 +30 0.165435 0.0549999 +53 0.167994 0.0549999 +54 0.264405 0.0200004 +32 0.262589 0.0200004 +SURF 0x30 +mat 2 +refs 4 +32 0.262589 0.0200004 +54 0.264405 0.0200004 +55 0.407362 0 +34 0.406649 0 +SURF 0x30 +mat 2 +refs 4 +34 0.406649 0 +55 0.407362 0 +56 0.493802 0 +36 0.493755 0 +SURF 0x30 +mat 2 +refs 4 +38 0.472535 1 +57 0.472707 1 +58 0.428824 0.994999 +39 0.428084 0.994999 +SURF 0x30 +mat 2 +refs 4 +39 0.428084 0.994999 +58 0.428824 0.994999 +59 0.391694 0.984998 +40 0.390474 0.984998 +SURF 0x30 +mat 2 +refs 4 +40 0.390474 0.984998 +59 0.391694 0.984998 +60 0.307306 0.952498 +41 0.304989 0.952498 +SURF 0x30 +mat 2 +refs 4 +41 0.304989 0.952498 +60 0.307306 0.952498 +61 0.283674 0.929999 +42 0.281055 0.929999 +SURF 0x30 +mat 2 +refs 4 +42 0.281055 0.929999 +61 0.283674 0.929999 +62 0.263423 0.8825 +43 0.260538 0.8825 +SURF 0x30 +mat 2 +refs 4 +43 0.260538 0.8825 +62 0.263423 0.8825 +63 0.246545 0.6825 +44 0.243444 0.6825 +SURF 0x30 +mat 2 +refs 4 +44 0.243444 0.6825 +63 0.246545 0.6825 +64 0.226293 0.635 +45 0.222927 0.635 +SURF 0x30 +mat 2 +refs 4 +45 0.222927 0.635 +64 0.226293 0.635 +65 0.155407 0.555 +46 0.151122 0.555 +SURF 0x30 +mat 2 +refs 4 +46 0.151122 0.555 +65 0.155407 0.555 +66 0.0925034 0.475 +47 0.0874052 0.475 +SURF 0x30 +mat 2 +refs 4 +47 0.0874052 0.475 +66 0.0925034 0.475 +67 0.0508135 0.3875 +48 0.0449856 0.3875 +SURF 0x30 +mat 2 +refs 4 +48 0.0449856 0.3875 +67 0.0508135 0.3875 +68 0.0114272 0.31 +49 0.0050915 0.31 +SURF 0x30 +mat 2 +refs 4 +49 0.0050915 0.31 +68 0.0114272 0.31 +69 0.0179915 0.247501 +50 0.0117399 0.247501 +SURF 0x30 +mat 2 +refs 4 +50 0.0117399 0.247501 +69 0.0179915 0.247501 +70 0.0311203 0.175 +51 0.0250368 0.175 +SURF 0x30 +mat 2 +refs 4 +51 0.0250368 0.175 +70 0.0311203 0.175 +71 0.0705033 0.105001 +52 0.0649344 0.105001 +SURF 0x30 +mat 2 +refs 4 +52 0.0649344 0.105001 +71 0.0705033 0.105001 +72 0.172245 0.0549999 +53 0.167994 0.0549999 +SURF 0x30 +mat 2 +refs 4 +53 0.167994 0.0549999 +72 0.172245 0.0549999 +73 0.267425 0.0200004 +54 0.264405 0.0200004 +SURF 0x30 +mat 2 +refs 4 +54 0.264405 0.0200004 +73 0.267425 0.0200004 +74 0.408549 0 +55 0.407362 0 +SURF 0x30 +mat 2 +refs 4 +55 0.407362 0 +74 0.408549 0 +75 0.49388 0 +56 0.493802 0 +SURF 0x30 +mat 2 +refs 4 +57 0.472707 1 +76 0.472942 1 +77 0.429853 0.994999 +58 0.428824 0.994999 +SURF 0x30 +mat 2 +refs 4 +58 0.428824 0.994999 +77 0.429853 0.994999 +78 0.393393 0.984998 +59 0.391694 0.984998 +SURF 0x30 +mat 2 +refs 4 +59 0.391694 0.984998 +78 0.393393 0.984998 +79 0.310527 0.952498 +60 0.307306 0.952498 +SURF 0x30 +mat 2 +refs 4 +60 0.307306 0.952498 +79 0.310527 0.952498 +80 0.287327 0.929999 +61 0.283674 0.929999 +SURF 0x30 +mat 2 +refs 4 +61 0.283674 0.929999 +80 0.287327 0.929999 +81 0.267438 0.8825 +62 0.263423 0.8825 +SURF 0x30 +mat 2 +refs 4 +62 0.263423 0.8825 +81 0.267438 0.8825 +82 0.250866 0.6825 +63 0.246545 0.6825 +SURF 0x30 +mat 2 +refs 4 +63 0.246545 0.6825 +82 0.250866 0.6825 +83 0.230981 0.635 +64 0.226293 0.635 +SURF 0x30 +mat 2 +refs 4 +64 0.226293 0.635 +83 0.230981 0.635 +84 0.161376 0.555 +65 0.155407 0.555 +SURF 0x30 +mat 2 +refs 4 +65 0.155407 0.555 +84 0.161376 0.555 +85 0.0996092 0.475 +66 0.0925034 0.475 +SURF 0x30 +mat 2 +refs 4 +66 0.0925034 0.475 +85 0.0996092 0.475 +86 0.0589282 0.3875 +67 0.0508135 0.3875 +SURF 0x30 +mat 2 +refs 4 +67 0.0508135 0.3875 +86 0.0589282 0.3875 +87 0.0202548 0.31 +68 0.0114272 0.31 +SURF 0x30 +mat 2 +refs 4 +68 0.0114272 0.31 +87 0.0202548 0.31 +88 0.0267014 0.247501 +69 0.0179915 0.247501 +SURF 0x30 +mat 2 +refs 4 +69 0.0179915 0.247501 +88 0.0267014 0.247501 +89 0.0395915 0.175 +70 0.0311203 0.175 +SURF 0x30 +mat 2 +refs 4 +70 0.0311203 0.175 +89 0.0395915 0.175 +90 0.0782649 0.105001 +71 0.0705033 0.105001 +SURF 0x30 +mat 2 +refs 4 +71 0.0705033 0.105001 +90 0.0782649 0.105001 +91 0.178167 0.0549999 +72 0.172245 0.0549999 +SURF 0x30 +mat 2 +refs 4 +72 0.172245 0.0549999 +91 0.178167 0.0549999 +92 0.271625 0.0200004 +73 0.267425 0.0200004 +SURF 0x30 +mat 2 +refs 4 +73 0.267425 0.0200004 +92 0.271625 0.0200004 +93 0.4102 0 +74 0.408549 0 +SURF 0x30 +mat 2 +refs 4 +74 0.408549 0 +93 0.4102 0 +94 0.493991 0 +75 0.49388 0 +SURF 0x30 +mat 2 +refs 4 +76 0.472942 1 +95 0.473241 1 +96 0.431165 0.994999 +77 0.429853 0.994999 +SURF 0x30 +mat 2 +refs 4 +77 0.429853 0.994999 +96 0.431165 0.994999 +97 0.395562 0.984998 +78 0.393393 0.984998 +SURF 0x30 +mat 2 +refs 4 +78 0.393393 0.984998 +97 0.395562 0.984998 +98 0.314647 0.952498 +79 0.310527 0.952498 +SURF 0x30 +mat 2 +refs 4 +79 0.310527 0.952498 +98 0.314647 0.952498 +99 0.291988 0.929999 +80 0.287327 0.929999 +SURF 0x30 +mat 2 +refs 4 +80 0.287327 0.929999 +99 0.291988 0.929999 +100 0.27257 0.8825 +81 0.267438 0.8825 +SURF 0x30 +mat 2 +refs 4 +81 0.267438 0.8825 +100 0.27257 0.8825 +101 0.256385 0.6825 +82 0.250866 0.6825 +SURF 0x30 +mat 2 +refs 4 +82 0.250866 0.6825 +101 0.256385 0.6825 +102 0.236967 0.635 +83 0.230981 0.635 +SURF 0x30 +mat 2 +refs 4 +83 0.230981 0.635 +102 0.236967 0.635 +103 0.168996 0.555 +84 0.161376 0.555 +SURF 0x30 +mat 2 +refs 4 +84 0.161376 0.555 +103 0.168996 0.555 +104 0.108682 0.475 +85 0.0996092 0.475 +SURF 0x30 +mat 2 +refs 4 +85 0.0996092 0.475 +104 0.108682 0.475 +105 0.0692893 0.3875 +86 0.0589282 0.3875 +SURF 0x30 +mat 2 +refs 4 +86 0.0589282 0.3875 +105 0.0692893 0.3875 +106 0.0315273 0.31 +87 0.0202548 0.31 +SURF 0x30 +mat 2 +refs 4 +87 0.0202548 0.31 +106 0.0315273 0.31 +107 0.0378192 0.247501 +88 0.0267014 0.247501 +SURF 0x30 +mat 2 +refs 4 +88 0.0267014 0.247501 +107 0.0378192 0.247501 +108 0.0504099 0.175 +89 0.0395915 0.175 +SURF 0x30 +mat 2 +refs 4 +89 0.0395915 0.175 +108 0.0504099 0.175 +109 0.088172 0.105001 +90 0.0782649 0.105001 +SURF 0x30 +mat 2 +refs 4 +90 0.0782649 0.105001 +109 0.088172 0.105001 +110 0.18573 0.0549999 +91 0.178167 0.0549999 +SURF 0x30 +mat 2 +refs 4 +91 0.178167 0.0549999 +110 0.18573 0.0549999 +111 0.276992 0.0200004 +92 0.271625 0.0200004 +SURF 0x30 +mat 2 +refs 4 +92 0.271625 0.0200004 +111 0.276992 0.0200004 +112 0.412312 0 +93 0.4102 0 +SURF 0x30 +mat 2 +refs 4 +93 0.4102 0 +112 0.412312 0 +113 0.494132 0 +94 0.493991 0 +SURF 0x30 +mat 2 +refs 4 +95 0.473241 1 +114 0.473608 1 +115 0.432755 0.994999 +96 0.431165 0.994999 +SURF 0x30 +mat 2 +refs 4 +96 0.431165 0.994999 +115 0.432755 0.994999 +116 0.398191 0.984998 +97 0.395562 0.984998 +SURF 0x30 +mat 2 +refs 4 +97 0.395562 0.984998 +116 0.398191 0.984998 +117 0.319634 0.952498 +98 0.314647 0.952498 +SURF 0x30 +mat 2 +refs 4 +98 0.314647 0.952498 +117 0.319634 0.952498 +118 0.297637 0.929999 +99 0.291988 0.929999 +SURF 0x30 +mat 2 +refs 4 +99 0.291988 0.929999 +118 0.297637 0.929999 +119 0.278785 0.8825 +100 0.27257 0.8825 +SURF 0x30 +mat 2 +refs 4 +100 0.27257 0.8825 +119 0.278785 0.8825 +120 0.263073 0.6825 +101 0.256385 0.6825 +SURF 0x30 +mat 2 +refs 4 +101 0.256385 0.6825 +120 0.263073 0.6825 +121 0.244218 0.635 +102 0.236967 0.635 +SURF 0x30 +mat 2 +refs 4 +102 0.236967 0.635 +121 0.244218 0.635 +122 0.178231 0.555 +103 0.168996 0.555 +SURF 0x30 +mat 2 +refs 4 +103 0.168996 0.555 +122 0.178231 0.555 +123 0.119676 0.475 +104 0.108682 0.475 +SURF 0x30 +mat 2 +refs 4 +104 0.108682 0.475 +123 0.119676 0.475 +124 0.0818498 0.3875 +105 0.0692893 0.3875 +SURF 0x30 +mat 2 +refs 4 +105 0.0692893 0.3875 +124 0.0818498 0.3875 +125 0.045184 0.31 +106 0.0315273 0.31 +SURF 0x30 +mat 2 +refs 4 +106 0.0315273 0.31 +125 0.045184 0.31 +126 0.0512944 0.247501 +107 0.0378192 0.247501 +SURF 0x30 +mat 2 +refs 4 +107 0.0378192 0.247501 +126 0.0512944 0.247501 +127 0.0635152 0.175 +108 0.0504099 0.175 +SURF 0x30 +mat 2 +refs 4 +108 0.0504099 0.175 +127 0.0635152 0.175 +128 0.100181 0.105001 +109 0.088172 0.105001 +SURF 0x30 +mat 2 +refs 4 +109 0.088172 0.105001 +128 0.100181 0.105001 +129 0.19489 0.0549999 +110 0.18573 0.0549999 +SURF 0x30 +mat 2 +refs 4 +110 0.18573 0.0549999 +129 0.19489 0.0549999 +130 0.283493 0.0200004 +111 0.276992 0.0200004 +SURF 0x30 +mat 2 +refs 4 +111 0.276992 0.0200004 +130 0.283493 0.0200004 +131 0.414868 0 +112 0.412312 0 +SURF 0x30 +mat 2 +refs 4 +112 0.412312 0 +131 0.414868 0 +132 0.494303 0 +113 0.494132 0 +SURF 0x30 +mat 2 +refs 4 +114 0.473608 1 +133 0.474035 1 +134 0.434618 0.994999 +115 0.432755 0.994999 +SURF 0x30 +mat 2 +refs 4 +115 0.432755 0.994999 +134 0.434618 0.994999 +135 0.401268 0.984998 +116 0.398191 0.984998 +SURF 0x30 +mat 2 +refs 4 +116 0.398191 0.984998 +135 0.401268 0.984998 +136 0.325469 0.952498 +117 0.319634 0.952498 +SURF 0x30 +mat 2 +refs 4 +117 0.319634 0.952498 +136 0.325469 0.952498 +137 0.304245 0.929999 +118 0.297637 0.929999 +SURF 0x30 +mat 2 +refs 4 +118 0.297637 0.929999 +137 0.304245 0.929999 +138 0.286055 0.8825 +119 0.278785 0.8825 +SURF 0x30 +mat 2 +refs 4 +119 0.278785 0.8825 +138 0.286055 0.8825 +139 0.270895 0.6825 +120 0.263073 0.6825 +SURF 0x30 +mat 2 +refs 4 +120 0.263073 0.6825 +139 0.270895 0.6825 +140 0.252702 0.635 +121 0.244218 0.635 +SURF 0x30 +mat 2 +refs 4 +121 0.244218 0.635 +140 0.252702 0.635 +141 0.189032 0.555 +122 0.178231 0.555 +SURF 0x30 +mat 2 +refs 4 +122 0.178231 0.555 +141 0.189032 0.555 +142 0.132535 0.475 +123 0.119676 0.475 +SURF 0x30 +mat 2 +refs 4 +123 0.119676 0.475 +142 0.132535 0.475 +143 0.0965356 0.3875 +124 0.0818498 0.3875 +SURF 0x30 +mat 2 +refs 4 +124 0.0818498 0.3875 +143 0.0965356 0.3875 +144 0.0611612 0.31 +125 0.045184 0.31 +SURF 0x30 +mat 2 +refs 4 +125 0.045184 0.31 +144 0.0611612 0.31 +145 0.0670564 0.247501 +126 0.0512944 0.247501 +SURF 0x30 +mat 2 +refs 4 +126 0.0512944 0.247501 +145 0.0670564 0.247501 +146 0.07885 0.175 +127 0.0635152 0.175 +SURF 0x30 +mat 2 +refs 4 +127 0.0635152 0.175 +146 0.07885 0.175 +147 0.114224 0.105001 +128 0.100181 0.105001 +SURF 0x30 +mat 2 +refs 4 +128 0.100181 0.105001 +147 0.114224 0.105001 +148 0.205608 0.0549999 +129 0.19489 0.0549999 +SURF 0x30 +mat 2 +refs 4 +129 0.19489 0.0549999 +148 0.205608 0.0549999 +149 0.2911 0.0200004 +130 0.283493 0.0200004 +SURF 0x30 +mat 2 +refs 4 +130 0.283493 0.0200004 +149 0.2911 0.0200004 +150 0.417858 0 +131 0.414868 0 +SURF 0x30 +mat 2 +refs 4 +131 0.414868 0 +150 0.417858 0 +151 0.494505 0 +132 0.494303 0 +SURF 0x30 +mat 2 +refs 4 +133 0.474035 1 +152 0.474519 1 +153 0.43674 0.994999 +134 0.434618 0.994999 +SURF 0x30 +mat 2 +refs 4 +134 0.434618 0.994999 +153 0.43674 0.994999 +154 0.404773 0.984998 +135 0.401268 0.984998 +SURF 0x30 +mat 2 +refs 4 +135 0.401268 0.984998 +154 0.404773 0.984998 +155 0.33212 0.952498 +136 0.325469 0.952498 +SURF 0x30 +mat 2 +refs 4 +136 0.325469 0.952498 +155 0.33212 0.952498 +156 0.311778 0.929999 +137 0.304245 0.929999 +SURF 0x30 +mat 2 +refs 4 +137 0.304245 0.929999 +156 0.311778 0.929999 +157 0.294342 0.8825 +138 0.286055 0.8825 +SURF 0x30 +mat 2 +refs 4 +138 0.286055 0.8825 +157 0.294342 0.8825 +158 0.279811 0.6825 +139 0.270895 0.6825 +SURF 0x30 +mat 2 +refs 4 +139 0.270895 0.6825 +158 0.279811 0.6825 +159 0.262374 0.635 +140 0.252702 0.635 +SURF 0x30 +mat 2 +refs 4 +140 0.252702 0.635 +159 0.262374 0.635 +160 0.201347 0.555 +141 0.189032 0.555 +SURF 0x30 +mat 2 +refs 4 +141 0.189032 0.555 +160 0.201347 0.555 +161 0.147194 0.475 +142 0.132535 0.475 +SURF 0x30 +mat 2 +refs 4 +142 0.132535 0.475 +161 0.147194 0.475 +162 0.113283 0.3875 +143 0.0965356 0.3875 +SURF 0x30 +mat 2 +refs 4 +143 0.0965356 0.3875 +162 0.113283 0.3875 +163 0.0793746 0.31 +144 0.0611612 0.31 +SURF 0x30 +mat 2 +refs 4 +144 0.0611612 0.31 +163 0.0793746 0.31 +164 0.0850243 0.247501 +145 0.0670564 0.247501 +SURF 0x30 +mat 2 +refs 4 +145 0.0670564 0.247501 +164 0.0850243 0.247501 +165 0.096327 0.175 +146 0.07885 0.175 +SURF 0x30 +mat 2 +refs 4 +146 0.07885 0.175 +165 0.096327 0.175 +166 0.130235 0.105001 +147 0.114224 0.105001 +SURF 0x30 +mat 2 +refs 4 +147 0.114224 0.105001 +166 0.130235 0.105001 +167 0.217825 0.0549999 +148 0.205608 0.0549999 +SURF 0x30 +mat 2 +refs 4 +148 0.205608 0.0549999 +167 0.217825 0.0549999 +168 0.299769 0.0200004 +149 0.2911 0.0200004 +SURF 0x30 +mat 2 +refs 4 +149 0.2911 0.0200004 +168 0.299769 0.0200004 +169 0.421268 0 +150 0.417858 0 +SURF 0x30 +mat 2 +refs 4 +150 0.417858 0 +169 0.421268 0 +170 0.49473 0 +151 0.494505 0 +SURF 0x30 +mat 2 +refs 4 +152 0.474519 1 +171 0.475064 1 +172 0.439111 0.994999 +153 0.43674 0.994999 +SURF 0x30 +mat 2 +refs 4 +153 0.43674 0.994999 +172 0.439111 0.994999 +173 0.408694 0.984998 +154 0.404773 0.984998 +SURF 0x30 +mat 2 +refs 4 +154 0.404773 0.984998 +173 0.408694 0.984998 +174 0.339556 0.952498 +155 0.33212 0.952498 +SURF 0x30 +mat 2 +refs 4 +155 0.33212 0.952498 +174 0.339556 0.952498 +175 0.320199 0.929999 +156 0.311778 0.929999 +SURF 0x30 +mat 2 +refs 4 +156 0.311778 0.929999 +175 0.320199 0.929999 +176 0.303606 0.8825 +157 0.294342 0.8825 +SURF 0x30 +mat 2 +refs 4 +157 0.294342 0.8825 +176 0.303606 0.8825 +177 0.289778 0.6825 +158 0.279811 0.6825 +SURF 0x30 +mat 2 +refs 4 +158 0.279811 0.6825 +177 0.289778 0.6825 +178 0.273186 0.635 +159 0.262374 0.635 +SURF 0x30 +mat 2 +refs 4 +159 0.262374 0.635 +178 0.273186 0.635 +179 0.215112 0.555 +160 0.201347 0.555 +SURF 0x30 +mat 2 +refs 4 +160 0.201347 0.555 +179 0.215112 0.555 +180 0.163578 0.475 +161 0.147194 0.475 +SURF 0x30 +mat 2 +refs 4 +161 0.147194 0.475 +180 0.163578 0.475 +181 0.131997 0.3875 +162 0.113283 0.3875 +SURF 0x30 +mat 2 +refs 4 +162 0.113283 0.3875 +181 0.131997 0.3875 +182 0.0997303 0.31 +163 0.0793746 0.31 +SURF 0x30 +mat 2 +refs 4 +163 0.0793746 0.31 +182 0.0997303 0.31 +183 0.105108 0.247501 +164 0.0850243 0.247501 +SURF 0x30 +mat 2 +refs 4 +164 0.0850243 0.247501 +183 0.105108 0.247501 +184 0.115862 0.175 +165 0.096327 0.175 +SURF 0x30 +mat 2 +refs 4 +165 0.096327 0.175 +184 0.115862 0.175 +185 0.148129 0.105001 +166 0.130235 0.105001 +SURF 0x30 +mat 2 +refs 4 +166 0.130235 0.105001 +185 0.148129 0.105001 +186 0.231482 0.0549999 +167 0.217825 0.0549999 +SURF 0x30 +mat 2 +refs 4 +167 0.217825 0.0549999 +186 0.231482 0.0549999 +187 0.309458 0.0200004 +168 0.299769 0.0200004 +SURF 0x30 +mat 2 +refs 4 +168 0.299769 0.0200004 +187 0.309458 0.0200004 +188 0.425078 0 +169 0.421268 0 +SURF 0x30 +mat 2 +refs 4 +169 0.421268 0 +188 0.425078 0 +189 0.494986 0 +170 0.49473 0 +SURF 0x30 +mat 2 +refs 4 +171 0.475064 1 +190 0.475663 1 +191 0.441721 0.994999 +172 0.439111 0.994999 +SURF 0x30 +mat 2 +refs 4 +172 0.439111 0.994999 +191 0.441721 0.994999 +192 0.413005 0.984998 +173 0.408694 0.984998 +SURF 0x30 +mat 2 +refs 4 +173 0.408694 0.984998 +192 0.413005 0.984998 +193 0.347738 0.952498 +174 0.339556 0.952498 +SURF 0x30 +mat 2 +refs 4 +174 0.339556 0.952498 +193 0.347738 0.952498 +194 0.32946 0.929999 +175 0.320199 0.929999 +SURF 0x30 +mat 2 +refs 4 +175 0.320199 0.929999 +194 0.32946 0.929999 +195 0.313796 0.8825 +176 0.303606 0.8825 +SURF 0x30 +mat 2 +refs 4 +176 0.303606 0.8825 +195 0.313796 0.8825 +196 0.300745 0.6825 +177 0.289778 0.6825 +SURF 0x30 +mat 2 +refs 4 +177 0.289778 0.6825 +196 0.300745 0.6825 +197 0.28508 0.635 +178 0.273186 0.635 +SURF 0x30 +mat 2 +refs 4 +178 0.273186 0.635 +197 0.28508 0.635 +198 0.230255 0.555 +179 0.215112 0.555 +SURF 0x30 +mat 2 +refs 4 +179 0.215112 0.555 +198 0.230255 0.555 +199 0.181604 0.475 +180 0.163578 0.475 +SURF 0x30 +mat 2 +refs 4 +180 0.163578 0.475 +199 0.181604 0.475 +200 0.152588 0.3875 +181 0.131997 0.3875 +SURF 0x30 +mat 2 +refs 4 +181 0.131997 0.3875 +200 0.152588 0.3875 +201 0.122127 0.31 +182 0.0997303 0.31 +SURF 0x30 +mat 2 +refs 4 +182 0.0997303 0.31 +201 0.122127 0.31 +202 0.127202 0.247501 +183 0.105108 0.247501 +SURF 0x30 +mat 2 +refs 4 +183 0.105108 0.247501 +202 0.127202 0.247501 +203 0.137358 0.175 +184 0.115862 0.175 +SURF 0x30 +mat 2 +refs 4 +184 0.115862 0.175 +203 0.137358 0.175 +204 0.167816 0.105001 +185 0.148129 0.105001 +SURF 0x30 +mat 2 +refs 4 +185 0.148129 0.105001 +204 0.167816 0.105001 +205 0.246508 0.0549999 +186 0.231482 0.0549999 +SURF 0x30 +mat 2 +refs 4 +186 0.231482 0.0549999 +205 0.246508 0.0549999 +206 0.320118 0.0200004 +187 0.309458 0.0200004 +SURF 0x30 +mat 2 +refs 4 +187 0.309458 0.0200004 +206 0.320118 0.0200004 +207 0.429268 0 +188 0.425078 0 +SURF 0x30 +mat 2 +refs 4 +188 0.425078 0 +207 0.429268 0 +208 0.495268 0 +189 0.494986 0 +SURF 0x30 +mat 2 +refs 4 +190 0.475663 1 +209 0.476312 1 +210 0.444556 0.994999 +191 0.441721 0.994999 +SURF 0x30 +mat 2 +refs 4 +191 0.441721 0.994999 +210 0.444556 0.994999 +211 0.417686 0.984998 +192 0.413005 0.984998 +SURF 0x30 +mat 2 +refs 4 +192 0.413005 0.984998 +211 0.417686 0.984998 +212 0.356619 0.952498 +193 0.347738 0.952498 +SURF 0x30 +mat 2 +refs 4 +193 0.347738 0.952498 +212 0.356619 0.952498 +213 0.339522 0.929999 +194 0.32946 0.929999 +SURF 0x30 +mat 2 +refs 4 +194 0.32946 0.929999 +213 0.339522 0.929999 +214 0.324863 0.8825 +195 0.313796 0.8825 +SURF 0x30 +mat 2 +refs 4 +195 0.313796 0.8825 +214 0.324863 0.8825 +215 0.312653 0.6825 +196 0.300745 0.6825 +SURF 0x30 +mat 2 +refs 4 +196 0.300745 0.6825 +215 0.312653 0.6825 +216 0.297994 0.635 +197 0.28508 0.635 +SURF 0x30 +mat 2 +refs 4 +197 0.28508 0.635 +216 0.297994 0.635 +217 0.246699 0.555 +198 0.230255 0.555 +SURF 0x30 +mat 2 +refs 4 +198 0.230255 0.555 +217 0.246699 0.555 +218 0.201179 0.475 +199 0.181604 0.475 +SURF 0x30 +mat 2 +refs 4 +199 0.181604 0.475 +218 0.201179 0.475 +219 0.174948 0.3875 +200 0.152588 0.3875 +SURF 0x30 +mat 2 +refs 4 +200 0.152588 0.3875 +219 0.174948 0.3875 +220 0.146448 0.31 +201 0.122127 0.31 +SURF 0x30 +mat 2 +refs 4 +201 0.122127 0.31 +220 0.146448 0.31 +221 0.151196 0.247501 +202 0.127202 0.247501 +SURF 0x30 +mat 2 +refs 4 +202 0.127202 0.247501 +221 0.151196 0.247501 +222 0.160696 0.175 +203 0.137358 0.175 +SURF 0x30 +mat 2 +refs 4 +203 0.137358 0.175 +222 0.160696 0.175 +223 0.189197 0.105001 +204 0.167816 0.105001 +SURF 0x30 +mat 2 +refs 4 +204 0.167816 0.105001 +223 0.189197 0.105001 +224 0.262821 0.0549999 +205 0.246508 0.0549999 +SURF 0x30 +mat 2 +refs 4 +205 0.246508 0.0549999 +224 0.262821 0.0549999 +225 0.331697 0.0200004 +206 0.320118 0.0200004 +SURF 0x30 +mat 2 +refs 4 +206 0.320118 0.0200004 +225 0.331697 0.0200004 +226 0.433821 0 +207 0.429268 0 +SURF 0x30 +mat 2 +refs 4 +207 0.429268 0 +226 0.433821 0 +227 0.495571 0 +208 0.495268 0 +SURF 0x30 +mat 2 +refs 4 +209 0.476312 1 +228 0.477008 1 +229 0.447599 0.994999 +210 0.444556 0.994999 +SURF 0x30 +mat 2 +refs 4 +210 0.444556 0.994999 +229 0.447599 0.994999 +230 0.422717 0.984998 +211 0.417686 0.984998 +SURF 0x30 +mat 2 +refs 4 +211 0.417686 0.984998 +230 0.422717 0.984998 +231 0.36616 0.952498 +212 0.356619 0.952498 +SURF 0x30 +mat 2 +refs 4 +212 0.356619 0.952498 +231 0.36616 0.952498 +232 0.350324 0.929999 +213 0.339522 0.929999 +SURF 0x30 +mat 2 +refs 4 +213 0.339522 0.929999 +232 0.350324 0.929999 +233 0.336751 0.8825 +214 0.324863 0.8825 +SURF 0x30 +mat 2 +refs 4 +214 0.324863 0.8825 +233 0.336751 0.8825 +234 0.325442 0.6825 +215 0.312653 0.6825 +SURF 0x30 +mat 2 +refs 4 +215 0.312653 0.6825 +234 0.325442 0.6825 +235 0.311869 0.635 +216 0.297994 0.635 +SURF 0x30 +mat 2 +refs 4 +216 0.297994 0.635 +235 0.311869 0.635 +236 0.264361 0.555 +217 0.246699 0.555 +SURF 0x30 +mat 2 +refs 4 +217 0.246699 0.555 +236 0.264361 0.555 +237 0.222207 0.475 +218 0.201179 0.475 +SURF 0x30 +mat 2 +refs 4 +218 0.201179 0.475 +237 0.222207 0.475 +238 0.198966 0.3875 +219 0.174948 0.3875 +SURF 0x30 +mat 2 +refs 4 +219 0.174948 0.3875 +238 0.198966 0.3875 +239 0.172571 0.31 +220 0.146448 0.31 +SURF 0x30 +mat 2 +refs 4 +220 0.146448 0.31 +239 0.172571 0.31 +240 0.17697 0.247501 +221 0.151196 0.247501 +SURF 0x30 +mat 2 +refs 4 +221 0.151196 0.247501 +240 0.17697 0.247501 +241 0.185767 0.175 +222 0.160696 0.175 +SURF 0x30 +mat 2 +refs 4 +222 0.160696 0.175 +241 0.185767 0.175 +242 0.212162 0.105001 +223 0.189197 0.105001 +SURF 0x30 +mat 2 +refs 4 +223 0.189197 0.105001 +242 0.212162 0.105001 +243 0.280349 0.0549999 +224 0.262821 0.0549999 +SURF 0x30 +mat 2 +refs 4 +224 0.262821 0.0549999 +243 0.280349 0.0549999 +244 0.344133 0.0200004 +225 0.331697 0.0200004 +SURF 0x30 +mat 2 +refs 4 +225 0.331697 0.0200004 +244 0.344133 0.0200004 +245 0.438711 0 +226 0.433821 0 +SURF 0x30 +mat 2 +refs 4 +226 0.433821 0 +245 0.438711 0 +246 0.495901 0 +227 0.495571 0 +SURF 0x30 +mat 2 +refs 4 +228 0.477008 1 +247 0.477751 1 +248 0.450838 0.994999 +229 0.447599 0.994999 +SURF 0x30 +mat 2 +refs 4 +229 0.447599 0.994999 +248 0.450838 0.994999 +249 0.428064 0.984998 +230 0.422717 0.984998 +SURF 0x30 +mat 2 +refs 4 +230 0.422717 0.984998 +249 0.428064 0.984998 +250 0.376312 0.952498 +231 0.36616 0.952498 +SURF 0x30 +mat 2 +refs 4 +231 0.36616 0.952498 +250 0.376312 0.952498 +251 0.361818 0.929999 +232 0.350324 0.929999 +SURF 0x30 +mat 2 +refs 4 +232 0.350324 0.929999 +251 0.361818 0.929999 +252 0.349399 0.8825 +233 0.336751 0.8825 +SURF 0x30 +mat 2 +refs 4 +233 0.336751 0.8825 +252 0.349399 0.8825 +253 0.339048 0.6825 +234 0.325442 0.6825 +SURF 0x30 +mat 2 +refs 4 +234 0.325442 0.6825 +253 0.339048 0.6825 +254 0.326625 0.635 +235 0.311869 0.635 +SURF 0x30 +mat 2 +refs 4 +235 0.311869 0.635 +254 0.326625 0.635 +255 0.283153 0.555 +236 0.264361 0.555 +SURF 0x30 +mat 2 +refs 4 +236 0.264361 0.555 +255 0.283153 0.555 +256 0.244574 0.475 +237 0.222207 0.475 +SURF 0x30 +mat 2 +refs 4 +237 0.222207 0.475 +256 0.244574 0.475 +257 0.224518 0.3875 +238 0.198966 0.3875 +SURF 0x30 +mat 2 +refs 4 +238 0.198966 0.3875 +257 0.224518 0.3875 +258 0.200362 0.31 +239 0.172571 0.31 +SURF 0x30 +mat 2 +refs 4 +239 0.172571 0.31 +258 0.200362 0.31 +259 0.204387 0.247501 +240 0.17697 0.247501 +SURF 0x30 +mat 2 +refs 4 +240 0.17697 0.247501 +259 0.204387 0.247501 +260 0.212438 0.175 +241 0.185767 0.175 +SURF 0x30 +mat 2 +refs 4 +241 0.185767 0.175 +260 0.212438 0.175 +261 0.236594 0.105001 +242 0.212162 0.105001 +SURF 0x30 +mat 2 +refs 4 +242 0.212162 0.105001 +261 0.236594 0.105001 +262 0.298989 0.0549999 +243 0.280349 0.0549999 +SURF 0x30 +mat 2 +refs 4 +243 0.280349 0.0549999 +262 0.298989 0.0549999 +263 0.357362 0.0200004 +244 0.344133 0.0200004 +SURF 0x30 +mat 2 +refs 4 +244 0.344133 0.0200004 +263 0.357362 0.0200004 +264 0.443914 0 +245 0.438711 0 +SURF 0x30 +mat 2 +refs 4 +245 0.438711 0 +264 0.443914 0 +265 0.496247 0 +246 0.495901 0 +SURF 0x30 +mat 2 +refs 4 +247 0.477751 1 +266 0.478535 1 +267 0.454254 0.994999 +248 0.450838 0.994999 +SURF 0x30 +mat 2 +refs 4 +248 0.450838 0.994999 +267 0.454254 0.994999 +268 0.43371 0.984998 +249 0.428064 0.984998 +SURF 0x30 +mat 2 +refs 4 +249 0.428064 0.984998 +268 0.43371 0.984998 +269 0.38702 0.952498 +250 0.376312 0.952498 +SURF 0x30 +mat 2 +refs 4 +250 0.376312 0.952498 +269 0.38702 0.952498 +270 0.373945 0.929999 +251 0.361818 0.929999 +SURF 0x30 +mat 2 +refs 4 +251 0.361818 0.929999 +270 0.373945 0.929999 +271 0.36274 0.8825 +252 0.349399 0.8825 +SURF 0x30 +mat 2 +refs 4 +252 0.349399 0.8825 +271 0.36274 0.8825 +272 0.353401 0.6825 +253 0.339048 0.6825 +SURF 0x30 +mat 2 +refs 4 +253 0.339048 0.6825 +272 0.353401 0.6825 +273 0.342196 0.635 +254 0.326625 0.635 +SURF 0x30 +mat 2 +refs 4 +254 0.326625 0.635 +273 0.342196 0.635 +274 0.302978 0.555 +255 0.283153 0.555 +SURF 0x30 +mat 2 +refs 4 +255 0.283153 0.555 +274 0.302978 0.555 +275 0.268175 0.475 +256 0.244574 0.475 +SURF 0x30 +mat 2 +refs 4 +256 0.244574 0.475 +275 0.268175 0.475 +276 0.251471 0.3875 +257 0.224518 0.3875 +SURF 0x30 +mat 2 +refs 4 +257 0.224518 0.3875 +276 0.251471 0.3875 +277 0.22968 0.31 +258 0.200362 0.31 +SURF 0x30 +mat 2 +refs 4 +258 0.200362 0.31 +277 0.22968 0.31 +278 0.233312 0.247501 +259 0.204387 0.247501 +SURF 0x30 +mat 2 +refs 4 +259 0.204387 0.247501 +278 0.233312 0.247501 +279 0.240575 0.175 +260 0.212438 0.175 +SURF 0x30 +mat 2 +refs 4 +260 0.212438 0.175 +279 0.240575 0.175 +280 0.262367 0.105001 +261 0.236594 0.105001 +SURF 0x30 +mat 2 +refs 4 +261 0.236594 0.105001 +280 0.262367 0.105001 +281 0.318659 0.0549999 +262 0.298989 0.0549999 +SURF 0x30 +mat 2 +refs 4 +262 0.298989 0.0549999 +281 0.318659 0.0549999 +282 0.371318 0.0200004 +263 0.357362 0.0200004 +SURF 0x30 +mat 2 +refs 4 +263 0.357362 0.0200004 +282 0.371318 0.0200004 +283 0.449402 0 +264 0.443914 0 +SURF 0x30 +mat 2 +refs 4 +264 0.443914 0 +283 0.449402 0 +284 0.496614 0 +265 0.496247 0 +SURF 0x30 +mat 2 +refs 4 +266 0.478535 1 +285 0.479352 1 +286 0.457829 0.994999 +267 0.454254 0.994999 +SURF 0x30 +mat 2 +refs 4 +267 0.454254 0.994999 +286 0.457829 0.994999 +287 0.439619 0.984998 +268 0.43371 0.984998 +SURF 0x30 +mat 2 +refs 4 +268 0.43371 0.984998 +287 0.439619 0.984998 +288 0.398232 0.952498 +269 0.38702 0.952498 +SURF 0x30 +mat 2 +refs 4 +269 0.38702 0.952498 +288 0.398232 0.952498 +289 0.386643 0.929999 +270 0.373945 0.929999 +SURF 0x30 +mat 2 +refs 4 +270 0.373945 0.929999 +289 0.386643 0.929999 +290 0.376709 0.8825 +271 0.36274 0.8825 +SURF 0x30 +mat 2 +refs 4 +271 0.36274 0.8825 +290 0.376709 0.8825 +291 0.36843 0.6825 +272 0.353401 0.6825 +SURF 0x30 +mat 2 +refs 4 +272 0.353401 0.6825 +291 0.36843 0.6825 +292 0.358496 0.635 +273 0.342196 0.635 +SURF 0x30 +mat 2 +refs 4 +273 0.342196 0.635 +292 0.358496 0.635 +293 0.32373 0.555 +274 0.302978 0.555 +SURF 0x30 +mat 2 +refs 4 +274 0.302978 0.555 +293 0.32373 0.555 +294 0.292879 0.475 +275 0.268175 0.475 +SURF 0x30 +mat 2 +refs 4 +275 0.268175 0.475 +294 0.292879 0.475 +295 0.279693 0.3875 +276 0.251471 0.3875 +SURF 0x30 +mat 2 +refs 4 +276 0.251471 0.3875 +295 0.279693 0.3875 +296 0.260376 0.31 +277 0.22968 0.31 +SURF 0x30 +mat 2 +refs 4 +277 0.22968 0.31 +296 0.260376 0.31 +297 0.263595 0.247501 +278 0.233312 0.247501 +SURF 0x30 +mat 2 +refs 4 +278 0.233312 0.247501 +297 0.263595 0.247501 +298 0.270035 0.175 +279 0.240575 0.175 +SURF 0x30 +mat 2 +refs 4 +279 0.240575 0.175 +298 0.270035 0.175 +299 0.289351 0.105001 +280 0.262367 0.105001 +SURF 0x30 +mat 2 +refs 4 +280 0.262367 0.105001 +299 0.289351 0.105001 +300 0.33925 0.0549999 +281 0.318659 0.0549999 +SURF 0x30 +mat 2 +refs 4 +281 0.318659 0.0549999 +300 0.33925 0.0549999 +301 0.38593 0.0200004 +282 0.371318 0.0200004 +SURF 0x30 +mat 2 +refs 4 +282 0.371318 0.0200004 +301 0.38593 0.0200004 +302 0.455149 0 +283 0.449402 0 +SURF 0x30 +mat 2 +refs 4 +283 0.449402 0 +302 0.455149 0 +303 0.497 0 +284 0.496614 0 +SURF 0x30 +mat 2 +refs 4 +285 0.479352 1 +304 0.480206 1 +305 0.461549 0.994999 +286 0.457829 0.994999 +SURF 0x30 +mat 2 +refs 4 +286 0.457829 0.994999 +305 0.461549 0.994999 +306 0.445763 0.984998 +287 0.439619 0.984998 +SURF 0x30 +mat 2 +refs 4 +287 0.439619 0.984998 +306 0.445763 0.984998 +307 0.409888 0.952498 +288 0.398232 0.952498 +SURF 0x30 +mat 2 +refs 4 +288 0.398232 0.952498 +307 0.409888 0.952498 +308 0.399843 0.929999 +289 0.386643 0.929999 +SURF 0x30 +mat 2 +refs 4 +289 0.386643 0.929999 +308 0.399843 0.929999 +309 0.391234 0.8825 +290 0.376709 0.8825 +SURF 0x30 +mat 2 +refs 4 +290 0.376709 0.8825 +309 0.391234 0.8825 +310 0.384057 0.6825 +291 0.36843 0.6825 +SURF 0x30 +mat 2 +refs 4 +291 0.36843 0.6825 +310 0.384057 0.6825 +311 0.375448 0.635 +292 0.358496 0.635 +SURF 0x30 +mat 2 +refs 4 +292 0.358496 0.635 +311 0.375448 0.635 +312 0.34531 0.555 +293 0.32373 0.555 +SURF 0x30 +mat 2 +refs 4 +293 0.32373 0.555 +312 0.34531 0.555 +313 0.318571 0.475 +294 0.292879 0.475 +SURF 0x30 +mat 2 +refs 4 +294 0.292879 0.475 +313 0.318571 0.475 +314 0.309037 0.3875 +295 0.279693 0.3875 +SURF 0x30 +mat 2 +refs 4 +295 0.279693 0.3875 +314 0.309037 0.3875 +315 0.292294 0.31 +296 0.260376 0.31 +SURF 0x30 +mat 2 +refs 4 +296 0.260376 0.31 +315 0.292294 0.31 +316 0.295085 0.247501 +297 0.263595 0.247501 +SURF 0x30 +mat 2 +refs 4 +297 0.263595 0.247501 +316 0.295085 0.247501 +317 0.300664 0.175 +298 0.270035 0.175 +SURF 0x30 +mat 2 +refs 4 +298 0.270035 0.175 +317 0.300664 0.175 +318 0.317408 0.105001 +299 0.289351 0.105001 +SURF 0x30 +mat 2 +refs 4 +299 0.289351 0.105001 +318 0.317408 0.105001 +319 0.360661 0.0549999 +300 0.33925 0.0549999 +SURF 0x30 +mat 2 +refs 4 +300 0.33925 0.0549999 +319 0.360661 0.0549999 +320 0.401124 0.0200004 +301 0.38593 0.0200004 +SURF 0x30 +mat 2 +refs 4 +301 0.38593 0.0200004 +320 0.401124 0.0200004 +321 0.461121 0 +302 0.455149 0 +SURF 0x30 +mat 2 +refs 4 +302 0.455149 0 +321 0.461121 0 +322 0.4974 0 +303 0.497 0 +SURF 0x30 +mat 2 +refs 4 +304 0.480206 1 +323 0.481087 1 +324 0.465392 0.994999 +305 0.461549 0.994999 +SURF 0x30 +mat 2 +refs 4 +305 0.461549 0.994999 +324 0.465392 0.994999 +325 0.452112 0.984998 +306 0.445763 0.984998 +SURF 0x30 +mat 2 +refs 4 +306 0.445763 0.984998 +325 0.452112 0.984998 +326 0.42193 0.952498 +307 0.409888 0.952498 +SURF 0x30 +mat 2 +refs 4 +307 0.409888 0.952498 +326 0.42193 0.952498 +327 0.413483 0.929999 +308 0.399843 0.929999 +SURF 0x30 +mat 2 +refs 4 +308 0.399843 0.929999 +327 0.413483 0.929999 +328 0.406239 0.8825 +309 0.391234 0.8825 +SURF 0x30 +mat 2 +refs 4 +309 0.391234 0.8825 +328 0.406239 0.8825 +329 0.400202 0.6825 +310 0.384057 0.6825 +SURF 0x30 +mat 2 +refs 4 +310 0.384057 0.6825 +329 0.400202 0.6825 +330 0.392959 0.635 +311 0.375448 0.635 +SURF 0x30 +mat 2 +refs 4 +311 0.375448 0.635 +330 0.392959 0.635 +331 0.367606 0.555 +312 0.34531 0.555 +SURF 0x30 +mat 2 +refs 4 +312 0.34531 0.555 +331 0.367606 0.555 +332 0.345111 0.475 +313 0.318571 0.475 +SURF 0x30 +mat 2 +refs 4 +313 0.318571 0.475 +332 0.345111 0.475 +333 0.339354 0.3875 +314 0.309037 0.3875 +SURF 0x30 +mat 2 +refs 4 +314 0.309037 0.3875 +333 0.339354 0.3875 +334 0.32527 0.31 +315 0.292294 0.31 +SURF 0x30 +mat 2 +refs 4 +315 0.292294 0.31 +334 0.32527 0.31 +335 0.327618 0.247501 +316 0.295085 0.247501 +SURF 0x30 +mat 2 +refs 4 +316 0.295085 0.247501 +335 0.327618 0.247501 +336 0.332312 0.175 +317 0.300664 0.175 +SURF 0x30 +mat 2 +refs 4 +317 0.300664 0.175 +336 0.332312 0.175 +337 0.346396 0.105001 +318 0.317408 0.105001 +SURF 0x30 +mat 2 +refs 4 +318 0.317408 0.105001 +337 0.346396 0.105001 +338 0.382783 0.0549999 +319 0.360661 0.0549999 +SURF 0x30 +mat 2 +refs 4 +319 0.360661 0.0549999 +338 0.382783 0.0549999 +339 0.416822 0.0200004 +320 0.401124 0.0200004 +SURF 0x30 +mat 2 +refs 4 +320 0.401124 0.0200004 +339 0.416822 0.0200004 +340 0.467292 0 +321 0.461121 0 +SURF 0x30 +mat 2 +refs 4 +321 0.461121 0 +340 0.467292 0 +341 0.497811 0 +322 0.4974 0 +SURF 0x30 +mat 2 +refs 4 +323 0.481087 1 +342 0.481988 1 +343 0.469337 0.994999 +324 0.465392 0.994999 +SURF 0x30 +mat 2 +refs 4 +324 0.465392 0.994999 +343 0.469337 0.994999 +344 0.458633 0.984998 +325 0.452112 0.984998 +SURF 0x30 +mat 2 +refs 4 +325 0.452112 0.984998 +344 0.458633 0.984998 +345 0.434302 0.952498 +326 0.42193 0.952498 +SURF 0x30 +mat 2 +refs 4 +326 0.42193 0.952498 +345 0.434302 0.952498 +346 0.427489 0.929999 +327 0.413483 0.929999 +SURF 0x30 +mat 2 +refs 4 +327 0.413483 0.929999 +346 0.427489 0.929999 +347 0.421648 0.8825 +328 0.406239 0.8825 +SURF 0x30 +mat 2 +refs 4 +328 0.406239 0.8825 +347 0.421648 0.8825 +348 0.416782 0.6825 +329 0.400202 0.6825 +SURF 0x30 +mat 2 +refs 4 +329 0.400202 0.6825 +348 0.416782 0.6825 +349 0.410944 0.635 +330 0.392959 0.635 +SURF 0x30 +mat 2 +refs 4 +330 0.392959 0.635 +349 0.410944 0.635 +350 0.390504 0.555 +331 0.367606 0.555 +SURF 0x30 +mat 2 +refs 4 +331 0.367606 0.555 +350 0.390504 0.555 +351 0.372371 0.475 +332 0.345111 0.475 +SURF 0x30 +mat 2 +refs 4 +332 0.345111 0.475 +351 0.372371 0.475 +352 0.370491 0.3875 +333 0.339354 0.3875 +SURF 0x30 +mat 2 +refs 4 +333 0.339354 0.3875 +352 0.370491 0.3875 +353 0.359135 0.31 +334 0.32527 0.31 +SURF 0x30 +mat 2 +refs 4 +334 0.32527 0.31 +353 0.359135 0.31 +354 0.361028 0.247501 +335 0.327618 0.247501 +SURF 0x30 +mat 2 +refs 4 +335 0.327618 0.247501 +354 0.361028 0.247501 +355 0.364811 0.175 +336 0.332312 0.175 +SURF 0x30 +mat 2 +refs 4 +336 0.332312 0.175 +355 0.364811 0.175 +356 0.376168 0.105001 +337 0.346396 0.105001 +SURF 0x30 +mat 2 +refs 4 +337 0.346396 0.105001 +356 0.376168 0.105001 +357 0.405502 0.0549999 +338 0.382783 0.0549999 +SURF 0x30 +mat 2 +refs 4 +338 0.382783 0.0549999 +357 0.405502 0.0549999 +358 0.432944 0.0200004 +339 0.416822 0.0200004 +SURF 0x30 +mat 2 +refs 4 +339 0.416822 0.0200004 +358 0.432944 0.0200004 +359 0.473631 0 +340 0.467292 0 +SURF 0x30 +mat 2 +refs 4 +340 0.467292 0 +359 0.473631 0 +360 0.498235 0 +341 0.497811 0 +SURF 0x30 +mat 2 +refs 4 +342 0.481988 1 +361 0.482913 1 +362 0.473366 0.994999 +343 0.469337 0.994999 +SURF 0x30 +mat 2 +refs 4 +343 0.469337 0.994999 +362 0.473366 0.994999 +363 0.465291 0.984998 +344 0.458633 0.984998 +SURF 0x30 +mat 2 +refs 4 +344 0.458633 0.984998 +363 0.465291 0.984998 +364 0.446933 0.952498 +345 0.434302 0.952498 +SURF 0x30 +mat 2 +refs 4 +345 0.434302 0.952498 +364 0.446933 0.952498 +365 0.441792 0.929999 +346 0.427489 0.929999 +SURF 0x30 +mat 2 +refs 4 +346 0.427489 0.929999 +365 0.441792 0.929999 +366 0.437386 0.8825 +347 0.421648 0.8825 +SURF 0x30 +mat 2 +refs 4 +347 0.421648 0.8825 +366 0.437386 0.8825 +367 0.433714 0.6825 +348 0.416782 0.6825 +SURF 0x30 +mat 2 +refs 4 +348 0.416782 0.6825 +367 0.433714 0.6825 +368 0.429308 0.635 +349 0.410944 0.635 +SURF 0x30 +mat 2 +refs 4 +349 0.410944 0.635 +368 0.429308 0.635 +369 0.413889 0.555 +350 0.390504 0.555 +SURF 0x30 +mat 2 +refs 4 +350 0.390504 0.555 +369 0.413889 0.555 +370 0.400206 0.475 +351 0.372371 0.475 +SURF 0x30 +mat 2 +refs 4 +351 0.372371 0.475 +370 0.400206 0.475 +371 0.402284 0.3875 +352 0.370491 0.3875 +SURF 0x30 +mat 2 +refs 4 +352 0.370491 0.3875 +371 0.402284 0.3875 +372 0.393719 0.31 +353 0.359135 0.31 +SURF 0x30 +mat 2 +refs 4 +353 0.359135 0.31 +372 0.393719 0.31 +373 0.395145 0.247501 +354 0.361028 0.247501 +SURF 0x30 +mat 2 +refs 4 +354 0.361028 0.247501 +373 0.395145 0.247501 +374 0.398003 0.175 +355 0.364811 0.175 +SURF 0x30 +mat 2 +refs 4 +355 0.364811 0.175 +374 0.398003 0.175 +375 0.406568 0.105001 +356 0.376168 0.105001 +SURF 0x30 +mat 2 +refs 4 +356 0.376168 0.105001 +375 0.406568 0.105001 +376 0.428703 0.0549999 +357 0.405502 0.0549999 +SURF 0x30 +mat 2 +refs 4 +357 0.405502 0.0549999 +376 0.428703 0.0549999 +377 0.449405 0.0200004 +358 0.432944 0.0200004 +SURF 0x30 +mat 2 +refs 4 +358 0.432944 0.0200004 +377 0.449405 0.0200004 +378 0.480105 0 +359 0.473631 0 +SURF 0x30 +mat 2 +refs 4 +359 0.473631 0 +378 0.480105 0 +379 0.498668 0 +360 0.498235 0 +SURF 0x30 +mat 2 +refs 4 +361 0.482913 1 +380 0.483851 1 +381 0.477458 0.994999 +362 0.473366 0.994999 +SURF 0x30 +mat 2 +refs 4 +362 0.473366 0.994999 +381 0.477458 0.994999 +382 0.472051 0.984998 +363 0.465291 0.984998 +SURF 0x30 +mat 2 +refs 4 +363 0.465291 0.984998 +382 0.472051 0.984998 +383 0.459763 0.952498 +364 0.446933 0.952498 +SURF 0x30 +mat 2 +refs 4 +364 0.446933 0.952498 +383 0.459763 0.952498 +384 0.456319 0.929999 +365 0.441792 0.929999 +SURF 0x30 +mat 2 +refs 4 +365 0.441792 0.929999 +384 0.456319 0.929999 +385 0.45337 0.8825 +366 0.437386 0.8825 +SURF 0x30 +mat 2 +refs 4 +366 0.437386 0.8825 +385 0.45337 0.8825 +386 0.450912 0.6825 +367 0.433714 0.6825 +SURF 0x30 +mat 2 +refs 4 +367 0.433714 0.6825 +386 0.450912 0.6825 +387 0.447962 0.635 +368 0.429308 0.635 +SURF 0x30 +mat 2 +refs 4 +368 0.429308 0.635 +387 0.447962 0.635 +388 0.437638 0.555 +369 0.413889 0.555 +SURF 0x30 +mat 2 +refs 4 +369 0.413889 0.555 +388 0.437638 0.555 +389 0.428478 0.475 +370 0.400206 0.475 +SURF 0x30 +mat 2 +refs 4 +370 0.400206 0.475 +389 0.428478 0.475 +390 0.434578 0.3875 +371 0.402284 0.3875 +SURF 0x30 +mat 2 +refs 4 +371 0.402284 0.3875 +390 0.434578 0.3875 +391 0.428844 0.31 +372 0.393719 0.31 +SURF 0x30 +mat 2 +refs 4 +372 0.393719 0.31 +391 0.428844 0.31 +392 0.429799 0.247501 +373 0.395145 0.247501 +SURF 0x30 +mat 2 +refs 4 +373 0.395145 0.247501 +392 0.429799 0.247501 +393 0.431713 0.175 +374 0.398003 0.175 +SURF 0x30 +mat 2 +refs 4 +374 0.398003 0.175 +393 0.431713 0.175 +394 0.437447 0.105001 +375 0.406568 0.105001 +SURF 0x30 +mat 2 +refs 4 +375 0.406568 0.105001 +394 0.437447 0.105001 +395 0.452267 0.0549999 +376 0.428703 0.0549999 +SURF 0x30 +mat 2 +refs 4 +376 0.428703 0.0549999 +395 0.452267 0.0549999 +396 0.466129 0.0200004 +377 0.449405 0.0200004 +SURF 0x30 +mat 2 +refs 4 +377 0.449405 0.0200004 +396 0.466129 0.0200004 +397 0.486683 0 +378 0.480105 0 +SURF 0x30 +mat 2 +refs 4 +378 0.480105 0 +397 0.486683 0 +398 0.499109 0 +379 0.498668 0 +SURF 0x30 +mat 2 +refs 4 +380 0.483851 1 +399 0.4848 1 +400 0.481595 0.994999 +381 0.477458 0.994999 +SURF 0x30 +mat 2 +refs 4 +381 0.477458 0.994999 +400 0.481595 0.994999 +401 0.478884 0.984998 +382 0.472051 0.984998 +SURF 0x30 +mat 2 +refs 4 +382 0.472051 0.984998 +401 0.478884 0.984998 +402 0.472724 0.952498 +383 0.459763 0.952498 +SURF 0x30 +mat 2 +refs 4 +383 0.459763 0.952498 +402 0.472724 0.952498 +403 0.470998 0.929999 +384 0.456319 0.929999 +SURF 0x30 +mat 2 +refs 4 +384 0.456319 0.929999 +403 0.470998 0.929999 +404 0.469519 0.8825 +385 0.45337 0.8825 +SURF 0x30 +mat 2 +refs 4 +385 0.45337 0.8825 +404 0.469519 0.8825 +405 0.468288 0.6825 +386 0.450912 0.6825 +SURF 0x30 +mat 2 +refs 4 +386 0.450912 0.6825 +405 0.468288 0.6825 +406 0.466808 0.635 +387 0.447962 0.635 +SURF 0x30 +mat 2 +refs 4 +387 0.447962 0.635 +406 0.466808 0.635 +407 0.461633 0.555 +388 0.437638 0.555 +SURF 0x30 +mat 2 +refs 4 +388 0.437638 0.555 +407 0.461633 0.555 +408 0.457042 0.475 +389 0.428478 0.475 +SURF 0x30 +mat 2 +refs 4 +389 0.428478 0.475 +408 0.457042 0.475 +409 0.467205 0.3875 +390 0.434578 0.3875 +SURF 0x30 +mat 2 +refs 4 +390 0.434578 0.3875 +409 0.467205 0.3875 +410 0.46433 0.31 +391 0.428844 0.31 +SURF 0x30 +mat 2 +refs 4 +391 0.428844 0.31 +410 0.46433 0.31 +411 0.464811 0.247501 +392 0.429799 0.247501 +SURF 0x30 +mat 2 +refs 4 +392 0.429799 0.247501 +411 0.464811 0.247501 +412 0.465769 0.175 +393 0.431713 0.175 +SURF 0x30 +mat 2 +refs 4 +393 0.431713 0.175 +412 0.465769 0.175 +413 0.468644 0.105001 +394 0.437447 0.105001 +SURF 0x30 +mat 2 +refs 4 +394 0.437447 0.105001 +413 0.468644 0.105001 +414 0.476073 0.0549999 +395 0.452267 0.0549999 +SURF 0x30 +mat 2 +refs 4 +395 0.452267 0.0549999 +414 0.476073 0.0549999 +415 0.483021 0.0200004 +396 0.466129 0.0200004 +SURF 0x30 +mat 2 +refs 4 +396 0.466129 0.0200004 +415 0.483021 0.0200004 +416 0.493325 0 +397 0.486683 0 +SURF 0x30 +mat 2 +refs 4 +397 0.486683 0 +416 0.493325 0 +417 0.499553 0 +398 0.499109 0 +SURF 0x30 +mat 2 +refs 4 +399 0.4848 1 +418 0.485751 1 +419 0.485751 0.994999 +400 0.481595 0.994999 +SURF 0x30 +mat 2 +refs 4 +400 0.481595 0.994999 +419 0.485751 0.994999 +420 0.485751 0.984998 +401 0.478884 0.984998 +SURF 0x30 +mat 2 +refs 4 +401 0.478884 0.984998 +420 0.485751 0.984998 +421 0.485751 0.952498 +402 0.472724 0.952498 +SURF 0x30 +mat 2 +refs 4 +402 0.472724 0.952498 +421 0.485751 0.952498 +422 0.485751 0.929999 +403 0.470998 0.929999 +SURF 0x30 +mat 2 +refs 4 +403 0.470998 0.929999 +422 0.485751 0.929999 +423 0.485751 0.8825 +404 0.469519 0.8825 +SURF 0x30 +mat 2 +refs 4 +404 0.469519 0.8825 +423 0.485751 0.8825 +424 0.485751 0.6825 +405 0.468288 0.6825 +SURF 0x30 +mat 2 +refs 4 +405 0.468288 0.6825 +424 0.485751 0.6825 +425 0.485751 0.635 +406 0.466808 0.635 +SURF 0x30 +mat 2 +refs 4 +406 0.466808 0.635 +425 0.485751 0.635 +426 0.485751 0.555 +407 0.461633 0.555 +SURF 0x30 +mat 2 +refs 4 +407 0.461633 0.555 +426 0.485751 0.555 +427 0.485751 0.475 +408 0.457042 0.475 +SURF 0x30 +mat 2 +refs 4 +408 0.457042 0.475 +427 0.485751 0.475 +428 0.5 0.3875 +409 0.467205 0.3875 +SURF 0x30 +mat 2 +refs 4 +409 0.467205 0.3875 +428 0.5 0.3875 +429 0.5 0.31 +410 0.46433 0.31 +SURF 0x30 +mat 2 +refs 4 +410 0.46433 0.31 +429 0.5 0.31 +430 0.5 0.247501 +411 0.464811 0.247501 +SURF 0x30 +mat 2 +refs 4 +411 0.464811 0.247501 +430 0.5 0.247501 +431 0.5 0.175 +412 0.465769 0.175 +SURF 0x30 +mat 2 +refs 4 +412 0.465769 0.175 +431 0.5 0.175 +432 0.5 0.105001 +413 0.468644 0.105001 +SURF 0x30 +mat 2 +refs 4 +413 0.468644 0.105001 +432 0.5 0.105001 +433 0.5 0.0549999 +414 0.476073 0.0549999 +SURF 0x30 +mat 2 +refs 4 +414 0.476073 0.0549999 +433 0.5 0.0549999 +434 0.5 0.0200004 +415 0.483021 0.0200004 +SURF 0x30 +mat 2 +refs 4 +415 0.483021 0.0200004 +434 0.5 0.0200004 +435 0.5 0 +416 0.493325 0 +SURF 0x30 +mat 2 +refs 4 +416 0.493325 0 +435 0.5 0 +436 0.5 0 +417 0.499553 0 +SURF 0x30 +mat 2 +refs 4 +418 0.485751 1 +437 0.486703 1 +438 0.489908 0.994999 +419 0.485751 0.994999 +SURF 0x30 +mat 2 +refs 4 +419 0.485751 0.994999 +438 0.489908 0.994999 +439 0.492618 0.984998 +420 0.485751 0.984998 +SURF 0x30 +mat 2 +refs 4 +420 0.485751 0.984998 +439 0.492618 0.984998 +440 0.498779 0.952498 +421 0.485751 0.952498 +SURF 0x30 +mat 2 +refs 4 +421 0.485751 0.952498 +440 0.498779 0.952498 +441 0.500504 0.929999 +422 0.485751 0.929999 +SURF 0x30 +mat 2 +refs 4 +422 0.485751 0.929999 +441 0.500504 0.929999 +442 0.501984 0.8825 +423 0.485751 0.8825 +SURF 0x30 +mat 2 +refs 4 +423 0.485751 0.8825 +442 0.501984 0.8825 +443 0.503215 0.6825 +424 0.485751 0.6825 +SURF 0x30 +mat 2 +refs 4 +424 0.485751 0.6825 +443 0.503215 0.6825 +444 0.504695 0.635 +425 0.485751 0.635 +SURF 0x30 +mat 2 +refs 4 +425 0.485751 0.635 +444 0.504695 0.635 +445 0.50987 0.555 +426 0.485751 0.555 +SURF 0x30 +mat 2 +refs 4 +426 0.485751 0.555 +445 0.50987 0.555 +446 0.514461 0.475 +427 0.485751 0.475 +SURF 0x30 +mat 2 +refs 4 +427 0.485751 0.475 +446 0.514461 0.475 +447 0.532795 0.3875 +428 0.5 0.3875 +SURF 0x30 +mat 2 +refs 4 +428 0.5 0.3875 +447 0.532795 0.3875 +448 0.53567 0.31 +429 0.5 0.31 +SURF 0x30 +mat 2 +refs 4 +429 0.5 0.31 +448 0.53567 0.31 +449 0.535189 0.247501 +430 0.5 0.247501 +SURF 0x30 +mat 2 +refs 4 +430 0.5 0.247501 +449 0.535189 0.247501 +450 0.534231 0.175 +431 0.5 0.175 +SURF 0x30 +mat 2 +refs 4 +431 0.5 0.175 +450 0.534231 0.175 +451 0.531356 0.105001 +432 0.5 0.105001 +SURF 0x30 +mat 2 +refs 4 +432 0.5 0.105001 +451 0.531356 0.105001 +452 0.52393 0.0549999 +433 0.5 0.0549999 +SURF 0x30 +mat 2 +refs 4 +433 0.5 0.0549999 +452 0.52393 0.0549999 +453 0.516979 0.0200004 +434 0.5 0.0200004 +SURF 0x30 +mat 2 +refs 4 +434 0.5 0.0200004 +453 0.516979 0.0200004 +454 0.506679 0 +435 0.5 0 +SURF 0x30 +mat 2 +refs 4 +435 0.5 0 +454 0.506679 0 +455 0.500447 0 +436 0.5 0 +SURF 0x30 +mat 2 +refs 4 +437 0.486703 1 +456 0.487651 1 +457 0.494041 0.994999 +438 0.489908 0.994999 +SURF 0x30 +mat 2 +refs 4 +438 0.489908 0.994999 +457 0.494041 0.994999 +458 0.499449 0.984998 +439 0.492618 0.984998 +SURF 0x30 +mat 2 +refs 4 +439 0.492618 0.984998 +458 0.499449 0.984998 +459 0.51174 0.952498 +440 0.498779 0.952498 +SURF 0x30 +mat 2 +refs 4 +440 0.498779 0.952498 +459 0.51174 0.952498 +460 0.51518 0.929999 +441 0.500504 0.929999 +SURF 0x30 +mat 2 +refs 4 +441 0.500504 0.929999 +460 0.51518 0.929999 +461 0.518133 0.8825 +442 0.501984 0.8825 +SURF 0x30 +mat 2 +refs 4 +442 0.501984 0.8825 +461 0.518133 0.8825 +462 0.520591 0.6825 +443 0.503215 0.6825 +SURF 0x30 +mat 2 +refs 4 +443 0.503215 0.6825 +462 0.520591 0.6825 +463 0.52354 0.635 +444 0.504695 0.635 +SURF 0x30 +mat 2 +refs 4 +444 0.504695 0.635 +463 0.52354 0.635 +464 0.533864 0.555 +445 0.50987 0.555 +SURF 0x30 +mat 2 +refs 4 +445 0.50987 0.555 +464 0.533864 0.555 +465 0.543025 0.475 +446 0.514461 0.475 +SURF 0x30 +mat 2 +refs 4 +446 0.514461 0.475 +465 0.543025 0.475 +466 0.565422 0.3875 +447 0.532795 0.3875 +SURF 0x30 +mat 2 +refs 4 +447 0.532795 0.3875 +466 0.565422 0.3875 +467 0.571159 0.31 +448 0.53567 0.31 +SURF 0x30 +mat 2 +refs 4 +448 0.53567 0.31 +467 0.571159 0.31 +468 0.570201 0.247501 +449 0.535189 0.247501 +SURF 0x30 +mat 2 +refs 4 +449 0.535189 0.247501 +468 0.570201 0.247501 +469 0.568291 0.175 +450 0.534231 0.175 +SURF 0x30 +mat 2 +refs 4 +450 0.534231 0.175 +469 0.568291 0.175 +470 0.562553 0.105001 +451 0.531356 0.105001 +SURF 0x30 +mat 2 +refs 4 +451 0.531356 0.105001 +470 0.562553 0.105001 +471 0.547736 0.0549999 +452 0.52393 0.0549999 +SURF 0x30 +mat 2 +refs 4 +452 0.52393 0.0549999 +471 0.547736 0.0549999 +472 0.533875 0.0200004 +453 0.516979 0.0200004 +SURF 0x30 +mat 2 +refs 4 +453 0.516979 0.0200004 +472 0.533875 0.0200004 +473 0.513321 0 +454 0.506679 0 +SURF 0x30 +mat 2 +refs 4 +454 0.506679 0 +473 0.513321 0 +474 0.500891 0 +455 0.500447 0 +SURF 0x30 +mat 2 +refs 4 +456 0.487651 1 +475 0.48859 1 +476 0.498134 0.994999 +457 0.494041 0.994999 +SURF 0x30 +mat 2 +refs 4 +457 0.494041 0.994999 +476 0.498134 0.994999 +477 0.506211 0.984998 +458 0.499449 0.984998 +SURF 0x30 +mat 2 +refs 4 +458 0.499449 0.984998 +477 0.506211 0.984998 +478 0.524569 0.952498 +459 0.51174 0.952498 +SURF 0x30 +mat 2 +refs 4 +459 0.51174 0.952498 +478 0.524569 0.952498 +479 0.529708 0.929999 +460 0.51518 0.929999 +SURF 0x30 +mat 2 +refs 4 +460 0.51518 0.929999 +479 0.529708 0.929999 +480 0.534117 0.8825 +461 0.518133 0.8825 +SURF 0x30 +mat 2 +refs 4 +461 0.518133 0.8825 +480 0.534117 0.8825 +481 0.537786 0.6825 +462 0.520591 0.6825 +SURF 0x30 +mat 2 +refs 4 +462 0.520591 0.6825 +481 0.537786 0.6825 +482 0.542191 0.635 +463 0.52354 0.635 +SURF 0x30 +mat 2 +refs 4 +463 0.52354 0.635 +482 0.542191 0.635 +483 0.557613 0.555 +464 0.533864 0.555 +SURF 0x30 +mat 2 +refs 4 +464 0.533864 0.555 +483 0.557613 0.555 +484 0.571297 0.475 +465 0.543025 0.475 +SURF 0x30 +mat 2 +refs 4 +465 0.543025 0.475 +484 0.571297 0.475 +485 0.597716 0.3875 +466 0.565422 0.3875 +SURF 0x30 +mat 2 +refs 4 +466 0.565422 0.3875 +485 0.597716 0.3875 +486 0.606285 0.31 +467 0.571159 0.31 +SURF 0x30 +mat 2 +refs 4 +467 0.571159 0.31 +486 0.606285 0.31 +487 0.604855 0.247501 +468 0.570201 0.247501 +SURF 0x30 +mat 2 +refs 4 +468 0.570201 0.247501 +487 0.604855 0.247501 +488 0.602 0.175 +469 0.568291 0.175 +SURF 0x30 +mat 2 +refs 4 +469 0.568291 0.175 +488 0.602 0.175 +489 0.593432 0.105001 +470 0.562553 0.105001 +SURF 0x30 +mat 2 +refs 4 +470 0.562553 0.105001 +489 0.593432 0.105001 +490 0.5713 0.0549999 +471 0.547736 0.0549999 +SURF 0x30 +mat 2 +refs 4 +471 0.547736 0.0549999 +490 0.5713 0.0549999 +491 0.550595 0.0200004 +472 0.533875 0.0200004 +SURF 0x30 +mat 2 +refs 4 +472 0.533875 0.0200004 +491 0.550595 0.0200004 +492 0.519895 0 +473 0.513321 0 +SURF 0x30 +mat 2 +refs 4 +473 0.513321 0 +492 0.519895 0 +493 0.501332 0 +474 0.500891 0 +SURF 0x30 +mat 2 +refs 4 +475 0.48859 1 +494 0.489511 1 +495 0.502166 0.994999 +476 0.498134 0.994999 +SURF 0x30 +mat 2 +refs 4 +476 0.498134 0.994999 +495 0.502166 0.994999 +496 0.51287 0.984998 +477 0.506211 0.984998 +SURF 0x30 +mat 2 +refs 4 +477 0.506211 0.984998 +496 0.51287 0.984998 +497 0.537201 0.952498 +478 0.524569 0.952498 +SURF 0x30 +mat 2 +refs 4 +478 0.524569 0.952498 +497 0.537201 0.952498 +498 0.544014 0.929999 +479 0.529708 0.929999 +SURF 0x30 +mat 2 +refs 4 +479 0.529708 0.929999 +498 0.544014 0.929999 +499 0.549852 0.8825 +480 0.534117 0.8825 +SURF 0x30 +mat 2 +refs 4 +480 0.534117 0.8825 +499 0.549852 0.8825 +500 0.554718 0.6825 +481 0.537786 0.6825 +SURF 0x30 +mat 2 +refs 4 +481 0.537786 0.6825 +500 0.554718 0.6825 +501 0.560559 0.635 +482 0.542191 0.635 +SURF 0x30 +mat 2 +refs 4 +482 0.542191 0.635 +501 0.560559 0.635 +502 0.580996 0.555 +483 0.557613 0.555 +SURF 0x30 +mat 2 +refs 4 +483 0.557613 0.555 +502 0.580996 0.555 +503 0.599132 0.475 +484 0.571297 0.475 +SURF 0x30 +mat 2 +refs 4 +484 0.571297 0.475 +503 0.599132 0.475 +504 0.629512 0.3875 +485 0.597716 0.3875 +SURF 0x30 +mat 2 +refs 4 +485 0.597716 0.3875 +504 0.629512 0.3875 +505 0.640865 0.31 +486 0.606285 0.31 +SURF 0x30 +mat 2 +refs 4 +486 0.606285 0.31 +505 0.640865 0.31 +506 0.638975 0.247501 +487 0.604855 0.247501 +SURF 0x30 +mat 2 +refs 4 +487 0.604855 0.247501 +506 0.638975 0.247501 +507 0.635189 0.175 +488 0.602 0.175 +SURF 0x30 +mat 2 +refs 4 +488 0.602 0.175 +507 0.635189 0.175 +508 0.623832 0.105001 +489 0.593432 0.105001 +SURF 0x30 +mat 2 +refs 4 +489 0.593432 0.105001 +508 0.623832 0.105001 +509 0.594501 0.0549999 +490 0.5713 0.0549999 +SURF 0x30 +mat 2 +refs 4 +490 0.5713 0.0549999 +509 0.594501 0.0549999 +510 0.567056 0.0200004 +491 0.550595 0.0200004 +SURF 0x30 +mat 2 +refs 4 +491 0.550595 0.0200004 +510 0.567056 0.0200004 +511 0.526369 0 +492 0.519895 0 +SURF 0x30 +mat 2 +refs 4 +492 0.519895 0 +511 0.526369 0 +512 0.501766 0 +493 0.501332 0 +SURF 0x30 +mat 2 +refs 4 +494 0.489511 1 +513 0.490416 1 +514 0.50611 0.994999 +495 0.502166 0.994999 +SURF 0x30 +mat 2 +refs 4 +495 0.502166 0.994999 +514 0.50611 0.994999 +515 0.519391 0.984998 +496 0.51287 0.984998 +SURF 0x30 +mat 2 +refs 4 +496 0.51287 0.984998 +515 0.519391 0.984998 +516 0.549569 0.952498 +497 0.537201 0.952498 +SURF 0x30 +mat 2 +refs 4 +497 0.537201 0.952498 +516 0.549569 0.952498 +517 0.55802 0.929999 +498 0.544014 0.929999 +SURF 0x30 +mat 2 +refs 4 +498 0.544014 0.929999 +517 0.55802 0.929999 +518 0.565264 0.8825 +499 0.549852 0.8825 +SURF 0x30 +mat 2 +refs 4 +499 0.549852 0.8825 +518 0.565264 0.8825 +519 0.5713 0.6825 +500 0.554718 0.6825 +SURF 0x30 +mat 2 +refs 4 +500 0.554718 0.6825 +519 0.5713 0.6825 +520 0.578544 0.635 +501 0.560559 0.635 +SURF 0x30 +mat 2 +refs 4 +501 0.560559 0.635 +520 0.578544 0.635 +521 0.603894 0.555 +502 0.580996 0.555 +SURF 0x30 +mat 2 +refs 4 +502 0.580996 0.555 +521 0.603894 0.555 +522 0.626391 0.475 +503 0.599132 0.475 +SURF 0x30 +mat 2 +refs 4 +503 0.599132 0.475 +522 0.626391 0.475 +523 0.660646 0.3875 +504 0.629512 0.3875 +SURF 0x30 +mat 2 +refs 4 +504 0.629512 0.3875 +523 0.660646 0.3875 +524 0.674733 0.31 +505 0.640865 0.31 +SURF 0x30 +mat 2 +refs 4 +505 0.640865 0.31 +524 0.674733 0.31 +525 0.672386 0.247501 +506 0.638975 0.247501 +SURF 0x30 +mat 2 +refs 4 +506 0.638975 0.247501 +525 0.672386 0.247501 +526 0.667691 0.175 +507 0.635189 0.175 +SURF 0x30 +mat 2 +refs 4 +507 0.635189 0.175 +526 0.667691 0.175 +527 0.653604 0.105001 +508 0.623832 0.105001 +SURF 0x30 +mat 2 +refs 4 +508 0.623832 0.105001 +527 0.653604 0.105001 +528 0.617217 0.0549999 +509 0.594501 0.0549999 +SURF 0x30 +mat 2 +refs 4 +509 0.594501 0.0549999 +528 0.617217 0.0549999 +529 0.583178 0.0200004 +510 0.567056 0.0200004 +SURF 0x30 +mat 2 +refs 4 +510 0.567056 0.0200004 +529 0.583178 0.0200004 +530 0.532708 0 +511 0.526369 0 +SURF 0x30 +mat 2 +refs 4 +511 0.526369 0 +530 0.532708 0 +531 0.502189 0 +512 0.501766 0 +SURF 0x30 +mat 2 +refs 4 +513 0.490416 1 +532 0.491297 1 +533 0.509951 0.994999 +514 0.50611 0.994999 +SURF 0x30 +mat 2 +refs 4 +514 0.50611 0.994999 +533 0.509951 0.994999 +534 0.525736 0.984998 +515 0.519391 0.984998 +SURF 0x30 +mat 2 +refs 4 +515 0.519391 0.984998 +534 0.525736 0.984998 +535 0.561615 0.952498 +516 0.549569 0.952498 +SURF 0x30 +mat 2 +refs 4 +516 0.549569 0.952498 +535 0.561615 0.952498 +536 0.57166 0.929999 +517 0.55802 0.929999 +SURF 0x30 +mat 2 +refs 4 +517 0.55802 0.929999 +536 0.57166 0.929999 +537 0.580269 0.8825 +518 0.565264 0.8825 +SURF 0x30 +mat 2 +refs 4 +518 0.565264 0.8825 +537 0.580269 0.8825 +538 0.587446 0.6825 +519 0.5713 0.6825 +SURF 0x30 +mat 2 +refs 4 +519 0.5713 0.6825 +538 0.587446 0.6825 +539 0.596055 0.635 +520 0.578544 0.635 +SURF 0x30 +mat 2 +refs 4 +520 0.578544 0.635 +539 0.596055 0.635 +540 0.62619 0.555 +521 0.603894 0.555 +SURF 0x30 +mat 2 +refs 4 +521 0.603894 0.555 +540 0.62619 0.555 +541 0.652931 0.475 +522 0.626391 0.475 +SURF 0x30 +mat 2 +refs 4 +522 0.626391 0.475 +541 0.652931 0.475 +542 0.690966 0.3875 +523 0.660646 0.3875 +SURF 0x30 +mat 2 +refs 4 +523 0.660646 0.3875 +542 0.690966 0.3875 +543 0.707707 0.31 +524 0.674733 0.31 +SURF 0x30 +mat 2 +refs 4 +524 0.674733 0.31 +543 0.707707 0.31 +544 0.704919 0.247501 +525 0.672386 0.247501 +SURF 0x30 +mat 2 +refs 4 +525 0.672386 0.247501 +544 0.704919 0.247501 +545 0.699336 0.175 +526 0.667691 0.175 +SURF 0x30 +mat 2 +refs 4 +526 0.667691 0.175 +545 0.699336 0.175 +546 0.682592 0.105001 +527 0.653604 0.105001 +SURF 0x30 +mat 2 +refs 4 +527 0.653604 0.105001 +546 0.682592 0.105001 +547 0.639339 0.0549999 +528 0.617217 0.0549999 +SURF 0x30 +mat 2 +refs 4 +528 0.617217 0.0549999 +547 0.639339 0.0549999 +548 0.598876 0.0200004 +529 0.583178 0.0200004 +SURF 0x30 +mat 2 +refs 4 +529 0.583178 0.0200004 +548 0.598876 0.0200004 +549 0.538879 0 +530 0.532708 0 +SURF 0x30 +mat 2 +refs 4 +530 0.532708 0 +549 0.538879 0 +550 0.502603 0 +531 0.502189 0 +SURF 0x30 +mat 2 +refs 4 +532 0.491297 1 +551 0.492148 1 +552 0.51367 0.994999 +533 0.509951 0.994999 +SURF 0x30 +mat 2 +refs 4 +533 0.509951 0.994999 +552 0.51367 0.994999 +553 0.531884 0.984998 +534 0.525736 0.984998 +SURF 0x30 +mat 2 +refs 4 +534 0.525736 0.984998 +553 0.531884 0.984998 +554 0.573271 0.952498 +535 0.561615 0.952498 +SURF 0x30 +mat 2 +refs 4 +535 0.561615 0.952498 +554 0.573271 0.952498 +555 0.58486 0.929999 +536 0.57166 0.929999 +SURF 0x30 +mat 2 +refs 4 +536 0.57166 0.929999 +555 0.58486 0.929999 +556 0.594794 0.8825 +537 0.580269 0.8825 +SURF 0x30 +mat 2 +refs 4 +537 0.580269 0.8825 +556 0.594794 0.8825 +557 0.60307 0.6825 +538 0.587446 0.6825 +SURF 0x30 +mat 2 +refs 4 +538 0.587446 0.6825 +557 0.60307 0.6825 +558 0.613004 0.635 +539 0.596055 0.635 +SURF 0x30 +mat 2 +refs 4 +539 0.596055 0.635 +558 0.613004 0.635 +559 0.647773 0.555 +540 0.62619 0.555 +SURF 0x30 +mat 2 +refs 4 +540 0.62619 0.555 +559 0.647773 0.555 +560 0.678621 0.475 +541 0.652931 0.475 +SURF 0x30 +mat 2 +refs 4 +541 0.652931 0.475 +560 0.678621 0.475 +561 0.720307 0.3875 +542 0.690966 0.3875 +SURF 0x30 +mat 2 +refs 4 +542 0.690966 0.3875 +561 0.720307 0.3875 +562 0.739624 0.31 +543 0.707707 0.31 +SURF 0x30 +mat 2 +refs 4 +543 0.707707 0.31 +562 0.739624 0.31 +563 0.736405 0.247501 +544 0.704919 0.247501 +SURF 0x30 +mat 2 +refs 4 +544 0.704919 0.247501 +563 0.736405 0.247501 +564 0.729965 0.175 +545 0.699336 0.175 +SURF 0x30 +mat 2 +refs 4 +545 0.699336 0.175 +564 0.729965 0.175 +565 0.710649 0.105001 +546 0.682592 0.105001 +SURF 0x30 +mat 2 +refs 4 +546 0.682592 0.105001 +565 0.710649 0.105001 +566 0.66075 0.0549999 +547 0.639339 0.0549999 +SURF 0x30 +mat 2 +refs 4 +547 0.639339 0.0549999 +566 0.66075 0.0549999 +567 0.61407 0.0200004 +548 0.598876 0.0200004 +SURF 0x30 +mat 2 +refs 4 +548 0.598876 0.0200004 +567 0.61407 0.0200004 +568 0.544854 0 +549 0.538879 0 +SURF 0x30 +mat 2 +refs 4 +549 0.538879 0 +568 0.544854 0 +569 0.503003 0 +550 0.502603 0 +SURF 0x30 +mat 2 +refs 4 +551 0.492148 1 +570 0.492968 1 +571 0.517248 0.994999 +552 0.51367 0.994999 +SURF 0x30 +mat 2 +refs 4 +552 0.51367 0.994999 +571 0.517248 0.994999 +572 0.537792 0.984998 +553 0.531884 0.984998 +SURF 0x30 +mat 2 +refs 4 +553 0.531884 0.984998 +572 0.537792 0.984998 +573 0.584483 0.952498 +554 0.573271 0.952498 +SURF 0x30 +mat 2 +refs 4 +554 0.573271 0.952498 +573 0.584483 0.952498 +574 0.597555 0.929999 +555 0.58486 0.929999 +SURF 0x30 +mat 2 +refs 4 +555 0.58486 0.929999 +574 0.597555 0.929999 +575 0.608763 0.8825 +556 0.594794 0.8825 +SURF 0x30 +mat 2 +refs 4 +556 0.594794 0.8825 +575 0.608763 0.8825 +576 0.618098 0.6825 +557 0.60307 0.6825 +SURF 0x30 +mat 2 +refs 4 +557 0.60307 0.6825 +576 0.618098 0.6825 +577 0.629307 0.635 +558 0.613004 0.635 +SURF 0x30 +mat 2 +refs 4 +558 0.613004 0.635 +577 0.629307 0.635 +578 0.668525 0.555 +559 0.647773 0.555 +SURF 0x30 +mat 2 +refs 4 +559 0.647773 0.555 +578 0.668525 0.555 +579 0.703328 0.475 +560 0.678621 0.475 +SURF 0x30 +mat 2 +refs 4 +560 0.678621 0.475 +579 0.703328 0.475 +580 0.748529 0.3875 +561 0.720307 0.3875 +SURF 0x30 +mat 2 +refs 4 +561 0.720307 0.3875 +580 0.748529 0.3875 +581 0.77032 0.31 +562 0.739624 0.31 +SURF 0x30 +mat 2 +refs 4 +562 0.739624 0.31 +581 0.77032 0.31 +582 0.766688 0.247501 +563 0.736405 0.247501 +SURF 0x30 +mat 2 +refs 4 +563 0.736405 0.247501 +582 0.766688 0.247501 +583 0.759425 0.175 +564 0.729965 0.175 +SURF 0x30 +mat 2 +refs 4 +564 0.729965 0.175 +583 0.759425 0.175 +584 0.737636 0.105001 +565 0.710649 0.105001 +SURF 0x30 +mat 2 +refs 4 +565 0.710649 0.105001 +584 0.737636 0.105001 +585 0.681341 0.0549999 +566 0.66075 0.0549999 +SURF 0x30 +mat 2 +refs 4 +566 0.66075 0.0549999 +585 0.681341 0.0549999 +586 0.628682 0.0200004 +567 0.61407 0.0200004 +SURF 0x30 +mat 2 +refs 4 +567 0.61407 0.0200004 +586 0.628682 0.0200004 +587 0.550598 0 +568 0.544854 0 +SURF 0x30 +mat 2 +refs 4 +568 0.544854 0 +587 0.550598 0 +588 0.503386 0 +569 0.503003 0 +SURF 0x30 +mat 2 +refs 4 +570 0.492968 1 +589 0.493752 1 +590 0.520665 0.994999 +571 0.517248 0.994999 +SURF 0x30 +mat 2 +refs 4 +571 0.517248 0.994999 +590 0.520665 0.994999 +591 0.543435 0.984998 +572 0.537792 0.984998 +SURF 0x30 +mat 2 +refs 4 +572 0.537792 0.984998 +591 0.543435 0.984998 +592 0.59519 0.952498 +573 0.584483 0.952498 +SURF 0x30 +mat 2 +refs 4 +573 0.584483 0.952498 +592 0.59519 0.952498 +593 0.609681 0.929999 +574 0.597555 0.929999 +SURF 0x30 +mat 2 +refs 4 +574 0.597555 0.929999 +593 0.609681 0.929999 +594 0.622104 0.8825 +575 0.608763 0.8825 +SURF 0x30 +mat 2 +refs 4 +575 0.608763 0.8825 +594 0.622104 0.8825 +595 0.632455 0.6825 +576 0.618098 0.6825 +SURF 0x30 +mat 2 +refs 4 +576 0.618098 0.6825 +595 0.632455 0.6825 +596 0.644874 0.635 +577 0.629307 0.635 +SURF 0x30 +mat 2 +refs 4 +577 0.629307 0.635 +596 0.644874 0.635 +597 0.68835 0.555 +578 0.668525 0.555 +SURF 0x30 +mat 2 +refs 4 +578 0.668525 0.555 +597 0.68835 0.555 +598 0.726925 0.475 +579 0.703328 0.475 +SURF 0x30 +mat 2 +refs 4 +579 0.703328 0.475 +598 0.726925 0.475 +599 0.775486 0.3875 +580 0.748529 0.3875 +SURF 0x30 +mat 2 +refs 4 +580 0.748529 0.3875 +599 0.775486 0.3875 +600 0.799638 0.31 +581 0.77032 0.31 +SURF 0x30 +mat 2 +refs 4 +581 0.77032 0.31 +600 0.799638 0.31 +601 0.795613 0.247501 +582 0.766688 0.247501 +SURF 0x30 +mat 2 +refs 4 +582 0.766688 0.247501 +601 0.795613 0.247501 +602 0.787562 0.175 +583 0.759425 0.175 +SURF 0x30 +mat 2 +refs 4 +583 0.759425 0.175 +602 0.787562 0.175 +603 0.76341 0.105001 +584 0.737636 0.105001 +SURF 0x30 +mat 2 +refs 4 +584 0.737636 0.105001 +603 0.76341 0.105001 +604 0.701011 0.0549999 +585 0.681341 0.0549999 +SURF 0x30 +mat 2 +refs 4 +585 0.681341 0.0549999 +604 0.701011 0.0549999 +605 0.642638 0.0200004 +586 0.628682 0.0200004 +SURF 0x30 +mat 2 +refs 4 +586 0.628682 0.0200004 +605 0.642638 0.0200004 +606 0.556087 0 +587 0.550598 0 +SURF 0x30 +mat 2 +refs 4 +587 0.550598 0 +606 0.556087 0 +607 0.503753 0 +588 0.503386 0 +SURF 0x30 +mat 2 +refs 4 +589 0.493752 1 +608 0.494495 1 +609 0.523904 0.994999 +590 0.520665 0.994999 +SURF 0x30 +mat 2 +refs 4 +590 0.520665 0.994999 +609 0.523904 0.994999 +610 0.548786 0.984998 +591 0.543435 0.984998 +SURF 0x30 +mat 2 +refs 4 +591 0.543435 0.984998 +610 0.548786 0.984998 +611 0.605343 0.952498 +592 0.59519 0.952498 +SURF 0x30 +mat 2 +refs 4 +592 0.59519 0.952498 +611 0.605343 0.952498 +612 0.621176 0.929999 +593 0.609681 0.929999 +SURF 0x30 +mat 2 +refs 4 +593 0.609681 0.929999 +612 0.621176 0.929999 +613 0.634748 0.8825 +594 0.622104 0.8825 +SURF 0x30 +mat 2 +refs 4 +594 0.622104 0.8825 +613 0.634748 0.8825 +614 0.646061 0.6825 +595 0.632455 0.6825 +SURF 0x30 +mat 2 +refs 4 +595 0.632455 0.6825 +614 0.646061 0.6825 +615 0.659634 0.635 +596 0.644874 0.635 +SURF 0x30 +mat 2 +refs 4 +596 0.644874 0.635 +615 0.659634 0.635 +616 0.707142 0.555 +597 0.68835 0.555 +SURF 0x30 +mat 2 +refs 4 +597 0.68835 0.555 +616 0.707142 0.555 +617 0.749295 0.475 +598 0.726925 0.475 +SURF 0x30 +mat 2 +refs 4 +598 0.726925 0.475 +617 0.749295 0.475 +618 0.801037 0.3875 +599 0.775486 0.3875 +SURF 0x30 +mat 2 +refs 4 +599 0.775486 0.3875 +618 0.801037 0.3875 +619 0.827429 0.31 +600 0.799638 0.31 +SURF 0x30 +mat 2 +refs 4 +600 0.799638 0.31 +619 0.827429 0.31 +620 0.823031 0.247501 +601 0.795613 0.247501 +SURF 0x30 +mat 2 +refs 4 +601 0.795613 0.247501 +620 0.823031 0.247501 +621 0.814233 0.175 +602 0.787562 0.175 +SURF 0x30 +mat 2 +refs 4 +602 0.787562 0.175 +621 0.814233 0.175 +622 0.787838 0.105001 +603 0.76341 0.105001 +SURF 0x30 +mat 2 +refs 4 +603 0.76341 0.105001 +622 0.787838 0.105001 +623 0.719655 0.0549999 +604 0.701011 0.0549999 +SURF 0x30 +mat 2 +refs 4 +604 0.701011 0.0549999 +623 0.719655 0.0549999 +624 0.655867 0.0200004 +605 0.642638 0.0200004 +SURF 0x30 +mat 2 +refs 4 +605 0.642638 0.0200004 +624 0.655867 0.0200004 +625 0.561289 0 +606 0.556087 0 +SURF 0x30 +mat 2 +refs 4 +606 0.556087 0 +625 0.561289 0 +626 0.504103 0 +607 0.503753 0 +SURF 0x30 +mat 2 +refs 4 +608 0.494495 1 +627 0.495191 1 +628 0.526947 0.994999 +609 0.523904 0.994999 +SURF 0x30 +mat 2 +refs 4 +609 0.523904 0.994999 +628 0.526947 0.994999 +629 0.553817 0.984998 +610 0.548786 0.984998 +SURF 0x30 +mat 2 +refs 4 +610 0.548786 0.984998 +629 0.553817 0.984998 +630 0.614884 0.952498 +611 0.605343 0.952498 +SURF 0x30 +mat 2 +refs 4 +611 0.605343 0.952498 +630 0.614884 0.952498 +631 0.631981 0.929999 +612 0.621176 0.929999 +SURF 0x30 +mat 2 +refs 4 +612 0.621176 0.929999 +631 0.631981 0.929999 +632 0.646636 0.8825 +613 0.634748 0.8825 +SURF 0x30 +mat 2 +refs 4 +613 0.634748 0.8825 +632 0.646636 0.8825 +633 0.65885 0.6825 +614 0.646061 0.6825 +SURF 0x30 +mat 2 +refs 4 +614 0.646061 0.6825 +633 0.65885 0.6825 +634 0.673506 0.635 +615 0.659634 0.635 +SURF 0x30 +mat 2 +refs 4 +615 0.659634 0.635 +634 0.673506 0.635 +635 0.724803 0.555 +616 0.707142 0.555 +SURF 0x30 +mat 2 +refs 4 +616 0.707142 0.555 +635 0.724803 0.555 +636 0.77032 0.475 +617 0.749295 0.475 +SURF 0x30 +mat 2 +refs 4 +617 0.749295 0.475 +636 0.77032 0.475 +637 0.825055 0.3875 +618 0.801037 0.3875 +SURF 0x30 +mat 2 +refs 4 +618 0.801037 0.3875 +637 0.825055 0.3875 +638 0.853552 0.31 +619 0.827429 0.31 +SURF 0x30 +mat 2 +refs 4 +619 0.827429 0.31 +638 0.853552 0.31 +639 0.848804 0.247501 +620 0.823031 0.247501 +SURF 0x30 +mat 2 +refs 4 +620 0.823031 0.247501 +639 0.848804 0.247501 +640 0.839304 0.175 +621 0.814233 0.175 +SURF 0x30 +mat 2 +refs 4 +621 0.814233 0.175 +640 0.839304 0.175 +641 0.810803 0.105001 +622 0.787838 0.105001 +SURF 0x30 +mat 2 +refs 4 +622 0.787838 0.105001 +641 0.810803 0.105001 +642 0.737179 0.0549999 +623 0.719655 0.0549999 +SURF 0x30 +mat 2 +refs 4 +623 0.719655 0.0549999 +642 0.737179 0.0549999 +643 0.668303 0.0200004 +624 0.655867 0.0200004 +SURF 0x30 +mat 2 +refs 4 +624 0.655867 0.0200004 +643 0.668303 0.0200004 +644 0.566179 0 +625 0.561289 0 +SURF 0x30 +mat 2 +refs 4 +625 0.561289 0 +644 0.566179 0 +645 0.504429 0 +626 0.504103 0 +SURF 0x30 +mat 2 +refs 4 +627 0.495191 1 +646 0.49584 1 +647 0.529779 0.994999 +628 0.526947 0.994999 +SURF 0x30 +mat 2 +refs 4 +628 0.526947 0.994999 +647 0.529779 0.994999 +648 0.558498 0.984998 +629 0.553817 0.984998 +SURF 0x30 +mat 2 +refs 4 +629 0.553817 0.984998 +648 0.558498 0.984998 +649 0.623765 0.952498 +630 0.614884 0.952498 +SURF 0x30 +mat 2 +refs 4 +630 0.614884 0.952498 +649 0.623765 0.952498 +650 0.642039 0.929999 +631 0.631981 0.929999 +SURF 0x30 +mat 2 +refs 4 +631 0.631981 0.929999 +650 0.642039 0.929999 +651 0.657703 0.8825 +632 0.646636 0.8825 +SURF 0x30 +mat 2 +refs 4 +632 0.646636 0.8825 +651 0.657703 0.8825 +652 0.670758 0.6825 +633 0.65885 0.6825 +SURF 0x30 +mat 2 +refs 4 +633 0.65885 0.6825 +652 0.670758 0.6825 +653 0.686423 0.635 +634 0.673506 0.635 +SURF 0x30 +mat 2 +refs 4 +634 0.673506 0.635 +653 0.686423 0.635 +654 0.741248 0.555 +635 0.724803 0.555 +SURF 0x30 +mat 2 +refs 4 +635 0.724803 0.555 +654 0.741248 0.555 +655 0.789896 0.475 +636 0.77032 0.475 +SURF 0x30 +mat 2 +refs 4 +636 0.77032 0.475 +655 0.789896 0.475 +656 0.847415 0.3875 +637 0.825055 0.3875 +SURF 0x30 +mat 2 +refs 4 +637 0.825055 0.3875 +656 0.847415 0.3875 +657 0.877876 0.31 +638 0.853552 0.31 +SURF 0x30 +mat 2 +refs 4 +638 0.853552 0.31 +657 0.877876 0.31 +658 0.872798 0.247501 +639 0.848804 0.247501 +SURF 0x30 +mat 2 +refs 4 +639 0.848804 0.247501 +658 0.872798 0.247501 +659 0.862646 0.175 +640 0.839304 0.175 +SURF 0x30 +mat 2 +refs 4 +640 0.839304 0.175 +659 0.862646 0.175 +660 0.832184 0.105001 +641 0.810803 0.105001 +SURF 0x30 +mat 2 +refs 4 +641 0.810803 0.105001 +660 0.832184 0.105001 +661 0.753496 0.0549999 +642 0.737179 0.0549999 +SURF 0x30 +mat 2 +refs 4 +642 0.737179 0.0549999 +661 0.753496 0.0549999 +662 0.679882 0.0200004 +643 0.668303 0.0200004 +SURF 0x30 +mat 2 +refs 4 +643 0.668303 0.0200004 +662 0.679882 0.0200004 +663 0.570732 0 +644 0.566179 0 +SURF 0x30 +mat 2 +refs 4 +644 0.566179 0 +663 0.570732 0 +664 0.504735 0 +645 0.504429 0 +SURF 0x30 +mat 2 +refs 4 +646 0.49584 1 +665 0.496439 1 +666 0.532388 0.994999 +647 0.529779 0.994999 +SURF 0x30 +mat 2 +refs 4 +647 0.529779 0.994999 +666 0.532388 0.994999 +667 0.562809 0.984998 +648 0.558498 0.984998 +SURF 0x30 +mat 2 +refs 4 +648 0.558498 0.984998 +667 0.562809 0.984998 +668 0.631947 0.952498 +649 0.623765 0.952498 +SURF 0x30 +mat 2 +refs 4 +649 0.623765 0.952498 +668 0.631947 0.952498 +669 0.651304 0.929999 +650 0.642039 0.929999 +SURF 0x30 +mat 2 +refs 4 +650 0.642039 0.929999 +669 0.651304 0.929999 +670 0.667896 0.8825 +651 0.657703 0.8825 +SURF 0x30 +mat 2 +refs 4 +651 0.657703 0.8825 +670 0.667896 0.8825 +671 0.681725 0.6825 +652 0.670758 0.6825 +SURF 0x30 +mat 2 +refs 4 +652 0.670758 0.6825 +671 0.681725 0.6825 +672 0.698317 0.635 +653 0.686423 0.635 +SURF 0x30 +mat 2 +refs 4 +653 0.686423 0.635 +672 0.698317 0.635 +673 0.756391 0.555 +654 0.741248 0.555 +SURF 0x30 +mat 2 +refs 4 +654 0.741248 0.555 +673 0.756391 0.555 +674 0.807924 0.475 +655 0.789896 0.475 +SURF 0x30 +mat 2 +refs 4 +655 0.789896 0.475 +674 0.807924 0.475 +675 0.868006 0.3875 +656 0.847415 0.3875 +SURF 0x30 +mat 2 +refs 4 +656 0.847415 0.3875 +675 0.868006 0.3875 +676 0.90027 0.31 +657 0.877876 0.31 +SURF 0x30 +mat 2 +refs 4 +657 0.877876 0.31 +676 0.90027 0.31 +677 0.894892 0.247501 +658 0.872798 0.247501 +SURF 0x30 +mat 2 +refs 4 +658 0.872798 0.247501 +677 0.894892 0.247501 +678 0.884138 0.175 +659 0.862646 0.175 +SURF 0x30 +mat 2 +refs 4 +659 0.862646 0.175 +678 0.884138 0.175 +679 0.851871 0.105001 +660 0.832184 0.105001 +SURF 0x30 +mat 2 +refs 4 +660 0.832184 0.105001 +679 0.851871 0.105001 +680 0.768518 0.0549999 +661 0.753496 0.0549999 +SURF 0x30 +mat 2 +refs 4 +661 0.753496 0.0549999 +680 0.768518 0.0549999 +681 0.690542 0.0200004 +662 0.679882 0.0200004 +SURF 0x30 +mat 2 +refs 4 +662 0.679882 0.0200004 +681 0.690542 0.0200004 +682 0.574922 0 +663 0.570732 0 +SURF 0x30 +mat 2 +refs 4 +663 0.570732 0 +682 0.574922 0 +683 0.505014 0 +664 0.504735 0 +SURF 0x30 +mat 2 +refs 4 +665 0.496439 1 +684 0.496983 1 +685 0.534762 0.994999 +666 0.532388 0.994999 +SURF 0x30 +mat 2 +refs 4 +666 0.532388 0.994999 +685 0.534762 0.994999 +686 0.566727 0.984998 +667 0.562809 0.984998 +SURF 0x30 +mat 2 +refs 4 +667 0.562809 0.984998 +686 0.566727 0.984998 +687 0.639379 0.952498 +668 0.631947 0.952498 +SURF 0x30 +mat 2 +refs 4 +668 0.631947 0.952498 +687 0.639379 0.952498 +688 0.659721 0.929999 +669 0.651304 0.929999 +SURF 0x30 +mat 2 +refs 4 +669 0.651304 0.929999 +688 0.659721 0.929999 +689 0.677161 0.8825 +670 0.667896 0.8825 +SURF 0x30 +mat 2 +refs 4 +670 0.667896 0.8825 +689 0.677161 0.8825 +690 0.691689 0.6825 +671 0.681725 0.6825 +SURF 0x30 +mat 2 +refs 4 +671 0.681725 0.6825 +690 0.691689 0.6825 +691 0.709126 0.635 +672 0.698317 0.635 +SURF 0x30 +mat 2 +refs 4 +672 0.698317 0.635 +691 0.709126 0.635 +692 0.770156 0.555 +673 0.756391 0.555 +SURF 0x30 +mat 2 +refs 4 +673 0.756391 0.555 +692 0.770156 0.555 +693 0.824308 0.475 +674 0.807924 0.475 +SURF 0x30 +mat 2 +refs 4 +674 0.807924 0.475 +693 0.824308 0.475 +694 0.886721 0.3875 +675 0.868006 0.3875 +SURF 0x30 +mat 2 +refs 4 +675 0.868006 0.3875 +694 0.886721 0.3875 +695 0.920625 0.31 +676 0.90027 0.31 +SURF 0x30 +mat 2 +refs 4 +676 0.90027 0.31 +695 0.920625 0.31 +696 0.914976 0.247501 +677 0.894892 0.247501 +SURF 0x30 +mat 2 +refs 4 +677 0.894892 0.247501 +696 0.914976 0.247501 +697 0.903673 0.175 +678 0.884138 0.175 +SURF 0x30 +mat 2 +refs 4 +678 0.884138 0.175 +697 0.903673 0.175 +698 0.869768 0.105001 +679 0.851871 0.105001 +SURF 0x30 +mat 2 +refs 4 +679 0.851871 0.105001 +698 0.869768 0.105001 +699 0.782175 0.0549999 +680 0.768518 0.0549999 +SURF 0x30 +mat 2 +refs 4 +680 0.768518 0.0549999 +699 0.782175 0.0549999 +700 0.700234 0.0200004 +681 0.690542 0.0200004 +SURF 0x30 +mat 2 +refs 4 +681 0.690542 0.0200004 +700 0.700234 0.0200004 +701 0.578736 0 +682 0.574922 0 +SURF 0x30 +mat 2 +refs 4 +682 0.574922 0 +701 0.578736 0 +702 0.50527 0 +683 0.505014 0 +SURF 0x30 +mat 2 +refs 4 +684 0.496983 1 +703 0.497468 1 +704 0.536884 0.994999 +685 0.534762 0.994999 +SURF 0x30 +mat 2 +refs 4 +685 0.534762 0.994999 +704 0.536884 0.994999 +705 0.570234 0.984998 +686 0.566727 0.984998 +SURF 0x30 +mat 2 +refs 4 +686 0.566727 0.984998 +705 0.570234 0.984998 +706 0.646031 0.952498 +687 0.639379 0.952498 +SURF 0x30 +mat 2 +refs 4 +687 0.639379 0.952498 +706 0.646031 0.952498 +707 0.667254 0.929999 +688 0.659721 0.929999 +SURF 0x30 +mat 2 +refs 4 +688 0.659721 0.929999 +707 0.667254 0.929999 +708 0.685447 0.8825 +689 0.677161 0.8825 +SURF 0x30 +mat 2 +refs 4 +689 0.677161 0.8825 +708 0.685447 0.8825 +709 0.700607 0.6825 +690 0.691689 0.6825 +SURF 0x30 +mat 2 +refs 4 +690 0.691689 0.6825 +709 0.700607 0.6825 +710 0.718797 0.635 +691 0.709126 0.635 +SURF 0x30 +mat 2 +refs 4 +691 0.709126 0.635 +710 0.718797 0.635 +711 0.782467 0.555 +692 0.770156 0.555 +SURF 0x30 +mat 2 +refs 4 +692 0.770156 0.555 +711 0.782467 0.555 +712 0.838967 0.475 +693 0.824308 0.475 +SURF 0x30 +mat 2 +refs 4 +693 0.824308 0.475 +712 0.838967 0.475 +713 0.903464 0.3875 +694 0.886721 0.3875 +SURF 0x30 +mat 2 +refs 4 +694 0.886721 0.3875 +713 0.903464 0.3875 +714 0.938839 0.31 +695 0.920625 0.31 +SURF 0x30 +mat 2 +refs 4 +695 0.920625 0.31 +714 0.938839 0.31 +715 0.932944 0.247501 +696 0.914976 0.247501 +SURF 0x30 +mat 2 +refs 4 +696 0.914976 0.247501 +715 0.932944 0.247501 +716 0.921153 0.175 +697 0.903673 0.175 +SURF 0x30 +mat 2 +refs 4 +697 0.903673 0.175 +716 0.921153 0.175 +717 0.885776 0.105001 +698 0.869768 0.105001 +SURF 0x30 +mat 2 +refs 4 +698 0.869768 0.105001 +717 0.885776 0.105001 +718 0.794392 0.0549999 +699 0.782175 0.0549999 +SURF 0x30 +mat 2 +refs 4 +699 0.782175 0.0549999 +718 0.794392 0.0549999 +719 0.708904 0.0200004 +700 0.700234 0.0200004 +SURF 0x30 +mat 2 +refs 4 +700 0.700234 0.0200004 +719 0.708904 0.0200004 +720 0.582142 0 +701 0.578736 0 +SURF 0x30 +mat 2 +refs 4 +701 0.578736 0 +720 0.582142 0 +721 0.505498 0 +702 0.50527 0 +SURF 0x30 +mat 2 +refs 4 +703 0.497468 1 +722 0.497895 1 +723 0.538744 0.994999 +704 0.536884 0.994999 +SURF 0x30 +mat 2 +refs 4 +704 0.536884 0.994999 +723 0.538744 0.994999 +724 0.573311 0.984998 +705 0.570234 0.984998 +SURF 0x30 +mat 2 +refs 4 +705 0.570234 0.984998 +724 0.573311 0.984998 +725 0.651869 0.952498 +706 0.646031 0.952498 +SURF 0x30 +mat 2 +refs 4 +706 0.646031 0.952498 +725 0.651869 0.952498 +726 0.673862 0.929999 +707 0.667254 0.929999 +SURF 0x30 +mat 2 +refs 4 +707 0.667254 0.929999 +726 0.673862 0.929999 +727 0.692718 0.8825 +708 0.685447 0.8825 +SURF 0x30 +mat 2 +refs 4 +708 0.685447 0.8825 +727 0.692718 0.8825 +728 0.70843 0.6825 +709 0.700607 0.6825 +SURF 0x30 +mat 2 +refs 4 +709 0.700607 0.6825 +728 0.70843 0.6825 +729 0.727282 0.635 +710 0.718797 0.635 +SURF 0x30 +mat 2 +refs 4 +710 0.718797 0.635 +729 0.727282 0.635 +730 0.793272 0.555 +711 0.782467 0.555 +SURF 0x30 +mat 2 +refs 4 +711 0.782467 0.555 +730 0.793272 0.555 +731 0.851827 0.475 +712 0.838967 0.475 +SURF 0x30 +mat 2 +refs 4 +712 0.838967 0.475 +731 0.851827 0.475 +732 0.918154 0.3875 +713 0.903464 0.3875 +SURF 0x30 +mat 2 +refs 4 +713 0.903464 0.3875 +732 0.918154 0.3875 +733 0.954816 0.31 +714 0.938839 0.31 +SURF 0x30 +mat 2 +refs 4 +714 0.938839 0.31 +733 0.954816 0.31 +734 0.948706 0.247501 +715 0.932944 0.247501 +SURF 0x30 +mat 2 +refs 4 +715 0.932944 0.247501 +734 0.948706 0.247501 +735 0.936485 0.175 +716 0.921153 0.175 +SURF 0x30 +mat 2 +refs 4 +716 0.921153 0.175 +735 0.936485 0.175 +736 0.899823 0.105001 +717 0.885776 0.105001 +SURF 0x30 +mat 2 +refs 4 +717 0.885776 0.105001 +736 0.899823 0.105001 +737 0.80511 0.0549999 +718 0.794392 0.0549999 +SURF 0x30 +mat 2 +refs 4 +718 0.794392 0.0549999 +737 0.80511 0.0549999 +738 0.716507 0.0200004 +719 0.708904 0.0200004 +SURF 0x30 +mat 2 +refs 4 +719 0.708904 0.0200004 +738 0.716507 0.0200004 +739 0.585132 0 +720 0.582142 0 +SURF 0x30 +mat 2 +refs 4 +720 0.582142 0 +739 0.585132 0 +740 0.505697 0 +721 0.505498 0 +SURF 0x30 +mat 2 +refs 4 +722 0.497895 1 +741 0.498258 1 +742 0.540335 0.994999 +723 0.538744 0.994999 +SURF 0x30 +mat 2 +refs 4 +723 0.538744 0.994999 +742 0.540335 0.994999 +743 0.575941 0.984998 +724 0.573311 0.984998 +SURF 0x30 +mat 2 +refs 4 +724 0.573311 0.984998 +743 0.575941 0.984998 +744 0.656856 0.952498 +725 0.651869 0.952498 +SURF 0x30 +mat 2 +refs 4 +725 0.651869 0.952498 +744 0.656856 0.952498 +745 0.679512 0.929999 +726 0.673862 0.929999 +SURF 0x30 +mat 2 +refs 4 +726 0.673862 0.929999 +745 0.679512 0.929999 +746 0.698933 0.8825 +727 0.692718 0.8825 +SURF 0x30 +mat 2 +refs 4 +727 0.692718 0.8825 +746 0.698933 0.8825 +747 0.715115 0.6825 +728 0.70843 0.6825 +SURF 0x30 +mat 2 +refs 4 +728 0.70843 0.6825 +747 0.715115 0.6825 +748 0.734536 0.635 +729 0.727282 0.635 +SURF 0x30 +mat 2 +refs 4 +729 0.727282 0.635 +748 0.734536 0.635 +749 0.802507 0.555 +730 0.793272 0.555 +SURF 0x30 +mat 2 +refs 4 +730 0.793272 0.555 +749 0.802507 0.555 +750 0.86282 0.475 +731 0.851827 0.475 +SURF 0x30 +mat 2 +refs 4 +731 0.851827 0.475 +750 0.86282 0.475 +751 0.930711 0.3875 +732 0.918154 0.3875 +SURF 0x30 +mat 2 +refs 4 +732 0.918154 0.3875 +751 0.930711 0.3875 +752 0.968476 0.31 +733 0.954816 0.31 +SURF 0x30 +mat 2 +refs 4 +733 0.954816 0.31 +752 0.968476 0.31 +753 0.962181 0.247501 +734 0.948706 0.247501 +SURF 0x30 +mat 2 +refs 4 +734 0.948706 0.247501 +753 0.962181 0.247501 +754 0.949593 0.175 +735 0.936485 0.175 +SURF 0x30 +mat 2 +refs 4 +735 0.936485 0.175 +754 0.949593 0.175 +755 0.911828 0.105001 +736 0.899823 0.105001 +SURF 0x30 +mat 2 +refs 4 +736 0.899823 0.105001 +755 0.911828 0.105001 +756 0.814274 0.0549999 +737 0.80511 0.0549999 +SURF 0x30 +mat 2 +refs 4 +737 0.80511 0.0549999 +756 0.814274 0.0549999 +757 0.723011 0.0200004 +738 0.716507 0.0200004 +SURF 0x30 +mat 2 +refs 4 +738 0.716507 0.0200004 +757 0.723011 0.0200004 +758 0.587691 0 +739 0.585132 0 +SURF 0x30 +mat 2 +refs 4 +739 0.585132 0 +758 0.587691 0 +759 0.505868 0 +740 0.505697 0 +SURF 0x30 +mat 2 +refs 4 +741 0.498258 1 +760 0.498561 1 +761 0.54165 0.994999 +742 0.540335 0.994999 +SURF 0x30 +mat 2 +refs 4 +742 0.540335 0.994999 +761 0.54165 0.994999 +762 0.57811 0.984998 +743 0.575941 0.984998 +SURF 0x30 +mat 2 +refs 4 +743 0.575941 0.984998 +762 0.57811 0.984998 +763 0.660972 0.952498 +744 0.656856 0.952498 +SURF 0x30 +mat 2 +refs 4 +744 0.656856 0.952498 +763 0.660972 0.952498 +764 0.684176 0.929999 +745 0.679512 0.929999 +SURF 0x30 +mat 2 +refs 4 +745 0.679512 0.929999 +764 0.684176 0.929999 +765 0.704061 0.8825 +746 0.698933 0.8825 +SURF 0x30 +mat 2 +refs 4 +746 0.698933 0.8825 +765 0.704061 0.8825 +766 0.720633 0.6825 +747 0.715115 0.6825 +SURF 0x30 +mat 2 +refs 4 +747 0.715115 0.6825 +766 0.720633 0.6825 +767 0.740522 0.635 +748 0.734536 0.635 +SURF 0x30 +mat 2 +refs 4 +748 0.734536 0.635 +767 0.740522 0.635 +768 0.810127 0.555 +749 0.802507 0.555 +SURF 0x30 +mat 2 +refs 4 +749 0.802507 0.555 +768 0.810127 0.555 +769 0.871894 0.475 +750 0.86282 0.475 +SURF 0x30 +mat 2 +refs 4 +750 0.86282 0.475 +769 0.871894 0.475 +770 0.941075 0.3875 +751 0.930711 0.3875 +SURF 0x30 +mat 2 +refs 4 +751 0.930711 0.3875 +770 0.941075 0.3875 +771 0.979745 0.31 +752 0.968476 0.31 +SURF 0x30 +mat 2 +refs 4 +752 0.968476 0.31 +771 0.979745 0.31 +772 0.973302 0.247501 +753 0.962181 0.247501 +SURF 0x30 +mat 2 +refs 4 +753 0.962181 0.247501 +772 0.973302 0.247501 +773 0.960409 0.175 +754 0.949593 0.175 +SURF 0x30 +mat 2 +refs 4 +754 0.949593 0.175 +773 0.960409 0.175 +774 0.921739 0.105001 +755 0.911828 0.105001 +SURF 0x30 +mat 2 +refs 4 +755 0.911828 0.105001 +774 0.921739 0.105001 +775 0.821833 0.0549999 +756 0.814274 0.0549999 +SURF 0x30 +mat 2 +refs 4 +756 0.814274 0.0549999 +775 0.821833 0.0549999 +776 0.728375 0.0200004 +757 0.723011 0.0200004 +SURF 0x30 +mat 2 +refs 4 +757 0.723011 0.0200004 +776 0.728375 0.0200004 +777 0.5898 0 +758 0.587691 0 +SURF 0x30 +mat 2 +refs 4 +758 0.587691 0 +777 0.5898 0 +778 0.506009 0 +759 0.505868 0 +SURF 0x30 +mat 2 +refs 4 +760 0.498561 1 +779 0.498796 1 +780 0.542679 0.994999 +761 0.54165 0.994999 +SURF 0x30 +mat 2 +refs 4 +761 0.54165 0.994999 +780 0.542679 0.994999 +781 0.579808 0.984998 +762 0.57811 0.984998 +SURF 0x30 +mat 2 +refs 4 +762 0.57811 0.984998 +781 0.579808 0.984998 +782 0.664197 0.952498 +763 0.660972 0.952498 +SURF 0x30 +mat 2 +refs 4 +763 0.660972 0.952498 +782 0.664197 0.952498 +783 0.687825 0.929999 +764 0.684176 0.929999 +SURF 0x30 +mat 2 +refs 4 +764 0.684176 0.929999 +783 0.687825 0.929999 +784 0.70808 0.8825 +765 0.704061 0.8825 +SURF 0x30 +mat 2 +refs 4 +765 0.704061 0.8825 +784 0.70808 0.8825 +785 0.724958 0.6825 +766 0.720633 0.6825 +SURF 0x30 +mat 2 +refs 4 +766 0.720633 0.6825 +785 0.724958 0.6825 +786 0.74521 0.635 +767 0.740522 0.635 +SURF 0x30 +mat 2 +refs 4 +767 0.740522 0.635 +786 0.74521 0.635 +787 0.816096 0.555 +768 0.810127 0.555 +SURF 0x30 +mat 2 +refs 4 +768 0.810127 0.555 +787 0.816096 0.555 +788 0.878996 0.475 +769 0.871894 0.475 +SURF 0x30 +mat 2 +refs 4 +769 0.871894 0.475 +788 0.878996 0.475 +789 0.94919 0.3875 +770 0.941075 0.3875 +SURF 0x30 +mat 2 +refs 4 +770 0.941075 0.3875 +789 0.94919 0.3875 +790 0.988573 0.31 +771 0.979745 0.31 +SURF 0x30 +mat 2 +refs 4 +771 0.979745 0.31 +790 0.988573 0.31 +791 0.982008 0.247501 +772 0.973302 0.247501 +SURF 0x30 +mat 2 +refs 4 +772 0.973302 0.247501 +791 0.982008 0.247501 +792 0.96888 0.175 +773 0.960409 0.175 +SURF 0x30 +mat 2 +refs 4 +773 0.960409 0.175 +792 0.96888 0.175 +793 0.929497 0.105001 +774 0.921739 0.105001 +SURF 0x30 +mat 2 +refs 4 +774 0.921739 0.105001 +793 0.929497 0.105001 +794 0.827755 0.0549999 +775 0.821833 0.0549999 +SURF 0x30 +mat 2 +refs 4 +775 0.821833 0.0549999 +794 0.827755 0.0549999 +795 0.732578 0.0200004 +776 0.728375 0.0200004 +SURF 0x30 +mat 2 +refs 4 +776 0.728375 0.0200004 +795 0.732578 0.0200004 +796 0.591451 0 +777 0.5898 0 +SURF 0x30 +mat 2 +refs 4 +777 0.5898 0 +796 0.591451 0 +797 0.506121 0 +778 0.506009 0 +SURF 0x30 +mat 2 +refs 4 +779 0.498796 1 +798 0.498964 1 +799 0.543415 0.994999 +780 0.542679 0.994999 +SURF 0x30 +mat 2 +refs 4 +780 0.542679 0.994999 +799 0.543415 0.994999 +800 0.581029 0.984998 +781 0.579808 0.984998 +SURF 0x30 +mat 2 +refs 4 +781 0.579808 0.984998 +800 0.581029 0.984998 +801 0.666511 0.952498 +782 0.664197 0.952498 +SURF 0x30 +mat 2 +refs 4 +782 0.664197 0.952498 +801 0.666511 0.952498 +802 0.690448 0.929999 +783 0.687825 0.929999 +SURF 0x30 +mat 2 +refs 4 +783 0.687825 0.929999 +802 0.690448 0.929999 +803 0.710962 0.8825 +784 0.70808 0.8825 +SURF 0x30 +mat 2 +refs 4 +784 0.70808 0.8825 +803 0.710962 0.8825 +804 0.728059 0.6825 +785 0.724958 0.6825 +SURF 0x30 +mat 2 +refs 4 +785 0.724958 0.6825 +804 0.728059 0.6825 +805 0.748576 0.635 +786 0.74521 0.635 +SURF 0x30 +mat 2 +refs 4 +786 0.74521 0.635 +805 0.748576 0.635 +806 0.82038 0.555 +787 0.816096 0.555 +SURF 0x30 +mat 2 +refs 4 +787 0.816096 0.555 +806 0.82038 0.555 +807 0.884097 0.475 +788 0.878996 0.475 +SURF 0x30 +mat 2 +refs 4 +788 0.878996 0.475 +807 0.884097 0.475 +808 0.955014 0.3875 +789 0.94919 0.3875 +SURF 0x30 +mat 2 +refs 4 +789 0.94919 0.3875 +808 0.955014 0.3875 +809 0.994912 0.31 +790 0.988573 0.31 +SURF 0x30 +mat 2 +refs 4 +790 0.988573 0.31 +809 0.994912 0.31 +810 0.98826 0.247501 +791 0.982008 0.247501 +SURF 0x30 +mat 2 +refs 4 +791 0.982008 0.247501 +810 0.98826 0.247501 +811 0.974963 0.175 +792 0.96888 0.175 +SURF 0x30 +mat 2 +refs 4 +792 0.96888 0.175 +811 0.974963 0.175 +812 0.935069 0.105001 +793 0.929497 0.105001 +SURF 0x30 +mat 2 +refs 4 +793 0.929497 0.105001 +812 0.935069 0.105001 +813 0.832006 0.0549999 +794 0.827755 0.0549999 +SURF 0x30 +mat 2 +refs 4 +794 0.827755 0.0549999 +813 0.832006 0.0549999 +814 0.735595 0.0200004 +795 0.732578 0.0200004 +SURF 0x30 +mat 2 +refs 4 +795 0.732578 0.0200004 +814 0.735595 0.0200004 +815 0.592638 0 +796 0.591451 0 +SURF 0x30 +mat 2 +refs 4 +796 0.591451 0 +815 0.592638 0 +816 0.506201 0 +797 0.506121 0 +SURF 0x30 +mat 2 +refs 4 +798 0.498964 1 +817 0.499068 1 +818 0.543862 0.994999 +799 0.543415 0.994999 +SURF 0x30 +mat 2 +refs 4 +799 0.543415 0.994999 +818 0.543862 0.994999 +819 0.581762 0.984998 +800 0.581029 0.984998 +SURF 0x30 +mat 2 +refs 4 +800 0.581029 0.984998 +819 0.581762 0.984998 +820 0.667906 0.952498 +801 0.666511 0.952498 +SURF 0x30 +mat 2 +refs 4 +801 0.666511 0.952498 +820 0.667906 0.952498 +821 0.692025 0.929999 +802 0.690448 0.929999 +SURF 0x30 +mat 2 +refs 4 +802 0.690448 0.929999 +821 0.692025 0.929999 +822 0.7127 0.8825 +803 0.710962 0.8825 +SURF 0x30 +mat 2 +refs 4 +803 0.710962 0.8825 +822 0.7127 0.8825 +823 0.729928 0.6825 +804 0.728059 0.6825 +SURF 0x30 +mat 2 +refs 4 +804 0.728059 0.6825 +823 0.729928 0.6825 +824 0.7506 0.635 +805 0.748576 0.635 +SURF 0x30 +mat 2 +refs 4 +805 0.748576 0.635 +824 0.7506 0.635 +825 0.82296 0.555 +806 0.82038 0.555 +SURF 0x30 +mat 2 +refs 4 +806 0.82038 0.555 +825 0.82296 0.555 +826 0.887168 0.475 +807 0.884097 0.475 +SURF 0x30 +mat 2 +refs 4 +807 0.884097 0.475 +826 0.887168 0.475 +827 0.958522 0.3875 +808 0.955014 0.3875 +SURF 0x30 +mat 2 +refs 4 +808 0.955014 0.3875 +827 0.958522 0.3875 +828 0.998726 0.31 +809 0.994912 0.31 +SURF 0x30 +mat 2 +refs 4 +809 0.994912 0.31 +828 0.998726 0.31 +829 0.992027 0.247501 +810 0.98826 0.247501 +SURF 0x30 +mat 2 +refs 4 +810 0.98826 0.247501 +829 0.992027 0.247501 +830 0.978625 0.175 +811 0.974963 0.175 +SURF 0x30 +mat 2 +refs 4 +811 0.974963 0.175 +830 0.978625 0.175 +831 0.938422 0.105001 +812 0.935069 0.105001 +SURF 0x30 +mat 2 +refs 4 +812 0.935069 0.105001 +831 0.938422 0.105001 +832 0.834565 0.0549999 +813 0.832006 0.0549999 +SURF 0x30 +mat 2 +refs 4 +813 0.832006 0.0549999 +832 0.834565 0.0549999 +833 0.737411 0.0200004 +814 0.735595 0.0200004 +SURF 0x30 +mat 2 +refs 4 +814 0.735595 0.0200004 +833 0.737411 0.0200004 +834 0.593354 0 +815 0.592638 0 +SURF 0x30 +mat 2 +refs 4 +815 0.592638 0 +834 0.593354 0 +835 0.506248 0 +816 0.506201 0 +SURF 0x30 +mat 2 +refs 4 +817 0.499068 1 +836 0.499102 1 +837 0.54401 0.994999 +818 0.543862 0.994999 +SURF 0x30 +mat 2 +refs 4 +818 0.543862 0.994999 +837 0.54401 0.994999 +838 0.582008 0.984998 +819 0.581762 0.984998 +SURF 0x30 +mat 2 +refs 4 +819 0.581762 0.984998 +838 0.582008 0.984998 +839 0.66837 0.952498 +820 0.667906 0.952498 +SURF 0x30 +mat 2 +refs 4 +820 0.667906 0.952498 +839 0.66837 0.952498 +840 0.692553 0.929999 +821 0.692025 0.929999 +SURF 0x30 +mat 2 +refs 4 +821 0.692025 0.929999 +840 0.692553 0.929999 +841 0.713279 0.8825 +822 0.7127 0.8825 +SURF 0x30 +mat 2 +refs 4 +822 0.7127 0.8825 +841 0.713279 0.8825 +842 0.730551 0.6825 +823 0.729928 0.6825 +SURF 0x30 +mat 2 +refs 4 +823 0.729928 0.6825 +842 0.730551 0.6825 +843 0.75128 0.635 +824 0.7506 0.635 +SURF 0x30 +mat 2 +refs 4 +824 0.7506 0.635 +843 0.75128 0.635 +844 0.823821 0.555 +825 0.82296 0.555 +SURF 0x30 +mat 2 +refs 4 +825 0.82296 0.555 +844 0.823821 0.555 +845 0.888194 0.475 +826 0.887168 0.475 +SURF 0x30 +mat 2 +refs 4 +826 0.887168 0.475 +845 0.888194 0.475 +846 0.959696 0.3875 +827 0.958522 0.3875 +SURF 0x30 +mat 2 +refs 4 +827 0.958522 0.3875 +846 0.959696 0.3875 +847 1 0.31 +828 0.998726 0.31 +SURF 0x30 +mat 2 +refs 4 +828 0.998726 0.31 +847 1 0.31 +848 0.993281 0.247501 +829 0.992027 0.247501 +SURF 0x30 +mat 2 +refs 4 +829 0.992027 0.247501 +848 0.993281 0.247501 +849 0.979846 0.175 +830 0.978625 0.175 +SURF 0x30 +mat 2 +refs 4 +830 0.978625 0.175 +849 0.979846 0.175 +850 0.939542 0.105001 +831 0.938422 0.105001 +SURF 0x30 +mat 2 +refs 4 +831 0.938422 0.105001 +850 0.939542 0.105001 +851 0.835423 0.0549999 +832 0.834565 0.0549999 +SURF 0x30 +mat 2 +refs 4 +832 0.834565 0.0549999 +851 0.835423 0.0549999 +852 0.738016 0.0200004 +833 0.737411 0.0200004 +SURF 0x30 +mat 2 +refs 4 +833 0.737411 0.0200004 +852 0.738016 0.0200004 +853 0.59359 0 +834 0.593354 0 +SURF 0x30 +mat 2 +refs 4 +834 0.593354 0 +853 0.59359 0 +854 0.506265 0 +835 0.506248 0 +SURF 0x30 +mat 2 +refs 4 +836 0.499102 1 +855 0.499068 1 +856 0.543862 0.994999 +837 0.54401 0.994999 +SURF 0x30 +mat 2 +refs 4 +837 0.54401 0.994999 +856 0.543862 0.994999 +857 0.581762 0.984998 +838 0.582008 0.984998 +SURF 0x30 +mat 2 +refs 4 +838 0.582008 0.984998 +857 0.581762 0.984998 +858 0.667906 0.952498 +839 0.66837 0.952498 +SURF 0x30 +mat 2 +refs 4 +839 0.66837 0.952498 +858 0.667906 0.952498 +859 0.692025 0.929999 +840 0.692553 0.929999 +SURF 0x30 +mat 2 +refs 4 +840 0.692553 0.929999 +859 0.692025 0.929999 +860 0.7127 0.8825 +841 0.713279 0.8825 +SURF 0x30 +mat 2 +refs 4 +841 0.713279 0.8825 +860 0.7127 0.8825 +861 0.729928 0.6825 +842 0.730551 0.6825 +SURF 0x30 +mat 2 +refs 4 +842 0.730551 0.6825 +861 0.729928 0.6825 +862 0.7506 0.635 +843 0.75128 0.635 +SURF 0x30 +mat 2 +refs 4 +843 0.75128 0.635 +862 0.7506 0.635 +863 0.82296 0.555 +844 0.823821 0.555 +SURF 0x30 +mat 2 +refs 4 +844 0.823821 0.555 +863 0.82296 0.555 +864 0.887168 0.475 +845 0.888194 0.475 +SURF 0x30 +mat 2 +refs 4 +845 0.888194 0.475 +864 0.887168 0.475 +865 0.958522 0.3875 +846 0.959696 0.3875 +SURF 0x30 +mat 2 +refs 4 +846 0.959696 0.3875 +865 0.958522 0.3875 +866 0.998726 0.31 +847 1 0.31 +SURF 0x30 +mat 2 +refs 4 +847 1 0.31 +866 0.998726 0.31 +867 0.992027 0.247501 +848 0.993281 0.247501 +SURF 0x30 +mat 2 +refs 4 +848 0.993281 0.247501 +867 0.992027 0.247501 +868 0.978625 0.175 +849 0.979846 0.175 +SURF 0x30 +mat 2 +refs 4 +849 0.979846 0.175 +868 0.978625 0.175 +869 0.938422 0.105001 +850 0.939542 0.105001 +SURF 0x30 +mat 2 +refs 4 +850 0.939542 0.105001 +869 0.938422 0.105001 +870 0.834565 0.0549999 +851 0.835423 0.0549999 +SURF 0x30 +mat 2 +refs 4 +851 0.835423 0.0549999 +870 0.834565 0.0549999 +871 0.737411 0.0200004 +852 0.738016 0.0200004 +SURF 0x30 +mat 2 +refs 4 +852 0.738016 0.0200004 +871 0.737411 0.0200004 +872 0.593354 0 +853 0.59359 0 +SURF 0x30 +mat 2 +refs 4 +853 0.59359 0 +872 0.593354 0 +873 0.506248 0 +854 0.506265 0 +SURF 0x30 +mat 2 +refs 4 +855 0.499068 1 +874 0.498964 1 +875 0.543415 0.994999 +856 0.543862 0.994999 +SURF 0x30 +mat 2 +refs 4 +856 0.543862 0.994999 +875 0.543415 0.994999 +876 0.581029 0.984998 +857 0.581762 0.984998 +SURF 0x30 +mat 2 +refs 4 +857 0.581762 0.984998 +876 0.581029 0.984998 +877 0.666511 0.952498 +858 0.667906 0.952498 +SURF 0x30 +mat 2 +refs 4 +858 0.667906 0.952498 +877 0.666511 0.952498 +878 0.690448 0.929999 +859 0.692025 0.929999 +SURF 0x30 +mat 2 +refs 4 +859 0.692025 0.929999 +878 0.690448 0.929999 +879 0.710962 0.8825 +860 0.7127 0.8825 +SURF 0x30 +mat 2 +refs 4 +860 0.7127 0.8825 +879 0.710962 0.8825 +880 0.728059 0.6825 +861 0.729928 0.6825 +SURF 0x30 +mat 0 +refs 4 +861 0.729928 0.6825 +880 0.728059 0.6825 +881 0.748576 0.635 +862 0.7506 0.635 +SURF 0x30 +mat 0 +refs 4 +862 0.7506 0.635 +881 0.748576 0.635 +882 0.82038 0.555 +863 0.82296 0.555 +SURF 0x30 +mat 0 +refs 4 +863 0.82296 0.555 +882 0.82038 0.555 +883 0.884097 0.475 +864 0.887168 0.475 +SURF 0x30 +mat 0 +refs 4 +864 0.887168 0.475 +883 0.884097 0.475 +884 0.955014 0.3875 +865 0.958522 0.3875 +SURF 0x30 +mat 0 +refs 4 +865 0.958522 0.3875 +884 0.955014 0.3875 +885 0.994912 0.31 +866 0.998726 0.31 +SURF 0x30 +mat 0 +refs 4 +866 0.998726 0.31 +885 0.994912 0.31 +886 0.98826 0.247501 +867 0.992027 0.247501 +SURF 0x30 +mat 0 +refs 4 +867 0.992027 0.247501 +886 0.98826 0.247501 +887 0.974963 0.175 +868 0.978625 0.175 +SURF 0x30 +mat 0 +refs 4 +868 0.978625 0.175 +887 0.974963 0.175 +888 0.935069 0.105001 +869 0.938422 0.105001 +SURF 0x30 +mat 0 +refs 4 +869 0.938422 0.105001 +888 0.935069 0.105001 +889 0.832006 0.0549999 +870 0.834565 0.0549999 +SURF 0x30 +mat 0 +refs 4 +870 0.834565 0.0549999 +889 0.832006 0.0549999 +890 0.735595 0.0200004 +871 0.737411 0.0200004 +SURF 0x30 +mat 2 +refs 4 +871 0.737411 0.0200004 +890 0.735595 0.0200004 +891 0.592638 0 +872 0.593354 0 +SURF 0x30 +mat 2 +refs 4 +872 0.593354 0 +891 0.592638 0 +892 0.506201 0 +873 0.506248 0 +SURF 0x30 +mat 2 +refs 4 +874 0.498964 1 +893 0.498796 1 +894 0.542679 0.994999 +875 0.543415 0.994999 +SURF 0x30 +mat 2 +refs 4 +875 0.543415 0.994999 +894 0.542679 0.994999 +895 0.579808 0.984998 +876 0.581029 0.984998 +SURF 0x30 +mat 1 +refs 4 +876 0.581029 0.984998 +895 0.579808 0.984998 +896 0.664197 0.952498 +877 0.666511 0.952498 +SURF 0x30 +mat 0 +refs 4 +877 0.666511 0.952498 +896 0.664197 0.952498 +897 0.687825 0.929999 +878 0.690448 0.929999 +SURF 0x30 +mat 0 +refs 4 +878 0.690448 0.929999 +897 0.687825 0.929999 +898 0.70808 0.8825 +879 0.710962 0.8825 +SURF 0x30 +mat 0 +refs 4 +879 0.710962 0.8825 +898 0.70808 0.8825 +899 0.724958 0.6825 +880 0.728059 0.6825 +SURF 0x30 +mat 0 +refs 4 +880 0.728059 0.6825 +899 0.724958 0.6825 +900 0.74521 0.635 +881 0.748576 0.635 +SURF 0x30 +mat 0 +refs 4 +881 0.748576 0.635 +900 0.74521 0.635 +901 0.816096 0.555 +882 0.82038 0.555 +SURF 0x30 +mat 0 +refs 4 +882 0.82038 0.555 +901 0.816096 0.555 +902 0.878996 0.475 +883 0.884097 0.475 +SURF 0x30 +mat 0 +refs 4 +883 0.884097 0.475 +902 0.878996 0.475 +903 0.94919 0.3875 +884 0.955014 0.3875 +SURF 0x30 +mat 0 +refs 4 +884 0.955014 0.3875 +903 0.94919 0.3875 +904 0.988573 0.31 +885 0.994912 0.31 +SURF 0x30 +mat 0 +refs 4 +885 0.994912 0.31 +904 0.988573 0.31 +905 0.982008 0.247501 +886 0.98826 0.247501 +SURF 0x30 +mat 0 +refs 4 +886 0.98826 0.247501 +905 0.982008 0.247501 +906 0.96888 0.175 +887 0.974963 0.175 +SURF 0x30 +mat 0 +refs 4 +887 0.974963 0.175 +906 0.96888 0.175 +907 0.929497 0.105001 +888 0.935069 0.105001 +SURF 0x30 +mat 0 +refs 4 +888 0.935069 0.105001 +907 0.929497 0.105001 +908 0.827755 0.0549999 +889 0.832006 0.0549999 +SURF 0x30 +mat 0 +refs 4 +889 0.832006 0.0549999 +908 0.827755 0.0549999 +909 0.732578 0.0200004 +890 0.735595 0.0200004 +SURF 0x30 +mat 2 +refs 4 +890 0.735595 0.0200004 +909 0.732578 0.0200004 +910 0.591451 0 +891 0.592638 0 +SURF 0x30 +mat 2 +refs 4 +891 0.592638 0 +910 0.591451 0 +911 0.506121 0 +892 0.506201 0 +SURF 0x30 +mat 2 +refs 4 +893 0.498796 1 +912 0.498561 1 +913 0.54165 0.994999 +894 0.542679 0.994999 +SURF 0x30 +mat 2 +refs 4 +894 0.542679 0.994999 +913 0.54165 0.994999 +914 0.57811 0.984998 +895 0.579808 0.984998 +SURF 0x30 +mat 0 +refs 4 +895 0.579808 0.984998 +914 0.57811 0.984998 +915 0.660972 0.952498 +896 0.664197 0.952498 +SURF 0x30 +mat 0 +refs 4 +896 0.664197 0.952498 +915 0.660972 0.952498 +916 0.684176 0.929999 +897 0.687825 0.929999 +SURF 0x30 +mat 0 +refs 4 +897 0.687825 0.929999 +916 0.684176 0.929999 +917 0.704061 0.8825 +898 0.70808 0.8825 +SURF 0x30 +mat 0 +refs 4 +898 0.70808 0.8825 +917 0.704061 0.8825 +918 0.720633 0.6825 +899 0.724958 0.6825 +SURF 0x30 +mat 0 +refs 4 +899 0.724958 0.6825 +918 0.720633 0.6825 +919 0.740522 0.635 +900 0.74521 0.635 +SURF 0x30 +mat 0 +refs 4 +900 0.74521 0.635 +919 0.740522 0.635 +920 0.810127 0.555 +901 0.816096 0.555 +SURF 0x30 +mat 0 +refs 4 +901 0.816096 0.555 +920 0.810127 0.555 +921 0.871894 0.475 +902 0.878996 0.475 +SURF 0x30 +mat 0 +refs 4 +902 0.878996 0.475 +921 0.871894 0.475 +922 0.941075 0.3875 +903 0.94919 0.3875 +SURF 0x30 +mat 0 +refs 4 +903 0.94919 0.3875 +922 0.941075 0.3875 +923 0.979745 0.31 +904 0.988573 0.31 +SURF 0x30 +mat 0 +refs 4 +904 0.988573 0.31 +923 0.979745 0.31 +924 0.973302 0.247501 +905 0.982008 0.247501 +SURF 0x30 +mat 0 +refs 4 +905 0.982008 0.247501 +924 0.973302 0.247501 +925 0.960409 0.175 +906 0.96888 0.175 +SURF 0x30 +mat 0 +refs 4 +906 0.96888 0.175 +925 0.960409 0.175 +926 0.921739 0.105001 +907 0.929497 0.105001 +SURF 0x30 +mat 0 +refs 4 +907 0.929497 0.105001 +926 0.921739 0.105001 +927 0.821833 0.0549999 +908 0.827755 0.0549999 +SURF 0x30 +mat 0 +refs 4 +908 0.827755 0.0549999 +927 0.821833 0.0549999 +928 0.728375 0.0200004 +909 0.732578 0.0200004 +SURF 0x30 +mat 0 +refs 4 +909 0.732578 0.0200004 +928 0.728375 0.0200004 +929 0.5898 0 +910 0.591451 0 +SURF 0x30 +mat 2 +refs 4 +910 0.591451 0 +929 0.5898 0 +930 0.506009 0 +911 0.506121 0 +SURF 0x30 +mat 2 +refs 4 +912 0.498561 1 +931 0.498258 1 +932 0.540335 0.994999 +913 0.54165 0.994999 +SURF 0x30 +mat 2 +refs 4 +913 0.54165 0.994999 +932 0.540335 0.994999 +933 0.575941 0.984998 +914 0.57811 0.984998 +SURF 0x30 +mat 0 +refs 4 +914 0.57811 0.984998 +933 0.575941 0.984998 +934 0.656856 0.952498 +915 0.660972 0.952498 +SURF 0x30 +mat 0 +refs 4 +915 0.660972 0.952498 +934 0.656856 0.952498 +935 0.679512 0.929999 +916 0.684176 0.929999 +SURF 0x30 +mat 0 +refs 4 +916 0.684176 0.929999 +935 0.679512 0.929999 +936 0.698933 0.8825 +917 0.704061 0.8825 +SURF 0x30 +mat 0 +refs 4 +917 0.704061 0.8825 +936 0.698933 0.8825 +937 0.715115 0.6825 +918 0.720633 0.6825 +SURF 0x30 +mat 0 +refs 4 +918 0.720633 0.6825 +937 0.715115 0.6825 +938 0.734536 0.635 +919 0.740522 0.635 +SURF 0x30 +mat 0 +refs 4 +919 0.740522 0.635 +938 0.734536 0.635 +939 0.802507 0.555 +920 0.810127 0.555 +SURF 0x30 +mat 0 +refs 4 +920 0.810127 0.555 +939 0.802507 0.555 +940 0.86282 0.475 +921 0.871894 0.475 +SURF 0x30 +mat 0 +refs 4 +921 0.871894 0.475 +940 0.86282 0.475 +941 0.930711 0.3875 +922 0.941075 0.3875 +SURF 0x30 +mat 0 +refs 4 +922 0.941075 0.3875 +941 0.930711 0.3875 +942 0.968476 0.31 +923 0.979745 0.31 +SURF 0x30 +mat 0 +refs 4 +923 0.979745 0.31 +942 0.968476 0.31 +943 0.962181 0.247501 +924 0.973302 0.247501 +SURF 0x30 +mat 0 +refs 4 +924 0.973302 0.247501 +943 0.962181 0.247501 +944 0.949593 0.175 +925 0.960409 0.175 +SURF 0x30 +mat 0 +refs 4 +925 0.960409 0.175 +944 0.949593 0.175 +945 0.911828 0.105001 +926 0.921739 0.105001 +SURF 0x30 +mat 0 +refs 4 +926 0.921739 0.105001 +945 0.911828 0.105001 +946 0.814274 0.0549999 +927 0.821833 0.0549999 +SURF 0x30 +mat 0 +refs 4 +927 0.821833 0.0549999 +946 0.814274 0.0549999 +947 0.723011 0.0200004 +928 0.728375 0.0200004 +SURF 0x30 +mat 0 +refs 4 +928 0.728375 0.0200004 +947 0.723011 0.0200004 +948 0.587691 0 +929 0.5898 0 +SURF 0x30 +mat 2 +refs 4 +929 0.5898 0 +948 0.587691 0 +949 0.505868 0 +930 0.506009 0 +SURF 0x30 +mat 2 +refs 4 +931 0.498258 1 +950 0.497895 1 +951 0.538744 0.994999 +932 0.540335 0.994999 +SURF 0x30 +mat 2 +refs 4 +932 0.540335 0.994999 +951 0.538744 0.994999 +952 0.573311 0.984998 +933 0.575941 0.984998 +SURF 0x30 +mat 0 +refs 4 +933 0.575941 0.984998 +952 0.573311 0.984998 +953 0.651869 0.952498 +934 0.656856 0.952498 +SURF 0x30 +mat 0 +refs 4 +934 0.656856 0.952498 +953 0.651869 0.952498 +954 0.673862 0.929999 +935 0.679512 0.929999 +SURF 0x30 +mat 0 +refs 4 +935 0.679512 0.929999 +954 0.673862 0.929999 +955 0.692718 0.8825 +936 0.698933 0.8825 +SURF 0x30 +mat 0 +refs 4 +936 0.698933 0.8825 +955 0.692718 0.8825 +956 0.70843 0.6825 +937 0.715115 0.6825 +SURF 0x30 +mat 0 +refs 4 +937 0.715115 0.6825 +956 0.70843 0.6825 +957 0.727282 0.635 +938 0.734536 0.635 +SURF 0x30 +mat 0 +refs 4 +938 0.734536 0.635 +957 0.727282 0.635 +958 0.793272 0.555 +939 0.802507 0.555 +SURF 0x30 +mat 0 +refs 4 +939 0.802507 0.555 +958 0.793272 0.555 +959 0.851827 0.475 +940 0.86282 0.475 +SURF 0x30 +mat 0 +refs 4 +940 0.86282 0.475 +959 0.851827 0.475 +960 0.918154 0.3875 +941 0.930711 0.3875 +SURF 0x30 +mat 0 +refs 4 +941 0.930711 0.3875 +960 0.918154 0.3875 +961 0.954816 0.31 +942 0.968476 0.31 +SURF 0x30 +mat 0 +refs 4 +942 0.968476 0.31 +961 0.954816 0.31 +962 0.948706 0.247501 +943 0.962181 0.247501 +SURF 0x30 +mat 0 +refs 4 +943 0.962181 0.247501 +962 0.948706 0.247501 +963 0.936485 0.175 +944 0.949593 0.175 +SURF 0x30 +mat 0 +refs 4 +944 0.949593 0.175 +963 0.936485 0.175 +964 0.899823 0.105001 +945 0.911828 0.105001 +SURF 0x30 +mat 0 +refs 4 +945 0.911828 0.105001 +964 0.899823 0.105001 +965 0.80511 0.0549999 +946 0.814274 0.0549999 +SURF 0x30 +mat 0 +refs 4 +946 0.814274 0.0549999 +965 0.80511 0.0549999 +966 0.716507 0.0200004 +947 0.723011 0.0200004 +SURF 0x30 +mat 0 +refs 4 +947 0.723011 0.0200004 +966 0.716507 0.0200004 +967 0.585135 0 +948 0.587691 0 +SURF 0x30 +mat 2 +refs 4 +948 0.587691 0 +967 0.585135 0 +968 0.505697 0 +949 0.505868 0 +SURF 0x30 +mat 2 +refs 4 +950 0.497895 1 +969 0.497468 1 +970 0.536884 0.994999 +951 0.538744 0.994999 +SURF 0x30 +mat 2 +refs 4 +951 0.538744 0.994999 +970 0.536884 0.994999 +971 0.570234 0.984998 +952 0.573311 0.984998 +SURF 0x30 +mat 0 +refs 4 +952 0.573311 0.984998 +971 0.570234 0.984998 +972 0.646031 0.952498 +953 0.651869 0.952498 +SURF 0x30 +mat 0 +refs 4 +953 0.651869 0.952498 +972 0.646031 0.952498 +973 0.667254 0.929999 +954 0.673862 0.929999 +SURF 0x30 +mat 0 +refs 4 +954 0.673862 0.929999 +973 0.667254 0.929999 +974 0.685447 0.8825 +955 0.692718 0.8825 +SURF 0x30 +mat 0 +refs 4 +955 0.692718 0.8825 +974 0.685447 0.8825 +975 0.700607 0.6825 +956 0.70843 0.6825 +SURF 0x30 +mat 0 +refs 4 +956 0.70843 0.6825 +975 0.700607 0.6825 +976 0.718797 0.635 +957 0.727282 0.635 +SURF 0x30 +mat 0 +refs 4 +957 0.727282 0.635 +976 0.718797 0.635 +977 0.782467 0.555 +958 0.793272 0.555 +SURF 0x30 +mat 0 +refs 4 +958 0.793272 0.555 +977 0.782467 0.555 +978 0.838967 0.475 +959 0.851827 0.475 +SURF 0x30 +mat 0 +refs 4 +959 0.851827 0.475 +978 0.838967 0.475 +979 0.903464 0.3875 +960 0.918154 0.3875 +SURF 0x30 +mat 0 +refs 4 +960 0.918154 0.3875 +979 0.903464 0.3875 +980 0.938839 0.31 +961 0.954816 0.31 +SURF 0x30 +mat 0 +refs 4 +961 0.954816 0.31 +980 0.938839 0.31 +981 0.932944 0.247501 +962 0.948706 0.247501 +SURF 0x30 +mat 0 +refs 4 +962 0.948706 0.247501 +981 0.932944 0.247501 +982 0.921153 0.175 +963 0.936485 0.175 +SURF 0x30 +mat 0 +refs 4 +963 0.936485 0.175 +982 0.921153 0.175 +983 0.885779 0.105001 +964 0.899823 0.105001 +SURF 0x30 +mat 0 +refs 4 +964 0.899823 0.105001 +983 0.885779 0.105001 +984 0.794392 0.0549999 +965 0.80511 0.0549999 +SURF 0x30 +mat 0 +refs 4 +965 0.80511 0.0549999 +984 0.794392 0.0549999 +985 0.708904 0.0200004 +966 0.716507 0.0200004 +SURF 0x30 +mat 0 +refs 4 +966 0.716507 0.0200004 +985 0.708904 0.0200004 +986 0.582142 0 +967 0.585135 0 +SURF 0x30 +mat 2 +refs 4 +967 0.585135 0 +986 0.582142 0 +987 0.505498 0 +968 0.505697 0 +SURF 0x30 +mat 2 +refs 4 +969 0.497468 1 +988 0.496983 1 +989 0.534762 0.994999 +970 0.536884 0.994999 +SURF 0x30 +mat 2 +refs 4 +970 0.536884 0.994999 +989 0.534762 0.994999 +990 0.566727 0.984998 +971 0.570234 0.984998 +SURF 0x30 +mat 0 +refs 4 +971 0.570234 0.984998 +990 0.566727 0.984998 +991 0.639379 0.952498 +972 0.646031 0.952498 +SURF 0x30 +mat 0 +refs 4 +972 0.646031 0.952498 +991 0.639379 0.952498 +992 0.659721 0.929999 +973 0.667254 0.929999 +SURF 0x30 +mat 0 +refs 4 +973 0.667254 0.929999 +992 0.659721 0.929999 +993 0.677161 0.8825 +974 0.685447 0.8825 +SURF 0x30 +mat 0 +refs 4 +974 0.685447 0.8825 +993 0.677161 0.8825 +994 0.691689 0.6825 +975 0.700607 0.6825 +SURF 0x30 +mat 0 +refs 4 +975 0.700607 0.6825 +994 0.691689 0.6825 +995 0.709126 0.635 +976 0.718797 0.635 +SURF 0x30 +mat 0 +refs 4 +976 0.718797 0.635 +995 0.709126 0.635 +996 0.770156 0.555 +977 0.782467 0.555 +SURF 0x30 +mat 0 +refs 4 +977 0.782467 0.555 +996 0.770156 0.555 +997 0.824308 0.475 +978 0.838967 0.475 +SURF 0x30 +mat 0 +refs 4 +978 0.838967 0.475 +997 0.824308 0.475 +998 0.886721 0.3875 +979 0.903464 0.3875 +SURF 0x30 +mat 0 +refs 4 +979 0.903464 0.3875 +998 0.886721 0.3875 +999 0.920625 0.31 +980 0.938839 0.31 +SURF 0x30 +mat 0 +refs 4 +980 0.938839 0.31 +999 0.920625 0.31 +1000 0.914976 0.247501 +981 0.932944 0.247501 +SURF 0x30 +mat 0 +refs 4 +981 0.932944 0.247501 +1000 0.914976 0.247501 +1001 0.903673 0.175 +982 0.921153 0.175 +SURF 0x30 +mat 0 +refs 4 +982 0.921153 0.175 +1001 0.903673 0.175 +1002 0.869768 0.105001 +983 0.885779 0.105001 +SURF 0x30 +mat 0 +refs 4 +983 0.885779 0.105001 +1002 0.869768 0.105001 +1003 0.782175 0.0549999 +984 0.794392 0.0549999 +SURF 0x30 +mat 0 +refs 4 +984 0.794392 0.0549999 +1003 0.782175 0.0549999 +1004 0.700234 0.0200004 +985 0.708904 0.0200004 +SURF 0x30 +mat 0 +refs 4 +985 0.708904 0.0200004 +1004 0.700234 0.0200004 +1005 0.578736 0 +986 0.582142 0 +SURF 0x30 +mat 2 +refs 4 +986 0.582142 0 +1005 0.578736 0 +1006 0.50527 0 +987 0.505498 0 +SURF 0x30 +mat 2 +refs 4 +988 0.496983 1 +1007 0.496439 1 +1008 0.532388 0.994999 +989 0.534762 0.994999 +SURF 0x30 +mat 2 +refs 4 +989 0.534762 0.994999 +1008 0.532388 0.994999 +1009 0.562809 0.984998 +990 0.566727 0.984998 +SURF 0x30 +mat 0 +refs 4 +990 0.566727 0.984998 +1009 0.562809 0.984998 +1010 0.631947 0.952498 +991 0.639379 0.952498 +SURF 0x30 +mat 0 +refs 4 +991 0.639379 0.952498 +1010 0.631947 0.952498 +1011 0.651304 0.929999 +992 0.659721 0.929999 +SURF 0x30 +mat 0 +refs 4 +992 0.659721 0.929999 +1011 0.651304 0.929999 +1012 0.667896 0.8825 +993 0.677161 0.8825 +SURF 0x30 +mat 0 +refs 4 +993 0.677161 0.8825 +1012 0.667896 0.8825 +1013 0.681725 0.6825 +994 0.691689 0.6825 +SURF 0x30 +mat 0 +refs 4 +994 0.691689 0.6825 +1013 0.681725 0.6825 +1014 0.698317 0.635 +995 0.709126 0.635 +SURF 0x30 +mat 0 +refs 4 +995 0.709126 0.635 +1014 0.698317 0.635 +1015 0.756391 0.555 +996 0.770156 0.555 +SURF 0x30 +mat 0 +refs 4 +996 0.770156 0.555 +1015 0.756391 0.555 +1016 0.807924 0.475 +997 0.824308 0.475 +SURF 0x30 +mat 0 +refs 4 +997 0.824308 0.475 +1016 0.807924 0.475 +1017 0.868006 0.3875 +998 0.886721 0.3875 +SURF 0x30 +mat 0 +refs 4 +998 0.886721 0.3875 +1017 0.868006 0.3875 +1018 0.90027 0.31 +999 0.920625 0.31 +SURF 0x30 +mat 0 +refs 4 +999 0.920625 0.31 +1018 0.90027 0.31 +1019 0.894892 0.247501 +1000 0.914976 0.247501 +SURF 0x30 +mat 0 +refs 4 +1000 0.914976 0.247501 +1019 0.894892 0.247501 +1020 0.884138 0.175 +1001 0.903673 0.175 +SURF 0x30 +mat 0 +refs 4 +1001 0.903673 0.175 +1020 0.884138 0.175 +1021 0.851871 0.105001 +1002 0.869768 0.105001 +SURF 0x30 +mat 0 +refs 4 +1002 0.869768 0.105001 +1021 0.851871 0.105001 +1022 0.768518 0.0549999 +1003 0.782175 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1003 0.782175 0.0549999 +1022 0.768518 0.0549999 +1023 0.690542 0.0200004 +1004 0.700234 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1004 0.700234 0.0200004 +1023 0.690542 0.0200004 +1024 0.574922 0 +1005 0.578736 0 +SURF 0x30 +mat 2 +refs 4 +1005 0.578736 0 +1024 0.574922 0 +1025 0.505014 0 +1006 0.50527 0 +SURF 0x30 +mat 2 +refs 4 +1007 0.496439 1 +1026 0.49584 1 +1027 0.529779 0.994999 +1008 0.532388 0.994999 +SURF 0x30 +mat 0 +refs 4 +1008 0.532388 0.994999 +1027 0.529779 0.994999 +1028 0.558498 0.984998 +1009 0.562809 0.984998 +SURF 0x30 +mat 0 +refs 4 +1009 0.562809 0.984998 +1028 0.558498 0.984998 +1029 0.623765 0.952498 +1010 0.631947 0.952498 +SURF 0x30 +mat 0 +refs 4 +1010 0.631947 0.952498 +1029 0.623765 0.952498 +1030 0.642042 0.929999 +1011 0.651304 0.929999 +SURF 0x30 +mat 0 +refs 4 +1011 0.651304 0.929999 +1030 0.642042 0.929999 +1031 0.657703 0.8825 +1012 0.667896 0.8825 +SURF 0x30 +mat 0 +refs 4 +1012 0.667896 0.8825 +1031 0.657703 0.8825 +1032 0.670758 0.6825 +1013 0.681725 0.6825 +SURF 0x30 +mat 0 +refs 4 +1013 0.681725 0.6825 +1032 0.670758 0.6825 +1033 0.686423 0.635 +1014 0.698317 0.635 +SURF 0x30 +mat 0 +refs 4 +1014 0.698317 0.635 +1033 0.686423 0.635 +1034 0.741248 0.555 +1015 0.756391 0.555 +SURF 0x30 +mat 0 +refs 4 +1015 0.756391 0.555 +1034 0.741248 0.555 +1035 0.789896 0.475 +1016 0.807924 0.475 +SURF 0x30 +mat 0 +refs 4 +1016 0.807924 0.475 +1035 0.789896 0.475 +1036 0.847415 0.3875 +1017 0.868006 0.3875 +SURF 0x30 +mat 0 +refs 4 +1017 0.868006 0.3875 +1036 0.847415 0.3875 +1037 0.877876 0.31 +1018 0.90027 0.31 +SURF 0x30 +mat 0 +refs 4 +1018 0.90027 0.31 +1037 0.877876 0.31 +1038 0.872798 0.247501 +1019 0.894892 0.247501 +SURF 0x30 +mat 0 +refs 4 +1019 0.894892 0.247501 +1038 0.872798 0.247501 +1039 0.862646 0.175 +1020 0.884138 0.175 +SURF 0x30 +mat 0 +refs 4 +1020 0.884138 0.175 +1039 0.862646 0.175 +1040 0.832184 0.105001 +1021 0.851871 0.105001 +SURF 0x30 +mat 0 +refs 4 +1021 0.851871 0.105001 +1040 0.832184 0.105001 +1041 0.753496 0.0549999 +1022 0.768518 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1022 0.768518 0.0549999 +1041 0.753496 0.0549999 +1042 0.679882 0.0200004 +1023 0.690542 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1023 0.690542 0.0200004 +1042 0.679882 0.0200004 +1043 0.570732 0 +1024 0.574922 0 +SURF 0x30 +mat 2 +refs 4 +1024 0.574922 0 +1043 0.570732 0 +1044 0.504735 0 +1025 0.505014 0 +SURF 0x30 +mat 2 +refs 4 +1026 0.49584 1 +1045 0.495191 1 +1046 0.526947 0.994999 +1027 0.529779 0.994999 +SURF 0x30 +mat 0 +refs 4 +1027 0.529779 0.994999 +1046 0.526947 0.994999 +1047 0.553817 0.984998 +1028 0.558498 0.984998 +SURF 0x30 +mat 0 +refs 4 +1028 0.558498 0.984998 +1047 0.553817 0.984998 +1048 0.614884 0.952498 +1029 0.623765 0.952498 +SURF 0x30 +mat 0 +refs 4 +1029 0.623765 0.952498 +1048 0.614884 0.952498 +1049 0.631981 0.929999 +1030 0.642042 0.929999 +SURF 0x30 +mat 0 +refs 4 +1030 0.642042 0.929999 +1049 0.631981 0.929999 +1050 0.646636 0.8825 +1031 0.657703 0.8825 +SURF 0x30 +mat 0 +refs 4 +1031 0.657703 0.8825 +1050 0.646636 0.8825 +1051 0.65885 0.6825 +1032 0.670758 0.6825 +SURF 0x30 +mat 0 +refs 4 +1032 0.670758 0.6825 +1051 0.65885 0.6825 +1052 0.673506 0.635 +1033 0.686423 0.635 +SURF 0x30 +mat 0 +refs 4 +1033 0.686423 0.635 +1052 0.673506 0.635 +1053 0.724803 0.555 +1034 0.741248 0.555 +SURF 0x30 +mat 0 +refs 4 +1034 0.741248 0.555 +1053 0.724803 0.555 +1054 0.77032 0.475 +1035 0.789896 0.475 +SURF 0x30 +mat 0 +refs 4 +1035 0.789896 0.475 +1054 0.77032 0.475 +1055 0.825055 0.3875 +1036 0.847415 0.3875 +SURF 0x30 +mat 0 +refs 4 +1036 0.847415 0.3875 +1055 0.825055 0.3875 +1056 0.853552 0.31 +1037 0.877876 0.31 +SURF 0x30 +mat 0 +refs 4 +1037 0.877876 0.31 +1056 0.853552 0.31 +1057 0.848804 0.247501 +1038 0.872798 0.247501 +SURF 0x30 +mat 0 +refs 4 +1038 0.872798 0.247501 +1057 0.848804 0.247501 +1058 0.839304 0.175 +1039 0.862646 0.175 +SURF 0x30 +mat 0 +refs 4 +1039 0.862646 0.175 +1058 0.839304 0.175 +1059 0.810803 0.105001 +1040 0.832184 0.105001 +SURF 0x30 +mat 0 +refs 4 +1040 0.832184 0.105001 +1059 0.810803 0.105001 +1060 0.737179 0.0549999 +1041 0.753496 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1041 0.753496 0.0549999 +1060 0.737179 0.0549999 +1061 0.668303 0.0200004 +1042 0.679882 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1042 0.679882 0.0200004 +1061 0.668303 0.0200004 +1062 0.566179 0 +1043 0.570732 0 +SURF 0x30 +mat 1 +refs 4 +1043 0.570732 0 +1062 0.566179 0 +1063 0.504429 0 +1044 0.504735 0 +SURF 0x30 +mat 2 +refs 4 +1045 0.495191 1 +1064 0.494495 1 +1065 0.523904 0.994999 +1046 0.526947 0.994999 +SURF 0x30 +mat 0 +refs 4 +1046 0.526947 0.994999 +1065 0.523904 0.994999 +1066 0.548786 0.984998 +1047 0.553817 0.984998 +SURF 0x30 +mat 0 +refs 4 +1047 0.553817 0.984998 +1066 0.548786 0.984998 +1067 0.605343 0.952498 +1048 0.614884 0.952498 +SURF 0x30 +mat 0 +refs 4 +1048 0.614884 0.952498 +1067 0.605343 0.952498 +1068 0.621176 0.929999 +1049 0.631981 0.929999 +SURF 0x30 +mat 0 +refs 4 +1049 0.631981 0.929999 +1068 0.621176 0.929999 +1069 0.634752 0.8825 +1050 0.646636 0.8825 +SURF 0x30 +mat 0 +refs 4 +1050 0.646636 0.8825 +1069 0.634752 0.8825 +1070 0.646061 0.6825 +1051 0.65885 0.6825 +SURF 0x30 +mat 0 +refs 4 +1051 0.65885 0.6825 +1070 0.646061 0.6825 +1071 0.659634 0.635 +1052 0.673506 0.635 +SURF 0x30 +mat 0 +refs 4 +1052 0.673506 0.635 +1071 0.659634 0.635 +1072 0.707142 0.555 +1053 0.724803 0.555 +SURF 0x30 +mat 0 +refs 4 +1053 0.724803 0.555 +1072 0.707142 0.555 +1073 0.749295 0.475 +1054 0.77032 0.475 +SURF 0x30 +mat 0 +refs 4 +1054 0.77032 0.475 +1073 0.749295 0.475 +1074 0.801037 0.3875 +1055 0.825055 0.3875 +SURF 0x30 +mat 0 +refs 4 +1055 0.825055 0.3875 +1074 0.801037 0.3875 +1075 0.827429 0.31 +1056 0.853552 0.31 +SURF 0x30 +mat 0 +refs 4 +1056 0.853552 0.31 +1075 0.827429 0.31 +1076 0.823031 0.247501 +1057 0.848804 0.247501 +SURF 0x30 +mat 0 +refs 4 +1057 0.848804 0.247501 +1076 0.823031 0.247501 +1077 0.814233 0.175 +1058 0.839304 0.175 +SURF 0x30 +mat 0 +refs 4 +1058 0.839304 0.175 +1077 0.814233 0.175 +1078 0.787838 0.105001 +1059 0.810803 0.105001 +SURF 0x30 +mat 0 +refs 4 +1059 0.810803 0.105001 +1078 0.787838 0.105001 +1079 0.719655 0.0549999 +1060 0.737179 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1060 0.737179 0.0549999 +1079 0.719655 0.0549999 +1080 0.655867 0.0200004 +1061 0.668303 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1061 0.668303 0.0200004 +1080 0.655867 0.0200004 +1081 0.561289 0 +1062 0.566179 0 +SURF 0x30 +mat 1 +refs 4 +1062 0.566179 0 +1081 0.561289 0 +1082 0.504103 0 +1063 0.504429 0 +SURF 0x30 +mat 2 +refs 4 +1064 0.494495 1 +1083 0.493752 1 +1084 0.520665 0.994999 +1065 0.523904 0.994999 +SURF 0x30 +mat 0 +refs 4 +1065 0.523904 0.994999 +1084 0.520665 0.994999 +1085 0.543435 0.984998 +1066 0.548786 0.984998 +SURF 0x30 +mat 0 +refs 4 +1066 0.548786 0.984998 +1085 0.543435 0.984998 +1086 0.59519 0.952498 +1067 0.605343 0.952498 +SURF 0x30 +mat 0 +refs 4 +1067 0.605343 0.952498 +1086 0.59519 0.952498 +1087 0.609681 0.929999 +1068 0.621176 0.929999 +SURF 0x30 +mat 0 +refs 4 +1068 0.621176 0.929999 +1087 0.609681 0.929999 +1088 0.622104 0.8825 +1069 0.634752 0.8825 +SURF 0x30 +mat 0 +refs 4 +1069 0.634752 0.8825 +1088 0.622104 0.8825 +1089 0.632455 0.6825 +1070 0.646061 0.6825 +SURF 0x30 +mat 0 +refs 4 +1070 0.646061 0.6825 +1089 0.632455 0.6825 +1090 0.644874 0.635 +1071 0.659634 0.635 +SURF 0x30 +mat 0 +refs 4 +1071 0.659634 0.635 +1090 0.644874 0.635 +1091 0.68835 0.555 +1072 0.707142 0.555 +SURF 0x30 +mat 0 +refs 4 +1072 0.707142 0.555 +1091 0.68835 0.555 +1092 0.726925 0.475 +1073 0.749295 0.475 +SURF 0x30 +mat 0 +refs 4 +1073 0.749295 0.475 +1092 0.726925 0.475 +1093 0.775486 0.3875 +1074 0.801037 0.3875 +SURF 0x30 +mat 0 +refs 4 +1074 0.801037 0.3875 +1093 0.775486 0.3875 +1094 0.799638 0.31 +1075 0.827429 0.31 +SURF 0x30 +mat 0 +refs 4 +1075 0.827429 0.31 +1094 0.799638 0.31 +1095 0.795613 0.247501 +1076 0.823031 0.247501 +SURF 0x30 +mat 0 +refs 4 +1076 0.823031 0.247501 +1095 0.795613 0.247501 +1096 0.787562 0.175 +1077 0.814233 0.175 +SURF 0x30 +mat 0 +refs 4 +1077 0.814233 0.175 +1096 0.787562 0.175 +1097 0.76341 0.105001 +1078 0.787838 0.105001 +SURF 0x30 +mat 0 +refs 4 +1078 0.787838 0.105001 +1097 0.76341 0.105001 +1098 0.701011 0.0549999 +1079 0.719655 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1079 0.719655 0.0549999 +1098 0.701011 0.0549999 +1099 0.642638 0.0200004 +1080 0.655867 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1080 0.655867 0.0200004 +1099 0.642638 0.0200004 +1100 0.556087 0 +1081 0.561289 0 +SURF 0x30 +mat 1 +refs 4 +1081 0.561289 0 +1100 0.556087 0 +1101 0.503753 0 +1082 0.504103 0 +SURF 0x30 +mat 2 +refs 4 +1083 0.493752 1 +1102 0.492968 1 +1103 0.517248 0.994999 +1084 0.520665 0.994999 +SURF 0x30 +mat 0 +refs 4 +1084 0.520665 0.994999 +1103 0.517248 0.994999 +1104 0.537792 0.984998 +1085 0.543435 0.984998 +SURF 0x30 +mat 0 +refs 4 +1085 0.543435 0.984998 +1104 0.537792 0.984998 +1105 0.584483 0.952498 +1086 0.59519 0.952498 +SURF 0x30 +mat 0 +refs 4 +1086 0.59519 0.952498 +1105 0.584483 0.952498 +1106 0.597555 0.929999 +1087 0.609681 0.929999 +SURF 0x30 +mat 0 +refs 4 +1087 0.609681 0.929999 +1106 0.597555 0.929999 +1107 0.608763 0.8825 +1088 0.622104 0.8825 +SURF 0x30 +mat 0 +refs 4 +1088 0.622104 0.8825 +1107 0.608763 0.8825 +1108 0.618098 0.6825 +1089 0.632455 0.6825 +SURF 0x30 +mat 0 +refs 4 +1089 0.632455 0.6825 +1108 0.618098 0.6825 +1109 0.629307 0.635 +1090 0.644874 0.635 +SURF 0x30 +mat 0 +refs 4 +1090 0.644874 0.635 +1109 0.629307 0.635 +1110 0.668525 0.555 +1091 0.68835 0.555 +SURF 0x30 +mat 0 +refs 4 +1091 0.68835 0.555 +1110 0.668525 0.555 +1111 0.703328 0.475 +1092 0.726925 0.475 +SURF 0x30 +mat 0 +refs 4 +1092 0.726925 0.475 +1111 0.703328 0.475 +1112 0.748529 0.3875 +1093 0.775486 0.3875 +SURF 0x30 +mat 0 +refs 4 +1093 0.775486 0.3875 +1112 0.748529 0.3875 +1113 0.77032 0.31 +1094 0.799638 0.31 +SURF 0x30 +mat 0 +refs 4 +1094 0.799638 0.31 +1113 0.77032 0.31 +1114 0.766688 0.247501 +1095 0.795613 0.247501 +SURF 0x30 +mat 0 +refs 4 +1095 0.795613 0.247501 +1114 0.766688 0.247501 +1115 0.759425 0.175 +1096 0.787562 0.175 +SURF 0x30 +mat 0 +refs 4 +1096 0.787562 0.175 +1115 0.759425 0.175 +1116 0.737636 0.105001 +1097 0.76341 0.105001 +SURF 0x30 +mat 0 +refs 4 +1097 0.76341 0.105001 +1116 0.737636 0.105001 +1117 0.681341 0.0549999 +1098 0.701011 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1098 0.701011 0.0549999 +1117 0.681341 0.0549999 +1118 0.628682 0.0200004 +1099 0.642638 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1099 0.642638 0.0200004 +1118 0.628682 0.0200004 +1119 0.550598 0 +1100 0.556087 0 +SURF 0x30 +mat 1 +refs 4 +1100 0.556087 0 +1119 0.550598 0 +1120 0.503386 0 +1101 0.503753 0 +SURF 0x30 +mat 2 +refs 4 +1102 0.492968 1 +1121 0.492148 1 +1122 0.51367 0.994999 +1103 0.517248 0.994999 +SURF 0x30 +mat 0 +refs 4 +1103 0.517248 0.994999 +1122 0.51367 0.994999 +1123 0.531884 0.984998 +1104 0.537792 0.984998 +SURF 0x30 +mat 0 +refs 4 +1104 0.537792 0.984998 +1123 0.531884 0.984998 +1124 0.573271 0.952498 +1105 0.584483 0.952498 +SURF 0x30 +mat 0 +refs 4 +1105 0.584483 0.952498 +1124 0.573271 0.952498 +1125 0.58486 0.929999 +1106 0.597555 0.929999 +SURF 0x30 +mat 0 +refs 4 +1106 0.597555 0.929999 +1125 0.58486 0.929999 +1126 0.594794 0.8825 +1107 0.608763 0.8825 +SURF 0x30 +mat 0 +refs 4 +1107 0.608763 0.8825 +1126 0.594794 0.8825 +1127 0.60307 0.6825 +1108 0.618098 0.6825 +SURF 0x30 +mat 0 +refs 4 +1108 0.618098 0.6825 +1127 0.60307 0.6825 +1128 0.613004 0.635 +1109 0.629307 0.635 +SURF 0x30 +mat 0 +refs 4 +1109 0.629307 0.635 +1128 0.613004 0.635 +1129 0.647773 0.555 +1110 0.668525 0.555 +SURF 0x30 +mat 0 +refs 4 +1110 0.668525 0.555 +1129 0.647773 0.555 +1130 0.678621 0.475 +1111 0.703328 0.475 +SURF 0x30 +mat 0 +refs 4 +1111 0.703328 0.475 +1130 0.678621 0.475 +1131 0.720307 0.3875 +1112 0.748529 0.3875 +SURF 0x30 +mat 0 +refs 4 +1112 0.748529 0.3875 +1131 0.720307 0.3875 +1132 0.739624 0.31 +1113 0.77032 0.31 +SURF 0x30 +mat 0 +refs 4 +1113 0.77032 0.31 +1132 0.739624 0.31 +1133 0.736405 0.247501 +1114 0.766688 0.247501 +SURF 0x30 +mat 0 +refs 4 +1114 0.766688 0.247501 +1133 0.736405 0.247501 +1134 0.729965 0.175 +1115 0.759425 0.175 +SURF 0x30 +mat 0 +refs 4 +1115 0.759425 0.175 +1134 0.729965 0.175 +1135 0.710649 0.105001 +1116 0.737636 0.105001 +SURF 0x30 +mat 0 +refs 4 +1116 0.737636 0.105001 +1135 0.710649 0.105001 +1136 0.66075 0.0549999 +1117 0.681341 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1117 0.681341 0.0549999 +1136 0.66075 0.0549999 +1137 0.61407 0.0200004 +1118 0.628682 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1118 0.628682 0.0200004 +1137 0.61407 0.0200004 +1138 0.544854 0 +1119 0.550598 0 +SURF 0x30 +mat 1 +refs 4 +1119 0.550598 0 +1138 0.544854 0 +1139 0.503003 0 +1120 0.503386 0 +SURF 0x30 +mat 2 +refs 4 +1121 0.492148 1 +1140 0.491297 1 +1141 0.509951 0.994999 +1122 0.51367 0.994999 +SURF 0x30 +mat 0 +refs 4 +1122 0.51367 0.994999 +1141 0.509951 0.994999 +1142 0.525736 0.984998 +1123 0.531884 0.984998 +SURF 0x30 +mat 0 +refs 4 +1123 0.531884 0.984998 +1142 0.525736 0.984998 +1143 0.561615 0.952498 +1124 0.573271 0.952498 +SURF 0x30 +mat 0 +refs 4 +1124 0.573271 0.952498 +1143 0.561615 0.952498 +1144 0.57166 0.929999 +1125 0.58486 0.929999 +SURF 0x30 +mat 0 +refs 4 +1125 0.58486 0.929999 +1144 0.57166 0.929999 +1145 0.580269 0.8825 +1126 0.594794 0.8825 +SURF 0x30 +mat 0 +refs 4 +1126 0.594794 0.8825 +1145 0.580269 0.8825 +1146 0.587446 0.6825 +1127 0.60307 0.6825 +SURF 0x30 +mat 0 +refs 4 +1127 0.60307 0.6825 +1146 0.587446 0.6825 +1147 0.596055 0.635 +1128 0.613004 0.635 +SURF 0x30 +mat 0 +refs 4 +1128 0.613004 0.635 +1147 0.596055 0.635 +1148 0.62619 0.555 +1129 0.647773 0.555 +SURF 0x30 +mat 0 +refs 4 +1129 0.647773 0.555 +1148 0.62619 0.555 +1149 0.652931 0.475 +1130 0.678621 0.475 +SURF 0x30 +mat 0 +refs 4 +1130 0.678621 0.475 +1149 0.652931 0.475 +1150 0.690966 0.3875 +1131 0.720307 0.3875 +SURF 0x30 +mat 0 +refs 4 +1131 0.720307 0.3875 +1150 0.690966 0.3875 +1151 0.707707 0.31 +1132 0.739624 0.31 +SURF 0x30 +mat 0 +refs 4 +1132 0.739624 0.31 +1151 0.707707 0.31 +1152 0.704919 0.247501 +1133 0.736405 0.247501 +SURF 0x30 +mat 0 +refs 4 +1133 0.736405 0.247501 +1152 0.704919 0.247501 +1153 0.699336 0.175 +1134 0.729965 0.175 +SURF 0x30 +mat 0 +refs 4 +1134 0.729965 0.175 +1153 0.699336 0.175 +1154 0.682592 0.105001 +1135 0.710649 0.105001 +SURF 0x30 +mat 0 +refs 4 +1135 0.710649 0.105001 +1154 0.682592 0.105001 +1155 0.639339 0.0549999 +1136 0.66075 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1136 0.66075 0.0549999 +1155 0.639339 0.0549999 +1156 0.598876 0.0200004 +1137 0.61407 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1137 0.61407 0.0200004 +1156 0.598876 0.0200004 +1157 0.538879 0 +1138 0.544854 0 +SURF 0x30 +mat 1 +refs 4 +1138 0.544854 0 +1157 0.538879 0 +1158 0.502603 0 +1139 0.503003 0 +SURF 0x30 +mat 2 +refs 4 +1140 0.491297 1 +1159 0.490416 1 +1160 0.50611 0.994999 +1141 0.509951 0.994999 +SURF 0x30 +mat 0 +refs 4 +1141 0.509951 0.994999 +1160 0.50611 0.994999 +1161 0.519391 0.984998 +1142 0.525736 0.984998 +SURF 0x30 +mat 0 +refs 4 +1142 0.525736 0.984998 +1161 0.519391 0.984998 +1162 0.549569 0.952498 +1143 0.561615 0.952498 +SURF 0x30 +mat 0 +refs 4 +1143 0.561615 0.952498 +1162 0.549569 0.952498 +1163 0.55802 0.929999 +1144 0.57166 0.929999 +SURF 0x30 +mat 0 +refs 4 +1144 0.57166 0.929999 +1163 0.55802 0.929999 +1164 0.565264 0.8825 +1145 0.580269 0.8825 +SURF 0x30 +mat 0 +refs 4 +1145 0.580269 0.8825 +1164 0.565264 0.8825 +1165 0.5713 0.6825 +1146 0.587446 0.6825 +SURF 0x30 +mat 0 +refs 4 +1146 0.587446 0.6825 +1165 0.5713 0.6825 +1166 0.578544 0.635 +1147 0.596055 0.635 +SURF 0x30 +mat 0 +refs 4 +1147 0.596055 0.635 +1166 0.578544 0.635 +1167 0.603894 0.555 +1148 0.62619 0.555 +SURF 0x30 +mat 0 +refs 4 +1148 0.62619 0.555 +1167 0.603894 0.555 +1168 0.626391 0.475 +1149 0.652931 0.475 +SURF 0x30 +mat 0 +refs 4 +1149 0.652931 0.475 +1168 0.626391 0.475 +1169 0.660646 0.3875 +1150 0.690966 0.3875 +SURF 0x30 +mat 0 +refs 4 +1150 0.690966 0.3875 +1169 0.660646 0.3875 +1170 0.674733 0.31 +1151 0.707707 0.31 +SURF 0x30 +mat 0 +refs 4 +1151 0.707707 0.31 +1170 0.674733 0.31 +1171 0.672386 0.247501 +1152 0.704919 0.247501 +SURF 0x30 +mat 0 +refs 4 +1152 0.704919 0.247501 +1171 0.672386 0.247501 +1172 0.667691 0.175 +1153 0.699336 0.175 +SURF 0x30 +mat 0 +refs 4 +1153 0.699336 0.175 +1172 0.667691 0.175 +1173 0.653604 0.105001 +1154 0.682592 0.105001 +SURF 0x30 +mat 0 +refs 4 +1154 0.682592 0.105001 +1173 0.653604 0.105001 +1174 0.422996 0.0519236 +1155 0.639339 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1155 0.639339 0.0549999 +1174 0.422996 0.0519236 +1175 0.583178 0.0200004 +1156 0.598876 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1156 0.598876 0.0200004 +1175 0.583178 0.0200004 +1176 0.532708 0 +1157 0.538879 0 +SURF 0x30 +mat 1 +refs 4 +1157 0.538879 0 +1176 0.532708 0 +1177 0.502189 0 +1158 0.502603 0 +SURF 0x30 +mat 2 +refs 4 +1159 0.490416 1 +1178 0.489511 1 +1179 0.502166 0.994999 +1160 0.50611 0.994999 +SURF 0x30 +mat 0 +refs 4 +1160 0.50611 0.994999 +1179 0.502166 0.994999 +1180 0.51287 0.984998 +1161 0.519391 0.984998 +SURF 0x30 +mat 0 +refs 4 +1161 0.519391 0.984998 +1180 0.51287 0.984998 +1181 0.537201 0.952498 +1162 0.549569 0.952498 +SURF 0x30 +mat 0 +refs 4 +1162 0.549569 0.952498 +1181 0.537201 0.952498 +1182 0.544014 0.929999 +1163 0.55802 0.929999 +SURF 0x30 +mat 0 +refs 4 +1163 0.55802 0.929999 +1182 0.544014 0.929999 +1183 0.549852 0.8825 +1164 0.565264 0.8825 +SURF 0x30 +mat 0 +refs 4 +1164 0.565264 0.8825 +1183 0.549852 0.8825 +1184 0.554718 0.6825 +1165 0.5713 0.6825 +SURF 0x30 +mat 0 +refs 4 +1165 0.5713 0.6825 +1184 0.554718 0.6825 +1185 0.560559 0.635 +1166 0.578544 0.635 +SURF 0x30 +mat 0 +refs 4 +1166 0.578544 0.635 +1185 0.560559 0.635 +1186 0.580996 0.555 +1167 0.603894 0.555 +SURF 0x30 +mat 0 +refs 4 +1167 0.603894 0.555 +1186 0.580996 0.555 +1187 0.599132 0.475 +1168 0.626391 0.475 +SURF 0x30 +mat 0 +refs 4 +1168 0.626391 0.475 +1187 0.599132 0.475 +1188 0.629512 0.3875 +1169 0.660646 0.3875 +SURF 0x30 +mat 0 +refs 4 +1169 0.660646 0.3875 +1188 0.629512 0.3875 +1189 0.640865 0.31 +1170 0.674733 0.31 +SURF 0x30 +mat 0 +refs 4 +1170 0.674733 0.31 +1189 0.640865 0.31 +1190 0.638975 0.247501 +1171 0.672386 0.247501 +SURF 0x30 +mat 0 +refs 4 +1171 0.672386 0.247501 +1190 0.638975 0.247501 +1191 0.635189 0.175 +1172 0.667691 0.175 +SURF 0x30 +mat 0 +refs 4 +1172 0.667691 0.175 +1191 0.635189 0.175 +1174 0.422996 0.0519236 +1173 0.653604 0.105001 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1192 0.567056 0.0200004 +1175 0.583178 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1175 0.583178 0.0200004 +1192 0.567056 0.0200004 +1193 0.526369 0 +1176 0.532708 0 +SURF 0x30 +mat 1 +refs 4 +1176 0.532708 0 +1193 0.526369 0 +1194 0.501766 0 +1177 0.502189 0 +SURF 0x30 +mat 2 +refs 4 +1178 0.489511 1 +1195 0.48859 1 +1196 0.498134 0.994999 +1179 0.502166 0.994999 +SURF 0x30 +mat 0 +refs 4 +1179 0.502166 0.994999 +1196 0.498134 0.994999 +1197 0.506211 0.984998 +1180 0.51287 0.984998 +SURF 0x30 +mat 0 +refs 4 +1180 0.51287 0.984998 +1197 0.506211 0.984998 +1198 0.524569 0.952498 +1181 0.537201 0.952498 +SURF 0x30 +mat 0 +refs 4 +1181 0.537201 0.952498 +1198 0.524569 0.952498 +1199 0.529711 0.929999 +1182 0.544014 0.929999 +SURF 0x30 +mat 0 +refs 4 +1182 0.544014 0.929999 +1199 0.529711 0.929999 +1200 0.534117 0.8825 +1183 0.549852 0.8825 +SURF 0x30 +mat 0 +refs 4 +1183 0.549852 0.8825 +1200 0.534117 0.8825 +1201 0.537786 0.6825 +1184 0.554718 0.6825 +SURF 0x30 +mat 0 +refs 4 +1184 0.554718 0.6825 +1201 0.537786 0.6825 +1202 0.542194 0.635 +1185 0.560559 0.635 +SURF 0x30 +mat 0 +refs 4 +1185 0.560559 0.635 +1202 0.542194 0.635 +1203 0.557613 0.555 +1186 0.580996 0.555 +SURF 0x30 +mat 0 +refs 4 +1186 0.580996 0.555 +1203 0.557613 0.555 +1204 0.571297 0.475 +1187 0.599132 0.475 +SURF 0x30 +mat 0 +refs 4 +1187 0.599132 0.475 +1204 0.571297 0.475 +1205 0.597716 0.3875 +1188 0.629512 0.3875 +SURF 0x30 +mat 0 +refs 4 +1188 0.629512 0.3875 +1205 0.597716 0.3875 +1206 0.606285 0.31 +1189 0.640865 0.31 +SURF 0x30 +mat 0 +refs 4 +1189 0.640865 0.31 +1206 0.606285 0.31 +1174 0.422996 0.0519236 +1190 0.638975 0.247501 +SURF 0x30 +mat 0 +refs 3 +1190 0.638975 0.247501 +1174 0.422996 0.0519236 +1191 0.635189 0.175 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1207 0.550595 0.0200004 +1192 0.567056 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1192 0.567056 0.0200004 +1207 0.550595 0.0200004 +1208 0.519895 0 +1193 0.526369 0 +SURF 0x30 +mat 1 +refs 4 +1193 0.526369 0 +1208 0.519895 0 +1209 0.501332 0 +1194 0.501766 0 +SURF 0x30 +mat 2 +refs 4 +1195 0.48859 1 +1210 0.487651 1 +1211 0.494041 0.994999 +1196 0.498134 0.994999 +SURF 0x30 +mat 0 +refs 4 +1196 0.498134 0.994999 +1211 0.494041 0.994999 +1212 0.499449 0.984998 +1197 0.506211 0.984998 +SURF 0x30 +mat 0 +refs 4 +1197 0.506211 0.984998 +1212 0.499449 0.984998 +1213 0.51174 0.952498 +1198 0.524569 0.952498 +SURF 0x30 +mat 0 +refs 4 +1198 0.524569 0.952498 +1213 0.51174 0.952498 +1214 0.51518 0.929999 +1199 0.529711 0.929999 +SURF 0x30 +mat 0 +refs 4 +1199 0.529711 0.929999 +1214 0.51518 0.929999 +1215 0.518133 0.8825 +1200 0.534117 0.8825 +SURF 0x30 +mat 0 +refs 4 +1200 0.534117 0.8825 +1215 0.518133 0.8825 +1216 0.520591 0.6825 +1201 0.537786 0.6825 +SURF 0x30 +mat 0 +refs 4 +1201 0.537786 0.6825 +1216 0.520591 0.6825 +1217 0.52354 0.635 +1202 0.542194 0.635 +SURF 0x30 +mat 0 +refs 4 +1202 0.542194 0.635 +1217 0.52354 0.635 +1218 0.533864 0.555 +1203 0.557613 0.555 +SURF 0x30 +mat 0 +refs 4 +1203 0.557613 0.555 +1218 0.533864 0.555 +1219 0.543025 0.475 +1204 0.571297 0.475 +SURF 0x30 +mat 0 +refs 4 +1204 0.571297 0.475 +1219 0.543025 0.475 +1220 0.565422 0.3875 +1205 0.597716 0.3875 +SURF 0x30 +mat 0 +refs 4 +1205 0.597716 0.3875 +1220 0.565422 0.3875 +1221 0.571159 0.31 +1206 0.606285 0.31 +SURF 0x30 +mat 0 +refs 3 +1206 0.606285 0.31 +1221 0.571159 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1222 0.533875 0.0200004 +1207 0.550595 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1207 0.550595 0.0200004 +1222 0.533875 0.0200004 +1223 0.513321 0 +1208 0.519895 0 +SURF 0x30 +mat 1 +refs 4 +1208 0.519895 0 +1223 0.513321 0 +1224 0.500891 0 +1209 0.501332 0 +SURF 0x30 +mat 2 +refs 4 +1210 0.487651 1 +1225 0.486703 1 +1226 0.489908 0.994999 +1211 0.494041 0.994999 +SURF 0x30 +mat 0 +refs 4 +1211 0.494041 0.994999 +1226 0.489908 0.994999 +1227 0.492618 0.984998 +1212 0.499449 0.984998 +SURF 0x30 +mat 0 +refs 4 +1212 0.499449 0.984998 +1227 0.492618 0.984998 +1228 0.498779 0.952498 +1213 0.51174 0.952498 +SURF 0x30 +mat 0 +refs 4 +1213 0.51174 0.952498 +1228 0.498779 0.952498 +1229 0.500504 0.929999 +1214 0.51518 0.929999 +SURF 0x30 +mat 0 +refs 4 +1214 0.51518 0.929999 +1229 0.500504 0.929999 +1230 0.501984 0.8825 +1215 0.518133 0.8825 +SURF 0x30 +mat 0 +refs 4 +1215 0.518133 0.8825 +1230 0.501984 0.8825 +1231 0.503215 0.6825 +1216 0.520591 0.6825 +SURF 0x30 +mat 0 +refs 4 +1216 0.520591 0.6825 +1231 0.503215 0.6825 +1232 0.504695 0.635 +1217 0.52354 0.635 +SURF 0x30 +mat 0 +refs 4 +1217 0.52354 0.635 +1232 0.504695 0.635 +1233 0.50987 0.555 +1218 0.533864 0.555 +SURF 0x30 +mat 0 +refs 4 +1218 0.533864 0.555 +1233 0.50987 0.555 +1234 0.514461 0.475 +1219 0.543025 0.475 +SURF 0x30 +mat 0 +refs 4 +1219 0.543025 0.475 +1234 0.514461 0.475 +1235 0.532795 0.3875 +1220 0.565422 0.3875 +SURF 0x30 +mat 0 +refs 4 +1220 0.565422 0.3875 +1235 0.532795 0.3875 +1236 0.53567 0.31 +1221 0.571159 0.31 +SURF 0x30 +mat 0 +refs 3 +1221 0.571159 0.31 +1236 0.53567 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1237 0.516979 0.0200004 +1222 0.533875 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1222 0.533875 0.0200004 +1237 0.516979 0.0200004 +1238 0.506679 0 +1223 0.513321 0 +SURF 0x30 +mat 1 +refs 4 +1223 0.513321 0 +1238 0.506679 0 +1239 0.500447 0 +1224 0.500891 0 +SURF 0x30 +mat 2 +refs 4 +1225 0.486703 1 +1240 0.485751 1 +1241 0.485751 0.994999 +1226 0.489908 0.994999 +SURF 0x30 +mat 0 +refs 4 +1226 0.489908 0.994999 +1241 0.485751 0.994999 +1242 0.485751 0.984998 +1227 0.492618 0.984998 +SURF 0x30 +mat 0 +refs 4 +1227 0.492618 0.984998 +1242 0.485751 0.984998 +1243 0.485751 0.952498 +1228 0.498779 0.952498 +SURF 0x30 +mat 0 +refs 4 +1228 0.498779 0.952498 +1243 0.485751 0.952498 +1244 0.485751 0.929999 +1229 0.500504 0.929999 +SURF 0x30 +mat 0 +refs 4 +1229 0.500504 0.929999 +1244 0.485751 0.929999 +1245 0.485751 0.8825 +1230 0.501984 0.8825 +SURF 0x30 +mat 0 +refs 4 +1230 0.501984 0.8825 +1245 0.485751 0.8825 +1246 0.485751 0.6825 +1231 0.503215 0.6825 +SURF 0x30 +mat 0 +refs 4 +1231 0.503215 0.6825 +1246 0.485751 0.6825 +1247 0.485751 0.635 +1232 0.504695 0.635 +SURF 0x30 +mat 0 +refs 4 +1232 0.504695 0.635 +1247 0.485751 0.635 +1248 0.485751 0.555 +1233 0.50987 0.555 +SURF 0x30 +mat 0 +refs 4 +1233 0.50987 0.555 +1248 0.485751 0.555 +1249 0.485751 0.475 +1234 0.514461 0.475 +SURF 0x30 +mat 0 +refs 4 +1234 0.514461 0.475 +1249 0.485751 0.475 +1250 0.5 0.3875 +1235 0.532795 0.3875 +SURF 0x30 +mat 0 +refs 4 +1235 0.532795 0.3875 +1250 0.5 0.3875 +1251 0.5 0.31 +1236 0.53567 0.31 +SURF 0x30 +mat 0 +refs 3 +1236 0.53567 0.31 +1251 0.5 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1252 0.5 0.0200004 +1237 0.516979 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1237 0.516979 0.0200004 +1252 0.5 0.0200004 +1253 0.5 0 +1238 0.506679 0 +SURF 0x30 +mat 1 +refs 4 +1238 0.506679 0 +1253 0.5 0 +1254 0.5 0 +1239 0.500447 0 +SURF 0x30 +mat 2 +refs 4 +1240 0.485751 1 +1255 0.4848 1 +1256 0.481595 0.994999 +1241 0.485751 0.994999 +SURF 0x30 +mat 0 +refs 4 +1241 0.485751 0.994999 +1256 0.481595 0.994999 +1257 0.478884 0.984998 +1242 0.485751 0.984998 +SURF 0x30 +mat 0 +refs 4 +1242 0.485751 0.984998 +1257 0.478884 0.984998 +1258 0.472724 0.952498 +1243 0.485751 0.952498 +SURF 0x30 +mat 0 +refs 4 +1243 0.485751 0.952498 +1258 0.472724 0.952498 +1259 0.470998 0.929999 +1244 0.485751 0.929999 +SURF 0x30 +mat 0 +refs 4 +1244 0.485751 0.929999 +1259 0.470998 0.929999 +1260 0.469519 0.8825 +1245 0.485751 0.8825 +SURF 0x30 +mat 0 +refs 4 +1245 0.485751 0.8825 +1260 0.469519 0.8825 +1261 0.468288 0.6825 +1246 0.485751 0.6825 +SURF 0x30 +mat 0 +refs 4 +1246 0.485751 0.6825 +1261 0.468288 0.6825 +1262 0.466808 0.635 +1247 0.485751 0.635 +SURF 0x30 +mat 0 +refs 4 +1247 0.485751 0.635 +1262 0.466808 0.635 +1263 0.461633 0.555 +1248 0.485751 0.555 +SURF 0x30 +mat 0 +refs 4 +1248 0.485751 0.555 +1263 0.461633 0.555 +1264 0.457042 0.475 +1249 0.485751 0.475 +SURF 0x30 +mat 0 +refs 4 +1249 0.485751 0.475 +1264 0.457042 0.475 +1265 0.467205 0.3875 +1250 0.5 0.3875 +SURF 0x30 +mat 0 +refs 4 +1250 0.5 0.3875 +1265 0.467205 0.3875 +1266 0.46433 0.31 +1251 0.5 0.31 +SURF 0x30 +mat 0 +refs 3 +1251 0.5 0.31 +1266 0.46433 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1267 0.483021 0.0200004 +1252 0.5 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1252 0.5 0.0200004 +1267 0.483021 0.0200004 +1268 0.493325 0 +1253 0.5 0 +SURF 0x30 +mat 1 +refs 4 +1253 0.5 0 +1268 0.493325 0 +1269 0.499553 0 +1254 0.5 0 +SURF 0x30 +mat 2 +refs 4 +1255 0.4848 1 +1270 0.483851 1 +1271 0.477458 0.994999 +1256 0.481595 0.994999 +SURF 0x30 +mat 0 +refs 4 +1256 0.481595 0.994999 +1271 0.477458 0.994999 +1272 0.472051 0.984998 +1257 0.478884 0.984998 +SURF 0x30 +mat 0 +refs 4 +1257 0.478884 0.984998 +1272 0.472051 0.984998 +1273 0.459763 0.952498 +1258 0.472724 0.952498 +SURF 0x30 +mat 0 +refs 4 +1258 0.472724 0.952498 +1273 0.459763 0.952498 +1274 0.456319 0.929999 +1259 0.470998 0.929999 +SURF 0x30 +mat 0 +refs 4 +1259 0.470998 0.929999 +1274 0.456319 0.929999 +1275 0.45337 0.8825 +1260 0.469519 0.8825 +SURF 0x30 +mat 0 +refs 4 +1260 0.469519 0.8825 +1275 0.45337 0.8825 +1276 0.450912 0.6825 +1261 0.468288 0.6825 +SURF 0x30 +mat 0 +refs 4 +1261 0.468288 0.6825 +1276 0.450912 0.6825 +1277 0.447962 0.635 +1262 0.466808 0.635 +SURF 0x30 +mat 0 +refs 4 +1262 0.466808 0.635 +1277 0.447962 0.635 +1278 0.437638 0.555 +1263 0.461633 0.555 +SURF 0x30 +mat 0 +refs 4 +1263 0.461633 0.555 +1278 0.437638 0.555 +1279 0.428478 0.475 +1264 0.457042 0.475 +SURF 0x30 +mat 0 +refs 4 +1264 0.457042 0.475 +1279 0.428478 0.475 +1280 0.434578 0.3875 +1265 0.467205 0.3875 +SURF 0x30 +mat 0 +refs 4 +1265 0.467205 0.3875 +1280 0.434578 0.3875 +1281 0.428844 0.31 +1266 0.46433 0.31 +SURF 0x30 +mat 0 +refs 3 +1266 0.46433 0.31 +1281 0.428844 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1282 0.466129 0.0200004 +1267 0.483021 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1267 0.483021 0.0200004 +1282 0.466129 0.0200004 +1283 0.486683 0 +1268 0.493325 0 +SURF 0x30 +mat 1 +refs 4 +1268 0.493325 0 +1283 0.486683 0 +1284 0.499109 0 +1269 0.499553 0 +SURF 0x30 +mat 2 +refs 4 +1270 0.483851 1 +1285 0.482913 1 +1286 0.473366 0.994999 +1271 0.477458 0.994999 +SURF 0x30 +mat 0 +refs 4 +1271 0.477458 0.994999 +1286 0.473366 0.994999 +1287 0.465291 0.984998 +1272 0.472051 0.984998 +SURF 0x30 +mat 0 +refs 4 +1272 0.472051 0.984998 +1287 0.465291 0.984998 +1288 0.446933 0.952498 +1273 0.459763 0.952498 +SURF 0x30 +mat 0 +refs 4 +1273 0.459763 0.952498 +1288 0.446933 0.952498 +1289 0.441792 0.929999 +1274 0.456319 0.929999 +SURF 0x30 +mat 0 +refs 4 +1274 0.456319 0.929999 +1289 0.441792 0.929999 +1290 0.437386 0.8825 +1275 0.45337 0.8825 +SURF 0x30 +mat 0 +refs 4 +1275 0.45337 0.8825 +1290 0.437386 0.8825 +1291 0.433714 0.6825 +1276 0.450912 0.6825 +SURF 0x30 +mat 0 +refs 4 +1276 0.450912 0.6825 +1291 0.433714 0.6825 +1292 0.429308 0.635 +1277 0.447962 0.635 +SURF 0x30 +mat 0 +refs 4 +1277 0.447962 0.635 +1292 0.429308 0.635 +1293 0.413889 0.555 +1278 0.437638 0.555 +SURF 0x30 +mat 0 +refs 4 +1278 0.437638 0.555 +1293 0.413889 0.555 +1294 0.400206 0.475 +1279 0.428478 0.475 +SURF 0x30 +mat 0 +refs 4 +1279 0.428478 0.475 +1294 0.400206 0.475 +1295 0.402287 0.3875 +1280 0.434578 0.3875 +SURF 0x30 +mat 0 +refs 4 +1280 0.434578 0.3875 +1295 0.402287 0.3875 +1296 0.393719 0.31 +1281 0.428844 0.31 +SURF 0x30 +mat 0 +refs 3 +1281 0.428844 0.31 +1296 0.393719 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1297 0.449405 0.0200004 +1282 0.466129 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1282 0.466129 0.0200004 +1297 0.449405 0.0200004 +1298 0.480105 0 +1283 0.486683 0 +SURF 0x30 +mat 1 +refs 4 +1283 0.486683 0 +1298 0.480105 0 +1299 0.498668 0 +1284 0.499109 0 +SURF 0x30 +mat 2 +refs 4 +1285 0.482913 1 +1300 0.481988 1 +1301 0.469337 0.994999 +1286 0.473366 0.994999 +SURF 0x30 +mat 0 +refs 4 +1286 0.473366 0.994999 +1301 0.469337 0.994999 +1302 0.458633 0.984998 +1287 0.465291 0.984998 +SURF 0x30 +mat 0 +refs 4 +1287 0.465291 0.984998 +1302 0.458633 0.984998 +1303 0.434302 0.952498 +1288 0.446933 0.952498 +SURF 0x30 +mat 0 +refs 4 +1288 0.446933 0.952498 +1303 0.434302 0.952498 +1304 0.427489 0.929999 +1289 0.441792 0.929999 +SURF 0x30 +mat 0 +refs 4 +1289 0.441792 0.929999 +1304 0.427489 0.929999 +1305 0.421648 0.8825 +1290 0.437386 0.8825 +SURF 0x30 +mat 0 +refs 4 +1290 0.437386 0.8825 +1305 0.421648 0.8825 +1306 0.416782 0.6825 +1291 0.433714 0.6825 +SURF 0x30 +mat 0 +refs 4 +1291 0.433714 0.6825 +1306 0.416782 0.6825 +1307 0.410944 0.635 +1292 0.429308 0.635 +SURF 0x30 +mat 0 +refs 4 +1292 0.429308 0.635 +1307 0.410944 0.635 +1308 0.390504 0.555 +1293 0.413889 0.555 +SURF 0x30 +mat 0 +refs 4 +1293 0.413889 0.555 +1308 0.390504 0.555 +1309 0.372371 0.475 +1294 0.400206 0.475 +SURF 0x30 +mat 0 +refs 4 +1294 0.400206 0.475 +1309 0.372371 0.475 +1310 0.370491 0.3875 +1295 0.402287 0.3875 +SURF 0x30 +mat 0 +refs 4 +1295 0.402287 0.3875 +1310 0.370491 0.3875 +1311 0.359135 0.31 +1296 0.393719 0.31 +SURF 0x30 +mat 0 +refs 3 +1296 0.393719 0.31 +1311 0.359135 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1312 0.432944 0.0200004 +1297 0.449405 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1297 0.449405 0.0200004 +1312 0.432944 0.0200004 +1313 0.473631 0 +1298 0.480105 0 +SURF 0x30 +mat 1 +refs 4 +1298 0.480105 0 +1313 0.473631 0 +1314 0.498235 0 +1299 0.498668 0 +SURF 0x30 +mat 2 +refs 4 +1300 0.481988 1 +1315 0.481087 1 +1316 0.465392 0.994999 +1301 0.469337 0.994999 +SURF 0x30 +mat 0 +refs 4 +1301 0.469337 0.994999 +1316 0.465392 0.994999 +1317 0.452112 0.984998 +1302 0.458633 0.984998 +SURF 0x30 +mat 0 +refs 4 +1302 0.458633 0.984998 +1317 0.452112 0.984998 +1318 0.421934 0.952498 +1303 0.434302 0.952498 +SURF 0x30 +mat 0 +refs 4 +1303 0.434302 0.952498 +1318 0.421934 0.952498 +1319 0.413483 0.929999 +1304 0.427489 0.929999 +SURF 0x30 +mat 0 +refs 4 +1304 0.427489 0.929999 +1319 0.413483 0.929999 +1320 0.406239 0.8825 +1305 0.421648 0.8825 +SURF 0x30 +mat 0 +refs 4 +1305 0.421648 0.8825 +1320 0.406239 0.8825 +1321 0.400202 0.6825 +1306 0.416782 0.6825 +SURF 0x30 +mat 0 +refs 4 +1306 0.416782 0.6825 +1321 0.400202 0.6825 +1322 0.392959 0.635 +1307 0.410944 0.635 +SURF 0x30 +mat 0 +refs 4 +1307 0.410944 0.635 +1322 0.392959 0.635 +1323 0.367606 0.555 +1308 0.390504 0.555 +SURF 0x30 +mat 0 +refs 4 +1308 0.390504 0.555 +1323 0.367606 0.555 +1324 0.345111 0.475 +1309 0.372371 0.475 +SURF 0x30 +mat 0 +refs 4 +1309 0.372371 0.475 +1324 0.345111 0.475 +1325 0.339354 0.3875 +1310 0.370491 0.3875 +SURF 0x30 +mat 0 +refs 4 +1310 0.370491 0.3875 +1325 0.339354 0.3875 +1326 0.32527 0.31 +1311 0.359135 0.31 +SURF 0x30 +mat 0 +refs 3 +1311 0.359135 0.31 +1326 0.32527 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1327 0.416822 0.0200004 +1312 0.432944 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1312 0.432944 0.0200004 +1327 0.416822 0.0200004 +1328 0.467292 0 +1313 0.473631 0 +SURF 0x30 +mat 1 +refs 4 +1313 0.473631 0 +1328 0.467292 0 +1329 0.497811 0 +1314 0.498235 0 +SURF 0x30 +mat 2 +refs 4 +1315 0.481087 1 +1330 0.480206 1 +1331 0.461549 0.994999 +1316 0.465392 0.994999 +SURF 0x30 +mat 0 +refs 4 +1316 0.465392 0.994999 +1331 0.461549 0.994999 +1332 0.445763 0.984998 +1317 0.452112 0.984998 +SURF 0x30 +mat 0 +refs 4 +1317 0.452112 0.984998 +1332 0.445763 0.984998 +1333 0.409888 0.952498 +1318 0.421934 0.952498 +SURF 0x30 +mat 0 +refs 4 +1318 0.421934 0.952498 +1333 0.409888 0.952498 +1334 0.399843 0.929999 +1319 0.413483 0.929999 +SURF 0x30 +mat 0 +refs 4 +1319 0.413483 0.929999 +1334 0.399843 0.929999 +1335 0.391234 0.8825 +1320 0.406239 0.8825 +SURF 0x30 +mat 0 +refs 4 +1320 0.406239 0.8825 +1335 0.391234 0.8825 +1336 0.384057 0.6825 +1321 0.400202 0.6825 +SURF 0x30 +mat 0 +refs 4 +1321 0.400202 0.6825 +1336 0.384057 0.6825 +1337 0.375448 0.635 +1322 0.392959 0.635 +SURF 0x30 +mat 0 +refs 4 +1322 0.392959 0.635 +1337 0.375448 0.635 +1338 0.34531 0.555 +1323 0.367606 0.555 +SURF 0x30 +mat 0 +refs 4 +1323 0.367606 0.555 +1338 0.34531 0.555 +1339 0.318571 0.475 +1324 0.345111 0.475 +SURF 0x30 +mat 0 +refs 4 +1324 0.345111 0.475 +1339 0.318571 0.475 +1340 0.309037 0.3875 +1325 0.339354 0.3875 +SURF 0x30 +mat 0 +refs 4 +1325 0.339354 0.3875 +1340 0.309037 0.3875 +1341 0.292294 0.31 +1326 0.32527 0.31 +SURF 0x30 +mat 0 +refs 3 +1326 0.32527 0.31 +1341 0.292294 0.31 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1342 0.401124 0.0200004 +1327 0.416822 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1327 0.416822 0.0200004 +1342 0.401124 0.0200004 +1343 0.461121 0 +1328 0.467292 0 +SURF 0x30 +mat 1 +refs 4 +1328 0.467292 0 +1343 0.461121 0 +1344 0.4974 0 +1329 0.497811 0 +SURF 0x30 +mat 2 +refs 4 +1330 0.480206 1 +1345 0.479352 1 +1346 0.457829 0.994999 +1331 0.461549 0.994999 +SURF 0x30 +mat 0 +refs 4 +1331 0.461549 0.994999 +1346 0.457829 0.994999 +1347 0.439619 0.984998 +1332 0.445763 0.984998 +SURF 0x30 +mat 0 +refs 4 +1332 0.445763 0.984998 +1347 0.439619 0.984998 +1348 0.398232 0.952498 +1333 0.409888 0.952498 +SURF 0x30 +mat 0 +refs 4 +1333 0.409888 0.952498 +1348 0.398232 0.952498 +1349 0.386643 0.929999 +1334 0.399843 0.929999 +SURF 0x30 +mat 0 +refs 4 +1334 0.399843 0.929999 +1349 0.386643 0.929999 +1350 0.376709 0.8825 +1335 0.391234 0.8825 +SURF 0x30 +mat 0 +refs 4 +1335 0.391234 0.8825 +1350 0.376709 0.8825 +1351 0.36843 0.6825 +1336 0.384057 0.6825 +SURF 0x30 +mat 0 +refs 4 +1336 0.384057 0.6825 +1351 0.36843 0.6825 +1352 0.358499 0.635 +1337 0.375448 0.635 +SURF 0x30 +mat 0 +refs 4 +1337 0.375448 0.635 +1352 0.358499 0.635 +1353 0.32373 0.555 +1338 0.34531 0.555 +SURF 0x30 +mat 0 +refs 4 +1338 0.34531 0.555 +1353 0.32373 0.555 +1354 0.292879 0.475 +1339 0.318571 0.475 +SURF 0x30 +mat 0 +refs 4 +1339 0.318571 0.475 +1354 0.292879 0.475 +1355 0.279693 0.3875 +1340 0.309037 0.3875 +SURF 0x30 +mat 0 +refs 4 +1340 0.309037 0.3875 +1355 0.279693 0.3875 +1356 0.260376 0.31 +1341 0.292294 0.31 +SURF 0x30 +mat 0 +refs 4 +1341 0.292294 0.31 +1356 0.260376 0.31 +1357 0.263595 0.247501 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1357 0.263595 0.247501 +1358 0.270035 0.175 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1358 0.270035 0.175 +1359 0.289351 0.105001 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1360 0.38593 0.0200004 +1342 0.401124 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1342 0.401124 0.0200004 +1360 0.38593 0.0200004 +1361 0.455149 0 +1343 0.461121 0 +SURF 0x30 +mat 1 +refs 4 +1343 0.461121 0 +1361 0.455149 0 +1362 0.497 0 +1344 0.4974 0 +SURF 0x30 +mat 2 +refs 4 +1345 0.479352 1 +1363 0.478535 1 +1364 0.454254 0.994999 +1346 0.457829 0.994999 +SURF 0x30 +mat 0 +refs 4 +1346 0.457829 0.994999 +1364 0.454254 0.994999 +1365 0.43371 0.984998 +1347 0.439619 0.984998 +SURF 0x30 +mat 0 +refs 4 +1347 0.439619 0.984998 +1365 0.43371 0.984998 +1366 0.38702 0.952498 +1348 0.398232 0.952498 +SURF 0x30 +mat 0 +refs 4 +1348 0.398232 0.952498 +1366 0.38702 0.952498 +1367 0.373945 0.929999 +1349 0.386643 0.929999 +SURF 0x30 +mat 0 +refs 4 +1349 0.386643 0.929999 +1367 0.373945 0.929999 +1368 0.36274 0.8825 +1350 0.376709 0.8825 +SURF 0x30 +mat 0 +refs 4 +1350 0.376709 0.8825 +1368 0.36274 0.8825 +1369 0.353401 0.6825 +1351 0.36843 0.6825 +SURF 0x30 +mat 0 +refs 4 +1351 0.36843 0.6825 +1369 0.353401 0.6825 +1370 0.342196 0.635 +1352 0.358499 0.635 +SURF 0x30 +mat 0 +refs 4 +1352 0.358499 0.635 +1370 0.342196 0.635 +1371 0.302978 0.555 +1353 0.32373 0.555 +SURF 0x30 +mat 0 +refs 4 +1353 0.32373 0.555 +1371 0.302978 0.555 +1372 0.268175 0.475 +1354 0.292879 0.475 +SURF 0x30 +mat 0 +refs 4 +1354 0.292879 0.475 +1372 0.268175 0.475 +1373 0.251471 0.3875 +1355 0.279693 0.3875 +SURF 0x30 +mat 0 +refs 4 +1355 0.279693 0.3875 +1373 0.251471 0.3875 +1374 0.22968 0.31 +1356 0.260376 0.31 +SURF 0x30 +mat 0 +refs 4 +1356 0.260376 0.31 +1374 0.22968 0.31 +1375 0.233312 0.247501 +1357 0.263595 0.247501 +SURF 0x30 +mat 0 +refs 4 +1357 0.263595 0.247501 +1375 0.233312 0.247501 +1376 0.240575 0.175 +1358 0.270035 0.175 +SURF 0x30 +mat 0 +refs 4 +1358 0.270035 0.175 +1376 0.240575 0.175 +1377 0.262367 0.105001 +1359 0.289351 0.105001 +SURF 0x30 +mat 0 +refs 3 +1359 0.289351 0.105001 +1377 0.262367 0.105001 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1378 0.371318 0.0200004 +1360 0.38593 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1360 0.38593 0.0200004 +1378 0.371318 0.0200004 +1379 0.449402 0 +1361 0.455149 0 +SURF 0x30 +mat 1 +refs 4 +1361 0.455149 0 +1379 0.449402 0 +1380 0.496614 0 +1362 0.497 0 +SURF 0x30 +mat 2 +refs 4 +1363 0.478535 1 +1381 0.477751 1 +1382 0.450838 0.994999 +1364 0.454254 0.994999 +SURF 0x30 +mat 0 +refs 4 +1364 0.454254 0.994999 +1382 0.450838 0.994999 +1383 0.428067 0.984998 +1365 0.43371 0.984998 +SURF 0x30 +mat 0 +refs 4 +1365 0.43371 0.984998 +1383 0.428067 0.984998 +1384 0.376312 0.952498 +1366 0.38702 0.952498 +SURF 0x30 +mat 0 +refs 4 +1366 0.38702 0.952498 +1384 0.376312 0.952498 +1385 0.361818 0.929999 +1367 0.373945 0.929999 +SURF 0x30 +mat 0 +refs 4 +1367 0.373945 0.929999 +1385 0.361818 0.929999 +1386 0.349399 0.8825 +1368 0.36274 0.8825 +SURF 0x30 +mat 0 +refs 4 +1368 0.36274 0.8825 +1386 0.349399 0.8825 +1387 0.339048 0.6825 +1369 0.353401 0.6825 +SURF 0x30 +mat 0 +refs 4 +1369 0.353401 0.6825 +1387 0.339048 0.6825 +1388 0.326625 0.635 +1370 0.342196 0.635 +SURF 0x30 +mat 0 +refs 4 +1370 0.342196 0.635 +1388 0.326625 0.635 +1389 0.283153 0.555 +1371 0.302978 0.555 +SURF 0x30 +mat 0 +refs 4 +1371 0.302978 0.555 +1389 0.283153 0.555 +1390 0.244577 0.475 +1372 0.268175 0.475 +SURF 0x30 +mat 0 +refs 4 +1372 0.268175 0.475 +1390 0.244577 0.475 +1391 0.224518 0.3875 +1373 0.251471 0.3875 +SURF 0x30 +mat 0 +refs 4 +1373 0.251471 0.3875 +1391 0.224518 0.3875 +1392 0.200362 0.31 +1374 0.22968 0.31 +SURF 0x30 +mat 0 +refs 4 +1374 0.22968 0.31 +1392 0.200362 0.31 +1393 0.204387 0.247501 +1375 0.233312 0.247501 +SURF 0x30 +mat 0 +refs 4 +1375 0.233312 0.247501 +1393 0.204387 0.247501 +1394 0.212438 0.175 +1376 0.240575 0.175 +SURF 0x30 +mat 0 +refs 4 +1376 0.240575 0.175 +1394 0.212438 0.175 +1395 0.236594 0.105001 +1377 0.262367 0.105001 +SURF 0x30 +mat 0 +refs 3 +1377 0.262367 0.105001 +1395 0.236594 0.105001 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 3 +1174 0.422996 0.0519236 +1396 0.357362 0.0200004 +1378 0.371318 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1378 0.371318 0.0200004 +1396 0.357362 0.0200004 +1397 0.443914 0 +1379 0.449402 0 +SURF 0x30 +mat 1 +refs 4 +1379 0.449402 0 +1397 0.443914 0 +1398 0.496247 0 +1380 0.496614 0 +SURF 0x30 +mat 2 +refs 4 +1381 0.477751 1 +1399 0.477008 1 +1400 0.447599 0.994999 +1382 0.450838 0.994999 +SURF 0x30 +mat 0 +refs 4 +1382 0.450838 0.994999 +1400 0.447599 0.994999 +1401 0.422717 0.984998 +1383 0.428067 0.984998 +SURF 0x30 +mat 0 +refs 4 +1383 0.428067 0.984998 +1401 0.422717 0.984998 +1402 0.36616 0.952498 +1384 0.376312 0.952498 +SURF 0x30 +mat 0 +refs 4 +1384 0.376312 0.952498 +1402 0.36616 0.952498 +1403 0.350324 0.929999 +1385 0.361818 0.929999 +SURF 0x30 +mat 0 +refs 4 +1385 0.361818 0.929999 +1403 0.350324 0.929999 +1404 0.336751 0.8825 +1386 0.349399 0.8825 +SURF 0x30 +mat 0 +refs 4 +1386 0.349399 0.8825 +1404 0.336751 0.8825 +1405 0.325442 0.6825 +1387 0.339048 0.6825 +SURF 0x30 +mat 0 +refs 4 +1387 0.339048 0.6825 +1405 0.325442 0.6825 +1406 0.311869 0.635 +1388 0.326625 0.635 +SURF 0x30 +mat 0 +refs 4 +1388 0.326625 0.635 +1406 0.311869 0.635 +1407 0.264361 0.555 +1389 0.283153 0.555 +SURF 0x30 +mat 0 +refs 4 +1389 0.283153 0.555 +1407 0.264361 0.555 +1408 0.222207 0.475 +1390 0.244577 0.475 +SURF 0x30 +mat 0 +refs 4 +1390 0.244577 0.475 +1408 0.222207 0.475 +1409 0.198966 0.3875 +1391 0.224518 0.3875 +SURF 0x30 +mat 0 +refs 4 +1391 0.224518 0.3875 +1409 0.198966 0.3875 +1410 0.172571 0.31 +1392 0.200362 0.31 +SURF 0x30 +mat 0 +refs 4 +1392 0.200362 0.31 +1410 0.172571 0.31 +1411 0.17697 0.247501 +1393 0.204387 0.247501 +SURF 0x30 +mat 0 +refs 4 +1393 0.204387 0.247501 +1411 0.17697 0.247501 +1412 0.185767 0.175 +1394 0.212438 0.175 +SURF 0x30 +mat 0 +refs 4 +1394 0.212438 0.175 +1412 0.185767 0.175 +1413 0.212162 0.105001 +1395 0.236594 0.105001 +SURF 0x30 +mat 0 +refs 4 +1395 0.236594 0.105001 +1413 0.212162 0.105001 +1414 0.280349 0.0549999 +1174 0.422996 0.0519236 +SURF 0x30 +mat 0 +refs 4 +1174 0.422996 0.0519236 +1414 0.280349 0.0549999 +1415 0.344133 0.0200004 +1396 0.357362 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1396 0.357362 0.0200004 +1415 0.344133 0.0200004 +1416 0.438711 0 +1397 0.443914 0 +SURF 0x30 +mat 1 +refs 4 +1397 0.443914 0 +1416 0.438711 0 +1417 0.495901 0 +1398 0.496247 0 +SURF 0x30 +mat 2 +refs 4 +1399 0.477008 1 +1418 0.476312 1 +1419 0.444556 0.994999 +1400 0.447599 0.994999 +SURF 0x30 +mat 0 +refs 4 +1400 0.447599 0.994999 +1419 0.444556 0.994999 +1420 0.417686 0.984998 +1401 0.422717 0.984998 +SURF 0x30 +mat 0 +refs 4 +1401 0.422717 0.984998 +1420 0.417686 0.984998 +1421 0.356619 0.952498 +1402 0.36616 0.952498 +SURF 0x30 +mat 0 +refs 4 +1402 0.36616 0.952498 +1421 0.356619 0.952498 +1422 0.339522 0.929999 +1403 0.350324 0.929999 +SURF 0x30 +mat 0 +refs 4 +1403 0.350324 0.929999 +1422 0.339522 0.929999 +1423 0.324863 0.8825 +1404 0.336751 0.8825 +SURF 0x30 +mat 0 +refs 4 +1404 0.336751 0.8825 +1423 0.324863 0.8825 +1424 0.312653 0.6825 +1405 0.325442 0.6825 +SURF 0x30 +mat 0 +refs 4 +1405 0.325442 0.6825 +1424 0.312653 0.6825 +1425 0.297994 0.635 +1406 0.311869 0.635 +SURF 0x30 +mat 0 +refs 4 +1406 0.311869 0.635 +1425 0.297994 0.635 +1426 0.246699 0.555 +1407 0.264361 0.555 +SURF 0x30 +mat 0 +refs 4 +1407 0.264361 0.555 +1426 0.246699 0.555 +1427 0.201179 0.475 +1408 0.222207 0.475 +SURF 0x30 +mat 0 +refs 4 +1408 0.222207 0.475 +1427 0.201179 0.475 +1428 0.174948 0.3875 +1409 0.198966 0.3875 +SURF 0x30 +mat 0 +refs 4 +1409 0.198966 0.3875 +1428 0.174948 0.3875 +1429 0.146448 0.31 +1410 0.172571 0.31 +SURF 0x30 +mat 0 +refs 4 +1410 0.172571 0.31 +1429 0.146448 0.31 +1430 0.1512 0.247501 +1411 0.17697 0.247501 +SURF 0x30 +mat 0 +refs 4 +1411 0.17697 0.247501 +1430 0.1512 0.247501 +1431 0.160696 0.175 +1412 0.185767 0.175 +SURF 0x30 +mat 0 +refs 4 +1412 0.185767 0.175 +1431 0.160696 0.175 +1432 0.189197 0.105001 +1413 0.212162 0.105001 +SURF 0x30 +mat 0 +refs 4 +1413 0.212162 0.105001 +1432 0.189197 0.105001 +1433 0.262821 0.0549999 +1414 0.280349 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1414 0.280349 0.0549999 +1433 0.262821 0.0549999 +1434 0.331697 0.0200004 +1415 0.344133 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1415 0.344133 0.0200004 +1434 0.331697 0.0200004 +1435 0.433821 0 +1416 0.438711 0 +SURF 0x30 +mat 1 +refs 4 +1416 0.438711 0 +1435 0.433821 0 +1436 0.495571 0 +1417 0.495901 0 +SURF 0x30 +mat 2 +refs 4 +1418 0.476312 1 +1437 0.475663 1 +1438 0.441721 0.994999 +1419 0.444556 0.994999 +SURF 0x30 +mat 0 +refs 4 +1419 0.444556 0.994999 +1438 0.441721 0.994999 +1439 0.413005 0.984998 +1420 0.417686 0.984998 +SURF 0x30 +mat 0 +refs 4 +1420 0.417686 0.984998 +1439 0.413005 0.984998 +1440 0.347738 0.952498 +1421 0.356619 0.952498 +SURF 0x30 +mat 0 +refs 4 +1421 0.356619 0.952498 +1440 0.347738 0.952498 +1441 0.32946 0.929999 +1422 0.339522 0.929999 +SURF 0x30 +mat 0 +refs 4 +1422 0.339522 0.929999 +1441 0.32946 0.929999 +1442 0.313796 0.8825 +1423 0.324863 0.8825 +SURF 0x30 +mat 0 +refs 4 +1423 0.324863 0.8825 +1442 0.313796 0.8825 +1443 0.300745 0.6825 +1424 0.312653 0.6825 +SURF 0x30 +mat 0 +refs 4 +1424 0.312653 0.6825 +1443 0.300745 0.6825 +1444 0.28508 0.635 +1425 0.297994 0.635 +SURF 0x30 +mat 0 +refs 4 +1425 0.297994 0.635 +1444 0.28508 0.635 +1445 0.230255 0.555 +1426 0.246699 0.555 +SURF 0x30 +mat 0 +refs 4 +1426 0.246699 0.555 +1445 0.230255 0.555 +1446 0.181604 0.475 +1427 0.201179 0.475 +SURF 0x30 +mat 0 +refs 4 +1427 0.201179 0.475 +1446 0.181604 0.475 +1447 0.152588 0.3875 +1428 0.174948 0.3875 +SURF 0x30 +mat 0 +refs 4 +1428 0.174948 0.3875 +1447 0.152588 0.3875 +1448 0.122127 0.31 +1429 0.146448 0.31 +SURF 0x30 +mat 0 +refs 4 +1429 0.146448 0.31 +1448 0.122127 0.31 +1449 0.127202 0.247501 +1430 0.1512 0.247501 +SURF 0x30 +mat 0 +refs 4 +1430 0.1512 0.247501 +1449 0.127202 0.247501 +1450 0.137358 0.175 +1431 0.160696 0.175 +SURF 0x30 +mat 0 +refs 4 +1431 0.160696 0.175 +1450 0.137358 0.175 +1451 0.167819 0.105001 +1432 0.189197 0.105001 +SURF 0x30 +mat 0 +refs 4 +1432 0.189197 0.105001 +1451 0.167819 0.105001 +1452 0.246508 0.0549999 +1433 0.262821 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1433 0.262821 0.0549999 +1452 0.246508 0.0549999 +1453 0.320118 0.0200004 +1434 0.331697 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1434 0.331697 0.0200004 +1453 0.320118 0.0200004 +1454 0.429268 0 +1435 0.433821 0 +SURF 0x30 +mat 1 +refs 4 +1435 0.433821 0 +1454 0.429268 0 +1455 0.495268 0 +1436 0.495571 0 +SURF 0x30 +mat 2 +refs 4 +1437 0.475663 1 +1456 0.475064 1 +1457 0.439111 0.994999 +1438 0.441721 0.994999 +SURF 0x30 +mat 0 +refs 4 +1438 0.441721 0.994999 +1457 0.439111 0.994999 +1458 0.408694 0.984998 +1439 0.413005 0.984998 +SURF 0x30 +mat 0 +refs 4 +1439 0.413005 0.984998 +1458 0.408694 0.984998 +1459 0.339556 0.952498 +1440 0.347738 0.952498 +SURF 0x30 +mat 0 +refs 4 +1440 0.347738 0.952498 +1459 0.339556 0.952498 +1460 0.320199 0.929999 +1441 0.32946 0.929999 +SURF 0x30 +mat 0 +refs 4 +1441 0.32946 0.929999 +1460 0.320199 0.929999 +1461 0.303606 0.8825 +1442 0.313796 0.8825 +SURF 0x30 +mat 0 +refs 4 +1442 0.313796 0.8825 +1461 0.303606 0.8825 +1462 0.289778 0.6825 +1443 0.300745 0.6825 +SURF 0x30 +mat 0 +refs 4 +1443 0.300745 0.6825 +1462 0.289778 0.6825 +1463 0.273186 0.635 +1444 0.28508 0.635 +SURF 0x30 +mat 0 +refs 4 +1444 0.28508 0.635 +1463 0.273186 0.635 +1464 0.215112 0.555 +1445 0.230255 0.555 +SURF 0x30 +mat 0 +refs 4 +1445 0.230255 0.555 +1464 0.215112 0.555 +1465 0.163578 0.475 +1446 0.181604 0.475 +SURF 0x30 +mat 0 +refs 4 +1446 0.181604 0.475 +1465 0.163578 0.475 +1466 0.131997 0.3875 +1447 0.152588 0.3875 +SURF 0x30 +mat 0 +refs 4 +1447 0.152588 0.3875 +1466 0.131997 0.3875 +1467 0.0997303 0.31 +1448 0.122127 0.31 +SURF 0x30 +mat 0 +refs 4 +1448 0.122127 0.31 +1467 0.0997303 0.31 +1468 0.105108 0.247501 +1449 0.127202 0.247501 +SURF 0x30 +mat 0 +refs 4 +1449 0.127202 0.247501 +1468 0.105108 0.247501 +1469 0.115862 0.175 +1450 0.137358 0.175 +SURF 0x30 +mat 0 +refs 4 +1450 0.137358 0.175 +1469 0.115862 0.175 +1470 0.148129 0.105001 +1451 0.167819 0.105001 +SURF 0x30 +mat 0 +refs 4 +1451 0.167819 0.105001 +1470 0.148129 0.105001 +1471 0.231482 0.0549999 +1452 0.246508 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1452 0.246508 0.0549999 +1471 0.231482 0.0549999 +1472 0.309458 0.0200004 +1453 0.320118 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1453 0.320118 0.0200004 +1472 0.309458 0.0200004 +1473 0.425078 0 +1454 0.429268 0 +SURF 0x30 +mat 2 +refs 4 +1454 0.429268 0 +1473 0.425078 0 +1474 0.494986 0 +1455 0.495268 0 +SURF 0x30 +mat 2 +refs 4 +1456 0.475064 1 +1475 0.474519 1 +1476 0.43674 0.994999 +1457 0.439111 0.994999 +SURF 0x30 +mat 2 +refs 4 +1457 0.439111 0.994999 +1476 0.43674 0.994999 +1477 0.404773 0.984998 +1458 0.408694 0.984998 +SURF 0x30 +mat 0 +refs 4 +1458 0.408694 0.984998 +1477 0.404773 0.984998 +1478 0.33212 0.952498 +1459 0.339556 0.952498 +SURF 0x30 +mat 0 +refs 4 +1459 0.339556 0.952498 +1478 0.33212 0.952498 +1479 0.311778 0.929999 +1460 0.320199 0.929999 +SURF 0x30 +mat 0 +refs 4 +1460 0.320199 0.929999 +1479 0.311778 0.929999 +1480 0.294342 0.8825 +1461 0.303606 0.8825 +SURF 0x30 +mat 0 +refs 4 +1461 0.303606 0.8825 +1480 0.294342 0.8825 +1481 0.279811 0.6825 +1462 0.289778 0.6825 +SURF 0x30 +mat 0 +refs 4 +1462 0.289778 0.6825 +1481 0.279811 0.6825 +1482 0.262377 0.635 +1463 0.273186 0.635 +SURF 0x30 +mat 0 +refs 4 +1463 0.273186 0.635 +1482 0.262377 0.635 +1483 0.201347 0.555 +1464 0.215112 0.555 +SURF 0x30 +mat 0 +refs 4 +1464 0.215112 0.555 +1483 0.201347 0.555 +1484 0.147194 0.475 +1465 0.163578 0.475 +SURF 0x30 +mat 0 +refs 4 +1465 0.163578 0.475 +1484 0.147194 0.475 +1485 0.113283 0.3875 +1466 0.131997 0.3875 +SURF 0x30 +mat 0 +refs 4 +1466 0.131997 0.3875 +1485 0.113283 0.3875 +1486 0.0793746 0.31 +1467 0.0997303 0.31 +SURF 0x30 +mat 0 +refs 4 +1467 0.0997303 0.31 +1486 0.0793746 0.31 +1487 0.0850243 0.247501 +1468 0.105108 0.247501 +SURF 0x30 +mat 0 +refs 4 +1468 0.105108 0.247501 +1487 0.0850243 0.247501 +1488 0.096327 0.175 +1469 0.115862 0.175 +SURF 0x30 +mat 0 +refs 4 +1469 0.115862 0.175 +1488 0.096327 0.175 +1489 0.130235 0.105001 +1470 0.148129 0.105001 +SURF 0x30 +mat 0 +refs 4 +1470 0.148129 0.105001 +1489 0.130235 0.105001 +1490 0.217825 0.0549999 +1471 0.231482 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1471 0.231482 0.0549999 +1490 0.217825 0.0549999 +1491 0.299769 0.0200004 +1472 0.309458 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1472 0.309458 0.0200004 +1491 0.299769 0.0200004 +1492 0.421268 0 +1473 0.425078 0 +SURF 0x30 +mat 2 +refs 4 +1473 0.425078 0 +1492 0.421268 0 +1493 0.49473 0 +1474 0.494986 0 +SURF 0x30 +mat 2 +refs 4 +1475 0.474519 1 +1494 0.474035 1 +1495 0.434618 0.994999 +1476 0.43674 0.994999 +SURF 0x30 +mat 2 +refs 4 +1476 0.43674 0.994999 +1495 0.434618 0.994999 +1496 0.401268 0.984998 +1477 0.404773 0.984998 +SURF 0x30 +mat 0 +refs 4 +1477 0.404773 0.984998 +1496 0.401268 0.984998 +1497 0.325469 0.952498 +1478 0.33212 0.952498 +SURF 0x30 +mat 0 +refs 4 +1478 0.33212 0.952498 +1497 0.325469 0.952498 +1498 0.304245 0.929999 +1479 0.311778 0.929999 +SURF 0x30 +mat 0 +refs 4 +1479 0.311778 0.929999 +1498 0.304245 0.929999 +1499 0.286055 0.8825 +1480 0.294342 0.8825 +SURF 0x30 +mat 0 +refs 4 +1480 0.294342 0.8825 +1499 0.286055 0.8825 +1500 0.270895 0.6825 +1481 0.279811 0.6825 +SURF 0x30 +mat 0 +refs 4 +1481 0.279811 0.6825 +1500 0.270895 0.6825 +1501 0.252702 0.635 +1482 0.262377 0.635 +SURF 0x30 +mat 0 +refs 4 +1482 0.262377 0.635 +1501 0.252702 0.635 +1502 0.189032 0.555 +1483 0.201347 0.555 +SURF 0x30 +mat 0 +refs 4 +1483 0.201347 0.555 +1502 0.189032 0.555 +1503 0.132535 0.475 +1484 0.147194 0.475 +SURF 0x30 +mat 0 +refs 4 +1484 0.147194 0.475 +1503 0.132535 0.475 +1504 0.0965356 0.3875 +1485 0.113283 0.3875 +SURF 0x30 +mat 0 +refs 4 +1485 0.113283 0.3875 +1504 0.0965356 0.3875 +1505 0.0611612 0.31 +1486 0.0793746 0.31 +SURF 0x30 +mat 0 +refs 4 +1486 0.0793746 0.31 +1505 0.0611612 0.31 +1506 0.0670564 0.247501 +1487 0.0850243 0.247501 +SURF 0x30 +mat 0 +refs 4 +1487 0.0850243 0.247501 +1506 0.0670564 0.247501 +1507 0.07885 0.175 +1488 0.096327 0.175 +SURF 0x30 +mat 0 +refs 4 +1488 0.096327 0.175 +1507 0.07885 0.175 +1508 0.114224 0.105001 +1489 0.130235 0.105001 +SURF 0x30 +mat 0 +refs 4 +1489 0.130235 0.105001 +1508 0.114224 0.105001 +1509 0.205608 0.0549999 +1490 0.217825 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1490 0.217825 0.0549999 +1509 0.205608 0.0549999 +1510 0.2911 0.0200004 +1491 0.299769 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1491 0.299769 0.0200004 +1510 0.2911 0.0200004 +1511 0.417858 0 +1492 0.421268 0 +SURF 0x30 +mat 2 +refs 4 +1492 0.421268 0 +1511 0.417858 0 +1512 0.494505 0 +1493 0.49473 0 +SURF 0x30 +mat 2 +refs 4 +1494 0.474035 1 +1513 0.473608 1 +1514 0.432755 0.994999 +1495 0.434618 0.994999 +SURF 0x30 +mat 2 +refs 4 +1495 0.434618 0.994999 +1514 0.432755 0.994999 +1515 0.398191 0.984998 +1496 0.401268 0.984998 +SURF 0x30 +mat 0 +refs 4 +1496 0.401268 0.984998 +1515 0.398191 0.984998 +1516 0.319634 0.952498 +1497 0.325469 0.952498 +SURF 0x30 +mat 0 +refs 4 +1497 0.325469 0.952498 +1516 0.319634 0.952498 +1517 0.297637 0.929999 +1498 0.304245 0.929999 +SURF 0x30 +mat 0 +refs 4 +1498 0.304245 0.929999 +1517 0.297637 0.929999 +1518 0.278785 0.8825 +1499 0.286055 0.8825 +SURF 0x30 +mat 0 +refs 4 +1499 0.286055 0.8825 +1518 0.278785 0.8825 +1519 0.263073 0.6825 +1500 0.270895 0.6825 +SURF 0x30 +mat 0 +refs 4 +1500 0.270895 0.6825 +1519 0.263073 0.6825 +1520 0.244218 0.635 +1501 0.252702 0.635 +SURF 0x30 +mat 0 +refs 4 +1501 0.252702 0.635 +1520 0.244218 0.635 +1521 0.178231 0.555 +1502 0.189032 0.555 +SURF 0x30 +mat 0 +refs 4 +1502 0.189032 0.555 +1521 0.178231 0.555 +1522 0.119676 0.475 +1503 0.132535 0.475 +SURF 0x30 +mat 0 +refs 4 +1503 0.132535 0.475 +1522 0.119676 0.475 +1523 0.0818498 0.3875 +1504 0.0965356 0.3875 +SURF 0x30 +mat 0 +refs 4 +1504 0.0965356 0.3875 +1523 0.0818498 0.3875 +1524 0.045184 0.31 +1505 0.0611612 0.31 +SURF 0x30 +mat 0 +refs 4 +1505 0.0611612 0.31 +1524 0.045184 0.31 +1525 0.0512944 0.247501 +1506 0.0670564 0.247501 +SURF 0x30 +mat 0 +refs 4 +1506 0.0670564 0.247501 +1525 0.0512944 0.247501 +1526 0.0635185 0.175 +1507 0.07885 0.175 +SURF 0x30 +mat 0 +refs 4 +1507 0.07885 0.175 +1526 0.0635185 0.175 +1527 0.100181 0.105001 +1508 0.114224 0.105001 +SURF 0x30 +mat 0 +refs 4 +1508 0.114224 0.105001 +1527 0.100181 0.105001 +1528 0.19489 0.0549999 +1509 0.205608 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1509 0.205608 0.0549999 +1528 0.19489 0.0549999 +1529 0.283493 0.0200004 +1510 0.2911 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1510 0.2911 0.0200004 +1529 0.283493 0.0200004 +1530 0.414868 0 +1511 0.417858 0 +SURF 0x30 +mat 2 +refs 4 +1511 0.417858 0 +1530 0.414868 0 +1531 0.494303 0 +1512 0.494505 0 +SURF 0x30 +mat 2 +refs 4 +1513 0.473608 1 +1532 0.473241 1 +1533 0.431165 0.994999 +1514 0.432755 0.994999 +SURF 0x30 +mat 2 +refs 4 +1514 0.432755 0.994999 +1533 0.431165 0.994999 +1534 0.395562 0.984998 +1515 0.398191 0.984998 +SURF 0x30 +mat 0 +refs 4 +1515 0.398191 0.984998 +1534 0.395562 0.984998 +1535 0.314647 0.952498 +1516 0.319634 0.952498 +SURF 0x30 +mat 0 +refs 4 +1516 0.319634 0.952498 +1535 0.314647 0.952498 +1536 0.291988 0.929999 +1517 0.297637 0.929999 +SURF 0x30 +mat 0 +refs 4 +1517 0.297637 0.929999 +1536 0.291988 0.929999 +1537 0.27257 0.8825 +1518 0.278785 0.8825 +SURF 0x30 +mat 0 +refs 4 +1518 0.278785 0.8825 +1537 0.27257 0.8825 +1538 0.256385 0.6825 +1519 0.263073 0.6825 +SURF 0x30 +mat 0 +refs 4 +1519 0.263073 0.6825 +1538 0.256385 0.6825 +1539 0.236967 0.635 +1520 0.244218 0.635 +SURF 0x30 +mat 0 +refs 4 +1520 0.244218 0.635 +1539 0.236967 0.635 +1540 0.168996 0.555 +1521 0.178231 0.555 +SURF 0x30 +mat 0 +refs 4 +1521 0.178231 0.555 +1540 0.168996 0.555 +1541 0.108682 0.475 +1522 0.119676 0.475 +SURF 0x30 +mat 0 +refs 4 +1522 0.119676 0.475 +1541 0.108682 0.475 +1542 0.0692893 0.3875 +1523 0.0818498 0.3875 +SURF 0x30 +mat 0 +refs 4 +1523 0.0818498 0.3875 +1542 0.0692893 0.3875 +1543 0.0315273 0.31 +1524 0.045184 0.31 +SURF 0x30 +mat 0 +refs 4 +1524 0.045184 0.31 +1543 0.0315273 0.31 +1544 0.0378192 0.247501 +1525 0.0512944 0.247501 +SURF 0x30 +mat 0 +refs 4 +1525 0.0512944 0.247501 +1544 0.0378192 0.247501 +1545 0.0504099 0.175 +1526 0.0635185 0.175 +SURF 0x30 +mat 0 +refs 4 +1526 0.0635185 0.175 +1545 0.0504099 0.175 +1546 0.088172 0.105001 +1527 0.100181 0.105001 +SURF 0x30 +mat 0 +refs 4 +1527 0.100181 0.105001 +1546 0.088172 0.105001 +1547 0.18573 0.0549999 +1528 0.19489 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1528 0.19489 0.0549999 +1547 0.18573 0.0549999 +1548 0.276992 0.0200004 +1529 0.283493 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1529 0.283493 0.0200004 +1548 0.276992 0.0200004 +1549 0.412312 0 +1530 0.414868 0 +SURF 0x30 +mat 2 +refs 4 +1530 0.414868 0 +1549 0.412312 0 +1550 0.494132 0 +1531 0.494303 0 +SURF 0x30 +mat 2 +refs 4 +1532 0.473241 1 +1551 0.472942 1 +1552 0.429853 0.994999 +1533 0.431165 0.994999 +SURF 0x30 +mat 2 +refs 4 +1533 0.431165 0.994999 +1552 0.429853 0.994999 +1553 0.393393 0.984998 +1534 0.395562 0.984998 +SURF 0x30 +mat 0 +refs 4 +1534 0.395562 0.984998 +1553 0.393393 0.984998 +1554 0.310527 0.952498 +1535 0.314647 0.952498 +SURF 0x30 +mat 0 +refs 4 +1535 0.314647 0.952498 +1554 0.310527 0.952498 +1555 0.287327 0.929999 +1536 0.291988 0.929999 +SURF 0x30 +mat 0 +refs 4 +1536 0.291988 0.929999 +1555 0.287327 0.929999 +1556 0.267438 0.8825 +1537 0.27257 0.8825 +SURF 0x30 +mat 0 +refs 4 +1537 0.27257 0.8825 +1556 0.267438 0.8825 +1557 0.250866 0.6825 +1538 0.256385 0.6825 +SURF 0x30 +mat 0 +refs 4 +1538 0.256385 0.6825 +1557 0.250866 0.6825 +1558 0.230981 0.635 +1539 0.236967 0.635 +SURF 0x30 +mat 0 +refs 4 +1539 0.236967 0.635 +1558 0.230981 0.635 +1559 0.161376 0.555 +1540 0.168996 0.555 +SURF 0x30 +mat 0 +refs 4 +1540 0.168996 0.555 +1559 0.161376 0.555 +1560 0.0996092 0.475 +1541 0.108682 0.475 +SURF 0x30 +mat 0 +refs 4 +1541 0.108682 0.475 +1560 0.0996092 0.475 +1561 0.0589282 0.3875 +1542 0.0692893 0.3875 +SURF 0x30 +mat 0 +refs 4 +1542 0.0692893 0.3875 +1561 0.0589282 0.3875 +1562 0.0202548 0.31 +1543 0.0315273 0.31 +SURF 0x30 +mat 0 +refs 4 +1543 0.0315273 0.31 +1562 0.0202548 0.31 +1563 0.0267014 0.247501 +1544 0.0378192 0.247501 +SURF 0x30 +mat 0 +refs 4 +1544 0.0378192 0.247501 +1563 0.0267014 0.247501 +1564 0.0395915 0.175 +1545 0.0504099 0.175 +SURF 0x30 +mat 0 +refs 4 +1545 0.0504099 0.175 +1564 0.0395915 0.175 +1565 0.0782649 0.105001 +1546 0.088172 0.105001 +SURF 0x30 +mat 0 +refs 4 +1546 0.088172 0.105001 +1565 0.0782649 0.105001 +1566 0.178167 0.0549999 +1547 0.18573 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1547 0.18573 0.0549999 +1566 0.178167 0.0549999 +1567 0.271625 0.0200004 +1548 0.276992 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1548 0.276992 0.0200004 +1567 0.271625 0.0200004 +1568 0.4102 0 +1549 0.412312 0 +SURF 0x30 +mat 2 +refs 4 +1549 0.412312 0 +1568 0.4102 0 +1569 0.493991 0 +1550 0.494132 0 +SURF 0x30 +mat 2 +refs 4 +1551 0.472942 1 +1570 0.472707 1 +1571 0.428824 0.994999 +1552 0.429853 0.994999 +SURF 0x30 +mat 2 +refs 4 +1552 0.429853 0.994999 +1571 0.428824 0.994999 +1572 0.391694 0.984998 +1553 0.393393 0.984998 +SURF 0x30 +mat 0 +refs 4 +1553 0.393393 0.984998 +1572 0.391694 0.984998 +1573 0.307306 0.952498 +1554 0.310527 0.952498 +SURF 0x30 +mat 0 +refs 4 +1554 0.310527 0.952498 +1573 0.307306 0.952498 +1574 0.283674 0.929999 +1555 0.287327 0.929999 +SURF 0x30 +mat 0 +refs 4 +1555 0.287327 0.929999 +1574 0.283674 0.929999 +1575 0.263423 0.8825 +1556 0.267438 0.8825 +SURF 0x30 +mat 0 +refs 4 +1556 0.267438 0.8825 +1575 0.263423 0.8825 +1576 0.246545 0.6825 +1557 0.250866 0.6825 +SURF 0x30 +mat 0 +refs 4 +1557 0.250866 0.6825 +1576 0.246545 0.6825 +1577 0.226293 0.635 +1558 0.230981 0.635 +SURF 0x30 +mat 0 +refs 4 +1558 0.230981 0.635 +1577 0.226293 0.635 +1578 0.155407 0.555 +1559 0.161376 0.555 +SURF 0x30 +mat 0 +refs 4 +1559 0.161376 0.555 +1578 0.155407 0.555 +1579 0.0925034 0.475 +1560 0.0996092 0.475 +SURF 0x30 +mat 0 +refs 4 +1560 0.0996092 0.475 +1579 0.0925034 0.475 +1580 0.0508135 0.3875 +1561 0.0589282 0.3875 +SURF 0x30 +mat 0 +refs 4 +1561 0.0589282 0.3875 +1580 0.0508135 0.3875 +1581 0.0114272 0.31 +1562 0.0202548 0.31 +SURF 0x30 +mat 0 +refs 4 +1562 0.0202548 0.31 +1581 0.0114272 0.31 +1582 0.0179915 0.247501 +1563 0.0267014 0.247501 +SURF 0x30 +mat 0 +refs 4 +1563 0.0267014 0.247501 +1582 0.0179915 0.247501 +1583 0.0311203 0.175 +1564 0.0395915 0.175 +SURF 0x30 +mat 0 +refs 4 +1564 0.0395915 0.175 +1583 0.0311203 0.175 +1584 0.0705033 0.105001 +1565 0.0782649 0.105001 +SURF 0x30 +mat 0 +refs 4 +1565 0.0782649 0.105001 +1584 0.0705033 0.105001 +1585 0.172245 0.0549999 +1566 0.178167 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1566 0.178167 0.0549999 +1585 0.172245 0.0549999 +1586 0.267425 0.0200004 +1567 0.271625 0.0200004 +SURF 0x30 +mat 0 +refs 4 +1567 0.271625 0.0200004 +1586 0.267425 0.0200004 +1587 0.408549 0 +1568 0.4102 0 +SURF 0x30 +mat 2 +refs 4 +1568 0.4102 0 +1587 0.408549 0 +1588 0.49388 0 +1569 0.493991 0 +SURF 0x30 +mat 2 +refs 4 +1570 0.472707 1 +1589 0.472535 1 +1590 0.428084 0.994999 +1571 0.428824 0.994999 +SURF 0x30 +mat 2 +refs 4 +1571 0.428824 0.994999 +1590 0.428084 0.994999 +1591 0.390474 0.984998 +1572 0.391694 0.984998 +SURF 0x30 +mat 1 +refs 4 +1572 0.391694 0.984998 +1591 0.390474 0.984998 +1592 0.304989 0.952498 +1573 0.307306 0.952498 +SURF 0x30 +mat 0 +refs 4 +1573 0.307306 0.952498 +1592 0.304989 0.952498 +1593 0.281055 0.929999 +1574 0.283674 0.929999 +SURF 0x30 +mat 0 +refs 4 +1574 0.283674 0.929999 +1593 0.281055 0.929999 +1594 0.260538 0.8825 +1575 0.263423 0.8825 +SURF 0x30 +mat 0 +refs 4 +1575 0.263423 0.8825 +1594 0.260538 0.8825 +1595 0.243444 0.6825 +1576 0.246545 0.6825 +SURF 0x30 +mat 0 +refs 4 +1576 0.246545 0.6825 +1595 0.243444 0.6825 +1596 0.222927 0.635 +1577 0.226293 0.635 +SURF 0x30 +mat 0 +refs 4 +1577 0.226293 0.635 +1596 0.222927 0.635 +1597 0.151122 0.555 +1578 0.155407 0.555 +SURF 0x30 +mat 0 +refs 4 +1578 0.155407 0.555 +1597 0.151122 0.555 +1598 0.0874052 0.475 +1579 0.0925034 0.475 +SURF 0x30 +mat 0 +refs 4 +1579 0.0925034 0.475 +1598 0.0874052 0.475 +1599 0.0449856 0.3875 +1580 0.0508135 0.3875 +SURF 0x30 +mat 0 +refs 4 +1580 0.0508135 0.3875 +1599 0.0449856 0.3875 +1600 0.0050915 0.31 +1581 0.0114272 0.31 +SURF 0x30 +mat 0 +refs 4 +1581 0.0114272 0.31 +1600 0.0050915 0.31 +1601 0.0117399 0.247501 +1582 0.0179915 0.247501 +SURF 0x30 +mat 0 +refs 4 +1582 0.0179915 0.247501 +1601 0.0117399 0.247501 +1602 0.0250368 0.175 +1583 0.0311203 0.175 +SURF 0x30 +mat 0 +refs 4 +1583 0.0311203 0.175 +1602 0.0250368 0.175 +1603 0.0649344 0.105001 +1584 0.0705033 0.105001 +SURF 0x30 +mat 0 +refs 4 +1584 0.0705033 0.105001 +1603 0.0649344 0.105001 +1604 0.167994 0.0549999 +1585 0.172245 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1585 0.172245 0.0549999 +1604 0.167994 0.0549999 +1605 0.264405 0.0200004 +1586 0.267425 0.0200004 +SURF 0x30 +mat 2 +refs 4 +1586 0.267425 0.0200004 +1605 0.264405 0.0200004 +1606 0.407362 0 +1587 0.408549 0 +SURF 0x30 +mat 2 +refs 4 +1587 0.408549 0 +1606 0.407362 0 +1607 0.493802 0 +1588 0.49388 0 +SURF 0x30 +mat 2 +refs 4 +1589 0.472535 1 +1608 0.472434 1 +1609 0.42764 0.994999 +1590 0.428084 0.994999 +SURF 0x30 +mat 2 +refs 4 +1590 0.428084 0.994999 +1609 0.42764 0.994999 +1610 0.389737 0.984998 +1591 0.390474 0.984998 +SURF 0x30 +mat 2 +refs 4 +1591 0.390474 0.984998 +1610 0.389737 0.984998 +1611 0.303596 0.952498 +1592 0.304989 0.952498 +SURF 0x30 +mat 2 +refs 4 +1592 0.304989 0.952498 +1611 0.303596 0.952498 +1612 0.279478 0.929999 +1593 0.281055 0.929999 +SURF 0x30 +mat 2 +refs 4 +1593 0.281055 0.929999 +1612 0.279478 0.929999 +1613 0.258802 0.8825 +1594 0.260538 0.8825 +SURF 0x30 +mat 2 +refs 4 +1594 0.260538 0.8825 +1613 0.258802 0.8825 +1614 0.241574 0.6825 +1595 0.243444 0.6825 +SURF 0x30 +mat 0 +refs 4 +1595 0.243444 0.6825 +1614 0.241574 0.6825 +1615 0.220899 0.635 +1596 0.222927 0.635 +SURF 0x30 +mat 0 +refs 4 +1596 0.222927 0.635 +1615 0.220899 0.635 +1616 0.148543 0.555 +1597 0.151122 0.555 +SURF 0x30 +mat 0 +refs 4 +1597 0.151122 0.555 +1616 0.148543 0.555 +1617 0.0843316 0.475 +1598 0.0874052 0.475 +SURF 0x30 +mat 0 +refs 4 +1598 0.0874052 0.475 +1617 0.0843316 0.475 +1618 0.0414781 0.3875 +1599 0.0449856 0.3875 +SURF 0x30 +mat 0 +refs 4 +1599 0.0449856 0.3875 +1618 0.0414781 0.3875 +1619 0.00127453 0.31 +1600 0.0050915 0.31 +SURF 0x30 +mat 0 +refs 4 +1600 0.0050915 0.31 +1619 0.00127453 0.31 +1620 0.0079768 0.247501 +1601 0.0117399 0.247501 +SURF 0x30 +mat 0 +refs 4 +1601 0.0117399 0.247501 +1620 0.0079768 0.247501 +1621 0.021378 0.175 +1602 0.0250368 0.175 +SURF 0x30 +mat 0 +refs 4 +1602 0.0250368 0.175 +1621 0.021378 0.175 +1622 0.0615781 0.105001 +1603 0.0649344 0.105001 +SURF 0x30 +mat 0 +refs 4 +1603 0.0649344 0.105001 +1622 0.0615781 0.105001 +1623 0.165435 0.0549999 +1604 0.167994 0.0549999 +SURF 0x30 +mat 0 +refs 4 +1604 0.167994 0.0549999 +1623 0.165435 0.0549999 +1624 0.262589 0.0200004 +1605 0.264405 0.0200004 +SURF 0x30 +mat 2 +refs 4 +1605 0.264405 0.0200004 +1624 0.262589 0.0200004 +1625 0.406649 0 +1606 0.407362 0 +SURF 0x30 +mat 2 +refs 4 +1606 0.407362 0 +1625 0.406649 0 +1626 0.493755 0 +1607 0.493802 0 +SURF 0x30 +mat 2 +refs 4 +1608 0.472434 1 +0 0.472401 1 +3 0.427492 0.994999 +1609 0.42764 0.994999 +SURF 0x30 +mat 2 +refs 4 +1609 0.42764 0.994999 +3 0.427492 0.994999 +5 0.389492 0.984998 +1610 0.389737 0.984998 +SURF 0x30 +mat 2 +refs 4 +1610 0.389737 0.984998 +5 0.389492 0.984998 +7 0.303132 0.952498 +1611 0.303596 0.952498 +SURF 0x30 +mat 2 +refs 4 +1611 0.303596 0.952498 +7 0.303132 0.952498 +9 0.27895 0.929999 +1612 0.279478 0.929999 +SURF 0x30 +mat 2 +refs 4 +1612 0.279478 0.929999 +9 0.27895 0.929999 +11 0.258224 0.8825 +1613 0.258802 0.8825 +SURF 0x30 +mat 2 +refs 4 +1613 0.258802 0.8825 +11 0.258224 0.8825 +13 0.240952 0.6825 +1614 0.241574 0.6825 +SURF 0x30 +mat 2 +refs 4 +1614 0.241574 0.6825 +13 0.240952 0.6825 +15 0.220223 0.635 +1615 0.220899 0.635 +SURF 0x30 +mat 2 +refs 4 +1615 0.220899 0.635 +15 0.220223 0.635 +17 0.147679 0.555 +1616 0.148543 0.555 +SURF 0x30 +mat 2 +refs 4 +1616 0.148543 0.555 +17 0.147679 0.555 +19 0.0833059 0.475 +1617 0.0843316 0.475 +SURF 0x30 +mat 2 +refs 4 +1617 0.0843316 0.475 +19 0.0833059 0.475 +21 0.0403078 0.3875 +1618 0.0414781 0.3875 +SURF 0x30 +mat 2 +refs 4 +1618 0.0414781 0.3875 +21 0.0403078 0.3875 +23 0 0.31 +1619 0.00127453 0.31 +SURF 0x30 +mat 2 +refs 4 +1619 0.00127453 0.31 +23 0 0.31 +25 0.00671911 0.247501 +1620 0.0079768 0.247501 +SURF 0x30 +mat 2 +refs 4 +1620 0.0079768 0.247501 +25 0.00671911 0.247501 +27 0.0201539 0.175 +1621 0.021378 0.175 +SURF 0x30 +mat 2 +refs 4 +1621 0.021378 0.175 +27 0.0201539 0.175 +29 0.0604583 0.105001 +1622 0.0615781 0.105001 +SURF 0x30 +mat 2 +refs 4 +1622 0.0615781 0.105001 +29 0.0604583 0.105001 +31 0.164581 0.0549999 +1623 0.165435 0.0549999 +SURF 0x30 +mat 2 +refs 4 +1623 0.165435 0.0549999 +31 0.164581 0.0549999 +33 0.261984 0.0200004 +1624 0.262589 0.0200004 +SURF 0x30 +mat 2 +refs 4 +1624 0.262589 0.0200004 +33 0.261984 0.0200004 +35 0.40641 0 +1625 0.406649 0 +SURF 0x30 +mat 2 +refs 4 +1625 0.406649 0 +35 0.40641 0 +37 0.493738 0 +1626 0.493755 0 +kids 0 diff --git a/demos/simon/astropong/data/shadow2.ac b/demos/simon/astropong/data/shadow2.ac new file mode 100644 index 0000000..50f1d27 --- /dev/null +++ b/demos/simon/astropong/data/shadow2.ac @@ -0,0 +1,577 @@ +AC3Db +MATERIAL "ac3dmat0" rgb 0 0 0 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +OBJECT world +kids 1 +OBJECT poly +name "disk" +numvert 82 +0.5 0 0 +0.498496 0 0.0387462 +0.493995 0 0.0772594 +0.486522 0 0.115308 +0.476124 0 0.152663 +0.462862 0 0.1891 +0.446816 0 0.2244 +0.428083 0 0.25835 +0.406776 0 0.290746 +0.383022 0 0.321394 +0.356965 0 0.350109 +0.328761 0 0.376718 +0.298579 0 0.401062 +0.266602 0 0.422993 +0.233022 0 0.442381 +0.19804 0 0.459108 +0.161867 0 0.473074 +0.124721 0 0.484195 +0.0868241 0 0.492404 +0.0484054 0 0.497651 +0.00969563 0 0.499906 +-0.0290725 0 0.499154 +-0.0676657 0 0.4954 +-0.105852 0 0.488667 +-0.143402 0 0.478995 +-0.180089 0 0.466442 +-0.215693 0 0.451084 +-0.25 0 0.433013 +-0.282803 0 0.412337 +-0.313906 0 0.389182 +-0.343121 0 0.363687 +-0.370272 0 0.336004 +-0.395196 0 0.3063 +-0.417744 0 0.274754 +-0.437779 0 0.241556 +-0.455182 0 0.206905 +-0.469846 0 0.17101 +-0.481685 0 0.134086 +-0.490628 0 0.0963561 +-0.496619 0 0.0580464 +-0.499624 0 0.0193876 +-0.499624 0 -0.0193878 +-0.496619 0 -0.0580465 +-0.490628 0 -0.0963562 +-0.481685 0 -0.134086 +-0.469846 0 -0.17101 +-0.455181 0 -0.206905 +-0.437779 0 -0.241556 +-0.417744 0 -0.274755 +-0.395196 0 -0.3063 +-0.370272 0 -0.336004 +-0.343121 0 -0.363687 +-0.313906 0 -0.389183 +-0.282803 0 -0.412338 +-0.25 0 -0.433013 +-0.215693 0 -0.451084 +-0.180089 0 -0.466442 +-0.143402 0 -0.478995 +-0.105852 0 -0.488667 +-0.0676655 0 -0.4954 +-0.0290723 0 -0.499154 +0.00969578 0 -0.499906 +0.0484056 0 -0.497651 +0.0868242 0 -0.492404 +0.124721 0 -0.484195 +0.161867 0 -0.473074 +0.19804 0 -0.459108 +0.233022 0 -0.442381 +0.266602 0 -0.422993 +0.298579 0 -0.401062 +0.328761 0 -0.376718 +0.356965 0 -0.350109 +0.383022 0 -0.321394 +0.406776 0 -0.290746 +0.428084 0 -0.25835 +0.446816 0 -0.224399 +0.462862 0 -0.1891 +0.476124 0 -0.152663 +0.486522 0 -0.115308 +0.493995 0 -0.0772592 +0.498496 0 -0.0387461 +0 0 0 +numsurf 81 +SURF 0x20 +mat 0 +refs 3 +0 1 0.5 +1 0.998496 0.461246 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +1 0.998496 0.461246 +2 0.993993 0.422726 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +2 0.993993 0.422726 +3 0.986517 0.38467 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +3 0.986517 0.38467 +4 0.976115 0.347308 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +4 0.976115 0.347308 +5 0.962848 0.310865 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +5 0.962848 0.310865 +6 0.946796 0.275558 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +6 0.946796 0.275558 +7 0.928056 0.241602 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +7 0.928056 0.241602 +8 0.906741 0.209199 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +8 0.906741 0.209199 +9 0.882978 0.178546 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +9 0.882978 0.178546 +10 0.856911 0.149825 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +10 0.856911 0.149825 +11 0.828696 0.123211 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +11 0.828696 0.123211 +12 0.798503 0.0988629 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +12 0.798503 0.0988629 +13 0.766514 0.0769272 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +13 0.766514 0.0769272 +14 0.732921 0.0575359 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +14 0.732921 0.0575359 +15 0.697926 0.0408056 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +15 0.697926 0.0408056 +16 0.66174 0.0268369 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +16 0.66174 0.0268369 +17 0.624579 0.0157139 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +17 0.624579 0.0157139 +18 0.586669 0.00750349 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +18 0.586669 0.00750349 +19 0.548236 0.002255 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +19 0.548236 0.002255 +20 0.509511 0 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +20 0.509511 0 +21 0.470729 0.000752024 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +21 0.470729 0.000752024 +22 0.432121 0.00450663 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +22 0.432121 0.00450663 +23 0.39392 0.0112412 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +23 0.39392 0.0112412 +24 0.356356 0.0209152 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +24 0.356356 0.0209152 +25 0.319655 0.0334704 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +25 0.319655 0.0334704 +26 0.284038 0.0488315 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +26 0.284038 0.0488315 +27 0.249718 0.0669059 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +27 0.249718 0.0669059 +28 0.216902 0.087585 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +28 0.216902 0.087585 +29 0.185788 0.110744 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +29 0.185788 0.110744 +30 0.156562 0.136245 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +30 0.156562 0.136245 +31 0.129401 0.163933 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +31 0.129401 0.163933 +32 0.104467 0.193642 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +32 0.104467 0.193642 +33 0.0819108 0.225194 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +33 0.0819108 0.225194 +34 0.0618681 0.258398 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +34 0.0618681 0.258398 +35 0.0444592 0.293056 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +35 0.0444592 0.293056 +36 0.0297888 0.328958 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +36 0.0297888 0.328958 +37 0.0179453 0.365889 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +37 0.0179453 0.365889 +38 0.00899969 0.403626 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +38 0.00899969 0.403626 +39 0.00300592 0.441943 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +39 0.00300592 0.441943 +40 0 0.480609 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +40 0 0.480609 +41 0 0.519391 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +41 0 0.519391 +42 0.00300595 0.558057 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +42 0.00300595 0.558057 +43 0.00899972 0.596374 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +43 0.00899972 0.596374 +44 0.0179453 0.634112 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +44 0.0179453 0.634112 +45 0.0297889 0.671042 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +45 0.0297889 0.671042 +46 0.0444592 0.706944 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +46 0.0444592 0.706944 +47 0.0618682 0.741602 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +47 0.0618682 0.741602 +48 0.0819109 0.774806 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +48 0.0819109 0.774806 +49 0.104467 0.806358 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +49 0.104467 0.806358 +50 0.129401 0.836067 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +50 0.129401 0.836067 +51 0.156562 0.863755 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +51 0.156562 0.863755 +52 0.185788 0.889256 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +52 0.185788 0.889256 +53 0.216902 0.912415 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +53 0.216902 0.912415 +54 0.249718 0.933094 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +54 0.249718 0.933094 +55 0.284038 0.951169 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +55 0.284038 0.951169 +56 0.319655 0.96653 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +56 0.319655 0.96653 +57 0.356356 0.979085 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +57 0.356356 0.979085 +58 0.39392 0.988759 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +58 0.39392 0.988759 +59 0.432121 0.995493 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +59 0.432121 0.995493 +60 0.470729 0.999248 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +60 0.470729 0.999248 +61 0.509511 1 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +61 0.509511 1 +62 0.548236 0.997745 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +62 0.548236 0.997745 +63 0.586669 0.992496 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +63 0.586669 0.992496 +64 0.624579 0.984286 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +64 0.624579 0.984286 +65 0.66174 0.973163 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +65 0.66174 0.973163 +66 0.697926 0.959194 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +66 0.697926 0.959194 +67 0.732921 0.942464 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +67 0.732921 0.942464 +68 0.766515 0.923073 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +68 0.766515 0.923073 +69 0.798504 0.901137 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +69 0.798504 0.901137 +70 0.828696 0.876789 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +70 0.828696 0.876789 +71 0.856911 0.850174 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +71 0.856911 0.850174 +72 0.882978 0.821454 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +72 0.882978 0.821454 +73 0.906741 0.790801 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +73 0.906741 0.790801 +74 0.928056 0.758398 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +74 0.928056 0.758398 +75 0.946796 0.724442 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +75 0.946796 0.724442 +76 0.962848 0.689135 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +76 0.962848 0.689135 +77 0.976115 0.652692 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +77 0.976115 0.652692 +78 0.986517 0.61533 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +78 0.986517 0.61533 +79 0.993993 0.577274 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +79 0.993993 0.577274 +80 0.998496 0.538753 +81 0.499812 0.5 +SURF 0x20 +mat 0 +refs 3 +80 0.998496 0.538753 +0 1 0.5 +81 0.499812 0.5 +kids 0 diff --git a/demos/simon/doc/index.html b/demos/simon/doc/index.html new file mode 100644 index 0000000..afa7e47 --- /dev/null +++ b/demos/simon/doc/index.html @@ -0,0 +1,256 @@ + + + + + WELCOME TO S.I.M.O.N + + + +

WELCOME TO S.I.M.O.N

+
by Steve Baker
+ +SIMON stands for: +
+
+     Simple
+     Interface for
+     Making
+     Oliver's programs
+     Nice.
+
+
+This is a simple set of functions that hide much of the nastiness +of 3D programming to make it possible for someone with only the +very minimum of programming experience to write simple 3D applications. +

+If you want something more complicated or with better features then +don't complain about SIMON - just use raw PLIB (upon which SIMON is +based). + +

HOW TO WRITE YOUR PROGRAM.

+ +You have to write TWO C (or C++) functions: +
+
+   int main ()
+
+
+...and... +
+
+   void siUpdate ()
+
+
+The 'main' function has to load whatever 3D models the program needs +and then call a function called 'siRun()'. +

+siRun does things like opening the 3D window, clearing the screen and +drawing all of the models. When it's time to move the models around, +it calls your function 'siUpdate'. +

+All SIMON programs have to start with the line: +

+
+   #include <simon.h>
+
+
+...this brings in all the information the compiler needs in order for you to +write a SIMON program. Think of it like '#include <stdio.h>' but for +programs that are just doing 3D rendering. +

+Then, you have to declare an integer variable for everything in the scene +that your program needs - which includes at least the scenery and the camera. +

+For example: +

+
+  int camera  ;
+  int tux     ;
+  int scenery ;
+ 
+
+Next, you have your 'main' program - which loads up the models and then +calls the 'siRun()' function and then exits. +
+
+  int main ()
+  {
+    scenery = siLoad ( "scenery.ac" ) ;
+    tux     = siLoad ( "tuxedo.ac"  ) ;
+
+    camera  = 0 ;
+ 
+    siRun () ;
+    return 0 ;
+  }
+
+
+The 'siLoad' function loads a 3D model and returns a number for +that model that you can save into a variable. That number can be +used to move the model around later on. The final part of this +'loading' stage is to set the number for the 'camera'. In SIMON, +the camera is always model number zero and you can't 'siLoad' a +model for it or it won't work. +

+Then, you call 'siRun()' - which runs the entire update process. If +'siRun' ever returns, you can just exit the program. +

+Now we have our scene all set up and ready to go - so the program +will call your 'siUpdate' function to move the models (and the +camera) around - and then draw the scene. +

+
+  int frameno = 0 ;
+
+  void siUpdate ()
+  {
+    frameno = frameno + 1 ;
+ 
+    siPosition ( tux   , 0,  0, 0, frameno, 0, 0 ) ;
+    siPosition ( camera, 0, -5, 1, 0, 0, 0 ) ;
+  }
+ 
+
+Here we defined a simple variable called 'frameno' which is increased +by one every time the 'siUpdate' function is called to give the program +an idea of how much time has gone by. +

+Finally, we set the position of the camera and tux by calling +'siPosition' for each of them. +

+'siPosition' is a function that needs SEVEN things to be passed to it. +

    +
  1. The first is the variable that contains the number of the object you + want to position. +
  2. The second is the X coordinate that you want that object to have + (in Meters). +
  3. The third is the Y coordinate. +
  4. The fourth is the Z coordinate (the height). +
  5. The fifth is the 'heading' - which is the direction that the object + is pointing. If you model your objects with their noses pointing + North in the modeller then this number will be the angle in degrees + measured in an anticlockwise direction from due North. +
  6. The sixth is the 'pitch' - which is the amount that the object is + leaning backwards (in degrees). +
  7. The seventh (and last) is the 'roll' - which is the amount that the + object is leaning sideways (also in degrees). +
+That's a lot of information - but it's what you need to tell the +object for it to know where to appear in the scene. +

+In our example program, we first had: +

+
+    siPosition ( tux, 0, 0, 0, frameno, 0, 0 ) ;
+
+
+...which puts Tux at X=0, Y=0, Z=0 (which is at the origin of the scene) +and sets his 'heading' equal to this 'frameno' variable. Thus, as time +goes on, and we keep adding one to 'frameno', Tux's heading number will +gradually increase from zero upwards. This should cause him to rotate +in place. Since pitch and roll are both zero, he'll be standing upright. +

+The slPosition command for the Camera: +

+
+    siPosition ( camera, 0, -5, 1, 0, 0, 0 ) ;
+
+
+...puts the camera at X=0, Y=-5, Z=1 - which is back 5 meters from where +Tux is - and one meter up into the air. This should give us a nice view +of him as he spins. + +

READING THE JOYSTICK.

+ +These functions let you read the Left/Right and Up/Down axes of the +joystick: +
+
+  leftright = siJoystickLR () ;
+  updown    = siJoystickUD () ;
+ 
+
+The numbers that this will put into the variables 'leftright' and +'updown' range from -1.0 to +1.0. Leftwards and Upwards movements +generate 1, Rightwards and Downwards movements generate -1, when the +stick is in the middle you get zeroes. +

+To read the buttons, you can use these functions: +

+
+  buttonA =  siJoystickA () ;
+  buttonB =  siJoystickB () ;
+  buttonC =  siJoystickC () ;
+  buttonD =  siJoystickD () ;
+  buttonL =  siJoystickL () ;
+  buttonR =  siJoystickR () ;
+
+
+...the variables should be 'int' varaibles and will be set to 1 if the +button is pressed or 0 if it's not. + +

OTHER MOVEMENT COMMANDS.

+ +Other commands let you set the Velocity for objects: +
+
+    siVelocity ( object, x, y, z, h, p, r ) ;
+
+
+...and set a speed and a direction: +
+
+    siSpeedAndDirection ( object, speed, heading, pitch ) ;
+
+
+...you can also get the current position for the object: +
+
+    x = siGetPositionX ( object ) ;
+    y = siGetPositionY ( object ) ;
+    z = siGetPositionZ ( object ) ;
+    h = siGetPositionH ( object ) ;
+    p = siGetPositionP ( object ) ;
+    r = siGetPositionR ( object ) ;
+
+
+

THE MAKEFILE.

+ +Once you start to have things like SIMON being used with your program, +it can be quite a complicated process to compile your program. It's a +lot of typing and you'll make lots of mistakes. +

+For that reason, Linux uses a command called 'make' to compile complicated +programs according to some rules that you tell it in a special file that's +called 'Makefile'. Once you have a 'Makefile' set up for your program, +you only ever need to type 'make' in order to compile your program - +no matter how complicated it gets to be. +

+A good 'Makefile' for a SIMON program would be: +

+
+  #
+  # List the names of the programs we want to build here...
+  #
+  TARGETS = test1
+ 
+  #======================== DON'T CHANGE THIS PART =============================
+  #
+  SIMONDIR = /usr/local/simon
+  SIMON = -I${SIMONDIR} -L${SIMONDIR}
+  LIBS  = -lsimon -lplibssg -lplibsg -lplibul -lglut -lGLU -lGL -L/usr/X11/lib -lX11 -lm
+ 
+  all: ${TARGETS}
+ 
+  #=============================================================================
+ 
+  #
+  # Copy this for every program you want to write - changing 'test1'
+  # to whatever your program is called.
+  #
+ 
+  test1 : test1.cxx ; g++ ${SIMON} -o test1 test1.cxx ${LIBS}                                               
+
+ + + diff --git a/demos/simon/src/Makefile b/demos/simon/src/Makefile new file mode 100644 index 0000000..1d3e57c --- /dev/null +++ b/demos/simon/src/Makefile @@ -0,0 +1,31 @@ +CXX=g++ + +SIMON = libsimon.a simon +LIBS = -lplibpsl -lplibssg -lplibsg -lplibjs -lplibul -lglut -lGLU -lGL -lpthread -L/usr/X11/lib -lX11 -lm + +all: ${SIMON} + +simon : libsimon.a simon.o + $(CXX) -o simon simon.o libsimon.a ${LIBS} -L$(HOME)/lib -L/usr/X11R6/lib + +simon.o : simon.cxx simon.h + $(CXX) -I. -o simon.o -c simon.cxx + +simon_api.o : simon_api.cxx simon.h + $(CXX) -o simon_api.o -c simon_api.cxx + +libsimon.a : simon_api.o + ar cru libsimon.a simon_api.o + +install: libsimon.a simon.h simon + mkdir -p /usr/local/simon + cp libsimon.a simon.h /usr/local/simon + cp simon /usr/local/bin + +uninstall: + rm -r /usr/local/simon + rm /usr/local/bin/simon + +clean: + rm -f simon libsimon.a *.o + diff --git a/demos/simon/src/simon.cxx b/demos/simon/src/simon.cxx new file mode 100644 index 0000000..043b0ea --- /dev/null +++ b/demos/simon/src/simon.cxx @@ -0,0 +1,231 @@ +/* + S.I.M.O.N - Simple Interface for Making Oliver's programs Nice + Copyright (C) 2002 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: simon.cxx 1699 2002-09-22 15:22:21Z sjbaker $ +*/ + + +#include +#include + + +pslValue my_print ( int argc, pslValue *argv, pslProgram *p ) +{ + for ( int i = 0 ; i < argc ; i++ ) + { + switch ( argv[i].getType () ) + { + case PSL_INT : printf ( "%d ", argv[i].getInt () ) ; break ; + case PSL_FLOAT : printf ( "%f ", argv[i].getFloat () ) ; break ; + case PSL_STRING : printf ( "%s", argv[i].getString () ) ; break ; + case PSL_VOID : printf ( "(void) " ) ; break ; + } + } + + pslValue ret ; + return ret ; +} + + +pslValue my_siJoystickUD ( int, pslValue *, pslProgram * ) +{ + pslValue ret ; + ret . set ( siJoystickUD () ) ; + return ret ; +} + + +pslValue my_siJoystickLR ( int, pslValue *, pslProgram * ) +{ + pslValue ret ; + ret . set ( siJoystickLR () ) ; + return ret ; +} + + +pslValue my_siJoystickA ( int, pslValue *, pslProgram * ) +{ + pslValue ret ; + ret . set ( siJoystickA () ) ; + return ret ; +} + + +pslValue my_siJoystickB ( int, pslValue *, pslProgram * ) +{ + pslValue ret ; + ret . set ( siJoystickB () ) ; + return ret ; +} + + +pslValue my_siJoystickC ( int, pslValue *, pslProgram * ) +{ + pslValue ret ; + ret . set ( siJoystickC () ) ; + return ret ; +} + + +pslValue my_siJoystickD ( int, pslValue *, pslProgram * ) +{ + pslValue ret ; + ret . set ( siJoystickD () ) ; + return ret ; +} + + +pslValue my_siJoystickL ( int, pslValue *, pslProgram * ) +{ + pslValue ret ; + ret . set ( siJoystickL () ) ; + return ret ; +} + + +pslValue my_siJoystickR ( int, pslValue *, pslProgram * ) +{ + pslValue ret ; + ret . set ( siJoystickR () ) ; + return ret ; +} + + +pslValue my_siLoad ( int argc, pslValue *argv, pslProgram *p ) +{ + if ( argc != 1 || argv[0].getType() != PSL_STRING ) + fprintf ( stderr, "siLoad: ERROR - Parameter must be a single string!\n" ) ; + + pslValue ret ; + ret . set ( siLoad ( argv[0].getString () ) ) ; + return ret ; +} + + + +pslValue my_fabs ( int argc, pslValue *argv, pslProgram *p ) +{ + pslValue ret ; + ret . set ( (float) fabs ( argv[0].getFloat () ) ) ; + return ret ; +} + + +pslValue my_siPosition ( int argc, pslValue *argv, pslProgram *p ) +{ + if ( argc != 7 ) + fprintf ( stderr, "siPosition: ERROR - Expected seven parameters?!?\n" ) ; + + siPosition ( argv[0].getInt (), + argv[1].getFloat (), + argv[2].getFloat (), + argv[3].getFloat (), + argv[4].getFloat (), + argv[5].getFloat (), + argv[6].getFloat () ) ; + + pslValue ret ; + return ret ; +} + + + + +pslExtension extensions [] = +{ + { "siLoad" , 1, my_siLoad }, + { "siPosition" , 7, my_siPosition }, + { "siJoystickUD", 0, my_siJoystickUD }, + { "siJoystickLR", 0, my_siJoystickLR }, + { "siJoystickA" , 0, my_siJoystickA }, + { "siJoystickB" , 0, my_siJoystickB }, + { "siJoystickC" , 0, my_siJoystickC }, + { "siJoystickD" , 0, my_siJoystickD }, + { "siJoystickL" , 0, my_siJoystickL }, + { "siJoystickR" , 0, my_siJoystickR }, + { "fabs" , 1, my_fabs }, + { "print" ,-1, my_print }, + { NULL, 0, NULL } +} ; + + +pslProgram *prog = NULL ; +ulClock ck ; + +int main ( int argc, char **argv ) +{ + if ( argc != 2 ) + { + fprintf ( stderr, "simon: Usage -\n\n" ) ; + fprintf ( stderr, " simon filename\n\n" ) ; + fprintf ( stderr, "Where: 'filename' is a PSL sourcefile\n\n" ) ; + exit ( 1 ) ; + } + + pslInit () ; + + /* Create program and compile it. */ + + prog = new pslProgram ( extensions, argv[1] ) ; + + ck.setMaxDelta ( 100000.0 ) ; + ck.update () ; + + prog -> compile ( argv[1] ) ; + + ck.update () ; + fprintf(stderr, "Compile Time: %fs.\n", ck.getDeltaTime () ) ; + + fprintf(stderr, "-------------------------------\n" ) ; + siRun () ; + return 0 ; +} + + +void siUpdate () +{ + static int nframes = 0 ; + static double total_time = 0.0 ; + + pslResult res ; + + ck.update () ; + do + { + res = prog -> step () ; + + } while ( res == PSL_PROGRAM_CONTINUE ) ; + + if ( res == PSL_PROGRAM_END ) + exit ( 0 ) ; + + ck.update () ; + total_time += ck.getDeltaTime () ; + nframes++ ; + + if ( nframes == 100 ) + { + fprintf ( stderr, "Avg PSL Interp time = %fs.\n", total_time / nframes ) ; + nframes = 0 ; + total_time = 0.0 ; + } +} + + diff --git a/demos/simon/src/simon.dsp b/demos/simon/src/simon.dsp new file mode 100644 index 0000000..9a9b967 --- /dev/null +++ b/demos/simon/src/simon.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="simon" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=simon - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "simon.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "simon.mak" CFG="simon - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "simon - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "simon - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +F90=df.exe +RSC=rc.exe + +!IF "$(CFG)" == "simon - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE F90 /compile_only /nologo /warn:nofileopt +# ADD F90 /compile_only /nologo /warn:nofileopt +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "." /I "..\..\..\..\" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "FREEGLUT_STATIC" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 ul.lib js.lib psl.lib ssg.lib sg.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libc.lib" /libpath:"..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "simon - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE F90 /check:bounds /compile_only /dbglibs /debug:full /nologo /traceback /warn:argument_checking /warn:nofileopt +# ADD F90 /check:bounds /compile_only /dbglibs /debug:full /nologo /traceback /warn:argument_checking /warn:nofileopt +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "." /I "..\..\..\..\" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "FREEGLUT_STATIC" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ul_d.lib js_d.lib psl_d.lib ssg_d.lib sg_d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libcd.lib" /pdbtype:sept /libpath:"..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "simon - Win32 Release" +# Name "simon - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;f90;for;f;fpp" +# Begin Source File + +SOURCE=.\simon.cxx +# End Source File +# Begin Source File + +SOURCE=.\simon_api.cxx +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\simon.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/demos/simon/src/simon.dsw b/demos/simon/src/simon.dsw new file mode 100644 index 0000000..0ffb6b5 --- /dev/null +++ b/demos/simon/src/simon.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "simon"=".\simon.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/demos/simon/src/simon.h b/demos/simon/src/simon.h new file mode 100644 index 0000000..4975e81 --- /dev/null +++ b/demos/simon/src/simon.h @@ -0,0 +1,83 @@ +/* + S.I.M.O.N - Simple Interface for Making Oliver's programs Nice + Copyright (C) 2002 Steve Baker + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: simon.h 1681 2002-09-15 02:51:44Z ude $ +*/ + + +#include +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#include + +#define SI_MAX_MODELS 500 + +void siUpdate () ; +void siRun () ; +int siLoad ( const char *filename ) ; +void siPosition ( int hh, float x, float y, + float z = 0.0f, + float h = 0.0f, + float p = 0.0f, + float r = 0.0f ) ; + +void siSpeedAndDirection ( int hh, float s, float h, float p = 0.0f ) ; + +void siVelocity ( int hh, float x, float y, + float z = 0.0f, + float h = 0.0f, + float p = 0.0f, + float r = 0.0f ) ; + +float siGetPositionX ( int h ) ; +float siGetPositionY ( int h ) ; +float siGetPositionZ ( int h ) ; +float siGetPositionH ( int h ) ; +float siGetPositionP ( int h ) ; +float siGetPositionR ( int h ) ; + +float siJoystickLR () ; +float siJoystickUD () ; + +bool siJoystickA () ; +bool siJoystickB () ; +bool siJoystickC () ; +bool siJoystickD () ; +bool siJoystickL () ; +bool siJoystickR () ; + diff --git a/demos/simon/src/simon_api.cxx b/demos/simon/src/simon_api.cxx new file mode 100644 index 0000000..fa83962 --- /dev/null +++ b/demos/simon/src/simon_api.cxx @@ -0,0 +1,365 @@ +/* + S.I.M.O.N - Simple Interface for Making Oliver's programs Nice + Copyright (C) 2002 Steve Baker + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: simon_api.cxx 2100 2006-11-03 22:31:54Z fayjf $ +*/ + + +#include "simon.h" +#include +#include +#include + +class siEntity ; + +static int siNextModel = 0 ; +static bool siInitialised = false ; +static ssgRoot *siScene = NULL ; +static siEntity *siModels [ SI_MAX_MODELS ] ; + +class siEntity +{ +protected: + + int handle ; + char *name ; + sgCoord pos ; + sgCoord vel ; + +public: + + siEntity ( const char *_fname ) + { + siModels [ siNextModel ] = this ; + + handle = siNextModel++ ; + + if ( siNextModel >= SI_MAX_MODELS ) + { + fprintf ( stderr, "simon: ERROR - More than %d models loaded!\n", SI_MAX_MODELS ) ; + exit ( 1 ) ; + } + + name = ulStrDup ( _fname ) ; + sgZeroCoord ( & pos ) ; + sgZeroCoord ( & vel ) ; + } + + int getHandle () const { return handle ; } + + float getPositionX () const { return pos.xyz[0] ; } + float getPositionY () const { return pos.xyz[1] ; } + float getPositionZ () const { return pos.xyz[2] ; } + float getPositionH () const { return pos.hpr[0] ; } + float getPositionP () const { return pos.hpr[1] ; } + float getPositionR () const { return pos.hpr[2] ; } + + void setSpeedAndDirection ( float s, float h, float p ) + { + sgMat4 tmp ; + sgMakeRotMat4 ( tmp, h, p, 0 ) ; + + sgSetVec3 ( vel.xyz, 0, s, 0 ) ; + sgXformPnt3 ( vel.xyz, tmp ) ; + sgSetVec3 ( pos.hpr, h, p, 0 ) ; + sgZeroVec3 ( vel.hpr ) ; + } + + void setVelocity ( float x, float y, float z, float h, float p, float r ) + { + sgSetCoord ( &vel, x, y, z, h, p, r ) ; + } + + void setPosition ( float x, float y, float z, float h, float p, float r ) + { + sgSetCoord ( &pos, x, y, z, h, p, r ) ; + } + + void updatePhysics ( double dt ) + { + sgAddScaledVec3 ( pos . xyz, vel . xyz, (float)dt ) ; + sgAddScaledVec3 ( pos . hpr, vel . hpr, (float)dt ) ; + } + + virtual void update ( double dt ) = 0 ; +} ; + + + +class siCamera : public siEntity +{ +public: + + siCamera () : siEntity ( "Camera" ) + { + } + + virtual void update ( double dt ) + { + updatePhysics ( dt ) ; + ssgSetCamera ( & pos ) ; + } +} ; + + + +class siModel : public siEntity +{ + ssgEntity *ent ; + ssgTransform *tra ; + +public: + + siModel ( const char *_fname ) : siEntity ( _fname ) + { + tra = new ssgTransform ; + ent = ssgLoad ( name ) ; + tra -> addKid ( ent ) ; + + ssgFlatten ( ent ) ; + ssgStripify ( tra ) ; + + siScene -> addKid ( tra ) ; + } + + virtual void update ( double dt ) + { + updatePhysics ( dt ) ; + tra -> setTransform ( & pos ) ; + } +} ; + + +static siEntity *getModel ( int i ) +{ + if ( i < 0 || i >= SI_MAX_MODELS || + siModels [ i ] == NULL ) + { + fprintf ( stderr, "simon: There is no such model as '%d'\n", i ) ; + exit ( 1 ) ; + } + + return siModels [ i ] ; +} + + +float siGetPositionX(int hh) { return getModel ( hh ) -> getPositionX () ; } +float siGetPositionY(int hh) { return getModel ( hh ) -> getPositionY () ; } +float siGetPositionZ(int hh) { return getModel ( hh ) -> getPositionZ () ; } +float siGetPositionH(int hh) { return getModel ( hh ) -> getPositionH () ; } +float siGetPositionP(int hh) { return getModel ( hh ) -> getPositionP () ; } +float siGetPositionR(int hh) { return getModel ( hh ) -> getPositionR () ; } + + +void siPosition ( int hh, float x, float y, float z, + float h, float p, float r ) +{ + getModel ( hh ) -> setPosition ( x, y, z, h, p, r ) ; +} + +void siSpeedAndDirection ( int hh, float s, float h, float p ) +{ + getModel ( hh ) -> setSpeedAndDirection ( s, h, p ) ; +} + +void siVelocity ( int hh, float x, float y, float z, + float h, float p, float r ) +{ + getModel ( hh ) -> setVelocity ( x, y, z, h, p, r ) ; +} + + +/* + The GLUT window reshape event +*/ + +static void siReshape ( int w, int h ) +{ + glViewport ( 0, 0, w, h ) ; +} + + + +/* + The GLUT keyboard event +*/ + +static void siKeyboard ( unsigned char k, int, int ) +{ + if ( k == 0x03 ) exit ( 0 ) ; +} + + + +static jsJoystick js (0) ; + +static bool A, B, C, D, L, R ; + +static float leftright ; +static float updown ; + +static void read_joystick () +{ + int b ; + float ax [ 10 ] ; + + js.read ( &b, ax ) ; + + leftright = ax[0] ; + updown = ax[1] ; + + A = (( b & 1 ) != 0) ; + B = (( b & 2 ) != 0) ; + C = (( b & 4 ) != 0) ; + D = (( b & 8 ) != 0) ; + R = (( b & 16 ) != 0) ; + L = (( b & 32 ) != 0) ; +} + +float siJoystickLR () { return -leftright ; } +float siJoystickUD () { return -updown ; } + +bool siJoystickA () { return A ; } +bool siJoystickB () { return B ; } +bool siJoystickC () { return C ; } +bool siJoystickD () { return D ; } +bool siJoystickL () { return L ; } +bool siJoystickR () { return R ; } + +/* + The GLUT redraw event +*/ + +static ulClock *siFrameTimer ; + +static void siRedraw () +{ + siFrameTimer -> update () ; + + double dt = siFrameTimer -> getDeltaTime () ; + + read_joystick () ; + + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + siUpdate () ; + + for ( int i = 0 ; i < siNextModel ; i++ ) + siModels [ i ] -> update ( dt ) ; + + ssgCullAndDraw ( siScene ) ; + + glutPostRedisplay () ; + glutSwapBuffers () ; + ulSleep(16); +} + + + +void siInit () +{ + if ( siInitialised ) + { + fprintf ( stderr, "simon: ERROR - siInit() was called more than once!\n" ) ; + exit ( 1 ) ; + } + + siInitialised = true ; + + siFrameTimer = new ulClock ; + + siFrameTimer -> update () ; + + int fake_argc = 1 ; + char *fake_argv[3] ; + fake_argv[0] = "Simon" ; + fake_argv[1] = "Simon Window." ; + fake_argv[2] = NULL ; + + /* Initialise GLUT */ + + glutInitWindowPosition ( 0, 0 ) ; + glutInitWindowSize ( 600, 600 ) ; + glutInit ( &fake_argc, fake_argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + glutCreateWindow ( fake_argv[1] ) ; + glutDisplayFunc ( siRedraw ) ; + glutReshapeFunc ( siReshape ) ; + glutKeyboardFunc ( siKeyboard ) ; + + /* Initialise SSG */ + + ssgInit () ; + + /* Some basic OpenGL setup */ + + glClearColor ( 0.2f, 0.7f, 1.0f, 1.0f ) ; + glEnable ( GL_DEPTH_TEST ) ; + + /* Set up the viewing parameters */ + + ssgSetFOV ( 90.0f, 90.0f ) ; + ssgSetNearFar ( 0.1f, 700.0f ) ; + + /* Set up the Sun. */ + + sgVec3 sunposn ; + sgSetVec3 ( sunposn, 0.2f, -0.5f, 0.5f ) ; + ssgGetLight ( 0 ) -> setPosition ( sunposn ) ; + + /* Set up the path to the data files */ + + ssgModelPath ( "data" ) ; + ssgTexturePath ( "data" ) ; + + /* Create a root node. */ + + siScene = new ssgRoot ; + + for ( int i = 0 ; i < SI_MAX_MODELS ; i++ ) + siModels [ i ] = NULL ; + + siNextModel = 0 ; + new siCamera () ; /* Thus guaranteeing this is handle zero */ +} + + + +/* Load a simple model */ + +int siLoad ( const char *filename ) +{ + if ( ! siInitialised ) + siInit () ; + + siModel *m = new siModel ( filename ) ; + + return m -> getHandle () ; +} + + +void siRun () +{ + if ( ! siInitialised ) + siInit () ; + + glutMainLoop () ; +} + diff --git a/demos/ttt3d/AUTHORS b/demos/ttt3d/AUTHORS new file mode 100644 index 0000000..a957b7c --- /dev/null +++ b/demos/ttt3d/AUTHORS @@ -0,0 +1,2 @@ +TTT3D was written by Steve Baker. + diff --git a/demos/ttt3d/COPYING b/demos/ttt3d/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/demos/ttt3d/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/demos/ttt3d/ChangeLog b/demos/ttt3d/ChangeLog new file mode 100644 index 0000000..06f3320 --- /dev/null +++ b/demos/ttt3d/ChangeLog @@ -0,0 +1,8 @@ + +TTT3D Change Log. +================= + +TTT3D v0.0.0 (July 21st 2001) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * First release. + diff --git a/demos/ttt3d/INSTALL b/demos/ttt3d/INSTALL new file mode 100644 index 0000000..b42a17a --- /dev/null +++ b/demos/ttt3d/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/demos/ttt3d/Makefile.am b/demos/ttt3d/Makefile.am new file mode 100644 index 0000000..3daeafd --- /dev/null +++ b/demos/ttt3d/Makefile.am @@ -0,0 +1,4 @@ +SUBDIRS = src wavs images data mods fonts doc + +EXTRA_DIST = autogen.sh README acinclude.m4 TTT3D.dsw TTT3D.dsp + diff --git a/demos/ttt3d/NEWS b/demos/ttt3d/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/demos/ttt3d/README b/demos/ttt3d/README new file mode 100644 index 0000000..58615fc --- /dev/null +++ b/demos/ttt3d/README @@ -0,0 +1,54 @@ + +TicTacToe 3D. +~~~~~~~~~~~~~ + by Steve Baker + + +INSTALLATION: + +Installation instructions are pretty basic, +and are covered in the documentation directory 'doc'. + + OpenGL (or Mesa) + GLUT (the GL Utility Toolkit) + PLIB (which can be obtained from one of: + http://plib.sourceforge.net + +Once that is done, it should be a simple matter of changing +to the directory where all this stuff is unpacked and type: + + ./configure + make + make install + +However, you might want to check the full documentation - +especially if you need to install Mesa/GLIDE/GLUT before +you can start. + +All documents are in HTML - so view them with your web browser. + +LICENSE: + +This software is released under the provisions of +the GNU General Public License (GPL) which can be +found in the file 'COPYING' in the current directory. + +DIRECTORY STRUCTURE: + +src -- Where the source code lives. + +data -- This contains all kinds of miscellaneous data + files. Right now, this is limited to the level + description files. + +doc -- Documentation - all in HTML + +images -- Texture maps and other images needed by the + game. These are currently all in 'SGI' image + format. + +wavs -- Sound files - mostly sound effects. + +mods -- Music files. + + diff --git a/demos/ttt3d/TTT3D.dsp b/demos/ttt3d/TTT3D.dsp new file mode 100644 index 0000000..e05fb7d --- /dev/null +++ b/demos/ttt3d/TTT3D.dsp @@ -0,0 +1,172 @@ +# Microsoft Developer Studio Project File - Name="TTT3D" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=TTT3D - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "TTT3D.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "TTT3D.mak" CFG="TTT3D - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "TTT3D - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "TTT3D - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "TTT3D - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../../" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sl.lib fnt.lib pui.lib ssgAux.lib ssg.lib sg.lib ul.lib glut32.lib opengl32.lib winmm.lib /nologo /subsystem:console /machine:I386 /out:"TTT3D.exe" /libpath:"../../" + +!ELSEIF "$(CFG)" == "TTT3D - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sl_d.lib fnt_d.lib pui_d.lib ssgAux_d.lib ssg_d.lib sg_d.lib ul_d.lib glut32.lib opengl32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /out:"TTT3D.exe" /pdbtype:sept /libpath:"../../" + +!ENDIF + +# Begin Target + +# Name "TTT3D - Win32 Release" +# Name "TTT3D - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\src\cell.cxx +# End Source File +# Begin Source File + +SOURCE=.\src\game.cxx +# End Source File +# Begin Source File + +SOURCE=.\src\gfx.cxx +# End Source File +# Begin Source File + +SOURCE=.\src\gui.cxx +# End Source File +# Begin Source File + +SOURCE=.\src\material.cxx +# End Source File +# Begin Source File + +SOURCE=.\src\puzzle.cxx +# End Source File +# Begin Source File + +SOURCE=.\src\sound.cxx +# End Source File +# Begin Source File + +SOURCE=.\src\status.cxx +# End Source File +# Begin Source File + +SOURCE=.\src\ttt3d.cxx +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\src\cell.h +# End Source File +# Begin Source File + +SOURCE=.\src\game.h +# End Source File +# Begin Source File + +SOURCE=.\src\gfx.h +# End Source File +# Begin Source File + +SOURCE=.\src\gui.h +# End Source File +# Begin Source File + +SOURCE=.\src\level.h +# End Source File +# Begin Source File + +SOURCE=.\src\material.h +# End Source File +# Begin Source File + +SOURCE=.\src\p3d.h +# End Source File +# Begin Source File + +SOURCE=.\src\puzzle.h +# End Source File +# Begin Source File + +SOURCE=.\src\sound.h +# End Source File +# Begin Source File + +SOURCE=.\src\status.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/demos/ttt3d/TTT3D.dsw b/demos/ttt3d/TTT3D.dsw new file mode 100644 index 0000000..ccb0384 --- /dev/null +++ b/demos/ttt3d/TTT3D.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "TTT3D"=.\TTT3D.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/demos/ttt3d/acinclude.m4 b/demos/ttt3d/acinclude.m4 new file mode 100755 index 0000000..3463ad8 --- /dev/null +++ b/demos/ttt3d/acinclude.m4 @@ -0,0 +1,8 @@ +AC_DEFUN(MY_EXPAND_DIR, [ + $1=$2 + $1=`( + test "x$prefix" = xNONE && prefix="$ac_default_prefix" + test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" + eval echo \""[$]$1"\" + )` +]) diff --git a/demos/ttt3d/autogen.sh b/demos/ttt3d/autogen.sh new file mode 100755 index 0000000..02a1eb9 --- /dev/null +++ b/demos/ttt3d/autogen.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +OSTYPE=`uname -s` + +AMFLAGS="--add-missing" +if test "$OSTYPE" = "IRIX" -o "$OSTYPE" = "IRIX64"; then + AMFLAGS=$AMFLAGS" --include-deps"; +fi + +echo "Running aclocal" +aclocal +echo "Running automake" +automake $AMFLAGS +echo "Running autoconf" +autoconf + +echo "======================================" +echo "Now you are ready to run './configure'" +echo "======================================" diff --git a/demos/ttt3d/configure.in b/demos/ttt3d/configure.in new file mode 100644 index 0000000..a120ca2 --- /dev/null +++ b/demos/ttt3d/configure.in @@ -0,0 +1,174 @@ +dnl Process this file with autoconf to produce a configure script. + +AC_INIT(src/ttt3d.cxx) +AM_INIT_AUTOMAKE(ttt3d, 0.2.0) + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_CPP +AC_PROG_CXX +AC_PROG_CXXCPP +AC_PROG_INSTALL + +plib_suffix="-lplibjs -lplibsl -lplibssgaux -lplibssg -lplibpu -lplibfnt -lplibsg -lplibul" + +AC_LANG_CPLUSPLUS + + +dnl Command line arguments. + +dnl Don't use AC_HELP_STRING here as old versions of autoconf do not +dnl understand it. +AC_ARG_WITH(GL, +[ --with-GL=DIR set the prefix directory where GL resides], +GL_PREFIX=$withval, GL_PREFIX=auto) + +if test "x$GL_PREFIX" != "xauto"; then + LDFLAGS="$LDFLAGS -L$GL_PREFIX/lib" + CPPFLAGS="$CPPFLAGS -I$GL_PREFIX/include" +fi + + +dnl Checks for library functions. +dnl check for OpenGL related libraries + +AC_CANONICAL_HOST + +case "${host}" in +*-*-cygwin* | *-*-mingw32*) + dnl CygWin under Windoze. + + LIBS="$LIBS -lwinmm -lglut32 -lglu32 -lopengl32 -luser32 -lgdi32" + ;; +*-apple-darwin*) + dnl Mac OS X + + LIBS="$LIBS -framework GLUT -lobjc -framework OpenGL -framework Carbon" + ;; +*) + dnl Check for X11 + + AC_PATH_XTRA + + LDFLAGS="$LDFLAGS $X_LIBS" + + LIBS="$LIBS $X_PRE_LIBS -lXi -lXmu -lXext -lX11 $X_EXTRA_LIBS -lm" + +dnl ========================================================= +dnl if test "x$x_includes" != "x"; then +dnl CPPFLAGS="$CPPFLAGS -I$x_includes" +dnl fi +dnl ========================================================= + + dnl Reasonable stuff non-windoze variants ... :-) + + AC_CHECK_LIB(GL, glNewList) + if test "x$ac_cv_lib_GL_glNewList" = "xno" ; then + dnl if no GL, check for MesaGL + AC_CHECK_LIB(MesaGL, glNewList,, + AC_MSG_ERROR([could not find working GL library])) + fi + + AC_CHECK_LIB(GLU, gluLookAt) + if test "x$ac_cv_lib_GLU_gluLookAt" = "xno" ; then + dnl if no GLU, check for MesaGLU + AC_CHECK_LIB(MesaGLU, gluLookAt,, + AC_MSG_ERROR([could not find working GLU library])) + fi + + dnl check for glut...or freeglut + AC_CHECK_LIB(freeglut, glutGetModifiers) + if test "x$ac_cv_lib_freeglut_glutGetModifiers" = "xno" ; then + dnl if no freeglut, check for Real GLUT + AC_CHECK_LIB(glut, glutGetModifiers,, + AC_MSG_ERROR([could not find working GLUT library])) + fi + + AC_CHECK_LIB(dl, dlclose) + + dnl Check SGI audio library + AC_CHECK_LIB(audio, ALopenport, SND_LIBS="-laudio") + ;; +esac + +dnl Check PLIB library +AC_CHECK_LIB(plibul, ulInit, true, +AC_MSG_ERROR([there seems to be a problem with the PLIB libraries])) + +LIBS="$plib_suffix $LIBS" + + +dnl Checks for header files. + +AC_HEADER_STDC + +AC_CHECK_HEADER(windows.h, AC_DEFINE(WIN32)) + +case "${host}" in +*-*-cygwin* | *-*-mingw32*) + dnl CygWin under Windoze. + + AC_CHECK_HEADERS(GL/gl.h GL/glu.h,, + AC_MSG_ERROR([OpenGL header files not found])) + + AC_CHECK_HEADER(GL/glut.h, AC_DEFINE(GLUT_IS_PRESENT), + AC_MSG_ERROR([GLUT header file not found])) + ;; +*-apple-darwin*) + dnl Mac OS X + + AC_CHECK_HEADERS(OpenGL/gl.h OpenGL/glu.h,, + AC_MSG_ERROR([OpenGL header files not found])) + + AC_CHECK_HEADER(GLUT/glut.h, AC_DEFINE(GLUT_IS_PRESENT), + AC_MSG_ERROR([GLUT header file not found])) + ;; +*) + AC_CHECK_HEADERS(GL/gl.h GL/glu.h,, + AC_MSG_ERROR([OpenGL header files not found])) + + if test "x$ac_cv_lib_freeglut_glutGetModifiers" = "xyes"; then + AC_CHECK_HEADER(GL/freeglut.h, AC_DEFINE(FREEGLUT_IS_PRESENT), + AC_MSG_ERROR([freeglut header file not found])) + else + AC_CHECK_HEADER(GL/glut.h, AC_DEFINE(GLUT_IS_PRESENT), + AC_MSG_ERROR([GLUT header file not found])) + fi + ;; +esac + +AC_CHECK_HEADER(plib/ul.h,, AC_MSG_ERROR([PLIB header files not found])) + + +dnl Warning flags +WFLAG="-Wall" +case "$host" in +mips-sgi-irix*) + if test "x$CXX" = "xCC"; then + WFLAG="-fullwarn"; + fi + ;; +*) + if test "x$CXX" = "xicpc" || test "x$CXX" = "xicc"; then + WFLAG="-w1" + fi + ;; +esac + +CFLAGS="$CFLAGS $WFLAG" +CXXFLAGS="$CXXFLAGS $WFLAG" + + +MY_EXPAND_DIR(ttt3d, "$datadir/games/$PACKAGE") +AC_DEFINE_UNQUOTED(TTT3D_DATADIR, "$ttt3d_datadir") + +AC_OUTPUT( Makefile \ + data/Makefile \ + doc/Makefile \ + fonts/Makefile \ + images/Makefile \ + mods/Makefile \ + src/Makefile \ + wavs/Makefile \ + ) + diff --git a/demos/ttt3d/data/Makefile.am b/demos/ttt3d/data/Makefile.am new file mode 100644 index 0000000..a2be649 --- /dev/null +++ b/demos/ttt3d/data/Makefile.am @@ -0,0 +1,7 @@ +# data/ + +pkgdatadir = $(datadir)/games/@PACKAGE@/data + +pkgdata_DATA = $(wildcard *.dat) + +EXTRA_DIST = $(pkgdata_DATA) \ No newline at end of file diff --git a/demos/ttt3d/data/levels.dat b/demos/ttt3d/data/levels.dat new file mode 100644 index 0000000..4880471 --- /dev/null +++ b/demos/ttt3d/data/levels.dat @@ -0,0 +1,2 @@ +Placeholder. + diff --git a/demos/ttt3d/doc/Makefile.am b/demos/ttt3d/doc/Makefile.am new file mode 100644 index 0000000..15b5d80 --- /dev/null +++ b/demos/ttt3d/doc/Makefile.am @@ -0,0 +1,5 @@ +# doc/ + +pkgdata_DATA = $(wildcard *.html) $(wildcard *.gif) + +EXTRA_DIST = $(pkgdata_DATA) diff --git a/demos/ttt3d/doc/index.html b/demos/ttt3d/doc/index.html new file mode 100644 index 0000000..ee2d550 --- /dev/null +++ b/demos/ttt3d/doc/index.html @@ -0,0 +1,95 @@ + + + + + Steve's 3D TicTacToe Player. + + +

Steve's 3D TicTacToe Player.

+By +Steve Baker <sjbaker1@airmail.net> +

Introduction.

+TicTacToe - the worlds most boring game. Well, when played +in three dimensions with a 4x4 board, this simple game takes +on an entirely new level of intellectual challenge. +

Installation:

+
+
+    ./configure
+    make 
+    make install
+
+
+If you are running Windoze or something that can't +run configure scripts and makefiles, don't sweat it. +There is just one C++ source file - no special options or libraries. +

+No, I won't provide a binary version, project +files and such. +

License:

+This program is offered under the terms of the GNU +Public License (GPL). +

Instructions:

+Run this from any shell: +
+
+    ttt3d
+
+
+The computer takes 'O's and lets you go first. The first +person to make a row of 4 wins. +
+
+                         ~~~ 3D TicTacToe ~~~
+                            by Steve Baker
+
+
+   |   |   |         |   |   |         |   |   |         |   |   |      
+   |   |   |         |   |   |         |   |   |         |   |   |      
+_1_|_2_|_3_|_4_   17_|18_|19_|20_   33_|34_|35_|36_   49_|50_|51_|52_   
+   |   |   |         |   |   |         |   |   |         |   |   |      
+   | X |   |         | O |   |         |   |   |         |   |   |      
+_5_|___|_7_|_8_   21_|___|23_|24_   37_|38_|39_|40_   53_|54_|55_|56_   
+   |   |   |         |   |   |         |   |   |         |   |   |      
+   | X |   |         |   |   |         |   |*O*|         |   |   |      
+_9_|___|11_|12_   25_|26_|27_|28_   41_|42_|___|44_   57_|58_|59_|60_   
+   |   |   |         |   |   |         |   |   |         |   |   |      
+   |   |   |         |   |   |         |   |   |         |   |   |      
+13 |14 |15 |16    29 |30 |31 |32    45 |46 |47 |48    61 |62 |63 |64    
+
+
+Where would you like to play your X ? 
+[1..64]: 
+
+
+(In the example above, the computer just played in square 43 the +asterisks help you see where he just played). +

+Imagine the four grids stacked on top of each other. (Either +from left to right or right to left - it doesn't matter). +You can form your row of four X's either within one layer - +or across layers. Anything that would be a straight line in +3D. So in this example: +

+
+   |   |   |         |   |   |         |   |   |         |   |   |      
+ X |   |   |         |   |   |         |   | O |      *O*|   |   | X    
+___|_2_|_3_|_4_   17_|18_|19_|20_   33_|34_|___|36_   ___|50_|51_|___   
+   |   |   |         |   |   |         |   |   |         |   |   |      
+   | X |   |         |   |   |         |*O*|   |       X | O |   |      
+_5_|___|_7_|_8_   21_|22_|23_|24_   37_|___|39_|40_   ___|___|55_|56_   
+   |   |   |         |   |   |         |   |   |         |   |   |      
+   |   |   |         |   |*O*|         |   |   |         | O | X | X    
+_9_|10_|11_|12_   25_|26_|___|28_   41_|42_|43_|44_   57_|___|___|___   
+   |   |   |         |   |   |         |   |   |         |   |   |      
+ X |   |   |*O*      |   |   | X       |   |   |       O | X |   | O    
+   |14 |15 |      29 |30 |31 |      45 |46 |47 |48       |   |63 |      
+
+
+...the computer just won with a diagonal line (when someone wins, +the winning line is highlighted with asterisks). +

+You'll find the computer is an extremely hard opponent to beat, +but it CAN BE DONE! + + diff --git a/demos/ttt3d/fonts/Makefile.am b/demos/ttt3d/fonts/Makefile.am new file mode 100644 index 0000000..0cac0fc --- /dev/null +++ b/demos/ttt3d/fonts/Makefile.am @@ -0,0 +1,7 @@ +# fonts/ + +pkgdatadir = $(datadir)/games/@PACKAGE@/fonts + +pkgdata_DATA = $(wildcard *.txf) + +EXTRA_DIST = $(pkgdata_DATA) \ No newline at end of file diff --git a/demos/ttt3d/fonts/sorority.txf b/demos/ttt3d/fonts/sorority.txf new file mode 100644 index 0000000..8b457aa Binary files /dev/null and b/demos/ttt3d/fonts/sorority.txf differ diff --git a/demos/ttt3d/images/Makefile.am b/demos/ttt3d/images/Makefile.am new file mode 100644 index 0000000..8f56852 --- /dev/null +++ b/demos/ttt3d/images/Makefile.am @@ -0,0 +1,7 @@ +# images/ + +pkgdatadir = $(datadir)/games/@PACKAGE@/images + +pkgdata_DATA = $(wildcard *.rgb) $(wildcard *.rgba) $(wildcard *.int) $(wildcard *.inta) + +EXTRA_DIST = $(pkgdata_DATA) \ No newline at end of file diff --git a/demos/ttt3d/images/O.rgb b/demos/ttt3d/images/O.rgb new file mode 100644 index 0000000..45bddcb Binary files /dev/null and b/demos/ttt3d/images/O.rgb differ diff --git a/demos/ttt3d/images/X.rgb b/demos/ttt3d/images/X.rgb new file mode 100644 index 0000000..b6fb473 Binary files /dev/null and b/demos/ttt3d/images/X.rgb differ diff --git a/demos/ttt3d/images/controls.rgb b/demos/ttt3d/images/controls.rgb new file mode 100644 index 0000000..09565e9 Binary files /dev/null and b/demos/ttt3d/images/controls.rgb differ diff --git a/demos/ttt3d/images/ground.rgb b/demos/ttt3d/images/ground.rgb new file mode 100644 index 0000000..9874e2f Binary files /dev/null and b/demos/ttt3d/images/ground.rgb differ diff --git a/demos/ttt3d/mods/Makefile.am b/demos/ttt3d/mods/Makefile.am new file mode 100644 index 0000000..236a373 --- /dev/null +++ b/demos/ttt3d/mods/Makefile.am @@ -0,0 +1,7 @@ +# mods/ + +pkgdatadir = $(datadir)/games/@PACKAGE@/mods + +pkgdata_DATA = $(wildcard *.mod) + +EXTRA_DIST = $(pkgdata_DATA) \ No newline at end of file diff --git a/demos/ttt3d/mods/mfarmer.mod b/demos/ttt3d/mods/mfarmer.mod new file mode 100644 index 0000000..ebec4c7 Binary files /dev/null and b/demos/ttt3d/mods/mfarmer.mod differ diff --git a/demos/ttt3d/src/Makefile.am b/demos/ttt3d/src/Makefile.am new file mode 100644 index 0000000..820363b --- /dev/null +++ b/demos/ttt3d/src/Makefile.am @@ -0,0 +1,12 @@ +# src/ + +bindir=$(prefix)/games + +bin_PROGRAMS = ttt3d + +ttt3d_SOURCES = \ + ttt3d.cxx gfx.cxx material.cxx gui.cxx status.cxx sound.cxx \ + cell.cxx puzzle.cxx game.cxx \ + p3d.h gfx.h gui.h material.h status.h sound.h \ + cell.h puzzle.h level.h game.h + diff --git a/demos/ttt3d/src/cell.cxx b/demos/ttt3d/src/cell.cxx new file mode 100644 index 0000000..1b7ec05 --- /dev/null +++ b/demos/ttt3d/src/cell.cxx @@ -0,0 +1,291 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: cell.cxx 1465 2002-08-30 14:05:59Z wolfram_kuss $ +*/ + + +#include "p3d.h" +#include + +static ssgBranch *wire_cube = NULL ; +static ssgBranch * X_cube = NULL ; +static ssgBranch * O_cube = NULL ; + + +ssgTransform *makeGround () +{ + ssgTransform *ground = new ssgTransform () ; + + sgVec4 *colour = new sgVec4 [ 1 ] ; + sgVec3 *normal = new sgVec3 [ 1 ] ; + sgVec2 *tcoord = new sgVec2 [ 4 ] ; + sgVec3 *scoord = new sgVec3 [ 4 ] ; + + sgSetVec4 ( colour[0], 1, 1, 1, 1 ) ; + + sgSetVec2 ( tcoord [ 0 ], 0, 0 ) ; + sgSetVec2 ( tcoord [ 1 ], 25, 0 ) ; + sgSetVec2 ( tcoord [ 2 ], 25, 25 ) ; + sgSetVec2 ( tcoord [ 3 ], 0, 25 ) ; + + sgSetVec3 ( normal [ 0 ], 0, 0, 1 ) ; + + sgSetVec3 ( scoord [ 0 ], -60, -60, -5.6f ) ; + sgSetVec3 ( scoord [ 1 ], 60, -60, -5.6f ) ; + sgSetVec3 ( scoord [ 2 ], 60, 60, -5.6f ) ; + sgSetVec3 ( scoord [ 3 ], -60, 60, -5.6f ) ; + + ssgVTable *vt1 = new ssgVTable ( (GLenum) GL_TRIANGLE_FAN, + 4, scoord, + 1, normal, + 4, tcoord, + 1, colour ) ; + + vt1 -> setState ( ground_gst ) ; ground -> addKid ( vt1 ) ; + + colour = new sgVec4 [ 1 ] ; + normal = new sgVec3 [ 1 ] ; + tcoord = new sgVec2 [ 6 ] ; + scoord = new sgVec3 [ 6 ] ; + + sgSetVec4 ( colour[0], 1, 1, 1, 1 ) ; + + sgSetVec2 ( tcoord [ 0 ], 0, 0 ) ; + sgSetVec2 ( tcoord [ 1 ], 1, 0 ) ; + sgSetVec2 ( tcoord [ 2 ], 1, 1 ) ; + sgSetVec2 ( tcoord [ 3 ], 0, 1 ) ; + sgSetVec2 ( tcoord [ 4 ], 1, 1 ) ; + sgSetVec2 ( tcoord [ 5 ], 1, 0 ) ; + + sgSetVec3 ( normal [ 0 ], 0, 0, 1 ) ; + + sgSetVec3 ( scoord [ 0 ], -2, -2, -2.5 ) ; + sgSetVec3 ( scoord [ 1 ], 1, -2, -2.5 ) ; + sgSetVec3 ( scoord [ 2 ], 1, 1, -2.5 ) ; + sgSetVec3 ( scoord [ 3 ], -2, 1, -2.5 ) ; + sgSetVec3 ( scoord [ 4 ], 1, 1, -2.5 ) ; + sgSetVec3 ( scoord [ 5 ], 1, -2, -2.5 ) ; + + vt1 = new ssgVTable ( (GLenum) GL_TRIANGLE_FAN, + 6, scoord, + 1, normal, + 6, tcoord, + 1, colour ) ; + + vt1 -> setState ( ctrls_gst ) ; ground -> addKid ( vt1 ) ; + + return ground ; +} ; + +ssgTransform *makeBlueWireCube() +{ + ssgTransform *sel_cube = new ssgTransform () ; + + sgVec4 *colour = new sgVec4 [ 1 ] ; + sgVec3 *normal = new sgVec3 [ 1 ] ; + sgVec2 *tcoord = new sgVec2 [ 1 ] ; + sgVec3 *scoord = new sgVec3 [ 8 ] ; + + sgSetVec4 ( colour[0], 1, 0, 1, 1 ) ; + sgSetVec3 ( normal[0], 1, 0, 0 ) ; + sgSetVec2 ( tcoord[0], 0, 0 ) ; + + sgSetVec3 ( scoord [ 0 ], -0.5, -0.5, -0.5 ) ; + sgSetVec3 ( scoord [ 1 ], -0.5, -0.5, 0.5 ) ; + sgSetVec3 ( scoord [ 2 ], 0.5, -0.5, 0.5 ) ; + sgSetVec3 ( scoord [ 3 ], 0.5, -0.5, -0.5 ) ; + + sgSetVec3 ( scoord [ 4 ], -0.5, 0.5, -0.5 ) ; + sgSetVec3 ( scoord [ 5 ], -0.5, 0.5, 0.5 ) ; + sgSetVec3 ( scoord [ 6 ], 0.5, 0.5, 0.5 ) ; + sgSetVec3 ( scoord [ 7 ], 0.5, 0.5, -0.5 ) ; + + unsigned short *sindex = new unsigned short [ 7 ] ; + unsigned short *cindex = new unsigned short [ 1 ] ; + unsigned short *nindex = new unsigned short [ 1 ] ; + unsigned short *tindex = new unsigned short [ 1 ] ; + + sindex [ 0 ] = 0 ; + sindex [ 1 ] = 1 ; + sindex [ 2 ] = 2 ; + sindex [ 3 ] = 6 ; + sindex [ 4 ] = 7 ; + sindex [ 5 ] = 3 ; + sindex [ 6 ] = 2 ; + + cindex [ 0 ] = 0 ; + nindex [ 0 ] = 0 ; + tindex [ 0 ] = 0 ; + + ssgVTable *vt1 = new ssgVTable ( (GLenum) GL_LINE_STRIP, + 7, sindex, scoord, + 1, nindex, normal, + 1, tindex, tcoord, + 1, cindex, colour ) ; + + sindex = new unsigned short [ 5 ] ; + + sindex [ 0 ] = 3 ; + sindex [ 1 ] = 0 ; + sindex [ 2 ] = 4 ; + sindex [ 3 ] = 5 ; + sindex [ 4 ] = 1 ; + + ssgVTable *vt2 = new ssgVTable ( (GLenum) GL_LINE_STRIP, + 5, sindex, scoord, + 1, nindex, normal, + 1, tindex, tcoord, + 1, cindex, colour ) ; + + sindex = new unsigned short [ 2 ] ; + + sindex [ 0 ] = 5 ; + sindex [ 1 ] = 6 ; + + ssgVTable *vt3 = new ssgVTable ( (GLenum) GL_LINE_STRIP, + 2, sindex, scoord, + 1, nindex, normal, + 1, tindex, tcoord, + 1, cindex, colour ) ; + + sindex = new unsigned short [ 2 ] ; + + sindex [ 0 ] = 4 ; + sindex [ 1 ] = 7 ; + + ssgVTable *vt4 = new ssgVTable ( (GLenum) GL_LINE_STRIP, + 2, sindex, scoord, + 1, nindex, normal, + 1, tindex, tcoord, + 1, cindex, colour ) ; + + vt1 -> setState ( default_gst ) ; sel_cube -> addKid ( vt1 ) ; + vt2 -> setState ( default_gst ) ; sel_cube -> addKid ( vt2 ) ; + vt3 -> setState ( default_gst ) ; sel_cube -> addKid ( vt3 ) ; + vt4 -> setState ( default_gst ) ; sel_cube -> addKid ( vt4 ) ; + + return sel_cube ; +} + + +static void makeWireCube() +{ + wire_cube = new ssgBranch () ; + + sgVec4 *colour = new sgVec4 [ 1 ] ; + sgVec3 *normal = new sgVec3 [ 1 ] ; + sgVec2 *tcoord = new sgVec2 [ 1 ] ; + sgVec3 *scoord = new sgVec3 [ 4 ] ; + + sgSetVec4 ( colour[0], 1.0, 1.0, 0.0, 0.7f ) ; + sgSetVec3 ( normal[0], 1, 0, 0 ) ; + sgSetVec2 ( tcoord[0], 0, 0 ) ; + + sgSetVec3 ( scoord [ 0 ], -0.5, -0.5, -0.5 ) ; + sgSetVec3 ( scoord [ 1 ], -0.5, 0.5, -0.5 ) ; + sgSetVec3 ( scoord [ 2 ], 0.5, 0.5, -0.5 ) ; + sgSetVec3 ( scoord [ 3 ], 0.5, -0.5, -0.5 ) ; + + unsigned short *sindex = new unsigned short [ 4 ] ; + unsigned short *cindex = new unsigned short [ 1 ] ; + unsigned short *nindex = new unsigned short [ 1 ] ; + unsigned short *tindex = new unsigned short [ 1 ] ; + + sindex [ 0 ] = 0 ; + sindex [ 1 ] = 1 ; + sindex [ 2 ] = 2 ; + sindex [ 3 ] = 3 ; + + cindex [ 0 ] = 0 ; + nindex [ 0 ] = 0 ; + tindex [ 0 ] = 0 ; + + ssgVTable *vt = new ssgVTable ( (GLenum) GL_LINE_LOOP, + 4, sindex, scoord, 1, nindex, normal, + 1, tindex, tcoord, 1, cindex, colour ) ; + + vt -> setState ( default_gst ) ; + wire_cube -> addKid ( vt ) ; +} + + +static ssgBranch *X () +{ + ssgaCube *XXX = new ssgaCube () ; + + XXX -> setSize ( 0.5 ) ; + XXX -> setKidState ( X_gst ) ; + + return XXX ; +} + + +static ssgBranch *O () +{ + ssgaSphere *OOO = new ssgaSphere ( 300 ) ; + + OOO -> setSize ( 0.7f ) ; + OOO -> setKidState ( O_gst ) ; + + return OOO ; +} + + +static void makeXcube () +{ + X_cube = new ssgBranch () ; + X_cube -> addKid ( X () ) ; +} + + +static void makeOcube () +{ + O_cube = new ssgBranch () ; + O_cube -> addKid ( O () ) ; +} + + +Cell::Cell ( int x, int y, int z, int size ) +{ + if ( wire_cube == NULL ) makeWireCube() ; + if ( X_cube == NULL ) makeXcube () ; + if ( O_cube == NULL ) makeOcube () ; + + sgSetCoord ( &c, (float)x - (float) size / 2.0f + 0.5f, + (float)y - (float) size / 2.0f + 0.5f, + (float)z - (float) size / 2.0f + 0.5f, 0,0,0 ) ; + + posn = new ssgTransform ( & c ) ; + cell = new ssgSelector () ; + + posn -> addKid ( cell ) ; + + /* Don't change the order of these without changing the defines */ + + cell -> addKid ( wire_cube ) ; + cell -> addKid ( X_cube ) ; + cell -> addKid ( O_cube ) ; + + what = WIRE_CELL ; + cell -> selectStep ( what ) ; +} + + diff --git a/demos/ttt3d/src/cell.h b/demos/ttt3d/src/cell.h new file mode 100644 index 0000000..f550573 --- /dev/null +++ b/demos/ttt3d/src/cell.h @@ -0,0 +1,55 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: cell.h 1427 2002-08-18 00:09:46Z ude $ +*/ + + +ssgTransform *makeBlueWireCube() ; +ssgTransform *makeGround() ; + +#define WIRE_CELL 0 +#define X_CELL 1 +#define O_CELL 2 + +class Cell +{ + sgCoord c ; + ssgTransform *posn ; + ssgSelector *cell ; + int what ; + +public: + + Cell ( int x, int y, int z, int size ) ; + + ssgBranch *getSSG () { return posn ; } + + int get () { return what ; } + + void set ( int n ) + { + what = n ; + cell -> selectStep ( n ) ; + } + +} ; + + diff --git a/demos/ttt3d/src/game.cxx b/demos/ttt3d/src/game.cxx new file mode 100644 index 0000000..f606796 --- /dev/null +++ b/demos/ttt3d/src/game.cxx @@ -0,0 +1,483 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: game.cxx 1427 2002-08-18 00:09:46Z ude $ +*/ + + +#include +#include +#include +#include "game.h" + +static char board [4][4][4] ; +static int last_x = -1 ; +static int last_y = -1 ; +static int last_z = -1 ; + +#define NUM_ROWS ( 3 * 16 + 3 * 8 + 4 ) + +static char *row [ NUM_ROWS ][ 4 ] ; +static char rowptr [ 4 ][ 4 ][ 4 ][ 8 ] ; +static char rowptrctr [ 4 ][ 4 ][ 4 ] ; + + +static void setupRowArray () +{ + int x, y, z; + + for ( x = 0 ; x < 4 ; x++ ) + for ( y = 0 ; y < 4 ; y++ ) + for ( z = 0 ; z < 4 ; z++ ) + { + rowptrctr [ x ][ y ][ z ] = 0 ; + + for ( int i = 0 ; i < 8 ; i++ ) + rowptr [ x ][ y ][ z ][ i ] = 127 ; + } + + int r = 0 ; + + /* 16 Z axis rows */ + + for ( x = 0 ; x < 4 ; x++ ) + for ( y = 0 ; y < 4 ; y++ ) + { + for ( z = 0 ; z < 4 ; z++ ) + { + row [ r ][ z ] = & board [ x ][ y ][ z ] ; + rowptr [ x ][ y ][ z ][ rowptrctr[x][y][z]++ ] = r ; + } + r++ ; + } + + /* 16 Y axis rows */ + + for ( x = 0 ; x < 4 ; x++ ) + for ( z = 0 ; z < 4 ; z++ ) + { + for ( y = 0 ; y < 4 ; y++ ) + { + row [ r ][ y ] = & board [ x ][ y ][ z ] ; + rowptr [ x ][ y ][ z ][ rowptrctr[x][y][z]++ ] = r ; + } + + r++ ; + } + + /* 16 Y axis rows */ + + for ( z = 0 ; z < 4 ; z++ ) + for ( y = 0 ; y < 4 ; y++ ) + { + for ( x = 0 ; x < 4 ; x++ ) + { + row [ r ][ x ] = & board [ x ][ y ][ z ] ; + rowptr [ x ][ y ][ z ][ rowptrctr[x][y][z]++ ] = r ; + } + + r++ ; + } + + /* 8 xy plane diagonals */ + + for ( z = 0 ; z < 4 ; z++ ) + { + int xy; + + for ( xy = 0 ; xy < 4 ; xy++ ) + { + row [ r ][ xy ] = & board [ xy ][ xy ][ z ] ; + rowptr [ xy ][ xy ][ z ][ rowptrctr[xy][xy][z]++ ] = r ; + } + + r++ ; + + for ( xy = 0 ; xy < 4 ; xy++ ) + { + row [ r ][ xy ] = & board [ xy ][ 3 - xy ][ z ] ; + rowptr [ xy ][3-xy][ z ][ rowptrctr[xy][3-xy][z]++ ] = r ; + } + + r++ ; + } + + /* 8 xz plane diagonals */ + + for ( y = 0 ; y < 4 ; y++ ) + { + int xz; + + for ( xz = 0 ; xz < 4 ; xz++ ) + { + row [ r ][ xz ] = & board [ xz ][ y ][ xz ] ; + rowptr [ xz ][ y ][ xz ][ rowptrctr[xz][y][xz]++ ] = r ; + } + + r++ ; + + for ( xz = 0 ; xz < 4 ; xz++ ) + { + row [ r ][ xz ] = & board [ xz ][ y ][ 3 - xz ] ; + rowptr [ xz ][ y ][3-xz][ rowptrctr[xz][y][3-xz]++ ] = r ; + } + + r++ ; + } + + /* 8 yz plane diagonals */ + + for ( x = 0 ; x < 4 ; x++ ) + { + int yz; + for ( yz = 0 ; yz < 4 ; yz++ ) + { + row [ r ][ yz ] = & board [ x ][ yz ][ yz ] ; + rowptr [ x ][ yz ][ yz ][ rowptrctr[x][yz][yz]++ ] = r ; + } + + r++ ; + + for ( yz = 0 ; yz < 4 ; yz++ ) + { + row [ r ][ yz ] = & board [ x ][ yz ][ 3 - yz ] ; + rowptr [ x ][ yz ][3-yz][ rowptrctr[x][yz][3-yz]++ ] = r ; + } + + r++ ; + } + + /* 4 grand diagonals. */ + + int xyz; + for ( xyz = 0 ; xyz < 4 ; xyz++ ) + { + row [ r ][ xyz ] = & board [ xyz ][ xyz ][ xyz ] ; + rowptr [ xyz ][ xyz ][ xyz ][ rowptrctr[xyz][xyz][xyz]++ ] = r ; + } + + r++ ; + + for ( xyz = 0 ; xyz < 4 ; xyz++ ) + { + row [ r ][ xyz ] = & board [ xyz ][ xyz ][ 3-xyz ] ; + rowptr [ xyz ][ xyz ][ 3-xyz ][ rowptrctr[xyz][xyz][3-xyz]++ ] = r ; + } + + r++ ; + + for ( xyz = 0 ; xyz < 4 ; xyz++ ) + { + row [ r ][ xyz ] = & board [ xyz ][ 3-xyz ][ xyz ] ; + rowptr [ xyz ][ 3-xyz ][ xyz ][ rowptrctr[xyz][3-xyz][xyz]++ ] = r ; + } + + r++ ; + + for ( xyz = 0 ; xyz < 4 ; xyz++ ) + { + row [ r ][ xyz ] = & board [ xyz ][ 3-xyz ][ 3-xyz ] ; + rowptr [ xyz ][ 3-xyz ][ 3-xyz ][ rowptrctr[xyz][3-xyz][3-xyz]++ ] = r ; + } + + r++ ; + + if ( r != NUM_ROWS ) + { + fprintf ( stderr, "%d rows?!?\n", r ) ; + exit ( 1 ) ; + } +} + + +static void clearBoard () +{ + for ( int x = 0 ; x < 4 ; x++ ) + for ( int y = 0 ; y < 4 ; y++ ) + for ( int z = 0 ; z < 4 ; z++ ) + board [ x ][ y ][ z ] = ' ' ; +} + + +/*void printBoard ( int winrow ) +{ + int x, y, z; + + for ( int i = 0 ; i < 50 ; i++ ) + printf ( "\n" ) ; + + printf ( " ~~~ 3D TicTacToe ~~~\n" ) ; + printf ( " by Steve Baker\n"); + printf ( "\n" ) ; + printf ( "\n" ) ; + + for ( y = 0 ; y < 4 ; y++ ) + { + for ( z = 0 ; z < 4 ; z++ ) + { + for ( x = 0 ; x < 4 ; x++ ) + { + printf ( " " ) ; + + if ( x != 3 ) + printf ( "|" ) ; + } + printf ( " " ) ; + } + printf ( "\n" ) ; + + for ( z = 0 ; z < 4 ; z++ ) + { + for ( x = 0 ; x < 4 ; x++ ) + { + int q ; + + for ( q = 0 ; q < 4 ; q++ ) + if ( row[winrow][q] == & board[x][y][z] ) + break ; + + if ( ( x == last_x && y == last_y && z == last_z ) || + q < 4 ) + printf ( "*%c*", board [ x ][ y ][ z ] ) ; + else + printf ( " %c ", board [ x ][ y ][ z ] ) ; + + if ( x != 3 ) + printf ( "|" ) ; + } + printf ( " " ) ; + } + printf ( "\n" ) ; + + for ( z = 0 ; z < 4 ; z++ ) + { + for ( x = 0 ; x < 4 ; x++ ) + { + if ( board [ x ][ y ][ z ] == ' ' ) + { + if ( y != 3 ) + { + if ( x+y*4+z*16+1 < 10 ) + printf ( "_%d_", x + y * 4 + z * 16 + 1 ) ; + else + printf ( "%2d_", x + y * 4 + z * 16 + 1 ) ; + } + else + printf ( "%2d ", x + y * 4 + z * 16 + 1 ) ; + } + else + if ( y != 3 ) + printf ( "___" ) ; + else + printf ( " " ) ; + + if ( x != 3 ) + printf ( "|" ) ; + } + printf ( " " ) ; + } + printf ( "\n" ) ; + } + + printf ( "\n" ) ; + printf ( "\n" ) ; +}*/ + + + +static int value [4][4] = /* Value of 1000000 means play here to win. */ +{ + { 1, 3,10, 1000000 }, /* No enemy, 0,1,2,3 of ours */ + { 2, 0, 0, 0 }, /* One enemy, 0,1,2,3 of ours */ + { 20, 0, 0, 0 }, /* Two enemy, 0,1,2,3 of ours */ + { 1000, 0, 0, 0 }, /* Three enemy, 0,1,2,3 of ours */ +} ; + + + +static int win = STILL_PLAYING ; + + +static int countRow ( int r ) +{ + int x = 0 ; + int o = 0 ; + + for ( int i = 0 ; i < 4 ; i++ ) + { + if ( *(row[r][i]) == 'X' ) x++ ; + if ( *(row[r][i]) == 'O' ) o++ ; + } + + if ( x == 4 ) { /* printBoard (r) ; */ + printf ( "** Human wins! **\n\n" ) ; + win = HUMAN_WIN ; + return 0 ; } + + if ( o == 4 ) { /* printBoard (r) ; */ + printf ( "** Computer wins! **\n\n" ) ; + win = COMPUTER_WIN ; + return 0 ; } + + return value [ x ][ o ] ; +} + + + +/*int getLoc ( char *msg ) +{ + + while ( 1 ) + { + int res = -1 ; + char s [ 21 ] ; + + printf ( "%s\n[1..64]: ", msg ) ; + fgets ( s, 20, stdin ) ; + + char *p = s ; + + while ( *p == ' ' || *p == '\t' ) p++ ; + + if ( isdigit ( *p ) ) + { + res = atoi ( p ) - 1 ; + + if ( res >= 0 && res <= 63 && board[res%4][(res%16)/4][res/16] == ' ' ) + return res ; + + if ( res >= 0 && res <= 63 ) + printf ( "You can't play there - it's already taken!\n" ) ; + else + printf ( "Please enter a number in the range 0 to 63.\n" ) ; + } + else + printf ( "Please type a NUMBER in the range 0 to 63.\n" ) ; + } +}*/ + + + +void game_init () +{ + win = STILL_PLAYING ; + setupRowArray () ; + clearBoard () ; +} + + +char get_board_entry ( int x, int y, int z ) +{ + return board[x][y][z] ; +} + + +int game_update ( int x, int y, int z ) +{ + int q; + + if ( win != STILL_PLAYING ) + game_init () ; + + /* printBoard (-1) ; */ + + board[x][y][z] = 'X' ; + + int rc = rowptrctr[x][y][z] ; + + for ( q = 0 ; q < rc ; q++ ) + { + int r = rowptr[x][y][z][q] ; + + countRow ( r ) ; /* Just to check for a win! */ + + if ( win != STILL_PLAYING ) + return win ; + } + + int best = -1 ; + int best_sum = 0 ; + + for ( int p = 0 ; p < 64 ; p++ ) + { + x = p % 4 ; + y = (p % 16)/4 ; + z = p/16 ; + + if ( board[x][y][z] != ' ' ) + continue ; + + rc = rowptrctr[x][y][z] ; + + int sum = 0 ; + + for ( int q = 0 ; q < rc ; q++ ) + { + int r = rowptr[x][y][z][q] ; + + sum += countRow ( r ) ; /* Just to check for a win! */ + + if ( win != STILL_PLAYING ) + { + board[x][y][z] = 'O' ; + return win ; + } + } + + if ( sum >= best_sum ) + { + best = p ; + best_sum = sum ; + } + } + + if ( best == -1 ) + { + /* printBoard (-1) ; */ + printf ( "** It's a draw! **\n\n" ) ; + return DRAWN_GAME ; + } + + x = best % 4 ; + y = (best % 16)/4 ; + z = best/16 ; + + board[x][y][z] = 'O' ; + + last_x = x ; + last_y = y ; + last_z = z ; + + rc = rowptrctr[x][y][z] ; + + for ( q = 0 ; q < rc ; q++ ) + { + int r = rowptr[x][y][z][q] ; + + countRow ( r ) ; /* Just to check for a win! */ + + if ( win != STILL_PLAYING ) + return win ; + } + + return STILL_PLAYING ; +} + + diff --git a/demos/ttt3d/src/game.h b/demos/ttt3d/src/game.h new file mode 100644 index 0000000..2642145 --- /dev/null +++ b/demos/ttt3d/src/game.h @@ -0,0 +1,33 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: game.h 1427 2002-08-18 00:09:46Z ude $ +*/ + + +#define STILL_PLAYING 0 +#define HUMAN_WIN 1 +#define COMPUTER_WIN 2 +#define DRAWN_GAME 3 + +void game_init () ; +char get_board_entry ( int x, int y, int z ) ; +int game_update ( int x, int y, int z ) ; + diff --git a/demos/ttt3d/src/gfx.cxx b/demos/ttt3d/src/gfx.cxx new file mode 100644 index 0000000..4443f5b --- /dev/null +++ b/demos/ttt3d/src/gfx.cxx @@ -0,0 +1,143 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: gfx.cxx 1465 2002-08-30 14:05:59Z wolfram_kuss $ +*/ + + +#include "p3d.h" + +static unsigned int lastGLUTKeystroke = 0 ; + +static void getGLUTSpecialKeystroke ( int key, int, int ) +{ + lastGLUTKeystroke = 256 + key ; +} + +static void getGLUTKeystroke ( unsigned char key, int, int ) +{ + lastGLUTKeystroke = key ; +} + +int getGLUTKeystroke () +{ + int k = lastGLUTKeystroke ; + lastGLUTKeystroke = 0 ; + return k ; +} + +static void reshape ( int w, int h ) +{ + glViewport ( 0, 0, w, h ) ; +} + +static void initWindow ( int w, int h ) +{ + int fake_argc = 1 ; + char *fake_argv[3] ; + + fake_argv[0] = "TTT3D" ; + fake_argv[1] = "TTT3D by Steve Baker." ; + fake_argv[2] = NULL ; + + glutInitWindowPosition ( 0, 0 ) ; + glutInitWindowSize ( w, h ) ; + glutInit ( &fake_argc, fake_argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + glutCreateWindow ( fake_argv[1] ) ; + glutDisplayFunc ( ttt3dMainLoop ) ; + glutKeyboardFunc ( getGLUTKeystroke ) ; + glutSpecialFunc ( getGLUTSpecialKeystroke ) ; + glutReshapeFunc ( reshape ) ; +#ifndef WIN32 + glutIdleFunc ( glutPostRedisplay ) ; +#endif +} + + +GFX::GFX () +{ + initWindow ( 640, 480 ) ; + + ssgInit () ; + + static int firsttime = 1 ; + + if ( firsttime ) + { + firsttime = 0 ; + initMaterials () ; + } + + ssgSetFOV ( 75.0f, 0.0f ) ; + ssgSetNearFar ( 0.01f, 10.0f ) ; + + sgCoord cam ; + sgSetVec3 ( cam.xyz, 0, 0, 0 ) ; + sgSetVec3 ( cam.hpr, 0, 0, 0 ) ; + ssgSetCamera ( & cam ) ; +} + + +void GFX::update () +{ + sgVec3 sunposn ; + sgVec4 skycol ; + sgVec4 white = { 1.0, 1.0, 1.0, 1.0 } ; + + sgSetVec3 ( sunposn, -0.2f, -0.5f, 0.2f ) ; + + sgSetVec4 ( skycol, 0.4f, 0.4f, 0.8f, 1.0f ) ; + + ssgGetLight ( 0 ) -> setPosition ( sunposn ) ; + ssgGetLight ( 0 ) -> setColour ( GL_AMBIENT , white ) ; + ssgGetLight ( 0 ) -> setColour ( GL_DIFFUSE , white ) ; + ssgGetLight ( 0 ) -> setColour ( GL_SPECULAR, white ) ; + + /* Clear the screen */ + + glClearColor ( skycol[0], skycol[1], skycol[2], skycol[3] ) ; + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + glEnable ( GL_DEPTH_TEST ) ; + + glFogf ( GL_FOG_DENSITY, 3.0f / 100.0f ) ; + glFogfv( GL_FOG_COLOR , skycol ) ; + glFogf ( GL_FOG_START , 0.0 ) ; + glFogi ( GL_FOG_MODE , GL_EXP ) ; + glHint ( GL_FOG_HINT , GL_NICEST ) ; + + sgCoord cam ; + sgSetVec3 ( cam.xyz, 0, 0, 0 ) ; + sgSetVec3 ( cam.hpr, 0, 0, 0 ) ; + ssgSetCamera ( & cam ) ; + + glEnable ( GL_FOG ) ; + ssgCullAndDraw ( scene ) ; + glDisable ( GL_FOG ) ; +} + + +void GFX::done () +{ + glutPostRedisplay () ; + glutSwapBuffers () ; +} + diff --git a/demos/ttt3d/src/gfx.h b/demos/ttt3d/src/gfx.h new file mode 100644 index 0000000..78ba048 --- /dev/null +++ b/demos/ttt3d/src/gfx.h @@ -0,0 +1,33 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: gfx.h 1427 2002-08-18 00:09:46Z ude $ +*/ + + +class GFX +{ +public: + + GFX () ; + void update () ; + void done () ; +} ; + diff --git a/demos/ttt3d/src/gui.cxx b/demos/ttt3d/src/gui.cxx new file mode 100644 index 0000000..1ad32d4 --- /dev/null +++ b/demos/ttt3d/src/gui.cxx @@ -0,0 +1,246 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: gui.cxx 1465 2002-08-30 14:05:59Z wolfram_kuss $ +*/ + + +#include "p3d.h" +#include "plib/pu.h" + +static int mouse_x ; +static int mouse_y ; +static int mouse_dx = 0 ; +static int mouse_dy = 0 ; +static int mouse_buttons = 0 ; + +fntTexFont *font ; + +static void motionfn ( int x, int y ) +{ + mouse_x = x ; + mouse_y = y ; + mouse_dx += mouse_x - 320 ; + mouse_dy += mouse_y - 240 ; + puMouse ( x, y ) ; +} + +static void mousefn ( int button, int updown, int x, int y ) +{ + mouse_x = x ; + mouse_y = y ; + + if ( updown == GLUT_DOWN ) + mouse_buttons |= (1<disable_music () ; } +static void music_on_cb ( puObject * ) { sound->enable_music () ; } +static void sfx_off_cb ( puObject * ) { sound->disable_sfx () ; } +static void sfx_on_cb ( puObject * ) { sound->enable_sfx () ; } + +static void exit_cb ( puObject * ) +{ + fprintf ( stderr, "Exiting TTT3D.\n" ) ; + exit ( 1 ) ; +} + +/* Menu bar entries: */ + +static char *exit_submenu [] = { "Exit", NULL } ; +static puCallback exit_submenu_cb [] = { exit_cb, NULL } ; + +static char *sound_submenu [] = { "Turn off Music", "Turn off Sounds", "Turn on Music", "Turn on Sounds", NULL } ; +static puCallback sound_submenu_cb [] = { music_off_cb, sfx_off_cb, music_on_cb, sfx_on_cb, NULL } ; + +static char *help_submenu [] = { "Versions...", "Credits...", "About...", "Help", NULL } ; +static puCallback help_submenu_cb [] = { versions_cb, credits_cb, about_cb, help_cb, NULL } ; + + + +GUI::GUI () +{ + hidden = TRUE ; + mouse_x = 320 ; + mouse_y = 240 ; + + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; + glutPassiveMotionFunc ( motionfn ) ; + + ssgInit () ; + puInit () ; + + font = new fntTexFont ; + font -> load ( "fonts/sorority.txf" ) ; + puFont ff ( font, 15 ) ; + puSetDefaultFonts ( ff, ff ) ; + puSetDefaultStyle ( PUSTYLE_SMALL_SHADED ) ; + puSetDefaultColourScheme ( 0.8f, 0.8f, 0.8f, 0.6f ) ; + + /* Make the menu bar */ + + main_menu_bar = new puMenuBar () ; + + main_menu_bar -> add_submenu ( "Exit" , exit_submenu , exit_submenu_cb ) ; + main_menu_bar -> add_submenu ( "Sound", sound_submenu, sound_submenu_cb ) ; + main_menu_bar -> add_submenu ( "Help" , help_submenu , help_submenu_cb ) ; + + main_menu_bar -> close () ; + main_menu_bar -> hide () ; +} + + +void GUI::show () +{ + hide_status () ; + hidden = FALSE ; + main_menu_bar -> reveal () ; +} + +void GUI::hide () +{ + hidden = TRUE ; + hide_status () ; + main_menu_bar -> hide () ; +} + +void GUI::update () +{ + int score = 0 ; /* INSERT SCORE-GETTER HERE */ + + keyboardInput () ; + drawStatusText ( score ) ; + + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; + glAlphaFunc ( GL_GREATER, 0.1f ) ; + glEnable ( GL_BLEND ) ; + + puDisplay () ; +} + + +void GUI::keyboardInput () +{ + int c = getGLUTKeystroke () ; + + if ( c <= 0 ) + return ; + + switch ( c ) + { + case 0x1B /* Escape */ : + case 0x03 /* Control-C */ : exit ( 0 ) ; + + case 'h' : hide_status () ; help () ; return ; + + case ' ' : if ( isHidden () ) + { + sound->playSfx ( SOUND_WHO_ELSE ) ; + show () ; + } + else + { + sound->playSfx ( SOUND_UGH ) ; + hide () ; + } + return ; + + case 'r' : + case 'R' : startLevel () ; return ; + + case (256+GLUT_KEY_LEFT ) : spinLeft () ; return ; + case (256+GLUT_KEY_RIGHT ) : spinRight () ; return ; + case (256+GLUT_KEY_UP ) : spinUp () ; return ; + case (256+GLUT_KEY_DOWN ) : spinDown () ; return ; + case (256+GLUT_KEY_PAGE_UP ) : zoomIn () ; return ; + case (256+GLUT_KEY_PAGE_DOWN ) : zoomOut () ; return ; + + default : /* DO NOTHING */ break ; + } + + if ( game_state == GAME_DEBRIEF ) + { + switch ( c ) + { + case 'r' : + case 'R' : startLevel () ; return ; + default : /* DO NOTHING */ break ; + } + } + + if ( game_state == GAME_RUNNING ) + { + switch ( c ) + { + case 'r' : + case 'R' : startLevel () ; return ; + + case '\n': + case '\r': makeMove () ; return ; + + case 'a' : puzzle->cursor_up () ; return ; + case 'z' : puzzle->cursor_down () ; return ; + case 's' : puzzle->cursor_in () ; return ; + case 'd' : puzzle->cursor_out () ; return ; + case 'x' : puzzle->cursor_left () ; return ; + case 'c' : puzzle->cursor_right () ; return ; + + default : /* DO NOTHING */ break ; + } + } +} + + diff --git a/demos/ttt3d/src/gui.h b/demos/ttt3d/src/gui.h new file mode 100644 index 0000000..8e40b4c --- /dev/null +++ b/demos/ttt3d/src/gui.h @@ -0,0 +1,46 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: gui.h 1427 2002-08-18 00:09:46Z ude $ +*/ + + +class GUI +{ + class puMenuBar *main_menu_bar ; + + int hidden ; + +public: + + GUI () ; + void update () ; + void show () ; + void hide () ; + int isHidden () { return hidden ; } + + void keyboardInput () ; +} ; + + +int getGLUTKeystroke () ; + +extern fntTexFont *font ; + diff --git a/demos/ttt3d/src/level.h b/demos/ttt3d/src/level.h new file mode 100644 index 0000000..f1357d5 --- /dev/null +++ b/demos/ttt3d/src/level.h @@ -0,0 +1,36 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: level.h 1427 2002-08-18 00:09:46Z ude $ +*/ + + +class Level +{ + int number ; + char *intro ; +} ; + + +#define GAME_INTRO 0 +#define GAME_RUNNING 1 +#define GAME_DEBRIEF 2 +#define GAME_START_OF_DAY 3 + diff --git a/demos/ttt3d/src/material.cxx b/demos/ttt3d/src/material.cxx new file mode 100644 index 0000000..5fbdaf9 --- /dev/null +++ b/demos/ttt3d/src/material.cxx @@ -0,0 +1,175 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: material.cxx 1465 2002-08-30 14:05:59Z wolfram_kuss $ +*/ + + +#include "p3d.h" + +ssgSimpleState *default_gst, *O_gst, *X_gst, *ground_gst, *ctrls_gst ; + +static Material gs_setup [] = +{ + /* gst texture_map clamp, trans,aref,light,frctn,0 */ + { &default_gst, "", FALSE, TRUE , 0.0f, FALSE, 1.0, 0 }, + { & ground_gst, "images/ground.rgb", FALSE, FALSE, 0.2f, FALSE, 1.0, 0 }, + { & ctrls_gst, "images/controls.rgb",FALSE, TRUE , 0.2f, FALSE, 1.0, 0 }, + { & X_gst, "images/X.rgb" , FALSE, FALSE, 0.2f, TRUE , 1.0, 0 }, + { & O_gst, "images/O.rgb" , FALSE, FALSE, 0.2f, TRUE , 1.0, 0 }, + { NULL, "", FALSE, FALSE, 0.0, FALSE, 1.0, 0 } +} ; + + +void Material::install ( int index ) +{ + *gst = new ssgSimpleState ; + + (*gst) -> ref () ; + (*gst) -> setExternalPropertyIndex ( index ) ; + + if ( texture_map [ 0 ] != '\0' ) + { + (*gst) -> setTexture ( texture_map, !clamp_tex, !clamp_tex ) ; + (*gst) -> enable ( GL_TEXTURE_2D ) ; + } + else + (*gst) -> disable ( GL_TEXTURE_2D ) ; + + if ( lighting ) + (*gst) -> enable ( GL_LIGHTING ) ; + else + (*gst) -> disable ( GL_LIGHTING ) ; + + (*gst) -> setShadeModel ( GL_SMOOTH ) ; + (*gst) -> disable ( GL_COLOR_MATERIAL ) ; + (*gst) -> enable ( GL_CULL_FACE ) ; + (*gst) -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + (*gst) -> setMaterial ( GL_AMBIENT, 0.3f, 0.3f, 0.3f, 1 ) ; + (*gst) -> setMaterial ( GL_DIFFUSE, 1, 1, 1, 1 ) ; + (*gst) -> setMaterial ( GL_EMISSION, 0, 0, 0, 1 ) ; + (*gst) -> setMaterial ( GL_SPECULAR, 0, 0, 0, 1 ) ; + (*gst) -> setShininess ( 0 ) ; + + if ( transparency ) + { + (*gst) -> setTranslucent () ; + (*gst) -> enable ( GL_ALPHA_TEST ) ; + (*gst) -> setAlphaClamp ( alpha_ref ) ; + (*gst) -> enable ( GL_BLEND ) ; + } + else + { + (*gst) -> setOpaque () ; + (*gst) -> disable ( GL_BLEND ) ; + } +} + + + +static ssgState *getAppState ( char *fname ) +{ + if ( fname == NULL || fname[0] == '\0' ) + return gs_setup [ 0 ] . getState() ; + + char *fn ; + + /* Remove all leading path information. */ + + for ( fn = & fname [ strlen ( fname ) - 1 ] ; fn != fname && + *fn != '/' ; fn-- ) + /* Search back for a '/' */ ; + + if ( *fn == '/' ) + fn++ ; + + char basename [ 1024 ] ; + + strcpy ( basename, fn ) ; + + /* Remove last trailing extension. */ + + for ( fn = & basename [ strlen ( basename ) - 1 ] ; fn != basename && + *fn != '.' ; fn-- ) + /* Search back for a '.' */ ; + + if ( *fn == '.' ) + *fn = '\0' ; + + for ( int i = 0 ; ! gs_setup [ i ] . isNull () ; i++ ) + { + char *fname2 = gs_setup [ i ] . getTexFname () ; + + if ( fname2 != NULL && fname2[0] != '\0' ) + { + char *fn2 ; + + /* Remove all leading path information. */ + + for ( fn2 = & fname2 [ strlen ( fname2 ) -1 ] ; fn2 != fname2 && + *fn2 != '/' ; fn2-- ) + /* Search back for a '/' */ ; + + if ( *fn2 == '/' ) + fn2++ ; + + char basename2 [ 1024 ] ; + + strcpy ( basename2, fn2 ) ; + + /* Remove last trailing extension. */ + + for ( fn2 = & basename2 [ strlen ( basename2 ) - 1 ] ; fn2 != basename2 && + *fn2 != '.' ; fn2-- ) + /* Search back for a '.' */ ; + + if ( *fn2 == '.' ) + *fn2 = '\0' ; + + if ( strcmp ( basename, basename2 ) == 0 ) + return gs_setup [ i ] . getState() ; + } + } + + return NULL ; +} + + + +void initMaterials () +{ + for ( int i = 0 ; ! gs_setup [ i ] . isNull () ; i++ ) + gs_setup [ i ] . install ( i ) ; + + ssgSetAppStateCallback ( getAppState ) ; +} + + +/*Material *getMaterial ( ssgState *s ) +{ + return & ( gs_setup [ s -> getExternalPropertyIndex () ] ) ; +} + + +Material *getMaterial ( ssgLeaf *l ) +{ + return getMaterial ( l -> getState () ) ; +}*/ + diff --git a/demos/ttt3d/src/material.h b/demos/ttt3d/src/material.h new file mode 100644 index 0000000..456fb31 --- /dev/null +++ b/demos/ttt3d/src/material.h @@ -0,0 +1,51 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: material.h 1427 2002-08-18 00:09:46Z ude $ +*/ + + +struct Material +{ +public: + ssgSimpleState **gst ; + + char *texture_map ; + int clamp_tex ; + int transparency ; + float alpha_ref ; + int lighting ; + float friction ; + unsigned int flags ; + + int isNull () { return gst == NULL ; } ; + void install ( int index ) ; + + ssgState *getState () { return *gst ; } + char *getTexFname () { return texture_map ; } +} ; + + +void initMaterials () ; +/*Material *getMaterial ( ssgState *s ) ; +Material *getMaterial ( ssgLeaf *l ) ;*/ + +extern ssgSimpleState *default_gst, *O_gst, *X_gst, *ground_gst, *ctrls_gst ; + diff --git a/demos/ttt3d/src/p3d.h b/demos/ttt3d/src/p3d.h new file mode 100644 index 0000000..dd9bbf0 --- /dev/null +++ b/demos/ttt3d/src/p3d.h @@ -0,0 +1,95 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: p3d.h 1687 2002-09-15 17:54:09Z ude $ +*/ + + +#include +#include +#include +#include +#ifdef WIN32 +#include +#else +#include +#endif +#include + +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#include +#include + +#ifndef M_PI +# define M_PI 3.14159265 +#endif + +#include "game.h" + +class GFX ; +class GUI ; +class SoundSystem ; +class Puzzle ; +class Cell ; +class Level ; + +extern GFX *gfx ; +extern GUI *gui ; +extern SoundSystem *sound ; +extern Puzzle *puzzle ; +extern Level level ; + +extern int game_state ; + +extern ssgRoot *scene ; +//extern const char *ttt3d_datadir ; + +void startLevel () ; +void makeMove () ; +void ttt3dMainLoop () ; +void initMaterials () ; + +#include "level.h" +#include "gfx.h" +#include "gui.h" +#include "material.h" +#include "status.h" +#include "sound.h" +#include "cell.h" +#include "puzzle.h" + +void spinUp () ; +void spinDown () ; +void spinLeft () ; +void spinRight () ; +void zoomIn () ; +void zoomOut () ; + diff --git a/demos/ttt3d/src/puzzle.cxx b/demos/ttt3d/src/puzzle.cxx new file mode 100644 index 0000000..0ea1b41 --- /dev/null +++ b/demos/ttt3d/src/puzzle.cxx @@ -0,0 +1,102 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puzzle.cxx 1427 2002-08-18 00:09:46Z ude $ +*/ + + +#include "p3d.h" + +static int size[3] ; + + +Puzzle::Puzzle () +{ + size[0] = 4 ; + size[1] = 4 ; + size[2] = 4 ; + + sgSetCoord ( &pos, 0, 0, 0, 0, 0, 0 ) ; + + ground = makeGround () ; + selector = makeBlueWireCube () ; + + spin = new ssgTransform ( &pos ) ; + spin -> addKid ( ground ) ; + spin -> addKid ( selector ) ; + + sel [ 0 ] = 0 ; + sel [ 1 ] = 0 ; + sel [ 2 ] = 0 ; + + for ( int x = 0 ; x < size [ 0 ] ; x++ ) + for ( int y = 0 ; y < size [ 1 ] ; y++ ) + for ( int z = 0 ; z < size [ 2 ] ; z++ ) + { + cell[x][y][z] = new Cell ( x, y, z, size[0] ) ; + spin -> addKid ( cell[x][y][z]->getSSG() ) ; + } + + reset () ; +} + + +void Puzzle::reset () +{ + cursor ( 0, 0, 0 ) ; + sgSetCoord ( &pos, 0, 0, 0, 0, 0, 0 ) ; + + for ( int x = 0 ; x < size [ 0 ] ; x++ ) + for ( int y = 0 ; y < size [ 1 ] ; y++ ) + for ( int z = 0 ; z < size [ 2 ] ; z++ ) + cell[x][y][z]->set(WIRE_CELL) ; + + setGameState ( STILL_PLAYING ) ; + game_init () ; +} + + +void Puzzle::update () +{ + static int flasher = 0 ; + sgCoord spos ; + sgSetVec3 ( spos.hpr, 0, 0, 0 ) ; + + flasher++ ; + if ( flasher > 5 ) + sgSetVec3 ( spos.xyz, (float)sel[0] - (float)size[0]/2.0f + 0.51f, + (float)sel[1] - (float)size[1]/2.0f + 0.51f, + (float)sel[2] - (float)size[2]/2.0f + 0.51f ) ; + else + sgSetVec3 ( spos.xyz, 1000000, 1000000, 1000000 ) ; + + if ( flasher > 60 ) + flasher = 0 ; + + selector -> setTransform ( & spos ) ; +} + + +Puzzle::~Puzzle () +{ + delete spin ; +} + + diff --git a/demos/ttt3d/src/puzzle.h b/demos/ttt3d/src/puzzle.h new file mode 100644 index 0000000..606e1e5 --- /dev/null +++ b/demos/ttt3d/src/puzzle.h @@ -0,0 +1,90 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puzzle.h 1427 2002-08-18 00:09:46Z ude $ +*/ + + +#define MAX_GRID 4 + + +class Puzzle +{ + sgCoord pos ; + + int sel [ 3 ] ; + + ssgTransform *spin ; + ssgTransform *selector ; + ssgTransform *ground ; + + Cell *cell [ MAX_GRID ][ MAX_GRID ][ MAX_GRID ] ; + + int game_state ; + +public: + Puzzle () ; + ~Puzzle () ; + + void reset () ; + void update () ; + + int getGameState () { return game_state ; } + void setGameState ( int gs ) { game_state = gs ; } + + int gameOver () { return game_state != STILL_PLAYING ; } + + void cursor ( int x, int y, int z ) + { + sel[0] = x & 3 ; + sel[1] = y & 3 ; + sel[2] = z & 3 ; + } + + int getCx () { return sel[0] ; } + int getCy () { return sel[1] ; } + int getCz () { return sel[2] ; } + + void step_up () { pos . xyz [ 1 ] += 0.5f ; spin->setTransform(&pos); } + void step_down () { pos . xyz [ 1 ] -= 0.5f ; spin->setTransform(&pos); } + void spin_up () { pos . hpr [ 2 ] += 5.0f ; spin->setTransform(&pos); } + void spin_down () { pos . hpr [ 2 ] -= 5.0f ; spin->setTransform(&pos); } + void spin_left () { pos . hpr [ 0 ] -= 5.0f ; spin->setTransform(&pos); } + void spin_right () { pos . hpr [ 0 ] += 5.0f ; spin->setTransform(&pos); } + + void cursor_up () { cursor(sel[0],sel[1],sel[2]+1) ; } + void cursor_down () { cursor(sel[0],sel[1],sel[2]-1) ; } + void cursor_in () { cursor(sel[0],sel[1]+1,sel[2]) ; } + void cursor_out () { cursor(sel[0],sel[1]-1,sel[2]) ; } + void cursor_left () { cursor(sel[0]-1,sel[1],sel[2]) ; } + void cursor_right () { cursor(sel[0]+1,sel[1],sel[2]) ; } + + void put_empty() { cell[sel[0]][sel[1]][sel[2]]->set(WIRE_CELL) ; } + void put_X () { cell[sel[0]][sel[1]][sel[2]]->set( X_CELL) ; } + void put_O () { cell[sel[0]][sel[1]][sel[2]]->set( O_CELL) ; } + + void put_empty ( int x, int y, int z ) { cell[x][y][z] -> set (WIRE_CELL);} + void put_X ( int x, int y, int z ) { cell[x][y][z] -> set ( X_CELL) ; } + void put_O ( int x, int y, int z ) { cell[x][y][z] -> set ( O_CELL) ; } + + ssgTransform *getSSG () { return spin ; } +} ; + + diff --git a/demos/ttt3d/src/sound.cxx b/demos/ttt3d/src/sound.cxx new file mode 100644 index 0000000..a8ad302 --- /dev/null +++ b/demos/ttt3d/src/sound.cxx @@ -0,0 +1,122 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: sound.cxx 1427 2002-08-18 00:09:46Z ude $ +*/ + + +#include "p3d.h" + +struct Sound +{ + const char *fname ; + slSample *s ; +} ; + + +static Sound sfx [] = +{ + { "wavs/ahooga.wav" , NULL }, + { "wavs/clap.wav" , NULL }, + { "wavs/frog.wav" , NULL }, + { "wavs/glasbk.wav" , NULL }, + { "wavs/pop.wav" , NULL }, + { "wavs/ugh.wav" , NULL }, + { "wavs/who_else.wav" , NULL }, + { NULL, NULL } +} ; + +static int music_off = FALSE ; +static int sfx_off = FALSE ; + +void SoundSystem::disable_music () +{ + sched -> stopMusic () ; + sched -> update () ; /* Ugh! Nasty Kludge! */ + sched -> update () ; /* Ugh! Nasty Kludge! */ + + music_off = TRUE ; +} + + +void SoundSystem::change_track ( const char *fname ) +{ + if ( fname == NULL ) + fname = "" ; + + if ( strcmp ( fname, current_track ) != 0 ) + { + strcpy ( current_track, fname ) ; + + if ( ! music_off ) + enable_music () ; + } +} + +void SoundSystem::enable_music () +{ + sched -> stopMusic () ; + + if ( current_track [ 0 ] != '\0' ) + sched -> loopMusic ( current_track ) ; + + music_off = FALSE ; +} + + +void SoundSystem::disable_sfx () { sfx_off = TRUE ; } +void SoundSystem:: enable_sfx () { sfx_off = FALSE ; } + + + +void SoundSystem::playSfx ( int sfx_num ) +{ + if ( ! sfx_off ) + sched -> playSample ( sfx[sfx_num].s, 1, SL_SAMPLE_MUTE, 2, NULL ) ; +} + + +SoundSystem::SoundSystem () +{ + sched = new slScheduler ; + + setSafetyMargin () ; + + for ( Sound *currsfx = &(sfx[0]) ; currsfx -> fname != NULL ; currsfx++ ) + currsfx -> s = new slSample ( currsfx -> fname, sched ) ; + + enable_sfx () ; + change_track ( "" ) ; + enable_music () ; +} + + +void SoundSystem::update () +{ +/* + Comment this next line out if the + sound causes big glitches on your + IRIX machine! +*/ + + sched -> update () ; +} + + diff --git a/demos/ttt3d/src/sound.h b/demos/ttt3d/src/sound.h new file mode 100644 index 0000000..6bfb1e1 --- /dev/null +++ b/demos/ttt3d/src/sound.h @@ -0,0 +1,56 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: sound.h 1427 2002-08-18 00:09:46Z ude $ +*/ + + +#define SOUND_AHOOGA 0 +#define SOUND_CLAP 1 +#define SOUND_FROG 2 +#define SOUND_GLASBK 3 +#define SOUND_POP 4 +#define SOUND_UGH 5 +#define SOUND_WHO_ELSE 6 + +class SoundSystem +{ + char current_track [ 256 ] ; + slScheduler *sched ; + +public: + SoundSystem () ; + + void update () ; + void playSfx ( int sound ) ; + + void setSafetyMargin ( float t = 0.25 ) + { + sched -> setSafetyMargin ( t ) ; + } + + void change_track ( const char *fname ) ; + void disable_music () ; + void enable_music () ; + + void disable_sfx () ; + void enable_sfx () ; +} ; + diff --git a/demos/ttt3d/src/status.cxx b/demos/ttt3d/src/status.cxx new file mode 100644 index 0000000..800e077 --- /dev/null +++ b/demos/ttt3d/src/status.cxx @@ -0,0 +1,358 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: status.cxx 2100 2006-11-03 22:31:54Z fayjf $ +*/ + + +#include "p3d.h" +#include + +#define MAX_STRING 30 +#define MAX_STRING_LENGTH 256 + +static int displayed_score = 0 ; + +static fntRenderer *text = NULL ; + +char debug_strings [ MAX_STRING ][ MAX_STRING_LENGTH ] ; +/*int next_string = 0 ; +int stats_enabled = FALSE ;*/ + +static int about_timer = 99999 ; +static int versions_timer = 99999 ; +static int credits_timer = 99999 ; +static int intro_timer = 0 ; +static int help_timer = 99999 ; + +void hide_status () { versions_timer = credits_timer = + intro_timer = help_timer = about_timer = 99999 ; } +void about () { about_timer = 0 ; } +void credits () { credits_timer = 0 ; } +void versions () { versions_timer = 0 ; } +void help () { help_timer = 0 ; } + +static void drawText ( const char *str, int sz, int x, int y ) +{ + text -> setFont ( font ) ; + text -> setPointSize ( (float)sz ) ; + + text -> begin () ; + text -> start2f ( (float)x, (float)y ) ; + text -> puts ( str ) ; + text -> end () ; +} + + +static void drawInverseDropShadowText ( const char *str, int sz, int x, int y ) +{ + glColor4f ( 1.0f, 1.0f, 1.0f, 1.0f ) ; + drawText ( str, sz, x, y ) ; + glColor4f ( 0.0f, 0.0f, 0.0f, 1.0f ) ; + drawText ( str, sz, x+1, y+1 ) ; +} + + +static void drawDropShadowText ( const char *str, int sz, int x, int y ) +{ + glColor4f ( 0.0f, 0.0f, 0.0f, 1.0f ) ; + + drawText ( str, sz, x, y ) ; + + glColor4f ( 1.0f, 1.0f, 1.0f, 1.0f ) ; + + drawText ( str, sz, x+1, y+1 ) ; +} + + +static void drawHelpText () +{ + drawDropShadowText ( "Press SPACE to toggle the menu.", 18, 70, 400 ) ; + drawDropShadowText ( "Press ESCAPE to exit the game.", 18, 70, 370 ) ; + drawDropShadowText ( "Use arrow keys and PgUp,PgDown,Home,End,Ins", 18, 70, 340 ) ; + drawDropShadowText ( " or Del to move the grid around.", 18, 70, 310 ) ; + drawDropShadowText ( "Move the current pipe with A,S,Z,W,E,X", 18, 70, 280 ) ; +} + + +static void drawTitleText () +{ + drawDropShadowText ( "TTT3D", 20, 70, 400 ) ; + drawDropShadowText ( "By Steve Baker", 12, 170, 385 ) ; +} + + +static void drawIntroText () +{ + drawTitleText () ; + + if ( intro_timer & 8 ) + drawDropShadowText ( "Press SPACE bar for menu.", + 15, 10, 430 ) ; +} + + +static const char *aboutText [] = +{ + " Yada, yada, yada.", + NULL +} ; + + +static void drawVersionsText () +{ + char str [ 256 ] ; + +#ifdef VERSION + sprintf ( str, "TTT3D: Version: %s", VERSION ) ; +#else + sprintf ( str, "TTT3D: Unknown Version." ) ; +#endif + drawDropShadowText ( str, 15, 20, 250 ) ; + + sprintf ( str, "PLIB Version: %s", ssgGetVersion() ) ; + drawDropShadowText ( str, 15, 20, 225 ) ; + + sprintf ( str, "OpenGL Version: %s", glGetString ( GL_VERSION ) ) ; + drawDropShadowText ( str, 15, 20, 200 ) ; + + sprintf ( str, "OpenGL Vendor: %s", glGetString ( GL_VENDOR ) ) ; + drawDropShadowText ( str, 15, 20, 175 ) ; + + sprintf ( str, "OpenGL Renderer: %s", glGetString ( GL_RENDERER ) ) ; + + if ( strlen ( str ) > 50 ) + { + int l = strlen ( str ) ; + int ll = 0 ; + + for ( int i = 0 ; i < l ; i++, ll++ ) + { + if ( ll > 40 && str[i] == ' ' ) + { + str[i] = '\n' ; + ll = 0 ; + } + } + } + + drawDropShadowText ( str, 15, 20, 150 ) ; + + if ( versions_timer & 8 ) + drawDropShadowText ( "Press SPACE to continue", + 15, 10, 430 ) ; +} + + +static void drawAboutText () +{ + drawTitleText () ; + + for ( int i = 0 ; aboutText [ i ] != NULL ; i++ ) + drawDropShadowText ( aboutText [ i ], + 10, 40, 230 - 10 * i ) ; + + if ( about_timer & 8 ) + drawDropShadowText ( "Press SPACE to continue", + 15, 10, 430 ) ; +} + + +static const char *creditsText [] = +{ + " Steve Baker - Coding, design, bug insertion.", + NULL +} ; + + + +static void drawCreditsText () +{ + drawTitleText () ; + + drawDropShadowText ( "Credits:", + 20, 70, 250 ) ; + + for ( int i = 0 ; creditsText [ i ] != NULL ; i++ ) + drawDropShadowText ( creditsText [ i ], + 12, 100, 230 - 12 * i ) ; + + if ( credits_timer & 8 ) + drawDropShadowText ( "Press SPACE to continue", + 15, 10, 430 ) ; +} + + + +static void drawScore () +{ + if ( displayed_score > 0 ) + { + char str [ 20 ] ; + sprintf ( str, "%9d", displayed_score ) ; + drawDropShadowText ( str, 18, 500, 410 ) ; + } +} + + + +static void drawInGameScore () +{ + char str [ 50 ] ; + + sprintf ( str, "TicTacToe 3D" ) ; + drawInverseDropShadowText ( str, 18, 360, 460 ) ; + + sprintf ( str, "A,Z : Move UP or DOWN" ) ; + drawDropShadowText ( str, 18, 360, 420 ) ; + sprintf ( str, "S,D,X,C : Move Sideways" ) ; + drawDropShadowText ( str, 18, 360, 400 ) ; + sprintf ( str, "Enter : Play at cursor" ) ; + drawDropShadowText ( str, 18, 360, 380 ) ; + sprintf ( str, "Arrow Keys : Spin Board" ) ; + drawDropShadowText ( str, 18, 360, 360 ) ; + + sprintf ( str, "Four in a row to win" ) ; + drawInverseDropShadowText ( str, 18, 60, 420 ) ; +} + + + +static void drawGameOverText ( int score ) +{ + static int timer = 0 ; + + displayed_score = score ; + + drawTitleText () ; + drawScore () ; + + glColor4f ( (float)sin ( (float)timer/5.1f ) / 2.0f + 0.5f, + (float)sin ( (float)timer/6.3f ) / 2.0f + 0.5f, + (float)sin ( (float)timer/7.2f ) / 2.0f + 0.5f, 0.5 ) ; + + + switch ( puzzle -> getGameState () ) + { + case STILL_PLAYING : break ; + + case HUMAN_WIN : drawText ( "YOU" , 50, 220, 230 ) ; + drawText ( "WON!", 50, 150, 180 ) ; + break ; + + case COMPUTER_WIN : drawText ( "YOU" , 50, 220, 230 ) ; + drawText ( "LOSE!", 50, 150, 180 ) ; + break ; + + case DRAWN_GAME : drawText ( "ITS A", 50, 220, 230 ) ; + drawText ( "DRAW!", 50, 150, 180 ) ; + break ; + } + + if ( timer++ & 8 ) + { + drawDropShadowText ( "Press R to reset and play again", 15, 10, 30 ) ; + } +} + + +static void drawGameIntroText () +{ + static int timer = 0 ; + + if ( timer++ & 8 ) + drawDropShadowText ( "Press S to start", 15, 10, 430 ) ; + + if ( help_timer++ < 400 ) + drawHelpText () ; + else + if ( intro_timer++ < 400 ) + drawIntroText () ; + else + if ( credits_timer++ < 1600 ) + drawCreditsText () ; + else + if ( about_timer++ < 1600 ) + drawAboutText () ; + else + if ( versions_timer++ < 1600 ) + drawVersionsText () ; +} + + +static void drawGameRunningText ( int score ) +{ + displayed_score = score ; + drawInGameScore () ; + + glColor4f ( 0.6f, 0.0f, 0.6f, 1.0f ) ; + + if ( help_timer++ < 400 ) + drawHelpText () ; + else + if ( credits_timer++ < 1600 ) + drawCreditsText () ; + else + if ( about_timer++ < 1600 ) + drawAboutText () ; + else + if ( versions_timer++ < 1600 ) + drawVersionsText () ; +} + + + +void drawStatusText ( int score ) +{ + if ( text == NULL ) + text = new fntRenderer () ; + + glMatrixMode ( GL_MODELVIEW ) ; + glPushMatrix () ; + glLoadIdentity () ; + + glMatrixMode ( GL_PROJECTION ) ; + glPushMatrix () ; + glLoadIdentity () ; + + glPushAttrib ( GL_ENABLE_BIT | GL_LIGHTING_BIT ) ; + glDisable ( GL_DEPTH_TEST ) ; + glDisable ( GL_LIGHTING ) ; + glDisable ( GL_FOG ) ; + glDisable ( GL_CULL_FACE ) ; + glDisable ( GL_ALPHA_TEST ) ; + glEnable ( GL_BLEND ) ; + + glOrtho ( 0, 640, 0, 480, 0, 100 ) ; + + switch ( game_state ) + { + case GAME_INTRO : drawGameIntroText () ; break ; + case GAME_DEBRIEF : drawGameOverText ( score ) ; break ; + case GAME_RUNNING : drawGameRunningText ( score ) ; break ; + } + + glPopAttrib () ; + glPopMatrix () ; + glMatrixMode ( GL_MODELVIEW ) ; + glPopMatrix () ; +} + + diff --git a/demos/ttt3d/src/status.h b/demos/ttt3d/src/status.h new file mode 100644 index 0000000..932bbce --- /dev/null +++ b/demos/ttt3d/src/status.h @@ -0,0 +1,40 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: status.h 1427 2002-08-18 00:09:46Z ude $ +*/ + + +void drawStatusText ( int score ) ; + +/*void stPrintf ( char *fmt, ... ) ; +void stToggle () ;*/ + +//void memorial () ; +void about () ; +void credits () ; +void versions () ; +void help () ; +void hide_status () ; + +/*double read_time_of_day () ; +void start_stopwatch () ; + +extern int time_out ;*/ diff --git a/demos/ttt3d/src/ttt3d.cxx b/demos/ttt3d/src/ttt3d.cxx new file mode 100644 index 0000000..0f4539f --- /dev/null +++ b/demos/ttt3d/src/ttt3d.cxx @@ -0,0 +1,286 @@ +/* + This file is part of TTT3D - Steve's 3D TicTacToe Player. + Copyright (C) 2001 Steve Baker + + TTT3D 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. + + TTT3D 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 TTT3D; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ttt3d.cxx 1480 2002-08-31 08:05:49Z wolfram_kuss $ +*/ + + +#include "p3d.h" +#include + +#if defined(WIN32) && !defined(__CYGWIN__) +# include +# include + +# define access _access +# define chdir _chdir +# define F_OK 04 +#endif + +static const char *ttt3d_datadir = NULL ; +GFX *gfx = NULL ; +GUI *gui = NULL ; +SoundSystem *sound = NULL ; +ssgRoot *scene = NULL ; +static ssgTransform *spin = NULL ; +Puzzle *puzzle = NULL ; +static float spin_rot = 0.0f ; +static float spin_alt = 0.0f ; +static float spin_pit = 0.0f ; +static float zoom = 60.0f ; +int game_state = GAME_START_OF_DAY ; + +Level level ; + +static void banner () +{ + printf ( "\n\n" ) ; + printf ( " TTT3D.\n" ) ; + printf ( "\n" ) ; + printf ( " / / \n" ) ; + printf ( " ____/____/____\n" ) ; + printf ( " / / \n" ) ; + printf ( " ____/____/____ \n" ) ; + printf ( " / / \n" ) ; + printf ( " / / \n" ) ; + printf ( "\n" ) ; + printf ( " by Steve Baker\n" ) ; + printf ( " \n" ) ; + printf ( "\n\n" ) ; +} + +static void cmdline_help () +{ + banner () ; + + printf ( "Usage:\n\n" ) ; + printf ( " ttt3d [OPTIONS]...\n\n" ) ; + printf ( "Options:\n" ) ; + printf ( " -h, --help Display this help message.\n" ) ; + printf ( " -D, --datadir DIR Load the game data from DIR defaults\n" ) ; + printf ( " to /usr/local/share/games/ttt3d\n" ) ; + printf ( "\n" ) ; +} + + +int main ( int argc, char **argv ) +{ + for ( int i = 1 ; i < argc ; i++ ) + { + if ( argv[i][0] == '-' ) + switch ( argv[i][1] ) + { + case '-' : + { + if ( strcmp ( & argv[i][2], "help" ) == 0 ) + { + cmdline_help () ; + exit ( 0 ) ; + } + } + break ; + + case 'h' : case 'H' : cmdline_help () ; exit ( 0 ) ; + default : break ; + } + } + + /* Set tux_aqfh_datadir to the correct directory */ + + if ( ttt3d_datadir == NULL ) + { + if ( getenv ( "TTT3D_DATADIR" ) != NULL ) + ttt3d_datadir = getenv ( "TTT3D_DATADIR" ) ; + else + if ( access ( "data/levels.dat", F_OK ) == 0 ) + ttt3d_datadir = "." ; + else + if ( access ( "../data/levels.dat", F_OK ) == 0 ) + ttt3d_datadir = ".." ; + else +#ifdef TTT3D_DATADIR + ttt3d_datadir = TTT3D_DATADIR ; +#else + ttt3d_datadir = "/usr/local/share/games/ttt3d" ; +#endif + } + + fprintf ( stderr, "Data files will be fetched from: '%s'\n", + ttt3d_datadir ) ; + + if ( chdir ( ttt3d_datadir ) == -1 ) + { + fprintf ( stderr, "Couldn't chdir() to '%s'.\n", ttt3d_datadir ) ; + exit ( 1 ) ; + } + + banner () ; + + gfx = new GFX ; + + sound = new SoundSystem ; + sound -> change_track ( "mods/mfarmer.mod" ) ; + + gui = new GUI ; + + scene = new ssgRoot ; + spin = new ssgTransform ; + scene -> addKid ( spin ) ; + + puzzle = new Puzzle () ; + + spin -> addKid ( puzzle -> getSSG () ) ; + spinLeft () ; + + signal ( 11, SIG_DFL ) ; + glutMainLoop () ; + return 0 ; +} + + + +static void spinPuzzle () +{ + sgMat4 rot, pit, final ; + + sgMakeRotMat4 ( rot, spin_rot, 0, 0 ) ; + sgMakeRotMat4 ( pit, 0, spin_pit, 0 ) ; + sgMultMat4 ( final, pit, rot ) ; + sgSetVec3 ( final[3], 0, 8, 0 /* spin_alt */ ) ; + + spin -> setTransform ( final ) ; +} + +void spinUp () +{ + spin_alt -= 0.4f ; + spin_pit += 3.5f ; + spinPuzzle () ; +} + +void spinDown () +{ + spin_alt += 0.4f ; + spin_pit -= 3.5f ; + spinPuzzle () ; +} + +void spinRight () +{ + spin_rot += 4.4f ; + spinPuzzle () ; +} + +void spinLeft () +{ + spin_rot -= 4.4f ; + spinPuzzle () ; +} + +void zoomIn () +{ + zoom *= 1.1f ; + + if ( zoom > 160 ) zoom = 160 ; + + ssgSetFOV ( zoom, zoom * 3.0f/4.0f ) ; +} + +void zoomOut () +{ + if ( zoom < 6 ) zoom = 6 ; + + zoom /= 1.1f ; + + ssgSetFOV ( zoom, zoom * 3.0f/4.0f ) ; +} + + +void startLevel () +{ + game_state = GAME_RUNNING ; + puzzle -> reset () ; + puzzle -> update () ; + sound -> playSfx ( SOUND_CLAP ) ; +} + + +void makeMove () +{ + if ( get_board_entry ( puzzle->getCx(), + puzzle->getCy(), + puzzle->getCz() ) != ' ' ) + sound->playSfx ( SOUND_FROG ) ; + else + { + int res = game_update ( puzzle->getCx(), + puzzle->getCy(), + puzzle->getCz() ) ; + + for ( int x = 0 ; x < 4 ; x++ ) + for ( int y = 0 ; y < 4 ; y++ ) + for ( int z = 0 ; z < 4 ; z++ ) + switch ( get_board_entry ( x, y, z ) ) + { + case ' ' : puzzle->put_empty ( x, y, z ) ; break ; + case 'X' : puzzle->put_X ( x, y, z ) ; break ; + case 'O' : puzzle->put_O ( x, y, z ) ; break ; + default : puzzle->put_empty ( x, y, z ) ; break ; + } + + puzzle->setGameState ( res ) ; + + sound->playSfx ( SOUND_POP ) ; + + if ( res == HUMAN_WIN ) + sound->playSfx ( SOUND_CLAP ) ; + else + if ( res == COMPUTER_WIN ) + sound->playSfx ( SOUND_GLASBK ) ; + else + if ( res == DRAWN_GAME ) + sound->playSfx ( SOUND_AHOOGA ) ; + } +} + + +void ttt3dMainLoop () +{ + switch ( game_state ) + { + case GAME_START_OF_DAY : startLevel () ; break ; + case GAME_INTRO : startLevel () ; break ; + case GAME_DEBRIEF : break ; + + case GAME_RUNNING : + if ( puzzle->gameOver () ) + game_state = GAME_DEBRIEF ; + break ; + } + + glLineWidth ( 2 ) ; + puzzle -> update () ; + gfx -> update () ; + gui -> update () ; + sound -> update () ; + gfx -> done () ; /* Swap buffers! */ +} + + diff --git a/demos/ttt3d/wavs/Makefile.am b/demos/ttt3d/wavs/Makefile.am new file mode 100644 index 0000000..10c6e8e --- /dev/null +++ b/demos/ttt3d/wavs/Makefile.am @@ -0,0 +1,7 @@ +# wavs/ + +pkgdatadir = $(datadir)/games/@PACKAGE@/wavs + +pkgdata_DATA = $(wildcard *.wav) + +EXTRA_DIST = $(pkgdata_DATA) \ No newline at end of file diff --git a/demos/ttt3d/wavs/ahooga.wav b/demos/ttt3d/wavs/ahooga.wav new file mode 100644 index 0000000..fb9fe26 Binary files /dev/null and b/demos/ttt3d/wavs/ahooga.wav differ diff --git a/demos/ttt3d/wavs/clap.wav b/demos/ttt3d/wavs/clap.wav new file mode 100644 index 0000000..5607603 Binary files /dev/null and b/demos/ttt3d/wavs/clap.wav differ diff --git a/demos/ttt3d/wavs/frog.wav b/demos/ttt3d/wavs/frog.wav new file mode 100644 index 0000000..c9e6fdd Binary files /dev/null and b/demos/ttt3d/wavs/frog.wav differ diff --git a/demos/ttt3d/wavs/glasbk.wav b/demos/ttt3d/wavs/glasbk.wav new file mode 100644 index 0000000..857040f Binary files /dev/null and b/demos/ttt3d/wavs/glasbk.wav differ diff --git a/demos/ttt3d/wavs/pop.wav b/demos/ttt3d/wavs/pop.wav new file mode 100644 index 0000000..524b8e2 Binary files /dev/null and b/demos/ttt3d/wavs/pop.wav differ diff --git a/demos/ttt3d/wavs/ugh.wav b/demos/ttt3d/wavs/ugh.wav new file mode 100644 index 0000000..630c04f Binary files /dev/null and b/demos/ttt3d/wavs/ugh.wav differ diff --git a/demos/ttt3d/wavs/who_else.wav b/demos/ttt3d/wavs/who_else.wav new file mode 100644 index 0000000..dc2706a Binary files /dev/null and b/demos/ttt3d/wavs/who_else.wav differ diff --git a/demos/widgy/README b/demos/widgy/README new file mode 100644 index 0000000..87fe594 --- /dev/null +++ b/demos/widgy/README @@ -0,0 +1,2 @@ +This demo package has been superceded by demos/p-guide + diff --git a/doc/FDS_logo.png b/doc/FDS_logo.png new file mode 100644 index 0000000..5f2713e Binary files /dev/null and b/doc/FDS_logo.png differ diff --git a/doc/FNT.png b/doc/FNT.png new file mode 100644 index 0000000..ab49b9e Binary files /dev/null and b/doc/FNT.png differ diff --git a/doc/JS.png b/doc/JS.png new file mode 100644 index 0000000..309ae5c Binary files /dev/null and b/doc/JS.png differ diff --git a/doc/MinigolfManiacs.png b/doc/MinigolfManiacs.png new file mode 100644 index 0000000..39d0092 Binary files /dev/null and b/doc/MinigolfManiacs.png differ diff --git a/doc/NET.png b/doc/NET.png new file mode 100644 index 0000000..6eea299 Binary files /dev/null and b/doc/NET.png differ diff --git a/doc/PSL.png b/doc/PSL.png new file mode 100644 index 0000000..f19eb6f Binary files /dev/null and b/doc/PSL.png differ diff --git a/doc/PUI.png b/doc/PUI.png new file mode 100644 index 0000000..1f1d4eb Binary files /dev/null and b/doc/PUI.png differ diff --git a/doc/PW.png b/doc/PW.png new file mode 100644 index 0000000..1fa1994 Binary files /dev/null and b/doc/PW.png differ diff --git a/doc/SG.png b/doc/SG.png new file mode 100644 index 0000000..fe7b4e4 Binary files /dev/null and b/doc/SG.png differ diff --git a/doc/SL.png b/doc/SL.png new file mode 100644 index 0000000..aa0bdf5 Binary files /dev/null and b/doc/SL.png differ diff --git a/doc/SSG.png b/doc/SSG.png new file mode 100644 index 0000000..e312790 Binary files /dev/null and b/doc/SSG.png differ diff --git a/doc/UL.png b/doc/UL.png new file mode 100644 index 0000000..3970533 Binary files /dev/null and b/doc/UL.png differ diff --git a/doc/auxlibs/index.html b/doc/auxlibs/index.html new file mode 100644 index 0000000..a922ff1 --- /dev/null +++ b/doc/auxlibs/index.html @@ -0,0 +1,55 @@ + + + + + Auxiliary Libraries for PLIB. + + + + + + + + + + +
+

Auxiliary Libraries for PLIB.

+
+ by Steve Baker +
+

Introduction

+PLIB/AUX is a suite of auxiliary libraries that build +higher level classes on top of the basic PLIB libraries. +

+These will be installed and named with the same +conventions as the base PLIB libraries, eg: +

+
+   /usr/include/plib/auxXXX.h
+   /usr/lib/libplibauxXXX.a
+
+
+...where 'XXX' is the name of the aux library. +

+PLIB/AUX functions, classes and constants are all +named after the base PLIB library that they logically +belong with, hence enhancements to SSG will share the +'ssg' prefix but add a 'u': +

+
+  eg
+      class ssguParticleSystem ;
+      class puuFileBrowser ;
+
+
+
+
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+ + + diff --git a/doc/contacts.html b/doc/contacts.html new file mode 100644 index 0000000..d3287e6 --- /dev/null +++ b/doc/contacts.html @@ -0,0 +1,114 @@ + + + + + PLIB: Contacting Us. + + + + + + + + + +
+PLIB Logo +
+
+
+

+ STEVE'S + PORTABLE + GAME + LIBRARY. +

+
+
+
    +And Lo, the Lion and the Sheep shall lie down together - but the Sheep won't +get much Sleep. +
    +-- Woody Allen +
+
+ +Sourceforge Logo +
+
+ + + + + + +
+HOME
+WHAT'S INSIDE
+LICENSE
+CONTACTS
+REQUIREMENTS
+GALLERY
+DOWNLOAD & INSTALL
+EXAMPLES
+ +SG +SSG
+ +SSGAUX +FNT
+ +PUI +PSL + +UL +JS
+ +NET +SL
+ +PW +PUAUX
+ + +
+

Contacting Us - and Contributing to PLIB.

+There are three PLIB mailing lists: +In order to keep the spam off the lists, it's set up so you have +to subscribe in order to send mail. To do that, visit: + +

+Please do not send me personal mail in situations when one of +the public mailing lists would be an appropriate forum - I hate +it when people do that and I'll usually ignore you. +

+The mailing list is set up to prohibit large attachments. HTML mail +and other non-ASCII forms of posting are NOT welcome. +

+
+
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+ + diff --git a/doc/contacts.png b/doc/contacts.png new file mode 100644 index 0000000..ad3b7a5 Binary files /dev/null and b/doc/contacts.png differ diff --git a/doc/download.html b/doc/download.html new file mode 100644 index 0000000..9b1d1c8 --- /dev/null +++ b/doc/download.html @@ -0,0 +1,225 @@ + + + + + PLIB: Downloading and Installing PLIB. + + + + + + + + + +
+PLIB Logo +
+
+
+

+ STEVE'S + PORTABLE + GAME + LIBRARY. +

+
+
+
    +And Lo, the Lion and the Sheep shall lie down together - but the Sheep won't +get much Sleep. +
    +-- Woody Allen +
+
+ +Sourceforge Logo +
+
+ + + + + + +
+HOME
+WHAT'S INSIDE
+LICENSE
+CONTACTS
+REQUIREMENTS
+GALLERY
+DOWNLOAD & INSTALL
+EXAMPLES
+ +SG +SSG
+ +SSGAUX +FNT
+ +PUI +PSL + +UL +JS
+ +NET +SL
+ +PW +PUAUX
+ +
+

Downloading and Installing PLIB.

+

The Short Answer (for Linux and CygWin users):

+Make sure you have OpenGL installed.
+Download this: PLIB - Version 1.8.4 +
+Run this (as 'root'): +
+     tar xzf plib-1.8.4.tar.gz
+     cd plib-1.8.4
+     ./configure ; make install
+
+Tadaaaa! +

+

The Long Answer: Downloading PLIB.

+You can get PLIB in various versions here. We follow the common Linux +convention where the second digit in the version number is EVEN for +stable versions and ODD for unstable and/or experimental versions. +

+End users should generally download the latest stable version but +application developers may wish to periodically compile their code +against the odd-numbered version so as to keep abreast of developments +in PLIB. +

+

+Download this using your browser by right-clicking on the name. If you +have InternetExplorer, you'll probably fall victim to it's stupid bug +where it unzips the file automatically - but forgets to +rename it to lose the '.gz' off the end. Just rename it yourself +before you try to un-tar it and all will be well. +

+PLIB documentation, example programs, fonts, etc are separated from +PLIB itself to minimise your download time. +

+The online documentation attempts to always track the latest stable +version of PLIB. If you are using some other version, you may want to +download the documentation appropriate to that release which comes with +the plib_examples tarball. + + +

+Un-tar this into a separate directory from PLIB itself - or else +all the configuration and makefiles will clash. Many of the example programs +require the GLUT library (or 'freeglut') - some other use SDL and FLTK. +

+ +More extensive PLIB demonstration programs are also separated from +PLIB itself and are individually tarballed with their own version +numbers. Generally, they'll run with the most recent stable version +of PLIB - but occasionally they'll rely on something in the latest +PLIB beta. +

+

+Un-tar these into a separate directory from PLIB itself - or else +all the configuration and makefiles will clash. + +

The Long Answer: Installing PLIB.

+On most Linux and other UNIX-like OS's, it's simply a matter of +unpacking the tar-ball, changing directory into the plib_x.y.z +directory that this creates and typing: +
+
+   ./configure
+   make install
+
+
+You'll need to +be 'root' to perform the last step. At the end of that process, +you should have a set of header files in /usr/include/plib +and a set of corresponding libraries in /usr/lib. There +are some example programs in the 'plib-x.y.z/examples' subdirectory. +

+WARNING: If you are using 'Mesa' instead of an 'Official' OpenGL, +please make sure you followed the instructions in the Mesa installation +notes that tell you to symbolically link /usr/lib/libGL.so +and /usr/lib/libGLU.so to their Mesa equivelents. More modern +versions of Mesa may install directly into that location - but +make sure that one way or another, /usr/lib/libGL.so points to your +current OpenGL/Mesa library. +

+Some Linux distro's install OpenGL/Mesa in /usr/X11R6/lib - that +is now officially deprecated - if your OpenGL/Mesa is installed +there then I suggest you add symbolic links to make the +files appear to be in /usr/lib. +

+If you are running some non-UNIX OS, (eg MS-Windows) there may be +instructions on how to build PLIB in README.{OS name}. If you +have problems - or can offer to streamline the +process, then please pass on your knowledge via the mailing list. +In general, it isn't complicated to install - you usually just have +to compile all of the source files in each directory and link +each subdirectory into a separate library. Don't try to make +PLIB into a M$ '.DLL' - it's not worth the effort! +

+If you have the Microsoft Visual C++ suite, you'll find a set +of project files - one in each source directory - plus a master +workspace at the top of the tree. +

+If you have all the Cygnus (CygWin) compiler/tools, then use +the UNIX build instructions. +

+There is now a README.mac for Macintosh users. + +

Where Does PLIB Install Itself?

+This is always a controversial topic. In order to maintain +our own sanity, we expect PLIB to be installed in one place +and in one place only. +
+
+  Libraries are in:    /usr/lib/libplibXXX.a
+
+  Headers are in:      /usr/include/plib/XXX.h
+
+
+(Where 'XXX' is the short acronym for the PLIB library in question - +in lowercase). +

+The now *VERY* obsolete PLIB 1.0.* used to install itself +into /usr/local/plib, but from version 1.1.0 onwards, the +modern location was adopted following discussions with +several Linux distributors. +

+Please don't even think about arguing about this decision, +it has been the topic of long and arduous discussion and it's +NEVER going to change! + +

+
+
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+ + diff --git a/doc/download.png b/doc/download.png new file mode 100644 index 0000000..cab20fb Binary files /dev/null and b/doc/download.png differ diff --git a/doc/examples.html b/doc/examples.html new file mode 100644 index 0000000..15f3a9b --- /dev/null +++ b/doc/examples.html @@ -0,0 +1,191 @@ + + + + + PLIB: A Portable Games Library. + + + + + + + + + +
+PLIB Logo +
+
+
+

+ STEVE'S + PORTABLE + GAME + LIBRARY. +

+
+
+
    +And Lo, the Lion and the Sheep shall lie down together - but the Sheep won't +get much Sleep. +
    +-- Woody Allen +
+
+ +Sourceforge Logo +
+
+ + + + + + +
+HOME
+WHAT'S INSIDE
+LICENSE
+CONTACTS
+REQUIREMENTS
+GALLERY
+DOWNLOAD & INSTALL
+EXAMPLES
+ +SG +SSG
+ +SSGAUX +FNT
+ +PUI +PSL + +UL +JS
+ +NET +SL
+ +PW +PUAUX
+ + +
+ +

PLIB: Example Programs and Demonstrations.

+ +PLIB has three sources of sample programs to learn from. +
    +
  • EXAMPLES: There is a bundle of small programs that each show + off one or two small aspects of PLIB and which are + not generally all that useful by themselves. +
  • DEMOS: These are fully worked out demonstration programs + that use a wide range of PLIB features to create complete + and useful programs that are still small enough to understand + quite easily. +
  • APPLICATIONS: Because many PLIB applications are OpenSourced, + there are a large number of complex programs that you can + look at to see how large games, simulations and interactive + tools can be built using this technology. +
+ +

EXAMPLES

+ +The PLIB example programs are distributed in +a separate tarball from the main PLIB distribution - and generally, it +is updated less often - but following the same version numbers as the +main PLIB library. +

+When you install that package, you'll see that the 'src' directory is +split into sections for each PLIB component library - with one or two +different examples for each library. +

+All of the examples are licensed under GPL as bundle and are maintained +under the PLIB SVN archive. +

    +
  • FNT:
      +
    • fnt_test - a basic TXF font browser. +
    • slideshow - a way to present a simple slide-show driven + from an ASCII text file. Who needs PowerPoint + when you have 'vi'? :-) +
    • data - this directory contains 20 different TXF fonts. +
    +
  • JS:
      +
    • js_demo - a program that shows the current output from + whatever joysticks it can detect. Useful for + testing out which buttons set which bits and + which axes are which. +
    +
  • NET:
      +
    • client-server - +
    • http_get - +
    • net_echo - +
    +
  • PUI:
      +
    • simple - the "Hello World" of PUI programs. +
    • complex - a fairly pointless program that shows how + to control a spinning OpenGL cube, and use + a variety of PUI widgets. +
    • widget_list - draws every kind of PUI widget each + in a separate window. This is what we used + to make the screenshots for the PUI manual. +
    +
  • SG:
      +
    • sg_quat_test - tests the SG quaternions...unsuccessfully + I think! +
    +
  • SL:
      +
    • example - plays a number of annoying sounds. +
    • mod_demo - plays a MOD format music file. +
    +
  • SSG:
      +
    • load_save - Load a 3D model - then just save it again. +
    • majik - A test (originally written to help the Majik3D + project) that shows Tux walking around on some + auto-generated terrain. +
    • state_test - Exercises some ssgSimpleState settings. +
    • tux - A model of Tux the Penguin spins around on a + pedestal encrusted in golden Herring. +
    • tween_test - Demonstrated the 'tween' effect. +
    • water - Demonstrates the ssgAux library - water/fire/lensflare/particles plus basic shapes, cube, teapot. +
    • viewer - A program to allow you to view any 3D model + and spin it around using the mouse. +
    +
  • UTIL:
      +
    • test_dir - tests some of the directory handling features. +
    +
+

DEMONSTRATIONS

+ +The PLIB demonstration programs are distributed in +their own separate tarballs - each has it's own version number and it's +own license conditions (although all of them must fall within the SourceForge +definition for OpenSourced software in order to reside on the SourceForge +server). All of the demonstrations are maintained under the PLIB SVN +archive. + +
    +
  • ExPoser - A program to allow you to animate characters for your + games using 'Skin and Bones' animation techniques. + ExPoser needs PLIB 1.5.1 or later. +
  • TTT3D - A complete 3D TicTacToe game played on a 4x4x4 board. + It's theoretically possible to beat it - theoretically. + TTT3D needs PLIB 1.4.0 or later. +
+ +

APPLICATIONS

+ +PLIB applications do not reside on the PLIB web site - but you can find +links to many of them in our image gallery. + +
+
+
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+ + diff --git a/doc/examples.png b/doc/examples.png new file mode 100644 index 0000000..4c419eb Binary files /dev/null and b/doc/examples.png differ diff --git a/doc/fgfs.png b/doc/fgfs.png new file mode 100644 index 0000000..46add27 Binary files /dev/null and b/doc/fgfs.png differ diff --git a/doc/fnt/index.html b/doc/fnt/index.html new file mode 100644 index 0000000..c7ace79 --- /dev/null +++ b/doc/fnt/index.html @@ -0,0 +1,385 @@ + + + + + + + A Font Library for OpenGL. + + + + + + + + + + +
+

A Font Library for OpenGL

+
+ by Steve Baker +
+

Introduction

+The FNT library was originally written to allow PUI programs to +produce text using texture maps instead of bitmaps because the +latter are typically very slow on consumer-grade 3D hardware. +

An Example.

+This example program is probably all you need in the +way of documentation - so it's the first thing we'll talk +about: +
+
+   /* Declarations */
+
+   fntRenderer texout ;
+
+   /* Load some fonts */
+
+   fntTexFont  TimesRoman ( "times_roman.txf" ) ;
+   fntTexFont  Courier    ( "courier.txf" ) ;
+
+   /* Select a font and pointsize to render with... */
+
+   texout . setFont      ( & TimesRoman ) ;
+   texout . setPointSize ( 24 ) ;
+
+   /* Print "Hello" and "World" */
+
+   texout . begin () ;
+     texout . start2f ( 50.0f, 80.0f ) ;
+     texout . puts ( "Hello" ) ;
+     texout . start2f ( 50.0f, 50.0f ) ;
+     texout . puts ( "World" ) ;
+   texout . end () ;
+ 
+
+

fntInit

+All programs that use the FNT library should call 'fntInit()' sometime +after they have established a valid OpenGL rendering context and +before they make any other FNT library calls. + +

The Classes

+There are three external classes used in FNT: +
+
+  class fntFont         -- An abstract base class from which all
+                           kinds of font representations could be
+                           derived.
+  class fntTexFont      -- A fntFont that uses texture mapping.
+  class fntRenderer     -- A class that draws text using a fntFont.
+
+
+

class fntFont

+Classes derived from the fntFont class all describe fonts. +This is an abstract base class from which fntTexFont is derived. +Other fntFont sub-classes could also be derived in the future. +(This means that you cannot declare a fntFont - but all classes derived +from fntFont will obey this description.) +

+This class appears quite complex since constructing and/or +querying the contents of a texture font is a complicated +business - and consequently, there is a lot of API to +support your ability to do that. Fortunately, most FNT +applications will just load a font from disk and use +fntFont::begin()/ +fntFont::puts()/ +fntFont::end() +functionality. +

+
+  class fntFont
+  {
+  public:
+    fntFont () ;
+    ~fntFont () ;
+    void putch ( sgVec3 curpos, float pointsize, float slant, char  c ) ;
+    void puts  ( sgVec3 curpos, float pointsize, float slant, char *s ) ;
+    void begin () ;
+    void end   () ;
+    void getBBox ( char *s, float pointsize, float slant,
+                            float *left, float *right,
+                            float *bot , float *top  ) ;
+
+    int  load ( char *fname, GLenum mag = GL_NEAREST,
+                             GLenum min = GL_LINEAR_MIPMAP_LINEAR ) ;
+
+    void setFixedPitch ( int fix ) ;
+    int   isFixedPitch ()          ;
+
+    void  setWidth     ( float w ) ;
+    void  setGap       ( float g ) ;
+
+    float getWidth     () ;
+    float getGap       () ;
+
+    int   hasGlyph ( char c ) ;
+  } ;
+
+
+fntFont::getBBox() returns the top, bottom, left and +right extents (in OpenGL units) of the string 's' if it were drawn at the +specified pointsize and slant. This routine knows how to deal with +newline characters. +

+fntFont::putch() draws the character 'c' at the +cursor position specified be 'curpos' (with the specified pointsize and slant) +and advances the cursor +to the right hand edge of the character it just rendered. +

+fntFont::puts() draws the entire string 's' at the +cursor position specified be 'curpos' +(with the specified pointsize and slant) and advances the cursor +to the right hand edge of the last character it rendered. +

+Both putch and puts will automatically switch the case of letters +from upper to lower or vice versa if the required character is +not present in the font but the letter with the reverse case +is present. Other missing characters will simply generate no +output and won't update the cursor position. If a space character +is not defined in the font, then a half-pointsize gap will be +generated instead. +

+puts (but NOT putch) knows how to deal with newline characters, +it drops the text down to the next line - leaving a one-third +pointsize gap between lines. +

+fntFont::begin()/end() since redundant mode changes are +costly in OpenGL, applications may optionally call fntFont::begin() +before rendering some text using a specified font and call fntFont::end() +at the end. Just like a glBegin()/glEnd() pair, +there are some fairly restrictive rules about what you can do between +a fntFont::begin() and a fntFont::end(): +

    +
  • The only OpenGL calls that are permitted are those that + are allowed between a glBegin()/glEnd(). +
  • You may not make calls to other member functions of other + fntFont objects or to fntRenderer objects. +
  • You may not call fntFont::begin() between another + fntFont::begin()/fntFont::end() pair. +
+

+You may call fntFont::putch() and/or +fntFont::puts() without +entering a fntFont::begin()/fntFont::end() +state - but if you do that, each call will result in +OpenGL state switching - which may well be redundant. +

+int load ( char *filename ) loads a font from disk, +returns TRUE on success, FALSE for failure. +

+int load ( char *filename, GLenum mag = GL_NEAREST, +GLenum min = GL_LINEAR_MIPMAP_LINEAR )...you can optionally +specify the OpenGL texture magnification and minification filters +- this is sometimes necessary to get the clearest possible text +at certain point sizes. Experiment! +

+void setFixedPitch ( int fixed ) if 'fixed' is TRUE, forces +the font to be fixed-pitch (so each letter or 'Glyph' is a standard width), +if 'fixed' is false then variable character widths are possible. +

+void setWidth ( float w ) For a fixed width font, this +sets the width of each character. If the actual characters are wider +than this, they will overlap, if they are narrower then there will be +a gap. +

+void setGap ( float g ) Set the gap between letters, can be +negative or positive. +

+The following routines allow you to query the font's setup: +

+
+    int   isFixedPitch ()
+    float getWidth     ()
+    float getGap       ()
+
+
+int hasGlyph() returns TRUE if the font contains a +glyph (graphic image) for a given ASCII character, FALSE otherwise. +Fonts that have only uppercase (or only lowercase) letters will still +return TRUE for corresponding characters of the opposite case because +the putch and puts routines will automatically case-convert in that +case. +

class fntTexFont

+fntTexFont is inherited from fntFont. +All functions of a fntFont are implemented in fntTextFont using +a texture map. +
+
+  class fntTexFont
+  {
+    public:
+      fntTexFont () ;
+      fntTexFont ( char *fname,
+                   GLenum mag = GL_NEAREST,
+                   GLenum min = GL_LINEAR_MIPMAP_LINEAR ) ;
+      ~fntTexFont () ;
+      void putch ( sgVec3 curpos, float pointsize, float slant, char  c ) ;
+      void puts  ( sgVec3 curpos, float pointsize, float slant, char *s ) ;
+      void begin () ;
+      void end   () ;
+      void getBBox ( char *s, float pointsize, float slant,
+			      float *left, float *right,
+			      float *bot , float *top  ) ;
+
+      int  load ( char *fname,
+                  GLenum mag = GL_NEAREST,
+                  GLenum min = GL_LINEAR_MIPMAP_LINEAR ) ;
+
+      void setFixedPitch ( int fix ) ;
+      int   isFixedPitch ()          ;
+
+      void  setWidth     ( float w ) ;
+      void  setGap       ( float g ) ;
+
+      float getWidth     () ;
+      float getGap       () ;
+
+      void setGlyph ( char c,
+		    float tex_left, float tex_right,
+		    float tex_bot , float tex_top  ,
+		    float vtx_left, float vtx_right,
+		    float vtx_bot , float vtx_top  ) ;
+    
+      int  getGlyph ( char c,
+		    float *tex_left = NULL, float *tex_right = NULL,
+		    float *tex_bot  = NULL, float *tex_top   = NULL,
+		    float *vtx_left = NULL, float *vtx_right = NULL,
+		    float *vtx_bot  = NULL, float *vtx_top   = NULL) ;
+    } ;
+
+
+

+int load ( char *filename ) loads a font from disk +using the extension of the filename to determine what format it is +stored in. Currently, the only supported format is Mark Kilgards 'texfont' +format - which has the '.txf' filename extension. Returns TRUE for +success, FALSE for failure. +Details of the TXF file format can be found in + +Marks's document about Textured Fonts +

+Just as with all fntFont derived classes, you can optionally specify +the OpenGL texture filter options for the loaded texture. +

+Each font is made up of zero or more 'Glyphs' (character shapes) packed +into a single texture map. If you didn't use 'load' to load the font +from disk, you'll have to define where each one lies on the map and +how big the quadrilateral it is to be drawn on is: +

+
+    void setGlyph ( char c,
+		    float tex_left, float tex_right,
+		    float tex_bot , float tex_top  ,
+		    float vtx_left, float vtx_right,
+		    float vtx_bot , float vtx_top  ) ;
+    
+
+Where 'c' is the character we are defining, 'tex_*' is the +left, right, top and bottom of the image of that character +in the texture map. Since texture coordinates are in the +range 0..1, these will typically be quite small numbers. +'vtx_*' is the left, right, top and bottom of the character's +rectangle in a coordinate system that has (0,0) at the +baseline of the character cell, and (1,1) at the top-right +corner of the tallest, widest character in the font. Hence, +a lower-case 'y' would have a negative 'vtx_bot'. +

+You can also query all this information: +

+
+    int  getGlyph ( char c,
+		    float *tex_left, float *tex_right,
+		    float *tex_bot , float *tex_top  ,
+		    float *vtx_left, float *vtx_right,
+		    float *vtx_bot , float *vtx_top  ) ;
+
+
+fntFont::getGlyph() returns TRUE if the character has +been defined in this font, FALSE otherwise. +

class fntRenderer

+This class is the one most people are going to be using +to render text in FNT. Most applications will declare +a single fntRenderer class for all their text needs. +
+
+  class fntRenderer
+  {
+  public:
+    fntRenderer ()
+
+    void start3fv ( sgVec3 pos ) ;
+    void start2fv ( sgVec2 pos ) ;
+    void start2f  ( float x, float y ) ;
+    void start3f  ( float x, float y, float z ) ;
+
+    void getCursor ( float *x, float *y, float *z )
+
+    fntFont *getFont () ;
+    void     setFont ( fntFont *f ) ;
+
+    void begin () ;
+    void end   () ;
+
+    void putch ( char  c ) ;
+    void puts  ( char *s ) ;
+  } ;
+
+
+fntRenderer::setFont() is used to tell the renderer which +font is current. fntRenderer::getFont() lets you find out +which font it is. You may not call fntRenderer::setFont() +between a fntRenderer::begin() and fntRenderer::end() +pair. +

+By default, uppercase characters of all fonts are one OpenGL unit high. +You can make characters larger or smaller by setting +fntRenderer::setPointSize(). You can also slant the characters +to form italic or oublique fonts using fntRenderer::setSlant(). +(The slant measures by how many OpenGL units the tops of uppercase +characters are sloped to the right). You can call either setPointSize or +setSlant between fntRenderer::begin() and +fntRenderer::end(). +

+The various kinds of fntRendered::start*() calls are +akin to the OpenGL glVertex* commands and they determine where +the next chunk of text will be drawn. Since this coordinate is +updated as text is drawn, you'll need to call +fntRenderer::getCursor() to +find out where the next chunk of text will be drawn. You can +call fntRenderer::start*(), +fntRenderer::putch() and +fntRenderer::puts() between +fntRenderer::begin()/fntRenderer::end() +calls. +

Making New TXF Fonts.

+The '.txf' font format was designed by Mark Kilgard - who +also produced some tools for dealing with them. +

+Check + +Marks's document about Textured Fonts for further information. +Of particular interest is Mark's "gentexfont" program that can +create a TXF format font from an X-windows font. +

+You can find out which X-fonts are stored on your machine using +the /usr/X11/bin/xlsfonts program. +

+There are over a dozen sample TXF fonts stored +in examples/src/fnt/data. +


+ + +
+Valid HTML 4.0! + +
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+
+ + + diff --git a/doc/gallery.html b/doc/gallery.html new file mode 100644 index 0000000..3159572 --- /dev/null +++ b/doc/gallery.html @@ -0,0 +1,188 @@ + + + + + PLIB: Gallery. + + + + + + + + + +
+PLIB Logo +
+
+
+

+ STEVE'S + PORTABLE + GAME + LIBRARY. +

+
+
+
    +And Lo, the Lion and the Sheep shall lie down together - but the Sheep won't +get much Sleep. +
    +-- Woody Allen +
+
+ +Sourceforge Logo +
+
+ + + + + +
+HOME
+WHAT'S INSIDE
+LICENSE
+CONTACTS
+REQUIREMENTS
+GALLERY
+DOWNLOAD & INSTALL
+EXAMPLES
+ +SG +SSG
+ +SSGAUX +FNT
+ +PUI +PSL + +UL +JS
+ +NET +SL
+ +PW +PUAUX
+ + +
+

ScreenShot Gallery.

+These images come from a wide variety of PLIB applications - some OpenSourced, +some commercial. Click on the thumbnail image for more detail and links to further +information. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

The FlightGear Flight Simulator.

+
+ +FlightGear
+
+

The Chronicles of the Evil Overlord.

+
+ +Chronicles of the Evil Overlord
+
+

The ExPoser Animation Tool.

+
+ +ExPoser
+
+

HardBall.

+
+ +HardBall
+
+

MOTE.

+
+ +MOTE
+
+

The PrettyPoly Modeller.

+
+ +PrettyPoly Modeller
+
+

TicTacToe 3D.

+
+ +TicTacToe 3D
+
+

TORCS Car Racing Simulator.

+
+ +TORCS
+
+

Tuxedo T. Penguin - A Quest for Herring.

+
+ +A Quest for Herring
+
+

TuxKart.

+
+ +TuxKart
+
+

TuxFleet.

+
+ +TuxFleet
+
+

Wizz.

+
+ +Wizz
+
+

Atlas Map Maker.

+
+ +Atlas Map Maker
+
+

Flight Dynamics Simulator.

+
+ +Flight Dynamics Simulator
+
+
+ +
+
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+ + diff --git a/doc/gallery.png b/doc/gallery.png new file mode 100644 index 0000000..1aa7d3d Binary files /dev/null and b/doc/gallery.png differ diff --git a/doc/home.png b/doc/home.png new file mode 100644 index 0000000..d512401 Binary files /dev/null and b/doc/home.png differ diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000..e9c2ec9 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,203 @@ + + + + + PLIB: A Portable Games Library. + + + + + + + + + +
+PLIB Logo +
+
+
+

+ STEVE'S + PORTABLE + GAME + LIBRARY. +

+
+
+
    +And Lo, the Lion and the Sheep shall lie down together - but the Sheep won't +get much Sleep. +
    +-- Woody Allen +
+
+ +Sourceforge Logo +
+
+ + + + + + +
+HOME
+WHAT'S INSIDE
+LICENSE
+CONTACTS
+REQUIREMENTS
+GALLERY
+DOWNLOAD & INSTALL
+EXAMPLES
+ +SG +SSG
+ +SSGAUX +FNT
+ +PUI +PSL + +UL +JS
+ +NET +SL
+ +PW +PUAUX
+ +
+ +

PLIB: A Suite of Portable Game Libraries.

+I (and an ever increasing band of helpers) have been spending +time to build a set of OpenSource (LGPL) libraries that will +permit programmers to write games and other realtime interactive +applications that are 100% portable across a wide range of hardware and +operating systems. + +

+PLIB includes sound effects, music, a complete 3D engine, font +rendering, a simple Windowing library, a game scripting language, +a GUI, networking, 3D math library and a +collection of handy utility functions. All are 100% portable +across nearly all modern computing platforms. What's more, it's +all available on line - and completely free. Each library component +is fairly independent of the others - so if you want to use SDL, +GTK, GLUT, or FLTK instead of PLIB's 'PW' windowing library, you can. +

+The latest stable version of PLIB is 1.8.4 - go to the +DOWNLOAD section to get a +copy - go to the WHAT'S INSIDE +section for documentation and a more detailed description of +what PLIB contains. + +

+If you are looking at other games libraries (and there are a LOT +to choose from) - ask yourself how many games have been written +for that library by people outside the group that wrote it. That +is the acid test of usability and PLIB passes with flying colours. + +

+PLIB is used by many projects (not all games - and not all +OpenSourced), here are some of the more prominent ones - there +are at least a hundred others: +

+ + + + + + + + + + + + + + + + + + + + +
+ Tux_AQFH Logo
+ Tux the Penguin - +
A Quest for herring.
TuxKart
+ + TuxKart Logo
+ FlightGear Logo
+ FlightGear
Majik3D
+ + Majik3D Logo
+ PrettyPoly Logo
+ + PrettyPoly Editor
TuxFleet
+ + TuxFleet Logo
TORCS
+ + TORCS Logo
+ Minigolf Maniacs Logo
+ + Minigolf Maniacs
+
+
+ + + + + + + + +
+ FDS Logo
+ + Flight Dynamics Simulator
+ MOTE Logo
+ + MOTE
+ + Spacething Logo
+ Spacething
+
+

+Unlike the many similar libraries, PLIB is easy to learn and +use - and has an object-oriented C++ interface. It's built +as a set of component libraries that you can pick and choose +between if (for example) you don't want to use PLIB's GUI but +you do want to use it's scene graph API. + +

+ +If you are reading this document from the source distribution on +your local disk, you can find the most up to date version of PLIB +here: +

+PLIB's web presence is currently hosted on SourceForge (with thanks to +VA Linux Inc for providing this free service), and the +project summary page is here: + + +
+
+
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+ + diff --git a/doc/js/index.html b/doc/js/index.html new file mode 100644 index 0000000..abdc32f --- /dev/null +++ b/doc/js/index.html @@ -0,0 +1,187 @@ + + + + + + + A Joystick Library. + + + + + + + + + + + +
+

A Joystick Library.

+
+ by Steve Baker +
+

Introduction

+JS is now just one component of PLIB. +

+This Joystick Library (JS) is a portable interface that +has no inherent restrictions over the number and type +of joysticks it supports - although in actuality, most +implementations will simply sit on top of an underlying +driver provided by the Operating System. +

+You should include the JS header file '/usr/include/plib/js.h' +and link to the JS library '/usr/lib/libjs.a'. +

+Before using any JS functions, you should initialise the +library by calling: +

+
+    jsInit () ;
+
+
+JS is essentially just a wrapper to make the various +underlying OS mechanisms look the same to application code. +
+
+  class jsJoystick
+  {
+     jsJoystick ( int id = 0 ) ;
+    ~jsJoystick () ;
+
+     const char* getName () const ;
+     int   getNumAxes    () const ;
+     int   getNumButtons () const ;
+     int   notWorking    () const ;
+     void  setError      () ;
+
+     float getDeadBand ( int axis ) const     ;
+     void  setDeadBand ( int axis, float db ) ;
+
+     float getSaturation ( int axis ) const     ;
+     void  setSaturation ( int axis, float st ) ;
+
+     void setMinRange ( float *axes ) ;
+     void setMaxRange ( float *axes ) ;
+     void setCenter   ( float *axes ) ;
+
+     void getMinRange ( float *axes ) const ;
+     void getMaxRange ( float *axes ) const ;
+     void getCenter   ( float *axes ) const ;
+
+     void read    ( int *buttons, float *axes ) ;
+     void rawRead ( int *buttons, float *axes ) ;
+  }
+
+
+You pass the identifier (0..n) of the joystick you wish to +open into the constructor function. If you leave the number +off, it'll grab the first joystick available. +

+If the joystick is unavailable, not working, not installed or +otherwise bad, the package will return zero for all the axes +and all the buttons will appear to be up. If you need to +check for the existance of a particular stick, you can +call notWorking() which returns JS_TRUE if +there is some problem with that stick, JS_FALSE otherwise. +

+getName() tells you the device name of the +joystick, if available through API calls in your OS. A +typical value is "CH PRODUCTS CH PRO PEDALS USB ". If no +name is available, this method will return the empty string. +

+getNumAxes() tells you how many axes the stick +has. Note that it is NOT safe to assume that all sticks have +the same number of axes - or that they all have a maximum of +three or something. When you pass axis data into and out of +JS, your arrays MUST be sized large enough for that stick. +

+When you are testing joystick code, you need to be sure your +program does the right thing when no joystick is installed. +Since it's inconvenient to do keep uninstalling your stick +to do that, we provide setError() which causes +that stick to react exactly as if it were not installed. +

+To read the joystick, just call read(&buttons,axes) +where 'buttons' is an integer and 'axes' is an array of +floating point numbers. The buttons variable will be populated +with a number that has one bit per button (0==Not Pressed, 1==Pressed) +and the elements of the axis array will be scaled from an idealized +-1.0 to +1.0 range. (In practice, your stick may not reach those +limits - or it may marginally exceed them). +

+For a basic two axis stick, axis zero is Left/Right with left being +negative and right positive. Axis one is North/South with north being +negative and right positive (this is counter-intuitive - but that's +what they do). +

+M$-Windows letters its stick axes X,Y,Z,R,U,V. These correspond +to JS axes 0,1,2,3,4,5,6. +

Buttons

+One continually annoying thing about PC joysticks is the lack of +standards for their names. Most sticks have at least two buttons - +mine has six (maybe some have still more). The problem is to know +how to name them. My game pad has buttons labelled A,B,C,D,R,L +corresponding to bits 0,1,2,3,4,5 in the 'buttons' variable. +

+Anyway, some joysticks have features that operate by setting +two or more button bits at once. This is quite easy to catch by +masking multiple bits from the 'buttons' word. +

Demo Program

+The demo program that comes with JS is quite useful for finding out +which buttons set which bits and which axes are which - and in +which direction they operate. +

Calibration

+Since most joysticks are analog devices (and fairly cheap, nasty ones +at that), you will not generally get numbers that are accurately +in the range -1..1 with exactly zero being returned when the joystick +is centered on it's springs. This means that you may wish to calibrate +your joystick. The rawRead routine bypasses all the scaling and +offsetting to return RAW data directly from the OS that you can use during +calibration. +

+For each axis of the joystick, you should provide a maximum number +(that you wish to correspond to 1.0 returned by read()), +a minimum number (corresponding to -1.0) and a center point number +(corresponding to 0.0) by calling +setMaxRange()/setMinRange()/setCenter() as appropriate. +

+However, even with calibration, you should expect the joystick to +drift somewhat over time due to the position of the cable, the +temperature of the potentiometers and probably, the phase of the moon. +This drift is typically not serious at the max and min limits - but +in some applications, the user will expect (for example) for his +character in a game to stop moving completely when he releases the +stick. Since we cannot guarantee to get the same exact number out +of the stick when he does this, you'll need to implement a 'dead band' +in the middle of the stick's travel. This is done with +setDeadBand(axis,amount) where 'axis' is the number of the +axis you wish to have a dead band implemented on - and 'amount' is the +amount of dead band either side of 0.0. +

+There are corresponding 'get' routines for each 'set'. +

+The read routine is auto-calibrated when you create +the joystick class - so if the joystick is not centered at that +moment, you will get bad data from that point onwards. This is +quite common in games - so don't feel too badly about it. Just +arrange to 'new' all your joysticks early on in the program - when +your user's hands are likely to still be on the keyboard or mouse - +and provide a hot-key to pause the game and recalibrate the stick +on demand. +


+ + +
+Valid HTML 4.0! + +
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+
+ + + diff --git a/doc/license.html b/doc/license.html new file mode 100644 index 0000000..a018eca --- /dev/null +++ b/doc/license.html @@ -0,0 +1,112 @@ + + + + + PLIB: Licensing. + + + + + + + + + +
+PLIB Logo +
+
+
+

+ STEVE'S + PORTABLE + GAME + LIBRARY. +

+
+
+
    +And Lo, the Lion and the Sheep shall lie down together - but the Sheep won't +get much Sleep. +
    +-- Woody Allen +
+
+ +Sourceforge Logo +
+
+ + + + + + +
+HOME
+WHAT'S INSIDE
+LICENSE
+CONTACTS
+REQUIREMENTS
+GALLERY
+DOWNLOAD & INSTALL
+EXAMPLES
+ +SG +SSG
+ +SSGAUX +FNT
+ +PUI +PSL + +UL +JS
+ +NET +SL
+ +PW +PUAUX
+ + +
+

PLIB Licensing.

+PLIB is licensed under the Library GNU Public License (LGPL). +

+Whilst this permits closed-source applications to use PLIB, you +are bound by certain restrictions under LGPL. Please be sure +to read and understant the 'LICENSE' file in the PLIB distribution +directory before you distribute any work based around or upon PLIB. +

+The PLIB example programs (being complete programs) are licensed +under the GNU General Public License (GPL). +

+Each of the demonstration programs has it's own license - but +they are all 'OpenSource' of one kind or another (as defined by +the SourceForge rules for OpenSourced software. Check the +distribution directory for each one for a LICENSE file describing +how it's licensed. +

Polite Request to Distributors.

+If you are a Linux or other OpenSource software distributor, +please do us the courtesy of only releasing stable versions +of PLIB and NOT versions labelled 'unstable' - or (especially) +any snapshot you may take from SVN. We are aware that legally, +you are entitled to do either of these things - but we ask +that you do not because it makes supporting PLIB that much +more difficult. +

+We would also appreciate being notified of which versions +you plan to ship - and approximately when so that we may +coordinate with you as to the best version to take. +

+
+
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+ + diff --git a/doc/license.png b/doc/license.png new file mode 100644 index 0000000..8aed83d Binary files /dev/null and b/doc/license.png differ diff --git a/doc/majik3d.png b/doc/majik3d.png new file mode 100644 index 0000000..81c00da Binary files /dev/null and b/doc/majik3d.png differ diff --git a/doc/marble.png b/doc/marble.png new file mode 100644 index 0000000..5c6c793 Binary files /dev/null and b/doc/marble.png differ diff --git a/doc/mote.png b/doc/mote.png new file mode 100644 index 0000000..031ac49 Binary files /dev/null and b/doc/mote.png differ diff --git a/doc/net/index.html b/doc/net/index.html new file mode 100644 index 0000000..f3ade67 --- /dev/null +++ b/doc/net/index.html @@ -0,0 +1,354 @@ + + + + + + + Pegasus Network Library + + + +
+

Pegasus Network Library

+
+

Introduction

+Pegasus is a C++ library for making networked games. Pegasus is based on +Medusa +and is part of PLIB. +Pegasus, like Medusa, runs as a single process, multiplexing I/O with its various +client and server connections within a single process/thread. Pegasus is supported +on any platform that includes a socket implementation with the select() function. +This includes Win32, Linux, and a majority of Unix implementations. +

+This document assumes a certain degree of knowledge of +TCP/IP and socket programming. +

+To use the NET library, you'll need to '#include ' and +link to libplibnet.a +

Symbol Conventions.

+Pegasus follows the same conventions for symbols and tokens that +are used by OpenGL and GLUT. All Pegasus symbols for classes and +functions start with net and all #define +tokens start with NET. Words within a class or function +name are Capitalised and NOT separated with underscores. Words +within #define tokens may be separated with underscores +to make them readable. +

Initialisation.

+The first NET call in any program must always be netInit(). +

Classes

+The following class hierarchy makes up the core package - which +can be extended to add functionality or to change some underlying +mechanisms. +
+
+   class netAddress
+
+   class netBuffer
+    |__ class netMessage
+
+   class netGuid
+    
+   class netSocket
+    |__ class netChannel
+         |__ class netBufferChannel
+         |    |__ class netChat
+         |    |__ class netMessageChannel
+         |
+         |__ class netMonitorServer
+
+
+

class netBuffer

+A simple buffer class. +
+class netBuffer
+{
+public:
+  netBuffer ( int max_length ) ;
+  ~netBuffer () ;
+
+  int getLength() const ;
+  int getMaxLength() const ;
+  char* getData() ;
+
+  void remove () ;
+  void remove (int pos, int n) ;
+  bool append (const char* s, int n) ;
+  bool append (int n) ;
+} ;
+
+

class netMessage

+A message buffer used to transfer binary data and handle byte swapping. +
+class netMessage : public netBuffer
+{
+public:
+
+  netMessage ( const char* s, int n ) ;
+  netMessage ( int type, int to_id, int from_id ) ;
+
+  int getType () const ;
+  int getToID () const ;
+  int getFromID () const ;
+
+  void geta ( void* a, int n ) const ;  // a=array; array should already be serialized
+  void puta ( const void* a, int n ) ;
+
+  int getch () const ;
+  void putch ( int c ) ;
+
+  bool getb () const ;
+  void putb ( bool b ) ;
+
+  int getw () const ;
+  void putw ( int i ) ;
+
+  int geti () const ;
+  void puti ( int i ) ;
+
+  void gets ( char* s, int n ) const ;
+  void puts ( const char* s ) ;
+
+  void print ( FILE *fd = stderr ) const ;
+};
+
+

class netAddress

+This is the representation of an Internet-style machine address. +
+class netAddress
+{
+public:
+  netAddress () ;
+  netAddress ( const char* host, int port ) ;
+
+  void set ( const char* host, int port ) ;
+
+  const char* getHost () const ;
+  int         getPort () const ;
+
+  static const char* getLocalHost () ;
+
+  bool getBroadcast () const ;
+} ;
+
+
+When reading from the network using one of the higher level classes, +you can use a netAddress with an empty string as the 'host' to mean +"accept data from any host". When writing to the network, the +reserved host name '<broadcast>' (the < and > are literally +there) will cause the message to be broadcast to all machines on your +subnet. +

+Otherwise, use either the machines' network name - or it's IP address +(as an ASCII string). +

class netSocket

+netSocket is the low-level socket class. +
+class netSocket
+{
+public:
+  netSocket () ;
+  virtual ~netSocket () ;
+
+  int getHandle () const ;
+  void setHandle (int handle) ;
+
+  bool  open ( bool stream=true ) ;
+  int   bind ( cchar* host, int port ) ;
+  int   listen ( int backlog ) ;
+  int   accept ( netAddress* addr ) ;
+  int   connect ( cchar* host, int port ) ;
+  int   send ( const void * buffer, int size, int flags = 0 ) ;
+  int   sendto ( const void * buffer, int size, int flags, const netAddress* to ) ;
+  int   recv ( void * buffer, int size, int flags = 0 ) ;
+  int   recvfrom ( void * buffer, int size, int flags, netAddress* from ) ;
+  void  close ( void ) ;
+  void  setBlocking ( bool blocking ) ;
+} ;
+
+

Example:

+This example is stripped of error checking for clarity: + + + + + +
+

Sender:

+
+  netInit () ;
+
+  netSocket *sock = new netSocket () ;
+  sock -> open        ( false ) ;
+  sock -> setBlocking ( false ) ;
+  sock -> connect     ( host, port ) ;
+
+  while ( !done )
+    sock -> send ( msg, len, 0 );
+
+  sock -> close () ;
+
+
+

Reciever:

+
+  netInit () ;
+
+  netSocket *sock = new netSocket () ;
+  sock -> open        ( false ) ;
+  sock -> setBlocking ( false ) ;
+  sock -> bind        ( host, port ) ;
+
+  while ( !done )
+    if ( (len = sock -> recv(msg, maxlen, 0)) >= 0 )
+      ...use the data...
+
+  sock -> close () ;
+
+
+This code produces a 'Datagram' connection - which is fast but unreliable +(using UDP protocol). Passing a 'true' to sock->open() would produce a +'Stream' connection (using TCP). + +

class netChannel

+netChannel adds event-handling to the low-level +netSocket class. Otherwise, it can be treated as +a normal non-blocking socket object. +The direct interface between the poll loop and +the channel object are the handleReadEvent and +handleWriteEvent methods. These are called +whenever a channel object 'fires' that event. +The firing of these low-level events can tell us whether +certain higher-level events have taken place, depending on +the timing and state of the connection. +
+class netChannel : public netSocket
+{
+public:
+
+  netChannel () ;
+  virtual ~netChannel () ;
+
+  void setHandle (int s, bool is_connected = true);
+  bool isConnected () const ;
+  bool isClosed () const ;
+  void shouldDelete () ;
+
+  // --------------------------------------------------
+  // socket methods
+  // --------------------------------------------------
+  
+  bool  open        ( bool stream=true ) ;
+  int   listen	    ( int backlog ) ;
+  int   connect     ( cchar* host, int port ) ;
+  int   send        ( const void * buf, int size, int flags = 0 ) ;
+  int   recv        ( void * buf, int size, int flags = 0 ) ;
+  void  close       ( void ) ;
+
+  // poll() eligibility predicates
+  virtual bool readable (void) ;
+  virtual bool writable (void) ;
+  
+  // --------------------------------------------------
+  // event handlers
+  // --------------------------------------------------
+  
+  void handleReadEvent (void);
+  void handleWriteEvent (void);
+  
+  // These are meant to be overridden.
+  virtual void handleConnect (void) ;
+  virtual void handleRead (void) ;
+  virtual void handleWrite (void) ;
+  virtual void handleClose (void) ;
+  virtual void handleAccept (void) ;
+  virtual void handleError (int error) ;
+
+  static bool poll (u32 timeout = 0 ) ;
+  static void loop (u32 timeout = 0 ) ;
+};
+
+

class netBufferChannel

+netBufferChannel is a netChannel with I/O buffering. +Clients and servers built on top of netBufferChannel +automatically support pipelining where you can send +multiple commands without waiting for the response +to each command before you send the next. +
+class netBufferChannel : public netChannel
+{
+public:
+  netBufferChannel (int in_buffer_size = 512, int out_buffer_size = 4096) ;
+  void closeWhenDone (void) ;
+
+  virtual bool bufferSend (const char* msg, int msg_len) ;
+  virtual void handleBufferRead (netBuffer& buffer) ;
+};
+
+

class netChat

+netChat adds support for 'chat' style protocols - +where one side sends a 'command', and the other sends +a response (examples would be the common internet +protocols - smtp, nntp, ftp, etc..). +

+The handle_buffer_read() method looks at the input +stream for the current 'terminator' (usually '\r\n' +for single-line responses, '\r\n.\r\n' for multi-line +

+class netChat : public netBufferChannel
+{
+public:
+  netChat () ;
+
+  void setTerminator (const char* t);
+  const char* getTerminator (void);
+
+  bool push (const char* s) ;
+
+  virtual void collectIncomingData (const char* s, int n) ;
+  virtual void foundTerminator (void) ;
+};
+
+

class netMessageChannel

+A channel for binary messages. Takes care of packing and unpacking them in/out of the buffers. +
+class netMessageChannel : public netBufferChannel
+{
+public:
+  netMessageChannel () ;
+
+  bool sendMessage ( const netMessage& msg ) ;
+  virtual void handleMessage ( const netMessage& msg ) ;
+};
+
+

class netMonitorServer

+The monitor server gives you remote, 'back-door' access to your server while it is running. netMonitor is a telnet command port with +password authorization. It can be paired with and used to remotely admin another server. +Once connected via any telnet client to the monitor, you can issue commands. The monitor can be hooked up to a python interpreter for added power. Since an ordinary telnet session is not secure, the password could be intercepted, but that level of security is usually not needed for games. +
+class netMonitorServer : public netChannel
+{
+public:
+  netMonitorServer( cchar* _name, int port ) ;
+  ~netMonitorServer() ;
+
+  cchar* getPassword () const ;
+  void setPassword ( cchar* string ) ;
+  void setPrompt ( cchar* string ) ;
+  void setCommandFunc ( void (*func)(cchar*, netMonitorChannel*) ) ;
+} ;
+
+
+ + +
+Valid HTML 4.0! + +
+ +Dave McClurg +<dpm@efn.org> +
+
+ + + diff --git a/doc/plib_logo.png b/doc/plib_logo.png new file mode 100644 index 0000000..445fbf8 Binary files /dev/null and b/doc/plib_logo.png differ diff --git a/doc/ppe_logo_1.png b/doc/ppe_logo_1.png new file mode 100644 index 0000000..be35010 Binary files /dev/null and b/doc/ppe_logo_1.png differ diff --git a/doc/psl/appl_guide.html b/doc/psl/appl_guide.html new file mode 100644 index 0000000..8039723 --- /dev/null +++ b/doc/psl/appl_guide.html @@ -0,0 +1,430 @@ + + + + + + + The PLIB Scripting Language: Applications Guide. + + +  + + + + +
+
+

The PSL Application Programmer's Guide.

+
By Steve Baker
+
+

Introduction

+This document is to help people writing C++ applications to include +scripting abilities using the PSL interpreter. +

+ +To include PSL scripts into your application requires that you: +

+
+   #include <plib/psl.h>
+
+
+...and link with '-lplibpsl' +

+Then, sometime before you call any other PSL functions, you must call: +

+
+   pslInit () ;
+
+
+Each PSL script is represented by an object of class pslProgram +

Example Application

+This is the simplest possible PSL application, it +loads a script called "test.psl", compiles and runs it. +
+
+  #include <plib/psl.h>
+
+  void main ()
+  {
+    pslInit () ;
+    pslExtension extensions [] = { { NULL, 0, NULL } } ;
+    pslProgram *prog = new pslProgram ( extensions, "Program1" ) ;
+    prog -> compile ( "test.psl" ) ;
+    while ( prog -> step () != PSL_PROGRAM_END ) /* Nothing */ ;
+  }
+
+
+Here is a line-by-line explanation: +

+

+ + + + + + +
pslInit () ; +Initialise PSL - this must be the first thing you do.
pslExtension extensions [] ... +Make a list of PSL extension functions.
+This program doesn't have any.
pslProgram *prog = new pslProgram... +Declare a program (called "MyProgram").
prog -> compile ( "test.psl" ) ; +Compile the program to bytecode.
while ( prog -> step () != PSL_PROGRAM_END )... + +Tell the PSL program to execute one 'step' +
Keep doing that until we reach the end of the program. +
+
+

+Easy! +

+Now let's look at class pslProgram in more detail. +

class pslProgram

+Each PSL script is represented by an object of class pslProgram. +
+
+  class pslProgram
+  {
+  public:
+
+    pslProgram ( const pslExtension *extns, const char *name ) ;
+
+    pslProgram ( pslProgram         *prog,  const char *name ) ;
+
+
+    void  setUserData ( void *data ) ;
+    void *getUserData () const ;
+
+    void  setProgName ( const char *name ) ;
+    char *getProgName () const ;
+
+    void      dump  () const ;
+    void      reset () ;
+    pslResult step  () ;
+    pslResult trace () ;
+
+    int compile ( const char *memptr, const char *fname ) ;
+    int compile ( const char *fname ) ;
+    int compile ( FILE *fd ) ;
+  } ;
+
+
+

pslProgram::pslProgram

+There are two constructor functions to choose from. The first +takes an array of 'extension functions' and the name by which +this program will be known (for error messages and such). The +second constructor takes an existing, compiled PSL program and +makes a copy of it - it too needs a program name. +

+The second version of the constructor is especially efficient +because this enables the script to be compiled just once - and +run multiple times in parallel. The second and subsequent +copies of the program consume much less RAM than the first +copy because they share the 'code' part of the script. +

+For example, you can run two copies of a script in parallel +like this: +

+
+  pslInit () ;
+ 
+  pslProgram *prog_1 = new pslProgram ( extensions, "code1" ) ;
+  prog_1 -> compile ( "data/test.psl" ) ;
+ 
+  pslProgram *prog_2 = new pslProgram ( prog_1, "code2" ) ;
+ 
+  while ( prog_1 -> step () != PSL_PROGRAM_END &&
+          prog_2 -> step () != PSL_PROGRAM_END )
+    /* NOTHING */ ;
+
+
+

pslProgram::compile

+When you compile a PSL program, any errors or warnings are reported +to stderr (by default) and the number of fatal compilation errors +is returned as the result of the 'compile' function. Programs may +choose to ignore any compilation errors - but executing the resulting +program will immediately produce a PSL_PROGRAM_END. +

+You can pass to the compiler either: +

    +
  1. The filename of the file containing the PSL source code...or... +
  2. A 'FILE *' descriptor for the file containing the PSL source...or... +
  3. The address of a null terminated string containing the + program source PLUS a name to use for the program when reporting + errors, etc. +
+If you pass the filename (1) or the address of the source with a name (3), +then error messages from PSL will refer to that name. But if you pass a +file destriptor then the program name that you passed to the constructor +function will be reported. +

+Applications that would like to report scripting errors in a more elegant +way, may register a callback function that will be called whenever there +is a problem within PSL: +

+
+  void pslSetErrorCallback ( void (*CB) ( pslProgram *, int, char *,
+                                                        int, char * ) ) ;         
+
+Your function will be called with five parameters: +
+
+  void myErrorCB ( pslProgram *prog, int severity,
+                   char *progname, int lineno, char *message ) ) ;         
+
+
    +
  • The 'prog' parameter is a pointer to the pslProgram that had the + problem. +
  • The 'severity' parameter is the error type and severity: +
      +
    • PSL_COMPILETIME_WARNING - A problem was found while + compiling the PSL program - but it may not be serious enough + to prevent it from running. +
    • PSL_COMPILETIME_ERROR - A serious problem was found while + compiling the PSL program - it won't run correctly. +
    • PSL_RUNTIME_WARNING - A problem was found while running + the PSL program - but it wasn't serious enough to prevent + the program from continuing to execute. +
    • PSL_RUNTIME_ERROR - The PSL program 'crashed' while being + executed. +
    +
  • The 'progname' parameter is the name of the program. +
  • The 'lineno' parameter is the line number at which the problem + occurred (if compiling) or the byte-code address at which it + failed (if at runtime). The latter isn't much use unless you + are a developer of the PSL interpreter. +
  • The 'message' parameter is the actual text of the error message. +
+Notice that at compiletime, the 'progname' parameter is the name of the +file or string being compiled (if that's known to the compiler). Since it's +possible for one PSL source file to '#include' another, you should +always use the 'progName' parameter in your error messages in preference +to prog->getProgName() member function. +

pslExtension

+We have not yet talked about this mysterious 'extensions' array that's passed +into the pslProgram constructor function. +

+It's important that your PSL scripts are able to interact with your C++ +program - and this is done by creating a number of C++ functions that +can be called by the PSL program as it executes. These are called +'extensions' because they extend the functionality of PSL. +

+The extension parameter to the pslProgram constructor is an array of +pslExtension structures: +

+
+  class pslExtension
+  {
+  public:
+
+    const char *symbol ;
+    int   argc ;
+    pslValue (*func) ( int, pslValue *, pslProgram *p ) ;
+  } ;
+                                                                               
+
+
    +
  • The 'symbol' field is the name of the extension function AS IT APPEARS INSIDE +PSL PROGRAMS. This doesn't have to be the same as the actual name of +your C++ function. +
  • The 'argc' field is the number of parameters the function expects. You can +set 'argc' to -1 to allow any number of parameters to be passed - so that you +can create functions that work like 'printf' does. +
  • The 'func' field is a pointer to your C++ function. +
+The list of pslExtensions is terminated by a { NULL, 0, NULL} +entry. +

+The C++ function has to look like this: +

+
+  pslValue my_func ( int argc, pslValue *argv, pslProgram *p )
+
+
+
    +
  • The 'argc' parameter to the C++ function is the number of +PSL parameters that were passed to it. It's useful to know this +number when your pslExtension had 'argc' set to -1. +

    +

  • The 'argv' parameter is an array containing the parameters +that PSL is passing to this function. Each element is a 'pslValue' +class which could contain any of the PSL variable types. +

    +

  • The 'p' parameter is a pointer to the pslProgram that was +running at the time this function was called. Notice that pslProgram's +can have user data associated with them - so this gives you quite a +bit of scope for accessing script-specific data structures. +

    +

  • When your script has finished doing it's job, it has to return +some kind of result. This is another one of those 'pslValue' +class objects. +
+

Example Extension Function

+This C++ function prints it's arguments to stdout and returns the +value 123.456. +
+ 
+  pslValue print ( int argc, pslValue *argv, pslProgram *p )
+  {
+    for ( int i = 0 ; i < argc ; i++ )
+    {
+      switch ( argv[i].getType () )
+      {
+	case PSL_INT    : printf ( "%d ", argv[i].getInt    () ) ; break ;
+	case PSL_FLOAT  : printf ( "%f ", argv[i].getFloat  () ) ; break ;
+	case PSL_STRING : printf ( "%s ", argv[i].getString () ) ; break ;
+	case PSL_VOID   : printf ( "(void) " ) ; break ;
+	default : printf ( "Illegal parameter passed to 'print'." ) ; break ;
+      }
+    }
+   
+    pslValue ret ;
+    ret.set ( 123.456f ) ;
+    return ret ;
+  }
+
+
+Adding this to the example program above, requires only that you +change the declaration of 'extensions' as follows: +
+
+  pslExtension extensions [] =
+  {
+    { "print", -1, print },
+    { NULL, 0, NULL }
+  } ;
+
+
+Now, now you can write "Hello World" in PSL script: +
+
+  int main ()
+  {
+    print ( "Hello World.\n" ) ;
+  }
+
+
+...and your C++ function 'print' will be called with one parameter +that'll contain the string value "Hello World.\n". +

pslValue

+The 'pslValue' class is used to pass numbers into and out of extension +functions. It contains the type and value of a number or string in PSL +and it looks like this: +
+
+  class pslValue
+  {
+  public:
+
+    pslType getType   () const ;
+
+    int     getInt    () const ;
+    float   getFloat  () const ;
+    char   *getString () const ;
+
+    void set () ;
+    void set ( int   v ) ;
+    void set ( float v ) ;
+    void set ( const char      *v ) ;
+    void set ( const pslNumber *v ) ;
+  } ;                                                                            
+
+
+Setting nothing into your pslValue ("my_value->set()") is used to +return a 'void' result from your extension function - that is the default +type for a pslValue. +

+The 'getType' call returns the type of this value - currently, +it can be: PSL_INT, PSL_FLOAT, PSL_STRING or PSL_VOID. If you 'set' the +pslValue, it automatically changes it's 'getType' result to match. +

+Doing a 'get' for a type that DOESN'T match the 'getType' of the pslValue +causes it to try to convert to that type. However, a 'getString' on a +non-string pslValue will return NULL. Doing a 'getInt' or 'getFloat' +on a PSL_STRING will perform an atoi() or atof() (respectively) in an +attempt to get a number from the string. +

Running, Tracing, Debugging.

+You run the PSL program one byte-code instruction at a time by calling the +pslProgram::step() function. A byte-code +instruction is rather like the 'machine code' of a physical computer and +it typically takes several byte-code instructions to implement each line +of PSL source code. +

+The 'step' function returns one of three possible results: +

    +
  • PSL_PROGRAM_CONTINUE -- The PSL program is running normally. +
  • PSL_PROGRAM_END -- The PSL program has finished running. This + could be because it simply ended normally - but it could also + be because it 'crashed' with a fatal runtime problem of some kind. +
  • PSL_PROGRAM_PAUSE -- There is a special 'pause' statement in PSL + and when that statement is executed, it causes 'step' to return + this value. +
+The PSL_PROGRAM_PAUSE return is intended to cope with the specific +case when PSL is being used in an interactive graphical application. +Typically, such applications will not want to run PSL scripts to +completion every frame - but instead run them up to the next 'pause' +statement. +

+A typical game might have dozens of PSL scripts running in parallel +and wish to run each of them until the script 'pause's. +

+So, your application's main loop might look something like this: +

+
+  read_the_joystick () ;
+
+  for ( int i = 0 ; i < num_scripts ; i++ )
+    while ( program [ i ] -> step () == PSL_PROGRAM_CONTINUE )
+      /* Do Nothing */ ;
+
+  render_the_graphics () ;
+  swap_the_doublebuffer () ;
+
+
+Then, one of those scripts (to move a monster for example) +might look like this: +
+
+   int main ()
+   {
+     int i = getMyMonster () ;
+
+     while ( 1 )
+     {
+       moveMonster ( i ) ;
+       pause ;
+     }
+   }
+
+
+The 'pause' command indicates that this script has completed it's +work for this frame. +

+Alternatively, some applications may wish to run the scripts for +fixed amounts of time, fixed numbers of byte-codes - or until +some other criterion is satisfied. +

Resetting a Script

+There is a pslProgram::reset() function that +restarts the PSL program from the beginning having first +reset all of its internal variables. +

Debugging PSL scripts

+For debugging PSL scripts, you may replace the 'step' call with +'trace' - which causes the byte-code for each instruction to be +printed to stderr as it's executed. +

+You can also call pslProgram::dump() to print out +all of the byte-code and the PSL symbol table for the program. +

Include paths.

+By default, PSL searches for files with relative pathnames in +the current directory - but you can override this by setting: +
+
+
+   pslScriptPath ( "directory" ) ;
+
+
+
+
+Steve J. Baker. <sjbaker1@airmail.net>
+ + diff --git a/doc/psl/impl_guide.html b/doc/psl/impl_guide.html new file mode 100644 index 0000000..001f2cb --- /dev/null +++ b/doc/psl/impl_guide.html @@ -0,0 +1,463 @@ + + + + + + + The PLIB Scripting Language: Implementation Guide. + + +  + + + + +
+
+

The PSL Implementation Guide.

+
By Steve Baker
+
+

Introduction

+This document describes the virtual machine that the PSL byte code +interpreter implements. +

+The machine has 65536 bytes of instruction memory (and hence, 16 bit +code addresses) and 256 variables (and hence 8 bit data addresses). +Each variable can be a 32 bit integer, an IEEE single precision float +or a character string of arbitary length. +

+In addition, there is a 256 element stack - each entry of which can +contain any PSL data type. +

+The machine has just two registers - the Program Counter (PC) and +the Stack Pointer (SP) - neither of which are accessible to running +programs directly. +

The Instruction Set

+Each instruction consists of a one byte opcode and some number of +bytes of data. +

+The hex numbers for these opcodes are listed in plib/src/psl/pslOpcodes.h +

+

OPCODE_BAD

+INTRUCTION BYTES: 1
+ + + + + +
+EFFECT: + Produces a 'Suspicious Opcode' error message and halts the program.
+ Generally, programs + that run amok for some reason (eg an error in the compiler) will + hit a zero byte fairly soon afterwards. Hence instruction 0x00 + is reserved to be the BAD instruction. Other unrecognised + instructions are also flagged as errors - but it's useful to + explicitly reserve opcode 0x00 for this function due to the + high probability of it being executed by broken programs.
+ +

OPCODE_LINE_NUMBER

+INTRUCTION BYTES: 3 + + + + + +
+EFFECT: + Updates the 'current line number' from the two bytes + embedded in the instruction.
+ +

OPCODE_PUSH_INT_CONSTANT

+ +INTRUCTION BYTES: 5 + + + + + +
+EFFECT: + Takes four bytes from the instruction and pushes them + onto the stack as an integer.
+ +

OPCODE_PUSH_FLOAT_CONSTANT

+INTRUCTION BYTES: 5 + + + + + +
+EFFECT: + Takes four bytes from the instruction and pushes them + onto the stack as a float.
+ +

OPCODE_PUSH_STRING_CONSTANT

+INTRUCTION BYTES: 1 + strlen string + 1 + + + + + +
+EFFECT: + Takes a null-terminated string from the instruction + stream and pushes it onto the stack.
+ +

OPCODE_GET_PARAMETER

+INTRUCTION BYTES: 3 + + + + + +
+EFFECT: + Fetches the value of a function's parameter from the + depths of the stack and puts it into a local variable. +

+ The second byte of the instruction is the + index of the variable. The third byte is a small + integer offset - which is the number of the parameter + you want. +

+ Look at the number two down from the top of the stack + (which should be + the number of parameters of a recently called + function). +

+ Now copy the stack element at + sp - ( nargs + 2 ) + offset + into the variable.

+ +

OPCODE_POP

+INTRUCTION BYTES: 1 + + + + + +
+EFFECT: + Throws away the top element of the stack.
+ +

OPCODE_CALLEXT

+INTRUCTION BYTES: 3 + + + + + +
+EFFECT: + The second byte of the instruction is the index of + a PSL 'extension function', the third + is the number of arguments being passed to it. +

+ Pop that number of values off the stack and pass them + to the extension function. +

+ Call the extension function. + Push the result onto the stack.

+ +

OPCODE_CALL

+INTRUCTION BYTES: 6 + + + + + +
+EFFECT: + [The number of aguments will already have been pushed + onto the stack.] +

+ The four bytes after the instruction is the function address. + The fifth byte is the number of arguments. +

+ Push return address.
+ PC = address of function. +

+ popNumber ( &result ) ;
+    pc = popInt () ;
+    nargs = popInt () ;
+    popVoid ( nargs ) ;
+ pushNumber ( &result ) ;

+ +

OPCODE_STACK_DUPLICATE

+INTRUCTION BYTES: 1 + + + + + +
+EFFECT: + Duplicate the top element of the stack.
+ +

OPCODE_EXCHANGE

+INTRUCTION BYTES: 1 + + + + + +
+EFFECT: + Exchange the top two elements of the stack.
+ + +

OPCODE_LESS

+

OPCODE_LESSEQUAL

+

OPCODE_GREATER

+

OPCODE_GREATEREQUAL

+

OPCODE_NOTEQUAL

+

OPCODE_EQUAL

+

OPCODE_ADD

+

OPCODE_SUB

+

OPCODE_SHIFTLEFT

+

OPCODE_SHIFTRIGHT

+

OPCODE_OROR

+

OPCODE_ANDAND

+

OPCODE_OR

+

OPCODE_AND

+

OPCODE_XOR

+

OPCODE_DIV

+

OPCODE_MOD

+

OPCODE_MULT

+INTRUCTION BYTES: 1 + + + + + +
+EFFECT: + Pop the top element from the stack and operate on it + and the next element down - leaving the result on + the stack in it's place. So (for example) if the + operation was 'SUB' (Subtract), and A is on top of + the stack and B is beneath it - then the result of + this operation would be to leave (B-A) on the stack + with no sign of either A or B. +

+ The 'ADD' operator also works with strings by concatenating + them.

+ +

OPCODE_NOT

+

OPCODE_TWIDDLE

+

OPCODE_NEG

+INTRUCTION BYTES: 1 + + + + + +
+EFFECT: + Perform the C unary '!', '~' or '-' operator on the top + element of the stack.
+ +

OPCODE_PAUSE

+INTRUCTION BYTES: 1 + + + + + +
+EFFECT: + Informs application program that the script wishes + to be paused until next frame.
+ +

OPCODE_HALT

+INTRUCTION BYTES: 1 + + + + + +
+EFFECT: + Informs the application that the script wishes to halt. + Even if the application ignores this request, the script + will continue looping at this location for ever.
+ +

OPCODE_PEEK_JUMP_TRUE

+

OPCODE_PEEK_JUMP_FALSE

+INTRUCTION BYTES: 3 + + + + + +
+EFFECT: + The two bytes at the end of the instruction contain + an address. Inspect the number off the top of the stack + (without popping it) - and branch to the specified + instruction if the value is TRUE (or FALSE as applicable).
+ +

OPCODE_JUMP_TRUE

+

OPCODE_JUMP_FALSE

+INTRUCTION BYTES: 3 + + + + + +
+EFFECT: + The two bytes at the end of the instruction contain + an address. POP the number off the top of the stack + (without popping it) - and branch to the specified + instruction if the value is TRUE (or FALSE as applicable).
+ +

OPCODE_JUMP

+INTRUCTION BYTES: 3 + + + + + +
+EFFECT: + The two bytes at the end of the instruction contain + an address. Jump to that address.
+ +

OPCODE_PUSH_VARIABLE

+INTRUCTION BYTES: 2 + + + + + +
+EFFECT: + The second byte of the instruction is the index of + a variable. The value of that variable is pushed onto + the stack.
+ +

OPCODE_POP_ADD_VARIABLE

+

OPCODE_POP_SUB_VARIABLE

+

OPCODE_POP_MUL_VARIABLE

+

OPCODE_POP_MOD_VARIABLE

+

OPCODE_POP_DIV_VARIABLE

+

OPCODE_POP_AND_VARIABLE

+

OPCODE_POP_OR_VARIABLE

+

OPCODE_POP_XOR_VARIABLE

+

OPCODE_POP_SHL_VARIABLE

+

OPCODE_POP_SHR_VARIABLE

+INTRUCTION BYTES: 1 + + + + + +
+EFFECT: + Three things are on the stack when this function is called.
+ The thing on top is the result of an expression evaluation.
+ The thing beneath that is the index of a variable.
+ The thing beneath that is the dimension of the variable.
+ The value is added to/subtracted from/multiplied by/etc + the variable - and stored back into the variable.
+ The new value of the variable is left on the stack.
+ +

OPCODE_POP_VARIABLE

+INTRUCTION BYTES: 1 + + + + + +
+EFFECT: + Three things are on the stack when this function is called.
+ The thing on top is the result of an expression evaluation.
+ The thing beneath that is the index of a variable.
+ The thing beneath that is the dimension of the variable.
+ The value is stored into the variable.
+ The new value of the variable is left on the stack.
+ +

OPCODE_SET_INT_ARRAY

+

OPCODE_SET_FLOAT_ARRAY

+

OPCODE_SET_STRING_ARRAY

+INTRUCTION BYTES: 2 + + + + + +
+EFFECT: + The second byte of the instruction is the index of an array + variable.
+ On the top of the stack is an integer.
+ This instruction allocates that number of elements of storage to + the array.
+ +

OPCODE_SET_INT_VARIABLE

+

OPCODE_SET_FLOAT_VARIABLE

+

OPCODE_SET_STRING_VARIABLE

+INTRUCTION BYTES: 2 + + + + + +
+EFFECT: + The second byte of the instruction is the index of a variable.
+ That variable is created, set to the appropriate type and + initialised appropriately.
+ +

OPCODE_FETCH

+INTRUCTION BYTES: 1 + + + + + +
+EFFECT: + The index of a variable is on top of the stack.
+ The thing beneath that is the dimension of the variable.
+ Replace those with the value of that variable.
+ +

OPCODE_INCREMENT_FETCH

+

OPCODE_DECREMENT_FETCH

+INTRUCTION BYTES: 1 + + + + + +
+EFFECT: + The index of a variable is on top of the stack.
+ The thing beneath that is the dimension of the variable.
+ Replace those + with the value of that variable. Post-increment/decrement the + variable.
+ +

OPCODE_INCREMENT_LVALUE

+

OPCODE_DECREMENT_LVALUE

+INTRUCTION BYTES: 1 + + + + + +
+EFFECT: + The index and dimension of a variable is on top of the stack.
+ Increment/decrement the variable leaving the stack + contents undisturbed.
+ +
+
+Steve J. Baker. <sjbaker1@airmail.net>
+ + diff --git a/doc/psl/index.html b/doc/psl/index.html new file mode 100644 index 0000000..37ed840 --- /dev/null +++ b/doc/psl/index.html @@ -0,0 +1,55 @@ + + + + + + + The PLIB Scripting Language. + + +  + + + + +
+
+

PSL: PLIB's Scripting Language.

+
By Steve Baker
+
+ +

Introduction

+Whilst applications can use any suitable scripting +language (Python, PERL, Lua, etc) in conjunction with PLIB, there are +attractions to using PLIB's own scripting language: PSL. +

+In particular, in using PSL, you do not add any dependancies on +your application. If the end user has the correct version of PLIB +installed - then the scripting language is already there - for sure. +

+PSL is a very light-weight C-like language with some features borrowed +from C++. It's also 'stackless' and very friendly to games applications. +

+There are two PSL documents: +

+

+Each application can extend PSL by providing additional built-in +functions - so if you are a PSL programer then you'll probably need to +read the documentation for whatever PSL-enabled application +you are writing for. If you are writing a PSL-enabled application, then +you'd better sit down and WRITE that document! +


+
+Steve J. Baker. <sjbaker1@airmail.net>
+ + diff --git a/doc/psl/prog_guide.html b/doc/psl/prog_guide.html new file mode 100644 index 0000000..41615d7 --- /dev/null +++ b/doc/psl/prog_guide.html @@ -0,0 +1,209 @@ + + + + + + + The PLIB Scripting Language: Programming Guide. + + +  + + + + +
+
+

The PLIB Scripting Language Programming Guide

+
By Steve Baker
+
+

Introduction

+ +This document explains how to write PSL programs. + +

+ +How you actually run those programs depends on which PSL-enabled +application you are running. There is a stand-alone PSL interpreter +in plib/examples/src/psl/psl_demo - but it doesn't include any +application-specific language extensions - so a PSL program +that's written for a specific application may not run +on psl_demo. + +

+ +However, psl_demo is great for learning to write PSL scripts. + +

The PSL Language

+ +PSL is designed to be as close to the C Programming +Language - although we +cut a few corners - we extended the language in a few places - and +we consciously omitted other features that are dangerous in a +scripting language. + +

+ +The following C features are implemented much as you'd expect: +

    +
  • Types 'void', 'int' and 'float' (and arrays of those things). +
  • Function definitions. +
  • Global variable definitions. +
  • Statement types: +
      +
    • Local variable definitions. +
    • Static variable definitions. +
    • "return" +
    • "break" +
    • "continue" +
    • "for" +
    • "do/while" +
    • "switch/case/default" +
    • "while" +
    • "if" +
    • "if/else" +
    • "{}" compound statements. +
    • Assignment statements. +
    • Procedure calls. +
    +
  • Most Arithmetic operators. +
  • Comments '/*' '*/'. +
  • C preprocessor directives: +
      +
    • "#include" +
    • "#define" without parameters. +
    • "#undef" +
    • "#ifdef/#endif" +
    • "#ifdef/#else/#endif" +
    • "#ifndef/#endif" +
    • "#ifndef/#else/#endif" +
    +
  • Special characters in strings: +
      +
    • "\n" +
    • "\r" +
    • "\a" +
    • "\b" +
    • "\f" +
    • "\t" +
    • "\\" +
    • "\"" +
    +
  • Recursion, etc. +
+ +Some new features have been added that are not part of C: +
    +
  • "pause" -- Pause the program until next frame. +
  • "string" data type (and arrays of strings). +
  • Casts are unnecessary between compatible types. +
  • C++ style '//' comments. +
  • C++ style local variable declarations. +
+Some features of C are NOT IMPLEMENTED in PSL: +
    +
  • Pointers. +
  • Casts. +
  • Dynamic Memory Allocation. +
  • ',' and '?:' operators in expressions. +
  • "static", "auto" and "register" storage class reserved words. +
  • "char", "short", "unsigned", "signed", "long", "double". +
  • "typedef" +
  • "enum", "union", bitfields. +
  • "goto". +
  • "#if" +
  • "#pragma" +
  • "#define" with parameters. +
  • 'f' and 'l' suffixes for float and long numbers. +
  • All preprocessor directives must have the '#' as the + very first character on the line - they cannot be + preceded with whitespace. +
+ +The following features are "NOT IMPLEMENTED YET" - but will +hopefully arrive soon: +
    +
  • Multiple variable definitions like 'int i, j, k ;' +
  • Structs. +
  • '\' to escape the end-of-line character in strings and macro's. +
  • Parameter passing by name. +
  • Many of C's standard library functions are needed. +
+ +

Compatibility Notes:

+

C++ style local variables.

+With PSL's C++ style locals, you can say things like this: +
+
+    for ( int i = 0 ; i < 10 ; i++ )  /* Do something */ ;
+
+
+In standard C++, the scope of the variable 'i' is from it's +declaration to the end of the 'for' loop. However, Microsoft's +Visual C++ uses an obsolete version of the C++ standard that +allows the scope of 'i' to continue to the end of the block +that contains the for loop. So: +

+WINDOWS USERS BEWARE: PSL IMPLEMENTS THIS CORRECTLY - *NOT* LIKE +MSVC. + +

Hard Limits

+Currently there are hard limits in many places - the number of +variables, the size of the program, the depth of nesting, etc. +These limits will gradually be removed as PSL is developed. + +

Debugging PSL Programs

+ +Specific PSL-enabled applications may have their own +special features to assist with debugging - but all +PSL-enabled applications support several 'shell variables' +that enable certain debugging features. +

+When using a command line shell, you can set these +variables using one of the following commands before +you run your application: +

+    setenv VARIABLE value     -- csh or tcsh
+    export VARIABLE=value     -- bash or sh
+    set VARIABLE=value        -- DOS shell
+
+

Byte-Code Dump

+It's possible to view the byte code that PSL generated +by setting the shell variable 'PSL_DUMP' to either: +
    +
  • never (the default) -- Never produce a dump unless + the application demands it. +
  • on_error -- Produce a dump whenever the PSL program + fails to compile for whatever reason. +
  • always -- Always produce a dump after the PSL program + finishes compiling. +
+

Byte-Code Execution Trace

+It's possible to view the byte code as it's executed +by setting the shell variable 'PSL_TRACE' to either: +
    +
  • never (the default) -- Never produce a trace unless + the application demands it. +
  • always -- Always produce a trace. +
+When the execution trace is enabled, extra instructions will be +inserted into the byte code to enable the PSL interpreter to +produce debug indicating which lines of the source code are +being traced. +

Byte-Code Stack Display

+If you have PSL_TRACE turned on (either via the config variable or +by the application program), then the shell variable 'PSL_STACK' +can be set to display the contents of the top eight stack locations +as the program is traced. If PSL_TRACE is disabled then PSL_STACK +has no effect. +
    +
  • never (the default) -- Never produce stack dumps + within a trace. +
  • always -- Always produce a stack dump within trace. +
+
+
+Steve J. Baker. <sjbaker1@airmail.net>
+ + + diff --git a/doc/puAux.png b/doc/puAux.png new file mode 100644 index 0000000..749fb94 Binary files /dev/null and b/doc/puAux.png differ diff --git a/doc/puAux/index.html b/doc/puAux/index.html new file mode 100644 index 0000000..a8373ea --- /dev/null +++ b/doc/puAux/index.html @@ -0,0 +1,54 @@ + + + + + SSG Auxiliary Libraries. + + + + + + + + + + +
+

PUI Auxiliary Libraries.

+
+ by Steve Baker +
+

Introduction

+ + + + +
+PLIB/puAux is a suite of auxiliary libraries that build +higher level classes on top of the basic PUI classes. +

+

+

+

Conventions

+puAux is installed and named with the same +conventions as the base PLIB libraries. +
+ie: +
+   /usr/include/plib/puAux.h
+   /usr/lib/libplibpuaux.a
+
+

+PLIB/puAux functions, classes and constants are all +named with an 'pua' or 'PUA' prefix. +
+

+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+ + + + diff --git a/doc/pui/BasicPUI.html b/doc/pui/BasicPUI.html new file mode 100644 index 0000000..f7cd4ab --- /dev/null +++ b/doc/pui/BasicPUI.html @@ -0,0 +1,636 @@ + + + + + + + + + BasicPUI + + + +
+

+Introduction to Using the Picoscopic User Interface

+ +
+

+John F. Fay

+ +
+

October 18, 2000

+(Updated by Sebastian Ude on October 02, 2001) +
+ +

+Contents

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1.Introduction:  +Graphical User Interfaces and Windowed Programs
2.Elementary PUI
2.1 Creating User Interface +Widgets
2.2 Invoking PUI
2.3 Widget Callbacks
3.Conclusion
+ +

+1.  Introduction:  +Graphical User Interfaces and Windowed Programs

+The Picoscopic User Interface (PUI) is designed to be a simple, easy-to-use +graphical user interface.  It is based on the OpenGL graphics language +and requires a windowing system, either the OpenGL Utility Toolkit (GLUT) +or another similar one.  The gentle reader is assumed either to be +familiar with OpenGL and his windowing system or at least to have their +manuals at hand. +

Basic to a GUI is the idea of a widget.  A widget is something +that appears on the computer screen and which transfers data from the user +to the program or from the program to the user.  The user can activate +a widget by pressing a key, clicking a mouse button, or by using some other +input device.  This lets the user send information to the program.  +A widget can also display text or a graphic, allowing the program to transfer +information to the user. +

A windowing system requires a specific style of program which differs +from a text-based program in several fundamental ways.  First, instead +of starting at the beginning of a problem and stopping at the end, a windowed +program starts by creating the windows and then enters an infinite loop +in which it responds to user inputs.  Second, instead of having a +self-contained hierarchy of functions which call each other, a windowed +program is controlled by the windowing system which calls functions as +it sees fit.  The following diagram shows the structure of a typical +windowed program. +

+
+        +------------------+
+        |   Main Program   |  The application developer
+        | Set up window(s) |  supplies this.
+        |   and widget(s)  |
+        +------------------+
+                 |
+                 V
+         +----------------+
+         | Window Manager |   The window manager library
+         |  (like GLUT)   |   supplies this.
+         +----------------+
+                 |
+          +------+--------+---------------+---------------+----> etc.
+          |               |               |               |
+          V               V               V               V
+     +----------+    +----------+    +----------+    +----------+
+     |  Window  |    |  Window  |    |  Window  |    |  Window  |  The application
+     |  Mouse   |    | Keyboard |    |   Idle   |    | Display  |  developer
+     | Callback |    | Callback |    | Callback |    | Callback |  supplies these.
+     +----------+    +----------+    +----------+    +----------+
+          |               |               |               |
+          V               V               V               V
+     +----------+    +----------+     May call       +----------+
+     |   PUI    |    |   PUI    |   PUI functions    |   PUI    |  PUI
+     |  Mouse   |    | Keyboard |    for default     | Display  |  supplies
+     | Function |    | Function |     behaviors      | Function |  these.
+     +----------+    +----------+                    +----------+
+          |               |
+          +-------+-------+
+                  |
+          +-------+-------+---------------+------> etc.
+          |               |               |
+          V               V               V
+     +----------+    +----------+    +----------+
+     | Widget 1 |    | Widget 2 |    | Widget 3 |  The application developer
+     | Callback |    | Callback |    | Callback |  supplies these.
+     +----------+    +----------+    +----------+
+
+
+

The functions that the application developer supplies are called "callbacks" +because the windowing system or user interface system "calls back" into +the application. +

A windowed program with a user interface, then, consists of a main program +and a set of callbacks.  The callbacks may invoke other function in +turn, but these are all arranged in hierarchical trees underneath the callbacks. +

A windowed program executes differently from a typical hierarchical +program as well.  It begins with the main program setting up the window(s) +and the user interface.  The main program then calls the window manager, +which contains an infinite loop and never returns control to the main program.  +(GLUT in particular has this behavior; I cannot speak for all window managers.)  +When the window manager needs to redraw the display that is shown on the +screen, it calls the application's Window Display Callback.  When +the user moves the mouse or clicks a mouse button, the window manager calls +the application's Window Mouse Callback.  When the user presses a +key on the keyboard, the window manager calls the application's Window +Keyboard Callback.  Other input devices cause the window manager to +call other callbacks in the application.  Finally, if the user hasn't +done anything for a while, the window manager will call the application's +Window Idle Callback. +

In building a window callback, the application developer must be sure +to call the appropriate PUI functions.  The applications's Window +Mouse Callback, for example, must call the PUI mouse function "puMouse" +if the user interface is to process a mouse click.  The application's +Window Display Callback, besides rendering any graphics in the window, +must also call the PUI display function "puDisplay" in order to display +the widgets in the user interface. +

When the application developer's window callback calls the appropriate +PUI function, PUI determines which (if any) widget the user has just activated +with his mouse, keyboard, or other input device.  PUI then calls that +widget's callback function which the application developer must supply +and which provides the actual heart of the interface.  The callback +for an input widget will probably read the text that the user has typed +there and pass it on to the application.  The callback for a button +widget may turn something in the program on or off.  What a callback +does is limited only by the application developer's imagination. +

+2.  Elementary PUI

+Using the Picoscopic User Interface on an elementary level requires three +things:  setting up the user interface widgets, invoking PUI from +the window callbacks, and supplying the widget callbacks. +

PUI was written in C++, designed to be invoked from C++ programs.  +The following text and examples will assume a program written in C++. +

+2.1 Creating User Interface +Widgets

+Most (or all) widgets have certain properties in common.  These are: +
    +
  • +position - the x- and y-coordinates, in pixels, of the lower left-hand +corner of the widget relative to the lower left-hand corner of the window
  • + +
  • +size - the width and height of the widget, in pixels
  • + +
  • +callback - the application program's function which is called when the +widget is activated
  • + +
  • +value - a number or character string that is associated with the widget
  • + +
  • +label - text that is printed next to the widget
  • + +
  • +legend - text that is printed inside the widget (some widgets only)
  • +
+PUI supports other widget properties, but these are enough to allow the +application developer to create a simple user interface. +

Each widget in the Picoscopic User Interface is an object in C++.  +The application developer creates a widget by defining a variable to point +to the object and creating a new object: +

+
+  puButton *button = new puButton ( 10, 10, 100, 30 ) ;
+
+
+

To set the properties of a widget, the application developer calls methods +in the object: +

+
+  button->setPosition ( x, y ) ;                  // Sets the position of the widget to
+                                                         (x, y)
+  button->setSize ( w, h ) ;                      // Sets the size of the widget to (w, h)
+  button->setCallback ( widget_cb ) ;             // Sets the callback to
+                                                         "void widget_cb ( puObject *ob )"
+  button->setLegend ( "Press Me" ) ;              // Sets the legend
+  button->setLabel ( "A Button:" ) ;              // Sets the label
+  button->setLabelPlace ( PUPLACE_LOWER_LEFT ) ;  // Makes the label print on the button's
+                                                          left
+
+
+

Other allowed values for the label position are: + +

    +
  • PUPLACE_ABOVE_LEFT +
  • PUPLACE_ABOVE_RIGHT +
  • PUPLACE_TOP_LEFT +
  • PUPLACE_TOP_CENTERED +
  • PUPLACE_TOP_RIGHT +
  • PUPLACE_UPPER_LEFT +
  • PUPLACE_UPPER_RIGHT +
  • PUPLACE_CENTERED_LEFT +
  • PUPLACE_CENTERED_RIGHT +
  • PUPLACE_LOWER_LEFT +
  • PUPLACE_LOWER_RIGHT (default) +
  • PUPLACE_BOTTOM_LEFT +
  • PUPLACE_BOTTOM_CENTERED +
  • PUPLACE_BOTTOM_RIGHT +
  • PUPLACE_BELOW_LEFT +
  • PUPLACE_BELOW_RIGHT +
+

For a detailed description of these have a look at the +PUI Programmers Guide. +

All of these calls are optional.  If the application developer +does not want to label a widget, he simply does not call "setLabel" or +"setLabelPlace".  Similarly, if he has set the widget's position and +size while creating the widget, there is no need to call "setPosition" +or "setSize". +

The following subsections describe some of the widget types that PUI +supports. +

+2.1.1 Button

+The button ("puButton") is a rectangle, usually containing a legend, which +is activated when the user clicks the mouse on it.  It has two possible +values, off and on; its actual value changes each time the user clicks +on it. +

The button has two possible methods of construction: +

    +
  • +puButton ( x1, y1, x2, y2 ) - creates a button with lower left-hand coordinates +of (x1, y1) and with upper right-hand coordinates of (x2, y2)
  • + +
  • +puButton ( x1, y1, "text" ) - creates a button with lower left-hand coordinates +of (x1, y1) and containing the text "text".  The size is set by the +size of the text.
  • +
+ +

+2.1.2 Button Box

+The button box ("puButtonBox") is a large rectangle containing a set of +buttons, each with text next to it, which the user can select.  It +is sometimes called a radio button.  It is created by creating a null-terminated +list of labels and then by calling the constructor function: +
+
+  char **labels = { "Label1", "Label2", "This is Label3", "Four", NULL } ;
+  puButtonBox my_box = new puButtonBox ( x1, x2, y1, y2, labels, <0|1> ) ;
+
+
+

This creates a button box with lower left-hand coordinates of (x1, y1) +and upper right-hand coordinates (x2, y2).  The number of buttons +is specified by the number of entries in the "labels" array; each string +before the NULL gets a button.  The final argument in the constructor +specifies whether the user can select multiple buttons (0) or whether selecting +a new button will deactivate the previously-selected button (1). +

The button box should not be given a legend. +

+2.1.3 Frame

+The frame ("puFrame") is a rectangular area that provides a background +for other widgets.  It should be defined before any other widgets +that go inside it or else it will cover them up.  It is constructed +by the following function call: +
    +
  • +puFrame ( x1, y1, x2, y2 ) - creates a frame with lower left-hand coordinates +of (x1, y1) and with upper right-hand coordinates of (x2, y2)
  • +
+The frame should not be given a legend.  It does not support a callback +either. +

+2.1.4 Input Box

+The input box ("puInput") is a rectangular area into which the user can +type text.  The user must first click the mouse inside the area and +then type the text.  He concludes by pressing <Enter> or <Tab> +or by clicking the mouse outside the input box. +

An input box is constructed by the following function call: +

    +
  • +puInput ( x1, y1, x2, y2 ) - creates an input box with lower left-hand +coordinates of (x1, y1) and with upper right-hand coordinates of (x2, y2)
  • +
+The input box should not be given a legend. +

+2.1.5 Menu Bar

+The menu bar ("puMenuBar") is easily the most complicated widget written +up here.  It consists of a horizontal bar containing buttons which +the user can click on.  The bar is always situated on the left-hand +edge of the window and is usually in the upper left-hand corner.  +It is constructed by the following function call: +
+
    +
  • +puMenuBar *menu = puMenuBar ( y ) - creates a menu bar with the lower left-hand +corner "y" pixels above the lower left-hand corner of the window.  +A value of -1 for "y" will put the menu bar in the upper left-hand corner +of the window.
  • +
+ +


Once the menu bar has been constructed, it must be loaded with its +entries and submenus.  A submenu is the list that drops down when +the user clicks on an entry in the menu.  A typical menu bar will +have the entries "File", "Edit", "Search", and "Help".  Under the +"File" entry is a submenu with entries "New", "Open", "Save", "Save As", +a separator, "Page Setup", "Print", another separator, and "Exit".  +Each entry in the submenu has its own widget callback function.  To +create a submenu, the application developer must first create two null-terminated +lists of character strings and callback functions: +

+
+  char      *file_submenu   [] = { "Exit", "-----",  "Print",  "Page Setup", "-----",
+                            "Save As",  "Save",  "Open",  "New", NULL } ;
+  puCallback file_submenu_cb[] = { exit_cb,    NULL, print_cb, page_setup_cb,    NULL,
+                           save_as_cb, save_cb, open_cb, new_cb, NULL } ;
+
+
+

Notice here that the submenu entries are placed in the list from bottom +to top.  After the last character string is a NULL entry; this tells +PUI that there aren't any more entries in the submenu.  The callbacks +for the separators are also null, indicating that there is no callback +for the separator.  The submenu is added to the menu bar with a call +to the "add_submenu" function: +

+
+  menu->add_submenu ( "File", file_submenu, file_submenu_cb ) ;
+
+
+

Further calls to "add_submenu" add the other submenus: +

+
+  char      *edit_submenu   [] = {  "Select All", "-----",  "Paste",  "Copy",  "Cut",
+                            "-----",  "Undo", NULL } ;
+  puCallback edit_submenu_cb[] = { select_all_cb,    NULL, paste_cb, copy_cb, cut_cb,
+                               NULL, undo_cb, NULL } ;
+  menu->add_submenu ( "Edit", edit_submenu, edit_submenu_cb ) ;
+
+  char      *search_submenu   [] = {  "Find Next",  "Find", NULL } ;
+  puCallback search_submenu_cb[] = { find_next_cb, find_cb, NULL } ;
+  menu->add_submenu ( "Search", search_submenu, search_submenu_cb ) ;
+
+  char      *help_submenu   [] = {  "About",  "Help", NULL } ;
+  puCallback help_submenu_cb[] = { about_cb, help_cb, NULL } ;
+  menu->add_submenu ( "Help", help_submenu, help_submenu_cb ) ;
+
+
+

When the last submenu has been added, the application developer must +close the menu bar: +

+
+  menu->close() ;
+
+
+

This is absolutely necessary or else PUI will think that any widgets +the application defines later are supposed to go into the menu bar. +

The menu bar does not support a legend.  It does not support a +callback itself, although all the entries in the submenus certainly do +support callbacks.  Repositioning and resizing a menu bar will be +problematic as well.  There may be an occasion when a menu bar can +take a label, but this would be rare. +

+2.1.6 One-Shot Button

+The one-shot button ("puOneShot") is a button whose value is always reset +immediately to zero after it has been activated.  In all other respects +it is the same as the regular button.  It is created in the same way +as the button: +
    +
  • +puOneShot ( x1, y1, x2, y2 ) - creates a one-shot button with lower left-hand +coordinates of (x1, y1) and with upper right-hand coordinates of (x2, y2)
  • + +
  • +puOneShot ( x1, y1, "text" ) - creates a one-shot button with lower left-hand +coordinates of (x1, y1) and containing the text "text".  The size +is set by the size of the text.
  • +
+ +

+2.1.7 Text Box

+The text box ("puText") is an output-only widget which displays a character +string.  It is created by the following constructor: +
    +
  • +puText ( x, y ) - creates a text box at the point (x, y) in the window
  • +
+The application actually adds the text by assigning a label and a label +place to the text box.  The label place will determine where relative +to the position of the text box the text itself will appear. +

+2.2 Invoking PUI

+The summary of invoking PUI is very simple: +
    +
  • +At the beginning of the program, before creating any widgets, the application +must call the function "puInit ()".
  • + +
  • +If the application developer wants PUI to process a mouse click, he must +have the application call the function "puMouse ( button, updown, x, y +)".
  • + +
  • +If the application developer wants PUI to process a mouse motion, he must +have the application call the function "puMouse ( x, y )".
  • + +
  • +If the application developer wants PUI to process a key from the keyboard, +he must have the application call the function "puKeyboard ( key, updown +)".
  • + +
  • +If the application developer wants PUI to display the user interface, he +must have the application call the function "puDisplay ()".
  • +
+The application developer must create window callbacks for the window manager +to call when the user interacts with the computer.  The following +are taken from GLUT, but another window manager will have similar callback +requirements. +

+2.2.1 Main Program Code

+In the main program, the application developer usually places the following +or similar statements: +
+
+  // Create the GLUT window and the OpenGL context
+
+  glutCreateWindow       ( "PUI Application"  ) ;
+
+  // Set up the GLUT window callbacks
+
+  glutDisplayFunc        ( displayfn  ) ;  // display the window
+  glutMouseFunc          ( mousefn    ) ;  // process mouse clicks
+  glutMotionFunc         ( motionfn   ) ;  // process mouse moves
+  glutPassiveMotionFunc  ( motionfn   ) ;
+  glutKeyboardFunc       ( keyboardfn ) ;  // process key presses
+  glutIdleFunc           ( displayfn  ) ;  // what to do when nothing's happening
+
+  // Initialize PUI
+
+  puInit () ;
+
+  // Set up the widgets here
+
+

+2.2.2 Window Callbacks

+The application's window callbacks should generally look like this.  +Again, these are written assuming GLUT; other window managers should be +similar. +
+
+  void displayfn ( void )
+  {
+    // stuff to display any non-PUI drawings
+
+    // update any PUI widgets that update by themselves ... like a timer display
+
+    // redisplay PUI
+
+    puDisplay () ;
+
+    // Finish up
+
+    glutSwapBuffers () ;
+    glutPostRedisplay () ;
+  }
+
+  void mousefn ( int button, int updown, int x, int y )
+  {
+    // Invoke the PUI mouse function
+
+    puMouse ( button, updown, x, y ) ;
+    glutPostRedisplay () ;
+  }
+
+  void motionfn ( int x, int y )
+  {
+    // Invoke the PUI mouse motion function
+
+    puMouse ( x, y ) ;
+    glutPostRedisplay () ;
+  }
+
+  void keyboardfn ( unsigned char key, int, int )
+  {
+    // Invoke the PUI keyboard function
+
+    puKeyboard ( key, PU_DOWN ) ;
+    glutPostRedisplay () ;
+  }
+
+
+

+2.2.3 Miscellaneous Other Tidbits

+If the application developer wishes to delete a widget, he should not delete +the object directly.  Instead he should call the PUI function "puDeleteObject +( ob )" with his widget pointer as the argument. +

+2.3 Widget Callbacks

+The final pieces to the puzzle are the widget callbacks.  These are +of the form +
+
+  void widget_cb ( puObject *ob )
+  {
+    // code goes here
+  }
+
+
+

where "puObject" is the C++ type for a generic widget.  When PUI +calls a widget callback, it passes to it the address of the widget whose +activation caused the callback.  This is useful because it allows +a single callback for multiple widgets: +

+
+  void widget_cb ( puObject *ob )
+  {
+    if ( ob == button )  // the button from section 2.1
+    {
+      ...
+    }
+    else if ( ob == my_box )  // the button box from section 2.1.2
+    {
+      ...
+    }
+    else
+    {
+      printf ( "Error - unknown widget" ) ;
+    }
+  }
+
+
+

A widget callback needs to be either a regular function (global +or defined in the same file that contains the widget's definition) or a +static member function of a class.  It cannot be a regular member +function of a class. +

+2.3.1 Widget Values

+It is frequently very useful in a callback to know the value of a widget.  +A PUI widget has an integer value, a floating-point value, and a character +string value.  These values are kept synchronized as much as possible.  +For example, if the application assigns an integer value to a widget, the +floating-point value is set equal to the integer and the integer is printed +into the character string. +

An application program can use the following function to retrieve the +value of a PUI widget ("ob" is the pointer to the object): +

+
+  int ivalue1 = ob->getValue () ;  // No argument, return the integer value
+
+  int ivalue2 ;
+  ob->getValue ( &ivalue2 ) ;  // Place the integer value in the argument
+
+  float fvalue ;
+  ob->getValue ( &fvalue ) ;  // Place the floating-point value in the argument
+
+  char svalue[PUSTRING_MAX] ;  // Create a string
+  ob->getValue ( svalue ) ;    // Copy the string value into the argument
+                               // Note that the argument is of type "char *"
+
+  char *sptr ;
+  ob->getValue ( &sptr ) ;  // Have the pointer point to the string value
+                            // Note that the argument is of type "char **"
+
+
+

The values of the various widgets have the following meanings: +

    +
  • +Button:  0 - turned off; 1 - turned on
  • + +
  • +Button Box:  If only one button can be activated at a time, the value +is the number of the button which is activated.  If multiple buttons +can be activated at once, then the bits in the integer value corresponding +to the activated buttons are one and the bits corresponding to the inactive +buttons are zero.
  • + +
  • +Frame:  no value
  • + +
  • +Input:  the string value is the character string that the user has +typed in
  • + +
  • +Menu Bar:  no value
  • + +
  • +One Shot Button:  value is always zero
  • + +
  • +Text:  no value
  • +
+ +

+3.  Conclusion

+This has been offered as an introduction to the Picoscopic User Interface.  +It makes no warranty as to its accuracy although efforts have been made +to make it correct.  It is offered in the hope that the gentle reader +will find it useful. +

The PUI has considerably greater capabilities than have been listed +here.  There are well over a dozen additional types of widgets.  +Additionally, the application developer can do many more things with this +widgets than have been described here. +

"As to more than these, my son, beware.  Of the making of many +books there is no end, and in much study there is weariness for the flesh." +- Ecclesiastes 12:12 + + diff --git a/doc/pui/FAQ.html b/doc/pui/FAQ.html new file mode 100644 index 0000000..1892769 --- /dev/null +++ b/doc/pui/FAQ.html @@ -0,0 +1,171 @@ + + + + + + + The Picoscopic User Interface: FAQ list. + + + + + + + + +
+Imagine Pooh Here + +

PUI: A Picoscopic User Interface

+

Frequently Asked Questions List.

+By Steve Baker +
+Here are some questions that have been asked about PUI: +

+

+


+

+

Q1: Can I build a Windoze DLL for PUI?

+ + Not from the present sources. Some Windoze compilers + require an '_export' directive on functions or classes + that are to be exported from the DLL. This is ugly and + I refuse to add non-standard syntax to the library just + to pander to a disgusting Windoze-ism. PUI is a VERY + small library and there is really no need for it to + be a DLL anyway. + +

Q2: Which versions of OpenGL and GLUT will support PUI?

+ + In principal, any version of GLUT since 2.0 and any + reasonably compliant OpenGL (including Mesa) should + be happy to support PUI. + +

Q3: Which machines/operating systems can run PUI?

+ + AFAIK, any machine with C++, OpenGL (or Mesa) and + GLUT will run PUI programs without problems. + +

Q4: Is PUI stable? Are there known bugs?

+ + So far, there have only been a couple of bugs reported + in PUI - the most significant is that the menu bar doesn't + work properly after the GLUT window has been resized. +

+ The 'complex' demo program seems to fail when a dialog + box is dismissed. This may be because the dialog object + is deleted inside a callback within a member function of + that object. This problem only appears under Microsoft + operating systems and so is hard for me to track down. + The simplest thing may be for me to change the demo + program so it just doesn't work that way. + +

Q5: What changes do you expect to make in future releases?

+ + I am generally unhappy about the somewhat inconsistant + set of constructor functions for the various widgets. + Some auto-size their widgets, some take the size directly, + others have both. This needs to be made much more consistant + across all the widget classes. +

+ I want to write a cute interactive GUI designer program to + write C++ source code for the PUI constructor functions + automatically. Something along the lines of the XForms + 'fdesign' or the FLTK 'fluid' programs. +

+ If GLUT ever changes to allow applications to run without + calling 'glutMainLoop', I will greatly improve the Dialog + box API which sucks right now. It would also spur me on + to write a File Selector widget. The problem is that + you'd really like to be able to write things like: +

+
+    if ( ( fd = fopen ( "babble", "w" ) ) == NULL )
+    {
+      if ( puYesNoDialog ( "Can't open babble file",
+                           "Do you want to continue?" ) )
+        return ;
+      else
+        exit ( 1 ) ;
+    }
+
+
+ However, the 'puYesNoDialog' function can't get it's + graphics up on the screen without returning to GLUT's + main loop - and it can't do that since the call to + puYesNoDialog is in a GLUT callback function. + Look at the ugly code in 'complex' to see how to do + this kind of thing without this facility. +

+ Finally, the appearance of PUI's widgets is somehow + not as neat as some other GUI's such as MUI and Motif. + This should be pretty easy to fix - and it's something + on the 'to do' list. + +

Q6: Where can I ask questions?

+ + Since PUI is now a part of PLIB, + all user level questions, development issues and announcements + are handled from the PLIB mailing list. + +

Q7: What's the difference between PUI and MUI?

+ + The main reason I wrote PUI was my disappointment + with MUI. +

+ MUI has now been 'abandoned' by it's author (Tom Davis) + who none-the-less retains copyright over it. MUI has + several known bugs - and the only known documentation + was written by me - and I have never actually written + a real application using it! +

+ The MUI library (distributed with GLUT) takes + over all of the GLUT callbacks - this makes it + very hard to write general purpose programs with + MUI. +

+ In contrast, it is very easy to add PUI widgets to + an existing OpenGL/GLUT application with only a + couple of lines of code. +

+ PUI also works quite well with 3D hardware such + as 3Dfx Voodoo that 'take over' the screen. Since + MUI and GLUT both create their menu's using the + underlying windowing system's GUI, these menu's + won't be visible on that kind of hardware. PUI + uses only OpenGL to do all kinds of widgets, so + portability onto 3Dfx hardware is assured. + +

Q8: Are there restrictions on using PUI ?

+ + PUI is OpenSource under the terms of LGPL. If for some reason, + you find LGPL too restrictive and if you wish to use it in some + major project then please talk to me about it - I can be flexible. + +

Q9: Do I have to write in C++ to use PUI?

+ + Yes - there will never be a {insert favorite non-C++ language here} + version of PUI. +
+ + +
+Valid HTML 4.0! + +
+Steve J. Baker. <sjbaker1@airmail.net> +
+
+ + diff --git a/doc/pui/complex.png b/doc/pui/complex.png new file mode 100644 index 0000000..6ddc95b Binary files /dev/null and b/doc/pui/complex.png differ diff --git a/doc/pui/index.html b/doc/pui/index.html new file mode 100644 index 0000000..da0878a --- /dev/null +++ b/doc/pui/index.html @@ -0,0 +1,2210 @@ + + + + + + + + The Picoscopic User Interface: Programmers Guide. + + +  + + + + + + +
+
Imagine Pooh Here
+
+
+

+PUI: A Picoscopic User Interface

+ +
+

+Programmers Guide.

+ +
By Steve Baker
+
+ +

+Introduction

+The Picoscopic User Interface (PUI - pronounced 'poohey') +is a simple set of C++ classes that allow programs written in GLUT and +OpenGL to create buttons, sliders, menus etc. +

Because PUI's widget rendering is performed using OpenGL calls, it is +well suited to the job of adding a few simple GUI elements to a game or +other interactive program where the GUI is required to overlay (often transparently) +some 3D rendering. By using OpenGL calls, PUI is much faster than most +other GUI libraries on systems with 3D rendering hardware. +

PUI is now a part of PLIB. +

The PUI FAQ list is here. There is also a +short +introduction to the basics of PUI from John F. Fay. +

Like most similar GUI's (MUI, Xforms, FLTK, GLUI, etc), PUI is comprised +of a base class (puObject) from which all the interesting +widgets are derived. Most of the packages functionality is concentrated +in the puObject class. +

+Contributions

+Mark Danks contributed code +for making PUI run without GLUT under Win32, +

AbdulWajid Mohamed added the 'PUSTYLE_SHADED' +and 'PUSTYLE_SMALL_SHADED' code. He also fixed a number of bug fixes. +

Dave McClurg added the puListBox and puFilePicker +widgets. +

John F. Fay added a few widgets and other things and reworked this document. +

+A Truly PUI API:

+Here are the elements that make up the PUI API: + + + + + + + + + + + + + + + + +
+

+Classes:

+
+

+Non-class functions:

+
+ + + + + +
+ +

+Note:

+In the description of each widget class below, there is a small screenshot +of one example of that widget. You can see the code used to generate those +screenshots in the PLIB example program +widget_list.cxx. However, +by changing the rendering style, you can make them look considerably different +from this. +

+PUI Terminology.

+Some terminology: +
    +
  • +WIDGET : A single graphic user interface entity such as a button, slider, +menu or some kind of decorative entity like a border or information string.
  • + +
  • +LEGEND : This is a text string that resides inside the widget's active +area.
  • + +
  • +LABEL : This is a text string that resides outside the widget's active +area.
  • + +
  • +VALUE : All puObjects have a current 'value' which +can be read or written as an integer, float or string. The exact meaning +of this value may vary from widget to widget. For some widget types, the +value has no meaning at all (eg a puFrame) - although +it is always available to be set and read by the application. The manner +in which the value of a widget is displayed (if at all) varies from widget +to widget.
  • + +
  • +ABOX : The Activity Box - A rectangular region that is the 'active' area +into which mouse clicks must be directed in order to make a widget do whatever +it does.
  • + +
  • +BBOX : The Bounding Box - A rectangular region that surrounds the pixels +drawn by the widget. This is typically the ABOX - extended to include the +LABEL string.
  • + +
  • +STRING : PUI recognizes only the printable ASCII set plus space and newline.
  • +
+ +

+Hello World in PUI.

+ + + + + + + +
Here is a simple example program. It pops up a window with a single +button widget that prints 'Hello World.' to stdout when you click it. (This +program is in the PUI examples directory as 'simple.cxx').Simple PUI example
+ +
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+#include <math.h>
+#include <GL/glut.h>
+#include <plib/pu.h>
+
+void motionfn ( int x, int y )
+{
+  puMouse ( x, y ) ;
+  glutPostRedisplay () ;
+}
+
+void mousefn ( int button, int updown, int x, int y )
+{
+  puMouse ( button, updown, x, y ) ;
+  glutPostRedisplay () ;
+}
+
+void displayfn ()
+{
+  glClearColor ( 0.1, 0.4, 0.1, 1.0 ) ;
+  glClear      ( GL_COLOR_BUFFER_BIT ) ;
+
+  puDisplay () ;
+
+  glutSwapBuffers   () ;
+  glutPostRedisplay () ;
+}
+
+void button_cb ( puObject * )
+{
+  fprintf ( stderr, "Hello World.\n" ) ;
+}
+ 
+
+int main ( int argc, char **argv )
+{
+  glutInitWindowSize  ( 240, 120 ) ;
+  glutInit            ( &argc, argv ) ;
+  glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ;
+  glutCreateWindow    ( "PUI Application"  ) ;
+  glutDisplayFunc     ( displayfn ) ;
+  glutMouseFunc       ( mousefn   ) ;
+  glutMotionFunc      ( motionfn  ) ;
+
+  puInit () ;
+
+  puOneShot *b = new puOneShot ( 50, 50, 200, 80 ) ;
+
+  b -> setLegend   ( "Say Hello" ) ;
+  b -> setCallback ( button_cb ) ;
+
+  glutMainLoop () ;
+
+  return 0 ;
+}
+Notice that the program uses a pretty conventional GLUT startup sequence, +with the usual callbacks for mouse events and redisplay. You can even continue +to use GLUT popup menus which will work quite happily in conjunction with +PUI menus. +

The needs of PUI are small - as a minimum, call the puMouse +function whenever the mouse is clicked or dragged, call the puKeyboard +function whenever a key is pressed, call the puDisplay +function frequently enough to maintain smooth interactions. +

The creation of the user interface is similarly simple, calling the +constructor function for the objects you need (with the dimensions of the +active area of each object) - then add labels, legends, callback functions, +etc. +

Whenever the puMouse function detects that the +mouse coordinate lies over an active widget, it calls the user-supplied +callback function and takes the necessary actions to update the graphics +on the next call to puDisplay. +

+Multiple Windows in PUI

+When you create a new widget, PUI places it in the current GLUT window. +If the your application opens multiple windows, you can place user interface +widgets in any window you please. The widget coordinates are calculated +from the lower left-hand corner of the window. There are a few recommended +practices when using PUI in connection with multiple windows: +
    +
  • +Make the first widget in a new window a puGroup +widget and place all of that window's widgets in that group. This is simply +good organization.
  • + +
  • +Do not place widgets that are displayed in one window under a puGroup +widget that is displayed in another window. That only works with recent +PLIB versions and is simply not recommended.
  • + +
  • +If the user will be able to reshape the window, include a window reshape +function that adjusts the positions and sizes of the widgets. If the user +should not resize the window then the window reshape function should reset +the window to its original size.
  • +
+ + + + + + + +
This is a more complicated example in the PUI example directory called +'complex.cxx', it produces a menu and a button that float in front of a +tumbling cube that is rendered in OpenGL. In a second window are two sliders +which allow the user to control the speed and direction of the cube's rotation. +A third window contains a bi-slider and a tri-slider which truncate the +cube in two directions.Complex PUI example
+ +

+Object Picking

+The most recent widget to be activated is called the "active widget." Usually +if you click the mouse on another widget the active widget immediately +deactivates and the new widget becomes the active widget. There are times, +however, when you will want to click the mouse somewhere in a window and +have the active widget operate on where you clicked the mouse. You do this +by setting and invoking the widget's "active callback." A simple GLUT mouse +function that does this is as follows: +
  static void mousefn ( int button, int updown, int x, int y )
+  {
+    if ( !puMouse ( button, updown, x, y ) )
+    {
+      // PUI didn't take the mouseclick, try the main window
+      mouse_x = x ;
+      mouse_y = puGetWindowHeight () - y ;
+      // Check for an active widget.
+      //  If there is one, call its active callback
+      if ( puActiveWidget () )
+        puActiveWidget () -> invokeActiveCallback () ;
+   }
+
+   glutPostRedisplay () ;
+ }
+First the mouse function calls puMouse to see if +the user clicked on a new PUI widget. If the user did not, puMouse +returns FALSE and the function executes the contents of the if-block. It +saves the mouse coordinates in a pair of global variables and, if there +is an active widget, it invokes the active widget's active callback. This +active callback will invoke the OpenGL select mode, create the pick matrix, +and redraw the window to get the selected objects. The PUI examples directory +has a program, "PointPicker", which does this. +

+Transparent GUI's

+One very trendy idea is to use translucent GUI widgets. This is handy because +the GUI doesn't intrude quite so badly into the available screen area. +Translucent menus have always been possible in PUI - it's just that nobody +ever actually wanted to do it. Here's what you do: +
    +
  • +Pick a default colour with an alpha component of about 0.4f.
  • + +
  • +Be sure to glEnable(GL_BLEND) and set up the appropriate blend functions. +I use glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA) and glAlphaFunc(GL_GREATER,0.1f) +- call these just before puDisplay().
  • + +
  • +Now, is that cool or what?
  • +
+ +

+Class Descriptions

+ +

+puFont

+A puFont is a simple class which can be constructed in one of two ways: +

+1.) Using a GLUT bitmap font:

+ +
  puFont::puFont ( void *glut_font ) ;
+  puFont::puFont () ;
+
+
+Where 'glut_font' is a GLUT_BITMAP font. +

In case of the second constructor which does not take any arguments +at all, a puFont is created from the GLUT_BITMAP_8_BY_13 fixed font, which +can be considered as the default PUI font. +

Since there are only seven GLUT_BITMAP fonts, these have all been pre-declared +within PUI (mainly for backwards compatability with PLIB versions before +1.0.7). +

  extern puFont PUFONT_8_BY_13 ;        - 8x13 Fixed width
+  extern puFont PUFONT_9_BY_15 ;        - 9x15 Fixed width
+  extern puFont PUFONT_TIMES_ROMAN_10 ; - 10-point Proportional
+  extern puFont PUFONT_TIMES_ROMAN_24 ; - 24-point Proportional
+  extern puFont PUFONT_HELVETICA_10 ;   - 10-point Proportional
+  extern puFont PUFONT_HELVETICA_12 ;   - 12-point Proportional
+  extern puFont PUFONT_HELVETICA_18 ;   - 18-point Proportional
+
+
+These are light on storage - but slow to render on most hardware-based +OpenGL implementations because GLUT uses glBitMap to render its glyphs. +If you wish to use PLIB on a software-only OpenGL implementation (Good +Luck!) then you'll want to use these GLUT fonts since glBitMap is usually +faster than texture-mapped text. +

+2.) Using a pre-built FNT font:

+ +
  puFont::puFont ( fntTexFont *tex_font,
+                   float pointsize, float slant = 0 ) ;
+
+
+Where 'tex_font' is texture-based font created using the +FNT +library and setting the pointsize and optional italic slant (both measured +in pixels). +
  +

After the puFont has been constructed, you can retrieve the height or +width of a certain amount of text: +

  int puFont::getStringHeight ( void ) const ;
+  int puFont::getStringHeight ( const char *str ) const ;
+  int puFont::getStringWidth  ( const char *str ) const ;
+
+
+The getStringHeight routine that does not take any parameters returns the +height of the "K" character. +

Note that always the height excluding the descender is returned. +There is another function which allows you to determine the font descender: +

  int puFont::getStringDescender ( void ) const ;
+
+
+The following function can be used to draw some text at a specific position: +
  void puFont::drawString ( const char *str, int x, int y ) ;
+
+
+However, this is not the recommended way of positioning text on the user +interface. Instead, have a look at the puText widget. +

+puObject

+All PUI widgets are derived from the puObject abstract base class. User +programs should never declare objects of this type. puObjects are in turn +derived from an internally defined puValue class - but this is never visible +to the user and is not documented here. +

When you declare most widgets, you must define the size of ABOX for +the widget. (This is actually the pixel coordinates of the rectangle around +the active area of the widget - with the origin at bottom-left of the window). +

   puObject::puObject ( int minx, int miny, int maxx, int maxy ) ;
+
+
+(Some widgets need more or fewer arguments to their constructor - but most +follow this scheme). +

You can always find the type of an object derived from puObject by calling: +

  int puObject::getType ( void ) const ;
+
+
+This returns a bitmask showing the inheritance of any object derived from +the puObject base class: +
  #define PUCLASS_VALUE
+  #define PUCLASS_OBJECT
+  #define PUCLASS_GROUP
+  #define PUCLASS_INTERFACE
+  #define PUCLASS_FRAME
+  #define PUCLASS_TEXT
+  #define PUCLASS_BUTTON
+  #define PUCLASS_ONESHOT
+  #define PUCLASS_POPUP
+  #define PUCLASS_POPUPMENU
+  #define PUCLASS_MENUBAR
+  #define PUCLASS_INPUT
+  #define PUCLASS_BUTTONBOX
+  #define PUCLASS_SLIDER
+  #define PUCLASS_DIALOGBOX
+  #define PUCLASS_ARROW
+  #define PUCLASS_LISTBOX
+  #define PUCLASS_DIAL
+  #define PUCLASS_FILEPICKER
+  #define PUCLASS_FILESELECTOR
+  #define PUCLASS_BISLIDER
+  #define PUCLASS_TRISLIDER
+  #define PUCLASS_VERTMENU
+  #define PUCLASS_LARGEINPUT
+  #define PUCLASS_COMBOBOX
+  #define PUCLASS_SELECTBOX
+
+
+Hence, if you declare an object of (say) class puOneShot, +then calling getType() for that object would return +
   PUCLASS_VALUE | PUCLASS_OBJECT | PUCLASS_BUTTON | PUCLASS_ONESHOT
+(since a puOneShot is a kind of puButton +which is a kind of puObject which is [although not documented that way +here] a kind of puValue). +

For the purposes of printing diagnostics, etc there is also: +

  const char *puObject::getTypeString ( void ) const ;
+
+
+...which returns a pointer to a statically allocated string which is the +name of the top-level class to which that object belongs. +
   struct puBox { int min[2] ; int max[2] ; }
+
+   puBox *puObject::getABox ( void ) ;
+   puBox *puObject::getBBox ( void ) ;
+
+
+get the ABOX (Activity Box) and BBOX (Bounding Box) of the object. +

You can also move or resize the ABOX of a widget after it has been declared +using: +

  void puObject::setPosition ( int x, int y ) ;
+  void puObject::setSize     ( int w, int h ) ;
+
+  void puObject::getPosition ( int *x, int *y ) const ;
+  void puObject::getSize     ( int *w, int *h ) const ;
+The bounding box is adjusted to fit around the activity box and the label, +if any. +

The following functions allow you to manipulate +the value of the widget: +

  void  puObject::clrValue ( void ) ;
+  void  puObject::setValue ( int   i ) ;
+  void  puObject::setValue ( float f ) ;
+  void  puObject::setValue ( const char *s ) ;
+
+  void  puObject::getValue ( int   *i ) ;
+  void  puObject::getValue ( float *f ) ;
+  void  puObject::getValue ( char  *s ) ;  /* copies the string value into the string that is passed in */
+  void  puObject::getValue ( char **s ) ;  /* sets the argument to point to the string value */
+  int   puObject::getValue ( void ) ;      /* Obsolete ! Use getIntegerValue instead. */
+
+  int   puObject::getIntegerValue ( void ) ;
+  float puObject::getFloatValue   ( void ) ;
+  char  puObject::getCharValue    ( void ) ;     /* returns the first character in the string value */
+  char *puObject::getStringValue  ( void ) ;
+
+
+The clrvalue() function has the special function of setting the string +value of the widget to the empty string - and the numeric parts to zero. +

Some kinds of widget have a default value that they can easily be reset +to. +

  void puObject::defaultValue ( void ) ;
+
+
+...allows you to return the widget to some known default value. The default +value can also be set and read: +
  void  puObject::setDefaultValue ( int    i ) ;
+  void  puObject::setDefaultValue ( float  f ) ;
+  void  puObject::setDefaultValue ( const char *s ) ;
+
+  void  puObject::getDefaultValue ( int   *i ) ;
+  void  puObject::getDefaultValue ( float *f ) ;
+  void  puObject::getDefaultValue ( char  *s ) ;
+  void  puObject::getDefaultValue ( char **s ) ;
+  int   puObject::getDefaultValue ( void ) ;  /* Obsolete ! Use getDefaultIntegerValue instead. */
+
+  int   puObject::getDefaultIntegerValue ( void ) ;
+  float puObject::getDefaultFloatValue   ( void ) ;
+  char *puObject::getDefaultStringValue  ( void ) ;
+
+
+There are many occasions when you'd really like to have the PUI widget +directly drive and/or reflect the value of some memory location in the +application code. These calls let you do that: +
  void puObject::setValuator ( int   *i ) ;
+  void puObject::setValuator ( float *f ) ;
+  void puObject::setValuator ( char  *s ) ;
+
+
+Once you make one of these calls, PUI will automatically update the memory +location indicated with the current value of the widget whenever it changes +- and also update the appearance of the widget to reflect the value stored +in that memory location whenever the widget is redrawn. This is often a +lot more convenient than using a callback function to register changes +in the widget's value. +

IMPORTANT NOTE: When you pass a 'char*' to setValuator, it is your responsibility +to ensure that this pointer is pointing at enough memory to store the longest +possible string that this widget can possibly need. The string in the puValue +class is defined as being PUSTRING_MAX characters long; currently this +is 80. +

Passing NULL to setValuator causes PUI to revert to using an internal +variable to store the widget's state. +

Each widget can also retain a pointer to user-supplied data: +

  void  puObject::setUserData ( void *data ) ;
+  void *puObject::getUserData ( void ) const ;
+When the widget is drawn, the application has control of the drawing style +and the colours in which the widget is drawn. Reasonable defaults are provided +by PUI if you don't set them: +
  void puObject::setStyle ( int style ) ;
+  int  puObject::getStyle ( void ) const ;
+
+  'style' is one of:
+      PUSTYLE_NONE
+      PUSTYLE_PLAIN
+      PUSTYLE_SHADED          -- This is the Default.
+      PUSTYLE_SMALL_SHADED
+      PUSTYLE_BEVELLED
+      PUSTYLE_SMALL_BEVELLED
+      PUSTYLE_BOXED
+      PUSTYLE_SPECIAL_UNDERLINED
+      PUSTYLE_DROPSHADOW
+      PUSTYLE_RADIO
+The various styles are interpreted as follows: +
    +
  • +PUSTYLE_NONE - No background is drawn for the widget - just the legend +and the label.
  • + +
  • +PUSTYLE_PLAIN - Just a plain solid-coloured rectangle.
  • + +
  • +PUSTYLE_BEVELLED - The widget is drawn with a three-dimensional-looking +bevelled edge around it - with the 'light' shining on it from the top left.
  • + +
  • +PUSTYLE_SMALL_BEVELLED - Same as for PUSTYLE_BEVELLED but with a smaller +border.
  • + +
  • +PUSTYLE_SHADED - Similar to PUSTYLE_BEVELLED - but with the main rectangle +counter-shaded.
  • + +
  • +PUSTYLE_SMALL_SHADED - Same as for PUSTYLE_SHADED but with a smaller border.
  • + +
  • +PUSTYLE_BOXED - A simple rectangle with a line around the outside.
  • + +
  • +PUSTYLE_SPECIAL_UNDERLINED - A simple rectangle drawn with a thin line +at the bottom, giving an "underlined" effect like you can see in the +puMenuBar +and puVerticalMenu widgets.
  • + +
  • +PUSTYLE_DROPSHADOW - A simple rectangle - but drawn with a shadow below +and to the right to make it look like it has been raised off of the page.
  • + +
  • +PUSTYLE_RADIO - The bounding rectangle and the legend text isn't drawn +at all - the widget is drawn as a small diamond shape which is filled in +when the object has a non-zero value. This is only useful for puButton +widgets.
  • +
+In case of PUSTYLE_BOXED and PUSTYLE_SPECIAL_UNDERLINED, you can alter +the thickness of the border around the widget / the width of the line at +the bottom of the widget or retrieve the current value: +
  void puObject::setBorderThickness ( int t ) ;
+  int  puObject::getBorderThickness ( void ) const ;
+You should be careful to call the "setBorderThickness" routine after you +have specified the widget style.  The "setStyle" function sets the +border thickness automatically and will overwrite any previous border thickness +you may have set. +

By default, a border thickness of two pixels is used in PUSTYLE_BOXED. +For PUSTYLE_SPECIAL_UNDERLINED, a one pixel wide line is drawn. +

In addition, you can use the negation of the style to swap the appearance +of the selected and deselected versions of an object. Hence, using a style +of -PUSTYLE_BEVELLED will produce a widget that appears to be pressed in +when its value is zero and popped out when it's value is non-zero. +

While most widgets default to a style of PUSTYLE_SHADED, some of the +more complex types such as sliders and menus pick more complex defaults +in order to look 'reasonable'. You can still override those defaults - +but the results can often be less than desirable. +

 void puObject::setColour ( int which, float  r, float g, float  b, float  a = 1.0f ) ;
+ void puObject::getColour ( int which, float *r, float *g, float *b, float *a = NULL ) const ;
+
+  'which' is one of:
+      PUCOL_FOREGROUND
+      PUCOL_BACKGROUND
+      PUCOL_HIGHLIGHT
+      PUCOL_LABEL
+      PUCOL_LEGEND
+      PUCOL_MISC
+
+
+Here is a description of each colour's meaning: +
    +
  • +PUCOL_FOREGROUND, PUCOL_BACKGROUND, PUCOL_HIGHLIGHT - Depending on the +style which you have set, these colours are used for different purposes +while drawing the widget's ABOX.
  • + +
  • +PUCOL_LABEL - Obviously, this is the colour which is used when drawing +the label of a widget.
  • + +
  • +PUCOL_LEGEND - The colour that is used when the legend string is drawn. +For the +puInput, puLargeInput +and puListBox classes, which don't have a legend, +PUCOL_LEGEND is the colour of other kind of text inside the widget.
  • + +
  • +PUCOL_MISC - This colour is used for miscellaneous things in some classes. +Currently, it indicates the colour of the arrow inside a +puArrowButton, +and it is used while drawing the circle that is inscribed in a puDial +or the text cursor in the puInput and puLargeInput +widgets.
  • +
+Picking all of the individual colours for each widget can be tedious, so +there is a handy function that sets a 'theme' colour for the widget and +then picks suitable colours near to that theme for the other colours of +the widget. This function works well enough that you will almost never +need to set the colours individually. +
  void puObject::setColourScheme ( float r, float g, float b, float a = 1.0f ) ;
+
+
+Please note that these routines only affect the appearance of the widget +itself in case of classes that contain subwidgets and are not menu widgets +(currently puFileSelector, puLargeInput, +puComboBox, +puSelectBox +and the obsolete puFilePicker class). +

However, these classes are all derived directly or indirectly from +puGroup, +and thus you can use the appropriate puGroup functions +in order to change the styles, colours or border thicknesses of the subwidgets. +

In addition to the pre-defined styles, PUI allows you to create your +own drawing function and save the related drawing data. This is done by +means of the "render data" and "render callback." A render callback is +a user-defined function that has the following definition: +

  typedef void (*puRenderCallback)(class puObject *, int dx, int dy, void *) ;
+
+
+The function takes four parameters: a pointer to the object whose render +callback this is, the x- and y-coordinates of the lower left-hand of the +widget, and a pointer to your render data. The user tells PUI to use his +rendering callback instead of the usual drawing function by invoking the +following function: +
  void puObject::setRenderCallback ( puRenderCallback *c, void *d = NULL ) ;
+The two arguments are the name of the render callback and an optional pointer +to the user-defined render data. If a render callback exists, the widget's +draw function renders only the activity box (unless PUSTYLE_NONE is used) +and the label (if you specified one) and calls the render callback afterwards +instead of executing the code which would normally be used to draw the +widget. +

PUI also has functions to allow the user to retrieve and invoke the +render callback: +

  puRenderCallback puObject::getRenderCallback ( void ) const ;
+  void      *puObject::getRenderCallbackData ( void ) const ;
+  void       puObject::invokeRenderCallback ( int dx, int dy ) ;
+
+
+When a widget is activated, its user-supplied callback function is called +(if it exists): +
  typedef void (*puCallback)(puObject *) ;
+ 
+  void       puObject::setCallback ( puCallback c ) ;
+  puCallback puObject::getCallback ( void ) const ;
+  void       puObject::invokeCallback ( void ) ;
+
+
+The callback is invoked (typically) when the user releases the left mouse +button when the cursor lies within the widget's active area. The user-supplied +function is called with the address of the widget as a parameter so that +the same callback can often be used with a variety of similar widgets. +It is also possible to invoke an object's callback explicitly using invokeCallback +- bear in mind that this does not change the value of the object - unless +the callback itself does so. +

There are occasionally times when you'd like the widget to be activated +when the user PRESSES the mouse button instead of when he RELEASES it (which +is the default). PUI lets you make widgets that are activated on both button-down +and +button up. You can even tell PUI to call your callback continually all +the time the left button is pushed while the cursor is inside the widget: +

  void puObject::setActiveDirn ( int dirn ) ;
+  int  puObject::getActiveDirn ( void ) const ;
+
+  where:
+    'dirn' is either PU_UP, PU_DOWN, PU_CONTINUAL or PU_UP_AND_DOWN.
+
+
+As discussed earlier, PUI tracks the most recently invoked widget and calls +it the "active widget". PUI allows you to define a callback to be invoked +for the active widget when the user clicks the mouse outside any user interface +widgets. You can also define a callback for PUI to call when the widget +is being deactivated, when the user is activating another widget. The following +functions do these things: +
  void       puObject::setActiveCallback ( puCallback c ) ;
+  puCallback puObject::getActiveCallback ( void ) const ;
+  void       puObject::invokeActiveCallback ( void ) ;
+
+  void       puObject::setDownCallback ( puCallback c ) ;
+  puCallback puObject::getDownCallback ( void ) const ;
+  virtual void puObject::invokeDownCallback ( void ) ;
+
+
+Most widgets can have a LEGEND (text inside the active area of the widget), +and also a LABEL (text outside the active area). The application gets to +choose where the LABEL is placed relative to the active area of the widget. +You can also move the LEGEND text around inside the widget. +
  void   puObject::setLegend ( const char *str ) ;
+  void   puObject::setLabel  ( const char *str ) ;
+
+  const char *puObject::getLegend ( void ) const ;
+  const char *puObject::getLabel  ( void ) const ;
+
+  void   puObject::setLegendFont ( puFont font ) ;
+  void   puObject::setLabelFont  ( puFont font ) ;
+
+  puFont puObject::getLegendFont ( void ) const ;
+  puFont puObject::getLabelFont  ( void ) const ;
+
+  void  puObject::setLabelPlace ( int place ) ;
+  int   puObject::getLabelPlace ( void ) const ;
+
+  where 'place' is one of:
+ + + + + + + + + +
+
      PUPLACE_ABOVE_LEFT
+      PUPLACE_ABOVE_RIGHT
+
+      PUPLACE_TOP_LEFT
+      PUPLACE_TOP_CENTERED
+      PUPLACE_TOP_RIGHT
+
+      PUPLACE_UPPER_LEFT
+      PUPLACE_UPPER_RIGHT
+
+      PUPLACE_CENTERED_LEFT
+      PUPLACE_CENTERED_RIGHT
+
+      PUPLACE_LOWER_LEFT
+      PUPLACE_LOWER_RIGHT    -- The default LABEL place
+
+      PUPLACE_BOTTOM_LEFT
+      PUPLACE_BOTTOM_CENTERED
+      PUPLACE_BOTTOM_RIGHT
+
+      PUPLACE_BELOW_LEFT
+      PUPLACE_BELOW_RIGHT
+
Illustration of label places
+ +
  void  puObject::setLegendPlace ( int place ) ;
+  int   puObject::getLegendPlace ( void ) const ;
+
+  where 'place' is one of:
+ + + + + + + + + +
+
      PUPLACE_TOP_LEFT
+      PUPLACE_TOP_CENTERED
+      PUPLACE_TOP_RIGHT
+
+      PUPLACE_CENTERED_LEFT
+      PUPLACE_CENTERED_CENTERED    -- The default LEGEND place.
+      PUPLACE_CENTERED_RIGHT
+
+      PUPLACE_BOTTOM_LEFT
+      PUPLACE_BOTTOM_CENTERED
+      PUPLACE_BOTTOM_RIGHT
+
Illustration of legend places
+ +

In previous PLIB versions, a different (and smaller) set of label and +legend place names was used. The old names are kept for backwards compatibility, +but should be considered as deprecated. They might be removed in the future. +

Here is how the old names translate into the new ones: +

  LABEL places:
+
+      PUPLACE_ABOVE          => PUPLACE_TOP_LEFT
+      PUPLACE_BELOW          => PUPLACE_BOTTOM_LEFT
+      PUPLACE_LEFT           => PUPLACE_LOWER_LEFT
+      PUPLACE_RIGHT          => PUPLACE_LOWER_RIGHT
+      PUPLACE_TOP_CENTER     => PUPLACE_TOP_CENTERED
+      PUPLACE_BOTTOM_CENTER  => PUPLACE_BOTTOM_CENTERED
+      PUPLACE_LEFT_CENTER    => PUPLACE_CENTERED_LEFT
+      PUPLACE_RIGHT_CENTER   => PUPLACE_CENTERED_RIGHT
+
+  LEGEND places:
+
+      PUPLACE_LEFT           => PUPLACE_CENTERED_LEFT
+      PUPLACE_CENTERED       => PUPLACE_CENTERED_CENTERED
+      PUPLACE_RIGHT          => PUPLACE_CENTERED_RIGHT
+
+
+Each widget can be hidden (so it isn't drawn - and can't be clicked on), +or simply 'greyed out' (so it can't be clicked on even though it's drawn +- but in a style that makes it clear that this is the case). +
  void puObject::greyOut    ( void ) ;
+  void puObject::activate   ( void ) ;  -- Undo the 'greyout' effect
+  int  puObject::isActive   ( void ) const ;
+
+  void puObject::hide       ( void ) ;
+  void puObject::reveal     ( void ) ;  -- Undo the 'hide' effect
+  int  puObject::isVisible  ( void ) const ;
+
+
+If you want to see or change which window a widget is drawn in, you use +the following functions: +
  void  puObject::setWindow ( int w ) ;
+  int   puObject::getWindow ( void ) const ;
+
+
+If you have some generic data that your widget needs but that doesn't fit +anywhere else, you can save it in the widget's "user data" entry: +
  void  puObject::setUserData ( void *data ) ;
+  void *puObject::getUserData ( void ) const ;
+
+
+Finally, an object can be made to react to the 'return' key on the keyboard +just as if it had been clicked with the mouse. +
   void puObject::makeReturnDefault ( int boolean ) ;
+   int  puObject::isReturnDefault   ( void ) const ;
+
+
+In general, it is very confusing to the user to have multiple objects set +up with ReturnDefault enabled (although PUI allows this). Typically, this +option is only used on buttons in simple Yes/No dialog boxes. +

+puButton

+View of puButton widgetThe +puButton class is derived from puObject. It implements +a simple push-button widget. When clicked its value alternates from '0' +to '1' and is highlighted graphically when in the '1' state. By default, +buttons 'latch' down when clicked. The application could change this to +a one-shot behavior by resetting the value to '0' in the buttons callback +(although it is a lot more convenient to simply use the puOneShot +class for this). +
  puButton::puButton ( int minx, int miny, const char *legend ) ;
+  puButton::puButton ( int minx, int miny, int maxx, int maxy ) ;
+where the first constructor sets the button's size automatically according +to the size of the 'legend' string. +

Apart from these convenient short-hand constructor functions, puButtons +have no special API - everything they need is in the puObject +API. +

+puArrowButton

+View of puArrowButton widgetThe +puArrowButton class is derived from puButton. The +only difference is that puArrowButton renders as an arrow rather than as +a rectangular button. +
  puArrowButton::puArrowButton ( int minx, int miny, int maxx, int maxy,
+                                 int arrow_type ) :
+
+where 'arrow_type' is one of:
+Single arrows:
+
+  PUARROW_UP
+  PUARROW_DOWN
+  PUARROW_LEFT
+  PUARROW_RIGHT
+
+Double arrows:
+
+  PUARROW_FASTUP
+  PUARROW_FASTDOWN
+  PUARROW_FASTLEFT
+  PUARROW_FASTRIGHT
+
+
+In addition, you can get/set the direction of the arrow in mid-run: +
  int  puArrowButton::getArrowType ( void  ) const ;
+  void puArrowButton::setArrowType ( int i ) ;
+
+
+A puArrowButton widget does not have a legend. +

+puOneShot

+View of puOneShot widgetThe +puOneShot class is derived from puButton. It implements +a simple push-button widget which automatically pops back out again as +soon as the mouse is released. This means that its value is always '1' +inside the callback function and '0' at all other times. +

puOneShot's have no special API - everything they need is in the puButton +API. +

+puRange

+There is a group of widgets whose values are restricted to be between a +minimum and a maximum value.  An abstract "puRange" widget class was +created to provide the common code for these widgets.  The "puRange" +object class is derived from the "puObject" class and includes methods +to get and set the allowed minimum and maximum values: +
  float puRange::getMinValue ( void ) const ;
+  virtual void puRange::setMinValue ( float f ) ;
+ +
  float puRange::getMaxValue ( void ) const ;
+  virtual void puRange::setMaxValue ( float f ) ;
+Default values are 0.0 for the minimum and 1.0 for the maximum.  If +you want to specify an increment (for example, if you want values to be +whole numbers) you can: +
  float puRange::getStepSize ( void ) const ;
+  void puRange::setStepSize ( float f ) ;
+The default step size is 0.0, meaning that the value changes continuously. +

+puSlider

+View of puSlider widgetThe +puSlider class is derived from puRange. It implements a slider widget. +When clicked, dragged or unclicked its value changes in proportion to where +it is clicked. For the value ( as returned by puObject::getValue(float +*f) ) ranges from 0.0 to 1.0 from the left to the right (or from the bottom +to the top). The application can change the position of the slider using +puObject::setValue(float f) with a number in the +range 0.0 to 1.0. +
  puSlider::puSlider ( int minx, int miny, int sz ) :
+  puSlider::puSlider ( int minx, int miny, int sz, TRUE ) :
+  puSlider::puSlider ( int minx, int miny, int sz, {TRUE|FALSE}, int width ) ;
+
+
+The first version produces a HORIZONTAL slider, the second version produces +a VERTICAL slider. The third version produces a slider with a non-default +width. +
  void  puSlider::setSliderFraction ( float f ) ;
+  float puSlider::getSliderFraction ( void ) const ;
+
+
+The 'slider fraction' is the proportion of the total width of the slider +widget that is taken up with the sliders' "handle". It defaults to 0.1 +(ie one tenth of the width of the entire widget). + +

  void  puSlider::setPageStepSize ( float f ) ;
+  float puSlider::getPageStepSize ( void ) const ;
+
+The 'page step size' defines how much the slider handle jumps +if one clicks on the slider background. It defaults to 0, which makes +the slider handle jump immediately to the clicked upon position. + +

There are several choices to be made relating to when (or how often) +you wish your callback function to be called: +

  void  puSlider::setCBMode ( int mode ) ;
+  float puSlider::getCBMode ( void ) const ;
+  
+   where 'mode' is one of:
+       PUSLIDER_CLICK  - Only invoke the callback when
+                         the mouse goes in the active direction.
+       PUSLIDER_DELTA  - Invoke the callback only when the value
+                         of the slider changes by more than a
+                         certain amount.
+       PUSLIDER_ALWAYS - Invoke the callback all the time that
+                         the mouse is in the widget with the mouse
+                         button pushed down. (This is the default).
+
+
+In the PUSLIDER_DELTA case, the amount of change required before the callback +is called is set by: +
  void  puSlider::setDelta ( float f ) ;
+  float puSlider::getDelta ( void ) const ;
+
+
+The parameter is expressed as a fraction of the total slider width (ie +0.0f to 1.0f). +
  int  puSlider::isVertical ( void ) const ;
+
+
+This returns TRUE for Vertical sliders - FALSE for Horizontal ones. +

+puDial

+View of puDial widgetThe +puDial class is derived from puRange and implements a square widget with +a circle inscribed in it. A radius of the circle is also drawn. The value +of the widget is proportional to the angle the radius makes with the vertical +with straight down being zero - then winding it clockwise, straight up +is 0.5 and straight down again being 1.0. The constructor takes three arguments: +the coordinates of the lower left-hand corner of the widget and the widget +size: +
  puDial::puDial ( int minx, int miny, int sz ) ;
+
+
+By default, you can move the pointer directly from 0.0 to 1.0 or 1.0 to +0.0 without winding it all the way around the dial. This is called 'wrapping' +the pointer. If you need to change the wrap mode, you can call: +
  void puDial::setWrap ( int wrapmode ) ;
+  int  puDial::getWrap ( void ) const ;
+
+  where:
+    'wrapmode' is either TRUE (default) or FALSE.
+
+
+Everything defined in the puSlider API can also +be applied to puDial widgets. +

+puBiSlider

+View of puBiSlider widgetThe +puBiSlider class implements a slider with two sliding boxes inside the +slider bar. It is based on the puSlider class, +meaning that anything you can do with a puSlider +you can also do with a puBiSlider. You define it with the following call: +
  puBiSlider::puBiSlider ( int minx, int miny, int sz, int vertical = FALSE ) ;
+
+Since there are two sliding boxes, they are considered to be a current minimum and current maximum value. These are both integers and neither one is stored in the "puValue" as the widget's value. You set and retrieve them with the following functions:
+ +
  void puBiSlider::setCurrentMax ( float f ) ;
+  void puBiSlider::setCurrentMin ( float f ) ;
+
+  float  puBiSlider::getCurrentMax ( void ) const ;
+  float  puBiSlider::getCurrentMin ( void ) const ;
+
+
+If the user clicks on the puBiSlider with his mouse, the box that is closer +to the mouse is activated and moves to the mouse position. The other box +will stay put. If the user drags the upper box over the lower box or vice +versa, the stationary box will move with the other box. +

+

+puTriSlider

+View of puTriSlider widgetThe +puTriSlider class implements a slider with three sliding boxes inside the +slider bar. It is based on the puBiSlider and +includes everything that widget supports. You define it with the following +call: +
  puTriSlider::puTriSlider ( int minx, int miny, int sz, int vertical = FALSE ) ; 
+
+
+The third box in the puTriSlider stores its value in the widget's value. +You can set and retrieve the absolute minimum and maximum values that the +widget boxes can take, and you can set and retrieve the current minimum +and maximum values in the same way that you do with the puBiSlider. +You can set and retrieve the value of the middle box by using the "setValue" +and "getValue" functions. +

The puTriSlider has an additional option which allows you to freeze +the boxes on the ends of the slider bar. The following functions let you +do this: +

   void puTriSlider::setFreezeEnds ( int val ) ;
+   int  puTriSlider::getFreezeEnds ( void ) const ;
+
+   where:
+     'val' is either TRUE (the default) or FALSE.
+
+
+ +

+puFrame

+View of puFrame widgetThe +puFrame class is derived from puObject. It is designed +to provide some aesthetic layout and labelling to your user interface. +As such, the user can never do anything to the frame by clicking on it +- there is no point in creating a callback for this kind of object since +it will never be called. The frame renders as a large PUCOL_FOREGROUND +coloured rectangle (with legend and label) in the appropriate style. +

puFrames have no special API - everything they need is in the puObject +API. +

+

+puText

+View of puText widgetThe +puText class is derived from puObject. It's function +is simply to allow text to be positioned on the user interface. Since puText +has no active area (it cannot be clicked), it has no legend text and the +text you want it to draw should be in the label string. +

The only special API for puText is its constructor function: +

  puText::puText ( int x, int y ) ;
+
+
+By default, this is the bottom-left corner of the label - but you can of +course change that with puObject::setLabelPlace(). +

Everything else that puText widgets need is in the puObject +API. +

+

+puInput

+View of puInput widgetThe +puInput class is derived from puObject. It's designed +for the specific purpose of allowing the user to input a string (or an +integer or floating point number). +

First, create the puInput object: +

   puInput::puInput ( int minx, int miny, int maxx, int maxy ) ;
+
+
+Note that puInput objects do not display their 'legend' string - the center +of the widget being used to draw the value as a string. +

A puInput object can be in two states - accepting keystrokes - or ignoring +them. Use these functions to toggle between the two states: +

  void puInput::acceptInput ( void ) ;
+  void puInput::rejectInput ( void ) ;
+  int  puInput::isAcceptingInput ( void ) const ;
+
+
+When the user hits the 'Return' key, the puInput is automatically set to +reject further input. When the user clicks the mouse onto the puInput, +it is automatically set to accept input - and the I-bar cursor is moved +next to the character nearest to where the mouse was clicked. +

The text area contains an 'I' bar cursor and a highlighted 'select' +area. You can get and set the character positions (not pixel coordinates) +of those entities: +

  void puInput::setCursor ( int pos ) ;
+  int  puInput::getCursor ( void ) const ;
+
+  void puInput::setSelectRegion ( int  start, int  end ) ;
+  void puInput::getSelectRegion ( int *start, int *end ) const ;
+
+
+Since a puInput uses the normal value getting and setting functions of +puObject, +you are limited to PUSTRING_MAX characters (currently 80). +

When typing into a puInput box, the Backspace, Delete, Home, End, Left +and Right Arrows, Space, Return, Tab, Esc and ^U keys have the expected +functions. All printable characters are inserted into the text. Everything +else is not accepted by the puInput and is available to other functions. +

If you want to restrict the characters that the input widget will accept, +you use the following functions: +

  void  puInput::setValidData ( const char *data ) ;  /* Sets list of valid characters to 'data' */
+  void  puInput::addValidData ( const char *data ) ;  /* Appends 'data' to list of valid characters */
+  char *puInput::getValidData ( void ) const ;        /* Returns pointer to list of valid characters */
+  int   puInput::isValidCharacter ( char c ) const ;  /* Returns 1 if character is valid and 0 if not */
+
+
+This will avoid, for example, the user typing his name into an input box +that is supposed to accept his birthdate. +

Additionally, you can let a puLargeInput widget reject all input that +would modify the text in the puInput box (everything except the Home, End, +Left and Right keys): +

  void puLargeInput::enableInput ( void ) ;
+  void puLargeInput::disableInput ( void ) ;
+  int  puLargeInput::inputDisabled ( void ) const ;
+
+  where:
+    inputDisabled() returns FALSE if the text can be modified and TRUE if it can not.
+
+
+If the text is too long to fit in the widget, only the rightmost characters +will be displayed. One space is always left to the right of the text to +give the user the impression that there is still room to type. +

+

+puLargeInput

+View of puLargeInput widgetThe +puLargeInput widget resembles the puInput widget +but it is actually based on the puGroup widget. +The reason for this is that the widget contains sub-widgets within it: +there is puFrame widget to display the text area; +two puSlider widgets to allow the user to scroll +vertically and horizontally; and there are up to four puArrowButton +widgets to allow rapid vertical scrolling. The puLargeInput widget allows +the user to enter an arbitrarily large amount of text, including multiple +carriage returns. This text is stored in a separate text buffer and is +not connected to the widget value. You create a puLargeInput widget with +the following call: +
  puLargeInput::puLargeInput ( int x, int y, int w, int h,
+                               int arrows, int sl_width ) ;
+
+
+Which creates a puLargeInput at location (x, y), with size (w, h), with +sliders of "sl_width" pixels wide, and with "arrows" pairs of up- and down-arrows +on the right-hand slider. Allowed values for "arrows" are 0, 1, and 2. +

The following functionality from the puInput +widget is also implemented in the puLargeInput widget: +

  void puLargeInput::acceptInput ( void ) ;
+  void puLargeInput::rejectInput ( void ) ;
+  int  puLargeInput::isAcceptingInput ( void ) const ;
+
+  void puLargeInput::setCursor ( int pos ) ;
+  int  puLargeInput::getCursor ( void ) const ;
+
+  void puLargeInput::setSelectRegion ( int  start, int  end ) ;
+  void puLargeInput::getSelectRegion ( int *start, int *end ) const ;
+
+  void  puLargeInput::setValidData ( const char *data ) ;  /* Sets list of valid characters to 'data' */
+  void  puLargeInput::addValidData ( const char *data ) ;  /* Appends 'data' to list of valid characters */
+  char *puLargeInput::getValidData ( void ) const ;        /* Returns pointer to list of valid characters */
+  int   puLargeInput::isValidCharacter ( char c ) const ;  /* Returns 1 if character is valid and 0 if not */
+
+  void puLargeInput::enableInput  ( void ) ;
+  void puLargeInput::disableInput ( void ) ;
+  int  puLargeInput::inputDisabled ( void ) const ;
+
+  where:
+    inputDisabled() returns FALSE if the text can be modified and TRUE if it can not.
+
+
+Besides the obvious methods of typing or erasing, you can add text to and +remove text from the widget using the following calls: +
  void  puLargeInput::setText ( const char *l ) ;  /* Erases current text and copies input string to text */
+  char *puLargeInput::getText ( void ) const ;     /* Returns the pointer to the text string */
+  void  puLargeInput::addNewLine ( const char *l ) ;  /* Inserts input string at start of next line after cursor */
+  void  puLargeInput::addText ( const char *l ) ;     /* Inserts input string at cursor position */
+  void  puLargeInput::appendText ( const char *l ) ;  /* Adds input string to the end of text */
+  void  puLargeInput::removeText ( int start, int end ) ;  /* Removes the text between character positions */
+
+
+The puLargeInput widget always stores a carriage return at the end of its +text. Even if you delete all the text in the widget, it will create an +empty carriage return. +

The puLargeInput widget also has a few other functions which may be +handy: +

  int  puLargeInput::getNumLines ( void ) const ;  /* Returns the number of lines in the text */
+  void puLargeInput::selectEntireLine ( void ) ;   /* Expands the select region to include full lines */
+  void puLargeInput::setTopLineInWindow ( int val ) ;  /* Sets the top line to be displayed in the widget window */
+
+
+puLargeInput widgets do not have a legend. +

+puGroup

+The puGroup class is derived from puObject. Its +purpose is to allow you to group together other puObjects +and to operate on them en masse. +

When you want to create a group of puObjects +using a puGroup, you construct the puGroup itself, then construct all the +widgets that you want to have inside it. When you have finished adding +widgets to the puGroup, you call: +

  void puGroup::close ( void ) ;
+
+
+puGroup widgets can be placed inside other puGroup widgets to an arbitrary +depth. When a puGroup is delete'ed, it will automatically delete everything +that it contains. +

It is also possible to retrieve the number of childs, and there is a +function which returns the first child inside a puGroup (or NULL if the +group is empty): +

  int puGroup::getNumChildren ( void ) const ;
+  puObject * puGroup::getFirstChild ( void ) const ;
+
+
+Doing a puObject::hide() on a puGroup will hide +all the objects inside the puGroup. Doing a puObject::greyout() +on a puGroup prevents anything inside that group from being clicked. +

A puGroup can be put into "floating" state, meaning that the user can +drag it around with the right mouse button pressed: +

  void puGroup::setFloating ( int value ) ;
+  int  puGroup::getFloating ( void ) const ;
+
+  where:
+    'value' is either TRUE or FALSE.
+
+
+By default, floating is not enabled. +

Colours, styles, etc are not propagated from puGroup to its children, +although there are six functions which allow you to change the appearances +of the child widgets on a per-child-class basis: +

  void puGroup::setChildStyle ( int childs, int style, int recursive = FALSE ) ;
+  void puGroup::setChildBorderThickness ( int childs, int t, int recursive = FALSE ) ;
+
+  void puGroup::setChildColour ( int childs, int which,
+                                 float r, float g, float b, float a = 1.0f,
+                                 int recursive = FALSE ) ;
+  void puGroup::setChildColourScheme ( int childs,
+                                       float r, float g, float b, float a = 1.0f,
+                                       int recursive = FALSE ) ;
+
+  void puGroup::setChildLegendFont ( int childs, puFont f, int recursive = FALSE ) ;
+  void puGroup::setChildLabelFont ( int childs, puFont f, int recursive = FALSE ) ;
+
+
+These routines all take a bitmask specifying which childs to apply the +specified value(s) for by or-ing the appropriate PUCLASS_ constants as +their first argument. +

The last parameter specifies whether the function should operate recursively, +meaning that if a child of the puGroup is another puGroup object or a widget +derived from puGroup, the attributes of the widgets in this group are also +changed. +

Have a look at the following example (assume inputbox to be a pointer +to a puLargeInput widget, which is derived +from puGroup and contains a puFrame, two puSlider +and up to four puArrowButton widgets): +

  inputbox -> setChildStyle ( PUCLASS_ARROW, PUSTYLE_BOXED ) ;
+  inputbox -> setChildColour ( PUCLASS_ARROW | PUCLASS_FRAME,
+                             PUCOL_HIGHLIGHT, 1.0, 1.0, 1.0 ) ;
+
+
+In this case, we would have set the style of all arrow button subwidgets +(if there were any) to PUSTYLE_BOXED and specified the "highlight" colour +of both the frame and the arrow button subwidgets to be white. +

Note that when you specify a child class in the bitmask, all childs +derived from that class are also affected. Hence, using PUCLASS_OBJECT +as the first argument of these functions is an easy way to change the parameters +of all child widgets. +

The coordinates of puGroup child objects are always specified relative +to the bottom-left corner of the puGroup rather than in absolute screen +coordinates. +

The puGroup widget is not drawn. It is commonly a good thing to do, +but certainly not essential, to make the first widget inside a puGroup +to be a puFrame of the group's desired size. The +frame will provide a background for all the other widgets in the group. +

+puInterface

+The puInterface class is derived from puGroup. This +class is another abstract class - application programs should not declare +puInterface objects. +

The difference between a simple puGroup and a +puInterface is that when an interface is enabled, it takes priority over +other widgets so that they cannot be clicked upon. Widgets such as popup +menus are typically puInterfaces which group a number of +puButtons. +

When declaring objects derived from puInterface, it is essential that +these objects are deleted in the reverse order to their creation (except +when your program is about to exit anyway). This is because PUI keeps a +list of puInterfaces on a stack, and attempting to delete a puInterface +from the middle of the stack will cause an error. +

The PUI system itself maintains a private global puInterface which is +used to group together all of the puObjects that +the application generates. +

+

+puPopup

+The puPopup class is derived from puInterface. +Its function is to pop up a bunch of other widgets on command. +

One significant difference between puPopups and other puObjects +is that it starts off hidden (puObject::isVisible()==FALSE) +- and the application (or some other widget) has to make it visible in +order for it to DO something. +

It's possible to use a puPopup to create a popup menu, as a part of +a drop-down menu and to implement dialog boxes and alert boxes. +

+

+puDialogBox

+View of example puDialogBox widget groupThe +puDialogBox class is derived from puPopup. While +there is a puDialogBox in existence (ie Constructed and not yet destroyed) +nothing that isn't contained within that puDialogBox will be activated +by either keyboard or mouse (Although they will still be re-drawn). +
   puDialogBox::puDialogBox ( int x, int y ) ;
+
+
+Here is a simple example where a callback function wants to tell the user +that its code hasn't been written yet... +
puDialogBox *dialog_box = NULL ;
+
+void go_away_callback ( puObject * )
+{
+  delete dialog_box ;
+  dialog_box = NULL ;
+}
+
+void make_dialog ( const char *txt )
+{
+  if ( dialog_box != NULL )
+    return ;
+
+  dialog_box = new puDialogBox ( 50, 50 ) ;
+  {
+    new puFrame ( 0, 0, 400, 100 ) ;
+    new puText  ( 10, 70 ) -> setLabel ( txt ) ;
+
+    puOneShot *ok = new puOneShot ( 180, 10, "OK" ) ;
+    ok -> makeReturnDefault ( TRUE ) ;
+    ok -> setCallback       ( go_away_callback ) ;
+  }
+  dialog_box -> close  () ;
+  dialog_box -> reveal () ;
+}
+
+void not_implemented_yet_callback ( puObject * )
+{
+  make_dialog ( "Sorry, that function isn't implemented yet" ) ;
+}
+
+
+When 'not_implemented_yet_callback' is called (presumably from another +puObject), +it calls 'make_dialog' to construct and activate a suitable dialog box +object. +

This causes the dialog box to pop up onto the screen. When the 'OK' +button is pressed (or the RETURN key is hit - since the button has +puObject::makeReturnDefault(TRUE) +set), the 'go_away_callback' is called - which deletes the dialog box (which +in turn causes the destruction of all the contents of that box). +

+

+puPopupMenu

+View of puPopupMenu widgetThe +puPopupMenu class is derived from puPopup. It's +designed for the specific purpose of building a simple popup menu - which +is actually implemented as a stack of buttons (puOneShot's +actually) with callbacks. +

First, create the puPopupMenu object: +

   puPopupMenu::puPopupMenu ( int x, int y ) ;
+
+
+Afterwards, each item is added: +
   puObject *puPopupMenu::add_item ( const char *str, puCallback cb ) ;
+
+
+Where 'str' is the string that will appear in the menu and 'cb' is the +corresponding callback that will be made if that menu item is clicked, +or NULL in order to indicate items that should not have an action when +clicked upon. +

Each item that you add will be translated into an appropriately sized, +styled and coloured puOneShot. The add_item() +function returns a pointer to the newly created puOneShot +casted into a puObject. +

Since puPopupMenu is derived from puPopup and +hence is a puGroup, don't forget to call +

  puPopupMenu::close () ;
+
+
+after you have finished adding the individual menu entries. +

A puPopupMenu does not have a label or a legend. +

+

+puMenuBar

+View of puMenuBar widgetThe +puMenuBar class is derived from puInterface. +It's designed for the specific purpose of building a horizontal strip menu +(typically at the top of the screen). Each entry in that menu is a +puOneShot +that pops up a puPopupMenu when clicked upon. +

First, create the puMenuBar object: +

   puMenuBar::puMenuBar ( int height = -1 ) ;
+
+
+Which creates a menu bar with height 'height' at the top of the window. +If you omit 'height', the menu bar height will be auto-determined through +the height of the current default legend font. +

Afterwards, PUI will always attempt to remain the menu bar at the top +of the screen, even if the screen is resized. +

Next, set up the colours for the menu - just as with any other puObject, +then add the individual items: +

  void *puMenuBar::add_submenu ( const char *name, char *legends[], puCallback cb[] );
+
+
+'name' is the name that appears on the menu bar, 'legends' is the NULL-terminated +list of strings that appear inside the popup menu and 'cb' is the list +of corresponding callback functions. (Both arrays should be NULL terminated +but the puCallback array can have other NULL pointers indicating PopupMenu +items that have no action when clicked upon). +

Each submenu that you add will be translated into a puOneShot +and an appropriately sized, styled and coloured puPopupMenu +which is hidden and revealed appropriately as it's button in the menu bar +is clicked upon. +

Don't forget (since this is a kind of puInterface) +that you need to call: +

  puMenuBar::close() ;
+
+
+...when you have finished creating the menu items. +

Example: +

  char      *file_submenu    [] = { "Exit" , "Close", "--------", "Save" , NULL};
+  puCallback file_submenu_cb [] = { exit_cb, cull_cb,       NULL, save_cb, NULL};
+  char      *help_submenu    [] = { "About...", "Help" , NULL } ;
+  puCallback help_submenu_cb [] = { about_cb  , help_cb, NULL } ;
+
+  puMenuBar *menu = new puMenuBar ( -1 ) ;
+  menu->add_submenu ( "File", file_submenu, file_submenu_cb ) ;
+  menu->add_submenu ( "Help", help_submenu, help_submenu_cb ) ;
+  menu->close () ;
+
+
+A puMenuBar does not have a label or a legend. +

+puVerticalMenu

+View of puVerticalMenu widgetThe +puVerticalMenu is derived from the puGroup class +and is designed to create a menu with its entries one above the other. +You create it with the following call: +
  puVerticalMenu::puVerticalMenu ( int x = -1, int y = -1 ) ;
+
+
+where using a default value for "x" will place the menu on the left-hand +side of its window and using a default value for "y" will place it on the +top of its window. Its behavior is essentially the same as that of the +puMenuBar +widget. +

A puVerticalMenu does not have a label or a legend. +

+

+puListBox

+View of puListBox widgetThe +puListBox widget is a multiple-line text widget which was designed to support +the puFileSelector widget. It is derived +from the puButton widget and supports that widget's +entire API. You create a puListBox by invoking the constructor method: +
  puListBox::puListBox  ( int minx, int miny, int maxx, int maxy,
+                          char **list = NULL) ;
+
+
+In this case "list" is a null-terminated array of character strings that +contain the items that go into the list box. You are responsible for supplying +this array and for making sure that it is still around the entire time +the puListBox widget is using it. The widget does not make its own +copy of the array. You can change which array the listbox operates on by +calling: +
  puListBox::newList ( char **list ) ;
+
+
+The puListBox widget supports three additional function calls in its API. +They are as follows: +
  int  puListBox::getNumItems ( void ) const ;  /* Return the number of items in the list */
+  int  puListBox::getTopItem  ( void ) const ;  /* Return the index of the top item that is displayed in the list */
+  void puListBox::setTopItem  ( int item_index ) ;  /* Set the index of the top item to be displayed */
+
+
+If the text is too wide for the box, it'll be truncated with "..." displayed +to the right of it to show the user that there is some missing text. +

A puListBox widget does not have a legend. +

+puButtonBox

+View of puButtonBox widgetThe +puButtonBox class is derived from puObject. It +automatically generates a number of 'radio' buttons in it's draw function +and has single callback function. It can optionally manage the problem +of ensuring that exactly one of the buttons is depressed at all times, +or it can allow multiple buttons to be active at the same time. +
  puButtonBox::puButtonBox ( int minx, int miny, int maxx, int maxy,
+                             char **labels, int one_button ) ;
+
+
+The 'labels' parameter is a NULL-terminated array of pointers-to-strings +containing the labels for each of the radio-buttons. These are drawn in +order from top to bottom of the Button Box. +

As with the puListBox widget, you can change +the list of labels in mid-run or retrieve the number of buttons: +

  void puButtonBox::newList ( char **list ) ;
+  int  puButtonBox::getNumItems ( void ) const ;
+
+
+Like most other puObjects, puButtonBox has a 'value' +that can be set using puObject::setValue(int i) +and read using puObject::getValue(). If 'one_button' +is set TRUE then the puButtonBox will use its value as the index of the +radio-button that is currently pressed. If 'one_button' is FALSE then the +puButtonBox will limit the number of buttons to 32 and use its value as +a mask indicating which buttons are set ('1'==button pressed, '0'==button +not pressed). +
  int puButtonBox::isOneButton ( void ) const ;
+
+
+This function returns TRUE for a one_button box, FALSE otherwise. +

By default, if one_button==TRUE then the first button is highlighted +since the 'value' of the puButtonBox is zero. If one_button==FALSE then +none of the buttons are pressed by default since the value is 0x00000000 +and that indicates no buttons pushed. +

In the one_button==TRUE case, setting the value to something out of +range will result in none of the radio buttons being highlighted. +

The puButtonBox widget does not have a legend. +

+puComboBox

+View of puComboBox widgetThe +puComboBox class is derived from puGroup. It implements +yet another widget that allows the user to select one option of an amount +of possible ones. +

The widget contains a puInput widget that displays +the currently selected item and even allows the user to type in an arbitrary +string if you allow him to do so (see below). There is also a +puPopupMenu +that contains all the entries - it is invisible until the user clicks on +the puArrowButton on the right of the combo +box, and it is hidden again after the user selects an item from it or if +he clicks somewhere else on the screen. +

You create a a puComboBox with the following call: +

  puComboBox::puComboBox ( int minx, int miny, int maxx, int maxy,
+                           char **list, int editable = TRUE ) ;
+
+
+Like the constructors of the previously described widgets, the puComboBox +constructor takes a NULL-terminated array of strings specifying the items +that should go into the widget as it's fourth parameter. If 'editable' +is TRUE (default), the input box is made editable for allowing the user +to enter a string in addition to selecting one of the entries from the +popup menu. +

Depending on the position of the puComboBox inside the window, the widget +automatically determines whether the popup menu should be shown above or +below the widget when the user clicks on the arrow. The puArrowButton +is either pointing in up or down direction to indicate where the menu will +pop up. +

Regardless of whether you passed TRUE or FALSE to the 'editable' parameter +when constructing the widget, the user can click inside the input box and +use the Up and Down keys to browse through the items. The Home and End +keys switch to the first or last item as you would expect, and the PgUp +/ PgDown can be used to toggle the popup menu. +

Just like all other classes which store a pointer to an array of strings +that indicates the widget's elements, the puComboBox class provides a routine +that allows you to change the list of elements in mid-run - and you can +also retrieve the number of items: +

  void puComboBox::newList ( char **list ) ;
+  int  puComboBox::getNumItems ( void ) const ;
+
+
+The puComboBox stores the currently selected item or the text that was +typed in by the user (if the combo box is 'editable' - see above) as the +widget's string value which can be retrieved using puObject::getValue(char +*s), puObject::getValue(char **s) or puObject::getStringValue(). +

There is also a function that allows you to retrieve the number of the +currently selected item: +

  int puComboBox::getCurrentItem ( void ) ;
+
+
+If the combo box is 'editable' and if the user typed in some text into +the input box instead of selecting an item from the popup menu or using +the appropriate keys, the function automatically compares the entered string +against each element in the list of items. If there is a match, the number +of the corresponding item is returned just as if it had been selected through +one of the more common methods. If there is no match, a negative number +is returned - it's up to the programmer to decide what the application +should do then (for example, show up a message box saying that an invalid +value was typed in). +

Last but not least, the number of the current item can also be set: +

  void puComboBox::setCurrentItem ( int number ) ;
+
+
+Whenever the current item is changed through the user or through the programmer +using one of the methods described above, the widget invokes its callback. +

A puComboBox widget does not have a legend. +

+puSelectBox

+View of puSelectBox widgetThe +puSelectBox class is derived from puGroup. It is +one more widget that is designed for the purpose of allowing the user to +select one element from a list of items. +

The widget contains a puInput widget that displays +the currently selected item. Unlike in the puComboBox +class, it can not be made editable. There are two puArrowButtons +that allow the user to select an item. If the currently selected item is +the first item, the 'down' arrow is automatically disabled and greyed out +- if the currently selected item is the last item, the same thing happens +to the 'up' arrow. +

You create a a puSelectBox with the following call: +

  puSelectBox::puSelectBox ( int minx, int miny, int maxx, int maxy,
+                             char **list ) ;
+
+
+Again, 'list' is a NULL-terminated array of strings specifying the items +that should appear in the widget. +

The remainder of the puSelectBox API is the same as the API of the puComboBox +class described above - you change the item list that in mid-run, retrieve +the number of items and set or retrieve the currently selected item: +

  void puSelectBox::newList ( char ** list ) ;
+
+  int  puSelectBox::getNumItems ( void ) const ;
+
+  int  puSelectBox::getCurrentItem ( void ) const ;
+  void puSelectBox::setCurrentItem ( int number ) ;
+
+
+Like the puComboBox widget, a puSelectBox additionally +stores the currently selected item as the widget's string value. +

The puSelectBox widget allows the user to select an item using the Up, +Down, PgUp, PgDown, Home and End keys after clicking into the input box +just as a puComboBox does. The only difference +is that the PgUp and PgDown keys don't toggle a popup menu (a puSelectBox +has none). Instead, they have the same meaning as the Up and Down keys. +

Whenever the current item is changed by the user (through clicking upon +one of the arrow buttons or using the appropriate keys) or by the programmer, +the widget invokes it's callback. +

A puSelectBox widget does not have a legend. +

+puFilePicker

+puFilePicker is now obsolete. Please use puFileSelector +instead. +

+puFileSelector

+View of puFileSelector widgetThe +puFileSelector class is derived from puDialogBox. +FileSelector creates a dialog box for selecting a file. The puFileSelector +widget contains: +
    +
  • +A puFrame widget of the puFileSelector's desired +size.
  • + +
  • +A puListBox widget for listing the files. It's +label is placed at the top of it (PUPLACE_TOP_LEFT) and can be set through +the 'title' argument of the puFileSelector constructor.
  • + +
  • +A puSlider widget with zero, two, or four +puArrowButton +widgets (depending on what you ask for) to scroll the file list.
  • + +
  • +Two puOneShot button widgets for the OK and Cancel +buttons.
  • + +
  • +A puInput to allow the user to type in the filename +by hand.
  • +
+The API for puFileSelector: +
  puFileSelector::puFileSelector ( int x, int y,
+                                   const char *dir,
+                                   const char *title = "Pick a file" ) ;
+  puFileSelector::puFileSelector ( int x, int y, int arrows,
+                                   const char *dir,
+                                   const char *title = "Pick a file" ) ;
+  puFileSelector::puFileSelector ( int x, int y, int w, int h,
+                                   const char *dir,
+                                   const char *title = "Pick a file" ) ;
+  puFileSelector::puFileSelector ( int x, int y, int w, int h, int arrows,
+                                   const char *dir,
+                                   const char *title = "Pick a file" ) ;
+
+
+The first constructor sets the position but uses a default value for the +size of the dialog box, currently defaulting to 170,220. The second is +like the first but also allows you to specify up- and down-arrows (0 for +none, 1 for single arrows, 2 for single and double arrows) next to the +list box. The third and fourth constructors allow you to also select the +size of the dialog box as well. +

The "dir" argument is the name of the directory whose files are to be +listed as a starting point - it can be either absolute or relative to the +current working directory. +

"title" is a title that is displayed in the puFileSelector widget. +

When a file has been picked by the user, the string value of the widget +will be set to the absolute pathname of the file. +

  puFileSelector::setSize ( int w, int h) ;
+
+
+This method is used to set the current width and height of the dialog box. +
  puFileSelector::setInitialValue ( const char *pathname ) ;
+
+
+Sets the initial value within the type-in area of the widget. This is generally +a simple file name - but it could be a full path either relative to the +'dir' you specified in the constructor or or an absolute path. +

The puFileSelector widget does not have a legend or a label. Instead, +you can specify the title which is displayed at the top of the widget when +constructing it. +

+Non-Class Functions.

+The following functions are not a part of any classes: +

+

+Setting Defaults

+It can be pretty tedious coding in the colours, fonts and style for every +puObject. +There are a number of routines that alter the defaults that will be assumed +for all subsequently constructed puObjects... +
  void puSetDefaultStyle ( int style ) ;
+  int  puGetDefaultStyle ( void ) ;
+
+  void   puSetDefaultFonts ( puFont  legendFont, puFont  labelFont ) ;
+  void   puGetDefaultFonts ( puFont *legendFont, puFont *labelFont ) ;
+  puFont puGetDefaultLabelFont  ( void ) ;
+  puFont puGetDefaultLegendFont ( void ) ;
+
+  void puSetDefaultColourScheme ( float  r, float  g, float  b, float  a = 1.0 );
+  void puGetDefaultColourScheme ( float *r, float *g, float *b, float *a = NULL);
+
+
+These take the same arguments as the corresponding puObject +class members. +

+

+puInit

+This must be the first PUI function that you call. It must be called after +GLUT window setup but before glutMainLoop(). +
   void puInit ( void ) ;
+
+
+ +

+puDisplay

+Causes PUI to redraw all of the currently created widgets. +
   void puDisplay ( void ) ;
+
+
+It sets up the GL transforms as follows: +
  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 ) ;
+
+  glViewport     ( 0, 0, w, h ) ;
+  glMatrixMode   ( GL_PROJECTION ) ;
+  glPushMatrix   () ;
+  glLoadIdentity () ;
+  gluOrtho2D     ( 0, w, 0, h ) ;
+  glMatrixMode   ( GL_MODELVIEW ) ;
+  glPushMatrix   () ;
+  glLoadIdentity () ;
+...and after it finishes rendering the GUI and the puCursor (see below), +it restores state like this: +
  glMatrixMode   ( GL_PROJECTION ) ;
+  glPopMatrix    () ;
+  glMatrixMode   ( GL_MODELVIEW ) ;
+  glPopMatrix    () ;
+  glPopAttrib    () ;
+
+
+All drawing code is done with whatever glMaterial/glTexture/glEnabled facilities +are currently set. All PUI rendering is done with simple colours and 2D +drawing functions such as glRect and glDrawPixels. +

This function is typically called from the glutDisplayFunc callback. +

Example: +

  void my_display_func ()
+  {
+    glClearColor ( 0.1, 0.4, 0.1, 1.0 ) ;
+    glClear      ( GL_COLOR_BUFFER_BIT ) ;
+    ...do your own OpenGL rendering...
+    puDisplay () ;
+    glutSwapBuffers   () ;
+    glutPostRedisplay () ;
+  }
+ 
+  .
+  .
+  puInit () ;
+  glutDisplayFunc ( my_display_func ) ;
+  .
+  .
+  glutMainLoop() ;
+
+
+ +

+puDeleteObject

+You should use this routine instead of deleting widgets directly. +
   void puDeleteObject ( puObject *ob ) ;
+
+
+ +

+puKeyboard

+This routine takes keystroke events (presumably generated by GLUT) and +uses them to decide which (if any) widgets changed state as a result. puKeyboard +doesn't do any actual graphics - so you have to call puDisplay +if you want the display to be updated. +
   int puKeyboard ( int key, int state ) ;
+
+   'key' is either an ASCII character, or one of the
+       PU_KEY_xxx symbols. These are named similarly
+       to the GLUT_KEY_xxx symbols but are numerically
+       set such that:
+
+           PU_KEY_xxx == GLUT_KEY_xxx + PU_KEY_GLUT_SPECIAL_OFFSET
+   'state' is one of
+       PU_DOWN           (which is the same as GLUT_DOWN)
+       PU_UP             (which is the same as GLUT_UP)
+       (At present, GLUT can only generate PU_DOWN events for the
+       keyboard - and PUI won't do anything with PU_UP events.
+
+
+Notice that this function will accept either an ASCII character or a special +keycode. +

The return result is TRUE if one of the widgets actually used the keystroke. +This can be used to determine if the keyboard event was 'consumed' by the +user interface - or whether it should be used in some other application-specific +way. It is also true to say that in a single-buffered application, the +puDisplay +function doesn't need to be called until puKeyboard() returns TRUE (unless +of course the application chooses to change a colour or a label or something). +

Example: +

   void my_keyboard_func ( unsigned char key, int x, int y )
+   {
+     puKeyboard ( key, PU_DOWN ) ;
+     glutPostRedisplay () ;
+   }
+ 
+   void my_special_func ( int special_key, int x, int y )
+   {
+     puKeyboard ( special_key + PU_KEY_GLUT_SPECIAL_OFFSET, PU_DOWN ) ;
+     glutPostRedisplay () ;
+   }
+ 
+   .
+   .
+   puInit () ;
+   glutKeyboardFunc ( my_keyboard_func ) ;
+   glutSpecialFunc  ( my_special_func  ) ;
+   .
+   .
+   glutMainLoop() ;
+
+
+Note: PU_KEY_GLUT_SPECIAL_OFFSET is required since the definitions of the +GLUT_KEY_xxx symbols overlap the ASCII character range but the PU_KEY_xxx +symbols don't. Hence PU_KEY_GLUT_SPECIAL_OFFSET is currently defined to +be 256. +

These are the code symbols for the special keys: +

    PU_KEY_F1       PU_KEY_F2         PU_KEY_F3     PU_KEY_F4
+    PU_KEY_F5       PU_KEY_F6         PU_KEY_F7     PU_KEY_F8
+    PU_KEY_F9       PU_KEY_F10        PU_KEY_F11    PU_KEY_F12
+
+    PU_KEY_LEFT     PU_KEY_UP         PU_KEY_RIGHT  PU_KEY_DOWN
+    PU_KEY_PAGE_UP  PU_KEY_PAGE_DOWN  PU_KEY_HOME   PU_KEY_END
+    PU_KEY_INSERT
+
+
+ +

+puMouse

+This routine take mouse events (presumably generated by GLUT) and uses +them to decide which (if any) widgets changed state as a result. puMouse +doesn't do any actual graphics - so you have to call puDisplay +if you want the display to be updated. +
   int puMouse ( int buttons, int state, int x, int y ) ;
+   int puMouse ( int x, int y ) ;
+
+   'buttons' is one of
+       PU_LEFT_BUTTON    (which is the same as GLUT_LEFT_BUTTON)
+       PU_MIDDLE_BUTTON  (which is the same as GLUT_MIDDLE_BUTTON)
+       PU_RIGHT_BUTTON   (which is the same as GLUT_RIGHT_BUTTON)
+   'state' is one of
+       PU_DOWN           (which is the same as GLUT_DOWN)
+       PU_UP             (which is the same as GLUT_UP)
+
+
+Notice that this function will accept exactly the arguments that GLUT passes +to the glutMouseFunc, glutMotionFunc and glutPassiveMotionFunc callbacks. +This means that the 'y' coordinate is reversed compared to those used in +OpenGL. The coordinate is flipped back inside the function before comparing +it to the active areas of all the widgets. +

Since GLUT doesn't tell you which mouse buttons are held while the mouse +is being 'dragged', the second form of the 'puMouse' function (which is +usually called from the glutMotionFunc and glutPassiveMotionFunc callbacks), +assumes that the mouse buttons are the same as for the last call to the +first form of the puMouse() call (which does have button information). +

The return result is TRUE if one of the widgets was actually hit by +the mouse event. This can be used to determine if the mouse event was 'consumed' +by the user interface - or whether it should be used in some other application-specific +way. It is also true to say that in a single-buffered application, the +puDisplay +function doesn't need to be called until puMouse() returns TRUE (unless +of course the application chooses to change a colour or a label or something). +

+The PUI 'soft' Cursor

+PUI can take motion events (presumably generated by GLUT - and passed on +to puMouse) and use them to draw a mouse cursor. +Typically, the underlying window manager will draw a perfectly good cursor +for you - but there are a few (rare) cases where such facilities are not +available and a cursor drawn using OpenGL is needed. +

It is also possible to show and hide the PUI cursor (note that it is +hidden by default): +

   void puShowCursor     ( void ) ;
+   void puHideCursor     ( void ) ;
+   int  puCursorIsHidden ( void ) ;
+
+
+The cursor is always drawn in black, with a white border - it is about +18 pixels wide and 18 pixels high and is drawn as an arrow pointing north-west. +At present, there is no way to change the cursor shape or colour. +

If you enable this function on a machine that does have a hardware (or +at least operating-system generated) cursor, then you will probably notice +that the PUI cursor lags behind the 'real' cursor. This is because the +PUI cursor can only be drawn at the end of the frame, after all the other +OpenGL drawing functions are complete. Also, if you are using a double-buffered +rendering context, the cursor won't appear in it's new position until the +buffers are swapped at the end of the frame. +

Still, for all its faults, if there is no other cursor provided for +you - PUI's cursor is a lot better than nothing. +

+Example of puMouse and puShowCursor usage:

+Example: +
   void my_mouse_func ( int button, int updown, int x, int y )
+   {
+     puMouse ( button, updown, x, y ) ;
+     glutPostRedisplay () ;
+   }
+ 
+   void my_motion_func ( int x, int y )
+   {
+     puMouse ( x, y ) ;
+     glutPostRedisplay () ;
+   }
+  .
+  . 
+  puInit () ;
+
+  glutMouseFunc         ( my_mouse_func  ) ;
+  glutMotionFunc        ( my_motion_func ) ;
+  glutPassiveMotionFunc ( my_motion_func ) ;
+
+  if ( my_hardware_doesnt_have_a_cursor )
+    puShowCursor () ;
+  .
+  .
+  glutMainLoop () ;
+
+
+ +

+Active Widget Functions

+PUI has three functions which you can use to manipulate the active widget. +Here they are: +
  void puDeactivateWidget ( void ) ;  /* Sets the Active Widget to NULL */
+  void puSetActiveWidget ( puObject *w ) ;  /* Sets the Active Widget */
+  puObject *puActiveWidget () ;  /* Returns the active widget */
+
+
+ +

+Cut and Paste

+You can cut and paste text between different puInput +widgets and puLargeInput widgets. The cut, copy, +and paste commands are the standard CTRL-X, CTRL-C, and CTRL-V. +

Interfacing with Windowing Libraries.

+PUI works with many windowing libraries (Currently: GLUT, freeglut, SDL, +FLTK and PLIB's own 'PW' library). Prior to version 1.8.1, PLIB required +GLUT or freeglut - and that library is +used in most of our example programs and demo's. +

+You have a choice about how to tell PUI which windowing library you are using: +

+EITHER: +

    +
  1. #define PU_USE_GLUT or PU_USE_PW or PU_USE_FLTK or PU_USE_SDL ...to + explicitly tell PUI which windowing library you want it to use. + Make sure you define this symbol BEFORE you '#include <plib/pu.h>'. + I would generally do this with a '-D' directive on your compile line. +
    +   eg:
    +      #define PU_USE_FLTK  1
    +      #include <plib/pu.h>
    +
    +

    +...OR... +

  2. Include the header file for whatever windowing library you are + using (PW, SDL, FLTK, GLUT, etc) BEFORE you '#include <plib/pu.h>'. + pu.h will then automatically detect which windowing library you are + using and set PU_USE_ appropriately. +
    +   eg:
    +      #include <FL/Fl_Gl_Window.H>
    +      #include <plib/pu.h>
    +
    +

    +...OR... +

  3. #define PU_USE_NONE before you include pu.h - and PUI will assume + nothing about your windowing library. This is an OK thing to do for + every source file EXCEPT the one that calls puInit() which must use one + of the other mechanisms. Use this technique if you are doing something + like writing a library of your own that uses PLIB but which also + needs to be independent of any windowing library. +

    +...OR... +

  4. #define PU_USE_NATIVE before you include pu.h - and PUI will try to + figure out what it needs to know using native commands such as those + in the wgl/glX/agl library - in the absence of a windowing library. + This may result in some problems if you want to do certain + operations for which PUI needs to query the windowing library. + Use of PU_USE_NATIVE is not recommended in systems that allow you + to resize the window or open multiple windows. +

    +...OR... +

  5. Do none of the above - in which case PUI will assume you are using + GLUT/freeglut. It has to work like this for reverse-compatibility + with applications written for PLIB 1.7.x and earlier. +
+Check out the example programs for PU - notably fltk_demo and sdl_example +in the examples/src/pui area and pw_pui in the examples/src/pw area. +

+If you have your own windowing library (ie not PW, GLUT, SDL or FLTK), +then you can make it work properly with PUI by defining four inline +functions and passing them into 'puSetWindowFuncs'. Look at (for +example) puGLUT.h to see how this is done. +


+ + + + + + +
Valid HTML 4.0! +
+Steve J. Baker. <sjbaker1@airmail.net>
+
+ + + diff --git a/doc/pui/labelplaces.png b/doc/pui/labelplaces.png new file mode 100644 index 0000000..02f1d6d Binary files /dev/null and b/doc/pui/labelplaces.png differ diff --git a/doc/pui/legendplaces.png b/doc/pui/legendplaces.png new file mode 100644 index 0000000..bf691b9 Binary files /dev/null and b/doc/pui/legendplaces.png differ diff --git a/doc/pui/pooh.png b/doc/pui/pooh.png new file mode 100644 index 0000000..399e906 Binary files /dev/null and b/doc/pui/pooh.png differ diff --git a/doc/pui/puArrowButton.png b/doc/pui/puArrowButton.png new file mode 100644 index 0000000..2e22cef Binary files /dev/null and b/doc/pui/puArrowButton.png differ diff --git a/doc/pui/puBiSlider.png b/doc/pui/puBiSlider.png new file mode 100644 index 0000000..a862dd0 Binary files /dev/null and b/doc/pui/puBiSlider.png differ diff --git a/doc/pui/puButton.png b/doc/pui/puButton.png new file mode 100644 index 0000000..5cbfa7f Binary files /dev/null and b/doc/pui/puButton.png differ diff --git a/doc/pui/puButtonBox.png b/doc/pui/puButtonBox.png new file mode 100644 index 0000000..ce86859 Binary files /dev/null and b/doc/pui/puButtonBox.png differ diff --git a/doc/pui/puComboBox.png b/doc/pui/puComboBox.png new file mode 100644 index 0000000..27e925c Binary files /dev/null and b/doc/pui/puComboBox.png differ diff --git a/doc/pui/puDial.png b/doc/pui/puDial.png new file mode 100644 index 0000000..022d9e1 Binary files /dev/null and b/doc/pui/puDial.png differ diff --git a/doc/pui/puDialogBox.png b/doc/pui/puDialogBox.png new file mode 100644 index 0000000..330e786 Binary files /dev/null and b/doc/pui/puDialogBox.png differ diff --git a/doc/pui/puFileSelector.png b/doc/pui/puFileSelector.png new file mode 100644 index 0000000..b63fae9 Binary files /dev/null and b/doc/pui/puFileSelector.png differ diff --git a/doc/pui/puFrame.png b/doc/pui/puFrame.png new file mode 100644 index 0000000..20c7c0d Binary files /dev/null and b/doc/pui/puFrame.png differ diff --git a/doc/pui/puInput.png b/doc/pui/puInput.png new file mode 100644 index 0000000..1f0277a Binary files /dev/null and b/doc/pui/puInput.png differ diff --git a/doc/pui/puLargeInput.png b/doc/pui/puLargeInput.png new file mode 100644 index 0000000..0b87362 Binary files /dev/null and b/doc/pui/puLargeInput.png differ diff --git a/doc/pui/puListBox.png b/doc/pui/puListBox.png new file mode 100644 index 0000000..0f096ab Binary files /dev/null and b/doc/pui/puListBox.png differ diff --git a/doc/pui/puMenuBar.png b/doc/pui/puMenuBar.png new file mode 100644 index 0000000..b762ac3 Binary files /dev/null and b/doc/pui/puMenuBar.png differ diff --git a/doc/pui/puOneShot.png b/doc/pui/puOneShot.png new file mode 100644 index 0000000..e5b6cc8 Binary files /dev/null and b/doc/pui/puOneShot.png differ diff --git a/doc/pui/puPopupMenu.png b/doc/pui/puPopupMenu.png new file mode 100644 index 0000000..f43ce38 Binary files /dev/null and b/doc/pui/puPopupMenu.png differ diff --git a/doc/pui/puSelectBox.png b/doc/pui/puSelectBox.png new file mode 100644 index 0000000..77d58de Binary files /dev/null and b/doc/pui/puSelectBox.png differ diff --git a/doc/pui/puSlider.png b/doc/pui/puSlider.png new file mode 100644 index 0000000..04da0b1 Binary files /dev/null and b/doc/pui/puSlider.png differ diff --git a/doc/pui/puText.png b/doc/pui/puText.png new file mode 100644 index 0000000..c7f4def Binary files /dev/null and b/doc/pui/puText.png differ diff --git a/doc/pui/puTriSlider.png b/doc/pui/puTriSlider.png new file mode 100644 index 0000000..2747102 Binary files /dev/null and b/doc/pui/puTriSlider.png differ diff --git a/doc/pui/puVerticalMenu.png b/doc/pui/puVerticalMenu.png new file mode 100644 index 0000000..3d6eb29 Binary files /dev/null and b/doc/pui/puVerticalMenu.png differ diff --git a/doc/pui/simple.png b/doc/pui/simple.png new file mode 100644 index 0000000..49da69a Binary files /dev/null and b/doc/pui/simple.png differ diff --git a/doc/pw/index.html b/doc/pw/index.html new file mode 100644 index 0000000..987770e --- /dev/null +++ b/doc/pw/index.html @@ -0,0 +1,203 @@ + + + + + + + A PLIB Windowing Library. + + + + + + + + + + +
+

A PLIB Windowing Library.

+
+ by Steve Baker +
+

Introduction

+PW is now just one component of PLIB. +

+The PLIB minimal Windowing Library (PW) is a portable interface that makes +it as simple as possible to make an OpenGL application that can open a +single window and read the mouse and keyboard. It is a wrapper to make the +various underlying OS mechanisms look the same to application code. +

+You should include the PW header file '/usr/include/plib/pw.h' +and link to the PW library '/usr/lib/libplibpw.a'. +

+Before using any other PW functions, you should initialise the +library by calling either: +

+
+void pwInit ( int multisample, int num_samples ) ;
+
+
+...or: +
+
+void pwInit ( int x, int y, int w, int h,
+              int multisample,
+              char *title, int border, int num_samples ) ;
+
+
+The first version creates a full-screen window with no borders, +titles, etc (or at least as close to that as your OS can manage). +The second version creates a window with it's origin at (x,y) of +dimensions w x h, with the specified title string, and optionally +with or without a border. +

+The window that's created will have the maximum number of colours +that your system supports - double-buffered plus a Z buffer. +

+Both forms allow you to specify whether you'd like multisampling +to be enabled or not - and if so, with how many samples. If your +system cannot produce the number of samples requested, pwInit will +fall back to the best it can do. +

+Then, initialise other PLIB components such as PUI. When initialisation +is complete, call this function: +

+
+void pwCallbacks ( pwKeybdFunc    *kb = NULL, pwMouseFunc *ms = NULL,
+                   pwMousePosFunc *mp = NULL, pwResizeCB *rcb = NULL,
+                   pwExitCB      *ecb = NULL ) ;
+
+
+These parameters are callback functions for (repectively) +incoming keyboard keystrokes, incoming mouse button press or +release events, mouse movements, window resize events and finally, +a window close callback. (That's invoked by PW when the user attempts +to close the window by pressing the exit button on the window border.) +PW also calls the exit function when it detects a fatal error that +occurs after the window has been successfully opened. +

+Your application has to be prepared for these callbacks to be invoked +at any time after pwCallbacks. PW allows you to issue OpenGL calls +any time after pwInit(). +

+The specifications of these various callbacks are: +

+
+typedef void pwResizeCB ( int w, int h ) ;
+typedef void pwExitCB   () ;
+typedef void pwKeybdFunc    ( int key, int updown, int x, int y ) ;
+typedef void pwMouseFunc    ( int button, int updown, int x, int y ) ;
+typedef void pwMousePosFunc ( int x, int y ) ;
+
+
+The 'updown' parameter is set to PW_DOWN when a key or mouse button +is pressed or to PW_UP when it's released. The 'key' parameter is +either an ASCII character or one of: +
+
+ PW_KEY_F1       PW_KEY_F2       PW_KEY_F3       PW_KEY_F4       
+ PW_KEY_F5       PW_KEY_F6       PW_KEY_F7       PW_KEY_F8       
+ PW_KEY_F9       PW_KEY_F10      PW_KEY_F11      PW_KEY_F12      
+
+ PW_KEY_LEFT     PW_KEY_UP       PW_KEY_RIGHT    PW_KEY_DOWN     
+
+ PW_KEY_PAGE_UP  PW_KEY_PAGE_DOWN
+
+ PW_KEY_HOME     PW_KEY_END      PW_KEY_INSERT   
+
+
+The 'button' parameter is one of: +
+
+ PW_LEFT_BUTTON  PW_MIDDLE_BUTTON  PW_RIGHT_BUTTON
+
+
+These constants are chosen to be identical to the similarly named +constants used in the PLIB PUI library so that it's easy to connect +a PUI GUI to a PW window. +

+Once the window is initialised, you may call other PLIB graphics +initialisations (puInit, ssgInit, etc). +

+So now you have your window open, you only need to do one thing - +call this function once per frame: +

+
+void pwSwapBuffers () ;
+
+
+This function swaps the double-buffers, collects keystrokes, mouse events +and resize events and calls whatever application-defined callbacks are +needed. It is NOT LEGAL to call pwSwapBuffers() from inside a PW callback +function. +

+When you wish to close the PW window, you should call: +

+
+void pwCleanup () ;
+
+
+Some applications need to know when the shift/control/alt keys are being +held down by the user: +
+
+int pwGetModifiers () ;
+
+
+This returns the state of those three keys as the OR of the three constants: +
+
+ PW_SHIFT  PW_CTRL  PW_ALT   
+
+
+Note that the results are only valid inside of a callback called from +pwSwapBuffers(). +

+By default, PW disallows auto-repeat of keyboard keys. This is generally what +you want for games. However, it's possible that you may want auto-repeat to +be enabled: +

+
+   void pwSetAutoRepeatKey ( bool enable ) ;
+
+
+If the user has told the windowing system that auto repeat should be off as +some kind of a global preference then pwSetAutoRepeatKey(true) won't turn +it back on again. +

+Finally, there are a number of functions for setting and getting the window +position and dimensions - also to set the current cursor shape: +

+
+void pwGetSize       ( int *w, int *h ) ;
+void pwSetSizeOrigin ( int x, int y, int w, int h ) ;
+void pwSetSize       ( int x, int y ) ;
+void pwSetOrigin     ( int w, int h ) ;
+void pwSetCursor     ( int c ) ;
+
+
+The available cursor shapes for pwSetCursor are: +
+
+   PW_CURSOR_NONE    0
+   PW_CURSOR_RIGHT   1
+   PW_CURSOR_LEFT    2
+   PW_CURSOR_QUERY   3
+   PW_CURSOR_AIM     4
+   PW_CURSOR_CIRCLE  5
+   PW_CURSOR_WAIT    6
+   PW_CURSOR_CROSS   7
+   PW_CURSOR_CUSTOM  8
+
+
+
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+ + + + diff --git a/doc/requirements.html b/doc/requirements.html new file mode 100644 index 0000000..eb88a0f --- /dev/null +++ b/doc/requirements.html @@ -0,0 +1,147 @@ + + + + + PLIB: Requirements & Portability. + + + + + + + + + +
+PLIB Logo +
+
+
+

+ STEVE'S + PORTABLE + GAME + LIBRARY. +

+
+
+
    +And Lo, the Lion and the Sheep shall lie down together - but the Sheep won't +get much Sleep. +
    +-- Woody Allen +
+
+ +Sourceforge Logo +
+
+ + + + + + +
+HOME
+WHAT'S INSIDE
+LICENSE
+CONTACTS
+REQUIREMENTS
+GALLERY
+DOWNLOAD & INSTALL
+EXAMPLES
+ +SG +SSG
+ +SSGAUX +FNT
+ +PUI +PSL + +UL +JS
+ +NET +SL
+ +PW +PUAUX
+ + +
+

Hardware Requirements for Running PLIB

+To do good 3D graphics, you'll need an OpenGL-compatible 3D graphics +accellerator that your operating system supports. Most systems can +run OpenGL in software only - but performance is so poor as to be +unusable in the kinds of application for which PLIB is intended. +

+If you want to hear sound effects and music, you'll obviously +need a sound card and some speakers or headphones. + +

Software Requirements for Running PLIB

+The PLIB team works hard to minimise our dependance on other +libraries to make it easy for end-users to install application +software without having to visit dozens of web sites to collect +the libraries they need. +
    +
  • 3D/2D Graphics: OpenGL. If you aren't already set up to + run OpenGL, you should check: +
      +
    • The OpenGL ARB site. +
    • Or download Mesa + (which is an excellent OpenGL clone by Brian Paul). +
    • If you are a Linux user, you may wish to check the + Linux3D Site. +
    • If you are a Windoze or Macintosh user, you should have + had a copy of OpenGL delivered with your operating + system. +
    +
  • Windowing: From version 1.8.0, PLIB itself is completely independent of + any other windowing library. However, some of the demo and example + programs use freeglut (or at a + pinch: + the original + GLUT (GL Utility Toolkit by Mark Kilgard). + freeglut + works very well with PLIB applications and is maintained by + many of the same people - so there is good continuity. + It's perfectly possible to write PLIB programs that don't use + either GLUT or freeglut - for example, you can use PLIB with + SDL). +
+ +

How Portable is PLIB?

+VERY! +
    +
  • All flavors of Linux are supported - on any CPU platform that + supports Xfree86 and OpenGL. +
  • All flavors of Win32 are + supported, using either MSVC++ or CygWin for compilation. + Theoretically you could use Borland C++ also, but since there is little + user base these days, the necessary 'project' files to build PLIB + under Borland's IDE tend to get outdated. +
  • Most other UNIX-like systems (at least BSD, IRIX, Solaris, OS-X) providing + they support X-windows. +
  • MacOS-X is also reasonably well supported. +
  • MacOS-9 runs everything except the joystick library. However, it's getting + hard to find people to test this port - so it may have problems by the time + you come to use it. +
  • Support for BeOS is problematic - for some reason, people who are prepared + to help out with porting PLIB to BeOS are hard to find. However, since + BeOS (I'm told) has compatibility with X, OpenGL and OSS, it should + be easy to port to and may just work 'out of the box'. +
+ +
+
+
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+ + diff --git a/doc/requirements.png b/doc/requirements.png new file mode 100644 index 0000000..7958ee3 Binary files /dev/null and b/doc/requirements.png differ diff --git a/doc/sg/index.html b/doc/sg/index.html new file mode 100644 index 0000000..216d58e --- /dev/null +++ b/doc/sg/index.html @@ -0,0 +1,1107 @@ + + + + + + + A Simple Geometry library for OpenGL. + + + + + + + + + + +
+

A Simple Geometry library for OpenGL

+
+ by Steve Baker +
+

Introduction

+Simple Geometry (SG) is simple set of matrix, quaternion and vector +math functions that were originally written to support the SSG +(Simple Scene Graph) API - but which are rather useful +for all sorts of OpenGL applications. +

+SG is now a part of PLIB. +

+Since SG is designed to work with OpenGL, it uses similar +naming conventions - all SG functions and other tokens +that work with 'float' precision math begin with 'sg' or 'SG'. +There are a complete duplicate set that work with double-precision +math that begin with 'sgd' or 'SGD'. +

+Most SG functions are implemented as 'inline' C++ +functions - for speed. The underlying data types are +mostly just arrays of 'float' - which is generally the most +efficient type for OpenGL programs. +

+SGD functions are absolutely identical to their SG +eqivelents - except for working at double precision. +This document doesn't describe the SGD functions, types +and constants. That would just be a waste of space - they +are just identical to the SG versions. +

Usage.

+You need to #include "sg.h" and link to the SG binary. +

Basic SG Types.

+Most SG functions operate on SGfloat data elements - which +are normally '#define'd as 'float'. Common data types are: +
+
+  SGfloat    -- A floating point number.
+  sgVec2     -- A two   element array of SGfloat
+  sgVec3     -- A three element array of SGfloat
+  sgVec4     -- A four  element array of SGfloat
+
+  sgMat4     -- A 4x4 element array of SGfloat
+
+  sgCoord    -- A simple structure used to hold
+                euler rotation angles and a 3D
+                translation:
+
+       struct sgCoord
+       {
+         sgVec3 xyz ;
+         sgVec3 hpr ;
+       } ;
+
+  sgLine3    -- An infinite line defined by a point
+                somewhere on the line and a normalized
+                direction vector.
+
+       struct sgLine3
+       {
+	 sgVec3 point_on_line ;
+	 sgVec3 direction_vector ;  /* Should be a unit vector */
+       } ;
+
+  sgLineSegment3 -- A finite line segment defined by it's
+                end-points.
+
+       struct sgLineSegment3
+       {
+	 sgVec3 a ;
+	 sgVec3 b ;
+       } ;
+
+  sgQuat     -- An sgVec4 holding the values (x, y, z, w),
+                representing the quaternion w + xi + yj + zk.
+
+  class sgSphere   -- A sphere
+  class sgBox      -- An axially aligned box.
+  class sgFrustum  -- An OpenGL-style view frustum
+
+  ...and the same again but in 'double' precision:
+
+    SGDfloat, sgdVec2, sgdVec3, sgdVec4,
+    sgdMat4, sgdCoord, sgdQuat, sgdSphere,
+    sgdBox, sgdFrustum
+
+
+Note 1: All angles used by or produced by SG are in degrees. +

+Note 2: Some functions refer to 'angle+axis' notation for rotations, +this is the same format that glRotate uses. +

sgVec*

+The sgVec* types are just simple arrays - designed especially +to hold values for OpenGL vertices, normals, texture coordinates +and colours with the minimum of fuss. These arrays come in 2, 3 and +four element versions - and almost all SG functions that can +operate on an sgVec are provided in three appropriately named +versions, one for each length varient. By convention, the +elements are in the order: +
    +
  • (X,Y), (X,Y,Z), (X,Y,Z,W) for vertices +
  • (S,T), (S,T,R), (S,T,R,Q) for texture coordinates +
  • (R,G,B), (R,G,B,A) for colours (two element arrays don't + make much sense as colours). +
  • (H,P,R) for heading/pitch/roll euler angle triplets. +
  • (nX,nY,nZ) for normals. +
  • (A,B,C,D) for plane equations. +
+

Lines

+A couple of SG functions take or produce data for a line in space. +There are generally two ways to specify a 3D line, either as +two points that lie on the line - or as one point and a direction +vector. +

+SG calls the first form a "line segment" (sgLineSegment3) and the +second form an "infinite line" (sgLine3). +

+You can find the infinite line that is the extension of a line segment +using: +

+
+  void sgLineSegment3ToLine3 ( sgLine3 *line,
+                         const sgLineSegment3 lineseg ) ;
+
+
+You can also find the distance from a point to either a line +or a line segment using: +
+
+  SGfloat sgDistToLineVec3               ( const sgLine3 line,
+					   const sgVec3  pnt )
+  SGfloat sgDistToLineSegmentVec3        ( const sgLineSegment3 line,
+					   const sgVec3  pnt )
+  SGfloat sgDistSquaredToLineVec3        ( const sgLine3 line,
+					   const sgVec3  pnt ) ;
+  SGfloat sgDistSquaredToLineSegmentVec3 ( const sgLineSegment3 line,
+					   const sgVec3  pnt ) ;
+
+
+Try to use the 'Squared' versions if you can because you +save a costly sqrt() function. +

sgMat4

+sgMat4 arrays are SM_float[4][4] arrays for convenience - but notice +that the order of the elements is such that you can take the +address of an sgMat4, cast that into a 'float *' ('double *' for +SGD) and pass the result to any OpenGL matrix function. eg: +
+
+   sgMat4 m ;
+   sgMakeIdentMat4 ( m ) ;
+   glLoadMatrixf ( (GMfloat *) m ) ;
+
+...or...
+
+   sgdMat4 m ;
+   sgdMakeIdentMat4 ( m ) ;
+   glLoadMatrixd ( (GMdouble *) m ) ;
+
+
+Another way to look at this is to treat an sgMat4 as an array +of four sgVec4's. This is convenient for quite a few reasons. +For example, you can extract the sgVec3 that represents the +translation part of an sgMat4 by just using mat[3] anywhere +where an sgMat3 would be appropriate. +

sgTriangleSolver functions

+Remember all those high-school trig problems (eg "Given two +sides and included angle, find length of remaining side")... +nope - neither do I. That's why these functions are useful. +

+ + + + + +
+NOTES: +
    +
  • lenA, lenB, lenC = The lengths of sides A, B and C. +
  • angA, angB, angC = The angles opposite sides A, B and C. +
  • SSS = Three sides. +
  • SAS = Two sides and the angle between them. +
  • ASA = Two angles and the side between them. +
  • SAA = One side and two angles that don't include it. +
  • ASS = Two sides and one angle that's not between them. +
+
+
Triangle
+
+A triangle can be specified completely using the 'SSS', 'SAS', +'SSA' and 'ASA' methods - but if you only know two sides and an +angle that's NOT between those two sides (the 'ASS' method) then +there are often two possible triangles that fit that description. +

+Hence (in the ASS case), SG needs to know whether one of the +unknown vertices is greater than 90 degrees (Obtuse) or less +than 90 degrees (Acute). Hence the two routines below that use +ASS notation have to be told whether angA is Obtuse or not. +

+
+void sgTriangleSolver_SSStoAAA ( SGfloat  lenA, SGfloat  lenB, SGfloat  lenC,
+                                 SGfloat *angA, SGfloat *angB, SGfloat *angC ) ;
+void sgTriangleSolver_SAStoASA ( SGfloat  lenA, SGfloat  angB, SGfloat  lenC,
+                                 SGfloat *angA, SGfloat *lenB, SGfloat *angC ) ;
+void sgTriangleSolver_ASAtoSAS ( SGfloat  angA, SGfloat  lenB, SGfloat  angC,
+                                 SGfloat *lenA, SGfloat *angB, SGfloat *lenC ) ;
+void sgTriangleSolver_SAAtoASS ( SGfloat  lenA, SGfloat  angB, SGfloat  angA,
+                                 SGfloat *angC, SGfloat *lenB, SGfloat *lenC ) ;
+void sgTriangleSolver_ASStoSAA ( SGfloat  angB, SGfloat  lenA, SGfloat  lenB,
+                                 bool angA_is_obtuse,
+                                 SGfloat *lenC, SGfloat *angA, SGfloat *angC ) ;
+
+
+These functions take three parameters which are a mixture of lengths and angles +for an arbitary triangle. They return the missing three parameters. +In all cases of 'degenerate' triangles (eg zero angles, zero lengths), the +package comes up with a plausible result - although it may not be a unique +solution. This should be robust and more roundoff-error-tolerant than +producing an error return. +

+Impossible triangles will produce all-zero results. +

+If one or more of the results are not needed, pass a NULL pointer for it +and the package can avoid doing the unnecessary trig and perhaps run a +little faster. +

+
+SGfloat sgTriangleSolver_ASAtoArea ( SGfloat angA, SGfloat lenB, SGfloat angC ) ;
+SGfloat sgTriangleSolver_SAStoArea ( SGfloat lenA, SGfloat angB, SGfloat lenC ) ;
+SGfloat sgTriangleSolver_SSStoArea ( SGfloat lenA, SGfloat lenB, SGfloat lenC ) ;
+SGfloat sgTriangleSolver_SAAtoArea ( SGfloat lenA, SGfloat angB, SGfloat angA ) ;
+SGfloat sgTriangleSolver_ASStoArea ( SGfloat angB, SGfloat lenA, SGfloat lenB,
+                                     bool angA_is_obtuse ) ;
+
+
+These compute the area of a triangle from three parameters. Impossible +triangles (eg lenA > lenB+lenC) return zero areas. +

sgCoord

+This simple structure contains two members - each of type +'sgVec3' - the first is 'xyz', the second 'hpr' - and together, +they represent a rotation followed by a translation. +

+There is a rich set of functions to interconvert sgCoord's and +sgMat4's. +

sgQuat

+The sgQuat is an array of four floats, (x, y, z, w), respresenting +the quaternion q = w + xi + yj + zk. +

+It can be used to encode rotations. +The quaternion (sin(a) * v, cos(a)) rotates 2*a about the vector v. +

+There is a rich set of functions to interconvert sgQuat's and +other rotation structures. +

sgSphere

+An sgSphere contains a sgVec3 for the center of the sphere and +an SGfloat for the radius. +
+
+class sgSphere
+{
+public:
+  sgVec3  center ;
+  SGfloat radius ;
+
+  SGfloat *getCenter (void) ;
+  SGfloat  getRadius (void) ;
+
+  void setCenter ( SGfloat x, SGfloat y, SGfloat z ) ;
+  void setRadius ( SGfloat r ) ;
+
+  int isEmpty (void) ;
+  void empty  (void) ;
+
+  void orthoXform ( sgMat4 m ) ;
+
+  void extend ( sgSphere *s ) ;
+  void extend ( sgBox    *b ) ;
+  void extend ( sgVec3    v ) ;
+
+  int intersects ( sgSphere *s ) ;
+  int intersects ( sgVec4 plane ) ;
+  int intersects ( sgBox *b ) ;
+} ;
+
+
+Since sgSphere's are frequently used as simple bounding shapes +for field-of-view culling, it's quite useful to be able to represent +an 'empty' sphere. This is represented using a sphere of +Negative radius. +

+The 'isEmpty()' function tests to see if a sphere is empty and the +'empty()' function forces the sphere to be empty. +

+The 'orthoXform(m)' function transforms the sphere using the matrix +'m' - which must be orthographic (since transforming a sphere +by a non-ortho matrix yields something that's no longer spherical). +

+Three 'extend' functions allow you to expand the sphere to +encompass other shapes. These functions attempt to minimise +the radius of the resulting sphere: +

+
+  void extend ( sgSphere *s ) ;
+  void extend ( sgBox    *b ) ;
+  void extend ( sgVec3    v ) ;
+
+
+There are also three intersection tests that return TRUE if the +volume contained by the sphere intersects the volume contained +by the other object: +
+
+  int intersects ( sgSphere *s ) ;
+  int intersects ( sgBox *b ) ;
+  int intersects ( sgVec4 plane ) ;
+
+
+('plane' in this context means the semi-infinite volume bounded +by that plane). +

sgBox

+An sgBox contains an sgVec3 for the vertex of the cube +at the minimum (X,Y,Z) and another at the maximum (X,Y,Z). +
+
+class sgBox
+{
+public:
+  sgVec3 min ;
+  sgVec3 max ;
+
+  SGfloat *getMin (void) ;
+  SGfloat *getMax (void) ;
+
+  void setMin ( SGfloat x, SGfloat y, SGfloat z ) ;
+  void setMax ( SGfloat x, SGfloat y, SGfloat z ) ;
+
+  int isEmpty(void) ;
+  void empty (void) ;
+
+  void extend  ( sgSphere *s ) ;
+  void extend  ( sgBox    *b ) ;
+  void extend  ( sgVec3    v ) ;
+
+  int intersects ( sgSphere *s ) ;
+  int intersects ( sgBox    *b ) ;
+  int intersects ( sgVec4   plane ) ;
+} ;
+
+
+
+Since sgBox'es are frequently used as simple bounding shapes +for field-of-view culling, it's quite useful to be able to represent +an 'empty' box. This is represented using a box whose minumum vertex +has larger X, Y or Z than its maximum vertex. +

+The 'isEmpty()' function tests to see if a box is empty and the +'empty()' function forces the box to be empty. +

+Three 'extend' functions allow you to expand the box to +encompass other shapes. These functions attempt to minimise +the size of the resulting box: +

+
+  void extend ( sgSphere *s ) ;
+  void extend ( sgBox    *b ) ;
+  void extend ( sgVec3    v ) ;
+
+
+There are also three intersection tests that return TRUE if the +volume contained by the box intersects the volume contained +by the other object: +
+
+  int intersects ( sgSphere *s ) ;
+  int intersects ( sgBox *b ) ;
+  int intersects ( sgVec4 plane ) ;
+
+
+('plane' in this context means the semi-infinite volume bounded +by that plane). +

sgFrustum

+An sgFrustum corresponds to the set of parameters that is +used to describe an OpenGL view frustum. +
+
+class sgFrustum
+{
+public:
+
+  sgFrustum (void) ;
+
+  void setFrustum ( SGfloat left  , SGfloat right,
+                    SGfloat bottom, SGfloat top,
+                    SGfloat near  , SGfloat far ) ;
+  void setFOV     ( SGfloat h, SGfloat v ) ;
+  void setNearFar ( SGfloat n, SGfloat f ) ;
+ 
+  SGfloat getHFOV (void) ;
+  SGfloat getVFOV (void) ;
+  SGfloat getNear (void) ;
+  SGfloat getFar  (void) ;
+  SGfloat getLeft (void) ;
+  SGfloat getRight(void) ;
+  SGfloat getTop  (void) ;
+  SGfloat getBot  (void) ;
+
+  void getFOV     ( SGfloat *h, SGfloat *v ) ;
+  void getNearFar ( SGfloat *n, SGfloat *f ) ;
+
+  int  contains ( sgVec3    p ) ;
+  int  contains ( sgSphere *s ) ;
+} ;
+
+
+There are two ways to use an sgFrustum: +
    +
  • You can call setNearFar() and setFOV() to set the near/far + clip planes and the field of view (in degrees - horizontally + and vertically). You can use all the get*() functions to + query the frustum. +
  • You can call setFrustum - with the same parameters as you'd + pass to a glFrustum command. You can subsequently update the + near/far planes with setNearFar() and use all the get*() + functions EXCEPT getFOV(). Since glFrustum allows one to + define all kinds of skewed frustums, it is impossible to + return meaningful FOV figures. +
+The constructor for an sgFrustum produces a simple +45 degree by 45 degree frustum with the near clip +at one unit and the far clip at one million units. +When using setFOV, the application programmer should be +aware that aspect ratios are not enforced, thus these +ratios can deviate from the window aspect ratio. +If this happens, a sphere will look like an ellipse. +
+
+  int  contains ( sgVec3    p ) ;
+  int  contains ( sgSphere *s ) ;
+
+
+...returns SG_OUTSIDE if the point or sphere lies entirely outside +the volume contained by the frustum, SG_INSIDE if it lies entirely +inside the frustum - or SG_STRADDLE if they only partially overlap. +

Constants.

+Since finding a portable definition for PI is impossible (thanks Mr Gates), +SG supplies a suitable definition - and some convenience multipliers +to convert degrees to radians and back again. +
+
+#define SG_PI
+#define SG_DEGREES_TO_RADIANS
+#define SG_RADIANS_TO_DEGREES
+
+
+

Vector functions:

+Pretty much all the low level vector functions are available for +sgVec2, sgVec3 and sgVec4. The order of parameters is always +destination first, operands next - in the order that you'd +write them in a C-style assignment statement. Hence (for example): +
+
+  sgAddVec3 ( dst, a, b ) ;   /* dst = a + b ; */
+  sgAddVec3 ( dst, a ) ;      /* dst += a ; */
+
+
+The following functions exist: +
    +
  • Zero - set all elements to zero. +
  • Set - set each element individually. +
  • Add - add vectors element by element. +
  • Sub - subtract vectors element by element. +
  • Scale - multiply each element of a vector by a variable. +
  • AddScaled - dst+=src*scale or dst = a + b * scale. +
  • Negate - negate each element of a vector. +
  • Compare - compare vectors element by element with optional tolerance. + (return TRUE if vectors are equal - within tolerances) +
  • Equal - return TRUE if vectors are exactly equal. +
  • Length - compute length of a vector. +
  • Distance - compute distance between two points. +
  • DistanceSquared - compute the square of the distance between two points. +
  • ScalarProduct - scalar (dot) product. +
  • VectorProduct - vector (cross) product (3-element vectors ONLY!). +
  • Normalise/Normalize - make vector be one unit long. +
  • Lerp - linear interpolate between a and b by fraction 'f'. +
  • LerpAngle - Lerp allowing for the modulo-360 problem. +
+Here are all the function prototypes - as you can see, the names +are 100% consistent and the paramter order is easy to remember. +
+  void sgZeroVec2 ( sgVec2 dst ) ;
+  void sgZeroVec3 ( sgVec3 dst ) ;
+  void sgZeroVec4 ( sgVec4 dst ) ;
+
+  void sgSetVec2  ( sgVec2 dst, SGfloat x, SGfloat y ) ;
+  void sgSetVec3  ( sgVec3 dst, SGfloat x, SGfloat y, SGfloat z ) ;
+  void sgSetVec4  ( sgVec4 dst, SGfloat x, SGfloat y, SGfloat z, SGfloat w ) ;
+
+  void sgCopyVec2 ( sgVec2 dst, sgVec2 src )
+  void sgCopyVec3 ( sgVec3 dst, sgVec3 src )
+  void sgCopyVec4 ( sgVec4 dst, sgVec4 src )
+
+  void sgAddVec2  ( sgVec2 dst, sgVec2 src )
+  void sgAddVec3  ( sgVec3 dst, sgVec3 src )
+  void sgAddVec4  ( sgVec4 dst, sgVec4 src )
+
+  void sgAddVec2  ( sgVec2 dst, sgVec2 src1, sgVec2 src2 )
+  void sgAddVec3  ( sgVec3 dst, sgVec3 src1, sgVec3 src2 )
+  void sgAddVec4  ( sgVec4 dst, sgVec4 src1, sgVec4 src2 )
+
+  void sgSubVec2  ( sgVec2 dst, sgVec2 src )
+  void sgSubVec3  ( sgVec3 dst, sgVec3 src )
+  void sgSubVec4  ( sgVec4 dst, sgVec4 src )
+
+  void sgSubVec2  ( sgVec2 dst, sgVec2 src1, sgVec2 src2 )
+  void sgSubVec3  ( sgVec3 dst, sgVec3 src1, sgVec3 src2 )
+  void sgSubVec4  ( sgVec4 dst, sgVec4 src1, sgVec4 src2 )
+
+  void sgNegateVec2 ( sgVec2 dst )
+  void sgNegateVec3 ( sgVec3 dst )
+  void sgNegateVec4 ( sgVec4 dst )
+
+  void sgNegateVec2 ( sgVec2 dst, sgVec2 src )
+  void sgNegateVec3 ( sgVec3 dst, sgVec3 src )
+  void sgNegateVec4 ( sgVec4 dst, sgVec4 src )
+
+  void sgScaleVec2  ( sgVec2 dst, SGfloat s )
+  void sgScaleVec3  ( sgVec3 dst, SGfloat s )
+  void sgScaleVec4  ( sgVec4 dst, SGfloat s )
+
+  void sgScaleVec2  ( sgVec2 dst, sgVec2 src, SGfloat s )
+  void sgScaleVec3  ( sgVec3 dst, sgVec3 src, SGfloat s )
+  void sgScaleVec4  ( sgVec4 dst, sgVec4 src, SGfloat s )
+
+  void sgAddScaledVec2  ( sgVec2 dst, svVec2 src, SGfloat s )
+  void sgAddScaledVec3  ( sgVec3 dst, svVec3 src, SGfloat s )
+  void sgAddScaledVec4  ( sgVec4 dst, svVec4 src, SGfloat s )
+
+  void sgAddScaledVec2  ( sgVec2 dst, sgVec2 a, svVec2 b, SGfloat s )
+  void sgAddScaledVec3  ( sgVec3 dst, sgVec3 a, svVec3 b, SGfloat s )
+  void sgAddScaledVec4  ( sgVec4 dst, sgVec4 a, svVec4 b, SGfloat s )
+
+  int sgCompareVec2 ( sgVec2 a, sgVec2 b, SGfloat tol )
+  int sgCompareVec3 ( sgVec3 a, sgVec3 b, SGfloat tol )
+  int sgCompareVec4 ( sgVec4 a, sgVec4 b, SGfloat tol )
+
+  int sgEqualVec2   ( sgVec2 a, sgVec2 b )
+  int sgEqualVec3   ( sgVec3 a, sgVec3 b )
+  int sgEqualVec4   ( sgVec4 a, sgVec4 b )
+
+  SGfloat sgScalarProductVec2 ( sgVec2 a, sgVec2 b )
+  SGfloat sgScalarProductVec3 ( sgVec3 a, sgVec3 b )
+  SGfloat sgScalarProductVec4 ( sgVec4 a, sgVec4 b )
+
+  void sgVectorProductVec3 ( sgVec3 dst, sgVec3 a, sgVec3 b )
+
+  SGfloat sgLerp ( SGfloat a, SGfloat b, SGfloat f )
+
+  void sgLerpVec2 ( sgVec2 dst, sgVec2 a, sgVec2 b, SGfloat f )
+  void sgLerpVec3 ( sgVec3 dst, sgVec3 a, sgVec3 b, SGfloat f )
+  void sgLerpVec4 ( sgVec4 dst, sgVec4 a, sgVec4 b, SGfloat f )
+
+  SGfloat sgDistanceSquaredVec2 ( sgVec2 a, sgVec2 b )
+  SGfloat sgDistanceSquaredVec3 ( sgVec3 a, sgVec3 b )
+  SGfloat sgDistanceSquaredVec4 ( sgVec4 a, sgVec4 b )
+
+  SGfloat sgDistanceVec2 ( sgVec2 a, sgVec2 b )
+  SGfloat sgDistanceVec3 ( sgVec3 a, sgVec3 b )
+  SGfloat sgDistanceVec4 ( sgVec4 a, sgVec4 b )
+
+  SGfloat sgLengthVec2 ( sgVec2 src )
+  SGfloat sgLengthVec3 ( sgVec3 src )
+  SGfloat sgLengthVec4 ( sgVec4 src )
+
+  /* Anglo-US spelling issues.  <sigh> */
+
+  #define sgNormalizeVec2 sgNormaliseVec2
+  #define sgNormalizeVec3 sgNormaliseVec3
+  #define sgNormalizeVec4 sgNormaliseVec4
+
+  void sgNormaliseVec2 ( sgVec2 dst )
+  void sgNormaliseVec3 ( sgVec3 dst )
+  void sgNormaliseVec4 ( sgVec4 dst )
+
+  void sgNormaliseVec2 ( sgVec2 dst, sgVec2 src )
+  void sgNormaliseVec3 ( sgVec3 dst, sgVec3 src )
+  void sgNormaliseVec4 ( sgVec4 dst, sgVec4 src )
+
+
+

Matrix Functions.

+The following functions let you construct an sgMat4 from a variety of +input data formats: +
+
+  void sgCopyMat4      ( sgMat4 dst, sgMat4 src ) ;
+
+  void sgMakeIdentMat4 ( sgMat4 dst ) ;
+
+  void sgMakeCoordMat4 ( sgMat4 dst, SGfloat x, SGfloat y, SGfloat z,
+                                     SGfloat h, SGfloat p, SGfloat r ) ;
+  void sgMakeCoordMat4 ( sgMat4 dst, sgVec3 xyz, sgVec3 hpr )
+  void sgMakeCoordMat4 ( sgMat4 dst, sgCoord *src )
+
+  void sgMakeRotMat4   ( sgMat4 dst, sgVec3 hpr )
+  void sgMakeRotMat4   ( sgMat4 dst, SGfloat h, SGfloat p, SGfloat r )
+  void sgMakeRotMat4   ( sgMat4 dst, SGfloat angle, sgVec3 axis ) ;
+
+  void sgMakeTransMat4 ( sgMat4 dst, sgVec3 xyz ) ;
+  void sgMakeTransMat4 ( sgMat4 dst, SGfloat x, SGfloat y, SGfloat z ) ;
+
+  void sgQuatToMatrix  ( sgMat4 dst, sgQuat quat ) ;
+
+
+
+You can multiply matrices: +
+
+  void sgMultMat4      ( sgMat4 dst, sgMat4 a, sgMat4 b ) ;
+  void sgPostMultMat4  ( sgMat4 dst, sgMat4 a ) ;
+  void sgPreMultMat4   ( sgMat4 dst, sgMat4 a ) ;
+
+
+You can do a cheap matrix inversion (for simple rotate/translate +matrices): +
+
+  void sgTransposeNegateMat4 ( sgMat4 dst ) ;
+  void sgTransposeNegateMat4 ( sgMat4 dst, sgMat4 src ) ;
+
+
+...or a (more costly) full matrix inversion (for more complex matrices): +
+
+  void sgInvertMat4 ( sgMat4 dst ) ;
+  void sgInvertMat4 ( sgMat4 dst, sgMat4 src ) ;
+
+
+You can transform vertices and points using a matrix. The 'Vec*' forms +assume that the vector merely need to be rotated (like you would want +for a surface normal for example) - whilst the 'Pnt*' forms perform +a rotate and translate. If your matrix is more complex and contains +scaling, shearing, perspective and such like, then use the 'FullXform' +versions - which are quite a bit slower than the other forms: +
+
+  void sgXformVec3     ( sgVec3 dst, sgMat4 mat ) ;
+  void sgXformVec3     ( sgVec3 dst, sgVec3 src, sgMat4 mat ) ;
+
+  void sgXformPnt3     ( sgVec3 dst, sgMat4 mat ) ;
+  void sgXformPnt3     ( sgVec3 dst, sgVec3 src, sgMat4 mat ) ;
+
+  void sgFullXformPnt3 ( sgVec3 dst, sgMat4 mat ) ;
+  void sgFullXformPnt3 ( sgVec3 dst, sgVec3 src, sgMat4 mat ) ;
+
+  void sgXformVec4     ( sgVec4 dst, sgMat4 mat ) ;
+  void sgXformVec4     ( sgVec4 dst, sgVec4 src, sgMat4 mat ) ;
+
+  void sgXformPnt4     ( sgVec4 dst, sgMat4 mat ) ;
+  void sgXformPnt4     ( sgVec4 dst, sgVec4 src, sgMat4 mat ) ;
+
+  void sgFullXformPnt4 ( sgVec4 dst, sgMat4 mat ) ;
+  void sgFullXformPnt4 ( sgVec4 dst, sgVec4 src, sgMat4 mat ) ;
+
+
+The properties of a matrix can be tested with: +
+  int sgClassifyMat4 ( const sgMat4 mat ) ;
+
+which returns a bitmask with zero or more of the following bits set: +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
SG_ROTATIONUpper 3x3 includes a rotational component.
SG_MIRRORChanges handedness.
SG_SCALEUniform scaling going on.
SG_NONORTHOUpper 3x3 not orthogonal (including non-uniform scaling).
SG_TRANSLATIONTranslates.
SG_PROJECTIONFourth column not 0,0,0,1.
+ +

Coord routines:

+These routines operate on 'sgCoord' structures: +
+
+  void sgZeroCoord ( sgCoord *dst ) ;
+  void sgSetCoord  ( sgCoord *dst, SGfloat x, SGfloat y, SGfloat z,
+                                   SGfloat h, SGfloat p, SGfloat r ) ;
+  void sgSetCoord  ( sgCoord *dst, sgVec3 xyz, sgVec3 hpr ) ;
+  void sgSetCoord  ( sgCoord *coord, sgMat4 src ) ;
+  void sgCopyCoord ( sgCoord *dst, sgCoord *src ) ;
+
+
+The varient of sgSetCoord that takes a matrix is somewhat tricky since +there is no way to convert matrices that are not simple rotate/translates +into sgCoord's - and even when the matrix is a simple rotate/translate, +there are a number of possible sets of Euler rotations that could +be appropriate to reproduce the behavior of the input matrix. sgSetCoord +picks a valid rotation - but just beware of this behaviour. +

Quaternion routines:

+Quaternions are convenient alternatives to Matrices for storing +rotations. +
+  void sgMakeIdentQuat ( sgQuat dst ) ;
+
+Creates the identity quaternion. (0,0,0,1) +
+  void sgSetQuat ( sgQuat dst, SGfloat w,
+                               SGfloat x,
+                               SGfloat y,
+                               SGfloat z ) ;
+
+Sets the four components of the quaternion. +
+  void sgCopyQuat ( sgQuat dst, sgQuat src ) ;
+
+Copies one quaternion into another. +
+  void sgNormalizeQuat ( sgQuat dst ) ;
+  void sgNormalizeQuat ( sgQuat dst, sgQuat src ) ;
+
+For most operations, quaternions need to be normalized, +these functions ensure that they are. +
+  void sgInvertQuat ( sgQuat dst ) ;
+  void sgInvertQuat ( sgQuat dst, sgQuat src ) ;
+
+Computes the inverse of a quaternion. +
+  void sgQuatToAngleAxis ( SGfloat *angle, sgVec3 axis, const sgQuat src ) ;
+  void sgQuatToAngleAxis ( SGfloat *angle,
+                           SGfloat *x, SGfloat *y, SGfloat *z,
+                           const sgQuat src ) ;
+
+Converts a quaternion into an angle+axis format - just the thing +to pass to glRotate for example. +
+  void sgAngleAxisToQuat ( sgQuat dst, SGfloat angle, const sgVec3 axis ) ;
+  void sgAngleAxisToQuat ( sgQuat dst,
+                           SGfloat angle,
+                           SGfloat x, SGfloat y, SGfloat z ) ;
+
+Converts an angle+axis rotation into a quaternion. +
+  void sgMultQuat     ( sgQuat dst, sgQuat a, sgQuat b ) ;
+  void sgPostMultQuat ( sgQuat dst, sgQuat q ) ;
+  void sgPreMultQuat  ( sgQuat dst, sgQuat q ) ;
+
+Concatenates quaternion rotations. +
+  void sgQuatToMatrix ( sgMat4 mat, sgQuat quat ) ;
+  void sgMatrixToQuat ( sgQuat quat, sgMat4 mat ) ;
+
+Converts between quaternions and rotation matrices. +
+  void sgPostRotQuat ( sgQuat dst, SGfloat angle, sgVec3 axis )
+  void sgPostRotQuat ( sgQuat dst, SGfloat angle,
+                       SGfloat x, SGfloat y, SGfloat z )
+  void sgPreRotQuat  ( sgQuat dst, SGfloat angle,
+                       SGfloat x, SGfloat y, SGfloat z )
+
+Rotates a quaternion by an angle/axis rotation. +
+extern void sgSlerpQuat ( sgQuat dst,
+                          const sgQuat from, const sgQuat to,
+                          const SGfloat t ) ;
+
+Interpolates between two quaternions. +

Miscellaneous Functions.

+
+  void sgHPRfromVec3 ( sgVec3 hpr, sgVec3 src ) ;
+
+This function takes a vector representing a direction and computes +a suitable heading and pitch angle to look along that vector. Since +the roll angle is indeterminate, it is set to zero. +
+  void sgMakeNormal ( sgVec3 dst, sgVec3 a, sgVec3 b, sgVec3 c ) ;
+
+This finds the surface normal of a triangle given three vertices. +

Plane Equation Functions:

+
+  SGfloat sgDistToPlaneVec3 ( sgVec4 plane, sgVec3 pnt ) ;
+
+This returns the distance from the point to the plane. +
+  SGfloat sgHeightAbovePlaneVec3 ( sgVec4 plane, sgVec3 pnt ) ;
+
+This returns the vertical (Z) distance from the point to the +plane (my applications tend to use Z-is-up conventions). +
+  void sgMakePlane ( sgVec4 dst, sgVec3 a, sgVec3 b, sgVec3 c ) ;
+
+This finds the plane equation of a triangle given three vertices. +
+  void sgMakePlane ( sgVec4 dst, sgVec3 normal, sgVec3 pnt ) ;
+
+This finds the plane equation of a plane given its normal and +a point on the plane. +

Intersection Calculations:

+These routines compute the intersections of various geometric +entities: +
+int sgIsectPlanePlane       ( sgVec3 point, sgVec3 dir,
+                              sgVec4 plane1, sgVec4 plane2 ) ;
+
+Two planes intersect along an infinite line. Given two planes, +this routine routines a point and direction for the intersection +line. It returns FALSE if presented with two parallel planes, +TRUE otherwise. +
+int sgIsectInfLinePlane     ( sgVec3 dst,
+                              sgVec3 l_org, sgVec3 l_vec,
+                              sgVec4 plane ) ;
+
+Given a plane, and an infinite line, +this routine routines the point at which they intersect. +It returns FALSE if presented with a line which is parallel +to the plane, TRUE otherwise. +
+int sgIsectInfLineInfLine   ( sgVec3 dst,
+                              sgVec3 l1_org, sgVec3 l1_vec,
+                              sgVec3 l2_org, sgVec3 l2_vec ) ;
+
+Two infinite lines in 3D are unlikely to intersect - even +if you actually expect them to (because of roundoff error). +Hence, this routine sets dst to the closest point on the +second line which is closest to the first line. Return +FALSE if the lines are parallel, TRUE otherwise. +
+SGfloat sgIsectLinesegPlane ( sgVec3 dst,
+                              sgVec3 v1, sgVec3 v2,
+                              sgVec4 plane ) ;
+
+Intersect a line segment with a plane. The return +result is in the range 0..1 if the intersection lies +between v1 and v2, >1 if beyond v2 and <0 if before v1. +FLT_MAX is returned if the vector does not intersect +the plane. +

Interconversion between sg and sgd types:

+The following routines interconvert between double precision +'sgd' types and their single precision 'sg' counterparts: +
+  void sgdSetVec2 ( sgdVec2 dst, sgVec2 src ) ;
+  void sgdSetVec3 ( sgdVec3 dst, sgVec3 src ) ;
+  void sgdSetVec4 ( sgdVec4 dst, sgVec4 src ) ;
+  void sgdSetMat4 ( sgdMat4 dst, sgMat4 src ) ;
+  void sgdSetCoord ( sgdCoord *dst, sgCoord *src ) ;
+
+  void sgSetVec2 ( sgVec2 dst, sgdVec2 src ) ;
+  void sgSetVec3 ( sgVec3 dst, sgdVec3 src ) ;
+  void sgSetVec4 ( sgVec4 dst, sgdVec4 src ) ;
+  void sgSetMat4 ( sgMat4 dst, sgdMat4 src ) ;
+  void sgSetCoord ( sgCoord *dst, sgdCoord *src ) ;
+
+

Perlin Noise.

+There are three classes that implement Perlin Noise functions +(in one, two and three dimensions). +
+
+class sgPerlinNoise_1D
+{
+  sgPerlinNoise_1D () ;
+  void regenerate  () ;
+  SGfloat getNoise ( SGfloat x ) ;
+} ;
+ 
+class sgPerlinNoise_2D
+{
+  sgPerlinNoise_2D () ;
+  void regenerate  () ;
+  SGfloat getNoise ( sgVec2 pos ) ;
+  SGfloat getNoise ( SGfloat x, SGfloat y ) ;
+} ;
+ 
+class sgPerlinNoise_3D
+{
+  sgPerlinNoise_3D () ;
+  void regenerate  () ;
+  SGfloat getNoise ( sgVec3 pos ) ;
+  SGfloat getNoise ( SGfloat x, SGfloat y, SGfloat z ) ;
+} ;
+
+
+In each case, you simply construct the class, then call 'getNoise' +with the coordinate (either one, two or three-dimensional) at which +you need the value for the noise function. Perlin noise is both +repeatable (if you make the same request twice, you get the same +result) and continuous (there are no large jumps between results +for points that are close to one-another). +

+Calling 'regenerate' will cause the function to subsequently +generate a different noise pattern (presuming you didn't re-seed +the 'rand()' function to the same value before each call). +

Spring/Mass/Damper model.

+Many applications can greatly benefit from some simple dynamics +modelling. SG includes two classes that taken together implement +a standard Spring-Mass-Damper model with Euler integration. +
+
+  class sgParticle ;
+  class sgSpringDamper ;
+
+
+The idea is that you connect up a bunch of 'particles' (which each have +mass, position and velocity) using a collection of springs (actually, these +are combinations springs and dampers). Then, each frame, you can apply +forces to some or all of the particles - and perhaps forcably reposition +some of them - then loop around updating all of the spring-damper models +to see what forces they apply to the particles as a result. Finally, you +should call the 'upadate' function for each particle to see where it ends +up some short time later. +
+
+class sgParticle
+{
+  sgParticle ( float mass ) ;
+  sgParticle ( float mass, float x, float y, float z ) ;
+  sgParticle ( float mass, sgVec3 position ) ;
+ 
+  float *getPos         () ;
+  float *getVel         () ;
+  float *getForce       () ;
+  float  getMass        () ;
+ 
+  void   setPos      ( sgVec3 p ) ;
+  void   setVel      ( sgVec3 v ) ;
+  void   setForce    ( sgVec3 f ) ;
+
+  void   setPos      ( float x, float y, float z ) ;
+  void   setVel      ( float x, float y, float z ) ;
+  void   setForce    ( float x, float y, float z ) ;
+
+  void   setMass     ( float  m ) ;
+ 
+  void zeroForce   ()           ;
+  void addForce    ( sgVec3 f ) ;
+  void gravityOnly ()           ;
+
+  void bounce ( sgVec3 normal, float coefRestitution ) ; 
+  void update ( float dt ) ;
+} ;
+
+
+Aside from the obvious set/get routines that allow you to set or get the +particles mass, position, velocity and the total force that's applied to it, +you can also zero the force (a usual thing to do at the start of each cycle) +or set the force equal to normal gravity, or you can add a force to whatever +is currently being applied. The constructor function requires that you +pass in the mass and (optionally) the initial position. The mass of a +particle cannot ever be zero because you'll get divide-by-zero errors +all over the place if you do. +
+
+class sgSpringDamper
+{
+  sgSpringDamper () ;
+  sgSpringDamper ( sgParticle *_p0, sgParticle *_p1,
+                   float _stiffness, float _damping,
+                   float _restLength = -1.0f ) ;
+ 
+  float       getRestLength () ;
+  float       getStiffness  () ;
+  float       getDamping    () ;
+  sgParticle *getParticle   ( int which ) ;
+ 
+  void setParticles ( sgParticle *_p0, sgParticle *_p1 ) ;
+  void setParticle  ( int which, sgParticle *p ) ;
+ 
+  void setRestLength () ;
+ 
+  void setRestLength ( float l ) ;
+  void setStiffness  ( float s ) ;
+  void setDamping    ( float d ) ;
+ 
+  void update () ;
+ 
+} ;
+
+
+Each spring/damper is connected to two sgParticle's. It has a stiffness +and a damping factor plus a 'rest' length (ie how long it is when no +forces are applied to the system). If you omit the rest length, it will be +calculated from the current positions of the two particles. +

+Apart from the usual set/get functions, there is a single 'update' routine +which calculates the forces on the two particles and calls 'addForce' to +each. +

+A typical application will look like this: +

+Initialisation: +

    +
  • Construct all the sgParticle's +
  • Construct all the sgSpringDamper's and connect them to the particles. +
+Initialisation: +Each frame... +
    +
  • For each particle: Set up all the EXTERNAL forces that apply to it: +
      +
    • particle->zeroForce () ; ...or... +
    • particle->gravityOnly () ; ...or... +
    • particle->setForce ( something ) ; +
    + Don't ever just allow the previous frame's forces to continue to be + applied. + +
  • For each spring/damper add in the forces it applies to + the particles it's connected to: spring -> update () ; + +
  • For each particle: Update it's velocity and position: particle -> update ( dt ) + (where 'dt' is the elapsed time since the previous frame). +
  • If the particle collided with something, then you can adjust + it's velocity using: + sgParticle::bounce ( sgVec3 normal, float coefRestitution ) + (Where 'normal' is the surface normal of the plane we hit and + 'coefRestitution' is 1.0 for perfectly elastic surfaces, 0.0 for + ultra-sticky surfaces...or somewhere in between). +
+As always with these systems, if you set the spring stiffness too high, or the +damping coefficient too low, these equations will tend to explode - generating +unreasonably large forces and velocities. The only way to fix this is to back +off the numbers - or call both sets of 'update' functions very frequently. +

+You have been warned! +

+By default, gravity is set to -9.8 meters/sec/sec in the Z direction - but this +assumes you are on earth, using the metric (mks) system and have Z-is-up coordinates. +

+If any of those are not true, you can change the force that 'particle->gravityOnly()' +applies using: +

+
+  void   sgSetGravity     ( float  g ) ;
+  void   sgSetGravityVec3 ( sgVec3 g ) ;
+  float *sgGetGravityVec3 () ;
+  float  sgGetGravity     () ;
+
+
+Note that 'sgSetGravity' and 'sgGetGravity' use positive numbers for the +accelleration due to gravity - and assume Z-is-up. But the 'Vec3' versions +make neither of those assumptions - so make sure the vector you give points +DOWNWARDS! +

+eg +

+
+    sgSetGravity ( 1.6 ) ;   /* On the Moon! */
+
+
+...but... +
+
+    sgSetVec3 ( lunar_gravity, 0.0, 0.0, -1.6 ) ;   /* Note minus sign! */
+    sgSetGravityVec3 ( lunar_gravity ) ;
+
+
+
+

Credits.

+Thanks to Kevin Thompson +who kindly donated the original Quaternion code. +
+ + +
+Valid HTML 4.0! + +
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+
+ + + diff --git a/doc/sg/triangle_params.png b/doc/sg/triangle_params.png new file mode 100644 index 0000000..476a629 Binary files /dev/null and b/doc/sg/triangle_params.png differ diff --git a/doc/sl/index.html b/doc/sl/index.html new file mode 100644 index 0000000..313f9ff --- /dev/null +++ b/doc/sl/index.html @@ -0,0 +1,71 @@ + + + + + + + The SL Sound and Mixer Libraries. + + + +

The SL Sound and Mixer Libraries.

+By Steve Baker +

Introduction.

+The 'SL' sound library is primarily targetted towards producing sound +effects for games, and isn't really intended for playing music (although +you could certainly use it for doing that). The emphasis is on low +CPU impact and low latency rather than high quality and fancy MIDI/MOD +facilities. +

+SL is a part of PLIB. +

+The 'SL' sound library will eventually become a fully portable freeware +sound library that should run on all major platforms. Right now, SL +runs under: +

    +
  • Linux on systems with OSS (the Open Sound System) installed +(it's usually a standard part of the kernel). +
  • Windows NT, 95 and 98. +
  • OpenBSD. +
  • SGI's IRIX. +
  • Other UNIX systems using OSS (which should include Solaris, FreeBSD, +BSD/OS, SCO and others) should be able to run the Linux version of +SL by adding '-DSL_USING_OSS_AUDIO' to the compile command line. +
+At present, there is no support for Apple's MacOS sound systems +- although it is hoped that these will be added in the near future. +
    +
  • The SL Library +deals with all aspects of sample replay for games and +other realtime applications - it is designed such that it can be +ported to other operating systems by replacing just the slDSP +class. +

    +

  • The SM Library +controls the audio mixer on a PC sound card and +probably only works 100% correctly within OSS - and then probably +only on fairly 'vanilla' Soundblaster-compatible sound cards. +Portability of SM is patchy - regard it as a bonus. +
+It is due to the relative non-portability of the SM routines +that these are in a separate library. For non-portable +applications, SL and SM can be considered as a single library. +

+Download the Open Sound System +drivers (previously known as VoxWare). +


+ + +
+Valid HTML 4.0! + +
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+
+ + + diff --git a/doc/sl/mixer.png b/doc/sl/mixer.png new file mode 100644 index 0000000..3a4a701 Binary files /dev/null and b/doc/sl/mixer.png differ diff --git a/doc/sl/sl.html b/doc/sl/sl.html new file mode 100644 index 0000000..be58cf6 --- /dev/null +++ b/doc/sl/sl.html @@ -0,0 +1,1048 @@ + + + + + + + The SL Sound Library. + + + + + + + + +
Imagine clown here

The SL Sound Library.

+By Steve Baker +
+

Introduction.

+This library allows one to play, mix and modify sound samples +in realtime - with a special view towards sound for interactive +systems such as games and simulation. +

+At present, SL can drive PC-style sound cards from +within Windows NT, 95 and 98, Linux and several +other UNIX systems. When not running under Windows, +SL relies on the +Open Sound System (OSS) drivers +(formerly known as `VoxWare') - which are generally a +standard part of the Linux Kernel and are available on +most other UNIX implementations. Notably, the SGI IRIX +operating system does not support OSS - so IRIX is +supported via the proprietary SGI Audio Library. +A future port to the Mac operating system is anticipated. +

+For PC-based Linux systems using relatively 'standard' SoundBlaster +compatible sound cards, there is a companion library 'SM' that allows +one to drive the Audio mixer on your sound card. Since the SM library +is not easily portable to other systems, it is not considered a part +of SL. SM may also be ported to Windows - but it's unlikely that it +will be more generally available so it's use is deprecated. +SM does not exist for IRIX. +

Credits.

+Steve Baker <sjbaker1@airmail.net> wrote the first cut of +the library for Intel-based Linux machines and maintains the +system and its documentation. +

+Tom Knienieder ported SL onto the Windows family of operating +systems, onto OpenBSD and also onto IRIX as a part of the FlightGear project. +

+Curt Olson is the leader of the FlightGear project and provided +useful testing and helpful comments in appropriate quantities. +

Overview

+The SL library allows one to operate at several levels. +
    +
  • class slDSP: Allows you to play raw audio samples, + (one at a time) into the DSP channel + of a typical sound card. This is designed to + be simple enough that it should be portable + onto a wide range of non-OSS systems - and it + is the only SL class that you would need to + port. +

    +

  • class slSample: Allows you to read sound samples from + disk in a range of standard formats, + and to shift their frequency, volume, + etc. +

    +

  • class slScheduler: This layer allows you to play a number + of 8 bit monophonic samples in parallel, + up to three of them are be mixed together + with a simple prioritization scheme to + allow for cases when the application + wants to play more than that. This + class only makes calls to slSample and slDSP + interfaces, and should therefore be quite + portable. +

    + slScheduler will be extended to support 16 bit + samples and stereo in the near future. +

+

Using the Library.

+To use this library, you must '#include "sl.h"' and link to +libsl.a or libsl.so. +

class slDSP.

+Hardly any programs will ever create more than one slDSP object - in fact, +most programs won't explicitly create any slDSP's at all since they'll +be more likely to use slScheduler - which is derived from slDSP. +

+Here are the member functions: +

+
+  class slDSP
+  {
+  public:
+
+    slDSP ( int rate, int stereo, int bps ) ;
+    slDSP ( char *device, int rate, int stereo, int bps ) ;
+   ~slDSP () ;
+    
+    void play ( void *buffer, size_t length ) ;
+
+    int working     () ;  /* For optimists  */
+    int not_working () ;  /* For pessimists */
+
+    int getBps   () ;
+    int getRate  () ;
+    int getStereo() ;
+
+    void sync () ;
+    void stop () ;
+  } ;
+
+
+By default, "/dev/dsp" (or just plain "dsp" under Windows) +is the device used by this class, but +an alternative device may be accessed if it's name is passed +into the constructor. The constructor function also needs to +know the desired sample replay rate, whether the sounds should +be played in stereo (TRUE) or mono (FALSE) and how many bits +per pixel of audio are to be provided (typically 8 or 16). +

+The constructor function cannot guarantee to provide the +exact settings you require since hardware sample replay +units vary considerably in capabilities from one manufacturer +to another. Hence, all applications should call +the slDSP::getBps/getStereo/getRate() commands after the +object has been created. These routines tell the application +the actual number of bits per sample, the stereo setup and +the sample rate that this channel is currently set up to support. +The getRate command gets the sampling rate in Hz. +

+The 'stop' function aborts any sounds that are currently being played +and the 'sync' function blocks until the current audio stream is +flushed. +

+The 'slDSP::not_working()' function returns TRUE if there is any kind of +problem with the driver. Mostly it returns TRUE if your system isn't +set up for audio. 'slDSP::working()' is provided by popular request +and is just the opposite. +

+The driver will not fail if you call it's member functions when +'slDSP::not_working()' returns TRUE - so programs written for audio +should work OK even on hardware with no audio support. +

+The play command takes raw audio data from a buffer in memory +(typically from the buffer of an slSample) and plays it with the +current settings. In 8bps mono mode, the data is a simple +unsigned byte stream. In 16bps mode, the data is a stream +of unsigned shorts and in stereo mode, samples alternate +between left and right channels - left first, then right. +

+Hence, each sound sample can be 1, 2 or 4 bytes long. +

+
+ 8bps Mono  :      L      |      L      |...
+16bps Mono  :    H   L    |    H   L    |...
+ 8bps Stereo:    LL LR    |    LL LR    |...
+16bps Stereo: HL LL HR LR | HL LL HR LR |...
+
+Where: L is a low  order byte (monophonic),
+       H is a high order byte (monophonic),
+      LL is low-order, left channel,
+      LR is low-order, right channel,
+      HL is high-order, left channel,
+      HR is high-order, right channel.
+
+
+

class slSample

+This class is intended to hold all the relevent information that +goes along with a digital sound sample. Most programs will create +a separate slSample for each sound effect or musical note: +
+
+class slSample
+{
+public:
+
+  slSample () ;
+  slSample ( Uchar *buff, int leng ) ;
+  slSample ( char *fname ) ;
+  slSample ( char *fname, slDSP *match ) ;
+ ~slSample () ;
+  char *getComment () ;
+  void   setComment ( char *nc ) ;
+
+  Uchar *getBuffer () ;
+  int    getLength () ;
+  void   setBuffer ( Uchar *buff, int leng ) ;
+
+  void setRate   ( int r ) ;
+  void setBps    ( int b ) ;
+  void setStereo ( int s ) ;
+
+  int  getRate   ()        ;
+  int  getBps    ()        ;
+  int  getStereo ()        ;
+
+  int  getPlayCount ()     ;
+
+  float getDuration ()     ;
+
+  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 autoMatch ( slDSP *player ) ;
+  void adjustVolume ( float vol ) ;
+
+  void print ( FILE *fd ) ;
+} ;
+
+
+There are three ways to construct a slSample - first, you can create +an (initially) empty sample: +
+
+  slSample::slSample () ;
+
+
+Secondly, you can provide a buffer of audio data (with either 1, 2 or 4 +bytes per sample) - along with the length of that buffer (in bytes - +NOT in samples). +
+
+  slSample::slSample ( Uchar *buff, int leng ) ;
+
+
+You can also load a file from disk: +
+
+  slSample::slSample ( char *fname ) ;
+
+
+In that case, slSample will look at the extension of the filename and +choose an appropriate loader for that file type. +

+Since sample files from disk may well not match the settings on +the slDSP that will be replaying it, there is an option to pass +the address of the slDSP that will be doing the replaying and have +the slSample automatically match it's settings to that of the +replay unit. +

+You can load a sample file into a slSample at any time using: +

+
+  int slSample::loadFile    ( char *fname ) ;
+  int slSample::loadRawFile ( char *fname ) ;
+  int slSample::loadAUFile  ( char *fname ) ;
+  int slSample::loadWavFile ( char *fname ) ;
+
+...and...
+
+  void slSample::autoMatch ( slDSP *player ) ;
+
+
+The basic 'slSample::loadFile' call will auto-detect the file type - the remaining +three calls presume the file to be of the type indicated irrespective +of the extension. +
+
+  Raw - A simple file containing just the samples in the same
+        format as required by the slDSP class (see above). These
+        often have the file extension '.ub' (unsigned byte).
+        Since this format has no header, it is always assumed to be
+        mono, 8000Hz and 8bps. If you know better - then use
+        setRate/setStereo/setBsp to sort out the resulting mess!
+  AU  - (Sun Microsystems 'audio' format), this file type typically
+        has the '.au' extension.
+  Wav - (Microsoft 'WAVE' format), this file type typically
+        has the '.wav' extension.
+
+
+All flavours of 'slSample::loadFile' return FALSE if the file cannot be read, +TRUE otherwise. slSample::autoMatch allows the sample to be tweaked to +work correctly with the slDSP that will be used to replay the sample +subsequently. +
+
+  char *slSample::getComment () ;
+  void  slSample::setComment ( char *nc ) ;
+
+
+Each sound sample can have a comment string associated with it. +Both '.wav' and '.au' files support such strings. In a 'wav' file, +there may be multiple strings - only the first is read. +
+
+  Uchar *slSample::getBuffer () ;
+  int    slSample::getLength () ;
+  void   slSample::setBuffer ( Uchar *buff, int leng ) ;
+
+
+These calls allow low level access to the sample buffer contained +in an slSample. slSample::setBuffer makes a private copy of the buffer you +pass to it, so you may delete your copy afterwards. slSample::getBuffer +returns a pointer to the local buffer inside the slSample - you +must not free it up. If you want to free up the memory in a slSample +without deleting it then you should call slSample::setBuffer(NULL,0). +

+The following calls get and set the internal parameters of an slSample: +

+
+  void slSample::setRate   ( int r ) ;
+  void slSample::setBps    ( int b ) ;
+  void slSample::setStereo ( int s ) ;
+
+  int  slSample::getRate   ()        ;
+  int  slSample::getBps    ()        ;
+  int  slSample::getStereo ()        ;
+
+
+Note that setting a parameter does not affect the audio data in +the buffer. If a sample was recorded at (say) 8KHz and you call +slSample::setRate(16000), then the sample will replay at 16KHz but will be +only half the usual duration and twice the frequency. The effects +of slSample::setBps and slSample::setStereo are even more destructive if used inappropriately. +

+The main use for the slSample::setRate/setBps/setStereo are for when the audio +data was created inside the program or read from a 'Raw' file format +and there was no other indication of these settings. By default, +such samples are assumed to be 8KHz, monophonic 8bps recordings. This +is supported by almost all audio cards. +

+If you need to manipulate the sample so that it sounds right when +replayed with settings that differ from those when it was recorded +then you need: +

+
+  void slSample::changeRate   ( int r ) ;
+  void slSample::changeBps    ( int b ) ;
+  void slSample::changeStereo ( int s ) ;
+
+
+It is sometimes useful to permenantly change the volume of a +sound sample: +
+
+  void slSample::adjustVolume ( float vol ) ;
+
+
+Setting vol to 2.0 would double the volume, setting it to 0.5 +would halve it. +

+Bear in mind though that these change/adjust routines make +permenant changes to the data in the sound buffer. The more +changes you make, the more noise you'll introduce into the +sample. If possible, record 16 bit samples and play with them +in a proper sample studio package - then reduce them to 8 bits +before you load them into an slSample. +

+These routines are also relatively slow - they create a new +sound buffer, process the old data to fit the new setup and +then free up the old buffer. The length and address of the +internal slSound buffer will often change as a result. +

+
+  float slSample::getDuration () ;
+
+
+This returns the duration of the sound sample in seconds. +
+
+  int slSample::getPlayCount () ;
+
+
+Returns a count of the number of simultaneous instances of this +sample are currently being played by slSchedulers (see below). +
+
+  void slSample::print ( FILE *fd ) ;
+
+
+This prints out all the parameters of the sound sample to the +specified file descriptor in human-readable form. +

class slScheduler.

+This class is where it all comes together. Most programs will +only create a single slScheduler. Since the slScheduler needs +dedicated access to the DSP, this class is inherited from an +slDSP - so most programs that use slScheduler should not declare +an slDSP as well. +

+IMPORTANT NOTE: Since slScheduler is derived from slDSP, all +slDSP member functions are available as slScheduler calls. +

+
+class slScheduler : public slDSP
+{
+public:
+  slScheduler ( int rate ) ;
+  slScheduler ( char *device, int rate ) ;
+ ~slScheduler () ;
+
+  float setSafetyMargin ( float seconds ) ;
+
+  void update () ;
+  void dumpUpdate () ;
+
+  void stopSample   ( slSample *s, int magic ) ;
+  void pauseSample  ( slSample *s, int magic ) ;
+  void resumeSample ( slSample *s, int magic ) ;
+
+  int loopSample ( slSample *s, int pri = 0,
+                   slPreemptMode mode = SL_SAMPLE_MUTE,
+                   int handle = 0, slCallBack cb = NULL ) ;
+  int playSample ( slSample *s, int pri = 1,
+                   slPreemptMode mode = SL_SAMPLE_ABORT,
+                   int handle = 0, slCallBack cb = NULL ) ;
+
+  void stopMusic   ( int magic ) ;
+  void pauseMusic  ( int magic ) ;
+  void resumeMusic ( int magic ) ;
+
+  int loopMusic  ( char *fname, int pri = 0,
+                   slPreemptMode mode = SL_SAMPLE_MUTE,
+                   int handle = 0, slCallBack cb = NULL ) ;
+  int playMusic  ( char *fname, int pri = 1,
+                   slPreemptMode mode = SL_SAMPLE_ABORT,
+                   int handle = 0, slCallBack cb = NULL ) ;
+} ;
+
+
+The idea behind slScheduler is that it manages all your music and +sound sample replay needs. You construct it at the start of your program run, load in your +slSamples and then call the 'slScheduler::update' function every iteration of your code. +

+The constructor function accepts a sample rate argument - note the +caveats in the slDSP contructor function - you need to call getRate() +to determine if your hardware was actually able to support the rate +you asked for - or whether you actually obtained some slightly +different rate. If you don't get a rate that matches your sound +samples then you'll need to call slSample::changeRate() or even +slSample::autoMatch for each one in turn to change it's sampling rate +to something that suits the hardware. +

+Notice that at present, slScheduler only supports 8bps monophonic +playback, this may change in the future. +

+Once everything is up and running, you can very easily play either +slSamples or music. Simply call: +

+
+  int slScheduler::loopSample ( slSample *s ) ;
+or
+  int slScheduler::playSample ( slSample *s ) ;
+
+  int slScheduler::loopMusic ( char *fname ) ;
+or
+  int slScheduler::playMusic ( char *fname ) ;
+
+
+There are additional arguments to these calls - but they are all +optional. slScheduler::loopSample() tells the scheduler to play +that sample in a loop forever, the slScheduler::playSample() tells +it to play the sample as a single one-shot effect. +

+Similarly, you can read and play music (currently only in 'MOD' +format). slScheduler::loopMusic() tells the scheduler to play +the music in a loop forever, the slScheduler::playMusic() tells +it to play the file as a single one-shot playback. +

+You can only play back one music track at a time. +

Preempting

+The slScheduler can (at present) play only three sounds at the +same time. You can ask it to play more than that - but only three +will actually sound at any given instant. If too many sounds try +to play at once, all but three of them will be 'pre-empted'. +

+You can tag each sample with a priority and a 'pre-empt' mode. The +priority indicates which sounds have priority over which others and +the 'pre-empt' mode tells it what to do if a sound of higher +priority wants to play in the meantime. +

+The full form of the slScheduler::loopSample/Music and +slScheduler::playSample/Music calls is: +

+
+  int slScheduler::loopSample ( slSample *s, int priority, slPreemptMode mode ) ;
+  int slScheduler::playSample ( slSample *s, int priority, slPreemptMode mode ) ;
+  int slScheduler::loopMusic  ( char *fname, int priority, slPreemptMode mode ) ;
+  int slScheduler::playMusic  ( char *fname, int priority, slPreemptMode mode ) ;
+
+
+The 'priority' is a simple integer. Zero is the least important +sound, SL_MAX_PRIORITY (currently set at 16) is the most +important. +

+The 'mode' parameter lets you choose what happens to a sound when +it is pre-empted. 'mode' is one of: +

    +
  • SL_SAMPLE_ABORT - If this sound is pre-empted, it simply +stops playing completely and is forgotten about by the scheduler. +
  • SL_SAMPLE_RESTART - If this sound is pre-empted, it will +stop playing - and restart from the beginning when the sound +system is free enough. Beware that on a busy sound system, the +same sound may try to start over and over again - producing a +stuttering effect as it is repeatedly stopped and restarted by +higher priority sounds. +
  • SL_SAMPLE_MUTE - The sound simply goes silent until +it either ends or the sound card becomes free enough for +it to carry on playing. The duration of the sound from start +to finish will be no different than if it had not been +pre-empted at all. +
  • SL_SAMPLE_DELAY - If this sound is pre-empted then it +will pause until the sound card becomes free again and continue +from exactly where it left off. +
  • SL_SAMPLE_CONTINUE - Although a higher priority sound +has come along, this sound will continue to play if it has +already been started. This is a useful mode for sounds that +need to be played without interruption - but which could be +delayed in time until the sound card is free. It is just +as if the priority of this sound jumps to SL_MAX_PRIORITY+1 +immediately it starts playing. +
+

Interacting with a Sample that's Playing.

+Also, you can ask the scheduler to tell you when something important +happens to your sound. +
+
+  int slScheduler::loopSample ( slSample *s, int priority, slPreemptMode mode,
+                                int magic, slCallBack cb ) ;
+  int slScheduler::playSample ( slSample *s, int priority, slPreemptMode mode,
+                                int magic, slCallBack cb ) ;
+                                int magic, slCallBack cb ) ;
+  int slScheduler::loopMusic  ( char *fname, int priority, slPreemptMode mode,
+                                int magic, slCallBack cb ) ;
+  int slScheduler::playMusic  ( char *fname, int priority, slPreemptMode mode,
+                                int magic, slCallBack cb ) ;
+
+
+The 'cb' parameter is the address of a callback function that SL +will call whenever something important happens to your sound. +

+Your function much accept three parameters: +

+
+  typedef void (*slCallBack) ( class slSample *sample, slEvent event, int magic ) ;
+
+
+The first parameter is the slSample that was being played when this +even happened, the second parameter tells you what happened: +
+
+  SL_EVENT_COMPLETE  -- The sound finished playing.
+  SL_EVENT_LOOPED    -- The sound looped back to the start.
+  SL_EVENT_PREEMPTED -- The sound was preempted by another sound.
+
+
+Other events may be added in the future, so your callback function +should be prepared to do nothing gracefully if an unknown event +comes along. +

+Since there may be multiple copies of a single sample being played +at the same time, the 'magic' parameter is a means for you to identify the +context that the sound comes from. You pick a magic number that's +meaningful to your application when you call slScheduler::playSample +or slScheduler::loopSample - and that number will be passed back to +your callback function whenever it is called. SL doesn't do anything +else with this magic number - so it's meaning can be anything +you want provided that the magic number must be non-zero. +

+A callback function can start new sounds playing, but if you +wait for the SL_EVENT_COMPLETE event to do that then there +may be a fraction of a second pause between the sound that +just stopped and the new one starting. +

+There are other ways to use the magic number to interact with +playing samples: +

+
+   void slScheduler::stopSample   ( slSample *sample, int magic ) ;
+   void slScheduler::pauseSample  ( slSample *sample, int magic ) ;
+   void slScheduler::resumeSample ( slSample *sample, int magic ) ;
+
+   void slScheduler::stopMusic   ( int magic ) ;
+   void slScheduler::pauseMusic  ( int magic ) ;
+   void slScheduler::resumeMusic ( int magic ) ;
+
+
+This stops/pauses/resumes all instances of the specified sample with +the specified magic number. The 'stopSample' command will even stop +looped samples. If the 'sample' is NULL then all samples with +that magic number are stopped/paused/resumed. If the 'magic' number +is zero then all instances of 'sample' are affected. If sample is +NULL and magic is zero then all currently playing sounds are +affected. +

+IMPORTANT NOTE: When you are playing a sample, it is important +not to delete it until after it has finished playing. SL keeps +count of the number of times each sample is playing - and will +produce a fatal error and exit if you attempt to do this. Note +that even if you tell the sample to stop playing using +slScheduler::stopSample, you must not delete it until *AFTER* +the next call to slScheduler::update(). You can use the +slSample::getPlayCount() function to find out how many playing +instances of a particular slSample there are. +

+

Envelopes.

+Most of the time, a sound can be simply played as-is. This is +highly desirable since doing real-time audio modification is +costly. However, there are times when you really need to +alter the pitch, volume, stereo-postion (pan) or filtering +of a sample in realtime. +

+One classic example of this is in a car racing game when +you want the pitch and volume of the engine to change in +response to the throttle and gear ratio - even though the +sound itself is really a simple looped sample. +

+To cater for these needs, SL has the concept of an 'envelope'. +An envelope is a array of floating point values and and array +of times at which those values are correct. The envelope can +be attached to a playing sound like this: +

+
+   slScheduler::addSampleEnvelope ( slSample *s, int magic,
+              int slot, slEnvelope *e, slEnvelopeType type ) ;
+   slScheduler::addMusicEnvelope ( int magic,
+              int slot, slEnvelope *e, slEnvelopeType type ) ;
+
+
+As with the other sample interaction commands, the sample and +magic number can be used as wild-cards to apply the same command +to a number of sample instances. +

+Each sample instance can has a minimum of four (and a maximum +of SL_MAX_ENVELOPES) slots into which an envelope can be placed. +Each envelope can operate on a different aspect of the sample +and the envelopes are applied to the sound in slotwise order. +

+To remove an envelope from a particular sample/magic/slot +combination, simply use slScheduler::addSampleEnvelope or +slScheduler::addMusicEnvelope with a NULL envelope. +

+Using a lot of envelopes will considerably increase the amount +of CPU time consumed by SL - so beware of trying overly fancy +effects. +

+The 'slEnvelopeType' argument defines which aspect of the sample's +performance will be affected by the envelope: +

+
+  SL_PITCH_ENVELOPE  : The value in the envelope determines the
+                       rate at which the sample is speeded up
+                       or slowed down during replay. A value of
+                       2.0 would double the pitch of the sound and
+                       halve it's duration. A value of 0.5 would
+                       halve the pitch and double the duration.
+
+  SL_VOLUME_ENVELOPE : The value of the envelope multiplies the
+                       amplitude (volume) of the sound. Beware of
+                       large multipliers that would cause the sound
+                       to be clipped and small multipliers that
+                       increase the noise level of the sample.
+
+  SL_FILTER_ENVELOPE : **NOT IMPLEMENTED YET**
+                       The value of this parameter determines the
+                       number of consecutive samples that are
+                       averaged together in a kind of moving average.
+                       Large numbers tend to muffle the sound.
+
+  SL_PAN_ENVELOPE    : **NOT IMPLEMENTED YET**
+                       The stereo position of the sound is moved
+                       to the left (negative numbers) or to the
+                       right (positive numbers). +/-1.0 is full-scale.
+
+  SL_ECHO_ENVELOPE   : **NOT IMPLEMENTED YET**
+                       The sound is added to a half volume copy of
+                       itself which is shifted in time by this number
+                       of seconds.
+
+
+In addition to these, there are a set of SL_INVERSE_PITCH_ENVELOPE, +SL_INVERSE_VOLUME_ENVELOPE, ...etc. These operate in an identical +manner to the standard envelopes - but with the opposite sense. +Hence, if you want to cross-fade two similar sounds then apply the +same envelope as an SL_VOLUME_ENVELOPE to one sample and as an +SL_INVERSE_VOLUME_ENVELOPE to the other and they will neatly +cross-fade. +

+Here is the class slEnvelope: +

+
+class slEnvelope
+{
+  slEnvelope ( int _nsteps = 1, slReplayMode _rm,
+                                float *_times, float *_values ) ;
+  slEnvelope ( int _nsteps = 1, slReplayMode _rm ) ;
+ ~slEnvelope () ;
+
+  int getPlayCount () ;
+
+  void setStep ( int n, float _time, float _value ) ;
+
+  float getStepValue ( int n ) ;
+  float getStepTime  ( int n ) ;
+
+  float getValue ( float _time ) ;
+} ;
+
+The envelope can be constructed either with or without initial data - +and can be either SL_SAMPLE_ONE_SHOT or SL_SAMPLE_LOOP. A one-shot +envelope retains it's final value indefinitely after it finishes +playing - a looped envelope returns to the start and repeats +indefinitely. +

+One very common thing to do is to create an slEnvelope containing +just one value. +

+The slEnvelope::setStep() function allows you to modify the value +of the n'th step of the envelope and to position it in time. +You can use this in realtime to dynamically interact with the +envelope and hence modify whatever samples are using that envelope +at the time. You can read back the time and value for any given +step of the envelope using slEnvelope::getStepTime() and +slEnvelope::getStepValue(). +

+Envelopes interpolate between the steps you provide - so if +a pitch envelope had just three value/time pairs: +

+
+  slEnvelope my_envelope ( 3, SL_SAMPLE_LOOP ) ;
+  my_envelope . setStep ( 0,  0.0, 1.0 ) ;
+  my_envelope . setStep ( 1, 10.0, 2.0 ) ;
+  my_envelope . setStep ( 2, 20.0, 1.0 ) ;
+
+  scheduler -> playSample ( my_sample ) ;
+  scheduler -> addSampleEnvelope ( my_sample, 0,
+                     0, & my_envelope, SL_PITCH_ENVELOPE ) ;
+
+
+...then this could be applied to a sample which would then +gradually increase in pitch over the next 10 seconds - by +which point, the pitch would have doubled - and over the +following 10 seconds, would gradually return to normal. +This behaviour would repeat for as long as the envelope +remained attached to that sample. +

+slEnvelope::getValue() returns the interpolated value at the specified +time. +

+You can remove an envelope from a sample thats playing by passing +a NULL envelope in the same slot. +

Timing the Audio Updates.

+The slScheduler has to pump audio data into the Linux device +driver in realtime. It does this by transferring a chunk +of pre-mixed audio data over to the Linux device driver +every time the it seems to be getting low on data. +

+Note that libsl is not using a separate thread +to do this - although you could place calls to slScheduler::update() +in a separate thread if you wanted to. That means that +if you call the update function too infrequently, the +Linux device driver will run out of data and you will +hear breaks and clicks in the audio. +

+Here is some advice on how to deal with this problem. +slScheduler supports this call: +

+
+  float slScheduler::setSafetyMargin ( float num_seconds ) ;
+
+
+The slScheduler::setSafetyMargin() call allows you to tell the scheduler +to ensure that there are at least 'num_seconds' of audio +queued up in the driver after each call to update. (The +default safety margin is two seconds - which is likely +to be on the long side in many applications). +

+If you make this number very large (say 4 seconds or more) +then Linux won't have enough buffer space to hold that +amount of audio data in it's internal buffer (which is +about 64Kb long on my system) - and slScheduler::update() will block +indefinitely trying to keep it that full. The audio +will be smooth - but your application will get zero +time to run in! +

+If you set the safety margin to a smaller number (but +still much larger than the rate that you call update - +say 1 or 2 seconds) then the system will produce smooth, +continuous audio - but there will be a significant delay +between calling the slScheduler::playSample() function and that sample +actually playing. That is because there is still a number of +seconds of data in the Linux buffer that has to be +played before your new sound will be heard. +

+For music replay, this is fine - all the audio was pre-planned, +so it'll sound great. But if you are creating the audio for +a game or something - then it's probably important that the +"BLAM!!" sound happens very soon after the player presses +the fire button. With safetyMargin set to two seconds, you +could get anywhere up to a two second delay! +

+Here is one (partial) remedy: +

+If you know that a VERY important sound has to be played +RIGHT NOW - then you can call the slScheduler::dumpUpdate() +function instead of the usual slScheduler::update() on that +frame. This will have the effect of telling Linux to +dump all the audio that has been queued but not yet +played - so that your important sound can play RIGHT +NOW. The downside is that a significant amount of +sounds that were sitting in the Linux queue will +be dumped - and a certain amount of CPU time will +be wasted as a result of having to compute those +seconds of audio twice. +

+If you were playing a boring buzzing noise for the sound of +an engine in a flight simulator - then losing a second +or two of it might be acceptable. If you were playing +continuous music in the background then using slScheduler::dumpUpdate() +would sound like your CD player skipping when you jog it +too hard. +

+The final solution is to set safetyMargin to something +quite small (say 0.2 seconds). This means that in theory, +all your sounds will be heard within 0.2 seconds of you +asking for them to play. Of course if you should fail to +call the slScheduler::update() function at LEAST once every 1/5th +second, Linux could run out of audio data and you'd get +gaps and clicks which sound REALLY TERRIBLE. +

+I find that even with the most simple application, I get +bad breakup with a safetyMargin anywhere under 0.13 seconds - +but that's on a fairly ancient 100MHz 486 - I would expect +a modern CPU to do better. +

+The sound library can keep up with an 8KHz mono, 8bps sample +rate consuming only 1ms of CPU time every iteration - also +on my 100MHz 486. +

+There are times when you might want to change safetyMargin +on-the-fly. This is fine - but the effect of the change +won't be noticable until the data that is currently +queued within Linux has been played. +

The Volume Level Conundrum.

+Globally, the volume is controlled by the audio mixer. If +you are using the 'SM' companion library then you can +do this with class slMixer - no +problem there - but the relative volume of the samples +that are played together cannot be controlled so easily. +

+For speed, the scheduler simply adds the sounds together +and clamps any values that would overflow. To do anything +more complex would consume significant amounts of CPU time. +

+(Since sounds are stored as unsigned char's the value +0x80 actually represents zero voltage - so the equation +for adding two sound samples 'a' and 'b' is: +

+
+   a + b - 0x80 
+
+
+it is important to bear this in mind if you do any work +on the slSample buffers yourself.) +

+Clearly if two sounds each range in voltage from utter +minimum (0x00) to absolute maximum (0xFF) then there will +be considerable distortion when they are added. The problem +gets even worse when there are three sounds. Hence, if you +really expect to play two sounds at once then you should +reduce the volume of each sample to the range 0x40 to 0xC0, +and if you expect to play three sounds at once then the +range 0x56 to 0xAA. However, if you do that then you are +in effect losing one or two bits of audio precision - which +raises noise levels quite a bit. +

+It would have been possible to go to 16 bit sound samples - but +not all PC sound cards can do that - and in any case, it would +double the amount of memory and CPU time taken to play the sounds. +

+One notable fact is that it is fairly unlikely that all +your sounds actually fill the range 0x00 to 0xFF exactly. Most +sampled sounds that you find recorded by home equipment are +typically either: +

    +
  • Over-recorded - they fill the range 0x00 to 0xFF - but + were actually recorded a too high a range and are + already pretty noisy. +
  • Under-recorded - they don't fill the range 0x00 to 0xFF. +
+If under-recorded, then further reducing the volume for the +sake of adding several sounds together may be unnecessary. +

+If over-recorded, then you'll need to reduce the volume of +the sample for sure since it's already being clipped. +

+Even in the happy case of perfect recordings, it's pretty +unlikely that the loudest parts of two sounds will happen +to replay at the exact same instant - and even if they +did, it might be in some rare spikes of audio where quality +might not suffer. +

+So, there is no solid mechanism to ensure the best quality. +You might want to spend some time playing with the relative +volumes of the various samples you use in your code. The +slSample::changeVolume() function is too slow to use in +realtime - but it is handy for tuning the samples right +after they have been loaded from disk. +

The Future.

+I keep hearing about compressed '.WAV' files - I havn't found +any yet - or a spec on how to read them. +

+There doesn't seem to be a spec for '.AU' files either - but +the header format seems simple enough from just looking at +a few example files. +

+It's also possible to allow more simultaneous sounds - the +limit of three is a bit arbitary - but again, CPU costs are +something to be concerned about. Fortunately, if I ever +increase the limit, it shouldn't affect existing programs. +

+It would be nice if the scheduler knew how to do stereo +and 16 bps. +

A Note about Reference Counting.

+Instances of the slEnvelope and slSample classes are 'reference +counted' within SL. That means that a counter in each object is +incremented each time you start one playing - and decremented +each time one stops. When you 'delete' an slEnvelope or an slSample, +the reference count will be checked to ensure it is zero - if it +is not then a fatal error will be produced if you then attempt +to call slScheduler::update() since that would play a sound that +has been deleted by the application. +

+The error does not occour at the point when you delete the +sample or envelope since it is OK to do that so long as you +never try to play more sounds later. It is therefore illegal +to delete a sample or envelope and then stop +it playing. +

+This arrangement allows an application to exit with outstanding +sounds queued up. +

Example Program.

+This example creates an 'engine' sound in memory using +some summed sine waves, loads a number of sounds (and +has them automatically matched to the current sound +replayer), then plays the engine sound in a loop, +periodically interrupting it with some other noises. +
+
+#include "sl.h"
+#include "sm.h"
+#include <math.h>
+
+/*
+  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 */
+#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 () ;
+  }
+}
+
+
+
+ + +
+Valid HTML 4.0! + +
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+
+ + + diff --git a/doc/sl/sl.png b/doc/sl/sl.png new file mode 100644 index 0000000..381a241 Binary files /dev/null and b/doc/sl/sl.png differ diff --git a/doc/sl/sm.html b/doc/sl/sm.html new file mode 100644 index 0000000..bc64a36 --- /dev/null +++ b/doc/sl/sm.html @@ -0,0 +1,106 @@ + + + + + + + The SL Mixer Library. + + + + + + + + +
Imagine kitchen mixers here +

The SL Mixer Library.

+By Steve Baker +
+

Introduction.

+This library allows one to drive the mixer controls of +most PC-style sound cards. It relies +on the Open Sound +System drivers (formerly known as 'VoxWare') +- which are generally a standard part of the Linux Kernel - and +which is also available on some other UNIX platforms. +

+A port of SM to the Windows family of operating systems +is currently underway. +

+SM does not work under SGI's IRIX. +

Using the Library.

+To use this library, you must '#include "sm.h"' and link to +libsm.a or libsm.so. +

class smMixer.

+This library comprises a single class 'smMixer'. +

+Most programs will only ever create a single smMixer object. +

+Here are the member functions: +

+
+  class smMixer
+  {
+    public:
+
+      smMixer () ;
+      smMixer ( char *device ) ;
+     ~smMixer () ;
+  
+      int not_working () ;
+
+      /* Volume/Treble/Bass controls are in integer percentages */
+
+      void setTreble       ( int treble ) ;
+      void setBass         ( int bass   ) ;
+
+      void setMasterVolume ( int volume ) ;
+      void setSynthVolume  ( int volume ) ;
+      void setPCMVolume    ( int volume ) ;
+      void setSpeakerVolume( int volume ) ;
+      void setLineVolume   ( int volume ) ;
+      void setMicVolume    ( int volume ) ;
+      void setCDVolume     ( int volume ) ;
+
+      void setMasterVolume ( int left, int right ) ;
+      void setSynthVolume  ( int left, int right ) ;
+      void setPCMVolume    ( int left, int right ) ;
+      void setSpeakerVolume( int left, int right ) ;
+      void setLineVolume   ( int left, int right ) ;
+      void setMicVolume    ( int left, int right ) ;
+      void setCDVolume     ( int left, int right ) ;
+  } ;
+
+
+Basically, each of the mixer devices can be driven with either +mono or stereo volume controls, each volume is a expressed as an +integer percentage of maximum. +

+By default, "/dev/mixer" is the device used by this class, but +an alternative device may be accessed if it's name is passed +into the constructor. +

+The 'not_working()' function returns TRUE if there is any kind of +problem with the driver. Mostly it returns TRUE if your system isn't +set up for audio. +

+The driver will not fail if you call it's member functions when +'not_working()' returns TRUE - so programs written for audio +should work OK even on Linux boxes with no audio support. +


+ + +
+Valid HTML 4.0! + +
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+
+ + + diff --git a/doc/spacething-small.png b/doc/spacething-small.png new file mode 100644 index 0000000..d1aab0b Binary files /dev/null and b/doc/spacething-small.png differ diff --git a/doc/ssg/LoaderWriter.html b/doc/ssg/LoaderWriter.html new file mode 100644 index 0000000..f0869d7 --- /dev/null +++ b/doc/ssg/LoaderWriter.html @@ -0,0 +1,315 @@ + + + + + A Simple Scene Graph API for OpenGL. + + + +

How to write plib-loaders and writers

+ +

1.1 Introduction

+ +This page is intended for those who wish to write loaders and writers +for plib. If you just use plib (using the included loaders and writers), you don't +really need to read this. + +It is quite easy to adapt 3D-file-loaders and writers to be used by ssg. Plib +already has many loaders and writers that may be used as examples.

+ +A brief note on cross platform compilation: Plib comes with +both Makefiles (for Unix and for the CygWin-system under Windows) +and workspace/project-files for Micro$oft Visual C++. If you +have both, please update, test and commit both. +Otherwise, when committing, please tell the people that something is +missing (for example: you didn't update the workspace files) and that some +kind soul should do so. +

+ +Both loaders and writers convert between ssg's internal geometry +representation and that of the file format. One key difference is that when +loading, you should support all possibile +geometry-representations of the file format. This is to ensure that +plib can handle all the possible variations of a file format that may be generated +by the tools that export to it. On the other hand, when writing a format, you can +pretty safely only write to one geometry format (unless you need features peculiar +to more than one geometry representation), because you have the final say on how the +data is to be written. +

+ +Regarding plib's geometry-representations: there are only two on the highest +level: ssgVtxTable and ssgVtxArray. Actually, there is also +ssgVTable, but that is deprecated. + +ssgVtxArray is newer, is derived +from ssgVtxTable and uses a index-list. Apart from that they are quite +similar, and both have an interface getNumTriangles () ; and +getTriangle ( i, ...); +For this reasons, it is easier to write a writer than a loader. + + +For both ssgVtxTable and ssgVtxArray you need to choose a +GL-type. Currently ssgLoaderWriterMesh (more on this in the +next section) uses GL_TRIANGLES. + + +

1.2 class ssgLoaderWriterMesh - an overview

+ +The two main parts of writing a loader are writing the actual parser (coding +the syntax of the format) and transferring the contents +to ssg. The second task is fairly trivial if your contents +obey the restrictions of ssg (which follow from OpenGL). +

+These are: +

+ +1. Each ssg-node can (currently) have only one texture. +
+2. Only one polygon or strip or fan per node. So you can't have a 3-, a 4- and a 5-sided +poly inside one node (without subdividing the polys into triangles) +
+3. Currently, you may have only one texture coordinate per vertex. +
+4. You may have only one normal per vertex. +

+To modularize the two steps parsing the format and transfering it to ssg +and to reduce redundant work, there is an intermediatory structure, the class +ssgLoaderWriterMesh. For example, this has a member function +
+void ssgLoaderWriterMesh::addFaceFromIntegerArray( int numVertices, int *vertices );
+
+With several calls, you can add several n-sided polys to one mesh ("one node"). +When you are done constructing the mesh from the file, you call +
+void ssgLoaderWriterMesh::addToSSG(
+		class ssgSimpleState *currentState,
+		class ssgLoaderOptions* current_options,
+		class ssgBranch *curr_branch_)
+
+and the class adds the information into the scene graph. It handles +ssgs' restrictions. For example, if the polygons of the mesh use +5 textures then at least 5 nodes will be added to the scene graph.

+ +Unfortunately, this class isn't completely finished. As of this +writing, Wolfram Kuss (w_kuss@rz-online.de) has implemented those +parts that were needed for the loaders he has finished thus far. Hopefully +people will contribute more features as time goes on.

+ +If you are writing a new loader for a file format that doesn't hold to +all restrictions of ssg (and virtually none do), you are urged to use this class. +Your loader will be more consistent and easier to maintain and read.

+ +Further, there are many optimizations that can be done (For example: "If the state is +different, but not the texture, do we need several nodes?" or "When we have multitexturing, +can we use that?" or "Is there an optimal strip length?" or "How do I subdivide polys into +triangles so that the stripifier will work well?"-- the list goes on +forever). Once we have good answers to these questions (and the will +to implement them), it will be easier to do them once in the ssgLoaderWriterMesh than in all the +loaders seperately. It is noteable that most loaders written before +ssgLoaderWriterMesh have had some sort of intermediatory mesh +structure.

+ +In the future, ssgLoaderWriterMesh should also be used for writers, doing the opposite +job: It takes the information from ssg with the restrictions and then looks whether +it can optimize (for example merging nodes) by relaxing the restrictions. + +

1.3 The Class ssgLoaderWriterMesh - A Deeper Look

+At the start of your loader, you create a new ssgLoaderWriterMesh +or do a reInit(). To insert the data into the ssgLoaderWriterMesh, +you have to add vertices, faces, materials, materialindexes (saying what face uses what material) +and, if applicable texture coordinates. For all of these, you can say in advance how many you have. +If you know that you have 3712 vertices, call createVertices(3712) and everything is allocated +at once and addVertex will be very fast. If you don't know in advance how many you have, you +still have to call createVertices(), as this also allocates the vertices. In this case, a +certain amount of vertices will be reserved and the list will dynamically grow as more are added.

+ +Vertices are simply sgVec3s. Faces are simply lists/arrays of vertex indexes. +For adding faces, use addFace if you already have a ssgIndexArray or use +addFaceFromIntegerArray if you have the vertex indexes in a C(++) array. +You need to add at least one material (ssgSimpleState). For each face, you tell +ssg which material to use via addMaterialIndex. Here is code from ssgLoadOFF, which tells +ssg to use the ssgSimpleState ss for all faces: + +
+

+
+	theMesh.createMaterials( 1 );
+	theMesh.addMaterial( &ss );
+	theMesh.createMaterialIndices( _ssgNoFacesToRead ) ;
+	for(i=0;i<_ssgNoFacesToRead ;i++)
+	   theMesh.addMaterialIndex ( 0 ) ;
+
+
+If the file format has texture coordinates, you have to find out whether it has them +per vertex or per vertex and face. If you look at a "straight forward" cube, +having texture coordinates per vertex means you can have 8, but if you have +texture coordinates per vertex and face, you can have 24 (each vertex is part of 3 faces). +The two functions corresponding to these cases are: +
+       void createPerFaceAndVertexTextureCoordinates2( int numReservedTextureCoordinate2Lists = 3 );
+       void addPerFaceAndVertexTextureCoordinate2( ssgTexCoordArray **textureCoordinateArray ); 
+
+or +
+        void createPerVertexTextureCoordinates2( int numReservedTextureCoordinates2 = 3 ); 
+        void addPerVertexTextureCoordinate2( sgVec2 textureCoordinate ); 
+
+ + +

2. Loaders

+ + +

2.1 class ssgLoaderOptions

+ +ssgLoaderOptions is a class that is defined in ssg.h. +It is used to tell the loader some options. +It is NOT used for user-setable options, although +this may be nice to have at some point. For example, +one COULD create a member-variable in it +telling the unit that one wants. The loader would then +be responsible to scale the object in such a way that +the sizes are in that unit (for example: meter, millimeter, etc). + +
+
+Regarding the reason for the callbacks in ssgLoaderOptions, Steve +wrote: +
+
+
+"Whenever a branch node is created. The deal is that most file formats +are +missing important features at the Branch level - but many support +comment +fields - or long ASCII name strings or something. The idea was to allow the artists to attach an ARBITARY comment string +in their modeller - and to have the loader trap these strings and pass +them on to the application.

+ +Hence, if the hook function is defined then when a branch node needs +to +be created, we call the application's callback with the ASCII string +that was embedded in the file and let the application construct the +ssgBranch +node. Hence, you could put the string "~LOD: RANGE=100 meters" +into the comment field in (say) the AC3D modeller. (AC3D calls this a +"Data" +field)...the application could then say to itself: "Any comment that +starts +with a tilde ('~') is a command to the loader" and parse such +'comments' +as commands. In this case, it would construct an ssgRangeSelector and +set +the transition range to 100m and return the application back to the +loader.

+ +Check the Tux Kart sources to see this in action." +

+ +So much for the quote from Steve. +

+ +As of this writing, the ssgLoaderOptions code has been copied from +another loader into ssgLoaderWriterMesh. + + +

2.2 ASCII file formats

+A lexical analyzer for ascii-files is available in ssgParser.cxx and +ssgParser.h. It converts the file into a stream of tokens and +handles comments. In a way, it has two APIs. +One hides the line structure from the loader. The loader just has +to say "getNextToken". +The other API operates in terms of exact line structure. +You do a getLine which reads all the tokens of that line into a +buffer and then you do a parseToken to get each token.

+ +The formats which currently use the parser are .X (which uses the +line-independant API), .ase, .scenery and .off (which use the +line-by-line-API).

+Some functions are used by both APIs. For example:

+ +

+	void openFile( const char* fname, const _ssgParserSpec* spec = 0 );
+

+ +In ssgParserSpec, you give the parser the specification of the format. +You say which characters start a comment, which characters are skipable, +which characters are used for braces (which are used to determine the +parser's level-- useful for parser's which work recursively). +Most important are the delimiters. These determine where one token ends and the +next one begins. For example, the first token of the line + +

+1234,567
+
+ +is 1234 if "," is a delimiter and +1234,567 otherwise. +The parser differentiates between skipable delimiters that +are "swallowed" by the parser and non-skipable ones that are +passed to the loader. So, regarding the example-line there +are three possibilities: +
+"," is not a delimiter => The line contains one token, namely +"1234,567" +
+"," is a skipable delimiter => The line contains two tokens, namely +"1234" and "567" +
+"," is a non-skipable delimiter => The line contains three tokens, +namely "1234", "," and "567" +
+ + +

3. Writers

+For an example how to write out geometry and material, look at +ssgSaveASE. + +For an easy example (geometry only), look at ssgSaveDXF or ssgSaveTRI. +The function + +
+int ssgSaveXYZ ( const char *filename, ssgEntity *ent )
+
+ +normally calls a function + +
+static void save_entities ( ssgEntity *e )
+
+ +which just recursively walks the scene graph. +You should be able to use this function and just +write a + +
+static void save_vtx_table ( ssgVtxTable *vt )
+
+ +which writes a ssgVtxTable.

+ + + +


+ + + + + + +
<= previous =Return to SSG Index
+
+ + +
+Valid HTML 4.0! + +
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+
+ + + diff --git a/doc/ssg/branches.html b/doc/ssg/branches.html new file mode 100644 index 0000000..bb21cea --- /dev/null +++ b/doc/ssg/branches.html @@ -0,0 +1,319 @@ + + + + + A Simple Scene Graph API for OpenGL. + + + +

class ssgBranch - A basic branch node.

+The basic ssgBranch node simply handles a node in the tree, +with zero or more child nodes which can be any kind of ssgEntity +except ssgRoot. +

+There are a rich set of functions for adding, deleting and +replacing child nodes: +

+
+class ssgBranch : public ssgEntity
+{
+  int        getNumKids    (void) ;
+  ssgEntity *getKid        ( int n ) ;
+  ssgEntity *getNextKid    (void) ;
+  int        searchForKid  ( ssgEntity *entity ) ;
+  void       addKid        ( ssgEntity *entity ) ;
+  void       removeKid     ( int n ) ;
+  void       removeKid     ( ssgEntity *entity ) ;
+  void       removeAllKids (void) ;
+  void       replaceKid    ( ssgEntity *old_entity, ssgEntity *new_entity ) ;
+} ;
+
+
+Most of these are pretty self-explanatory. +ssgBranch::getNumKids() returns the number of child nodes +beneath this branch. +ssgBranch::getKid(n) returns the address of the n'th child ssgEntity. +ssgBranch::getNextKid() returns the address of the child entity following +the last one returned by getKid or getNextKid - returning NULL when all child nodes +have been exhausted. +ssgBranch::searchForKid(entity) searches for the specified entity +in the list of child nodes and returns it's index (ie the inverse of getKid). +ssgBranch::addKid(entity) adds the specified entity to the list of +child nodes - the new node is added at the end of the list and will therefore +have the highest numbered index. +ssgBranch::removeKid(n) removes the n'th child node and renumbers +any higher numbered children so there are never any gaps in the number range. +ssgBranch::removeKid(entity) same as removeKid(searchForKid(entity)). +ssgBranch::removeAllKids() remove ALL child entities. +ssgBranch::replaceKid(old, new) replaces old with new. +If the entity removed by any of these commands has a ref count of +zero, it will be deleted. + +

class ssgInvisible - Invisible parts of a Scene Graph.

+It's sometimes useful to have sections of the scene graph that are never +rendered to the screen. These are frequently used for collision detection +and other non-graphical operations. + +

class ssgRoot - The Root of the Scene Graph,

+The node at the root of the scene graph is special. At present, +it resembles an ssgBranch externally. +
+
+class ssgRoot : public ssgBranch
+{
+} ;
+
+
+ +

class ssgTweenController - A morph controller,

+This is essentially identical to an ssgBranch - but adds API to +set the current 'bank' settings of all ssgTween leaf nodes beneath it. +

+An ssgTween is a leaf node that can hold multiple geometric +representations that it smoothly interpolates between. +

+
+  ssgTweenController::selectBank ( float b ) ;
+  float ssgTweenController::getCurrBank () ;
+
+
+This allows you to set which of the banks of it's daughter ssgTweens +will be rendered. That's a "float" quantity - so if you selectBank(2.4) +then the ssgTweens will render their vertices in a position (colour, etc) +that's 40% of the way between the bank 2 and bank 3. +

+You can also set the behaviour when the selected bank number is larger +than the number of banks in the model. This tends to happen when you +simply add some amount of to the bank selector each frame in order +to keep the animation running forever: +

+
+  ssgTweenController::setMode ( int mode ) ;
+
+
+'mode' can either be SSGTWEEN_STOP_AT_END or SSGTWEEN_REPEAT. +The default is STOP_AT_END - where anytime the bank selector +is larger than the actual number of banks in the ssgTween node, +it is clamped to the largest possible number. If you choose +REPEAT, then the bank number will be taken modulo the number of +banks. +

class ssgSelector - A switch point,

+Most ssgBranch nodes represent a collection of objects that +are all present in the scene at the same time. ssgSelector +nodes (and derived classes) typically represent a single +object that can be represented in more than one way. +

+A selector contains up to 32 daughter objects and a +32 bit unsigned integer mask. Where there is a one bit +in the mask, that child object will be drawn, where +there is a zero, it will not. +

+ssgSelector::select(mask) sets the mask, +ssgSelector::getSelect() returns the current +state of the mask, ssgSelector::selectStep(n) +sets the n'th mask bit and zeroes out all the others - effectively +causing only the n'th child object to be displayed. +

+It is quite common to have an ssgSelector with just one +child object that can be enabled with select(1) and disabled +with select(0). + +

class ssgTimedSelector - An animation node,

+This is a selector in which the selection is made as a function +of the amount of time elapsed. +

+SSG will draw each of the child objects in turn for some amount +of time before going onto the next node in the sequence. You +set the time for each child using: +

+
+   ssgTimedSelector::setDuration ( float time, int which_child ) ;
+
+
+...or you can set the same time for each of the child nodes using: +
+
+   ssgTimedSelector::setDuration ( float time ) ;
+
+
+(At present, times are measured in SSG update cycles - ultimately, +there will be an option to set the times in seconds - but until +I have a reasonably accurate portable timer library, I can't +easily implement this). +

+The animation doesn't have to start at the first child node and +end at the last. It is sometimes useful to be able to replay +just a subset of them. +

+
+   ssgTimedSelector::setLimits ( int start_child, int end_child ) ;
+
+
+You can also choose between a number of animation algorithms: +
+
+   ssgTimedSelector::setMode ( ssgAnimDirection mode ) ;
+
+     Where mode is one of:
+
+       SSG_ANIM_ONESHOT, SSG_ANIM_SHUTTLE, SSG_ANIM_SWING
+
+
+
    +
  • In SSG_ANIM_ONESHOT mode, the animation starts at the first child + you specified with setLimits and ends at the last child you + specified. Once the last child has been displayed, the animation + will automatically go into STOP mode and continue to display + that last object until the application intervenes. +
  • In SSG_ANIM_SHUTTLE mode, the animation goes from the start + child to the end child - but unlike SSG_ANIM_ONESHOT, when + the animation has finished displaying the last child object, + it resets to the start child and does it all over again. + SSG_ANIM_SHUTTLE animations don't stop running unless the + application stops them. +
  • In SSG_ANIM_SWING mode, the animation goes from the start + child to the end child - but when the end is reached, the + animation reverses direction and heads back to the start + again. The animation oscillates like a swing until the + application stops it. +
+

+When all this preparation is done, the application must +control the animation: +

+
+    ssgTimedSelector::control ( ssgAnimEnum cntrl ) ;
+
+    Where 'cntrl' is one of:
+
+       SSG_ANIM_START, SSG_ANIM_STOP,
+       SSG_ANIM_PAUSE, SSG_ANIM_RESUME
+
+
+These controls work just like you'd expect. Start, Stop, +Pause, Resume. SSG_ANIM_START resets the animation to +the 'start' child and lets it rip. SSG_ANIM_STOP causes +it to stop wherever it is and continue to display that +child node indefinitely. SSG_ANIM_PAUSE pauses the +animation wherever it is right now and SSG_ANIM_RESUME +allows it to continue from whatever point it was paused. +

+When the animation is in SSG_ANIM_STOP mode, you can +use this node just like a normal ssgSelector node +using the ssgSelector API. +

+If you need to know which child object is currently being +displayed, you cannot call ssgSelector::getSelect() because +SSG computes the animation step only if the node is actually +on-screen. Instead call ssgTimedSelector::getStep() which +returns the currently selected child node. +

class ssgRangeSelector - A level of detail node,

+This is a selector in which the selection is made automatically +based on the range to the object. This is principally used to +allow you to save time by drawing simpler versions of objects +at long ranges and more complex ones close up. +

+Since an ssgRangeSelector is a kind of +ssgSelector, you can find +out which version of the object was most recently drawn using +getSelect(). However, if the object was not drawn recently, that +may not be a very useful thing to know. Mostly, it's useful in +the post-cull callback. +

+You set the ranges at which each daughter object will be drawn +by passing an array of lengths to +ssgRangeSelector::setRanges(float *ranges,int nranges). +The first parameter is an array of ranges and the second is the +number of elements in that array. Note that element N of the +array is the range beyond which child object N will be drawn. +The array should contain one more range than there are child +objects - and beyond the last range, nothing will be drawn. +setRanges takes a copy of your array so you can delete it after +the call. If nranges is less than the number required, the +remaining ranges will be set to infinity. You can query the +current range array with float getRange(int n) which +returns the n'th range in the array. +

+In some cases, you'd like to build several complete versions +of an object such that just one of those versions will be +drawn - and that is the default behaviour. In other cases, +you'd like some basic object to be rendered at long range +and for additional parts to be added to it at shorter ranges. +This is called 'additive' mode and it is set using +setAdditive(int additive) +and queried with isAdditive(). +

class ssgBaseTransform - Nodes with transformations.

+It is common to wish to move objects around in the scene, scale and rotate +them, move their texture maps, etc. All of these operations entail +manipulating a matrix associated with the branch node and the +ssgBaseTransform contains the functionality to store and manipulate +that matrix. Applications use one of the derived classes of ssgBaseTransform +to actually do something with that matrix. +
+
+class ssgBaseTransform : ssgBranch
+{
+  void getTransform ( sgMat4 xform ) ;
+  virtual void setTransform ( sgVec3 xyz ) ;
+  virtual void setTransform ( sgCoord *xform ) ;
+  virtual void setTransform ( sgCoord *xform, float sx, float sy, float sz ) ;
+  virtual void setTransform ( sgMat4 xform ) ;
+} ;
+
+
+You can set up the transformation matrix using ssgBaseTransform::setTransform() +which has versions that allow you to pass either a full-blown +4x4 matrix, a simple translation, an 'sgCoord' (which is an xyz translation +and a hpr rotation) or an sgCoord and scale factors in each of X, Y and Z +directions. +

+ssgBaseTransform::getTransform(matrix) copies the current +transform into the matrix that you provide. +

class ssgTransform - Nodes with spatial transformations.

+An ssgTransform is derived from ssgBaseTransform and uses the base classes' +transform to transform all the spatial vertices and normals of it's +child nodes. This is done by applying the current transform to the +GL_MODELVIEW stack each frame. +

class ssgTexTrans - Nodes with moving texture

+ssgTexTrans nodes are just like ssgTransform nodes except that the +resulting matrix is applied to the GL_TEXTURE stack rather than +the modelview stack. Hence, altering the transform moves the texture +map(s) on the descendent leaf nodes. +

class ssgCutout - turn-to-face-the-viewer nodes.

+Cutout nodes will normally contain only leaf nodes that are +modelled with polygons in the X/Z plane. The ssgCutout will rotate +those polygons such that they turn to continually face the viewer. +

+There are actually two distinct forms of ssgCutout - depending on +what value is passed as a parameter to the constructor function. +ssgCutout(TRUE) produces an object that rotates around it's +origin such as to keep the X/Z plane parallel to the screen and +ssgCutout(FALSE) produces one that tries to stay parallel to the +screen - but which is only allowed to rotate about the Z axis. +The latter form is useful for objects with cylindrical symmetry +and the former for those with spherical symmetry. + +


+ + + + + + +
<= previous =Return to SSG Index= next =>
+
+ + +
+Valid HTML 4.0! + +
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+
+ + + diff --git a/doc/ssg/index.html b/doc/ssg/index.html new file mode 100644 index 0000000..b90657a --- /dev/null +++ b/doc/ssg/index.html @@ -0,0 +1,157 @@ + + + + + A Simple Scene Graph API for OpenGL. + + + +
+

SSG: A Simple Scene Graph API

+

for OpenGL

+ by Steve Baker +
+

Introduction

+Simple Scene Graph (SSG) is intended to be a really simple, +low-impact, scene graph API that layers nicely on top +of OpenGL using C++ and which works with or without GLUT. +

+SSG is a part of PLIB. +

+This document assumes a certain degree of knowledge of +OpenGL. +

+SSG includes a subsidiary library of simple matix and vector +math with support for some intersection testing, field-of-view +culling and such like. This is called +'Simple Geometry' (SG). +SG is used extensively by SSG - but is also useful as a +standalone library. +

+A Scene Graph is essentially just a tree-structured database +containing a hierarchy of branches - and a bunch of leaf nodes. +Each leaf node does some OpenGL rendering - the branch nodes +are intended to manage things like: field of view (FOV) culling, +level of detail (LOD) management, transformations, and animation. +

+In addition, each leaf node has a structure tacked on to it +to encapsulate OpenGL state information - and that in turn +may optionally have a texture applied to it. +

+In addition to managing the scene graph, SSG contains code +to manage the positions of cameras, lights and other rendering +aspects of OpenGL. +

Symbol Conventions.

+Both SSG an SG follow conventions for symbols and tokens that +are the conventions used by OpenGL and GLUT. +

+Hence, all SSG symbols for classes and functions start with ssg +and all #define tokens start with SSG. Functions and symbols +that belong to the SG library similarly start with sg or SG. +

+Words within a class or function name are Capitalised and NOT +separated with underscores. Words within #define tokens may +be separated with underscores to make them readable. +

Initialisation.

+The first SSG call in any program must always be ssgInit(). Call +ssgInit only after you have obtained an OpenGL rendering context +(or called glutInit() and created a rendering window if you are +using glut). +

Classes

+The following class hierarchy makes up the core package - which +can be extended to add functionality or to change some underlying +mechanisms. +
+
+   class ssgBase
+    |__ class ssgSimpleList
+    |    |
+    |    |__ class ssgVertexArray
+    |    |__ class ssgNormalArray
+    |    |__ class ssgTexCoordArray
+    |    |__ class ssgColourArray
+    |    |__ class ssgIndexArray
+    |
+    |__ class ssgEntity
+    |    |
+    |    |__ class ssgLeaf
+    |    |    |__ class ssgVTable (deprecated)
+    |    |    |__ class ssgVtxTable
+    |    |          |__ class ssgTween
+    |    |          |__ class ssgVtxArray
+    |    |
+    |    |__ class ssgBranch
+    |         |__ class ssgRoot
+    |         |__ class ssgInvisible
+    |         |__ class ssgSelector
+    |         |    |__ class ssgTimedSelector
+    |         |    |__ class ssgRangeSelector
+    |         |
+    |         |__ class ssgBaseTransform
+    |         |    |__ class ssgTransform
+    |         |    |__ class ssgTexTrans
+    |         |
+    |         |__ class ssgCutout
+    |         |__ class ssgTweenController
+    |
+    |___ class ssgState
+    |     |__ class ssgSimpleState
+    |         |__ class ssgStateSelector
+    |
+    |___ class ssgTexture
+
+
+The general idea is that, all geometry is contained in ssgLeaf classes, +all data heirarchy is in a ssgBranch classes and all OpenGL state information +is in ssgStates. +

+You may not declare instances of ssgBase, ssgEntity, ssgBaseTransform, +ssgLeaf or ssgState since they are all abstract classes. +

+It is presumed that applications will add new kinds of leaves, branches, +states and textures to customise SSG to their needs. +

+Here are the further chapters: +

+The base class +
+An entity of the graph +
+A leaf of the graph +
+A branch of the graph +
+States (material etc) +
+ssgContext +
+Non-class functions: Loading, saving and optimizing databases +
+How to write plib-loaders and writers +

+You can go through all the SSG-documentation by clicking on the "= next =>"-links at the bottom of each page. +

+


+ + + + + + +
= next =>
+
+ + +
+Valid HTML 4.0! + +
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+
+ + + diff --git a/doc/ssg/non_class.html b/doc/ssg/non_class.html new file mode 100644 index 0000000..f4de9ae --- /dev/null +++ b/doc/ssg/non_class.html @@ -0,0 +1,936 @@ + + + + + A Simple Scene Graph API for OpenGL. + + + +

Non-class Functions.

+So, with the class functions described above, it is +fairly simple to construct a scene graph. So, now that +you have one, what can you do with it? +
+  void ssgCullAndDraw ( ssgRoot *root ) ;
+
+This call deals with the entire process of rendering the database. +Your application need only call ssgInit(), build a database, +create a current context and call ssgCullAndDraw using the root node +of that database. +

Intersection Testing.

+Most applications need to test the scenery to see if moving +objects have collided with it - there are several ways to do +that - but they all share the same mechanisms: +
+
+int  ssgIsect ( ssgRoot *root, sgSphere *s, sgMat4 m, ssgHit **results ) ;
+int  ssgHOT   ( ssgRoot *root, sgVec3    s, sgMat4 m, ssgHit **results ) ;
+int  ssgLOS   ( ssgRoot *root, sgVec3    s, sgMat4 m, ssgHit **results ) ;
+
+
+These three calls implement various ways to test the database for collisions, +weapon impacts and such like. In each case, the search for a collision +starts at 'root', and the database is transformed by the matrix 'm' +before the test is evaluated - hence, 'm' is ususally the inverse of +the matrix describing the test object's location. +
    +
  • ssgIsect intersects a sphere against the scene. +
  • ssgHOT intersects a vertical line starting at the point 's' (remember, +in SSG, positive Z is 'up'). This is often used to compute +the Height-of-Terrain - hence the name 'HOT'. +
  • ssgLOS intersects an arbitary vector whose direction is defined by 's'. +
+The result in either case is an integer telling +you how many triangles impacted the sphere/vector. If you need to know more +about these intersections, pass the address of a ssgHit * variable as +the last parameter and it will be returned pointing at a STATIC array +of ssgHit structures. Thats a confusing explanation - and an example +will help: +
+
+ie:
+
+   ssgHit *results ;
+
+   int num_hits = ssgIsect ( root, &sphere, mat, &results ) ;
+
+   for ( int i = 0 ; i < num_hits ; i++ )
+   {
+     ssgHit *h = &(results [ i ]) ;
+
+     /* Do something with 'h' */
+   }
+
+
+Remember, you must finish using the results array before you do +another ssgIsect/ssgHOT/ssgLOS because all three functions share +the same results array. +

+By default, these functions only detect collisions with the front face +of polygons. You can make them detect only the back faces using: +

+
+  void ssgSetBackFaceCollisions ( bool b ) ;
+
+
+

+An ssgHit looks like this: +

+
+class ssgHit
+{
+  ssgLeaf *leaf ;
+  int      triangle ;
+  sgVec4   plane ;
+  sgMat4   matrix ;
+
+  ssgHit ()
+  int getNumPathEntries () ;
+  ssgEntity *getPathEntry ( int i ) ;
+} ;
+
+
+The 'leaf' member points at the leaf node that impacted the sphere. +The 'triangle' member tells you which triangle within the leaf +did the impacting. The 'plane' member contains the plane equation +of the impacting triangle and the 'matrix' element tells you +the net result of concatenating all the transform nodes from +the root to the leaf to the matrix you provided in the ssgIsect call. +

+It's possible for there to be multiple paths through the +scene graph to the leaf node. Sometimes you'll need to +look back up the tree to see nodes above the one that we actually +impacted with. Hence, you can read all the ssgEntities that were +traversed on the path from the root down to the leaf. Calling +the 'getNumPathEntries' function to find the number of nodes +along the path - and then 'getPathEntry(n)' to get the n'th entry +in the path. The 'root' node will always be the zeroth entry +in the path - and the leaf node will always be the last. +

Lights.

+SSG supports the eight standard OpenGL light sources as class 'ssgLight'. +Since there are only a finite number of these, they all exist all the +time - you just call: +
+
+  ssgLight *ssgGetLight ( int i ) ;
+
+
+...to get the i'th light should you need to manipulate it. +
+
+class ssgLight
+{
+  int isOn () ;
+  void on  () ;
+  void off () ;
+
+  void setPosition ( const sgVec3 pos ) ;
+  void setPosition ( float x, float y, float z ) ;
+
+  void setColour ( GLenum which , const sgVec4 colour ) ;
+  void setColour ( GLenum which , float r, float g, float b ) ;
+
+  void setHeadlight ( int head ) ;
+  int  isHeadlight () ;
+
+  void setSpotlight ( int spot ) ;
+  int  isSpotlight () ;
+
+  void setSpotDirection ( const sgVec3 dir ) ;
+  void setSpotDirection ( float x, float y, float z ) ;
+  void setSpotDiffusion ( float exponent, float cutoff = 90.0f ) ;
+  void setSpotAttenuation ( float constant, float linear, float quadratic ) ; 
+} ;
+
+
+Each light can be turned on or off - or tested to see if it's on or off. +

+Lights are positioned with 'setPosition()' - which can be relative +to the origin of the world - or relative to the SSG camera (in 'headlight' +mode). +

+If the 'spotlight' mode is enabled, +then the light intensity has a certain distribution and attenuation. +These parameters can be set with the 'setSpotXxx' methods. +Otherwise, the light source is considered to be directional, +or infinitely far away (in the direction of its position). +The 'spotlight' mode is initially disabled. + +

Miscellany.

+It's convenient to find out how much texture memory has been +consumed: +
+
+  int ssgGetNumTexelsLoaded () ;
+
+
+(Bear in mind that a texel could be 16 or 32 bits depending on +the hardware - and with MIPmapping enabled, 25% of the texels +will be in the MIPmaps - so ssgGetNumTexelsLoaded will return +a larger number than the total of the sizes of the input images +might suggest. +

Loading Database Files.

+To load a model file into SSG, you can either call a loader +function that is specific to the format of the file you +wish to load - or you can call 'ssgLoad' - which parses +the filename extension and calls the appropriate format-specific +loader. +

+At time or writing, there are MANY loaders for SSG: +

    +
  • ssgLoadSSG - for '.ssg' files - the 'native' SSG format. +
  • ssgLoadAC - for '.ac' files - a somewhat obscure format produced + by the 'AC3D' modelling tool - reasonably well tried + and tested. +
  • ssgLoad3ds - for '.3ds' files as produced by 3DStudio. +
  • ssgLoadASE - 3DSMAX ASCII EXPORT Version 2.00, well tested +
  • ssgLoadDXF - AutoCADs famous DXF format. well tested +
  • ssgLoadFLT - OpenFlight. Works for OpenFlight files generated by +recent versions of MultiGen - but not for those generated by some other +tools such as Designers' Workbench. +
  • ssgLoadMD2 - Quake MD2 +
  • ssgLoadOBJ - Wavefront, works well +
  • ssgLoadTRI - simple Tri format from "Andy Colbournes Editor". +
  • ssgLoadX - Microsofts DirectX-Format. Most features work. +
  • ssgLoadOFF - Geomview's OFF +
  • ssgLoadM - ??? +
  • ssgLoadATG - Ascii TerraGear. Used by Flight Gear Flight Sim. +
  • ssgLoadVRML1 - VRML1 format, only partially implemented. +
  • ssgLoadIV - Inventor format, only partially implemented. +
  • ssgLoadStrip - The format of a stripifier. +
+ +
+
+  typedef ssgBranch *(*ssgHookFunc)(char *) ;
+
+  ssgEntity *ssgLoad    ( const char *fname, const ssgLoaderOptions *options = NULL ) ;
+  
+  ssgEntity *ssgLoadSSG ( const char *fname, const ssgLoaderOptions *options = NULL ) ;
+  ssgEntity *ssgLoadAC  ( const char *fname, const ssgLoaderOptions *options = NULL ) ;
+  ssgEntity *ssgLoad3ds ( const char *fname, const ssgLoaderOptions *options = NULL ) ;
+  ...etc...
+
+
+Minimally, all you need to do is to call ssgLoadAC/ssgLoad3ds with the +name of the file to load. However, most file formats (AC3D's +and 3Dstudio's included) lack many desirable features, and it is also often +necessary to store application-specific information in the +file. +

+SSG's loaders will decode the comment fields found in the +nodes of many common file formats and pass these onto the +application via 'hookfunc'. This function should decode +the string and construct whatever kind of SSG node it +considers appropriate. +

+Similarly, the application may wish to embellish the +ssgState of a loaded node - and since state information +rarely has a comment field in most file formats, we +pass the texture filename instead and expect the application +to construct the entire ssgState: +

+
+  void ssgSetAppStateCallback ( ssgState *(*cb)(char *) ) ;
+
+
+One common problem with file loaders is that it's +often possible to refer to a second file from inside +the first - but the path to that file is often +not adequately defined by the original file. Hence, +the application can specify a file path to be prepended +to all model or texture file names. +
+
+  void ssgModelPath   ( char *path ) ;
+  void ssgTexturePath ( char *path ) ;
+
+
+You can only supply one path. If you need additional features, use the +function ulFindFile (for more see util-library-doc). + +The last three functions simply set values in the _ssgCurrentOptions +(type ssgLoaderOptions), for example: + +
+inline void ssgModelPath   ( const char *path )
+{
+  _ssgCurrentOptions -> setModelDir ( path ) ;
+}
+
+ +For more on ssgLoaderOptions see also the next page of this doc. + +

+ +Some loaders for file formats that use texture formats not +supported by ssg use this functions to find textures: +

+void ssgFindOptConvertTexture( char * filepath, char * tfname ) 
+
+It finds and optionally (= if necessary) converts the texture. +This is only really implemented for Windo$ :-(, for all others it +should just be the two lines you will find in the comment. I didn't +test it, that's the reason I commented it out. But it will warn you +when you have to convert something, so even for non-Windo$-users the +new function is already a step forward. +For the actual conversion, at first I wanted to use GIMP. So, in Deja, +I looked for "+gimp +convert +batch" and similar strings. I found +several people asking, but almost all the answer were to use +ImageMagick instead. ImageMagick is free as in beer. Also, the docs I +got with the newest gimp is extremely sparse :-(. Therefore, I tried +ImageMagick and this worked straight away. You should find ImageMagick +under +

+http://www.wizards.dupont.com/cristy/ImageMagick.html +

+Plib uses the ImageMagick application "convert". Since there are other +convert.exe-programs on my computer, I had to copy the ImageMagick +stuff into the directory of my plib-application, so that it uses the correct +convert.exe. +

+ + +Most file formats contain considerable numbers of redundant +nodes (because of the way people build using these tools). +This function walks a database sub-tree multiplying +out any ssgTransform nodes and replacing them with +ssgBranch'ed - unless they have userdata associated with them. +Any branch nodes with zero kids are deleted - any with just +one kid are eliminated and the child node pushed up one level. +

+
+  void ssgFlatten ( ssgEntity *ent ) ;
+
+
+It's important for 3D performance to optimise +triangles into triangle strips or fans. Since most +file formats don't record strip/fan information, +it's useful to call: +
+
+  void ssgStripify ( ssgEntity *ent ) ;
+
+
+

Saving Database Files.

+Most SSG programs will simply load a file and display it in +some way - but occasionally, it's useful to be able to write +a file back out again. +

+To write a model file from SSG, you can either call a writer +function that is specific to the format of the file you +wish to save - or you can call 'ssgSave' - which parses +the filename extension and calls the appropriate format-specific +writer. +

+Saving into ssg-format is done with these functions: +

    +
  • ssgSaveSSG - for '.ssg' files - the 'native' SSG format. +
+
+
+  int ssgSave    ( char *fname, ssgEntity *ent ) ;
+  int ssgSaveSSG ( char *fname, ssgEntity *ent ) ;
+
+
+This returns TRUE if the operation worked - FALSE if it failed. +You will also find writers for the 3DS, AC, ASE, ATG, DXF, M, OBJ, OFF, QHI, TRI and +X formats. + +

Features of the file formats and status of the loaders/writers

+ +Here comes a table of the features of all the file formats and loaders and writers. +VRML doesn't really work, so you won't find it here. +The "QHI" (QHull Input - a format used by a toll to create convex hulls) +writer only writes a point cloud and suppoorts no other features, so I also didn't add it to the table. +BTW, if you want to create convex hulls of existing geometry, you just need a few lines. Look +into PPE (prettypoly editor, on SourceForge as well), into the file ppeCoreFuncs.cxx, +function addConvexHull. +The SSG loaders/writers support all +features of the ssg-lib, so missing features mean they miss in the library (normaly because they miss in OpenGL) +The letters mean: +

+A = feature not in file format +
+B = feature in file format and not implemented, not planned. +
+C = feature in file format and not implemented, but planned. +
+D = feature in file format and partly implemented or not tested. +
+E = feature in file format and implemented. +

+And here are the features with some explanaitions: +

+ +
    +
  • Filled polys - Planar polygons. In the ssg-lib, this is the only primitive you can use to make "solid" looking models. This is a 2D primitive; it has no volume but an area. +
  • # sides - No of sides per poly. This is of course equal to number of vertices per poly. Some formats support only triangles, some +also quads and some support n-sided polys, that is they have no restrictions. +
  • Lines - for example used for high voltage lines in a flight simulator. +This is a 1D primitive; it has no area but a length. +
  • Points - for example used for small lights. +This is a "0D" primitive; it has no length. +
  • Sub objects - The complete model may consist of several sub models. +There are several reasons one wants this, for example to make the structure of the model +clearer to humans, to easily enable humans or programs to move, colour, texture, animate etc +one part, for example one wheel of the complete model. +
  • Hierarchie - You not only have sub objects, but there is a parent-kid relation between some, +for example, the upper arm of a human model may be "under" the body and the lower arm "under" the upper arm etc. +
  • DAG - direct acyclic graph means that the hierarchie may not only be a tree where +each node has exactly one parent (apart from the root, which has zero parents), but that nodes may have more than one parent. +Used for example in cars to have the wheel geometry only once. If the one wheel-node has four parents, this means +it will be rendered four times when the scene is drawn. +
  • Colours - Things can have a colour. Uncoloured objects are always white. +
  • Textures - Texture things with 2D bitmaps. +
  • Texture coordinates - The texture mapping is arbitrary. +
  • Texture coord. per face AND vertex - If a vertex is part of three faces, then this feature +allows it to have three texture coordinates. For example, a cube may have 18 texture coordinates, even if it has much fewer vertices. +
  • Texture per face - each face may have another texture bitmap. Formats (and the ssg lib) that +don't have this have to increase the number of nodes to get this effect. +
  • Transparency - Some polys may be partially or completely transparent. +
  • Animation - There may be many different sorts of animation. +
  • Billboards - geometry that automatically rotates so it always faces the viewer. Normaly flat. +As an example, can be used to model trees in a driving simulator. +
  • LOD - stands for "Level of Detail" and means there can be geometries of varying +complexity for the model, so for example, if it is near the viewer you use many polys +and if it is far away you use few polys so that the impact on rendering speed is low. +
  • Other switches - switch means you can switch the visibility of some nodes on and off. +
  • Ascii or Binary - A stands for Ascii, B for Binary files. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Feature 3DS
load
 AC
load/
save
 ASC
save
 ASE
load/
save
 ATG
load/
save
 DXF
load
 DXF
save
 FLT
load
 M
load/
save
 MD2
load
 OBJ
load
 OBJ
save
 OFF
load/
save
 SSG
load/
save
 Strip
load
 TRI
load/
save
 X
load
 IV
load
 VRML1
load
 Filled polys E E E E E E E(5) E E/D ? E E E E E  E E E
 # sides  n/3 3 3 n 3,4(4) 3 n   n? 3 n n(4)  3? n 3,4 3,4
 Lines A D/C C E A(?) E E A A ? E E A? E A  A B B
 Points A A E C A(?) A A B A ? A A A E A  A B B
 Sub objects E E/D E E A(?) A A E A ? C-D C-D A E A  E E E
 Hierarchie A E/D E? E A(?) A A E A ? C C A E A  C E E
 DAG A A A A A(?) A A E A ? A A A E A  A(?) E E
 Colours E E/D E? E ? E E D(1) A ? D C A E A  E B B
 Textures D E/D E E E A A E A ? D C B E A  E E E
 Texture coord. D E E E E A A E A ? E C B E A  E E E
 Texture coord.
per face
AND vertex
 D(?) D(?) A E E A A A A ? E C B(?) A A  C E E
 Texture per face  D(?)/- C A E A A E A ? A A B(?) A A  C B A
 Transparency D D D D A(?) A A E A ? A? A? B(?) E A  E B B
 Animation B A A E A A A B(2) A ? A? A? A E A  B or C B A
 Billboards  A A A A A A E A ? A A A E A  A B A
 LOD  A A A A A A E A ? A A A E A  A B B
 Other switches  A A A A A A D A ? A A A E A  A D D
 A=Ascii or
B=Binary
 B A A A A A A B A B A A A B ? A A+B(3) A A
+footnotes: +

+(1) problematic for ancient files +
+(2) DOFs are not implemented +
+(3) There is an ascii- and a binary X-file-format. +I only implemented the ascii-one and probably wont implement the +binary one. There is a free (as in beer) converter by Microsoft +running under Windo$. +
+(4) It is possible to have polys with an arbitrary number of vertices in ssg. +But then you may only use one poly per node. Also, you can not mix 3 and 4 sided polys in one node. +
+(5) Some OpenGL modes, like for example Quads, are ignored. This means some parts of the model +may dissappear when saving into DXF files. +

+Additional info on some formats: + +

+ATG: +
+ATG stands for ascii TerraGear. Loading of TriStrips and TriFans not implemented yet. +Untextured parts are lost, for example when you save and load +Steve Bakers Tuxedo, you will loose the feet, since they are not +textured. +The files written are not optimal, they use no strips/fans, +only have triangles etc. +Also, one vertex that needs several texture coords is written out several +times. + + +

+3ds-writer: +
+I (Per) have one basicly working, but since there seems to be so much else to do +with plib right now, I'm a bit reluctant to put my energy into it. Also, the +only 3ds-loader I've tested files written by it with is the one in ssg :-) + + +

+OFF loader: +
+Warning: There are two formats called OFF! We support the OFF from GeomView, +not the one from DEC. +We support 2D and 3D, but no higher dimensions. + +

+.SSG file loader/writer: +
+We number .SSG file formats so that for example the loaders knows +what to expect. Until now, there is +
+format "0" - Used by plib 1.2.0, 1.3.x +
+format "1" - Will be used by 1.4.0 +
+Currently, we are between "0" and "1". Normally, we want to keep at least our loader +compatible, but the changes from zero to one would bloat the code so much and it seems +.SSG file version zero were only used by people for temporary files, so we decided to make an incompatible break. +If you need to read or write version zero, either get plib from SVN with the date 14.1.2001, or, if you are a Windo$ person, get +prettypoly.sourceforge.net/download/ppewinbin_ssg_version_zero.zip +This allows you to save and load .ssg version zero. +
+One of the new features in format "1" might be worth mentioning. +It is now possible to load and save *any* class derived from ssgBase (notably +the ssgAux node types). +All that is needed for saving to work is an implementation of the virtual save() method. +Loading requires the corresponing load() method, and also means for creating +an instance of the class, which is accomplished +by a call to ssgRegisterType(). +See the ssgAux implementation for example usage; +the convenience function ssgaInit() registers the ssgAux classes. +

+.X file writer: +
+Planned. +

+.X file loader: +
+The .X-entity "Frame" is not yet implemented. +If you convert files into .X with "3D Exploration", you can check the +option "without frames". + +

+VRML1/IV file loaders: +
+These are only partially implemented, and are useful primarily for +mesh-based models (textured or untextured). It would be useful to add +material support to these loaders, as well as explicit normal definition. + +
+ + + + + + +
<= previous =Return to SSG Index= next =>
+
+ + +
+Valid HTML 4.0! + +
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+
+ + + diff --git a/doc/ssg/ssgBase.html b/doc/ssg/ssgBase.html new file mode 100644 index 0000000..bf7667d --- /dev/null +++ b/doc/ssg/ssgBase.html @@ -0,0 +1,233 @@ + + + + + A Simple Scene Graph API for OpenGL. + + + +

class ssgBase - The Universal Abstract Base Class.

+All significant SSG classes are derived from ssgBase - which offers a type testing +mechanism and a means to print out the tree hierarchy in human-readable form, +or to save/load it to/from disk. +
+
+class ssgBase 
+{
+  void  ref () ;
+  void  deRef () ;
+  int     getRef () ;
+
+  int   isA ( int ty ) ;
+  int   isAKindOf  ( int ty ) ;
+
+  int   getType (void) ;
+  virtual char *getTypeName(void) ;
+
+  ssgBase *getUserData () ;
+  void  setUserData ( ssgBase *user_data ) ;
+
+  void  setName ( char *nm ) ;
+  char *getName () ;
+  const char *getPrintableName () ;
+
+  virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ;
+  virtual int load ( FILE *fd ) ;
+  virtual int save  ( FILE *fd = stderr ) ;
+
+  ssgBase *clone ( int clone_flags ) ;
+}  ;
+
+
+ +

Reference Counting.

+All SSG classes are reference counted - that means that whenever you +connect a node into the scene graph with ssgBranch::addKid(), we +increment its reference count and each time we remove a node from +the graph with ssgBranch::removeKid(), we decrement the count - +and if it's zero, we'll delete the node to recover memory. +

+Sometimes, you need a node to stay in memory even though it may be +be disconnected from the scene graph. You can achieve that by +calling ssgBase::ref() to increment the reference count. +If you later find you don't need that node anymore then you may +ssgBase::deRef() it. If you ssgBase::deRef() +a node to zero, SSG won't automatically delete it - you still need to use +delete to do that. Since such deletions are recursive, +you may delete an entire sub-branch with a single call. +

+Instead of using ssgBase::deRef() directly, you should use +ssgDeRefDelete() which automatically deletes the node if +the reference count drops to zero. +

+You can read the current ref count for a node +using ssgBase::getRef(). +

Names.

+It's often useful to attach an ASCII name to a node in the +scene graph - this is often derived from a name field in +whatever modelling tool was used to create the object. +ssgBase::setName(s) sets the name, +ssgBase::getName() returns it. + +

User Data

+Although one can derive a new C++ class from an SSG class and thereby customise +it's behavior, it's often more convenient to simply attach application-specific +data structures to a basic entity. Two functions are provided: +ssgBase::getUserData() and ssgBase::setUserData(data). +

+Notice that user data is of class ssgBase - which means that user data +can be named, ref-counted - and can in turn have user data of it's own. +This allows user data to be formed into linked lists when multiple +user data items need to be attached to a single node. + +

Destructor Functions

+When an SSG entity is NOT connected into the scene graph in any +way, then the correct way to get rid of it and free up memory +is to call it's destructor function. However, when the entity +is included into the scene graph, you should disconnect it +from the tree and let the reference count mechanism take care +of the cleanup. +

Type Names

+SSG frequently needs to know what kind of an object an ssgBase is. +Since C++ programs may create new classes that inherit from SSG +classes, we provide several functions to make run time type determination +possible. There is an external function for each type that +returns the type token for that type: +
+
+  int ssgTypeBase       () ;
+  int ssgTypeEntity     () ;
+  int ssgTypeLeaf       () ;
+  int ssgTypeVTable     () ;
+  int ssgTypeVtxTable   () ;
+  int ssgTypeDisplayList() ;
+  int ssgTypeBranch     () ;
+  int ssgTypeBaseTransform ();
+  int ssgTypeTransform  () ;
+  int ssgTypeTexTrans   () ;
+  int ssgTypeSelector   () ;
+  int ssgTypeTimedSelector () ;
+  int ssgTypeRangeSelector () ;
+  int ssgTypeRoot       () ;
+  int ssgTypeCutout     () ;
+
+
+Now, you can use the ssgBase::isA(type) or ssgBase::isAKindOf +to test the type of the node. For example, if you want to test +whether a node is a Leaf node or a Branch node, you can do this: +
+
+  if ( mynode -> isAKindOf ( ssgTypeLeaf() ) )
+    printf ( "Leaf node\n" ) ;
+  else
+  if ( mynode -> isAKindOf ( ssgTypeBranch() ) )
+    printf ( "Branch node\n" ) ;
+  else
+    printf ( "Something else\n" ) ;
+
+
+Notice that if you ran that code on (say) an ssgSelector, then it'll +print "Branch node" since the Selector class is derived from the Branch +class. If you wanted to tell if a node was *exactly* a Branch node - +and not from a derived class, then you could use: +
+
+  if ( mynode -> isA ( ssgTypeBranch() ) )
+    printf ( "Branch node\n" ) ;
+
+
+Finally, you can actually read the type of a node - either as a +token (using ssgBase::getType()) or as an ASCII string +(using ssgBase::getTypeName()). The latter is very useful +for debug routines: +
+
+  printf ( "ERROR - something wrong with my '%s' node.\n",
+                    mynode -> getTypeName () ) ;
+
+
+ +

Printing

+It's sometimes useful during debug to print a section of the +scene graph so you can examine it. ssgBase::print(fd, indent, how_much) +does that for you - it prints out the node itself - and anything +connected beneath it in the scene graph. fd is the +file descriptor to print to (defaults to stderr) and +indent is a string that will prefix all output lines +- and is used internally within SSG to make printout of tree +structures more legible by indenting them. +

+The values for the parameter how_much may be 0,1,2,3 or 4 +and determine how much is printed, with 0 meaning little +and 4 meaning much. +
+For how_much = 0, basic information of the branches is printed +
+For 1, additionally there is: basic leaf info, state pointers +
+For 2, additionally there is: states, user data, number of parents, +bSphere +
+For 3, additionally there is: Reference count +
+For 4, additionally there is: contents of vertex-, normal-, colour-, +texCoord- and index-arrays +
+Experience tells that for how_much = 0 you get very little +out put, with 1, 2 and 3 a manageable amount and with 4 a huge amount, +up to 100 MB for a medium sized model. + + +

+It would be unwise +to attempt to parse the output of ssgBase::print into another +program since it is only intended for human consumption and the +format may change dramatically between revisions of SSG. + +

Cloning:

+All classes derived from ssgBase have a member function +ssgBase *clone(int clone_flags) which new's a +new object of that class as a copy of the calling object. +

+The 'clone_flags' is a set of tokens that you 'OR' together to +specify how 'deep' you want the cloning to go. By default +(with clone_flags==0), only the object itself is cloned and +the clone will simply point to the same child structures as +the original object. However, if you OR in 'SSG_CLONE_RECURSIVE', +then all ssgEntities beneath this one will also be cloned. +ORing in SSG_CLONE_GEOMETRY will cause all the per-vertex data +at the leaf nodes to also be cloned. SSG_CLONE_STATE causes +ssgState objects to be cloned also, SSG_CLONE_STATE_RECURSIVE +also causes states pointed to by other states to be copied, +SSG_CLONE_USERDATA causes user data attached to +the original node to be referenced (NOT copied) by the clone - +otherwise, user data for the clone is set to NULL. Finally, +SSG_CLONE_TEXTURE causes texture maps to be replicated also. +

+Most copy operations will typically use either zero, SSG_CLONE_RECURSIVE +or (SSG_CLONE_RECURSIVE | SSG_CLONE_GEOMETRY) + +


+ + + + + + +
<= previous =Return to SSG Index= next =>
+
+ + +
+Valid HTML 4.0! + +
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+
+ + + diff --git a/doc/ssg/ssgContext.html b/doc/ssg/ssgContext.html new file mode 100644 index 0000000..9ab6498 --- /dev/null +++ b/doc/ssg/ssgContext.html @@ -0,0 +1,183 @@ + + + + + A Simple Scene Graph API for OpenGL. + + + +

ssgContext

+A 'context' is a set of parameters that relate to rendering +one SSG image. It contains the camera parameters and some +default state information. +
+
+  class ssgContext
+  {
+    ssgContext () ;
+    void forceBasicState () { basicState -> force () ; }
+
+    void makeCurrent () ;
+    int  isCurrent () ;
+
+    void overrideTexture   ( int on_off ) ;
+    void overrideCullface  ( int on_off ) ;
+    int  textureOverridden  () { return ovTexture  ; }
+    int  cullfaceOverridden () { return ovCullface ; }
+    void setCullface ( int on_off ) { cullFace = on_off ; }
+    int  cullfaceIsEnabled () { return cullFace ; }
+
+    sgFrustum *getFrustum () { return frustum ; }
+
+    void getNearFar ( float *n, float *f ) ;
+    void getFOV     ( float *w, float *h ) ;
+    void getOrtho   ( float *w, float *h ) ;
+    void setNearFar ( float  n, float  f ) ;
+    void setOrtho   ( float  w, float  h ) ;
+    void setFOV     ( float  w, float  h ) ;
+
+    int  isOrtho () { return orthographic ; }
+
+    void getCameraPosition ( sgVec3 pos ) ;
+    void setCamera ( sgMat4 mat ) ;
+    void setCamera ( sgCoord *coord ) ;
+
+    void loadProjectionMatrix () ;
+    void loadModelviewMatrix  () ;
+
+    void getProjectionMatrix  ( sgMat4 dst ) ;
+    void getModelviewMatrix   ( sgMat4 dst ) ;
+
+    void  clrClipPlane   ( int i ) ;
+    void  setClipPlane   ( int i, sgVec4 plane ) ;
+    int   isSetClipPlane ( int i ) ;
+    float *getClipPlane  ( int i ) ;
+  } ;
+
+
+In all 3D rendering, you need the concept of a virtual camera - or +eyepoint. This is set up in SSG with the following calls: +
+
+  void ssgContext::setFOV    ( float w, float h ) ;
+  void ssgContext::setNearFar( float n, float f ) ;
+  void ssgContext::setCamera ( sgCoord *coord ) ;
+
+
+The setFOV call sets up the vertical and horizontal fields +of view (in degrees), setNearFar sets the near and far +clip planes (in whatever units your model is built in). +Finally, you can position the virtual camera relative to +the database origin using setCamera. +

+Very often, an SSG program contains other non-SSG routines that +are accessing OpenGL state. Even a menu drawn using PUI or an +overlay in raw OpenGL or using FNT will change the current +state of OpenGL. Since SSG does 'lazy' state changes (only +updating those states that need to be changed) - it will be +fooled into no setting some things that some ssgLeaf nodes +really need. +

+This isn't a problem so long as the application doesn't change states +DURING ssgCullAndDraw (by using derived class member functions, callbacks, +etc). If you need to do that then be sure to call forceBasicState() +before you return to SSG. +

+
+   void ssgContext::forceBasicState ( void ) ;
+
+
+

+During testing, you sometimes need to disable texture rendering, +or backface culling: +

+
+  void ssgContext::overrideTexture  ( int on_off ) ;
+  void ssgContext::overrideCullface ( int on_off ) ;
+
+
+The six standard OpenGL user-defined clipping planes +can be setup and managed automatically using these +calls: +
+
+    void  clrClipPlane   ( int i ) ;
+    void  setClipPlane   ( int i, sgVec4 plane ) ;
+    int   isSetClipPlane ( int i ) ;
+    float *getClipPlane  ( int i ) ;
+
+
+setClipPlane takes the number of the plane (0 through 5) and +a plane equation which will be applied at the next cull/draw +cycle. clrClipPlane removes a clip plane. isSetClipPlane inquires +about whether the i'th plane is turned on and getClipPlane returns +the plane that's currently set as the i'th plane. +

+Once you have your context set up as you'd like, you have to +make it become the 'current' context. +

+
+  void ssgContext::makeCurrent () ;
+
+
+There is a non-class function: +
+
+  ssgContext *ssgGetCurrentContext() ;
+
+
+...which returns the current context. +

+The 'ssgContext' class was not present in PLIB 1.0.xx, so (for +backwards compatibility) there is an initial context assigned +inside ssgInit(). In addition to the member functions of ssgContext, +there are a number of equivelent global functions that are +equivelent to ssgGetCurrentContext()->member_function(). These +functions are deprecated for new code: +

+
+  inline void ssgForceBasicState   () ;
+  inline void ssgGetCameraPosition ( sgVec3 pos ) ;
+  inline void ssgOverrideTexture   ( int on_off ) ;
+  inline void ssgOverrideCullface  ( int on_off ) ;
+  inline void ssgGetNearFar        ( float *n, float *f ) ;
+  inline void ssgGetFOV            ( float *w, float *h ) ;
+  inline void ssgSetFOV            ( float w, float h ) ;
+  inline void ssgSetOrtho          ( float w, float h ) ;
+  inline void ssgSetNearFar        ( float n, float f ) ;
+  inline void ssgSetCamera         ( sgMat4 mat ) ;
+  inline void ssgSetCamera         ( sgCoord *coord ) ;
+  inline void ssgLoadProjectionMatrix () ;
+  inline void ssgLoadProjectionMatrix ( sgFrustum *f ) ;
+  inline void ssgGetProjectionMatrix  ( sgMat4 dst ) ;
+  inline void ssgGetModelviewMatrix   ( sgMat4 dst ) ;
+  inline void ssgLoadModelviewMatrix  () ;
+  inline void ssgLoadModelviewMatrix  ( sgMat4 mat ) ;
+
+
+ + +
+ + + + + + +
<= previous =Return to SSG Index= next =>
+
+ + +
+Valid HTML 4.0! + +
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+
+ + + diff --git a/doc/ssg/ssgEntity.html b/doc/ssg/ssgEntity.html new file mode 100644 index 0000000..51d6ffa --- /dev/null +++ b/doc/ssg/ssgEntity.html @@ -0,0 +1,146 @@ + + + + + A Simple Scene Graph API for OpenGL. + + + +

class ssgEntity - A Node in the Tree.

+All nodes in the SSG scene graph are ssgEntities. +
+
+clas ssgEntity : public ssgBase
+{
+public:
+ 
+  ssgEntity (void) ;
+  virtual ~ssgEntity (void) ;
+  
+  int  getTraversalMask     () ;
+  void setTraversalMask     ( int t ) ;
+  void setTraversalMaskBits ( int t ) ;
+  void clrTraversalMaskBits ( int t ) ;
+
+  virtual void recalcBSphere (void) ;
+  int  isDirtyBSphere (void) ;
+  void dirtyBSphere  () ;
+  sgSphere *getBSphere () ;
+
+  virtual int getNumKids (void) ;
+  int getNumParents () ;
+  ssgBranch *getParent ( int p ) ;
+  ssgBranch *getNextParent () ;
+
+  virtual void cull  ( sgFrustum *f, sgMat4 m, int test_needed ) ;
+  virtual void isect ( sgSphere  *s, sgMat4 m, int test_needed ) ;
+  virtual void hot   ( sgVec3     s, sgMat4 m, int test_needed ) ;
+} ;
+
+
+ +

The tree structure.

+Every entity has a list of parent entities and (conceptually), a list of +child entities ("kids"). In practice, ssgRoot nodes never have parents +and ssgLeaf nodes never have kids. +

+The structure of the scene graph permits the same node to be inserted +into the graph in multiple locations. This is useful for saving +space when the same object is needed many times in the scene. +Hence, any given node may have more than one parent node. +

+You can traverse the list of parent nodes +using ssgEntity::getNumParents() to find out the number +of parents this node has and +ssgEntity::getParent(n) to locate the n'th parent. +

+Alternatively, after calling getParent, you can call getNextParent +to get the N+1'th parent node - it returns NULL when no more parents +are available. +

+As a convenience for general tree-walking routines, there is a +ssgEntity::getNumKids() call - which will always +return zero on leaf nodes. You cannot actually get kid nodes unless +the node is some kind of ssgBranch. + +

Traversals

+Much of the work done on an SSG scene graph entails 'traversing' +the tree structure. This is done most commonly to display the +scene using OpenGL - but is also done when doing intersection +testing and other operations. +

+It's quite useful to be able to limit the traversal so that +certain nodes do not get tested. This can save time - or +prevent undesirable side-effects. +

+Each entity has a 'traveral mask' - which is a simple integer +with one bit per kind of traversal. At present, there are +three kinds of traversal: +

+
+SSGTRAV_CULL   -- Culling to the field of view.
+SSGTRAV_ISECT  -- General intersection testing.
+SSGTRAV_HOT    -- Height-over-terrain testing.
+
+
+You can directly set or get the traversal mask with ssgEntity::setTraversalMask(m) +ssgEntity::getTraversalMask(). You can set an individual traversal bit using +ssgEntity::setTraversalMaskBits(m) or clear one using +ssgEntity::clrTraversalMaskBits(m). + +

Bounding Sphere

+Quite a few graphics algorithms can be accellerated using a +bounding sphere. The standard ssgEntity uses bounding +spheres to do field-of-view and intersection testing. +

+Clearly one does not want to recompute the bounding sphere +every frame - just some objects do change their size over +time. Hence, the bounding sphere is lazily evaluated. +

+Whenever you do something to change the size or shape of an entity, +you should call ssgEntity::dirtyBSphere(). This will +mark this entity's sphere as invalid ("dirty") and also, walk +backwards up the scene graph tree making all the nodes above +this one dirty too. The next time SSG needs to know the bounding +sphere size, it'll recompute it. +

+If you'd prefer for the bounding sphere recalculation to be +done immediately, then you can call ssgEntity::recalcBSphere() +and it will be done immediately. Branch nodes like ssgTransforms will +automatically dirty their bounding spheres when necessary. Leaf nodes +generally do not. +

+When anyone needs to know the bounding sphere size for a node, +they'll call ssgEntity::getBSphere() - which will +recaclulate the Bsphere if it needs to. + +

Culling and Drawing

+The actual tree-traversal, culling and rendering is handled by +a virtual function ssgEntity::cull() - calling +this on the root node in the scene graph causes the entire +scene to be rendered in an efficient manner. + +
+ + + + + + +
<= previous =Return to SSG Index= next =>
+
+ + +
+Valid HTML 4.0! + +
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+
+ + + diff --git a/doc/ssg/ssgLeaf.html b/doc/ssg/ssgLeaf.html new file mode 100644 index 0000000..9c5f08b --- /dev/null +++ b/doc/ssg/ssgLeaf.html @@ -0,0 +1,305 @@ + + + + + A Simple Scene Graph API for OpenGL. + + + +

class ssgLeaf - Leaf nodes.

+Leaf nodes are those that actually make OpenGL calls +or take other 'rendering' actions - they contain +all of the geometric information in the scene. +
+
+class ssgLeaf : public ssgEntity
+{
+public:
+  int  getExternalPropertyIndex ()
+  int  isTranslucent ()
+  int       hasState ()
+  ssgState *getState ()
+  void      setState ( ssgState *st )
+
+  virtual float *getVertex   ( int i )
+  virtual float *getNormal   ( int i )
+  virtual float *getColour   ( int i )
+  virtual float *getTexCoord ( int i )
+
+  virtual int  getNumTriangles() ;
+  virtual void getTriangle ( int n, short *v1, short *v2, short *v3 )
+
+  virtual int  getNumLines () ;
+  virtual void getLine ( int n, short *v1, short *v2 ) ;
+
+  int  getNumLines () ;
+  void getLine ( int n, short *v1, short *v2 ) ;
+
+  virtual void transform ( sgMat4 m )
+
+  void setCullFace ( int cf )
+  int  getCullFace ()
+
+  void makeDList () ;
+  void deleteDList () ;
+  GLuint getDListIndex () ;
+} ;
+
+
+ +

Pre- and Post-Draw Callbacks.

+It's frequently useful to have an application function called +just before and/or just after a leaf node is rendered. +
+
+  typedef int (*ssgCallback)( ssgEntity * ) ;
+  ssgCallback getCallback ( int which ) ;
+  void setCallback ( int which, ssgCallback cb ) ;
+
+
+(Where 'which' is either SSG_CALLBACK_PREDRAW for a function that's +to be called before the node is drawn or SSG_CALLBACK_POSTDRAW for +one that's called after rendering.) In both cases, the function will +be passed a pointer to the leaf node that's about to be drawn, and +(in the case of PREDRAW callbacks), may return FALSE to prevent the +node from being drawn, or TRUE to have it draw normally. +

Display Lists

+A leaf node is normally rendered in 'immediate' mode in OpenGL, +so that changes you make to the leaf will be reflected on the +screen on the next occasion that it's drawn. However, on some +graphics hardware, it's more efficient to create an OpenGL +display list for each leaf node. This can be managed by +calling ssgLeaf::makeDList(). If you want to +make changes to the Leaf, you'll have to call makeDList again +since OpenGL does not support the editing of display lists. +

+You can call ssgLeaf::deleteDList() to stop +this leaf from being display listed from now on and to +free up the display list memory. +ssgLeaf::getDListIndex() returns the OpenGL +display list handle - or zero if no display list exists +for this leaf. +

+If you change a leaf node's geometry when it has an +active display list without calling either deleteDList +or makeDList again, then any subsequent operation +involving rendering this node could fail. + +

Face Culling.

+By default, ssgLeaf nodes are back-face culled, you can change +that for any given node using ssgLeaf::setCullFace(cf) +where cf is TRUE to enable backface culling, +FALSE to disable it. You can test the state of face culling +using ssgLeaf::getCullFace(). +

State Management.

+OpenGL supports a wide selection of state information - things like +texture, materials and such. All of this information is held in a +separate SSG class hierarchy: 'ssgState'. Each leaf has a state +which it sets up before drawing the geometry that the leaf contains. +

+Nodes may also be stateless - but that isn't useful for any +of the existing SSG leaf node types. +

+You can set the state for a node using ssgLeaf::setState(state) +and query it using ssgLeaf::getState(). You can ask if +a node has state information attached using ssgLeaf::hasState(). +

+Since OpenGL does not render translucent object well when Z-buffering +is enabled, it's often useful to know if an object is translucent. +ssgLeaf::isTranslucent() handles that test. +

+It is often useful to tag ssgState's with external properties - and +you can retrieve the property of a leaf's state using +ssgLeaf::getExternalPropertyIndex(). +

Querying Geometry

+The actual storage format for geometry in classes derived from +ssgLeaf varies from class to class. However, it's very useful +to be able to query the geometry in an implementation-independent +manner. +

+Although classes derived from ssgLeaf are entitled to store their +geometry in any form, all of them are required to respond to +queries about basic triangle primitives. +

+Firstly, you can get a count of the number of triangles in this +leaf using ssgLeaf::getNumTriangles(). Each triangle +has an index number for each vertex which can be queried using +ssgLeaf::getTriangle(n,&v1,&v2,&v3) which copies +the 'short' indices for the n'th triangle's three vertices into +v1, v2 and v3. +

+Once you know the indices of a triangle's vertices, you can ask for +more information about that vertex using +ssgLeaf::getVertex(i), +ssgLeaf::getNormal(i), +ssgLeaf::getColour(i), and +ssgLeaf::getTexCoord(i). These calls allow you to +retrieve the i'th vertex, normal, colour or texture coordinate as +a short floating point array. (3 elements for Vertex and Normal, +4 elements for Colour (RGBA) and two elements for a texture coordinate. +

+Analogous to getting the triangles, +you may use ssgLeaf::getNumLines () +and ssgLeaf::getLine ( int n, short *v1, short *v2 ) ; +to get the number of lines and to get the n. line. + +

+You can transform all the vertices of a leaf each frame by placing +an ssgTransform node above the leaf in the scene graph - but for +transformations that never change, it's more efficient to pre-transform +the vertices in the leaf node. +ssgLeaf::transform(matrix) permenantly transforms all +the vertices and normals of this leaf by multiplying them by the +matrix. (In the case of the normals, the translation part of the +matrix is ignored). +

+It's inadvisable to repeatedly transform a leaf using transform +since roundoff error will be accumulated with bad consequences (eventually). +In those cases, use an ssgTransform node. + +

class ssgVtxTable - A Vertex-table leaf node.

+This class allows one to represent leaf geometry as arrays of vertex, +normal, texture coordinate and colour data. As a derived class of +ssgLeaf, Vertex Tables add a constructor function to take the +pre-computed vertex data: +
+
+  ssgVtxTable ( GLenum ty, ssgVertexArray   *vl,
+                           ssgNormalArray   *nl,
+                           ssgTexCoordArray *tl,
+                           ssgColourArray   *cl ) ;
+
+
+'ty' is an OpenGL primitive type (such as one might pass to glBegin): +
+
+    GL_POLYGON
+    GL_TRIANGLE_FAN
+    GL_TRIANGLES
+    GL_TRIANGLE_STRIP
+    GL_QUAD_STRIP
+    GL_QUADS
+
+
+the remaining arguments are lists of (x,y,z) vertices, (nx,ny,nz) +normals, (s,t) texture coordinates and (r,g,b,a) colours. +

class ssgVertexArray/ssgNormalArray/ssgTexCoordArray/ssgColourArray - Vertex data storage classes.

+These four classes are used for storing vertex data for ssgVtxTable nodes. +Each class implements an extensible array that grows as you add data to +it. +
+
+  ssg*Array::ssg*Array ( int init = 3 ) ;
+
+
+When you construct the array, you may specify an initial size for it, +the default is three elements. If you don't know how big the array +is, don't worry about it - but if you do know, there are time and +storage space advantages to telling the class the exact number. +
+
+  void ssgVertexArray  ::add ( sgVec3 data ) ;
+  void ssgNormalArray  ::add ( sgVec3 data ) ;
+  void ssgTexCoordArray::add ( sgVec2 data ) ;
+  void ssgColourArray  ::add ( sgVec4 data ) ;
+
+
+These functions tack another data element onto the end of the array. +
+
+  float *ssg*Array::get ( int i ) ;
+
+
+Returns the address of the i'th element of the array. +
+
+  int ssg*Array::getNum () ;
+
+
+Returns the number of data elements currently stored in the array. +
+
+  void ssg*Array::removeAll () ;
+
+
+Empties the array. +

class ssgTween - A Vertex-table morphing node.

+This node is derived from ssgVtxTable. Where VtxTable can retain +a set of arrays, one each for Vertex coordinates, Normals, Texture +Coordinates and Colours, the ssgTween node can store an unlimited +number of 'banks' of these arrays. +

+Hence, one constructs an ssgTween by specifying it's OpenGL primitive +type: +

+
+  ssgTween::ssgTween ( GLenum ty ) ;
+
+
+And then create some number of 'banks' of data arrays by calling: +
+
+  int ssgTween::newBank ( ssgVertexArray   *vl,
+                          ssgNormalArray   *nl,
+                          ssgTexCoordArray *tl,
+                          ssgColourArray   *cl ) ;
+
+
+...once for each bank. All other ssgVtxTable calls operate ONLY +on the 'current bank' - which is either the most recent one you +created with newBank - or you can go back to an older bank by +calling: +
+
+  void ssgTween::setBank ( int bankID ) ;
+  int  ssgTween::getBank () ;
+
+
+(newBank returns the number of the bank it created in case you +lose count!). +

+ssgTween's idea of the 'current bank' is reset to zero after +rendering it...so be sure to always call setBank immediately +before working on it's component arrays. +

+When the ssgTween node is rendered, it works cooperatively +with whichever ssgTweenController node is above it in the +scene graph. See the section on ssgTweenController for more +details. +

+IMPORTANT NOTE: There must be an identical number of vertices, +normals, etc in each bank. If you get that wrong, SSG will +exit with an 'abort'. Note that there is a specific optimisation +in ssgTween that avoids the computational cost of interpolating +between two sets of vertex data if EITHER: +

    +
  • The ssgTweenController's selected bank number happens to +be an integer. +
  • The previous and next banks have the same ssg*Array pointer. +Since one generally doesn't wish to interpolate normals, colours +or texture coordinates, it's important to pay attention to this. +
+
+ + + + + + +
<= previous =Return to SSG Index= next =>
+
+ + +
+Valid HTML 4.0! + +
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+
+ + + diff --git a/doc/ssg/state.html b/doc/ssg/state.html new file mode 100644 index 0000000..7205e21 --- /dev/null +++ b/doc/ssg/state.html @@ -0,0 +1,255 @@ + + + + + A Simple Scene Graph API for OpenGL. + + + +

class ssgState - OpenGL state representation.

+Each leaf node will have some kind of ssgState node associated +with it that contains all relevent OpenGL state information. +

+There can (in principal) be a number of different ways to represent +OpenGL state - but all must be derived from an ssgState: +

+
+  class ssgState : public ssgBase
+  {
+    int  getExternalPropertyIndex () ;
+    void setExternalPropertyIndex ( int i ) ;
+
+    ssgStateCallback getStateCallback ( int cb_type ) ;
+    void setStateCallback ( int cb_type, ssgStateCallback cb ) ;
+
+    virtual void force () ;
+    virtual void apply () ;
+  } ;
+
+
+

Callbacks.

+States are 'applied' immediately before the geometry they are attached +to is rendered. Applying the state causes all of it's properties to +be set up in OpenGL. +

+Each state has three optional callback function hooks. The application +program can have a function called before the state is applied, after +it is applied (but before the geometry is drawn) and another after the +geometry is rendered - immediately before the next state is applied. +

+You can set those three callbacks with setStateCallback - passing +either SSG_CALLBACK_PREAPPLY, SSG_CALLBACK_PREDRAW or SSG_CALLBACK_POSTDRAW +as the first parameter and the address of your function as the second. +

External Properties.

+Each state entity can have an external property - which is a simple +integer that can be set using ssgState::setExternalPropertyIndex(i) +or queried using ssgState::getExternalPropertyIndex(). +External properties are of use to certain sorts of applications programs, +for example, a game might want to encode the set of OpenGL state information +that represents Lava as something that is hot and Ice as something that +is cold by encoding the temperature of the material in the External +property field. Most applications will probably use this field as an +index into a table of material properties inside the application itself. +

Applying a State.

+Whilst it's rare for an application to need to deal with an ssgState +once it has been defined, there may be occasions when the application +wishes to draw objects of it's own without using SSG's scene graph. +This often is the case with on-screeen symbology. +

+In such cases, it is important to bear in mind that SSG changes the +OpenGL state as little as possible - in order to save time. Hence, +when a leaf node has just been drawn with one set of state information, +and another leaf node is about to be drawn using another, SSG carefully +compares the two states to see how they differ and arranges to make +only the fewest possible OpenGL state change calls. If the application +goes in "behind SSG's back" and changes state then SSG will be confused. +

+There are two ways to achive this. One is to use SSG state classes to +change the state by calling ssgState::apply(). That call +will ensure that OpenGL's state matches the desired state using the +minimum of calls. However, if your application absolutely MUST make +it's own state calls then you should call ssgState::force() +to force all aspects of a specified state to be set in OpenGL so that +SSG can be certain about how things are set up. +

class ssgSimpleState - Simple State class.

+ssgSimpleState is currently the only concrete class derived from +ssgState. It has so far proved adequate for all state management. +
+  class ssgSimpleState : ssgState
+  {
+    void disable ( GLenum mode ) ;
+    void enable  ( GLenum mode ) ;
+    void set ( GLenum mode, int val ) { val ? enable(mode) : disable(mode) ; }
+  
+    void setTexture ( char *fname, int wrapu = TRUE, int wrapv = TRUE )
+    void setTexture ( ssgTexture *tex )
+    void setTexture ( GLuint tex )
+    void setColourMaterial ( GLenum which )
+    void setMaterial ( GLenum which, float r, float g, float b, float a = 1.0f )
+    void setMaterial   ( GLenum which, sgVec4 rgba )
+    void setShininess ( float sh )
+    void setShadeModel ( GLenum model )
+    void setAlphaClamp ( float clamp )
+  } ;
+
+These calls mostly correspond to similarly named OpenGL functions. +

Enable and Disable calls:

+ssgSimpleState:: disable ( mode ), +ssgSimpleState:: enable ( mode ) and +ssgSimpleState:: set ( mode, val ) provide +the same services as glEnable and glDisable ('set' is a convenience function +that is a 'disable' if 'val' is FALSE, 'enable' otherwise). The 'mode' +parameter uses tokens that are similarly named to those in OpenGL: +
+
+  SSG_GL_TEXTURE_EN
+  SSG_GL_CULL_FACE_EN
+  SSG_GL_COLOR_MATERIAL_EN
+  SSG_GL_BLEND_EN
+  SSG_GL_ALPHA_TEST_EN
+  SSG_GL_LIGHTING_EN
+ 
+
+

Texture states.

+There are three ways to attach a texture to an ssgSimpleState: +ssgSimpleState::setTexture ( fname, wrapu, wrapv ), +ssgSimpleState::setTexture ( ssgtexture ), and +ssgSimpleState::setTexture ( texture_handle ). +In the form that takes a filename, U-axis wrap and V-axis wrap flags, the +texture is loaded from a texture file on disk (see ssgTexture +below for details on how this is done). The map will be MIPmapped and set with +a texture environment that is GL_LINEAR_MIPMAP_LINEAR and GL_MODULATE. +

+If you need something fancier, then declare an 'ssgTexture' class and +pass that to the setTexture function. You can also load your own +texture and pass the OpenGL glBindTexture handle to setTexture. +

If you need the texture file name, first check that +isEnabled ( GL_TEXTURE_2D ) returns true, then you may call +getTextureFilename(). But you should still check the return value for NULL and for "". + +

Materials.

+These calls are all very similar to OpenGL calls - and take the same +parameters: +ssgSimpleState::setColourMaterial(which) +ssgSimpleState::setMaterial(which,r,g,b,a) +ssgSimpleState::setMaterial(which,rgba) +ssgSimpleState::setShininess(sh) +ssgSimpleState::setShadeModel(model) +ssgSimpleState::setAlphaClamp(clamp) +

class ssgTexture - Storing texture maps.

+An ssgTexture loads a texture map for you with the minimum possible +fuss - but offers less flexibility than if you did so yourself. +

+The ssgTexture constructor function +ssgTexture::ssgTexture( char *fname, +int wrapu = TRUE, int wrapv = TRUE ) does all the work, +presuming that you require GL_LINEAR_MIPMAP_LINEAR filtering and a +GL_MODULATE texture environment. +

+You can obtain the OpenGL glBindTexture handle for the texture +using ssgTexture::getHandle(). +

+When ssgTexture loads a map from disk, it uses the filename +extension to determine which image format the file is in. +

+Currently, only SGI format and uncompressed +8 or 24 bit BMP images are supported - but more +formats are planned for the future. Filenames ending with +'.rgb', '.rgba', '.int', '.inta', '.bw' are assumed to be +SGI formatted files, '.bmp' are in Microsoft's BMP format +and '.png' are in Portable Network Graphics format. +

+If for any reason ssgTexture cannot load the requested file, +it creates a 2x2 texel red and white chequerboard map to +enable the program to continue running. This is often very +useful for debugging and to enable program development to +continue when texture maps are not yet painted. +

class ssgStateSelector - Switchable State class.

+There are cases where you would like to be able to switch between a +number of different states for a given leaf node. +
+  class ssgStateSelector : ssgSimpleState
+  {
+    ssgStateSelector ( int nstates ) ;
+
+    void            selectStep ( unsigned int s ) ;
+    int             getSelectStep  (void) ;
+    ssgSimpleState *getCurrentStep (void) ;
+    void            setStep ( int i, ssgSimpleState *step ) ;
+    ssgSimpleState *getStep ( int i ) ;
+  } ;
+
+This class is used to switch between some number of ssgSimpleStates. +You could (for example) draw the ground for your game as either +grass or snow - depending on the season. Construct objects of this +class with the number of alternative representations you will require +as it's parameter, then create a number of ssgSimpleStates - passing +them to ssgStateSelector::setStep(). You can then select which +step you wish to render using ssgStateSelector::selectStep(). +

+ssgStateSelector::getSelectStep() returns the number of the currently +selected step. ssgStateSelector::getCurrentStep() returns a pointer to +the currently selected ssgSimpleState. ssgStateSelector::getStep() +returns a pointer to the i'th ssgSimpleState. +

+Since ssgStateSelector is derived from ssgSimpleState, +all the other ssgSimpleState calls work - and the effect is to +operate on the currently selected ssgSimpleState. +

+Example: +

+
+     ssgStateSelector *s = new ssgStateSelector ( 2 ) ;
+     ssgSimpleState *grass = new ssgSimpleState () ;
+     ssgSimpleState *snow  = new ssgSimpleState () ;
+
+     ...set up grass and snow states appropriately...
+
+     s -> setStep ( 0, grass ) ;
+     s -> setStep ( 1, snow  ) ;
+
+     leafnode1 -> setState ( s ) ;
+     leafnode2 -> setState ( s ) ;
+     leafnode3 -> setState ( s ) ;
+
+     ...choose grass or snow...
+
+     if ( ! winter )
+       s -> selectStep ( 0 ) ;
+     else
+       s -> selectStep ( 1 ) ;
+
+     ...render the scene...
+
+
+Notice that one selectStep call changes the material on all +leaf nodes that use that ssgStateSelector. + + + + + +
+ + + + + + +
<= previous =Return to SSG Index= next =>
+
+ + +
+Valid HTML 4.0! + +
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+
+ + + diff --git a/doc/ssgAux.png b/doc/ssgAux.png new file mode 100644 index 0000000..13d6d56 Binary files /dev/null and b/doc/ssgAux.png differ diff --git a/doc/ssgAux/index.html b/doc/ssgAux/index.html new file mode 100644 index 0000000..c6258ea --- /dev/null +++ b/doc/ssgAux/index.html @@ -0,0 +1,886 @@ + + + + + SSG Auxiliary Libraries. + + + + + + + + + + +
+

SSG Auxiliary Libraries.

+
+ by Steve Baker +
+

Introduction

+ + + + + +
+PLIB/ssgAux is a suite of auxiliary libraries that build +higher level classes on top of the basic SSG classes. +

+

+
+
+ssgAux screenshot +
+This image was created entirely from ssgAux primitives. +
+
+

+

Conventions

+ssgAux is installed and named with the same +conventions as the base PLIB libraries. +
+ie: +
+   /usr/include/plib/ssgAux.h
+   /usr/lib/libplibssgaux.a
+
+

+PLIB/ssgAux functions, classes and constants are all +named with an 'ssga' or 'SSGA' prefix. +
+eg: +

+   class ssgaShape ;
+   SSGA_TYPE_CUBE
+
+ +

ssgaShape

+This is an abstract base class for many of the more +complex classes in the ssgAux 'collection'. The idea +is that ssgaShape's are really ssgBranch nodes that create +their own child nodes - but they behave in such a way that +you are never concerned with the nodes they create beneath +themselves. +
+
+class ssgaShape : public ssgBranch
+{
+  ssgaShape (void) ;
+  ssgaShape ( int numtris ) ;
+ 
+  float *getCenter  () { return center     ; }
+  float *getSize    () { return size       ; }
+  int    getNumTris () { return ntriangles ; }
+ 
+  void setColour  ( sgVec4 c ) { sgCopyVec4 ( colour, c ) ; regenerate () ; }
+  void setCenter  ( sgVec3 c ) { sgCopyVec3 ( center, c ) ; regenerate () ; }
+  void setSize    ( sgVec3 s ) { sgCopyVec3 ( size  , s ) ; regenerate () ; }
+  void setSize    ( float  s ) { sgSetVec3  ( size,s,s,s) ; regenerate () ; }
+  void setNumTris ( int ntri ) { ntriangles = ntri ; regenerate () ; }
+ 
+  void setKidState    ( ssgState *s ) ;
+  void setKidCallback ( int cb_type, ssgCallback cb ) ;
+ 
+  virtual void regenerate () = 0 ;                                              
+}
+
+The constructor allows you to specify the approximate number of +triangles you'd like the shape to consume. For some shapes, this +will be ignored (eg the Cube has 12 triangles - no matter how many +you ask for) - for others, it's honored only approximately (eg the +Sphere can only generate certain specific numbers of triangles) - +and for others, it may be honored exactly. +

+You can also set the colour of all the polygons and the ssgState and +callbacks that are applied to all of the child nodes. +

+setCenter allows you to position the center point of the object in +3D space - and setSize lets you determine the overall dimensions of +the object (this too may also be approximate - the 'size' of a teapot +is hard to specify in any useful way). The version of 'setSize' that +takes an sgVec3 allow you to generate cuboids from cubes and sphereoids +from spheres...but not all shapes allow this. +

+The 'regenerate' call allows the complete child structure of the object +to be deleted and then recreated. This is occasionaly useful if (for +example) you have walked down into the child structures and modified +them - and you'd like the shape back into it's pristine conditions. + +

ssgaCube

+
+
+class ssgaCube : public ssgaShape
+{
+  ssgaCube (void) ;
+  ssgaCube ( int numtris ) ;
+  virtual void regenerate () ;
+} ;
+ 
+
+This is the simplest of ssgaShapes - it defines nothing new over +and above the standard ssgaShape. + +

ssgaPatch

+
 
+ 
+class ssgaPatch : public ssgaShape
+{
+  ssgaPatch (void) ;
+  ssgaPatch ( int numtris ) ;
+ 
+  void setControlPoint ( int s, int t, sgVec3 xyz, sgVec2 uv, sgVec4 rgba ) ;
+  void setControlPoint ( int s, int t,
+                         float x, float y, float z,
+                         float u, float v,
+                         float r, float g, float b, float a ) ;
+  void getControlPoint ( int s, int t, sgVec3 xyz, sgVec2 uv, sgVec4 rgba ) ;
+ 
+  virtual void regenerate () ;
+} ;
+ 
+
+This implements a basic spline patch - with a 4x4 grid of 'control points' +that define its shape. 'setContolPoint' allows you to set the spatial +position, the texture coordinate and the colour at any given (s,t) position. +(s and t each must be in the range 0..3). +

+It's necessary to call the 'regenerate' function whenever you have added +or changed one or more control points. + + +

ssgaTeapot

+
+ 
+class ssgaTeapot : public ssgaShape
+{
+  ssgaTeapot (void) ;
+  ssgaTeapot ( int numtris ) ;
+  virtual void regenerate () ;
+} ;
+ 
+
+This creates the 'classic' Martin Newell teapot model. + +

ssgaSphere

+
+  
+class ssgaSphere : public ssgaShape
+{
+  ssgaSphere (void) ;
+  ssgaSphere ( int numtris ) ;
+ 
+  void setLatLongStyle ( int ll ) ;
+  int  isLatLongStyle  () ;
+  virtual void regenerate () ;
+} ;
+
+
+There are two ways to generate a sphere model - one is to produce a +fairly uniform grid of triangles that are as nearly equilateral +as possible. The alternative is to generate more nearly right-triangles +in cylindrical strips that are stacked on top of each other with a +circular disk at top and bottom. +

+The function 'setLatLongStyle(ll)' allows you to choose which you want, +call regenerate after you change types! + +

ssgaCylinder

+
+ 
+class ssgaCylinder : public ssgaShape
+{
+  ssgaCylinder (void) ;
+  ssgaCylinder ( int numtris ) ;
+ 
+  void makeCapped ( int c ) ;
+  int  isCapped   () ;
+  virtual void regenerate () ;
+} ;                                                                             
+
+
+Cylinders also come in two forms - capped and uncapped. Once again, +if you change the capped versus uncapped status, call regenerate to +make the new version. + +

ssgaWaveSystem

+This class is for handling water waves. +It generates a large polygonal mesh which it distorts in +realtime to simulate water waves. +

+The simulation uses between one and sixteen "Wave Trains" - each +using a class: +

+
+class ssgaWaveTrain
+{
+  ssgaWaveTrain () ;
+ 
+  float getSpeed      () ;
+  float getLength     () ;
+  float getLambda     () ;
+  float getHeading    () ;
+  float getWaveHeight () ;
+
+  void  setSpeed      ( float s ) ;
+  void  setLength     ( float l ) ;
+  void  setLambda     ( float l ) ;
+  void  setHeading    ( float h ) ;
+  void  setWaveHeight ( float h ) ;
+} ;                                                                             
+
+
+So, you create a bunch of these trains (typically, two or three +is plenty to generate 'interesting' motion). +Each wave train has a direction in which the waves are travelling, +a speed, a wave length (which also affects the shape of the wave), +the height of the wave and a 'lambda' term (which controls how much +the tops of the waves bend over). +

+Next, generate the ssgaWaveSystem: +

+ 
+class ssgaWaveSystem : public ssgaShape
+{
+  ssgaWaveSystem ( int ntri ) ;
+ 
+  virtual void        regenerate  () ;
+ 
+  ssgaWSDepthCallback getDepthCallback () ;
+  void                setDepthCallback ( ssgaWSDepthCallback cb ) ;
+ 
+  ssgaWaveTrain *getWaveTrain ( int i ) ;
+  void           setWaveTrain ( int i, ssgaWaveTrain *t ) ;
+ 
+  float getWindSpeed   () ;
+  float getWindDirn    () ;
+  float getEdgeFlatten () ;
+  float getTexScaleU   () ;
+  float getTexScaleV   () ;
+ 
+  void  setWindSpeed   ( float speed      ) ;
+  void  setWindDirn    ( float dirn       ) ;
+  void  setEdgeFlatten ( float dist       ) ;
+  void  setTexScale    ( float u, float v ) ;
+ 
+  void updateAnimation ( float t ) ;
+} ;
+
+
+The appearance of waves varies greatly with the depth of the +water - and this simulation produces the correct effects. There +is an optional user-callback that can be used to feed water depth +values into the simulation. The wave system will likely call this +function many thousands of times per frame - so make sure your +depth function is very efficient. If you don't provide a depth +function then the water will be assumed to be infinitely deep. +

+You can determine the number of polygons used to render +the patch of waves, the size of the wave patch and the amount +of texture repetition. The 'EdgeFlatten' setting determines +to what distance from the edge of the patch the waves are +gradually flattened out. This is useful because it allows +you to keep all those expensive wave polygons close to the +camera - and feather them out over range so that they blend +gently into a larger flat ocean. +

+Designing waves by calling the ssgaWaveSystem API is quite +difficult. You are advised to use the wave designer program +in the PLIB examples package. This program lets you adjust +wave parameters until it looks how you'd like - then hit the +'Write C++ code' to write out a source code snippet that you +can cut and paste into your program. +

+There is a 'README' in the 'water' source directory that +explains how to use the program in a little more detail. +That's all the wave system documentation I have time to write +just now - sorry. + +

ssgaParticleSystem

+This is a very flexible implementation of particle systems - it's not +as efficient as you might want for thousands of particles - this is intended +for high flexibility and relatively fewer numbers of particles. + +

+All of that flexibility is evident in the complex constructor function: +

+
+  class ssgaParticleSystem : public ssgVtxArray
+  {
+    ssgaParticleSystem ( int max ,          /* Max Number of particles      */
+                         int init,          /* Number to launch initially   */
+                       float add ,          /* Max number to create per sec */
+                         int turn_to_face,  /* Turn to face camera?         */
+                       float size,          /* Size of particles            */
+                       float bsphere_rad,   /* Size of bounding sphere      */
+      ssgaParticleCreateFunc create,        /* Initial create fn.           */
+      ssgaParticleUpdateFunc update = NULL, /* Update function              */
+      ssgaParticleDeleteFunc del     = NULL /* Remove function              */
+                      ) ;
+
+    void  setSize ( float sz ) ;
+    float getSize () ;
+
+    update ( float dt ) ;
+
+    int getNumActiveParticles () ;
+  } ;
+
+
+There are three callback functions - with the following types: +
+ 
+  typedef void (* ssgaParticleCreateFunc) ( ssgaParticleSystem *ps,
+					    int index,
+					    ssgaParticle *p ) ;
+ 
+  typedef void (* ssgaParticleUpdateFunc) ( float deltaTime,
+					    ssgaParticleSystem *ps,
+					    int index,
+					    ssgaParticle *p ) ;
+ 
+  typedef void (* ssgaParticleDeleteFunc) ( ssgaParticleSystem *ps,
+					    int index,
+					    ssgaParticle *p ) ;
+
+
+There is also a public class for a single particle: +
+ 
+class ssgaParticle
+{
+public:
+ 
+  sgVec4 col ;
+  sgVec3 pos ;
+  sgVec3 vel ;
+  sgVec3 acc ;
+ 
+  float size ;
+  float time_to_live ;
+  void *userData ;
+ 
+  ssgaParticle () ;
+ 
+} ;                                                                             
+
+
+This is best explained with an example. +Here is an example of a fountain model: +
+
+  fountain = new ssgaParticleSystem ( 2000, /* Max Number of particles */
+                                         2, /* Number to launch initially */
+                                       200, /* Max number to create per sec */
+                                      TRUE, /* Turn to face? */
+                                       0.2, /* Size of particles */
+                                      20.0, /* Size of bounding sphere */
+                           fountain_create, /* Initial create fn. */
+                           fountain_update  /* Update function */ ) ;
+ 
+
+This creates a system that has the capability to draw 2000 particles +(each is a quadrilateral). Two particles are launched initially and 200 +more are added gradually every second. You can choose to have each particle +turn to face the camera - or to be oriented in the X/Z plane, mine are set to +turn-to-face. The particles are 0.2 OpenGL units across. +

+This fountain is a continuous effect - so the inital number of particles +to launch is small - and the 'per second' creation rate determines the +flow. If you wanted something more like an explosion, have a larger number +of initial particles and none launched per-second after that. +

+One messiness is that we don't know how big the fountain may become over +time - and it's VERY inefficient to recompute the bsphere every frame. Hence +you have to tell the class what the maximum bounding sphere of the fountain +is at the outset so we can field-of-view cull it - this could be a near +infinite radius (MAX_FLOAT say) if you truly don't know how big it could +get - but that's inefficient because all 2,000 particles must be sent to +OpenGL even if the fountain is 20 miles away behind the camera - so do your +best to come up with some kind of a reasonable guess. +

+fountain_create and fountain_update are user-defined callback functions, +we could also have defined a 'fountain_delete' function - but many applications +won't need this. +

    +
  • The 'create' callback is called every time the system needs to + create a new particle. +
  • The 'update' callback is called on every update cycle for every + particle that's in flight. +
  • The 'delete' callback is called when the system has decided + that a particle has 'died'. +
+You have to have a 'create' function - but the other two are optional. +

+These callbacks are passed the address of the particle system, the index +number and address of the particle that's being created/updated/deleted - +and (for the 'update' function only) - the amount of elapsed time since +this particle was last updated. +

+The callbacks can set, read or change any or all aspects of the particle... +it's colour, position, velocity, accelleration, size and 'time to live' +(in seconds). +There is also a user data pointer - so you can hang your own data onto +each individual particle. +

+The particle system automatically moves each particle according to the usual +laws of motion and decrements it's time-to-live - so in many cases, +you can just set the initial velocity, the force due to +gravity and a reasonable time to live - and let the particle system code +do the rest. +

+My 'fountain_create' function looks like this: +

+
+void fountain_create ( ssgaParticleSystem *, int, ssgaParticle *p )
+{
+  sgSetVec4 ( p -> col, 1, 1, 1, 1 ) ;  /* initially white */
+  sgSetVec3 ( p -> pos, 0, 0, 0 ) ;     /* start off on the ground */
+  sgSetVec3 ( p -> vel, (rand()%1000-500)/300.0f,
+                        (rand()%1000-500)/300.0f, 50.0f ) ;
+                                        /* Shoot up and out */
+  sgSetVec3 ( p -> acc, 0, 0, -9.8f ) ; /* Gravity */
+  p -> time_to_live = 5 ;               /* Droplets evaporate after 5 seconds */
+}
+
+
+It populates the particle with an initial colour, position, velocity and +accelleration and gives it a 'time to live' of five seconds. The velocity +is randomised a bit to make a nicer looking fountain. +

+You can do all sorts of fancy things to the colour, position, velocity and +accelleration in your 'update' function. +

+
+void fountain_update ( ssgaParticle *p )
+{
+  if ( p -> pos [ 2 ] < 0 )
+    p -> time_to_live = -1 ;
+ 
+  p -> col [ 2 ] = (p -> time_to_live > 2) ? 1 : (p -> time_to_live/2.0f) ;
+}
+
+
+...this one just erases particles that go below zero altitude (by +setting their time-to-live variable to -1) and makes them go a pretty +shade of yellow for the last two seconds before they die. +

+The 'delete' function is principally useful for freeing up any user-data +you allocated in the 'create' function or during 'update's. Don't +delete the particle though - the particle system recycles it to avoid +doing too much dynamic memory allocation. +

+All that remains is to call the ssgaParticleSystem::update function +every frame with a parameter that tells the system how much time has +elapsed since the last call. This allows you to easily speed up, slow +down or pause the particles (or even run them backwards if you want). +

+I call this every frame: +

+
+void updateFountain ()
+{
+  static ulClock ck ;
+
+  ck . update () ;
+ 
+  if ( fountain != NULL )
+    fountain -> update ( ck.getDeltaTime () ) ;
+}
+                                                                                
+
+This function could also check the number of particles currently in flight +and delete the fountain when there are none left - that might be useful +for an explosion or something where you'd want to save CPU time by not +running the explosion particle system when all the pieces have landed +and 'gone away'. +

+The size of each particle is the size field of the individual particle +MULTIPLIED by the number you pass into the size parameter of the +ssgaParticleSystem constructor (or set with setSize()). This allows you +to cheaply set the particle size for all the particles at once - or to +tweak the size of each one in turn. The number in the particle structure +defaults to 1.0 so you can ignore it and just set the size in the +particle system overall. +

+ssgaParticleSystem is derived from ssgVtxArray - so you can apply textures and +other state things using the usual ssgVtxArray::setState(ssgSimpleState*) +call. I applied a texture with a fuzzy alpha-blended circle. +

+While debugging this, I got a bug which caused a picture of Tux to be +applied instead of the droplet texture - it was absolutely hilarious +to see 2000 tiny penguins shooting up in a fountain and falling gently +to earth! + +

ssgaFire

+This class is actually a highly specialised particle system. +You have to construct it quite carefully in order to get a nice +looking fire: +
+
+  class ssgaFire : public ssgaParticleSystem
+  {
+    ssgaFire ( int num_tris,
+               float radius = 1.0f,
+               float height = 5.0f,
+               float speed  = 2.0f ) ;
+ 
+    virtual ~ssgaFire () ;
+ 
+    virtual void update ( float t ) ;
+ 
+    void setUpwardSpeed ( float spd )
+    void setHeight      ( float hgt )
+    void setRadius      ( float rad )
+    void setHotColour   ( sgVec4 col )
+  } ;
+
+
+In the constructor, you set the number of triangles you wish to +generate, the radius and height of the approximately cylindrical +fire and the speed at which the flames head up towards the sky. +

+The number of polygons you use tends to be rather critical - too +many and your fire will look too 'smooth' and will be mostly +white-hot. Too few and it'll look like a number of detached +reddish blobs floating upwards. For the default radius, between +100 and 200 triangles seems to look good - for a 10 meter patch +of fire, you may need as many as 2000 triangles to make it look +effective. All three parameters (speed, height and radius) can +be manipulated in realtime - but since the number of polygons +is fixed, there is a limit to the amount of realtime tweaking +you can do without making it look silly. +

+The 'setHotColour' function allows you to set the colour +of the hottest flames (at the base of the fire). Since many +layers of polygons add up to form the colour, you'll tend to +want to use a primary colour with about 10% of one or two of +the other primaries. The default colour is (1.0, 0.2, 0.1, 1.0) +which produces red flames with yellow and white in the hotter +regions. +

+ +

ssgaLensFlare

+When you view the sun (or some other very bright light source) through +the imperfect lens of a camera, you get a row of bright circles and +rings in a line from the light source, through the center of the lens. +This is called a 'lens flare' and it can be very effective in computer +graphics in depicting a light source that's brighter than the computer +screen can display. It almost makes you want to squint because of +the brightness. +

+The ssgaLensFlare object is a special kind of ssgaShape that can be +positioned beneath the same transform +as the source of the light - and it 'just works'. You don't need +to set any parameters - just add it into the SSG scene graph in the +right place. +

+eg: +

+
+   ssgTransform *myTransform ;
+   ssgBranch    *myLightSource ;
+
+   /* Set up myTransform and myLightsource */
+
+   ...
+
+   myTransform -> addKid ( myLightSource ) ;
+   myTransform -> addKid ( new ssgaLensFlare ) ;
+
+
+It contains a (hard-coded) 256x128 texture map which is compiled +into the code and shared between however many lens flares there +are in the scene. +

+ +

ssgaSky

+ + + + + +
+The ssgaSky class models a blended sky dome, with methods to add celestial +bodies, for example a haloed sun or a textured moon, and methods to add +clouds, stars and planets. +

+WARNING - Solaris C/C++ compilers (from Sun Microsystems Inc) have +some nasty '#define's for the word 'SUN' and 'sun'. If you are writing +portable software, you might want to pick an alternative word! PLIB uses 'Sol', +the formal astronomical name for the star that happens to be our sun. +

+The sky implements various time of day lighting effects, it plays well +with fog and visibility effects, and implements scudded cloud fly-through +effects. Additionally, you can wire in the output of the SimGear +SGEphemeris +class to accurately position all the objects in the sky. +

+This sky dome code was based on the SimGear +sky code, written by Curtis Olson, which is used in +FlightGear. +The code was moved into PLIB for easier access, STL was removed and 'flat +earth' methods added. The main reason the code was moved here was to allow +the PLIB community to add their own extensions (not relevant to FlightGear), +to build for example, 'un-realistic' sky domes, with green skies, purple +clouds or multiple suns. This has not yet fully been achieved, but hopefully +when someone finds the time or has the need, these features will be added. +

+
+ssgaSky screenshots +
+ssgaSky screenshots +
+
+
+class ssgaSky
+{
+public:
+
+  ssgaSky( void );
+  ~ssgaSky( void );
+
+  void build( double h_radius, double v_radius,
+	  int nplanets, sgdVec3 *planet_data,
+	  int nstars, sgdVec3 *star_data);
+
+  ssgaCelestialBody* addBody( const char *body_tex_path, const char *halo_tex_path, double size, double dist, bool sol = false );
+  ssgaCelestialBody* addBody( ssgSimpleState *orb_state, ssgSimpleState *halo_state, double size, double dist, bool sol = false );
+  ssgaCelestialBody* getBody(int i) { return bodies.get(i); }
+  int getBodyCount() { return bodies.getNum(); }
+
+  ssgaCloudLayer* addCloud( const char *cloud_tex_path, float span, float elevation, float thickness, float transition );
+  ssgaCloudLayer* addCloud( ssgSimpleState *cloud_state, float span, float elevation, float thickness, float transition );
+  ssgaCloudLayer* getCloud(int i) { return clouds.get(i); }
+  int getCloudCount() { return clouds.getNum(); }
+
+  bool repositionFlat( sgVec3 view_pos, double spin, double dt );
+  bool reposition( sgVec3 view_pos, sgVec3 zero_elev, sgVec3 view_up,
+                   double lon, double lat, double alt, double spin, double gst, double dt );
+
+  bool repaint( sgVec4 sky_color, sgVec4 fog_color, sgVec4 cloud_color, double sol_angle,
+	  int nplanets, sgdVec3 *planet_data,
+	  int nstars, sgdVec3 *star_data );
+
+  void modifyVisibility( float alt, float time_factor );
+
+  void preDraw();
+  void postDraw( float alt );
+
+  void enable();
+  void disable();
+
+  float getVisibility();
+  void setVisibility( float v );
+} ;
+
+

Building the sky

+Once you have created an instance of ssgaSky you must call the +build() method. The arguments you pass to the build() method +allow you to specify the size of your sky dome, a number of planets, +and a multitude of stars. For the planets and stars you pass in +an array of right ascensions, declinations, magnitudes, and the +distance from the view point. +

Celestial Bodies

+Celestial bodies (eg. sun, moon or even mars if you like) can be +added or modified individually. To add a body use the addBody() +method. The arguments allow you to specify the body texture, the +halo texture, the size of the body, the body distance (usually the +sky dome size) and a boolean flag to indicate if the body should +be used as a reference to 'spin' the dome based on the bodies rotation +for correct sunrise and sunset effects (nb. the sun reference is only used +by repositionFlat() so the user does not need to calculate the spin +parameter). There is an additional form of this method that allows +you to specify your own ssgSimpleState for drawing the body and halo +texture. +

+Body accessor methods are available to: +

    +
  • set body right ascension and declination +
  • get body position and color +
+note: body angle and rotation are calculated internally (by +ssgaSky::repositionFlat() only) for sunrise and sunset effects. +
+class ssgaCelestialBody
+{
+...
+  void getPosition ( sgCoord* p );
+
+  void setAngle ( double angle );
+  double getAngle ();
+
+  void setRotation ( double rotation );
+  double getRotation ();
+
+  void setRightAscension ( double ra );
+  double getRightAscension ();
+
+  void setDeclination ( double decl );
+  double getDeclination ();
+
+  void setDist ( double dist );
+  double getDist ();
+
+  float *getColor();
+} ;
+
+

Cloud Layers

+Cloud layers can be added or modified individually. To add a cloud +layer use the addCloud() method. The arguments allow you to specify +cloud texture, the size of the cloud object, base height above sea +level, layer thickness and a transition zone for entering/leaving +the cloud layer. There is an additional form of this method that +allows you to specify your own ssgSimpleState for drawing the cloud +layer texture. +

+Cloud accessor methods are available to: +

    +
  • enable/disable clouds +
  • set elevation above sea level +
  • set thickness and transition - used to simulate cloud 'puffs' +
  • set speed and direction - used to simulate cloud movement +
+
+class ssgaCloudLayer
+{
+...
+  void enable();
+  void disable();
+  bool isEnabled();
+
+  float getElevation ();
+  void  setElevation ( float elevation );
+
+  float getThickness ();
+  void  setThickness ( float thickness );
+
+  float getTransition ();
+  void  setTransition ( float transition );
+
+  float getSpeed ();
+  void  setSpeed ( float val );
+
+  float getDirection ();
+  void  setDirection ( float val );
+} ;
+
+

Repainting the Sky

+As the sun circles the globe, you can call the repaint() method to +re-color the sky objects to simulate sunrise and sunset effects, +visibility, and other lighting changes. The arguments allow you +to specify a base sky color (for the top of the dome), a fog color +(for the horizon), a cloud color (for blending clouds with the fog +color), the sun angle with the horizon (for sunrise/sunset effects), +and new star and planet data so that we can optionally change the +magnitude of these (for day/night transitions). +

Positioning Sky Objects

+As time progresses and as you move across the surface of the earth, +the apparent position of the objects and the various lighting effects +can change. At this point you may wish to call celestial body +setRightAscension() and setDeclination() methods to update the +position of your bodies (SimGear +SGEphemeris +can be used if you wish to place bodies correctly). +

+Once you have specified the positions of all the sky objects, you must +call the repositionFlat() or reposition() method to allow you to specify +your view position. +

+The repositionFlat() arguments allow you to specify view position for +a 'flat earth' model. A 'spin' angle can be specified for orienting +the sky with the sun position so sunset and sunrise effects look correct. +If you specified a body to be the sun reference on addBody() you do not +need to specify the 'spin' angle. You may specify the amount of elapsed +time since the sky was last updated (used to animate cloud movement). +

+The reposition() arguments allow you to specify your view position in +world Cartesian coordinates, the zero elevation position in world +Cartesian coordinates (your longitude, your latitude, sea level), +the 'up' vector in world Cartesian coordinates, current longitude, +latitude, and altitude. A 'spin' angle can be specified for +orienting the sky with the sun position so sunset and sunrise +effects look correct. You must specify GMT side real time. You may +specify the amount of elapsed time since the sky was last updated +(used to animate cloud movement). +

Rendering the Sky

+The sky is designed to be rendered in two stages. The first stage +renders the parts that form your back drop - the sky dome, the +stars, the planets and the celestial bodies. These should be +rendered before the rest of your scene by calling the preDraw() +method. The second stage renders the clouds which are likely to be +translucent and should be drawn after your scene has been rendered. +Use the postDraw() method to draw the second stage of the sky. +

+A typical application might do the following: +

+thesky->preDraw(); 
+ssgCullAndDraw ( myscene ) ; 
+thesky->postDraw( my_altitude ); 
+
+The current altitude in meters is passed to the postDraw() +method so the clouds layers can be rendered correctly from +most distant to closest. +

Visibility Effects

+Visibility and fog is important for correctly rendering the sky. +You can inform ssgaSky of the current visibility by calling +the setVisibility() method. +

+When transitioning through clouds, it is nice to pull in the +fog as you get close to the cloud layer to hide the fact that +the clouds are drawn as a flat polygon. As you get nearer to +the cloud layer it is also nice to temporarily pull in the +visibility to simulate the effects of flying in and out of +the puffy edge of the cloud. These effects can all be +accomplished by calling the modifyVisibility() method. The +arguments allow you to specify your current altitude +(which is then compared to the altitudes of the various +cloud layers). You can also specify a time factor which +should be the length in seconds since the last time you +called modifyVisibility(). The time_factor value allows the +puffy cloud effect to be calculated correctly. +

+The modifyVisibility() method alters the ssgaSky's internal +idea of visibility, so you should subsequently call +getVisibility() to get the actual modified visibility. +You should then make the appropriate glFog() calls to +setup fog properly for your scene. +

Accessor Methods

+Once an instance of ssgaSky has been successfully +initialized, there are a couple accessor methods you +can use such as getBodyCount() to return the number +of celestial bodies, getBody(i) to return body number +i, getCloudCount() to return the number +of cloud layers, getCloud(i) to return cloud +layer number i, getVisibility() to return the actual +visibility as modified by the sky/cloud model. +

+


+ + +
+Valid HTML 4.0! + +
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+
+ + + diff --git a/doc/ssgAux/snapshot.png b/doc/ssgAux/snapshot.png new file mode 100644 index 0000000..aebbc81 Binary files /dev/null and b/doc/ssgAux/snapshot.png differ diff --git a/doc/ssgAux/ssgaSky.png b/doc/ssgAux/ssgaSky.png new file mode 100644 index 0000000..2f334d1 Binary files /dev/null and b/doc/ssgAux/ssgaSky.png differ diff --git a/doc/torcs_logo.png b/doc/torcs_logo.png new file mode 100644 index 0000000..7f44a4a Binary files /dev/null and b/doc/torcs_logo.png differ diff --git a/doc/tux_aqfh.png b/doc/tux_aqfh.png new file mode 100644 index 0000000..4ddec9b Binary files /dev/null and b/doc/tux_aqfh.png differ diff --git a/doc/tuxfleet_logo.png b/doc/tuxfleet_logo.png new file mode 100644 index 0000000..f1ef56a Binary files /dev/null and b/doc/tuxfleet_logo.png differ diff --git a/doc/tuxkart_logo.png b/doc/tuxkart_logo.png new file mode 100644 index 0000000..c8d3a2c Binary files /dev/null and b/doc/tuxkart_logo.png differ diff --git a/doc/util/index.html b/doc/util/index.html new file mode 100644 index 0000000..1d33d3f --- /dev/null +++ b/doc/util/index.html @@ -0,0 +1,626 @@ + + + + + + + The Utility Library. + + + +

The PLIB general Utility Library.

+By Sebastian Ude +

Introduction

+The 'UL' utility library is primarily targeted towards hiding common +operating system functions behind a thin layer that makes them portable. +Additionally, it provides some helper classes or routines that were +usually written to support certain parts of the +PLIB library, but at some point we felt that +they could be useful for user applications as well. +

+UL is a part of PLIB. + +

Contents:

+ + +

Quick reference:

+ + + +

Classes:

+

Non-class functions:

+ +
+ + + + + + + +
+ +

Misc. routines

+ +

ulSleep

+

+  void ulSleep ( int seconds ) ;
+
+Now comes a typical example of what the UL library does. If you need to +'sleep' for, say, 3 seconds, then under Linux/UNIX, you'd need to call: +

+  sleep ( 3 ) ;
+
+But under MS-Windows, you have to say: +

+  Sleep ( 3000 ) ;
+
+In order to avoid writing non-portable code, you can instead call: +

+  ulSleep ( 3 ) ;
+
+...under either operating system. + +

+

ulMilliSecondSleep

+

+  void ulMilliSecondSleep ( int milliseconds ) ;
+
+Same as ulSleep, except that it sleeps (as you +may have guessed) a certain number of milliseconds instead of seconds. + +

File handling

+ +

ulFindFile

+

+  void ulFindFile ( char *filenameOutput, const char *path, const char * tfnameInput, const char *sAPOM ) ;
+
+Basically, this utility function adds tfnameInput to the path and puts this +into the buffer filenameOutput. +

+It handles special chars in path: +

    +
  • ";;" is replaced by ";" +
  • "$$" is replaced by "$" +
  • "$(APOM)" is replaced by sAPOM +
+If there are ";" in path, the path-variable is interpreted as several paths +"segments", delimited by ";". The first file found by this function is +returned. It looks from left to right. A segment may end in $(...). ulFindFile +will then look in in this path and recursively in all the sub-paths. +

+Some examples: +

+To load *.MDl-models, it is very nice to set the texture path to +"$(APOM);$(APOM)/texture;$(APOM)/../texture". This consists of three segments +and tells ulFindFile to look in the path of the model, in a subpath texture +and in a path texture "besides" the path of the model. Some *.mdl-models are +shipped in a directory which contains a "texture"-directory, a +"Model"-directory and others. In this case you find the texture in +"$(APOM)/../texture". +

+Another example: You have all your textures in a directory-structure under +/roomplan: +

+textures --+-- Wallpapers
+           |
+		   +-- Wood --+-- Oak
+           |          |
+		   |          +-- pine
+           ...
+
+Then you should simply use the following texture path: +"/roomplan/$(...)" + +

+

ulFileExists

+

+  bool ulFileExists ( const char *fileName ) ;
+
+Returns "true" if a file with the name 'fileName' exists, or "false" if +it does not. + +

+

ulIsAbsolutePathName

+

+  int ulIsAbsolutePathName ( const char *pathname ) ;
+
+Returns '1' if 'pathname' is an absolute pathname or '0' if it is an +relative one. + +

+

ulGetCWD

+

+  char * ulGetCWD ( char *result, int maxlength ) ;
+
+Stores the current working directory in 'result', which has enough space +for 'maxlength' characters, including the trailing '\0'. On success, +'result' is returned. + +

+

ulMakePath

+

+  char * ulMakePath ( char *path, const char *dir, const char *fname ) ;
+
+Concatenates the strings 'dir' and 'fname', puts the system's slash character +inbetween and stores stores the result in 'path'. Be sure that the buffer +'path' is large enough to store 'strlen ( dir ) + strlen ( fname ) + 2' +(slash and trailing '\0') characters. + +

Directory handling

+ +

struct ulDir

+This structure provides a portable way to read directories. To allocate and +initialize a new ulDir structure, call: +

+  ulDir * ulOpenDir ( const char* dirname ) ;
+
+This function returns a pointer to a newly allocated ulDir structure on +success or a NULL pointer if the specified directory could not be read. +

+After you have constructed an ulDir structure, the directory content can +be read with subsequent calls to: +


+  struct ulDirEnt
+  {
+    char d_name [ UL_NAME_MAX+1 ] ;
+    bool d_isdir ;
+  } ;
+  ulDirEnt * ulReadDir ( ulDir *dir ) ;
+
+This function returns a pointer to a ulDirEnt structure which resides in +the corresponding ulDir structure and which has the above form. The "d_isdir" +flag indicates if a directory entry is another directory. If the end of the +directory has been reached, the function returns NULL. +

+To free an ulDir object and to close the associated directory stream, +please call: +


+  void ulCloseDir ( ulDir *dir ) ;
+
+ +

Data storage

+ +

class ulList

+

+  ulList::ulList ( int init_max = 1 ) ;
+
+This class stores a list of generic (void*) pointers using an +automatically-growing array. Since the process of resizing the internal +array is rather expensive, it is important that one picks a reasonable default +array size (init_max) when constructing an ulList object if performance +matters. Remember that a too large size means that some memory is wasted (but +memory is cheap nowadays), while a too small one means that expensive array +resize operations will be necessary later. +

+If you have absolutely no clue about how many entities will be stored, +you should probably look at the linked list class +below, which has it's own disadvantages, though. +

+Once you have constructed an ulList (hopefully with a good initial size), +you can insert an element using one of the following methods: +


+  void ulList::addEntity ( void *entity ) ;
+  void ulList::addBefore ( int n, void *entity ) ;
+
+While the first one simply adds the new entity to the tail of the list, +the second one lets you specify an exact position (0 is the first element). +Note that due to it's array implementation, inserting an entity at the head +or the middle of the ulList requires that the following entities are all +shifted one array slot to the right, which can be a rather expensive +operation. +

+These functions automatically check whether there is room for one more element +and double the internal array's size if necessary. However, as said +previously, resizing the array is a rather expensive process, so it is not +recommended that you rely too much on this behavior. Instead, pick a good +initial array size. +

+Note that ulList allows you to have multiple entities with the same data +value in the list. Please also note that ulList does not make it's own copy +of the data pointed to by 'entity'. It is up to you to take care of that the +memory region that 'entity' points to holds something useful as long as the +ulList exists. Be especially careful with addresses of variables that have a +limited lifetime. +

+To retrieve an entity, call: +


+  void * ulList::getEntity ( unsigned int n ) ;
+
+Where 'n' is the position of the entity in the list. If 'n' is not a valid +index, NULL is returned. Once you have called this function, you can use +subsequent calls to +

+  void * ulList::getNextEntity ( void ) ;
+
+in order to retrieve the following entities in the list. If there are no more +entities, this function will return NULL. +

+To remove an entity, call one of: +


+  void ulList::removeEntity ( unsigned int n ) ;
+  void ulList::removeEntity ( void *entity ) ;
+
+Where the second function removes the first entity with the specified +data value in case there are multiple ones. +

+To replace the value of an entity, call one of: +


+  void ulList::replaceEntity ( unsigned int n, void *new_entity ) ;
+  void ulList::replaceEntity ( void *old_entity, void *new_entity ) ;
+
+Where the second function will replace the value of the first entity +with the specified old data value in case there are multiple ones. +

+And finally, you can retrieve the number of entities stored in the list +(that's not necessarily the internal array's size), remove all +entities or retrieve the position of an entity by specifying it's data +value: +


+  void ulList::getNumEntities ( void ) const ;
+  void ulList::removeAllEntities () ;
+  int  ulList::searchForEntity ( void *entity ) const ;
+
+Where the latter returns a negative value if no entity with the specified +value was found in the list, and otherwise the position of the first +entity with the specified data value. + +

+

class ulLinkedList

+

+  ulLinkedList::ulLinkedList () ;
+
+The ulLinkedList class stores generic (void*) pointers using a linked list +of nodes where each node maintains a pointer to the next node. +

+This technique has some advantages compared to an array implementation of a +list like ulList. +

    +
  • +No wasted memory. When storing data using arrays (as +ulList does), it is a common practice to choose an array +size that seems "large enough". Most of the time the number of entities stored +will be smaller than the available array slots, so some memory space is wasted. +With a linked list, we allocate single nodes. No memory is wasted (except a +few bytes for each node's pointer to the next node). + +
  • +Resizing an array is an expensive operation, since usually the whole array +content has to be copied from the old to the new memory location. We do not +have this problem with linked lists. + +
  • +In contrast to arrays, it is a cheap operation to insert or remove entities +to / from the head or middle of a linked list. While with an array, the +following entities must all be shifted one slot to the left or right, we +simply need to (re)connect a few pointers with a linked list. +
+There are some disadvantages, though: +
    +
  • +In contrast to an array, there is no cheap way to locate the n-th entity in a +linked list. With an array, you simply have to add the desired position +multiplied with the size of an element to the array's base address and +look at the content of the memory at this location - a very simple operation. +With a linked list, however, we need to iterate over all nodes 'n' times, +so locating the 1000th node is a rather expensive operation. + +
  • +One may argue that insertion operations are more expensive with linked lists +than with arrays, since we allocate single nodes from the heap in contrast +to an array, where the whole list is one huge allocated block of memory. +Although allocation from the heap is indeed rather expensive, this is not +true when it comes to insertions to the middle of a list, these are usually +way more expensive with arrays. Furthermore, a list implemented using +an array such as ulList may make resizes of the array +necessary on insertions, which are again rather expensive. +
+Decide yourself if a list implemented as an array such as +ulList or a linked list implementation like this one fits +your needs better. +

+Once you have constructed a ulLinkedList object, you can insert a node using +one of: +


+  void ulLinkedList::appendNode ( void *data ) ;
+  void ulLinkedList::prependNode ( void *data ) ;
+  void ulLinkedList::insertNode ( void *data, int pos ) ;
+
+While "appendNode" adds the new node at the tail of the list, "prependNode" +will place the new node at the head of the list, and "insertNode" allows +you to specify the desired position ('0' is the first node) yourself; 'pos' +must be either '0' or a number between '0' and the number of nodes minus one. +"prependNode" is equal to calling "insertNode" with pos == 0. +

+Note that ulLinkedList allows you to have two nodes with the same data in +the list. Also note that just as ulList, ulLinkedList +does not make it's own copy of the memory pointed to by 'data', so make sure +that the corresponding memory location holds something useful as long as the +list exists. +

+To retrieve the number of nodes in the list, call: +


+  int ulLinkedList::getNumNodes ( void ) const ;
+
+

+To retrieve the data of the node at a certain position in the list, call: +


+  void * ulLinkedList::getNodeData ( int pos ) const ;
+
+Where 'pos' must be a number between '0' and the number of nodes minus one, +again. +

+If you need to retrieve the position of a node in the list by specifying it's +data value, call: +


+  int ulLinkedList::getNodePosition ( void *data ) const ;
+
+If there is more than one node whose data value is 'data' in the list, this +function will return the position of the first one. If there is no +node with the specified data value in the list, this function will return a +negative number to indicate failure. +

+Checking if the return value of "getNodePosition" is non-negative is also +the recommended way to determine whether there exists at least one node with +a certain data value in a list. +

+To remove a node from the list, call one of: +


+  bool ulLinkedList::removeNode ( void *data ) ;
+  void * ulLinkedList::removeNode ( int pos ) ;
+
+Where the first function returns 'true' if the node was sucessfully removed or +'false' if it could not find a node whose value is 'data'. In case there is +more than one node whose data value is 'data', it will remove the first +one. With the second function, 'pos' has to be a number between '0' and the +number of nodes minus one. It's return value is the removed node's data +value. +

+To iterate over the list (starting from the head) and to have a custom +function being called for each node's data pointer, call: +


+  typedef bool (*ulIterateFunc)( void *data, void *user_data ) ;
+  void * ulLinkedList::forEach ( ulIterateFunc fn, void *user_data = NULL ) const ;
+
+The iteration process will stop if your ulIterateFunc returns 'false', in +which case "forEach" returns the data value of the node at which the iteration +stopped, or if the tail of the list has been reached, in which case "forEach" +returns NULL. The user_data pointer will be passed to your ulIterateFunc as +the second argument. +

+ulLinkedList allows you to maintain a sorted list as an option. To set up +a sorted list, simply be sure to insert all nodes using the sorted insertion +function as soon as there is at least one node in the list. It's prototype is: +


+  typedef int (*ulCompareFunc)( const void *data1, const void *data2 ) ;
+  int ulList::insertSorted ( void *data, ulCompareFunc comparefn ) ;
+
+Where 'comparefn' is your custom comparison function that takes two +data pointers, compares them and returns a memcmp / strcmp-like result: +
    +
  • +A number less than zero if "data1" is "smaller" than "data2", that +means if "data1" had to be inserted before "data2" in the list. + +
  • +A number equal to zero if "data1" is equal to "data2", that means if +"data" had to be inserted immediately before or after "data2" in the list. + +
  • +A number greater than zero if "data1" is "greater" than "data2", +that means if "data" had to be inserted after "data2" in the list. +
+The return value of "insertSorted" is the position of the new node in the list +on success, or a negative value if you tried to do a sorted insertion on a +non-sorted list, that is a list which contains more than one node of which +at least one was not inserted using the sorted insertion function. In the +latter case, the new node would not have been inserted to the list. +

+To determine whether a list is sorted or not, call the following function: +


+  bool ulLinkedList::isSorted ( void ) const ;
+
+Note that with a linked list, you must not modify the criteria of a +node's data that is used for sorting without removing the node from the list +and re-inserting it. +

+Finally, you can empty a list (remove all nodes) by calling: +


+  typedef bool (*ulIterateFunc)( const void *data ) ;
+  void ulList::empty ( ulIterateFunc destroyfn = NULL, void *user_data = NULL ) ;
+
+Where "destroyfn" is an optionally specified function that will be called +with each destroyed node's data pointer as the first and with user_data as +the second argument. This is for example useful if the list entries are +pointers to dynamically allocated objects that have to be freed on destruction +of the list. The return value of the specified function is ignored. + +

+

ulHashTable

+Not yet. + +

Error handling

+ +

ulSetErrorCallback

+

+  typedef void (*ulErrorCallback) ( enum ulSeverity severity, char* msg ) ;
+  void ulSetErrorCallback ( ulErrorCallback cb ) ;
+
+PLIB has an internal error handling system +that the subsystems use to report debug, warning or error messages. +An application can set up an error callback that PLIB will call whenever such +a message occurs in addition to printing the message on the user's terminal. +

+ulSeverety indicates the importance of an message and is currently defined +the following way: +


+  enum ulSeverity
+  {
+    UL_DEBUG,
+    UL_WARNING,
+    UL_FATAL
+  } ;
+
+Where +
    +
  • UL_DEBUG are unimportant debug messages that can usually safely be ignored +
  • UL_WARNING are important warning messages that should not be ignored +
  • UL_FATAL are fatal errors that PLIB can not recover from +
+ +

+

ulGetErrorCallback

+

+  typedef void (*ulErrorCallback) ( enum ulSeverity severity, char* msg ) ;
+  ulErrorCallback ulGetErrorCallback ( void ) ;
+
+Returns the current error callback (if +any, else NULL is returned). + +

+

ulGetError

+

+  char * ulGetError ( void ) ;
+
+Returns a pointer to the error buffer, that is, the last error message or an +empty string if there were not any error messages or if the error buffer has +just been cleared. + +

+

ulClearError

+

+  void ulClearError ( void ) ;
+
+Clears the error buffer. + +

Misc. classes

+ +

class ulDynamicLibrary

+

+  ulDynamicLibrary::ulDynamicLibrary ( const char *libname ) ;
+
+This class provides a portable way to load a dynamic library and to retrieve +the memory address of a specific function afterwards. When constructing an +ulDynamicLibrary object, you have to specify the name of the dynamic library +you want to operate on without the platform-specific file extension +for dynamic libraries. +

+Afterwards, you can retrieve the memory address where a function / symbol of +the library has been loaded by calling: +


+  void * ulDynamicLibrary::getFuncAddress ( const char *funcname ) :
+
+This function returns NULL if the specified symbol was not found. + +

+

ulClock

+

+  ulClock::ulClock () ;
+
+No further documentation yet. + +

ulPropertySet

+Not yet. + +

String handling

+ +

ulStrEqual

+

+  int ulStrEqual ( const char *s1, const char *s2 ) ;
+
+This function provides a portable way to compare two strings while ignoring +the case of the characters. We need it since half of the machines on the +planet provide strcasecmp and the other half stricmp for this purpose. +

+In contrast to the libc string comparison routines, this routine returns '1' +if the strings are equal and '0' if they are not. + +

+

ulStrNEqual

+

+  int ulStrNEqual ( const char *s1, const char *s2, int len ) ;
+
+Same as ulStrEqual, except that it only compares the first 'len' characters +of the strings. + +

+

Endian handling

+

+  bool ulIsLittleEndian ( void ) ;
+  bool ulIsBigEndian ( void ) ;
+
+  unsigned short ulEndianLittle16 ( unsigned short x ) ;
+  unsigned int ulEndianLittle32 ( unsigned int x ) ;
+  float ulEndianLittleFloat ( float x ) ;
+
+  unsigned short ulEndianBig16 ( unsigned short x ) ;
+  unsigned int ulEndianBig32 ( unsigned int x ) ;
+  float ulEndianBigFloat ( float x ) ;
+
+  void ulEndianLittleArray16 ( unsigned short *x, int length ) ;
+  void ulEndianLittleArray32 ( unsigned int *x, int length ) ;
+  void ulEndianLittleArrayFloat ( float *x, int length ) ;
+
+  void ulEndianBigArray16 ( unsigned short *x, int length ) ;
+  void ulEndianBigArray32 ( unsigned int *x, int length ) ;
+  void ulEndianBigArrayFloat ( float *x, int length ) ;
+
+  unsigned short ulEndianReadLittle16 ( FILE *f ) ;
+  unsigned int ulEndianReadLittle32 ( FILE *f ) ;
+  float ulEndianReadLittleFloat ( FILE *f ) ;
+
+  unsigned short ulEndianReadBig16 ( FILE *f ) ;
+  unsigned int ulEndianReadBig32 ( FILE *f ) ;
+  float ulEndianReadBigFloat ( FILE *f ) ;
+
+  size_t ulEndianWriteLittle16 ( FILE *f, unsigned short x ) ;
+  size_t ulEndianWriteLittle32 ( FILE *f, unsigned int x ) ;
+  size_t ulEndianWriteLittleFloat ( FILE *f, float x ) ;
+
+  size_t ulEndianWriteBig16 ( FILE *f, unsigned short x ) ;
+  size_t ulEndianWriteBig32 ( FILE *f, unsigned int x ) ;
+  size_t ulEndianWriteBigFloat ( FILE *f, float x ) ;
+
+No further documentation yet. + +
+ + +
+Valid HTML 4.0! + +
+Sebastian Ude <ude@handshake.de> +
+
+ + + diff --git a/doc/valid-html40.png b/doc/valid-html40.png new file mode 100644 index 0000000..a6cf106 Binary files /dev/null and b/doc/valid-html40.png differ diff --git a/doc/whats_inside.html b/doc/whats_inside.html new file mode 100644 index 0000000..ccba9d1 --- /dev/null +++ b/doc/whats_inside.html @@ -0,0 +1,196 @@ + + + + + PLIB: What's In PLIB + + + + + + + + + +
+PLIB Logo +
+
+
+

+ STEVE'S + PORTABLE + GAME + LIBRARY. +

+
+
+
    +And Lo, the Lion and the Sheep shall lie down together - but the Sheep won't +get much Sleep. +
    +-- Woody Allen +
+
+ +Sourceforge Logo +
+
+ + + + + + +
+HOME
+WHAT'S INSIDE
+LICENSE
+CONTACTS
+REQUIREMENTS
+GALLERY
+DOWNLOAD & INSTALL
+EXAMPLES
+ +SG +SSG
+ +SSGAUX +FNT
+ +PUI +PSL + +UL +JS
+ +NET +SL
+ +PW +PUAUX
+ + +
+

What's Inside PLIB?

+PLIB is comprised of a number of semi-autonomous libraries +that you can pretty much mix and match - using as much or +as little PLIB as you need. The components libraries are: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Picoscopic User Interface Library (PUI)A fully portable set of GUI widgets that need OpenGL and C++ + to operate. Useful for games because rendering these widgets is + performed very quickly by your 3D hardware.
Sound Library (SL)A fully portable Audio driver suited to C++, GLUT + and realtime applications that need low latency. Includes + a simple 'MOD' music loader/player.
Standard Geometry Library(SG)A set of matrix and vector math functions that was + specifically written to simplify the writing of efficient OpenGL + programs. You need to include this code into any SSG applications. + Widely used within PLIB itself. +
Simple Scene Graph Library (SSG)A scene graph library layered on top of OpenGL. Also contains code to load and save lots of 3D file formats.
PUI Auxiliary Library (PUAUX)Additional functionality layered onto PUI - not every PUI program + will need these but they can perhaps save you some effort.
SSG Auxiliary Library (SSGA)Additional functionality layered onto SSG - not every SSG program + will need these but they can perhaps save you some effort.
Joystick wrappers (JS)Supports more Joysticks with more axes and buttons than GLUT.
Fonts'n'Text Library (FNT)Supports text output in OpenGL using texture mapped fonts. + These are much faster to render than GLUT's fonts.
Utility Library (UL)A simple portability library to hide basic operating system + incompatibilities. Widely used within PLIB itself.
Pegasus Network Library (NET)Pegasus is a C++ library for assist you in adding + networking to your games.
PLIB Scripting Language (PSL)A very lightweight, stackless C-like scripting language.
PLIB Windowing Library (PW)A lightweight windowing library. This is a very basic + library - it only supports a single, double-buffered RGB + OpenGL window - with support for keyboard and mouse. + Simple though it is, it's usually plenty for OpenGL games + and other simple OpenGL applications.
+

+

Goodies: Samples and Demo's

+There are quite a few example programs that each show off +one aspect of PLIB's use. We also distribute a set of demonstration +programs. These tend to be more complete and usable applications - some +games, some tools. These also show off PLIB's features - but in a +more holistic way than the example programs. + +

Documentation.

+All documentation is available online (click on the package name +in the section above) and distributed with PLIB in HTML. +

+There are some interdependencies between the PLIB components - all +need the common utility library - many need the standard geometry +library for matix operations: + + + + + +
+
    +
  • PW is independent +
  • UL is independent +
  • JS depends only on UL +
  • SL depends only on UL +
  • SG depends only on UL +
  • NET depends only on UL +
+
+
    +
  • FNT depends on UL and SG +
  • SSG depends on UL and SG +
  • SSGAUX depends on UL, SG and SSG +
  • PUI depends on UL, SG and FNT +
  • PUAUX depends on UL, SG, FNT and PUI +
  • PSL depends on UL, SG and SSG +
+
+ +

+
+
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+ + diff --git a/doc/whats_inside.png b/doc/whats_inside.png new file mode 100644 index 0000000..17002c5 Binary files /dev/null and b/doc/whats_inside.png differ diff --git a/examples/AUTHORS b/examples/AUTHORS new file mode 100644 index 0000000..fa63a8a --- /dev/null +++ b/examples/AUTHORS @@ -0,0 +1,62 @@ +PLIB was originally written by Steve Baker as a solo project - but +has subsequently been greatly enhanced and expanded by a 'cast of +thousands'. + +Most important of all - the 'official' PLIB developers: + + Alex Perry + Curtis Olson + Ben Woodhead + Dave McClurg + Gerard Decatrel + Gil Carter + Giancarlo Niccolai + James Jones + John Fay ("Mr. PUI") + Juergen Marquardt + Mark Vallevand + Marten Stromberg + Nathan Matias + Norman Vine + Per Liedman + Sam Stickland + Sebastian Ude + Steve Baker <--- Hmmm - must sort this list by SECOND name! + Will Lachance + Wolfram Kuss + +Apologies to anyone I've left out - please let me know +who you are and I'll add you in. + + Christopher St.John + Christian Mayer + Darrell Walisser + Dave Heil + Erik Hofman + Kevin Thompson + Karl Kremer + Negative0 <---- Who? Some kind of 1's complement arithmetic fanatic? + Mark Danks + Michael Kurth + Sean Palmer + Simon Britnell + Themie Gouthas + Tony Knienieder + Trent Gamblin + +Special mention must go to: + + Daryll Strauss (GLIDE port to Linux) + David Bucciarelli (Mesa -> GLIDE interface) + Brian Paul (Mesa) + Curtis Olson (FlightGear guru and all-round "Mr Nice Guy", + who nagged me into writing most of this stuff!) + Vasily Lewis (Tireless maintainer and sysadmin at Woodsoup + where PLIB was first hosted) + Toru Egashira (Who wrote a program called 'NSPmod' which was + the original basis of the SL 'MOD' player - + although the original code has been almost + entirely rewritten in the process of merging + it with SL. + Everyone at OPENGL-GAMEDEV-L + diff --git a/examples/COPYING b/examples/COPYING new file mode 100644 index 0000000..eeb586b --- /dev/null +++ b/examples/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/examples/COPYING.DATA b/examples/COPYING.DATA new file mode 100644 index 0000000..0473e4d --- /dev/null +++ b/examples/COPYING.DATA @@ -0,0 +1,5 @@ +All fonts, textures, models and other data is licensed under the same +license as the code unless otherwise stated. + +Please see COPYING for more details. + diff --git a/examples/ChangeLog b/examples/ChangeLog new file mode 100644 index 0000000..041368b --- /dev/null +++ b/examples/ChangeLog @@ -0,0 +1,34 @@ + +PLIB_Examples Change Log. +========================= + +PLIB_Examples v1.8.0 (March 19th 2004) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Added examples for PW, PSL, ssgAux and puAux. + + +PLIB_Examples v1.6.1 (Sept 4th 2002) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Added missing files from the 'water/data' directory. + +PLIB_Examples v1.4.1 (June 25th 2001) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + * Changes are now reported in main 'PLIB' CHANGES + file. + +PLIB_Examples v1.1.8 (Jan 23rd 2000) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Updated examples and documents to + match latest PLIB main code. + +PLIB_Examples v1.1.2 (Nov 8th 1999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Example programs split from main + PLIB distribution. + * Example programs are now under GPL + rather than LGPL. Previous releases + of these programs that were released + under LGPL may still be used under + those terms. + diff --git a/examples/INSTALL b/examples/INSTALL new file mode 100644 index 0000000..05782eb --- /dev/null +++ b/examples/INSTALL @@ -0,0 +1,203 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Configure Options +================= +On some occations opengl are not found on systems. Additional +commandline parameters have been added to resolve this issue. + +--with-gl GL prefix + +Examples +./configure --with-gl=/usr/local + +This should help with locating GL when configure is unable to find +the files. + + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Compiling for Windows with MSVC +=============================== + +You can easily compile plib with MSVC 6. First compile plib +itself. Then open the included workspace in MSVC, choose what you +want to compile (build/set active configuration) and then compile (F7). + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 0000000..edaab67 --- /dev/null +++ b/examples/Makefile.am @@ -0,0 +1,16 @@ +SUBDIRS = src + +EXTRA_DIST = README COPYING.DATA plib_examples.dsp plib_examples.dsw install-sh missing autogen.sh + +dist-hook: + tar cf - doc \ + src/ssg/tux/data \ + src/ssg/water/data \ + src/ssg/sky/data \ + src/ssg/majik/data \ + src/ssg/shrubs/data \ + src/psl/data \ + src/fnt/data \ + data \ + | ( cd $(distdir) ; tar xf - ) + diff --git a/examples/NEWS b/examples/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/examples/README b/examples/README new file mode 100644 index 0000000..bf3dce0 --- /dev/null +++ b/examples/README @@ -0,0 +1,23 @@ + +PLIB Examples and Documents +=========================== + by Steve Baker. + +LICENSING: + +These example programs are offered as OpenSource freeware +under the provisions of the GNU Public +License (GPL). Those terms and conditions are +detailed in the file 'COPYING' in this directory. + +REQUIREMENTS: + +In addition to the PLIB libraries that I provide, you +will also need OpenGL (OpenGL 1.1 or later - +Mesa 3.0 or later) and GLUT (The OpenGL utilities +toolkit - version 3.7 or later) and a hardware 3D +graphics accellerator that supports OpenGL. + + by Steve Baker. + + http://www.sjbaker.org diff --git a/examples/autogen.sh b/examples/autogen.sh new file mode 100755 index 0000000..02a1eb9 --- /dev/null +++ b/examples/autogen.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +OSTYPE=`uname -s` + +AMFLAGS="--add-missing" +if test "$OSTYPE" = "IRIX" -o "$OSTYPE" = "IRIX64"; then + AMFLAGS=$AMFLAGS" --include-deps"; +fi + +echo "Running aclocal" +aclocal +echo "Running automake" +automake $AMFLAGS +echo "Running autoconf" +autoconf + +echo "======================================" +echo "Now you are ready to run './configure'" +echo "======================================" diff --git a/examples/configure.in b/examples/configure.in new file mode 100644 index 0000000..30de1bb --- /dev/null +++ b/examples/configure.in @@ -0,0 +1,313 @@ +dnl Process this file with autoconf to produce a configure script. + +AC_INIT(src/js/js_demo.cxx) +AM_INIT_AUTOMAKE(plib_examples, 1.8.5) + + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_CPP +AC_PROG_CXX +AC_PROG_CXXCPP +AC_PROG_INSTALL + +AC_LANG_CPLUSPLUS + + +dnl Command line arguments. + +dnl Don't use AC_HELP_STRING here as old versions of autoconf do not +dnl understand it. +AC_ARG_WITH(GL, +[ --with-GL=DIR set the prefix directory where GL resides], +GL_PREFIX=$withval, GL_PREFIX=auto) + + +AC_ARG_ENABLE(fnt, +[ --enable-fnt build FNT examples default: yes],, +enable_fnt=yes) + +AC_ARG_ENABLE(js, +[ --enable-js build JS examples default: yes],, +enable_js=yes) + +AC_ARG_ENABLE(pw, +[ --enable-pw build PW examples default: yes],, +enable_pw=yes) + +AC_ARG_ENABLE(net, +[ --enable-net build NET examples default: yes],, +enable_net=yes) + +AC_ARG_ENABLE(pui, +[ --enable-pui build PUI examples default: yes],, +enable_pui=yes) + +AC_ARG_ENABLE(sg, +[ --enable-sg build SG examples default: yes],, +enable_sg=yes) + +AC_ARG_ENABLE(psl, +[ --enable-psl build PSL examples default: yes],, +enable_psl=yes) + +AC_ARG_ENABLE(sl, +[ --enable-sl build SL examples default: yes],, +enable_sl=yes) + +AC_ARG_ENABLE(ssg, +[ --enable-ssg build SSG/ssgAux examples default: yes],, +enable_ssg=yes) + +AC_ARG_ENABLE(ul, +[ --enable-ul build UTIL examples default: yes],, +enable_ul=yes) + + +if test "x$enable_fnt" = "xyes"; then need_opengl=yes; fi +if test "x$enable_pui" = "xyes"; then need_opengl=yes; fi +if test "x$enable_sg" = "xyes"; then need_opengl=yes; fi +if test "x$enable_ssg" = "xyes"; then need_opengl=yes; fi +if test "x$enable_ssgaux" = "xyes"; then need_opengl=yes; fi + +AM_CONDITIONAL(BUILD_FNT, test "x$enable_fnt" = "xyes") +AM_CONDITIONAL(BUILD_JS, test "x$enable_js" = "xyes") +AM_CONDITIONAL(BUILD_PW, test "x$enable_pw" = "xyes") +AM_CONDITIONAL(BUILD_NET, test "x$enable_net" = "xyes") +AM_CONDITIONAL(BUILD_PUI, test "x$enable_pui" = "xyes") +AM_CONDITIONAL(BUILD_SG, test "x$enable_sg" = "xyes") +AM_CONDITIONAL(BUILD_PSL, test "x$enable_psl" = "xyes") +AM_CONDITIONAL(BUILD_SL, test "x$enable_sl" = "xyes") +AM_CONDITIONAL(BUILD_SSG, test "x$enable_ssg" = "xyes") +AM_CONDITIONAL(BUILD_UL, test "x$enable_ul" = "xyes") + +if test "x$need_opengl" = "xyes" && test "x$GL_PREFIX" != "xauto"; then + LDFLAGS="$LDFLAGS -L$GL_PREFIX/lib" + CPPFLAGS="$CPPFLAGS -I$GL_PREFIX/include" +fi + + +dnl Checks for library functions. +dnl check for OpenGL related libraries + +AC_CANONICAL_HOST + +case "${host}" in +*-*-cygwin*) + + dnl CygWin under Windoze. + + dnl Sound / joystick stuff, mmtimer (ulClock !) + LIBS="$LIBS -lwinmm" + + dnl OpenGL libraries + OGL_LIBS="-lglu32 -lopengl32 -lgdi32" + GLUT_LIBS="-lglut32" + ;; +*-*-mingw32*) + dnl Mingw under Windoze. + + dnl Sound / joystick stuff, mmtimer (ulClock !) + LIBS="$LIBS -lwinmm -lwsock32" + + + dnl OpenGL libraries + OGL_LIBS="-lglu32 -lopengl32 -lgdi32" + GLUT_LIBS="-lglut32" + ;; +*-apple-darwin*) + dnl Mac OS X + + dnl OpenGL libraries + OGL_LIBS="-framework OpenGL" + GLUT_LIBS="-framework GLUT -lobjc" + + dnl Sound libraries + SND_LIBS="-framework Carbon" + ;; +*) + if test "x$need_opengl" = "xyes"; then + dnl Check for X11 + + AC_PATH_XTRA + + LDFLAGS="$LDFLAGS $X_LIBS" + + OGL_LIBS="$X_PRE_LIBS -lXi -lXmu -lXext -lX11 $X_EXTRA_LIBS -lm" + +dnl ========================================================= +dnl if test "x$x_includes" != "x"; then +dnl CPPFLAGS="$CPPFLAGS -I$x_includes" +dnl fi +dnl ========================================================= + + dnl Reasonable stuff non-windoze variants ... :-) + + AC_CHECK_LIB(pthread, pthread_create) + + AC_CHECK_LIB(GL, glNewList, OGL_LIBS="-lGL $OGL_LIBS",,$OGL_LIBS) + if test "x$ac_cv_lib_GL_glNewList" = "xno" ; then + dnl if no GL, check for MesaGL + AC_CHECK_LIB(MesaGL, glNewList, OGL_LIBS="-lMesaGL $OGL_LIBS", + AC_MSG_ERROR([could not find working GL library]), + $OGL_LIBS) + fi + + AC_CHECK_LIB(GLU, gluLookAt, OGL_LIBS="-lGLU $OGL_LIBS",,$OGL_LIBS) + if test "x$ac_cv_lib_GLU_gluLookAt" = "xno" ; then + dnl if no GLU, check for MesaGLU + AC_CHECK_LIB(MesaGLU, gluLookAt, + OGL_LIBS="-lMesaGLU $OGL_LIBS", + AC_MSG_ERROR([could not find working GLU library]), + $OGL_LIBS) + fi + + dnl check for glut...or freeglut + + AC_CHECK_LIB(freeglut, glutGetModifiers, GLUT_LIBS="-lfreeglut",, + $OGL_LIBS) + if test "x$ac_cv_lib_freeglut_glutGetModifiers" = "xno" ; then + dnl if no freeglut, check for real GLUT + AC_CHECK_LIB(glut, glutGetModifiers, GLUT_LIBS="-lglut", + AC_MSG_ERROR([could not find working GLUT library]), + $OGL_LIBS) + fi + fi + + AC_CHECK_LIB(dl, dlclose) + + dnl Check SGI audio library + AC_CHECK_LIB(audio, ALopenport, SND_LIBS="-laudio") + ;; +esac + +dnl Check PLIB library +AC_CHECK_LIB(plibul, ulInit, true, +AC_MSG_ERROR([there seems to be a problem with the PLIB libraries])) + + +AC_SUBST(OGL_LIBS) +AC_SUBST(GLUT_LIBS) +AC_SUBST(SND_LIBS) + + +dnl Checks for header files. + +AC_HEADER_STDC + +AC_CHECK_HEADER(windows.h, AC_DEFINE(WIN32)) + +if test "x$need_opengl" = "xyes"; then + dnl Check for OpenGl header files + + case "${host}" in + *-*-cygwin* | *-*-mingw32*) + dnl CygWin under Windoze. + + AC_CHECK_HEADERS(GL/gl.h GL/glu.h,, + AC_MSG_ERROR([OpenGL header files not found])) + + AC_CHECK_HEADER(GL/glut.h, AC_DEFINE(GLUT_IS_PRESENT), + AC_MSG_ERROR([GLUT header file not found])) + ;; + *-apple-darwin*) + dnl Mac OS X + + AC_CHECK_HEADERS(OpenGL/gl.h OpenGL/glu.h,, + AC_MSG_ERROR([OpenGL header files not found])) + + AC_CHECK_HEADER(GLUT/glut.h, AC_DEFINE(GLUT_IS_PRESENT), + AC_MSG_ERROR([GLUT header file not found])) + ;; + *) + AC_CHECK_HEADERS(GL/gl.h GL/glu.h,, + AC_MSG_ERROR([OpenGL header files not found])) + + if test "x$ac_cv_lib_freeglut_glutGetModifiers" = "xyes"; then + AC_CHECK_HEADER(GL/freeglut.h, AC_DEFINE(FREEGLUT_IS_PRESENT), + AC_MSG_ERROR([freeglut header file not found])) + else + AC_CHECK_HEADER(GL/glut.h, AC_DEFINE(GLUT_IS_PRESENT), + AC_MSG_ERROR([GLUT header file not found])) + fi + ;; + esac +fi + +AC_CHECK_HEADER(plib/ul.h,, AC_MSG_ERROR([PLIB header files not found])) + + +dnl Warning flags +WFLAG="-Wall" +case "$host" in +mips-sgi-irix*) + if test "x$CXX" = "xCC"; then + WFLAG="-fullwarn"; + fi + ;; +*) + if test "x$CXX" = "xicpc" || test "x$CXX" = "xicc"; then + WFLAG="-w1" + fi + ;; +esac + +CFLAGS="$CFLAGS $WFLAG" +CXXFLAGS="$CXXFLAGS $WFLAG" + + +AC_OUTPUT( \ + Makefile \ + src/Makefile \ + src/js/Makefile \ + src/pw/Makefile \ + src/pui/Makefile \ + src/sg/Makefile \ + src/sl/Makefile \ + src/ssg/Makefile \ + src/ssg/tux/Makefile \ + src/ssg/majik/Makefile \ + src/ssg/load_save/Makefile \ + src/ssg/state_test/Makefile \ + src/ssg/tween_test/Makefile \ + src/ssg/viewer/Makefile \ + src/ssg/water/Makefile \ + src/ssg/sky/Makefile \ + src/ssg/dynamics/Makefile \ + src/ssg/shrubs/Makefile \ + src/ssg/shapes/Makefile \ + src/fnt/Makefile \ + src/net/Makefile \ + src/net/client_server/Makefile \ + src/net/http_get/Makefile \ + src/net/net_echo/Makefile \ + src/psl/Makefile \ + src/util/Makefile ) + +if test "x$need_opengl" = "xyes"; then + if test "x$ac_cv_lib_freeglut_glutGetModifiers" = "xyes"; then + glut_msg="yes (found freeglut)" + else + glut_msg="yes (found GLUT)" + fi +else + glut_msg="no" +fi + +AC_MSG_RESULT( +[PLIB configuration information: + + Building FNT examples: $enable_fnt + Building JS examples: $enable_js + Building PW examples: $enable_pw + Building NET examples: $enable_net + Building PUI examples: $enable_pui + Building SG examples: $enable_sg + Building PSL examples: $enable_psl + Building SL examples: $enable_sl + Building SSG/ssgAux examples: $enable_ssg + Building UTIL examples: $enable_ul + + Need GLUT: $glut_msg +]) + diff --git a/examples/plib_examples.dsp b/examples/plib_examples.dsp new file mode 100644 index 0000000..f6c5c9f --- /dev/null +++ b/examples/plib_examples.dsp @@ -0,0 +1,61 @@ +# Microsoft Developer Studio Project File - Name="plib_examples" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Generic Project" 0x010a + +CFG=plib_examples - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "plib_examples.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "plib_examples.mak" CFG="plib_examples - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "plib_examples - Win32 Release" (based on "Win32 (x86) Generic Project") +!MESSAGE "plib_examples - Win32 Debug" (based on "Win32 (x86) Generic Project") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +MTL=midl.exe + +!IF "$(CFG)" == "plib_examples - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "plib_examples - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "plib_examples___Win32_Debug" +# PROP BASE Intermediate_Dir "plib_examples___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "plib_examples - Win32 Release" +# Name "plib_examples - Win32 Debug" +# End Target +# End Project diff --git a/examples/plib_examples.dsw b/examples/plib_examples.dsw new file mode 100644 index 0000000..ee61f00 --- /dev/null +++ b/examples/plib_examples.dsw @@ -0,0 +1,491 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "PointPicker"=.\src\pui\PointPicker.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "WavingFlag"=.\src\ssg\tux\WavingFlag.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "complex"=.\src\pui\complex.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "dynamics"=.\src\ssg\dynamics\dynamics.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "example"=.\src\sl\example.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "fnt_test"=.\src\fnt\fnt_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "http_get"=.\src\net\http_get\http_get.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "js_demo"=.\src\js\js_demo.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "load"=.\src\ssg\load_save\load.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "majik_demo"=.\src\ssg\majik\majik_demo.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "mod_demo"=.\src\sl\mod_demo.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "net_echo"=.\src\net\net_echo\net_echo.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "net_udp_client"=.\src\net\client_server\net_udp_client.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "net_udp_server"=.\src\net\client_server\net_udp_server.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "plib_examples"=.\plib_examples.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name complex + End Project Dependency + Begin Project Dependency + Project_Dep_Name example + End Project Dependency + Begin Project Dependency + Project_Dep_Name fnt_test + End Project Dependency + Begin Project Dependency + Project_Dep_Name http_get + End Project Dependency + Begin Project Dependency + Project_Dep_Name js_demo + End Project Dependency + Begin Project Dependency + Project_Dep_Name load + End Project Dependency + Begin Project Dependency + Project_Dep_Name majik_demo + End Project Dependency + Begin Project Dependency + Project_Dep_Name mod_demo + End Project Dependency + Begin Project Dependency + Project_Dep_Name net_echo + End Project Dependency + Begin Project Dependency + Project_Dep_Name net_udp_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name net_udp_server + End Project Dependency + Begin Project Dependency + Project_Dep_Name save + End Project Dependency + Begin Project Dependency + Project_Dep_Name sg_quat_test + End Project Dependency + Begin Project Dependency + Project_Dep_Name simple + End Project Dependency + Begin Project Dependency + Project_Dep_Name slideshow + End Project Dependency + Begin Project Dependency + Project_Dep_Name tux_example + End Project Dependency + Begin Project Dependency + Project_Dep_Name viewer + End Project Dependency + Begin Project Dependency + Project_Dep_Name net_http_get + End Project Dependency + Begin Project Dependency + Project_Dep_Name PointPicker + End Project Dependency + Begin Project Dependency + Project_Dep_Name test_dir + End Project Dependency + Begin Project Dependency + Project_Dep_Name tween_test + End Project Dependency + Begin Project Dependency + Project_Dep_Name WavingFlag + End Project Dependency + Begin Project Dependency + Project_Dep_Name widget_list + End Project Dependency + Begin Project Dependency + Project_Dep_Name water + End Project Dependency + Begin Project Dependency + Project_Dep_Name dynamics + End Project Dependency + Begin Project Dependency + Project_Dep_Name psl_demo + End Project Dependency + Begin Project Dependency + Project_Dep_Name pw_demo + End Project Dependency + Begin Project Dependency + Project_Dep_Name pw_pui + End Project Dependency + Begin Project Dependency + Project_Dep_Name sky + End Project Dependency + Begin Project Dependency + Project_Dep_Name stest + End Project Dependency +}}} + +############################################################################### + +Project: "psl_demo"=.\src\psl\psl_demo.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "pview"=.\src\ssg\viewer\pview.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "pw_demo"=.\src\pw\pw_demo.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "pw_pui"=.\src\pw\pw_pui.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "save"=.\src\ssg\load_save\save.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "sg_quat_test"=.\src\sg\sg_quat_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "simple"=.\src\pui\simple.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "sky"=.\src\ssg\sky\sky.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "slideshow"=.\src\fnt\slideshow.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "stest"=.\src\ssg\state_test\stest.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "test_dir"=.\src\util\test_dir.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "tux_example"=.\src\ssg\tux\tux_example.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "tween_test"=.\src\ssg\tween_test\tween_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "viewer"=.\src\ssg\viewer\viewer.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "water"=.\src\ssg\water\water.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "widget_list"=.\src\pui\widget_list.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "widget_test"=.\src\pui\widget_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/examples/src/Makefile.am b/examples/src/Makefile.am new file mode 100644 index 0000000..b5ad0ed --- /dev/null +++ b/examples/src/Makefile.am @@ -0,0 +1,3 @@ + +SUBDIRS = js pui sl sg ssg fnt net util psl pw + diff --git a/examples/src/fnt/Makefile.am b/examples/src/fnt/Makefile.am new file mode 100644 index 0000000..ac132ce --- /dev/null +++ b/examples/src/fnt/Makefile.am @@ -0,0 +1,18 @@ +if BUILD_FNT + +noinst_PROGRAMS = fnt_test slideshow hello_world + +hello_world_SOURCES = hello_world.cxx + +fnt_test_SOURCES = fnt_test.cxx + +slideshow_SOURCES = slideshow.cxx + +hello_world_LDADD = -lplibpw -lplibfnt -lplibsg -lplibul $(OGL_LIBS) +fnt_test_LDADD = -lplibfnt -lplibsg -lplibul $(GLUT_LIBS) $(OGL_LIBS) +slideshow_LDADD = -lplibfnt -lplibsg -lplibul $(GLUT_LIBS) $(OGL_LIBS) + +endif + +EXTRA_DIST = fnt_test.dsp slideshow.dsp + diff --git a/examples/src/fnt/data/AvantGarde-Book.txf b/examples/src/fnt/data/AvantGarde-Book.txf new file mode 100644 index 0000000..fe1318e Binary files /dev/null and b/examples/src/fnt/data/AvantGarde-Book.txf differ diff --git a/examples/src/fnt/data/AvantGarde-BookOblique.txf b/examples/src/fnt/data/AvantGarde-BookOblique.txf new file mode 100644 index 0000000..c0ce949 Binary files /dev/null and b/examples/src/fnt/data/AvantGarde-BookOblique.txf differ diff --git a/examples/src/fnt/data/AvantGarde-Demi.txf b/examples/src/fnt/data/AvantGarde-Demi.txf new file mode 100644 index 0000000..52c697a Binary files /dev/null and b/examples/src/fnt/data/AvantGarde-Demi.txf differ diff --git a/examples/src/fnt/data/AvantGarde-DemiOblique.txf b/examples/src/fnt/data/AvantGarde-DemiOblique.txf new file mode 100644 index 0000000..c5a54f8 Binary files /dev/null and b/examples/src/fnt/data/AvantGarde-DemiOblique.txf differ diff --git a/examples/src/fnt/data/Bookman-Demi.txf b/examples/src/fnt/data/Bookman-Demi.txf new file mode 100644 index 0000000..aabe051 Binary files /dev/null and b/examples/src/fnt/data/Bookman-Demi.txf differ diff --git a/examples/src/fnt/data/Bookman-DemiItalic.txf b/examples/src/fnt/data/Bookman-DemiItalic.txf new file mode 100644 index 0000000..d2f8de5 Binary files /dev/null and b/examples/src/fnt/data/Bookman-DemiItalic.txf differ diff --git a/examples/src/fnt/data/Bookman-Light.txf b/examples/src/fnt/data/Bookman-Light.txf new file mode 100644 index 0000000..481585f Binary files /dev/null and b/examples/src/fnt/data/Bookman-Light.txf differ diff --git a/examples/src/fnt/data/Bookman-LightItalic.txf b/examples/src/fnt/data/Bookman-LightItalic.txf new file mode 100644 index 0000000..b2cbc76 Binary files /dev/null and b/examples/src/fnt/data/Bookman-LightItalic.txf differ diff --git a/examples/src/fnt/data/Courier-Bold.txf b/examples/src/fnt/data/Courier-Bold.txf new file mode 100644 index 0000000..13b0205 Binary files /dev/null and b/examples/src/fnt/data/Courier-Bold.txf differ diff --git a/examples/src/fnt/data/Courier-BoldOblique.txf b/examples/src/fnt/data/Courier-BoldOblique.txf new file mode 100644 index 0000000..cb250f5 Binary files /dev/null and b/examples/src/fnt/data/Courier-BoldOblique.txf differ diff --git a/examples/src/fnt/data/Courier-Oblique.txf b/examples/src/fnt/data/Courier-Oblique.txf new file mode 100644 index 0000000..7dfd2dc Binary files /dev/null and b/examples/src/fnt/data/Courier-Oblique.txf differ diff --git a/examples/src/fnt/data/Courier.txf b/examples/src/fnt/data/Courier.txf new file mode 100644 index 0000000..dc51395 Binary files /dev/null and b/examples/src/fnt/data/Courier.txf differ diff --git a/examples/src/fnt/data/Helvetica-Bold.txf b/examples/src/fnt/data/Helvetica-Bold.txf new file mode 100644 index 0000000..a435ea6 Binary files /dev/null and b/examples/src/fnt/data/Helvetica-Bold.txf differ diff --git a/examples/src/fnt/data/Helvetica-BoldOblique.txf b/examples/src/fnt/data/Helvetica-BoldOblique.txf new file mode 100644 index 0000000..fea9ca7 Binary files /dev/null and b/examples/src/fnt/data/Helvetica-BoldOblique.txf differ diff --git a/examples/src/fnt/data/Helvetica-Oblique.txf b/examples/src/fnt/data/Helvetica-Oblique.txf new file mode 100644 index 0000000..8b4fba2 Binary files /dev/null and b/examples/src/fnt/data/Helvetica-Oblique.txf differ diff --git a/examples/src/fnt/data/Helvetica.txf b/examples/src/fnt/data/Helvetica.txf new file mode 100644 index 0000000..4ac9638 Binary files /dev/null and b/examples/src/fnt/data/Helvetica.txf differ diff --git a/examples/src/fnt/data/NewCenturySchlbk-Bold.txf b/examples/src/fnt/data/NewCenturySchlbk-Bold.txf new file mode 100644 index 0000000..cb06095 Binary files /dev/null and b/examples/src/fnt/data/NewCenturySchlbk-Bold.txf differ diff --git a/examples/src/fnt/data/NewCenturySchlbk-BoldItalic.txf b/examples/src/fnt/data/NewCenturySchlbk-BoldItalic.txf new file mode 100644 index 0000000..733845f Binary files /dev/null and b/examples/src/fnt/data/NewCenturySchlbk-BoldItalic.txf differ diff --git a/examples/src/fnt/data/NewCenturySchlbk-Italic.txf b/examples/src/fnt/data/NewCenturySchlbk-Italic.txf new file mode 100644 index 0000000..e6366a3 Binary files /dev/null and b/examples/src/fnt/data/NewCenturySchlbk-Italic.txf differ diff --git a/examples/src/fnt/data/NewCenturySchlbk-Roman.txf b/examples/src/fnt/data/NewCenturySchlbk-Roman.txf new file mode 100644 index 0000000..7781ea9 Binary files /dev/null and b/examples/src/fnt/data/NewCenturySchlbk-Roman.txf differ diff --git a/examples/src/fnt/data/Palatino-Bold.txf b/examples/src/fnt/data/Palatino-Bold.txf new file mode 100644 index 0000000..1261c5d Binary files /dev/null and b/examples/src/fnt/data/Palatino-Bold.txf differ diff --git a/examples/src/fnt/data/Palatino-BoldItalic.txf b/examples/src/fnt/data/Palatino-BoldItalic.txf new file mode 100644 index 0000000..a27c45f Binary files /dev/null and b/examples/src/fnt/data/Palatino-BoldItalic.txf differ diff --git a/examples/src/fnt/data/Palatino-Italic.txf b/examples/src/fnt/data/Palatino-Italic.txf new file mode 100644 index 0000000..a9609ac Binary files /dev/null and b/examples/src/fnt/data/Palatino-Italic.txf differ diff --git a/examples/src/fnt/data/Palatino-Roman.txf b/examples/src/fnt/data/Palatino-Roman.txf new file mode 100644 index 0000000..98335df Binary files /dev/null and b/examples/src/fnt/data/Palatino-Roman.txf differ diff --git a/examples/src/fnt/data/README b/examples/src/fnt/data/README new file mode 100644 index 0000000..55cdd8c --- /dev/null +++ b/examples/src/fnt/data/README @@ -0,0 +1,48 @@ + +These antialiased '.txf' fonts were generated by Andrew Ross from +Ghostscript fonts using his afm2txf script which can be found in the +'tools' area of PLIB. All Ghostscript fonts used were GPL and Copyright +(C) URW++ Design & Development Incorporated. + + +Things that make them better than existing fonts are (quoted from Andrew): + ++ They are complete. Each one has glyphs rendered for every printable + ASCII character. No more property confusion from different strings + rendering identically due to missing glyphs. This alone is enough + to make them worth the price of admission. :) + ++ They are rendered and antialiased from vector descriptions, instead + of being pixel-for-pixel copies of X11 screen fonts. So they look a + lot better under most conditions (at very small sizes the difference + is negligible as mipmapping does the antialiasing for you). + ++ They have more space around the glyphs. Mark Kilgard's 'gentexfont' + program packed the glyphs too tightly togther; at small sizes, you could + see "bleeding" in the textures from nearby characters. + ++ They make better use of space in general. The characters are drawn + as large as practical for simple layout code (i.e., I scale them up, + but don't do any gymnastics like recursive packing or non-rectangular + layout). So you get more font for your texture byte. Most of the + existing '.txf' fonts use only about half of the available texture + space. + ++ They are professional fonts. I don't know where "typewriter.txf" + came from, but it is awfully ugly. I replaced it with the antialiased + Helvetica (in FlightGear), and things look *so* much nicer. + + +Stuff that isn't ideal: + ++ They're stored as 8 bit gray scale images instead of bitmaps, which + means that the files are significantly larger. The texture memory + footprint is the same, however. + + +Note that you still find the inferior textured fonts that came with PLIB +before in the 'old' directory. + + +- Sebastian Ude, August 2002 + diff --git a/examples/src/fnt/data/Times-Bold.txf b/examples/src/fnt/data/Times-Bold.txf new file mode 100644 index 0000000..401560a Binary files /dev/null and b/examples/src/fnt/data/Times-Bold.txf differ diff --git a/examples/src/fnt/data/Times-BoldItalic.txf b/examples/src/fnt/data/Times-BoldItalic.txf new file mode 100644 index 0000000..9b76475 Binary files /dev/null and b/examples/src/fnt/data/Times-BoldItalic.txf differ diff --git a/examples/src/fnt/data/Times-Italic.txf b/examples/src/fnt/data/Times-Italic.txf new file mode 100644 index 0000000..78b8114 Binary files /dev/null and b/examples/src/fnt/data/Times-Italic.txf differ diff --git a/examples/src/fnt/data/Times-Roman.txf b/examples/src/fnt/data/Times-Roman.txf new file mode 100644 index 0000000..e459c74 Binary files /dev/null and b/examples/src/fnt/data/Times-Roman.txf differ diff --git a/examples/src/fnt/data/ZapfChancery-MediumItalic.txf b/examples/src/fnt/data/ZapfChancery-MediumItalic.txf new file mode 100644 index 0000000..bf364b1 Binary files /dev/null and b/examples/src/fnt/data/ZapfChancery-MediumItalic.txf differ diff --git a/examples/src/fnt/data/old/README b/examples/src/fnt/data/old/README new file mode 100644 index 0000000..71ab94d --- /dev/null +++ b/examples/src/fnt/data/old/README @@ -0,0 +1,34 @@ + +TXF Font Pack. +~~~~~~~~~~~~~~ + +Most of these fonts were created from the X-windows +fonts that are distributed with Xfree86. The +exceptions are Sorority, Curlfont, Default and +Haeberli which came from Mark Kilgards' "texfont" +distribution. + +I used Mark's program called 'gentexfont' to convert +X fonts into '.txf' format - which can be read into +the PLIB FNT component. + +Large bold-faced fonts seem to work best. There +is little point in converting the italic versions +of these fonts since FNT can do a reasonable job +of italicising them on-the-fly. + +Using large fonts gives them the best chance of +scaling them without undue aliasing either in +pixel or texel space. These fonts all fit pretty +well into 256x256 maps - using smaller maps would +require you to go for smaller font sizes - larger +maps would not fit into 3Dfx and similar hardware. + +Medium and fine fonts look pretty terrible when scaled, +I have omitted all the fine fonts and some of the +worst medium fonts from the set that come with Xfree86. + +You can preview these using the fnt_test program, +or use them from within other programs that use +Mark's TXF format. + diff --git a/examples/src/fnt/data/old/charter.txf b/examples/src/fnt/data/old/charter.txf new file mode 100644 index 0000000..d565321 Binary files /dev/null and b/examples/src/fnt/data/old/charter.txf differ diff --git a/examples/src/fnt/data/old/courier-bold.txf b/examples/src/fnt/data/old/courier-bold.txf new file mode 100644 index 0000000..3bdf0db Binary files /dev/null and b/examples/src/fnt/data/old/courier-bold.txf differ diff --git a/examples/src/fnt/data/old/courier_medium.txf b/examples/src/fnt/data/old/courier_medium.txf new file mode 100644 index 0000000..7fbbafd Binary files /dev/null and b/examples/src/fnt/data/old/courier_medium.txf differ diff --git a/examples/src/fnt/data/old/curlfont.txf b/examples/src/fnt/data/old/curlfont.txf new file mode 100644 index 0000000..6a84544 Binary files /dev/null and b/examples/src/fnt/data/old/curlfont.txf differ diff --git a/examples/src/fnt/data/old/default.txf b/examples/src/fnt/data/old/default.txf new file mode 100644 index 0000000..1b51f46 Binary files /dev/null and b/examples/src/fnt/data/old/default.txf differ diff --git a/examples/src/fnt/data/old/derniere.txf b/examples/src/fnt/data/old/derniere.txf new file mode 100644 index 0000000..385dbfa Binary files /dev/null and b/examples/src/fnt/data/old/derniere.txf differ diff --git a/examples/src/fnt/data/old/haeberli.txf b/examples/src/fnt/data/old/haeberli.txf new file mode 100644 index 0000000..22d7e52 Binary files /dev/null and b/examples/src/fnt/data/old/haeberli.txf differ diff --git a/examples/src/fnt/data/old/helvetica_bold.txf b/examples/src/fnt/data/old/helvetica_bold.txf new file mode 100644 index 0000000..83301d3 Binary files /dev/null and b/examples/src/fnt/data/old/helvetica_bold.txf differ diff --git a/examples/src/fnt/data/old/helvetica_medium.txf b/examples/src/fnt/data/old/helvetica_medium.txf new file mode 100644 index 0000000..d6f432c Binary files /dev/null and b/examples/src/fnt/data/old/helvetica_medium.txf differ diff --git a/examples/src/fnt/data/old/junius.txf b/examples/src/fnt/data/old/junius.txf new file mode 100644 index 0000000..ef346ef Binary files /dev/null and b/examples/src/fnt/data/old/junius.txf differ diff --git a/examples/src/fnt/data/old/ledfixed.txf b/examples/src/fnt/data/old/ledfixed.txf new file mode 100644 index 0000000..7951948 Binary files /dev/null and b/examples/src/fnt/data/old/ledfixed.txf differ diff --git a/examples/src/fnt/data/old/lucida.txf b/examples/src/fnt/data/old/lucida.txf new file mode 100644 index 0000000..1923cc8 Binary files /dev/null and b/examples/src/fnt/data/old/lucida.txf differ diff --git a/examples/src/fnt/data/old/lucidabright_bold.txf b/examples/src/fnt/data/old/lucidabright_bold.txf new file mode 100644 index 0000000..06fdb53 Binary files /dev/null and b/examples/src/fnt/data/old/lucidabright_bold.txf differ diff --git a/examples/src/fnt/data/old/schoolbook_bold.txf b/examples/src/fnt/data/old/schoolbook_bold.txf new file mode 100644 index 0000000..3491827 Binary files /dev/null and b/examples/src/fnt/data/old/schoolbook_bold.txf differ diff --git a/examples/src/fnt/data/old/schoolbook_medium.txf b/examples/src/fnt/data/old/schoolbook_medium.txf new file mode 100644 index 0000000..92802d2 Binary files /dev/null and b/examples/src/fnt/data/old/schoolbook_medium.txf differ diff --git a/examples/src/fnt/data/old/sorority.txf b/examples/src/fnt/data/old/sorority.txf new file mode 100644 index 0000000..8b457aa Binary files /dev/null and b/examples/src/fnt/data/old/sorority.txf differ diff --git a/examples/src/fnt/data/old/symbol.txf b/examples/src/fnt/data/old/symbol.txf new file mode 100644 index 0000000..a7d18df Binary files /dev/null and b/examples/src/fnt/data/old/symbol.txf differ diff --git a/examples/src/fnt/data/old/times_bold.txf b/examples/src/fnt/data/old/times_bold.txf new file mode 100644 index 0000000..1abc5fa Binary files /dev/null and b/examples/src/fnt/data/old/times_bold.txf differ diff --git a/examples/src/fnt/data/old/times_medium.txf b/examples/src/fnt/data/old/times_medium.txf new file mode 100644 index 0000000..1022289 Binary files /dev/null and b/examples/src/fnt/data/old/times_medium.txf differ diff --git a/examples/src/fnt/data/old/typewriter.txf b/examples/src/fnt/data/old/typewriter.txf new file mode 100644 index 0000000..a3abc09 Binary files /dev/null and b/examples/src/fnt/data/old/typewriter.txf differ diff --git a/examples/src/fnt/data/test_slideshow.txt b/examples/src/fnt/data/test_slideshow.txt new file mode 100644 index 0000000..00c79ee --- /dev/null +++ b/examples/src/fnt/data/test_slideshow.txt @@ -0,0 +1,36 @@ +1 +2 +3 Hello to the first page. +4 Advance by pressing "enter" +5 +* +6 This is the second page. +7 Go back with backspace. +8 +9 +* +10 It seems you pressed enter again instead of backspace ;) +11 +12 +13 +14 +15 +16 +17 This time some more lines +18 +19 +20 +* +The fourth page +* +The fifth page +* +The sixth page +* +The seventh page +************************************************| +* +* +* +* + diff --git a/examples/src/fnt/fnt_test.cxx b/examples/src/fnt/fnt_test.cxx new file mode 100644 index 0000000..7830f8a --- /dev/null +++ b/examples/src/fnt/fnt_test.cxx @@ -0,0 +1,282 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: fnt_test.cxx 2032 2005-07-05 15:43:18Z bram $ +*/ + + +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#include + +static fntRenderer *text ; + +static const char *font_names [] = +{ + "Helvetica.txf", /* This is the default */ + "Helvetica-Bold.txf", + "Helvetica-Oblique.txf", + "Helvetica-BoldOblique.txf", + + "AvantGarde-Book.txf", + "AvantGarde-BookOblique.txf", + "AvantGarde-Demi.txf", + "AvantGarde-DemiOblique.txf", + + "Bookman-Light.txf", + "Bookman-LightItalic.txf", + "Bookman-Demi.txf", + "Bookman-DemiItalic.txf", + + "Courier.txf", + "Courier-Bold.txf", + "Courier-Oblique.txf", + "Courier-BoldOblique.txf", + + "NewCenturySchlbk-Roman.txf", + "NewCenturySchlbk-Italic.txf", + "NewCenturySchlbk-Bold.txf", + "NewCenturySchlbk-BoldItalic.txf", + + "Palatino-Roman.txf", + "Palatino-Italic.txf", + "Palatino-Bold.txf", + "Palatino-BoldItalic.txf", + + "Times-Roman.txf", + "Times-Italic.txf", + "Times-Bold.txf", + "Times-BoldItalic.txf", + + "ZapfChancery-MediumItalic.txf", + + "old/sorority.txf", + "old/charter.txf", +/* "old/courier-bold.txf", + "old/courier_medium.txf", */ + "old/curlfont.txf", + "old/default.txf", + "old/derniere.txf", + "old/haeberli.txf", +/* "old/helvetica_bold.txf", + "old/helvetica_medium.txf", */ + "old/junius.txf", + "old/ledfixed.txf", + "old/lucida.txf", + "old/lucidabright_bold.txf", +/* "old/schoolbook_bold.txf", + "old/schoolbook_medium.txf", */ + "old/symbol.txf", +/* "old/times_bold.txf", + "old/times_medium.txf", + "old/typewriter.txf", */ + NULL +} ; + +static fntTexFont **font_list ; + +static int cur_font = 0 ; +static int max_font = 0 ; + +static void motionfn ( int, int ) +{ + glutPostRedisplay () ; +} + +static void keyfn ( unsigned char key, int, int ) +{ + cur_font++ ; + + if ( cur_font >= max_font ) + cur_font = 0 ; +} + +static void mousefn ( int /*button*/, int /*updown*/, int /*x*/, int /*y*/ ) +{ + exit ( 0 ) ; +} + +static int getWindowHeight () { return glutGet ( (GLenum) GLUT_WINDOW_HEIGHT ) ; } +static int getWindowWidth () { return glutGet ( (GLenum) GLUT_WINDOW_WIDTH ) ; } + +static void setOpenGLState ( void ) +{ + int w = getWindowWidth () ; + int h = getWindowHeight () ; + + glPushAttrib ( GL_ENABLE_BIT | GL_VIEWPORT_BIT | GL_TRANSFORM_BIT | GL_LIGHTING_BIT ) ; + glDisable ( GL_LIGHTING ) ; + glDisable ( GL_FOG ) ; + glDisable ( GL_TEXTURE_2D ) ; + glDisable ( GL_DEPTH_TEST ) ; + glDisable ( GL_CULL_FACE ) ; + glEnable ( GL_ALPHA_TEST ) ; + glEnable ( GL_BLEND ) ; + glAlphaFunc ( GL_GREATER, 0.1f ) ; + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; + + glViewport ( 0, 0, w, h ) ; + glMatrixMode ( GL_PROJECTION ) ; + glPushMatrix () ; + glLoadIdentity () ; + gluOrtho2D ( 0, w, 0, h ) ; + glMatrixMode ( GL_MODELVIEW ) ; + glPushMatrix () ; + glLoadIdentity () ; +} + +static void restoreOpenGLState ( void ) +{ + glMatrixMode ( GL_PROJECTION ) ; + glPopMatrix () ; + glMatrixMode ( GL_MODELVIEW ) ; + glPopMatrix () ; + glPopAttrib () ; +} + + + +static void displayfn (void) +{ + setOpenGLState () ; + glClearColor ( 0.1f, 0.4f, 0.1f, 1.0f ) ; + glClear ( GL_COLOR_BUFFER_BIT ) ; + + text -> setFont ( font_list [ 0 ] ) ; + text -> setPointSize ( 25.0f ) ; + + text -> begin () ; + glColor3f ( 1.0f, 1.0f, 0.0f ) ; + text -> start2f ( 50.0f, 400.0f ) ; + text -> puts ( "This is the PLIB Font Demo." ) ; + text -> end () ; + + text -> setFont ( font_list [ 0 ] ) ; + text -> setPointSize ( 12.0f ) ; + + text -> begin () ; + glColor3f ( 0.0f, 0.0f, 0.0f ) ; + text -> start2f ( 270.0f, 168.0f ) ; + text -> puts ( "The current font is:" ) ; + text -> start2f ( 300.0f, 148.0f ) ; + text -> puts ( font_names [ cur_font ] ) ; + text -> start2f ( 270.0f, 128.0f ) ; + text -> puts ( "Press any key to change the font.\nClick the mouse to exit." ) ; + text -> end () ; + + text -> setFont ( font_list [ cur_font ] ) ; + text -> setPointSize ( 25.0f ) ; + + text -> begin () ; + glColor3f ( 0.0f, 1.0f, 1.0f ) ; + text -> start2f ( 50.0f, 360.0f ) ; + text -> puts ( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ) ; + glColor3f ( 1.0f, 0.0f, 1.0f ) ; + text -> start2f ( 50.0f, 320.0f ) ; + text -> puts ( "abcdefghijklmnopqrstuvwxyz" ) ; + glColor3f ( 1.0f, 0.0f, 0.0f ) ; + text -> start2f ( 50.0f, 280.0f ) ; + text -> puts ( "0123456789!@#$%^&*()+-={}[]:\"'<>?,./`~_" ) ; + text -> end () ; + + text -> setPointSize ( 9.0f ) ; + text -> begin () ; + glColor3f ( 0, 0, 0 ) ; + text -> start2f ( -50.0f, 265.0f ) ; + text -> puts ( "This is a very long line, in fact, this line is so long, that it starts left of viewport. We are curious to see wether this line is still visible in plib." ) ; + text -> end () ; + + glDisable ( GL_TEXTURE_2D ) ; + glBegin ( GL_LINE_LOOP ) ; + glColor3f ( 1.0f, 0.0f, 1.0f ) ; + glVertex2f ( 0.0f, 0.0f ) ; + glVertex2f ( 256.0f, 0.0f ) ; + glVertex2f ( 256.0f, 256.0f ) ; + glVertex2f ( 0.0f, 256.0f ) ; + glEnd () ; + + glEnable ( GL_TEXTURE_2D ) ; + glBegin ( GL_TRIANGLE_STRIP ) ; + glColor3f ( 1.0f, 1.0f, 1.0f ) ; + glTexCoord2f( 0.0f, 0.0f ) ; glVertex2f ( 0.0f, 0.0f ) ; + glTexCoord2f( 1.0f, 0.0f ) ; glVertex2f ( 256.0f, 0.0f ) ; + glTexCoord2f( 0.0f, 1.0f ) ; glVertex2f ( 0.0f, 256.0f ) ; + glTexCoord2f( 1.0f, 1.0f ) ; glVertex2f ( 256.0f, 256.0f ) ; + glEnd () ; + + restoreOpenGLState () ; + glutSwapBuffers () ; + glutPostRedisplay () ; +} + + +int main ( int argc, char **argv ) +{ + font_list = new fntTexFont* [ sizeof(font_names) / sizeof(font_names[0]) ] ; + + glutInitWindowPosition ( 0, 0 ) ; + glutInitWindowSize ( 640, 480 ) ; + glutInit ( &argc, argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + glutCreateWindow ( "FNT Application" ) ; + glutDisplayFunc ( displayfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; + glutKeyboardFunc ( keyfn ) ; + + text = new fntRenderer () ; + + for ( max_font = 0 ; font_names [ max_font ] != NULL ; max_font++ ) + { + char fname [ 256 ] ; + +#ifdef macintosh + sprintf ( fname, ":data:%s", font_names [ max_font ] ) ; +#else + sprintf ( fname, "data/%s", font_names [ max_font ] ) ; +#endif + + font_list [ max_font ] = new fntTexFont ( fname ) ; + } + + cur_font = 0 ; + + glutMainLoop () ; + return 0 ; +} + diff --git a/examples/src/fnt/fnt_test.dsp b/examples/src/fnt/fnt_test.dsp new file mode 100644 index 0000000..7b6f640 --- /dev/null +++ b/examples/src/fnt/fnt_test.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="fnt_test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=fnt_test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "fnt_test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "fnt_test.mak" CFG="fnt_test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "fnt_test - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "fnt_test - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "fnt_test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib fnt.lib sg.lib ul.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /machine:I386 /out:"fnt_test.exe" /libpath:"..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "fnt_test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib fnt_d.lib sg_d.lib ul_d.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /debug /machine:I386 /out:"fnt_test.exe" /pdbtype:sept /libpath:"..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "fnt_test - Win32 Release" +# Name "fnt_test - Win32 Debug" +# Begin Source File + +SOURCE=.\fnt_test.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/fnt/hello_world.cxx b/examples/src/fnt/hello_world.cxx new file mode 100644 index 0000000..7146d7a --- /dev/null +++ b/examples/src/fnt/hello_world.cxx @@ -0,0 +1,65 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: hello_world.cxx 1996 2004-12-29 07:19:40Z sjbaker $ +*/ + + +#include +#include + +int main ( int argc, char **argv ) +{ + int w, h ; + + pwInit ( 100, 100, 230, 50, false, "FNT Hello World Demo", true, 0 ) ; + pwSetCallbacks ( NULL, NULL, NULL, NULL, NULL ) ; + pwGetSize ( &w, &h ) ; + + fntRenderer *text = new fntRenderer () ; + + text -> setFont ( new fntTexFont ( "data/Helvetica.txf" ) ) ; + text -> setPointSize ( 30.0f ) ; + + glEnable ( GL_ALPHA_TEST ) ; + glEnable ( GL_BLEND ) ; + glAlphaFunc ( GL_GREATER, 0.1f ) ; + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; + glMatrixMode ( GL_PROJECTION ) ; + glLoadIdentity () ; + glOrtho ( 0, w, 0, h, -1, 1 ) ; + + while ( 1 ) + { + glClearColor ( 0.1f, 0.4f, 0.1f, 1.0f ) ; + glClear ( GL_COLOR_BUFFER_BIT ) ; + + text -> begin () ; + glColor3f ( 1.0f, 1.0f, 0.0f ) ; + text -> start2f ( 10.0f, 10.0f ) ; + text -> puts ( "Hello World." ) ; + text -> end () ; + + pwSwapBuffers () ; + } + + return 0 ; +} + diff --git a/examples/src/fnt/slideshow.cxx b/examples/src/fnt/slideshow.cxx new file mode 100644 index 0000000..3b0a6ac --- /dev/null +++ b/examples/src/fnt/slideshow.cxx @@ -0,0 +1,235 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: slideshow.cxx 2099 2006-11-03 20:04:40Z fayjf $ +*/ + + +#include +#include +#include +#ifdef WIN32 +# include +# ifdef __CYGWIN32__ +# include +# include +# else +# include +# endif +#else +# include +# include +#endif +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#include + +static fntRenderer *text ; +static fntTexFont *font ; + +static char *file ; +static char **line ; +static int *page ; +static int num_lines = 0 ; +static int num_pages = 0 ; +static int curr_page = 0 ; + +static void motionfn ( int, int ) +{ + glutPostRedisplay () ; +} + +static void keyfn ( unsigned char key, int, int ) +{ + switch ( key ) + { + case 'H' : case 'R' : curr_page = 0 ; break ; + + case '<' : case '{' : curr_page-=5 ; break ; + + case 0x08 : /* Backspace */ + case '[' : case ',' : curr_page-- ; break ; + + case '>' : case '}' : curr_page+=5 ; break ; + case ' ' : + case '\n' : + case '\r' : + case ']' : case '.' : curr_page++ ; break ; + + case 0x03 : /* Ctrl-C */ + case 'x' : + case 'X' : exit ( 0 ) ; + } + + if ( curr_page < 0 ) curr_page = 0 ; + if ( curr_page >= num_pages ) curr_page = num_pages-1 ; +} + +static void mousefn ( int /*button*/, int /*updown*/, int /*x*/, int /*y*/ ) +{ + exit ( 0 ) ; +} + +static int getWindowHeight () { return glutGet ( (GLenum) GLUT_WINDOW_HEIGHT ) ; } +static int getWindowWidth () { return glutGet ( (GLenum) GLUT_WINDOW_WIDTH ) ; } + +static void setOpenGLState ( void ) +{ + int w = getWindowWidth () ; + int h = getWindowHeight () ; + + glutWarpPointer ( 320, 240 ) ; + + glPushAttrib ( GL_ENABLE_BIT | GL_VIEWPORT_BIT | GL_TRANSFORM_BIT | GL_LIGHTING_BIT ) ; + glDisable ( GL_LIGHTING ) ; + glDisable ( GL_FOG ) ; + glDisable ( GL_TEXTURE_2D ) ; + glDisable ( GL_DEPTH_TEST ) ; + glDisable ( GL_CULL_FACE ) ; + glEnable ( GL_ALPHA_TEST ) ; + glEnable ( GL_BLEND ) ; + glAlphaFunc ( GL_GREATER, 0.1f ) ; + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; + + glViewport ( 0, 0, w, h ) ; + glMatrixMode ( GL_PROJECTION ) ; + glPushMatrix () ; + glLoadIdentity () ; + gluOrtho2D ( 0, w, 0, h ) ; + glMatrixMode ( GL_MODELVIEW ) ; + glPushMatrix () ; + glLoadIdentity () ; +} + +static void restoreOpenGLState ( void ) +{ + glMatrixMode ( GL_PROJECTION ) ; + glPopMatrix () ; + glMatrixMode ( GL_MODELVIEW ) ; + glPopMatrix () ; + glPopAttrib () ; +} + + + +static void displayfn (void) +{ + setOpenGLState () ; + glClearColor ( 0.1f, 0.4f, 0.1f, 1.0f ) ; + glClear ( GL_COLOR_BUFFER_BIT ) ; + + text -> setFont ( font ) ; + text -> setPointSize ( 25.0f ) ; + + int row = 460 ; + + text -> begin () ; + glColor3f ( 1.0f, 1.0f, 1.0f ) ; + + for ( int i = page [ curr_page ] ; + i < page [ curr_page+1 ]-1 && i < num_lines && row > 0 ; i++ ) + { + text -> start2f ( 10.0f, (float)row ) ; + text -> puts ( line[i] ) ; + row -= 30 ; + } + text -> end () ; + + restoreOpenGLState () ; + glutSwapBuffers () ; + glutPostRedisplay () ; +} + + +int main ( int argc, char **argv ) +{ + + struct stat buf ; + const char* fname = NULL ; + + if ( argc > 1 ) + fname = argv[1] ; + else + fname = "data/test_slideshow.txt" ; + + FILE *fd = fopen ( fname, "r" ) ; + + if ( fd == NULL ) + exit ( 1 ) ; + + fstat ( fileno(fd), & buf ) ; + + off_t len = buf.st_size ; + + file = new char [ len+1 ] ; + line = new char* [ len+1 ] ; + page = new int [ len+1 ] ; + + fread ( file, 1, len, fd ) ; + fclose ( fd ) ; + + file [ len ] = '\0' ; + + num_lines = 0 ; + num_pages = 0 ; + + line [ num_lines ] = file ; + page [ num_pages ] = 0 ; + + for ( int i = 0 ; i < len ; i++ ) + { + if ( file [ i ] == '\n' ) + { + file [ i ] = '\0' ; + line [ ++num_lines ] = & file [ i+1 ] ; + + if ( line [ num_lines ][ 0 ] == '*' ) + page [ ++num_pages ] = num_lines+1 ; + } + } + + glutInitWindowPosition ( 0, 0 ) ; + glutInitWindowSize ( 640, 480 ) ; + glutInit ( &argc, argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + glutCreateWindow ( "FNT Application" ) ; + glutDisplayFunc ( displayfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; + glutKeyboardFunc ( keyfn ) ; + + text = new fntRenderer () ; + font = new fntTexFont ( "data/old/lucida.txf" ) ; + + glutMainLoop () ; + return 0 ; +} + + diff --git a/examples/src/fnt/slideshow.dsp b/examples/src/fnt/slideshow.dsp new file mode 100644 index 0000000..e9a2aec --- /dev/null +++ b/examples/src/fnt/slideshow.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="slideshow" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=slideshow - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "slideshow.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "slideshow.mak" CFG="slideshow - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "slideshow - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "slideshow - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "slideshow - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib fnt.lib sg.lib ul.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libcd.lib" /out:"slideshow.exe" /libpath:"..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "slideshow - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib fnt_d.lib sg_d.lib ul_d.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /debug /machine:I386 /out:"slideshow.exe" /pdbtype:sept /libpath:"..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "slideshow - Win32 Release" +# Name "slideshow - Win32 Debug" +# Begin Source File + +SOURCE=.\slideshow.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/js/Makefile.am b/examples/src/js/Makefile.am new file mode 100644 index 0000000..655d2de --- /dev/null +++ b/examples/src/js/Makefile.am @@ -0,0 +1,12 @@ +if BUILD_JS + +noinst_PROGRAMS = js_demo + +js_demo_SOURCES = js_demo.cxx + +js_demo_LDADD = -lplibjs -lplibul + +endif + +EXTRA_DIST = js_demo.dsp + diff --git a/examples/src/js/js_demo.cxx b/examples/src/js/js_demo.cxx new file mode 100644 index 0000000..6b64621 --- /dev/null +++ b/examples/src/js/js_demo.cxx @@ -0,0 +1,124 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: js_demo.cxx 1551 2002-09-01 12:04:53Z ude $ +*/ + + +#include + +int main ( int, char ** ) +{ + jsJoystick *js[2] ; + float *ax[2] ; + + jsInit () ; + + js[0] = new jsJoystick ( 0 ) ; + js[1] = new jsJoystick ( 1 ) ; + + printf ( "Joystick test program.\n" ) ; + printf ( "~~~~~~~~~~~~~~~~~~~~~~\n" ) ; + + if ( js[0]->notWorking () ) + printf ( "Joystick 0 not detected\n" ) ; + else + printf ( "Joystick 0 is \"%s\"\n", js[0]->getName() ) ; + + if ( js[1]->notWorking () ) + printf ( "Joystick 1 not detected\n" ) ; + else + printf ( "Joystick 1 is \"%s\"\n", js[1]->getName() ) ; + + if ( js[0]->notWorking () && js[1]->notWorking () ) exit ( 1 ) ; + + ax[0] = new float [ js[0]->getNumAxes () ] ; + ax[1] = new float [ js[1]->getNumAxes () ] ; + + int i, j ; + + for ( i = 0 ; i < 2 ; i++ ) + printf ( "+---------------JS.%d-----------------", i ) ; + + printf ( "+\n" ) ; + + for ( i = 0 ; i < 2 ; i++ ) + { + if ( js[i]->notWorking () ) + printf ( "| ~~~ Not Detected ~~~ " ) ; + else + { + printf ( "| Btns " ) ; + + for ( j = 0 ; j < js[i]->getNumAxes () ; j++ ) + printf ( "Ax:%d ", j ) ; + + for ( ; j < 6 ; j++ ) + printf ( " " ) ; + } + } + + printf ( "|\n" ) ; + + for ( i = 0 ; i < 2 ; i++ ) + printf ( "+------------------------------------" ) ; + + printf ( "+\n" ) ; + + while (1) + { + for ( i = 0 ; i < 2 ; i++ ) + { + if ( js[i]->notWorking () ) + printf ( "| . . . . . . . . . " ) ; + else + { + int b ; + + js[i]->read ( &b, ax[i] ) ; + + printf ( "| %04x ", b ) ; + + for ( j = 0 ; j < js[i]->getNumAxes () ; j++ ) + printf ( "%+.1f ", ax[i][j] ) ; + + for ( ; j < 6 ; j++ ) + printf ( " . " ) ; + } + } + + printf ( "|\r" ) ; + fflush ( stdout ) ; + + /* give other processes a chance */ + +#ifdef WIN32 + Sleep ( 1 ) ; +#elif defined(sgi) + sginap ( 1 ) ; +#else + usleep ( 1000 ) ; +#endif + } + + return 0 ; +} + + diff --git a/examples/src/js/js_demo.dsp b/examples/src/js/js_demo.dsp new file mode 100644 index 0000000..ca789ae --- /dev/null +++ b/examples/src/js/js_demo.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="js_demo" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=js_demo - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "js_demo.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "js_demo.mak" CFG="js_demo - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "js_demo - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "js_demo - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "js_demo - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ul.lib js.lib winmm.lib /nologo /subsystem:console /machine:I386 /out:"js_demo.exe" /libpath:"..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "js_demo - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ul_d.lib js_d.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /out:"js_demo.exe" /pdbtype:sept /libpath:"..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "js_demo - Win32 Release" +# Name "js_demo - Win32 Debug" +# Begin Source File + +SOURCE=.\js_demo.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/net/Makefile.am b/examples/src/net/Makefile.am new file mode 100644 index 0000000..3e3d542 --- /dev/null +++ b/examples/src/net/Makefile.am @@ -0,0 +1,3 @@ + +SUBDIRS = client_server http_get net_echo + diff --git a/examples/src/net/client_server/Makefile.am b/examples/src/net/client_server/Makefile.am new file mode 100644 index 0000000..1d13015 --- /dev/null +++ b/examples/src/net/client_server/Makefile.am @@ -0,0 +1,14 @@ +if BUILD_NET + +noinst_PROGRAMS = net_udp_client net_udp_server + +net_udp_client_SOURCES = net_udp_client.cxx +net_udp_client_LDADD = -lplibnet -lplibul + +net_udp_server_SOURCES = net_udp_server.cxx +net_udp_server_LDADD = -lplibnet -lplibul + +endif + +EXTRA_DIST = net_udp_client.dsp net_udp_server.dsp + diff --git a/examples/src/net/client_server/README b/examples/src/net/client_server/README new file mode 100644 index 0000000..bcc7e35 --- /dev/null +++ b/examples/src/net/client_server/README @@ -0,0 +1,25 @@ + +This example demonstrates a simple one-way communication path +between a client and a server. + +It uses UDP protocol - which is unreliable but fast - don't +use it for messages that utterly must get there! + +The client program can be told to send to the server on any port number of +any host computer - by default it uses 'localhost'. + +The server program can be told to listen out on any port number +and to either listen to just one specific client - or to accept +messages from any client. + +Usage: + + net_udp_client [-p port] [servername] + net_udp_server [-p port] [clientname] + +The default for the client is to use port 5501 on 'localhost'. +The default to the server is to listen on port 5501 and to allow anyone +to send to it. The name "" refers to the broadcast address. +(To enter it on the command line, you'll need to escape the < and > +symbols like this: \ ) + diff --git a/examples/src/net/client_server/net_udp_client.cxx b/examples/src/net/client_server/net_udp_client.cxx new file mode 100644 index 0000000..28724b7 --- /dev/null +++ b/examples/src/net/client_server/net_udp_client.cxx @@ -0,0 +1,105 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: net_udp_client.cxx 1898 2004-03-21 17:13:00Z sjbaker $ +*/ + +// This is an example of a UDP client that blasts messages at a +// server. +// +// UDP is a "fire and forget" protocal so the client and server can be +// started up in any order. The client doesn't care if the server +// receives the messages and the server doesn't care if the client is +// sending messages, so either side can be killed and restarted at any +// time. + +#include +#include +#include + +void help () +{ + fprintf ( stderr, "net_udp_client: Usage -\n" ) ; + fprintf ( stderr, "\n" ) ; + fprintf ( stderr, " net_udp_client [-h] [-p port] [hostname]\n" ) ; + fprintf ( stderr, "\n" ) ; + fprintf ( stderr, "Where:\n" ) ; + fprintf ( stderr, " -h -- Help (displays this message).\n" ) ; + fprintf ( stderr, " -p port -- Set the port number (def=5501).\n" ) ; + fprintf ( stderr, " hostname -- Set the host name (def=localhost).\n" ) ; + fprintf ( stderr, "\n" ) ; + exit ( 0 ) ; +} + +int main ( int argc, char **argv ) +{ + int port = 5501 ; + char host[256] = "localhost" ; + + for ( int i = 1 ; i < argc ; i++ ) + { + if ( argv [ i ][ 0 ] == '-' || argv [ i ][ 0 ] == '+' ) + switch ( argv [ i ][ 1 ] ) + { + case 'p' : port = atoi ( argv [ ++i ] ) ; break ; + case 'h' : + default : help () ; break ; + } + else + strcpy ( host, argv [ i ] ) ; + } + + fprintf ( stderr, "Talking to host '%s' on port %d\n", host, port ) ; + + // Must call this before any other net stuff + + netInit() ; + + netSocket *sock = new netSocket () ; + + if ( ! sock -> open ( false ) ) // open a UDP socket + { + printf ( "error opening socket\n" ) ; + return -1 ; + } + + sock -> setBlocking ( false ) ; + + if ( sock -> connect( host, port ) == -1 ) + { + printf ( "error connecting to %s:%d\n", host, port ) ; + return -1 ; + } + + char msg[256] = "Hello world!" ; + + int len = strlen ( msg ) ; + + while ( true ) + { + ulSleep ( 1 ) ; + sock -> send( msg, len, 0 ); + printf("msg sent = %s\n", msg); + } + + return 0; +} + + diff --git a/examples/src/net/client_server/net_udp_client.dsp b/examples/src/net/client_server/net_udp_client.dsp new file mode 100644 index 0000000..4384d7b --- /dev/null +++ b/examples/src/net/client_server/net_udp_client.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="net_udp_client" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=net_udp_client - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "net_udp_client.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "net_udp_client.mak" CFG="net_udp_client - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "net_udp_client - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "net_udp_client - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "net_udp_client - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib net.lib ul.lib wsock32.lib /nologo /subsystem:console /machine:I386 /out:"net_udp_client.exe" /libpath:"..\..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "net_udp_client - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib net_d.lib ul_d.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /out:"net_udp_client.exe" /pdbtype:sept /libpath:"..\..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "net_udp_client - Win32 Release" +# Name "net_udp_client - Win32 Debug" +# Begin Source File + +SOURCE=.\net_udp_client.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/net/client_server/net_udp_server.cxx b/examples/src/net/client_server/net_udp_server.cxx new file mode 100644 index 0000000..714b44b --- /dev/null +++ b/examples/src/net/client_server/net_udp_server.cxx @@ -0,0 +1,87 @@ +// This is an example of a UDP server that accepts messages coming from a +// client. +// +// UDP is a "fire and forget" protocal so the client and server can be +// started up in any order. The client doesn't care if the server +// receives the messages and the server doesn't care if the client is +// sending messages, so either side can be killed and restarted at any +// time. + +#include +#include + + +void help () +{ + fprintf ( stderr, "net_udp_server: Usage -\n" ) ; + fprintf ( stderr, "\n" ) ; + fprintf ( stderr, " net_udp_server [-h] [-p port] [hostname]\n" ) ; + fprintf ( stderr, "\n" ) ; + fprintf ( stderr, "Where:\n" ) ; + fprintf ( stderr, " -h -- Help (displays this message).\n" ) ; + fprintf ( stderr, " -p port -- Set the port number (def=5501).\n" ) ; + fprintf ( stderr, " hostname -- Set the client host name (def=any host).\n"); + fprintf ( stderr, "\n" ) ; + exit ( 0 ) ; +} + + +int main( int argc, char **argv ) +{ + int port = 5501 ; + char host [ 256 ] = "" ; + + for ( int i = 1 ; i < argc ; i++ ) + { + if ( argv [ i ][ 0 ] == '-' || argv [ i ][ 0 ] == '+' ) + switch ( argv [ i ][ 1 ] ) + { + case 'p' : port = atoi ( argv [ ++i ] ) ; break ; + case 'h' : + default : help () ; break ; + } + else + strcpy ( host, argv [ i ] ) ; + } + + if ( host [ 0 ] == '\0' ) + fprintf ( stderr, "Listening to any host on port %d\n", port ) ; + else + fprintf ( stderr, "Listening to host '%s' on port %d\n", host, port ) ; + + // Must call this before any other net stuff + + netInit () ; + + netSocket *sock = new netSocket () ; + + if ( ! sock -> open( false ) ) // open a UDP socket + { + printf ( "error opening socket\n" ) ; + return -1 ; + } + + sock -> setBlocking ( false ) ; + + if ( sock -> bind( host, port ) == -1 ) + { + printf ( "error binding to port %s:%d\n", host, port ) ; + return -1 ; + } + + char msg [ 256 ] ; + int maxlen = 256 ; + int len ; + + while ( true ) + { + if ( (len = sock -> recv(msg, maxlen, 0)) >= 0 ) + { + msg[len] = '\0' ; + printf ( "msg received = %s\n", msg ) ; + } + } + + return 0 ; +} + diff --git a/examples/src/net/client_server/net_udp_server.dsp b/examples/src/net/client_server/net_udp_server.dsp new file mode 100644 index 0000000..041a001 --- /dev/null +++ b/examples/src/net/client_server/net_udp_server.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="net_udp_server" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=net_udp_server - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "net_udp_server.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "net_udp_server.mak" CFG="net_udp_server - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "net_udp_server - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "net_udp_server - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "net_udp_server - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib net.lib ul.lib wsock32.lib /nologo /subsystem:console /machine:I386 /out:"net_udp_server.exe" /libpath:"..\..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "net_udp_server - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib net_d.lib ul_d.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /out:"net_udp_server.exe" /pdbtype:sept /libpath:"..\..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "net_udp_server - Win32 Release" +# Name "net_udp_server - Win32 Debug" +# Begin Source File + +SOURCE=.\net_udp_server.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/net/http_get/Makefile.am b/examples/src/net/http_get/Makefile.am new file mode 100644 index 0000000..f335a24 --- /dev/null +++ b/examples/src/net/http_get/Makefile.am @@ -0,0 +1,12 @@ +if BUILD_NET + +noinst_PROGRAMS = http_get + +http_get_SOURCES = http_get.cxx + +http_get_LDADD = -lplibnet -lplibul + +endif + +EXTRA_DIST = http_get.dsp + diff --git a/examples/src/net/http_get/README b/examples/src/net/http_get/README new file mode 100644 index 0000000..6d2ee85 --- /dev/null +++ b/examples/src/net/http_get/README @@ -0,0 +1,6 @@ + +This demonstrates the fetching of a HTTP web page using the network +library. + +It's hardwired to fetch the PLIB home-page. + diff --git a/examples/src/net/http_get/http_get.cxx b/examples/src/net/http_get/http_get.cxx new file mode 100644 index 0000000..adb7b8f --- /dev/null +++ b/examples/src/net/http_get/http_get.cxx @@ -0,0 +1,75 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: http_get.cxx 1906 2004-03-22 19:44:50Z sjbaker $ +*/ + +#include + +class HTTPClient : public netBufferChannel +{ + FILE *fpout ; + +public: + + HTTPClient ( const char* host, const char* path ) + { + open () ; + connect ( host, 80 ) ; + + const char* s = netFormat ( "GET %s HTTP/1.1\r\n", path ) ; + bufferSend ( s, strlen(s) ) ; + const char* h = netFormat ( "host: %s\r\n", host ) ; + bufferSend ( h, strlen(h) ) ; + const char *c = netFormat ( "Connection: close\r\n\r\n" ) ; + bufferSend ( c, strlen(c) ) ; + } + + ~HTTPClient () + { + if( fpout ) + fclose( fpout ); + } + + virtual void handleBufferRead (netBuffer& buffer) + { + const char* s = buffer.getData(); + + while (*s) + fputc(*s++,stdout); + + buffer.remove(); + } +} ; + + +int main ( int argc, char * argv[] ) +{ + netInit ( &argc, argv ) ; + + new HTTPClient ( "plib.sourceforge.net", "/index.html" ) ; + + netChannel::loop ( 0 ) ; + return 0 ; +} + + + + diff --git a/examples/src/net/http_get/http_get.dsp b/examples/src/net/http_get/http_get.dsp new file mode 100644 index 0000000..4a6d509 --- /dev/null +++ b/examples/src/net/http_get/http_get.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="http_get" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=http_get - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "http_get.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "http_get.mak" CFG="http_get - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "http_get - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "http_get - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "http_get - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib net.lib ul.lib wsock32.lib /nologo /subsystem:console /machine:I386 /out:"http_get.exe" /libpath:"..\..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "http_get - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib net_d.lib ul_d.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /out:"http_get.exe" /pdbtype:sept /libpath:"..\..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "http_get - Win32 Release" +# Name "http_get - Win32 Debug" +# Begin Source File + +SOURCE=.\http_get.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/net/net_echo/Makefile.am b/examples/src/net/net_echo/Makefile.am new file mode 100644 index 0000000..f0566ef --- /dev/null +++ b/examples/src/net/net_echo/Makefile.am @@ -0,0 +1,12 @@ +if BUILD_NET + +noinst_PROGRAMS = net_echo + +net_echo_SOURCES = net_echo.cxx + +net_echo_LDADD = -lplibnet -lplibul + +endif + +EXTRA_DIST = net_echo.dsp + diff --git a/examples/src/net/net_echo/README b/examples/src/net/net_echo/README new file mode 100644 index 0000000..a38fbfb --- /dev/null +++ b/examples/src/net/net_echo/README @@ -0,0 +1,16 @@ + +This is a simple example server that reads lines of text from the client +and echoes them back. An echo server is usually running on TCP +port 7 of Unix machines. + +Start it running someplace on your network, then use 'telnet' to +connect to it on port 8000: + + telnet localhost 8000 + +...notice that you can open multiple telnet sessions - and the +server echoes the right data back to the right client. + +You can choose a port number other than 8000 by putting it on the +command line of the echo server. + diff --git a/examples/src/net/net_echo/net_echo.cxx b/examples/src/net/net_echo/net_echo.cxx new file mode 100644 index 0000000..26ac15c --- /dev/null +++ b/examples/src/net/net_echo/net_echo.cxx @@ -0,0 +1,97 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: net_echo.cxx 1898 2004-03-21 17:13:00Z sjbaker $ +*/ + +#include + +/* +** simple example server that reads lines of text from the client +** and echoes them back. An echo server is usually running on TCP +** port 7 of Unix machines. +*/ + +class EchoChannel : public netChat +{ + netBuffer buffer ; + +public: + + EchoChannel() : buffer(512) { setTerminator("\r\n"); } + + virtual void collectIncomingData (const char* s, int n) + { + buffer.append(s,n); + } + + virtual void foundTerminator (void) + { + const char* s = buffer.getData(); + printf("echo: %s\n",s); + + push(s); + push(getTerminator()); + + buffer.remove(); + } +} ; + +class EchoServer : private netChannel +{ + virtual bool writable (void) { return false ; } + + virtual void handleAccept (void) + { + netAddress addr ; + int handle = accept ( &addr ) ; + printf("Client %s:%d connected\n",addr.getHost(),addr.getPort()); + + EchoChannel * ec = new EchoChannel; + ec->setHandle ( handle ) ; + } + +public: + + EchoServer ( int port ) + { + open () ; + bind ("", port) ; + listen (5) ; + + printf ( "Echo Server started on port %d\n", port ) ; + } +} ; + +int +main (int argc, char * argv[]) +{ + int port = 8000 ; + + if (argc > 1) + port = atoi (argv[1]); + + netInit(&argc,argv); + + new EchoServer ( port ) ; + + netChannel::loop(0); + return 0; +} diff --git a/examples/src/net/net_echo/net_echo.dsp b/examples/src/net/net_echo/net_echo.dsp new file mode 100644 index 0000000..01e8340 --- /dev/null +++ b/examples/src/net/net_echo/net_echo.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="net_echo" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=net_echo - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "net_echo.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "net_echo.mak" CFG="net_echo - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "net_echo - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "net_echo - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "net_echo - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib net.lib ul.lib wsock32.lib /nologo /subsystem:console /machine:I386 /out:"net_echo.exe" /libpath:"..\..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "net_echo - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib net_d.lib ul_d.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /out:"net_echo.exe" /pdbtype:sept /libpath:"..\..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "net_echo - Win32 Release" +# Name "net_echo - Win32 Debug" +# Begin Source File + +SOURCE=.\net_echo.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/psl/Makefile.am b/examples/src/psl/Makefile.am new file mode 100644 index 0000000..b2b20fb --- /dev/null +++ b/examples/src/psl/Makefile.am @@ -0,0 +1,13 @@ +if BUILD_PSL + +noinst_PROGRAMS = psl_demo + +psl_demo_SOURCES = psl_demo.cxx + +psl_demo_LDADD = -lplibpsl -lplibul -lm + +endif + +EXTRA_DIST = psl_demo.dsp + + diff --git a/examples/src/psl/data/header.psh b/examples/src/psl/data/header.psh new file mode 100644 index 0000000..9fbe382 --- /dev/null +++ b/examples/src/psl/data/header.psh @@ -0,0 +1,4 @@ + +void newline () { printf ( "\n" ) ; } +void tab () { printf ( "\t" ) ; } + diff --git a/examples/src/psl/data/test.psl b/examples/src/psl/data/test.psl new file mode 100644 index 0000000..2beaac2 --- /dev/null +++ b/examples/src/psl/data/test.psl @@ -0,0 +1,9 @@ + + +void main () +{ + int diff ; + + if ( diff == 1 ) { diff = 2 ; } else { diff = 3 ; } +} + diff --git a/examples/src/psl/psl_demo.cxx b/examples/src/psl/psl_demo.cxx new file mode 100644 index 0000000..cfd3c6b --- /dev/null +++ b/examples/src/psl/psl_demo.cxx @@ -0,0 +1,129 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: psl_demo.cxx 1912 2004-03-24 10:54:56Z nmcevoy $ +*/ + + +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include + +pslValue my_printf ( int argc, pslValue *argv, pslProgram *p ) +{ + if ( argv[0].getType() != PSL_STRING ) + printf ( "printf: ERROR - First param must be a string!\n" ) ; + else + { + printf ( "%s", argv[0].getString() ) ; + + for ( int i = 1 ; i < argc ; i++ ) + { + switch ( argv[i].getType () ) + { + case PSL_INT : printf ( "%d ", argv[i].getInt () ) ; break ; + case PSL_FLOAT : printf ( "%f ", argv[i].getFloat () ) ; break ; + case PSL_STRING : printf ( "%s ", argv[i].getString () ) ; break ; + case PSL_VOID : printf ( "(void) " ) ; break ; + } + } + } + + pslValue ret ; + return ret ; +} + + +pslValue identify ( int argc, pslValue *argv, pslProgram *p ) +{ + printf ( "I am %s.\n", (char *)( p->getUserData ()) ) ; + + pslValue ret ; + return ret ; +} + + +pslExtension extensions [] = +{ + { "identify", 0, identify }, + { "printf", -1, my_printf }, + { NULL, 0, NULL } +} ; + + +int main () +{ + pslInit () ; + + /* Create program 1 and compile it. */ + + pslProgram *prog_1 = new pslProgram ( extensions, "code1" ) ; + + ulClock ck ; + ck.setMaxDelta ( 100000.0 ) ; + ck.update () ; + + prog_1 -> compile ( "data/test.psl" ) ; + + ck.update () ; + fprintf(stderr, "%fs compiletime elapsed\n", ck.getDeltaTime () ) ; + + prog_1 -> dump () ; + + /* Clone program 2 from program 1 */ + + pslProgram *prog_2 = new pslProgram ( prog_1, "code2" ) ; + + /* Make program 3 from inline strings. */ + + pslProgram *prog_3 = new pslProgram ( extensions, "inline" ) ; + + prog_3 -> compile ( "int main () { printf ( \"Hello World.\\n\" ) ; }\n", + "HelloProgram" ) ; + + /* Make them unique by assigning user data to them */ + + prog_1 -> setUserData ( (void *) "Program 1" ) ; + prog_2 -> setUserData ( (void *) "Program 2" ) ; + prog_3 -> setUserData ( (void *) "Program 3" ) ; + + ck.update () ; + + while ( 1 ) + { + if ( prog_1 -> step () == PSL_PROGRAM_END && + prog_2 -> step () == PSL_PROGRAM_END && + prog_3 -> step () == PSL_PROGRAM_END ) + break ; + } + ck.update () ; + fprintf(stderr, "%fs runtime elapsed\n", ck.getDeltaTime () ) ; + + exit ( 0 ) ; + + return 0 ; +} + + diff --git a/examples/src/psl/psl_demo.dsp b/examples/src/psl/psl_demo.dsp new file mode 100644 index 0000000..6ba3ba0 --- /dev/null +++ b/examples/src/psl/psl_demo.dsp @@ -0,0 +1,90 @@ +# Microsoft Developer Studio Project File - Name="psl_demo" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=psl_demo - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "psl_demo.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "psl_demo.mak" CFG="psl_demo - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "psl_demo - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "psl_demo - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "psl_demo - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib psl.lib ul.lib /nologo /subsystem:console /machine:I386 /out:"psl_demo.exe" /libpath:"..\..\..\..\plib" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "psl_demo - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib psl_d.lib ul_d.lib /nologo /subsystem:console /debug /machine:I386 /out:"psl_demo.exe" /pdbtype:sept /libpath:"..\..\..\..\plib" +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "psl_demo - Win32 Release" +# Name "psl_demo - Win32 Debug" +# Begin Source File + +SOURCE=.\psl_demo.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/pui/Makefile.am b/examples/src/pui/Makefile.am new file mode 100644 index 0000000..d5e0aaf --- /dev/null +++ b/examples/src/pui/Makefile.am @@ -0,0 +1,31 @@ +if BUILD_PUI + +noinst_PROGRAMS = simple complex widget_list PointPicker widget_test + +simple_SOURCES = simple.cxx + +complex_SOURCES = complex.cxx + +widget_test_SOURCES = widget_test.cxx + +widget_list_SOURCES = widget_list.cxx + +PointPicker_SOURCES = PointPicker.cxx + +simple_LDADD = -lplibpu -lplibfnt -lplibsg -lplibul $(GLUT_LIBS) $(OGL_LIBS) + +complex_LDADD = -lplibpuaux -lplibpu -lplibfnt -lplibsg -lplibul $(GLUT_LIBS) $(OGL_LIBS) + +widget_test_LDADD = -lplibpuaux -lplibpu -lplibfnt -lplibsg -lplibul $(GLUT_LIBS) \ + $(OGL_LIBS) + +widget_list_LDADD = -lplibpuaux -lplibpu -lplibfnt -lplibsg -lplibul $(GLUT_LIBS) \ + $(OGL_LIBS) + +PointPicker_LDADD = -lplibpuaux -lplibpu -lplibfnt -lplibsg -lplibul $(GLUT_LIBS) \ + $(OGL_LIBS) + +endif + +EXTRA_DIST = complex.dsp simple.dsp PointPicker.dsp widget_list.dsp widget_test.dsp + diff --git a/examples/src/pui/PointPicker.cxx b/examples/src/pui/PointPicker.cxx new file mode 100644 index 0000000..c2f0618 --- /dev/null +++ b/examples/src/pui/PointPicker.cxx @@ -0,0 +1,446 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: PointPicker.cxx 2143 2009-01-21 17:18:45Z fayjf $ +*/ + +// Point Picker Program by John Fay, October 2000. +// This is a demonstration program for PUI. It displays a set of points in +// a window and allows the user to pick them with the right mouse button. +// It demonstrates the following PUI capabilities: +// - puInput widget +// - puOneShot widget +// - active widget functionality, with up, active, and down callbacks +// - valuators +// +// To use it, the user does the following: +// First Method: Click in the input widget and type the number of the +// point +// Second Method: Click in the input widget and right-click on a point to +// select it. +// +// For both methods, clicking the left (one-shot) button moves the point +// to the right. When it gets far enough to the right, it wraps around to +// the left and moves slightly upwards. + +#include +#include +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#include +#include + +//#define VOODOO 1 + +/***********************************\ +* * +* These are the PUI widget pointers * +* * +\***********************************/ + +static int main_window ; +static puText *instruction ; +static puInput *point_no ; +static puOneShot *move_point ; +static puButton *exit_button ; +static puaLargeInput *input ; + +static int picked_point ; +static int mouse_x, mouse_y ; // Mouse coordinates + +//static fntTexFont *tim ; + +/**********************************\ +* * +* Here are the point coordinates * +* * +\**********************************/ + +typedef struct { + float x, y, z ; +} node ; + +#define NUMBER_POINTS 30 + +static node point[NUMBER_POINTS] ; + +static int firsttime; + +static void drawSinglePickableObject ( int i, float x, float y, float z ) +{ + // I realize that putting the point size, normal, and begin/end inside the for-loop + // is less efficient, but for the purposes of the demo I want everything required + // to draw a single pickable object in this routine. + + glPointSize ( 10.0f ) ; + glBegin ( GL_POINTS ) ; + glNormal3f ( 1.0f, 0.0f, 0.0f ) ; // Needed so the points show color + + if ( i == picked_point ) + glColor4f ( 1.0f, 0.0f, 0.0f, 1.0f ) ; + else + glColor4f ( 0.0f, 1.0f, 0.0f, 1.0f ) ; + + glVertex3f ( x, y, z ) ; + + glEnd () ; +} + +static void drawPoints (void) +{ + + if ( firsttime ) + { + /* + Deliberately do this only once - it's a better test of + PUI's attempts to leave the OpenGL state undisturbed + */ + glEnable ( GL_BLEND ) ; + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glAlphaFunc(GL_GREATER,0.1f); + + firsttime = FALSE ; + + 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 ) ; + + // Assign point coordinates (random values between zero and one) + + for ( int i = 0; i < NUMBER_POINTS; i++ ) + { + point[i].x = ( (float) i / (float)NUMBER_POINTS * 2 ) - 1 ; + point[i].y = ( (float)( ( i * i * i ) % NUMBER_POINTS) / (float)NUMBER_POINTS * 2 ) - 1 ; + point[i].z = ( (float)( ( i * i ) % NUMBER_POINTS) / (float)NUMBER_POINTS * 2 ) - 1 ; + } + } + + GLfloat matrix[16] ; + glGetFloatv ( GL_MODELVIEW_MATRIX, matrix ) ; + glGetFloatv ( GL_PROJECTION_MATRIX, matrix ) ; + + for ( int i = 0 ; i < NUMBER_POINTS ; i++ ) + { + drawSinglePickableObject ( i, point[i].x, point[i].y, point[i].z ) ; + } +} + + +/**************************************\ +* * +* 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 puObject *active_widget = (puObject *)NULL ; +static void mousefn ( int button, int updown, int x, int y ) +{ + if ( updown == PU_UP ) active_widget = puActiveWidget () ; + if ( !puMouse ( button, updown, x, y ) ) + { + // PUI didn't take the mouseclick, try the main window + + mouse_x = x ; + mouse_y = puGetWindowHeight () - y ; + + // Check for an active widget. If there is one, call its active callback + + if ( active_widget ) + { + active_widget -> invokeActiveCallback () ; + // Make sure PUI keeps the active widget active + puSetActiveWidget ( active_widget, 0, 0 ) ; + } + } + + glutPostRedisplay () ; +} + +/**************************************\ +* * +* This function redisplays the PUI and * +* the points, 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.4f, 0.1f, 0.1f, 1.0f ) ; + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + /* Draw the points */ + + drawPoints () ; + + /* Make PUI redraw */ + + puDisplay () ; + + /* Off we go again... */ + + glutSwapBuffers () ; + glutPostRedisplay () ; +} + +/***********************************\ +* * +* Here are the PUI widget callback * +* functions. * +* * +\***********************************/ + +// Point Number Input Widget Up Callback + +static void point_no_up_cb ( puObject *ob ) +{ + printf ( "Calling the up-callback with partial data: %d\n", picked_point ) ; + if ( input->inputDisabled () ) + input->enableInput () ; + else + input->disableInput () ; +} + +// Point Number Input Widget Active Callback + +static void point_no_active_cb ( puObject *ob ) +{ + GLint viewport[4] ; // Viewport + glGetIntegerv ( GL_VIEWPORT, viewport ) ; + + GLuint buffer[512]; + glSelectBuffer ( 512L, buffer ); // Set up the buffer to put hits into + glRenderMode ( GL_SELECT ) ; // Go into Select mode + + glInitNames (); // Empty the name stack + + glMatrixMode ( GL_PROJECTION ) ; // Set the Projection matrix for picking + glPushMatrix () ; // Save the current matrix + glLoadIdentity(); + + // Many thanks to Dave McClurg for getting the transformation matrices to work correctly + /* create 10x10 pixel picking region near cursor location */ + gluPickMatrix ( (double)mouse_x, (double)mouse_y, + 10.0f, 10.0f, viewport ) ; + + gluPerspective ( 40.0, 1.0, 1.0, 10.0 ) ; + + for ( int i = 0 ; i < NUMBER_POINTS ; i++ ) + { + glPushName ( i ) ; + drawSinglePickableObject ( i, point[i].x, point[i].y, point[i].z ) ; + glPopName () ; + } + + glPopMatrix(); + glFlush(); + + long hits = glRenderMode ( GL_RENDER ) ; // Back to Rendering mode, get number of hits + + if ( hits ) + point_no->setValue ( (int)buffer[3] ) ; + + printf ( "Active point %d %d %ld\n", mouse_x, mouse_y, hits ) ; + + glMatrixMode ( GL_MODELVIEW ); // got set to GL_PROJECTION earlier +} + +// Point Number Input Widget Down Callback + +static void point_no_down_cb ( puObject *ob ) +{ + printf ( "Calling the down callback with full data: %d\n", picked_point ) ; + if ( picked_point < 0 ) + { + printf ( "Value too small, setting it to zero\n" ) ; + picked_point = 0 ; + } + + if ( picked_point > NUMBER_POINTS - 1 ) + { + printf ( "Value too big, setting it to %d\n", NUMBER_POINTS - 1 ) ; + picked_point = NUMBER_POINTS - 1 ; + } + + point_no->setValue ( picked_point ) ; +} + +// Move Point Button Callback + +static void move_point_cb ( puObject *ob ) +{ + point[picked_point].x += 0.1f ; + if ( point[picked_point].x > 1.0 ) + { + point[picked_point].x = -1.0 ; + point[picked_point].y += 0.1f ; + } +} + +static void exit_cb ( puObject * ) +{ + fprintf ( stderr, "Exiting PUI demo program.\n" ) ; + exit ( 1 ) ; +} + + +int main ( int argc, char **argv ) +{ + firsttime = TRUE; + picked_point = 0 ; + + // Set up the window + + glutInitWindowPosition( 100, 0 ) ; + glutInitWindowSize ( 640, 480 ) ; + glutInit ( &argc, argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + main_window = glutCreateWindow ( "Point Picker PUI Application" ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; + glutPassiveMotionFunc ( motionfn ) ; + glutIdleFunc ( displayfn ) ; + + puInit () ; + +#ifdef VOODOO + puShowCursor () ; +#endif + + // Set up the font + + //tim = new fntTexFont ; + //tim -> load ( "../fnt/data/old/times_medium.txf" ) ; + //puFont times_medium ( tim, 15, 0.3f ) ; + //puSetDefaultFonts ( times_medium, times_medium ) ; + puSetDefaultStyle ( PUSTYLE_SMALL_SHADED ) ; + puSetDefaultColourScheme ( 0.1f, 0.8f, 0.1f, 1.0f) ; + + // Set up the widgets in the window + + instruction = new puText ( 10, 450 ) ; + instruction -> setColour ( PUCOL_LABEL, 1.0, 1.0, 1.0 ) ; + instruction -> setLabel ( "Enter a point number in the input box, or\n" + "left-click in the input box and right-click on a point." ) ; + + point_no = new puInput ( 150, 60, 240, 80 ) ; + point_no->setValuator ( &picked_point ) ; + point_no->setLabel ( "Point Number" ) ; + point_no->setLabelPlace ( PUPLACE_LEFT_CENTER ) ; + point_no->setCallback ( point_no_up_cb ) ; + point_no->setActiveCallback ( point_no_active_cb ) ; + point_no->setDownCallback ( point_no_down_cb ) ; + + move_point = new puOneShot ( 10, 10, 250, 50 ) ; + move_point->setLegend ( "Move Selected Point" ) ; + move_point->setCallback ( move_point_cb ) ; + move_point->makeReturnDefault ( TRUE ) ; + + exit_button = new puButton ( 260, 10, 360, 50 ) ; + exit_button->setLegend ( "Exit" ) ; + exit_button->setCallback ( exit_cb ) ; + exit_button->setStyle ( PUSTYLE_BOXED ) ; + exit_button->setLegendPlace ( PUPLACE_CENTERED_LEFT ) ; + + input = new puaLargeInput ( 440, 0, 200, 300, 1, 20, TRUE ) ; + //input->setChildStyle ( PUCLASS_ARROW, PUSTYLE_BOXED ) ; + //input->setChildBorderThickness ( PUCLASS_ARROW, 15 ) ; + input->setValue( "This is a large input box\n" + "This is line two of a large input box\n" + "Line 3\n" + "Line 4\n" + "This is an extremely long line in the large input box, so long it passes the box width\n" + "Line 6\n" + "Line 7\n" + "Line 8\n" + "Line 9\n" + "Line 10\n" + "Line 11\n" + "Line 12\n" + "Line 13\n" + "Line 14\n" + "Line 15\n" + "Line 16\n" + "Line 17\n" + "Line 18\n" + "Line 19\n" + "Line 20\n" + "Line 21\n" + "Line 22\n" + "Line 23\n" + "Line 24\n" + "Line 25\n" + "Line 26\n" + "Line 27\n" + "Line 28\n" + "Line 29\n" + "Line 30\n" ) ; + + glutMainLoop () ; + return 0 ; +} + + diff --git a/examples/src/pui/PointPicker.dsp b/examples/src/pui/PointPicker.dsp new file mode 100644 index 0000000..5cef7ed --- /dev/null +++ b/examples/src/pui/PointPicker.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="PointPicker" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=PointPicker - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "PointPicker.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "PointPicker.mak" CFG="PointPicker - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "PointPicker - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "PointPicker - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "PointPicker - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib pui.lib puAux.lib fnt.lib sg.lib ul.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /machine:I386 /out:"PointPicker.exe" /libpath:"..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "PointPicker - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib pui_d.lib puAux_d.lib fnt_d.lib sg_d.lib ul_d.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /debug /machine:I386 /out:"PointPicker.exe" /pdbtype:sept /libpath:"..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "PointPicker - Win32 Release" +# Name "PointPicker - Win32 Debug" +# Begin Source File + +SOURCE=.\PointPicker.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/pui/complex.cxx b/examples/src/pui/complex.cxx new file mode 100644 index 0000000..8e94822 --- /dev/null +++ b/examples/src/pui/complex.cxx @@ -0,0 +1,636 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: complex.cxx 2099 2006-11-03 20:04:40Z fayjf $ +*/ + + +#include +#include +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#include +#include + +//#define VOODOO 1 + +/***********************************\ +* * +* These are the PUI widget pointers * +* * +\***********************************/ + +static int main_window ; +static puMenuBar *main_menu_bar ; +static puButton *hide_menu_button ; +static puDialogBox *dialog_box ; +static puText *dialog_box_message ; +static puOneShot *dialog_box_ok_button ; +static puText *timer_text ; +static puGroup *mygroup ; +static puInput *input1 ; +static puInput *input2 ; + +static int slider_window ; +static puSlider *rspeedSlider ; +static puSlider *directSlider ; + +static int save_window ; +static puaFileSelector *file_selector ; + +static int coordinate_window ; +static puaBiSlider *x_coordinate ; +static puaTriSlider *y_coordinate ; + +//static fntTexFont *hel ; +//static fntTexFont *tim ; + +/***********************************\ +* * +* This is a generic tumbling cube * +* * +\***********************************/ + +static const GLfloat light_diffuse [] = {0.0, 1.0, 0.0, 1.0} ; /* Red diffuse light. */ +static const GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0} ; /* Infinite light location. */ + +static const 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} +} ; + +static const 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} +} ; + +static const 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; + +static 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 + */ + glEnable ( GL_BLEND ) ; + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glAlphaFunc(GL_GREATER,0.1f); + + 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] ) ; + for ( int j = 0; j < 4; j++ ) + { + float xmult =(float)(x_coordinate->getCurrentMax () - x_coordinate->getCurrentMin ()) / + (float)(x_coordinate->getMaxValue () - x_coordinate->getMinValue ()) ; + float ymult =(float)(y_coordinate->getCurrentMax () - y_coordinate->getCurrentMin ()) / + (float)(y_coordinate->getMaxValue () - y_coordinate->getMinValue ()) ; + + float x = cube_v[cube_i[i][j]][0] * xmult ; + float y = cube_v[cube_i[i][j]][1] * ymult ; + float z = cube_v[cube_i[i][j]][2] ; + glVertex3f ( x, y, z ) ; + } + } + + 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.1f, 0.3f, 0.5f, 1.0f ) ; + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + /* Draw the tumbling cube */ + + float val ; rspeedSlider->getValue ( &val ) ; + float dir ; directSlider->getValue ( &dir ) ; + + glRotatef( 4*val, 3.0f * ( 2.0f * dir - 1.0f ) , 2.0f * ( 1.0f - 2.0f * dir ) , 1.0f ); + + drawCube () ; + + /* Update the 'timer' */ + + time_t t = time ( NULL ) ; + timer_text -> setLabel ( ctime ( & t ) ) ; + + /* Make PUI redraw */ + + puDisplay () ; + + /* Off we go again... */ + + glutSwapBuffers () ; + glutPostRedisplay () ; +} + +static void sliderdisplayfn (void) +{ + /* + Function to display only the slider window + We must set the glut window first or we get an annoying flicker in the main window. + */ + + glutSetWindow ( slider_window ) ; + + /* Clear the screen */ + + glClearColor ( 0.1f, 0.3f, 0.5f, 1.0f ) ; + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + /* Make PUI redraw the slider window */ + + puDisplay ( slider_window ) ; + + /* Off we go again... */ + + glutSwapBuffers () ; + glutPostRedisplay () ; +} + + +static void savedisplayfn (void) +{ + /* + Function to display only the save window + We must set the glut window first or we get an annoying flicker in the main window. + */ + + glutSetWindow ( save_window ) ; + + /* Clear the screen */ + + glClearColor ( 0.1f, 0.1f, 5.0f, 1.0f ) ; + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + /* Make PUI redraw the save window */ + + puDisplay ( save_window ) ; + + /* Off we go again... */ + + glutSwapBuffers () ; + glutPostRedisplay () ; +} + + +static void coorddisplayfn (void) +{ + /* + Function to display only the slider window + We must set the glut window first or we get an annoying flicker in the main window. + */ + + glutSetWindow ( coordinate_window ) ; + + /* Clear the screen */ + + glClearColor ( 0.1f, 0.3f, 0.5f, 1.0f ) ; + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + /* Make PUI redraw the slider window */ + + puDisplay ( coordinate_window ) ; + + /* Off we go again... */ + + glutSwapBuffers () ; + glutPostRedisplay () ; +} + + +/***********************************\ +* * +* Here are the PUI widget callback * +* functions. * +* * +\***********************************/ + +static 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" ) ; + } +} + + +static void go_away_cb ( puObject * ) +{ + // Delete the dialog box when its 'OK' button is pressed. + + puDeleteObject( dialog_box ) ; + dialog_box = NULL ; +} + +static void mk_dialog ( char *fmt, ... ) +{ + static char txt [ PUSTRING_MAX ] ; + + va_list argptr ; + va_start(argptr, fmt) ; + vsprintf( txt, fmt, argptr ) ; + va_end(argptr) ; + + 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 () ; +} + +static void pick_cb ( puObject * ) +{ + char* filename ; + file_selector -> getValue ( &filename ) ; + + //NOTE: interface creation/deletion must be nested + //the old interface must be deleted *before* a new one is created + //otherwise the interface stack will be messed up + puDeleteObject ( file_selector ) ; + file_selector = 0 ; + glutHideWindow () ; + glutSetWindow ( main_window ) ; + + if ( filename[0] != 0 ) + mk_dialog ( "Saving File:\n%s", filename ) ; + else + mk_dialog ( "Save canceled" ) ; +} + +static void savereshapefn ( int w, int h ) +{ + if ( file_selector ) + file_selector->setSize ( w, h ) ; +} + +static void coordreshapefn ( int w, int h ) +{ + x_coordinate->setSize ( 20, h-40 ) ; + y_coordinate->setSize ( 20, h-40 ) ; + y_coordinate->setPosition ( w/2 - 5, 30 ) ; +} + +static void save_cb ( puObject * ) +{ + static int save_count = 0 ; // Number of buttons in file picker + int w = 320, h = 270 ; + glutSetWindow ( save_window ) ; + glutShowWindow () ; + glutReshapeWindow ( w, h ) ; + glutPositionWindow ( ( 640 - w ) / 2, ( 480 - h ) / 2 ) ; + if ( ++save_count > 2 ) save_count = 0 ; + + file_selector = new puaFileSelector ( 0, 0, w, h, save_count, ".", "Pick Place To Save" ) ; + file_selector -> setCallback ( pick_cb ) ; + file_selector->setChildStyle ( PUCLASS_ONESHOT, PUSTYLE_BOXED ) ; + file_selector->setChildBorderThickness ( PUCLASS_ONESHOT, 5 ) ; + file_selector->setChildColour ( PUCLASS_SLIDER, 0, 0.5, 0.5, 0.5 ) ; +} + +static void ni_cb ( puObject * ) +{ + mk_dialog ( "Warning:\nSorry, that function isn't implemented" ) ; +} + +static void about_cb ( puObject * ) +{ + mk_dialog ( "About:\nThis is the PUI 'complex' program" ) ; +} + +static void help_cb ( puObject * ) +{ + mk_dialog ( "Help:\nSorry, no help is available for this demo" ) ; +} + +static void edit_cb ( puObject * ) +{ +} + +static void exit_cb ( puObject * ) +{ + fprintf ( stderr, "Exiting PUI demo program.\n" ) ; + exit ( 1 ) ; +} + +/* Menu bar entries: */ + +static char *file_submenu [] = { "Exit", "Close", "------------", "Print - this is a long entry", "------------", "Save", "New", NULL } ; +static puCallback file_submenu_cb [] = { exit_cb, exit_cb, NULL, ni_cb, NULL, save_cb, ni_cb, NULL } ; + +static char *edit_submenu [] = { "Do nothing", NULL } ; +static puCallback edit_submenu_cb [] = { edit_cb, NULL } ; + +static char *help_submenu [] = { "About...", "Help", NULL } ; +static puCallback help_submenu_cb [] = { about_cb, help_cb, NULL } ; + + +static void sliderCB( puObject *) +{ + glutPostRedisplay(); +} + +static void coordCB( puObject *) +{ + glutPostRedisplay(); +} + +int main ( int argc, char **argv ) +{ + firsttime = TRUE; + + glutInitWindowPosition( 100, 0 ) ; + glutInitWindowSize ( 640, 480 ) ; + glutInit ( &argc, argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + main_window = glutCreateWindow ( "Complex PUI Application" ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; + +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + glutIdleFunc ( displayfn ) ; + + puInit () ; + +#ifdef VOODOO + puShowCursor () ; +#endif + + //hel = new fntTexFont ; + //tim = new fntTexFont ; + //hel -> load ( "../fnt/data/old/helvetica_medium.txf" ) ; + //tim -> load ( "../fnt/data/old/times_medium.txf" ) ; + //puFont helvetica ( hel, 15 ) ; + //puFont times_medium ( tim, 13 ) ; + //puSetDefaultFonts ( helvetica, times_medium ) ; + puSetDefaultStyle ( PUSTYLE_SMALL_SHADED ) ; + puSetDefaultColourScheme ( 0.3f, 0.4f, 0.6f, 1.0f) ; + + 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 the Menu" ) ; + hide_menu_button->setCallback ( hide_menu_cb ) ; + // hide_menu_button->setLegendPlace ( PUPLACE_CENTER ) ; + 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 () ; + + mygroup = new puGroup ( 40, 40 ) ; + input1 = new puInput ( 10, 70, 90, 90 ) ; + input2 = new puInput ( 10, 40, 90, 60 ) ; + mygroup->close () ; + + slider_window = glutCreateWindow ( "Slider Window" ) ; + glutPositionWindow ( 20, 100 ) ; + glutReshapeWindow ( 150, 200 ) ; + glutDisplayFunc ( sliderdisplayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; + glutPassiveMotionFunc ( motionfn ) ; + glutIdleFunc ( sliderdisplayfn ) ; + + //load the texture for the 2nd window + //hel -> load ( "../fnt/data/old/helvetica_medium.txf" ) ; + //tim -> load ( "../fnt/data/old/times_medium.txf" ) ; + + puGroup *slider_group = new puGroup ( 0, 0 ) ; // Necessary so that "sliderdisplayfn" will draw all widgets + + rspeedSlider = new puSlider (10,30,150,TRUE); + rspeedSlider->setDelta(0.1f); + rspeedSlider->setCBMode( PUSLIDER_DELTA ); + rspeedSlider->setCallback(sliderCB); + rspeedSlider->setLabel ( "Speed" ) ; + rspeedSlider->setLabelPlace ( PUPLACE_BOTTOM_LEFT ) ; + rspeedSlider->setValue ( 0.8f ) ; + + directSlider = new puSlider (80,30,150,TRUE); + directSlider->setDelta(0.1f); + directSlider->setCBMode( PUSLIDER_DELTA ); + directSlider->setCallback(sliderCB); + directSlider->setLabel ( "Direction" ) ; + directSlider->setLabelPlace ( PUPLACE_BOTTOM_LEFT ) ; + + slider_group -> close () ; + + save_window = glutCreateWindow ( "Saving" ) ; + glutDisplayFunc ( savedisplayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; + glutPassiveMotionFunc ( motionfn ) ; + glutIdleFunc ( savedisplayfn ) ; + glutReshapeFunc ( savereshapefn ) ; + glutHideWindow () ; + + //load the texture for the save window + //hel -> load ( "../fnt/data/old/helvetica_medium.txf" ) ; + //tim -> load ( "../fnt/data/old/times_medium.txf" ) ; + + // Coordinate Selection Window + + coordinate_window = glutCreateWindow ( "Coordinate Window" ) ; + glutPositionWindow ( 420, 100 ) ; + glutReshapeWindow ( 250, 400 ) ; + glutDisplayFunc ( coorddisplayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; + glutPassiveMotionFunc ( motionfn ) ; + glutIdleFunc ( coorddisplayfn ) ; + glutReshapeFunc ( coordreshapefn ) ; + + //load the texture for the 2nd window + //hel -> load ( "../fnt/data/old/helvetica_medium.txf" ) ; + //tim -> load ( "../fnt/data/old/times_medium.txf" ) ; + + puGroup *coordinate_group = new puGroup ( 0, 0 ) ; // Necessary so that "groupdisplayfn" will draw all widgets + + x_coordinate = new puaBiSlider ( 50,10,350,TRUE ) ; + x_coordinate->setMinValue ( -20 ) ; + x_coordinate->setMaxValue ( 20 ) ; + x_coordinate->setCurrentMin ( -20 ) ; + x_coordinate->setCurrentMax ( 20 ) ; +// x_coordinate->setDelta(0.1); +// x_coordinate->setCBMode( PUSLIDER_DELTA ); + x_coordinate->setCallback(coordCB); + x_coordinate->setLabel ( "X-coords" ) ; + x_coordinate->setLabelPlace ( PUPLACE_TOP_CENTERED ) ; + + y_coordinate = new puaTriSlider (200,30,350,TRUE); + y_coordinate->setMinValue ( -20 ) ; + y_coordinate->setMaxValue ( 20 ) ; + y_coordinate->setCurrentMin ( -20 ) ; + y_coordinate->setCurrentMax ( 20 ) ; + y_coordinate->setFreezeEnds ( FALSE ) ; + y_coordinate->setValue ( 0 ) ; +// y_coordinate->setDelta(0.1); +// y_coordinate->setCBMode( PUSLIDER_DELTA ); + y_coordinate->setCallback(coordCB); + y_coordinate->setLabel ( "Y-coords" ) ; + y_coordinate->setLabelPlace ( PUPLACE_BOTTOM_CENTERED ) ; + + coordinate_group -> close () ; + +// hel -> load ( "../fnt/data/old/helvetica_medium.txf" ) ; +// tim -> load ( "../fnt/data/old/times_medium.txf" ) ; + + glutMainLoop () ; + return 0 ; +} + + diff --git a/examples/src/pui/complex.dsp b/examples/src/pui/complex.dsp new file mode 100644 index 0000000..8a6903d --- /dev/null +++ b/examples/src/pui/complex.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="complex" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=complex - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "complex.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "complex.mak" CFG="complex - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "complex - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "complex - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "complex - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib pui.lib puAux.lib fnt.lib sg.lib ul.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /machine:I386 /out:"complex.exe" /libpath:"..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "complex - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib pui_d.lib puAux_d.lib fnt_d.lib sg_d.lib ul_d.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /debug /machine:I386 /out:"complex.exe" /pdbtype:sept /libpath:"..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "complex - Win32 Release" +# Name "complex - Win32 Debug" +# Begin Source File + +SOURCE=.\complex.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/pui/fltk_demo/Makefile b/examples/src/pui/fltk_demo/Makefile new file mode 100644 index 0000000..721bb3b --- /dev/null +++ b/examples/src/pui/fltk_demo/Makefile @@ -0,0 +1,25 @@ +# -*-Makefile-*- $Id: Makefile 1877 2004-02-25 11:01:31Z stromberg $ + + +CXXFLAGS = $(shell fltk-config --use-gl --cxxflags) -Wall -O2 -DPU_USE_FLTK +LDFLAGS = $(shell fltk-config --use-gl --ldflags) -lplibpu -lplibfnt -lplibul + +OBJS = main.o gui.o puf.o + + +fltk_demo: $(OBJS) + g++ $(OBJS) $(LDFLAGS) -o $@ + +clean: + rm -f gui.{h,cxx} *.o *~ + + +%.o: %.cxx + g++ $(CXXFLAGS) -c $< + +%.h %.cxx: %.fl + fluid -c $< + + +main.o gui.o: gui.h puf.h +puf.o: puf.h diff --git a/examples/src/pui/fltk_demo/gui.fl b/examples/src/pui/fltk_demo/gui.fl new file mode 100644 index 0000000..1e19020 --- /dev/null +++ b/examples/src/pui/fltk_demo/gui.fl @@ -0,0 +1,48 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0104 +header_name {.h} +code_name {.cxx} +Function {make_window()} {open +} { + Fl_Window main_window { + label {fluid window} open + xywh {544 347 265 285} type Double hide + } { + Fl_Box gl_area {selected + xywh {15 50 235 180} labelsize 12 align 1 + code0 {\#include "puf.h"} + class Puf_Window + } + Fl_Menu_Bar {} {open + xywh {0 0 265 20} labelsize 12 textsize 12 + } { + submenu {} { + label File open + xywh {0 0 100 20} labelsize 12 + } { + menuitem {} { + label Quit + callback {exit(0);} + xywh {0 0 100 20} labelsize 12 + code0 {\#include } + } + } + submenu {} { + label Edit open + xywh {0 0 100 20} labelsize 12 + } {} + submenu {} { + label View open + xywh {15 15 100 20} labelsize 12 + } {} + } + Fl_Box {} { + label {OpenGL Area} + xywh {15 30 235 20} labelfont 1 labelsize 12 + } + Fl_Button toggle_other { + label {Show / Hide} + xywh {70 250 120 25} labelsize 12 + } + } +} diff --git a/examples/src/pui/fltk_demo/main.cxx b/examples/src/pui/fltk_demo/main.cxx new file mode 100644 index 0000000..d79a2a6 --- /dev/null +++ b/examples/src/pui/fltk_demo/main.cxx @@ -0,0 +1,143 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: main.cxx 1877 2004-02-25 11:01:31Z stromberg $ +*/ + + +#include "puf.h" +#include "gui.h" +#include + + +static Puf_Window *window1; +static Puf_Window *window2; + +static puButton *button1; +static puButton *button2; + +static puInput *input1; +static puInput *input2; + + +static void hello_cb(puObject *o) +{ + puInput *i = (o == button1 ? input1 : input2); + char *s = 0; + i->getValue(&s); + fprintf(stderr, "[Window %d] Hello: %s\n", o == button1 ? 1 : 2, s); +} + + +static void toggle_cb(puObject *o) +{ + if (main_window->visible()) + main_window->hide(); + else + main_window->show(); +} + + +static void quit_cb(puObject *o) +{ + main_window->hide(); + window1->hide(); +} + + +static void init_pui() +{ + window1->make_current(); + + puInit(); + + new puGroup(0, 0); + puButton *b = new puOneShot(50, 50, 200, 80); + b->setLegend("Show / Hide"); + b->setCallback(toggle_cb); + button1 = new puOneShot(50, 120, 200, 150); + button1->setLegend("Say Hello"); + button1->setCallback(hello_cb); + input1 = new puInput(50, 170, 200, 200); + puMenuBar *menu = new puMenuBar(); + char *menu_text[] = { "Quit", "----", "----", NULL }; + puCallback menu_cb[] = { quit_cb, NULL, NULL }; + char *dummy_text[] = { "----", NULL }; + puCallback dummy_cb[] = { NULL }; + menu->add_submenu("File", menu_text, menu_cb); + menu->add_submenu("Edit", dummy_text, dummy_cb); + menu->add_submenu("View", dummy_text, dummy_cb); + menu->close(); + puPopGroup(); + + window2->make_current(); + + new puInterface(0, 0); + new puGroup(0, 0); + button2 = new puOneShot(50, 50, 200, 80); + button2->setLegend("Say Hello"); + button2->setCallback(hello_cb); + input2 = new puInput(50, 100, 200, 130); + puPopGroup(); +} + + +static void toggle_fl(Fl_Widget *widget, void *data) +{ + if (window1->visible()) + window1->hide(); + else + window1->show(); +} + + +// This is for debugging, to see that redraw occurs when it should. +static void refresh(void *data) +{ + window1->redraw(); + window2->redraw(); + Fl::repeat_timeout(2.0, refresh); +} + + +int main(int argc, char **argv) +{ + window1 = new Puf_Window(250, 270, "OpenGL Window"); + window1->show(); + + make_window()->show(); + window2 = gl_area; + + init_pui(); + + toggle_other->callback(toggle_fl); + Fl::add_timeout(3.0, refresh); + + return Fl::run(); +} + + +/* + Local Variables: + mode: C++ + c-basic-offset: 4 + c-file-offsets: ((substatement-open 0) (case-label 0)) + End: +*/ diff --git a/examples/src/pui/fltk_demo/puf.cxx b/examples/src/pui/fltk_demo/puf.cxx new file mode 100644 index 0000000..808c0f8 --- /dev/null +++ b/examples/src/pui/fltk_demo/puf.cxx @@ -0,0 +1,186 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puf.cxx 1877 2004-02-25 11:01:31Z stromberg $ +*/ + + +#include "puf.h" +#include +#include + + +int puf_translate_key(int key) +{ + const short xtab[][2] = { + { FL_BackSpace, '\b' }, + { FL_Tab, '\t' }, + { FL_Enter, '\r' }, + { FL_Escape, 0x1b }, + { FL_Home, PU_KEY_HOME }, + { FL_Left, PU_KEY_LEFT }, + { FL_Up, PU_KEY_UP }, + { FL_Right, PU_KEY_RIGHT }, + { FL_Down, PU_KEY_DOWN }, + { FL_Page_Up, PU_KEY_PAGE_UP }, + { FL_Page_Down, PU_KEY_PAGE_DOWN }, + { FL_End, PU_KEY_END }, + { FL_Insert, PU_KEY_INSERT }, + { FL_KP + 0, '0' }, + { FL_KP + 1, '1' }, + { FL_KP + 2, '2' }, + { FL_KP + 3, '3' }, + { FL_KP + 4, '4' }, + { FL_KP + 5, '5' }, + { FL_KP + 6, '6' }, + { FL_KP + 7, '7' }, + { FL_KP + 8, '8' }, + { FL_KP + 9, '9' }, + { FL_KP_Enter, '\r' }, + { FL_F + 1, PU_KEY_F1 }, + { FL_F + 2, PU_KEY_F2 }, + { FL_F + 3, PU_KEY_F3 }, + { FL_F + 4, PU_KEY_F4 }, + { FL_F + 5, PU_KEY_F5 }, + { FL_F + 6, PU_KEY_F6 }, + { FL_F + 7, PU_KEY_F7 }, + { FL_F + 8, PU_KEY_F8 }, + { FL_F + 9, PU_KEY_F9 }, + { FL_F + 10, PU_KEY_F10 }, + { FL_F + 11, PU_KEY_F11 }, + { FL_F + 12, PU_KEY_F12 }, + { FL_Delete, 0x7f }, + }; + + static short xmap[256] = { 0 }; + + if (xmap[ FL_BackSpace & 0xff ] == 0) { + for (unsigned i = 0; i < sizeof(xtab) / sizeof(xtab[0]); i++) + xmap[ xtab[i][0] & 0xff ] = xtab[i][1]; + } + + return key <= 0xff ? key : key >= 0xff00 ? xmap[ key & 0xff ] : 0; +} + + +int puf_handle_event(Fl_Gl_Window *window, int event) +{ + int n, ret = 1; + + switch (event) { + + case FL_PUSH: + case FL_RELEASE: + window->make_current(); + ret = puMouse(Fl::event_button() - 1, event == FL_PUSH ? PU_DOWN : PU_UP, + Fl::event_x(), Fl::event_y()); + window->redraw(); + break; + + case FL_DRAG: + window->make_current(); + ret = puMouse(Fl::event_x(), Fl::event_y()); + window->redraw(); + break; + + case FL_ENTER: + window->take_focus(); + break; + + case FL_FOCUS: + case FL_UNFOCUS: + window->redraw(); + break; + + case FL_KEYDOWN: + case FL_KEYUP: + n = Fl::event_length(); + ret = 0; + if (Fl::event_key() <= 0xff && n > 0) { + const char *s = Fl::event_text(); + window->make_current(); + for (int i = 0; i < n; i++) + ret |= puKeyboard(s[i], event == FL_KEYDOWN ? PU_DOWN : PU_UP); + } else { + int key = puf_translate_key(Fl::event_key()); + if (key != 0) { + window->make_current(); + ret = puKeyboard(key, event == FL_KEYDOWN ? PU_DOWN : PU_UP); + } + } + if (ret != 0) + window->redraw(); + break; + + default: + ret = 0; + } + + return ret; +} + + +int Puf_Window::handle(int event) +{ + return puf_handle_event(this, event) || Fl_Gl_Window::handle(event); +} + + +void Puf_Window::draw() +{ + if (!valid()) + glViewport(0, 0, w(), h()); + + glClear(GL_COLOR_BUFFER_BIT); + +#if 1 // draw a border showing current focus + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, w(), 0, h(), -1, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + float c = (Fl::focus() == this ? 0.9f : 0.5f); + glColor3f(c, c, c); + + float x0 = 0.5f, x1 = w() - 0.5f; + float y0 = 0.5f, y1 = h() - 0.5f; + + glBegin(GL_LINE_LOOP); + glVertex2f(x0, y0); + glVertex2f(x1, y0); + glVertex2f(x1, y1); + glVertex2f(x0, y1); + glEnd(); + +#endif + + puDisplay(); +} + + +/* + Local Variables: + mode: C++ + c-basic-offset: 4 + c-file-offsets: ((substatement-open 0) (case-label 0)) + End: +*/ diff --git a/examples/src/pui/fltk_demo/puf.h b/examples/src/pui/fltk_demo/puf.h new file mode 100644 index 0000000..5a72cf7 --- /dev/null +++ b/examples/src/pui/fltk_demo/puf.h @@ -0,0 +1,61 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puf.h 1877 2004-02-25 11:01:31Z stromberg $ +*/ + + +#ifndef puf_h +#define puf_h + +#include + + +// Functions for passing FLTK events to PUI + +int puf_translate_key(int key_code); +int puf_handle_event(Fl_Gl_Window *, int event); + + +// An FLTK window class for simple PUI integration + +class Puf_Window : public Fl_Gl_Window +{ + protected: + virtual int handle(int); + virtual void draw(); + public: + Puf_Window(int X, int Y, int W, int H, const char *L = 0) + : Fl_Gl_Window(X, Y, W, H, L) {} + Puf_Window(int W, int H, const char *L = 0) + : Fl_Gl_Window(W, H, L) {} +}; + + +#endif + + +/* + Local Variables: + mode: C++ + c-basic-offset: 4 + c-file-offsets: ((substatement-open 0) (case-label 0)) + End: +*/ diff --git a/examples/src/pui/sdl_example/Demo.cxx b/examples/src/pui/sdl_example/Demo.cxx new file mode 100644 index 0000000..4379006 --- /dev/null +++ b/examples/src/pui/sdl_example/Demo.cxx @@ -0,0 +1,75 @@ +#include +#include +#include + +#include "Demo.h" + + +static puInput* input = NULL; + + + +static void on_quit(puObject*) +{ + exit(0); +} + +static void on_say_hello(puObject*) +{ + printf("Hello World!\n"); +} + +static void on_print_text(puObject*) +{ + printf("Input text: %s\n", input->getStringValue()); +} + + + +void initPUI() +{ + puInit(); + + puSetDefaultStyle(PUSTYLE_SMALL_BEVELLED); + puSetDefaultColourScheme(0.75f, 0.75f, 0.75f, 1.0f); +} + + +void createInterface() +{ + // menu bar + puMenuBar* menu = new puMenuBar(); + char* menu_text[] = { + "Quit", + "----", + "Say Hello", + "Print text", + NULL + }; + puCallback menu_cb[] = { + on_quit, + NULL, + on_say_hello, + on_print_text, + NULL + }; + menu->add_submenu("Demo", menu_text, menu_cb); + menu->close(); + + // input and buttons + puButton* button; + button = new puOneShot(100, 200, 220, 225); + button->setLegend("Quit"); + button->setCallback(on_quit); + + button = new puOneShot(100, 250, 220, 275); + button->setLegend("Say Hello"); + button->setCallback(on_say_hello); + + button = new puOneShot(100, 300, 220, 325); + button->setLegend("Print text"); + button->setCallback(on_print_text); + + input = new puInput(250, 300, 450, 325); +} + diff --git a/examples/src/pui/sdl_example/Demo.h b/examples/src/pui/sdl_example/Demo.h new file mode 100644 index 0000000..efa6a29 --- /dev/null +++ b/examples/src/pui/sdl_example/Demo.h @@ -0,0 +1,10 @@ +#ifndef DEMO_H +#define DEMO_H + + +void initPUI(); + +void createInterface(); + + +#endif diff --git a/examples/src/pui/sdl_example/EventLoopSDL.cxx b/examples/src/pui/sdl_example/EventLoopSDL.cxx new file mode 100644 index 0000000..c1eefe4 --- /dev/null +++ b/examples/src/pui/sdl_example/EventLoopSDL.cxx @@ -0,0 +1,180 @@ +#include +#include +#include + +#include "EventLoopSDL.h" + + +static bool stop_requested; + + + +void EventLoopSDL::run() +{ + SDL_Event event; + + stop_requested = false; + while (!stop_requested) { + + // process events + SDL_WaitEvent(NULL); + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + stop_requested = true; + break; + case SDL_MOUSEMOTION: + onMouseMove(event.motion.state, event.motion.x, event.motion.y); + break; + case SDL_MOUSEBUTTONDOWN: + onMouseDown(event.button.button, event.button.x, event.button.y); + break; + case SDL_MOUSEBUTTONUP: + onMouseUp(event.button.button, event.button.x, event.button.y); + break; + case SDL_KEYDOWN: + onKeyDown(event.key.keysym); + break; + case SDL_KEYUP: + onKeyUp(event.key.keysym); + break; + } + } + + // redraw + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + draw(); + SDL_GL_SwapBuffers(); + } +} + + +void EventLoopSDL::stop() +{ + stop_requested = true; +} + + +void EventLoopSDL::draw() +{ + puDisplay(); +} + + +int EventLoopSDL::translateKey(const SDL_keysym& keysym) +{ + // Printable characters + if (keysym.unicode > 0) + return keysym.unicode; + + // Numpad key, translate no non-numpad equivalent + if (keysym.sym >= SDLK_KP0 && keysym.sym <= SDLK_KP_EQUALS) { + switch (keysym.sym) { + case SDLK_KP0: + return PU_KEY_INSERT; + case SDLK_KP1: + return PU_KEY_END; + case SDLK_KP2: + return PU_KEY_DOWN; + case SDLK_KP3: + return PU_KEY_PAGE_DOWN; + case SDLK_KP4: + return PU_KEY_LEFT; + case SDLK_KP6: + return PU_KEY_RIGHT; + case SDLK_KP7: + return PU_KEY_HOME; + case SDLK_KP8: + return PU_KEY_UP; + case SDLK_KP9: + return PU_KEY_PAGE_UP; + default: + return -1; + } + } + + // Everything else + switch (keysym.sym) { + case SDLK_UP: + return PU_KEY_UP; + case SDLK_DOWN: + return PU_KEY_DOWN; + case SDLK_LEFT: + return PU_KEY_LEFT; + case SDLK_RIGHT: + return PU_KEY_RIGHT; + + case SDLK_PAGEUP: + return PU_KEY_PAGE_UP; + case SDLK_PAGEDOWN: + return PU_KEY_PAGE_DOWN; + case SDLK_HOME: + return PU_KEY_HOME; + case SDLK_END: + return PU_KEY_END; + case SDLK_INSERT: + return PU_KEY_INSERT; + case SDLK_DELETE: + return -1; + + case SDLK_F1: + return PU_KEY_F1; + case SDLK_F2: + return PU_KEY_F2; + case SDLK_F3: + return PU_KEY_F3; + case SDLK_F4: + return PU_KEY_F4; + case SDLK_F5: + return PU_KEY_F5; + case SDLK_F6: + return PU_KEY_F6; + case SDLK_F7: + return PU_KEY_F7; + case SDLK_F8: + return PU_KEY_F8; + case SDLK_F9: + return PU_KEY_F9; + case SDLK_F10: + return PU_KEY_F10; + case SDLK_F11: + return PU_KEY_F11; + case SDLK_F12: + return PU_KEY_F12; + + default: + return -1; + } +} + +int EventLoopSDL::translateMouse(int btn) +{ + // SDL counts buttons from 1, PUI from 0 + return btn-1; +} + + +int EventLoopSDL::onMouseMove(char state, int x, int y) +{ + return false; +} + +int EventLoopSDL::onMouseDown(int btn, int x, int y) +{ + return puMouse(translateMouse(btn), PU_DOWN, x, y); +} + +int EventLoopSDL::onMouseUp(int btn, int x, int y) +{ + return puMouse(translateMouse(btn), PU_UP, x, y); +} + +int EventLoopSDL::onKeyDown(const SDL_keysym& keysym) +{ + return puKeyboard(translateKey(keysym), PU_DOWN); +} + +int EventLoopSDL::onKeyUp(const SDL_keysym& keysym) +{ + return puKeyboard(translateKey(keysym), PU_UP); +} diff --git a/examples/src/pui/sdl_example/EventLoopSDL.h b/examples/src/pui/sdl_example/EventLoopSDL.h new file mode 100644 index 0000000..d8da91f --- /dev/null +++ b/examples/src/pui/sdl_example/EventLoopSDL.h @@ -0,0 +1,32 @@ +#ifndef EVENTLOOPSDL_H +#define EVENTLOOPSDL_H + + +class EventLoopSDL +{ +public: + // starts the main loop + static void run(); + + // requests main loop termination + static void stop(); + + // draw one frame + static void draw(); + + // translates an SDL keysym to the PUI equivalent + static int translateKey(const SDL_keysym& keysym); + + // translates an SDL mouse button to the PUI equivalent + static int translateMouse(int btn); + + // event handlers + static int onMouseMove(char state, int x, int y); + static int onMouseDown(int btn, int x, int y); + static int onMouseUp(int btn, int x, int y); + static int onKeyDown(const SDL_keysym& keysym); + static int onKeyUp(const SDL_keysym& keysym); +}; + + +#endif diff --git a/examples/src/pui/sdl_example/Makefile b/examples/src/pui/sdl_example/Makefile new file mode 100644 index 0000000..df0bc8d --- /dev/null +++ b/examples/src/pui/sdl_example/Makefile @@ -0,0 +1,38 @@ +SDL_LDFLAGS := $(shell sdl-config --libs) +OGL_LDFLAGS := -lGL -lGLU +PUI_LDFLAGS := -lplibpu -lplibfnt -lplibsg -lplibul +LDFLAGS := $(OGL_LDFLAGS) $(SDL_LDFLAGS) $(PUI_LDFLAGS) -lm + +SDL_CFLAGS := $(shell sdl-config --cflags) +PUI_CFLAGS := -DPU_USE_SDL +CXXFLAGS := -Wall -g $(SDL_CFLAGS) $(PUI_CFLAGS) + +CXX := g++ + + +OBJECT := mainSDL.o EventLoopSDL.o Demo.o + + +%.o : %.cxx + $(CXX) $(CXXFLAGS) -c $< + + +sdl_example: $(OBJECT) + $(CXX) -o $@ $+ $(LDFLAGS) + + +.PHONY: clean depend + +clean: + rm -f *.o sdl_example + +depend: + makedepend -Y *.cxx >/dev/null 2>&1 + + +# Do 'make depend' to regenerate dependencies. +# DO NOT DELETE + +Demo.o: Demo.h +EventLoopSDL.o: EventLoopSDL.h +mainSDL.o: Demo.h EventLoopSDL.h diff --git a/examples/src/pui/sdl_example/mainSDL.cxx b/examples/src/pui/sdl_example/mainSDL.cxx new file mode 100644 index 0000000..d43af52 --- /dev/null +++ b/examples/src/pui/sdl_example/mainSDL.cxx @@ -0,0 +1,58 @@ +#include +#include +#include "SDL.h" + +#include "Demo.h" +#include "EventLoopSDL.h" + + +// default window size +static const int WIDTH = 640; +static const int HEIGHT = 480; + + +static void initSDL(int w, int h, const char *title) +{ + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); + exit(1); + } + atexit(SDL_Quit); + + if (SDL_SetVideoMode(w, h, 0, SDL_OPENGL | SDL_ANYFORMAT/* | SDL_FULLSCREEN*/) == NULL) { + fprintf(stderr, "Unable to create OpenGL screen: %s\n", SDL_GetError()); + exit(1); + } + + if (title) + SDL_WM_SetCaption(title, NULL); + + SDL_EnableKeyRepeat(150, 75); + SDL_EnableUNICODE(true); +} + + +void initOGL(int w, int h) +{ + glViewport(0, 0, w, h); + glClearColor(0.1f, 0.4f, 0.1f, 1.0f); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glAlphaFunc(GL_GREATER, 0.1f); +} + + +int main(int argc, char *argv[]) +{ + initSDL(WIDTH, HEIGHT, "PUI with SDL sample"); + initOGL(WIDTH, HEIGHT); + initPUI(); + + createInterface(); + + EventLoopSDL::run(); + + return 0; +} + diff --git a/examples/src/pui/simple.cxx b/examples/src/pui/simple.cxx new file mode 100644 index 0000000..9aace3b --- /dev/null +++ b/examples/src/pui/simple.cxx @@ -0,0 +1,131 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: simple.cxx 1551 2002-09-01 12:04:53Z ude $ +*/ + + +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#include + +//#define VOODOO 1 + +void motionfn ( int x, int y ) +{ + puMouse ( x, y ) ; + glutPostRedisplay () ; +} + +void mousefn ( int button, int updown, int x, int y ) +{ + puMouse ( button, updown, x, y ) ; + glutPostRedisplay () ; +} + +void displayfn ( void ) +{ + glClearColor ( 0.1f, 0.4f, 0.1f, 1.0f ) ; + glClear ( GL_COLOR_BUFFER_BIT ) ; + + puDisplay () ; + + glutSwapBuffers () ; + + /* The next line is not neccessary - you could remove it safely without + affecting the functionality of this simple example program. + + It exists because in every application which does some more stuff + than creating user interface widgets, you normally do want to + redraw your scenery as often as possible for smooth animation. */ + + glutPostRedisplay () ; +} + +void button_cb ( puObject * ) +{ + fprintf ( stderr, "Hello World.\n" ) ; +} + + +int main ( int argc, char **argv ) +{ +#ifdef VOODOO + glutInitWindowPosition ( 0, 0 ) ; +#endif + glutInitWindowSize ( 640, 480 ) ; + glutInit ( &argc, argv ) ; + + /* Note that in order for PUI and this example program to work, you + definitely don't need a depth buffer. + + However, most applications using PUI do some more things than rendering + PUI widgets. In every "real" program, you usually do need a depth + buffer - we are requesting one in the next line so that PLIB programmers + can write their applications upon this example code without running + into problems. */ + + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + + glutCreateWindow ( "PUI Application" ) ; + glutDisplayFunc ( displayfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; + +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + puInit () ; + +#ifdef VOODOO + puShowCursor () ; +#endif + + puOneShot *b = new puOneShot ( 50, 50, 200, 80 ) ; + + b -> setLegend ( "Say Hello" ) ; + b -> setCallback ( button_cb ) ; + +printf ( "%d\n", PLIB_VERSION ) ; + + glutMainLoop () ; + + return 0 ; +} + diff --git a/examples/src/pui/simple.dsp b/examples/src/pui/simple.dsp new file mode 100644 index 0000000..a8bdb29 --- /dev/null +++ b/examples/src/pui/simple.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="simple" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=simple - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "simple.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "simple.mak" CFG="simple - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "simple - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "simple - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "simple - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib pui.lib fnt.lib sg.lib ul.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /machine:I386 /out:"simple.exe" /libpath:"..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "simple - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib pui_d.lib fnt_d.lib sg_d.lib ul_d.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /debug /machine:I386 /out:"simple.exe" /pdbtype:sept /libpath:"..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "simple - Win32 Release" +# Name "simple - Win32 Debug" +# Begin Source File + +SOURCE=.\simple.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/pui/widget_list.cxx b/examples/src/pui/widget_list.cxx new file mode 100644 index 0000000..9e453ee --- /dev/null +++ b/examples/src/pui/widget_list.cxx @@ -0,0 +1,684 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: widget_list.cxx 2143 2009-01-21 17:18:45Z fayjf $ +*/ + +// Sample program to create a copy of each widget in PUI + +#include +#include +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#include +#include + +//#define VOODOO 1 + +/***********************************\ +* * +* These are the PUI widget pointers * +* * +\***********************************/ + +static int main_window ; + +static int button_box_window ; +static puButtonBox *button_box ; + +static int frame_window ; +static puFrame *frame ; + +static int text_window ; +static puText *text ; + +static int button_window ; +static puButton *button ; +static puText *button_text ; + +static int one_shot_window ; +static puOneShot *one_shot ; + +static int popup_menu_window ; +static puPopupMenu *popup_menu ; + +static int menu_bar_window ; +static puMenuBar *menu_bar ; + +static int input_window ; +static puInput *input ; + +static int slider_window ; +static puSlider *slider ; + +static int arrow_button_window ; +static puArrowButton *arrow_button ; + +static int dial_window ; +static puDial *dial ; + +static int list_box_window ; +static puListBox *list_box ; + +static int file_selector_window ; +static puaFileSelector *file_selector ; + +static int bislider_window ; +static puaBiSlider *bislider ; + +static int trislider_window ; +static puaTriSlider *trislider ; + +static int vertical_menu_window ; +static puaVerticalMenu *vertical_menu ; + +static int dialog_box_window ; +static puDialogBox *dialog_box ; + +static int large_input_window ; +static puaLargeInput *large_input ; + +static int combo_box_window ; +static puaComboBox *combo_box ; + +static int select_box_window ; +static puaSelectBox *select_box ; + +//static fntTexFont *tim ; + + + +/**************************************\ +* * +* 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 btn, int updown, int x, int y ) +{ + puMouse ( btn, updown, x, y ) ; + glutPostRedisplay () ; +} + +/**************************************\ +* * +* This function redisplays the PUI * +* * +\**************************************/ + +static void displayfn (void) +{ + /* Clear the screen */ + + glClearColor ( 0.55f, 0.55f, 0.55f, 1.0f ) ; + glClear ( GL_COLOR_BUFFER_BIT ) ; + + /* Make PUI redraw */ + + puDisplay () ; + + /* Swap buffers */ + + glutSwapBuffers () ; +} + + +/***********************************\ +* * +* Here are the PUI widget callback * +* functions. * +* * +\***********************************/ + +static void exit_cb ( puObject * ) +{ + fprintf ( stderr, "Exiting PUI demo program.\n" ) ; + exit ( 1 ) ; +} + +/* Menu bar entries: */ + +static char *file_submenu [] = { "Exit", "Close", "========", "Print", "========", "Save", "New", NULL } ; +static puCallback file_submenu_cb [] = { exit_cb, exit_cb, NULL, NULL , NULL, NULL, NULL, NULL } ; + +static char *edit_submenu [] = { "Do nothing.", NULL } ; +puCallback edit_submenu_cb [] = { NULL, NULL } ; + +static char *help_submenu [] = { "About...", "Help", NULL } ; +puCallback help_submenu_cb [] = { NULL, NULL, NULL } ; + + +int main ( int argc, char **argv ) +{ + glutInitWindowPosition( 100, 0 ) ; + glutInitWindowSize ( 640, 480 ) ; + glutInit ( &argc, argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE ) ; + main_window = glutCreateWindow ( "PUI Widget List" ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + puInit () ; + +#ifdef VOODOO + puShowCursor () ; +#endif + + //tim = new fntTexFont ; + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + //puFont times_medium ( tim, 12 ) ; + //puSetDefaultFonts ( times_medium, times_medium ) ; + puSetDefaultStyle ( PUSTYLE_SMALL_SHADED ) ; + puSetDefaultColourScheme ( 0.8f, 0.8f, 0.8f, 1.0f ) ; + + + /* Set up the secondary windows and their widgets */ + + button_box_window = glutCreateWindow ( "Button Box Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 180, 100 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + char *button_box_entries [] = { "First Entry", "Second Entry", "Third Entry", NULL } ; + button_box = new puButtonBox ( 10, 10, 130, 80, button_box_entries, TRUE ) ; + button_box->setLabel ( "Label" ) ; + + + frame_window = glutCreateWindow ( "Frame Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 180, 100 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + frame = new puFrame ( 10, 10, 130, 80 ) ; + frame->setLabel ( "Label" ) ; + frame->setLegend ( "Legend" ) ; + + + text_window = glutCreateWindow ( "Text Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 180, 100 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + text = new puText ( 10, 10 ) ; + text->setLabel ( "Label" ) ; + + + button_window = glutCreateWindow ( "Button Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 220, 160 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + button_text = new puText ( 5, 6 ) ; + button_text->setLabel ( "XCHECK:" ) ; + + button = new puButton ( 90, 10, 90+16, 10+16, PUBUTTON_XCHECK ) ; + button->setLabelPlace ( PUPLACE_CENTERED_RIGHT ) ; + button->setLabel ( "Label" ) ; + button->setValue ( 1 ) ; + + button_text = new puText ( 5, 36 ) ; + button_text->setLabel ( "VCHECK:" ) ; + + button = new puButton ( 90, 40, 90+16, 40+16, PUBUTTON_VCHECK ) ; + button->setLabelPlace ( PUPLACE_CENTERED_RIGHT ) ; + button->setLabel ( "Label" ) ; + button->setValue ( 1 ) ; + + button_text = new puText ( 5, 66 ) ; + button_text->setLabel ( "CIRCLE:" ) ; + + button = new puButton ( 90, 70, 90+16, 70+16, PUBUTTON_CIRCLE ) ; + button->setLabelPlace ( PUPLACE_CENTERED_RIGHT ) ; + button->setLabel ( "Label" ) ; + button->setValue ( 1 ) ; + + button_text = new puText ( 5, 96 ) ; + button_text->setLabel ( "RADIO:" ) ; + + button = new puButton ( 90, 100, 90+16, 100+16, PUBUTTON_RADIO ) ; + button->setLabelPlace ( PUPLACE_CENTERED_RIGHT ) ; + button->setLabel ( "Label" ) ; + button->setValue ( 1 ) ; + + button_text = new puText ( 5, 128 ) ; + button_text->setLabel ( "NORMAL:" ) ; + + button = new puButton ( 90, 130, 170, 150 ) ; + button->setLabelPlace ( PUPLACE_CENTERED_RIGHT ) ; + button->setLabel ( "Label" ) ; + button->setLegend ( "Legend" ) ; + button->setValue ( 1 ) ; + + + one_shot_window = glutCreateWindow ( "One Shot Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 180, 100 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + one_shot = new puOneShot ( 10, 10, 90, 30 ) ; + one_shot->setLabel ( "Label" ) ; + one_shot->setLegend ( "Legend" ) ; + + + popup_menu_window = glutCreateWindow ( "Popup Menu Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 80, 100 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + popup_menu = new puPopupMenu ( 10, 10 ) ; + popup_menu->add_item ( "Cut", NULL ) ; + popup_menu->add_item ( "Copy", NULL ) ; + popup_menu->add_item ( "Paste", NULL ) ; + popup_menu->add_item ( "Delete", NULL ) ; + popup_menu->close () ; + popup_menu->reveal () ; + + + menu_bar_window = glutCreateWindow ( "Menu Bar Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 180, 200 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + menu_bar = new puMenuBar () ; + { + menu_bar -> add_submenu ( "File", file_submenu, file_submenu_cb ) ; + menu_bar -> add_submenu ( "Edit", edit_submenu, edit_submenu_cb ) ; + menu_bar -> add_submenu ( "Help", help_submenu, help_submenu_cb ) ; + } + menu_bar -> close () ; + + + input_window = glutCreateWindow ( "Input Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 180, 100 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + input = new puInput ( 10, 10, 90, 30 ) ; + input->setLabel ( "Label" ) ; + + + slider_window = glutCreateWindow ( "Slider Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 180, 100 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + slider = new puSlider ( 10, 10, 120, FALSE ) ; + slider->setLabel ( "Label" ) ; + slider->setLegend ( "Legend" ) ; + + + arrow_button_window = glutCreateWindow ( "Arrow Button Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 180, 100 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + arrow_button = new puArrowButton ( 10, 10, 50, 50, PUARROW_RIGHT ) ; + arrow_button->setLabel ( "Label" ) ; + + + dial_window = glutCreateWindow ( "Dial Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 180, 100 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + dial = new puDial ( 10, 10, 60 ) ; + dial->setLabel ( "Label" ) ; + dial->setLegend ( "Legend" ) ; + + + list_box_window = glutCreateWindow ( "List Box Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 180, 100 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + char *list_box_entries [] = { "First Entry", "Second Entry", "Third Entry", "Very long Entry that will get truncated", NULL } ; + list_box = new puListBox ( 10, 10, 130, 80, list_box_entries ) ; + list_box->setLabel ( "Label" ) ; + + + file_selector_window = glutCreateWindow ( "File Selector Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 300, 220 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + file_selector = new puaFileSelector ( 10, 10, 280, 200, "." ) ; + + + bislider_window = glutCreateWindow ( "BiSlider Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 180, 100 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + bislider = new puaBiSlider ( 10, 10, 120, FALSE ) ; + bislider->setLabel ( "Label" ) ; + bislider->setLegend ( "Legend" ) ; + bislider->setMaxValue ( 20 ) ; + bislider->setCurrentMin ( 4 ) ; + bislider->setCurrentMax ( 15 ) ; + + + trislider_window = glutCreateWindow ( "TriSlider Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 100, 200 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + trislider = new puaTriSlider ( 20, 10, 180, TRUE ) ; + trislider->setLabel ( "Label" ) ; + trislider->setLegend ( "Legend" ) ; + trislider->setMaxValue ( 20 ) ; + trislider->setCurrentMin ( 4 ) ; + trislider->setCurrentMax ( 15 ) ; + trislider->setValue ( 12 ) ; + + + vertical_menu_window = glutCreateWindow ( "Vertical Menu Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 180, 200 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + vertical_menu = new puaVerticalMenu () ; + { + vertical_menu -> add_submenu ( "File", file_submenu, file_submenu_cb ) ; + vertical_menu -> add_submenu ( "Edit", edit_submenu, edit_submenu_cb ) ; + vertical_menu -> add_submenu ( "Help", help_submenu, help_submenu_cb ) ; + } + vertical_menu -> close () ; + + + dialog_box_window = glutCreateWindow ( "Dialog Box Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 180, 100 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + dialog_box = new puDialogBox ( 10, 10 ) ; + new puOneShot ( 20, 20, "OK" ) ; + new puOneShot ( 100, 20, "Cancel" ) ; + puText *dialog_text = new puText ( 20, 60 ) ; + dialog_text->setLabel ( "Dialog Box Text\nand Widgets" ) ; + dialog_box->close () ; + dialog_box->reveal () ; + + + large_input_window = glutCreateWindow ( "Large Input Window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 300, 200 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + large_input = new puaLargeInput ( 10, 10, 240, 180, 2, 20 ) ; + large_input->setLabel ( "Label" ) ; + large_input->setValue ( "This is text in the Large Input widget.\n" + "This is a second line of text" ) ; + + + combo_box_window = glutCreateWindow ( "Combo Box window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 300, 200 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + char *combo_box_entries [] = { "First Entry", "Second Entry", "Third Entry", "Fourth Entry", "Sixth Entry", "Seventh Entry", NULL } ; + combo_box = new puaComboBox ( 10, 158, 250, 190, + combo_box_entries ) ; + /* Don't do that in your own application ! */ + combo_box -> __getPopupMenu() -> reveal() ; + combo_box->setLabel ( "Label" ) ; + + + select_box_window = glutCreateWindow ( "Select Box window" ) ; + glutPositionWindow ( 200, 100 ) ; + glutReshapeWindow ( 300, 60 ) ; + glutDisplayFunc ( displayfn ) ; + glutKeyboardFunc ( keyfn ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; +#ifdef VOODOO + glutPassiveMotionFunc ( motionfn ) ; +#endif + + //tim -> load ( "../fnt/data/old/times_bold.txf" ) ; + + glEnable ( GL_BLEND ) ; + glAlphaFunc ( GL_GEQUAL, 0.1f ) ; + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; + + select_box = new puaSelectBox ( 10, 14, 250, 46, + combo_box_entries ) ; + select_box->setLabel ( "Label" ) ; + + glutMainLoop () ; + return 0 ; +} + + diff --git a/examples/src/pui/widget_list.dsp b/examples/src/pui/widget_list.dsp new file mode 100644 index 0000000..0e7a92d --- /dev/null +++ b/examples/src/pui/widget_list.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="widget_list" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=widget_list - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "widget_list.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "widget_list.mak" CFG="simple - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "widget_list - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "widget_list - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "widget_list - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib pui.lib puAux.lib fnt.lib sg.lib ul.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /machine:I386 /out:"widget_list.exe" /libpath:"..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "widget_list - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib pui_d.lib puAux_d.lib fnt_d.lib sg_d.lib ul_d.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /debug /machine:I386 /out:"widget_list.exe" /pdbtype:sept /libpath:"..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "widget_list - Win32 Release" +# Name "widget_list - Win32 Debug" +# Begin Source File + +SOURCE=.\widget_list.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/pui/widget_test.cxx b/examples/src/pui/widget_test.cxx new file mode 100644 index 0000000..a90a253 --- /dev/null +++ b/examples/src/pui/widget_test.cxx @@ -0,0 +1,219 @@ +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#include + + +int margin = 50; + +char *long_text; +puObject *widget; + + + +// samples + +char text[] = + "This program is meant to be used for widget testing. Insert your code\n" + "between BEGIN and END marks. Use list, long_list, text and long_text\n" + "as widget contents where appropriate. It's intended that there are no resizing\n" + "limits. This allows to verify that the widget works even in insanely small\n" + "sizes, or at least doesn't crash then.\n" + "\n" + "Some random parts from the pui documentation:\n" + "\n" + "Like the constructors of the previously described widgets, the puComboBox\n" + "constructor takes a NULL-terminated array of strings specifying the items\n" + "that should go into the widget as it's fourth parameter. If 'editable'\n" + "is TRUE (default), the input box is made editable for allowing the user\n" + "to enter a string in addition to selecting one of the entries from the\n" + "popup menu.\n" + "\n" + "Depending on the position of the puComboBox inside the window, the widget\n" + "automatically determines whether the popup menu should be shown above or\n" + "below the widget when the user clicks on the arrow. The puArrowButton\n" + "is either pointing in up or down direction to indicate where the menu will\n" + "pop up.\n" + "\n" + "Regardless of whether you passed TRUE or FALSE to the 'editable' parameter\n" + "when constructing the widget, the user can click inside the input box and\n" + "use the Up and Down keys to browse through the items. The Home and End\n" + "keys switch to the first or last item as you would expect, and the PgUp/PgDown\n" + "can be used to toggle the popup menu.\n" + "\n" + "Just like all other classes which store a pointer to an array of strings\n" + "that indicates the widget's elements, the puComboBox class provides a routine\n" + "that allows you to change the list of elements in mid-run - and you can\n" + "also retrieve the number of items.\n"; + +char *list[] = { + "puArrowButton", "puButton", "puButtonBox", "puDial", "puFrame", + "puGroup", "puInput", "puInterface", "puListBox", "puMenuBar", + "puObject", "puOneShot", "puPopup", "puPopupMenu", "puSlider", + "puText", "puValue", 0}; + +char *long_list[] = { + "PUARROW_DOWN", "PUARROW_FASTDOWN", "PUARROW_FASTLEFT", "PUARROW_FASTRIGHT", + "PUARROW_FASTUP", "PUARROW_LEFT", "PUARROW_RIGHT", "PUARROW_UP", + "PUBUTTON_CIRCLE", "PUBUTTON_NORMAL", "PUBUTTON_RADIO", "PUBUTTON_VCHECK", + "PUBUTTON_XCHECK", "PUCLASS_ARROW", "PUCLASS_BUTTON", "PUCLASS_BUTTONBOX", + "PUCLASS_DIAL", "PUCLASS_DIALOGBOX", "PUCLASS_FRAME", "PUCLASS_GROUP", + "PUCLASS_INPUT", "PUCLASS_INTERFACE", "PUCLASS_LISTBOX", "PUCLASS_MENUBAR", + "PUCLASS_OBJECT", "PUCLASS_ONESHOT", "PUCLASS_POPUP", "PUCLASS_POPUPMENU", + "PUCLASS_SLIDER", "PUCLASS_TEXT", "PUCLASS_VALUE", "PUCOL_BACKGROUND", + "PUCOL_EDITFIELD", "PUCOL_FOREGROUND", "PUCOL_HIGHLIGHT", "PUCOL_LABEL", + "PUCOL_LEGEND", "PUCOL_MAX", "PUCOL_MISC", "PUDEACTIVATE_ON_MOUSE_CLICK", + "PUDEACTIVATE_ON_NEXT_WIDGET_ACTIVATION", "PUPLACE_ABOVE", + "PUPLACE_ABOVE_LEFT", "PUPLACE_ABOVE_RIGHT", "PUPLACE_BELOW", + "PUPLACE_BELOW_LEFT", "PUPLACE_BELOW_RIGHT", "PUPLACE_BOTTOM_CENTER", + "PUPLACE_BOTTOM_CENTERED", "PUPLACE_BOTTOM_LEFT", "PUPLACE_BOTTOM_RIGHT", + "PUPLACE_CENTERED", "PUPLACE_CENTERED_CENTERED", "PUPLACE_CENTERED_LEFT", + "PUPLACE_CENTERED_RIGHT", "PUPLACE_DEFAULT", "PUPLACE_LABEL_DEFAULT", + "PUPLACE_LEFT", "PUPLACE_LEFT_CENTER", "PUPLACE_LEGEND_DEFAULT", + "PUPLACE_LOWER_LEFT", "PUPLACE_LOWER_RIGHT", "PUPLACE_RIGHT", + "PUPLACE_RIGHT_CENTER", "PUPLACE_TOP_CENTER", "PUPLACE_TOP_CENTERED", + "PUPLACE_TOP_LEFT", "PUPLACE_TOP_RIGHT", "PUPLACE_UPPER_LEFT", + "PUPLACE_UPPER_RIGHT", "PUSLIDER_ALWAYS", "PUSLIDER_CLICK", + "PUSLIDER_DELTA", "PUSTRING_INITIAL", "PUSTRING_MAX", "PUSTR_BGAP", + "PUSTR_LGAP", "PUSTR_RGAP", "PUSTR_TGAP", "PUSTYLE_BEVELLED", + "PUSTYLE_BOXED", "PUSTYLE_DEFAULT", "PUSTYLE_DROPSHADOW", "PUSTYLE_MAX", + "PUSTYLE_NONE", "PUSTYLE_PLAIN", "PUSTYLE_RADIO", "PUSTYLE_SHADED", + "PUSTYLE_SMALL_BEVELLED", "PUSTYLE_SMALL_SHADED", "PUSTYLE_SPECIAL_UNDERLINED", + "PU_CONTINUAL", "PU_DOWN", "PU_DRAG", "PU_KEY_DOWN", "PU_KEY_END", "PU_KEY_F1", + "PU_KEY_F10", "PU_KEY_F11", "PU_KEY_F12", "PU_KEY_F2", "PU_KEY_F3", + "PU_KEY_F4", "PU_KEY_F5", "PU_KEY_F6", "PU_KEY_F7", "PU_KEY_F8", "PU_KEY_F9", + "PU_KEY_GLUT_SPECIAL_OFFSET", "PU_KEY_HOME", "PU_KEY_INSERT", "PU_KEY_LEFT", + "PU_KEY_PAGE_DOWN", "PU_KEY_PAGE_UP", "PU_KEY_RIGHT", "PU_KEY_UP", + "PU_LEFT_BUTTON", "PU_MIDDLE_BUTTON", "PU_NOBUTTON", "PU_RADIO_BUTTON_SIZE", + "PU_RIGHT_BUTTON", "PU_UP", "PU_UP_AND_DOWN", 0}; + + + + +// callback functions + +void motionfn(int x, int y) +{ + puMouse(x, y); + glutPostRedisplay(); +} + + +void mousefn(int button, int updown, int x, int y) +{ + puMouse(button, updown, x, y); + glutPostRedisplay(); +} + + +void specialfn(int key, int, int) +{ + printf("SPECIAL=%d\n", key); + puKeyboard(key + PU_KEY_GLUT_SPECIAL_OFFSET, PU_DOWN); + glutPostRedisplay(); +} + + +void keyfn(unsigned char key, int, int) +{ + printf("KEY=%d\n", key); + puKeyboard(key, PU_DOWN); + glutPostRedisplay(); + if (key == 27) + exit(0); +} + + +void displayfn(void) +{ + glClearColor(0.4f, 0.4f, 0.4f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + puDisplay(); + glutSwapBuffers(); + glutPostRedisplay(); +} + + +void reshapefn(int w, int h) +{ + widget->setSize(w - 2 * margin, h - 2 * margin); +} + + +void callback(puObject *object) +{ + printf("callback value: [%s]\n", object->getStringValue()); +} + + +void atexitfn(void) +{ + delete [] long_text; +} + + + + +int main(int argc, char **argv) +{ + printf("PLIB Version %d\n", PLIB_VERSION); + + atexit(atexitfn); + const int REPEAT = 10; + long_text = new char[REPEAT * strlen(text) + REPEAT + 1]; + long_text[0] = '\0'; + for (int i = 0; i < REPEAT; i++) { + strcat(long_text, text); + strcat(long_text, "\n"); + } + + glutInitWindowSize(640, 480); + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH); + glutCreateWindow("PUI Application"); + glutDisplayFunc(displayfn); + glutMouseFunc(mousefn); + glutKeyboardFunc(keyfn); + glutSpecialFunc(specialfn); + glutMotionFunc(motionfn); + glutReshapeFunc(reshapefn); + + puSetDefaultStyle(PUSTYLE_SMALL_SHADED); + puInit(); + // + //-- BEGIN ---------------------------------------------------------------------- + + + margin = 50; + + widget = new puaLargeInput(margin, margin, 420, 400, 11, 20, false); + widget->setValue(text); + widget->setCallback(callback); + + + //-- END ------------------------------------------------------------------------ + // + int w, h; + widget->getSize(&w, &h); + glutReshapeWindow(w + 2 * margin, h + 2 * margin); + glutMainLoop(); + return 0; +} + diff --git a/examples/src/pui/widget_test.dep b/examples/src/pui/widget_test.dep new file mode 100644 index 0000000..7f75fa3 --- /dev/null +++ b/examples/src/pui/widget_test.dep @@ -0,0 +1,2 @@ +# Microsoft Developer Studio Generated Dependency File, included by widget_test.mak + diff --git a/examples/src/pui/widget_test.dsp b/examples/src/pui/widget_test.dsp new file mode 100644 index 0000000..2c5ae7d --- /dev/null +++ b/examples/src/pui/widget_test.dsp @@ -0,0 +1,101 @@ +# Microsoft Developer Studio Project File - Name="widget_test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=widget_test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "widget_test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "widget_test.mak" CFG="widget_test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "widget_test - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "widget_test - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +F90=df.exe +RSC=rc.exe + +!IF "$(CFG)" == "widget_test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE F90 /compile_only /nologo /warn:nofileopt +# ADD F90 /compile_only /nologo /warn:nofileopt +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "widget_test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "widget_test___Win32_Debug" +# PROP BASE Intermediate_Dir "widget_test___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "widget_test___Win32_Debug" +# PROP Intermediate_Dir "widget_test___Win32_Debug" +# PROP Target_Dir "" +# ADD BASE F90 /check:bounds /compile_only /dbglibs /debug:full /nologo /traceback /warn:argument_checking /warn:nofileopt +# ADD F90 /check:bounds /compile_only /dbglibs /debug:full /nologo /traceback /warn:argument_checking /warn:nofileopt +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "widget_test - Win32 Release" +# Name "widget_test - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/examples/src/pui/widget_test.mak b/examples/src/pui/widget_test.mak new file mode 100644 index 0000000..92ef5ea --- /dev/null +++ b/examples/src/pui/widget_test.mak @@ -0,0 +1,143 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on widget_test.dsp +!IF "$(CFG)" == "" +CFG=widget_test - Win32 Debug +!MESSAGE No configuration specified. Defaulting to widget_test - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "widget_test - Win32 Release" && "$(CFG)" != "widget_test - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "widget_test.mak" CFG="widget_test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "widget_test - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "widget_test - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +CPP=cl.exe +F90=df.exe +RSC=rc.exe + +!IF "$(CFG)" == "widget_test - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release + +ALL : + + +CLEAN : + -@erase + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +F90_PROJ=/compile_only /nologo /warn:nofileopt /module:"Release/" /object:"Release/" +F90_OBJS=.\Release/ +CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\widget_test.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\widget_test.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\widget_test.pdb" /machine:I386 /out:"$(OUTDIR)\widget_test.exe" +LINK32_OBJS= \ + + +!ELSEIF "$(CFG)" == "widget_test - Win32 Debug" + +OUTDIR=.\widget_test___Win32_Debug +INTDIR=.\widget_test___Win32_Debug + +ALL : + + +CLEAN : + -@erase + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +F90_PROJ=/check:bounds /compile_only /dbglibs /debug:full /nologo /traceback /warn:argument_checking /warn:nofileopt /module:"widget_test___Win32_Debug/" /object:"widget_test___Win32_Debug/" /pdbfile:"widget_test___Win32_Debug/DF60.PDB" +F90_OBJS=.\widget_test___Win32_Debug/ +CPP_PROJ=/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\widget_test.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\widget_test.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\widget_test.pdb" /debug /machine:I386 /out:"$(OUTDIR)\widget_test.exe" /pdbtype:sept +LINK32_OBJS= \ + + +!ENDIF + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.SUFFIXES: .fpp + +.for{$(F90_OBJS)}.obj: + $(F90) $(F90_PROJ) $< + +.f{$(F90_OBJS)}.obj: + $(F90) $(F90_PROJ) $< + +.f90{$(F90_OBJS)}.obj: + $(F90) $(F90_PROJ) $< + +.fpp{$(F90_OBJS)}.obj: + $(F90) $(F90_PROJ) $< + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("widget_test.dep") +!INCLUDE "widget_test.dep" +!ELSE +!MESSAGE Warning: cannot find "widget_test.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "widget_test - Win32 Release" || "$(CFG)" == "widget_test - Win32 Debug" + +!ENDIF + diff --git a/examples/src/pui/widget_test.plg b/examples/src/pui/widget_test.plg new file mode 100644 index 0000000..1f30dc9 --- /dev/null +++ b/examples/src/pui/widget_test.plg @@ -0,0 +1,33 @@ + + +
+

Build Log

+

+--------------------Configuration: widget_test - Win32 Debug-------------------- +

+

Command Lines

+Creating temporary file "C:\DOCUME~1\fayjf\LOCALS~1\Temp\c\RSP7C.tmp" with contents +[ +/nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"Debug/widget_test.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c +"V:\dev\PilgrimWork\plib_svn\trunk\examples\src\pui\widget_test.cxx" +] +Creating command line "cl.exe @C:\DOCUME~1\fayjf\LOCALS~1\Temp\c\RSP7C.tmp" +Creating temporary file "C:\DOCUME~1\fayjf\LOCALS~1\Temp\c\RSP7D.tmp" with contents +[ +kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib pui_d.lib puAux_d.lib fnt_d.lib sg_d.lib ul_d.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /incremental:yes /pdb:"Debug/widget_test.pdb" /debug /machine:I386 /out:"widget_test.exe" /pdbtype:sept /libpath:"..\..\..\..\plib" +.\Debug\widget_test.obj +] +Creating command line "link.exe @C:\DOCUME~1\fayjf\LOCALS~1\Temp\c\RSP7D.tmp" +

Output Window

+Compiling... +widget_test.cxx +v:\dev\pilgrimwork\plib_svn\trunk\examples\src\pui\widget_test.cxx(17) : fatal error C1083: Cannot open include file: 'GL/glut.h': No such file or directory +Error executing cl.exe. + + + +

Results

+widget_test.exe - 1 error(s), 0 warning(s) +
+ + diff --git a/examples/src/pw/Makefile.am b/examples/src/pw/Makefile.am new file mode 100644 index 0000000..d025721 --- /dev/null +++ b/examples/src/pw/Makefile.am @@ -0,0 +1,14 @@ +if BUILD_PW + +noinst_PROGRAMS = pw_demo pw_pui + +pw_demo_SOURCES = pw_demo.cxx +pw_pui_SOURCES = pw_pui.cxx + +pw_demo_LDADD = -lplibpw -lplibul $(OGL_LIBS) +pw_pui_LDADD = -lplibpw -lplibpu -lplibfnt -lplibsg -lplibul $(OGL_LIBS) + +endif + +EXTRA_DIST = pw_demo.dsp + diff --git a/examples/src/pw/pw_demo.cxx b/examples/src/pw/pw_demo.cxx new file mode 100644 index 0000000..f483e16 --- /dev/null +++ b/examples/src/pw/pw_demo.cxx @@ -0,0 +1,104 @@ + +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#include +#include +#include +#include +#include +#include + +void exFunc () +{ + fprintf ( stderr, "Exiting.\n" ) ; + pwCleanup () ; + exit ( 0 ) ; +} + + +void rsFunc ( int w, int h ) +{ + fprintf ( stderr, "Resized to %d x %d\n", w, h ) ; +} + + +void mpFunc ( int x, int y ) +{ + fprintf ( stderr, "Mouse is at (%4dx%4d)\r", x, y ) ; +} + + +void msFunc ( int button, int updn, int x, int y ) +{ + fprintf ( stderr, "Mouse button %d dirn %d at (%4dx%4d)\n", + button, updn, x, y ) ; +} + + +char keyIsDown [ 512 ] = { 0 } ; + +void kbFunc ( int key, int updn, int x, int y ) +{ + fprintf ( stderr, "Keyboard key %d dirn %d at (%4dx%4d) ", + key, updn, x, y ) ; + + keyIsDown [ key ] = (updn==PW_DOWN) ; + + for ( int i = 0 ; i < 512 ; i++ ) + if ( keyIsDown [ i ] ) + { + if ( i > ' ' && i < 0x7F ) + fprintf ( stderr, "%c ", i ) ; + else + fprintf ( stderr, "0x%2x ", i ) ; + } + + fprintf ( stderr, "\n" ) ; + + if ( updn == PW_DOWN ) + { + if ( key == '<' ) pwSetSize ( 100, 100 ) ; + else + if ( key == '>' ) pwSetSize ( 640, 480 ) ; + else + if ( key == 'a' ) pwSetAutoRepeatKey ( true ) ; + else + if ( key == 'b' ) pwSetAutoRepeatKey ( false ) ; + + if ( key == 0x1B ) /* ESC */ + { + pwCleanup () ; + exit ( 0 ) ; + } + } +} + + +int main ( int, char ** ) +{ + printf ( "PLIB/PW Demo.\n" ) ; + printf ( "=============\n\n" ) ; + printf ( "Type or mouse in the window to see PW callbacks in action.\n" ) ; + printf ( "Hit '<' or '>' to resize the window from within the program.\n" ) ; + printf ( "Hit 'a' or 'b' to enable or disable auto key repeat.\n" ) ; + printf ( "Hit ESC to exit.\n" ) ; + printf ( "\n" ) ; + + pwInit ( 100, 100, 640, 480, false, "PLIB Window Demo", true, 0 ) ; + + pwSetCallbacks ( kbFunc, msFunc, mpFunc, rsFunc, exFunc ) ; + + while ( 1 ) + { + glClearColor ( 0.5f, 0.1f, 0.1f, 1.0 ) ; + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + pwSwapBuffers () ; + } + + return 0; +} + + diff --git a/examples/src/pw/pw_demo.dsp b/examples/src/pw/pw_demo.dsp new file mode 100644 index 0000000..278b0e2 --- /dev/null +++ b/examples/src/pw/pw_demo.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="pw_demo" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=pw_demo - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "pw_demo.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "pw_demo.mak" CFG="pw_demo - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "pw_demo - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "pw_demo - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "pw_demo - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0xc09 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ul.lib pw.lib opengl32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "pw_demo - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "pw_demo___Win32_Debug" +# PROP BASE Intermediate_Dir "pw_demo___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0xc09 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ul_d.lib pw_d.lib opengl32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "pw_demo - Win32 Release" +# Name "pw_demo - Win32 Debug" +# Begin Source File + +SOURCE=.\pw_demo.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/pw/pw_pui.cxx b/examples/src/pw/pw_pui.cxx new file mode 100644 index 0000000..8b1b4ef --- /dev/null +++ b/examples/src/pw/pw_pui.cxx @@ -0,0 +1,75 @@ + +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#include +#include +#include +#include +#include +#include // This needs to be before +#include + +void exFunc () +{ + fprintf ( stderr, "Exiting.\n" ) ; + pwCleanup () ; + exit ( 0 ) ; +} + + +void rsFunc ( int w, int h ) +{ + fprintf ( stderr, "Resized to %d x %d\n", w, h ) ; +} + + +void mpFunc ( int x, int y ) +{ + puMouse ( x, y ) ; +} + + +void msFunc ( int button, int updn, int x, int y ) +{ + puMouse ( button, updn, x, y ) ; +} + + +void kbFunc ( int key, int updn, int x, int y ) +{ + puKeyboard ( key, updn, x, y ) ; +} + + +void button_cb ( puObject * ) +{ + fprintf ( stderr, "Hello World.\n" ) ; +} + + +int main ( int, char ** ) +{ + pwInit ( 100, 100, 640, 480, false, "PLIB Window Demo", true, 0 ) ; + puInit () ; + + puOneShot *b = new puOneShot ( 50, 50, 200, 80 ) ; + + b -> setLegend ( "Say Hello" ) ; + b -> setCallback ( button_cb ) ; + + pwSetCallbacks ( kbFunc, msFunc, mpFunc, rsFunc, exFunc ) ; + while ( 1 ) + { + glClearColor ( 0.5f, 0.1f, 0.1f, 1.0f ) ; + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + puDisplay () ; + pwSwapBuffers () ; + } + + return 0; +} + + diff --git a/examples/src/pw/pw_pui.dsp b/examples/src/pw/pw_pui.dsp new file mode 100644 index 0000000..4056dc3 --- /dev/null +++ b/examples/src/pw/pw_pui.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="pw_pui" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=pw_pui - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "pw_pui.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "pw_pui.mak" CFG="pw_pui - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "pw_pui - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "pw_pui - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "pw_pui - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0xc09 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sg.lib fnt.lib pui.lib ul.lib pw.lib opengl32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "pw_pui - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0xc09 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sg_d.lib fnt_d.lib pui_d.lib ul_d.lib pw_d.lib opengl32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "pw_pui - Win32 Release" +# Name "pw_pui - Win32 Debug" +# Begin Source File + +SOURCE=.\pw_pui.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/sg/Makefile.am b/examples/src/sg/Makefile.am new file mode 100644 index 0000000..004ec69 --- /dev/null +++ b/examples/src/sg/Makefile.am @@ -0,0 +1,12 @@ +if BUILD_SG + +noinst_PROGRAMS = sg_quat_test + +sg_quat_test_SOURCES = sg_quat_test.cxx + +sg_quat_test_LDADD = -lplibsg -lplibul $(GLUT_LIBS) $(OGL_LIBS) + +endif + +EXTRA_DIST = sg_quat_test.dsp + diff --git a/examples/src/sg/sg_quat_test.cxx b/examples/src/sg/sg_quat_test.cxx new file mode 100644 index 0000000..6258afb --- /dev/null +++ b/examples/src/sg/sg_quat_test.cxx @@ -0,0 +1,287 @@ +/* + This is a demonstration of Quaternion vs. Euler rotation + + The cube on the left uses Euler rotation. The cube on + the right uses Quaternion rotation. As you can see the + Euler cube is in midst of a gimble-lock-death-throw, + while the Quaternion cube is happily spinning away. + + I have setup two rows of keys to control the cubes rotations. + + Quaternion Rotation Toggles: + q - toggle X axis rotation + w - toggle Y axis rotation + e - toggle Z axis rotation + r - reset quaternion to initial state + t - untoggle all rotations + + Euler Rotation Toggles: + a - toggle X axis rotation + s - toggle Y axis rotation + d - toggle Z axis rotation + f - reset euler to initial state + g - untoggle all rotations + + ESC exits + + Written by Michael Kurth (kurth@futurekill.com) (negative0@earthlink.net) +*/ +#ifdef WIN32 +# include +#else +# include +#endif + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#include + +#define XSIZE 320 +#define YSIZE 320 + +static sgVec3 Euler ; +static sgVec3 EulerPos ; +static sgVec3 EulerRot ; + +static sgVec3 Quat ; +static sgVec3 QuatPos ; +static sgQuat QuatRot ; + +static const GLfloat cube_vertices[] = +{ + -1.0, -1.0, 1.0, 1.0, 0.0, 0.0, + 1.0, -1.0, 1.0, 0.5, 0.5, 0.0, + 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, + -1.0, 1.0, 1.0, 0.0, 0.5, 0.5, + -1.0, -1.0, -1.0, 0.0, 0.0, 1.0, + 1.0, -1.0, -1.0, 0.5, 0.0, 0.5, + 1.0, 1.0, -1.0, 1.0, 0.0, 0.0, + -1.0, 1.0, -1.0, 0.5, 0.5, 0.0 +} ; + +static const GLubyte frontIndices[] = { 0, 1, 2, 3 } ; +static const GLubyte backIndices[] = { 5, 4, 7, 6 } ; + +static const GLubyte rightIndices[] = { 1, 5, 6, 2 } ; +static const GLubyte leftIndices[] = { 4, 0, 3, 7 } ; + +static const GLubyte topIndices[] = { 3, 2, 6, 7 } ; +static const GLubyte bottomIndices[] = { 4, 5, 1, 0 } ; + +static void InitEulerCube( ) +{ + sgSetVec3( Euler, 1, 1, 1 ) ; + sgSetVec3( EulerRot, 0, 0, 0 ) ; + sgSetVec3( EulerPos, -2, 0, -5 ) ; +} + +static void RotateEulerCube( ) +{ + if( Euler[ SG_X ] ) + { + EulerRot[ SG_X ] += 5.0 ; + if( EulerRot[ SG_X ] > 360. ) + EulerRot[ SG_X ] = 0.0 ; + } + + if( Euler[ SG_Y ] ) + { + EulerRot[ SG_Y ] += 5.0 ; + if( EulerRot[ SG_Y ] > 360. ) + EulerRot[ SG_Y ] = 0.0 ; + } + + if( Euler[ SG_Z ] ) + { + EulerRot[ SG_Z ] += 5.0 ; + if( EulerRot[ SG_Z ] > 360. ) + EulerRot[ SG_Z ] = 0.0 ; + } + +} + +static void InitQuatCube( ) +{ + sgSetVec3( Quat, 1, 1, 1 ) ; + sgMakeIdentQuat( QuatRot ) ; + sgSetVec3( QuatPos, 2, 0, -5 ) ; +} + +static void RotateQuatCube( ) +{ + if( Quat[ SG_X ] ) + sgRotQuat( QuatRot, 5.0, 1.0, 0.0, 0.0 ) ; + + if( Quat[ SG_Y ] ) + sgRotQuat( QuatRot, 5.0, 0.0, 1.0, 0.0 ) ; + + if( Quat[ SG_Z ] ) + sgRotQuat( QuatRot, 5.0, 0.0, 0.0, 1.0 ) ; +} + + +static void DrawCube( ) +{ + glDrawElements( GL_QUADS, 4, GL_UNSIGNED_BYTE, frontIndices ) ; + glDrawElements( GL_QUADS, 4, GL_UNSIGNED_BYTE, backIndices ) ; + glDrawElements( GL_QUADS, 4, GL_UNSIGNED_BYTE, rightIndices ) ; + glDrawElements( GL_QUADS, 4, GL_UNSIGNED_BYTE, leftIndices ) ; + glDrawElements( GL_QUADS, 4, GL_UNSIGNED_BYTE, topIndices ) ; + glDrawElements( GL_QUADS, 4, GL_UNSIGNED_BYTE, bottomIndices ) ; +} + +static void Redisplay( void ) +{ + sgMat4 matrix ; + + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + glLoadIdentity( ) ; + glTranslatef( 0, 0, -5 ) ; + + glPushMatrix( ) ; + { + glTranslatef( QuatPos[ SG_X ], QuatPos[ SG_Y ], QuatPos[ SG_Z ] ) ; + + sgQuatToMatrix( matrix, QuatRot ) ; + glMultMatrixf( (float*)matrix ) ; + + DrawCube( ) ; + } + glPopMatrix( ) ; + + glPushMatrix( ) ; + { + glTranslatef( EulerPos[ SG_X ], EulerPos[ SG_Y ], EulerPos[ SG_Z ] ) ; + + sgMakeRotMat4( matrix, EulerRot ) ; + glMultMatrixf( (float*)matrix ) ; + + DrawCube( ) ; + } + glPopMatrix( ) ; + + + glutSwapBuffers( ) ; +} + +static void Idle( ) +{ + static int lastTime = 0; + int time = glutGet((GLenum)GLUT_ELAPSED_TIME); + if (time > lastTime + 10) + { + RotateQuatCube( ) ; + RotateEulerCube( ) ; + + lastTime = time; + } + glutPostRedisplay( ) ; +} + +static void Keyboard( unsigned char key, int xPos, int yPos ) +{ + switch( key ) + { + case 27: + exit( 0 ) ; + case 'q': + Quat[ SG_X ] = !Quat[ SG_X ] ; + break ; + case 'w': + Quat[ SG_Y ] = !Quat[ SG_Y ] ; + break ; + case 'e': + Quat[ SG_Z ] = !Quat[ SG_Z ] ; + break ; + case 'r': + InitQuatCube( ) ; + break ; + case 't': + sgSetVec3( Quat, 0, 0, 0 ) ; + break ; + + case 'a': + Euler[ SG_X ] = !Euler[ SG_X ] ; + break ; + case 's': + Euler[ SG_Y ] = !Euler[ SG_Y ] ; + break ; + case 'd': + Euler[ SG_Z ] = !Euler[ SG_Z ] ; + break ; + case 'f': + InitEulerCube( ) ; + break ; + case 'g': + sgSetVec3( Euler, 0, 0, 0 ) ; + break ; + } +} + +static void Reshape( int w, int h ) +{ + + if( h == 0 ) + { + h = 1 ; + } + + glViewport( 0, 0, w, h ) ; + + glMatrixMode( GL_PROJECTION ) ; + glLoadIdentity( ) ; + + gluPerspective( 45.0f, (GLfloat)w / (GLfloat)h, 0.1f, 100.0f ) ; + + glMatrixMode( GL_MODELVIEW ) ; + glLoadIdentity( ) ; +} + +static void Init( void ) +{ + glClearColor( 0.0, 0.0, 0.0, 0.0 ) ; + + glEnable(GL_DEPTH_TEST); + glCullFace(GL_BACK); + glEnable(GL_CULL_FACE); + + glEnableClientState( GL_VERTEX_ARRAY ) ; + glEnableClientState( GL_COLOR_ARRAY ) ; + + glVertexPointer( 3, GL_FLOAT, 6*sizeof(GLfloat), cube_vertices ) ; + glColorPointer( 3, GL_FLOAT, 6*sizeof(GLfloat), &cube_vertices[3] ) ; + + InitEulerCube( ) ; + InitQuatCube( ) ; + + Reshape( XSIZE, YSIZE ) ; +} + +int main( int argc, char **argv ) +{ + glutInit( &argc, argv ) ; + glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH ) ; + glutInitWindowSize( XSIZE, YSIZE ) ; + glutCreateWindow( "Quaternion Demo" ) ; + + Init( ) ; + + glutDisplayFunc( Redisplay ) ; + glutReshapeFunc( Reshape ) ; + glutKeyboardFunc( Keyboard ) ; + glutIdleFunc( Idle ) ; + + glutShowWindow( ) ; + glutMainLoop( ) ; + return 0 ; +} + diff --git a/examples/src/sg/sg_quat_test.dsp b/examples/src/sg/sg_quat_test.dsp new file mode 100644 index 0000000..590e94c --- /dev/null +++ b/examples/src/sg/sg_quat_test.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="sg_quat_test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=sg_quat_test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "sg_quat_test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "sg_quat_test.mak" CFG="sg_quat_test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "sg_quat_test - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "sg_quat_test - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "sg_quat_test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sg.lib ul.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /machine:I386 /out:"sg_quat_test.exe" /libpath:"..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "sg_quat_test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sg_d.lib ul_d.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /debug /machine:I386 /out:"sg_quat_test.exe" /pdbtype:sept /libpath:"..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "sg_quat_test - Win32 Release" +# Name "sg_quat_test - Win32 Debug" +# Begin Source File + +SOURCE=.\sg_quat_test.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/sl/Makefile.am b/examples/src/sl/Makefile.am new file mode 100644 index 0000000..d4a1eec --- /dev/null +++ b/examples/src/sl/Makefile.am @@ -0,0 +1,17 @@ +if BUILD_SL + +noinst_PROGRAMS = example mod_demo playsound + +example_SOURCES = example.cxx +mod_demo_SOURCES = mod_demo.cxx +playsound_SOURCES = playsound.cxx + +example_LDADD = -lplibsm -lplibsl -lplibul $(SND_LIBS) -lm +mod_demo_LDADD = -lplibsm -lplibsl -lplibul $(SND_LIBS) -lm +playsound_LDADD = -lplibsm -lplibsl -lplibul $(SND_LIBS) -lm + +endif + +EXTRA_DIST = cuckoo.au scream.ub wheeee.ub zzap.wav tuxr.mod \ + mod_demo.dsp example.dsp + diff --git a/examples/src/sl/README b/examples/src/sl/README new file mode 100644 index 0000000..d9eb2fc --- /dev/null +++ b/examples/src/sl/README @@ -0,0 +1,18 @@ + +The music 'tuxr.mod' was composed by Matt Thomas +specificially for the TuxKart game - it is used here +for demonstration purposes only. Please don't use +it in your applications. + + +example -- Plays a variety of sounds read from samples on disk plus + it generates a sound in-situ in memory. A good general + sound sample replay example. + +playsound -- Plays any sound sample file that you enter on it's + command line. Much simpler than 'example'. + +mod_demo -- Plays a '.mod' music file. + + -- Steve Baker. + diff --git a/examples/src/sl/cuckoo.au b/examples/src/sl/cuckoo.au new file mode 100644 index 0000000..f5fb009 Binary files /dev/null and b/examples/src/sl/cuckoo.au differ diff --git a/examples/src/sl/example.cxx b/examples/src/sl/example.cxx new file mode 100644 index 0000000..870ce80 --- /dev/null +++ b/examples/src/sl/example.cxx @@ -0,0 +1,118 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: example.cxx 1551 2002-09-01 12:04:53Z ude $ +*/ + + +#include +#include +#include + +/* + Construct a sound scheduler and a mixer. +*/ + +slScheduler sched ( 8000 ) ; +smMixer mixer ( "/dev/mixer" ) ; + +#ifndef M_PI +#define EX_PI 3.1415926535 +#else +#define EX_PI M_PI +#endif + +int main ( int, char ** ) +{ + mixer . setMasterVolume ( 100 ) ; + sched . setSafetyMargin ( 0.128f ) ; + + /* 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 = (float)( sin ( (double) i * 2.0 * EX_PI / (8000.0/ 50.0) ) + + sin ( (double) i * 2.0 * EX_PI / (8000.0/149.0) ) + + sin ( (double) i * 2.0 * EX_PI / (8000.0/152.0) ) + + sin ( (double) i * 2.0 * EX_PI / (8000.0/192.0) ) + ) / 8.0f + 0.5f ; + + /* Convert to unsigned byte */ + + buffer [ i ] = (Uchar) ( level * 255.0f ) ; + } + + /* 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 ( 10.0f ) ; + s2 -> adjustVolume ( 0.5f ) ; + s3 -> adjustVolume ( 0.2f ) ; + s3 -> adjustVolume ( 0.3f ) ; + + /* Play the engine sample continuously. */ + + sched . loopSample ( s ) ; + sched . loopSample ( s4 ) ; + + int tim = 0 ; /* My periodic event timer. */ + + while ( SL_TRUE ) + { + tim++ ; /* Time passes */ + + if ( tim % 140 == 0 ) sched.playSample ( s1 ) ; + + /* + 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 () ; + } + + return 0 ; +} + diff --git a/examples/src/sl/example.dsp b/examples/src/sl/example.dsp new file mode 100644 index 0000000..20fa369 --- /dev/null +++ b/examples/src/sl/example.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="example" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=example - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "example.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "example.mak" CFG="example - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "example - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "example - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "example - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sl.lib ul.lib winmm.lib /nologo /subsystem:console /machine:I386 /out:"example.exe" /libpath:"..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "example - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sl_d.lib ul_d.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /out:"example.exe" /pdbtype:sept /libpath:"..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "example - Win32 Release" +# Name "example - Win32 Debug" +# Begin Source File + +SOURCE=.\example.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/sl/mod_demo.cxx b/examples/src/sl/mod_demo.cxx new file mode 100644 index 0000000..8fa0435 --- /dev/null +++ b/examples/src/sl/mod_demo.cxx @@ -0,0 +1,73 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: mod_demo.cxx 2014 2005-02-01 01:14:13Z sjbaker $ +*/ + + +#include +#include +#include + +/* + Construct a sound scheduler and a mixer. +*/ + + +slScheduler sched ( 44100 ) ; + +void callback ( slSample *, slEvent event, int ) +{ + if ( event == SL_EVENT_COMPLETE ) + exit ( 0 ) ; +} + + +int main ( int argc, char **argv ) +{ + sched . setSafetyMargin ( 0.5 ) ; + + if ( argc == 2 ) + sched . playMusic ( argv[1], 1, SL_SAMPLE_ABORT, 0, callback ) ; + else + sched . loopMusic ( "tuxr.mod" ) ; + + + while ( SL_TRUE ) + { + /* + 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 + + sched . update () ; + } + + return 0 ; +} + diff --git a/examples/src/sl/mod_demo.dsp b/examples/src/sl/mod_demo.dsp new file mode 100644 index 0000000..b4c163d --- /dev/null +++ b/examples/src/sl/mod_demo.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="mod_demo" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=mod_demo - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_demo.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_demo.mak" CFG="mod_demo - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_demo - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "mod_demo - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_demo - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sl.lib ul.lib winmm.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libcd.lib" /out:"mod_demo.exe" /libpath:"..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "mod_demo - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sl_d.lib ul_d.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /out:"mod_demo.exe" /pdbtype:sept /libpath:"..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "mod_demo - Win32 Release" +# Name "mod_demo - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_demo.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/sl/playsound.cxx b/examples/src/sl/playsound.cxx new file mode 100644 index 0000000..9f94268 --- /dev/null +++ b/examples/src/sl/playsound.cxx @@ -0,0 +1,81 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: playsound.cxx 1996 2004-12-29 07:19:40Z sjbaker $ +*/ + + +#include +#include +#include + +/* + Construct a sound scheduler and a mixer. +*/ + +slScheduler sched ( 8000 ) ; +smMixer mixer ( "/dev/mixer" ) ; + +#ifndef M_PI +#define EX_PI 3.1415926535 +#else +#define EX_PI M_PI +#endif + +int main ( int argc, char **argv ) +{ + mixer . setMasterVolume ( 100 ) ; + sched . setSafetyMargin ( 0.128f ) ; + + /* Set up the samples and a loop */ + + slSample *s1 = new slSample ( argv[1], & sched ) ; + + s1 -> adjustVolume ( 10.0f ) ; + + sched . loopSample ( s1 ) ; + + int tim = 0 ; /* My periodic event timer. */ + + while ( SL_TRUE ) + { + tim++ ; /* Time passes */ + +#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 () ; + } + + return 0 ; +} + + diff --git a/examples/src/sl/scream.ub b/examples/src/sl/scream.ub new file mode 100644 index 0000000..80d41b6 --- /dev/null +++ b/examples/src/sl/scream.ub @@ -0,0 +1 @@ +~~~€‚€€~~€€€€€~€~€€€€€€‚€}~€‚ƒ‚ƒ~||„„„€‚€}y|ƒŠ†‚~||}z{‡ŒŒ€zy€ƒsn{•“xip…Ž{wmƒ‘ˆwŠ„xˆ‡h„Š“‹wz|}Œ€…‡†ik~“{px|…‡~‡‡‚ot„‹€w}{†|‹„vjnŒwu}{†|‚ŠpoŠˆwx{ƒŠ†‹ƒwl‚‹‡xt}|…|ˆ€|ymŠ‹Œt||‡…Š}~xtˆ”‘†n{w~„‰ywjx‘„t}|€„‚Š}qp“†‡uw}€ƒƒ€…jx’€—}„}…„Žsnn’€r}~ƒ‚}ƒ€€|w‹…ƒ}x€~ƒ€{}†r‡ˆŠw‰zŒ†}~so~–‡‹p€ƒ„€€u{y‰€|}y‚ˆ€€„„rrˆ~„ptˆ†xry”yŒ|ƒ„ˆ…}|‚„}t‚€‚{x…‡w|~}q~Œv~jz†…‹p}r}’€|yƒ‡‚‚ƒƒmx}‚prˆ„Žtu€r„™y‰m‡‡‰v„m›t{o†||y{Œ|xt‘uxy‹Ž€|t‡vr›x„mu„€‰p}‚„˜{r†…}„{‡{t–y{r{І†y|wŒ †osŠ~xu{zz‚€q}‡ƒ†~€vrƒŽ~k}†‰ƒv‚v”–}€pˆƒ€}x…uw‰x‚vˆ‚uz}u˜‰vzm€‚Šwy{•‰sƒŠ†}w|„v”Œ|~y†‚‚€ws„‰„kqƒ‡xtŽp‹…yt€Š‰{w|ŒŠ}n„ŠŒvs€v—†~utz„ˆ‚„z†}n…ŠŽxp€„„z‘†zs†‹„|xtŠz‡…|x{z‚sz”…my‚ˆ…pz’zpz„„oz†€xu‘Œus…†‰zx~–‘{yq†Œ†{pƒ††p„…‚„r„„‚}sw•‚{ls”„ny„y{Š~‰rv|„Š|~yˆŽƒuqŠ“‰unzˆz‹ƒzqvƒ†€ˆuy†…~t}…wq~†v†“ƒq~„‡ƒxy”{v}„Š~u~‚‚tw“†|t{†ƒ€z€z–‡zt†ˆŠzt…ƒw†‚ƒvz€ˆ|v†‰~yrƒ‘†zt}†y‹†‚qz„†‚yy‹…~rx‹‡o†s~•}‚q~‹vx‡Œ}px~ކ}rz„xv‰‰{tw‰‹€pt—Ž}wu{އvt}‰‚tŒŠ€~v†††{vx„—~xt„€{sƒw‹‚tp€ŠŒ|r~€†‡vy„~t~‚‚{Š„|wx€Š‡~ovŒ…xv„‹v{†‹zn~yt}†‰vtwŒ˜†ur”†yt|x~„sz}…Š€|t†‰‡vr…pv‚{†’ˆwpx†ˆztˆ’†wt‚”Žwow‹~}“|wsˆ…|x|“‘wrxŽ”pp††w}Š‚yt{†xyx}‹{~†{y}€€s‰”†ym€…ˆxz‚|vˆˆwr€Šƒvx}w‡‡€|u€Šˆ‚ry‹…zv„Ž„xz}ˆws“~rwЇƒx|u–‹wvy‰ˆ„vy‡y~‹ˆ}z{„‰€zwx€vvyŒ‘|u}ˆ‚Œ†{p}‚‰…~}u‰ˆ€uŠr~‚…•ƒ€r|€…‡v‰Ž|pv’“zp€‰„uˆ–|yw†‡…|r‰|zz„Œ„xw……zu……z{xƒ††|n‰“†xqv’{pzzyŠ‚‰puy‹Ž…ss“‡pt‚ƒmy‚zyŽŠxou‹Š„zw…ކ{pvŠvr‡|tŽzsr†‰wv}xxzƒˆ€{wƒ‚~{ˆŠ|sy€‰ˆ~{|z†Šƒ‚}|‚y|sŒ†|ww‡…€z‚‚x{…„}vƒ‹ƒ}w~…’ˆuu‰‚xp†•‹wr‚„‡€}z}†wt€Œ|{z‚~€|v{Žzyx|‡‚ˆx€psˆˆ‡~u}‡‡„ss‘‚{{x‹ƒsv††ƒ|ˆ‹~r~Œ‹}{{{‰‚|x€„‚„€€}t…’ˆ‚u~|ƒ‚|~~•zxt|‡~y|}y|†pyƒŠ…~r~Œ€wx„†€„~z{„zw|ˆŒx|v€—xz{{„Іzxt~ƒvuxŠŽ‰sr„‡‚t„‚yxƒ…‚€{tˆ‡ywxˆ}t|€€’†‰yvwƒ†€}|’}yvy‹’ƒvy…}wŠ„qq~‰†~uu’†}sx„‹tx€‚zy…~rs…ˆŠ}vŠ}zv}wv‚{x’Œ}sr„І{~}‚„~w}†}s|…€{†„vv{‰Œpt‰…{u|‚Œ‡}u€ƒvu’~zrz‰‰wyqŽ‘zz|‰Œtz€~„Žzpt‰ˆ€{yzxŠƒyp†‡ˆwtx€’~€y{Š‚{€‚€{…Š€v~{€‹‚v}z}‘Žvz€ƒx‰„~wxz……uu~zx‡Œ‚vt~……~v‘Œ}xs{‰‹{tx~v}Žyrs„†€y…Ž‚}|u‘|stƒ€wŽ€vp~†‡~‚|…ƒ}}{ƒ“vn„‰{‡’‚}r~‚†€|{’wtx„‚†z{~‚w~zv„‰~y}v}{u}ƒƒ‚|‚|x‹‰€y{Šƒst~x‰—‚t{}Š„t†ˆ}vx~…‚tw~{w„ƒvqz……ƒ|v”ˆ|vv„‚‚‚€y{{’†z|…†w{r‹–}v€ƒ…~zw‡•|xw|ˆ„|z}yw„‹‡€oy‰‰…}tyŒxr|”„yr€ƒw}ˆpvˆŒ‡}uy…xuv”‚p{ƒy…tr‚Š‹~qpˆ|w|‚~‚}|‚‹~z€ƒƒ}}w~Ž~yv|ˆ„‚~‡‚pw†ŒutzŽŠƒw|u{†~w}„†r|’yw~…ƒ~~€|y‰‚y|†}|€|‘|v|…ˆ{vz‹„|z|~„††}}|yt’€}sy‚‡~uˆ“„vƒ€|~…zv‰|xvƒzr}~so~„‰|~ˆwux‘}to†‚€„{qz„†ƒ~u~zx|„ƒ‚~|‚~}Œ~w}…ƒ}}w„’†€|{‹‹x{~v‹”Šxqt„‡ƒ}wƒŒ}r‡•vq€…x‡Šypy„€x†˜ˆrr„……„~x{~|yŽ~yu€ˆ}yyx‚Žy{x|‡}ƒ|ut„tsކrs||„‰……vuy‡†zx~}wy…ŽŠxuyx“‡ytx€„…„sy‡€}w}”‚xo~„}’Žro†…w“stƒ…Šxu…wvЉ€tt‚ˆ„}uz‹€{x~‰€}~€zz}‰{x€Š„{}y‹”‚€wz†}x†•yq‚‹…~t|ƒ‚{ˆ…uv{†……s…’‡|y}Ž‹}uy~wŒ‡tsy‡Š{||‰†~z|}}tw„€w‡’…wn~‰‡zt{Œyvƒˆƒ||€†}x€Š~z|†€|~|t”Œ|xx„„ƒ}w„’‰{wy„†„||‚}|‚}|~†„qsˆ‡zx{†…|y…‰ywŒŒsxŒ„{z}x‚Ž…„vyy‰ƒ‚n}Œ}vz‚†…}z}z‡ˆƒu{€‚‚{}Œ†€{{‡…yv€utˆƒwv}„†|‹‰|y}{‹‡|t~€}…~s|†‹~x{ˆzvy‡„~‚ƒ€}|xu–„xtˆ~t{~ˆ”„~{|€†ƒ~yz†…ƒzz€ƒƒ~|sŠ€xz€ƒ†{|zy€Ž„yu‡‰~zy‚„‡ƒz||……|tv•†}uxˆ‡ƒxz{…Œ‚€}x}Žu‚„„szˆqz„‡~tz‹‚{z|~€ƒ‚‚xuzŽˆvtvŒsyx‘…yzwІ}v‰˜vs‚…‚…u{„ƒz……ys‡Š„u{{’uz{…‡ƒ}„ƒp‘†qsŒ’Štt€|xŠstz‡‡}~{…ƒwz€Œywxƒ€z‹“|ss‚‡‚‚€{vzŠ„||x‡†ƒw|vwŒˆ„x|€‚€}~~Ž|x€€}ˆ€t}†|x‹—‚st†ˆ„{{w”ˆwx|…€~„xxŒ‚t|‰|x|€w†‰~sz‚‡~y{‹„yq€†…„xz€‚„z‰‹y{x…‚|t…“|zx€‡‡~u~|‡’„|sz€ƒ‚€~||}z’‡{uy‡„}z}v–€~uy…‡…|z|„Ž€|xx‡w}ƒ‰wt…Ž}py‡Š|u}x“Œ}{{€€~~~y€ˆƒ{|€z~ƒ„p{{v}ƒˆ}€ƒu‰Ž‰{r|†wˆ…wx|€Œƒxr€„†|z…{w}‚}~|}ˆ~}{~…„€~y…‹ˆy{€‚€€|z€‹€zu{ˆ~u…}ŽŒzxy…„y|€…’…zt…„ƒ}{‚ˆ}ˆ…x€„€x€{|}xuyˆ‡„uz~Œ~wv~~‡zv~‡{„•‹sr{†„}t“‹|uyŒŠ†vz‚|sŒ–‰qt}‰…zy‹~v{ƒ…‹‡yx|‡}x‹”€qq†…~ˆ‚|x…ˆ~}{€‚‚ƒ‡v‡}y…‡ƒ~xvŠ“yvy†ˆw}y€Žz{{ƒ„}‚~‚x‚І~xz‚‡}~x‡Žyt}„‰|{ˆyxy‰†~}~}~€‡‰wz…‚z~€‚x‰“…xux‡‡zyy…Šxw~€€‰€y{„{y€u}„}|…}q”‹yusЉqy€p…}v~ƒ‚†‚v‹†t}Šƒ|}„y‡†ww~‡~{†“ysw‡†‚~}|~„‚„yƒ€{zƒ…‚|ƒ{•~yq‚…ƒ|}„y|……z{|…Š„s|xv’Œƒpv‚…„|ty‚vx}‚{}|€~„†|‚‡yyƒƒwr—†tt}†ˆzz|z†ˆƒzyƒ‡‚~|‚ƒ{€…ˆxx{„ˆ„{s|Œy|€„…}~xyŽ”‡ps‡…ƒ~}|w|„yy„{v‹•‰qr„‰„{w}‚wx‚ƒ‚|~€{}~~€ƒt|yx}ˆ€„s„txƒ‡ƒ‚~€~…‡z{ƒ‚{~€ƒ~s~‘‚vu€…€y{“‡t|€~ƒ‚ƒ|||}{†~x{}‰t‚~u•ˆ€vs„ŠŒwwx…€zu€…~ƒtu€„rx€‡ƒ~‚‘Œ|{wˆ‚zw„{{€~yxw‘p{†zr”ƒst…ˆƒ~€t’yvz…€‚„|}w…ŒŒwu„‡€‚|t–…ru|……€}v‡‘„vz‚|„„|{‚|t‚}zu}ˆ‚|t}Š|xx€~~‚u~‹ˆ~ux{‰~z|†yp”‰rs|†€~yއ|~|„€‚vzˆ~v‡‹}y…}uƒŒ‚~v‚‡‚y{|†z}€‚„{y}€…„zz†~|~…‚y{s…Š|xu€‡„}{{{Œ’}xx~…ˆ|zƒ‚}|z‚‘s{ƒ…z|sŽxy}ˆ{‚rz‡ztz…ƒ‡€|{~€|‰}v{…ˆ}€|s‡‡zxzƒ‡„~zyŽ‚wz„€~zƒˆ€‡‚z|†ƒw{z”‡wuzˆƒ|uˆ{y€‚…€~~~ƒz‡‹yyxŒ‚{€~|Ž’yx|ˆŠ‚{xy}Ž„zz}…€ƒ|~{‡}}|ƒ…ysx…yu{†‡„|yv|‘…wy|„…||ƒzyˆƒ|x}‚{vy~wv~ˆ†}zw‰Ž‡vw|‰‚u‚€~z…zt€†€€pyŽ~wt}‹‹‚yvy‹Œ‡xu|‡…€{x‰„}xwІvwƒwqŽŠtu‚…„yy‹€xy‚‚‚ƒ{€|…‚|‡‚|}~†}z{w’†}wz‚€}x‹†t}~~‰ƒtˆtx‰‰vx‚‡…}~v‚…y{{ƒƒ…z}xƒ~x{…‡„}|€…yxˆ„tv}…‡rŽŠyy‰„„zz{}‡†‚tv€†…~|vu…†qs|‹x{€‡}zy‚€€z|yŠ‹ts„Šˆ||‚{pŽ”‰urƒŒ‰x{€€}{|ƒ€‡z{€|€‚Œyxƒ„€}x†“x{z€‡ƒyx~„€x}ƒ‚†ƒ|z‚{†sv€„‚}~‡q€‰}|t{Љs~„r„‡wq}…ˆ„€|w‚‰}ty‡…}y|~€„‡{z}„…}zˆ”†wxz‚ƒ„~z{{†„Šxx……|~yŠƒzs€…Œ{u}ƒ€…zvu‡~xu‚€u”{sq„‰‹}yt‘~zx€„ƒ‡‚y{~ƒƒ|ŠŒw~~€„„‚t‰–x{w…ˆƒ|{€~‚|tsƒ†‚|}}|ˆ‚xxu…‰€xz‚‚|vŠ’ˆrx‡†€|}x‹Š€{wƒ„…}~~ƒƒuy‹ƒzy‚ˆ~v{–tsxˆ‡yy}Œ‹‚y~‚‚€|€}‚‰‹{mxƒuz‚ƒs‰”ztu†…{~u„“|{~~‡„|}„ˆ…wy}Œ|x„‡pŠ€zu€†‚|uˆ‚{{}…‚‚~}{~€‹uw}Žwszˆ„ryŒƒvu~ˆzy{wŽ~yy{…ƒ€z{z†Š‚|zyІ|tƒ‡zyŒ…{s|‚†‚||x†ƒ}~‚€|x†‡ys……‚|{‚v„vy€ˆƒyw~|Œ€}y}…‚‚€}}€}€Š‚x}ƒˆy}ƒw~Œ„uzЇ{wx‡„{}~‚~ƒ{~€‡~~{|…„}{€ƒv‚Ž~{u|„‰ƒvzw‰{|‚„}{ƒ‚~€}t…{|wx•xu{‰ˆ†xxzw|}„†z|~ƒ†{€†~{yŠ…ƒz{|Ž–ww{†Œ…xr~xŽ„vty†‡|~z~Š„xw‰}zx†„wvˆŽ|q|„„€zy{……~z}‚„€ƒ}y|€p…„}~€||uˆvv‚…†€yy{‰…‚}zy†‹~wx‚‚y|‚‰€v~‡~~„su“†|tvˆŒ‡u|yzˆ‹„uw„‚…€x~‹u†~„‚zu{’{w}ƒƒ…~{‡†zz}Љvt|…„x…}tŒŠ}xzx‚Œ|v|†‡ƒu{}‹ƒ|v€‚„~‚‚{qŽtuŠ’Šyxy{|„ŒŽwsw……yw‹„ty…„~€€~ƒ„|‚ˆzyƒ‡z~zŠ‘{xx„……€yy{‰„|x~ƒ†…~~{€yŠ“‹uu|ˆ€‚{‹}|{ˆ…€z}€~Љˆvyz}‚wu…~w‚“tx‚Š„}zt€‰|}{€€~|~‰„}v†Ž{{‚‚€uŒƒzu€ˆƒz|xy‘„~w„€€€|yˆŒxtw„|}v‚‘‡|s|†‡€xy€{z~‚~~}…„vƒŒzs€ˆ‡|{}{†‘Švuwˆ†€{|z‰{|~{ˆ‚~{~z€|‰Žvw†…‚~|{wy€…‚ƒxx€Žƒ}y{ƒ…~||v‰Œƒ~€|€„‚€}sy†xu{‹‰„u{xx‰‰‚yw€ƒ†„|ƒx~ІzwŠŽ{v€‚}xŒ”v{ƒ‡„~wxƒ‰w{…€€€ƒ„yy…{}„‡~}|vu…‹vz‚ˆ„|}xy…}yz€ƒ„~~z‰Žwp‚‰Š}z}tŽ•†xty††}w‚‹zvƒ†€€€ƒ}|…ƒtz†ƒ}†~{w~Ž…ws€‰‡}|zxŽz|~~ƒ€|u†‹‡z{~ƒ‡€{|vzŒ†}vz€‡„{|yˆŽ„|{}€ƒƒy†ˆyt€…ƒ{‚ˆ~zv‚Ž–vv~„ˆ}xz}‹‚}x|ƒ‡|{zƒ|……{v„†…z~uƒŽ{ww|‡†‚|{}xŠŒ|qz‚ƒ„‚{~|€…‰€wu‰vyƒy‡vr‡€zy~yx€‡ƒ„|~y~‚Šƒr‡ƒ}y…‚q|”…vx‚†|}€yŽ‘ƒ{x€ƒ~~yzŒ…~xywxsyˆy‚~vv…†{|x}Ž{z„‚‚~~y…„yr}Œ}u†y|‰xuŠƒ~v{xˆ|z~€ƒ…~}~~}~Їvy‚‡ƒ~z}~vyv††ƒ{~{€Š‚€y|„}}|ƒ„{}ƒ€€z~‚€||Œwr€…†~v‚…z€…|uzƒˆƒ{x{|ƒ~xx‰‹†ww|††t|vx„‡~{u‚Œ~ux‚…~{~~yŒƒ}ww|‹|s~‚‚zˆŽŒwt{„ƒ}}‚vƒ|y|…†~~~ƒyƒvuyŒˆ~v}ƒxxxy‚‚~„€x‹w~„€y‡‹„~s„†ƒ}~}|zŒˆ‚wzz€‡‚~€}ˆ††~x{€Šz}€€‚‚†z‚ƒ€~€zwŒ†|x~‚…†{ƒ‡~v„ƒ~~…€~Љwv{Š€u~„‚tu’ƒrt†€€~v~‰…€zz}†…ƒ}|}x€‡†…t{††€‚~{‚Ž{vwˆƒ}x}|x‡}vv‚ƒƒƒz{u‡‘ŒytzŠŠyy‚~vu~‘‡vz€‚„‚}u|‡ƒ‚{||ƒ~‚‚}v„‡~~€}‚€}~vz‹†€w€|‡ƒz|xuŒŠwv{ˆ……w{}z~ŒŽˆtr€‰Œxv€~‰Š‡~ww{ˆ‹‰{ww|}†Œ€ys|„‹‰~zu€y‚vt|†…ˆ}zz€zz‰‹ˆ|tzz†‰ˆ|yy€y€‡uqy|††‹~xz€yyƒŽ†„p|}‰‰‡‚x{||y|’Іuz€‚‡Š…zx}‚‚t…‘Œs{|ˆƒ~…„yu|y‹ˆ…{u}}}‚Š„~wz€|„މ~uy€‡€|ƒ…{{}~„ˆ…z|~ƒ€ˆ~}~€~|vŒ‡‡y{€~}‚…„}||~€‹‡„|€~}~‚ƒƒ„x}€~~t~‰†‰}x{€ƒ„†ƒƒ{|}}…zs…ˆ†‚~|z|‚„‡}|z|‚†…us…„ˆ†„€||z~‚†„€~~€~€~}€…‚}~}‡€€…xw€ƒ†~‚€~€„€{€|ƒƒ€‚€yx}ƒ„}}~~~~‚†‡€|yv~‰ŒŠ|}|}ƒ…ƒ|{€‚}~‚ƒ}|}|‚„„†€‚‚€|{}ƒ‚…‚zz}ƒ„~|x€…†Š„~}}z|z‚„‹„€~~}|{}„ˆ„€|‚}~}€‚„€~€€}€ƒyz~‚€{‚‚‚~‚‚€~~}}€‚‚‚‚‚|{‚€€ƒ}z|}€ƒ†ƒ|}€€€~}„ƒ‚~{€‚€~x|„ƒƒ‚‚€~}~‡„~‚ƒ|y|‚ƒ‚~€‚ƒ€~~€€€€€}€~}„‚}{~ƒ‚€€„|}€€}‚†}}}~~€ƒ€~|‚†ƒ{}‚‚€}~€}†ƒ€|}}…„‚€~||~„„„€}|~‚‚‚‚‚ƒ|{€€€…‚€}}€~€~ƒ€ƒ„€€}~~€…„€|{„‚~}ƒ~~||}„~€€~‚ƒ‚||~„€}€€€€~€€‚}~€„~€‚€|{„}~€€€€‚|}€‚~„‚€€|‚ƒƒ€|~‚‚}}‚ƒ~}€€}|€€€‚~|~‚~€€}~~€ƒƒ~€~€€€~„~}}ƒƒ}‚€ƒ€|‚ƒƒ‚~~}~‚€‚‚‚~}|~„ƒ~€€€~}‚‚‚€}€‚‚~~€‚}€€€€‚€~}~~ƒ‚€‚}||€ƒ‚~€}~‚€~„~}€€||‚‚‚~~|„„€ƒ‚~}‚‚€‚„}{~…ƒ‚|}†}~€ƒ€}€€€‚ƒ~||€„€{€‚~~€€€€€~‚}}z‚~ƒ~|€‚‚~€€}~ƒ…{{~}€‚€‚‚~~}€‚~€€€€€€€€€€~€€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€ \ No newline at end of file diff --git a/examples/src/sl/tuxr.mod b/examples/src/sl/tuxr.mod new file mode 100644 index 0000000..5077a67 Binary files /dev/null and b/examples/src/sl/tuxr.mod differ diff --git a/examples/src/sl/wheeee.ub b/examples/src/sl/wheeee.ub new file mode 100644 index 0000000..84d1ae7 Binary files /dev/null and b/examples/src/sl/wheeee.ub differ diff --git a/examples/src/sl/zzap.wav b/examples/src/sl/zzap.wav new file mode 100644 index 0000000..101029c Binary files /dev/null and b/examples/src/sl/zzap.wav differ diff --git a/examples/src/ssg/Makefile.am b/examples/src/ssg/Makefile.am new file mode 100644 index 0000000..77f8ee0 --- /dev/null +++ b/examples/src/ssg/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = tux majik load_save state_test viewer tween_test water sky shrubs dynamics shapes + +EXTRA_DIST = README diff --git a/examples/src/ssg/README b/examples/src/ssg/README new file mode 100644 index 0000000..0d23bba --- /dev/null +++ b/examples/src/ssg/README @@ -0,0 +1,20 @@ +SSG Example programs. +~~~~~~~~~~~~~~~~~~~~~ + +Tux -- Loads a 3D Tux model and a simple scene and + animates it until you hit key. + Needs to be run from it's source directory + so it can find it's data files. + +Majik -- An example I wrote for the Majik team + http://majik.netti.fi to show them how to + make a viewer for large area terrain. + It's pretty basic. + +Water -- A demo of some ssgAux stuff - waves, particle-systems + a teapot and a cube. + +Sky -- A demo of a sky dome, with sun, moon, stars and clouds. + +Dynamics -- Spring/Mass/Damper demo. + diff --git a/examples/src/ssg/dynamics/Makefile.am b/examples/src/ssg/dynamics/Makefile.am new file mode 100644 index 0000000..c81647a --- /dev/null +++ b/examples/src/ssg/dynamics/Makefile.am @@ -0,0 +1,12 @@ +if BUILD_SSG + +noinst_PROGRAMS = dynamics + +dynamics_SOURCES = dynamics.cxx + +dynamics_LDADD = -lplibpu -lplibfnt -lplibssgaux -lplibssg -lplibsg -lplibul $(GLUT_LIBS) $(OGL_LIBS) + +endif + +EXTRA_DIST = dynamics.dsp + diff --git a/examples/src/ssg/dynamics/data/bw.rgb b/examples/src/ssg/dynamics/data/bw.rgb new file mode 100644 index 0000000..c60c278 Binary files /dev/null and b/examples/src/ssg/dynamics/data/bw.rgb differ diff --git a/examples/src/ssg/dynamics/data/mg.rgb b/examples/src/ssg/dynamics/data/mg.rgb new file mode 100644 index 0000000..c7f26ed Binary files /dev/null and b/examples/src/ssg/dynamics/data/mg.rgb differ diff --git a/examples/src/ssg/dynamics/dynamics.cxx b/examples/src/ssg/dynamics/dynamics.cxx new file mode 100644 index 0000000..19d95f0 --- /dev/null +++ b/examples/src/ssg/dynamics/dynamics.cxx @@ -0,0 +1,450 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: dynamics.cxx 2099 2006-11-03 20:04:40Z fayjf $ +*/ + + +#include +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include +#include +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#define GUI_BASE 80 +#define VIEW_GUI_BASE 20 +#define FONT_COLOUR 1,1,1,1 +#define DEEPEST_HELL -10000.0 +#define HOT_TOLERANCE 1.0f + +static ssgRoot *scene = NULL ; +static ssgaWaveSystem *ocean = NULL ; +static ssgSimpleState *sea_state = NULL ; +static ssgSimpleState *cube_state = NULL ; + +static ssgaWaveTrain trains [ 3 ] ; + +static ssgTransform *cube [ 10 ] ; +static sgParticle *particle [ 10 ] ; +static sgSpringDamper *spring [ 20 ] ; +static int num_particles ; +static int num_springs ; + +static void resetSMD () +{ + particle [ 0 ] -> setPos ( 2.0f, -4.0f, 0.0f ) ; + particle [ 1 ] -> setPos ( 2.4f, 0.0f, 6.0f ) ; + particle [ 2 ] -> setPos ( 2.1f, 4.0f, 0.0f ) ; + particle [ 3 ] -> setPos ( 4.1f, -4.0f, 4.0f ) ; + particle [ 4 ] -> setPos ( 0.0f, -4.0f, 4.0f ) ; + particle [ 5 ] -> setPos ( 4.0f, 4.0f, 4.0f ) ; + particle [ 6 ] -> setPos ( 0.0f, 4.0f, 4.0f ) ; + + particle [ 0 ] -> setVel ( 0, 0, 0 ) ; + particle [ 1 ] -> setVel ( 0, 0, 30 ) ; + particle [ 2 ] -> setVel ( 0, 0, 0 ) ; + particle [ 3 ] -> setVel ( 0, 0, 0 ) ; + particle [ 4 ] -> setVel ( 0, 0, 0 ) ; + particle [ 5 ] -> setVel ( 0, 0, 0 ) ; + particle [ 6 ] -> setVel ( 0, 0, 0 ) ; +} + +static void initSMD () +{ + particle [ 0 ] = new sgParticle ( 1.0f, 2.0f, -4.0f, 4.0f ) ; + particle [ 1 ] = new sgParticle ( 1.0f, 2.4f, 0.0f, 6.0f ) ; + particle [ 2 ] = new sgParticle ( 1.0f, 2.0f, 4.0f, 4.0f ) ; + particle [ 3 ] = new sgParticle ( 1.0f, 4.0f, -4.0f, 0.0f ) ; + particle [ 4 ] = new sgParticle ( 1.0f, 0.0f, -4.0f, 0.0f ) ; + particle [ 5 ] = new sgParticle ( 1.0f, 4.0f, 4.0f, 0.0f ) ; + particle [ 6 ] = new sgParticle ( 1.0f, 0.0f, 4.0f, 0.0f ) ; + + num_particles = 7 ; + + int s=0; + + spring [s++] = new sgSpringDamper ( particle[0], particle[1], 50.0f, 1.0f ) ; + spring [s++] = new sgSpringDamper ( particle[0], particle[2], 50.0f, 1.0f ) ; + spring [s++] = new sgSpringDamper ( particle[0], particle[3], 50.0f, 1.0f ) ; + spring [s++] = new sgSpringDamper ( particle[0], particle[4], 50.0f, 1.0f ) ; + spring [s++] = new sgSpringDamper ( particle[0], particle[5], 50.0f, 1.0f ) ; + spring [s++] = new sgSpringDamper ( particle[1], particle[2], 50.0f, 1.0f ) ; + spring [s++] = new sgSpringDamper ( particle[2], particle[3], 50.0f, 1.0f ) ; + spring [s++] = new sgSpringDamper ( particle[2], particle[5], 50.0f, 1.0f ) ; + spring [s++] = new sgSpringDamper ( particle[2], particle[6], 50.0f, 1.0f ) ; + spring [s++] = new sgSpringDamper ( particle[3], particle[4], 50.0f, 1.0f ) ; + spring [s++] = new sgSpringDamper ( particle[3], particle[5], 50.0f, 1.0f ) ; + spring [s++] = new sgSpringDamper ( particle[4], particle[6], 50.0f, 1.0f ) ; + spring [s++] = new sgSpringDamper ( particle[5], particle[6], 50.0f, 1.0f ) ; + spring [s++] = new sgSpringDamper ( particle[3], particle[6], 50.0f, 1.0f ) ; + spring [s++] = new sgSpringDamper ( particle[4], particle[5], 50.0f, 1.0f ) ; + + spring [s++] = new sgSpringDamper ( particle[2], particle[4], 50.0f, 1.0f ) ; + spring [s++] = new sgSpringDamper ( particle[0], particle[6], 50.0f, 1.0f ) ; + + num_springs = s ; + + for ( int i = 0 ; i < num_particles ; i++ ) + { + ssgaCube *cb = new ssgaCube () ; + cb -> setKidState ( cube_state ) ; + cb -> regenerate () ; + + cube [ i ] = new ssgTransform () ; + cube [ i ] -> addKid ( cb ) ; + cube [ i ] -> clrTraversalMaskBits ( SSGTRAV_ISECT | SSGTRAV_HOT ) ; + + scene -> addKid ( cube[i] ) ; + } +} + + + +static float getHeightAndNormal ( sgVec3 my_position, sgVec3 normal ) +{ + /* Look for the nearest polygon *beneath* my_position */ + + ssgHit *results ; + int num_hits ; + + float hot ; /* H.O.T == Height Of Terrain */ + sgVec3 HOTvec ; + + sgMat4 invmat ; + sgMakeIdentMat4 ( invmat ) ; + invmat[3][0] = - my_position [0] ; + invmat[3][1] = - my_position [1] ; + invmat[3][2] = 0.0 ; + + sgSetVec3 ( HOTvec, 0.0f, 0.0f, my_position [ 2 ]+HOT_TOLERANCE ) ; + + num_hits = ssgHOT ( scene, HOTvec, invmat, &results ) ; + + hot = DEEPEST_HELL ; + + for ( int i = 0 ; i < num_hits ; i++ ) + { + ssgHit *h = &results [ i ] ; + + float hgt = - h->plane[3] / h->plane[2] ; + + if ( hgt >= hot ) + { + hot = hgt ; + + if ( normal != NULL ) + sgCopyVec3 ( normal, h->plane ) ; + } + } + + return hot ; +} + + + +#define RESTITUTION 0.9f + + +static void updateSMD ( float dt ) +{ + int i; + for ( i = 0 ; i < num_particles ; i++ ) + { + sgVec3 friction ; + + sgScaleVec3 ( friction, particle[i]->getVel (), 0.1f ) ; + + particle [ i ] -> gravityOnly () ; + particle [ i ] -> subForce ( friction ) ; + } + + for ( i = 0 ; i < num_springs ; i++ ) + spring [ i ] -> update () ; + + for ( i = 0 ; i < num_particles ; i++ ) + { + particle [ i ] -> update ( dt ) ; + + sgVec3 normal ; + + float hot = getHeightAndNormal ( particle [ i ] -> getPos(), normal ) ; + + if ( particle [ i ] -> getPos ()[2] <= hot ) + { + particle [ i ] -> bounce ( normal, RESTITUTION ) ; + particle [ i ] -> getPos ()[2] = hot ; + } + } + + for ( i = 0 ; i < num_particles ; i++ ) + cube [ i ] -> setTransform ( particle[i] -> getPos () ) ; +} + + +static sgCoord campos = { { 0, -20, 8 }, { 0, -20, 0 } } ; + +static void update_motion ( int frameno ) +{ + ssgSetCamera ( & campos ) ; + + ocean -> setWindDirn ( 25.0f * (float)sin ( frameno / 10.0 ) ) ; + + static ulClock ck ; ck . update () ; + + float t = (float)ck . getAbsTime () ; + float dt = (float)ck . getDeltaTime () ; + + if ( dt > 0.05f ) dt = 0.05f ; + + ocean -> updateAnimation ( t ) ; + + updateSMD ( dt ) ; +} + + + +/* + The GLUT window reshape event +*/ + +static void reshape ( int w, int h ) +{ + glViewport ( 0, 0, w, h ) ; +} + + + +/* + The GLUT keyboard/mouse events +*/ + + +static void keyboard ( unsigned char key, int, int ) +{ + switch ( key ) + { + case 0x03 : exit ( 0 ) ; + default : resetSMD () ; break ; + } +} + + +static void specialfn ( int key, int x, int y ) +{ +} + + +static void motionfn ( int x, int y ) +{ +} + +static void mousefn ( int button, int updown, int x, int y ) +{ +} + + + +/* + The GLUT redraw event +*/ + +static void redraw () +{ +static int frameno = 0 ; +frameno++ ; + + update_motion ( frameno % 2000 ) ; + + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + ssgCullAndDraw ( scene ) ; + + glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL ) ; + + glutPostRedisplay () ; + glutSwapBuffers () ; +} + + + +static void init_graphics () +{ + int fake_argc = 1 ; + char *fake_argv[3] ; + fake_argv[0] = "ssgExample" ; + fake_argv[1] = "Simple Scene Graph : Example Program." ; + fake_argv[2] = NULL ; + + /* + Initialise GLUT + */ + + glutInitWindowPosition ( 0, 0 ) ; + glutInitWindowSize ( 640, 480 ) ; + glutInit ( &fake_argc, fake_argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + glutCreateWindow ( fake_argv[1] ) ; + glutDisplayFunc ( redraw ) ; + glutReshapeFunc ( reshape ) ; + glutKeyboardFunc ( keyboard ) ; + glutSpecialFunc ( specialfn ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; + glutPassiveMotionFunc ( motionfn ) ; + + ssgInit () ; + + /* + Some basic OpenGL setup + */ + + glClearColor ( 0.2f, 0.7f, 1.0f, 1.0f ) ; + glEnable ( GL_DEPTH_TEST ) ; + + /* + Set up the viewing parameters + */ + + ssgSetFOV ( 60.0f, 0.0f ) ; + ssgSetNearFar ( 1.0f, 700.0f ) ; + + /* + Set up the Sun. + */ + + sgVec3 sunposn ; + sgSetVec3 ( sunposn, 0.1f, -1.0f, 0.1f ) ; + ssgGetLight ( 0 ) -> setPosition ( sunposn ) ; +} + + +static void init_states () +{ + cube_state = new ssgSimpleState () ; + cube_state -> setTexture ( "data/mg.rgb" ) ; + cube_state -> enable ( GL_TEXTURE_2D ) ; + cube_state -> setShadeModel ( GL_SMOOTH ) ; + cube_state -> enable ( GL_CULL_FACE ) ; + cube_state -> enable ( GL_BLEND ) ; + cube_state -> enable ( GL_LIGHTING ) ; + cube_state -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + cube_state -> setMaterial ( GL_EMISSION, 0, 0, 0, 1 ) ; + cube_state -> setMaterial ( GL_SPECULAR, 1, 1, 1, 1 ) ; + cube_state -> setShininess ( 2 ) ; + + sea_state = new ssgSimpleState () ; + sea_state -> setTexture ( "data/bw.rgb" ) ; + sea_state -> enable ( GL_TEXTURE_2D ) ; + sea_state -> setShadeModel ( GL_SMOOTH ) ; + sea_state -> enable ( GL_CULL_FACE ) ; + sea_state -> disable ( GL_BLEND ) ; + sea_state -> enable ( GL_LIGHTING ) ; + sea_state -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + sea_state -> setMaterial ( GL_EMISSION, 0, 0, 0, 1 ) ; + sea_state -> setMaterial ( GL_SPECULAR, 1, 1, 1, 1 ) ; + sea_state -> setShininess ( 5 ) ; +} + + + +static void load_database () +{ + /* Set up the path to the data files */ + + ssgModelPath ( "data" ) ; + ssgTexturePath ( "data" ) ; + + /* Load the states */ + + init_states () ; + + sgVec4 WHITE = { 1.0, 1.0, 1.0, 1.0 } ; + + /* Set up some interesting defaults. */ + + trains[0] . setSpeed ( 3.1f ) ; + trains[0] . setLength ( 0.8f ) ; + trains[0] . setLambda ( 0.6f ) ; + trains[0] . setHeading ( 47.0f ) ; + trains[0] . setWaveHeight ( 0.2f ) ; + + trains[1] . setSpeed ( 4.6f ) ; + trains[1] . setLength ( 0.8f ) ; + trains[1] . setLambda ( 1.0f ) ; + trains[1] . setHeading ( 36.0f ) ; + trains[1] . setWaveHeight ( 0.1f ) ; + + trains[2] . setSpeed ( 8.5f ) ; + trains[2] . setLength ( 0.6f ) ; + trains[2] . setLambda ( 1.0f ) ; + trains[2] . setHeading ( 65.0f ) ; + trains[2] . setWaveHeight ( 0.1f ) ; + + ocean = new ssgaWaveSystem ( 10000 ) ; + ocean -> setColour ( WHITE ) ; + ocean -> setSize ( 100 ) ; + ocean -> setTexScale ( 3, 3 ) ; + ocean -> setKidState ( sea_state ) ; + ocean -> setWindSpeed ( 10.0f ) ; + ocean -> setWaveTrain ( 0, & trains[0] ) ; + ocean -> setWaveTrain ( 1, & trains[1] ) ; + ocean -> setWaveTrain ( 2, & trains[2] ) ; + ocean -> regenerate () ; + + /* Build the scene graph */ + + scene = new ssgRoot ; + scene -> addKid ( ocean ) ; + + initSMD () ; +} + + +/* + The works. +*/ + +int main ( int, char ** ) +{ + init_graphics () ; + load_database () ; + glutMainLoop () ; + return 0 ; +} + + + diff --git a/examples/src/ssg/dynamics/dynamics.dsp b/examples/src/ssg/dynamics/dynamics.dsp new file mode 100644 index 0000000..68c71b0 --- /dev/null +++ b/examples/src/ssg/dynamics/dynamics.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="dynamics" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=dynamics - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "dynamics.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "dynamics.mak" CFG="dynamics - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "dynamics - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "dynamics - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "dynamics - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssgAux.lib ssg.lib sg.lib ul.lib winmm.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /machine:I386 /out:"dynamics.exe" /libpath:"..\..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "dynamics - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssgAux_d.lib ssg_d.lib sg_d.lib ul_d.lib winmm.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /debug /machine:I386 /out:"dynamics.exe" /pdbtype:sept /libpath:"..\..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "dynamics - Win32 Release" +# Name "dynamics - Win32 Debug" +# Begin Source File + +SOURCE=.\dynamics.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/ssg/load_save/Makefile.am b/examples/src/ssg/load_save/Makefile.am new file mode 100644 index 0000000..fe4b821 --- /dev/null +++ b/examples/src/ssg/load_save/Makefile.am @@ -0,0 +1,14 @@ +if BUILD_SSG + +noinst_PROGRAMS = load save + +load_SOURCES = load.cxx +save_SOURCES = save.cxx + +load_LDADD = -lplibssg -lplibsg -lplibul $(GLUT_LIBS) $(OGL_LIBS) +save_LDADD = -lplibssg -lplibsg -lplibul $(GLUT_LIBS) $(OGL_LIBS) + +endif + +EXTRA_DIST = load.dsp save.dsp + diff --git a/examples/src/ssg/load_save/data/Penguin_beak.rgb b/examples/src/ssg/load_save/data/Penguin_beak.rgb new file mode 100644 index 0000000..b1e0e79 Binary files /dev/null and b/examples/src/ssg/load_save/data/Penguin_beak.rgb differ diff --git a/examples/src/ssg/load_save/data/Penguin_body.rgb b/examples/src/ssg/load_save/data/Penguin_body.rgb new file mode 100644 index 0000000..1ba0f4b Binary files /dev/null and b/examples/src/ssg/load_save/data/Penguin_body.rgb differ diff --git a/examples/src/ssg/load_save/data/embossed_herring.bmp b/examples/src/ssg/load_save/data/embossed_herring.bmp new file mode 100644 index 0000000..795e5d1 Binary files /dev/null and b/examples/src/ssg/load_save/data/embossed_herring.bmp differ diff --git a/examples/src/ssg/load_save/data/pedestal.ac b/examples/src/ssg/load_save/data/pedestal.ac new file mode 100644 index 0000000..3c112e2 --- /dev/null +++ b/examples/src/ssg/load_save/data/pedestal.ac @@ -0,0 +1,81 @@ +AC3Db +MATERIAL "" rgb 1 1 1 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "" rgb 1 1 1 amb 0.2 0.2 0.2 emis 1 1 1 spec 0.502 0.502 0.502 shi 0 trans 0 +OBJECT world +kids 2 +OBJECT poly +name "box" +texture "wood.rgb" +texrep 5 5 +numvert 8 +-1.29615 -0.6 -1.29615 +-1 0 -1 +1 0 -1 +1.3 -0.6 -1.29615 +-1.29615 -0.6 1.3 +-1 0 1 +1 0 1 +1.3 -0.6 1.3 +numsurf 6 +SURF 0x0 +mat 0 +refs 4 +0 0 0 +1 0.114074 0.114074 +2 0.884445 0.114074 +3 1 0 +SURF 0x0 +mat 0 +refs 4 +6 0.884445 0.884445 +7 1 1 +3 1 0 +2 0.884445 0.114074 +SURF 0x0 +mat 0 +refs 4 +7 1 1 +6 0.884445 0.884445 +5 0.114074 0.884445 +4 0 1 +SURF 0x0 +mat 0 +refs 4 +4 0 1 +5 0.114074 0.884445 +1 0.114074 0.114074 +0 0 0 +SURF 0x0 +mat 0 +refs 4 +1 0.114074 0.114074 +5 0.114074 0.884445 +6 0.884445 0.884445 +2 0.884445 0.114074 +SURF 0x0 +mat 0 +refs 4 +4 0 1 +0 0 0 +3 1 0 +7 1 1 +kids 0 +OBJECT poly +name "rect" +loc -0.0500002 0 -2.5 +texture "embossed_herring.bmp" +texrep 20 30 +numvert 4 +-17.95 -0.7 -18.6 +17.95 -0.7 -18.6 +17.95 -0.7 18.6 +-17.95 -0.7 18.6 +numsurf 1 +SURF 0x0 +mat 1 +refs 4 +3 0 0 +2 1 0 +1 1 1 +0 0 1 +kids 0 diff --git a/examples/src/ssg/load_save/data/pedestal.safe b/examples/src/ssg/load_save/data/pedestal.safe new file mode 100644 index 0000000..3d613b9 --- /dev/null +++ b/examples/src/ssg/load_save/data/pedestal.safe @@ -0,0 +1,81 @@ +AC3Db +MATERIAL "" rgb 1 1 1 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "" rgb 1 1 1 amb 0.2 0.2 0.2 emis 1 1 1 spec 0.502 0.502 0.502 shi 0 trans 0 +OBJECT world +kids 2 +OBJECT poly +name "box" +texture "wood.rgb" +texrep 5 5 +numvert 8 +-1.29615 -0.6 -1.29615 +-1 0 -1 +1 0 -1 +1.3 -0.6 -1.29615 +-1.29615 -0.6 1.3 +-1 0 1 +1 0 1 +1.3 -0.6 1.3 +numsurf 6 +SURF 0x0 +mat 0 +refs 4 +0 0 0 +1 0.114074 0.114074 +2 0.884445 0.114074 +3 1 0 +SURF 0x0 +mat 0 +refs 4 +6 0.884445 0.884445 +7 1 1 +3 1 0 +2 0.884445 0.114074 +SURF 0x0 +mat 0 +refs 4 +7 1 1 +6 0.884445 0.884445 +5 0.114074 0.884445 +4 0 1 +SURF 0x0 +mat 0 +refs 4 +4 0 1 +5 0.114074 0.884445 +1 0.114074 0.114074 +0 0 0 +SURF 0x0 +mat 0 +refs 4 +1 0.114074 0.114074 +5 0.114074 0.884445 +6 0.884445 0.884445 +2 0.884445 0.114074 +SURF 0x0 +mat 0 +refs 4 +4 0 1 +0 0 0 +3 1 0 +7 1 1 +kids 0 +OBJECT poly +name "rect" +loc -0.0500002 0 -2.5 +texture "embossed_herring.rgb" +texrep 20 30 +numvert 4 +-17.95 -0.7 -18.6 +17.95 -0.7 -18.6 +17.95 -0.7 18.6 +-17.95 -0.7 18.6 +numsurf 1 +SURF 0x0 +mat 1 +refs 4 +3 0 0 +2 1 0 +1 1 1 +0 0 1 +kids 0 diff --git a/examples/src/ssg/load_save/data/tuxedo.ac b/examples/src/ssg/load_save/data/tuxedo.ac new file mode 100644 index 0000000..12e4754 --- /dev/null +++ b/examples/src/ssg/load_save/data/tuxedo.ac @@ -0,0 +1,1695 @@ +AC3Db +MATERIAL "" rgb 0 0 0 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "" rgb 1 0.702 0 amb 1 0.702 0 emis 0 0 0 spec 0 0 0 shi 0 trans 0 +MATERIAL "" rgb 1 1 1 amb 1 1 1 emis 0 0 0 spec 0 0 0 shi 0 trans 0 +OBJECT world +kids 1 +OBJECT group +name "Tuxedo.T.Penguin" +kids 3 +OBJECT poly +name "tuxfeet" +loc 0.0203744 -0.479517 0.101666 +numvert 14 +-0.0744405 0.473224 0.119889 +0.100559 0.473224 -0.200111 +0.175559 0.473224 0.199889 +0.250559 0.473224 -0.200111 +0.425559 0.473224 0.119889 +0.250559 0.523224 -0.200111 +0.100559 0.523224 -0.200111 +-0.425559 0.476776 0.120111 +-0.25056 0.476776 -0.199889 +-0.17556 0.476776 0.200111 +-0.100559 0.476776 -0.199889 +0.0744405 0.476776 0.120111 +-0.100559 0.526776 -0.199889 +-0.25056 0.526776 -0.199889 +numsurf 12 +SURF 0x0 +mat 1 +refs 3 +0 0 0.1 +1 0.9 0 +2 0 0.8 +SURF 0x0 +mat 1 +refs 3 +3 1 0.1 +2 0 0.8 +1 0.9 0 +SURF 0x0 +mat 1 +refs 3 +2 0 0.8 +3 1 0.1 +4 0.5 1 +SURF 0x0 +mat 1 +refs 3 +4 0.5 1 +5 1 0.1 +2 0 0.8 +SURF 0x0 +mat 1 +refs 3 +6 0.9 0 +2 0 0.8 +5 1 0.1 +SURF 0x0 +mat 1 +refs 3 +2 0 0.8 +6 0.9 0 +0 0 0.1 +SURF 0x0 +mat 1 +refs 3 +7 0 0.1 +8 0.9 0 +9 0 0.8 +SURF 0x0 +mat 1 +refs 3 +10 1 0.1 +9 0 0.8 +8 0.9 0 +SURF 0x0 +mat 1 +refs 3 +9 0 0.8 +10 1 0.1 +11 0.5 1 +SURF 0x0 +mat 1 +refs 3 +11 0.5 1 +12 1 0.1 +9 0 0.8 +SURF 0x0 +mat 1 +refs 3 +13 0.9 0 +9 0 0.8 +12 1 0.1 +SURF 0x0 +mat 1 +refs 3 +9 0 0.8 +13 0.9 0 +7 0 0.1 +kids 0 +OBJECT poly +name "tuxbody" +loc 0.0124385 0.107258 -0.188333 +texture "Penguin_body.rgb" +numvert 115 +0.097524 1.07 -0.0756895 +-0.0202512 1.11 0 +0.119749 1.07 0 +0.0379068 1.07 -0.127348 +-0.0401753 1.07 -0.138575 +-0.111932 1.07 -0.105805 +-0.154581 1.07 -0.0394426 +-0.154581 1.07 0.0394426 +-0.111932 1.07 0.105805 +-0.0401753 1.07 0.138575 +0.0379068 1.07 0.127348 +0.097524 1.07 0.0756895 +0.184749 0.975 0 +0.152205 0.975 -0.110831 +0.064909 0.975 -0.186475 +-0.0494259 0.975 -0.202913 +-0.154498 0.975 -0.154929 +-0.216947 0.975 -0.057755 +-0.216947 0.975 0.057755 +-0.154498 0.975 0.154929 +-0.0494259 0.975 0.202913 +0.064909 0.975 0.186475 +0.152205 0.975 0.110831 +0.199749 0.68 0 +0.164825 0.68 -0.118941 +0.07114 0.68 -0.200119 +-0.0515605 0.68 -0.217761 +-0.16432 0.68 -0.166265 +-0.231339 0.68 -0.061981 +-0.231339 0.68 0.061981 +-0.16432 0.68 0.166265 +-0.0515605 0.68 0.217761 +0.07114 0.68 0.200119 +0.164825 0.68 0.118941 +0.284749 0.555 0 +0.236331 0.555 -0.164896 +0.10645 0.555 -0.277438 +-0.0636575 0.555 -0.301895 +-0.219984 0.555 -0.230503 +-0.312897 0.555 -0.0859285 +-0.312897 0.555 0.0859285 +-0.219984 0.555 0.230503 +-0.0636575 0.555 0.301895 +0.10645 0.555 0.277438 +0.236331 0.555 0.164896 +0.369749 0.43 0 +0.307837 0.43 -0.21085 +0.14176 0.43 -0.354757 +-0.075754 0.43 -0.38603 +-0.275647 0.43 -0.294742 +-0.394453 0.43 -0.109876 +-0.394453 0.43 0.109876 +-0.275647 0.43 0.294742 +-0.075754 0.43 0.38603 +0.14176 0.43 0.354757 +0.307837 0.43 0.21085 +0.414749 0.305 0 +0.345694 0.305 -0.235179 +0.160454 0.305 -0.39569 +-0.0821585 0.305 -0.430573 +-0.305115 0.305 -0.328751 +-0.437631 0.305 -0.122553 +-0.437631 0.305 0.122553 +-0.305115 0.305 0.328751 +-0.0821585 0.305 0.430573 +0.160454 0.305 0.39569 +0.345694 0.305 0.235179 +0.409749 0.185 0 +0.341488 0.185 -0.232476 +0.158377 0.185 -0.391142 +-0.081447 0.185 -0.425623 +-0.301841 0.185 -0.324973 +-0.432833 0.185 -0.121145 +-0.432833 0.185 0.121145 +-0.301841 0.185 0.324973 +-0.081447 0.185 0.425623 +0.158377 0.185 0.391142 +0.341488 0.185 0.232476 +0.354748 2.23517e-08 0 +0.295219 2.23517e-08 -0.202741 +0.135529 2.23517e-08 -0.341112 +-0.0736195 2.23517e-08 -0.371183 +-0.265824 2.23517e-08 -0.283406 +-0.380061 2.23517e-08 -0.10565 +-0.380061 2.23517e-08 0.10565 +-0.265824 2.23517e-08 0.283406 +-0.0736195 2.23517e-08 0.371183 +0.135529 2.23517e-08 0.341112 +0.295219 2.23517e-08 0.202741 +0.154748 -0.1 0 +0.126968 -0.1 -0.094612 +0.052446 -0.1 -0.159185 +-0.0451563 -0.1 -0.173219 +-0.134852 -0.1 -0.132256 +-0.188163 -0.1 -0.0493032 +-0.188163 -0.1 0.0493032 +-0.134852 -0.1 0.132256 +-0.0451564 -0.1 0.173219 +0.052446 -0.1 0.159185 +0.126968 -0.1 0.094612 +0.211872 0.567025 0.1 +0.211872 0.567025 -0.1 +0.316872 0.532025 0.1 +0.316872 0.532025 -0.1 +0.456872 0.392025 0.1 +0.456872 0.392025 -0.1 +0.56187 0.217025 0 +-0.211873 0.58637 0.1 +-0.211873 0.58637 -0.1 +-0.316873 0.55137 0.1 +-0.316873 0.55137 -0.1 +-0.456872 0.41137 0.1 +-0.456872 0.41137 -0.1 +-0.56187 0.23637 0 +-0.0202512 -0.11 0 +numsurf 218 +SURF 0x10 +mat 2 +refs 3 +0 -1 0.967213 +1 -1 1 +2 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +3 -1 0.967213 +1 -1 1 +0 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +4 -1 0.967213 +1 -1 1 +3 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +5 -1 0.967213 +1 -1 1 +4 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +6 -1 0.967213 +1 -1 1 +5 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +7 -0.614934 0.967213 +1 -0.5 1 +6 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +8 -0.578443 0.967213 +1 -0.5 1 +7 -0.614934 0.967213 +SURF 0x10 +mat 2 +refs 3 +9 -0.517047 0.967213 +1 -0.5 1 +8 -0.578443 0.967213 +SURF 0x10 +mat 2 +refs 3 +10 -0.450239 0.967213 +1 -0.5 1 +9 -0.517047 0.967213 +SURF 0x10 +mat 2 +refs 3 +11 -0.39923 0.967213 +1 -0.5 1 +10 -0.450239 0.967213 +SURF 0x10 +mat 2 +refs 3 +2 -0.380214 0.967213 +1 -0.5 1 +11 -0.39923 0.967213 +SURF 0x10 +mat 2 +refs 3 +2 -1 0.967213 +12 -1 0.889344 +0 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +13 -1 0.889344 +0 -1 0.967213 +12 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +0 -1 0.967213 +13 -1 0.889344 +3 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +14 -1 0.889344 +3 -1 0.967213 +13 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +3 -1 0.967213 +14 -1 0.889344 +4 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +15 -1 0.889344 +4 -1 0.967213 +14 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +4 -1 0.967213 +15 -1 0.889344 +5 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +16 -1 0.889344 +5 -1 0.967213 +15 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +5 -1 0.967213 +16 -1 0.889344 +6 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +17 -1 0.889344 +6 -1 0.967213 +16 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +6 -1 0.967213 +17 -1 0.889344 +7 -0.614934 0.967213 +SURF 0x10 +mat 2 +refs 3 +18 -0.668296 0.889344 +7 -0.614934 0.967213 +17 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +7 -0.614934 0.967213 +18 -0.668296 0.889344 +8 -0.578443 0.967213 +SURF 0x10 +mat 2 +refs 3 +19 -0.614863 0.889344 +8 -0.578443 0.967213 +18 -0.668296 0.889344 +SURF 0x10 +mat 2 +refs 3 +8 -0.578443 0.967213 +19 -0.614863 0.889344 +9 -0.517047 0.967213 +SURF 0x10 +mat 2 +refs 3 +20 -0.524962 0.889344 +9 -0.517047 0.967213 +19 -0.614863 0.889344 +SURF 0x10 +mat 2 +refs 3 +9 -0.517047 0.967213 +20 -0.524962 0.889344 +10 -0.450239 0.967213 +SURF 0x10 +mat 2 +refs 3 +21 -0.427136 0.889344 +10 -0.450239 0.967213 +20 -0.524962 0.889344 +SURF 0x10 +mat 2 +refs 3 +10 -0.450239 0.967213 +21 -0.427136 0.889344 +11 -0.39923 0.967213 +SURF 0x10 +mat 2 +refs 3 +22 -0.352443 0.889344 +11 -0.39923 0.967213 +21 -0.427136 0.889344 +SURF 0x10 +mat 2 +refs 3 +11 -0.39923 0.967213 +22 -0.352443 0.889344 +2 -0.380214 0.967213 +SURF 0x10 +mat 2 +refs 3 +12 -0.324599 0.889344 +2 -0.380214 0.967213 +22 -0.352443 0.889344 +SURF 0x10 +mat 2 +refs 3 +12 -1 0.889344 +23 -1 0.647541 +13 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +24 -1 0.647541 +13 -1 0.889344 +23 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +13 -1 0.889344 +24 -1 0.647541 +14 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +25 -1 0.647541 +14 -1 0.889344 +24 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +14 -1 0.889344 +25 -1 0.647541 +15 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +26 -1 0.647541 +15 -1 0.889344 +25 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +15 -1 0.889344 +26 -1 0.647541 +16 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +27 -1 0.647541 +16 -1 0.889344 +26 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +16 -1 0.889344 +27 -1 0.647541 +17 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +28 -1 0.647541 +17 -1 0.889344 +27 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +17 -1 0.889344 +28 -1 0.647541 +18 -0.668296 0.889344 +SURF 0x10 +mat 2 +refs 3 +29 -0.68061 0.647541 +18 -0.668296 0.889344 +28 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +18 -0.668296 0.889344 +29 -0.68061 0.647541 +19 -0.614863 0.889344 +SURF 0x10 +mat 2 +refs 3 +30 -0.623268 0.647541 +19 -0.614863 0.889344 +29 -0.68061 0.647541 +SURF 0x10 +mat 2 +refs 3 +19 -0.614863 0.889344 +30 -0.623268 0.647541 +20 -0.524962 0.889344 +SURF 0x10 +mat 2 +refs 3 +31 -0.526789 0.647541 +20 -0.524962 0.889344 +30 -0.623268 0.647541 +SURF 0x10 +mat 2 +refs 3 +20 -0.524962 0.889344 +31 -0.526789 0.647541 +21 -0.427136 0.889344 +SURF 0x10 +mat 2 +refs 3 +32 -0.421804 0.647541 +21 -0.427136 0.889344 +31 -0.526789 0.647541 +SURF 0x10 +mat 2 +refs 3 +21 -0.427136 0.889344 +32 -0.421804 0.647541 +22 -0.352443 0.889344 +SURF 0x10 +mat 2 +refs 3 +33 -0.341646 0.647541 +22 -0.352443 0.889344 +32 -0.421804 0.647541 +SURF 0x10 +mat 2 +refs 3 +22 -0.352443 0.889344 +33 -0.341646 0.647541 +12 -0.324599 0.889344 +SURF 0x10 +mat 2 +refs 3 +23 -0.311765 0.647541 +12 -0.324599 0.889344 +33 -0.341646 0.647541 +SURF 0x10 +mat 2 +refs 3 +23 -1 0.647541 +34 -1 0.545082 +24 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +35 -1 0.545082 +24 -1 0.647541 +34 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +24 -1 0.647541 +35 -1 0.545082 +25 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +36 -1 0.545082 +25 -1 0.647541 +35 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +25 -1 0.647541 +36 -1 0.545082 +26 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +37 -1 0.545082 +26 -1 0.647541 +36 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +26 -1 0.647541 +37 -1 0.545082 +27 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +38 -1 0.545082 +27 -1 0.647541 +37 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +27 -1 0.647541 +38 -1 0.545082 +28 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +39 -1 0.545082 +28 -1 0.647541 +38 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +28 -1 0.647541 +39 -1 0.545082 +29 -0.68061 0.647541 +SURF 0x10 +mat 2 +refs 3 +40 -0.750392 0.545082 +29 -0.68061 0.647541 +39 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +29 -0.68061 0.647541 +40 -0.750392 0.545082 +30 -0.623268 0.647541 +SURF 0x10 +mat 2 +refs 3 +41 -0.670894 0.545082 +30 -0.623268 0.647541 +40 -0.750392 0.545082 +SURF 0x10 +mat 2 +refs 3 +30 -0.623268 0.647541 +41 -0.670894 0.545082 +31 -0.526789 0.647541 +SURF 0x10 +mat 2 +refs 3 +42 -0.537139 0.545082 +31 -0.526789 0.647541 +41 -0.670894 0.545082 +SURF 0x10 +mat 2 +refs 3 +31 -0.526789 0.647541 +42 -0.537139 0.545082 +32 -0.421804 0.647541 +SURF 0x10 +mat 2 +refs 3 +43 -0.391592 0.545082 +32 -0.421804 0.647541 +42 -0.537139 0.545082 +SURF 0x10 +mat 2 +refs 3 +32 -0.421804 0.647541 +43 -0.391592 0.545082 +33 -0.341646 0.647541 +SURF 0x10 +mat 2 +refs 3 +44 -0.280464 0.545082 +33 -0.341646 0.647541 +43 -0.391592 0.545082 +SURF 0x10 +mat 2 +refs 3 +33 -0.341646 0.647541 +44 -0.280464 0.545082 +23 -0.311765 0.647541 +SURF 0x10 +mat 2 +refs 3 +34 -0.239037 0.545082 +23 -0.311765 0.647541 +44 -0.280464 0.545082 +SURF 0x10 +mat 2 +refs 3 +34 -1 0.545082 +45 -1 0.442623 +35 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +46 -1 0.442623 +35 -1 0.545082 +45 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +35 -1 0.545082 +46 -1 0.442623 +36 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +47 -1 0.442623 +36 -1 0.545082 +46 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +36 -1 0.545082 +47 -1 0.442623 +37 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +48 -1 0.442623 +37 -1 0.545082 +47 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +37 -1 0.545082 +48 -1 0.442623 +38 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +49 -1 0.442623 +38 -1 0.545082 +48 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +38 -1 0.545082 +49 -1 0.442623 +39 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +50 -1 0.442623 +39 -1 0.545082 +49 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +39 -1 0.545082 +50 -1 0.442623 +40 -0.750392 0.545082 +SURF 0x10 +mat 2 +refs 3 +51 -0.820173 0.442623 +40 -0.750392 0.545082 +50 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +40 -0.750392 0.545082 +51 -0.820173 0.442623 +41 -0.670894 0.545082 +SURF 0x10 +mat 2 +refs 3 +52 -0.71852 0.442623 +41 -0.670894 0.545082 +51 -0.820173 0.442623 +SURF 0x10 +mat 2 +refs 3 +41 -0.670894 0.545082 +52 -0.71852 0.442623 +42 -0.537139 0.545082 +SURF 0x10 +mat 2 +refs 3 +53 -0.547489 0.442623 +42 -0.537139 0.545082 +52 -0.71852 0.442623 +SURF 0x10 +mat 2 +refs 3 +42 -0.537139 0.545082 +53 -0.547489 0.442623 +43 -0.391592 0.545082 +SURF 0x10 +mat 2 +refs 3 +54 -0.36138 0.442623 +43 -0.391592 0.545082 +53 -0.547489 0.442623 +SURF 0x10 +mat 2 +refs 3 +43 -0.391592 0.545082 +54 -0.36138 0.442623 +44 -0.280464 0.545082 +SURF 0x10 +mat 2 +refs 3 +55 -0.219282 0.442623 +44 -0.280464 0.545082 +54 -0.36138 0.442623 +SURF 0x10 +mat 2 +refs 3 +44 -0.280464 0.545082 +55 -0.219282 0.442623 +34 -0.239037 0.545082 +SURF 0x10 +mat 2 +refs 3 +45 -0.16631 0.442623 +34 -0.239037 0.545082 +55 -0.219282 0.442623 +SURF 0x10 +mat 2 +refs 3 +45 -1 0.442623 +56 -1 0.340164 +46 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +57 -1 0.340164 +46 -1 0.442623 +56 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +46 -1 0.442623 +57 -1 0.340164 +47 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +58 -1 0.340164 +47 -1 0.442623 +57 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +47 -1 0.442623 +58 -1 0.340164 +48 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +59 -1 0.340164 +48 -1 0.442623 +58 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +48 -1 0.442623 +59 -1 0.340164 +49 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +60 -1 0.340164 +49 -1 0.442623 +59 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +49 -1 0.442623 +60 -1 0.340164 +50 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +61 -1 0.340164 +50 -1 0.442623 +60 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +50 -1 0.442623 +61 -1 0.340164 +51 -0.820173 0.442623 +SURF 0x10 +mat 2 +refs 3 +62 -0.857116 0.340164 +51 -0.820173 0.442623 +61 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +51 -0.820173 0.442623 +62 -0.857116 0.340164 +52 -0.71852 0.442623 +SURF 0x10 +mat 2 +refs 3 +63 -0.743734 0.340164 +52 -0.71852 0.442623 +62 -0.857116 0.340164 +SURF 0x10 +mat 2 +refs 3 +52 -0.71852 0.442623 +63 -0.743734 0.340164 +53 -0.547489 0.442623 +SURF 0x10 +mat 2 +refs 3 +64 -0.552969 0.340164 +53 -0.547489 0.442623 +63 -0.743734 0.340164 +SURF 0x10 +mat 2 +refs 3 +53 -0.547489 0.442623 +64 -0.552969 0.340164 +54 -0.36138 0.442623 +SURF 0x10 +mat 2 +refs 3 +65 -0.345386 0.340164 +54 -0.36138 0.442623 +64 -0.552969 0.340164 +SURF 0x10 +mat 2 +refs 3 +54 -0.36138 0.442623 +65 -0.345386 0.340164 +55 -0.219282 0.442623 +SURF 0x10 +mat 2 +refs 3 +66 -0.186892 0.340164 +55 -0.219282 0.442623 +65 -0.345386 0.340164 +SURF 0x10 +mat 2 +refs 3 +55 -0.219282 0.442623 +66 -0.186892 0.340164 +45 -0.16631 0.442623 +SURF 0x10 +mat 2 +refs 3 +56 -0.127807 0.340164 +45 -0.16631 0.442623 +66 -0.186892 0.340164 +SURF 0x10 +mat 2 +refs 3 +56 -1 0.340164 +67 -1 0.241803 +57 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +68 -1 0.241803 +57 -1 0.340164 +67 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +57 -1 0.340164 +68 -1 0.241803 +58 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +69 -1 0.241803 +58 -1 0.340164 +68 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +58 -1 0.340164 +69 -1 0.241803 +59 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +70 -1 0.241803 +59 -1 0.340164 +69 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +59 -1 0.340164 +70 -1 0.241803 +60 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +71 -1 0.241803 +60 -1 0.340164 +70 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +60 -1 0.340164 +71 -1 0.241803 +61 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +72 -1 0.241803 +61 -1 0.340164 +71 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +61 -1 0.340164 +72 -1 0.241803 +62 -0.857116 0.340164 +SURF 0x10 +mat 2 +refs 3 +73 -0.853011 0.241803 +62 -0.857116 0.340164 +72 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +62 -0.857116 0.340164 +73 -0.853011 0.241803 +63 -0.743734 0.340164 +SURF 0x10 +mat 2 +refs 3 +74 -0.740933 0.241803 +63 -0.743734 0.340164 +73 -0.853011 0.241803 +SURF 0x10 +mat 2 +refs 3 +63 -0.743734 0.340164 +74 -0.740933 0.241803 +64 -0.552969 0.340164 +SURF 0x10 +mat 2 +refs 3 +75 -0.55236 0.241803 +64 -0.552969 0.340164 +74 -0.740933 0.241803 +SURF 0x10 +mat 2 +refs 3 +64 -0.552969 0.340164 +75 -0.55236 0.241803 +65 -0.345386 0.340164 +SURF 0x10 +mat 2 +refs 3 +76 -0.347163 0.241803 +65 -0.345386 0.340164 +75 -0.55236 0.241803 +SURF 0x10 +mat 2 +refs 3 +65 -0.345386 0.340164 +76 -0.347163 0.241803 +66 -0.186892 0.340164 +SURF 0x10 +mat 2 +refs 3 +77 -0.190491 0.241803 +66 -0.186892 0.340164 +76 -0.347163 0.241803 +SURF 0x10 +mat 2 +refs 3 +66 -0.186892 0.340164 +77 -0.190491 0.241803 +56 -0.127807 0.340164 +SURF 0x10 +mat 2 +refs 3 +67 -0.132086 0.241803 +56 -0.127807 0.340164 +77 -0.190491 0.241803 +SURF 0x10 +mat 2 +refs 3 +67 -1 0.241803 +78 -1 0.0901639 +68 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +79 -1 0.0901639 +68 -1 0.241803 +78 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +68 -1 0.241803 +79 -1 0.0901639 +69 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +80 -1 0.0901639 +69 -1 0.241803 +79 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +69 -1 0.241803 +80 -1 0.0901639 +70 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +81 -1 0.0901639 +70 -1 0.241803 +80 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +70 -1 0.241803 +81 -1 0.0901639 +71 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +82 -1 0.0901639 +71 -1 0.241803 +81 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +71 -1 0.241803 +82 -1 0.0901639 +72 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +83 -1 0.0901639 +72 -1 0.241803 +82 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +72 -1 0.241803 +83 -1 0.0901639 +73 -0.853011 0.241803 +SURF 0x10 +mat 2 +refs 3 +84 -0.807859 0.0901639 +73 -0.853011 0.241803 +83 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +73 -0.853011 0.241803 +84 -0.807859 0.0901639 +74 -0.740933 0.241803 +SURF 0x10 +mat 2 +refs 3 +85 -0.710116 0.0901639 +74 -0.740933 0.241803 +84 -0.807859 0.0901639 +SURF 0x10 +mat 2 +refs 3 +74 -0.740933 0.241803 +85 -0.710116 0.0901639 +75 -0.55236 0.241803 +SURF 0x10 +mat 2 +refs 3 +86 -0.545663 0.0901639 +75 -0.55236 0.241803 +85 -0.710116 0.0901639 +SURF 0x10 +mat 2 +refs 3 +75 -0.55236 0.241803 +86 -0.545663 0.0901639 +76 -0.347163 0.241803 +SURF 0x10 +mat 2 +refs 3 +87 -0.366712 0.0901639 +76 -0.347163 0.241803 +86 -0.545663 0.0901639 +SURF 0x10 +mat 2 +refs 3 +76 -0.347163 0.241803 +87 -0.366712 0.0901639 +77 -0.190491 0.241803 +SURF 0x10 +mat 2 +refs 3 +88 -0.230079 0.0901639 +77 -0.190491 0.241803 +87 -0.366712 0.0901639 +SURF 0x10 +mat 2 +refs 3 +77 -0.190491 0.241803 +88 -0.230079 0.0901639 +67 -0.132086 0.241803 +SURF 0x10 +mat 2 +refs 3 +78 -0.179144 0.0901639 +67 -0.132086 0.241803 +88 -0.230079 0.0901639 +SURF 0x10 +mat 2 +refs 3 +78 -1 0.0901639 +89 -1 0.00819672 +79 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +90 -1 0.00819672 +79 -1 0.0901639 +89 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +79 -1 0.0901639 +90 -1 0.00819672 +80 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +91 -1 0.00819672 +80 -1 0.0901639 +90 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +80 -1 0.0901639 +91 -1 0.00819672 +81 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +92 -1 0.00819672 +81 -1 0.0901639 +91 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +81 -1 0.0901639 +92 -1 0.00819672 +82 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +93 -1 0.00819672 +82 -1 0.0901639 +92 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +82 -1 0.0901639 +93 -1 0.00819672 +83 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +94 -1 0.00819672 +83 -1 0.0901639 +93 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +83 -1 0.0901639 +94 -1 0.00819672 +84 -0.807859 0.0901639 +SURF 0x10 +mat 2 +refs 3 +95 -0.643667 0.00819672 +84 -0.807859 0.0901639 +94 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +84 -0.807859 0.0901639 +95 -0.643667 0.00819672 +85 -0.710116 0.0901639 +SURF 0x10 +mat 2 +refs 3 +96 -0.598054 0.00819672 +85 -0.710116 0.0901639 +95 -0.643667 0.00819672 +SURF 0x10 +mat 2 +refs 3 +85 -0.710116 0.0901639 +96 -0.598054 0.00819672 +86 -0.545663 0.0901639 +SURF 0x10 +mat 2 +refs 3 +97 -0.521309 0.00819672 +86 -0.545663 0.0901639 +96 -0.598054 0.00819672 +SURF 0x10 +mat 2 +refs 3 +86 -0.545663 0.0901639 +97 -0.521309 0.00819672 +87 -0.366712 0.0901639 +SURF 0x10 +mat 2 +refs 3 +98 -0.437799 0.00819672 +87 -0.366712 0.0901639 +97 -0.521309 0.00819672 +SURF 0x10 +mat 2 +refs 3 +87 -0.366712 0.0901639 +98 -0.437799 0.00819672 +88 -0.230079 0.0901639 +SURF 0x10 +mat 2 +refs 3 +99 -0.374037 0.00819672 +88 -0.230079 0.0901639 +98 -0.437799 0.00819672 +SURF 0x10 +mat 2 +refs 3 +88 -0.230079 0.0901639 +99 -0.374037 0.00819672 +78 -0.179144 0.0901639 +SURF 0x10 +mat 2 +refs 3 +89 -0.350267 0.00819672 +78 -0.179144 0.0901639 +99 -0.374037 0.00819672 +SURF 0x10 +mat 0 +refs 3 +100 0 0 +101 0 0 +102 0 0 +SURF 0x10 +mat 0 +refs 3 +103 0 0 +102 0 0 +101 0 0 +SURF 0x10 +mat 0 +refs 3 +102 0 0 +103 0 0 +104 0 0 +SURF 0x10 +mat 0 +refs 3 +105 0 0 +104 0 0 +103 0 0 +SURF 0x10 +mat 0 +refs 3 +104 0 0 +105 0 0 +106 0 0 +SURF 0x10 +mat 0 +refs 2 +105 0 0 +106 0 0 +SURF 0x10 +mat 0 +refs 2 +105 0 0 +106 0 0 +SURF 0x10 +mat 0 +refs 3 +106 0 0 +105 0 0 +104 0 0 +SURF 0x10 +mat 0 +refs 3 +103 0 0 +104 0 0 +105 0 0 +SURF 0x10 +mat 0 +refs 3 +104 0 0 +103 0 0 +102 0 0 +SURF 0x10 +mat 0 +refs 3 +107 0 0 +108 0 0 +109 0 0 +SURF 0x10 +mat 0 +refs 3 +110 0 0 +109 0 0 +108 0 0 +SURF 0x10 +mat 0 +refs 3 +109 0 0 +110 0 0 +111 0 0 +SURF 0x10 +mat 0 +refs 3 +112 0 0 +111 0 0 +110 0 0 +SURF 0x10 +mat 0 +refs 3 +111 0 0 +112 0 0 +113 0 0 +SURF 0x10 +mat 0 +refs 2 +112 0 0 +113 0 0 +SURF 0x10 +mat 0 +refs 2 +112 0 0 +113 0 0 +SURF 0x10 +mat 0 +refs 3 +113 0 0 +112 0 0 +111 0 0 +SURF 0x10 +mat 0 +refs 3 +110 0 0 +111 0 0 +112 0 0 +SURF 0x10 +mat 0 +refs 3 +111 0 0 +110 0 0 +109 0 0 +SURF 0x10 +mat 2 +refs 3 +89 -1 0.00819672 +114 -1 0 +90 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +90 -1 0.00819672 +114 -1 0 +91 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +91 -1 0.00819672 +114 -1 0 +92 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +92 -1 0.00819672 +114 -1 0 +93 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +93 -1 0.00819672 +114 -1 0 +94 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +94 -1 0.00819672 +114 -1 0 +95 -0.643667 0.00819672 +SURF 0x10 +mat 2 +refs 3 +95 -0.643667 0.00819672 +114 -0.5 0 +96 -0.598054 0.00819672 +SURF 0x10 +mat 2 +refs 3 +96 -0.598054 0.00819672 +114 -0.5 0 +97 -0.521309 0.00819672 +SURF 0x10 +mat 2 +refs 3 +97 -0.521309 0.00819672 +114 -0.5 0 +98 -0.437799 0.00819672 +SURF 0x10 +mat 2 +refs 3 +98 -0.437799 0.00819672 +114 -0.5 0 +99 -0.374037 0.00819672 +SURF 0x10 +mat 2 +refs 3 +99 -0.374037 0.00819672 +114 -0.5 0 +89 -0.350267 0.00819672 +kids 0 +OBJECT poly +name "tuxbeak" +loc -0.0328128 0.372259 0.086667 +texture "Penguin_beak.rgb" +numvert 17 +0.0565685 0.514 0.1 +1.11759e-08 0.5 0.125 +0.08 0.5 0.1 +1.11759e-08 0.528 0.1 +-0.0565685 0.514 0.1 +-0.08 0.5 0.1 +-0.0565685 0.486 0.1 +1.11759e-08 0.472 0.1 +0.0565685 0.486 0.1 +0.16 0.5 -0.125 +0.113137 0.556 -0.125 +1.11759e-08 0.612 -0.125 +-0.113137 0.556 -0.125 +-0.16 0.5 -0.125 +-0.113137 0.444 -0.125 +1.11759e-08 0.388 -0.125 +0.113137 0.444 -0.125 +numsurf 24 +SURF 0x10 +mat 2 +refs 3 +0 -0.342865 -0.342865 +1 -0.5 -0.5 +2 -0.277778 -0.5 +SURF 0x10 +mat 2 +refs 3 +3 -0.5 -0.277778 +1 -0.5 -0.5 +0 -0.342865 -0.342865 +SURF 0x10 +mat 2 +refs 3 +4 -0.657135 -0.342865 +1 -0.5 -0.5 +3 -0.5 -0.277778 +SURF 0x10 +mat 2 +refs 3 +5 -0.722222 -0.5 +1 -0.5 -0.5 +4 -0.657135 -0.342865 +SURF 0x10 +mat 2 +refs 3 +6 -0.657135 -0.657135 +1 -0.5 -0.5 +5 -0.722222 -0.5 +SURF 0x10 +mat 2 +refs 3 +7 -0.5 -0.722222 +1 -0.5 -0.5 +6 -0.657135 -0.657135 +SURF 0x10 +mat 2 +refs 3 +8 -0.342865 -0.657135 +1 -0.5 -0.5 +7 -0.5 -0.722222 +SURF 0x10 +mat 2 +refs 3 +2 -0.277778 -0.5 +1 -0.5 -0.5 +8 -0.342865 -0.657135 +SURF 0x10 +mat 2 +refs 3 +2 -0.277778 -0.5 +9 -0.0555556 -0.5 +0 -0.342865 -0.342865 +SURF 0x10 +mat 2 +refs 3 +10 -0.18573 -0.18573 +0 -0.342865 -0.342865 +9 -0.0555556 -0.5 +SURF 0x10 +mat 2 +refs 3 +0 -0.342865 -0.342865 +10 -0.18573 -0.18573 +3 -0.5 -0.277778 +SURF 0x10 +mat 2 +refs 3 +11 -0.5 -0.0555556 +3 -0.5 -0.277778 +10 -0.18573 -0.18573 +SURF 0x10 +mat 2 +refs 3 +3 -0.5 -0.277778 +11 -0.5 -0.0555556 +4 -0.657135 -0.342865 +SURF 0x10 +mat 2 +refs 3 +12 -0.81427 -0.18573 +4 -0.657135 -0.342865 +11 -0.5 -0.0555556 +SURF 0x10 +mat 2 +refs 3 +4 -0.657135 -0.342865 +12 -0.81427 -0.18573 +5 -0.722222 -0.5 +SURF 0x10 +mat 2 +refs 3 +13 -0.944444 -0.5 +5 -0.722222 -0.5 +12 -0.81427 -0.18573 +SURF 0x10 +mat 2 +refs 3 +5 -0.722222 -0.5 +13 -0.944444 -0.5 +6 -0.657135 -0.657135 +SURF 0x10 +mat 2 +refs 3 +14 -0.81427 -0.81427 +6 -0.657135 -0.657135 +13 -0.944444 -0.5 +SURF 0x10 +mat 2 +refs 3 +6 -0.657135 -0.657135 +14 -0.81427 -0.81427 +7 -0.5 -0.722222 +SURF 0x10 +mat 2 +refs 3 +15 -0.5 -0.944444 +7 -0.5 -0.722222 +14 -0.81427 -0.81427 +SURF 0x10 +mat 2 +refs 3 +7 -0.5 -0.722222 +15 -0.5 -0.944444 +8 -0.342865 -0.657135 +SURF 0x10 +mat 2 +refs 3 +16 -0.18573 -0.81427 +8 -0.342865 -0.657135 +15 -0.5 -0.944444 +SURF 0x10 +mat 2 +refs 3 +8 -0.342865 -0.657135 +16 -0.18573 -0.81427 +2 -0.277778 -0.5 +SURF 0x10 +mat 2 +refs 3 +9 -0.0555556 -0.5 +2 -0.277778 -0.5 +16 -0.18573 -0.81427 +kids 0 diff --git a/examples/src/ssg/load_save/data/wood.rgb b/examples/src/ssg/load_save/data/wood.rgb new file mode 100644 index 0000000..3094af0 Binary files /dev/null and b/examples/src/ssg/load_save/data/wood.rgb differ diff --git a/examples/src/ssg/load_save/load.cxx b/examples/src/ssg/load_save/load.cxx new file mode 100644 index 0000000..3af3d36 --- /dev/null +++ b/examples/src/ssg/load_save/load.cxx @@ -0,0 +1,234 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: load.cxx 2099 2006-11-03 20:04:40Z fayjf $ +*/ + + +#include +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +static ssgRoot *scene = NULL ; +static ssgTransform *penguin = NULL ; +static ssgTransform *pedestal = NULL ; + +/* + Something to make some interesting motion + for both Tux and the camera. +*/ + +static void update_motion () +{ + static int frameno = 0 ; + + frameno++ ; + + sgCoord campos ; + sgCoord tuxpos ; + + /* + Spin Tux, make the camera pan sinusoidally left and right + */ + + sgSetCoord ( & campos, 0.0f, -5.0f, 1.0f, 25.0f * (float)sin(frameno/100.0), 0.0f, 0.0f ) ; + sgSetCoord ( & tuxpos, 0.0f, 0.0f, 0.0f, (float)frameno, 0.0f, 0.0f ) ; + + ssgSetCamera ( & campos ) ; + penguin -> setTransform ( & tuxpos ) ; +} + + + +/* + The GLUT window reshape event +*/ + +static void reshape ( int w, int h ) +{ + glViewport ( 0, 0, w, h ) ; +} + + + +/* + The GLUT keyboard event +*/ + +static void keyboard ( unsigned char, int, int ) +{ + exit ( 0 ) ; +} + + + +/* + The GLUT redraw event +*/ + +static void redraw () +{ + update_motion () ; + + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + ssgCullAndDraw ( scene ) ; + + glutPostRedisplay () ; + glutSwapBuffers () ; +} + + + +static void init_graphics () +{ + int fake_argc = 1 ; + char *fake_argv[3] ; + fake_argv[0] = "ssgExample" ; + fake_argv[1] = "Simple Scene Graph : Example Program." ; + fake_argv[2] = NULL ; + + /* + Initialise GLUT + */ + + glutInitWindowPosition ( 0, 0 ) ; + glutInitWindowSize ( 640, 480 ) ; + glutInit ( &fake_argc, fake_argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + glutCreateWindow ( fake_argv[1] ) ; + glutDisplayFunc ( redraw ) ; + glutReshapeFunc ( reshape ) ; + glutKeyboardFunc ( keyboard ) ; + + /* + Initialise SSG + */ + + ssgInit () ; + + /* + Some basic OpenGL setup + */ + + glClearColor ( 0.2f, 0.7f, 1.0f, 1.0f ) ; + glEnable ( GL_DEPTH_TEST ) ; + + /* + Set up the viewing parameters + */ + + ssgSetFOV ( 60.0f, 0.0f ) ; + ssgSetNearFar ( 1.0f, 700.0f ) ; + + /* + Set up the Sun. + */ + + sgVec3 sunposn ; + sgSetVec3 ( sunposn, 0.2f, -0.5f, 0.5f ) ; + ssgGetLight ( 0 ) -> setPosition ( sunposn ) ; +} + + +/* + Load a simple database +*/ + +static void load_database () +{ + /* + Set up the path to the data files + */ + + ssgModelPath ( "data" ) ; + ssgTexturePath ( "data" ) ; + + /* + Create a root node - and a transform to position + the pedestal - and another to position the penguin + beneath that (in the tree that is). + */ + + scene = new ssgRoot ; + pedestal = new ssgTransform ; + penguin = new ssgTransform ; + + /* + Load the models - optimise them a bit + and then add them into the scene. + */ + + ssgEntity *ped_obj = ssgLoadAC ( "pedestal.ac" ) ; + ssgEntity *tux_obj = ssgLoadSSG ( "tuxedo.ssg" ) ; + + if ( ped_obj == NULL ) + ulSetError ( UL_FATAL, "Cannot load pedastal.ac" ) ; + if ( tux_obj == NULL ) + ulSetError ( UL_FATAL, "Cannot load tuxedo.ssg -- Please run 'save' first" ) ; + + tux_obj->print(); + + penguin -> addKid ( tux_obj ) ; + pedestal -> addKid ( ped_obj ) ; + + /*ssgFlatten ( tux_obj ) ;*/ + ssgFlatten ( ped_obj ) ; + /*ssgStripify ( penguin ) ;*/ + ssgStripify ( pedestal ) ; + + pedestal -> addKid ( penguin ) ; + scene -> addKid ( pedestal ) ; +} + + + +/* + The works. +*/ + +int main ( int, char ** ) +{ + init_graphics () ; + load_database () ; + glutMainLoop () ; + return 0 ; +} + + + diff --git a/examples/src/ssg/load_save/load.dsp b/examples/src/ssg/load_save/load.dsp new file mode 100644 index 0000000..59dd658 --- /dev/null +++ b/examples/src/ssg/load_save/load.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="load" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=load - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "load.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "load.mak" CFG="load - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "load - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "load - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "load - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg.lib sg.lib ul.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /machine:I386 /out:"load.exe" /libpath:"..\..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "load - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg_d.lib sg_d.lib ul_d.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /debug /machine:I386 /out:"load.exe" /pdbtype:sept /libpath:"..\..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "load - Win32 Release" +# Name "load - Win32 Debug" +# Begin Source File + +SOURCE=.\load.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/ssg/load_save/save.cxx b/examples/src/ssg/load_save/save.cxx new file mode 100644 index 0000000..4525afd --- /dev/null +++ b/examples/src/ssg/load_save/save.cxx @@ -0,0 +1,131 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: save.cxx 1551 2002-09-01 12:04:53Z ude $ +*/ + + +#include +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +static ssgRoot *scene = NULL ; +static ssgTransform *object = NULL ; +static ssgEntity *obj_obj = NULL ; + + +static void redraw () +{ + return ; +} + + +static void init_graphics () +{ + int fake_argc = 1 ; + char *fake_argv[3] ; + fake_argv[0] = "ssgExample" ; + fake_argv[1] = "Simple Scene Graph : Example Program." ; + fake_argv[2] = NULL ; + + /* + Initialise GLUT + */ + + glutInitWindowPosition ( 0, 0 ) ; + glutInitWindowSize ( 640, 480 ) ; + glutInit ( &fake_argc, fake_argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + glutCreateWindow ( fake_argv[1] ) ; + glutDisplayFunc ( redraw ) ; + + /* + Initialise SSG + */ + + ssgInit () ; +} + + +static void load_database () +{ + /* + Set up the path to the data files + */ + + ssgModelPath ( "data" ) ; + ssgTexturePath ( "data" ) ; + + /* + Create a root node - and a transform to position + the object beneath that (in the tree that is). + */ + + scene = new ssgRoot ; + object = new ssgTransform ; + + /* + Load the models - optimise them a bit + and then add them into the scene. + */ + + obj_obj = ssgLoadAC ( "tuxedo.ac" ) ; + + object -> addKid ( obj_obj ) ; + + ssgFlatten ( obj_obj ) ; + ssgStripify ( object ) ; + scene -> addKid ( object ) ; +} + + +static void save_database () +{ + ssgSaveSSG ( "data/tuxedo.ssg", object ) ; +} + + + +int main ( int, char ** ) +{ + init_graphics () ; + load_database () ; + save_database () ; + return 0 ; +} + diff --git a/examples/src/ssg/load_save/save.dsp b/examples/src/ssg/load_save/save.dsp new file mode 100644 index 0000000..2d3fd23 --- /dev/null +++ b/examples/src/ssg/load_save/save.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="save" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=save - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "save.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "save.mak" CFG="save - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "save - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "save - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "save - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg.lib sg.lib ul.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /machine:I386 /out:"save.exe" /libpath:"..\..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "save - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg_d.lib sg_d.lib ul_d.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /debug /machine:I386 /out:"save.exe" /pdbtype:sept /libpath:"..\..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "save - Win32 Release" +# Name "save - Win32 Debug" +# Begin Source File + +SOURCE=.\save.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/ssg/majik/Makefile.am b/examples/src/ssg/majik/Makefile.am new file mode 100644 index 0000000..7375cb1 --- /dev/null +++ b/examples/src/ssg/majik/Makefile.am @@ -0,0 +1,14 @@ +if BUILD_SSG + +noinst_PROGRAMS = majik_demo + +majik_demo_SOURCES = elevation_map.h \ + image_map.h \ + majik_demo.cxx + +majik_demo_LDADD = -lplibjs -lplibssg -lplibsg -lplibul $(GLUT_LIBS) $(OGL_LIBS) + +endif + +EXTRA_DIST = majik_demo.dsp + diff --git a/examples/src/ssg/majik/data/Penguin_beak.rgb b/examples/src/ssg/majik/data/Penguin_beak.rgb new file mode 100644 index 0000000..b1e0e79 Binary files /dev/null and b/examples/src/ssg/majik/data/Penguin_beak.rgb differ diff --git a/examples/src/ssg/majik/data/Penguin_body.rgb b/examples/src/ssg/majik/data/Penguin_body.rgb new file mode 100644 index 0000000..1ba0f4b Binary files /dev/null and b/examples/src/ssg/majik/data/Penguin_body.rgb differ diff --git a/examples/src/ssg/majik/data/bumpnoise.rgb b/examples/src/ssg/majik/data/bumpnoise.rgb new file mode 100644 index 0000000..5cac5ee Binary files /dev/null and b/examples/src/ssg/majik/data/bumpnoise.rgb differ diff --git a/examples/src/ssg/majik/data/majik.rgb b/examples/src/ssg/majik/data/majik.rgb new file mode 100644 index 0000000..9ff1262 Binary files /dev/null and b/examples/src/ssg/majik/data/majik.rgb differ diff --git a/examples/src/ssg/majik/data/tuxedo.ac b/examples/src/ssg/majik/data/tuxedo.ac new file mode 100644 index 0000000..12e4754 --- /dev/null +++ b/examples/src/ssg/majik/data/tuxedo.ac @@ -0,0 +1,1695 @@ +AC3Db +MATERIAL "" rgb 0 0 0 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "" rgb 1 0.702 0 amb 1 0.702 0 emis 0 0 0 spec 0 0 0 shi 0 trans 0 +MATERIAL "" rgb 1 1 1 amb 1 1 1 emis 0 0 0 spec 0 0 0 shi 0 trans 0 +OBJECT world +kids 1 +OBJECT group +name "Tuxedo.T.Penguin" +kids 3 +OBJECT poly +name "tuxfeet" +loc 0.0203744 -0.479517 0.101666 +numvert 14 +-0.0744405 0.473224 0.119889 +0.100559 0.473224 -0.200111 +0.175559 0.473224 0.199889 +0.250559 0.473224 -0.200111 +0.425559 0.473224 0.119889 +0.250559 0.523224 -0.200111 +0.100559 0.523224 -0.200111 +-0.425559 0.476776 0.120111 +-0.25056 0.476776 -0.199889 +-0.17556 0.476776 0.200111 +-0.100559 0.476776 -0.199889 +0.0744405 0.476776 0.120111 +-0.100559 0.526776 -0.199889 +-0.25056 0.526776 -0.199889 +numsurf 12 +SURF 0x0 +mat 1 +refs 3 +0 0 0.1 +1 0.9 0 +2 0 0.8 +SURF 0x0 +mat 1 +refs 3 +3 1 0.1 +2 0 0.8 +1 0.9 0 +SURF 0x0 +mat 1 +refs 3 +2 0 0.8 +3 1 0.1 +4 0.5 1 +SURF 0x0 +mat 1 +refs 3 +4 0.5 1 +5 1 0.1 +2 0 0.8 +SURF 0x0 +mat 1 +refs 3 +6 0.9 0 +2 0 0.8 +5 1 0.1 +SURF 0x0 +mat 1 +refs 3 +2 0 0.8 +6 0.9 0 +0 0 0.1 +SURF 0x0 +mat 1 +refs 3 +7 0 0.1 +8 0.9 0 +9 0 0.8 +SURF 0x0 +mat 1 +refs 3 +10 1 0.1 +9 0 0.8 +8 0.9 0 +SURF 0x0 +mat 1 +refs 3 +9 0 0.8 +10 1 0.1 +11 0.5 1 +SURF 0x0 +mat 1 +refs 3 +11 0.5 1 +12 1 0.1 +9 0 0.8 +SURF 0x0 +mat 1 +refs 3 +13 0.9 0 +9 0 0.8 +12 1 0.1 +SURF 0x0 +mat 1 +refs 3 +9 0 0.8 +13 0.9 0 +7 0 0.1 +kids 0 +OBJECT poly +name "tuxbody" +loc 0.0124385 0.107258 -0.188333 +texture "Penguin_body.rgb" +numvert 115 +0.097524 1.07 -0.0756895 +-0.0202512 1.11 0 +0.119749 1.07 0 +0.0379068 1.07 -0.127348 +-0.0401753 1.07 -0.138575 +-0.111932 1.07 -0.105805 +-0.154581 1.07 -0.0394426 +-0.154581 1.07 0.0394426 +-0.111932 1.07 0.105805 +-0.0401753 1.07 0.138575 +0.0379068 1.07 0.127348 +0.097524 1.07 0.0756895 +0.184749 0.975 0 +0.152205 0.975 -0.110831 +0.064909 0.975 -0.186475 +-0.0494259 0.975 -0.202913 +-0.154498 0.975 -0.154929 +-0.216947 0.975 -0.057755 +-0.216947 0.975 0.057755 +-0.154498 0.975 0.154929 +-0.0494259 0.975 0.202913 +0.064909 0.975 0.186475 +0.152205 0.975 0.110831 +0.199749 0.68 0 +0.164825 0.68 -0.118941 +0.07114 0.68 -0.200119 +-0.0515605 0.68 -0.217761 +-0.16432 0.68 -0.166265 +-0.231339 0.68 -0.061981 +-0.231339 0.68 0.061981 +-0.16432 0.68 0.166265 +-0.0515605 0.68 0.217761 +0.07114 0.68 0.200119 +0.164825 0.68 0.118941 +0.284749 0.555 0 +0.236331 0.555 -0.164896 +0.10645 0.555 -0.277438 +-0.0636575 0.555 -0.301895 +-0.219984 0.555 -0.230503 +-0.312897 0.555 -0.0859285 +-0.312897 0.555 0.0859285 +-0.219984 0.555 0.230503 +-0.0636575 0.555 0.301895 +0.10645 0.555 0.277438 +0.236331 0.555 0.164896 +0.369749 0.43 0 +0.307837 0.43 -0.21085 +0.14176 0.43 -0.354757 +-0.075754 0.43 -0.38603 +-0.275647 0.43 -0.294742 +-0.394453 0.43 -0.109876 +-0.394453 0.43 0.109876 +-0.275647 0.43 0.294742 +-0.075754 0.43 0.38603 +0.14176 0.43 0.354757 +0.307837 0.43 0.21085 +0.414749 0.305 0 +0.345694 0.305 -0.235179 +0.160454 0.305 -0.39569 +-0.0821585 0.305 -0.430573 +-0.305115 0.305 -0.328751 +-0.437631 0.305 -0.122553 +-0.437631 0.305 0.122553 +-0.305115 0.305 0.328751 +-0.0821585 0.305 0.430573 +0.160454 0.305 0.39569 +0.345694 0.305 0.235179 +0.409749 0.185 0 +0.341488 0.185 -0.232476 +0.158377 0.185 -0.391142 +-0.081447 0.185 -0.425623 +-0.301841 0.185 -0.324973 +-0.432833 0.185 -0.121145 +-0.432833 0.185 0.121145 +-0.301841 0.185 0.324973 +-0.081447 0.185 0.425623 +0.158377 0.185 0.391142 +0.341488 0.185 0.232476 +0.354748 2.23517e-08 0 +0.295219 2.23517e-08 -0.202741 +0.135529 2.23517e-08 -0.341112 +-0.0736195 2.23517e-08 -0.371183 +-0.265824 2.23517e-08 -0.283406 +-0.380061 2.23517e-08 -0.10565 +-0.380061 2.23517e-08 0.10565 +-0.265824 2.23517e-08 0.283406 +-0.0736195 2.23517e-08 0.371183 +0.135529 2.23517e-08 0.341112 +0.295219 2.23517e-08 0.202741 +0.154748 -0.1 0 +0.126968 -0.1 -0.094612 +0.052446 -0.1 -0.159185 +-0.0451563 -0.1 -0.173219 +-0.134852 -0.1 -0.132256 +-0.188163 -0.1 -0.0493032 +-0.188163 -0.1 0.0493032 +-0.134852 -0.1 0.132256 +-0.0451564 -0.1 0.173219 +0.052446 -0.1 0.159185 +0.126968 -0.1 0.094612 +0.211872 0.567025 0.1 +0.211872 0.567025 -0.1 +0.316872 0.532025 0.1 +0.316872 0.532025 -0.1 +0.456872 0.392025 0.1 +0.456872 0.392025 -0.1 +0.56187 0.217025 0 +-0.211873 0.58637 0.1 +-0.211873 0.58637 -0.1 +-0.316873 0.55137 0.1 +-0.316873 0.55137 -0.1 +-0.456872 0.41137 0.1 +-0.456872 0.41137 -0.1 +-0.56187 0.23637 0 +-0.0202512 -0.11 0 +numsurf 218 +SURF 0x10 +mat 2 +refs 3 +0 -1 0.967213 +1 -1 1 +2 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +3 -1 0.967213 +1 -1 1 +0 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +4 -1 0.967213 +1 -1 1 +3 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +5 -1 0.967213 +1 -1 1 +4 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +6 -1 0.967213 +1 -1 1 +5 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +7 -0.614934 0.967213 +1 -0.5 1 +6 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +8 -0.578443 0.967213 +1 -0.5 1 +7 -0.614934 0.967213 +SURF 0x10 +mat 2 +refs 3 +9 -0.517047 0.967213 +1 -0.5 1 +8 -0.578443 0.967213 +SURF 0x10 +mat 2 +refs 3 +10 -0.450239 0.967213 +1 -0.5 1 +9 -0.517047 0.967213 +SURF 0x10 +mat 2 +refs 3 +11 -0.39923 0.967213 +1 -0.5 1 +10 -0.450239 0.967213 +SURF 0x10 +mat 2 +refs 3 +2 -0.380214 0.967213 +1 -0.5 1 +11 -0.39923 0.967213 +SURF 0x10 +mat 2 +refs 3 +2 -1 0.967213 +12 -1 0.889344 +0 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +13 -1 0.889344 +0 -1 0.967213 +12 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +0 -1 0.967213 +13 -1 0.889344 +3 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +14 -1 0.889344 +3 -1 0.967213 +13 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +3 -1 0.967213 +14 -1 0.889344 +4 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +15 -1 0.889344 +4 -1 0.967213 +14 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +4 -1 0.967213 +15 -1 0.889344 +5 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +16 -1 0.889344 +5 -1 0.967213 +15 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +5 -1 0.967213 +16 -1 0.889344 +6 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +17 -1 0.889344 +6 -1 0.967213 +16 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +6 -1 0.967213 +17 -1 0.889344 +7 -0.614934 0.967213 +SURF 0x10 +mat 2 +refs 3 +18 -0.668296 0.889344 +7 -0.614934 0.967213 +17 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +7 -0.614934 0.967213 +18 -0.668296 0.889344 +8 -0.578443 0.967213 +SURF 0x10 +mat 2 +refs 3 +19 -0.614863 0.889344 +8 -0.578443 0.967213 +18 -0.668296 0.889344 +SURF 0x10 +mat 2 +refs 3 +8 -0.578443 0.967213 +19 -0.614863 0.889344 +9 -0.517047 0.967213 +SURF 0x10 +mat 2 +refs 3 +20 -0.524962 0.889344 +9 -0.517047 0.967213 +19 -0.614863 0.889344 +SURF 0x10 +mat 2 +refs 3 +9 -0.517047 0.967213 +20 -0.524962 0.889344 +10 -0.450239 0.967213 +SURF 0x10 +mat 2 +refs 3 +21 -0.427136 0.889344 +10 -0.450239 0.967213 +20 -0.524962 0.889344 +SURF 0x10 +mat 2 +refs 3 +10 -0.450239 0.967213 +21 -0.427136 0.889344 +11 -0.39923 0.967213 +SURF 0x10 +mat 2 +refs 3 +22 -0.352443 0.889344 +11 -0.39923 0.967213 +21 -0.427136 0.889344 +SURF 0x10 +mat 2 +refs 3 +11 -0.39923 0.967213 +22 -0.352443 0.889344 +2 -0.380214 0.967213 +SURF 0x10 +mat 2 +refs 3 +12 -0.324599 0.889344 +2 -0.380214 0.967213 +22 -0.352443 0.889344 +SURF 0x10 +mat 2 +refs 3 +12 -1 0.889344 +23 -1 0.647541 +13 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +24 -1 0.647541 +13 -1 0.889344 +23 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +13 -1 0.889344 +24 -1 0.647541 +14 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +25 -1 0.647541 +14 -1 0.889344 +24 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +14 -1 0.889344 +25 -1 0.647541 +15 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +26 -1 0.647541 +15 -1 0.889344 +25 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +15 -1 0.889344 +26 -1 0.647541 +16 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +27 -1 0.647541 +16 -1 0.889344 +26 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +16 -1 0.889344 +27 -1 0.647541 +17 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +28 -1 0.647541 +17 -1 0.889344 +27 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +17 -1 0.889344 +28 -1 0.647541 +18 -0.668296 0.889344 +SURF 0x10 +mat 2 +refs 3 +29 -0.68061 0.647541 +18 -0.668296 0.889344 +28 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +18 -0.668296 0.889344 +29 -0.68061 0.647541 +19 -0.614863 0.889344 +SURF 0x10 +mat 2 +refs 3 +30 -0.623268 0.647541 +19 -0.614863 0.889344 +29 -0.68061 0.647541 +SURF 0x10 +mat 2 +refs 3 +19 -0.614863 0.889344 +30 -0.623268 0.647541 +20 -0.524962 0.889344 +SURF 0x10 +mat 2 +refs 3 +31 -0.526789 0.647541 +20 -0.524962 0.889344 +30 -0.623268 0.647541 +SURF 0x10 +mat 2 +refs 3 +20 -0.524962 0.889344 +31 -0.526789 0.647541 +21 -0.427136 0.889344 +SURF 0x10 +mat 2 +refs 3 +32 -0.421804 0.647541 +21 -0.427136 0.889344 +31 -0.526789 0.647541 +SURF 0x10 +mat 2 +refs 3 +21 -0.427136 0.889344 +32 -0.421804 0.647541 +22 -0.352443 0.889344 +SURF 0x10 +mat 2 +refs 3 +33 -0.341646 0.647541 +22 -0.352443 0.889344 +32 -0.421804 0.647541 +SURF 0x10 +mat 2 +refs 3 +22 -0.352443 0.889344 +33 -0.341646 0.647541 +12 -0.324599 0.889344 +SURF 0x10 +mat 2 +refs 3 +23 -0.311765 0.647541 +12 -0.324599 0.889344 +33 -0.341646 0.647541 +SURF 0x10 +mat 2 +refs 3 +23 -1 0.647541 +34 -1 0.545082 +24 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +35 -1 0.545082 +24 -1 0.647541 +34 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +24 -1 0.647541 +35 -1 0.545082 +25 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +36 -1 0.545082 +25 -1 0.647541 +35 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +25 -1 0.647541 +36 -1 0.545082 +26 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +37 -1 0.545082 +26 -1 0.647541 +36 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +26 -1 0.647541 +37 -1 0.545082 +27 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +38 -1 0.545082 +27 -1 0.647541 +37 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +27 -1 0.647541 +38 -1 0.545082 +28 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +39 -1 0.545082 +28 -1 0.647541 +38 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +28 -1 0.647541 +39 -1 0.545082 +29 -0.68061 0.647541 +SURF 0x10 +mat 2 +refs 3 +40 -0.750392 0.545082 +29 -0.68061 0.647541 +39 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +29 -0.68061 0.647541 +40 -0.750392 0.545082 +30 -0.623268 0.647541 +SURF 0x10 +mat 2 +refs 3 +41 -0.670894 0.545082 +30 -0.623268 0.647541 +40 -0.750392 0.545082 +SURF 0x10 +mat 2 +refs 3 +30 -0.623268 0.647541 +41 -0.670894 0.545082 +31 -0.526789 0.647541 +SURF 0x10 +mat 2 +refs 3 +42 -0.537139 0.545082 +31 -0.526789 0.647541 +41 -0.670894 0.545082 +SURF 0x10 +mat 2 +refs 3 +31 -0.526789 0.647541 +42 -0.537139 0.545082 +32 -0.421804 0.647541 +SURF 0x10 +mat 2 +refs 3 +43 -0.391592 0.545082 +32 -0.421804 0.647541 +42 -0.537139 0.545082 +SURF 0x10 +mat 2 +refs 3 +32 -0.421804 0.647541 +43 -0.391592 0.545082 +33 -0.341646 0.647541 +SURF 0x10 +mat 2 +refs 3 +44 -0.280464 0.545082 +33 -0.341646 0.647541 +43 -0.391592 0.545082 +SURF 0x10 +mat 2 +refs 3 +33 -0.341646 0.647541 +44 -0.280464 0.545082 +23 -0.311765 0.647541 +SURF 0x10 +mat 2 +refs 3 +34 -0.239037 0.545082 +23 -0.311765 0.647541 +44 -0.280464 0.545082 +SURF 0x10 +mat 2 +refs 3 +34 -1 0.545082 +45 -1 0.442623 +35 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +46 -1 0.442623 +35 -1 0.545082 +45 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +35 -1 0.545082 +46 -1 0.442623 +36 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +47 -1 0.442623 +36 -1 0.545082 +46 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +36 -1 0.545082 +47 -1 0.442623 +37 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +48 -1 0.442623 +37 -1 0.545082 +47 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +37 -1 0.545082 +48 -1 0.442623 +38 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +49 -1 0.442623 +38 -1 0.545082 +48 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +38 -1 0.545082 +49 -1 0.442623 +39 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +50 -1 0.442623 +39 -1 0.545082 +49 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +39 -1 0.545082 +50 -1 0.442623 +40 -0.750392 0.545082 +SURF 0x10 +mat 2 +refs 3 +51 -0.820173 0.442623 +40 -0.750392 0.545082 +50 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +40 -0.750392 0.545082 +51 -0.820173 0.442623 +41 -0.670894 0.545082 +SURF 0x10 +mat 2 +refs 3 +52 -0.71852 0.442623 +41 -0.670894 0.545082 +51 -0.820173 0.442623 +SURF 0x10 +mat 2 +refs 3 +41 -0.670894 0.545082 +52 -0.71852 0.442623 +42 -0.537139 0.545082 +SURF 0x10 +mat 2 +refs 3 +53 -0.547489 0.442623 +42 -0.537139 0.545082 +52 -0.71852 0.442623 +SURF 0x10 +mat 2 +refs 3 +42 -0.537139 0.545082 +53 -0.547489 0.442623 +43 -0.391592 0.545082 +SURF 0x10 +mat 2 +refs 3 +54 -0.36138 0.442623 +43 -0.391592 0.545082 +53 -0.547489 0.442623 +SURF 0x10 +mat 2 +refs 3 +43 -0.391592 0.545082 +54 -0.36138 0.442623 +44 -0.280464 0.545082 +SURF 0x10 +mat 2 +refs 3 +55 -0.219282 0.442623 +44 -0.280464 0.545082 +54 -0.36138 0.442623 +SURF 0x10 +mat 2 +refs 3 +44 -0.280464 0.545082 +55 -0.219282 0.442623 +34 -0.239037 0.545082 +SURF 0x10 +mat 2 +refs 3 +45 -0.16631 0.442623 +34 -0.239037 0.545082 +55 -0.219282 0.442623 +SURF 0x10 +mat 2 +refs 3 +45 -1 0.442623 +56 -1 0.340164 +46 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +57 -1 0.340164 +46 -1 0.442623 +56 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +46 -1 0.442623 +57 -1 0.340164 +47 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +58 -1 0.340164 +47 -1 0.442623 +57 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +47 -1 0.442623 +58 -1 0.340164 +48 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +59 -1 0.340164 +48 -1 0.442623 +58 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +48 -1 0.442623 +59 -1 0.340164 +49 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +60 -1 0.340164 +49 -1 0.442623 +59 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +49 -1 0.442623 +60 -1 0.340164 +50 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +61 -1 0.340164 +50 -1 0.442623 +60 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +50 -1 0.442623 +61 -1 0.340164 +51 -0.820173 0.442623 +SURF 0x10 +mat 2 +refs 3 +62 -0.857116 0.340164 +51 -0.820173 0.442623 +61 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +51 -0.820173 0.442623 +62 -0.857116 0.340164 +52 -0.71852 0.442623 +SURF 0x10 +mat 2 +refs 3 +63 -0.743734 0.340164 +52 -0.71852 0.442623 +62 -0.857116 0.340164 +SURF 0x10 +mat 2 +refs 3 +52 -0.71852 0.442623 +63 -0.743734 0.340164 +53 -0.547489 0.442623 +SURF 0x10 +mat 2 +refs 3 +64 -0.552969 0.340164 +53 -0.547489 0.442623 +63 -0.743734 0.340164 +SURF 0x10 +mat 2 +refs 3 +53 -0.547489 0.442623 +64 -0.552969 0.340164 +54 -0.36138 0.442623 +SURF 0x10 +mat 2 +refs 3 +65 -0.345386 0.340164 +54 -0.36138 0.442623 +64 -0.552969 0.340164 +SURF 0x10 +mat 2 +refs 3 +54 -0.36138 0.442623 +65 -0.345386 0.340164 +55 -0.219282 0.442623 +SURF 0x10 +mat 2 +refs 3 +66 -0.186892 0.340164 +55 -0.219282 0.442623 +65 -0.345386 0.340164 +SURF 0x10 +mat 2 +refs 3 +55 -0.219282 0.442623 +66 -0.186892 0.340164 +45 -0.16631 0.442623 +SURF 0x10 +mat 2 +refs 3 +56 -0.127807 0.340164 +45 -0.16631 0.442623 +66 -0.186892 0.340164 +SURF 0x10 +mat 2 +refs 3 +56 -1 0.340164 +67 -1 0.241803 +57 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +68 -1 0.241803 +57 -1 0.340164 +67 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +57 -1 0.340164 +68 -1 0.241803 +58 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +69 -1 0.241803 +58 -1 0.340164 +68 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +58 -1 0.340164 +69 -1 0.241803 +59 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +70 -1 0.241803 +59 -1 0.340164 +69 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +59 -1 0.340164 +70 -1 0.241803 +60 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +71 -1 0.241803 +60 -1 0.340164 +70 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +60 -1 0.340164 +71 -1 0.241803 +61 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +72 -1 0.241803 +61 -1 0.340164 +71 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +61 -1 0.340164 +72 -1 0.241803 +62 -0.857116 0.340164 +SURF 0x10 +mat 2 +refs 3 +73 -0.853011 0.241803 +62 -0.857116 0.340164 +72 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +62 -0.857116 0.340164 +73 -0.853011 0.241803 +63 -0.743734 0.340164 +SURF 0x10 +mat 2 +refs 3 +74 -0.740933 0.241803 +63 -0.743734 0.340164 +73 -0.853011 0.241803 +SURF 0x10 +mat 2 +refs 3 +63 -0.743734 0.340164 +74 -0.740933 0.241803 +64 -0.552969 0.340164 +SURF 0x10 +mat 2 +refs 3 +75 -0.55236 0.241803 +64 -0.552969 0.340164 +74 -0.740933 0.241803 +SURF 0x10 +mat 2 +refs 3 +64 -0.552969 0.340164 +75 -0.55236 0.241803 +65 -0.345386 0.340164 +SURF 0x10 +mat 2 +refs 3 +76 -0.347163 0.241803 +65 -0.345386 0.340164 +75 -0.55236 0.241803 +SURF 0x10 +mat 2 +refs 3 +65 -0.345386 0.340164 +76 -0.347163 0.241803 +66 -0.186892 0.340164 +SURF 0x10 +mat 2 +refs 3 +77 -0.190491 0.241803 +66 -0.186892 0.340164 +76 -0.347163 0.241803 +SURF 0x10 +mat 2 +refs 3 +66 -0.186892 0.340164 +77 -0.190491 0.241803 +56 -0.127807 0.340164 +SURF 0x10 +mat 2 +refs 3 +67 -0.132086 0.241803 +56 -0.127807 0.340164 +77 -0.190491 0.241803 +SURF 0x10 +mat 2 +refs 3 +67 -1 0.241803 +78 -1 0.0901639 +68 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +79 -1 0.0901639 +68 -1 0.241803 +78 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +68 -1 0.241803 +79 -1 0.0901639 +69 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +80 -1 0.0901639 +69 -1 0.241803 +79 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +69 -1 0.241803 +80 -1 0.0901639 +70 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +81 -1 0.0901639 +70 -1 0.241803 +80 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +70 -1 0.241803 +81 -1 0.0901639 +71 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +82 -1 0.0901639 +71 -1 0.241803 +81 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +71 -1 0.241803 +82 -1 0.0901639 +72 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +83 -1 0.0901639 +72 -1 0.241803 +82 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +72 -1 0.241803 +83 -1 0.0901639 +73 -0.853011 0.241803 +SURF 0x10 +mat 2 +refs 3 +84 -0.807859 0.0901639 +73 -0.853011 0.241803 +83 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +73 -0.853011 0.241803 +84 -0.807859 0.0901639 +74 -0.740933 0.241803 +SURF 0x10 +mat 2 +refs 3 +85 -0.710116 0.0901639 +74 -0.740933 0.241803 +84 -0.807859 0.0901639 +SURF 0x10 +mat 2 +refs 3 +74 -0.740933 0.241803 +85 -0.710116 0.0901639 +75 -0.55236 0.241803 +SURF 0x10 +mat 2 +refs 3 +86 -0.545663 0.0901639 +75 -0.55236 0.241803 +85 -0.710116 0.0901639 +SURF 0x10 +mat 2 +refs 3 +75 -0.55236 0.241803 +86 -0.545663 0.0901639 +76 -0.347163 0.241803 +SURF 0x10 +mat 2 +refs 3 +87 -0.366712 0.0901639 +76 -0.347163 0.241803 +86 -0.545663 0.0901639 +SURF 0x10 +mat 2 +refs 3 +76 -0.347163 0.241803 +87 -0.366712 0.0901639 +77 -0.190491 0.241803 +SURF 0x10 +mat 2 +refs 3 +88 -0.230079 0.0901639 +77 -0.190491 0.241803 +87 -0.366712 0.0901639 +SURF 0x10 +mat 2 +refs 3 +77 -0.190491 0.241803 +88 -0.230079 0.0901639 +67 -0.132086 0.241803 +SURF 0x10 +mat 2 +refs 3 +78 -0.179144 0.0901639 +67 -0.132086 0.241803 +88 -0.230079 0.0901639 +SURF 0x10 +mat 2 +refs 3 +78 -1 0.0901639 +89 -1 0.00819672 +79 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +90 -1 0.00819672 +79 -1 0.0901639 +89 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +79 -1 0.0901639 +90 -1 0.00819672 +80 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +91 -1 0.00819672 +80 -1 0.0901639 +90 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +80 -1 0.0901639 +91 -1 0.00819672 +81 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +92 -1 0.00819672 +81 -1 0.0901639 +91 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +81 -1 0.0901639 +92 -1 0.00819672 +82 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +93 -1 0.00819672 +82 -1 0.0901639 +92 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +82 -1 0.0901639 +93 -1 0.00819672 +83 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +94 -1 0.00819672 +83 -1 0.0901639 +93 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +83 -1 0.0901639 +94 -1 0.00819672 +84 -0.807859 0.0901639 +SURF 0x10 +mat 2 +refs 3 +95 -0.643667 0.00819672 +84 -0.807859 0.0901639 +94 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +84 -0.807859 0.0901639 +95 -0.643667 0.00819672 +85 -0.710116 0.0901639 +SURF 0x10 +mat 2 +refs 3 +96 -0.598054 0.00819672 +85 -0.710116 0.0901639 +95 -0.643667 0.00819672 +SURF 0x10 +mat 2 +refs 3 +85 -0.710116 0.0901639 +96 -0.598054 0.00819672 +86 -0.545663 0.0901639 +SURF 0x10 +mat 2 +refs 3 +97 -0.521309 0.00819672 +86 -0.545663 0.0901639 +96 -0.598054 0.00819672 +SURF 0x10 +mat 2 +refs 3 +86 -0.545663 0.0901639 +97 -0.521309 0.00819672 +87 -0.366712 0.0901639 +SURF 0x10 +mat 2 +refs 3 +98 -0.437799 0.00819672 +87 -0.366712 0.0901639 +97 -0.521309 0.00819672 +SURF 0x10 +mat 2 +refs 3 +87 -0.366712 0.0901639 +98 -0.437799 0.00819672 +88 -0.230079 0.0901639 +SURF 0x10 +mat 2 +refs 3 +99 -0.374037 0.00819672 +88 -0.230079 0.0901639 +98 -0.437799 0.00819672 +SURF 0x10 +mat 2 +refs 3 +88 -0.230079 0.0901639 +99 -0.374037 0.00819672 +78 -0.179144 0.0901639 +SURF 0x10 +mat 2 +refs 3 +89 -0.350267 0.00819672 +78 -0.179144 0.0901639 +99 -0.374037 0.00819672 +SURF 0x10 +mat 0 +refs 3 +100 0 0 +101 0 0 +102 0 0 +SURF 0x10 +mat 0 +refs 3 +103 0 0 +102 0 0 +101 0 0 +SURF 0x10 +mat 0 +refs 3 +102 0 0 +103 0 0 +104 0 0 +SURF 0x10 +mat 0 +refs 3 +105 0 0 +104 0 0 +103 0 0 +SURF 0x10 +mat 0 +refs 3 +104 0 0 +105 0 0 +106 0 0 +SURF 0x10 +mat 0 +refs 2 +105 0 0 +106 0 0 +SURF 0x10 +mat 0 +refs 2 +105 0 0 +106 0 0 +SURF 0x10 +mat 0 +refs 3 +106 0 0 +105 0 0 +104 0 0 +SURF 0x10 +mat 0 +refs 3 +103 0 0 +104 0 0 +105 0 0 +SURF 0x10 +mat 0 +refs 3 +104 0 0 +103 0 0 +102 0 0 +SURF 0x10 +mat 0 +refs 3 +107 0 0 +108 0 0 +109 0 0 +SURF 0x10 +mat 0 +refs 3 +110 0 0 +109 0 0 +108 0 0 +SURF 0x10 +mat 0 +refs 3 +109 0 0 +110 0 0 +111 0 0 +SURF 0x10 +mat 0 +refs 3 +112 0 0 +111 0 0 +110 0 0 +SURF 0x10 +mat 0 +refs 3 +111 0 0 +112 0 0 +113 0 0 +SURF 0x10 +mat 0 +refs 2 +112 0 0 +113 0 0 +SURF 0x10 +mat 0 +refs 2 +112 0 0 +113 0 0 +SURF 0x10 +mat 0 +refs 3 +113 0 0 +112 0 0 +111 0 0 +SURF 0x10 +mat 0 +refs 3 +110 0 0 +111 0 0 +112 0 0 +SURF 0x10 +mat 0 +refs 3 +111 0 0 +110 0 0 +109 0 0 +SURF 0x10 +mat 2 +refs 3 +89 -1 0.00819672 +114 -1 0 +90 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +90 -1 0.00819672 +114 -1 0 +91 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +91 -1 0.00819672 +114 -1 0 +92 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +92 -1 0.00819672 +114 -1 0 +93 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +93 -1 0.00819672 +114 -1 0 +94 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +94 -1 0.00819672 +114 -1 0 +95 -0.643667 0.00819672 +SURF 0x10 +mat 2 +refs 3 +95 -0.643667 0.00819672 +114 -0.5 0 +96 -0.598054 0.00819672 +SURF 0x10 +mat 2 +refs 3 +96 -0.598054 0.00819672 +114 -0.5 0 +97 -0.521309 0.00819672 +SURF 0x10 +mat 2 +refs 3 +97 -0.521309 0.00819672 +114 -0.5 0 +98 -0.437799 0.00819672 +SURF 0x10 +mat 2 +refs 3 +98 -0.437799 0.00819672 +114 -0.5 0 +99 -0.374037 0.00819672 +SURF 0x10 +mat 2 +refs 3 +99 -0.374037 0.00819672 +114 -0.5 0 +89 -0.350267 0.00819672 +kids 0 +OBJECT poly +name "tuxbeak" +loc -0.0328128 0.372259 0.086667 +texture "Penguin_beak.rgb" +numvert 17 +0.0565685 0.514 0.1 +1.11759e-08 0.5 0.125 +0.08 0.5 0.1 +1.11759e-08 0.528 0.1 +-0.0565685 0.514 0.1 +-0.08 0.5 0.1 +-0.0565685 0.486 0.1 +1.11759e-08 0.472 0.1 +0.0565685 0.486 0.1 +0.16 0.5 -0.125 +0.113137 0.556 -0.125 +1.11759e-08 0.612 -0.125 +-0.113137 0.556 -0.125 +-0.16 0.5 -0.125 +-0.113137 0.444 -0.125 +1.11759e-08 0.388 -0.125 +0.113137 0.444 -0.125 +numsurf 24 +SURF 0x10 +mat 2 +refs 3 +0 -0.342865 -0.342865 +1 -0.5 -0.5 +2 -0.277778 -0.5 +SURF 0x10 +mat 2 +refs 3 +3 -0.5 -0.277778 +1 -0.5 -0.5 +0 -0.342865 -0.342865 +SURF 0x10 +mat 2 +refs 3 +4 -0.657135 -0.342865 +1 -0.5 -0.5 +3 -0.5 -0.277778 +SURF 0x10 +mat 2 +refs 3 +5 -0.722222 -0.5 +1 -0.5 -0.5 +4 -0.657135 -0.342865 +SURF 0x10 +mat 2 +refs 3 +6 -0.657135 -0.657135 +1 -0.5 -0.5 +5 -0.722222 -0.5 +SURF 0x10 +mat 2 +refs 3 +7 -0.5 -0.722222 +1 -0.5 -0.5 +6 -0.657135 -0.657135 +SURF 0x10 +mat 2 +refs 3 +8 -0.342865 -0.657135 +1 -0.5 -0.5 +7 -0.5 -0.722222 +SURF 0x10 +mat 2 +refs 3 +2 -0.277778 -0.5 +1 -0.5 -0.5 +8 -0.342865 -0.657135 +SURF 0x10 +mat 2 +refs 3 +2 -0.277778 -0.5 +9 -0.0555556 -0.5 +0 -0.342865 -0.342865 +SURF 0x10 +mat 2 +refs 3 +10 -0.18573 -0.18573 +0 -0.342865 -0.342865 +9 -0.0555556 -0.5 +SURF 0x10 +mat 2 +refs 3 +0 -0.342865 -0.342865 +10 -0.18573 -0.18573 +3 -0.5 -0.277778 +SURF 0x10 +mat 2 +refs 3 +11 -0.5 -0.0555556 +3 -0.5 -0.277778 +10 -0.18573 -0.18573 +SURF 0x10 +mat 2 +refs 3 +3 -0.5 -0.277778 +11 -0.5 -0.0555556 +4 -0.657135 -0.342865 +SURF 0x10 +mat 2 +refs 3 +12 -0.81427 -0.18573 +4 -0.657135 -0.342865 +11 -0.5 -0.0555556 +SURF 0x10 +mat 2 +refs 3 +4 -0.657135 -0.342865 +12 -0.81427 -0.18573 +5 -0.722222 -0.5 +SURF 0x10 +mat 2 +refs 3 +13 -0.944444 -0.5 +5 -0.722222 -0.5 +12 -0.81427 -0.18573 +SURF 0x10 +mat 2 +refs 3 +5 -0.722222 -0.5 +13 -0.944444 -0.5 +6 -0.657135 -0.657135 +SURF 0x10 +mat 2 +refs 3 +14 -0.81427 -0.81427 +6 -0.657135 -0.657135 +13 -0.944444 -0.5 +SURF 0x10 +mat 2 +refs 3 +6 -0.657135 -0.657135 +14 -0.81427 -0.81427 +7 -0.5 -0.722222 +SURF 0x10 +mat 2 +refs 3 +15 -0.5 -0.944444 +7 -0.5 -0.722222 +14 -0.81427 -0.81427 +SURF 0x10 +mat 2 +refs 3 +7 -0.5 -0.722222 +15 -0.5 -0.944444 +8 -0.342865 -0.657135 +SURF 0x10 +mat 2 +refs 3 +16 -0.18573 -0.81427 +8 -0.342865 -0.657135 +15 -0.5 -0.944444 +SURF 0x10 +mat 2 +refs 3 +8 -0.342865 -0.657135 +16 -0.18573 -0.81427 +2 -0.277778 -0.5 +SURF 0x10 +mat 2 +refs 3 +9 -0.0555556 -0.5 +2 -0.277778 -0.5 +16 -0.18573 -0.81427 +kids 0 diff --git a/examples/src/ssg/majik/elevation_map.h b/examples/src/ssg/majik/elevation_map.h new file mode 100644 index 0000000..645e494 --- /dev/null +++ b/examples/src/ssg/majik/elevation_map.h @@ -0,0 +1,3859 @@ + +unsigned char elevation_map [] = +{ + 0, 0, 7, 22, 37, 46, 51, 53, 54, 63, 71, 75, 76, 73, 65, 55, 44, + 52, 55, 59, 66, 72, 73, 70, 61, 62, 57, 47, 33, 15, 1, 0, 0, 0, + 0, 2, 4, 9, 20, 31, 39, 56, 71, 81, 87, 87, 82, 73, 59, 71, 75, + 75, 73, 70, 67, 61, 48, 46, 43, 37, 31, 22, 9, 0, 0, 0, 3, 9, + 11, 8, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 26, 43, 57, + 65, 70, 69, 65, 71, 75, 74, 67, 53, 29, 2, 0, 1, 23, 41, 51, 51, + 44, 32, 19, 23, 29, 31, 27, 22, 21, 16, 3, 15, 29, 40, 46, 46, 40, + 32, 27, 32, 28, 23, 20, 14, 5, 0, 0, 0, 15, 31, 40, 43, 38, 29, + 20, 22, 18, 11, 8, 5, 0, 0, 0, 0, 0, 9, 14, 14, 9, 4, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 25, 41, 55, 64, 68, 83, + 95,103,108,105, 97, 88, 78, 87, 93, 97,100,105,106,103, 96, 92, 81, + 69, 57, 41, 21, 0, 0, 3, 33, 58, 73, 79, 79, 74, 67, 73, 75, 73, + 63, 47, 25, 2, 0, 0, 0, 0, 4, 7, 8, 7, 3, 6, 11, 21, 26, + 23, 14, 0, 0, 2, 32, 57, 74, 84, 87, 87, 85, 92, 94, 91, 88, 87, + 84, 77, 66, 79, 92,101,105,103, 95, 84, 70, 71, 70, 64, 53, 36, 14, + 0, 0, 11, 27, 43, 55, 63, 67, 69, 70, 70, 79, 84, 87, 85, 81, 74, + 65, 57, 60, 66, 73, 76, 77, 74, 69, 71, 69, 62, 52, 37, 22, 8, 1, + 0, 0, 0, 3, 9, 19, 29, 44, 60, 74, 84, 89, 89, 85, 76, 66, 68, + 74, 77, 76, 74, 71, 65, 61, 59, 56, 50, 39, 25, 9, 0, 0, 2, 8, + 15, 18, 15, 9, 2, 0, 0, 0, 0, 0, 0, 1, 8, 18, 26, 32, 43, + 57, 66, 71, 71, 74, 79, 80, 78, 69, 52, 27, 0, 0, 4, 26, 44, 53, + 54, 48, 37, 25, 22, 28, 31, 28, 25, 19, 12, 16, 29, 43, 54, 59, 59, + 54, 45, 33, 23, 20, 16, 11, 4, 0, 0, 0, 8, 29, 46, 57, 60, 59, + 53, 45, 39, 37, 34, 31, 27, 20, 11, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 2, 1, 1, 2, 4, 7, 12, 23, 39, 52, 60, 69, + 84, 96,106,112,110,103, 94, 92, 95,100,106,113,118,119,114,105, 95, + 85, 74, 60, 41, 20, 0, 0, 5, 33, 57, 72, 79, 79, 75, 68, 73, 74, + 70, 59, 41, 19, 3, 0, 0, 0, 0, 0, 7, 13, 14, 11, 2, 0, 5, + 11, 9, 2, 0, 0, 12, 40, 65, 81, 90, 94, 94, 92, 96, 97, 95, 94, + 92, 88, 80, 73, 75, 84, 93, 96, 95, 87, 75, 60, 55, 52, 45, 31, 12, + 0, 0, 12, 23, 38, 52, 62, 70, 74, 76, 77, 77, 85, 92, 95, 96, 92, + 87, 80, 74, 70, 75, 79, 83, 83, 79, 74, 78, 78, 74, 68, 58, 47, 36, + 27, 20, 12, 9, 13, 18, 25, 36, 48, 64, 78, 88, 93, 94, 90, 82, 74, + 77, 79, 79, 79, 79, 77, 74, 72, 70, 67, 61, 53, 40, 27, 14, 16, 21, + 25, 26, 25, 21, 15, 9, 4, 2, 1, 2, 5, 11, 19, 29, 39, 47, 52, + 56, 60, 68, 74, 76, 81, 84, 85, 80, 70, 51, 23, 11, 8, 18, 28, 43, + 52, 55, 51, 43, 33, 25, 26, 29, 31, 27, 22, 21, 27, 38, 51, 61, 67, + 68, 65, 58, 48, 38, 28, 19, 11, 3, 0, 0, 4, 22, 43, 59, 69, 74, + 74, 72, 66, 62, 59, 57, 54, 48, 41, 32, 20, 6, 1, 3, 4, 2, 0, + 0, 0, 0, 1, 6, 13, 19, 25, 28, 29, 29, 31, 33, 34, 37, 45, 56, + 69, 83, 96,106,113,114,110,105,106,109,113,120,125,130,132,127,115, +103, 91, 79, 62, 41, 18, 8, 3, 11, 28, 52, 67, 75, 78, 75, 71, 68, + 69, 64, 54, 36, 20, 14, 7, 0, 0, 0, 0, 6, 15, 20, 20, 12, 0, + 0, 0, 0, 0, 0, 0, 20, 47, 69, 83, 92, 96, 97, 97, 99,101,102, +100, 96, 91, 82, 80, 81, 81, 84, 88, 85, 78, 66, 52, 34, 28, 20, 6, + 0, 0, 0, 21, 31, 43, 54, 63, 70, 74, 77, 78, 81, 89, 96,101,102, +100, 96, 89, 83, 78, 83, 86, 88, 88, 85, 79, 84, 85, 84, 80, 74, 66, + 57, 51, 44, 33, 20, 21, 25, 31, 40, 53, 68, 81, 91, 96, 98, 94, 87, + 81, 84, 84, 85, 84, 85, 85, 83, 80, 78, 75, 72, 65, 57, 47, 37, 36, + 39, 43, 45, 43, 39, 32, 23, 18, 13, 11, 12, 16, 23, 34, 46, 56, 63, + 67, 70, 72, 74, 78, 82, 87, 90, 88, 83, 70, 50, 33, 27, 25, 32, 40, + 47, 52, 53, 52, 46, 40, 33, 27, 31, 33, 32, 31, 31, 33, 43, 54, 63, + 71, 74, 73, 67, 59, 48, 37, 25, 14, 5, 0, 5, 19, 36, 54, 67, 77, + 83, 85, 84, 81, 79, 76, 74, 70, 64, 57, 48, 37, 25, 12, 2, 4, 4, + 3, 2, 2, 6, 14, 25, 34, 43, 50, 53, 53, 53, 51, 50, 50, 50, 51, + 55, 67, 80, 93,104,113,117,114,118,120,122,127,132,137,140,142,136, +124,110, 96, 81, 63, 40, 28, 25, 20, 21, 31, 41, 58, 68, 74, 74, 73, + 68, 63, 58, 47, 36, 29, 23, 18, 9, 0, 0, 0, 2, 15, 23, 26, 19, + 8, 0, 0, 0, 0, 0, 5, 28, 51, 69, 82, 90, 94, 97, 99,102,105, +107,105,100, 92, 88, 87, 87, 85, 81, 76, 74, 66, 55, 41, 27, 13, 0, + 0, 0, 0, 11, 26, 32, 40, 50, 58, 65, 70, 74, 77, 84, 91, 97,102, +103,102, 98, 92, 87, 84, 88, 92, 93, 93, 90, 84, 88, 91, 91, 88, 84, + 78, 72, 66, 59, 48, 33, 27, 29, 36, 44, 56, 71, 84, 93, 99,101, 97, + 91, 85, 88, 88, 88, 89, 92, 92, 91, 88, 85, 83, 79, 76, 71, 65, 59, + 53, 56, 59, 60, 58, 53, 46, 37, 28, 25, 23, 20, 23, 32, 43, 55, 65, + 73, 76, 78, 79, 80, 83, 86, 91, 93, 92, 84, 71, 52, 47, 40, 37, 41, + 47, 53, 56, 56, 54, 50, 44, 38, 32, 34, 38, 39, 39, 37, 38, 44, 53, + 62, 70, 74, 75, 73, 66, 55, 43, 29, 19, 15, 12, 21, 33, 47, 61, 73, + 81, 88, 91, 92, 91, 88, 86, 83, 79, 74, 67, 58, 48, 38, 27, 18, 9, + 3, 3, 5, 8, 15, 27, 40, 52, 60, 65, 68, 69, 67, 64, 61, 61, 66, + 68, 70, 72, 77, 89,101,110,115,122,128,130,133,136,139,142,145,145, +139,128,113, 97, 81, 61, 47, 45, 43, 39, 37, 37, 43, 50, 58, 66, 72, + 73, 71, 65, 57, 50, 41, 34, 28, 23, 16, 6, 0, 0, 0, 11, 22, 27, + 22, 13, 2, 0, 0, 0, 0, 12, 32, 51, 66, 77, 84, 89, 93, 98,103, +109,111,109,103, 94, 92, 92, 90, 87, 81, 73, 60, 51, 40, 29, 20, 8, + 0, 0, 1, 11, 20, 27, 31, 39, 48, 55, 62, 67, 73, 78, 84, 90, 95, + 99,100, 98, 95, 90, 85, 84, 90, 94, 96, 96, 93, 88, 92, 95, 96, 93, + 89, 84, 78, 73, 66, 55, 40, 31, 32, 38, 46, 58, 73, 85, 95,101,102, + 98, 92, 85, 89, 90, 90, 96,101,101, 98, 96, 95, 91, 87, 85, 83, 80, + 77, 74, 70, 72, 73, 70, 65, 57, 47, 44, 43, 41, 38, 33, 34, 46, 58, + 69, 76, 79, 82, 83, 84, 88, 90, 93, 96, 93, 85, 73, 61, 56, 47, 43, + 45, 48, 52, 55, 55, 54, 52, 47, 40, 34, 41, 46, 48, 46, 43, 40, 43, + 50, 59, 67, 73, 74, 74, 68, 58, 45, 37, 37, 34, 31, 36, 45, 55, 65, + 74, 82, 88, 92, 95, 95, 93, 91, 88, 83, 77, 70, 62, 53, 45, 37, 29, + 22, 16, 12, 8, 11, 21, 36, 50, 62, 70, 74, 77, 77, 75, 71, 73, 79, + 82, 82, 80, 79, 81, 87, 96,106,114,124,132,137,139,139,139,140,140, +140,136,127,113, 96, 79, 62, 60, 58, 57, 56, 56, 58, 59, 59, 57, 60, + 65, 70, 70, 66, 59, 51, 43, 34, 28, 25, 20, 12, 0, 0, 0, 2, 15, + 21, 20, 12, 3, 0, 0, 0, 3, 15, 32, 47, 59, 69, 76, 82, 89, 95, +102,110,113,113,106, 96, 92, 92, 90, 85, 78, 68, 55, 40, 26, 16, 11, + 4, 0, 7, 15, 21, 25, 27, 37, 46, 53, 59, 63, 67, 71, 74, 79, 85, + 89, 91, 92, 89, 86, 82, 77, 83, 88, 94, 96, 97, 95, 91, 93, 96, 97, + 95, 90, 84, 78, 73, 67, 56, 41, 31, 37, 48, 55, 60, 74, 86, 95,100, +101, 96, 91, 84, 88, 89, 96,105,110,110,107,106,108,105,100, 94, 92, + 92, 90, 88, 83, 83, 83, 80, 75, 67, 58, 58, 57, 56, 54, 50, 44, 44, + 56, 67, 75, 79, 82, 84, 88, 94, 96, 95, 97, 95, 88, 75, 66, 60, 50, + 43, 43, 44, 47, 50, 51, 51, 48, 45, 39, 40, 50, 56, 56, 53, 47, 46, + 51, 51, 54, 61, 67, 71, 71, 66, 57, 48, 53, 55, 53, 48, 46, 52, 59, + 66, 74, 79, 85, 90, 93, 95, 93, 91, 88, 83, 76, 68, 60, 52, 45, 39, + 34, 29, 26, 21, 16, 13, 22, 39, 55, 66, 74, 78, 79, 79, 78, 79, 88, + 93, 95, 92, 89, 85, 89, 90, 95,102,113,122,132,137,137,134,142,143, +134,130,128,120,108, 92, 75, 72, 70, 68, 68, 68, 71, 74, 76, 76, 74, + 68, 66, 70, 68, 63, 56, 48, 39, 31, 25, 21, 20, 14, 5, 0, 0, 0, + 4, 12, 12, 7, 2, 0, 0, 0, 4, 14, 28, 40, 50, 58, 67, 79, 88, + 92,100,109,113,113,108, 97, 90, 89, 86, 80, 71, 59, 46, 32, 19, 12, + 8, 6, 12, 21, 27, 28, 28, 28, 38, 46, 53, 57, 59, 61, 63, 67, 72, + 76, 79, 80, 79, 77, 74, 69, 70, 77, 84, 91, 95, 96, 95, 91, 94, 96, + 96, 93, 88, 80, 74, 68, 62, 52, 37, 37, 50, 58, 63, 64, 76, 87, 95, + 99, 99, 94, 88, 81, 84, 93,106,115,121,120,115,114,119,118,113,107, +100,101,100, 97, 92, 94, 93, 91, 85, 77, 67, 66, 65, 65, 65, 62, 58, + 53, 51, 63, 72, 77, 80, 85, 94,100,101, 96, 99, 96, 89, 79, 67, 59, + 47, 38, 36, 37, 38, 40, 43, 44, 43, 39, 37, 50, 60, 64, 64, 60, 53, + 50, 55, 56, 55, 56, 62, 66, 67, 63, 56, 63, 67, 69, 66, 61, 55, 56, + 60, 67, 75, 80, 82, 86, 89, 91, 90, 88, 84, 79, 72, 63, 54, 45, 39, + 36, 33, 31, 28, 23, 19, 15, 23, 40, 56, 68, 74, 78, 78, 79, 79, 91, +100,105,106,102, 96, 91, 96, 98, 99,101,109,119,127,132,133,152,167, +167,156,136,119,113,102, 88, 79, 78, 79, 81, 79, 77, 80, 84, 88, 88, + 84, 78, 69, 70, 69, 64, 55, 44, 38, 29, 19, 16, 16, 15, 9, 0, 0, + 0, 0, 1, 3, 2, 0, 0, 0, 0, 1, 9, 20, 29, 37, 50, 65, 77, + 84, 86, 95,105,113,113,108, 98, 86, 83, 79, 72, 61, 47, 33, 20, 9, + 4, 4, 7, 21, 31, 34, 34, 29, 25, 33, 40, 45, 47, 48, 48, 48, 52, + 57, 62, 65, 66, 65, 62, 58, 58, 62, 71, 79, 86, 91, 93, 92, 88, 94, + 96, 94, 89, 83, 74, 68, 60, 55, 47, 43, 46, 56, 63, 67, 68, 80, 90, + 96, 99, 97, 92, 84, 78, 88,102,115,127,133,133,127,120,125,127,123, +119,112,106,105,102,105,107,106,102, 96, 87, 78, 68, 67, 69, 70, 69, + 67, 64, 60, 59, 68, 74, 81, 90, 98,102,103, 98,101, 99, 92, 83, 70, + 55, 41, 29, 37, 38, 37, 33, 33, 34, 34, 33, 47, 60, 69, 74, 73, 67, + 59, 50, 55, 57, 57, 56, 58, 62, 63, 59, 67, 74, 77, 78, 75, 69, 62, + 57, 68, 79, 86, 92, 93, 92, 90, 87, 86, 84, 79, 74, 65, 56, 45, 36, + 29, 32, 34, 33, 29, 21, 14, 11, 25, 41, 56, 66, 73, 74, 75, 75, 88, +100,109,114,113,108,101, 94,100,103,105,106,107,114,123,128,150,173, +188,190,177,152,125,106, 96, 85, 86, 89, 92, 92, 90, 82, 85, 90, 93, + 94, 91, 84, 76, 66, 66, 61, 54, 51, 46, 38, 27, 12, 14, 14, 12, 5, + 0, 0, 0, 0, 0, 0, 0, 1, 3, 3, 3, 2, 9, 16, 29, 45, 59, + 69, 75, 77, 89,101,108,111,106, 97, 85, 73, 68, 59, 47, 33, 26, 16, + 7, 0, 0, 11, 25, 36, 40, 38, 33, 27, 22, 27, 29, 31, 31, 39, 46, + 50, 51, 51, 51, 51, 53, 56, 60, 64, 66, 65, 74, 82, 88, 90, 89, 85, + 90, 91, 89, 84, 77, 73, 70, 62, 55, 50, 44, 50, 59, 65, 69, 72, 83, + 92, 98,100, 97, 92, 84, 85, 94,109,124,137,143,143,136,128,130,133, +133,129,124,120,117,118,121,121,119,113,105, 96, 85, 76, 68, 70, 72, + 73, 73, 71, 68, 67, 70, 78, 86, 94,101,104,103, 99,102,100, 94, 84, + 72, 57, 40, 33, 40, 41, 40, 38, 36, 34, 34, 47, 60, 72, 79, 82, 80, + 74, 66, 56, 54, 56, 57, 58, 59, 60, 63, 69, 76, 81, 84, 84, 80, 74, + 68, 74, 77, 87, 95,101,103,103,101, 97, 93, 88, 82, 75, 68, 60, 53, + 48, 44, 37, 34, 34, 32, 25, 14, 9, 23, 39, 53, 62, 67, 69, 69, 80, + 92,105,114,120,119,113,105, 98, 98,102,105,108,111,115,122,134,158, +181,198,198,186,161,133,113, 97, 95, 98,102,104,103,100, 91, 85, 90, + 94, 96, 93, 88, 80, 72, 65, 60, 57, 53, 47, 40, 28, 14, 14, 15, 13, + 7, 6, 8, 7, 6, 7, 9, 11, 11, 11, 8, 5, 3, 4, 12, 22, 34, + 46, 55, 60, 71, 84, 95,102,105,102, 93, 82, 69, 57, 47, 39, 32, 25, + 18, 9, 0, 0, 11, 26, 37, 41, 41, 36, 28, 22, 21, 26, 32, 40, 48, + 54, 58, 59, 60, 60, 61, 61, 62, 64, 66, 66, 65, 70, 79, 84, 87, 87, + 84, 82, 83, 80, 76, 71, 68, 64, 57, 50, 43, 38, 48, 58, 65, 70, 73, + 83, 92, 97, 99, 97, 92, 87, 89, 97,113,128,140,149,147,140,132,137, +142,142,140,136,132,130,132,136,136,130,121,110, 99, 88, 79, 70, 72, + 74, 76, 76, 75, 74, 73, 75, 81, 89, 96,102,106,105,100,100, 98, 92, + 83, 71, 55, 39, 29, 36, 39, 39, 39, 38, 39, 48, 61, 73, 83, 88, 91, + 88, 81, 72, 66, 63, 63, 66, 67, 66, 69, 73, 79, 84, 88, 89, 88, 84, + 79, 81, 85, 88, 92,101,108,113,114,113,109,103, 96, 89, 82, 74, 67, + 61, 62, 59, 53, 44, 37, 36, 31, 21, 15, 16, 31, 44, 54, 58, 60, 67, + 83, 96,108,118,123,123,118,110,103,101,101,104,113,119,122,125,134, +158,179,194,194,183,163,137,118,103,106,110,113,115,113,109,100, 88, + 85, 90, 93, 92, 89, 83, 74, 67, 61, 55, 50, 43, 34, 25, 16, 15, 14, + 12, 7, 12, 16, 19, 21, 22, 22, 21, 19, 14, 9, 4, 0, 2, 4, 12, + 21, 29, 37, 51, 65, 78, 88, 95, 96, 93, 84, 73, 58, 46, 37, 29, 26, + 21, 16, 8, 7, 4, 9, 23, 34, 40, 40, 36, 27, 27, 31, 37, 43, 50, + 56, 61, 65, 67, 69, 69, 69, 67, 65, 64, 63, 63, 60, 67, 75, 80, 83, + 83, 80, 76, 73, 70, 66, 62, 58, 53, 45, 37, 31, 32, 43, 54, 63, 71, + 75, 81, 88, 95, 97, 97, 94, 89, 90, 97,113,128,140,147,145,139,136, +143,149,149,147,143,140,139,142,147,143,134,123,110, 97, 87, 78, 73, + 74, 79, 84, 85, 83, 77, 76, 78, 84, 90, 97,103,107,106,100, 96, 94, + 88, 79, 66, 50, 33, 20, 26, 29, 32, 33, 36, 45, 60, 72, 83, 91, 96, + 97, 94, 87, 77, 74, 71, 71, 76, 79, 80, 80, 80, 85, 90, 92, 92, 90, + 86, 84, 90, 93, 95, 96,104,113,120,123,123,119,112,102, 93, 85, 77, + 69, 70, 71, 70, 64, 56, 46, 40, 38, 32, 21, 21, 21, 32, 41, 46, 47, + 65, 81, 94,106,115,121,122,118,112,107,106,106,115,124,130,133,130, +136,150,169,181,183,173,158,137,121,111,114,119,122,123,121,115,106, + 94, 80, 84, 88, 89, 87, 82, 74, 65, 57, 50, 41, 34, 28, 22, 18, 14, + 11, 7, 5, 15, 23, 29, 33, 36, 34, 31, 23, 15, 7, 0, 0, 2, 5, + 5, 6, 14, 27, 43, 57, 70, 79, 85, 86, 82, 73, 59, 43, 29, 21, 18, + 15, 13, 13, 16, 15, 11, 8, 21, 31, 37, 37, 33, 26, 32, 38, 43, 48, + 53, 58, 63, 67, 70, 73, 74, 72, 69, 64, 59, 57, 55, 54, 63, 71, 75, + 78, 77, 74, 72, 67, 63, 57, 51, 44, 37, 32, 28, 22, 29, 38, 47, 59, + 69, 77, 81, 85, 91, 96, 97, 96, 93, 90, 96,112,125,137,143,142,134, +142,149,150,149,145,142,139,139,142,147,142,132,120,106, 93, 83, 76, + 74, 81, 88, 92, 93, 90, 82, 77, 78, 84, 90, 97,103,107,106,100, 92, + 90, 84, 74, 59, 44, 31, 15, 15, 16, 20, 23, 32, 52, 67, 79, 88, 97, +102,102, 98, 90, 79, 78, 76, 78, 84, 89, 92, 92, 91, 90, 92, 93, 92, + 90, 87, 91, 96, 98, 97, 98,104,113,122,128,129,124,115,104, 94, 84, + 75, 69, 72, 74, 74, 70, 62, 53, 45, 46, 41, 31, 27, 27, 22, 27, 33, + 36, 57, 76, 89,101,109,114,115,113,109,107,108,115,127,137,143,145, +142,140,147,156,165,165,159,149,134,122,115,120,123,127,127,123,117, +108, 96, 82, 77, 81, 83, 81, 77, 69, 59, 48, 41, 40, 37, 31, 23, 16, + 9, 5, 0, 5, 16, 26, 34, 41, 44, 41, 36, 26, 14, 3, 0, 0, 2, + 4, 5, 3, 4, 16, 31, 44, 57, 66, 72, 72, 66, 55, 39, 21, 14, 4, + 2, 2, 9, 16, 20, 19, 15, 9, 19, 26, 29, 29, 27, 23, 33, 39, 45, + 48, 52, 55, 58, 62, 67, 71, 73, 71, 66, 59, 51, 45, 41, 51, 59, 64, + 68, 69, 67, 65, 63, 58, 52, 45, 36, 29, 26, 21, 18, 20, 29, 39, 47, + 55, 66, 77, 84, 88, 89, 93, 96, 98, 96, 93, 96,111,124,134,140,137, +133,143,147,147,143,137,133,129,129,133,136,132,123,112,100, 88, 80, + 79, 84, 91, 96,100,100, 95, 87, 76, 77, 82, 88, 96,102,105,104, 98, + 89, 85, 79, 68, 52, 38, 26, 12, 11, 9, 6, 13, 34, 55, 70, 82, 91, + 99,104,105,100, 91, 80, 79, 77, 84, 92, 96, 99, 99, 97, 95, 92, 90, + 88, 87, 90, 96,100, 99, 97, 96,102,111,120,127,129,124,114,102, 91, + 80, 71, 65, 69, 73, 74, 70, 64, 56, 50, 52, 48, 40, 32, 33, 31, 22, + 21, 23, 44, 65, 79, 91, 98,103,105,104,102,103,111,123,136,149,156, +156,150,143,154,161,163,161,152,140,130,122,117,121,124,124,123,119, +112,103, 93, 80, 69, 73, 74, 74, 69, 60, 48, 38, 40, 40, 37, 31, 21, + 12, 3, 0, 0, 3, 14, 26, 36, 44, 47, 45, 38, 26, 12, 0, 0, 0, + 3, 4, 5, 3, 3, 3, 14, 26, 38, 48, 53, 53, 46, 33, 16, 6, 0, + 0, 0, 2, 9, 16, 20, 19, 14, 12, 18, 21, 23, 22, 20, 19, 29, 37, + 40, 43, 44, 45, 47, 52, 59, 64, 67, 65, 59, 50, 38, 29, 36, 44, 51, + 55, 56, 55, 53, 51, 50, 45, 38, 29, 19, 14, 12, 7, 7, 16, 27, 38, + 48, 55, 61, 75, 84, 89, 92, 92, 95, 98, 99, 96, 96,111,123,133,137, +136,133,140,142,139,132,125,119,115,114,118,121,119,113,103, 92, 82, + 84, 89, 93, 99,103,106,104, 98, 89, 76, 77, 83, 86, 93, 99,102,102, + 95, 85, 82, 75, 63, 45, 29, 18, 5, 3, 3, 6, 19, 36, 55, 70, 81, + 90, 99,104,104, 99, 90, 79, 77, 77, 88, 96,102,103,102, 98, 95, 91, + 84, 83, 88, 95,100,101, 97, 96, 94, 98,107,114,121,124,120,110, 97, + 85, 80, 72, 58, 60, 65, 67, 66, 62, 55, 51, 54, 53, 46, 37, 39, 39, + 33, 22, 15, 26, 50, 66, 78, 86, 90, 92, 93, 93,100,112,125,140,152, +159,161,156,143,156,169,175,177,169,154,136,123,118,119,120,119,114, +109,102, 96, 87, 75, 62, 63, 64, 62, 56, 46, 33, 36, 39, 39, 34, 26, + 14, 4, 0, 0, 0, 4, 12, 22, 34, 44, 48, 46, 38, 25, 9, 0, 0, + 0, 2, 3, 6, 5, 0, 0, 0, 6, 15, 25, 29, 29, 22, 14, 4, 2, + 2, 0, 0, 1, 8, 14, 18, 15, 12, 14, 18, 19, 18, 14, 12, 11, 22, + 29, 32, 32, 32, 33, 32, 37, 45, 52, 56, 55, 47, 36, 22, 15, 25, 33, + 38, 40, 39, 36, 32, 31, 29, 26, 20, 13, 4, 0, 0, 0, 0, 9, 22, + 36, 47, 55, 60, 71, 82, 89, 92, 93, 93, 96, 97, 95, 98,113,125,136, +139,136,129,133,133,127,120,112,106,102,101,103,107,106,102, 95, 87, + 85, 92, 96, 98,103,107,108,106, 99, 89, 77, 82, 88, 91, 91, 96, 99, + 98, 92, 84, 80, 73, 59, 40, 19, 7, 0, 0, 1, 18, 33, 46, 54, 67, + 79, 88, 96,102,102, 97, 89, 79, 73, 80, 91, 99,102,103,100, 96, 92, + 87, 80, 85, 93, 98,100, 98, 94, 98,103,108,109,111,115,118,113,103, + 98, 96, 92, 83, 70, 55, 54, 57, 58, 56, 52, 48, 52, 52, 46, 41, 46, + 47, 44, 36, 23, 12, 29, 48, 62, 72, 77, 79, 81, 87, 97,110,123,137, +149,156,158,152,142,154,169,181,186,181,167,145,125,121,114,113,111, +105, 98, 92, 85, 78, 66, 57, 56, 54, 50, 43, 31, 26, 32, 36, 34, 27, + 16, 4, 0, 0, 0, 12, 25, 33, 36, 33, 43, 47, 45, 38, 25, 11, 2, + 0, 0, 0, 2, 6, 6, 2, 0, 0, 0, 0, 7, 16, 21, 21, 15, 6, + 3, 2, 4, 3, 9, 15, 16, 14, 12, 14, 19, 20, 18, 19, 18, 11, 2, + 13, 19, 21, 19, 23, 27, 26, 18, 26, 36, 40, 39, 32, 20, 9, 0, 7, + 14, 19, 19, 16, 12, 8, 7, 7, 6, 3, 0, 0, 0, 0, 0, 0, 0, + 15, 31, 44, 54, 60, 65, 78, 86, 91, 93, 92, 92, 93, 90,104,119,133, +143,145,142,132,123,121,115,110,107,104,104,100, 92, 95, 96, 94, 94, + 94, 93, 94, 96, 98,102,106,108,105, 99, 89, 77, 86, 92, 95, 95, 95, + 96, 95, 87, 86, 81, 73, 59, 40, 18, 0, 0, 0, 5, 23, 43, 57, 67, + 73, 76, 85, 94,100,101, 97, 89, 79, 67, 80, 91, 97,101, 99, 95, 90, + 87, 88, 91, 94, 96, 98, 98, 96, 90,102,111,118,120,119,115,114,110, +110,111,108,102, 92, 78, 60, 39, 45, 47, 46, 45, 41, 44, 44, 39, 45, + 52, 54, 53, 46, 34, 22, 12, 32, 46, 57, 63, 66, 74, 82, 92,104,117, +128,137,143,143,139,130,145,163,177,186,183,171,152,129,127,119,110, +102, 96, 88, 82, 74, 74, 71, 69, 66, 60, 52, 38, 20, 22, 27, 28, 25, + 16, 3, 0, 0, 0, 13, 31, 44, 52, 53, 50, 43, 47, 46, 40, 29, 15, + 2, 0, 0, 0, 2, 7, 7, 4, 0, 0, 0, 0, 5, 16, 23, 25, 21, + 13, 2, 13, 16, 18, 22, 25, 23, 18, 11, 20, 23, 23, 20, 22, 22, 15, + 5, 1, 5, 5, 11, 15, 18, 16, 8, 5, 13, 19, 25, 27, 23, 15, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, + 3, 11, 26, 43, 55, 63, 69, 73, 80, 87, 91, 93, 93, 93, 94,109,124, +139,150,154,150,140,129,121,117,113,113,114,113,109,100, 92, 94, 96, + 98, 99,100,102,103,103,100,103,106,105,100, 92, 82, 86, 92, 96, 97, + 96, 95, 92, 91, 89, 84, 76, 63, 45, 22, 4, 0, 0, 7, 27, 48, 65, + 76, 83, 86, 85, 90, 96, 98, 96, 88, 78, 72, 79, 89, 95, 96, 93, 88, + 93, 96, 97,101,103,104,103,102, 99, 99,106,117,125,130,132,130,127, +124,123,121,117,108, 96, 83, 66, 46, 32, 33, 34, 36, 34, 34, 36, 39, + 46, 53, 56, 55, 50, 39, 27, 18, 22, 34, 45, 54, 62, 74, 88, 98,106, +113,121,129,136,142,143,143,158,161,163,175,177,169,152,134,132,123, +113,102, 92, 85, 84, 82, 80, 79, 76, 72, 65, 55, 40, 31, 29, 27, 22, + 13, 1, 0, 0, 0, 15, 33, 50, 61, 67, 67, 64, 58, 50, 48, 44, 34, + 23, 11, 1, 0, 0, 3, 11, 15, 16, 13, 8, 4, 0, 5, 18, 27, 32, + 31, 26, 27, 31, 36, 39, 40, 39, 34, 26, 14, 22, 27, 26, 22, 26, 25, + 19, 11, 0, 0, 0, 5, 8, 11, 8, 1, 0, 0, 7, 20, 27, 27, 22, + 13, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 7, 12, + 14, 9, 18, 26, 43, 58, 68, 75, 79, 82, 85, 88, 92, 94, 95, 95,107, +121,136,149,156,154,145,136,127,121,119,122,123,121,114,104, 95, 94, + 96, 99,101,102,103,106,107,102,101,104,105,102, 95, 88, 88, 89, 94, + 97, 98, 98, 97, 96, 93, 89, 81, 69, 52, 29, 19, 12, 7, 14, 29, 54, + 72, 84, 92, 96, 94, 88, 90, 92, 91, 84, 75, 75, 80, 88, 92, 92, 88, + 95,102,107,108,110,111,111,110,108,107,108,110,120,132,140,147,147, +145,139,134,128,120,110, 97, 84, 68, 51, 33, 20, 21, 23, 27, 31, 31, + 34, 41, 47, 51, 50, 45, 37, 26, 19, 27, 37, 46, 55, 61, 77, 91,102, +111,120,129,140,149,156,159,158,173,173,167,161,167,163,150,134,132, +125,115,104, 93, 86, 85, 84, 83, 81, 79, 74, 66, 55, 43, 41, 39, 36, + 26, 14, 0, 0, 9, 25, 39, 54, 67, 75, 80, 81, 78, 74, 66, 56, 44, + 38, 31, 21, 13, 6, 5, 11, 19, 23, 26, 23, 21, 20, 18, 14, 27, 38, + 46, 51, 54, 56, 58, 60, 61, 60, 56, 50, 38, 23, 20, 25, 26, 23, 27, + 27, 22, 14, 4, 0, 0, 0, 2, 2, 1, 0, 0, 0, 7, 21, 32, 37, + 36, 29, 23, 19, 15, 13, 12, 11, 8, 5, 2, 0, 1, 5, 8, 12, 15, + 20, 21, 18, 23, 31, 43, 59, 72, 80, 85, 88, 89, 90, 91, 94, 96, 95, +100,112,124,136,145,149,145,137,129,123,125,127,127,122,114,104, 95, + 92, 94, 96, 97, 99,101,104,105,102, 97,102,104,103, 98, 92, 92, 92, + 92, 94, 97, 99, 99, 98, 96, 92, 84, 74, 57, 37, 28, 20, 12, 16, 31, + 57, 76, 88, 97,101,100, 93, 86, 87, 85, 80, 73, 75, 81, 88, 89, 88, + 90,102,111,115,115,115,114,113,113,112,113,115,119,122,134,149,158, +161,159,150,140,128,117,104, 92, 79, 65, 51, 36, 21, 22, 23, 27, 28, + 29, 28, 33, 38, 40, 40, 36, 29, 21, 23, 31, 40, 50, 57, 63, 77, 91, +102,113,124,136,149,159,167,171,169,179,179,171,158,158,156,145,129, +128,123,115,105, 95, 86, 82, 81, 80, 79, 77, 73, 64, 52, 48, 47, 46, + 40, 29, 14, 0, 13, 33, 47, 59, 70, 79, 86, 90, 91, 89, 86, 79, 71, + 57, 40, 34, 28, 21, 21, 20, 19, 23, 28, 31, 32, 32, 36, 36, 31, 41, + 54, 64, 72, 75, 78, 79, 79, 78, 76, 71, 63, 52, 36, 19, 22, 25, 23, + 26, 26, 23, 16, 8, 5, 3, 5, 9, 13, 16, 18, 16, 11, 14, 29, 43, + 50, 53, 50, 46, 43, 40, 37, 34, 29, 26, 20, 14, 13, 14, 15, 16, 18, + 19, 22, 26, 23, 27, 32, 40, 59, 74, 83, 88, 92, 93, 92, 92, 94, 95, + 94, 93,101,111,121,129,134,136,130,124,123,125,125,123,118,110,100, + 91, 88, 89, 91, 92, 92, 95, 98,101,100, 95, 98,101,102,100, 93, 93, + 93, 92, 89, 93, 96, 98, 97, 96, 92, 86, 76, 60, 41, 32, 21, 11, 14, + 33, 59, 78, 89, 97,102,100, 94, 87, 81, 80, 76, 71, 73, 81, 87, 88, + 85, 92,104,113,119,118,115,113,111,110,111,113,121,127,128,134,149, +159,165,163,150,134,120,107, 94, 83, 71, 58, 46, 34, 21, 22, 25, 26, + 28, 28, 28, 27, 27, 28, 28, 25, 21, 25, 28, 34, 43, 52, 59, 66, 74, + 88,100,113,125,139,152,163,171,173,171,175,175,165,152,147,149,140, +125,123,120,113,105, 96, 87, 79, 75, 75, 75, 74, 69, 61, 48, 48, 50, + 47, 40, 29, 14, 11, 32, 52, 64, 72, 79, 87, 92, 96, 97, 97, 95, 89, + 81, 69, 51, 36, 31, 29, 31, 29, 27, 25, 29, 33, 37, 40, 47, 52, 51, + 55, 68, 79, 86, 91, 92, 92, 92, 91, 88, 82, 74, 63, 47, 27, 19, 25, + 25, 21, 22, 22, 15, 11, 9, 15, 19, 23, 26, 28, 31, 32, 29, 23, 36, + 48, 57, 62, 62, 60, 59, 58, 56, 52, 47, 40, 32, 29, 29, 29, 26, 23, + 23, 26, 27, 27, 27, 26, 28, 37, 56, 72, 83, 89, 93, 94, 94, 93, 93, + 94, 92, 91, 91, 96,103,112,118,120,118,115,117,119,119,115,110,102, + 92, 84, 84, 84, 84, 84, 84, 86, 90, 94, 95, 93, 92, 96, 98, 98, 94, + 92, 92, 90, 88, 87, 91, 92, 92, 92, 89, 84, 75, 60, 40, 28, 16, 5, + 7, 34, 59, 75, 86, 93, 96, 96, 90, 82, 78, 77, 72, 65, 69, 79, 85, + 86, 84, 92,102,111,114,113,109,105,102,102,105,112,122,130,134,132, +143,152,158,154,139,122,107, 92, 80, 68, 56, 45, 37, 27, 20, 21, 23, + 25, 26, 27, 33, 37, 38, 36, 31, 27, 27, 28, 29, 34, 43, 53, 61, 68, + 74, 82, 96,109,122,136,149,159,165,165,163,158,159,150,139,139,140, +133,120,117,114,111,103, 95, 86, 78, 73, 69, 69, 68, 64, 57, 45, 43, + 45, 44, 38, 27, 14, 25, 46, 63, 73, 78, 84, 88, 93, 97,101,102,100, + 96, 88, 77, 61, 38, 29, 32, 34, 33, 29, 23, 27, 32, 38, 46, 56, 64, + 66, 67, 79, 88, 96,102,103,103,102,100, 96, 90, 82, 72, 56, 36, 18, + 25, 27, 25, 18, 18, 11, 12, 19, 25, 29, 32, 33, 34, 39, 41, 41, 40, + 40, 52, 60, 65, 67, 67, 69, 69, 68, 65, 60, 52, 44, 46, 46, 41, 36, + 29, 32, 33, 33, 28, 29, 29, 26, 31, 50, 67, 79, 87, 91, 93, 93, 92, + 93, 93, 94, 95, 94, 91, 92, 96,102,104,105,105,106,107,107,104, 99, + 92, 82, 78, 78, 77, 75, 76, 80, 82, 81, 87, 89, 90, 88, 89, 92, 94, + 92, 87, 87, 87, 84, 81, 82, 84, 84, 84, 84, 79, 71, 57, 37, 20, 7, + 0, 9, 36, 56, 71, 79, 84, 87, 86, 81, 74, 76, 75, 69, 59, 66, 78, + 84, 85, 84, 88, 96,102,105,102, 97, 93, 97,101,103,105,118,129,134, +132,133,139,140,134,122,106, 91, 78, 69, 55, 37, 27, 21, 15, 15, 18, + 20, 21, 27, 34, 40, 46, 48, 47, 43, 36, 28, 27, 27, 31, 40, 51, 61, + 70, 76, 80, 90,103,117,129,139,147,149,149,145,137,137,133,127,133, +133,127,113,110,110,106,100, 92, 85, 76, 67, 61, 61, 62, 59, 53, 41, + 32, 36, 36, 31, 22, 23, 34, 53, 67, 75, 79, 83, 87, 92, 96, 99,102, +101, 98, 92, 83, 69, 48, 23, 27, 31, 31, 26, 19, 22, 29, 39, 50, 63, + 74, 79, 80, 86, 95,102,109,110,109,107,104,101, 95, 88, 77, 62, 40, + 26, 26, 29, 28, 21, 11, 5, 16, 25, 31, 34, 36, 36, 37, 40, 45, 48, + 51, 51, 52, 59, 64, 67, 69, 73, 75, 76, 74, 70, 62, 57, 59, 57, 52, + 44, 34, 36, 36, 33, 28, 32, 33, 32, 41, 48, 60, 74, 82, 87, 88, 89, + 91, 93, 92, 93, 96, 96, 95, 92, 88, 91, 93, 92, 92, 93, 94, 94, 92, + 88, 80, 71, 73, 74, 74, 71, 72, 74, 75, 75, 79, 84, 87, 88, 85, 84, + 87, 87, 84, 80, 81, 81, 79, 74, 74, 74, 74, 75, 73, 65, 53, 32, 11, + 0, 0, 12, 34, 52, 63, 69, 73, 74, 74, 71, 75, 77, 74, 67, 57, 63, + 74, 81, 84, 83, 81, 88, 92, 92, 89, 90, 97,102,105,106,105,111,123, +129,129,123,123,122,117,105, 90, 85, 79, 70, 55, 34, 12, 5, 5, 8, + 12, 15, 25, 32, 39, 45, 51, 54, 54, 50, 40, 28, 21, 19, 22, 33, 45, + 58, 68, 75, 80, 84, 98,111,121,129,132,132,130,127,122,119,117,123, +127,125,118,106,103,103,101, 95, 91, 84, 74, 63, 51, 55, 56, 54, 48, + 37, 23, 21, 22, 20, 26, 32, 39, 56, 68, 74, 77, 80, 88, 94, 96, 96, + 98, 98, 96, 92, 85, 74, 56, 33, 20, 23, 23, 19, 12, 18, 37, 53, 63, + 69, 82, 89, 92, 94,100,107,112,113,111,109,106,102, 96, 89, 79, 65, + 45, 38, 28, 33, 31, 23, 12, 4, 16, 27, 33, 36, 36, 36, 36, 39, 45, + 51, 55, 57, 59, 61, 62, 63, 67, 73, 78, 81, 81, 79, 73, 64, 65, 63, + 57, 50, 40, 33, 31, 26, 31, 36, 38, 43, 53, 60, 64, 67, 76, 80, 84, + 89, 93, 94, 93, 89, 93, 95, 96, 93, 90, 86, 82, 80, 79, 80, 82, 82, + 80, 77, 72, 65, 70, 72, 72, 69, 68, 72, 72, 69, 74, 79, 84, 86, 86, + 84, 81, 79, 79, 78, 76, 75, 75, 74, 69, 62, 64, 66, 65, 60, 48, 29, + 7, 0, 0, 12, 31, 45, 54, 57, 59, 61, 67, 73, 76, 77, 73, 64, 60, + 59, 72, 78, 82, 82, 81, 79, 80, 79, 85, 92, 98,102,104,103,102,102, +113,120,121,118,111,107,101, 90, 86, 83, 76, 66, 51, 28, 7, 0, 0, + 1, 8, 19, 27, 33, 39, 45, 51, 54, 53, 48, 38, 25, 9, 7, 11, 21, + 36, 50, 62, 71, 77, 81, 95,106,114,120,121,120,119,113,110,107,113, +119,120,117,109, 98, 98, 97, 94, 91, 86, 78, 67, 56, 54, 53, 51, 48, + 43, 32, 18, 5, 8, 16, 31, 40, 50, 56, 66, 72, 82, 92,102,108,110, +108,102, 95, 93, 91, 85, 75, 60, 40, 28, 16, 16, 13, 9, 28, 48, 63, + 73, 77, 90, 98,104,107,107,109,113,113,117,115,111,103, 96, 90, 79, + 65, 57, 50, 40, 34, 32, 25, 12, 9, 14, 25, 31, 34, 34, 43, 48, 52, + 51, 50, 56, 62, 66, 70, 72, 74, 74, 72, 78, 84, 87, 87, 83, 76, 67, + 62, 58, 52, 45, 37, 32, 32, 36, 39, 41, 54, 61, 66, 69, 71, 75, 80, + 86, 90, 92, 94, 92, 88, 88, 92, 93, 92, 91, 88, 84, 82, 79, 71, 68, + 70, 73, 73, 69, 62, 62, 65, 66, 66, 65, 66, 67, 72, 77, 81, 83, 84, + 85, 84, 84, 84, 81, 76, 76, 75, 73, 73, 71, 66, 56, 55, 57, 54, 45, + 29, 9, 0, 0, 5, 21, 33, 40, 44, 56, 64, 69, 74, 75, 74, 68, 58, + 59, 58, 69, 76, 79, 80, 79, 79, 78, 79, 84, 89, 94, 96, 96, 95, 93, + 92,103,110,112,109,103, 97, 90, 85, 81, 77, 69, 57, 39, 18, 6, 0, + 0, 1, 12, 21, 28, 41, 52, 56, 56, 53, 50, 44, 34, 22, 12, 7, 8, + 9, 25, 40, 54, 65, 73, 77, 90,100,107,111,113,120,123,118,110,105, +110,112,112,106, 98, 96, 95, 92, 87, 84, 78, 68, 59, 60, 58, 56, 52, + 43, 32, 20, 7, 0, 3, 20, 34, 47, 58, 67, 74, 83, 92,102,111,117, +119,114,108,101, 91, 88, 84, 76, 63, 45, 36, 25, 19, 16, 18, 38, 55, + 68, 76, 86, 99,109,114,119,119,119,120,123,128,127,121,112,102, 92, + 83, 74, 67, 59, 50, 34, 29, 22, 11, 13, 19, 25, 32, 39, 47, 53, 57, + 57, 55, 51, 58, 65, 72, 76, 79, 83, 84, 80, 76, 84, 90, 93, 92, 87, + 78, 68, 57, 50, 45, 40, 37, 37, 39, 40, 51, 59, 65, 68, 69, 71, 74, + 79, 84, 88, 89, 89, 88, 84, 84, 88, 90, 91, 90, 88, 85, 83, 79, 70, + 57, 58, 65, 68, 67, 62, 56, 55, 56, 58, 60, 63, 67, 73, 79, 82, 83, + 82, 80, 81, 82, 84, 83, 79, 76, 78, 78, 76, 74, 71, 62, 50, 45, 45, + 40, 29, 13, 0, 0, 0, 8, 19, 32, 48, 61, 67, 71, 72, 72, 67, 59, + 52, 53, 59, 69, 74, 77, 77, 76, 75, 74, 76, 79, 84, 86, 87, 85, 82, + 79, 84, 94, 99,101, 98, 94, 89, 84, 79, 74, 68, 59, 44, 23, 11, 0, + 0, 0, 7, 15, 26, 40, 52, 60, 62, 61, 57, 52, 44, 36, 25, 13, 3, + 3, 3, 18, 34, 50, 61, 69, 74, 82, 92, 97,107,115,123,125,120,111, +104,104,104,102, 96, 95, 95, 92, 88, 81, 75, 67, 57, 62, 62, 59, 55, + 48, 37, 22, 4, 0, 0, 5, 22, 38, 53, 64, 74, 83, 91,100,110,118, +122,122,117,110,102, 92, 88, 83, 75, 64, 47, 41, 33, 28, 25, 29, 47, + 61, 71, 80, 95,109,119,125,128,128,127,127,130,134,133,127,117,106, + 96, 87, 79, 72, 64, 54, 38, 23, 16, 8, 14, 23, 34, 43, 51, 56, 59, + 60, 58, 54, 51, 59, 67, 74, 79, 83, 87, 88, 85, 80, 81, 91, 96, 97, + 93, 85, 75, 63, 47, 41, 38, 37, 37, 38, 46, 56, 61, 64, 65, 65, 67, + 71, 75, 79, 82, 83, 82, 79, 75, 80, 84, 87, 87, 87, 85, 83, 81, 76, + 66, 53, 45, 55, 61, 63, 60, 55, 54, 55, 56, 58, 58, 65, 72, 78, 81, + 81, 79, 74, 74, 76, 80, 82, 79, 75, 79, 81, 81, 78, 73, 66, 56, 43, + 36, 34, 28, 16, 1, 0, 0, 6, 23, 40, 55, 64, 69, 69, 68, 64, 58, + 47, 43, 50, 60, 67, 71, 72, 71, 69, 68, 68, 69, 72, 74, 74, 73, 69, + 64, 61, 75, 84, 88, 88, 86, 83, 79, 74, 70, 64, 57, 44, 27, 9, 2, + 0, 0, 6, 13, 25, 38, 51, 59, 64, 65, 62, 57, 52, 45, 34, 22, 9, + 0, 0, 0, 14, 29, 45, 58, 67, 74, 80, 88, 98,109,118,124,125,119, +108,100, 98, 96, 92, 94, 94, 93, 90, 83, 74, 65, 53, 56, 61, 60, 55, + 47, 38, 25, 9, 0, 0, 0, 9, 25, 39, 54, 66, 77, 87, 96,105,113, +120,122,120,113,106, 99, 90, 86, 81, 74, 63, 48, 43, 38, 33, 29, 41, + 56, 66, 74, 87,102,117,127,132,132,130,128,128,132,136,133,127,118, +107, 97, 88, 80, 74, 66, 55, 39, 20, 8, 5, 12, 26, 39, 51, 58, 61, + 61, 59, 55, 48, 51, 59, 66, 72, 76, 80, 85, 87, 85, 81, 77, 88, 96, + 98, 96, 88, 79, 66, 50, 33, 31, 31, 31, 37, 48, 56, 59, 60, 59, 58, + 60, 64, 69, 73, 74, 74, 72, 68, 70, 75, 79, 80, 80, 79, 78, 76, 75, + 71, 60, 46, 37, 43, 52, 56, 54, 51, 50, 52, 54, 55, 54, 59, 69, 75, + 78, 78, 74, 69, 63, 68, 74, 78, 77, 74, 78, 81, 82, 80, 74, 66, 58, + 46, 33, 28, 25, 18, 5, 0, 0, 15, 33, 48, 59, 65, 67, 66, 62, 55, + 46, 34, 39, 51, 59, 64, 64, 63, 60, 57, 55, 55, 57, 59, 59, 57, 53, + 46, 40, 48, 62, 70, 73, 73, 70, 67, 63, 60, 56, 51, 41, 27, 8, 0, + 1, 2, 11, 14, 22, 36, 48, 57, 63, 65, 64, 60, 57, 55, 48, 37, 22, + 5, 0, 0, 2, 19, 34, 46, 54, 64, 71, 79, 88, 99,109,118,122,121, +113,102, 92, 92, 89, 92, 92, 92, 91, 86, 76, 62, 51, 44, 52, 56, 53, + 45, 34, 21, 8, 0, 0, 1, 7, 12, 25, 38, 51, 63, 75, 86, 96,104, +112,117,117,113,108,101, 95, 89, 84, 78, 69, 58, 44, 38, 36, 33, 34, + 51, 62, 71, 76, 92,107,121,129,132,130,127,123,122,125,129,128,123, +114,105, 96, 90, 80, 74, 65, 54, 38, 19, 1, 0, 5, 23, 41, 54, 61, + 62, 60, 54, 47, 41, 50, 56, 61, 65, 68, 72, 77, 80, 80, 78, 74, 83, + 91, 94, 92, 86, 78, 66, 50, 28, 20, 19, 20, 33, 44, 51, 53, 53, 51, + 54, 58, 57, 61, 64, 65, 63, 59, 56, 62, 67, 70, 71, 70, 68, 66, 64, + 63, 59, 50, 37, 27, 27, 38, 44, 43, 40, 41, 45, 48, 51, 51, 51, 62, + 70, 73, 72, 67, 61, 53, 56, 64, 72, 74, 71, 74, 77, 79, 78, 73, 62, + 55, 46, 36, 22, 20, 15, 5, 0, 5, 25, 41, 54, 61, 64, 64, 60, 54, + 45, 44, 41, 41, 50, 55, 57, 55, 50, 44, 39, 37, 37, 38, 40, 38, 34, + 27, 20, 16, 32, 45, 52, 53, 51, 52, 48, 43, 41, 39, 34, 23, 8, 0, + 0, 2, 12, 19, 20, 29, 43, 55, 61, 65, 64, 61, 59, 60, 58, 51, 39, + 23, 6, 0, 0, 8, 26, 40, 51, 57, 59, 67, 76, 87, 96,106,113,115, +113,104, 93, 86, 85, 89, 91, 91, 88, 86, 80, 68, 51, 34, 37, 43, 44, + 39, 28, 15, 2, 0, 5, 13, 20, 25, 28, 28, 33, 44, 57, 70, 81, 92, +100,106,110,110,106,101, 98, 95, 88, 81, 73, 62, 50, 36, 26, 26, 26, + 38, 55, 67, 74, 79, 92,108,120,125,125,123,119,114,113,117,120,120, +115,109,101, 97, 92, 83, 73, 64, 52, 36, 18, 0, 0, 0, 19, 39, 53, + 60, 61, 56, 47, 37, 40, 45, 52, 56, 57, 55, 56, 61, 67, 71, 72, 70, + 74, 82, 85, 84, 79, 73, 62, 47, 28, 7, 5, 8, 23, 34, 40, 43, 41, + 43, 51, 53, 50, 51, 54, 54, 51, 46, 43, 50, 55, 56, 56, 54, 51, 48, + 46, 46, 44, 36, 23, 15, 11, 19, 25, 25, 23, 28, 34, 40, 44, 45, 44, + 53, 61, 65, 64, 59, 53, 48, 48, 54, 64, 69, 70, 66, 69, 71, 71, 65, + 56, 46, 41, 33, 22, 13, 8, 1, 1, 11, 32, 48, 58, 62, 62, 59, 54, + 51, 54, 53, 48, 40, 44, 46, 46, 39, 31, 29, 25, 15, 13, 15, 16, 14, + 9, 3, 0, 0, 12, 22, 27, 27, 37, 41, 39, 31, 20, 20, 16, 6, 2, + 0, 0, 8, 20, 23, 21, 34, 48, 58, 64, 64, 61, 56, 61, 62, 59, 52, + 39, 22, 5, 0, 0, 14, 29, 43, 52, 57, 60, 61, 72, 83, 92,101,106, +107,102, 94, 83, 82, 87, 89, 89, 87, 84, 79, 73, 59, 39, 21, 25, 28, + 27, 20, 7, 1, 3, 14, 25, 32, 36, 39, 41, 40, 47, 50, 55, 60, 74, + 84, 92, 98,102,102, 99, 96, 98, 95, 87, 77, 65, 52, 38, 22, 9, 12, + 16, 38, 56, 69, 77, 81, 90,104,113,118,117,113,109,109,107,106,110, +111,108,103, 97, 96, 93, 85, 74, 63, 51, 33, 15, 0, 0, 0, 11, 33, + 50, 57, 57, 51, 39, 28, 34, 46, 53, 55, 54, 48, 40, 40, 48, 56, 61, + 64, 64, 70, 74, 73, 69, 63, 56, 44, 27, 8, 0, 0, 8, 20, 26, 29, + 29, 36, 41, 41, 36, 40, 44, 43, 39, 32, 25, 32, 37, 37, 36, 32, 28, + 26, 23, 25, 25, 21, 14, 4, 0, 0, 2, 2, 3, 8, 18, 27, 34, 38, + 38, 40, 52, 56, 56, 52, 48, 48, 46, 46, 56, 65, 68, 67, 61, 59, 59, + 54, 46, 37, 32, 27, 19, 8, 0, 0, 0, 16, 37, 53, 61, 63, 61, 56, + 56, 62, 64, 61, 54, 43, 32, 32, 29, 25, 27, 27, 21, 11, 0, 0, 1, + 3, 1, 0, 0, 0, 0, 0, 3, 15, 27, 33, 32, 23, 9, 3, 5, 6, + 4, 0, 0, 12, 20, 21, 23, 38, 52, 60, 64, 63, 58, 55, 60, 62, 58, + 50, 37, 19, 2, 0, 0, 15, 31, 43, 52, 56, 58, 60, 64, 76, 87, 94, + 98, 98, 92, 83, 79, 86, 89, 89, 87, 83, 77, 72, 63, 48, 29, 22, 14, + 11, 7, 0, 0, 1, 16, 29, 38, 44, 46, 48, 50, 59, 68, 72, 72, 66, + 65, 75, 84, 90, 94, 96, 94, 96, 96, 92, 84, 78, 70, 56, 36, 12, 0, + 0, 8, 32, 54, 69, 78, 84, 86, 97,105,108,106,104,106,106,102, 96, +101,102,102, 98, 94, 95, 92, 85, 76, 67, 57, 44, 28, 9, 0, 0, 2, + 25, 43, 52, 52, 45, 33, 20, 32, 43, 48, 48, 45, 38, 28, 18, 28, 39, + 50, 56, 60, 61, 60, 57, 54, 52, 46, 37, 26, 12, 0, 0, 0, 4, 12, + 16, 18, 20, 23, 21, 26, 31, 33, 32, 27, 20, 15, 8, 13, 14, 14, 18, + 20, 19, 15, 7, 9, 9, 6, 1, 0, 0, 0, 0, 0, 0, 0, 9, 19, + 26, 29, 28, 41, 48, 50, 47, 45, 46, 43, 33, 50, 61, 66, 68, 64, 58, + 50, 41, 34, 29, 22, 19, 13, 5, 0, 0, 0, 20, 41, 57, 64, 66, 63, + 58, 66, 71, 71, 66, 57, 43, 26, 14, 18, 22, 23, 21, 14, 7, 0, 0, + 0, 1, 5, 5, 1, 0, 0, 0, 0, 8, 20, 27, 26, 19, 9, 2, 9, + 12, 12, 9, 6, 8, 13, 13, 25, 39, 52, 60, 63, 62, 56, 50, 55, 56, + 52, 43, 28, 11, 0, 0, 0, 13, 27, 39, 47, 52, 54, 56, 59, 68, 79, + 87, 90, 89, 84, 74, 83, 88, 90, 89, 84, 78, 73, 64, 55, 44, 34, 25, + 13, 2, 0, 0, 0, 7, 22, 34, 43, 46, 48, 51, 64, 75, 84, 88, 88, + 84, 77, 68, 78, 85, 90, 93, 93, 92, 92, 88, 87, 83, 76, 64, 47, 23, + 0, 0, 0, 23, 48, 66, 78, 84, 87, 88, 95, 97, 97,101,102,100, 96, + 90, 94, 96, 97, 96, 92, 89, 88, 82, 78, 69, 59, 50, 37, 20, 0, 0, + 0, 16, 34, 43, 44, 37, 25, 18, 26, 36, 40, 40, 37, 33, 31, 21, 16, + 23, 37, 47, 55, 60, 61, 59, 52, 44, 46, 45, 39, 27, 12, 0, 0, 0, + 0, 2, 5, 6, 7, 11, 15, 20, 23, 25, 28, 28, 23, 16, 11, 7, 7, + 12, 14, 15, 12, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 6, 15, 20, 22, 32, 43, 47, 48, 46, 44, 41, 41, 45, 56, 63, 65, 64, + 59, 54, 47, 40, 27, 20, 18, 13, 7, 0, 0, 0, 20, 41, 57, 66, 68, + 66, 69, 75, 79, 77, 70, 59, 43, 33, 27, 23, 23, 23, 23, 20, 14, 6, + 0, 2, 11, 18, 19, 16, 11, 4, 0, 0, 5, 16, 23, 27, 25, 20, 13, + 12, 16, 19, 19, 18, 16, 20, 27, 38, 47, 52, 58, 62, 61, 56, 50, 45, + 47, 43, 33, 20, 13, 3, 0, 1, 13, 23, 34, 45, 54, 61, 67, 69, 67, + 69, 78, 82, 82, 77, 78, 87, 91, 92, 89, 84, 81, 79, 72, 62, 53, 43, + 31, 19, 5, 0, 0, 5, 16, 23, 32, 40, 45, 48, 62, 74, 86, 94, 99, +101, 97, 91, 84, 75, 79, 86, 91, 93, 95, 94, 93, 92, 88, 82, 71, 54, + 31, 7, 0, 0, 15, 40, 61, 74, 83, 87, 88, 90, 92, 94, 95, 94, 94, + 96,100,104,103, 97, 95, 92, 90, 88, 87, 84, 75, 62, 50, 39, 25, 6, + 0, 0, 7, 21, 29, 29, 23, 19, 19, 21, 29, 34, 36, 33, 34, 31, 22, + 6, 8, 22, 37, 50, 57, 60, 67, 67, 61, 51, 54, 52, 43, 28, 12, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 6, 19, 28, 34, 34, 29, 22, 16, 12, + 9, 6, 9, 12, 11, 7, 1, 0, 0, 0, 4, 7, 9, 12, 9, 1, 1, + 6, 12, 14, 15, 19, 22, 37, 46, 52, 54, 54, 53, 53, 54, 54, 55, 58, + 59, 57, 54, 52, 46, 33, 19, 19, 19, 18, 12, 8, 13, 16, 37, 54, 63, + 66, 67, 77, 84, 84, 82, 74, 62, 47, 46, 40, 34, 32, 31, 29, 26, 21, + 15, 16, 15, 18, 26, 29, 29, 26, 19, 11, 5, 7, 18, 26, 31, 32, 29, + 25, 21, 20, 19, 21, 22, 25, 28, 34, 45, 53, 56, 55, 59, 60, 57, 52, + 46, 40, 37, 33, 28, 23, 14, 8, 8, 21, 33, 44, 54, 62, 70, 76, 79, + 76, 73, 71, 76, 79, 79, 82, 90, 95, 96, 92, 86, 85, 84, 79, 71, 62, + 53, 41, 27, 19, 15, 12, 16, 26, 32, 33, 37, 45, 54, 69, 81, 92,101, +108,111,109,104, 98, 90, 81, 77, 84, 89, 93, 96, 96, 95, 92, 84, 74, + 57, 34, 11, 4, 2, 12, 31, 53, 69, 79, 84, 87, 88, 90, 91, 89, 95, +100,103,113,119,118,111,102, 92, 91, 90, 90, 88, 81, 70, 55, 39, 27, + 11, 4, 0, 0, 7, 13, 14, 15, 16, 18, 22, 26, 31, 32, 33, 32, 28, + 20, 5, 0, 8, 25, 39, 58, 71, 78, 79, 73, 64, 62, 62, 57, 46, 28, + 18, 13, 6, 1, 0, 0, 0, 0, 0, 11, 21, 28, 34, 36, 32, 25, 18, + 12, 7, 5, 6, 13, 18, 19, 19, 16, 14, 12, 11, 12, 15, 19, 16, 13, + 13, 13, 20, 22, 19, 16, 19, 33, 47, 56, 61, 63, 63, 63, 62, 60, 56, + 53, 48, 51, 51, 52, 48, 38, 22, 20, 23, 25, 22, 16, 21, 25, 31, 48, + 58, 61, 74, 83, 88, 89, 85, 77, 65, 57, 56, 50, 41, 37, 34, 32, 29, + 27, 32, 36, 36, 33, 32, 38, 39, 37, 31, 20, 12, 7, 14, 22, 29, 33, + 36, 34, 32, 31, 29, 28, 28, 29, 32, 37, 45, 53, 56, 56, 54, 57, 56, + 53, 47, 43, 39, 37, 34, 32, 25, 23, 23, 25, 37, 47, 57, 66, 74, 81, + 84, 83, 79, 75, 77, 82, 84, 85, 94,100,102, 98, 92, 88, 88, 84, 78, + 72, 63, 53, 39, 38, 34, 31, 26, 32, 37, 38, 34, 46, 57, 73, 84, 94, +104,112,117,119,117,113,105, 96, 85, 76, 81, 88, 93, 96, 95, 91, 83, + 72, 54, 32, 13, 12, 9, 21, 31, 43, 60, 73, 80, 84, 86, 87, 86, 95, +103,108,115,129,136,133,125,113,102, 90, 89, 91, 91, 85, 75, 62, 46, + 28, 14, 15, 11, 7, 3, 4, 7, 9, 12, 18, 23, 28, 31, 32, 31, 28, + 23, 16, 4, 0, 0, 16, 41, 61, 74, 82, 84, 79, 72, 72, 74, 69, 60, + 45, 39, 33, 27, 19, 13, 7, 6, 8, 16, 28, 39, 47, 51, 50, 44, 36, + 28, 22, 18, 15, 15, 21, 27, 31, 32, 31, 28, 26, 25, 22, 22, 22, 23, + 25, 25, 20, 26, 28, 26, 19, 16, 31, 48, 61, 68, 71, 72, 70, 67, 63, + 57, 52, 48, 45, 44, 48, 47, 39, 25, 20, 26, 29, 27, 19, 21, 23, 28, + 43, 53, 61, 74, 84, 90, 90, 86, 79, 68, 64, 62, 55, 45, 38, 33, 31, + 29, 36, 44, 50, 51, 48, 44, 43, 45, 44, 37, 25, 14, 6, 5, 14, 22, + 31, 36, 38, 38, 37, 34, 33, 33, 33, 36, 39, 41, 48, 53, 54, 50, 52, + 53, 51, 46, 41, 38, 37, 37, 36, 32, 33, 34, 37, 39, 44, 54, 63, 72, + 80, 85, 85, 82, 79, 79, 84, 87, 88, 97,104,108,106, 99, 89, 90, 88, + 84, 79, 72, 61, 56, 54, 51, 46, 41, 37, 39, 39, 37, 48, 62, 74, 85, + 95,104,113,120,124,127,125,120,111, 99, 86, 74, 79, 87, 91, 91, 87, + 78, 65, 47, 25, 14, 15, 16, 29, 41, 50, 53, 64, 74, 79, 82, 84, 93, +104,113,117,128,145,154,150,137,123,110, 97, 88, 88, 89, 86, 78, 67, + 53, 38, 25, 26, 20, 15, 9, 4, 1, 3, 7, 15, 23, 28, 31, 31, 29, + 28, 23, 13, 2, 0, 0, 14, 39, 59, 74, 82, 84, 80, 75, 81, 83, 79, + 72, 60, 58, 54, 46, 38, 31, 29, 28, 25, 33, 44, 53, 59, 61, 59, 53, + 45, 37, 29, 23, 20, 19, 26, 33, 37, 39, 39, 38, 36, 34, 32, 31, 31, + 33, 34, 33, 27, 31, 32, 28, 21, 13, 29, 51, 64, 73, 76, 75, 74, 69, + 62, 55, 48, 44, 43, 44, 44, 43, 38, 27, 20, 26, 29, 27, 19, 14, 16, + 22, 38, 48, 56, 70, 81, 87, 88, 84, 78, 69, 68, 65, 56, 45, 39, 36, + 29, 28, 39, 51, 58, 60, 58, 53, 46, 48, 46, 39, 26, 12, 2, 0, 3, + 12, 22, 31, 37, 38, 37, 36, 33, 33, 33, 37, 41, 43, 43, 46, 48, 45, + 44, 47, 46, 41, 38, 40, 37, 33, 34, 33, 36, 39, 41, 43, 45, 47, 54, + 64, 74, 81, 83, 81, 79, 80, 87, 90, 89, 99,109,113,113,108, 97, 90, + 89, 86, 83, 77, 68, 66, 64, 60, 56, 53, 47, 41, 39, 37, 51, 67, 81, + 93,104,113,119,121,125,132,134,132,124,113, 99, 83, 68, 78, 84, 84, + 79, 70, 55, 36, 14, 12, 15, 20, 37, 51, 59, 61, 60, 66, 73, 77, 85, +101,113,123,127,137,159,167,161,147,129,114,102, 91, 84, 85, 83, 77, + 68, 57, 45, 33, 32, 28, 21, 15, 8, 4, 6, 9, 13, 22, 28, 31, 28, + 27, 27, 27, 23, 18, 13, 9, 9, 32, 53, 67, 76, 79, 78, 84, 91, 92, + 89, 81, 74, 73, 69, 63, 55, 52, 52, 51, 45, 48, 57, 64, 68, 67, 63, + 56, 47, 38, 29, 22, 19, 19, 26, 33, 38, 40, 41, 41, 40, 38, 37, 36, + 37, 38, 39, 38, 32, 32, 31, 27, 20, 11, 29, 52, 66, 74, 77, 76, 74, + 67, 61, 65, 65, 60, 50, 40, 43, 40, 34, 27, 19, 23, 26, 23, 13, 1, + 3, 21, 36, 45, 48, 60, 73, 79, 81, 79, 74, 69, 69, 65, 56, 53, 53, + 52, 47, 45, 43, 52, 61, 64, 63, 58, 51, 51, 47, 38, 23, 13, 8, 3, + 2, 1, 11, 21, 28, 32, 32, 29, 28, 28, 29, 33, 40, 44, 39, 39, 40, + 39, 34, 39, 38, 33, 43, 48, 47, 38, 28, 29, 32, 37, 39, 40, 41, 43, + 44, 51, 63, 72, 75, 76, 76, 82, 88, 92, 91,101,112,120,122,117,106, + 93, 89, 88, 84, 79, 72, 72, 69, 64, 60, 57, 53, 47, 40, 36, 53, 71, + 85,100,114,128,139,142,137,133,139,140,136,125,111, 94, 75, 66, 74, + 74, 69, 58, 41, 21, 6, 6, 11, 19, 41, 58, 67, 69, 66, 59, 65, 71, + 89,107,123,134,139,142,163,169,163,147,129,114,102, 92, 84, 78, 77, + 74, 66, 57, 47, 38, 36, 32, 26, 20, 16, 21, 25, 25, 21, 28, 33, 34, + 33, 32, 37, 39, 36, 29, 25, 20, 15, 23, 43, 58, 67, 71, 82, 93,100, +102, 97, 89, 84, 84, 80, 75, 69, 68, 68, 67, 61, 62, 68, 73, 74, 72, + 65, 56, 45, 36, 26, 22, 19, 18, 23, 29, 34, 37, 38, 39, 38, 37, 36, + 34, 36, 38, 39, 38, 32, 29, 27, 22, 15, 13, 31, 52, 66, 74, 76, 74, + 71, 67, 75, 79, 79, 75, 65, 50, 41, 39, 32, 28, 20, 20, 20, 16, 6, + 0, 3, 20, 33, 41, 44, 45, 59, 67, 71, 70, 67, 69, 69, 64, 56, 58, + 62, 62, 62, 62, 58, 53, 60, 64, 63, 58, 52, 52, 46, 37, 20, 18, 15, + 12, 12, 11, 7, 9, 18, 20, 21, 20, 19, 19, 21, 26, 34, 40, 38, 33, + 34, 32, 26, 29, 28, 34, 47, 55, 57, 51, 38, 22, 25, 29, 33, 33, 33, + 33, 34, 36, 46, 59, 65, 68, 74, 83, 89, 92, 91,101,113,123,128,123, +113, 99, 88, 88, 85, 80, 74, 73, 69, 62, 58, 55, 52, 47, 41, 36, 54, + 72, 88,103,121,139,154,159,154,142,137,142,142,133,119,102, 84, 63, + 61, 62, 57, 45, 28, 11, 6, 5, 6, 19, 44, 63, 73, 74, 71, 62, 58, + 70, 92,112,130,147,152,149,159,163,156,142,125,111, 99, 90, 83, 76, + 69, 67, 61, 54, 46, 39, 34, 33, 29, 27, 32, 36, 38, 37, 32, 41, 46, + 47, 46, 43, 43, 44, 41, 44, 40, 33, 22, 16, 32, 47, 58, 74, 89,100, +108,110,105, 97, 88, 89, 88, 84, 80, 79, 79, 77, 72, 76, 80, 82, 80, + 75, 67, 55, 44, 43, 41, 40, 41, 41, 38, 34, 31, 32, 33, 33, 32, 29, + 28, 27, 28, 31, 33, 32, 27, 25, 21, 15, 7, 15, 31, 51, 64, 71, 73, + 70, 67, 76, 84, 88, 88, 84, 74, 59, 41, 40, 36, 29, 25, 18, 16, 11, + 0, 2, 6, 15, 28, 36, 39, 39, 40, 51, 56, 59, 65, 68, 68, 64, 54, + 58, 63, 66, 70, 71, 68, 62, 56, 60, 59, 55, 55, 53, 46, 36, 18, 16, + 15, 14, 16, 16, 13, 7, 4, 7, 7, 9, 14, 18, 20, 21, 22, 29, 29, + 31, 31, 28, 21, 20, 19, 36, 50, 59, 62, 59, 50, 33, 16, 22, 25, 26, + 25, 31, 33, 33, 29, 44, 53, 61, 73, 81, 87, 89, 88, 99,113,123,129, +125,114,101, 88, 88, 86, 80, 74, 70, 64, 56, 51, 51, 46, 41, 38, 40, + 60, 74, 85,102,120,140,158,165,161,147,132,139,140,134,122,106, 88, + 68, 52, 53, 47, 36, 22, 12, 8, 6, 2, 20, 46, 65, 75, 77, 73, 64, + 53, 70, 93,114,136,154,161,158,147,152,145,133,123,115,106, 95, 81, + 74, 64, 59, 54, 48, 48, 44, 43, 37, 36, 38, 41, 45, 47, 46, 41, 50, + 55, 57, 57, 55, 54, 54, 57, 60, 57, 52, 44, 34, 32, 48, 64, 80, 94, +106,113,117,113,106, 97, 91, 91, 90, 88, 87, 85, 85, 87, 90, 92, 92, + 88, 80, 69, 56, 57, 56, 55, 58, 60, 58, 55, 50, 45, 40, 37, 33, 31, + 31, 32, 32, 32, 31, 25, 25, 21, 16, 11, 5, 11, 18, 31, 50, 62, 68, + 69, 66, 71, 80, 88, 93, 94, 88, 79, 66, 50, 40, 37, 29, 27, 22, 15, + 9, 5, 6, 9, 15, 20, 28, 32, 34, 36, 40, 47, 55, 61, 65, 66, 62, + 53, 50, 57, 65, 72, 74, 73, 68, 63, 60, 59, 58, 57, 54, 47, 36, 18, + 7, 8, 9, 15, 16, 13, 8, 5, 4, 5, 7, 11, 13, 16, 18, 20, 22, + 25, 27, 27, 23, 18, 11, 18, 33, 48, 58, 62, 60, 53, 39, 22, 18, 20, + 25, 31, 37, 39, 39, 34, 36, 46, 57, 67, 74, 79, 82, 87, 98,110,120, +125,122,113,100, 88, 87, 84, 78, 69, 65, 57, 48, 53, 51, 45, 36, 33, + 47, 68, 83, 93, 99,111,129,147,158,156,147,133,128,130,128,118,104, + 88, 69, 52, 46, 40, 29, 21, 12, 7, 5, 1, 19, 45, 63, 73, 74, 70, + 61, 53, 71, 93,114,136,156,163,161,152,143,137,130,125,118,109, 97, + 84, 75, 65, 52, 48, 51, 51, 48, 44, 40, 41, 44, 47, 51, 54, 53, 50, + 53, 58, 61, 63, 64, 65, 66, 70, 72, 70, 66, 60, 53, 47, 56, 71, 85, + 97,109,117,120,118,112,105,100, 96, 93, 94, 96, 97,100,102,104,104, +102, 95, 85, 72, 67, 68, 66, 71, 74, 73, 70, 65, 59, 54, 50, 45, 41, + 41, 41, 41, 40, 37, 32, 26, 20, 16, 7, 6, 8, 13, 19, 32, 50, 60, + 64, 65, 62, 71, 82, 91, 96, 97, 93, 84, 73, 59, 46, 34, 31, 29, 26, + 21, 14, 8, 11, 13, 15, 19, 21, 23, 27, 31, 36, 41, 48, 54, 58, 59, + 57, 51, 38, 47, 60, 69, 74, 75, 73, 68, 64, 62, 59, 56, 52, 44, 33, + 18, 0, 0, 2, 7, 9, 8, 4, 1, 0, 0, 0, 2, 4, 6, 8, 11, + 14, 16, 19, 19, 16, 11, 7, 16, 29, 43, 52, 57, 56, 50, 38, 23, 15, + 19, 25, 33, 39, 44, 44, 39, 32, 39, 47, 56, 62, 70, 79, 86, 96,105, +113,118,114,108, 97, 87, 83, 79, 73, 62, 58, 50, 45, 47, 45, 38, 27, + 29, 55, 75, 90,102,107,109,115,130,142,145,140,132,117,117,115,109, + 98, 84, 67, 54, 45, 38, 31, 23, 13, 6, 5, 4, 15, 39, 57, 66, 68, + 64, 55, 56, 73, 92,111,130,147,158,158,150,142,136,129,122,114,106, + 96, 85, 75, 66, 54, 46, 48, 50, 48, 43, 46, 48, 48, 50, 54, 57, 58, + 57, 53, 57, 61, 65, 68, 71, 74, 77, 79, 77, 74, 69, 65, 61, 60, 74, + 87, 98,108,114,118,117,113,110,106,102, 99, 97,102,108,113,115,117, +115,110,102, 90, 76, 74, 75, 79, 83, 84, 81, 77, 71, 64, 59, 55, 50, + 50, 48, 47, 46, 43, 39, 32, 23, 20, 16, 14, 12, 9, 12, 16, 31, 47, + 57, 61, 61, 58, 68, 80, 90, 96, 97, 95, 88, 77, 66, 54, 41, 31, 32, + 31, 26, 19, 16, 19, 21, 23, 22, 19, 21, 22, 22, 26, 31, 36, 40, 45, + 47, 47, 43, 37, 37, 51, 62, 70, 74, 74, 70, 65, 60, 56, 51, 45, 38, + 28, 15, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 6, 13, 16, 19, 18, 16, 13, 12, 22, 32, 40, 45, 45, 41, 32, 20, + 14, 13, 21, 31, 39, 45, 46, 41, 32, 28, 34, 46, 58, 68, 76, 84, 91, + 98,103,106,105,101, 93, 86, 77, 72, 65, 54, 48, 41, 36, 36, 34, 27, + 20, 36, 60, 80, 95,106,113,113,112,113,124,129,130,125,113,102,102, + 97, 89, 78, 64, 56, 47, 39, 32, 25, 14, 4, 3, 9, 14, 32, 48, 58, + 60, 56, 56, 61, 72, 88,103,119,132,140,143,140,136,129,123,115,108, +100, 92, 83, 76, 67, 57, 47, 43, 44, 43, 46, 51, 55, 56, 56, 55, 58, + 61, 61, 59, 54, 58, 62, 67, 72, 75, 78, 79, 77, 74, 72, 69, 68, 68, + 74, 84, 94,102,107,110,111,110,109,108,105,102, 98,106,114,121,125, +125,123,117,107, 95, 81, 78, 81, 88, 90, 90, 87, 81, 74, 67, 61, 57, + 53, 54, 53, 51, 47, 41, 37, 31, 23, 19, 16, 18, 18, 16, 14, 11, 26, + 41, 52, 56, 56, 54, 63, 76, 86, 93, 96, 93, 87, 79, 69, 58, 46, 33, + 36, 36, 31, 25, 22, 23, 26, 28, 31, 29, 25, 20, 21, 20, 20, 21, 23, + 28, 33, 37, 37, 33, 26, 38, 51, 61, 67, 69, 66, 60, 54, 47, 40, 34, + 27, 20, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 11, 18, 21, 22, 21, 18, 13, 12, 19, 25, 29, 31, 28, 23, + 20, 16, 7, 14, 25, 34, 41, 43, 39, 29, 19, 25, 41, 54, 63, 71, 77, + 83, 88, 91, 93, 93, 91, 88, 84, 77, 67, 56, 46, 38, 33, 26, 21, 19, + 14, 14, 39, 62, 81, 96,107,113,114,112,106,107,113,117,115,107, 93, + 88, 84, 79, 68, 65, 57, 48, 39, 32, 23, 15, 3, 2, 13, 20, 26, 40, + 48, 52, 56, 62, 65, 68, 81, 93,103,113,121,125,125,123,119,113,106, + 99, 92, 86, 81, 75, 67, 59, 51, 40, 37, 39, 47, 54, 59, 61, 62, 61, + 57, 61, 63, 62, 57, 52, 56, 61, 67, 71, 74, 74, 72, 69, 67, 67, 68, + 70, 73, 79, 86, 92, 96, 98,100,101,102,104,104,102,100,106,115,124, +128,129,127,121,112,101, 88, 80, 86, 92, 95, 94, 89, 83, 75, 68, 62, + 59, 55, 56, 55, 52, 46, 45, 41, 34, 25, 21, 16, 18, 19, 20, 18, 20, + 29, 36, 44, 50, 51, 50, 55, 69, 80, 88, 90, 88, 84, 76, 68, 58, 46, + 37, 41, 41, 36, 28, 26, 25, 27, 29, 33, 34, 33, 27, 18, 12, 9, 8, + 9, 13, 18, 23, 27, 26, 22, 22, 36, 47, 56, 59, 57, 51, 41, 32, 25, + 18, 13, 8, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 2, 0, 0, 0, 8, 16, 22, 26, 25, 21, 15, 8, 3, 7, 12, 14, 15, + 16, 19, 16, 7, 5, 16, 26, 33, 36, 32, 22, 16, 23, 34, 47, 55, 61, + 66, 70, 74, 76, 78, 79, 80, 80, 79, 75, 67, 54, 38, 26, 23, 18, 12, + 5, 2, 18, 39, 60, 78, 91,102,108,110,108,102, 96, 97,101,102, 96, + 86, 74, 70, 64, 68, 66, 58, 47, 39, 31, 22, 13, 2, 1, 13, 21, 29, + 38, 47, 55, 62, 66, 67, 65, 71, 79, 88, 95,102,107,110,108,105,100, + 94, 88, 84, 84, 79, 73, 67, 61, 54, 44, 34, 39, 45, 53, 59, 64, 66, + 65, 61, 58, 61, 62, 58, 51, 47, 52, 56, 60, 62, 61, 59, 57, 57, 58, + 62, 66, 71, 72, 74, 78, 81, 84, 86, 89, 93, 97,100,101,100,102,112, +121,124,125,125,122,115,106, 95, 82, 88, 95, 97, 95, 90, 83, 77, 74, + 64, 60, 56, 57, 55, 51, 44, 45, 41, 33, 25, 25, 22, 15, 18, 18, 16, + 26, 38, 45, 46, 41, 45, 45, 45, 61, 74, 80, 83, 81, 76, 69, 62, 53, + 46, 46, 50, 48, 41, 32, 27, 31, 31, 28, 32, 34, 36, 33, 25, 11, 0, + 0, 6, 11, 11, 8, 14, 16, 15, 12, 19, 31, 39, 45, 43, 34, 25, 26, + 25, 16, 3, 0, 0, 0, 6, 9, 9, 6, 2, 0, 0, 0, 0, 2, 3, + 3, 2, 0, 0, 0, 5, 15, 23, 27, 27, 22, 15, 7, 3, 0, 2, 6, + 9, 13, 15, 13, 6, 3, 6, 15, 22, 25, 22, 14, 21, 29, 33, 36, 43, + 46, 48, 52, 54, 56, 63, 69, 70, 71, 73, 72, 65, 53, 37, 20, 13, 9, + 3, 0, 5, 22, 36, 54, 70, 83, 92, 98,101,101, 96, 90, 82, 84, 87, + 84, 75, 60, 57, 65, 68, 66, 58, 46, 39, 27, 19, 9, 1, 2, 11, 20, + 29, 40, 51, 59, 65, 68, 68, 63, 57, 67, 76, 81, 83, 89, 92, 92, 91, + 87, 82, 77, 79, 79, 75, 69, 67, 63, 57, 47, 39, 36, 38, 47, 57, 63, + 67, 67, 63, 57, 57, 58, 56, 50, 41, 39, 43, 45, 46, 44, 45, 53, 57, + 58, 55, 58, 64, 66, 66, 64, 64, 67, 71, 75, 81, 87, 92, 96, 98, 99, +105,113,117,119,121,122,119,113,102, 92, 88, 96, 97, 96, 91, 85, 84, + 79, 69, 63, 59, 57, 54, 48, 40, 39, 34, 26, 27, 28, 28, 23, 16, 14, + 16, 31, 44, 52, 55, 52, 44, 39, 39, 54, 65, 72, 74, 72, 66, 58, 55, + 53, 51, 57, 59, 57, 48, 36, 28, 37, 41, 40, 34, 32, 34, 33, 26, 13, + 8, 9, 11, 13, 11, 4, 1, 5, 6, 6, 5, 13, 21, 26, 25, 16, 26, + 29, 28, 20, 5, 0, 0, 1, 11, 15, 16, 13, 7, 1, 0, 0, 1, 6, + 8, 7, 4, 0, 0, 0, 0, 12, 21, 26, 27, 23, 15, 14, 15, 13, 7, + 2, 3, 5, 7, 6, 2, 1, 4, 6, 9, 12, 9, 13, 25, 33, 37, 34, + 27, 25, 26, 28, 38, 53, 63, 69, 69, 65, 65, 66, 61, 52, 36, 16, 6, + 0, 0, 0, 11, 29, 44, 54, 59, 71, 79, 86, 90, 92, 90, 84, 76, 67, + 71, 69, 60, 55, 60, 66, 68, 66, 57, 52, 46, 33, 16, 4, 3, 4, 5, + 15, 27, 39, 50, 58, 64, 67, 65, 59, 65, 69, 77, 80, 79, 74, 75, 76, + 75, 73, 69, 69, 72, 73, 69, 65, 67, 65, 60, 52, 40, 36, 26, 38, 50, + 59, 65, 67, 64, 58, 50, 52, 50, 45, 38, 31, 27, 31, 28, 38, 48, 56, + 61, 63, 61, 58, 55, 59, 60, 60, 64, 68, 70, 70, 67, 76, 84, 91, 96, +100,103,106,110,113,118,122,123,119,111,100, 88, 95, 97, 96, 92, 87, + 85, 80, 71, 69, 65, 60, 54, 48, 39, 28, 19, 21, 26, 31, 32, 32, 27, + 19, 20, 34, 47, 57, 61, 60, 53, 43, 32, 48, 59, 65, 65, 61, 58, 55, + 54, 59, 65, 69, 70, 67, 58, 44, 26, 37, 44, 46, 44, 39, 33, 29, 25, + 26, 29, 31, 28, 21, 11, 1, 0, 0, 0, 0, 1, 1, 6, 11, 9, 19, + 27, 33, 32, 27, 15, 0, 0, 0, 11, 16, 16, 13, 7, 2, 0, 0, 0, + 3, 5, 4, 1, 0, 0, 0, 0, 7, 16, 23, 26, 22, 15, 22, 25, 22, + 15, 8, 1, 0, 0, 0, 0, 0, 4, 6, 5, 1, 0, 13, 26, 34, 37, + 33, 23, 13, 4, 18, 36, 52, 62, 68, 68, 63, 56, 59, 57, 48, 36, 19, + 2, 0, 0, 0, 18, 37, 51, 60, 65, 66, 66, 74, 79, 82, 81, 77, 70, + 60, 51, 56, 57, 59, 65, 69, 70, 66, 56, 56, 51, 39, 22, 4, 3, 3, + 0, 16, 29, 40, 46, 54, 60, 63, 61, 68, 74, 78, 79, 77, 74, 68, 57, + 64, 64, 60, 56, 57, 61, 62, 58, 64, 68, 68, 65, 58, 48, 37, 41, 39, + 40, 47, 56, 60, 60, 56, 47, 43, 41, 37, 34, 37, 39, 40, 43, 47, 52, + 56, 62, 65, 64, 62, 60, 61, 64, 69, 74, 78, 80, 81, 79, 76, 79, 82, + 91, 98,104,110,115,119,118,124,128,127,121,110, 97, 92, 95, 95, 92, + 88, 84, 79, 78, 77, 74, 70, 63, 54, 45, 37, 34, 33, 29, 29, 36, 38, + 37, 38, 43, 41, 48, 58, 63, 62, 56, 46, 45, 53, 59, 63, 63, 61, 57, + 62, 68, 72, 76, 79, 79, 75, 67, 55, 38, 31, 39, 44, 46, 45, 41, 39, + 38, 40, 44, 45, 44, 37, 27, 14, 4, 3, 3, 0, 0, 0, 0, 3, 8, + 18, 29, 38, 39, 33, 22, 7, 0, 0, 8, 13, 13, 11, 15, 16, 14, 8, + 2, 2, 2, 2, 1, 0, 2, 5, 5, 13, 20, 22, 23, 21, 22, 29, 31, + 27, 20, 11, 12, 13, 12, 8, 6, 3, 3, 5, 5, 1, 0, 9, 22, 29, + 32, 28, 20, 11, 14, 15, 27, 44, 56, 62, 64, 60, 54, 53, 52, 47, 37, + 22, 7, 0, 0, 1, 20, 38, 52, 60, 65, 66, 65, 62, 64, 69, 70, 68, + 64, 65, 61, 59, 61, 65, 69, 71, 70, 65, 59, 59, 54, 43, 26, 15, 12, + 8, 8, 23, 37, 46, 52, 56, 59, 62, 66, 73, 79, 83, 84, 82, 77, 71, + 65, 61, 60, 57, 52, 44, 45, 50, 56, 63, 69, 71, 70, 66, 59, 50, 56, + 48, 46, 44, 40, 47, 50, 47, 41, 33, 31, 36, 40, 43, 46, 48, 51, 55, + 58, 61, 62, 66, 66, 65, 64, 66, 70, 76, 82, 87, 91, 92, 92, 88, 84, + 86, 87, 92,101,109,117,122,123,129,136,137,133,123,110, 99, 93, 90, + 89, 88, 85, 84, 84, 84, 81, 78, 72, 64, 56, 51, 48, 48, 43, 34, 37, + 43, 46, 58, 63, 62, 57, 55, 59, 59, 54, 51, 58, 63, 67, 67, 65, 60, + 65, 74, 78, 79, 82, 83, 82, 79, 72, 62, 48, 33, 33, 40, 45, 47, 47, + 47, 46, 48, 53, 55, 55, 50, 41, 31, 20, 13, 14, 11, 3, 0, 0, 2, + 8, 21, 32, 38, 40, 36, 26, 13, 0, 0, 6, 8, 11, 19, 27, 31, 31, + 26, 21, 18, 16, 13, 11, 13, 18, 20, 19, 21, 28, 29, 26, 19, 28, 36, + 36, 31, 22, 18, 23, 27, 26, 22, 16, 11, 3, 3, 3, 3, 7, 14, 18, + 23, 27, 25, 20, 20, 23, 25, 23, 28, 43, 52, 54, 53, 48, 47, 48, 45, + 37, 25, 12, 0, 0, 0, 16, 33, 46, 55, 59, 61, 61, 57, 48, 52, 55, + 63, 70, 72, 69, 66, 67, 69, 71, 71, 68, 61, 60, 59, 54, 44, 28, 23, + 19, 14, 13, 29, 40, 50, 54, 58, 61, 64, 68, 73, 79, 84, 85, 85, 82, + 78, 74, 71, 66, 60, 53, 44, 39, 43, 52, 61, 69, 74, 74, 73, 68, 62, + 66, 61, 54, 46, 41, 37, 34, 34, 34, 36, 39, 44, 48, 50, 50, 52, 54, + 57, 61, 63, 61, 65, 67, 66, 66, 68, 74, 80, 87, 93, 99,102,102, 99, + 93, 91, 92, 92, 96,104,113,121,124,136,145,149,147,137,124,113,105, + 96, 88, 84, 84, 86, 87, 87, 85, 82, 76, 70, 63, 59, 59, 58, 54, 44, + 36, 44, 60, 72, 77, 76, 72, 66, 61, 58, 58, 61, 66, 70, 71, 69, 64, + 61, 73, 80, 84, 83, 84, 83, 81, 78, 73, 65, 55, 43, 41, 41, 44, 48, + 51, 52, 52, 54, 58, 61, 62, 59, 54, 45, 34, 23, 27, 25, 18, 7, 0, + 0, 9, 20, 29, 36, 37, 33, 26, 16, 12, 8, 4, 5, 13, 23, 33, 40, + 41, 40, 38, 34, 32, 28, 27, 27, 29, 31, 28, 32, 38, 39, 33, 28, 32, + 38, 38, 32, 22, 23, 31, 36, 36, 31, 22, 14, 5, 0, 4, 9, 15, 20, + 22, 21, 20, 21, 23, 29, 31, 29, 28, 26, 23, 34, 40, 41, 39, 41, 45, + 43, 37, 26, 15, 4, 0, 0, 7, 22, 34, 43, 47, 51, 52, 48, 39, 33, + 53, 66, 74, 77, 74, 71, 70, 70, 70, 69, 64, 58, 58, 57, 53, 43, 31, + 27, 21, 15, 19, 32, 43, 50, 54, 57, 61, 63, 66, 70, 76, 80, 84, 85, + 84, 83, 80, 78, 73, 66, 56, 44, 41, 39, 45, 56, 66, 73, 76, 76, 74, + 71, 71, 68, 63, 58, 52, 47, 43, 41, 43, 46, 52, 56, 60, 60, 58, 53, + 53, 56, 59, 61, 59, 64, 66, 65, 65, 67, 74, 81, 89, 96,103,109,110, +106, 99, 96, 98, 96, 92, 98,108,117,128,142,154,159,159,152,142,130, +121,111,100, 88, 84, 84, 87, 88, 85, 82, 77, 71, 65, 62, 63, 64, 60, + 52, 38, 50, 67, 79, 84, 84, 80, 74, 69, 65, 64, 66, 70, 73, 73, 69, + 62, 66, 77, 83, 84, 82, 79, 77, 74, 72, 68, 63, 56, 48, 50, 50, 50, + 50, 54, 55, 55, 56, 60, 63, 66, 65, 61, 55, 46, 36, 40, 39, 33, 21, + 6, 0, 7, 15, 23, 28, 29, 29, 27, 28, 26, 21, 15, 7, 13, 22, 33, + 41, 45, 46, 47, 47, 45, 43, 39, 37, 38, 37, 36, 46, 51, 48, 41, 36, + 40, 38, 37, 29, 20, 25, 33, 38, 38, 33, 23, 21, 18, 9, 14, 18, 21, + 23, 25, 26, 28, 29, 33, 36, 34, 33, 31, 28, 22, 15, 25, 28, 28, 38, + 41, 41, 36, 27, 16, 6, 0, 0, 0, 7, 18, 25, 29, 33, 37, 36, 40, + 43, 55, 69, 77, 80, 77, 73, 70, 69, 68, 65, 59, 55, 54, 52, 47, 38, + 32, 28, 21, 14, 23, 34, 41, 48, 57, 62, 65, 66, 66, 65, 70, 74, 79, + 82, 84, 84, 83, 81, 77, 70, 60, 46, 41, 40, 39, 45, 58, 67, 73, 74, + 74, 73, 68, 68, 67, 65, 63, 60, 57, 55, 54, 54, 61, 67, 70, 69, 64, + 57, 48, 52, 55, 56, 54, 60, 63, 62, 61, 64, 70, 79, 88, 96,103,110, +112,108,102,102,103,101, 96, 92,101,115,130,145,158,165,167,165,158, +149,139,127,113, 98, 87, 84, 83, 84, 81, 78, 73, 67, 62, 60, 62, 65, + 63, 56, 50, 53, 69, 81, 86, 86, 83, 78, 72, 68, 65, 65, 69, 72, 71, + 66, 59, 68, 77, 81, 81, 76, 72, 67, 63, 60, 59, 57, 53, 53, 55, 56, + 56, 55, 55, 57, 58, 58, 60, 64, 67, 68, 66, 62, 55, 47, 52, 52, 46, + 33, 15, 2, 2, 8, 14, 23, 34, 41, 44, 43, 39, 33, 26, 19, 21, 29, + 38, 45, 50, 52, 54, 53, 53, 51, 47, 44, 43, 40, 51, 59, 62, 59, 50, + 39, 43, 40, 32, 26, 18, 23, 31, 37, 37, 29, 31, 34, 32, 23, 23, 23, + 25, 28, 39, 46, 50, 48, 44, 40, 37, 34, 32, 28, 25, 18, 9, 15, 20, + 33, 38, 38, 33, 26, 20, 12, 3, 0, 0, 0, 0, 4, 8, 19, 32, 44, + 51, 53, 58, 71, 79, 81, 77, 72, 69, 66, 64, 60, 54, 47, 45, 44, 40, + 31, 29, 26, 18, 20, 27, 34, 47, 57, 63, 66, 68, 68, 67, 65, 61, 66, + 71, 74, 78, 79, 80, 79, 77, 72, 62, 50, 38, 38, 37, 36, 44, 55, 63, + 67, 69, 69, 59, 62, 65, 68, 69, 69, 68, 65, 62, 62, 70, 75, 77, 75, + 69, 59, 46, 45, 48, 48, 51, 57, 58, 57, 56, 59, 66, 74, 82, 91, 99, +105,108,105,103,108,109,105, 98, 89, 99,115,132,145,158,165,169,171, +169,165,159,147,129,111, 92, 84, 79, 76, 74, 69, 63, 58, 54, 53, 57, + 61, 62, 60, 63, 61, 67, 78, 84, 84, 80, 75, 70, 64, 61, 61, 64, 67, + 65, 61, 59, 68, 74, 76, 74, 67, 61, 63, 60, 54, 45, 45, 45, 53, 57, + 58, 59, 59, 59, 60, 63, 65, 61, 62, 66, 68, 68, 65, 58, 56, 61, 62, + 56, 41, 23, 6, 0, 1, 19, 37, 48, 55, 56, 53, 47, 40, 34, 29, 28, + 33, 39, 45, 48, 53, 56, 56, 54, 54, 51, 47, 45, 52, 63, 71, 73, 69, + 58, 43, 43, 39, 28, 19, 12, 19, 26, 29, 31, 29, 41, 47, 45, 36, 31, + 29, 28, 39, 53, 61, 65, 63, 57, 46, 43, 44, 39, 31, 26, 21, 14, 5, + 14, 27, 34, 34, 31, 28, 27, 21, 8, 3, 0, 0, 0, 0, 8, 20, 36, + 50, 57, 61, 62, 73, 79, 80, 75, 72, 71, 67, 61, 55, 48, 38, 33, 32, + 29, 22, 23, 20, 23, 26, 29, 44, 56, 63, 67, 68, 67, 66, 65, 64, 60, + 55, 58, 63, 67, 70, 73, 74, 73, 70, 63, 53, 37, 32, 31, 29, 27, 37, + 47, 53, 57, 58, 45, 52, 59, 66, 71, 74, 74, 72, 67, 69, 76, 81, 81, + 78, 69, 57, 43, 38, 40, 40, 47, 53, 54, 52, 50, 61, 68, 72, 74, 84, + 92, 97,100, 99,108,113,114,110,101, 91, 96,113,128,142,152,171,179, +175,173,175,173,163,145,123,102, 84, 76, 65, 63, 58, 52, 47, 46, 44, + 47, 54, 57, 68, 73, 73, 69, 72, 76, 76, 74, 68, 62, 57, 53, 52, 55, + 58, 58, 55, 59, 66, 70, 69, 64, 61, 67, 70, 67, 59, 47, 31, 40, 50, + 55, 57, 58, 58, 59, 61, 65, 67, 65, 61, 65, 67, 68, 65, 59, 63, 68, + 69, 62, 47, 28, 8, 0, 4, 26, 45, 57, 61, 61, 57, 50, 44, 40, 37, + 36, 36, 38, 41, 45, 50, 55, 57, 54, 55, 53, 50, 46, 61, 73, 79, 81, + 76, 65, 50, 39, 36, 25, 11, 5, 12, 18, 22, 22, 34, 48, 56, 55, 45, + 37, 33, 29, 46, 61, 71, 75, 74, 66, 55, 47, 48, 45, 38, 28, 25, 20, + 12, 6, 20, 28, 31, 28, 31, 32, 27, 16, 8, 3, 0, 0, 7, 18, 26, + 39, 54, 62, 66, 67, 74, 79, 79, 73, 74, 72, 65, 56, 50, 43, 31, 20, + 19, 18, 13, 19, 27, 31, 31, 34, 51, 60, 66, 67, 66, 63, 60, 58, 58, + 56, 53, 48, 47, 52, 56, 59, 62, 64, 64, 61, 54, 41, 26, 23, 21, 19, + 14, 25, 33, 38, 41, 29, 39, 51, 61, 69, 74, 75, 74, 69, 75, 81, 84, + 83, 76, 65, 50, 32, 33, 34, 37, 47, 52, 52, 48, 45, 58, 65, 70, 73, + 74, 82, 88, 90,101,111,118,118,113,104, 94, 88,104,119,134,158,177, +190,188,169,175,179,175,158,134,112, 92, 74, 61, 51, 46, 48, 50, 50, + 46, 38, 46, 60, 73, 79, 80, 78, 73, 68, 68, 64, 62, 60, 57, 54, 50, + 45, 48, 50, 53, 59, 63, 64, 62, 56, 63, 69, 72, 69, 61, 48, 36, 33, + 44, 50, 53, 54, 59, 63, 63, 61, 63, 62, 61, 64, 66, 66, 63, 58, 66, + 72, 73, 66, 51, 31, 11, 0, 5, 27, 46, 57, 61, 60, 54, 47, 45, 41, + 41, 43, 45, 46, 45, 41, 47, 54, 57, 56, 54, 55, 53, 50, 65, 77, 84, + 85, 80, 70, 54, 34, 31, 20, 6, 0, 5, 11, 14, 15, 34, 51, 59, 59, + 51, 39, 34, 31, 48, 65, 75, 80, 79, 74, 62, 48, 45, 44, 38, 33, 32, + 27, 20, 8, 12, 21, 26, 26, 29, 32, 28, 18, 16, 12, 4, 4, 18, 31, + 39, 44, 58, 66, 69, 70, 76, 79, 78, 71, 73, 68, 60, 50, 43, 36, 23, + 7, 6, 6, 11, 27, 36, 38, 37, 36, 51, 59, 63, 62, 58, 53, 47, 45, + 45, 45, 44, 43, 41, 40, 40, 41, 46, 52, 56, 56, 53, 44, 32, 15, 14, + 12, 6, 4, 12, 19, 23, 34, 41, 45, 56, 66, 73, 75, 74, 74, 79, 84, + 84, 80, 71, 56, 37, 29, 29, 29, 38, 46, 50, 47, 41, 40, 52, 60, 64, + 67, 70, 74, 79, 88, 99,110,117,118,113,106, 96, 88, 99,114,134,158, +179,190,190,173,173,179,179,167,145,121,101, 83, 65, 48, 48, 50, 51, + 50, 45, 38, 39, 58, 72, 79, 82, 80, 77, 73, 70, 68, 66, 64, 61, 58, + 60, 58, 54, 51, 55, 58, 59, 59, 55, 55, 61, 66, 68, 65, 57, 44, 38, + 37, 40, 45, 52, 58, 62, 65, 65, 62, 59, 59, 61, 63, 65, 64, 62, 57, + 64, 70, 71, 64, 50, 29, 9, 0, 4, 26, 43, 52, 55, 52, 54, 58, 56, + 52, 47, 46, 52, 56, 58, 56, 48, 53, 57, 58, 53, 54, 54, 53, 66, 78, + 85, 87, 84, 74, 59, 40, 23, 13, 3, 0, 0, 5, 9, 12, 29, 46, 57, + 59, 53, 40, 36, 32, 46, 63, 75, 82, 83, 79, 70, 58, 47, 40, 40, 40, + 40, 37, 31, 20, 9, 9, 16, 23, 29, 31, 28, 23, 22, 18, 11, 12, 27, + 41, 51, 54, 61, 69, 72, 73, 77, 78, 76, 69, 69, 63, 53, 43, 37, 28, + 16, 0, 3, 12, 18, 32, 40, 41, 40, 39, 48, 55, 56, 53, 46, 45, 45, + 41, 34, 29, 31, 32, 34, 36, 38, 41, 41, 37, 43, 47, 48, 47, 41, 28, + 13, 6, 0, 0, 0, 5, 21, 37, 44, 48, 52, 65, 74, 77, 77, 74, 79, + 82, 80, 75, 63, 45, 27, 27, 26, 27, 37, 43, 43, 38, 31, 37, 46, 53, + 56, 58, 61, 66, 73, 83, 94,104,111,112,109,102, 94, 88, 96,112,130, +152,171,183,181,165,169,179,181,175,156,132,110, 92, 77, 61, 52, 52, + 52, 50, 45, 38, 39, 50, 65, 74, 79, 79, 77, 74, 72, 70, 69, 67, 65, + 70, 72, 70, 64, 58, 56, 56, 55, 52, 51, 55, 58, 61, 60, 55, 46, 36, + 34, 34, 39, 45, 52, 58, 62, 64, 63, 59, 56, 55, 57, 59, 61, 61, 60, + 56, 57, 63, 64, 57, 43, 22, 5, 6, 7, 25, 39, 46, 46, 47, 60, 65, + 63, 59, 53, 46, 56, 64, 67, 66, 60, 51, 56, 56, 52, 48, 50, 55, 68, + 79, 86, 88, 85, 77, 63, 46, 29, 15, 4, 0, 0, 0, 4, 8, 20, 38, + 51, 56, 54, 44, 37, 34, 39, 58, 73, 81, 84, 82, 75, 65, 55, 45, 45, + 46, 46, 45, 40, 32, 22, 15, 20, 26, 31, 32, 29, 22, 22, 18, 18, 22, + 39, 53, 61, 64, 65, 71, 75, 75, 74, 74, 71, 68, 65, 57, 44, 38, 31, + 22, 18, 11, 12, 20, 23, 32, 38, 39, 38, 37, 45, 48, 46, 41, 39, 38, + 37, 31, 22, 15, 18, 21, 25, 28, 33, 38, 39, 38, 38, 47, 57, 61, 59, + 52, 38, 25, 11, 0, 0, 6, 23, 34, 43, 47, 51, 65, 75, 79, 80, 77, + 76, 78, 75, 68, 55, 34, 23, 21, 19, 27, 34, 36, 32, 26, 21, 33, 39, + 41, 43, 45, 47, 53, 62, 74, 86, 95,101,102,100, 95, 89, 85, 91,106, +124,143,159,169,165,152,163,173,179,175,159,139,118,100, 86, 73, 57, + 52, 51, 47, 43, 39, 45, 47, 54, 64, 71, 73, 73, 72, 71, 70, 69, 67, + 73, 77, 79, 77, 71, 62, 55, 53, 48, 47, 52, 54, 54, 52, 47, 40, 31, + 23, 25, 28, 34, 41, 50, 55, 59, 59, 57, 52, 47, 46, 48, 51, 54, 56, + 56, 53, 46, 53, 54, 47, 33, 14, 9, 13, 13, 22, 34, 39, 37, 47, 62, + 68, 66, 61, 54, 46, 58, 67, 73, 72, 67, 59, 55, 55, 51, 40, 45, 57, + 69, 79, 85, 88, 85, 78, 66, 51, 33, 16, 3, 0, 0, 0, 0, 5, 9, + 27, 43, 51, 53, 47, 36, 33, 29, 51, 67, 77, 82, 81, 76, 67, 58, 50, + 44, 46, 47, 48, 46, 40, 33, 26, 22, 28, 32, 33, 31, 25, 20, 22, 27, + 34, 51, 63, 71, 73, 72, 74, 78, 79, 78, 74, 70, 66, 60, 48, 39, 33, + 32, 34, 31, 22, 22, 27, 27, 27, 32, 32, 29, 33, 40, 39, 36, 33, 32, + 28, 22, 15, 6, 2, 5, 8, 12, 18, 23, 34, 45, 51, 52, 50, 61, 70, + 72, 68, 60, 51, 38, 25, 9, 5, 21, 27, 36, 41, 48, 66, 77, 82, 83, + 80, 74, 73, 70, 61, 46, 25, 16, 13, 16, 25, 28, 27, 21, 16, 27, 37, + 39, 37, 32, 26, 27, 34, 46, 60, 74, 84, 88, 90, 89, 86, 83, 81, 85, +101,117,133,147,152,149,143,154,163,171,167,156,139,121,105, 92, 80, + 66, 50, 45, 40, 36, 37, 45, 50, 53, 54, 58, 63, 65, 66, 66, 66, 66, + 69, 76, 79, 80, 79, 73, 62, 53, 47, 41, 47, 51, 51, 46, 40, 32, 22, + 12, 8, 15, 25, 29, 36, 44, 50, 53, 52, 47, 40, 34, 33, 34, 39, 44, + 47, 50, 48, 41, 40, 43, 38, 25, 8, 12, 16, 16, 18, 27, 31, 28, 40, + 56, 63, 62, 58, 51, 43, 55, 67, 74, 74, 69, 63, 57, 54, 50, 44, 47, + 59, 68, 76, 82, 84, 83, 77, 67, 52, 34, 15, 1, 0, 0, 0, 0, 2, + 8, 16, 32, 44, 50, 48, 40, 29, 23, 40, 58, 70, 76, 76, 73, 64, 55, + 46, 39, 39, 43, 45, 46, 44, 38, 33, 27, 26, 29, 31, 29, 25, 23, 26, + 32, 44, 59, 70, 76, 78, 76, 76, 82, 84, 82, 77, 71, 64, 55, 39, 36, + 41, 48, 48, 44, 33, 33, 34, 31, 22, 22, 21, 21, 29, 32, 28, 28, 26, + 22, 15, 13, 9, 4, 4, 2, 0, 0, 4, 20, 36, 50, 58, 62, 62, 62, + 74, 79, 79, 75, 69, 60, 47, 31, 12, 15, 15, 23, 31, 50, 67, 78, 83, + 84, 81, 75, 68, 65, 56, 41, 20, 7, 3, 13, 19, 20, 22, 21, 21, 34, + 41, 40, 33, 26, 21, 16, 11, 22, 40, 57, 68, 74, 77, 77, 76, 78, 81, + 83, 95,110,123,133,136,132,132,140,150,156,154,145,132,118,105, 94, + 84, 71, 55, 34, 29, 23, 27, 38, 47, 53, 55, 55, 53, 55, 58, 60, 61, + 60, 69, 74, 77, 76, 74, 68, 56, 47, 40, 41, 47, 50, 45, 37, 26, 19, + 15, 9, 7, 13, 20, 22, 27, 37, 41, 43, 40, 34, 25, 26, 25, 20, 22, + 28, 34, 39, 39, 34, 29, 32, 29, 20, 11, 11, 14, 15, 13, 19, 21, 19, + 26, 41, 51, 51, 47, 41, 34, 50, 62, 69, 70, 66, 62, 59, 57, 55, 53, + 48, 58, 65, 72, 77, 79, 78, 73, 63, 50, 32, 12, 3, 2, 0, 0, 0, + 2, 7, 12, 22, 37, 45, 48, 45, 34, 18, 29, 47, 59, 66, 66, 62, 54, + 45, 36, 29, 25, 29, 36, 39, 39, 37, 34, 29, 23, 23, 25, 23, 21, 21, + 26, 32, 51, 64, 74, 79, 80, 78, 79, 86, 88, 85, 79, 71, 61, 48, 38, + 50, 59, 63, 62, 55, 44, 44, 41, 34, 22, 11, 9, 18, 22, 21, 20, 21, + 18, 15, 16, 14, 9, 12, 9, 5, 0, 0, 0, 14, 32, 50, 62, 69, 72, + 70, 74, 83, 85, 84, 80, 74, 63, 46, 23, 6, 1, 9, 27, 52, 68, 78, + 83, 83, 80, 74, 66, 62, 54, 39, 18, 0, 0, 6, 12, 19, 22, 21, 27, + 38, 40, 36, 26, 27, 26, 20, 8, 0, 16, 34, 47, 56, 61, 63, 68, 77, + 80, 82, 91,104,115,123,124,120,121,128,134,139,137,130,121,111,101, + 92, 83, 72, 57, 38, 15, 8, 13, 26, 38, 47, 53, 55, 54, 48, 48, 52, + 54, 57, 63, 67, 68, 66, 63, 56, 44, 39, 34, 43, 47, 46, 39, 27, 27, + 26, 22, 14, 5, 7, 11, 12, 18, 27, 32, 32, 27, 19, 13, 16, 15, 12, + 6, 13, 19, 25, 27, 25, 21, 26, 25, 19, 11, 11, 8, 11, 9, 7, 12, + 11, 6, 20, 28, 31, 28, 26, 25, 40, 54, 60, 61, 59, 57, 59, 57, 58, + 57, 53, 54, 60, 65, 70, 71, 70, 66, 58, 45, 26, 12, 16, 16, 11, 0, + 0, 0, 4, 13, 16, 29, 40, 46, 46, 39, 23, 29, 34, 46, 52, 52, 46, + 38, 28, 20, 14, 9, 12, 19, 25, 28, 29, 29, 26, 21, 14, 13, 13, 12, + 14, 19, 34, 53, 66, 74, 79, 80, 77, 84, 90, 92, 88, 80, 70, 57, 41, + 54, 67, 74, 77, 74, 65, 53, 53, 47, 37, 22, 6, 4, 9, 12, 7, 12, + 12, 16, 21, 20, 15, 16, 18, 13, 7, 7, 5, 4, 5, 23, 45, 62, 74, + 79, 79, 76, 83, 87, 88, 87, 82, 73, 56, 31, 4, 0, 3, 29, 53, 68, + 76, 79, 79, 77, 72, 67, 63, 55, 40, 20, 0, 0, 0, 9, 19, 22, 22, + 27, 34, 34, 26, 29, 32, 29, 22, 9, 0, 0, 12, 26, 37, 45, 51, 64, + 74, 79, 84, 94,102,111,115,115,111,110,115,121,123,121,115,109,101, + 94, 88, 79, 70, 55, 37, 15, 0, 0, 9, 25, 38, 47, 52, 52, 47, 39, + 45, 47, 50, 54, 54, 53, 50, 45, 38, 34, 31, 38, 44, 46, 43, 33, 29, + 32, 32, 27, 18, 5, 0, 0, 0, 8, 18, 22, 21, 15, 6, 4, 12, 16, + 16, 12, 7, 8, 9, 12, 12, 18, 23, 25, 21, 14, 8, 8, 7, 5, 4, + 1, 2, 0, 0, 3, 5, 6, 7, 14, 28, 40, 47, 48, 53, 59, 60, 58, + 56, 56, 53, 47, 53, 57, 60, 62, 62, 58, 51, 38, 20, 25, 31, 31, 23, + 11, 0, 0, 1, 12, 19, 25, 36, 44, 46, 40, 36, 40, 43, 39, 34, 32, + 26, 16, 8, 2, 3, 1, 0, 0, 7, 14, 18, 19, 18, 15, 9, 2, 0, + 0, 1, 13, 33, 52, 65, 74, 78, 78, 80, 89, 95, 96, 91, 82, 69, 54, + 53, 70, 81, 87, 88, 82, 73, 60, 59, 53, 39, 22, 8, 2, 0, 0, 0, + 2, 14, 23, 27, 25, 18, 19, 19, 19, 19, 15, 14, 12, 6, 14, 38, 59, + 75, 84, 88, 86, 80, 85, 88, 88, 85, 76, 60, 34, 4, 0, 3, 28, 51, + 64, 72, 74, 73, 71, 72, 71, 68, 60, 45, 25, 2, 0, 0, 7, 18, 23, + 25, 25, 26, 23, 28, 33, 34, 31, 22, 8, 0, 0, 0, 9, 22, 33, 44, + 57, 68, 74, 87,100,110,117,118,113,107,100,105,109,111,109,105, 99, + 93, 88, 83, 76, 66, 53, 34, 14, 0, 0, 0, 8, 23, 37, 44, 45, 43, + 34, 41, 44, 41, 40, 38, 33, 29, 22, 26, 28, 36, 43, 45, 45, 39, 28, + 32, 36, 33, 26, 18, 5, 0, 0, 0, 1, 8, 13, 11, 9, 6, 3, 13, + 19, 21, 20, 15, 9, 6, 0, 9, 20, 27, 31, 29, 25, 16, 7, 8, 11, + 11, 7, 1, 0, 0, 0, 0, 0, 0, 2, 14, 26, 33, 34, 50, 57, 60, + 59, 55, 51, 47, 38, 51, 57, 58, 56, 55, 52, 45, 34, 32, 36, 40, 40, + 33, 18, 0, 0, 0, 9, 20, 26, 34, 41, 44, 39, 46, 51, 51, 46, 37, + 23, 9, 0, 2, 5, 7, 7, 5, 2, 0, 0, 3, 6, 7, 5, 1, 0, + 0, 0, 0, 7, 27, 47, 61, 70, 74, 76, 86, 95,100, 99, 92, 82, 68, + 52, 68, 82, 92, 97, 96, 89, 79, 65, 63, 55, 41, 25, 7, 0, 0, 0, + 0, 7, 21, 31, 33, 31, 23, 18, 25, 27, 27, 31, 31, 28, 21, 9, 33, + 58, 76, 87, 92, 92, 88, 83, 86, 88, 85, 77, 61, 36, 5, 0, 2, 26, + 46, 59, 64, 65, 73, 77, 78, 77, 74, 64, 50, 28, 5, 0, 0, 4, 15, + 23, 28, 29, 31, 31, 34, 38, 38, 33, 31, 22, 7, 0, 0, 3, 14, 27, + 40, 53, 65, 78, 92,106,119,128,130,127,120,112,106,104, 98, 98, 96, + 98, 97, 93, 85, 75, 65, 53, 36, 19, 5, 0, 0, 0, 9, 22, 31, 33, + 31, 36, 43, 44, 40, 34, 25, 27, 32, 32, 33, 37, 41, 44, 44, 41, 33, + 33, 37, 43, 45, 41, 32, 16, 2, 0, 0, 1, 4, 11, 14, 13, 11, 7, + 13, 20, 25, 25, 23, 19, 14, 11, 8, 19, 28, 34, 36, 33, 27, 21, 12, + 13, 18, 19, 16, 12, 5, 0, 0, 0, 0, 0, 4, 15, 22, 26, 40, 51, + 57, 58, 57, 54, 50, 47, 57, 64, 66, 65, 62, 57, 52, 48, 47, 46, 45, + 43, 34, 19, 0, 0, 0, 9, 20, 28, 33, 38, 43, 48, 55, 58, 56, 50, + 38, 23, 15, 19, 20, 19, 14, 12, 12, 9, 7, 6, 5, 5, 5, 3, 1, + 0, 0, 0, 0, 1, 19, 39, 55, 65, 72, 79, 89, 96,100, 98, 91, 79, + 64, 69, 83, 95,104,108,106, 97, 86, 73, 63, 55, 43, 26, 9, 0, 0, + 0, 5, 15, 27, 37, 41, 43, 41, 39, 40, 43, 45, 46, 45, 40, 32, 21, + 31, 55, 74, 86, 92, 93, 91, 86, 84, 86, 84, 75, 60, 34, 5, 0, 2, + 25, 43, 53, 57, 64, 76, 81, 82, 80, 75, 66, 51, 29, 6, 0, 0, 1, + 14, 25, 33, 38, 39, 40, 41, 43, 41, 45, 41, 33, 18, 0, 0, 2, 11, + 21, 37, 52, 67, 81, 96,112,127,139,143,140,134,128,122,114,107, 99, + 99,101,100, 96, 88, 79, 69, 57, 44, 29, 15, 1, 0, 0, 0, 8, 15, + 19, 28, 38, 44, 44, 39, 29, 22, 31, 37, 39, 40, 43, 44, 43, 40, 34, + 37, 45, 55, 60, 61, 56, 47, 32, 20, 18, 15, 18, 20, 20, 18, 16, 14, + 11, 18, 26, 31, 32, 31, 27, 23, 20, 19, 18, 20, 28, 32, 33, 31, 28, + 22, 12, 19, 25, 28, 27, 23, 19, 14, 7, 1, 0, 0, 9, 19, 25, 31, + 44, 53, 58, 60, 60, 60, 59, 63, 71, 75, 75, 74, 70, 65, 62, 60, 58, + 55, 47, 37, 23, 11, 4, 7, 9, 20, 28, 34, 40, 47, 54, 59, 61, 58, + 50, 36, 27, 34, 39, 39, 37, 31, 22, 13, 14, 15, 18, 20, 20, 20, 19, + 18, 16, 16, 16, 15, 9, 14, 29, 46, 59, 68, 79, 88, 93, 95, 92, 84, + 73, 73, 86, 97,110,119,122,119,109, 96, 83, 70, 56, 41, 27, 12, 13, + 14, 16, 23, 36, 46, 55, 60, 62, 61, 60, 60, 61, 61, 59, 56, 51, 43, + 32, 26, 48, 67, 79, 86, 88, 87, 84, 82, 84, 81, 73, 57, 33, 4, 0, + 2, 23, 40, 48, 51, 63, 76, 82, 82, 79, 74, 62, 46, 25, 13, 5, 0, + 0, 12, 26, 37, 44, 47, 48, 47, 47, 51, 53, 50, 40, 26, 8, 0, 0, + 7, 14, 32, 50, 66, 83, 99,115,132,145,152,152,149,145,140,133,124, +114,104,102,100, 96, 89, 81, 72, 62, 50, 36, 21, 7, 0, 0, 0, 0, + 7, 18, 27, 37, 41, 40, 34, 25, 16, 27, 36, 40, 43, 44, 43, 39, 34, + 36, 53, 64, 71, 74, 74, 68, 60, 48, 38, 33, 29, 29, 31, 31, 28, 22, + 15, 14, 23, 33, 38, 39, 38, 34, 29, 27, 26, 25, 23, 21, 21, 26, 28, + 31, 27, 19, 18, 27, 34, 37, 37, 33, 27, 19, 9, 3, 5, 7, 19, 26, + 31, 36, 48, 57, 62, 66, 68, 68, 68, 76, 81, 84, 83, 79, 76, 74, 71, + 67, 62, 54, 44, 32, 21, 23, 26, 25, 22, 25, 32, 39, 46, 54, 60, 61, + 56, 46, 32, 40, 50, 54, 54, 48, 41, 31, 20, 14, 19, 26, 32, 34, 34, + 34, 33, 32, 31, 32, 31, 27, 21, 29, 44, 56, 67, 75, 82, 86, 87, 83, + 76, 78, 88,101,113,125,136,139,132,120,106, 92, 80, 68, 54, 38, 33, + 31, 29, 33, 40, 51, 60, 68, 72, 74, 74, 74, 74, 74, 72, 69, 64, 58, + 51, 44, 34, 39, 56, 68, 75, 79, 79, 78, 79, 80, 78, 69, 54, 29, 3, + 0, 5, 22, 38, 46, 46, 57, 71, 78, 78, 74, 66, 53, 38, 27, 19, 14, + 11, 6, 11, 26, 39, 48, 53, 53, 51, 52, 55, 56, 53, 45, 32, 14, 7, + 0, 1, 7, 25, 44, 63, 81, 98,114,130,145,154,158,159,159,159,156, +145,130,115,101, 99, 94, 88, 81, 77, 71, 59, 45, 27, 11, 0, 0, 0, + 0, 2, 13, 23, 31, 36, 34, 28, 18, 7, 18, 28, 36, 38, 39, 38, 33, + 33, 53, 68, 77, 82, 83, 81, 77, 70, 61, 53, 46, 40, 39, 39, 39, 36, + 31, 25, 20, 32, 39, 44, 45, 43, 39, 40, 37, 32, 29, 27, 25, 22, 20, + 20, 26, 26, 21, 13, 25, 34, 40, 41, 39, 32, 23, 13, 7, 11, 13, 19, + 28, 36, 40, 44, 54, 62, 68, 72, 74, 74, 78, 85, 88, 89, 88, 84, 81, + 78, 74, 67, 59, 50, 41, 43, 44, 43, 39, 34, 29, 26, 31, 39, 50, 56, + 56, 52, 41, 34, 46, 56, 61, 59, 53, 44, 32, 21, 11, 18, 28, 38, 43, + 45, 45, 44, 41, 41, 43, 43, 41, 38, 34, 44, 55, 63, 70, 75, 78, 79, + 80, 81, 87,100,113,127,140,150,152,143,129,114,101, 89, 78, 65, 53, + 53, 51, 45, 47, 53, 60, 68, 74, 79, 80, 81, 82, 83, 81, 78, 74, 69, + 63, 57, 53, 46, 37, 43, 54, 62, 69, 74, 75, 77, 76, 74, 65, 50, 27, + 2, 1, 12, 21, 37, 44, 44, 45, 60, 67, 67, 62, 52, 44, 34, 26, 20, + 20, 20, 16, 13, 26, 39, 50, 54, 53, 50, 53, 55, 56, 54, 47, 37, 20, + 15, 4, 0, 0, 15, 36, 57, 77, 95,111,125,139,149,156,159,167,173, +173,163,147,125,107, 96, 92, 87, 87, 84, 79, 69, 55, 38, 22, 8, 3, + 0, 0, 0, 4, 14, 20, 23, 22, 19, 11, 1, 4, 14, 22, 28, 29, 36, + 39, 45, 64, 78, 85, 88, 88, 85, 81, 76, 71, 65, 60, 54, 46, 45, 44, + 41, 38, 31, 32, 37, 45, 50, 50, 47, 46, 51, 48, 44, 38, 33, 26, 23, + 22, 22, 23, 21, 19, 12, 19, 29, 37, 40, 38, 29, 20, 9, 8, 13, 18, + 20, 29, 38, 45, 47, 51, 60, 67, 72, 74, 76, 77, 85, 91, 93, 92, 89, + 85, 82, 76, 70, 67, 66, 64, 62, 60, 57, 51, 43, 37, 33, 28, 29, 38, + 45, 46, 43, 34, 33, 46, 56, 60, 58, 51, 39, 27, 15, 6, 11, 26, 39, + 47, 51, 51, 50, 48, 50, 48, 52, 53, 52, 48, 44, 53, 60, 67, 74, 79, + 83, 84, 85, 96,109,121,134,149,158,159,150,134,120,106, 95, 85, 74, + 69, 69, 67, 60, 57, 61, 67, 73, 77, 79, 81, 82, 84, 85, 84, 80, 75, + 71, 66, 65, 61, 59, 55, 48, 57, 65, 70, 72, 72, 72, 72, 68, 60, 46, + 26, 2, 6, 16, 28, 37, 44, 43, 36, 43, 50, 50, 48, 43, 36, 28, 22, + 20, 22, 27, 26, 22, 26, 38, 47, 52, 51, 48, 51, 53, 54, 53, 48, 39, + 26, 22, 11, 0, 0, 5, 25, 47, 70, 88,103,117,128,137,145,154,165, +177,181,175,158,133,111, 94, 89, 92, 93, 91, 85, 76, 63, 48, 32, 19, + 15, 11, 4, 4, 6, 7, 7, 7, 8, 6, 2, 0, 0, 0, 9, 21, 32, + 40, 46, 54, 71, 82, 88, 90, 88, 86, 84, 83, 79, 74, 71, 66, 59, 51, + 47, 45, 41, 37, 39, 43, 48, 52, 53, 51, 52, 57, 56, 54, 52, 48, 45, + 38, 29, 23, 26, 26, 20, 12, 12, 21, 29, 32, 29, 22, 12, 4, 7, 13, + 18, 21, 28, 39, 47, 53, 55, 56, 63, 68, 71, 74, 75, 82, 90, 94, 94, + 92, 88, 84, 82, 85, 85, 84, 79, 75, 72, 66, 57, 52, 51, 46, 38, 29, + 33, 34, 32, 31, 26, 26, 38, 48, 53, 51, 40, 28, 21, 13, 1, 2, 20, + 36, 46, 52, 54, 53, 57, 60, 58, 57, 59, 60, 58, 54, 52, 57, 65, 74, + 80, 84, 84, 92,102,112,123,136,149,156,156,149,134,121,108, 98, 89, + 80, 81, 81, 79, 74, 65, 68, 71, 74, 76, 77, 78, 79, 81, 83, 81, 78, + 74, 74, 76, 75, 70, 69, 68, 65, 59, 66, 68, 68, 66, 65, 64, 61, 54, + 41, 23, 5, 9, 22, 36, 45, 48, 46, 39, 28, 36, 39, 38, 33, 27, 20, + 18, 18, 25, 32, 34, 33, 32, 40, 47, 51, 48, 46, 46, 50, 51, 52, 50, + 43, 31, 28, 16, 0, 0, 0, 20, 40, 60, 81, 96,107,117,125,136,145, +156,171,181,177,161,136,113, 94, 90, 96, 98, 96, 90, 80, 68, 54, 39, + 28, 27, 23, 18, 11, 11, 9, 7, 5, 5, 5, 3, 1, 0, 0, 6, 20, + 33, 44, 52, 59, 74, 83, 88, 88, 91, 96, 96, 93, 87, 79, 76, 72, 65, + 58, 51, 48, 46, 40, 41, 45, 47, 52, 54, 53, 53, 58, 59, 58, 58, 58, + 57, 53, 45, 34, 28, 29, 26, 19, 11, 14, 18, 21, 19, 11, 11, 15, 16, + 15, 15, 21, 25, 37, 47, 55, 59, 61, 59, 62, 65, 68, 71, 77, 88, 93, + 95, 93, 89, 91, 96,100, 99, 96, 90, 83, 78, 71, 65, 65, 63, 57, 48, + 36, 29, 31, 28, 23, 16, 14, 25, 34, 39, 37, 37, 40, 38, 28, 13, 0, + 12, 29, 43, 51, 54, 55, 63, 66, 63, 61, 65, 66, 65, 61, 55, 55, 62, + 73, 79, 82, 86, 93,101,110,120,132,142,149,147,140,130,118,107, 98, + 91, 84, 88, 90, 88, 83, 73, 73, 74, 74, 74, 72, 71, 71, 74, 76, 76, + 74, 78, 81, 83, 81, 75, 77, 79, 77, 72, 63, 63, 61, 57, 56, 55, 53, + 47, 38, 22, 13, 14, 27, 41, 52, 56, 54, 47, 37, 27, 31, 29, 25, 23, + 26, 27, 27, 25, 36, 40, 43, 41, 46, 51, 52, 48, 54, 54, 50, 51, 52, + 51, 46, 34, 32, 21, 4, 0, 0, 15, 36, 51, 74, 88, 99,108,122,136, +147,143,161,173,173,159,136,113, 96, 92, 98,100, 97, 92, 82, 69, 54, + 39, 34, 36, 34, 31, 25, 19, 12, 7, 5, 6, 7, 8, 8, 7, 6, 5, + 20, 34, 46, 57, 65, 73, 81, 86, 94,101,105,106,102, 94, 84, 74, 71, + 64, 58, 55, 53, 50, 44, 36, 40, 43, 50, 53, 55, 55, 54, 55, 55, 57, + 60, 60, 58, 53, 43, 31, 33, 31, 26, 19, 14, 15, 14, 8, 16, 23, 28, + 31, 29, 26, 21, 18, 29, 43, 54, 61, 65, 65, 63, 57, 61, 65, 73, 84, + 92, 95, 95, 92,101,108,111,109,102, 95, 86, 79, 78, 77, 75, 72, 65, + 54, 40, 25, 26, 26, 23, 20, 15, 12, 18, 23, 36, 45, 50, 47, 38, 22, + 3, 5, 25, 39, 50, 55, 57, 63, 65, 61, 65, 69, 71, 70, 66, 59, 57, + 57, 69, 75, 78, 84, 91, 97,105,113,124,133,139,139,133,123,113,103, + 96, 90, 88, 93, 96, 94, 88, 79, 79, 77, 74, 71, 67, 63, 64, 65, 68, + 71, 76, 81, 84, 85, 84, 78, 83, 85, 84, 79, 70, 56, 48, 44, 45, 44, + 43, 40, 33, 23, 21, 22, 29, 44, 54, 59, 59, 54, 45, 36, 29, 27, 28, + 31, 33, 36, 36, 36, 39, 46, 50, 51, 54, 57, 56, 58, 62, 61, 57, 56, + 58, 57, 52, 41, 32, 22, 11, 5, 3, 6, 26, 43, 67, 82, 93,102,113, +128,137,136,145,156,158,147,129,111, 98, 95,100,102, 98, 91, 80, 74, + 65, 53, 47, 43, 41, 40, 38, 33, 27, 21, 14, 7, 11, 16, 20, 19, 15, + 15, 19, 34, 50, 62, 72, 80, 87, 94,102,109,113,113,108,100, 90, 81, + 74, 68, 64, 61, 58, 54, 48, 40, 32, 31, 40, 47, 52, 55, 57, 58, 57, + 53, 57, 60, 59, 55, 47, 36, 36, 34, 31, 26, 20, 16, 15, 20, 27, 36, + 40, 43, 41, 38, 33, 29, 37, 41, 48, 58, 64, 67, 66, 62, 57, 60, 69, + 83, 92, 96, 97, 98,108,114,117,113,106, 96, 90, 88, 86, 84, 80, 75, + 66, 54, 38, 22, 23, 25, 23, 22, 19, 18, 18, 22, 36, 45, 51, 48, 40, + 26, 7, 6, 20, 36, 47, 54, 58, 60, 61, 63, 66, 70, 71, 69, 65, 58, + 58, 58, 65, 71, 73, 79, 86, 98,111,121,128,130,132,132,129,125,121, +114,104, 92, 90, 96, 99, 98, 93, 83, 82, 79, 74, 67, 62, 66, 70, 71, + 71, 74, 79, 83, 86, 87, 84, 80, 84, 87, 84, 79, 69, 55, 45, 46, 47, + 41, 32, 32, 28, 29, 27, 31, 28, 41, 53, 59, 61, 59, 53, 45, 39, 37, + 38, 39, 40, 43, 44, 44, 45, 52, 56, 58, 61, 63, 62, 64, 67, 67, 64, + 65, 69, 70, 66, 56, 41, 32, 23, 18, 11, 4, 12, 36, 61, 77, 88, 96, +102,113,123,124,129,134,134,127,114,101, 98, 99,105,105,100, 92, 86, + 81, 74, 63, 60, 55, 50, 50, 47, 43, 38, 32, 23, 14, 19, 27, 32, 33, + 29, 26, 29, 36, 51, 65, 78, 87, 95,102,109,113,115,113,109,102, 92, + 84, 78, 73, 69, 65, 61, 57, 51, 44, 36, 27, 28, 34, 43, 48, 53, 56, + 55, 51, 56, 59, 60, 57, 51, 39, 36, 37, 34, 32, 28, 27, 27, 32, 39, + 45, 48, 50, 47, 44, 39, 37, 43, 47, 50, 52, 58, 62, 63, 61, 54, 56, + 66, 80, 91, 97,101,102,111,117,119,115,109, 99, 95, 92, 89, 86, 81, + 74, 63, 48, 31, 20, 22, 23, 23, 22, 21, 19, 19, 22, 28, 39, 46, 46, + 40, 27, 11, 6, 14, 29, 41, 50, 54, 57, 58, 59, 61, 63, 63, 61, 56, + 54, 56, 57, 64, 69, 69, 74, 88,101,113,123,129,134,137,139,140,137, +133,127,114,101, 93,100,104,104, 99, 88, 82, 77, 73, 73, 78, 82, 84, + 81, 76, 79, 82, 85, 87, 88, 86, 82, 82, 83, 80, 74, 63, 60, 61, 59, + 53, 43, 32, 26, 31, 33, 34, 38, 33, 37, 48, 56, 60, 60, 57, 51, 46, + 45, 45, 46, 51, 53, 52, 50, 52, 57, 61, 65, 69, 71, 69, 68, 70, 72, + 70, 73, 78, 80, 78, 70, 58, 47, 38, 28, 19, 8, 3, 28, 53, 71, 83, + 92, 97,102,107,112,113,115,113,108, 99, 96, 98,107,111,109,102, 95, + 92, 88, 79, 73, 69, 64, 58, 57, 54, 50, 44, 38, 31, 26, 28, 36, 40, + 44, 43, 37, 39, 44, 51, 67, 81, 92,101,107,111,113,112,109,103, 97, + 90, 84, 77, 73, 68, 64, 59, 54, 48, 41, 34, 28, 28, 31, 32, 36, 41, + 46, 46, 47, 54, 58, 59, 57, 51, 40, 33, 36, 37, 36, 34, 34, 36, 40, + 46, 51, 52, 52, 48, 45, 40, 39, 45, 52, 54, 55, 54, 54, 57, 56, 51, + 51, 63, 79, 89, 97,103,107,111,117,118,115,110,102, 96, 92, 89, 84, + 78, 69, 55, 47, 38, 41, 43, 40, 33, 22, 20, 18, 18, 19, 23, 28, 36, + 39, 36, 26, 12, 5, 11, 23, 34, 43, 47, 52, 53, 50, 51, 52, 50, 46, + 43, 50, 53, 59, 66, 68, 69, 73, 86, 99,110,119,125,130,136,140,145, +145,142,134,121,106,100,105,111,111,104, 94, 83, 81, 84, 89, 95,100, +102,100, 94, 89, 83, 84, 87, 88, 87, 84, 80, 76, 74, 72, 72, 72, 71, + 68, 61, 51, 38, 26, 32, 36, 38, 41, 40, 32, 41, 50, 56, 58, 57, 53, + 50, 48, 54, 60, 63, 64, 60, 54, 56, 63, 67, 72, 75, 77, 76, 71, 73, + 74, 74, 78, 83, 86, 85, 79, 69, 59, 48, 38, 25, 12, 11, 18, 43, 63, + 76, 85, 91, 94, 96, 97, 99, 98, 95, 90, 88, 98,108,115,118,113,104, +101, 97, 92, 83, 77, 74, 70, 66, 64, 60, 54, 47, 40, 36, 38, 39, 41, + 46, 50, 51, 47, 46, 51, 54, 68, 82, 93,102,107,108,106,102, 98, 93, + 88, 83, 77, 72, 67, 62, 57, 51, 44, 38, 32, 26, 23, 26, 27, 29, 31, + 32, 33, 37, 43, 50, 55, 56, 54, 47, 37, 29, 33, 36, 37, 37, 37, 38, + 43, 47, 50, 50, 47, 44, 40, 37, 37, 44, 52, 56, 58, 57, 54, 51, 50, + 47, 45, 61, 75, 87, 96,105,112,114,114,115,113,110,103, 95, 90, 85, + 80, 73, 66, 66, 62, 60, 64, 65, 62, 55, 41, 23, 14, 13, 13, 16, 20, + 23, 28, 28, 22, 12, 3, 6, 16, 27, 33, 40, 46, 46, 39, 37, 34, 31, + 27, 38, 45, 54, 64, 68, 67, 73, 75, 83, 94,103,110,115,122,128,134, +140,143,142,134,121,109,102,112,117,117,110, 98, 92, 93, 96,102,109, +114,118,115,110,102, 95, 86, 83, 84, 84, 83, 81, 80, 79, 79, 78, 77, + 74, 71, 62, 52, 40, 28, 31, 36, 39, 41, 43, 39, 33, 40, 47, 52, 53, + 51, 50, 58, 65, 70, 73, 71, 66, 57, 60, 69, 74, 76, 80, 83, 81, 76, + 74, 77, 78, 79, 84, 88, 88, 84, 74, 66, 56, 44, 31, 16, 15, 14, 28, + 51, 67, 77, 83, 85, 86, 86, 87, 88, 87, 89,100,109,117,122,123,115, +108,106,102, 95, 84, 79, 75, 74, 74, 70, 64, 59, 55, 48, 41, 47, 52, + 53, 51, 52, 54, 53, 51, 56, 59, 68, 82, 92, 99,102,100, 95, 89, 84, + 78, 74, 69, 65, 60, 55, 50, 43, 34, 27, 20, 15, 12, 14, 18, 20, 22, + 25, 26, 27, 31, 37, 44, 48, 50, 47, 40, 31, 23, 28, 31, 32, 32, 32, + 33, 38, 41, 43, 40, 38, 34, 31, 29, 29, 39, 50, 56, 59, 58, 55, 51, + 47, 43, 43, 60, 75, 86, 95,105,114,120,121,117,111,108,102, 96, 88, + 80, 74, 74, 78, 78, 75, 78, 80, 80, 77, 71, 58, 39, 16, 7, 7, 8, + 11, 13, 16, 20, 18, 11, 0, 1, 11, 19, 25, 33, 38, 39, 31, 20, 16, + 13, 25, 34, 48, 61, 68, 69, 70, 76, 79, 79, 87, 94, 99,104,110,117, +123,129,134,133,128,115,109,110,119,123,121,113,101,100,102,106,112, +118,124,128,127,120,112,102, 92, 81, 78, 79, 79, 79, 79, 80, 80, 79, + 77, 73, 66, 57, 47, 37, 27, 27, 32, 36, 37, 43, 41, 37, 31, 37, 41, + 44, 48, 55, 64, 71, 76, 77, 75, 70, 60, 67, 75, 79, 79, 84, 87, 86, + 81, 77, 79, 81, 80, 83, 86, 87, 83, 75, 67, 58, 47, 33, 19, 15, 13, + 11, 34, 53, 66, 73, 75, 74, 73, 75, 79, 87, 99,110,118,123,127,125, +117,114,113,107, 97, 85, 78, 79, 81, 79, 75, 69, 66, 63, 56, 48, 57, + 63, 66, 65, 60, 54, 55, 54, 60, 64, 67, 79, 88, 94, 94, 88, 81, 74, + 71, 62, 53, 50, 46, 43, 37, 29, 21, 16, 12, 7, 3, 2, 3, 5, 9, + 13, 15, 16, 18, 21, 27, 34, 38, 39, 37, 29, 20, 16, 21, 23, 23, 22, + 21, 21, 25, 28, 28, 26, 23, 20, 22, 21, 21, 31, 44, 53, 57, 56, 53, + 46, 41, 34, 47, 67, 82, 92, 99,103,114,121,123,119,112,104,101, 95, + 88, 76, 75, 83, 88, 89, 87, 89, 92, 91, 88, 81, 70, 53, 28, 4, 6, + 9, 6, 6, 6, 11, 12, 7, 0, 0, 6, 13, 15, 22, 28, 28, 20, 8, + 2, 13, 28, 43, 56, 65, 70, 70, 74, 80, 83, 82, 79, 84, 88, 96,102, +103,110,115,120,120,115,112,109,120,128,129,124,113,104,104,106,110, +114,121,127,130,129,123,114,105, 95, 84, 71, 70, 71, 73, 75, 76, 76, + 74, 71, 64, 56, 46, 37, 29, 23, 22, 25, 29, 27, 37, 40, 39, 34, 26, + 29, 39, 47, 55, 65, 73, 78, 79, 78, 72, 62, 74, 80, 84, 84, 88, 90, + 89, 84, 82, 81, 84, 84, 82, 80, 81, 77, 71, 66, 61, 53, 39, 22, 12, + 8, 6, 14, 36, 51, 59, 62, 60, 57, 63, 78, 93,106,115,122,125,127, +124,122,123,120,112,100, 87, 76, 83, 85, 84, 79, 73, 69, 67, 61, 55, + 64, 72, 76, 75, 70, 60, 53, 57, 64, 69, 71, 77, 84, 87, 84, 77, 79, + 79, 74, 64, 48, 28, 23, 20, 16, 19, 18, 15, 9, 5, 4, 7, 9, 8, + 6, 2, 3, 5, 5, 8, 14, 21, 25, 26, 23, 16, 7, 8, 12, 13, 11, + 8, 5, 4, 7, 11, 11, 8, 14, 20, 23, 21, 13, 23, 37, 47, 52, 51, + 45, 38, 31, 29, 54, 74, 88, 97,103,106,112,120,121,118,110,101, 96, + 92, 84, 75, 85, 93, 98,101, 99, 96, 98, 97, 95, 88, 78, 62, 39, 13, + 5, 9, 7, 2, 3, 4, 6, 4, 0, 0, 3, 8, 9, 11, 15, 15, 7, + 0, 6, 19, 33, 47, 59, 66, 70, 70, 79, 84, 87, 85, 79, 73, 79, 90, + 96, 96, 97,102,106,106,109,107,120,130,136,134,125,113,103,103,109, +115,120,120,122,125,124,119,112,102, 93, 82, 70, 57, 58, 61, 65, 67, + 67, 65, 59, 51, 39, 29, 22, 23, 22, 22, 20, 19, 16, 27, 34, 37, 36, + 32, 33, 38, 45, 53, 63, 72, 78, 80, 79, 74, 63, 78, 85, 88, 89, 89, + 92, 91, 86, 88, 88, 87, 87, 84, 80, 74, 67, 69, 69, 67, 61, 53, 39, + 21, 3, 0, 0, 14, 31, 41, 45, 44, 39, 62, 81, 96,107,115,120,122, +123,128,133,134,129,119,105, 90, 75, 83, 86, 86, 83, 77, 71, 67, 61, + 63, 72, 79, 82, 81, 75, 64, 50, 61, 70, 74, 77, 77, 80, 81, 77, 80, + 82, 81, 75, 64, 46, 23, 4, 11, 14, 16, 15, 12, 6, 3, 6, 9, 12, + 13, 11, 6, 1, 0, 0, 0, 0, 5, 9, 11, 8, 2, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 9, 15, 16, 14, 6, 16, 29, 39, 43, + 40, 33, 23, 15, 37, 60, 79, 92,102,107,108,106,113,117,113,107, 99, + 90, 84, 76, 85, 95,104,111,113,112,107,100, 99, 97, 92, 83, 69, 48, + 23, 1, 6, 5, 3, 3, 2, 3, 1, 0, 0, 1, 5, 6, 4, 2, 1, + 0, 3, 13, 22, 32, 44, 55, 62, 65, 75, 84, 88, 91, 88, 82, 74, 67, + 79, 86, 89, 89, 91, 96,102,104,117,129,139,142,136,124,111, 97,105, +114,123,129,132,129,123,115,112,106, 97, 88, 78, 65, 52, 39, 44, 48, + 52, 52, 50, 43, 33, 21, 27, 29, 29, 27, 29, 29, 26, 29, 19, 25, 32, + 36, 41, 47, 53, 59, 64, 64, 70, 77, 80, 79, 74, 68, 81, 88, 92, 94, + 93, 92, 92, 94, 96, 97, 96, 93, 89, 84, 80, 80, 80, 75, 72, 69, 64, + 55, 41, 25, 4, 0, 0, 8, 19, 25, 29, 45, 67, 84, 96,105,112,113, +127,137,145,150,150,142,128,112, 96, 81, 79, 84, 85, 84, 81, 77, 73, + 70, 72, 77, 82, 84, 82, 75, 66, 61, 68, 76, 81, 84, 84, 83, 82, 81, + 82, 82, 79, 72, 59, 40, 22, 14, 8, 11, 12, 11, 9, 16, 23, 27, 25, + 21, 16, 13, 8, 6, 5, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 6, 3, 3, 12, 22, 29, + 29, 25, 15, 7, 27, 48, 69, 85, 97,107,111,112,109,106,108,108,104, + 98, 92, 85, 88, 96,107,117,124,127,124,118,110, 99, 97, 93, 85, 74, + 55, 32, 9, 3, 3, 4, 3, 1, 0, 0, 0, 4, 5, 4, 5, 4, 0, + 0, 2, 12, 22, 31, 39, 46, 53, 60, 68, 77, 85, 90, 92, 90, 84, 78, + 71, 70, 75, 80, 85, 89, 95,102,112,123,136,143,143,136,123,109,104, +106,115,125,133,137,136,132,124,118,109,100, 91, 81, 72, 61, 52, 40, + 29, 32, 33, 32, 27, 22, 23, 31, 33, 32, 31, 37, 40, 38, 41, 32, 23, + 27, 38, 48, 57, 63, 70, 73, 72, 69, 75, 79, 78, 73, 73, 84, 92, 96, + 98, 99, 99,100,102,106,107,105,102, 97, 93, 91, 92, 92, 88, 81, 74, + 71, 66, 57, 44, 26, 6, 0, 0, 9, 16, 34, 55, 74, 87, 96,103,107, +121,142,158,165,171,169,158,137,118,100, 85, 82, 81, 84, 84, 83, 80, + 77, 75, 77, 81, 84, 85, 84, 81, 77, 73, 76, 84, 89, 92, 92, 90, 87, + 84, 82, 79, 74, 65, 52, 34, 32, 26, 21, 18, 18, 19, 26, 36, 44, 46, + 45, 40, 34, 27, 21, 16, 14, 13, 9, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 7, 16, + 20, 18, 9, 1, 19, 40, 59, 78, 92,103,113,117,117,114,111,104,100, +100, 96, 93, 89, 98,107,119,129,137,139,134,125,117,105,100, 96, 88, + 76, 59, 38, 16, 1, 0, 1, 0, 0, 0, 0, 3, 9, 12, 12, 9, 6, + 4, 5, 12, 21, 29, 37, 41, 47, 52, 58, 66, 74, 82, 88, 90, 88, 84, + 79, 75, 74, 74, 80, 87, 93,100,109,118,129,139,145,143,136,123,111, +106,100,110,120,129,136,139,137,133,127,119,110,101, 92, 82, 72, 61, + 50, 36, 22, 25, 27, 26, 23, 21, 27, 28, 27, 34, 41, 46, 47, 47, 40, + 32, 25, 38, 52, 62, 70, 74, 76, 74, 73, 74, 78, 77, 74, 77, 86, 93, + 98,101,102,103,105,109,113,113,112,108,103,100, 97,100,102, 99, 93, + 84, 74, 72, 67, 58, 45, 29, 14, 3, 14, 28, 46, 64, 79, 90, 97,102, +108,129,154,171,181,186,181,167,143,122,103, 88, 87, 88, 87, 85, 83, + 81, 79, 77, 79, 83, 87, 89, 90, 88, 86, 82, 84, 92, 99,102,101, 96, + 91, 85, 80, 74, 65, 54, 39, 36, 37, 34, 31, 29, 28, 34, 44, 51, 57, + 60, 58, 54, 46, 38, 29, 22, 18, 16, 14, 8, 1, 0, 0, 0, 0, 0, + 5, 6, 4, 0, 1, 7, 11, 7, 1, 0, 0, 0, 0, 0, 0, 0, 4, + 9, 11, 6, 4, 3, 27, 50, 67, 83, 96,108,115,120,120,119,113,106, + 96, 95, 94, 93, 95,105,114,127,137,145,147,140,130,120,109,102, 97, + 89, 77, 61, 41, 21, 6, 0, 0, 0, 0, 0, 0, 7, 14, 18, 16, 15, + 12, 11, 12, 18, 26, 32, 38, 41, 44, 47, 52, 59, 68, 76, 81, 84, 84, + 83, 79, 78, 78, 78, 79, 88, 96,104,113,121,129,137,140,139,132,122, +112,104, 99,100,109,119,128,133,137,136,132,125,118,109, 99, 88, 78, + 67, 54, 39, 25, 26, 27, 27, 25, 21, 20, 21, 27, 34, 41, 48, 51, 47, + 43, 37, 31, 38, 51, 63, 71, 75, 75, 74, 71, 76, 79, 77, 78, 81, 86, + 92, 96,100,102,103,106,111,114,115,113,110,105,102,102,104,109,108, +104, 96, 85, 74, 72, 67, 58, 48, 38, 28, 27, 41, 55, 70, 82, 91, 96, +100,110,130,156,173,183,188,183,169,145,123,104, 91, 92, 93, 94, 92, + 88, 81, 77, 76, 78, 83, 88, 92, 94, 95, 93, 90, 92,102,108,111,109, +102, 94, 84, 75, 65, 52, 37, 23, 32, 37, 39, 37, 36, 40, 47, 54, 59, + 63, 66, 65, 60, 53, 41, 32, 22, 18, 16, 15, 11, 3, 0, 0, 0, 0, + 5, 12, 13, 9, 3, 6, 13, 15, 9, 2, 0, 0, 0, 0, 0, 0, 0, + 1, 4, 7, 11, 9, 6, 32, 53, 70, 85, 97,108,115,119,120,119,114, +106, 95, 89, 90, 90, 96,106,115,128,139,145,147,140,129,119,109,106, +100, 90, 78, 61, 43, 29, 16, 3, 0, 0, 0, 0, 0, 8, 16, 19, 19, + 16, 14, 13, 13, 19, 28, 37, 40, 41, 39, 38, 48, 55, 59, 66, 72, 75, + 77, 77, 78, 79, 79, 79, 79, 87, 95,104,113,119,124,128,129,129,125, +120,113,104, 95, 89, 96,105,113,121,127,129,128,125,121,113,102, 92, + 80, 68, 54, 37, 23, 27, 28, 27, 23, 20, 18, 20, 23, 29, 37, 44, 47, + 40, 41, 40, 34, 40, 52, 59, 67, 71, 70, 68, 72, 79, 80, 78, 79, 83, + 84, 88, 92, 95, 96, 98,102,107,112,112,110,106,103,101,101,105,112, +114,113,106, 96, 84, 73, 71, 66, 61, 56, 48, 41, 47, 59, 70, 80, 88, + 94, 97,108,125,145,159,171,177,173,161,140,121,104, 93, 96, 98, 99, + 97, 92, 84, 74, 72, 74, 79, 86, 92, 96, 99, 99, 96,100,110,118,120, +115,106, 95, 83, 69, 53, 36, 18, 11, 22, 32, 37, 38, 43, 50, 54, 58, + 61, 64, 67, 67, 62, 53, 41, 29, 19, 13, 13, 14, 9, 3, 0, 0, 1, + 1, 8, 15, 16, 13, 6, 9, 14, 14, 8, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 11, 16, 16, 16, 13, 29, 52, 68, 83, 94,102,109,113,113,113, +110,103, 92, 83, 84, 84, 90,101,110,121,132,139,139,134,125,115,113, +109,101, 91, 78, 63, 53, 40, 25, 9, 1, 0, 0, 0, 0, 7, 14, 16, + 16, 14, 11, 8, 9, 18, 29, 38, 43, 44, 41, 40, 48, 51, 55, 59, 62, + 64, 66, 70, 73, 76, 79, 79, 79, 83, 92,100,107,111,113,113,114,115, +115,113,111,105, 96, 84, 82, 90, 97,105,112,114,117,118,115,111,102, + 90, 78, 63, 47, 29, 26, 27, 27, 25, 20, 16, 14, 14, 15, 20, 26, 32, + 38, 31, 39, 40, 38, 43, 54, 60, 62, 62, 61, 66, 76, 82, 83, 80, 78, + 83, 84, 82, 84, 86, 88, 90, 93, 99,103,104,102,100, 97, 96, 98,103, +111,117,118,113,103, 91, 77, 71, 70, 68, 66, 61, 54, 48, 57, 66, 76, + 84, 89, 94,102,114,127,136,145,152,154,145,132,115,102, 93, 96,101, +102,101, 94, 84, 74, 66, 73, 77, 83, 90, 96,101,102,100,106,117,125, +127,120,108, 94, 79, 66, 58, 45, 26, 13, 11, 21, 29, 37, 46, 52, 55, + 57, 58, 60, 63, 63, 58, 48, 37, 23, 20, 16, 9, 11, 7, 2, 0, 4, + 6, 5, 11, 18, 18, 14, 8, 11, 13, 12, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 16, 26, 29, 27, 20, 22, 44, 61, 76, 86, 94, 99,102,102, +103,102, 97, 89, 79, 75, 74, 80, 90, 99,109,119,127,129,127,120,113, +114,110,102, 90, 77, 69, 59, 46, 29, 16, 8, 0, 0, 0, 0, 3, 9, + 12, 11, 7, 4, 2, 4, 14, 26, 34, 40, 43, 41, 44, 53, 56, 55, 56, + 62, 66, 68, 68, 66, 71, 75, 77, 76, 77, 84, 92, 96, 98, 98, 98, 99, +101,103,105,105,102, 96, 86, 74, 74, 81, 88, 93, 98,102,105,105,102, + 95, 84, 70, 54, 36, 27, 27, 26, 23, 18, 12, 8, 5, 4, 4, 6, 9, + 16, 22, 23, 33, 38, 38, 46, 55, 60, 61, 57, 56, 70, 80, 85, 86, 83, + 77, 79, 81, 79, 74, 75, 76, 79, 82, 88, 93, 94, 93, 92, 97,101,101, + 99,108,115,119,117,108, 95, 81, 69, 70, 71, 70, 66, 60, 51, 48, 57, + 66, 75, 83, 89, 93,101,108,113,121,127,130,128,121,110, 98, 91, 96, +101,103,102, 95, 85, 72, 63, 74, 79, 83, 88, 96,102,104,102,110,122, +130,130,122,108, 92, 75, 70, 64, 54, 36, 23, 20, 12, 19, 34, 45, 50, + 52, 52, 52, 53, 56, 56, 52, 43, 31, 23, 21, 16, 9, 8, 6, 1, 2, + 7, 11, 11, 11, 18, 18, 14, 8, 9, 11, 7, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 21, 34, 41, 43, 38, 29, 34, 51, 65, 76, 83, 88, 89, + 90, 91, 92, 88, 83, 75, 65, 62, 65, 76, 85, 96,106,114,119,119,113, +111,113,108,100, 89, 77, 70, 60, 48, 31, 25, 16, 7, 0, 0, 0, 0, + 3, 4, 3, 0, 0, 0, 0, 6, 18, 28, 36, 39, 41, 44, 53, 57, 58, + 60, 61, 63, 67, 67, 65, 63, 70, 72, 71, 69, 74, 80, 84, 84, 83, 88, + 93, 95, 95, 93, 96, 96, 92, 84, 74, 66, 68, 68, 74, 79, 84, 89, 92, + 90, 84, 74, 58, 40, 27, 27, 28, 27, 21, 12, 3, 0, 0, 0, 0, 0, + 0, 0, 9, 15, 27, 33, 41, 51, 57, 61, 60, 56, 65, 73, 81, 87, 88, + 85, 80, 74, 76, 74, 69, 62, 67, 73, 75, 76, 82, 84, 87, 92, 96, 99, + 98, 95,103,111,115,113,105, 93, 80, 66, 68, 70, 70, 66, 60, 51, 40, + 44, 56, 66, 74, 82, 88, 93, 96, 96,101,108,112,113,110,102, 93, 85, + 92, 98,102,101, 95, 85, 72, 57, 70, 78, 82, 88, 96,102,104,102,111, +122,130,130,122,107, 91, 74, 71, 66, 57, 41, 27, 23, 15, 13, 31, 41, + 46, 51, 57, 59, 56, 48, 48, 44, 36, 25, 20, 16, 12, 5, 8, 6, 1, + 2, 9, 14, 14, 9, 16, 16, 13, 7, 9, 8, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 23, 40, 50, 53, 51, 45, 38, 50, 57, 64, 71, 74, + 76, 77, 78, 79, 79, 76, 71, 63, 54, 48, 59, 71, 84, 95,104,111,113, +110,104,106,103, 96, 88, 77, 65, 56, 43, 38, 33, 26, 15, 4, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 1, 0, 11, 21, 29, 37, 41, 44, 47, 51, + 55, 60, 64, 65, 62, 61, 59, 54, 61, 63, 63, 61, 60, 65, 68, 67, 76, + 83, 88, 90, 91, 89, 86, 84, 82, 78, 70, 59, 59, 60, 60, 58, 65, 73, + 77, 77, 72, 61, 44, 32, 38, 41, 40, 36, 26, 14, 2, 0, 0, 0, 0, + 0, 5, 9, 13, 22, 28, 38, 46, 54, 58, 60, 59, 63, 72, 79, 83, 87, + 89, 88, 84, 79, 76, 74, 71, 67, 64, 69, 73, 74, 75, 79, 83, 87, 90, + 92, 90, 92, 98,104,107,104, 96, 85, 72, 63, 66, 68, 67, 64, 57, 47, + 38, 43, 54, 60, 65, 75, 84, 88, 92, 92, 88, 88, 94, 96, 96, 92, 86, + 79, 85, 92, 96, 96, 92, 83, 71, 56, 62, 72, 78, 87, 95,101,102,100, +109,119,125,125,117,103, 88, 73, 70, 66, 58, 44, 26, 23, 18, 21, 31, + 40, 50, 57, 61, 62, 59, 51, 40, 36, 28, 20, 14, 8, 5, 9, 12, 9, + 3, 0, 7, 14, 15, 12, 16, 16, 12, 7, 9, 13, 13, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 22, 40, 53, 59, 59, 55, 51, 52, 59, 62, 61, + 59, 70, 77, 79, 76, 72, 65, 62, 57, 52, 44, 56, 64, 73, 85, 96,103, +106,105,101, 96, 95, 90, 83, 74, 64, 55, 47, 44, 39, 33, 23, 12, 0, + 1, 2, 3, 5, 7, 7, 5, 6, 5, 2, 6, 18, 27, 36, 43, 47, 52, + 56, 58, 56, 61, 65, 65, 59, 48, 43, 51, 53, 52, 50, 47, 46, 48, 55, + 65, 74, 79, 84, 85, 84, 83, 82, 78, 68, 61, 53, 45, 48, 48, 46, 44, + 53, 59, 60, 58, 57, 51, 44, 47, 50, 46, 39, 27, 13, 5, 2, 0, 1, + 2, 4, 11, 15, 19, 26, 33, 41, 48, 54, 56, 58, 65, 72, 78, 84, 88, + 88, 89, 90, 88, 84, 81, 78, 74, 71, 66, 64, 68, 71, 72, 74, 78, 79, + 80, 80, 82, 87, 91, 94, 93, 89, 81, 70, 56, 60, 62, 63, 62, 59, 53, + 45, 40, 44, 43, 48, 57, 69, 78, 84, 87, 88, 84, 77, 73, 77, 79, 77, + 74, 71, 78, 84, 88, 88, 84, 76, 65, 53, 55, 64, 74, 84, 92, 97, 98, + 96,104,113,117,115,108, 96, 82, 74, 69, 65, 57, 44, 25, 21, 19, 28, + 39, 48, 56, 61, 64, 64, 60, 53, 44, 34, 26, 16, 8, 7, 8, 14, 18, + 14, 7, 2, 4, 12, 15, 11, 16, 16, 12, 6, 13, 20, 22, 15, 6, 2, + 0, 0, 1, 6, 8, 5, 1, 16, 37, 53, 61, 64, 63, 59, 57, 60, 63, + 64, 68, 71, 75, 79, 77, 72, 63, 53, 48, 45, 40, 47, 56, 61, 76, 86, + 94, 98, 98, 95, 91, 85, 80, 74, 67, 59, 53, 47, 45, 43, 38, 28, 19, + 12, 15, 15, 16, 18, 16, 14, 8, 6, 4, 0, 5, 15, 26, 36, 43, 48, + 52, 57, 58, 56, 60, 65, 66, 61, 51, 38, 38, 40, 38, 34, 31, 29, 32, + 39, 51, 61, 70, 75, 78, 79, 78, 77, 73, 62, 53, 46, 36, 32, 32, 29, + 23, 32, 39, 53, 60, 61, 57, 50, 52, 52, 47, 39, 27, 13, 11, 11, 14, + 15, 15, 12, 12, 16, 21, 26, 34, 41, 47, 52, 55, 65, 73, 78, 82, 87, + 89, 89, 87, 88, 88, 86, 83, 79, 75, 71, 66, 60, 60, 63, 66, 68, 69, + 69, 67, 70, 75, 79, 80, 80, 77, 71, 61, 48, 51, 54, 55, 55, 54, 51, + 46, 40, 36, 39, 37, 34, 48, 60, 70, 76, 79, 79, 76, 71, 64, 58, 55, + 57, 57, 62, 68, 73, 75, 75, 72, 65, 57, 50, 46, 57, 71, 81, 88, 92, + 92, 92, 98,104,106,104, 97, 87, 75, 74, 69, 63, 54, 41, 25, 15, 19, + 32, 44, 53, 58, 62, 63, 62, 59, 53, 45, 37, 27, 16, 5, 8, 11, 16, + 21, 18, 11, 3, 2, 9, 13, 12, 18, 18, 12, 3, 15, 25, 29, 25, 16, + 11, 7, 4, 11, 16, 19, 18, 9, 9, 31, 50, 61, 66, 67, 65, 62, 63, + 66, 71, 75, 79, 81, 78, 74, 69, 61, 50, 37, 36, 32, 33, 44, 51, 65, + 76, 84, 88, 88, 88, 84, 81, 75, 68, 57, 48, 45, 43, 41, 40, 37, 32, + 26, 26, 28, 29, 29, 28, 25, 19, 9, 4, 0, 0, 4, 15, 25, 34, 40, + 45, 48, 53, 54, 51, 58, 64, 66, 61, 51, 43, 38, 27, 21, 16, 12, 9, + 12, 25, 41, 55, 62, 64, 68, 69, 68, 67, 63, 52, 44, 40, 29, 15, 13, + 8, 4, 21, 40, 55, 62, 63, 61, 56, 53, 51, 46, 39, 28, 15, 20, 25, + 27, 27, 25, 20, 12, 13, 19, 21, 31, 39, 45, 47, 57, 68, 76, 80, 84, + 86, 88, 88, 85, 83, 84, 83, 80, 76, 71, 65, 60, 55, 50, 53, 56, 57, + 56, 54, 50, 59, 65, 67, 65, 61, 54, 44, 36, 38, 40, 41, 41, 41, 40, + 38, 36, 33, 32, 31, 33, 36, 38, 47, 56, 62, 66, 66, 63, 59, 54, 50, + 46, 45, 46, 50, 54, 57, 58, 57, 55, 53, 52, 48, 41, 51, 65, 77, 84, + 87, 85, 84, 90, 94, 95, 92, 87, 78, 76, 74, 67, 59, 50, 37, 22, 7, + 13, 29, 43, 52, 56, 58, 58, 57, 54, 48, 44, 37, 28, 21, 14, 13, 18, + 18, 21, 19, 12, 3, 2, 7, 11, 12, 19, 19, 14, 6, 12, 23, 31, 29, + 22, 16, 11, 11, 18, 23, 28, 29, 25, 13, 25, 44, 58, 66, 69, 67, 64, + 64, 69, 73, 78, 84, 87, 84, 77, 63, 55, 44, 31, 25, 21, 18, 27, 40, + 54, 64, 71, 75, 77, 77, 77, 75, 71, 63, 52, 36, 31, 31, 32, 32, 34, + 33, 29, 37, 39, 39, 39, 37, 31, 21, 9, 0, 0, 0, 9, 25, 36, 41, + 40, 39, 41, 44, 44, 45, 57, 64, 65, 60, 48, 44, 40, 28, 12, 0, 0, + 0, 8, 23, 40, 55, 62, 64, 60, 55, 54, 53, 47, 36, 37, 33, 23, 7, + 0, 0, 6, 26, 43, 55, 61, 64, 63, 60, 55, 48, 44, 38, 28, 28, 32, + 36, 37, 36, 31, 23, 14, 5, 12, 12, 23, 33, 40, 44, 57, 68, 76, 79, + 80, 83, 84, 83, 80, 74, 75, 75, 73, 67, 60, 54, 48, 45, 40, 36, 40, + 40, 39, 34, 34, 44, 50, 50, 44, 34, 23, 25, 26, 27, 32, 33, 29, 25, + 21, 21, 21, 23, 26, 28, 31, 33, 36, 37, 37, 41, 44, 44, 41, 39, 37, + 34, 33, 32, 32, 34, 36, 38, 46, 52, 54, 54, 51, 46, 38, 43, 59, 71, + 78, 79, 77, 75, 81, 84, 84, 81, 76, 74, 75, 72, 63, 53, 41, 29, 16, + 5, 2, 20, 36, 45, 50, 51, 50, 47, 44, 41, 40, 36, 36, 33, 25, 14, + 20, 20, 19, 16, 11, 3, 1, 5, 8, 12, 19, 21, 16, 7, 5, 18, 26, + 26, 20, 14, 8, 14, 21, 27, 33, 38, 37, 28, 21, 38, 53, 62, 67, 66, + 63, 67, 74, 75, 76, 83, 87, 87, 81, 70, 52, 36, 23, 13, 9, 4, 18, + 31, 43, 51, 57, 60, 63, 64, 66, 67, 65, 58, 46, 28, 12, 14, 19, 27, + 31, 29, 37, 43, 45, 45, 44, 40, 33, 22, 8, 0, 0, 0, 14, 31, 44, + 51, 51, 45, 36, 31, 29, 44, 56, 63, 63, 57, 45, 43, 38, 26, 9, 0, + 0, 0, 6, 21, 39, 53, 61, 62, 57, 44, 34, 32, 27, 27, 31, 27, 16, + 1, 0, 0, 13, 29, 44, 54, 60, 63, 63, 63, 59, 53, 43, 38, 44, 46, + 44, 44, 45, 40, 33, 23, 13, 3, 2, 1, 14, 26, 33, 38, 52, 64, 72, + 74, 74, 75, 75, 74, 72, 66, 61, 62, 59, 52, 50, 48, 41, 29, 27, 26, + 20, 21, 19, 14, 16, 23, 28, 25, 16, 9, 13, 21, 32, 37, 38, 37, 33, + 27, 19, 11, 5, 11, 16, 22, 26, 28, 28, 27, 25, 19, 14, 13, 13, 14, + 15, 15, 15, 15, 15, 15, 15, 29, 41, 50, 54, 53, 48, 43, 37, 44, 53, + 65, 71, 72, 67, 64, 70, 73, 73, 71, 66, 71, 72, 68, 58, 47, 40, 27, + 9, 0, 0, 7, 23, 33, 37, 38, 37, 34, 32, 32, 33, 38, 43, 43, 34, + 21, 16, 16, 13, 13, 9, 3, 0, 6, 8, 12, 19, 22, 20, 12, 5, 5, + 14, 16, 12, 6, 7, 14, 20, 28, 36, 43, 46, 41, 34, 40, 48, 58, 62, + 62, 59, 72, 79, 82, 80, 78, 84, 85, 81, 72, 57, 37, 14, 5, 0, 0, + 9, 22, 31, 37, 46, 52, 52, 50, 54, 58, 57, 51, 38, 20, 2, 3, 13, + 20, 23, 32, 41, 46, 46, 46, 45, 40, 33, 22, 9, 0, 0, 0, 14, 33, + 47, 55, 56, 51, 41, 31, 27, 43, 55, 61, 61, 54, 41, 37, 32, 20, 8, + 8, 7, 12, 11, 19, 36, 51, 58, 59, 52, 36, 15, 11, 9, 20, 25, 21, + 18, 14, 6, 5, 19, 33, 45, 53, 57, 60, 62, 63, 61, 55, 52, 53, 58, + 60, 59, 52, 51, 44, 34, 21, 11, 2, 0, 0, 4, 15, 26, 32, 41, 55, + 63, 66, 65, 65, 65, 64, 61, 56, 46, 44, 39, 46, 52, 52, 46, 34, 18, + 13, 9, 2, 0, 0, 0, 3, 5, 0, 0, 3, 19, 32, 39, 41, 40, 37, + 32, 27, 26, 21, 14, 4, 5, 12, 16, 18, 18, 15, 11, 4, 0, 0, 0, + 0, 4, 7, 7, 4, 0, 0, 3, 20, 36, 45, 48, 47, 43, 36, 37, 47, + 55, 58, 63, 63, 57, 52, 58, 61, 62, 60, 61, 66, 67, 62, 56, 57, 54, + 45, 29, 7, 0, 0, 8, 18, 22, 23, 23, 25, 21, 22, 27, 38, 46, 47, + 41, 28, 12, 8, 8, 9, 7, 3, 5, 7, 9, 11, 19, 23, 23, 16, 6, + 0, 0, 0, 0, 0, 4, 9, 16, 25, 34, 45, 51, 52, 47, 53, 56, 56, + 57, 56, 63, 76, 85, 89, 89, 84, 78, 81, 78, 71, 58, 40, 20, 1, 0, + 0, 2, 13, 19, 29, 39, 44, 43, 36, 41, 46, 47, 41, 29, 18, 4, 0, + 6, 13, 27, 39, 46, 47, 46, 45, 44, 40, 34, 25, 13, 0, 0, 0, 9, + 29, 45, 54, 57, 53, 45, 33, 41, 48, 52, 58, 58, 51, 37, 27, 23, 20, + 22, 22, 28, 34, 33, 28, 37, 46, 54, 54, 45, 27, 5, 0, 2, 13, 22, + 31, 33, 28, 21, 20, 27, 36, 45, 51, 55, 61, 61, 61, 61, 64, 66, 65, + 70, 72, 69, 61, 55, 47, 34, 26, 18, 7, 0, 0, 0, 6, 18, 26, 33, + 41, 51, 54, 60, 62, 60, 55, 51, 45, 36, 22, 33, 44, 51, 52, 46, 33, + 18, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 23, 34, 40, 40, 37, + 32, 38, 41, 41, 37, 29, 19, 7, 0, 3, 5, 5, 2, 0, 0, 0, 0, + 0, 3, 6, 8, 6, 0, 0, 0, 0, 9, 25, 36, 39, 37, 32, 26, 38, + 52, 60, 63, 61, 55, 47, 38, 46, 51, 53, 54, 54, 59, 60, 56, 62, 65, + 64, 58, 45, 23, 0, 0, 0, 4, 11, 20, 26, 28, 25, 15, 21, 32, 43, + 46, 43, 32, 16, 0, 6, 9, 9, 14, 18, 18, 13, 8, 18, 23, 26, 22, + 13, 1, 0, 0, 0, 0, 1, 12, 23, 34, 41, 45, 54, 57, 61, 66, 68, + 67, 62, 52, 66, 79, 89, 95, 96, 92, 84, 76, 74, 67, 56, 39, 26, 11, + 0, 0, 0, 3, 12, 23, 32, 36, 32, 22, 29, 34, 38, 38, 31, 18, 4, + 0, 7, 23, 38, 47, 52, 52, 48, 46, 47, 44, 38, 32, 22, 9, 0, 0, + 0, 18, 37, 48, 53, 52, 45, 36, 45, 54, 59, 58, 53, 46, 32, 16, 26, + 31, 33, 38, 46, 51, 50, 41, 50, 56, 57, 52, 39, 20, 0, 0, 0, 16, + 33, 44, 46, 43, 36, 29, 37, 39, 43, 52, 60, 65, 65, 57, 69, 74, 76, + 75, 76, 76, 73, 63, 60, 51, 36, 25, 15, 5, 0, 0, 0, 4, 6, 18, + 27, 37, 45, 54, 61, 64, 62, 58, 51, 43, 34, 28, 29, 39, 45, 45, 38, + 26, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 19, 26, 34, 38, 37, + 33, 39, 46, 50, 50, 47, 40, 31, 20, 12, 6, 4, 3, 4, 6, 9, 14, + 18, 16, 13, 13, 15, 13, 7, 1, 1, 1, 12, 19, 20, 22, 21, 16, 25, + 39, 52, 60, 64, 63, 57, 50, 44, 53, 54, 50, 52, 53, 55, 58, 62, 69, + 73, 72, 66, 54, 34, 11, 0, 0, 0, 8, 18, 23, 25, 22, 14, 20, 27, + 37, 41, 39, 28, 14, 9, 11, 16, 22, 29, 33, 33, 29, 19, 18, 22, 26, + 23, 16, 8, 2, 0, 3, 7, 12, 19, 32, 43, 52, 56, 61, 68, 74, 78, + 79, 78, 73, 71, 73, 81, 91, 96, 97, 94, 88, 80, 74, 66, 58, 50, 37, + 22, 6, 0, 0, 2, 13, 22, 28, 28, 23, 13, 21, 29, 34, 32, 23, 13, + 9, 12, 27, 41, 53, 59, 60, 58, 55, 62, 63, 58, 50, 39, 32, 21, 8, + 0, 0, 3, 22, 37, 45, 47, 44, 37, 41, 53, 60, 62, 59, 52, 40, 32, + 29, 37, 41, 51, 58, 62, 61, 55, 58, 64, 65, 60, 48, 29, 7, 0, 4, + 25, 43, 54, 57, 55, 50, 45, 45, 48, 52, 58, 64, 68, 71, 72, 76, 81, + 83, 82, 80, 79, 74, 67, 62, 51, 34, 18, 12, 9, 3, 7, 4, 11, 14, + 15, 18, 31, 41, 52, 59, 61, 60, 56, 50, 43, 36, 29, 27, 33, 37, 34, + 26, 13, 0, 0, 0, 0, 1, 2, 3, 5, 9, 18, 28, 38, 44, 44, 40, + 37, 33, 41, 47, 52, 53, 51, 45, 37, 28, 21, 16, 14, 14, 16, 21, 27, + 33, 38, 40, 39, 36, 33, 31, 29, 29, 29, 28, 23, 25, 21, 13, 1, 7, + 22, 36, 46, 55, 58, 56, 52, 45, 51, 58, 59, 56, 51, 55, 59, 64, 70, + 76, 79, 79, 73, 61, 43, 19, 0, 0, 0, 0, 7, 13, 15, 13, 9, 18, + 27, 34, 37, 34, 28, 22, 18, 20, 27, 34, 43, 47, 48, 46, 37, 29, 34, + 37, 36, 32, 26, 21, 20, 23, 28, 31, 34, 36, 46, 56, 63, 70, 77, 84, + 88, 88, 87, 84, 88, 89, 88, 88, 93, 94, 91, 84, 78, 73, 68, 62, 55, + 45, 32, 16, 18, 18, 20, 25, 29, 32, 32, 28, 20, 15, 21, 22, 19, 18, + 20, 19, 34, 47, 58, 66, 70, 69, 66, 66, 72, 73, 69, 61, 50, 38, 29, + 18, 3, 0, 0, 7, 22, 33, 39, 39, 37, 36, 48, 58, 63, 63, 59, 53, + 46, 44, 47, 54, 61, 67, 72, 72, 68, 62, 67, 69, 65, 55, 39, 18, 4, + 13, 34, 52, 62, 66, 65, 61, 57, 57, 60, 65, 71, 76, 79, 82, 82, 84, + 88, 89, 88, 84, 81, 75, 65, 58, 46, 31, 26, 26, 23, 18, 25, 19, 15, + 20, 22, 23, 23, 33, 45, 52, 53, 51, 46, 41, 36, 31, 27, 25, 25, 25, + 20, 9, 0, 0, 0, 2, 4, 6, 8, 12, 16, 25, 33, 44, 52, 56, 56, + 52, 44, 37, 40, 46, 51, 51, 50, 45, 39, 33, 27, 23, 22, 23, 26, 32, + 40, 47, 55, 59, 60, 60, 59, 58, 58, 57, 57, 54, 46, 32, 22, 13, 1, + 7, 15, 26, 36, 41, 45, 44, 41, 45, 56, 61, 62, 59, 54, 56, 62, 69, + 76, 82, 84, 83, 77, 65, 47, 26, 6, 0, 0, 0, 0, 0, 2, 1, 6, + 15, 26, 33, 37, 37, 32, 26, 23, 28, 34, 44, 53, 59, 61, 59, 52, 40, + 46, 48, 47, 44, 40, 37, 38, 43, 46, 48, 50, 48, 46, 57, 66, 76, 84, + 92, 97, 99, 97, 99,102,104,102, 95, 86, 86, 83, 77, 72, 69, 66, 63, + 57, 50, 37, 37, 37, 36, 37, 39, 40, 40, 39, 34, 26, 14, 9, 7, 11, + 20, 25, 41, 55, 63, 72, 76, 79, 77, 73, 71, 76, 78, 75, 70, 60, 46, + 33, 23, 11, 0, 0, 0, 5, 18, 27, 33, 36, 32, 41, 53, 61, 65, 64, + 61, 56, 54, 56, 61, 67, 74, 78, 80, 79, 72, 69, 71, 68, 60, 47, 28, + 20, 25, 45, 61, 71, 74, 74, 71, 67, 72, 74, 77, 82, 86, 90, 92, 91, + 92, 96, 96, 92, 87, 82, 76, 65, 51, 44, 44, 41, 41, 39, 34, 44, 33, + 25, 22, 26, 29, 31, 31, 29, 36, 37, 33, 29, 26, 22, 20, 19, 16, 13, + 11, 4, 2, 0, 0, 3, 6, 7, 8, 12, 15, 23, 33, 43, 53, 59, 63, + 63, 60, 53, 45, 43, 45, 47, 47, 46, 44, 39, 34, 31, 31, 33, 36, 39, + 41, 48, 57, 66, 72, 75, 78, 79, 79, 78, 77, 76, 73, 63, 47, 26, 13, + 14, 19, 18, 13, 20, 25, 27, 27, 38, 48, 57, 61, 61, 57, 53, 55, 63, + 72, 79, 85, 88, 85, 79, 68, 52, 32, 19, 6, 0, 0, 0, 0, 0, 0, + 1, 11, 22, 31, 36, 36, 33, 28, 28, 39, 43, 51, 60, 66, 70, 69, 63, + 54, 56, 57, 56, 54, 51, 48, 53, 58, 61, 62, 61, 59, 55, 56, 69, 79, + 91,100,107,110,108,113,118,119,113,105, 93, 79, 72, 67, 63, 61, 61, + 60, 56, 48, 48, 50, 50, 48, 47, 47, 47, 45, 43, 38, 29, 19, 7, 3, + 15, 29, 46, 59, 68, 74, 79, 83, 84, 83, 78, 73, 77, 79, 79, 75, 68, + 57, 40, 26, 16, 4, 0, 0, 0, 2, 13, 23, 31, 33, 34, 47, 57, 63, + 66, 65, 62, 60, 60, 63, 69, 75, 81, 85, 86, 82, 74, 73, 71, 65, 55, + 40, 37, 40, 54, 69, 78, 82, 81, 79, 78, 84, 87, 87, 91, 95, 98, 99, + 97,101,104,102, 97, 89, 81, 75, 65, 59, 58, 57, 56, 55, 53, 50, 59, + 52, 40, 29, 26, 29, 32, 32, 27, 18, 12, 9, 6, 4, 4, 4, 5, 4, + 2, 4, 3, 0, 0, 3, 8, 8, 9, 16, 21, 21, 23, 36, 46, 55, 62, + 66, 67, 64, 59, 53, 47, 53, 55, 56, 56, 53, 50, 46, 43, 43, 45, 50, + 54, 57, 58, 64, 74, 81, 87, 90, 92, 92, 92, 90, 88, 84, 74, 58, 36, + 19, 26, 29, 25, 14, 2, 7, 21, 32, 41, 48, 54, 57, 55, 52, 48, 52, + 62, 72, 80, 87, 88, 86, 79, 69, 55, 45, 36, 21, 9, 4, 0, 0, 0, + 0, 0, 3, 15, 25, 31, 33, 32, 29, 37, 47, 52, 55, 64, 72, 75, 74, + 70, 62, 64, 65, 63, 61, 58, 61, 65, 70, 73, 73, 73, 72, 70, 67, 75, + 83, 96,109,118,123,121,124,130,132,123,112, 98, 84, 70, 57, 53, 53, + 54, 54, 52, 55, 56, 56, 55, 54, 52, 50, 47, 45, 43, 38, 31, 21, 11, + 20, 34, 48, 60, 70, 75, 79, 83, 86, 87, 85, 81, 75, 74, 77, 79, 79, + 74, 65, 52, 33, 19, 11, 3, 5, 5, 4, 5, 13, 26, 32, 32, 39, 51, + 59, 64, 66, 64, 60, 60, 62, 69, 74, 81, 87, 90, 89, 84, 76, 74, 71, + 63, 52, 51, 54, 62, 76, 85, 89, 89, 87, 91, 97, 99, 99,100,104,106, +106,103,109,112,109,102, 92, 79, 74, 72, 72, 71, 70, 69, 70, 68, 63, + 70, 66, 58, 45, 33, 28, 28, 27, 21, 9, 0, 0, 0, 0, 0, 0, 0, + 2, 6, 7, 6, 4, 8, 18, 21, 18, 26, 32, 33, 31, 28, 32, 44, 54, + 61, 65, 67, 65, 61, 56, 52, 57, 62, 64, 64, 62, 58, 54, 51, 51, 55, + 60, 66, 70, 72, 73, 79, 88, 94, 99,102,102,101, 99, 96, 92, 81, 65, + 45, 36, 38, 38, 29, 16, 11, 11, 23, 33, 39, 44, 47, 48, 46, 48, 51, + 56, 60, 70, 79, 85, 88, 85, 79, 71, 61, 58, 50, 37, 26, 21, 15, 8, + 0, 0, 0, 0, 4, 15, 23, 28, 29, 29, 41, 53, 57, 58, 67, 74, 78, + 78, 73, 69, 71, 71, 69, 67, 70, 75, 79, 81, 83, 84, 85, 85, 84, 79, + 79, 86,102,117,129,137,137,132,140,140,130,117,102, 88, 78, 71, 59, + 52, 54, 56, 58, 59, 58, 56, 54, 52, 50, 46, 43, 40, 37, 33, 27, 18, + 19, 33, 46, 58, 67, 74, 77, 79, 82, 85, 86, 85, 81, 76, 70, 74, 77, + 79, 77, 70, 58, 41, 23, 16, 12, 19, 21, 20, 15, 8, 19, 29, 34, 34, + 44, 54, 60, 63, 61, 57, 60, 70, 76, 79, 79, 86, 92, 92, 90, 84, 79, + 77, 72, 63, 61, 64, 69, 83, 92, 96, 97, 96,102,109,112,111,109,113, +113,113,109,115,118,113,105, 93, 79, 74, 80, 81, 80, 78, 80, 81, 79, + 74, 76, 75, 71, 62, 50, 36, 32, 26, 16, 3, 0, 1, 2, 0, 0, 0, + 0, 4, 9, 12, 13, 13, 23, 31, 32, 33, 44, 51, 52, 46, 37, 31, 38, + 48, 56, 61, 63, 63, 60, 56, 52, 58, 64, 67, 68, 66, 62, 58, 54, 55, + 60, 67, 74, 78, 81, 83, 83, 93,101,106,109,109,107,103,101, 96, 85, + 71, 61, 52, 48, 45, 34, 27, 28, 26, 22, 29, 33, 33, 36, 36, 44, 53, + 60, 67, 70, 69, 76, 83, 86, 84, 80, 74, 70, 67, 59, 47, 44, 41, 37, + 28, 16, 6, 4, 2, 3, 8, 14, 22, 27, 29, 41, 53, 59, 60, 68, 74, + 78, 78, 74, 74, 77, 76, 74, 73, 78, 83, 86, 89, 92, 94, 95, 95, 93, + 88, 81, 89,107,124,142,154,154,145,143,143,133,119,104, 92, 87, 79, + 67, 59, 60, 61, 61, 59, 55, 51, 48, 46, 43, 44, 41, 36, 28, 25, 19, + 12, 22, 38, 51, 61, 68, 73, 74, 74, 78, 80, 81, 80, 78, 73, 66, 68, + 74, 77, 76, 72, 61, 45, 27, 21, 21, 32, 37, 37, 29, 21, 16, 26, 34, + 38, 38, 47, 55, 58, 56, 55, 66, 76, 83, 86, 86, 84, 90, 93, 92, 88, + 84, 84, 80, 74, 69, 72, 75, 90,100,106,108,106,113,121,123,121,120, +122,122,118,114,120,121,117,107, 94, 80, 79, 85, 87, 86, 86, 89, 90, + 88, 83, 79, 80, 78, 72, 63, 53, 40, 32, 23, 22, 25, 27, 27, 22, 15, + 7, 0, 7, 15, 21, 23, 27, 34, 40, 41, 52, 61, 66, 66, 60, 48, 38, + 31, 41, 50, 55, 57, 57, 54, 50, 46, 54, 61, 65, 66, 64, 60, 56, 52, + 53, 59, 67, 75, 81, 85, 88, 88, 99,107,113,114,113,111,109,103, 98, + 89, 83, 74, 63, 58, 52, 40, 43, 43, 37, 26, 20, 20, 19, 20, 33, 46, + 58, 69, 75, 77, 76, 74, 81, 84, 85, 83, 79, 74, 71, 64, 63, 63, 62, + 59, 52, 40, 27, 12, 8, 4, 9, 15, 18, 25, 29, 34, 48, 55, 60, 68, + 74, 77, 76, 72, 78, 80, 80, 79, 79, 80, 85, 89, 97,102,103,102,101, + 99, 94, 86, 94,113,133,154,167,167,158,142,142,133,120,106, 96, 89, + 80, 68, 66, 66, 65, 62, 57, 51, 44, 40, 47, 53, 54, 51, 44, 33, 20, + 8, 5, 21, 36, 48, 58, 64, 67, 66, 67, 69, 72, 73, 72, 69, 63, 56, + 62, 69, 73, 73, 67, 57, 41, 25, 26, 32, 44, 48, 48, 41, 31, 21, 29, + 33, 39, 41, 43, 50, 53, 51, 60, 72, 81, 88, 91, 91, 89, 87, 91, 92, + 90, 92, 92, 88, 83, 74, 76, 81, 96,109,118,121,121,120,129,132,130, +133,134,130,124,115,120,121,117,107, 95, 91, 88, 87, 88, 92, 95, 97, + 97, 94, 88, 81, 82, 81, 78, 73, 65, 57, 48, 44, 44, 46, 47, 45, 40, + 32, 21, 13, 16, 23, 31, 37, 40, 45, 51, 57, 66, 74, 78, 77, 71, 59, + 41, 33, 36, 44, 48, 50, 51, 56, 58, 55, 59, 61, 62, 61, 61, 61, 62, + 62, 62, 59, 64, 74, 81, 87, 90, 92,103,112,118,119,117,122,124,120, +111,102, 94, 84, 73, 69, 62, 51, 52, 48, 40, 25, 5, 3, 8, 22, 36, + 53, 67, 77, 82, 84, 82, 79, 79, 84, 87, 88, 86, 84, 80, 79, 79, 80, + 80, 77, 72, 62, 50, 36, 18, 11, 7, 15, 20, 22, 27, 34, 41, 51, 59, + 67, 72, 74, 72, 74, 79, 82, 84, 84, 83, 84, 88, 96,105,112,113,113, +110,105,101, 97, 96,114,136,158,171,175,167,150,136,128,119,107, 96, + 88, 79, 74, 72, 70, 66, 61, 54, 46, 38, 44, 52, 56, 57, 54, 46, 36, + 23, 12, 12, 25, 38, 50, 59, 67, 71, 71, 67, 60, 59, 59, 57, 53, 46, + 51, 57, 62, 65, 63, 57, 45, 29, 31, 32, 43, 53, 58, 57, 51, 41, 32, + 31, 34, 37, 40, 43, 48, 50, 53, 61, 73, 81, 88, 92, 92, 92, 90, 92, + 94, 97,100,100, 97, 92, 84, 79, 86,103,120,132,140,140,140,142,145, +149,150,149,142,133,120,114,115,112,104,101,100, 97, 96, 96, 98,101, +102,100, 96, 89, 83, 84, 84, 82, 78, 73, 66, 60, 57, 56, 57, 57, 55, + 50, 43, 33, 25, 25, 29, 38, 45, 52, 59, 63, 67, 74, 80, 84, 83, 77, + 65, 48, 33, 31, 38, 40, 48, 57, 63, 66, 66, 70, 71, 70, 70, 69, 69, + 69, 71, 70, 68, 66, 71, 80, 88, 93, 95,104,113,119,120,125,136,140, +136,125,114,104, 93, 84, 81, 74, 64, 56, 51, 38, 20, 0, 0, 13, 27, + 46, 63, 76, 84, 88, 89, 87, 84, 81, 84, 88, 91, 92, 92, 92, 92, 94, + 95, 93, 91, 84, 77, 66, 55, 39, 19, 9, 9, 16, 20, 21, 26, 36, 46, + 55, 61, 65, 66, 65, 73, 79, 83, 84, 84, 84, 84, 88, 97,108,115,121, +121,119,114,110,105,102,111,128,149,165,171,167,156,140,127,114,105, + 97, 89, 83, 77, 73, 69, 64, 58, 50, 40, 32, 41, 48, 53, 53, 50, 43, + 32, 20, 9, 18, 31, 45, 56, 64, 70, 72, 70, 65, 57, 50, 44, 40, 40, + 41, 45, 48, 52, 51, 47, 39, 27, 32, 36, 38, 51, 60, 64, 63, 59, 52, + 44, 39, 37, 38, 40, 46, 50, 51, 54, 63, 70, 76, 83, 88, 89, 90, 91, + 93, 98,103,107,109,107,102, 92, 80, 89,109,129,149,161,163,161,161, +163,167,167,163,154,140,124,109,108,105,103,106,106,103,101,100,100, +100, 99, 96, 91, 84, 83, 84, 84, 83, 80, 76, 72, 67, 64, 63, 62, 61, + 58, 54, 48, 41, 36, 33, 36, 47, 58, 66, 73, 75, 75, 79, 85, 88, 86, + 80, 69, 53, 33, 27, 33, 39, 50, 59, 67, 70, 73, 76, 76, 75, 74, 73, + 72, 73, 75, 75, 74, 71, 69, 79, 88, 95, 98,102,113,119,120,130,143, +152,149,137,125,113,100, 96, 92, 86, 77, 65, 52, 37, 23, 12, 2, 15, + 36, 54, 70, 81, 88, 92, 92, 90, 87, 84, 83, 89, 94, 97, 99,101,102, +105,105,103,100, 94, 86, 78, 69, 57, 41, 21, 3, 7, 13, 15, 15, 25, + 37, 46, 54, 57, 57, 62, 71, 77, 80, 81, 81, 81, 82, 86, 95,107,117, +123,127,125,122,117,112,107,103,115,132,147,158,159,154,140,125,112, +100, 95, 88, 83, 76, 70, 64, 58, 51, 43, 34, 27, 33, 40, 44, 44, 40, + 33, 23, 13, 6, 19, 34, 47, 58, 65, 69, 69, 65, 58, 50, 43, 37, 33, + 33, 37, 38, 36, 34, 31, 25, 16, 23, 33, 37, 44, 55, 62, 66, 66, 63, + 58, 54, 51, 48, 50, 51, 53, 56, 58, 60, 65, 71, 73, 74, 79, 84, 86, + 89, 94,101,108,113,117,114,109,100, 87, 93,114,140,165,179,183,179, +177,177,179,177,171,159,143,127,109,100, 99,106,110,109,106,102, 99, + 97, 95, 92, 88, 83, 82, 79, 80, 81, 81, 79, 77, 74, 70, 67, 66, 64, + 62, 59, 56, 53, 50, 46, 41, 50, 62, 73, 79, 84, 86, 86, 84, 88, 90, + 88, 82, 71, 54, 34, 25, 31, 36, 47, 58, 66, 70, 76, 79, 78, 75, 73, + 72, 72, 73, 75, 77, 78, 77, 74, 79, 88, 96,100,102,111,118,121,129, +142,152,152,143,130,117,111,109,103, 96, 88, 78, 67, 54, 40, 26, 12, + 16, 38, 56, 72, 82, 89, 92, 92, 90, 87, 83, 82, 89, 95, 99,102,105, +109,112,112,110,105, 99, 92, 85, 79, 71, 60, 44, 25, 9, 12, 14, 15, + 16, 25, 37, 44, 47, 47, 55, 64, 72, 75, 76, 76, 75, 77, 86, 93,102, +113,123,128,129,127,122,118,111,105,102,113,125,136,142,142,132,120, +106, 92, 89, 84, 79, 70, 61, 53, 46, 39, 32, 26, 21, 21, 28, 32, 31, + 26, 20, 12, 4, 4, 19, 34, 48, 58, 64, 65, 62, 56, 46, 38, 29, 31, + 40, 47, 52, 52, 45, 32, 15, 1, 11, 21, 28, 32, 43, 53, 59, 63, 64, + 63, 61, 59, 57, 57, 57, 58, 60, 62, 64, 67, 69, 69, 70, 69, 70, 75, + 80, 85, 92,102,111,118,121,119,113,103, 90, 98,122,150,179,194,196, +190,186,183,181,177,171,158,140,123,105, 92,102,108,111,110,105,100, + 96, 95, 92, 89, 86, 83, 80, 74, 74, 75, 76, 76, 74, 73, 70, 73, 75, + 78, 79, 77, 74, 69, 62, 55, 51, 62, 74, 84, 91, 94, 96, 95, 90, 90, + 91, 88, 82, 70, 53, 32, 25, 29, 31, 41, 53, 61, 65, 75, 77, 75, 72, + 69, 67, 67, 69, 73, 78, 84, 84, 83, 85, 91, 95, 99,101,109,119,123, +122,130,140,143,137,127,121,123,120,113,105, 96, 88, 79, 67, 53, 37, + 18, 12, 32, 51, 67, 78, 85, 88, 89, 87, 84, 79, 83, 91, 96, 99,101, +104,108,112,112,110,105,100, 95, 90, 85, 81, 74, 63, 48, 27, 18, 16, + 15, 11, 13, 26, 34, 38, 38, 44, 55, 63, 67, 68, 68, 68, 74, 84, 92, + 98,110,121,129,132,130,130,129,122,113,102, 96,105,114,122,124,119, +109, 96, 84, 82, 77, 70, 59, 47, 37, 29, 23, 19, 15, 13, 12, 14, 16, + 15, 12, 6, 2, 0, 5, 16, 33, 47, 56, 60, 59, 53, 43, 32, 22, 29, + 41, 52, 59, 62, 59, 51, 34, 16, 13, 6, 14, 19, 27, 37, 44, 51, 54, + 57, 59, 59, 59, 59, 60, 60, 61, 63, 65, 68, 72, 75, 76, 76, 75, 72, + 74, 79, 82, 90,101,111,119,122,120,113,103, 93,104,130,163,190,204, +204,196,188,183,177,171,163,149,133,115, 99, 95,104,111,112,109,102, + 97, 97, 96, 92, 88, 84, 79, 74, 62, 63, 66, 68, 70, 71, 71, 71, 77, + 82, 87, 90, 90, 87, 80, 72, 62, 59, 74, 85, 94,100,102,102,101, 96, + 92, 92, 88, 80, 68, 51, 28, 25, 31, 33, 34, 44, 52, 61, 71, 72, 70, + 66, 71, 70, 64, 63, 68, 79, 87, 89, 88, 91, 96, 98, 96, 97,109,119, +125,125,120,125,129,127,123,129,132,128,121,113,103, 95, 86, 74, 60, + 41, 20, 2, 19, 38, 56, 69, 77, 82, 83, 81, 78, 79, 88, 96,101,102, +100, 98,102,106,107,105,102, 99, 98, 95, 91, 89, 85, 78, 66, 48, 25, + 16, 13, 6, 3, 16, 26, 29, 29, 28, 41, 51, 57, 63, 65, 65, 71, 81, + 89, 96,106,119,129,134,134,136,137,134,128,118,106, 94, 96,103,107, +104, 96, 86, 75, 73, 66, 57, 43, 27, 16, 9, 5, 4, 3, 3, 3, 3, + 3, 2, 2, 2, 1, 2, 8, 15, 32, 45, 54, 56, 52, 43, 29, 22, 28, + 36, 47, 58, 65, 67, 63, 52, 37, 34, 28, 18, 4, 6, 16, 25, 31, 36, + 40, 45, 48, 52, 55, 56, 57, 59, 60, 62, 64, 67, 72, 77, 80, 82, 82, + 80, 78, 80, 82, 88, 99,110,118,120,117,109, 99, 94,113,140,175,200, +208,206,194,192,186,169,159,149,136,122,107, 94, 99,108,113,112,107, + 99, 96, 96, 94, 90, 84, 78, 71, 65, 46, 48, 53, 58, 63, 67, 69, 70, + 77, 84, 92, 96, 97, 94, 88, 77, 66, 70, 84, 94,102,107,108,106,103, + 97, 95, 93, 88, 79, 65, 45, 25, 26, 33, 37, 36, 34, 39, 55, 64, 66, + 71, 79, 81, 79, 74, 64, 63, 79, 88, 92, 93, 95,100,102, 99, 96,109, +121,129,130,124,114,115,115,127,134,137,133,125,117,108,100, 90, 79, + 63, 43, 19, 0, 2, 20, 39, 55, 65, 72, 74, 74, 77, 84, 94,101,103, +102, 99, 93, 93, 97, 99, 99,102,108,109,105, 96, 96, 93, 88, 78, 62, + 40, 15, 8, 0, 1, 8, 19, 22, 22, 19, 31, 48, 60, 67, 71, 72, 76, + 79, 84, 91,104,119,130,139,139,137,142,142,140,132,120,106, 92, 86, + 90, 88, 82, 73, 65, 60, 53, 40, 25, 18, 14, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 11, 16, 32, 45, 52, 52, 46, 34, 21, 27, + 39, 46, 51, 61, 67, 69, 63, 53, 53, 50, 40, 25, 5, 0, 3, 9, 14, + 21, 27, 29, 34, 40, 45, 47, 50, 56, 60, 62, 62, 61, 67, 74, 79, 83, + 84, 82, 79, 81, 81, 88, 98,109,114,115,111,102, 93, 98,121,152,186, +206,212,206,192,200,192,173,147,134,123,110, 96, 93,103,111,114,112, +105, 96, 92, 92, 88, 84, 77, 68, 59, 51, 27, 31, 38, 47, 57, 64, 69, + 72, 73, 82, 90, 96, 98, 96, 89, 79, 66, 80, 92,102,109,111,110,105, +101,100, 98, 95, 88, 78, 61, 40, 16, 27, 36, 39, 40, 38, 39, 53, 61, + 73, 83, 88, 91, 88, 81, 72, 61, 78, 88, 93, 96, 96, 99,101, 98,104, +111,123,132,133,127,115,104,117,128,136,137,134,127,118,109,102, 92, + 80, 64, 44, 18, 0, 0, 1, 19, 37, 51, 59, 67, 74, 77, 89, 98,103, +104,102, 96, 92, 84, 89, 94,102,109,113,114,110,101,102,101, 95, 85, + 70, 48, 22, 1, 3, 5, 4, 14, 19, 20, 25, 28, 47, 60, 69, 74, 76, + 77, 79, 77, 92,106,122,136,145,149,143,137,140,142,137,128,115,101, + 87, 74, 74, 67, 59, 54, 51, 45, 37, 23, 25, 21, 15, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 6, 21, 36, 47, 53, 52, 44, 31, 14, + 31, 43, 51, 56, 61, 67, 67, 61, 63, 62, 57, 45, 27, 9, 0, 0, 6, + 19, 29, 34, 37, 36, 33, 31, 40, 48, 54, 58, 60, 60, 58, 55, 63, 70, + 75, 77, 77, 79, 79, 79, 88, 99,108,113,112,105, 96, 87,104,129,163, +196,212,214,206,190,198,192,173,147,124,113,100, 87, 96,106,113,115, +112,104, 94, 84, 82, 79, 73, 64, 54, 41, 32, 46, 45, 39, 38, 51, 62, + 71, 76, 79, 78, 85, 92, 95, 93, 87, 77, 78, 90,101,109,113,112,108, +107,107,104,101, 95, 87, 74, 57, 34, 23, 25, 33, 40, 43, 41, 53, 63, + 73, 82, 90, 95, 96, 93, 86, 77, 68, 75, 86, 93, 96, 98, 99,100,102, +109,115,122,129,130,124,115,113,117,128,134,136,134,137,134,125,111, + 97, 83, 67, 48, 27, 7, 0, 2, 8, 19, 38, 55, 66, 74, 79, 92,101, +105,105,102,101, 99, 92, 92, 98,105,113,118,118,113,105,107,106,100, + 89, 75, 55, 29, 18, 11, 7, 4, 9, 20, 27, 33, 38, 45, 59, 69, 76, + 80, 84, 84, 86, 94,109,124,139,150,154,152,145,134,133,132,127,117, +105, 93, 81, 73, 66, 62, 58, 53, 46, 37, 31, 32, 28, 22, 14, 5, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 13, 26, 40, 50, 54, 52, 44, 29, + 21, 28, 41, 51, 57, 61, 64, 65, 66, 67, 65, 57, 44, 23, 12, 2, 7, + 13, 26, 36, 40, 41, 40, 43, 46, 50, 54, 57, 61, 63, 66, 66, 64, 60, + 58, 63, 67, 71, 73, 75, 84, 93,102,109,111,107,100, 90, 92,109,134, +167,196,210,210,198,183,192,183,165,142,122,106, 94, 91, 99,108,114, +117,113,104, 94, 84, 73, 63, 55, 45, 33, 34, 43, 61, 61, 55, 45, 52, + 61, 74, 82, 85, 85, 81, 88, 92, 91, 85, 79, 88, 98,108,113,114,111, +106,111,109,103, 98, 91, 81, 69, 51, 37, 33, 28, 29, 37, 41, 48, 62, + 72, 79, 86, 92, 96, 97, 94, 88, 81, 76, 81, 86, 90, 95, 98,100,102, +103,109,117,123,128,129,127,123,122,124,128,133,140,149,154,154,142, +125,110, 94, 79, 63, 45, 25, 7, 14, 19, 23, 32, 52, 65, 74, 80, 93, +102,106,106,101,102,102, 96, 94,102,111,118,123,124,120,112,109,108, +103, 93, 80, 63, 44, 33, 25, 20, 16, 12, 23, 33, 40, 47, 54, 61, 68, + 77, 84, 88, 92, 95, 96,107,122,134,145,149,149,145,137,125,121,119, +113,105, 96, 86, 79, 73, 68, 62, 56, 46, 37, 39, 40, 38, 32, 25, 25, + 23, 21, 20, 19, 14, 8, 2, 2, 4, 8, 16, 28, 39, 47, 50, 47, 39, + 28, 29, 34, 41, 48, 57, 62, 65, 67, 67, 66, 62, 53, 37, 22, 9, 14, + 21, 28, 37, 44, 50, 52, 53, 54, 55, 58, 60, 63, 65, 68, 69, 69, 67, + 63, 60, 59, 61, 66, 74, 81, 89, 97,105,109,109,103, 94, 90, 95,111, +133,161,183,192,188,175,177,179,171,154,134,117,103, 92, 96,104,112, +117,117,112,103, 92, 83, 72, 60, 47, 36, 40, 50, 57, 72, 72, 66, 56, + 58, 65, 75, 85, 91, 91, 88, 87, 91, 90, 85, 88, 95,105,112,115,113, +109,107,111,107, 99, 92, 83, 72, 58, 40, 41, 40, 37, 33, 32, 37, 55, + 68, 76, 82, 86, 90, 93, 93, 91, 87, 82, 84, 89, 93, 96, 98, 99,100, +100,102,105,112,119,125,129,130,129,128,130,133,139,147,158,165,165, +156,136,119,102, 88, 72, 55, 37, 20, 21, 26, 29, 36, 47, 63, 73, 79, + 92,102,106,106,102, 99,100, 96, 96,104,114,123,129,130,127,120,111, +109,105, 97, 86, 73, 57, 46, 37, 31, 25, 20, 23, 36, 46, 55, 63, 70, + 75, 78, 84, 92, 97,102,103,102,113,123,130,134,136,137,134,127,115, +107,104,100, 95, 88, 82, 77, 73, 66, 58, 46, 43, 46, 47, 45, 40, 43, + 44, 43, 41, 41, 39, 33, 25, 14, 8, 8, 11, 16, 26, 36, 40, 41, 39, + 32, 33, 37, 41, 47, 52, 55, 61, 64, 65, 64, 60, 54, 43, 26, 18, 14, + 22, 29, 38, 46, 54, 59, 61, 60, 59, 59, 61, 62, 64, 65, 67, 68, 67, + 64, 60, 58, 59, 63, 69, 77, 85, 92,100,106,108,106, 99, 90, 92, 98, +108,127,147,161,165,159,150,163,163,152,137,122,109, 97, 92,100,107, +113,115,113,108, 99, 89, 79, 69, 56, 41, 45, 52, 59, 66, 76, 77, 73, + 63, 62, 70, 76, 87, 93, 94, 92, 90, 93, 92, 92, 95, 99,108,113,114, +112,106,106,108,102, 92, 83, 72, 58, 43, 37, 41, 44, 43, 38, 32, 40, + 58, 71, 78, 82, 84, 84, 85, 85, 84, 82, 81, 90, 95, 98,100,100,100, +100,100, 99, 99,105,112,119,124,127,129,129,130,132,137,143,152,161, +163,156,139,121,104, 89, 74, 57, 40, 26, 21, 27, 31, 36, 45, 61, 72, + 77, 90,101,106,107,102, 93, 94, 92, 95,105,117,127,134,136,133,127, +119,110,107,100, 92, 81, 69, 57, 46, 38, 32, 26, 22, 34, 48, 60, 70, + 78, 83, 85, 84, 91, 99,105,108,106,102,108,113,117,120,123,125,122, +115,106, 96, 92, 90, 86, 82, 79, 75, 69, 60, 47, 45, 51, 52, 50, 53, + 56, 57, 56, 56, 56, 54, 47, 37, 23, 12, 9, 9, 14, 22, 28, 31, 31, + 27, 31, 36, 41, 47, 51, 53, 53, 58, 61, 61, 57, 51, 41, 29, 19, 12, + 16, 23, 31, 41, 52, 59, 64, 66, 64, 61, 60, 60, 60, 63, 66, 66, 64, + 62, 58, 54, 53, 54, 60, 67, 76, 84, 92, 98,102,104,102, 96, 87, 93, + 99,102,115,128,136,136,132,140,147,142,132,120,108, 97, 88, 93,101, +107,110,110,106, 99, 91, 82, 73, 62, 47, 45, 51, 56, 63, 70, 75, 78, + 74, 67, 63, 71, 76, 86, 93, 94, 93, 94, 99, 98, 96,100,102,106,110, +111,107,102,103,102, 96, 84, 74, 62, 44, 25, 29, 38, 44, 44, 40, 36, + 45, 61, 72, 78, 79, 78, 76, 75, 74, 74, 73, 83, 92, 98,100,101,100, + 99, 97, 97, 97, 96, 96,102,109,114,120,123,124,124,127,136,136,137, +145,149,143,130,114,100, 85, 70, 53, 37, 23, 15, 22, 27, 32, 43, 59, + 70, 74, 88, 98,105,107,102, 93, 85, 85, 92,103,115,127,134,137,136, +130,124,117,109,102, 96, 88, 79, 71, 64, 57, 50, 41, 31, 28, 46, 60, + 73, 82, 88, 92, 91, 87, 96,104,107,105,100, 93, 96, 99,102,107,113, +114,113,107, 97, 86, 82, 81, 79, 79, 76, 72, 62, 50, 45, 51, 52, 56, + 61, 64, 64, 64, 63, 64, 62, 56, 44, 29, 13, 9, 12, 11, 16, 20, 20, + 18, 23, 29, 36, 43, 50, 53, 53, 51, 53, 55, 53, 46, 37, 26, 14, 9, + 9, 13, 19, 27, 39, 52, 61, 66, 67, 65, 61, 58, 57, 63, 67, 69, 68, + 65, 60, 56, 53, 51, 47, 52, 61, 70, 79, 86, 91, 96, 97, 96, 92, 84, + 90, 96, 97,102,111,115,115,115,127,129,122,113,102, 92, 84, 82, 90, + 97,102,102,100, 95, 88, 79, 70, 60, 50, 40, 45, 51, 56, 62, 69, 71, + 75, 74, 68, 61, 68, 73, 83, 90, 92, 92,102,108,107,102,102,104,102, +104,104,102, 99,101, 97, 88, 83, 77, 67, 50, 28, 22, 29, 38, 40, 37, + 43, 50, 63, 73, 76, 75, 76, 78, 76, 70, 60, 65, 81, 92, 96, 98, 98, + 96, 94, 92, 92, 93, 93, 89, 92, 98,104,110,113,114,114,128,139,140, +133,124,128,125,115,104, 91, 76, 60, 41, 26, 15, 5, 12, 19, 25, 40, + 57, 67, 71, 84, 96,103,106,102, 92, 80, 75, 87, 99,112,123,130,133, +132,129,125,120,113,106, 99, 93, 87, 81, 77, 74, 71, 64, 56, 43, 40, + 57, 72, 84, 92, 96, 96, 92, 91, 99,102,101, 96, 88, 81, 82, 86, 92, + 99,105,107,104, 96, 86, 74, 73, 74, 76, 76, 72, 64, 52, 40, 46, 53, + 60, 65, 66, 66, 65, 65, 67, 66, 59, 47, 31, 14, 15, 16, 12, 12, 12, + 9, 14, 20, 27, 34, 43, 50, 52, 51, 46, 46, 47, 43, 33, 23, 15, 5, + 4, 4, 6, 11, 19, 33, 47, 58, 65, 66, 63, 58, 54, 60, 67, 70, 70, + 68, 63, 57, 52, 48, 45, 43, 40, 50, 59, 68, 74, 80, 85, 89, 90, 88, + 84, 84, 90, 92, 88, 96, 99,100,105,112,112,105, 96, 86, 75, 65, 74, + 83, 90, 92, 92, 88, 81, 73, 63, 52, 43, 32, 34, 40, 45, 51, 56, 63, + 64, 70, 70, 66, 60, 62, 66, 79, 87, 90,103,113,120,119,113,102,105, +102, 97, 97, 96, 98, 98, 93, 84, 83, 79, 70, 55, 38, 31, 21, 28, 32, + 36, 45, 53, 65, 73, 74, 72, 78, 80, 79, 74, 64, 69, 78, 88, 92, 93, + 92, 89, 87, 84, 84, 85, 86, 84, 82, 88, 93, 98,102,104,112,127,139, +142,134,121,108,107,100, 91, 78, 63, 45, 26, 12, 4, 0, 0, 7, 20, + 39, 54, 63, 66, 79, 92,101,103,100, 91, 78, 68, 81, 94,106,115,122, +124,123,122,121,119,114,109,102, 95, 90, 86, 84, 84, 84, 79, 74, 62, + 47, 51, 68, 82, 92, 98, 99, 95, 89, 91, 95, 94, 89, 84, 78, 76, 74, + 76, 85, 94, 99, 99, 94, 84, 72, 63, 67, 72, 74, 72, 65, 54, 39, 40, + 54, 61, 64, 65, 64, 64, 63, 65, 65, 58, 46, 31, 19, 19, 18, 12, 8, + 6, 6, 16, 28, 36, 39, 41, 48, 50, 46, 40, 39, 38, 31, 19, 15, 7, + 0, 0, 0, 1, 2, 12, 28, 43, 54, 62, 64, 62, 56, 52, 62, 68, 70, + 68, 64, 57, 50, 44, 39, 37, 34, 33, 33, 41, 51, 58, 65, 73, 79, 83, + 84, 82, 78, 81, 84, 80, 82, 86, 88, 93, 97, 96, 88, 84, 79, 71, 67, + 68, 72, 79, 81, 79, 74, 64, 54, 41, 29, 21, 16, 25, 31, 36, 46, 55, + 59, 56, 63, 65, 63, 59, 55, 63, 76, 84, 99,113,127,133,133,124,113, +104,102, 93, 92, 96, 98, 97, 92, 81, 80, 77, 70, 56, 43, 34, 25, 16, + 20, 33, 44, 58, 68, 74, 74, 69, 75, 79, 79, 74, 74, 79, 81, 82, 85, + 85, 85, 85, 84, 82, 78, 73, 74, 72, 74, 78, 83, 88, 91, 92,107,121, +133,137,132,119,104, 92, 86, 77, 63, 47, 34, 21, 7, 0, 0, 0, 1, + 19, 37, 50, 58, 60, 75, 88, 96, 98, 94, 84, 71, 61, 76, 88,100,108, +113,113,112,111,113,113,111,108,104, 99, 93, 86, 86, 88, 88, 88, 83, + 74, 61, 45, 61, 77, 88, 96, 97, 94, 88, 83, 88, 88, 84, 81, 81, 79, + 74, 65, 72, 82, 89, 91, 87, 79, 66, 53, 59, 66, 70, 70, 65, 55, 41, + 39, 52, 58, 61, 65, 70, 72, 69, 62, 62, 56, 45, 29, 19, 18, 15, 7, + 8, 5, 12, 23, 36, 44, 45, 40, 46, 45, 40, 32, 32, 28, 20, 7, 5, + 0, 0, 0, 0, 3, 9, 12, 27, 40, 51, 60, 63, 61, 56, 50, 59, 64, + 64, 61, 55, 45, 36, 28, 23, 25, 26, 25, 25, 27, 31, 36, 45, 56, 66, + 74, 78, 79, 77, 72, 74, 74, 69, 74, 78, 79, 82, 79, 79, 79, 74, 67, + 70, 70, 69, 66, 68, 64, 59, 54, 46, 34, 20, 2, 5, 14, 21, 36, 47, + 56, 59, 54, 53, 56, 56, 55, 53, 65, 79, 93,109,125,140,150,149,137, +124,113,105, 98, 94, 97, 99, 97, 92, 83, 74, 72, 66, 54, 40, 34, 26, + 18, 20, 34, 50, 61, 69, 74, 74, 69, 69, 73, 74, 71, 79, 85, 88, 88, + 88, 88, 87, 85, 82, 79, 74, 68, 63, 63, 65, 68, 72, 75, 78, 87,100, +113,123,127,122,112, 99, 86, 75, 65, 55, 44, 32, 21, 12, 1, 0, 0, + 0, 15, 31, 43, 51, 57, 72, 84, 91, 92, 87, 76, 59, 57, 72, 84, 94, +100,103,103,102,110,112,111,107,105,103,101, 96, 91, 84, 88, 90, 90, + 87, 79, 68, 54, 54, 70, 82, 88, 90, 88, 83, 78, 81, 82, 80, 79, 79, + 78, 74, 68, 72, 76, 78, 80, 78, 70, 58, 45, 48, 57, 64, 66, 63, 55, + 48, 50, 53, 59, 65, 70, 74, 74, 72, 65, 58, 53, 43, 28, 15, 14, 11, + 8, 9, 12, 19, 29, 41, 50, 52, 46, 41, 39, 32, 27, 23, 18, 8, 0, + 0, 0, 0, 0, 0, 8, 15, 16, 26, 38, 45, 56, 60, 59, 54, 48, 55, + 58, 56, 51, 41, 37, 33, 25, 16, 15, 18, 19, 18, 18, 23, 29, 34, 39, + 53, 63, 71, 74, 74, 70, 64, 65, 62, 65, 71, 74, 74, 75, 75, 74, 69, + 67, 70, 70, 68, 66, 63, 61, 57, 52, 43, 31, 15, 0, 2, 11, 23, 37, + 47, 55, 57, 52, 45, 43, 46, 47, 58, 74, 89,103,120,140,158,165,161, +149,133,120,111,102, 95, 96, 97, 97, 93, 85, 71, 66, 60, 50, 34, 31, + 23, 16, 25, 37, 48, 59, 67, 71, 72, 68, 61, 64, 65, 71, 81, 88, 92, + 92, 92, 90, 87, 83, 79, 73, 69, 67, 65, 62, 58, 54, 55, 57, 68, 79, + 92,102,111,113,111,102, 91, 79, 68, 57, 47, 38, 28, 26, 21, 8, 0, + 0, 0, 11, 25, 36, 41, 54, 69, 79, 85, 84, 78, 65, 46, 53, 67, 79, + 88, 94, 96, 95, 96,102,105,103,101, 99, 99, 97, 94, 89, 84, 88, 91, + 91, 88, 81, 71, 58, 60, 61, 72, 78, 79, 76, 72, 70, 74, 76, 75, 74, + 74, 74, 70, 72, 75, 78, 78, 74, 66, 59, 50, 39, 33, 45, 54, 58, 59, + 55, 57, 58, 61, 65, 70, 74, 75, 74, 71, 64, 54, 47, 37, 22, 14, 12, + 8, 7, 8, 19, 25, 36, 50, 57, 59, 54, 45, 37, 31, 23, 15, 15, 11, + 12, 14, 12, 4, 2, 3, 9, 16, 18, 23, 32, 37, 47, 52, 52, 48, 47, + 53, 54, 48, 39, 36, 34, 28, 19, 16, 14, 11, 12, 12, 8, 11, 16, 22, + 25, 37, 51, 60, 66, 68, 67, 62, 54, 53, 55, 63, 69, 72, 73, 72, 69, + 63, 63, 65, 66, 65, 64, 62, 59, 55, 50, 40, 27, 13, 1, 6, 16, 27, + 39, 48, 54, 55, 47, 41, 34, 32, 41, 64, 82, 97,113,132,154,171,177, +171,156,136,123,113,103, 95, 92, 95, 96, 94, 88, 75, 60, 55, 46, 31, + 23, 19, 15, 25, 34, 44, 53, 60, 65, 68, 66, 59, 54, 55, 67, 79, 88, + 92, 94, 92, 88, 84, 77, 71, 70, 71, 70, 68, 63, 56, 45, 34, 44, 58, + 71, 82, 91, 97,100, 97, 91, 81, 69, 57, 46, 38, 29, 31, 32, 27, 14, + 0, 0, 0, 5, 18, 27, 36, 51, 64, 74, 79, 77, 69, 53, 33, 46, 61, + 74, 82, 87, 88, 88, 87, 92, 94, 94, 92, 92, 92, 90, 88, 84, 83, 87, + 90, 90, 88, 80, 71, 62, 63, 63, 58, 62, 63, 60, 55, 61, 66, 69, 69, + 69, 69, 70, 72, 74, 78, 79, 78, 73, 62, 47, 39, 33, 26, 29, 40, 47, + 52, 55, 60, 63, 65, 68, 71, 73, 73, 71, 65, 58, 48, 39, 28, 15, 12, + 11, 7, 5, 14, 25, 31, 43, 55, 63, 65, 60, 51, 41, 31, 29, 29, 27, + 27, 32, 33, 29, 22, 14, 13, 11, 14, 16, 20, 23, 23, 34, 39, 41, 40, + 48, 52, 50, 40, 33, 32, 28, 21, 13, 12, 9, 5, 6, 4, 2, 0, 1, + 7, 12, 20, 33, 45, 54, 59, 60, 57, 50, 41, 44, 56, 64, 69, 69, 66, + 61, 54, 53, 55, 57, 57, 58, 57, 55, 51, 44, 33, 21, 12, 11, 18, 27, + 36, 40, 46, 51, 51, 39, 33, 27, 22, 45, 69, 87,102,119,137,159,175, +179,171,154,136,122,111,105, 97, 92, 91, 93, 93, 89, 79, 63, 52, 43, + 29, 14, 11, 12, 20, 29, 44, 53, 56, 57, 61, 62, 58, 52, 43, 58, 72, + 81, 88, 90, 88, 83, 75, 66, 67, 68, 69, 70, 68, 62, 53, 39, 25, 28, + 45, 57, 68, 76, 82, 84, 83, 78, 68, 56, 43, 33, 26, 27, 32, 33, 28, + 16, 1, 0, 0, 0, 12, 21, 32, 46, 59, 69, 73, 70, 59, 41, 20, 37, + 53, 66, 74, 79, 81, 80, 79, 80, 83, 84, 84, 84, 83, 80, 78, 79, 81, + 85, 88, 88, 85, 79, 68, 64, 65, 62, 56, 44, 41, 38, 41, 51, 55, 57, + 59, 61, 63, 67, 71, 75, 78, 79, 76, 70, 59, 44, 28, 27, 23, 15, 25, + 34, 40, 51, 58, 61, 63, 65, 67, 68, 66, 62, 56, 46, 37, 28, 18, 8, + 11, 11, 7, 3, 20, 32, 38, 48, 59, 66, 69, 64, 55, 44, 43, 44, 44, + 39, 45, 50, 51, 47, 39, 27, 21, 18, 13, 13, 14, 13, 12, 20, 26, 36, + 44, 50, 50, 44, 33, 29, 27, 21, 12, 6, 4, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 13, 25, 36, 45, 50, 48, 41, 29, 33, 48, 58, 63, 63, + 58, 51, 40, 34, 37, 40, 44, 46, 47, 45, 40, 37, 33, 27, 18, 23, 32, + 40, 46, 48, 47, 43, 43, 26, 21, 16, 29, 48, 71, 88,103,119,136,158, +171,173,165,149,130,118,111,110,103,100, 96, 90, 92, 91, 84, 69, 50, + 41, 28, 12, 2, 4, 11, 31, 48, 58, 60, 58, 53, 57, 57, 55, 51, 55, + 58, 70, 78, 81, 78, 72, 61, 60, 62, 63, 64, 66, 65, 59, 48, 32, 21, + 20, 27, 39, 48, 57, 63, 66, 66, 61, 53, 39, 27, 18, 18, 25, 29, 31, + 27, 14, 0, 0, 0, 5, 9, 16, 26, 39, 53, 62, 66, 62, 51, 31, 8, + 25, 41, 55, 64, 69, 72, 72, 71, 73, 75, 76, 76, 75, 73, 71, 73, 74, + 77, 81, 84, 84, 81, 74, 65, 64, 64, 60, 52, 38, 21, 16, 28, 36, 39, + 41, 45, 50, 54, 60, 67, 72, 75, 74, 71, 64, 53, 39, 25, 19, 20, 16, + 11, 19, 26, 40, 50, 53, 54, 57, 58, 58, 55, 50, 40, 31, 22, 16, 6, + 4, 7, 9, 8, 14, 27, 39, 45, 52, 60, 67, 69, 65, 55, 53, 56, 58, + 56, 54, 59, 62, 62, 60, 54, 41, 27, 21, 14, 9, 11, 9, 14, 25, 34, + 41, 46, 48, 46, 38, 26, 26, 21, 13, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 6, 14, 25, 33, 36, 29, 19, 23, 39, 51, 56, + 54, 47, 36, 22, 11, 11, 16, 22, 27, 29, 36, 39, 38, 33, 27, 25, 32, + 39, 46, 51, 51, 47, 38, 29, 9, 6, 18, 34, 50, 70, 86,100,113,128, +145,158,161,152,137,123,112,113,113,110,112,108, 99, 91, 92, 86, 74, + 57, 41, 29, 13, 0, 0, 8, 33, 52, 62, 64, 61, 53, 52, 56, 57, 56, + 60, 59, 53, 62, 66, 62, 54, 52, 53, 54, 55, 57, 59, 59, 54, 41, 26, + 18, 14, 8, 16, 23, 32, 39, 44, 45, 43, 36, 22, 15, 11, 11, 18, 23, + 26, 22, 9, 0, 3, 8, 13, 18, 21, 21, 33, 46, 56, 59, 55, 43, 22, + 1, 9, 26, 40, 50, 56, 59, 59, 60, 62, 65, 66, 66, 63, 60, 61, 64, + 67, 71, 75, 78, 79, 76, 70, 61, 60, 60, 55, 45, 31, 14, 6, 12, 18, + 20, 22, 32, 41, 46, 50, 58, 65, 68, 67, 63, 55, 44, 32, 20, 11, 15, + 16, 12, 7, 13, 25, 34, 38, 39, 41, 43, 41, 38, 31, 22, 12, 9, 4, + 1, 0, 5, 8, 19, 26, 36, 48, 55, 56, 60, 65, 66, 62, 55, 61, 66, + 69, 68, 65, 68, 70, 70, 69, 63, 53, 36, 19, 9, 3, 4, 6, 20, 32, + 40, 44, 45, 45, 40, 29, 26, 23, 16, 5, 0, 0, 0, 5, 11, 11, 8, + 9, 8, 3, 0, 0, 3, 5, 3, 1, 4, 14, 19, 15, 13, 16, 31, 40, + 46, 43, 33, 19, 7, 2, 0, 0, 0, 9, 22, 31, 33, 32, 27, 22, 27, + 33, 40, 46, 50, 48, 41, 31, 15, 0, 0, 18, 37, 54, 68, 82, 94,105, +117,130,140,143,139,127,114,106,111,113,122,125,121,111, 98, 92, 88, + 79, 64, 46, 32, 15, 0, 0, 7, 33, 54, 64, 67, 62, 54, 46, 54, 59, + 60, 62, 61, 54, 43, 45, 41, 40, 43, 44, 45, 45, 47, 51, 52, 46, 34, + 19, 13, 7, 0, 0, 1, 8, 16, 22, 26, 25, 20, 9, 11, 8, 9, 11, + 16, 19, 15, 4, 4, 12, 18, 22, 28, 34, 34, 34, 43, 48, 53, 50, 37, + 18, 0, 0, 8, 22, 32, 39, 41, 44, 44, 47, 52, 53, 53, 51, 47, 47, + 52, 55, 60, 66, 70, 72, 71, 65, 57, 54, 54, 48, 39, 25, 9, 4, 0, + 0, 0, 11, 23, 34, 41, 43, 45, 54, 58, 57, 52, 43, 33, 22, 13, 5, + 12, 16, 15, 11, 4, 7, 15, 18, 18, 20, 21, 21, 18, 12, 3, 0, 0, + 0, 0, 0, 3, 18, 31, 37, 46, 58, 65, 66, 63, 61, 61, 57, 59, 67, + 74, 77, 78, 76, 74, 74, 74, 72, 67, 57, 41, 20, 1, 0, 0, 9, 25, + 36, 41, 43, 41, 39, 33, 27, 27, 22, 14, 6, 0, 0, 5, 16, 21, 21, + 18, 19, 19, 14, 5, 7, 11, 15, 13, 5, 0, 0, 1, 6, 13, 15, 22, + 32, 36, 31, 20, 21, 21, 15, 4, 0, 0, 1, 13, 21, 23, 22, 18, 22, + 26, 31, 38, 43, 44, 41, 33, 21, 5, 0, 0, 14, 34, 54, 70, 82, 90, + 95,105,117,125,129,127,119,109,100,110,122,134,139,134,123,108, 94, + 91, 82, 69, 53, 38, 20, 1, 0, 4, 31, 52, 63, 66, 62, 53, 43, 52, + 60, 64, 62, 57, 50, 37, 22, 29, 33, 36, 40, 47, 51, 50, 41, 43, 38, + 27, 14, 8, 3, 0, 0, 0, 0, 1, 6, 12, 14, 12, 4, 7, 5, 4, + 4, 9, 12, 9, 0, 11, 20, 27, 31, 40, 48, 50, 44, 52, 58, 58, 53, + 38, 18, 0, 0, 0, 4, 13, 19, 21, 22, 23, 26, 32, 36, 37, 37, 37, + 36, 38, 38, 44, 53, 60, 64, 65, 61, 55, 44, 45, 40, 32, 20, 7, 0, + 0, 0, 0, 4, 18, 29, 37, 40, 39, 38, 44, 43, 40, 39, 36, 27, 15, + 0, 9, 16, 19, 18, 12, 5, 0, 0, 0, 0, 2, 2, 1, 0, 0, 0, + 0, 0, 1, 5, 13, 27, 39, 44, 59, 70, 75, 77, 74, 69, 61, 52, 61, + 71, 79, 84, 86, 85, 81, 74, 73, 71, 66, 57, 40, 19, 0, 0, 0, 11, + 25, 34, 38, 37, 33, 29, 31, 32, 33, 34, 29, 20, 6, 0, 9, 21, 28, + 29, 28, 25, 22, 19, 21, 25, 26, 22, 19, 9, 0, 0, 0, 6, 14, 19, + 20, 26, 28, 23, 29, 33, 34, 28, 20, 11, 1, 0, 3, 11, 13, 16, 19, + 21, 23, 27, 33, 37, 37, 33, 25, 12, 0, 0, 2, 19, 34, 54, 71, 83, + 91, 96, 96,107,114,119,117,113,114,111,114,129,143,152,149,136,120, +105, 93, 84, 74, 62, 48, 29, 8, 0, 0, 20, 43, 56, 61, 59, 52, 43, + 50, 59, 65, 65, 60, 51, 39, 29, 28, 32, 37, 44, 50, 52, 51, 41, 38, + 36, 33, 26, 18, 9, 0, 0, 0, 0, 0, 0, 3, 7, 7, 2, 3, 2, + 0, 0, 6, 8, 9, 9, 15, 26, 34, 43, 53, 59, 61, 56, 63, 69, 70, + 66, 54, 36, 13, 0, 0, 0, 1, 0, 0, 7, 16, 21, 20, 18, 18, 27, + 38, 46, 51, 52, 48, 43, 48, 56, 60, 59, 54, 44, 36, 33, 27, 19, 8, + 3, 0, 0, 0, 7, 13, 22, 31, 36, 36, 36, 36, 38, 40, 40, 37, 31, + 19, 11, 9, 18, 22, 23, 21, 15, 9, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 8, 15, 22, 29, 37, 47, 59, 72, 80, 85, 86, 84, 78, 71, 70, + 74, 77, 85, 92, 96, 96, 92, 85, 73, 67, 62, 54, 38, 18, 1, 0, 0, + 9, 19, 27, 28, 27, 29, 37, 41, 47, 52, 51, 46, 37, 22, 8, 8, 22, + 31, 36, 37, 36, 33, 33, 36, 39, 40, 37, 29, 16, 3, 0, 0, 6, 14, + 20, 22, 23, 25, 28, 33, 38, 38, 40, 37, 28, 16, 7, 5, 12, 16, 20, + 22, 31, 38, 40, 39, 36, 31, 26, 16, 6, 0, 0, 6, 21, 34, 56, 73, + 84, 91, 94, 93,100,106,109,113,122,125,123,120,134,150,161,161,152, +136,119,105, 94, 84, 73, 58, 40, 19, 0, 0, 6, 29, 45, 54, 54, 50, + 43, 46, 57, 64, 66, 62, 54, 43, 33, 32, 36, 39, 45, 50, 51, 47, 39, + 45, 46, 44, 36, 26, 16, 7, 2, 4, 7, 6, 2, 0, 0, 2, 1, 1, + 0, 4, 9, 15, 20, 23, 25, 27, 36, 45, 55, 63, 68, 69, 69, 76, 80, + 82, 78, 68, 52, 31, 11, 4, 2, 2, 0, 0, 0, 6, 12, 13, 14, 18, + 27, 43, 54, 60, 61, 57, 48, 52, 56, 57, 57, 53, 44, 32, 29, 27, 25, + 20, 14, 8, 5, 2, 7, 14, 16, 23, 28, 29, 29, 29, 33, 36, 37, 36, + 31, 25, 26, 25, 20, 26, 28, 28, 25, 20, 14, 6, 0, 0, 0, 5, 12, + 13, 8, 18, 26, 33, 40, 46, 53, 61, 71, 81, 88, 92, 93, 90, 84, 80, + 84, 87, 87, 95,103,108,110,106, 98, 86, 70, 58, 51, 39, 22, 16, 8, + 8, 16, 23, 28, 29, 36, 45, 51, 55, 59, 62, 62, 59, 52, 40, 26, 16, + 22, 34, 41, 44, 45, 44, 43, 45, 47, 48, 45, 38, 26, 12, 2, 7, 11, + 13, 16, 19, 20, 21, 23, 31, 40, 46, 48, 46, 40, 32, 25, 21, 21, 23, + 29, 36, 43, 48, 51, 48, 45, 40, 32, 23, 12, 0, 0, 7, 20, 38, 59, + 74, 84, 88, 91, 89, 95, 99,104,118,129,137,139,134,137,152,165,169, +163,150,132,117,104, 92, 80, 66, 50, 29, 9, 0, 0, 13, 31, 43, 47, + 46, 41, 43, 55, 63, 66, 63, 56, 45, 36, 39, 41, 41, 43, 47, 47, 45, + 47, 54, 55, 52, 44, 33, 23, 14, 8, 11, 16, 16, 13, 6, 0, 0, 0, + 0, 5, 12, 20, 27, 33, 38, 40, 44, 51, 59, 66, 72, 74, 77, 82, 87, + 92, 92, 88, 79, 65, 47, 28, 22, 20, 13, 3, 0, 0, 1, 9, 18, 21, + 23, 27, 45, 57, 64, 66, 60, 50, 55, 61, 63, 60, 53, 44, 32, 33, 34, + 33, 29, 22, 15, 8, 4, 3, 9, 13, 14, 20, 22, 21, 21, 23, 27, 29, + 29, 33, 39, 41, 39, 34, 29, 33, 33, 31, 27, 22, 14, 2, 2, 2, 14, + 23, 27, 25, 34, 43, 50, 55, 60, 65, 72, 79, 88, 95, 98, 98, 94, 92, + 92, 95, 96, 96,107,115,122,123,120,111, 98, 82, 62, 51, 41, 32, 32, + 26, 21, 21, 26, 32, 40, 50, 56, 59, 61, 65, 68, 69, 67, 62, 54, 41, + 31, 32, 39, 47, 52, 52, 52, 50, 51, 53, 52, 50, 43, 32, 19, 15, 20, + 23, 25, 23, 22, 23, 28, 29, 37, 44, 50, 52, 52, 48, 44, 40, 38, 39, + 40, 44, 48, 52, 55, 56, 56, 53, 48, 40, 29, 15, 1, 0, 6, 21, 46, + 64, 77, 84, 86, 87, 88, 92, 92,106,121,134,145,152,152,147,150,161, +167,167,159,142,125,111, 96, 84, 71, 54, 37, 20, 1, 0, 0, 15, 31, + 39, 41, 39, 39, 53, 62, 66, 64, 57, 47, 40, 45, 47, 46, 45, 43, 43, + 48, 56, 61, 61, 56, 48, 38, 28, 18, 13, 14, 23, 26, 25, 18, 7, 0, + 0, 3, 11, 20, 29, 38, 44, 48, 52, 57, 63, 70, 74, 79, 81, 88, 92, + 97,101,102, 97, 89, 76, 60, 45, 43, 43, 38, 27, 13, 14, 19, 20, 21, + 26, 26, 26, 44, 57, 64, 65, 58, 50, 59, 65, 66, 62, 55, 45, 33, 38, + 41, 40, 36, 27, 18, 8, 3, 0, 2, 6, 8, 11, 13, 12, 11, 13, 16, + 21, 33, 43, 50, 52, 50, 45, 38, 37, 37, 34, 31, 26, 18, 9, 12, 14, + 21, 33, 39, 39, 50, 56, 62, 66, 70, 74, 78, 84, 92, 99,102,101,102, +103,103,105,105,109,120,130,136,136,130,121,108, 92, 74, 54, 47, 44, + 46, 41, 38, 38, 43, 47, 54, 59, 62, 63, 64, 67, 70, 72, 72, 68, 62, + 53, 45, 45, 46, 54, 59, 59, 58, 55, 55, 55, 54, 51, 45, 36, 25, 27, + 32, 34, 34, 33, 29, 33, 40, 41, 39, 44, 48, 52, 53, 52, 52, 52, 53, + 53, 54, 56, 57, 58, 59, 60, 60, 58, 54, 46, 33, 16, 2, 0, 5, 32, + 55, 70, 79, 84, 84, 83, 88, 89, 92,106,120,134,149,161,167,167,161, +152,158,161,156,143,127,112, 97, 84, 71, 55, 40, 26, 11, 0, 0, 2, + 18, 29, 34, 36, 37, 52, 62, 66, 64, 58, 47, 47, 51, 51, 50, 47, 44, + 47, 54, 61, 65, 64, 58, 50, 41, 34, 22, 14, 16, 28, 34, 34, 28, 18, + 5, 0, 5, 16, 27, 38, 45, 51, 55, 59, 65, 72, 77, 81, 84, 89, 95, +100,105,109,110,105, 96, 85, 72, 58, 61, 63, 61, 54, 41, 28, 34, 36, + 31, 26, 27, 26, 41, 54, 60, 59, 52, 54, 63, 68, 68, 62, 54, 43, 36, + 43, 46, 45, 39, 29, 16, 5, 0, 0, 0, 0, 2, 4, 5, 3, 3, 4, + 13, 25, 37, 48, 55, 56, 54, 51, 46, 39, 37, 34, 29, 25, 18, 13, 18, + 21, 28, 41, 48, 50, 60, 66, 71, 74, 75, 78, 81, 87, 93,100,102,107, +113,114,113,113,113,124,136,145,147,143,136,125,113, 98, 82, 64, 53, + 53, 55, 53, 51, 52, 55, 59, 63, 65, 66, 64, 64, 66, 69, 71, 72, 71, + 67, 59, 54, 55, 56, 63, 67, 67, 64, 65, 63, 57, 55, 53, 47, 40, 33, + 37, 40, 43, 41, 39, 36, 40, 48, 51, 50, 50, 50, 50, 51, 53, 55, 59, + 62, 63, 64, 64, 63, 62, 62, 62, 62, 62, 58, 50, 36, 15, 1, 0, 14, + 41, 62, 76, 83, 85, 84, 84, 88, 88, 91,103,117,130,145,161,175,181, +179,169,150,145,143,134,121,107, 94, 80, 67, 52, 39, 29, 18, 1, 0, + 0, 6, 19, 26, 28, 34, 51, 61, 66, 65, 58, 48, 50, 52, 52, 50, 46, + 46, 51, 56, 62, 66, 64, 57, 48, 45, 39, 27, 13, 19, 33, 41, 43, 37, + 25, 9, 0, 7, 20, 32, 41, 48, 53, 56, 61, 69, 75, 82, 86, 89, 95, +101,105,110,114,114,112,103, 92, 81, 72, 76, 80, 80, 76, 67, 53, 45, + 47, 43, 32, 25, 23, 37, 47, 53, 51, 45, 57, 65, 69, 67, 60, 51, 39, + 40, 46, 50, 48, 41, 29, 14, 6, 1, 0, 0, 0, 0, 0, 1, 0, 7, + 11, 13, 26, 38, 50, 56, 57, 55, 54, 51, 46, 39, 31, 26, 21, 15, 12, + 19, 25, 33, 47, 55, 57, 67, 73, 76, 77, 78, 79, 81, 86, 92, 99,103, +115,123,125,123,121,129,142,152,156,152,145,134,124,113,101, 88, 73, + 59, 58, 61, 59, 58, 60, 63, 66, 69, 69, 68, 66, 70, 69, 66, 68, 70, + 70, 67, 61, 60, 61, 68, 74, 76, 74, 73, 74, 73, 68, 61, 55, 52, 45, + 40, 43, 47, 48, 47, 45, 41, 45, 52, 55, 56, 59, 61, 62, 62, 60, 57, + 63, 68, 71, 71, 70, 69, 72, 70, 64, 65, 65, 62, 53, 37, 13, 0, 0, + 21, 48, 69, 81, 87, 88, 84, 85, 88, 85, 88, 99,114,130,143,156,175, +188,190,181,163,140,128,122,111, 99, 86, 74, 59, 45, 33, 27, 19, 6, + 0, 0, 0, 8, 16, 20, 32, 50, 61, 66, 66, 59, 50, 48, 50, 48, 45, + 41, 45, 48, 54, 59, 63, 60, 54, 50, 47, 41, 29, 12, 20, 36, 46, 48, + 43, 29, 13, 0, 8, 22, 34, 43, 48, 51, 54, 60, 68, 77, 84, 90, 94, + 97,102,106,112,115,118,115,109, 99, 88, 82, 88, 93, 96, 94, 87, 76, + 60, 55, 51, 40, 25, 21, 32, 40, 43, 39, 46, 58, 66, 68, 65, 60, 51, + 40, 47, 54, 55, 51, 43, 29, 13, 4, 0, 0, 0, 0, 0, 0, 0, 2, + 12, 18, 20, 25, 38, 47, 54, 54, 53, 53, 53, 51, 46, 39, 26, 18, 12, + 7, 15, 23, 37, 51, 58, 61, 71, 76, 79, 79, 79, 82, 82, 84, 91, 96, +108,123,133,136,133,130,145,158,163,159,150,139,127,118,111,101, 91, + 79, 68, 62, 63, 61, 60, 63, 67, 71, 73, 72, 70, 70, 75, 76, 74, 68, + 67, 68, 65, 61, 64, 72, 80, 84, 86, 84, 79, 80, 79, 74, 68, 61, 57, + 54, 47, 46, 50, 52, 52, 50, 46, 46, 53, 55, 57, 62, 67, 70, 71, 70, + 66, 65, 72, 75, 76, 74, 75, 78, 77, 70, 68, 68, 65, 55, 37, 12, 0, + 0, 23, 52, 73, 84, 91, 92, 88, 84, 86, 83, 83, 99,115,133,145,147, +165,181,190,183,167,145,123,108, 99, 88, 79, 70, 59, 47, 34, 22, 18, + 7, 0, 0, 0, 0, 7, 11, 31, 48, 61, 67, 67, 62, 52, 40, 41, 39, + 36, 36, 44, 50, 53, 52, 55, 53, 51, 51, 47, 40, 28, 11, 21, 38, 48, + 51, 45, 31, 13, 0, 8, 22, 33, 40, 44, 46, 48, 55, 68, 77, 84, 92, + 99,103,105,104,109,114,118,118,113,105, 96, 88, 96,103,108,108,102, + 92, 78, 63, 58, 48, 33, 19, 28, 33, 34, 29, 43, 55, 62, 65, 67, 62, + 54, 43, 52, 58, 61, 57, 47, 31, 13, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 12, 20, 25, 28, 37, 45, 51, 51, 57, 57, 53, 52, 50, 44, 33, 15, + 11, 2, 11, 20, 37, 52, 60, 62, 73, 78, 79, 79, 84, 87, 87, 82, 88, + 95,113,130,145,150,147,140,156,165,165,158,145,132,120,112,106,100, + 93, 86, 78, 70, 65, 60, 59, 62, 67, 72, 74, 75, 74, 70, 75, 78, 77, + 74, 70, 65, 62, 63, 75, 85, 92, 96, 96, 93, 88, 82, 81, 77, 72, 69, + 69, 69, 64, 54, 52, 54, 55, 54, 52, 50, 48, 50, 53, 59, 66, 71, 74, + 74, 72, 66, 74, 79, 80, 79, 79, 81, 79, 72, 73, 73, 69, 58, 39, 12, + 0, 1, 23, 53, 74, 88, 95, 98, 96, 92, 89, 86, 84, 98,113,128,137, +139,156,173,181,179,165,143,123,108, 96, 88, 79, 69, 59, 48, 37, 27, + 19, 12, 6, 0, 0, 0, 0, 8, 28, 47, 60, 66, 66, 61, 52, 40, 32, + 29, 29, 38, 45, 51, 53, 52, 48, 48, 50, 48, 45, 38, 26, 9, 22, 38, + 48, 50, 43, 27, 8, 0, 9, 22, 32, 38, 40, 41, 45, 62, 74, 81, 87, + 96,104,111,114,113,109,109,113,115,113,109,102, 96,101,110,117,118, +112,102, 88, 74, 68, 57, 40, 27, 25, 28, 28, 23, 34, 47, 56, 67, 71, + 67, 59, 50, 52, 60, 63, 61, 52, 37, 19, 3, 0, 0, 0, 0, 2, 6, + 6, 7, 8, 15, 22, 29, 38, 45, 48, 53, 58, 58, 54, 51, 50, 44, 33, + 18, 13, 3, 7, 16, 34, 50, 59, 62, 70, 76, 78, 81, 87, 90, 90, 86, + 85, 94,114,134,152,159,158,150,159,165,163,152,139,133,129,120,110, +100, 95, 91, 86, 81, 77, 74, 68, 60, 65, 71, 74, 76, 75, 73, 74, 78, + 79, 79, 76, 74, 70, 79, 88, 98,106,110,110,106,101, 94, 89, 86, 83, + 82, 84, 84, 80, 72, 59, 59, 58, 58, 59, 58, 58, 59, 59, 56, 60, 67, + 72, 74, 73, 69, 76, 81, 84, 84, 82, 82, 79, 77, 77, 76, 71, 59, 39, + 12, 0, 2, 25, 53, 75, 90,100,105,105,102, 99, 95, 90, 96,108,118, +124,129,145,161,171,171,158,139,120,105, 94, 84, 74, 63, 52, 41, 32, + 25, 20, 15, 9, 3, 0, 0, 0, 5, 25, 43, 55, 61, 60, 55, 44, 33, + 26, 23, 28, 36, 43, 48, 50, 47, 45, 45, 45, 45, 43, 37, 26, 9, 19, + 34, 44, 45, 37, 21, 3, 0, 12, 23, 32, 37, 39, 40, 46, 63, 74, 80, + 90,102,112,120,125,124,119,110,105,109,110,108,104,101,105,113,120, +122,117,107, 94, 83, 77, 65, 47, 33, 20, 23, 23, 18, 25, 39, 59, 71, + 75, 74, 67, 58, 50, 58, 62, 60, 53, 40, 22, 7, 0, 0, 0, 2, 11, + 15, 15, 14, 15, 19, 25, 32, 39, 45, 48, 50, 54, 53, 48, 50, 47, 41, + 31, 22, 19, 8, 2, 11, 28, 45, 56, 59, 65, 72, 75, 83, 88, 93, 94, + 90, 82, 92,111,130,147,156,156,154,163,163,156,143,142,139,133,124, +113,103, 97, 95, 92, 89, 87, 84, 81, 75, 67, 67, 71, 74, 74, 73, 76, + 79, 82, 84, 83, 82, 84, 92,102,113,121,125,125,121,114,107,102, 98, + 95, 96, 98, 97, 94, 86, 75, 67, 70, 73, 74, 73, 70, 68, 66, 61, 55, + 63, 70, 73, 73, 69, 77, 83, 85, 86, 84, 84, 82, 79, 79, 76, 70, 56, + 34, 7, 0, 3, 26, 53, 74, 90,102,110,113,113,109,104, 97, 90, 99, +106,111,121,134,149,158,158,147,129,113, 99, 87, 75, 63, 51, 39, 29, + 23, 19, 16, 14, 11, 5, 0, 0, 0, 2, 20, 36, 46, 51, 50, 43, 32, + 21, 15, 16, 22, 31, 37, 41, 43, 39, 37, 37, 39, 40, 39, 34, 25, 11, + 14, 29, 38, 38, 29, 14, 0, 2, 14, 23, 32, 36, 38, 40, 44, 61, 72, + 81, 94,106,117,127,132,132,127,118,110,102,102,103,103,102,107,114, +120,121,118,109, 96, 91, 84, 73, 54, 37, 22, 20, 19, 13, 15, 39, 61, + 74, 79, 78, 74, 66, 55, 54, 59, 58, 52, 39, 23, 8, 0, 0, 0, 7, + 18, 23, 25, 20, 21, 23, 27, 32, 38, 43, 46, 46, 45, 46, 48, 48, 45, + 38, 27, 27, 23, 13, 0, 3, 21, 38, 50, 54, 58, 65, 74, 82, 89, 94, + 96, 93, 87, 88,105,122,136,145,149,159,163,159,147,145,143,140,133, +123,113,104, 99, 97, 96, 93, 92, 92, 90, 86, 81, 74, 69, 69, 71, 74, + 78, 81, 84, 87, 88, 89, 94,103,113,124,134,139,139,134,127,119,113, +109,105,109,111,110,105, 97, 87, 75, 80, 85, 88, 89, 88, 86, 80, 71, + 58, 60, 68, 71, 71, 69, 77, 83, 86, 86, 85, 87, 84, 79, 78, 74, 65, + 50, 26, 1, 0, 6, 26, 51, 72, 88,102,112,119,120,117,111,103, 93, + 89, 94,100,112,122,133,140,139,130,117,102, 89, 76, 62, 47, 33, 22, + 18, 15, 16, 18, 13, 12, 7, 1, 0, 0, 0, 12, 26, 34, 38, 34, 27, + 16, 13, 5, 7, 15, 22, 28, 32, 31, 28, 26, 26, 29, 32, 33, 31, 23, + 12, 9, 25, 32, 32, 23, 8, 0, 2, 13, 22, 29, 34, 37, 39, 45, 56, + 71, 84, 96,108,119,128,133,133,128,122,114,109,104,102,101,103,107, +113,117,118,115,108,102, 98, 91, 77, 57, 39, 25, 15, 14, 7, 14, 41, + 62, 75, 81, 81, 77, 71, 61, 52, 56, 55, 48, 37, 21, 6, 1, 0, 0, + 11, 21, 28, 31, 26, 22, 23, 26, 29, 33, 38, 41, 43, 43, 45, 46, 46, + 41, 34, 28, 31, 27, 18, 5, 0, 11, 27, 40, 46, 51, 58, 68, 78, 86, + 92, 96, 95, 90, 90, 99,113,125,134,150,161,159,149,143,143,142,136, +128,123,117,110,106,102, 96, 96, 95, 96, 96, 95, 92, 88, 83, 78, 74, + 77, 79, 82, 85, 88, 90, 92, 99,109,120,130,140,145,147,142,133,127, +121,117,113,117,120,119,113,104, 93, 82, 89, 96,101,102,102, 98, 92, + 82, 70, 71, 69, 69, 68, 68, 77, 82, 85, 86, 86, 88, 87, 79, 76, 70, + 59, 41, 18, 0, 0, 8, 26, 47, 67, 84, 97,109,118,122,120,114,107, + 96, 84, 82, 90,100,109,118,122,121,113,102, 88, 75, 59, 43, 29, 25, + 20, 15, 13, 15, 16, 12, 12, 11, 5, 0, 0, 0, 6, 15, 21, 22, 18, + 11, 8, 6, 0, 0, 6, 13, 18, 20, 19, 14, 13, 14, 18, 22, 25, 25, + 20, 11, 8, 20, 28, 28, 20, 4, 0, 1, 11, 20, 29, 37, 39, 38, 45, + 57, 73, 85, 96,107,115,122,125,125,122,119,115,112,108,105,103,103, +108,112,113,114,113,112,108,103, 94, 79, 59, 41, 25, 12, 9, 3, 16, + 43, 63, 76, 81, 81, 78, 72, 62, 50, 53, 51, 44, 32, 16, 4, 3, 0, + 0, 9, 20, 28, 32, 28, 20, 18, 19, 21, 25, 29, 34, 37, 38, 41, 44, + 43, 38, 31, 26, 31, 29, 21, 8, 0, 0, 15, 27, 34, 39, 51, 60, 72, + 81, 88, 93, 93, 90, 92,101,112,123,137,150,156,150,137,140,140,140, +143,140,133,124,122,115,109,100, 96, 95, 96, 99,101,100, 96, 92, 87, + 82, 79, 80, 82, 84, 87, 89, 92, 98,108,118,127,136,140,142,139,133, +127,122,119,115,119,122,121,115,107, 96, 88, 97,105,111,112,110,105, + 98, 88, 84, 84, 81, 73, 66, 66, 75, 81, 84, 84, 87, 90, 89, 82, 74, + 66, 53, 32, 8, 3, 1, 9, 23, 43, 61, 77, 91,103,113,118,118,114, +108, 98, 87, 74, 79, 88, 96,102,105,103, 96, 86, 73, 56, 38, 27, 25, + 21, 16, 11, 8, 11, 12, 8, 13, 14, 9, 1, 0, 0, 2, 9, 12, 11, + 6, 2, 4, 0, 0, 0, 0, 5, 8, 8, 6, 2, 7, 11, 11, 12, 15, + 18, 14, 6, 5, 18, 26, 26, 18, 3, 0, 0, 6, 21, 33, 41, 45, 46, + 45, 57, 73, 84, 95,102,109,113,113,113,113,112,112,113,113,109,104, +102,109,115,120,122,120,115,111,104, 95, 80, 59, 43, 26, 9, 6, 3, + 19, 44, 63, 74, 79, 79, 74, 68, 59, 50, 51, 47, 39, 26, 11, 2, 2, + 1, 3, 6, 16, 25, 28, 26, 19, 9, 8, 11, 14, 18, 23, 26, 29, 34, + 38, 38, 34, 27, 21, 27, 27, 21, 11, 3, 4, 3, 13, 20, 29, 43, 51, + 61, 73, 82, 88, 88, 88, 90, 99,111,122,134,143,145,136,133,137,154, +163,165,156,143,143,137,127,115,107,100,100, 97,100,103,104,102, 98, + 92, 85, 81, 81, 81, 81, 83, 85, 88, 92,101,109,117,123,127,129,127, +124,120,118,115,113,114,118,117,112,103, 93, 95,103,112,115,115,113, +107, 99, 93, 97, 97, 92, 83, 68, 63, 74, 79, 83, 84, 87, 90, 89, 83, + 72, 63, 47, 28, 15, 13, 9, 9, 26, 50, 67, 79, 86, 96,106,112,113, +111,106, 99, 89, 78, 66, 74, 81, 87, 90, 88, 81, 70, 53, 33, 23, 29, + 32, 31, 25, 14, 3, 3, 4, 8, 15, 18, 15, 7, 0, 0, 0, 4, 6, + 4, 0, 0, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 2, 7, 8, 5, + 6, 8, 6, 0, 4, 18, 25, 25, 16, 2, 0, 0, 6, 21, 33, 43, 47, + 48, 50, 54, 70, 81, 90, 96,100,102,102,101,101,108,115,121,121,117, +108,101,108,117,122,124,121,115,109,102, 92, 78, 60, 45, 26, 8, 4, + 1, 20, 45, 62, 72, 75, 74, 68, 60, 51, 50, 50, 45, 34, 20, 5, 0, + 0, 1, 6, 7, 9, 18, 22, 21, 14, 9, 12, 12, 13, 11, 8, 13, 16, + 23, 28, 31, 29, 23, 16, 20, 22, 18, 9, 7, 8, 6, 2, 6, 21, 36, + 46, 53, 62, 74, 80, 83, 84, 86, 94,105,115,125,132,130,123,137,161, +181,190,186,173,161,163,154,139,123,113,107,100, 97, 99,103,105,103, + 99, 92, 84, 82, 80, 82, 84, 84, 82, 82, 83, 89, 96,103,109,113,113, +113,113,111,110,110,110,108,109,108,103, 96, 91, 99,107,113,117,114, +110,104, 99,106,110,109,102, 90, 74, 61, 72, 78, 82, 83, 85, 89, 88, + 82, 72, 62, 46, 29, 22, 19, 14, 7, 32, 56, 74, 86, 94, 99,102,103, +106,106,103, 98, 91, 81, 70, 56, 65, 72, 75, 74, 66, 53, 34, 22, 29, + 34, 36, 32, 25, 13, 1, 0, 1, 11, 19, 21, 20, 12, 1, 0, 0, 1, + 3, 2, 0, 0, 0, 0, 0, 3, 9, 12, 8, 0, 0, 0, 0, 3, 5, + 4, 1, 1, 0, 0, 5, 18, 26, 26, 18, 3, 0, 0, 4, 19, 31, 39, + 44, 46, 46, 47, 63, 76, 84, 89, 92, 92, 92, 91, 96,105,113,121,123, +120,111, 97,107,115,120,121,117,111,105, 96, 88, 76, 64, 48, 27, 11, + 5, 0, 21, 44, 59, 67, 68, 64, 56, 47, 48, 50, 47, 41, 29, 14, 1, + 0, 0, 0, 4, 8, 9, 9, 14, 13, 19, 23, 26, 25, 20, 13, 4, 0, + 1, 8, 16, 22, 23, 21, 15, 9, 13, 12, 8, 11, 11, 8, 3, 0, 14, + 31, 43, 51, 57, 64, 73, 76, 84, 89, 92, 96,105,113,117,115,133,159, +188,206,212,208,194,173,175,167,150,132,120,112,102, 92, 96,101,102, +100, 94, 88, 84, 80, 85, 90, 92, 93, 92, 88, 82, 76, 84, 90, 95, 99, +102,102,102,102,102,104,105,105,102, 98, 93, 87, 92, 99,107,112,113, +110,104, 99,107,114,119,118,109, 95, 79, 60, 70, 77, 82, 84, 84, 86, + 85, 78, 74, 64, 46, 26, 23, 20, 15, 19, 39, 62, 79, 90, 99,105,109, +111,111,104,101, 98, 93, 86, 77, 65, 50, 52, 56, 55, 48, 40, 29, 26, + 33, 37, 37, 32, 22, 9, 1, 0, 1, 11, 19, 21, 19, 12, 2, 0, 0, + 2, 5, 5, 2, 0, 0, 0, 3, 12, 18, 16, 11, 0, 0, 0, 0, 0, + 3, 3, 1, 0, 0, 0, 3, 18, 26, 26, 19, 8, 1, 0, 1, 14, 25, + 33, 39, 50, 56, 57, 68, 74, 79, 84, 88, 90, 92, 95, 99,102,110,118, +121,119,111, 98,103,111,113,113,109,110,106, 98, 88, 77, 65, 48, 27, + 13, 6, 3, 22, 43, 55, 60, 59, 52, 48, 51, 51, 50, 46, 40, 37, 27, + 13, 0, 0, 0, 0, 5, 11, 14, 16, 21, 27, 33, 38, 38, 34, 28, 20, + 12, 1, 0, 4, 13, 19, 20, 18, 13, 13, 14, 14, 14, 13, 11, 5, 0, + 4, 21, 34, 46, 54, 61, 69, 79, 88, 93, 97,102,105,110,117,129,150, +183,210,226,232,228,216,196,179,173,159,142,127,114,105,101,100,101, +101, 99, 96, 90, 85, 89, 93, 98,101,101, 99, 95, 89, 84, 79, 82, 87, + 91, 96,100,103,105,103,100,102,102,101, 97, 93, 97,102,105,105,108, +108,105,100,102,110,118,122,121,112, 99, 84, 66, 67, 74, 79, 83, 84, + 84, 82, 79, 75, 65, 50, 31, 25, 19, 16, 33, 45, 65, 79, 91,100,107, +112,117,117,110, 99, 98, 96, 92, 84, 74, 60, 44, 45, 46, 43, 36, 25, + 32, 38, 40, 39, 33, 22, 9, 4, 2, 0, 6, 12, 15, 13, 7, 0, 0, + 1, 7, 11, 12, 9, 4, 0, 4, 12, 18, 19, 16, 9, 0, 0, 0, 0, + 6, 8, 7, 4, 0, 0, 0, 1, 12, 21, 25, 19, 14, 9, 9, 13, 18, + 25, 34, 45, 55, 61, 66, 77, 83, 87, 90, 92, 93, 95, 96, 98,101,105, +113,118,117,111, 99, 96,102,103,103,106,106,102, 93, 83, 73, 59, 43, + 21, 14, 7, 5, 23, 41, 51, 53, 48, 47, 55, 56, 53, 51, 51, 53, 50, + 40, 26, 8, 1, 0, 1, 5, 11, 16, 20, 25, 31, 38, 43, 45, 44, 40, + 33, 25, 13, 0, 0, 6, 15, 20, 23, 25, 25, 26, 26, 25, 20, 14, 11, + 4, 0, 6, 21, 34, 46, 56, 66, 77, 87, 94,100,105,110,117,125,140, +167,202,228,240,243,241,232,216,196,175,165,152,137,124,114,109,107, +106,105,102, 99, 93, 89, 95,100,104,107,108,105,100, 94, 88, 83, 79, + 79, 85, 91, 96,100,102,102, 99, 96, 98, 97, 96,100,106,111,113,110, +104,103,101, 96,103,110,118,122,121,113,102, 88, 74, 68, 71, 74, 79, + 81, 82, 79, 77, 73, 64, 50, 37, 34, 32, 31, 46, 47, 63, 76, 87, 96, +103,111,117,119,112,101, 97, 98, 96, 91, 82, 69, 53, 41, 43, 39, 32, + 29, 37, 43, 45, 41, 36, 25, 12, 3, 1, 0, 0, 3, 5, 4, 0, 0, + 2, 7, 13, 18, 19, 16, 11, 6, 9, 14, 16, 15, 13, 6, 0, 0, 0, + 7, 14, 16, 16, 13, 9, 4, 1, 4, 12, 18, 20, 22, 22, 21, 21, 22, + 25, 29, 38, 46, 55, 62, 74, 84, 89, 92, 94, 95, 95, 95, 96, 95, 96, + 99,106,112,113,109,100, 94, 96, 99,101,102, 99, 93, 84, 74, 62, 48, + 31, 15, 13, 7, 7, 27, 41, 48, 46, 44, 54, 59, 58, 53, 55, 58, 59, + 57, 50, 36, 19, 14, 8, 5, 11, 12, 18, 22, 25, 31, 37, 43, 47, 48, + 46, 40, 33, 19, 0, 0, 2, 13, 25, 31, 33, 34, 36, 36, 33, 29, 22, + 15, 11, 7, 7, 11, 22, 38, 53, 64, 74, 84, 92, 99,106,114,122,133, +150,179,212,235,245,247,246,240,226,208,183,171,161,147,133,122,114, +111,109,108,105,102, 97, 93, 98,103,108,111,112,109,102, 96, 90, 85, + 82, 79, 79, 81, 87, 92, 94, 94, 92, 92, 93, 93, 97,103,110,114,114, +109,101,100, 97, 96,103,109,113,118,117,113,104, 92, 79, 72, 74, 77, + 79, 81, 81, 79, 74, 68, 59, 47, 41, 43, 43, 44, 54, 53, 56, 68, 78, + 87, 96,104,113,115,111,101, 95, 98, 98, 94, 85, 73, 57, 41, 43, 39, + 32, 33, 40, 45, 46, 43, 37, 26, 14, 4, 0, 0, 0, 0, 0, 0, 2, + 4, 6, 12, 18, 22, 23, 21, 15, 9, 11, 13, 12, 9, 6, 0, 0, 0, + 4, 15, 21, 23, 23, 21, 16, 13, 9, 11, 16, 23, 29, 32, 32, 29, 27, + 27, 27, 29, 34, 41, 50, 61, 76, 87, 93, 96, 96, 96, 94, 93, 94, 94, + 92, 92, 98,103,106,104, 98, 93, 95, 96, 96, 95, 90, 82, 71, 58, 46, + 32, 16, 13, 12, 7, 13, 33, 44, 47, 43, 50, 57, 60, 56, 54, 58, 61, + 61, 59, 52, 40, 28, 23, 15, 9, 15, 18, 19, 21, 22, 26, 32, 38, 43, + 46, 45, 41, 34, 20, 0, 0, 2, 14, 26, 34, 37, 38, 39, 39, 38, 34, + 29, 21, 16, 15, 16, 20, 25, 37, 52, 64, 74, 84, 94,104,114,125,134, +140,156,186,218,238,246,248,246,241,228,208,179,173,167,156,140,127, +117,111,109,107,106,103,101, 96, 99,103,109,113,113,109,102, 96, 89, + 84, 82, 80, 80, 81, 81, 80, 83, 83, 82, 88, 89, 88, 93,101,109,113, +111,104, 96, 96, 94, 96,102,105,108,110,111,108,102, 94, 84, 74, 76, + 78, 79, 80, 79, 77, 73, 64, 54, 43, 41, 46, 50, 52, 57, 54, 46, 53, + 63, 74, 84, 93,103,108,106, 98, 92, 95, 96, 92, 84, 71, 55, 46, 46, + 43, 33, 33, 39, 44, 45, 41, 37, 28, 15, 6, 1, 0, 0, 0, 3, 6, + 7, 8, 11, 15, 21, 25, 26, 23, 16, 7, 6, 6, 3, 1, 0, 0, 0, + 0, 9, 21, 27, 28, 28, 27, 28, 22, 18, 19, 25, 31, 36, 37, 36, 32, + 28, 27, 25, 23, 26, 31, 40, 59, 75, 87, 93, 96, 96, 96, 93, 96, 96, + 92, 92, 89, 88, 93, 96, 97, 94, 90, 92, 92, 90, 86, 79, 67, 54, 45, + 28, 13, 6, 11, 12, 13, 21, 39, 47, 48, 45, 52, 56, 57, 52, 53, 55, + 57, 58, 55, 50, 38, 31, 26, 16, 16, 21, 22, 20, 20, 19, 20, 23, 28, + 34, 38, 38, 36, 28, 14, 0, 0, 5, 13, 25, 32, 34, 36, 37, 37, 37, + 36, 32, 27, 18, 20, 23, 27, 31, 34, 50, 63, 75, 86, 98,111,124,136, +147,154,158,186,216,235,243,246,243,234,218,194,171,175,171,159,142, +127,114,108,105,104,104,104,102,101, 97,102,107,111,111,107,101, 93, + 87, 85, 82, 79, 79, 80, 80, 79, 75, 70, 77, 83, 86, 85, 85, 94,102, +104,102, 96, 91, 91, 91, 96,100,101,101,102,102,101, 98, 93, 84, 73, + 75, 77, 78, 78, 77, 75, 72, 64, 52, 37, 38, 46, 52, 55, 54, 51, 40, + 32, 50, 62, 69, 80, 92, 98, 98, 94, 86, 89, 90, 87, 78, 64, 50, 52, + 52, 47, 38, 28, 36, 41, 47, 47, 43, 33, 21, 7, 2, 2, 2, 4, 7, + 11, 11, 9, 12, 15, 20, 25, 26, 23, 16, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 23, 28, 31, 32, 39, 41, 36, 23, 26, 31, 36, 39, 38, 34, + 29, 25, 21, 16, 14, 20, 21, 32, 52, 70, 83, 90, 94, 95, 94, 96, 99, + 98, 94, 92, 91, 88, 82, 85, 88, 87, 84, 85, 85, 82, 75, 64, 50, 38, + 28, 12, 0, 2, 8, 13, 25, 31, 45, 53, 52, 47, 51, 52, 50, 47, 47, + 48, 50, 50, 47, 41, 31, 27, 22, 14, 23, 28, 27, 22, 19, 15, 19, 16, + 19, 22, 26, 26, 23, 16, 4, 0, 1, 8, 13, 19, 23, 26, 27, 28, 28, + 29, 31, 31, 28, 21, 21, 26, 29, 33, 37, 45, 60, 74, 87,100,114,130, +145,158,163,163,179,208,228,236,238,231,216,194,169,165,171,167,156, +139,123,111,105,103,100,101,102,102,102, 97, 99,104,107,107,103, 96, + 88, 87, 87, 84, 79, 77, 78, 78, 75, 71, 74, 79, 82, 82, 81, 78, 82, + 90, 92, 90, 84, 84, 86, 90, 96, 97,104,108,107,102, 94, 92, 88, 82, + 71, 71, 73, 74, 74, 73, 71, 69, 63, 52, 36, 32, 41, 48, 53, 47, 43, + 43, 45, 53, 63, 69, 71, 78, 86, 89, 88, 83, 82, 81, 78, 69, 54, 56, + 58, 57, 52, 41, 33, 38, 46, 51, 50, 45, 36, 22, 8, 0, 1, 2, 4, + 8, 11, 9, 8, 8, 12, 18, 22, 23, 21, 14, 2, 0, 0, 0, 1, 3, + 1, 0, 0, 11, 21, 27, 29, 41, 50, 51, 45, 32, 31, 36, 39, 39, 37, + 31, 22, 18, 12, 14, 21, 26, 32, 39, 44, 62, 76, 85, 91, 92, 92, 96, + 99, 98, 93, 94, 93, 90, 84, 77, 75, 76, 75, 76, 75, 71, 61, 47, 28, + 18, 8, 0, 0, 0, 12, 27, 37, 41, 53, 59, 58, 52, 47, 45, 40, 40, + 39, 39, 39, 38, 36, 29, 19, 20, 14, 22, 31, 33, 32, 25, 20, 16, 21, + 20, 15, 11, 13, 13, 9, 3, 0, 0, 5, 12, 13, 12, 13, 13, 14, 15, + 22, 26, 26, 23, 25, 21, 16, 22, 28, 32, 36, 37, 53, 69, 84, 98,114, +130,147,159,163,161,173,198,214,221,218,204,183,161,147,156,161,159, +147,132,115,104,105,104,101, 96, 97, 99, 98, 95, 95,100,102,102, 98, + 92, 84, 83, 84, 80, 76, 74, 75, 74, 72, 68, 74, 80, 84, 84, 80, 74, + 68, 76, 79, 76, 76, 78, 84, 91, 95, 96,105,112,113,111,102, 90, 82, + 77, 66, 64, 66, 67, 66, 66, 64, 63, 59, 50, 34, 26, 33, 40, 45, 38, + 48, 55, 58, 55, 61, 65, 65, 64, 74, 79, 80, 78, 74, 72, 67, 57, 57, + 59, 61, 60, 58, 55, 50, 41, 48, 52, 50, 44, 33, 19, 4, 0, 0, 0, + 0, 5, 6, 5, 3, 3, 6, 12, 18, 21, 20, 13, 1, 0, 0, 0, 2, + 2, 0, 0, 0, 5, 15, 25, 38, 48, 54, 55, 50, 36, 38, 40, 41, 40, + 34, 25, 15, 8, 14, 21, 27, 31, 40, 46, 51, 54, 70, 80, 87, 91, 92, + 92, 95, 93, 96, 97, 96, 93, 87, 79, 70, 61, 61, 62, 61, 56, 45, 29, + 12, 0, 0, 0, 0, 13, 28, 40, 48, 50, 61, 66, 64, 58, 48, 38, 36, + 36, 40, 40, 37, 29, 25, 18, 9, 9, 19, 28, 37, 39, 36, 31, 23, 15, + 20, 19, 14, 7, 3, 2, 0, 0, 0, 0, 8, 13, 13, 8, 2, 1, 12, + 21, 29, 33, 34, 31, 23, 15, 9, 15, 21, 26, 28, 29, 41, 59, 76, 92, +108,123,139,150,154,150,169,188,198,200,190,169,147,129,134,142,147, +143,134,121,108, 97,100,100, 97, 94, 90, 92, 91, 87, 91, 96, 98, 98, + 94, 88, 79, 73, 74, 72, 70, 72, 73, 73, 70, 63, 71, 78, 83, 84, 81, + 75, 67, 58, 62, 65, 68, 77, 85, 92, 95, 94,103,112,115,113,106, 96, + 83, 70, 59, 55, 61, 65, 68, 67, 62, 54, 51, 43, 31, 23, 25, 31, 36, + 43, 53, 60, 63, 60, 52, 55, 55, 53, 63, 70, 72, 71, 67, 62, 57, 53, + 53, 56, 58, 65, 67, 65, 60, 54, 50, 51, 48, 40, 28, 20, 11, 0, 0, + 0, 0, 0, 2, 3, 5, 11, 12, 9, 15, 19, 18, 12, 0, 0, 0, 0, + 2, 1, 0, 0, 3, 11, 20, 31, 43, 52, 57, 57, 52, 38, 40, 41, 41, + 38, 29, 19, 12, 16, 21, 27, 31, 33, 41, 46, 50, 52, 64, 75, 84, 89, + 92, 95, 96, 98,101,102,100, 95, 88, 79, 68, 57, 46, 47, 47, 44, 36, + 23, 9, 0, 0, 7, 21, 34, 46, 55, 59, 59, 67, 70, 68, 61, 52, 39, + 40, 45, 48, 47, 43, 36, 25, 14, 7, 14, 22, 32, 39, 43, 43, 40, 32, + 22, 14, 13, 8, 4, 0, 0, 0, 0, 0, 0, 8, 12, 11, 6, 5, 12, + 16, 26, 33, 38, 39, 38, 33, 26, 18, 18, 21, 26, 29, 32, 41, 60, 74, + 84, 99,113,127,137,140,143,158,169,173,169,156,137,120,113,117,122, +125,125,119,110, 99, 90, 91, 92, 90, 88, 84, 83, 81, 81, 85, 89, 91, + 90, 87, 80, 73, 66, 63, 63, 66, 68, 69, 69, 66, 60, 64, 73, 78, 80, + 79, 74, 65, 58, 56, 61, 70, 79, 86, 92, 96, 95, 97,105,111,111,105, + 96, 84, 73, 60, 58, 63, 66, 68, 67, 62, 54, 41, 36, 26, 18, 22, 27, + 33, 40, 51, 58, 61, 59, 51, 40, 39, 39, 52, 59, 61, 60, 57, 52, 46, + 41, 41, 50, 60, 66, 70, 69, 66, 61, 57, 52, 46, 39, 32, 23, 13, 0, + 0, 0, 1, 5, 7, 7, 7, 12, 15, 14, 15, 18, 15, 8, 4, 3, 2, + 4, 4, 4, 0, 0, 4, 13, 22, 34, 46, 55, 59, 59, 53, 41, 36, 37, + 37, 32, 23, 12, 19, 23, 27, 31, 31, 29, 37, 40, 41, 45, 59, 71, 79, + 86, 91, 95, 98,101,103,103,100, 94, 85, 74, 61, 50, 38, 34, 37, 36, + 32, 25, 14, 16, 25, 37, 47, 57, 64, 68, 70, 70, 68, 70, 67, 60, 50, + 43, 45, 50, 52, 50, 44, 36, 25, 13, 7, 14, 22, 32, 39, 48, 52, 48, + 41, 32, 23, 14, 6, 5, 6, 5, 3, 1, 0, 0, 4, 6, 5, 12, 25, + 32, 34, 36, 34, 39, 40, 40, 38, 36, 28, 26, 29, 33, 34, 37, 39, 57, + 73, 83, 92,106,118,125,129,130,136,140,140,134,124,113,101, 96, 98, +102,105,105,102, 96, 89, 81, 79, 81, 80, 78, 74, 74, 71, 70, 74, 77, + 78, 77, 73, 66, 58, 52, 51, 53, 57, 60, 62, 61, 58, 53, 57, 65, 71, + 73, 72, 66, 59, 54, 54, 60, 70, 79, 88, 93, 97, 96, 93, 96,102,103, +100, 92, 83, 71, 59, 56, 60, 63, 64, 62, 57, 48, 37, 31, 22, 12, 18, + 23, 31, 32, 43, 52, 56, 54, 47, 33, 21, 27, 39, 46, 48, 47, 43, 38, + 36, 27, 33, 45, 55, 62, 66, 68, 67, 65, 62, 58, 52, 44, 34, 23, 11, + 0, 0, 0, 6, 9, 11, 11, 8, 11, 14, 14, 16, 18, 14, 14, 14, 12, + 7, 9, 8, 8, 4, 0, 5, 11, 21, 33, 46, 54, 59, 58, 54, 43, 28, + 28, 28, 23, 16, 13, 20, 26, 29, 29, 28, 22, 27, 28, 29, 39, 53, 63, + 73, 79, 86, 92, 96,101,102,102, 97, 89, 79, 66, 51, 38, 27, 21, 25, + 25, 25, 20, 31, 41, 52, 61, 69, 74, 78, 79, 79, 79, 76, 73, 67, 60, + 52, 52, 53, 52, 52, 48, 41, 32, 20, 9, 4, 11, 19, 28, 44, 54, 57, + 55, 48, 40, 31, 19, 11, 7, 11, 13, 12, 7, 0, 0, 0, 0, 12, 28, + 41, 48, 51, 48, 44, 37, 36, 38, 39, 38, 33, 31, 36, 37, 37, 37, 37, + 51, 67, 79, 88, 98,109,117,120,118,117,117,113,108,101, 92, 84, 79, + 79, 81, 84, 86, 86, 82, 77, 70, 65, 68, 67, 64, 62, 62, 59, 54, 56, + 58, 58, 56, 50, 43, 36, 31, 32, 37, 43, 48, 51, 51, 47, 40, 48, 56, + 61, 62, 60, 56, 50, 45, 47, 56, 68, 78, 87, 93, 96, 96, 93, 88, 93, + 96, 93, 87, 78, 66, 55, 53, 56, 58, 58, 55, 50, 41, 36, 28, 20, 11, + 9, 15, 22, 20, 32, 40, 46, 46, 40, 29, 14, 15, 26, 32, 33, 31, 26, + 25, 25, 27, 26, 34, 44, 53, 58, 62, 65, 66, 65, 61, 54, 45, 33, 20, + 6, 0, 0, 3, 11, 14, 14, 12, 8, 7, 12, 18, 20, 20, 19, 20, 20, + 18, 13, 15, 13, 13, 9, 3, 4, 9, 15, 28, 41, 51, 55, 55, 50, 40, + 27, 18, 18, 16, 9, 11, 18, 23, 26, 26, 22, 14, 13, 14, 19, 33, 44, + 53, 61, 70, 77, 84, 91, 96, 98, 96, 92, 82, 70, 54, 37, 23, 15, 13, + 11, 12, 13, 31, 48, 60, 70, 77, 83, 86, 88, 88, 86, 85, 84, 79, 74, + 67, 61, 63, 63, 60, 55, 51, 44, 34, 20, 4, 0, 4, 12, 31, 46, 55, + 58, 56, 52, 45, 36, 22, 13, 8, 14, 18, 16, 9, 0, 0, 0, 7, 26, + 43, 54, 59, 59, 56, 50, 40, 29, 27, 32, 34, 33, 32, 37, 38, 37, 36, + 36, 43, 60, 74, 83, 91,100,107,111,110,104, 97, 92, 86, 80, 77, 75, + 73, 67, 66, 63, 64, 66, 64, 60, 54, 48, 52, 51, 47, 48, 48, 45, 37, + 34, 41, 44, 43, 39, 34, 28, 27, 27, 32, 36, 36, 36, 36, 31, 27, 37, + 44, 48, 48, 45, 40, 36, 33, 38, 50, 63, 75, 84, 90, 93, 94, 92, 87, + 85, 88, 85, 79, 71, 60, 52, 54, 55, 55, 53, 50, 45, 40, 34, 27, 19, + 8, 1, 5, 12, 13, 23, 27, 33, 37, 33, 26, 16, 14, 12, 16, 18, 14, + 8, 11, 22, 26, 27, 29, 34, 39, 46, 53, 58, 63, 64, 61, 54, 43, 29, + 14, 0, 0, 0, 6, 14, 18, 16, 14, 15, 13, 18, 22, 25, 23, 20, 22, + 23, 20, 14, 19, 20, 18, 16, 11, 2, 9, 14, 19, 32, 41, 46, 46, 40, + 32, 21, 9, 8, 8, 5, 4, 9, 15, 19, 19, 14, 5, 0, 0, 12, 23, + 32, 39, 47, 58, 64, 73, 81, 88, 91, 88, 83, 72, 57, 39, 21, 9, 4, + 6, 6, 4, 19, 40, 58, 72, 80, 87, 92, 93, 93, 92, 90, 88, 88, 84, + 79, 71, 74, 74, 73, 69, 64, 59, 52, 41, 27, 8, 0, 0, 11, 29, 45, + 53, 56, 54, 50, 45, 36, 22, 11, 8, 15, 19, 16, 8, 0, 0, 0, 20, + 38, 51, 59, 62, 61, 56, 47, 38, 27, 16, 18, 25, 25, 28, 34, 36, 36, + 34, 38, 40, 53, 67, 78, 85, 91, 97,101,101, 96, 91, 84, 80, 81, 80, + 80, 79, 73, 64, 60, 53, 43, 41, 40, 34, 29, 33, 32, 28, 31, 32, 38, + 38, 34, 38, 39, 37, 33, 32, 33, 33, 29, 37, 41, 44, 41, 33, 21, 14, + 23, 29, 32, 31, 26, 21, 21, 21, 26, 40, 56, 68, 78, 84, 87, 87, 86, + 82, 79, 80, 78, 72, 65, 60, 53, 58, 60, 60, 57, 53, 47, 41, 34, 26, + 16, 7, 0, 0, 0, 5, 18, 23, 25, 26, 27, 22, 16, 15, 12, 4, 3, + 0, 0, 5, 16, 20, 23, 29, 37, 44, 48, 51, 50, 57, 60, 58, 51, 39, + 25, 15, 1, 0, 0, 8, 18, 21, 21, 18, 21, 20, 21, 26, 28, 28, 23, + 21, 21, 18, 13, 21, 26, 25, 22, 18, 11, 8, 15, 20, 22, 28, 32, 31, + 26, 18, 8, 0, 2, 8, 11, 7, 7, 13, 16, 14, 6, 0, 0, 0, 2, + 11, 15, 23, 41, 54, 61, 64, 67, 76, 79, 78, 71, 59, 43, 26, 15, 1, + 0, 2, 11, 27, 39, 46, 63, 77, 86, 92, 96, 96, 95, 92, 89, 88, 88, + 85, 79, 81, 83, 82, 80, 76, 72, 67, 60, 50, 33, 14, 0, 0, 7, 26, + 39, 47, 50, 47, 44, 39, 32, 20, 6, 8, 15, 16, 13, 3, 0, 0, 9, + 29, 45, 54, 59, 60, 58, 51, 40, 29, 19, 9, 2, 8, 12, 22, 31, 33, + 33, 37, 45, 47, 48, 62, 74, 81, 85, 87, 91, 91, 88, 84, 87, 90, 91, + 88, 84, 84, 79, 68, 57, 50, 38, 22, 16, 13, 12, 15, 15, 13, 25, 34, + 41, 41, 38, 37, 36, 36, 37, 38, 38, 37, 32, 40, 47, 50, 47, 39, 27, + 21, 21, 16, 13, 11, 7, 9, 12, 11, 13, 28, 45, 58, 67, 74, 76, 77, + 76, 74, 73, 74, 72, 65, 62, 58, 56, 61, 63, 63, 60, 55, 48, 40, 33, + 25, 15, 5, 0, 0, 0, 0, 7, 14, 18, 18, 21, 20, 14, 12, 11, 5, + 0, 0, 0, 0, 6, 11, 14, 23, 34, 43, 50, 52, 51, 50, 55, 54, 47, + 36, 25, 15, 1, 0, 0, 12, 22, 27, 27, 22, 23, 23, 20, 26, 31, 32, + 28, 21, 15, 11, 13, 23, 31, 33, 28, 22, 16, 8, 16, 22, 25, 21, 14, + 12, 6, 0, 0, 0, 5, 13, 18, 16, 11, 12, 16, 16, 11, 2, 0, 0, + 0, 0, 0, 15, 34, 50, 58, 60, 58, 61, 66, 65, 58, 45, 27, 19, 7, + 0, 0, 8, 31, 50, 60, 66, 67, 78, 87, 93, 96, 96, 92, 89, 86, 85, + 84, 82, 86, 88, 89, 88, 85, 81, 76, 72, 66, 56, 40, 20, 0, 0, 4, + 21, 32, 39, 40, 38, 34, 31, 26, 15, 3, 6, 11, 12, 6, 0, 0, 0, + 19, 37, 47, 53, 55, 54, 51, 47, 48, 45, 33, 15, 0, 0, 2, 16, 26, + 32, 34, 41, 50, 52, 50, 60, 72, 79, 83, 82, 80, 80, 79, 87, 94, 98, + 98, 95, 88, 86, 82, 72, 57, 47, 34, 19, 1, 0, 0, 4, 13, 18, 25, + 34, 40, 40, 38, 37, 37, 37, 38, 38, 38, 36, 33, 44, 52, 55, 53, 45, + 32, 25, 25, 20, 11, 0, 0, 0, 0, 0, 0, 14, 29, 44, 53, 58, 60, + 61, 62, 65, 70, 71, 68, 61, 57, 53, 57, 62, 64, 64, 61, 55, 47, 39, + 31, 22, 13, 7, 1, 0, 0, 0, 0, 0, 5, 13, 18, 19, 14, 5, 5, + 3, 0, 0, 0, 0, 0, 0, 3, 12, 23, 36, 45, 48, 48, 43, 50, 51, + 45, 33, 21, 12, 0, 0, 0, 16, 29, 36, 36, 32, 26, 21, 20, 22, 28, + 32, 32, 26, 16, 3, 13, 26, 36, 40, 38, 28, 18, 9, 19, 25, 25, 20, + 11, 0, 0, 0, 0, 0, 11, 20, 25, 25, 20, 13, 20, 22, 20, 14, 5, + 0, 0, 0, 0, 7, 27, 43, 52, 54, 52, 45, 52, 52, 45, 33, 18, 6, + 0, 0, 0, 25, 48, 65, 74, 78, 79, 77, 86, 91, 92, 91, 88, 83, 79, + 78, 82, 87, 91, 93, 94, 92, 88, 84, 79, 74, 69, 59, 45, 25, 2, 0, + 0, 14, 25, 29, 29, 27, 26, 22, 19, 13, 11, 8, 5, 3, 0, 0, 0, + 8, 26, 40, 48, 51, 48, 46, 54, 59, 59, 55, 43, 23, 1, 0, 0, 13, + 26, 34, 39, 43, 50, 52, 59, 66, 74, 80, 83, 82, 77, 69, 78, 88, 96, +102,103,100, 92, 84, 79, 70, 57, 46, 32, 15, 0, 0, 0, 8, 19, 25, + 27, 31, 37, 37, 41, 41, 39, 34, 33, 33, 34, 29, 39, 50, 56, 59, 57, + 50, 37, 23, 23, 19, 11, 1, 0, 0, 0, 0, 0, 1, 14, 26, 34, 38, + 40, 43, 54, 63, 69, 70, 68, 62, 53, 43, 53, 59, 61, 61, 57, 52, 43, + 33, 25, 20, 20, 19, 13, 5, 0, 0, 0, 0, 2, 9, 15, 18, 15, 8, + 0, 1, 5, 7, 8, 8, 9, 14, 16, 13, 18, 27, 38, 44, 45, 41, 41, + 44, 39, 29, 18, 7, 0, 0, 5, 25, 38, 46, 48, 46, 43, 39, 34, 25, + 21, 28, 32, 29, 23, 22, 18, 31, 41, 47, 47, 40, 28, 15, 19, 22, 22, + 15, 5, 0, 0, 3, 11, 18, 21, 26, 29, 29, 25, 19, 28, 33, 33, 31, + 25, 16, 9, 4, 2, 12, 23, 32, 39, 40, 37, 29, 37, 37, 32, 21, 7, + 0, 0, 0, 16, 41, 62, 75, 82, 84, 84, 82, 85, 89, 89, 87, 82, 83, + 91, 94, 94, 95, 96, 98,100,100,100, 96, 90, 79, 71, 61, 46, 26, 3, + 0, 0, 8, 18, 20, 21, 31, 36, 33, 27, 23, 21, 18, 12, 6, 0, 0, + 2, 12, 26, 37, 41, 41, 47, 56, 62, 65, 65, 59, 47, 27, 3, 0, 0, + 14, 29, 41, 51, 56, 61, 66, 73, 78, 82, 84, 84, 83, 79, 79, 79, 86, + 96,102,106,104, 97, 88, 79, 70, 60, 47, 31, 13, 0, 0, 0, 11, 21, + 28, 33, 36, 38, 43, 46, 46, 44, 45, 48, 52, 54, 56, 59, 62, 63, 63, + 60, 53, 40, 27, 18, 14, 8, 2, 0, 0, 0, 1, 5, 5, 4, 11, 16, + 19, 21, 36, 48, 59, 66, 69, 69, 64, 57, 54, 59, 62, 63, 63, 61, 58, + 54, 46, 34, 27, 25, 27, 27, 23, 13, 21, 5, 0, 0, 4, 11, 15, 16, + 13, 9, 7, 6, 11, 15, 19, 22, 27, 27, 23, 28, 29, 33, 41, 44, 41, + 38, 34, 29, 25, 15, 4, 0, 0, 11, 31, 46, 55, 59, 60, 58, 57, 53, + 43, 31, 29, 37, 40, 43, 43, 38, 38, 51, 58, 59, 55, 46, 33, 29, 31, + 27, 19, 9, 11, 20, 29, 38, 43, 44, 40, 32, 29, 25, 27, 37, 43, 46, + 46, 44, 40, 36, 31, 28, 23, 31, 37, 37, 32, 23, 18, 23, 25, 20, 13, + 5, 0, 0, 13, 36, 57, 73, 83, 88, 88, 87, 84, 87, 89, 88, 84, 87, + 96,105,109,110,112,114,117,118,117,114,109,100, 88, 75, 63, 47, 26, + 11, 0, 0, 3, 7, 12, 26, 38, 45, 44, 39, 36, 31, 26, 20, 14, 7, + 1, 3, 12, 19, 26, 29, 43, 57, 64, 68, 71, 69, 62, 50, 34, 20, 8, + 6, 16, 37, 52, 63, 71, 76, 80, 85, 88, 91, 92, 91, 89, 88, 88, 88, + 84, 93,102,106,106,102, 92, 83, 73, 60, 46, 29, 20, 15, 8, 5, 8, + 19, 27, 33, 37, 40, 44, 46, 52, 58, 63, 68, 72, 76, 79, 80, 82, 81, + 78, 71, 60, 47, 34, 25, 18, 13, 11, 12, 14, 18, 23, 27, 26, 18, 4, + 3, 5, 8, 25, 38, 51, 60, 65, 67, 65, 59, 61, 67, 70, 71, 70, 69, + 67, 63, 57, 48, 43, 33, 36, 41, 41, 36, 41, 23, 9, 0, 0, 3, 9, + 14, 19, 21, 21, 21, 20, 20, 25, 29, 34, 33, 34, 39, 40, 38, 39, 44, + 43, 39, 37, 32, 26, 15, 2, 0, 0, 14, 36, 52, 62, 67, 69, 69, 69, + 66, 57, 44, 38, 47, 55, 58, 59, 55, 48, 61, 69, 72, 69, 61, 52, 40, + 40, 37, 29, 23, 32, 41, 53, 59, 62, 61, 55, 45, 29, 23, 37, 45, 51, + 55, 57, 58, 57, 56, 54, 52, 46, 38, 38, 36, 28, 18, 20, 25, 25, 20, + 13, 5, 2, 14, 32, 53, 70, 81, 88, 91, 91, 88, 88, 90, 90, 88, 92, +100,109,119,124,128,132,137,140,140,137,130,121,109, 96, 84, 71, 56, + 39, 25, 11, 5, 2, 0, 14, 31, 44, 52, 51, 47, 43, 38, 32, 26, 20, + 14, 9, 7, 9, 14, 23, 36, 51, 61, 67, 70, 71, 71, 68, 61, 50, 37, + 25, 16, 22, 45, 63, 75, 84, 88, 92, 95, 96, 96, 96, 95, 94, 93, 94, + 93, 89, 90, 98,104,106,102, 93, 83, 71, 58, 43, 34, 34, 32, 27, 21, + 20, 26, 31, 36, 40, 46, 53, 59, 64, 70, 75, 81, 86, 92, 95, 96, 96, + 95, 89, 82, 73, 62, 52, 44, 37, 29, 21, 23, 29, 36, 43, 45, 41, 31, + 15, 0, 0, 0, 12, 25, 38, 51, 58, 62, 62, 59, 66, 70, 72, 73, 73, + 73, 72, 69, 64, 58, 54, 44, 41, 52, 56, 53, 54, 37, 20, 6, 0, 0, + 2, 12, 21, 27, 31, 33, 34, 34, 34, 34, 38, 41, 45, 47, 47, 45, 39, + 41, 41, 40, 38, 34, 27, 16, 2, 0, 0, 16, 38, 54, 64, 70, 74, 74, + 76, 74, 66, 54, 46, 57, 65, 69, 70, 66, 60, 73, 79, 82, 79, 74, 66, + 56, 48, 47, 41, 39, 47, 57, 67, 74, 76, 74, 67, 56, 41, 38, 44, 51, + 55, 59, 63, 65, 67, 69, 68, 67, 63, 55, 43, 32, 23, 12, 20, 25, 23, + 19, 12, 11, 19, 32, 50, 67, 79, 88, 92, 94, 92, 90, 93, 92, 91, 95, +106,117,125,133,142,149,158,165,171,169,159,147,130,115,102, 90, 79, + 65, 51, 36, 20, 11, 5, 5, 18, 33, 46, 53, 53, 50, 45, 39, 34, 28, + 23, 20, 16, 16, 20, 27, 38, 48, 59, 67, 72, 75, 78, 78, 76, 70, 61, + 50, 38, 27, 31, 56, 74, 86, 94, 99,102,102,102, 99, 97, 96, 95, 96, + 97, 96, 92, 85, 93, 99,101, 98, 90, 79, 65, 51, 38, 41, 45, 46, 46, + 43, 40, 38, 45, 51, 56, 61, 65, 69, 73, 77, 82, 88, 96,102,108,110, +108,103, 97, 88, 79, 71, 63, 58, 52, 44, 33, 31, 38, 46, 53, 55, 51, + 39, 23, 4, 0, 0, 0, 9, 23, 37, 47, 54, 55, 58, 65, 69, 70, 71, + 71, 71, 71, 70, 65, 61, 58, 50, 45, 57, 64, 63, 58, 41, 23, 7, 0, + 0, 0, 4, 18, 28, 36, 41, 44, 45, 45, 45, 47, 50, 53, 53, 52, 47, + 40, 36, 38, 38, 37, 34, 28, 16, 2, 0, 0, 16, 37, 53, 62, 69, 72, + 74, 76, 75, 69, 59, 53, 63, 71, 75, 76, 73, 73, 83, 88, 91, 88, 83, + 75, 67, 58, 57, 54, 48, 55, 65, 75, 82, 84, 82, 75, 65, 56, 58, 54, + 52, 55, 59, 63, 67, 71, 74, 75, 74, 73, 66, 57, 43, 25, 8, 19, 22, + 22, 23, 25, 29, 37, 48, 63, 78, 88, 94, 96, 96, 93, 98, 98, 96, 93, +106,120,136,150,161,163,169,183,196,200,196,183,161,139,121,106, 95, + 84, 72, 59, 44, 26, 15, 8, 21, 33, 43, 47, 50, 50, 45, 40, 36, 29, + 26, 22, 21, 20, 22, 27, 36, 45, 54, 63, 70, 74, 77, 79, 81, 79, 75, + 68, 58, 48, 36, 43, 67, 84, 96,103,107,108,107,102, 98, 95, 93, 93, + 95, 97, 96, 92, 85, 87, 91, 92, 90, 82, 69, 53, 37, 38, 44, 51, 56, + 59, 60, 58, 56, 58, 64, 69, 73, 74, 77, 84, 90, 92, 92,100,109,115, +118,114,108,100, 92, 83, 75, 70, 66, 61, 54, 44, 32, 39, 50, 56, 58, + 53, 43, 27, 9, 0, 0, 0, 0, 8, 22, 34, 41, 45, 53, 60, 63, 63, + 63, 63, 64, 65, 65, 61, 58, 57, 51, 46, 59, 66, 67, 57, 40, 21, 12, + 4, 0, 0, 0, 9, 23, 36, 43, 48, 50, 51, 51, 52, 54, 55, 54, 50, + 44, 37, 28, 31, 32, 33, 32, 27, 16, 7, 3, 0, 15, 34, 48, 58, 63, + 66, 68, 72, 72, 67, 60, 59, 68, 74, 77, 78, 74, 83, 92, 96, 97, 94, + 88, 81, 74, 67, 68, 67, 63, 58, 67, 78, 86, 88, 88, 83, 75, 72, 73, + 68, 58, 52, 55, 59, 64, 69, 74, 76, 77, 77, 74, 67, 57, 45, 31, 39, + 43, 44, 43, 44, 51, 59, 66, 74, 86, 95, 99,101, 99,102,105,102, 97, +102,115,134,156,177,190,192,190,206,219,223,218,202,175,145,130,115, + 99, 87, 76, 63, 47, 28, 19, 22, 37, 47, 53, 54, 51, 45, 37, 31, 26, + 21, 19, 18, 18, 19, 22, 28, 37, 45, 53, 60, 66, 70, 74, 77, 79, 79, + 77, 71, 62, 53, 41, 57, 78, 93,104,111,113,112,109,102,107,108,104, + 97, 92, 94, 94, 90, 84, 79, 81, 81, 77, 68, 53, 34, 37, 48, 54, 55, + 61, 68, 71, 71, 70, 69, 74, 79, 81, 81, 89, 97,104,107,106,102,110, +118,119,115,108, 99, 91, 82, 75, 72, 70, 67, 61, 53, 41, 36, 45, 53, + 54, 50, 39, 26, 11, 0, 0, 0, 0, 0, 8, 20, 28, 33, 44, 50, 52, + 57, 65, 66, 60, 54, 56, 53, 47, 50, 47, 45, 57, 64, 65, 50, 33, 32, + 28, 20, 8, 0, 0, 0, 15, 29, 40, 46, 50, 51, 51, 52, 53, 52, 48, + 43, 36, 27, 20, 22, 25, 27, 28, 23, 14, 13, 9, 3, 14, 31, 43, 51, + 55, 56, 58, 62, 64, 61, 57, 64, 70, 74, 77, 77, 81, 92, 99,102,102, + 96, 89, 83, 75, 77, 79, 79, 76, 73, 69, 79, 87, 92, 92, 89, 84, 84, + 82, 77, 67, 60, 58, 63, 65, 65, 70, 74, 76, 79, 79, 76, 71, 62, 53, + 56, 59, 60, 59, 62, 70, 77, 81, 83, 94,102,105,106,104,108,109,104, + 98,107,123,145,171,194,208,210,208,225,235,238,232,216,186,156,143, +124,106, 88, 78, 65, 48, 28, 26, 39, 51, 58, 60, 58, 52, 45, 36, 25, + 21, 16, 13, 8, 11, 13, 16, 23, 31, 39, 46, 53, 57, 61, 66, 72, 76, + 77, 76, 72, 65, 56, 50, 71, 88,102,112,117,117,113,111,121,127,127, +120,109, 96, 90, 90, 87, 80, 71, 69, 66, 60, 50, 33, 32, 46, 58, 64, + 66, 65, 73, 77, 78, 78, 79, 84, 87, 88, 89, 98,108,117,121,119,113, +107,113,115,113,105, 96, 88, 84, 76, 71, 70, 68, 64, 58, 48, 37, 36, + 44, 46, 41, 33, 21, 9, 0, 0, 0, 0, 0, 0, 8, 14, 21, 31, 37, + 46, 62, 71, 74, 69, 58, 43, 41, 32, 37, 39, 41, 52, 58, 58, 40, 41, + 43, 40, 36, 22, 5, 0, 0, 6, 21, 32, 39, 43, 43, 43, 43, 43, 41, + 37, 29, 22, 13, 12, 14, 16, 20, 21, 19, 14, 15, 13, 6, 14, 28, 38, + 44, 45, 46, 50, 51, 54, 56, 61, 67, 72, 74, 75, 76, 88, 97,103,105, +102, 96, 88, 80, 82, 85, 87, 88, 86, 83, 79, 79, 88, 95, 97, 97, 95, + 91, 89, 84, 82, 79, 75, 72, 74, 75, 74, 70, 74, 79, 83, 84, 82, 78, + 73, 67, 71, 72, 73, 79, 84, 88, 91, 92,102,110,113,114,112,110,110, +104,103,118,133,150,175,198,210,212,226,238,244,245,242,228,198,161, +149,129,110, 93, 79, 65, 48, 28, 40, 53, 62, 66, 66, 62, 54, 45, 45, + 44, 39, 31, 20, 13, 6, 3, 7, 13, 20, 28, 36, 41, 47, 53, 59, 66, + 72, 75, 75, 73, 67, 58, 63, 82, 98,111,120,123,121,117,129,142,149, +147,133,117,101, 88, 87, 82, 75, 65, 54, 48, 40, 26, 26, 29, 50, 64, + 72, 74, 74, 74, 79, 81, 83, 88, 92, 95, 95, 93,102,113,123,128,128, +123,115,109,112,108,102, 99, 95, 89, 80, 68, 68, 67, 65, 60, 53, 44, + 36, 32, 36, 32, 29, 25, 18, 8, 0, 0, 0, 0, 0, 1, 6, 12, 19, + 25, 46, 64, 74, 77, 74, 64, 50, 31, 22, 22, 29, 36, 44, 50, 48, 43, + 45, 47, 50, 46, 34, 16, 0, 1, 3, 12, 20, 27, 32, 41, 46, 47, 41, + 33, 23, 15, 8, 6, 15, 22, 22, 16, 16, 15, 13, 15, 15, 11, 18, 23, + 32, 36, 37, 45, 51, 53, 54, 57, 62, 67, 71, 73, 74, 78, 89, 98,103, +102, 98, 90, 87, 88, 90, 92, 95, 95, 94, 91, 88, 88, 88, 96,102,106, +106,104,102, 98, 96, 94, 90, 84, 80, 82, 82, 80, 76, 79, 86, 91, 93, + 92, 89, 86, 84, 85, 88, 92, 95, 98, 99, 99,108,115,120,121,119,115, +113,111,113,128,145,163,181,198,212,223,235,244,248,249,246,238,212, +177,145,128,112, 96, 80, 65, 50, 41, 53, 63, 70, 74, 72, 67, 58, 60, + 60, 58, 52, 43, 29, 16, 9, 5, 5, 8, 14, 22, 32, 43, 52, 59, 63, + 64, 70, 74, 75, 74, 68, 71, 74, 92,108,121,129,130,127,132,145,159, +165,159,142,122,103, 89, 81, 75, 67, 56, 43, 32, 21, 14, 13, 25, 47, + 64, 74, 79, 81, 82, 84, 87, 92, 96,100,102,102,100,101,111,120,127, +127,123,117,112,109,107,105,102, 98, 92, 83, 70, 63, 64, 62, 59, 54, + 46, 40, 38, 39, 38, 36, 31, 25, 15, 5, 0, 0, 0, 0, 0, 1, 4, + 12, 18, 40, 58, 70, 75, 74, 66, 54, 38, 22, 11, 20, 28, 36, 40, 39, + 39, 43, 52, 56, 54, 44, 28, 9, 11, 13, 15, 19, 23, 33, 43, 48, 48, + 43, 33, 22, 13, 5, 13, 21, 27, 27, 21, 16, 14, 11, 16, 19, 16, 16, + 16, 20, 25, 34, 43, 47, 48, 50, 53, 58, 63, 67, 70, 72, 77, 88, 96, + 99, 96, 91, 88, 94, 96, 96, 99,101,102,100, 98, 96, 96, 97, 99,106, +113,117,117,114,112,109,107,102, 96, 88, 87, 88, 88, 84, 79, 89, 97, +103,106,105,102,101,101,102,103,106,107,108,108,109,115,120,121,120, +118,114,113,117,130,147,163,181,196,210,221,234,244,249,250,249,242, +223,188,154,127,113, 99, 85, 72, 57, 52, 60, 70, 76, 79, 78, 73, 67, + 70, 69, 67, 61, 51, 36, 18, 7, 3, 3, 6, 13, 22, 33, 45, 55, 63, + 67, 68, 70, 74, 76, 76, 79, 83, 87,102,118,130,137,139,134,149,159, +169,173,163,145,125,107, 92, 79, 67, 55, 41, 28, 18, 5, 0, 0, 13, + 38, 59, 73, 81, 85, 88, 89, 92, 96,101,105,108,109,106,101,102,111, +117,119,117,113,109,106,105,103,102, 97, 92, 83, 70, 57, 59, 59, 58, + 54, 48, 43, 41, 41, 40, 37, 32, 25, 16, 6, 1, 0, 0, 0, 0, 0, + 0, 5, 12, 27, 46, 60, 67, 69, 65, 57, 45, 32, 18, 15, 23, 29, 31, + 33, 29, 43, 53, 59, 58, 51, 37, 19, 20, 22, 23, 26, 29, 33, 38, 44, + 45, 39, 29, 18, 6, 13, 19, 23, 29, 31, 26, 18, 15, 9, 16, 22, 22, + 21, 19, 18, 25, 32, 37, 39, 39, 40, 44, 50, 56, 60, 64, 67, 74, 85, + 92, 92, 89, 86, 93, 98,100,100,101,102,103,103,102,102,102,104,105, +109,119,125,128,127,122,119,115,112,106, 98, 90, 92, 92, 89, 83, 91, +102,113,118,120,117,114,113,113,113,113,114,114,114,114,115,118,120, +121,121,119,114,115,128,140,154,171,183,196,210,226,240,247,249,248, +243,225,194,158,128,113,102, 90, 77, 63, 58, 65, 74, 79, 82, 82, 79, + 74, 75, 75, 73, 66, 56, 39, 19, 3, 0, 0, 1, 8, 19, 32, 44, 55, + 62, 67, 69, 72, 77, 78, 83, 88, 91, 96,112,125,137,145,145,147,161, +167,173,171,161,143,125,109, 94, 81, 67, 58, 51, 43, 32, 19, 3, 0, + 4, 23, 48, 67, 79, 86, 89, 92, 94, 97,102,105,109,111,110,104, 97, + 99,104,107,107,104,102,101, 99, 99, 97, 94, 88, 80, 67, 50, 53, 55, + 58, 59, 55, 46, 40, 40, 38, 33, 27, 20, 12, 5, 2, 0, 0, 0, 0, + 0, 0, 0, 7, 13, 29, 45, 55, 60, 60, 56, 48, 39, 28, 14, 18, 22, + 22, 21, 22, 38, 51, 58, 58, 53, 40, 26, 27, 28, 28, 28, 29, 31, 33, + 33, 34, 29, 20, 7, 13, 18, 22, 26, 31, 33, 29, 21, 18, 12, 14, 22, + 26, 27, 27, 26, 22, 26, 28, 28, 26, 26, 31, 38, 45, 52, 57, 61, 67, + 79, 85, 86, 82, 87, 93, 98, 99, 97, 98,100,102,103,103,104,106,108, +108,112,124,134,139,137,130,125,121,117,112,105, 96, 91, 92, 89, 84, + 93,107,119,127,129,127,123,121,119,118,117,117,118,118,119,121,123, +124,125,125,123,120,118,128,142,156,169,177,177,188,206,228,241,245, +244,238,219,190,156,125,114,105, 94, 81, 67, 61, 67, 74, 80, 84, 86, + 85, 80, 79, 79, 76, 70, 58, 40, 18, 0, 0, 0, 2, 9, 16, 27, 40, + 52, 59, 63, 67, 76, 81, 81, 87, 92, 96,103,118,132,143,150,152,159, +169,171,167,161,150,136,121,107, 94, 81, 74, 69, 63, 56, 46, 34, 19, + 1, 13, 27, 38, 57, 73, 83, 88, 89, 91, 93, 96,101,104,108,108,104, + 98, 92, 92, 95, 96, 94, 93, 96, 93, 92, 92, 88, 84, 75, 61, 43, 46, + 54, 61, 62, 58, 50, 37, 34, 31, 25, 20, 18, 12, 8, 8, 7, 3, 1, + 0, 0, 0, 0, 2, 11, 16, 25, 37, 46, 51, 52, 50, 44, 37, 25, 11, + 14, 13, 9, 14, 31, 45, 53, 55, 51, 39, 28, 29, 29, 27, 25, 23, 23, + 25, 25, 21, 14, 5, 12, 18, 22, 25, 34, 37, 36, 34, 28, 20, 13, 8, + 20, 26, 29, 32, 31, 27, 19, 16, 14, 12, 18, 19, 23, 32, 40, 48, 53, + 58, 72, 78, 79, 76, 83, 89, 93, 93, 92, 94,101,106,108,108,103,104, +106,107,115,130,143,149,143,136,128,123,119,113,107, 99, 90, 88, 86, + 81, 95,109,120,128,130,128,124,121,118,115,113,114,115,117,119,122, +124,127,128,128,127,124,123,130,142,154,161,165,163,159,177,204,225, +234,234,226,206,177,145,122,118,109, 98, 85, 70, 62, 66, 74, 80, 86, + 89, 90, 88, 81, 81, 79, 73, 60, 41, 16, 0, 0, 0, 5, 12, 22, 29, + 36, 47, 55, 59, 73, 82, 87, 87, 87, 93, 97,106,120,133,143,152,158, +171,175,169,159,149,136,124,113,102, 92, 83, 80, 77, 72, 66, 58, 48, + 36, 16, 20, 33, 44, 50, 62, 75, 81, 83, 84, 85, 88, 92, 96,100,102, +100, 95, 89, 84, 83, 84, 84, 88, 91, 88, 84, 84, 81, 76, 67, 53, 36, + 44, 56, 62, 63, 58, 47, 34, 26, 20, 26, 28, 26, 19, 16, 15, 14, 11, + 5, 5, 3, 0, 0, 0, 5, 16, 25, 29, 31, 38, 44, 46, 45, 43, 34, + 20, 5, 4, 6, 6, 22, 37, 46, 48, 44, 33, 28, 28, 26, 22, 20, 22, + 19, 13, 13, 11, 2, 4, 13, 20, 25, 33, 43, 45, 41, 40, 37, 28, 16, + 8, 13, 22, 28, 32, 32, 28, 19, 7, 1, 3, 8, 9, 9, 18, 28, 37, + 44, 48, 62, 70, 71, 70, 76, 82, 84, 84, 89, 95,101,105,109,109,105, +100,102,104,121,139,152,154,149,137,134,124,117,111,104, 96, 88, 80, + 79, 82, 96,109,119,123,124,122,118,113,110,107,106,107,108,111,113, +117,121,123,125,127,128,127,128,130,139,147,150,150,147,139,150,173, +196,210,212,202,181,158,132,124,121,113,102, 88, 72, 61, 67, 74, 79, + 86, 92, 94, 93, 87, 84, 81, 75, 63, 44, 16, 0, 0, 2, 12, 16, 25, + 33, 39, 43, 50, 64, 79, 88, 93, 93, 89, 91, 95,106,118,130,142,150, +165,179,177,183,179,161,139,115,105, 96, 87, 84, 83, 80, 77, 72, 66, + 58, 48, 32, 32, 39, 48, 54, 55, 64, 72, 74, 80, 88, 91, 89, 85, 90, + 92, 92, 88, 84, 79, 75, 74, 75, 80, 84, 81, 74, 74, 73, 67, 57, 41, + 31, 45, 56, 62, 61, 54, 41, 27, 15, 26, 34, 37, 33, 26, 23, 21, 20, + 18, 14, 9, 7, 4, 0, 0, 9, 20, 28, 34, 37, 33, 33, 40, 44, 45, + 40, 29, 16, 4, 4, 1, 15, 29, 38, 39, 34, 27, 25, 23, 21, 25, 32, + 34, 29, 19, 3, 0, 2, 9, 14, 20, 27, 38, 47, 50, 45, 48, 47, 40, + 29, 15, 5, 14, 22, 28, 31, 27, 18, 5, 0, 0, 0, 0, 0, 8, 19, + 26, 32, 37, 53, 61, 65, 64, 66, 72, 78, 84, 87, 92, 96,102,104,105, +102, 94, 96,111,129,147,159,159,150,142,142,132,118,106, 99, 92, 82, + 70, 72, 85, 97,107,113,115,113,111,107,103,103,102, 99, 96, 98,101, +104,108,113,115,119,121,123,124,128,133,137,139,136,133,129,123,129, +147,167,181,183,173,154,136,124,127,125,118,105, 90, 74, 60, 72, 79, + 84, 88, 92, 96, 96, 91, 87, 85, 79, 67, 48, 21, 0, 0, 2, 12, 19, + 26, 36, 41, 44, 48, 68, 83, 94,100,101, 96, 88, 90,102,113,124,136, +156,175,186,183,194,192,179,154,125,103, 89, 80, 81, 82, 80, 78, 74, + 69, 63, 56, 43, 43, 44, 52, 56, 56, 53, 59, 68, 82, 90, 93, 92, 86, + 78, 82, 84, 85, 84, 82, 77, 73, 66, 71, 75, 73, 66, 65, 62, 57, 46, + 31, 31, 45, 54, 58, 56, 46, 32, 16, 19, 33, 40, 43, 38, 28, 25, 21, + 21, 21, 20, 16, 12, 7, 2, 0, 12, 27, 40, 48, 51, 47, 39, 38, 45, + 51, 52, 46, 34, 16, 2, 0, 12, 25, 32, 33, 29, 27, 22, 20, 29, 38, + 45, 45, 40, 28, 11, 0, 4, 14, 21, 26, 29, 36, 45, 47, 54, 58, 58, + 53, 44, 31, 15, 3, 12, 20, 25, 23, 18, 6, 0, 0, 0, 0, 2, 13, + 23, 29, 31, 25, 44, 55, 60, 61, 60, 66, 75, 80, 88, 94, 96, 97, 99, + 99, 96, 88,102,118,137,158,167,165,154,137,139,130,118,104, 94, 85, + 74, 61, 74, 87, 97,104,108,107,103,100,103,106,106,104,100, 95, 91, + 89, 96,101,105,107,108,111,113,115,121,127,133,136,134,128,119,107, +117,130,145,156,156,147,133,121,125,129,128,120,108, 92, 76, 58, 72, + 81, 87, 91, 92, 96, 97, 92, 92, 91, 85, 75, 57, 31, 2, 0, 0, 6, + 14, 27, 37, 43, 45, 50, 69, 85, 97,104,106,102, 95, 85, 97,109,120, +140,163,183,190,181,194,196,186,163,134,110, 90, 74, 76, 77, 79, 81, + 81, 77, 70, 56, 45, 44, 50, 56, 58, 57, 54, 46, 66, 81, 90, 94, 92, + 87, 79, 76, 81, 84, 83, 80, 80, 78, 71, 58, 63, 61, 59, 58, 55, 47, + 37, 21, 28, 40, 50, 52, 47, 37, 21, 5, 23, 37, 44, 45, 38, 27, 19, + 16, 20, 22, 22, 23, 22, 18, 9, 0, 11, 28, 45, 56, 60, 59, 54, 44, + 53, 59, 61, 57, 46, 29, 11, 6, 14, 22, 29, 32, 31, 27, 25, 33, 40, + 48, 53, 53, 47, 36, 18, 7, 7, 19, 28, 34, 38, 40, 47, 55, 61, 66, + 67, 64, 58, 47, 34, 22, 11, 6, 13, 15, 13, 8, 2, 0, 0, 0, 9, + 20, 28, 34, 36, 31, 39, 47, 55, 61, 67, 72, 78, 85, 93, 98,101,102, +101, 98, 96, 97,110,127,147,163,171,167,154,137,127,121,111,100, 88, + 78, 68, 66, 78, 88, 96,101,102, 99, 95,100,103,105,105,102, 98, 94, + 94, 98,102,103,105,107,108,109,114,120,122,121,128,133,132,127,118, +114,113,118,128,134,134,128,119,114,119,124,124,119,107, 93, 78, 62, + 69, 80, 88, 93, 96, 98, 98, 99,100, 98, 92, 82, 66, 43, 14, 0, 0, + 4, 16, 28, 37, 43, 46, 53, 70, 86, 98,107,111,108,100, 92, 98,110, +125,147,167,183,188,179,188,192,183,163,136,113, 94, 79, 79, 82, 84, + 87, 86, 83, 76, 64, 50, 47, 54, 58, 59, 57, 53, 56, 65, 78, 87, 91, + 90, 89, 86, 84, 84, 84, 85, 86, 85, 82, 75, 63, 53, 53, 54, 52, 48, + 41, 29, 15, 20, 31, 38, 39, 34, 22, 6, 12, 29, 43, 48, 46, 39, 27, + 13, 21, 26, 27, 25, 31, 33, 32, 25, 13, 12, 27, 46, 59, 67, 68, 64, + 56, 57, 64, 66, 63, 54, 39, 20, 19, 19, 25, 29, 31, 28, 27, 37, 43, + 47, 53, 56, 56, 51, 39, 29, 26, 25, 26, 34, 43, 46, 47, 50, 57, 64, + 69, 73, 72, 69, 62, 54, 45, 36, 22, 12, 16, 19, 18, 14, 9, 5, 5, + 16, 27, 37, 41, 43, 39, 39, 50, 58, 66, 72, 77, 82, 88, 94, 99,102, +103,103,102, 99,107,119,133,149,161,163,158,147,133,121,110,101, 92, + 84, 74, 66, 72, 81, 88, 94, 96, 96, 92, 93, 98,100,100, 99, 96, 93, + 90, 96,100,103,105,106,106,106,107,113,120,123,122,129,134,134,129, +120,120,120,117,111,115,115,112,105,102,106,112,113,111,102, 92, 78, + 64, 66, 79, 89, 96,102,104,105,105,105,102, 96, 85, 71, 50, 23, 1, + 0, 8, 19, 27, 33, 37, 45, 54, 72, 86, 99,108,113,111,105, 98,106, +117,132,150,167,177,177,169,179,183,175,156,132,112, 94, 83, 84, 87, + 88, 89, 88, 84, 78, 68, 55, 47, 53, 56, 56, 58, 62, 67, 74, 82, 88, + 93, 95, 95, 93, 92, 92, 92, 91, 90, 88, 83, 76, 65, 54, 46, 46, 45, + 41, 36, 25, 12, 9, 18, 22, 21, 14, 8, 3, 22, 39, 51, 54, 52, 44, + 31, 19, 20, 25, 25, 31, 39, 45, 45, 40, 29, 26, 26, 47, 63, 73, 75, + 74, 67, 58, 66, 70, 68, 61, 48, 33, 32, 25, 25, 27, 27, 32, 39, 45, + 48, 50, 53, 54, 54, 48, 48, 46, 44, 41, 41, 43, 50, 53, 54, 54, 56, + 63, 70, 74, 75, 75, 73, 68, 63, 56, 47, 36, 25, 21, 23, 23, 21, 19, + 19, 23, 34, 44, 48, 51, 48, 45, 50, 60, 69, 75, 80, 84, 88, 92, 96, + 98,100,102,101,107,114,124,133,142,147,147,140,132,123,113,102, 89, + 82, 75, 68, 66, 75, 82, 87, 89, 89, 88, 85, 91, 92, 93, 92, 91, 88, + 85, 86, 92, 97,100,101,102,102, 99,103,110,117,121,124,132,137,139, +133,123,124,124,120,112,102, 99, 96, 92, 89, 91, 96, 99, 99, 95, 87, + 76, 63, 64, 79, 89, 98,104,108,109,108,106,102, 94, 84, 69, 51, 28, + 8, 1, 11, 19, 23, 27, 33, 41, 58, 73, 86, 97,106,111,111,107,103, +111,122,136,150,161,163,159,161,169,169,159,140,122,105, 90, 85, 87, + 89, 90, 90, 88, 84, 77, 69, 57, 45, 51, 57, 62, 67, 72, 76, 81, 87, + 91, 95, 96, 97, 97, 97, 97, 96, 95, 92, 88, 81, 74, 64, 55, 50, 46, + 44, 39, 32, 22, 11, 0, 3, 7, 8, 6, 2, 13, 33, 48, 58, 61, 58, + 50, 38, 25, 22, 19, 26, 38, 47, 54, 56, 52, 40, 38, 34, 51, 68, 78, + 81, 80, 75, 65, 66, 71, 71, 66, 56, 44, 43, 38, 37, 38, 41, 45, 48, + 51, 48, 46, 47, 48, 50, 56, 59, 59, 57, 54, 53, 54, 56, 59, 62, 63, + 60, 60, 67, 72, 75, 77, 77, 75, 74, 70, 64, 57, 47, 37, 27, 28, 29, + 29, 31, 32, 38, 47, 53, 55, 55, 53, 51, 61, 71, 77, 81, 83, 84, 87, + 88, 91, 93, 95,103,112,118,123,127,128,128,124,121,114,110,102, 91, + 79, 68, 63, 57, 68, 76, 79, 81, 81, 80, 79, 83, 85, 85, 84, 83, 80, + 78, 76, 79, 86, 91, 96, 99,101, 99, 98,103,108,113,119,128,137,143, +143,137,127,125,124,121,113,102, 90, 81, 79, 78, 74, 79, 84, 86, 84, + 79, 71, 62, 62, 78, 89, 99,105,108,108,105,102, 95, 87, 76, 62, 45, + 27, 12, 3, 11, 16, 19, 22, 29, 46, 61, 74, 84, 93,100,104,106,104, +103,112,123,134,145,150,149,142,150,156,152,140,124,110, 96, 84, 86, + 88, 90, 90, 88, 85, 80, 74, 67, 58, 47, 52, 60, 67, 73, 78, 81, 84, + 88, 90, 92, 95, 96, 98,100,101, 99, 96, 91, 84, 78, 70, 61, 55, 52, + 51, 47, 43, 34, 23, 11, 0, 0, 0, 0, 0, 4, 21, 40, 55, 63, 65, + 62, 56, 45, 33, 25, 21, 29, 43, 54, 60, 62, 57, 46, 46, 40, 56, 73, + 82, 85, 84, 79, 70, 67, 72, 72, 69, 61, 52, 48, 46, 47, 50, 52, 53, + 54, 51, 45, 40, 38, 44, 53, 60, 65, 67, 65, 61, 60, 60, 63, 66, 69, + 71, 69, 63, 61, 67, 72, 74, 77, 78, 77, 76, 74, 70, 63, 55, 44, 33, + 33, 37, 39, 41, 40, 47, 53, 55, 57, 56, 54, 62, 71, 77, 79, 80, 79, + 79, 79, 80, 84, 93,102,110,114,114,113,111,107,103,101, 97, 94, 88, + 79, 64, 50, 45, 55, 66, 72, 73, 71, 69, 71, 76, 79, 79, 76, 74, 75, + 74, 73, 71, 74, 81, 88, 93, 96, 96, 95,100,105,110,113,121,130,140, +147,147,140,129,122,122,119,111,102, 90, 79, 67, 63, 62, 60, 67, 71, + 72, 69, 63, 60, 61, 76, 88, 96,102,102,101, 97, 92, 84, 74, 62, 48, + 34, 21, 9, 5, 7, 11, 13, 19, 31, 50, 63, 72, 79, 86, 92, 95, 97, + 96, 98,108,119,129,136,139,134,127,136,139,132,122,109, 96, 84, 81, + 84, 88, 89, 88, 86, 82, 76, 74, 69, 60, 52, 48, 59, 68, 74, 79, 83, + 84, 84, 85, 87, 88, 92, 95, 98, 99, 97, 92, 87, 79, 72, 67, 58, 54, + 53, 53, 50, 44, 34, 22, 8, 0, 0, 0, 0, 0, 7, 25, 43, 56, 64, + 66, 64, 59, 51, 41, 33, 29, 33, 47, 57, 62, 63, 58, 50, 47, 43, 63, + 77, 85, 88, 85, 79, 71, 67, 72, 72, 69, 63, 55, 50, 50, 52, 55, 57, + 57, 55, 50, 40, 32, 33, 43, 53, 61, 68, 71, 68, 64, 62, 67, 71, 71, + 74, 75, 74, 70, 65, 65, 65, 69, 72, 74, 76, 77, 78, 77, 73, 66, 56, + 44, 36, 39, 44, 46, 46, 43, 48, 51, 54, 55, 53, 63, 72, 76, 78, 75, + 72, 72, 72, 69, 78, 88, 96,103,105,102, 97, 92, 92, 89, 84, 79, 77, + 72, 61, 46, 26, 37, 50, 59, 62, 60, 56, 64, 71, 74, 74, 70, 67, 71, + 73, 73, 72, 70, 70, 76, 82, 87, 90, 90, 95,100,105,109,113,120,129, +139,145,145,139,128,117,117,113,107, 98, 88, 78, 68, 60, 53, 43, 46, + 53, 56, 56, 57, 57, 60, 75, 85, 92, 95, 94, 90, 85, 78, 68, 55, 41, + 28, 19, 11, 8, 5, 1, 3, 8, 15, 32, 51, 61, 68, 74, 78, 81, 84, + 85, 85, 89, 99,109,119,124,125,122,114,122,122,115,105, 94, 84, 74, + 78, 82, 85, 87, 85, 82, 77, 77, 75, 69, 61, 52, 44, 53, 63, 71, 77, + 79, 79, 79, 78, 82, 83, 84, 88, 92, 94, 92, 88, 80, 73, 71, 67, 58, + 52, 53, 54, 51, 45, 33, 20, 5, 0, 0, 0, 0, 0, 9, 22, 40, 53, + 61, 64, 63, 59, 54, 46, 39, 37, 37, 47, 57, 61, 60, 54, 47, 46, 53, + 70, 81, 87, 87, 84, 77, 68, 68, 71, 70, 67, 61, 54, 45, 47, 52, 56, + 58, 58, 54, 46, 34, 34, 41, 46, 52, 61, 69, 72, 69, 65, 72, 76, 78, + 77, 74, 76, 75, 73, 68, 67, 68, 67, 63, 67, 70, 74, 76, 78, 76, 71, + 61, 50, 36, 40, 46, 48, 47, 41, 38, 41, 46, 48, 54, 64, 72, 74, 74, + 70, 64, 68, 69, 72, 76, 79, 88, 93, 94, 88, 88, 91, 90, 86, 77, 64, + 55, 50, 39, 23, 22, 29, 39, 46, 47, 43, 55, 64, 69, 70, 66, 60, 57, + 63, 67, 68, 67, 66, 64, 67, 73, 78, 80, 86, 92, 96,101,104,109,114, +122,130,137,137,133,123,111,111,107,101, 93, 84, 74, 65, 59, 54, 45, + 41, 45, 50, 52, 53, 52, 60, 73, 81, 85, 85, 82, 76, 69, 59, 53, 51, + 45, 34, 19, 5, 5, 3, 0, 0, 5, 13, 29, 47, 57, 62, 69, 75, 78, + 77, 72, 71, 78, 88, 98,107,113,114,112,105,107,106,100, 92, 83, 78, + 80, 83, 79, 84, 84, 83, 79, 74, 74, 73, 66, 57, 48, 41, 41, 54, 63, + 69, 73, 72, 79, 87, 91, 92, 88, 82, 84, 86, 84, 80, 74, 69, 68, 63, + 55, 50, 53, 53, 51, 43, 29, 15, 0, 0, 0, 0, 3, 8, 12, 22, 32, + 46, 54, 58, 58, 56, 52, 46, 41, 38, 39, 45, 54, 57, 55, 47, 43, 45, + 63, 76, 84, 87, 84, 79, 71, 65, 68, 69, 67, 62, 55, 48, 34, 39, 45, + 52, 56, 56, 53, 44, 32, 40, 50, 56, 59, 62, 69, 72, 68, 74, 79, 83, + 84, 82, 79, 74, 71, 69, 66, 63, 66, 69, 69, 66, 61, 66, 72, 74, 74, + 69, 60, 47, 34, 40, 45, 46, 45, 39, 29, 27, 32, 44, 56, 66, 72, 74, + 71, 65, 56, 61, 62, 72, 77, 79, 80, 83, 81, 84, 87, 88, 84, 78, 66, + 48, 27, 22, 20, 22, 22, 21, 27, 31, 29, 40, 52, 60, 63, 63, 58, 50, + 41, 50, 54, 56, 57, 55, 54, 54, 57, 64, 72, 79, 84, 89, 92, 96, 98, +103,110,117,122,123,120,113,102,103,100, 94, 87, 78, 68, 60, 53, 48, + 43, 44, 45, 47, 47, 47, 44, 58, 69, 75, 77, 74, 67, 58, 48, 50, 52, + 51, 50, 44, 33, 19, 4, 2, 0, 0, 3, 14, 25, 39, 50, 62, 73, 79, + 82, 79, 74, 64, 63, 75, 87, 96,102,105,103, 98, 92, 91, 86, 80, 77, + 78, 83, 84, 79, 82, 83, 81, 77, 71, 66, 64, 57, 55, 48, 40, 29, 38, + 50, 58, 62, 74, 84, 92, 96, 96, 91, 84, 75, 78, 76, 72, 66, 62, 60, + 55, 46, 50, 53, 53, 48, 39, 25, 11, 3, 5, 4, 2, 13, 20, 23, 25, + 25, 34, 44, 48, 51, 50, 45, 40, 36, 34, 36, 39, 48, 52, 50, 41, 39, + 56, 71, 80, 85, 85, 80, 73, 63, 66, 67, 66, 61, 54, 45, 38, 37, 39, + 38, 47, 53, 54, 52, 45, 32, 41, 53, 60, 65, 68, 71, 74, 77, 81, 85, + 88, 88, 86, 83, 79, 76, 72, 64, 58, 58, 63, 66, 66, 63, 59, 65, 68, + 67, 62, 54, 41, 31, 37, 40, 41, 39, 33, 25, 19, 31, 43, 55, 64, 69, + 69, 65, 57, 47, 52, 58, 69, 75, 79, 79, 79, 79, 79, 80, 79, 74, 64, + 48, 28, 11, 12, 16, 18, 18, 16, 16, 18, 22, 31, 41, 48, 52, 50, 44, + 36, 28, 31, 37, 39, 40, 39, 47, 55, 59, 61, 64, 69, 74, 81, 88, 93, + 99,101, 99,102,107,109,107,101, 92, 93, 90, 85, 77, 69, 68, 65, 60, + 54, 51, 50, 48, 47, 46, 43, 39, 52, 60, 64, 62, 57, 47, 47, 54, 58, + 62, 64, 62, 56, 44, 28, 12, 3, 0, 0, 2, 15, 28, 41, 55, 67, 76, + 81, 82, 79, 72, 61, 61, 63, 75, 86, 93, 96, 96, 93, 88, 82, 78, 74, + 73, 79, 83, 82, 78, 80, 80, 79, 74, 70, 64, 60, 58, 57, 52, 45, 36, + 31, 40, 52, 63, 76, 86, 92, 96, 94, 88, 79, 71, 70, 69, 65, 60, 54, + 48, 46, 47, 51, 53, 52, 46, 34, 21, 16, 22, 22, 21, 15, 21, 31, 36, + 38, 38, 38, 44, 48, 50, 51, 51, 50, 47, 41, 34, 29, 40, 46, 45, 38, + 47, 62, 75, 83, 85, 83, 76, 65, 63, 65, 65, 61, 55, 46, 36, 31, 32, + 36, 34, 44, 51, 54, 52, 45, 33, 40, 54, 63, 70, 75, 79, 81, 84, 87, + 89, 90, 89, 86, 83, 79, 76, 74, 67, 57, 46, 51, 57, 59, 58, 53, 56, + 58, 57, 52, 44, 33, 23, 27, 31, 32, 31, 26, 20, 21, 23, 36, 48, 57, + 60, 60, 54, 45, 40, 45, 55, 66, 73, 75, 76, 74, 71, 70, 68, 65, 57, + 45, 29, 21, 12, 7, 11, 12, 11, 14, 16, 20, 25, 32, 37, 39, 36, 27, + 22, 15, 9, 14, 19, 21, 25, 36, 45, 52, 56, 59, 63, 68, 74, 81, 88, + 94, 97, 97, 94, 88, 93, 96, 95, 90, 83, 79, 76, 71, 66, 67, 69, 69, + 65, 60, 57, 55, 53, 50, 46, 41, 37, 39, 45, 45, 45, 45, 54, 64, 70, + 73, 74, 73, 69, 60, 48, 33, 16, 5, 0, 0, 0, 15, 31, 46, 59, 70, + 78, 80, 79, 75, 66, 54, 54, 56, 63, 74, 83, 88, 89, 88, 84, 79, 74, + 69, 74, 79, 81, 80, 75, 76, 75, 73, 69, 65, 61, 59, 59, 58, 54, 47, + 39, 31, 36, 48, 62, 75, 84, 91, 92, 88, 81, 72, 62, 63, 62, 59, 54, + 50, 46, 45, 48, 52, 53, 50, 40, 31, 25, 36, 40, 39, 36, 29, 25, 36, + 43, 47, 48, 45, 52, 55, 57, 58, 58, 58, 57, 53, 45, 38, 38, 41, 41, + 38, 52, 67, 78, 84, 85, 81, 72, 58, 60, 61, 60, 56, 48, 39, 28, 23, + 22, 27, 32, 41, 50, 53, 51, 45, 33, 38, 53, 64, 73, 79, 83, 85, 88, + 89, 90, 88, 86, 82, 78, 74, 73, 72, 67, 59, 48, 38, 40, 46, 47, 44, + 46, 45, 43, 38, 31, 23, 16, 14, 16, 19, 20, 19, 16, 18, 21, 23, 36, + 45, 48, 46, 40, 29, 34, 38, 52, 62, 68, 70, 69, 64, 59, 54, 50, 44, + 34, 29, 27, 21, 12, 5, 15, 22, 27, 28, 32, 33, 32, 38, 40, 40, 34, + 25, 12, 0, 0, 0, 2, 7, 18, 28, 38, 46, 50, 52, 57, 64, 72, 79, + 85, 90, 93, 91, 85, 77, 80, 84, 83, 79, 71, 63, 58, 57, 59, 62, 66, + 68, 66, 62, 60, 57, 54, 50, 44, 39, 34, 31, 27, 29, 43, 56, 68, 77, + 81, 82, 80, 77, 70, 60, 47, 33, 19, 7, 0, 0, 1, 11, 29, 46, 60, + 71, 76, 78, 74, 67, 56, 43, 43, 47, 50, 61, 70, 76, 79, 80, 78, 74, + 69, 70, 74, 78, 79, 78, 74, 69, 66, 62, 59, 56, 55, 55, 56, 55, 52, + 46, 38, 32, 26, 40, 56, 71, 80, 85, 85, 80, 71, 59, 56, 57, 55, 52, + 47, 44, 41, 43, 46, 51, 51, 45, 37, 32, 40, 52, 55, 52, 46, 38, 27, + 33, 43, 50, 53, 51, 54, 58, 60, 61, 61, 62, 62, 59, 52, 47, 45, 44, + 41, 40, 54, 68, 79, 84, 84, 79, 67, 52, 55, 55, 54, 50, 41, 32, 21, + 14, 9, 18, 28, 39, 47, 51, 50, 44, 33, 34, 51, 63, 73, 79, 83, 85, + 88, 88, 86, 83, 79, 74, 70, 66, 66, 66, 64, 59, 51, 38, 32, 32, 33, + 34, 32, 28, 25, 20, 26, 31, 32, 28, 21, 16, 8, 11, 13, 13, 15, 18, + 21, 29, 33, 31, 25, 22, 27, 31, 46, 57, 62, 62, 58, 51, 41, 33, 26, + 18, 20, 23, 23, 21, 23, 26, 33, 39, 41, 44, 46, 46, 40, 40, 40, 38, + 31, 20, 8, 1, 0, 0, 0, 0, 7, 19, 28, 36, 38, 40, 47, 55, 63, + 72, 79, 83, 84, 79, 71, 60, 66, 70, 69, 64, 55, 47, 43, 43, 45, 51, + 57, 61, 61, 59, 57, 54, 51, 45, 40, 34, 29, 27, 25, 38, 54, 67, 78, + 84, 88, 86, 82, 76, 67, 56, 44, 31, 21, 8, 2, 6, 9, 9, 23, 43, + 58, 68, 73, 72, 66, 56, 43, 28, 27, 34, 38, 44, 53, 61, 67, 70, 70, + 67, 63, 68, 72, 74, 74, 73, 70, 66, 60, 53, 47, 53, 57, 60, 61, 56, + 45, 38, 32, 26, 21, 26, 45, 62, 73, 77, 76, 70, 58, 44, 48, 48, 45, + 41, 38, 34, 33, 36, 40, 45, 44, 38, 37, 34, 51, 61, 62, 57, 50, 40, + 29, 22, 34, 44, 50, 47, 52, 56, 58, 59, 60, 60, 61, 60, 54, 53, 50, + 46, 43, 40, 53, 67, 78, 83, 82, 76, 63, 46, 46, 46, 45, 41, 34, 26, + 16, 9, 5, 14, 25, 36, 44, 47, 46, 40, 31, 29, 46, 59, 68, 75, 79, + 81, 82, 81, 78, 73, 67, 61, 57, 54, 55, 58, 58, 56, 50, 39, 25, 23, + 23, 21, 16, 13, 15, 25, 32, 40, 45, 45, 40, 31, 18, 9, 8, 12, 13, + 13, 15, 14, 19, 16, 11, 14, 18, 23, 38, 48, 53, 52, 45, 34, 22, 11, + 1, 4, 11, 18, 32, 40, 43, 44, 51, 54, 54, 56, 57, 56, 50, 41, 39, + 34, 26, 15, 12, 9, 6, 0, 0, 0, 0, 8, 16, 21, 22, 25, 32, 40, + 51, 59, 66, 70, 68, 61, 50, 45, 51, 53, 51, 44, 34, 26, 21, 21, 26, + 36, 46, 54, 56, 55, 52, 46, 40, 36, 31, 26, 22, 20, 26, 44, 60, 73, + 82, 87, 88, 86, 79, 71, 63, 59, 51, 39, 26, 9, 13, 21, 27, 28, 23, + 36, 53, 62, 65, 63, 55, 43, 27, 13, 11, 21, 28, 31, 32, 40, 48, 54, + 57, 56, 57, 61, 64, 66, 67, 66, 65, 63, 59, 61, 62, 59, 63, 69, 72, + 68, 58, 43, 22, 14, 11, 11, 28, 48, 60, 65, 64, 57, 44, 34, 39, 38, + 33, 29, 25, 21, 21, 23, 29, 34, 34, 32, 33, 41, 57, 65, 65, 58, 48, + 38, 26, 16, 18, 31, 38, 37, 43, 48, 51, 52, 52, 53, 55, 55, 56, 55, + 52, 46, 46, 41, 50, 65, 75, 81, 80, 74, 59, 40, 34, 34, 34, 37, 36, + 29, 20, 8, 0, 8, 19, 29, 38, 43, 41, 37, 28, 25, 39, 52, 61, 67, + 70, 71, 72, 70, 65, 58, 51, 45, 45, 43, 43, 48, 52, 52, 47, 38, 23, + 12, 11, 7, 5, 15, 31, 41, 46, 47, 55, 58, 55, 46, 33, 20, 12, 9, + 12, 8, 12, 11, 6, 6, 1, 4, 7, 14, 27, 37, 41, 39, 31, 18, 9, + 0, 0, 0, 12, 31, 46, 54, 56, 58, 64, 65, 63, 63, 63, 61, 55, 46, + 39, 32, 31, 33, 34, 32, 25, 13, 7, 6, 1, 0, 3, 6, 6, 15, 20, + 22, 32, 40, 47, 48, 45, 34, 23, 31, 34, 33, 27, 19, 9, 7, 9, 14, + 21, 31, 41, 50, 53, 54, 52, 47, 39, 27, 16, 13, 11, 9, 26, 46, 62, + 74, 82, 85, 85, 81, 74, 76, 75, 70, 59, 44, 27, 12, 25, 38, 46, 48, + 44, 36, 44, 54, 56, 52, 41, 28, 15, 7, 1, 8, 19, 25, 27, 23, 26, + 34, 40, 40, 45, 51, 53, 55, 56, 57, 58, 58, 64, 73, 76, 74, 68, 74, + 77, 74, 65, 51, 31, 11, 0, 0, 9, 29, 45, 52, 51, 44, 31, 23, 27, + 25, 25, 22, 19, 14, 8, 8, 15, 21, 22, 23, 28, 45, 59, 65, 63, 55, + 46, 43, 32, 14, 2, 11, 19, 19, 29, 34, 37, 38, 38, 40, 44, 51, 55, + 54, 51, 50, 51, 45, 45, 60, 72, 78, 77, 70, 56, 36, 21, 23, 32, 36, + 36, 31, 20, 8, 0, 0, 11, 21, 29, 34, 36, 31, 23, 26, 31, 43, 51, + 55, 56, 56, 56, 54, 48, 41, 43, 44, 44, 40, 32, 38, 44, 46, 43, 34, + 19, 3, 0, 0, 7, 28, 45, 55, 59, 58, 61, 65, 64, 57, 45, 29, 20, + 9, 7, 5, 11, 12, 8, 2, 0, 0, 0, 2, 14, 23, 27, 25, 16, 3, + 0, 0, 0, 4, 25, 44, 57, 64, 65, 71, 75, 74, 71, 66, 66, 63, 56, + 47, 44, 47, 51, 54, 54, 51, 41, 29, 29, 27, 20, 8, 0, 0, 0, 4, + 9, 11, 11, 18, 22, 22, 16, 6, 13, 16, 16, 12, 9, 5, 2, 1, 6, + 15, 21, 23, 31, 39, 44, 46, 45, 41, 34, 23, 11, 0, 0, 2, 21, 43, + 60, 72, 78, 80, 79, 75, 82, 84, 82, 74, 61, 44, 25, 21, 39, 54, 63, + 66, 62, 53, 48, 50, 46, 40, 29, 16, 11, 2, 0, 0, 11, 20, 25, 23, + 19, 13, 21, 23, 28, 34, 38, 45, 51, 50, 48, 55, 70, 81, 87, 87, 83, + 75, 79, 76, 68, 54, 36, 16, 2, 0, 0, 12, 27, 37, 38, 32, 21, 11, + 20, 25, 25, 22, 18, 12, 5, 0, 1, 7, 9, 14, 28, 45, 56, 61, 58, + 56, 60, 59, 51, 33, 11, 0, 0, 4, 14, 19, 21, 22, 22, 25, 37, 47, + 52, 52, 52, 56, 56, 50, 40, 56, 68, 74, 74, 66, 51, 29, 9, 19, 27, + 31, 31, 25, 14, 3, 0, 0, 0, 9, 20, 26, 27, 25, 19, 27, 32, 33, + 37, 39, 39, 40, 38, 45, 48, 54, 57, 56, 52, 43, 28, 33, 39, 41, 38, + 27, 12, 0, 0, 0, 18, 39, 55, 64, 68, 66, 62, 67, 67, 62, 53, 39, + 22, 12, 0, 7, 14, 18, 15, 9, 0, 0, 0, 0, 1, 9, 14, 13, 6, + 0, 0, 0, 5, 19, 38, 54, 65, 71, 71, 79, 82, 81, 76, 70, 63, 59, + 52, 60, 64, 65, 64, 65, 65, 61, 53, 53, 53, 51, 43, 29, 12, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 8, 7, 3, 0, 0, 2, + 12, 21, 28, 33, 34, 34, 33, 36, 36, 32, 26, 16, 4, 0, 0, 0, 13, + 34, 53, 65, 72, 74, 72, 79, 84, 86, 83, 74, 58, 37, 16, 33, 53, 67, + 75, 78, 74, 66, 55, 57, 52, 40, 26, 9, 2, 0, 0, 0, 6, 16, 23, + 23, 19, 12, 6, 9, 11, 19, 31, 40, 45, 44, 34, 55, 73, 85, 93, 96, + 92, 86, 78, 76, 69, 56, 47, 33, 18, 0, 0, 0, 15, 26, 29, 27, 22, + 20, 19, 23, 23, 25, 25, 21, 15, 4, 0, 0, 1, 8, 27, 41, 52, 55, + 52, 61, 67, 67, 60, 46, 23, 0, 0, 0, 3, 7, 9, 16, 21, 31, 36, + 46, 51, 54, 59, 61, 59, 51, 36, 52, 63, 70, 69, 60, 45, 22, 4, 12, + 19, 22, 20, 12, 2, 0, 0, 3, 2, 2, 5, 14, 18, 18, 18, 27, 33, + 34, 33, 29, 36, 45, 52, 56, 61, 65, 66, 64, 58, 48, 44, 46, 45, 41, + 33, 20, 5, 0, 0, 4, 26, 47, 62, 71, 74, 73, 69, 64, 65, 62, 55, + 45, 32, 20, 11, 14, 21, 25, 25, 19, 11, 1, 0, 0, 0, 0, 1, 2, + 0, 0, 0, 4, 18, 34, 51, 63, 72, 76, 77, 84, 85, 84, 79, 74, 66, + 60, 68, 74, 79, 80, 80, 79, 77, 75, 74, 74, 73, 69, 62, 50, 31, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 11, 11, 6, 7, 18, + 25, 29, 31, 37, 40, 43, 43, 43, 40, 37, 32, 23, 15, 6, 0, 0, 0, + 7, 28, 46, 58, 65, 66, 73, 79, 83, 83, 77, 65, 46, 23, 32, 47, 64, + 76, 84, 86, 83, 75, 66, 60, 56, 48, 36, 20, 7, 0, 0, 8, 22, 31, + 31, 25, 21, 14, 8, 7, 9, 14, 22, 31, 36, 36, 39, 57, 74, 88, 96, +101, 99, 93, 87, 80, 74, 66, 56, 43, 25, 5, 0, 0, 7, 20, 27, 32, + 33, 33, 32, 33, 36, 37, 36, 32, 25, 13, 0, 0, 4, 13, 23, 37, 45, + 48, 53, 63, 69, 70, 64, 52, 31, 6, 0, 0, 4, 12, 20, 29, 40, 48, + 52, 55, 60, 64, 67, 66, 62, 53, 38, 46, 58, 64, 63, 54, 37, 15, 0, + 2, 6, 7, 5, 3, 0, 0, 18, 23, 22, 15, 9, 11, 6, 8, 14, 26, + 33, 36, 36, 32, 43, 54, 62, 68, 73, 74, 74, 70, 62, 55, 57, 58, 57, + 52, 41, 27, 12, 7, 9, 14, 32, 52, 67, 75, 79, 78, 74, 68, 61, 58, + 53, 45, 36, 26, 19, 20, 27, 31, 31, 26, 18, 9, 3, 0, 0, 0, 0, + 1, 4, 7, 12, 20, 32, 46, 59, 70, 78, 82, 82, 86, 88, 85, 81, 75, + 69, 70, 76, 82, 86, 89, 91, 92, 91, 90, 89, 88, 86, 82, 74, 61, 44, + 22, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 15, 18, 15, 16, 32, + 44, 51, 54, 55, 53, 47, 50, 50, 50, 50, 45, 39, 29, 19, 12, 12, 12, + 12, 9, 25, 41, 53, 58, 63, 72, 77, 79, 75, 66, 51, 29, 31, 46, 59, + 73, 83, 89, 91, 88, 83, 74, 65, 55, 47, 38, 27, 18, 9, 11, 27, 40, + 48, 48, 41, 27, 18, 13, 12, 13, 15, 20, 25, 31, 36, 44, 62, 79, 91, + 99,103,103, 99, 93, 88, 81, 73, 61, 46, 26, 6, 0, 0, 8, 20, 28, + 36, 39, 40, 41, 43, 44, 44, 41, 36, 26, 14, 1, 1, 8, 18, 25, 32, + 38, 44, 55, 64, 70, 71, 66, 54, 37, 25, 16, 16, 21, 29, 40, 51, 59, + 65, 68, 70, 73, 75, 75, 73, 67, 55, 39, 39, 51, 57, 55, 46, 31, 11, + 0, 0, 0, 1, 5, 4, 8, 14, 37, 43, 40, 34, 25, 19, 16, 8, 8, + 22, 32, 38, 39, 37, 45, 59, 69, 75, 80, 81, 79, 74, 64, 63, 66, 67, + 64, 58, 47, 34, 19, 19, 21, 23, 33, 53, 67, 76, 81, 80, 77, 71, 62, + 52, 48, 41, 34, 27, 22, 23, 31, 33, 32, 27, 21, 14, 11, 5, 0, 0, + 0, 7, 14, 20, 26, 32, 44, 57, 67, 74, 82, 87, 88, 88, 88, 86, 81, + 77, 72, 75, 80, 85, 89, 93, 96, 99,101,101,100, 98, 95, 89, 81, 68, + 51, 29, 12, 9, 6, 2, 0, 0, 0, 0, 0, 5, 14, 20, 22, 20, 37, + 53, 63, 69, 72, 72, 70, 66, 61, 57, 54, 54, 51, 43, 38, 33, 29, 27, + 27, 26, 23, 28, 39, 48, 52, 59, 67, 72, 71, 65, 53, 34, 22, 44, 57, + 66, 76, 84, 90, 92, 91, 86, 79, 71, 60, 46, 37, 29, 22, 18, 27, 43, + 55, 61, 60, 54, 40, 23, 15, 13, 13, 14, 18, 22, 28, 39, 53, 68, 81, + 92,100,104,105,102, 98, 92, 86, 76, 63, 46, 25, 6, 0, 0, 6, 15, + 25, 32, 37, 41, 45, 47, 47, 45, 40, 33, 22, 11, 0, 3, 12, 22, 29, + 34, 34, 44, 55, 63, 68, 69, 65, 59, 50, 40, 34, 34, 40, 48, 57, 66, + 73, 77, 79, 81, 84, 84, 83, 79, 71, 58, 39, 37, 41, 47, 46, 38, 23, + 6, 0, 0, 0, 1, 7, 16, 25, 32, 50, 56, 54, 48, 39, 31, 27, 21, + 20, 22, 29, 39, 43, 41, 43, 59, 72, 79, 84, 86, 84, 77, 66, 67, 71, + 71, 68, 61, 51, 38, 25, 27, 27, 28, 34, 51, 65, 74, 79, 79, 76, 69, + 60, 50, 39, 33, 27, 22, 20, 25, 29, 31, 28, 23, 19, 14, 13, 11, 5, + 0, 2, 13, 22, 31, 36, 41, 58, 72, 80, 86, 88, 92, 95, 96, 95, 92, + 89, 85, 80, 82, 85, 86, 90, 94, 99,102,105,106,105,102, 98, 92, 83, + 70, 53, 33, 19, 18, 14, 8, 3, 2, 5, 8, 8, 8, 18, 23, 26, 33, + 50, 64, 74, 79, 82, 82, 80, 77, 74, 72, 71, 70, 67, 63, 57, 52, 46, + 41, 40, 41, 44, 45, 44, 45, 47, 52, 59, 63, 60, 52, 37, 18, 34, 54, + 63, 69, 76, 82, 87, 89, 88, 85, 79, 72, 61, 47, 31, 26, 22, 23, 40, + 54, 64, 69, 68, 61, 48, 31, 15, 12, 11, 11, 20, 29, 39, 50, 61, 74, + 83, 91, 97,101,102,102, 99, 95, 88, 77, 62, 43, 22, 12, 2, 0, 1, + 7, 14, 21, 28, 36, 41, 45, 45, 41, 36, 25, 14, 3, 0, 5, 16, 28, + 36, 39, 38, 48, 58, 65, 70, 72, 70, 65, 57, 50, 45, 47, 53, 60, 68, + 74, 80, 84, 87, 88, 90, 91, 88, 84, 75, 61, 40, 34, 32, 37, 34, 27, + 15, 1, 2, 3, 6, 13, 20, 29, 38, 45, 58, 63, 62, 57, 50, 41, 40, + 36, 33, 38, 40, 38, 45, 47, 45, 55, 69, 79, 85, 88, 85, 79, 68, 66, + 70, 70, 66, 59, 50, 39, 31, 32, 31, 29, 34, 45, 59, 69, 74, 75, 71, + 63, 54, 44, 31, 22, 16, 12, 12, 20, 23, 23, 20, 15, 11, 8, 11, 12, + 9, 6, 4, 16, 27, 37, 43, 54, 72, 84, 92, 96, 97, 96,101,103,103, +102, 98, 93, 88, 87, 90, 92, 91, 92, 96,101,104,105,103,100, 96, 90, + 81, 69, 53, 33, 25, 23, 20, 14, 7, 6, 11, 14, 15, 13, 20, 27, 32, + 40, 55, 69, 79, 84, 87, 87, 85, 83, 80, 79, 80, 81, 79, 76, 71, 65, + 59, 59, 60, 60, 61, 60, 57, 50, 41, 40, 48, 51, 47, 37, 21, 19, 41, + 58, 65, 67, 72, 75, 79, 81, 81, 79, 75, 68, 58, 45, 28, 18, 16, 32, + 46, 58, 67, 71, 70, 63, 51, 32, 15, 7, 5, 16, 28, 38, 47, 56, 66, + 76, 83, 88, 92, 95, 96, 97, 96, 93, 86, 75, 59, 38, 23, 15, 5, 0, + 0, 0, 1, 7, 15, 25, 33, 38, 38, 34, 26, 15, 4, 0, 1, 8, 21, + 34, 43, 46, 45, 52, 61, 67, 72, 73, 70, 65, 58, 52, 50, 52, 58, 65, + 72, 78, 83, 86, 88, 91, 93, 93, 92, 86, 77, 63, 41, 32, 26, 25, 23, + 16, 6, 11, 15, 20, 22, 23, 31, 39, 46, 53, 62, 67, 67, 62, 56, 51, + 52, 48, 44, 51, 56, 57, 54, 51, 51, 47, 62, 74, 82, 86, 84, 79, 68, + 59, 64, 64, 60, 54, 46, 37, 33, 34, 31, 34, 33, 37, 51, 60, 66, 67, + 61, 52, 43, 34, 25, 14, 3, 0, 6, 14, 15, 14, 9, 4, 1, 0, 4, + 8, 9, 8, 8, 18, 31, 40, 46, 64, 81, 94,102,107,106,102,105,109, +111,110,105,100, 94, 89, 92, 95, 95, 92, 92, 96, 98, 98, 96, 93, 89, + 84, 77, 66, 51, 33, 27, 27, 22, 16, 9, 7, 13, 16, 18, 16, 22, 32, + 38, 41, 54, 67, 78, 84, 86, 86, 85, 84, 83, 83, 85, 88, 88, 85, 81, + 75, 70, 74, 74, 74, 74, 73, 68, 59, 45, 31, 33, 36, 31, 21, 8, 23, + 44, 58, 62, 61, 62, 64, 66, 68, 70, 69, 65, 58, 50, 38, 25, 9, 20, + 34, 47, 58, 66, 69, 67, 60, 47, 29, 12, 0, 9, 23, 36, 45, 53, 59, + 68, 75, 79, 83, 87, 89, 88, 90, 91, 88, 82, 71, 55, 34, 22, 14, 4, + 0, 0, 0, 0, 1, 2, 9, 20, 26, 27, 22, 14, 4, 0, 2, 6, 11, + 27, 41, 51, 55, 53, 52, 61, 67, 71, 71, 67, 62, 55, 48, 47, 52, 59, + 65, 72, 77, 81, 84, 86, 89, 92, 93, 92, 87, 78, 63, 41, 28, 20, 15, + 12, 5, 12, 19, 28, 36, 38, 39, 40, 44, 51, 58, 67, 69, 69, 66, 60, + 61, 62, 59, 53, 61, 68, 72, 72, 65, 53, 48, 53, 66, 77, 82, 81, 76, + 66, 53, 53, 53, 50, 44, 38, 33, 36, 34, 34, 40, 40, 38, 41, 51, 55, + 55, 47, 37, 29, 22, 15, 8, 0, 0, 0, 6, 6, 3, 0, 0, 0, 0, + 0, 2, 6, 7, 9, 19, 32, 43, 50, 70, 88,102,112,115,113,109,107, +113,115,114,111,104, 97, 92, 92, 94, 95, 94, 92, 88, 89, 89, 86, 84, + 80, 77, 71, 61, 50, 34, 27, 26, 23, 18, 12, 9, 14, 18, 16, 14, 26, + 37, 46, 52, 54, 61, 74, 79, 83, 84, 83, 83, 83, 84, 88, 91, 92, 92, + 88, 84, 80, 83, 83, 82, 81, 79, 75, 66, 52, 31, 18, 20, 15, 7, 9, + 26, 44, 54, 56, 52, 57, 60, 58, 54, 53, 53, 50, 44, 37, 28, 20, 23, + 25, 33, 43, 53, 60, 63, 61, 54, 40, 22, 5, 0, 14, 27, 38, 46, 53, + 58, 65, 72, 77, 87, 93, 96, 93, 87, 84, 82, 76, 66, 51, 31, 18, 9, + 1, 0, 0, 0, 1, 6, 6, 3, 6, 13, 14, 11, 4, 0, 0, 5, 8, + 15, 33, 48, 58, 62, 61, 56, 59, 65, 67, 66, 62, 56, 48, 43, 41, 51, + 60, 65, 67, 73, 76, 79, 81, 84, 88, 90, 90, 85, 77, 62, 39, 26, 14, + 7, 3, 7, 16, 27, 38, 47, 51, 51, 55, 59, 60, 61, 72, 75, 72, 69, + 67, 69, 70, 67, 60, 69, 77, 82, 83, 78, 68, 53, 40, 57, 69, 75, 76, + 72, 62, 48, 36, 37, 34, 31, 29, 33, 36, 36, 32, 39, 41, 39, 36, 40, + 44, 41, 32, 31, 22, 11, 4, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 7, 19, 33, 45, 51, 72, 89,104,115,121,119,113, +107,113,117,115,112,105, 98, 94, 92, 94, 94, 92, 92, 88, 85, 80, 76, + 73, 71, 69, 65, 59, 48, 36, 22, 25, 25, 23, 21, 19, 19, 21, 20, 26, + 33, 43, 53, 59, 62, 65, 67, 75, 79, 82, 87, 91, 92, 92, 89, 93, 96, + 97, 96, 93, 90, 87, 85, 84, 84, 82, 77, 69, 54, 33, 8, 6, 4, 2, + 13, 25, 40, 48, 48, 56, 61, 63, 61, 55, 46, 37, 28, 23, 20, 26, 32, + 37, 39, 39, 38, 46, 54, 56, 54, 46, 32, 14, 0, 0, 14, 26, 36, 41, + 46, 51, 58, 71, 83, 92, 97, 98, 95, 88, 76, 75, 71, 61, 47, 29, 12, + 5, 1, 1, 3, 3, 5, 7, 6, 2, 0, 3, 4, 2, 0, 0, 0, 3, + 5, 21, 39, 55, 65, 69, 68, 63, 56, 62, 64, 62, 57, 50, 41, 36, 37, + 51, 60, 65, 66, 67, 71, 74, 76, 79, 84, 86, 86, 83, 74, 59, 36, 23, + 8, 2, 0, 12, 22, 36, 46, 55, 61, 68, 74, 76, 76, 75, 84, 81, 79, + 76, 74, 75, 75, 73, 68, 76, 84, 88, 89, 84, 75, 62, 46, 46, 56, 63, + 64, 61, 52, 40, 28, 22, 21, 23, 27, 31, 33, 34, 31, 34, 38, 37, 33, + 32, 31, 28, 28, 26, 16, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 18, 33, 45, 53, 69, 88,102,114,121,121, +117,111,111,113,112,108,102,103,104,103,101, 97, 99,100, 98, 96, 92, + 88, 81, 71, 69, 68, 65, 60, 51, 39, 27, 26, 27, 28, 29, 31, 33, 38, + 45, 51, 54, 56, 62, 66, 68, 72, 76, 83, 88, 94, 98,101,100, 97, 97, +102,103,104,102,101, 98, 97, 94, 86, 79, 75, 68, 55, 34, 9, 0, 0, + 2, 14, 25, 36, 43, 51, 57, 61, 61, 58, 52, 41, 32, 26, 28, 27, 34, + 41, 47, 51, 52, 50, 43, 43, 46, 44, 37, 23, 8, 0, 0, 6, 16, 25, + 29, 34, 51, 64, 75, 85, 92, 96, 96, 91, 83, 72, 71, 65, 57, 45, 29, + 19, 18, 15, 15, 15, 14, 12, 9, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 12, 28, 46, 60, 69, 72, 71, 66, 60, 60, 62, 59, 54, 46, 46, 47, + 54, 61, 65, 68, 68, 65, 70, 77, 82, 83, 80, 84, 84, 80, 73, 57, 32, + 19, 1, 0, 3, 19, 40, 58, 67, 74, 79, 84, 88, 89, 88, 86, 95, 93, + 92, 91, 87, 81, 79, 74, 74, 81, 88, 92, 92, 88, 79, 67, 53, 48, 46, + 43, 44, 41, 34, 26, 18, 14, 14, 18, 21, 25, 27, 27, 25, 29, 34, 34, + 33, 29, 27, 26, 25, 21, 11, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 13, 29, 43, 50, 65, 84, 98,111,118, +120,117,113,113,112,112,112,113,113,113,112,109,103,108,111,113,112, +109,105, 97, 86, 73, 73, 73, 70, 64, 54, 44, 36, 29, 32, 38, 43, 48, + 55, 60, 65, 66, 65, 60, 63, 66, 71, 77, 84, 92, 97,102,104,104,101, +102,107,110,112,111,110,108,108,104, 94, 80, 72, 66, 55, 37, 13, 0, + 0, 0, 12, 23, 34, 43, 51, 56, 58, 57, 52, 43, 38, 39, 43, 45, 41, + 43, 51, 57, 60, 61, 60, 52, 37, 31, 29, 23, 14, 2, 0, 0, 0, 2, + 8, 19, 38, 56, 68, 77, 84, 88, 90, 88, 83, 74, 69, 67, 61, 53, 41, + 29, 31, 31, 29, 28, 27, 23, 16, 13, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 16, 32, 48, 61, 68, 71, 69, 64, 60, 60, 60, 57, 54, 54, 55, + 54, 65, 72, 74, 74, 74, 72, 74, 79, 84, 84, 81, 84, 84, 80, 73, 57, + 33, 8, 0, 0, 13, 39, 61, 76, 84, 88, 93, 96, 99, 99, 97, 94,104, +105,106,105,101, 93, 83, 76, 79, 85, 90, 93, 92, 87, 79, 68, 56, 47, + 40, 32, 21, 13, 11, 6, 3, 7, 11, 13, 14, 18, 19, 18, 15, 25, 31, + 32, 31, 28, 25, 22, 22, 19, 8, 0, 0, 0, 7, 12, 6, 0, 0, 0, + 0, 1, 3, 2, 0, 3, 2, 0, 0, 6, 22, 37, 45, 59, 79, 92,103, +111,113,114,114,115,118,120,121,122,121,119,117,113,110,117,122,127, +127,124,120,111, 98, 84, 75, 77, 76, 73, 65, 56, 48, 41, 36, 41, 51, + 59, 66, 72, 74, 74, 72, 65, 57, 60, 67, 75, 84, 92, 98,102,104,104, +102,107,111,113,115,115,114,113,113,110, 98, 84, 66, 61, 53, 38, 16, + 0, 0, 5, 16, 25, 31, 40, 48, 52, 52, 48, 43, 46, 48, 51, 54, 55, + 52, 48, 56, 62, 66, 67, 65, 57, 41, 23, 13, 9, 3, 0, 0, 0, 0, + 0, 8, 25, 41, 57, 67, 74, 79, 81, 80, 77, 71, 67, 66, 63, 56, 47, + 37, 36, 38, 39, 39, 38, 34, 28, 20, 14, 6, 0, 4, 4, 2, 0, 0, + 0, 0, 4, 16, 33, 47, 58, 63, 65, 63, 60, 58, 60, 59, 60, 60, 61, + 60, 62, 72, 77, 79, 79, 79, 77, 74, 79, 83, 82, 83, 85, 85, 81, 73, + 57, 33, 7, 0, 3, 31, 57, 76, 89, 96,101,103,106,107,106,104,102, +111,115,120,120,115,106, 94, 80, 81, 87, 90, 92, 89, 84, 76, 67, 57, + 46, 32, 18, 6, 0, 0, 0, 6, 14, 20, 22, 19, 9, 7, 6, 9, 20, + 26, 27, 26, 23, 21, 20, 20, 18, 8, 0, 0, 5, 16, 20, 14, 4, 0, + 0, 6, 12, 14, 13, 5, 7, 7, 2, 0, 0, 13, 27, 36, 53, 71, 84, + 94,102,106,109,112,117,122,127,129,128,125,122,118,113,117,125,133, +137,139,136,130,120,106, 91, 76, 79, 79, 77, 70, 62, 55, 50, 43, 41, + 53, 63, 72, 77, 79, 78, 74, 67, 58, 52, 61, 72, 82, 90, 97,102,103, +102,104,110,113,114,114,113,113,113,113,110, 99, 84, 64, 55, 48, 36, + 16, 7, 4, 12, 21, 27, 28, 34, 41, 45, 43, 41, 48, 53, 54, 56, 60, + 62, 58, 53, 57, 62, 65, 66, 63, 55, 40, 22, 4, 0, 3, 3, 0, 1, + 6, 12, 15, 27, 41, 53, 61, 67, 69, 69, 67, 63, 64, 65, 63, 58, 50, + 39, 33, 37, 40, 43, 44, 43, 38, 28, 22, 15, 7, 9, 15, 13, 8, 1, + 0, 0, 0, 7, 16, 27, 40, 51, 55, 56, 55, 53, 59, 60, 61, 64, 66, + 66, 64, 66, 74, 79, 83, 87, 87, 84, 78, 78, 80, 82, 85, 87, 86, 81, + 72, 56, 33, 7, 2, 18, 47, 71, 87, 99,107,110,111,111,111,110,108, +106,114,123,132,136,130,120,105, 90, 86, 86, 88, 88, 84, 79, 72, 63, + 56, 48, 38, 25, 8, 4, 1, 6, 11, 19, 27, 29, 26, 15, 0, 0, 3, + 13, 19, 21, 20, 18, 15, 14, 16, 15, 7, 3, 1, 12, 22, 26, 19, 7, + 1, 8, 16, 23, 27, 25, 19, 20, 14, 7, 0, 0, 3, 16, 25, 44, 62, + 75, 84, 91, 96,100,106,113,122,129,133,132,127,120,115,113,122,132, +139,142,140,136,130,122,108, 93, 79, 77, 77, 74, 69, 62, 57, 53, 48, + 43, 51, 62, 72, 77, 79, 78, 74, 66, 58, 54, 60, 68, 79, 88, 96,100, +101,100,106,110,111,111,110,107,106,105,106,103, 94, 80, 61, 46, 39, + 28, 20, 16, 13, 16, 25, 28, 28, 26, 33, 36, 36, 46, 52, 56, 57, 59, + 63, 65, 62, 54, 54, 56, 58, 57, 55, 46, 32, 15, 3, 0, 5, 8, 8, + 15, 23, 29, 33, 32, 36, 45, 51, 54, 55, 53, 59, 62, 63, 61, 58, 52, + 41, 29, 29, 32, 36, 39, 41, 40, 36, 27, 23, 19, 13, 22, 26, 22, 14, + 4, 0, 0, 0, 6, 16, 25, 29, 38, 43, 45, 45, 54, 59, 59, 63, 68, + 71, 71, 68, 68, 74, 81, 89, 92, 92, 89, 83, 82, 83, 85, 88, 88, 85, + 79, 69, 53, 29, 7, 7, 29, 58, 79, 94,106,113,114,114,119,121,117, +109,108,113,128,142,150,147,134,117,100, 94, 90, 84, 83, 79, 73, 68, + 63, 54, 50, 43, 34, 39, 38, 31, 21, 26, 31, 34, 36, 32, 21, 4, 0, + 0, 5, 11, 13, 12, 9, 7, 7, 9, 11, 6, 7, 6, 15, 25, 27, 19, + 7, 8, 18, 28, 36, 40, 38, 33, 34, 27, 14, 4, 3, 2, 5, 13, 34, + 52, 64, 73, 79, 85, 91, 98,108,119,128,132,130,123,115,111,117,125, +133,136,136,133,128,122,115,105, 92, 79, 73, 71, 67, 61, 55, 53, 51, + 50, 47, 43, 55, 66, 73, 75, 74, 70, 63, 58, 60, 59, 66, 77, 88, 94, + 98, 99, 99,104,107,107,104,101, 97, 95, 93, 95, 93, 87, 74, 57, 36, + 28, 27, 23, 19, 16, 18, 26, 31, 28, 21, 23, 25, 38, 48, 54, 57, 61, + 66, 64, 66, 64, 57, 46, 45, 44, 41, 38, 29, 18, 11, 9, 7, 7, 12, + 19, 28, 38, 44, 46, 43, 33, 32, 36, 37, 41, 53, 59, 61, 59, 55, 51, + 43, 31, 20, 27, 31, 28, 31, 34, 34, 29, 28, 27, 23, 26, 34, 36, 29, + 19, 20, 18, 9, 3, 2, 12, 19, 22, 22, 28, 32, 41, 53, 58, 56, 66, + 73, 75, 75, 71, 67, 73, 85, 93, 96, 96, 92, 86, 84, 85, 87, 88, 87, + 84, 76, 64, 47, 23, 8, 9, 37, 64, 84, 97,109,115,117,129,142,145, +137,122,108,111,127,145,158,159,147,128,110,100, 96, 88, 78, 73, 71, + 69, 63, 51, 48, 53, 62, 66, 65, 58, 47, 39, 45, 50, 48, 41, 26, 8, + 0, 0, 0, 2, 4, 3, 2, 3, 1, 5, 7, 6, 9, 9, 18, 25, 25, + 16, 8, 16, 28, 39, 48, 53, 52, 46, 47, 40, 26, 8, 6, 5, 0, 4, + 23, 40, 52, 61, 67, 76, 83, 89,101,113,122,127,125,119,111,106,115, +123,128,128,125,120,113,109,103, 96, 88, 77, 64, 59, 54, 46, 41, 41, + 44, 46, 47, 46, 44, 55, 63, 67, 68, 65, 60, 60, 61, 57, 63, 77, 88, + 95, 98, 98, 96,100,102, 99, 96, 91, 86, 82, 80, 81, 82, 77, 66, 51, + 29, 26, 26, 22, 18, 14, 16, 26, 29, 28, 21, 14, 26, 40, 50, 55, 60, + 68, 71, 67, 66, 65, 59, 48, 33, 23, 19, 14, 7, 7, 12, 15, 15, 14, + 15, 27, 38, 47, 54, 54, 48, 37, 21, 19, 26, 41, 52, 57, 57, 53, 47, + 40, 32, 25, 26, 33, 37, 34, 26, 23, 25, 28, 33, 34, 33, 37, 44, 44, + 37, 40, 43, 39, 31, 18, 5, 6, 13, 15, 15, 14, 20, 37, 48, 54, 58, + 69, 77, 80, 79, 75, 68, 74, 86, 94, 97, 96, 92, 86, 85, 85, 87, 87, + 84, 79, 71, 57, 38, 14, 7, 8, 38, 66, 84, 98,109,114,127,150,169, +173,159,139,118,107,123,142,159,165,156,137,118,102,100, 92, 84, 75, + 72, 69, 62, 48, 58, 69, 78, 82, 81, 74, 64, 51, 57, 60, 60, 53, 39, + 19, 0, 0, 0, 0, 0, 0, 6, 8, 8, 3, 7, 7, 9, 12, 18, 22, + 21, 12, 25, 34, 40, 51, 59, 64, 64, 56, 57, 51, 37, 19, 9, 7, 3, + 0, 14, 29, 40, 50, 62, 74, 79, 81, 92,104,114,120,119,113,107,100, +108,113,117,115,112,105, 99, 95, 91, 86, 79, 71, 61, 48, 37, 26, 22, + 23, 29, 36, 40, 44, 43, 41, 52, 58, 60, 59, 57, 54, 54, 50, 67, 81, + 91, 98,102,101, 97, 93, 93, 91, 88, 86, 84, 84, 79, 69, 70, 66, 58, + 50, 41, 32, 22, 16, 11, 8, 13, 22, 28, 27, 20, 8, 28, 43, 53, 58, + 62, 68, 69, 64, 66, 65, 59, 48, 33, 16, 2, 0, 0, 3, 12, 18, 22, + 26, 29, 31, 41, 51, 57, 57, 51, 39, 22, 6, 23, 39, 48, 52, 50, 44, + 36, 29, 31, 33, 36, 36, 37, 34, 25, 13, 25, 36, 43, 46, 48, 48, 51, + 51, 55, 60, 62, 60, 52, 38, 19, 1, 7, 11, 12, 8, 13, 27, 39, 46, + 61, 74, 83, 87, 86, 82, 75, 68, 81, 89, 92, 91, 87, 84, 83, 83, 84, + 83, 79, 74, 63, 47, 26, 4, 2, 4, 36, 64, 84, 98,108,114,137,165, +186,190,177,150,124,110,118,136,154,161,158,142,124,109,102, 96, 88, + 84, 79, 74, 69, 61, 70, 80, 88, 91, 89, 83, 73, 60, 65, 69, 69, 63, + 51, 31, 9, 0, 0, 0, 0, 4, 9, 13, 13, 8, 12, 14, 14, 15, 16, + 20, 19, 28, 40, 48, 54, 59, 68, 73, 72, 66, 66, 59, 46, 28, 16, 7, + 3, 0, 7, 21, 33, 41, 56, 67, 74, 74, 85, 96,105,114,121,121,114, +108,111,111,108,103, 99, 97, 97, 93, 86, 76, 69, 62, 58, 54, 50, 44, + 33, 20, 16, 20, 27, 32, 34, 34, 41, 50, 54, 55, 54, 52, 51, 53, 69, + 83, 92, 99,102,102, 98, 94, 91, 89, 88, 92, 96, 96, 91, 81, 69, 63, + 61, 56, 51, 43, 34, 27, 18, 5, 8, 19, 25, 23, 18, 13, 32, 46, 55, + 59, 62, 62, 62, 64, 65, 62, 55, 44, 27, 9, 3, 4, 5, 5, 13, 22, + 34, 44, 50, 51, 46, 51, 55, 55, 48, 37, 21, 15, 21, 34, 43, 45, 41, + 36, 31, 34, 37, 40, 43, 44, 41, 36, 29, 25, 34, 45, 54, 59, 62, 64, + 65, 67, 72, 75, 77, 74, 67, 55, 37, 18, 8, 8, 11, 12, 9, 21, 34, + 50, 65, 78, 87, 92, 92, 88, 83, 77, 74, 80, 84, 83, 83, 86, 88, 88, + 84, 79, 74, 66, 55, 41, 26, 12, 7, 2, 32, 61, 82, 96,105,119,143, +173,192,194,181,154,128,110,113,128,145,156,154,143,128,113,104,100, + 93, 88, 85, 80, 74, 71, 79, 88, 94, 96, 94, 87, 76, 67, 71, 74, 74, + 69, 59, 43, 22, 4, 0, 0, 1, 6, 9, 12, 12, 9, 18, 21, 22, 22, + 25, 25, 28, 38, 50, 57, 63, 67, 73, 75, 74, 76, 74, 68, 55, 38, 21, + 6, 0, 0, 5, 18, 28, 36, 46, 58, 64, 67, 79, 92,108,120,127,127, +121,118,122,121,115,108, 99, 99, 98, 94, 88, 79, 68, 67, 67, 66, 63, + 59, 50, 34, 18, 13, 9, 16, 20, 21, 33, 43, 48, 51, 52, 50, 48, 50, + 65, 78, 88, 93, 97, 97, 96, 92, 90, 88, 96,102,107,108,103, 94, 82, + 70, 63, 61, 58, 52, 44, 36, 25, 11, 9, 18, 22, 21, 15, 19, 36, 47, + 54, 58, 59, 60, 60, 61, 60, 56, 46, 32, 14, 13, 13, 14, 15, 14, 18, + 34, 50, 59, 66, 68, 64, 57, 51, 50, 44, 32, 27, 27, 28, 32, 39, 41, + 38, 32, 29, 36, 38, 41, 45, 46, 45, 43, 39, 37, 44, 55, 62, 68, 73, + 74, 76, 78, 81, 84, 86, 84, 79, 68, 53, 36, 19, 12, 13, 15, 16, 20, + 34, 51, 66, 78, 87, 92, 92, 90, 87, 83, 80, 79, 80, 83, 85, 88, 89, + 88, 85, 80, 74, 65, 55, 41, 23, 18, 13, 6, 33, 60, 79, 92,104,123, +147,173,188,188,171,147,124,111,112,121,134,145,147,140,129,115,107, +102, 96, 92, 88, 84, 78, 77, 84, 92, 98,100, 96, 88, 76, 70, 74, 76, + 76, 72, 63, 48, 31, 15, 8, 6, 3, 6, 7, 7, 7, 15, 22, 27, 31, + 33, 34, 33, 36, 44, 53, 61, 67, 73, 77, 80, 83, 84, 81, 74, 62, 46, + 27, 11, 0, 3, 7, 14, 25, 32, 38, 47, 54, 63, 82, 98,113,124,132, +132,127,134,137,134,127,117,106,106,105,102, 95, 85, 74, 72, 74, 74, + 74, 69, 59, 45, 28, 13, 7, 2, 4, 14, 27, 37, 44, 47, 47, 46, 44, + 43, 56, 68, 77, 84, 88, 89, 89, 88, 87, 93,102,111,117,119,114,105, + 93, 80, 67, 66, 63, 59, 51, 40, 28, 16, 18, 20, 22, 23, 26, 27, 37, + 45, 50, 53, 53, 53, 53, 54, 52, 45, 33, 21, 21, 21, 20, 21, 22, 28, + 33, 46, 60, 71, 78, 80, 79, 73, 65, 57, 50, 44, 40, 38, 37, 34, 36, + 38, 36, 31, 25, 32, 36, 40, 44, 45, 46, 46, 46, 47, 54, 62, 70, 75, + 79, 81, 83, 84, 86, 89, 91, 90, 85, 77, 65, 50, 31, 26, 19, 20, 22, + 21, 32, 47, 61, 73, 81, 86, 88, 88, 86, 84, 84, 84, 84, 85, 86, 87, + 87, 85, 83, 79, 73, 64, 53, 37, 25, 21, 15, 11, 36, 60, 77, 88,105, +124,145,163,173,169,154,133,115,110,113,113,124,133,137,136,127,115, +108,104, 99, 92, 88, 85, 79, 80, 87, 94, 99,100, 96, 86, 74, 70, 74, + 75, 74, 71, 62, 50, 34, 20, 13, 8, 3, 4, 4, 3, 9, 19, 26, 36, + 41, 46, 46, 44, 41, 46, 54, 62, 69, 76, 82, 87, 89, 89, 86, 78, 66, + 51, 34, 19, 6, 4, 8, 12, 21, 27, 33, 39, 51, 69, 87,102,117,128, +134,134,142,154,154,150,140,127,113,109,108,106, 99, 89, 78, 74, 76, + 78, 78, 74, 64, 50, 33, 19, 7, 1, 0, 8, 20, 31, 38, 43, 43, 41, + 39, 36, 41, 54, 62, 69, 74, 79, 81, 81, 84, 95,105,115,123,125,121, +112,100, 87, 73, 70, 68, 63, 54, 41, 27, 23, 26, 28, 32, 36, 38, 38, + 34, 40, 41, 43, 43, 43, 43, 43, 39, 29, 28, 29, 27, 26, 25, 27, 37, + 45, 51, 55, 68, 78, 85, 88, 88, 84, 78, 70, 62, 55, 48, 45, 43, 37, + 31, 33, 33, 29, 27, 27, 32, 36, 39, 41, 44, 47, 51, 56, 62, 69, 74, + 79, 83, 85, 87, 88, 88, 91, 92, 92, 89, 83, 74, 60, 44, 40, 36, 28, + 27, 25, 22, 37, 51, 61, 68, 74, 78, 79, 81, 83, 84, 84, 84, 84, 84, + 83, 82, 81, 79, 75, 70, 61, 48, 33, 27, 22, 19, 20, 39, 61, 75, 87, +103,120,136,147,150,143,130,117,105,107,113,113,115,123,128,128,122, +113,109,105,100, 93, 88, 85, 80, 81, 88, 94, 98, 98, 93, 84, 71, 67, + 70, 71, 69, 64, 56, 44, 31, 20, 13, 7, 0, 0, 0, 0, 11, 25, 37, + 46, 54, 57, 57, 55, 50, 52, 61, 68, 74, 78, 85, 90, 93, 92, 88, 79, + 67, 53, 37, 22, 11, 3, 6, 8, 16, 22, 28, 38, 54, 73, 90,105,119, +130,137,139,159,171,169,163,152,137,121,108,107,105,100, 91, 79, 74, + 76, 78, 77, 72, 62, 48, 33, 20, 11, 4, 0, 2, 13, 23, 32, 37, 38, + 37, 34, 37, 39, 54, 64, 71, 73, 72, 70, 73, 81, 93,104,114,122,124, +121,113,101, 88, 74, 73, 71, 64, 54, 39, 26, 29, 33, 37, 41, 45, 47, + 47, 40, 32, 31, 33, 33, 27, 27, 27, 31, 34, 36, 34, 32, 28, 27, 37, + 48, 58, 66, 70, 71, 80, 88, 92, 92, 90, 84, 78, 69, 60, 52, 46, 41, + 36, 27, 27, 28, 28, 28, 29, 33, 38, 44, 48, 53, 57, 60, 64, 71, 78, + 84, 88, 91, 93, 94, 94, 92, 91, 92, 93, 91, 86, 78, 68, 52, 53, 51, + 45, 34, 25, 18, 19, 31, 39, 47, 54, 60, 66, 72, 76, 79, 82, 82, 81, + 80, 79, 80, 79, 74, 72, 67, 58, 45, 37, 29, 28, 29, 32, 44, 62, 74, + 82, 97,112,122,127,125,119,110,101, 99,102,109,112,111,113,118,120, +115,108,108,104, 99, 92, 88, 84, 79, 79, 86, 92, 96, 95, 89, 79, 66, + 61, 63, 63, 60, 55, 45, 33, 22, 13, 7, 2, 0, 0, 0, 5, 20, 33, + 45, 56, 63, 67, 68, 65, 59, 59, 65, 73, 77, 79, 85, 92, 94, 92, 86, + 77, 68, 58, 43, 22, 12, 3, 1, 3, 11, 18, 23, 37, 55, 74, 91,106, +120,132,140,150,171,179,175,171,159,145,129,113,102,101, 96, 88, 79, + 70, 72, 73, 71, 65, 54, 41, 27, 19, 8, 3, 0, 0, 4, 14, 23, 29, + 33, 32, 32, 36, 39, 52, 64, 72, 74, 73, 67, 64, 76, 88,100,109,114, +115,113,106, 96, 85, 76, 76, 72, 64, 52, 34, 34, 43, 46, 45, 47, 52, + 54, 53, 45, 34, 36, 37, 34, 28, 21, 31, 38, 40, 40, 38, 33, 33, 44, + 50, 57, 69, 78, 82, 83, 80, 86, 92, 93, 91, 87, 79, 71, 60, 50, 41, + 36, 28, 20, 19, 22, 25, 27, 29, 36, 44, 51, 57, 62, 65, 67, 69, 77, + 84, 91, 95, 96, 97, 98, 98, 96, 91, 92, 92, 91, 87, 80, 72, 62, 65, + 64, 59, 48, 32, 14, 0, 4, 11, 18, 26, 36, 46, 57, 65, 73, 76, 77, + 77, 75, 77, 79, 79, 73, 69, 64, 56, 45, 39, 34, 37, 39, 41, 46, 63, + 74, 79, 88,100,107,109,105, 99, 92, 84, 93, 96,103,107,107,105,110, +112,110,102,104,102, 96, 90, 85, 83, 79, 76, 82, 88, 91, 90, 84, 74, + 60, 51, 53, 52, 48, 40, 31, 20, 9, 3, 0, 0, 0, 0, 3, 12, 27, + 40, 52, 62, 70, 75, 76, 74, 69, 68, 68, 75, 79, 82, 84, 90, 92, 90, + 83, 79, 74, 66, 51, 29, 9, 0, 0, 0, 4, 11, 19, 37, 52, 72, 89, +105,120,133,143,154,171,177,173,167,159,149,133,118,102, 94, 91, 84, + 76, 66, 64, 63, 61, 54, 43, 39, 33, 23, 11, 0, 0, 0, 0, 4, 14, + 22, 27, 28, 26, 31, 37, 45, 61, 70, 74, 72, 65, 56, 69, 82, 92,100, +104,104,101, 96, 88, 80, 80, 78, 73, 62, 47, 37, 48, 56, 58, 57, 53, + 56, 57, 55, 47, 50, 55, 56, 54, 47, 38, 37, 43, 45, 44, 40, 36, 41, + 54, 58, 64, 77, 86, 92, 93, 91, 85, 88, 90, 89, 84, 78, 68, 55, 43, + 32, 25, 18, 9, 8, 14, 19, 22, 26, 33, 43, 52, 60, 65, 68, 70, 71, + 80, 88, 94, 97, 99, 98, 97, 98, 97, 92, 90, 91, 90, 87, 81, 74, 72, + 74, 74, 69, 58, 43, 22, 4, 0, 0, 11, 23, 33, 39, 41, 55, 66, 70, + 70, 71, 70, 74, 77, 75, 69, 68, 64, 56, 50, 44, 37, 40, 44, 47, 47, + 62, 73, 77, 78, 87, 92, 92, 88, 82, 79, 83, 91, 89, 96,100,100, 98, +102,105,103, 97, 99, 96, 92, 85, 83, 81, 77, 70, 76, 82, 85, 84, 79, + 70, 55, 40, 41, 40, 36, 28, 19, 8, 0, 0, 0, 0, 0, 1, 11, 21, + 32, 43, 54, 66, 75, 81, 84, 84, 79, 73, 74, 75, 80, 84, 85, 87, 88, + 85, 86, 85, 81, 73, 59, 39, 15, 0, 0, 0, 0, 12, 23, 39, 55, 67, + 85,102,118,133,147,158,161,163,159,156,150,142,129,115,102, 88, 84, + 79, 72, 62, 55, 53, 50, 41, 44, 43, 38, 34, 26, 13, 0, 0, 0, 0, + 4, 15, 23, 27, 26, 21, 27, 36, 51, 62, 67, 66, 60, 51, 61, 74, 84, + 90, 92, 92, 88, 84, 83, 83, 82, 79, 72, 60, 47, 45, 57, 64, 67, 67, + 63, 59, 58, 56, 60, 66, 70, 71, 69, 62, 53, 43, 48, 50, 48, 44, 39, + 45, 55, 58, 71, 83, 92, 99,101, 97, 91, 84, 85, 84, 79, 72, 60, 46, + 31, 20, 12, 5, 0, 0, 3, 8, 12, 16, 23, 34, 46, 55, 62, 66, 68, + 69, 81, 89, 94, 96, 96, 94, 94, 93, 92, 91, 91, 91, 89, 86, 81, 74, + 79, 82, 81, 77, 66, 51, 29, 11, 3, 8, 23, 36, 44, 46, 47, 46, 58, + 63, 64, 65, 67, 67, 70, 68, 70, 71, 67, 60, 55, 51, 45, 39, 44, 48, + 51, 58, 68, 74, 74, 73, 77, 76, 74, 74, 71, 82, 89, 83, 88, 92, 92, + 92, 96, 99, 98, 93, 91, 89, 84, 81, 80, 79, 74, 71, 75, 84, 89, 91, + 88, 80, 70, 57, 51, 48, 41, 32, 19, 15, 12, 5, 0, 0, 0, 5, 21, + 37, 50, 61, 67, 69, 77, 84, 88, 89, 87, 82, 79, 76, 81, 85, 88, 88, + 88, 88, 89, 88, 84, 77, 64, 46, 23, 3, 0, 0, 7, 19, 28, 40, 55, + 67, 81, 98,114,133,150,165,175,177,167,149,133,127,118,107, 95, 83, + 79, 74, 65, 56, 47, 43, 39, 37, 40, 39, 45, 44, 38, 26, 14, 3, 0, + 0, 0, 8, 20, 27, 29, 25, 16, 21, 34, 48, 56, 56, 51, 52, 57, 66, + 74, 79, 79, 78, 83, 84, 84, 84, 83, 79, 71, 58, 58, 56, 61, 70, 74, + 75, 74, 73, 71, 71, 74, 79, 82, 82, 79, 73, 63, 54, 52, 53, 52, 48, + 45, 48, 57, 66, 77, 88, 96,102,102, 99, 92, 85, 79, 78, 73, 64, 52, + 43, 33, 22, 8, 0, 0, 0, 0, 2, 11, 19, 23, 23, 36, 46, 55, 60, + 63, 65, 77, 84, 88, 88, 90, 95, 98, 97, 95, 94, 93, 92, 90, 87, 81, + 78, 84, 88, 88, 83, 74, 59, 40, 33, 26, 19, 29, 41, 48, 51, 50, 48, + 48, 56, 59, 62, 67, 70, 72, 74, 76, 76, 73, 66, 61, 58, 54, 50, 44, + 44, 48, 50, 62, 69, 71, 69, 67, 67, 66, 64, 67, 78, 84, 75, 81, 83, + 83, 84, 89, 93, 93, 88, 83, 80, 79, 78, 77, 75, 75, 73, 77, 85, 92, + 95, 94, 88, 80, 72, 63, 54, 46, 39, 34, 28, 22, 14, 3, 0, 0, 7, + 28, 48, 64, 75, 82, 84, 83, 84, 90, 92, 90, 86, 86, 84, 82, 86, 88, + 88, 88, 88, 88, 87, 84, 77, 66, 51, 31, 11, 0, 3, 15, 25, 33, 37, + 51, 63, 78, 95,112,130,152,171,183,188,177,154,130,112,105, 96, 85, + 77, 74, 67, 58, 47, 37, 33, 31, 26, 28, 38, 45, 46, 43, 36, 26, 15, + 6, 5, 1, 11, 16, 27, 31, 28, 19, 7, 16, 32, 40, 43, 47, 57, 61, + 59, 63, 65, 63, 71, 80, 84, 84, 84, 83, 78, 69, 68, 67, 64, 64, 74, + 79, 83, 84, 84, 84, 84, 87, 90, 91, 89, 85, 79, 71, 62, 55, 53, 52, + 51, 48, 54, 63, 72, 80, 89, 96,100,100, 96, 92, 85, 79, 73, 65, 57, + 48, 39, 29, 19, 6, 0, 0, 0, 2, 11, 19, 25, 26, 22, 26, 38, 47, + 54, 58, 62, 67, 74, 79, 86, 92, 98,102,101, 98, 97, 96, 94, 92, 87, + 82, 80, 87, 92, 92, 89, 81, 70, 55, 50, 43, 37, 29, 41, 48, 52, 51, + 48, 45, 47, 53, 61, 69, 74, 78, 80, 82, 81, 78, 71, 63, 62, 61, 59, + 54, 44, 45, 48, 54, 64, 67, 66, 63, 61, 58, 54, 61, 71, 74, 66, 72, + 74, 72, 74, 81, 86, 87, 84, 79, 76, 74, 74, 73, 72, 74, 72, 77, 86, + 93, 96, 96, 93, 87, 81, 75, 68, 60, 53, 45, 37, 28, 19, 8, 4, 11, + 19, 32, 56, 74, 86, 92, 95, 95, 93, 91, 92, 91, 92, 93, 89, 84, 87, + 88, 88, 87, 85, 85, 83, 79, 73, 63, 50, 32, 15, 8, 12, 22, 31, 36, + 38, 41, 56, 75, 91,107,124,145,165,181,188,177,154,129,110, 95, 84, + 75, 71, 69, 61, 48, 37, 25, 23, 22, 19, 18, 32, 40, 44, 43, 38, 32, + 25, 15, 14, 8, 15, 23, 27, 29, 27, 18, 7, 7, 18, 27, 40, 53, 61, + 64, 61, 52, 47, 45, 62, 75, 79, 80, 81, 79, 74, 74, 74, 73, 70, 67, + 77, 84, 89, 92, 93, 93, 94, 96, 96, 96, 93, 88, 82, 75, 68, 61, 53, + 50, 48, 47, 54, 64, 73, 79, 84, 89, 92, 92, 90, 86, 83, 78, 72, 63, + 54, 44, 32, 21, 9, 0, 0, 0, 5, 14, 21, 26, 28, 27, 22, 28, 33, + 39, 46, 52, 56, 63, 70, 78, 85, 92, 97,101,101, 99, 98, 97, 95, 92, + 88, 83, 81, 89, 94, 96, 94, 88, 79, 67, 61, 54, 48, 41, 38, 46, 50, + 48, 46, 40, 39, 47, 60, 72, 79, 83, 84, 85, 84, 79, 73, 62, 62, 63, + 64, 61, 52, 40, 47, 50, 56, 61, 61, 57, 54, 50, 44, 53, 60, 62, 54, + 60, 61, 59, 61, 71, 76, 79, 76, 72, 70, 69, 68, 67, 67, 71, 69, 76, + 84, 92, 96, 96, 94, 91, 87, 83, 77, 69, 60, 51, 39, 28, 18, 11, 11, + 23, 33, 39, 59, 79, 92,100,104,104,102,100, 97, 96, 97, 98, 94, 87, + 88, 88, 86, 88, 86, 80, 77, 73, 65, 56, 44, 29, 14, 13, 18, 27, 33, + 37, 39, 41, 55, 72, 86,100,114,132,150,167,173,165,143,122,104, 89, + 79, 79, 79, 78, 70, 56, 34, 13, 13, 15, 12, 15, 22, 31, 36, 37, 37, + 33, 29, 21, 20, 14, 18, 28, 33, 29, 21, 12, 2, 6, 16, 29, 44, 57, + 64, 66, 62, 52, 33, 28, 48, 63, 70, 72, 73, 72, 73, 78, 78, 76, 74, + 70, 79, 88, 93, 97, 98, 99, 99,100, 99, 96, 92, 87, 81, 75, 71, 65, + 56, 44, 44, 43, 47, 59, 66, 71, 74, 77, 78, 79, 78, 77, 76, 73, 67, + 58, 47, 34, 21, 8, 0, 0, 0, 5, 16, 23, 28, 29, 29, 26, 26, 31, + 33, 33, 34, 40, 47, 56, 65, 74, 82, 88, 93, 96, 96, 96, 96, 96, 99, + 98, 92, 84, 81, 90, 96,100, 99, 95, 88, 78, 69, 62, 56, 50, 40, 38, + 43, 43, 39, 31, 31, 40, 59, 72, 79, 84, 86, 86, 83, 78, 70, 60, 56, + 60, 64, 64, 57, 44, 45, 50, 50, 52, 52, 47, 44, 38, 31, 40, 46, 47, + 38, 45, 46, 44, 45, 56, 64, 68, 66, 62, 61, 61, 61, 60, 61, 64, 64, + 74, 82, 88, 92, 93, 92, 91, 89, 87, 81, 74, 63, 50, 36, 22, 12, 8, + 18, 36, 47, 54, 59, 79, 93,103,109,110,109,106,102,100,101,101, 96, + 88, 88, 88, 88, 90, 88, 83, 74, 63, 55, 45, 33, 21, 11, 12, 20, 29, + 36, 39, 41, 53, 59, 67, 79, 91,103,115,130,143,150,143,128,111, 95, + 90, 88, 88, 88, 85, 78, 64, 43, 16, 3, 6, 5, 14, 23, 29, 29, 28, + 29, 29, 29, 23, 22, 18, 18, 28, 33, 31, 18, 1, 0, 3, 15, 29, 45, + 57, 64, 66, 62, 52, 36, 15, 27, 44, 52, 55, 58, 63, 74, 78, 79, 77, + 74, 71, 81, 89, 96, 98, 99, 99, 99, 99, 96, 92, 87, 82, 78, 74, 71, + 66, 57, 44, 34, 34, 33, 45, 52, 55, 56, 56, 57, 59, 61, 63, 65, 64, + 58, 50, 37, 22, 8, 0, 0, 0, 2, 16, 27, 33, 34, 32, 28, 25, 29, + 32, 32, 28, 22, 25, 34, 46, 56, 66, 74, 79, 84, 86, 87, 90, 98,104, +107,106,100, 91, 82, 91, 98,102,103,101, 95, 88, 80, 71, 61, 54, 45, + 33, 31, 31, 27, 19, 23, 39, 58, 71, 79, 83, 84, 83, 79, 72, 64, 55, + 46, 52, 59, 62, 58, 47, 41, 47, 50, 45, 37, 33, 29, 25, 19, 25, 29, + 29, 19, 25, 27, 26, 27, 39, 48, 54, 53, 51, 51, 52, 54, 54, 52, 56, + 56, 68, 76, 82, 85, 87, 87, 87, 88, 87, 82, 73, 60, 45, 27, 12, 2, + 3, 23, 45, 59, 67, 70, 77, 92,102,109,112,111,107,103,100,100,100, + 95, 90, 90, 88, 90, 92, 89, 84, 78, 69, 55, 36, 19, 8, 3, 5, 19, + 29, 37, 41, 51, 62, 67, 68, 72, 82, 91,101,112,121,125,122,111, 99, + 99, 97, 96, 95, 94, 92, 84, 71, 52, 25, 8, 0, 0, 11, 23, 32, 36, + 34, 28, 23, 26, 23, 22, 19, 16, 25, 28, 25, 12, 0, 0, 0, 9, 26, + 41, 54, 61, 62, 59, 52, 38, 18, 11, 18, 26, 31, 40, 58, 70, 76, 77, + 75, 73, 73, 83, 90, 95, 96, 96, 94, 93, 92, 88, 84, 79, 76, 74, 69, + 68, 64, 56, 43, 26, 21, 19, 23, 29, 29, 28, 27, 34, 40, 41, 43, 50, + 51, 47, 38, 25, 9, 5, 3, 0, 0, 11, 27, 37, 41, 40, 33, 26, 31, + 33, 32, 28, 22, 14, 7, 16, 29, 43, 53, 60, 66, 70, 74, 83, 91,100, +107,111,111,105, 96, 84, 92,100,105,107,105,100, 94, 88, 80, 65, 57, + 47, 34, 19, 15, 12, 4, 15, 38, 57, 69, 75, 78, 79, 76, 71, 63, 55, + 46, 39, 38, 50, 56, 55, 50, 39, 44, 46, 43, 33, 19, 14, 11, 6, 7, + 12, 12, 0, 4, 7, 8, 8, 20, 29, 36, 37, 36, 38, 43, 46, 48, 47, + 45, 47, 60, 68, 74, 77, 79, 84, 84, 83, 84, 79, 68, 54, 34, 18, 0, + 0, 1, 28, 53, 69, 77, 80, 80, 88, 98,105,108,108,104,100, 96, 95, + 94, 90, 92, 92, 91, 91, 91, 88, 84, 79, 72, 59, 41, 19, 0, 0, 1, + 16, 29, 39, 45, 58, 68, 73, 73, 79, 84, 92, 98, 99,103,107,104,102, +103,103,102,103,100, 99, 96, 88, 77, 59, 34, 12, 0, 0, 4, 19, 31, + 38, 40, 36, 27, 21, 22, 20, 19, 14, 18, 20, 15, 3, 0, 0, 4, 18, + 26, 36, 48, 55, 56, 55, 50, 39, 25, 6, 0, 0, 7, 31, 51, 64, 72, + 74, 72, 69, 75, 84, 89, 92, 92, 89, 86, 85, 84, 79, 83, 85, 84, 79, + 70, 63, 61, 54, 41, 26, 9, 5, 0, 2, 1, 7, 21, 32, 37, 36, 31, + 31, 34, 32, 25, 13, 5, 6, 5, 0, 3, 21, 38, 47, 50, 45, 37, 29, + 33, 33, 29, 22, 13, 3, 0, 0, 11, 22, 33, 41, 47, 59, 70, 79, 88, + 96,105,111,112,107, 99, 87, 93,102,108,110,108,103, 97, 92, 84, 72, + 59, 48, 34, 18, 0, 0, 0, 16, 38, 55, 65, 70, 71, 71, 68, 67, 70, + 68, 61, 48, 29, 37, 46, 51, 50, 44, 39, 41, 39, 31, 19, 9, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 12, 19, 20, 31, 36, 36, 39, 44, + 45, 41, 32, 46, 56, 62, 66, 74, 79, 80, 75, 76, 71, 60, 44, 31, 15, + 0, 0, 4, 33, 59, 75, 84, 87, 87, 85, 94,100,102,101, 96, 91, 86, + 85, 88, 92, 94, 96, 96, 93, 90, 85, 81, 76, 70, 59, 44, 22, 0, 0, + 0, 15, 31, 43, 52, 60, 70, 74, 83, 91, 97,101,102,102,100, 95,100, +104,108,113,117,117,112,102, 98, 92, 81, 66, 44, 19, 0, 0, 0, 9, + 25, 34, 39, 38, 32, 20, 22, 19, 16, 13, 11, 11, 5, 0, 3, 13, 21, + 27, 37, 41, 45, 46, 48, 50, 47, 40, 28, 13, 0, 0, 0, 21, 43, 58, + 67, 70, 69, 66, 76, 84, 88, 88, 86, 82, 79, 76, 79, 85, 89, 91, 88, + 82, 72, 58, 57, 51, 40, 26, 11, 0, 0, 0, 0, 2, 15, 25, 29, 28, + 21, 13, 19, 19, 14, 12, 6, 6, 3, 0, 15, 34, 50, 57, 58, 53, 41, + 29, 31, 29, 23, 14, 4, 0, 0, 0, 0, 3, 13, 26, 40, 53, 63, 72, + 81, 91,100,106,108,105, 97, 86, 97,105,111,112,109,103, 98, 91, 84, + 74, 63, 50, 33, 15, 0, 0, 0, 19, 39, 54, 62, 65, 65, 64, 72, 78, + 80, 79, 73, 61, 44, 26, 38, 45, 48, 48, 45, 39, 37, 28, 23, 14, 9, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 14, 26, 32, 33, 38, + 45, 48, 46, 38, 31, 37, 45, 55, 65, 70, 71, 66, 67, 62, 50, 33, 23, + 9, 0, 0, 8, 38, 62, 78, 86, 89, 88, 86, 92, 96, 96, 93, 88, 84, + 92, 95, 93, 92, 96,100,101,100, 97, 92, 84, 71, 64, 56, 44, 25, 4, + 0, 0, 13, 32, 47, 60, 70, 78, 86, 95,103,111,115,117,114,112,111, +113,118,124,130,134,133,125,113,100, 91, 82, 69, 51, 28, 6, 0, 0, + 1, 13, 25, 31, 32, 28, 21, 23, 22, 16, 12, 7, 3, 0, 4, 15, 26, + 36, 40, 45, 50, 52, 54, 53, 46, 44, 40, 32, 19, 4, 0, 0, 12, 33, + 51, 60, 64, 64, 67, 77, 83, 85, 88, 88, 87, 92, 94, 94, 95, 93, 92, + 88, 81, 71, 57, 50, 44, 36, 25, 18, 11, 5, 3, 4, 9, 14, 15, 20, + 18, 13, 5, 3, 11, 14, 15, 13, 9, 6, 9, 28, 47, 60, 66, 66, 60, + 51, 38, 26, 20, 13, 8, 8, 9, 7, 0, 0, 2, 11, 23, 38, 54, 68, + 79, 86, 89, 93,100,102,100, 94, 90,100,107,110,109,107,110,107, 99, + 89, 79, 67, 52, 32, 11, 0, 0, 2, 22, 40, 53, 58, 60, 61, 73, 79, + 85, 88, 86, 79, 69, 53, 36, 31, 40, 46, 50, 50, 47, 45, 44, 40, 31, + 19, 15, 13, 8, 3, 13, 11, 8, 1, 0, 0, 0, 0, 5, 19, 27, 29, + 39, 48, 54, 54, 48, 39, 31, 34, 45, 54, 58, 57, 58, 59, 53, 39, 23, + 14, 3, 0, 1, 13, 41, 64, 78, 85, 88, 86, 85, 91, 92, 92, 88, 82, + 89, 96, 99, 98, 96, 97,101,103,104,102, 99, 90, 76, 58, 53, 44, 29, + 13, 7, 1, 8, 31, 51, 66, 78, 87, 96,105,114,123,129,133,132,130, +129,132,139,147,154,158,154,143,128,113, 97, 82, 69, 54, 36, 16, 0, + 0, 0, 4, 9, 16, 20, 19, 21, 23, 21, 16, 11, 6, 4, 6, 13, 23, + 34, 43, 47, 48, 52, 54, 57, 57, 51, 43, 40, 36, 27, 20, 15, 9, 7, + 20, 39, 51, 56, 56, 68, 77, 84, 92, 95, 95, 98,109,113,113,113,111, +105, 96, 88, 76, 64, 52, 47, 45, 41, 38, 34, 32, 31, 31, 31, 27, 22, + 13, 8, 6, 5, 5, 5, 12, 16, 19, 19, 16, 22, 40, 55, 65, 71, 71, + 67, 59, 48, 37, 26, 20, 23, 27, 29, 27, 18, 11, 16, 26, 37, 50, 62, + 74, 85, 92, 96, 98, 97, 96, 96, 92, 92,100,104,105,108,114,118,115, +107, 96, 84, 71, 53, 29, 6, 4, 11, 16, 26, 40, 50, 54, 53, 65, 76, + 84, 90, 92, 91, 84, 74, 59, 43, 32, 34, 43, 47, 50, 51, 51, 53, 52, + 44, 33, 22, 23, 22, 19, 25, 27, 23, 15, 2, 0, 0, 0, 0, 11, 21, + 28, 41, 52, 59, 61, 58, 51, 43, 33, 36, 41, 44, 43, 51, 52, 44, 29, + 13, 6, 0, 1, 11, 19, 44, 63, 75, 82, 84, 82, 86, 89, 90, 88, 84, + 85, 90, 97,100, 99, 97, 96, 99,102,103,103,101, 93, 79, 60, 50, 44, + 33, 27, 22, 14, 6, 27, 51, 69, 82, 92,102,112,122,132,139,145,147, +147,147,150,159,167,173,175,171,159,142,123,107, 92, 76, 57, 39, 23, + 8, 1, 2, 2, 7, 11, 14, 16, 20, 21, 18, 13, 8, 6, 5, 9, 16, + 27, 37, 44, 48, 50, 48, 52, 55, 57, 53, 41, 40, 38, 34, 34, 32, 28, + 21, 19, 26, 39, 47, 56, 67, 82, 92,100,102,102,112,127,134,136,133, +127,118,108, 97, 88, 78, 69, 59, 54, 53, 53, 54, 54, 55, 54, 52, 47, + 38, 27, 14, 6, 8, 11, 11, 9, 18, 23, 26, 26, 32, 46, 58, 66, 71, + 73, 70, 65, 57, 47, 37, 33, 38, 41, 44, 41, 34, 23, 29, 38, 47, 57, + 68, 79, 89, 98,104,107,107,104,101, 97, 93, 96, 98,102,112,120,123, +121,112,100, 87, 72, 52, 27, 9, 16, 22, 27, 32, 39, 46, 47, 45, 63, + 76, 84, 91, 94, 92, 86, 76, 61, 46, 38, 36, 36, 41, 45, 48, 51, 55, + 56, 52, 44, 33, 29, 32, 29, 37, 41, 38, 28, 13, 3, 0, 0, 0, 6, + 16, 29, 41, 53, 61, 66, 64, 59, 53, 43, 31, 31, 31, 33, 41, 44, 36, + 20, 4, 0, 0, 8, 19, 25, 47, 63, 73, 77, 78, 81, 86, 87, 86, 84, + 81, 88, 92, 94, 96, 96, 96, 94, 93, 96, 98, 99, 98, 92, 79, 60, 45, + 41, 34, 36, 32, 23, 14, 27, 50, 69, 83, 93,102,112,121,130,139,147, +152,156,158,161,169,175,181,181,175,163,147,130,114,100, 85, 68, 47, + 28, 15, 5, 9, 13, 14, 14, 14, 15, 16, 15, 12, 6, 8, 7, 3, 8, + 16, 26, 34, 40, 44, 44, 44, 45, 51, 55, 53, 45, 38, 37, 39, 41, 43, + 40, 34, 31, 29, 34, 44, 58, 74, 88, 99,107,111,109,120,140,154,154, +149,139,128,115,104, 95, 88, 82, 74, 64, 60, 62, 64, 67, 69, 68, 65, + 58, 50, 37, 25, 13, 8, 13, 14, 12, 19, 27, 32, 32, 38, 48, 56, 63, + 68, 70, 70, 68, 62, 55, 45, 40, 45, 48, 50, 48, 43, 32, 38, 45, 53, + 62, 71, 81, 92,102,110,115,117,113,108,102, 96, 90, 94,104,113,120, +123,119,111, 99, 86, 71, 50, 23, 16, 23, 29, 33, 36, 34, 40, 41, 38, + 56, 71, 80, 88, 92, 91, 85, 75, 62, 47, 45, 41, 37, 32, 37, 40, 45, + 51, 55, 54, 48, 41, 34, 38, 38, 47, 53, 50, 39, 23, 12, 3, 2, 4, + 5, 15, 27, 39, 52, 60, 66, 67, 64, 58, 50, 38, 22, 21, 23, 33, 34, + 26, 11, 0, 0, 2, 14, 23, 31, 50, 62, 69, 73, 76, 82, 84, 83, 80, + 78, 80, 88, 93, 95, 93, 92, 93, 92, 90, 85, 88, 90, 90, 85, 74, 58, + 39, 38, 33, 39, 38, 29, 22, 38, 52, 65, 79, 89, 97,106,113,121,129, +137,145,152,156,159,165,169,173,171,165,154,142,128,115,104, 91, 77, + 59, 38, 21, 13, 16, 23, 27, 27, 25, 20, 18, 13, 7, 12, 14, 11, 6, + 3, 12, 21, 27, 32, 34, 34, 34, 37, 45, 52, 53, 50, 39, 32, 37, 41, + 45, 44, 40, 37, 37, 40, 48, 60, 75, 90,102,113,118,118,122,143,159, +163,156,143,130,118,108, 99, 94, 90, 84, 77, 67, 64, 68, 73, 74, 74, + 70, 62, 53, 41, 29, 19, 13, 13, 15, 14, 20, 29, 36, 34, 38, 45, 51, + 56, 60, 64, 66, 67, 64, 58, 48, 41, 45, 47, 48, 47, 44, 34, 40, 47, + 55, 62, 72, 81, 92,104,114,123,125,122,114,105, 96, 88, 92,102,112, +117,117,112,103, 93, 81, 66, 46, 22, 19, 25, 28, 32, 34, 33, 33, 34, + 31, 43, 60, 72, 81, 86, 86, 82, 73, 60, 47, 50, 47, 41, 34, 26, 27, + 32, 40, 48, 50, 47, 44, 40, 41, 44, 53, 59, 57, 47, 32, 16, 7, 3, + 7, 8, 12, 27, 38, 46, 56, 63, 65, 64, 60, 53, 41, 27, 15, 14, 23, + 25, 16, 4, 0, 0, 5, 16, 26, 36, 52, 61, 66, 69, 76, 80, 79, 76, + 74, 71, 78, 86, 92, 93, 92, 87, 89, 90, 88, 83, 75, 76, 78, 74, 66, + 52, 34, 33, 29, 37, 37, 29, 33, 47, 58, 64, 72, 81, 88, 96,102,108, +114,122,129,136,140,143,149,150,152,149,143,136,127,120,112,103, 94, + 82, 68, 50, 28, 20, 22, 31, 36, 36, 32, 25, 19, 11, 15, 21, 23, 19, + 9, 0, 4, 12, 18, 21, 22, 22, 27, 36, 40, 47, 53, 54, 47, 33, 29, + 36, 40, 41, 39, 37, 37, 39, 47, 58, 74, 88,102,114,123,125,122,137, +154,158,150,139,127,115,106,100, 96, 95, 92, 86, 78, 67, 66, 71, 74, + 73, 68, 60, 51, 39, 28, 20, 15, 11, 14, 14, 21, 31, 37, 34, 34, 39, + 46, 57, 61, 60, 60, 64, 64, 59, 50, 37, 37, 39, 39, 39, 37, 31, 37, + 45, 53, 61, 72, 80, 92,104,118,129,133,129,120,108, 97, 92, 92,100, +106,108,106,100, 92, 84, 74, 59, 41, 22, 16, 20, 22, 25, 28, 28, 25, + 26, 23, 23, 43, 57, 70, 77, 79, 76, 68, 56, 48, 52, 50, 45, 37, 28, + 21, 16, 26, 36, 40, 43, 41, 41, 43, 46, 55, 61, 60, 53, 38, 20, 9, + 1, 6, 7, 16, 29, 43, 50, 52, 55, 59, 59, 57, 52, 43, 29, 14, 8, + 14, 15, 8, 0, 0, 3, 8, 16, 25, 39, 53, 61, 64, 66, 72, 74, 72, + 67, 63, 60, 73, 81, 87, 88, 86, 81, 84, 87, 85, 81, 73, 61, 61, 59, + 53, 43, 29, 26, 23, 32, 32, 29, 43, 54, 61, 64, 65, 69, 76, 84, 89, + 96,102,107,113,120,123,125,127,128,128,125,121,117,111,107,103, 98, + 92, 84, 72, 56, 37, 27, 27, 37, 43, 41, 36, 26, 16, 14, 23, 29, 32, + 27, 16, 3, 0, 3, 7, 9, 11, 13, 23, 33, 38, 45, 54, 58, 55, 45, + 33, 25, 31, 33, 32, 31, 31, 39, 48, 55, 68, 84, 99,113,124,130,130, +125,139,143,139,129,119,112,107,100, 96, 96, 94, 91, 85, 77, 66, 64, + 68, 67, 61, 53, 43, 32, 23, 16, 14, 11, 11, 13, 23, 33, 37, 33, 29, + 40, 58, 70, 75, 75, 69, 59, 61, 57, 48, 34, 25, 26, 26, 26, 25, 21, + 29, 39, 51, 67, 79, 87, 91,104,120,133,139,133,122,108, 96, 96, 96, + 96, 99, 98, 93, 87, 79, 71, 61, 51, 37, 23, 12, 11, 11, 13, 18, 20, + 19, 16, 16, 13, 20, 38, 54, 65, 69, 68, 62, 52, 46, 51, 51, 45, 38, + 37, 33, 26, 18, 21, 28, 33, 36, 37, 43, 48, 51, 59, 59, 54, 43, 26, + 8, 0, 0, 12, 25, 34, 48, 56, 58, 55, 50, 51, 51, 47, 41, 31, 18, + 11, 5, 7, 2, 0, 0, 6, 11, 14, 21, 41, 54, 60, 63, 62, 62, 64, + 60, 61, 58, 56, 63, 72, 78, 79, 75, 77, 80, 82, 81, 76, 67, 55, 41, + 41, 38, 32, 23, 18, 16, 25, 25, 38, 50, 58, 62, 62, 59, 55, 63, 79, + 91,101,109,113,113,112,109,110,111,111,109,107,103,100, 96, 93, 92, + 90, 87, 80, 71, 57, 39, 37, 36, 41, 45, 43, 34, 23, 13, 20, 29, 37, + 38, 32, 21, 7, 0, 0, 0, 1, 3, 5, 16, 26, 29, 44, 56, 61, 61, + 54, 41, 31, 20, 22, 22, 23, 31, 40, 48, 55, 58, 76, 92,108,121,130, +133,130,124,129,125,120,119,115,111,102, 92, 93, 93, 92, 88, 81, 73, + 64, 58, 58, 53, 48, 44, 38, 29, 20, 9, 6, 6, 16, 27, 34, 37, 32, + 26, 47, 66, 79, 84, 85, 80, 71, 60, 56, 46, 32, 14, 18, 22, 21, 13, + 11, 22, 38, 57, 72, 83, 89, 92,106,121,134,140,134,122,107, 95, 97, + 98, 96, 91, 88, 81, 73, 64, 59, 51, 41, 33, 25, 15, 7, 0, 1, 5, + 9, 9, 6, 6, 4, 1, 18, 37, 51, 58, 60, 56, 47, 39, 46, 47, 44, + 41, 44, 43, 36, 23, 22, 16, 20, 25, 31, 41, 50, 53, 51, 54, 52, 44, + 31, 16, 2, 7, 20, 33, 43, 52, 58, 60, 58, 53, 43, 39, 38, 34, 27, + 18, 15, 11, 5, 1, 0, 1, 7, 12, 13, 20, 38, 50, 56, 59, 58, 56, + 55, 55, 56, 54, 55, 63, 69, 72, 74, 74, 75, 77, 77, 74, 67, 56, 43, + 28, 25, 23, 20, 15, 12, 11, 19, 27, 39, 50, 56, 58, 56, 52, 51, 65, + 80, 93,103,112,115,117,114,112,109,105,102,100, 98, 96, 95, 92, 88, + 82, 81, 79, 74, 66, 53, 47, 45, 43, 43, 44, 39, 28, 16, 20, 27, 34, + 40, 40, 36, 25, 12, 1, 0, 0, 0, 0, 1, 9, 20, 33, 48, 60, 66, + 66, 60, 46, 36, 25, 20, 20, 22, 28, 36, 45, 48, 52, 68, 85,100,113, +123,128,128,124,122,121,120,118,113,107, 99, 89, 89, 89, 88, 85, 80, + 74, 67, 63, 61, 59, 55, 51, 44, 36, 26, 15, 7, 11, 22, 32, 37, 37, + 32, 31, 53, 71, 84, 91, 92, 89, 82, 73, 63, 54, 43, 29, 20, 25, 26, + 19, 12, 27, 45, 62, 75, 84, 90, 93,107,122,134,139,133,120,106, 95, + 95, 96, 93, 88, 78, 70, 63, 63, 59, 52, 40, 28, 23, 19, 13, 7, 0, + 5, 9, 9, 6, 0, 0, 0, 0, 16, 33, 45, 51, 50, 45, 39, 37, 39, + 43, 47, 50, 50, 44, 33, 27, 20, 8, 14, 28, 41, 51, 54, 52, 46, 45, + 40, 32, 21, 9, 13, 26, 38, 47, 52, 57, 59, 57, 53, 43, 27, 25, 23, + 20, 19, 20, 15, 9, 4, 0, 0, 5, 11, 14, 14, 29, 40, 46, 48, 48, + 46, 45, 45, 45, 45, 51, 60, 67, 71, 74, 74, 73, 73, 72, 72, 66, 55, + 38, 20, 11, 11, 9, 6, 5, 6, 14, 22, 34, 45, 50, 51, 46, 45, 58, + 69, 83, 95,105,113,117,118,117,113,110,105,101, 96, 92, 89, 87, 84, + 81, 75, 74, 72, 68, 60, 53, 52, 50, 46, 39, 38, 31, 19, 20, 26, 31, + 37, 41, 41, 37, 28, 18, 8, 0, 0, 0, 0, 0, 11, 23, 38, 53, 64, + 71, 71, 65, 53, 37, 27, 20, 18, 18, 22, 34, 43, 47, 50, 59, 76, 91, +102,112,118,120,120,119,118,115,112,106, 99, 91, 84, 84, 84, 82, 79, + 75, 71, 66, 64, 63, 61, 57, 52, 44, 36, 26, 16, 9, 15, 26, 34, 38, + 37, 34, 37, 58, 76, 89, 97,101, 98, 92, 85, 78, 70, 60, 48, 34, 28, + 29, 25, 20, 37, 53, 68, 79, 86, 91, 93,106,120,132,134,129,119,106, + 96, 89, 89, 88, 82, 74, 61, 59, 60, 57, 51, 40, 29, 18, 16, 14, 11, + 4, 8, 13, 16, 16, 11, 5, 1, 0, 1, 12, 27, 37, 41, 41, 38, 38, + 40, 46, 51, 55, 56, 53, 44, 33, 26, 20, 15, 27, 41, 51, 51, 50, 45, + 37, 36, 29, 22, 14, 15, 28, 39, 46, 50, 51, 53, 52, 48, 40, 25, 11, + 11, 12, 21, 25, 20, 13, 6, 2, 0, 0, 6, 12, 14, 18, 26, 31, 32, + 33, 34, 32, 29, 31, 31, 43, 53, 61, 67, 70, 70, 67, 72, 75, 75, 70, + 59, 44, 26, 21, 13, 0, 0, 0, 3, 11, 15, 25, 36, 40, 40, 36, 48, + 61, 70, 84, 94,103,110,113,115,113,112,108,104,102, 99, 94, 88, 80, + 73, 70, 65, 66, 65, 61, 54, 52, 52, 51, 45, 36, 28, 20, 14, 25, 29, + 32, 36, 38, 38, 34, 29, 22, 14, 7, 0, 0, 0, 0, 11, 26, 40, 55, + 66, 73, 74, 68, 56, 37, 25, 16, 11, 8, 20, 32, 40, 50, 57, 64, 67, + 78, 88, 97,104,109,111,112,111,108,102, 96, 88, 81, 79, 76, 74, 71, + 68, 64, 61, 59, 59, 60, 59, 54, 47, 39, 29, 20, 12, 8, 20, 31, 38, + 40, 37, 40, 44, 62, 79, 92,102,106,106,102, 95, 89, 82, 74, 63, 50, + 32, 31, 26, 27, 44, 59, 72, 81, 88, 91, 92,104,115,125,128,123,114, +104, 96, 88, 82, 80, 76, 68, 57, 56, 54, 53, 48, 40, 31, 20, 11, 11, + 9, 6, 11, 16, 21, 23, 22, 18, 12, 4, 1, 7, 12, 20, 29, 34, 34, + 36, 40, 46, 52, 57, 59, 59, 54, 47, 41, 37, 32, 23, 37, 47, 43, 43, + 39, 33, 28, 25, 20, 14, 13, 25, 34, 39, 41, 39, 40, 40, 38, 32, 19, + 3, 0, 14, 25, 28, 25, 16, 18, 14, 6, 2, 4, 8, 14, 15, 18, 22, + 25, 26, 25, 22, 19, 15, 18, 31, 43, 53, 59, 62, 61, 63, 71, 75, 75, + 71, 61, 48, 36, 33, 23, 9, 0, 0, 0, 5, 11, 14, 23, 29, 29, 33, + 46, 58, 67, 80, 90, 97,103,106,108,107,106,105,109,108,105, 99, 92, + 85, 78, 69, 60, 59, 58, 55, 48, 46, 48, 46, 40, 28, 18, 9, 16, 25, + 27, 26, 27, 28, 28, 27, 25, 21, 18, 12, 3, 0, 0, 0, 8, 25, 40, + 54, 65, 73, 74, 68, 56, 37, 18, 8, 0, 6, 23, 39, 51, 59, 65, 69, + 70, 68, 71, 80, 88, 94, 98,101,101, 96, 91, 84, 75, 74, 71, 65, 60, + 54, 48, 45, 44, 45, 48, 52, 51, 46, 38, 28, 19, 11, 6, 9, 23, 36, + 43, 44, 39, 45, 48, 64, 80, 93,103,109,110,107,102, 96, 91, 83, 73, + 58, 40, 26, 22, 29, 46, 62, 74, 83, 88, 91, 91,100,111,118,119,115, +108,100, 93, 87, 79, 73, 69, 63, 54, 52, 50, 47, 44, 39, 32, 23, 15, + 8, 6, 7, 12, 18, 22, 27, 29, 29, 26, 18, 4, 5, 9, 9, 14, 22, + 26, 28, 34, 40, 48, 55, 60, 62, 60, 57, 54, 51, 45, 37, 29, 39, 31, + 32, 31, 27, 22, 18, 14, 11, 7, 18, 25, 28, 28, 26, 23, 23, 23, 20, + 8, 0, 2, 18, 28, 33, 29, 27, 32, 31, 22, 9, 5, 5, 13, 16, 16, + 16, 18, 18, 15, 12, 9, 7, 11, 18, 28, 39, 46, 48, 46, 56, 64, 71, + 72, 70, 62, 51, 45, 44, 36, 21, 4, 0, 0, 2, 5, 6, 13, 19, 20, + 25, 37, 50, 59, 73, 82, 88, 93, 96, 96, 96, 96,102,108,110,108,102, + 96, 92, 88, 80, 73, 62, 52, 50, 44, 37, 40, 38, 31, 19, 7, 4, 13, + 20, 20, 16, 14, 14, 14, 15, 15, 16, 15, 12, 5, 0, 0, 0, 4, 20, + 34, 50, 61, 68, 69, 64, 52, 31, 8, 0, 0, 14, 34, 50, 60, 66, 71, + 72, 70, 65, 59, 57, 68, 77, 84, 88, 88, 84, 78, 69, 64, 63, 58, 50, + 39, 29, 22, 19, 19, 23, 31, 37, 37, 33, 25, 16, 7, 5, 2, 12, 28, + 40, 48, 48, 44, 45, 50, 63, 79, 92,102,107,109,108,104,100, 94, 86, + 76, 61, 43, 21, 14, 25, 44, 61, 74, 82, 88, 89, 89, 96,104,109,109, +105, 99, 92, 88, 83, 75, 67, 62, 58, 51, 43, 41, 41, 39, 36, 31, 25, + 16, 9, 7, 8, 11, 15, 20, 26, 32, 37, 38, 34, 22, 8, 9, 8, 4, + 7, 13, 16, 22, 29, 39, 47, 55, 60, 62, 61, 61, 59, 54, 44, 31, 26, + 14, 18, 19, 20, 19, 14, 7, 5, 4, 7, 13, 14, 13, 9, 5, 5, 6, + 5, 0, 5, 9, 22, 33, 38, 34, 40, 46, 46, 40, 26, 7, 4, 8, 15, + 18, 16, 9, 6, 3, 0, 0, 4, 8, 9, 14, 21, 27, 29, 29, 41, 53, + 61, 66, 66, 61, 53, 52, 51, 44, 31, 13, 0, 0, 0, 1, 0, 3, 11, + 14, 13, 21, 33, 46, 61, 71, 77, 80, 83, 84, 84, 86, 96,103,107,107, +103, 98, 99, 95, 88, 82, 74, 61, 45, 38, 28, 28, 27, 20, 9, 0, 0, + 6, 9, 7, 2, 0, 0, 0, 0, 3, 5, 7, 6, 4, 3, 0, 0, 0, + 13, 27, 40, 53, 61, 62, 57, 44, 23, 1, 0, 1, 25, 44, 58, 66, 71, + 74, 74, 69, 61, 55, 47, 40, 55, 66, 72, 74, 70, 63, 53, 50, 47, 40, + 28, 14, 11, 7, 2, 0, 0, 9, 18, 20, 16, 11, 3, 2, 3, 8, 16, + 33, 47, 54, 55, 50, 43, 46, 60, 76, 88, 96,102,104,103,102, 98, 93, + 85, 74, 58, 38, 15, 1, 16, 37, 56, 71, 80, 85, 88, 86, 92, 97, 99, + 98, 94, 88, 82, 78, 74, 67, 58, 55, 53, 47, 38, 32, 33, 34, 33, 27, + 21, 14, 8, 5, 5, 11, 21, 28, 32, 32, 38, 45, 45, 38, 26, 15, 13, + 9, 2, 7, 9, 14, 21, 29, 38, 46, 54, 59, 61, 63, 62, 56, 46, 31, + 13, 0, 2, 7, 12, 14, 14, 11, 4, 0, 0, 2, 2, 0, 0, 0, 0, + 0, 0, 3, 12, 18, 28, 39, 43, 41, 51, 58, 60, 55, 43, 23, 3, 4, + 13, 16, 15, 9, 1, 0, 0, 0, 0, 4, 6, 6, 5, 8, 8, 8, 20, + 34, 47, 56, 60, 60, 55, 53, 54, 50, 38, 22, 7, 0, 0, 0, 0, 0, + 4, 9, 11, 8, 13, 32, 46, 56, 62, 66, 68, 70, 71, 74, 87, 96,102, +104,103,100,102, 99, 93, 88, 80, 71, 57, 37, 23, 15, 14, 8, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, + 0, 5, 18, 31, 44, 52, 54, 48, 36, 15, 0, 0, 9, 32, 51, 61, 68, + 71, 73, 71, 68, 70, 67, 60, 48, 36, 43, 53, 56, 53, 46, 36, 29, 27, + 19, 5, 4, 4, 4, 1, 0, 0, 0, 1, 3, 2, 0, 0, 0, 5, 12, + 21, 39, 54, 60, 61, 56, 44, 41, 57, 73, 84, 92, 96, 97, 97, 96, 93, + 88, 79, 68, 51, 28, 5, 0, 7, 28, 50, 66, 76, 82, 84, 82, 87, 91, + 91, 88, 82, 74, 68, 64, 61, 54, 47, 48, 47, 43, 34, 22, 26, 29, 31, + 26, 18, 7, 1, 0, 0, 12, 26, 37, 43, 44, 40, 46, 50, 47, 40, 27, + 16, 12, 5, 2, 5, 14, 29, 43, 48, 51, 54, 58, 59, 59, 59, 54, 43, + 26, 8, 0, 0, 5, 6, 9, 13, 13, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 15, 22, 34, 45, 50, 47, 57, 65, 69, 65, 55, 38, 15, + 0, 7, 11, 11, 5, 0, 0, 0, 0, 0, 0, 1, 3, 2, 0, 0, 0, + 0, 15, 32, 45, 54, 57, 55, 48, 52, 50, 43, 31, 16, 4, 0, 0, 0, + 0, 1, 6, 7, 8, 13, 19, 33, 43, 51, 61, 67, 70, 68, 61, 76, 88, + 96,101,102,102, 99, 96, 92, 88, 83, 75, 64, 47, 26, 4, 4, 0, 0, + 0, 0, 0, 0, 0, 6, 13, 15, 14, 7, 0, 0, 0, 0, 0, 0, 0, + 2, 6, 9, 11, 23, 37, 45, 48, 43, 29, 9, 0, 0, 13, 34, 51, 60, + 64, 66, 67, 72, 75, 77, 74, 67, 55, 39, 21, 32, 37, 37, 31, 22, 12, + 5, 0, 2, 8, 14, 15, 11, 4, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 11, 28, 47, 60, 66, 67, 61, 50, 34, 54, 69, 79, 87, 91, 92, 91, 89, + 86, 81, 72, 58, 39, 15, 0, 0, 0, 20, 43, 61, 73, 79, 79, 77, 84, + 85, 83, 77, 69, 58, 52, 45, 45, 43, 44, 41, 38, 33, 26, 15, 21, 26, + 28, 25, 16, 5, 0, 0, 0, 11, 27, 40, 47, 51, 48, 43, 51, 52, 48, + 40, 28, 15, 7, 0, 11, 28, 45, 57, 63, 65, 62, 58, 60, 61, 57, 48, + 34, 18, 1, 0, 0, 0, 2, 4, 8, 9, 6, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 14, 26, 41, 53, 57, 56, 58, 66, 71, 69, 61, 46, + 27, 9, 7, 7, 6, 4, 1, 4, 8, 11, 8, 5, 7, 7, 5, 1, 0, + 0, 0, 0, 14, 31, 44, 51, 52, 48, 48, 50, 46, 39, 28, 19, 9, 5, + 5, 6, 7, 6, 13, 18, 22, 28, 37, 47, 58, 66, 72, 74, 73, 65, 63, + 78, 88, 97,102,104,104,102, 97, 88, 81, 76, 67, 53, 33, 12, 7, 2, + 0, 0, 0, 0, 2, 7, 18, 25, 28, 27, 21, 12, 2, 0, 0, 0, 0, + 3, 11, 18, 22, 23, 20, 28, 38, 40, 37, 25, 6, 0, 6, 16, 32, 46, + 54, 57, 67, 74, 79, 81, 81, 78, 70, 57, 39, 21, 22, 22, 22, 19, 13, + 9, 7, 7, 13, 19, 22, 25, 25, 19, 7, 0, 0, 0, 0, 0, 0, 2, + 11, 23, 40, 57, 68, 73, 73, 67, 56, 44, 50, 64, 75, 82, 86, 92, 96, + 94, 88, 79, 67, 52, 33, 13, 0, 0, 6, 18, 38, 57, 69, 75, 77, 74, + 78, 78, 74, 66, 54, 47, 52, 53, 51, 48, 46, 41, 34, 25, 15, 11, 18, + 22, 23, 20, 13, 3, 0, 0, 0, 6, 22, 37, 46, 51, 51, 47, 47, 52, + 52, 48, 40, 29, 20, 12, 23, 41, 57, 68, 74, 77, 75, 72, 64, 58, 56, + 47, 33, 14, 0, 0, 0, 0, 0, 0, 3, 4, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 12, 29, 45, 57, 63, 63, 56, 63, 68, 68, 62, + 51, 34, 21, 21, 20, 16, 13, 16, 23, 27, 27, 25, 20, 18, 19, 18, 14, + 8, 1, 0, 0, 4, 18, 28, 38, 44, 44, 48, 52, 52, 48, 44, 38, 32, + 28, 29, 31, 31, 29, 26, 31, 36, 40, 48, 58, 67, 74, 79, 80, 78, 72, + 60, 65, 81, 92,102,107,109,109,103, 92, 79, 76, 69, 57, 39, 18, 13, + 7, 1, 0, 0, 3, 8, 14, 26, 34, 39, 39, 33, 23, 13, 3, 0, 0, + 2, 11, 20, 27, 32, 33, 31, 23, 25, 28, 26, 16, 9, 5, 12, 20, 27, + 40, 47, 60, 74, 80, 84, 87, 86, 80, 71, 57, 38, 27, 28, 28, 27, 26, + 23, 21, 20, 22, 26, 32, 40, 43, 40, 32, 20, 7, 3, 1, 0, 0, 5, + 14, 26, 40, 55, 67, 76, 79, 79, 73, 63, 53, 59, 67, 75, 83, 90, 96, + 99, 98, 92, 85, 74, 61, 44, 23, 4, 2, 13, 22, 34, 55, 68, 74, 75, + 72, 69, 68, 63, 53, 43, 48, 56, 56, 53, 50, 44, 37, 28, 18, 4, 5, + 11, 15, 16, 14, 8, 1, 5, 6, 6, 7, 14, 29, 41, 47, 50, 48, 45, + 53, 56, 55, 51, 43, 33, 25, 37, 52, 65, 76, 83, 87, 88, 85, 79, 69, + 54, 47, 36, 19, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 11, 27, 45, 58, 66, 67, 62, 57, 63, 64, + 60, 52, 40, 38, 36, 32, 27, 31, 36, 40, 43, 41, 37, 32, 28, 28, 27, + 22, 18, 12, 2, 8, 14, 20, 25, 33, 37, 40, 48, 53, 56, 57, 56, 54, + 52, 51, 51, 52, 52, 50, 46, 41, 45, 51, 58, 67, 74, 80, 84, 84, 82, + 76, 65, 53, 73, 88, 99,107,111,111,105, 94, 81, 76, 71, 59, 41, 21, + 18, 11, 5, 0, 2, 9, 16, 20, 31, 41, 47, 47, 43, 33, 21, 11, 6, + 3, 11, 19, 26, 32, 37, 39, 37, 31, 21, 13, 13, 18, 20, 19, 16, 22, + 28, 34, 50, 65, 77, 84, 88, 90, 88, 82, 72, 56, 37, 36, 36, 36, 36, + 34, 33, 32, 32, 36, 46, 54, 57, 56, 52, 43, 32, 20, 15, 12, 7, 5, + 14, 27, 40, 54, 66, 76, 82, 84, 83, 78, 70, 60, 65, 73, 79, 86, 92, + 96, 99, 99, 96, 89, 81, 70, 53, 32, 13, 9, 14, 22, 34, 55, 68, 74, + 74, 71, 64, 57, 51, 41, 40, 51, 56, 56, 52, 48, 41, 32, 20, 9, 0, + 0, 3, 6, 7, 7, 12, 19, 21, 19, 13, 12, 11, 18, 32, 41, 46, 47, + 44, 53, 60, 62, 59, 52, 43, 34, 46, 58, 70, 80, 88, 93, 96, 96, 92, + 83, 71, 54, 39, 27, 12, 11, 1, 0, 0, 0, 0, 0, 0, 0, 3, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 7, 21, 39, 54, 63, 66, 63, 59, 57, + 59, 57, 52, 53, 53, 48, 44, 43, 48, 52, 54, 54, 50, 45, 40, 39, 37, + 33, 28, 23, 19, 12, 16, 25, 32, 38, 41, 45, 47, 48, 53, 57, 60, 62, + 64, 64, 63, 63, 64, 64, 62, 59, 54, 50, 55, 62, 71, 79, 84, 87, 87, + 84, 78, 67, 48, 64, 83, 95,103,108,108,102, 92, 79, 78, 73, 61, 44, + 23, 19, 13, 6, 2, 6, 16, 23, 25, 36, 46, 53, 54, 50, 41, 28, 16, + 12, 13, 18, 23, 28, 32, 36, 38, 38, 33, 27, 25, 21, 23, 29, 32, 32, + 32, 36, 40, 53, 66, 76, 84, 89, 91, 88, 82, 71, 54, 41, 44, 43, 41, + 40, 39, 38, 40, 47, 56, 64, 68, 68, 65, 59, 51, 41, 36, 28, 21, 15, + 12, 21, 36, 51, 63, 74, 81, 85, 86, 84, 79, 74, 66, 68, 75, 81, 87, + 91, 95, 97, 97, 96, 92, 86, 76, 60, 39, 20, 14, 11, 16, 36, 55, 68, + 74, 74, 70, 63, 55, 45, 34, 43, 50, 54, 54, 56, 54, 48, 38, 25, 8, + 0, 0, 0, 2, 15, 26, 34, 38, 36, 29, 20, 14, 13, 11, 21, 34, 41, + 44, 41, 55, 64, 67, 65, 58, 47, 44, 52, 61, 72, 81, 90, 97,102,105, +102, 94, 84, 69, 51, 34, 23, 23, 14, 7, 2, 0, 0, 0, 0, 0, 2, + 1, 0, 0, 1, 4, 1, 0, 0, 0, 4, 14, 28, 44, 55, 59, 59, 59, + 59, 60, 61, 63, 63, 62, 58, 52, 57, 62, 64, 64, 60, 55, 48, 50, 47, + 44, 38, 33, 27, 23, 20, 23, 33, 41, 47, 51, 52, 52, 52, 51, 55, 60, + 64, 67, 69, 70, 69, 70, 69, 68, 65, 60, 55, 53, 61, 70, 78, 83, 86, + 86, 83, 76, 65, 52, 57, 77, 89, 97,101,101, 95, 85, 80, 80, 74, 62, + 44, 25, 19, 12, 5, 3, 9, 21, 29, 32, 38, 50, 57, 59, 55, 46, 33, + 19, 21, 22, 23, 25, 26, 27, 29, 32, 33, 40, 44, 44, 39, 34, 38, 43, + 43, 44, 45, 47, 52, 62, 72, 79, 85, 88, 86, 80, 69, 53, 46, 47, 46, + 44, 41, 43, 47, 53, 60, 67, 74, 75, 74, 70, 63, 56, 54, 48, 41, 38, + 33, 26, 25, 40, 56, 68, 77, 83, 85, 85, 83, 79, 74, 69, 67, 74, 79, + 84, 88, 91, 93, 94, 95, 93, 88, 79, 64, 41, 23, 15, 6, 13, 38, 57, + 68, 73, 72, 67, 60, 52, 40, 34, 41, 47, 52, 57, 60, 59, 54, 44, 28, + 9, 0, 0, 0, 19, 36, 47, 53, 53, 47, 36, 23, 13, 12, 11, 9, 25, + 36, 39, 41, 58, 68, 72, 70, 61, 50, 51, 55, 61, 70, 79, 88, 97,105, +110,109,102, 92, 80, 63, 43, 33, 33, 26, 20, 13, 4, 0, 0, 0, 0, + 1, 1, 0, 0, 4, 7, 5, 0, 0, 0, 0, 6, 16, 28, 40, 47, 50, + 53, 57, 61, 65, 68, 69, 68, 63, 63, 69, 73, 74, 71, 65, 57, 58, 58, + 54, 48, 45, 43, 39, 29, 27, 29, 40, 50, 54, 56, 55, 54, 52, 48, 48, + 54, 60, 64, 68, 69, 69, 69, 68, 67, 64, 60, 56, 51, 54, 63, 72, 78, + 81, 81, 78, 72, 60, 57, 59, 71, 83, 89, 92, 90, 85, 80, 84, 84, 77, + 63, 43, 22, 16, 9, 2, 3, 12, 25, 33, 37, 40, 53, 60, 63, 60, 51, + 37, 27, 28, 27, 25, 21, 19, 18, 18, 22, 37, 50, 56, 58, 55, 48, 43, + 48, 51, 50, 50, 50, 51, 54, 62, 71, 78, 82, 81, 76, 67, 53, 46, 47, + 45, 46, 48, 51, 54, 59, 65, 72, 77, 77, 75, 71, 65, 67, 66, 58, 53, + 53, 51, 43, 41, 40, 56, 69, 77, 81, 83, 82, 79, 75, 71, 68, 62, 71, + 76, 80, 84, 88, 88, 90, 92, 93, 90, 81, 66, 41, 23, 13, 3, 18, 41, + 58, 67, 70, 68, 63, 57, 47, 36, 32, 39, 44, 52, 57, 61, 61, 57, 47, + 31, 9, 0, 0, 11, 33, 52, 62, 66, 63, 55, 40, 29, 13, 9, 8, 7, + 16, 29, 34, 45, 61, 72, 75, 73, 63, 55, 55, 60, 75, 86, 92, 96, 94, +103,110,111,107, 99, 88, 74, 54, 40, 38, 32, 27, 20, 12, 1, 0, 0, + 0, 0, 1, 0, 2, 8, 11, 8, 1, 0, 0, 0, 0, 5, 12, 20, 27, + 33, 40, 47, 56, 62, 67, 70, 69, 65, 73, 79, 81, 80, 76, 68, 62, 64, + 63, 58, 52, 50, 50, 46, 38, 36, 36, 46, 54, 57, 57, 55, 52, 48, 48, + 47, 52, 54, 57, 61, 63, 63, 63, 62, 61, 59, 55, 51, 47, 45, 52, 62, + 69, 74, 74, 70, 64, 56, 61, 62, 64, 75, 80, 81, 79, 76, 84, 88, 86, + 78, 63, 40, 18, 12, 5, 0, 3, 12, 23, 33, 37, 43, 56, 64, 67, 64, + 55, 41, 32, 31, 27, 21, 15, 12, 9, 5, 21, 39, 54, 64, 68, 66, 60, + 51, 51, 52, 51, 48, 46, 50, 52, 51, 59, 68, 74, 75, 73, 64, 53, 43, + 48, 50, 51, 52, 53, 55, 59, 65, 72, 76, 76, 74, 73, 75, 76, 73, 63, + 61, 63, 62, 57, 57, 56, 54, 67, 74, 78, 79, 78, 74, 71, 67, 65, 60, + 65, 71, 78, 87, 92, 92, 87, 91, 92, 90, 81, 66, 40, 21, 9, 11, 22, + 44, 58, 65, 66, 62, 57, 51, 43, 31, 27, 34, 40, 47, 53, 57, 59, 56, + 47, 31, 8, 0, 0, 18, 44, 62, 73, 74, 70, 59, 46, 38, 22, 11, 6, + 6, 12, 25, 31, 48, 65, 75, 79, 74, 64, 60, 59, 73, 88,100,108,111, +108,102,107,109,108,102, 93, 80, 63, 44, 36, 31, 27, 22, 15, 6, 1, + 0, 0, 0, 0, 0, 7, 13, 15, 13, 5, 8, 6, 1, 1, 0, 0, 2, + 6, 20, 31, 39, 45, 53, 60, 64, 64, 72, 79, 85, 88, 86, 80, 73, 63, + 65, 64, 60, 54, 52, 51, 48, 41, 46, 46, 51, 56, 57, 54, 50, 45, 51, + 55, 55, 57, 61, 61, 59, 55, 56, 56, 55, 54, 52, 48, 45, 40, 39, 39, + 50, 58, 63, 64, 61, 55, 60, 63, 62, 58, 68, 72, 71, 69, 79, 86, 89, + 87, 78, 61, 38, 12, 6, 0, 0, 3, 7, 20, 28, 32, 47, 60, 69, 72, + 69, 61, 47, 31, 26, 21, 16, 15, 14, 11, 15, 20, 40, 58, 70, 74, 74, + 69, 59, 48, 48, 46, 44, 47, 52, 53, 52, 47, 57, 65, 69, 69, 66, 60, + 53, 47, 50, 51, 55, 60, 65, 68, 70, 69, 74, 74, 76, 79, 80, 79, 74, + 64, 67, 70, 70, 66, 68, 68, 66, 64, 73, 75, 76, 74, 75, 74, 71, 62, + 57, 59, 69, 80, 88, 92, 92, 86, 90, 92, 90, 81, 65, 39, 21, 8, 16, + 22, 43, 55, 60, 60, 55, 50, 46, 38, 27, 21, 31, 38, 43, 43, 48, 52, + 51, 43, 27, 15, 1, 0, 21, 48, 67, 77, 79, 74, 63, 47, 39, 23, 12, + 7, 7, 11, 23, 29, 52, 68, 78, 80, 76, 68, 67, 65, 80, 96,110,120, +123,120,112,103,107,107,104, 96, 85, 71, 53, 44, 28, 25, 22, 16, 8, + 6, 3, 0, 0, 3, 7, 13, 18, 19, 15, 16, 21, 21, 15, 7, 0, 0, + 0, 1, 12, 23, 33, 40, 47, 53, 59, 66, 74, 83, 88, 89, 87, 82, 74, + 64, 63, 62, 59, 55, 51, 48, 48, 53, 57, 57, 55, 55, 52, 46, 44, 52, + 57, 59, 59, 57, 62, 63, 62, 60, 57, 55, 53, 52, 52, 51, 51, 48, 43, + 36, 39, 50, 55, 57, 54, 53, 57, 59, 57, 50, 59, 62, 61, 71, 79, 85, + 88, 84, 74, 56, 31, 6, 0, 0, 0, 3, 8, 15, 23, 37, 52, 64, 73, + 75, 73, 65, 52, 36, 21, 18, 16, 14, 11, 13, 22, 28, 45, 62, 74, 79, + 79, 74, 65, 55, 47, 45, 46, 47, 50, 50, 46, 41, 50, 59, 66, 69, 69, + 65, 61, 58, 58, 61, 65, 70, 74, 75, 76, 74, 74, 76, 78, 79, 79, 75, + 69, 68, 70, 73, 73, 69, 74, 74, 74, 73, 74, 77, 80, 82, 83, 82, 78, + 70, 59, 59, 71, 80, 88, 91, 89, 89, 92, 94, 91, 81, 64, 38, 19, 12, + 19, 21, 38, 48, 53, 52, 54, 58, 54, 44, 28, 18, 28, 39, 45, 46, 39, + 37, 38, 33, 31, 22, 8, 4, 19, 45, 65, 76, 79, 76, 66, 51, 32, 16, + 9, 9, 9, 14, 26, 34, 55, 71, 79, 82, 78, 74, 73, 71, 84, 99,113, +123,128,125,119,110,103,104,102, 96, 86, 74, 59, 44, 27, 22, 20, 15, + 11, 12, 11, 9, 9, 13, 16, 20, 21, 21, 20, 29, 36, 36, 32, 23, 13, + 3, 0, 0, 2, 12, 22, 31, 38, 45, 53, 62, 72, 79, 84, 85, 83, 77, + 69, 61, 62, 60, 58, 55, 54, 54, 56, 62, 67, 66, 60, 53, 45, 40, 52, + 58, 60, 61, 59, 54, 56, 58, 58, 57, 55, 54, 53, 53, 52, 52, 51, 48, + 43, 34, 34, 41, 48, 51, 50, 45, 50, 50, 45, 37, 46, 50, 62, 74, 79, + 84, 83, 77, 65, 46, 21, 2, 0, 0, 0, 0, 6, 14, 26, 39, 54, 65, + 73, 74, 72, 63, 51, 36, 21, 14, 12, 8, 5, 18, 26, 31, 51, 66, 76, + 80, 80, 76, 68, 58, 52, 47, 46, 45, 43, 40, 36, 31, 41, 52, 60, 65, + 67, 66, 64, 63, 65, 69, 72, 74, 76, 76, 75, 74, 73, 74, 74, 74, 72, + 68, 69, 70, 72, 74, 72, 70, 74, 76, 76, 77, 79, 84, 87, 88, 88, 86, + 81, 74, 63, 60, 71, 79, 85, 88, 90, 93, 96, 96, 90, 79, 61, 33, 15, + 13, 18, 16, 29, 39, 44, 54, 62, 65, 60, 47, 29, 25, 27, 39, 47, 50, + 43, 27, 22, 29, 32, 27, 18, 13, 18, 36, 56, 69, 74, 73, 65, 51, 33, + 16, 12, 11, 9, 20, 29, 41, 60, 74, 81, 82, 78, 75, 75, 75, 86, 98, +111,121,127,125,121,113,105, 97, 95, 89, 81, 71, 57, 37, 23, 18, 14, + 11, 9, 14, 16, 21, 23, 23, 25, 26, 26, 22, 29, 41, 47, 48, 45, 38, + 28, 19, 9, 5, 0, 0, 7, 16, 23, 32, 41, 52, 63, 71, 75, 76, 74, + 68, 61, 59, 59, 57, 55, 56, 59, 61, 64, 69, 74, 73, 65, 51, 38, 46, + 56, 61, 60, 58, 53, 46, 41, 46, 47, 48, 48, 48, 47, 47, 47, 45, 44, + 41, 37, 33, 33, 36, 43, 46, 45, 40, 37, 34, 27, 23, 36, 54, 67, 75, + 79, 79, 75, 66, 52, 31, 8, 0, 0, 0, 0, 0, 2, 11, 23, 39, 53, + 63, 69, 70, 65, 57, 45, 31, 18, 7, 4, 1, 9, 21, 28, 38, 55, 68, + 76, 79, 79, 74, 66, 57, 51, 46, 43, 39, 33, 27, 19, 20, 31, 41, 50, + 56, 59, 60, 61, 63, 67, 71, 74, 74, 74, 73, 70, 67, 68, 70, 69, 68, + 67, 67, 67, 68, 69, 69, 66, 67, 71, 74, 75, 78, 83, 88, 92, 93, 92, + 88, 83, 74, 66, 65, 74, 80, 86, 90, 94, 97, 99, 96, 88, 75, 55, 27, + 8, 13, 14, 9, 21, 34, 51, 63, 70, 71, 64, 50, 37, 34, 29, 38, 46, + 50, 43, 28, 12, 23, 31, 31, 25, 20, 26, 29, 41, 56, 63, 64, 59, 47, + 32, 15, 14, 13, 16, 28, 36, 51, 67, 77, 82, 82, 77, 75, 76, 79, 85, + 95,104,113,118,120,119,113,107, 97, 88, 79, 71, 61, 50, 26, 18, 11, + 5, 1, 5, 14, 26, 32, 36, 38, 36, 32, 29, 26, 38, 50, 56, 57, 54, + 48, 40, 32, 25, 20, 14, 4, 0, 0, 7, 15, 29, 37, 50, 58, 62, 63, + 60, 55, 55, 57, 55, 52, 56, 60, 64, 67, 70, 72, 78, 77, 69, 55, 40, + 48, 57, 59, 56, 50, 41, 33, 23, 27, 31, 34, 36, 37, 38, 38, 37, 36, + 32, 29, 29, 31, 31, 29, 37, 40, 39, 37, 31, 25, 19, 28, 46, 60, 71, + 76, 76, 73, 65, 53, 36, 20, 8, 0, 0, 0, 0, 2, 2, 5, 19, 36, + 50, 58, 62, 61, 56, 47, 34, 22, 12, 3, 0, 2, 14, 23, 28, 44, 58, + 67, 73, 74, 72, 66, 58, 51, 45, 40, 36, 29, 21, 11, 2, 7, 16, 26, + 33, 39, 44, 47, 52, 56, 61, 66, 69, 70, 68, 65, 60, 60, 64, 64, 64, + 62, 61, 60, 60, 61, 61, 58, 53, 59, 64, 68, 72, 77, 84, 91, 95, 96, + 95, 90, 83, 74, 71, 72, 79, 85, 91, 95, 97,100,100, 95, 85, 70, 48, + 20, 7, 11, 7, 4, 26, 46, 61, 71, 74, 74, 66, 51, 46, 45, 39, 32, + 40, 43, 38, 25, 16, 18, 26, 29, 28, 22, 31, 36, 38, 38, 47, 51, 48, + 39, 25, 13, 14, 15, 29, 39, 44, 59, 73, 80, 84, 82, 76, 72, 75, 79, + 84, 89, 96,102,107,110,112,110,105, 98, 89, 79, 67, 53, 38, 21, 11, + 1, 0, 0, 4, 19, 31, 40, 45, 48, 47, 40, 34, 29, 41, 54, 60, 61, + 59, 55, 48, 41, 36, 33, 29, 19, 4, 0, 0, 3, 18, 26, 32, 41, 45, + 46, 44, 48, 52, 52, 51, 55, 63, 68, 69, 68, 72, 73, 78, 78, 72, 59, + 53, 54, 53, 53, 46, 37, 26, 19, 18, 16, 21, 21, 20, 22, 25, 26, 25, + 22, 22, 23, 25, 26, 26, 23, 28, 32, 32, 31, 26, 22, 22, 40, 55, 65, + 72, 74, 72, 63, 52, 45, 37, 23, 8, 0, 0, 0, 9, 16, 16, 9, 12, + 28, 43, 51, 53, 51, 45, 34, 25, 15, 6, 0, 0, 7, 19, 26, 31, 47, + 58, 64, 66, 64, 59, 52, 44, 37, 33, 29, 23, 16, 7, 0, 0, 0, 4, + 8, 13, 18, 22, 27, 33, 40, 50, 56, 60, 60, 58, 53, 46, 53, 56, 56, + 54, 52, 50, 47, 47, 47, 46, 41, 40, 47, 53, 59, 65, 74, 84, 92, 97, +100, 97, 91, 83, 78, 75, 78, 85, 90, 95, 97,100,102,100, 92, 80, 63, + 40, 15, 5, 5, 0, 12, 37, 57, 69, 75, 76, 74, 65, 55, 56, 54, 46, + 33, 28, 31, 27, 20, 15, 12, 21, 26, 26, 22, 29, 38, 41, 41, 38, 32, + 32, 25, 15, 11, 14, 33, 45, 52, 54, 68, 79, 84, 84, 81, 74, 67, 73, + 79, 87, 94,100,103,102, 99,102,102,100, 96, 89, 79, 67, 52, 34, 11, + 0, 0, 0, 0, 6, 20, 34, 45, 52, 56, 57, 53, 44, 36, 40, 54, 60, + 62, 60, 57, 53, 54, 48, 44, 41, 33, 18, 1, 0, 0, 4, 12, 16, 22, + 27, 32, 38, 41, 44, 47, 53, 61, 71, 77, 77, 73, 69, 71, 76, 78, 74, + 64, 61, 61, 56, 44, 32, 20, 23, 25, 21, 13, 12, 9, 6, 8, 12, 12, + 11, 8, 12, 14, 15, 16, 16, 14, 20, 22, 23, 21, 20, 18, 33, 50, 61, + 68, 72, 71, 65, 57, 58, 54, 44, 27, 7, 0, 0, 8, 23, 31, 31, 23, + 12, 21, 33, 40, 43, 39, 32, 27, 23, 13, 1, 0, 8, 15, 23, 28, 31, + 46, 54, 57, 55, 50, 41, 32, 23, 18, 15, 13, 9, 7, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 8, 19, 29, 40, 46, 47, 44, 38, 33, 40, 43, + 41, 39, 34, 31, 28, 26, 26, 23, 18, 25, 32, 40, 52, 63, 71, 83, 92, + 99,102, 99, 92, 83, 80, 77, 84, 90, 95, 97, 99,100,100, 97, 88, 75, + 56, 34, 20, 3, 0, 0, 21, 46, 65, 74, 78, 76, 72, 62, 64, 65, 60, + 51, 34, 15, 13, 12, 11, 11, 8, 14, 19, 20, 20, 23, 33, 40, 41, 38, + 27, 13, 8, 2, 7, 31, 50, 60, 65, 65, 74, 84, 87, 86, 81, 74, 68, + 72, 76, 87, 96,104,109,107,102, 92, 92, 92, 90, 84, 76, 63, 46, 26, + 0, 0, 0, 0, 11, 19, 25, 37, 48, 57, 63, 66, 64, 58, 47, 39, 50, + 57, 59, 59, 60, 65, 66, 62, 53, 53, 45, 33, 16, 0, 0, 0, 0, 2, + 7, 14, 20, 26, 31, 38, 46, 52, 67, 78, 84, 84, 79, 69, 65, 74, 76, + 74, 68, 67, 65, 59, 46, 26, 26, 29, 29, 23, 13, 0, 0, 0, 0, 1, + 3, 1, 0, 0, 2, 3, 4, 3, 5, 8, 11, 12, 11, 9, 22, 40, 55, + 64, 70, 70, 67, 62, 67, 68, 62, 50, 29, 5, 0, 0, 18, 34, 44, 44, + 37, 23, 16, 26, 32, 33, 29, 25, 26, 21, 8, 1, 13, 23, 31, 31, 32, + 31, 39, 46, 45, 39, 29, 21, 13, 2, 0, 0, 3, 15, 22, 23, 18, 7, + 8, 11, 7, 0, 0, 0, 0, 0, 0, 7, 19, 27, 29, 28, 22, 15, 22, + 23, 22, 18, 13, 8, 4, 2, 1, 0, 4, 11, 22, 40, 55, 65, 69, 82, + 93,101,104,102, 94, 84, 80, 83, 89, 94, 97, 99, 99, 99, 98, 94, 84, + 70, 53, 39, 21, 2, 0, 0, 28, 54, 70, 78, 79, 75, 69, 69, 72, 71, + 63, 51, 31, 8, 0, 0, 0, 4, 7, 7, 9, 11, 12, 13, 25, 33, 37, + 33, 22, 5, 0, 0, 20, 46, 64, 74, 77, 76, 80, 88, 90, 88, 83, 79, + 77, 71, 72, 84, 96,105,110,108,101, 89, 81, 82, 81, 77, 68, 53, 33, 13 +}; diff --git a/examples/src/ssg/majik/image_map.h b/examples/src/ssg/majik/image_map.h new file mode 100644 index 0000000..e0048b8 --- /dev/null +++ b/examples/src/ssg/majik/image_map.h @@ -0,0 +1,13111 @@ + +unsigned char image_map [] = +{ + 30, 2,128, 87, 65,237,120,122, 70,124,150, 22,124,167, 6, + 122,175, 0,122,178, 0,121,180, 0,121,181, 0,119,187, 0, + 117,192, 0,115,194, 0,115,195, 0,116,193, 0,118,188, 0, + 121,182, 0,123,173, 1,121,179, 0,121,182, 0,120,184, 0, + 118,189, 0,116,192, 0,116,193, 0,117,191, 0,119,186, 0, + 119,186, 0,120,183, 0,122,176, 0,124,164, 9,123,139, 37, + 114,104,197, 87, 65,237, 30, 2,128, 69, 60,230,109, 92,251, + 115,107,129,118,114, 96,121,127, 58,124,147, 26,124,161, 11, + 123,169, 4,120,182, 0,117,192, 0,113,198, 0,111,202, 0, + 111,202, 0,113,199, 0,116,193, 0,120,184, 0,117,192, 0, + 115,194, 0,115,194, 0,116,193, 0,117,191, 0,118,189, 0, + 119,186, 0,122,177, 0,122,175, 0,123,172, 2,124,167, 6, + 124,161, 11,124,150, 22,121,127, 58, 99, 75,247, 30, 2,128, + 94, 70,242,117,110,109,121,127, 58,122,130, 53,121,125, 63, + 117,110,109,105, 84,252, 30, 43,203, 30, 37,192, 30, 43,203, + 30, 55,222, 99, 75,247,109, 92,251,111, 96,248,111, 96,248, + 109, 92,251,121,127, 58,124,155, 16,123,172, 2,120,183, 0, + 118,188, 0,117,191, 0,117,191, 0,118,188, 0,117,192, 0, + 115,194, 0,115,194, 0,118,189, 0,121,180, 0,124,160, 12, + 115,107,129, 30, 2,128,114,104,197,124,152, 20,123,171, 3, + 122,178, 0,122,178, 0,123,173, 1,124,162, 10,124,145, 29, + 124,152, 20,124,160, 12,124,161, 11,124,157, 15,124,150, 22, + 124,149, 24,123,141, 34,117,110,109,123,139, 37,124,160, 12, + 123,170, 3,122,175, 0,122,175, 0,123,170, 3,124,162, 10, + 124,157, 15,124,162, 10,124,158, 13,124,152, 20,124,147, 26, + 123,137, 41,118,117, 85, 99, 75,247, 30, 2,128,107, 89,252, + 123,139, 37,124,161, 11,123,170, 3,123,172, 2,123,168, 5, + 124,160, 12,124,147, 26,124,150, 22,124,143, 31,122,130, 53, + 121,125, 63,118,117, 85,113,100,242, 87, 65,237, 30, 10,132, + 30, 49,213,113,100,242,121,127, 58,123,137, 41,123,137, 41, + 121,127, 58,118,114, 96,113,100,242,114,104,197,111, 96,248, + 111, 96,248,111, 96,248,107, 89,252, 99, 75,247, 30, 43,203, + 30, 2,128, 30, 43,203,102, 80,250,120,122, 70,124,154, 18, + 123,171, 3,121,182, 0,118,188, 0,117,190, 0,112,199, 0, + 107,206, 0,104,210, 0,102,212, 0,103,211, 0,106,207, 0, + 110,202, 0,114,196, 0,111,202, 0,108,205, 0,106,207, 0, + 105,209, 0,103,211, 0,103,212, 0,104,210, 0,107,207, 0, + 109,204, 0,113,198, 0,117,191, 0,120,183, 0,123,171, 3, + 124,149, 24,113,100,242, 30, 2,128,117,110,109,124,164, 9, + 120,184, 0,116,193, 0,114,197, 0,114,197, 0,115,194, 0, + 118,189, 0,116,193, 0,115,194, 0,116,193, 0,119,187, 0, + 122,176, 0,124,154, 18,115,107,129, 30, 26,168, 30, 55,222, + 87, 65,237,109, 92,251,118,114, 96,120,122, 70,121,125, 63, + 120,122, 70,117,110,109,119,119, 77,122,130, 53,124,149, 24, + 124,155, 16,124,152, 20,123,137, 41,109, 92,251, 30, 2,128, + 115,107,129,124,162, 10,120,183, 0,115,194, 0,112,200, 0, + 111,202, 0,111,202, 0,111,201, 0,108,205, 0,108,206, 0, + 109,204, 0,110,202, 0,111,202, 0,112,200, 0,114,196, 0, + 118,189, 0,114,197, 0,109,204, 0,105,209, 0,103,211, 0, + 104,210, 0,107,206, 0,112,200, 0,117,191, 0,117,192, 0, + 117,191, 0,118,188, 0,121,180, 0,124,166, 7,123,137, 41, + 99, 75,247,109, 92,251,122,130, 53,124,157, 15,123,172, 2, + 121,182, 0,119,187, 0,118,189, 0,117,191, 0,117,191, 0, + 117,191, 0,114,197, 0,112,200, 0,111,202, 0,111,201, 0, + 113,198, 0,116,193, 0,118,188, 0,120,183, 0,119,185, 0, + 118,189, 0,116,193, 0,115,195, 0,114,196, 0,115,194, 0, + 117,191, 0,117,192, 0,117,191, 0,119,186, 0,121,179, 0, + 124,167, 6,124,150, 22,121,125, 63,114,104,197,105, 84,252, + 102, 80,250,111, 96,248,117,110,109,121,127, 58,124,145, 29, + 124,160, 12,123,173, 1,119,185, 0,115,194, 0,112,200, 0, + 110,203, 0,110,203, 0,111,201, 0,115,195, 0,118,189, 0, + 117,190, 0,115,194, 0,114,196, 0,115,195, 0,116,193, 0, + 117,192, 0,118,188, 0,119,186, 0,120,184, 0,120,182, 0, + 122,178, 0,123,169, 4,124,154, 18,121,127, 58,107, 89,252, + 109, 92,251,115,107,129,121,125, 63,123,139, 37,124,143, 31, + 123,139, 37,121,127, 58,115,107,129,102, 80,250, 30, 43,203, + 30, 43,203, 30, 43,203, 69, 60,230,105, 84,252,114,104,197, + 121,125, 63,124,143, 31,124,155, 16,124,162, 10,123,172, 2, + 120,183, 0,118,189, 0,117,192, 0,117,192, 0,116,193, 0, + 114,197, 0,113,198, 0,114,196, 0,117,191, 0,121,179, 0, + 124,157, 15,111, 96,248, 94, 70,242,118,114, 96,124,155, 16, + 123,173, 1,121,180, 0,121,181, 0,122,177, 0,124,167, 6, + 124,154, 18,124,150, 22,124,158, 13,124,161, 11,124,158, 13, + 124,154, 18,124,145, 29,122,132, 48,123,141, 34,124,160, 12, + 123,172, 2,121,181, 0,120,184, 0,120,184, 0,121,181, 0, + 123,174, 1,124,164, 9,124,152, 20,124,147, 26,123,141, 34, + 122,130, 53,118,114, 96, 99, 75,247, 30, 49,213, 94, 70,242, + 121,125, 63,124,160, 12,122,175, 0,120,183, 0,119,185, 0, + 120,184, 0,121,180, 0,123,174, 1,123,169, 4,124,167, 6, + 124,165, 8,124,161, 11,124,157, 15,124,147, 26,122,130, 53, + 113,100,242, 99, 75,247,109, 92,251,113,100,242,111, 96,248, + 114,104,197,111, 96,248,102, 80,250, 87, 65,237, 69, 60,230, + 99, 75,247,107, 89,252,113,100,242,115,107,129,114,104,197, + 114,104,197,115,107,129,118,114, 96,120,122, 70,122,132, 48, + 124,152, 20,123,169, 4,121,179, 0,119,185, 0,117,191, 0, + 112,200, 0,107,207, 0,103,212, 0,101,214, 0,101,213, 0, + 104,210, 0,108,206, 0,109,204, 0,107,206, 0,105,209, 0, + 103,212, 0,100,214, 0, 98,216, 0, 98,217, 0,100,215, 0, + 103,211, 0,107,206, 0,111,201, 0,116,193, 0,119,185, 0, + 123,171, 3,124,147, 26,109, 92,251, 30, 55,222,118,117, 85, + 124,164, 9,120,183, 0,116,192, 0,114,197, 0,114,197, 0, + 115,194, 0,117,190, 0,116,193, 0,116,193, 0,117,191, 0, + 120,184, 0,123,171, 3,124,145, 29,117,110,109,105, 84,252, + 105, 84,252,105, 84,252,107, 89,252,113,100,242,120,122, 70, + 122,135, 44,123,137, 41,122,130, 53,115,107,129,113,100,242, + 118,117, 85,122,130, 53,121,127, 58,115,107,129, 30, 49,213, + 30, 49,213,122,132, 48,123,170, 3,118,188, 0,113,198, 0, + 109,203, 0,108,206, 0,108,206, 0,108,205, 0,107,207, 0, + 106,207, 0,107,206, 0,108,206, 0,108,205, 0,110,202, 0, + 113,198, 0,116,193, 0,115,194, 0,112,200, 0,108,205, 0, + 107,207, 0,107,206, 0,111,202, 0,115,194, 0,119,185, 0, + 121,182, 0,121,179, 0,123,174, 1,124,161, 11,122,132, 48, + 94, 70,242, 30, 20,155,122,132, 48,124,152, 20,123,168, 5, + 121,179, 0,119,186, 0,117,191, 0,115,194, 0,115,195, 0, + 114,196, 0,114,196, 0,111,201, 0,109,204, 0,107,206, 0, + 107,207, 0,108,205, 0,111,202, 0,113,198, 0,116,193, 0, + 117,191, 0,115,194, 0,114,197, 0,112,199, 0,112,199, 0, + 114,197, 0,115,194, 0,114,196, 0,114,196, 0,115,194, 0, + 117,190, 0,120,184, 0,122,176, 0,124,166, 7,124,157, 15, + 124,147, 26,122,132, 48,121,127, 58,122,135, 44,124,143, 31, + 124,154, 18,124,166, 7,122,177, 0,118,188, 0,114,196, 0, + 110,202, 0,108,205, 0,108,206, 0,109,203, 0,113,199, 0, + 115,194, 0,114,196, 0,114,197, 0,114,197, 0,114,197, 0, + 114,197, 0,114,196, 0,115,194, 0,116,192, 0,117,191, 0, + 118,189, 0,119,186, 0,121,180, 0,123,170, 3,124,157, 15, + 123,137, 41,123,141, 34,124,149, 24,124,154, 18,124,155, 16, + 124,154, 18,124,149, 24,123,139, 37,121,127, 58,118,114, 96, + 115,107,129,114,104,197,115,107,129,118,117, 85,122,130, 53, + 124,145, 29,124,160, 12,123,169, 4,122,176, 0,121,179, 0, + 120,182, 0,119,185, 0,117,190, 0,116,193, 0,115,195, 0, + 113,198, 0,112,200, 0,111,201, 0,113,198, 0,117,191, 0, + 122,178, 0,124,152, 20,122,130, 53,121,125, 63,124,143, 31, + 124,158, 13,123,172, 2,121,179, 0,121,182, 0,122,178, 0, + 123,172, 2,124,164, 9,124,154, 18,124,155, 16,124,160, 12, + 124,161, 11,124,157, 15,124,150, 22,124,149, 24,124,157, 15, + 123,168, 5,122,178, 0,119,186, 0,118,189, 0,117,190, 0, + 118,188, 0,120,184, 0,122,177, 0,123,168, 5,124,158, 13, + 124,145, 29,122,130, 53,117,110,109,105, 84,252,109, 92,251, + 118,114, 96,124,150, 22,123,172, 2,120,184, 0,117,191, 0, + 115,194, 0,115,194, 0,116,192, 0,118,189, 0,119,186, 0, + 120,184, 0,120,183, 0,121,181, 0,122,177, 0,123,171, 3, + 124,162, 10,124,147, 26,119,119, 77,114,104,197,117,110,109, + 118,114, 96,115,107,129,111, 96,248,102, 80,250, 94, 70,242, + 105, 84,252,114,104,197,119,119, 77,122,135, 44,124,145, 29, + 124,154, 18,124,158, 13,124,160, 12,124,160, 12,124,161, 11, + 124,164, 9,124,165, 8,124,167, 6,123,174, 1,120,182, 0, + 117,191, 0,112,199, 0,107,207, 0,103,212, 0,100,215, 0, + 100,215, 0,101,213, 0,103,211, 0,103,212, 0,102,213, 0, + 100,215, 0, 98,217, 0, 96,219, 0, 94,220, 0, 94,221, 0, + 95,219, 0, 99,215, 0,104,210, 0,109,204, 0,114,197, 0, + 119,186, 0,123,171, 3,124,143, 31,121,125, 63,117,110,109, + 122,130, 53,124,158, 13,121,179, 0,118,189, 0,115,194, 0, + 114,196, 0,115,194, 0,117,192, 0,117,190, 0,117,191, 0, + 118,188, 0,121,181, 0,124,166, 7,124,147, 26,123,137, 41, + 120,122, 70,111, 96,248,111, 96,248,107, 89,252,102, 80,250, + 119,119, 77,123,139, 37,124,147, 26,124,147, 26,122,132, 48, + 113,100,242, 99, 75,247,107, 89,252,105, 84,252, 87, 65,237, + 30, 55,222,107, 89,252,124,147, 26,122,176, 0,117,191, 0, + 112,199, 0,109,204, 0,107,207, 0,106,207, 0,106,207, 0, + 106,208, 0,105,209, 0,105,209, 0,105,209, 0,107,207, 0, + 109,204, 0,113,199, 0,113,198, 0,113,198, 0,113,198, 0, + 112,200, 0,110,202, 0,111,201, 0,114,196, 0,118,189, 0, + 121,179, 0,124,165, 8,124,158, 13,124,147, 26,119,119, 77, + 87, 65,237, 30, 31,180,111, 96,248,124,149, 24,124,161, 11, + 123,172, 2,121,181, 0,119,187, 0,117,191, 0,115,194, 0, + 114,196, 0,114,196, 0,113,198, 0,110,203, 0,107,207, 0, + 105,209, 0,104,210, 0,105,209, 0,107,207, 0,110,203, 0, + 112,199, 0,114,196, 0,112,199, 0,111,201, 0,110,202, 0, + 110,202, 0,111,201, 0,114,197, 0,112,200, 0,111,201, 0, + 112,200, 0,113,198, 0,116,193, 0,118,189, 0,120,183, 0, + 122,178, 0,123,173, 1,124,164, 9,124,147, 26,124,149, 24, + 124,154, 18,124,161, 11,123,170, 3,121,180, 0,117,190, 0, + 113,198, 0,109,204, 0,107,207, 0,106,208, 0,108,206, 0, + 111,202, 0,113,198, 0,112,200, 0,112,200, 0,111,201, 0, + 112,200, 0,111,201, 0,111,201, 0,112,199, 0,113,198, 0, + 114,196, 0,115,194, 0,116,192, 0,118,188, 0,120,183, 0, + 122,176, 0,124,167, 6,124,166, 7,123,169, 4,123,172, 2, + 123,174, 1,123,172, 2,123,169, 4,124,162, 10,124,152, 20, + 124,143, 31,122,135, 44,122,130, 53,122,132, 48,123,141, 34, + 124,152, 20,124,165, 8,122,175, 0,120,182, 0,119,187, 0, + 118,189, 0,117,191, 0,116,192, 0,115,194, 0,114,196, 0, + 113,199, 0,111,202, 0,109,203, 0,110,202, 0,112,199, 0, + 117,191, 0,122,178, 0,124,164, 9,124,157, 15,124,154, 18, + 124,162, 10,123,170, 3,122,176, 0,121,179, 0,121,180, 0, + 121,179, 0,122,175, 0,123,170, 3,124,164, 9,124,157, 15, + 124,161, 11,124,164, 9,124,162, 10,124,161, 11,124,161, 11, + 124,164, 9,123,172, 2,121,181, 0,119,187, 0,117,192, 0, + 116,193, 0,116,193, 0,118,189, 0,120,184, 0,122,177, 0, + 124,167, 6,124,154, 18,123,137, 41,118,117, 85,109, 92,251, + 118,117, 85,124,145, 29,124,166, 7,121,181, 0,118,189, 0, + 114,196, 0,112,199, 0,111,201, 0,112,200, 0,113,198, 0, + 114,197, 0,115,195, 0,116,193, 0,117,191, 0,118,188, 0, + 120,183, 0,122,177, 0,124,167, 6,124,154, 18,122,132, 48, + 115,107,129,118,114, 96,118,114, 96,117,110,109,115,107,129, + 115,107,129,119,119, 77,123,137, 41,124,154, 18,124,165, 8, + 123,172, 2,122,178, 0,121,180, 0,121,180, 0,121,180, 0, + 122,178, 0,122,178, 0,122,178, 0,122,178, 0,122,178, 0, + 121,182, 0,118,189, 0,113,198, 0,108,205, 0,103,211, 0, + 100,214, 0, 99,216, 0,100,215, 0, 98,216, 0, 98,217, 0, + 97,218, 0, 95,219, 0, 94,221, 0, 92,222, 0, 92,223, 0, + 91,223, 0, 93,222, 0, 96,219, 0,101,213, 0,107,207, 0, + 113,198, 0,119,187, 0,123,170, 3,124,158, 13,124,154, 18, + 124,147, 26,124,149, 24,124,161, 11,123,171, 3,120,184, 0, + 117,190, 0,116,193, 0,115,194, 0,116,193, 0,117,190, 0, + 119,187, 0,120,184, 0,122,176, 0,124,166, 7,124,160, 12, + 124,152, 20,124,143, 31,121,127, 58,111, 96,248,105, 84,252, + 87, 65,237,115,107,129,123,139, 37,124,152, 20,124,155, 16, + 124,145, 29,121,125, 63,107, 89,252, 30, 43,203, 30, 49,213, + 30, 49,213, 69, 60,230,118,117, 85,124,158, 13,122,178, 0, + 117,191, 0,113,199, 0,109,203, 0,108,206, 0,106,207, 0, + 106,208, 0,104,210, 0,103,211, 0,102,212, 0,103,211, 0, + 105,209, 0,108,205, 0,110,202, 0,111,202, 0,111,202, 0, + 111,201, 0,113,198, 0,115,195, 0,116,193, 0,118,189, 0, + 121,182, 0,123,171, 3,124,157, 15,122,135, 44,111, 96,248, + 30, 43,203, 30, 26,168,109, 92,251,122,130, 53,124,155, 16, + 124,162, 10,123,170, 3,122,178, 0,120,184, 0,118,188, 0, + 117,191, 0,116,193, 0,114,196, 0,112,200, 0,109,204, 0, + 106,207, 0,104,210, 0,104,210, 0,104,210, 0,106,208, 0, + 108,205, 0,111,202, 0,112,200, 0,110,202, 0,109,204, 0, + 108,205, 0,108,205, 0,109,203, 0,112,200, 0,110,202, 0, + 109,204, 0,109,204, 0,110,202, 0,112,200, 0,114,196, 0, + 116,192, 0,118,189, 0,120,184, 0,122,177, 0,124,164, 9, + 124,157, 15,124,160, 12,124,166, 7,123,173, 1,120,182, 0, + 117,192, 0,112,200, 0,108,205, 0,106,208, 0,105,209, 0, + 106,207, 0,109,204, 0,111,201, 0,110,202, 0,110,202, 0, + 110,202, 0,110,203, 0,108,205, 0,108,205, 0,109,204, 0, + 110,202, 0,111,201, 0,112,199, 0,114,197, 0,115,195, 0, + 117,192, 0,118,188, 0,120,184, 0,121,180, 0,120,182, 0, + 120,184, 0,119,185, 0,120,184, 0,121,180, 0,122,175, 0, + 124,167, 6,124,158, 13,124,154, 18,124,152, 20,124,147, 26, + 124,152, 20,124,162, 10,123,172, 2,121,182, 0,118,188, 0, + 116,193, 0,115,195, 0,114,196, 0,114,197, 0,113,198, 0, + 112,199, 0,111,201, 0,109,204, 0,108,205, 0,109,204, 0, + 112,200, 0,117,192, 0,121,179, 0,122,176, 0,123,170, 3, + 124,167, 6,123,171, 3,122,176, 0,121,180, 0,120,182, 0, + 120,182, 0,121,181, 0,122,178, 0,123,173, 1,123,168, 5, + 124,162, 10,124,165, 8,123,168, 5,123,169, 4,123,169, 4, + 124,167, 6,123,168, 5,123,173, 1,121,180, 0,119,186, 0, + 117,191, 0,115,194, 0,115,194, 0,116,193, 0,118,189, 0, + 121,182, 0,123,172, 2,124,160, 12,124,145, 29,123,139, 37, + 122,132, 48,124,149, 24,124,164, 9,122,176, 0,119,186, 0, + 116,193, 0,113,198, 0,110,202, 0,109,204, 0,108,205, 0, + 109,204, 0,110,202, 0,111,201, 0,112,199, 0,114,197, 0, + 116,193, 0,118,189, 0,120,184, 0,122,177, 0,123,168, 5, + 124,157, 15,124,143, 31,121,127, 58,117,110,109,117,110,109, + 118,117, 85,121,125, 63,123,139, 37,124,157, 15,123,170, 3, + 121,179, 0,119,185, 0,118,188, 0,117,190, 0,117,191, 0, + 118,189, 0,118,188, 0,119,186, 0,119,186, 0,118,189, 0, + 117,190, 0,117,191, 0,116,192, 0,114,196, 0,110,203, 0, + 105,209, 0,101,213, 0, 99,215, 0, 97,218, 0, 95,220, 0, + 94,220, 0, 94,221, 0, 93,222, 0, 92,222, 0, 91,223, 0, + 91,224, 0, 91,224, 0, 92,222, 0, 95,220, 0,100,215, 0, + 106,207, 0,113,198, 0,119,186, 0,122,176, 0,123,174, 1, + 123,172, 2,123,169, 4,124,167, 6,124,167, 6,123,172, 2, + 122,178, 0,120,184, 0,118,189, 0,116,192, 0,116,193, 0, + 117,192, 0,118,188, 0,120,183, 0,122,178, 0,123,171, 3, + 124,165, 8,124,158, 13,124,152, 20,123,141, 34,119,119, 77, + 102, 80,250, 30, 55,222,105, 84,252,122,130, 53,124,150, 22, + 124,157, 15,124,150, 22,122,135, 44,115,107,129, 94, 70,242, + 30, 37,192, 30, 55,222,109, 92,251,122,132, 48,124,162, 10, + 122,178, 0,118,189, 0,114,196, 0,112,200, 0,110,203, 0, + 108,205, 0,106,208, 0,104,210, 0,102,213, 0,101,214, 0, + 102,213, 0,104,210, 0,108,206, 0,109,204, 0,109,204, 0, + 109,203, 0,111,202, 0,113,198, 0,116,193, 0,119,185, 0, + 122,178, 0,123,170, 3,124,160, 12,124,147, 26,121,125, 63, + 109, 92,251, 87, 65,237,114,104,197,122,130, 53,124,147, 26, + 124,157, 15,124,161, 11,123,169, 4,122,177, 0,121,182, 0, + 119,186, 0,118,189, 0,116,193, 0,114,196, 0,112,200, 0, + 109,203, 0,107,206, 0,106,208, 0,105,209, 0,106,208, 0, + 107,206, 0,109,203, 0,111,201, 0,112,200, 0,109,203, 0, + 108,206, 0,107,207, 0,107,207, 0,108,205, 0,110,202, 0, + 109,204, 0,107,206, 0,107,207, 0,108,205, 0,110,203, 0, + 112,200, 0,114,196, 0,116,193, 0,118,189, 0,121,182, 0, + 123,170, 3,124,161, 11,124,162, 10,123,168, 5,122,175, 0, + 120,184, 0,116,193, 0,111,201, 0,107,206, 0,105,209, 0, + 105,209, 0,106,208, 0,109,204, 0,111,201, 0,110,203, 0, + 109,203, 0,109,203, 0,107,207, 0,105,209, 0,105,209, 0, + 106,208, 0,107,207, 0,107,206, 0,109,204, 0,111,202, 0, + 111,201, 0,112,199, 0,113,198, 0,114,196, 0,116,193, 0, + 117,191, 0,116,192, 0,116,193, 0,117,191, 0,118,188, 0, + 120,183, 0,122,176, 0,123,173, 1,123,172, 2,123,171, 3, + 123,168, 5,124,164, 9,124,165, 8,122,175, 0,120,184, 0, + 117,191, 0,115,195, 0,114,197, 0,113,199, 0,112,199, 0, + 112,200, 0,110,202, 0,109,203, 0,108,205, 0,107,207, 0, + 108,205, 0,111,201, 0,116,193, 0,119,186, 0,120,182, 0, + 122,176, 0,123,172, 2,123,174, 1,122,177, 0,121,179, 0, + 121,182, 0,121,182, 0,121,181, 0,121,179, 0,122,176, 0, + 123,170, 3,124,165, 8,123,171, 3,122,175, 0,122,177, 0, + 122,175, 0,123,172, 2,123,170, 3,123,172, 2,122,178, 0, + 120,184, 0,118,189, 0,116,193, 0,115,194, 0,116,193, 0, + 117,190, 0,120,184, 0,123,174, 1,124,167, 6,124,167, 6, + 124,165, 8,124,161, 11,124,166, 7,123,174, 1,121,182, 0, + 118,188, 0,115,194, 0,113,199, 0,110,202, 0,108,205, 0, + 107,206, 0,107,206, 0,108,205, 0,109,204, 0,110,202, 0, + 112,199, 0,114,196, 0,117,191, 0,119,186, 0,121,180, 0, + 123,174, 1,124,167, 6,124,160, 12,124,150, 22,123,141, 34, + 122,132, 48,121,125, 63,122,130, 53,124,149, 24,124,166, 7, + 122,178, 0,119,186, 0,117,191, 0,115,194, 0,114,196, 0, + 114,196, 0,115,194, 0,117,192, 0,116,193, 0,114,197, 0, + 113,199, 0,113,199, 0,113,198, 0,114,197, 0,113,198, 0, + 111,202, 0,107,207, 0,103,212, 0,100,215, 0, 96,219, 0, + 94,221, 0, 92,222, 0, 92,222, 0, 92,222, 0, 92,222, 0, + 92,223, 0, 92,223, 0, 92,223, 0, 93,222, 0, 95,219, 0, + 100,214, 0,107,207, 0,114,197, 0,119,186, 0,119,185, 0, + 120,184, 0,120,183, 0,120,182, 0,120,182, 0,120,184, 0, + 120,184, 0,120,184, 0,120,183, 0,119,185, 0,118,188, 0, + 117,191, 0,117,191, 0,118,189, 0,120,184, 0,122,178, 0, + 123,172, 2,124,165, 8,124,158, 13,124,154, 18,124,147, 26, + 122,132, 48,113,100,242, 30, 55,222, 30, 43,203,115,107,129, + 123,139, 37,124,149, 24,124,147, 26,122,132, 48,117,110,109, + 105, 84,252, 99, 75,247,105, 84,252,117,110,109,123,139, 37, + 124,162, 10,122,176, 0,120,184, 0,117,191, 0,115,195, 0, + 113,199, 0,110,203, 0,107,206, 0,104,210, 0,101,213, 0, + 100,215, 0,100,214, 0,103,212, 0,107,207, 0,108,205, 0, + 108,205, 0,109,203, 0,111,201, 0,114,196, 0,117,190, 0, + 121,182, 0,123,170, 3,124,155, 16,123,141, 34,122,130, 53, + 118,114, 96,113,100,242,120,122, 70,123,139, 37,124,149, 24, + 124,154, 18,124,157, 15,124,167, 6,122,175, 0,121,180, 0, + 120,184, 0,119,187, 0,118,189, 0,117,192, 0,115,194, 0, + 114,197, 0,111,201, 0,110,203, 0,109,204, 0,109,204, 0, + 110,203, 0,111,201, 0,113,199, 0,114,196, 0,112,199, 0, + 110,202, 0,108,206, 0,107,207, 0,106,207, 0,107,206, 0, + 109,204, 0,108,205, 0,107,207, 0,106,207, 0,107,206, 0, + 109,203, 0,112,200, 0,114,196, 0,116,193, 0,118,189, 0, + 120,182, 0,123,171, 3,124,161, 11,124,167, 6,122,177, 0, + 121,182, 0,119,185, 0,115,194, 0,111,201, 0,107,206, 0, + 105,209, 0,105,209, 0,107,207, 0,109,204, 0,112,200, 0, + 110,202, 0,110,203, 0,107,207, 0,103,211, 0,101,213, 0, + 101,213, 0,102,212, 0,103,212, 0,102,212, 0,103,211, 0, + 105,209, 0,108,206, 0,108,205, 0,109,204, 0,109,203, 0, + 110,202, 0,112,199, 0,112,199, 0,112,199, 0,113,198, 0, + 115,194, 0,118,189, 0,120,184, 0,120,184, 0,120,183, 0, + 120,182, 0,121,181, 0,122,178, 0,123,173, 1,123,173, 1, + 120,182, 0,118,189, 0,115,194, 0,114,197, 0,113,199, 0, + 112,200, 0,110,202, 0,108,206, 0,107,207, 0,107,206, 0, + 106,207, 0,107,206, 0,110,202, 0,115,194, 0,118,189, 0, + 119,185, 0,122,178, 0,123,172, 2,123,172, 2,123,173, 1, + 122,176, 0,122,178, 0,122,178, 0,122,178, 0,122,177, 0, + 123,174, 1,123,169, 4,123,170, 3,122,178, 0,120,182, 0, + 120,182, 0,121,180, 0,122,176, 0,122,175, 0,122,178, 0, + 122,178, 0,121,181, 0,119,186, 0,118,189, 0,117,192, 0, + 117,192, 0,118,189, 0,120,183, 0,122,177, 0,121,180, 0, + 121,182, 0,121,180, 0,122,177, 0,122,175, 0,121,179, 0, + 120,184, 0,118,189, 0,116,193, 0,114,197, 0,111,201, 0, + 109,203, 0,108,205, 0,107,206, 0,108,205, 0,109,204, 0, + 110,202, 0,112,199, 0,115,195, 0,117,190, 0,119,185, 0, + 121,179, 0,123,174, 1,123,169, 4,124,165, 8,124,160, 12, + 124,155, 16,124,149, 24,123,141, 34,122,135, 44,124,150, 22, + 123,169, 4,121,182, 0,118,189, 0,115,194, 0,114,196, 0, + 114,197, 0,114,197, 0,114,196, 0,114,197, 0,110,202, 0, + 108,205, 0,107,206, 0,108,205, 0,110,203, 0,111,201, 0, + 110,203, 0,109,203, 0,107,206, 0,104,210, 0,100,214, 0, + 97,218, 0, 94,221, 0, 92,222, 0, 92,222, 0, 93,221, 0, + 91,223, 0, 91,223, 0, 93,221, 0, 94,220, 0, 95,220, 0, + 98,217, 0,102,212, 0,108,205, 0,115,194, 0,116,192, 0, + 117,191, 0,117,190, 0,117,190, 0,117,190, 0,117,192, 0, + 115,194, 0,115,195, 0,115,195, 0,116,193, 0,117,190, 0, + 118,189, 0,117,191, 0,117,190, 0,119,187, 0,120,182, 0, + 122,177, 0,123,169, 4,124,161, 11,124,154, 18,124,149, 24, + 124,147, 26,123,137, 41,118,117, 85, 99, 75,247, 30, 43,203, + 87, 65,237,118,114, 96,122,132, 48,122,132, 48,120,122, 70, + 115,107,129,111, 96,248,107, 89,252,109, 92,251,118,114, 96, + 123,137, 41,124,158, 13,123,170, 3,122,178, 0,120,184, 0, + 118,189, 0,114,197, 0,110,202, 0,109,204, 0,105,209, 0, + 102,213, 0,100,215, 0,100,215, 0,102,212, 0,106,207, 0, + 109,203, 0,110,203, 0,111,201, 0,113,198, 0,117,192, 0, + 120,184, 0,122,175, 0,124,162, 10,124,145, 29,122,132, 48, + 121,125, 63,119,119, 77,122,132, 48,124,149, 24,124,157, 15, + 124,158, 13,124,158, 13,124,158, 13,123,168, 5,122,175, 0, + 121,180, 0,120,183, 0,120,184, 0,119,186, 0,119,187, 0, + 118,189, 0,116,192, 0,115,195, 0,114,197, 0,113,198, 0, + 114,197, 0,114,196, 0,116,193, 0,117,191, 0,117,191, 0, + 114,196, 0,112,200, 0,109,204, 0,107,206, 0,107,207, 0, + 107,206, 0,109,204, 0,108,206, 0,107,207, 0,107,207, 0, + 108,205, 0,110,202, 0,113,198, 0,116,193, 0,117,190, 0, + 119,186, 0,121,179, 0,124,167, 6,124,167, 6,122,178, 0, + 120,184, 0,119,187, 0,118,188, 0,115,195, 0,111,202, 0, + 107,206, 0,106,208, 0,106,208, 0,108,206, 0,110,202, 0, + 113,198, 0,112,200, 0,108,205, 0,103,212, 0, 99,215, 0, + 97,217, 0, 98,217, 0, 99,215, 0,100,215, 0, 98,217, 0, + 98,216, 0,100,215, 0,102,212, 0,105,209, 0,105,209, 0, + 105,209, 0,106,207, 0,108,205, 0,108,206, 0,108,205, 0, + 109,204, 0,111,201, 0,114,196, 0,118,189, 0,118,189, 0, + 118,188, 0,118,188, 0,118,188, 0,119,186, 0,120,184, 0, + 121,180, 0,122,178, 0,119,187, 0,116,192, 0,114,196, 0, + 113,198, 0,111,201, 0,108,206, 0,105,209, 0,105,209, 0, + 107,207, 0,106,208, 0,107,207, 0,110,203, 0,114,197, 0, + 118,189, 0,120,184, 0,122,176, 0,123,168, 5,124,166, 7, + 124,167, 6,123,168, 5,123,170, 3,123,172, 2,123,173, 1, + 123,172, 2,123,169, 4,124,167, 6,122,178, 0,119,185, 0, + 118,188, 0,118,188, 0,119,185, 0,121,180, 0,122,178, 0, + 121,182, 0,120,182, 0,121,182, 0,120,182, 0,119,186, 0, + 118,189, 0,118,189, 0,119,187, 0,120,182, 0,119,187, 0, + 118,189, 0,117,191, 0,118,189, 0,119,186, 0,121,182, 0, + 120,182, 0,119,185, 0,118,189, 0,115,194, 0,113,198, 0, + 113,199, 0,111,201, 0,110,203, 0,109,204, 0,109,203, 0, + 110,202, 0,112,200, 0,114,197, 0,116,192, 0,119,187, 0, + 121,181, 0,123,174, 1,123,169, 4,124,166, 7,124,164, 9, + 124,161, 11,124,158, 13,124,152, 20,124,145, 29,123,139, 37, + 124,152, 20,123,170, 3,120,182, 0,117,190, 0,115,194, 0, + 114,196, 0,114,196, 0,114,197, 0,114,197, 0,109,204, 0, + 105,209, 0,103,211, 0,103,212, 0,105,209, 0,107,207, 0, + 109,204, 0,107,207, 0,106,208, 0,106,208, 0,105,209, 0, + 102,213, 0, 98,217, 0, 95,219, 0, 94,221, 0, 94,221, 0, + 89,225, 0, 86,228, 0, 86,228, 0, 88,226, 0, 93,222, 0, + 98,217, 0,100,214, 0,105,209, 0,110,202, 0,114,197, 0, + 114,196, 0,114,197, 0,113,198, 0,114,197, 0,114,196, 0, + 113,198, 0,112,200, 0,110,202, 0,110,202, 0,112,200, 0, + 114,196, 0,117,191, 0,117,191, 0,117,191, 0,118,188, 0, + 121,182, 0,123,173, 1,123,168, 5,124,160, 12,124,145, 29, + 123,141, 34,123,141, 34,123,139, 37,121,127, 58,113,100,242, + 94, 70,242, 30, 55,222, 94, 70,242,114,104,197,117,110,109, + 115,107,129,113,100,242,107, 89,252,105, 84,252,107, 89,252, + 114,104,197,121,127, 58,124,147, 26,124,160, 12,124,167, 6, + 122,178, 0,118,188, 0,114,196, 0,112,200, 0,111,201, 0, + 107,206, 0,103,211, 0,100,214, 0,100,215, 0,102,212, 0, + 106,208, 0,111,201, 0,112,199, 0,114,197, 0,116,192, 0, + 119,186, 0,122,176, 0,124,164, 9,124,147, 26,121,127, 58, + 118,114, 96,118,114, 96,120,122, 70,124,149, 24,124,161, 11, + 124,165, 8,124,165, 8,124,160, 12,124,154, 18,124,164, 9, + 123,170, 3,123,174, 1,122,176, 0,122,177, 0,122,177, 0, + 122,177, 0,121,179, 0,120,183, 0,119,186, 0,118,188, 0, + 118,189, 0,118,188, 0,119,186, 0,120,184, 0,120,184, 0, + 119,186, 0,117,192, 0,114,197, 0,111,201, 0,109,204, 0, + 108,205, 0,108,205, 0,110,202, 0,108,206, 0,107,207, 0, + 108,206, 0,110,203, 0,112,199, 0,115,194, 0,117,190, 0, + 119,185, 0,121,182, 0,122,176, 0,123,172, 2,122,175, 0, + 120,182, 0,119,187, 0,118,189, 0,117,190, 0,113,198, 0, + 109,203, 0,107,207, 0,106,208, 0,106,207, 0,109,204, 0, + 112,200, 0,114,196, 0,110,202, 0,104,210, 0, 99,215, 0, + 95,219, 0, 94,221, 0, 94,221, 0, 95,219, 0, 98,217, 0, + 96,219, 0, 95,219, 0, 97,218, 0, 98,217, 0,101,214, 0, + 103,212, 0,103,211, 0,104,210, 0,103,211, 0,102,212, 0, + 103,212, 0,105,209, 0,107,207, 0,111,202, 0,114,196, 0, + 117,190, 0,118,189, 0,117,191, 0,117,191, 0,117,191, 0, + 118,189, 0,118,188, 0,119,185, 0,120,184, 0,117,190, 0, + 115,194, 0,113,198, 0,109,203, 0,106,208, 0,104,210, 0, + 104,210, 0,106,208, 0,105,209, 0,106,208, 0,108,205, 0, + 112,199, 0,117,191, 0,121,182, 0,123,171, 3,124,160, 12, + 124,167, 6,123,168, 5,124,167, 6,124,164, 9,124,164, 9, + 124,165, 8,124,165, 8,124,164, 9,122,176, 0,119,185, 0, + 117,191, 0,116,193, 0,116,193, 0,118,189, 0,120,184, 0, + 122,178, 0,121,182, 0,120,183, 0,120,183, 0,120,182, 0, + 120,184, 0,119,186, 0,119,187, 0,120,184, 0,118,189, 0, + 116,193, 0,114,196, 0,114,196, 0,115,194, 0,117,191, 0, + 119,186, 0,120,183, 0,117,190, 0,114,197, 0,111,201, 0, + 109,204, 0,108,205, 0,108,205, 0,109,203, 0,111,202, 0, + 111,201, 0,112,200, 0,114,197, 0,116,193, 0,118,188, 0, + 120,182, 0,123,174, 1,124,166, 7,124,160, 12,124,162, 10, + 124,165, 8,124,164, 9,124,160, 12,124,149, 24,123,137, 41, + 122,130, 53,124,154, 18,123,171, 3,120,182, 0,118,189, 0, + 116,193, 0,115,194, 0,115,194, 0,115,194, 0,110,202, 0, + 105,209, 0,102,213, 0,100,215, 0,100,215, 0,102,212, 0, + 105,209, 0,108,206, 0,105,209, 0,104,210, 0,103,211, 0, + 103,212, 0,102,212, 0,100,215, 0, 97,218, 0, 95,220, 0, + 89,225, 0, 85,229, 0, 82,231, 0, 82,231, 0, 84,229, 0, + 89,225, 0, 96,219, 0,103,212, 0,107,207, 0,111,201, 0, + 111,201, 0,110,203, 0,108,205, 0,108,205, 0,109,203, 0, + 113,199, 0,111,201, 0,109,203, 0,108,205, 0,108,206, 0, + 109,204, 0,112,200, 0,115,195, 0,118,189, 0,118,189, 0, + 119,186, 0,121,181, 0,122,178, 0,122,175, 0,123,168, 5, + 124,157, 15,122,132, 48,123,137, 41,123,137, 41,122,132, 48, + 118,117, 85,113,100,242,111, 96,248,105, 84,252, 99, 75,247, + 109, 92,251,109, 92,251,111, 96,248,114,104,197,117,110,109, + 117,110,109,117,110,109,115,107,129,121,127, 58,123,141, 34, + 124,160, 12,123,174, 1,120,184, 0,117,191, 0,115,194, 0, + 114,196, 0,110,203, 0,105,209, 0,102,212, 0,101,214, 0, + 103,212, 0,106,207, 0,111,201, 0,116,193, 0,117,190, 0, + 120,184, 0,122,176, 0,124,164, 9,124,155, 16,123,141, 34, + 120,122, 70,105, 84,252,107, 89,252,122,130, 53,124,154, 18, + 124,166, 7,123,170, 3,123,168, 5,124,164, 9,124,157, 15, + 124,150, 22,124,157, 15,124,160, 12,124,161, 11,124,161, 11, + 123,169, 4,122,175, 0,122,178, 0,122,178, 0,122,178, 0, + 122,178, 0,122,178, 0,121,180, 0,120,182, 0,119,185, 0, + 118,188, 0,118,189, 0,118,188, 0,115,194, 0,113,199, 0, + 110,202, 0,109,203, 0,110,203, 0,111,201, 0,109,203, 0, + 109,204, 0,110,203, 0,112,200, 0,114,196, 0,116,193, 0, + 117,191, 0,119,186, 0,121,182, 0,122,178, 0,123,173, 1, + 122,178, 0,120,184, 0,118,188, 0,117,191, 0,116,192, 0, + 112,199, 0,108,205, 0,106,208, 0,105,209, 0,106,207, 0, + 109,204, 0,112,200, 0,111,201, 0,108,206, 0,102,213, 0, + 96,219, 0, 92,222, 0, 91,223, 0, 91,223, 0, 93,222, 0, + 95,220, 0, 94,220, 0, 94,221, 0, 94,221, 0, 95,220, 0, + 96,219, 0, 98,217, 0, 99,216, 0, 98,216, 0, 97,217, 0, + 97,217, 0, 98,217, 0,100,215, 0,103,211, 0,107,207, 0, + 111,201, 0,115,195, 0,117,190, 0,117,191, 0,116,192, 0, + 116,193, 0,116,193, 0,117,192, 0,117,190, 0,118,189, 0, + 117,191, 0,114,196, 0,111,201, 0,108,206, 0,105,209, 0, + 103,211, 0,104,210, 0,106,208, 0,105,209, 0,105,209, 0, + 108,206, 0,112,200, 0,116,192, 0,120,183, 0,123,170, 3, + 124,164, 9,123,170, 3,123,171, 3,123,170, 3,123,168, 5, + 124,166, 7,124,165, 8,124,165, 8,122,176, 0,119,185, 0, + 116,192, 0,114,197, 0,113,199, 0,113,198, 0,115,194, 0, + 118,189, 0,120,182, 0,121,181, 0,120,182, 0,120,183, 0, + 120,184, 0,120,184, 0,119,185, 0,119,187, 0,117,191, 0, + 115,195, 0,113,198, 0,112,200, 0,112,200, 0,113,198, 0, + 115,194, 0,117,190, 0,116,193, 0,114,196, 0,111,202, 0, + 107,206, 0,105,209, 0,104,210, 0,104,210, 0,105,209, 0, + 106,207, 0,108,205, 0,110,202, 0,113,199, 0,115,194, 0, + 117,190, 0,119,185, 0,121,180, 0,122,177, 0,123,173, 1, + 124,167, 6,124,165, 8,124,165, 8,124,162, 10,124,154, 18, + 123,137, 41,121,127, 58,124,152, 20,123,169, 4,121,180, 0, + 119,186, 0,118,189, 0,117,191, 0,117,191, 0,113,198, 0, + 108,205, 0,103,211, 0,100,215, 0, 98,217, 0, 98,217, 0, + 100,215, 0,103,211, 0,106,208, 0,106,208, 0,104,210, 0, + 103,211, 0,102,212, 0,101,214, 0, 99,215, 0, 97,218, 0, + 93,221, 0, 88,226, 0, 83,230, 0, 80,233, 0, 80,233, 0, + 82,231, 0, 87,227, 0, 94,221, 0,100,214, 0,106,207, 0, + 107,206, 0,106,208, 0,105,209, 0,103,211, 0,104,210, 0, + 105,209, 0,109,204, 0,111,201, 0,109,203, 0,108,206, 0, + 107,207, 0,108,205, 0,110,202, 0,113,198, 0,116,192, 0, + 118,188, 0,119,185, 0,120,183, 0,121,180, 0,122,176, 0, + 123,170, 3,124,158, 13,123,137, 41,123,137, 41,123,139, 37, + 122,135, 44,120,122, 70,119,119, 77,121,125, 63,120,122, 70, + 119,119, 77,120,122, 70,121,127, 58,122,130, 53,122,130, 53, + 122,130, 53,121,125, 63,118,117, 85,117,110,109,118,114, 96, + 122,132, 48,124,150, 22,124,165, 8,122,175, 0,121,182, 0, + 119,185, 0,117,192, 0,112,200, 0,107,206, 0,104,210, 0, + 103,211, 0,105,209, 0,108,205, 0,113,199, 0,117,191, 0, + 120,183, 0,122,176, 0,123,169, 4,124,162, 10,124,154, 18, + 124,143, 31,121,127, 58,109, 92,251,107, 89,252,122,130, 53, + 124,155, 16,124,167, 6,123,171, 3,123,171, 3,124,166, 7, + 124,158, 13,124,150, 22,124,149, 24,124,155, 16,124,162, 10, + 123,170, 3,122,177, 0,121,181, 0,120,184, 0,120,184, 0, + 119,185, 0,119,185, 0,119,186, 0,119,186, 0,119,186, 0, + 118,188, 0,118,189, 0,118,189, 0,118,188, 0,117,191, 0, + 114,197, 0,112,200, 0,111,202, 0,111,202, 0,112,200, 0, + 113,199, 0,112,199, 0,113,198, 0,115,195, 0,117,192, 0, + 117,190, 0,118,188, 0,120,183, 0,122,178, 0,123,172, 2, + 123,168, 5,122,177, 0,120,184, 0,118,188, 0,117,191, 0, + 116,193, 0,112,199, 0,109,204, 0,106,207, 0,106,208, 0, + 106,207, 0,108,205, 0,111,202, 0,110,203, 0,106,207, 0, + 100,214, 0, 95,220, 0, 92,223, 0, 90,225, 0, 90,224, 0, + 92,223, 0, 94,221, 0, 92,222, 0, 91,223, 0, 91,223, 0, + 92,223, 0, 93,222, 0, 94,221, 0, 94,220, 0, 94,221, 0, + 93,222, 0, 93,222, 0, 94,220, 0, 97,217, 0,101,213, 0, + 106,208, 0,110,202, 0,114,197, 0,117,191, 0,116,192, 0, + 115,194, 0,115,195, 0,115,195, 0,115,194, 0,116,193, 0, + 116,193, 0,115,194, 0,113,198, 0,110,203, 0,107,207, 0, + 104,210, 0,103,212, 0,103,211, 0,105,209, 0,105,209, 0, + 106,208, 0,109,204, 0,112,199, 0,117,192, 0,121,182, 0, + 123,169, 4,124,160, 12,124,166, 7,123,169, 4,123,169, 4, + 123,169, 4,123,168, 5,123,169, 4,122,177, 0,119,186, 0, + 116,193, 0,112,199, 0,110,202, 0,109,204, 0,110,202, 0, + 113,198, 0,116,192, 0,118,189, 0,119,187, 0,119,187, 0, + 118,189, 0,118,189, 0,118,189, 0,117,191, 0,116,193, 0, + 114,197, 0,112,200, 0,110,202, 0,110,203, 0,110,202, 0, + 112,200, 0,114,197, 0,113,198, 0,111,201, 0,110,202, 0, + 108,205, 0,105,209, 0,102,212, 0,100,214, 0,100,215, 0, + 100,214, 0,102,213, 0,104,210, 0,107,207, 0,110,203, 0, + 113,199, 0,115,194, 0,118,189, 0,119,186, 0,119,186, 0, + 120,184, 0,121,180, 0,123,173, 1,124,167, 6,124,166, 7, + 124,161, 11,124,149, 24,123,139, 37,123,141, 34,124,161, 11, + 123,173, 1,121,181, 0,120,184, 0,119,185, 0,118,189, 0, + 112,199, 0,107,207, 0,102,212, 0, 98,216, 0, 97,218, 0, + 97,218, 0, 98,216, 0,101,213, 0,104,210, 0,105,209, 0, + 105,209, 0,103,211, 0,100,214, 0, 98,217, 0, 97,218, 0, + 96,219, 0, 93,221, 0, 88,226, 0, 83,230, 0, 81,232, 0, + 81,232, 0, 83,230, 0, 87,227, 0, 92,222, 0, 98,216, 0, + 104,210, 0,103,212, 0,101,213, 0,100,214, 0, 99,215, 0, + 100,215, 0,102,213, 0,105,209, 0,110,202, 0,111,201, 0, + 109,203, 0,108,205, 0,108,205, 0,110,203, 0,112,199, 0, + 115,194, 0,118,189, 0,119,186, 0,121,182, 0,122,178, 0, + 123,172, 2,124,165, 8,124,154, 18,123,141, 34,123,139, 37, + 123,137, 41,122,132, 48,120,122, 70,122,132, 48,123,141, 34, + 124,145, 29,124,149, 24,124,150, 22,124,150, 22,124,149, 24, + 124,145, 29,123,137, 41,121,127, 58,118,114, 96,113,100,242, + 115,107,129,118,114, 96,122,132, 48,124,149, 24,124,160, 12, + 124,167, 6,122,178, 0,118,188, 0,114,196, 0,110,202, 0, + 107,206, 0,107,207, 0,108,205, 0,112,200, 0,116,193, 0, + 120,184, 0,122,175, 0,124,167, 6,124,160, 12,124,155, 16, + 124,149, 24,123,141, 34,121,125, 63,120,122, 70,118,114, 96, + 121,127, 58,124,152, 20,124,165, 8,123,170, 3,123,170, 3, + 124,166, 7,124,157, 15,124,157, 15,124,161, 11,124,167, 6, + 123,172, 2,122,178, 0,120,182, 0,119,186, 0,118,188, 0, + 118,189, 0,117,191, 0,117,191, 0,117,191, 0,118,189, 0, + 118,188, 0,118,188, 0,119,187, 0,119,187, 0,119,185, 0, + 118,189, 0,115,194, 0,113,198, 0,112,199, 0,112,199, 0, + 113,198, 0,115,195, 0,116,193, 0,117,191, 0,118,189, 0, + 119,186, 0,120,184, 0,121,180, 0,123,174, 1,124,167, 6, + 124,161, 11,124,162, 10,123,172, 2,121,181, 0,119,187, 0, + 117,192, 0,115,194, 0,113,198, 0,110,202, 0,107,206, 0, + 106,207, 0,106,207, 0,108,206, 0,110,203, 0,109,203, 0, + 106,207, 0,100,214, 0, 95,220, 0, 92,223, 0, 90,224, 0, + 91,224, 0, 92,222, 0, 93,222, 0, 91,223, 0, 90,225, 0, + 90,225, 0, 90,224, 0, 91,223, 0, 92,223, 0, 92,222, 0, + 91,223, 0, 90,224, 0, 91,223, 0, 93,221, 0, 97,218, 0, + 101,213, 0,106,207, 0,111,202, 0,114,196, 0,116,193, 0, + 116,193, 0,114,197, 0,112,200, 0,111,201, 0,112,199, 0, + 114,196, 0,115,195, 0,114,196, 0,112,200, 0,109,203, 0, + 106,207, 0,104,210, 0,102,212, 0,103,212, 0,105,209, 0, + 107,207, 0,108,206, 0,110,202, 0,114,197, 0,118,189, 0, + 122,178, 0,124,164, 9,124,147, 26,124,155, 16,124,160, 12, + 124,162, 10,124,164, 9,124,166, 7,123,174, 1,119,185, 0, + 116,192, 0,112,199, 0,109,204, 0,107,207, 0,106,207, 0, + 108,206, 0,111,202, 0,114,196, 0,116,193, 0,117,192, 0, + 117,192, 0,115,195, 0,114,197, 0,113,198, 0,113,198, 0, + 113,198, 0,111,201, 0,109,203, 0,108,205, 0,108,205, 0, + 109,203, 0,111,201, 0,112,200, 0,109,203, 0,108,205, 0, + 107,206, 0,107,207, 0,103,211, 0,100,214, 0, 98,217, 0, + 97,218, 0, 97,218, 0, 98,217, 0,101,214, 0,104,210, 0, + 108,205, 0,111,201, 0,114,196, 0,117,191, 0,117,191, 0, + 117,192, 0,117,191, 0,118,188, 0,120,182, 0,122,175, 0, + 123,170, 3,123,168, 5,124,162, 10,124,149, 24,124,149, 24, + 124,149, 24,124,162, 10,123,171, 3,122,175, 0,122,176, 0, + 118,188, 0,113,198, 0,108,206, 0,103,212, 0, 99,215, 0, + 97,217, 0, 97,218, 0, 98,216, 0,101,214, 0,102,212, 0, + 103,212, 0,103,212, 0, 99,215, 0, 96,219, 0, 94,220, 0, + 94,221, 0, 94,220, 0, 93,222, 0, 89,225, 0, 85,228, 0, + 83,230, 0, 83,230, 0, 85,229, 0, 88,226, 0, 92,222, 0, + 97,217, 0,101,214, 0,100,215, 0, 98,217, 0, 97,218, 0, + 97,218, 0, 97,217, 0, 99,215, 0,103,212, 0,108,206, 0, + 113,198, 0,112,200, 0,110,202, 0,110,203, 0,111,202, 0, + 113,199, 0,115,194, 0,118,188, 0,120,183, 0,122,178, 0, + 123,171, 3,124,165, 8,124,158, 13,124,150, 22,124,143, 31, + 123,137, 41,122,130, 53,120,122, 70,118,117, 85,123,139, 37, + 124,152, 20,124,160, 12,124,164, 9,124,166, 7,124,165, 8, + 124,161, 11,124,152, 20,123,139, 37,120,122, 70,111, 96,248, + 109, 92,251,115,107,129,118,117, 85,118,117, 85,119,119, 77, + 123,137, 41,124,157, 15,123,172, 2,120,183, 0,117,191, 0, + 114,197, 0,111,201, 0,111,201, 0,113,199, 0,116,193, 0, + 120,184, 0,123,172, 2,124,160, 12,124,149, 24,124,143, 31, + 123,139, 37,122,135, 44,122,135, 44,123,141, 34,123,139, 37, + 122,130, 53,121,125, 63,124,149, 24,124,161, 11,124,167, 6, + 124,167, 6,124,164, 9,124,155, 16,124,162, 10,123,168, 5, + 123,172, 2,122,177, 0,121,180, 0,120,184, 0,119,187, 0, + 118,189, 0,117,191, 0,116,193, 0,116,193, 0,116,192, 0, + 117,191, 0,118,188, 0,120,184, 0,120,183, 0,121,182, 0, + 121,181, 0,119,187, 0,117,192, 0,115,194, 0,114,196, 0, + 114,196, 0,115,194, 0,116,192, 0,118,189, 0,119,187, 0, + 120,183, 0,122,178, 0,123,173, 1,124,167, 6,124,162, 10, + 124,158, 13,124,150, 22,124,160, 12,123,168, 5,122,176, 0, + 120,184, 0,117,191, 0,114,196, 0,113,198, 0,111,201, 0, + 109,204, 0,107,207, 0,106,207, 0,107,207, 0,108,205, 0, + 109,203, 0,107,207, 0,101,214, 0, 96,219, 0, 92,222, 0, + 91,223, 0, 91,223, 0, 93,221, 0, 91,223, 0, 90,225, 0, + 89,225, 0, 90,225, 0, 91,224, 0, 91,223, 0, 92,222, 0, + 92,222, 0, 91,223, 0, 90,224, 0, 91,223, 0, 94,221, 0, + 98,217, 0,103,212, 0,108,205, 0,112,199, 0,115,195, 0, + 115,194, 0,113,198, 0,110,202, 0,108,205, 0,108,205, 0, + 109,203, 0,113,199, 0,114,196, 0,114,196, 0,112,200, 0, + 109,203, 0,106,207, 0,104,210, 0,102,212, 0,103,212, 0, + 105,209, 0,109,204, 0,109,203, 0,112,200, 0,116,193, 0, + 120,184, 0,123,173, 1,124,161, 11,123,139, 37,123,139, 37, + 123,141, 34,124,147, 26,124,152, 20,124,162, 10,121,179, 0, + 118,189, 0,114,197, 0,110,202, 0,106,207, 0,104,210, 0, + 104,210, 0,106,208, 0,109,203, 0,114,197, 0,114,196, 0, + 115,195, 0,114,196, 0,112,200, 0,110,203, 0,109,204, 0, + 109,204, 0,109,204, 0,109,203, 0,108,205, 0,108,205, 0, + 108,205, 0,109,203, 0,111,202, 0,109,204, 0,107,207, 0, + 106,208, 0,106,207, 0,106,208, 0,103,211, 0,100,215, 0, + 97,218, 0, 95,220, 0, 95,220, 0, 96,219, 0, 99,215, 0, + 103,211, 0,108,206, 0,112,200, 0,115,194, 0,117,191, 0, + 116,192, 0,115,194, 0,116,193, 0,117,191, 0,119,186, 0, + 121,180, 0,123,174, 1,122,175, 0,123,171, 3,124,161, 11, + 124,157, 15,124,157, 15,124,150, 22,124,157, 15,124,164, 9, + 124,166, 7,120,183, 0,115,195, 0,110,203, 0,105,209, 0, + 102,213, 0,100,215, 0, 99,215, 0,100,214, 0,102,213, 0, + 102,212, 0,102,212, 0, 99,215, 0, 95,219, 0, 92,222, 0, + 91,223, 0, 91,224, 0, 91,223, 0, 92,223, 0, 90,224, 0, + 88,226, 0, 86,228, 0, 86,228, 0, 87,227, 0, 90,225, 0, + 93,221, 0, 97,218, 0, 99,215, 0, 98,217, 0, 97,218, 0, + 95,219, 0, 95,219, 0, 97,218, 0, 99,216, 0,102,212, 0, + 107,207, 0,113,199, 0,114,196, 0,113,198, 0,112,199, 0, + 113,198, 0,114,196, 0,117,191, 0,120,184, 0,122,177, 0, + 123,171, 3,123,170, 3,124,167, 6,124,161, 11,124,152, 20, + 123,141, 34,121,127, 58,118,117, 85,113,100,242,118,117, 85, + 123,141, 34,124,155, 16,124,165, 8,123,171, 3,123,173, 1, + 123,171, 3,124,166, 7,124,155, 16,123,137, 41,117,110,109, + 99, 75,247,107, 89,252,115,107,129,118,114, 96,118,117, 85, + 117,110,109,118,114, 96,123,141, 34,124,161, 11,123,173, 1, + 120,183, 0,118,189, 0,116,192, 0,116,192, 0,118,189, 0, + 121,182, 0,123,169, 4,124,149, 24,123,137, 41,118,114, 96, + 115,107,129,115,107,129,121,127, 58,123,141, 34,124,147, 26, + 124,145, 29,123,139, 37,121,127, 58,124,145, 29,124,155, 16, + 124,160, 12,124,160, 12,124,157, 15,124,152, 20,124,164, 9, + 123,169, 4,123,174, 1,122,177, 0,121,179, 0,121,182, 0, + 120,184, 0,119,186, 0,118,189, 0,117,192, 0,116,193, 0, + 117,192, 0,118,189, 0,120,184, 0,122,178, 0,123,174, 1, + 123,171, 3,122,178, 0,120,184, 0,118,188, 0,117,190, 0, + 117,191, 0,118,189, 0,118,188, 0,119,187, 0,120,184, 0, + 121,179, 0,123,174, 1,124,166, 7,124,160, 12,124,155, 16, + 124,149, 24,124,143, 31,124,147, 26,124,160, 12,123,169, 4, + 122,176, 0,121,182, 0,118,189, 0,114,196, 0,112,200, 0, + 110,202, 0,110,203, 0,108,205, 0,107,207, 0,106,208, 0, + 107,207, 0,108,205, 0,107,207, 0,101,214, 0, 96,219, 0, + 93,221, 0, 92,223, 0, 92,222, 0, 94,221, 0, 91,223, 0, + 90,224, 0, 90,224, 0, 91,223, 0, 92,222, 0, 94,221, 0, + 95,220, 0, 95,220, 0, 94,221, 0, 93,222, 0, 94,221, 0, + 97,218, 0,101,214, 0,105,209, 0,110,202, 0,113,198, 0, + 114,197, 0,112,200, 0,109,204, 0,107,207, 0,105,209, 0, + 105,209, 0,107,206, 0,111,202, 0,115,195, 0,114,196, 0, + 113,199, 0,110,202, 0,107,207, 0,105,209, 0,103,211, 0, + 103,211, 0,106,208, 0,110,203, 0,111,201, 0,114,197, 0, + 117,190, 0,121,179, 0,123,168, 5,124,155, 16,122,132, 48, + 122,130, 53,121,127, 58,119,119, 77,122,135, 44,124,165, 8, + 121,182, 0,117,191, 0,113,199, 0,109,204, 0,106,208, 0, + 103,211, 0,103,211, 0,105,209, 0,109,204, 0,113,198, 0, + 114,197, 0,114,196, 0,112,200, 0,109,204, 0,107,207, 0, + 106,208, 0,106,208, 0,106,207, 0,107,206, 0,109,204, 0, + 109,203, 0,110,202, 0,111,202, 0,109,203, 0,107,207, 0, + 105,209, 0,106,208, 0,106,207, 0,107,207, 0,105,209, 0, + 101,214, 0, 98,217, 0, 95,219, 0, 95,220, 0, 96,219, 0, + 100,215, 0,104,210, 0,109,204, 0,113,198, 0,117,192, 0, + 118,188, 0,117,191, 0,116,193, 0,116,193, 0,117,191, 0, + 118,188, 0,120,182, 0,122,178, 0,121,179, 0,122,177, 0, + 123,170, 3,124,162, 10,124,164, 9,124,161, 11,124,150, 22, + 124,149, 24,124,152, 20,123,173, 1,118,188, 0,114,197, 0, + 109,204, 0,106,208, 0,104,210, 0,103,211, 0,103,211, 0, + 104,210, 0,104,210, 0,101,214, 0, 97,218, 0, 93,222, 0, + 90,225, 0, 88,226, 0, 88,226, 0, 89,225, 0, 91,223, 0, + 89,226, 0, 87,227, 0, 87,227, 0, 87,227, 0, 89,225, 0, + 92,223, 0, 94,220, 0, 97,218, 0, 99,216, 0, 97,217, 0, + 96,219, 0, 96,219, 0, 97,218, 0, 98,217, 0,101,214, 0, + 104,210, 0,108,205, 0,113,198, 0,117,191, 0,116,193, 0, + 115,194, 0,116,193, 0,117,191, 0,119,185, 0,122,177, 0, + 123,168, 5,123,170, 3,123,170, 3,124,167, 6,124,161, 11, + 124,149, 24,122,132, 48,117,110,109,107, 89,252, 94, 70,242, + 117,110,109,123,137, 41,124,155, 16,124,166, 7,123,173, 1, + 122,176, 0,123,174, 1,123,168, 5,124,155, 16,122,132, 48, + 111, 96,248,102, 80,250,111, 96,248,117,110,109,118,114, 96, + 118,117, 85,117,110,109,117,110,109,117,110,109,123,137, 41, + 124,155, 16,123,168, 5,122,177, 0,121,180, 0,121,180, 0, + 122,175, 0,124,164, 9,123,141, 34,119,119, 77,113,100,242, + 102, 80,250,102, 80,250,115,107,129,121,127, 58,123,141, 34, + 124,147, 26,124,145, 29,123,137, 41,122,132, 48,124,143, 31, + 124,149, 24,124,152, 20,124,150, 22,124,147, 26,124,145, 29, + 124,160, 12,124,167, 6,123,170, 3,123,172, 2,123,173, 1, + 123,174, 1,122,176, 0,121,179, 0,120,184, 0,118,188, 0, + 118,189, 0,118,188, 0,120,184, 0,122,178, 0,123,168, 5, + 124,160, 12,124,166, 7,123,173, 1,122,178, 0,121,182, 0, + 120,182, 0,121,182, 0,121,180, 0,122,178, 0,122,178, 0, + 123,174, 1,123,168, 5,124,160, 12,124,145, 29,123,137, 41, + 122,132, 48,120,122, 70,120,122, 70,123,141, 34,124,157, 15, + 123,168, 5,122,177, 0,121,182, 0,119,186, 0,115,194, 0, + 112,200, 0,110,203, 0,109,204, 0,109,204, 0,107,206, 0, + 106,208, 0,106,208, 0,107,207, 0,107,207, 0,101,214, 0, + 97,218, 0, 94,221, 0, 92,222, 0, 93,222, 0, 94,221, 0, + 92,223, 0, 91,223, 0, 92,222, 0, 94,221, 0, 96,219, 0, + 98,217, 0, 99,215, 0,100,215, 0, 98,216, 0, 97,217, 0, + 98,217, 0,100,214, 0,104,210, 0,108,205, 0,113,199, 0, + 112,200, 0,110,203, 0,108,205, 0,106,208, 0,104,210, 0, + 103,212, 0,103,211, 0,106,208, 0,110,203, 0,115,195, 0, + 114,196, 0,112,199, 0,111,201, 0,108,205, 0,106,208, 0, + 104,210, 0,105,209, 0,107,206, 0,111,201, 0,113,199, 0, + 115,194, 0,119,187, 0,123,174, 1,124,160, 12,124,143, 31, + 118,117, 85,117,110,109,117,110,109,119,119, 77,124,145, 29, + 124,166, 7,121,182, 0,117,191, 0,113,198, 0,109,203, 0, + 106,208, 0,103,211, 0,103,211, 0,106,208, 0,109,203, 0, + 114,197, 0,114,196, 0,114,196, 0,110,202, 0,107,207, 0, + 105,209, 0,104,210, 0,105,209, 0,106,208, 0,107,206, 0, + 109,204, 0,112,200, 0,112,199, 0,110,202, 0,107,206, 0, + 105,209, 0,105,209, 0,106,207, 0,107,207, 0,108,206, 0, + 106,208, 0,102,212, 0,100,215, 0, 97,217, 0, 96,219, 0, + 98,217, 0,101,213, 0,106,207, 0,111,201, 0,113,198, 0, + 116,192, 0,120,184, 0,119,185, 0,118,188, 0,118,189, 0, + 118,189, 0,119,186, 0,121,182, 0,122,178, 0,121,181, 0, + 121,180, 0,122,175, 0,124,167, 6,123,169, 4,123,169, 4, + 124,164, 9,124,150, 22,123,139, 37,124,155, 16,122,178, 0, + 118,189, 0,114,196, 0,111,201, 0,109,203, 0,108,205, 0, + 108,205, 0,108,205, 0,105,209, 0,101,214, 0, 96,219, 0, + 92,223, 0, 89,225, 0, 87,227, 0, 87,227, 0, 88,226, 0, + 91,223, 0, 88,226, 0, 85,228, 0, 84,229, 0, 84,229, 0, + 85,228, 0, 89,226, 0, 93,222, 0, 97,218, 0, 98,216, 0, + 98,217, 0, 98,217, 0, 98,217, 0,100,215, 0,102,213, 0, + 104,210, 0,107,207, 0,111,202, 0,115,194, 0,119,186, 0, + 119,187, 0,118,188, 0,119,186, 0,120,182, 0,122,175, 0, + 124,164, 9,124,166, 7,123,169, 4,123,169, 4,124,165, 8, + 124,155, 16,123,137, 41,118,114, 96,102, 80,250, 30, 31,180, + 94, 70,242,118,114, 96,122,132, 48,124,150, 22,124,165, 8, + 123,173, 1,122,177, 0,122,175, 0,123,168, 5,124,154, 18, + 121,127, 58,113,100,242,105, 84,252,111, 96,248,115,107,129, + 117,110,109,119,119, 77,118,117, 85,113,100,242,111, 96,248, + 111, 96,248,119,119, 77,123,139, 37,124,154, 18,124,160, 12, + 124,160, 12,124,150, 22,123,137, 41,118,114, 96,115,107,129, + 115,107,129,109, 92,251, 99, 75,247,114,104,197,121,125, 63, + 123,137, 41,124,143, 31,123,139, 37,122,132, 48,123,137, 41, + 124,143, 31,124,145, 29,124,143, 31,123,137, 41,122,132, 48, + 122,130, 53,124,150, 22,124,160, 12,124,162, 10,124,162, 10, + 124,162, 10,124,164, 9,124,162, 10,124,167, 6,123,174, 1, + 121,179, 0,120,182, 0,121,182, 0,122,176, 0,124,166, 7, + 124,150, 22,123,139, 37,124,154, 18,124,164, 9,123,168, 5, + 123,170, 3,123,169, 4,124,166, 7,124,162, 10,124,161, 11, + 124,160, 12,124,155, 16,124,147, 26,122,135, 44,118,114, 96, + 109, 92,251,105, 84,252,102, 80,250,113,100,242,121,127, 58, + 124,150, 22,124,166, 7,122,176, 0,121,182, 0,119,185, 0, + 117,192, 0,113,199, 0,110,203, 0,108,205, 0,108,205, 0, + 108,205, 0,107,207, 0,106,207, 0,107,206, 0,106,208, 0, + 100,214, 0, 96,219, 0, 93,222, 0, 92,222, 0, 93,222, 0, + 95,220, 0, 94,221, 0, 94,221, 0, 95,219, 0, 98,217, 0, + 101,214, 0,103,212, 0,105,209, 0,105,209, 0,104,210, 0, + 102,212, 0,103,212, 0,105,209, 0,107,206, 0,111,202, 0, + 111,201, 0,109,204, 0,107,207, 0,106,208, 0,104,210, 0, + 102,212, 0,102,212, 0,103,212, 0,106,208, 0,110,203, 0, + 114,196, 0,113,199, 0,110,202, 0,109,204, 0,109,204, 0, + 107,207, 0,106,208, 0,106,208, 0,109,204, 0,112,200, 0, + 113,198, 0,116,193, 0,120,184, 0,123,170, 3,124,145, 29, + 120,122, 70,105, 84,252, 94, 70,242,114,104,197,124,143, 31, + 124,164, 9,122,175, 0,121,181, 0,118,189, 0,114,197, 0, + 110,202, 0,107,207, 0,105,209, 0,104,210, 0,106,207, 0, + 110,203, 0,114,197, 0,116,193, 0,113,198, 0,109,204, 0, + 106,208, 0,104,210, 0,104,210, 0,105,209, 0,107,207, 0, + 109,204, 0,111,202, 0,113,198, 0,111,201, 0,108,205, 0, + 106,208, 0,105,209, 0,106,208, 0,108,206, 0,106,208, 0, + 104,210, 0,102,212, 0,102,213, 0,101,214, 0, 99,215, 0, + 98,216, 0,100,215, 0,104,210, 0,106,208, 0,107,207, 0, + 109,204, 0,112,199, 0,117,191, 0,121,182, 0,121,181, 0, + 120,183, 0,120,184, 0,120,182, 0,121,179, 0,122,177, 0, + 121,179, 0,121,179, 0,122,175, 0,123,171, 3,122,175, 0, + 122,176, 0,123,173, 1,124,166, 7,124,152, 20,122,132, 48, + 124,160, 12,122,177, 0,119,186, 0,116,192, 0,114,196, 0, + 114,197, 0,113,198, 0,111,202, 0,106,207, 0,101,213, 0, + 97,218, 0, 92,222, 0, 90,225, 0, 88,226, 0, 88,226, 0, + 89,225, 0, 91,223, 0, 89,226, 0, 85,228, 0, 83,230, 0, + 82,231, 0, 83,230, 0, 86,228, 0, 91,224, 0, 96,219, 0, + 97,217, 0,100,215, 0,100,215, 0,101,214, 0,103,211, 0, + 106,208, 0,109,204, 0,111,201, 0,114,196, 0,118,189, 0, + 120,183, 0,120,182, 0,121,181, 0,122,178, 0,123,172, 2, + 124,161, 11,124,155, 16,124,162, 10,124,166, 7,124,165, 8, + 124,157, 15,123,141, 34,118,114, 96, 94, 70,242, 30, 26,168, + 105, 84,252,122,132, 48,124,154, 18,124,164, 9,124,166, 7, + 124,164, 9,123,172, 2,122,176, 0,123,174, 1,123,168, 5, + 124,154, 18,122,130, 53,115,107,129,107, 89,252, 99, 75,247, + 105, 84,252,115,107,129,119,119, 77,119,119, 77,115,107,129, + 99, 75,247, 30, 55,222, 30, 49,213,105, 84,252,120,122, 70, + 123,141, 34,124,149, 24,124,149, 24,123,139, 37,119,119, 77, + 117,110,109,115,107,129,118,114, 96,117,110,109,121,127, 58, + 123,139, 37,123,141, 34,123,137, 41,122,132, 48,123,137, 41, + 124,145, 29,124,147, 26,124,143, 31,124,145, 29,124,143, 31, + 122,130, 53,115,107,129,122,135, 44,124,145, 29,124,149, 24, + 124,145, 29,124,152, 20,124,157, 15,124,155, 16,124,143, 31, + 124,155, 16,124,166, 7,123,170, 3,123,169, 4,124,162, 10, + 124,147, 26,121,127, 58,111, 96,248,120,122, 70,123,137, 41, + 124,145, 29,124,145, 29,123,141, 34,122,132, 48,121,125, 63, + 120,122, 70,120,122, 70,119,119, 77,117,110,109,111, 96,248, + 94, 70,242, 30, 37,192, 30, 20,155, 30, 20,155, 30, 55,222, + 113,100,242,123,139, 37,124,161, 11,123,173, 1,121,181, 0, + 119,185, 0,118,188, 0,114,196, 0,111,201, 0,109,204, 0, + 108,205, 0,108,205, 0,108,205, 0,108,205, 0,109,203, 0, + 103,211, 0, 98,217, 0, 94,221, 0, 91,223, 0, 91,224, 0, + 91,223, 0, 94,221, 0, 97,218, 0, 97,217, 0, 99,215, 0, + 101,213, 0,102,212, 0,103,211, 0,103,211, 0,105,209, 0, + 109,204, 0,107,206, 0,107,207, 0,108,206, 0,108,206, 0, + 108,206, 0,108,205, 0,108,206, 0,107,207, 0,106,208, 0, + 104,210, 0,103,212, 0,102,212, 0,103,211, 0,106,208, 0, + 110,203, 0,114,196, 0,111,201, 0,109,204, 0,107,206, 0, + 107,206, 0,107,206, 0,107,207, 0,107,206, 0,111,202, 0, + 111,201, 0,113,198, 0,116,193, 0,120,184, 0,123,170, 3, + 124,143, 31,109, 92,251, 30, 20,155, 30, 49,213,118,117, 85, + 124,152, 20,123,172, 2,120,183, 0,118,189, 0,116,193, 0, + 115,195, 0,111,201, 0,108,206, 0,105,209, 0,105,209, 0, + 106,207, 0,110,203, 0,114,197, 0,118,189, 0,113,198, 0, + 109,204, 0,106,207, 0,105,209, 0,106,208, 0,107,206, 0, + 109,203, 0,111,202, 0,110,202, 0,109,204, 0,108,206, 0, + 107,207, 0,106,208, 0,106,208, 0,107,207, 0,109,203, 0, + 105,209, 0,101,214, 0, 98,216, 0, 98,217, 0, 98,217, 0, + 99,215, 0,100,215, 0,101,213, 0,101,213, 0,101,214, 0, + 102,212, 0,105,209, 0,109,204, 0,114,196, 0,119,185, 0, + 123,169, 4,123,174, 1,122,176, 0,122,175, 0,123,174, 1, + 123,171, 3,123,173, 1,123,173, 1,123,169, 4,123,174, 1, + 121,179, 0,121,181, 0,121,180, 0,122,175, 0,124,165, 8, + 124,150, 22,122,132, 48,124,162, 10,122,175, 0,120,183, 0, + 119,187, 0,118,189, 0,116,193, 0,113,199, 0,109,204, 0, + 103,211, 0, 99,216, 0, 95,220, 0, 92,222, 0, 91,223, 0, + 91,223, 0, 92,222, 0, 94,220, 0, 91,224, 0, 87,227, 0, + 84,229, 0, 82,231, 0, 83,230, 0, 85,229, 0, 89,225, 0, + 95,220, 0, 95,219, 0, 98,217, 0,101,213, 0,104,210, 0, + 107,207, 0,110,202, 0,113,199, 0,116,193, 0,116,193, 0, + 117,192, 0,117,191, 0,118,189, 0,119,185, 0,121,179, 0, + 123,168, 5,124,147, 26,124,150, 22,124,157, 15,124,158, 13, + 124,154, 18,123,141, 34,117,110,109, 30, 55,222, 30, 5,128, + 102, 80,250,122,135, 44,124,161, 11,123,173, 1,121,179, 0, + 121,180, 0,122,178, 0,123,172, 2,122,176, 0,122,175, 0, + 123,170, 3,124,160, 12,123,139, 37,115,107,129, 99, 75,247, + 30, 20,155, 99, 75,247,115,107,129,120,122, 70,120,122, 70, + 118,114, 96,113,100,242,102, 80,250, 30, 49,213, 99, 75,247, + 118,117, 85,123,141, 34,124,152, 20,124,154, 18,124,149, 24, + 122,135, 44,115,107,129,122,135, 44,123,141, 34,124,143, 31, + 124,150, 22,124,154, 18,124,152, 20,124,143, 31,122,130, 53, + 124,147, 26,124,152, 20,124,152, 20,124,147, 26,124,150, 22, + 124,150, 22,123,139, 37,118,117, 85,114,104,197,118,117, 85, + 118,117, 85,122,130, 53,123,139, 37,124,143, 31,123,141, 34, + 121,125, 63,118,117, 85,122,135, 44,124,145, 29,124,154, 18, + 124,157, 15,124,152, 20,123,139, 37,118,117, 85,107, 89,252, + 109, 92,251,105, 84,252,102, 80,250, 94, 70,242,107, 89,252, + 111, 96,248,109, 92,251, 99, 75,247, 30, 43,203, 30, 43,203, + 30, 31,180, 30, 43,203, 87, 65,237,107, 89,252,114,104,197, + 115,107,129,117,110,109,122,130, 53,124,155, 16,123,172, 2, + 121,182, 0,119,187, 0,117,191, 0,116,193, 0,113,198, 0, + 111,202, 0,109,204, 0,108,205, 0,108,205, 0,108,205, 0, + 108,206, 0,102,213, 0, 96,219, 0, 92,222, 0, 89,225, 0, + 89,226, 0, 89,225, 0, 92,223, 0, 95,220, 0, 97,217, 0, + 99,216, 0,100,214, 0,100,214, 0,100,215, 0,100,215, 0, + 102,213, 0,105,209, 0,108,205, 0,108,206, 0,107,207, 0, + 106,208, 0,106,208, 0,105,209, 0,105,209, 0,104,210, 0, + 104,210, 0,105,209, 0,104,210, 0,103,212, 0,103,211, 0, + 105,209, 0,109,204, 0,113,199, 0,111,201, 0,108,205, 0, + 107,207, 0,106,207, 0,107,207, 0,107,206, 0,108,205, 0, + 109,204, 0,110,203, 0,112,200, 0,115,195, 0,119,187, 0, + 123,174, 1,124,150, 22,118,114, 96,111, 96,248,109, 92,251, + 120,122, 70,124,157, 15,122,177, 0,118,188, 0,115,195, 0, + 112,199, 0,111,201, 0,111,201, 0,109,203, 0,107,207, 0, + 106,208, 0,107,207, 0,110,202, 0,114,196, 0,116,192, 0, + 114,197, 0,110,203, 0,107,206, 0,107,207, 0,108,205, 0, + 110,202, 0,108,205, 0,107,207, 0,106,207, 0,105,209, 0, + 104,210, 0,103,211, 0,104,210, 0,105,209, 0,106,208, 0, + 106,208, 0,103,212, 0, 99,216, 0, 96,219, 0, 94,220, 0, + 94,221, 0, 94,220, 0, 95,219, 0, 96,219, 0, 97,218, 0, + 97,217, 0, 99,216, 0,102,212, 0,107,207, 0,112,199, 0, + 118,189, 0,122,175, 0,124,162, 10,124,164, 9,124,165, 8, + 124,166, 7,124,165, 8,124,165, 8,124,166, 7,123,169, 4, + 122,175, 0,121,180, 0,120,182, 0,121,182, 0,122,178, 0, + 123,169, 4,124,157, 15,124,143, 31,124,150, 22,124,165, 8, + 123,174, 1,121,181, 0,119,186, 0,115,194, 0,110,202, 0, + 106,208, 0,103,212, 0,100,215, 0, 97,217, 0, 95,220, 0, + 93,222, 0, 91,223, 0, 91,223, 0, 91,223, 0, 88,226, 0, + 87,227, 0, 87,227, 0, 84,229, 0, 84,229, 0, 85,228, 0, + 89,225, 0, 93,221, 0, 94,221, 0, 97,218, 0,100,215, 0, + 104,210, 0,109,204, 0,111,201, 0,112,200, 0,113,199, 0, + 113,198, 0,114,197, 0,115,195, 0,116,192, 0,118,188, 0, + 121,182, 0,123,170, 3,124,161, 11,124,160, 12,124,157, 15, + 124,150, 22,122,135, 44,114,104,197, 30, 55,222, 30, 37,192, + 113,100,242,123,139, 37,124,164, 9,122,178, 0,119,186, 0, + 118,189, 0,118,189, 0,118,188, 0,120,184, 0,122,178, 0, + 122,177, 0,123,173, 1,124,165, 8,124,152, 20,122,130, 53, + 114,104,197,102, 80,250,105, 84,252,117,110,109,122,130, 53, + 123,139, 37,123,141, 34,122,135, 44,121,125, 63,118,114, 96, + 111, 96,248,118,117, 85,124,143, 31,124,157, 15,124,162, 10, + 124,161, 11,124,155, 16,124,157, 15,124,161, 11,124,166, 7, + 123,169, 4,123,170, 3,123,169, 4,124,165, 8,124,155, 16, + 123,137, 41,124,150, 22,124,157, 15,124,155, 16,124,150, 22, + 124,155, 16,124,154, 18,124,145, 29,122,130, 53,109, 92,251, + 102, 80,250,113,100,242,118,117, 85,121,125, 63,122,130, 53, + 121,125, 63,114,104,197, 30, 49,213, 99, 75,247,120,122, 70, + 124,147, 26,124,157, 15,124,157, 15,124,150, 22,122,135, 44, + 118,117, 85,113,100,242,107, 89,252,102, 80,250,102, 80,250, + 105, 84,252,102, 80,250, 94, 70,242, 30, 49,213, 30, 31,180, + 30, 43,203, 99, 75,247,111, 96,248,117,110,109,120,122, 70, + 122,132, 48,123,137, 41,121,127, 58,124,143, 31,124,155, 16, + 123,172, 2,120,184, 0,117,190, 0,115,194, 0,114,197, 0, + 113,199, 0,111,201, 0,110,202, 0,108,205, 0,108,206, 0, + 107,206, 0,107,206, 0,102,212, 0, 97,217, 0, 93,222, 0, + 90,225, 0, 88,226, 0, 89,226, 0, 91,224, 0, 93,222, 0, + 95,219, 0, 97,217, 0, 98,217, 0, 97,218, 0, 97,218, 0, + 97,217, 0,100,215, 0,103,211, 0,107,206, 0,108,206, 0, + 107,207, 0,106,208, 0,105,209, 0,105,209, 0,104,210, 0, + 103,212, 0,102,212, 0,104,210, 0,105,209, 0,103,211, 0, + 103,211, 0,105,209, 0,107,206, 0,110,202, 0,110,202, 0, + 110,203, 0,108,206, 0,106,207, 0,106,208, 0,106,208, 0, + 106,207, 0,107,207, 0,108,205, 0,110,203, 0,113,198, 0, + 117,191, 0,121,179, 0,124,160, 12,124,145, 29,122,132, 48, + 120,122, 70,123,137, 41,124,160, 12,121,181, 0,116,192, 0, + 112,200, 0,109,204, 0,107,207, 0,108,206, 0,110,202, 0, + 109,203, 0,108,205, 0,109,204, 0,112,200, 0,115,194, 0, + 115,194, 0,113,198, 0,110,202, 0,109,204, 0,109,204, 0, + 110,202, 0,107,206, 0,104,210, 0,102,212, 0,102,212, 0, + 101,213, 0,101,214, 0,101,214, 0,101,213, 0,102,212, 0, + 102,212, 0,102,212, 0,101,213, 0, 98,217, 0, 94,221, 0, + 92,223, 0, 90,224, 0, 90,224, 0, 91,224, 0, 92,222, 0, + 93,221, 0, 95,220, 0, 98,217, 0,101,213, 0,106,207, 0, + 112,200, 0,117,190, 0,122,178, 0,124,164, 9,124,147, 26, + 124,149, 24,124,152, 20,124,157, 15,124,161, 11,124,161, 11, + 124,165, 8,123,171, 3,122,176, 0,122,178, 0,122,178, 0, + 123,174, 1,124,167, 6,124,155, 16,124,145, 29,124,157, 15, + 124,167, 6,122,175, 0,121,182, 0,119,186, 0,114,196, 0, + 109,204, 0,105,209, 0,101,214, 0, 98,217, 0, 95,220, 0, + 92,223, 0, 90,225, 0, 88,226, 0, 87,227, 0, 88,226, 0, + 85,229, 0, 85,229, 0, 86,228, 0, 87,227, 0, 86,228, 0, + 87,227, 0, 89,225, 0, 93,221, 0, 94,221, 0, 96,219, 0, + 99,215, 0,103,211, 0,108,205, 0,111,201, 0,111,201, 0, + 112,200, 0,112,199, 0,113,198, 0,114,197, 0,116,193, 0, + 118,189, 0,121,182, 0,123,172, 2,123,171, 3,123,169, 4, + 124,166, 7,124,155, 16,123,137, 41,113,100,242, 99, 75,247, + 121,127, 58,124,154, 18,123,169, 4,121,181, 0,118,189, 0, + 115,194, 0,113,198, 0,113,198, 0,114,196, 0,116,193, 0, + 118,189, 0,120,182, 0,123,173, 1,123,168, 5,124,161, 11, + 124,149, 24,122,135, 44,119,119, 77,118,117, 85,122,130, 53, + 124,145, 29,124,152, 20,124,155, 16,124,152, 20,124,149, 24, + 124,147, 26,124,143, 31,123,137, 41,124,157, 15,123,168, 5, + 122,175, 0,122,178, 0,121,181, 0,120,182, 0,120,184, 0, + 119,185, 0,119,186, 0,119,185, 0,120,182, 0,122,178, 0, + 123,168, 5,124,152, 20,124,147, 26,124,154, 18,124,155, 16, + 124,152, 20,124,157, 15,124,157, 15,124,150, 22,123,137, 41, + 118,114, 96,111, 96,248,107, 89,252,111, 96,248,115,107,129, + 115,107,129,114,104,197,113,100,242,105, 84,252, 87, 65,237, + 120,122, 70,124,149, 24,124,162, 10,124,167, 6,124,166, 7, + 124,160, 12,124,152, 20,124,145, 29,123,139, 37,122,135, 44, + 122,132, 48,122,130, 53,121,125, 63,118,117, 85,115,107,129, + 111, 96,248,114,104,197,118,117, 85,121,125, 63,122,132, 48, + 123,139, 37,124,147, 26,124,149, 24,124,143, 31,124,152, 20, + 124,161, 11,123,172, 2,120,184, 0,116,192, 0,113,198, 0, + 111,201, 0,110,202, 0,110,203, 0,109,203, 0,109,204, 0, + 108,206, 0,107,207, 0,107,206, 0,105,209, 0,101,214, 0, + 96,219, 0, 93,222, 0, 91,224, 0, 90,225, 0, 91,224, 0, + 92,222, 0, 95,220, 0, 97,218, 0, 96,219, 0, 95,219, 0, + 95,219, 0, 97,218, 0,100,215, 0,103,211, 0,107,206, 0, + 109,204, 0,108,206, 0,107,207, 0,106,207, 0,106,208, 0, + 105,209, 0,103,211, 0,103,211, 0,104,210, 0,106,207, 0, + 105,209, 0,103,211, 0,104,210, 0,106,208, 0,108,205, 0, + 109,204, 0,109,204, 0,109,204, 0,108,206, 0,106,207, 0, + 106,208, 0,106,208, 0,106,208, 0,107,207, 0,109,204, 0, + 112,200, 0,116,193, 0,120,183, 0,124,167, 6,124,158, 13, + 124,147, 26,122,132, 48,123,141, 34,124,161, 11,120,183, 0, + 115,195, 0,110,202, 0,106,207, 0,105,209, 0,105,209, 0, + 108,205, 0,111,201, 0,111,202, 0,111,201, 0,113,198, 0, + 116,193, 0,115,194, 0,113,198, 0,110,202, 0,110,203, 0, + 110,202, 0,109,203, 0,105,209, 0,101,214, 0, 99,215, 0, + 99,215, 0, 99,215, 0,100,215, 0,100,215, 0,100,214, 0, + 101,214, 0,100,214, 0, 99,215, 0, 98,217, 0, 97,218, 0, + 93,221, 0, 90,225, 0, 88,226, 0, 87,227, 0, 87,227, 0, + 89,225, 0, 92,223, 0, 95,220, 0, 99,216, 0,103,211, 0, + 108,205, 0,114,197, 0,118,188, 0,122,178, 0,124,166, 7, + 124,149, 24,124,150, 22,124,152, 20,124,157, 15,124,158, 13, + 124,160, 12,124,158, 13,124,164, 9,123,168, 5,123,170, 3, + 123,170, 3,124,166, 7,124,160, 12,124,149, 24,124,152, 20, + 124,161, 11,123,170, 3,122,178, 0,120,183, 0,119,187, 0, + 114,196, 0,109,204, 0,104,210, 0,100,214, 0, 96,219, 0, + 93,222, 0, 90,225, 0, 87,227, 0, 86,228, 0, 85,229, 0, + 85,228, 0, 83,230, 0, 83,230, 0, 85,229, 0, 88,226, 0, + 88,226, 0, 88,226, 0, 91,224, 0, 95,220, 0, 95,220, 0, + 97,218, 0, 99,215, 0,103,211, 0,107,206, 0,111,201, 0, + 113,199, 0,113,198, 0,113,198, 0,114,197, 0,114,196, 0, + 116,193, 0,118,188, 0,121,179, 0,122,177, 0,122,176, 0, + 122,175, 0,123,170, 3,124,160, 12,123,137, 41,111, 96,248, + 122,135, 44,124,164, 9,122,176, 0,120,184, 0,117,191, 0, + 114,197, 0,111,201, 0,109,203, 0,109,204, 0,110,203, 0, + 111,201, 0,114,197, 0,117,192, 0,120,183, 0,123,170, 3, + 124,165, 8,124,158, 13,124,149, 24,124,149, 24,124,147, 26, + 124,145, 29,124,152, 20,124,158, 13,124,161, 11,124,162, 10, + 124,162, 10,124,166, 7,124,166, 7,124,161, 11,123,171, 3, + 121,181, 0,118,188, 0,116,192, 0,115,194, 0,114,196, 0, + 114,197, 0,114,197, 0,114,196, 0,115,195, 0,117,192, 0, + 119,187, 0,121,179, 0,124,166, 7,124,145, 29,124,150, 22, + 124,154, 18,124,152, 20,124,155, 16,124,155, 16,124,152, 20, + 123,141, 34,121,125, 63,118,117, 85,117,110,109,118,117, 85, + 121,127, 58,122,135, 44,123,141, 34,124,143, 31,123,141, 34, + 122,130, 53,123,137, 41,124,160, 12,123,172, 2,122,178, 0, + 121,180, 0,122,178, 0,122,175, 0,123,172, 2,123,170, 3, + 124,167, 6,124,165, 8,124,160, 12,124,155, 16,124,147, 26, + 123,137, 41,122,135, 44,123,137, 41,123,139, 37,123,141, 34, + 124,143, 31,124,145, 29,124,150, 22,124,155, 16,124,152, 20, + 124,157, 15,124,162, 10,123,170, 3,120,184, 0,116,193, 0, + 112,199, 0,110,202, 0,109,204, 0,108,205, 0,108,205, 0, + 109,204, 0,108,206, 0,107,206, 0,108,206, 0,108,205, 0, + 105,209, 0,101,214, 0, 97,217, 0, 95,220, 0, 93,221, 0, + 93,222, 0, 94,220, 0, 96,219, 0, 97,218, 0, 96,219, 0, + 96,219, 0, 97,218, 0, 98,216, 0,101,213, 0,105,209, 0, + 109,204, 0,110,202, 0,110,203, 0,109,204, 0,109,204, 0, + 108,205, 0,107,206, 0,106,208, 0,105,209, 0,105,209, 0, + 107,206, 0,106,208, 0,105,209, 0,104,210, 0,105,209, 0, + 108,205, 0,108,205, 0,108,205, 0,109,204, 0,110,203, 0, + 108,205, 0,107,207, 0,106,208, 0,106,207, 0,107,207, 0, + 108,205, 0,111,201, 0,115,195, 0,119,185, 0,123,171, 3, + 124,162, 10,124,149, 24,122,130, 53,123,137, 41,124,164, 9, + 120,184, 0,114,196, 0,110,203, 0,106,207, 0,105,209, 0, + 105,209, 0,108,206, 0,111,202, 0,113,198, 0,113,198, 0, + 115,195, 0,117,192, 0,116,193, 0,113,198, 0,111,202, 0, + 110,202, 0,111,201, 0,108,205, 0,103,211, 0,100,215, 0, + 98,217, 0, 98,216, 0, 99,215, 0,100,214, 0,101,214, 0, + 101,213, 0,101,214, 0,100,215, 0, 97,217, 0, 95,219, 0, + 95,220, 0, 93,221, 0, 90,225, 0, 87,227, 0, 86,228, 0, + 87,227, 0, 89,225, 0, 93,221, 0, 98,217, 0,102,212, 0, + 108,206, 0,112,199, 0,117,192, 0,120,184, 0,122,175, 0, + 124,165, 8,124,149, 24,124,150, 22,124,154, 18,124,155, 16, + 124,158, 13,124,158, 13,124,158, 13,124,157, 15,124,157, 15, + 124,158, 13,124,158, 13,124,154, 18,124,149, 24,124,154, 18, + 124,158, 13,124,165, 8,123,172, 2,121,179, 0,120,184, 0, + 118,189, 0,116,193, 0,110,202, 0,105,209, 0,100,214, 0, + 96,219, 0, 92,222, 0, 89,225, 0, 87,227, 0, 85,229, 0, + 85,229, 0, 85,229, 0, 84,229, 0, 84,229, 0, 86,228, 0, + 89,225, 0, 90,224, 0, 90,225, 0, 92,223, 0, 96,219, 0, + 97,218, 0, 98,217, 0,100,215, 0,103,211, 0,107,207, 0, + 111,202, 0,114,197, 0,115,194, 0,115,194, 0,115,194, 0, + 116,193, 0,117,191, 0,119,186, 0,122,177, 0,122,177, 0, + 122,178, 0,122,176, 0,123,170, 3,124,160, 12,123,137, 41, + 122,130, 53,124,162, 10,121,179, 0,118,188, 0,116,192, 0, + 114,197, 0,111,202, 0,108,205, 0,107,207, 0,106,207, 0, + 106,207, 0,107,206, 0,110,203, 0,113,198, 0,117,191, 0, + 122,178, 0,124,166, 7,124,161, 11,124,160, 12,124,161, 11, + 124,160, 12,124,157, 15,124,154, 18,124,160, 12,124,164, 9, + 124,167, 6,123,170, 3,122,176, 0,121,179, 0,122,178, 0, + 121,182, 0,117,190, 0,114,197, 0,111,201, 0,109,204, 0, + 108,205, 0,108,205, 0,108,205, 0,109,204, 0,110,202, 0, + 113,199, 0,115,194, 0,119,187, 0,122,176, 0,124,157, 15, + 124,145, 29,124,154, 18,124,154, 18,124,149, 24,124,150, 22, + 124,150, 22,123,139, 37,122,130, 53,121,127, 58,123,139, 37, + 124,145, 29,124,152, 20,124,155, 16,124,158, 13,124,161, 11, + 124,162, 10,124,160, 12,124,152, 20,124,166, 7,122,177, 0, + 120,183, 0,119,186, 0,119,186, 0,119,185, 0,120,184, 0, + 120,184, 0,120,182, 0,121,179, 0,122,176, 0,123,170, 3, + 124,162, 10,124,160, 12,124,160, 12,124,160, 12,124,155, 16, + 124,152, 20,124,152, 20,124,155, 16,124,157, 15,124,157, 15, + 124,157, 15,124,155, 16,124,158, 13,124,167, 6,120,182, 0, + 116,192, 0,112,199, 0,110,203, 0,108,205, 0,108,206, 0, + 108,206, 0,108,205, 0,108,205, 0,108,206, 0,109,204, 0, + 109,204, 0,109,204, 0,107,207, 0,104,210, 0,101,214, 0, + 98,216, 0, 98,217, 0, 98,216, 0, 99,215, 0, 99,216, 0, + 98,217, 0, 98,217, 0, 99,215, 0,101,213, 0,105,209, 0, + 109,204, 0,112,200, 0,112,200, 0,112,200, 0,112,200, 0, + 112,200, 0,112,200, 0,111,201, 0,109,203, 0,108,206, 0, + 107,206, 0,108,205, 0,108,205, 0,107,207, 0,106,208, 0, + 106,208, 0,108,206, 0,109,204, 0,109,204, 0,109,203, 0, + 110,202, 0,111,202, 0,109,204, 0,108,205, 0,108,205, 0, + 109,204, 0,110,203, 0,112,200, 0,115,194, 0,119,185, 0, + 123,170, 3,124,158, 13,123,141, 34,118,117, 85,120,122, 70, + 124,165, 8,120,184, 0,115,194, 0,111,201, 0,108,205, 0, + 107,207, 0,107,207, 0,109,203, 0,113,199, 0,114,196, 0, + 114,196, 0,116,192, 0,118,188, 0,117,191, 0,114,197, 0, + 111,201, 0,111,201, 0,112,200, 0,109,204, 0,104,210, 0, + 101,214, 0,100,215, 0,100,214, 0,102,213, 0,103,211, 0, + 104,210, 0,104,210, 0,103,211, 0,101,214, 0, 97,218, 0, + 94,220, 0, 93,221, 0, 94,221, 0, 91,223, 0, 89,225, 0, + 88,226, 0, 89,226, 0, 92,222, 0, 97,218, 0,102,212, 0, + 108,205, 0,113,198, 0,117,190, 0,120,182, 0,123,174, 1, + 124,167, 6,124,157, 15,124,147, 26,124,149, 24,124,152, 20, + 124,154, 18,124,155, 16,124,157, 15,124,164, 9,124,167, 6, + 123,168, 5,124,166, 7,124,161, 11,124,157, 15,124,157, 15, + 124,158, 13,124,160, 12,124,165, 8,123,172, 2,121,180, 0, + 119,186, 0,117,190, 0,115,194, 0,113,199, 0,107,207, 0, + 102,213, 0, 97,218, 0, 93,222, 0, 90,225, 0, 87,227, 0, + 86,228, 0, 86,228, 0, 87,227, 0, 88,226, 0, 87,227, 0, + 89,225, 0, 92,222, 0, 92,222, 0, 92,223, 0, 94,221, 0, + 98,217, 0, 99,216, 0,100,215, 0,101,214, 0,104,210, 0, + 107,206, 0,111,201, 0,114,196, 0,116,193, 0,117,191, 0, + 117,191, 0,117,190, 0,118,188, 0,120,183, 0,123,174, 1, + 123,172, 2,123,174, 1,123,173, 1,123,168, 5,124,157, 15, + 123,137, 41,124,154, 18,122,175, 0,119,187, 0,116,193, 0, + 114,196, 0,112,200, 0,110,202, 0,108,205, 0,106,207, 0, + 105,209, 0,105,209, 0,105,209, 0,107,207, 0,110,202, 0, + 114,196, 0,119,186, 0,123,168, 5,124,160, 12,124,162, 10, + 124,165, 8,124,164, 9,124,160, 12,124,152, 20,124,157, 15, + 124,162, 10,123,168, 5,122,175, 0,120,182, 0,118,188, 0, + 118,189, 0,118,189, 0,114,197, 0,110,202, 0,107,207, 0, + 105,209, 0,104,210, 0,104,210, 0,105,209, 0,105,209, 0, + 107,207, 0,109,203, 0,113,199, 0,116,192, 0,120,182, 0, + 124,166, 7,124,143, 31,124,154, 18,124,157, 15,124,154, 18, + 124,143, 31,124,143, 31,122,130, 53,122,132, 48,124,145, 29, + 124,154, 18,124,160, 12,124,162, 10,124,164, 9,124,165, 8, + 123,169, 4,123,171, 3,123,171, 3,123,170, 3,123,170, 3, + 121,179, 0,119,185, 0,118,188, 0,118,189, 0,118,189, 0, + 117,191, 0,117,191, 0,117,190, 0,118,188, 0,119,185, 0, + 121,179, 0,123,173, 1,122,175, 0,122,175, 0,123,171, 3, + 124,166, 7,124,160, 12,124,162, 10,124,164, 9,124,164, 9, + 124,158, 13,124,160, 12,124,160, 12,124,155, 16,124,161, 11, + 122,178, 0,118,189, 0,114,197, 0,111,202, 0,109,204, 0, + 108,205, 0,108,205, 0,108,205, 0,108,205, 0,108,205, 0, + 108,206, 0,107,206, 0,108,206, 0,109,204, 0,109,204, 0, + 107,207, 0,105,209, 0,103,211, 0,103,211, 0,103,211, 0, + 103,212, 0,102,212, 0,102,212, 0,103,211, 0,106,208, 0, + 109,204, 0,113,199, 0,114,196, 0,114,196, 0,114,196, 0, + 115,194, 0,115,195, 0,113,198, 0,113,199, 0,113,198, 0, + 111,202, 0,110,203, 0,109,203, 0,110,202, 0,110,203, 0, + 108,205, 0,108,206, 0,109,204, 0,111,202, 0,111,202, 0, + 111,202, 0,112,200, 0,113,198, 0,113,199, 0,112,200, 0, + 112,200, 0,112,200, 0,112,200, 0,114,197, 0,117,192, 0, + 120,183, 0,124,167, 6,124,147, 26,120,122, 70,105, 84,252, + 121,127, 58,124,166, 7,120,182, 0,117,192, 0,114,197, 0, + 112,200, 0,111,202, 0,111,201, 0,113,198, 0,116,193, 0, + 115,195, 0,115,194, 0,117,191, 0,120,184, 0,118,189, 0, + 114,196, 0,112,200, 0,111,201, 0,112,200, 0,110,202, 0, + 107,207, 0,104,210, 0,103,211, 0,105,209, 0,106,207, 0, + 108,205, 0,106,207, 0,105,209, 0,104,210, 0,103,211, 0, + 98,216, 0, 95,220, 0, 93,221, 0, 94,221, 0, 94,221, 0, + 92,222, 0, 92,223, 0, 93,221, 0, 97,218, 0,103,212, 0, + 109,204, 0,114,196, 0,117,191, 0,121,182, 0,124,167, 6, + 124,157, 15,124,149, 24,123,139, 37,123,139, 37,124,143, 31, + 124,147, 26,124,149, 24,124,157, 15,124,165, 8,123,170, 3, + 122,175, 0,122,177, 0,122,176, 0,123,172, 2,124,166, 7, + 124,158, 13,124,157, 15,124,157, 15,124,161, 11,123,170, 3, + 122,178, 0,119,186, 0,117,191, 0,115,195, 0,113,198, 0, + 109,203, 0,104,210, 0, 99,216, 0, 95,220, 0, 92,222, 0, + 90,224, 0, 90,225, 0, 90,225, 0, 91,224, 0, 92,222, 0, + 92,222, 0, 94,221, 0, 95,219, 0, 94,221, 0, 94,221, 0, + 95,219, 0,100,215, 0,101,213, 0,101,213, 0,103,212, 0, + 105,209, 0,108,205, 0,111,201, 0,115,195, 0,118,189, 0, + 119,186, 0,119,186, 0,119,186, 0,120,184, 0,121,180, 0, + 123,171, 3,124,162, 10,124,166, 7,124,166, 7,124,161, 11, + 124,150, 22,124,152, 20,124,165, 8,121,180, 0,118,189, 0, + 115,194, 0,114,197, 0,112,199, 0,111,202, 0,109,204, 0, + 107,207, 0,106,208, 0,105,209, 0,105,209, 0,106,208, 0, + 109,204, 0,112,199, 0,117,191, 0,122,177, 0,124,152, 20, + 124,157, 15,124,161, 11,124,161, 11,124,155, 16,124,145, 29, + 124,150, 22,124,160, 12,123,169, 4,122,178, 0,119,187, 0, + 116,193, 0,114,197, 0,113,198, 0,111,201, 0,107,206, 0, + 104,210, 0,102,213, 0,101,213, 0,102,213, 0,102,212, 0, + 103,211, 0,105,209, 0,107,206, 0,110,202, 0,114,196, 0, + 119,186, 0,123,170, 3,124,155, 16,124,155, 16,124,160, 12, + 124,158, 13,124,149, 24,122,130, 53,118,117, 85,123,141, 34, + 124,154, 18,124,161, 11,124,165, 8,124,166, 7,124,166, 7, + 124,167, 6,123,170, 3,123,174, 1,122,177, 0,122,178, 0, + 122,178, 0,121,179, 0,120,184, 0,118,188, 0,118,189, 0, + 117,191, 0,116,193, 0,115,194, 0,115,195, 0,115,194, 0, + 117,191, 0,119,186, 0,120,183, 0,120,184, 0,120,183, 0, + 121,179, 0,123,173, 1,124,165, 8,124,166, 7,124,166, 7, + 124,164, 9,124,158, 13,124,162, 10,124,164, 9,124,162, 10, + 123,171, 3,122,177, 0,119,185, 0,116,193, 0,113,199, 0, + 111,202, 0,110,202, 0,110,203, 0,109,204, 0,108,205, 0, + 108,205, 0,108,205, 0,107,207, 0,107,207, 0,107,206, 0, + 109,204, 0,110,202, 0,109,204, 0,108,205, 0,108,205, 0, + 109,204, 0,108,205, 0,108,206, 0,108,206, 0,108,205, 0, + 110,202, 0,113,198, 0,117,192, 0,116,193, 0,115,194, 0, + 116,193, 0,117,192, 0,116,192, 0,115,194, 0,115,194, 0, + 115,194, 0,114,197, 0,112,200, 0,111,202, 0,110,202, 0, + 111,201, 0,112,200, 0,111,202, 0,111,202, 0,112,200, 0, + 113,198, 0,113,198, 0,113,198, 0,114,197, 0,115,194, 0, + 116,193, 0,115,194, 0,115,194, 0,115,194, 0,116,193, 0, + 118,188, 0,121,180, 0,124,162, 10,122,130, 53,109, 92,251, + 94, 70,242,122,132, 48,124,165, 8,121,179, 0,119,187, 0, + 117,191, 0,116,193, 0,115,194, 0,115,194, 0,117,192, 0, + 115,194, 0,114,196, 0,116,193, 0,118,189, 0,120,183, 0, + 119,187, 0,115,194, 0,113,198, 0,112,200, 0,112,199, 0, + 113,198, 0,110,202, 0,109,204, 0,108,205, 0,110,203, 0, + 109,203, 0,106,207, 0,104,210, 0,103,211, 0,103,212, 0, + 103,211, 0,101,214, 0, 97,218, 0, 95,220, 0, 95,220, 0, + 97,218, 0, 97,218, 0, 97,218, 0, 99,216, 0,103,211, 0, + 109,203, 0,111,201, 0,114,197, 0,117,191, 0,121,182, 0, + 124,165, 8,122,132, 48,118,117, 85,118,117, 85,121,125, 63, + 122,132, 48,123,139, 37,124,154, 18,124,162, 10,123,169, 4, + 123,174, 1,122,178, 0,121,181, 0,121,181, 0,122,178, 0, + 123,170, 3,124,158, 13,124,149, 24,124,145, 29,124,150, 22, + 124,164, 9,123,174, 1,120,184, 0,117,190, 0,115,194, 0, + 113,198, 0,112,200, 0,106,208, 0,101,214, 0, 97,217, 0, + 95,220, 0, 94,221, 0, 94,221, 0, 94,220, 0, 95,219, 0, + 97,218, 0, 98,217, 0, 99,216, 0, 97,218, 0, 95,219, 0, + 96,219, 0, 98,216, 0,103,212, 0,104,210, 0,104,210, 0, + 105,209, 0,107,206, 0,109,204, 0,112,200, 0,116,193, 0, + 119,187, 0,122,178, 0,121,182, 0,120,182, 0,121,181, 0, + 122,177, 0,124,167, 6,124,152, 20,124,149, 24,124,150, 22, + 124,147, 26,124,155, 16,124,162, 10,123,169, 4,120,182, 0, + 117,190, 0,115,194, 0,114,196, 0,113,198, 0,110,202, 0, + 108,206, 0,107,207, 0,107,207, 0,106,208, 0,106,208, 0, + 107,207, 0,108,205, 0,111,201, 0,116,193, 0,120,182, 0, + 124,164, 9,124,147, 26,124,152, 20,124,152, 20,124,145, 29, + 122,132, 48,124,143, 31,124,167, 6,121,180, 0,119,187, 0, + 117,191, 0,113,199, 0,110,203, 0,108,205, 0,108,206, 0, + 105,209, 0,102,212, 0,101,214, 0,100,214, 0,101,214, 0, + 102,213, 0,103,212, 0,104,210, 0,107,207, 0,110,203, 0, + 114,197, 0,118,188, 0,123,174, 1,123,168, 5,124,158, 13, + 124,164, 9,124,161, 11,124,152, 20,122,132, 48,118,114, 96, + 123,141, 34,124,157, 15,124,164, 9,124,166, 7,124,166, 7, + 124,166, 7,124,166, 7,123,169, 4,123,174, 1,122,178, 0, + 121,182, 0,120,183, 0,120,184, 0,119,186, 0,119,186, 0, + 119,187, 0,118,189, 0,116,193, 0,114,196, 0,113,198, 0, + 113,198, 0,114,197, 0,116,193, 0,118,188, 0,118,188, 0, + 119,187, 0,120,183, 0,122,178, 0,123,170, 3,124,164, 9, + 124,161, 11,124,155, 16,124,161, 11,124,166, 7,123,168, 5, + 123,172, 2,121,180, 0,119,185, 0,118,188, 0,118,189, 0, + 115,195, 0,113,198, 0,112,200, 0,110,203, 0,108,205, 0, + 108,206, 0,108,205, 0,110,203, 0,108,205, 0,107,206, 0, + 107,207, 0,108,205, 0,109,203, 0,111,201, 0,113,199, 0, + 113,198, 0,114,197, 0,113,198, 0,113,199, 0,113,199, 0, + 113,198, 0,114,196, 0,116,192, 0,118,188, 0,117,191, 0, + 116,192, 0,116,192, 0,117,191, 0,117,190, 0,116,192, 0, + 116,192, 0,117,191, 0,115,194, 0,114,197, 0,112,200, 0, + 111,201, 0,111,201, 0,112,200, 0,113,198, 0,114,197, 0, + 114,197, 0,114,196, 0,115,195, 0,115,194, 0,115,194, 0, + 116,193, 0,117,191, 0,119,186, 0,118,188, 0,118,189, 0, + 118,188, 0,119,185, 0,122,177, 0,124,160, 12,120,122, 70, + 30, 49,213, 99, 75,247,122,132, 48,124,161, 11,123,174, 1, + 121,181, 0,120,183, 0,120,184, 0,119,186, 0,118,189, 0, + 116,193, 0,115,195, 0,114,196, 0,116,193, 0,118,188, 0, + 119,185, 0,120,184, 0,116,192, 0,114,196, 0,113,199, 0, + 113,199, 0,113,198, 0,114,197, 0,113,198, 0,114,197, 0, + 111,201, 0,109,204, 0,106,208, 0,104,210, 0,103,211, 0, + 104,210, 0,105,209, 0,105,209, 0,100,214, 0, 98,217, 0, + 97,217, 0, 98,216, 0,101,214, 0,102,212, 0,105,209, 0, + 109,203, 0,111,201, 0,112,199, 0,115,195, 0,118,189, 0, + 122,178, 0,124,158, 13,120,122, 70,102, 80,250,109, 92,251, + 114,104,197,121,125, 63,124,145, 29,124,157, 15,124,164, 9, + 123,169, 4,123,174, 1,122,178, 0,121,181, 0,121,180, 0, + 122,177, 0,123,168, 5,124,154, 18,121,127, 58,120,122, 70, + 122,130, 53,124,149, 24,124,166, 7,122,178, 0,119,186, 0, + 117,192, 0,114,196, 0,113,198, 0,107,206, 0,103,212, 0, + 100,215, 0, 98,217, 0, 97,217, 0, 98,217, 0, 98,217, 0, + 100,215, 0,101,213, 0,102,212, 0,100,215, 0, 98,217, 0, + 98,217, 0, 99,216, 0,102,213, 0,106,208, 0,106,208, 0, + 106,207, 0,108,206, 0,109,204, 0,111,201, 0,114,196, 0, + 118,189, 0,120,182, 0,121,181, 0,121,180, 0,122,178, 0, + 122,177, 0,123,172, 2,124,162, 10,124,143, 31,118,117, 85, + 121,125, 63,123,141, 34,124,161, 11,123,170, 3,122,178, 0, + 120,182, 0,118,189, 0,116,192, 0,113,199, 0,108,205, 0, + 105,209, 0,102,212, 0,101,213, 0,102,212, 0,104,210, 0, + 107,206, 0,108,205, 0,109,204, 0,111,201, 0,115,194, 0, + 119,185, 0,123,170, 3,124,158, 13,123,141, 34,123,141, 34, + 122,135, 44,121,127, 58,124,158, 13,122,177, 0,119,187, 0, + 116,193, 0,114,196, 0,109,203, 0,106,208, 0,103,211, 0, + 102,212, 0,102,212, 0,102,213, 0,100,214, 0,100,214, 0, + 99,216, 0, 99,215, 0,101,214, 0,104,210, 0,107,207, 0, + 109,203, 0,114,197, 0,118,188, 0,120,183, 0,122,178, 0, + 123,170, 3,124,165, 8,124,162, 10,124,154, 18,122,132, 48, + 121,127, 58,123,137, 41,124,154, 18,124,161, 11,124,165, 8, + 124,165, 8,123,172, 2,122,177, 0,121,179, 0,122,178, 0, + 122,178, 0,120,182, 0,119,186, 0,118,189, 0,117,191, 0, + 116,192, 0,115,194, 0,115,194, 0,116,192, 0,114,196, 0, + 112,200, 0,111,202, 0,111,202, 0,112,199, 0,115,195, 0, + 118,189, 0,119,186, 0,120,184, 0,121,179, 0,123,174, 1, + 124,167, 6,124,162, 10,124,162, 10,124,166, 7,123,169, 4, + 123,171, 3,121,181, 0,119,186, 0,118,189, 0,117,191, 0, + 117,192, 0,115,194, 0,113,198, 0,111,201, 0,109,203, 0, + 108,205, 0,108,206, 0,108,205, 0,110,202, 0,110,202, 0, + 109,204, 0,108,205, 0,108,205, 0,109,204, 0,110,202, 0, + 112,200, 0,113,199, 0,114,197, 0,117,192, 0,117,190, 0, + 117,191, 0,116,193, 0,116,193, 0,117,191, 0,119,186, 0, + 119,186, 0,118,188, 0,118,189, 0,118,189, 0,118,188, 0, + 118,189, 0,118,189, 0,116,192, 0,114,196, 0,113,198, 0, + 112,199, 0,112,200, 0,111,201, 0,112,200, 0,112,200, 0, + 112,200, 0,113,198, 0,115,195, 0,115,195, 0,115,194, 0, + 116,193, 0,116,193, 0,117,192, 0,118,189, 0,120,182, 0, + 121,182, 0,120,183, 0,121,181, 0,123,174, 1,124,160, 12, + 121,127, 58, 69, 60,230, 30, 55,222,118,117, 85,124,149, 24, + 124,164, 9,123,170, 3,123,173, 1,120,182, 0,118,188, 0, + 117,191, 0,116,193, 0,115,194, 0,116,193, 0,117,190, 0, + 120,184, 0,120,184, 0,120,184, 0,117,191, 0,115,195, 0, + 114,197, 0,113,198, 0,114,197, 0,114,197, 0,114,196, 0, + 114,197, 0,112,200, 0,110,203, 0,108,206, 0,107,207, 0, + 107,207, 0,107,206, 0,108,205, 0,108,205, 0,104,210, 0, + 101,213, 0,101,214, 0,102,213, 0,104,210, 0,106,207, 0, + 109,203, 0,111,201, 0,113,198, 0,114,196, 0,117,191, 0, + 120,183, 0,123,169, 4,124,143, 31,119,119, 77, 99, 75,247, + 69, 60,230,114,104,197,122,132, 48,124,149, 24,124,158, 13, + 123,171, 3,121,179, 0,120,182, 0,120,182, 0,121,180, 0, + 122,178, 0,123,173, 1,124,165, 8,124,150, 22,122,132, 48, + 120,122, 70,121,125, 63,121,127, 58,124,154, 18,123,170, 3, + 121,181, 0,118,188, 0,116,193, 0,114,196, 0,109,203, 0, + 105,209, 0,102,212, 0,101,214, 0,100,214, 0, 98,217, 0, + 97,218, 0, 98,216, 0,101,213, 0,103,211, 0,101,213, 0, + 101,214, 0,101,214, 0,103,212, 0,106,208, 0,107,207, 0, + 107,206, 0,108,205, 0,111,202, 0,112,200, 0,114,196, 0, + 117,190, 0,120,184, 0,119,185, 0,120,184, 0,120,182, 0, + 121,179, 0,123,172, 2,124,162, 10,124,147, 26,120,122, 70, + 107, 89,252,117,110,109,124,147, 26,124,165, 8,122,176, 0, + 120,184, 0,118,189, 0,115,194, 0,112,199, 0,108,205, 0, + 105,209, 0,101,214, 0, 99,216, 0, 98,217, 0,100,215, 0, + 102,212, 0,105,209, 0,109,204, 0,110,202, 0,112,200, 0, + 115,195, 0,119,187, 0,123,174, 1,124,166, 7,124,154, 18, + 124,145, 29,123,141, 34,124,143, 31,123,168, 5,121,182, 0, + 117,190, 0,115,195, 0,111,201, 0,106,208, 0,102,213, 0, + 100,215, 0, 98,217, 0, 98,217, 0, 98,217, 0, 98,217, 0, + 97,218, 0, 95,220, 0, 95,219, 0, 97,217, 0,101,214, 0, + 104,210, 0,108,205, 0,112,199, 0,115,194, 0,118,189, 0, + 120,184, 0,122,178, 0,124,165, 8,124,160, 12,124,150, 22, + 122,130, 53,122,135, 44,124,145, 29,124,154, 18,124,162, 10, + 123,169, 4,122,176, 0,121,180, 0,120,183, 0,120,183, 0, + 121,182, 0,122,178, 0,120,184, 0,118,188, 0,116,192, 0, + 115,195, 0,114,197, 0,112,199, 0,112,200, 0,113,198, 0, + 115,195, 0,112,200, 0,109,203, 0,108,205, 0,108,205, 0, + 111,202, 0,114,196, 0,117,190, 0,120,183, 0,122,178, 0, + 123,174, 1,123,170, 3,124,167, 6,124,167, 6,123,169, 4, + 123,170, 3,122,178, 0,120,184, 0,118,188, 0,117,190, 0, + 117,191, 0,117,192, 0,115,194, 0,114,197, 0,112,200, 0, + 110,202, 0,110,203, 0,110,203, 0,110,202, 0,112,200, 0, + 112,200, 0,110,202, 0,109,203, 0,109,204, 0,109,203, 0, + 110,202, 0,111,201, 0,112,199, 0,114,197, 0,117,191, 0, + 120,183, 0,120,184, 0,118,188, 0,117,190, 0,118,189, 0, + 119,186, 0,120,182, 0,121,182, 0,120,182, 0,120,184, 0, + 119,185, 0,119,187, 0,118,189, 0,116,193, 0,114,197, 0, + 113,199, 0,112,199, 0,113,199, 0,113,198, 0,113,198, 0, + 113,199, 0,112,200, 0,112,199, 0,114,197, 0,115,195, 0, + 114,196, 0,114,196, 0,115,195, 0,116,193, 0,117,192, 0, + 119,186, 0,122,178, 0,123,174, 1,123,174, 1,123,170, 3, + 124,160, 12,122,135, 44,102, 80,250, 30, 20,155,105, 84,252, + 121,125, 63,124,145, 29,124,162, 10,122,177, 0,119,186, 0, + 118,189, 0,117,192, 0,116,192, 0,116,192, 0,118,189, 0, + 120,184, 0,121,179, 0,121,180, 0,120,184, 0,117,191, 0, + 115,194, 0,114,196, 0,114,196, 0,115,195, 0,115,194, 0, + 115,194, 0,115,195, 0,114,197, 0,112,200, 0,111,201, 0, + 111,202, 0,111,201, 0,113,199, 0,114,197, 0,112,200, 0, + 108,206, 0,106,208, 0,105,209, 0,106,208, 0,108,206, 0, + 110,203, 0,112,200, 0,114,197, 0,115,194, 0,117,190, 0, + 120,184, 0,123,173, 1,124,152, 20,122,130, 53,113,100,242, + 87, 65,237,109, 92,251,120,122, 70,123,139, 37,124,155, 16, + 123,170, 3,121,179, 0,119,185, 0,119,186, 0,119,186, 0, + 120,183, 0,121,179, 0,123,173, 1,124,166, 7,124,154, 18, + 122,135, 44,117,110,109,117,110,109,117,110,109,124,143, 31, + 124,165, 8,122,178, 0,119,186, 0,117,191, 0,115,194, 0, + 113,199, 0,109,204, 0,106,207, 0,102,212, 0, 99,215, 0, + 97,218, 0, 96,219, 0, 98,217, 0,101,214, 0,103,211, 0, + 103,211, 0,103,211, 0,105,209, 0,107,207, 0,107,206, 0, + 107,206, 0,108,205, 0,110,202, 0,113,198, 0,115,194, 0, + 118,189, 0,120,183, 0,119,186, 0,119,186, 0,120,184, 0, + 121,182, 0,122,177, 0,124,167, 6,124,150, 22,118,114, 96, + 94, 70,242, 69, 60,230,118,117, 85,124,150, 22,123,168, 5, + 121,180, 0,118,188, 0,115,194, 0,112,199, 0,109,204, 0, + 105,209, 0,101,213, 0, 98,216, 0, 97,218, 0, 97,218, 0, + 99,216, 0,101,213, 0,105,209, 0,109,204, 0,110,202, 0, + 112,199, 0,115,194, 0,118,188, 0,122,176, 0,123,171, 3, + 124,164, 9,124,158, 13,124,154, 18,124,160, 12,122,176, 0, + 119,186, 0,117,192, 0,113,198, 0,107,206, 0,102,213, 0, + 98,217, 0, 96,219, 0, 95,220, 0, 95,220, 0, 95,219, 0, + 95,219, 0, 94,220, 0, 93,221, 0, 94,221, 0, 95,219, 0, + 99,216, 0,103,212, 0,107,207, 0,111,202, 0,114,197, 0, + 116,192, 0,118,188, 0,121,181, 0,123,168, 5,124,152, 20, + 123,141, 34,121,125, 63,123,137, 41,124,152, 20,124,165, 8, + 123,172, 2,122,178, 0,120,182, 0,120,184, 0,119,185, 0, + 120,184, 0,121,181, 0,122,178, 0,120,184, 0,118,189, 0, + 116,193, 0,114,197, 0,112,199, 0,111,202, 0,110,202, 0, + 111,201, 0,113,198, 0,113,198, 0,109,204, 0,107,207, 0, + 106,207, 0,108,205, 0,111,201, 0,115,194, 0,119,187, 0, + 122,176, 0,123,171, 3,123,168, 5,124,167, 6,124,167, 6, + 123,168, 5,122,175, 0,120,182, 0,119,186, 0,118,188, 0, + 118,188, 0,118,188, 0,118,189, 0,117,192, 0,115,194, 0, + 114,197, 0,113,199, 0,112,199, 0,113,199, 0,114,197, 0, + 115,194, 0,113,198, 0,112,200, 0,111,202, 0,111,202, 0, + 111,202, 0,111,201, 0,112,199, 0,113,198, 0,115,195, 0, + 118,189, 0,121,180, 0,123,174, 1,121,182, 0,119,186, 0, + 119,187, 0,119,185, 0,121,182, 0,121,181, 0,121,182, 0, + 120,182, 0,120,184, 0,120,184, 0,118,188, 0,116,192, 0, + 114,196, 0,113,198, 0,113,198, 0,114,197, 0,115,194, 0, + 115,194, 0,115,195, 0,113,198, 0,113,199, 0,114,197, 0, + 115,194, 0,114,197, 0,113,198, 0,113,198, 0,114,196, 0, + 116,193, 0,118,189, 0,120,182, 0,123,172, 2,124,166, 7, + 124,165, 8,124,158, 13,123,141, 34,114,104,197, 30, 31,180, + 87, 65,237,119,119, 77,124,152, 20,123,170, 3,121,182, 0, + 118,188, 0,117,191, 0,117,191, 0,117,190, 0,118,188, 0, + 120,184, 0,122,176, 0,123,172, 2,122,178, 0,119,185, 0, + 118,189, 0,117,192, 0,116,192, 0,117,192, 0,117,191, 0, + 117,190, 0,117,190, 0,117,191, 0,116,192, 0,115,194, 0, + 115,194, 0,116,193, 0,117,191, 0,118,188, 0,119,186, 0, + 115,194, 0,112,200, 0,110,202, 0,110,202, 0,111,201, 0, + 112,199, 0,114,197, 0,115,194, 0,117,191, 0,118,188, 0, + 120,183, 0,123,173, 1,124,157, 15,121,127, 58,115,107,129, + 109, 92,251,111, 96,248,119,119, 77,122,135, 44,124,154, 18, + 123,168, 5,122,178, 0,120,184, 0,118,188, 0,118,188, 0, + 119,186, 0,120,183, 0,121,179, 0,123,174, 1,124,165, 8, + 124,150, 22,121,127, 58,105, 84,252,102, 80,250,113,100,242, + 123,137, 41,124,160, 12,123,174, 1,120,184, 0,118,189, 0, + 116,193, 0,113,198, 0,110,202, 0,106,208, 0,102,213, 0, + 98,216, 0, 96,219, 0, 96,219, 0, 98,217, 0,102,212, 0, + 105,209, 0,106,208, 0,107,207, 0,108,205, 0,108,206, 0, + 108,206, 0,108,205, 0,109,203, 0,112,199, 0,116,193, 0, + 118,188, 0,121,180, 0,120,182, 0,119,186, 0,119,185, 0, + 121,182, 0,122,176, 0,123,168, 5,124,154, 18,121,127, 58, + 102, 80,250, 30, 37,192,102, 80,250,121,127, 58,124,154, 18, + 123,169, 4,121,181, 0,118,189, 0,114,196, 0,111,202, 0, + 107,207, 0,103,211, 0,100,215, 0, 98,217, 0, 97,218, 0, + 98,217, 0,100,215, 0,103,212, 0,106,208, 0,109,203, 0, + 111,201, 0,113,198, 0,116,193, 0,119,187, 0,122,177, 0, + 123,172, 2,123,168, 5,124,164, 9,124,160, 12,123,171, 3, + 120,182, 0,118,189, 0,116,193, 0,111,202, 0,104,210, 0, + 99,216, 0, 95,219, 0, 94,221, 0, 94,221, 0, 94,220, 0, + 95,220, 0, 95,220, 0, 94,221, 0, 93,222, 0, 94,221, 0, + 95,219, 0, 98,216, 0,102,212, 0,106,207, 0,110,202, 0, + 113,198, 0,116,193, 0,118,189, 0,121,182, 0,123,169, 4, + 124,147, 26,121,125, 63,118,117, 85,122,132, 48,124,155, 16, + 123,169, 4,122,178, 0,120,184, 0,119,186, 0,119,186, 0, + 120,184, 0,121,182, 0,122,177, 0,122,178, 0,120,184, 0, + 118,189, 0,116,192, 0,115,195, 0,113,198, 0,111,201, 0, + 111,202, 0,111,201, 0,113,198, 0,114,196, 0,110,202, 0, + 107,207, 0,106,208, 0,107,207, 0,110,202, 0,114,197, 0, + 118,189, 0,122,178, 0,124,164, 9,124,161, 11,124,161, 11, + 124,161, 11,124,167, 6,122,177, 0,120,182, 0,120,184, 0, + 119,185, 0,120,184, 0,120,184, 0,119,185, 0,118,188, 0, + 117,191, 0,116,193, 0,115,194, 0,115,194, 0,116,192, 0, + 117,190, 0,117,191, 0,115,194, 0,114,197, 0,113,198, 0, + 113,198, 0,114,197, 0,114,196, 0,115,195, 0,115,194, 0, + 117,192, 0,119,185, 0,122,175, 0,124,167, 6,123,172, 2, + 121,179, 0,120,182, 0,121,181, 0,122,178, 0,122,178, 0, + 121,179, 0,121,181, 0,121,182, 0,121,181, 0,120,184, 0, + 117,191, 0,115,194, 0,114,196, 0,114,196, 0,115,194, 0, + 117,191, 0,119,187, 0,117,190, 0,116,193, 0,114,196, 0, + 114,196, 0,116,193, 0,114,196, 0,113,198, 0,113,199, 0, + 113,198, 0,115,194, 0,118,189, 0,120,184, 0,122,175, 0, + 124,164, 9,124,158, 13,124,154, 18,124,143, 31,118,117, 85, + 99, 75,247,109, 92,251,123,139, 37,124,164, 9,122,177, 0, + 120,184, 0,118,188, 0,118,189, 0,118,189, 0,119,186, 0, + 121,182, 0,122,175, 0,124,165, 8,123,169, 4,122,178, 0, + 120,184, 0,118,188, 0,118,188, 0,119,187, 0,119,185, 0, + 120,183, 0,121,182, 0,121,182, 0,120,183, 0,120,184, 0, + 120,184, 0,120,183, 0,121,180, 0,122,175, 0,123,170, 3, + 122,177, 0,119,186, 0,117,191, 0,116,193, 0,116,193, 0, + 117,191, 0,118,189, 0,119,187, 0,119,185, 0,120,182, 0, + 122,178, 0,123,171, 3,124,157, 15,121,125, 63,111, 96,248, + 114,104,197,115,107,129,122,130, 53,123,137, 41,124,150, 22, + 124,166, 7,122,177, 0,120,183, 0,119,187, 0,118,188, 0, + 118,188, 0,119,185, 0,120,183, 0,121,182, 0,122,177, 0, + 124,167, 6,124,150, 22,118,117, 85, 30, 55,222, 30, 49,213, + 115,107,129,124,145, 29,124,165, 8,122,175, 0,121,181, 0, + 118,188, 0,117,192, 0,114,197, 0,110,202, 0,106,208, 0, + 102,213, 0, 98,216, 0, 97,218, 0, 97,217, 0,100,214, 0, + 104,210, 0,108,205, 0,109,204, 0,110,203, 0,109,204, 0, + 108,205, 0,108,205, 0,109,204, 0,111,201, 0,115,195, 0, + 119,186, 0,122,178, 0,123,173, 1,121,179, 0,120,182, 0, + 121,180, 0,123,174, 1,124,165, 8,124,149, 24,121,125, 63, + 105, 84,252, 99, 75,247,114,104,197,120,122, 70,122,132, 48, + 124,154, 18,123,168, 5,122,178, 0,119,187, 0,115,194, 0, + 111,201, 0,107,207, 0,103,211, 0,101,214, 0, 99,216, 0, + 99,216, 0,100,215, 0,102,212, 0,105,209, 0,107,206, 0, + 110,203, 0,112,200, 0,114,196, 0,117,191, 0,120,184, 0, + 123,173, 1,123,168, 5,124,166, 7,124,164, 9,124,165, 8, + 122,178, 0,119,186, 0,117,192, 0,115,195, 0,109,204, 0, + 102,212, 0, 97,217, 0, 95,220, 0, 94,221, 0, 94,220, 0, + 95,219, 0, 97,218, 0, 97,218, 0, 96,219, 0, 95,220, 0, + 95,220, 0, 97,218, 0,100,215, 0,103,211, 0,107,207, 0, + 109,203, 0,113,198, 0,116,193, 0,118,188, 0,121,181, 0, + 123,168, 5,124,145, 29,114,104,197,111, 96,248,118,117, 85, + 124,152, 20,123,171, 3,121,181, 0,119,186, 0,119,186, 0, + 119,185, 0,121,181, 0,122,176, 0,123,171, 3,122,178, 0, + 120,182, 0,119,186, 0,118,188, 0,117,190, 0,116,192, 0, + 114,196, 0,113,198, 0,113,198, 0,114,196, 0,116,193, 0, + 112,199, 0,109,204, 0,108,206, 0,108,205, 0,111,201, 0, + 114,196, 0,118,189, 0,122,178, 0,124,158, 13,124,147, 26, + 124,145, 29,124,147, 26,124,164, 9,123,173, 1,122,178, 0, + 121,180, 0,121,180, 0,122,178, 0,121,181, 0,120,184, 0, + 120,183, 0,119,186, 0,118,188, 0,118,188, 0,119,187, 0, + 120,184, 0,120,182, 0,119,186, 0,118,189, 0,117,191, 0, + 117,192, 0,117,191, 0,117,190, 0,118,189, 0,118,188, 0, + 119,187, 0,120,184, 0,122,178, 0,124,167, 6,124,157, 15, + 124,157, 15,123,168, 5,123,173, 1,123,172, 2,123,170, 3, + 123,171, 3,123,174, 1,122,177, 0,122,178, 0,122,178, 0, + 122,178, 0,119,186, 0,117,191, 0,116,193, 0,116,192, 0, + 118,189, 0,119,186, 0,121,180, 0,120,182, 0,118,188, 0, + 116,192, 0,116,193, 0,117,192, 0,116,193, 0,114,196, 0, + 114,197, 0,114,196, 0,116,193, 0,119,186, 0,121,182, 0, + 122,175, 0,124,166, 7,124,150, 22,124,147, 26,123,139, 37, + 118,117, 85,111, 96,248,118,117, 85,124,154, 18,123,171, 3, + 121,181, 0,119,186, 0,118,188, 0,118,188, 0,119,185, 0, + 121,181, 0,123,174, 1,123,173, 1,123,171, 3,123,171, 3, + 122,178, 0,121,182, 0,120,183, 0,121,182, 0,122,178, 0, + 123,173, 1,123,169, 4,124,167, 6,124,167, 6,123,168, 5, + 123,170, 3,123,168, 5,124,165, 8,124,157, 15,124,147, 26, + 123,141, 34,124,162, 10,123,174, 1,121,179, 0,121,180, 0, + 122,178, 0,121,179, 0,122,177, 0,123,172, 2,123,171, 3, + 123,169, 4,124,165, 8,124,152, 20,121,125, 63,105, 84,252, + 113,100,242,115,107,129,122,132, 48,124,145, 29,124,147, 26, + 124,160, 12,123,172, 2,121,182, 0,119,186, 0,118,188, 0, + 118,188, 0,119,186, 0,120,184, 0,119,185, 0,120,184, 0, + 122,178, 0,123,169, 4,124,152, 20,119,119, 77, 69, 60,230, + 69, 60,230,121,125, 63,124,155, 16,123,170, 3,122,178, 0, + 120,183, 0,120,184, 0,118,189, 0,115,195, 0,111,202, 0, + 107,207, 0,103,212, 0,100,214, 0, 99,215, 0,100,214, 0, + 103,211, 0,108,205, 0,111,201, 0,111,201, 0,110,203, 0, + 109,204, 0,109,204, 0,110,202, 0,111,201, 0,113,198, 0, + 117,190, 0,122,178, 0,124,165, 8,124,167, 6,123,172, 2, + 123,173, 1,123,169, 4,124,158, 13,123,139, 37,115,107,129, + 113,100,242,118,117, 85,122,135, 44,124,147, 26,124,154, 18, + 124,158, 13,124,158, 13,124,164, 9,123,173, 1,120,183, 0, + 117,191, 0,113,198, 0,109,204, 0,105,209, 0,103,212, 0, + 101,213, 0,101,213, 0,103,212, 0,105,209, 0,106,208, 0, + 107,206, 0,110,202, 0,113,198, 0,116,193, 0,119,186, 0, + 122,178, 0,124,166, 7,124,155, 16,124,155, 16,124,155, 16, + 123,168, 5,121,182, 0,118,189, 0,115,194, 0,114,197, 0, + 108,205, 0,102,212, 0, 98,217, 0, 96,219, 0, 96,219, 0, + 97,218, 0, 98,217, 0,100,215, 0,100,215, 0, 99,216, 0, + 98,217, 0, 98,217, 0, 99,215, 0,102,213, 0,105,209, 0, + 106,207, 0,108,205, 0,112,199, 0,116,193, 0,118,188, 0, + 121,179, 0,124,166, 7,124,143, 31,113,100,242, 30, 55,222, + 109, 92,251,124,145, 29,123,169, 4,121,180, 0,119,185, 0, + 119,186, 0,120,182, 0,122,176, 0,124,167, 6,123,170, 3, + 123,174, 1,121,179, 0,120,182, 0,120,183, 0,121,182, 0, + 120,182, 0,119,186, 0,118,189, 0,117,192, 0,116,192, 0, + 117,191, 0,115,194, 0,113,199, 0,111,201, 0,112,200, 0, + 114,197, 0,116,193, 0,119,186, 0,122,176, 0,124,158, 13, + 120,122, 70,118,117, 85,121,125, 63,124,152, 20,124,165, 8, + 123,170, 3,123,172, 2,123,171, 3,123,172, 2,122,178, 0, + 121,180, 0,122,178, 0,122,178, 0,121,181, 0,121,181, 0, + 122,178, 0,122,175, 0,123,172, 2,122,178, 0,121,182, 0, + 120,182, 0,120,182, 0,121,181, 0,122,178, 0,122,177, 0, + 122,175, 0,122,175, 0,123,173, 1,124,166, 7,124,152, 20, + 123,139, 37,122,130, 53,124,145, 29,124,154, 18,124,154, 18, + 124,152, 20,124,158, 13,124,165, 8,123,170, 3,123,173, 1, + 123,174, 1,123,173, 1,121,180, 0,119,186, 0,118,188, 0, + 118,188, 0,120,184, 0,121,180, 0,122,177, 0,122,177, 0, + 121,181, 0,118,188, 0,117,191, 0,117,191, 0,118,189, 0, + 117,191, 0,117,192, 0,117,192, 0,118,188, 0,120,182, 0, + 122,175, 0,123,171, 3,124,164, 9,124,150, 22,122,135, 44, + 121,125, 63,114,104,197,114,104,197,122,130, 53,124,162, 10, + 122,177, 0,120,184, 0,119,186, 0,119,186, 0,120,184, 0, + 121,181, 0,122,178, 0,121,181, 0,121,180, 0,122,177, 0, + 123,170, 3,123,173, 1,122,175, 0,122,175, 0,123,169, 4, + 124,161, 11,124,160, 12,124,154, 18,123,139, 37,122,135, 44, + 123,139, 37,123,141, 34,123,137, 41,121,127, 58,117,110,109, + 107, 89,252,113,100,242,122,132, 48,124,150, 22,124,157, 15, + 124,157, 15,124,167, 6,123,171, 3,123,169, 4,124,161, 11, + 124,147, 26,124,147, 26,123,141, 34,119,119, 77,115,107,129, + 107, 89,252,113,100,242,121,125, 63,124,147, 26,124,152, 20, + 124,149, 24,124,165, 8,122,177, 0,120,184, 0,118,188, 0, + 118,188, 0,119,186, 0,120,182, 0,119,186, 0,119,186, 0, + 120,184, 0,121,179, 0,123,169, 4,124,150, 22,118,117, 85, + 30, 55,222,107, 89,252,123,137, 41,124,160, 12,123,172, 2, + 121,179, 0,120,183, 0,119,185, 0,119,186, 0,116,192, 0, + 112,199, 0,108,205, 0,105,209, 0,103,212, 0,102,212, 0, + 104,210, 0,108,206, 0,112,199, 0,113,199, 0,111,202, 0, + 110,203, 0,110,203, 0,111,202, 0,112,200, 0,114,197, 0, + 116,193, 0,120,184, 0,123,169, 4,124,149, 24,124,154, 18, + 124,158, 13,124,157, 15,124,147, 26,120,122, 70,114,104,197, + 117,110,109,123,137, 41,124,154, 18,124,162, 10,124,166, 7, + 123,169, 4,123,171, 3,123,170, 3,122,176, 0,122,178, 0, + 121,182, 0,119,185, 0,116,193, 0,112,200, 0,108,205, 0, + 106,208, 0,105,209, 0,105,209, 0,106,208, 0,107,207, 0, + 106,208, 0,107,206, 0,111,202, 0,114,196, 0,118,188, 0, + 121,179, 0,123,168, 5,124,150, 22,121,127, 58,122,132, 48, + 123,141, 34,123,168, 5,120,182, 0,117,191, 0,114,196, 0, + 113,198, 0,109,203, 0,103,211, 0,100,215, 0, 98,216, 0, + 99,216, 0,100,214, 0,102,213, 0,102,213, 0,102,212, 0, + 103,212, 0,101,213, 0,101,214, 0,102,212, 0,104,210, 0, + 106,207, 0,107,207, 0,108,205, 0,111,201, 0,115,194, 0, + 119,187, 0,122,178, 0,124,164, 9,123,139, 37,111, 96,248, + 30, 31,180, 30, 43,203,122,130, 53,124,164, 9,122,178, 0, + 120,183, 0,120,183, 0,122,178, 0,123,169, 4,124,158, 13, + 124,165, 8,122,175, 0,121,180, 0,121,182, 0,121,181, 0, + 122,177, 0,123,170, 3,123,170, 3,122,177, 0,120,182, 0, + 119,186, 0,118,188, 0,118,188, 0,117,191, 0,116,193, 0, + 116,193, 0,117,191, 0,119,187, 0,120,182, 0,123,173, 1, + 124,157, 15,121,125, 63, 87, 65,237,102, 80,250,121,125, 63, + 124,147, 26,124,155, 16,124,160, 12,124,160, 12,124,166, 7, + 123,171, 3,123,171, 3,124,166, 7,123,170, 3,123,173, 1, + 123,172, 2,123,169, 4,124,162, 10,124,154, 18,124,162, 10, + 124,167, 6,124,167, 6,124,166, 7,124,162, 10,124,158, 13, + 124,155, 16,124,152, 20,124,154, 18,124,154, 18,124,149, 24, + 123,137, 41,118,114, 96,109, 92,251,111, 96,248,115,107,129, + 115,107,129,117,110,109,121,125, 63,124,143, 31,124,157, 15, + 124,165, 8,123,168, 5,123,168, 5,123,170, 3,121,179, 0, + 120,182, 0,120,182, 0,121,179, 0,122,177, 0,122,177, 0, + 122,175, 0,122,175, 0,120,182, 0,118,188, 0,117,190, 0, + 118,189, 0,119,186, 0,120,184, 0,120,184, 0,121,181, 0, + 122,175, 0,124,167, 6,124,162, 10,124,157, 15,124,145, 29, + 121,125, 63,111, 96,248, 94, 70,242,107, 89,252,123,141, 34, + 124,167, 6,121,180, 0,119,186, 0,119,187, 0,119,186, 0, + 120,182, 0,120,182, 0,119,186, 0,118,188, 0,119,186, 0, + 121,181, 0,123,172, 2,124,162, 10,124,162, 10,124,160, 12, + 124,154, 18,124,157, 15,124,157, 15,124,149, 24,122,130, 53, + 109, 92,251,105, 84,252,114,104,197,117,110,109,114,104,197, + 105, 84,252, 30, 55,222, 30, 43,203, 87, 65,237,113,100,242, + 117,110,109,123,139, 37,124,157, 15,124,164, 9,124,162, 10, + 124,152, 20,121,127, 58,117,110,109,118,117, 85,119,119, 77, + 118,114, 96,113,100,242,113,100,242,122,132, 48,124,147, 26, + 124,149, 24,124,152, 20,123,168, 5,121,179, 0,119,185, 0, + 118,188, 0,119,187, 0,120,184, 0,121,182, 0,119,185, 0, + 119,186, 0,120,184, 0,122,178, 0,124,167, 6,124,145, 29, + 115,107,129, 30, 37,192,111, 96,248,123,139, 37,124,161, 11, + 123,172, 2,121,179, 0,120,182, 0,120,184, 0,119,185, 0, + 118,188, 0,115,195, 0,111,202, 0,108,206, 0,106,208, 0, + 106,208, 0,108,205, 0,112,199, 0,114,197, 0,111,201, 0, + 110,203, 0,110,203, 0,111,202, 0,112,199, 0,114,196, 0, + 116,192, 0,119,187, 0,122,177, 0,124,160, 12,124,150, 22, + 123,137, 41,122,130, 53,120,122, 70,109, 92,251, 99, 75,247, + 114,104,197,123,141, 34,124,160, 12,123,168, 5,123,173, 1, + 122,175, 0,122,177, 0,122,178, 0,120,184, 0,117,190, 0, + 116,192, 0,116,192, 0,118,189, 0,118,188, 0,115,194, 0, + 112,200, 0,109,203, 0,108,206, 0,107,207, 0,108,206, 0, + 107,207, 0,107,207, 0,108,205, 0,112,200, 0,114,196, 0, + 117,191, 0,120,182, 0,124,166, 7,122,132, 48,109, 92,251, + 102, 80,250,121,125, 63,124,162, 10,121,181, 0,117,191, 0, + 114,196, 0,112,200, 0,111,201, 0,106,207, 0,103,211, 0, + 102,212, 0,103,212, 0,103,211, 0,103,212, 0,103,212, 0, + 104,210, 0,107,207, 0,105,209, 0,104,210, 0,105,209, 0, + 106,208, 0,108,206, 0,107,206, 0,108,205, 0,111,201, 0, + 115,195, 0,118,189, 0,120,183, 0,123,173, 1,124,158, 13, + 121,127, 58, 69, 60,230, 30, 2,128,115,107,129,124,154, 18, + 123,172, 2,121,179, 0,121,179, 0,123,174, 1,124,164, 9, + 124,147, 26,124,162, 10,123,172, 2,122,177, 0,122,177, 0, + 123,174, 1,123,168, 5,124,158, 13,124,143, 31,124,158, 13, + 123,169, 4,122,178, 0,120,182, 0,119,185, 0,119,186, 0, + 119,185, 0,120,183, 0,121,181, 0,121,179, 0,122,175, 0, + 124,167, 6,124,155, 16,122,132, 48,105, 84,252, 30, 2,128, + 99, 75,247,118,114, 96,122,132, 48,123,141, 34,124,143, 31, + 124,147, 26,124,152, 20,124,149, 24,124,155, 16,124,161, 11, + 124,164, 9,124,162, 10,124,157, 15,124,147, 26,123,139, 37, + 121,125, 63,122,135, 44,123,137, 41,123,137, 41,124,143, 31, + 124,147, 26,124,145, 29,123,139, 37,120,122, 70,121,127, 58, + 121,127, 58,119,119, 77,114,104,197,102, 80,250, 30, 43,203, + 30, 10,132, 30, 2,128, 30, 10,132, 30, 49,213,109, 92,251, + 121,127, 58,124,145, 29,124,155, 16,124,160, 12,124,158, 13, + 123,171, 3,122,177, 0,122,178, 0,122,176, 0,123,174, 1, + 122,175, 0,123,172, 2,124,164, 9,122,178, 0,119,186, 0, + 118,189, 0,117,190, 0,118,188, 0,120,184, 0,122,178, 0, + 123,171, 3,124,165, 8,124,160, 12,124,150, 22,124,145, 29, + 122,135, 44,118,117, 85, 99, 75,247, 30, 2,128,109, 92,251, + 124,147, 26,123,171, 3,120,183, 0,118,188, 0,118,189, 0, + 119,187, 0,120,184, 0,118,189, 0,117,192, 0,117,192, 0, + 118,189, 0,120,183, 0,123,172, 2,124,155, 16,123,137, 41, + 124,143, 31,124,150, 22,124,152, 20,124,149, 24,123,137, 41, + 120,122, 70,113,100,242, 87, 65,237,107, 89,252,114,104,197, + 118,117, 85,118,117, 85,114,104,197, 99, 75,247, 30, 49,213, + 30, 2,128, 99, 75,247,121,125, 63,124,147, 26,124,157, 15, + 124,155, 16,124,145, 29,121,127, 58,115,107,129,121,127, 58, + 122,132, 48,122,132, 48,121,127, 58,119,119, 77,121,125, 63, + 122,135, 44,122,135, 44,124,154, 18,123,169, 4,121,179, 0, + 119,185, 0,119,187, 0,119,186, 0,120,182, 0,122,178, 0, + 121,182, 0,120,182, 0,121,179, 0,123,172, 2,124,158, 13, + 122,130, 53, 99, 75,247, 30, 2,128,105, 84,252,122,135, 44, + 124,157, 15,123,169, 4,122,176, 0,121,179, 0,121,181, 0, + 120,182, 0,120,184, 0,117,190, 0,114,197, 0,111,202, 0, + 109,203, 0,110,203, 0,112,200, 0,116,193, 0,112,199, 0, + 110,202, 0,109,203, 0,110,203, 0,112,200, 0,114,196, 0, + 116,193, 0,118,188, 0,121,182, 0,123,173, 1,124,165, 8, + 124,154, 18,122,135, 44,115,107,129, 69, 60,230, 30, 2,128, + 87, 65,237,120,122, 70,124,150, 22,124,165, 8,123,172, 2, + 122,175, 0,122,177, 0,122,178, 0,118,188, 0,115,194, 0, + 112,200, 0,110,202, 0,110,202, 0,112,200, 0,114,196, 0, + 117,190, 0,114,196, 0,111,201, 0,109,203, 0,108,205, 0, + 108,205, 0,108,205, 0,108,205, 0,110,202, 0,111,202, 0, + 112,199, 0,115,195, 0,118,188, 0,122,176, 0,124,152, 20, + 111, 96,248, 30, 2,128,113,100,242,124,152, 20,122,177, 0, + 118,189, 0,114,196, 0,112,200, 0,111,202, 0,110,202, 0, + 107,206, 0,106,207, 0,106,207, 0,105,209, 0,105,209, 0, + 105,209, 0,107,207, 0,109,203, 0,108,206, 0,107,207, 0, + 106,207, 0,107,207, 0,108,205, 0,110,203, 0,110,202, 0, + 113,199, 0,114,196, 0,117,191, 0,120,184, 0,122,178, 0, + 124,167, 6,124,147, 26,113,100,242, 30, 31,180,102, 80,250, + 123,141, 34,124,165, 8,123,172, 2,123,173, 1,124,167, 6, + 124,154, 18,124,143, 31,124,155, 16,124,166, 7,123,170, 3, + 123,170, 3,124,167, 6,124,164, 9,124,161, 11,124,149, 24, + 123,141, 34,124,152, 20,124,167, 6,122,176, 0,121,182, 0, + 119,185, 0,119,186, 0,120,184, 0,121,179, 0,123,173, 1, + 122,175, 0,123,174, 1,123,169, 4,124,157, 15,122,132, 48, + 102, 80,250, 30, 55,222,105, 84,252,111, 96,248,115,107,129, + 118,117, 85,119,119, 77,120,122, 70,122,130, 53,123,139, 37, + 124,147, 26,124,152, 20,124,154, 18,124,158, 13,124,158, 13, + 124,152, 20,123,141, 34,122,130, 53,120,122, 70,120,122, 70, + 122,132, 48,123,137, 41,123,139, 37,122,132, 48,119,119, 77, + 111, 96,248,109, 92,251,109, 92,251,105, 84,252,107, 89,252, + 107, 89,252,107, 89,252,111, 96,248,107, 89,252, 30, 55,222, + 99, 75,247,115,107,129,119,119, 77,123,139, 37,124,147, 26, + 124,150, 22,124,162, 10,123,172, 2,122,176, 0,122,177, 0, + 122,175, 0,123,173, 1,123,171, 3,123,171, 3,123,174, 1, + 120,182, 0,119,187, 0,118,188, 0,118,188, 0,120,184, 0, + 121,181, 0,122,176, 0,123,170, 3,124,157, 15,124,147, 26, + 124,143, 31,122,135, 44,120,122, 70,113,100,242,102, 80,250, + 113,100,242,124,147, 26,123,171, 3,120,183, 0,118,189, 0, + 117,190, 0,118,189, 0,117,191, 0,115,194, 0,114,197, 0, + 114,196, 0,117,191, 0,120,184, 0,123,172, 2,124,164, 9, + 124,157, 15,124,152, 20,124,152, 20,124,152, 20,124,152, 20, + 124,147, 26,123,137, 41,119,119, 77,109, 92,251,115,107,129, + 122,130, 53,124,143, 31,124,145, 29,123,141, 34,122,130, 53, + 118,114, 96,107, 89,252,102, 80,250,118,117, 85,123,141, 34, + 124,152, 20,124,157, 15,124,154, 18,124,147, 26,122,135, 44, + 122,132, 48,123,141, 34,124,145, 29,124,145, 29,124,143, 31, + 123,141, 34,124,147, 26,124,157, 15,123,168, 5,122,176, 0, + 121,179, 0,120,184, 0,119,186, 0,119,186, 0,120,182, 0, + 122,178, 0,123,174, 1,122,176, 0,123,172, 2,124,164, 9, + 124,147, 26,122,135, 44,117,110,109, 94, 70,242,114,104,197, + 122,135, 44,124,152, 20,124,165, 8,123,174, 1,121,181, 0, + 119,186, 0,118,189, 0,117,191, 0,118,189, 0,117,191, 0, + 114,196, 0,113,199, 0,113,199, 0,114,196, 0,114,196, 0, + 111,202, 0,109,204, 0,108,205, 0,110,203, 0,112,200, 0, + 113,198, 0,114,197, 0,116,192, 0,119,186, 0,121,180, 0, + 123,172, 2,124,161, 11,124,145, 29,118,117, 85,107, 89,252, + 102, 80,250,118,117, 85,123,141, 34,124,152, 20,124,162, 10, + 123,170, 3,123,174, 1,122,177, 0,119,186, 0,115,194, 0, + 111,201, 0,108,206, 0,106,208, 0,105,209, 0,106,207, 0, + 109,204, 0,112,200, 0,115,194, 0,114,197, 0,111,201, 0, + 109,204, 0,108,205, 0,107,206, 0,108,206, 0,108,205, 0, + 109,204, 0,110,202, 0,113,199, 0,117,192, 0,121,181, 0, + 124,161, 11,120,122, 70, 94, 70,242,102, 80,250,123,139, 37, + 123,170, 3,119,186, 0,115,194, 0,112,199, 0,111,202, 0, + 110,202, 0,109,203, 0,108,205, 0,108,206, 0,107,206, 0, + 108,206, 0,108,206, 0,107,207, 0,105,209, 0,103,211, 0, + 104,210, 0,106,207, 0,107,206, 0,108,205, 0,109,203, 0, + 110,202, 0,111,202, 0,112,200, 0,115,194, 0,119,186, 0, + 122,178, 0,123,169, 4,124,154, 18,119,119, 77, 99, 75,247, + 99, 75,247,120,122, 70,124,149, 24,124,160, 12,124,160, 12, + 124,152, 20,124,145, 29,124,145, 29,124,149, 24,124,160, 12, + 124,165, 8,124,166, 7,124,164, 9,124,165, 8,124,161, 11, + 124,150, 22,119,119, 77,121,125, 63,124,150, 22,124,167, 6, + 122,178, 0,120,183, 0,119,185, 0,118,189, 0,118,189, 0, + 119,186, 0,122,178, 0,121,181, 0,121,179, 0,123,172, 2, + 124,158, 13,122,132, 48,111, 96,248,107, 89,252,113,100,242, + 113,100,242,109, 92,251,102, 80,250, 94, 70,242,105, 84,252, + 114,104,197,119,119, 77,124,145, 29,124,158, 13,124,165, 8, + 124,165, 8,124,160, 12,124,150, 22,123,141, 34,122,132, 48, + 121,127, 58,119,119, 77,121,127, 58,122,132, 48,122,130, 53, + 120,122, 70,114,104,197,111, 96,248,109, 92,251,113,100,242, + 118,114, 96,120,122, 70,121,127, 58,122,132, 48,121,127, 58, + 114,104,197,114,104,197,119,119, 77,122,132, 48,123,137, 41, + 123,139, 37,124,145, 29,124,150, 22,124,167, 6,122,175, 0, + 121,179, 0,121,181, 0,121,181, 0,121,180, 0,121,180, 0, + 121,181, 0,121,181, 0,121,182, 0,120,184, 0,120,184, 0, + 120,183, 0,121,181, 0,121,179, 0,122,175, 0,124,164, 9, + 124,145, 29,124,145, 29,124,145, 29,124,143, 31,122,132, 48, + 121,125, 63,122,135, 44,123,141, 34,124,167, 6,121,181, 0, + 119,187, 0,118,189, 0,118,189, 0,114,196, 0,112,200, 0, + 112,200, 0,113,199, 0,115,194, 0,119,186, 0,122,176, 0, + 122,175, 0,123,170, 3,124,165, 8,124,162, 10,124,161, 11, + 124,160, 12,124,155, 16,124,149, 24,123,139, 37,123,141, 34, + 123,139, 37,124,143, 31,124,155, 16,124,160, 12,124,160, 12, + 124,155, 16,124,145, 29,122,130, 53,118,117, 85,120,122, 70, + 124,143, 31,124,155, 16,124,161, 11,124,162, 10,124,160, 12, + 124,154, 18,124,149, 24,124,147, 26,124,145, 29,124,149, 24, + 124,150, 22,124,154, 18,124,158, 13,124,165, 8,123,174, 1, + 121,180, 0,120,182, 0,121,182, 0,120,184, 0,119,185, 0, + 120,183, 0,121,179, 0,122,175, 0,123,170, 3,124,167, 6, + 124,164, 9,124,158, 13,124,152, 20,123,137, 41,121,125, 63, + 121,125, 63,124,149, 24,124,164, 9,123,173, 1,121,181, 0, + 119,186, 0,117,191, 0,115,195, 0,114,197, 0,115,195, 0, + 116,193, 0,117,192, 0,115,195, 0,114,197, 0,114,197, 0, + 113,199, 0,109,203, 0,107,206, 0,107,207, 0,108,205, 0, + 111,201, 0,111,201, 0,112,200, 0,114,197, 0,117,192, 0, + 119,186, 0,121,180, 0,123,171, 3,124,157, 15,124,145, 29, + 123,139, 37,122,132, 48,123,141, 34,124,155, 16,124,162, 10, + 124,164, 9,124,167, 6,123,174, 1,121,181, 0,117,191, 0, + 113,198, 0,109,204, 0,105,209, 0,102,212, 0,101,214, 0, + 102,213, 0,103,211, 0,106,208, 0,109,203, 0,113,198, 0, + 114,196, 0,112,200, 0,110,203, 0,108,205, 0,107,207, 0, + 107,207, 0,107,206, 0,109,204, 0,112,200, 0,116,193, 0, + 120,183, 0,124,165, 8,122,130, 53,118,114, 96,115,107,129, + 122,132, 48,124,161, 11,121,180, 0,117,191, 0,114,197, 0, + 112,200, 0,111,202, 0,110,202, 0,109,203, 0,109,204, 0, + 110,203, 0,107,206, 0,105,209, 0,104,210, 0,100,215, 0, + 98,217, 0, 98,216, 0,101,214, 0,105,209, 0,109,204, 0, + 109,204, 0,109,203, 0,109,203, 0,110,202, 0,113,198, 0, + 117,191, 0,121,182, 0,123,169, 4,124,157, 15,122,130, 53, + 118,114, 96,113,100,242,113,100,242,120,122, 70,122,135, 44, + 123,137, 41,123,139, 37,123,141, 34,124,143, 31,124,150, 22, + 124,155, 16,124,161, 11,124,162, 10,124,164, 9,124,162, 10, + 124,158, 13,124,147, 26,118,117, 85, 99, 75,247,121,125, 63, + 124,154, 18,123,169, 4,120,184, 0,117,192, 0,114,196, 0, + 114,197, 0,116,193, 0,118,188, 0,119,186, 0,119,186, 0, + 120,183, 0,122,175, 0,124,158, 13,124,143, 31,122,135, 44, + 119,119, 77,114,104,197,109, 92,251,102, 80,250, 87, 65,237, + 94, 70,242,113,100,242,122,130, 53,124,149, 24,124,158, 13, + 124,165, 8,124,166, 7,124,162, 10,124,154, 18,124,143, 31, + 122,132, 48,120,122, 70,118,117, 85,119,119, 77,122,135, 44, + 124,143, 31,124,145, 29,124,145, 29,123,141, 34,123,137, 41, + 122,132, 48,122,130, 53,122,132, 48,123,139, 37,124,145, 29, + 123,141, 34,122,135, 44,122,135, 44,122,135, 44,124,147, 26, + 124,150, 22,124,145, 29,123,141, 34,124,145, 29,124,164, 9, + 122,176, 0,120,182, 0,119,186, 0,119,187, 0,119,187, 0, + 119,187, 0,119,186, 0,119,185, 0,120,182, 0,121,180, 0, + 122,177, 0,122,178, 0,122,178, 0,121,179, 0,122,177, 0, + 123,168, 5,124,150, 22,124,147, 26,124,152, 20,124,154, 18, + 124,150, 22,123,141, 34,124,149, 24,124,154, 18,124,161, 11, + 122,177, 0,120,184, 0,119,186, 0,116,193, 0,112,199, 0, + 110,202, 0,110,203, 0,111,201, 0,114,196, 0,118,188, 0, + 120,183, 0,120,182, 0,122,178, 0,123,171, 3,124,167, 6, + 124,165, 8,124,162, 10,124,160, 12,124,157, 15,124,162, 10, + 124,166, 7,124,166, 7,124,164, 9,124,162, 10,123,168, 5, + 123,169, 4,124,167, 6,124,161, 11,124,147, 26,122,132, 48, + 120,122, 70,123,137, 41,124,150, 22,124,160, 12,124,164, 9, + 124,166, 7,124,165, 8,124,162, 10,124,161, 11,124,160, 12, + 124,158, 13,124,158, 13,124,160, 12,124,162, 10,124,167, 6, + 123,174, 1,121,180, 0,120,182, 0,120,182, 0,121,181, 0, + 120,183, 0,120,182, 0,121,180, 0,122,176, 0,123,172, 2, + 123,169, 4,124,167, 6,124,165, 8,124,162, 10,124,154, 18, + 124,152, 20,124,152, 20,124,154, 18,124,167, 6,122,176, 0, + 120,183, 0,118,189, 0,116,193, 0,113,198, 0,112,200, 0, + 112,199, 0,114,197, 0,115,194, 0,114,196, 0,113,199, 0, + 112,200, 0,111,201, 0,108,206, 0,105,209, 0,105,209, 0, + 106,208, 0,109,204, 0,110,202, 0,110,202, 0,112,200, 0, + 114,196, 0,116,192, 0,119,187, 0,121,180, 0,123,169, 4, + 123,168, 5,124,165, 8,124,161, 11,124,155, 16,124,162, 10, + 124,167, 6,123,168, 5,124,165, 8,122,175, 0,120,183, 0, + 116,193, 0,112,200, 0,108,206, 0,103,211, 0,101,214, 0, + 99,216, 0, 98,217, 0, 99,216, 0,100,214, 0,103,211, 0, + 107,207, 0,111,201, 0,115,195, 0,113,198, 0,110,202, 0, + 108,205, 0,107,207, 0,107,206, 0,109,204, 0,112,199, 0, + 116,192, 0,121,181, 0,124,162, 10,122,135, 44,122,132, 48, + 121,127, 58,124,149, 24,124,161, 11,123,172, 2,119,185, 0, + 116,193, 0,113,198, 0,112,200, 0,111,201, 0,111,202, 0, + 111,201, 0,107,206, 0,104,210, 0,102,212, 0, 99,215, 0, + 95,220, 0, 93,222, 0, 94,221, 0, 96,219, 0,100,215, 0, + 105,209, 0,109,203, 0,110,203, 0,109,204, 0,109,204, 0, + 111,201, 0,115,194, 0,119,186, 0,122,175, 0,124,158, 13, + 123,137, 41,123,139, 37,122,130, 53,120,122, 70,117,110,109, + 118,114, 96,120,122, 70,121,127, 58,122,132, 48,124,143, 31, + 124,152, 20,124,158, 13,124,161, 11,124,162, 10,124,161, 11, + 124,158, 13,124,152, 20,123,141, 34,118,114, 96, 69, 60,230, + 99, 75,247,123,141, 34,123,171, 3,119,186, 0,115,194, 0, + 113,199, 0,112,200, 0,114,197, 0,116,192, 0,116,192, 0, + 116,193, 0,117,191, 0,119,185, 0,123,174, 1,123,169, 4, + 124,164, 9,124,157, 15,124,145, 29,122,135, 44,120,122, 70, + 119,119, 77,121,125, 63,123,141, 34,124,158, 13,123,169, 4, + 122,176, 0,122,178, 0,122,178, 0,123,173, 1,124,166, 7, + 124,158, 13,124,150, 22,124,143, 31,123,139, 37,123,139, 37, + 124,149, 24,124,157, 15,124,161, 11,124,162, 10,124,161, 11, + 124,158, 13,124,155, 16,124,154, 18,124,150, 22,124,150, 22, + 124,150, 22,124,152, 20,124,154, 18,124,154, 18,124,147, 26, + 124,155, 16,124,158, 13,124,155, 16,124,145, 29,123,141, 34, + 124,161, 11,122,177, 0,119,186, 0,117,190, 0,117,192, 0, + 116,192, 0,117,191, 0,118,189, 0,119,187, 0,120,183, 0, + 121,179, 0,122,177, 0,123,174, 1,123,173, 1,122,177, 0, + 122,176, 0,123,169, 4,124,154, 18,124,147, 26,124,155, 16, + 124,160, 12,124,157, 15,124,145, 29,124,149, 24,124,152, 20, + 124,158, 13,123,172, 2,121,180, 0,119,186, 0,115,194, 0, + 112,200, 0,109,203, 0,109,203, 0,111,201, 0,114,197, 0, + 117,190, 0,118,188, 0,119,186, 0,121,182, 0,123,174, 1, + 123,168, 5,124,164, 9,124,161, 11,124,160, 12,124,166, 7, + 123,173, 1,122,178, 0,122,178, 0,122,177, 0,123,173, 1, + 123,172, 2,123,174, 1,123,173, 1,124,167, 6,124,154, 18, + 123,137, 41,119,119, 77,118,117, 85,123,137, 41,124,150, 22, + 124,161, 11,124,166, 7,123,168, 5,123,168, 5,124,167, 6, + 124,165, 8,124,164, 9,124,164, 9,124,164, 9,124,166, 7, + 123,169, 4,123,171, 3,122,177, 0,121,180, 0,121,181, 0, + 122,178, 0,121,179, 0,121,180, 0,122,178, 0,122,175, 0, + 123,171, 3,123,168, 5,124,167, 6,124,167, 6,124,166, 7, + 124,162, 10,124,164, 9,124,165, 8,124,167, 6,123,169, 4, + 123,173, 1,121,181, 0,119,187, 0,116,192, 0,113,198, 0, + 111,201, 0,111,201, 0,113,199, 0,114,197, 0,114,197, 0, + 112,200, 0,111,202, 0,110,202, 0,106,207, 0,103,211, 0, + 102,212, 0,103,212, 0,106,208, 0,110,203, 0,109,203, 0, + 110,202, 0,112,200, 0,114,197, 0,116,192, 0,119,186, 0, + 120,182, 0,121,181, 0,122,178, 0,122,175, 0,123,171, 3, + 124,167, 6,123,169, 4,123,169, 4,124,167, 6,122,177, 0, + 119,186, 0,115,194, 0,111,201, 0,107,206, 0,103,211, 0, + 100,214, 0, 98,217, 0, 96,219, 0, 95,219, 0, 96,219, 0, + 98,217, 0,101,214, 0,106,208, 0,111,201, 0,116,193, 0, + 114,197, 0,111,202, 0,109,204, 0,109,204, 0,111,202, 0, + 114,196, 0,118,188, 0,122,176, 0,124,154, 18,123,137, 41, + 123,139, 37,123,141, 34,124,160, 12,123,171, 3,122,178, 0, + 121,180, 0,118,188, 0,115,194, 0,114,197, 0,113,199, 0, + 112,200, 0,108,205, 0,103,211, 0,100,214, 0, 99,216, 0, + 95,220, 0, 91,224, 0, 89,226, 0, 89,225, 0, 92,222, 0, + 97,218, 0,101,213, 0,106,207, 0,110,202, 0,110,202, 0, + 110,203, 0,111,201, 0,114,196, 0,118,189, 0,121,180, 0, + 123,168, 5,124,154, 18,124,155, 16,124,147, 26,123,139, 37, + 121,127, 58,118,114, 96,114,104,197,117,110,109,120,122, 70, + 123,139, 37,124,152, 20,124,158, 13,124,161, 11,124,161, 11, + 124,160, 12,124,158, 13,124,152, 20,122,135, 44,115,107,129, + 109, 92,251,105, 84,252,123,137, 41,123,169, 4,120,184, 0, + 116,193, 0,113,199, 0,112,200, 0,113,198, 0,115,194, 0, + 113,198, 0,112,199, 0,114,197, 0,116,192, 0,119,185, 0, + 120,184, 0,121,181, 0,122,175, 0,123,168, 5,124,161, 11, + 124,160, 12,124,158, 13,124,154, 18,124,164, 9,123,173, 1, + 121,180, 0,120,184, 0,119,186, 0,120,184, 0,121,180, 0, + 123,174, 1,124,167, 6,124,160, 12,124,152, 20,124,147, 26, + 124,145, 29,124,155, 16,124,164, 9,124,167, 6,123,169, 4, + 123,169, 4,123,168, 5,124,166, 7,124,165, 8,124,162, 10, + 124,161, 11,124,161, 11,124,164, 9,124,165, 8,124,164, 9, + 124,157, 15,124,161, 11,124,162, 10,124,158, 13,124,149, 24, + 122,135, 44,124,160, 12,122,178, 0,118,188, 0,116,193, 0, + 115,195, 0,115,194, 0,116,193, 0,117,191, 0,119,186, 0, + 121,182, 0,122,177, 0,123,173, 1,123,172, 2,123,173, 1, + 123,173, 1,123,172, 2,123,168, 5,124,157, 15,124,147, 26, + 124,155, 16,124,160, 12,124,157, 15,124,145, 29,123,137, 41, + 123,141, 34,124,150, 22,123,168, 5,122,177, 0,120,182, 0, + 117,191, 0,113,198, 0,111,202, 0,110,202, 0,112,200, 0, + 114,196, 0,117,191, 0,117,190, 0,118,188, 0,120,182, 0, + 123,174, 1,123,169, 4,124,166, 7,124,160, 12,124,158, 13, + 123,169, 4,122,178, 0,120,184, 0,119,185, 0,120,184, 0, + 121,180, 0,122,175, 0,122,177, 0,122,175, 0,123,169, 4, + 124,155, 16,122,132, 48,115,107,129,105, 84,252,117,110,109, + 122,132, 48,124,150, 22,124,161, 11,124,167, 6,123,168, 5, + 124,167, 6,124,166, 7,124,164, 9,124,164, 9,124,164, 9, + 124,167, 6,123,171, 3,123,172, 2,123,172, 2,122,175, 0, + 122,177, 0,123,174, 1,123,173, 1,122,176, 0,122,175, 0, + 123,171, 3,123,168, 5,123,170, 3,124,167, 6,124,164, 9, + 124,165, 8,124,164, 9,124,166, 7,123,169, 4,123,171, 3, + 123,172, 2,123,174, 1,122,176, 0,121,181, 0,118,188, 0, + 115,194, 0,113,198, 0,112,199, 0,113,198, 0,114,197, 0, + 113,198, 0,111,202, 0,109,203, 0,110,203, 0,106,208, 0, + 102,213, 0,100,215, 0,100,215, 0,102,212, 0,106,207, 0, + 109,203, 0,110,203, 0,111,201, 0,112,199, 0,114,196, 0, + 117,190, 0,118,189, 0,118,188, 0,119,185, 0,120,182, 0, + 121,180, 0,122,176, 0,123,171, 3,123,169, 4,124,167, 6, + 122,178, 0,118,189, 0,113,198, 0,108,205, 0,103,211, 0, + 100,214, 0, 98,217, 0, 97,217, 0, 96,219, 0, 94,221, 0, + 93,221, 0, 94,221, 0, 96,219, 0,100,215, 0,106,208, 0, + 112,199, 0,117,190, 0,114,196, 0,112,200, 0,112,200, 0, + 114,197, 0,117,191, 0,121,182, 0,124,166, 7,123,137, 41, + 122,132, 48,123,139, 37,124,147, 26,124,167, 6,122,178, 0, + 120,184, 0,119,186, 0,119,185, 0,118,189, 0,116,193, 0, + 114,196, 0,111,201, 0,105,209, 0,100,215, 0, 97,218, 0, + 95,219, 0, 92,222, 0, 87,227, 0, 86,228, 0, 87,227, 0, + 90,224, 0, 95,220, 0,100,215, 0,105,209, 0,109,204, 0, + 112,200, 0,111,201, 0,112,199, 0,114,196, 0,117,190, 0, + 120,183, 0,123,174, 1,124,164, 9,124,162, 10,124,158, 13, + 124,149, 24,123,139, 37,121,125, 63,118,114, 96,119,119, 77, + 121,127, 58,122,135, 44,124,150, 22,124,158, 13,124,161, 11, + 124,158, 13,124,157, 15,124,157, 15,124,157, 15,124,152, 20, + 124,143, 31,122,135, 44,121,127, 58,121,127, 58,124,162, 10, + 121,180, 0,118,189, 0,115,195, 0,114,197, 0,114,196, 0, + 112,200, 0,109,204, 0,108,205, 0,110,203, 0,113,198, 0, + 115,194, 0,116,193, 0,117,191, 0,119,187, 0,121,182, 0, + 121,179, 0,121,179, 0,122,178, 0,123,174, 1,122,177, 0, + 120,183, 0,118,188, 0,117,190, 0,118,189, 0,119,187, 0, + 120,182, 0,122,176, 0,123,168, 5,124,160, 12,124,150, 22, + 124,145, 29,124,145, 29,124,155, 16,124,164, 9,123,168, 5, + 123,170, 3,123,171, 3,123,171, 3,123,170, 3,123,168, 5, + 124,167, 6,124,166, 7,124,167, 6,123,168, 5,123,169, 4, + 123,168, 5,124,162, 10,124,162, 10,124,161, 11,124,157, 15, + 124,147, 26,122,130, 53,124,160, 12,121,179, 0,118,189, 0, + 115,194, 0,114,196, 0,115,195, 0,116,193, 0,118,189, 0, + 119,186, 0,118,188, 0,118,188, 0,119,185, 0,122,178, 0, + 123,170, 3,123,172, 2,123,170, 3,124,165, 8,124,157, 15, + 124,145, 29,124,152, 20,124,155, 16,124,152, 20,122,135, 44, + 114,104,197,117,110,109,124,149, 24,124,166, 7,123,174, 1, + 122,177, 0,119,185, 0,116,193, 0,114,197, 0,113,198, 0, + 114,197, 0,115,194, 0,117,191, 0,117,191, 0,118,188, 0, + 120,182, 0,121,180, 0,121,180, 0,121,179, 0,122,176, 0, + 123,174, 1,123,172, 2,121,179, 0,119,186, 0,118,188, 0, + 119,187, 0,120,184, 0,122,178, 0,122,178, 0,122,176, 0, + 123,168, 5,124,152, 20,122,135, 44,121,125, 63,117,110,109, + 115,107,129,114,104,197,122,130, 53,124,149, 24,124,158, 13, + 124,162, 10,124,162, 10,124,160, 12,124,158, 13,124,158, 13, + 124,160, 12,124,164, 9,123,170, 3,123,173, 1,123,169, 4, + 123,169, 4,123,170, 3,123,169, 4,124,165, 8,123,169, 4, + 123,168, 5,124,164, 9,123,172, 2,122,177, 0,122,176, 0, + 123,168, 5,124,158, 13,124,160, 12,124,162, 10,124,167, 6, + 123,169, 4,123,170, 3,123,171, 3,123,172, 2,123,173, 1, + 122,178, 0,119,187, 0,116,192, 0,115,194, 0,115,195, 0, + 115,195, 0,113,199, 0,110,202, 0,109,204, 0,109,204, 0, + 105,209, 0,101,214, 0, 98,217, 0, 97,218, 0, 99,216, 0, + 103,212, 0,108,205, 0,110,203, 0,110,202, 0,112,200, 0, + 114,197, 0,116,192, 0,116,192, 0,117,191, 0,118,188, 0, + 119,185, 0,120,183, 0,121,180, 0,122,176, 0,123,170, 3, + 124,166, 7,121,180, 0,117,192, 0,111,201, 0,105,209, 0, + 100,215, 0, 95,220, 0, 92,222, 0, 91,223, 0, 92,222, 0, + 94,221, 0, 92,222, 0, 92,223, 0, 93,222, 0, 96,219, 0, + 101,214, 0,108,206, 0,115,194, 0,118,189, 0,116,193, 0, + 116,193, 0,117,191, 0,120,184, 0,123,171, 3,124,149, 24, + 119,119, 77,119,119, 77,122,130, 53,124,145, 29,123,171, 3, + 120,184, 0,118,189, 0,117,191, 0,118,189, 0,120,184, 0, + 118,188, 0,117,192, 0,110,203, 0,102,212, 0, 97,218, 0, + 93,221, 0, 92,222, 0, 91,223, 0, 87,227, 0, 85,228, 0, + 87,227, 0, 90,224, 0, 95,220, 0,100,215, 0,105,209, 0, + 109,204, 0,112,200, 0,114,196, 0,114,196, 0,116,193, 0, + 118,189, 0,120,183, 0,122,176, 0,123,168, 5,124,166, 7, + 124,162, 10,124,155, 16,124,147, 26,123,141, 34,124,149, 24, + 124,154, 18,124,154, 18,124,149, 24,124,158, 13,124,164, 9, + 124,165, 8,124,164, 9,124,162, 10,124,167, 6,123,169, 4, + 124,166, 7,124,160, 12,124,154, 18,124,147, 26,123,139, 37, + 124,152, 20,123,172, 2,120,184, 0,118,189, 0,117,192, 0, + 113,199, 0,108,205, 0,105,209, 0,105,209, 0,106,207, 0, + 110,203, 0,112,200, 0,112,200, 0,113,198, 0,115,194, 0, + 117,191, 0,117,190, 0,117,190, 0,118,189, 0,119,186, 0, + 119,186, 0,117,190, 0,116,193, 0,116,193, 0,116,192, 0, + 118,188, 0,120,182, 0,123,174, 1,124,166, 7,124,155, 16, + 124,150, 22,124,145, 29,124,143, 31,124,152, 20,124,160, 12, + 124,165, 8,124,167, 6,123,168, 5,123,169, 4,123,168, 5, + 124,167, 6,124,166, 7,124,165, 8,124,166, 7,123,168, 5, + 123,169, 4,123,168, 5,124,162, 10,124,160, 12,124,157, 15, + 124,150, 22,123,139, 37,122,135, 44,124,161, 11,121,179, 0, + 118,189, 0,116,193, 0,115,195, 0,115,194, 0,117,192, 0, + 118,189, 0,115,194, 0,114,197, 0,114,197, 0,115,194, 0, + 118,188, 0,122,178, 0,123,171, 3,123,169, 4,124,162, 10, + 124,158, 13,124,147, 26,124,147, 26,124,147, 26,123,141, 34, + 119,119, 77, 99, 75,247,117,110,109,124,147, 26,124,164, 9, + 123,171, 3,123,173, 1,123,174, 1,120,184, 0,118,189, 0, + 117,192, 0,117,191, 0,118,189, 0,117,191, 0,117,191, 0, + 118,188, 0,120,182, 0,120,184, 0,119,186, 0,119,186, 0, + 119,186, 0,119,186, 0,120,184, 0,121,180, 0,119,185, 0, + 118,188, 0,119,187, 0,120,184, 0,121,179, 0,121,179, 0, + 122,175, 0,124,167, 6,124,147, 26,124,143, 31,123,139, 37, + 122,132, 48,122,132, 48,122,130, 53,120,122, 70,121,127, 58, + 124,143, 31,124,147, 26,124,149, 24,124,147, 26,124,145, 29, + 124,145, 29,124,149, 24,124,155, 16,124,165, 8,123,170, 3, + 123,168, 5,124,164, 9,124,165, 8,124,162, 10,124,155, 16, + 124,160, 12,124,158, 13,124,165, 8,122,176, 0,121,182, 0, + 120,183, 0,122,178, 0,123,168, 5,124,150, 22,124,154, 18, + 124,160, 12,124,164, 9,124,164, 9,124,164, 9,124,164, 9, + 124,165, 8,124,166, 7,122,175, 0,120,184, 0,118,188, 0, + 117,190, 0,116,193, 0,112,199, 0,110,203, 0,109,204, 0, + 109,204, 0,105,209, 0,100,214, 0, 97,218, 0, 95,220, 0, + 97,218, 0,100,214, 0,106,208, 0,110,202, 0,110,202, 0, + 111,201, 0,113,198, 0,115,194, 0,116,193, 0,117,191, 0, + 119,186, 0,120,184, 0,121,182, 0,121,179, 0,122,176, 0, + 123,171, 3,124,166, 7,121,181, 0,116,192, 0,110,202, 0, + 104,210, 0, 97,217, 0, 92,222, 0, 89,226, 0, 87,227, 0, + 89,226, 0, 91,223, 0, 92,222, 0, 91,223, 0, 91,223, 0, + 94,221, 0, 98,217, 0,104,210, 0,112,200, 0,119,187, 0, + 119,186, 0,119,186, 0,120,183, 0,123,174, 1,124,158, 13, + 122,130, 53,119,119, 77,118,117, 85,119,119, 77,124,145, 29, + 123,173, 1,119,187, 0,116,193, 0,115,194, 0,117,192, 0, + 119,186, 0,120,184, 0,117,191, 0,109,204, 0,101,214, 0, + 94,220, 0, 90,224, 0, 89,225, 0, 90,225, 0, 87,227, 0, + 87,227, 0, 88,226, 0, 91,223, 0, 96,219, 0,101,214, 0, + 106,208, 0,109,203, 0,112,199, 0,115,195, 0,117,191, 0, + 118,189, 0,119,186, 0,121,181, 0,122,175, 0,123,169, 4, + 124,165, 8,124,164, 9,124,160, 12,124,157, 15,124,162, 10, + 124,166, 7,123,168, 5,124,167, 6,124,162, 10,123,171, 3, + 122,175, 0,122,176, 0,122,175, 0,123,172, 2,123,172, 2, + 123,173, 1,123,171, 3,123,173, 1,123,170, 3,124,164, 9, + 124,150, 22,123,141, 34,124,162, 10,122,176, 0,120,184, 0, + 115,194, 0,110,203, 0,105,209, 0,102,212, 0,101,213, 0, + 103,211, 0,106,207, 0,110,202, 0,110,203, 0,110,202, 0, + 112,200, 0,113,198, 0,114,197, 0,114,197, 0,114,196, 0, + 116,192, 0,115,195, 0,113,198, 0,113,199, 0,113,198, 0, + 115,194, 0,118,189, 0,121,182, 0,123,173, 1,123,172, 2, + 123,171, 3,123,170, 3,123,171, 3,123,171, 3,123,168, 5, + 124,165, 8,124,161, 11,124,162, 10,124,164, 9,124,164, 9, + 124,162, 10,124,160, 12,124,158, 13,124,157, 15,124,158, 13, + 124,161, 11,124,164, 9,124,162, 10,124,157, 15,124,154, 18, + 124,149, 24,123,139, 37,120,122, 70,123,139, 37,124,161, 11, + 122,178, 0,118,188, 0,117,192, 0,116,193, 0,117,191, 0, + 118,189, 0,115,195, 0,112,200, 0,110,202, 0,110,202, 0, + 112,200, 0,116,193, 0,120,184, 0,123,171, 3,123,170, 3, + 124,166, 7,124,160, 12,124,154, 18,124,143, 31,123,141, 34, + 122,130, 53,113,100,242,115,107,129,119,119, 77,123,139, 37, + 124,158, 13,124,166, 7,123,169, 4,123,169, 4,123,170, 3, + 122,178, 0,120,182, 0,120,184, 0,118,188, 0,117,190, 0, + 117,190, 0,118,188, 0,121,181, 0,120,184, 0,119,187, 0, + 118,189, 0,117,191, 0,117,192, 0,117,190, 0,119,186, 0, + 120,182, 0,119,185, 0,120,184, 0,121,182, 0,121,182, 0, + 121,180, 0,122,175, 0,124,166, 7,124,143, 31,123,141, 34, + 123,139, 37,123,137, 41,123,141, 34,123,141, 34,122,135, 44, + 120,122, 70,118,114, 96,120,122, 70,120,122, 70,121,127, 58, + 123,137, 41,124,143, 31,124,147, 26,124,149, 24,124,150, 22, + 124,160, 12,124,160, 12,124,161, 11,124,161, 11,124,158, 13, + 124,149, 24,124,147, 26,124,145, 29,124,166, 7,122,178, 0, + 120,184, 0,119,186, 0,120,184, 0,122,178, 0,124,164, 9, + 123,141, 34,124,150, 22,124,154, 18,124,155, 16,124,154, 18, + 124,161, 11,124,164, 9,124,164, 9,124,160, 12,123,173, 1, + 121,180, 0,119,186, 0,116,193, 0,113,198, 0,111,202, 0, + 110,203, 0,110,202, 0,106,208, 0,100,214, 0, 97,218, 0, + 95,220, 0, 96,219, 0,100,215, 0,105,209, 0,110,202, 0, + 110,202, 0,111,201, 0,113,198, 0,116,193, 0,117,191, 0, + 118,188, 0,120,182, 0,122,178, 0,122,178, 0,122,175, 0, + 123,171, 3,123,168, 5,123,170, 3,119,185, 0,115,194, 0, + 111,201, 0,105,209, 0, 98,217, 0, 92,223, 0, 88,226, 0, + 86,228, 0, 87,227, 0, 90,224, 0, 94,221, 0, 92,222, 0, + 92,223, 0, 93,221, 0, 97,218, 0,103,212, 0,110,202, 0, + 117,190, 0,121,179, 0,121,180, 0,122,176, 0,124,166, 7, + 124,150, 22,122,132, 48,121,125, 63,119,119, 77,115,107,129, + 124,147, 26,122,175, 0,118,188, 0,115,194, 0,114,196, 0, + 116,193, 0,118,188, 0,121,180, 0,117,191, 0,108,205, 0, + 100,215, 0, 93,222, 0, 89,226, 0, 87,227, 0, 88,226, 0, + 90,224, 0, 89,225, 0, 91,224, 0, 94,221, 0, 97,218, 0, + 99,215, 0,103,212, 0,107,206, 0,113,198, 0,115,194, 0, + 118,188, 0,120,184, 0,121,181, 0,122,177, 0,122,177, 0, + 123,173, 1,123,172, 2,124,167, 6,124,166, 7,123,168, 5, + 123,171, 3,123,174, 1,122,176, 0,122,175, 0,123,171, 3, + 122,178, 0,121,182, 0,120,183, 0,120,183, 0,121,182, 0, + 121,181, 0,121,181, 0,120,183, 0,119,185, 0,120,183, 0, + 121,179, 0,123,173, 1,124,165, 8,124,162, 10,122,177, 0, + 118,188, 0,113,198, 0,108,206, 0,103,212, 0,100,215, 0, + 99,216, 0,100,214, 0,103,212, 0,106,207, 0,109,204, 0, + 109,204, 0,109,203, 0,110,202, 0,111,202, 0,111,201, 0, + 111,201, 0,111,202, 0,109,203, 0,108,205, 0,109,204, 0, + 110,202, 0,113,198, 0,117,191, 0,120,182, 0,120,183, 0, + 120,182, 0,121,182, 0,120,184, 0,119,185, 0,120,184, 0, + 121,182, 0,122,178, 0,123,174, 1,123,170, 3,124,167, 6, + 124,164, 9,124,161, 11,124,161, 11,124,162, 10,124,162, 10, + 124,162, 10,124,161, 11,124,154, 18,124,154, 18,124,149, 24, + 123,141, 34,122,130, 53,118,117, 85,122,130, 53,124,143, 31, + 124,161, 11,122,178, 0,119,186, 0,117,190, 0,117,191, 0, + 118,189, 0,117,192, 0,113,198, 0,110,202, 0,108,205, 0, + 108,206, 0,110,202, 0,114,197, 0,118,189, 0,122,178, 0, + 123,170, 3,124,167, 6,124,160, 12,124,157, 15,124,150, 22, + 123,139, 37,121,127, 58,118,117, 85,119,119, 77,121,127, 58, + 123,139, 37,124,147, 26,124,158, 13,124,162, 10,124,165, 8, + 124,166, 7,123,170, 3,122,176, 0,121,182, 0,119,186, 0, + 118,188, 0,118,189, 0,119,186, 0,121,180, 0,122,178, 0, + 120,183, 0,118,188, 0,116,192, 0,115,194, 0,116,193, 0, + 117,190, 0,119,187, 0,119,185, 0,120,184, 0,120,184, 0, + 120,183, 0,121,181, 0,122,176, 0,124,166, 7,124,143, 31, + 120,122, 70,121,125, 63,121,127, 58,123,139, 37,123,141, 34, + 122,135, 44,121,125, 63,118,117, 85,118,114, 96,118,117, 85, + 120,122, 70,122,130, 53,122,135, 44,123,141, 34,124,143, 31, + 124,147, 26,124,150, 22,124,154, 18,124,157, 15,124,157, 15, + 124,152, 20,124,143, 31,122,130, 53,124,143, 31,124,164, 9, + 122,177, 0,120,184, 0,119,186, 0,119,185, 0,121,180, 0, + 123,169, 4,124,150, 22,124,143, 31,124,147, 26,124,154, 18, + 124,161, 11,124,167, 6,123,169, 4,123,169, 4,124,165, 8, + 124,166, 7,122,175, 0,120,183, 0,118,189, 0,115,194, 0, + 114,197, 0,113,199, 0,111,202, 0,106,208, 0,101,213, 0, + 98,217, 0, 96,219, 0, 97,218, 0,100,214, 0,105,209, 0, + 110,202, 0,111,202, 0,112,200, 0,114,196, 0,117,191, 0, + 118,188, 0,120,183, 0,122,177, 0,121,180, 0,122,178, 0, + 123,174, 1,124,166, 7,124,164, 9,122,176, 0,117,190, 0, + 112,199, 0,108,205, 0,106,208, 0,101,214, 0, 95,220, 0, + 90,224, 0, 88,226, 0, 88,226, 0, 90,224, 0, 94,221, 0, + 95,220, 0, 94,220, 0, 95,220, 0, 98,216, 0,103,211, 0, + 110,202, 0,117,191, 0,121,179, 0,122,175, 0,123,170, 3, + 124,160, 12,124,149, 24,122,132, 48,120,122, 70,118,117, 85, + 114,104,197,124,145, 29,123,174, 1,119,187, 0,116,193, 0, + 115,194, 0,117,191, 0,119,186, 0,121,180, 0,117,192, 0, + 108,205, 0,100,215, 0, 93,222, 0, 88,226, 0, 87,227, 0, + 87,227, 0, 89,225, 0, 91,223, 0, 92,222, 0, 94,220, 0, + 96,219, 0, 98,216, 0,102,213, 0,106,207, 0,112,200, 0, + 115,194, 0,118,188, 0,121,179, 0,122,177, 0,122,178, 0, + 122,178, 0,122,177, 0,123,173, 1,123,170, 3,123,171, 3, + 123,173, 1,122,176, 0,122,178, 0,121,181, 0,121,180, 0, + 122,178, 0,121,180, 0,120,184, 0,119,186, 0,119,187, 0, + 118,188, 0,118,188, 0,118,189, 0,117,191, 0,116,192, 0, + 117,191, 0,118,189, 0,119,185, 0,121,180, 0,122,176, 0, + 120,182, 0,117,192, 0,111,201, 0,106,207, 0,102,213, 0, + 99,216, 0, 98,217, 0, 98,216, 0,101,214, 0,103,211, 0, + 105,209, 0,107,207, 0,108,205, 0,108,206, 0,107,207, 0, + 106,207, 0,105,209, 0,105,209, 0,103,211, 0,103,211, 0, + 105,209, 0,107,206, 0,111,201, 0,116,192, 0,118,189, 0, + 117,190, 0,118,189, 0,117,192, 0,116,193, 0,116,193, 0, + 117,191, 0,118,188, 0,120,184, 0,121,181, 0,122,178, 0, + 123,174, 1,123,171, 3,123,171, 3,123,171, 3,123,171, 3, + 123,170, 3,124,167, 6,124,162, 10,124,155, 16,124,147, 26, + 123,141, 34,120,122, 70,119,119, 77,121,125, 63,122,135, 44, + 124,145, 29,124,162, 10,122,178, 0,119,185, 0,118,188, 0, + 118,188, 0,119,186, 0,117,192, 0,113,199, 0,109,204, 0, + 107,207, 0,106,207, 0,108,205, 0,112,200, 0,116,193, 0, + 120,184, 0,122,175, 0,124,165, 8,124,161, 11,124,160, 12, + 124,155, 16,124,149, 24,123,137, 41,121,125, 63,122,130, 53, + 122,135, 44,123,139, 37,124,145, 29,124,149, 24,124,152, 20, + 124,157, 15,124,161, 11,124,166, 7,123,171, 3,122,177, 0, + 121,181, 0,120,184, 0,120,184, 0,120,183, 0,122,178, 0, + 123,168, 5,122,176, 0,119,185, 0,117,191, 0,115,194, 0, + 115,194, 0,116,193, 0,117,190, 0,118,188, 0,119,186, 0, + 120,184, 0,120,182, 0,121,179, 0,123,173, 1,124,164, 9, + 124,143, 31,113,100,242,105, 84,252,115,107,129,120,122, 70, + 121,127, 58,121,125, 63,118,114, 96,114,104,197,111, 96,248, + 111, 96,248,113,100,242,115,107,129,118,114, 96,119,119, 77, + 121,125, 63,122,130, 53,123,137, 41,123,141, 34,124,145, 29, + 124,145, 29,123,141, 34,122,130, 53,120,122, 70,123,141, 34, + 124,160, 12,123,172, 2,121,179, 0,120,183, 0,120,182, 0, + 122,178, 0,123,168, 5,124,152, 20,123,139, 37,124,145, 29, + 124,154, 18,124,164, 9,123,169, 4,123,173, 1,123,173, 1, + 123,169, 4,124,162, 10,123,169, 4,122,176, 0,120,182, 0, + 119,186, 0,117,191, 0,114,197, 0,111,201, 0,107,207, 0, + 103,211, 0,100,215, 0, 98,216, 0,100,215, 0,102,212, 0, + 106,207, 0,111,202, 0,112,199, 0,114,197, 0,116,193, 0, + 119,186, 0,120,184, 0,122,178, 0,123,174, 1,122,176, 0, + 123,174, 1,123,168, 5,124,157, 15,124,160, 12,121,182, 0, + 115,194, 0,109,203, 0,105,209, 0,102,212, 0,102,213, 0, + 99,215, 0, 94,220, 0, 91,223, 0, 91,224, 0, 92,223, 0, + 94,221, 0, 99,216, 0, 99,216, 0, 99,215, 0,102,213, 0, + 106,208, 0,112,200, 0,118,189, 0,121,181, 0,123,174, 1, + 123,168, 5,124,161, 11,124,152, 20,122,135, 44,119,119, 77, + 118,117, 85,118,114, 96,123,139, 37,123,169, 4,120,183, 0, + 118,189, 0,117,190, 0,118,188, 0,121,182, 0,120,182, 0, + 116,193, 0,108,205, 0,101,214, 0, 94,220, 0, 90,224, 0, + 88,226, 0, 88,226, 0, 89,225, 0, 91,223, 0, 93,222, 0, + 95,220, 0, 97,218, 0,100,215, 0,103,212, 0,107,207, 0, + 111,201, 0,115,194, 0,118,189, 0,121,181, 0,122,175, 0, + 122,177, 0,122,178, 0,122,177, 0,123,172, 2,122,175, 0, + 122,177, 0,122,177, 0,122,178, 0,121,181, 0,120,183, 0, + 120,184, 0,120,183, 0,121,180, 0,120,183, 0,119,186, 0, + 118,188, 0,117,190, 0,117,192, 0,116,193, 0,114,196, 0, + 114,197, 0,114,196, 0,116,193, 0,117,191, 0,118,188, 0, + 119,186, 0,119,185, 0,115,194, 0,111,202, 0,106,208, 0, + 102,212, 0,100,215, 0, 98,216, 0, 99,216, 0,100,215, 0, + 101,213, 0,103,212, 0,104,210, 0,106,208, 0,106,207, 0, + 104,210, 0,102,212, 0,100,214, 0, 99,215, 0, 99,216, 0, + 99,215, 0,101,213, 0,105,209, 0,109,203, 0,115,195, 0, + 115,194, 0,115,194, 0,114,197, 0,112,199, 0,112,200, 0, + 113,198, 0,114,196, 0,117,192, 0,118,188, 0,120,184, 0, + 121,182, 0,122,178, 0,122,178, 0,122,177, 0,122,176, 0, + 122,175, 0,123,172, 2,123,169, 4,124,162, 10,124,152, 20, + 124,147, 26,123,141, 34,123,137, 41,122,132, 48,121,127, 58, + 122,132, 48,123,141, 34,124,161, 11,122,176, 0,120,183, 0, + 119,186, 0,119,186, 0,120,184, 0,117,190, 0,113,198, 0, + 109,203, 0,107,207, 0,106,207, 0,107,206, 0,110,202, 0, + 114,196, 0,118,189, 0,121,181, 0,123,171, 3,124,161, 11, + 124,162, 10,124,161, 11,124,155, 16,124,145, 29,123,141, 34, + 124,145, 29,124,149, 24,124,152, 20,124,150, 22,124,145, 29, + 124,149, 24,124,150, 22,124,150, 22,124,155, 16,124,161, 11, + 124,166, 7,123,170, 3,123,174, 1,122,176, 0,122,176, 0, + 123,172, 2,124,167, 6,124,167, 6,122,178, 0,119,186, 0, + 117,191, 0,116,193, 0,116,193, 0,117,191, 0,118,188, 0, + 119,185, 0,120,182, 0,122,178, 0,123,174, 1,123,168, 5, + 124,158, 13,123,139, 37,113,100,242, 69, 60,230, 94, 70,242, + 109, 92,251,114,104,197,113,100,242,109, 92,251, 99, 75,247, + 69, 60,230, 30, 55,222, 94, 70,242,107, 89,252,113,100,242, + 114,104,197,113,100,242,113,100,242,119,119, 77,122,135, 44, + 123,141, 34,124,145, 29,124,143, 31,123,141, 34,122,135, 44, + 122,132, 48,124,150, 22,124,162, 10,123,170, 3,123,174, 1, + 123,174, 1,123,171, 3,124,162, 10,124,147, 26,123,137, 41, + 122,135, 44,124,149, 24,124,161, 11,123,169, 4,123,174, 1, + 122,175, 0,123,171, 3,124,162, 10,124,158, 13,124,165, 8, + 122,175, 0,120,184, 0,117,190, 0,115,195, 0,112,200, 0, + 109,204, 0,106,208, 0,104,210, 0,103,212, 0,103,211, 0, + 105,209, 0,108,205, 0,111,201, 0,114,196, 0,116,192, 0, + 118,188, 0,121,181, 0,122,177, 0,123,171, 3,124,166, 7, + 124,166, 7,124,165, 8,124,157, 15,124,147, 26,124,166, 7, + 119,185, 0,113,198, 0,107,206, 0,103,212, 0,100,214, 0, + 100,215, 0,101,214, 0,100,215, 0, 96,219, 0, 95,220, 0, + 94,220, 0, 96,219, 0,100,215, 0,105,209, 0,105,209, 0, + 106,207, 0,110,203, 0,114,196, 0,118,188, 0,120,182, 0, + 122,176, 0,123,169, 4,124,162, 10,124,154, 18,123,137, 41, + 118,114, 96,117,110,109,121,127, 58,123,137, 41,124,162, 10, + 122,177, 0,120,184, 0,119,185, 0,120,182, 0,120,182, 0, + 119,186, 0,116,192, 0,110,202, 0,104,210, 0, 98,217, 0, + 94,221, 0, 92,223, 0, 91,223, 0, 92,223, 0, 93,222, 0, + 95,220, 0, 97,218, 0, 99,215, 0,102,212, 0,105,209, 0, + 109,204, 0,112,199, 0,115,195, 0,118,189, 0,120,183, 0, + 122,176, 0,123,172, 2,123,173, 1,123,172, 2,122,175, 0, + 122,178, 0,121,182, 0,120,182, 0,120,182, 0,121,182, 0, + 120,184, 0,119,186, 0,119,186, 0,120,184, 0,121,181, 0, + 120,184, 0,119,186, 0,118,189, 0,116,192, 0,115,194, 0, + 114,196, 0,114,197, 0,114,196, 0,115,194, 0,116,192, 0, + 117,191, 0,117,190, 0,117,190, 0,116,193, 0,112,200, 0, + 108,206, 0,105,209, 0,102,212, 0,101,213, 0,101,214, 0, + 101,213, 0,102,213, 0,102,212, 0,103,211, 0,104,210, 0, + 106,208, 0,103,212, 0,100,215, 0, 97,217, 0, 96,219, 0, + 96,219, 0, 97,218, 0, 99,216, 0,102,212, 0,107,206, 0, + 113,198, 0,114,196, 0,113,198, 0,110,202, 0,109,203, 0, + 109,203, 0,111,202, 0,113,198, 0,115,194, 0,118,189, 0, + 119,186, 0,120,183, 0,121,180, 0,121,181, 0,121,180, 0, + 122,178, 0,122,176, 0,123,171, 3,124,167, 6,124,161, 11, + 124,152, 20,124,145, 29,123,141, 34,124,143, 31,124,143, 31, + 123,141, 34,123,137, 41,122,130, 53,124,155, 16,123,171, 3, + 121,179, 0,120,182, 0,120,182, 0,121,181, 0,119,187, 0, + 115,195, 0,111,201, 0,108,205, 0,107,207, 0,108,205, 0, + 111,202, 0,114,197, 0,117,191, 0,120,184, 0,122,175, 0, + 124,164, 9,124,166, 7,124,166, 7,124,161, 11,124,154, 18, + 124,150, 22,124,152, 20,124,155, 16,124,158, 13,124,161, 11, + 124,160, 12,124,154, 18,124,147, 26,124,149, 24,124,147, 26, + 124,147, 26,124,149, 24,124,152, 20,124,158, 13,124,164, 9, + 124,167, 6,124,167, 6,124,164, 9,124,155, 16,123,168, 5, + 122,178, 0,119,186, 0,118,189, 0,117,191, 0,118,189, 0, + 119,185, 0,121,181, 0,122,176, 0,123,170, 3,124,165, 8, + 124,157, 15,124,147, 26,121,127, 58,109, 92,251,107, 89,252, + 102, 80,250, 87, 65,237, 69, 60,230, 69, 60,230, 30, 49,213, + 30, 37,192, 30, 31,180, 30, 55,222, 99, 75,247,107, 89,252, + 111, 96,248,111, 96,248,109, 92,251,105, 84,252,117,110,109, + 122,130, 53,124,143, 31,124,149, 24,124,150, 22,124,149, 24, + 124,143, 31,122,135, 44,122,132, 48,124,145, 29,124,154, 18, + 124,160, 12,124,161, 11,124,158, 13,124,152, 20,124,147, 26, + 123,141, 34,120,122, 70,123,137, 41,124,154, 18,124,165, 8, + 123,171, 3,123,172, 2,123,169, 4,124,160, 12,124,145, 29, + 124,154, 18,123,171, 3,121,181, 0,119,187, 0,117,192, 0, + 114,196, 0,112,199, 0,110,202, 0,109,204, 0,108,205, 0, + 108,205, 0,109,204, 0,110,202, 0,112,200, 0,114,196, 0, + 118,189, 0,120,182, 0,122,175, 0,123,168, 5,124,164, 9, + 124,155, 16,124,149, 24,124,145, 29,123,137, 41,123,137, 41, + 123,169, 4,119,186, 0,113,198, 0,107,207, 0,102,212, 0, + 100,214, 0,100,215, 0,101,214, 0,103,212, 0,102,212, 0, + 100,215, 0, 99,216, 0, 99,215, 0,102,212, 0,108,205, 0, + 110,202, 0,112,200, 0,114,197, 0,117,190, 0,118,188, 0, + 120,183, 0,122,177, 0,123,169, 4,124,162, 10,124,152, 20, + 123,139, 37,117,110,109,115,107,129,122,135, 44,124,147, 26, + 124,155, 16,123,170, 3,122,177, 0,121,179, 0,120,182, 0, + 119,186, 0,118,188, 0,117,190, 0,113,198, 0,108,205, 0, + 104,210, 0,100,215, 0, 97,217, 0, 96,219, 0, 96,219, 0, + 97,218, 0, 98,217, 0,100,214, 0,103,212, 0,106,208, 0, + 109,204, 0,111,201, 0,113,198, 0,115,194, 0,118,189, 0, + 120,184, 0,122,178, 0,123,170, 3,124,167, 6,123,169, 4, + 122,176, 0,121,181, 0,120,184, 0,119,186, 0,119,186, 0, + 119,186, 0,120,183, 0,119,186, 0,119,187, 0,119,186, 0, + 120,183, 0,121,179, 0,120,182, 0,119,186, 0,118,189, 0, + 117,192, 0,116,193, 0,116,193, 0,116,192, 0,117,191, 0, + 118,189, 0,118,189, 0,117,190, 0,117,191, 0,116,193, 0, + 114,197, 0,111,201, 0,109,204, 0,107,207, 0,106,208, 0, + 105,209, 0,105,209, 0,104,210, 0,103,211, 0,103,211, 0, + 104,210, 0,105,209, 0,103,212, 0, 99,215, 0, 96,219, 0, + 95,220, 0, 95,220, 0, 95,219, 0, 97,217, 0,101,214, 0, + 105,209, 0,110,202, 0,113,198, 0,111,201, 0,108,205, 0, + 107,206, 0,108,206, 0,110,203, 0,112,199, 0,115,194, 0, + 117,190, 0,119,186, 0,120,184, 0,121,182, 0,120,182, 0, + 121,182, 0,121,179, 0,122,175, 0,123,174, 1,123,171, 3, + 124,165, 8,124,154, 18,124,149, 24,123,141, 34,124,143, 31, + 124,145, 29,124,147, 26,124,143, 31,124,147, 26,124,160, 12, + 124,166, 7,123,173, 1,122,178, 0,122,178, 0,122,178, 0, + 121,182, 0,117,191, 0,113,198, 0,110,202, 0,109,203, 0, + 110,202, 0,112,200, 0,115,195, 0,117,190, 0,120,184, 0, + 122,175, 0,124,167, 6,123,171, 3,123,171, 3,124,166, 7, + 124,158, 13,124,155, 16,124,154, 18,124,157, 15,124,160, 12, + 124,164, 9,124,165, 8,124,164, 9,124,157, 15,124,143, 31, + 122,132, 48,121,127, 58,121,125, 63,121,127, 58,122,135, 44, + 124,143, 31,124,152, 20,124,157, 15,124,155, 16,124,150, 22, + 124,150, 22,124,166, 7,122,176, 0,120,182, 0,120,184, 0, + 120,183, 0,122,178, 0,123,171, 3,124,162, 10,124,154, 18, + 124,143, 31,122,135, 44,121,125, 63,115,107,129,111, 96,248, + 114,104,197,113,100,242,111, 96,248,107, 89,252, 94, 70,242, + 30, 55,222, 30, 37,192, 30, 31,180, 87, 65,237,107, 89,252, + 113,100,242,115,107,129,115,107,129,113,100,242,107, 89,252, + 111, 96,248,121,125, 63,123,141, 34,124,150, 22,124,155, 16, + 124,154, 18,124,149, 24,123,139, 37,121,125, 63,117,110,109, + 120,122, 70,122,132, 48,123,137, 41,123,139, 37,123,141, 34, + 124,145, 29,123,141, 34,120,122, 70,118,117, 85,123,141, 34, + 124,155, 16,124,164, 9,124,166, 7,124,162, 10,124,150, 22, + 123,141, 34,124,152, 20,124,165, 8,122,176, 0,121,182, 0, + 119,186, 0,118,189, 0,117,191, 0,116,193, 0,115,195, 0, + 114,196, 0,114,197, 0,113,198, 0,113,198, 0,114,197, 0, + 115,194, 0,118,189, 0,121,181, 0,123,168, 5,124,155, 16, + 124,152, 20,124,143, 31,122,132, 48,118,117, 85,115,107,129, + 124,143, 31,123,169, 4,119,185, 0,114,196, 0,109,204, 0, + 105,209, 0,102,212, 0,101,213, 0,102,212, 0,104,210, 0, + 107,207, 0,106,207, 0,105,209, 0,105,209, 0,107,207, 0, + 111,201, 0,116,193, 0,117,191, 0,118,188, 0,117,190, 0, + 118,189, 0,120,184, 0,122,176, 0,123,169, 4,124,161, 11, + 124,150, 22,122,135, 44,115,107,129,114,104,197,122,135, 44, + 124,149, 24,124,160, 12,123,168, 5,122,176, 0,121,182, 0, + 119,186, 0,118,189, 0,118,189, 0,118,188, 0,117,192, 0, + 114,197, 0,110,202, 0,107,206, 0,105,209, 0,102,212, 0, + 101,213, 0,102,212, 0,103,211, 0,105,209, 0,108,206, 0, + 110,202, 0,112,200, 0,112,200, 0,114,197, 0,116,193, 0, + 118,189, 0,119,186, 0,121,181, 0,123,173, 1,124,165, 8, + 123,169, 4,123,174, 1,121,180, 0,120,184, 0,118,188, 0, + 118,189, 0,118,188, 0,119,186, 0,120,184, 0,119,186, 0, + 119,186, 0,120,184, 0,122,178, 0,122,176, 0,121,179, 0, + 120,182, 0,119,185, 0,119,186, 0,119,186, 0,120,184, 0, + 120,183, 0,120,183, 0,120,184, 0,119,186, 0,118,189, 0, + 117,192, 0,116,192, 0,116,193, 0,114,196, 0,113,198, 0, + 112,200, 0,111,201, 0,110,203, 0,108,205, 0,106,207, 0, + 105,209, 0,105,209, 0,105,209, 0,105,209, 0,101,214, 0, + 97,217, 0, 96,219, 0, 96,219, 0, 96,219, 0, 97,218, 0, + 99,215, 0,103,212, 0,107,206, 0,113,199, 0,110,202, 0, + 107,206, 0,106,207, 0,107,206, 0,109,203, 0,112,199, 0, + 114,196, 0,116,193, 0,118,188, 0,119,185, 0,120,182, 0, + 120,183, 0,121,182, 0,122,178, 0,123,173, 1,123,174, 1, + 123,171, 3,124,164, 9,124,154, 18,124,154, 18,124,150, 22, + 123,139, 37,124,143, 31,124,143, 31,123,141, 34,124,155, 16, + 123,168, 5,123,174, 1,122,175, 0,123,171, 3,123,174, 1, + 123,174, 1,123,174, 1,119,186, 0,116,193, 0,113,198, 0, + 112,199, 0,113,198, 0,115,195, 0,117,191, 0,119,186, 0, + 121,180, 0,122,175, 0,122,175, 0,122,178, 0,122,177, 0, + 123,171, 3,124,162, 10,124,157, 15,124,161, 11,124,161, 11, + 124,158, 13,124,162, 10,124,165, 8,124,166, 7,124,164, 9, + 124,154, 18,122,130, 53,107, 89,252,109, 92,251,119,119, 77, + 122,130, 53,122,130, 53,121,125, 63,123,137, 41,123,141, 34, + 123,139, 37,122,132, 48,124,145, 29,124,161, 11,123,169, 4, + 123,174, 1,123,172, 2,124,165, 8,124,154, 18,124,155, 16, + 124,154, 18,123,141, 34,117,110,109,105, 84,252, 87, 65,237, + 111, 96,248,119,119, 77,121,127, 58,121,127, 58,119,119, 77, + 115,107,129,107, 89,252, 99, 75,247, 94, 70,242,109, 92,251, + 115,107,129,117,110,109,117,110,109,115,107,129,111, 96,248, + 102, 80,250,102, 80,250,118,117, 85,123,139, 37,124,152, 20, + 124,157, 15,124,157, 15,124,150, 22,123,139, 37,120,122, 70, + 117,110,109,113,100,242,115,107,129,119,119, 77,121,127, 58, + 122,135, 44,123,139, 37,122,135, 44,119,119, 77,117,110,109, + 119,119, 77,123,139, 37,124,150, 22,124,154, 18,124,150, 22, + 123,137, 41,124,149, 24,124,160, 12,124,164, 9,124,166, 7, + 123,172, 2,122,175, 0,122,177, 0,121,179, 0,121,181, 0, + 120,182, 0,119,187, 0,117,191, 0,117,191, 0,117,192, 0, + 116,193, 0,116,192, 0,118,188, 0,121,180, 0,124,167, 6, + 124,147, 26,122,135, 44,121,127, 58,117,110,109,105, 84,252, + 118,117, 85,124,150, 22,124,166, 7,121,181, 0,117,191, 0, + 112,199, 0,109,204, 0,106,208, 0,105,209, 0,105,209, 0, + 107,207, 0,109,203, 0,113,199, 0,112,200, 0,111,202, 0, + 112,200, 0,115,194, 0,119,185, 0,120,183, 0,118,188, 0, + 117,190, 0,118,189, 0,120,184, 0,122,175, 0,123,169, 4, + 124,157, 15,124,145, 29,121,127, 58,114,104,197,115,107,129, + 122,130, 53,124,147, 26,124,160, 12,123,170, 3,122,178, 0, + 120,184, 0,118,188, 0,117,190, 0,117,190, 0,119,187, 0, + 120,183, 0,118,189, 0,115,195, 0,113,198, 0,112,199, 0, + 110,203, 0,108,205, 0,108,205, 0,109,204, 0,111,202, 0, + 113,199, 0,114,196, 0,114,197, 0,114,197, 0,115,194, 0, + 117,191, 0,118,189, 0,119,187, 0,120,183, 0,122,176, 0, + 123,169, 4,124,166, 7,123,168, 5,122,176, 0,120,183, 0, + 119,187, 0,118,189, 0,118,189, 0,119,187, 0,120,183, 0, + 120,183, 0,120,184, 0,120,182, 0,122,178, 0,123,171, 3, + 123,169, 4,123,172, 2,123,174, 1,122,175, 0,123,173, 1, + 123,174, 1,121,180, 0,120,183, 0,120,184, 0,121,182, 0, + 120,184, 0,118,188, 0,118,189, 0,118,189, 0,118,188, 0, + 118,188, 0,118,189, 0,117,192, 0,115,194, 0,113,198, 0, + 111,202, 0,108,205, 0,107,207, 0,106,208, 0,106,208, 0, + 103,211, 0,100,214, 0, 99,216, 0, 98,217, 0, 97,217, 0, + 97,218, 0, 98,217, 0,100,214, 0,104,210, 0,109,204, 0, + 110,202, 0,107,207, 0,106,207, 0,107,207, 0,109,204, 0, + 111,201, 0,112,200, 0,114,197, 0,117,191, 0,119,187, 0, + 120,184, 0,120,183, 0,121,181, 0,122,177, 0,123,170, 3, + 123,169, 4,124,165, 8,124,155, 16,124,157, 15,124,158, 13, + 124,158, 13,124,152, 20,123,141, 34,123,137, 41,123,141, 34, + 124,161, 11,123,173, 1,121,179, 0,121,182, 0,121,179, 0, + 123,173, 1,123,169, 4,123,169, 4,121,181, 0,118,188, 0, + 116,192, 0,115,194, 0,116,192, 0,118,189, 0,120,184, 0, + 121,182, 0,121,180, 0,122,178, 0,120,183, 0,120,184, 0, + 120,183, 0,122,177, 0,124,166, 7,124,158, 13,124,167, 6, + 123,171, 3,123,170, 3,124,165, 8,124,162, 10,124,165, 8, + 124,164, 9,124,155, 16,122,135, 44,121,125, 63,121,127, 58, + 122,130, 53,122,135, 44,122,130, 53,118,114, 96,114,104,197, + 118,117, 85,119,119, 77,119,119, 77,118,117, 85,122,135, 44, + 124,149, 24,124,155, 16,124,154, 18,123,141, 34,124,155, 16, + 124,160, 12,124,158, 13,124,147, 26,118,117, 85, 69, 60,230, + 30, 37,192,114,104,197,122,130, 53,123,139, 37,123,141, 34, + 122,135, 44,120,122, 70,114,104,197,109, 92,251,105, 84,252, + 114,104,197,119,119, 77,121,125, 63,120,122, 70,118,114, 96, + 109, 92,251, 30, 49,213, 30, 55,222,113,100,242,122,132, 48, + 124,149, 24,124,155, 16,124,157, 15,124,152, 20,123,139, 37, + 123,137, 41,123,139, 37,122,135, 44,120,122, 70,115,107,129, + 117,110,109,118,117, 85,120,122, 70,119,119, 77,115,107,129, + 114,104,197,118,114, 96,119,119, 77,121,127, 58,122,132, 48, + 121,127, 58,122,135, 44,124,154, 18,124,164, 9,124,167, 6, + 124,165, 8,124,157, 15,124,154, 18,124,155, 16,124,158, 13, + 123,168, 5,121,180, 0,119,187, 0,117,191, 0,117,191, 0, + 118,188, 0,118,188, 0,118,189, 0,119,186, 0,121,179, 0, + 124,166, 7,123,141, 34,119,119, 77,111, 96,248, 99, 75,247, + 99, 75,247,122,130, 53,124,160, 12,123,173, 1,121,181, 0, + 120,184, 0,117,192, 0,114,197, 0,111,201, 0,109,203, 0, + 109,204, 0,109,203, 0,112,200, 0,115,195, 0,118,189, 0, + 117,192, 0,117,191, 0,119,185, 0,121,182, 0,119,185, 0, + 118,189, 0,117,190, 0,118,189, 0,120,183, 0,121,179, 0, + 122,175, 0,124,164, 9,123,141, 34,118,114, 96,117,110,109, + 118,114, 96,118,117, 85,123,139, 37,124,157, 15,123,169, 4, + 122,178, 0,120,184, 0,118,188, 0,118,189, 0,118,188, 0, + 120,184, 0,118,188, 0,117,191, 0,114,196, 0,113,198, 0, + 114,197, 0,115,194, 0,115,194, 0,115,195, 0,115,194, 0, + 116,193, 0,117,191, 0,117,191, 0,116,192, 0,116,193, 0, + 117,191, 0,118,188, 0,118,189, 0,118,188, 0,119,185, 0, + 121,179, 0,123,170, 3,124,166, 7,124,155, 16,123,168, 5, + 122,178, 0,120,184, 0,118,188, 0,118,189, 0,118,188, 0, + 120,184, 0,122,178, 0,121,179, 0,122,178, 0,123,174, 1, + 123,168, 5,124,161, 11,124,157, 15,124,161, 11,124,158, 13, + 123,168, 5,122,177, 0,120,182, 0,119,186, 0,119,187, 0, + 119,186, 0,120,184, 0,121,182, 0,120,184, 0,119,185, 0, + 119,185, 0,118,188, 0,117,190, 0,117,191, 0,117,191, 0, + 118,189, 0,115,195, 0,112,200, 0,109,204, 0,107,207, 0, + 105,209, 0,104,210, 0,103,212, 0,101,213, 0,100,214, 0, + 98,216, 0, 97,218, 0, 97,218, 0, 98,217, 0,101,214, 0, + 105,209, 0,110,202, 0,107,206, 0,106,207, 0,107,207, 0, + 109,204, 0,111,202, 0,111,201, 0,113,198, 0,117,192, 0, + 117,191, 0,118,188, 0,119,185, 0,121,181, 0,122,177, 0, + 123,169, 4,124,158, 13,124,145, 29,124,149, 24,124,155, 16, + 124,161, 11,124,162, 10,124,162, 10,124,157, 15,124,145, 29, + 124,147, 26,124,165, 8,122,176, 0,120,183, 0,119,186, 0, + 119,185, 0,121,180, 0,123,172, 2,124,162, 10,122,177, 0, + 120,184, 0,118,188, 0,118,188, 0,119,186, 0,120,184, 0, + 121,182, 0,121,181, 0,120,184, 0,118,188, 0,117,191, 0, + 117,191, 0,118,189, 0,120,184, 0,123,173, 1,124,155, 16, + 124,167, 6,123,173, 1,122,175, 0,123,173, 1,123,169, 4, + 124,164, 9,124,160, 12,124,154, 18,124,155, 16,124,160, 12, + 124,161, 11,124,158, 13,124,149, 24,122,130, 53,114,104,197, + 69, 60,230,105, 84,252,109, 92,251,113,100,242,114,104,197, + 114,104,197,119,119, 77,122,130, 53,121,127, 58,124,145, 29, + 124,157, 15,124,164, 9,124,162, 10,124,157, 15,123,139, 37, + 113,100,242, 30, 31,180,113,100,242,122,130, 53,123,141, 34, + 123,141, 34,122,135, 44,120,122, 70,115,107,129,111, 96,248, + 107, 89,252,111, 96,248,117,110,109,118,117, 85,118,114, 96, + 114,104,197, 99, 75,247, 30, 26,168, 69, 60,230,111, 96,248, + 120,122, 70,123,141, 34,124,152, 20,124,155, 16,124,150, 22, + 123,139, 37,124,150, 22,124,154, 18,124,150, 22,123,139, 37, + 121,125, 63,114,104,197,109, 92,251,102, 80,250,105, 84,252, + 105, 84,252,113,100,242,118,114, 96,119,119, 77,118,117, 85, + 114,104,197,113,100,242,122,135, 44,124,155, 16,124,165, 8, + 124,167, 6,124,164, 9,124,152, 20,122,135, 44,118,114, 96, + 124,143, 31,124,166, 7,121,179, 0,119,186, 0,117,190, 0, + 117,190, 0,119,187, 0,120,182, 0,120,184, 0,120,183, 0, + 122,177, 0,124,166, 7,124,145, 29,115,107,129, 30, 55,222, + 30, 10,132,109, 92,251,124,143, 31,124,167, 6,122,178, 0, + 119,185, 0,118,188, 0,118,189, 0,118,189, 0,116,193, 0, + 114,197, 0,113,199, 0,113,198, 0,114,196, 0,117,191, 0, + 119,185, 0,122,178, 0,120,182, 0,120,183, 0,120,184, 0, + 118,188, 0,117,191, 0,117,191, 0,118,189, 0,120,182, 0, + 120,182, 0,122,178, 0,123,169, 4,124,150, 22,118,114, 96, + 117,110,109,117,110,109,111, 96,248,123,141, 34,124,160, 12, + 123,170, 3,122,175, 0,121,181, 0,119,185, 0,119,187, 0, + 119,186, 0,117,190, 0,115,194, 0,114,196, 0,114,197, 0, + 114,196, 0,115,194, 0,117,190, 0,120,183, 0,118,188, 0, + 118,188, 0,119,185, 0,120,182, 0,120,183, 0,119,186, 0, + 119,186, 0,120,184, 0,118,188, 0,117,190, 0,117,190, 0, + 118,188, 0,120,184, 0,122,177, 0,124,167, 6,123,171, 3, + 123,169, 4,123,170, 3,122,176, 0,120,182, 0,119,185, 0, + 119,185, 0,120,182, 0,122,176, 0,123,172, 2,123,171, 3, + 124,167, 6,124,165, 8,124,167, 6,123,169, 4,123,170, 3, + 123,172, 2,122,176, 0,121,179, 0,120,182, 0,119,186, 0, + 118,188, 0,118,188, 0,119,186, 0,119,185, 0,119,186, 0, + 118,188, 0,117,191, 0,116,193, 0,114,196, 0,113,198, 0, + 113,198, 0,114,197, 0,115,195, 0,114,197, 0,113,199, 0, + 109,204, 0,106,208, 0,103,211, 0,101,213, 0, 99,215, 0, + 98,217, 0, 98,216, 0, 96,219, 0, 95,220, 0, 95,219, 0, + 97,217, 0,101,213, 0,106,207, 0,108,205, 0,107,206, 0, + 107,206, 0,108,205, 0,110,202, 0,112,200, 0,114,197, 0, + 114,196, 0,114,196, 0,115,194, 0,117,191, 0,119,187, 0, + 121,181, 0,123,174, 1,124,167, 6,124,165, 8,124,164, 9, + 124,160, 12,124,160, 12,124,166, 7,123,168, 5,124,167, 6, + 123,168, 5,123,172, 2,123,171, 3,122,177, 0,120,184, 0, + 119,187, 0,119,186, 0,120,182, 0,122,175, 0,123,174, 1, + 121,180, 0,120,184, 0,119,187, 0,119,187, 0,119,186, 0, + 120,183, 0,119,186, 0,117,190, 0,116,192, 0,115,195, 0, + 114,197, 0,114,197, 0,115,194, 0,118,189, 0,121,182, 0, + 123,168, 5,124,161, 11,123,169, 4,123,173, 1,122,175, 0, + 123,174, 1,123,171, 3,123,169, 4,123,168, 5,123,170, 3, + 123,173, 1,123,174, 1,123,173, 1,124,167, 6,124,157, 15, + 123,137, 41,118,114, 96,117,110,109,117,110,109,109, 92,251, + 105, 84,252,109, 92,251,113,100,242,117,110,109,121,125, 63, + 124,143, 31,124,160, 12,123,168, 5,123,169, 4,124,164, 9, + 124,150, 22,120,122, 70, 99, 75,247,111, 96,248,121,125, 63, + 122,135, 44,122,135, 44,122,130, 53,123,139, 37,123,141, 34, + 123,137, 41,121,125, 63,115,107,129,115,107,129,115,107,129, + 115,107,129,114,104,197,109, 92,251,115,107,129,118,117, 85, + 118,117, 85,122,135, 44,124,147, 26,124,150, 22,124,152, 20, + 124,149, 24,124,150, 22,124,160, 12,124,161, 11,124,157, 15, + 124,147, 26,122,130, 53,122,132, 48,122,135, 44,122,132, 48, + 121,125, 63,119,119, 77,117,110,109,117,110,109,118,117, 85, + 118,117, 85,114,104,197,113,100,242,121,127, 58,124,150, 22, + 124,160, 12,124,162, 10,124,158, 13,124,147, 26,122,130, 53, + 123,137, 41,123,139, 37,124,157, 15,123,173, 1,120,182, 0, + 119,186, 0,118,188, 0,119,185, 0,121,181, 0,121,180, 0, + 121,179, 0,122,176, 0,124,167, 6,124,150, 22,120,122, 70, + 99, 75,247, 30, 37,192,114,104,197,124,147, 26,123,168, 5, + 121,179, 0,119,185, 0,118,188, 0,118,189, 0,118,188, 0, + 119,186, 0,118,188, 0,117,191, 0,117,191, 0,117,190, 0, + 118,188, 0,118,188, 0,119,186, 0,120,184, 0,119,186, 0, + 118,188, 0,117,191, 0,117,192, 0,117,191, 0,118,188, 0, + 120,184, 0,120,184, 0,121,181, 0,123,172, 2,124,155, 16, + 123,139, 37,122,132, 48,121,125, 63,121,125, 63,124,152, 20, + 124,167, 6,122,175, 0,121,179, 0,120,182, 0,120,184, 0, + 119,186, 0,118,189, 0,116,193, 0,114,197, 0,112,199, 0, + 112,200, 0,113,199, 0,114,196, 0,117,192, 0,118,188, 0, + 119,186, 0,119,185, 0,120,183, 0,121,179, 0,123,173, 1, + 123,174, 1,122,178, 0,120,182, 0,119,187, 0,117,191, 0, + 117,192, 0,117,191, 0,118,189, 0,120,184, 0,122,178, 0, + 120,182, 0,122,177, 0,122,175, 0,123,173, 1,123,170, 3, + 122,176, 0,122,178, 0,122,176, 0,123,171, 3,124,164, 9, + 124,161, 11,124,166, 7,123,170, 3,123,172, 2,122,175, 0, + 122,177, 0,122,178, 0,121,182, 0,120,184, 0,119,186, 0, + 119,186, 0,118,189, 0,118,189, 0,118,188, 0,118,188, 0, + 118,189, 0,117,191, 0,115,195, 0,113,199, 0,111,202, 0, + 109,204, 0,108,205, 0,109,204, 0,110,202, 0,112,200, 0, + 111,201, 0,111,202, 0,108,205, 0,105,209, 0,102,213, 0, + 99,216, 0, 97,218, 0, 97,218, 0, 95,220, 0, 93,222, 0, + 92,222, 0, 94,221, 0, 97,218, 0,101,213, 0,106,208, 0, + 108,205, 0,109,203, 0,110,203, 0,110,202, 0,111,201, 0, + 112,200, 0,112,200, 0,112,200, 0,113,198, 0,114,196, 0, + 116,192, 0,118,188, 0,120,182, 0,122,178, 0,122,177, 0, + 122,177, 0,123,172, 2,124,165, 8,124,167, 6,123,172, 2, + 122,175, 0,120,184, 0,119,187, 0,119,186, 0,120,183, 0, + 121,182, 0,120,184, 0,120,184, 0,121,181, 0,122,178, 0, + 120,184, 0,119,187, 0,118,189, 0,118,189, 0,118,188, 0, + 119,185, 0,118,188, 0,116,193, 0,114,196, 0,114,197, 0, + 113,199, 0,112,199, 0,113,199, 0,114,197, 0,116,192, 0, + 119,186, 0,122,177, 0,124,164, 9,124,164, 9,123,170, 3, + 123,174, 1,122,176, 0,122,176, 0,122,176, 0,122,175, 0, + 122,177, 0,121,180, 0,121,182, 0,121,182, 0,122,178, 0, + 123,171, 3,124,161, 11,124,147, 26,122,135, 44,123,137, 41, + 122,130, 53,117,110,109,102, 80,250,111, 96,248,115,107,129, + 121,125, 63,124,149, 24,124,162, 10,123,168, 5,123,170, 3, + 124,166, 7,124,155, 16,122,135, 44,111, 96,248,111, 96,248, + 119,119, 77,121,125, 63,122,130, 53,124,145, 29,124,157, 15, + 124,161, 11,124,161, 11,124,155, 16,124,149, 24,124,143, 31, + 123,141, 34,122,135, 44,122,130, 53,122,135, 44,124,143, 31, + 124,147, 26,124,145, 29,124,149, 24,124,158, 13,124,160, 12, + 124,155, 16,124,145, 29,124,158, 13,124,166, 7,124,166, 7, + 124,161, 11,124,150, 22,124,143, 31,124,152, 20,124,157, 15, + 124,155, 16,124,150, 22,123,141, 34,122,130, 53,117,110,109, + 117,110,109,117,110,109,117,110,109,120,122, 70,123,137, 41, + 124,143, 31,124,152, 20,124,157, 15,124,154, 18,124,147, 26, + 124,147, 26,124,152, 20,124,154, 18,124,152, 20,124,158, 13, + 123,172, 2,121,179, 0,121,181, 0,121,180, 0,122,177, 0, + 122,176, 0,122,177, 0,123,174, 1,124,167, 6,124,154, 18, + 122,132, 48,113,100,242, 87, 65,237,113,100,242,123,141, 34, + 124,164, 9,122,175, 0,121,182, 0,120,184, 0,119,186, 0, + 119,186, 0,120,183, 0,122,177, 0,121,179, 0,121,182, 0, + 119,187, 0,117,191, 0,116,192, 0,117,191, 0,118,189, 0, + 118,189, 0,117,191, 0,117,192, 0,117,192, 0,117,190, 0, + 119,186, 0,119,185, 0,120,184, 0,121,181, 0,123,173, 1, + 124,158, 13,124,152, 20,124,145, 29,123,137, 41,122,135, 44, + 124,160, 12,123,170, 3,122,178, 0,121,181, 0,120,184, 0, + 119,186, 0,118,188, 0,117,190, 0,116,193, 0,114,197, 0, + 112,200, 0,111,201, 0,111,201, 0,113,199, 0,114,196, 0, + 115,194, 0,117,192, 0,118,189, 0,119,185, 0,121,180, 0, + 123,173, 1,123,169, 4,123,172, 2,121,179, 0,119,186, 0, + 117,191, 0,116,193, 0,115,194, 0,116,193, 0,117,190, 0, + 119,186, 0,118,189, 0,119,186, 0,121,181, 0,122,175, 0, + 123,171, 3,124,167, 6,124,165, 8,124,165, 8,124,165, 8, + 124,166, 7,123,169, 4,123,173, 1,122,177, 0,122,178, 0, + 122,178, 0,121,179, 0,121,181, 0,120,183, 0,119,186, 0, + 119,187, 0,119,186, 0,118,188, 0,118,189, 0,118,189, 0, + 118,189, 0,117,190, 0,116,193, 0,113,198, 0,111,202, 0, + 108,205, 0,106,208, 0,104,210, 0,104,210, 0,106,208, 0, + 108,205, 0,109,204, 0,108,205, 0,109,204, 0,107,207, 0, + 103,211, 0,100,215, 0, 97,217, 0, 96,219, 0, 93,222, 0, + 91,224, 0, 90,225, 0, 90,224, 0, 92,222, 0, 96,219, 0, + 100,215, 0,103,211, 0,107,207, 0,110,202, 0,112,200, 0, + 112,200, 0,111,201, 0,111,202, 0,111,202, 0,111,201, 0, + 113,199, 0,115,195, 0,117,191, 0,119,187, 0,120,184, 0, + 120,184, 0,120,184, 0,121,181, 0,123,173, 1,124,166, 7, + 123,173, 1,119,185, 0,116,192, 0,114,196, 0,115,195, 0, + 116,192, 0,118,189, 0,119,186, 0,120,184, 0,120,184, 0, + 119,186, 0,118,189, 0,117,191, 0,117,192, 0,117,191, 0, + 118,188, 0,119,186, 0,116,193, 0,113,198, 0,112,200, 0, + 112,199, 0,112,200, 0,112,199, 0,113,198, 0,114,196, 0, + 116,193, 0,118,188, 0,121,182, 0,123,172, 2,123,171, 3, + 123,171, 3,123,173, 1,122,177, 0,122,178, 0,121,179, 0, + 121,179, 0,121,181, 0,120,184, 0,119,186, 0,119,186, 0, + 120,184, 0,121,181, 0,123,174, 1,124,165, 8,124,152, 20, + 124,157, 15,124,154, 18,124,143, 31,120,122, 70,107, 89,252, + 113,100,242,121,127, 58,124,147, 26,124,160, 12,124,166, 7, + 124,167, 6,124,164, 9,124,155, 16,123,141, 34,122,132, 48, + 121,125, 63,118,114, 96,118,117, 85,122,135, 44,124,152, 20, + 124,164, 9,123,170, 3,123,171, 3,123,170, 3,123,168, 5, + 124,165, 8,124,162, 10,124,158, 13,124,157, 15,124,157, 15, + 124,160, 12,124,161, 11,124,158, 13,124,162, 10,123,168, 5, + 123,169, 4,124,164, 9,124,158, 13,124,162, 10,123,168, 5, + 123,168, 5,124,162, 10,124,150, 22,124,152, 20,124,161, 11, + 124,166, 7,124,166, 7,124,161, 11,124,150, 22,123,137, 41, + 118,117, 85,113,100,242,118,114, 96,121,127, 58,123,139, 37, + 124,147, 26,124,150, 22,124,149, 24,124,147, 26,124,149, 24, + 124,152, 20,124,160, 12,124,161, 11,124,160, 12,124,158, 13, + 124,155, 16,124,152, 20,124,165, 8,123,170, 3,123,171, 3, + 123,169, 4,123,171, 3,123,174, 1,123,172, 2,124,167, 6, + 124,155, 16,123,139, 37,118,114, 96,105, 84,252,113,100,242, + 120,122, 70,124,150, 22,124,165, 8,123,172, 2,122,176, 0, + 122,178, 0,121,179, 0,122,177, 0,123,169, 4,124,164, 9, + 121,180, 0,118,189, 0,115,194, 0,114,196, 0,115,194, 0, + 117,192, 0,117,191, 0,117,191, 0,117,191, 0,117,191, 0, + 118,188, 0,120,184, 0,120,184, 0,120,183, 0,121,180, 0, + 123,172, 2,124,161, 11,124,157, 15,124,149, 24,123,139, 37, + 124,145, 29,124,162, 10,123,172, 2,122,178, 0,121,181, 0, + 120,183, 0,119,186, 0,119,187, 0,118,189, 0,117,191, 0, + 115,195, 0,113,198, 0,112,200, 0,111,201, 0,112,200, 0, + 112,199, 0,113,198, 0,114,196, 0,116,193, 0,118,189, 0, + 120,182, 0,123,173, 1,123,171, 3,123,169, 4,123,174, 1, + 120,182, 0,118,189, 0,116,193, 0,115,195, 0,115,195, 0, + 115,194, 0,117,192, 0,117,192, 0,117,190, 0,119,187, 0, + 120,184, 0,121,179, 0,122,176, 0,123,172, 2,123,171, 3, + 123,172, 2,122,175, 0,121,179, 0,120,182, 0,119,185, 0, + 119,185, 0,120,184, 0,121,180, 0,121,180, 0,120,182, 0, + 120,184, 0,119,186, 0,120,184, 0,118,188, 0,118,189, 0, + 118,188, 0,118,188, 0,118,189, 0,116,193, 0,113,198, 0, + 110,203, 0,107,207, 0,104,210, 0,102,213, 0,101,213, 0, + 103,212, 0,106,208, 0,107,207, 0,106,208, 0,107,207, 0, + 108,205, 0,106,208, 0,102,212, 0, 99,216, 0, 95,220, 0, + 91,223, 0, 89,226, 0, 87,227, 0, 87,227, 0, 89,225, 0, + 91,223, 0, 94,220, 0, 97,217, 0,101,214, 0,105,209, 0, + 110,202, 0,112,200, 0,112,200, 0,111,202, 0,110,202, 0, + 111,201, 0,113,199, 0,114,196, 0,117,192, 0,118,188, 0, + 119,186, 0,119,187, 0,118,188, 0,119,185, 0,121,179, 0, + 123,168, 5,122,178, 0,118,189, 0,114,197, 0,112,200, 0, + 112,200, 0,113,198, 0,115,194, 0,117,191, 0,118,188, 0, + 118,188, 0,118,189, 0,117,191, 0,116,193, 0,116,193, 0, + 117,191, 0,119,186, 0,118,189, 0,114,196, 0,112,199, 0, + 112,200, 0,113,199, 0,114,197, 0,114,196, 0,115,194, 0, + 116,192, 0,117,190, 0,119,187, 0,120,182, 0,122,177, 0, + 122,178, 0,122,178, 0,122,178, 0,122,178, 0,121,181, 0, + 121,182, 0,121,182, 0,120,182, 0,119,185, 0,119,187, 0, + 118,189, 0,118,188, 0,119,186, 0,121,182, 0,122,175, 0, + 124,166, 7,123,170, 3,123,169, 4,124,164, 9,124,149, 24, + 119,119, 77,111, 96,248,120,122, 70,123,139, 37,124,152, 20, + 124,158, 13,124,160, 12,124,160, 12,124,157, 15,124,158, 13, + 124,155, 16,124,149, 24,123,139, 37,120,122, 70,122,135, 44, + 124,150, 22,124,164, 9,123,171, 3,123,174, 1,122,175, 0, + 122,176, 0,122,176, 0,123,174, 1,123,172, 2,123,169, 4, + 124,167, 6,123,168, 5,124,167, 6,124,166, 7,122,175, 0, + 122,178, 0,122,177, 0,123,171, 3,124,166, 7,123,170, 3, + 123,168, 5,124,167, 6,124,160, 12,124,147, 26,124,154, 18, + 124,164, 9,123,168, 5,123,168, 5,124,164, 9,124,152, 20, + 124,149, 24,124,143, 31,121,127, 58,123,137, 41,124,143, 31, + 124,149, 24,124,152, 20,124,154, 18,124,155, 16,124,158, 13, + 124,160, 12,124,164, 9,124,166, 7,124,165, 8,124,164, 9, + 124,161, 11,124,158, 13,124,150, 22,123,139, 37,124,154, 18, + 124,158, 13,124,158, 13,123,168, 5,123,171, 3,123,171, 3, + 124,166, 7,124,157, 15,123,141, 34,119,119, 77,113,100,242, + 107, 89,252,113,100,242,120,122, 70,124,143, 31,124,154, 18, + 124,160, 12,124,164, 9,124,167, 6,124,166, 7,123,170, 3, + 123,172, 2,121,182, 0,117,191, 0,114,196, 0,113,198, 0, + 114,196, 0,116,193, 0,117,191, 0,117,191, 0,117,190, 0, + 118,188, 0,120,184, 0,121,182, 0,121,181, 0,121,179, 0, + 122,176, 0,123,168, 5,124,162, 10,124,158, 13,124,149, 24, + 123,137, 41,124,152, 20,124,165, 8,123,171, 3,122,177, 0, + 120,183, 0,119,186, 0,118,188, 0,118,189, 0,118,189, 0, + 118,188, 0,117,191, 0,115,194, 0,114,197, 0,113,199, 0, + 112,200, 0,112,200, 0,112,199, 0,113,198, 0,114,196, 0, + 117,191, 0,119,185, 0,122,175, 0,123,171, 3,123,170, 3, + 123,169, 4,123,174, 1,120,184, 0,118,189, 0,116,193, 0, + 115,194, 0,115,194, 0,116,193, 0,117,190, 0,117,190, 0, + 118,189, 0,118,188, 0,119,187, 0,119,185, 0,120,183, 0, + 121,182, 0,121,181, 0,121,181, 0,119,186, 0,118,189, 0, + 117,191, 0,117,191, 0,118,188, 0,120,183, 0,122,177, 0, + 121,179, 0,121,182, 0,120,182, 0,121,181, 0,119,185, 0, + 119,187, 0,119,186, 0,119,186, 0,118,188, 0,117,191, 0, + 114,197, 0,110,202, 0,107,207, 0,104,210, 0,101,213, 0, + 101,214, 0,102,212, 0,105,209, 0,105,209, 0,104,210, 0, + 105,209, 0,107,207, 0,109,204, 0,105,209, 0, 99,215, 0, + 94,220, 0, 91,224, 0, 88,226, 0, 86,228, 0, 86,228, 0, + 86,228, 0, 88,226, 0, 90,225, 0, 92,222, 0, 95,219, 0, + 100,215, 0,106,208, 0,111,202, 0,112,200, 0,112,199, 0, + 112,200, 0,113,198, 0,114,196, 0,116,193, 0,118,189, 0, + 119,186, 0,119,185, 0,119,186, 0,118,188, 0,119,187, 0, + 120,182, 0,122,178, 0,121,180, 0,117,191, 0,113,198, 0, + 111,201, 0,111,201, 0,112,199, 0,114,196, 0,116,192, 0, + 117,190, 0,118,188, 0,118,188, 0,117,191, 0,116,192, 0, + 117,192, 0,118,189, 0,120,184, 0,117,190, 0,114,196, 0, + 113,198, 0,113,198, 0,115,195, 0,116,192, 0,118,189, 0, + 119,187, 0,119,185, 0,120,184, 0,120,183, 0,121,180, 0, + 121,180, 0,121,182, 0,120,182, 0,120,182, 0,121,182, 0, + 121,182, 0,120,183, 0,120,184, 0,120,184, 0,119,185, 0, + 118,188, 0,118,189, 0,117,190, 0,118,189, 0,119,186, 0, + 121,182, 0,122,176, 0,121,179, 0,121,179, 0,122,175, 0, + 124,164, 9,123,139, 37,115,107,129,115,107,129,121,125, 63, + 123,137, 41,124,152, 20,124,165, 8,123,171, 3,123,173, 1, + 123,172, 2,123,169, 4,124,164, 9,124,155, 16,124,145, 29, + 124,149, 24,124,160, 12,123,168, 5,123,174, 1,122,178, 0, + 121,179, 0,121,181, 0,121,180, 0,121,180, 0,122,178, 0, + 122,176, 0,123,173, 1,123,172, 2,123,170, 3,122,178, 0, + 120,184, 0,119,186, 0,120,184, 0,122,178, 0,123,169, 4, + 123,172, 2,123,170, 3,124,162, 10,124,155, 16,124,143, 31, + 124,152, 20,124,161, 11,124,167, 6,124,167, 6,124,160, 12, + 124,161, 11,124,165, 8,124,162, 10,124,152, 20,124,152, 20, + 124,152, 20,124,154, 18,124,158, 13,123,169, 4,122,175, 0, + 122,178, 0,122,177, 0,123,173, 1,123,170, 3,124,167, 6, + 124,165, 8,124,162, 10,124,158, 13,124,154, 18,124,143, 31, + 121,127, 58,123,139, 37,124,147, 26,124,164, 9,123,168, 5, + 123,168, 5,124,164, 9,124,155, 16,124,147, 26,122,132, 48, + 117,110,109,111, 96,248, 99, 75,247, 87, 65,237,111, 96,248, + 118,114, 96,121,125, 63,124,145, 29,124,162, 10,123,173, 1, + 122,178, 0,121,180, 0,120,184, 0,117,192, 0,114,197, 0, + 113,198, 0,114,196, 0,116,192, 0,117,191, 0,118,189, 0, + 118,188, 0,119,185, 0,121,181, 0,122,176, 0,123,174, 1, + 123,173, 1,123,170, 3,124,161, 11,124,160, 12,124,155, 16, + 124,143, 31,124,147, 26,124,157, 15,124,165, 8,122,176, 0, + 120,183, 0,119,187, 0,118,189, 0,117,190, 0,117,190, 0, + 118,189, 0,118,188, 0,119,186, 0,118,189, 0,117,192, 0, + 115,194, 0,114,196, 0,114,197, 0,113,198, 0,114,197, 0, + 114,196, 0,116,192, 0,119,186, 0,122,178, 0,123,168, 5, + 123,168, 5,124,167, 6,124,166, 7,123,173, 1,121,182, 0, + 119,187, 0,118,189, 0,117,191, 0,117,191, 0,120,184, 0, + 119,186, 0,118,188, 0,117,190, 0,117,191, 0,117,191, 0, + 117,190, 0,118,188, 0,119,186, 0,119,186, 0,117,191, 0, + 115,194, 0,114,196, 0,115,194, 0,117,191, 0,120,184, 0, + 122,175, 0,123,174, 1,122,177, 0,122,177, 0,122,178, 0, + 120,183, 0,120,184, 0,120,183, 0,120,182, 0,120,184, 0, + 118,189, 0,116,193, 0,113,199, 0,109,204, 0,106,208, 0, + 103,211, 0,102,212, 0,103,211, 0,104,210, 0,102,212, 0, + 102,213, 0,103,211, 0,106,208, 0,110,203, 0,106,208, 0, + 99,215, 0, 94,221, 0, 91,224, 0, 88,226, 0, 86,228, 0, + 85,228, 0, 85,229, 0, 85,228, 0, 86,228, 0, 87,227, 0, + 90,224, 0, 95,220, 0,101,214, 0,108,205, 0,112,200, 0, + 114,197, 0,115,195, 0,116,193, 0,117,191, 0,119,187, 0, + 120,184, 0,121,181, 0,121,180, 0,120,183, 0,119,186, 0, + 119,186, 0,119,185, 0,119,187, 0,119,186, 0,118,189, 0, + 114,196, 0,112,200, 0,112,200, 0,113,198, 0,115,194, 0, + 117,191, 0,118,188, 0,119,186, 0,119,186, 0,118,188, 0, + 118,189, 0,118,188, 0,119,186, 0,120,184, 0,117,190, 0, + 115,194, 0,115,195, 0,116,193, 0,118,189, 0,119,186, 0, + 119,187, 0,119,185, 0,121,181, 0,123,174, 1,123,174, 1, + 123,174, 1,121,180, 0,120,183, 0,120,184, 0,120,184, 0, + 120,184, 0,120,184, 0,119,185, 0,119,187, 0,118,188, 0, + 119,186, 0,119,186, 0,118,189, 0,117,190, 0,117,190, 0, + 118,188, 0,120,184, 0,120,182, 0,119,186, 0,119,186, 0, + 120,182, 0,123,171, 3,124,152, 20,119,119, 77,102, 80,250, + 114,104,197,124,145, 29,124,167, 6,122,177, 0,121,182, 0, + 120,182, 0,121,180, 0,122,176, 0,123,170, 3,124,165, 8, + 124,160, 12,124,158, 13,124,164, 9,123,169, 4,123,174, 1, + 122,177, 0,121,180, 0,120,182, 0,120,182, 0,121,181, 0, + 121,181, 0,122,178, 0,122,176, 0,123,174, 1,121,179, 0, + 119,187, 0,117,192, 0,116,193, 0,117,191, 0,120,184, 0, + 123,172, 2,123,172, 2,123,169, 4,124,158, 13,124,145, 29, + 122,132, 48,124,145, 29,124,155, 16,124,160, 12,124,161, 11, + 124,160, 12,123,171, 3,122,176, 0,123,174, 1,124,166, 7, + 124,161, 11,124,160, 12,124,158, 13,123,169, 4,121,180, 0, + 119,186, 0,118,188, 0,119,187, 0,120,183, 0,122,175, 0, + 123,172, 2,123,173, 1,123,169, 4,124,161, 11,124,155, 16, + 124,149, 24,123,137, 41,118,117, 85,123,137, 41,124,157, 15, + 124,165, 8,124,165, 8,124,161, 11,124,158, 13,124,157, 15, + 124,149, 24,121,125, 63,117,110,109,109, 92,251, 87, 65,237, + 94, 70,242,113,100,242,121,125, 63,124,147, 26,124,166, 7, + 122,178, 0,120,183, 0,119,186, 0,119,186, 0,116,193, 0, + 114,197, 0,113,198, 0,115,194, 0,116,192, 0,117,192, 0, + 118,189, 0,119,186, 0,121,182, 0,122,177, 0,123,168, 5, + 124,164, 9,124,162, 10,124,160, 12,124,150, 22,124,152, 20, + 124,147, 26,124,152, 20,124,155, 16,124,160, 12,123,173, 1, + 120,182, 0,119,187, 0,118,189, 0,117,190, 0,118,189, 0, + 118,189, 0,118,188, 0,118,188, 0,119,185, 0,121,182, 0, + 120,184, 0,119,187, 0,118,189, 0,117,191, 0,116,193, 0, + 116,193, 0,116,193, 0,117,191, 0,119,187, 0,121,180, 0, + 124,167, 6,124,162, 10,124,161, 11,124,160, 12,124,157, 15, + 124,167, 6,122,176, 0,121,180, 0,120,183, 0,120,184, 0, + 123,174, 1,121,179, 0,120,184, 0,118,189, 0,117,192, 0, + 116,193, 0,116,193, 0,116,192, 0,118,189, 0,117,191, 0, + 115,195, 0,113,198, 0,113,198, 0,114,196, 0,117,191, 0, + 120,183, 0,123,172, 2,123,168, 5,123,170, 3,123,170, 3, + 122,176, 0,121,180, 0,121,181, 0,121,179, 0,122,178, 0, + 119,186, 0,117,190, 0,116,192, 0,115,194, 0,112,200, 0, + 109,204, 0,106,207, 0,105,209, 0,106,208, 0,102,212, 0, + 100,215, 0,100,215, 0,101,213, 0,105,209, 0,109,204, 0, + 107,207, 0,100,214, 0, 95,220, 0, 91,223, 0, 89,225, 0, + 85,229, 0, 83,230, 0, 84,229, 0, 85,229, 0, 84,229, 0, + 85,229, 0, 87,227, 0, 91,224, 0, 97,218, 0,104,210, 0, + 112,200, 0,115,195, 0,118,188, 0,119,187, 0,120,184, 0, + 121,179, 0,122,176, 0,122,175, 0,123,173, 1,122,176, 0, + 121,181, 0,120,183, 0,117,190, 0,116,193, 0,116,193, 0, + 117,191, 0,116,192, 0,115,195, 0,115,195, 0,116,193, 0, + 117,190, 0,119,186, 0,120,183, 0,121,180, 0,121,179, 0, + 121,182, 0,120,184, 0,120,184, 0,121,182, 0,120,184, 0, + 118,189, 0,117,191, 0,117,191, 0,118,188, 0,119,186, 0, + 118,189, 0,117,191, 0,118,189, 0,120,184, 0,122,176, 0, + 124,161, 11,123,170, 3,122,178, 0,121,182, 0,120,183, 0, + 120,184, 0,120,184, 0,120,184, 0,119,186, 0,118,188, 0, + 118,189, 0,118,188, 0,119,186, 0,118,188, 0,118,189, 0, + 117,190, 0,118,188, 0,120,184, 0,119,187, 0,117,190, 0, + 117,191, 0,119,186, 0,122,176, 0,124,158, 13,121,125, 63, + 94, 70,242,118,114, 96,124,155, 16,123,174, 1,120,183, 0, + 119,186, 0,119,186, 0,120,183, 0,122,178, 0,123,173, 1, + 123,170, 3,124,167, 6,124,166, 7,124,166, 7,123,168, 5, + 123,171, 3,123,174, 1,122,178, 0,121,182, 0,120,183, 0, + 121,181, 0,121,182, 0,121,180, 0,122,178, 0,122,175, 0, + 119,186, 0,116,193, 0,114,197, 0,113,198, 0,115,195, 0, + 118,188, 0,122,178, 0,123,169, 4,124,166, 7,124,154, 18, + 122,130, 53,118,117, 85,122,132, 48,124,143, 31,124,150, 22, + 124,150, 22,124,165, 8,122,177, 0,120,182, 0,121,182, 0, + 123,174, 1,124,167, 6,124,164, 9,124,160, 12,122,175, 0, + 119,186, 0,117,192, 0,115,194, 0,116,193, 0,118,189, 0, + 121,182, 0,122,176, 0,122,177, 0,123,174, 1,123,168, 5, + 124,158, 13,124,154, 18,124,147, 26,122,132, 48,119,119, 77, + 124,147, 26,124,158, 13,124,161, 11,124,158, 13,124,161, 11, + 124,162, 10,124,157, 15,123,141, 34,121,125, 63,117,110,109, + 107, 89,252,107, 89,252,120,122, 70,124,143, 31,124,155, 16, + 123,169, 4,121,181, 0,119,186, 0,118,189, 0,118,189, 0, + 115,194, 0,114,197, 0,114,197, 0,116,193, 0,116,193, 0, + 116,192, 0,118,188, 0,120,182, 0,122,178, 0,123,172, 2, + 124,161, 11,124,147, 26,124,145, 29,124,143, 31,122,135, 44, + 124,145, 29,124,157, 15,124,161, 11,124,161, 11,124,165, 8, + 122,178, 0,119,185, 0,118,189, 0,118,189, 0,118,189, 0, + 119,187, 0,119,185, 0,120,184, 0,120,184, 0,120,182, 0, + 121,180, 0,122,177, 0,122,176, 0,121,179, 0,120,182, 0, + 120,184, 0,119,186, 0,118,188, 0,118,188, 0,119,186, 0, + 121,181, 0,123,171, 3,124,155, 16,124,152, 20,124,149, 24, + 124,145, 29,123,137, 41,124,154, 18,124,164, 9,123,168, 5, + 123,171, 3,124,160, 12,123,169, 4,122,178, 0,119,186, 0, + 117,191, 0,116,193, 0,115,194, 0,116,193, 0,117,191, 0, + 115,194, 0,113,198, 0,112,200, 0,112,199, 0,115,195, 0, + 118,188, 0,122,178, 0,124,162, 10,124,164, 9,124,165, 8, + 124,167, 6,122,176, 0,121,179, 0,121,179, 0,122,177, 0, + 123,174, 1,120,184, 0,118,188, 0,117,191, 0,116,193, 0, + 115,194, 0,113,199, 0,110,202, 0,109,203, 0,105,209, 0, + 101,214, 0, 98,216, 0, 98,216, 0,100,215, 0,103,211, 0, + 108,206, 0,110,202, 0,103,211, 0, 98,217, 0, 93,221, 0, + 88,226, 0, 84,229, 0, 82,231, 0, 82,231, 0, 85,228, 0, + 84,229, 0, 83,230, 0, 84,229, 0, 88,226, 0, 93,221, 0, + 101,214, 0,109,204, 0,116,193, 0,119,186, 0,122,178, 0, + 122,175, 0,122,177, 0,122,178, 0,122,178, 0,122,175, 0, + 123,168, 5,122,175, 0,119,185, 0,116,193, 0,114,197, 0, + 113,198, 0,114,196, 0,116,193, 0,117,190, 0,117,190, 0, + 118,188, 0,119,186, 0,119,185, 0,120,183, 0,121,181, 0, + 122,178, 0,123,174, 1,122,177, 0,122,178, 0,121,180, 0, + 120,184, 0,119,187, 0,118,188, 0,119,186, 0,120,182, 0, + 119,187, 0,117,191, 0,116,192, 0,117,191, 0,119,186, 0, + 122,177, 0,124,166, 7,124,164, 9,123,173, 1,122,178, 0, + 121,180, 0,121,181, 0,120,184, 0,119,187, 0,119,187, 0, + 119,186, 0,119,187, 0,119,186, 0,119,186, 0,118,188, 0, + 118,189, 0,118,189, 0,119,187, 0,120,184, 0,118,189, 0, + 116,192, 0,116,193, 0,118,189, 0,122,178, 0,124,161, 11, + 122,130, 53, 94, 70,242,118,117, 85,124,157, 15,122,175, 0, + 120,183, 0,119,186, 0,119,185, 0,121,181, 0,122,176, 0, + 123,174, 1,123,171, 3,123,171, 3,123,172, 2,123,174, 1, + 122,175, 0,123,174, 1,123,171, 3,122,176, 0,121,181, 0, + 120,183, 0,120,182, 0,121,181, 0,121,182, 0,121,180, 0, + 122,178, 0,118,188, 0,114,196, 0,112,200, 0,111,201, 0, + 113,198, 0,117,191, 0,121,181, 0,124,165, 8,124,161, 11, + 124,147, 26,119,119, 77,113,100,242,118,117, 85,122,130, 53, + 123,137, 41,123,139, 37,124,165, 8,122,178, 0,120,184, 0, + 120,184, 0,122,178, 0,123,169, 4,124,165, 8,124,161, 11, + 122,177, 0,118,188, 0,115,194, 0,113,198, 0,114,197, 0, + 116,193, 0,119,186, 0,122,177, 0,123,174, 1,123,173, 1, + 123,168, 5,124,164, 9,124,162, 10,124,157, 15,124,147, 26, + 121,125, 63,122,132, 48,124,149, 24,124,155, 16,124,155, 16, + 124,160, 12,124,162, 10,124,158, 13,124,143, 31,123,141, 34, + 122,132, 48,118,114, 96,118,114, 96,124,143, 31,124,161, 11, + 123,169, 4,123,173, 1,120,184, 0,118,189, 0,117,191, 0, + 117,191, 0,115,195, 0,114,197, 0,114,196, 0,117,192, 0, + 116,193, 0,117,190, 0,119,185, 0,122,178, 0,123,172, 2, + 124,166, 7,124,152, 20,120,122, 70,119,119, 77,119,119, 77, + 122,130, 53,124,157, 15,124,166, 7,123,168, 5,124,167, 6, + 124,166, 7,122,178, 0,120,184, 0,119,187, 0,119,186, 0, + 120,184, 0,121,180, 0,122,176, 0,123,174, 1,123,174, 1, + 123,174, 1,123,173, 1,123,172, 2,123,171, 3,123,170, 3, + 123,170, 3,123,171, 3,122,175, 0,121,179, 0,120,182, 0, + 120,182, 0,121,180, 0,123,173, 1,124,162, 10,123,139, 37, + 123,137, 41,122,132, 48,119,119, 77,118,114, 96,122,132, 48, + 124,145, 29,124,152, 20,124,165, 8,123,171, 3,123,174, 1, + 120,182, 0,118,189, 0,116,193, 0,115,194, 0,115,194, 0, + 116,193, 0,114,197, 0,112,200, 0,112,200, 0,113,198, 0, + 117,192, 0,120,182, 0,124,167, 6,124,160, 12,124,160, 12, + 124,160, 12,123,168, 5,122,175, 0,122,178, 0,122,176, 0, + 123,171, 3,123,170, 3,121,179, 0,119,185, 0,118,188, 0, + 118,189, 0,117,191, 0,116,193, 0,114,197, 0,110,202, 0, + 106,208, 0,101,213, 0, 99,216, 0, 98,216, 0,100,215, 0, + 103,212, 0,107,207, 0,110,202, 0,106,208, 0,100,215, 0, + 93,221, 0, 88,226, 0, 83,230, 0, 82,231, 0, 82,231, 0, + 85,229, 0, 85,229, 0, 83,230, 0, 83,230, 0, 86,228, 0, + 91,224, 0, 97,217, 0,105,209, 0,112,199, 0,118,188, 0, + 122,177, 0,122,177, 0,122,178, 0,122,178, 0,122,178, 0, + 123,174, 1,123,168, 5,123,169, 4,120,184, 0,116,192, 0, + 114,197, 0,113,199, 0,113,198, 0,114,196, 0,116,193, 0, + 117,191, 0,117,190, 0,118,189, 0,118,188, 0,119,186, 0, + 120,184, 0,119,185, 0,120,184, 0,121,181, 0,122,178, 0, + 121,182, 0,120,184, 0,120,184, 0,120,184, 0,121,182, 0, + 121,182, 0,119,186, 0,118,189, 0,117,190, 0,118,188, 0, + 120,183, 0,123,173, 1,123,168, 5,124,167, 6,123,170, 3, + 123,174, 1,121,179, 0,120,184, 0,119,186, 0,118,188, 0, + 118,188, 0,119,186, 0,120,184, 0,120,184, 0,119,186, 0, + 119,187, 0,118,188, 0,118,188, 0,119,186, 0,120,183, 0, + 118,188, 0,117,191, 0,117,192, 0,118,188, 0,122,178, 0, + 124,160, 12,121,127, 58,111, 96,248,118,114, 96,124,155, 16, + 123,172, 2,121,179, 0,121,182, 0,121,179, 0,121,181, 0, + 120,184, 0,120,182, 0,121,179, 0,122,176, 0,122,175, 0, + 121,179, 0,120,182, 0,120,184, 0,120,182, 0,122,177, 0, + 121,180, 0,120,183, 0,120,184, 0,121,180, 0,121,181, 0, + 121,181, 0,121,180, 0,118,189, 0,114,196, 0,111,201, 0, + 111,202, 0,112,200, 0,116,193, 0,120,184, 0,123,170, 3, + 124,152, 20,122,135, 44,117,110,109,105, 84,252,113,100,242, + 118,117, 85,121,127, 58,122,132, 48,124,160, 12,122,175, 0, + 120,183, 0,120,184, 0,121,180, 0,123,170, 3,124,166, 7, + 124,162, 10,122,175, 0,119,187, 0,115,194, 0,113,199, 0, + 112,199, 0,114,197, 0,117,191, 0,120,184, 0,122,176, 0, + 123,170, 3,123,170, 3,123,170, 3,123,170, 3,124,167, 6, + 124,161, 11,124,147, 26,121,127, 58,121,127, 58,123,141, 34, + 124,152, 20,124,160, 12,124,161, 11,124,158, 13,124,152, 20, + 124,150, 22,124,143, 31,122,130, 53,122,132, 48,124,157, 15, + 123,171, 3,122,178, 0,121,181, 0,119,186, 0,117,191, 0, + 116,192, 0,116,193, 0,114,196, 0,114,196, 0,115,195, 0, + 117,191, 0,117,191, 0,119,187, 0,121,180, 0,123,172, 2, + 124,167, 6,124,158, 13,123,141, 34,113,100,242,117,110,109, + 122,132, 48,124,143, 31,124,162, 10,123,170, 3,123,171, 3, + 123,170, 3,123,169, 4,122,177, 0,121,182, 0,120,182, 0, + 121,180, 0,122,175, 0,123,174, 1,123,174, 1,123,171, 3, + 124,165, 8,124,160, 12,124,161, 11,124,162, 10,124,165, 8, + 124,166, 7,123,168, 5,123,171, 3,123,171, 3,124,167, 6, + 123,172, 2,122,176, 0,122,177, 0,122,176, 0,123,171, 3, + 124,158, 13,122,135, 44,119,119, 77,109, 92,251, 69, 60,230, + 87, 65,237,118,117, 85,124,149, 24,124,167, 6,123,173, 1, + 122,177, 0,121,179, 0,118,188, 0,116,193, 0,114,196, 0, + 114,196, 0,115,194, 0,114,197, 0,113,199, 0,113,198, 0, + 115,194, 0,119,187, 0,123,174, 1,124,157, 15,124,157, 15, + 124,155, 16,124,157, 15,124,167, 6,123,172, 2,123,172, 2, + 123,168, 5,124,161, 11,124,167, 6,122,175, 0,121,180, 0, + 120,182, 0,120,184, 0,119,186, 0,118,189, 0,116,193, 0, + 112,199, 0,108,206, 0,103,211, 0,101,214, 0,101,214, 0, + 102,213, 0,104,210, 0,108,206, 0,110,202, 0,107,207, 0, + 101,214, 0, 94,220, 0, 89,225, 0, 85,229, 0, 83,230, 0, + 83,230, 0, 86,228, 0, 85,228, 0, 83,230, 0, 83,230, 0, + 84,229, 0, 88,226, 0, 94,221, 0,101,213, 0,108,205, 0, + 114,196, 0,119,186, 0,121,179, 0,121,179, 0,121,179, 0, + 122,178, 0,123,174, 1,123,168, 5,123,169, 4,122,178, 0, + 118,188, 0,115,194, 0,114,197, 0,114,197, 0,114,196, 0, + 116,193, 0,116,192, 0,117,191, 0,117,191, 0,118,189, 0, + 118,188, 0,117,191, 0,116,192, 0,117,191, 0,118,188, 0, + 120,184, 0,120,182, 0,120,182, 0,121,182, 0,121,179, 0, + 122,178, 0,121,182, 0,120,184, 0,119,186, 0,119,185, 0, + 121,182, 0,122,175, 0,124,166, 7,124,165, 8,124,165, 8, + 123,169, 4,123,174, 1,121,179, 0,120,184, 0,119,186, 0, + 118,188, 0,119,187, 0,120,184, 0,120,182, 0,121,182, 0, + 120,183, 0,120,184, 0,119,186, 0,119,186, 0,119,185, 0, + 120,182, 0,120,183, 0,119,187, 0,118,188, 0,120,183, 0, + 123,172, 2,124,150, 22,118,117, 85,119,119, 77,120,122, 70, + 124,154, 18,123,169, 4,122,175, 0,122,175, 0,122,176, 0, + 119,185, 0,118,188, 0,119,187, 0,120,184, 0,121,180, 0, + 122,175, 0,120,182, 0,118,188, 0,118,189, 0,118,189, 0, + 119,185, 0,122,178, 0,120,182, 0,120,182, 0,121,179, 0, + 122,177, 0,122,178, 0,121,182, 0,117,190, 0,114,197, 0, + 111,201, 0,110,202, 0,111,201, 0,114,196, 0,119,187, 0, + 122,175, 0,124,160, 12,123,139, 37,118,114, 96,102, 80,250, + 94, 70,242,109, 92,251,118,114, 96,121,125, 63,124,147, 26, + 123,168, 5,122,178, 0,120,182, 0,121,181, 0,123,173, 1, + 124,167, 6,124,165, 8,123,169, 4,120,184, 0,116,193, 0, + 113,198, 0,112,200, 0,113,199, 0,115,194, 0,118,188, 0, + 121,182, 0,123,174, 1,123,174, 1,122,175, 0,122,175, 0, + 123,174, 1,123,170, 3,124,162, 10,124,150, 22,123,139, 37, + 124,147, 26,124,155, 16,124,161, 11,124,162, 10,124,160, 12, + 124,150, 22,124,150, 22,124,143, 31,124,143, 31,124,150, 22, + 123,169, 4,121,180, 0,119,186, 0,118,188, 0,118,188, 0, + 117,192, 0,115,194, 0,115,194, 0,115,194, 0,116,193, 0, + 117,192, 0,117,190, 0,118,188, 0,120,183, 0,123,173, 1, + 123,168, 5,124,161, 11,124,150, 22,124,143, 31,122,130, 53, + 122,132, 48,124,147, 26,124,152, 20,124,162, 10,123,168, 5, + 123,169, 4,123,168, 5,124,167, 6,123,174, 1,122,177, 0, + 122,175, 0,123,171, 3,123,169, 4,123,168, 5,124,167, 6, + 124,161, 11,124,150, 22,123,139, 37,124,143, 31,124,149, 24, + 124,154, 18,124,158, 13,124,164, 9,123,168, 5,123,169, 4, + 123,168, 5,123,168, 5,122,176, 0,120,183, 0,119,186, 0, + 120,184, 0,121,179, 0,123,168, 5,124,154, 18,122,130, 53, + 111, 96,248, 30, 55,222,119,119, 77,124,152, 20,124,165, 8, + 123,172, 2,122,176, 0,122,178, 0,118,188, 0,115,194, 0, + 114,197, 0,113,198, 0,114,196, 0,115,195, 0,114,196, 0, + 115,194, 0,117,190, 0,121,182, 0,124,165, 8,124,152, 20, + 124,149, 24,124,145, 29,124,157, 15,124,165, 8,124,166, 7, + 124,162, 10,124,155, 16,124,149, 24,124,164, 9,123,169, 4, + 123,171, 3,123,172, 2,123,174, 1,122,176, 0,121,180, 0, + 119,186, 0,115,194, 0,111,201, 0,107,206, 0,105,209, 0, + 104,210, 0,105,209, 0,107,206, 0,110,203, 0,111,201, 0, + 109,204, 0,103,212, 0, 96,219, 0, 91,223, 0, 87,227, 0, + 85,228, 0, 86,228, 0, 89,225, 0, 87,227, 0, 85,229, 0, + 83,230, 0, 84,229, 0, 87,227, 0, 92,222, 0, 98,216, 0, + 105,209, 0,111,201, 0,116,193, 0,120,183, 0,121,179, 0, + 122,178, 0,122,176, 0,123,172, 2,123,169, 4,123,174, 1, + 122,176, 0,121,181, 0,118,188, 0,117,192, 0,116,193, 0, + 116,193, 0,116,192, 0,117,192, 0,117,191, 0,117,191, 0, + 118,189, 0,116,193, 0,114,196, 0,114,197, 0,114,196, 0, + 117,192, 0,119,186, 0,121,182, 0,121,180, 0,122,177, 0, + 122,176, 0,121,179, 0,121,181, 0,121,181, 0,121,179, 0, + 122,176, 0,123,170, 3,124,161, 11,124,152, 20,124,154, 18, + 124,158, 13,124,165, 8,123,171, 3,122,178, 0,121,182, 0, + 120,184, 0,120,184, 0,120,183, 0,121,179, 0,122,176, 0, + 122,175, 0,122,177, 0,122,178, 0,121,181, 0,120,182, 0, + 120,182, 0,121,180, 0,122,175, 0,121,180, 0,121,181, 0, + 122,176, 0,124,164, 9,123,137, 41,121,127, 58,122,135, 44, + 122,135, 44,124,150, 22,124,165, 8,123,169, 4,124,167, 6, + 122,176, 0,119,186, 0,117,190, 0,118,189, 0,119,186, 0, + 121,181, 0,122,175, 0,120,184, 0,118,189, 0,116,193, 0, + 116,192, 0,118,189, 0,120,184, 0,121,182, 0,121,182, 0, + 122,178, 0,123,170, 3,123,174, 1,120,183, 0,117,191, 0, + 114,197, 0,111,201, 0,110,202, 0,111,201, 0,114,196, 0, + 118,189, 0,122,178, 0,124,164, 9,123,141, 34,117,110,109, + 94, 70,242, 30, 37,192, 99, 75,247,111, 96,248,118,117, 85, + 121,127, 58,124,157, 15,123,172, 2,122,178, 0,121,180, 0, + 122,176, 0,124,166, 7,124,164, 9,124,160, 12,122,178, 0, + 118,189, 0,114,196, 0,113,199, 0,113,198, 0,115,195, 0, + 118,189, 0,120,184, 0,122,178, 0,123,173, 1,122,175, 0, + 122,176, 0,122,177, 0,122,175, 0,123,170, 3,124,164, 9, + 124,155, 16,124,150, 22,124,158, 13,124,162, 10,124,164, 9, + 124,161, 11,124,154, 18,124,147, 26,124,150, 22,124,157, 15, + 124,165, 8,122,178, 0,119,187, 0,117,192, 0,116,193, 0, + 116,192, 0,116,193, 0,114,196, 0,114,197, 0,114,196, 0, + 115,194, 0,117,191, 0,118,189, 0,119,185, 0,122,177, 0, + 123,169, 4,124,164, 9,124,162, 10,124,165, 8,124,161, 11, + 124,150, 22,124,150, 22,124,157, 15,124,157, 15,124,157, 15, + 124,162, 10,124,162, 10,124,160, 12,124,164, 9,123,170, 3, + 123,169, 4,124,166, 7,124,164, 9,124,162, 10,124,158, 13, + 124,150, 22,123,139, 37,119,119, 77,115,107,129,118,117, 85, + 121,125, 63,122,132, 48,124,143, 31,124,152, 20,124,165, 8, + 123,174, 1,122,178, 0,121,179, 0,122,178, 0,119,186, 0, + 117,191, 0,116,192, 0,117,190, 0,119,185, 0,122,178, 0, + 123,168, 5,124,154, 18,121,127, 58,118,117, 85,124,149, 24, + 124,157, 15,124,166, 7,123,171, 3,122,177, 0,118,189, 0, + 114,196, 0,113,199, 0,112,199, 0,113,198, 0,116,193, 0, + 116,193, 0,117,191, 0,119,186, 0,122,175, 0,124,154, 18, + 123,141, 34,122,135, 44,123,141, 34,124,154, 18,124,158, 13, + 124,157, 15,124,149, 24,123,141, 34,124,157, 15,124,167, 6, + 123,169, 4,124,167, 6,124,162, 10,124,155, 16,124,157, 15, + 124,165, 8,122,175, 0,119,185, 0,115,194, 0,112,200, 0, + 110,202, 0,109,203, 0,110,203, 0,111,201, 0,112,199, 0, + 113,198, 0,111,201, 0,105,209, 0, 99,216, 0, 94,221, 0, + 90,224, 0, 89,225, 0, 90,225, 0, 91,223, 0, 89,226, 0, + 87,227, 0, 85,229, 0, 86,228, 0, 88,226, 0, 92,222, 0, + 97,217, 0,103,211, 0,108,205, 0,113,198, 0,118,189, 0, + 122,178, 0,123,174, 1,123,170, 3,124,166, 7,124,167, 6, + 123,174, 1,122,178, 0,121,180, 0,121,181, 0,120,184, 0, + 119,187, 0,118,188, 0,118,189, 0,118,189, 0,118,189, 0, + 118,189, 0,117,191, 0,115,195, 0,114,197, 0,113,198, 0, + 114,197, 0,116,193, 0,119,186, 0,121,180, 0,122,176, 0, + 123,171, 3,122,176, 0,122,178, 0,122,178, 0,122,175, 0, + 123,170, 3,124,162, 10,124,150, 22,122,132, 48,121,125, 63, + 123,139, 37,124,154, 18,124,160, 12,124,166, 7,123,173, 1, + 122,178, 0,121,180, 0,121,179, 0,122,176, 0,123,170, 3, + 124,165, 8,124,164, 9,124,165, 8,123,169, 4,123,173, 1, + 122,176, 0,122,178, 0,122,177, 0,123,171, 3,123,170, 3, + 123,172, 2,123,168, 5,124,154, 18,121,125, 63,122,132, 48, + 123,141, 34,123,141, 34,124,143, 31,124,157, 15,124,161, 11, + 124,158, 13,123,170, 3,120,182, 0,119,187, 0,119,186, 0, + 120,184, 0,122,178, 0,123,172, 2,121,182, 0,118,189, 0, + 116,193, 0,116,193, 0,117,191, 0,119,187, 0,120,183, 0, + 121,181, 0,122,178, 0,123,173, 1,122,176, 0,120,184, 0, + 117,190, 0,115,195, 0,113,199, 0,112,200, 0,112,199, 0, + 114,196, 0,118,189, 0,121,179, 0,124,165, 8,123,139, 37, + 114,104,197,102, 80,250, 87, 65,237, 87, 65,237,111, 96,248, + 115,107,129,121,125, 63,123,141, 34,124,162, 10,123,173, 1, + 122,178, 0,122,177, 0,123,170, 3,124,160, 12,124,152, 20, + 123,170, 3,120,184, 0,117,191, 0,115,195, 0,115,195, 0, + 116,193, 0,118,188, 0,121,182, 0,122,175, 0,123,169, 4, + 123,169, 4,123,172, 2,123,174, 1,122,175, 0,123,173, 1, + 123,168, 5,124,164, 9,124,157, 15,124,155, 16,124,160, 12, + 124,161, 11,124,160, 12,124,154, 18,124,152, 20,124,155, 16, + 124,162, 10,123,173, 1,120,184, 0,117,191, 0,115,195, 0, + 114,196, 0,115,195, 0,115,195, 0,113,199, 0,112,200, 0, + 113,199, 0,114,196, 0,117,192, 0,118,188, 0,121,182, 0, + 123,169, 4,124,166, 7,123,171, 3,122,177, 0,122,177, 0, + 123,173, 1,124,164, 9,124,164, 9,124,165, 8,124,161, 11, + 124,150, 22,124,150, 22,124,149, 24,124,149, 24,124,160, 12, + 124,162, 10,124,158, 13,124,158, 13,124,155, 16,124,150, 22, + 123,139, 37,122,135, 44,121,127, 58,118,114, 96,118,114, 96, + 115,107,129,109, 92,251,109, 92,251,118,114, 96,124,147, 26, + 124,166, 7,122,178, 0,120,184, 0,119,186, 0,119,186, 0, + 119,186, 0,116,193, 0,114,197, 0,114,197, 0,115,194, 0, + 117,191, 0,119,185, 0,122,176, 0,124,161, 11,122,132, 48, + 123,139, 37,123,139, 37,124,152, 20,124,161, 11,122,178, 0, + 118,189, 0,114,196, 0,112,199, 0,112,200, 0,113,198, 0, + 115,194, 0,117,190, 0,118,188, 0,120,182, 0,123,171, 3, + 124,147, 26,120,122, 70,117,110,109,122,135, 44,124,145, 29, + 124,147, 26,124,150, 22,124,149, 24,124,149, 24,124,165, 8, + 123,171, 3,123,170, 3,124,164, 9,124,155, 16,124,149, 24, + 123,141, 34,122,130, 53,124,150, 22,123,170, 3,120,183, 0, + 117,190, 0,115,194, 0,114,196, 0,114,196, 0,115,195, 0, + 114,196, 0,113,198, 0,112,199, 0,107,206, 0,101,213, 0, + 97,218, 0, 94,221, 0, 93,222, 0, 94,221, 0, 94,221, 0, + 92,223, 0, 89,225, 0, 88,226, 0, 89,226, 0, 91,224, 0, + 94,221, 0, 98,216, 0,103,211, 0,108,206, 0,112,200, 0, + 117,192, 0,121,182, 0,124,165, 8,124,160, 12,124,152, 20, + 124,157, 15,123,168, 5,122,176, 0,121,180, 0,121,182, 0, + 121,182, 0,121,180, 0,121,182, 0,120,184, 0,119,185, 0, + 119,186, 0,119,185, 0,117,191, 0,115,194, 0,114,196, 0, + 115,195, 0,115,194, 0,117,190, 0,120,182, 0,122,176, 0, + 123,170, 3,123,171, 3,122,176, 0,122,178, 0,123,174, 1, + 124,167, 6,124,155, 16,124,145, 29,123,139, 37,121,127, 58, + 120,122, 70,122,135, 44,124,147, 26,124,150, 22,124,157, 15, + 124,167, 6,123,171, 3,123,172, 2,123,170, 3,124,165, 8, + 124,154, 18,124,155, 16,124,154, 18,124,147, 26,124,150, 22, + 124,158, 13,124,165, 8,123,169, 4,123,169, 4,124,165, 8, + 124,160, 12,124,162, 10,124,160, 12,124,147, 26,122,130, 53, + 122,130, 53,123,137, 41,123,139, 37,122,135, 44,124,145, 29, + 124,149, 24,124,145, 29,124,155, 16,123,171, 3,122,178, 0, + 122,178, 0,122,176, 0,123,171, 3,124,165, 8,122,178, 0, + 119,186, 0,117,191, 0,117,191, 0,118,189, 0,119,186, 0, + 120,184, 0,120,183, 0,121,182, 0,121,180, 0,122,177, 0, + 120,184, 0,118,188, 0,116,192, 0,114,196, 0,114,197, 0, + 114,196, 0,116,193, 0,119,187, 0,122,178, 0,124,162, 10, + 122,132, 48,117,110,109,115,107,129,109, 92,251, 30, 55,222, + 105, 84,252,115,107,129,120,122, 70,122,132, 48,124,150, 22, + 124,167, 6,123,174, 1,122,177, 0,123,174, 1,124,165, 8, + 124,143, 31,124,160, 12,122,176, 0,120,184, 0,118,189, 0, + 118,189, 0,119,186, 0,121,181, 0,123,174, 1,124,166, 7, + 124,160, 12,124,154, 18,124,160, 12,124,166, 7,123,169, 4, + 123,169, 4,124,167, 6,124,165, 8,124,160, 12,124,152, 20, + 124,152, 20,124,154, 18,124,152, 20,124,149, 24,124,149, 24, + 124,155, 16,124,162, 10,122,178, 0,118,188, 0,116,193, 0, + 114,197, 0,113,198, 0,114,196, 0,114,197, 0,111,201, 0, + 110,202, 0,111,201, 0,114,197, 0,117,192, 0,119,186, 0, + 122,177, 0,123,168, 5,122,178, 0,120,184, 0,119,187, 0, + 119,186, 0,121,182, 0,123,173, 1,123,173, 1,123,171, 3, + 124,165, 8,124,150, 22,122,130, 53,121,127, 58,124,143, 31, + 124,150, 22,124,149, 24,124,147, 26,124,149, 24,124,143, 31, + 123,139, 37,123,141, 34,123,137, 41,121,127, 58,122,132, 48, + 121,127, 58,118,117, 85,111, 96,248,109, 92,251,111, 96,248, + 123,137, 41,124,162, 10,122,178, 0,119,186, 0,117,191, 0, + 116,192, 0,117,191, 0,115,194, 0,112,199, 0,111,201, 0, + 112,200, 0,113,198, 0,115,194, 0,119,187, 0,122,175, 0, + 124,152, 20,119,119, 77,114,104,197,121,127, 58,124,157, 15, + 121,179, 0,117,190, 0,114,196, 0,112,199, 0,112,199, 0, + 113,198, 0,115,194, 0,118,189, 0,119,186, 0,121,181, 0, + 123,169, 4,124,143, 31,109, 92,251,107, 89,252,119,119, 77, + 122,132, 48,124,145, 29,124,150, 22,124,149, 24,124,157, 15, + 123,168, 5,123,170, 3,124,166, 7,124,155, 16,124,157, 15, + 124,155, 16,124,147, 26,121,125, 63,111, 96,248,123,141, 34, + 124,165, 8,122,176, 0,120,182, 0,119,186, 0,119,187, 0, + 117,190, 0,114,196, 0,113,198, 0,113,199, 0,109,204, 0, + 103,211, 0, 99,215, 0, 97,218, 0, 96,219, 0, 98,217, 0, + 97,217, 0, 95,220, 0, 93,221, 0, 92,222, 0, 92,222, 0, + 94,220, 0, 97,217, 0,101,214, 0,105,209, 0,108,205, 0, + 112,199, 0,116,192, 0,120,183, 0,123,168, 5,123,139, 37, + 121,125, 63,122,135, 44,124,155, 16,123,168, 5,122,176, 0, + 121,180, 0,121,182, 0,121,181, 0,122,177, 0,122,177, 0, + 121,179, 0,121,181, 0,120,183, 0,119,187, 0,118,189, 0, + 117,190, 0,118,189, 0,119,187, 0,120,182, 0,123,173, 1, + 123,169, 4,124,165, 8,123,172, 2,122,176, 0,122,175, 0, + 123,169, 4,124,157, 15,124,157, 15,124,155, 16,124,150, 22, + 123,137, 41,118,117, 85,120,122, 70,122,130, 53,122,132, 48, + 124,143, 31,124,157, 15,124,162, 10,124,162, 10,124,157, 15, + 124,145, 29,122,135, 44,123,141, 34,123,139, 37,122,132, 48, + 119,119, 77,122,135, 44,124,145, 29,124,154, 18,124,157, 15, + 124,154, 18,124,149, 24,124,155, 16,124,154, 18,124,145, 29, + 122,130, 53,122,130, 53,121,125, 63,122,130, 53,121,127, 58, + 120,122, 70,122,132, 48,122,130, 53,119,119, 77,124,147, 26, + 124,158, 13,124,161, 11,124,158, 13,124,155, 16,124,154, 18, + 123,170, 3,121,181, 0,119,185, 0,119,186, 0,120,184, 0, + 120,183, 0,120,184, 0,120,183, 0,120,184, 0,120,183, 0, + 121,180, 0,121,181, 0,119,185, 0,118,188, 0,117,191, 0, + 117,192, 0,117,191, 0,118,189, 0,120,184, 0,123,174, 1, + 124,155, 16,122,132, 48,123,141, 34,123,141, 34,122,130, 53, + 113,100,242, 69, 60,230,109, 92,251,118,114, 96,122,135, 44, + 123,141, 34,124,160, 12,123,170, 3,122,175, 0,122,175, 0, + 123,169, 4,124,152, 20,124,160, 12,124,165, 8,122,175, 0, + 121,179, 0,121,179, 0,122,175, 0,123,168, 5,124,158, 13, + 124,147, 26,123,137, 41,121,127, 58,122,132, 48,124,145, 29, + 124,154, 18,124,158, 13,124,160, 12,124,160, 12,124,155, 16, + 124,149, 24,123,137, 41,122,135, 44,122,135, 44,122,132, 48, + 123,137, 41,124,145, 29,124,165, 8,121,180, 0,118,189, 0, + 115,194, 0,114,197, 0,113,198, 0,114,196, 0,112,200, 0, + 109,203, 0,109,204, 0,110,202, 0,113,198, 0,117,191, 0, + 120,183, 0,123,171, 3,121,181, 0,118,189, 0,115,194, 0, + 114,196, 0,116,193, 0,118,188, 0,121,180, 0,121,180, 0, + 122,176, 0,124,167, 6,124,150, 22,119,119, 77,118,114, 96, + 121,127, 58,122,132, 48,120,122, 70,122,132, 48,122,132, 48, + 123,141, 34,124,149, 24,124,147, 26,123,139, 37,123,141, 34, + 124,143, 31,122,135, 44,120,122, 70,120,122, 70,118,117, 85, + 118,114, 96,118,117, 85,124,152, 20,123,174, 1,119,186, 0, + 116,193, 0,114,197, 0,114,197, 0,115,195, 0,112,199, 0, + 111,202, 0,110,202, 0,111,202, 0,113,199, 0,116,193, 0, + 120,182, 0,124,161, 11,118,114, 96, 30, 49,213,117,110,109, + 124,160, 12,121,180, 0,117,190, 0,115,195, 0,114,197, 0, + 114,197, 0,114,196, 0,116,192, 0,118,189, 0,119,187, 0, + 121,182, 0,123,170, 3,124,147, 26,109, 92,251, 30, 55,222, + 111, 96,248,121,127, 58,124,145, 29,124,150, 22,124,150, 22, + 124,157, 15,124,165, 8,124,165, 8,124,155, 16,124,160, 12, + 124,162, 10,124,160, 12,124,150, 22,121,127, 58,102, 80,250, + 102, 80,250,122,132, 48,124,155, 16,124,167, 6,123,174, 1, + 122,178, 0,118,188, 0,115,194, 0,114,197, 0,112,200, 0, + 108,206, 0,104,210, 0,101,214, 0, 99,215, 0, 99,215, 0, + 101,214, 0,101,213, 0, 99,215, 0, 97,217, 0, 97,218, 0, + 97,217, 0, 99,215, 0,102,213, 0,105,209, 0,108,206, 0, + 110,202, 0,114,197, 0,117,191, 0,121,182, 0,124,167, 6, + 123,139, 37,105, 84,252,105, 84,252,121,127, 58,124,154, 18, + 123,168, 5,122,176, 0,121,179, 0,121,179, 0,122,176, 0, + 123,169, 4,123,174, 1,122,176, 0,122,178, 0,121,181, 0, + 121,181, 0,121,180, 0,122,178, 0,123,174, 1,123,168, 5, + 124,165, 8,124,161, 11,123,168, 5,123,173, 1,122,175, 0, + 123,172, 2,124,164, 9,124,160, 12,124,162, 10,124,162, 10, + 124,157, 15,124,143, 31,118,117, 85,105, 84,252,109, 92,251, + 109, 92,251,121,125, 63,124,143, 31,124,150, 22,124,149, 24, + 123,139, 37,119,119, 77,118,114, 96,122,132, 48,123,141, 34, + 123,141, 34,122,132, 48,120,122, 70,121,125, 63,121,127, 58, + 122,132, 48,122,132, 48,124,143, 31,124,152, 20,124,154, 18, + 124,149, 24,123,137, 41,121,125, 63,121,125, 63,120,122, 70, + 118,117, 85,118,114, 96,114,104,197,115,107,129,111, 96,248, + 105, 84,252,117,110,109,118,117, 85,119,119, 77,120,122, 70, + 123,137, 41,124,158, 13,123,170, 3,122,176, 0,122,177, 0, + 121,180, 0,120,184, 0,119,185, 0,120,184, 0,120,182, 0, + 120,182, 0,121,180, 0,122,176, 0,121,180, 0,120,183, 0, + 119,185, 0,119,186, 0,119,186, 0,120,184, 0,122,178, 0, + 123,168, 5,124,147, 26,124,154, 18,124,161, 11,124,161, 11, + 124,152, 20,122,130, 53, 99, 75,247, 69, 60,230,114,104,197, + 122,132, 48,124,145, 29,124,154, 18,124,166, 7,123,173, 1, + 122,175, 0,123,170, 3,124,166, 7,123,170, 3,123,172, 2, + 123,169, 4,124,165, 8,124,162, 10,124,155, 16,123,141, 34, + 121,125, 63,115,107,129,117,110,109,114,104,197,107, 89,252, + 113,100,242,120,122, 70,123,137, 41,124,143, 31,124,145, 29, + 124,143, 31,123,139, 37,121,127, 58,115,107,129,111, 96,248, + 109, 92,251,114,104,197,122,135, 44,124,164, 9,121,179, 0, + 118,188, 0,116,193, 0,114,196, 0,114,196, 0,113,198, 0, + 110,203, 0,107,206, 0,107,207, 0,109,204, 0,113,199, 0, + 117,191, 0,121,181, 0,121,180, 0,117,191, 0,113,198, 0, + 111,202, 0,110,202, 0,113,199, 0,116,193, 0,119,185, 0, + 120,184, 0,121,180, 0,123,169, 4,124,150, 22,121,125, 63, + 115,107,129,109, 92,251,107, 89,252,107, 89,252,115,107,129, + 123,137, 41,124,152, 20,124,157, 15,124,154, 18,124,143, 31, + 124,145, 29,124,145, 29,124,145, 29,124,145, 29,123,139, 37, + 123,137, 41,122,132, 48,119,119, 77,123,137, 41,123,168, 5, + 120,184, 0,115,194, 0,112,200, 0,110,202, 0,111,201, 0, + 113,198, 0,111,201, 0,110,202, 0,110,202, 0,111,201, 0, + 115,195, 0,119,185, 0,124,165, 8,118,114, 96, 30, 2,128, + 117,110,109,124,158, 13,122,178, 0,118,188, 0,116,192, 0, + 116,193, 0,116,193, 0,117,192, 0,116,192, 0,117,192, 0, + 117,190, 0,119,185, 0,123,174, 1,124,154, 18,115,107,129, + 30, 10,132, 99, 75,247,120,122, 70,124,143, 31,124,152, 20, + 124,154, 18,124,154, 18,124,155, 16,124,152, 20,124,158, 13, + 124,164, 9,124,165, 8,124,161, 11,124,150, 22,121,125, 63, + 105, 84,252, 30, 2,128,105, 84,252,121,127, 58,124,150, 22, + 124,164, 9,123,173, 1,120,183, 0,117,190, 0,115,194, 0, + 111,202, 0,105,209, 0,101,213, 0, 99,216, 0, 98,216, 0, + 100,215, 0,102,212, 0,105,209, 0,103,211, 0,102,213, 0, + 101,214, 0,102,213, 0,103,211, 0,106,208, 0,108,205, 0, + 110,202, 0,112,199, 0,115,195, 0,118,189, 0,121,180, 0, + 124,165, 8,123,137, 41,105, 84,252, 30, 2,128, 94, 70,242, + 121,125, 63,124,152, 20,124,167, 6,123,173, 1,123,174, 1, + 123,172, 2,124,165, 8,123,171, 3,123,173, 1,123,171, 3, + 123,170, 3,123,168, 5,124,164, 9,124,160, 12,124,150, 22, + 124,155, 16,124,158, 13,124,166, 7,123,172, 2,123,174, 1, + 123,174, 1,123,169, 4,124,158, 13,124,162, 10,124,166, 7, + 124,164, 9,124,155, 16,124,143, 31,118,117, 85, 87, 65,237, + 30, 2,128, 30, 55,222,114,104,197,121,125, 63,122,135, 44, + 122,130, 53,121,127, 58,119,119, 77,117,110,109,122,135, 44, + 124,145, 29,124,149, 24,124,147, 26,123,139, 37,121,127, 58, + 119,119, 77,111, 96,248,121,127, 58,124,147, 26,124,157, 15, + 124,161, 11,124,160, 12,124,154, 18,123,141, 34,120,122, 70, + 121,125, 63,122,130, 53,122,130, 53,120,122, 70,114,104,197, + 99, 75,247, 30, 37,192, 30, 2,128, 30, 15,143, 30, 31,180, + 69, 60,230,115,107,129,123,137, 41,124,155, 16,124,164, 9, + 124,165, 8,122,178, 0,120,183, 0,119,185, 0,120,184, 0, + 121,182, 0,122,178, 0,122,176, 0,123,168, 5,122,178, 0, + 120,183, 0,120,184, 0,120,182, 0,121,182, 0,121,179, 0, + 123,174, 1,124,165, 8,124,162, 10,124,166, 7,123,170, 3, + 123,170, 3,124,164, 9,124,143, 31,111, 96,248, 30, 2,128, + 107, 89,252,121,127, 58,124,147, 26,124,155, 16,124,165, 8, + 123,171, 3,123,173, 1,123,169, 4,122,175, 0,122,178, 0, + 122,178, 0,122,175, 0,124,167, 6,124,152, 20,121,127, 58, + 111, 96,248,115,107,129,118,117, 85,120,122, 70,120,122, 70, + 118,117, 85,115,107,129,109, 92,251,111, 96,248,117,110,109, + 119,119, 77,120,122, 70,118,117, 85,114,104,197,102, 80,250, + 30, 43,203, 30, 2,128, 69, 60,230,120,122, 70,124,157, 15, + 122,176, 0,119,186, 0,117,191, 0,115,194, 0,115,195, 0, + 111,201, 0,107,206, 0,105,209, 0,106,208, 0,108,205, 0, + 113,199, 0,117,190, 0,121,179, 0,117,190, 0,113,199, 0, + 109,204, 0,106,207, 0,107,207, 0,110,203, 0,114,197, 0, + 118,188, 0,119,187, 0,121,182, 0,123,171, 3,124,154, 18, + 120,122, 70,111, 96,248, 30, 55,222, 30, 2,128, 94, 70,242, + 120,122, 70,124,149, 24,124,161, 11,124,164, 9,124,161, 11, + 124,152, 20,124,143, 31,124,154, 18,124,157, 15,124,157, 15, + 124,161, 11,124,161, 11,124,158, 13,124,149, 24,121,127, 58, + 124,164, 9,120,184, 0,115,195, 0,111,202, 0,108,205, 0, + 108,205, 0,110,202, 0,112,199, 0,111,201, 0,110,202, 0, + 111,201, 0,114,196, 0,119,186, 0,124,166, 7,118,117, 85, + 30, 26,168,115,107,129,124,155, 16,122,175, 0,120,184, 0, + 118,188, 0,118,188, 0,116,193, 0,114,196, 0,114,196, 0, + 114,196, 0,116,193, 0,118,188, 0,122,178, 0,124,158, 13, + 118,117, 85, 30, 31,180, 30, 55,222,118,114, 96,123,139, 37, + 124,152, 20,124,158, 13,124,160, 12,124,161, 11,124,161, 11, + 124,165, 8,123,168, 5,123,168, 5,124,164, 9,124,161, 11, + 124,150, 22,120,122, 70, 69, 60,230, 94, 70,242,117,110,109, + 123,137, 41,124,157, 15,123,170, 3,121,180, 0,118,188, 0, + 114,196, 0,108,205, 0,103,212, 0, 98,217, 0, 95,220, 0, + 94,220, 0, 95,219, 0, 98,217, 0,101,214, 0,103,212, 0, + 103,211, 0,106,208, 0,106,208, 0,107,207, 0,106,208, 0, + 106,207, 0,108,205, 0,111,201, 0,115,194, 0,118,188, 0, + 121,180, 0,124,166, 7,124,145, 29,118,117, 85, 94, 70,242, + 30, 49,213,105, 84,252,121,127, 58,124,150, 22,124,161, 11, + 124,164, 9,124,161, 11,124,166, 7,123,172, 2,123,173, 1, + 123,170, 3,124,165, 8,124,154, 18,124,157, 15,124,162, 10, + 124,162, 10,124,164, 9,124,167, 6,123,171, 3,123,173, 1, + 123,173, 1,123,171, 3,124,164, 9,124,164, 9,124,167, 6, + 123,172, 2,123,174, 1,123,171, 3,124,162, 10,123,141, 34, + 115,107,129,111, 96,248,111, 96,248,114,104,197,118,114, 96, + 122,130, 53,123,137, 41,122,135, 44,122,130, 53,120,122, 70, + 122,135, 44,124,147, 26,124,154, 18,124,154, 18,124,152, 20, + 124,145, 29,123,137, 41,122,130, 53,121,125, 63,124,145, 29, + 124,158, 13,124,165, 8,124,166, 7,124,164, 9,124,157, 15, + 124,149, 24,122,132, 48,122,135, 44,124,143, 31,124,145, 29, + 123,141, 34,122,132, 48,118,117, 85,113,100,242,105, 84,252, + 87, 65,237, 30, 37,192, 94, 70,242,118,114, 96,123,139, 37, + 124,150, 22,124,155, 16,123,170, 3,122,178, 0,120,183, 0, + 120,184, 0,120,183, 0,121,181, 0,122,178, 0,122,176, 0, + 120,183, 0,118,188, 0,118,189, 0,118,188, 0,119,186, 0, + 120,183, 0,121,179, 0,122,177, 0,122,176, 0,122,175, 0, + 123,174, 1,123,172, 2,124,165, 8,124,145, 29,113,100,242, + 69, 60,230,105, 84,252,121,127, 58,124,147, 26,124,158, 13, + 124,164, 9,123,168, 5,123,172, 2,122,177, 0,121,182, 0, + 120,184, 0,120,182, 0,122,178, 0,123,168, 5,124,152, 20, + 123,139, 37,124,145, 29,124,147, 26,124,145, 29,123,137, 41, + 122,132, 48,122,132, 48,121,127, 58,120,122, 70,119,119, 77, + 118,117, 85,118,117, 85,118,117, 85,117,110,109,114,104,197, + 111, 96,248,111, 96,248,111, 96,248,107, 89,252,114,104,197, + 124,145, 29,123,169, 4,121,182, 0,118,188, 0,116,192, 0, + 114,197, 0,110,203, 0,107,207, 0,105,209, 0,106,208, 0, + 109,204, 0,114,197, 0,118,188, 0,117,191, 0,112,199, 0, + 107,206, 0,103,211, 0,102,212, 0,103,212, 0,106,207, 0, + 111,201, 0,116,193, 0,119,187, 0,121,182, 0,123,172, 2, + 124,155, 16,121,127, 58,107, 89,252,107, 89,252,109, 92,251, + 118,117, 85,123,139, 37,124,157, 15,124,167, 6,123,171, 3, + 123,172, 2,123,171, 3,123,169, 4,123,170, 3,123,172, 2, + 123,174, 1,122,175, 0,123,174, 1,123,170, 3,124,162, 10, + 124,149, 24,124,161, 11,121,182, 0,116,193, 0,111,201, 0, + 108,205, 0,108,205, 0,109,204, 0,111,201, 0,112,200, 0, + 111,201, 0,112,200, 0,115,194, 0,119,185, 0,124,165, 8, + 118,117, 85, 30, 49,213,115,107,129,124,154, 18,123,172, 2, + 121,180, 0,120,183, 0,118,188, 0,115,195, 0,113,198, 0, + 113,199, 0,113,198, 0,115,194, 0,118,189, 0,122,178, 0, + 124,160, 12,119,119, 77,105, 84,252, 30, 55,222,114,104,197, + 123,137, 41,124,154, 18,124,164, 9,123,168, 5,123,169, 4, + 123,170, 3,123,171, 3,123,172, 2,123,171, 3,123,174, 1, + 123,171, 3,124,164, 9,124,143, 31,113,100,242, 94, 70,242, + 115,107,129,122,130, 53,124,149, 24,124,167, 6,121,179, 0, + 118,189, 0,113,198, 0,107,207, 0,101,214, 0, 95,219, 0, + 92,222, 0, 91,223, 0, 92,223, 0, 93,221, 0, 95,220, 0, + 97,218, 0,100,215, 0,102,212, 0,106,208, 0,106,208, 0, + 105,209, 0,105,209, 0,107,207, 0,110,202, 0,114,197, 0, + 117,191, 0,120,183, 0,123,173, 1,124,160, 12,123,139, 37, + 114,104,197, 30, 37,192, 30, 55,222,109, 92,251,121,125, 63, + 123,139, 37,124,145, 29,124,158, 13,123,168, 5,123,173, 1, + 123,173, 1,123,169, 4,124,160, 12,124,150, 22,124,161, 11, + 124,167, 6,123,169, 4,123,170, 3,123,172, 2,123,173, 1, + 123,172, 2,123,170, 3,124,165, 8,124,167, 6,123,174, 1, + 121,182, 0,119,185, 0,119,186, 0,120,182, 0,122,176, 0, + 124,162, 10,124,147, 26,124,143, 31,123,139, 37,124,143, 31, + 124,147, 26,124,147, 26,124,143, 31,123,141, 34,123,137, 41, + 122,130, 53,124,143, 31,124,155, 16,124,161, 11,124,162, 10, + 124,161, 11,124,157, 15,124,152, 20,124,147, 26,124,145, 29, + 124,143, 31,124,147, 26,124,158, 13,124,162, 10,124,164, 9, + 124,161, 11,124,158, 13,124,150, 22,122,132, 48,124,145, 29, + 124,154, 18,124,158, 13,124,157, 15,124,152, 20,124,145, 29, + 123,137, 41,120,122, 70,114,104,197,107, 89,252,111, 96,248, + 121,127, 58,124,145, 29,124,154, 18,124,161, 11,123,173, 1, + 121,180, 0,120,184, 0,119,185, 0,119,185, 0,119,185, 0, + 120,184, 0,119,187, 0,117,192, 0,115,194, 0,115,194, 0, + 116,193, 0,117,191, 0,118,188, 0,119,186, 0,119,185, 0, + 120,184, 0,121,182, 0,122,176, 0,124,167, 6,124,152, 20, + 122,130, 53,118,114, 96,120,122, 70,121,127, 58,124,147, 26, + 124,158, 13,124,165, 8,123,170, 3,122,176, 0,121,181, 0, + 120,184, 0,119,186, 0,120,184, 0,122,178, 0,124,166, 7, + 124,157, 15,124,165, 8,123,169, 4,123,169, 4,124,167, 6, + 124,161, 11,124,150, 22,122,135, 44,123,137, 41,123,139, 37, + 124,143, 31,124,147, 26,124,147, 26,124,147, 26,124,145, 29, + 124,143, 31,123,141, 34,123,141, 34,123,141, 34,123,139, 37, + 121,127, 58,123,137, 41,124,160, 12,122,175, 0,120,184, 0, + 117,190, 0,114,197, 0,110,202, 0,108,205, 0,107,206, 0, + 109,204, 0,112,200, 0,116,193, 0,116,193, 0,111,201, 0, + 106,207, 0,101,213, 0, 98,217, 0, 97,218, 0, 98,217, 0, + 102,213, 0,107,207, 0,112,199, 0,117,191, 0,120,182, 0, + 123,171, 3,124,157, 15,122,132, 48,122,135, 44,123,137, 41, + 123,141, 34,124,152, 20,124,166, 7,122,175, 0,121,182, 0, + 119,185, 0,119,186, 0,119,186, 0,119,185, 0,119,185, 0, + 119,186, 0,119,186, 0,120,184, 0,120,182, 0,122,178, 0, + 123,172, 2,124,162, 10,124,155, 16,122,177, 0,118,189, 0, + 114,197, 0,111,201, 0,110,202, 0,111,202, 0,112,200, 0, + 113,199, 0,112,200, 0,113,198, 0,116,193, 0,120,183, 0, + 124,164, 9,118,114, 96, 87, 65,237,115,107,129,124,152, 20, + 123,170, 3,122,177, 0,122,178, 0,119,187, 0,115,195, 0, + 113,199, 0,113,199, 0,114,197, 0,116,193, 0,119,186, 0, + 122,175, 0,124,154, 18,122,135, 44,118,117, 85,111, 96,248, + 113,100,242,122,132, 48,124,155, 16,124,167, 6,123,173, 1, + 122,176, 0,122,177, 0,122,176, 0,122,176, 0,122,178, 0, + 121,180, 0,122,178, 0,123,170, 3,124,155, 16,121,125, 63, + 111, 96,248,111, 96,248,120,122, 70,123,137, 41,124,162, 10, + 122,178, 0,118,189, 0,112,199, 0,106,208, 0, 99,215, 0, + 94,221, 0, 91,224, 0, 89,225, 0, 89,225, 0, 90,225, 0, + 91,224, 0, 92,223, 0, 94,221, 0, 96,219, 0,100,215, 0, + 103,211, 0,105,209, 0,105,209, 0,107,207, 0,110,203, 0, + 113,198, 0,116,192, 0,119,186, 0,122,178, 0,124,166, 7, + 124,149, 24,120,122, 70, 94, 70,242, 30, 31,180, 69, 60,230, + 111, 96,248,120,122, 70,124,143, 31,124,157, 15,124,167, 6, + 123,171, 3,123,170, 3,124,165, 8,124,154, 18,123,141, 34, + 124,157, 15,124,166, 7,123,170, 3,123,172, 2,123,173, 1, + 123,172, 2,123,169, 4,124,165, 8,124,166, 7,121,180, 0, + 118,188, 0,117,192, 0,116,193, 0,116,193, 0,117,190, 0, + 119,185, 0,122,177, 0,123,168, 5,124,164, 9,124,160, 12, + 124,160, 12,124,161, 11,124,161, 11,124,158, 13,124,150, 22, + 123,139, 37,123,137, 41,124,152, 20,124,164, 9,123,168, 5, + 123,169, 4,123,168, 5,124,165, 8,124,160, 12,124,157, 15, + 124,155, 16,124,154, 18,124,152, 20,124,149, 24,124,149, 24, + 124,155, 16,124,158, 13,124,161, 11,124,157, 15,124,145, 29, + 124,143, 31,124,157, 15,124,165, 8,124,167, 6,124,167, 6, + 124,164, 9,124,157, 15,124,145, 29,121,127, 58,117,110,109, + 118,117, 85,120,122, 70,124,145, 29,124,155, 16,124,161, 11, + 124,166, 7,122,177, 0,120,183, 0,119,186, 0,118,189, 0, + 117,190, 0,117,190, 0,117,190, 0,115,195, 0,113,198, 0, + 112,200, 0,112,199, 0,114,197, 0,115,195, 0,116,193, 0, + 117,192, 0,118,189, 0,119,186, 0,121,181, 0,123,173, 1, + 124,162, 10,124,149, 24,124,152, 20,124,155, 16,124,154, 18, + 124,150, 22,124,154, 18,124,162, 10,123,169, 4,122,175, 0, + 121,181, 0,119,185, 0,119,186, 0,120,182, 0,122,175, 0, + 124,162, 10,123,170, 3,122,178, 0,121,181, 0,121,181, 0, + 122,177, 0,123,171, 3,124,161, 11,124,147, 26,123,137, 41, + 124,145, 29,124,155, 16,124,162, 10,124,165, 8,124,165, 8, + 124,165, 8,124,164, 9,124,162, 10,124,161, 11,124,162, 10, + 124,161, 11,124,157, 15,124,149, 24,124,160, 12,123,173, 1, + 120,182, 0,118,189, 0,115,194, 0,113,199, 0,111,201, 0, + 111,202, 0,112,199, 0,115,195, 0,114,196, 0,110,202, 0, + 105,209, 0,100,214, 0, 96,219, 0, 93,222, 0, 92,222, 0, + 94,221, 0, 98,217, 0,103,212, 0,108,205, 0,113,198, 0, + 117,190, 0,121,181, 0,123,168, 5,124,164, 9,124,161, 11, + 124,160, 12,124,164, 9,123,170, 3,122,178, 0,119,185, 0, + 117,190, 0,116,192, 0,115,194, 0,115,194, 0,115,194, 0, + 115,194, 0,116,193, 0,116,192, 0,117,191, 0,118,188, 0, + 120,184, 0,122,178, 0,123,173, 1,124,165, 8,123,169, 4, + 120,182, 0,117,190, 0,115,194, 0,114,197, 0,114,197, 0, + 114,196, 0,114,197, 0,113,198, 0,114,196, 0,117,191, 0, + 121,181, 0,124,160, 12,117,110,109,107, 89,252,118,117, 85, + 124,150, 22,123,168, 5,122,175, 0,122,175, 0,120,183, 0, + 117,192, 0,114,196, 0,114,196, 0,116,193, 0,118,189, 0, + 121,180, 0,123,168, 5,124,157, 15,124,145, 29,123,137, 41, + 122,130, 53,119,119, 77,122,130, 53,124,155, 16,123,169, 4, + 122,177, 0,121,180, 0,121,180, 0,122,178, 0,121,179, 0, + 121,182, 0,120,182, 0,121,180, 0,123,174, 1,124,162, 10, + 123,137, 41,120,122, 70,109, 92,251,114,104,197,120,122, 70, + 124,154, 18,123,173, 1,119,187, 0,113,198, 0,106,208, 0, + 100,215, 0, 94,220, 0, 91,224, 0, 89,226, 0, 88,226, 0, + 87,227, 0, 87,227, 0, 87,227, 0, 88,226, 0, 91,224, 0, + 94,220, 0, 99,215, 0,105,209, 0,106,208, 0,108,206, 0, + 110,202, 0,113,198, 0,114,196, 0,117,192, 0,120,184, 0, + 123,174, 1,124,157, 15,122,130, 53,107, 89,252, 87, 65,237, + 30, 49,213, 87, 65,237,115,107,129,122,135, 44,124,152, 20, + 124,161, 11,124,166, 7,124,165, 8,124,158, 13,124,143, 31, + 120,122, 70,124,143, 31,124,158, 13,124,166, 7,123,168, 5, + 123,169, 4,123,168, 5,124,164, 9,124,164, 9,121,180, 0, + 117,190, 0,114,196, 0,113,199, 0,112,199, 0,113,198, 0, + 114,196, 0,117,191, 0,119,186, 0,121,180, 0,122,175, 0, + 123,170, 3,123,169, 4,123,169, 4,123,169, 4,124,166, 7, + 124,161, 11,124,154, 18,124,147, 26,124,162, 10,123,169, 4, + 123,173, 1,123,174, 1,123,172, 2,123,169, 4,123,170, 3, + 124,167, 6,124,162, 10,124,160, 12,124,157, 15,124,154, 18, + 124,150, 22,124,147, 26,124,147, 26,124,155, 16,124,155, 16, + 124,149, 24,122,135, 44,124,154, 18,124,165, 8,123,170, 3, + 123,171, 3,123,169, 4,124,162, 10,124,152, 20,122,135, 44, + 120,122, 70,122,130, 53,122,135, 44,124,145, 29,124,158, 13, + 124,166, 7,123,170, 3,123,173, 1,121,181, 0,119,186, 0, + 117,190, 0,116,192, 0,116,193, 0,115,194, 0,114,196, 0, + 111,201, 0,110,202, 0,110,203, 0,110,202, 0,112,200, 0, + 113,198, 0,114,196, 0,116,193, 0,118,189, 0,120,184, 0, + 122,178, 0,123,171, 3,123,172, 2,123,173, 1,123,172, 2, + 123,169, 4,124,165, 8,124,160, 12,124,155, 16,124,161, 11, + 123,169, 4,122,178, 0,120,182, 0,120,182, 0,121,179, 0, + 123,171, 3,124,165, 8,122,175, 0,120,182, 0,119,186, 0, + 120,184, 0,121,180, 0,123,173, 1,124,162, 10,124,149, 24, + 122,130, 53,124,143, 31,124,158, 13,123,168, 5,123,172, 2, + 123,174, 1,123,174, 1,123,173, 1,123,171, 3,123,171, 3, + 123,172, 2,123,172, 2,123,171, 3,123,168, 5,124,165, 8, + 123,173, 1,121,182, 0,119,187, 0,117,191, 0,115,194, 0, + 114,196, 0,114,197, 0,113,198, 0,113,198, 0,111,202, 0, + 105,209, 0,100,214, 0, 95,219, 0, 92,223, 0, 89,225, 0, + 89,225, 0, 91,223, 0, 95,220, 0,100,215, 0,105,209, 0, + 110,203, 0,114,196, 0,118,188, 0,121,180, 0,121,180, 0, + 122,178, 0,123,174, 1,122,176, 0,121,180, 0,119,185, 0, + 117,190, 0,115,194, 0,114,197, 0,113,198, 0,113,198, 0, + 113,199, 0,112,199, 0,113,198, 0,114,196, 0,116,193, 0, + 117,191, 0,119,187, 0,120,183, 0,121,180, 0,122,175, 0, + 124,167, 6,123,172, 2,121,181, 0,119,186, 0,117,191, 0, + 116,193, 0,115,194, 0,114,196, 0,115,195, 0,116,193, 0, + 118,188, 0,122,178, 0,124,157, 15,115,107,129,114,104,197, + 122,132, 48,124,149, 24,124,167, 6,123,173, 1,123,173, 1, + 123,174, 1,119,185, 0,118,189, 0,118,189, 0,119,186, 0, + 121,179, 0,123,173, 1,124,165, 8,124,155, 16,124,147, 26, + 124,147, 26,124,147, 26,123,141, 34,122,135, 44,124,155, 16, + 123,169, 4,122,178, 0,121,181, 0,121,180, 0,122,178, 0, + 121,180, 0,121,182, 0,120,182, 0,121,181, 0,122,176, 0, + 124,167, 6,124,147, 26,123,139, 37,118,114, 96, 99, 75,247, + 111, 96,248,123,139, 37,124,166, 7,120,183, 0,114,196, 0, + 107,206, 0,101,214, 0, 96,219, 0, 92,222, 0, 90,225, 0, + 88,226, 0, 87,227, 0, 86,228, 0, 85,229, 0, 85,229, 0, + 87,227, 0, 90,224, 0, 96,219, 0,102,212, 0,107,207, 0, + 109,204, 0,111,202, 0,111,202, 0,112,200, 0,114,197, 0, + 117,191, 0,121,182, 0,123,168, 5,124,150, 22,121,125, 63, + 117,110,109,111, 96,248,105, 84,252,109, 92,251,118,114, 96, + 123,137, 41,124,147, 26,124,152, 20,124,150, 22,124,145, 29, + 122,130, 53,114,104,197,118,114, 96,123,137, 41,124,150, 22, + 124,158, 13,124,160, 12,124,166, 7,123,169, 4,123,174, 1, + 118,188, 0,114,196, 0,111,201, 0,110,202, 0,110,202, 0, + 111,201, 0,113,198, 0,115,195, 0,117,192, 0,118,188, 0, + 119,185, 0,121,181, 0,122,175, 0,123,174, 1,123,173, 1, + 123,171, 3,123,168, 5,124,161, 11,124,162, 10,124,167, 6, + 123,174, 1,122,178, 0,122,178, 0,122,176, 0,122,175, 0, + 122,178, 0,122,177, 0,123,173, 1,123,168, 5,124,164, 9, + 124,155, 16,124,152, 20,124,150, 22,124,150, 22,124,152, 20, + 124,149, 24,124,145, 29,122,132, 48,124,145, 29,124,160, 12, + 124,167, 6,123,170, 3,123,168, 5,124,160, 12,124,147, 26, + 121,127, 58,121,125, 63,122,135, 44,124,143, 31,124,147, 26, + 124,160, 12,123,168, 5,123,174, 1,122,176, 0,122,178, 0, + 119,185, 0,118,189, 0,116,192, 0,115,194, 0,115,195, 0, + 114,196, 0,111,201, 0,109,204, 0,108,205, 0,109,204, 0, + 110,203, 0,111,201, 0,113,199, 0,115,195, 0,117,191, 0, + 118,189, 0,118,189, 0,118,188, 0,119,186, 0,119,185, 0, + 120,183, 0,122,178, 0,123,172, 2,124,167, 6,124,164, 9, + 124,158, 13,124,160, 12,123,168, 5,123,174, 1,122,175, 0, + 123,172, 2,124,165, 8,124,164, 9,122,175, 0,120,182, 0, + 119,185, 0,120,184, 0,122,178, 0,123,169, 4,124,157, 15, + 123,139, 37,119,119, 77,122,130, 53,124,155, 16,123,169, 4, + 122,176, 0,122,178, 0,122,178, 0,122,178, 0,122,177, 0, + 122,178, 0,122,177, 0,121,179, 0,121,180, 0,121,179, 0, + 122,177, 0,123,173, 1,121,180, 0,119,185, 0,118,189, 0, + 115,194, 0,114,197, 0,112,199, 0,112,200, 0,111,201, 0, + 107,207, 0,102,213, 0, 97,217, 0, 93,221, 0, 90,225, 0, + 88,226, 0, 87,227, 0, 89,225, 0, 93,221, 0, 98,217, 0, + 103,212, 0,107,206, 0,111,201, 0,115,194, 0,117,191, 0, + 117,191, 0,118,189, 0,119,185, 0,120,183, 0,119,186, 0, + 118,189, 0,116,193, 0,114,196, 0,114,197, 0,113,198, 0, + 113,199, 0,112,200, 0,111,201, 0,112,200, 0,113,198, 0, + 115,194, 0,117,192, 0,118,189, 0,118,188, 0,119,186, 0, + 120,184, 0,121,182, 0,122,177, 0,120,183, 0,118,188, 0, + 117,191, 0,116,192, 0,116,192, 0,116,192, 0,116,192, 0, + 117,190, 0,119,185, 0,122,175, 0,124,155, 16,115,107,129, + 119,119, 77,123,141, 34,124,158, 13,124,167, 6,123,173, 1, + 123,172, 2,124,166, 7,123,172, 2,122,178, 0,122,178, 0, + 122,177, 0,123,172, 2,124,166, 7,124,158, 13,124,150, 22, + 124,147, 26,124,150, 22,124,157, 15,124,155, 16,124,150, 22, + 124,155, 16,123,168, 5,122,176, 0,121,179, 0,122,178, 0, + 122,177, 0,122,178, 0,121,180, 0,121,181, 0,121,180, 0, + 122,177, 0,123,169, 4,124,155, 16,124,150, 22,122,130, 53, + 102, 80,250, 69, 60,230,118,117, 85,124,154, 18,122,176, 0, + 117,191, 0,110,202, 0,104,210, 0, 99,216, 0, 95,220, 0, + 92,222, 0, 91,224, 0, 89,226, 0, 86,228, 0, 84,229, 0, + 83,230, 0, 84,229, 0, 88,226, 0, 94,221, 0,101,214, 0, + 108,206, 0,110,203, 0,109,204, 0,108,205, 0,109,204, 0, + 111,201, 0,115,195, 0,119,187, 0,122,177, 0,124,162, 10, + 124,145, 29,123,139, 37,122,130, 53,118,114, 96,118,114, 96, + 119,119, 77,120,122, 70,120,122, 70,120,122, 70,121,125, 63, + 119,119, 77,115,107,129,102, 80,250, 30, 43,203,107, 89,252, + 121,127, 58,124,149, 24,124,162, 10,123,170, 3,122,175, 0, + 121,181, 0,117,192, 0,113,199, 0,110,202, 0,109,203, 0, + 110,202, 0,111,201, 0,112,200, 0,112,199, 0,114,197, 0, + 115,194, 0,117,192, 0,118,189, 0,120,184, 0,122,178, 0, + 122,176, 0,123,174, 1,123,171, 3,124,167, 6,123,169, 4, + 123,172, 2,122,177, 0,121,179, 0,121,180, 0,122,178, 0, + 121,179, 0,120,183, 0,120,182, 0,121,181, 0,121,179, 0, + 122,177, 0,123,174, 1,123,168, 5,124,160, 12,124,152, 20, + 124,155, 16,124,155, 16,124,147, 26,122,132, 48,122,132, 48, + 124,149, 24,124,160, 12,124,162, 10,124,160, 12,124,150, 22, + 122,132, 48,118,114, 96,120,122, 70,122,135, 44,124,143, 31, + 124,149, 24,124,158, 13,123,169, 4,122,176, 0,121,180, 0, + 121,182, 0,120,182, 0,119,187, 0,117,190, 0,117,192, 0, + 116,193, 0,115,194, 0,113,199, 0,109,203, 0,108,206, 0, + 108,206, 0,109,204, 0,110,202, 0,112,200, 0,113,199, 0, + 111,201, 0,111,201, 0,112,200, 0,114,197, 0,115,194, 0, + 116,192, 0,118,189, 0,120,183, 0,121,179, 0,122,178, 0, + 122,175, 0,123,168, 5,124,160, 12,124,164, 9,124,165, 8, + 124,162, 10,124,161, 11,124,155, 16,124,155, 16,123,168, 5, + 122,177, 0,121,180, 0,122,178, 0,123,170, 3,124,158, 13, + 124,149, 24,122,135, 44,114,104,197,115,107,129,124,147, 26, + 124,166, 7,122,175, 0,121,179, 0,121,181, 0,121,180, 0, + 120,183, 0,119,185, 0,120,184, 0,120,183, 0,120,184, 0, + 119,185, 0,120,184, 0,121,181, 0,121,179, 0,120,183, 0, + 118,188, 0,115,194, 0,113,198, 0,112,200, 0,112,200, 0, + 109,204, 0,105,209, 0,101,214, 0, 97,218, 0, 93,222, 0, + 90,225, 0, 88,226, 0, 88,226, 0, 90,225, 0, 93,221, 0, + 97,217, 0,102,212, 0,106,208, 0,110,203, 0,113,198, 0, + 113,198, 0,113,198, 0,114,197, 0,116,193, 0,118,188, 0, + 117,190, 0,117,192, 0,116,193, 0,115,195, 0,114,196, 0, + 114,196, 0,114,197, 0,113,198, 0,112,199, 0,113,198, 0, + 114,196, 0,115,194, 0,115,194, 0,115,195, 0,115,194, 0, + 117,191, 0,117,191, 0,117,190, 0,118,188, 0,120,184, 0, + 118,189, 0,117,190, 0,117,190, 0,118,189, 0,118,188, 0, + 118,188, 0,119,186, 0,121,181, 0,123,171, 3,124,152, 20, + 118,117, 85,121,127, 58,124,150, 22,124,166, 7,123,174, 1, + 122,177, 0,122,175, 0,123,169, 4,124,158, 13,124,166, 7, + 123,169, 4,123,168, 5,124,164, 9,124,157, 15,124,147, 26, + 124,143, 31,124,143, 31,124,154, 18,124,162, 10,124,165, 8, + 124,164, 9,124,162, 10,123,170, 3,122,176, 0,122,178, 0, + 122,177, 0,122,175, 0,122,175, 0,122,178, 0,122,178, 0, + 121,179, 0,122,178, 0,123,172, 2,124,161, 11,124,158, 13, + 123,141, 34,113,100,242, 30, 37,192,109, 92,251,124,147, 26, + 123,170, 3,119,185, 0,113,198, 0,107,207, 0,102,212, 0, + 99,216, 0, 96,219, 0, 93,222, 0, 91,224, 0, 88,226, 0, + 85,229, 0, 83,230, 0, 84,229, 0, 87,227, 0, 93,222, 0, + 100,214, 0,108,206, 0,109,203, 0,107,207, 0,106,208, 0, + 107,207, 0,109,203, 0,113,198, 0,117,190, 0,121,181, 0, + 123,169, 4,124,158, 13,124,157, 15,124,152, 20,124,143, 31, + 122,130, 53,122,130, 53,121,127, 58,120,122, 70,118,117, 85, + 118,117, 85,118,117, 85,117,110,109,114,104,197,107, 89,252, + 99, 75,247,119,119, 77,124,147, 26,124,164, 9,123,173, 1, + 121,179, 0,120,184, 0,116,193, 0,112,199, 0,110,202, 0, + 110,202, 0,109,204, 0,107,207, 0,107,207, 0,108,205, 0, + 111,202, 0,114,197, 0,115,195, 0,116,192, 0,118,188, 0, + 120,184, 0,122,178, 0,122,177, 0,122,175, 0,123,170, 3, + 123,171, 3,123,174, 1,122,176, 0,121,179, 0,121,181, 0, + 121,180, 0,121,180, 0,120,184, 0,120,184, 0,120,184, 0, + 120,184, 0,120,184, 0,120,183, 0,121,180, 0,123,174, 1, + 124,165, 8,124,158, 13,124,160, 12,124,155, 16,124,145, 29, + 122,130, 53,123,137, 41,124,143, 31,124,149, 24,124,145, 29, + 122,130, 53,122,130, 53,123,139, 37,123,141, 34,123,139, 37, + 123,139, 37,124,149, 24,124,154, 18,124,167, 6,122,176, 0, + 121,182, 0,120,184, 0,119,186, 0,120,184, 0,119,186, 0, + 118,188, 0,117,190, 0,117,192, 0,114,196, 0,110,202, 0, + 108,205, 0,107,206, 0,108,205, 0,110,203, 0,109,204, 0, + 107,207, 0,105,209, 0,106,208, 0,107,207, 0,109,203, 0, + 112,199, 0,114,196, 0,117,192, 0,118,188, 0,118,188, 0, + 119,187, 0,120,183, 0,122,177, 0,124,166, 7,124,160, 12, + 124,161, 11,124,158, 13,124,152, 20,123,141, 34,123,137, 41, + 124,154, 18,124,165, 8,123,169, 4,124,167, 6,124,167, 6, + 123,170, 3,123,168, 5,124,158, 13,122,135, 44,111, 96,248, + 122,132, 48,124,160, 12,123,172, 2,122,178, 0,121,181, 0, + 121,182, 0,119,187, 0,118,189, 0,119,187, 0,119,186, 0, + 118,188, 0,118,189, 0,118,188, 0,119,186, 0,121,182, 0, + 121,182, 0,119,186, 0,116,193, 0,114,197, 0,113,199, 0, + 111,201, 0,108,205, 0,105,209, 0,101,213, 0, 98,217, 0, + 94,221, 0, 91,223, 0, 90,225, 0, 90,224, 0, 92,223, 0, + 94,220, 0, 98,216, 0,102,212, 0,106,208, 0,109,204, 0, + 112,200, 0,110,202, 0,109,203, 0,110,202, 0,112,199, 0, + 116,193, 0,116,193, 0,116,193, 0,115,194, 0,116,193, 0, + 116,192, 0,117,192, 0,117,192, 0,115,194, 0,115,195, 0, + 115,195, 0,116,193, 0,114,196, 0,113,198, 0,112,199, 0, + 113,198, 0,115,194, 0,114,196, 0,114,197, 0,114,196, 0, + 116,192, 0,119,187, 0,119,187, 0,119,186, 0,120,183, 0, + 120,182, 0,121,182, 0,121,180, 0,122,176, 0,123,168, 5, + 124,150, 22,122,135, 44,123,137, 41,124,157, 15,123,171, 3, + 121,179, 0,120,182, 0,121,181, 0,122,176, 0,124,167, 6, + 124,157, 15,124,161, 11,124,160, 12,124,154, 18,124,152, 20, + 124,155, 16,124,157, 15,124,157, 15,124,154, 18,124,166, 7, + 123,170, 3,123,172, 2,123,171, 3,122,175, 0,122,178, 0, + 121,179, 0,122,177, 0,121,181, 0,121,181, 0,122,178, 0, + 122,178, 0,121,179, 0,122,178, 0,122,175, 0,124,165, 8, + 124,162, 10,124,149, 24,118,114, 96,102, 80,250, 99, 75,247, + 123,139, 37,124,166, 7,122,178, 0,116,193, 0,110,202, 0, + 106,208, 0,102,212, 0, 97,218, 0, 93,222, 0, 90,224, 0, + 91,223, 0, 87,227, 0, 85,229, 0, 85,229, 0, 87,227, 0, + 93,222, 0,100,215, 0,107,207, 0,109,204, 0,106,208, 0, + 105,209, 0,106,207, 0,109,204, 0,113,199, 0,117,191, 0, + 121,181, 0,123,169, 4,124,165, 8,124,166, 7,124,165, 8, + 124,161, 11,124,154, 18,124,145, 29,122,132, 48,120,122, 70, + 118,117, 85,119,119, 77,120,122, 70,121,125, 63,121,125, 63, + 120,122, 70,119,119, 77,118,117, 85,124,147, 26,124,165, 8, + 122,175, 0,120,183, 0,118,188, 0,116,193, 0,113,198, 0, + 111,201, 0,108,206, 0,105,209, 0,103,211, 0,103,212, 0, + 105,209, 0,108,206, 0,112,200, 0,115,194, 0,117,192, 0, + 118,188, 0,120,184, 0,121,182, 0,121,180, 0,122,178, 0, + 123,173, 1,124,166, 7,123,170, 3,123,172, 2,122,178, 0, + 121,180, 0,121,182, 0,121,182, 0,121,181, 0,121,182, 0, + 121,182, 0,120,183, 0,119,185, 0,119,185, 0,120,184, 0, + 121,180, 0,123,172, 2,124,161, 11,124,164, 9,124,161, 11, + 124,155, 16,124,145, 29,123,137, 41,123,139, 37,123,137, 41, + 121,125, 63,123,141, 34,124,152, 20,124,158, 13,124,161, 11, + 124,160, 12,124,155, 16,124,149, 24,124,143, 31,124,160, 12, + 123,172, 2,121,181, 0,119,186, 0,118,188, 0,118,188, 0, + 119,187, 0,120,183, 0,119,186, 0,118,188, 0,116,193, 0, + 112,200, 0,108,205, 0,107,206, 0,107,206, 0,109,204, 0, + 105,209, 0,102,212, 0,101,214, 0,102,213, 0,104,210, 0, + 107,206, 0,111,201, 0,114,197, 0,114,196, 0,114,196, 0, + 115,194, 0,116,192, 0,118,188, 0,121,181, 0,123,170, 3, + 124,154, 18,124,155, 16,124,155, 16,124,152, 20,124,147, 26, + 123,139, 37,122,132, 48,124,143, 31,124,152, 20,124,166, 7, + 123,174, 1,122,178, 0,122,176, 0,123,168, 5,124,150, 22, + 117,110,109,118,117, 85,124,154, 18,123,169, 4,122,178, 0, + 121,182, 0,120,183, 0,119,187, 0,118,188, 0,119,186, 0, + 118,188, 0,117,191, 0,117,192, 0,117,191, 0,118,189, 0, + 120,184, 0,120,183, 0,120,183, 0,117,191, 0,115,194, 0, + 114,196, 0,112,200, 0,109,204, 0,106,207, 0,103,211, 0, + 100,215, 0, 96,219, 0, 94,221, 0, 92,222, 0, 92,222, 0, + 94,221, 0, 97,218, 0,100,215, 0,104,210, 0,107,207, 0, + 109,203, 0,110,202, 0,108,205, 0,107,207, 0,108,206, 0, + 110,202, 0,114,197, 0,114,197, 0,114,196, 0,115,194, 0, + 117,192, 0,118,189, 0,119,187, 0,118,188, 0,118,188, 0, + 117,190, 0,117,192, 0,115,195, 0,113,198, 0,112,200, 0, + 111,201, 0,112,200, 0,114,196, 0,112,199, 0,111,201, 0, + 112,200, 0,114,197, 0,117,191, 0,120,182, 0,122,177, 0, + 123,173, 1,123,174, 1,123,173, 1,123,172, 2,123,170, 3, + 124,164, 9,124,152, 20,124,149, 24,124,150, 22,124,160, 12, + 123,173, 1,121,181, 0,120,184, 0,120,184, 0,121,181, 0, + 123,174, 1,124,166, 7,124,160, 12,124,157, 15,124,158, 13, + 124,161, 11,124,164, 9,124,166, 7,124,166, 7,124,166, 7, + 123,169, 4,122,175, 0,122,178, 0,122,178, 0,121,181, 0, + 120,183, 0,120,182, 0,120,184, 0,119,186, 0,119,186, 0, + 120,183, 0,120,182, 0,120,184, 0,120,183, 0,121,179, 0, + 123,171, 3,124,162, 10,124,150, 22,122,130, 53,118,117, 85, + 117,110,109,119,119, 77,124,155, 16,123,172, 2,118,189, 0, + 113,199, 0,108,205, 0,105,209, 0,100,215, 0, 95,220, 0, + 92,222, 0, 93,222, 0, 91,224, 0, 88,226, 0, 88,226, 0, + 90,224, 0, 95,220, 0,101,214, 0,106,208, 0,107,206, 0, + 105,209, 0,105,209, 0,106,208, 0,109,204, 0,113,198, 0, + 116,193, 0,118,188, 0,121,180, 0,122,176, 0,123,172, 2, + 123,171, 3,123,170, 3,123,168, 5,124,164, 9,124,157, 15, + 124,149, 24,123,137, 41,120,122, 70,122,130, 53,123,141, 34, + 124,147, 26,124,145, 29,123,139, 37,123,139, 37,124,145, 29, + 124,165, 8,122,178, 0,119,186, 0,116,192, 0,113,198, 0, + 111,202, 0,108,206, 0,104,210, 0,102,213, 0,100,214, 0, + 100,214, 0,102,212, 0,105,209, 0,109,203, 0,113,198, 0, + 116,193, 0,117,190, 0,118,188, 0,119,186, 0,120,184, 0, + 121,181, 0,122,177, 0,123,170, 3,124,162, 10,124,161, 11, + 123,170, 3,122,176, 0,121,179, 0,121,182, 0,120,183, 0, + 120,184, 0,120,183, 0,121,180, 0,120,183, 0,119,185, 0, + 120,184, 0,121,182, 0,122,176, 0,124,166, 7,124,166, 7, + 124,165, 8,124,161, 11,124,155, 16,124,147, 26,123,141, 34, + 123,139, 37,124,147, 26,124,157, 15,124,166, 7,123,170, 3, + 123,172, 2,123,171, 3,123,168, 5,124,164, 9,124,160, 12, + 124,167, 6,123,171, 3,122,177, 0,120,184, 0,118,188, 0, + 118,189, 0,118,189, 0,119,186, 0,120,183, 0,119,185, 0, + 117,191, 0,112,199, 0,109,204, 0,107,207, 0,106,207, 0, + 106,208, 0,102,212, 0,100,215, 0, 99,216, 0,100,215, 0, + 103,212, 0,107,207, 0,109,203, 0,110,202, 0,111,201, 0, + 112,200, 0,113,198, 0,115,194, 0,118,189, 0,121,181, 0, + 123,168, 5,124,150, 22,124,152, 20,124,154, 18,124,152, 20, + 124,150, 22,124,145, 29,124,143, 31,124,143, 31,124,150, 22, + 124,166, 7,123,174, 1,122,178, 0,122,177, 0,123,170, 3, + 124,155, 16,120,122, 70,119,119, 77,124,147, 26,124,166, 7, + 122,176, 0,121,181, 0,120,184, 0,119,185, 0,119,186, 0, + 119,187, 0,118,189, 0,117,191, 0,117,192, 0,117,191, 0, + 118,188, 0,120,184, 0,120,184, 0,120,184, 0,118,188, 0, + 117,192, 0,116,193, 0,114,197, 0,111,201, 0,106,208, 0, + 101,214, 0, 97,217, 0, 95,220, 0, 94,220, 0, 94,221, 0, + 94,221, 0, 95,220, 0, 96,219, 0, 97,217, 0,100,215, 0, + 103,211, 0,108,205, 0,109,203, 0,107,207, 0,106,208, 0, + 106,208, 0,108,205, 0,112,199, 0,113,199, 0,114,197, 0, + 115,194, 0,118,189, 0,119,186, 0,118,189, 0,117,191, 0, + 117,192, 0,117,192, 0,115,194, 0,114,197, 0,112,199, 0, + 111,201, 0,111,202, 0,112,200, 0,113,198, 0,112,200, 0, + 111,202, 0,112,200, 0,114,197, 0,117,191, 0,121,182, 0, + 123,174, 1,122,175, 0,122,176, 0,123,171, 3,124,162, 10, + 124,162, 10,124,158, 13,124,160, 12,124,157, 15,124,161, 11, + 124,158, 13,123,171, 3,121,180, 0,120,184, 0,119,186, 0, + 120,184, 0,121,180, 0,123,174, 1,123,169, 4,124,167, 6, + 123,168, 5,123,169, 4,123,170, 3,123,172, 2,123,173, 1, + 123,173, 1,123,174, 1,121,179, 0,120,182, 0,120,184, 0, + 119,186, 0,119,187, 0,119,186, 0,118,188, 0,118,189, 0, + 118,189, 0,118,188, 0,118,188, 0,117,191, 0,117,191, 0, + 118,189, 0,120,182, 0,123,171, 3,124,162, 10,124,152, 20, + 124,143, 31,122,130, 53,118,114, 96,122,132, 48,124,166, 7, + 119,186, 0,114,196, 0,110,202, 0,107,207, 0,104,210, 0, + 100,215, 0, 97,218, 0, 96,219, 0, 95,220, 0, 93,221, 0, + 93,221, 0, 95,219, 0,100,215, 0,105,209, 0,106,208, 0, + 106,208, 0,103,211, 0,103,211, 0,105,209, 0,109,204, 0, + 111,201, 0,113,198, 0,115,194, 0,119,187, 0,119,185, 0, + 121,182, 0,122,178, 0,122,178, 0,122,176, 0,123,172, 2, + 123,168, 5,124,162, 10,124,152, 20,123,137, 41,124,145, 29, + 124,157, 15,124,162, 10,124,164, 9,124,160, 12,124,155, 16, + 124,160, 12,124,166, 7,122,178, 0,118,188, 0,114,196, 0, + 111,202, 0,107,206, 0,104,210, 0,102,213, 0,100,215, 0, + 99,215, 0,100,215, 0,102,213, 0,105,209, 0,108,205, 0, + 112,200, 0,114,196, 0,116,193, 0,117,191, 0,118,188, 0, + 119,186, 0,120,183, 0,122,178, 0,123,173, 1,124,166, 7, + 124,157, 15,124,158, 13,124,165, 8,123,172, 2,122,177, 0, + 121,180, 0,120,182, 0,121,182, 0,122,178, 0,120,182, 0, + 120,184, 0,119,185, 0,120,183, 0,122,178, 0,123,169, 4, + 124,166, 7,124,167, 6,124,165, 8,124,162, 10,124,158, 13, + 124,157, 15,124,157, 15,124,162, 10,123,169, 4,123,174, 1, + 122,177, 0,122,178, 0,122,176, 0,123,173, 1,123,169, 4, + 124,167, 6,123,172, 2,122,176, 0,122,178, 0,121,179, 0, + 120,184, 0,119,186, 0,119,187, 0,119,186, 0,121,181, 0, + 120,182, 0,118,189, 0,113,198, 0,109,204, 0,106,207, 0, + 105,209, 0,105,209, 0,101,214, 0, 99,216, 0, 98,217, 0, + 99,215, 0,102,213, 0,106,208, 0,107,206, 0,108,205, 0, + 110,203, 0,111,201, 0,113,198, 0,116,193, 0,119,187, 0, + 122,177, 0,124,161, 11,124,147, 26,124,150, 22,124,152, 20, + 124,152, 20,124,150, 22,124,149, 24,124,145, 29,124,145, 29, + 124,150, 22,124,158, 13,123,169, 4,122,175, 0,122,175, 0, + 123,170, 3,124,157, 15,122,130, 53,119,119, 77,123,137, 41, + 124,160, 12,123,171, 3,122,178, 0,121,181, 0,120,183, 0, + 120,184, 0,120,184, 0,119,186, 0,119,187, 0,119,187, 0, + 119,186, 0,120,182, 0,121,181, 0,120,182, 0,120,183, 0, + 118,188, 0,117,191, 0,117,191, 0,115,194, 0,110,202, 0, + 105,209, 0,100,214, 0, 97,218, 0, 95,220, 0, 93,221, 0, + 92,222, 0, 92,222, 0, 92,223, 0, 92,222, 0, 94,221, 0, + 95,219, 0,100,215, 0,105,209, 0,108,205, 0,105,209, 0, + 103,211, 0,103,211, 0,106,208, 0,110,202, 0,113,199, 0, + 114,196, 0,116,193, 0,116,193, 0,114,196, 0,113,199, 0, + 112,200, 0,113,198, 0,115,195, 0,114,197, 0,113,199, 0, + 111,201, 0,111,202, 0,110,202, 0,111,201, 0,113,199, 0, + 113,199, 0,112,199, 0,113,198, 0,116,193, 0,119,187, 0, + 119,185, 0,119,186, 0,120,184, 0,121,180, 0,123,172, 2, + 124,162, 10,124,155, 16,124,161, 11,124,164, 9,124,165, 8, + 123,168, 5,124,164, 9,124,167, 6,122,177, 0,120,182, 0, + 119,185, 0,119,185, 0,120,183, 0,122,178, 0,122,175, 0, + 123,174, 1,123,174, 1,122,175, 0,122,178, 0,121,180, 0, + 121,179, 0,122,178, 0,121,179, 0,120,183, 0,119,186, 0, + 118,188, 0,117,191, 0,117,192, 0,117,191, 0,117,190, 0, + 117,191, 0,116,192, 0,117,191, 0,116,193, 0,114,196, 0, + 113,198, 0,114,196, 0,117,191, 0,120,184, 0,122,176, 0, + 123,168, 5,124,158, 13,124,145, 29,121,125, 63,117,110,109, + 124,158, 13,121,180, 0,117,192, 0,112,199, 0,109,204, 0, + 106,207, 0,105,209, 0,102,212, 0,101,214, 0,100,215, 0, + 99,215, 0,100,215, 0,102,212, 0,106,208, 0,107,207, 0, + 106,208, 0,102,212, 0,101,214, 0,102,213, 0,105,209, 0, + 107,206, 0,108,205, 0,110,202, 0,114,197, 0,116,193, 0, + 117,191, 0,118,188, 0,120,184, 0,120,183, 0,121,181, 0, + 122,178, 0,123,173, 1,123,168, 5,124,161, 11,124,155, 16, + 124,158, 13,124,166, 7,123,170, 3,123,173, 1,123,172, 2, + 124,167, 6,123,169, 4,123,173, 1,122,178, 0,118,189, 0, + 113,198, 0,109,204, 0,105,209, 0,102,212, 0,101,214, 0, + 100,214, 0,101,214, 0,102,213, 0,104,210, 0,106,207, 0, + 109,203, 0,112,200, 0,114,196, 0,116,193, 0,117,190, 0, + 118,188, 0,120,184, 0,121,181, 0,122,177, 0,123,171, 3, + 124,165, 8,124,158, 13,124,158, 13,124,161, 11,124,162, 10, + 124,166, 7,123,171, 3,122,175, 0,122,175, 0,122,176, 0, + 121,181, 0,120,184, 0,120,184, 0,120,183, 0,122,178, 0, + 123,170, 3,124,164, 9,124,166, 7,124,167, 6,124,166, 7, + 124,165, 8,124,165, 8,124,166, 7,123,170, 3,122,175, 0, + 122,178, 0,121,179, 0,121,179, 0,122,177, 0,123,174, 1, + 123,170, 3,123,169, 4,123,174, 1,121,179, 0,121,181, 0, + 121,182, 0,121,181, 0,121,181, 0,120,183, 0,120,182, 0, + 122,178, 0,122,178, 0,119,187, 0,114,197, 0,110,203, 0, + 106,207, 0,104,210, 0,102,212, 0,101,214, 0, 99,216, 0, + 98,216, 0, 99,215, 0,101,213, 0,105,209, 0,107,207, 0, + 108,205, 0,110,203, 0,112,200, 0,114,196, 0,117,191, 0, + 121,182, 0,122,176, 0,123,168, 5,123,171, 3,123,172, 2, + 123,170, 3,124,164, 9,124,150, 22,124,147, 26,124,143, 31, + 124,143, 31,124,145, 29,124,152, 20,124,158, 13,124,166, 7, + 123,169, 4,124,166, 7,124,155, 16,122,132, 48,118,117, 85, + 122,130, 53,124,152, 20,124,165, 8,123,172, 2,122,176, 0, + 121,179, 0,121,180, 0,122,178, 0,122,178, 0,121,179, 0, + 122,178, 0,122,175, 0,123,172, 2,122,178, 0,121,180, 0, + 120,184, 0,118,189, 0,117,190, 0,117,191, 0,116,193, 0, + 111,201, 0,106,208, 0,101,213, 0, 98,217, 0, 96,219, 0, + 94,220, 0, 93,222, 0, 92,223, 0, 91,224, 0, 91,224, 0, + 91,223, 0, 93,221, 0, 97,217, 0,103,212, 0,105,209, 0, + 103,211, 0,101,214, 0,101,214, 0,103,211, 0,108,206, 0, + 112,199, 0,113,198, 0,112,200, 0,110,203, 0,107,206, 0, + 105,209, 0,105,209, 0,105,209, 0,108,206, 0,110,203, 0, + 112,199, 0,112,200, 0,111,202, 0,110,202, 0,111,202, 0, + 112,200, 0,113,198, 0,115,195, 0,116,193, 0,116,192, 0, + 116,192, 0,116,192, 0,117,192, 0,117,190, 0,119,186, 0, + 122,178, 0,123,168, 5,124,155, 16,124,162, 10,124,166, 7, + 123,168, 5,123,171, 3,123,170, 3,124,162, 10,123,171, 3, + 122,178, 0,120,182, 0,120,184, 0,120,183, 0,121,180, 0, + 122,178, 0,122,177, 0,121,181, 0,119,185, 0,119,187, 0, + 118,188, 0,119,185, 0,121,181, 0,120,182, 0,119,187, 0, + 118,189, 0,116,192, 0,115,194, 0,114,196, 0,115,195, 0, + 117,192, 0,116,193, 0,115,194, 0,115,194, 0,114,196, 0, + 112,199, 0,111,201, 0,111,201, 0,114,197, 0,117,191, 0, + 120,184, 0,122,177, 0,123,168, 5,124,154, 18,122,132, 48, + 122,130, 53,124,143, 31,123,172, 2,119,187, 0,115,195, 0, + 111,201, 0,109,204, 0,108,206, 0,107,207, 0,106,207, 0, + 106,208, 0,106,208, 0,107,206, 0,109,203, 0,110,202, 0, + 106,208, 0,102,212, 0, 99,215, 0, 98,216, 0,100,214, 0, + 103,211, 0,105,209, 0,106,207, 0,109,204, 0,112,199, 0, + 114,196, 0,116,193, 0,117,191, 0,118,189, 0,118,188, 0, + 119,185, 0,121,181, 0,122,176, 0,123,170, 3,124,166, 7, + 123,168, 5,123,169, 4,123,171, 3,122,175, 0,122,178, 0, + 122,178, 0,122,176, 0,122,175, 0,122,178, 0,121,181, 0, + 117,190, 0,113,199, 0,108,205, 0,104,210, 0,102,212, 0, + 102,212, 0,103,212, 0,104,210, 0,106,208, 0,108,205, 0, + 110,202, 0,112,199, 0,114,196, 0,116,192, 0,118,189, 0, + 119,186, 0,120,183, 0,122,178, 0,123,173, 1,123,168, 5, + 124,162, 10,124,155, 16,124,152, 20,124,155, 16,124,157, 15, + 124,160, 12,124,161, 11,124,162, 10,124,164, 9,124,167, 6, + 123,172, 2,122,178, 0,121,182, 0,120,182, 0,121,181, 0, + 122,176, 0,124,167, 6,124,160, 12,124,164, 9,124,166, 7, + 124,167, 6,124,167, 6,124,167, 6,123,168, 5,123,172, 2, + 122,176, 0,122,178, 0,122,178, 0,122,176, 0,123,173, 1, + 123,170, 3,124,167, 6,124,167, 6,123,173, 1,121,179, 0, + 120,182, 0,120,184, 0,120,183, 0,121,181, 0,122,178, 0, + 122,178, 0,122,176, 0,123,174, 1,119,186, 0,115,194, 0, + 111,202, 0,107,207, 0,103,211, 0,101,214, 0,100,215, 0, + 100,215, 0, 99,215, 0,100,215, 0,101,213, 0,104,210, 0, + 107,206, 0,109,203, 0,111,201, 0,113,198, 0,116,193, 0, + 118,189, 0,118,189, 0,119,186, 0,119,185, 0,118,188, 0, + 118,188, 0,119,186, 0,121,182, 0,123,171, 3,124,152, 20, + 123,137, 41,122,135, 44,122,135, 44,123,141, 34,124,147, 26, + 124,152, 20,124,158, 13,124,158, 13,124,150, 22,122,132, 48, + 117,110,109,119,119, 77,123,141, 34,124,157, 15,124,164, 9, + 123,170, 3,122,175, 0,122,175, 0,123,169, 4,124,167, 6, + 124,165, 8,124,161, 11,124,157, 15,123,168, 5,123,174, 1, + 121,181, 0,118,188, 0,117,190, 0,118,189, 0,116,193, 0, + 115,194, 0,112,199, 0,108,206, 0,104,210, 0,101,213, 0, + 99,215, 0, 97,218, 0, 95,220, 0, 93,221, 0, 92,223, 0, + 91,223, 0, 91,223, 0, 93,221, 0, 97,217, 0,102,213, 0, + 104,210, 0,101,214, 0, 99,216, 0, 99,216, 0,101,213, 0, + 106,208, 0,109,204, 0,108,205, 0,107,207, 0,104,210, 0, + 102,213, 0,100,215, 0, 98,216, 0, 99,215, 0,101,213, 0, + 104,210, 0,107,206, 0,111,201, 0,112,199, 0,112,200, 0, + 112,200, 0,112,199, 0,113,198, 0,113,198, 0,114,197, 0, + 114,197, 0,114,196, 0,114,196, 0,115,194, 0,117,192, 0, + 119,186, 0,121,179, 0,123,170, 3,124,158, 13,124,161, 11, + 124,166, 7,123,169, 4,123,171, 3,123,172, 2,123,169, 4, + 124,164, 9,123,170, 3,122,176, 0,121,179, 0,121,180, 0, + 122,178, 0,122,178, 0,120,184, 0,118,188, 0,117,191, 0, + 116,193, 0,117,192, 0,118,189, 0,120,183, 0,119,185, 0, + 117,191, 0,116,193, 0,115,195, 0,113,198, 0,112,199, 0, + 113,198, 0,115,195, 0,115,194, 0,114,196, 0,114,196, 0, + 114,197, 0,112,200, 0,110,202, 0,110,202, 0,112,200, 0, + 115,194, 0,118,189, 0,120,182, 0,123,173, 1,124,161, 11, + 123,141, 34,123,139, 37,123,137, 41,124,158, 13,122,178, 0, + 118,189, 0,114,196, 0,112,199, 0,111,201, 0,111,201, 0, + 111,201, 0,111,202, 0,110,202, 0,111,202, 0,110,203, 0, + 105,209, 0,102,213, 0, 99,216, 0, 97,218, 0, 97,218, 0, + 99,215, 0,102,212, 0,103,212, 0,104,210, 0,107,206, 0, + 112,200, 0,114,197, 0,115,194, 0,115,194, 0,116,193, 0, + 117,191, 0,118,188, 0,120,184, 0,121,182, 0,122,177, 0, + 123,171, 3,122,176, 0,121,179, 0,121,180, 0,122,178, 0, + 121,179, 0,121,181, 0,121,180, 0,122,178, 0,120,182, 0, + 120,184, 0,117,190, 0,113,199, 0,108,205, 0,106,208, 0, + 105,209, 0,105,209, 0,107,206, 0,110,203, 0,112,200, 0, + 114,196, 0,116,193, 0,117,191, 0,118,188, 0,119,185, 0, + 121,182, 0,122,178, 0,123,172, 2,124,165, 8,124,157, 15, + 124,147, 26,123,139, 37,122,132, 48,123,137, 41,124,143, 31, + 124,147, 26,124,150, 22,124,154, 18,124,155, 16,124,157, 15, + 124,161, 11,124,167, 6,123,173, 1,122,177, 0,122,178, 0, + 122,176, 0,123,170, 3,124,161, 11,124,152, 20,124,158, 13, + 124,161, 11,124,162, 10,124,162, 10,124,162, 10,124,164, 9, + 123,168, 5,123,171, 3,123,172, 2,123,170, 3,123,168, 5, + 124,165, 8,124,161, 11,124,160, 12,124,160, 12,123,169, 4, + 122,178, 0,120,182, 0,120,184, 0,120,184, 0,121,182, 0, + 122,178, 0,122,176, 0,123,172, 2,123,172, 2,119,185, 0, + 115,194, 0,111,201, 0,107,206, 0,103,211, 0,100,215, 0, + 98,217, 0, 97,217, 0, 99,216, 0,101,214, 0,102,212, 0, + 104,210, 0,107,207, 0,110,202, 0,113,198, 0,115,194, 0, + 116,193, 0,114,196, 0,114,196, 0,115,194, 0,114,196, 0, + 113,198, 0,113,198, 0,114,196, 0,117,192, 0,120,184, 0, + 123,169, 4,123,141, 34,120,122, 70,120,122, 70,121,125, 63, + 122,130, 53,122,135, 44,123,141, 34,124,147, 26,124,143, 31, + 122,130, 53,111, 96,248,114,104,197,122,130, 53,124,145, 29, + 124,154, 18,124,164, 9,123,168, 5,123,169, 4,124,161, 11, + 124,147, 26,123,141, 34,122,135, 44,124,154, 18,124,165, 8, + 122,177, 0,119,186, 0,117,190, 0,117,191, 0,117,191, 0, + 115,195, 0,114,197, 0,114,197, 0,111,202, 0,108,206, 0, + 106,208, 0,103,211, 0,101,213, 0, 99,216, 0, 97,218, 0, + 95,220, 0, 93,221, 0, 94,221, 0, 95,220, 0, 99,215, 0, + 102,213, 0,101,213, 0, 98,217, 0, 97,218, 0, 97,217, 0, + 100,214, 0,105,209, 0,105,209, 0,105,209, 0,103,212, 0, + 101,214, 0, 98,216, 0, 96,219, 0, 95,220, 0, 95,219, 0, + 98,217, 0,101,214, 0,104,210, 0,108,205, 0,113,198, 0, + 114,196, 0,114,197, 0,114,197, 0,114,197, 0,114,197, 0, + 113,198, 0,113,198, 0,114,197, 0,114,196, 0,116,193, 0, + 118,189, 0,120,183, 0,122,176, 0,124,167, 6,124,157, 15, + 124,157, 15,124,162, 10,124,166, 7,124,167, 6,123,172, 2, + 123,171, 3,124,167, 6,124,161, 11,124,167, 6,123,171, 3, + 123,173, 1,122,177, 0,121,182, 0,118,188, 0,117,192, 0, + 115,195, 0,114,196, 0,115,194, 0,117,191, 0,119,185, 0, + 118,189, 0,115,194, 0,114,197, 0,114,197, 0,112,200, 0, + 111,202, 0,111,201, 0,113,198, 0,114,196, 0,114,197, 0, + 113,198, 0,113,198, 0,112,199, 0,111,201, 0,111,202, 0, + 112,199, 0,115,194, 0,118,189, 0,120,184, 0,122,176, 0, + 124,164, 9,124,145, 29,123,139, 37,122,135, 44,122,130, 53, + 124,165, 8,121,180, 0,118,189, 0,116,193, 0,115,194, 0, + 115,194, 0,116,193, 0,115,194, 0,114,197, 0,111,202, 0, + 106,208, 0,101,213, 0, 98,216, 0, 97,218, 0, 95,219, 0, + 96,219, 0, 99,216, 0,100,215, 0,100,214, 0,102,212, 0, + 106,207, 0,111,201, 0,114,196, 0,114,197, 0,113,198, 0, + 114,197, 0,115,194, 0,117,191, 0,118,189, 0,119,187, 0, + 120,182, 0,122,177, 0,120,183, 0,119,187, 0,118,189, 0, + 118,188, 0,119,185, 0,121,181, 0,121,182, 0,121,181, 0, + 119,185, 0,118,188, 0,118,189, 0,114,197, 0,110,202, 0, + 108,206, 0,108,206, 0,110,202, 0,113,198, 0,115,194, 0, + 117,192, 0,119,186, 0,121,180, 0,122,178, 0,122,175, 0, + 123,172, 2,124,167, 6,124,160, 12,124,149, 24,123,141, 34, + 122,132, 48,120,122, 70,117,110,109,115,107,129,117,110,109, + 118,117, 85,121,127, 58,122,135, 44,123,139, 37,123,141, 34, + 124,143, 31,124,149, 24,124,157, 15,124,165, 8,123,168, 5, + 123,169, 4,124,167, 6,124,160, 12,124,147, 26,123,141, 34, + 124,149, 24,124,152, 20,124,152, 20,124,150, 22,124,149, 24, + 124,149, 24,124,154, 18,124,158, 13,124,158, 13,124,155, 16, + 124,152, 20,124,147, 26,124,150, 22,124,149, 24,124,149, 24, + 124,161, 11,123,173, 1,121,180, 0,120,183, 0,120,182, 0, + 121,180, 0,122,175, 0,123,171, 3,124,165, 8,122,176, 0, + 118,189, 0,113,199, 0,109,204, 0,106,208, 0,104,210, 0, + 100,215, 0, 97,217, 0, 97,218, 0, 98,217, 0,101,214, 0, + 103,211, 0,105,209, 0,107,206, 0,110,202, 0,115,195, 0, + 115,194, 0,112,199, 0,110,202, 0,110,203, 0,111,202, 0, + 110,203, 0,109,204, 0,109,204, 0,110,202, 0,113,198, 0, + 117,191, 0,121,180, 0,124,158, 13,118,114, 96,119,119, 77, + 121,127, 58,119,119, 77,119,119, 77,119,119, 77,122,130, 53, + 122,132, 48,120,122, 70,109, 92,251,105, 84,252,119,119, 77, + 122,135, 44,123,139, 37,124,150, 22,124,158, 13,124,158, 13, + 124,147, 26,121,125, 63,115,107,129,122,135, 44,124,158, 13, + 123,172, 2,120,182, 0,118,188, 0,117,191, 0,117,191, 0, + 115,194, 0,113,198, 0,112,199, 0,113,199, 0,114,197, 0, + 112,200, 0,110,202, 0,107,207, 0,105,209, 0,104,210, 0, + 101,213, 0, 99,215, 0, 98,217, 0, 98,217, 0, 99,215, 0, + 101,214, 0,102,213, 0, 98,217, 0, 95,220, 0, 95,220, 0, + 96,219, 0,100,215, 0,103,211, 0,103,211, 0,103,212, 0, + 101,213, 0,100,215, 0, 97,217, 0, 95,219, 0, 94,220, 0, + 95,220, 0, 97,218, 0,100,215, 0,103,211, 0,107,206, 0, + 112,200, 0,117,192, 0,117,191, 0,117,192, 0,116,193, 0, + 115,194, 0,115,195, 0,115,195, 0,115,194, 0,117,192, 0, + 118,188, 0,120,182, 0,122,175, 0,124,167, 6,124,160, 12, + 124,152, 20,124,150, 22,124,154, 18,124,160, 12,124,157, 15, + 124,167, 6,123,170, 3,123,169, 4,124,165, 8,124,155, 16, + 124,160, 12,123,169, 4,122,176, 0,121,182, 0,118,188, 0, + 116,193, 0,114,196, 0,114,197, 0,114,196, 0,116,192, 0, + 119,186, 0,116,193, 0,113,198, 0,112,200, 0,112,200, 0, + 110,202, 0,109,203, 0,110,203, 0,112,200, 0,113,199, 0, + 113,198, 0,112,200, 0,112,200, 0,113,199, 0,113,198, 0, + 113,198, 0,114,196, 0,117,192, 0,118,189, 0,119,186, 0, + 121,180, 0,123,169, 4,124,150, 22,122,132, 48,121,125, 63, + 119,119, 77,123,137, 41,124,166, 7,122,178, 0,120,184, 0, + 119,186, 0,119,185, 0,120,183, 0,119,187, 0,114,196, 0, + 108,205, 0,103,212, 0, 99,215, 0, 97,218, 0, 96,219, 0, + 95,219, 0, 96,219, 0, 97,218, 0, 97,218, 0, 98,217, 0, + 101,214, 0,105,209, 0,111,202, 0,115,195, 0,112,199, 0, + 111,201, 0,112,200, 0,114,197, 0,116,193, 0,117,191, 0, + 118,189, 0,119,186, 0,121,182, 0,118,188, 0,116,192, 0, + 115,195, 0,115,194, 0,117,191, 0,119,185, 0,121,180, 0, + 120,183, 0,118,188, 0,117,191, 0,117,192, 0,114,196, 0, + 112,200, 0,111,202, 0,112,200, 0,114,196, 0,114,197, 0, + 114,197, 0,115,194, 0,118,188, 0,122,177, 0,124,158, 13, + 124,152, 20,124,147, 26,123,141, 34,124,145, 29,124,143, 31, + 123,139, 37,121,127, 58,118,117, 85,118,114, 96,120,122, 70, + 121,127, 58,121,125, 63,119,119, 77,115,107,129,117,110,109, + 118,117, 85,118,117, 85,121,125, 63,123,137, 41,124,149, 24, + 124,154, 18,124,155, 16,124,152, 20,123,141, 34,120,122, 70, + 121,125, 63,122,132, 48,122,135, 44,122,130, 53,121,125, 63, + 118,117, 85,118,114, 96,120,122, 70,122,130, 53,122,130, 53, + 121,125, 63,123,137, 41,124,147, 26,124,152, 20,124,149, 24, + 122,135, 44,124,152, 20,124,167, 6,122,176, 0,121,179, 0, + 122,178, 0,123,174, 1,123,168, 5,124,161, 11,124,160, 12, + 121,181, 0,116,193, 0,110,202, 0,106,207, 0,104,210, 0, + 103,212, 0,101,214, 0, 98,217, 0, 97,217, 0, 98,216, 0, + 101,213, 0,105,209, 0,107,207, 0,109,204, 0,112,200, 0, + 115,194, 0,111,201, 0,108,205, 0,106,208, 0,105,209, 0, + 106,208, 0,107,207, 0,106,208, 0,106,207, 0,107,206, 0, + 110,202, 0,114,196, 0,119,186, 0,123,169, 4,122,135, 44, + 118,117, 85,121,127, 58,120,122, 70,115,107,129,117,110,109, + 118,114, 96,119,119, 77,118,114, 96,105, 84,252,102, 80,250, + 117,110,109,121,125, 63,121,127, 58,122,130, 53,123,139, 37, + 123,139, 37,120,122, 70,109, 92,251,119,119, 77,124,145, 29, + 124,164, 9,122,176, 0,120,184, 0,118,189, 0,117,191, 0, + 117,191, 0,114,197, 0,112,200, 0,111,202, 0,111,201, 0, + 114,197, 0,116,193, 0,114,197, 0,109,203, 0,107,207, 0, + 107,207, 0,106,207, 0,104,210, 0,103,212, 0,103,212, 0, + 102,213, 0,102,212, 0, 98,217, 0, 94,220, 0, 93,222, 0, + 93,221, 0, 96,219, 0,100,214, 0,104,210, 0,104,210, 0, + 102,213, 0, 99,215, 0, 98,217, 0, 98,217, 0, 97,218, 0, + 96,219, 0, 96,219, 0, 98,217, 0,101,214, 0,104,210, 0, + 108,205, 0,113,199, 0,117,191, 0,120,183, 0,120,184, 0, + 119,186, 0,118,188, 0,118,189, 0,118,189, 0,118,188, 0, + 120,184, 0,122,178, 0,123,169, 4,124,160, 12,124,150, 22, + 124,152, 20,124,150, 22,124,150, 22,124,147, 26,124,145, 29, + 123,141, 34,124,157, 15,124,165, 8,124,167, 6,124,166, 7, + 124,162, 10,124,164, 9,123,168, 5,123,174, 1,121,180, 0, + 119,187, 0,116,192, 0,114,196, 0,113,198, 0,114,197, 0, + 116,193, 0,119,187, 0,114,196, 0,111,201, 0,110,202, 0, + 110,203, 0,110,203, 0,109,204, 0,109,204, 0,111,201, 0, + 110,202, 0,110,202, 0,111,202, 0,111,202, 0,112,200, 0, + 113,198, 0,115,194, 0,118,189, 0,117,191, 0,117,191, 0, + 118,189, 0,119,186, 0,121,180, 0,123,169, 4,124,149, 24, + 117,110,109,111, 96,248,111, 96,248,123,137, 41,124,161, 11, + 123,171, 3,123,174, 1,123,173, 1,123,169, 4,119,186, 0, + 113,198, 0,107,207, 0,102,212, 0, 99,215, 0, 98,217, 0, + 97,218, 0, 97,218, 0, 95,220, 0, 94,221, 0, 93,221, 0, + 95,220, 0, 98,217, 0,103,211, 0,109,203, 0,115,194, 0, + 112,199, 0,111,201, 0,111,201, 0,112,199, 0,114,196, 0, + 117,192, 0,118,189, 0,119,186, 0,119,187, 0,116,192, 0, + 114,197, 0,113,199, 0,113,198, 0,115,194, 0,118,188, 0, + 122,178, 0,119,186, 0,117,191, 0,115,194, 0,114,196, 0, + 114,196, 0,113,198, 0,113,198, 0,114,196, 0,113,198, 0, + 113,199, 0,113,198, 0,115,194, 0,118,188, 0,122,175, 0, + 124,152, 20,118,114, 96,122,130, 53,123,137, 41,123,141, 34, + 123,139, 37,122,132, 48,119,119, 77,117,110,109,119,119, 77, + 121,127, 58,122,132, 48,122,135, 44,122,130, 53,119,119, 77, + 114,104,197,105, 84,252, 69, 60,230, 99, 75,247,111, 96,248, + 118,117, 85,121,127, 58,122,130, 53,121,125, 63,115,107,129, + 102, 80,250,111, 96,248,114,104,197,113,100,242,107, 89,252, + 94, 70,242, 30, 43,203, 30, 43,203, 30, 43,203, 87, 65,237, + 102, 80,250,115,107,129,121,127, 58,123,139, 37,123,141, 34, + 123,137, 41,119,119, 77,123,141, 34,124,160, 12,123,169, 4, + 123,172, 2,123,170, 3,124,164, 9,124,152, 20,123,139, 37, + 124,167, 6,119,185, 0,114,197, 0,108,205, 0,105,209, 0, + 102,212, 0,102,212, 0,103,212, 0,100,215, 0, 99,216, 0, + 100,215, 0,102,212, 0,106,208, 0,109,203, 0,112,200, 0, + 115,195, 0,111,201, 0,107,206, 0,103,211, 0,101,214, 0, + 100,215, 0,101,214, 0,102,212, 0,105,209, 0,106,208, 0, + 106,207, 0,109,204, 0,112,199, 0,117,191, 0,122,177, 0, + 124,152, 20,114,104,197,119,119, 77,118,117, 85,117,110,109, + 117,110,109,115,107,129,117,110,109,114,104,197,102, 80,250, + 111, 96,248,114,104,197,118,117, 85,119,119, 77,118,114, 96, + 115,107,129,114,104,197, 94, 70,242,117,110,109,122,135, 44, + 124,150, 22,124,162, 10,123,173, 1,121,182, 0,119,186, 0, + 118,188, 0,115,194, 0,112,200, 0,110,202, 0,109,204, 0, + 110,202, 0,113,199, 0,115,194, 0,118,189, 0,114,197, 0, + 111,201, 0,110,203, 0,110,203, 0,109,204, 0,107,207, 0, + 104,210, 0,103,211, 0, 99,216, 0, 95,220, 0, 92,222, 0, + 91,223, 0, 93,222, 0, 96,219, 0,101,214, 0,106,207, 0, + 103,211, 0,100,215, 0, 97,218, 0, 95,220, 0, 94,221, 0, + 95,220, 0, 97,218, 0, 99,215, 0,101,214, 0,103,212, 0, + 106,207, 0,110,202, 0,114,196, 0,118,188, 0,121,179, 0, + 123,169, 4,123,173, 1,122,177, 0,121,179, 0,121,179, 0, + 122,178, 0,123,172, 2,124,164, 9,124,149, 24,124,157, 15, + 124,160, 12,124,160, 12,124,157, 15,124,160, 12,124,160, 12, + 124,155, 16,124,160, 12,124,145, 29,124,154, 18,124,162, 10, + 124,166, 7,123,171, 3,122,176, 0,121,180, 0,120,184, 0, + 118,188, 0,118,188, 0,117,191, 0,114,196, 0,113,198, 0, + 114,197, 0,115,194, 0,117,190, 0,113,198, 0,110,202, 0, + 108,205, 0,108,206, 0,108,205, 0,108,205, 0,108,205, 0, + 108,206, 0,107,207, 0,106,207, 0,107,207, 0,108,205, 0, + 110,203, 0,112,200, 0,113,198, 0,113,198, 0,113,198, 0, + 115,194, 0,116,192, 0,117,191, 0,118,188, 0,121,182, 0, + 123,171, 3,124,154, 18,118,114, 96,111, 96,248,107, 89,252, + 121,125, 63,124,145, 29,124,154, 18,124,160, 12,123,174, 1, + 118,189, 0,112,200, 0,107,207, 0,103,211, 0,101,214, 0, + 100,215, 0, 95,219, 0, 92,222, 0, 91,224, 0, 89,225, 0, + 89,225, 0, 91,223, 0, 95,220, 0,101,214, 0,107,207, 0, + 113,198, 0,114,197, 0,112,200, 0,111,201, 0,112,200, 0, + 113,198, 0,114,196, 0,116,193, 0,117,191, 0,116,192, 0, + 114,196, 0,113,199, 0,112,200, 0,113,199, 0,115,194, 0, + 118,189, 0,119,186, 0,117,190, 0,115,195, 0,113,198, 0, + 112,200, 0,112,200, 0,112,199, 0,113,199, 0,113,198, 0, + 113,199, 0,113,199, 0,114,197, 0,116,192, 0,120,184, 0, + 123,170, 3,124,150, 22,123,137, 41,121,125, 63,122,130, 53, + 122,132, 48,122,130, 53,121,127, 58,123,141, 34,124,152, 20, + 124,157, 15,124,154, 18,124,149, 24,123,141, 34,122,135, 44, + 121,125, 63,119,119, 77,118,117, 85,118,114, 96,114,104,197, + 99, 75,247,102, 80,250,105, 84,252,105, 84,252,102, 80,250, + 30, 55,222, 30, 37,192, 69, 60,230, 87, 65,237, 87, 65,237, + 30, 49,213, 30, 31,180, 69, 60,230,105, 84,252,107, 89,252, + 107, 89,252,105, 84,252,105, 84,252,115,107,129,118,117, 85, + 119,119, 77,117,110,109,117,110,109,122,132, 48,124,150, 22, + 124,160, 12,124,160, 12,124,154, 18,123,139, 37,120,122, 70, + 124,157, 15,122,177, 0,117,191, 0,111,201, 0,106,207, 0, + 102,212, 0,101,214, 0,101,214, 0,102,213, 0,103,212, 0, + 102,212, 0,102,212, 0,103,211, 0,106,208, 0,109,204, 0, + 111,201, 0,110,202, 0,107,207, 0,102,212, 0, 99,216, 0, + 96,219, 0, 95,219, 0, 96,219, 0, 98,216, 0,101,213, 0, + 106,208, 0,106,207, 0,108,205, 0,111,201, 0,116,193, 0, + 121,182, 0,124,162, 10,121,127, 58,117,110,109,117,110,109, + 118,114, 96,117,110,109,114,104,197,111, 96,248,107, 89,252, + 111, 96,248,118,114, 96,118,117, 85,118,114, 96,118,117, 85, + 118,114, 96,113,100,242,105, 84,252,115,107,129,122,132, 48, + 124,150, 22,124,161, 11,123,169, 4,122,175, 0,121,180, 0, + 119,185, 0,117,190, 0,114,196, 0,111,201, 0,109,203, 0, + 109,204, 0,109,203, 0,112,200, 0,114,196, 0,117,192, 0, + 117,191, 0,115,194, 0,113,198, 0,111,201, 0,110,203, 0, + 107,206, 0,105,209, 0,101,214, 0, 97,218, 0, 93,222, 0, + 91,223, 0, 91,223, 0, 93,222, 0, 97,218, 0,102,213, 0, + 103,211, 0,103,212, 0, 99,215, 0, 96,219, 0, 94,221, 0, + 92,222, 0, 93,222, 0, 94,221, 0, 96,219, 0, 98,216, 0, + 102,213, 0,105,209, 0,109,204, 0,113,198, 0,116,192, 0, + 119,186, 0,121,179, 0,123,170, 3,124,160, 12,124,162, 10, + 124,164, 9,124,162, 10,124,157, 15,124,150, 22,124,152, 20, + 124,161, 11,124,164, 9,124,162, 10,124,161, 11,124,167, 6, + 123,170, 3,123,168, 5,123,171, 3,124,162, 10,124,152, 20, + 124,157, 15,123,168, 5,122,177, 0,120,183, 0,119,187, 0, + 117,191, 0,116,193, 0,116,192, 0,117,191, 0,115,194, 0, + 114,197, 0,114,196, 0,116,193, 0,116,193, 0,112,200, 0, + 109,204, 0,107,207, 0,106,208, 0,106,208, 0,106,208, 0, + 105,209, 0,104,210, 0,103,212, 0,102,212, 0,103,211, 0, + 104,210, 0,106,207, 0,108,205, 0,109,204, 0,109,204, 0, + 109,204, 0,110,202, 0,113,198, 0,116,193, 0,117,192, 0, + 118,189, 0,120,183, 0,123,173, 1,124,155, 16,119,119, 77, + 109, 92,251,113,100,242,121,127, 58,123,141, 34,124,165, 8, + 121,182, 0,116,193, 0,111,202, 0,107,207, 0,104,210, 0, + 102,212, 0, 97,217, 0, 91,223, 0, 88,226, 0, 86,228, 0, + 85,229, 0, 85,228, 0, 88,226, 0, 92,222, 0, 98,216, 0, + 105,209, 0,111,201, 0,113,199, 0,113,198, 0,112,200, 0, + 112,200, 0,112,199, 0,113,198, 0,114,196, 0,115,194, 0, + 114,196, 0,113,198, 0,112,200, 0,111,201, 0,112,200, 0, + 113,198, 0,114,196, 0,116,193, 0,115,195, 0,112,200, 0, + 110,203, 0,108,205, 0,108,205, 0,109,203, 0,111,202, 0, + 112,200, 0,113,199, 0,114,197, 0,115,194, 0,118,188, 0, + 121,179, 0,124,165, 8,124,162, 10,124,155, 16,124,149, 24, + 124,143, 31,124,143, 31,124,145, 29,124,155, 16,124,166, 7, + 123,173, 1,122,175, 0,123,174, 1,123,170, 3,124,165, 8, + 124,157, 15,124,149, 24,123,141, 34,123,137, 41,122,135, 44, + 121,127, 58,117,110,109,102, 80,250,105, 84,252,105, 84,252, + 94, 70,242, 30, 37,192, 30, 55,222,105, 84,252,109, 92,251, + 107, 89,252, 99, 75,247, 94, 70,242,111, 96,248,115,107,129, + 115,107,129,114,104,197,113,100,242,109, 92,251, 99, 75,247, + 107, 89,252,107, 89,252, 99, 75,247,113,100,242,120,122, 70, + 123,141, 34,124,147, 26,124,143, 31,121,127, 58,114,104,197, + 124,145, 29,123,170, 3,120,184, 0,114,196, 0,109,204, 0, + 104,210, 0,100,214, 0, 99,216, 0, 99,216, 0,100,215, 0, + 101,214, 0,103,211, 0,105,209, 0,105,209, 0,107,207, 0, + 108,205, 0,110,203, 0,106,208, 0,102,212, 0, 98,217, 0, + 95,220, 0, 92,222, 0, 92,222, 0, 93,221, 0, 96,219, 0, + 99,216, 0,103,211, 0,105,209, 0,107,207, 0,110,202, 0, + 115,195, 0,120,184, 0,123,168, 5,123,141, 34,114,104,197, + 113,100,242,114,104,197,113,100,242,107, 89,252, 87, 65,237, + 105, 84,252,117,110,109,121,127, 58,122,132, 48,122,132, 48, + 121,127, 58,119,119, 77,118,114, 96,118,117, 85,122,132, 48, + 124,149, 24,124,160, 12,124,167, 6,123,171, 3,122,176, 0, + 121,179, 0,120,184, 0,118,189, 0,115,194, 0,113,199, 0, + 110,202, 0,109,203, 0,110,202, 0,112,200, 0,114,197, 0, + 115,194, 0,116,193, 0,115,194, 0,113,198, 0,111,202, 0, + 108,205, 0,105,209, 0,102,213, 0, 98,216, 0, 95,220, 0, + 92,222, 0, 91,224, 0, 91,223, 0, 93,222, 0, 97,218, 0, + 101,214, 0,103,212, 0,105,209, 0,101,213, 0, 98,217, 0, + 95,220, 0, 93,222, 0, 92,222, 0, 92,222, 0, 94,221, 0, + 95,219, 0, 98,217, 0,101,213, 0,105,209, 0,109,204, 0, + 113,199, 0,116,192, 0,119,186, 0,122,178, 0,124,166, 7, + 124,150, 22,124,154, 18,124,157, 15,124,155, 16,124,152, 20, + 124,149, 24,124,157, 15,124,158, 13,124,157, 15,124,165, 8, + 123,171, 3,122,175, 0,122,176, 0,122,176, 0,123,170, 3, + 124,162, 10,124,154, 18,123,168, 5,121,179, 0,119,186, 0, + 117,191, 0,115,194, 0,115,195, 0,115,194, 0,116,193, 0, + 115,194, 0,114,196, 0,114,196, 0,115,194, 0,114,196, 0, + 111,201, 0,108,205, 0,106,208, 0,105,209, 0,104,210, 0, + 104,210, 0,103,211, 0,102,213, 0,100,214, 0,100,215, 0, + 101,214, 0,102,212, 0,104,210, 0,105,209, 0,106,207, 0, + 105,209, 0,105,209, 0,106,208, 0,108,205, 0,112,200, 0, + 115,194, 0,116,192, 0,118,189, 0,120,184, 0,123,174, 1, + 124,160, 12,123,137, 41,117,110,109,123,137, 41,124,158, 13, + 122,175, 0,118,188, 0,114,197, 0,109,203, 0,106,207, 0, + 105,209, 0,102,212, 0, 95,220, 0, 89,226, 0, 85,229, 0, + 83,230, 0, 82,231, 0, 83,230, 0, 86,228, 0, 91,223, 0, + 97,218, 0,104,210, 0,110,202, 0,111,202, 0,110,202, 0, + 111,202, 0,111,201, 0,112,199, 0,113,198, 0,114,197, 0, + 114,196, 0,114,197, 0,112,199, 0,111,202, 0,110,203, 0, + 109,203, 0,110,202, 0,111,201, 0,113,199, 0,112,200, 0, + 108,205, 0,106,208, 0,105,209, 0,105,209, 0,107,207, 0, + 109,204, 0,111,201, 0,113,198, 0,116,193, 0,118,188, 0, + 121,181, 0,123,169, 4,124,166, 7,124,167, 6,124,165, 8, + 124,161, 11,124,160, 12,124,158, 13,124,165, 8,123,173, 1, + 122,178, 0,120,183, 0,119,185, 0,120,184, 0,121,181, 0, + 122,175, 0,123,168, 5,124,160, 12,124,150, 22,124,143, 31, + 123,141, 34,123,137, 41,121,125, 63,114,104,197,107, 89,252, + 105, 84,252, 94, 70,242, 30, 55,222,109, 92,251,118,117, 85, + 119,119, 77,118,114, 96,111, 96,248,114,104,197,120,122, 70, + 122,130, 53,120,122, 70,114,104,197,111, 96,248,105, 84,252, + 94, 70,242, 30, 55,222, 30, 55,222, 69, 60,230,109, 92,251, + 118,114, 96,121,127, 58,122,130, 53,119,119, 77,118,114, 96, + 117,110,109,124,157, 15,122,178, 0,118,189, 0,112,199, 0, + 107,207, 0,102,212, 0, 99,215, 0, 98,217, 0, 98,217, 0, + 98,217, 0,100,215, 0,103,212, 0,107,207, 0,107,206, 0, + 108,206, 0,108,205, 0,107,206, 0,103,211, 0,100,215, 0, + 95,219, 0, 92,222, 0, 91,224, 0, 90,224, 0, 92,223, 0, + 94,220, 0, 98,217, 0,102,213, 0,104,210, 0,106,207, 0, + 110,203, 0,114,196, 0,119,186, 0,123,171, 3,124,149, 24, + 119,119, 77,107, 89,252,105, 84,252,102, 80,250, 69, 60,230, + 87, 65,237,111, 96,248,120,122, 70,123,137, 41,124,143, 31, + 123,141, 34,123,139, 37,122,132, 48,122,130, 53,122,132, 48, + 124,143, 31,124,155, 16,124,162, 10,123,168, 5,123,171, 3, + 123,173, 1,122,176, 0,121,179, 0,120,184, 0,117,190, 0, + 115,195, 0,113,198, 0,112,200, 0,112,200, 0,112,199, 0, + 114,197, 0,114,196, 0,114,196, 0,114,196, 0,114,197, 0, + 110,202, 0,107,207, 0,103,211, 0,100,214, 0, 97,217, 0, + 95,220, 0, 92,222, 0, 92,223, 0, 92,222, 0, 94,221, 0, + 97,218, 0,101,214, 0,103,211, 0,106,208, 0,105,209, 0, + 102,213, 0, 98,217, 0, 95,220, 0, 94,221, 0, 92,222, 0, + 93,222, 0, 94,221, 0, 96,219, 0, 98,216, 0,102,213, 0, + 106,208, 0,110,202, 0,114,196, 0,118,189, 0,121,181, 0, + 123,169, 4,124,154, 18,124,155, 16,124,157, 15,124,157, 15, + 124,154, 18,124,149, 24,124,147, 26,124,149, 24,124,157, 15, + 124,165, 8,123,171, 3,122,177, 0,122,178, 0,122,176, 0, + 123,172, 2,124,167, 6,124,161, 11,123,168, 5,122,178, 0, + 119,187, 0,117,192, 0,115,194, 0,115,194, 0,116,193, 0, + 117,192, 0,115,195, 0,114,197, 0,114,196, 0,114,196, 0, + 113,198, 0,111,201, 0,108,205, 0,107,207, 0,105,209, 0, + 105,209, 0,104,210, 0,103,212, 0,101,214, 0,100,215, 0, + 99,215, 0,100,215, 0,101,213, 0,103,211, 0,104,210, 0, + 105,209, 0,103,211, 0,102,213, 0,102,212, 0,103,211, 0, + 107,207, 0,111,201, 0,115,194, 0,116,192, 0,118,189, 0, + 120,184, 0,122,177, 0,123,168, 5,124,158, 13,124,157, 15, + 123,171, 3,121,182, 0,117,191, 0,113,199, 0,109,204, 0, + 107,207, 0,105,209, 0,101,213, 0, 94,220, 0, 88,226, 0, + 85,229, 0, 83,230, 0, 82,231, 0, 83,230, 0, 85,228, 0, + 91,224, 0, 97,218, 0,103,211, 0,109,204, 0,109,204, 0, + 108,205, 0,108,206, 0,109,204, 0,110,202, 0,113,198, 0, + 114,196, 0,115,195, 0,114,196, 0,112,199, 0,110,202, 0, + 109,204, 0,108,206, 0,107,206, 0,108,205, 0,109,203, 0, + 108,205, 0,105,209, 0,102,212, 0,101,214, 0,102,213, 0, + 104,210, 0,108,206, 0,112,200, 0,115,194, 0,118,188, 0, + 121,179, 0,124,167, 6,124,152, 20,124,162, 10,124,167, 6, + 123,169, 4,124,167, 6,124,166, 7,123,170, 3,122,176, 0, + 121,181, 0,120,184, 0,119,187, 0,118,189, 0,118,188, 0, + 119,185, 0,121,180, 0,123,171, 3,124,162, 10,124,150, 22, + 124,143, 31,123,141, 34,123,139, 37,122,130, 53,117,110,109, + 109, 92,251,107, 89,252,105, 84,252,107, 89,252,118,117, 85, + 122,132, 48,122,135, 44,121,127, 58,117,110,109,119,119, 77, + 122,135, 44,123,139, 37,121,127, 58,115,107,129,105, 84,252, + 87, 65,237, 30, 55,222, 30, 37,192, 30, 26,168, 30, 49,213, + 102, 80,250,114,104,197,118,114, 96,120,122, 70,122,130, 53, + 121,127, 58,119,119, 77,124,162, 10,121,180, 0,117,191, 0, + 111,201, 0,106,207, 0,102,212, 0, 99,215, 0, 98,217, 0, + 98,217, 0, 98,217, 0,100,215, 0,103,212, 0,107,206, 0, + 110,203, 0,109,203, 0,109,203, 0,107,207, 0,103,212, 0, + 99,215, 0, 95,220, 0, 92,222, 0, 91,224, 0, 90,224, 0, + 92,223, 0, 95,220, 0, 98,217, 0,102,213, 0,103,212, 0, + 105,209, 0,109,203, 0,114,196, 0,119,186, 0,123,172, 2, + 124,160, 12,123,141, 34,117,110,109,102, 80,250, 30, 55,222, + 30, 49,213, 87, 65,237,111, 96,248,121,125, 63,123,141, 34, + 124,145, 29,124,145, 29,123,141, 34,123,137, 41,122,135, 44, + 122,135, 44,124,145, 29,124,158, 13,124,167, 6,123,170, 3, + 123,171, 3,123,169, 4,123,168, 5,122,177, 0,121,182, 0, + 120,184, 0,118,189, 0,116,192, 0,115,194, 0,114,196, 0, + 114,196, 0,114,196, 0,114,197, 0,114,197, 0,114,197, 0, + 114,197, 0,111,202, 0,107,206, 0,103,211, 0,100,214, 0, + 98,217, 0, 96,219, 0, 95,220, 0, 95,220, 0, 95,220, 0, + 96,219, 0, 98,217, 0,100,214, 0,103,211, 0,107,206, 0, + 110,203, 0,107,207, 0,103,211, 0,100,215, 0, 97,217, 0, + 95,219, 0, 95,220, 0, 95,220, 0, 96,219, 0, 97,217, 0, + 100,214, 0,104,210, 0,109,204, 0,113,198, 0,117,190, 0, + 121,181, 0,124,167, 6,124,152, 20,124,157, 15,124,158, 13, + 124,157, 15,124,152, 20,124,147, 26,124,143, 31,124,147, 26, + 124,152, 20,124,160, 12,124,167, 6,123,173, 1,122,176, 0, + 123,170, 3,123,171, 3,123,170, 3,124,165, 8,123,170, 3, + 121,179, 0,120,184, 0,118,189, 0,117,192, 0,117,191, 0, + 117,190, 0,116,192, 0,114,197, 0,113,198, 0,114,196, 0, + 114,197, 0,112,199, 0,112,200, 0,110,202, 0,109,204, 0, + 107,206, 0,107,207, 0,106,208, 0,105,209, 0,102,212, 0, + 101,214, 0,101,214, 0,101,213, 0,103,212, 0,104,210, 0, + 105,209, 0,105,209, 0,103,211, 0,101,214, 0,100,215, 0, + 100,214, 0,103,212, 0,107,207, 0,112,200, 0,116,193, 0, + 117,192, 0,118,189, 0,119,186, 0,120,182, 0,122,177, 0, + 123,171, 3,122,176, 0,120,184, 0,117,191, 0,113,198, 0, + 110,202, 0,108,206, 0,106,207, 0,102,212, 0, 96,219, 0, + 91,224, 0, 87,227, 0, 85,229, 0, 84,229, 0, 85,229, 0, + 87,227, 0, 92,223, 0, 97,217, 0,103,211, 0,108,205, 0, + 107,207, 0,106,208, 0,106,208, 0,106,207, 0,109,204, 0, + 112,200, 0,115,194, 0,116,192, 0,115,194, 0,114,197, 0, + 111,201, 0,109,204, 0,107,207, 0,106,208, 0,106,208, 0, + 107,207, 0,105,209, 0,101,213, 0, 98,216, 0, 98,217, 0, + 99,215, 0,103,212, 0,107,206, 0,112,199, 0,117,191, 0, + 121,180, 0,124,166, 7,124,143, 31,122,130, 53,124,150, 22, + 124,162, 10,124,167, 6,123,168, 5,123,172, 2,122,178, 0, + 121,181, 0,120,184, 0,119,186, 0,118,188, 0,118,189, 0, + 118,189, 0,119,186, 0,121,180, 0,123,171, 3,124,160, 12, + 124,145, 29,122,135, 44,122,135, 44,123,137, 41,121,127, 58, + 117,110,109,111, 96,248,113,100,242,114,104,197,114,104,197, + 121,125, 63,123,139, 37,123,141, 34,122,135, 44,119,119, 77, + 121,127, 58,123,137, 41,123,137, 41,121,125, 63,113,100,242, + 99, 75,247, 30, 49,213, 30, 31,180, 30, 26,168, 30, 15,143, + 30, 31,180, 94, 70,242,115,107,129,122,130, 53,123,141, 34, + 123,141, 34,123,141, 34,122,135, 44,124,160, 12,121,179, 0, + 117,190, 0,112,199, 0,108,206, 0,104,210, 0,102,213, 0, + 100,214, 0,100,214, 0,100,214, 0,101,213, 0,104,210, 0, + 108,205, 0,112,199, 0,112,200, 0,112,200, 0,109,203, 0, + 105,209, 0,101,213, 0, 97,217, 0, 94,221, 0, 92,222, 0, + 92,222, 0, 93,221, 0, 96,219, 0, 99,215, 0,100,214, 0, + 102,213, 0,105,209, 0,109,204, 0,114,196, 0,119,187, 0, + 121,180, 0,123,170, 3,124,154, 18,121,127, 58,114,104,197, + 94, 70,242, 30, 26,168, 30, 49,213,107, 89,252,120,122, 70, + 123,137, 41,123,141, 34,123,141, 34,123,137, 41,122,130, 53, + 121,125, 63,121,127, 58,124,143, 31,124,160, 12,123,168, 5, + 123,172, 2,123,173, 1,123,171, 3,123,170, 3,122,177, 0, + 122,178, 0,121,182, 0,120,184, 0,119,186, 0,118,188, 0, + 118,189, 0,117,191, 0,116,193, 0,115,195, 0,114,197, 0, + 114,197, 0,114,197, 0,112,199, 0,109,204, 0,105,209, 0, + 102,212, 0,101,214, 0,100,214, 0,100,215, 0,100,215, 0, + 99,215, 0, 99,215, 0,100,215, 0,101,214, 0,103,211, 0, + 107,207, 0,112,200, 0,113,199, 0,109,203, 0,106,207, 0, + 103,211, 0,101,214, 0,100,215, 0, 99,216, 0, 98,216, 0, + 99,215, 0,101,214, 0,105,209, 0,109,203, 0,114,196, 0, + 119,187, 0,122,176, 0,124,160, 12,124,155, 16,124,157, 15, + 124,157, 15,124,154, 18,124,147, 26,123,141, 34,123,137, 41, + 123,137, 41,123,139, 37,124,147, 26,124,155, 16,124,162, 10, + 123,168, 5,124,161, 11,123,169, 4,123,170, 3,123,168, 5, + 123,172, 2,121,181, 0,119,185, 0,119,186, 0,119,186, 0, + 119,186, 0,118,189, 0,115,195, 0,113,199, 0,112,199, 0, + 113,198, 0,114,196, 0,112,199, 0,112,200, 0,113,199, 0, + 112,200, 0,111,201, 0,110,202, 0,109,203, 0,108,205, 0, + 106,208, 0,104,210, 0,103,211, 0,104,210, 0,105,209, 0, + 106,207, 0,107,207, 0,106,208, 0,104,210, 0,101,214, 0, + 99,216, 0, 98,216, 0,100,215, 0,104,210, 0,109,204, 0, + 114,196, 0,117,192, 0,117,191, 0,117,190, 0,118,189, 0, + 119,186, 0,121,181, 0,122,177, 0,120,183, 0,118,189, 0, + 115,195, 0,112,200, 0,110,203, 0,108,206, 0,105,209, 0, + 100,215, 0, 95,219, 0, 93,222, 0, 91,224, 0, 89,225, 0, + 89,226, 0, 91,224, 0, 94,221, 0, 99,215, 0,105,209, 0, + 108,205, 0,107,207, 0,105,209, 0,104,210, 0,105,209, 0, + 108,206, 0,112,200, 0,116,193, 0,118,189, 0,116,193, 0, + 114,196, 0,112,199, 0,109,203, 0,107,207, 0,105,209, 0, + 104,210, 0,105,209, 0,103,212, 0, 99,216, 0, 96,219, 0, + 95,219, 0, 98,217, 0,102,212, 0,108,206, 0,114,197, 0, + 118,189, 0,120,184, 0,123,174, 1,124,155, 16,122,135, 44, + 122,130, 53,124,149, 24,124,160, 12,124,167, 6,122,175, 0, + 121,179, 0,121,182, 0,120,183, 0,120,184, 0,119,185, 0, + 119,187, 0,119,187, 0,120,184, 0,122,177, 0,124,167, 6, + 124,152, 20,124,147, 26,123,141, 34,121,127, 58,122,130, 53, + 120,122, 70,115,107,129,113,100,242,118,114, 96,119,119, 77, + 118,117, 85,122,130, 53,124,143, 31,124,143, 31,123,137, 41, + 121,125, 63,122,130, 53,122,135, 44,122,132, 48,118,114, 96, + 105, 84,252, 99, 75,247, 30, 49,213, 30, 20,155, 30, 15,143, + 30, 20,155, 30, 31,180, 94, 70,242,118,117, 85,123,141, 34, + 124,155, 16,124,160, 12,124,157, 15,124,147, 26,124,150, 22, + 123,173, 1,119,186, 0,115,195, 0,111,201, 0,108,206, 0, + 106,208, 0,105,209, 0,104,210, 0,104,210, 0,105,209, 0, + 106,207, 0,110,203, 0,114,197, 0,115,194, 0,115,194, 0, + 113,198, 0,109,203, 0,106,208, 0,102,213, 0, 98,217, 0, + 95,219, 0, 95,220, 0, 95,219, 0, 98,217, 0,100,215, 0, + 100,215, 0,101,213, 0,105,209, 0,109,203, 0,114,196, 0, + 117,191, 0,120,184, 0,122,175, 0,124,160, 12,123,141, 34, + 121,125, 63,113,100,242, 30, 55,222, 30, 20,155, 94, 70,242, + 117,110,109,121,127, 58,122,132, 48,122,130, 53,120,122, 70, + 118,114, 96,115,107,129,118,114, 96,123,137, 41,124,155, 16, + 124,165, 8,123,170, 3,123,172, 2,123,171, 3,123,173, 1, + 121,180, 0,120,182, 0,121,182, 0,120,182, 0,119,186, 0, + 118,189, 0,117,190, 0,117,190, 0,118,189, 0,117,192, 0, + 115,194, 0,114,196, 0,115,195, 0,114,196, 0,112,200, 0, + 109,204, 0,107,207, 0,106,208, 0,106,208, 0,106,208, 0, + 106,208, 0,105,209, 0,104,210, 0,103,211, 0,103,211, 0, + 104,210, 0,107,207, 0,111,201, 0,116,193, 0,116,193, 0, + 113,198, 0,110,202, 0,108,205, 0,106,208, 0,105,209, 0, + 103,211, 0,103,211, 0,104,210, 0,107,206, 0,112,200, 0, + 117,191, 0,121,181, 0,124,166, 7,124,157, 15,124,157, 15, + 124,155, 16,124,152, 20,124,143, 31,122,132, 48,121,125, 63, + 118,117, 85,118,114, 96,118,114, 96,119,119, 77,121,127, 58, + 123,141, 34,124,150, 22,124,152, 20,124,164, 9,123,168, 5, + 123,168, 5,122,175, 0,121,182, 0,119,185, 0,119,186, 0, + 120,183, 0,120,182, 0,117,191, 0,113,198, 0,111,201, 0, + 111,201, 0,112,199, 0,114,196, 0,114,197, 0,113,198, 0, + 114,197, 0,115,194, 0,115,194, 0,115,195, 0,114,197, 0, + 113,199, 0,110,202, 0,108,205, 0,108,206, 0,108,205, 0, + 108,205, 0,106,207, 0,105,209, 0,105,209, 0,106,208, 0, + 102,212, 0, 99,215, 0, 98,217, 0, 99,216, 0,102,212, 0, + 107,206, 0,113,198, 0,117,191, 0,117,191, 0,117,192, 0, + 117,191, 0,118,189, 0,119,185, 0,122,178, 0,122,177, 0, + 120,183, 0,118,189, 0,115,194, 0,112,199, 0,110,203, 0, + 108,205, 0,105,209, 0,102,212, 0,100,215, 0, 97,217, 0, + 95,219, 0, 94,220, 0, 95,220, 0, 97,217, 0,101,213, 0, + 106,208, 0,109,204, 0,107,207, 0,105,209, 0,104,210, 0, + 105,209, 0,107,206, 0,111,201, 0,116,192, 0,119,187, 0, + 116,193, 0,114,197, 0,112,199, 0,110,202, 0,107,207, 0, + 105,209, 0,103,211, 0,105,209, 0,101,213, 0, 97,218, 0, + 94,220, 0, 94,220, 0, 97,218, 0,102,212, 0,109,204, 0, + 115,194, 0,117,191, 0,118,188, 0,121,181, 0,124,166, 7, + 124,152, 20,124,147, 26,122,132, 48,124,145, 29,124,165, 8, + 123,174, 1,122,178, 0,121,179, 0,121,179, 0,121,179, 0, + 121,180, 0,120,182, 0,120,182, 0,121,179, 0,123,172, 2, + 124,161, 11,124,152, 20,124,149, 24,123,141, 34,121,127, 58, + 121,125, 63,119,119, 77,114,104,197,115,107,129,120,122, 70, + 122,130, 53,122,130, 53,122,130, 53,124,143, 31,124,143, 31, + 123,137, 41,121,125, 63,121,127, 58,122,130, 53,120,122, 70, + 111, 96,248,111, 96,248,105, 84,252, 30, 55,222, 30, 20,155, + 30, 10,132, 30, 31,180, 30, 43,203, 87, 65,237,118,117, 85, + 124,149, 24,124,165, 8,123,171, 3,123,172, 2,123,168, 5, + 124,160, 12,124,165, 8,122,178, 0,118,188, 0,115,195, 0, + 112,199, 0,110,202, 0,110,203, 0,109,203, 0,109,204, 0, + 109,204, 0,110,202, 0,112,199, 0,115,194, 0,118,188, 0, + 119,186, 0,118,188, 0,115,195, 0,111,201, 0,107,207, 0, + 103,212, 0,100,215, 0, 98,217, 0, 98,217, 0,100,215, 0, + 101,214, 0,100,214, 0,102,212, 0,105,209, 0,110,203, 0, + 114,196, 0,117,191, 0,119,185, 0,122,177, 0,124,161, 11, + 124,154, 18,123,141, 34,120,122, 70,107, 89,252, 30, 26,168, + 30, 31,180,107, 89,252,117,110,109,118,114, 96,117,110,109, + 113,100,242,105, 84,252, 99, 75,247,109, 92,251,119,119, 77, + 124,143, 31,124,158, 13,124,166, 7,123,169, 4,123,171, 3, + 123,173, 1,121,180, 0,120,183, 0,120,184, 0,119,185, 0, + 119,186, 0,119,187, 0,118,189, 0,118,189, 0,118,188, 0, + 119,187, 0,117,191, 0,116,192, 0,117,192, 0,117,191, 0, + 115,194, 0,113,198, 0,112,200, 0,112,200, 0,112,199, 0, + 110,202, 0,108,205, 0,107,206, 0,107,206, 0,108,205, 0, + 107,207, 0,107,207, 0,109,204, 0,112,200, 0,115,194, 0, + 118,189, 0,117,190, 0,117,190, 0,115,194, 0,114,197, 0, + 112,200, 0,110,203, 0,109,204, 0,109,203, 0,112,200, 0, + 116,193, 0,120,184, 0,123,170, 3,124,157, 15,124,157, 15, + 124,158, 13,124,157, 15,124,149, 24,122,132, 48,117,110,109, + 105, 84,252, 99, 75,247, 69, 60,230,102, 80,250,111, 96,248, + 113,100,242,113,100,242,121,127, 58,123,139, 37,124,157, 15, + 124,164, 9,123,171, 3,122,178, 0,120,183, 0,119,186, 0, + 119,185, 0,120,182, 0,118,188, 0,116,193, 0,113,198, 0, + 111,202, 0,110,202, 0,111,201, 0,113,198, 0,115,194, 0, + 115,195, 0,115,194, 0,117,191, 0,119,186, 0,118,189, 0, + 116,193, 0,115,194, 0,115,195, 0,113,199, 0,112,200, 0, + 111,202, 0,109,204, 0,107,207, 0,106,208, 0,106,208, 0, + 107,206, 0,104,210, 0,101,214, 0, 99,215, 0,100,215, 0, + 103,211, 0,108,205, 0,113,198, 0,118,189, 0,117,190, 0, + 117,191, 0,117,191, 0,118,189, 0,119,185, 0,122,178, 0, + 123,170, 3,123,173, 1,120,182, 0,118,189, 0,115,194, 0, + 113,199, 0,110,202, 0,108,205, 0,107,207, 0,107,207, 0, + 105,209, 0,102,212, 0,101,214, 0,100,214, 0,101,213, 0, + 104,210, 0,108,205, 0,111,201, 0,109,204, 0,106,208, 0, + 105,209, 0,105,209, 0,107,206, 0,111,201, 0,116,192, 0, + 120,183, 0,117,191, 0,114,196, 0,113,199, 0,110,202, 0, + 107,207, 0,105,209, 0,103,211, 0,105,209, 0,101,214, 0, + 97,218, 0, 94,220, 0, 94,220, 0, 97,218, 0,102,212, 0, + 109,204, 0,116,193, 0,117,192, 0,118,189, 0,120,183, 0, + 123,171, 3,124,157, 15,124,152, 20,123,139, 37,122,135, 44, + 124,161, 11,123,171, 3,122,175, 0,122,178, 0,120,183, 0, + 120,184, 0,120,182, 0,122,177, 0,122,177, 0,123,173, 1, + 124,166, 7,124,154, 18,124,147, 26,123,141, 34,122,132, 48, + 118,117, 85,121,125, 63,119,119, 77,114,104,197,115,107,129, + 121,127, 58,123,137, 41,123,137, 41,121,127, 58,123,141, 34, + 123,141, 34,122,135, 44,120,122, 70,121,127, 58,121,125, 63, + 118,114, 96,105, 84,252,109, 92,251,105, 84,252, 69, 60,230, + 30, 26,168, 30, 26,168, 30, 55,222, 69, 60,230, 69, 60,230, + 118,117, 85,124,152, 20,123,170, 3,122,178, 0,121,180, 0, + 122,178, 0,123,174, 1,123,168, 5,122,178, 0,120,183, 0, + 118,188, 0,117,192, 0,115,194, 0,115,195, 0,114,196, 0, + 114,196, 0,114,197, 0,114,197, 0,115,195, 0,117,192, 0, + 119,187, 0,121,181, 0,122,177, 0,120,184, 0,117,192, 0, + 112,200, 0,107,206, 0,103,211, 0,101,214, 0,100,214, 0, + 101,213, 0,103,211, 0,103,212, 0,104,210, 0,107,207, 0, + 110,202, 0,114,196, 0,118,188, 0,120,182, 0,123,172, 2, + 123,168, 5,124,164, 9,124,155, 16,123,139, 37,118,114, 96, + 69, 60,230, 69, 60,230, 69, 60,230,107, 89,252,109, 92,251, + 111, 96,248,114,104,197,113,100,242,114,104,197,114,104,197, + 113,100,242,122,130, 53,124,149, 24,124,160, 12,124,167, 6, + 123,171, 3,123,173, 1,122,176, 0,122,178, 0,121,182, 0, + 119,185, 0,118,188, 0,118,188, 0,119,186, 0,119,186, 0, + 120,184, 0,121,181, 0,119,186, 0,119,187, 0,119,187, 0, + 119,186, 0,119,185, 0,118,188, 0,117,190, 0,118,189, 0, + 115,195, 0,112,199, 0,110,202, 0,109,203, 0,109,204, 0, + 110,203, 0,111,201, 0,112,200, 0,113,199, 0,114,196, 0, + 117,191, 0,120,184, 0,120,184, 0,119,185, 0,119,185, 0, + 120,184, 0,118,188, 0,116,193, 0,114,196, 0,114,196, 0, + 116,192, 0,119,186, 0,123,173, 1,124,162, 10,123,168, 5, + 123,171, 3,123,170, 3,124,166, 7,124,155, 16,123,137, 41, + 115,107,129, 94, 70,242, 69, 60,230, 30, 49,213, 94, 70,242, + 111, 96,248,118,117, 85,121,127, 58,122,135, 44,124,150, 22, + 124,158, 13,123,168, 5,122,175, 0,121,181, 0,120,184, 0, + 119,185, 0,120,184, 0,119,187, 0,116,192, 0,114,197, 0, + 112,199, 0,111,202, 0,110,203, 0,110,202, 0,112,200, 0, + 114,197, 0,115,195, 0,116,193, 0,117,192, 0,118,189, 0, + 118,188, 0,117,191, 0,116,193, 0,116,193, 0,115,194, 0, + 114,197, 0,112,199, 0,111,202, 0,109,203, 0,109,204, 0, + 109,203, 0,109,204, 0,106,208, 0,103,211, 0,102,212, 0, + 103,211, 0,107,207, 0,111,201, 0,116,192, 0,119,187, 0, + 118,189, 0,117,190, 0,118,189, 0,118,188, 0,120,183, 0, + 122,176, 0,123,168, 5,123,172, 2,121,181, 0,119,185, 0, + 118,188, 0,115,194, 0,112,200, 0,110,202, 0,109,204, 0, + 109,204, 0,110,202, 0,110,202, 0,108,206, 0,107,207, 0, + 107,207, 0,108,205, 0,111,201, 0,114,197, 0,111,201, 0, + 108,205, 0,107,207, 0,107,207, 0,109,204, 0,112,199, 0, + 117,192, 0,120,182, 0,119,186, 0,116,192, 0,114,196, 0, + 111,202, 0,107,206, 0,105,209, 0,104,210, 0,105,209, 0, + 102,213, 0, 98,217, 0, 96,219, 0, 96,219, 0, 99,216, 0, + 104,210, 0,110,202, 0,116,193, 0,117,191, 0,118,189, 0, + 120,184, 0,123,173, 1,124,155, 16,124,152, 20,124,143, 31, + 124,149, 24,124,161, 11,123,170, 3,122,178, 0,120,183, 0, + 119,186, 0,119,186, 0,120,184, 0,122,178, 0,123,170, 3, + 124,166, 7,124,158, 13,124,147, 26,123,137, 41,121,125, 63, + 118,117, 85,121,127, 58,122,132, 48,121,127, 58,117,110,109, + 111, 96,248,120,122, 70,123,137, 41,123,139, 37,122,132, 48, + 123,141, 34,123,141, 34,122,132, 48,120,122, 70,121,127, 58, + 122,135, 44,122,135, 44,118,117, 85,111, 96,248,107, 89,252, + 69, 60,230, 30, 55,222, 87, 65,237,107, 89,252,109, 92,251, + 105, 84,252,117,110,109,124,150, 22,123,170, 3,121,180, 0, + 120,184, 0,120,184, 0,121,182, 0,122,178, 0,121,179, 0, + 120,184, 0,119,186, 0,119,186, 0,120,184, 0,117,191, 0, + 114,196, 0,114,197, 0,115,195, 0,116,192, 0,118,188, 0, + 119,186, 0,120,183, 0,121,179, 0,123,173, 1,120,182, 0, + 118,188, 0,116,193, 0,111,201, 0,107,207, 0,104,210, 0, + 103,212, 0,103,211, 0,105,209, 0,107,207, 0,107,206, 0, + 109,203, 0,112,199, 0,115,194, 0,118,188, 0,121,182, 0, + 122,176, 0,123,173, 1,123,169, 4,124,164, 9,124,152, 20, + 122,132, 48,113,100,242,114,104,197,115,107,129,117,110,109, + 118,117, 85,120,122, 70,120,122, 70,118,117, 85,119,119, 77, + 118,117, 85,115,107,129,119,119, 77,124,143, 31,124,157, 15, + 124,166, 7,123,172, 2,122,176, 0,121,179, 0,120,182, 0, + 120,184, 0,120,182, 0,119,186, 0,118,188, 0,118,188, 0, + 120,184, 0,122,177, 0,123,172, 2,122,178, 0,121,180, 0, + 121,179, 0,122,178, 0,122,176, 0,122,175, 0,122,177, 0, + 121,182, 0,118,188, 0,116,193, 0,114,197, 0,112,200, 0, + 111,201, 0,112,200, 0,112,199, 0,113,199, 0,114,196, 0, + 117,190, 0,119,186, 0,121,180, 0,123,174, 1,122,177, 0, + 122,177, 0,122,175, 0,123,173, 1,121,180, 0,120,184, 0, + 119,185, 0,120,184, 0,120,183, 0,122,178, 0,123,173, 1, + 122,176, 0,122,178, 0,122,175, 0,123,169, 4,124,157, 15, + 122,135, 44,118,117, 85,115,107,129,111, 96,248,114,104,197, + 115,107,129,118,114, 96,122,130, 53,123,139, 37,124,145, 29, + 124,155, 16,124,164, 9,123,171, 3,122,177, 0,121,181, 0, + 120,182, 0,120,184, 0,118,188, 0,116,192, 0,114,196, 0, + 112,200, 0,110,202, 0,110,202, 0,110,203, 0,109,203, 0, + 110,202, 0,112,200, 0,113,198, 0,114,196, 0,115,194, 0, + 117,192, 0,118,189, 0,118,188, 0,117,190, 0,117,192, 0, + 116,192, 0,115,194, 0,114,196, 0,114,197, 0,113,198, 0, + 113,198, 0,113,199, 0,111,202, 0,109,204, 0,108,206, 0, + 108,205, 0,110,203, 0,113,198, 0,117,191, 0,120,182, 0, + 119,185, 0,119,186, 0,119,187, 0,119,186, 0,120,184, 0, + 121,180, 0,123,174, 1,123,170, 3,123,173, 1,123,172, 2, + 122,177, 0,120,183, 0,117,191, 0,114,196, 0,112,200, 0, + 111,202, 0,110,202, 0,112,200, 0,114,196, 0,116,193, 0, + 114,196, 0,114,197, 0,114,196, 0,115,194, 0,117,192, 0, + 114,196, 0,112,200, 0,110,202, 0,110,202, 0,112,200, 0, + 115,195, 0,118,188, 0,121,180, 0,121,182, 0,118,188, 0, + 115,194, 0,112,200, 0,108,205, 0,106,207, 0,106,208, 0, + 107,207, 0,103,211, 0,100,214, 0, 99,216, 0, 99,215, 0, + 102,212, 0,107,207, 0,113,199, 0,116,193, 0,117,191, 0, + 118,188, 0,120,183, 0,123,173, 1,124,154, 18,124,149, 24, + 124,145, 29,124,158, 13,123,169, 4,122,177, 0,120,182, 0, + 119,186, 0,118,188, 0,118,188, 0,119,185, 0,121,180, 0, + 123,173, 1,124,165, 8,124,155, 16,123,141, 34,121,125, 63, + 120,122, 70,121,125, 63,123,137, 41,124,143, 31,123,137, 41, + 120,122, 70,115,107,129,118,114, 96,122,132, 48,123,139, 37, + 122,130, 53,123,141, 34,123,141, 34,122,132, 48,119,119, 77, + 122,135, 44,124,147, 26,124,150, 22,123,139, 37,119,119, 77, + 115,107,129,113,100,242,109, 92,251,114,104,197,119,119, 77, + 121,125, 63,118,117, 85,114,104,197,123,141, 34,124,167, 6, + 121,180, 0,119,186, 0,118,188, 0,119,187, 0,120,184, 0, + 120,183, 0,119,185, 0,119,187, 0,118,188, 0,117,190, 0, + 117,192, 0,115,194, 0,114,197, 0,114,196, 0,116,192, 0, + 119,187, 0,121,180, 0,122,177, 0,123,174, 1,123,170, 3, + 122,176, 0,120,182, 0,119,186, 0,115,195, 0,111,201, 0, + 108,206, 0,106,208, 0,106,208, 0,107,206, 0,109,204, 0, + 111,201, 0,113,198, 0,115,194, 0,118,189, 0,120,184, 0, + 121,180, 0,122,176, 0,123,174, 1,123,172, 2,123,168, 5, + 124,158, 13,124,145, 29,122,132, 48,123,139, 37,123,139, 37, + 123,141, 34,124,143, 31,123,141, 34,123,137, 41,121,125, 63, + 119,119, 77,118,114, 96,113,100,242,118,117, 85,123,139, 37, + 124,155, 16,124,166, 7,123,172, 2,122,177, 0,121,179, 0, + 120,183, 0,120,184, 0,120,182, 0,119,185, 0,118,188, 0, + 118,189, 0,119,186, 0,122,178, 0,123,168, 5,123,168, 5, + 123,170, 3,123,168, 5,124,165, 8,124,161, 11,124,160, 12, + 124,162, 10,123,169, 4,122,178, 0,119,186, 0,117,191, 0, + 115,194, 0,114,196, 0,114,197, 0,114,196, 0,114,196, 0, + 116,193, 0,119,186, 0,121,180, 0,122,175, 0,124,166, 7, + 124,162, 10,124,162, 10,124,160, 12,124,152, 20,124,162, 10, + 123,169, 4,121,180, 0,119,185, 0,119,186, 0,120,183, 0, + 122,178, 0,121,179, 0,121,179, 0,122,176, 0,123,169, 4, + 124,157, 15,122,135, 44,122,130, 53,122,130, 53,123,137, 41, + 123,139, 37,123,139, 37,122,132, 48,122,132, 48,123,141, 34, + 124,149, 24,124,155, 16,124,165, 8,123,171, 3,122,176, 0, + 121,179, 0,121,182, 0,118,188, 0,116,193, 0,114,196, 0, + 113,199, 0,111,202, 0,110,203, 0,110,203, 0,111,202, 0, + 110,202, 0,110,202, 0,111,201, 0,112,199, 0,114,197, 0, + 115,194, 0,117,192, 0,118,189, 0,119,185, 0,119,185, 0, + 119,187, 0,118,189, 0,117,190, 0,117,191, 0,117,191, 0, + 118,189, 0,117,191, 0,115,194, 0,114,197, 0,113,198, 0, + 113,198, 0,114,196, 0,117,192, 0,119,186, 0,122,177, 0, + 122,178, 0,121,181, 0,121,182, 0,121,182, 0,121,181, 0, + 122,178, 0,122,175, 0,123,170, 3,124,166, 7,123,169, 4, + 124,167, 6,124,165, 8,122,177, 0,119,185, 0,117,191, 0, + 115,195, 0,114,197, 0,114,197, 0,115,195, 0,117,192, 0, + 118,188, 0,120,184, 0,121,182, 0,120,183, 0,120,183, 0, + 119,186, 0,117,190, 0,116,193, 0,115,194, 0,115,194, 0, + 116,192, 0,118,188, 0,120,183, 0,122,178, 0,122,175, 0, + 120,183, 0,117,192, 0,113,198, 0,110,202, 0,108,205, 0, + 108,205, 0,109,204, 0,106,208, 0,103,211, 0,103,212, 0, + 103,211, 0,106,207, 0,111,202, 0,115,194, 0,116,193, 0, + 117,191, 0,119,187, 0,121,181, 0,123,171, 3,124,154, 18, + 123,139, 37,124,145, 29,124,162, 10,123,173, 1,121,180, 0, + 120,184, 0,119,186, 0,119,187, 0,119,186, 0,120,184, 0, + 121,180, 0,123,174, 1,124,167, 6,124,157, 15,123,141, 34, + 118,117, 85,121,125, 63,122,130, 53,123,141, 34,124,149, 24, + 124,143, 31,122,130, 53,117,110,109,115,107,129,121,127, 58, + 122,135, 44,122,132, 48,124,143, 31,124,143, 31,122,132, 48, + 117,110,109,123,139, 37,124,154, 18,124,160, 12,124,154, 18, + 123,141, 34,122,130, 53,120,122, 70,118,114, 96,122,130, 53, + 123,141, 34,124,145, 29,124,143, 31,121,127, 58,121,127, 58, + 124,161, 11,122,178, 0,119,186, 0,118,189, 0,118,189, 0, + 118,188, 0,119,186, 0,119,187, 0,118,189, 0,117,192, 0, + 115,194, 0,114,197, 0,113,198, 0,114,196, 0,115,194, 0, + 117,191, 0,119,186, 0,122,178, 0,124,167, 6,124,166, 7, + 124,162, 10,124,164, 9,123,173, 1,122,178, 0,118,188, 0, + 115,195, 0,112,200, 0,110,202, 0,110,202, 0,110,202, 0, + 112,200, 0,113,198, 0,115,194, 0,117,190, 0,120,183, 0, + 122,177, 0,123,174, 1,123,172, 2,123,171, 3,123,170, 3, + 124,167, 6,124,162, 10,124,155, 16,124,155, 16,124,158, 13, + 124,160, 12,124,160, 12,124,158, 13,124,154, 18,124,145, 29, + 121,127, 58,118,114, 96,113,100,242,107, 89,252,118,114, 96, + 123,139, 37,124,154, 18,124,165, 8,123,170, 3,123,174, 1, + 122,177, 0,121,180, 0,121,181, 0,122,178, 0,120,184, 0, + 118,188, 0,118,189, 0,119,186, 0,122,178, 0,123,172, 2, + 123,168, 5,124,157, 15,124,149, 24,123,141, 34,122,132, 48, + 121,127, 58,122,132, 48,124,154, 18,123,171, 3,121,182, 0, + 119,186, 0,118,188, 0,117,190, 0,117,191, 0,117,190, 0, + 118,189, 0,119,187, 0,121,179, 0,123,173, 1,123,170, 3, + 124,160, 12,123,139, 37,122,135, 44,121,125, 63,118,114, 96, + 124,149, 24,123,170, 3,121,182, 0,119,186, 0,119,187, 0, + 119,186, 0,120,182, 0,121,180, 0,122,178, 0,122,175, 0, + 123,169, 4,124,158, 13,123,139, 37,124,147, 26,124,154, 18, + 124,157, 15,124,157, 15,124,154, 18,124,147, 26,122,132, 48, + 122,135, 44,124,145, 29,124,149, 24,124,161, 11,123,169, 4, + 123,174, 1,122,176, 0,120,183, 0,117,190, 0,115,195, 0, + 113,198, 0,112,200, 0,111,201, 0,110,202, 0,110,202, 0, + 111,201, 0,112,199, 0,112,200, 0,112,199, 0,113,198, 0, + 115,195, 0,117,192, 0,118,188, 0,119,185, 0,121,182, 0, + 122,178, 0,121,180, 0,120,182, 0,120,183, 0,120,182, 0, + 121,181, 0,122,178, 0,120,184, 0,118,188, 0,118,189, 0, + 118,188, 0,119,186, 0,121,181, 0,123,173, 1,124,166, 7, + 123,168, 5,123,170, 3,123,171, 3,123,171, 3,123,171, 3, + 123,170, 3,123,168, 5,124,166, 7,124,164, 9,124,162, 10, + 124,161, 11,124,164, 9,124,166, 7,123,168, 5,122,176, 0, + 120,182, 0,119,186, 0,118,189, 0,118,189, 0,119,187, 0, + 120,184, 0,121,181, 0,122,178, 0,122,175, 0,123,174, 1, + 122,175, 0,122,178, 0,121,181, 0,120,183, 0,120,184, 0, + 120,183, 0,121,182, 0,121,180, 0,121,179, 0,122,177, 0, + 123,171, 3,122,178, 0,118,188, 0,114,196, 0,112,200, 0, + 111,202, 0,111,201, 0,112,200, 0,109,203, 0,108,206, 0, + 107,206, 0,108,205, 0,111,202, 0,114,196, 0,115,195, 0, + 116,193, 0,118,189, 0,120,184, 0,122,178, 0,124,167, 6, + 124,150, 22,120,122, 70,122,135, 44,124,160, 12,123,172, 2, + 121,179, 0,120,182, 0,120,184, 0,120,184, 0,120,183, 0, + 121,181, 0,122,177, 0,123,173, 1,124,167, 6,124,158, 13, + 124,149, 24,123,137, 41,122,135, 44,124,143, 31,124,143, 31, + 124,149, 24,124,145, 29,122,132, 48,117,110,109,115,107,129, + 120,122, 70,122,130, 53,122,132, 48,124,145, 29,124,145, 29, + 123,137, 41,119,119, 77,122,132, 48,124,152, 20,124,161, 11, + 124,160, 12,124,150, 22,123,141, 34,122,130, 53,122,130, 53, + 124,143, 31,124,152, 20,124,158, 13,124,160, 12,124,154, 18, + 122,135, 44,124,154, 18,123,173, 1,120,184, 0,118,189, 0, + 117,191, 0,118,189, 0,118,188, 0,118,188, 0,117,191, 0, + 116,193, 0,114,196, 0,112,200, 0,111,202, 0,112,200, 0, + 114,196, 0,119,187, 0,121,182, 0,123,173, 1,124,161, 11, + 124,154, 18,124,149, 24,124,143, 31,124,157, 15,123,170, 3, + 121,181, 0,118,188, 0,117,192, 0,115,194, 0,114,196, 0, + 114,196, 0,114,196, 0,115,194, 0,117,192, 0,119,187, 0, + 121,179, 0,124,166, 7,124,161, 11,124,161, 11,124,162, 10, + 124,162, 10,124,165, 8,124,164, 9,124,160, 12,124,167, 6, + 123,169, 4,123,169, 4,123,169, 4,124,167, 6,124,161, 11, + 124,149, 24,121,127, 58,113,100,242, 99, 75,247,107, 89,252, + 121,127, 58,124,154, 18,124,166, 7,123,171, 3,123,170, 3, + 123,169, 4,123,171, 3,123,173, 1,123,173, 1,123,174, 1, + 120,183, 0,118,188, 0,118,188, 0,119,185, 0,122,177, 0, + 123,173, 1,123,170, 3,124,158, 13,122,132, 48,107, 89,252, + 94, 70,242,107, 89,252,121,125, 63,124,152, 20,123,170, 3, + 121,182, 0,119,186, 0,118,188, 0,119,185, 0,121,182, 0, + 121,181, 0,121,180, 0,122,176, 0,124,166, 7,124,167, 6, + 124,164, 9,124,152, 20,120,122, 70,102, 80,250, 99, 75,247, + 119,119, 77,124,155, 16,123,172, 2,121,182, 0,119,186, 0, + 118,188, 0,119,187, 0,119,185, 0,121,182, 0,122,177, 0, + 123,173, 1,123,168, 5,124,158, 13,124,158, 13,124,162, 10, + 124,166, 7,124,167, 6,124,166, 7,124,161, 11,124,152, 20, + 123,137, 41,118,117, 85,122,132, 48,122,132, 48,124,152, 20, + 124,164, 9,123,170, 3,123,173, 1,120,183, 0,117,190, 0, + 115,195, 0,114,197, 0,113,198, 0,112,199, 0,112,200, 0, + 112,199, 0,113,198, 0,115,194, 0,115,194, 0,115,194, 0, + 116,193, 0,118,189, 0,119,185, 0,121,181, 0,122,177, 0, + 123,174, 1,123,170, 3,124,166, 7,123,170, 3,123,170, 3, + 123,169, 4,124,165, 8,124,165, 8,123,173, 1,122,178, 0, + 122,178, 0,123,173, 1,124,165, 8,124,152, 20,124,154, 18, + 124,155, 16,124,157, 15,124,162, 10,124,164, 9,124,160, 12, + 124,154, 18,124,149, 24,124,149, 24,124,149, 24,124,152, 20, + 124,155, 16,124,158, 13,124,161, 11,124,164, 9,124,166, 7, + 124,167, 6,124,167, 6,123,171, 3,123,173, 1,123,173, 1, + 123,171, 3,123,169, 4,124,167, 6,124,165, 8,124,164, 9, + 124,162, 10,124,162, 10,124,165, 8,124,166, 7,123,168, 5, + 122,175, 0,121,179, 0,121,181, 0,121,181, 0,122,178, 0, + 122,175, 0,123,168, 5,123,172, 2,120,184, 0,117,192, 0, + 114,196, 0,114,197, 0,114,196, 0,115,194, 0,113,198, 0, + 112,200, 0,112,200, 0,113,198, 0,115,195, 0,116,193, 0, + 115,194, 0,116,192, 0,119,187, 0,121,180, 0,123,171, 3, + 124,160, 12,123,141, 34,118,117, 85,115,107,129,124,147, 26, + 124,166, 7,123,174, 1,122,178, 0,122,178, 0,122,178, 0, + 122,176, 0,123,173, 1,123,171, 3,123,170, 3,124,166, 7, + 124,166, 7,124,164, 9,124,154, 18,123,137, 41,124,147, 26, + 124,147, 26,124,145, 29,123,141, 34,122,130, 53,117,110,109, + 114,104,197,118,117, 85,121,125, 63,122,132, 48,124,145, 29, + 124,149, 24,123,141, 34,120,122, 70,118,117, 85,124,143, 31, + 124,155, 16,124,155, 16,124,147, 26,123,137, 41,121,125, 63, + 123,137, 41,124,149, 24,124,157, 15,124,164, 9,123,168, 5, + 124,167, 6,124,158, 13,124,149, 24,123,168, 5,121,180, 0, + 119,186, 0,118,189, 0,118,189, 0,119,187, 0,118,189, 0, + 116,193, 0,115,194, 0,115,195, 0,112,199, 0,111,202, 0, + 111,202, 0,113,198, 0,117,191, 0,121,179, 0,124,166, 7, + 124,152, 20,122,135, 44,121,127, 58,118,114, 96,124,143, 31, + 124,161, 11,123,172, 2,122,178, 0,120,183, 0,119,185, 0, + 119,187, 0,118,188, 0,118,189, 0,118,189, 0,118,188, 0, + 120,184, 0,122,175, 0,124,158, 13,122,132, 48,123,137, 41, + 124,145, 29,124,157, 15,124,161, 11,124,160, 12,124,167, 6, + 123,172, 2,123,174, 1,123,174, 1,123,173, 1,123,170, 3, + 124,164, 9,124,150, 22,121,125, 63,102, 80,250, 87, 65,237, + 105, 84,252,123,137, 41,124,161, 11,123,173, 1,122,178, 0, + 122,178, 0,123,174, 1,124,166, 7,124,161, 11,124,160, 12, + 123,173, 1,120,182, 0,119,187, 0,119,187, 0,120,183, 0, + 123,174, 1,123,172, 2,123,168, 5,124,155, 16,121,127, 58, + 94, 70,242, 94, 70,242,105, 84,252,119,119, 77,124,149, 24, + 123,169, 4,121,180, 0,119,186, 0,119,186, 0,120,183, 0, + 123,173, 1,124,165, 8,124,162, 10,124,157, 15,124,157, 15, + 124,161, 11,124,157, 15,123,141, 34,114,104,197, 99, 75,247, + 102, 80,250,122,135, 44,124,160, 12,123,173, 1,121,181, 0, + 119,185, 0,119,187, 0,119,187, 0,119,187, 0,120,184, 0, + 121,180, 0,123,172, 2,123,168, 5,123,173, 1,122,175, 0, + 123,173, 1,123,173, 1,123,174, 1,123,170, 3,124,164, 9, + 124,152, 20,122,135, 44,117,110,109,115,107,129,114,104,197, + 123,137, 41,124,155, 16,124,164, 9,123,168, 5,121,179, 0, + 118,188, 0,116,192, 0,115,194, 0,115,194, 0,115,194, 0, + 115,194, 0,115,194, 0,116,192, 0,118,189, 0,119,186, 0, + 119,186, 0,120,184, 0,121,179, 0,122,178, 0,122,177, 0, + 123,171, 3,124,160, 12,124,157, 15,124,155, 16,124,147, 26, + 124,149, 24,124,145, 29,123,137, 41,123,141, 34,124,152, 20, + 124,158, 13,124,154, 18,123,141, 34,121,127, 58,122,135, 44, + 124,149, 24,124,162, 10,124,167, 6,123,168, 5,124,167, 6, + 124,164, 9,124,157, 15,124,145, 29,122,130, 53,118,117, 85, + 122,130, 53,123,141, 34,124,150, 22,124,155, 16,124,158, 13, + 124,158, 13,124,157, 15,124,154, 18,124,145, 29,123,137, 41, + 122,135, 44,122,135, 44,123,137, 41,123,139, 37,123,139, 37, + 123,139, 37,123,139, 37,123,139, 37,123,139, 37,123,139, 37, + 124,160, 12,123,171, 3,122,178, 0,121,181, 0,121,180, 0, + 122,177, 0,123,172, 2,124,167, 6,123,173, 1,121,180, 0, + 118,188, 0,117,192, 0,116,192, 0,118,189, 0,118,188, 0, + 117,191, 0,116,193, 0,116,193, 0,117,192, 0,118,189, 0, + 117,192, 0,116,192, 0,117,190, 0,120,184, 0,122,176, 0, + 123,170, 3,124,157, 15,121,127, 58,113,100,242, 87, 65,237, + 120,122, 70,124,152, 20,124,164, 9,124,167, 6,123,168, 5, + 124,167, 6,124,165, 8,124,162, 10,124,162, 10,124,164, 9, + 123,168, 5,123,172, 2,123,172, 2,124,165, 8,124,149, 24, + 123,141, 34,123,141, 34,122,135, 44,122,135, 44,121,127, 58, + 117,110,109,109, 92,251,119,119, 77,121,125, 63,122,132, 48, + 124,145, 29,124,150, 22,124,147, 26,122,132, 48,118,117, 85, + 118,117, 85,123,137, 41,123,141, 34,122,132, 48,119,119, 77, + 120,122, 70,123,137, 41,124,147, 26,124,158, 13,124,166, 7, + 123,172, 2,122,175, 0,123,171, 3,124,165, 8,123,170, 3, + 122,177, 0,120,184, 0,119,186, 0,119,186, 0,120,184, 0, + 116,192, 0,114,197, 0,113,199, 0,113,198, 0,114,196, 0, + 112,200, 0,111,201, 0,113,198, 0,116,192, 0,120,183, 0, + 124,167, 6,123,137, 41,118,117, 85,113,100,242,111, 96,248, + 121,127, 58,124,150, 22,124,161, 11,124,167, 6,122,175, 0, + 121,179, 0,121,179, 0,122,178, 0,121,181, 0,120,184, 0, + 120,183, 0,122,178, 0,123,168, 5,124,147, 26,115,107,129, + 117,110,109,122,135, 44,124,147, 26,124,152, 20,124,162, 10, + 123,171, 3,122,175, 0,122,175, 0,122,175, 0,123,174, 1, + 123,170, 3,124,164, 9,124,150, 22,121,127, 58,102, 80,250, + 69, 60,230,105, 84,252,123,137, 41,124,164, 9,122,176, 0, + 121,182, 0,120,182, 0,122,178, 0,123,171, 3,124,161, 11, + 124,157, 15,123,172, 2,121,182, 0,119,186, 0,119,186, 0, + 121,181, 0,123,171, 3,124,167, 6,124,162, 10,124,147, 26, + 121,125, 63,121,125, 63,120,122, 70,122,132, 48,122,130, 53, + 124,145, 29,124,166, 7,122,178, 0,120,184, 0,120,184, 0, + 121,179, 0,124,166, 7,123,139, 37,122,130, 53,121,127, 58, + 124,147, 26,124,154, 18,124,149, 24,124,143, 31,123,137, 41, + 119,119, 77,118,117, 85,124,145, 29,124,164, 9,123,174, 1, + 121,180, 0,120,183, 0,119,185, 0,119,186, 0,119,187, 0, + 119,186, 0,121,182, 0,121,179, 0,121,180, 0,120,184, 0, + 119,185, 0,120,184, 0,121,179, 0,122,178, 0,123,173, 1, + 124,165, 8,124,149, 24,122,130, 53,115,107,129, 94, 70,242, + 30, 55,222,118,114, 96,123,139, 37,124,155, 16,124,162, 10, + 123,171, 3,121,182, 0,119,187, 0,118,189, 0,118,188, 0, + 118,188, 0,118,188, 0,118,188, 0,119,186, 0,120,182, 0, + 122,175, 0,123,173, 1,123,169, 4,122,175, 0,121,179, 0, + 121,179, 0,122,175, 0,124,165, 8,124,143, 31,122,135, 44, + 121,127, 58,115,107,129,113,100,242,105, 84,252,111, 96,248, + 117,110,109,118,117, 85,113,100,242,102, 80,250,117,110,109, + 124,145, 29,124,162, 10,123,169, 4,123,171, 3,123,170, 3, + 124,167, 6,124,162, 10,124,157, 15,124,155, 16,124,149, 24, + 123,137, 41,118,114, 96,118,117, 85,122,132, 48,123,141, 34, + 124,143, 31,124,143, 31,123,139, 37,122,130, 53,118,114, 96, + 111, 96,248, 94, 70,242, 99, 75,247,109, 92,251,118,114, 96, + 120,122, 70,120,122, 70,118,114, 96,109, 92,251,107, 89,252, + 117,110,109,124,147, 26,124,166, 7,123,174, 1,122,177, 0, + 122,176, 0,123,172, 2,124,166, 7,124,167, 6,122,176, 0, + 121,182, 0,120,184, 0,119,187, 0,119,187, 0,120,183, 0, + 121,179, 0,120,184, 0,119,186, 0,119,186, 0,119,185, 0, + 119,186, 0,118,189, 0,118,189, 0,119,186, 0,120,182, 0, + 120,183, 0,121,181, 0,123,174, 1,124,160, 12,120,122, 70, + 30, 49,213, 94, 70,242,121,125, 63,124,143, 31,124,150, 22, + 124,152, 20,124,152, 20,124,154, 18,124,149, 24,124,150, 22, + 124,157, 15,123,168, 5,122,175, 0,122,176, 0,123,171, 3, + 124,158, 13,122,132, 48,121,125, 63,121,125, 63,121,127, 58, + 120,122, 70,117,110,109,118,117, 85,120,122, 70,121,127, 58, + 122,130, 53,124,145, 29,124,152, 20,124,152, 20,123,141, 34, + 119,119, 77,111, 96,248,107, 89,252,113,100,242,107, 89,252, + 109, 92,251,118,114, 96,121,127, 58,123,141, 34,124,154, 18, + 124,165, 8,123,174, 1,122,178, 0,121,179, 0,122,176, 0, + 121,180, 0,120,182, 0,120,182, 0,120,183, 0,120,182, 0, + 119,187, 0,115,195, 0,111,201, 0,110,203, 0,110,203, 0, + 112,200, 0,114,196, 0,113,198, 0,114,196, 0,117,192, 0, + 120,184, 0,123,170, 3,124,147, 26,114,104,197, 87, 65,237, + 69, 60,230,115,107,129,122,135, 44,124,145, 29,124,160, 12, + 123,169, 4,123,173, 1,123,172, 2,124,166, 7,123,171, 3, + 122,175, 0,122,176, 0,123,171, 3,124,160, 12,124,143, 31, + 118,114, 96,107, 89,252,119,119, 77,122,135, 44,124,157, 15, + 123,169, 4,122,175, 0,122,176, 0,122,175, 0,123,174, 1, + 123,173, 1,123,170, 3,124,165, 8,124,154, 18,122,135, 44, + 113,100,242, 30, 49,213, 69, 60,230,121,127, 58,124,160, 12, + 123,174, 1,121,181, 0,120,183, 0,121,180, 0,123,174, 1, + 124,164, 9,123,171, 3,122,177, 0,121,179, 0,120,184, 0, + 120,184, 0,122,178, 0,124,167, 6,124,157, 15,124,152, 20, + 124,147, 26,124,150, 22,124,150, 22,124,158, 13,124,165, 8, + 124,164, 9,124,158, 13,124,167, 6,122,175, 0,121,181, 0, + 121,181, 0,123,174, 1,124,157, 15,118,117, 85, 87, 65,237, + 115,107,129,122,135, 44,124,150, 22,124,161, 11,124,164, 9, + 124,158, 13,124,149, 24,124,147, 26,124,157, 15,124,166, 7, + 123,174, 1,122,178, 0,121,182, 0,119,186, 0,119,186, 0, + 119,186, 0,119,186, 0,118,188, 0,118,189, 0,118,188, 0, + 117,191, 0,116,192, 0,117,191, 0,119,186, 0,121,182, 0, + 122,176, 0,124,165, 8,124,155, 16,124,143, 31,120,122, 70, + 105, 84,252, 30, 2,128, 99, 75,247,119,119, 77,124,143, 31, + 124,155, 16,124,164, 9,123,171, 3,122,178, 0,121,181, 0, + 119,185, 0,119,186, 0,119,185, 0,121,182, 0,122,178, 0, + 123,174, 1,124,166, 7,124,150, 22,124,164, 9,123,173, 1, + 122,178, 0,121,179, 0,122,175, 0,124,164, 9,124,143, 31, + 115,107,129,113,100,242,102, 80,250, 30, 37,192, 30, 10,132, + 30, 31,180, 30, 49,213, 30, 43,203, 30, 2,128, 99, 75,247, + 121,127, 58,124,152, 20,124,165, 8,123,170, 3,123,170, 3, + 124,167, 6,124,162, 10,123,168, 5,123,171, 3,123,171, 3, + 124,167, 6,124,160, 12,124,145, 29,120,122, 70,111, 96,248, + 117,110,109,118,117, 85,118,117, 85,115,107,129,109, 92,251, + 105, 84,252,105, 84,252,105, 84,252,111, 96,248,117,110,109, + 119,119, 77,121,125, 63,119,119, 77,113,100,242, 69, 60,230, + 30, 2,128, 99, 75,247,121,127, 58,124,154, 18,124,166, 7, + 123,169, 4,124,167, 6,124,162, 10,124,155, 16,123,168, 5, + 121,179, 0,119,185, 0,119,187, 0,119,186, 0,121,182, 0, + 122,176, 0,123,168, 5,122,175, 0,122,178, 0,121,180, 0, + 121,181, 0,121,181, 0,120,184, 0,119,185, 0,120,182, 0, + 119,186, 0,118,188, 0,118,188, 0,120,184, 0,123,174, 1, + 124,152, 20,113,100,242, 30, 2,128,102, 80,250,118,114, 96, + 122,130, 53,124,147, 26,124,155, 16,124,158, 13,124,154, 18, + 123,139, 37,124,149, 24,124,162, 10,123,172, 2,122,175, 0, + 123,172, 2,124,162, 10,123,141, 34,111, 96,248,119,119, 77, + 121,127, 58,121,127, 58,123,137, 41,124,143, 31,124,143, 31, + 122,135, 44,121,125, 63,124,143, 31,124,152, 20,124,155, 16, + 124,150, 22,122,135, 44,114,104,197, 30, 49,213, 30, 2,128, + 30, 31,180, 69, 60,230,114,104,197,122,132, 48,124,152, 20, + 124,165, 8,123,171, 3,123,174, 1,121,181, 0,120,183, 0, + 119,186, 0,118,189, 0,117,190, 0,118,189, 0,119,186, 0, + 121,179, 0,118,189, 0,114,197, 0,110,203, 0,107,206, 0, + 107,207, 0,108,205, 0,112,200, 0,115,195, 0,115,194, 0, + 118,189, 0,120,182, 0,123,169, 4,124,155, 16,122,130, 53, + 105, 84,252, 30, 2,128, 99, 75,247,117,110,109,122,132, 48, + 124,152, 20,124,162, 10,124,166, 7,124,162, 10,124,150, 22, + 124,160, 12,124,165, 8,123,168, 5,123,168, 5,124,161, 11, + 124,143, 31,118,114, 96, 99, 75,247,120,122, 70,124,152, 20, + 123,168, 5,122,176, 0,121,179, 0,121,179, 0,122,177, 0, + 122,175, 0,122,176, 0,123,173, 1,123,168, 5,124,162, 10, + 124,150, 22,121,127, 58,105, 84,252, 30, 2,128,109, 92,251, + 124,143, 31,124,167, 6,122,177, 0,121,180, 0,121,179, 0, + 123,174, 1,124,166, 7,123,174, 1,121,181, 0,120,184, 0, + 120,184, 0,121,180, 0,122,175, 0,124,162, 10,123,141, 34, + 124,155, 16,124,161, 11,124,164, 9,123,168, 5,122,175, 0, + 122,178, 0,122,178, 0,123,171, 3,122,178, 0,120,182, 0, + 120,183, 0,121,179, 0,123,169, 4,124,147, 26,111, 96,248, + 30, 2,128,109, 92,251,123,141, 34,124,164, 9,123,173, 1, + 122,175, 0,123,172, 2,124,166, 7,124,160, 12,124,167, 6, + 123,169, 4,123,172, 2,121,179, 0,119,185, 0,118,188, 0, + 118,188, 0,120,183, 0,117,191, 0,115,194, 0,115,195, 0, + 115,194, 0,115,195, 0,115,195, 0,116,193, 0,119,187, 0, + 119,185, 0,122,178, 0,124,166, 7,124,154, 18,123,139, 37, + 118,117, 85, 94, 70,242, 94, 70,242,109, 92,251,118,114, 96, + 119,119, 77,124,143, 31,124,157, 15,124,167, 6,123,174, 1, + 121,181, 0,119,186, 0,118,188, 0,119,186, 0,120,184, 0, + 122,178, 0,123,172, 2,124,165, 8,124,158, 13,124,160, 12, + 123,169, 4,123,174, 1,123,174, 1,123,168, 5,124,155, 16, + 122,130, 53,107, 89,252, 87, 65,237, 87, 65,237, 94, 70,242, + 87, 65,237, 69, 60,230, 69, 60,230, 94, 70,242,111, 96,248, + 121,125, 63,124,145, 29,124,155, 16,124,165, 8,123,168, 5, + 124,167, 6,124,164, 9,123,169, 4,122,175, 0,122,178, 0, + 122,178, 0,122,176, 0,123,170, 3,124,161, 11,124,147, 26, + 122,132, 48,119,119, 77,118,114, 96,117,110,109,118,114, 96, + 119,119, 77,121,127, 58,123,137, 41,124,143, 31,123,141, 34, + 122,135, 44,122,135, 44,123,139, 37,122,135, 44,120,122, 70, + 114,104,197,114,104,197,114,104,197,122,132, 48,124,145, 29, + 124,147, 26,124,150, 22,124,149, 24,123,141, 34,124,154, 18, + 123,169, 4,121,179, 0,119,185, 0,118,188, 0,119,187, 0, + 120,183, 0,122,178, 0,123,173, 1,121,180, 0,121,181, 0, + 122,178, 0,121,179, 0,121,180, 0,121,182, 0,120,184, 0, + 119,186, 0,117,191, 0,116,193, 0,116,192, 0,118,189, 0, + 121,181, 0,124,165, 8,122,130, 53, 30, 55,222, 30, 37,192, + 109, 92,251,121,125, 63,124,143, 31,124,152, 20,124,154, 18, + 124,150, 22,123,137, 41,124,147, 26,124,157, 15,124,167, 6, + 123,171, 3,123,169, 4,124,158, 13,123,137, 41,121,127, 58, + 122,130, 53,123,141, 34,124,150, 22,124,160, 12,124,164, 9, + 124,164, 9,124,160, 12,124,145, 29,124,143, 31,124,150, 22, + 124,155, 16,124,152, 20,123,141, 34,121,125, 63,115,107,129, + 113,100,242,117,110,109,120,122, 70,122,132, 48,124,145, 29, + 124,162, 10,123,172, 2,121,179, 0,120,182, 0,119,186, 0, + 117,190, 0,116,193, 0,114,196, 0,114,197, 0,114,196, 0, + 116,193, 0,117,192, 0,116,193, 0,113,198, 0,109,204, 0, + 107,207, 0,106,207, 0,108,206, 0,110,202, 0,113,198, 0, + 116,193, 0,118,189, 0,120,184, 0,122,178, 0,124,167, 6, + 124,150, 22,119,119, 77,107, 89,252,109, 92,251,115,107,129, + 122,135, 44,124,150, 22,124,158, 13,124,158, 13,124,152, 20, + 122,135, 44,124,149, 24,124,160, 12,124,165, 8,124,162, 10, + 124,152, 20,122,135, 44,121,127, 58,122,132, 48,124,157, 15, + 123,171, 3,121,180, 0,120,184, 0,119,185, 0,120,184, 0, + 121,182, 0,119,186, 0,119,187, 0,120,184, 0,122,178, 0, + 123,169, 4,124,162, 10,124,149, 24,121,125, 63, 94, 70,242, + 30, 26,168,117,110,109,124,150, 22,124,167, 6,123,174, 1, + 122,176, 0,123,173, 1,124,167, 6,123,171, 3,121,180, 0, + 119,185, 0,119,186, 0,120,184, 0,121,179, 0,123,170, 3, + 124,162, 10,124,160, 12,124,167, 6,123,171, 3,122,178, 0, + 120,184, 0,119,186, 0,119,186, 0,121,182, 0,120,184, 0, + 118,188, 0,118,188, 0,119,185, 0,122,177, 0,124,160, 12, + 120,122, 70, 69, 60,230,118,114, 96,124,154, 18,123,172, 2, + 121,181, 0,120,183, 0,121,182, 0,122,178, 0,123,174, 1, + 123,174, 1,122,177, 0,121,179, 0,120,184, 0,118,188, 0, + 117,190, 0,117,192, 0,116,192, 0,115,195, 0,113,198, 0, + 112,199, 0,113,199, 0,113,198, 0,114,197, 0,116,193, 0, + 118,189, 0,119,186, 0,122,178, 0,124,165, 8,124,143, 31, + 122,132, 48,121,127, 58,117,110,109,120,122, 70,118,114, 96, + 122,130, 53,123,137, 41,123,139, 37,124,143, 31,124,161, 11, + 123,171, 3,121,179, 0,120,184, 0,119,186, 0,119,185, 0, + 120,182, 0,122,178, 0,123,172, 2,124,166, 7,124,160, 12, + 124,157, 15,124,164, 9,124,167, 6,124,165, 8,124,155, 16, + 122,135, 44,113,100,242, 87, 65,237,105, 84,252,111, 96,248, + 114,104,197,115,107,129,117,110,109,118,117, 85,121,127, 58, + 124,143, 31,124,158, 13,123,168, 5,123,173, 1,123,173, 1, + 123,170, 3,124,167, 6,124,164, 9,123,171, 3,122,176, 0, + 121,179, 0,121,180, 0,122,178, 0,123,174, 1,124,167, 6, + 124,158, 13,124,149, 24,123,141, 34,123,137, 41,123,137, 41, + 123,141, 34,124,149, 24,124,157, 15,124,164, 9,123,168, 5, + 123,170, 3,123,169, 4,124,166, 7,124,164, 9,124,161, 11, + 124,160, 12,124,160, 12,124,160, 12,124,158, 13,124,152, 20, + 124,154, 18,124,149, 24,122,135, 44,114,104,197,120,122, 70, + 124,150, 22,124,166, 7,122,175, 0,121,182, 0,120,184, 0, + 120,182, 0,121,179, 0,123,174, 1,122,178, 0,120,184, 0, + 120,184, 0,120,182, 0,122,178, 0,121,182, 0,120,184, 0, + 118,188, 0,117,191, 0,115,195, 0,114,197, 0,114,197, 0, + 116,193, 0,119,186, 0,123,172, 2,124,145, 29,109, 92,251, + 30, 55,222, 30, 55,222,111, 96,248,120,122, 70,122,135, 44, + 123,139, 37,122,135, 44,121,127, 58,124,143, 31,124,157, 15, + 124,165, 8,124,167, 6,124,165, 8,124,158, 13,124,150, 22, + 124,143, 31,124,147, 26,124,157, 15,124,165, 8,123,172, 2, + 122,176, 0,122,177, 0,122,175, 0,124,167, 6,124,160, 12, + 124,165, 8,124,167, 6,124,166, 7,124,162, 10,124,155, 16, + 124,149, 24,124,147, 26,124,152, 20,124,158, 13,124,161, 11, + 124,165, 8,124,166, 7,122,175, 0,120,182, 0,119,187, 0, + 117,191, 0,114,196, 0,112,200, 0,110,202, 0,110,202, 0, + 111,202, 0,112,200, 0,110,202, 0,110,203, 0,110,202, 0, + 110,202, 0,108,205, 0,108,206, 0,109,204, 0,112,200, 0, + 114,196, 0,116,193, 0,117,190, 0,119,186, 0,121,182, 0, + 123,174, 1,124,162, 10,123,141, 34,124,143, 31,124,143, 31, + 124,147, 26,124,154, 18,124,160, 12,124,162, 10,124,162, 10, + 124,158, 13,124,147, 26,123,139, 37,124,149, 24,124,150, 22, + 124,145, 29,124,143, 31,124,147, 26,124,145, 29,124,165, 8, + 122,176, 0,120,184, 0,118,189, 0,117,191, 0,117,191, 0, + 118,189, 0,118,189, 0,116,192, 0,116,193, 0,117,191, 0, + 119,186, 0,122,178, 0,123,168, 5,124,160, 12,124,143, 31, + 117,110,109, 30, 31,180, 30, 55,222,120,122, 70,124,150, 22, + 124,164, 9,123,169, 4,123,169, 4,124,167, 6,124,166, 7, + 122,177, 0,120,184, 0,119,187, 0,119,187, 0,120,184, 0, + 121,180, 0,122,175, 0,123,173, 1,122,176, 0,121,181, 0, + 119,186, 0,118,189, 0,116,192, 0,116,192, 0,117,190, 0, + 119,186, 0,118,189, 0,117,191, 0,118,188, 0,121,182, 0, + 123,169, 4,124,143, 31,118,114, 96,122,135, 44,124,165, 8, + 121,179, 0,119,186, 0,118,189, 0,118,188, 0,119,186, 0, + 120,183, 0,120,183, 0,119,185, 0,118,188, 0,117,192, 0, + 115,195, 0,114,197, 0,113,199, 0,113,199, 0,112,200, 0, + 110,202, 0,110,203, 0,110,202, 0,112,200, 0,113,198, 0, + 115,194, 0,118,188, 0,120,184, 0,122,175, 0,124,161, 11, + 124,155, 16,124,155, 16,124,152, 20,124,143, 31,124,154, 18, + 124,145, 29,123,139, 37,124,147, 26,124,150, 22,124,152, 20, + 124,152, 20,124,164, 9,123,174, 1,121,179, 0,121,180, 0, + 122,178, 0,122,175, 0,123,171, 3,124,166, 7,124,161, 11, + 124,157, 15,124,154, 18,124,154, 18,124,154, 18,124,147, 26, + 121,127, 58,113,100,242,105, 84,252,107, 89,252,115,107,129, + 118,114, 96,119,119, 77,121,125, 63,122,132, 48,123,141, 34, + 124,154, 18,124,164, 9,123,173, 1,121,179, 0,120,182, 0, + 120,182, 0,121,179, 0,123,173, 1,124,167, 6,123,170, 3, + 122,175, 0,122,178, 0,122,178, 0,122,178, 0,123,174, 1, + 123,169, 4,124,164, 9,124,157, 15,124,152, 20,124,150, 22, + 124,152, 20,124,155, 16,124,162, 10,123,170, 3,122,176, 0, + 121,182, 0,120,184, 0,119,185, 0,119,185, 0,120,184, 0, + 120,184, 0,120,184, 0,120,183, 0,120,183, 0,121,181, 0, + 122,175, 0,124,162, 10,124,150, 22,122,135, 44,114,104,197, + 120,122, 70,123,139, 37,124,155, 16,124,166, 7,123,171, 3, + 123,174, 1,123,173, 1,123,171, 3,123,174, 1,120,182, 0, + 119,186, 0,119,186, 0,120,184, 0,121,181, 0,120,182, 0, + 119,186, 0,117,191, 0,115,195, 0,113,199, 0,112,200, 0, + 112,199, 0,114,196, 0,118,188, 0,122,176, 0,124,155, 16, + 119,119, 77, 99, 75,247, 94, 70,242, 94, 70,242,102, 80,250, + 113,100,242,115,107,129,114,104,197,119,119, 77,123,139, 37, + 124,155, 16,124,164, 9,124,167, 6,124,167, 6,124,162, 10, + 124,155, 16,124,152, 20,124,158, 13,124,165, 8,123,173, 1, + 121,180, 0,120,184, 0,119,186, 0,120,184, 0,121,179, 0, + 123,170, 3,122,175, 0,122,177, 0,122,176, 0,123,173, 1, + 123,170, 3,124,167, 6,123,168, 5,123,172, 2,122,175, 0, + 122,177, 0,122,178, 0,122,177, 0,122,175, 0,120,183, 0, + 118,189, 0,115,195, 0,112,200, 0,109,204, 0,106,207, 0, + 106,208, 0,106,207, 0,106,208, 0,104,210, 0,103,211, 0, + 105,209, 0,107,206, 0,111,201, 0,111,201, 0,112,199, 0, + 114,196, 0,116,192, 0,117,191, 0,118,189, 0,119,187, 0, + 120,183, 0,122,178, 0,124,167, 6,124,167, 6,124,167, 6, + 124,166, 7,124,167, 6,123,169, 4,123,170, 3,123,170, 3, + 123,169, 4,124,165, 8,124,155, 16,123,137, 41,121,127, 58, + 120,122, 70,122,130, 53,124,147, 26,124,154, 18,123,171, 3, + 121,182, 0,119,187, 0,116,192, 0,115,195, 0,114,197, 0, + 114,196, 0,116,193, 0,117,192, 0,115,195, 0,114,196, 0, + 115,194, 0,117,191, 0,119,185, 0,122,175, 0,124,164, 9, + 124,152, 20,122,130, 53,105, 84,252, 30, 20,155, 87, 65,237, + 118,117, 85,124,143, 31,124,157, 15,124,164, 9,124,166, 7, + 124,162, 10,123,171, 3,121,180, 0,119,186, 0,118,188, 0, + 118,188, 0,119,186, 0,120,182, 0,121,181, 0,120,182, 0, + 119,186, 0,118,189, 0,116,193, 0,114,196, 0,113,198, 0, + 114,197, 0,116,192, 0,117,191, 0,117,192, 0,117,190, 0, + 119,185, 0,122,176, 0,124,158, 13,124,147, 26,124,154, 18, + 123,174, 1,119,186, 0,117,192, 0,115,194, 0,116,193, 0, + 117,192, 0,118,189, 0,116,192, 0,115,194, 0,114,196, 0, + 113,199, 0,111,201, 0,109,203, 0,109,204, 0,109,204, 0, + 108,205, 0,107,207, 0,107,207, 0,108,205, 0,111,202, 0, + 113,199, 0,115,195, 0,118,188, 0,122,178, 0,123,173, 1, + 123,173, 1,123,171, 3,123,171, 3,123,169, 4,124,165, 8, + 123,173, 1,124,164, 9,124,154, 18,124,150, 22,124,155, 16, + 124,160, 12,124,161, 11,124,161, 11,124,160, 12,124,166, 7, + 124,167, 6,124,164, 9,124,160, 12,124,155, 16,124,150, 22, + 124,147, 26,124,145, 29,123,141, 34,122,135, 44,122,130, 53, + 118,114, 96,115,107,129,111, 96,248,105, 84,252,117,110,109, + 119,119, 77,120,122, 70,121,125, 63,122,132, 48,123,139, 37, + 124,152, 20,124,164, 9,123,172, 2,121,180, 0,120,184, 0, + 119,187, 0,119,187, 0,119,185, 0,121,180, 0,123,174, 1, + 123,172, 2,123,174, 1,122,176, 0,122,176, 0,122,175, 0, + 123,173, 1,123,169, 4,124,165, 8,124,161, 11,124,161, 11, + 124,164, 9,124,166, 7,123,169, 4,123,171, 3,122,177, 0, + 120,183, 0,118,189, 0,116,192, 0,115,194, 0,114,196, 0, + 114,197, 0,114,197, 0,114,196, 0,114,196, 0,115,195, 0, + 116,193, 0,119,187, 0,122,176, 0,124,155, 16,122,135, 44, + 123,137, 41,124,145, 29,124,143, 31,122,135, 44,124,147, 26, + 124,154, 18,124,157, 15,124,157, 15,123,168, 5,122,177, 0, + 120,183, 0,119,186, 0,119,186, 0,120,183, 0,121,180, 0, + 121,182, 0,119,187, 0,116,192, 0,114,197, 0,111,201, 0, + 110,202, 0,111,201, 0,114,197, 0,117,190, 0,121,179, 0, + 124,162, 10,124,145, 29,119,119, 77,105, 84,252,102, 80,250, + 99, 75,247, 30, 55,222, 30, 43,203, 87, 65,237,114,104,197, + 122,130, 53,124,150, 22,124,161, 11,124,166, 7,124,166, 7, + 124,164, 9,124,158, 13,124,158, 13,123,169, 4,123,172, 2, + 122,178, 0,119,185, 0,118,189, 0,117,191, 0,117,191, 0, + 119,187, 0,121,181, 0,120,182, 0,120,183, 0,120,182, 0, + 121,181, 0,122,178, 0,122,177, 0,121,180, 0,120,184, 0, + 119,186, 0,119,186, 0,119,186, 0,120,184, 0,121,182, 0, + 120,182, 0,117,191, 0,114,197, 0,109,204, 0,105,209, 0, + 102,212, 0,101,213, 0,102,212, 0,100,214, 0, 98,216, 0, + 98,217, 0,100,215, 0,103,211, 0,108,205, 0,114,197, 0, + 116,192, 0,118,189, 0,119,187, 0,119,186, 0,119,186, 0, + 119,185, 0,120,182, 0,122,177, 0,122,177, 0,122,178, 0, + 122,178, 0,122,177, 0,122,176, 0,122,176, 0,122,176, 0, + 123,174, 1,123,172, 2,123,168, 5,124,160, 12,124,145, 29, + 120,122, 70,117,110,109,123,139, 37,124,160, 12,122,175, 0, + 120,184, 0,117,190, 0,116,193, 0,114,197, 0,112,199, 0, + 112,200, 0,112,199, 0,114,196, 0,116,193, 0,114,196, 0, + 114,197, 0,114,197, 0,115,194, 0,117,190, 0,120,183, 0, + 123,170, 3,124,155, 16,123,141, 34,118,114, 96, 94, 70,242, + 87, 65,237, 94, 70,242,115,107,129,122,135, 44,124,152, 20, + 124,161, 11,124,164, 9,124,165, 8,122,176, 0,120,183, 0, + 119,187, 0,118,189, 0,118,188, 0,119,186, 0,119,185, 0, + 119,185, 0,119,187, 0,117,191, 0,115,194, 0,113,198, 0, + 111,201, 0,111,201, 0,113,199, 0,116,193, 0,116,193, 0, + 117,192, 0,118,188, 0,121,182, 0,123,170, 3,124,167, 6, + 123,170, 3,121,181, 0,117,191, 0,114,196, 0,113,199, 0, + 113,198, 0,114,197, 0,114,196, 0,112,200, 0,111,202, 0, + 111,202, 0,109,204, 0,107,206, 0,106,208, 0,106,208, 0, + 106,207, 0,105,209, 0,103,211, 0,104,210, 0,106,207, 0, + 110,203, 0,113,198, 0,115,194, 0,118,188, 0,120,184, 0, + 120,184, 0,120,183, 0,120,182, 0,121,182, 0,121,180, 0, + 122,178, 0,120,184, 0,121,179, 0,123,170, 3,124,160, 12, + 124,155, 16,124,160, 12,124,162, 10,124,162, 10,124,157, 15, + 124,143, 31,122,132, 48,121,127, 58,119,119, 77,118,114, 96, + 118,114, 96,118,114, 96,118,117, 85,118,114, 96,115,107,129, + 118,114, 96,117,110,109,113,100,242,107, 89,252,117,110,109, + 121,125, 63,121,125, 63,121,127, 58,123,141, 34,124,149, 24, + 124,149, 24,124,152, 20,124,166, 7,122,175, 0,121,182, 0, + 119,186, 0,118,189, 0,118,189, 0,118,188, 0,120,184, 0, + 121,180, 0,122,176, 0,121,180, 0,121,182, 0,120,182, 0, + 120,182, 0,121,180, 0,122,178, 0,122,175, 0,123,172, 2, + 123,172, 2,123,174, 1,122,178, 0,121,181, 0,120,183, 0, + 120,184, 0,118,188, 0,116,193, 0,113,198, 0,111,202, 0, + 109,203, 0,109,204, 0,108,205, 0,109,204, 0,109,203, 0, + 110,202, 0,112,200, 0,115,194, 0,120,184, 0,124,166, 7, + 124,145, 29,124,155, 16,124,160, 12,124,154, 18,123,137, 41, + 115,107,129,120,122, 70,124,149, 24,124,162, 10,123,171, 3, + 122,177, 0,121,181, 0,120,183, 0,121,182, 0,121,179, 0, + 122,177, 0,121,179, 0,119,186, 0,116,192, 0,113,198, 0, + 111,202, 0,110,202, 0,111,201, 0,114,197, 0,117,191, 0, + 121,182, 0,123,174, 1,124,166, 7,124,149, 24,121,127, 58, + 118,114, 96,111, 96,248, 94, 70,242, 30, 31,180, 30, 37,192, + 94, 70,242,117,110,109,123,139, 37,124,154, 18,124,161, 11, + 124,164, 9,124,162, 10,124,160, 12,124,167, 6,122,176, 0, + 121,179, 0,121,182, 0,118,188, 0,116,192, 0,115,194, 0, + 115,194, 0,117,191, 0,119,186, 0,118,188, 0,118,188, 0, + 119,187, 0,119,186, 0,120,184, 0,119,186, 0,118,188, 0, + 117,191, 0,116,193, 0,116,193, 0,116,193, 0,116,192, 0, + 117,191, 0,118,189, 0,115,194, 0,112,199, 0,107,207, 0, + 102,213, 0, 98,216, 0, 97,218, 0, 97,217, 0, 96,219, 0, + 94,220, 0, 94,221, 0, 97,218, 0,101,214, 0,106,208, 0, + 112,200, 0,117,191, 0,120,183, 0,121,180, 0,121,180, 0, + 121,181, 0,121,181, 0,121,179, 0,121,182, 0,120,182, 0, + 120,182, 0,121,182, 0,121,181, 0,121,179, 0,122,178, 0, + 122,176, 0,123,174, 1,123,172, 2,123,168, 5,124,161, 11, + 124,149, 24,122,130, 53,124,147, 26,124,165, 8,122,177, 0, + 119,185, 0,117,191, 0,115,194, 0,114,197, 0,112,199, 0, + 111,201, 0,111,202, 0,111,201, 0,113,198, 0,115,194, 0, + 116,193, 0,114,196, 0,114,197, 0,114,197, 0,116,193, 0, + 118,188, 0,121,179, 0,124,164, 9,124,145, 29,122,130, 53, + 117,110,109,118,117, 85,118,117, 85,118,114, 96,118,117, 85, + 122,135, 44,124,155, 16,124,162, 10,124,162, 10,123,169, 4, + 122,178, 0,120,184, 0,118,188, 0,118,189, 0,118,188, 0, + 119,185, 0,119,185, 0,119,186, 0,117,191, 0,116,193, 0, + 113,198, 0,111,202, 0,109,203, 0,110,203, 0,112,200, 0, + 115,195, 0,115,194, 0,117,192, 0,119,187, 0,121,179, 0, + 122,178, 0,121,181, 0,119,186, 0,115,195, 0,111,201, 0, + 110,203, 0,110,203, 0,111,202, 0,109,204, 0,106,207, 0, + 106,208, 0,106,208, 0,105,209, 0,103,211, 0,103,212, 0, + 103,212, 0,104,210, 0,102,213, 0,101,214, 0,102,213, 0, + 105,209, 0,109,204, 0,114,197, 0,116,193, 0,116,192, 0, + 116,192, 0,117,192, 0,117,191, 0,117,191, 0,117,191, 0, + 117,190, 0,119,187, 0,117,191, 0,118,189, 0,120,184, 0, + 123,174, 1,124,164, 9,124,158, 13,124,158, 13,124,157, 15, + 124,149, 24,121,127, 58,107, 89,252, 30, 31,180, 87, 65,237, + 99, 75,247, 30, 55,222, 30, 43,203,105, 84,252,115,107,129, + 119,119, 77,120,122, 70,119,119, 77,118,114, 96,121,125, 63, + 124,143, 31,124,149, 24,124,143, 31,124,155, 16,124,162, 10, + 124,164, 9,124,161, 11,124,158, 13,124,162, 10,123,173, 1, + 121,181, 0,119,186, 0,118,188, 0,118,189, 0,118,188, 0, + 119,186, 0,120,182, 0,121,179, 0,120,183, 0,119,186, 0, + 118,188, 0,118,188, 0,119,186, 0,120,184, 0,121,181, 0, + 122,178, 0,122,178, 0,121,182, 0,119,185, 0,118,189, 0, + 117,191, 0,116,192, 0,116,193, 0,114,197, 0,110,202, 0, + 108,206, 0,106,208, 0,105,209, 0,105,209, 0,105,209, 0, + 106,208, 0,107,207, 0,109,204, 0,113,198, 0,118,188, 0, + 123,174, 1,124,166, 7,123,168, 5,123,168, 5,124,160, 12, + 123,141, 34,122,130, 53,122,130, 53,124,152, 20,124,164, 9, + 123,169, 4,123,173, 1,122,176, 0,122,177, 0,122,175, 0, + 122,177, 0,122,178, 0,120,182, 0,119,185, 0,117,191, 0, + 114,197, 0,111,201, 0,110,202, 0,111,201, 0,114,197, 0, + 117,192, 0,119,186, 0,120,184, 0,122,178, 0,124,167, 6, + 124,155, 16,124,149, 24,123,139, 37,121,125, 63,111, 96,248, + 105, 84,252,102, 80,250,107, 89,252,118,114, 96,123,139, 37, + 124,152, 20,124,158, 13,124,160, 12,124,160, 12,123,171, 3, + 121,180, 0,120,183, 0,120,184, 0,118,189, 0,116,193, 0, + 114,196, 0,114,196, 0,116,193, 0,117,191, 0,117,192, 0, + 117,192, 0,117,191, 0,118,189, 0,117,191, 0,115,194, 0, + 114,197, 0,113,198, 0,112,199, 0,112,200, 0,111,201, 0, + 111,201, 0,112,200, 0,114,197, 0,114,197, 0,111,201, 0, + 105,209, 0, 99,216, 0, 95,220, 0, 92,222, 0, 92,222, 0, + 94,221, 0, 92,223, 0, 92,223, 0, 94,220, 0, 99,216, 0, + 105,209, 0,110,202, 0,114,196, 0,117,192, 0,120,184, 0, + 121,179, 0,121,181, 0,120,182, 0,120,184, 0,120,184, 0, + 120,184, 0,120,182, 0,121,181, 0,121,179, 0,122,178, 0, + 122,175, 0,123,172, 2,123,170, 3,124,167, 6,124,164, 9, + 124,157, 15,124,143, 31,124,145, 29,124,164, 9,122,175, 0, + 120,184, 0,118,189, 0,116,193, 0,114,196, 0,114,197, 0, + 113,199, 0,111,201, 0,111,201, 0,111,201, 0,113,198, 0, + 115,195, 0,117,191, 0,116,193, 0,114,196, 0,114,197, 0, + 114,196, 0,117,191, 0,120,184, 0,123,171, 3,124,152, 20, + 123,141, 34,122,132, 48,124,145, 29,124,149, 24,124,147, 26, + 123,139, 37,121,125, 63,124,145, 29,124,160, 12,124,165, 8, + 124,165, 8,123,173, 1,121,181, 0,119,185, 0,119,187, 0, + 119,186, 0,120,183, 0,119,185, 0,117,191, 0,115,195, 0, + 114,197, 0,114,197, 0,111,201, 0,109,204, 0,108,205, 0, + 109,203, 0,112,200, 0,114,197, 0,114,196, 0,116,192, 0, + 119,187, 0,119,186, 0,118,188, 0,117,191, 0,112,199, 0, + 109,204, 0,107,207, 0,106,207, 0,107,207, 0,105,209, 0, + 102,213, 0,101,214, 0,101,214, 0,102,213, 0,100,214, 0, + 100,215, 0,100,214, 0,102,213, 0, 99,215, 0, 98,216, 0, + 100,215, 0,103,211, 0,108,205, 0,114,197, 0,115,194, 0, + 113,198, 0,113,198, 0,113,198, 0,114,196, 0,113,198, 0, + 113,198, 0,114,197, 0,115,194, 0,115,195, 0,115,194, 0, + 117,192, 0,119,186, 0,122,178, 0,124,166, 7,124,162, 10, + 124,155, 16,123,141, 34,117,110,109,111, 96,248,114,104,197, + 115,107,129,113,100,242,109, 92,251, 99, 75,247,105, 84,252, + 118,114, 96,121,127, 58,122,132, 48,122,135, 44,122,135, 44, + 124,152, 20,124,161, 11,124,162, 10,124,164, 9,123,173, 1, + 122,178, 0,121,179, 0,122,175, 0,124,167, 6,124,161, 11, + 123,168, 5,122,177, 0,120,182, 0,119,186, 0,119,187, 0, + 119,187, 0,119,185, 0,120,182, 0,121,179, 0,120,184, 0, + 118,188, 0,118,189, 0,117,190, 0,118,189, 0,119,186, 0, + 120,184, 0,121,181, 0,121,182, 0,119,185, 0,118,189, 0, + 116,193, 0,114,196, 0,113,198, 0,112,199, 0,112,199, 0, + 108,205, 0,105,209, 0,103,212, 0,102,213, 0,102,213, 0, + 102,212, 0,104,210, 0,105,209, 0,107,207, 0,111,201, 0, + 117,192, 0,119,186, 0,121,179, 0,122,177, 0,123,174, 1, + 124,165, 8,124,157, 15,124,158, 13,124,155, 16,124,150, 22, + 124,160, 12,124,164, 9,124,164, 9,124,166, 7,124,166, 7, + 123,173, 1,121,180, 0,119,185, 0,118,189, 0,117,191, 0, + 117,191, 0,115,195, 0,112,199, 0,111,201, 0,112,200, 0, + 113,198, 0,116,193, 0,117,191, 0,118,189, 0,120,184, 0, + 122,176, 0,123,173, 1,123,171, 3,124,167, 6,124,158, 13, + 123,141, 34,119,119, 77,118,114, 96,115,107,129,117,110,109, + 121,125, 63,123,137, 41,124,150, 22,124,157, 15,124,160, 12, + 123,171, 3,121,180, 0,120,184, 0,119,185, 0,117,190, 0, + 115,194, 0,114,196, 0,114,196, 0,116,193, 0,115,194, 0, + 114,196, 0,115,195, 0,115,194, 0,116,193, 0,114,196, 0, + 112,199, 0,111,201, 0,110,203, 0,109,204, 0,108,206, 0, + 107,206, 0,107,206, 0,108,205, 0,110,202, 0,113,198, 0, + 110,203, 0,102,212, 0, 96,219, 0, 91,223, 0, 89,226, 0, + 89,226, 0, 91,224, 0, 91,223, 0, 91,223, 0, 94,221, 0, + 98,217, 0,103,211, 0,108,205, 0,111,202, 0,114,197, 0, + 118,189, 0,120,184, 0,119,185, 0,119,186, 0,119,186, 0, + 120,184, 0,121,182, 0,122,178, 0,122,177, 0,122,175, 0, + 123,172, 2,123,173, 1,123,171, 3,124,166, 7,124,158, 13, + 124,154, 18,124,145, 29,122,132, 48,124,150, 22,123,168, 5, + 122,178, 0,119,186, 0,117,190, 0,116,193, 0,116,193, 0, + 115,194, 0,114,196, 0,113,198, 0,113,198, 0,113,198, 0, + 114,196, 0,116,193, 0,118,189, 0,117,190, 0,116,193, 0, + 114,196, 0,115,195, 0,116,192, 0,119,186, 0,123,174, 1, + 124,157, 15,124,149, 24,124,149, 24,124,162, 10,124,167, 6, + 124,167, 6,124,160, 12,124,149, 24,123,141, 34,124,155, 16, + 124,165, 8,123,168, 5,123,168, 5,122,176, 0,121,182, 0, + 120,184, 0,120,182, 0,121,182, 0,118,189, 0,115,195, 0, + 112,199, 0,111,201, 0,111,201, 0,112,200, 0,109,203, 0, + 108,205, 0,108,205, 0,110,202, 0,112,200, 0,112,200, 0, + 113,198, 0,116,193, 0,117,191, 0,116,192, 0,115,194, 0, + 109,203, 0,105,209, 0,103,212, 0,102,212, 0,103,212, 0, + 100,214, 0, 97,217, 0, 97,218, 0, 97,217, 0, 98,217, 0, + 97,218, 0, 97,218, 0, 98,216, 0,100,215, 0, 98,217, 0, + 97,217, 0, 99,216, 0,102,212, 0,108,206, 0,113,198, 0, + 114,197, 0,111,201, 0,111,202, 0,111,201, 0,111,201, 0, + 110,203, 0,109,203, 0,110,202, 0,112,199, 0,114,197, 0, + 113,198, 0,114,196, 0,116,192, 0,119,187, 0,121,180, 0, + 123,170, 3,124,162, 10,124,152, 20,124,150, 22,124,154, 18, + 124,157, 15,124,157, 15,124,150, 22,123,139, 37,120,122, 70, + 113,100,242,120,122, 70,123,139, 37,124,149, 24,124,152, 20, + 124,157, 15,124,165, 8,123,170, 3,123,171, 3,121,179, 0, + 119,186, 0,118,189, 0,118,189, 0,119,185, 0,122,177, 0, + 123,168, 5,124,161, 11,123,171, 3,122,178, 0,121,182, 0, + 120,183, 0,120,183, 0,121,181, 0,122,178, 0,122,175, 0, + 121,181, 0,119,186, 0,118,188, 0,118,189, 0,118,188, 0, + 119,185, 0,120,182, 0,121,179, 0,121,180, 0,120,184, 0, + 118,189, 0,115,194, 0,113,198, 0,111,201, 0,110,202, 0, + 110,202, 0,106,208, 0,102,212, 0,100,214, 0,100,215, 0, + 100,215, 0,101,214, 0,102,213, 0,104,210, 0,106,208, 0, + 110,203, 0,112,199, 0,115,194, 0,119,187, 0,120,184, 0, + 121,179, 0,123,170, 3,123,172, 2,123,172, 2,124,167, 6, + 124,155, 16,124,147, 26,124,147, 26,124,145, 29,124,147, 26, + 124,164, 9,122,175, 0,120,184, 0,117,191, 0,115,194, 0, + 114,196, 0,115,195, 0,116,193, 0,113,198, 0,112,200, 0, + 111,201, 0,112,199, 0,114,197, 0,116,193, 0,117,192, 0, + 118,188, 0,119,187, 0,119,187, 0,119,186, 0,120,184, 0, + 121,179, 0,123,170, 3,124,157, 15,122,132, 48,121,125, 63, + 118,114, 96,121,127, 58,123,139, 37,124,143, 31,124,154, 18, + 124,160, 12,124,165, 8,122,177, 0,121,182, 0,119,185, 0, + 117,190, 0,115,194, 0,114,196, 0,115,195, 0,116,192, 0, + 114,196, 0,113,198, 0,113,198, 0,114,197, 0,114,197, 0, + 113,198, 0,111,201, 0,110,203, 0,106,207, 0,105,209, 0, + 104,210, 0,105,209, 0,105,209, 0,106,208, 0,108,206, 0, + 111,201, 0,108,206, 0,100,214, 0, 94,221, 0, 89,226, 0, + 86,228, 0, 86,228, 0, 88,226, 0, 91,223, 0, 91,223, 0, + 94,221, 0, 98,217, 0,103,212, 0,107,207, 0,110,203, 0, + 113,198, 0,117,190, 0,118,189, 0,118,189, 0,118,188, 0, + 119,186, 0,120,183, 0,122,178, 0,123,173, 1,123,170, 3, + 122,176, 0,121,180, 0,121,181, 0,122,178, 0,123,173, 1, + 124,164, 9,124,147, 26,121,125, 63,118,117, 85,124,149, 24, + 124,166, 7,122,177, 0,120,184, 0,118,188, 0,118,189, 0, + 118,189, 0,118,189, 0,117,191, 0,116,192, 0,116,193, 0, + 116,192, 0,117,191, 0,119,187, 0,120,182, 0,119,186, 0, + 117,191, 0,116,193, 0,116,193, 0,118,189, 0,120,183, 0, + 123,171, 3,124,154, 18,124,155, 16,124,162, 10,123,173, 1, + 122,177, 0,122,177, 0,123,171, 3,124,161, 11,124,149, 24, + 124,160, 12,124,164, 9,123,169, 4,123,171, 3,123,172, 2, + 122,178, 0,121,180, 0,122,178, 0,119,185, 0,116,192, 0, + 113,198, 0,110,202, 0,109,204, 0,109,204, 0,110,203, 0, + 111,202, 0,109,204, 0,109,204, 0,109,203, 0,109,204, 0, + 109,204, 0,110,202, 0,112,199, 0,115,194, 0,115,195, 0, + 113,198, 0,107,207, 0,102,213, 0, 98,216, 0, 97,217, 0, + 97,217, 0, 98,217, 0, 95,220, 0, 94,221, 0, 94,220, 0, + 94,221, 0, 93,221, 0, 94,220, 0, 96,219, 0, 99,215, 0, + 98,217, 0, 97,217, 0, 99,216, 0,102,212, 0,107,206, 0, + 109,204, 0,110,202, 0,111,202, 0,110,202, 0,109,204, 0, + 107,206, 0,106,207, 0,106,207, 0,108,206, 0,110,202, 0, + 113,198, 0,113,199, 0,113,198, 0,114,196, 0,116,193, 0, + 118,188, 0,120,183, 0,122,177, 0,123,173, 1,123,173, 1, + 122,175, 0,122,176, 0,123,174, 1,123,170, 3,124,162, 10, + 124,149, 24,122,135, 44,123,141, 34,124,152, 20,124,161, 11, + 124,167, 6,123,170, 3,123,174, 1,122,178, 0,120,183, 0, + 118,189, 0,116,193, 0,114,196, 0,114,196, 0,117,192, 0, + 120,184, 0,123,171, 3,124,164, 9,124,166, 7,123,173, 1, + 122,177, 0,122,178, 0,122,178, 0,120,182, 0,120,184, 0, + 121,182, 0,120,184, 0,119,186, 0,119,186, 0,119,186, 0, + 119,186, 0,119,186, 0,119,186, 0,119,186, 0,119,186, 0, + 120,184, 0,118,188, 0,116,193, 0,113,198, 0,111,202, 0, + 109,203, 0,109,204, 0,104,210, 0,101,214, 0, 98,216, 0, + 98,217, 0, 99,216, 0, 97,218, 0, 96,219, 0, 98,217, 0, + 101,214, 0,104,210, 0,108,206, 0,112,200, 0,116,193, 0, + 117,191, 0,119,186, 0,122,178, 0,121,179, 0,122,177, 0, + 123,170, 3,124,154, 18,118,117, 85,117,110,109,121,125, 63, + 124,150, 22,124,166, 7,121,180, 0,118,189, 0,114,196, 0, + 113,199, 0,112,200, 0,113,199, 0,114,197, 0,114,197, 0, + 112,200, 0,111,202, 0,110,202, 0,111,201, 0,112,200, 0, + 113,198, 0,114,197, 0,114,197, 0,113,198, 0,113,198, 0, + 114,196, 0,116,192, 0,119,186, 0,122,178, 0,124,166, 7, + 124,143, 31,122,130, 53,120,122, 70,123,139, 37,124,147, 26, + 124,150, 22,124,157, 15,124,165, 8,123,171, 3,122,178, 0, + 120,184, 0,118,189, 0,116,192, 0,116,193, 0,116,192, 0, + 116,193, 0,114,197, 0,113,199, 0,112,200, 0,112,200, 0, + 112,199, 0,112,200, 0,110,202, 0,107,207, 0,103,211, 0, + 101,214, 0,100,215, 0,100,214, 0,101,213, 0,103,211, 0, + 105,209, 0,106,207, 0,107,207, 0,100,215, 0, 93,222, 0, + 88,226, 0, 85,229, 0, 84,229, 0, 86,228, 0, 89,225, 0, + 93,222, 0, 95,220, 0, 98,217, 0,102,212, 0,107,207, 0, + 110,202, 0,114,197, 0,115,194, 0,116,192, 0,117,191, 0, + 118,189, 0,119,186, 0,121,181, 0,122,175, 0,123,168, 5, + 123,173, 1,121,179, 0,120,182, 0,120,183, 0,121,181, 0, + 122,175, 0,124,166, 7,124,152, 20,122,132, 48,122,132, 48, + 124,154, 18,123,168, 5,122,178, 0,120,184, 0,118,189, 0, + 117,192, 0,117,192, 0,118,189, 0,119,185, 0,120,184, 0, + 120,184, 0,120,183, 0,121,180, 0,122,175, 0,122,178, 0, + 120,183, 0,119,186, 0,118,188, 0,119,187, 0,120,183, 0, + 123,174, 1,124,160, 12,124,161, 11,124,162, 10,123,172, 2, + 121,180, 0,120,184, 0,120,183, 0,122,178, 0,123,171, 3, + 124,162, 10,124,161, 11,124,165, 8,124,167, 6,123,170, 3, + 123,172, 2,122,177, 0,122,178, 0,121,180, 0,119,186, 0, + 116,193, 0,113,198, 0,110,202, 0,109,204, 0,108,205, 0, + 109,204, 0,109,203, 0,109,204, 0,108,206, 0,106,207, 0, + 105,209, 0,105,209, 0,106,207, 0,108,205, 0,112,200, 0, + 114,197, 0,111,201, 0,104,210, 0, 98,217, 0, 94,221, 0, + 92,223, 0, 92,223, 0, 92,223, 0, 91,223, 0, 91,224, 0, + 90,225, 0, 89,225, 0, 90,225, 0, 91,223, 0, 94,221, 0, + 98,217, 0,100,215, 0, 99,215, 0,101,214, 0,103,211, 0, + 105,209, 0,105,209, 0,106,207, 0,107,207, 0,107,207, 0, + 106,208, 0,105,209, 0,105,209, 0,105,209, 0,107,207, 0, + 110,203, 0,112,199, 0,112,200, 0,112,200, 0,113,199, 0, + 114,196, 0,116,193, 0,118,189, 0,119,185, 0,120,183, 0, + 120,182, 0,120,183, 0,120,183, 0,121,182, 0,122,178, 0, + 123,172, 2,124,164, 9,124,154, 18,124,154, 18,124,160, 12, + 123,168, 5,123,174, 1,121,179, 0,120,184, 0,119,187, 0, + 118,189, 0,115,194, 0,113,198, 0,112,200, 0,112,199, 0, + 114,196, 0,118,188, 0,122,177, 0,124,164, 9,124,161, 11, + 123,168, 5,123,170, 3,122,177, 0,120,183, 0,119,187, 0, + 118,189, 0,118,189, 0,117,191, 0,117,192, 0,117,191, 0, + 117,191, 0,117,191, 0,117,191, 0,117,191, 0,117,192, 0, + 117,191, 0,117,190, 0,118,189, 0,117,192, 0,113,198, 0, + 110,202, 0,108,205, 0,107,206, 0,103,211, 0,100,215, 0, + 98,217, 0, 98,217, 0, 96,219, 0, 93,222, 0, 92,223, 0, + 93,222, 0, 96,219, 0,100,215, 0,103,211, 0,108,205, 0, + 112,200, 0,113,198, 0,115,194, 0,118,188, 0,120,182, 0, + 122,178, 0,123,168, 5,124,147, 26,109, 92,251,109, 92,251, + 122,135, 44,124,157, 15,122,175, 0,119,187, 0,115,195, 0, + 112,200, 0,110,202, 0,110,203, 0,111,202, 0,112,200, 0, + 113,198, 0,112,200, 0,110,202, 0,109,204, 0,108,205, 0, + 108,205, 0,108,205, 0,108,205, 0,108,206, 0,107,206, 0, + 108,205, 0,109,204, 0,112,200, 0,114,196, 0,118,189, 0, + 121,182, 0,123,169, 4,124,145, 29,121,127, 58,121,127, 58, + 123,141, 34,124,147, 26,124,149, 24,124,155, 16,124,166, 7, + 122,175, 0,121,182, 0,119,186, 0,118,188, 0,118,189, 0, + 118,188, 0,116,193, 0,114,197, 0,112,199, 0,112,200, 0, + 112,200, 0,112,200, 0,112,200, 0,110,202, 0,106,207, 0, + 102,212, 0, 99,215, 0, 97,217, 0, 97,217, 0, 98,217, 0, + 100,215, 0,101,213, 0,103,211, 0,104,210, 0,101,214, 0, + 95,220, 0, 90,225, 0, 86,228, 0, 85,229, 0, 86,228, 0, + 88,226, 0, 92,223, 0, 95,219, 0,100,215, 0,103,211, 0, + 106,207, 0,110,203, 0,112,199, 0,114,196, 0,116,193, 0, + 117,191, 0,118,188, 0,120,184, 0,122,178, 0,123,170, 3, + 124,162, 10,123,171, 3,122,177, 0,121,180, 0,121,180, 0, + 122,178, 0,123,172, 2,124,162, 10,124,147, 26,121,127, 58, + 124,143, 31,124,161, 11,123,174, 1,120,182, 0,118,188, 0, + 117,191, 0,116,192, 0,117,191, 0,118,188, 0,120,183, 0, + 122,178, 0,123,173, 1,123,170, 3,123,170, 3,123,171, 3, + 123,174, 1,122,177, 0,121,179, 0,122,178, 0,122,176, 0, + 123,169, 4,124,157, 15,124,162, 10,124,166, 7,123,168, 5, + 122,178, 0,119,185, 0,118,188, 0,119,187, 0,120,184, 0, + 121,179, 0,123,173, 1,123,169, 4,124,167, 6,123,168, 5, + 123,170, 3,122,175, 0,122,178, 0,122,178, 0,121,181, 0, + 119,187, 0,117,191, 0,115,195, 0,112,199, 0,110,202, 0, + 110,203, 0,109,203, 0,109,204, 0,108,205, 0,106,208, 0, + 104,210, 0,102,212, 0,102,213, 0,102,212, 0,105,209, 0, + 108,205, 0,113,198, 0,110,203, 0,102,213, 0, 95,220, 0, + 90,225, 0, 87,227, 0, 87,227, 0, 87,227, 0, 87,227, 0, + 87,227, 0, 86,228, 0, 86,228, 0, 87,227, 0, 89,226, 0, + 92,223, 0, 96,219, 0,102,213, 0,102,212, 0,103,211, 0, + 104,210, 0,103,212, 0,103,212, 0,104,210, 0,105,209, 0, + 105,209, 0,105,209, 0,105,209, 0,106,208, 0,107,207, 0, + 109,204, 0,112,200, 0,112,199, 0,112,200, 0,112,200, 0, + 112,199, 0,113,198, 0,115,195, 0,116,192, 0,118,189, 0, + 118,188, 0,119,187, 0,119,186, 0,119,186, 0,120,184, 0, + 121,181, 0,122,177, 0,123,171, 3,124,166, 7,124,164, 9, + 124,166, 7,122,176, 0,120,184, 0,118,189, 0,116,193, 0, + 115,194, 0,115,194, 0,114,197, 0,111,201, 0,110,202, 0, + 111,201, 0,113,198, 0,117,191, 0,121,180, 0,124,164, 9, + 124,157, 15,124,164, 9,123,169, 4,122,178, 0,120,184, 0, + 118,189, 0,117,191, 0,116,193, 0,115,195, 0,115,195, 0, + 115,194, 0,116,193, 0,116,193, 0,116,192, 0,116,193, 0, + 115,194, 0,115,194, 0,116,193, 0,117,192, 0,117,191, 0, + 114,197, 0,110,202, 0,107,206, 0,106,208, 0,104,210, 0, + 100,214, 0, 98,217, 0, 98,217, 0, 94,220, 0, 91,223, 0, + 89,225, 0, 90,225, 0, 92,222, 0, 96,219, 0,100,214, 0, + 105,209, 0,107,207, 0,108,205, 0,111,201, 0,114,196, 0, + 118,188, 0,121,179, 0,124,167, 6,124,152, 20,122,132, 48, + 115,107,129,123,139, 37,124,166, 7,121,181, 0,117,191, 0, + 113,198, 0,110,202, 0,109,204, 0,108,205, 0,109,203, 0, + 111,202, 0,112,200, 0,112,199, 0,110,203, 0,108,206, 0, + 106,207, 0,106,208, 0,105,209, 0,104,210, 0,103,211, 0, + 103,211, 0,104,210, 0,105,209, 0,108,206, 0,111,201, 0, + 114,196, 0,117,191, 0,120,183, 0,123,171, 3,124,149, 24, + 117,110,109,120,122, 70,122,135, 44,123,139, 37,123,139, 37, + 124,154, 18,124,167, 6,122,175, 0,121,181, 0,120,183, 0, + 120,183, 0,119,186, 0,117,192, 0,114,196, 0,113,198, 0, + 113,198, 0,113,198, 0,113,198, 0,113,199, 0,111,201, 0, + 107,206, 0,102,212, 0, 99,216, 0, 97,218, 0, 95,219, 0, + 96,219, 0, 97,218, 0, 99,216, 0,101,214, 0,102,212, 0, + 104,210, 0, 99,215, 0, 94,221, 0, 90,224, 0, 88,226, 0, + 87,227, 0, 89,226, 0, 92,223, 0, 96,219, 0,101,214, 0, + 105,209, 0,107,206, 0,110,202, 0,112,199, 0,115,195, 0, + 117,191, 0,118,188, 0,120,184, 0,122,178, 0,123,172, 2, + 124,165, 8,124,157, 15,124,164, 9,123,170, 3,123,173, 1, + 123,173, 1,123,170, 3,124,164, 9,124,152, 20,122,135, 44, + 119,119, 77,124,145, 29,124,165, 8,122,176, 0,120,184, 0, + 118,188, 0,117,191, 0,117,191, 0,118,188, 0,120,184, 0, + 122,178, 0,123,172, 2,124,167, 6,124,164, 9,124,164, 9, + 124,167, 6,123,168, 5,124,166, 7,124,165, 8,124,161, 11, + 124,154, 18,123,141, 34,124,152, 20,124,164, 9,124,167, 6, + 123,173, 1,121,182, 0,119,186, 0,118,189, 0,118,189, 0, + 119,187, 0,120,184, 0,121,181, 0,122,178, 0,122,177, 0, + 122,178, 0,122,178, 0,121,180, 0,120,182, 0,120,184, 0, + 119,185, 0,118,188, 0,117,192, 0,116,193, 0,115,194, 0, + 114,197, 0,112,200, 0,111,201, 0,110,203, 0,108,206, 0, + 105,209, 0,102,212, 0,100,215, 0, 99,216, 0,100,215, 0, + 102,213, 0,105,209, 0,111,202, 0,108,205, 0,100,215, 0, + 92,223, 0, 86,228, 0, 83,230, 0, 83,230, 0, 83,230, 0, + 84,229, 0, 84,229, 0, 83,230, 0, 84,229, 0, 85,229, 0, + 87,227, 0, 91,223, 0, 95,219, 0,102,213, 0,105,209, 0, + 106,208, 0,103,212, 0,101,213, 0,102,213, 0,103,212, 0, + 105,209, 0,106,208, 0,106,207, 0,107,206, 0,109,204, 0, + 110,202, 0,112,199, 0,113,199, 0,114,197, 0,113,198, 0, + 113,198, 0,113,198, 0,114,197, 0,114,196, 0,116,193, 0, + 117,191, 0,118,189, 0,118,189, 0,118,188, 0,119,186, 0, + 120,184, 0,120,182, 0,121,180, 0,122,178, 0,122,175, 0, + 123,171, 3,122,178, 0,119,186, 0,116,193, 0,114,197, 0, + 112,200, 0,111,201, 0,111,201, 0,112,200, 0,110,202, 0, + 109,203, 0,110,202, 0,113,199, 0,117,192, 0,121,181, 0, + 124,165, 8,124,154, 18,124,161, 11,124,166, 7,122,176, 0, + 120,184, 0,118,189, 0,117,191, 0,115,195, 0,114,197, 0, + 114,196, 0,115,194, 0,116,193, 0,116,192, 0,116,192, 0, + 116,193, 0,115,194, 0,114,196, 0,114,196, 0,114,196, 0, + 115,194, 0,114,197, 0,110,202, 0,107,207, 0,105,209, 0, + 105,209, 0,101,214, 0, 98,216, 0, 97,217, 0, 95,220, 0, + 91,223, 0, 89,225, 0, 89,225, 0, 91,223, 0, 94,220, 0, + 99,216, 0,101,214, 0,102,213, 0,104,210, 0,107,207, 0, + 110,202, 0,114,196, 0,118,189, 0,121,181, 0,123,170, 3, + 124,155, 16,122,132, 48,123,141, 34,123,168, 5,120,182, 0, + 116,192, 0,113,199, 0,110,203, 0,108,205, 0,108,205, 0, + 109,203, 0,111,202, 0,112,199, 0,113,199, 0,110,203, 0, + 107,206, 0,106,208, 0,104,210, 0,103,211, 0,102,213, 0, + 101,214, 0,101,214, 0,101,213, 0,103,211, 0,106,208, 0, + 109,204, 0,111,201, 0,114,197, 0,117,192, 0,119,185, 0, + 123,173, 1,124,154, 18,121,127, 58,122,132, 48,123,137, 41, + 123,139, 37,123,141, 34,124,154, 18,124,167, 6,123,173, 1, + 122,176, 0,122,176, 0,121,182, 0,118,188, 0,116,192, 0, + 115,194, 0,115,195, 0,115,195, 0,115,194, 0,114,196, 0, + 111,201, 0,108,205, 0,104,210, 0,100,215, 0, 97,218, 0, + 95,220, 0, 95,220, 0, 95,219, 0, 97,218, 0, 98,216, 0, + 101,214, 0,103,211, 0,105,209, 0,100,215, 0, 96,219, 0, + 93,222, 0, 91,223, 0, 91,223, 0, 94,221, 0, 98,217, 0, + 103,212, 0,108,205, 0,110,203, 0,112,200, 0,114,197, 0, + 117,191, 0,119,186, 0,121,180, 0,122,175, 0,123,169, 4, + 124,162, 10,124,155, 16,124,149, 24,124,149, 24,124,158, 13, + 124,162, 10,124,161, 11,124,155, 16,124,147, 26,122,132, 48, + 118,114, 96,118,114, 96,124,145, 29,124,165, 8,122,177, 0, + 120,184, 0,118,188, 0,118,188, 0,119,186, 0,120,182, 0, + 122,175, 0,123,168, 5,124,160, 12,124,161, 11,123,170, 3, + 122,176, 0,121,179, 0,121,179, 0,123,174, 1,124,162, 10, + 123,139, 37,114,104,197,122,130, 53,124,149, 24,124,158, 13, + 124,162, 10,123,172, 2,121,180, 0,120,184, 0,119,187, 0, + 118,188, 0,119,187, 0,119,186, 0,120,184, 0,120,183, 0, + 120,183, 0,120,183, 0,120,184, 0,119,185, 0,119,186, 0, + 118,188, 0,118,189, 0,117,191, 0,117,191, 0,117,191, 0, + 117,191, 0,117,191, 0,115,194, 0,113,198, 0,111,201, 0, + 108,205, 0,105,209, 0,101,214, 0, 98,216, 0, 97,217, 0, + 98,217, 0,100,214, 0,104,210, 0,109,203, 0,106,208, 0, + 97,218, 0, 89,225, 0, 83,230, 0, 81,232, 0, 80,232, 0, + 82,231, 0, 82,231, 0, 83,230, 0, 83,230, 0, 84,229, 0, + 85,229, 0, 88,226, 0, 92,223, 0, 97,218, 0,103,211, 0, + 108,205, 0,105,209, 0,102,212, 0,101,214, 0,101,213, 0, + 103,211, 0,105,209, 0,107,207, 0,107,206, 0,108,205, 0, + 110,203, 0,111,201, 0,112,199, 0,113,198, 0,116,193, 0, + 115,194, 0,115,194, 0,115,195, 0,115,195, 0,115,194, 0, + 116,193, 0,117,191, 0,116,193, 0,115,194, 0,114,196, 0, + 114,197, 0,114,196, 0,115,194, 0,117,191, 0,119,186, 0, + 121,182, 0,122,178, 0,119,186, 0,115,194, 0,112,200, 0, + 109,204, 0,108,206, 0,107,207, 0,107,206, 0,109,203, 0, + 109,203, 0,109,204, 0,110,202, 0,113,199, 0,117,191, 0, + 121,180, 0,124,162, 10,124,154, 18,124,160, 12,124,161, 11, + 123,171, 3,121,180, 0,119,186, 0,118,188, 0,115,194, 0, + 114,196, 0,115,194, 0,116,192, 0,117,191, 0,118,189, 0, + 118,189, 0,117,191, 0,116,193, 0,114,196, 0,112,200, 0, + 112,200, 0,112,199, 0,111,201, 0,109,204, 0,107,206, 0, + 106,208, 0,105,209, 0,102,213, 0, 98,217, 0, 97,218, 0, + 97,218, 0, 94,220, 0, 92,223, 0, 91,223, 0, 92,222, 0, + 95,219, 0, 97,217, 0, 97,218, 0, 98,217, 0,100,215, 0, + 103,211, 0,107,207, 0,110,202, 0,114,197, 0,118,189, 0, + 121,180, 0,124,167, 6,124,143, 31,122,132, 48,124,162, 10, + 122,178, 0,118,189, 0,114,196, 0,111,201, 0,110,202, 0, + 110,203, 0,111,202, 0,112,200, 0,114,197, 0,112,199, 0, + 109,204, 0,107,207, 0,106,208, 0,105,209, 0,103,211, 0, + 102,212, 0,101,214, 0,101,214, 0,101,213, 0,103,211, 0, + 105,209, 0,107,206, 0,109,203, 0,111,201, 0,113,198, 0, + 115,194, 0,119,187, 0,122,177, 0,124,157, 15,124,143, 31, + 123,141, 34,123,139, 37,122,130, 53,122,135, 44,124,155, 16, + 124,165, 8,123,168, 5,123,168, 5,123,173, 1,121,182, 0, + 119,187, 0,118,189, 0,117,190, 0,117,190, 0,117,190, 0, + 116,193, 0,112,200, 0,108,205, 0,106,208, 0,101,213, 0, + 97,217, 0, 95,220, 0, 94,221, 0, 94,220, 0, 94,220, 0, + 95,220, 0, 97,218, 0,100,215, 0,104,210, 0,107,207, 0, + 103,211, 0,100,215, 0, 97,218, 0, 96,219, 0, 98,217, 0, + 102,213, 0,107,207, 0,112,200, 0,113,199, 0,114,196, 0, + 117,191, 0,120,184, 0,122,176, 0,124,167, 6,124,160, 12, + 124,152, 20,124,145, 29,123,139, 37,122,135, 44,122,132, 48, + 123,137, 41,123,141, 34,123,139, 37,122,132, 48,119,119, 77, + 115,107,129,111, 96,248,118,117, 85,123,141, 34,124,164, 9, + 122,176, 0,120,182, 0,119,185, 0,120,184, 0,121,180, 0, + 123,172, 2,124,162, 10,124,150, 22,124,160, 12,123,171, 3, + 121,179, 0,120,184, 0,119,186, 0,120,184, 0,122,178, 0, + 124,165, 8,123,141, 34,122,135, 44,119,119, 77,123,137, 41, + 124,145, 29,124,157, 15,124,167, 6,123,173, 1,122,178, 0, + 121,181, 0,120,183, 0,120,184, 0,120,184, 0,120,184, 0, + 120,184, 0,119,185, 0,119,185, 0,119,186, 0,119,187, 0, + 118,188, 0,117,190, 0,116,192, 0,115,194, 0,115,195, 0, + 115,195, 0,115,194, 0,116,192, 0,115,194, 0,114,197, 0, + 113,199, 0,109,203, 0,105,209, 0,101,214, 0, 98,217, 0, + 97,218, 0, 98,217, 0,100,214, 0,104,210, 0,108,205, 0, + 103,211, 0, 94,220, 0, 87,227, 0, 82,231, 0, 79,234, 0, + 79,234, 0, 80,232, 0, 82,231, 0, 83,230, 0, 84,229, 0, + 85,229, 0, 87,227, 0, 90,225, 0, 94,221, 0, 99,215, 0, + 106,208, 0,107,206, 0,103,211, 0,101,214, 0,101,214, 0, + 102,213, 0,104,210, 0,106,207, 0,106,207, 0,107,207, 0, + 108,205, 0,110,202, 0,112,200, 0,114,197, 0,115,194, 0, + 119,186, 0,119,187, 0,118,189, 0,117,190, 0,117,191, 0, + 117,192, 0,117,192, 0,117,192, 0,114,196, 0,113,199, 0, + 111,202, 0,109,203, 0,109,203, 0,111,202, 0,113,198, 0, + 116,192, 0,119,186, 0,120,184, 0,116,193, 0,111,201, 0, + 108,206, 0,105,209, 0,104,210, 0,104,210, 0,105,209, 0, + 107,207, 0,109,204, 0,109,204, 0,110,202, 0,113,198, 0, + 117,190, 0,122,178, 0,124,158, 13,124,154, 18,124,161, 11, + 124,164, 9,124,165, 8,123,173, 1,121,179, 0,119,186, 0, + 117,192, 0,116,192, 0,117,191, 0,118,189, 0,117,192, 0, + 117,191, 0,118,188, 0,119,187, 0,117,190, 0,114,197, 0, + 111,202, 0,110,203, 0,110,202, 0,109,204, 0,107,207, 0, + 106,208, 0,107,207, 0,106,207, 0,102,213, 0, 98,217, 0, + 96,219, 0, 96,219, 0, 98,217, 0, 96,219, 0, 95,220, 0, + 95,219, 0, 97,218, 0, 95,220, 0, 94,221, 0, 95,220, 0, + 97,217, 0,100,214, 0,104,210, 0,107,206, 0,111,201, 0, + 115,194, 0,119,185, 0,123,171, 3,124,147, 26,115,107,129, + 124,145, 29,123,168, 5,120,182, 0,117,191, 0,114,196, 0, + 113,199, 0,112,199, 0,113,198, 0,114,196, 0,114,197, 0, + 110,202, 0,107,207, 0,105,209, 0,105,209, 0,105,209, 0, + 106,208, 0,104,210, 0,103,212, 0,102,212, 0,103,211, 0, + 104,210, 0,106,208, 0,106,208, 0,107,206, 0,109,204, 0, + 110,203, 0,111,201, 0,114,196, 0,118,189, 0,122,177, 0, + 124,154, 18,123,141, 34,122,135, 44,119,119, 77,117,110,109, + 123,141, 34,124,155, 16,124,160, 12,124,160, 12,124,158, 13, + 123,171, 3,122,178, 0,120,183, 0,119,187, 0,118,188, 0, + 118,188, 0,117,192, 0,113,198, 0,110,203, 0,107,207, 0, + 103,212, 0, 98,217, 0, 95,220, 0, 93,221, 0, 93,221, 0, + 93,222, 0, 92,222, 0, 93,221, 0, 95,220, 0, 98,216, 0, + 103,212, 0,108,206, 0,107,207, 0,104,210, 0,102,212, 0, + 103,211, 0,107,207, 0,111,201, 0,115,194, 0,116,193, 0, + 118,189, 0,120,183, 0,123,172, 2,124,157, 15,123,141, 34, + 121,127, 58,118,117, 85,118,114, 96,117,110,109,117,110,109, + 117,110,109,117,110,109,117,110,109,115,107,129,115,107,129, + 115,107,129,114,104,197,115,107,129,121,125, 63,123,139, 37, + 124,162, 10,123,174, 1,121,181, 0,120,182, 0,121,179, 0, + 123,172, 2,124,160, 12,124,150, 22,124,158, 13,124,166, 7, + 122,176, 0,120,184, 0,118,188, 0,118,189, 0,119,187, 0, + 121,179, 0,124,167, 6,124,165, 8,124,158, 13,124,143, 31, + 118,114, 96,119,119, 77,123,141, 34,124,154, 18,124,161, 11, + 124,166, 7,123,170, 3,123,174, 1,122,177, 0,121,179, 0, + 121,182, 0,120,182, 0,120,183, 0,120,184, 0,119,185, 0, + 119,186, 0,118,188, 0,118,189, 0,116,192, 0,114,196, 0, + 113,198, 0,113,199, 0,113,199, 0,113,198, 0,114,196, 0, + 113,198, 0,113,199, 0,110,202, 0,106,208, 0,101,213, 0, + 98,216, 0, 98,217, 0, 99,216, 0,102,213, 0,106,208, 0, + 108,206, 0,100,214, 0, 92,223, 0, 84,229, 0, 80,233, 0, + 78,234, 0, 78,234, 0, 81,232, 0, 81,232, 0, 82,231, 0, + 85,228, 0, 87,227, 0, 90,225, 0, 93,222, 0, 97,218, 0, + 102,212, 0,108,206, 0,106,208, 0,102,212, 0,100,214, 0, + 101,214, 0,102,212, 0,106,208, 0,107,207, 0,107,207, 0, + 108,206, 0,109,203, 0,112,200, 0,114,196, 0,117,192, 0, + 118,188, 0,122,175, 0,122,177, 0,121,180, 0,120,184, 0, + 119,187, 0,118,189, 0,117,191, 0,117,191, 0,114,196, 0, + 112,200, 0,109,204, 0,107,207, 0,106,207, 0,108,206, 0, + 110,202, 0,114,196, 0,118,189, 0,117,191, 0,112,200, 0, + 108,206, 0,104,210, 0,102,212, 0,102,212, 0,103,212, 0, + 104,210, 0,106,207, 0,107,206, 0,108,205, 0,110,202, 0, + 114,197, 0,118,188, 0,123,174, 1,124,154, 18,124,155, 16, + 124,164, 9,124,167, 6,124,166, 7,124,165, 8,123,169, 4, + 121,182, 0,118,188, 0,118,189, 0,117,192, 0,114,197, 0, + 113,198, 0,114,197, 0,116,193, 0,118,188, 0,119,187, 0, + 114,197, 0,110,202, 0,108,205, 0,108,205, 0,107,206, 0, + 105,209, 0,105,209, 0,106,208, 0,107,207, 0,102,213, 0, + 97,217, 0, 95,220, 0, 94,220, 0, 96,219, 0,100,215, 0, + 99,215, 0, 99,215, 0, 95,219, 0, 93,221, 0, 92,222, 0, + 94,221, 0, 96,219, 0, 99,216, 0,102,212, 0,105,209, 0, + 109,203, 0,114,197, 0,119,187, 0,123,172, 2,124,145, 29, + 105, 84,252,115,107,129,124,147, 26,123,169, 4,121,182, 0, + 118,188, 0,116,192, 0,115,194, 0,115,194, 0,114,196, 0, + 112,200, 0,108,206, 0,105,209, 0,104,210, 0,104,210, 0, + 106,208, 0,108,205, 0,108,205, 0,106,207, 0,106,208, 0, + 106,208, 0,104,210, 0,102,212, 0,102,213, 0,103,211, 0, + 107,207, 0,107,207, 0,108,205, 0,110,202, 0,114,196, 0, + 119,186, 0,123,170, 3,123,139, 37,121,125, 63,113,100,242, + 114,104,197,121,125, 63,124,145, 29,124,150, 22,124,150, 22, + 124,145, 29,124,161, 11,122,177, 0,119,185, 0,118,189, 0, + 117,192, 0,116,192, 0,115,195, 0,114,197, 0,112,200, 0, + 109,204, 0,103,211, 0, 98,217, 0, 94,220, 0, 92,222, 0, + 92,222, 0, 92,222, 0, 91,223, 0, 91,223, 0, 92,223, 0, + 94,221, 0, 98,217, 0,103,212, 0,109,204, 0,111,201, 0, + 109,203, 0,110,202, 0,113,199, 0,116,193, 0,118,188, 0, + 119,185, 0,121,180, 0,123,170, 3,124,154, 18,124,143, 31, + 123,137, 41,120,122, 70,111, 96,248, 99, 75,247, 69, 60,230, + 87, 65,237, 94, 70,242, 94, 70,242, 99, 75,247,102, 80,250, + 105, 84,252,107, 89,252,109, 92,251,118,117, 85,122,130, 53, + 123,141, 34,124,162, 10,123,174, 1,121,179, 0,121,179, 0, + 122,175, 0,124,165, 8,124,149, 24,124,157, 15,123,169, 4, + 122,175, 0,122,178, 0,119,186, 0,118,189, 0,117,191, 0, + 119,187, 0,121,180, 0,121,180, 0,122,178, 0,123,170, 3, + 124,154, 18,118,117, 85,105, 84,252,117,110,109,121,127, 58, + 123,137, 41,124,149, 24,124,157, 15,124,160, 12,124,165, 8, + 123,170, 3,123,174, 1,122,176, 0,122,178, 0,120,182, 0, + 119,185, 0,119,186, 0,119,186, 0,119,186, 0,118,189, 0, + 116,193, 0,114,197, 0,112,199, 0,112,200, 0,113,199, 0, + 114,197, 0,113,198, 0,113,198, 0,110,202, 0,106,208, 0, + 102,213, 0,100,215, 0, 99,215, 0,101,214, 0,104,210, 0, + 108,205, 0,106,208, 0, 97,217, 0, 89,225, 0, 82,231, 0, + 78,234, 0, 77,235, 0, 78,234, 0, 81,232, 0, 80,233, 0, + 81,232, 0, 85,229, 0, 90,224, 0, 93,221, 0, 97,218, 0, + 101,213, 0,107,207, 0,108,205, 0,104,210, 0,101,214, 0, + 100,215, 0,101,214, 0,103,211, 0,107,207, 0,108,205, 0, + 109,204, 0,110,202, 0,112,200, 0,114,196, 0,117,190, 0, + 120,184, 0,122,178, 0,124,157, 15,124,161, 11,123,168, 5, + 122,176, 0,120,183, 0,118,188, 0,117,191, 0,116,192, 0, + 116,193, 0,113,199, 0,109,203, 0,107,207, 0,106,208, 0, + 107,207, 0,110,203, 0,114,197, 0,118,189, 0,113,198, 0, + 109,204, 0,105,209, 0,102,213, 0,101,214, 0,101,213, 0, + 103,211, 0,105,209, 0,105,209, 0,106,208, 0,107,206, 0, + 110,202, 0,114,196, 0,119,186, 0,123,170, 3,123,141, 34, + 124,157, 15,124,166, 7,123,169, 4,123,170, 3,123,168, 5, + 123,169, 4,121,180, 0,119,186, 0,116,193, 0,112,199, 0, + 110,202, 0,109,204, 0,110,202, 0,113,198, 0,116,192, 0, + 119,186, 0,114,196, 0,110,202, 0,108,205, 0,107,207, 0, + 107,207, 0,106,208, 0,105,209, 0,106,208, 0,103,211, 0, + 101,214, 0, 97,218, 0, 94,221, 0, 94,221, 0, 95,219, 0, + 99,215, 0,103,211, 0, 99,216, 0, 95,220, 0, 93,222, 0, + 92,222, 0, 93,221, 0, 95,219, 0, 98,216, 0,102,213, 0, + 105,209, 0,109,204, 0,113,198, 0,118,188, 0,123,173, 1, + 124,143, 31, 99, 75,247, 30, 20,155,114,104,197,124,145, 29, + 124,167, 6,122,178, 0,120,184, 0,118,189, 0,116,193, 0, + 114,196, 0,110,203, 0,106,208, 0,104,210, 0,103,211, 0, + 105,209, 0,107,207, 0,108,205, 0,112,200, 0,110,203, 0, + 108,206, 0,105,209, 0,102,213, 0,100,215, 0,100,215, 0, + 101,213, 0,105,209, 0,105,209, 0,105,209, 0,107,206, 0, + 111,201, 0,117,191, 0,122,177, 0,124,150, 22,114,104,197, + 117,110,109,118,117, 85,118,114, 96,123,137, 41,124,145, 29, + 124,147, 26,124,154, 18,124,158, 13,122,176, 0,119,185, 0, + 117,191, 0,115,194, 0,115,195, 0,114,196, 0,114,197, 0, + 114,196, 0,109,204, 0,103,212, 0, 97,218, 0, 93,222, 0, + 91,224, 0, 90,225, 0, 91,223, 0, 92,222, 0, 92,223, 0, + 91,223, 0, 92,222, 0, 95,220, 0, 99,215, 0,105,209, 0, + 111,202, 0,115,194, 0,116,193, 0,118,189, 0,120,184, 0, + 121,181, 0,122,178, 0,123,174, 1,124,167, 6,124,152, 20, + 124,154, 18,124,149, 24,123,139, 37,119,119, 77,107, 89,252, + 30, 55,222, 30, 31,180, 30, 2,128, 30, 37,192, 30, 43,203, + 30, 43,203, 30, 31,180, 30, 49,213,107, 89,252,117,110,109, + 119,119, 77,124,149, 24,124,166, 7,122,176, 0,121,180, 0, + 121,179, 0,123,173, 1,124,161, 11,123,137, 41,124,161, 11, + 123,172, 2,122,178, 0,120,182, 0,119,186, 0,118,189, 0, + 118,189, 0,119,186, 0,119,187, 0,119,186, 0,120,183, 0, + 123,174, 1,124,157, 15,121,127, 58,111, 96,248, 87, 65,237, + 119,119, 77,124,145, 29,124,160, 12,124,165, 8,124,167, 6, + 124,166, 7,124,164, 9,124,161, 11,123,170, 3,122,177, 0, + 121,181, 0,120,184, 0,119,185, 0,119,185, 0,120,184, 0, + 121,182, 0,119,187, 0,117,191, 0,115,194, 0,114,196, 0, + 114,196, 0,114,197, 0,114,197, 0,114,197, 0,110,202, 0, + 106,208, 0,102,212, 0,100,214, 0,101,214, 0,103,211, 0, + 107,207, 0,111,202, 0,103,211, 0, 95,220, 0, 87,227, 0, + 80,232, 0, 77,235, 0, 77,235, 0, 78,234, 0, 82,231, 0, + 80,233, 0, 81,232, 0, 85,229, 0, 90,224, 0, 96,219, 0, + 100,214, 0,105,209, 0,111,202, 0,107,207, 0,103,212, 0, + 100,214, 0, 99,215, 0,101,214, 0,103,211, 0,108,206, 0, + 112,200, 0,113,199, 0,114,197, 0,116,193, 0,118,188, 0, + 121,181, 0,123,171, 3,124,162, 10,122,175, 0,123,174, 1, + 123,169, 4,123,168, 5,122,178, 0,119,186, 0,117,192, 0, + 115,195, 0,114,197, 0,114,196, 0,111,201, 0,109,204, 0, + 107,206, 0,108,205, 0,111,202, 0,114,196, 0,114,196, 0, + 109,203, 0,105,209, 0,102,213, 0,100,214, 0,101,214, 0, + 102,212, 0,102,212, 0,102,212, 0,103,211, 0,105,209, 0, + 107,206, 0,111,202, 0,115,194, 0,120,183, 0,124,165, 8, + 124,152, 20,124,154, 18,124,164, 9,123,170, 3,123,172, 2, + 123,171, 3,121,180, 0,119,187, 0,116,193, 0,113,199, 0, + 109,203, 0,107,206, 0,107,207, 0,108,205, 0,111,201, 0, + 114,196, 0,117,190, 0,115,194, 0,111,201, 0,108,205, 0, + 107,207, 0,106,208, 0,106,208, 0,105,209, 0,104,210, 0, + 102,213, 0, 99,215, 0, 97,218, 0, 95,220, 0, 94,220, 0, + 96,219, 0, 99,215, 0,100,215, 0, 99,216, 0, 95,220, 0, + 93,221, 0, 93,222, 0, 93,221, 0, 92,222, 0, 93,221, 0, + 96,219, 0,101,214, 0,106,207, 0,112,199, 0,118,189, 0, + 122,177, 0,124,157, 15,120,122, 70,105, 84,252,115,107,129, + 121,125, 63,124,145, 29,123,168, 5,121,182, 0,118,189, 0, + 116,193, 0,114,197, 0,108,205, 0,105,209, 0,103,211, 0, + 103,211, 0,105,209, 0,105,209, 0,106,208, 0,109,204, 0, + 109,204, 0,106,208, 0,103,211, 0,100,214, 0, 98,216, 0, + 98,216, 0,100,214, 0,103,211, 0,102,212, 0,103,212, 0, + 105,209, 0,110,203, 0,115,194, 0,121,182, 0,124,160, 12, + 124,143, 31,122,130, 53,120,122, 70,118,114, 96,121,127, 58, + 124,147, 26,124,157, 15,124,164, 9,123,168, 5,123,174, 1, + 120,184, 0,117,191, 0,115,195, 0,113,198, 0,112,200, 0, + 112,200, 0,111,201, 0,108,206, 0,102,213, 0, 96,219, 0, + 92,222, 0, 89,225, 0, 89,226, 0, 89,225, 0, 91,224, 0, + 93,221, 0, 94,221, 0, 94,221, 0, 95,219, 0, 99,216, 0, + 103,211, 0,108,205, 0,113,198, 0,116,193, 0,118,189, 0, + 119,186, 0,120,184, 0,121,180, 0,122,175, 0,124,167, 6, + 124,161, 11,124,162, 10,124,158, 13,124,150, 22,123,137, 41, + 118,117, 85,115,107,129,113,100,242,111, 96,248,109, 92,251, + 102, 80,250, 87, 65,237, 94, 70,242,102, 80,250,109, 92,251, + 118,114, 96,122,135, 44,124,155, 16,123,170, 3,122,178, 0, + 121,181, 0,121,179, 0,123,173, 1,124,160, 12,124,149, 24, + 124,158, 13,123,171, 3,122,178, 0,120,183, 0,119,186, 0, + 118,188, 0,118,188, 0,118,189, 0,118,189, 0,118,188, 0, + 120,183, 0,123,173, 1,124,152, 20,122,132, 48,115,107,129, + 120,122, 70,122,135, 44,124,155, 16,124,166, 7,123,170, 3, + 123,171, 3,123,170, 3,123,172, 2,122,175, 0,122,178, 0, + 121,181, 0,120,183, 0,119,186, 0,119,187, 0,118,189, 0, + 118,189, 0,118,188, 0,119,185, 0,120,184, 0,119,187, 0, + 118,189, 0,117,192, 0,116,193, 0,115,194, 0,112,200, 0, + 108,205, 0,104,210, 0,102,213, 0,101,214, 0,102,212, 0, + 105,209, 0,109,203, 0,109,204, 0,102,213, 0, 93,221, 0, + 86,228, 0, 80,232, 0, 78,235, 0, 78,235, 0, 80,233, 0, + 83,230, 0, 81,232, 0, 83,230, 0, 86,228, 0, 91,223, 0, + 97,218, 0,103,212, 0,108,206, 0,109,204, 0,106,208, 0, + 102,212, 0,100,215, 0, 99,216, 0,100,214, 0,103,211, 0, + 108,206, 0,112,200, 0,116,193, 0,119,187, 0,121,182, 0, + 123,174, 1,124,164, 9,124,165, 8,123,172, 2,119,186, 0, + 119,186, 0,121,182, 0,123,174, 1,121,179, 0,119,186, 0, + 116,193, 0,113,199, 0,111,201, 0,111,201, 0,113,198, 0, + 110,202, 0,109,204, 0,109,204, 0,111,201, 0,114,197, 0, + 110,202, 0,106,208, 0,102,212, 0,100,214, 0,100,215, 0, + 101,214, 0,103,212, 0,101,214, 0,102,213, 0,104,210, 0, + 106,208, 0,109,204, 0,113,198, 0,117,191, 0,122,178, 0, + 124,167, 6,124,164, 9,124,158, 13,124,160, 12,124,167, 6, + 123,171, 3,122,177, 0,119,186, 0,116,192, 0,114,197, 0, + 111,201, 0,108,205, 0,107,207, 0,106,207, 0,108,206, 0, + 110,202, 0,113,198, 0,115,195, 0,113,198, 0,111,201, 0, + 109,203, 0,107,206, 0,106,208, 0,105,209, 0,105,209, 0, + 104,210, 0,102,213, 0, 99,216, 0, 97,218, 0, 95,220, 0, + 95,220, 0, 95,219, 0, 97,218, 0, 97,218, 0, 96,219, 0, + 95,220, 0, 94,221, 0, 92,223, 0, 90,225, 0, 89,226, 0, + 89,226, 0, 91,223, 0, 96,219, 0,101,213, 0,108,206, 0, + 114,197, 0,119,187, 0,123,174, 1,124,154, 18,120,122, 70, + 123,137, 41,124,145, 29,124,152, 20,124,162, 10,121,179, 0, + 118,188, 0,116,193, 0,113,198, 0,108,205, 0,105,209, 0, + 103,212, 0,103,212, 0,105,209, 0,105,209, 0,105,209, 0, + 107,207, 0,108,206, 0,105,209, 0,101,214, 0, 98,216, 0, + 97,218, 0, 96,219, 0, 98,217, 0,101,214, 0,102,213, 0, + 102,212, 0,104,210, 0,108,205, 0,113,198, 0,119,187, 0, + 123,173, 1,124,164, 9,124,154, 18,124,147, 26,123,141, 34, + 122,132, 48,124,152, 20,124,164, 9,123,170, 3,122,176, 0, + 121,181, 0,119,186, 0,117,190, 0,114,196, 0,112,200, 0, + 110,202, 0,108,205, 0,107,206, 0,107,207, 0,102,212, 0, + 97,218, 0, 93,221, 0, 91,224, 0, 90,225, 0, 90,225, 0, + 91,224, 0, 92,222, 0, 96,219, 0, 97,217, 0, 98,217, 0, + 100,214, 0,103,211, 0,107,207, 0,111,201, 0,114,197, 0, + 116,193, 0,117,190, 0,119,186, 0,120,182, 0,122,175, 0, + 124,167, 6,123,169, 4,123,170, 3,123,168, 5,124,162, 10, + 124,154, 18,124,154, 18,124,152, 20,124,149, 24,124,147, 26, + 124,145, 29,123,137, 41,121,125, 63,115,107,129,115,107,129, + 118,114, 96,121,125, 63,123,141, 34,124,158, 13,123,169, 4, + 122,176, 0,122,178, 0,122,176, 0,123,169, 4,124,158, 13, + 124,160, 12,124,165, 8,123,171, 3,122,177, 0,120,183, 0, + 119,186, 0,118,188, 0,118,189, 0,118,189, 0,118,189, 0, + 119,186, 0,121,180, 0,124,167, 6,124,150, 22,121,127, 58, + 123,137, 41,124,149, 24,124,158, 13,124,167, 6,123,173, 1, + 122,178, 0,121,179, 0,121,180, 0,121,181, 0,121,182, 0, + 120,184, 0,119,185, 0,119,187, 0,118,188, 0,117,190, 0, + 117,191, 0,117,191, 0,118,189, 0,119,187, 0,119,185, 0, + 120,184, 0,119,186, 0,118,189, 0,116,193, 0,113,198, 0, + 110,203, 0,106,207, 0,103,211, 0,102,213, 0,102,213, 0, + 104,210, 0,108,206, 0,109,203, 0,107,206, 0,101,214, 0, + 94,221, 0, 87,227, 0, 83,230, 0, 81,232, 0, 82,231, 0, + 84,229, 0, 84,229, 0, 83,230, 0, 85,229, 0, 89,226, 0, + 93,221, 0, 99,216, 0,104,210, 0,108,205, 0,107,207, 0, + 103,211, 0,101,214, 0, 99,216, 0, 99,216, 0,101,214, 0, + 104,210, 0,108,205, 0,112,199, 0,116,192, 0,119,185, 0, + 122,176, 0,124,166, 7,123,170, 3,122,178, 0,120,183, 0, + 116,192, 0,116,192, 0,118,189, 0,120,182, 0,120,184, 0, + 118,188, 0,115,194, 0,111,201, 0,109,204, 0,109,204, 0, + 110,202, 0,111,202, 0,109,204, 0,109,203, 0,111,201, 0, + 110,202, 0,107,206, 0,103,211, 0,101,214, 0, 99,215, 0, + 100,215, 0,102,213, 0,102,212, 0,101,214, 0,102,212, 0, + 106,208, 0,109,204, 0,112,199, 0,116,192, 0,120,184, 0, + 123,170, 3,123,171, 3,123,170, 3,124,167, 6,124,164, 9, + 124,162, 10,124,167, 6,121,182, 0,117,190, 0,115,195, 0, + 113,199, 0,111,201, 0,109,203, 0,108,205, 0,108,205, 0, + 109,204, 0,111,202, 0,113,199, 0,112,200, 0,110,203, 0, + 108,205, 0,107,207, 0,106,208, 0,106,208, 0,105,209, 0, + 105,209, 0,105,209, 0,103,211, 0,101,214, 0, 98,217, 0, + 96,219, 0, 95,220, 0, 94,220, 0, 95,220, 0, 95,220, 0, + 94,220, 0, 94,221, 0, 92,222, 0, 90,224, 0, 88,226, 0, + 86,228, 0, 86,228, 0, 88,226, 0, 93,222, 0, 98,217, 0, + 104,210, 0,110,202, 0,116,192, 0,121,182, 0,124,167, 6, + 124,147, 26,124,149, 24,124,155, 16,124,160, 12,124,166, 7, + 122,176, 0,119,187, 0,116,193, 0,114,197, 0,108,205, 0, + 105,209, 0,103,212, 0,103,212, 0,105,209, 0,106,208, 0, + 105,209, 0,107,207, 0,107,207, 0,103,211, 0,100,215, 0, + 97,218, 0, 95,220, 0, 94,220, 0, 95,219, 0, 98,217, 0, + 101,214, 0,102,213, 0,103,211, 0,106,207, 0,111,201, 0, + 116,193, 0,120,183, 0,122,175, 0,124,167, 6,124,161, 11, + 124,154, 18,124,147, 26,124,152, 20,124,166, 7,122,175, 0, + 121,182, 0,119,187, 0,117,191, 0,115,194, 0,114,196, 0, + 112,200, 0,109,204, 0,106,207, 0,105,209, 0,104,210, 0, + 104,210, 0,100,215, 0, 97,218, 0, 94,220, 0, 93,221, 0, + 93,222, 0, 92,222, 0, 93,221, 0, 95,219, 0, 99,215, 0, + 102,212, 0,103,211, 0,105,209, 0,107,206, 0,110,202, 0, + 113,199, 0,114,196, 0,116,193, 0,118,189, 0,120,184, 0, + 122,175, 0,123,172, 2,122,175, 0,122,176, 0,123,174, 1, + 123,170, 3,123,172, 2,123,173, 1,123,172, 2,123,171, 3, + 123,171, 3,123,169, 4,124,164, 9,124,154, 18,123,137, 41, + 121,125, 63,121,125, 63,122,130, 53,123,141, 34,124,155, 16, + 124,166, 7,123,170, 3,123,171, 3,123,169, 4,124,162, 10, + 124,164, 9,124,167, 6,123,171, 3,122,176, 0,121,179, 0, + 121,182, 0,119,186, 0,118,188, 0,118,188, 0,118,188, 0, + 119,185, 0,121,181, 0,123,172, 2,124,155, 16,124,143, 31, + 123,137, 41,124,150, 22,124,160, 12,123,168, 5,122,175, 0, + 121,181, 0,120,184, 0,119,186, 0,119,185, 0,120,184, 0, + 120,184, 0,119,186, 0,119,186, 0,118,188, 0,118,188, 0, + 118,189, 0,117,190, 0,118,189, 0,118,188, 0,119,185, 0, + 120,184, 0,120,184, 0,119,187, 0,117,191, 0,114,196, 0, + 111,201, 0,108,205, 0,105,209, 0,103,212, 0,102,212, 0, + 103,212, 0,106,208, 0,109,203, 0,108,205, 0,106,208, 0, + 102,212, 0, 95,219, 0, 90,224, 0, 87,227, 0, 86,228, 0, + 87,227, 0, 89,225, 0, 87,227, 0, 87,227, 0, 89,225, 0, + 92,222, 0, 97,218, 0,102,213, 0,106,207, 0,108,205, 0, + 105,209, 0,102,212, 0,100,215, 0, 99,215, 0,100,215, 0, + 102,212, 0,106,208, 0,110,203, 0,114,197, 0,117,191, 0, + 120,182, 0,123,171, 3,123,174, 1,121,179, 0,120,184, 0, + 118,189, 0,115,195, 0,114,196, 0,116,193, 0,119,187, 0, + 119,186, 0,117,191, 0,115,195, 0,111,202, 0,108,205, 0, + 108,206, 0,108,205, 0,109,203, 0,108,205, 0,108,205, 0, + 109,204, 0,107,206, 0,106,208, 0,102,212, 0,100,214, 0, + 100,215, 0,101,214, 0,103,212, 0,103,212, 0,102,212, 0, + 105,209, 0,108,205, 0,112,199, 0,116,192, 0,120,184, 0, + 123,172, 2,124,167, 6,123,171, 3,123,173, 1,123,172, 2, + 123,168, 5,124,162, 10,123,170, 3,120,184, 0,117,192, 0, + 114,196, 0,113,199, 0,112,200, 0,112,200, 0,111,201, 0, + 111,201, 0,112,200, 0,113,199, 0,113,198, 0,109,203, 0, + 107,206, 0,106,208, 0,105,209, 0,105,209, 0,105,209, 0, + 105,209, 0,105,209, 0,106,208, 0,106,208, 0,103,211, 0, + 101,214, 0, 98,217, 0, 96,219, 0, 95,219, 0, 95,220, 0, + 95,220, 0, 94,220, 0, 94,221, 0, 92,222, 0, 91,223, 0, + 89,225, 0, 87,227, 0, 87,227, 0, 88,226, 0, 92,222, 0, + 97,217, 0,103,211, 0,110,203, 0,115,194, 0,120,183, 0, + 123,170, 3,124,155, 16,124,149, 24,124,157, 15,124,161, 11, + 124,166, 7,123,174, 1,119,186, 0,116,192, 0,114,196, 0, + 109,203, 0,105,209, 0,103,212, 0,102,212, 0,105,209, 0, + 108,205, 0,108,206, 0,109,204, 0,107,206, 0,103,211, 0, + 99,216, 0, 95,219, 0, 93,221, 0, 93,222, 0, 94,221, 0, + 95,219, 0, 98,217, 0,101,213, 0,102,212, 0,105,209, 0, + 109,204, 0,113,198, 0,117,191, 0,120,183, 0,122,175, 0, + 123,168, 5,124,162, 10,124,155, 16,124,150, 22,124,165, 8, + 122,177, 0,119,185, 0,117,191, 0,114,196, 0,112,199, 0, + 111,201, 0,112,200, 0,109,204, 0,106,208, 0,103,211, 0, + 102,212, 0,103,212, 0,105,209, 0,102,212, 0,100,215, 0, + 99,216, 0, 98,217, 0, 97,218, 0, 96,219, 0, 97,218, 0, + 99,215, 0,103,212, 0,107,207, 0,109,204, 0,109,203, 0, + 111,201, 0,113,199, 0,114,197, 0,115,194, 0,117,191, 0, + 119,185, 0,122,176, 0,123,174, 1,122,178, 0,121,179, 0, + 122,178, 0,121,180, 0,120,182, 0,120,183, 0,120,182, 0, + 120,182, 0,120,182, 0,121,181, 0,122,176, 0,124,167, 6, + 124,152, 20,122,132, 48,121,127, 58,121,127, 58,123,137, 41, + 124,150, 22,124,158, 13,124,161, 11,124,161, 11,124,157, 15, + 124,161, 11,124,166, 7,123,171, 3,122,176, 0,122,178, 0, + 121,180, 0,121,180, 0,120,184, 0,119,186, 0,119,186, 0, + 120,183, 0,122,178, 0,123,171, 3,124,160, 12,124,145, 29, + 122,132, 48,123,141, 34,124,152, 20,124,161, 11,123,171, 3, + 121,179, 0,120,184, 0,118,188, 0,118,189, 0,118,188, 0, + 119,186, 0,119,185, 0,119,185, 0,119,185, 0,119,187, 0, + 118,189, 0,118,189, 0,118,188, 0,119,186, 0,120,184, 0, + 121,181, 0,121,180, 0,121,181, 0,119,185, 0,118,189, 0, + 115,195, 0,112,200, 0,109,204, 0,106,208, 0,104,210, 0, + 103,211, 0,105,209, 0,107,207, 0,111,202, 0,108,205, 0, + 106,208, 0,105,209, 0, 99,215, 0, 95,220, 0, 93,222, 0, + 93,222, 0, 94,221, 0, 92,223, 0, 90,224, 0, 91,223, 0, + 94,221, 0, 98,217, 0,102,212, 0,106,207, 0,110,202, 0, + 108,205, 0,105,209, 0,102,212, 0,101,213, 0,101,213, 0, + 103,212, 0,106,208, 0,109,204, 0,113,199, 0,116,193, 0, + 119,186, 0,122,176, 0,123,174, 1,122,178, 0,120,182, 0, + 119,187, 0,117,191, 0,115,194, 0,114,196, 0,115,194, 0, + 118,189, 0,119,187, 0,117,192, 0,115,195, 0,111,201, 0, + 108,205, 0,108,206, 0,108,205, 0,108,206, 0,106,208, 0, + 106,208, 0,107,207, 0,105,209, 0,105,209, 0,103,212, 0, + 101,213, 0,101,214, 0,102,212, 0,104,210, 0,104,210, 0, + 104,210, 0,107,207, 0,112,200, 0,115,194, 0,119,186, 0, + 123,173, 1,124,154, 18,124,160, 12,123,168, 5,123,173, 1, + 123,173, 1,123,170, 3,124,166, 7,123,174, 1,119,186, 0, + 116,192, 0,114,196, 0,114,197, 0,114,196, 0,115,195, 0, + 115,194, 0,115,194, 0,116,193, 0,116,193, 0,112,199, 0, + 108,205, 0,106,208, 0,105,209, 0,105,209, 0,105,209, 0, + 106,208, 0,106,207, 0,106,207, 0,106,207, 0,107,207, 0, + 107,207, 0,105,209, 0,102,213, 0,100,215, 0, 98,217, 0, + 97,218, 0, 96,219, 0, 96,219, 0, 95,219, 0, 93,222, 0, + 93,222, 0, 92,222, 0, 91,224, 0, 90,225, 0, 91,223, 0, + 94,220, 0,100,215, 0,105,209, 0,111,201, 0,117,191, 0, + 121,180, 0,124,167, 6,124,152, 20,123,139, 37,124,150, 22, + 124,157, 15,124,162, 10,123,172, 2,120,184, 0,117,191, 0, + 116,193, 0,110,202, 0,106,208, 0,103,211, 0,102,212, 0, + 104,210, 0,108,205, 0,111,201, 0,111,201, 0,109,204, 0, + 104,210, 0, 99,215, 0, 95,219, 0, 93,221, 0, 92,222, 0, + 93,222, 0, 94,220, 0, 96,219, 0, 99,216, 0,102,213, 0, + 104,210, 0,107,207, 0,110,202, 0,114,197, 0,117,192, 0, + 118,188, 0,120,183, 0,122,178, 0,123,171, 3,124,161, 11, + 124,158, 13,122,175, 0,119,185, 0,116,193, 0,113,199, 0, + 110,202, 0,109,204, 0,109,204, 0,111,202, 0,107,207, 0, + 103,211, 0,102,212, 0,103,211, 0,105,209, 0,108,205, 0, + 107,207, 0,106,208, 0,104,210, 0,102,212, 0,100,214, 0, + 100,215, 0,100,214, 0,102,212, 0,106,207, 0,111,201, 0, + 113,199, 0,113,198, 0,114,197, 0,114,197, 0,115,195, 0, + 116,192, 0,119,186, 0,122,178, 0,123,174, 1,122,178, 0, + 121,179, 0,120,182, 0,119,186, 0,118,188, 0,118,188, 0, + 118,188, 0,119,187, 0,118,188, 0,119,186, 0,120,182, 0, + 123,173, 1,124,160, 12,122,135, 44,121,127, 58,122,132, 48, + 122,130, 53,123,141, 34,124,147, 26,124,147, 26,124,143, 31, + 124,152, 20,124,160, 12,124,166, 7,123,172, 2,122,178, 0, + 121,180, 0,121,180, 0,122,178, 0,121,180, 0,121,182, 0, + 121,180, 0,122,175, 0,124,167, 6,124,155, 16,123,137, 41, + 121,127, 58,121,127, 58,122,135, 44,124,145, 29,124,157, 15, + 123,169, 4,121,179, 0,119,186, 0,118,189, 0,118,189, 0, + 118,188, 0,119,186, 0,120,184, 0,120,183, 0,119,187, 0, + 118,189, 0,117,191, 0,117,190, 0,118,188, 0,119,185, 0, + 120,182, 0,121,180, 0,122,178, 0,122,176, 0,121,179, 0, + 119,186, 0,117,191, 0,114,197, 0,111,201, 0,109,204, 0, + 107,207, 0,106,207, 0,107,207, 0,109,204, 0,112,200, 0, + 109,203, 0,107,207, 0,106,207, 0,104,210, 0,101,214, 0, + 99,215, 0, 99,215, 0, 99,215, 0, 95,219, 0, 95,220, 0, + 97,218, 0,100,214, 0,104,210, 0,108,205, 0,112,200, 0, + 113,199, 0,109,203, 0,106,207, 0,105,209, 0,104,210, 0, + 105,209, 0,107,206, 0,110,202, 0,114,197, 0,117,191, 0, + 119,185, 0,122,178, 0,123,170, 3,123,174, 1,122,178, 0, + 120,182, 0,119,186, 0,117,191, 0,117,192, 0,115,194, 0, + 116,193, 0,117,190, 0,119,186, 0,117,190, 0,116,193, 0, + 112,199, 0,109,203, 0,108,205, 0,108,205, 0,104,210, 0, + 102,212, 0,102,212, 0,105,209, 0,104,210, 0,103,211, 0, + 105,209, 0,103,211, 0,103,211, 0,105,209, 0,106,208, 0, + 105,209, 0,106,207, 0,110,202, 0,112,199, 0,114,196, 0, + 118,189, 0,122,178, 0,124,158, 13,124,150, 22,124,160, 12, + 123,168, 5,123,170, 3,124,167, 6,123,172, 2,122,178, 0, + 119,187, 0,116,193, 0,115,195, 0,115,194, 0,115,195, 0, + 114,196, 0,115,195, 0,117,191, 0,119,185, 0,118,188, 0, + 113,198, 0,109,204, 0,107,207, 0,106,208, 0,106,208, 0, + 107,207, 0,108,206, 0,108,205, 0,108,205, 0,108,205, 0, + 108,205, 0,110,203, 0,109,204, 0,106,208, 0,103,211, 0, + 101,213, 0,100,215, 0,100,215, 0,100,215, 0, 95,220, 0, + 92,222, 0, 92,223, 0, 94,221, 0, 96,219, 0, 95,220, 0, + 96,219, 0, 99,215, 0,103,211, 0,109,204, 0,115,195, 0, + 119,185, 0,123,171, 3,124,155, 16,123,139, 37,118,117, 85, + 122,132, 48,124,145, 29,124,154, 18,123,170, 3,120,183, 0, + 118,189, 0,117,192, 0,112,200, 0,107,207, 0,104,210, 0, + 103,212, 0,104,210, 0,108,205, 0,113,198, 0,115,194, 0, + 111,202, 0,106,208, 0,101,214, 0, 97,218, 0, 94,220, 0, + 94,221, 0, 94,221, 0, 95,220, 0, 96,219, 0, 98,217, 0, + 100,215, 0,103,212, 0,106,208, 0,108,205, 0,111,202, 0, + 113,198, 0,114,196, 0,115,194, 0,117,192, 0,118,188, 0, + 120,182, 0,123,172, 2,123,170, 3,120,183, 0,116,192, 0, + 112,200, 0,108,205, 0,107,207, 0,107,207, 0,109,204, 0, + 109,204, 0,106,208, 0,104,210, 0,105,209, 0,107,207, 0, + 110,202, 0,113,198, 0,113,199, 0,111,201, 0,109,204, 0, + 106,208, 0,103,211, 0,102,212, 0,103,211, 0,107,207, 0, + 111,201, 0,116,193, 0,116,193, 0,115,194, 0,115,195, 0, + 115,195, 0,116,192, 0,118,188, 0,121,179, 0,123,170, 3, + 122,175, 0,121,180, 0,119,185, 0,118,188, 0,118,189, 0, + 118,189, 0,118,188, 0,118,188, 0,118,189, 0,118,189, 0, + 120,184, 0,122,176, 0,124,161, 11,123,137, 41,123,139, 37, + 123,141, 34,122,132, 48,122,132, 48,122,132, 48,121,127, 58, + 123,137, 41,124,147, 26,124,157, 15,124,165, 8,123,172, 2, + 122,178, 0,121,179, 0,122,178, 0,122,175, 0,122,175, 0, + 122,176, 0,123,172, 2,124,164, 9,124,152, 20,123,139, 37, + 118,117, 85,118,114, 96,118,114, 96,119,119, 77,122,130, 53, + 124,145, 29,124,164, 9,122,176, 0,120,184, 0,118,188, 0, + 118,189, 0,119,187, 0,120,184, 0,121,181, 0,119,185, 0, + 118,189, 0,117,191, 0,117,191, 0,117,190, 0,119,187, 0, + 120,183, 0,121,179, 0,122,177, 0,123,174, 1,123,172, 2, + 123,170, 3,122,178, 0,120,184, 0,117,190, 0,115,194, 0, + 113,198, 0,111,201, 0,110,203, 0,109,203, 0,110,202, 0, + 112,200, 0,112,200, 0,109,203, 0,109,204, 0,110,202, 0, + 107,207, 0,106,208, 0,105,209, 0,103,211, 0,101,214, 0, + 101,214, 0,103,211, 0,107,207, 0,111,201, 0,115,194, 0, + 118,188, 0,115,194, 0,112,199, 0,109,203, 0,108,205, 0, + 109,204, 0,110,202, 0,113,198, 0,116,193, 0,119,187, 0, + 121,179, 0,123,172, 2,124,162, 10,124,165, 8,123,170, 3, + 123,174, 1,122,178, 0,120,182, 0,119,187, 0,118,188, 0, + 117,191, 0,117,191, 0,118,189, 0,119,185, 0,119,186, 0, + 118,189, 0,114,197, 0,111,202, 0,109,203, 0,104,210, 0, + 100,215, 0, 98,217, 0, 98,217, 0,100,214, 0,104,210, 0, + 103,211, 0,105,209, 0,106,207, 0,106,207, 0,107,207, 0, + 106,208, 0,106,208, 0,108,205, 0,112,200, 0,112,199, 0, + 114,197, 0,117,191, 0,121,182, 0,123,168, 5,124,161, 11, + 124,149, 24,124,158, 13,124,162, 10,124,166, 7,123,174, 1, + 121,180, 0,118,188, 0,116,193, 0,115,194, 0,116,192, 0, + 114,196, 0,113,198, 0,114,197, 0,116,193, 0,118,188, 0, + 117,191, 0,114,196, 0,110,202, 0,108,205, 0,108,205, 0, + 109,204, 0,110,203, 0,111,202, 0,112,200, 0,112,200, 0, + 111,201, 0,111,201, 0,112,200, 0,113,199, 0,110,202, 0, + 108,205, 0,106,208, 0,105,209, 0,103,211, 0,101,214, 0, + 95,219, 0, 92,222, 0, 91,223, 0, 93,221, 0, 97,217, 0, + 102,212, 0,102,212, 0,105,209, 0,109,204, 0,114,196, 0, + 119,187, 0,123,174, 1,124,155, 16,122,132, 48,118,114, 96, + 107, 89,252,113,100,242,120,122, 70,124,147, 26,123,169, 4, + 121,181, 0,119,187, 0,118,189, 0,114,197, 0,109,204, 0, + 105,209, 0,104,210, 0,105,209, 0,109,204, 0,114,196, 0, + 117,190, 0,113,198, 0,108,206, 0,103,212, 0, 99,215, 0, + 97,218, 0, 96,219, 0, 97,218, 0, 97,218, 0, 97,217, 0, + 98,217, 0,100,215, 0,102,213, 0,104,210, 0,107,206, 0, + 109,203, 0,111,201, 0,112,200, 0,112,200, 0,112,200, 0, + 114,197, 0,116,193, 0,119,186, 0,122,176, 0,122,178, 0, + 117,190, 0,113,199, 0,108,205, 0,106,208, 0,106,208, 0, + 107,206, 0,110,203, 0,109,204, 0,107,206, 0,108,206, 0, + 110,203, 0,112,200, 0,114,196, 0,115,195, 0,116,193, 0, + 115,195, 0,111,201, 0,108,206, 0,106,208, 0,106,208, 0, + 108,206, 0,112,200, 0,116,192, 0,119,187, 0,118,189, 0, + 116,192, 0,116,193, 0,116,192, 0,118,188, 0,121,181, 0, + 123,169, 4,123,170, 3,121,181, 0,119,186, 0,118,188, 0, + 118,188, 0,118,188, 0,118,188, 0,119,187, 0,118,188, 0, + 118,188, 0,120,184, 0,122,175, 0,124,161, 11,124,145, 29, + 124,145, 29,124,143, 31,122,132, 48,121,125, 63,119,119, 77, + 119,119, 77,123,141, 34,124,158, 13,124,166, 7,123,169, 4, + 123,171, 3,122,177, 0,122,178, 0,122,175, 0,123,170, 3, + 123,169, 4,123,168, 5,124,161, 11,124,145, 29,123,139, 37, + 120,122, 70,109, 92,251,107, 89,252,109, 92,251,114,104,197, + 115,107,129,122,132, 48,124,158, 13,123,172, 2,121,181, 0, + 119,186, 0,118,188, 0,119,186, 0,120,182, 0,121,179, 0, + 119,186, 0,117,190, 0,117,191, 0,117,190, 0,118,188, 0, + 120,183, 0,122,178, 0,123,173, 1,123,169, 4,124,167, 6, + 124,165, 8,124,164, 9,124,164, 9,123,171, 3,122,178, 0, + 120,184, 0,118,188, 0,116,193, 0,114,197, 0,112,199, 0, + 112,200, 0,113,199, 0,114,196, 0,113,198, 0,112,200, 0, + 113,198, 0,113,199, 0,111,201, 0,110,202, 0,108,205, 0, + 106,207, 0,107,207, 0,110,202, 0,112,200, 0,114,197, 0, + 117,192, 0,118,189, 0,117,190, 0,116,192, 0,114,197, 0, + 113,198, 0,114,197, 0,116,193, 0,118,188, 0,121,181, 0, + 123,171, 3,124,160, 12,124,149, 24,123,141, 34,124,154, 18, + 124,161, 11,124,166, 7,122,175, 0,121,182, 0,120,184, 0, + 120,182, 0,119,187, 0,118,188, 0,119,187, 0,120,184, 0, + 121,182, 0,119,187, 0,115,195, 0,112,200, 0,106,208, 0, + 100,215, 0, 95,219, 0, 94,221, 0, 94,221, 0, 96,219, 0, + 100,215, 0,103,211, 0,105,209, 0,108,205, 0,108,205, 0, + 107,207, 0,106,208, 0,106,207, 0,109,204, 0,113,198, 0, + 113,198, 0,114,196, 0,117,191, 0,120,182, 0,123,172, 2, + 124,165, 8,124,154, 18,123,141, 34,124,147, 26,124,164, 9, + 123,173, 1,120,184, 0,117,190, 0,116,193, 0,116,193, 0, + 117,191, 0,115,194, 0,114,197, 0,114,197, 0,115,194, 0, + 116,193, 0,114,197, 0,113,198, 0,113,199, 0,111,201, 0, + 111,201, 0,111,201, 0,111,201, 0,112,200, 0,113,199, 0, + 114,196, 0,116,193, 0,116,193, 0,116,192, 0,116,193, 0, + 114,196, 0,112,199, 0,110,202, 0,109,204, 0,108,205, 0, + 102,212, 0, 97,217, 0, 94,221, 0, 92,222, 0, 94,221, 0, + 98,217, 0,103,211, 0,109,204, 0,111,201, 0,114,196, 0, + 119,187, 0,122,176, 0,124,165, 8,124,149, 24,120,122, 70, + 99, 75,247, 30, 55,222, 30, 55,222,114,104,197,124,145, 29, + 124,167, 6,122,178, 0,120,184, 0,119,185, 0,115,194, 0, + 110,202, 0,107,207, 0,106,208, 0,108,206, 0,112,200, 0, + 117,192, 0,119,186, 0,115,195, 0,110,202, 0,105,209, 0, + 102,212, 0,100,214, 0,100,215, 0,101,214, 0,101,214, 0, + 100,215, 0,100,214, 0,101,214, 0,102,212, 0,103,211, 0, + 106,208, 0,108,205, 0,111,201, 0,111,201, 0,110,202, 0, + 110,202, 0,110,202, 0,112,199, 0,116,193, 0,119,186, 0, + 123,174, 1,119,186, 0,114,196, 0,110,202, 0,107,207, 0, + 106,207, 0,108,206, 0,110,202, 0,112,199, 0,110,202, 0, + 110,202, 0,112,200, 0,113,198, 0,113,198, 0,114,197, 0, + 115,194, 0,118,188, 0,116,192, 0,113,199, 0,110,203, 0, + 109,204, 0,111,202, 0,114,197, 0,118,189, 0,121,180, 0, + 120,184, 0,118,189, 0,117,191, 0,117,191, 0,118,188, 0, + 121,182, 0,123,171, 3,123,169, 4,121,179, 0,120,184, 0, + 119,186, 0,118,188, 0,117,191, 0,116,192, 0,117,191, 0, + 119,186, 0,119,186, 0,120,182, 0,123,174, 1,124,160, 12, + 124,145, 29,124,143, 31,123,139, 37,120,122, 70,121,125, 63, + 118,117, 85,122,132, 48,124,152, 20,124,166, 7,123,173, 1, + 123,174, 1,123,170, 3,122,175, 0,123,174, 1,123,170, 3, + 124,162, 10,124,162, 10,124,158, 13,124,147, 26,120,122, 70, + 118,117, 85,109, 92,251, 30, 43,203, 30, 43,203, 99, 75,247, + 117,110,109,121,127, 58,122,132, 48,124,157, 15,123,170, 3, + 122,178, 0,119,185, 0,119,187, 0,119,186, 0,120,182, 0, + 122,178, 0,120,184, 0,118,188, 0,118,188, 0,119,186, 0, + 121,182, 0,123,174, 1,124,166, 7,124,158, 13,124,152, 20, + 124,154, 18,124,155, 16,124,154, 18,124,154, 18,124,157, 15, + 124,161, 11,124,166, 7,123,174, 1,120,182, 0,118,189, 0, + 115,194, 0,114,196, 0,114,197, 0,114,196, 0,116,192, 0, + 115,194, 0,116,193, 0,117,191, 0,115,194, 0,114,196, 0, + 114,197, 0,113,199, 0,114,197, 0,114,197, 0,114,197, 0, + 115,194, 0,118,189, 0,117,191, 0,117,191, 0,117,191, 0, + 118,189, 0,117,190, 0,118,188, 0,120,184, 0,121,181, 0, + 122,175, 0,124,165, 8,124,147, 26,115,107,129,118,117, 85, + 123,137, 41,124,149, 24,124,166, 7,122,176, 0,120,182, 0, + 120,184, 0,121,181, 0,121,180, 0,120,182, 0,120,182, 0, + 121,182, 0,121,180, 0,118,188, 0,114,197, 0,108,205, 0, + 102,213, 0, 96,219, 0, 92,223, 0, 89,225, 0, 90,225, 0, + 92,222, 0, 96,219, 0,100,215, 0,103,211, 0,106,208, 0, + 108,206, 0,106,207, 0,106,208, 0,106,207, 0,108,205, 0, + 112,199, 0,115,194, 0,116,192, 0,118,189, 0,121,181, 0, + 123,170, 3,124,165, 8,124,155, 16,124,143, 31,124,147, 26, + 124,165, 8,122,178, 0,119,186, 0,117,191, 0,116,193, 0, + 116,193, 0,117,191, 0,117,191, 0,116,193, 0,116,193, 0, + 117,192, 0,114,197, 0,111,201, 0,110,202, 0,110,202, 0, + 110,202, 0,110,202, 0,111,202, 0,111,201, 0,113,199, 0, + 114,197, 0,116,193, 0,117,190, 0,119,187, 0,119,187, 0, + 118,188, 0,117,190, 0,116,192, 0,115,194, 0,114,196, 0, + 111,202, 0,105,209, 0,100,214, 0, 97,218, 0, 95,219, 0, + 97,218, 0,101,214, 0,106,208, 0,111,201, 0,115,194, 0, + 118,188, 0,121,182, 0,123,173, 1,124,162, 10,124,149, 24, + 122,132, 48,114,104,197, 30, 55,222, 30, 37,192,113,100,242, + 123,139, 37,124,161, 11,123,172, 2,122,178, 0,120,183, 0, + 116,192, 0,112,200, 0,109,204, 0,109,204, 0,111,202, 0, + 115,195, 0,120,184, 0,120,183, 0,116,192, 0,112,200, 0, + 108,206, 0,105,209, 0,104,210, 0,104,210, 0,105,209, 0, + 101,213, 0,101,214, 0,101,214, 0,102,212, 0,103,211, 0, + 104,210, 0,105,209, 0,107,207, 0,109,204, 0,112,200, 0, + 110,202, 0,109,203, 0,109,203, 0,111,202, 0,114,197, 0, + 117,190, 0,121,181, 0,121,181, 0,117,191, 0,113,199, 0, + 110,202, 0,109,203, 0,110,202, 0,112,199, 0,114,196, 0, + 113,198, 0,113,199, 0,113,198, 0,114,197, 0,114,197, 0, + 114,196, 0,116,193, 0,117,190, 0,116,192, 0,115,195, 0, + 114,196, 0,113,198, 0,114,196, 0,117,191, 0,120,184, 0, + 123,174, 1,122,177, 0,120,183, 0,118,188, 0,118,189, 0, + 119,187, 0,121,182, 0,122,177, 0,122,178, 0,121,180, 0, + 120,184, 0,118,188, 0,117,191, 0,116,193, 0,115,194, 0, + 116,192, 0,118,188, 0,120,184, 0,121,180, 0,123,172, 2, + 124,158, 13,123,139, 37,123,137, 41,122,130, 53,121,125, 63, + 121,127, 58,122,132, 48,124,145, 29,124,160, 12,123,171, 3, + 122,178, 0,121,179, 0,122,175, 0,123,171, 3,123,169, 4, + 124,162, 10,124,157, 15,124,152, 20,124,143, 31,121,125, 63, + 109, 92,251,109, 92,251,105, 84,252, 30, 55,222, 69, 60,230, + 111, 96,248,121,125, 63,123,139, 37,123,141, 34,124,155, 16, + 123,168, 5,123,174, 1,120,182, 0,119,185, 0,120,184, 0, + 121,181, 0,122,177, 0,121,182, 0,120,184, 0,120,182, 0, + 122,178, 0,123,171, 3,124,167, 6,124,164, 9,124,154, 18, + 123,141, 34,123,139, 37,124,143, 31,124,145, 29,124,143, 31, + 124,143, 31,124,152, 20,124,160, 12,124,165, 8,123,169, 4, + 121,180, 0,119,187, 0,117,192, 0,115,194, 0,116,193, 0, + 117,191, 0,118,188, 0,118,188, 0,119,186, 0,118,188, 0, + 117,192, 0,116,193, 0,115,194, 0,115,194, 0,115,194, 0, + 115,194, 0,117,191, 0,118,189, 0,117,191, 0,117,191, 0, + 117,190, 0,118,189, 0,119,187, 0,119,186, 0,120,183, 0, + 121,179, 0,123,172, 2,124,161, 11,123,139, 37,111, 96,248, + 115,107,129,122,130, 53,124,152, 20,124,167, 6,122,176, 0, + 121,182, 0,120,183, 0,121,179, 0,123,174, 1,123,172, 2, + 122,175, 0,122,176, 0,120,184, 0,115,194, 0,110,203, 0, + 104,210, 0, 98,217, 0, 92,223, 0, 88,226, 0, 86,228, 0, + 87,227, 0, 90,225, 0, 94,221, 0, 98,217, 0,101,214, 0, + 104,210, 0,107,206, 0,107,207, 0,106,207, 0,106,207, 0, + 108,205, 0,111,201, 0,117,192, 0,118,189, 0,119,185, 0, + 122,178, 0,124,165, 8,124,161, 11,124,152, 20,123,141, 34, + 124,154, 18,124,167, 6,122,177, 0,120,184, 0,118,189, 0, + 117,192, 0,116,192, 0,117,190, 0,119,186, 0,118,188, 0, + 118,188, 0,117,192, 0,113,198, 0,110,202, 0,109,204, 0, + 108,205, 0,109,204, 0,109,203, 0,111,202, 0,112,199, 0, + 114,197, 0,116,193, 0,117,191, 0,118,189, 0,118,188, 0, + 119,186, 0,120,184, 0,121,181, 0,121,182, 0,120,183, 0, + 117,190, 0,114,197, 0,109,204, 0,104,210, 0,101,214, 0, + 100,215, 0,101,214, 0,105,209, 0,109,204, 0,114,197, 0, + 117,190, 0,120,183, 0,122,176, 0,123,168, 5,124,158, 13, + 124,155, 16,124,149, 24,121,125, 63,102, 80,250, 69, 60,230, + 107, 89,252,122,130, 53,124,154, 18,124,166, 7,123,171, 3, + 121,181, 0,117,191, 0,114,197, 0,111,201, 0,112,200, 0, + 114,196, 0,118,188, 0,122,175, 0,121,180, 0,118,189, 0, + 114,197, 0,110,202, 0,108,206, 0,107,207, 0,107,206, 0, + 107,207, 0,104,210, 0,103,211, 0,104,210, 0,105,209, 0, + 106,208, 0,106,208, 0,106,207, 0,108,206, 0,110,203, 0, + 112,200, 0,110,202, 0,109,204, 0,109,204, 0,110,202, 0, + 113,198, 0,117,192, 0,120,184, 0,119,185, 0,119,186, 0, + 116,192, 0,114,196, 0,114,197, 0,115,195, 0,116,192, 0, + 117,191, 0,115,194, 0,115,195, 0,115,194, 0,116,193, 0, + 115,194, 0,116,193, 0,117,191, 0,116,192, 0,115,194, 0, + 114,196, 0,114,196, 0,116,193, 0,118,189, 0,120,184, 0, + 122,178, 0,123,169, 4,124,164, 9,123,174, 1,121,181, 0, + 120,184, 0,120,184, 0,121,182, 0,120,183, 0,120,184, 0, + 119,186, 0,118,188, 0,117,191, 0,116,193, 0,115,194, 0, + 115,194, 0,117,192, 0,118,188, 0,121,181, 0,122,176, 0, + 124,167, 6,124,150, 22,123,137, 41,122,132, 48,121,125, 63, + 120,122, 70,121,125, 63,124,145, 29,124,154, 18,124,166, 7, + 122,178, 0,120,183, 0,120,184, 0,121,181, 0,123,174, 1, + 124,167, 6,124,161, 11,124,152, 20,123,139, 37,123,139, 37, + 122,130, 53,122,132, 48,123,137, 41,122,132, 48,118,114, 96, + 115,107,129,117,110,109,121,127, 58,123,141, 34,124,143, 31, + 124,152, 20,124,162, 10,124,167, 6,122,176, 0,121,179, 0, + 121,179, 0,122,177, 0,122,176, 0,121,180, 0,121,181, 0, + 122,177, 0,123,169, 4,124,166, 7,124,165, 8,124,158, 13, + 124,145, 29,123,141, 34,123,137, 41,122,130, 53,122,132, 48, + 122,132, 48,121,125, 63,122,130, 53,123,141, 34,124,150, 22, + 124,154, 18,124,167, 6,122,178, 0,119,185, 0,118,189, 0, + 117,190, 0,118,189, 0,119,186, 0,121,181, 0,121,180, 0, + 121,182, 0,119,187, 0,117,191, 0,116,192, 0,116,193, 0, + 116,192, 0,117,191, 0,119,187, 0,119,187, 0,118,188, 0, + 118,189, 0,118,188, 0,118,188, 0,119,186, 0,120,184, 0, + 121,182, 0,122,178, 0,123,170, 3,124,157, 15,122,135, 44, + 114,104,197,119,119, 77,123,141, 34,124,157, 15,123,169, 4, + 122,177, 0,121,181, 0,121,182, 0,122,176, 0,123,171, 3, + 124,165, 8,124,162, 10,123,171, 3,118,188, 0,113,199, 0, + 106,207, 0,100,214, 0, 94,221, 0, 89,226, 0, 85,229, 0, + 84,229, 0, 85,229, 0, 88,226, 0, 93,222, 0, 97,218, 0, + 100,214, 0,104,210, 0,107,206, 0,108,205, 0,107,206, 0, + 107,207, 0,108,206, 0,110,202, 0,115,194, 0,119,185, 0, + 121,182, 0,122,175, 0,124,161, 11,124,152, 20,124,145, 29, + 123,139, 37,124,154, 18,124,165, 8,123,173, 1,121,180, 0, + 119,185, 0,118,188, 0,117,190, 0,118,189, 0,120,184, 0, + 121,181, 0,121,182, 0,118,189, 0,114,197, 0,110,202, 0, + 108,205, 0,108,206, 0,109,204, 0,110,202, 0,112,200, 0, + 114,196, 0,117,192, 0,117,191, 0,117,192, 0,117,191, 0, + 117,190, 0,119,187, 0,120,182, 0,123,174, 1,124,165, 8, + 123,173, 1,120,184, 0,117,192, 0,113,199, 0,109,204, 0, + 106,207, 0,105,209, 0,106,207, 0,109,204, 0,113,198, 0, + 117,191, 0,120,183, 0,122,175, 0,123,168, 5,124,160, 12, + 124,161, 11,124,162, 10,124,157, 15,123,137, 41,111, 96,248, + 99, 75,247,102, 80,250,118,117, 85,124,143, 31,124,157, 15, + 124,166, 7,122,178, 0,118,188, 0,115,194, 0,114,197, 0, + 114,196, 0,117,191, 0,121,180, 0,124,164, 9,122,175, 0, + 119,186, 0,116,193, 0,113,199, 0,111,202, 0,110,202, 0, + 110,202, 0,111,202, 0,108,205, 0,108,206, 0,108,206, 0, + 108,205, 0,108,205, 0,109,204, 0,109,203, 0,110,202, 0, + 112,200, 0,112,199, 0,111,202, 0,109,203, 0,109,203, 0, + 110,202, 0,113,198, 0,117,192, 0,119,186, 0,119,187, 0, + 119,187, 0,120,184, 0,119,186, 0,119,187, 0,119,185, 0, + 121,182, 0,119,186, 0,118,189, 0,117,191, 0,117,191, 0, + 117,191, 0,117,191, 0,117,191, 0,116,192, 0,115,194, 0, + 114,196, 0,114,197, 0,114,196, 0,116,193, 0,119,186, 0, + 122,176, 0,123,169, 4,124,164, 9,124,155, 16,124,160, 12, + 123,170, 3,122,176, 0,121,179, 0,121,182, 0,119,185, 0, + 119,187, 0,118,188, 0,117,190, 0,117,192, 0,116,193, 0, + 116,193, 0,117,192, 0,118,188, 0,120,184, 0,122,177, 0, + 123,169, 4,124,158, 13,123,139, 37,122,132, 48,122,130, 53, + 120,122, 70,118,117, 85,123,137, 41,124,154, 18,124,161, 11, + 123,172, 2,121,182, 0,119,187, 0,118,188, 0,119,185, 0, + 122,178, 0,123,171, 3,124,161, 11,124,160, 12,124,160, 12, + 124,157, 15,124,157, 15,124,162, 10,124,164, 9,124,160, 12, + 124,150, 22,123,137, 41,122,135, 44,122,130, 53,123,137, 41, + 123,141, 34,124,147, 26,124,152, 20,124,152, 20,124,165, 8, + 123,169, 4,123,171, 3,123,170, 3,122,177, 0,121,179, 0, + 122,178, 0,123,170, 3,124,164, 9,124,162, 10,124,158, 13, + 124,149, 24,122,135, 44,122,132, 48,121,127, 58,118,117, 85, + 119,119, 77,118,114, 96,115,107,129,109, 92,251,114,104,197, + 120,122, 70,122,132, 48,124,147, 26,124,164, 9,123,174, 1, + 121,181, 0,120,184, 0,119,185, 0,120,183, 0,122,178, 0, + 123,171, 3,123,173, 1,120,182, 0,118,188, 0,117,191, 0, + 117,191, 0,118,189, 0,119,186, 0,121,181, 0,121,180, 0, + 121,182, 0,120,183, 0,120,183, 0,120,184, 0,120,183, 0, + 121,182, 0,122,178, 0,123,173, 1,124,164, 9,124,149, 24, + 122,132, 48,122,130, 53,124,143, 31,124,157, 15,124,166, 7, + 123,170, 3,122,175, 0,122,178, 0,122,178, 0,123,169, 4, + 124,164, 9,124,157, 15,124,150, 22,123,174, 1,117,191, 0, + 111,202, 0,104,210, 0, 98,217, 0, 92,222, 0, 87,227, 0, + 84,229, 0, 83,230, 0, 85,229, 0, 89,226, 0, 93,222, 0, + 97,218, 0,101,214, 0,103,211, 0,106,207, 0,109,204, 0, + 109,204, 0,108,205, 0,108,205, 0,110,203, 0,114,197, 0, + 119,187, 0,121,179, 0,123,172, 2,124,160, 12,123,137, 41, + 122,130, 53,122,132, 48,124,147, 26,124,160, 12,123,173, 1, + 121,180, 0,120,182, 0,120,183, 0,119,186, 0,119,186, 0, + 120,184, 0,121,179, 0,123,172, 2,120,184, 0,116,192, 0, + 113,198, 0,110,202, 0,109,203, 0,110,202, 0,112,199, 0, + 115,194, 0,118,189, 0,118,189, 0,117,190, 0,117,191, 0, + 117,191, 0,117,190, 0,119,186, 0,121,180, 0,123,169, 4, + 124,154, 18,124,158, 13,123,174, 1,120,183, 0,117,190, 0, + 115,195, 0,113,199, 0,112,200, 0,112,199, 0,114,196, 0, + 117,190, 0,120,182, 0,123,172, 2,124,164, 9,124,155, 16, + 124,157, 15,124,162, 10,124,164, 9,124,158, 13,123,141, 34, + 114,104,197,102, 80,250,109, 92,251,113,100,242,122,132, 48, + 124,149, 24,124,162, 10,122,175, 0,120,184, 0,117,191, 0, + 116,193, 0,117,191, 0,120,184, 0,123,171, 3,124,147, 26, + 124,167, 6,121,180, 0,118,189, 0,115,194, 0,114,197, 0, + 113,198, 0,113,198, 0,114,197, 0,113,198, 0,112,199, 0, + 112,200, 0,112,200, 0,112,200, 0,112,199, 0,113,198, 0, + 114,196, 0,114,197, 0,113,198, 0,111,201, 0,110,202, 0, + 110,202, 0,111,201, 0,114,197, 0,117,190, 0,118,188, 0, + 118,188, 0,119,186, 0,120,182, 0,123,173, 1,123,171, 3, + 123,168, 5,123,171, 3,122,178, 0,121,182, 0,120,183, 0, + 120,184, 0,119,186, 0,119,187, 0,118,189, 0,117,192, 0, + 115,194, 0,114,196, 0,114,197, 0,115,195, 0,117,191, 0, + 120,184, 0,123,173, 1,124,158, 13,124,157, 15,124,152, 20, + 123,139, 37,124,154, 18,124,165, 8,123,170, 3,122,178, 0, + 120,184, 0,119,186, 0,119,187, 0,118,188, 0,118,189, 0, + 117,190, 0,118,189, 0,119,186, 0,120,182, 0,122,175, 0, + 124,167, 6,124,158, 13,124,143, 31,121,125, 63,122,130, 53, + 122,130, 53,120,122, 70,117,110,109,124,147, 26,124,162, 10, + 123,168, 5,122,177, 0,120,184, 0,118,189, 0,117,191, 0, + 118,188, 0,121,182, 0,123,173, 1,123,172, 2,123,173, 1, + 123,173, 1,123,169, 4,123,174, 1,122,178, 0,122,178, 0, + 122,176, 0,123,169, 4,124,157, 15,124,149, 24,124,143, 31, + 122,135, 44,122,135, 44,123,137, 41,122,135, 44,122,132, 48, + 124,147, 26,124,155, 16,124,166, 7,123,173, 1,122,178, 0, + 122,178, 0,123,173, 1,124,164, 9,124,160, 12,124,157, 15, + 124,149, 24,122,132, 48,119,119, 77,118,114, 96,115,107,129, + 113,100,242,113,100,242,109, 92,251, 99, 75,247, 30, 49,213, + 30, 31,180, 94, 70,242,111, 96,248,118,117, 85,122,135, 44, + 124,154, 18,124,166, 7,123,174, 1,122,178, 0,122,177, 0, + 123,171, 3,124,160, 12,124,164, 9,122,177, 0,120,184, 0, + 119,187, 0,119,187, 0,120,184, 0,122,178, 0,123,170, 3, + 124,165, 8,124,167, 6,123,170, 3,123,173, 1,122,175, 0, + 122,176, 0,123,174, 1,123,170, 3,124,167, 6,124,164, 9, + 124,157, 15,124,143, 31,124,152, 20,124,162, 10,123,170, 3, + 122,175, 0,122,177, 0,122,176, 0,123,172, 2,123,172, 2, + 124,155, 16,124,149, 24,123,141, 34,124,160, 12,122,177, 0, + 117,192, 0,110,202, 0,104,210, 0, 98,217, 0, 93,222, 0, + 88,226, 0, 85,229, 0, 85,229, 0, 86,228, 0, 90,225, 0, + 94,220, 0, 98,216, 0,101,214, 0,101,213, 0,104,210, 0, + 105,209, 0,107,207, 0,109,203, 0,109,204, 0,109,204, 0, + 112,200, 0,117,191, 0,122,178, 0,123,171, 3,124,158, 13, + 122,132, 48,115,107,129,118,114, 96,122,130, 53,124,161, 11, + 122,177, 0,120,184, 0,119,185, 0,120,184, 0,121,180, 0, + 120,183, 0,120,183, 0,121,182, 0,122,178, 0,121,182, 0, + 120,184, 0,117,191, 0,114,196, 0,113,198, 0,114,196, 0, + 116,192, 0,119,186, 0,119,185, 0,119,186, 0,119,187, 0, + 118,188, 0,118,189, 0,118,188, 0,120,184, 0,122,177, 0, + 124,162, 10,124,149, 24,124,147, 26,124,157, 15,123,169, 4, + 122,177, 0,120,183, 0,119,187, 0,118,189, 0,118,189, 0, + 119,186, 0,121,180, 0,123,169, 4,124,157, 15,124,143, 31, + 124,143, 31,124,154, 18,124,160, 12,124,161, 11,124,157, 15, + 123,137, 41,111, 96,248,105, 84,252,113,100,242,118,117, 85, + 121,127, 58,123,141, 34,124,155, 16,123,169, 4,121,180, 0, + 119,186, 0,118,189, 0,119,186, 0,122,178, 0,124,161, 11, + 121,125, 63,124,154, 18,123,171, 3,121,182, 0,118,188, 0, + 117,191, 0,116,192, 0,116,192, 0,117,192, 0,116,193, 0, + 115,194, 0,115,195, 0,115,195, 0,115,194, 0,116,193, 0, + 117,192, 0,116,193, 0,115,194, 0,114,196, 0,113,198, 0, + 112,200, 0,112,200, 0,113,198, 0,115,194, 0,118,188, 0, + 118,188, 0,118,188, 0,119,185, 0,121,179, 0,123,168, 5, + 124,149, 24,123,141, 34,124,158, 13,124,166, 7,123,169, 4, + 123,171, 3,123,174, 1,122,178, 0,121,181, 0,119,185, 0, + 118,189, 0,116,192, 0,115,194, 0,115,194, 0,117,192, 0, + 118,188, 0,121,180, 0,123,169, 4,124,154, 18,124,145, 29, + 124,147, 26,123,141, 34,122,130, 53,124,145, 29,124,155, 16, + 123,170, 3,122,178, 0,121,180, 0,121,181, 0,120,183, 0, + 120,184, 0,120,184, 0,121,182, 0,122,178, 0,123,170, 3, + 124,161, 11,124,150, 22,123,141, 34,119,119, 77,118,114, 96, + 120,122, 70,121,127, 58,121,125, 63,123,137, 41,124,157, 15, + 123,169, 4,123,174, 1,121,179, 0,119,185, 0,118,189, 0, + 117,191, 0,118,188, 0,121,182, 0,121,180, 0,120,182, 0, + 120,184, 0,120,182, 0,121,181, 0,120,184, 0,119,186, 0, + 119,186, 0,119,185, 0,121,181, 0,123,171, 3,124,157, 15, + 124,149, 24,123,137, 41,121,127, 58,122,130, 53,121,127, 58, + 123,137, 41,124,154, 18,124,165, 8,123,171, 3,122,175, 0, + 122,177, 0,122,175, 0,123,168, 5,124,155, 16,124,155, 16, + 124,149, 24,122,135, 44,114,104,197,107, 89,252,102, 80,250, + 102, 80,250,111, 96,248,113,100,242,109, 92,251,107, 89,252, + 102, 80,250, 30, 49,213, 30, 26,168, 69, 60,230,102, 80,250, + 115,107,129,119,119, 77,123,137, 41,124,154, 18,124,164, 9, + 124,166, 7,124,160, 12,124,145, 29,124,152, 20,123,169, 4, + 122,178, 0,120,182, 0,121,181, 0,122,176, 0,124,166, 7, + 124,150, 22,122,130, 53,122,130, 53,123,141, 34,124,150, 22, + 124,157, 15,124,160, 12,124,166, 7,123,169, 4,123,168, 5, + 124,164, 9,124,157, 15,124,154, 18,124,162, 10,123,169, 4, + 122,175, 0,122,178, 0,122,178, 0,122,176, 0,123,168, 5, + 124,160, 12,121,127, 58,119,119, 77,124,143, 31,124,165, 8, + 122,178, 0,117,191, 0,111,201, 0,105,209, 0,100,215, 0, + 95,220, 0, 91,224, 0, 88,226, 0, 87,227, 0, 89,225, 0, + 92,222, 0, 97,218, 0,101,214, 0,100,214, 0,100,214, 0, + 101,213, 0,101,214, 0,102,212, 0,106,208, 0,109,204, 0, + 109,204, 0,111,201, 0,115,194, 0,120,183, 0,123,171, 3, + 124,160, 12,122,135, 44,102, 80,250,105, 84,252,121,125, 63, + 124,164, 9,121,179, 0,119,186, 0,118,188, 0,119,186, 0, + 121,180, 0,121,179, 0,120,182, 0,120,183, 0,120,182, 0, + 119,185, 0,120,184, 0,121,180, 0,119,186, 0,118,189, 0, + 119,186, 0,121,181, 0,121,179, 0,121,180, 0,121,181, 0, + 121,182, 0,120,183, 0,120,184, 0,120,184, 0,121,181, 0, + 123,171, 3,124,155, 16,124,143, 31,123,137, 41,121,125, 63, + 123,141, 34,124,152, 20,124,162, 10,123,169, 4,123,173, 1, + 123,174, 1,123,172, 2,124,166, 7,124,150, 22,123,139, 37, + 122,130, 53,122,130, 53,124,143, 31,124,152, 20,124,155, 16, + 124,150, 22,121,127, 58,111, 96,248,117,110,109,121,125, 63, + 122,135, 44,124,143, 31,124,149, 24,124,149, 24,124,164, 9, + 122,175, 0,120,182, 0,120,184, 0,121,182, 0,123,172, 2, + 124,150, 22,114,104,197,121,127, 58,124,155, 16,123,170, 3, + 122,178, 0,120,182, 0,120,184, 0,120,184, 0,119,185, 0, + 119,186, 0,118,188, 0,118,189, 0,118,189, 0,119,187, 0, + 119,185, 0,119,186, 0,118,188, 0,118,189, 0,117,192, 0, + 115,194, 0,114,196, 0,114,197, 0,115,195, 0,117,191, 0, + 119,186, 0,119,185, 0,119,185, 0,121,182, 0,123,174, 1, + 124,161, 11,123,137, 41,119,119, 77,122,132, 48,124,143, 31, + 124,147, 26,124,150, 22,124,162, 10,123,171, 3,122,175, 0, + 122,178, 0,120,184, 0,118,188, 0,117,190, 0,118,189, 0, + 119,187, 0,121,182, 0,123,173, 1,124,162, 10,124,147, 26, + 122,130, 53,123,139, 37,123,141, 34,122,132, 48,120,122, 70, + 122,135, 44,124,154, 18,124,165, 8,123,168, 5,123,169, 4, + 123,171, 3,123,172, 2,123,171, 3,123,168, 5,124,161, 11, + 124,150, 22,122,132, 48,121,127, 58,118,114, 96,114,104,197, + 113,100,242,118,117, 85,121,125, 63,124,145, 29,124,155, 16, + 124,166, 7,122,177, 0,121,182, 0,120,182, 0,119,185, 0, + 118,188, 0,118,189, 0,119,186, 0,121,182, 0,119,186, 0, + 118,189, 0,117,191, 0,117,190, 0,118,188, 0,117,190, 0, + 117,191, 0,117,191, 0,117,191, 0,119,187, 0,121,180, 0, + 124,166, 7,124,145, 29,121,127, 58,117,110,109,118,114, 96, + 119,119, 77,124,147, 26,124,162, 10,123,170, 3,123,173, 1, + 123,174, 1,123,174, 1,123,170, 3,124,160, 12,124,155, 16, + 124,152, 20,123,141, 34,118,117, 85, 87, 65,237, 30, 49,213, + 105, 84,252,118,117, 85,122,130, 53,122,130, 53,121,125, 63, + 121,127, 58,121,125, 63,117,110,109, 99, 75,247,105, 84,252, + 117,110,109,118,117, 85,117,110,109,114,104,197,118,114, 96, + 123,137, 41,124,145, 29,123,139, 37,122,135, 44,123,141, 34, + 124,161, 11,123,170, 3,122,175, 0,123,172, 2,124,164, 9, + 124,145, 29,120,122, 70,115,107,129, 87, 65,237, 69, 60,230, + 111, 96,248,121,127, 58,124,150, 22,124,161, 11,124,164, 9, + 124,162, 10,124,157, 15,124,150, 22,124,157, 15,124,164, 9, + 123,170, 3,122,175, 0,122,178, 0,122,177, 0,123,171, 3, + 124,161, 11,123,139, 37, 99, 75,247,113,100,242,124,143, 31, + 124,167, 6,121,181, 0,117,190, 0,113,199, 0,108,206, 0, + 103,211, 0, 99,216, 0, 94,220, 0, 92,223, 0, 91,223, 0, + 92,222, 0, 95,219, 0,100,215, 0,103,212, 0,101,214, 0, + 100,215, 0, 97,218, 0, 96,219, 0, 97,217, 0,101,214, 0, + 106,208, 0,108,205, 0,110,202, 0,114,197, 0,118,188, 0, + 122,175, 0,124,162, 10,123,139, 37,107, 89,252, 30, 37,192, + 120,122, 70,124,164, 9,121,181, 0,118,188, 0,118,189, 0, + 119,186, 0,121,181, 0,122,175, 0,121,181, 0,120,184, 0, + 119,185, 0,119,186, 0,119,186, 0,121,181, 0,123,172, 2, + 123,174, 1,123,171, 3,123,170, 3,123,172, 2,123,173, 1, + 123,174, 1,123,174, 1,122,176, 0,122,178, 0,121,179, 0, + 122,175, 0,124,165, 8,124,145, 29,122,135, 44,120,122, 70, + 113,100,242,105, 84,252,114,104,197,121,125, 63,123,141, 34, + 124,150, 22,124,155, 16,124,154, 18,124,147, 26,121,127, 58, + 122,130, 53,121,125, 63,121,127, 58,122,130, 53,123,141, 34, + 124,145, 29,123,139, 37,118,114, 96,118,114, 96,122,132, 48, + 124,143, 31,124,150, 22,124,158, 13,124,165, 8,124,165, 8, + 124,165, 8,123,172, 2,122,177, 0,121,180, 0,122,178, 0, + 124,167, 6,124,143, 31,109, 92,251,102, 80,250,121,125, 63, + 124,150, 22,124,162, 10,123,169, 4,123,171, 3,123,173, 1, + 123,173, 1,122,176, 0,121,179, 0,121,180, 0,121,180, 0, + 122,178, 0,122,176, 0,122,176, 0,121,179, 0,121,182, 0, + 119,185, 0,118,189, 0,117,191, 0,116,192, 0,117,192, 0, + 118,188, 0,120,183, 0,121,181, 0,121,181, 0,122,177, 0, + 123,169, 4,124,154, 18,121,127, 58,118,114, 96,107, 89,252, + 109, 92,251,113,100,242,122,130, 53,124,152, 20,124,165, 8, + 123,171, 3,123,172, 2,123,174, 1,121,181, 0,120,184, 0, + 120,183, 0,121,179, 0,123,172, 2,124,164, 9,124,150, 22, + 122,135, 44,118,117, 85,122,132, 48,123,141, 34,123,139, 37, + 122,130, 53,118,114, 96,120,122, 70,123,139, 37,124,143, 31, + 124,143, 31,124,147, 26,124,149, 24,124,149, 24,124,143, 31, + 122,132, 48,117,110,109, 99, 75,247,107, 89,252,111, 96,248, + 113,100,242,111, 96,248,117,110,109,124,143, 31,124,161, 11, + 124,167, 6,122,175, 0,120,184, 0,118,188, 0,118,189, 0, + 119,187, 0,119,186, 0,119,186, 0,120,183, 0,120,184, 0, + 118,189, 0,116,193, 0,114,196, 0,114,196, 0,115,195, 0, + 116,193, 0,116,193, 0,116,193, 0,116,192, 0,118,189, 0, + 120,183, 0,123,171, 3,124,147, 26,114,104,197, 94, 70,242, + 107, 89,252,121,127, 58,124,154, 18,124,166, 7,123,171, 3, + 123,172, 2,123,171, 3,123,169, 4,124,164, 9,124,157, 15, + 124,157, 15,124,150, 22,123,137, 41,119,119, 77,105, 84,252, + 69, 60,230,118,117, 85,123,141, 34,124,149, 24,124,149, 24, + 124,143, 31,124,145, 29,124,145, 29,123,137, 41,118,117, 85, + 120,122, 70,122,130, 53,123,139, 37,122,135, 44,118,117, 85, + 94, 70,242,105, 84,252,114,104,197,119,119, 77,122,135, 44, + 123,139, 37,124,150, 22,124,162, 10,124,166, 7,124,161, 11, + 124,147, 26,124,149, 24,124,149, 24,123,139, 37,118,114, 96, + 69, 60,230, 30, 43,203,114,104,197,122,135, 44,124,149, 24, + 124,152, 20,124,150, 22,124,143, 31,124,150, 22,124,155, 16, + 124,161, 11,123,168, 5,123,172, 2,123,173, 1,123,171, 3, + 124,164, 9,124,149, 24,118,117, 85, 30, 2,128,107, 89,252, + 123,137, 41,124,165, 8,121,181, 0,117,191, 0,113,199, 0, + 109,203, 0,107,206, 0,103,211, 0, 99,216, 0, 96,219, 0, + 95,220, 0, 95,219, 0, 98,217, 0,102,213, 0,105,209, 0, + 101,213, 0, 97,218, 0, 93,221, 0, 92,222, 0, 93,221, 0, + 97,218, 0,102,212, 0,108,206, 0,109,204, 0,113,199, 0, + 117,191, 0,121,180, 0,123,168, 5,124,147, 26,114,104,197, + 30, 2,128,118,114, 96,124,161, 11,121,179, 0,119,187, 0, + 118,189, 0,119,186, 0,121,180, 0,123,172, 2,121,179, 0, + 119,185, 0,118,188, 0,119,186, 0,120,183, 0,122,178, 0, + 124,167, 6,124,150, 22,124,160, 12,124,164, 9,124,166, 7, + 123,170, 3,122,176, 0,122,178, 0,122,178, 0,123,171, 3, + 123,172, 2,123,168, 5,124,157, 15,123,137, 41,121,125, 63, + 117,110,109, 94, 70,242, 30, 2,128, 87, 65,237,111, 96,248, + 114,104,197,119,119, 77,122,132, 48,123,137, 41,122,132, 48, + 118,114, 96,120,122, 70,118,117, 85,118,114, 96,118,114, 96, + 121,127, 58,122,132, 48,121,127, 58,111, 96,248,122,130, 53, + 124,147, 26,124,157, 15,124,161, 11,123,170, 3,122,177, 0, + 122,178, 0,123,173, 1,121,179, 0,120,184, 0,120,184, 0, + 121,180, 0,123,168, 5,124,143, 31,107, 89,252, 30, 2,128, + 94, 70,242,118,114, 96,122,135, 44,124,145, 29,124,149, 24, + 124,150, 22,124,152, 20,124,155, 16,124,162, 10,124,166, 7, + 124,167, 6,124,167, 6,124,167, 6,124,166, 7,123,168, 5, + 123,168, 5,123,173, 1,121,180, 0,119,185, 0,118,188, 0, + 118,188, 0,119,186, 0,121,182, 0,123,173, 1,123,174, 1, + 123,170, 3,124,162, 10,124,147, 26,120,122, 70,107, 89,252, + 30, 55,222, 30, 2,128, 69, 60,230,118,114, 96,124,143, 31, + 124,160, 12,124,167, 6,123,170, 3,123,169, 4,123,168, 5, + 123,173, 1,123,172, 2,123,170, 3,123,169, 4,124,166, 7, + 124,157, 15,123,139, 37,111, 96,248,121,127, 58,123,141, 34, + 124,145, 29,124,143, 31,122,132, 48,118,117, 85,111, 96,248, + 111, 96,248,109, 92,251,113,100,242,115,107,129,115,107,129, + 114,104,197,111, 96,248, 87, 65,237, 30, 2,128, 87, 65,237, + 109, 92,251,114,104,197,118,117, 85,122,135, 44,124,157, 15, + 123,169, 4,123,173, 1,120,184, 0,117,191, 0,115,194, 0, + 114,196, 0,115,194, 0,117,191, 0,119,186, 0,121,179, 0, + 119,186, 0,117,192, 0,114,197, 0,112,200, 0,111,201, 0, + 111,201, 0,113,198, 0,116,193, 0,116,193, 0,117,192, 0, + 118,189, 0,120,183, 0,123,170, 3,124,145, 29,107, 89,252, + 30, 2,128,102, 80,250,122,130, 53,124,154, 18,124,165, 8, + 123,168, 5,124,167, 6,124,164, 9,124,160, 12,124,161, 11, + 124,162, 10,124,164, 9,124,165, 8,124,160, 12,124,147, 26, + 119,119, 77, 99, 75,247,121,127, 58,124,149, 24,124,158, 13, + 124,160, 12,124,158, 13,124,154, 18,124,150, 22,124,145, 29, + 124,149, 24,124,154, 18,124,155, 16,124,150, 22,124,145, 29, + 121,127, 58,105, 84,252, 30, 2,128,102, 80,250,119,119, 77, + 123,137, 41,124,145, 29,124,147, 26,124,155, 16,124,158, 13, + 124,152, 20,124,160, 12,124,164, 9,124,165, 8,124,158, 13, + 124,147, 26,122,130, 53,114,104,197, 87, 65,237,117,110,109, + 122,130, 53,122,135, 44,123,141, 34,124,145, 29,124,149, 24, + 124,152, 20,124,157, 15,124,164, 9,124,167, 6,124,167, 6, + 124,164, 9,124,154, 18,122,132, 48,105, 84,252, 30, 55,222, + 115,107,129,124,145, 29,124,165, 8,121,181, 0,117,192, 0, + 112,199, 0,109,204, 0,107,207, 0,107,207, 0,102,212, 0, + 100,215, 0, 98,217, 0, 99,216, 0,100,215, 0,100,215, 0, + 101,214, 0,100,215, 0, 95,220, 0, 91,223, 0, 89,225, 0, + 90,225, 0, 93,222, 0, 98,217, 0,103,211, 0,108,205, 0, + 112,200, 0,115,194, 0,119,186, 0,122,177, 0,124,160, 12, + 121,125, 63, 30, 37,192,102, 80,250,124,147, 26,123,172, 2, + 120,182, 0,119,186, 0,120,184, 0,121,179, 0,123,172, 2, + 122,178, 0,120,184, 0,118,188, 0,118,188, 0,119,185, 0, + 122,178, 0,123,169, 4,124,160, 12,124,158, 13,124,162, 10, + 124,167, 6,123,173, 1,122,178, 0,121,179, 0,122,178, 0, + 123,171, 3,123,168, 5,124,166, 7,124,164, 9,124,155, 16, + 124,143, 31,121,127, 58,111, 96,248, 87, 65,237,107, 89,252, + 111, 96,248,107, 89,252,107, 89,252,117,110,109,120,122, 70, + 120,122, 70,115,107,129,117,110,109,115,107,129,111, 96,248, + 113,100,242,119,119, 77,121,125, 63,121,127, 58,121,127, 58, + 123,139, 37,124,155, 16,124,165, 8,123,172, 2,121,180, 0, + 120,184, 0,119,186, 0,120,182, 0,119,187, 0,117,191, 0, + 117,191, 0,118,189, 0,121,181, 0,124,166, 7,122,135, 44, + 102, 80,250, 94, 70,242,111, 96,248,114,104,197,111, 96,248, + 113,100,242,120,122, 70,123,141, 34,124,149, 24,124,147, 26, + 124,143, 31,124,143, 31,124,157, 15,123,168, 5,122,175, 0, + 122,178, 0,121,179, 0,122,177, 0,123,172, 2,122,177, 0, + 120,182, 0,119,185, 0,120,184, 0,121,181, 0,123,173, 1, + 124,166, 7,124,164, 9,124,157, 15,124,145, 29,121,125, 63, + 117,110,109,109, 92,251,102, 80,250,109, 92,251,120,122, 70, + 122,135, 44,124,150, 22,124,161, 11,124,166, 7,124,166, 7, + 124,166, 7,124,166, 7,123,168, 5,123,170, 3,123,170, 3, + 124,167, 6,124,161, 11,124,145, 29,122,130, 53,121,127, 58, + 124,143, 31,124,150, 22,124,152, 20,124,149, 24,123,139, 37, + 121,127, 58,118,114, 96,107, 89,252, 30, 43,203, 30, 31,180, + 94, 70,242,111, 96,248,113,100,242,111, 96,248, 99, 75,247, + 114,104,197,121,125, 63,123,139, 37,124,150, 22,124,160, 12, + 124,167, 6,122,176, 0,120,184, 0,116,192, 0,113,198, 0, + 111,201, 0,111,201, 0,112,200, 0,114,196, 0,117,192, 0, + 117,191, 0,115,194, 0,114,196, 0,111,201, 0,109,204, 0, + 107,207, 0,107,207, 0,108,205, 0,111,201, 0,116,193, 0, + 118,189, 0,119,186, 0,121,181, 0,123,168, 5,124,143, 31, + 114,104,197, 94, 70,242,113,100,242,121,127, 58,124,145, 29, + 124,157, 15,124,158, 13,124,157, 15,124,160, 12,124,167, 6, + 123,171, 3,122,176, 0,121,179, 0,122,178, 0,122,175, 0, + 124,167, 6,124,150, 22,121,125, 63,121,125, 63,124,150, 22, + 124,161, 11,124,166, 7,124,167, 6,124,166, 7,124,164, 9, + 124,164, 9,124,166, 7,123,169, 4,123,170, 3,124,167, 6, + 124,160, 12,123,141, 34,117,110,109, 87, 65,237,102, 80,250, + 119,119, 77,123,137, 41,124,147, 26,124,150, 22,124,152, 20, + 124,154, 18,124,158, 13,124,164, 9,123,168, 5,123,168, 5, + 123,170, 3,124,167, 6,124,158, 13,123,141, 34,120,122, 70, + 118,117, 85,122,132, 48,123,141, 34,124,147, 26,124,150, 22, + 124,161, 11,123,168, 5,123,170, 3,123,169, 4,124,166, 7, + 124,161, 11,124,155, 16,123,141, 34,119,119, 77,107, 89,252, + 107, 89,252,119,119, 77,124,149, 24,124,165, 8,120,182, 0, + 116,193, 0,112,200, 0,109,204, 0,108,206, 0,108,205, 0, + 105,209, 0,103,212, 0,102,213, 0,100,215, 0, 97,218, 0, + 96,219, 0, 97,218, 0, 98,217, 0, 93,221, 0, 89,225, 0, + 87,227, 0, 87,227, 0, 89,225, 0, 93,222, 0, 98,217, 0, + 103,211, 0,108,206, 0,112,200, 0,116,193, 0,120,184, 0, + 123,170, 3,124,145, 29,109, 92,251, 30, 15,143,119,119, 77, + 124,160, 12,123,174, 1,121,181, 0,121,181, 0,122,178, 0, + 123,172, 2,122,175, 0,120,183, 0,118,188, 0,118,189, 0, + 119,186, 0,121,181, 0,123,172, 2,124,164, 9,124,162, 10, + 124,166, 7,123,169, 4,123,174, 1,122,178, 0,122,178, 0, + 122,176, 0,123,169, 4,123,174, 1,122,175, 0,123,173, 1, + 124,166, 7,124,155, 16,123,141, 34,120,122, 70,115,107,129, + 118,114, 96,120,122, 70,119,119, 77,115,107,129,102, 80,250, + 113,100,242,115,107,129,114,104,197,114,104,197,113,100,242, + 118,114, 96,121,127, 58,123,139, 37,124,147, 26,124,152, 20, + 124,154, 18,124,157, 15,124,166, 7,123,174, 1,121,182, 0, + 119,187, 0,117,190, 0,117,191, 0,117,191, 0,115,195, 0, + 113,198, 0,113,199, 0,114,196, 0,117,190, 0,121,179, 0, + 124,161, 11,122,130, 53,118,114, 96,115,107,129,115,107,129, + 107, 89,252, 87, 65,237,105, 84,252,119,119, 77,122,132, 48, + 122,135, 44,123,137, 41,124,143, 31,124,157, 15,123,172, 2, + 121,181, 0,119,185, 0,119,186, 0,120,183, 0,122,177, 0, + 121,179, 0,120,182, 0,120,183, 0,120,183, 0,121,180, 0, + 123,173, 1,124,162, 10,124,160, 12,124,157, 15,124,154, 18, + 124,147, 26,123,137, 41,121,125, 63,118,117, 85,115,107,129, + 120,122, 70,123,137, 41,123,141, 34,124,152, 20,124,158, 13, + 124,160, 12,124,160, 12,124,160, 12,124,164, 9,124,166, 7, + 124,167, 6,124,166, 7,124,161, 11,124,154, 18,124,155, 16, + 124,154, 18,124,147, 26,124,155, 16,124,158, 13,124,158, 13, + 124,154, 18,124,147, 26,123,137, 41,119,119, 77,102, 80,250, + 30, 49,213,105, 84,252,118,117, 85,122,132, 48,122,135, 44, + 121,125, 63,124,143, 31,124,155, 16,124,164, 9,123,170, 3, + 122,175, 0,121,180, 0,119,186, 0,117,192, 0,113,198, 0, + 110,202, 0,108,205, 0,108,205, 0,109,203, 0,112,200, 0, + 113,198, 0,112,200, 0,111,202, 0,111,202, 0,107,206, 0, + 104,210, 0,102,212, 0,101,213, 0,103,212, 0,106,208, 0, + 111,201, 0,117,191, 0,120,184, 0,122,178, 0,123,169, 4, + 124,150, 22,123,141, 34,121,125, 63,121,125, 63,123,141, 34, + 124,152, 20,124,158, 13,124,160, 12,124,166, 7,123,174, 1, + 122,178, 0,121,182, 0,120,184, 0,119,186, 0,119,186, 0, + 120,184, 0,121,179, 0,123,170, 3,124,155, 16,123,141, 34, + 124,150, 22,124,165, 8,123,171, 3,123,173, 1,123,174, 1, + 123,173, 1,123,172, 2,123,174, 1,122,176, 0,122,177, 0, + 123,174, 1,123,168, 5,124,155, 16,122,132, 48,115,107,129, + 120,122, 70,122,130, 53,122,135, 44,123,141, 34,124,145, 29, + 124,147, 26,124,149, 24,124,152, 20,124,161, 11,123,170, 3, + 122,175, 0,122,177, 0,122,175, 0,123,170, 3,124,162, 10, + 124,154, 18,124,149, 24,124,149, 24,124,152, 20,124,160, 12, + 124,166, 7,123,172, 2,122,177, 0,122,178, 0,122,177, 0, + 123,174, 1,123,170, 3,124,162, 10,124,152, 20,122,132, 48, + 113,100,242,113,100,242,120,122, 70,124,147, 26,123,168, 5, + 120,184, 0,115,194, 0,112,200, 0,110,202, 0,109,204, 0, + 110,203, 0,107,206, 0,106,208, 0,103,211, 0, 98,216, 0, + 95,220, 0, 92,222, 0, 92,222, 0, 93,221, 0, 92,222, 0, + 89,225, 0, 86,228, 0, 85,228, 0, 87,227, 0, 89,225, 0, + 94,221, 0, 99,216, 0,103,211, 0,109,204, 0,113,198, 0, + 118,189, 0,122,178, 0,124,160, 12,121,127, 58, 30, 49,213, + 87, 65,237,122,135, 44,124,161, 11,123,172, 2,122,176, 0, + 122,175, 0,123,171, 3,123,172, 2,121,182, 0,119,187, 0, + 118,189, 0,119,187, 0,120,182, 0,123,174, 1,124,166, 7, + 123,169, 4,123,171, 3,123,171, 3,123,172, 2,122,176, 0, + 122,176, 0,123,174, 1,122,176, 0,121,181, 0,121,182, 0, + 121,179, 0,123,173, 1,124,164, 9,124,152, 20,123,137, 41, + 121,125, 63,122,130, 53,123,141, 34,123,141, 34,122,135, 44, + 119,119, 77,109, 92,251,109, 92,251,111, 96,248,113,100,242, + 118,117, 85,122,132, 48,124,147, 26,124,157, 15,124,164, 9, + 123,168, 5,123,170, 3,123,173, 1,122,178, 0,120,184, 0, + 118,189, 0,116,192, 0,115,194, 0,114,196, 0,113,199, 0, + 111,202, 0,109,204, 0,108,205, 0,110,202, 0,114,197, 0, + 118,188, 0,122,176, 0,124,158, 13,124,150, 22,124,147, 26, + 122,135, 44,117,110,109,102, 80,250,109, 92,251,114,104,197, + 121,127, 58,124,143, 31,124,149, 24,124,152, 20,124,157, 15, + 123,174, 1,120,183, 0,118,188, 0,118,189, 0,119,185, 0, + 122,178, 0,121,182, 0,119,186, 0,119,187, 0,119,185, 0, + 121,180, 0,123,173, 1,124,162, 10,124,164, 9,124,165, 8, + 124,164, 9,124,160, 12,124,150, 22,123,139, 37,121,125, 63, + 118,114, 96,117,110,109,121,127, 58,122,135, 44,123,137, 41, + 124,147, 26,124,150, 22,124,149, 24,124,149, 24,124,152, 20, + 124,157, 15,124,160, 12,124,160, 12,124,164, 9,123,169, 4, + 123,171, 3,123,169, 4,124,165, 8,124,160, 12,124,164, 9, + 124,164, 9,124,161, 11,124,157, 15,124,150, 22,123,137, 41, + 115,107,129,115,107,129,115,107,129,123,137, 41,124,152, 20, + 124,157, 15,124,154, 18,124,165, 8,123,172, 2,122,178, 0, + 121,182, 0,119,185, 0,118,188, 0,116,192, 0,114,197, 0, + 110,202, 0,107,206, 0,106,208, 0,106,208, 0,108,206, 0, + 109,204, 0,108,205, 0,107,206, 0,107,207, 0,107,207, 0, + 102,212, 0, 99,215, 0, 97,218, 0, 97,218, 0, 98,217, 0, + 101,214, 0,106,208, 0,113,199, 0,119,186, 0,122,178, 0, + 123,171, 3,124,162, 10,124,162, 10,124,155, 16,124,149, 24, + 124,149, 24,124,155, 16,124,162, 10,123,170, 3,122,178, 0, + 120,182, 0,120,184, 0,119,186, 0,118,188, 0,117,190, 0, + 117,191, 0,118,189, 0,119,186, 0,121,181, 0,123,171, 3, + 124,161, 11,124,162, 10,123,169, 4,122,176, 0,121,179, 0, + 121,179, 0,121,179, 0,122,178, 0,122,178, 0,121,180, 0, + 121,179, 0,122,178, 0,123,172, 2,124,162, 10,124,145, 29, + 123,139, 37,124,147, 26,124,152, 20,124,154, 18,124,152, 20, + 124,150, 22,124,152, 20,124,158, 13,124,160, 12,124,167, 6, + 123,173, 1,122,178, 0,121,179, 0,121,179, 0,122,177, 0, + 123,173, 1,123,170, 3,123,168, 5,123,169, 4,123,170, 3, + 123,173, 1,122,177, 0,121,179, 0,121,182, 0,120,182, 0, + 120,182, 0,121,180, 0,122,177, 0,123,170, 3,124,160, 12, + 123,139, 37,114,104,197,113,100,242,119,119, 77,124,149, 24, + 122,175, 0,118,188, 0,114,196, 0,112,200, 0,111,201, 0, + 111,202, 0,110,202, 0,109,204, 0,108,205, 0,103,212, 0, + 97,217, 0, 93,221, 0, 91,224, 0, 89,225, 0, 89,225, 0, + 90,224, 0, 89,225, 0, 87,227, 0, 86,228, 0, 86,228, 0, + 87,227, 0, 91,223, 0, 96,219, 0,101,214, 0,107,207, 0, + 112,200, 0,117,192, 0,121,181, 0,124,167, 6,124,147, 26, + 114,104,197, 30, 31,180,109, 92,251,123,139, 37,124,161, 11, + 123,169, 4,123,171, 3,123,169, 4,123,169, 4,121,180, 0, + 119,186, 0,118,189, 0,118,188, 0,120,183, 0,122,176, 0, + 123,170, 3,123,174, 1,122,176, 0,122,175, 0,123,174, 1, + 123,172, 2,123,172, 2,122,177, 0,120,182, 0,119,186, 0, + 119,186, 0,120,182, 0,122,177, 0,123,168, 5,124,158, 13, + 124,143, 31,122,135, 44,123,137, 41,124,152, 20,124,155, 16, + 124,154, 18,124,143, 31,120,122, 70,109, 92,251,109, 92,251, + 117,110,109,122,130, 53,124,147, 26,124,160, 12,123,168, 5, + 123,173, 1,122,177, 0,121,179, 0,120,183, 0,119,187, 0, + 117,191, 0,115,194, 0,114,197, 0,113,198, 0,110,202, 0, + 108,205, 0,106,207, 0,105,209, 0,105,209, 0,106,207, 0, + 110,203, 0,115,195, 0,119,185, 0,123,174, 1,123,172, 2, + 123,172, 2,123,168, 5,124,157, 15,122,135, 44,123,137, 41, + 124,145, 29,124,147, 26,124,149, 24,124,155, 16,124,155, 16, + 124,155, 16,123,173, 1,120,183, 0,118,188, 0,118,188, 0, + 120,184, 0,122,178, 0,120,184, 0,118,188, 0,118,189, 0, + 119,186, 0,121,182, 0,123,174, 1,124,164, 9,123,168, 5, + 123,171, 3,123,170, 3,124,166, 7,124,157, 15,124,143, 31, + 121,125, 63,117,110,109,109, 92,251,115,107,129,119,119, 77, + 121,125, 63,122,130, 53,122,135, 44,122,132, 48,122,130, 53, + 122,135, 44,123,141, 34,124,149, 24,124,164, 9,123,172, 2, + 122,178, 0,121,179, 0,122,178, 0,123,174, 1,123,168, 5, + 124,167, 6,124,167, 6,124,165, 8,124,161, 11,124,155, 16, + 124,143, 31,121,127, 58,122,132, 48,123,137, 41,124,149, 24, + 124,164, 9,123,169, 4,123,169, 4,122,178, 0,120,182, 0, + 119,186, 0,118,189, 0,117,191, 0,116,193, 0,114,196, 0, + 112,200, 0,108,205, 0,106,208, 0,105,209, 0,105,209, 0, + 105,209, 0,104,210, 0,104,210, 0,103,211, 0,103,211, 0, + 102,213, 0, 98,217, 0, 94,220, 0, 93,222, 0, 93,222, 0, + 94,220, 0, 97,217, 0,102,212, 0,109,204, 0,116,193, 0, + 121,181, 0,122,176, 0,123,173, 1,122,175, 0,123,171, 3, + 123,168, 5,123,168, 5,123,172, 2,122,176, 0,121,181, 0, + 120,184, 0,119,186, 0,119,187, 0,118,188, 0,118,189, 0, + 117,191, 0,116,192, 0,116,192, 0,117,190, 0,119,186, 0, + 121,180, 0,123,174, 1,123,174, 1,122,175, 0,121,181, 0, + 120,184, 0,120,184, 0,120,184, 0,121,182, 0,121,182, 0, + 121,182, 0,121,181, 0,122,178, 0,123,174, 1,124,166, 7, + 124,154, 18,124,157, 15,124,162, 10,124,165, 8,124,165, 8, + 124,164, 9,124,160, 12,124,164, 9,123,170, 3,123,171, 3, + 123,169, 4,123,173, 1,122,177, 0,121,179, 0,121,180, 0, + 121,179, 0,121,179, 0,121,179, 0,121,180, 0,121,180, 0, + 121,181, 0,120,182, 0,120,183, 0,120,184, 0,120,184, 0, + 119,185, 0,119,185, 0,120,184, 0,121,181, 0,122,175, 0, + 124,164, 9,123,141, 34,115,107,129,107, 89,252,118,117, 85, + 124,162, 10,121,182, 0,117,191, 0,114,197, 0,112,200, 0, + 112,200, 0,112,199, 0,110,202, 0,110,203, 0,109,204, 0, + 103,212, 0, 98,217, 0, 93,221, 0, 90,225, 0, 87,227, 0, + 86,228, 0, 86,228, 0, 87,227, 0, 89,225, 0, 88,226, 0, + 87,227, 0, 88,226, 0, 91,223, 0, 95,219, 0,101,214, 0, + 106,207, 0,112,200, 0,117,192, 0,121,182, 0,123,170, 3, + 124,155, 16,122,130, 53, 94, 70,242, 87, 65,237,115,107,129, + 124,143, 31,124,160, 12,124,165, 8,124,166, 7,124,167, 6, + 121,179, 0,119,186, 0,118,189, 0,118,188, 0,120,184, 0, + 122,176, 0,122,176, 0,122,178, 0,122,178, 0,122,178, 0, + 122,176, 0,123,173, 1,122,176, 0,121,181, 0,119,186, 0, + 118,188, 0,118,188, 0,120,184, 0,122,178, 0,123,171, 3, + 124,165, 8,124,150, 22,123,137, 41,123,141, 34,124,158, 13, + 124,165, 8,124,165, 8,124,158, 13,124,143, 31,118,117, 85, + 107, 89,252,118,117, 85,123,141, 34,124,157, 15,123,168, 5, + 123,174, 1,122,178, 0,121,182, 0,120,184, 0,118,188, 0, + 116,192, 0,114,196, 0,113,198, 0,112,200, 0,110,203, 0, + 107,206, 0,105,209, 0,103,211, 0,102,213, 0,101,213, 0, + 103,211, 0,107,207, 0,111,201, 0,116,192, 0,120,184, 0, + 119,186, 0,119,187, 0,119,186, 0,121,181, 0,123,171, 3, + 124,158, 13,124,165, 8,124,166, 7,124,161, 11,124,155, 16, + 124,157, 15,124,155, 16,123,171, 3,121,181, 0,119,185, 0, + 120,184, 0,121,179, 0,121,181, 0,119,187, 0,117,190, 0, + 117,190, 0,119,186, 0,121,181, 0,123,172, 2,124,166, 7, + 123,172, 2,122,175, 0,123,174, 1,123,169, 4,124,160, 12, + 123,141, 34,118,117, 85,111, 96,248, 94, 70,242, 94, 70,242, + 109, 92,251,115,107,129,118,114, 96,118,117, 85,117,110,109, + 117,110,109,118,114, 96,122,135, 44,124,154, 18,124,167, 6, + 122,177, 0,121,182, 0,120,182, 0,121,181, 0,122,178, 0, + 122,175, 0,123,169, 4,124,167, 6,124,165, 8,124,160, 12, + 124,154, 18,124,143, 31,122,135, 44,124,143, 31,124,149, 24, + 124,158, 13,123,171, 3,122,177, 0,122,178, 0,119,185, 0, + 118,189, 0,117,192, 0,116,193, 0,115,194, 0,114,196, 0, + 113,198, 0,111,202, 0,108,205, 0,105,209, 0,104,210, 0, + 102,212, 0,100,214, 0,100,215, 0,100,215, 0,100,215, 0, + 100,214, 0, 96,219, 0, 93,222, 0, 91,224, 0, 90,224, 0, + 91,223, 0, 93,222, 0, 96,219, 0,100,214, 0,106,208, 0, + 113,199, 0,118,188, 0,121,180, 0,121,180, 0,121,182, 0, + 121,180, 0,122,178, 0,121,179, 0,121,182, 0,120,184, 0, + 119,187, 0,118,188, 0,118,189, 0,118,188, 0,118,188, 0, + 118,189, 0,117,191, 0,117,192, 0,116,192, 0,117,192, 0, + 118,189, 0,120,184, 0,121,181, 0,121,182, 0,120,182, 0, + 119,187, 0,118,189, 0,118,189, 0,118,188, 0,118,188, 0, + 119,187, 0,120,183, 0,121,182, 0,121,180, 0,122,176, 0, + 123,170, 3,124,164, 9,124,167, 6,123,170, 3,123,172, 2, + 123,171, 3,123,169, 4,124,166, 7,123,170, 3,122,177, 0, + 122,178, 0,122,178, 0,122,178, 0,122,178, 0,122,178, 0, + 122,178, 0,121,180, 0,121,182, 0,120,184, 0,119,186, 0, + 119,187, 0,118,188, 0,118,188, 0,119,187, 0,119,186, 0, + 119,186, 0,119,186, 0,119,186, 0,119,186, 0,120,184, 0, + 122,178, 0,124,166, 7,123,139, 37,114,104,197, 99, 75,247, + 123,137, 41,123,171, 3,119,186, 0,115,195, 0,112,199, 0, + 111,201, 0,112,200, 0,112,200, 0,110,202, 0,110,202, 0, + 109,204, 0,104,210, 0, 99,216, 0, 94,220, 0, 91,224, 0, + 87,227, 0, 84,229, 0, 83,230, 0, 83,230, 0, 85,228, 0, + 89,225, 0, 91,224, 0, 91,223, 0, 93,221, 0, 97,217, 0, + 102,212, 0,108,206, 0,113,198, 0,118,189, 0,121,179, 0, + 123,169, 4,124,160, 12,124,143, 31,114,104,197, 69, 60,230, + 102, 80,250,119,119, 77,124,145, 29,124,155, 16,124,158, 13, + 124,165, 8,122,178, 0,119,186, 0,118,189, 0,118,188, 0, + 120,184, 0,122,177, 0,122,178, 0,121,179, 0,121,179, 0, + 122,178, 0,122,175, 0,122,175, 0,122,178, 0,120,182, 0, + 119,186, 0,118,189, 0,118,188, 0,120,183, 0,122,177, 0, + 123,174, 1,123,169, 4,124,157, 15,122,135, 44,124,145, 29, + 124,164, 9,123,171, 3,123,172, 2,124,167, 6,124,154, 18, + 121,127, 58,107, 89,252,120,122, 70,124,147, 26,124,162, 10, + 123,171, 3,122,177, 0,121,180, 0,120,182, 0,119,186, 0, + 117,191, 0,115,194, 0,113,199, 0,111,201, 0,110,203, 0, + 107,206, 0,105,209, 0,103,211, 0,101,213, 0,100,215, 0, + 100,215, 0,101,214, 0,104,210, 0,108,205, 0,113,198, 0, + 116,192, 0,115,195, 0,113,198, 0,113,198, 0,115,195, 0, + 118,189, 0,121,180, 0,123,174, 1,122,176, 0,123,172, 2, + 124,162, 10,124,154, 18,124,152, 20,124,167, 6,122,176, 0, + 121,180, 0,122,178, 0,123,174, 1,120,183, 0,118,188, 0, + 117,191, 0,118,189, 0,119,185, 0,122,178, 0,123,169, 4, + 123,170, 3,122,175, 0,122,178, 0,122,177, 0,123,171, 3, + 124,160, 12,123,137, 41,119,119, 77,114,104,197, 94, 70,242, + 30, 31,180, 69, 60,230,105, 84,252,113,100,242,114,104,197, + 113,100,242,120,122, 70,122,130, 53,122,135, 44,124,155, 16, + 123,168, 5,122,178, 0,120,182, 0,120,183, 0,121,182, 0, + 121,181, 0,122,178, 0,122,175, 0,123,169, 4,124,161, 11, + 124,155, 16,124,149, 24,123,139, 37,122,132, 48,124,145, 29, + 124,154, 18,124,164, 9,122,176, 0,121,182, 0,120,183, 0, + 118,189, 0,116,193, 0,115,195, 0,114,196, 0,114,196, 0, + 114,197, 0,113,198, 0,111,201, 0,108,205, 0,106,208, 0, + 104,210, 0, 99,215, 0, 97,218, 0, 96,219, 0, 97,218, 0, + 97,217, 0, 95,220, 0, 91,223, 0, 89,225, 0, 88,226, 0, + 89,225, 0, 91,224, 0, 93,221, 0, 96,219, 0,100,215, 0, + 105,209, 0,110,202, 0,116,193, 0,120,184, 0,120,184, 0, + 119,186, 0,120,184, 0,120,184, 0,119,185, 0,119,187, 0, + 118,189, 0,117,191, 0,117,191, 0,117,190, 0,118,189, 0, + 117,191, 0,117,191, 0,118,189, 0,117,190, 0,117,191, 0, + 117,191, 0,118,189, 0,119,186, 0,119,185, 0,119,186, 0, + 117,190, 0,116,193, 0,115,195, 0,115,194, 0,116,193, 0, + 115,194, 0,116,193, 0,117,190, 0,119,186, 0,121,182, 0, + 121,179, 0,123,174, 1,123,170, 3,123,172, 2,122,176, 0, + 122,177, 0,122,176, 0,123,174, 1,123,171, 3,123,174, 1, + 121,179, 0,121,182, 0,120,182, 0,120,184, 0,119,186, 0, + 119,186, 0,119,186, 0,119,185, 0,120,183, 0,119,187, 0, + 117,190, 0,117,192, 0,117,192, 0,117,191, 0,117,191, 0, + 116,192, 0,117,191, 0,118,188, 0,118,188, 0,118,188, 0, + 119,186, 0,121,180, 0,124,167, 6,122,135, 44,109, 92,251, + 105, 84,252,124,149, 24,122,177, 0,117,191, 0,113,198, 0, + 111,202, 0,110,202, 0,112,200, 0,111,201, 0,110,202, 0, + 111,201, 0,110,202, 0,106,208, 0,100,215, 0, 94,220, 0, + 91,223, 0, 88,226, 0, 84,229, 0, 82,231, 0, 82,231, 0, + 83,230, 0, 87,227, 0, 92,223, 0, 95,220, 0, 97,218, 0, + 101,214, 0,106,208, 0,111,201, 0,116,193, 0,120,184, 0, + 123,174, 1,124,164, 9,124,157, 15,124,145, 29,119,119, 77, + 87, 65,237,102, 80,250,105, 84,252,121,125, 63,123,141, 34, + 124,147, 26,124,162, 10,122,178, 0,119,186, 0,118,189, 0, + 118,189, 0,120,184, 0,122,178, 0,122,177, 0,122,178, 0, + 122,177, 0,123,174, 1,123,171, 3,123,174, 1,122,177, 0, + 121,181, 0,120,184, 0,119,187, 0,119,185, 0,121,181, 0, + 122,178, 0,122,176, 0,123,171, 3,124,160, 12,122,132, 48, + 124,147, 26,124,166, 7,122,175, 0,122,177, 0,123,172, 2, + 124,160, 12,122,135, 44,107, 89,252,121,125, 63,124,150, 22, + 124,165, 8,123,172, 2,122,177, 0,122,178, 0,121,181, 0, + 119,185, 0,117,190, 0,114,196, 0,112,200, 0,109,203, 0, + 108,206, 0,106,207, 0,104,210, 0,103,212, 0,101,214, 0, + 99,215, 0, 98,216, 0, 99,215, 0,102,213, 0,106,208, 0, + 110,202, 0,113,199, 0,110,202, 0,108,205, 0,107,207, 0, + 108,206, 0,111,202, 0,115,195, 0,119,185, 0,121,182, 0, + 122,178, 0,123,170, 3,124,154, 18,124,149, 24,124,162, 10, + 123,170, 3,123,172, 2,123,169, 4,122,175, 0,120,184, 0, + 118,189, 0,117,190, 0,118,188, 0,119,185, 0,122,178, 0, + 123,170, 3,122,176, 0,121,181, 0,121,182, 0,122,178, 0, + 123,172, 2,124,160, 12,122,135, 44,118,114, 96,113,100,242, + 94, 70,242, 30, 26,168, 30, 31,180, 87, 65,237,107, 89,252, + 113,100,242,115,107,129,122,132, 48,124,143, 31,124,147, 26, + 124,154, 18,123,168, 5,122,176, 0,121,181, 0,121,181, 0, + 121,180, 0,121,180, 0,121,180, 0,122,178, 0,122,175, 0, + 123,169, 4,124,155, 16,124,143, 31,122,132, 48,120,122, 70, + 123,139, 37,124,152, 20,124,167, 6,122,178, 0,120,184, 0, + 119,186, 0,117,192, 0,115,195, 0,114,197, 0,114,197, 0, + 114,197, 0,113,199, 0,113,199, 0,112,200, 0,109,204, 0, + 107,207, 0,102,212, 0, 97,218, 0, 94,221, 0, 93,222, 0, + 94,221, 0, 94,220, 0, 91,224, 0, 88,226, 0, 87,227, 0, + 87,227, 0, 89,225, 0, 92,222, 0, 95,219, 0, 98,216, 0, + 101,214, 0,105,209, 0,109,204, 0,114,197, 0,117,190, 0, + 119,186, 0,119,187, 0,119,186, 0,119,185, 0,119,187, 0, + 118,189, 0,117,192, 0,116,193, 0,116,192, 0,117,191, 0, + 117,191, 0,115,194, 0,115,195, 0,116,193, 0,117,190, 0, + 118,189, 0,117,190, 0,118,188, 0,119,186, 0,118,188, 0, + 116,192, 0,113,198, 0,112,200, 0,111,201, 0,112,200, 0, + 114,197, 0,113,198, 0,114,197, 0,115,194, 0,117,190, 0, + 119,186, 0,120,183, 0,121,181, 0,122,176, 0,122,175, 0, + 122,178, 0,121,179, 0,121,179, 0,122,178, 0,122,175, 0, + 122,175, 0,121,180, 0,121,182, 0,120,183, 0,119,186, 0, + 118,189, 0,117,191, 0,117,192, 0,117,191, 0,118,189, 0, + 118,188, 0,116,192, 0,115,194, 0,115,195, 0,115,194, 0, + 115,194, 0,114,196, 0,114,196, 0,117,191, 0,117,190, 0, + 117,190, 0,118,188, 0,121,182, 0,124,167, 6,122,132, 48, + 102, 80,250,107, 89,252,124,152, 20,121,179, 0,116,193, 0, + 112,200, 0,109,204, 0,109,204, 0,110,202, 0,112,200, 0, + 111,201, 0,112,199, 0,112,199, 0,106,208, 0, 99,215, 0, + 94,221, 0, 91,224, 0, 90,224, 0, 86,228, 0, 83,230, 0, + 82,231, 0, 83,230, 0, 86,228, 0, 91,224, 0, 97,218, 0, + 102,212, 0,106,208, 0,110,202, 0,114,197, 0,117,191, 0, + 120,184, 0,122,176, 0,124,165, 8,124,150, 22,124,143, 31, + 120,122, 70,111, 96,248,107, 89,252,105, 84,252,113,100,242, + 120,122, 70,122,130, 53,124,161, 11,122,177, 0,119,186, 0, + 118,189, 0,118,189, 0,119,186, 0,121,179, 0,123,170, 3, + 123,171, 3,123,169, 4,124,166, 7,124,166, 7,123,173, 1, + 122,178, 0,121,180, 0,121,179, 0,121,182, 0,121,180, 0, + 122,178, 0,122,178, 0,122,176, 0,123,170, 3,124,158, 13, + 122,130, 53,124,149, 24,123,168, 5,122,177, 0,122,178, 0, + 123,174, 1,124,161, 11,122,135, 44,105, 84,252,121,125, 63, + 124,150, 22,124,164, 9,123,170, 3,123,173, 1,122,175, 0, + 122,177, 0,121,182, 0,117,190, 0,114,196, 0,112,200, 0, + 108,205, 0,106,208, 0,104,210, 0,103,211, 0,103,211, 0, + 102,213, 0,100,215, 0, 98,216, 0, 98,216, 0,100,214, 0, + 103,211, 0,107,207, 0,110,202, 0,107,207, 0,104,210, 0, + 102,212, 0,102,212, 0,105,209, 0,109,204, 0,114,196, 0, + 119,187, 0,120,184, 0,122,177, 0,124,164, 9,124,145, 29, + 124,158, 13,124,164, 9,124,165, 8,124,160, 12,123,172, 2, + 121,182, 0,119,186, 0,118,188, 0,118,189, 0,119,186, 0, + 121,181, 0,123,172, 2,121,179, 0,120,184, 0,119,186, 0, + 120,183, 0,122,176, 0,124,161, 11,122,135, 44,107, 89,252, + 99, 75,247, 30, 49,213, 30, 15,143, 30, 43,203,102, 80,250, + 111, 96,248,114,104,197,114,104,197,122,132, 48,124,147, 26, + 124,154, 18,124,158, 13,124,167, 6,123,174, 1,122,178, 0, + 122,178, 0,120,183, 0,120,183, 0,121,180, 0,121,179, 0, + 122,178, 0,123,173, 1,124,164, 9,123,139, 37,122,130, 53, + 115,107,129,122,130, 53,124,147, 26,124,167, 6,121,179, 0, + 119,185, 0,119,186, 0,116,193, 0,114,196, 0,114,197, 0, + 114,197, 0,112,200, 0,111,202, 0,111,202, 0,113,199, 0, + 110,202, 0,107,206, 0,100,214, 0, 94,220, 0, 91,224, 0, + 89,225, 0, 90,224, 0, 92,223, 0, 88,226, 0, 86,228, 0, + 86,228, 0, 88,226, 0, 91,224, 0, 94,221, 0, 98,217, 0, + 101,214, 0,103,212, 0,105,209, 0,108,205, 0,111,201, 0, + 114,196, 0,117,191, 0,118,188, 0,119,185, 0,120,184, 0, + 119,186, 0,118,189, 0,116,192, 0,115,194, 0,115,194, 0, + 116,193, 0,117,191, 0,115,194, 0,114,196, 0,114,196, 0, + 115,194, 0,117,191, 0,118,188, 0,119,186, 0,119,187, 0, + 115,194, 0,111,201, 0,108,205, 0,107,207, 0,107,207, 0, + 108,205, 0,110,202, 0,113,199, 0,113,198, 0,114,196, 0, + 116,192, 0,117,191, 0,117,191, 0,117,191, 0,118,188, 0, + 121,181, 0,121,179, 0,121,181, 0,121,182, 0,121,181, 0, + 121,179, 0,122,178, 0,122,177, 0,122,178, 0,121,180, 0, + 120,184, 0,118,189, 0,117,192, 0,116,193, 0,116,193, 0, + 116,192, 0,118,189, 0,115,194, 0,114,197, 0,113,198, 0, + 114,197, 0,114,197, 0,113,198, 0,114,197, 0,116,192, 0, + 116,193, 0,116,193, 0,117,191, 0,120,184, 0,123,169, 4, + 122,132, 48, 99, 75,247,114,104,197,124,152, 20,121,180, 0, + 115,194, 0,110,202, 0,107,206, 0,106,208, 0,107,207, 0, + 108,205, 0,110,203, 0,111,201, 0,112,200, 0,106,208, 0, + 100,215, 0, 95,220, 0, 92,222, 0, 92,222, 0, 88,226, 0, + 85,229, 0, 83,230, 0, 83,230, 0, 86,228, 0, 91,223, 0, + 97,218, 0,102,212, 0,107,207, 0,110,202, 0,114,197, 0, + 117,191, 0,120,184, 0,122,177, 0,124,167, 6,124,157, 15, + 124,145, 29,122,132, 48,119,119, 77,111, 96,248,102, 80,250, + 87, 65,237,109, 92,251,121,125, 63,124,158, 13,122,176, 0, + 119,185, 0,118,189, 0,118,189, 0,119,186, 0,121,179, 0, + 123,170, 3,124,162, 10,124,160, 12,124,160, 12,123,168, 5, + 123,174, 1,122,178, 0,121,180, 0,121,179, 0,122,177, 0, + 122,177, 0,122,178, 0,122,177, 0,123,174, 1,123,168, 5, + 124,155, 16,121,127, 58,124,150, 22,123,168, 5,122,177, 0, + 122,178, 0,123,172, 2,124,157, 15,121,125, 63,107, 89,252, + 121,127, 58,124,150, 22,124,162, 10,123,168, 5,123,170, 3, + 123,171, 3,123,174, 1,119,186, 0,116,193, 0,113,198, 0, + 111,202, 0,107,207, 0,103,211, 0,101,214, 0,100,215, 0, + 100,215, 0,102,213, 0,102,213, 0,100,215, 0, 99,215, 0, + 100,215, 0,102,213, 0,105,209, 0,107,207, 0,105,209, 0, + 101,213, 0, 99,216, 0, 98,216, 0,101,214, 0,105,209, 0, + 110,202, 0,115,194, 0,117,190, 0,120,183, 0,123,170, 3, + 124,157, 15,124,154, 18,124,158, 13,124,158, 13,124,152, 20, + 124,165, 8,122,176, 0,120,182, 0,118,189, 0,117,192, 0, + 118,189, 0,120,184, 0,122,178, 0,121,179, 0,119,185, 0, + 119,187, 0,119,186, 0,121,179, 0,124,167, 6,124,145, 29, + 117,110,109, 99, 75,247, 30, 49,213, 30, 43,203,105, 84,252, + 115,107,129,119,119, 77,119,119, 77,120,122, 70,121,125, 63, + 123,139, 37,124,150, 22,124,160, 12,123,168, 5,123,174, 1, + 122,177, 0,121,180, 0,120,184, 0,120,184, 0,121,181, 0, + 122,178, 0,122,178, 0,123,173, 1,124,164, 9,124,143, 31, + 122,135, 44,117,110,109,120,122, 70,123,141, 34,124,165, 8, + 122,178, 0,120,184, 0,119,186, 0,117,191, 0,115,195, 0, + 114,196, 0,113,198, 0,111,202, 0,109,203, 0,109,203, 0, + 111,201, 0,111,201, 0,108,206, 0,100,215, 0, 93,221, 0, + 89,225, 0, 87,227, 0, 88,226, 0, 89,225, 0, 87,227, 0, + 86,228, 0, 87,227, 0, 89,225, 0, 92,222, 0, 94,221, 0, + 95,220, 0, 98,217, 0,101,213, 0,105,209, 0,107,206, 0, + 109,204, 0,111,201, 0,113,198, 0,114,196, 0,116,193, 0, + 117,190, 0,119,185, 0,118,188, 0,117,192, 0,115,194, 0, + 115,195, 0,115,194, 0,116,193, 0,115,194, 0,114,196, 0, + 114,197, 0,114,197, 0,115,195, 0,116,193, 0,117,191, 0, + 114,197, 0,110,202, 0,106,208, 0,103,212, 0,101,213, 0, + 101,213, 0,103,212, 0,105,209, 0,108,206, 0,110,203, 0, + 111,201, 0,112,199, 0,113,199, 0,112,200, 0,112,200, 0, + 113,198, 0,116,192, 0,120,184, 0,120,184, 0,120,184, 0, + 120,184, 0,120,184, 0,120,184, 0,120,184, 0,120,184, 0, + 120,184, 0,120,182, 0,119,185, 0,118,189, 0,116,192, 0, + 116,193, 0,116,193, 0,117,191, 0,115,195, 0,113,198, 0, + 112,200, 0,112,200, 0,113,199, 0,113,199, 0,114,197, 0, + 114,196, 0,114,196, 0,115,195, 0,117,192, 0,120,184, 0, + 123,169, 4,122,132, 48, 99, 75,247,115,107,129,124,154, 18, + 121,180, 0,115,194, 0,109,203, 0,105,209, 0,103,211, 0, + 103,211, 0,104,210, 0,106,208, 0,107,206, 0,109,203, 0, + 107,207, 0,102,212, 0, 98,216, 0, 96,219, 0, 95,220, 0, + 91,224, 0, 87,227, 0, 85,229, 0, 85,229, 0, 88,226, 0, + 92,222, 0, 98,217, 0,103,211, 0,108,206, 0,112,200, 0, + 116,193, 0,119,187, 0,121,179, 0,123,171, 3,124,162, 10, + 124,154, 18,124,147, 26,123,139, 37,121,127, 58,117,110,109, + 99, 75,247, 30, 43,203, 30, 55,222,118,117, 85,124,154, 18, + 123,172, 2,121,182, 0,119,186, 0,119,185, 0,121,182, 0, + 123,173, 1,124,164, 9,124,155, 16,124,152, 20,124,158, 13, + 124,166, 7,123,172, 2,122,177, 0,122,178, 0,122,176, 0, + 123,174, 1,123,174, 1,123,174, 1,123,174, 1,123,172, 2, + 124,167, 6,124,155, 16,121,127, 58,124,145, 29,124,165, 8, + 123,173, 1,123,174, 1,124,167, 6,124,149, 24,117,110,109, + 113,100,242,122,132, 48,124,152, 20,124,162, 10,124,167, 6, + 123,169, 4,123,170, 3,122,175, 0,119,187, 0,115,194, 0, + 113,198, 0,109,203, 0,105,209, 0,101,214, 0, 98,217, 0, + 96,219, 0, 96,219, 0, 98,217, 0,101,213, 0,103,211, 0, + 102,213, 0,101,213, 0,102,212, 0,103,211, 0,105,209, 0, + 103,211, 0,100,215, 0, 98,217, 0, 97,218, 0, 99,216, 0, + 102,212, 0,108,206, 0,112,199, 0,114,196, 0,118,188, 0, + 122,176, 0,124,164, 9,124,147, 26,124,152, 20,124,152, 20, + 124,143, 31,124,154, 18,123,169, 4,120,184, 0,117,192, 0, + 115,194, 0,116,193, 0,118,189, 0,120,184, 0,122,178, 0, + 120,184, 0,119,186, 0,119,185, 0,121,180, 0,123,170, 3, + 124,150, 22,120,122, 70,109, 92,251, 94, 70,242, 99, 75,247, + 115,107,129,122,130, 53,123,139, 37,123,139, 37,123,137, 41, + 123,139, 37,124,145, 29,124,154, 18,124,162, 10,123,169, 4, + 123,174, 1,122,177, 0,122,178, 0,121,181, 0,121,180, 0, + 122,177, 0,122,178, 0,122,176, 0,123,171, 3,124,161, 11, + 124,150, 22,124,145, 29,121,125, 63,115,107,129,122,130, 53, + 124,158, 13,123,174, 1,120,182, 0,120,184, 0,118,188, 0, + 116,192, 0,115,194, 0,112,199, 0,110,202, 0,108,205, 0, + 108,206, 0,109,203, 0,113,199, 0,109,204, 0,101,214, 0, + 94,220, 0, 90,224, 0, 88,226, 0, 88,226, 0, 89,226, 0, + 87,227, 0, 87,227, 0, 88,226, 0, 91,223, 0, 91,223, 0, + 92,222, 0, 94,221, 0, 96,219, 0,100,215, 0,104,210, 0, + 106,207, 0,107,206, 0,109,204, 0,110,203, 0,111,202, 0, + 112,200, 0,113,198, 0,115,194, 0,118,189, 0,118,189, 0, + 117,192, 0,116,193, 0,115,194, 0,116,193, 0,115,195, 0, + 114,197, 0,113,199, 0,112,200, 0,112,199, 0,113,199, 0, + 112,200, 0,108,205, 0,104,210, 0,100,214, 0, 97,217, 0, + 96,219, 0, 96,219, 0, 97,217, 0,100,215, 0,102,212, 0, + 105,209, 0,106,208, 0,107,206, 0,107,207, 0,106,208, 0, + 106,207, 0,108,206, 0,111,201, 0,115,194, 0,118,189, 0, + 117,191, 0,116,193, 0,116,193, 0,116,193, 0,117,191, 0, + 117,190, 0,118,189, 0,119,186, 0,121,182, 0,119,187, 0, + 117,191, 0,116,193, 0,116,193, 0,117,191, 0,114,196, 0, + 112,199, 0,111,201, 0,111,201, 0,112,200, 0,112,200, 0, + 113,199, 0,114,197, 0,114,197, 0,115,195, 0,117,191, 0, + 120,182, 0,124,165, 8,120,122, 70, 99, 75,247,117,110,109, + 124,155, 16,121,180, 0,115,194, 0,109,203, 0,105,209, 0, + 101,213, 0,100,215, 0,100,214, 0,102,213, 0,103,211, 0, + 106,207, 0,109,203, 0,106,208, 0,103,212, 0,101,214, 0, + 97,217, 0, 93,221, 0, 90,225, 0, 88,226, 0, 88,226, 0, + 90,224, 0, 95,220, 0,100,214, 0,106,208, 0,111,202, 0, + 115,194, 0,119,187, 0,122,178, 0,123,169, 4,124,160, 12, + 124,152, 20,124,145, 29,123,141, 34,123,137, 41,122,130, 53, + 118,117, 85,107, 89,252, 30, 31,180, 30, 31,180,115,107,129, + 124,147, 26,124,166, 7,122,175, 0,122,178, 0,122,178, 0, + 123,172, 2,124,162, 10,124,149, 24,123,139, 37,123,141, 34, + 124,150, 22,124,161, 11,124,167, 6,123,171, 3,123,172, 2, + 123,169, 4,124,167, 6,124,167, 6,123,169, 4,123,170, 3, + 123,169, 4,124,165, 8,124,154, 18,122,130, 53,123,137, 41, + 124,160, 12,123,168, 5,123,168, 5,124,160, 12,123,137, 41, + 107, 89,252,115,107,129,123,137, 41,124,152, 20,124,162, 10, + 124,166, 7,123,168, 5,123,170, 3,123,173, 1,119,186, 0, + 116,192, 0,113,198, 0,108,206, 0,103,212, 0, 99,216, 0, + 95,219, 0, 94,221, 0, 94,221, 0, 95,219, 0, 98,216, 0, + 101,213, 0,104,210, 0,104,210, 0,104,210, 0,104,210, 0, + 104,210, 0,102,212, 0,100,215, 0, 98,217, 0, 97,217, 0, + 98,216, 0,102,213, 0,107,207, 0,109,204, 0,112,200, 0, + 116,193, 0,121,181, 0,124,167, 6,124,150, 22,124,147, 26, + 124,145, 29,122,135, 44,123,139, 37,123,169, 4,119,186, 0, + 116,193, 0,114,197, 0,114,196, 0,116,193, 0,118,189, 0, + 121,182, 0,121,181, 0,120,184, 0,120,184, 0,121,179, 0, + 123,169, 4,124,152, 20,121,125, 63,111, 96,248,102, 80,250, + 109, 92,251,120,122, 70,124,143, 31,124,152, 20,124,154, 18, + 124,147, 26,124,149, 24,124,152, 20,124,157, 15,124,162, 10, + 123,168, 5,123,172, 2,122,175, 0,122,175, 0,123,174, 1, + 122,175, 0,122,177, 0,122,177, 0,123,174, 1,123,168, 5, + 124,157, 15,124,157, 15,124,152, 20,122,135, 44,113,100,242, + 117,110,109,124,149, 24,123,168, 5,122,178, 0,121,181, 0, + 120,184, 0,118,188, 0,116,193, 0,113,199, 0,110,203, 0, + 108,206, 0,107,207, 0,108,205, 0,111,202, 0,110,202, 0, + 103,211, 0, 97,218, 0, 93,222, 0, 91,224, 0, 90,225, 0, + 87,227, 0, 87,227, 0, 87,227, 0, 90,224, 0, 91,224, 0, + 91,223, 0, 92,223, 0, 94,221, 0, 97,218, 0,100,214, 0, + 103,211, 0,106,208, 0,106,207, 0,107,207, 0,108,205, 0, + 108,205, 0,109,204, 0,109,203, 0,111,201, 0,113,198, 0, + 115,194, 0,117,191, 0,117,191, 0,117,192, 0,116,193, 0, + 114,196, 0,113,198, 0,112,200, 0,111,202, 0,110,202, 0, + 110,203, 0,108,206, 0,104,210, 0,100,215, 0, 96,219, 0, + 93,221, 0, 92,222, 0, 92,222, 0, 93,221, 0, 95,219, 0, + 98,217, 0,100,215, 0,102,213, 0,103,211, 0,102,213, 0, + 101,214, 0,101,213, 0,103,211, 0,106,207, 0,111,202, 0, + 115,194, 0,113,198, 0,111,201, 0,110,202, 0,110,203, 0, + 110,202, 0,111,201, 0,113,198, 0,117,192, 0,120,184, 0, + 119,185, 0,117,190, 0,117,192, 0,117,192, 0,117,191, 0, + 114,196, 0,112,199, 0,111,201, 0,111,201, 0,111,201, 0, + 111,202, 0,112,200, 0,114,197, 0,114,196, 0,116,193, 0, + 118,188, 0,122,178, 0,124,155, 16,114,104,197, 69, 60,230, + 119,119, 77,124,155, 16,122,178, 0,116,192, 0,110,202, 0, + 105,209, 0,101,214, 0, 98,217, 0, 98,217, 0, 99,216, 0, + 101,214, 0,104,210, 0,108,205, 0,110,203, 0,108,206, 0, + 105,209, 0,101,214, 0, 97,218, 0, 94,221, 0, 92,223, 0, + 92,222, 0, 94,220, 0, 99,216, 0,104,210, 0,110,203, 0, + 115,195, 0,119,186, 0,122,176, 0,124,164, 9,124,150, 22, + 124,143, 31,123,139, 37,123,141, 34,124,143, 31,122,135, 44, + 122,132, 48,120,122, 70,114,104,197, 30, 55,222, 30, 20,155, + 107, 89,252,122,132, 48,124,155, 16,124,165, 8,123,168, 5, + 124,165, 8,124,157, 15,123,141, 34,122,135, 44,118,117, 85, + 120,122, 70,123,139, 37,124,150, 22,124,158, 13,124,162, 10, + 124,161, 11,124,158, 13,124,155, 16,124,155, 16,124,160, 12, + 124,162, 10,124,164, 9,124,161, 11,124,152, 20,122,132, 48, + 121,127, 58,124,154, 18,124,162, 10,124,162, 10,124,152, 20, + 121,125, 63, 99, 75,247,115,107,129,122,135, 44,124,150, 22, + 124,160, 12,124,165, 8,124,167, 6,123,169, 4,123,174, 1, + 120,182, 0,117,192, 0,112,200, 0,107,207, 0,102,212, 0, + 98,217, 0, 95,220, 0, 94,221, 0, 94,221, 0, 95,220, 0, + 97,218, 0,100,215, 0,102,213, 0,103,211, 0,105,209, 0, + 105,209, 0,104,210, 0,102,212, 0,100,214, 0, 99,216, 0, + 98,216, 0, 99,215, 0,102,212, 0,105,209, 0,106,208, 0, + 109,204, 0,114,196, 0,120,183, 0,123,169, 4,124,154, 18, + 123,139, 37,123,137, 41,120,122, 70,123,137, 41,123,171, 3, + 119,186, 0,115,194, 0,113,198, 0,113,198, 0,114,196, 0, + 117,192, 0,119,186, 0,121,179, 0,120,182, 0,121,182, 0, + 122,177, 0,124,167, 6,124,149, 24,119,119, 77,114,104,197, + 105, 84,252,113,100,242,122,130, 53,124,149, 24,124,158, 13, + 124,161, 11,124,155, 16,124,150, 22,124,152, 20,124,155, 16, + 124,160, 12,124,164, 9,123,168, 5,123,171, 3,123,172, 2, + 123,172, 2,123,174, 1,122,175, 0,122,175, 0,123,171, 3, + 124,165, 8,124,158, 13,124,161, 11,124,157, 15,124,143, 31, + 118,117, 85, 99, 75,247,122,130, 53,124,157, 15,123,170, 3, + 122,175, 0,122,178, 0,120,184, 0,117,190, 0,114,196, 0, + 111,201, 0,108,205, 0,107,207, 0,107,206, 0,109,203, 0, + 109,203, 0,106,208, 0,100,215, 0, 96,219, 0, 93,221, 0, + 89,225, 0, 87,227, 0, 87,227, 0, 90,225, 0, 91,223, 0, + 91,223, 0, 91,223, 0, 93,222, 0, 95,220, 0, 97,218, 0, + 99,216, 0,101,213, 0,103,212, 0,105,209, 0,107,207, 0, + 107,207, 0,107,206, 0,107,207, 0,107,207, 0,107,206, 0, + 109,204, 0,110,202, 0,112,199, 0,114,196, 0,115,194, 0, + 114,196, 0,114,197, 0,113,199, 0,111,201, 0,110,202, 0, + 109,203, 0,108,205, 0,106,208, 0,102,213, 0, 98,217, 0, + 94,220, 0, 92,223, 0, 91,224, 0, 90,224, 0, 91,223, 0, + 94,221, 0, 95,219, 0, 97,217, 0, 99,216, 0,100,214, 0, + 99,216, 0, 98,217, 0, 98,217, 0,100,215, 0,103,211, 0, + 108,205, 0,113,199, 0,110,203, 0,107,207, 0,105,209, 0, + 104,210, 0,105,209, 0,106,208, 0,109,204, 0,113,199, 0, + 117,191, 0,117,192, 0,117,191, 0,117,191, 0,117,190, 0, + 117,190, 0,114,196, 0,113,199, 0,111,201, 0,111,201, 0, + 111,201, 0,110,202, 0,111,202, 0,114,197, 0,115,195, 0, + 117,191, 0,120,184, 0,123,171, 3,124,143, 31,113,100,242, + 87, 65,237,121,125, 63,124,155, 16,122,176, 0,118,189, 0, + 112,200, 0,106,207, 0,102,213, 0, 98,216, 0, 97,218, 0, + 98,217, 0,100,215, 0,102,212, 0,107,207, 0,112,200, 0, + 113,199, 0,109,203, 0,105,209, 0,102,213, 0, 98,216, 0, + 97,218, 0, 97,217, 0,100,214, 0,105,209, 0,110,202, 0, + 115,194, 0,120,184, 0,123,172, 2,124,160, 12,124,154, 18, + 124,147, 26,123,139, 37,122,135, 44,123,139, 37,123,141, 34, + 122,132, 48,122,132, 48,122,130, 53,118,117, 85,102, 80,250, + 30, 37,192, 99, 75,247,119,119, 77,123,139, 37,124,149, 24, + 124,150, 22,124,143, 31,122,130, 53,121,125, 63,119,119, 77, + 111, 96,248,113,100,242,119,119, 77,122,135, 44,124,143, 31, + 124,147, 26,124,145, 29,123,137, 41,122,135, 44,123,137, 41, + 124,143, 31,124,150, 22,124,154, 18,124,154, 18,124,147, 26, + 122,130, 53,121,125, 63,124,147, 26,124,158, 13,124,158, 13, + 124,147, 26,118,114, 96, 69, 60,230,114,104,197,122,130, 53, + 124,147, 26,124,160, 12,124,167, 6,123,169, 4,123,168, 5, + 123,174, 1,120,183, 0,116,193, 0,111,201, 0,107,207, 0, + 102,212, 0, 99,215, 0, 97,218, 0, 96,219, 0, 96,219, 0, + 97,218, 0, 98,217, 0, 99,215, 0,101,214, 0,102,212, 0, + 103,211, 0,104,210, 0,104,210, 0,102,212, 0,101,214, 0, + 100,215, 0,100,215, 0,100,215, 0,101,214, 0,102,212, 0, + 104,210, 0,108,206, 0,114,197, 0,120,184, 0,123,171, 3, + 124,154, 18,122,132, 48,121,127, 58,117,110,109,123,141, 34, + 123,172, 2,119,187, 0,115,195, 0,113,198, 0,113,198, 0, + 114,196, 0,116,192, 0,119,186, 0,122,178, 0,121,180, 0, + 122,178, 0,123,173, 1,124,162, 10,123,141, 34,118,114, 96, + 117,110,109,109, 92,251,111, 96,248,121,127, 58,124,147, 26, + 124,158, 13,124,162, 10,124,158, 13,124,147, 26,124,143, 31, + 124,145, 29,124,149, 24,124,154, 18,124,160, 12,124,165, 8, + 124,167, 6,123,168, 5,123,171, 3,123,173, 1,123,172, 2, + 123,168, 5,124,161, 11,124,155, 16,124,161, 11,124,160, 12, + 124,149, 24,121,125, 63,111, 96,248,113,100,242,123,139, 37, + 124,157, 15,124,165, 8,123,169, 4,122,178, 0,119,185, 0, + 116,192, 0,113,198, 0,110,202, 0,108,205, 0,108,205, 0, + 109,203, 0,109,204, 0,105,209, 0,101,214, 0, 97,218, 0, + 92,222, 0, 89,225, 0, 88,226, 0, 89,225, 0, 92,222, 0, + 92,223, 0, 92,223, 0, 92,223, 0, 91,223, 0, 92,223, 0, + 94,221, 0, 96,219, 0, 97,218, 0, 99,215, 0,102,213, 0, + 105,209, 0,107,207, 0,107,206, 0,107,207, 0,106,208, 0, + 105,209, 0,105,209, 0,107,207, 0,108,205, 0,111,202, 0, + 113,199, 0,114,197, 0,113,198, 0,113,199, 0,112,200, 0, + 111,202, 0,110,203, 0,109,204, 0,106,208, 0,102,212, 0, + 98,216, 0, 95,219, 0, 93,222, 0, 92,223, 0, 91,223, 0, + 92,222, 0, 94,221, 0, 95,219, 0, 97,218, 0, 98,217, 0, + 99,215, 0, 98,217, 0, 97,218, 0, 97,217, 0, 99,215, 0, + 102,212, 0,107,207, 0,110,202, 0,106,207, 0,103,211, 0, + 101,214, 0,101,214, 0,101,213, 0,103,211, 0,106,208, 0, + 110,202, 0,112,200, 0,112,200, 0,113,198, 0,116,193, 0, + 118,189, 0,118,189, 0,115,194, 0,113,198, 0,112,200, 0, + 112,200, 0,111,202, 0,109,203, 0,110,203, 0,113,199, 0, + 116,193, 0,118,189, 0,121,180, 0,124,162, 10,121,125, 63, + 117,110,109,114,104,197,121,127, 58,124,152, 20,123,172, 2, + 119,186, 0,114,196, 0,109,204, 0,104,210, 0,100,215, 0, + 98,216, 0, 98,216, 0,100,215, 0,102,212, 0,106,208, 0, + 111,202, 0,116,193, 0,114,197, 0,110,202, 0,107,207, 0, + 105,209, 0,103,211, 0,104,210, 0,107,207, 0,111,201, 0, + 116,193, 0,120,182, 0,123,168, 5,124,157, 15,124,154, 18, + 124,149, 24,123,141, 34,122,130, 53,121,125, 63,122,130, 53, + 122,132, 48,121,125, 63,122,135, 44,123,137, 41,121,127, 58, + 114,104,197, 30, 55,222, 87, 65,237,115,107,129,121,127, 58, + 122,132, 48,122,130, 53,119,119, 77,115,107,129,118,114, 96, + 113,100,242, 69, 60,230, 87, 65,237,111, 96,248,118,117, 85, + 121,125, 63,121,125, 63,119,119, 77,115,107,129,120,122, 70, + 122,130, 53,122,130, 53,122,132, 48,123,139, 37,124,143, 31, + 123,137, 41,119,119, 77,118,117, 85,124,143, 31,124,155, 16, + 124,155, 16,124,143, 31,117,110,109, 30, 43,203,109, 92,251, + 119,119, 77,124,149, 24,124,164, 9,123,171, 3,123,174, 1, + 122,175, 0,123,174, 1,120,183, 0,116,193, 0,112,200, 0, + 107,206, 0,104,210, 0,102,213, 0,100,214, 0,100,215, 0, + 100,214, 0,100,214, 0,101,214, 0,101,214, 0,100,215, 0, + 100,215, 0,102,213, 0,103,211, 0,104,210, 0,102,213, 0, + 99,215, 0, 98,217, 0, 97,218, 0, 98,217, 0, 99,215, 0, + 101,214, 0,103,211, 0,107,206, 0,113,198, 0,120,184, 0, + 123,172, 2,124,155, 16,121,127, 58,119,119, 77,117,110,109, + 124,145, 29,123,173, 1,119,187, 0,115,194, 0,114,197, 0, + 114,197, 0,115,194, 0,117,190, 0,120,184, 0,122,178, 0, + 122,178, 0,122,176, 0,123,169, 4,124,155, 16,122,130, 53, + 115,107,129,115,107,129,114,104,197,117,110,109,119,119, 77, + 123,141, 34,124,154, 18,124,158, 13,124,155, 16,124,145, 29, + 121,127, 58,121,125, 63,122,130, 53,123,137, 41,124,143, 31, + 124,152, 20,124,155, 16,124,160, 12,124,165, 8,123,168, 5, + 123,168, 5,124,165, 8,124,157, 15,124,149, 24,124,157, 15, + 124,157, 15,124,149, 24,122,130, 53,117,110,109,118,114, 96, + 117,110,109,122,135, 44,124,147, 26,124,160, 12,123,172, 2, + 122,178, 0,119,186, 0,116,193, 0,113,199, 0,110,202, 0, + 110,202, 0,110,202, 0,109,203, 0,106,208, 0,101,214, 0, + 97,218, 0, 93,221, 0, 91,223, 0, 91,224, 0, 93,222, 0, + 94,221, 0, 92,222, 0, 89,226, 0, 87,227, 0, 86,228, 0, + 88,226, 0, 91,223, 0, 91,223, 0, 92,222, 0, 95,219, 0, + 99,215, 0,102,212, 0,105,209, 0,105,209, 0,106,207, 0, + 105,209, 0,104,210, 0,103,211, 0,104,210, 0,106,208, 0, + 108,205, 0,111,201, 0,113,198, 0,113,198, 0,113,198, 0, + 113,198, 0,112,199, 0,111,201, 0,110,202, 0,108,205, 0, + 105,209, 0,102,213, 0, 99,216, 0, 97,218, 0, 95,219, 0, + 95,220, 0, 95,219, 0, 96,219, 0, 98,217, 0, 98,216, 0, + 99,215, 0,100,215, 0,100,215, 0, 98,216, 0, 99,216, 0, + 101,214, 0,104,210, 0,108,205, 0,107,206, 0,104,210, 0, + 101,214, 0, 99,215, 0, 99,215, 0,100,214, 0,102,212, 0, + 106,208, 0,108,205, 0,106,207, 0,106,207, 0,108,205, 0, + 112,199, 0,117,190, 0,119,187, 0,116,193, 0,114,197, 0, + 112,199, 0,112,200, 0,111,202, 0,109,203, 0,110,203, 0, + 112,199, 0,116,192, 0,119,187, 0,122,176, 0,124,158, 13, + 123,139, 37,122,135, 44,121,127, 58,121,127, 58,124,155, 16, + 122,178, 0,118,189, 0,114,197, 0,111,201, 0,107,207, 0, + 103,212, 0,101,214, 0,100,214, 0,101,214, 0,103,212, 0, + 106,208, 0,110,203, 0,114,196, 0,118,189, 0,116,193, 0, + 113,198, 0,111,202, 0,109,203, 0,110,202, 0,113,198, 0, + 117,191, 0,121,180, 0,124,164, 9,124,152, 20,124,160, 12, + 124,162, 10,124,161, 11,124,154, 18,123,137, 41,117,110,109, + 117,110,109,118,114, 96,121,125, 63,123,139, 37,124,143, 31, + 123,139, 37,120,122, 70,105, 84,252, 30, 55,222,109, 92,251, + 118,114, 96,119,119, 77,118,114, 96,113,100,242,109, 92,251, + 109, 92,251, 87, 65,237, 30, 15,143, 87, 65,237,113,100,242, + 117,110,109,115,107,129,113,100,242,107, 89,252, 94, 70,242, + 115,107,129,120,122, 70,121,125, 63,118,117, 85,119,119, 77, + 121,125, 63,119,119, 77,111, 96,248,118,114, 96,124,143, 31, + 124,154, 18,124,154, 18,123,141, 34,115,107,129, 69, 60,230, + 94, 70,242,119,119, 77,124,149, 24,124,164, 9,123,172, 2, + 122,176, 0,122,177, 0,122,178, 0,121,181, 0,117,191, 0, + 113,198, 0,109,203, 0,107,207, 0,105,209, 0,105,209, 0, + 105,209, 0,105,209, 0,105,209, 0,102,212, 0, 99,215, 0, + 97,217, 0, 97,217, 0, 99,216, 0,102,212, 0,105,209, 0, + 102,212, 0, 99,216, 0, 97,218, 0, 96,219, 0, 97,217, 0, + 99,215, 0,102,213, 0,105,209, 0,108,205, 0,114,196, 0, + 119,185, 0,123,174, 1,124,155, 16,121,125, 63,118,114, 96, + 114,104,197,124,147, 26,123,174, 1,119,186, 0,116,192, 0, + 115,194, 0,116,193, 0,117,190, 0,119,185, 0,122,178, 0, + 122,178, 0,122,178, 0,123,174, 1,124,165, 8,124,147, 26, + 118,117, 85,107, 89,252,107, 89,252,114,104,197,119,119, 77, + 120,122, 70,121,127, 58,124,143, 31,124,150, 22,124,149, 24, + 123,137, 41,121,127, 58,122,132, 48,122,132, 48,122,135, 44, + 122,130, 53,121,125, 63,122,135, 44,123,141, 34,124,152, 20, + 124,158, 13,124,161, 11,124,160, 12,124,152, 20,123,141, 34, + 124,147, 26,124,150, 22,124,143, 31,121,127, 58,120,122, 70, + 121,125, 63,119,119, 77,115,107,129,119,119, 77,124,149, 24, + 124,166, 7,122,175, 0,121,180, 0,119,186, 0,116,193, 0, + 113,198, 0,112,199, 0,112,200, 0,111,201, 0,108,206, 0, + 103,211, 0, 99,215, 0, 96,219, 0, 94,221, 0, 94,220, 0, + 97,218, 0, 92,222, 0, 87,227, 0, 83,230, 0, 82,231, 0, + 82,231, 0, 85,229, 0, 87,227, 0, 87,227, 0, 89,226, 0, + 92,222, 0, 97,218, 0,100,215, 0,102,212, 0,105,209, 0, + 106,207, 0,106,208, 0,104,210, 0,103,211, 0,104,210, 0, + 106,208, 0,108,205, 0,112,200, 0,113,199, 0,113,198, 0, + 113,199, 0,112,200, 0,112,200, 0,113,199, 0,113,199, 0, + 112,199, 0,110,203, 0,107,207, 0,104,210, 0,102,213, 0, + 100,214, 0,100,215, 0,100,215, 0,100,214, 0,101,214, 0, + 101,213, 0,101,213, 0,101,213, 0,102,212, 0,102,213, 0, + 102,212, 0,104,210, 0,107,207, 0,109,204, 0,106,208, 0, + 102,212, 0,100,215, 0, 99,216, 0,100,215, 0,101,213, 0, + 103,211, 0,106,208, 0,103,212, 0,101,213, 0,102,213, 0, + 105,209, 0,109,203, 0,115,194, 0,119,186, 0,116,192, 0, + 114,196, 0,113,199, 0,112,199, 0,111,201, 0,110,203, 0, + 110,202, 0,113,199, 0,116,192, 0,119,186, 0,122,175, 0, + 124,160, 12,124,150, 22,124,145, 29,123,137, 41,120,122, 70, + 124,162, 10,120,182, 0,116,193, 0,111,201, 0,108,206, 0, + 106,208, 0,105,209, 0,104,210, 0,103,212, 0,103,212, 0, + 104,210, 0,106,208, 0,109,204, 0,113,198, 0,117,191, 0, + 120,182, 0,118,188, 0,116,192, 0,115,194, 0,116,193, 0, + 118,189, 0,121,180, 0,124,165, 8,124,150, 22,124,160, 12, + 124,165, 8,124,166, 7,124,162, 10,124,154, 18,122,135, 44, + 114,104,197, 69, 60,230,114,104,197,122,130, 53,124,145, 29, + 124,149, 24,124,147, 26,122,132, 48,114,104,197, 30, 55,222, + 102, 80,250,114,104,197,117,110,109,115,107,129,109, 92,251, + 94, 70,242, 30, 49,213, 30, 10,132, 94, 70,242,117,110,109, + 121,127, 58,122,132, 48,121,125, 63,113,100,242, 87, 65,237, + 30, 43,203,107, 89,252,117,110,109,118,117, 85,118,114, 96, + 114,104,197,114,104,197,109, 92,251, 30, 55,222,118,117, 85, + 124,143, 31,124,155, 16,124,155, 16,124,143, 31,117,110,109, + 105, 84,252, 30, 49,213,118,114, 96,124,145, 29,124,161, 11, + 123,169, 4,123,173, 1,122,175, 0,122,175, 0,122,176, 0, + 119,187, 0,115,195, 0,112,200, 0,110,203, 0,109,204, 0, + 108,205, 0,109,204, 0,109,204, 0,107,207, 0,103,211, 0, + 100,215, 0, 97,217, 0, 97,218, 0, 98,217, 0,101,214, 0, + 106,207, 0,102,212, 0, 99,215, 0, 98,217, 0, 97,217, 0, + 99,216, 0,101,214, 0,103,211, 0,107,207, 0,110,202, 0, + 115,195, 0,118,188, 0,122,177, 0,124,157, 15,122,130, 53, + 118,117, 85,107, 89,252,124,149, 24,123,173, 1,120,184, 0, + 118,189, 0,117,190, 0,118,188, 0,120,182, 0,122,176, 0, + 122,177, 0,122,178, 0,122,176, 0,123,171, 3,124,160, 12, + 123,137, 41,114,104,197, 30, 31,180, 30, 37,192,107, 89,252, + 118,114, 96,121,125, 63,121,127, 58,121,127, 58,123,137, 41, + 122,135, 44,124,145, 29,124,152, 20,124,155, 16,124,154, 18, + 124,147, 26,122,135, 44,118,114, 96,107, 89,252,114,104,197, + 121,125, 63,123,141, 34,124,150, 22,124,152, 20,124,149, 24, + 123,139, 37,121,127, 58,122,135, 44,122,132, 48,121,125, 63, + 122,130, 53,122,130, 53,121,125, 63,117,110,109,102, 80,250, + 123,137, 41,124,161, 11,123,172, 2,122,178, 0,120,183, 0, + 118,188, 0,116,193, 0,115,195, 0,112,200, 0,110,203, 0, + 108,205, 0,107,207, 0,103,211, 0,100,214, 0, 99,216, 0, + 99,215, 0, 94,221, 0, 87,227, 0, 82,231, 0, 78,234, 0, + 77,235, 0, 78,234, 0, 81,232, 0, 85,229, 0, 84,229, 0, + 86,228, 0, 89,225, 0, 94,221, 0, 98,217, 0,101,214, 0, + 104,210, 0,109,204, 0,107,207, 0,105,209, 0,104,210, 0, + 105,209, 0,108,206, 0,110,202, 0,112,200, 0,113,198, 0, + 111,201, 0,109,203, 0,108,205, 0,108,205, 0,109,204, 0, + 110,202, 0,113,199, 0,115,195, 0,112,200, 0,109,203, 0, + 107,206, 0,106,208, 0,105,209, 0,104,210, 0,104,210, 0, + 105,209, 0,104,210, 0,103,211, 0,103,211, 0,103,211, 0, + 104,210, 0,106,208, 0,108,205, 0,111,202, 0,109,204, 0, + 106,208, 0,102,212, 0,101,214, 0,100,214, 0,101,213, 0, + 103,211, 0,106,208, 0,102,212, 0,100,215, 0, 98,217, 0, + 98,216, 0,102,213, 0,107,206, 0,114,197, 0,119,185, 0, + 117,191, 0,114,196, 0,113,199, 0,112,200, 0,112,200, 0, + 111,201, 0,111,201, 0,114,196, 0,115,194, 0,118,188, 0, + 122,175, 0,124,155, 16,124,152, 20,124,147, 26,123,139, 37, + 124,145, 29,123,169, 4,119,186, 0,114,197, 0,109,203, 0, + 106,208, 0,103,211, 0,102,213, 0,101,214, 0,101,214, 0, + 103,211, 0,105,209, 0,106,208, 0,108,205, 0,111,201, 0, + 114,196, 0,118,188, 0,122,178, 0,121,179, 0,120,182, 0, + 121,182, 0,122,177, 0,123,170, 3,124,160, 12,124,155, 16, + 124,164, 9,124,167, 6,124,167, 6,124,162, 10,124,150, 22, + 121,127, 58,114,104,197,111, 96,248,114,104,197,122,130, 53, + 124,145, 29,124,149, 24,124,145, 29,122,132, 48,115,107,129, + 87, 65,237,107, 89,252,115,107,129,118,117, 85,118,117, 85, + 115,107,129,109, 92,251, 87, 65,237, 99, 75,247,117,110,109, + 122,132, 48,124,143, 31,123,141, 34,122,130, 53,113,100,242, + 30, 43,203, 30, 20,155, 99, 75,247,113,100,242,117,110,109, + 117,110,109,114,104,197,111, 96,248,105, 84,252, 99, 75,247, + 117,110,109,124,143, 31,124,155, 16,124,155, 16,124,145, 29, + 121,125, 63,114,104,197,109, 92,251,114,104,197,123,137, 41, + 124,154, 18,124,164, 9,123,169, 4,122,178, 0,120,182, 0, + 120,183, 0,117,190, 0,115,194, 0,114,197, 0,112,200, 0, + 110,202, 0,109,203, 0,108,205, 0,107,206, 0,106,208, 0, + 105,209, 0,101,213, 0, 98,216, 0, 97,217, 0, 98,217, 0, + 101,214, 0,106,208, 0,104,210, 0,101,214, 0,100,215, 0, + 100,214, 0,102,213, 0,101,213, 0,103,212, 0,106,208, 0, + 110,202, 0,114,196, 0,118,188, 0,122,177, 0,124,157, 15, + 122,135, 44,119,119, 77,117,110,109,124,150, 22,123,172, 2, + 121,182, 0,119,185, 0,120,184, 0,121,179, 0,122,177, 0, + 122,178, 0,122,178, 0,122,178, 0,122,175, 0,123,170, 3, + 124,167, 6,124,157, 15,122,135, 44,107, 89,252, 30, 31,180, + 94, 70,242,109, 92,251,118,117, 85,122,130, 53,123,137, 41, + 123,141, 34,124,149, 24,124,157, 15,124,164, 9,123,168, 5, + 123,168, 5,124,165, 8,124,158, 13,124,147, 26,122,132, 48, + 114,104,197,111, 96,248,118,114, 96,122,135, 44,124,145, 29, + 124,147, 26,124,143, 31,122,135, 44,122,135, 44,123,137, 41, + 123,137, 41,123,137, 41,122,135, 44,122,130, 53,118,117, 85, + 109, 92,251,118,114, 96,124,149, 24,124,165, 8,122,175, 0, + 121,181, 0,119,186, 0,117,191, 0,114,197, 0,110,202, 0, + 108,205, 0,106,207, 0,105,209, 0,103,211, 0,101,213, 0, + 99,216, 0, 95,220, 0, 89,225, 0, 83,230, 0, 78,235, 0, + 74,237, 0, 72,239, 0, 74,238, 0, 76,236, 0, 80,232, 0, + 83,230, 0, 85,229, 0, 87,227, 0, 91,223, 0, 95,219, 0, + 100,215, 0,103,211, 0,105,209, 0,105,209, 0,105,209, 0, + 105,209, 0,106,208, 0,107,207, 0,109,203, 0,111,201, 0, + 110,203, 0,108,205, 0,106,208, 0,105,209, 0,105,209, 0, + 106,208, 0,107,206, 0,110,203, 0,112,200, 0,114,197, 0, + 113,199, 0,111,202, 0,109,204, 0,107,207, 0,105,209, 0, + 104,210, 0,103,211, 0,104,210, 0,105,209, 0,105,209, 0, + 104,210, 0,105,209, 0,106,207, 0,108,205, 0,106,207, 0, + 104,210, 0,103,211, 0,103,211, 0,102,212, 0,102,212, 0, + 103,211, 0,105,209, 0,105,209, 0,101,213, 0, 98,216, 0, + 97,218, 0, 97,217, 0,101,214, 0,106,208, 0,112,200, 0, + 118,189, 0,118,189, 0,115,194, 0,114,197, 0,112,199, 0, + 112,200, 0,112,200, 0,113,199, 0,114,197, 0,115,194, 0, + 118,188, 0,122,178, 0,124,161, 11,124,154, 18,124,145, 29, + 123,141, 34,124,164, 9,123,174, 1,118,188, 0,114,197, 0, + 109,204, 0,105,209, 0,102,212, 0,101,214, 0, 99,216, 0, + 99,216, 0,101,213, 0,106,208, 0,106,208, 0,107,207, 0, + 109,204, 0,112,200, 0,115,194, 0,119,185, 0,123,173, 1, + 123,174, 1,122,175, 0,123,172, 2,124,166, 7,124,154, 18, + 124,162, 10,123,168, 5,123,170, 3,123,169, 4,124,164, 9, + 124,150, 22,121,127, 58,118,114, 96,115,107,129,113,100,242, + 119,119, 77,122,132, 48,123,139, 37,122,135, 44,120,122, 70, + 109, 92,251,105, 84,252,114,104,197,120,122, 70,122,130, 53, + 122,132, 48,121,127, 58,118,114, 96,111, 96,248,118,114, 96, + 122,132, 48,124,143, 31,124,145, 29,123,141, 34,121,127, 58, + 111, 96,248, 30, 37,192, 30, 55,222,113,100,242,119,119, 77, + 121,125, 63,120,122, 70,118,114, 96,113,100,242,109, 92,251, + 109, 92,251,114,104,197,122,132, 48,124,149, 24,124,154, 18, + 124,145, 29,123,137, 41,121,127, 58,121,127, 58,122,135, 44, + 124,143, 31,124,154, 18,124,165, 8,123,174, 1,121,182, 0, + 119,186, 0,118,189, 0,114,196, 0,112,199, 0,111,202, 0, + 109,203, 0,109,204, 0,108,205, 0,107,206, 0,107,207, 0, + 106,208, 0,105,209, 0,103,211, 0,100,214, 0, 98,216, 0, + 99,216, 0,101,214, 0,106,208, 0,107,207, 0,105,209, 0, + 104,210, 0,104,210, 0,103,212, 0,103,212, 0,104,210, 0, + 108,205, 0,112,199, 0,116,193, 0,120,184, 0,123,172, 2, + 124,149, 24,123,137, 41,120,122, 70,118,117, 85,124,152, 20, + 123,171, 3,122,178, 0,121,180, 0,122,177, 0,122,176, 0, + 121,182, 0,120,182, 0,121,180, 0,122,178, 0,122,178, 0, + 121,180, 0,122,178, 0,123,170, 3,124,155, 16,121,125, 63, + 114,104,197,109, 92,251,114,104,197,118,117, 85,122,130, 53, + 123,141, 34,124,147, 26,124,154, 18,124,161, 11,123,168, 5, + 123,172, 2,123,174, 1,123,173, 1,123,170, 3,124,164, 9, + 124,154, 18,122,135, 44,105, 84,252,111, 96,248,119,119, 77, + 123,139, 37,124,147, 26,124,152, 20,124,154, 18,124,154, 18, + 124,155, 16,124,155, 16,124,154, 18,124,147, 26,123,137, 41, + 122,130, 53,118,114, 96,113,100,242,119,119, 77,124,149, 24, + 124,165, 8,122,175, 0,120,182, 0,118,189, 0,114,196, 0, + 111,202, 0,108,206, 0,105,209, 0,103,211, 0,101,213, 0, + 99,216, 0, 96,219, 0, 92,223, 0, 86,228, 0, 79,233, 0, + 74,238, 0, 70,241, 0, 69,242, 0, 70,241, 0, 72,239, 0, + 76,236, 0, 80,232, 0, 84,229, 0, 86,228, 0, 89,225, 0, + 92,222, 0, 96,219, 0,100,215, 0,102,213, 0,102,212, 0, + 103,212, 0,103,211, 0,104,210, 0,106,208, 0,108,205, 0, + 110,203, 0,107,206, 0,105,209, 0,103,211, 0,102,212, 0, + 102,212, 0,103,211, 0,105,209, 0,108,206, 0,110,202, 0, + 112,199, 0,114,197, 0,114,197, 0,111,201, 0,109,204, 0, + 107,207, 0,105,209, 0,104,210, 0,105,209, 0,106,208, 0, + 107,207, 0,106,208, 0,106,207, 0,107,207, 0,105,209, 0, + 103,212, 0,101,214, 0,100,214, 0,101,213, 0,103,211, 0, + 104,210, 0,105,209, 0,107,207, 0,104,210, 0,101,213, 0, + 98,216, 0, 97,218, 0, 97,217, 0,100,215, 0,104,210, 0, + 110,202, 0,116,193, 0,117,190, 0,117,192, 0,115,194, 0, + 114,197, 0,113,198, 0,113,199, 0,114,197, 0,114,196, 0, + 116,193, 0,118,188, 0,122,178, 0,124,167, 6,124,165, 8, + 124,162, 10,124,161, 11,122,175, 0,122,176, 0,119,187, 0, + 115,195, 0,111,202, 0,107,207, 0,104,210, 0,101,214, 0, + 99,216, 0, 98,217, 0,101,214, 0,105,209, 0,106,207, 0, + 106,208, 0,107,207, 0,109,204, 0,113,199, 0,117,191, 0, + 121,180, 0,123,171, 3,123,172, 2,123,169, 4,124,162, 10, + 124,160, 12,124,167, 6,123,172, 2,123,174, 1,123,171, 3, + 124,166, 7,124,154, 18,122,132, 48,117,110,109,114,104,197, + 109, 92,251,109, 92,251,117,110,109,118,117, 85,118,114, 96, + 113,100,242,111, 96,248,115,107,129,120,122, 70,122,135, 44, + 124,143, 31,124,145, 29,123,141, 34,122,130, 53,119,119, 77, + 121,127, 58,123,137, 41,123,141, 34,123,139, 37,122,135, 44, + 119,119, 77,105, 84,252, 30, 26,168,107, 89,252,120,122, 70, + 123,137, 41,123,141, 34,123,141, 34,122,135, 44,121,127, 58, + 118,114, 96,114,104,197,118,114, 96,122,132, 48,124,143, 31, + 124,147, 26,124,150, 22,124,150, 22,124,149, 24,124,149, 24, + 124,150, 22,124,154, 18,124,160, 12,123,168, 5,122,175, 0, + 121,182, 0,119,186, 0,116,193, 0,112,200, 0,110,203, 0, + 108,205, 0,108,206, 0,107,206, 0,107,206, 0,107,206, 0, + 107,207, 0,107,206, 0,107,207, 0,106,208, 0,103,212, 0, + 101,214, 0,100,214, 0,102,213, 0,105,209, 0,108,206, 0, + 107,207, 0,106,208, 0,105,209, 0,105,209, 0,106,208, 0, + 108,205, 0,112,200, 0,116,193, 0,119,186, 0,122,177, 0, + 124,161, 11,123,139, 37,122,135, 44,120,122, 70,120,122, 70, + 124,157, 15,123,171, 3,122,177, 0,122,175, 0,123,173, 1, + 121,181, 0,120,184, 0,120,184, 0,121,180, 0,121,182, 0, + 120,184, 0,120,184, 0,120,183, 0,122,178, 0,124,166, 7, + 124,145, 29,123,137, 41,121,125, 63,118,117, 85,122,130, 53, + 122,132, 48,124,143, 31,124,150, 22,124,154, 18,124,161, 11, + 124,167, 6,123,172, 2,122,176, 0,122,177, 0,122,175, 0, + 123,170, 3,124,164, 9,124,145, 29,113,100,242,111, 96,248, + 115,107,129,122,135, 44,124,154, 18,124,161, 11,124,164, 9, + 124,165, 8,124,166, 7,124,166, 7,124,164, 9,124,160, 12, + 124,150, 22,123,139, 37,122,130, 53,120,122, 70,120,122, 70, + 122,130, 53,124,150, 22,123,168, 5,121,180, 0,118,188, 0, + 116,193, 0,112,200, 0,108,205, 0,106,208, 0,103,212, 0, + 100,215, 0, 97,218, 0, 94,221, 0, 89,225, 0, 83,230, 0, + 77,235, 0, 72,239, 0, 68,242, 0, 66,243, 0, 67,243, 0, + 70,241, 0, 74,237, 0, 78,234, 0, 83,230, 0, 85,229, 0, + 87,227, 0, 90,224, 0, 94,221, 0, 97,218, 0,100,215, 0, + 101,214, 0,102,213, 0,102,212, 0,103,211, 0,105,209, 0, + 106,207, 0,108,205, 0,106,208, 0,104,210, 0,102,212, 0, + 101,214, 0,101,214, 0,102,213, 0,104,210, 0,107,207, 0, + 109,203, 0,111,201, 0,113,199, 0,114,197, 0,114,197, 0, + 113,198, 0,111,202, 0,109,204, 0,108,206, 0,108,206, 0, + 108,205, 0,109,204, 0,108,205, 0,108,205, 0,106,207, 0, + 104,210, 0,101,213, 0,100,215, 0,100,215, 0,102,213, 0, + 105,209, 0,105,209, 0,106,207, 0,107,207, 0,104,210, 0, + 102,213, 0,100,215, 0, 98,216, 0, 99,216, 0,100,214, 0, + 103,211, 0,108,205, 0,114,197, 0,116,192, 0,115,194, 0, + 114,196, 0,114,197, 0,113,198, 0,113,198, 0,114,197, 0, + 116,193, 0,117,190, 0,120,184, 0,122,176, 0,123,171, 3, + 123,172, 2,123,172, 2,123,173, 1,121,181, 0,121,180, 0, + 120,182, 0,117,190, 0,114,196, 0,111,202, 0,107,207, 0, + 103,211, 0,100,214, 0, 99,215, 0,101,214, 0,105,209, 0, + 107,206, 0,106,208, 0,106,208, 0,108,206, 0,111,201, 0, + 116,193, 0,120,183, 0,123,171, 3,123,172, 2,123,169, 4, + 124,162, 10,124,164, 9,123,170, 3,123,174, 1,122,175, 0, + 123,172, 2,124,167, 6,124,155, 16,123,137, 41,118,114, 96, + 109, 92,251,102, 80,250, 94, 70,242, 99, 75,247,105, 84,252, + 111, 96,248,115,107,129,118,114, 96,119,119, 77,122,132, 48, + 124,143, 31,124,150, 22,124,152, 20,124,149, 24,123,139, 37, + 121,127, 58,122,130, 53,122,135, 44,122,132, 48,121,127, 58, + 119,119, 77,113,100,242, 87, 65,237, 87, 65,237,118,114, 96, + 123,139, 37,124,149, 24,124,152, 20,124,152, 20,124,149, 24, + 123,141, 34,122,135, 44,121,127, 58,122,130, 53,123,141, 34, + 124,152, 20,124,160, 12,124,162, 10,124,162, 10,124,160, 12, + 124,157, 15,124,157, 15,124,157, 15,124,160, 12,124,165, 8, + 123,171, 3,122,178, 0,119,186, 0,115,195, 0,111,202, 0, + 108,205, 0,107,207, 0,107,207, 0,107,207, 0,108,206, 0, + 108,205, 0,108,206, 0,108,206, 0,109,204, 0,109,204, 0, + 106,208, 0,104,210, 0,103,212, 0,103,211, 0,106,208, 0, + 108,205, 0,107,206, 0,107,207, 0,107,207, 0,107,206, 0, + 109,203, 0,113,199, 0,117,192, 0,120,184, 0,122,175, 0, + 124,162, 10,123,141, 34,122,135, 44,122,132, 48,120,122, 70, + 122,135, 44,124,164, 9,123,173, 1,122,176, 0,123,172, 2, + 122,178, 0,120,183, 0,119,185, 0,120,182, 0,121,181, 0, + 120,184, 0,119,186, 0,119,186, 0,120,184, 0,121,179, 0, + 123,170, 3,124,158, 13,124,152, 20,123,139, 37,121,127, 58, + 123,139, 37,124,143, 31,124,145, 29,124,149, 24,124,150, 22, + 124,155, 16,124,162, 10,123,168, 5,123,172, 2,122,175, 0, + 123,174, 1,123,171, 3,124,165, 8,124,147, 26,113,100,242, + 111, 96,248,115,107,129,123,137, 41,124,155, 16,124,165, 8, + 124,167, 6,123,168, 5,123,169, 4,123,169, 4,123,168, 5, + 124,165, 8,124,160, 12,124,149, 24,123,141, 34,123,139, 37, + 123,141, 34,124,147, 26,124,154, 18,124,167, 6,121,179, 0, + 118,188, 0,115,194, 0,112,200, 0,108,206, 0,103,211, 0, + 100,215, 0, 96,219, 0, 93,221, 0, 92,223, 0, 88,226, 0, + 82,231, 0, 76,236, 0, 71,240, 0, 67,243, 0, 66,244, 0, + 67,243, 0, 70,241, 0, 74,238, 0, 78,234, 0, 83,230, 0, + 85,229, 0, 86,228, 0, 88,226, 0, 92,223, 0, 95,219, 0, + 99,216, 0,101,214, 0,102,213, 0,102,212, 0,103,212, 0, + 104,210, 0,105,209, 0,107,207, 0,106,208, 0,104,210, 0, + 102,213, 0,100,214, 0,100,214, 0,102,213, 0,104,210, 0, + 107,207, 0,110,203, 0,112,200, 0,113,199, 0,113,198, 0, + 113,198, 0,113,198, 0,113,198, 0,113,198, 0,112,199, 0, + 112,199, 0,113,199, 0,110,202, 0,110,203, 0,110,202, 0, + 108,205, 0,105,209, 0,102,213, 0,100,214, 0,101,214, 0, + 103,211, 0,107,207, 0,107,207, 0,108,206, 0,107,207, 0, + 105,209, 0,103,211, 0,102,212, 0,101,213, 0,101,214, 0, + 102,212, 0,104,210, 0,108,206, 0,112,200, 0,115,194, 0, + 115,195, 0,114,196, 0,114,197, 0,113,198, 0,114,197, 0, + 114,196, 0,116,193, 0,118,188, 0,121,181, 0,123,172, 2, + 123,171, 3,122,175, 0,122,178, 0,121,179, 0,120,183, 0, + 121,181, 0,122,175, 0,121,180, 0,119,187, 0,116,193, 0, + 112,200, 0,108,205, 0,104,210, 0,102,212, 0,103,212, 0, + 106,208, 0,109,204, 0,107,206, 0,107,207, 0,108,205, 0, + 112,200, 0,117,192, 0,121,182, 0,122,175, 0,122,175, 0, + 123,172, 2,124,164, 9,124,164, 9,123,169, 4,123,173, 1, + 123,174, 1,123,171, 3,124,167, 6,124,158, 13,123,139, 37, + 119,119, 77,114,104,197,111, 96,248,109, 92,251,111, 96,248, + 117,110,109,119,119, 77,120,122, 70,121,125, 63,122,130, 53, + 123,139, 37,124,149, 24,124,154, 18,124,155, 16,124,152, 20, + 123,141, 34,120,122, 70,119,119, 77,119,119, 77,117,110,109, + 114,104,197,111, 96,248, 99, 75,247, 94, 70,242,107, 89,252, + 121,127, 58,124,149, 24,124,157, 15,124,158, 13,124,158, 13, + 124,157, 15,124,158, 13,124,150, 22,124,143, 31,124,145, 29, + 124,154, 18,124,161, 11,124,166, 7,124,167, 6,124,166, 7, + 124,162, 10,124,158, 13,124,157, 15,124,154, 18,124,152, 20, + 124,155, 16,124,161, 11,123,170, 3,120,184, 0,115,194, 0, + 111,202, 0,108,205, 0,107,207, 0,107,207, 0,107,207, 0, + 108,205, 0,107,207, 0,107,207, 0,108,205, 0,109,204, 0, + 110,203, 0,110,202, 0,108,205, 0,107,207, 0,106,207, 0, + 108,206, 0,109,203, 0,109,204, 0,108,205, 0,109,203, 0, + 111,201, 0,114,197, 0,118,189, 0,121,181, 0,123,174, 1, + 124,158, 13,122,135, 44,119,119, 77,122,130, 53,122,132, 48, + 122,135, 44,124,149, 24,123,169, 4,122,176, 0,122,177, 0, + 123,174, 1,121,179, 0,120,182, 0,120,183, 0,121,179, 0, + 121,180, 0,121,182, 0,120,183, 0,120,184, 0,121,182, 0, + 122,178, 0,123,168, 5,124,161, 11,124,155, 16,123,141, 34, + 123,141, 34,124,149, 24,124,150, 22,124,147, 26,124,147, 26, + 124,145, 29,124,147, 26,124,152, 20,124,158, 13,124,165, 8, + 123,168, 5,123,168, 5,124,166, 7,124,158, 13,123,137, 41, + 105, 84,252,111, 96,248,118,117, 85,122,135, 44,124,154, 18, + 124,162, 10,124,165, 8,124,166, 7,124,167, 6,124,167, 6, + 124,167, 6,124,166, 7,124,162, 10,124,157, 15,124,143, 31, + 124,147, 26,124,152, 20,124,157, 15,124,161, 11,124,165, 8, + 122,178, 0,119,187, 0,115,194, 0,111,201, 0,106,208, 0, + 101,214, 0, 96,219, 0, 93,222, 0, 90,224, 0, 89,226, 0, + 88,226, 0, 82,231, 0, 76,236, 0, 72,239, 0, 68,242, 0, + 67,243, 0, 69,242, 0, 72,239, 0, 76,236, 0, 81,232, 0, + 85,229, 0, 84,229, 0, 85,229, 0, 87,227, 0, 91,223, 0, + 95,219, 0,100,215, 0,102,212, 0,103,211, 0,103,211, 0, + 103,211, 0,103,211, 0,104,210, 0,105,209, 0,106,207, 0, + 104,210, 0,102,212, 0,101,214, 0,101,214, 0,102,212, 0, + 105,209, 0,108,205, 0,111,202, 0,111,201, 0,113,199, 0, + 114,197, 0,114,197, 0,113,198, 0,113,198, 0,114,197, 0, + 115,194, 0,117,191, 0,114,196, 0,112,199, 0,111,201, 0, + 111,201, 0,111,201, 0,108,206, 0,105,209, 0,103,211, 0, + 105,209, 0,107,207, 0,109,204, 0,109,204, 0,109,204, 0, + 107,207, 0,105,209, 0,105,209, 0,105,209, 0,105,209, 0, + 105,209, 0,105,209, 0,106,208, 0,108,205, 0,112,200, 0, + 116,193, 0,115,194, 0,114,196, 0,114,196, 0,114,196, 0, + 114,196, 0,115,194, 0,116,192, 0,118,188, 0,121,179, 0, + 124,167, 6,123,168, 5,122,175, 0,121,179, 0,121,182, 0, + 121,181, 0,122,178, 0,123,170, 3,124,162, 10,122,178, 0, + 119,186, 0,117,191, 0,113,198, 0,109,204, 0,106,208, 0, + 106,208, 0,108,206, 0,111,201, 0,110,203, 0,109,203, 0, + 111,202, 0,114,196, 0,118,188, 0,122,178, 0,121,179, 0, + 121,179, 0,122,176, 0,123,168, 5,124,158, 13,124,166, 7, + 123,171, 3,122,176, 0,122,176, 0,123,172, 2,124,164, 9, + 124,149, 24,120,122, 70,115,107,129,115,107,129,115,107,129, + 118,114, 96,120,122, 70,122,130, 53,122,130, 53,121,127, 58, + 122,132, 48,123,139, 37,124,147, 26,124,154, 18,124,155, 16, + 124,152, 20,123,141, 34,118,117, 85,113,100,242,107, 89,252, + 94, 70,242,105, 84,252,109, 92,251,109, 92,251,107, 89,252, + 113,100,242,122,132, 48,124,152, 20,124,158, 13,124,161, 11, + 124,162, 10,123,169, 4,123,171, 3,124,166, 7,124,152, 20, + 124,155, 16,124,161, 11,124,166, 7,123,169, 4,123,168, 5, + 124,165, 8,124,160, 12,124,154, 18,124,149, 24,123,141, 34, + 123,137, 41,124,147, 26,124,149, 24,124,162, 10,121,179, 0, + 117,191, 0,112,199, 0,109,203, 0,108,206, 0,107,206, 0, + 108,206, 0,107,207, 0,106,208, 0,106,208, 0,108,206, 0, + 108,205, 0,109,204, 0,110,202, 0,113,199, 0,111,201, 0, + 110,202, 0,111,202, 0,112,200, 0,111,201, 0,111,201, 0, + 113,199, 0,115,194, 0,118,188, 0,122,178, 0,123,168, 5, + 124,158, 13,122,132, 48,102, 80,250,115,107,129,121,125, 63, + 122,135, 44,124,154, 18,124,161, 11,123,174, 1,121,180, 0, + 121,179, 0,122,176, 0,122,178, 0,121,179, 0,122,178, 0, + 122,176, 0,122,176, 0,122,177, 0,122,178, 0,122,178, 0, + 122,176, 0,123,171, 3,124,161, 11,124,157, 15,124,150, 22, + 123,137, 41,124,152, 20,124,158, 13,124,157, 15,124,150, 22, + 124,145, 29,123,139, 37,124,145, 29,123,141, 34,124,145, 29, + 124,150, 22,124,155, 16,124,155, 16,124,152, 20,123,141, 34, + 118,114, 96,105, 84,252,114,104,197,121,125, 63,122,135, 44, + 124,145, 29,124,152, 20,124,155, 16,124,157, 15,124,158, 13, + 124,158, 13,124,160, 12,124,161, 11,124,161, 11,124,158, 13, + 124,149, 24,124,149, 24,124,155, 16,124,160, 12,124,164, 9, + 124,167, 6,123,174, 1,119,185, 0,116,193, 0,111,202, 0, + 105,209, 0,100,215, 0, 94,220, 0, 91,224, 0, 88,226, 0, + 87,227, 0, 87,227, 0, 83,230, 0, 78,234, 0, 74,238, 0, + 71,240, 0, 71,240, 0, 73,238, 0, 76,236, 0, 81,232, 0, + 85,228, 0, 86,228, 0, 85,229, 0, 86,228, 0, 88,226, 0, + 92,222, 0, 97,218, 0,101,214, 0,103,211, 0,104,210, 0, + 105,209, 0,105,209, 0,105,209, 0,104,210, 0,105,209, 0, + 106,207, 0,106,208, 0,103,211, 0,102,212, 0,102,212, 0, + 104,210, 0,107,207, 0,110,202, 0,111,202, 0,111,202, 0, + 112,200, 0,114,197, 0,114,196, 0,114,196, 0,114,196, 0, + 115,194, 0,117,192, 0,116,193, 0,114,197, 0,113,199, 0, + 113,199, 0,113,198, 0,114,196, 0,113,199, 0,109,203, 0, + 108,205, 0,109,203, 0,112,200, 0,112,200, 0,111,201, 0, + 109,203, 0,107,207, 0,106,207, 0,103,211, 0,102,212, 0, + 102,212, 0,104,210, 0,108,206, 0,109,204, 0,110,202, 0, + 113,199, 0,117,192, 0,117,192, 0,116,193, 0,116,193, 0, + 116,193, 0,116,193, 0,117,192, 0,117,191, 0,119,187, 0, + 121,179, 0,124,166, 7,124,162, 10,123,171, 3,122,177, 0, + 121,180, 0,122,176, 0,123,172, 2,123,172, 2,123,174, 1, + 121,180, 0,119,187, 0,117,191, 0,117,192, 0,114,196, 0, + 111,201, 0,110,203, 0,110,202, 0,112,199, 0,113,199, 0, + 113,198, 0,114,196, 0,117,191, 0,121,181, 0,120,182, 0, + 120,184, 0,120,183, 0,121,179, 0,123,171, 3,124,164, 9, + 123,168, 5,122,175, 0,122,178, 0,122,178, 0,123,174, 1, + 124,166, 7,124,150, 22,121,125, 63,113,100,242,114,104,197, + 115,107,129,118,114, 96,121,125, 63,122,130, 53,121,127, 58, + 121,125, 63,121,125, 63,122,132, 48,124,143, 31,124,150, 22, + 124,152, 20,124,149, 24,123,137, 41,115,107,129, 87, 65,237, + 87, 65,237,105, 84,252,114,104,197,117,110,109,114,104,197, + 109, 92,251,113,100,242,122,130, 53,124,149, 24,124,157, 15, + 124,160, 12,123,171, 3,122,178, 0,122,178, 0,123,174, 1, + 124,162, 10,124,161, 11,124,166, 7,123,169, 4,123,169, 4, + 124,167, 6,124,161, 11,124,150, 22,124,143, 31,122,132, 48, + 123,137, 41,124,149, 24,124,155, 16,124,162, 10,123,169, 4, + 123,173, 1,119,186, 0,115,195, 0,111,201, 0,109,204, 0, + 108,205, 0,108,205, 0,107,207, 0,106,208, 0,106,208, 0, + 108,205, 0,108,206, 0,108,205, 0,109,203, 0,112,200, 0, + 114,196, 0,115,194, 0,115,195, 0,115,194, 0,115,195, 0, + 115,194, 0,117,192, 0,119,186, 0,122,176, 0,124,158, 13, + 124,143, 31,121,125, 63,102, 80,250, 94, 70,242,113,100,242, + 122,132, 48,124,157, 15,124,167, 6,123,171, 3,121,180, 0, + 120,184, 0,120,184, 0,121,179, 0,122,176, 0,123,174, 1, + 123,170, 3,123,170, 3,123,169, 4,123,169, 4,123,169, 4, + 123,168, 5,124,166, 7,124,160, 12,124,145, 29,124,147, 26, + 123,137, 41,124,150, 22,124,161, 11,124,164, 9,124,162, 10, + 124,154, 18,124,147, 26,123,141, 34,124,149, 24,124,147, 26, + 123,139, 37,122,130, 53,122,135, 44,122,135, 44,121,127, 58, + 117,110,109, 99, 75,247,111, 96,248,118,117, 85,122,132, 48, + 122,135, 44,122,132, 48,122,135, 44,122,135, 44,123,137, 41, + 123,139, 37,124,150, 22,124,155, 16,124,155, 16,124,152, 20, + 124,154, 18,124,149, 24,123,141, 34,124,150, 22,124,158, 13, + 124,162, 10,124,166, 7,124,167, 6,121,180, 0,117,191, 0, + 112,200, 0,106,208, 0,100,215, 0, 94,220, 0, 90,224, 0, + 87,227, 0, 87,227, 0, 87,227, 0, 85,229, 0, 80,233, 0, + 77,235, 0, 75,237, 0, 76,236, 0, 79,234, 0, 83,230, 0, + 87,227, 0, 90,224, 0, 88,226, 0, 87,227, 0, 87,227, 0, + 90,224, 0, 94,221, 0, 99,215, 0,103,211, 0,103,211, 0, + 103,211, 0,105,209, 0,107,207, 0,106,207, 0,106,208, 0, + 106,208, 0,107,206, 0,107,206, 0,105,209, 0,104,210, 0, + 104,210, 0,106,208, 0,109,204, 0,112,200, 0,112,199, 0, + 112,200, 0,113,198, 0,115,195, 0,115,194, 0,115,194, 0, + 115,194, 0,116,192, 0,117,190, 0,115,194, 0,113,198, 0, + 112,200, 0,112,200, 0,113,198, 0,115,194, 0,117,190, 0, + 115,195, 0,114,197, 0,115,195, 0,115,195, 0,114,196, 0, + 112,200, 0,109,204, 0,107,206, 0,107,207, 0,103,211, 0, + 101,214, 0,100,215, 0,101,214, 0,105,209, 0,109,203, 0, + 113,199, 0,114,196, 0,118,189, 0,118,188, 0,118,189, 0, + 118,189, 0,118,189, 0,118,189, 0,118,188, 0,119,187, 0, + 120,184, 0,122,178, 0,124,165, 8,124,155, 16,124,164, 9, + 123,170, 3,123,174, 1,123,168, 5,122,177, 0,121,182, 0, + 120,184, 0,121,182, 0,119,186, 0,118,188, 0,118,188, 0, + 118,188, 0,115,194, 0,114,197, 0,113,198, 0,114,196, 0, + 116,193, 0,116,192, 0,118,189, 0,120,183, 0,120,183, 0, + 120,184, 0,119,186, 0,119,185, 0,120,184, 0,121,182, 0, + 122,178, 0,123,171, 3,122,177, 0,121,179, 0,122,178, 0, + 123,173, 1,124,164, 9,124,145, 29,118,114, 96, 94, 70,242, + 99, 75,247,105, 84,252,113,100,242,118,117, 85,119,119, 77, + 118,117, 85,117,110,109,117,110,109,119,119, 77,122,132, 48, + 124,143, 31,124,149, 24,124,147, 26,122,135, 44,114,104,197, + 30, 31,180,102, 80,250,109, 92,251,115,107,129,115,107,129, + 113,100,242,102, 80,250,107, 89,252,118,117, 85,123,139, 37, + 124,154, 18,123,168, 5,122,177, 0,121,181, 0,121,182, 0, + 122,178, 0,124,166, 7,123,168, 5,123,170, 3,123,171, 3, + 123,170, 3,124,165, 8,124,154, 18,123,139, 37,121,125, 63, + 123,137, 41,124,149, 24,124,157, 15,124,161, 11,123,170, 3, + 122,175, 0,122,178, 0,121,181, 0,117,191, 0,113,198, 0, + 111,202, 0,109,204, 0,108,205, 0,108,205, 0,107,206, 0, + 108,205, 0,107,207, 0,106,207, 0,107,207, 0,108,205, 0, + 111,202, 0,114,197, 0,117,191, 0,119,186, 0,119,186, 0, + 119,186, 0,119,186, 0,120,182, 0,123,174, 1,124,160, 12, + 122,132, 48, 99, 75,247, 30, 37,192, 30, 43,203,109, 92,251, + 122,135, 44,124,158, 13,123,170, 3,122,177, 0,122,178, 0, + 119,186, 0,118,189, 0,118,188, 0,120,184, 0,122,177, 0, + 123,168, 5,124,166, 7,124,166, 7,123,170, 3,123,170, 3, + 124,167, 6,124,160, 12,124,154, 18,124,143, 31,121,127, 58, + 121,127, 58,124,145, 29,124,158, 13,124,167, 6,123,169, 4, + 124,166, 7,124,161, 11,124,152, 20,123,139, 37,124,147, 26, + 124,145, 29,123,137, 41,120,122, 70,117,110,109,115,107,129, + 109, 92,251, 69, 60,230,105, 84,252,113,100,242,121,125, 63, + 122,135, 44,122,135, 44,121,125, 63,115,107,129,114,104,197, + 122,132, 48,124,149, 24,124,160, 12,124,164, 9,124,165, 8, + 124,161, 11,124,152, 20,123,139, 37,121,127, 58,123,139, 37, + 124,149, 24,124,155, 16,124,158, 13,124,160, 12,123,171, 3, + 120,184, 0,115,195, 0,109,204, 0,102,212, 0, 97,218, 0, + 92,222, 0, 89,225, 0, 89,226, 0, 89,225, 0, 85,228, 0, + 82,231, 0, 80,233, 0, 80,233, 0, 82,231, 0, 85,228, 0, + 90,224, 0, 95,220, 0, 93,221, 0, 91,223, 0, 90,224, 0, + 91,223, 0, 93,221, 0, 97,217, 0,102,212, 0,106,207, 0, + 105,209, 0,105,209, 0,106,207, 0,108,206, 0,109,203, 0, + 109,204, 0,109,204, 0,111,202, 0,109,204, 0,107,207, 0, + 106,208, 0,106,208, 0,108,206, 0,110,202, 0,114,197, 0, + 116,193, 0,115,194, 0,116,192, 0,117,191, 0,116,192, 0, + 116,193, 0,116,193, 0,117,191, 0,119,187, 0,117,192, 0, + 114,196, 0,112,199, 0,112,200, 0,113,198, 0,115,194, 0, + 118,189, 0,120,184, 0,119,186, 0,118,188, 0,117,190, 0, + 114,196, 0,111,201, 0,109,204, 0,107,206, 0,108,206, 0, + 104,210, 0,101,214, 0, 99,215, 0,100,215, 0,103,212, 0, + 107,207, 0,112,199, 0,117,191, 0,120,184, 0,121,182, 0, + 119,186, 0,118,188, 0,117,190, 0,118,189, 0,119,186, 0, + 121,181, 0,122,178, 0,123,172, 2,124,161, 11,124,152, 20, + 124,154, 18,124,161, 11,124,166, 7,123,172, 2,121,180, 0, + 119,185, 0,119,187, 0,119,185, 0,121,179, 0,121,182, 0, + 121,182, 0,121,180, 0,119,187, 0,117,191, 0,116,192, 0, + 117,192, 0,118,189, 0,119,186, 0,120,183, 0,121,180, 0, + 121,180, 0,120,182, 0,120,184, 0,118,188, 0,118,189, 0, + 118,188, 0,119,185, 0,121,181, 0,122,178, 0,122,178, 0, + 122,177, 0,123,170, 3,124,158, 13,124,147, 26,122,130, 53, + 109, 92,251, 94, 70,242, 87, 65,237,102, 80,250,113,100,242, + 115,107,129,117,110,109,118,117, 85,122,130, 53,122,132, 48, + 121,127, 58,123,139, 37,124,145, 29,124,143, 31,122,132, 48, + 113,100,242, 94, 70,242,107, 89,252,113,100,242,115,107,129, + 114,104,197,109, 92,251,107, 89,252,117,110,109,122,130, 53, + 124,147, 26,124,161, 11,123,172, 2,121,179, 0,120,183, 0, + 120,183, 0,121,179, 0,123,168, 5,123,170, 3,123,171, 3, + 123,171, 3,123,168, 5,124,160, 12,124,145, 29,122,132, 48, + 123,141, 34,124,149, 24,124,157, 15,124,161, 11,124,164, 9, + 123,171, 3,122,175, 0,122,178, 0,121,179, 0,118,188, 0, + 115,194, 0,112,200, 0,110,203, 0,108,205, 0,107,206, 0, + 107,207, 0,106,208, 0,105,209, 0,105,209, 0,105,209, 0, + 107,206, 0,110,202, 0,114,197, 0,117,190, 0,120,183, 0, + 122,175, 0,122,176, 0,122,176, 0,123,173, 1,124,166, 7, + 124,152, 20,121,127, 58,105, 84,252,107, 89,252,120,122, 70, + 124,149, 24,124,165, 8,122,175, 0,121,182, 0,120,184, 0, + 120,184, 0,118,189, 0,117,191, 0,117,190, 0,119,186, 0, + 121,179, 0,123,169, 4,123,170, 3,123,174, 1,122,177, 0, + 122,176, 0,123,172, 2,124,166, 7,124,154, 18,123,137, 41, + 120,122, 70,123,137, 41,124,150, 22,124,162, 10,123,169, 4, + 123,172, 2,123,172, 2,123,170, 3,124,162, 10,124,150, 22, + 123,137, 41,122,135, 44,121,125, 63,118,114, 96,113,100,242, + 107, 89,252, 99, 75,247, 94, 70,242,105, 84,252,113,100,242, + 121,125, 63,122,132, 48,122,130, 53,119,119, 77,118,117, 85, + 122,132, 48,123,141, 34,124,155, 16,124,164, 9,123,168, 5, + 123,169, 4,123,168, 5,124,164, 9,124,155, 16,124,143, 31, + 124,143, 31,124,149, 24,124,155, 16,124,160, 12,124,162, 10, + 123,171, 3,119,185, 0,115,194, 0,112,200, 0,106,208, 0, + 100,215, 0, 95,219, 0, 92,222, 0, 92,223, 0, 91,223, 0, + 88,226, 0, 85,228, 0, 85,229, 0, 85,228, 0, 88,226, 0, + 92,222, 0, 98,217, 0,100,215, 0, 99,216, 0, 97,218, 0, + 96,219, 0, 96,219, 0, 98,217, 0,101,213, 0,106,208, 0, + 109,203, 0,109,204, 0,109,204, 0,109,203, 0,110,202, 0, + 112,200, 0,112,199, 0,113,198, 0,113,198, 0,111,201, 0, + 110,203, 0,109,204, 0,109,203, 0,111,202, 0,113,198, 0, + 116,193, 0,118,189, 0,119,187, 0,119,187, 0,118,189, 0, + 117,190, 0,117,191, 0,117,191, 0,118,189, 0,119,185, 0, + 118,188, 0,116,193, 0,114,196, 0,113,198, 0,114,197, 0, + 116,193, 0,118,188, 0,120,184, 0,120,182, 0,119,186, 0, + 117,191, 0,114,197, 0,111,201, 0,108,205, 0,107,207, 0, + 107,206, 0,106,207, 0,103,211, 0,101,214, 0,101,214, 0, + 103,211, 0,107,207, 0,112,200, 0,116,193, 0,119,185, 0, + 120,184, 0,119,187, 0,118,189, 0,117,190, 0,118,189, 0, + 119,186, 0,121,181, 0,123,171, 3,124,166, 7,124,155, 16, + 124,143, 31,124,150, 22,124,157, 15,124,164, 9,123,170, 3, + 122,178, 0,120,184, 0,119,186, 0,120,184, 0,122,178, 0, + 123,170, 3,123,169, 4,123,169, 4,121,179, 0,120,184, 0, + 119,186, 0,119,185, 0,120,183, 0,121,179, 0,122,175, 0, + 123,171, 3,123,171, 3,122,178, 0,119,185, 0,118,189, 0, + 117,191, 0,117,191, 0,118,189, 0,119,186, 0,120,183, 0, + 121,179, 0,122,175, 0,123,169, 4,124,162, 10,124,152, 20, + 122,135, 44,111, 96,248,102, 80,250,105, 84,252,114,104,197, + 118,117, 85,120,122, 70,120,122, 70,120,122, 70,122,132, 48, + 123,139, 37,123,137, 41,123,139, 37,124,143, 31,123,139, 37, + 121,125, 63,118,114, 96,117,110,109,115,107,129,118,114, 96, + 118,114, 96,118,114, 96,111, 96,248,111, 96,248,118,114, 96, + 122,135, 44,124,150, 22,124,165, 8,122,175, 0,121,182, 0, + 120,184, 0,120,184, 0,121,180, 0,123,171, 3,124,166, 7, + 124,167, 6,124,167, 6,124,162, 10,124,152, 20,122,132, 48, + 124,145, 29,124,152, 20,124,157, 15,124,161, 11,124,161, 11, + 124,160, 12,124,167, 6,123,170, 3,123,171, 3,123,174, 1, + 120,184, 0,117,192, 0,114,197, 0,111,201, 0,109,204, 0, + 107,206, 0,106,208, 0,105,209, 0,104,210, 0,104,210, 0, + 105,209, 0,108,206, 0,111,201, 0,115,194, 0,119,186, 0, + 122,178, 0,123,168, 5,124,165, 8,124,167, 6,124,166, 7, + 124,162, 10,124,154, 18,123,137, 41,123,141, 34,124,154, 18, + 124,167, 6,122,176, 0,120,183, 0,118,188, 0,117,190, 0, + 117,191, 0,117,191, 0,117,190, 0,117,191, 0,118,189, 0, + 119,185, 0,122,178, 0,123,172, 2,123,174, 1,122,178, 0, + 121,179, 0,122,178, 0,123,173, 1,124,166, 7,124,154, 18, + 122,135, 44,120,122, 70,123,137, 41,124,150, 22,124,162, 10, + 123,169, 4,122,177, 0,121,179, 0,122,177, 0,123,171, 3, + 124,162, 10,124,152, 20,123,137, 41,119,119, 77,118,117, 85, + 119,119, 77,118,117, 85,117,110,109,114,104,197,109, 92,251, + 109, 92,251,118,114, 96,119,119, 77,118,117, 85,122,132, 48, + 124,154, 18,124,162, 10,124,165, 8,124,166, 7,124,165, 8, + 123,169, 4,123,170, 3,123,170, 3,123,168, 5,124,166, 7, + 124,158, 13,124,155, 16,124,160, 12,124,164, 9,124,165, 8, + 124,167, 6,123,169, 4,120,183, 0,116,193, 0,112,199, 0, + 108,205, 0,103,212, 0, 98,216, 0, 96,219, 0, 95,220, 0, + 94,220, 0, 93,222, 0, 92,223, 0, 92,223, 0, 93,221, 0, + 96,219, 0,100,214, 0,105,209, 0,107,207, 0,106,208, 0, + 105,209, 0,103,211, 0,103,211, 0,104,210, 0,107,207, 0, + 110,203, 0,113,198, 0,114,197, 0,113,198, 0,113,198, 0, + 114,196, 0,115,194, 0,116,193, 0,117,192, 0,117,191, 0, + 116,193, 0,114,196, 0,114,196, 0,114,196, 0,116,193, 0, + 118,189, 0,120,184, 0,121,179, 0,122,178, 0,121,180, 0, + 120,183, 0,119,185, 0,119,186, 0,119,186, 0,120,184, 0, + 121,180, 0,120,183, 0,118,188, 0,117,192, 0,116,193, 0, + 116,192, 0,118,189, 0,120,184, 0,121,181, 0,121,181, 0, + 119,185, 0,117,191, 0,114,197, 0,110,202, 0,108,205, 0, + 106,207, 0,107,207, 0,108,205, 0,107,207, 0,104,210, 0, + 104,210, 0,105,209, 0,108,205, 0,112,199, 0,117,192, 0, + 120,184, 0,120,182, 0,119,185, 0,119,187, 0,118,188, 0, + 119,186, 0,120,183, 0,122,177, 0,124,167, 6,124,161, 11, + 124,150, 22,122,132, 48,124,143, 31,124,152, 20,124,161, 11, + 124,162, 10,123,172, 2,121,179, 0,120,182, 0,121,181, 0, + 122,176, 0,124,164, 9,124,149, 24,124,157, 15,123,169, 4, + 122,175, 0,122,177, 0,122,176, 0,123,172, 2,123,168, 5, + 124,166, 7,124,157, 15,124,164, 9,123,174, 1,121,182, 0, + 119,186, 0,118,189, 0,117,190, 0,118,189, 0,118,188, 0, + 119,186, 0,120,184, 0,121,179, 0,123,173, 1,124,165, 8, + 124,152, 20,122,130, 53,109, 92,251, 94, 70,242,113,100,242, + 119,119, 77,121,127, 58,122,130, 53,122,130, 53,121,125, 63, + 122,130, 53,123,137, 41,123,137, 41,123,141, 34,124,143, 31, + 123,137, 41,123,137, 41,123,137, 41,122,132, 48,120,122, 70, + 121,127, 58,121,125, 63,121,125, 63,118,114, 96,109, 92,251, + 118,117, 85,122,130, 53,124,149, 24,124,164, 9,122,175, 0, + 121,181, 0,120,184, 0,120,184, 0,121,181, 0,123,172, 2, + 124,158, 13,124,158, 13,124,158, 13,124,152, 20,123,141, 34, + 122,135, 44,124,147, 26,124,155, 16,124,160, 12,124,160, 12, + 124,158, 13,124,150, 22,124,157, 15,124,158, 13,124,160, 12, + 123,169, 4,121,180, 0,119,187, 0,116,193, 0,114,197, 0, + 111,201, 0,109,204, 0,107,207, 0,105,209, 0,104,210, 0, + 105,209, 0,106,207, 0,110,203, 0,114,197, 0,118,189, 0, + 122,178, 0,123,168, 5,124,157, 15,124,149, 24,124,154, 18, + 124,154, 18,124,154, 18,124,147, 26,124,161, 11,123,171, 3, + 121,179, 0,119,186, 0,117,191, 0,115,194, 0,114,196, 0, + 114,197, 0,114,197, 0,114,197, 0,115,195, 0,116,193, 0, + 118,189, 0,119,185, 0,121,179, 0,121,179, 0,121,180, 0, + 121,179, 0,121,179, 0,122,177, 0,123,171, 3,124,162, 10, + 124,147, 26,121,127, 58,118,114, 96,122,130, 53,124,145, 29, + 124,158, 13,123,173, 1,121,181, 0,120,183, 0,121,182, 0, + 122,177, 0,123,170, 3,124,161, 11,124,145, 29,122,130, 53, + 120,122, 70,122,130, 53,122,135, 44,122,132, 48,120,122, 70, + 113,100,242,102, 80,250,109, 92,251,111, 96,248,122,132, 48, + 124,158, 13,123,171, 3,122,177, 0,122,178, 0,122,177, 0, + 123,173, 1,124,167, 6,124,166, 7,123,168, 5,123,169, 4, + 123,168, 5,124,164, 9,124,161, 11,124,166, 7,124,167, 6, + 124,167, 6,124,167, 6,124,167, 6,122,178, 0,118,189, 0, + 114,197, 0,110,202, 0,106,208, 0,102,213, 0, 99,216, 0, + 98,217, 0, 98,216, 0, 99,216, 0, 99,216, 0,100,215, 0, + 102,212, 0,105,209, 0,108,205, 0,112,200, 0,114,197, 0, + 114,197, 0,113,198, 0,112,200, 0,111,201, 0,111,201, 0, + 113,199, 0,114,196, 0,117,191, 0,118,188, 0,117,190, 0, + 118,189, 0,118,188, 0,119,186, 0,119,186, 0,120,184, 0, + 121,181, 0,120,182, 0,120,184, 0,120,184, 0,120,182, 0, + 122,178, 0,123,172, 2,124,166, 7,124,161, 11,124,162, 10, + 124,167, 6,123,172, 2,122,177, 0,122,178, 0,122,178, 0, + 122,176, 0,123,170, 3,122,177, 0,120,182, 0,119,186, 0, + 119,186, 0,119,185, 0,120,182, 0,122,178, 0,123,174, 1, + 122,176, 0,120,182, 0,117,190, 0,114,196, 0,111,202, 0, + 108,205, 0,107,207, 0,107,207, 0,108,205, 0,110,202, 0, + 108,205, 0,107,207, 0,108,205, 0,111,202, 0,114,196, 0, + 118,189, 0,121,182, 0,121,180, 0,120,182, 0,120,184, 0, + 120,184, 0,121,182, 0,122,178, 0,123,171, 3,124,166, 7, + 124,158, 13,124,147, 26,122,130, 53,121,127, 58,123,139, 37, + 124,150, 22,124,147, 26,124,162, 10,123,170, 3,122,175, 0, + 122,175, 0,123,170, 3,124,160, 12,123,137, 41,123,139, 37, + 124,155, 16,124,162, 10,124,164, 9,124,161, 11,124,155, 16, + 124,154, 18,124,154, 18,124,157, 15,124,155, 16,124,165, 8, + 123,173, 1,121,180, 0,120,184, 0,119,186, 0,118,188, 0, + 118,189, 0,118,188, 0,119,186, 0,121,181, 0,123,174, 1, + 124,164, 9,124,147, 26,119,119, 77, 99, 75,247, 94, 70,242, + 117,110,109,122,130, 53,123,137, 41,123,137, 41,122,132, 48, + 121,125, 63,120,122, 70,122,132, 48,124,143, 31,124,147, 26, + 124,147, 26,124,145, 29,124,147, 26,124,147, 26,124,143, 31, + 122,135, 44,123,139, 37,122,135, 44,122,135, 44,121,127, 58, + 117,110,109,118,114, 96,121,127, 58,123,139, 37,124,158, 13, + 123,171, 3,122,178, 0,121,182, 0,121,182, 0,122,178, 0, + 123,170, 3,124,157, 15,124,143, 31,124,143, 31,123,141, 34, + 121,127, 58,122,130, 53,124,143, 31,124,152, 20,124,155, 16, + 124,155, 16,124,150, 22,123,137, 41,122,135, 44,123,137, 41, + 124,145, 29,124,164, 9,123,173, 1,121,180, 0,119,186, 0, + 117,191, 0,114,196, 0,112,200, 0,109,204, 0,107,207, 0, + 106,208, 0,107,207, 0,109,204, 0,113,199, 0,117,191, 0, + 121,181, 0,124,167, 6,124,152, 20,123,139, 37,122,135, 44, + 122,130, 53,122,132, 48,122,135, 44,124,161, 11,122,177, 0, + 119,185, 0,117,191, 0,114,196, 0,112,199, 0,111,201, 0, + 110,202, 0,110,202, 0,111,201, 0,111,201, 0,112,200, 0, + 114,197, 0,115,194, 0,118,189, 0,119,186, 0,119,187, 0, + 119,187, 0,119,185, 0,121,182, 0,122,178, 0,123,173, 1, + 124,165, 8,124,147, 26,118,114, 96,107, 89,252,118,114, 96, + 122,132, 48,124,161, 11,122,175, 0,121,182, 0,120,184, 0, + 120,182, 0,121,179, 0,123,174, 1,124,166, 7,124,150, 22, + 122,135, 44,121,125, 63,123,137, 41,124,143, 31,123,141, 34, + 121,127, 58,111, 96,248, 30, 55,222, 87, 65,237,120,122, 70, + 124,155, 16,123,172, 2,121,181, 0,120,184, 0,120,184, 0, + 120,182, 0,122,178, 0,123,170, 3,124,160, 12,124,157, 15, + 124,162, 10,124,165, 8,124,164, 9,124,162, 10,124,167, 6, + 123,168, 5,124,167, 6,124,166, 7,124,166, 7,123,172, 2, + 119,185, 0,116,193, 0,112,199, 0,109,204, 0,105,209, 0, + 102,212, 0,101,214, 0,101,213, 0,103,211, 0,106,207, 0, + 109,204, 0,111,201, 0,113,198, 0,114,196, 0,115,194, 0, + 116,193, 0,118,189, 0,118,189, 0,119,187, 0,118,188, 0, + 118,189, 0,118,188, 0,119,185, 0,121,181, 0,122,177, 0, + 121,179, 0,122,178, 0,122,176, 0,122,177, 0,122,177, 0, + 123,174, 1,124,167, 6,124,165, 8,123,171, 3,123,173, 1, + 123,172, 2,123,169, 4,124,165, 8,124,158, 13,124,157, 15, + 124,157, 15,124,162, 10,124,166, 7,124,166, 7,124,166, 7, + 124,166, 7,124,161, 11,124,157, 15,124,167, 6,123,173, 1, + 122,177, 0,122,177, 0,123,174, 1,123,170, 3,124,166, 7, + 124,164, 9,123,168, 5,122,178, 0,119,187, 0,115,194, 0, + 112,200, 0,109,203, 0,108,205, 0,108,206, 0,109,204, 0, + 111,202, 0,111,201, 0,110,202, 0,111,201, 0,114,197, 0, + 117,192, 0,119,185, 0,121,179, 0,121,181, 0,121,182, 0, + 121,182, 0,121,180, 0,122,178, 0,123,174, 1,123,170, 3, + 124,165, 8,124,157, 15,124,145, 29,121,125, 63,114,104,197, + 118,117, 85,122,132, 48,122,135, 44,124,152, 20,124,157, 15, + 124,164, 9,124,167, 6,124,164, 9,124,155, 16,123,141, 34, + 123,137, 41,122,132, 48,123,141, 34,124,143, 31,123,137, 41, + 121,125, 63,122,130, 53,124,150, 22,124,155, 16,124,157, 15, + 124,160, 12,124,165, 8,123,169, 4,122,175, 0,121,180, 0, + 120,184, 0,119,187, 0,118,188, 0,119,186, 0,121,181, 0, + 123,172, 2,124,160, 12,123,137, 41,113,100,242, 30, 43,203, + 99, 75,247,119,119, 77,123,137, 41,124,143, 31,123,141, 34, + 123,137, 41,123,139, 37,122,135, 44,124,143, 31,124,150, 22, + 124,154, 18,124,152, 20,124,147, 26,124,150, 22,124,152, 20, + 124,147, 26,123,137, 41,124,145, 29,124,147, 26,124,143, 31, + 123,141, 34,122,130, 53,115,107,129,121,127, 58,123,137, 41, + 124,145, 29,124,162, 10,123,171, 3,122,175, 0,122,175, 0, + 123,170, 3,124,162, 10,124,149, 24,121,127, 58,121,125, 63, + 121,125, 63,118,117, 85,118,114, 96,121,127, 58,123,139, 37, + 124,145, 29,124,145, 29,123,137, 41,118,117, 85,111, 96,248, + 111, 96,248,122,132, 48,124,152, 20,124,162, 10,123,169, 4, + 122,176, 0,120,184, 0,118,188, 0,116,193, 0,113,198, 0, + 110,202, 0,109,204, 0,110,202, 0,112,199, 0,116,192, 0, + 120,183, 0,123,169, 4,124,149, 24,121,127, 58,118,114, 96, + 119,119, 77,119,119, 77,118,114, 96,124,145, 29,123,170, 3, + 120,184, 0,116,192, 0,113,198, 0,111,202, 0,109,204, 0, + 108,205, 0,108,205, 0,109,204, 0,109,203, 0,110,202, 0, + 110,202, 0,112,200, 0,114,197, 0,117,192, 0,116,193, 0, + 116,193, 0,116,193, 0,117,191, 0,118,188, 0,120,184, 0, + 121,179, 0,123,171, 3,124,157, 15,121,125, 63, 30, 55,222, + 105, 84,252,122,130, 53,124,160, 12,123,174, 1,121,180, 0, + 120,182, 0,121,181, 0,122,178, 0,123,174, 1,124,166, 7, + 124,150, 22,122,130, 53,121,125, 63,123,139, 37,124,145, 29, + 123,141, 34,121,125, 63,102, 80,250, 30, 15,143,113,100,242, + 124,147, 26,123,168, 5,122,178, 0,120,184, 0,119,186, 0, + 119,186, 0,120,182, 0,122,176, 0,123,168, 5,124,157, 15, + 123,141, 34,124,143, 31,124,154, 18,124,154, 18,124,158, 13, + 124,165, 8,124,166, 7,124,166, 7,124,165, 8,123,168, 5, + 123,170, 3,121,180, 0,118,189, 0,114,196, 0,111,201, 0, + 109,204, 0,106,207, 0,105,209, 0,105,209, 0,107,207, 0, + 109,204, 0,112,200, 0,113,198, 0,113,198, 0,113,198, 0, + 113,198, 0,114,197, 0,116,193, 0,118,188, 0,119,185, 0, + 121,180, 0,123,172, 2,123,171, 3,123,170, 3,124,165, 8, + 124,160, 12,124,164, 9,124,162, 10,124,158, 13,124,161, 11, + 124,162, 10,123,168, 5,123,168, 5,124,165, 8,123,168, 5, + 123,169, 4,124,167, 6,124,164, 9,124,162, 10,124,164, 9, + 124,164, 9,124,160, 12,124,167, 6,123,171, 3,123,173, 1, + 123,171, 3,124,164, 9,124,149, 24,123,137, 41,124,152, 20, + 124,160, 12,124,162, 10,124,161, 11,124,155, 16,124,149, 24, + 124,149, 24,124,149, 24,124,155, 16,123,170, 3,120,182, 0, + 117,190, 0,114,196, 0,112,200, 0,111,202, 0,111,202, 0, + 111,201, 0,113,199, 0,114,197, 0,113,198, 0,114,196, 0, + 116,192, 0,118,188, 0,119,185, 0,121,180, 0,120,184, 0, + 119,185, 0,119,185, 0,120,183, 0,121,180, 0,122,176, 0, + 123,171, 3,124,165, 8,124,155, 16,123,141, 34,120,122, 70, + 109, 92,251,102, 80,250,113,100,242,118,117, 85,124,143, 31, + 124,152, 20,124,154, 18,124,155, 16,124,157, 15,124,150, 22, + 123,141, 34,123,139, 37,122,132, 48,118,114, 96,117,110,109, + 113,100,242,105, 84,252,118,117, 85,123,141, 34,124,147, 26, + 124,152, 20,124,160, 12,124,167, 6,123,173, 1,122,177, 0, + 122,178, 0,122,178, 0,120,183, 0,119,185, 0,120,184, 0, + 122,178, 0,123,169, 4,124,154, 18,123,139, 37,114,104,197, + 30, 15,143, 99, 75,247,121,125, 63,124,143, 31,124,149, 24, + 124,149, 24,124,143, 31,124,149, 24,124,147, 26,124,149, 24, + 124,155, 16,124,158, 13,124,158, 13,124,152, 20,124,149, 24, + 124,149, 24,124,143, 31,122,135, 44,124,149, 24,124,155, 16, + 124,154, 18,124,150, 22,124,143, 31,122,130, 53,121,125, 63, + 123,139, 37,124,147, 26,124,150, 22,124,158, 13,124,162, 10, + 124,161, 11,124,155, 16,124,143, 31,121,125, 63,111, 96,248, + 115,107,129,121,125, 63,122,130, 53,120,122, 70,120,122, 70, + 122,135, 44,123,141, 34,123,137, 41,119,119, 77,109, 92,251, + 30, 49,213, 30, 55,222,115,107,129,122,130, 53,123,139, 37, + 124,152, 20,123,171, 3,121,181, 0,119,186, 0,118,188, 0, + 118,189, 0,115,195, 0,114,197, 0,114,196, 0,117,192, 0, + 120,184, 0,123,172, 2,124,155, 16,123,139, 37,114,104,197, + 105, 84,252,115,107,129,122,130, 53,124,157, 15,123,169, 4, + 122,175, 0,119,187, 0,114,196, 0,111,201, 0,108,205, 0, + 107,207, 0,107,207, 0,107,206, 0,108,205, 0,110,203, 0, + 110,202, 0,110,202, 0,111,201, 0,114,197, 0,113,198, 0, + 112,199, 0,113,199, 0,113,198, 0,115,195, 0,116,192, 0, + 118,189, 0,119,185, 0,122,178, 0,124,164, 9,123,137, 41, + 94, 70,242, 30, 43,203,120,122, 70,124,155, 16,123,169, 4, + 122,176, 0,122,178, 0,122,176, 0,123,173, 1,123,169, 4, + 124,162, 10,124,147, 26,119,119, 77,121,125, 63,123,139, 37, + 123,141, 34,122,135, 44,117,110,109, 30, 37,192, 69, 60,230, + 121,127, 58,124,160, 12,123,174, 1,121,181, 0,120,184, 0, + 119,185, 0,120,184, 0,122,178, 0,123,170, 3,124,160, 12, + 124,145, 29,121,127, 58,115,107,129,121,125, 63,122,132, 48, + 124,150, 22,124,161, 11,124,164, 9,124,164, 9,124,167, 6, + 123,174, 1,122,176, 0,122,177, 0,119,186, 0,116,193, 0, + 113,198, 0,111,201, 0,111,202, 0,109,204, 0,109,204, 0, + 110,202, 0,112,200, 0,111,202, 0,109,203, 0,109,204, 0, + 110,202, 0,112,200, 0,112,200, 0,114,197, 0,117,190, 0, + 120,183, 0,122,178, 0,123,168, 5,124,150, 22,123,141, 34, + 122,135, 44,122,132, 48,123,139, 37,123,139, 37,122,135, 44, + 124,154, 18,124,165, 8,123,171, 3,123,171, 3,123,168, 5, + 124,167, 6,124,166, 7,124,166, 7,124,167, 6,123,168, 5, + 123,168, 5,124,167, 6,124,162, 10,123,170, 3,122,176, 0, + 122,178, 0,122,176, 0,123,169, 4,124,157, 15,124,149, 24, + 124,149, 24,123,141, 34,122,135, 44,122,130, 53,120,122, 70, + 121,127, 58,122,132, 48,122,130, 53,122,135, 44,124,158, 13, + 123,174, 1,120,184, 0,118,189, 0,116,193, 0,115,195, 0, + 114,196, 0,115,195, 0,115,194, 0,116,193, 0,115,194, 0, + 116,192, 0,118,188, 0,119,186, 0,120,184, 0,120,182, 0, + 119,186, 0,119,187, 0,119,187, 0,119,185, 0,121,182, 0, + 122,177, 0,123,170, 3,124,164, 9,124,154, 18,123,139, 37, + 118,117, 85,105, 84,252, 30, 37,192, 87, 65,237,102, 80,250, + 120,122, 70,123,137, 41,124,143, 31,124,143, 31,124,149, 24, + 124,147, 26,123,137, 41,122,132, 48,122,130, 53,118,117, 85, + 107, 89,252, 30, 49,213, 87, 65,237,107, 89,252,119,119, 77, + 122,130, 53,123,137, 41,124,152, 20,124,165, 8,123,172, 2, + 122,178, 0,121,179, 0,122,178, 0,122,178, 0,121,182, 0, + 121,181, 0,122,176, 0,124,166, 7,124,154, 18,123,139, 37, + 114,104,197, 30, 15,143,105, 84,252,122,132, 48,124,150, 22, + 124,157, 15,124,157, 15,124,150, 22,124,152, 20,124,152, 20, + 124,147, 26,124,155, 16,124,161, 11,124,162, 10,124,158, 13, + 124,149, 24,123,139, 37,122,130, 53,122,135, 44,124,152, 20, + 124,161, 11,124,164, 9,124,158, 13,124,150, 22,123,141, 34, + 121,125, 63,123,141, 34,124,150, 22,124,154, 18,124,149, 24, + 123,137, 41,122,132, 48,119,119, 77,113,100,242, 87, 65,237, + 102, 80,250,118,117, 85,122,135, 44,124,143, 31,123,141, 34, + 122,130, 53,122,132, 48,123,141, 34,123,141, 34,122,130, 53, + 115,107,129, 87, 65,237, 30, 26,168, 30, 49,213,102, 80,250, + 109, 92,251,123,139, 37,124,165, 8,122,178, 0,120,184, 0, + 119,185, 0,120,184, 0,119,186, 0,118,189, 0,118,188, 0, + 120,184, 0,123,174, 1,124,157, 15,124,145, 29,120,122, 70, + 87, 65,237, 69, 60,230,121,125, 63,124,161, 11,122,178, 0, + 119,185, 0,118,189, 0,118,189, 0,114,196, 0,111,202, 0, + 108,205, 0,107,207, 0,107,207, 0,108,205, 0,110,203, 0, + 111,201, 0,111,201, 0,112,200, 0,113,199, 0,111,201, 0, + 110,202, 0,110,203, 0,110,202, 0,111,201, 0,113,198, 0, + 115,195, 0,116,192, 0,118,189, 0,120,182, 0,123,170, 3, + 124,147, 26,107, 89,252, 30, 20,155,118,114, 96,124,149, 24, + 124,162, 10,123,169, 4,123,170, 3,123,168, 5,124,165, 8, + 124,161, 11,124,155, 16,123,139, 37,117,110,109,119,119, 77, + 122,130, 53,122,132, 48,119,119, 77,102, 80,250, 30, 31,180, + 113,100,242,124,145, 29,124,167, 6,122,176, 0,121,180, 0, + 121,182, 0,121,181, 0,122,178, 0,122,176, 0,122,177, 0, + 123,174, 1,124,164, 9,123,139, 37,102, 80,250, 94, 70,242, + 115,107,129,123,141, 34,124,155, 16,124,162, 10,124,165, 8, + 123,171, 3,122,178, 0,121,179, 0,122,178, 0,119,185, 0, + 116,192, 0,114,197, 0,112,199, 0,113,199, 0,113,198, 0, + 113,198, 0,114,197, 0,111,202, 0,108,206, 0,106,208, 0, + 106,208, 0,107,206, 0,110,202, 0,111,201, 0,113,199, 0, + 116,192, 0,120,183, 0,122,176, 0,124,165, 8,124,145, 29, + 114,104,197, 99, 75,247,109, 92,251,118,114, 96,122,135, 44, + 124,143, 31,124,154, 18,124,165, 8,123,170, 3,123,170, 3, + 123,168, 5,124,167, 6,124,167, 6,124,167, 6,123,168, 5, + 123,168, 5,123,168, 5,124,166, 7,124,164, 9,123,173, 1, + 121,179, 0,121,182, 0,121,180, 0,123,174, 1,124,162, 10, + 124,154, 18,124,154, 18,124,147, 26,122,130, 53,113,100,242, + 102, 80,250,111, 96,248,113,100,242,107, 89,252,113,100,242, + 123,137, 41,124,160, 12,123,173, 1,121,180, 0,120,184, 0, + 119,185, 0,119,186, 0,119,186, 0,118,188, 0,117,191, 0, + 117,192, 0,117,190, 0,119,186, 0,120,183, 0,121,180, 0, + 120,183, 0,119,186, 0,118,188, 0,118,188, 0,119,186, 0, + 121,182, 0,122,176, 0,123,169, 4,124,161, 11,124,150, 22, + 122,135, 44,120,122, 70,114,104,197, 69, 60,230, 30, 2,128, + 30, 2,128, 87, 65,237,113,100,242,118,117, 85,122,135, 44, + 124,143, 31,124,145, 29,123,137, 41,118,117, 85,118,117, 85, + 117,110,109,113,100,242,111, 96,248,107, 89,252,102, 80,250, + 105, 84,252,109, 92,251,117,110,109,122,132, 48,124,152, 20, + 124,166, 7,123,174, 1,122,177, 0,122,177, 0,123,172, 2, + 122,178, 0,122,178, 0,123,174, 1,124,164, 9,124,149, 24, + 122,132, 48,109, 92,251, 30, 2,128,113,100,242,123,141, 34, + 124,160, 12,124,166, 7,124,166, 7,124,162, 10,124,155, 16, + 124,149, 24,124,147, 26,124,150, 22,124,158, 13,124,162, 10, + 124,162, 10,124,155, 16,123,141, 34,117,110,109,122,135, 44, + 124,155, 16,124,166, 7,123,170, 3,123,168, 5,124,158, 13, + 124,143, 31,121,127, 58,124,145, 29,124,154, 18,124,154, 18, + 124,147, 26,122,130, 53,111, 96,248, 30, 43,203, 30, 2,128, + 30, 43,203,111, 96,248,122,130, 53,124,147, 26,124,154, 18, + 124,154, 18,124,147, 26,122,135, 44,124,147, 26,124,150, 22, + 124,147, 26,123,137, 41,118,117, 85,105, 84,252, 30, 55,222, + 30, 10,132, 69, 60,230,120,122, 70,124,157, 15,123,172, 2, + 121,179, 0,121,181, 0,121,179, 0,123,174, 1,121,179, 0, + 121,179, 0,123,174, 1,124,164, 9,124,143, 31,119,119, 77, + 102, 80,250, 30, 2,128,113,100,242,124,154, 18,122,177, 0, + 118,188, 0,115,194, 0,114,196, 0,114,197, 0,114,196, 0, + 111,201, 0,109,204, 0,108,205, 0,109,204, 0,110,202, 0, + 112,199, 0,114,197, 0,114,196, 0,113,199, 0,111,202, 0, + 109,204, 0,108,205, 0,108,206, 0,108,205, 0,110,202, 0, + 112,200, 0,114,197, 0,115,194, 0,117,191, 0,120,184, 0, + 123,174, 1,124,154, 18,115,107,129, 30, 2,128,111, 96,248, + 123,137, 41,124,154, 18,124,160, 12,124,160, 12,124,157, 15, + 124,155, 16,124,150, 22,124,145, 29,122,135, 44,122,130, 53, + 121,125, 63,118,117, 85,117,110,109,107, 89,252, 30, 26,168, + 102, 80,250,121,125, 63,124,155, 16,123,170, 3,122,177, 0, + 122,178, 0,122,177, 0,122,175, 0,121,181, 0,120,184, 0, + 120,184, 0,121,182, 0,123,172, 2,124,152, 20,114,104,197, + 30, 2,128,109, 92,251,122,135, 44,124,155, 16,124,165, 8, + 123,169, 4,123,172, 2,122,178, 0,121,179, 0,120,184, 0, + 118,189, 0,115,194, 0,113,198, 0,112,199, 0,113,199, 0, + 114,196, 0,117,191, 0,114,196, 0,110,202, 0,107,207, 0, + 104,210, 0,104,210, 0,105,209, 0,108,205, 0,112,200, 0, + 114,197, 0,117,191, 0,120,183, 0,122,175, 0,124,162, 10, + 123,139, 37,107, 89,252, 30, 2,128,105, 84,252,121,125, 63, + 124,145, 29,124,154, 18,124,157, 15,124,161, 11,124,167, 6, + 124,167, 6,123,171, 3,123,171, 3,123,169, 4,124,165, 8, + 124,164, 9,124,164, 9,124,165, 8,124,160, 12,123,169, 4, + 122,178, 0,120,182, 0,120,184, 0,120,183, 0,122,178, 0, + 124,167, 6,124,152, 20,124,152, 20,124,145, 29,122,130, 53, + 114,104,197,105, 84,252, 87, 65,237, 30, 37,192, 30, 2,128, + 30, 49,213,114,104,197,123,137, 41,124,155, 16,124,165, 8, + 123,168, 5,123,170, 3,123,172, 2,121,181, 0,119,187, 0, + 117,191, 0,117,191, 0,117,190, 0,119,186, 0,121,180, 0, + 123,172, 2,121,180, 0,120,184, 0,119,186, 0,119,186, 0, + 120,183, 0,121,179, 0,123,172, 2,124,164, 9,124,154, 18, + 124,147, 26,124,147, 26,124,145, 29,122,135, 44,118,117, 85, + 99, 75,247,111, 96,248, 30, 31,180, 94, 70,242,115,107,129, + 121,127, 58,123,139, 37,124,143, 31,123,139, 37,121,125, 63, + 113,100,242,114,104,197,118,117, 85,120,122, 70,121,125, 63, + 121,125, 63,121,127, 58,123,137, 41,123,141, 34,122,135, 44, + 124,143, 31,124,157, 15,123,168, 5,123,173, 1,123,174, 1, + 123,171, 3,123,171, 3,123,173, 1,123,169, 4,124,160, 12, + 124,143, 31,120,122, 70, 94, 70,242, 30, 26,168,118,117, 85, + 124,154, 18,123,168, 5,122,175, 0,122,177, 0,122,175, 0, + 123,172, 2,123,169, 4,124,165, 8,124,154, 18,124,149, 24, + 124,158, 13,124,162, 10,124,160, 12,124,152, 20,124,150, 22, + 124,143, 31,124,161, 11,123,171, 3,122,176, 0,122,176, 0, + 123,170, 3,124,158, 13,123,139, 37,124,145, 29,124,150, 22, + 124,150, 22,123,139, 37,118,117, 85, 94, 70,242,105, 84,252, + 117,110,109,122,130, 53,124,143, 31,124,149, 24,124,155, 16, + 124,160, 12,124,160, 12,124,154, 18,124,145, 29,124,158, 13, + 124,164, 9,124,164, 9,124,161, 11,124,154, 18,123,141, 34, + 121,127, 58,118,114, 96,115,107,129,122,132, 48,124,152, 20, + 124,162, 10,123,169, 4,123,170, 3,124,167, 6,124,160, 12, + 124,167, 6,124,167, 6,124,162, 10,124,149, 24,120,122, 70, + 99, 75,247, 30, 49,213,102, 80,250,123,141, 34,123,171, 3, + 119,186, 0,115,194, 0,113,199, 0,112,200, 0,112,200, 0, + 113,199, 0,111,201, 0,110,203, 0,110,203, 0,111,202, 0, + 113,199, 0,112,199, 0,109,204, 0,108,206, 0,108,206, 0, + 107,206, 0,107,207, 0,106,208, 0,105,209, 0,105,209, 0, + 105,209, 0,107,207, 0,109,203, 0,114,197, 0,117,192, 0, + 119,186, 0,122,175, 0,124,155, 16,117,110,109, 30, 49,213, + 105, 84,252,121,125, 63,124,143, 31,124,147, 26,124,149, 24, + 124,161, 11,124,166, 7,124,164, 9,124,157, 15,124,152, 20, + 124,149, 24,124,143, 31,122,132, 48,119,119, 77,111, 96,248, + 94, 70,242,115,107,129,122,132, 48,124,155, 16,124,167, 6, + 123,171, 3,123,171, 3,122,176, 0,120,182, 0,119,186, 0, + 118,188, 0,118,188, 0,120,184, 0,122,176, 0,124,157, 15, + 117,110,109, 94, 70,242,107, 89,252,123,137, 41,124,160, 12, + 123,171, 3,122,178, 0,120,182, 0,119,186, 0,118,189, 0, + 116,193, 0,114,196, 0,113,199, 0,112,200, 0,112,200, 0, + 112,199, 0,114,197, 0,114,197, 0,114,197, 0,111,201, 0, + 107,207, 0,104,210, 0,103,212, 0,103,211, 0,106,207, 0, + 110,202, 0,114,197, 0,117,191, 0,119,185, 0,122,176, 0, + 124,161, 11,122,135, 44,113,100,242, 87, 65,237,107, 89,252, + 122,130, 53,124,149, 24,124,158, 13,124,164, 9,124,166, 7, + 123,168, 5,123,172, 2,122,175, 0,122,175, 0,123,173, 1, + 123,174, 1,122,177, 0,121,179, 0,121,181, 0,120,182, 0, + 120,184, 0,119,186, 0,119,187, 0,119,187, 0,119,185, 0, + 121,180, 0,123,170, 3,124,157, 15,124,143, 31,123,137, 41, + 121,125, 63,115,107,129,105, 84,252,102, 80,250,107, 89,252, + 114,104,197,118,117, 85,118,117, 85,118,114, 96,122,130, 53, + 123,141, 34,124,145, 29,124,149, 24,124,166, 7,122,177, 0, + 120,184, 0,118,189, 0,117,191, 0,117,191, 0,118,188, 0, + 120,183, 0,121,181, 0,120,184, 0,119,186, 0,119,187, 0, + 119,187, 0,119,186, 0,120,184, 0,121,181, 0,122,175, 0, + 124,165, 8,124,157, 15,124,154, 18,124,157, 15,124,157, 15, + 124,152, 20,122,135, 44,124,149, 24,118,117, 85,102, 80,250, + 107, 89,252,118,114, 96,122,130, 53,123,139, 37,123,141, 34, + 122,135, 44,121,127, 58,120,122, 70,119,119, 77,122,130, 53, + 123,139, 37,124,145, 29,124,150, 22,124,157, 15,124,157, 15, + 124,152, 20,124,158, 13,124,160, 12,124,164, 9,123,171, 3, + 123,173, 1,123,171, 3,123,168, 5,124,165, 8,124,160, 12, + 124,154, 18,123,139, 37,118,114, 96, 69, 60,230, 30, 49,213, + 122,130, 53,124,161, 11,122,175, 0,121,182, 0,120,184, 0, + 119,185, 0,120,184, 0,120,183, 0,121,180, 0,123,172, 2, + 124,161, 11,124,160, 12,124,167, 6,123,170, 3,123,172, 2, + 123,172, 2,123,168, 5,123,168, 5,122,178, 0,120,184, 0, + 120,184, 0,121,182, 0,122,175, 0,124,164, 9,124,160, 12, + 124,161, 11,124,157, 15,124,145, 29,121,127, 58,122,130, 53, + 124,147, 26,124,160, 12,123,168, 5,123,172, 2,123,173, 1, + 123,170, 3,124,162, 10,124,160, 12,124,154, 18,124,157, 15, + 124,167, 6,123,172, 2,122,175, 0,122,175, 0,123,173, 1, + 123,170, 3,124,166, 7,124,161, 11,124,158, 13,124,152, 20, + 124,161, 11,124,167, 6,124,167, 6,124,162, 10,124,152, 20, + 124,143, 31,124,152, 20,124,154, 18,124,147, 26,122,135, 44, + 118,117, 85,109, 92,251,105, 84,252,122,135, 44,124,166, 7, + 120,183, 0,116,193, 0,112,199, 0,110,202, 0,110,202, 0, + 111,202, 0,112,200, 0,111,202, 0,110,203, 0,110,202, 0, + 112,200, 0,111,202, 0,107,207, 0,103,211, 0,102,213, 0, + 101,213, 0,101,214, 0,100,215, 0, 99,216, 0, 98,216, 0, + 99,216, 0,100,215, 0,102,213, 0,105,209, 0,110,202, 0, + 115,194, 0,119,187, 0,122,176, 0,124,155, 16,122,130, 53, + 113,100,242,109, 92,251,117,110,109,120,122, 70,122,132, 48, + 124,155, 16,123,168, 5,123,174, 1,123,173, 1,123,169, 4, + 124,166, 7,124,161, 11,124,155, 16,124,147, 26,123,137, 41, + 120,122, 70,114,104,197,117,110,109,122,132, 48,124,145, 29, + 124,155, 16,124,160, 12,123,172, 2,120,183, 0,118,188, 0, + 117,190, 0,117,192, 0,117,191, 0,119,186, 0,122,178, 0, + 124,165, 8,124,147, 26,121,125, 63,119,119, 77,123,141, 34, + 124,167, 6,121,179, 0,119,187, 0,117,192, 0,115,195, 0, + 113,198, 0,111,201, 0,110,202, 0,109,204, 0,109,204, 0, + 109,204, 0,110,203, 0,110,202, 0,110,202, 0,110,202, 0, + 112,200, 0,108,205, 0,105,209, 0,103,212, 0,103,212, 0, + 105,209, 0,108,205, 0,112,199, 0,116,193, 0,119,185, 0, + 122,175, 0,124,160, 12,124,147, 26,123,139, 37,121,125, 63, + 118,117, 85,121,125, 63,124,145, 29,124,157, 15,124,164, 9, + 124,167, 6,123,170, 3,123,173, 1,122,175, 0,121,179, 0, + 120,184, 0,119,187, 0,117,190, 0,116,192, 0,115,195, 0, + 114,197, 0,113,198, 0,113,199, 0,113,198, 0,114,196, 0, + 117,192, 0,119,185, 0,122,176, 0,124,165, 8,124,154, 18, + 124,143, 31,122,135, 44,122,130, 53,122,132, 48,123,137, 41, + 124,143, 31,124,152, 20,124,157, 15,124,155, 16,124,143, 31, + 118,114, 96,117,110,109,118,117, 85,121,125, 63,124,154, 18, + 123,168, 5,122,178, 0,119,185, 0,118,188, 0,118,189, 0, + 118,188, 0,120,184, 0,119,186, 0,118,189, 0,117,191, 0, + 117,192, 0,117,191, 0,117,191, 0,118,189, 0,119,187, 0, + 120,183, 0,122,177, 0,123,172, 2,124,164, 9,124,166, 7, + 123,171, 3,123,171, 3,124,166, 7,123,171, 3,124,152, 20, + 121,127, 58,113,100,242,105, 84,252,117,110,109,121,127, 58, + 123,137, 41,124,145, 29,124,149, 24,124,149, 24,124,149, 24, + 124,147, 26,124,147, 26,124,154, 18,124,160, 12,124,165, 8, + 124,164, 9,124,165, 8,123,169, 4,123,170, 3,123,168, 5, + 123,169, 4,123,173, 1,123,172, 2,123,169, 4,124,167, 6, + 124,162, 10,124,155, 16,123,139, 37,115,107,129, 30, 37,192, + 87, 65,237,123,137, 41,124,166, 7,121,179, 0,119,186, 0, + 118,189, 0,117,191, 0,117,191, 0,117,191, 0,118,189, 0, + 120,183, 0,123,173, 1,123,168, 5,122,176, 0,121,182, 0, + 120,184, 0,120,184, 0,121,182, 0,122,177, 0,119,186, 0, + 117,191, 0,116,192, 0,117,191, 0,119,186, 0,121,179, 0, + 123,170, 3,123,170, 3,124,167, 6,124,160, 12,124,152, 20, + 124,162, 10,123,171, 3,121,180, 0,120,184, 0,119,186, 0, + 119,186, 0,121,182, 0,123,174, 1,124,160, 12,124,152, 20, + 124,167, 6,123,174, 1,122,178, 0,121,182, 0,120,183, 0, + 120,184, 0,120,183, 0,120,182, 0,121,181, 0,121,179, 0, + 122,175, 0,123,168, 5,123,168, 5,124,166, 7,124,158, 13, + 124,143, 31,124,147, 26,124,154, 18,124,154, 18,124,147, 26, + 122,135, 44,118,117, 85,115,107,129,123,137, 41,124,162, 10, + 121,180, 0,117,191, 0,113,198, 0,110,202, 0,109,204, 0, + 109,204, 0,110,202, 0,110,202, 0,109,203, 0,109,203, 0, + 110,202, 0,108,205, 0,105,209, 0,102,213, 0, 98,217, 0, + 96,219, 0, 95,220, 0, 94,221, 0, 92,222, 0, 92,223, 0, + 92,223, 0, 92,222, 0, 94,220, 0, 97,217, 0,102,213, 0, + 107,207, 0,112,200, 0,117,192, 0,120,182, 0,123,169, 4, + 124,154, 18,122,130, 53,118,117, 85,115,107,129,109, 92,251, + 123,137, 41,124,161, 11,123,173, 1,121,179, 0,122,178, 0, + 122,176, 0,123,172, 2,123,168, 5,124,162, 10,124,155, 16, + 124,147, 26,123,137, 41,121,127, 58,120,122, 70,121,127, 58, + 123,137, 41,124,152, 20,124,166, 7,122,178, 0,119,186, 0, + 118,189, 0,117,191, 0,117,192, 0,117,192, 0,117,190, 0, + 119,186, 0,122,178, 0,124,167, 6,124,154, 18,123,141, 34, + 124,150, 22,123,174, 1,119,187, 0,115,194, 0,112,200, 0, + 110,202, 0,108,205, 0,107,206, 0,107,207, 0,107,207, 0, + 107,207, 0,107,206, 0,108,206, 0,108,205, 0,108,206, 0, + 108,205, 0,110,203, 0,109,203, 0,106,208, 0,103,211, 0, + 103,212, 0,105,209, 0,108,205, 0,112,199, 0,117,192, 0, + 120,184, 0,123,172, 2,124,165, 8,124,165, 8,124,162, 10, + 124,157, 15,124,149, 24,124,147, 26,124,155, 16,124,161, 11, + 124,166, 7,123,170, 3,122,175, 0,121,180, 0,120,184, 0, + 118,188, 0,117,191, 0,115,194, 0,113,198, 0,111,201, 0, + 109,204, 0,107,206, 0,107,207, 0,107,207, 0,107,206, 0, + 110,203, 0,113,199, 0,116,193, 0,119,186, 0,121,179, 0, + 123,173, 1,124,167, 6,124,160, 12,124,149, 24,124,152, 20, + 124,160, 12,124,166, 7,123,172, 2,123,174, 1,123,171, 3, + 124,161, 11,123,139, 37,107, 89,252, 99, 75,247,107, 89,252, + 122,132, 48,124,154, 18,123,168, 5,122,178, 0,120,184, 0, + 119,186, 0,119,186, 0,120,184, 0,118,189, 0,117,191, 0, + 116,192, 0,116,193, 0,116,193, 0,116,193, 0,116,192, 0, + 117,191, 0,118,188, 0,120,184, 0,121,181, 0,123,173, 1, + 123,171, 3,121,179, 0,120,182, 0,121,180, 0,121,181, 0, + 124,167, 6,124,147, 26,119,119, 77,107, 89,252, 94, 70,242, + 115,107,129,122,132, 48,124,149, 24,124,157, 15,124,161, 11, + 124,164, 9,124,165, 8,124,165, 8,124,165, 8,124,165, 8, + 123,168, 5,123,171, 3,123,174, 1,122,176, 0,122,176, 0, + 123,174, 1,123,169, 4,123,171, 3,123,171, 3,123,170, 3, + 123,168, 5,124,165, 8,124,157, 15,123,141, 34,115,107,129, + 30, 49,213, 99, 75,247,123,141, 34,123,168, 5,121,181, 0, + 118,188, 0,117,191, 0,116,193, 0,115,194, 0,115,195, 0, + 116,193, 0,118,189, 0,121,181, 0,122,175, 0,120,183, 0, + 118,188, 0,117,191, 0,117,191, 0,118,189, 0,119,185, 0, + 116,193, 0,114,197, 0,113,199, 0,114,197, 0,115,194, 0, + 118,189, 0,120,182, 0,122,177, 0,122,176, 0,123,171, 3, + 123,169, 4,122,176, 0,120,183, 0,118,189, 0,116,193, 0, + 115,195, 0,116,193, 0,118,189, 0,120,182, 0,123,171, 3, + 123,168, 5,123,173, 1,122,178, 0,121,182, 0,120,184, 0, + 119,187, 0,118,188, 0,118,189, 0,117,191, 0,117,190, 0, + 118,189, 0,119,187, 0,121,182, 0,123,172, 2,124,162, 10, + 124,152, 20,122,132, 48,124,147, 26,124,154, 18,124,152, 20, + 124,145, 29,122,132, 48,122,130, 53,124,145, 29,124,162, 10, + 122,178, 0,118,189, 0,114,197, 0,110,202, 0,108,205, 0, + 108,206, 0,109,204, 0,109,203, 0,108,205, 0,108,205, 0, + 109,204, 0,107,206, 0,103,212, 0, 99,216, 0, 96,219, 0, + 94,221, 0, 91,223, 0, 90,225, 0, 88,226, 0, 86,228, 0, + 85,229, 0, 85,228, 0, 87,227, 0, 90,224, 0, 94,220, 0, + 99,215, 0,104,210, 0,109,203, 0,114,197, 0,118,188, 0, + 122,178, 0,124,166, 7,124,147, 26,122,130, 53,118,117, 85, + 118,117, 85,124,143, 31,124,164, 9,122,175, 0,121,180, 0, + 121,180, 0,122,178, 0,123,174, 1,123,169, 4,124,165, 8, + 124,158, 13,124,152, 20,124,147, 26,123,141, 34,123,141, 34, + 124,147, 26,124,157, 15,123,168, 5,122,177, 0,120,184, 0, + 118,189, 0,116,192, 0,115,194, 0,114,196, 0,114,196, 0, + 115,195, 0,117,191, 0,119,186, 0,122,178, 0,123,168, 5, + 124,157, 15,124,161, 11,120,182, 0,115,194, 0,111,201, 0, + 108,206, 0,106,208, 0,105,209, 0,104,210, 0,105,209, 0, + 106,208, 0,106,207, 0,107,207, 0,107,206, 0,107,207, 0, + 106,207, 0,107,207, 0,108,205, 0,111,201, 0,108,205, 0, + 106,208, 0,105,209, 0,106,208, 0,109,203, 0,114,197, 0, + 118,188, 0,122,178, 0,123,168, 5,123,171, 3,123,174, 1, + 122,175, 0,122,175, 0,123,172, 2,123,170, 3,123,168, 5, + 123,174, 1,122,178, 0,120,182, 0,119,186, 0,118,188, 0, + 117,191, 0,116,193, 0,114,196, 0,113,199, 0,110,202, 0, + 107,207, 0,104,210, 0,102,212, 0,101,213, 0,102,212, 0, + 104,210, 0,106,207, 0,110,202, 0,114,197, 0,117,192, 0, + 119,187, 0,120,184, 0,121,179, 0,123,173, 1,124,164, 9, + 124,161, 11,123,168, 5,122,175, 0,121,180, 0,121,182, 0, + 122,178, 0,123,169, 4,124,152, 20,118,114, 96, 30, 37,192, + 30, 55,222,111, 96,248,121,127, 58,124,152, 20,124,167, 6, + 122,176, 0,121,181, 0,121,182, 0,120,184, 0,118,188, 0, + 117,191, 0,117,191, 0,117,192, 0,117,192, 0,117,192, 0, + 117,192, 0,117,191, 0,118,188, 0,119,186, 0,120,184, 0, + 122,178, 0,123,174, 1,120,183, 0,118,188, 0,119,187, 0, + 120,184, 0,123,171, 3,124,152, 20,120,122, 70,107, 89,252, + 30, 55,222, 87, 65,237,118,114, 96,124,143, 31,124,158, 13, + 124,166, 7,123,171, 3,123,173, 1,123,174, 1,123,174, 1, + 123,174, 1,122,176, 0,122,178, 0,121,180, 0,121,180, 0, + 121,179, 0,122,176, 0,123,170, 3,124,166, 7,123,168, 5, + 123,168, 5,124,167, 6,124,165, 8,124,158, 13,123,141, 34, + 115,107,129,105, 84,252,102, 80,250,123,141, 34,124,167, 6, + 121,180, 0,119,186, 0,117,191, 0,116,192, 0,115,194, 0, + 115,195, 0,115,194, 0,117,191, 0,120,184, 0,121,180, 0, + 119,187, 0,117,192, 0,115,194, 0,115,195, 0,116,193, 0, + 116,193, 0,112,199, 0,110,202, 0,109,204, 0,110,202, 0, + 112,199, 0,115,194, 0,118,189, 0,120,184, 0,120,183, 0, + 121,181, 0,122,177, 0,121,182, 0,118,188, 0,115,194, 0, + 113,199, 0,112,200, 0,113,199, 0,115,194, 0,118,188, 0, + 120,182, 0,120,184, 0,121,181, 0,121,179, 0,121,182, 0, + 120,184, 0,119,187, 0,118,189, 0,117,192, 0,115,194, 0, + 115,194, 0,115,194, 0,116,193, 0,118,189, 0,120,183, 0, + 123,172, 2,124,154, 18,121,125, 63,124,145, 29,124,150, 22, + 124,150, 22,124,152, 20,124,154, 18,124,160, 12,124,167, 6, + 122,177, 0,119,187, 0,114,196, 0,110,202, 0,108,206, 0, + 107,207, 0,107,207, 0,108,205, 0,106,208, 0,106,208, 0, + 107,207, 0,108,205, 0,103,212, 0, 98,217, 0, 93,222, 0, + 89,225, 0, 87,227, 0, 87,227, 0, 85,228, 0, 83,230, 0, + 80,232, 0, 80,233, 0, 80,232, 0, 83,230, 0, 87,227, 0, + 92,222, 0, 97,217, 0,103,212, 0,107,206, 0,112,200, 0, + 116,192, 0,120,184, 0,123,173, 1,124,155, 16,123,139, 37, + 121,125, 63,124,149, 24,124,164, 9,123,172, 2,122,176, 0, + 122,178, 0,122,178, 0,123,174, 1,123,170, 3,124,166, 7, + 124,160, 12,124,155, 16,124,150, 22,124,149, 24,124,147, 26, + 124,150, 22,124,157, 15,124,166, 7,123,174, 1,121,181, 0, + 119,187, 0,117,191, 0,116,193, 0,114,196, 0,114,197, 0, + 113,198, 0,114,197, 0,115,194, 0,117,190, 0,120,184, 0, + 122,177, 0,124,166, 7,123,172, 2,118,189, 0,112,200, 0, + 107,207, 0,104,210, 0,102,212, 0,102,212, 0,102,212, 0, + 104,210, 0,106,208, 0,107,206, 0,108,205, 0,108,205, 0, + 107,206, 0,106,207, 0,107,207, 0,108,205, 0,111,201, 0, + 111,202, 0,109,204, 0,108,205, 0,109,203, 0,113,199, 0, + 117,191, 0,121,180, 0,124,167, 6,123,168, 5,123,173, 1, + 122,178, 0,120,182, 0,120,184, 0,119,185, 0,120,184, 0, + 120,182, 0,120,184, 0,118,188, 0,117,191, 0,116,193, 0, + 115,194, 0,114,196, 0,112,200, 0,109,203, 0,108,205, 0, + 109,204, 0,105,209, 0,102,213, 0, 99,215, 0, 98,216, 0, + 100,215, 0,102,212, 0,105,209, 0,109,204, 0,112,199, 0, + 115,194, 0,117,191, 0,118,189, 0,119,186, 0,121,181, 0, + 123,173, 1,124,162, 10,123,169, 4,122,178, 0,120,182, 0, + 120,184, 0,121,180, 0,123,172, 2,124,157, 15,121,127, 58, + 99, 75,247, 30, 15,143, 87, 65,237,113,100,242,121,125, 63, + 124,150, 22,124,165, 8,123,171, 3,123,174, 1,121,180, 0, + 119,185, 0,119,187, 0,119,187, 0,119,187, 0,119,187, 0, + 118,188, 0,118,188, 0,118,188, 0,119,186, 0,120,184, 0, + 120,183, 0,122,178, 0,122,175, 0,120,184, 0,118,189, 0, + 118,189, 0,120,183, 0,123,170, 3,124,149, 24,122,132, 48, + 118,114, 96, 99, 75,247, 30, 2,128, 99, 75,247,121,127, 58, + 124,152, 20,124,166, 7,123,172, 2,122,177, 0,122,178, 0, + 122,178, 0,122,178, 0,121,179, 0,121,181, 0,121,182, 0, + 121,181, 0,122,178, 0,123,173, 1,124,167, 6,124,158, 13, + 124,161, 11,124,162, 10,124,164, 9,124,162, 10,124,157, 15, + 123,141, 34,120,122, 70,117,110,109,109, 92,251,123,139, 37, + 124,165, 8,122,177, 0,120,184, 0,119,187, 0,118,189, 0, + 117,190, 0,116,192, 0,116,192, 0,118,189, 0,119,185, 0, + 120,184, 0,117,190, 0,116,193, 0,114,196, 0,114,196, 0, + 115,194, 0,112,199, 0,109,204, 0,107,207, 0,106,207, 0, + 108,206, 0,110,202, 0,113,198, 0,116,193, 0,118,189, 0, + 117,190, 0,118,189, 0,119,187, 0,120,184, 0,118,189, 0, + 114,196, 0,111,201, 0,110,202, 0,110,202, 0,112,199, 0, + 115,194, 0,116,192, 0,116,193, 0,117,190, 0,120,184, 0, + 121,179, 0,121,182, 0,120,184, 0,118,188, 0,117,191, 0, + 116,193, 0,115,195, 0,114,196, 0,114,196, 0,116,193, 0, + 118,189, 0,120,183, 0,123,174, 1,124,161, 11,123,169, 4, + 123,172, 2,123,173, 1,123,172, 2,123,173, 1,122,178, 0, + 120,184, 0,118,189, 0,115,194, 0,111,201, 0,107,206, 0, + 106,208, 0,105,209, 0,106,208, 0,105,209, 0,103,211, 0, + 104,210, 0,106,207, 0,105,209, 0, 99,215, 0, 93,221, 0, + 88,226, 0, 84,229, 0, 82,231, 0, 81,232, 0, 82,231, 0, + 78,234, 0, 75,236, 0, 75,237, 0, 76,236, 0, 79,233, 0, + 84,229, 0, 91,224, 0, 94,220, 0, 99,215, 0,106,208, 0, + 111,202, 0,115,195, 0,119,187, 0,122,176, 0,124,158, 13, + 124,145, 29,124,150, 22,124,167, 6,122,176, 0,121,180, 0, + 121,181, 0,122,178, 0,123,174, 1,124,167, 6,124,161, 11, + 124,155, 16,124,149, 24,124,145, 29,124,143, 31,124,143, 31, + 124,145, 29,124,150, 22,124,158, 13,124,167, 6,123,174, 1, + 121,180, 0,119,185, 0,118,189, 0,117,191, 0,116,193, 0, + 114,196, 0,114,197, 0,114,197, 0,114,196, 0,117,192, 0, + 119,186, 0,121,180, 0,123,171, 3,120,183, 0,114,196, 0, + 108,205, 0,103,211, 0,101,214, 0,100,214, 0,101,214, 0, + 102,213, 0,105,209, 0,102,212, 0,102,212, 0,103,211, 0, + 106,207, 0,109,204, 0,108,206, 0,108,206, 0,109,203, 0, + 112,200, 0,114,197, 0,113,198, 0,113,198, 0,114,196, 0, + 117,190, 0,121,180, 0,124,165, 8,124,167, 6,122,177, 0, + 121,181, 0,121,182, 0,119,186, 0,117,190, 0,117,192, 0, + 117,192, 0,117,191, 0,117,191, 0,115,194, 0,114,197, 0, + 113,198, 0,113,198, 0,110,203, 0,106,207, 0,103,211, 0, + 102,212, 0,103,212, 0,105,209, 0,101,213, 0, 98,216, 0, + 98,217, 0, 99,215, 0,102,212, 0,106,208, 0,109,204, 0, + 113,199, 0,115,194, 0,116,192, 0,117,191, 0,118,189, 0, + 119,186, 0,121,180, 0,123,171, 3,124,166, 7,123,174, 1, + 121,180, 0,121,181, 0,122,178, 0,123,169, 4,124,155, 16, + 122,130, 53,109, 92,251, 30, 37,192, 30, 43,203,105, 84,252, + 113,100,242,121,125, 63,124,147, 26,124,158, 13,124,164, 9, + 123,173, 1,122,178, 0,121,179, 0,120,183, 0,118,188, 0, + 118,189, 0,119,185, 0,121,181, 0,120,182, 0,121,180, 0, + 122,176, 0,122,178, 0,122,176, 0,123,174, 1,120,183, 0, + 118,188, 0,118,188, 0,122,178, 0,124,164, 9,124,162, 10, + 124,158, 13,124,147, 26,121,125, 63, 99, 75,247, 30, 37,192, + 111, 96,248,123,139, 37,124,160, 12,123,170, 3,122,175, 0, + 122,178, 0,122,178, 0,122,178, 0,121,179, 0,121,180, 0, + 121,179, 0,122,177, 0,123,172, 2,124,166, 7,124,157, 15, + 124,147, 26,124,150, 22,124,154, 18,124,157, 15,124,158, 13, + 124,152, 20,123,137, 41,122,135, 44,121,127, 58,117,110,109, + 123,137, 41,124,161, 11,123,172, 2,122,178, 0,121,182, 0, + 120,182, 0,120,184, 0,119,186, 0,118,188, 0,119,186, 0, + 120,183, 0,118,188, 0,117,191, 0,115,194, 0,114,196, 0, + 114,196, 0,113,198, 0,109,204, 0,106,208, 0,104,210, 0, + 105,209, 0,107,207, 0,110,203, 0,112,199, 0,115,194, 0, + 114,196, 0,114,197, 0,114,197, 0,115,195, 0,116,193, 0, + 117,191, 0,114,197, 0,111,202, 0,109,204, 0,108,205, 0, + 110,203, 0,112,200, 0,112,200, 0,113,199, 0,114,196, 0, + 118,189, 0,119,185, 0,120,184, 0,119,187, 0,118,188, 0, + 118,188, 0,117,191, 0,116,193, 0,115,195, 0,114,197, 0, + 114,197, 0,115,195, 0,117,192, 0,119,186, 0,121,180, 0, + 120,182, 0,120,184, 0,119,185, 0,120,184, 0,119,186, 0, + 117,191, 0,114,196, 0,113,198, 0,112,199, 0,108,206, 0, + 105,209, 0,103,211, 0,103,212, 0,103,211, 0,102,212, 0, + 102,213, 0,103,211, 0,106,208, 0,102,212, 0, 97,218, 0, + 91,224, 0, 85,229, 0, 81,232, 0, 78,234, 0, 78,235, 0, + 78,234, 0, 74,237, 0, 72,239, 0, 71,240, 0, 72,239, 0, + 76,236, 0, 82,231, 0, 88,226, 0, 91,223, 0, 96,219, 0, + 103,212, 0,110,202, 0,114,196, 0,118,188, 0,122,177, 0, + 124,158, 13,124,155, 16,123,169, 4,122,178, 0,120,184, 0, + 119,185, 0,120,184, 0,121,179, 0,123,174, 1,124,166, 7, + 124,154, 18,124,149, 24,123,141, 34,122,135, 44,121,125, 63, + 122,130, 53,122,135, 44,123,141, 34,124,152, 20,124,161, 11, + 123,169, 4,122,175, 0,121,180, 0,120,183, 0,119,186, 0, + 118,189, 0,116,192, 0,115,195, 0,114,196, 0,115,195, 0, + 116,192, 0,118,188, 0,120,182, 0,122,178, 0,117,192, 0, + 110,202, 0,104,210, 0,101,214, 0, 99,216, 0, 99,216, 0, + 100,215, 0,101,214, 0, 97,217, 0, 95,219, 0, 95,219, 0, + 98,217, 0,102,213, 0,107,207, 0,109,203, 0,109,203, 0, + 111,202, 0,113,198, 0,117,192, 0,117,191, 0,118,189, 0, + 119,185, 0,122,178, 0,124,164, 9,124,162, 10,122,175, 0, + 120,184, 0,118,188, 0,118,189, 0,118,188, 0,116,193, 0, + 114,196, 0,114,196, 0,114,196, 0,114,197, 0,112,200, 0, + 111,202, 0,110,202, 0,110,203, 0,106,208, 0,102,212, 0, + 99,216, 0, 97,217, 0, 98,217, 0,100,215, 0,102,212, 0, + 100,215, 0, 99,215, 0,100,214, 0,103,211, 0,107,207, 0, + 110,202, 0,112,200, 0,115,195, 0,117,192, 0,117,191, 0, + 117,190, 0,118,188, 0,120,184, 0,122,177, 0,124,167, 6, + 124,166, 7,123,173, 1,122,175, 0,123,171, 3,124,164, 9, + 124,149, 24,121,127, 58,111, 96,248, 69, 60,230, 30, 49,213, + 69, 60,230,102, 80,250,111, 96,248,121,125, 63,123,137, 41, + 124,149, 24,124,161, 11,124,167, 6,122,175, 0,119,186, 0, + 117,192, 0,116,193, 0,117,191, 0,120,184, 0,123,172, 2, + 123,171, 3,124,162, 10,124,167, 6,123,169, 4,123,171, 3, + 121,179, 0,120,184, 0,120,184, 0,123,170, 3,123,171, 3, + 123,172, 2,123,170, 3,124,166, 7,124,150, 22,118,117, 85, + 94, 70,242, 94, 70,242,119,119, 77,124,149, 24,124,162, 10, + 123,169, 4,123,172, 2,123,172, 2,123,172, 2,123,172, 2, + 123,172, 2,123,171, 3,124,167, 6,124,160, 12,124,150, 22, + 122,135, 44,122,132, 48,123,137, 41,123,141, 34,124,147, 26, + 124,149, 24,124,145, 29,123,137, 41,123,139, 37,122,135, 44, + 119,119, 77,123,137, 41,124,158, 13,123,168, 5,123,173, 1, + 123,174, 1,122,175, 0,122,178, 0,122,178, 0,121,181, 0, + 120,182, 0,119,186, 0,118,189, 0,116,192, 0,115,194, 0, + 115,194, 0,115,195, 0,110,202, 0,106,207, 0,104,210, 0, + 103,211, 0,104,210, 0,107,207, 0,110,202, 0,113,198, 0, + 113,199, 0,111,201, 0,111,202, 0,110,202, 0,111,201, 0, + 112,199, 0,114,197, 0,114,197, 0,110,202, 0,107,206, 0, + 106,207, 0,106,207, 0,107,206, 0,109,204, 0,110,203, 0, + 112,200, 0,113,199, 0,114,197, 0,115,194, 0,116,192, 0, + 115,194, 0,115,194, 0,116,193, 0,117,191, 0,115,194, 0, + 114,197, 0,112,199, 0,112,200, 0,113,199, 0,114,196, 0, + 116,193, 0,118,189, 0,117,192, 0,116,192, 0,116,193, 0, + 114,197, 0,112,200, 0,110,202, 0,109,204, 0,109,204, 0, + 104,210, 0,101,213, 0,100,215, 0,100,215, 0,101,214, 0, + 101,213, 0,101,213, 0,103,211, 0,104,210, 0, 98,216, 0, + 94,221, 0, 89,225, 0, 84,229, 0, 80,233, 0, 78,235, 0, + 77,235, 0, 74,237, 0, 71,240, 0, 68,242, 0, 68,242, 0, + 69,241, 0, 74,238, 0, 80,233, 0, 87,227, 0, 90,225, 0, + 95,220, 0,101,213, 0,108,205, 0,114,197, 0,118,188, 0, + 122,177, 0,124,158, 13,123,170, 3,121,180, 0,119,186, 0, + 118,189, 0,118,189, 0,119,186, 0,121,181, 0,123,174, 1, + 123,174, 1,123,173, 1,123,169, 4,124,161, 11,124,147, 26, + 122,135, 44,119,119, 77,117,110,109,120,122, 70,122,135, 44, + 124,147, 26,124,158, 13,124,166, 7,123,171, 3,122,176, 0, + 121,180, 0,120,184, 0,118,189, 0,116,192, 0,115,194, 0, + 115,194, 0,116,193, 0,118,189, 0,120,184, 0,119,187, 0, + 113,199, 0,106,208, 0,101,214, 0, 98,217, 0, 97,218, 0, + 97,217, 0, 99,216, 0, 95,220, 0, 91,223, 0, 90,225, 0, + 90,224, 0, 94,221, 0, 99,216, 0,105,209, 0,110,202, 0, + 111,202, 0,113,199, 0,115,194, 0,118,188, 0,121,181, 0, + 122,177, 0,123,170, 3,124,155, 16,124,155, 16,124,160, 12, + 122,178, 0,118,188, 0,116,192, 0,115,194, 0,115,194, 0, + 116,193, 0,114,197, 0,113,198, 0,112,199, 0,110,202, 0, + 109,204, 0,107,206, 0,107,206, 0,108,205, 0,104,210, 0, + 100,215, 0, 97,218, 0, 95,220, 0, 95,220, 0, 97,218, 0, + 99,215, 0,102,213, 0,101,214, 0,102,212, 0,105,209, 0, + 106,208, 0,107,206, 0,110,203, 0,113,198, 0,117,190, 0, + 117,190, 0,118,189, 0,118,188, 0,119,185, 0,121,180, 0, + 123,173, 1,124,166, 7,124,162, 10,124,166, 7,124,162, 10, + 124,160, 12,124,154, 18,124,143, 31,121,125, 63,109, 92,251, + 30, 49,213, 30, 43,203, 30, 43,203, 99, 75,247,114,104,197, + 119,119, 77,122,132, 48,124,145, 29,124,154, 18,122,175, 0, + 118,188, 0,116,193, 0,114,196, 0,116,193, 0,118,188, 0, + 122,178, 0,124,161, 11,124,150, 22,124,150, 22,124,160, 12, + 124,166, 7,123,173, 1,122,178, 0,122,177, 0,123,172, 2, + 123,174, 1,122,176, 0,122,178, 0,122,175, 0,124,165, 8, + 123,141, 34,113,100,242,114,104,197,117,110,109,122,132, 48, + 124,147, 26,124,157, 15,124,162, 10,123,171, 3,122,175, 0, + 122,176, 0,123,171, 3,124,164, 9,124,152, 20,123,139, 37, + 121,125, 63,119,119, 77,123,139, 37,124,150, 22,124,150, 22, + 123,141, 34,123,141, 34,123,139, 37,122,135, 44,123,139, 37, + 123,139, 37,122,130, 53,124,143, 31,124,152, 20,124,162, 10, + 124,166, 7,124,167, 6,123,174, 1,122,178, 0,121,180, 0, + 121,181, 0,120,183, 0,119,186, 0,118,189, 0,117,192, 0, + 116,193, 0,115,194, 0,114,196, 0,110,203, 0,106,208, 0, + 104,210, 0,104,210, 0,106,208, 0,109,203, 0,111,202, 0, + 110,202, 0,109,203, 0,108,205, 0,107,206, 0,107,206, 0, + 108,206, 0,109,204, 0,110,202, 0,110,202, 0,110,202, 0, + 107,207, 0,104,210, 0,103,212, 0,103,212, 0,103,211, 0, + 105,209, 0,106,208, 0,107,207, 0,108,206, 0,109,203, 0, + 112,200, 0,113,198, 0,113,199, 0,113,199, 0,113,198, 0, + 115,195, 0,114,197, 0,111,201, 0,109,204, 0,108,205, 0, + 108,205, 0,110,203, 0,111,201, 0,112,200, 0,111,201, 0, + 110,202, 0,109,204, 0,107,206, 0,106,208, 0,106,208, 0, + 106,208, 0,102,212, 0, 99,215, 0, 98,217, 0, 97,217, 0, + 98,217, 0, 99,215, 0,100,214, 0,101,214, 0,100,214, 0, + 95,220, 0, 91,224, 0, 87,227, 0, 83,230, 0, 80,233, 0, + 77,235, 0, 75,237, 0, 72,239, 0, 68,242, 0, 66,244, 0, + 65,245, 0, 67,243, 0, 71,240, 0, 77,235, 0, 84,229, 0, + 91,224, 0, 95,220, 0,101,214, 0,107,207, 0,113,198, 0, + 118,188, 0,122,178, 0,123,171, 3,121,180, 0,119,187, 0, + 117,191, 0,116,193, 0,116,192, 0,118,189, 0,120,184, 0, + 119,185, 0,119,185, 0,120,184, 0,121,179, 0,123,172, 2, + 124,160, 12,123,141, 34,121,127, 58,118,117, 85,118,117, 85, + 121,125, 63,123,137, 41,124,150, 22,124,162, 10,123,172, 2, + 121,179, 0,120,184, 0,119,187, 0,118,188, 0,117,191, 0, + 115,194, 0,115,194, 0,116,193, 0,117,190, 0,117,192, 0, + 115,194, 0,109,204, 0,102,212, 0, 97,217, 0, 95,220, 0, + 94,220, 0, 95,219, 0, 94,221, 0, 91,224, 0, 87,227, 0, + 86,228, 0, 87,227, 0, 91,223, 0, 97,218, 0,104,210, 0, + 110,203, 0,113,198, 0,115,194, 0,118,189, 0,120,182, 0, + 123,172, 2,124,162, 10,124,149, 24,123,137, 41,122,135, 44, + 124,154, 18,122,176, 0,118,188, 0,115,194, 0,114,197, 0, + 113,198, 0,113,199, 0,112,200, 0,111,202, 0,109,204, 0, + 107,207, 0,105,209, 0,104,210, 0,104,210, 0,105,209, 0, + 105,209, 0,101,214, 0, 98,217, 0, 95,219, 0, 95,219, 0, + 97,218, 0, 99,216, 0,101,214, 0,102,213, 0,102,212, 0, + 103,211, 0,104,210, 0,106,208, 0,109,204, 0,112,199, 0, + 117,191, 0,119,187, 0,118,188, 0,119,186, 0,120,184, 0, + 121,181, 0,122,175, 0,123,170, 3,123,168, 5,123,169, 4, + 123,168, 5,124,166, 7,124,161, 11,124,154, 18,123,139, 37, + 118,117, 85,105, 84,252, 87, 65,237, 30, 49,213, 87, 65,237, + 109, 92,251,114,104,197,118,114, 96,122,132, 48,124,143, 31, + 123,170, 3,120,184, 0,117,191, 0,115,194, 0,116,193, 0, + 118,189, 0,121,181, 0,123,168, 5,124,150, 22,122,130, 53, + 124,147, 26,124,158, 13,124,166, 7,123,170, 3,123,169, 4, + 123,169, 4,123,172, 2,121,179, 0,120,182, 0,121,181, 0, + 123,173, 1,124,158, 13,121,127, 58,122,130, 53,122,135, 44, + 123,139, 37,124,145, 29,124,152, 20,124,164, 9,123,172, 2, + 122,177, 0,122,177, 0,123,172, 2,124,164, 9,124,150, 22, + 122,135, 44,118,117, 85,122,135, 44,124,149, 24,124,157, 15, + 124,157, 15,124,149, 24,123,141, 34,123,137, 41,122,130, 53, + 123,141, 34,124,145, 29,123,141, 34,123,141, 34,123,141, 34, + 124,147, 26,124,154, 18,124,165, 8,123,172, 2,122,176, 0, + 122,177, 0,122,178, 0,121,180, 0,120,184, 0,119,187, 0, + 118,189, 0,117,191, 0,116,192, 0,114,196, 0,110,202, 0, + 107,207, 0,106,208, 0,107,207, 0,109,204, 0,110,202, 0, + 108,206, 0,107,207, 0,107,207, 0,106,208, 0,105,209, 0, + 105,209, 0,105,209, 0,106,208, 0,107,207, 0,107,207, 0, + 106,207, 0,106,208, 0,103,212, 0,100,214, 0, 99,216, 0, + 99,216, 0,100,215, 0,101,214, 0,102,213, 0,102,212, 0, + 104,210, 0,107,207, 0,110,202, 0,111,202, 0,110,202, 0, + 110,202, 0,112,200, 0,114,197, 0,110,203, 0,106,207, 0, + 104,210, 0,103,212, 0,103,211, 0,104,210, 0,105,209, 0, + 105,209, 0,105,209, 0,104,210, 0,103,212, 0,102,212, 0, + 102,212, 0,102,212, 0,102,213, 0, 99,215, 0, 98,217, 0, + 97,217, 0, 98,217, 0, 98,216, 0,100,215, 0,100,215, 0, + 99,216, 0, 94,220, 0, 90,224, 0, 87,227, 0, 83,230, 0, + 80,232, 0, 78,235, 0, 75,237, 0, 72,239, 0, 68,242, 0, + 65,245, 0, 64,245, 0, 65,244, 0, 69,241, 0, 75,237, 0, + 82,231, 0, 89,226, 0, 95,219, 0,100,214, 0,106,208, 0, + 111,201, 0,116,192, 0,120,183, 0,121,179, 0,119,185, 0, + 117,191, 0,115,195, 0,114,197, 0,114,196, 0,116,193, 0, + 118,189, 0,117,191, 0,117,191, 0,118,189, 0,119,186, 0, + 122,178, 0,124,166, 7,124,143, 31,120,122, 70,117,110,109, + 117,110,109,119,119, 77,122,135, 44,124,150, 22,124,164, 9, + 123,174, 1,121,182, 0,119,187, 0,118,189, 0,117,190, 0, + 117,191, 0,115,194, 0,115,195, 0,115,195, 0,114,197, 0, + 112,199, 0,111,202, 0,104,210, 0, 98,216, 0, 94,220, 0, + 92,222, 0, 92,222, 0, 93,221, 0, 90,225, 0, 87,227, 0, + 85,228, 0, 85,229, 0, 87,227, 0, 91,224, 0, 96,219, 0, + 102,212, 0,108,205, 0,114,197, 0,118,189, 0,121,182, 0, + 123,171, 3,124,158, 13,124,143, 31,118,117, 85,111, 96,248, + 107, 89,252,122,135, 44,123,168, 5,120,184, 0,116,193, 0, + 113,198, 0,111,201, 0,110,202, 0,110,203, 0,108,205, 0, + 107,207, 0,105,209, 0,103,211, 0,102,212, 0,102,213, 0, + 103,212, 0,105,209, 0,104,210, 0,101,214, 0, 99,216, 0, + 98,217, 0, 99,216, 0,100,214, 0,102,213, 0,103,212, 0, + 103,211, 0,104,210, 0,105,209, 0,106,207, 0,109,204, 0, + 112,199, 0,117,191, 0,120,183, 0,120,184, 0,120,184, 0, + 120,184, 0,121,181, 0,122,177, 0,123,172, 2,123,171, 3, + 123,171, 3,123,170, 3,124,167, 6,124,162, 10,124,154, 18, + 123,141, 34,119,119, 77,114,104,197,107, 89,252,102, 80,250, + 94, 70,242, 99, 75,247,107, 89,252,111, 96,248,118,117, 85, + 122,132, 48,124,157, 15,122,175, 0,119,185, 0,118,189, 0, + 117,191, 0,118,188, 0,120,183, 0,123,174, 1,124,162, 10, + 124,143, 31,123,139, 37,124,152, 20,124,160, 12,124,161, 11, + 124,164, 9,124,160, 12,123,172, 2,121,180, 0,120,184, 0, + 120,184, 0,122,178, 0,124,167, 6,124,145, 29,124,147, 26, + 124,150, 22,124,152, 20,124,155, 16,124,160, 12,124,164, 9, + 123,168, 5,123,173, 1,123,174, 1,123,169, 4,124,160, 12, + 124,143, 31,119,119, 77,122,135, 44,124,145, 29,124,152, 20, + 124,160, 12,124,161, 11,124,155, 16,124,143, 31,123,139, 37, + 121,127, 58,123,141, 34,124,150, 22,124,150, 22,124,149, 24, + 124,145, 29,124,143, 31,124,154, 18,124,162, 10,124,167, 6, + 123,169, 4,123,169, 4,123,170, 3,123,173, 1,122,178, 0, + 120,182, 0,119,185, 0,118,188, 0,118,189, 0,116,193, 0, + 111,201, 0,109,204, 0,108,205, 0,110,203, 0,111,201, 0, + 108,205, 0,106,208, 0,105,209, 0,105,209, 0,105,209, 0, + 104,210, 0,104,210, 0,104,210, 0,104,210, 0,104,210, 0, + 104,210, 0,103,211, 0,103,211, 0,102,213, 0, 98,217, 0, + 96,219, 0, 95,220, 0, 95,219, 0, 97,218, 0, 98,217, 0, + 99,215, 0,101,214, 0,103,212, 0,106,208, 0,109,203, 0, + 109,204, 0,108,205, 0,110,203, 0,112,199, 0,109,204, 0, + 104,210, 0,100,214, 0, 98,216, 0, 98,217, 0, 99,216, 0, + 100,215, 0,100,215, 0,100,214, 0,100,215, 0,100,215, 0, + 100,215, 0,100,215, 0,100,215, 0,100,215, 0, 99,215, 0, + 98,216, 0, 98,217, 0, 97,217, 0, 97,217, 0, 98,217, 0, + 100,215, 0, 99,215, 0, 95,220, 0, 92,223, 0, 89,226, 0, + 85,229, 0, 83,230, 0, 80,232, 0, 78,235, 0, 74,237, 0, + 70,241, 0, 66,243, 0, 65,245, 0, 66,244, 0, 69,242, 0, + 74,237, 0, 81,232, 0, 88,226, 0, 95,220, 0,100,215, 0, + 105,209, 0,109,203, 0,114,196, 0,119,187, 0,120,184, 0, + 118,188, 0,116,193, 0,114,197, 0,113,199, 0,113,199, 0, + 114,197, 0,116,193, 0,115,194, 0,115,194, 0,116,193, 0, + 118,189, 0,120,182, 0,123,169, 4,124,145, 29,117,110,109, + 109, 92,251,107, 89,252,114,104,197,121,125, 63,124,145, 29, + 124,162, 10,123,173, 1,121,182, 0,119,186, 0,118,189, 0, + 117,191, 0,116,192, 0,114,196, 0,114,196, 0,112,199, 0, + 110,202, 0,109,204, 0,107,207, 0,101,214, 0, 96,219, 0, + 92,222, 0, 91,224, 0, 91,224, 0, 90,224, 0, 87,227, 0, + 86,228, 0, 85,229, 0, 85,229, 0, 87,227, 0, 91,223, 0, + 96,219, 0,102,213, 0,108,206, 0,113,198, 0,118,189, 0, + 120,184, 0,122,178, 0,123,172, 2,124,162, 10,124,145, 29, + 117,110,109,102, 80,250,118,114, 96,124,152, 20,122,177, 0, + 118,189, 0,114,197, 0,111,201, 0,110,203, 0,109,204, 0, + 108,206, 0,106,207, 0,105,209, 0,103,211, 0,102,213, 0, + 101,214, 0,101,213, 0,103,211, 0,106,207, 0,106,208, 0, + 103,211, 0,102,212, 0,102,212, 0,103,211, 0,105,209, 0, + 105,209, 0,106,208, 0,106,208, 0,106,207, 0,108,206, 0, + 110,202, 0,113,198, 0,118,189, 0,122,178, 0,121,180, 0, + 121,182, 0,120,184, 0,120,184, 0,121,182, 0,122,175, 0, + 123,170, 3,123,170, 3,123,168, 5,124,164, 9,124,157, 15, + 124,147, 26,122,132, 48,118,117, 85,115,107,129,113,100,242, + 111, 96,248,109, 92,251,105, 84,252, 94, 70,242, 99, 75,247, + 113,100,242,120,122, 70,122,135, 44,124,160, 12,123,174, 1, + 121,182, 0,119,185, 0,119,185, 0,120,182, 0,122,177, 0, + 123,169, 4,124,158, 13,123,137, 41,124,143, 31,124,150, 22, + 124,150, 22,124,149, 24,124,150, 22,123,168, 5,122,178, 0, + 120,184, 0,120,184, 0,121,180, 0,123,170, 3,124,155, 16, + 124,157, 15,124,158, 13,124,158, 13,124,158, 13,124,160, 12, + 124,161, 11,124,164, 9,124,164, 9,124,165, 8,124,160, 12, + 124,147, 26,120,122, 70,122,135, 44,124,143, 31,124,150, 22, + 124,155, 16,124,161, 11,124,164, 9,124,160, 12,124,149, 24, + 124,143, 31,122,132, 48,123,137, 41,124,150, 22,124,155, 16, + 124,157, 15,124,157, 15,124,155, 16,124,150, 22,124,155, 16, + 124,158, 13,124,158, 13,124,155, 16,124,155, 16,124,161, 11, + 123,168, 5,123,174, 1,121,179, 0,120,183, 0,119,186, 0, + 118,189, 0,114,197, 0,111,201, 0,111,201, 0,113,199, 0, + 111,202, 0,108,205, 0,106,208, 0,106,208, 0,106,207, 0, + 106,208, 0,105,209, 0,105,209, 0,104,210, 0,104,210, 0, + 103,211, 0,103,212, 0,102,212, 0,102,212, 0,101,214, 0, + 96,219, 0, 93,221, 0, 92,222, 0, 92,222, 0, 94,220, 0, + 96,219, 0, 97,217, 0, 99,216, 0,101,214, 0,103,211, 0, + 107,207, 0,109,204, 0,108,205, 0,110,203, 0,112,200, 0, + 108,205, 0,102,212, 0, 98,217, 0, 95,219, 0, 95,220, 0, + 95,219, 0, 97,218, 0, 97,217, 0, 98,217, 0, 98,216, 0, + 99,216, 0, 99,216, 0, 98,216, 0, 98,216, 0, 98,217, 0, + 97,217, 0, 97,218, 0, 96,219, 0, 96,219, 0, 96,219, 0, + 97,218, 0, 98,217, 0, 98,216, 0, 95,220, 0, 91,223, 0, + 88,226, 0, 85,228, 0, 84,229, 0, 84,229, 0, 82,231, 0, + 78,234, 0, 74,238, 0, 70,241, 0, 68,242, 0, 68,242, 0, + 71,240, 0, 75,236, 0, 82,231, 0, 88,226, 0, 96,219, 0, + 100,215, 0,103,211, 0,108,206, 0,113,198, 0,118,189, 0, + 119,186, 0,118,189, 0,115,194, 0,113,198, 0,112,200, 0, + 111,201, 0,111,201, 0,113,198, 0,114,197, 0,114,197, 0, + 115,195, 0,117,191, 0,120,184, 0,123,170, 3,124,143, 31, + 107, 89,252, 69, 60,230, 99, 75,247,115,107,129,121,127, 58, + 123,141, 34,124,157, 15,123,170, 3,121,179, 0,120,184, 0, + 119,187, 0,118,189, 0,115,195, 0,113,198, 0,113,198, 0, + 111,202, 0,108,205, 0,107,207, 0,104,210, 0, 98,216, 0, + 94,221, 0, 91,223, 0, 89,225, 0, 89,225, 0, 87,227, 0, + 85,228, 0, 85,229, 0, 86,228, 0, 87,227, 0, 89,225, 0, + 93,222, 0, 97,217, 0,102,212, 0,108,206, 0,113,198, 0, + 116,193, 0,117,191, 0,119,187, 0,120,182, 0,122,175, 0, + 124,165, 8,124,145, 29,114,104,197,122,135, 44,124,157, 15, + 123,168, 5,120,183, 0,116,193, 0,112,199, 0,110,202, 0, + 110,203, 0,109,204, 0,108,205, 0,107,207, 0,105,209, 0, + 103,211, 0,102,212, 0,102,212, 0,103,211, 0,106,208, 0, + 109,204, 0,108,205, 0,107,206, 0,107,207, 0,108,206, 0, + 108,205, 0,107,207, 0,108,205, 0,109,204, 0,109,204, 0, + 110,202, 0,112,200, 0,115,194, 0,119,186, 0,123,172, 2, + 122,175, 0,121,181, 0,119,186, 0,119,186, 0,120,184, 0, + 122,178, 0,124,167, 6,124,165, 8,124,161, 11,124,154, 18, + 124,147, 26,124,143, 31,122,132, 48,121,125, 63,121,125, 63, + 120,122, 70,117,110,109,114,104,197,113,100,242,109, 92,251, + 94, 70,242, 94, 70,242,115,107,129,122,130, 53,123,141, 34, + 124,154, 18,124,167, 6,122,175, 0,122,178, 0,121,179, 0, + 122,178, 0,123,173, 1,124,167, 6,124,154, 18,122,130, 53, + 123,137, 41,122,135, 44,121,127, 58,123,137, 41,124,161, 11, + 123,174, 1,121,180, 0,121,182, 0,122,178, 0,123,169, 4, + 124,158, 13,124,160, 12,124,160, 12,124,157, 15,124,154, 18, + 124,152, 20,124,152, 20,124,154, 18,124,154, 18,124,149, 24, + 123,137, 41,118,117, 85,122,132, 48,124,143, 31,124,150, 22, + 124,154, 18,124,165, 8,124,167, 6,124,166, 7,124,165, 8, + 124,158, 13,124,147, 26,122,135, 44,121,125, 63,124,147, 26, + 124,155, 16,124,160, 12,124,162, 10,124,161, 11,124,157, 15, + 124,145, 29,123,141, 34,123,137, 41,122,132, 48,124,143, 31, + 124,145, 29,124,152, 20,124,162, 10,123,170, 3,122,177, 0, + 121,180, 0,120,184, 0,116,192, 0,114,196, 0,114,197, 0, + 115,195, 0,112,199, 0,110,203, 0,108,205, 0,108,205, 0, + 109,204, 0,108,206, 0,105,209, 0,103,212, 0,102,212, 0, + 102,212, 0,104,210, 0,103,211, 0,103,212, 0,102,212, 0, + 99,215, 0, 94,220, 0, 91,223, 0, 90,225, 0, 91,223, 0, + 93,222, 0, 95,220, 0, 97,218, 0, 98,217, 0,100,215, 0, + 102,212, 0,106,208, 0,109,203, 0,110,202, 0,111,201, 0, + 113,198, 0,107,206, 0,102,213, 0, 98,217, 0, 95,220, 0, + 94,220, 0, 95,220, 0, 96,219, 0, 97,217, 0, 98,216, 0, + 99,215, 0,100,215, 0,100,215, 0, 99,215, 0, 99,216, 0, + 98,217, 0, 97,218, 0, 96,219, 0, 95,219, 0, 95,220, 0, + 95,220, 0, 95,219, 0, 96,219, 0, 97,218, 0, 94,220, 0, + 91,223, 0, 89,226, 0, 87,227, 0, 86,228, 0, 87,227, 0, + 87,227, 0, 84,229, 0, 79,234, 0, 74,237, 0, 72,239, 0, + 72,239, 0, 74,237, 0, 78,234, 0, 84,229, 0, 91,224, 0, + 97,218, 0, 98,216, 0,102,213, 0,106,208, 0,111,201, 0, + 117,191, 0,119,186, 0,118,189, 0,116,193, 0,113,198, 0, + 111,201, 0,110,203, 0,109,203, 0,110,202, 0,113,198, 0, + 113,198, 0,114,197, 0,116,193, 0,119,185, 0,123,171, 3, + 123,141, 34, 99, 75,247, 30, 26,168,109, 92,251,118,117, 85, + 122,132, 48,124,150, 22,124,160, 12,124,166, 7,122,176, 0, + 121,182, 0,120,184, 0,116,193, 0,113,199, 0,111,202, 0, + 111,202, 0,111,202, 0,108,205, 0,106,207, 0,103,212, 0, + 98,217, 0, 94,221, 0, 91,223, 0, 89,225, 0, 88,226, 0, + 85,229, 0, 84,229, 0, 85,228, 0, 87,227, 0, 90,225, 0, + 93,222, 0, 96,219, 0,100,215, 0,104,210, 0,109,204, 0, + 112,199, 0,113,198, 0,114,196, 0,116,192, 0,118,189, 0, + 120,184, 0,122,177, 0,124,166, 7,123,141, 34,124,147, 26, + 124,164, 9,123,173, 1,122,178, 0,119,186, 0,115,194, 0, + 113,198, 0,112,199, 0,112,200, 0,111,201, 0,110,202, 0, + 109,204, 0,107,207, 0,105,209, 0,105,209, 0,105,209, 0, + 107,206, 0,110,203, 0,112,200, 0,112,199, 0,112,200, 0, + 112,200, 0,110,202, 0,109,204, 0,110,202, 0,112,200, 0, + 112,200, 0,113,198, 0,115,195, 0,118,189, 0,121,180, 0, + 124,166, 7,123,173, 1,120,182, 0,119,186, 0,119,187, 0, + 120,184, 0,122,176, 0,124,165, 8,124,155, 16,124,147, 26, + 124,155, 16,124,158, 13,124,155, 16,124,145, 29,123,141, 34, + 123,139, 37,123,137, 41,122,130, 53,118,117, 85,118,117, 85, + 117,110,109,111, 96,248, 94, 70,242,109, 92,251,118,117, 85, + 123,141, 34,124,154, 18,124,160, 12,124,161, 11,123,168, 5, + 123,173, 1,122,175, 0,123,174, 1,123,172, 2,124,165, 8, + 124,147, 26,118,117, 85,118,114, 96,119,119, 77,119,119, 77, + 124,150, 22,124,167, 6,122,175, 0,122,177, 0,123,173, 1, + 124,164, 9,124,158, 13,124,158, 13,124,155, 16,124,150, 22, + 124,147, 26,124,150, 22,124,145, 29,122,135, 44,122,135, 44, + 122,130, 53,115,107,129,118,114, 96,122,135, 44,124,147, 26, + 124,154, 18,124,164, 9,123,172, 2,123,174, 1,123,171, 3, + 123,170, 3,124,167, 6,124,158, 13,123,141, 34,121,125, 63, + 122,135, 44,124,150, 22,124,158, 13,124,162, 10,124,162, 10, + 124,158, 13,124,145, 29,120,122, 70,114,104,197,117,110,109, + 121,125, 63,121,127, 58,121,127, 58,124,143, 31,124,158, 13, + 124,167, 6,123,173, 1,122,177, 0,119,186, 0,117,191, 0, + 117,192, 0,117,191, 0,115,195, 0,113,199, 0,112,200, 0, + 112,200, 0,110,203, 0,107,206, 0,105,209, 0,103,211, 0, + 102,213, 0,102,213, 0,103,211, 0,105,209, 0,105,209, 0, + 103,211, 0, 97,217, 0, 92,222, 0, 89,225, 0, 89,226, 0, + 90,225, 0, 92,222, 0, 93,221, 0, 96,219, 0, 99,216, 0, + 101,214, 0,103,211, 0,107,207, 0,110,202, 0,113,198, 0, + 114,197, 0,113,199, 0,107,207, 0,102,213, 0, 98,217, 0, + 97,218, 0, 96,219, 0, 97,218, 0, 98,216, 0,100,215, 0, + 101,213, 0,102,212, 0,103,212, 0,102,212, 0,102,212, 0, + 101,214, 0,100,215, 0, 99,216, 0, 97,217, 0, 97,218, 0, + 96,219, 0, 95,219, 0, 95,220, 0, 95,219, 0, 95,220, 0, + 94,220, 0, 92,222, 0, 90,224, 0, 89,225, 0, 89,225, 0, + 90,224, 0, 92,222, 0, 89,225, 0, 85,229, 0, 80,232, 0, + 78,235, 0, 77,235, 0, 79,233, 0, 83,230, 0, 88,226, 0, + 94,221, 0, 96,219, 0, 97,217, 0,100,215, 0,105,209, 0, + 110,202, 0,116,192, 0,119,186, 0,118,189, 0,115,194, 0, + 114,197, 0,111,201, 0,109,204, 0,108,206, 0,108,205, 0, + 111,202, 0,112,200, 0,113,198, 0,115,194, 0,119,187, 0, + 123,173, 1,123,141, 34, 87, 65,237, 30, 43,203,115,107,129, + 122,132, 48,123,141, 34,124,154, 18,124,164, 9,123,169, 4, + 123,172, 2,122,178, 0,118,188, 0,114,197, 0,110,202, 0, + 108,205, 0,108,205, 0,110,203, 0,109,204, 0,107,206, 0, + 103,212, 0, 98,216, 0, 94,220, 0, 91,223, 0, 89,225, 0, + 86,228, 0, 83,230, 0, 84,229, 0, 83,230, 0, 83,230, 0, + 87,227, 0, 92,222, 0, 99,215, 0,103,211, 0,107,207, 0, + 111,202, 0,112,200, 0,112,199, 0,113,198, 0,114,196, 0, + 116,192, 0,118,189, 0,120,184, 0,122,177, 0,124,162, 10, + 124,162, 10,123,169, 4,122,177, 0,121,181, 0,121,182, 0, + 118,188, 0,116,192, 0,116,193, 0,113,198, 0,110,202, 0, + 109,204, 0,110,203, 0,111,201, 0,109,203, 0,108,205, 0, + 109,204, 0,110,202, 0,112,200, 0,114,197, 0,115,194, 0, + 116,193, 0,115,194, 0,113,198, 0,112,200, 0,113,198, 0, + 115,194, 0,115,194, 0,116,193, 0,118,189, 0,120,183, 0, + 123,171, 3,124,161, 11,123,174, 1,120,182, 0,119,186, 0, + 119,186, 0,121,181, 0,123,171, 3,124,157, 15,123,139, 37, + 124,155, 16,124,165, 8,124,167, 6,124,164, 9,124,155, 16, + 124,152, 20,124,149, 24,124,147, 26,124,143, 31,123,137, 41, + 121,127, 58,120,122, 70,118,114, 96,111, 96,248,113,100,242, + 121,127, 58,124,147, 26,124,158, 13,124,165, 8,124,167, 6, + 124,164, 9,124,164, 9,123,170, 3,123,173, 1,123,174, 1, + 123,170, 3,124,160, 12,123,141, 34,118,114, 96,118,114, 96, + 114,104,197,123,139, 37,124,160, 12,123,168, 5,123,169, 4, + 124,165, 8,124,157, 15,124,154, 18,124,152, 20,124,149, 24, + 124,154, 18,124,162, 10,124,165, 8,124,160, 12,124,145, 29, + 117,110,109,113,100,242,115,107,129,121,127, 58,123,137, 41, + 124,147, 26,124,157, 15,123,168, 5,122,176, 0,122,178, 0, + 123,174, 1,122,177, 0,122,176, 0,123,170, 3,124,160, 12, + 123,139, 37,118,117, 85,123,137, 41,124,150, 22,124,158, 13, + 124,161, 11,124,157, 15,124,143, 31,118,117, 85, 87, 65,237, + 94, 70,242,109, 92,251,111, 96,248,111, 96,248,121,125, 63, + 124,145, 29,124,155, 16,124,162, 10,124,167, 6,121,180, 0, + 119,186, 0,118,188, 0,118,188, 0,118,189, 0,116,192, 0, + 114,196, 0,112,200, 0,111,202, 0,109,204, 0,107,207, 0, + 105,209, 0,103,211, 0,103,211, 0,105,209, 0,108,206, 0, + 107,207, 0,101,214, 0, 95,220, 0, 90,224, 0, 87,227, 0, + 87,227, 0, 89,225, 0, 91,223, 0, 91,223, 0, 94,221, 0, + 98,216, 0,103,212, 0,106,208, 0,109,204, 0,113,199, 0, + 117,191, 0,116,192, 0,111,201, 0,106,207, 0,102,212, 0, + 100,215, 0, 99,215, 0,100,215, 0,101,214, 0,102,212, 0, + 104,210, 0,104,210, 0,104,210, 0,106,208, 0,107,207, 0, + 106,208, 0,105,209, 0,103,211, 0,102,212, 0,100,214, 0, + 99,215, 0, 98,217, 0, 97,217, 0, 97,218, 0, 96,219, 0, + 95,220, 0, 94,221, 0, 92,222, 0, 92,222, 0, 93,222, 0, + 94,221, 0, 95,220, 0, 97,218, 0, 95,220, 0, 90,224, 0, + 86,228, 0, 83,230, 0, 83,230, 0, 85,229, 0, 89,226, 0, + 93,222, 0, 96,219, 0, 95,219, 0, 96,219, 0, 98,216, 0, + 103,211, 0,109,203, 0,116,193, 0,119,185, 0,116,192, 0, + 114,197, 0,112,200, 0,110,202, 0,108,205, 0,107,207, 0, + 107,207, 0,109,204, 0,111,202, 0,111,201, 0,114,197, 0, + 118,189, 0,122,177, 0,124,149, 24, 99, 75,247, 30, 37,192, + 115,107,129,122,132, 48,124,145, 29,124,155, 16,124,166, 7, + 123,171, 3,123,173, 1,122,177, 0,117,190, 0,112,199, 0, + 108,206, 0,105,209, 0,105,209, 0,107,207, 0,110,202, 0, + 109,203, 0,105,209, 0,100,215, 0, 96,219, 0, 93,222, 0, + 88,226, 0, 84,229, 0, 82,231, 0, 83,230, 0, 81,232, 0, + 81,232, 0, 83,230, 0, 89,226, 0, 96,219, 0,104,210, 0, + 110,203, 0,113,198, 0,113,198, 0,113,199, 0,113,198, 0, + 114,196, 0,115,194, 0,117,191, 0,119,187, 0,120,182, 0, + 123,172, 2,123,172, 2,123,173, 1,121,179, 0,120,182, 0, + 120,182, 0,121,180, 0,120,184, 0,117,190, 0,113,199, 0, + 109,203, 0,108,205, 0,109,204, 0,111,201, 0,114,196, 0, + 113,199, 0,112,200, 0,111,201, 0,112,200, 0,113,199, 0, + 114,196, 0,116,193, 0,118,189, 0,117,192, 0,115,194, 0, + 116,193, 0,118,189, 0,118,188, 0,119,186, 0,120,183, 0, + 122,175, 0,124,161, 11,124,161, 11,123,174, 1,121,181, 0, + 120,184, 0,120,182, 0,122,175, 0,124,162, 10,123,141, 34, + 124,145, 29,124,164, 9,123,170, 3,123,172, 2,123,168, 5, + 124,158, 13,124,154, 18,124,149, 24,124,149, 24,124,149, 24, + 124,147, 26,123,141, 34,122,132, 48,120,122, 70,115,107,129, + 113,100,242,122,132, 48,124,157, 15,123,170, 3,122,177, 0, + 122,178, 0,122,176, 0,123,169, 4,123,168, 5,123,174, 1, + 122,178, 0,121,179, 0,122,175, 0,124,165, 8,123,141, 34, + 115,107,129,107, 89,252,122,132, 48,124,154, 18,124,162, 10, + 124,164, 9,124,160, 12,124,157, 15,124,150, 22,124,147, 26, + 124,160, 12,123,168, 5,123,174, 1,123,174, 1,123,170, 3, + 124,158, 13,122,130, 53, 99, 75,247,118,114, 96,123,137, 41, + 124,149, 24,124,155, 16,124,160, 12,124,166, 7,123,174, 1, + 122,176, 0,121,181, 0,120,184, 0,120,184, 0,121,180, 0, + 123,173, 1,124,161, 11,123,139, 37,117,110,109,122,132, 48, + 124,147, 26,124,154, 18,124,152, 20,124,143, 31,119,119, 77, + 94, 70,242, 30, 2,128, 30, 55,222,105, 84,252,115,107,129, + 122,135, 44,124,152, 20,124,160, 12,124,161, 11,124,154, 18, + 123,173, 1,121,182, 0,119,185, 0,119,186, 0,119,185, 0, + 118,189, 0,115,194, 0,113,198, 0,110,202, 0,108,206, 0, + 107,207, 0,106,207, 0,106,208, 0,106,208, 0,107,207, 0, + 110,202, 0,105,209, 0, 98,216, 0, 92,222, 0, 88,226, 0, + 86,228, 0, 86,228, 0, 89,226, 0, 92,222, 0, 92,222, 0, + 94,220, 0, 98,216, 0,103,211, 0,108,206, 0,111,201, 0, + 115,194, 0,119,186, 0,115,194, 0,111,202, 0,106,207, 0, + 103,211, 0,102,212, 0,102,212, 0,104,210, 0,105,209, 0, + 104,210, 0,103,212, 0,103,212, 0,103,211, 0,105,209, 0, + 107,206, 0,109,204, 0,110,203, 0,107,207, 0,105,209, 0, + 103,211, 0,102,212, 0,102,212, 0,101,214, 0,100,215, 0, + 99,215, 0, 97,217, 0, 95,219, 0, 94,221, 0, 93,222, 0, + 93,221, 0, 95,220, 0, 98,217, 0,102,212, 0, 99,216, 0, + 94,220, 0, 91,224, 0, 88,226, 0, 88,226, 0, 90,224, 0, + 94,221, 0, 97,217, 0, 96,219, 0, 95,220, 0, 95,220, 0, + 98,217, 0,102,212, 0,108,205, 0,115,195, 0,120,184, 0, + 116,192, 0,113,198, 0,111,202, 0,109,204, 0,108,205, 0, + 107,207, 0,106,207, 0,109,204, 0,108,205, 0,109,204, 0, + 111,201, 0,115,194, 0,120,183, 0,124,161, 11,115,107,129, + 30, 2,128,105, 84,252,119,119, 77,123,137, 41,124,157, 15, + 124,167, 6,123,172, 2,123,174, 1,122,178, 0,117,191, 0, + 111,201, 0,106,207, 0,103,211, 0,103,212, 0,104,210, 0, + 107,206, 0,111,201, 0,106,207, 0,102,213, 0, 98,217, 0, + 92,223, 0, 87,227, 0, 83,230, 0, 82,231, 0, 83,230, 0, + 81,232, 0, 80,232, 0, 82,231, 0, 87,227, 0, 93,221, 0, + 101,213, 0,109,203, 0,116,193, 0,115,195, 0,114,196, 0, + 114,197, 0,113,198, 0,113,198, 0,114,196, 0,117,191, 0, + 120,182, 0,123,174, 1,123,173, 1,122,178, 0,120,182, 0, + 120,184, 0,120,183, 0,121,181, 0,122,175, 0,118,189, 0, + 113,198, 0,109,203, 0,108,206, 0,108,205, 0,111,202, 0, + 114,197, 0,115,195, 0,113,198, 0,112,200, 0,112,199, 0, + 113,198, 0,113,198, 0,114,196, 0,117,192, 0,120,184, 0, + 119,187, 0,119,186, 0,120,184, 0,120,184, 0,121,182, 0, + 122,176, 0,124,167, 6,124,149, 24,124,158, 13,123,170, 3, + 122,178, 0,121,179, 0,122,176, 0,124,167, 6,124,149, 24, + 118,117, 85,124,152, 20,124,167, 6,123,173, 1,123,174, 1, + 123,168, 5,124,157, 15,124,145, 29,123,141, 34,124,147, 26, + 124,150, 22,124,150, 22,124,152, 20,124,150, 22,124,143, 31, + 121,127, 58,109, 92,251,122,130, 53,124,158, 13,123,174, 1, + 120,182, 0,119,185, 0,120,184, 0,121,181, 0,123,173, 1, + 121,180, 0,120,184, 0,119,186, 0,120,183, 0,122,175, 0, + 124,160, 12,122,130, 53,119,119, 77,123,137, 41,124,150, 22, + 124,160, 12,124,162, 10,124,161, 11,124,157, 15,124,154, 18, + 124,164, 9,123,170, 3,122,177, 0,121,180, 0,121,180, 0, + 122,176, 0,124,166, 7,124,143, 31,120,122, 70,120,122, 70, + 124,145, 29,124,158, 13,124,165, 8,123,168, 5,123,170, 3, + 122,176, 0,121,182, 0,119,186, 0,118,189, 0,118,189, 0, + 118,188, 0,120,184, 0,122,176, 0,124,165, 8,124,150, 22, + 122,130, 53,119,119, 77,122,135, 44,123,139, 37,122,135, 44, + 121,125, 63,115,107,129,102, 80,250, 69, 60,230,111, 96,248, + 121,127, 58,124,147, 26,124,158, 13,124,165, 8,124,166, 7, + 124,161, 11,123,169, 4,122,176, 0,121,182, 0,119,186, 0, + 118,189, 0,116,192, 0,114,196, 0,111,201, 0,108,205, 0, + 106,208, 0,105,209, 0,105,209, 0,105,209, 0,106,208, 0, + 107,207, 0,106,207, 0,101,213, 0, 95,219, 0, 90,224, 0, + 87,227, 0, 85,229, 0, 86,228, 0, 89,226, 0, 92,222, 0, + 95,219, 0, 97,217, 0,101,214, 0,105,209, 0,110,202, 0, + 114,196, 0,117,190, 0,118,189, 0,114,196, 0,110,202, 0, + 107,207, 0,105,209, 0,105,209, 0,106,208, 0,107,206, 0, + 105,209, 0,104,210, 0,103,211, 0,103,211, 0,104,210, 0, + 106,208, 0,108,206, 0,108,206, 0,106,208, 0,105,209, 0, + 104,210, 0,103,211, 0,102,212, 0,102,212, 0,102,213, 0, + 100,215, 0, 98,217, 0, 97,218, 0, 97,217, 0, 95,220, 0, + 94,221, 0, 94,221, 0, 95,219, 0, 98,216, 0,100,215, 0, + 100,215, 0, 98,216, 0, 95,220, 0, 93,221, 0, 93,221, 0, + 95,220, 0, 98,217, 0,100,215, 0, 98,217, 0, 96,219, 0, + 96,219, 0, 98,217, 0,102,212, 0,108,205, 0,114,196, 0, + 119,186, 0,117,191, 0,113,198, 0,110,202, 0,108,205, 0, + 107,207, 0,106,208, 0,106,208, 0,106,208, 0,105,209, 0, + 106,208, 0,108,205, 0,113,199, 0,118,189, 0,123,172, 2, + 123,137, 41, 69, 60,230, 94, 70,242,118,114, 96,123,141, 34, + 124,158, 13,124,167, 6,123,172, 2,122,175, 0,121,180, 0, + 117,191, 0,111,201, 0,106,208, 0,102,212, 0,101,214, 0, + 102,212, 0,105,209, 0,109,204, 0,106,208, 0,101,213, 0, + 96,219, 0, 90,224, 0, 86,228, 0, 83,230, 0, 82,231, 0, + 83,230, 0, 82,231, 0, 81,232, 0, 83,230, 0, 87,227, 0, + 93,222, 0,100,214, 0,108,206, 0,114,197, 0,114,197, 0, + 113,199, 0,112,200, 0,111,202, 0,111,201, 0,112,199, 0, + 115,195, 0,118,188, 0,122,178, 0,122,176, 0,121,181, 0, + 120,184, 0,120,184, 0,120,183, 0,121,180, 0,120,182, 0, + 118,188, 0,114,196, 0,111,202, 0,109,204, 0,109,203, 0, + 110,203, 0,111,201, 0,112,200, 0,112,200, 0,112,200, 0, + 111,201, 0,111,201, 0,111,201, 0,113,199, 0,115,194, 0, + 119,187, 0,121,180, 0,121,180, 0,121,181, 0,121,179, 0, + 122,177, 0,123,171, 3,124,160, 12,123,139, 37,124,147, 26, + 124,161, 11,123,168, 5,123,169, 4,124,165, 8,124,150, 22, + 119,119, 77,122,132, 48,124,160, 12,123,172, 2,122,177, 0, + 122,175, 0,123,169, 4,124,157, 15,122,135, 44,124,149, 24, + 124,155, 16,124,157, 15,124,154, 18,124,161, 11,124,164, 9, + 124,162, 10,124,154, 18,122,135, 44,122,132, 48,124,157, 15, + 122,175, 0,120,184, 0,118,189, 0,117,190, 0,118,188, 0, + 120,182, 0,120,183, 0,118,188, 0,118,189, 0,119,187, 0, + 121,181, 0,123,169, 4,124,147, 26,124,145, 29,124,145, 29, + 124,154, 18,124,160, 12,124,161, 11,124,158, 13,124,157, 15, + 124,167, 6,123,172, 2,122,176, 0,121,180, 0,120,182, 0, + 120,182, 0,122,178, 0,123,169, 4,124,160, 12,124,155, 16, + 124,154, 18,124,155, 16,124,165, 8,123,172, 2,122,175, 0, + 122,176, 0,122,178, 0,120,183, 0,118,188, 0,117,191, 0, + 116,193, 0,116,192, 0,117,191, 0,119,186, 0,121,181, 0, + 123,174, 1,124,166, 7,124,150, 22,122,132, 48,123,141, 34, + 124,145, 29,124,143, 31,123,137, 41,121,127, 58,118,117, 85, + 118,117, 85,123,141, 34,124,157, 15,124,167, 6,123,171, 3, + 123,172, 2,123,169, 4,123,169, 4,122,178, 0,120,184, 0, + 118,189, 0,116,192, 0,114,196, 0,113,199, 0,110,202, 0, + 108,206, 0,106,208, 0,105,209, 0,104,210, 0,104,210, 0, + 105,209, 0,106,208, 0,102,212, 0, 98,217, 0, 94,221, 0, + 90,225, 0, 87,227, 0, 87,227, 0, 88,226, 0, 90,224, 0, + 94,221, 0, 97,217, 0,101,213, 0,105,209, 0,108,205, 0, + 112,200, 0,115,194, 0,118,189, 0,116,192, 0,113,198, 0, + 110,202, 0,108,206, 0,107,207, 0,107,207, 0,108,205, 0, + 108,205, 0,106,208, 0,105,209, 0,105,209, 0,106,208, 0, + 107,207, 0,108,205, 0,109,203, 0,107,207, 0,105,209, 0, + 104,210, 0,103,211, 0,103,212, 0,103,212, 0,103,212, 0, + 102,212, 0,100,215, 0, 98,217, 0, 97,218, 0, 97,218, 0, + 95,220, 0, 93,221, 0, 93,221, 0, 95,220, 0, 98,217, 0, + 98,217, 0, 98,217, 0, 99,216, 0,101,214, 0, 99,215, 0, + 99,215, 0,101,214, 0,103,211, 0,105,209, 0,103,212, 0, + 101,214, 0,100,215, 0,101,214, 0,104,210, 0,109,204, 0, + 114,196, 0,118,188, 0,118,189, 0,114,197, 0,110,203, 0, + 107,207, 0,105,209, 0,103,211, 0,103,211, 0,103,211, 0, + 103,211, 0,104,210, 0,107,207, 0,111,201, 0,117,192, 0, + 122,178, 0,124,152, 20,114,104,197,109, 92,251,121,125, 63, + 124,145, 29,124,157, 15,124,164, 9,124,167, 6,123,174, 1, + 121,181, 0,116,192, 0,111,201, 0,106,208, 0,102,212, 0, + 100,214, 0,101,214, 0,103,211, 0,106,208, 0,103,212, 0, + 99,216, 0, 94,221, 0, 89,225, 0, 86,228, 0, 84,229, 0, + 84,229, 0, 85,228, 0, 83,230, 0, 83,230, 0, 84,229, 0, + 88,226, 0, 94,221, 0,101,214, 0,108,206, 0,112,199, 0, + 112,200, 0,111,202, 0,110,202, 0,110,203, 0,110,202, 0, + 112,200, 0,114,196, 0,117,190, 0,121,182, 0,122,176, 0, + 121,180, 0,120,182, 0,120,182, 0,120,184, 0,119,186, 0, + 118,189, 0,115,194, 0,113,199, 0,110,202, 0,108,205, 0, + 107,206, 0,107,206, 0,108,205, 0,109,204, 0,109,204, 0, + 109,204, 0,109,204, 0,109,203, 0,110,202, 0,112,199, 0, + 115,195, 0,118,188, 0,121,181, 0,122,175, 0,122,175, 0, + 123,174, 1,123,171, 3,124,166, 7,124,154, 18,122,132, 48, + 121,127, 58,124,143, 31,124,150, 22,124,149, 24,123,137, 41, + 121,125, 63,117,110,109,124,150, 22,123,169, 4,122,178, 0, + 121,181, 0,121,179, 0,123,173, 1,124,161, 11,124,145, 29, + 124,147, 26,124,154, 18,124,154, 18,124,161, 11,123,169, 4, + 123,174, 1,123,174, 1,123,170, 3,124,160, 12,124,155, 16, + 124,155, 16,122,176, 0,119,187, 0,116,193, 0,115,194, 0, + 116,193, 0,118,189, 0,120,184, 0,118,189, 0,117,191, 0, + 117,190, 0,119,186, 0,122,177, 0,124,164, 9,124,162, 10, + 124,154, 18,124,154, 18,124,157, 15,124,157, 15,124,162, 10, + 123,169, 4,123,174, 1,122,177, 0,122,178, 0,121,180, 0, + 121,181, 0,121,181, 0,122,177, 0,122,177, 0,122,175, 0, + 123,173, 1,123,171, 3,123,171, 3,123,172, 2,122,178, 0, + 121,180, 0,121,181, 0,121,181, 0,120,182, 0,119,187, 0, + 117,191, 0,116,193, 0,115,194, 0,115,194, 0,116,193, 0, + 117,190, 0,119,187, 0,120,182, 0,122,176, 0,124,166, 7, + 124,154, 18,124,149, 24,124,152, 20,124,152, 20,124,149, 24, + 124,145, 29,124,145, 29,124,152, 20,124,165, 8,123,173, 1, + 122,177, 0,122,178, 0,122,177, 0,123,174, 1,122,178, 0, + 119,185, 0,117,191, 0,115,194, 0,113,198, 0,112,200, 0, + 110,202, 0,109,204, 0,107,207, 0,106,208, 0,105,209, 0, + 105,209, 0,105,209, 0,102,212, 0,100,215, 0, 96,219, 0, + 94,221, 0, 91,223, 0, 90,224, 0, 90,224, 0, 92,223, 0, + 94,221, 0, 97,218, 0,100,214, 0,105,209, 0,110,203, 0, + 113,199, 0,115,194, 0,117,190, 0,118,189, 0,115,194, 0, + 113,199, 0,111,202, 0,110,203, 0,110,203, 0,110,202, 0, + 111,201, 0,109,204, 0,108,205, 0,108,205, 0,108,205, 0, + 109,204, 0,110,202, 0,111,201, 0,111,201, 0,108,205, 0, + 106,207, 0,105,209, 0,105,209, 0,104,210, 0,105,209, 0, + 106,208, 0,104,210, 0,101,213, 0, 99,216, 0, 97,217, 0, + 96,219, 0, 94,221, 0, 92,222, 0, 92,222, 0, 94,221, 0, + 97,218, 0, 96,219, 0, 96,219, 0, 98,217, 0,101,214, 0, + 105,209, 0,106,208, 0,107,207, 0,108,205, 0,110,203, 0, + 109,204, 0,107,207, 0,106,208, 0,106,208, 0,107,206, 0, + 111,202, 0,115,195, 0,119,187, 0,118,188, 0,114,197, 0, + 110,203, 0,106,208, 0,103,211, 0,102,212, 0,102,213, 0, + 102,212, 0,103,212, 0,105,209, 0,108,206, 0,112,200, 0, + 117,191, 0,122,178, 0,124,158, 13,121,125, 63,114,104,197, + 122,130, 53,124,145, 29,124,152, 20,124,157, 15,124,164, 9, + 123,171, 3,120,184, 0,116,193, 0,111,201, 0,106,207, 0, + 103,212, 0,101,214, 0,101,214, 0,102,212, 0,104,210, 0, + 101,214, 0, 97,218, 0, 93,222, 0, 89,225, 0, 87,227, 0, + 87,227, 0, 87,227, 0, 87,227, 0, 85,228, 0, 85,228, 0, + 87,227, 0, 92,223, 0, 97,218, 0,103,211, 0,109,203, 0, + 111,201, 0,111,202, 0,110,203, 0,109,203, 0,109,203, 0, + 110,202, 0,112,200, 0,114,196, 0,117,191, 0,120,183, 0, + 123,174, 1,122,178, 0,120,183, 0,119,186, 0,118,189, 0, + 116,192, 0,115,195, 0,113,198, 0,111,202, 0,109,204, 0, + 107,206, 0,107,207, 0,106,207, 0,106,207, 0,106,207, 0, + 106,207, 0,107,207, 0,107,206, 0,109,204, 0,110,202, 0, + 113,198, 0,115,194, 0,118,188, 0,121,182, 0,122,178, 0, + 122,175, 0,123,173, 1,123,169, 4,124,162, 10,124,150, 22, + 122,130, 53,111, 96,248,117,110,109,120,122, 70,121,125, 63, + 119,119, 77,115,107,129,122,135, 44,124,164, 9,122,177, 0, + 120,184, 0,119,186, 0,120,184, 0,122,178, 0,123,168, 5, + 124,154, 18,124,150, 22,124,145, 29,124,155, 16,123,168, 5, + 122,176, 0,121,181, 0,120,182, 0,121,179, 0,123,170, 3, + 123,168, 5,124,165, 8,122,178, 0,117,190, 0,114,196, 0, + 113,198, 0,113,198, 0,115,194, 0,118,188, 0,118,189, 0, + 117,192, 0,117,192, 0,118,189, 0,120,182, 0,123,173, 1, + 123,172, 2,123,168, 5,124,167, 6,123,168, 5,123,171, 3, + 123,174, 1,122,177, 0,122,178, 0,122,177, 0,122,175, 0, + 122,176, 0,122,177, 0,122,178, 0,120,182, 0,120,184, 0, + 120,184, 0,120,183, 0,121,181, 0,121,180, 0,121,181, 0, + 120,182, 0,120,184, 0,119,186, 0,119,187, 0,119,185, 0, + 119,185, 0,118,189, 0,116,192, 0,115,194, 0,114,196, 0, + 114,196, 0,115,194, 0,116,193, 0,117,191, 0,118,188, 0, + 120,183, 0,122,176, 0,124,167, 6,124,157, 15,124,158, 13, + 124,160, 12,124,160, 12,124,161, 11,124,162, 10,123,168, 5, + 122,176, 0,121,180, 0,121,182, 0,121,182, 0,121,180, 0, + 122,178, 0,119,186, 0,117,192, 0,114,196, 0,113,198, 0, + 112,199, 0,112,200, 0,111,202, 0,110,202, 0,109,204, 0, + 108,205, 0,107,206, 0,104,210, 0,101,214, 0, 98,216, 0, + 97,218, 0, 95,219, 0, 95,220, 0, 95,220, 0, 96,219, 0, + 97,217, 0,100,215, 0,101,213, 0,105,209, 0,109,204, 0, + 114,197, 0,117,190, 0,119,187, 0,120,183, 0,117,190, 0, + 115,195, 0,114,197, 0,113,198, 0,113,198, 0,113,198, 0, + 114,197, 0,112,199, 0,111,201, 0,111,201, 0,112,200, 0, + 112,199, 0,113,198, 0,114,196, 0,115,195, 0,114,197, 0, + 111,201, 0,109,204, 0,107,207, 0,106,208, 0,105,209, 0, + 106,208, 0,106,208, 0,104,210, 0,102,212, 0,100,214, 0, + 98,217, 0, 95,220, 0, 92,222, 0, 91,223, 0, 91,223, 0, + 92,222, 0, 95,219, 0, 96,219, 0, 96,219, 0, 97,217, 0, + 100,214, 0,104,210, 0,109,203, 0,113,198, 0,114,197, 0, + 114,196, 0,115,194, 0,114,197, 0,112,200, 0,111,201, 0, + 112,200, 0,114,197, 0,117,192, 0,119,186, 0,119,186, 0, + 114,196, 0,110,203, 0,106,208, 0,103,211, 0,102,212, 0, + 102,212, 0,103,211, 0,105,209, 0,107,206, 0,111,202, 0, + 115,195, 0,119,186, 0,123,174, 1,124,157, 15,122,132, 48, + 117,110,109,122,130, 53,123,141, 34,124,145, 29,124,150, 22, + 124,160, 12,122,175, 0,119,186, 0,116,193, 0,112,200, 0, + 108,205, 0,105,209, 0,103,211, 0,103,212, 0,103,211, 0, + 104,210, 0,101,214, 0, 97,218, 0, 93,221, 0, 91,224, 0, + 89,225, 0, 90,225, 0, 91,223, 0, 89,225, 0, 88,226, 0, + 89,225, 0, 92,223, 0, 96,219, 0,101,213, 0,107,207, 0, + 112,200, 0,111,201, 0,110,202, 0,109,203, 0,109,203, 0, + 110,202, 0,111,201, 0,113,198, 0,115,194, 0,118,189, 0, + 120,184, 0,122,176, 0,121,179, 0,119,185, 0,118,189, 0, + 116,193, 0,114,196, 0,113,198, 0,112,200, 0,110,202, 0, + 109,203, 0,108,205, 0,107,206, 0,107,207, 0,106,208, 0, + 105,209, 0,105,209, 0,106,208, 0,107,207, 0,109,204, 0, + 112,200, 0,114,196, 0,117,191, 0,119,186, 0,121,182, 0, + 121,179, 0,122,178, 0,122,176, 0,123,172, 2,124,165, 8, + 124,152, 20,122,130, 53,109, 92,251, 94, 70,242,107, 89,252, + 113,100,242,113,100,242,118,114, 96,124,149, 24,123,170, 3, + 121,182, 0,119,187, 0,118,188, 0,119,186, 0,120,182, 0, + 123,174, 1,124,164, 9,124,154, 18,124,149, 24,124,160, 12, + 123,172, 2,121,181, 0,119,185, 0,119,186, 0,120,183, 0, + 122,175, 0,122,175, 0,123,170, 3,120,182, 0,116,193, 0, + 113,199, 0,111,201, 0,112,200, 0,114,197, 0,117,191, 0, + 118,189, 0,116,192, 0,116,192, 0,117,191, 0,119,186, 0, + 121,179, 0,122,177, 0,122,175, 0,122,176, 0,122,178, 0, + 121,179, 0,121,180, 0,121,181, 0,122,178, 0,123,174, 1, + 123,170, 3,123,168, 5,123,173, 1,121,180, 0,119,185, 0, + 118,188, 0,118,189, 0,118,188, 0,119,186, 0,119,185, 0, + 119,185, 0,119,187, 0,118,189, 0,117,191, 0,117,192, 0, + 117,191, 0,119,187, 0,119,186, 0,118,189, 0,116,192, 0, + 115,194, 0,114,196, 0,114,196, 0,114,196, 0,115,195, 0, + 115,194, 0,117,191, 0,119,187, 0,121,182, 0,123,173, 1, + 124,164, 9,124,164, 9,124,167, 6,123,169, 4,123,171, 3, + 123,170, 3,122,176, 0,121,180, 0,121,182, 0,120,183, 0, + 120,182, 0,121,181, 0,119,186, 0,117,192, 0,114,196, 0, + 114,197, 0,113,198, 0,114,197, 0,114,197, 0,114,197, 0, + 113,198, 0,112,200, 0,108,205, 0,104,210, 0,101,213, 0, + 100,215, 0,100,215, 0,100,215, 0,101,214, 0,102,212, 0, + 104,210, 0,105,209, 0,106,207, 0,108,206, 0,110,202, 0, + 114,197, 0,118,188, 0,122,178, 0,123,174, 1,121,182, 0, + 118,189, 0,116,192, 0,116,193, 0,117,192, 0,117,191, 0, + 117,192, 0,115,195, 0,114,197, 0,114,197, 0,115,195, 0, + 115,194, 0,115,194, 0,115,194, 0,116,193, 0,117,192, 0, + 116,193, 0,113,198, 0,110,202, 0,108,205, 0,107,207, 0, + 107,207, 0,107,206, 0,105,209, 0,103,211, 0,101,213, 0, + 100,215, 0, 97,217, 0, 94,220, 0, 92,223, 0, 90,224, 0, + 90,224, 0, 92,223, 0, 95,220, 0, 97,218, 0, 97,218, 0, + 98,217, 0,101,214, 0,105,209, 0,109,203, 0,114,197, 0, + 118,189, 0,119,187, 0,119,186, 0,119,185, 0,118,189, 0, + 117,192, 0,116,192, 0,117,191, 0,119,187, 0,119,185, 0, + 119,186, 0,115,195, 0,110,202, 0,107,207, 0,105,209, 0, + 104,210, 0,105,209, 0,106,207, 0,109,204, 0,112,200, 0, + 115,194, 0,119,186, 0,122,177, 0,124,165, 8,124,149, 24, + 121,127, 58,118,117, 85,120,122, 70,122,130, 53,122,135, 44, + 124,145, 29,124,161, 11,122,178, 0,119,187, 0,116,192, 0, + 114,197, 0,111,201, 0,109,204, 0,107,206, 0,106,207, 0, + 107,207, 0,106,208, 0,102,212, 0, 98,217, 0, 95,220, 0, + 93,222, 0, 92,222, 0, 93,221, 0, 95,219, 0, 93,222, 0, + 92,222, 0, 94,221, 0, 97,218, 0,102,213, 0,107,207, 0, + 112,200, 0,113,198, 0,112,200, 0,110,202, 0,110,203, 0, + 110,202, 0,111,201, 0,113,199, 0,115,195, 0,115,194, 0, + 117,191, 0,119,185, 0,121,179, 0,122,177, 0,120,184, 0, + 117,190, 0,115,194, 0,114,197, 0,112,199, 0,112,200, 0, + 112,200, 0,111,201, 0,111,202, 0,110,202, 0,109,204, 0, + 107,206, 0,106,208, 0,106,208, 0,106,207, 0,108,205, 0, + 111,202, 0,114,197, 0,116,192, 0,118,189, 0,120,184, 0, + 121,181, 0,121,180, 0,121,180, 0,122,178, 0,123,173, 1, + 124,165, 8,124,150, 22,121,125, 63,105, 84,252, 30, 26,168, + 30, 55,222, 94, 70,242,102, 80,250,120,122, 70,124,154, 18, + 123,172, 2,120,182, 0,118,188, 0,118,189, 0,118,188, 0, + 120,184, 0,122,178, 0,123,171, 3,124,164, 9,124,160, 12, + 124,164, 9,122,176, 0,120,183, 0,119,186, 0,119,187, 0, + 120,184, 0,122,178, 0,122,176, 0,123,172, 2,119,187, 0, + 114,196, 0,111,201, 0,110,202, 0,111,201, 0,114,197, 0, + 117,192, 0,118,189, 0,116,192, 0,116,192, 0,117,191, 0, + 119,187, 0,121,182, 0,122,178, 0,122,178, 0,121,179, 0, + 121,182, 0,120,183, 0,120,183, 0,121,182, 0,122,178, 0, + 123,170, 3,124,162, 10,124,164, 9,123,172, 2,121,180, 0, + 119,186, 0,117,190, 0,117,192, 0,117,190, 0,118,188, 0, + 119,186, 0,118,189, 0,117,192, 0,117,192, 0,116,193, 0, + 115,194, 0,115,194, 0,117,191, 0,118,188, 0,118,188, 0, + 118,188, 0,117,191, 0,116,192, 0,115,194, 0,115,195, 0, + 114,196, 0,114,196, 0,114,196, 0,116,193, 0,118,189, 0, + 120,182, 0,123,173, 1,124,166, 7,123,169, 4,123,173, 1, + 122,175, 0,122,175, 0,123,172, 2,122,177, 0,122,178, 0, + 121,181, 0,121,182, 0,121,180, 0,119,187, 0,116,192, 0, + 115,195, 0,114,196, 0,115,194, 0,116,192, 0,116,192, 0, + 116,192, 0,117,191, 0,114,196, 0,110,202, 0,107,207, 0, + 104,210, 0,103,211, 0,104,210, 0,106,207, 0,108,205, 0, + 109,204, 0,110,203, 0,112,200, 0,114,197, 0,114,196, 0, + 116,192, 0,119,186, 0,122,175, 0,124,155, 16,124,167, 6, + 122,178, 0,120,184, 0,119,186, 0,119,185, 0,120,182, 0, + 118,188, 0,117,192, 0,116,193, 0,116,193, 0,117,191, 0, + 118,189, 0,117,192, 0,116,193, 0,116,193, 0,116,192, 0, + 117,191, 0,117,191, 0,115,195, 0,113,199, 0,111,202, 0, + 109,203, 0,109,203, 0,107,206, 0,105,209, 0,103,211, 0, + 102,213, 0,100,215, 0, 98,217, 0, 95,220, 0, 92,222, 0, + 91,224, 0, 91,224, 0, 92,222, 0, 95,220, 0, 99,216, 0, + 99,216, 0,100,215, 0,102,212, 0,106,208, 0,110,202, 0, + 114,196, 0,117,190, 0,119,185, 0,121,180, 0,123,172, 2, + 122,175, 0,121,180, 0,120,182, 0,120,182, 0,120,183, 0, + 120,183, 0,119,185, 0,115,194, 0,111,201, 0,108,205, 0, + 107,206, 0,108,206, 0,109,203, 0,111,201, 0,114,196, 0, + 117,190, 0,121,182, 0,123,171, 3,124,158, 13,124,145, 29, + 122,130, 53,121,125, 63,118,117, 85,114,104,197,117,110,109, + 121,125, 63,123,139, 37,124,162, 10,122,178, 0,119,186, 0, + 117,190, 0,116,193, 0,114,196, 0,113,198, 0,112,200, 0, + 111,201, 0,111,201, 0,110,203, 0,106,208, 0,102,213, 0, + 98,217, 0, 96,219, 0, 96,219, 0, 97,218, 0,100,215, 0, + 97,218, 0, 97,218, 0, 99,215, 0,103,211, 0,108,206, 0, + 112,200, 0,115,194, 0,114,196, 0,113,199, 0,111,201, 0, + 111,202, 0,111,201, 0,113,199, 0,114,196, 0,114,196, 0, + 115,194, 0,117,191, 0,119,186, 0,121,179, 0,123,173, 1, + 121,180, 0,119,187, 0,117,192, 0,114,196, 0,114,197, 0, + 114,197, 0,114,197, 0,114,196, 0,113,199, 0,112,199, 0, + 112,200, 0,110,202, 0,108,205, 0,108,206, 0,109,204, 0, + 110,202, 0,113,198, 0,116,193, 0,117,192, 0,118,189, 0, + 120,184, 0,121,179, 0,121,180, 0,121,181, 0,122,178, 0, + 123,174, 1,124,164, 9,124,147, 26,118,117, 85, 94, 70,242, + 30, 5,128, 30, 43,203,102, 80,250,111, 96,248,121,127, 58, + 124,150, 22,123,170, 3,121,180, 0,119,186, 0,118,188, 0, + 119,187, 0,120,184, 0,121,181, 0,122,175, 0,123,169, 4, + 124,167, 6,124,167, 6,122,176, 0,120,183, 0,119,186, 0, + 119,185, 0,121,181, 0,122,176, 0,122,175, 0,121,180, 0, + 117,191, 0,113,198, 0,111,202, 0,111,202, 0,112,200, 0, + 114,196, 0,117,190, 0,117,190, 0,117,192, 0,117,191, 0, + 118,189, 0,119,186, 0,121,181, 0,123,174, 1,122,176, 0, + 121,179, 0,120,182, 0,120,184, 0,120,184, 0,121,181, 0, + 122,175, 0,124,165, 8,124,165, 8,123,171, 3,122,175, 0, + 121,179, 0,119,186, 0,117,191, 0,116,192, 0,117,191, 0, + 118,188, 0,116,192, 0,115,195, 0,114,196, 0,114,196, 0, + 116,193, 0,115,195, 0,115,194, 0,116,193, 0,117,190, 0, + 118,189, 0,117,190, 0,118,189, 0,119,187, 0,118,189, 0, + 117,191, 0,116,193, 0,115,195, 0,114,196, 0,115,195, 0, + 117,192, 0,119,186, 0,122,178, 0,124,166, 7,123,170, 3, + 122,175, 0,122,177, 0,122,176, 0,123,171, 3,123,168, 5, + 123,171, 3,122,175, 0,122,177, 0,121,181, 0,118,188, 0, + 116,192, 0,115,194, 0,115,194, 0,117,191, 0,118,188, 0, + 117,190, 0,117,191, 0,116,192, 0,115,195, 0,114,197, 0, + 110,202, 0,108,205, 0,108,206, 0,110,202, 0,110,202, 0, + 109,204, 0,109,203, 0,111,201, 0,114,196, 0,118,188, 0, + 121,182, 0,122,178, 0,123,169, 4,124,152, 20,124,150, 22, + 124,160, 12,123,169, 4,122,175, 0,122,176, 0,123,172, 2, + 121,182, 0,118,188, 0,117,191, 0,117,191, 0,118,189, 0, + 119,185, 0,120,183, 0,119,187, 0,118,189, 0,117,190, 0, + 118,189, 0,118,189, 0,118,188, 0,118,189, 0,116,193, 0, + 114,196, 0,113,198, 0,111,201, 0,109,204, 0,107,207, 0, + 105,209, 0,103,211, 0,102,213, 0,100,215, 0, 97,218, 0, + 94,220, 0, 92,222, 0, 92,222, 0, 94,221, 0, 97,218, 0, + 101,214, 0,101,214, 0,102,212, 0,105,209, 0,108,205, 0, + 112,200, 0,115,194, 0,118,188, 0,120,184, 0,121,181, 0, + 123,174, 1,123,171, 3,123,174, 1,122,178, 0,121,179, 0, + 121,180, 0,121,179, 0,119,185, 0,116,193, 0,113,198, 0, + 111,201, 0,111,201, 0,113,199, 0,115,195, 0,117,191, 0, + 120,184, 0,121,180, 0,122,178, 0,123,174, 1,124,165, 8, + 124,145, 29,118,117, 85,118,117, 85,117,110,109,102, 80,250, + 107, 89,252,118,117, 85,122,135, 44,124,160, 12,122,176, 0, + 120,183, 0,119,186, 0,117,191, 0,115,194, 0,114,196, 0, + 114,196, 0,116,192, 0,117,192, 0,114,196, 0,110,202, 0, + 106,208, 0,102,212, 0,100,215, 0,100,215, 0,101,214, 0, + 103,211, 0,102,212, 0,103,212, 0,105,209, 0,109,204, 0, + 112,199, 0,114,196, 0,113,198, 0,112,199, 0,114,197, 0, + 112,200, 0,112,200, 0,112,199, 0,114,197, 0,116,193, 0, + 115,194, 0,116,193, 0,118,189, 0,120,183, 0,122,177, 0, + 123,171, 3,123,171, 3,121,181, 0,119,187, 0,117,191, 0, + 116,193, 0,116,192, 0,114,197, 0,111,202, 0,109,204, 0, + 109,204, 0,110,202, 0,113,199, 0,112,200, 0,111,201, 0, + 112,200, 0,113,198, 0,116,193, 0,117,191, 0,117,190, 0, + 119,187, 0,121,182, 0,122,178, 0,121,180, 0,121,180, 0, + 122,178, 0,123,172, 2,124,160, 12,123,139, 37,113,100,242, + 94, 70,242, 69, 60,230, 99, 75,247,117,110,109,121,125, 63, + 122,132, 48,124,150, 22,124,162, 10,122,175, 0,121,181, 0, + 120,184, 0,120,184, 0,120,182, 0,121,179, 0,122,175, 0, + 123,171, 3,123,168, 5,123,169, 4,123,174, 1,121,181, 0, + 120,183, 0,121,182, 0,122,176, 0,123,172, 2,123,174, 1, + 119,187, 0,115,195, 0,112,200, 0,111,202, 0,112,200, 0, + 114,197, 0,117,192, 0,118,188, 0,117,190, 0,117,191, 0, + 118,189, 0,119,186, 0,121,182, 0,122,177, 0,124,165, 8, + 123,169, 4,123,174, 1,121,179, 0,120,182, 0,120,182, 0, + 121,180, 0,123,173, 1,124,162, 10,123,170, 3,122,178, 0, + 120,182, 0,120,184, 0,119,186, 0,117,191, 0,116,192, 0, + 117,190, 0,115,194, 0,114,197, 0,112,199, 0,112,200, 0, + 113,199, 0,114,197, 0,115,194, 0,117,192, 0,117,191, 0, + 118,189, 0,119,187, 0,118,189, 0,117,191, 0,117,191, 0, + 118,189, 0,119,186, 0,118,189, 0,116,192, 0,115,194, 0, + 116,193, 0,117,191, 0,119,185, 0,122,176, 0,124,165, 8, + 123,170, 3,123,174, 1,122,175, 0,123,174, 1,123,169, 4, + 124,160, 12,124,157, 15,124,162, 10,123,173, 1,120,182, 0, + 118,189, 0,116,192, 0,116,193, 0,117,192, 0,118,188, 0, + 120,182, 0,119,186, 0,119,186, 0,116,192, 0,114,196, 0, + 114,197, 0,113,198, 0,112,199, 0,113,198, 0,112,200, 0, + 111,202, 0,110,202, 0,112,200, 0,114,196, 0,118,189, 0, + 122,177, 0,124,157, 15,124,150, 22,124,147, 26,124,150, 22, + 124,150, 22,124,149, 24,124,157, 15,124,161, 11,124,160, 12, + 123,170, 3,121,179, 0,119,185, 0,119,187, 0,119,187, 0, + 120,184, 0,122,178, 0,123,171, 3,122,178, 0,121,181, 0, + 120,182, 0,120,183, 0,121,182, 0,121,181, 0,121,181, 0, + 120,183, 0,118,188, 0,116,192, 0,114,197, 0,112,200, 0, + 110,203, 0,108,205, 0,107,207, 0,106,208, 0,104,210, 0, + 101,213, 0, 99,216, 0, 97,218, 0, 97,218, 0, 98,217, 0, + 100,214, 0,104,210, 0,104,210, 0,105,209, 0,108,206, 0, + 111,202, 0,114,196, 0,117,190, 0,119,185, 0,121,180, 0, + 122,177, 0,123,172, 2,123,173, 1,123,174, 1,122,176, 0, + 122,176, 0,122,176, 0,123,173, 1,120,184, 0,117,191, 0, + 115,194, 0,114,196, 0,116,193, 0,118,189, 0,120,184, 0, + 122,177, 0,122,178, 0,121,179, 0,122,178, 0,122,178, 0, + 123,173, 1,124,164, 9,124,145, 29,118,114, 96,115,107,129, + 99, 75,247, 87, 65,237,117,110,109,123,137, 41,124,154, 18, + 123,169, 4,122,178, 0,119,186, 0,116,193, 0,114,197, 0, + 113,199, 0,114,197, 0,116,193, 0,118,188, 0,119,187, 0, + 115,194, 0,111,202, 0,107,207, 0,104,210, 0,103,211, 0, + 104,210, 0,106,208, 0,109,204, 0,109,204, 0,111,201, 0, + 113,198, 0,114,196, 0,114,196, 0,112,199, 0,112,200, 0, + 114,197, 0,113,199, 0,112,199, 0,113,198, 0,114,196, 0, + 117,192, 0,118,189, 0,118,188, 0,120,183, 0,121,182, 0, + 122,177, 0,123,170, 3,124,160, 12,123,168, 5,122,178, 0, + 120,184, 0,119,186, 0,115,194, 0,112,200, 0,109,204, 0, + 107,207, 0,107,207, 0,109,204, 0,112,200, 0,115,194, 0, + 114,196, 0,115,195, 0,116,192, 0,118,189, 0,119,186, 0, + 119,185, 0,121,182, 0,122,175, 0,122,178, 0,121,180, 0, + 121,180, 0,122,177, 0,123,169, 4,124,154, 18,122,130, 53, + 117,110,109,118,117, 85,118,114, 96,115,107,129,122,135, 44, + 124,147, 26,124,152, 20,124,154, 18,124,154, 18,124,165, 8, + 123,173, 1,122,177, 0,122,178, 0,122,178, 0,123,174, 1, + 123,170, 3,124,166, 7,124,165, 8,124,166, 7,123,169, 4, + 122,177, 0,121,179, 0,122,178, 0,123,171, 3,123,169, 4, + 120,182, 0,117,192, 0,113,198, 0,111,201, 0,111,201, 0, + 113,198, 0,116,193, 0,119,187, 0,118,189, 0,118,189, 0, + 118,189, 0,119,186, 0,121,181, 0,123,174, 1,123,168, 5, + 124,167, 6,123,169, 4,123,168, 5,122,176, 0,121,180, 0, + 121,181, 0,121,179, 0,123,174, 1,124,162, 10,123,171, 3, + 121,180, 0,119,185, 0,118,188, 0,117,190, 0,117,192, 0, + 116,193, 0,114,196, 0,113,198, 0,111,201, 0,110,202, 0, + 110,202, 0,111,201, 0,112,199, 0,114,197, 0,115,195, 0, + 116,192, 0,118,188, 0,120,184, 0,120,184, 0,119,187, 0, + 118,189, 0,118,189, 0,119,187, 0,120,184, 0,118,188, 0, + 117,190, 0,118,189, 0,119,186, 0,121,181, 0,123,171, 3, + 124,161, 11,124,167, 6,123,170, 3,123,171, 3,123,169, 4, + 124,164, 9,124,154, 18,124,145, 29,124,161, 11,123,172, 2, + 121,182, 0,118,188, 0,117,191, 0,117,191, 0,118,188, 0, + 120,183, 0,122,176, 0,121,179, 0,120,184, 0,117,191, 0, + 115,194, 0,114,197, 0,114,197, 0,114,197, 0,114,197, 0, + 114,197, 0,113,198, 0,114,197, 0,116,193, 0,118,188, 0, + 122,177, 0,124,158, 13,122,130, 53,122,132, 48,123,141, 34, + 124,143, 31,124,143, 31,123,141, 34,123,141, 34,124,143, 31, + 124,150, 22,124,161, 11,123,171, 3,122,177, 0,121,179, 0, + 122,178, 0,123,173, 1,124,166, 7,124,158, 13,124,161, 11, + 124,167, 6,123,169, 4,123,170, 3,123,169, 4,122,176, 0, + 121,182, 0,120,184, 0,119,186, 0,118,188, 0,117,191, 0, + 115,194, 0,113,198, 0,110,202, 0,108,205, 0,106,208, 0, + 105,209, 0,106,208, 0,105,209, 0,102,212, 0,102,213, 0, + 102,212, 0,105,209, 0,108,205, 0,108,205, 0,109,203, 0, + 111,201, 0,114,196, 0,117,191, 0,117,190, 0,118,188, 0, + 119,185, 0,121,181, 0,122,178, 0,122,178, 0,122,177, 0, + 122,176, 0,122,175, 0,123,172, 2,123,169, 4,121,179, 0, + 119,185, 0,118,188, 0,119,186, 0,120,183, 0,122,176, 0, + 122,176, 0,121,181, 0,120,184, 0,119,186, 0,118,188, 0, + 119,186, 0,120,182, 0,123,173, 1,124,158, 13,122,132, 48, + 117,110,109,102, 80,250, 69, 60,230,115,107,129,123,139, 37, + 124,158, 13,123,171, 3,121,182, 0,118,189, 0,115,195, 0, + 113,198, 0,113,199, 0,114,197, 0,116,192, 0,119,186, 0, + 119,186, 0,119,187, 0,115,194, 0,111,201, 0,108,205, 0, + 107,207, 0,107,207, 0,108,205, 0,110,202, 0,113,199, 0, + 114,196, 0,115,194, 0,116,193, 0,114,197, 0,112,199, 0, + 113,199, 0,114,196, 0,113,198, 0,113,198, 0,114,197, 0, + 115,194, 0,117,191, 0,118,188, 0,119,185, 0,120,184, 0, + 120,183, 0,121,179, 0,123,174, 1,124,166, 7,124,161, 11, + 123,170, 3,121,179, 0,119,187, 0,115,195, 0,111,201, 0, + 108,205, 0,107,207, 0,108,206, 0,110,202, 0,114,197, 0, + 117,192, 0,117,191, 0,117,191, 0,118,188, 0,119,185, 0, + 121,181, 0,122,177, 0,122,175, 0,122,176, 0,122,178, 0, + 121,180, 0,121,179, 0,122,175, 0,124,165, 8,124,149, 24, + 123,141, 34,124,150, 22,124,150, 22,124,149, 24,123,139, 37, + 124,149, 24,124,161, 11,124,166, 7,123,168, 5,123,168, 5, + 123,168, 5,123,173, 1,122,177, 0,122,178, 0,122,178, 0, + 122,178, 0,122,178, 0,122,176, 0,123,171, 3,124,165, 8, + 124,160, 12,123,170, 3,122,175, 0,123,174, 1,123,168, 5, + 122,176, 0,119,186, 0,115,194, 0,112,199, 0,111,201, 0, + 112,199, 0,115,195, 0,118,188, 0,119,187, 0,118,188, 0, + 118,188, 0,119,186, 0,121,182, 0,122,175, 0,124,166, 7, + 124,161, 11,124,162, 10,124,166, 7,124,165, 8,123,173, 1, + 122,178, 0,121,181, 0,121,179, 0,123,174, 1,124,164, 9, + 123,170, 3,121,181, 0,119,187, 0,117,191, 0,115,194, 0, + 114,197, 0,113,198, 0,112,200, 0,111,202, 0,110,203, 0, + 109,203, 0,110,203, 0,111,201, 0,112,199, 0,114,197, 0, + 115,195, 0,116,193, 0,118,189, 0,120,183, 0,122,175, 0, + 122,178, 0,120,183, 0,120,184, 0,120,184, 0,121,180, 0, + 120,182, 0,120,184, 0,120,183, 0,121,179, 0,123,173, 1, + 124,164, 9,124,152, 20,124,157, 15,124,161, 11,124,162, 10, + 124,161, 11,124,155, 16,124,147, 26,124,149, 24,124,152, 20, + 124,166, 7,122,177, 0,120,183, 0,119,185, 0,119,185, 0, + 121,181, 0,123,174, 1,123,170, 3,123,174, 1,121,182, 0, + 118,189, 0,116,193, 0,115,194, 0,115,195, 0,116,193, 0, + 117,192, 0,117,191, 0,117,190, 0,118,188, 0,120,183, 0, + 123,174, 1,124,160, 12,124,149, 24,122,132, 48,120,122, 70, + 122,130, 53,122,132, 48,122,130, 53,123,137, 41,123,141, 34, + 124,147, 26,124,154, 18,124,162, 10,124,167, 6,123,169, 4, + 124,166, 7,124,157, 15,124,150, 22,123,139, 37,121,127, 58, + 123,137, 41,124,145, 29,124,149, 24,124,154, 18,124,166, 7, + 123,174, 1,121,179, 0,120,182, 0,120,184, 0,119,187, 0, + 117,190, 0,115,194, 0,113,198, 0,110,202, 0,108,206, 0, + 106,207, 0,106,207, 0,108,206, 0,110,202, 0,108,205, 0, + 107,207, 0,107,206, 0,109,203, 0,112,199, 0,114,197, 0, + 115,195, 0,117,192, 0,118,189, 0,118,189, 0,117,191, 0, + 117,191, 0,118,188, 0,119,185, 0,120,183, 0,121,182, 0, + 121,180, 0,122,178, 0,122,175, 0,123,171, 3,124,167, 6, + 123,169, 4,123,174, 1,123,174, 1,123,174, 1,123,174, 1, + 121,181, 0,118,188, 0,117,191, 0,116,193, 0,115,194, 0, + 116,193, 0,117,191, 0,119,185, 0,122,177, 0,124,164, 9, + 123,141, 34,118,117, 85,102, 80,250,102, 80,250,113,100,242, + 123,139, 37,124,161, 11,122,175, 0,120,184, 0,117,191, 0, + 114,196, 0,113,198, 0,114,197, 0,115,194, 0,118,189, 0, + 121,181, 0,121,181, 0,120,182, 0,119,187, 0,115,194, 0, + 112,199, 0,110,202, 0,110,203, 0,110,202, 0,112,200, 0, + 114,197, 0,115,194, 0,117,191, 0,115,194, 0,114,197, 0, + 113,198, 0,113,198, 0,115,194, 0,115,195, 0,115,194, 0, + 116,193, 0,117,191, 0,118,188, 0,119,186, 0,120,184, 0, + 120,184, 0,120,184, 0,121,181, 0,122,176, 0,123,169, 4, + 124,161, 11,124,166, 7,122,177, 0,119,186, 0,115,194, 0, + 112,200, 0,109,204, 0,109,204, 0,110,202, 0,113,198, 0, + 116,192, 0,119,186, 0,119,187, 0,119,186, 0,120,184, 0, + 121,181, 0,122,178, 0,122,175, 0,123,174, 1,122,177, 0, + 121,179, 0,121,180, 0,122,178, 0,123,170, 3,124,161, 11, + 124,154, 18,124,166, 7,123,170, 3,123,169, 4,124,166, 7, + 124,160, 12,124,154, 18,124,166, 7,123,172, 2,122,176, 0, + 122,177, 0,123,174, 1,121,179, 0,121,182, 0,120,183, 0, + 120,184, 0,120,184, 0,120,184, 0,120,183, 0,121,180, 0, + 123,174, 1,123,168, 5,123,168, 5,123,171, 3,123,171, 3, + 123,168, 5,121,179, 0,118,189, 0,114,196, 0,112,200, 0, + 111,201, 0,113,198, 0,116,192, 0,120,184, 0,119,185, 0, + 119,186, 0,119,185, 0,120,182, 0,122,177, 0,123,169, 4, + 124,158, 13,124,152, 20,124,150, 22,124,157, 15,124,162, 10, + 123,171, 3,122,178, 0,121,180, 0,122,178, 0,123,174, 1, + 124,164, 9,123,168, 5,121,180, 0,118,188, 0,116,193, 0, + 114,197, 0,112,199, 0,111,201, 0,110,202, 0,110,203, 0, + 109,203, 0,110,202, 0,111,201, 0,113,199, 0,114,196, 0, + 115,194, 0,116,193, 0,116,192, 0,118,189, 0,120,184, 0, + 122,177, 0,123,168, 5,123,170, 3,122,175, 0,122,176, 0, + 123,173, 1,122,175, 0,123,174, 1,123,172, 2,123,168, 5, + 124,161, 11,124,152, 20,123,141, 34,123,137, 41,123,141, 34, + 124,145, 29,124,147, 26,124,145, 29,123,141, 34,124,143, 31, + 124,149, 24,124,152, 20,124,166, 7,123,174, 1,122,177, 0, + 122,175, 0,123,170, 3,124,160, 12,124,165, 8,123,168, 5, + 121,179, 0,119,186, 0,117,190, 0,117,191, 0,117,191, 0, + 118,188, 0,120,184, 0,121,181, 0,122,178, 0,123,173, 1, + 124,165, 8,124,160, 12,124,157, 15,124,149, 24,122,132, 48, + 118,117, 85,123,139, 37,124,150, 22,124,157, 15,124,158, 13, + 124,162, 10,124,164, 9,124,162, 10,123,168, 5,123,170, 3, + 123,170, 3,124,165, 8,124,154, 18,122,132, 48,111, 96,248, + 99, 75,247,111, 96,248,115,107,129,120,122, 70,124,143, 31, + 124,158, 13,123,168, 5,122,175, 0,122,178, 0,121,179, 0, + 120,183, 0,118,188, 0,116,192, 0,114,197, 0,111,201, 0, + 109,203, 0,108,205, 0,109,204, 0,111,201, 0,114,196, 0, + 113,198, 0,112,200, 0,112,199, 0,114,197, 0,117,192, 0, + 119,187, 0,120,184, 0,120,183, 0,120,184, 0,119,186, 0, + 118,189, 0,117,190, 0,118,189, 0,119,186, 0,119,185, 0, + 120,183, 0,121,181, 0,122,178, 0,123,173, 1,123,169, 4, + 124,165, 8,124,161, 11,124,157, 15,124,160, 12,123,172, 2, + 120,182, 0,117,190, 0,114,196, 0,113,198, 0,113,199, 0, + 113,198, 0,114,196, 0,117,191, 0,119,185, 0,122,176, 0, + 124,164, 9,124,145, 29,120,122, 70,107, 89,252,111, 96,248, + 114,104,197,122,130, 53,124,160, 12,122,175, 0,119,185, 0, + 117,192, 0,115,195, 0,114,196, 0,115,194, 0,118,189, 0, + 120,182, 0,123,172, 2,123,172, 2,122,176, 0,122,178, 0, + 119,186, 0,117,191, 0,115,195, 0,114,197, 0,113,198, 0, + 114,196, 0,115,194, 0,117,191, 0,117,191, 0,115,194, 0, + 114,196, 0,114,197, 0,114,196, 0,116,193, 0,117,191, 0, + 118,189, 0,119,186, 0,120,184, 0,120,182, 0,121,182, 0, + 121,182, 0,120,182, 0,121,182, 0,121,179, 0,122,175, 0, + 123,168, 5,124,162, 10,124,155, 16,123,170, 3,120,182, 0, + 117,192, 0,113,198, 0,111,201, 0,111,201, 0,113,198, 0, + 117,192, 0,120,184, 0,120,182, 0,120,183, 0,121,182, 0, + 121,179, 0,122,176, 0,123,173, 1,123,171, 3,123,172, 2, + 122,175, 0,122,178, 0,122,178, 0,123,174, 1,124,167, 6, + 124,162, 10,123,170, 3,121,179, 0,121,182, 0,121,179, 0, + 122,175, 0,123,168, 5,124,157, 15,124,164, 9,123,172, 2, + 122,178, 0,121,180, 0,122,178, 0,121,181, 0,120,184, 0, + 119,185, 0,119,186, 0,119,186, 0,119,186, 0,119,186, 0, + 120,184, 0,121,179, 0,122,176, 0,123,174, 1,123,173, 1, + 123,171, 3,123,170, 3,121,181, 0,117,190, 0,114,197, 0, + 112,200, 0,112,200, 0,114,197, 0,118,189, 0,121,179, 0, + 121,182, 0,121,182, 0,121,181, 0,122,178, 0,123,171, 3, + 124,162, 10,124,149, 24,123,137, 41,121,127, 58,124,143, 31, + 124,158, 13,123,169, 4,122,176, 0,122,178, 0,122,178, 0, + 123,173, 1,124,164, 9,124,165, 8,122,178, 0,119,187, 0, + 116,193, 0,114,197, 0,112,199, 0,111,201, 0,110,202, 0, + 110,202, 0,111,201, 0,112,199, 0,114,197, 0,116,193, 0, + 117,191, 0,118,189, 0,118,189, 0,118,189, 0,118,188, 0, + 120,184, 0,122,178, 0,123,168, 5,124,162, 10,124,162, 10, + 124,164, 9,124,165, 8,124,162, 10,124,158, 13,124,154, 18, + 124,147, 26,124,155, 16,124,161, 11,124,162, 10,124,158, 13, + 124,149, 24,123,141, 34,121,125, 63,122,130, 53,122,135, 44, + 122,135, 44,123,139, 37,124,143, 31,124,149, 24,124,160, 12, + 124,164, 9,124,161, 11,124,154, 18,124,150, 22,124,157, 15, + 124,161, 11,122,175, 0,120,183, 0,119,186, 0,119,186, 0, + 120,184, 0,122,178, 0,123,171, 3,124,164, 9,124,155, 16, + 124,143, 31,124,147, 26,124,152, 20,124,152, 20,124,149, 24, + 124,152, 20,124,155, 16,124,164, 9,123,169, 4,123,171, 3, + 123,173, 1,122,175, 0,122,175, 0,123,170, 3,123,170, 3, + 123,170, 3,123,168, 5,124,161, 11,124,147, 26,121,125, 63, + 114,104,197,109, 92,251, 69, 60,230, 30, 31,180,107, 89,252, + 120,122, 70,124,145, 29,124,158, 13,124,166, 7,123,168, 5, + 123,170, 3,122,176, 0,121,182, 0,119,187, 0,116,192, 0, + 114,197, 0,112,199, 0,112,200, 0,114,197, 0,117,192, 0, + 119,185, 0,118,189, 0,117,191, 0,117,191, 0,118,188, 0, + 121,182, 0,122,176, 0,123,172, 2,123,172, 2,123,174, 1, + 122,178, 0,120,183, 0,119,186, 0,119,186, 0,120,184, 0, + 120,183, 0,121,181, 0,122,178, 0,123,174, 1,123,170, 3, + 124,165, 8,124,160, 12,124,157, 15,124,154, 18,123,168, 5, + 121,181, 0,118,189, 0,114,196, 0,112,200, 0,110,202, 0, + 111,201, 0,113,199, 0,115,195, 0,118,189, 0,120,182, 0, + 123,173, 1,124,161, 11,124,149, 24,121,125, 63,115,107,129, + 119,119, 77,121,127, 58,121,127, 58,124,152, 20,123,172, 2, + 120,184, 0,117,190, 0,116,193, 0,116,192, 0,118,189, 0, + 120,182, 0,123,172, 2,124,158, 13,124,157, 15,124,165, 8, + 123,168, 5,123,173, 1,121,180, 0,119,186, 0,118,189, 0, + 117,191, 0,117,191, 0,118,189, 0,119,187, 0,117,190, 0, + 116,192, 0,116,193, 0,115,194, 0,116,193, 0,117,191, 0, + 118,189, 0,119,185, 0,121,180, 0,122,176, 0,121,180, 0, + 120,183, 0,119,185, 0,119,186, 0,120,182, 0,123,174, 1, + 123,168, 5,124,162, 10,124,155, 16,124,149, 24,124,155, 16, + 123,174, 1,119,186, 0,116,193, 0,114,196, 0,115,195, 0, + 117,191, 0,120,184, 0,123,173, 1,122,177, 0,122,177, 0, + 123,174, 1,123,171, 3,123,168, 5,124,165, 8,124,164, 9, + 124,166, 7,123,170, 3,123,174, 1,123,173, 1,123,168, 5, + 124,167, 6,124,165, 8,122,178, 0,119,186, 0,119,186, 0, + 120,183, 0,122,178, 0,123,170, 3,124,160, 12,124,150, 22, + 124,165, 8,123,173, 1,122,178, 0,122,176, 0,121,179, 0, + 120,182, 0,120,184, 0,120,184, 0,119,185, 0,119,185, 0, + 119,186, 0,119,185, 0,121,181, 0,121,180, 0,122,178, 0, + 122,175, 0,123,172, 2,123,170, 3,121,180, 0,118,189, 0, + 114,196, 0,112,199, 0,113,199, 0,115,195, 0,119,187, 0, + 122,175, 0,122,175, 0,122,175, 0,123,174, 1,123,171, 3, + 124,165, 8,124,155, 16,123,141, 34,121,127, 58,118,117, 85, + 123,137, 41,124,154, 18,124,166, 7,123,173, 1,122,176, 0, + 122,175, 0,123,170, 3,124,161, 11,124,160, 12,122,175, 0, + 120,184, 0,117,190, 0,115,194, 0,114,197, 0,113,198, 0, + 113,199, 0,113,198, 0,114,196, 0,116,193, 0,118,189, 0, + 119,186, 0,120,183, 0,121,181, 0,121,182, 0,120,184, 0, + 120,184, 0,120,182, 0,122,178, 0,123,169, 4,124,154, 18, + 124,152, 20,124,152, 20,124,149, 24,123,141, 34,122,135, 44, + 123,139, 37,124,154, 18,124,162, 10,123,170, 3,123,174, 1, + 123,174, 1,123,170, 3,124,161, 11,124,143, 31,121,127, 58, + 121,125, 63,122,132, 48,122,135, 44,122,135, 44,123,139, 37, + 123,137, 41,124,145, 29,123,141, 34,122,130, 53,123,137, 41, + 124,143, 31,124,152, 20,123,168, 5,122,177, 0,121,180, 0, + 121,179, 0,123,174, 1,124,165, 8,124,150, 22,122,130, 53, + 114,104,197,118,114, 96,122,130, 53,124,143, 31,124,162, 10, + 123,170, 3,123,172, 2,123,173, 1,122,178, 0,121,181, 0, + 121,181, 0,120,182, 0,120,183, 0,120,182, 0,122,178, 0, + 123,171, 3,123,169, 4,124,165, 8,124,155, 16,123,139, 37, + 122,132, 48,121,127, 58,119,119, 77,107, 89,252, 30, 49,213, + 30, 55,222,109, 92,251,121,125, 63,123,141, 34,124,149, 24, + 124,150, 22,124,154, 18,124,162, 10,123,170, 3,122,178, 0, + 120,184, 0,118,189, 0,117,191, 0,117,190, 0,119,186, 0, + 122,178, 0,123,174, 1,122,178, 0,121,180, 0,122,178, 0, + 123,173, 1,124,165, 8,124,155, 16,124,149, 24,124,149, 24, + 124,155, 16,124,166, 7,122,175, 0,121,181, 0,120,182, 0, + 121,182, 0,121,179, 0,122,175, 0,123,170, 3,124,166, 7, + 124,161, 11,124,155, 16,124,150, 22,124,147, 26,124,155, 16, + 123,173, 1,119,185, 0,116,193, 0,113,199, 0,111,202, 0, + 110,202, 0,111,201, 0,114,197, 0,117,192, 0,119,187, 0, + 120,184, 0,122,178, 0,123,169, 4,124,155, 16,121,127, 58, + 122,135, 44,124,149, 24,124,157, 15,124,158, 13,124,152, 20, + 124,166, 7,121,180, 0,119,186, 0,118,188, 0,119,187, 0, + 121,182, 0,123,172, 2,124,157, 15,122,135, 44,122,130, 53, + 124,149, 24,124,158, 13,124,161, 11,124,162, 10,123,170, 3, + 122,177, 0,121,181, 0,120,183, 0,120,182, 0,120,183, 0, + 119,186, 0,118,188, 0,118,189, 0,118,189, 0,118,189, 0, + 118,188, 0,119,187, 0,120,184, 0,119,186, 0,119,186, 0, + 120,184, 0,119,187, 0,117,191, 0,116,192, 0,117,190, 0, + 120,184, 0,123,172, 2,124,150, 22,123,137, 41,122,130, 53, + 122,130, 53,124,158, 13,122,177, 0,119,185, 0,118,188, 0, + 118,188, 0,120,183, 0,123,173, 1,124,165, 8,123,169, 4, + 123,168, 5,124,164, 9,124,160, 12,124,154, 18,124,149, 24, + 124,149, 24,124,152, 20,124,160, 12,124,165, 8,124,165, 8, + 124,162, 10,124,164, 9,123,171, 3,120,183, 0,118,188, 0, + 118,188, 0,120,184, 0,122,177, 0,123,168, 5,124,155, 16, + 123,141, 34,124,143, 31,124,161, 11,123,168, 5,124,167, 6, + 123,172, 2,122,177, 0,122,178, 0,121,179, 0,121,179, 0, + 121,180, 0,121,182, 0,121,182, 0,120,182, 0,121,182, 0, + 121,179, 0,122,175, 0,122,175, 0,123,171, 3,122,178, 0, + 118,188, 0,115,194, 0,113,198, 0,113,198, 0,116,193, 0, + 120,184, 0,123,170, 3,124,165, 8,124,165, 8,124,165, 8, + 124,167, 6,124,166, 7,124,160, 12,124,147, 26,121,125, 63, + 113,100,242,121,125, 63,124,145, 29,124,160, 12,123,168, 5, + 123,172, 2,123,171, 3,124,167, 6,124,158, 13,124,154, 18, + 123,169, 4,121,179, 0,119,186, 0,118,189, 0,117,191, 0, + 117,192, 0,116,192, 0,117,191, 0,118,188, 0,120,184, 0, + 122,178, 0,123,174, 1,123,174, 1,123,172, 2,123,172, 2, + 122,177, 0,121,179, 0,121,179, 0,122,176, 0,123,168, 5, + 124,152, 20,122,132, 48,122,130, 53,120,122, 70,118,117, 85, + 123,139, 37,124,161, 11,123,171, 3,122,175, 0,122,176, 0, + 121,182, 0,120,184, 0,121,182, 0,122,175, 0,124,164, 9, + 124,147, 26,122,132, 48,121,127, 58,122,132, 48,121,125, 63, + 122,132, 48,122,130, 53,119,119, 77,119,119, 77,114,104,197, + 118,114, 96,120,122, 70,123,137, 41,124,157, 15,124,167, 6, + 123,171, 3,123,169, 4,124,161, 11,124,143, 31,121,127, 58, + 111, 96,248, 69, 60,230,105, 84,252,122,132, 48,124,161, 11, + 122,175, 0,121,181, 0,120,182, 0,120,184, 0,118,188, 0, + 118,188, 0,119,187, 0,119,187, 0,119,187, 0,119,186, 0, + 121,182, 0,122,175, 0,123,169, 4,124,162, 10,124,161, 11, + 124,164, 9,124,165, 8,124,162, 10,124,154, 18,122,135, 44, + 120,122, 70,119,119, 77,114,104,197,109, 92,251,117,110,109, + 119,119, 77,119,119, 77,123,139, 37,124,147, 26,124,150, 22, + 124,162, 10,123,170, 3,122,176, 0,122,177, 0,123,174, 1, + 124,165, 8,124,152, 20,124,161, 11,124,165, 8,124,164, 9, + 124,157, 15,124,145, 29,121,127, 58,120,122, 70,121,127, 58, + 123,137, 41,124,149, 24,124,161, 11,123,171, 3,122,178, 0, + 121,180, 0,121,181, 0,121,179, 0,122,176, 0,123,169, 4, + 124,157, 15,123,141, 34,122,135, 44,122,130, 53,121,127, 58, + 124,155, 16,122,175, 0,119,186, 0,115,194, 0,113,199, 0, + 111,201, 0,111,201, 0,113,198, 0,116,193, 0,115,195, 0, + 115,194, 0,117,191, 0,120,184, 0,123,173, 1,124,157, 15, + 122,132, 48,124,154, 18,123,168, 5,122,175, 0,122,177, 0, + 123,173, 1,124,166, 7,123,173, 1,121,181, 0,120,182, 0, + 121,179, 0,123,171, 3,124,158, 13,123,139, 37,120,122, 70, + 114,104,197,121,125, 63,124,145, 29,124,154, 18,124,157, 15, + 124,152, 20,124,155, 16,124,165, 8,123,170, 3,123,170, 3, + 123,174, 1,122,178, 0,121,180, 0,121,182, 0,120,182, 0, + 120,183, 0,120,184, 0,120,184, 0,118,188, 0,116,193, 0, + 115,195, 0,115,194, 0,117,190, 0,116,193, 0,114,196, 0, + 115,194, 0,118,188, 0,122,178, 0,124,161, 11,122,130, 53, + 109, 92,251,111, 96,248,121,127, 58,124,160, 12,123,174, 1, + 121,179, 0,122,178, 0,123,173, 1,124,161, 11,124,152, 20, + 124,157, 15,124,154, 18,124,154, 18,124,150, 22,124,145, 29, + 123,137, 41,121,125, 63,121,125, 63,123,139, 37,124,149, 24, + 124,150, 22,124,152, 20,124,158, 13,123,174, 1,120,184, 0, + 118,188, 0,119,187, 0,121,182, 0,122,175, 0,123,172, 2, + 124,162, 10,123,137, 41,115,107,129,122,130, 53,124,145, 29, + 124,145, 29,124,160, 12,124,165, 8,124,167, 6,123,168, 5, + 123,168, 5,123,170, 3,123,173, 1,122,178, 0,121,182, 0, + 121,181, 0,122,178, 0,122,178, 0,122,178, 0,123,174, 1, + 123,174, 1,119,185, 0,116,192, 0,114,196, 0,114,196, 0, + 117,191, 0,120,182, 0,124,166, 7,124,149, 24,124,152, 20, + 124,162, 10,124,166, 7,124,166, 7,124,161, 11,124,147, 26, + 121,125, 63, 94, 70,242,113,100,242,122,130, 53,124,149, 24, + 124,160, 12,124,165, 8,124,166, 7,124,161, 11,124,152, 20, + 124,155, 16,124,161, 11,123,172, 2,122,178, 0,121,182, 0, + 120,182, 0,120,182, 0,120,182, 0,121,181, 0,122,177, 0, + 123,171, 3,123,172, 2,123,173, 1,123,173, 1,123,170, 3, + 124,162, 10,123,168, 5,123,173, 1,122,175, 0,123,172, 2, + 124,165, 8,124,145, 29,117,110,109,105, 84,252, 87, 65,237, + 120,122, 70,124,158, 13,123,174, 1,121,182, 0,120,184, 0, + 120,184, 0,119,186, 0,118,188, 0,118,188, 0,120,183, 0, + 123,174, 1,124,160, 12,124,147, 26,121,127, 58,120,122, 70, + 118,117, 85,122,130, 53,122,132, 48,121,125, 63,115,107,129, + 105, 84,252, 94, 70,242,107, 89,252,115,107,129,123,137, 41, + 124,152, 20,124,157, 15,124,154, 18,123,141, 34,117,110,109, + 102, 80,250, 30, 55,222,102, 80,250,118,114, 96,124,154, 18, + 123,173, 1,120,183, 0,118,188, 0,118,188, 0,117,192, 0, + 115,194, 0,115,194, 0,117,192, 0,118,189, 0,118,189, 0, + 119,187, 0,120,182, 0,122,176, 0,123,173, 1,122,176, 0, + 122,178, 0,121,181, 0,121,181, 0,122,178, 0,123,171, 3, + 124,160, 12,124,160, 12,124,157, 15,124,147, 26,121,125, 63, + 105, 84,252, 94, 70,242,102, 80,250,118,114, 96,121,127, 58, + 122,130, 53,122,130, 53,124,143, 31,124,150, 22,124,150, 22, + 123,141, 34,119,119, 77,122,135, 44,123,141, 34,123,141, 34, + 122,132, 48,121,127, 58,118,117, 85,115,107,129,114,104,197, + 119,119, 77,123,139, 37,124,149, 24,124,152, 20,124,161, 11, + 123,169, 4,123,173, 1,122,175, 0,123,174, 1,123,171, 3, + 124,165, 8,124,152, 20,122,130, 53,109, 92,251,105, 84,252, + 115,107,129,124,149, 24,123,172, 2,119,185, 0,116,192, 0, + 114,196, 0,113,198, 0,114,197, 0,115,194, 0,113,199, 0, + 112,200, 0,113,199, 0,115,194, 0,119,186, 0,123,173, 1, + 124,154, 18,124,149, 24,123,169, 4,121,181, 0,119,187, 0, + 118,189, 0,119,186, 0,121,180, 0,122,177, 0,122,178, 0, + 122,175, 0,123,170, 3,124,160, 12,123,141, 34,122,130, 53, + 115,107,129, 87, 65,237,111, 96,248,122,130, 53,124,147, 26, + 124,154, 18,124,152, 20,124,145, 29,122,135, 44,124,149, 24, + 124,152, 20,124,158, 13,124,165, 8,123,168, 5,123,174, 1, + 122,178, 0,122,178, 0,122,177, 0,121,182, 0,117,191, 0, + 113,198, 0,111,202, 0,111,202, 0,112,199, 0,115,194, 0, + 114,197, 0,115,195, 0,117,190, 0,121,181, 0,124,166, 7, + 123,141, 34,115,107,129, 30, 43,203, 87, 65,237,122,132, 48, + 124,157, 15,124,167, 6,123,168, 5,124,162, 10,124,149, 24, + 122,130, 53,124,147, 26,124,154, 18,124,154, 18,124,150, 22, + 124,143, 31,122,132, 48,118,117, 85,111, 96,248,114,104,197, + 120,122, 70,121,127, 58,123,137, 41,124,158, 13,123,174, 1, + 120,182, 0,119,186, 0,120,184, 0,120,182, 0,119,185, 0, + 120,184, 0,122,178, 0,124,164, 9,122,130, 53, 69, 60,230, + 109, 92,251,118,114, 96,123,137, 41,124,145, 29,124,149, 24, + 124,150, 22,124,150, 22,124,154, 18,124,167, 6,122,176, 0, + 121,179, 0,121,179, 0,121,179, 0,120,182, 0,120,182, 0, + 122,178, 0,123,170, 3,120,182, 0,117,190, 0,115,194, 0, + 116,193, 0,118,189, 0,122,178, 0,124,160, 12,121,127, 58, + 124,145, 29,124,157, 15,124,161, 11,124,161, 11,124,154, 18, + 123,137, 41,117,110,109, 30, 2,128, 30, 43,203,111, 96,248, + 121,127, 58,124,147, 26,124,155, 16,124,157, 15,124,154, 18, + 124,145, 29,124,157, 15,124,162, 10,124,164, 9,124,167, 6, + 123,169, 4,123,169, 4,123,170, 3,123,168, 5,123,174, 1, + 122,177, 0,121,181, 0,120,183, 0,120,182, 0,121,179, 0, + 123,172, 2,124,158, 13,124,164, 9,123,169, 4,123,171, 3, + 123,168, 5,124,157, 15,122,132, 48,102, 80,250, 30, 2,128, + 107, 89,252,124,143, 31,123,169, 4,121,182, 0,118,188, 0, + 117,190, 0,118,189, 0,119,186, 0,118,189, 0,118,189, 0, + 119,186, 0,121,180, 0,123,169, 4,124,150, 22,122,132, 48, + 111, 96,248,120,122, 70,123,137, 41,124,143, 31,123,139, 37, + 121,127, 58,113,100,242, 69, 60,230, 30, 26,168, 30, 55,222, + 114,104,197,121,127, 58,123,137, 41,122,135, 44,119,119, 77, + 99, 75,247, 30, 2,128, 99, 75,247,118,117, 85,124,145, 29, + 123,168, 5,121,181, 0,118,188, 0,117,192, 0,117,192, 0, + 114,197, 0,113,199, 0,113,198, 0,115,195, 0,117,191, 0, + 119,187, 0,120,184, 0,121,179, 0,119,185, 0,118,188, 0, + 118,188, 0,118,188, 0,118,188, 0,118,188, 0,119,186, 0, + 121,180, 0,121,180, 0,121,180, 0,122,178, 0,123,172, 2, + 124,160, 12,122,132, 48,102, 80,250, 30, 2,128, 30, 55,222, + 102, 80,250,107, 89,252,105, 84,252,109, 92,251,113,100,242, + 111, 96,248, 94, 70,242,109, 92,251,115,107,129,118,117, 85, + 121,125, 63,120,122, 70,117,110,109,109, 92,251, 99, 75,247, + 115,107,129,122,132, 48,124,149, 24,124,158, 13,124,164, 9, + 124,165, 8,124,165, 8,124,164, 9,124,166, 7,124,166, 7, + 124,162, 10,124,155, 16,123,141, 34,118,114, 96, 87, 65,237, + 30, 2,128, 99, 75,247,122,135, 44,124,165, 8,121,180, 0, + 118,188, 0,116,192, 0,116,193, 0,116,192, 0,114,197, 0, + 112,200, 0,111,201, 0,112,199, 0,116,193, 0,120,184, 0, + 124,167, 6,123,141, 34,124,164, 9,121,180, 0,118,189, 0, + 115,194, 0,114,196, 0,115,194, 0,118,189, 0,121,182, 0, + 120,183, 0,121,179, 0,123,170, 3,124,155, 16,121,127, 58, + 115,107,129, 94, 70,242, 30, 2,128, 99, 75,247,119,119, 77, + 123,141, 34,124,152, 20,124,152, 20,124,145, 29,122,132, 48, + 119,119, 77,121,127, 58,122,130, 53,124,145, 29,124,161, 11, + 123,170, 3,123,174, 1,123,173, 1,124,165, 8,121,182, 0, + 116,193, 0,111,201, 0,108,205, 0,107,207, 0,108,205, 0, + 111,201, 0,114,196, 0,115,195, 0,117,191, 0,120,182, 0, + 122,176, 0,124,164, 9,124,143, 31,111, 96,248, 30, 2,128, + 111, 96,248,123,139, 37,124,155, 16,124,160, 12,124,157, 15, + 124,150, 22,124,147, 26,124,145, 29,124,152, 20,124,152, 20, + 124,154, 18,124,154, 18,124,149, 24,123,139, 37,118,114, 96, + 69, 60,230,107, 89,252,114,104,197,121,125, 63,124,157, 15, + 123,171, 3,121,179, 0,121,182, 0,121,179, 0,119,186, 0, + 118,189, 0,118,189, 0,119,185, 0,122,175, 0,124,152, 20, + 111, 96,248, 30, 2,128, 99, 75,247,117,110,109,120,122, 70, + 121,127, 58,123,141, 34,124,149, 24,124,161, 11,124,166, 7, + 122,175, 0,122,178, 0,121,181, 0,120,184, 0,119,186, 0, + 120,184, 0,122,178, 0,124,166, 7,121,179, 0,119,187, 0, + 117,191, 0,117,191, 0,119,185, 0,123,174, 1,124,150, 22, + 118,114, 96,122,132, 48,124,145, 29,124,150, 22,124,147, 26, + 122,132, 48,115,107,129, 30, 55,222,109, 92,251,117,110,109, + 115,107,129,115,107,129,118,117, 85,123,137, 41,124,143, 31, + 124,143, 31,124,143, 31,124,157, 15,124,164, 9,124,165, 8, + 124,164, 9,124,160, 12,124,166, 7,123,174, 1,121,179, 0, + 120,182, 0,119,186, 0,118,188, 0,118,189, 0,118,188, 0, + 120,184, 0,122,177, 0,123,173, 1,122,175, 0,123,174, 1, + 123,171, 3,124,164, 9,124,147, 26,118,117, 85, 94, 70,242, + 105, 84,252,118,114, 96,124,155, 16,122,176, 0,119,186, 0, + 117,192, 0,115,194, 0,116,193, 0,117,191, 0,118,188, 0, + 118,188, 0,119,186, 0,121,182, 0,123,174, 1,124,162, 10, + 124,147, 26,122,130, 53,123,137, 41,124,149, 24,124,154, 18, + 124,154, 18,124,145, 29,122,130, 53,114,104,197, 87, 65,237, + 30, 15,143, 30, 37,192,105, 84,252,114,104,197,115,107,129, + 109, 92,251, 94, 70,242,105, 84,252,118,114, 96,124,143, 31, + 124,165, 8,122,178, 0,119,187, 0,116,192, 0,115,195, 0, + 114,196, 0,112,200, 0,111,201, 0,112,200, 0,114,197, 0, + 116,193, 0,118,189, 0,119,185, 0,117,190, 0,115,194, 0, + 114,197, 0,113,198, 0,113,198, 0,114,197, 0,114,196, 0, + 115,194, 0,116,193, 0,116,193, 0,116,193, 0,117,191, 0, + 119,186, 0,122,178, 0,124,161, 11,122,130, 53,102, 80,250, + 30, 55,222, 30, 37,192, 30, 31,180, 30, 20,155, 30, 15,143, + 30, 26,168, 30, 15,143, 30, 20,155, 87, 65,237,113,100,242, + 119,119, 77,122,130, 53,122,130, 53,119,119, 77,120,122, 70, + 124,143, 31,124,154, 18,124,160, 12,124,161, 11,124,167, 6, + 123,170, 3,123,172, 2,123,172, 2,123,172, 2,123,170, 3, + 124,167, 6,124,162, 10,124,152, 20,123,139, 37,119,119, 77, + 105, 84,252,105, 84,252,107, 89,252,120,122, 70,124,158, 13, + 122,175, 0,120,184, 0,118,188, 0,118,189, 0,116,193, 0, + 114,197, 0,112,199, 0,112,199, 0,114,196, 0,118,188, 0, + 122,175, 0,124,152, 20,124,162, 10,122,176, 0,118,188, 0, + 115,195, 0,112,200, 0,111,201, 0,112,199, 0,115,194, 0, + 118,189, 0,119,185, 0,120,182, 0,122,177, 0,124,166, 7, + 124,147, 26,120,122, 70,109, 92,251, 99, 75,247,121,125, 63, + 124,150, 22,124,161, 11,124,161, 11,124,154, 18,124,149, 24, + 123,137, 41,121,125, 63,120,122, 70,121,127, 58,123,137, 41, + 124,150, 22,124,161, 11,124,166, 7,124,166, 7,123,169, 4, + 120,183, 0,115,194, 0,110,202, 0,107,207, 0,105,209, 0, + 106,208, 0,108,205, 0,111,202, 0,113,198, 0,116,193, 0, + 118,189, 0,120,182, 0,123,172, 2,124,154, 18,118,117, 85, + 30, 31,180, 99, 75,247,120,122, 70,124,147, 26,124,157, 15, + 124,162, 10,124,164, 9,124,164, 9,124,162, 10,124,164, 9, + 124,166, 7,124,167, 6,124,166, 7,124,162, 10,124,154, 18, + 122,135, 44,111, 96,248,107, 89,252,118,114, 96,122,135, 44, + 124,152, 20,124,167, 6,123,174, 1,122,177, 0,121,180, 0, + 119,187, 0,117,191, 0,117,191, 0,118,188, 0,121,179, 0, + 124,161, 11,119,119, 77,107, 89,252,105, 84,252,118,114, 96, + 122,132, 48,124,147, 26,124,160, 12,123,170, 3,122,177, 0, + 121,179, 0,121,182, 0,119,185, 0,118,188, 0,118,189, 0, + 118,189, 0,119,186, 0,121,180, 0,123,168, 5,122,175, 0, + 120,184, 0,118,188, 0,119,187, 0,121,181, 0,124,167, 6, + 123,139, 37,111, 96,248,115,107,129,119,119, 77,120,122, 70, + 118,117, 85,117,110,109,107, 89,252,107, 89,252,124,143, 31, + 124,152, 20,124,150, 22,123,139, 37,121,127, 58,122,130, 53, + 119,119, 77,121,125, 63,123,137, 41,124,155, 16,124,164, 9, + 124,166, 7,124,166, 7,124,162, 10,123,172, 2,121,181, 0, + 119,186, 0,117,190, 0,116,193, 0,115,194, 0,116,193, 0, + 117,191, 0,119,186, 0,121,182, 0,120,183, 0,120,184, 0, + 120,183, 0,121,179, 0,123,171, 3,124,157, 15,122,132, 48, + 120,122, 70,121,127, 58,123,137, 41,124,162, 10,121,179, 0, + 118,189, 0,115,194, 0,114,197, 0,114,196, 0,115,194, 0, + 117,190, 0,119,186, 0,120,184, 0,121,180, 0,123,174, 1, + 124,166, 7,124,155, 16,124,145, 29,124,147, 26,124,157, 15, + 124,161, 11,124,161, 11,124,155, 16,124,143, 31,121,127, 58, + 117,110,109,105, 84,252, 30, 31,180, 30, 55,222,105, 84,252, + 114,104,197,118,114, 96,120,122, 70,122,132, 48,124,147, 26, + 124,162, 10,122,175, 0,120,184, 0,117,191, 0,114,196, 0, + 113,199, 0,113,199, 0,111,201, 0,110,202, 0,111,201, 0, + 113,198, 0,115,194, 0,117,191, 0,117,191, 0,115,195, 0, + 113,199, 0,111,201, 0,110,203, 0,109,204, 0,109,204, 0, + 109,204, 0,109,203, 0,110,203, 0,110,202, 0,111,201, 0, + 113,199, 0,115,194, 0,119,186, 0,123,173, 1,124,150, 22, + 118,117, 85,113,100,242,109, 92,251, 99, 75,247, 30, 49,213, + 30, 37,192, 30, 49,213, 30, 49,213, 69, 60,230,113,100,242, + 121,125, 63,123,139, 37,124,143, 31,123,139, 37,123,141, 34, + 124,162, 10,123,173, 1,122,178, 0,121,181, 0,121,182, 0, + 121,180, 0,122,176, 0,122,178, 0,122,178, 0,122,178, 0, + 122,178, 0,123,174, 1,123,169, 4,124,160, 12,124,145, 29, + 122,132, 48,122,132, 48,122,132, 48,122,132, 48,121,127, 58, + 124,154, 18,123,171, 3,121,180, 0,120,184, 0,119,187, 0, + 116,192, 0,114,196, 0,114,197, 0,115,194, 0,118,189, 0, + 122,178, 0,124,160, 12,124,161, 11,122,175, 0,120,184, 0, + 116,193, 0,112,199, 0,110,203, 0,109,204, 0,110,202, 0, + 112,199, 0,115,194, 0,118,188, 0,121,182, 0,122,176, 0, + 123,168, 5,124,157, 15,124,143, 31,121,127, 58,122,130, 53, + 124,157, 15,123,170, 3,122,177, 0,122,177, 0,123,171, 3, + 124,157, 15,124,143, 31,122,135, 44,122,132, 48,122,135, 44, + 123,139, 37,124,147, 26,124,154, 18,124,161, 11,124,166, 7, + 123,173, 1,119,186, 0,114,197, 0,109,204, 0,106,208, 0, + 104,210, 0,104,210, 0,106,208, 0,108,205, 0,110,202, 0, + 113,198, 0,116,193, 0,119,186, 0,122,175, 0,124,155, 16, + 119,119, 77, 87, 65,237,107, 89,252,121,125, 63,124,147, 26, + 124,158, 13,124,166, 7,123,169, 4,123,170, 3,123,171, 3, + 123,172, 2,123,173, 1,123,173, 1,123,171, 3,124,166, 7, + 124,155, 16,123,137, 41,114,104,197,114,104,197,121,125, 63, + 124,143, 31,124,154, 18,124,162, 10,123,168, 5,123,173, 1, + 121,182, 0,118,188, 0,117,191, 0,117,192, 0,118,189, 0, + 121,181, 0,124,167, 6,124,154, 18,123,141, 34,123,141, 34, + 124,149, 24,124,160, 12,123,170, 3,122,178, 0,120,184, 0, + 118,188, 0,117,190, 0,117,191, 0,116,193, 0,115,194, 0, + 115,194, 0,116,193, 0,118,189, 0,121,182, 0,123,169, 4, + 123,169, 4,122,178, 0,120,183, 0,121,182, 0,122,175, 0, + 124,161, 11,122,130, 53,102, 80,250, 30, 43,203, 87, 65,237, + 114,104,197,118,117, 85,118,114, 96,121,125, 63,123,137, 41, + 124,167, 6,123,172, 2,123,170, 3,124,165, 8,124,154, 18, + 124,145, 29,123,141, 34,121,125, 63,121,125, 63,124,150, 22, + 124,162, 10,123,168, 5,123,169, 4,124,167, 6,123,174, 1, + 120,184, 0,117,191, 0,115,194, 0,113,198, 0,113,198, 0, + 114,197, 0,115,194, 0,118,188, 0,119,187, 0,118,189, 0, + 118,189, 0,118,188, 0,120,184, 0,122,176, 0,124,165, 8, + 124,145, 29,124,145, 29,124,149, 24,124,152, 20,124,164, 9, + 121,180, 0,118,189, 0,115,195, 0,113,198, 0,113,198, 0, + 114,196, 0,117,192, 0,119,186, 0,121,179, 0,122,177, 0, + 123,171, 3,124,165, 8,124,157, 15,124,150, 22,124,152, 20, + 124,161, 11,124,164, 9,124,162, 10,124,157, 15,124,149, 24, + 123,137, 41,122,130, 53,118,117, 85,107, 89,252, 69, 60,230, + 113,100,242,120,122, 70,123,137, 41,124,147, 26,124,155, 16, + 124,162, 10,123,173, 1,120,183, 0,118,189, 0,115,194, 0, + 113,199, 0,111,202, 0,110,202, 0,110,202, 0,110,202, 0, + 111,201, 0,113,198, 0,114,196, 0,116,192, 0,115,194, 0, + 113,198, 0,111,201, 0,110,203, 0,108,205, 0,107,207, 0, + 106,208, 0,105,209, 0,105,209, 0,105,209, 0,106,208, 0, + 107,206, 0,110,203, 0,113,198, 0,117,190, 0,122,178, 0, + 124,160, 12,122,132, 48,121,127, 58,119,119, 77,115,107,129, + 107, 89,252,105, 84,252,109, 92,251,113,100,242,111, 96,248, + 118,117, 85,123,137, 41,124,147, 26,124,150, 22,124,147, 26, + 124,167, 6,121,180, 0,119,187, 0,117,191, 0,116,192, 0, + 116,192, 0,117,191, 0,118,189, 0,119,186, 0,120,183, 0, + 121,181, 0,121,181, 0,122,178, 0,123,172, 2,123,168, 5, + 124,164, 9,124,160, 12,124,157, 15,124,157, 15,124,155, 16, + 124,152, 20,124,158, 13,123,169, 4,122,177, 0,121,179, 0, + 120,184, 0,118,189, 0,116,192, 0,117,192, 0,118,188, 0, + 121,180, 0,124,165, 8,124,150, 22,123,173, 1,120,183, 0, + 118,189, 0,115,195, 0,112,200, 0,109,203, 0,108,205, 0, + 109,204, 0,111,201, 0,114,197, 0,117,192, 0,119,185, 0, + 122,175, 0,124,167, 6,124,160, 12,124,150, 22,124,143, 31, + 124,157, 15,123,172, 2,121,182, 0,119,186, 0,119,185, 0, + 121,181, 0,123,170, 3,124,152, 20,123,139, 37,122,135, 44, + 122,135, 44,123,137, 41,124,143, 31,124,150, 22,124,158, 13, + 123,169, 4,121,180, 0,117,190, 0,113,198, 0,109,204, 0, + 105,209, 0,103,211, 0,103,211, 0,104,210, 0,106,208, 0, + 108,205, 0,111,201, 0,115,195, 0,119,187, 0,122,175, 0, + 124,154, 18,119,119, 77,109, 92,251,107, 89,252,119,119, 77, + 123,139, 37,124,154, 18,124,162, 10,124,167, 6,123,171, 3, + 123,174, 1,122,176, 0,122,176, 0,123,174, 1,123,170, 3, + 124,164, 9,124,150, 22,122,130, 53,111, 96,248,117,110,109, + 122,132, 48,124,150, 22,124,160, 12,124,165, 8,124,165, 8, + 123,173, 1,121,182, 0,119,187, 0,117,190, 0,117,191, 0, + 118,188, 0,120,184, 0,122,178, 0,123,170, 3,124,165, 8, + 124,165, 8,123,170, 3,122,177, 0,120,183, 0,118,189, 0, + 116,193, 0,114,196, 0,114,197, 0,113,198, 0,112,200, 0, + 112,200, 0,112,199, 0,114,197, 0,117,192, 0,120,184, 0, + 123,169, 4,124,167, 6,123,171, 3,122,176, 0,122,175, 0, + 123,168, 5,124,152, 20,119,119, 77, 69, 60,230, 30, 55,222, + 99, 75,247,114,104,197,120,122, 70,123,141, 34,124,154, 18, + 124,162, 10,122,178, 0,120,182, 0,121,181, 0,122,177, 0, + 123,169, 4,124,161, 11,124,157, 15,124,149, 24,124,147, 26, + 124,150, 22,124,160, 12,123,169, 4,123,172, 2,123,171, 3, + 123,172, 2,120,184, 0,116,192, 0,114,197, 0,112,200, 0, + 111,201, 0,112,200, 0,114,196, 0,118,189, 0,118,189, 0, + 117,192, 0,117,192, 0,117,190, 0,119,186, 0,122,178, 0, + 123,168, 5,124,154, 18,124,157, 15,124,157, 15,124,158, 13, + 124,165, 8,122,178, 0,118,188, 0,115,194, 0,114,197, 0, + 114,197, 0,115,195, 0,117,191, 0,119,185, 0,122,178, 0, + 123,169, 4,124,164, 9,124,157, 15,124,150, 22,124,147, 26, + 124,154, 18,124,160, 12,124,161, 11,124,158, 13,124,152, 20, + 124,145, 29,123,137, 41,122,135, 44,122,130, 53,118,117, 85, + 111, 96,248,115,107,129,122,135, 44,124,150, 22,124,161, 11, + 124,166, 7,123,171, 3,120,184, 0,116,192, 0,113,198, 0, + 111,201, 0,110,202, 0,109,204, 0,107,206, 0,107,207, 0, + 107,206, 0,108,205, 0,110,203, 0,111,201, 0,113,198, 0, + 113,199, 0,111,201, 0,111,201, 0,109,203, 0,108,206, 0, + 106,208, 0,104,210, 0,103,211, 0,103,212, 0,103,211, 0, + 104,210, 0,106,208, 0,108,205, 0,112,199, 0,117,191, 0, + 121,180, 0,124,164, 9,124,145, 29,124,143, 31,123,137, 41, + 121,125, 63,117,110,109,115,107,129,118,117, 85,121,125, 63, + 121,125, 63,121,125, 63,124,143, 31,124,152, 20,124,155, 16, + 124,164, 9,122,178, 0,118,188, 0,115,194, 0,114,197, 0, + 113,199, 0,113,199, 0,113,198, 0,114,196, 0,115,194, 0, + 116,192, 0,117,192, 0,117,191, 0,118,189, 0,119,187, 0, + 120,183, 0,121,179, 0,122,175, 0,123,171, 3,123,170, 3, + 123,171, 3,123,173, 1,123,174, 1,123,173, 1,123,174, 1, + 122,176, 0,121,179, 0,120,184, 0,119,187, 0,119,185, 0, + 121,179, 0,124,167, 6,124,143, 31,124,165, 8,121,181, 0, + 119,187, 0,117,191, 0,115,195, 0,113,199, 0,111,202, 0, + 110,203, 0,110,202, 0,111,201, 0,114,197, 0,116,192, 0, + 119,186, 0,122,176, 0,124,161, 11,124,155, 16,124,150, 22, + 124,152, 20,123,170, 3,121,181, 0,118,188, 0,117,191, 0, + 117,190, 0,119,186, 0,122,177, 0,124,161, 11,123,139, 37, + 122,132, 48,122,130, 53,122,130, 53,124,147, 26,124,160, 12, + 123,169, 4,122,178, 0,119,186, 0,116,193, 0,112,199, 0, + 109,204, 0,106,207, 0,105,209, 0,104,210, 0,105,209, 0, + 106,208, 0,107,206, 0,110,202, 0,114,196, 0,119,186, 0, + 123,172, 2,124,150, 22,122,132, 48,115,107,129,102, 80,250, + 114,104,197,120,122, 70,123,137, 41,124,149, 24,124,158, 13, + 124,166, 7,123,171, 3,123,174, 1,123,174, 1,123,171, 3, + 124,166, 7,124,154, 18,123,137, 41,117,110,109,109, 92,251, + 118,117, 85,123,141, 34,124,158, 13,124,166, 7,123,169, 4, + 123,168, 5,122,177, 0,120,184, 0,118,188, 0,117,191, 0, + 116,192, 0,117,191, 0,118,188, 0,120,183, 0,122,178, 0, + 123,174, 1,122,176, 0,121,180, 0,119,185, 0,117,190, 0, + 115,194, 0,113,198, 0,112,200, 0,111,202, 0,110,202, 0, + 109,203, 0,109,204, 0,110,202, 0,112,200, 0,115,194, 0, + 119,186, 0,123,170, 3,124,165, 8,124,162, 10,124,167, 6, + 124,165, 8,124,157, 15,123,139, 37,114,104,197,115,107,129, + 117,110,109,119,119, 77,122,135, 44,124,147, 26,124,160, 12, + 123,168, 5,123,174, 1,120,184, 0,119,187, 0,119,186, 0, + 120,183, 0,122,178, 0,123,171, 3,123,170, 3,124,166, 7, + 124,164, 9,123,168, 5,123,170, 3,123,168, 5,123,174, 1, + 122,176, 0,123,174, 1,121,182, 0,117,191, 0,114,197, 0, + 111,201, 0,110,202, 0,111,201, 0,114,197, 0,117,190, 0, + 118,189, 0,117,191, 0,117,191, 0,118,189, 0,120,184, 0, + 122,178, 0,123,169, 4,124,161, 11,124,162, 10,124,161, 11, + 124,160, 12,124,165, 8,123,174, 1,120,184, 0,117,191, 0, + 115,194, 0,115,194, 0,117,192, 0,119,187, 0,121,181, 0, + 123,173, 1,124,161, 11,124,150, 22,123,141, 34,122,132, 48, + 122,132, 48,124,147, 26,124,152, 20,124,152, 20,124,147, 26, + 123,139, 37,122,130, 53,121,125, 63,122,130, 53,122,132, 48, + 121,127, 58,119,119, 77,118,114, 96,123,141, 34,124,157, 15, + 124,167, 6,123,172, 2,121,181, 0,116,192, 0,112,200, 0, + 108,205, 0,107,207, 0,106,207, 0,107,207, 0,105,209, 0, + 104,210, 0,104,210, 0,105,209, 0,106,208, 0,108,205, 0, + 110,202, 0,111,202, 0,109,203, 0,109,204, 0,109,204, 0, + 108,205, 0,107,207, 0,105,209, 0,103,211, 0,103,211, 0, + 104,210, 0,105,209, 0,107,207, 0,109,203, 0,113,198, 0, + 117,191, 0,121,180, 0,124,164, 9,124,154, 18,124,152, 20, + 124,147, 26,123,137, 41,120,122, 70,119,119, 77,122,130, 53, + 123,137, 41,123,139, 37,122,135, 44,124,147, 26,124,157, 15, + 124,162, 10,123,170, 3,121,182, 0,117,191, 0,114,197, 0, + 112,200, 0,111,202, 0,111,202, 0,111,201, 0,112,199, 0, + 113,198, 0,114,197, 0,113,198, 0,113,198, 0,114,197, 0, + 115,195, 0,117,192, 0,118,188, 0,120,184, 0,120,184, 0, + 119,185, 0,119,185, 0,119,186, 0,119,185, 0,120,183, 0, + 122,178, 0,123,171, 3,123,170, 3,122,177, 0,122,178, 0, + 122,176, 0,124,167, 6,124,149, 24,124,145, 29,123,171, 3, + 120,184, 0,118,188, 0,118,189, 0,116,192, 0,115,194, 0, + 114,197, 0,113,198, 0,113,198, 0,114,197, 0,115,194, 0, + 117,190, 0,120,184, 0,123,174, 1,124,158, 13,124,143, 31, + 123,141, 34,124,162, 10,122,175, 0,120,184, 0,118,189, 0, + 117,192, 0,117,191, 0,119,187, 0,122,178, 0,124,162, 10, + 123,139, 37,120,122, 70,118,117, 85,123,141, 34,124,158, 13, + 123,168, 5,122,176, 0,120,182, 0,118,189, 0,115,195, 0, + 112,199, 0,110,202, 0,109,204, 0,107,206, 0,107,207, 0, + 106,207, 0,107,207, 0,108,205, 0,111,201, 0,115,194, 0, + 120,184, 0,123,168, 5,124,152, 20,123,139, 37,118,117, 85, + 102, 80,250, 87, 65,237,105, 84,252,114,104,197,120,122, 70, + 123,139, 37,124,154, 18,124,164, 9,123,168, 5,123,168, 5, + 124,165, 8,124,155, 16,123,139, 37,118,114, 96,109, 92,251, + 114,104,197,121,125, 63,124,149, 24,124,165, 8,123,172, 2, + 122,175, 0,123,174, 1,121,179, 0,119,186, 0,118,189, 0, + 116,192, 0,116,193, 0,117,191, 0,118,188, 0,120,184, 0, + 121,179, 0,122,178, 0,121,179, 0,120,184, 0,118,188, 0, + 116,192, 0,114,196, 0,112,199, 0,111,201, 0,110,202, 0, + 109,204, 0,108,205, 0,108,205, 0,109,204, 0,111,201, 0, + 114,196, 0,119,187, 0,123,171, 3,124,162, 10,124,155, 16, + 124,154, 18,124,152, 20,123,141, 34,119,119, 77,122,130, 53, + 123,139, 37,124,147, 26,124,150, 22,124,152, 20,124,161, 11, + 123,169, 4,122,175, 0,121,180, 0,119,186, 0,118,189, 0, + 118,189, 0,119,186, 0,120,182, 0,122,178, 0,121,179, 0, + 122,177, 0,123,173, 1,122,178, 0,120,182, 0,120,183, 0, + 121,181, 0,122,178, 0,122,178, 0,122,176, 0,119,186, 0, + 115,194, 0,113,199, 0,111,201, 0,112,200, 0,114,197, 0, + 117,190, 0,120,184, 0,118,188, 0,118,188, 0,119,185, 0, + 121,181, 0,122,175, 0,124,167, 6,124,164, 9,124,165, 8, + 124,161, 11,124,165, 8,124,164, 9,124,167, 6,122,178, 0, + 119,185, 0,118,189, 0,118,189, 0,119,186, 0,121,179, 0, + 123,172, 2,124,165, 8,124,154, 18,123,137, 41,117,110,109, + 113,100,242,119,119, 77,123,137, 41,123,139, 37,123,137, 41, + 121,127, 58,118,114, 96,114,104,197,113,100,242,118,114, 96, + 121,125, 63,121,127, 58,121,125, 63,121,125, 63,124,143, 31, + 124,161, 11,123,170, 3,122,175, 0,118,188, 0,113,198, 0, + 108,206, 0,104,210, 0,102,212, 0,103,212, 0,104,210, 0, + 103,211, 0,102,213, 0,101,214, 0,101,213, 0,103,211, 0, + 105,209, 0,108,206, 0,110,203, 0,108,205, 0,107,206, 0, + 107,206, 0,108,205, 0,108,205, 0,107,207, 0,106,208, 0, + 106,208, 0,107,207, 0,108,205, 0,110,203, 0,112,200, 0, + 114,196, 0,118,189, 0,122,178, 0,124,164, 9,124,157, 15, + 124,157, 15,124,150, 22,123,141, 34,121,127, 58,120,122, 70, + 122,135, 44,123,141, 34,124,143, 31,123,141, 34,124,150, 22, + 124,162, 10,123,168, 5,123,171, 3,121,181, 0,118,189, 0, + 114,196, 0,112,200, 0,111,201, 0,111,201, 0,111,201, 0, + 112,200, 0,112,199, 0,112,199, 0,111,201, 0,110,202, 0, + 110,202, 0,111,201, 0,113,198, 0,115,194, 0,117,191, 0, + 116,193, 0,115,194, 0,116,193, 0,116,193, 0,116,193, 0, + 117,190, 0,120,184, 0,123,174, 1,124,161, 11,124,164, 9, + 124,166, 7,124,161, 11,124,149, 24,121,125, 63,124,152, 20, + 123,173, 1,120,184, 0,119,186, 0,119,186, 0,119,186, 0, + 118,188, 0,118,189, 0,117,190, 0,117,191, 0,117,191, 0, + 118,188, 0,120,184, 0,122,178, 0,123,168, 5,124,154, 18, + 121,127, 58,124,147, 26,124,165, 8,122,176, 0,120,184, 0, + 118,189, 0,117,191, 0,118,189, 0,119,185, 0,122,176, 0, + 124,160, 12,122,132, 48,113,100,242,121,127, 58,124,152, 20, + 124,166, 7,123,174, 1,121,180, 0,120,184, 0,117,190, 0, + 115,194, 0,114,197, 0,112,199, 0,111,202, 0,110,203, 0, + 110,202, 0,109,203, 0,109,204, 0,110,202, 0,113,199, 0, + 117,192, 0,121,182, 0,124,165, 8,124,150, 22,123,137, 41, + 118,114, 96, 94, 70,242, 30, 10,132, 30, 49,213,107, 89,252, + 114,104,197,115,107,129,121,127, 58,124,147, 26,124,155, 16, + 124,157, 15,124,150, 22,123,137, 41,118,114, 96,111, 96,248, + 115,107,129,119,119, 77,122,130, 53,124,157, 15,123,171, 3, + 122,178, 0,121,182, 0,121,180, 0,121,179, 0,119,186, 0, + 118,189, 0,117,192, 0,117,192, 0,118,189, 0,119,186, 0, + 121,182, 0,122,177, 0,122,176, 0,121,179, 0,120,184, 0, + 118,188, 0,116,192, 0,114,196, 0,113,198, 0,112,200, 0, + 111,201, 0,110,203, 0,109,204, 0,108,205, 0,109,204, 0, + 111,202, 0,114,196, 0,119,187, 0,123,171, 3,124,158, 13, + 124,147, 26,123,139, 37,122,132, 48,118,117, 85,122,132, 48, + 124,145, 29,124,158, 13,124,166, 7,123,168, 5,123,169, 4, + 123,170, 3,123,173, 1,122,178, 0,120,184, 0,118,189, 0, + 117,191, 0,117,191, 0,118,189, 0,119,185, 0,119,186, 0, + 119,186, 0,120,184, 0,121,180, 0,119,186, 0,117,190, 0, + 116,192, 0,116,192, 0,118,188, 0,121,180, 0,122,177, 0, + 121,180, 0,118,189, 0,114,196, 0,113,199, 0,113,198, 0, + 115,195, 0,118,189, 0,121,180, 0,121,180, 0,121,180, 0, + 122,178, 0,123,173, 1,123,168, 5,124,164, 9,124,166, 7, + 124,165, 8,124,165, 8,123,170, 3,123,170, 3,123,168, 5, + 123,171, 3,122,178, 0,121,182, 0,121,182, 0,122,176, 0, + 124,167, 6,124,160, 12,124,150, 22,123,139, 37,121,125, 63, + 113,100,242,105, 84,252,113,100,242,119,119, 77,119,119, 77, + 117,110,109,109, 92,251, 94, 70,242, 99, 75,247, 94, 70,242, + 105, 84,252,115,107,129,119,119, 77,120,122, 70,121,127, 58, + 124,145, 29,124,162, 10,123,172, 2,122,178, 0,117,191, 0, + 110,202, 0,105,209, 0,101,214, 0, 99,215, 0,100,215, 0, + 102,213, 0,102,212, 0,100,214, 0, 99,215, 0,100,215, 0, + 101,214, 0,103,211, 0,106,207, 0,108,205, 0,109,204, 0, + 108,206, 0,107,206, 0,108,206, 0,109,204, 0,110,202, 0, + 110,203, 0,110,203, 0,111,201, 0,112,200, 0,113,198, 0, + 114,196, 0,117,192, 0,119,186, 0,122,178, 0,124,165, 8, + 124,157, 15,124,155, 16,124,152, 20,124,143, 31,122,132, 48, + 121,127, 58,123,137, 41,124,143, 31,123,141, 34,123,137, 41, + 124,155, 16,124,167, 6,122,175, 0,121,179, 0,121,181, 0, + 119,186, 0,116,193, 0,114,197, 0,112,199, 0,112,200, 0, + 112,199, 0,112,199, 0,112,199, 0,112,200, 0,110,202, 0, + 109,204, 0,108,205, 0,109,204, 0,110,202, 0,112,200, 0, + 113,198, 0,112,199, 0,112,199, 0,113,199, 0,113,198, 0, + 114,197, 0,115,194, 0,118,189, 0,121,179, 0,124,161, 11, + 124,143, 31,124,147, 26,123,139, 37,120,122, 70,121,127, 58, + 124,155, 16,123,173, 1,121,181, 0,120,182, 0,121,179, 0, + 120,183, 0,119,185, 0,120,184, 0,121,181, 0,121,180, 0, + 121,180, 0,122,178, 0,123,173, 1,124,167, 6,124,158, 13, + 124,147, 26,124,152, 20,124,154, 18,124,164, 9,123,172, 2, + 121,180, 0,119,185, 0,119,187, 0,119,186, 0,121,181, 0, + 123,170, 3,124,150, 22,118,117, 85,113,100,242,123,137, 41, + 124,157, 15,123,168, 5,122,175, 0,121,180, 0,120,184, 0, + 118,188, 0,116,192, 0,114,196, 0,111,202, 0,108,205, 0, + 107,207, 0,108,205, 0,111,202, 0,112,200, 0,113,199, 0, + 115,195, 0,118,189, 0,122,178, 0,124,161, 11,124,143, 31, + 121,127, 58,114,104,197, 69, 60,230, 30, 55,222, 94, 70,242, + 114,104,197,119,119, 77,119,119, 77,117,110,109,119,119, 77, + 122,135, 44,123,137, 41,122,130, 53,118,114, 96,105, 84,252, + 109, 92,251,118,117, 85,121,125, 63,123,139, 37,124,164, 9, + 122,177, 0,120,184, 0,119,186, 0,119,186, 0,120,182, 0, + 120,184, 0,118,188, 0,118,189, 0,118,189, 0,119,186, 0, + 120,182, 0,122,177, 0,123,172, 2,123,171, 3,122,178, 0, + 119,185, 0,118,188, 0,118,189, 0,116,193, 0,115,195, 0, + 114,197, 0,113,198, 0,112,200, 0,110,202, 0,109,203, 0, + 109,203, 0,111,201, 0,114,196, 0,119,186, 0,123,169, 4, + 124,155, 16,123,137, 41,120,122, 70,117,110,109,120,122, 70, + 123,141, 34,124,157, 15,123,168, 5,122,176, 0,122,178, 0, + 122,178, 0,121,182, 0,120,184, 0,119,185, 0,119,186, 0, + 116,192, 0,115,194, 0,116,192, 0,117,191, 0,118,189, 0, + 117,191, 0,117,191, 0,118,189, 0,119,185, 0,117,191, 0, + 114,196, 0,113,199, 0,112,199, 0,114,196, 0,117,190, 0, + 121,180, 0,123,170, 3,120,183, 0,117,191, 0,115,194, 0, + 115,195, 0,116,192, 0,119,186, 0,122,177, 0,124,166, 7, + 124,167, 6,124,165, 8,124,161, 11,124,160, 12,124,164, 9, + 124,166, 7,124,166, 7,124,162, 10,123,169, 4,123,171, 3, + 123,169, 4,124,166, 7,123,170, 3,123,173, 1,123,171, 3, + 124,162, 10,124,161, 11,124,150, 22,122,130, 53,118,114, 96, + 113,100,242,105, 84,252,111, 96,248,105, 84,252,114,104,197, + 113,100,242,102, 80,250, 30, 55,222, 87, 65,237, 99, 75,247, + 99, 75,247, 30, 49,213,102, 80,250,113,100,242,118,114, 96, + 120,122, 70,124,145, 29,124,164, 9,123,174, 1,122,178, 0, + 116,192, 0,110,203, 0,103,211, 0, 99,215, 0, 97,217, 0, + 98,217, 0,100,215, 0,102,212, 0,100,215, 0, 99,216, 0, + 99,215, 0,101,214, 0,103,211, 0,106,208, 0,108,206, 0, + 108,205, 0,108,206, 0,108,206, 0,108,205, 0,109,204, 0, + 110,202, 0,111,201, 0,113,198, 0,115,195, 0,116,193, 0, + 117,192, 0,117,191, 0,118,188, 0,120,184, 0,122,177, 0, + 124,166, 7,124,150, 22,124,154, 18,124,154, 18,124,152, 20, + 124,149, 24,124,145, 29,124,145, 29,124,149, 24,124,147, 26, + 124,155, 16,124,164, 9,123,172, 2,121,180, 0,120,184, 0, + 119,186, 0,118,188, 0,118,189, 0,115,194, 0,114,197, 0, + 113,199, 0,111,202, 0,109,204, 0,108,205, 0,108,205, 0, + 110,203, 0,108,205, 0,107,207, 0,106,207, 0,107,207, 0, + 108,205, 0,109,203, 0,111,202, 0,111,201, 0,112,200, 0, + 112,200, 0,113,199, 0,114,196, 0,117,191, 0,121,181, 0, + 124,164, 9,121,125, 63,119,119, 77,118,114, 96,115,107,129, + 122,135, 44,124,154, 18,123,170, 3,122,177, 0,122,177, 0, + 120,182, 0,119,186, 0,119,187, 0,119,186, 0,121,182, 0, + 122,175, 0,124,167, 6,124,158, 13,124,152, 20,124,147, 26, + 124,155, 16,124,162, 10,124,167, 6,123,169, 4,123,169, 4, + 123,168, 5,122,175, 0,121,181, 0,120,182, 0,121,181, 0, + 122,175, 0,124,162, 10,123,137, 41,109, 92,251,113,100,242, + 123,137, 41,124,155, 16,124,166, 7,123,171, 3,122,175, 0, + 122,178, 0,120,184, 0,117,192, 0,112,199, 0,109,204, 0, + 106,207, 0,106,208, 0,107,206, 0,110,202, 0,115,195, 0, + 115,194, 0,117,192, 0,119,186, 0,122,176, 0,124,160, 12, + 122,132, 48,118,117, 85,114,104,197,114,104,197,117,110,109, + 117,110,109,118,117, 85,120,122, 70,119,119, 77,115,107,129, + 105, 84,252,117,110,109,118,114, 96,115,107,129,107, 89,252, + 30, 55,222,105, 84,252,117,110,109,118,117, 85,124,149, 24, + 123,169, 4,121,182, 0,118,188, 0,117,191, 0,117,190, 0, + 119,187, 0,120,182, 0,119,186, 0,118,188, 0,119,186, 0, + 120,183, 0,122,178, 0,123,171, 3,124,166, 7,124,167, 6, + 122,178, 0,119,185, 0,118,188, 0,118,189, 0,118,189, 0, + 117,192, 0,116,193, 0,115,195, 0,114,197, 0,112,200, 0, + 111,201, 0,111,201, 0,112,199, 0,115,194, 0,120,184, 0, + 124,166, 7,124,152, 20,121,125, 63,115,107,129,113,100,242, + 122,132, 48,124,150, 22,124,166, 7,122,175, 0,121,182, 0, + 119,186, 0,117,190, 0,116,193, 0,115,195, 0,115,195, 0, + 115,194, 0,112,200, 0,113,198, 0,114,197, 0,115,195, 0, + 115,194, 0,115,194, 0,115,194, 0,116,193, 0,117,190, 0, + 115,195, 0,112,200, 0,110,202, 0,110,203, 0,112,200, 0, + 115,194, 0,119,186, 0,122,175, 0,122,175, 0,120,182, 0, + 119,187, 0,118,188, 0,119,186, 0,121,179, 0,123,170, 3, + 124,158, 13,124,150, 22,124,149, 24,124,152, 20,124,157, 15, + 124,161, 11,124,164, 9,124,165, 8,124,161, 11,124,165, 8, + 123,168, 5,124,167, 6,124,164, 9,124,162, 10,124,161, 11, + 124,158, 13,124,158, 13,124,155, 16,123,141, 34,118,114, 96, + 94, 70,242, 69, 60,230,109, 92,251,114,104,197,107, 89,252, + 102, 80,250, 94, 70,242, 30, 43,203, 30, 31,180, 87, 65,237, + 105, 84,252,107, 89,252, 87, 65,237,105, 84,252,102, 80,250, + 109, 92,251,117,110,109,124,143, 31,124,164, 9,123,174, 1, + 121,180, 0,117,191, 0,110,202, 0,104,210, 0,100,215, 0, + 97,217, 0, 97,217, 0, 99,216, 0,101,214, 0,101,214, 0, + 100,214, 0,101,214, 0,102,212, 0,104,210, 0,104,210, 0, + 103,211, 0,104,210, 0,105,209, 0,106,207, 0,106,208, 0, + 105,209, 0,106,208, 0,107,207, 0,108,205, 0,110,202, 0, + 113,198, 0,117,192, 0,117,191, 0,117,190, 0,118,188, 0, + 119,185, 0,122,178, 0,123,169, 4,124,157, 15,124,155, 16, + 124,157, 15,124,158, 13,124,160, 12,124,161, 11,124,164, 9, + 123,168, 5,123,174, 1,122,178, 0,121,181, 0,120,182, 0, + 119,186, 0,118,189, 0,117,190, 0,116,192, 0,115,195, 0, + 112,199, 0,110,202, 0,108,206, 0,106,208, 0,105,209, 0, + 105,209, 0,106,207, 0,106,207, 0,105,209, 0,104,210, 0, + 103,211, 0,104,210, 0,105,209, 0,106,208, 0,106,207, 0, + 108,206, 0,111,201, 0,114,197, 0,115,194, 0,117,190, 0, + 121,182, 0,124,165, 8,121,127, 58, 99, 75,247, 87, 65,237, + 115,107,129,123,137, 41,124,154, 18,124,166, 7,123,172, 2, + 122,178, 0,120,183, 0,119,186, 0,119,186, 0,120,184, 0, + 121,179, 0,123,171, 3,124,162, 10,124,155, 16,124,158, 13, + 124,157, 15,124,165, 8,123,171, 3,122,176, 0,122,178, 0, + 121,179, 0,122,178, 0,123,172, 2,123,172, 2,122,175, 0, + 123,173, 1,124,167, 6,124,152, 20,121,125, 63, 99, 75,247, + 105, 84,252,119,119, 77,123,141, 34,124,154, 18,124,160, 12, + 124,165, 8,122,178, 0,118,188, 0,115,194, 0,111,201, 0, + 108,205, 0,107,207, 0,107,207, 0,109,204, 0,112,199, 0, + 116,192, 0,117,192, 0,118,188, 0,120,183, 0,123,174, 1, + 124,160, 12,124,145, 29,124,143, 31,123,139, 37,123,139, 37, + 123,139, 37,123,137, 41,122,132, 48,121,127, 58,117,110,109, + 105, 84,252, 30, 55,222,107, 89,252,111, 96,248,107, 89,252, + 94, 70,242, 87, 65,237,105, 84,252,115,107,129,122,132, 48, + 124,158, 13,122,175, 0,119,185, 0,117,191, 0,116,192, 0, + 117,192, 0,118,189, 0,119,185, 0,119,185, 0,119,186, 0, + 120,184, 0,121,181, 0,122,175, 0,122,175, 0,122,176, 0, + 121,181, 0,119,186, 0,118,188, 0,117,190, 0,117,190, 0, + 118,188, 0,117,191, 0,114,196, 0,113,199, 0,112,199, 0, + 113,198, 0,112,200, 0,112,200, 0,113,198, 0,116,193, 0, + 120,183, 0,124,162, 10,124,145, 29,114,104,197,107, 89,252, + 117,110,109,124,145, 29,123,170, 3,120,184, 0,118,189, 0, + 116,193, 0,114,197, 0,112,200, 0,110,202, 0,110,203, 0, + 110,202, 0,111,201, 0,107,206, 0,108,205, 0,108,205, 0, + 109,204, 0,111,202, 0,113,198, 0,114,197, 0,115,194, 0, + 115,194, 0,113,198, 0,110,202, 0,108,205, 0,108,205, 0, + 110,202, 0,114,197, 0,118,189, 0,121,180, 0,122,177, 0, + 122,175, 0,123,172, 2,123,173, 1,123,171, 3,124,165, 8, + 124,155, 16,124,143, 31,123,137, 41,123,137, 41,124,143, 31, + 124,149, 24,124,154, 18,124,157, 15,124,157, 15,124,154, 18, + 124,160, 12,124,165, 8,124,165, 8,124,164, 9,124,160, 12, + 124,157, 15,124,155, 16,124,154, 18,124,149, 24,122,130, 53, + 109, 92,251, 30, 15,143, 69, 60,230,113,100,242,117,110,109, + 109, 92,251, 30, 55,222, 30, 26,168, 30, 15,143, 30, 37,192, + 99, 75,247,109, 92,251,111, 96,248,102, 80,250,111, 96,248, + 109, 92,251, 99, 75,247,111, 96,248,122,135, 44,124,160, 12, + 123,172, 2,122,178, 0,118,188, 0,112,200, 0,106,208, 0, + 101,214, 0, 98,216, 0, 98,217, 0, 99,216, 0,100,215, 0, + 100,214, 0,101,214, 0,101,214, 0,101,214, 0,100,214, 0, + 100,215, 0,100,215, 0,101,214, 0,102,213, 0,104,210, 0, + 102,212, 0,101,214, 0,100,214, 0,101,214, 0,102,213, 0, + 103,211, 0,106,207, 0,111,201, 0,116,193, 0,116,193, 0, + 116,193, 0,117,191, 0,118,188, 0,121,181, 0,123,173, 1, + 124,166, 7,124,160, 12,124,162, 10,123,168, 5,123,172, 2, + 122,177, 0,121,182, 0,119,185, 0,118,188, 0,118,189, 0, + 118,188, 0,119,185, 0,119,187, 0,118,189, 0,117,192, 0, + 114,196, 0,112,200, 0,109,204, 0,106,207, 0,105,209, 0, + 103,211, 0,103,211, 0,105,209, 0,104,210, 0,102,212, 0, + 101,213, 0,101,214, 0,101,214, 0,101,213, 0,102,212, 0, + 102,212, 0,103,211, 0,108,206, 0,113,198, 0,116,192, 0, + 118,189, 0,121,182, 0,124,167, 6,122,135, 44, 87, 65,237, + 30, 26,168,111, 96,248,122,132, 48,124,152, 20,124,165, 8, + 123,172, 2,122,178, 0,120,182, 0,120,184, 0,120,183, 0, + 121,179, 0,123,172, 2,123,168, 5,123,169, 4,123,172, 2, + 123,174, 1,123,171, 3,123,172, 2,122,178, 0,120,183, 0, + 119,185, 0,119,186, 0,119,185, 0,121,179, 0,124,167, 6, + 124,161, 11,124,160, 12,124,152, 20,123,137, 41,115,107,129, + 30, 55,222, 30, 31,180,102, 80,250,115,107,129,121,125, 63, + 124,145, 29,123,168, 5,120,182, 0,117,190, 0,114,196, 0, + 112,200, 0,110,202, 0,109,203, 0,110,202, 0,112,199, 0, + 116,193, 0,117,191, 0,118,189, 0,119,186, 0,121,180, 0, + 123,171, 3,124,160, 12,124,161, 11,124,161, 11,124,160, 12, + 124,158, 13,124,157, 15,124,152, 20,123,141, 34,122,135, 44, + 118,117, 85,105, 84,252, 99, 75,247,107, 89,252,105, 84,252, + 87, 65,237, 30, 43,203, 69, 60,230,107, 89,252,118,117, 85, + 123,141, 34,124,162, 10,122,177, 0,119,186, 0,117,190, 0, + 117,192, 0,117,191, 0,118,188, 0,119,185, 0,119,185, 0, + 119,185, 0,120,183, 0,121,181, 0,121,181, 0,121,182, 0, + 121,181, 0,118,188, 0,116,192, 0,115,194, 0,115,194, 0, + 116,193, 0,116,192, 0,116,193, 0,114,197, 0,112,200, 0, + 112,200, 0,113,198, 0,112,200, 0,112,200, 0,113,198, 0, + 116,193, 0,120,183, 0,124,164, 9,121,125, 63, 99, 75,247, + 30, 55,222,122,135, 44,123,169, 4,119,186, 0,115,195, 0, + 112,200, 0,110,202, 0,108,205, 0,107,207, 0,106,208, 0, + 106,208, 0,106,207, 0,108,206, 0,103,211, 0,103,211, 0, + 103,212, 0,103,211, 0,105,209, 0,108,205, 0,112,199, 0, + 115,195, 0,114,197, 0,111,201, 0,109,203, 0,108,205, 0, + 109,204, 0,111,202, 0,114,197, 0,117,190, 0,120,182, 0, + 122,176, 0,123,170, 3,124,162, 10,124,149, 24,122,135, 44, + 122,130, 53,119,119, 77,117,110,109,120,122, 70,122,130, 53, + 122,135, 44,123,137, 41,124,143, 31,124,145, 29,124,143, 31, + 123,139, 37,124,154, 18,124,161, 11,124,162, 10,124,161, 11, + 124,158, 13,124,154, 18,124,150, 22,124,150, 22,124,145, 29, + 121,125, 63,102, 80,250, 30, 31,180,107, 89,252,120,122, 70, + 122,132, 48,119,119, 77,109, 92,251, 69, 60,230, 30, 49,213, + 105, 84,252,114,104,197,117,110,109,115,107,129,107, 89,252, + 117,110,109,115,107,129,109, 92,251, 94, 70,242,119,119, 77, + 124,150, 22,124,167, 6,123,174, 1,120,184, 0,114,197, 0, + 108,205, 0,104,210, 0,101,214, 0,100,215, 0,100,215, 0, + 100,215, 0, 99,215, 0, 98,216, 0, 98,217, 0, 97,217, 0, + 97,218, 0, 97,217, 0, 98,217, 0, 99,216, 0,100,215, 0, + 101,213, 0, 99,216, 0, 97,218, 0, 95,219, 0, 95,219, 0, + 96,219, 0, 98,217, 0,101,214, 0,106,208, 0,112,200, 0, + 115,194, 0,114,196, 0,115,195, 0,116,193, 0,118,188, 0, + 120,182, 0,122,177, 0,123,171, 3,124,166, 7,123,171, 3, + 122,178, 0,120,184, 0,118,189, 0,116,192, 0,115,194, 0, + 115,194, 0,116,192, 0,118,188, 0,120,183, 0,119,185, 0, + 118,189, 0,115,194, 0,112,200, 0,109,204, 0,106,208, 0, + 104,210, 0,103,211, 0,103,211, 0,105,209, 0,102,212, 0, + 101,214, 0,100,215, 0, 99,215, 0, 99,215, 0,100,215, 0, + 100,215, 0,100,215, 0,101,213, 0,106,208, 0,112,200, 0, + 118,189, 0,119,186, 0,121,180, 0,123,168, 5,123,141, 34, + 102, 80,250, 94, 70,242,118,117, 85,123,141, 34,124,154, 18, + 124,161, 11,123,170, 3,122,177, 0,121,179, 0,121,179, 0, + 122,177, 0,123,172, 2,122,175, 0,122,177, 0,122,178, 0, + 121,181, 0,121,182, 0,121,179, 0,122,177, 0,120,182, 0, + 119,186, 0,118,189, 0,118,189, 0,118,188, 0,120,183, 0, + 123,171, 3,124,152, 20,122,135, 44,121,127, 58,117,110,109, + 107, 89,252, 69, 60,230, 30, 37,192, 30, 55,222,105, 84,252, + 121,125, 63,124,154, 18,123,171, 3,120,183, 0,118,189, 0, + 115,194, 0,114,197, 0,113,198, 0,113,198, 0,114,196, 0, + 117,192, 0,118,189, 0,118,189, 0,119,187, 0,120,182, 0, + 122,176, 0,124,167, 6,124,166, 7,123,168, 5,123,169, 4, + 123,169, 4,123,168, 5,124,165, 8,124,158, 13,124,147, 26, + 123,137, 41,119,119, 77,109, 92,251,118,114, 96,118,114, 96, + 115,107,129,107, 89,252, 69, 60,230, 94, 70,242,107, 89,252, + 118,114, 96,123,141, 34,124,164, 9,122,176, 0,120,184, 0, + 119,187, 0,118,188, 0,119,187, 0,119,185, 0,120,184, 0, + 119,185, 0,120,184, 0,119,185, 0,119,185, 0,119,186, 0, + 119,185, 0,119,186, 0,116,192, 0,114,196, 0,114,197, 0, + 114,197, 0,114,197, 0,114,196, 0,116,193, 0,114,197, 0, + 112,199, 0,113,199, 0,112,199, 0,111,201, 0,111,201, 0, + 113,198, 0,116,193, 0,120,183, 0,124,164, 9,120,122, 70, + 105, 84,252,117,110,109,124,161, 11,120,183, 0,115,195, 0, + 110,203, 0,107,207, 0,105,209, 0,104,210, 0,103,212, 0, + 102,212, 0,103,212, 0,103,211, 0,105,209, 0,101,214, 0, + 99,215, 0, 98,217, 0, 98,217, 0, 99,215, 0,103,212, 0, + 108,206, 0,113,198, 0,113,198, 0,111,202, 0,109,203, 0, + 109,204, 0,110,203, 0,112,200, 0,115,195, 0,118,189, 0, + 120,183, 0,122,175, 0,124,162, 10,124,143, 31,119,119, 77, + 105, 84,252, 30, 55,222,109, 92,251,119,119, 77,123,137, 41, + 124,147, 26,124,150, 22,124,145, 29,121,127, 58,120,122, 70, + 119,119, 77,121,127, 58,124,147, 26,124,155, 16,124,157, 15, + 124,155, 16,124,152, 20,124,149, 24,124,147, 26,124,147, 26, + 124,143, 31,121,125, 63,105, 84,252, 99, 75,247,118,117, 85, + 123,141, 34,124,147, 26,123,137, 41,118,114, 96,105, 84,252, + 111, 96,248,119,119, 77,122,132, 48,123,137, 41,122,135, 44, + 118,117, 85,120,122, 70,120,122, 70,115,107,129,105, 84,252, + 107, 89,252,122,135, 44,124,157, 15,124,166, 7,121,180, 0, + 117,192, 0,112,200, 0,108,206, 0,105,209, 0,103,212, 0, + 102,213, 0,101,214, 0, 99,216, 0, 97,218, 0, 95,219, 0, + 95,220, 0, 95,220, 0, 96,219, 0, 97,218, 0, 98,216, 0, + 100,215, 0, 99,216, 0, 96,219, 0, 94,221, 0, 92,222, 0, + 92,222, 0, 93,222, 0, 94,220, 0, 98,217, 0,103,212, 0, + 109,204, 0,115,195, 0,114,197, 0,114,197, 0,114,196, 0, + 117,191, 0,119,186, 0,121,182, 0,122,178, 0,123,172, 2, + 123,171, 3,121,180, 0,119,187, 0,116,192, 0,114,196, 0, + 114,197, 0,114,196, 0,116,193, 0,118,189, 0,120,184, 0, + 121,179, 0,119,186, 0,116,192, 0,113,199, 0,109,203, 0, + 106,207, 0,105,209, 0,104,210, 0,105,209, 0,103,211, 0, + 101,213, 0,100,214, 0,100,215, 0,100,215, 0,100,215, 0, + 100,214, 0,100,214, 0,100,214, 0,101,213, 0,106,208, 0, + 112,200, 0,118,188, 0,121,182, 0,122,177, 0,124,166, 7, + 123,141, 34,120,122, 70,118,114, 96,122,132, 48,124,149, 24, + 124,157, 15,124,158, 13,124,165, 8,123,171, 3,123,174, 1, + 123,172, 2,123,171, 3,122,177, 0,121,180, 0,121,181, 0, + 120,182, 0,119,185, 0,119,186, 0,120,184, 0,121,180, 0, + 120,183, 0,119,186, 0,118,188, 0,118,189, 0,119,187, 0, + 121,182, 0,123,170, 3,124,150, 22,118,114, 96,109, 92,251, + 117,110,109,117,110,109,113,100,242,114,104,197,119,119, 77, + 122,132, 48,123,139, 37,124,157, 15,123,171, 3,121,180, 0, + 119,186, 0,118,189, 0,117,191, 0,117,191, 0,118,189, 0, + 119,187, 0,118,188, 0,118,188, 0,119,187, 0,120,184, 0, + 122,178, 0,123,169, 4,124,164, 9,124,167, 6,123,170, 3, + 123,172, 2,123,173, 1,123,172, 2,123,168, 5,124,158, 13, + 124,150, 22,123,139, 37,120,122, 70,121,127, 58,123,139, 37, + 122,135, 44,121,125, 63,114,104,197, 99, 75,247, 99, 75,247, + 111, 96,248,120,122, 70,123,141, 34,124,157, 15,123,170, 3, + 122,178, 0,121,182, 0,120,182, 0,121,182, 0,121,180, 0, + 120,184, 0,119,185, 0,119,186, 0,118,188, 0,118,189, 0, + 118,189, 0,118,188, 0,118,189, 0,115,194, 0,114,197, 0, + 112,199, 0,111,202, 0,111,202, 0,112,200, 0,114,196, 0, + 114,196, 0,113,198, 0,113,199, 0,111,201, 0,111,202, 0, + 111,201, 0,113,198, 0,116,192, 0,120,182, 0,124,164, 9, + 120,122, 70,115,107,129,124,143, 31,122,176, 0,117,192, 0, + 111,202, 0,106,208, 0,102,212, 0,101,213, 0,101,214, 0, + 101,214, 0,101,214, 0,101,213, 0,102,212, 0,103,212, 0, + 100,215, 0, 97,218, 0, 94,221, 0, 93,222, 0, 94,220, 0, + 98,217, 0,103,211, 0,109,203, 0,111,201, 0,111,201, 0, + 110,202, 0,110,202, 0,112,200, 0,114,197, 0,116,192, 0, + 119,187, 0,120,182, 0,122,177, 0,123,168, 5,124,154, 18, + 121,125, 63,118,114, 96,114,104,197,119,119, 77,122,130, 53, + 124,145, 29,124,157, 15,124,160, 12,124,155, 16,123,139, 37, + 113,100,242,105, 84,252,117,110,109,122,135, 44,124,145, 29, + 124,149, 24,124,147, 26,124,143, 31,123,139, 37,123,137, 41, + 123,141, 34,123,139, 37,120,122, 70,117,110,109,114,104,197, + 122,132, 48,124,150, 22,124,155, 16,124,145, 29,120,122, 70, + 114,104,197,121,125, 63,123,141, 34,124,152, 20,124,157, 15, + 124,154, 18,124,145, 29,124,147, 26,123,137, 41,120,122, 70, + 113,100,242,113,100,242,117,110,109,123,141, 34,124,154, 18, + 123,173, 1,119,186, 0,115,194, 0,112,200, 0,109,204, 0, + 107,207, 0,105,209, 0,103,212, 0,100,215, 0, 97,218, 0, + 95,220, 0, 94,221, 0, 94,221, 0, 95,219, 0, 98,217, 0, + 99,215, 0,100,215, 0, 97,218, 0, 94,221, 0, 92,222, 0, + 91,223, 0, 92,223, 0, 93,222, 0, 94,220, 0, 97,218, 0, + 102,212, 0,108,205, 0,114,197, 0,114,196, 0,114,196, 0, + 115,194, 0,117,191, 0,119,186, 0,120,183, 0,121,180, 0, + 122,177, 0,123,172, 2,122,178, 0,119,186, 0,116,192, 0, + 114,196, 0,114,197, 0,114,196, 0,116,193, 0,118,189, 0, + 120,184, 0,121,181, 0,119,185, 0,117,190, 0,114,197, 0, + 110,202, 0,107,207, 0,105,209, 0,105,209, 0,105,209, 0, + 103,212, 0,101,213, 0,101,214, 0,101,214, 0,101,213, 0, + 102,212, 0,103,212, 0,103,211, 0,103,212, 0,104,210, 0, + 108,206, 0,113,198, 0,119,186, 0,122,175, 0,123,169, 4, + 124,158, 13,124,147, 26,123,141, 34,122,135, 44,123,141, 34, + 124,154, 18,124,158, 13,124,158, 13,124,155, 16,124,164, 9, + 124,166, 7,124,166, 7,122,175, 0,121,179, 0,120,182, 0, + 120,183, 0,120,184, 0,119,187, 0,118,188, 0,119,186, 0, + 121,181, 0,121,181, 0,120,182, 0,120,184, 0,120,183, 0, + 121,182, 0,122,175, 0,124,162, 10,123,139, 37,117,110,109, + 111, 96,248,118,117, 85,121,125, 63,121,125, 63,123,139, 37, + 124,152, 20,124,160, 12,124,164, 9,124,162, 10,124,166, 7, + 123,174, 1,122,178, 0,121,181, 0,121,182, 0,121,180, 0, + 120,184, 0,119,186, 0,119,187, 0,119,186, 0,120,184, 0, + 121,179, 0,123,171, 3,124,160, 12,124,160, 12,124,162, 10, + 124,166, 7,123,169, 4,123,171, 3,123,170, 3,124,166, 7, + 124,157, 15,124,152, 20,124,145, 29,122,135, 44,124,150, 22, + 124,155, 16,124,150, 22,123,137, 41,118,114, 96,113,100,242, + 102, 80,250,109, 92,251,119,119, 77,123,141, 34,124,154, 18, + 124,160, 12,123,168, 5,123,172, 2,123,174, 1,123,174, 1, + 121,181, 0,120,184, 0,120,184, 0,119,187, 0,117,190, 0, + 117,192, 0,117,192, 0,117,190, 0,117,190, 0,115,194, 0, + 113,198, 0,110,203, 0,108,205, 0,108,205, 0,110,203, 0, + 112,199, 0,113,199, 0,112,199, 0,111,201, 0,110,202, 0, + 110,202, 0,111,201, 0,114,197, 0,117,191, 0,121,180, 0, + 124,160, 12,120,122, 70,120,122, 70,124,160, 12,120,184, 0, + 114,197, 0,108,206, 0,103,212, 0,100,214, 0,100,215, 0, + 100,215, 0, 98,217, 0, 97,217, 0, 99,216, 0,102,213, 0, + 102,212, 0,100,215, 0, 95,220, 0, 91,223, 0, 89,225, 0, + 90,224, 0, 93,221, 0, 99,216, 0,105,209, 0,108,206, 0, + 109,203, 0,112,200, 0,112,199, 0,114,197, 0,116,193, 0, + 117,190, 0,119,187, 0,121,181, 0,122,178, 0,123,172, 2, + 124,165, 8,123,169, 4,123,168, 5,124,161, 11,124,149, 24, + 124,155, 16,124,161, 11,124,165, 8,124,166, 7,124,162, 10, + 124,149, 24,118,114, 96, 30, 37,192,105, 84,252,118,117, 85, + 122,130, 53,122,135, 44,122,132, 48,121,127, 58,120,122, 70, + 120,122, 70,121,127, 58,122,130, 53,119,119, 77,120,122, 70, + 119,119, 77,123,139, 37,124,154, 18,124,157, 15,124,145, 29, + 120,122, 70,121,125, 63,124,143, 31,124,158, 13,124,166, 7, + 123,170, 3,123,168, 5,124,164, 9,124,165, 8,124,157, 15, + 123,137, 41,118,114, 96,117,110,109,115,107,129,118,117, 85, + 122,135, 44,124,165, 8,121,179, 0,118,188, 0,116,193, 0, + 114,197, 0,111,201, 0,109,204, 0,106,208, 0,102,212, 0, + 98,217, 0, 95,220, 0, 94,221, 0, 94,220, 0, 97,218, 0, + 99,215, 0,101,214, 0, 99,216, 0, 96,219, 0, 94,221, 0, + 93,222, 0, 93,222, 0, 94,221, 0, 95,220, 0, 97,218, 0, + 99,215, 0,103,211, 0,108,205, 0,114,197, 0,116,193, 0, + 117,192, 0,118,189, 0,119,186, 0,121,182, 0,121,180, 0, + 122,178, 0,122,178, 0,122,176, 0,123,172, 2,121,182, 0, + 118,189, 0,116,193, 0,115,194, 0,115,194, 0,117,191, 0, + 119,187, 0,120,184, 0,119,185, 0,120,184, 0,118,189, 0, + 114,196, 0,110,202, 0,108,206, 0,106,208, 0,106,208, 0, + 106,208, 0,103,211, 0,102,212, 0,102,212, 0,103,211, 0, + 105,209, 0,106,207, 0,107,206, 0,108,205, 0,107,206, 0, + 108,205, 0,111,202, 0,115,194, 0,120,183, 0,124,166, 7, + 124,158, 13,124,157, 15,124,152, 20,124,145, 29,123,141, 34, + 124,143, 31,124,155, 16,124,161, 11,124,158, 13,124,149, 24, + 124,152, 20,124,154, 18,123,168, 5,122,177, 0,121,181, 0, + 120,183, 0,119,186, 0,118,189, 0,118,188, 0,118,189, 0, + 118,188, 0,120,183, 0,122,175, 0,123,174, 1,123,173, 1, + 123,171, 3,123,168, 5,124,160, 12,124,143, 31,122,130, 53, + 121,127, 58,120,122, 70,120,122, 70,122,132, 48,124,145, 29, + 124,158, 13,123,168, 5,123,173, 1,122,175, 0,123,172, 2, + 124,164, 9,124,162, 10,124,166, 7,124,167, 6,123,171, 3, + 121,180, 0,120,184, 0,119,186, 0,120,184, 0,121,182, 0, + 122,178, 0,123,172, 2,124,161, 11,124,147, 26,124,157, 15, + 124,161, 11,124,158, 13,124,161, 11,124,165, 8,124,165, 8, + 124,160, 12,124,158, 13,124,157, 15,124,152, 20,124,155, 16, + 124,165, 8,124,166, 7,124,160, 12,124,145, 29,124,147, 26, + 124,143, 31,121,127, 58,117,110,109,115,107,129,122,132, 48, + 124,145, 29,124,150, 22,124,150, 22,124,158, 13,124,162, 10, + 123,171, 3,121,180, 0,120,184, 0,120,182, 0,118,189, 0, + 116,193, 0,115,194, 0,115,194, 0,117,192, 0,118,189, 0, + 116,193, 0,111,201, 0,108,205, 0,107,207, 0,107,207, 0, + 108,205, 0,111,201, 0,112,200, 0,111,201, 0,111,202, 0, + 110,202, 0,111,202, 0,112,200, 0,115,195, 0,118,188, 0, + 122,176, 0,124,152, 20,121,125, 63,121,127, 58,124,167, 6, + 118,188, 0,112,200, 0,106,207, 0,102,213, 0, 99,215, 0, + 99,216, 0, 95,220, 0, 91,223, 0, 91,224, 0, 92,222, 0, + 97,218, 0,102,212, 0,101,214, 0, 95,219, 0, 91,224, 0, + 88,226, 0, 87,227, 0, 90,224, 0, 95,220, 0,101,213, 0, + 105,209, 0,107,207, 0,110,202, 0,114,196, 0,116,193, 0, + 117,192, 0,117,191, 0,119,187, 0,122,178, 0,122,177, 0, + 121,180, 0,119,186, 0,118,189, 0,118,188, 0,120,184, 0, + 122,176, 0,123,169, 4,123,174, 1,122,178, 0,122,177, 0, + 123,171, 3,124,155, 16,121,125, 63, 30, 55,222, 30, 37,192, + 107, 89,252,115,107,129,118,114, 96,117,110,109,115,107,129, + 117,110,109,114,104,197,118,117, 85,120,122, 70,119,119, 77, + 121,127, 58,121,127, 58,124,143, 31,124,154, 18,124,154, 18, + 123,141, 34,121,125, 63,123,141, 34,124,158, 13,123,169, 4, + 122,177, 0,121,180, 0,121,179, 0,122,175, 0,122,176, 0, + 123,170, 3,124,155, 16,121,125, 63,119,119, 77,118,117, 85, + 113,100,242,118,114, 96,124,152, 20,123,170, 3,121,179, 0, + 119,186, 0,118,189, 0,115,195, 0,112,199, 0,110,203, 0, + 105,209, 0,100,214, 0, 97,218, 0, 95,219, 0, 96,219, 0, + 98,217, 0,101,214, 0,103,212, 0, 99,215, 0, 97,218, 0, + 95,220, 0, 95,220, 0, 96,219, 0, 98,217, 0,100,215, 0, + 102,213, 0,104,210, 0,107,207, 0,110,202, 0,114,196, 0, + 118,188, 0,120,184, 0,121,181, 0,122,175, 0,123,171, 3, + 123,171, 3,123,173, 1,122,175, 0,122,176, 0,122,175, 0, + 123,173, 1,121,182, 0,119,187, 0,118,189, 0,117,190, 0, + 118,188, 0,119,185, 0,119,185, 0,119,186, 0,120,183, 0, + 119,187, 0,114,196, 0,110,202, 0,107,206, 0,106,208, 0, + 106,208, 0,107,207, 0,105,209, 0,105,209, 0,106,208, 0, + 107,207, 0,109,204, 0,111,201, 0,113,199, 0,113,198, 0, + 113,198, 0,113,199, 0,114,196, 0,118,189, 0,122,178, 0, + 124,160, 12,124,155, 16,124,155, 16,124,150, 22,124,143, 31, + 123,137, 41,123,141, 34,124,155, 16,124,160, 12,124,158, 13, + 124,149, 24,123,137, 41,124,155, 16,123,170, 3,122,178, 0, + 121,182, 0,119,185, 0,117,190, 0,117,192, 0,118,189, 0, + 118,189, 0,118,188, 0,120,184, 0,122,177, 0,124,164, 9, + 124,152, 20,124,145, 29,123,137, 41,120,122, 70,120,122, 70, + 122,132, 48,123,139, 37,123,139, 37,123,137, 41,123,139, 37, + 124,157, 15,123,168, 5,122,176, 0,121,181, 0,121,181, 0, + 122,177, 0,124,167, 6,124,149, 24,124,145, 29,124,155, 16, + 123,171, 3,121,179, 0,120,183, 0,120,183, 0,121,180, 0, + 122,176, 0,123,170, 3,124,162, 10,124,154, 18,124,155, 16, + 124,164, 9,124,167, 6,124,165, 8,124,155, 16,124,152, 20, + 124,154, 18,124,158, 13,124,164, 9,124,165, 8,124,164, 9, + 124,167, 6,123,173, 1,123,173, 1,124,167, 6,123,170, 3, + 123,172, 2,123,169, 4,124,161, 11,124,143, 31,118,117, 85, + 119,119, 77,122,135, 44,123,139, 37,123,139, 37,123,137, 41, + 124,147, 26,124,167, 6,122,177, 0,121,181, 0,120,184, 0, + 117,191, 0,114,196, 0,113,198, 0,114,197, 0,115,194, 0, + 117,190, 0,116,193, 0,111,201, 0,108,206, 0,106,207, 0, + 107,207, 0,109,204, 0,111,201, 0,111,201, 0,111,201, 0, + 111,202, 0,111,202, 0,112,200, 0,114,197, 0,117,192, 0, + 120,183, 0,123,168, 5,123,137, 41,120,122, 70,121,125, 63, + 123,168, 5,118,189, 0,112,200, 0,106,208, 0,102,213, 0, + 100,215, 0, 95,219, 0, 89,225, 0, 85,228, 0, 85,229, 0, + 87,227, 0, 92,222, 0, 98,216, 0,102,212, 0, 97,218, 0, + 91,223, 0, 87,227, 0, 86,228, 0, 88,226, 0, 92,222, 0, + 98,216, 0,104,210, 0,105,209, 0,108,205, 0,112,200, 0, + 115,194, 0,116,192, 0,117,191, 0,119,186, 0,122,177, 0, + 120,184, 0,117,191, 0,114,196, 0,113,199, 0,113,198, 0, + 115,194, 0,118,188, 0,122,178, 0,120,183, 0,119,185, 0, + 119,185, 0,121,180, 0,123,169, 4,124,145, 29,109, 92,251, + 30, 5,128, 69, 60,230,102, 80,250,107, 89,252,113,100,242, + 119,119, 77,121,125, 63,121,125, 63,117,110,109,120,122, 70, + 120,122, 70,121,127, 58,122,132, 48,124,143, 31,124,150, 22, + 124,149, 24,122,132, 48,124,154, 18,124,165, 8,123,170, 3, + 122,178, 0,120,184, 0,118,188, 0,118,188, 0,120,182, 0, + 120,183, 0,122,178, 0,124,167, 6,124,145, 29,121,127, 58, + 120,122, 70,117,110,109,102, 80,250,123,137, 41,124,160, 12, + 123,170, 3,122,178, 0,119,186, 0,116,193, 0,114,197, 0, + 113,198, 0,108,205, 0,103,211, 0,100,215, 0, 98,217, 0, + 98,217, 0,100,214, 0,102,212, 0,105,209, 0,102,212, 0, + 100,215, 0, 99,216, 0, 99,215, 0,101,214, 0,103,211, 0, + 106,208, 0,107,206, 0,109,204, 0,111,201, 0,114,197, 0, + 117,192, 0,119,186, 0,122,177, 0,124,167, 6,124,155, 16, + 124,150, 22,124,152, 20,124,160, 12,124,166, 7,123,170, 3, + 123,173, 1,123,172, 2,123,171, 3,121,179, 0,120,184, 0, + 119,185, 0,120,184, 0,120,183, 0,121,181, 0,121,181, 0, + 122,178, 0,118,189, 0,113,198, 0,109,204, 0,106,208, 0, + 105,209, 0,105,209, 0,106,207, 0,108,205, 0,108,205, 0, + 109,204, 0,110,202, 0,111,201, 0,112,200, 0,112,200, 0, + 114,197, 0,117,191, 0,117,191, 0,118,189, 0,120,184, 0, + 122,178, 0,123,171, 3,124,162, 10,124,150, 22,123,141, 34, + 122,130, 53,121,125, 63,122,135, 44,124,150, 22,124,158, 13, + 124,157, 15,124,147, 26,121,125, 63,124,158, 13,123,172, 2, + 121,180, 0,120,184, 0,119,186, 0,117,190, 0,117,191, 0, + 118,188, 0,118,189, 0,118,188, 0,120,184, 0,122,177, 0, + 124,164, 9,123,141, 34,115,107,129, 94, 70,242,107, 89,252, + 117,110,109,122,132, 48,124,143, 31,124,150, 22,124,155, 16, + 124,160, 12,124,161, 11,123,171, 3,122,178, 0,120,183, 0, + 120,183, 0,122,178, 0,123,169, 4,124,150, 22,119,119, 77, + 124,152, 20,123,169, 4,122,177, 0,121,179, 0,122,178, 0, + 123,173, 1,124,166, 7,124,160, 12,124,161, 11,124,164, 9, + 124,166, 7,124,166, 7,124,167, 6,124,165, 8,124,154, 18, + 122,135, 44,124,154, 18,124,166, 7,123,172, 2,122,175, 0, + 122,177, 0,122,177, 0,122,178, 0,122,178, 0,121,182, 0, + 119,185, 0,119,186, 0,119,185, 0,121,179, 0,123,168, 5, + 124,145, 29,114,104,197,120,122, 70,122,130, 53,122,132, 48, + 121,125, 63,122,135, 44,124,157, 15,123,169, 4,122,175, 0, + 119,186, 0,115,194, 0,112,199, 0,111,202, 0,111,201, 0, + 113,199, 0,115,194, 0,117,190, 0,113,198, 0,110,203, 0, + 109,204, 0,109,204, 0,111,202, 0,112,200, 0,112,199, 0, + 112,199, 0,112,200, 0,112,199, 0,114,197, 0,116,193, 0, + 119,187, 0,122,176, 0,124,155, 16,118,114, 96,115,107,129, + 118,114, 96,124,166, 7,118,188, 0,112,200, 0,106,208, 0, + 102,212, 0,100,215, 0, 92,222, 0, 86,228, 0, 82,231, 0, + 82,231, 0, 84,229, 0, 89,225, 0, 96,219, 0,101,213, 0, + 98,216, 0, 93,222, 0, 89,226, 0, 87,227, 0, 88,226, 0, + 91,223, 0, 96,219, 0,102,213, 0,104,210, 0,107,207, 0, + 110,202, 0,112,200, 0,114,197, 0,115,194, 0,117,191, 0, + 119,186, 0,117,191, 0,113,198, 0,110,202, 0,109,204, 0, + 110,203, 0,112,199, 0,116,193, 0,119,185, 0,118,188, 0, + 117,191, 0,117,191, 0,119,187, 0,122,178, 0,124,161, 11, + 121,127, 58, 87, 65,237, 69, 60,230, 94, 70,242,107, 89,252, + 118,114, 96,121,127, 58,122,135, 44,122,135, 44,121,125, 63, + 122,132, 48,123,137, 41,123,137, 41,123,139, 37,123,141, 34, + 124,147, 26,124,145, 29,124,158, 13,123,170, 3,122,177, 0, + 121,181, 0,120,184, 0,117,190, 0,116,193, 0,116,192, 0, + 118,189, 0,118,189, 0,120,184, 0,122,175, 0,124,158, 13, + 123,141, 34,120,122, 70,117,110,109,107, 89,252,120,122, 70, + 124,149, 24,124,164, 9,123,171, 3,120,182, 0,118,189, 0, + 116,193, 0,115,194, 0,111,201, 0,107,207, 0,103,211, 0, + 100,215, 0, 97,217, 0, 97,217, 0,100,215, 0,102,212, 0, + 101,214, 0,101,214, 0,102,212, 0,104,210, 0,106,208, 0, + 106,207, 0,106,207, 0,108,205, 0,111,201, 0,115,195, 0, + 117,191, 0,119,186, 0,120,184, 0,121,181, 0,122,178, 0, + 123,173, 1,124,164, 9,124,147, 26,123,141, 34,124,147, 26, + 124,157, 15,124,162, 10,124,165, 8,124,165, 8,123,171, 3, + 122,178, 0,121,181, 0,121,182, 0,121,181, 0,121,179, 0, + 122,178, 0,121,180, 0,117,191, 0,112,199, 0,108,205, 0, + 106,208, 0,104,210, 0,105,209, 0,106,208, 0,108,206, 0, + 109,204, 0,110,203, 0,110,202, 0,108,205, 0,107,207, 0, + 107,207, 0,109,204, 0,113,198, 0,117,191, 0,119,187, 0, + 119,186, 0,120,182, 0,122,178, 0,123,172, 2,124,165, 8, + 124,157, 15,124,143, 31,118,117, 85,121,125, 63,124,145, 29, + 124,154, 18,124,152, 20,124,143, 31,122,135, 44,124,162, 10, + 122,175, 0,121,182, 0,120,184, 0,119,186, 0,119,186, 0, + 119,186, 0,118,188, 0,118,188, 0,119,186, 0,121,182, 0, + 123,173, 1,124,157, 15,121,127, 58,117,110,109,118,114, 96, + 118,117, 85,118,117, 85,122,135, 44,124,150, 22,124,165, 8, + 123,173, 1,122,178, 0,122,178, 0,122,175, 0,122,178, 0, + 121,182, 0,121,182, 0,122,177, 0,124,167, 6,124,149, 24, + 123,139, 37,124,149, 24,124,165, 8,123,172, 2,123,174, 1, + 123,171, 3,124,166, 7,124,161, 11,124,165, 8,124,167, 6, + 123,170, 3,123,172, 2,123,173, 1,123,171, 3,124,166, 7, + 124,160, 12,124,154, 18,124,165, 8,123,174, 1,121,181, 0, + 120,184, 0,119,186, 0,118,188, 0,118,188, 0,118,189, 0, + 116,192, 0,115,194, 0,114,196, 0,115,194, 0,118,189, 0, + 121,182, 0,124,167, 6,124,143, 31,121,125, 63,121,125, 63, + 122,130, 53,122,132, 48,121,127, 58,124,149, 24,124,165, 8, + 122,178, 0,118,188, 0,114,196, 0,111,202, 0,109,204, 0, + 109,204, 0,110,202, 0,112,199, 0,114,196, 0,116,193, 0, + 113,198, 0,112,200, 0,112,199, 0,112,199, 0,111,201, 0, + 110,202, 0,110,202, 0,112,200, 0,114,197, 0,116,193, 0, + 118,189, 0,121,182, 0,123,171, 3,124,155, 16,122,132, 48, + 120,122, 70,115,107,129,124,162, 10,119,186, 0,113,199, 0, + 107,207, 0,103,211, 0, 98,217, 0, 91,223, 0, 85,229, 0, + 81,232, 0, 81,232, 0, 83,230, 0, 89,226, 0, 95,220, 0, + 101,213, 0,100,214, 0, 95,220, 0, 91,224, 0, 88,226, 0, + 89,226, 0, 91,223, 0, 95,220, 0,100,215, 0,103,211, 0, + 105,209, 0,108,205, 0,110,202, 0,111,201, 0,113,198, 0, + 115,194, 0,117,192, 0,114,197, 0,110,202, 0,108,206, 0, + 107,207, 0,108,206, 0,111,202, 0,115,195, 0,118,189, 0, + 117,192, 0,115,194, 0,115,194, 0,117,191, 0,120,184, 0, + 123,172, 2,124,150, 22,118,114, 96,113,100,242,113,100,242, + 114,104,197,119,119, 77,121,127, 58,122,132, 48,122,132, 48, + 121,127, 58,124,143, 31,124,149, 24,124,150, 22,124,150, 22, + 124,154, 18,124,154, 18,124,158, 13,123,168, 5,122,178, 0, + 120,183, 0,119,187, 0,118,189, 0,116,193, 0,115,194, 0, + 115,194, 0,115,195, 0,115,194, 0,117,190, 0,121,182, 0, + 123,168, 5,124,149, 24,119,119, 77,111, 96,248,113,100,242, + 118,117, 85,124,143, 31,124,158, 13,124,166, 7,122,175, 0, + 120,184, 0,118,188, 0,118,189, 0,114,197, 0,108,205, 0, + 102,212, 0, 98,217, 0, 95,219, 0, 95,219, 0, 97,217, 0, + 98,216, 0, 97,218, 0, 97,217, 0, 99,215, 0,102,212, 0, + 106,208, 0,106,208, 0,106,208, 0,108,206, 0,110,202, 0, + 114,197, 0,117,190, 0,118,189, 0,118,189, 0,118,189, 0, + 119,187, 0,120,184, 0,122,178, 0,124,165, 8,124,143, 31, + 122,135, 44,121,127, 58,123,141, 34,124,147, 26,124,149, 24, + 124,164, 9,123,172, 2,122,177, 0,122,178, 0,121,179, 0, + 122,178, 0,122,177, 0,122,178, 0,118,188, 0,114,196, 0, + 110,202, 0,108,205, 0,106,207, 0,106,207, 0,107,207, 0, + 108,205, 0,109,203, 0,110,202, 0,107,207, 0,104,210, 0, + 102,212, 0,102,212, 0,104,210, 0,108,206, 0,113,199, 0, + 117,191, 0,119,187, 0,119,186, 0,120,184, 0,121,179, 0, + 123,173, 1,124,166, 7,124,154, 18,122,130, 53,121,127, 58, + 124,143, 31,124,150, 22,124,149, 24,123,139, 37,124,145, 29, + 124,166, 7,122,176, 0,121,181, 0,120,184, 0,120,184, 0, + 119,185, 0,119,185, 0,119,186, 0,119,185, 0,120,182, 0, + 122,175, 0,124,162, 10,123,137, 41,122,135, 44,122,135, 44, + 123,137, 41,123,139, 37,123,137, 41,124,143, 31,124,165, 8, + 122,178, 0,120,184, 0,118,189, 0,117,190, 0,118,188, 0, + 120,183, 0,122,178, 0,122,178, 0,123,173, 1,124,162, 10, + 124,157, 15,124,157, 15,124,158, 13,124,162, 10,123,169, 4, + 123,171, 3,123,168, 5,124,162, 10,124,160, 12,124,166, 7, + 123,168, 5,123,171, 3,123,174, 1,122,175, 0,123,174, 1, + 123,172, 2,123,169, 4,124,167, 6,123,173, 1,121,182, 0, + 119,186, 0,117,190, 0,116,193, 0,115,194, 0,115,195, 0, + 114,196, 0,113,198, 0,112,200, 0,111,201, 0,112,200, 0, + 114,197, 0,117,190, 0,121,180, 0,124,166, 7,124,145, 29, + 122,132, 48,122,135, 44,123,139, 37,123,141, 34,124,147, 26, + 124,165, 8,122,178, 0,118,189, 0,114,196, 0,111,202, 0, + 109,204, 0,108,205, 0,109,203, 0,111,202, 0,112,199, 0, + 113,198, 0,114,197, 0,113,198, 0,112,199, 0,111,201, 0, + 110,202, 0,110,203, 0,110,202, 0,111,201, 0,113,198, 0, + 116,193, 0,118,188, 0,121,182, 0,123,171, 3,124,152, 20, + 124,143, 31,122,135, 44,119,119, 77,124,164, 9,119,185, 0, + 114,197, 0,109,204, 0,103,211, 0, 97,218, 0, 90,224, 0, + 85,229, 0, 82,231, 0, 82,231, 0, 85,229, 0, 90,224, 0, + 96,219, 0,101,214, 0,101,214, 0, 97,217, 0, 93,221, 0, + 91,224, 0, 90,224, 0, 92,223, 0, 95,220, 0, 99,215, 0, + 102,212, 0,104,210, 0,107,207, 0,109,204, 0,110,202, 0, + 112,200, 0,114,196, 0,114,196, 0,112,200, 0,108,205, 0, + 106,208, 0,105,209, 0,107,207, 0,110,202, 0,115,195, 0, + 117,191, 0,116,193, 0,115,195, 0,115,195, 0,116,192, 0, + 119,187, 0,122,177, 0,124,161, 11,123,139, 37,121,125, 63, + 119,119, 77,117,110,109,119,119, 77,120,122, 70,120,122, 70, + 120,122, 70,123,139, 37,124,150, 22,124,157, 15,124,161, 11, + 124,164, 9,124,165, 8,124,164, 9,124,166, 7,123,173, 1, + 121,180, 0,119,186, 0,118,189, 0,116,193, 0,114,196, 0, + 113,198, 0,112,199, 0,112,200, 0,113,198, 0,116,193, 0, + 119,186, 0,122,175, 0,124,157, 15,122,130, 53,113,100,242, + 117,110,109,120,122, 70,123,137, 41,124,154, 18,124,162, 10, + 123,168, 5,122,176, 0,121,181, 0,119,187, 0,113,199, 0, + 106,208, 0,100,214, 0, 96,219, 0, 94,221, 0, 94,221, 0, + 95,219, 0, 93,221, 0, 92,222, 0, 93,221, 0, 95,219, 0, + 99,216, 0,103,212, 0,103,212, 0,103,211, 0,105,209, 0, + 107,206, 0,111,201, 0,116,193, 0,116,192, 0,116,193, 0, + 115,194, 0,116,193, 0,117,191, 0,120,184, 0,123,174, 1, + 124,158, 13,122,135, 44,120,122, 70,115,107,129,118,114, 96, + 123,137, 41,124,157, 15,124,167, 6,123,173, 1,122,176, 0, + 122,176, 0,122,175, 0,123,173, 1,123,172, 2,120,182, 0, + 117,190, 0,114,196, 0,112,200, 0,110,202, 0,110,203, 0, + 110,203, 0,110,202, 0,111,202, 0,108,205, 0,104,210, 0, + 101,214, 0, 99,216, 0, 98,217, 0,100,215, 0,103,211, 0, + 108,205, 0,113,198, 0,118,189, 0,118,189, 0,119,187, 0, + 120,184, 0,122,178, 0,123,170, 3,124,158, 13,123,141, 34, + 124,143, 31,124,147, 26,124,150, 22,124,152, 20,124,155, 16, + 124,157, 15,124,167, 6,123,174, 1,122,178, 0,121,180, 0, + 121,180, 0,121,180, 0,121,180, 0,121,181, 0,121,179, 0, + 123,174, 1,124,164, 9,124,149, 24,124,149, 24,124,149, 24, + 124,147, 26,124,149, 24,124,150, 22,124,158, 13,124,164, 9, + 122,175, 0,119,185, 0,117,192, 0,114,196, 0,113,198, 0, + 114,197, 0,116,193, 0,118,188, 0,120,183, 0,122,178, 0, + 123,173, 1,123,170, 3,123,168, 5,124,167, 6,124,165, 8, + 124,166, 7,123,168, 5,124,166, 7,124,161, 11,124,154, 18, + 124,162, 10,124,166, 7,123,170, 3,123,173, 1,123,174, 1, + 122,175, 0,122,175, 0,122,175, 0,122,176, 0,121,181, 0, + 119,186, 0,117,191, 0,115,194, 0,114,197, 0,113,198, 0, + 112,199, 0,112,200, 0,111,201, 0,110,203, 0,109,204, 0, + 109,203, 0,111,201, 0,114,196, 0,118,188, 0,122,178, 0, + 124,161, 11,124,155, 16,124,145, 29,124,147, 26,124,150, 22, + 124,149, 24,124,162, 10,122,176, 0,119,186, 0,116,193, 0, + 113,198, 0,111,201, 0,110,202, 0,110,202, 0,111,201, 0, + 112,200, 0,112,200, 0,112,200, 0,112,200, 0,111,201, 0, + 111,201, 0,111,202, 0,111,202, 0,111,201, 0,112,199, 0, + 114,197, 0,116,193, 0,118,188, 0,121,180, 0,124,167, 6, + 124,154, 18,124,149, 24,123,139, 37,122,130, 53,124,166, 7, + 119,185, 0,114,196, 0,110,202, 0,103,211, 0, 96,219, 0, + 91,224, 0, 87,227, 0, 85,229, 0, 85,228, 0, 89,226, 0, + 94,221, 0, 99,215, 0,101,213, 0,100,214, 0,100,215, 0, + 96,219, 0, 94,221, 0, 92,222, 0, 93,222, 0, 95,219, 0, + 99,215, 0,102,212, 0,103,211, 0,106,208, 0,108,205, 0, + 110,202, 0,111,201, 0,114,197, 0,113,198, 0,111,202, 0, + 108,206, 0,106,208, 0,105,209, 0,107,207, 0,111,201, 0, + 115,194, 0,117,191, 0,116,193, 0,115,194, 0,115,194, 0, + 117,192, 0,119,186, 0,122,178, 0,124,165, 8,124,147, 26, + 122,135, 44,121,125, 63,117,110,109,118,114, 96,118,114, 96, + 117,110,109,121,127, 58,124,145, 29,124,155, 16,124,166, 7, + 123,171, 3,122,175, 0,122,175, 0,123,173, 1,123,171, 3, + 122,175, 0,121,181, 0,119,186, 0,117,191, 0,115,195, 0, + 113,199, 0,111,202, 0,110,203, 0,110,203, 0,111,201, 0, + 114,196, 0,118,189, 0,122,178, 0,124,165, 8,124,145, 29, + 119,119, 77,118,114, 96,121,125, 63,122,132, 48,124,149, 24, + 124,157, 15,124,164, 9,123,169, 4,122,178, 0,117,191, 0, + 111,202, 0,104,210, 0, 99,216, 0, 95,220, 0, 93,221, 0, + 93,221, 0, 91,223, 0, 89,226, 0, 89,226, 0, 89,225, 0, + 92,223, 0, 95,219, 0,100,214, 0,102,213, 0,102,212, 0, + 103,212, 0,106,208, 0,110,203, 0,114,196, 0,116,193, 0, + 115,195, 0,114,196, 0,114,196, 0,116,193, 0,118,188, 0, + 122,178, 0,124,164, 9,124,145, 29,120,122, 70,114,104,197, + 107, 89,252,121,125, 63,124,147, 26,124,161, 11,123,168, 5, + 123,172, 2,123,172, 2,123,171, 3,123,169, 4,124,166, 7, + 123,171, 3,121,181, 0,119,186, 0,117,191, 0,115,194, 0, + 114,197, 0,113,198, 0,113,198, 0,112,200, 0,107,206, 0, + 103,211, 0, 99,215, 0, 97,218, 0, 96,219, 0, 97,217, 0, + 101,214, 0,105,209, 0,111,202, 0,116,193, 0,117,191, 0, + 117,190, 0,119,187, 0,121,181, 0,123,171, 3,124,157, 15, + 124,152, 20,124,155, 16,124,158, 13,124,162, 10,124,166, 7, + 123,168, 5,123,168, 5,124,165, 8,123,170, 3,123,171, 3, + 123,172, 2,123,172, 2,123,172, 2,123,172, 2,123,172, 2, + 123,169, 4,124,160, 12,124,158, 13,124,160, 12,124,157, 15, + 124,155, 16,124,154, 18,124,157, 15,124,167, 6,123,174, 1, + 122,178, 0,121,182, 0,117,190, 0,114,196, 0,111,201, 0, + 110,202, 0,110,202, 0,112,200, 0,114,196, 0,117,191, 0, + 119,186, 0,121,182, 0,122,177, 0,123,174, 1,123,172, 2, + 124,167, 6,124,161, 11,124,164, 9,124,164, 9,124,160, 12, + 124,157, 15,124,157, 15,124,162, 10,124,166, 7,123,169, 4, + 123,171, 3,123,173, 1,122,176, 0,122,178, 0,120,182, 0, + 119,186, 0,117,191, 0,115,194, 0,114,197, 0,112,199, 0, + 111,201, 0,111,202, 0,110,202, 0,110,202, 0,109,204, 0, + 108,205, 0,108,205, 0,110,203, 0,112,199, 0,116,193, 0, + 119,185, 0,123,173, 1,123,170, 3,124,166, 7,124,158, 13, + 124,157, 15,124,154, 18,124,150, 22,124,167, 6,122,178, 0, + 119,186, 0,117,190, 0,116,193, 0,114,196, 0,114,197, 0, + 113,198, 0,112,199, 0,112,200, 0,112,200, 0,112,200, 0, + 112,200, 0,112,200, 0,112,199, 0,113,199, 0,113,198, 0, + 114,197, 0,115,194, 0,117,191, 0,119,186, 0,122,177, 0, + 124,164, 9,124,157, 15,124,150, 22,124,145, 29,124,147, 26, + 123,169, 4,119,186, 0,115,194, 0,111,202, 0,104,210, 0, + 98,217, 0, 93,222, 0, 90,224, 0, 89,225, 0, 91,223, 0, + 94,220, 0, 99,216, 0,103,211, 0,102,212, 0,100,214, 0, + 100,214, 0, 99,215, 0, 97,218, 0, 95,220, 0, 95,220, 0, + 97,218, 0,100,214, 0,102,213, 0,103,211, 0,105,209, 0, + 108,205, 0,110,202, 0,111,201, 0,113,198, 0,113,198, 0, + 110,202, 0,108,206, 0,106,208, 0,106,208, 0,108,205, 0, + 112,200, 0,117,192, 0,118,189, 0,117,191, 0,117,192, 0, + 117,191, 0,118,188, 0,120,182, 0,123,173, 1,124,161, 11, + 124,147, 26,122,135, 44,120,122, 70,113,100,242,113,100,242, + 111, 96,248,113,100,242,122,130, 53,124,154, 18,124,167, 6, + 122,175, 0,121,181, 0,120,183, 0,120,183, 0,121,182, 0, + 122,178, 0,121,179, 0,119,186, 0,117,190, 0,116,193, 0, + 114,196, 0,111,201, 0,109,203, 0,108,205, 0,108,205, 0, + 110,202, 0,114,197, 0,118,189, 0,121,180, 0,124,167, 6, + 124,150, 22,122,130, 53,117,110,109,119,119, 77,121,125, 63, + 123,141, 34,124,150, 22,124,158, 13,123,168, 5,121,181, 0, + 116,193, 0,109,203, 0,103,211, 0, 98,217, 0, 94,220, 0, + 92,222, 0, 92,222, 0, 87,227, 0, 85,229, 0, 85,228, 0, + 87,227, 0, 89,225, 0, 92,222, 0, 97,217, 0,102,212, 0, + 102,212, 0,103,211, 0,105,209, 0,109,204, 0,114,197, 0, + 116,193, 0,115,195, 0,114,196, 0,114,196, 0,116,192, 0, + 119,186, 0,122,177, 0,124,164, 9,124,147, 26,122,130, 53, + 118,114, 96,113,100,242,115,107,129,122,135, 44,124,152, 20, + 124,162, 10,124,167, 6,123,168, 5,124,167, 6,124,165, 8, + 124,167, 6,123,169, 4,121,181, 0,118,188, 0,117,192, 0, + 116,193, 0,116,192, 0,117,191, 0,116,193, 0,113,198, 0, + 108,205, 0,103,211, 0,100,215, 0, 97,218, 0, 96,219, 0, + 97,217, 0,100,214, 0,105,209, 0,110,202, 0,115,194, 0, + 116,193, 0,117,192, 0,118,188, 0,121,181, 0,123,169, 4, + 124,155, 16,124,160, 12,124,164, 9,124,167, 6,123,171, 3, + 123,174, 1,122,176, 0,122,176, 0,123,170, 3,124,162, 10, + 124,161, 11,124,164, 9,124,164, 9,124,157, 15,124,157, 15, + 124,157, 15,124,161, 11,124,165, 8,124,166, 7,124,165, 8, + 124,162, 10,124,158, 13,124,157, 15,124,167, 6,122,177, 0, + 120,184, 0,118,189, 0,117,191, 0,117,192, 0,113,198, 0, + 110,202, 0,108,205, 0,108,205, 0,109,203, 0,112,200, 0, + 114,196, 0,117,191, 0,119,185, 0,121,179, 0,122,175, 0, + 123,171, 3,124,166, 7,124,157, 15,124,157, 15,124,158, 13, + 124,158, 13,124,158, 13,124,160, 12,124,164, 9,123,168, 5, + 123,173, 1,122,177, 0,121,180, 0,120,183, 0,119,185, 0, + 118,188, 0,117,192, 0,114,196, 0,112,200, 0,110,202, 0, + 109,204, 0,108,205, 0,108,206, 0,108,206, 0,109,204, 0, + 109,204, 0,108,205, 0,108,205, 0,109,204, 0,111,201, 0, + 114,196, 0,117,190, 0,121,179, 0,121,180, 0,122,178, 0, + 123,174, 1,124,165, 8,124,154, 18,124,143, 31,124,145, 29, + 124,161, 11,123,169, 4,122,176, 0,121,181, 0,119,185, 0, + 118,189, 0,116,192, 0,115,195, 0,114,197, 0,113,199, 0, + 113,199, 0,113,198, 0,113,198, 0,114,197, 0,113,198, 0, + 114,197, 0,115,194, 0,116,192, 0,118,189, 0,120,184, 0, + 123,174, 1,124,167, 6,124,160, 12,124,158, 13,124,160, 12, + 124,162, 10,123,173, 1,119,186, 0,115,194, 0,113,199, 0, + 106,207, 0,101,214, 0, 97,218, 0, 95,219, 0, 96,219, 0, + 98,217, 0,101,213, 0,105,209, 0,106,208, 0,104,210, 0, + 102,213, 0,101,214, 0,101,214, 0,100,215, 0, 98,216, 0, + 98,217, 0, 99,215, 0,102,212, 0,102,212, 0,103,211, 0, + 106,208, 0,108,205, 0,110,202, 0,112,200, 0,114,197, 0, + 114,197, 0,111,201, 0,109,204, 0,107,207, 0,107,206, 0, + 110,203, 0,114,197, 0,118,189, 0,119,186, 0,119,187, 0, + 119,187, 0,119,185, 0,121,182, 0,123,174, 1,124,164, 9, + 124,150, 22,122,135, 44,120,122, 70,115,107,129,102, 80,250, + 102, 80,250,107, 89,252,118,117, 85,124,147, 26,124,164, 9, + 123,174, 1,120,182, 0,119,187, 0,118,189, 0,117,190, 0, + 118,188, 0,120,184, 0,120,184, 0,118,188, 0,116,193, 0, + 114,196, 0,114,197, 0,111,201, 0,109,204, 0,108,206, 0, + 108,205, 0,111,201, 0,114,196, 0,117,190, 0,120,184, 0, + 123,172, 2,124,150, 22,122,132, 48,117,110,109,114,104,197, + 117,110,109,122,130, 53,124,143, 31,124,152, 20,124,167, 6, + 121,182, 0,116,193, 0,109,204, 0,103,212, 0, 98,217, 0, + 94,221, 0, 92,223, 0, 89,225, 0, 85,229, 0, 83,230, 0, + 84,229, 0, 85,229, 0, 87,227, 0, 91,224, 0, 95,220, 0, + 100,215, 0,104,210, 0,105,209, 0,107,207, 0,110,202, 0, + 114,197, 0,117,191, 0,116,192, 0,116,193, 0,117,192, 0, + 118,188, 0,121,181, 0,123,171, 3,124,157, 15,124,145, 29, + 121,125, 63,117,110,109,111, 96,248,105, 84,252,118,114, 96, + 123,137, 41,124,152, 20,124,160, 12,124,164, 9,124,162, 10, + 124,162, 10,124,166, 7,123,169, 4,121,179, 0,118,188, 0, + 116,192, 0,115,194, 0,116,193, 0,118,189, 0,118,188, 0, + 115,195, 0,110,202, 0,105,209, 0,102,213, 0,100,215, 0, + 99,215, 0,100,214, 0,103,212, 0,107,207, 0,111,201, 0, + 115,195, 0,115,195, 0,116,192, 0,118,188, 0,121,179, 0, + 124,165, 8,124,165, 8,123,172, 2,122,175, 0,123,174, 1, + 122,176, 0,121,179, 0,121,181, 0,121,180, 0,123,174, 1, + 124,165, 8,124,166, 7,124,167, 6,124,165, 8,124,158, 13, + 124,149, 24,124,161, 11,123,168, 5,123,170, 3,123,170, 3, + 123,168, 5,124,164, 9,124,164, 9,123,173, 1,122,178, 0, + 120,183, 0,117,191, 0,114,196, 0,113,199, 0,112,199, 0, + 113,198, 0,111,201, 0,109,204, 0,108,205, 0,109,204, 0, + 111,202, 0,114,197, 0,117,192, 0,119,185, 0,122,178, 0, + 123,171, 3,124,166, 7,124,158, 13,124,147, 26,124,145, 29, + 124,150, 22,124,154, 18,124,157, 15,124,160, 12,124,166, 7, + 123,173, 1,122,178, 0,120,183, 0,119,186, 0,118,188, 0, + 118,189, 0,117,191, 0,114,196, 0,112,200, 0,109,204, 0, + 107,206, 0,107,207, 0,106,207, 0,106,208, 0,106,208, 0, + 107,207, 0,109,204, 0,109,204, 0,109,204, 0,109,204, 0, + 111,202, 0,113,198, 0,116,192, 0,119,186, 0,118,188, 0, + 118,188, 0,120,184, 0,122,177, 0,124,162, 10,123,137, 41, + 113,100,242,118,114, 96,122,130, 53,124,143, 31,124,155, 16, + 124,166, 7,122,175, 0,120,183, 0,118,188, 0,116,193, 0, + 115,195, 0,114,196, 0,114,196, 0,115,194, 0,114,196, 0, + 114,197, 0,114,197, 0,116,193, 0,117,191, 0,118,188, 0, + 120,182, 0,123,174, 1,123,169, 4,124,165, 8,124,167, 6, + 123,169, 4,123,171, 3,122,175, 0,119,187, 0,116,193, 0, + 114,197, 0,110,202, 0,105,209, 0,102,212, 0,102,213, 0, + 103,211, 0,106,208, 0,109,204, 0,112,200, 0,108,205, 0, + 107,207, 0,104,210, 0,102,212, 0,102,212, 0,103,211, 0, + 101,213, 0,101,214, 0,101,213, 0,104,210, 0,103,211, 0, + 105,209, 0,107,207, 0,109,203, 0,111,201, 0,112,199, 0, + 114,197, 0,115,195, 0,113,199, 0,110,202, 0,109,204, 0, + 109,203, 0,112,200, 0,115,194, 0,119,185, 0,122,178, 0, + 121,180, 0,121,179, 0,122,177, 0,123,170, 3,124,161, 11, + 124,147, 26,121,127, 58,117,110,109,113,100,242, 99, 75,247, + 69, 60,230,107, 89,252,117,110,109,122,132, 48,124,157, 15, + 123,170, 3,121,179, 0,119,186, 0,117,191, 0,115,194, 0, + 115,195, 0,115,194, 0,117,191, 0,117,190, 0,117,190, 0, + 115,194, 0,114,197, 0,113,199, 0,112,200, 0,109,203, 0, + 108,205, 0,109,203, 0,112,199, 0,114,197, 0,115,194, 0, + 118,189, 0,122,178, 0,124,160, 12,121,127, 58,113,100,242, + 94, 70,242,105, 84,252,118,114, 96,122,130, 53,124,145, 29, + 124,167, 6,121,179, 0,116,192, 0,110,203, 0,103,211, 0, + 98,217, 0, 94,221, 0, 91,223, 0, 89,226, 0, 85,229, 0, + 84,229, 0, 85,229, 0, 86,228, 0, 87,227, 0, 90,225, 0, + 94,221, 0, 98,216, 0,104,210, 0,108,206, 0,109,204, 0, + 112,200, 0,115,195, 0,118,189, 0,118,188, 0,119,187, 0, + 119,186, 0,121,181, 0,123,172, 2,123,169, 4,124,164, 9, + 124,152, 20,122,130, 53,111, 96,248,102, 80,250, 30, 55,222, + 99, 75,247,118,114, 96,123,137, 41,124,150, 22,124,157, 15, + 124,158, 13,124,155, 16,124,161, 11,124,167, 6,123,174, 1, + 119,186, 0,117,191, 0,116,193, 0,116,192, 0,118,188, 0, + 120,182, 0,117,191, 0,113,199, 0,108,205, 0,105,209, 0, + 103,211, 0,103,211, 0,105,209, 0,107,207, 0,110,202, 0, + 113,198, 0,113,198, 0,114,196, 0,116,193, 0,119,186, 0, + 122,176, 0,124,167, 6,122,177, 0,120,182, 0,120,184, 0, + 120,183, 0,121,180, 0,120,182, 0,120,183, 0,121,182, 0, + 122,176, 0,122,178, 0,121,182, 0,120,182, 0,121,181, 0, + 122,176, 0,123,168, 5,124,167, 6,123,172, 2,123,174, 1, + 123,173, 1,123,170, 3,124,166, 7,123,171, 3,121,181, 0, + 120,184, 0,118,188, 0,114,196, 0,111,201, 0,108,205, 0, + 108,205, 0,109,204, 0,111,201, 0,110,202, 0,109,203, 0, + 110,203, 0,112,200, 0,114,196, 0,117,190, 0,121,182, 0, + 123,172, 2,124,162, 10,124,154, 18,124,143, 31,121,127, 58, + 121,125, 63,123,137, 41,124,145, 29,124,150, 22,124,155, 16, + 124,164, 9,123,172, 2,121,179, 0,119,185, 0,118,188, 0, + 117,190, 0,117,191, 0,117,192, 0,113,198, 0,110,202, 0, + 108,206, 0,106,207, 0,106,208, 0,106,208, 0,106,207, 0, + 106,208, 0,106,207, 0,108,205, 0,109,203, 0,109,204, 0, + 109,203, 0,111,202, 0,113,198, 0,116,193, 0,116,192, 0, + 115,194, 0,116,193, 0,117,191, 0,120,184, 0,123,172, 2, + 124,150, 22,118,114, 96, 30, 55,222,105, 84,252,122,130, 53, + 124,152, 20,124,164, 9,123,169, 4,123,171, 3,121,182, 0, + 118,189, 0,117,191, 0,117,191, 0,117,192, 0,117,191, 0, + 116,193, 0,114,196, 0,115,194, 0,117,191, 0,117,190, 0, + 118,188, 0,120,182, 0,122,178, 0,123,173, 1,124,167, 6, + 123,170, 3,123,173, 1,122,176, 0,122,176, 0,119,186, 0, + 116,193, 0,114,196, 0,114,196, 0,111,202, 0,108,205, 0, + 109,204, 0,110,202, 0,113,199, 0,114,197, 0,112,199, 0, + 109,204, 0,110,203, 0,107,207, 0,105,209, 0,105,209, 0, + 106,208, 0,104,210, 0,103,211, 0,104,210, 0,106,207, 0, + 106,208, 0,107,207, 0,109,204, 0,111,201, 0,112,199, 0, + 113,198, 0,114,196, 0,117,191, 0,115,195, 0,113,199, 0, + 111,201, 0,112,200, 0,114,197, 0,117,191, 0,121,182, 0, + 123,170, 3,123,171, 3,123,170, 3,124,166, 7,124,158, 13, + 124,145, 29,121,125, 63,113,100,242,102, 80,250, 87, 65,237, + 30, 49,213, 69, 60,230,114,104,197,122,130, 53,124,149, 24, + 124,162, 10,123,172, 2,121,181, 0,118,189, 0,115,194, 0, + 113,198, 0,112,200, 0,112,200, 0,114,197, 0,116,193, 0, + 115,194, 0,115,194, 0,113,198, 0,112,200, 0,111,201, 0, + 111,202, 0,110,202, 0,111,201, 0,111,201, 0,111,201, 0, + 113,198, 0,116,193, 0,120,184, 0,123,169, 4,123,139, 37, + 102, 80,250, 30, 20,155, 30, 55,222,113,100,242,122,132, 48, + 124,152, 20,123,169, 4,121,182, 0,118,189, 0,111,201, 0, + 105,209, 0, 98,216, 0, 94,221, 0, 90,224, 0, 88,226, 0, + 87,227, 0, 87,227, 0, 87,227, 0, 88,226, 0, 89,225, 0, + 91,223, 0, 95,220, 0, 99,215, 0,105,209, 0,110,202, 0, + 112,200, 0,114,197, 0,116,192, 0,119,186, 0,121,182, 0, + 121,180, 0,122,178, 0,123,171, 3,123,173, 1,123,172, 2, + 123,168, 5,124,165, 8,124,155, 16,122,135, 44,113,100,242, + 30, 49,213, 30, 31,180, 94, 70,242,118,114, 96,123,139, 37, + 124,152, 20,124,157, 15,124,155, 16,124,149, 24,124,157, 15, + 124,166, 7,122,178, 0,119,186, 0,118,189, 0,118,189, 0, + 119,185, 0,122,178, 0,119,186, 0,115,194, 0,112,200, 0, + 109,203, 0,108,205, 0,109,204, 0,110,202, 0,112,200, 0, + 112,199, 0,112,199, 0,113,199, 0,114,197, 0,116,192, 0, + 119,185, 0,122,176, 0,123,174, 1,120,183, 0,118,188, 0, + 118,189, 0,118,189, 0,119,187, 0,120,184, 0,120,184, 0, + 120,182, 0,119,185, 0,118,189, 0,117,191, 0,117,192, 0, + 117,191, 0,119,186, 0,121,180, 0,123,172, 2,122,177, 0, + 122,178, 0,122,177, 0,123,173, 1,123,169, 4,123,174, 1, + 121,182, 0,120,184, 0,117,192, 0,112,199, 0,108,205, 0, + 106,208, 0,105,209, 0,106,207, 0,109,204, 0,112,200, 0, + 111,201, 0,112,200, 0,114,197, 0,116,192, 0,119,185, 0, + 122,175, 0,124,161, 11,124,147, 26,122,132, 48,118,117, 85, + 107, 89,252,109, 92,251,117,110,109,121,125, 63,122,132, 48, + 123,141, 34,124,152, 20,124,165, 8,122,175, 0,121,182, 0, + 119,186, 0,118,189, 0,117,190, 0,117,191, 0,113,198, 0, + 110,203, 0,108,206, 0,107,207, 0,107,207, 0,108,206, 0, + 108,206, 0,108,205, 0,108,205, 0,109,204, 0,109,204, 0, + 109,204, 0,110,203, 0,111,201, 0,113,198, 0,115,194, 0, + 114,197, 0,113,199, 0,113,198, 0,114,196, 0,118,189, 0, + 122,178, 0,124,160, 12,122,130, 53,117,110,109,121,125, 63, + 124,152, 20,124,166, 7,123,173, 1,122,175, 0,122,176, 0, + 122,175, 0,120,184, 0,119,187, 0,118,188, 0,118,188, 0, + 118,189, 0,118,189, 0,117,191, 0,117,190, 0,117,191, 0, + 117,192, 0,118,189, 0,119,185, 0,121,182, 0,122,178, 0, + 123,174, 1,123,169, 4,123,173, 1,122,177, 0,122,178, 0, + 120,184, 0,117,190, 0,116,193, 0,115,194, 0,116,193, 0, + 114,196, 0,115,195, 0,116,193, 0,116,193, 0,117,192, 0, + 113,199, 0,110,203, 0,112,199, 0,110,202, 0,109,204, 0, + 109,204, 0,108,205, 0,107,207, 0,106,208, 0,106,208, 0, + 108,205, 0,109,204, 0,110,203, 0,112,200, 0,113,198, 0, + 113,198, 0,114,197, 0,115,194, 0,117,192, 0,115,194, 0, + 112,200, 0,110,203, 0,109,204, 0,110,202, 0,113,198, 0, + 117,191, 0,120,183, 0,122,178, 0,122,177, 0,123,171, 3, + 124,162, 10,124,145, 29,123,139, 37,122,132, 48,118,117, 85, + 102, 80,250, 30, 49,213, 30, 55,222,118,117, 85,124,149, 24, + 124,167, 6,122,178, 0,119,186, 0,118,189, 0,117,191, 0, + 114,196, 0,112,200, 0,110,202, 0,110,203, 0,111,202, 0, + 113,199, 0,114,197, 0,115,195, 0,113,198, 0,111,201, 0, + 110,202, 0,110,202, 0,110,202, 0,110,202, 0,110,203, 0, + 110,202, 0,112,200, 0,114,196, 0,118,188, 0,122,175, 0, + 124,152, 20,117,110,109, 30, 43,203,102, 80,250,120,122, 70, + 124,145, 29,124,158, 13,123,170, 3,121,182, 0,118,189, 0, + 113,198, 0,106,208, 0,100,215, 0, 94,221, 0, 89,225, 0, + 86,228, 0, 84,229, 0, 84,229, 0, 86,228, 0, 90,225, 0, + 94,221, 0, 95,219, 0, 98,216, 0,102,212, 0,107,206, 0, + 112,199, 0,114,197, 0,116,193, 0,118,188, 0,120,182, 0, + 122,176, 0,123,172, 2,123,169, 4,124,167, 6,123,170, 3, + 123,169, 4,123,174, 1,123,173, 1,123,168, 5,124,155, 16, + 123,137, 41,117,110,109,102, 80,250,102, 80,250,111, 96,248, + 121,125, 63,124,147, 26,124,157, 15,124,160, 12,124,154, 18, + 123,141, 34,124,149, 24,124,165, 8,122,177, 0,120,182, 0, + 120,182, 0,122,178, 0,121,179, 0,120,183, 0,118,189, 0, + 115,194, 0,114,197, 0,114,197, 0,114,196, 0,112,199, 0, + 112,200, 0,112,200, 0,112,200, 0,112,199, 0,114,197, 0, + 117,192, 0,120,184, 0,120,184, 0,120,182, 0,119,186, 0, + 117,191, 0,116,193, 0,115,194, 0,115,194, 0,116,193, 0, + 117,192, 0,117,192, 0,115,194, 0,114,197, 0,113,199, 0, + 113,199, 0,114,197, 0,116,193, 0,119,187, 0,121,181, 0, + 121,179, 0,121,180, 0,121,179, 0,122,177, 0,123,174, 1, + 122,177, 0,120,183, 0,118,189, 0,114,196, 0,110,202, 0, + 107,207, 0,105,209, 0,104,210, 0,106,208, 0,108,205, 0, + 111,201, 0,114,197, 0,114,196, 0,116,193, 0,118,188, 0, + 121,179, 0,123,172, 2,124,164, 9,124,150, 22,121,125, 63, + 107, 89,252, 30, 31,180, 30, 43,203,102, 80,250,115,107,129, + 122,130, 53,124,145, 29,124,152, 20,124,152, 20,124,166, 7, + 122,175, 0,121,182, 0,119,185, 0,119,187, 0,118,188, 0, + 114,196, 0,112,200, 0,110,202, 0,110,202, 0,109,203, 0, + 107,206, 0,106,208, 0,106,207, 0,107,206, 0,108,206, 0, + 108,205, 0,108,205, 0,109,203, 0,111,202, 0,113,198, 0, + 114,196, 0,112,200, 0,110,202, 0,110,202, 0,112,199, 0, + 116,193, 0,120,184, 0,123,170, 3,124,164, 9,124,155, 16, + 124,145, 29,124,160, 12,123,171, 3,122,177, 0,122,178, 0, + 122,178, 0,122,177, 0,122,177, 0,120,182, 0,120,184, 0, + 119,186, 0,118,189, 0,117,191, 0,116,192, 0,116,193, 0, + 115,195, 0,115,195, 0,116,193, 0,118,189, 0,119,186, 0, + 120,184, 0,121,181, 0,122,178, 0,123,173, 1,123,173, 1, + 122,177, 0,122,178, 0,119,186, 0,117,191, 0,117,192, 0, + 117,191, 0,118,189, 0,118,189, 0,118,189, 0,118,188, 0, + 118,189, 0,114,196, 0,112,200, 0,115,194, 0,113,198, 0, + 112,199, 0,112,199, 0,112,200, 0,110,203, 0,108,205, 0, + 108,205, 0,110,202, 0,112,199, 0,113,198, 0,114,197, 0, + 114,196, 0,114,196, 0,115,194, 0,115,194, 0,116,193, 0, + 114,196, 0,111,201, 0,108,205, 0,107,206, 0,108,206, 0, + 110,202, 0,113,198, 0,116,192, 0,119,187, 0,121,181, 0, + 122,175, 0,123,169, 4,124,165, 8,124,158, 13,124,150, 22, + 123,137, 41,117,110,109,107, 89,252,111, 96,248,120,122, 70, + 124,158, 13,122,177, 0,118,188, 0,115,194, 0,113,199, 0, + 112,200, 0,112,199, 0,112,200, 0,109,203, 0,109,204, 0, + 109,203, 0,111,201, 0,111,201, 0,112,200, 0,113,199, 0, + 111,201, 0,110,202, 0,110,202, 0,110,202, 0,110,202, 0, + 110,202, 0,111,202, 0,112,200, 0,114,196, 0,118,189, 0, + 122,178, 0,124,161, 11,122,130, 53,111, 96,248,117,110,109, + 123,139, 37,124,154, 18,124,164, 9,124,167, 6,122,178, 0, + 119,187, 0,114,196, 0,107,206, 0,101,214, 0, 94,220, 0, + 89,225, 0, 85,229, 0, 83,230, 0, 82,231, 0, 84,229, 0, + 89,226, 0, 94,220, 0,101,214, 0,103,211, 0,107,207, 0, + 111,201, 0,114,196, 0,116,193, 0,118,189, 0,120,184, 0, + 122,176, 0,124,167, 6,124,164, 9,124,161, 11,124,155, 16, + 124,158, 13,123,168, 5,123,174, 1,122,175, 0,123,172, 2, + 124,166, 7,124,155, 16,123,139, 37,119,119, 77,118,117, 85, + 114,104,197,122,130, 53,123,141, 34,124,157, 15,124,161, 11, + 124,158, 13,124,145, 29,120,122, 70,123,141, 34,124,162, 10, + 123,170, 3,123,172, 2,122,176, 0,120,183, 0,119,186, 0, + 120,184, 0,119,187, 0,118,188, 0,119,187, 0,117,192, 0, + 113,198, 0,112,200, 0,112,200, 0,112,200, 0,112,199, 0, + 114,196, 0,117,191, 0,117,190, 0,118,189, 0,118,188, 0, + 118,188, 0,116,193, 0,114,197, 0,112,199, 0,112,200, 0, + 112,200, 0,112,200, 0,112,200, 0,111,202, 0,109,203, 0, + 109,204, 0,110,203, 0,111,201, 0,114,197, 0,117,192, 0, + 119,186, 0,121,182, 0,121,180, 0,121,179, 0,122,178, 0, + 122,177, 0,121,181, 0,119,187, 0,116,192, 0,113,198, 0, + 110,203, 0,107,207, 0,105,209, 0,105,209, 0,107,207, 0, + 109,204, 0,111,201, 0,114,197, 0,116,193, 0,118,188, 0, + 120,183, 0,122,177, 0,123,169, 4,124,160, 12,124,145, 29, + 119,119, 77,105, 84,252, 30, 31,180, 99, 75,247,115,107,129, + 122,130, 53,124,145, 29,124,154, 18,124,155, 16,124,150, 22, + 124,155, 16,123,168, 5,122,176, 0,121,181, 0,120,184, 0, + 119,186, 0,118,189, 0,115,194, 0,114,197, 0,111,201, 0, + 108,205, 0,106,208, 0,105,209, 0,105,209, 0,106,208, 0, + 106,207, 0,107,207, 0,108,206, 0,109,204, 0,111,202, 0, + 113,199, 0,113,198, 0,111,202, 0,109,204, 0,108,205, 0, + 110,203, 0,113,198, 0,117,191, 0,121,182, 0,122,178, 0, + 123,172, 2,124,167, 6,124,160, 12,123,171, 3,122,177, 0, + 121,179, 0,122,178, 0,122,177, 0,123,174, 1,122,176, 0, + 121,180, 0,119,186, 0,117,191, 0,115,194, 0,114,196, 0, + 113,198, 0,113,199, 0,113,198, 0,114,196, 0,117,192, 0, + 119,187, 0,119,186, 0,119,186, 0,120,184, 0,121,181, 0, + 123,173, 1,123,174, 1,122,177, 0,121,181, 0,118,188, 0, + 118,189, 0,118,189, 0,119,187, 0,119,186, 0,120,184, 0, + 121,181, 0,119,186, 0,117,192, 0,115,194, 0,118,189, 0, + 116,192, 0,116,193, 0,116,192, 0,115,194, 0,113,198, 0, + 111,201, 0,111,202, 0,112,200, 0,114,197, 0,115,195, 0, + 115,194, 0,116,193, 0,116,193, 0,116,192, 0,116,193, 0, + 116,192, 0,114,196, 0,111,201, 0,108,205, 0,107,207, 0, + 107,207, 0,108,205, 0,111,202, 0,113,198, 0,115,194, 0, + 117,190, 0,119,185, 0,121,180, 0,123,174, 1,124,167, 6, + 124,158, 13,124,145, 29,121,125, 63,118,114, 96,122,130, 53, + 124,145, 29,124,162, 10,120,182, 0,116,193, 0,111,201, 0, + 108,205, 0,107,206, 0,107,206, 0,108,205, 0,109,204, 0, + 109,204, 0,109,204, 0,109,204, 0,108,205, 0,110,203, 0, + 112,200, 0,111,202, 0,110,202, 0,110,202, 0,111,202, 0, + 111,201, 0,111,201, 0,112,199, 0,114,197, 0,116,193, 0, + 119,187, 0,122,178, 0,124,162, 10,123,139, 37,121,125, 63, + 122,132, 48,124,150, 22,124,161, 11,124,166, 7,123,168, 5, + 123,171, 3,120,182, 0,115,194, 0,109,204, 0,102,212, 0, + 96,219, 0, 91,224, 0, 86,228, 0, 83,230, 0, 82,231, 0, + 84,229, 0, 89,226, 0, 95,220, 0,101,213, 0,107,206, 0, + 112,200, 0,115,194, 0,117,192, 0,117,191, 0,119,186, 0, + 122,177, 0,124,167, 6,124,154, 18,124,152, 20,124,150, 22, + 124,145, 29,124,143, 31,124,162, 10,123,170, 3,123,173, 1, + 123,172, 2,123,168, 5,124,162, 10,124,154, 18,123,139, 37, + 123,137, 41,121,125, 63,123,139, 37,124,152, 20,124,157, 15, + 124,160, 12,124,157, 15,124,143, 31,120,122, 70,120,122, 70, + 124,143, 31,124,157, 15,123,170, 3,121,180, 0,119,186, 0, + 118,188, 0,119,186, 0,121,179, 0,122,176, 0,123,174, 1, + 119,186, 0,115,194, 0,114,197, 0,113,198, 0,113,198, 0, + 114,197, 0,115,194, 0,116,193, 0,115,194, 0,116,193, 0, + 117,191, 0,118,189, 0,114,196, 0,112,200, 0,110,203, 0, + 109,204, 0,108,205, 0,108,205, 0,108,206, 0,107,207, 0, + 107,207, 0,107,207, 0,108,205, 0,110,202, 0,113,199, 0, + 115,194, 0,117,190, 0,119,186, 0,121,180, 0,122,178, 0, + 122,177, 0,122,176, 0,121,181, 0,118,188, 0,116,193, 0, + 114,197, 0,112,200, 0,110,203, 0,109,204, 0,109,204, 0, + 109,203, 0,111,201, 0,112,199, 0,114,196, 0,116,192, 0, + 119,187, 0,121,181, 0,123,173, 1,124,162, 10,124,149, 24, + 121,127, 58,113,100,242, 99, 75,247,105, 84,252,118,117, 85, + 123,137, 41,124,149, 24,124,155, 16,124,158, 13,124,157, 15, + 124,150, 22,124,158, 13,124,164, 9,123,169, 4,122,175, 0, + 121,179, 0,120,182, 0,119,187, 0,117,191, 0,114,196, 0, + 111,201, 0,108,205, 0,106,207, 0,105,209, 0,105,209, 0, + 106,208, 0,106,208, 0,106,207, 0,107,206, 0,109,204, 0, + 110,202, 0,112,199, 0,113,198, 0,110,203, 0,108,206, 0, + 107,207, 0,108,206, 0,110,202, 0,114,197, 0,118,189, 0, + 119,186, 0,121,181, 0,122,177, 0,123,171, 3,123,168, 5, + 122,175, 0,122,178, 0,122,177, 0,122,175, 0,123,170, 3, + 123,169, 4,122,176, 0,119,185, 0,116,192, 0,114,197, 0, + 112,199, 0,112,200, 0,111,201, 0,112,200, 0,114,197, 0, + 116,193, 0,119,186, 0,119,186, 0,119,187, 0,118,188, 0, + 119,186, 0,121,179, 0,123,170, 3,122,176, 0,122,178, 0, + 120,182, 0,119,186, 0,119,186, 0,120,183, 0,121,181, 0, + 122,178, 0,123,173, 1,121,180, 0,119,185, 0,119,186, 0, + 121,181, 0,119,185, 0,119,186, 0,120,184, 0,119,186, 0, + 117,192, 0,115,195, 0,114,197, 0,115,195, 0,116,192, 0, + 117,191, 0,117,191, 0,117,190, 0,118,189, 0,118,189, 0, + 117,192, 0,117,191, 0,115,195, 0,112,200, 0,109,204, 0, + 107,207, 0,107,207, 0,108,206, 0,109,204, 0,111,202, 0, + 112,199, 0,114,196, 0,117,191, 0,119,185, 0,122,178, 0, + 123,169, 4,124,158, 13,124,143, 31,122,130, 53,122,130, 53, + 124,152, 20,124,164, 9,123,169, 4,120,184, 0,114,197, 0, + 109,204, 0,105,209, 0,103,211, 0,103,211, 0,104,210, 0, + 105,209, 0,106,207, 0,107,207, 0,106,207, 0,106,208, 0, + 108,206, 0,111,202, 0,110,202, 0,110,202, 0,111,201, 0, + 110,202, 0,111,201, 0,113,198, 0,114,196, 0,116,193, 0, + 118,188, 0,120,182, 0,123,173, 1,124,160, 12,123,137, 41, + 122,135, 44,124,143, 31,124,157, 15,124,164, 9,124,167, 6, + 123,169, 4,123,171, 3,121,182, 0,116,192, 0,111,201, 0, + 105,209, 0,100,215, 0, 94,221, 0, 89,225, 0, 86,228, 0, + 85,229, 0, 86,228, 0, 91,223, 0, 97,218, 0,103,211, 0, + 110,203, 0,114,197, 0,114,197, 0,114,197, 0,114,196, 0, + 117,191, 0,120,182, 0,124,165, 8,122,135, 44,122,135, 44, + 123,139, 37,122,132, 48,123,139, 37,124,150, 22,124,161, 11, + 124,166, 7,124,167, 6,124,167, 6,124,164, 9,124,160, 12, + 124,149, 24,124,147, 26,123,137, 41,124,143, 31,124,158, 13, + 124,164, 9,124,160, 12,124,149, 24,122,132, 48,115,107,129, + 119,119, 77,123,141, 34,124,160, 12,123,173, 1,120,183, 0, + 118,188, 0,118,189, 0,119,186, 0,121,179, 0,124,164, 9, + 124,158, 13,122,177, 0,119,187, 0,117,191, 0,116,192, 0, + 116,193, 0,116,192, 0,116,193, 0,114,196, 0,114,196, 0, + 115,195, 0,116,193, 0,117,191, 0,114,197, 0,110,202, 0, + 108,205, 0,106,207, 0,106,208, 0,106,208, 0,106,208, 0, + 105,209, 0,106,208, 0,107,207, 0,109,204, 0,111,202, 0, + 113,198, 0,115,194, 0,117,192, 0,118,188, 0,120,182, 0, + 123,173, 1,123,173, 1,123,172, 2,122,176, 0,120,184, 0, + 118,189, 0,117,192, 0,115,194, 0,114,196, 0,114,196, 0, + 114,197, 0,114,196, 0,114,196, 0,115,195, 0,116,193, 0, + 118,189, 0,120,184, 0,122,176, 0,124,165, 8,124,149, 24, + 121,125, 63,111, 96,248,107, 89,252,105, 84,252,118,117, 85, + 123,141, 34,124,152, 20,124,158, 13,124,160, 12,124,160, 12, + 124,155, 16,124,155, 16,124,161, 11,124,164, 9,124,164, 9, + 124,165, 8,123,170, 3,122,176, 0,120,182, 0,118,188, 0, + 115,194, 0,113,199, 0,110,202, 0,108,205, 0,107,207, 0, + 107,207, 0,107,207, 0,107,207, 0,107,207, 0,106,208, 0, + 106,208, 0,108,205, 0,112,200, 0,113,198, 0,109,203, 0, + 107,207, 0,105,209, 0,106,208, 0,107,206, 0,110,202, 0, + 114,196, 0,117,191, 0,119,186, 0,120,182, 0,122,178, 0, + 123,170, 3,123,168, 5,123,172, 2,123,172, 2,123,169, 4, + 124,161, 11,124,161, 11,123,170, 3,120,184, 0,116,192, 0, + 114,197, 0,112,200, 0,111,201, 0,111,201, 0,112,199, 0, + 114,196, 0,117,191, 0,119,185, 0,120,182, 0,119,185, 0, + 118,188, 0,118,188, 0,120,183, 0,123,173, 1,123,174, 1, + 122,178, 0,122,178, 0,121,179, 0,121,179, 0,122,176, 0, + 123,173, 1,123,168, 5,124,161, 11,123,170, 3,122,175, 0, + 122,176, 0,123,168, 5,123,174, 1,122,175, 0,123,173, 1, + 123,174, 1,120,182, 0,118,188, 0,117,190, 0,118,189, 0, + 119,186, 0,119,186, 0,119,186, 0,119,186, 0,119,185, 0, + 119,186, 0,118,188, 0,118,188, 0,116,193, 0,113,199, 0, + 110,202, 0,109,204, 0,108,205, 0,108,205, 0,109,204, 0, + 110,203, 0,111,202, 0,113,198, 0,116,193, 0,119,187, 0, + 122,178, 0,124,166, 7,124,150, 22,122,132, 48,121,125, 63, + 124,143, 31,124,166, 7,122,176, 0,121,181, 0,120,184, 0, + 114,197, 0,108,205, 0,104,210, 0,102,213, 0,101,213, 0, + 102,213, 0,103,212, 0,104,210, 0,105,209, 0,105,209, 0, + 105,209, 0,107,207, 0,110,202, 0,110,202, 0,110,202, 0, + 110,202, 0,109,203, 0,110,202, 0,112,199, 0,115,194, 0, + 119,187, 0,121,182, 0,123,174, 1,124,164, 9,124,149, 24, + 122,130, 53,122,132, 48,124,147, 26,124,160, 12,124,166, 7, + 123,169, 4,123,171, 3,121,180, 0,120,184, 0,118,189, 0, + 114,197, 0,109,204, 0,104,210, 0, 99,215, 0, 94,220, 0, + 91,223, 0, 89,225, 0, 91,223, 0, 95,220, 0,101,214, 0, + 107,206, 0,109,203, 0,110,202, 0,110,202, 0,110,202, 0, + 111,201, 0,114,196, 0,118,188, 0,123,172, 2,123,141, 34, + 117,110,109,119,119, 77,118,117, 85,123,137, 41,124,152, 20, + 124,160, 12,124,160, 12,124,158, 13,124,160, 12,124,160, 12, + 124,160, 12,124,152, 20,124,150, 22,124,143, 31,124,143, 31, + 124,158, 13,124,164, 9,124,161, 11,124,143, 31,114,104,197, + 99, 75,247,117,110,109,123,139, 37,124,160, 12,123,174, 1, + 120,183, 0,118,188, 0,118,189, 0,119,186, 0,121,179, 0, + 124,166, 7,123,139, 37,124,157, 15,123,173, 1,121,179, 0, + 121,182, 0,120,184, 0,119,187, 0,116,193, 0,114,196, 0, + 114,197, 0,114,196, 0,115,194, 0,117,192, 0,113,198, 0, + 110,203, 0,107,207, 0,106,208, 0,106,208, 0,106,208, 0, + 106,208, 0,106,208, 0,107,207, 0,109,204, 0,111,202, 0, + 113,199, 0,114,196, 0,116,193, 0,117,192, 0,118,189, 0, + 120,183, 0,123,173, 1,124,165, 8,124,165, 8,124,164, 9, + 123,174, 1,121,179, 0,121,182, 0,120,182, 0,120,182, 0, + 120,183, 0,120,184, 0,119,186, 0,119,187, 0,118,188, 0, + 118,188, 0,120,184, 0,122,178, 0,124,167, 6,124,150, 22, + 121,125, 63,113,100,242,102, 80,250,102, 80,250,115,107,129, + 123,141, 34,124,157, 15,124,164, 9,124,165, 8,124,162, 10, + 124,158, 13,124,154, 18,124,160, 12,124,162, 10,124,162, 10, + 124,158, 13,124,150, 22,124,154, 18,124,165, 8,122,175, 0, + 120,182, 0,118,189, 0,116,193, 0,114,197, 0,112,200, 0, + 111,201, 0,111,202, 0,109,203, 0,106,208, 0,103,211, 0, + 102,212, 0,103,212, 0,105,209, 0,109,204, 0,113,199, 0, + 109,204, 0,106,208, 0,104,210, 0,104,210, 0,105,209, 0, + 107,206, 0,110,202, 0,113,198, 0,117,192, 0,119,186, 0, + 121,181, 0,123,174, 1,124,164, 9,124,161, 11,124,161, 11, + 124,157, 15,124,145, 29,124,152, 20,123,169, 4,120,184, 0, + 117,192, 0,114,197, 0,112,199, 0,112,200, 0,112,199, 0, + 114,197, 0,116,192, 0,118,188, 0,121,182, 0,122,175, 0, + 121,179, 0,120,184, 0,119,186, 0,120,184, 0,122,176, 0, + 123,171, 3,122,176, 0,122,178, 0,123,174, 1,124,167, 6, + 124,164, 9,124,160, 12,124,154, 18,124,145, 29,124,154, 18, + 124,160, 12,124,160, 12,124,145, 29,124,154, 18,124,157, 15, + 124,155, 16,124,157, 15,123,169, 4,122,177, 0,121,181, 0, + 121,180, 0,122,178, 0,122,178, 0,121,179, 0,121,181, 0, + 121,181, 0,121,179, 0,120,182, 0,120,182, 0,117,190, 0, + 115,195, 0,113,199, 0,111,201, 0,111,202, 0,111,202, 0, + 111,202, 0,110,202, 0,111,202, 0,113,199, 0,116,193, 0, + 119,185, 0,123,174, 1,124,157, 15,122,132, 48,115,107,129, + 117,110,109,124,152, 20,123,174, 1,120,184, 0,118,189, 0, + 117,191, 0,114,196, 0,109,204, 0,104,210, 0,102,213, 0, + 101,214, 0,101,214, 0,102,212, 0,104,210, 0,105,209, 0, + 105,209, 0,105,209, 0,107,206, 0,109,203, 0,109,203, 0, + 110,202, 0,109,203, 0,109,204, 0,110,203, 0,112,200, 0, + 114,196, 0,117,191, 0,121,182, 0,124,166, 7,124,145, 29, + 121,125, 63,117,110,109,118,117, 85,124,145, 29,124,160, 12, + 124,167, 6,123,171, 3,122,178, 0,119,186, 0,118,189, 0, + 117,190, 0,116,192, 0,113,199, 0,109,204, 0,105,209, 0, + 101,214, 0, 97,217, 0, 96,219, 0, 97,218, 0,101,214, 0, + 106,208, 0,106,208, 0,106,207, 0,107,207, 0,107,206, 0, + 108,206, 0,109,204, 0,112,200, 0,117,192, 0,121,179, 0, + 124,154, 18,121,125, 63,107, 89,252,109, 92,251,122,130, 53, + 124,152, 20,124,162, 10,124,166, 7,124,165, 8,124,158, 13, + 124,152, 20,124,155, 16,124,152, 20,124,150, 22,124,145, 29, + 123,141, 34,124,154, 18,124,158, 13,124,154, 18,122,132, 48, + 99, 75,247, 30, 43,203,107, 89,252,121,127, 58,124,155, 16, + 123,171, 3,121,181, 0,119,186, 0,119,186, 0,120,184, 0, + 121,179, 0,123,168, 5,124,143, 31,122,130, 53,124,143, 31, + 124,155, 16,124,161, 11,123,170, 3,120,184, 0,117,191, 0, + 115,195, 0,114,196, 0,115,194, 0,116,193, 0,116,193, 0, + 112,199, 0,109,203, 0,107,206, 0,107,207, 0,107,207, 0, + 108,206, 0,108,205, 0,108,205, 0,110,202, 0,112,200, 0, + 114,197, 0,115,195, 0,116,193, 0,117,191, 0,117,190, 0, + 118,188, 0,120,182, 0,123,172, 2,124,155, 16,124,149, 24, + 124,145, 29,124,152, 20,124,160, 12,124,160, 12,124,158, 13, + 124,157, 15,124,165, 8,123,170, 3,123,171, 3,123,172, 2, + 122,178, 0,122,178, 0,122,176, 0,123,168, 5,124,154, 18, + 121,127, 58,118,117, 85,117,110,109,107, 89,252, 99, 75,247, + 122,130, 53,124,157, 15,124,167, 6,123,171, 3,123,170, 3, + 124,164, 9,124,155, 16,124,161, 11,124,164, 9,124,162, 10, + 124,158, 13,124,150, 22,123,137, 41,120,122, 70,123,141, 34, + 124,160, 12,123,172, 2,121,180, 0,119,185, 0,118,189, 0, + 117,191, 0,116,193, 0,112,199, 0,109,204, 0,105,209, 0, + 102,212, 0,101,214, 0,101,214, 0,103,211, 0,107,207, 0, + 112,200, 0,109,204, 0,105,209, 0,103,211, 0,102,212, 0, + 103,211, 0,105,209, 0,108,206, 0,110,202, 0,113,198, 0, + 118,188, 0,120,183, 0,122,176, 0,124,165, 8,124,145, 29, + 123,139, 37,122,132, 48,118,114, 96,123,139, 37,123,168, 5, + 120,183, 0,117,191, 0,115,194, 0,114,196, 0,114,197, 0, + 115,195, 0,117,192, 0,119,187, 0,121,182, 0,122,175, 0, + 123,169, 4,123,168, 5,122,178, 0,120,182, 0,121,182, 0, + 122,178, 0,123,169, 4,123,173, 1,122,175, 0,123,172, 2, + 124,164, 9,124,145, 29,123,137, 41,122,130, 53,119,119, 77, + 120,122, 70,122,132, 48,122,132, 48,111, 96,248,118,114, 96, + 120,122, 70,121,125, 63,121,125, 63,124,147, 26,124,160, 12, + 124,166, 7,124,167, 6,124,166, 7,123,168, 5,123,172, 2, + 122,175, 0,122,177, 0,122,176, 0,123,174, 1,122,176, 0, + 119,185, 0,117,190, 0,116,193, 0,114,196, 0,114,197, 0, + 112,200, 0,112,200, 0,112,199, 0,112,200, 0,114,197, 0, + 117,190, 0,121,181, 0,124,165, 8,124,143, 31,113,100,242, + 30, 55,222,114,104,197,124,158, 13,121,180, 0,117,191, 0, + 114,196, 0,113,198, 0,113,198, 0,110,202, 0,106,208, 0, + 103,211, 0,102,212, 0,102,212, 0,103,211, 0,105,209, 0, + 107,207, 0,107,206, 0,108,206, 0,109,203, 0,109,204, 0, + 108,205, 0,109,204, 0,109,204, 0,109,204, 0,110,202, 0, + 112,200, 0,114,197, 0,116,192, 0,120,184, 0,123,171, 3, + 124,145, 29,107, 89,252, 87, 65,237,114,104,197,123,141, 34, + 124,160, 12,123,169, 4,123,174, 1,120,184, 0,117,190, 0, + 116,193, 0,116,193, 0,114,197, 0,112,200, 0,108,205, 0, + 106,208, 0,106,208, 0,104,210, 0,102,212, 0,103,211, 0, + 105,209, 0,104,210, 0,104,210, 0,104,210, 0,104,210, 0, + 105,209, 0,106,208, 0,107,207, 0,110,202, 0,114,196, 0, + 120,184, 0,124,165, 8,122,132, 48,107, 89,252, 30, 55,222, + 118,114, 96,124,145, 29,124,161, 11,123,168, 5,123,170, 3, + 124,166, 7,124,157, 15,124,149, 24,124,150, 22,124,147, 26, + 124,145, 29,123,137, 41,124,143, 31,124,147, 26,123,139, 37, + 117,110,109, 30, 49,213,107, 89,252,118,114, 96,124,143, 31, + 124,155, 16,124,166, 7,122,177, 0,121,182, 0,120,182, 0, + 121,182, 0,122,178, 0,123,169, 4,124,154, 18,119,119, 77, + 107, 89,252,111, 96,248,120,122, 70,124,161, 11,122,178, 0, + 118,188, 0,116,192, 0,116,193, 0,116,192, 0,117,191, 0, + 115,194, 0,112,200, 0,110,203, 0,108,205, 0,109,204, 0, + 110,203, 0,111,201, 0,111,201, 0,112,200, 0,114,197, 0, + 112,199, 0,111,201, 0,112,200, 0,114,197, 0,117,191, 0, + 119,187, 0,119,186, 0,121,181, 0,123,171, 3,124,155, 16, + 121,127, 58,118,117, 85,111, 96,248,115,107,129,114,104,197, + 120,122, 70,124,149, 24,124,162, 10,124,167, 6,124,166, 7, + 124,161, 11,124,161, 11,124,165, 8,124,162, 10,124,154, 18, + 122,135, 44,118,117, 85,119,119, 77,118,117, 85,109, 92,251, + 117,110,109,124,149, 24,123,168, 5,122,176, 0,122,178, 0, + 123,174, 1,124,167, 6,124,160, 12,124,164, 9,124,164, 9, + 124,160, 12,124,150, 22,122,135, 44,117,110,109,105, 84,252, + 109, 92,251,122,130, 53,124,150, 22,124,164, 9,123,171, 3, + 122,176, 0,120,184, 0,117,191, 0,114,197, 0,110,202, 0, + 107,207, 0,103,211, 0,101,214, 0,101,214, 0,102,212, 0, + 106,208, 0,111,202, 0,108,205, 0,105,209, 0,102,212, 0, + 101,213, 0,102,212, 0,104,210, 0,106,207, 0,108,205, 0, + 112,200, 0,116,192, 0,120,184, 0,122,177, 0,124,165, 8, + 124,143, 31,113,100,242,102, 80,250,109, 92,251,123,141, 34, + 123,168, 5,121,182, 0,118,188, 0,117,191, 0,117,192, 0, + 117,192, 0,117,190, 0,118,189, 0,117,191, 0,117,190, 0, + 119,186, 0,122,177, 0,124,160, 12,124,167, 6,122,175, 0, + 122,178, 0,122,178, 0,123,173, 1,123,169, 4,123,171, 3, + 123,169, 4,124,161, 11,124,145, 29,121,127, 58,114,104,197, + 109, 92,251,102, 80,250,105, 84,252,107, 89,252, 30, 2,128, + 30, 26,168, 30, 49,213, 87, 65,237,102, 80,250,115,107,129, + 122,132, 48,124,145, 29,124,147, 26,124,161, 11,124,166, 7, + 124,166, 7,123,169, 4,123,173, 1,123,174, 1,123,171, 3, + 124,162, 10,122,175, 0,120,182, 0,119,186, 0,118,189, 0, + 115,194, 0,114,197, 0,113,198, 0,115,194, 0,115,195, 0, + 117,192, 0,119,185, 0,123,173, 1,124,161, 11,123,139, 37, + 111, 96,248, 30, 2,128,118,114, 96,124,164, 9,120,184, 0, + 115,194, 0,112,200, 0,111,202, 0,111,202, 0,111,201, 0, + 108,206, 0,105,209, 0,104,210, 0,105,209, 0,107,207, 0, + 109,204, 0,111,201, 0,111,201, 0,110,202, 0,109,204, 0, + 108,206, 0,107,207, 0,107,207, 0,108,205, 0,109,203, 0, + 111,201, 0,113,198, 0,115,195, 0,117,191, 0,120,184, 0, + 123,173, 1,124,150, 22,113,100,242, 30, 2,128,109, 92,251, + 123,139, 37,124,161, 11,123,172, 2,121,179, 0,119,185, 0, + 117,191, 0,115,194, 0,112,199, 0,109,204, 0,106,207, 0, + 105,209, 0,105,209, 0,104,210, 0,105,209, 0,107,206, 0, + 105,209, 0,103,211, 0,102,212, 0,100,215, 0, 99,216, 0, + 99,216, 0,101,214, 0,105,209, 0,106,208, 0,109,204, 0, + 113,198, 0,118,189, 0,123,173, 1,124,145, 29,105, 84,252, + 30, 2,128, 99, 75,247,121,127, 58,124,154, 18,124,165, 8, + 123,169, 4,123,168, 5,124,162, 10,124,147, 26,124,150, 22, + 124,145, 29,123,141, 34,122,135, 44,122,130, 53,122,130, 53, + 118,117, 85, 94, 70,242,117,110,109,122,135, 44,124,149, 24, + 124,157, 15,124,167, 6,123,171, 3,123,174, 1,122,175, 0, + 122,177, 0,122,178, 0,122,176, 0,123,170, 3,124,158, 13, + 122,135, 44,105, 84,252, 30, 2,128,111, 96,248,124,149, 24, + 123,172, 2,120,184, 0,118,189, 0,117,191, 0,117,191, 0, + 118,189, 0,115,195, 0,112,200, 0,110,202, 0,110,202, 0, + 111,201, 0,113,199, 0,114,197, 0,115,195, 0,114,197, 0, + 111,201, 0,110,203, 0,109,204, 0,110,202, 0,113,199, 0, + 116,192, 0,120,184, 0,120,183, 0,122,178, 0,123,170, 3, + 124,155, 16,122,130, 53,107, 89,252, 30, 43,203, 30, 2,128, + 30, 55,222,115,107,129,123,139, 37,124,154, 18,124,160, 12, + 124,158, 13,124,149, 24,122,135, 44,124,145, 29,124,145, 29, + 123,137, 41,122,132, 48,119,119, 77,119,119, 77,117,110,109, + 105, 84,252,123,139, 37,124,165, 8,122,178, 0,120,183, 0, + 120,184, 0,121,180, 0,123,171, 3,124,160, 12,124,161, 11, + 124,160, 12,124,152, 20,123,137, 41,118,114, 96,107, 89,252, + 30, 43,203, 30, 2,128, 87, 65,237,117,110,109,122,135, 44, + 124,155, 16,123,170, 3,121,180, 0,119,187, 0,116,192, 0, + 113,198, 0,109,204, 0,105,209, 0,103,212, 0,102,212, 0, + 103,211, 0,106,207, 0,111,201, 0,106,207, 0,103,211, 0, + 101,214, 0,101,214, 0,102,213, 0,104,210, 0,106,208, 0, + 109,204, 0,112,200, 0,116,193, 0,119,187, 0,122,178, 0, + 124,164, 9,123,139, 37,107, 89,252, 30, 2,128,109, 92,251, + 124,145, 29,123,169, 4,121,181, 0,119,186, 0,118,188, 0, + 118,188, 0,118,188, 0,116,192, 0,114,196, 0,113,198, 0, + 114,197, 0,116,193, 0,119,186, 0,123,173, 1,124,155, 16, + 123,168, 5,123,174, 1,122,177, 0,122,177, 0,123,174, 1, + 123,169, 4,124,167, 6,124,158, 13,124,152, 20,123,137, 41, + 121,127, 58,118,114, 96,111, 96,248, 94, 70,242, 30, 31,180, + 107, 89,252,105, 84,252, 99, 75,247, 30, 43,203, 30, 15,143, + 30, 55,222,111, 96,248,118,117, 85,123,137, 41,124,155, 16, + 124,162, 10,124,164, 9,123,168, 5,123,174, 1,122,177, 0, + 122,175, 0,123,168, 5,124,161, 11,124,167, 6,123,174, 1, + 121,182, 0,118,188, 0,117,191, 0,117,192, 0,118,189, 0, + 118,189, 0,119,186, 0,122,178, 0,124,164, 9,124,152, 20, + 121,127, 58, 99, 75,247, 30, 55,222,121,125, 63,123,168, 5, + 119,186, 0,114,196, 0,111,201, 0,110,203, 0,110,202, 0, + 111,201, 0,109,204, 0,107,207, 0,107,207, 0,108,205, 0, + 110,202, 0,112,200, 0,108,205, 0,107,206, 0,108,205, 0, + 108,205, 0,107,207, 0,105,209, 0,105,209, 0,105,209, 0, + 106,207, 0,108,205, 0,112,200, 0,117,192, 0,118,188, 0, + 120,182, 0,123,173, 1,124,154, 18,118,114, 96, 94, 70,242, + 102, 80,250,122,135, 44,124,162, 10,122,176, 0,119,185, 0, + 117,191, 0,114,196, 0,111,201, 0,107,206, 0,104,210, 0, + 101,214, 0, 99,215, 0, 99,216, 0,100,215, 0,101,214, 0, + 101,214, 0,100,214, 0, 98,216, 0, 96,219, 0, 94,220, 0, + 93,221, 0, 94,221, 0, 96,219, 0,100,215, 0,105,209, 0, + 109,204, 0,113,199, 0,117,191, 0,122,178, 0,124,158, 13, + 119,119, 77, 30, 55,222, 99, 75,247,114,104,197,122,135, 44, + 124,154, 18,124,161, 11,124,162, 10,124,158, 13,124,149, 24, + 124,152, 20,124,150, 22,123,141, 34,122,132, 48,120,122, 70, + 117,110,109,111, 96,248,118,114, 96,123,139, 37,124,155, 16, + 124,166, 7,123,170, 3,123,174, 1,122,178, 0,121,179, 0, + 121,181, 0,121,180, 0,122,175, 0,123,173, 1,123,170, 3, + 124,162, 10,124,145, 29,118,114, 96,107, 89,252, 99, 75,247, + 122,132, 48,124,164, 9,122,178, 0,119,185, 0,118,188, 0, + 118,188, 0,118,189, 0,114,196, 0,112,199, 0,111,201, 0, + 110,202, 0,110,202, 0,111,202, 0,109,204, 0,108,206, 0, + 108,206, 0,107,206, 0,108,205, 0,109,204, 0,110,202, 0, + 113,198, 0,117,192, 0,120,183, 0,122,178, 0,123,173, 1, + 124,166, 7,124,154, 18,124,143, 31,122,130, 53,118,117, 85, + 117,110,109,118,114, 96,121,127, 58,123,137, 41,123,139, 37, + 124,147, 26,124,143, 31,122,135, 44,118,117, 85,117,110,109, + 122,130, 53,123,137, 41,123,139, 37,122,135, 44,121,127, 58, + 119,119, 77,121,127, 58,124,158, 13,122,176, 0,119,185, 0, + 118,189, 0,118,189, 0,119,185, 0,122,178, 0,123,168, 5, + 124,155, 16,124,147, 26,122,135, 44,121,125, 63,121,125, 63, + 121,127, 58,120,122, 70,111, 96,248,105, 84,252,115,107,129, + 122,130, 53,124,152, 20,123,168, 5,121,181, 0,117,190, 0, + 114,197, 0,111,201, 0,110,203, 0,108,205, 0,105,209, 0, + 105,209, 0,105,209, 0,108,206, 0,109,203, 0,105,209, 0, + 102,212, 0,101,213, 0,102,213, 0,102,212, 0,101,213, 0, + 102,212, 0,106,208, 0,110,203, 0,114,197, 0,118,189, 0, + 121,179, 0,124,162, 10,122,130, 53, 99, 75,247,102, 80,250, + 115,107,129,124,150, 22,123,170, 3,121,180, 0,120,184, 0, + 119,185, 0,119,186, 0,116,193, 0,114,197, 0,111,201, 0, + 110,202, 0,111,201, 0,114,197, 0,117,191, 0,121,180, 0, + 124,166, 7,124,161, 11,123,170, 3,122,175, 0,122,178, 0, + 122,178, 0,122,176, 0,123,174, 1,123,173, 1,123,170, 3, + 124,161, 11,124,145, 29,123,139, 37,122,135, 44,121,125, 63, + 117,110,109,122,135, 44,122,130, 53,121,125, 63,114,104,197, + 69, 60,230, 30, 26,168, 30, 49,213,109, 92,251,118,117, 85, + 124,145, 29,124,157, 15,124,160, 12,123,169, 4,122,177, 0, + 121,181, 0,121,181, 0,122,177, 0,123,169, 4,124,161, 11, + 124,165, 8,123,174, 1,121,181, 0,120,184, 0,120,183, 0, + 120,184, 0,120,184, 0,121,180, 0,123,169, 4,124,152, 20, + 123,137, 41,117,110,109, 69, 60,230,114,104,197,122,135, 44, + 123,171, 3,118,188, 0,114,196, 0,111,201, 0,110,202, 0, + 111,201, 0,111,201, 0,109,204, 0,108,205, 0,109,204, 0, + 110,202, 0,113,199, 0,110,203, 0,107,207, 0,106,208, 0, + 106,208, 0,107,207, 0,106,207, 0,105,209, 0,104,210, 0, + 103,211, 0,104,210, 0,106,208, 0,109,203, 0,115,195, 0, + 120,184, 0,121,180, 0,123,173, 1,124,160, 12,122,135, 44, + 120,122, 70,114,104,197,121,125, 63,124,161, 11,122,178, 0, + 118,189, 0,114,196, 0,111,202, 0,107,207, 0,103,211, 0, + 100,215, 0, 97,218, 0, 95,220, 0, 94,221, 0, 94,221, 0, + 94,220, 0, 95,220, 0, 94,221, 0, 92,222, 0, 90,224, 0, + 89,226, 0, 88,226, 0, 89,226, 0, 91,223, 0, 95,220, 0, + 100,214, 0,106,207, 0,113,199, 0,117,191, 0,121,181, 0, + 124,166, 7,123,141, 34,113,100,242,102, 80,250,111, 96,248, + 118,114, 96,121,127, 58,123,141, 34,124,147, 26,124,145, 29, + 124,149, 24,124,152, 20,124,149, 24,123,141, 34,122,130, 53, + 119,119, 77,118,114, 96,119,119, 77,122,135, 44,124,152, 20, + 124,165, 8,123,172, 2,122,176, 0,122,177, 0,121,179, 0, + 121,181, 0,120,183, 0,120,183, 0,122,178, 0,123,172, 2, + 123,170, 3,124,166, 7,124,157, 15,124,147, 26,123,139, 37, + 121,127, 58,120,122, 70,124,147, 26,123,169, 4,122,178, 0, + 120,182, 0,120,182, 0,117,190, 0,114,196, 0,112,200, 0, + 109,204, 0,107,206, 0,107,206, 0,106,208, 0,102,213, 0, + 100,215, 0,100,215, 0,100,215, 0,101,214, 0,103,211, 0, + 107,207, 0,110,202, 0,115,195, 0,118,188, 0,121,179, 0, + 122,176, 0,123,174, 1,123,171, 3,123,168, 5,124,165, 8, + 124,162, 10,124,161, 11,124,161, 11,124,161, 11,124,157, 15, + 124,150, 22,122,135, 44,121,125, 63,119,119, 77,118,117, 85, + 118,117, 85,118,117, 85,122,132, 48,123,141, 34,124,145, 29, + 124,145, 29,123,141, 34,124,150, 22,123,170, 3,121,182, 0, + 118,188, 0,117,192, 0,117,192, 0,118,189, 0,120,184, 0, + 122,177, 0,124,167, 6,124,155, 16,124,147, 26,124,152, 20, + 124,157, 15,124,160, 12,124,157, 15,124,143, 31,122,130, 53, + 123,141, 34,124,155, 16,124,167, 6,122,178, 0,119,186, 0, + 115,194, 0,111,201, 0,108,205, 0,107,207, 0,106,208, 0, + 106,207, 0,107,207, 0,107,207, 0,108,205, 0,109,204, 0, + 105,209, 0,103,211, 0,103,211, 0,102,212, 0,100,215, 0, + 98,216, 0, 99,215, 0,102,212, 0,107,207, 0,112,200, 0, + 117,192, 0,121,180, 0,124,160, 12,119,119, 77,118,114, 96, + 122,130, 53,123,141, 34,124,155, 16,123,170, 3,122,178, 0, + 121,181, 0,121,180, 0,118,188, 0,115,195, 0,112,200, 0, + 109,203, 0,108,205, 0,109,204, 0,112,200, 0,116,193, 0, + 120,184, 0,123,172, 2,124,162, 10,124,165, 8,123,172, 2, + 122,176, 0,122,178, 0,122,178, 0,122,178, 0,121,180, 0, + 121,179, 0,123,173, 1,124,164, 9,124,150, 22,124,152, 20, + 124,150, 22,124,145, 29,124,154, 18,124,157, 15,124,152, 20, + 123,139, 37,115,107,129, 99, 75,247, 69, 60,230, 99, 75,247, + 113,100,242,122,130, 53,124,149, 24,124,158, 13,123,171, 3, + 121,179, 0,120,184, 0,119,186, 0,120,184, 0,122,178, 0, + 123,172, 2,124,164, 9,124,166, 7,123,171, 3,123,173, 1, + 123,172, 2,122,178, 0,121,179, 0,123,173, 1,124,160, 12, + 122,135, 44,119,119, 77,105, 84,252,114,104,197,122,130, 53, + 124,145, 29,123,173, 1,119,187, 0,115,194, 0,113,199, 0, + 112,200, 0,113,199, 0,111,201, 0,110,203, 0,109,203, 0, + 110,202, 0,112,200, 0,111,201, 0,109,203, 0,106,207, 0, + 105,209, 0,106,208, 0,106,207, 0,107,207, 0,106,208, 0, + 105,209, 0,104,210, 0,104,210, 0,105,209, 0,108,205, 0, + 114,197, 0,119,185, 0,122,178, 0,123,173, 1,124,164, 9, + 124,157, 15,124,150, 22,123,137, 41,119,119, 77,124,157, 15, + 122,178, 0,117,191, 0,113,199, 0,108,205, 0,105,209, 0, + 101,214, 0, 97,218, 0, 94,221, 0, 92,222, 0, 91,224, 0, + 90,224, 0, 90,224, 0, 90,224, 0, 89,225, 0, 87,227, 0, + 86,228, 0, 85,229, 0, 84,229, 0, 85,229, 0, 87,227, 0, + 91,223, 0, 97,218, 0,102,212, 0,109,204, 0,115,195, 0, + 120,183, 0,123,169, 4,124,152, 20,121,125, 63,114,104,197, + 115,107,129,115,107,129,120,122, 70,122,130, 53,123,137, 41, + 123,141, 34,124,147, 26,124,149, 24,124,143, 31,122,135, 44, + 121,125, 63,119,119, 77,118,117, 85,121,127, 58,123,141, 34, + 124,157, 15,124,167, 6,123,173, 1,122,177, 0,122,178, 0, + 122,177, 0,121,179, 0,121,182, 0,120,183, 0,121,180, 0, + 123,171, 3,123,170, 3,123,168, 5,124,165, 8,124,165, 8, + 124,162, 10,124,158, 13,124,149, 24,124,145, 29,124,155, 16, + 123,169, 4,122,176, 0,120,182, 0,118,189, 0,113,199, 0, + 108,205, 0,105,209, 0,104,210, 0,105,209, 0,101,214, 0, + 95,219, 0, 93,221, 0, 93,222, 0, 94,221, 0, 95,219, 0, + 98,216, 0,102,212, 0,106,207, 0,110,202, 0,114,196, 0, + 117,191, 0,120,184, 0,121,181, 0,121,180, 0,121,180, 0, + 121,181, 0,121,181, 0,121,182, 0,121,181, 0,121,179, 0, + 122,176, 0,123,168, 5,124,157, 15,123,137, 41,119,119, 77, + 121,125, 63,122,130, 53,122,130, 53,121,127, 58,124,143, 31, + 124,152, 20,124,155, 16,124,155, 16,124,162, 10,122,175, 0, + 120,184, 0,118,189, 0,117,192, 0,116,193, 0,117,191, 0, + 118,188, 0,120,183, 0,122,176, 0,124,167, 6,124,164, 9, + 123,168, 5,123,171, 3,123,173, 1,123,171, 3,124,165, 8, + 124,152, 20,124,160, 12,123,168, 5,122,176, 0,120,183, 0, + 117,190, 0,114,197, 0,110,203, 0,106,208, 0,103,211, 0, + 102,212, 0,102,212, 0,103,211, 0,105,209, 0,106,207, 0, + 108,205, 0,107,207, 0,106,208, 0,104,210, 0,101,214, 0, + 98,217, 0, 97,218, 0, 97,217, 0,101,214, 0,105,209, 0, + 111,202, 0,116,192, 0,121,179, 0,124,157, 15,121,127, 58, + 123,141, 34,124,150, 22,124,157, 15,124,162, 10,123,169, 4, + 122,175, 0,122,176, 0,123,174, 1,119,187, 0,115,195, 0, + 112,200, 0,109,204, 0,108,206, 0,108,205, 0,111,201, 0, + 115,195, 0,119,186, 0,122,175, 0,123,168, 5,124,166, 7, + 124,166, 7,123,171, 3,123,174, 1,122,177, 0,122,178, 0, + 121,182, 0,120,182, 0,121,179, 0,123,173, 1,124,164, 9, + 124,160, 12,124,162, 10,124,160, 12,124,167, 6,123,171, 3, + 123,168, 5,124,158, 13,122,135, 44,117,110,109,102, 80,250, + 111, 96,248,111, 96,248,119,119, 77,123,141, 34,124,160, 12, + 123,171, 3,121,180, 0,119,186, 0,118,189, 0,118,188, 0, + 120,184, 0,121,180, 0,123,172, 2,124,161, 11,124,161, 11, + 124,161, 11,124,164, 9,123,171, 3,123,173, 1,124,166, 7, + 124,147, 26,118,114, 96,111, 96,248,107, 89,252,121,125, 63, + 124,145, 29,124,154, 18,122,176, 0,119,187, 0,116,193, 0, + 114,196, 0,114,196, 0,113,198, 0,111,201, 0,111,202, 0, + 111,201, 0,112,200, 0,113,198, 0,110,202, 0,109,204, 0, + 108,206, 0,107,207, 0,107,207, 0,107,207, 0,108,206, 0, + 108,205, 0,107,207, 0,106,208, 0,106,208, 0,106,208, 0, + 109,204, 0,114,197, 0,119,185, 0,123,174, 1,123,171, 3, + 124,165, 8,124,166, 7,124,162, 10,124,152, 20,123,137, 41, + 124,157, 15,122,178, 0,117,191, 0,112,199, 0,108,205, 0, + 104,210, 0,101,214, 0, 97,217, 0, 94,220, 0, 92,222, 0, + 90,224, 0, 89,225, 0, 88,226, 0, 88,226, 0, 87,227, 0, + 85,228, 0, 84,229, 0, 83,230, 0, 83,230, 0, 84,229, 0, + 87,227, 0, 90,224, 0, 94,220, 0,100,215, 0,105,209, 0, + 111,201, 0,117,190, 0,122,176, 0,124,158, 13,123,139, 37, + 118,117, 85,121,127, 58,122,135, 44,123,137, 41,123,137, 41, + 123,137, 41,123,139, 37,123,141, 34,123,139, 37,122,132, 48, + 119,119, 77,121,125, 63,120,122, 70,117,110,109,121,125, 63, + 123,141, 34,124,155, 16,124,165, 8,123,170, 3,123,173, 1, + 123,173, 1,123,173, 1,123,174, 1,122,178, 0,121,182, 0, + 121,180, 0,123,174, 1,123,168, 5,124,167, 6,123,169, 4, + 123,171, 3,123,172, 2,123,170, 3,124,165, 8,124,161, 11, + 124,160, 12,124,165, 8,123,173, 1,120,184, 0,116,193, 0, + 110,202, 0,106,208, 0,102,212, 0,101,214, 0,102,213, 0, + 98,217, 0, 92,223, 0, 89,226, 0, 89,226, 0, 90,225, 0, + 92,222, 0, 95,220, 0, 99,215, 0,103,211, 0,107,206, 0, + 110,202, 0,113,199, 0,115,194, 0,118,188, 0,119,185, 0, + 119,186, 0,118,188, 0,118,189, 0,117,191, 0,117,190, 0, + 118,188, 0,120,184, 0,122,178, 0,124,167, 6,124,154, 18, + 122,135, 44,121,125, 63,122,135, 44,123,137, 41,122,132, 48, + 124,145, 29,124,157, 15,124,162, 10,124,162, 10,123,168, 5, + 122,177, 0,120,182, 0,119,187, 0,117,190, 0,117,191, 0, + 117,191, 0,117,190, 0,119,186, 0,121,182, 0,123,174, 1, + 123,170, 3,123,174, 1,122,177, 0,122,178, 0,122,177, 0, + 123,172, 2,124,162, 10,123,168, 5,123,174, 1,121,180, 0, + 119,186, 0,117,192, 0,113,198, 0,109,204, 0,105,209, 0, + 101,213, 0, 99,215, 0, 99,216, 0,100,215, 0,102,212, 0, + 105,209, 0,107,207, 0,109,203, 0,108,206, 0,103,211, 0, + 100,215, 0, 98,217, 0, 97,218, 0, 98,217, 0,101,214, 0, + 106,208, 0,111,201, 0,117,192, 0,122,178, 0,124,152, 20, + 123,141, 34,124,152, 20,124,160, 12,124,164, 9,124,166, 7, + 124,165, 8,123,170, 3,123,171, 3,123,168, 5,120,182, 0, + 117,192, 0,113,198, 0,110,202, 0,109,204, 0,109,204, 0, + 111,201, 0,115,194, 0,119,186, 0,122,176, 0,123,174, 1, + 123,171, 3,124,167, 6,124,162, 10,124,167, 6,123,170, 3, + 123,174, 1,122,178, 0,121,182, 0,121,181, 0,122,177, 0, + 123,171, 3,124,165, 8,123,168, 5,123,168, 5,122,176, 0, + 121,180, 0,122,178, 0,123,169, 4,124,152, 20,122,132, 48, + 117,110,109,115,107,129,118,114, 96,118,117, 85,123,139, 37, + 124,157, 15,123,169, 4,121,179, 0,119,185, 0,118,189, 0, + 118,189, 0,118,188, 0,120,184, 0,122,178, 0,123,168, 5, + 124,150, 22,124,149, 24,124,152, 20,124,164, 9,124,165, 8, + 124,155, 16,122,130, 53,107, 89,252,102, 80,250,115,107,129, + 123,137, 41,124,152, 20,124,161, 11,122,178, 0,119,186, 0, + 117,191, 0,116,193, 0,115,195, 0,113,199, 0,112,200, 0, + 112,199, 0,113,198, 0,114,196, 0,113,198, 0,110,202, 0, + 108,205, 0,107,206, 0,108,205, 0,108,205, 0,108,205, 0, + 108,205, 0,109,203, 0,111,201, 0,110,202, 0,109,203, 0, + 109,203, 0,111,201, 0,115,194, 0,120,184, 0,123,169, 4, + 123,168, 5,124,164, 9,123,169, 4,123,168, 5,124,160, 12, + 124,150, 22,123,168, 5,121,179, 0,118,188, 0,114,197, 0, + 110,203, 0,106,207, 0,103,212, 0,100,215, 0, 97,217, 0, + 95,220, 0, 92,222, 0, 91,224, 0, 89,225, 0, 88,226, 0, + 87,227, 0, 86,228, 0, 85,228, 0, 85,229, 0, 85,229, 0, + 86,228, 0, 89,226, 0, 91,223, 0, 95,220, 0, 99,215, 0, + 103,211, 0,109,204, 0,114,196, 0,120,184, 0,123,168, 5, + 124,149, 24,122,135, 44,123,141, 34,124,152, 20,124,157, 15, + 124,157, 15,124,154, 18,124,147, 26,124,143, 31,122,135, 44, + 120,122, 70,122,132, 48,123,137, 41,122,130, 53,119,119, 77, + 117,110,109,122,132, 48,124,149, 24,124,157, 15,124,162, 10, + 124,165, 8,124,165, 8,124,165, 8,124,167, 6,123,174, 1, + 121,179, 0,121,180, 0,122,178, 0,123,169, 4,124,162, 10, + 124,167, 6,123,171, 3,123,174, 1,123,173, 1,123,170, 3, + 124,167, 6,124,167, 6,123,170, 3,122,177, 0,119,185, 0, + 115,194, 0,109,203, 0,104,210, 0,100,214, 0, 98,216, 0, + 98,216, 0, 97,218, 0, 91,223, 0, 87,227, 0, 87,227, 0, + 88,226, 0, 91,223, 0, 94,220, 0, 98,216, 0,102,212, 0, + 106,208, 0,108,206, 0,109,203, 0,112,200, 0,114,196, 0, + 118,189, 0,118,188, 0,117,190, 0,116,193, 0,115,194, 0, + 116,193, 0,117,191, 0,119,186, 0,121,180, 0,123,171, 3, + 124,160, 12,124,145, 29,122,135, 44,122,135, 44,123,139, 37, + 123,137, 41,124,147, 26,124,160, 12,124,166, 7,124,165, 8, + 123,168, 5,123,174, 1,122,178, 0,120,182, 0,119,185, 0, + 118,188, 0,118,189, 0,118,189, 0,118,188, 0,120,184, 0, + 122,177, 0,123,171, 3,123,174, 1,122,176, 0,122,177, 0, + 122,176, 0,123,173, 1,124,165, 8,123,170, 3,122,176, 0, + 121,182, 0,119,186, 0,116,192, 0,113,198, 0,109,204, 0, + 103,211, 0,100,215, 0, 97,218, 0, 96,219, 0, 97,218, 0, + 100,215, 0,103,211, 0,107,207, 0,110,202, 0,108,205, 0, + 104,210, 0,101,214, 0, 99,216, 0, 99,216, 0,101,214, 0, + 104,210, 0,108,205, 0,113,198, 0,118,189, 0,122,175, 0, + 124,150, 22,124,145, 29,124,154, 18,124,158, 13,124,162, 10, + 124,165, 8,124,164, 9,124,164, 9,124,165, 8,124,161, 11, + 123,172, 2,119,185, 0,116,192, 0,113,198, 0,111,201, 0, + 111,201, 0,113,199, 0,116,193, 0,119,185, 0,122,176, 0, + 122,178, 0,122,176, 0,123,171, 3,124,165, 8,124,155, 16, + 124,157, 15,124,162, 10,123,170, 3,122,177, 0,122,178, 0, + 122,176, 0,123,173, 1,123,170, 3,123,171, 3,123,173, 1, + 121,180, 0,120,184, 0,120,183, 0,122,176, 0,124,162, 10, + 123,141, 34,120,122, 70,117,110,109,120,122, 70,121,125, 63, + 122,132, 48,124,157, 15,123,168, 5,122,175, 0,120,182, 0, + 119,187, 0,118,188, 0,118,188, 0,119,185, 0,121,180, 0, + 123,171, 3,124,157, 15,123,139, 37,123,137, 41,124,152, 20, + 124,154, 18,123,141, 34,118,114, 96, 87, 65,237,111, 96,248, + 118,117, 85,123,141, 34,124,155, 16,124,166, 7,121,179, 0, + 119,186, 0,118,189, 0,117,191, 0,115,195, 0,113,198, 0, + 114,197, 0,115,195, 0,116,193, 0,117,192, 0,114,196, 0, + 111,201, 0,109,204, 0,108,205, 0,109,204, 0,111,202, 0, + 110,203, 0,109,203, 0,110,202, 0,112,199, 0,115,194, 0, + 115,195, 0,114,196, 0,115,194, 0,118,189, 0,121,179, 0, + 124,165, 8,124,164, 9,124,160, 12,124,167, 6,124,167, 6, + 124,160, 12,124,164, 9,122,176, 0,120,184, 0,118,188, 0, + 116,192, 0,113,198, 0,110,202, 0,107,207, 0,105,209, 0, + 102,212, 0,100,215, 0, 97,218, 0, 95,220, 0, 93,222, 0, + 92,223, 0, 91,223, 0, 90,225, 0, 89,225, 0, 89,225, 0, + 90,225, 0, 91,223, 0, 93,222, 0, 95,219, 0, 98,217, 0, + 101,214, 0,104,210, 0,108,206, 0,113,199, 0,117,190, 0, + 122,178, 0,124,158, 13,124,147, 26,124,150, 22,124,161, 11, + 124,166, 7,124,166, 7,124,162, 10,124,154, 18,124,145, 29, + 122,130, 53,123,139, 37,124,149, 24,124,152, 20,124,145, 29, + 121,127, 58,113,100,242,118,114, 96,122,132, 48,124,143, 31, + 124,149, 24,124,150, 22,124,150, 22,124,157, 15,124,166, 7, + 123,170, 3,122,176, 0,121,180, 0,121,181, 0,122,176, 0, + 124,164, 9,124,160, 12,124,166, 7,123,170, 3,123,171, 3, + 123,169, 4,124,167, 6,124,167, 6,123,169, 4,122,176, 0, + 120,184, 0,116,193, 0,110,202, 0,104,210, 0,100,215, 0, + 97,218, 0, 96,219, 0, 97,218, 0, 92,222, 0, 89,226, 0, + 88,226, 0, 89,225, 0, 92,222, 0, 95,219, 0, 99,215, 0, + 103,212, 0,105,209, 0,107,207, 0,107,206, 0,109,204, 0, + 111,201, 0,114,196, 0,118,189, 0,118,189, 0,117,192, 0, + 116,193, 0,116,193, 0,117,190, 0,119,185, 0,122,178, 0, + 123,169, 4,124,158, 13,124,147, 26,123,139, 37,122,130, 53, + 123,137, 41,123,137, 41,124,149, 24,124,161, 11,124,167, 6, + 124,165, 8,124,165, 8,123,169, 4,122,175, 0,120,183, 0, + 119,186, 0,119,185, 0,119,185, 0,118,188, 0,118,188, 0, + 120,184, 0,122,178, 0,124,167, 6,124,167, 6,123,169, 4, + 123,169, 4,123,169, 4,124,167, 6,124,161, 11,124,167, 6, + 123,174, 1,121,180, 0,119,186, 0,116,192, 0,113,198, 0, + 109,204, 0,103,211, 0, 98,216, 0, 95,220, 0, 94,221, 0, + 95,220, 0, 98,217, 0,102,212, 0,106,207, 0,109,204, 0, + 108,205, 0,105,209, 0,103,212, 0,102,212, 0,103,212, 0, + 105,209, 0,108,205, 0,112,200, 0,116,193, 0,120,184, 0, + 123,171, 3,124,150, 22,123,141, 34,124,147, 26,124,150, 22, + 124,154, 18,124,158, 13,124,158, 13,124,154, 18,124,155, 16, + 124,152, 20,124,152, 20,123,172, 2,120,183, 0,117,191, 0, + 114,196, 0,114,197, 0,115,195, 0,117,190, 0,120,182, 0, + 122,177, 0,121,179, 0,122,178, 0,123,174, 1,124,167, 6, + 124,158, 13,124,149, 24,123,141, 34,124,155, 16,124,166, 7, + 123,170, 3,123,172, 2,123,171, 3,123,171, 3,123,172, 2, + 122,175, 0,121,182, 0,119,186, 0,119,185, 0,121,180, 0, + 123,168, 5,124,147, 26,121,127, 58,114,104,197,119,119, 77, + 120,122, 70,123,141, 34,124,160, 12,123,172, 2,122,178, 0, + 121,179, 0,121,182, 0,120,184, 0,120,184, 0,120,183, 0, + 121,179, 0,123,172, 2,124,160, 12,123,137, 41,121,125, 63, + 123,137, 41,123,139, 37,121,125, 63,109, 92,251,105, 84,252, + 117,110,109,121,125, 63,123,141, 34,124,154, 18,123,169, 4, + 121,180, 0,119,186, 0,118,188, 0,118,189, 0,116,192, 0, + 115,194, 0,116,192, 0,118,189, 0,119,187, 0,119,185, 0, + 116,193, 0,113,198, 0,111,202, 0,110,202, 0,111,201, 0, + 113,198, 0,112,200, 0,111,202, 0,111,201, 0,113,198, 0, + 116,193, 0,119,186, 0,119,186, 0,120,184, 0,121,180, 0, + 123,172, 2,124,160, 12,124,155, 16,124,152, 20,124,162, 10, + 124,162, 10,124,160, 12,123,172, 2,121,181, 0,119,186, 0, + 118,188, 0,118,188, 0,117,191, 0,115,195, 0,112,200, 0, + 110,203, 0,107,207, 0,104,210, 0,102,212, 0,100,215, 0, + 98,217, 0, 97,218, 0, 96,219, 0, 95,219, 0, 95,220, 0, + 95,220, 0, 96,219, 0, 97,217, 0, 99,216, 0,101,214, 0, + 102,212, 0,104,210, 0,106,208, 0,108,205, 0,112,200, 0, + 116,192, 0,120,182, 0,124,167, 6,124,157, 15,124,157, 15, + 124,167, 6,123,172, 2,123,171, 3,124,166, 7,124,155, 16, + 123,141, 34,123,137, 41,124,152, 20,124,160, 12,124,162, 10, + 124,157, 15,123,141, 34,117,110,109,107, 89,252,117,110,109, + 120,122, 70,121,127, 58,122,130, 53,122,135, 44,124,152, 20, + 124,164, 9,123,168, 5,123,174, 1,121,181, 0,120,184, 0, + 121,182, 0,123,174, 1,124,164, 9,124,154, 18,124,161, 11, + 124,164, 9,124,162, 10,124,161, 11,124,161, 11,123,169, 4, + 122,177, 0,121,182, 0,117,190, 0,112,200, 0,106,208, 0, + 100,214, 0, 96,219, 0, 94,220, 0, 94,220, 0, 96,219, 0, + 92,222, 0, 91,223, 0, 92,222, 0, 95,220, 0, 98,217, 0, + 101,214, 0,102,212, 0,105,209, 0,107,207, 0,107,207, 0, + 108,206, 0,109,204, 0,111,201, 0,114,196, 0,118,189, 0, + 118,188, 0,117,190, 0,118,189, 0,119,186, 0,121,180, 0, + 123,172, 2,124,162, 10,124,152, 20,123,141, 34,123,137, 41, + 122,130, 53,122,130, 53,122,135, 44,124,152, 20,124,164, 9, + 124,167, 6,124,164, 9,124,160, 12,123,170, 3,120,184, 0, + 117,191, 0,115,194, 0,115,194, 0,117,191, 0,120,184, 0, + 119,186, 0,120,183, 0,122,177, 0,124,165, 8,124,154, 18, + 124,155, 16,124,155, 16,124,155, 16,124,154, 18,124,149, 24, + 124,160, 12,123,169, 4,122,178, 0,118,189, 0,114,197, 0, + 111,202, 0,109,204, 0,103,211, 0, 98,217, 0, 94,221, 0, + 92,222, 0, 94,221, 0, 97,218, 0,102,212, 0,107,207, 0, + 107,207, 0,107,207, 0,107,207, 0,106,208, 0,106,208, 0, + 108,205, 0,111,202, 0,114,197, 0,117,192, 0,119,186, 0, + 122,178, 0,124,167, 6,124,152, 20,122,132, 48,122,130, 53, + 122,130, 53,122,135, 44,124,143, 31,124,147, 26,124,145, 29, + 123,141, 34,123,141, 34,122,135, 44,124,147, 26,123,168, 5, + 121,181, 0,118,188, 0,117,191, 0,117,190, 0,119,186, 0, + 121,179, 0,122,175, 0,122,178, 0,122,178, 0,123,174, 1, + 123,168, 5,124,167, 6,124,164, 9,124,155, 16,124,143, 31, + 124,149, 24,124,158, 13,124,164, 9,124,166, 7,124,167, 6, + 123,172, 2,122,177, 0,122,178, 0,120,184, 0,120,184, 0, + 121,181, 0,123,172, 2,124,155, 16,121,125, 63,105, 84,252, + 113,100,242,122,132, 48,124,154, 18,124,165, 8,122,177, 0, + 120,182, 0,120,184, 0,121,182, 0,122,178, 0,122,178, 0, + 122,178, 0,122,176, 0,123,171, 3,124,161, 11,124,143, 31, + 122,130, 53,118,117, 85,120,122, 70,115,107,129,102, 80,250, + 113,100,242,119,119, 77,122,130, 53,123,137, 41,124,149, 24, + 123,171, 3,121,181, 0,119,185, 0,119,187, 0,119,186, 0, + 119,186, 0,118,188, 0,119,185, 0,119,186, 0,120,184, 0, + 120,182, 0,119,187, 0,116,192, 0,114,196, 0,114,197, 0, + 115,194, 0,114,196, 0,113,198, 0,113,199, 0,113,198, 0, + 115,195, 0,118,189, 0,121,182, 0,123,171, 3,123,171, 3, + 123,168, 5,124,162, 10,124,152, 20,124,143, 31,123,141, 34, + 124,154, 18,124,154, 18,123,168, 5,122,178, 0,120,184, 0, + 119,186, 0,119,186, 0,120,184, 0,121,182, 0,119,187, 0, + 114,197, 0,109,204, 0,105,209, 0,102,213, 0,100,214, 0, + 100,215, 0,101,214, 0,102,213, 0,101,213, 0,101,214, 0, + 101,214, 0,102,213, 0,102,212, 0,104,210, 0,105,209, 0, + 107,207, 0,108,205, 0,108,205, 0,109,203, 0,111,202, 0, + 113,198, 0,117,192, 0,120,183, 0,123,169, 4,124,167, 6, + 124,166, 7,123,171, 3,123,174, 1,123,172, 2,124,165, 8, + 124,152, 20,122,135, 44,124,147, 26,124,160, 12,124,167, 6, + 123,168, 5,124,162, 10,124,149, 24,120,122, 70,102, 80,250, + 107, 89,252,111, 96,248,114,104,197,117,110,109,118,117, 85, + 123,141, 34,124,155, 16,124,160, 12,123,173, 1,120,182, 0, + 119,186, 0,119,186, 0,121,181, 0,123,171, 3,124,161, 11, + 124,147, 26,124,150, 22,124,150, 22,124,152, 20,124,161, 11, + 123,170, 3,122,177, 0,121,182, 0,120,184, 0,115,195, 0, + 108,205, 0,102,212, 0, 97,217, 0, 94,220, 0, 94,221, 0, + 94,220, 0, 96,219, 0, 95,220, 0, 96,219, 0, 98,217, 0, + 98,217, 0, 99,215, 0,101,214, 0,104,210, 0,108,205, 0, + 108,205, 0,108,205, 0,109,204, 0,110,202, 0,113,198, 0, + 116,193, 0,118,188, 0,120,184, 0,120,184, 0,121,180, 0, + 122,177, 0,123,173, 1,123,168, 5,124,160, 12,124,147, 26, + 121,127, 58,119,119, 77,119,119, 77,123,141, 34,124,157, 15, + 124,165, 8,124,167, 6,124,162, 10,124,155, 16,122,176, 0, + 118,189, 0,114,197, 0,112,200, 0,111,201, 0,113,198, 0, + 117,192, 0,119,185, 0,120,182, 0,122,175, 0,124,162, 10, + 123,137, 41,124,143, 31,124,150, 22,124,149, 24,122,135, 44, + 122,130, 53,124,150, 22,123,168, 5,120,183, 0,116,192, 0, + 112,199, 0,110,203, 0,109,204, 0,103,212, 0, 97,217, 0, + 93,221, 0, 92,223, 0, 93,221, 0, 97,218, 0,102,212, 0, + 107,206, 0,106,207, 0,106,208, 0,107,207, 0,109,204, 0, + 110,202, 0,113,198, 0,116,193, 0,118,188, 0,120,184, 0, + 122,178, 0,123,171, 3,124,164, 9,124,154, 18,123,139, 37, + 120,122, 70,111, 96,248,114,104,197,118,117, 85,121,127, 58, + 121,127, 58,119,119, 77,119,119, 77,118,114, 96,114,104,197, + 124,143, 31,124,167, 6,122,178, 0,120,184, 0,119,185, 0, + 120,182, 0,122,176, 0,123,169, 4,122,175, 0,122,176, 0, + 123,173, 1,123,171, 3,123,173, 1,123,172, 2,124,166, 7, + 124,152, 20,124,150, 22,123,141, 34,124,147, 26,124,154, 18, + 124,161, 11,123,171, 3,122,178, 0,121,180, 0,122,178, 0, + 121,181, 0,121,179, 0,123,173, 1,124,161, 11,123,141, 34, + 115,107,129,120,122, 70,124,147, 26,124,164, 9,123,172, 2, + 121,179, 0,120,184, 0,119,185, 0,120,184, 0,121,180, 0, + 123,172, 2,123,169, 4,123,168, 5,124,165, 8,124,157, 15, + 124,143, 31,123,139, 37,122,130, 53,118,117, 85,114,104,197, + 107, 89,252,114,104,197,120,122, 70,122,132, 48,122,135, 44, + 124,147, 26,123,168, 5,122,178, 0,120,182, 0,120,184, 0, + 120,184, 0,120,182, 0,121,182, 0,121,182, 0,120,182, 0, + 121,181, 0,121,182, 0,119,187, 0,117,191, 0,116,192, 0, + 116,193, 0,115,194, 0,115,194, 0,114,196, 0,114,196, 0, + 116,193, 0,118,189, 0,120,182, 0,123,172, 2,124,158, 13, + 124,154, 18,124,152, 20,124,147, 26,123,139, 37,122,132, 48, + 122,130, 53,124,145, 29,124,157, 15,123,169, 4,122,178, 0, + 120,182, 0,120,184, 0,120,182, 0,121,179, 0,122,178, 0, + 118,188, 0,113,198, 0,108,205, 0,104,210, 0,101,214, 0, + 99,215, 0, 99,216, 0,100,215, 0,101,214, 0,102,213, 0, + 103,211, 0,104,210, 0,105,209, 0,106,208, 0,107,207, 0, + 107,206, 0,108,205, 0,110,202, 0,113,199, 0,113,198, 0, + 114,197, 0,115,194, 0,118,189, 0,121,180, 0,122,176, 0, + 123,174, 1,123,172, 2,123,172, 2,123,173, 1,123,169, 4, + 124,158, 13,123,141, 34,124,147, 26,124,157, 15,124,165, 8, + 123,170, 3,123,170, 3,124,166, 7,124,154, 18,122,132, 48, + 114,104,197,105, 84,252, 87, 65,237, 99, 75,247,107, 89,252, + 114,104,197,121,127, 58,124,147, 26,124,164, 9,122,177, 0, + 119,185, 0,118,189, 0,118,189, 0,119,185, 0,122,175, 0, + 124,166, 7,124,154, 18,124,147, 26,124,147, 26,124,150, 22, + 124,158, 13,124,166, 7,123,174, 1,122,177, 0,121,179, 0, + 117,190, 0,111,201, 0,105,209, 0,100,215, 0, 97,218, 0, + 95,220, 0, 95,220, 0, 96,219, 0, 97,218, 0, 97,217, 0, + 98,217, 0, 98,216, 0,100,215, 0,102,212, 0,106,208, 0, + 110,203, 0,110,203, 0,110,203, 0,110,202, 0,111,201, 0, + 113,198, 0,115,194, 0,118,189, 0,119,187, 0,119,186, 0, + 120,184, 0,121,182, 0,122,178, 0,123,173, 1,124,166, 7, + 124,155, 16,123,139, 37,120,122, 70,122,130, 53,124,150, 22, + 124,162, 10,124,167, 6,124,167, 6,124,162, 10,124,161, 11, + 121,180, 0,117,192, 0,112,200, 0,109,204, 0,108,205, 0, + 110,203, 0,113,199, 0,116,193, 0,119,187, 0,121,181, 0, + 123,172, 2,124,160, 12,124,147, 26,124,154, 18,124,155, 16, + 124,145, 29,122,132, 48,124,157, 15,123,174, 1,119,186, 0, + 115,194, 0,112,200, 0,109,203, 0,108,205, 0,102,212, 0, + 97,218, 0, 93,221, 0, 92,222, 0, 94,221, 0, 98,217, 0, + 103,212, 0,107,206, 0,107,206, 0,107,207, 0,108,205, 0, + 110,202, 0,114,196, 0,117,191, 0,119,187, 0,119,187, 0, + 120,184, 0,121,179, 0,123,170, 3,124,158, 13,124,152, 20, + 124,145, 29,122,135, 44,120,122, 70,113,100,242,118,117, 85, + 121,127, 58,121,127, 58,119,119, 77,113,100,242,102, 80,250, + 69, 60,230,111, 96,248,123,141, 34,124,164, 9,123,174, 1, + 122,178, 0,122,178, 0,123,174, 1,123,169, 4,124,167, 6, + 123,169, 4,123,172, 2,122,176, 0,122,178, 0,122,178, 0, + 123,173, 1,124,164, 9,124,157, 15,124,147, 26,121,125, 63, + 123,137, 41,124,158, 13,123,171, 3,122,178, 0,121,181, 0, + 121,179, 0,122,175, 0,123,174, 1,123,170, 3,124,162, 10, + 124,149, 24,121,127, 58,122,135, 44,124,155, 16,123,168, 5, + 122,176, 0,121,179, 0,120,183, 0,120,184, 0,120,183, 0, + 121,180, 0,123,172, 2,124,157, 15,124,154, 18,124,152, 20, + 124,147, 26,124,145, 29,124,147, 26,123,139, 37,121,127, 58, + 118,114, 96,109, 92,251,111, 96,248,118,117, 85,122,130, 53, + 123,137, 41,123,137, 41,124,160, 12,123,170, 3,122,175, 0, + 122,177, 0,122,177, 0,122,175, 0,123,174, 1,123,174, 1, + 123,174, 1,123,174, 1,122,178, 0,119,185, 0,118,189, 0, + 117,192, 0,116,193, 0,116,193, 0,116,193, 0,116,193, 0, + 116,192, 0,116,192, 0,118,189, 0,121,182, 0,123,168, 5, + 124,147, 26,122,130, 53,122,130, 53,121,127, 58,119,119, 77, + 118,117, 85,119,119, 77,123,137, 41,124,150, 22,124,165, 8, + 123,174, 1,122,178, 0,122,178, 0,122,175, 0,123,174, 1, + 120,184, 0,117,191, 0,112,199, 0,107,206, 0,103,211, 0, + 100,214, 0, 99,216, 0, 98,216, 0, 99,216, 0,100,215, 0, + 101,213, 0,103,211, 0,105,209, 0,107,207, 0,108,205, 0, + 110,203, 0,111,202, 0,112,200, 0,113,198, 0,115,194, 0, + 116,193, 0,116,192, 0,117,190, 0,119,185, 0,121,180, 0, + 121,179, 0,122,178, 0,122,175, 0,123,169, 4,123,168, 5, + 124,161, 11,124,145, 29,124,147, 26,124,155, 16,124,161, 11, + 124,167, 6,123,171, 3,123,171, 3,124,167, 6,124,158, 13, + 124,143, 31,121,125, 63,111, 96,248, 30, 55,222, 30, 26,168, + 30, 55,222,111, 96,248,122,130, 53,124,152, 20,123,168, 5, + 121,180, 0,118,188, 0,117,192, 0,117,192, 0,118,188, 0, + 121,180, 0,124,167, 6,124,157, 15,124,147, 26,124,143, 31, + 124,143, 31,124,150, 22,124,165, 8,123,172, 2,122,176, 0, + 122,178, 0,120,184, 0,115,195, 0,109,204, 0,104,210, 0, + 101,214, 0, 98,216, 0, 98,217, 0, 98,217, 0, 98,217, 0, + 98,216, 0, 99,215, 0,101,214, 0,103,212, 0,106,208, 0, + 109,204, 0,112,200, 0,112,200, 0,112,200, 0,113,199, 0, + 114,197, 0,115,194, 0,117,192, 0,118,189, 0,118,188, 0, + 119,187, 0,119,186, 0,120,183, 0,121,179, 0,123,173, 1, + 124,166, 7,124,155, 16,123,141, 34,121,127, 58,123,139, 37, + 124,155, 16,124,165, 8,123,168, 5,124,167, 6,124,165, 8, + 124,167, 6,120,184, 0,115,195, 0,110,203, 0,106,207, 0, + 105,209, 0,106,208, 0,108,205, 0,111,201, 0,114,196, 0, + 117,191, 0,119,185, 0,122,177, 0,124,165, 8,124,158, 13, + 124,160, 12,124,154, 18,124,147, 26,124,167, 6,121,180, 0, + 117,190, 0,114,197, 0,111,201, 0,109,204, 0,108,205, 0, + 103,212, 0, 98,217, 0, 94,221, 0, 93,221, 0, 95,220, 0, + 98,217, 0,103,212, 0,107,207, 0,110,203, 0,110,203, 0, + 110,202, 0,113,199, 0,116,193, 0,119,186, 0,120,184, 0, + 119,185, 0,120,183, 0,122,178, 0,123,170, 3,124,160, 12, + 124,143, 31,123,141, 34,123,137, 41,122,130, 53,118,114, 96, + 121,125, 63,122,135, 44,123,141, 34,123,141, 34,122,130, 53, + 118,117, 85,114,104,197, 87, 65,237,114,104,197,122,132, 48, + 124,157, 15,124,167, 6,123,171, 3,123,171, 3,123,168, 5, + 123,168, 5,123,170, 3,122,175, 0,122,178, 0,121,182, 0, + 120,182, 0,121,180, 0,123,173, 1,124,164, 9,124,155, 16, + 124,147, 26,123,139, 37,124,157, 15,123,171, 3,122,178, 0, + 122,178, 0,122,178, 0,123,174, 1,124,167, 6,124,166, 7, + 124,160, 12,124,150, 22,123,137, 41,123,139, 37,124,158, 13, + 123,169, 4,122,175, 0,122,178, 0,122,178, 0,121,180, 0, + 121,179, 0,122,177, 0,123,170, 3,124,154, 18,122,130, 53, + 122,130, 53,122,132, 48,124,149, 24,124,154, 18,124,147, 26, + 122,135, 44,119,119, 77,115,107,129,102, 80,250,111, 96,248, + 119,119, 77,122,132, 48,123,137, 41,124,143, 31,124,155, 16, + 124,161, 11,124,162, 10,124,164, 9,124,165, 8,124,162, 10, + 124,160, 12,124,161, 11,124,161, 11,123,172, 2,121,180, 0, + 119,186, 0,118,189, 0,117,191, 0,117,191, 0,118,189, 0, + 116,192, 0,115,194, 0,115,194, 0,117,191, 0,120,184, 0, + 123,173, 1,124,155, 16,124,149, 24,122,135, 44,113,100,242, + 109, 92,251,111, 96,248,117,110,109,122,130, 53,123,139, 37, + 124,154, 18,124,166, 7,123,170, 3,123,170, 3,124,166, 7, + 122,177, 0,119,186, 0,117,191, 0,112,200, 0,108,206, 0, + 104,210, 0,101,213, 0,100,215, 0, 99,215, 0,100,215, 0, + 101,214, 0,102,212, 0,103,211, 0,104,210, 0,106,208, 0, + 108,206, 0,110,202, 0,113,198, 0,116,193, 0,117,191, 0, + 118,188, 0,118,189, 0,118,188, 0,119,186, 0,121,181, 0, + 121,179, 0,121,179, 0,122,178, 0,123,174, 1,124,166, 7, + 124,158, 13,124,147, 26,123,137, 41,124,154, 18,124,160, 12, + 124,162, 10,124,166, 7,123,168, 5,123,168, 5,124,165, 8, + 124,160, 12,124,150, 22,123,137, 41,120,122, 70,109, 92,251, + 30, 37,192, 30, 20,155,107, 89,252,122,130, 53,124,155, 16, + 123,170, 3,121,182, 0,118,189, 0,116,193, 0,116,193, 0, + 117,190, 0,120,182, 0,124,167, 6,124,154, 18,123,141, 34, + 122,130, 53,121,125, 63,124,147, 26,124,162, 10,123,170, 3, + 122,178, 0,120,183, 0,118,188, 0,118,189, 0,114,196, 0, + 110,202, 0,106,207, 0,103,211, 0,102,213, 0,101,214, 0, + 101,214, 0,101,214, 0,102,212, 0,104,210, 0,107,207, 0, + 110,202, 0,113,198, 0,114,197, 0,115,195, 0,115,194, 0, + 117,192, 0,117,190, 0,118,188, 0,119,186, 0,120,184, 0, + 120,184, 0,119,185, 0,120,184, 0,121,181, 0,122,176, 0, + 123,169, 4,124,160, 12,124,147, 26,122,132, 48,121,125, 63, + 124,147, 26,124,161, 11,123,168, 5,123,170, 3,124,167, 6, + 123,170, 3,123,173, 1,119,186, 0,114,197, 0,108,205, 0, + 105,209, 0,103,212, 0,103,212, 0,105,209, 0,107,206, 0, + 110,203, 0,113,199, 0,115,194, 0,119,187, 0,122,178, 0, + 124,162, 10,124,161, 11,124,155, 16,124,157, 15,123,173, 1, + 120,184, 0,116,192, 0,113,198, 0,110,202, 0,109,204, 0, + 109,204, 0,103,211, 0, 99,215, 0, 96,219, 0, 95,220, 0, + 97,218, 0,100,215, 0,103,211, 0,107,207, 0,110,202, 0, + 113,199, 0,113,198, 0,115,195, 0,117,190, 0,120,183, 0, + 120,182, 0,121,181, 0,121,180, 0,122,177, 0,123,170, 3, + 124,161, 11,124,147, 26,122,130, 53,122,130, 53,121,127, 58, + 119,119, 77,122,130, 53,123,141, 34,124,149, 24,124,152, 20, + 124,150, 22,124,143, 31,122,132, 48,118,114, 96,114,104,197, + 120,122, 70,122,132, 48,124,147, 26,124,160, 12,124,165, 8, + 124,165, 8,124,166, 7,123,170, 3,122,175, 0,121,179, 0, + 120,183, 0,120,184, 0,120,184, 0,121,181, 0,122,176, 0, + 123,171, 3,124,167, 6,124,162, 10,124,152, 20,124,167, 6, + 122,176, 0,123,172, 2,123,172, 2,123,169, 4,124,164, 9, + 124,158, 13,124,154, 18,124,147, 26,123,137, 41,122,135, 44, + 124,154, 18,124,165, 8,123,169, 4,123,171, 3,123,169, 4, + 123,170, 3,123,170, 3,123,168, 5,124,162, 10,124,145, 29, + 117,110,109,111, 96,248,123,137, 41,124,154, 18,124,158, 13, + 124,154, 18,123,141, 34,124,143, 31,123,137, 41,119,119, 77, + 115,107,129,118,114, 96,121,125, 63,123,137, 41,123,139, 37, + 124,143, 31,124,150, 22,124,154, 18,124,155, 16,124,154, 18, + 124,150, 22,124,145, 29,123,139, 37,124,143, 31,124,161, 11, + 123,172, 2,121,180, 0,120,184, 0,119,186, 0,119,186, 0, + 119,187, 0,117,192, 0,115,194, 0,115,194, 0,117,192, 0, + 119,186, 0,122,177, 0,124,166, 7,124,164, 9,124,152, 20, + 121,127, 58,102, 80,250, 94, 70,242,113,100,242,118,117, 85, + 122,130, 53,123,137, 41,124,152, 20,124,160, 12,124,160, 12, + 124,164, 9,122,175, 0,120,184, 0,118,189, 0,113,198, 0, + 109,203, 0,106,207, 0,104,210, 0,103,212, 0,102,212, 0, + 102,212, 0,103,212, 0,103,211, 0,102,213, 0,102,212, 0, + 103,211, 0,106,208, 0,108,205, 0,111,201, 0,114,196, 0, + 117,191, 0,119,185, 0,120,184, 0,120,184, 0,121,182, 0, + 122,177, 0,122,175, 0,122,177, 0,122,175, 0,123,170, 3, + 124,158, 13,124,143, 31,121,127, 58,123,141, 34,124,154, 18, + 124,157, 15,124,155, 16,124,157, 15,124,158, 13,124,158, 13, + 124,157, 15,124,154, 18,124,149, 24,124,143, 31,122,132, 48, + 117,110,109, 94, 70,242, 30, 31,180, 94, 70,242,121,125, 63, + 124,154, 18,123,170, 3,121,181, 0,118,188, 0,116,193, 0, + 116,193, 0,117,190, 0,120,182, 0,124,167, 6,124,143, 31, + 121,125, 63,113,100,242,119,119, 77,124,152, 20,123,169, 4, + 122,178, 0,120,184, 0,118,188, 0,117,191, 0,117,191, 0, + 117,190, 0,117,192, 0,113,198, 0,110,202, 0,108,206, 0, + 106,208, 0,105,209, 0,105,209, 0,107,207, 0,109,204, 0, + 112,200, 0,115,194, 0,116,193, 0,117,192, 0,118,188, 0, + 119,185, 0,121,181, 0,122,177, 0,123,174, 1,123,173, 1, + 123,174, 1,122,177, 0,121,179, 0,122,178, 0,122,175, 0, + 123,168, 5,124,158, 13,124,145, 29,122,130, 53,119,119, 77, + 121,127, 58,124,152, 20,124,166, 7,123,172, 2,123,173, 1, + 123,169, 4,123,174, 1,122,177, 0,118,188, 0,113,198, 0, + 108,205, 0,104,210, 0,102,213, 0,101,213, 0,102,212, 0, + 105,209, 0,107,207, 0,109,204, 0,112,199, 0,116,193, 0, + 120,184, 0,123,170, 3,124,155, 16,124,150, 22,124,160, 12, + 122,175, 0,119,186, 0,115,194, 0,112,199, 0,110,202, 0, + 109,204, 0,109,204, 0,105,209, 0,101,214, 0, 98,216, 0, + 98,217, 0, 99,215, 0,102,212, 0,105,209, 0,108,205, 0, + 111,202, 0,114,197, 0,116,193, 0,117,191, 0,119,187, 0, + 121,181, 0,121,179, 0,122,178, 0,122,176, 0,123,173, 1, + 123,169, 4,124,162, 10,124,152, 20,123,139, 37,121,125, 63, + 119,119, 77,120,122, 70,122,132, 48,124,143, 31,124,150, 22, + 124,157, 15,124,160, 12,124,160, 12,124,155, 16,124,143, 31, + 118,114, 96,118,117, 85,121,127, 58,121,127, 58,123,137, 41, + 124,150, 22,124,155, 16,124,158, 13,124,165, 8,123,170, 3, + 122,177, 0,121,182, 0,119,185, 0,119,186, 0,119,185, 0, + 120,183, 0,121,181, 0,122,178, 0,123,174, 1,124,167, 6, + 124,160, 12,123,169, 4,124,161, 11,124,162, 10,124,161, 11, + 124,157, 15,124,150, 22,124,143, 31,123,137, 41,122,130, 53, + 120,122, 70,124,143, 31,124,154, 18,124,158, 13,124,158, 13, + 124,155, 16,124,152, 20,124,152, 20,124,152, 20,124,147, 26, + 121,125, 63,109, 92,251,115,107,129,124,143, 31,124,158, 13, + 124,164, 9,124,160, 12,124,157, 15,124,162, 10,124,161, 11, + 124,150, 22,121,127, 58,118,117, 85,118,117, 85,122,135, 44, + 123,141, 34,123,141, 34,123,141, 34,124,143, 31,124,143, 31, + 123,139, 37,122,132, 48,121,127, 58,120,122, 70,122,130, 53, + 124,143, 31,124,158, 13,123,169, 4,122,175, 0,122,177, 0, + 122,175, 0,120,182, 0,118,188, 0,117,192, 0,116,192, 0, + 117,191, 0,119,186, 0,122,178, 0,123,174, 1,123,173, 1, + 124,166, 7,124,149, 24,118,114, 96, 87, 65,237,102, 80,250, + 115,107,129,118,117, 85,119,119, 77,122,135, 44,124,145, 29, + 124,147, 26,124,154, 18,124,167, 6,122,178, 0,120,184, 0, + 116,193, 0,113,199, 0,110,202, 0,108,205, 0,107,207, 0, + 107,207, 0,107,207, 0,107,207, 0,104,210, 0,102,212, 0, + 101,213, 0,102,212, 0,104,210, 0,107,207, 0,108,205, 0, + 110,202, 0,113,198, 0,116,193, 0,119,186, 0,121,179, 0, + 122,178, 0,123,173, 1,124,167, 6,123,170, 3,123,168, 5, + 124,161, 11,124,145, 29,120,122, 70,118,114, 96,122,135, 44, + 124,147, 26,124,147, 26,123,141, 34,123,137, 41,123,137, 41, + 123,137, 41,123,139, 37,123,139, 37,123,141, 34,123,139, 37, + 122,132, 48,118,117, 85,113,100,242, 94, 70,242, 69, 60,230, + 118,114, 96,124,147, 26,124,165, 8,122,178, 0,119,186, 0, + 117,190, 0,117,191, 0,118,188, 0,121,179, 0,124,161, 11, + 121,125, 63,105, 84,252,102, 80,250,123,137, 41,124,165, 8, + 122,178, 0,119,185, 0,118,189, 0,117,192, 0,116,192, 0, + 117,191, 0,118,188, 0,120,184, 0,120,183, 0,117,190, 0, + 114,196, 0,112,200, 0,110,202, 0,110,202, 0,112,200, 0, + 114,196, 0,117,191, 0,118,188, 0,119,187, 0,120,184, 0, + 122,178, 0,123,169, 4,124,160, 12,124,150, 22,124,145, 29, + 124,145, 29,124,152, 20,124,161, 11,124,167, 6,124,167, 6, + 124,164, 9,124,154, 18,123,141, 34,120,122, 70,118,117, 85, + 115,107,129,122,132, 48,124,158, 13,123,170, 3,122,177, 0, + 122,177, 0,123,173, 1,123,174, 1,122,178, 0,119,187, 0, + 114,197, 0,109,204, 0,105,209, 0,102,212, 0,102,213, 0, + 102,212, 0,103,211, 0,105,209, 0,108,206, 0,111,201, 0, + 115,195, 0,119,186, 0,123,172, 2,124,149, 24,123,137, 41, + 124,154, 18,123,173, 1,119,186, 0,116,193, 0,113,199, 0, + 110,202, 0,110,203, 0,110,203, 0,107,207, 0,103,211, 0, + 102,213, 0,102,213, 0,103,211, 0,106,208, 0,108,205, 0, + 110,202, 0,112,199, 0,115,194, 0,118,189, 0,119,186, 0, + 120,184, 0,122,178, 0,123,172, 2,123,171, 3,123,171, 3, + 123,169, 4,124,166, 7,124,161, 11,124,154, 18,123,141, 34, + 121,127, 58,120,122, 70,121,125, 63,122,130, 53,123,139, 37, + 124,147, 26,124,155, 16,124,162, 10,124,167, 6,123,168, 5, + 124,165, 8,124,150, 22,121,125, 63,121,127, 58,121,125, 63, + 118,114, 96,120,122, 70,122,135, 44,123,141, 34,124,150, 22, + 124,160, 12,123,169, 4,122,176, 0,121,182, 0,119,185, 0, + 119,186, 0,119,186, 0,119,186, 0,120,184, 0,121,181, 0, + 123,173, 1,124,161, 11,124,155, 16,123,137, 41,124,143, 31, + 124,145, 29,124,147, 26,124,145, 29,123,137, 41,120,122, 70, + 118,117, 85,118,114, 96,120,122, 70,122,135, 44,123,137, 41, + 122,135, 44,121,127, 58,118,117, 85,118,117, 85,119,119, 77, + 118,117, 85,111, 96,248,118,117, 85,121,127, 58,124,150, 22, + 124,164, 9,123,168, 5,124,165, 8,123,170, 3,122,175, 0, + 122,175, 0,123,170, 3,124,155, 16,120,122, 70,118,114, 96, + 121,125, 63,123,139, 37,124,143, 31,123,141, 34,121,127, 58, + 119,119, 77,117,110,109,113,100,242,111, 96,248,118,114, 96, + 121,125, 63,121,127, 58,123,137, 41,124,149, 24,124,157, 15, + 124,160, 12,124,160, 12,123,171, 3,121,180, 0,119,186, 0, + 118,189, 0,118,189, 0,119,186, 0,121,180, 0,121,179, 0, + 122,178, 0,123,173, 1,124,161, 11,122,135, 44,113,100,242, + 99, 75,247,109, 92,251,114,104,197,109, 92,251,117,110,109, + 122,130, 53,123,137, 41,122,135, 44,124,149, 24,124,164, 9, + 122,175, 0,119,186, 0,117,192, 0,114,196, 0,113,198, 0, + 112,199, 0,112,200, 0,112,200, 0,111,201, 0,107,207, 0, + 104,210, 0,102,212, 0,102,212, 0,104,210, 0,106,208, 0, + 106,208, 0,107,206, 0,110,202, 0,113,199, 0,116,193, 0, + 119,186, 0,123,174, 1,123,168, 5,124,158, 13,124,158, 13, + 124,157, 15,124,147, 26,121,127, 58,107, 89,252,111, 96,248, + 119,119, 77,121,127, 58,120,122, 70,115,107,129,111, 96,248, + 107, 89,252,109, 92,251,113,100,242,117,110,109,118,117, 85, + 120,122, 70,119,119, 77,118,114, 96,117,110,109,109, 92,251, + 87, 65,237,111, 96,248,122,135, 44,124,157, 15,123,170, 3, + 121,180, 0,119,186, 0,119,186, 0,120,183, 0,123,173, 1, + 124,152, 20,114,104,197, 30, 20,155,114,104,197,124,154, 18, + 123,173, 1,120,184, 0,118,189, 0,117,192, 0,116,193, 0, + 116,193, 0,117,191, 0,119,186, 0,121,182, 0,122,176, 0, + 123,170, 3,121,182, 0,118,189, 0,116,192, 0,116,193, 0, + 117,191, 0,119,187, 0,121,180, 0,122,178, 0,122,176, 0, + 123,170, 3,124,158, 13,123,137, 41,122,130, 53,120,122, 70, + 115,107,129,107, 89,252,113,100,242,121,127, 58,124,143, 31, + 124,147, 26,123,141, 34,122,130, 53,117,110,109,115,107,129, + 117,110,109,121,125, 63,123,141, 34,124,164, 9,122,176, 0, + 121,181, 0,121,182, 0,122,178, 0,123,172, 2,122,175, 0, + 119,185, 0,115,195, 0,110,202, 0,107,207, 0,104,210, 0, + 103,211, 0,104,210, 0,105,209, 0,106,208, 0,108,205, 0, + 111,201, 0,115,194, 0,120,184, 0,123,168, 5,123,139, 37, + 114,104,197,123,141, 34,124,167, 6,120,182, 0,117,192, 0, + 113,198, 0,111,201, 0,110,202, 0,111,201, 0,109,204, 0, + 106,207, 0,106,208, 0,106,208, 0,108,206, 0,110,202, 0, + 113,199, 0,114,196, 0,115,194, 0,118,189, 0,120,184, 0, + 121,182, 0,121,180, 0,122,176, 0,123,168, 5,124,162, 10, + 124,164, 9,124,165, 8,124,164, 9,124,157, 15,124,149, 24, + 123,137, 41,121,125, 63,118,117, 85,118,117, 85,122,130, 53, + 124,149, 24,124,158, 13,124,162, 10,124,162, 10,123,168, 5, + 123,174, 1,123,174, 1,123,168, 5,124,155, 16,123,139, 37, + 122,135, 44,121,127, 58,115,107,129,120,122, 70,121,127, 58, + 123,137, 41,124,149, 24,124,160, 12,123,168, 5,122,175, 0, + 121,181, 0,120,184, 0,119,186, 0,119,187, 0,119,186, 0, + 120,182, 0,122,175, 0,124,161, 11,122,135, 44,111, 96,248, + 115,107,129,120,122, 70,122,132, 48,123,137, 41,123,137, 41, + 122,130, 53,118,114, 96,113,100,242,111, 96,248,115,107,129, + 115,107,129,113,100,242,105, 84,252,105, 84,252, 87, 65,237, + 87, 65,237, 94, 70,242,117,110,109,122,132, 48,124,143, 31, + 124,158, 13,123,169, 4,123,172, 2,123,171, 3,122,178, 0, + 120,184, 0,119,185, 0,121,182, 0,123,172, 2,124,152, 20, + 117,110,109,118,114, 96,122,135, 44,123,141, 34,123,139, 37, + 121,127, 58,114,104,197, 87, 65,237, 30, 31,180, 94, 70,242, + 111, 96,248,118,114, 96,119,119, 77,119,119, 77,118,117, 85, + 121,125, 63,121,125, 63,121,125, 63,124,147, 26,124,165, 8, + 122,176, 0,120,182, 0,119,185, 0,119,185, 0,121,182, 0, + 121,180, 0,121,181, 0,122,178, 0,123,168, 5,124,150, 22, + 120,122, 70,113,100,242, 94, 70,242,102, 80,250, 94, 70,242, + 107, 89,252,118,114, 96,121,127, 58,122,130, 53,121,125, 63, + 122,135, 44,124,162, 10,122,175, 0,120,182, 0,119,186, 0, + 118,189, 0,117,190, 0,117,191, 0,117,192, 0,115,194, 0, + 111,202, 0,107,207, 0,105,209, 0,103,211, 0,104,210, 0, + 105,209, 0,105,209, 0,106,208, 0,108,205, 0,110,202, 0, + 113,198, 0,117,192, 0,120,183, 0,124,167, 6,124,152, 20, + 123,139, 37,123,137, 41,121,125, 63,113,100,242, 30, 49,213, + 87, 65,237,107, 89,252,109, 92,251,107, 89,252, 99, 75,247, + 111, 96,248,114,104,197,111, 96,248, 94, 70,242, 69, 60,230, + 87, 65,237,105, 84,252,105, 84,252,113,100,242,115,107,129, + 114,104,197,109, 92,251,107, 89,252,118,117, 85,124,143, 31, + 124,161, 11,123,173, 1,121,179, 0,121,181, 0,122,177, 0, + 124,166, 7,123,139, 37, 99, 75,247, 30, 49,213,121,127, 58, + 124,162, 10,122,178, 0,119,186, 0,117,190, 0,117,192, 0, + 116,193, 0,117,192, 0,117,190, 0,117,191, 0,118,189, 0, + 119,185, 0,122,177, 0,124,166, 7,123,172, 2,121,180, 0, + 120,182, 0,121,180, 0,122,175, 0,124,166, 7,124,160, 12, + 124,157, 15,124,145, 29,118,117, 85,118,114, 96,118,114, 96, + 118,114, 96,114,104,197, 94, 70,242, 30, 31,180, 87, 65,237, + 114,104,197,117,110,109,115,107,129,109, 92,251, 99, 75,247, + 109, 92,251,118,117, 85,122,132, 48,124,149, 24,123,169, 4, + 121,181, 0,119,185, 0,119,186, 0,120,182, 0,123,173, 1, + 123,171, 3,120,183, 0,116,193, 0,112,200, 0,109,204, 0, + 107,207, 0,106,207, 0,106,207, 0,107,207, 0,108,205, 0, + 110,202, 0,114,197, 0,117,190, 0,122,178, 0,124,158, 13, + 118,117, 85, 69, 60,230,120,122, 70,124,158, 13,122,178, 0, + 118,189, 0,115,195, 0,113,199, 0,112,200, 0,113,199, 0, + 111,202, 0,109,204, 0,109,204, 0,110,202, 0,113,199, 0, + 115,194, 0,117,190, 0,118,188, 0,119,186, 0,121,181, 0, + 122,176, 0,122,177, 0,122,176, 0,123,172, 2,124,165, 8, + 124,150, 22,124,155, 16,124,160, 12,124,161, 11,124,155, 16, + 124,143, 31,120,122, 70,114,104,197,111, 96,248,109, 92,251, + 122,132, 48,124,155, 16,124,167, 6,123,172, 2,123,173, 1, + 123,170, 3,122,175, 0,122,178, 0,122,176, 0,123,170, 3, + 124,157, 15,123,141, 34,122,132, 48,118,117, 85,115,107,129, + 118,117, 85,123,137, 41,124,160, 12,123,172, 2,122,177, 0, + 122,178, 0,121,181, 0,120,184, 0,120,184, 0,120,184, 0, + 120,184, 0,121,181, 0,123,172, 2,124,155, 16,121,125, 63, + 30, 37,192,111, 96,248,118,117, 85,119,119, 77,121,127, 58, + 122,135, 44,122,135, 44,120,122, 70,109, 92,251,109, 92,251, + 102, 80,250, 99, 75,247, 87, 65,237,102, 80,250,102, 80,250, + 30, 55,222, 30, 2,128,102, 80,250,119,119, 77,123,139, 37, + 124,150, 22,124,165, 8,123,174, 1,122,178, 0,122,176, 0, + 120,183, 0,118,188, 0,117,191, 0,118,188, 0,121,182, 0, + 123,168, 5,123,139, 37,109, 92,251,120,122, 70,122,130, 53, + 122,130, 53,118,117, 85,107, 89,252, 87, 65,237, 30, 55,222, + 69, 60,230,102, 80,250,107, 89,252,114,104,197,117,110,109, + 115,107,129,111, 96,248, 99, 75,247, 30, 43,203,111, 96,248, + 123,139, 37,124,162, 10,123,174, 1,121,181, 0,120,183, 0, + 121,182, 0,122,177, 0,121,179, 0,122,178, 0,123,172, 2, + 124,161, 11,123,141, 34,118,114, 96,105, 84,252, 30, 37,192, + 102, 80,250,113,100,242,114,104,197,119,119, 77,120,122, 70, + 121,125, 63,122,135, 44,124,145, 29,124,164, 9,123,172, 2, + 122,178, 0,119,186, 0,118,189, 0,117,191, 0,117,190, 0, + 119,186, 0,115,195, 0,110,202, 0,107,207, 0,105,209, 0, + 104,210, 0,105,209, 0,106,208, 0,107,207, 0,109,204, 0, + 110,202, 0,112,199, 0,115,194, 0,118,188, 0,122,176, 0, + 124,155, 16,118,114, 96,118,114, 96,113,100,242, 87, 65,237, + 30, 15,143, 30, 26,168, 94, 70,242,109, 92,251,107, 89,252, + 119,119, 77,122,135, 44,123,139, 37,123,137, 41,120,122, 70, + 111, 96,248, 30, 55,222, 30, 5,128, 30, 26,168, 87, 65,237, + 107, 89,252,111, 96,248,115,107,129,119,119, 77,121,127, 58, + 122,130, 53,124,152, 20,124,167, 6,123,174, 1,122,177, 0, + 123,172, 2,124,160, 12,121,127, 58, 30, 49,213,113,100,242, + 122,135, 44,124,165, 8,122,178, 0,119,185, 0,118,188, 0, + 118,189, 0,118,189, 0,116,192, 0,115,194, 0,114,196, 0, + 115,194, 0,118,189, 0,121,182, 0,123,169, 4,124,149, 24, + 124,162, 10,124,167, 6,124,167, 6,124,161, 11,124,150, 22, + 122,132, 48,118,117, 85,109, 92,251,115,107,129,121,125, 63, + 123,137, 41,123,139, 37,122,130, 53,118,114, 96,102, 80,250, + 30, 15,143, 87, 65,237,102, 80,250, 87, 65,237, 69, 60,230, + 30, 43,203,105, 84,252,118,117, 85,122,130, 53,124,158, 13, + 122,176, 0,119,185, 0,118,189, 0,118,189, 0,119,186, 0, + 122,178, 0,124,165, 8,121,181, 0,117,191, 0,114,197, 0, + 111,202, 0,109,204, 0,109,204, 0,109,204, 0,110,203, 0, + 111,201, 0,113,198, 0,116,192, 0,120,184, 0,123,169, 4, + 123,139, 37, 99, 75,247, 30, 15,143,111, 96,248,124,147, 26, + 123,172, 2,119,186, 0,116,193, 0,114,197, 0,114,197, 0, + 114,196, 0,112,200, 0,111,201, 0,112,199, 0,114,196, 0, + 117,191, 0,120,184, 0,121,179, 0,123,174, 1,123,174, 1, + 123,172, 2,123,173, 1,123,171, 3,123,168, 5,124,164, 9, + 124,155, 16,123,139, 37,124,149, 24,124,155, 16,124,158, 13, + 124,154, 18,123,141, 34,118,117, 85, 99, 75,247, 30, 26,168, + 105, 84,252,122,130, 53,124,157, 15,123,170, 3,122,176, 0, + 122,178, 0,122,177, 0,123,172, 2,122,178, 0,121,179, 0, + 122,177, 0,123,170, 3,124,158, 13,123,139, 37,120,122, 70, + 107, 89,252,122,130, 53,124,158, 13,123,174, 1,120,183, 0, + 119,187, 0,118,188, 0,119,186, 0,120,184, 0,119,185, 0, + 119,186, 0,120,183, 0,122,177, 0,124,165, 8,124,143, 31, + 114,104,197, 30, 43,203,102, 80,250,113,100,242,115,107,129, + 118,114, 96,121,125, 63,121,127, 58,119,119, 77,109, 92,251, + 113,100,242,105, 84,252, 87, 65,237, 30, 55,222, 99, 75,247, + 99, 75,247, 30, 55,222, 30, 31,180,102, 80,250,118,117, 85, + 123,137, 41,124,155, 16,123,171, 3,121,180, 0,120,183, 0, + 120,182, 0,120,184, 0,118,189, 0,117,192, 0,117,191, 0, + 119,186, 0,122,175, 0,124,157, 15,121,127, 58,120,122, 70, + 120,122, 70,119,119, 77,118,114, 96,114,104,197,118,114, 96, + 121,125, 63,122,130, 53,121,125, 63,118,117, 85,120,122, 70, + 120,122, 70,118,117, 85,114,104,197,105, 84,252, 30, 49,213, + 30, 55,222,107, 89,252,123,137, 41,124,161, 11,123,173, 1, + 122,178, 0,121,179, 0,122,177, 0,122,177, 0,122,178, 0, + 122,175, 0,123,169, 4,124,158, 13,124,145, 29,121,127, 58, + 118,117, 85,118,117, 85,119,119, 77,120,122, 70,119,119, 77, + 122,135, 44,124,143, 31,124,150, 22,124,158, 13,124,167, 6, + 122,176, 0,120,184, 0,118,189, 0,116,192, 0,115,194, 0, + 116,193, 0,118,188, 0,119,187, 0,114,196, 0,110,202, 0, + 106,207, 0,104,210, 0,103,211, 0,103,211, 0,104,210, 0, + 106,207, 0,110,202, 0,113,198, 0,115,195, 0,118,189, 0, + 121,180, 0,124,164, 9,122,132, 48,120,122, 70,115,107,129, + 105, 84,252, 30, 55,222, 87, 65,237,107, 89,252,115,107,129, + 120,122, 70,124,143, 31,124,154, 18,124,158, 13,124,157, 15, + 124,149, 24,122,132, 48,115,107,129, 94, 70,242, 30, 49,213, + 30, 37,192,102, 80,250,117,110,109,122,130, 53,124,143, 31, + 124,150, 22,124,152, 20,124,147, 26,124,158, 13,123,168, 5, + 123,170, 3,124,167, 6,124,154, 18,119,119, 77,107, 89,252, + 119,119, 77,123,141, 34,124,162, 10,122,175, 0,121,181, 0, + 120,183, 0,118,189, 0,115,194, 0,114,197, 0,113,198, 0, + 113,198, 0,114,196, 0,117,191, 0,120,183, 0,123,169, 4, + 124,149, 24,124,150, 22,124,150, 22,124,150, 22,124,145, 29, + 122,135, 44,121,127, 58,120,122, 70,120,122, 70,122,135, 44, + 124,145, 29,124,150, 22,124,154, 18,124,154, 18,124,145, 29, + 120,122, 70,102, 80,250, 94, 70,242, 87, 65,237, 30, 49,213, + 69, 60,230,102, 80,250,115,107,129,122,130, 53,124,152, 20, + 123,170, 3,120,183, 0,117,190, 0,116,193, 0,116,193, 0, + 118,189, 0,120,182, 0,123,173, 1,122,178, 0,118,188, 0, + 115,194, 0,113,199, 0,111,201, 0,108,205, 0,107,207, 0, + 108,206, 0,110,202, 0,114,197, 0,118,189, 0,121,179, 0, + 124,164, 9,122,135, 44,107, 89,252, 94, 70,242,119,119, 77, + 124,143, 31,123,168, 5,120,183, 0,117,191, 0,115,194, 0, + 114,196, 0,116,193, 0,114,196, 0,114,196, 0,115,194, 0, + 118,189, 0,121,181, 0,122,176, 0,121,179, 0,121,180, 0, + 122,178, 0,122,177, 0,122,175, 0,123,171, 3,124,165, 8, + 124,154, 18,123,139, 37,122,130, 53,124,143, 31,124,150, 22, + 124,152, 20,124,147, 26,122,135, 44,117,110,109, 99, 75,247, + 107, 89,252,109, 92,251,119,119, 77,124,150, 22,124,167, 6, + 122,175, 0,122,178, 0,122,178, 0,122,176, 0,122,176, 0, + 121,179, 0,121,179, 0,122,177, 0,123,170, 3,124,160, 12, + 124,147, 26,122,132, 48,124,152, 20,123,171, 3,120,183, 0, + 117,190, 0,115,194, 0,114,196, 0,115,194, 0,116,192, 0, + 118,188, 0,120,184, 0,120,182, 0,122,176, 0,124,164, 9, + 123,137, 41,105, 84,252, 30, 43,203, 30, 26,168, 69, 60,230, + 94, 70,242,111, 96,248,117,110,109,118,114, 96,114,104,197, + 111, 96,248,114,104,197,109, 92,251, 87, 65,237, 30, 55,222, + 99, 75,247,102, 80,250, 94, 70,242, 69, 60,230, 99, 75,247, + 115,107,129,122,132, 48,124,160, 12,123,174, 1,120,183, 0, + 119,187, 0,119,187, 0,120,182, 0,119,187, 0,117,190, 0, + 117,190, 0,119,186, 0,122,178, 0,124,165, 8,124,149, 24, + 124,149, 24,124,147, 26,123,141, 34,122,135, 44,123,141, 34, + 124,152, 20,124,157, 15,124,157, 15,124,154, 18,124,147, 26, + 124,143, 31,124,145, 29,124,143, 31,123,137, 41,121,125, 63, + 114,104,197,105, 84,252,113,100,242,118,114, 96,124,143, 31, + 124,158, 13,123,168, 5,123,173, 1,123,173, 1,122,177, 0, + 121,179, 0,121,179, 0,122,177, 0,123,173, 1,123,168, 5, + 124,162, 10,124,158, 13,124,160, 12,124,161, 11,124,161, 11, + 124,160, 12,124,155, 16,124,161, 11,124,166, 7,123,170, 3, + 122,177, 0,120,184, 0,118,189, 0,115,194, 0,114,197, 0, + 113,198, 0,114,196, 0,116,192, 0,119,185, 0,118,188, 0, + 113,198, 0,108,205, 0,105,209, 0,102,212, 0,102,213, 0, + 102,213, 0,104,210, 0,108,205, 0,114,197, 0,115,195, 0, + 117,191, 0,120,183, 0,123,169, 4,124,143, 31,122,135, 44, + 120,122, 70,114,104,197,105, 84,252,109, 92,251,117,110,109, + 121,125, 63,123,137, 41,124,155, 16,124,165, 8,123,169, 4, + 123,169, 4,124,164, 9,124,152, 20,122,135, 44,117,110,109, + 111, 96,248,105, 84,252,115,107,129,122,130, 53,124,147, 26, + 124,157, 15,124,162, 10,124,164, 9,124,161, 11,124,152, 20, + 124,154, 18,124,158, 13,124,155, 16,123,141, 34,121,127, 58, + 118,117, 85,122,132, 48,124,147, 26,124,157, 15,123,170, 3, + 122,176, 0,119,185, 0,116,193, 0,113,198, 0,112,200, 0, + 111,202, 0,111,201, 0,113,198, 0,117,192, 0,120,183, 0, + 123,168, 5,124,157, 15,124,158, 13,124,158, 13,124,157, 15, + 124,155, 16,124,152, 20,124,149, 24,124,147, 26,124,150, 22, + 124,155, 16,124,162, 10,123,170, 3,123,172, 2,123,170, 3, + 124,162, 10,124,147, 26,120,122, 70,117,110,109,114,104,197, + 111, 96,248,109, 92,251,118,117, 85,123,137, 41,124,155, 16, + 123,170, 3,121,182, 0,118,189, 0,115,195, 0,114,197, 0, + 114,197, 0,116,193, 0,119,187, 0,121,180, 0,120,184, 0, + 118,189, 0,115,194, 0,112,199, 0,109,203, 0,107,207, 0, + 106,208, 0,106,208, 0,108,205, 0,111,201, 0,115,194, 0, + 119,186, 0,123,173, 1,124,152, 20,118,114, 96,115,107,129, + 122,135, 44,124,150, 22,124,165, 8,121,182, 0,117,190, 0, + 115,194, 0,115,194, 0,116,192, 0,117,191, 0,117,190, 0, + 119,187, 0,121,180, 0,123,172, 2,122,177, 0,120,182, 0, + 120,182, 0,121,180, 0,122,178, 0,123,173, 1,124,167, 6, + 124,158, 13,124,143, 31,118,114, 96,118,117, 85,122,130, 53, + 123,139, 37,123,141, 34,123,137, 41,121,125, 63,114,104,197, + 118,117, 85,119,119, 77,119,119, 77,120,122, 70,123,137, 41, + 124,160, 12,123,171, 3,122,176, 0,122,178, 0,122,177, 0, + 123,174, 1,121,180, 0,120,182, 0,121,182, 0,122,178, 0, + 123,172, 2,124,164, 9,124,154, 18,124,167, 6,121,179, 0, + 118,188, 0,115,195, 0,112,199, 0,111,202, 0,110,202, 0, + 111,201, 0,114,197, 0,117,191, 0,121,181, 0,122,176, 0, + 124,166, 7,124,145, 29,115,107,129,109, 92,251, 30, 37,192, + 30, 10,132, 30, 49,213,102, 80,250,109, 92,251,109, 92,251, + 102, 80,250,113,100,242,117,110,109,113,100,242, 99, 75,247, + 30, 55,222,105, 84,252,109, 92,251,107, 89,252, 99, 75,247, + 99, 75,247,111, 96,248,122,130, 53,124,157, 15,123,174, 1, + 120,184, 0,118,189, 0,118,189, 0,119,186, 0,120,183, 0, + 119,187, 0,118,188, 0,119,185, 0,121,179, 0,123,170, 3, + 123,168, 5,124,166, 7,124,162, 10,124,157, 15,124,161, 11, + 124,166, 7,123,170, 3,123,172, 2,123,171, 3,124,167, 6, + 124,162, 10,124,158, 13,124,158, 13,124,157, 15,124,150, 22, + 124,143, 31,122,132, 48,115,107,129,121,125, 63,123,137, 41, + 124,147, 26,124,154, 18,124,164, 9,124,167, 6,123,170, 3, + 122,177, 0,121,180, 0,120,182, 0,120,183, 0,120,182, 0, + 121,181, 0,121,179, 0,122,178, 0,122,178, 0,121,179, 0, + 121,179, 0,122,178, 0,122,175, 0,123,171, 3,123,174, 1, + 122,178, 0,120,184, 0,118,189, 0,115,194, 0,113,198, 0, + 112,200, 0,112,200, 0,113,199, 0,115,195, 0,118,188, 0, + 121,180, 0,116,193, 0,110,202, 0,106,208, 0,102,212, 0, + 101,214, 0,101,214, 0,103,211, 0,108,206, 0,113,198, 0, + 115,195, 0,117,192, 0,120,184, 0,123,171, 3,124,149, 24, + 124,143, 31,122,130, 53,118,117, 85,111, 96,248,115,107,129, + 121,127, 58,123,141, 34,124,147, 26,124,161, 11,123,171, 3, + 122,176, 0,122,176, 0,123,172, 2,124,164, 9,124,149, 24, + 122,130, 53,119,119, 77,117,110,109,122,130, 53,124,145, 29, + 124,155, 16,124,162, 10,124,167, 6,123,169, 4,124,167, 6, + 124,161, 11,124,149, 24,122,135, 44,122,135, 44,124,143, 31, + 124,147, 26,124,145, 29,123,141, 34,124,150, 22,124,158, 13, + 124,165, 8,122,178, 0,118,188, 0,114,196, 0,112,200, 0, + 110,202, 0,109,203, 0,110,202, 0,113,199, 0,116,192, 0, + 120,182, 0,124,167, 6,124,166, 7,124,166, 7,124,166, 7, + 124,166, 7,124,165, 8,124,164, 9,124,162, 10,124,162, 10, + 124,166, 7,122,175, 0,121,181, 0,120,183, 0,120,182, 0, + 121,179, 0,123,172, 2,124,162, 10,124,147, 26,123,139, 37, + 122,132, 48,120,122, 70,118,117, 85,123,137, 41,124,157, 15, + 123,170, 3,121,181, 0,118,189, 0,115,195, 0,113,199, 0, + 112,200, 0,112,199, 0,114,196, 0,117,191, 0,119,185, 0, + 118,188, 0,116,193, 0,114,197, 0,111,201, 0,108,205, 0, + 107,207, 0,106,208, 0,106,208, 0,107,207, 0,110,203, 0, + 113,198, 0,117,191, 0,121,180, 0,124,162, 10,122,135, 44, + 121,127, 58,123,137, 41,124,150, 22,124,165, 8,121,182, 0, + 117,190, 0,115,194, 0,115,194, 0,117,192, 0,118,188, 0, + 120,183, 0,122,178, 0,123,171, 3,123,170, 3,122,178, 0, + 120,182, 0,120,182, 0,121,179, 0,122,177, 0,123,171, 3, + 124,162, 10,124,147, 26,121,127, 58,109, 92,251,111, 96,248, + 117,110,109,119,119, 77,120,122, 70,120,122, 70,122,132, 48, + 124,145, 29,124,149, 24,124,145, 29,122,135, 44,122,132, 48, + 122,130, 53,124,143, 31,124,162, 10,123,171, 3,122,175, 0, + 122,176, 0,123,173, 1,121,180, 0,119,185, 0,119,186, 0, + 120,184, 0,121,179, 0,123,172, 2,124,165, 8,122,175, 0, + 120,184, 0,117,191, 0,113,198, 0,110,202, 0,108,205, 0, + 107,207, 0,107,207, 0,108,205, 0,112,199, 0,117,192, 0, + 121,181, 0,123,169, 4,124,157, 15,122,132, 48,122,130, 53, + 114,104,197,102, 80,250, 30, 55,222, 69, 60,230, 94, 70,242, + 87, 65,237, 94, 70,242,113,100,242,117,110,109,114,104,197, + 102, 80,250, 87, 65,237,109, 92,251,113,100,242,109, 92,251, + 105, 84,252, 99, 75,247,111, 96,248,120,122, 70,124,149, 24, + 123,169, 4,121,181, 0,119,187, 0,118,189, 0,119,187, 0, + 120,184, 0,120,183, 0,120,184, 0,120,183, 0,121,179, 0, + 121,180, 0,121,180, 0,122,177, 0,123,173, 1,123,172, 2, + 122,177, 0,121,179, 0,121,181, 0,121,181, 0,122,178, 0, + 123,174, 1,123,170, 3,123,169, 4,124,167, 6,124,164, 9, + 124,158, 13,124,152, 20,124,145, 29,122,132, 48,123,141, 34, + 124,154, 18,124,162, 10,123,168, 5,123,171, 3,123,174, 1, + 122,176, 0,122,177, 0,121,180, 0,120,183, 0,119,185, 0, + 119,186, 0,118,188, 0,118,188, 0,119,187, 0,119,187, 0, + 118,188, 0,118,188, 0,119,186, 0,120,184, 0,121,181, 0, + 122,178, 0,121,182, 0,119,186, 0,117,192, 0,114,197, 0, + 112,200, 0,111,202, 0,111,202, 0,112,200, 0,114,196, 0, + 118,189, 0,122,177, 0,118,188, 0,112,199, 0,107,206, 0, + 104,210, 0,102,212, 0,102,212, 0,104,210, 0,109,204, 0, + 114,197, 0,114,196, 0,116,193, 0,119,186, 0,123,173, 1, + 124,152, 20,124,145, 29,122,135, 44,119,119, 77,115,107,129, + 119,119, 77,123,141, 34,124,152, 20,124,154, 18,124,166, 7, + 122,175, 0,121,180, 0,121,181, 0,122,178, 0,123,171, 3, + 124,158, 13,123,141, 34,122,132, 48,122,135, 44,124,143, 31, + 124,152, 20,124,158, 13,124,162, 10,124,166, 7,123,168, 5, + 123,168, 5,124,164, 9,124,157, 15,124,154, 18,124,149, 24, + 124,152, 20,124,160, 12,124,162, 10,124,162, 10,124,162, 10, + 124,166, 7,123,170, 3,121,180, 0,118,189, 0,115,195, 0, + 112,200, 0,110,203, 0,109,204, 0,110,202, 0,113,199, 0, + 117,192, 0,121,181, 0,123,171, 3,123,173, 1,123,172, 2, + 123,171, 3,123,170, 3,123,169, 4,123,168, 5,123,170, 3, + 122,176, 0,120,182, 0,118,188, 0,117,190, 0,117,190, 0, + 118,188, 0,120,184, 0,122,178, 0,123,171, 3,124,166, 7, + 124,158, 13,124,149, 24,123,139, 37,122,132, 48,124,149, 24, + 124,166, 7,122,178, 0,119,187, 0,116,193, 0,113,198, 0, + 111,201, 0,111,201, 0,112,200, 0,114,197, 0,116,193, 0, + 118,189, 0,117,190, 0,115,194, 0,113,198, 0,111,202, 0, + 109,204, 0,107,206, 0,106,207, 0,106,207, 0,107,207, 0, + 108,205, 0,111,201, 0,115,195, 0,119,185, 0,123,169, 4, + 124,147, 26,123,137, 41,122,130, 53,123,141, 34,124,166, 7, + 121,182, 0,117,190, 0,116,193, 0,116,193, 0,117,191, 0, + 119,187, 0,121,182, 0,123,174, 1,124,165, 8,123,172, 2, + 122,178, 0,121,181, 0,121,181, 0,120,182, 0,121,181, 0, + 122,177, 0,123,168, 5,124,154, 18,121,125, 63,102, 80,250, + 94, 70,242,105, 84,252,115,107,129,123,139, 37,124,155, 16, + 124,165, 8,123,168, 5,124,166, 7,124,160, 12,124,147, 26, + 123,137, 41,122,135, 44,122,130, 53,124,149, 24,124,165, 8, + 123,171, 3,123,173, 1,123,171, 3,121,182, 0,118,188, 0, + 118,189, 0,118,188, 0,120,184, 0,122,176, 0,123,173, 1, + 121,179, 0,119,186, 0,116,192, 0,113,198, 0,109,203, 0, + 106,207, 0,104,210, 0,103,211, 0,105,209, 0,108,206, 0, + 112,200, 0,117,191, 0,122,178, 0,124,165, 8,124,152, 20, + 124,152, 20,123,137, 41,120,122, 70,115,107,129,102, 80,250, + 87, 65,237, 30, 43,203, 30, 55,222,109, 92,251,115,107,129, + 114,104,197,107, 89,252, 99, 75,247,114,104,197,118,114, 96, + 114,104,197,102, 80,250, 94, 70,242,109, 92,251,118,114, 96, + 123,137, 41,124,158, 13,123,173, 1,121,182, 0,120,184, 0, + 120,184, 0,120,184, 0,120,184, 0,119,185, 0,119,186, 0, + 119,187, 0,119,187, 0,119,186, 0,120,184, 0,121,179, 0, + 120,183, 0,119,186, 0,118,188, 0,118,188, 0,119,185, 0, + 121,182, 0,122,177, 0,122,178, 0,122,176, 0,123,173, 1, + 123,168, 5,124,164, 9,124,157, 15,124,152, 20,124,147, 26, + 124,152, 20,124,164, 9,123,171, 3,122,176, 0,122,178, 0, + 121,179, 0,121,179, 0,121,179, 0,122,178, 0,121,182, 0, + 119,185, 0,118,188, 0,118,189, 0,117,191, 0,117,191, 0, + 117,191, 0,117,191, 0,117,191, 0,117,190, 0,118,188, 0, + 119,185, 0,121,182, 0,121,180, 0,119,186, 0,117,191, 0, + 114,196, 0,112,199, 0,111,201, 0,111,201, 0,112,199, 0, + 115,195, 0,118,188, 0,121,179, 0,120,183, 0,114,196, 0, + 110,203, 0,106,207, 0,105,209, 0,105,209, 0,107,206, 0, + 111,201, 0,113,198, 0,113,198, 0,115,194, 0,119,186, 0, + 123,173, 1,124,154, 18,124,145, 29,122,132, 48,118,117, 85, + 117,110,109,121,127, 58,124,149, 24,124,160, 12,124,162, 10, + 123,168, 5,122,178, 0,120,183, 0,120,184, 0,121,182, 0, + 122,175, 0,124,164, 9,124,145, 29,124,149, 24,124,150, 22, + 124,152, 20,124,154, 18,124,155, 16,124,157, 15,124,160, 12, + 124,162, 10,124,164, 9,123,170, 3,123,173, 1,123,173, 1, + 123,169, 4,124,165, 8,123,168, 5,123,172, 2,123,172, 2, + 123,173, 1,123,174, 1,122,176, 0,121,179, 0,119,186, 0, + 116,192, 0,114,197, 0,111,201, 0,110,202, 0,111,201, 0, + 113,198, 0,117,191, 0,121,180, 0,122,175, 0,122,176, 0, + 122,175, 0,123,173, 1,123,171, 3,123,172, 2,122,176, 0, + 121,180, 0,119,185, 0,118,189, 0,116,193, 0,115,194, 0, + 116,193, 0,117,191, 0,119,187, 0,120,182, 0,121,181, 0, + 122,177, 0,123,171, 3,123,168, 5,124,164, 9,124,155, 16, + 124,154, 18,123,170, 3,120,182, 0,117,190, 0,114,196, 0, + 112,199, 0,111,201, 0,111,201, 0,112,199, 0,114,197, 0, + 116,193, 0,117,191, 0,118,189, 0,115,194, 0,114,197, 0, + 112,200, 0,110,202, 0,109,204, 0,108,205, 0,108,206, 0, + 107,206, 0,108,205, 0,110,202, 0,114,197, 0,118,188, 0, + 123,171, 3,124,152, 20,123,139, 37,119,119, 77,122,135, 44, + 123,168, 5,120,183, 0,117,190, 0,116,193, 0,116,192, 0, + 118,189, 0,119,185, 0,121,179, 0,123,170, 3,124,165, 8, + 123,171, 3,122,176, 0,121,179, 0,120,183, 0,119,185, 0, + 120,184, 0,121,181, 0,123,173, 1,124,158, 13,121,127, 58, + 87, 65,237, 30, 43,203,113,100,242,124,145, 29,124,166, 7, + 122,176, 0,121,180, 0,121,180, 0,122,176, 0,124,166, 7, + 124,152, 20,122,135, 44,122,132, 48,122,130, 53,121,127, 58, + 124,154, 18,124,166, 7,123,169, 4,123,171, 3,120,184, 0, + 117,190, 0,116,192, 0,117,191, 0,119,186, 0,122,178, 0, + 122,178, 0,121,182, 0,119,186, 0,117,191, 0,114,197, 0, + 110,202, 0,106,207, 0,103,211, 0,101,213, 0,102,213, 0, + 104,210, 0,108,205, 0,113,198, 0,119,187, 0,123,172, 2, + 124,164, 9,124,164, 9,124,155, 16,124,147, 26,122,135, 44, + 118,114, 96,107, 89,252, 69, 60,230, 30, 43,203,107, 89,252, + 114,104,197,114,104,197,111, 96,248,109, 92,251,118,114, 96, + 120,122, 70,118,117, 85,107, 89,252, 94, 70,242,109, 92,251, + 113,100,242,119,119, 77,123,141, 34,124,158, 13,123,170, 3, + 122,176, 0,122,178, 0,121,180, 0,120,183, 0,119,186, 0, + 118,188, 0,117,190, 0,117,191, 0,117,190, 0,119,187, 0, + 119,187, 0,117,191, 0,116,193, 0,116,193, 0,117,192, 0, + 118,188, 0,120,183, 0,120,184, 0,120,184, 0,121,181, 0, + 122,177, 0,123,174, 1,123,172, 2,123,169, 4,124,160, 12, + 124,157, 15,124,160, 12,123,170, 3,122,178, 0,121,181, 0, + 120,182, 0,121,182, 0,121,181, 0,121,179, 0,122,177, 0, + 122,177, 0,121,181, 0,119,185, 0,118,188, 0,117,190, 0, + 117,191, 0,117,191, 0,117,191, 0,117,190, 0,118,189, 0, + 118,188, 0,119,185, 0,120,182, 0,122,178, 0,121,181, 0, + 119,187, 0,116,192, 0,114,196, 0,113,198, 0,113,198, 0, + 114,196, 0,116,192, 0,119,185, 0,120,183, 0,120,184, 0, + 117,192, 0,112,199, 0,110,203, 0,109,204, 0,109,203, 0, + 111,201, 0,113,198, 0,112,200, 0,112,200, 0,114,196, 0, + 119,187, 0,123,172, 2,124,150, 22,123,141, 34,121,127, 58, + 115,107,129,117,110,109,122,132, 48,124,154, 18,124,164, 9, + 124,167, 6,123,170, 3,121,180, 0,119,185, 0,119,187, 0, + 119,185, 0,122,178, 0,124,167, 6,124,157, 15,124,158, 13, + 124,157, 15,124,154, 18,124,149, 24,124,145, 29,124,143, 31, + 124,143, 31,124,150, 22,124,167, 6,122,178, 0,120,182, 0, + 120,184, 0,121,182, 0,122,177, 0,123,172, 2,122,177, 0, + 122,178, 0,122,178, 0,122,178, 0,122,178, 0,122,178, 0, + 121,181, 0,119,186, 0,117,192, 0,114,196, 0,113,199, 0, + 113,198, 0,115,195, 0,118,189, 0,121,180, 0,122,175, 0, + 122,176, 0,123,174, 1,122,175, 0,122,177, 0,122,178, 0, + 121,181, 0,120,184, 0,118,188, 0,116,192, 0,114,196, 0, + 114,196, 0,115,194, 0,117,192, 0,118,188, 0,118,189, 0, + 118,189, 0,120,184, 0,121,180, 0,121,180, 0,122,178, 0, + 123,172, 2,123,171, 3,123,170, 3,120,182, 0,117,191, 0, + 114,196, 0,113,198, 0,112,199, 0,113,199, 0,114,197, 0, + 115,194, 0,117,192, 0,117,190, 0,119,186, 0,117,192, 0, + 115,195, 0,113,198, 0,112,200, 0,110,202, 0,110,202, 0, + 109,203, 0,108,205, 0,108,205, 0,109,203, 0,113,198, 0, + 118,189, 0,123,171, 3,124,152, 20,122,135, 44,117,110,109, + 124,143, 31,123,171, 3,120,184, 0,118,189, 0,117,191, 0, + 117,190, 0,119,187, 0,120,183, 0,122,176, 0,124,166, 7, + 124,162, 10,123,169, 4,123,173, 1,121,179, 0,120,183, 0, + 119,186, 0,119,186, 0,120,183, 0,122,176, 0,124,161, 11, + 121,127, 58, 30, 49,213, 30, 55,222,122,130, 53,124,164, 9, + 121,179, 0,119,186, 0,118,189, 0,119,187, 0,121,182, 0, + 123,170, 3,124,160, 12,122,135, 44,121,127, 58,121,125, 63, + 120,122, 70,123,141, 34,124,160, 12,124,165, 8,123,174, 1, + 119,186, 0,116,192, 0,115,194, 0,116,193, 0,119,187, 0, + 121,182, 0,121,182, 0,119,185, 0,115,194, 0,111,201, 0, + 108,205, 0,107,207, 0,108,206, 0,104,210, 0,101,213, 0, + 101,214, 0,102,212, 0,106,208, 0,110,202, 0,116,193, 0, + 121,181, 0,123,170, 3,123,168, 5,124,162, 10,124,157, 15, + 124,147, 26,122,132, 48,114,104,197,105, 84,252, 30, 55,222, + 102, 80,250,113,100,242,114,104,197,111, 96,248,115,107,129, + 121,125, 63,122,130, 53,121,125, 63,114,104,197,109, 92,251, + 111, 96,248,113,100,242,113,100,242,118,117, 85,122,132, 48, + 124,147, 26,124,157, 15,124,164, 9,123,170, 3,122,176, 0, + 120,182, 0,119,186, 0,118,189, 0,117,191, 0,117,191, 0, + 118,188, 0,116,193, 0,114,197, 0,113,198, 0,113,198, 0, + 115,195, 0,117,190, 0,119,186, 0,118,188, 0,119,187, 0, + 120,184, 0,121,179, 0,122,178, 0,122,178, 0,122,175, 0, + 123,168, 5,124,166, 7,124,166, 7,122,175, 0,121,181, 0, + 120,183, 0,120,183, 0,121,182, 0,121,179, 0,122,177, 0, + 122,177, 0,122,176, 0,121,179, 0,121,181, 0,120,183, 0, + 119,186, 0,119,187, 0,119,187, 0,119,187, 0,119,186, 0, + 119,186, 0,120,184, 0,121,182, 0,122,178, 0,122,176, 0, + 123,174, 1,121,179, 0,119,186, 0,117,191, 0,116,193, 0, + 116,193, 0,117,191, 0,118,188, 0,120,182, 0,119,186, 0, + 119,186, 0,118,188, 0,115,194, 0,113,198, 0,113,198, 0, + 114,197, 0,115,195, 0,112,200, 0,110,202, 0,111,201, 0, + 114,196, 0,119,187, 0,123,170, 3,124,143, 31,122,132, 48, + 118,117, 85,113,100,242,117,110,109,122,132, 48,124,152, 20, + 124,164, 9,124,167, 6,123,172, 2,120,182, 0,118,188, 0, + 118,189, 0,118,188, 0,121,182, 0,123,171, 3,124,162, 10, + 124,161, 11,124,157, 15,124,149, 24,123,139, 37,122,132, 48, + 121,127, 58,118,117, 85,124,149, 24,123,169, 4,121,181, 0, + 118,188, 0,117,190, 0,118,189, 0,119,185, 0,122,178, 0, + 122,178, 0,121,179, 0,122,178, 0,122,177, 0,122,175, 0, + 122,178, 0,121,179, 0,122,178, 0,120,184, 0,117,190, 0, + 116,193, 0,115,194, 0,116,193, 0,118,188, 0,121,180, 0, + 123,172, 2,122,177, 0,122,178, 0,122,178, 0,121,179, 0, + 121,180, 0,121,182, 0,120,184, 0,118,188, 0,116,192, 0, + 115,195, 0,115,195, 0,115,194, 0,116,193, 0,115,194, 0, + 115,195, 0,116,193, 0,119,187, 0,119,186, 0,119,187, 0, + 119,186, 0,120,183, 0,120,183, 0,120,182, 0,121,181, 0, + 118,189, 0,115,194, 0,114,196, 0,114,197, 0,114,196, 0, + 115,194, 0,117,192, 0,118,189, 0,118,188, 0,119,185, 0, + 118,188, 0,117,192, 0,114,196, 0,111,202, 0,109,204, 0, + 109,204, 0,111,202, 0,109,204, 0,108,205, 0,109,203, 0, + 113,198, 0,118,189, 0,123,170, 3,124,149, 24,121,127, 58, + 122,130, 53,124,150, 22,123,173, 1,120,184, 0,118,188, 0, + 118,189, 0,119,186, 0,120,183, 0,122,178, 0,123,172, 2, + 124,161, 11,124,157, 15,124,165, 8,123,170, 3,122,176, 0, + 121,180, 0,120,183, 0,120,184, 0,120,182, 0,122,176, 0, + 124,161, 11,121,125, 63, 99, 75,247, 99, 75,247,124,143, 31, + 123,173, 1,119,186, 0,116,193, 0,115,194, 0,117,191, 0, + 120,184, 0,122,175, 0,123,168, 5,124,150, 22,122,130, 53, + 119,119, 77,119,119, 77,122,132, 48,124,154, 18,124,161, 11, + 122,177, 0,118,188, 0,115,194, 0,114,197, 0,115,194, 0, + 118,188, 0,119,185, 0,120,184, 0,116,193, 0,110,202, 0, + 105,209, 0,102,212, 0,101,214, 0,102,212, 0,105,209, 0, + 102,212, 0,102,213, 0,102,212, 0,104,210, 0,108,205, 0, + 113,198, 0,119,187, 0,123,173, 1,124,166, 7,124,161, 11, + 124,157, 15,124,150, 22,123,139, 37,119,119, 77,114,104,197, + 105, 84,252, 69, 60,230,107, 89,252,109, 92,251,113,100,242, + 120,122, 70,122,135, 44,123,139, 37,122,135, 44,118,117, 85, + 121,125, 63,119,119, 77,114,104,197,114,104,197,111, 96,248, + 111, 96,248,115,107,129,119,119, 77,124,147, 26,124,161, 11, + 123,169, 4,123,174, 1,121,180, 0,119,185, 0,118,188, 0, + 118,188, 0,116,192, 0,114,197, 0,111,201, 0,110,202, 0, + 111,201, 0,113,198, 0,116,193, 0,119,187, 0,118,188, 0, + 118,188, 0,119,185, 0,121,181, 0,121,179, 0,122,178, 0, + 122,177, 0,123,171, 3,122,175, 0,122,175, 0,122,178, 0, + 120,182, 0,120,183, 0,121,181, 0,122,178, 0,123,174, 1, + 122,178, 0,121,182, 0,121,182, 0,120,183, 0,119,186, 0, + 119,186, 0,120,184, 0,121,182, 0,120,182, 0,120,182, 0, + 121,182, 0,121,181, 0,121,179, 0,122,177, 0,123,174, 1, + 123,170, 3,123,169, 4,123,169, 4,122,178, 0,120,184, 0, + 119,187, 0,118,188, 0,119,186, 0,121,182, 0,119,185, 0, + 119,187, 0,119,186, 0,120,184, 0,117,190, 0,116,192, 0, + 117,192, 0,117,191, 0,114,197, 0,111,201, 0,110,203, 0, + 111,202, 0,114,196, 0,119,186, 0,123,168, 5,122,132, 48, + 119,119, 77,113,100,242,111, 96,248,117,110,109,120,122, 70, + 124,147, 26,124,158, 13,124,162, 10,122,176, 0,119,185, 0, + 117,191, 0,116,192, 0,117,191, 0,119,186, 0,122,176, 0, + 124,161, 11,124,155, 16,124,149, 24,123,141, 34,123,139, 37, + 123,137, 41,122,130, 53,123,139, 37,124,147, 26,123,170, 3, + 120,184, 0,117,191, 0,115,194, 0,115,194, 0,117,191, 0, + 120,184, 0,122,177, 0,122,177, 0,122,175, 0,123,173, 1, + 122,176, 0,121,179, 0,121,180, 0,121,179, 0,122,176, 0, + 120,183, 0,118,188, 0,117,191, 0,117,191, 0,118,189, 0, + 119,185, 0,121,180, 0,122,176, 0,122,178, 0,122,178, 0, + 121,182, 0,119,185, 0,118,188, 0,117,190, 0,117,191, 0, + 117,191, 0,116,193, 0,115,194, 0,115,195, 0,114,197, 0, + 113,198, 0,114,197, 0,116,193, 0,118,188, 0,118,189, 0, + 117,191, 0,117,191, 0,118,189, 0,117,190, 0,117,190, 0, + 118,189, 0,118,188, 0,116,193, 0,115,194, 0,115,195, 0, + 115,194, 0,115,194, 0,115,194, 0,117,192, 0,119,186, 0, + 120,183, 0,120,184, 0,117,191, 0,113,198, 0,110,202, 0, + 108,205, 0,108,205, 0,111,201, 0,109,203, 0,108,205, 0, + 109,203, 0,113,198, 0,118,188, 0,123,169, 4,124,149, 24, + 121,125, 63,123,141, 34,124,150, 22,123,172, 2,121,182, 0, + 119,185, 0,119,185, 0,121,182, 0,122,178, 0,122,175, 0, + 123,168, 5,124,157, 15,124,149, 24,124,161, 11,123,168, 5, + 123,172, 2,123,172, 2,122,177, 0,121,179, 0,122,178, 0, + 123,172, 2,124,157, 15,123,139, 37,114,104,197,105, 84,252, + 124,149, 24,122,177, 0,118,189, 0,114,196, 0,114,197, 0, + 115,194, 0,119,187, 0,122,176, 0,123,169, 4,124,152, 20, + 122,132, 48,120,122, 70,120,122, 70,122,130, 53,124,152, 20, + 124,160, 12,121,179, 0,117,190, 0,114,196, 0,113,198, 0, + 115,195, 0,117,190, 0,118,189, 0,118,188, 0,113,198, 0, + 107,207, 0,101,213, 0, 98,217, 0, 97,218, 0, 98,217, 0, + 101,214, 0,104,210, 0,102,212, 0,102,212, 0,103,211, 0, + 107,207, 0,111,201, 0,117,192, 0,121,180, 0,123,173, 1, + 124,158, 13,124,154, 18,124,150, 22,123,141, 34,121,125, 63, + 119,119, 77,117,110,109,113,100,242,113,100,242,117,110,109, + 120,122, 70,122,135, 44,124,143, 31,124,145, 29,123,139, 37, + 123,141, 34,124,149, 24,124,149, 24,123,139, 37,120,122, 70, + 111, 96,248,107, 89,252,107, 89,252,114,104,197,122,132, 48, + 124,152, 20,124,164, 9,123,170, 3,122,176, 0,121,180, 0, + 120,184, 0,118,189, 0,115,194, 0,112,199, 0,110,202, 0, + 110,203, 0,111,202, 0,113,199, 0,116,193, 0,118,188, 0, + 119,187, 0,119,186, 0,120,184, 0,121,182, 0,122,178, 0, + 122,177, 0,122,177, 0,121,180, 0,120,183, 0,120,183, 0, + 121,182, 0,121,182, 0,121,179, 0,122,175, 0,123,173, 1, + 121,179, 0,120,183, 0,120,184, 0,120,184, 0,120,183, 0, + 119,186, 0,119,187, 0,119,186, 0,119,185, 0,120,183, 0, + 121,182, 0,121,180, 0,121,179, 0,121,179, 0,122,178, 0, + 122,178, 0,122,177, 0,123,172, 2,124,166, 7,123,169, 4, + 122,178, 0,121,182, 0,120,183, 0,121,181, 0,121,180, 0, + 120,183, 0,120,184, 0,120,183, 0,122,178, 0,120,184, 0, + 119,186, 0,119,186, 0,117,192, 0,114,197, 0,111,201, 0, + 110,202, 0,112,200, 0,116,193, 0,120,182, 0,124,161, 11, + 119,119, 77,113,100,242, 99, 75,247,109, 92,251,117,110,109, + 121,125, 63,123,139, 37,124,152, 20,124,167, 6,121,179, 0, + 118,188, 0,116,193, 0,115,194, 0,116,193, 0,118,188, 0, + 121,179, 0,124,166, 7,124,149, 24,124,143, 31,123,141, 34, + 123,137, 41,122,130, 53,122,135, 44,124,150, 22,124,158, 13, + 123,174, 1,119,186, 0,116,193, 0,114,197, 0,114,197, 0, + 115,194, 0,118,188, 0,121,182, 0,122,176, 0,123,174, 1, + 122,175, 0,122,176, 0,122,178, 0,122,178, 0,122,175, 0, + 123,171, 3,122,178, 0,120,184, 0,118,189, 0,117,191, 0, + 117,191, 0,118,188, 0,119,186, 0,120,184, 0,120,184, 0, + 119,186, 0,118,188, 0,117,191, 0,116,193, 0,115,194, 0, + 115,195, 0,115,194, 0,115,194, 0,115,195, 0,114,196, 0, + 114,197, 0,114,197, 0,115,194, 0,117,191, 0,117,190, 0, + 117,191, 0,116,193, 0,116,193, 0,117,191, 0,116,193, 0, + 115,194, 0,116,193, 0,116,193, 0,115,194, 0,114,196, 0, + 113,198, 0,113,199, 0,112,199, 0,113,199, 0,114,196, 0, + 117,191, 0,120,184, 0,120,184, 0,117,192, 0,113,198, 0, + 110,202, 0,109,204, 0,110,203, 0,110,203, 0,108,205, 0, + 108,206, 0,109,204, 0,113,198, 0,118,188, 0,123,168, 5, + 124,145, 29,122,132, 48,124,145, 29,124,149, 24,123,168, 5, + 122,177, 0,121,180, 0,121,179, 0,121,181, 0,120,184, 0, + 121,181, 0,123,173, 1,124,158, 13,124,143, 31,124,158, 13, + 123,169, 4,123,174, 1,122,175, 0,123,169, 4,124,167, 6, + 123,168, 5,124,164, 9,124,161, 11,124,150, 22,121,125, 63, + 118,114, 96,124,145, 29,123,174, 1,118,188, 0,115,195, 0, + 114,197, 0,115,195, 0,118,189, 0,122,178, 0,124,162, 10, + 123,141, 34,121,127, 58,121,127, 58,121,127, 58,123,137, 41, + 124,155, 16,124,165, 8,121,182, 0,117,192, 0,114,197, 0, + 113,199, 0,114,196, 0,116,193, 0,116,193, 0,117,192, 0, + 112,200, 0,106,208, 0,100,214, 0, 97,218, 0, 95,220, 0, + 96,219, 0, 98,217, 0,101,213, 0,104,210, 0,103,211, 0, + 105,209, 0,107,207, 0,111,201, 0,115,194, 0,120,184, 0, + 123,173, 1,124,157, 15,124,150, 22,124,147, 26,123,139, 37, + 122,130, 53,122,132, 48,122,130, 53,121,127, 58,121,127, 58, + 122,135, 44,123,141, 34,124,147, 26,124,149, 24,124,149, 24, + 124,147, 26,124,160, 12,124,166, 7,124,166, 7,124,162, 10, + 124,152, 20,122,135, 44,117,110,109,102, 80,250,109, 92,251, + 115,107,129,122,132, 48,124,150, 22,124,161, 11,123,168, 5, + 123,174, 1,121,180, 0,119,186, 0,116,192, 0,114,197, 0, + 112,200, 0,111,201, 0,112,199, 0,114,196, 0,117,191, 0, + 119,186, 0,119,186, 0,119,185, 0,120,184, 0,121,182, 0, + 121,181, 0,121,181, 0,120,182, 0,119,186, 0,118,189, 0, + 118,189, 0,119,185, 0,121,180, 0,123,174, 1,123,170, 3, + 121,179, 0,120,184, 0,119,185, 0,119,186, 0,120,184, 0, + 121,181, 0,120,182, 0,120,184, 0,120,184, 0,120,183, 0, + 121,182, 0,121,181, 0,121,180, 0,121,180, 0,121,179, 0, + 121,179, 0,122,178, 0,122,177, 0,123,172, 2,124,165, 8, + 124,165, 8,123,171, 3,122,177, 0,122,178, 0,122,178, 0, + 123,174, 1,122,178, 0,122,178, 0,123,174, 1,124,167, 6, + 122,175, 0,122,178, 0,119,186, 0,116,193, 0,114,197, 0, + 112,200, 0,112,199, 0,114,196, 0,118,188, 0,122,175, 0, + 124,149, 24,115,107,129,102, 80,250, 30, 55,222,102, 80,250, + 113,100,242,119,119, 77,123,137, 41,124,155, 16,123,169, 4, + 121,181, 0,118,188, 0,116,193, 0,115,194, 0,116,192, 0, + 119,187, 0,122,178, 0,124,166, 7,124,149, 24,123,137, 41, + 122,132, 48,121,125, 63,118,117, 85,124,143, 31,124,155, 16, + 124,161, 11,122,178, 0,118,189, 0,115,195, 0,113,198, 0, + 113,198, 0,115,195, 0,117,190, 0,120,184, 0,121,179, 0, + 122,176, 0,122,175, 0,123,174, 1,123,172, 2,123,170, 3, + 124,166, 7,124,161, 11,123,171, 3,121,179, 0,119,185, 0, + 118,188, 0,118,189, 0,118,189, 0,118,188, 0,119,187, 0, + 118,188, 0,117,191, 0,116,192, 0,115,194, 0,115,195, 0, + 115,195, 0,115,194, 0,116,193, 0,116,193, 0,116,193, 0, + 115,194, 0,116,193, 0,116,192, 0,117,190, 0,117,191, 0, + 117,191, 0,116,192, 0,116,193, 0,116,192, 0,117,191, 0, + 115,194, 0,115,195, 0,115,195, 0,114,196, 0,114,197, 0, + 112,200, 0,111,202, 0,110,202, 0,110,202, 0,111,201, 0, + 113,198, 0,116,193, 0,119,187, 0,119,185, 0,117,192, 0, + 114,197, 0,111,201, 0,110,202, 0,109,203, 0,108,205, 0, + 107,207, 0,107,207, 0,109,203, 0,114,197, 0,119,186, 0, + 124,164, 9,123,139, 37,122,135, 44,124,143, 31,123,141, 34, + 124,160, 12,123,169, 4,123,173, 1,121,181, 0,119,186, 0, + 118,188, 0,119,185, 0,122,176, 0,124,160, 12,124,154, 18, + 124,157, 15,123,169, 4,122,176, 0,122,178, 0,123,172, 2, + 124,157, 15,124,150, 22,124,160, 12,124,162, 10,124,157, 15, + 124,143, 31,122,135, 44,124,143, 31,124,166, 7,120,182, 0, + 117,191, 0,116,193, 0,116,193, 0,118,188, 0,122,178, 0, + 124,164, 9,123,141, 34,122,132, 48,122,130, 53,121,127, 58, + 124,147, 26,124,160, 12,123,171, 3,119,185, 0,116,193, 0, + 113,198, 0,113,199, 0,114,196, 0,115,194, 0,115,194, 0, + 115,194, 0,111,201, 0,106,208, 0,101,214, 0, 97,217, 0, + 95,219, 0, 96,219, 0, 97,217, 0,100,215, 0,103,211, 0, + 106,207, 0,107,206, 0,110,203, 0,113,198, 0,117,192, 0, + 120,183, 0,124,167, 6,124,152, 20,124,143, 31,123,137, 41, + 122,130, 53,121,127, 58,123,137, 41,123,141, 34,124,149, 24, + 124,152, 20,124,152, 20,124,154, 18,124,155, 16,124,155, 16, + 124,150, 22,124,160, 12,123,171, 3,122,176, 0,122,177, 0, + 123,174, 1,123,168, 5,124,158, 13,124,145, 29,121,127, 58, + 118,117, 85,111, 96,248,111, 96,248,120,122, 70,123,141, 34, + 124,152, 20,124,162, 10,123,171, 3,121,179, 0,119,187, 0, + 117,192, 0,115,194, 0,115,195, 0,116,193, 0,117,190, 0, + 119,186, 0,120,184, 0,120,184, 0,120,183, 0,121,182, 0, + 120,182, 0,120,184, 0,119,186, 0,118,188, 0,117,191, 0, + 115,194, 0,116,193, 0,118,188, 0,122,178, 0,123,168, 5, + 122,175, 0,120,182, 0,119,186, 0,119,185, 0,120,184, 0, + 121,180, 0,122,175, 0,123,171, 3,122,175, 0,122,176, 0, + 122,177, 0,122,177, 0,122,177, 0,122,176, 0,122,176, 0, + 122,176, 0,123,174, 1,123,173, 1,123,171, 3,124,167, 6, + 124,164, 9,124,164, 9,124,166, 7,123,172, 2,122,175, 0, + 123,174, 1,123,170, 3,124,167, 6,124,165, 8,124,157, 15, + 124,152, 20,124,166, 7,121,181, 0,118,189, 0,115,194, 0, + 114,197, 0,114,197, 0,115,194, 0,118,189, 0,121,179, 0, + 124,161, 11,121,125, 63,111, 96,248, 30, 49,213, 30, 55,222, + 99, 75,247,102, 80,250,115,107,129,122,130, 53,124,152, 20, + 123,169, 4,121,180, 0,119,187, 0,117,191, 0,117,191, 0, + 118,188, 0,120,183, 0,123,174, 1,124,161, 11,124,143, 31, + 120,122, 70,118,114, 96,114,104,197,121,127, 58,124,149, 24, + 124,158, 13,123,168, 5,121,182, 0,117,190, 0,115,195, 0, + 114,197, 0,114,197, 0,116,193, 0,118,189, 0,120,183, 0, + 122,178, 0,122,175, 0,123,172, 2,123,169, 4,124,164, 9, + 124,157, 15,124,145, 29,124,147, 26,124,161, 11,123,171, 3, + 122,178, 0,120,182, 0,120,184, 0,119,185, 0,119,186, 0, + 119,187, 0,118,189, 0,117,192, 0,116,193, 0,115,194, 0, + 115,194, 0,116,193, 0,117,191, 0,118,189, 0,117,190, 0, + 117,191, 0,117,191, 0,117,190, 0,118,189, 0,118,189, 0, + 118,189, 0,117,190, 0,117,191, 0,117,191, 0,118,189, 0, + 118,189, 0,117,192, 0,116,193, 0,115,194, 0,114,196, 0, + 112,199, 0,110,202, 0,109,204, 0,108,205, 0,108,205, 0, + 110,202, 0,112,199, 0,115,194, 0,118,189, 0,118,188, 0, + 116,193, 0,113,198, 0,111,201, 0,109,203, 0,108,206, 0, + 106,207, 0,106,208, 0,107,207, 0,110,202, 0,115,194, 0, + 121,182, 0,124,157, 15,121,125, 63,122,135, 44,123,137, 41, + 121,127, 58,124,149, 24,124,165, 8,122,178, 0,119,187, 0, + 117,191, 0,117,192, 0,118,188, 0,122,178, 0,124,167, 6, + 124,165, 8,124,160, 12,123,168, 5,122,175, 0,122,178, 0, + 123,172, 2,124,158, 13,122,132, 48,124,152, 20,124,161, 11, + 124,161, 11,124,154, 18,124,147, 26,124,155, 16,124,160, 12, + 123,171, 3,120,182, 0,119,187, 0,118,188, 0,120,184, 0, + 122,176, 0,124,162, 10,123,139, 37,123,137, 41,122,135, 44, + 123,141, 34,124,158, 13,124,166, 7,122,178, 0,118,189, 0, + 114,196, 0,113,199, 0,113,199, 0,114,196, 0,115,194, 0, + 115,195, 0,114,197, 0,111,201, 0,107,206, 0,103,211, 0, + 100,214, 0, 98,216, 0, 98,217, 0, 98,217, 0,100,215, 0, + 102,212, 0,106,207, 0,110,202, 0,114,197, 0,117,192, 0, + 119,186, 0,122,178, 0,124,155, 16,124,143, 31,122,130, 53, + 118,117, 85,114,104,197,118,117, 85,123,137, 41,124,155, 16, + 124,162, 10,124,166, 7,123,168, 5,124,166, 7,124,162, 10, + 124,160, 12,124,155, 16,123,168, 5,122,178, 0,120,182, 0, + 120,183, 0,121,181, 0,122,177, 0,123,170, 3,124,162, 10, + 124,154, 18,124,147, 26,123,137, 41,118,114, 96, 87, 65,237, + 113,100,242,120,122, 70,123,139, 37,124,160, 12,124,167, 6, + 122,178, 0,120,184, 0,119,186, 0,119,187, 0,119,185, 0, + 121,182, 0,121,182, 0,120,183, 0,121,182, 0,121,179, 0, + 120,182, 0,119,185, 0,118,188, 0,118,189, 0,117,191, 0, + 116,192, 0,114,196, 0,114,196, 0,117,191, 0,121,182, 0, + 123,170, 3,122,177, 0,120,183, 0,120,184, 0,120,182, 0, + 122,178, 0,123,171, 3,124,164, 9,124,152, 20,124,157, 15, + 124,161, 11,124,165, 8,124,166, 7,124,167, 6,123,168, 5, + 123,168, 5,124,167, 6,124,166, 7,124,162, 10,124,160, 12, + 124,160, 12,124,161, 11,124,161, 11,124,160, 12,124,167, 6, + 123,170, 3,123,169, 4,124,167, 6,124,161, 11,124,154, 18, + 124,145, 29,124,158, 13,122,175, 0,119,185, 0,117,192, 0, + 115,195, 0,115,195, 0,116,193, 0,118,188, 0,121,180, 0, + 124,166, 7,124,147, 26,121,125, 63,105, 84,252, 30, 55,222, + 99, 75,247,107, 89,252,115,107,129,115,107,129,118,117, 85, + 124,145, 29,124,166, 7,122,178, 0,120,184, 0,119,186, 0, + 119,186, 0,120,182, 0,122,176, 0,124,165, 8,124,150, 22, + 122,132, 48,117,110,109,105, 84,252,115,107,129,123,137, 41, + 124,152, 20,124,158, 13,123,173, 1,120,184, 0,118,189, 0, + 116,193, 0,116,193, 0,116,192, 0,118,189, 0,120,184, 0, + 122,178, 0,123,174, 1,123,170, 3,124,166, 7,124,160, 12, + 124,149, 24,122,130, 53,115,107,129,120,122, 70,123,141, 34, + 124,155, 16,124,164, 9,123,169, 4,123,173, 1,122,176, 0, + 121,179, 0,120,182, 0,119,186, 0,118,189, 0,117,191, 0, + 117,191, 0,117,190, 0,118,188, 0,119,185, 0,119,185, 0, + 118,188, 0,118,188, 0,118,188, 0,119,186, 0,119,186, 0, + 119,185, 0,119,185, 0,119,186, 0,119,186, 0,120,184, 0, + 121,180, 0,120,184, 0,118,188, 0,117,190, 0,116,192, 0, + 114,196, 0,112,200, 0,109,204, 0,107,206, 0,107,207, 0, + 107,206, 0,109,203, 0,112,199, 0,115,194, 0,117,192, 0, + 116,192, 0,114,197, 0,111,201, 0,109,204, 0,107,206, 0, + 106,207, 0,105,209, 0,105,209, 0,107,206, 0,111,201, 0, + 117,191, 0,122,177, 0,124,147, 26,120,122, 70,122,130, 53, + 120,122, 70,118,114, 96,124,155, 16,122,175, 0,119,186, 0, + 117,192, 0,115,194, 0,116,193, 0,118,189, 0,122,178, 0, + 122,175, 0,123,174, 1,123,169, 4,124,162, 10,123,170, 3, + 123,172, 2,123,168, 5,124,154, 18,123,141, 34,124,143, 31, + 124,155, 16,124,160, 12,124,158, 13,124,150, 22,124,161, 11, + 124,166, 7,123,168, 5,123,168, 5,122,176, 0,122,178, 0, + 122,177, 0,123,169, 4,124,154, 18,122,135, 44,123,137, 41, + 123,139, 37,124,160, 12,123,169, 4,123,173, 1,120,184, 0, + 116,193, 0,113,198, 0,112,200, 0,113,199, 0,115,195, 0, + 116,192, 0,115,194, 0,114,197, 0,112,200, 0,110,203, 0, + 107,207, 0,105,209, 0,102,212, 0,101,213, 0,101,214, 0, + 101,213, 0,103,211, 0,106,208, 0,110,203, 0,114,197, 0, + 118,189, 0,121,180, 0,123,168, 5,124,149, 24,122,130, 53, + 114,104,197, 94, 70,242, 87, 65,237,118,114, 96,124,145, 29, + 124,161, 11,123,170, 3,123,174, 1,122,177, 0,122,176, 0, + 123,170, 3,124,165, 8,124,160, 12,123,171, 3,121,181, 0, + 119,185, 0,119,186, 0,120,184, 0,121,182, 0,122,177, 0, + 123,171, 3,124,166, 7,124,164, 9,124,160, 12,124,145, 29, + 118,114, 96, 30, 43,203, 30, 55,222,117,110,109,124,143, 31, + 124,155, 16,124,162, 10,123,171, 3,123,174, 1,122,175, 0, + 123,173, 1,122,177, 0,121,179, 0,121,179, 0,122,178, 0, + 121,182, 0,119,187, 0,117,190, 0,117,191, 0,117,190, 0, + 116,192, 0,116,193, 0,114,196, 0,114,196, 0,116,192, 0, + 120,184, 0,121,180, 0,121,181, 0,121,180, 0,121,180, 0, + 122,175, 0,124,167, 6,124,155, 16,124,145, 29,124,143, 31, + 123,141, 34,124,149, 24,124,149, 24,124,147, 26,124,150, 22, + 124,154, 18,124,155, 16,124,154, 18,124,150, 22,124,150, 22, + 124,152, 20,124,154, 18,124,155, 16,124,155, 16,124,152, 20, + 124,158, 13,124,162, 10,124,162, 10,124,161, 11,124,155, 16, + 124,150, 22,124,150, 22,123,170, 3,121,182, 0,118,188, 0, + 116,192, 0,115,194, 0,116,192, 0,119,187, 0,121,179, 0, + 123,174, 1,124,167, 6,124,152, 20,121,125, 63,102, 80,250, + 87, 65,237,109, 92,251,121,127, 58,123,141, 34,123,141, 34, + 121,127, 58,122,132, 48,124,158, 13,123,172, 2,122,178, 0, + 121,180, 0,122,178, 0,123,174, 1,124,165, 8,124,154, 18, + 123,139, 37,119,119, 77,109, 92,251,102, 80,250,120,122, 70, + 124,145, 29,124,155, 16,124,161, 11,122,176, 0,120,184, 0, + 118,188, 0,118,189, 0,118,188, 0,120,184, 0,121,179, 0, + 123,173, 1,124,167, 6,124,164, 9,124,160, 12,124,152, 20, + 123,141, 34,120,122, 70,111, 96,248, 30, 55,222,109, 92,251, + 118,114, 96,121,125, 63,122,135, 44,124,143, 31,124,150, 22, + 124,157, 15,124,164, 9,123,170, 3,122,178, 0,120,182, 0, + 119,185, 0,119,185, 0,120,184, 0,121,180, 0,122,175, 0, + 121,180, 0,120,182, 0,120,182, 0,121,181, 0,121,179, 0, + 122,178, 0,122,176, 0,122,176, 0,122,176, 0,122,175, 0, + 123,171, 3,123,170, 3,122,176, 0,121,180, 0,120,184, 0, + 118,188, 0,115,194, 0,112,200, 0,109,204, 0,106,207, 0, + 105,209, 0,106,207, 0,109,204, 0,112,199, 0,114,196, 0, + 115,194, 0,114,196, 0,111,201, 0,109,203, 0,107,206, 0, + 106,207, 0,105,209, 0,105,209, 0,105,209, 0,108,205, 0, + 113,198, 0,119,187, 0,123,170, 3,123,139, 37,118,117, 85, + 118,117, 85,111, 96,248,122,132, 48,124,167, 6,120,183, 0, + 117,191, 0,115,194, 0,115,195, 0,116,193, 0,118,188, 0, + 121,182, 0,120,182, 0,121,181, 0,122,175, 0,124,164, 9, + 124,158, 13,124,161, 11,124,157, 15,124,147, 26,123,139, 37, + 122,132, 48,124,149, 24,124,155, 16,124,155, 16,124,150, 22, + 124,160, 12,123,168, 5,123,171, 3,123,171, 3,123,168, 5, + 124,162, 10,124,162, 10,124,154, 18,123,139, 37,122,130, 53, + 123,137, 41,124,164, 9,123,174, 1,121,179, 0,121,181, 0, + 117,190, 0,114,197, 0,112,200, 0,112,200, 0,113,198, 0, + 115,194, 0,118,189, 0,116,193, 0,114,197, 0,111,202, 0, + 108,206, 0,105,209, 0,104,210, 0,104,210, 0,106,208, 0, + 105,209, 0,104,210, 0,105,209, 0,107,207, 0,110,203, 0, + 114,197, 0,118,189, 0,121,179, 0,124,165, 8,122,130, 53, + 113,100,242, 30, 43,203, 30, 10,132, 94, 70,242,119,119, 77, + 124,147, 26,124,165, 8,123,174, 1,121,179, 0,120,182, 0, + 120,183, 0,121,180, 0,123,173, 1,124,166, 7,123,170, 3, + 121,181, 0,119,185, 0,119,186, 0,119,185, 0,120,183, 0, + 121,180, 0,121,181, 0,122,177, 0,123,173, 1,123,171, 3, + 124,164, 9,124,143, 31,114,104,197, 30, 26,168, 69, 60,230, + 118,114, 96,122,132, 48,123,141, 34,124,150, 22,124,157, 15, + 124,162, 10,123,168, 5,123,171, 3,123,173, 1,122,176, 0, + 121,180, 0,119,186, 0,117,192, 0,114,196, 0,114,196, 0, + 116,193, 0,117,191, 0,117,192, 0,115,195, 0,114,196, 0, + 116,193, 0,118,188, 0,119,186, 0,119,186, 0,120,182, 0, + 123,173, 1,124,162, 10,124,147, 26,124,152, 20,124,154, 18, + 124,149, 24,122,135, 44,122,132, 48,121,127, 58,119,119, 77, + 121,125, 63,122,132, 48,122,132, 48,122,130, 53,121,125, 63, + 122,132, 48,123,137, 41,123,139, 37,123,141, 34,123,141, 34, + 123,137, 41,124,147, 26,124,150, 22,124,152, 20,124,149, 24, + 124,147, 26,124,143, 31,124,164, 9,122,178, 0,119,186, 0, + 117,190, 0,116,192, 0,117,192, 0,118,188, 0,120,183, 0, + 120,184, 0,121,181, 0,123,173, 1,124,157, 15,120,122, 70, + 94, 70,242, 87, 65,237,121,125, 63,124,152, 20,124,161, 11, + 124,161, 11,124,152, 20,122,132, 48,124,149, 24,124,164, 9, + 123,170, 3,123,172, 2,123,169, 4,124,162, 10,124,157, 15, + 124,152, 20,122,135, 44,114,104,197,111, 96,248,121,125, 63, + 123,139, 37,124,152, 20,124,158, 13,124,161, 11,122,175, 0, + 121,181, 0,120,183, 0,121,182, 0,122,178, 0,123,171, 3, + 124,162, 10,124,152, 20,124,143, 31,123,139, 37,122,135, 44, + 121,127, 58,120,122, 70,118,114, 96,109, 92,251, 30, 55,222, + 102, 80,250,107, 89,252,105, 84,252,105, 84,252,105, 84,252, + 109, 92,251,115,107,129,121,125, 63,124,145, 29,124,160, 12, + 123,170, 3,122,175, 0,122,176, 0,123,173, 1,123,168, 5, + 124,164, 9,123,170, 3,123,172, 2,123,171, 3,123,169, 4, + 124,165, 8,124,161, 11,124,158, 13,124,155, 16,124,155, 16, + 124,152, 20,124,143, 31,124,154, 18,124,162, 10,123,170, 3, + 121,179, 0,119,187, 0,117,192, 0,112,199, 0,108,205, 0, + 106,208, 0,105,209, 0,106,208, 0,108,205, 0,112,199, 0, + 113,198, 0,114,196, 0,112,200, 0,109,203, 0,107,206, 0, + 106,207, 0,106,208, 0,105,209, 0,105,209, 0,106,207, 0, + 110,202, 0,115,194, 0,120,182, 0,124,165, 8,124,147, 26, + 117,110,109,111, 96,248,107, 89,252,124,149, 24,122,175, 0, + 118,188, 0,115,194, 0,114,196, 0,115,195, 0,116,192, 0, + 119,186, 0,118,188, 0,118,188, 0,119,185, 0,122,178, 0, + 124,165, 8,123,139, 37,122,135, 44,122,132, 48,122,130, 53, + 122,130, 53,121,125, 63,123,137, 41,124,145, 29,124,147, 26, + 124,147, 26,124,152, 20,124,164, 9,123,170, 3,123,171, 3, + 123,168, 5,124,157, 15,122,135, 44,121,125, 63,115,107,129, + 120,122, 70,124,161, 11,122,178, 0,119,185, 0,118,188, 0, + 118,188, 0,115,194, 0,112,200, 0,111,202, 0,111,201, 0, + 113,198, 0,115,194, 0,117,190, 0,116,192, 0,115,195, 0, + 111,202, 0,107,207, 0,103,211, 0,102,213, 0,102,212, 0, + 105,209, 0,108,205, 0,108,205, 0,108,205, 0,109,203, 0, + 112,200, 0,115,195, 0,119,187, 0,122,175, 0,124,155, 16, + 109, 92,251, 30, 26,168, 30, 37,192,113,100,242,122,130, 53, + 124,145, 29,124,154, 18,124,167, 6,122,177, 0,120,183, 0, + 119,187, 0,118,189, 0,118,188, 0,120,184, 0,122,176, 0, + 123,169, 4,122,178, 0,120,183, 0,120,184, 0,120,184, 0, + 119,185, 0,118,188, 0,118,189, 0,119,186, 0,121,180, 0, + 121,180, 0,123,174, 1,124,164, 9,123,141, 34,113,100,242, + 87, 65,237, 30, 49,213,107, 89,252,115,107,129,120,122, 70, + 123,137, 41,124,147, 26,124,155, 16,124,161, 11,123,168, 5, + 122,175, 0,121,179, 0,118,189, 0,114,196, 0,112,200, 0, + 112,200, 0,114,197, 0,117,191, 0,118,188, 0,116,193, 0, + 115,195, 0,115,194, 0,117,190, 0,118,189, 0,118,188, 0, + 120,184, 0,122,175, 0,124,155, 16,124,155, 16,124,160, 12, + 124,160, 12,124,152, 20,122,135, 44,113,100,242,105, 84,252, + 94, 70,242,107, 89,252,114,104,197,117,110,109,114,104,197, + 109, 92,251,111, 96,248,115,107,129,117,110,109,118,114, 96, + 117,110,109,118,117, 85,121,125, 63,122,130, 53,122,132, 48, + 122,130, 53,121,127, 58,124,150, 22,123,170, 3,121,182, 0, + 118,188, 0,117,191, 0,117,191, 0,118,189, 0,119,186, 0, + 118,189, 0,117,190, 0,119,186, 0,122,178, 0,124,160, 12, + 118,117, 85, 30, 43,203,107, 89,252,124,143, 31,124,165, 8, + 123,173, 1,123,173, 1,124,167, 6,124,152, 20,123,141, 34, + 124,155, 16,124,162, 10,124,164, 9,124,160, 12,124,154, 18, + 124,155, 16,124,149, 24,121,125, 63,114,104,197,122,135, 44, + 124,152, 20,124,161, 11,124,161, 11,124,162, 10,124,161, 11, + 123,169, 4,122,175, 0,123,174, 1,123,169, 4,124,160, 12, + 124,149, 24,122,135, 44,115,107,129,109, 92,251,107, 89,252, + 117,110,109,123,139, 37,124,150, 22,124,152, 20,124,143, 31, + 120,122, 70,121,125, 63,122,130, 53,120,122, 70,113,100,242, + 69, 60,230, 30, 20,155, 30, 31,180, 30, 37,192,105, 84,252, + 120,122, 70,124,145, 29,124,157, 15,124,160, 12,124,158, 13, + 124,150, 22,123,139, 37,124,150, 22,124,152, 20,124,150, 22, + 124,143, 31,122,135, 44,121,125, 63,118,114, 96,115,107,129, + 114,104,197,111, 96,248,118,114, 96,122,130, 53,124,150, 22, + 123,170, 3,121,182, 0,118,188, 0,117,191, 0,113,199, 0, + 108,205, 0,105,209, 0,103,211, 0,105,209, 0,108,206, 0, + 112,200, 0,113,198, 0,112,199, 0,110,203, 0,108,206, 0, + 106,207, 0,106,208, 0,106,208, 0,106,208, 0,106,208, 0, + 108,206, 0,112,200, 0,117,191, 0,121,180, 0,123,169, 4, + 124,149, 24,115,107,129, 30, 55,222,113,100,242,124,158, 13, + 121,181, 0,117,191, 0,114,196, 0,114,197, 0,115,194, 0, + 117,191, 0,117,191, 0,116,192, 0,117,192, 0,119,187, 0, + 122,178, 0,124,161, 11,121,125, 63,107, 89,252,109, 92,251, + 113,100,242,118,114, 96,120,122, 70,120,122, 70,121,127, 58, + 122,130, 53,122,132, 48,122,135, 44,124,154, 18,124,164, 9, + 124,167, 6,124,164, 9,124,150, 22,118,117, 85, 94, 70,242, + 99, 75,247,124,147, 26,122,175, 0,118,188, 0,116,193, 0, + 114,196, 0,115,195, 0,113,198, 0,110,202, 0,109,203, 0, + 110,202, 0,112,199, 0,114,197, 0,114,196, 0,117,192, 0, + 116,192, 0,112,200, 0,107,207, 0,103,211, 0,101,213, 0, + 102,212, 0,105,209, 0,110,203, 0,113,198, 0,113,199, 0, + 113,198, 0,114,196, 0,117,190, 0,121,180, 0,124,164, 9, 122,135, 44 +} ; diff --git a/examples/src/ssg/majik/majik_demo.cxx b/examples/src/ssg/majik/majik_demo.cxx new file mode 100644 index 0000000..3ead8ca --- /dev/null +++ b/examples/src/ssg/majik/majik_demo.cxx @@ -0,0 +1,433 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: majik_demo.cxx 2099 2006-11-03 20:04:40Z fayjf $ +*/ + + +#include +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include +#include +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#define TILE_SIZE 2000.0f /* cubits */ +#define LAMBDA (TILE_SIZE/48.0f) +#define TILE_GRID_SIZE 20 /* Even number please! */ +#define TRIANGLE_GRID_SIZE 12 /* Num vertices */ +#define ELEVATION_SCALE 4.0f +#define ONLINE_TERRAIN_RANGE ((float)(TILE_GRID_SIZE/2 )* TILE_SIZE ) /* cubits */ +#define VISUAL_RANGE ((float)(TILE_GRID_SIZE/2-1)* TILE_SIZE ) /* cubits */ + +/***** *****/ + +static ssgSimpleState *state = NULL ; +static ssgRoot *scene = NULL ; +static ssgTransform *penguin = NULL ; +static ssgTransform *terrain = NULL ; +static ssgTransform *tilegrid [ TILE_GRID_SIZE ][ TILE_GRID_SIZE ] ; + +#include "elevation_map.h" +#include "image_map.h" + +static jsJoystick *js ; +static float *ax ; +static sgCoord tuxpos = { { 0.0f,0.0f,0.0f }, { 0.0f,0.0f,0.0f } } ; + +#define ROT_SPEED 5.0f +#define TRANS_SPEED 10.0f + +static void update_motion () +{ + static int frameno = 0 ; + + frameno++ ; + + sgCoord campos ; + + int buttons ; + + js -> read ( &buttons, ax ) ; + + tuxpos.hpr[0] -= ax [ 0 ] * ROT_SPEED ; + tuxpos.xyz[0] -= (float)sin ( tuxpos.hpr[0] * SG_DEGREES_TO_RADIANS ) * ax[1] * TRANS_SPEED ; + tuxpos.xyz[1] += (float)cos ( tuxpos.hpr[0] * SG_DEGREES_TO_RADIANS ) * ax[1] * TRANS_SPEED ; + + sgVec3 test_vec ; + sgMat4 invmat ; + sgMakeIdentMat4 ( invmat ) ; + + invmat[3][0] = -tuxpos.xyz[0] ; + invmat[3][1] = -tuxpos.xyz[1] ; + invmat[3][2] = 0.0f ; + + test_vec [0] = 0.0f ; + test_vec [1] = 0.0f ; + test_vec [2] = 100000.0f ; + + ssgHit *results ; + int num_hits = ssgHOT ( scene, test_vec, invmat, &results ) ; + + float hot = -1000000.0f ; + + for ( int i = 0 ; i < num_hits ; i++ ) + { + ssgHit *h = &results [ i ] ; + + float hgt = - h->plane[3] / h->plane[2] ; + + if ( hgt >= hot ) + hot = hgt ; + } + + tuxpos . xyz [ 2 ] = hot + 0.1f ; + tuxpos . hpr [ 1 ] = 0.0f ; + tuxpos . hpr [ 2 ] = 0.0f ; + + sgCopyVec3 ( campos.xyz, tuxpos.xyz ) ; + + campos . hpr [ 0 ] = 0.0f ; + campos . hpr [ 1 ] = -20.0f ; + campos . hpr [ 2 ] = 0.0f ; + campos . xyz [ 0 ] += 1.0f ; + campos . xyz [ 1 ] -= 20.0f ; + campos . xyz [ 2 ] += 12.0f ; + + ssgSetCamera ( & campos ) ; + penguin -> setTransform ( & tuxpos ) ; +} + + + +/* + The GLUT window reshape event +*/ + +static void reshape ( int w, int h ) +{ + glViewport ( 0, 0, w, h ) ; +} + + + +/* + The GLUT keyboard event +*/ + +static void keyboard ( unsigned char k, int, int ) +{ + static int wireframe = FALSE ; + + if ( k == 'w' ) + { + wireframe = ! wireframe ; + + glPolygonMode ( GL_FRONT_AND_BACK, wireframe ? GL_LINE : GL_FILL ) ; + } + + if ( k == 0x03 || k == 'x' ) + exit ( 0 ) ; +} + + + +/* + The GLUT redraw event +*/ + +static void redraw () +{ + update_motion () ; + + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + ssgCullAndDraw ( scene ) ; + + glutPostRedisplay () ; + glutSwapBuffers () ; +} + + + +static void init_graphics () +{ + int fake_argc = 1 ; + char *fake_argv[3] ; + fake_argv[0] = "MajikTerrain" ; + fake_argv[1] = "Majik Terrain Demo - by Steve Baker" ; + fake_argv[2] = NULL ; + + jsInit () ; + + js = new jsJoystick ( 0 ) ; + + if ( js -> notWorking () || js -> getNumAxes () < 2 ) + { + fprintf ( stderr, + "Majik_Demo: Joystick with at least two axes required.\n" ) ; + exit ( 0 ) ; + } + + ax = new float [ js->getNumAxes () ] ; + + /* + Initialise GLUT + */ + + glutInitWindowPosition ( 0, 0 ) ; + glutInitWindowSize ( 640, 480 ) ; + glutInit ( &fake_argc, fake_argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + glutCreateWindow ( fake_argv[1] ) ; + glutDisplayFunc ( redraw ) ; + glutReshapeFunc ( reshape ) ; + glutKeyboardFunc ( keyboard ) ; + + /* + Initialise SSG + */ + + ssgInit () ; + + /* + Some basic OpenGL setup + */ + + sgVec4 skycol ; sgSetVec4 ( skycol, 0.4f, 0.7f, 1.0f, 1.0f ) ; + sgVec4 fogcol ; sgSetVec4 ( fogcol, 0.4f, 0.7f, 1.0f, 1.0f ) ; + + glClearColor ( skycol[0], skycol[1], skycol[2], skycol[3] ) ; + + glEnable ( GL_DEPTH_TEST ) ; + + /* + Set up the viewing parameters + */ + + ssgSetFOV ( 60.0f, 0.0f ) ; + ssgSetNearFar ( 1.0f, 30000.0f ) ; + + /* + Initial Position + */ + + sgCoord startpos ; + sgSetCoord ( &startpos, 2350.0f, -920.0f, 0.0f, 0.0f, 0.0f, 0.0f ) ; + + /* + Set up some fog + */ + + glFogf ( GL_FOG_DENSITY, 0.015f / 100.0f ) ; + glFogfv( GL_FOG_COLOR , fogcol ) ; + glFogf ( GL_FOG_START , 0.0 ) ; + glFogi ( GL_FOG_MODE , GL_EXP2 ) ; + glHint ( GL_FOG_HINT , GL_NICEST ) ; + glEnable ( GL_FOG ) ; + + /* + Set up the Sun. + */ + + sgVec3 sunposn ; + sgVec4 sunamb ; + sgSetVec3 ( sunposn, 0.2f, -0.5f, 0.5f ) ; + sgSetVec4 ( sunamb , 0.4f, 0.4f, 0.4f, 1.0f ) ; + ssgGetLight ( 0 ) -> setPosition ( sunposn ) ; + ssgGetLight ( 0 ) -> setColour ( GL_AMBIENT, sunamb ) ; +} + + +static ssgBranch *createTileLOD ( int x, int y, ssgSimpleState *state, int ntris, float z_off ) +{ + sgVec4 *scolors = new sgVec4 [ (ntris+1) * (ntris+1) ] ; + sgVec2 *tcoords = new sgVec2 [ (ntris+1) * (ntris+1) ] ; + sgVec3 *snorms = new sgVec3 [ (ntris+1) * (ntris+1) ] ; + sgVec3 *scoords = new sgVec3 [ (ntris+1) * (ntris+1) ] ; + + for ( int j = 0 ; j < (ntris+1) ; j++ ) + for ( int i = 0 ; i < (ntris+1) ; i++ ) + { + int address = (int)floor( 12.0f * ((float)x + (float)i / (float)ntris) ) % 256 + + ((int)floor( 12.0f * ((float)y + (float)j / (float)ntris) ) % 256 ) * 256 ; + int addressN = (int)floor( 12.0f * ((float)x + (float)i / (float)ntris) ) % 256 + + ((int)floor( 12.0f * ((float)y + (float)j / (float)ntris)+1.0f ) % 256 ) * 256 ; + int addressE = (int)floor( 12.0f * ((float)x + (float)i / (float)ntris)+1.0f ) % 256 + + ((int)floor( 12.0f * ((float)y + (float)j / (float)ntris) ) % 256 ) * 256 ; + + float zz = (float) elevation_map [ address ] * ELEVATION_SCALE + z_off ; + float zzN = (float) elevation_map [ addressN ] * ELEVATION_SCALE + z_off ; + float zzE = (float) elevation_map [ addressE ] * ELEVATION_SCALE + z_off ; + + float rr = (float) image_map [ address * 3 + 0 ] / 255.0f ; + float gg = (float) image_map [ address * 3 + 1 ] / 255.0f ; + float bb = (float) image_map [ address * 3 + 2 ] / 255.0f ; + + float xx = (float) i * (TILE_SIZE/(float)ntris) ; + float yy = (float) j * (TILE_SIZE/(float)ntris) ; + + sgVec3 nrm ; + + nrm [ 0 ] = (zz - zzE) / (TILE_SIZE/12.0f) ; + nrm [ 1 ] = (zz - zzN) / (TILE_SIZE/12.0f) ; + nrm [ 2 ] = (float)sqrt ( nrm[0] * nrm[0] + nrm[1] * nrm[1] ) ; + + sgCopyVec3( snorms [i+j*(ntris+1)], nrm ) ; + sgSetVec2 ( tcoords [i+j*(ntris+1)], xx/LAMBDA, yy/LAMBDA ) ; + sgSetVec4 ( scolors [i+j*(ntris+1)], rr, gg, bb, 1.0f ) ; + sgSetVec3 ( scoords [i+j*(ntris+1)], xx, yy, zz ) ; + } + + ssgBranch *branch = new ssgBranch () ; + + for ( int i = 0 ; i < ntris ; i++ ) + { + unsigned short *vlist = new unsigned short [ 2 * (ntris+1) ] ; + + for ( int j = 0 ; j < (ntris+1) ; j++ ) + { + vlist [ j + j ] = j + (i+1) * (ntris+1) ; + vlist [ j + j + 1 ] = j + i * (ntris+1) ; + } + + ssgLeaf *gset = new ssgVTable ( GL_TRIANGLE_STRIP, + 2 * (ntris+1), vlist, scoords, + 2 * (ntris+1), vlist, snorms , + 2 * (ntris+1), vlist, tcoords, + 2 * (ntris+1), vlist, scolors ) ; + gset -> setState ( state ) ; + branch -> addKid ( gset ) ; + } + + return branch ; +} + + +static void createTile ( ssgTransform *tile, int x, int y, ssgSimpleState *state ) +{ + float rr[] = { 0.0f, 6000.0f, 7000.0f, 12000.0f } ; + ssgRangeSelector *lod = new ssgRangeSelector () ; + + lod -> addKid ( createTileLOD ( x, y, state, TRIANGLE_GRID_SIZE - 1, 0.0f ) ) ; + lod -> addKid ( createTileLOD ( x, y, state, TRIANGLE_GRID_SIZE/2 - 1, -30.0f ) ) ; + lod -> addKid ( createTileLOD ( x, y, state, TRIANGLE_GRID_SIZE/4 - 1, -250.0f ) ) ; + lod -> setRanges ( rr, 4 ) ; + + tile -> addKid ( lod ) ; +} + + +/* + Load a simple database +*/ + +static void load_database () +{ + /* + Set up the path to the data files + */ + + ssgModelPath ( "data" ) ; + ssgTexturePath ( "data" ) ; + + /* + Create a root node - and a transform to position + the terrain - and another to position the player. + */ + + scene = new ssgRoot ; + penguin = new ssgTransform ; + terrain = new ssgTransform ; + state = new ssgSimpleState ; + state -> setTexture ( "data/bumpnoise.rgb" ) ; + state -> enable ( GL_TEXTURE_2D ) ; + state -> enable ( GL_LIGHTING ) ; + state -> setShadeModel ( GL_SMOOTH ) ; + state -> enable ( GL_COLOR_MATERIAL ) ; + state -> enable ( GL_CULL_FACE ) ; + state -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + state -> setMaterial ( GL_EMISSION, 0, 0, 0, 1 ) ; + state -> setMaterial ( GL_SPECULAR, 0, 0, 0, 1 ) ; + state -> setShininess ( 0 ) ; + state -> setOpaque () ; + state -> disable ( GL_BLEND ) ; + + /* + Load the models - optimise them a bit + and then add them into the scene. + */ + + ssgEntity *tux_obj = ssgLoadAC ( "tuxedo.ac" ) ; + + penguin -> addKid ( tux_obj ) ; + ssgFlatten ( tux_obj ) ; + ssgStripify ( penguin ) ; + penguin -> clrTraversalMaskBits ( SSGTRAV_HOT ) ; + + for ( int i = 0 ; i < TILE_GRID_SIZE ; i++ ) + for ( int j = 0 ; j < TILE_GRID_SIZE ; j++ ) + { + tilegrid [ i ][ j ] = new ssgTransform ; + + terrain -> addKid ( tilegrid [ i ][ j ] ) ; + + sgVec3 tilepos ; + sgSetVec3 ( tilepos, (float)i * TILE_SIZE - ONLINE_TERRAIN_RANGE, + (float)j * TILE_SIZE - ONLINE_TERRAIN_RANGE, 0.0f ) ; + + tilegrid [ i ][ j ] -> setTransform ( tilepos ) ; + createTile ( tilegrid [ i ][ j ], i, j, state ) ; + } + + scene -> addKid ( terrain ) ; + scene -> addKid ( penguin ) ; +} + + + +/* + The works. +*/ + +int main ( int, char ** ) +{ + init_graphics () ; + load_database () ; + glutMainLoop () ; + return 0 ; +} + diff --git a/examples/src/ssg/majik/majik_demo.dsp b/examples/src/ssg/majik/majik_demo.dsp new file mode 100644 index 0000000..b95e4c8 --- /dev/null +++ b/examples/src/ssg/majik/majik_demo.dsp @@ -0,0 +1,96 @@ +# Microsoft Developer Studio Project File - Name="majik_demo" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=majik_demo - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "majik_demo.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "majik_demo.mak" CFG="majik_demo - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "majik_demo - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "majik_demo - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "majik_demo - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg.lib sg.lib ul.lib js.lib winmm.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /machine:I386 /out:"majik_demo.exe" /libpath:"..\..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "majik_demo - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg_d.lib sg_d.lib ul_d.lib js_d.lib winmm.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /debug /machine:I386 /out:"majik_demo.exe" /pdbtype:sept /libpath:"..\..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "majik_demo - Win32 Release" +# Name "majik_demo - Win32 Debug" +# Begin Source File + +SOURCE=.\elevation_map.h +# End Source File +# Begin Source File + +SOURCE=.\image_map.h +# End Source File +# Begin Source File + +SOURCE=.\majik_demo.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/ssg/shapes/Makefile.am b/examples/src/ssg/shapes/Makefile.am new file mode 100644 index 0000000..3a41859 --- /dev/null +++ b/examples/src/ssg/shapes/Makefile.am @@ -0,0 +1,10 @@ +if BUILD_SSG + +noinst_PROGRAMS = shapes + +shapes_SOURCES = shapes.cxx + +shapes_LDADD = -lplibssgaux -lplibssg -lplibsg -lplibul -lplibpw $(OGL_LIBS) + +endif + diff --git a/examples/src/ssg/shapes/shapes.cxx b/examples/src/ssg/shapes/shapes.cxx new file mode 100644 index 0000000..3b0dbce --- /dev/null +++ b/examples/src/ssg/shapes/shapes.cxx @@ -0,0 +1,180 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: shapes.cxx 2015 2005-02-02 15:48:09Z sjbaker $ +*/ + + +#include +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include +#include +#include +#include + +#define MAX_SHAPE 5 +static ssgRoot *scene = NULL ; +static ssgTransform *shape [ MAX_SHAPE ] = { NULL } ; + +static sgVec4 colour [ MAX_SHAPE ] = +{ + { 1, 0, 0, 1 }, + { 0, 1, 0, 1 }, + { 0, 0, 1, 1 }, + { 1, 1, 0, 1 }, + { 0, 1, 1, 1 } +} ; + +/* + Something to make some interesting motion +*/ + +static void update_motion () +{ + static int frameno = 0 ; + + frameno++ ; + + sgCoord campos ; + + sgSetCoord ( & campos, 0.0f, -6.0f, 0.0f, 0.0f, 0.0f, 0.0f ) ; + ssgSetCamera ( & campos ) ; + + for ( int i = 0 ; i < MAX_SHAPE ; i++ ) + { + sgCoord pos ; + sgSetCoord ( & pos, 2.0f*(float)(i % 3)-2.0f, 0.0f, + 2.0f*(float)(i / 3)-1.5f, + frameno/100.0f, frameno/20.0f, 0.0f ) ; + shape [ i ] -> setTransform ( & pos ) ; + } +} + + +static void redraw () +{ + update_motion () ; + + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + ssgCullAndDraw ( scene ) ; + + pwSwapBuffers () ; +} + + + +static void init_graphics () +{ + pwInit ( 100, 100, 640, 480, false, "PLIB Shapes Demo", true, 0 ) ; + pwSetCallbacks ( NULL, NULL, NULL, NULL, NULL ) ; + + /* + Initialise SSG + */ + + ssgInit () ; + + /* + Some basic OpenGL setup + */ + + glClearColor ( 0.2f, 0.7f, 1.0f, 1.0f ) ; + glEnable ( GL_DEPTH_TEST ) ; + + /* + Set up the viewing parameters + */ + + ssgSetFOV ( 60.0f, 0.0f ) ; + ssgSetNearFar ( 1.0f, 700.0f ) ; + + /* + Set up the Sun. + */ + + sgVec3 sunposn ; + sgSetVec3 ( sunposn, 0.2f, -0.5f, 0.5f ) ; + ssgGetLight ( 0 ) -> setPosition ( sunposn ) ; +} + + +/* + Create a simple database +*/ + +static void load_database () +{ + scene = new ssgRoot ; + + ssgSimpleState *state = new ssgSimpleState () ; + state -> setShininess ( 8.0f ) ; + + for ( int i = 0 ; i < MAX_SHAPE ; i++ ) + { + ssgaShape *s ; + + shape [ i ] = new ssgTransform ; + scene -> addKid ( shape [ i ] ) ; + + switch ( i ) + { + case 0 : s = new ssgaCube ( 1000 ) ; break ; + case 1 : s = new ssgaCylinder ( 1000 ) ; break ; + case 2 : s = new ssgaSphere ( 1000 ) ; + ((ssgaSphere*)s) -> setLatLongStyle ( FALSE) ; break ; + case 3 : s = new ssgaSphere ( 1000 ) ; + ((ssgaSphere*)s) -> setLatLongStyle ( TRUE ) ; break ; + case 4 : + default: s = new ssgaTeapot ( 1000 ) ; break ; + } + + s -> setColour ( colour[i] ) ; + s -> setKidState ( state ) ; + shape [ i ] -> addKid ( s ) ; + } +} + + + +/* + The works. +*/ + +int main ( int, char ** ) +{ + init_graphics () ; + load_database () ; + + while ( 1 ) + redraw () ; + + return 0 ; +} + + + diff --git a/examples/src/ssg/shrubs/Makefile.am b/examples/src/ssg/shrubs/Makefile.am new file mode 100644 index 0000000..dfdcaca --- /dev/null +++ b/examples/src/ssg/shrubs/Makefile.am @@ -0,0 +1,12 @@ +if BUILD_SSG + +noinst_PROGRAMS = shrubs + +shrubs_SOURCES = shrubs.cxx + +shrubs_LDADD = -lplibssgaux -lplibssg -lplibpu -lplibfnt -lplibsg -lplibul $(GLUT_LIBS) $(OGL_LIBS) + +endif + +EXTRA_DIST = + diff --git a/examples/src/ssg/shrubs/data/Courier-Bold.txf b/examples/src/ssg/shrubs/data/Courier-Bold.txf new file mode 100644 index 0000000..13b0205 Binary files /dev/null and b/examples/src/ssg/shrubs/data/Courier-Bold.txf differ diff --git a/examples/src/ssg/shrubs/data/deciduous-tree.rgb b/examples/src/ssg/shrubs/data/deciduous-tree.rgb new file mode 100644 index 0000000..d59441f Binary files /dev/null and b/examples/src/ssg/shrubs/data/deciduous-tree.rgb differ diff --git a/examples/src/ssg/shrubs/shrubs.cxx b/examples/src/ssg/shrubs/shrubs.cxx new file mode 100644 index 0000000..e960a9e --- /dev/null +++ b/examples/src/ssg/shrubs/shrubs.cxx @@ -0,0 +1,718 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: shrubs.cxx 2053 2005-11-14 12:12:25Z bram $ +*/ + +// $Id: shrubs.cxx 2053 2005-11-14 12:12:25Z bram $ + +#include +#include +#include +#include + +#include +#include + +#ifdef UL_WIN32 +# include +#else +# include +# include +#endif + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef UL_MAC_OSX +# include +# else +# include +# endif +#endif + + +#define TILE_RES 12 +#define NUM_TILES (TILE_RES * TILE_RES) + +#define TILE_SIZE 300.0f +#define WORLD_SIZE (TILE_RES * TILE_SIZE) + +#define FRAC_LEVEL 7 // --> 128*128 + + +// framerate control +static double min_delta = 1.0 / 200.0; +static double cur_delta = 1.0 / 50.0; + +// terrain grid (display list) +static GLuint grid; +static bool draw_grid = true; + +// billboard config +static float near_dist = 500.0f; +static float fade_dist = 2000.0f; +static float clip_dist = 2500.0f; +static int draw_num = 1000; +static int fade_num = 100; + +// state variables (GLUT enforced) +static int winsx = 800, winsy = 600; +static int mousex, mousey, bstate; + +// motion model +static int model = 1; // 0 - trackball, 1 - fly + +// trackball +static sgQuat rot = { 0, 0, 0, 1 }; +static sgVec3 tra = { 0, 1500, 0 }; + +// fly +static sgVec2 spin; +static float thrust; +static float speed; +static sgVec3 hpr; +static sgVec3 pos = { 0, -0.25f * WORLD_SIZE, 20.0f }; +static sgVec3 dir = { 0, 1, 0 }; + +// scene +static ssgRoot *scene; +static ssgaBillboards *bb[NUM_TILES]; + +// gui +static fntRenderer *text; +static puSlider *near_dist_sl, *fade_dist_sl, *clip_dist_sl; +static puSlider *draw_num_sl, *fade_num_sl; + + +inline float clampf(float x, float lo, float hi) +{ + return x <= lo ? lo : x >= hi ? hi : x; +} + + +static double get_time() +{ +#ifdef UL_WIN32 + static LONGLONG t0, f; + LONGLONG t; + QueryPerformanceCounter((LARGE_INTEGER *) &t); + if (f == 0) { + QueryPerformanceFrequency((LARGE_INTEGER *) &f); + t0 = t; + } + return (double) (t - t0) / f; +#else + static struct timeval t0; + struct timeval t; + gettimeofday(&t, 0); + if (t0.tv_sec == 0) + t0 = t; + return (t.tv_sec - t0.tv_sec) + 1e-6 * (t.tv_usec - t0.tv_usec); +#endif +} + + +#ifdef UL_WIN32 +inline void srand48(int seed) { srand(seed); } +inline double drand48() { return (double) rand() / RAND_MAX; } +#endif + +#ifdef _MSC_VER /* UL_MSVC sometimes defined for mingw (gcc) */ +inline float hypotf(float x, float y) { return sqrtf(x*x + y*y); } +#define snprintf _snprintf +#endif + + +static void motion_fn(int x, int y) +{ + if (bstate || !puMouse(x, y)) { + + if (model == 1) { + if (bstate & 4) { + spin[0] = 0; + spin[1] = 0; + } else { + spin[0] = 2.0f * x / winsx - 1.0f; + spin[1] = 2.0f * y / winsy - 1.0f; + } + } else { + float fx = 2.0f * x / winsx - 1.0f; + float fy = 1.0f - 2.0f * y / winsy; + float dx = 2.0f * (x - mousex) / winsx; + float dy = 2.0f * (mousey - y) / winsy; + + if (bstate & 1) { + float a = 0.5f * hypotf(dx, dy); + if (a > 1e-6f) { + sgQuat q; + q[0] = dy * (1.0f - fx * fx); + q[1] = dy * fx - dx * fy; + q[2] = dx * (fy * fy - 1.0f); + sgScaleVec3(q, sinf(a) / sgLengthVec3(q)); + q[3] = cosf(a); + sgMultQuat(rot, rot, q); + } + } + + if (bstate & 4) { + tra[1] = tra[1] / (1.0f - dy); + } + } + } + mousex = x; + mousey = y; +} + + +static void mouse_fn(int button, int updown, int x, int y) +{ + if (bstate || !puMouse(button, updown, x, y)) { + int bit = 0; + switch (button) { + case GLUT_LEFT_BUTTON: bit = 1; break; + case GLUT_MIDDLE_BUTTON: bit = 2; break; + case GLUT_RIGHT_BUTTON: bit = 4; break; + } + switch (updown) { + case GLUT_DOWN: bstate |= bit; break; + case GLUT_UP: bstate &= ~bit; break; + } + thrust = (bstate & 1) - (bstate & 4) / 2; + if (bstate & 4) { + spin[0] = 0; + spin[1] = 0; + } + } + mousex = x; + mousey = y; +} + + +static void special_fn(int key, int x, int y) +{ + if (!puKeyboard(key + PU_KEY_GLUT_SPECIAL_OFFSET, PU_DOWN)) { + switch (key) { + case GLUT_KEY_UP: min_delta *= 1.1; break; + case GLUT_KEY_DOWN: min_delta /= 1.1; break; + } + } +} + + +static void keyboard_fn(unsigned char key, int, int) +{ + if (!puKeyboard(key, PU_DOWN)) { + switch (key) { + case 0x1b: + exit(0); + case '1': + model = 0; + break; + case '2': + model = 1; + break; + case 'g': + draw_grid = !draw_grid; + break; + } + } +} + + + +static void update_bboards() +{ + for (int i = 0; i < NUM_TILES; i++) { + bb[i]->setNearRange(near_dist); + bb[i]->setFadeRange(fade_dist); + bb[i]->setClipRange(clip_dist); + bb[i]->setDrawNum(draw_num); + bb[i]->setFadeNum(fade_num); + } +} + +static void near_dist_cb(puObject *ob) +{ + near_dist = ob->getFloatValue(); + update_bboards(); +} + +static void fade_dist_cb(puObject *ob) +{ + fade_dist = ob->getFloatValue(); + update_bboards(); +} + +static void clip_dist_cb(puObject *ob) +{ + clip_dist = ob->getFloatValue(); + update_bboards(); +} + +static void draw_num_cb(puObject *ob) +{ + draw_num = ob->getIntegerValue(); + update_bboards(); +} + +static void fade_num_cb(puObject *ob) +{ + fade_num = ob->getIntegerValue(); + update_bboards(); +} + + + +static void init_scene() +{ + int i, x, y; + + scene = new ssgRoot; + + // produce a simple diamond-square fractal + const int size = 1 << FRAC_LEVEL; + const int mask = size - 1; + float *elev = new float[size * size]; // height map + memset(elev, 0, sizeof(elev)); + for (i = FRAC_LEVEL; i > 0; i--) { + int s = 1 << i, t = s >> 1; + float r = 750.0f * powf(s / size, 0.9f); + for (y = 0; y < size; y += s) { + int y1 = (y + s) & mask; + for (x = 0; x < size; x += s) { + int x1 = (x + s) & mask; + elev[(y + t) * size + (x + t)] = (0.25f * (elev[y * size + x ] + + elev[y * size + x1] + + elev[y1 * size + x ] + + elev[y1 * size + x1]) + + r * (0.5f - (float) drand48())); + } + } + r = 750.0f * powf(0.7071f * s / size, 0.9f); + for (y = 0; y < size; y += s) { + int y0 = (y - t) & mask; + int y1 = (y + s) & mask; + for (x = 0; x < size; x += s) { + int x0 = (x - t) & mask; + int x1 = (x + s) & mask; + elev[y * size + (x + t)] = (0.25f * (elev[y0 * size + (x + t)] + + elev[y * size + x ] + + elev[y * size + x1] + + elev[(y + t) * size + (x + t)]) + + r * (0.5f - (float) drand48())); + elev[(y + t) * size + x] = (0.25f * (elev[(y + t) * size + x0] + + elev[y * size + x] + + elev[y1 * size + x] + + elev[(y + t) * size + (x + t)]) + + r * (0.5f - (float) drand48())); + } + } + } + + // generate display list + grid = glGenLists(1); + glNewList(grid, GL_COMPILE); + for (y = 0; y <= size; y += 4) { + glBegin(GL_LINE_STRIP); + for (x = 0; x <= size; x++) + glVertex3f(((float) x / size - 0.5f) * WORLD_SIZE, + ((float) y / size - 0.5f) * WORLD_SIZE, + elev[(y & mask) * size + (x & mask)]); + glEnd(); + } + for (x = 0; x <= size; x += 4) { + glBegin(GL_LINE_STRIP); + for (y = 0; y <= size; y++) + glVertex3f(((float) x / size - 0.5f) * WORLD_SIZE, + ((float) y / size - 0.5f) * WORLD_SIZE, + elev[(y & mask) * size + (x & mask)]); + glEnd(); + } + glEndList(); + + + // now load the shrubs + + ssgTexture *tex = new ssgTexture("data/deciduous-tree.rgb", FALSE, FALSE); + + ssgaBillboards::initTexAlpha(tex); + + for (y = 0; y < TILE_RES; y++) { + for (x = 0; x < TILE_RES; x++) { + ssgaBillboards *b = new ssgaBillboards; + + b->setTexture(tex); + b->setWidth(3.0f); + b->setHeight(8.0f); + + float tx = (x - 0.5f * TILE_RES) * TILE_SIZE; + float ty = (y - 0.5f * TILE_RES) * TILE_SIZE; + + for (int i = 0; i < 3000; i++) { + + float x = tx + drand48() * TILE_SIZE; + float y = ty + drand48() * TILE_SIZE; + float z; + + // bilinear lookup + float xf = (0.5f + x / WORLD_SIZE) * size; + float yf = (0.5f + y / WORLD_SIZE) * size; + int x0 = (int) xf; + int y0 = (int) yf; + int x1 = x0 + 1; + int y1 = y0 + 1; + float xw1 = xf - (float) x0; + float yw1 = yf - (float) y0; + float xw0 = 1.0f - xw1; + float yw0 = 1.0f - yw1; + x0 &= mask; + y0 &= mask; + x1 &= mask; + y1 &= mask; + z = (elev[y0 * size + x0] * xw0 * yw0 + + elev[y0 * size + x1] * xw1 * yw0 + + elev[y1 * size + x0] * xw0 * yw1 + + elev[y1 * size + x1] * xw1 * yw1); + + b->add(x, y, z, 0.75f + 0.5f * drand48()); + } + + bb[y * TILE_RES + x] = b; + + scene->addKid(b); + } + } + + x = (int)((0.5f + pos[0] / WORLD_SIZE) * size); + y = (int)((0.5f + pos[1] / WORLD_SIZE) * size); + pos[2] += elev[(y & mask) * size + (x & mask)]; + + delete [] elev; + + update_bboards(); +} + + +static void init_gui() +{ + fntInit(); + + fntTexFont *font = new fntTexFont("data/Courier-Bold.txf"); + + text = new fntRenderer(); + text->setFont(font); + text->setPointSize(18); + + puInit(); + + puSetDefaultFonts(puFont(font, 14), puFont(font, 18)); + puSetDefaultStyle(PUSTYLE_SMALL_SHADED); + puSetDefaultColourScheme(0.7f, 0.7f, 0.7f, 1.0f); + + puGroup *group = new puGroup(0, 0); + puSlider *sl; + int h = winsy; + + near_dist_sl = sl = new puSlider(250, h - 30, 150); + sl->setValue(near_dist); + sl->setMinValue(100.0f); + sl->setMaxValue(5000.0f); + sl->setCallback(near_dist_cb); + + fade_dist_sl = sl = new puSlider(250, h - 55, 150); + sl->setValue(fade_dist); + sl->setMinValue(100.0f); + sl->setMaxValue(5000.0f); + sl->setCallback(fade_dist_cb); + + clip_dist_sl = sl = new puSlider(250, h - 80, 150); + sl->setValue(clip_dist); + sl->setMinValue(100.0f); + sl->setMaxValue(5000.0f); + sl->setCallback(clip_dist_cb); + + draw_num_sl = sl = new puSlider(250, h - 110, 150); + sl->setValue(draw_num); + sl->setMinValue(0); + sl->setMaxValue(3000); + sl->setCallback(draw_num_cb); + + fade_num_sl = sl = new puSlider(250, h - 135, 150); + sl->setValue(fade_num); + sl->setMinValue(0); + sl->setMaxValue(3000); + sl->setCallback(fade_num_cb); + + group->close(); +} + + +static void reshape_fn(int w, int h) +{ + winsx = w; + winsy = h; + + glViewport(0, 0, w, h); + + if (near_dist_sl) { + near_dist_sl->setPosition(250, h - 30); + fade_dist_sl->setPosition(250, h - 55); + clip_dist_sl->setPosition(250, h - 80); + draw_num_sl->setPosition(250, h - 110); + fade_num_sl->setPosition(250, h - 135); + } +} + + +static void display_fn() +{ + static float backlog1[256]; + static float backlog2[256]; + + static double last_time; + static double sync_time; + static int frame_count; + + double t0 = get_time(); + int i; + + frame_count++; + + glClearColor(0.5f, 0.5f, 0.5f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); + + sgMat4 mat; + + if (model == 0) { + // trackball + sgQuatToMatrix(mat, rot); + sgCopyVec3(mat[3], tra); + sgTransposeNegateMat4(mat); + } else { + // fly + float dt = cur_delta; + float s = powf(0.2f, dt); + hpr[2] = s * hpr[2] + (1.0f - s) * 40.0f * spin[0]; + hpr[1] = s * hpr[1] + (1.0f - s) * 40.0f * spin[1]; + hpr[0] -= dt * hpr[2]; + float a = 10.0f * (thrust - dir[2]); + speed = clampf(speed + a * dt, 1.0f, 25.0f); + sgAddScaledVec3(pos, dir, dt * speed); + sgMakeCoordMat4(mat, pos, hpr); + sgCopyVec3(dir, mat[1]); + } + + ssgaBillboards::total_drawn = 0; + + ssgSetCamera(mat); + ssgCullAndDraw(scene); + ssgLoadModelviewMatrix(); + + glDisable(GL_TEXTURE_2D); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_LIGHTING); + glDisable(GL_BLEND); + glDisable(GL_LINE_SMOOTH); + + if (draw_grid) { + glColor3f(0, 0, 0); + glCallList(grid); + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glAlphaFunc(GL_GREATER, 0.3f); + glEnable(GL_ALPHA_TEST); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + + // timings + + const float y0 = 0.45f, y1 = 1.0f; + const float d0 = 0, d1 = 0.05f; + + glBegin(GL_LINE_STRIP); + glColor3f(0.4f, 0.7f, 0.4f); + for (i = 1; i <= 256; i++) { + float d = backlog2[(frame_count - i) & 0xff]; + glVertex2f(2.0f * i / 257 - 1.0f, y0 + (y1 - y0) * (d - d0) / (d1 - d0)); + } + glEnd(); + + glBegin(GL_LINE_STRIP); + glColor3f(0.7f, 0.7f, 0.7f); + for (i = 1; i <= 256; i++) { + float d = backlog1[(frame_count - i) & 0xff]; + glVertex2f(2.0f * i / 257 - 1.0f, y0 + (y1 - y0) * (d - d0) / (d1 - d0)); + } + glEnd(); + + glBegin(GL_LINES); + glColor3f(0.3f, 0.4f, 0.4f); + float y = y0 + (y1 - y0) * ((float) min_delta - d0) / (d1 - d0); + glVertex2f(-1.0f, y); + glVertex2f( 1.0f, y); + glEnd(); + + + // gui + + int w = winsx; + int h = winsy; + char buf[64]; + + glOrtho(0, w, 0, h, 0, 1); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glColor3f(0, 0, 0); + + text->begin(); + + text->start2f(w - 200, h - 30); + text->puts("fps:"); + snprintf(buf, sizeof(buf), "%.0f Hz", 1.0 / cur_delta); + text->start2f(w - 100, h - 30); + text->puts(buf); + + text->start2f(w - 200, h - 55); + text->puts("shrubs:"); + snprintf(buf, sizeof(buf), "%d\n", ssgaBillboards::total_drawn); + text->start2f(w - 100, h - 55); + text->puts(buf); + + text->start2f(20, h - 30); + text->puts("NearRange:"); + snprintf(buf, sizeof(buf), "%5.0f", near_dist); + text->start2f(150, h - 30); + text->puts(buf); + + text->start2f(20, h - 55); + text->puts("FadeRange:"); + snprintf(buf, sizeof(buf), "%5.0f", fade_dist); + text->start2f(150, h - 55); + text->puts(buf); + + text->start2f(20, h - 80); + text->puts("ClipRange:"); + snprintf(buf, sizeof(buf), "%5.0f", clip_dist); + text->start2f(150, h - 80); + text->puts(buf); + + text->start2f(20, h - 110); + text->puts("DrawNum:"); + snprintf(buf, sizeof(buf), "%5d", draw_num); + text->start2f(150, h - 110); + text->puts(buf); + + text->start2f(20, h - 135); + text->puts("FadeNum:"); + snprintf(buf, sizeof(buf), "%5d", fade_num); + text->start2f(150, h - 135); + text->puts(buf); + + text->end(); + + puDisplay(); + + glFinish(); + + + // sync + + double t1 = get_time(); + + backlog1[frame_count & 0xff] = t1 - t0; + backlog2[frame_count & 0xff] = t1 - last_time; + + last_time = t1; + + sync_time += min_delta; + + if (t1 < sync_time) { + double dt = sync_time - t1 - 0.005; + if (dt > 0) { +#ifdef UL_WIN32 + Sleep((int)(1e+3 * dt)); +#else + usleep((int)(1e+6 * dt)); +#endif + } + } else if (t1 > sync_time + 0.05) + sync_time = t1; + + cur_delta = 0; + for (i = 0; i < 256; i++) + cur_delta += backlog2[i]; + cur_delta *= 1.0 / 256; + + glutSwapBuffers(); + glutPostRedisplay(); +} + + + +int main(int argc, char** argv) +{ + srand48(time(0)); + + glutInit(&argc, argv); + glutInitWindowSize(winsx, winsy); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); + glutCreateWindow("shrubs"); + + glutDisplayFunc(display_fn); + glutReshapeFunc(reshape_fn); + glutMouseFunc(mouse_fn); + glutMotionFunc(motion_fn); + glutKeyboardFunc(keyboard_fn); + glutSpecialFunc(special_fn); + + ssgInit(); + + ssgSetFOV(60.0f, 0.0f); + ssgSetNearFar(10.0f, 10000.0f); + + //ssgModelPath("."); + //ssgTexturePath("."); + + init_scene(); + + init_gui(); + + glutMainLoop(); + + return 0; +} + + +/* + Local Variables: + mode: C++ + c-basic-offset: 4 + c-file-offsets: ((substatement-open 0) (case-label 0)) + End: +*/ diff --git a/examples/src/ssg/sky/Makefile.am b/examples/src/ssg/sky/Makefile.am new file mode 100644 index 0000000..3599ca5 --- /dev/null +++ b/examples/src/ssg/sky/Makefile.am @@ -0,0 +1,12 @@ +if BUILD_SSG + +noinst_PROGRAMS = sky + +sky_SOURCES = sky.cxx + +sky_LDADD = -lplibpuaux -lplibpu -lplibfnt -lplibssgaux -lplibssg -lplibsg -lplibul $(GLUT_LIBS) $(OGL_LIBS) + +endif + +EXTRA_DIST = sky.dsp README + diff --git a/examples/src/ssg/sky/README b/examples/src/ssg/sky/README new file mode 100644 index 0000000..ebdc29b --- /dev/null +++ b/examples/src/ssg/sky/README @@ -0,0 +1,39 @@ + +SkyDome. +~~~~~~~~~~~~~~~~ + +The PLIB ssgAux library contains a class for creating a sky dome. + + class ssgaSky ; + +The program in this directory demonstrates creating a sky dome, +including the sun, moon, stars and clouds. + +This program does not attempt to place celestial bodies accurately +if you wish to place sun, moon, planets & stars correctly then you +could possibly plug-in the SimGear Ephemeris code. + + +Keyboard controls: + +left/right : turn left/right +up/down arrow : look up/down +up/down arrow + shift : increase/decrease altitude +a/z : move forward/backward +f : fullscreen +w : wireframe +s : solid +space : toggle gui on and off +q/esc : quit + + +History: + +Written by Durk Talsma. Originally started October 1997, for distribution +with the FlightGear project. Version 2 was written in August and +September 1998. This code is based upon algorithms and data kindly +provided by Mr. Paul Schlyter. (pausch@saaf.se). + +Separated out rendering pieces and converted to ssg by Curt Olson, March 2000. + +Moved (from SimGear) into ssgAux by Nick McEvoy, July 2003. \ No newline at end of file diff --git a/examples/src/ssg/sky/data/candy.rgb b/examples/src/ssg/sky/data/candy.rgb new file mode 100644 index 0000000..c897f26 Binary files /dev/null and b/examples/src/ssg/sky/data/candy.rgb differ diff --git a/examples/src/ssg/sky/data/halo.rgba b/examples/src/ssg/sky/data/halo.rgba new file mode 100644 index 0000000..e02d6b3 Binary files /dev/null and b/examples/src/ssg/sky/data/halo.rgba differ diff --git a/examples/src/ssg/sky/data/moon.rgba b/examples/src/ssg/sky/data/moon.rgba new file mode 100644 index 0000000..0d9c721 Binary files /dev/null and b/examples/src/ssg/sky/data/moon.rgba differ diff --git a/examples/src/ssg/sky/data/ocean.rgb b/examples/src/ssg/sky/data/ocean.rgb new file mode 100644 index 0000000..a72795b Binary files /dev/null and b/examples/src/ssg/sky/data/ocean.rgb differ diff --git a/examples/src/ssg/sky/data/scattered.rgba b/examples/src/ssg/sky/data/scattered.rgba new file mode 100644 index 0000000..1ed0d9b Binary files /dev/null and b/examples/src/ssg/sky/data/scattered.rgba differ diff --git a/examples/src/ssg/sky/data/sorority.txf b/examples/src/ssg/sky/data/sorority.txf new file mode 100644 index 0000000..8b457aa Binary files /dev/null and b/examples/src/ssg/sky/data/sorority.txf differ diff --git a/examples/src/ssg/sky/sky.cxx b/examples/src/ssg/sky/sky.cxx new file mode 100644 index 0000000..269860d --- /dev/null +++ b/examples/src/ssg/sky/sky.cxx @@ -0,0 +1,688 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: sky.cxx 2077 2006-04-13 16:21:42Z bram $ +*/ + + +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include +#include +#include +#include +#include +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#define ROT_SPEED 2.0f +#define TRANS_SPEED 5.0f + +#define MAX_BODIES 2 +#define MAX_CLOUDS 3 + +#define GUI_BASE 20 +#define FONT_COLOUR 1,1,1,1 + +static int wireframe = FALSE ; +static int displayGUI = TRUE ; + +static puaSelectBox *bodySelectBox = (puaSelectBox *) NULL ; +static puDial *bodyRADial = (puDial *) NULL ; +static puDial *bodyDeclDial = (puDial *) NULL ; +static puSlider *cloudElevationSlider = (puSlider *) NULL ; +static puaSelectBox *cloudSelectBox = (puaSelectBox *) NULL ; +static puButton *cloudEnableButton = (puButton *) NULL ; + +static ssgRoot *scene = NULL ; +static ssgaSky *sky = NULL ; +static ssgTransform *teapot = NULL ; +static ssgTransform *wave = NULL ; + +static ssgaTeapot *tpt_obj = NULL ; +static ssgaWaveSystem *wave_obj = NULL ; +static ssgaWaveTrain wave_train; + +static ssgaCelestialBody *bodies[MAX_BODIES] = {NULL} ; +static ssgaCloudLayer *clouds[MAX_CLOUDS] = {NULL} ; + +static ssgSimpleState *teapot_state = NULL ; +static ssgSimpleState *wave_state = NULL ; + +static int nstars = 1000 ; +static sgdVec3 *star_data = NULL ; +static int nplanets = 0 ; +static sgdVec3 *planet_data = NULL ; + +static char *bodyNameList[] = { "Sun", "Moon", NULL } ; +static char *cloudNameList[] = { "Cloud 0", "Cloud 1", "Cloud 2", NULL } ; + +static int curr_body = 0 ; +static int curr_cloud = 0 ; + +static sgVec4 black = { 0.0f, 0.0f, 0.0f, 1.0f } ; +static sgVec4 white = { 1.0f, 1.0f, 1.0f, 1.0f } ; +static sgVec4 translucent_white = { 1.0f, 1.0f, 1.0f, 0.8f } ; + +static sgVec4 base_sky_color = { 0.39f, 0.50f, 0.74f, 1.0f } ; +static sgVec4 base_fog_color = { 0.84f, 0.87f, 1.00f, 1.0f } ; + +static sgVec4 base_ambient = { 0.2f, 0.2f, 0.2f, 1.0f } ; +static sgVec4 base_diffuse = { 1.0f, 1.0f, 1.0f, 1.0f } ; +static sgVec4 base_specular = { 1.0f, 1.0f, 1.0f, 1.0f } ; + +static sgVec4 sky_color ; +static sgVec4 fog_color ; +static sgVec4 cloud_color ; + +static sgVec4 scene_ambient ; +static sgVec4 scene_diffuse ; +static sgVec4 scene_specular ; + +static const double m_log01 = -log( 0.01 ); +static const double sqrt_m_log01 = sqrt( m_log01 ); + +static int mods = 0 ; +unsigned char keypress = 0 ; +static int special_key = 0 ; + +static sgCoord campos = { { -300, 0, 10 }, { -90, 0, 0 } } ; + +static void bodySelectBox_cb ( puObject *ob ) +{ + curr_body = ((puaSelectBox *) ob) -> getCurrentItem () ; + + if ( curr_body < 0 ) + curr_body = 0 ; + + if ( curr_body >= MAX_BODIES ) + curr_body = MAX_BODIES - 1 ; + + bodyRADial -> setValue ( float(bodies[curr_body]->getRightAscension () * SGD_RADIANS_TO_DEGREES) ) ; + bodyDeclDial -> setValue ( float(bodies[curr_body]->getDeclination () * SGD_RADIANS_TO_DEGREES) ) ; +} + +static void bodyRADial_cb ( puObject *ob ) +{ + bodies[curr_body] -> setRightAscension ( ob -> getFloatValue () * SGD_DEGREES_TO_RADIANS ) ; + ob -> setLegend ( ob -> getStringValue () ) ; +} + +static void bodyDeclDial_cb ( puObject *ob ) +{ + bodies[curr_body] -> setDeclination ( ob -> getFloatValue () * SGD_DEGREES_TO_RADIANS ) ; + ob -> setLegend ( ob -> getStringValue () ) ; +} + +static void cloudSelectBox_cb ( puObject *ob ) +{ + curr_cloud = ((puaSelectBox *) ob) -> getCurrentItem () ; + + if ( curr_cloud < 0 ) + curr_cloud = 0 ; + + if ( curr_cloud >= MAX_CLOUDS ) + curr_cloud = MAX_CLOUDS - 1 ; + + cloudElevationSlider -> setValue ( clouds[curr_cloud]->getElevation() ) ; + cloudEnableButton -> setValue ( clouds[curr_cloud]->isEnabled() ) ; +} + +static void cloudElevationSlider_cb ( puObject *ob ) +{ + clouds[curr_cloud] -> setElevation ( ob -> getFloatValue () ) ; + ob -> setLegend ( ob -> getStringValue () ) ; +} + +static void cloudEnableButton_cb ( puObject *ob ) +{ + if ( ob -> getIntegerValue () ) + clouds[curr_cloud] -> enable() ; + else + clouds[curr_cloud] -> disable() ; +} + +static void update_motion () +{ + static int frameno = 0 ; + static ulClock ck ; + + frameno++ ; + + ck . update () ; + + double t = ck . getAbsTime () ; + double dt = ck . getDeltaTime () ; + + /* update camera + + keyboard controls: + - left/right : turn left/right + - up/down arrow : look up/down + - up/down arrow + shift : increase/decrease altitude + - a/z : move forward/backward + + todo: add mouse or joystick support + */ + + if ( special_key == GLUT_KEY_UP ) + { + if ( mods & GLUT_ACTIVE_SHIFT ) + campos.xyz[SG_Z] += TRANS_SPEED ; + else + campos.hpr[1] += ROT_SPEED ; + } + else if ( special_key == GLUT_KEY_DOWN ) + { + if ( mods & GLUT_ACTIVE_SHIFT ) + campos.xyz[SG_Z] -= TRANS_SPEED ; + else + campos.hpr[1] -= ROT_SPEED ; + } + else if ( special_key == GLUT_KEY_LEFT ) + campos.hpr[0] += ROT_SPEED ; + else if ( special_key == GLUT_KEY_RIGHT ) + campos.hpr[0] -= ROT_SPEED ; + + if ( keypress == 'a' || keypress == 'A' ) + { + campos.xyz[SG_X] -= sgSin ( campos.hpr[0] * SG_DEGREES_TO_RADIANS ) * TRANS_SPEED ; + campos.xyz[SG_Y] += sgCos ( campos.hpr[0] * SG_DEGREES_TO_RADIANS ) * TRANS_SPEED ; + } + else if ( keypress == 'z' || keypress == 'Z' ) + { + campos.xyz[SG_X] += sgSin ( campos.hpr[0] * SG_DEGREES_TO_RADIANS ) * TRANS_SPEED ; + campos.xyz[SG_Y] -= sgCos ( campos.hpr[0] * SG_DEGREES_TO_RADIANS ) * TRANS_SPEED ; + } + + ssgSetCamera ( & campos ) ; + + /* update teapot */ + + sgCoord teapotpos ; + sgSetCoord ( & teapotpos, -280.0f, -8.0f, 3.0f, frameno/5.0f, 0.0f, 0.0f ) ; + teapot -> setTransform ( & teapotpos ) ; + + /* update waves */ + + sgCoord wavepos ; + sgSetCoord ( & wavepos, 0, 0, 0, 0, 0, 0 ) ; + wave -> setTransform ( & wavepos ) ; + wave_obj -> updateAnimation ( (float)t ) ; + + /* move heaven & earth ... + if you wish to place sun, moon, planets & stars correctly then + you will need to use SimGear Ephemeris code */ + //bodies[0] -> setDeclination ( bodies[0] -> getDeclination() - 0.01*SGD_DEGREES_TO_RADIANS ); + //bodies[1] -> setDeclination ( bodies[1] -> getDeclination() - 0.01*SGD_DEGREES_TO_RADIANS ); + + /* update sky */ + + sky -> repositionFlat ( campos.xyz, 0, dt ); + sky -> modifyVisibility ( campos.xyz[SG_Z], (float)dt ); + + double sol_angle = bodies[0]->getAngle(); + double sky_brightness = (1.0 + cos(sol_angle))/2.0; // 0.0 - 1.0 + double scene_brightness = pow(sky_brightness,0.5); + + /* set sky color */ + sky_color[0] = base_sky_color[0] * (float)sky_brightness; + sky_color[1] = base_sky_color[1] * (float)sky_brightness; + sky_color[2] = base_sky_color[2] * (float)sky_brightness; + sky_color[3] = base_sky_color[3]; + + /* set cloud and fog color */ + cloud_color[0] = fog_color[0] = base_fog_color[0] * (float)sky_brightness; + cloud_color[1] = fog_color[1] = base_fog_color[1] * (float)sky_brightness; + cloud_color[2] = fog_color[2] = base_fog_color[2] * (float)sky_brightness; + cloud_color[3] = fog_color[3] = base_fog_color[3]; + + /* repaint the sky */ + sky -> repaint ( sky_color, fog_color, cloud_color, sol_angle, nplanets, planet_data, nstars, star_data ); + + /* set light source */ + sgCoord solpos; + bodies[0] -> getPosition ( & solpos ); + ssgGetLight ( 0 ) -> setPosition ( solpos.xyz ) ; + + scene_ambient[0] = base_ambient[0] * (float)scene_brightness; + scene_ambient[1] = base_ambient[1] * (float)scene_brightness; + scene_ambient[2] = base_ambient[2] * (float)scene_brightness; + scene_ambient[3] = 1.0; + + scene_diffuse[0] = base_diffuse[0] * (float)scene_brightness; + scene_diffuse[1] = base_diffuse[1] * (float)scene_brightness; + scene_diffuse[2] = base_diffuse[2] * (float)scene_brightness; + scene_diffuse[3] = 1.0; + + scene_specular[0] = base_specular[0] * (float)scene_brightness; + scene_specular[1] = base_specular[1] * (float)scene_brightness; + scene_specular[2] = base_specular[2] * (float)scene_brightness; + scene_specular[3] = 1.0; + // GL_LIGHT_MODEL_AMBIENT has a default non-zero value so if + // we only update GL_AMBIENT for our lights we will never get + // a completely dark scene. So, we set GL_LIGHT_MODEL_AMBIENT + // explicitely to black. + glLightModelfv( GL_LIGHT_MODEL_AMBIENT, black ); + ssgGetLight( 0 ) -> setColour( GL_AMBIENT, scene_ambient ); + ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, scene_diffuse ); + ssgGetLight( 0 ) -> setColour( GL_SPECULAR, scene_specular ); +} + + + +/* + The GLUT window reshape event +*/ + +static void reshape ( int w, int h ) +{ + glViewport ( 0, 0, w, h ) ; +} + + +/* + The GLUT keyboard/mouse events +*/ + +static void keyboard ( unsigned char key, int x, int y ) +{ + keypress = key; + + if ( key == 'f' || key == 'F' ) + /* fullscreen */ + glutFullScreen(); + else if ( key == 'w' || key == 'W' ) + /* wireframe */ + wireframe = TRUE ; + else if ( key == 's' || key == 'S' ) + /* fill */ + wireframe = FALSE ; + else if ( key == ' ' ) + /* show/hide gui */ + displayGUI = ! displayGUI ; + else if ( key == 'q' || key == 'Q' || key == 27 /* esc */ ) + /* quit */ + exit ( 0 ) ; +} + +static void keyboard_up ( unsigned char key, int x, int y ) +{ + keypress = 0; +} + +static void special ( int key, int x, int y ) +{ + mods = glutGetModifiers(); + special_key = key; +} + +static void special_up ( int key, int x, int y ) +{ + mods = glutGetModifiers(); + if ( special_key == key ) + special_key = 0; +} + +static void motionfn ( int x, int y ) +{ + if ( displayGUI ) + puMouse ( x, y ) ; +} + +static void mousefn ( int button, int updown, int x, int y ) +{ + if ( displayGUI ) + puMouse ( button, updown, x, y ) ; +} + +/* + The GLUT redraw event +*/ + +static void redraw () +{ + update_motion () ; + + glClearColor ( fog_color[0], fog_color[1], fog_color[2], fog_color[3] ) ; + + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + if ( wireframe ) + glPolygonMode ( GL_FRONT_AND_BACK, GL_LINE ) ; + else + glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL ) ; + + /* Adjust fog based on visibility (when in clouds) */ + GLfloat fog_exp2_density = (float)sqrt_m_log01 / sky->getVisibility(); + glEnable( GL_FOG ); + glFogf ( GL_FOG_DENSITY, fog_exp2_density); + glFogi ( GL_FOG_MODE, GL_EXP2 ); + glFogfv ( GL_FOG_COLOR, fog_color ); + + /* Draw scene */ + + // we need a white diffuse light for the phase of the moon + ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, white ); + + sky -> preDraw ( ); + + // return to the desired diffuse color + ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, scene_diffuse ); + + ssgCullAndDraw ( scene ) ; + sky -> postDraw ( campos.xyz[SG_Z] ); /* altitude */ + + /* Draw gui */ + + glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL ) ; + if ( displayGUI ) + puDisplay () ; + + glutPostRedisplay () ; + glutSwapBuffers () ; +} + + + +static void init_graphics () +{ + int fake_argc = 1 ; + char *fake_argv[3] ; + fake_argv[0] = "ssgExample" ; + fake_argv[1] = "Simple Scene Graph : Example Program." ; + fake_argv[2] = NULL ; + + /* Initialise GLUT */ + + glutInitWindowPosition ( 0, 0 ) ; + glutInitWindowSize ( 640, 480 ) ; + glutInit ( &fake_argc, fake_argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + glutCreateWindow ( fake_argv[1] ) ; + glutDisplayFunc ( redraw ) ; + glutReshapeFunc ( reshape ) ; + glutKeyboardFunc ( keyboard ) ; + glutKeyboardUpFunc ( keyboard_up ) ; + glutSpecialFunc ( special ) ; + glutSpecialUpFunc ( special_up ) ; + glutMouseFunc ( mousefn ) ; + glutMotionFunc ( motionfn ) ; + + /* Initialise SSG */ + + puInit () ; + ssgInit () ; + + /* Some basic OpenGL setup */ + + glEnable ( GL_DEPTH_TEST ) ; + + /* Set up the viewing parameters */ + + ssgSetFOV ( 60, 45 ) ; + ssgSetNearFar ( 1, 200000 ) ; /* nb. skydome is scalable ... so far can be reduced */ + + /* Set up the Sun */ + + sgVec3 solposn ; + sgSetVec3 ( solposn, 0, 0, 0 ) ; + ssgGetLight ( 0 ) -> setPosition ( solposn ) ; +} + + +/* + Load a simple database +*/ + +static void load_database () +{ + /* Set up the path to the data files */ + + ssgModelPath ( "data" ) ; + ssgTexturePath ( "data" ) ; + + /* Setup teapot state */ + + teapot_state = new ssgSimpleState () ; + teapot_state -> setTexture ( "data/candy.rgb" ) ; + teapot_state -> enable ( GL_TEXTURE_2D ) ; + teapot_state -> setShadeModel ( GL_SMOOTH ) ; + teapot_state -> enable ( GL_CULL_FACE ) ; + teapot_state -> enable ( GL_BLEND ) ; + teapot_state -> enable ( GL_LIGHTING ) ; + teapot_state -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + teapot_state -> setMaterial ( GL_EMISSION, 0, 0, 0, 1 ) ; + teapot_state -> setMaterial ( GL_SPECULAR, 1, 1, 1, 1 ) ; + teapot_state -> setShininess ( 2 ) ; + + /* Setup wave state */ + + wave_state = new ssgSimpleState () ; + wave_state -> setTexture ( "data/ocean.rgb" ) ; + wave_state -> enable ( GL_TEXTURE_2D ) ; + wave_state -> setShadeModel ( GL_SMOOTH ) ; + wave_state -> enable ( GL_CULL_FACE ) ; + wave_state -> enable ( GL_BLEND ) ; + wave_state -> enable ( GL_LIGHTING ) ; + wave_state -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + wave_state -> setMaterial ( GL_EMISSION, 0, 0, 0, 1 ) ; + wave_state -> setMaterial ( GL_SPECULAR, 1, 1, 1, 1 ) ; + wave_state -> setShininess ( 5 ) ; + + wave_train.setSpeed ( 1.0f ) ; + wave_train.setLength ( 3.0f ) ; + wave_train.setLambda ( 0.5f ) ; + wave_train.setHeading ( 30.0f ) ; + wave_train.setWaveHeight ( 1.5f ) ; + + /* Create object */ + + tpt_obj = new ssgaTeapot ( 1000 ) ; + tpt_obj -> setSize ( 2 ) ; + tpt_obj -> setKidState ( teapot_state ) ; + tpt_obj -> regenerate () ; + + sgVec3 pos = {0, 0, 0}; + + wave_obj = new ssgaWaveSystem ( 4000 ) ; + wave_obj->setColour ( white ) ; + wave_obj->setSize ( 80000 ) ; /* todo: fix this ... prefer size 2000, + but wave system has recently changed and + no longer stretches on for 'infinity' :( */ + wave_obj->setTexScale ( 32, 32 ) ; + wave_obj->setCenter ( pos ) ; + wave_obj->setKidState ( wave_state ) ; + wave_obj->setWindSpeed ( 10.0f ) ; + wave_obj->setWaveTrain ( 0, &wave_train ) ; + + /* Build the scene graph */ + + star_data = new sgdVec3[nstars] ; + for ( int i = 0; i < nstars; i++ ) + { + star_data[i][0] = ssgaRandom() * SGD_PI ; + star_data[i][1] = ssgaRandom() * SGD_PI ; + star_data[i][2] = ssgaRandom() ; + } + + /* sky */ + sky = new ssgaSky ; + sky -> build ( 80000, 80000, nplanets, planet_data, nstars, star_data ); + /* sun */ + bodies[0] = sky -> addBody ( + NULL, // body texture + "data/halo.rgba", // halo texture + 5000, // size + 80000, // distance + true ); // is sun - dome painted based on this + bodies[0] -> setDeclination ( 20*SGD_DEGREES_TO_RADIANS ); + /* moon */ + bodies[1] = sky -> addBody ( + "data/moon.rgba", // body texture + NULL, // halo texture + 5000, // size + 80000 ); // distance + bodies[1] -> setDeclination ( 65*SGD_DEGREES_TO_RADIANS ); + /* clouds */ + clouds[0] = sky -> addCloud ( + "data/scattered.rgba", // texture + 80000, // span + 2000, // elevation, + 100, // thickness + 100 ); // transition + clouds[0] -> setSpeed ( 50 ) ; + clouds[0] -> setDirection ( 45 ) ; + clouds[1] = sky -> addCloud ( + "data/scattered.rgba", // texture + 80000, // span + 3000, // elevation, + 100, // thickness + 100 ); // transition + clouds[1] -> setSpeed ( 20 ) ; + clouds[1] -> setDirection ( 30 ) ; + clouds[2] = sky -> addCloud ( + "data/scattered.rgba", // texture + 80000, // span + 1000, // elevation, + 100, // thickness + 100 ); // transition + clouds[2] -> setSpeed ( 5 ) ; + clouds[2] -> setDirection ( 20 ) ; + + teapot = new ssgTransform ; + teapot -> addKid ( tpt_obj ) ; + + wave = new ssgTransform ; + wave -> addKid ( wave_obj ) ; + + scene = new ssgRoot ; + scene -> addKid ( teapot ) ; + scene -> addKid ( wave ) ; +} + + +static void init_gui () +{ + static puFont *sorority ; + static fntTexFont *fnt ; + + fnt = new fntTexFont () ; + fnt -> load ( "data/sorority.txf" ) ; + sorority = new puFont ( fnt, 12 ) ; + + puSetDefaultFonts ( *sorority, *sorority ) ; + puSetDefaultStyle ( PUSTYLE_SMALL_SHADED ) ; + puSetDefaultColourScheme ( 0.2f, 0.5f, 0.2f, 0.5f ) ; + + puGroup *window_group = new puGroup ( 0, 0 ) ; + + bodyRADial = new puDial ( 150, GUI_BASE+90, 50 ) ; + bodyRADial->setWrap ( 1 ) ; + bodyRADial->setMaxValue ( 360 ) ; + bodyRADial->setMinValue ( 0 ) ; + bodyRADial->setStepSize ( 0.1f ) ; + bodyRADial->setCBMode ( PUSLIDER_ALWAYS ) ; + bodyRADial->setCallback ( bodyRADial_cb ) ; + bodyRADial->setLabel ( "Right Ascension" ) ; + bodyRADial->setLabelPlace ( PUPLACE_CENTERED_RIGHT ) ; + bodyRADial->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + bodyRADial->setLegendPlace ( PUPLACE_BOTTOM_CENTERED ) ; + + bodyDeclDial = new puDial ( 400, GUI_BASE+90, 50 ) ; + bodyDeclDial->setWrap ( 1 ) ; + bodyDeclDial->setMaxValue ( 360 ) ; + bodyDeclDial->setMinValue ( 0 ) ; + bodyDeclDial->setStepSize ( 0.1f ) ; + bodyDeclDial->setCBMode ( PUSLIDER_ALWAYS ) ; + bodyDeclDial->setCallback ( bodyDeclDial_cb ) ; + bodyDeclDial->setLabel ( "Declination" ) ; + bodyDeclDial->setLabelPlace ( PUPLACE_CENTERED_RIGHT ) ; + bodyDeclDial->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + bodyDeclDial->setLegendPlace ( PUPLACE_BOTTOM_CENTERED ) ; + + bodySelectBox = new puaSelectBox ( 150, GUI_BASE+150, 300, GUI_BASE+180, bodyNameList ) ; + bodySelectBox->setCallback ( bodySelectBox_cb ) ; + bodySelectBox->setCurrentItem ( 0 ) ; + bodySelectBox->setLabel ( "Edit Body" ) ; + bodySelectBox->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; + bodySelectBox->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + /* Set everything up on the first time around */ + bodySelectBox_cb ( bodySelectBox ) ; + + cloudElevationSlider = new puSlider ( 150, GUI_BASE+20, 90, false, 20 ) ; + cloudElevationSlider->setMaxValue ( 10000.0f ) ; + cloudElevationSlider->setMinValue ( 100.0f ) ; + cloudElevationSlider->setStepSize ( 10.0f ) ; + cloudElevationSlider->setCBMode ( PUSLIDER_ALWAYS ) ; + cloudElevationSlider->setCallback ( cloudElevationSlider_cb ) ; + cloudElevationSlider->setLabel ( "Cloud Elevation" ) ; + cloudElevationSlider->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; + cloudElevationSlider->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + cloudEnableButton = new puButton ( 150, GUI_BASE, " " ) ; + cloudEnableButton->setStyle ( PUSTYLE_RADIO ) ; + cloudEnableButton->setCallback ( cloudEnableButton_cb ) ; + cloudEnableButton->setLabel ( "Enable Cloud" ) ; + cloudEnableButton->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; + cloudEnableButton->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + cloudSelectBox = new puaSelectBox ( 150, GUI_BASE+50, 300, GUI_BASE+80, cloudNameList ) ; + cloudSelectBox->setCallback ( cloudSelectBox_cb ) ; + cloudSelectBox->setCurrentItem ( 0 ) ; + cloudSelectBox->setLabel ( "Edit Cloud" ) ; + cloudSelectBox->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; + cloudSelectBox->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + /* Set everything up on the first time around */ + cloudSelectBox_cb ( cloudSelectBox ) ; + + window_group->close () ; +} + + +/* + The works. +*/ + +int main ( int, char ** ) +{ + init_graphics () ; + load_database () ; + init_gui () ; + glutMainLoop () ; + return 0 ; +} diff --git a/examples/src/ssg/sky/sky.dsp b/examples/src/ssg/sky/sky.dsp new file mode 100644 index 0000000..0e3440d --- /dev/null +++ b/examples/src/ssg/sky/sky.dsp @@ -0,0 +1,87 @@ +# Microsoft Developer Studio Project File - Name="sky" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=sky - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "sky.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "sky.mak" CFG="sky - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "sky - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "sky - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "sky - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0xc09 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sg.lib ssg.lib pui.lib puAux.lib fnt.lib ul.lib ssgAux.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "sky - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0xc09 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sg_d.lib ssg_d.lib pui_d.lib puAux_d.lib fnt_d.lib ul_d.lib ssgAux_d.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "sky - Win32 Release" +# Name "sky - Win32 Debug" +# Begin Source File + +SOURCE=.\sky.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/ssg/state_test/Makefile.am b/examples/src/ssg/state_test/Makefile.am new file mode 100644 index 0000000..7ed262f --- /dev/null +++ b/examples/src/ssg/state_test/Makefile.am @@ -0,0 +1,12 @@ +if BUILD_SSG + +noinst_PROGRAMS = stest + +stest_SOURCES = stest.cxx + +stest_LDADD = -lplibssg -lplibsg -lplibul $(GLUT_LIBS) $(OGL_LIBS) + +endif + +EXTRA_DIST = herring.inta stest.dsp + diff --git a/examples/src/ssg/state_test/herring.inta b/examples/src/ssg/state_test/herring.inta new file mode 100644 index 0000000..0a54bee Binary files /dev/null and b/examples/src/ssg/state_test/herring.inta differ diff --git a/examples/src/ssg/state_test/stest.cxx b/examples/src/ssg/state_test/stest.cxx new file mode 100644 index 0000000..9ddaeeb --- /dev/null +++ b/examples/src/ssg/state_test/stest.cxx @@ -0,0 +1,323 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: stest.cxx 2099 2006-11-03 20:04:40Z fayjf $ +*/ + + +#include +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +static ssgRoot *scene = NULL ; +static ssgTransform *object = NULL ; +static ssgStateSelector *big_red_switch = NULL ; + +/* + Something to make some interesting motion + for both Object and the camera. +*/ + +static void update_motion () +{ + static int frameno = 0 ; + + frameno++ ; + + sgCoord campos ; + sgCoord objpos ; + + /* + Spin Object, make the camera pan sinusoidally left and right + */ + + sgSetCoord ( & campos, 0.0f, -5.0f, 1.0f, + /*25.0 * sin(frameno/100.0)*/0.0f, 0.0f, 0.0f ) ; + sgSetCoord ( & objpos, 0.0f, 0.0f, 0.0f, (float)frameno, 0.0f, 0.0f ) ; + + ssgSetCamera ( & campos ) ; + object -> setTransform ( & objpos ) ; + + if ( frameno % 600 == 0 ) + big_red_switch -> selectStep ( 0 ) ; + + if ( frameno % 600 == 300 ) + big_red_switch -> selectStep ( 1 ) ; +} + + + +/* + The GLUT window reshape event +*/ + +static void reshape ( int w, int h ) +{ + glViewport ( 0, 0, w, h ) ; +} + + + +/* + The GLUT keyboard event +*/ + +static void keyboard ( unsigned char, int, int ) +{ + exit ( 0 ) ; +} + + + +/* + The GLUT redraw event +*/ + +static void redraw () +{ + update_motion () ; + + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + ssgCullAndDraw ( scene ) ; + + glutPostRedisplay () ; + glutSwapBuffers () ; +} + + + +static void init_graphics () +{ + int fake_argc = 1 ; + char *fake_argv[3] ; + fake_argv[0] = "Viewer" ; + fake_argv[1] = "Simple Scene Graph : Viewer Program." ; + fake_argv[2] = NULL ; + + /* + Initialise GLUT + */ + + glutInitWindowPosition ( 0, 0 ) ; + glutInitWindowSize ( 640, 480 ) ; + glutInit ( &fake_argc, fake_argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + glutCreateWindow ( fake_argv[1] ) ; + glutDisplayFunc ( redraw ) ; + glutReshapeFunc ( reshape ) ; + glutKeyboardFunc ( keyboard ) ; + + /* + Initialise SSG + */ + + ssgInit () ; + + /* + Some basic OpenGL setup + */ + + glClearColor ( 0.2f, 0.7f, 1.0f, 1.0f ) ; + glEnable ( GL_DEPTH_TEST ) ; + + /* + Set up the viewing parameters + */ + + ssgSetFOV ( 60.0f, 0.0f ) ; + ssgSetNearFar ( 1.0f, 700.0f ) ; + + /* + Set up the Sun. + */ + + sgVec3 sunposn ; + sgSetVec3 ( sunposn, 0.2f, -0.5f, 0.5f ) ; + ssgGetLight ( 0 ) -> setPosition ( sunposn ) ; +} + + + +static ssgEntity *make_herring () +{ + big_red_switch = new ssgStateSelector ( 2 ) ; + + ssgSimpleState *st0 = new ssgSimpleState ; + ssgSimpleState *st1 = new ssgSimpleState ; + + /* Texture ... or not */ + + st0 -> setTexture ( "herring.inta" ) ; + st0 -> enable ( GL_TEXTURE_2D ) ; + + st1 -> disable ( GL_TEXTURE_2D ) ; + + /* Other Stuff */ + + st0 -> setShadeModel ( GL_SMOOTH ) ; + st1 -> setShadeModel ( GL_SMOOTH ) ; + + st0 -> enable ( GL_CULL_FACE ) ; + st1 -> enable ( GL_CULL_FACE ) ; + + st0 -> setTranslucent () ; + st1 -> setTranslucent () ; + + st0 -> enable ( GL_ALPHA_TEST ) ; + st1 -> enable ( GL_ALPHA_TEST ) ; + + st0 -> setAlphaClamp ( 0.9f ) ; + st1 -> setAlphaClamp ( 0.9f ) ; + + st0 -> enable ( GL_BLEND ) ; + st1 -> enable ( GL_BLEND ) ; + + /* Lighting (where the magic happens) */ + + /* A RED herring (because the polygon is red). */ + st0 -> enable ( GL_LIGHTING ) ; + st0 -> enable ( GL_COLOR_MATERIAL ) ; + st0 -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + st0 -> setMaterial ( GL_EMISSION, 0, 0, 0, 1 ) ; + st0 -> setMaterial ( GL_SPECULAR, 0, 0, 0, 1 ) ; + st0 -> setShininess ( 0 ) ; + + /* Hopefully, a GREEN rectangle. */ + st1 -> enable ( GL_LIGHTING ) ; + st1 -> disable ( GL_COLOR_MATERIAL ) ; + st1 -> setMaterial ( GL_AMBIENT , 0, 1, 0, 1 ) ; + st1 -> setMaterial ( GL_DIFFUSE , 0, 1, 0, 1 ) ; + st1 -> setMaterial ( GL_EMISSION, 0, 0, 0, 1 ) ; + st1 -> setMaterial ( GL_SPECULAR, 0, 0, 0, 1 ) ; + st1 -> setShininess ( 0 ) ; + + /* Set up the selector */ + + big_red_switch -> setStep ( 0, st0 ) ; + big_red_switch -> setStep ( 1, st1 ) ; + + big_red_switch -> selectStep ( 0 ) ; /* Textured! */ + + sgVec4 *scolors = new sgVec4 [ 1 ] ; + sgVec3 *scoords = new sgVec3 [ 6 ] ; + sgVec2 *tcoords = new sgVec2 [ 6 ] ; + sgVec3 *snorms = new sgVec3 [ 1 ] ; + + /* RED! */ + sgSetVec4 ( scolors [ 0 ], 1.0f, 0.0f, 0.0f, 1.0f ) ; + sgSetVec3 ( snorms[0], 0.0f, 1.0f, 0.0f ) ; + + sgSetVec3(scoords[0], -1.0, 0.0, 0.0 ) ; + sgSetVec3(scoords[1], 1.0, 0.0, 0.0 ) ; + sgSetVec3(scoords[2], -1.0, 0.0, 1.0 ) ; + sgSetVec3(scoords[3], 1.0, 0.0, 1.0 ) ; + sgSetVec3(scoords[4], -1.0, 0.0, 0.0 ) ; + sgSetVec3(scoords[5], 1.0, 0.0, 0.0 ) ; + + sgSetVec2(tcoords[0], 0.0, 0.0 ) ; + sgSetVec2(tcoords[1], 1.0, 0.0 ) ; + sgSetVec2(tcoords[2], 0.0, 1.0 ) ; + sgSetVec2(tcoords[3], 1.0, 1.0 ) ; + sgSetVec2(tcoords[4], 0.0, 0.0 ) ; + sgSetVec2(tcoords[5], 1.0, 0.0 ) ; + + ssgLeaf *gset = new ssgVTable ( GL_TRIANGLE_STRIP, + 6, scoords, + 1, snorms, + 6, tcoords, + 1, scolors ) ; + + gset -> setState ( big_red_switch ) ; + + return gset ; +} + + +/* + Load a simple database +*/ + +static void load_database () +{ + /* + Set up the path to the data files + */ + + ssgModelPath ( "." ) ; + ssgTexturePath ( "." ) ; + + /* + Create a root node - and a transform to position + the object beneath that (in the tree that is). + */ + + scene = new ssgRoot ; + object = new ssgTransform ; + + /* + Load the models - optimise them a bit + and then add them into the scene. + */ + + ssgEntity *obj_obj = make_herring () ; + + object -> addKid ( obj_obj ) ; + + //ssgFlatten ( obj_obj ) ; + //ssgStripify ( object ) ; + scene -> addKid ( object ) ; + scene -> print () ; +} + + + +/* + The works. +*/ + +int main ( int, char ** ) +{ + init_graphics () ; + load_database () ; + glutMainLoop () ; + return 0 ; +} + + + diff --git a/examples/src/ssg/state_test/stest.dsp b/examples/src/ssg/state_test/stest.dsp new file mode 100644 index 0000000..3ed5698 --- /dev/null +++ b/examples/src/ssg/state_test/stest.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="stest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=stest - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "stest.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "stest.mak" CFG="stest - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "stest - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "stest - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "stest - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg.lib sg.lib ul.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /machine:I386 /out:"stest.exe" /libpath:"..\..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "stest - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg_d.lib sg_d.lib ul_d.lib opengl32.lib glu32.lib glut32.lib Shlwapi.lib /nologo /subsystem:console /debug /machine:I386 /out:"stest.exe" /pdbtype:sept /libpath:"..\..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "stest - Win32 Release" +# Name "stest - Win32 Debug" +# Begin Source File + +SOURCE=.\stest.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/ssg/tux/Makefile.am b/examples/src/ssg/tux/Makefile.am new file mode 100644 index 0000000..329c474 --- /dev/null +++ b/examples/src/ssg/tux/Makefile.am @@ -0,0 +1,14 @@ +if BUILD_SSG + +noinst_PROGRAMS = tux_example WavingFlagDemo + +tux_example_SOURCES = tux_example.cxx +WavingFlagDemo_SOURCES = WavingFlag.cxx WavingFlagDemo.cxx WavingFlag.h + +tux_example_LDADD = -lplibssg -lplibsg -lplibul $(GLUT_LIBS) $(OGL_LIBS) +WavingFlagDemo_LDADD = -lplibssg -lplibsg -lplibul $(GLUT_LIBS) $(OGL_LIBS) + +endif + +EXTRA_DIST = tux_example.dsp WavingFlag.dsp + diff --git a/examples/src/ssg/tux/WavingFlag.cxx b/examples/src/ssg/tux/WavingFlag.cxx new file mode 100644 index 0000000..682c97d --- /dev/null +++ b/examples/src/ssg/tux/WavingFlag.cxx @@ -0,0 +1,203 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: WavingFlag.cxx 2099 2006-11-03 20:04:40Z fayjf $ +*/ + + +#ifdef WIN32 +# include +#else +# include +#endif + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#include +#include "WavingFlag.h" + +WavingFlag::WavingFlag( sgVec4 color, char *texture1, char *texture2, int s ) +{ + size = s; + int numVertices = size*size; + branch = new ssgBranch(); + branch->clrTraversalMaskBits ( SSGTRAV_HOT ) ; + + colors = new ssgColourArray( numVertices ); + normals = new ssgNormalArray( numVertices ); + texCoords = new ssgTexCoordArray( numVertices ); + vertices = new ssgVertexArray( numVertices ); + int i; + for ( i = 0; i < numVertices; i++ ) + { + sgVec3 n = { 0.0, 0.0, 0.0 }; + sgVec2 t = { 0.0, 0.0 }; + colors->add( color ); + normals->add( n ); + texCoords->add( t ); + vertices->add( n ); + } + ssgSimpleState *state1 = new ssgSimpleState ; + if ( texture1 ) + { + state1->setTexture( texture1 ) ; + state1->enable( GL_TEXTURE_2D ) ; + } + else + { + state1->disable( GL_TEXTURE_2D ) ; + } + state1->enable( GL_LIGHTING ) ; + state1->setShadeModel( GL_SMOOTH ) ; + state1->enable( GL_COLOR_MATERIAL ) ; + state1->setColourMaterial( GL_AMBIENT_AND_DIFFUSE ) ; + state1->setMaterial( GL_EMISSION, 0.91f, 0.41f, 0.81f, .94f ) ; + state1->setMaterial( GL_SPECULAR, 0.91f, 0.41f, 0.81f, .94f ) ; + state1->setShininess( 0.3f ) ; + state1->setTranslucent() ; + state1->enable( GL_BLEND ) ; + state1->enable ( GL_ALPHA_TEST ) ; + state1->setAlphaClamp ( 0.0f ) ; + + ssgSimpleState *state2 = new ssgSimpleState ; + if ( texture2 ) + { + state2->setTexture( texture2 ) ; + state2->enable( GL_TEXTURE_2D ) ; + } + else + { + if ( texture1 ) + { + state2->setTexture( texture1 ) ; + state2->enable( GL_TEXTURE_2D ) ; + } + else + { + state2->disable( GL_TEXTURE_2D ) ; + } + } + state2->enable( GL_LIGHTING ) ; + state2->setShadeModel( GL_SMOOTH ) ; + state2->enable( GL_COLOR_MATERIAL ) ; + state2->setColourMaterial( GL_AMBIENT_AND_DIFFUSE ) ; + state2->setMaterial( GL_EMISSION, 0.91f, 0.41f, 0.81f, .94f ) ; + state2->setMaterial( GL_SPECULAR, 0.91f, 0.41f, 0.81f, .94f ) ; + state2->setShininess( 0.3f ) ; + state2->setTranslucent() ; + state2->enable( GL_BLEND ) ; + state2->enable ( GL_ALPHA_TEST ) ; + state2->setAlphaClamp ( 0.0f ) ; + + branch = new ssgBranch; + int x,z; + for ( x = 0; x < size; x++ ) + { + ssgIndexArray *indices = new ssgIndexArray( size*2 ); // one side of the flag + ssgIndexArray *indices2 = new ssgIndexArray( size*2 ); // and the other side + for ( z = 0; z < size; z++ ) + { + int i = x*size + z; + + float *v = vertices->get( i ); + v[0] = (float)x/(size - 1.0f); + v[1] = 0.0; + v[2] = (float)z/(size - 1.0f); + + float *t = texCoords->get( i ); + sgSetVec2( t, v[0], v[2] ); + + indices->add( i ); + indices->add( i+size ); + indices2->add( i+size ); + indices2->add( i ); + } + if ( x < size-1 ) + { + ssgLeaf *l = new ssgVtxArray( GL_TRIANGLE_STRIP, + vertices, + normals, + texCoords, + colors, + indices ); + l->setState ( state1 ); + branch->addKid( l ); + ssgLeaf *l2 = new ssgVtxArray( GL_TRIANGLE_STRIP, + vertices, + normals, + texCoords, + colors, + indices2 ); + l2->setState ( state2 ); + branch->addKid( l2 ); + } + } +} + +WavingFlag::~WavingFlag() +{ +} + +void WavingFlag::animate( float time, float windVelocity ) +{ + if ( windVelocity < 3.0 ) windVelocity = 3.0; + if ( windVelocity > 25.0 ) windVelocity = 25.0; + float r = 0.6f/windVelocity; // half wave height + float w = windVelocity/2.0f; // angular acceleration + float k = windVelocity*3.0f; // wave number + float d = (1.0f-windVelocity/25.0f)*(SG_PI/2.0f); + + int x,z; + for ( z = size-1; z >= 0; z-- ) + { + for ( x = 1; x < size; x++ ) + { + int i = x*size + z; + + float *v = vertices->get( i ); + v[0] = ((float)x * (float)cos(d)) / (size - 1.0f); + float a = k*(v[0]) - w*time; // phase angle + v[1] = r * (float)cos( a ); + v[0] -= v[1]; + v[2] = ((float)z - (float)x * (float)sin(d)) / (size - 1.0f); + float *n = normals->get( i ); + n[0] = (float)cos(d); + n[1] = v[1]; + //d *= 1.002; + } + k *= 0.9f; + } + if ( d > SG_PI/2.0 ) printf ("Problems\n"); + branch -> dirtyBSphere () ; +} + +ssgEntity *WavingFlag::getObject() +{ + return branch; +} + diff --git a/examples/src/ssg/tux/WavingFlag.dsp b/examples/src/ssg/tux/WavingFlag.dsp new file mode 100644 index 0000000..3895f75 --- /dev/null +++ b/examples/src/ssg/tux/WavingFlag.dsp @@ -0,0 +1,96 @@ +# Microsoft Developer Studio Project File - Name="WavingFlag" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=WavingFlag - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "WavingFlag.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "WavingFlag.mak" CFG="WavingFlag - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "WavingFlag - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "WavingFlag - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "WavingFlag - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg.lib sg.lib ul.lib glut32.lib opengl32.lib glu32.lib /nologo /subsystem:console /machine:I386 /out:"WavingFlag.exe" /libpath:"..\..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "WavingFlag - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg_d.lib sg_d.lib ul_d.lib glut32.lib opengl32.lib glu32.lib /nologo /subsystem:console /debug /machine:I386 /out:"WavingFlag.exe" /pdbtype:sept /libpath:"..\..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "WavingFlag - Win32 Release" +# Name "WavingFlag - Win32 Debug" +# Begin Source File + +SOURCE=.\WavingFlag.cxx +# End Source File +# Begin Source File + +SOURCE=.\WavingFlag.h +# End Source File +# Begin Source File + +SOURCE=.\WavingFlagDemo.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/ssg/tux/WavingFlag.h b/examples/src/ssg/tux/WavingFlag.h new file mode 100644 index 0000000..97943c0 --- /dev/null +++ b/examples/src/ssg/tux/WavingFlag.h @@ -0,0 +1,44 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: WavingFlag.h 1551 2002-09-01 12:04:53Z ude $ +*/ + + +#ifndef _WAVINGFLAG_ +#define _WAVINGFLAG_ + +class WavingFlag +{ +public: + WavingFlag( sgVec4 color, char *texture1=NULL, char *texture2=NULL, int s=5 ); + ~WavingFlag(); + void animate( float time, float windVelocity ); + ssgEntity *getObject(); +private: + ssgBranch *branch; + ssgColourArray *colors; + ssgNormalArray *normals; + ssgTexCoordArray *texCoords; + ssgVertexArray *vertices; + int size; +}; + +#endif diff --git a/examples/src/ssg/tux/WavingFlagDemo.cxx b/examples/src/ssg/tux/WavingFlagDemo.cxx new file mode 100644 index 0000000..8cea52e --- /dev/null +++ b/examples/src/ssg/tux/WavingFlagDemo.cxx @@ -0,0 +1,194 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: WavingFlagDemo.cxx 1551 2002-09-01 12:04:53Z ude $ +*/ + + +#ifdef WIN32 +# include +#else +# include +#endif + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#include +#include "WavingFlag.h" + + +static WavingFlag* flag = NULL ; +static float flagTime = 0.0f ; +static ssgRoot* scene = NULL ; + +/* + The GLUT window reshape event +*/ + +static void reshape ( int w, int h ) +{ + glViewport ( 0, 0, w, h ) ; +} + + + +/* + The GLUT keyboard event +*/ + +static void keyboard ( unsigned char, int, int ) +{ + exit ( 0 ) ; +} + + + +static void idle () +{ + static int lastTime = 0; + int time = glutGet((GLenum)GLUT_ELAPSED_TIME); + if (time != lastTime) { + lastTime = time; + flagTime += 0.02f ; + } +} + + +/* + The GLUT redraw event +*/ + +static void redraw () +{ + sgCoord campos ; + sgSetCoord ( & campos, 0.0f, -3.0f, 0.0f, 0.0f, 0.0f, 0.0f ) ; + ssgSetCamera ( & campos ) ; + + flag -> animate( flagTime, 20 ); + + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + ssgCullAndDraw ( scene ) ; + + glutPostRedisplay () ; + glutSwapBuffers () ; +} + + + +static void init_graphics () +{ + int fake_argc = 1 ; + char *fake_argv[3] ; + fake_argv[0] = "ssgExample" ; + fake_argv[1] = "Waving Flag Example Program." ; + fake_argv[2] = NULL ; + + /* + Initialise GLUT + */ + + glutInitWindowPosition ( 0, 0 ) ; + glutInitWindowSize ( 640, 480 ) ; + glutInit ( &fake_argc, fake_argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + glutCreateWindow ( fake_argv[1] ) ; + glutDisplayFunc ( redraw ) ; + glutReshapeFunc ( reshape ) ; + glutKeyboardFunc ( keyboard ) ; + glutIdleFunc ( idle ) ; + + /* + Initialise SSG + */ + + ssgInit () ; + + /* + Some basic OpenGL setup + */ + + glClearColor ( 0.2f, 0.7f, 1.0f, 1.0f ) ; + glEnable ( GL_DEPTH_TEST ) ; + + /* + Set up the viewing parameters + */ + + ssgSetFOV ( 60.0f, 0.0f ) ; + ssgSetNearFar ( 1.0f, 700.0f ) ; + + /* + Set up the Sun. + */ + + sgVec3 sunposn ; + sgSetVec3 ( sunposn, 0.2f, -0.5f, 0.5f ) ; + ssgGetLight ( 0 ) -> setPosition ( sunposn ) ; +} + + +/* + Load a simple database +*/ + +static void load_database () +{ + /* + Set up the path to the data files + */ + + ssgModelPath ( "data" ) ; + ssgTexturePath ( "data" ) ; + + /* + Create a root node and the flag. + */ + + scene = new ssgRoot ; + + sgVec4 flagColor = { 1.0f, 0.0f, 0.0f, 1.0f }; + flag = new WavingFlag ( flagColor, "data/Penguin_body.rgb", "data/Penguin_body.rgb" ) ; + + scene -> addKid ( flag -> getObject() ) ; +} + + + +/* + The works. +*/ + +int main ( int, char ** ) +{ + init_graphics () ; + load_database () ; + glutMainLoop () ; + return 0 ; +} + diff --git a/examples/src/ssg/tux/data/Penguin_beak.rgb b/examples/src/ssg/tux/data/Penguin_beak.rgb new file mode 100644 index 0000000..b1e0e79 Binary files /dev/null and b/examples/src/ssg/tux/data/Penguin_beak.rgb differ diff --git a/examples/src/ssg/tux/data/Penguin_body.rgb b/examples/src/ssg/tux/data/Penguin_body.rgb new file mode 100644 index 0000000..1ba0f4b Binary files /dev/null and b/examples/src/ssg/tux/data/Penguin_body.rgb differ diff --git a/examples/src/ssg/tux/data/embossed_herring.bmp b/examples/src/ssg/tux/data/embossed_herring.bmp new file mode 100644 index 0000000..795e5d1 Binary files /dev/null and b/examples/src/ssg/tux/data/embossed_herring.bmp differ diff --git a/examples/src/ssg/tux/data/pedestal.ac b/examples/src/ssg/tux/data/pedestal.ac new file mode 100644 index 0000000..3c112e2 --- /dev/null +++ b/examples/src/ssg/tux/data/pedestal.ac @@ -0,0 +1,81 @@ +AC3Db +MATERIAL "" rgb 1 1 1 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "" rgb 1 1 1 amb 0.2 0.2 0.2 emis 1 1 1 spec 0.502 0.502 0.502 shi 0 trans 0 +OBJECT world +kids 2 +OBJECT poly +name "box" +texture "wood.rgb" +texrep 5 5 +numvert 8 +-1.29615 -0.6 -1.29615 +-1 0 -1 +1 0 -1 +1.3 -0.6 -1.29615 +-1.29615 -0.6 1.3 +-1 0 1 +1 0 1 +1.3 -0.6 1.3 +numsurf 6 +SURF 0x0 +mat 0 +refs 4 +0 0 0 +1 0.114074 0.114074 +2 0.884445 0.114074 +3 1 0 +SURF 0x0 +mat 0 +refs 4 +6 0.884445 0.884445 +7 1 1 +3 1 0 +2 0.884445 0.114074 +SURF 0x0 +mat 0 +refs 4 +7 1 1 +6 0.884445 0.884445 +5 0.114074 0.884445 +4 0 1 +SURF 0x0 +mat 0 +refs 4 +4 0 1 +5 0.114074 0.884445 +1 0.114074 0.114074 +0 0 0 +SURF 0x0 +mat 0 +refs 4 +1 0.114074 0.114074 +5 0.114074 0.884445 +6 0.884445 0.884445 +2 0.884445 0.114074 +SURF 0x0 +mat 0 +refs 4 +4 0 1 +0 0 0 +3 1 0 +7 1 1 +kids 0 +OBJECT poly +name "rect" +loc -0.0500002 0 -2.5 +texture "embossed_herring.bmp" +texrep 20 30 +numvert 4 +-17.95 -0.7 -18.6 +17.95 -0.7 -18.6 +17.95 -0.7 18.6 +-17.95 -0.7 18.6 +numsurf 1 +SURF 0x0 +mat 1 +refs 4 +3 0 0 +2 1 0 +1 1 1 +0 0 1 +kids 0 diff --git a/examples/src/ssg/tux/data/pedestal.safe b/examples/src/ssg/tux/data/pedestal.safe new file mode 100644 index 0000000..3d613b9 --- /dev/null +++ b/examples/src/ssg/tux/data/pedestal.safe @@ -0,0 +1,81 @@ +AC3Db +MATERIAL "" rgb 1 1 1 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "" rgb 1 1 1 amb 0.2 0.2 0.2 emis 1 1 1 spec 0.502 0.502 0.502 shi 0 trans 0 +OBJECT world +kids 2 +OBJECT poly +name "box" +texture "wood.rgb" +texrep 5 5 +numvert 8 +-1.29615 -0.6 -1.29615 +-1 0 -1 +1 0 -1 +1.3 -0.6 -1.29615 +-1.29615 -0.6 1.3 +-1 0 1 +1 0 1 +1.3 -0.6 1.3 +numsurf 6 +SURF 0x0 +mat 0 +refs 4 +0 0 0 +1 0.114074 0.114074 +2 0.884445 0.114074 +3 1 0 +SURF 0x0 +mat 0 +refs 4 +6 0.884445 0.884445 +7 1 1 +3 1 0 +2 0.884445 0.114074 +SURF 0x0 +mat 0 +refs 4 +7 1 1 +6 0.884445 0.884445 +5 0.114074 0.884445 +4 0 1 +SURF 0x0 +mat 0 +refs 4 +4 0 1 +5 0.114074 0.884445 +1 0.114074 0.114074 +0 0 0 +SURF 0x0 +mat 0 +refs 4 +1 0.114074 0.114074 +5 0.114074 0.884445 +6 0.884445 0.884445 +2 0.884445 0.114074 +SURF 0x0 +mat 0 +refs 4 +4 0 1 +0 0 0 +3 1 0 +7 1 1 +kids 0 +OBJECT poly +name "rect" +loc -0.0500002 0 -2.5 +texture "embossed_herring.rgb" +texrep 20 30 +numvert 4 +-17.95 -0.7 -18.6 +17.95 -0.7 -18.6 +17.95 -0.7 18.6 +-17.95 -0.7 18.6 +numsurf 1 +SURF 0x0 +mat 1 +refs 4 +3 0 0 +2 1 0 +1 1 1 +0 0 1 +kids 0 diff --git a/examples/src/ssg/tux/data/tuxedo.ac b/examples/src/ssg/tux/data/tuxedo.ac new file mode 100644 index 0000000..12e4754 --- /dev/null +++ b/examples/src/ssg/tux/data/tuxedo.ac @@ -0,0 +1,1695 @@ +AC3Db +MATERIAL "" rgb 0 0 0 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "" rgb 1 0.702 0 amb 1 0.702 0 emis 0 0 0 spec 0 0 0 shi 0 trans 0 +MATERIAL "" rgb 1 1 1 amb 1 1 1 emis 0 0 0 spec 0 0 0 shi 0 trans 0 +OBJECT world +kids 1 +OBJECT group +name "Tuxedo.T.Penguin" +kids 3 +OBJECT poly +name "tuxfeet" +loc 0.0203744 -0.479517 0.101666 +numvert 14 +-0.0744405 0.473224 0.119889 +0.100559 0.473224 -0.200111 +0.175559 0.473224 0.199889 +0.250559 0.473224 -0.200111 +0.425559 0.473224 0.119889 +0.250559 0.523224 -0.200111 +0.100559 0.523224 -0.200111 +-0.425559 0.476776 0.120111 +-0.25056 0.476776 -0.199889 +-0.17556 0.476776 0.200111 +-0.100559 0.476776 -0.199889 +0.0744405 0.476776 0.120111 +-0.100559 0.526776 -0.199889 +-0.25056 0.526776 -0.199889 +numsurf 12 +SURF 0x0 +mat 1 +refs 3 +0 0 0.1 +1 0.9 0 +2 0 0.8 +SURF 0x0 +mat 1 +refs 3 +3 1 0.1 +2 0 0.8 +1 0.9 0 +SURF 0x0 +mat 1 +refs 3 +2 0 0.8 +3 1 0.1 +4 0.5 1 +SURF 0x0 +mat 1 +refs 3 +4 0.5 1 +5 1 0.1 +2 0 0.8 +SURF 0x0 +mat 1 +refs 3 +6 0.9 0 +2 0 0.8 +5 1 0.1 +SURF 0x0 +mat 1 +refs 3 +2 0 0.8 +6 0.9 0 +0 0 0.1 +SURF 0x0 +mat 1 +refs 3 +7 0 0.1 +8 0.9 0 +9 0 0.8 +SURF 0x0 +mat 1 +refs 3 +10 1 0.1 +9 0 0.8 +8 0.9 0 +SURF 0x0 +mat 1 +refs 3 +9 0 0.8 +10 1 0.1 +11 0.5 1 +SURF 0x0 +mat 1 +refs 3 +11 0.5 1 +12 1 0.1 +9 0 0.8 +SURF 0x0 +mat 1 +refs 3 +13 0.9 0 +9 0 0.8 +12 1 0.1 +SURF 0x0 +mat 1 +refs 3 +9 0 0.8 +13 0.9 0 +7 0 0.1 +kids 0 +OBJECT poly +name "tuxbody" +loc 0.0124385 0.107258 -0.188333 +texture "Penguin_body.rgb" +numvert 115 +0.097524 1.07 -0.0756895 +-0.0202512 1.11 0 +0.119749 1.07 0 +0.0379068 1.07 -0.127348 +-0.0401753 1.07 -0.138575 +-0.111932 1.07 -0.105805 +-0.154581 1.07 -0.0394426 +-0.154581 1.07 0.0394426 +-0.111932 1.07 0.105805 +-0.0401753 1.07 0.138575 +0.0379068 1.07 0.127348 +0.097524 1.07 0.0756895 +0.184749 0.975 0 +0.152205 0.975 -0.110831 +0.064909 0.975 -0.186475 +-0.0494259 0.975 -0.202913 +-0.154498 0.975 -0.154929 +-0.216947 0.975 -0.057755 +-0.216947 0.975 0.057755 +-0.154498 0.975 0.154929 +-0.0494259 0.975 0.202913 +0.064909 0.975 0.186475 +0.152205 0.975 0.110831 +0.199749 0.68 0 +0.164825 0.68 -0.118941 +0.07114 0.68 -0.200119 +-0.0515605 0.68 -0.217761 +-0.16432 0.68 -0.166265 +-0.231339 0.68 -0.061981 +-0.231339 0.68 0.061981 +-0.16432 0.68 0.166265 +-0.0515605 0.68 0.217761 +0.07114 0.68 0.200119 +0.164825 0.68 0.118941 +0.284749 0.555 0 +0.236331 0.555 -0.164896 +0.10645 0.555 -0.277438 +-0.0636575 0.555 -0.301895 +-0.219984 0.555 -0.230503 +-0.312897 0.555 -0.0859285 +-0.312897 0.555 0.0859285 +-0.219984 0.555 0.230503 +-0.0636575 0.555 0.301895 +0.10645 0.555 0.277438 +0.236331 0.555 0.164896 +0.369749 0.43 0 +0.307837 0.43 -0.21085 +0.14176 0.43 -0.354757 +-0.075754 0.43 -0.38603 +-0.275647 0.43 -0.294742 +-0.394453 0.43 -0.109876 +-0.394453 0.43 0.109876 +-0.275647 0.43 0.294742 +-0.075754 0.43 0.38603 +0.14176 0.43 0.354757 +0.307837 0.43 0.21085 +0.414749 0.305 0 +0.345694 0.305 -0.235179 +0.160454 0.305 -0.39569 +-0.0821585 0.305 -0.430573 +-0.305115 0.305 -0.328751 +-0.437631 0.305 -0.122553 +-0.437631 0.305 0.122553 +-0.305115 0.305 0.328751 +-0.0821585 0.305 0.430573 +0.160454 0.305 0.39569 +0.345694 0.305 0.235179 +0.409749 0.185 0 +0.341488 0.185 -0.232476 +0.158377 0.185 -0.391142 +-0.081447 0.185 -0.425623 +-0.301841 0.185 -0.324973 +-0.432833 0.185 -0.121145 +-0.432833 0.185 0.121145 +-0.301841 0.185 0.324973 +-0.081447 0.185 0.425623 +0.158377 0.185 0.391142 +0.341488 0.185 0.232476 +0.354748 2.23517e-08 0 +0.295219 2.23517e-08 -0.202741 +0.135529 2.23517e-08 -0.341112 +-0.0736195 2.23517e-08 -0.371183 +-0.265824 2.23517e-08 -0.283406 +-0.380061 2.23517e-08 -0.10565 +-0.380061 2.23517e-08 0.10565 +-0.265824 2.23517e-08 0.283406 +-0.0736195 2.23517e-08 0.371183 +0.135529 2.23517e-08 0.341112 +0.295219 2.23517e-08 0.202741 +0.154748 -0.1 0 +0.126968 -0.1 -0.094612 +0.052446 -0.1 -0.159185 +-0.0451563 -0.1 -0.173219 +-0.134852 -0.1 -0.132256 +-0.188163 -0.1 -0.0493032 +-0.188163 -0.1 0.0493032 +-0.134852 -0.1 0.132256 +-0.0451564 -0.1 0.173219 +0.052446 -0.1 0.159185 +0.126968 -0.1 0.094612 +0.211872 0.567025 0.1 +0.211872 0.567025 -0.1 +0.316872 0.532025 0.1 +0.316872 0.532025 -0.1 +0.456872 0.392025 0.1 +0.456872 0.392025 -0.1 +0.56187 0.217025 0 +-0.211873 0.58637 0.1 +-0.211873 0.58637 -0.1 +-0.316873 0.55137 0.1 +-0.316873 0.55137 -0.1 +-0.456872 0.41137 0.1 +-0.456872 0.41137 -0.1 +-0.56187 0.23637 0 +-0.0202512 -0.11 0 +numsurf 218 +SURF 0x10 +mat 2 +refs 3 +0 -1 0.967213 +1 -1 1 +2 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +3 -1 0.967213 +1 -1 1 +0 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +4 -1 0.967213 +1 -1 1 +3 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +5 -1 0.967213 +1 -1 1 +4 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +6 -1 0.967213 +1 -1 1 +5 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +7 -0.614934 0.967213 +1 -0.5 1 +6 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +8 -0.578443 0.967213 +1 -0.5 1 +7 -0.614934 0.967213 +SURF 0x10 +mat 2 +refs 3 +9 -0.517047 0.967213 +1 -0.5 1 +8 -0.578443 0.967213 +SURF 0x10 +mat 2 +refs 3 +10 -0.450239 0.967213 +1 -0.5 1 +9 -0.517047 0.967213 +SURF 0x10 +mat 2 +refs 3 +11 -0.39923 0.967213 +1 -0.5 1 +10 -0.450239 0.967213 +SURF 0x10 +mat 2 +refs 3 +2 -0.380214 0.967213 +1 -0.5 1 +11 -0.39923 0.967213 +SURF 0x10 +mat 2 +refs 3 +2 -1 0.967213 +12 -1 0.889344 +0 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +13 -1 0.889344 +0 -1 0.967213 +12 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +0 -1 0.967213 +13 -1 0.889344 +3 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +14 -1 0.889344 +3 -1 0.967213 +13 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +3 -1 0.967213 +14 -1 0.889344 +4 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +15 -1 0.889344 +4 -1 0.967213 +14 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +4 -1 0.967213 +15 -1 0.889344 +5 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +16 -1 0.889344 +5 -1 0.967213 +15 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +5 -1 0.967213 +16 -1 0.889344 +6 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +17 -1 0.889344 +6 -1 0.967213 +16 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +6 -1 0.967213 +17 -1 0.889344 +7 -0.614934 0.967213 +SURF 0x10 +mat 2 +refs 3 +18 -0.668296 0.889344 +7 -0.614934 0.967213 +17 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +7 -0.614934 0.967213 +18 -0.668296 0.889344 +8 -0.578443 0.967213 +SURF 0x10 +mat 2 +refs 3 +19 -0.614863 0.889344 +8 -0.578443 0.967213 +18 -0.668296 0.889344 +SURF 0x10 +mat 2 +refs 3 +8 -0.578443 0.967213 +19 -0.614863 0.889344 +9 -0.517047 0.967213 +SURF 0x10 +mat 2 +refs 3 +20 -0.524962 0.889344 +9 -0.517047 0.967213 +19 -0.614863 0.889344 +SURF 0x10 +mat 2 +refs 3 +9 -0.517047 0.967213 +20 -0.524962 0.889344 +10 -0.450239 0.967213 +SURF 0x10 +mat 2 +refs 3 +21 -0.427136 0.889344 +10 -0.450239 0.967213 +20 -0.524962 0.889344 +SURF 0x10 +mat 2 +refs 3 +10 -0.450239 0.967213 +21 -0.427136 0.889344 +11 -0.39923 0.967213 +SURF 0x10 +mat 2 +refs 3 +22 -0.352443 0.889344 +11 -0.39923 0.967213 +21 -0.427136 0.889344 +SURF 0x10 +mat 2 +refs 3 +11 -0.39923 0.967213 +22 -0.352443 0.889344 +2 -0.380214 0.967213 +SURF 0x10 +mat 2 +refs 3 +12 -0.324599 0.889344 +2 -0.380214 0.967213 +22 -0.352443 0.889344 +SURF 0x10 +mat 2 +refs 3 +12 -1 0.889344 +23 -1 0.647541 +13 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +24 -1 0.647541 +13 -1 0.889344 +23 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +13 -1 0.889344 +24 -1 0.647541 +14 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +25 -1 0.647541 +14 -1 0.889344 +24 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +14 -1 0.889344 +25 -1 0.647541 +15 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +26 -1 0.647541 +15 -1 0.889344 +25 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +15 -1 0.889344 +26 -1 0.647541 +16 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +27 -1 0.647541 +16 -1 0.889344 +26 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +16 -1 0.889344 +27 -1 0.647541 +17 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +28 -1 0.647541 +17 -1 0.889344 +27 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +17 -1 0.889344 +28 -1 0.647541 +18 -0.668296 0.889344 +SURF 0x10 +mat 2 +refs 3 +29 -0.68061 0.647541 +18 -0.668296 0.889344 +28 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +18 -0.668296 0.889344 +29 -0.68061 0.647541 +19 -0.614863 0.889344 +SURF 0x10 +mat 2 +refs 3 +30 -0.623268 0.647541 +19 -0.614863 0.889344 +29 -0.68061 0.647541 +SURF 0x10 +mat 2 +refs 3 +19 -0.614863 0.889344 +30 -0.623268 0.647541 +20 -0.524962 0.889344 +SURF 0x10 +mat 2 +refs 3 +31 -0.526789 0.647541 +20 -0.524962 0.889344 +30 -0.623268 0.647541 +SURF 0x10 +mat 2 +refs 3 +20 -0.524962 0.889344 +31 -0.526789 0.647541 +21 -0.427136 0.889344 +SURF 0x10 +mat 2 +refs 3 +32 -0.421804 0.647541 +21 -0.427136 0.889344 +31 -0.526789 0.647541 +SURF 0x10 +mat 2 +refs 3 +21 -0.427136 0.889344 +32 -0.421804 0.647541 +22 -0.352443 0.889344 +SURF 0x10 +mat 2 +refs 3 +33 -0.341646 0.647541 +22 -0.352443 0.889344 +32 -0.421804 0.647541 +SURF 0x10 +mat 2 +refs 3 +22 -0.352443 0.889344 +33 -0.341646 0.647541 +12 -0.324599 0.889344 +SURF 0x10 +mat 2 +refs 3 +23 -0.311765 0.647541 +12 -0.324599 0.889344 +33 -0.341646 0.647541 +SURF 0x10 +mat 2 +refs 3 +23 -1 0.647541 +34 -1 0.545082 +24 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +35 -1 0.545082 +24 -1 0.647541 +34 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +24 -1 0.647541 +35 -1 0.545082 +25 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +36 -1 0.545082 +25 -1 0.647541 +35 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +25 -1 0.647541 +36 -1 0.545082 +26 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +37 -1 0.545082 +26 -1 0.647541 +36 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +26 -1 0.647541 +37 -1 0.545082 +27 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +38 -1 0.545082 +27 -1 0.647541 +37 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +27 -1 0.647541 +38 -1 0.545082 +28 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +39 -1 0.545082 +28 -1 0.647541 +38 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +28 -1 0.647541 +39 -1 0.545082 +29 -0.68061 0.647541 +SURF 0x10 +mat 2 +refs 3 +40 -0.750392 0.545082 +29 -0.68061 0.647541 +39 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +29 -0.68061 0.647541 +40 -0.750392 0.545082 +30 -0.623268 0.647541 +SURF 0x10 +mat 2 +refs 3 +41 -0.670894 0.545082 +30 -0.623268 0.647541 +40 -0.750392 0.545082 +SURF 0x10 +mat 2 +refs 3 +30 -0.623268 0.647541 +41 -0.670894 0.545082 +31 -0.526789 0.647541 +SURF 0x10 +mat 2 +refs 3 +42 -0.537139 0.545082 +31 -0.526789 0.647541 +41 -0.670894 0.545082 +SURF 0x10 +mat 2 +refs 3 +31 -0.526789 0.647541 +42 -0.537139 0.545082 +32 -0.421804 0.647541 +SURF 0x10 +mat 2 +refs 3 +43 -0.391592 0.545082 +32 -0.421804 0.647541 +42 -0.537139 0.545082 +SURF 0x10 +mat 2 +refs 3 +32 -0.421804 0.647541 +43 -0.391592 0.545082 +33 -0.341646 0.647541 +SURF 0x10 +mat 2 +refs 3 +44 -0.280464 0.545082 +33 -0.341646 0.647541 +43 -0.391592 0.545082 +SURF 0x10 +mat 2 +refs 3 +33 -0.341646 0.647541 +44 -0.280464 0.545082 +23 -0.311765 0.647541 +SURF 0x10 +mat 2 +refs 3 +34 -0.239037 0.545082 +23 -0.311765 0.647541 +44 -0.280464 0.545082 +SURF 0x10 +mat 2 +refs 3 +34 -1 0.545082 +45 -1 0.442623 +35 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +46 -1 0.442623 +35 -1 0.545082 +45 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +35 -1 0.545082 +46 -1 0.442623 +36 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +47 -1 0.442623 +36 -1 0.545082 +46 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +36 -1 0.545082 +47 -1 0.442623 +37 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +48 -1 0.442623 +37 -1 0.545082 +47 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +37 -1 0.545082 +48 -1 0.442623 +38 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +49 -1 0.442623 +38 -1 0.545082 +48 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +38 -1 0.545082 +49 -1 0.442623 +39 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +50 -1 0.442623 +39 -1 0.545082 +49 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +39 -1 0.545082 +50 -1 0.442623 +40 -0.750392 0.545082 +SURF 0x10 +mat 2 +refs 3 +51 -0.820173 0.442623 +40 -0.750392 0.545082 +50 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +40 -0.750392 0.545082 +51 -0.820173 0.442623 +41 -0.670894 0.545082 +SURF 0x10 +mat 2 +refs 3 +52 -0.71852 0.442623 +41 -0.670894 0.545082 +51 -0.820173 0.442623 +SURF 0x10 +mat 2 +refs 3 +41 -0.670894 0.545082 +52 -0.71852 0.442623 +42 -0.537139 0.545082 +SURF 0x10 +mat 2 +refs 3 +53 -0.547489 0.442623 +42 -0.537139 0.545082 +52 -0.71852 0.442623 +SURF 0x10 +mat 2 +refs 3 +42 -0.537139 0.545082 +53 -0.547489 0.442623 +43 -0.391592 0.545082 +SURF 0x10 +mat 2 +refs 3 +54 -0.36138 0.442623 +43 -0.391592 0.545082 +53 -0.547489 0.442623 +SURF 0x10 +mat 2 +refs 3 +43 -0.391592 0.545082 +54 -0.36138 0.442623 +44 -0.280464 0.545082 +SURF 0x10 +mat 2 +refs 3 +55 -0.219282 0.442623 +44 -0.280464 0.545082 +54 -0.36138 0.442623 +SURF 0x10 +mat 2 +refs 3 +44 -0.280464 0.545082 +55 -0.219282 0.442623 +34 -0.239037 0.545082 +SURF 0x10 +mat 2 +refs 3 +45 -0.16631 0.442623 +34 -0.239037 0.545082 +55 -0.219282 0.442623 +SURF 0x10 +mat 2 +refs 3 +45 -1 0.442623 +56 -1 0.340164 +46 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +57 -1 0.340164 +46 -1 0.442623 +56 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +46 -1 0.442623 +57 -1 0.340164 +47 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +58 -1 0.340164 +47 -1 0.442623 +57 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +47 -1 0.442623 +58 -1 0.340164 +48 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +59 -1 0.340164 +48 -1 0.442623 +58 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +48 -1 0.442623 +59 -1 0.340164 +49 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +60 -1 0.340164 +49 -1 0.442623 +59 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +49 -1 0.442623 +60 -1 0.340164 +50 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +61 -1 0.340164 +50 -1 0.442623 +60 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +50 -1 0.442623 +61 -1 0.340164 +51 -0.820173 0.442623 +SURF 0x10 +mat 2 +refs 3 +62 -0.857116 0.340164 +51 -0.820173 0.442623 +61 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +51 -0.820173 0.442623 +62 -0.857116 0.340164 +52 -0.71852 0.442623 +SURF 0x10 +mat 2 +refs 3 +63 -0.743734 0.340164 +52 -0.71852 0.442623 +62 -0.857116 0.340164 +SURF 0x10 +mat 2 +refs 3 +52 -0.71852 0.442623 +63 -0.743734 0.340164 +53 -0.547489 0.442623 +SURF 0x10 +mat 2 +refs 3 +64 -0.552969 0.340164 +53 -0.547489 0.442623 +63 -0.743734 0.340164 +SURF 0x10 +mat 2 +refs 3 +53 -0.547489 0.442623 +64 -0.552969 0.340164 +54 -0.36138 0.442623 +SURF 0x10 +mat 2 +refs 3 +65 -0.345386 0.340164 +54 -0.36138 0.442623 +64 -0.552969 0.340164 +SURF 0x10 +mat 2 +refs 3 +54 -0.36138 0.442623 +65 -0.345386 0.340164 +55 -0.219282 0.442623 +SURF 0x10 +mat 2 +refs 3 +66 -0.186892 0.340164 +55 -0.219282 0.442623 +65 -0.345386 0.340164 +SURF 0x10 +mat 2 +refs 3 +55 -0.219282 0.442623 +66 -0.186892 0.340164 +45 -0.16631 0.442623 +SURF 0x10 +mat 2 +refs 3 +56 -0.127807 0.340164 +45 -0.16631 0.442623 +66 -0.186892 0.340164 +SURF 0x10 +mat 2 +refs 3 +56 -1 0.340164 +67 -1 0.241803 +57 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +68 -1 0.241803 +57 -1 0.340164 +67 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +57 -1 0.340164 +68 -1 0.241803 +58 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +69 -1 0.241803 +58 -1 0.340164 +68 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +58 -1 0.340164 +69 -1 0.241803 +59 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +70 -1 0.241803 +59 -1 0.340164 +69 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +59 -1 0.340164 +70 -1 0.241803 +60 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +71 -1 0.241803 +60 -1 0.340164 +70 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +60 -1 0.340164 +71 -1 0.241803 +61 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +72 -1 0.241803 +61 -1 0.340164 +71 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +61 -1 0.340164 +72 -1 0.241803 +62 -0.857116 0.340164 +SURF 0x10 +mat 2 +refs 3 +73 -0.853011 0.241803 +62 -0.857116 0.340164 +72 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +62 -0.857116 0.340164 +73 -0.853011 0.241803 +63 -0.743734 0.340164 +SURF 0x10 +mat 2 +refs 3 +74 -0.740933 0.241803 +63 -0.743734 0.340164 +73 -0.853011 0.241803 +SURF 0x10 +mat 2 +refs 3 +63 -0.743734 0.340164 +74 -0.740933 0.241803 +64 -0.552969 0.340164 +SURF 0x10 +mat 2 +refs 3 +75 -0.55236 0.241803 +64 -0.552969 0.340164 +74 -0.740933 0.241803 +SURF 0x10 +mat 2 +refs 3 +64 -0.552969 0.340164 +75 -0.55236 0.241803 +65 -0.345386 0.340164 +SURF 0x10 +mat 2 +refs 3 +76 -0.347163 0.241803 +65 -0.345386 0.340164 +75 -0.55236 0.241803 +SURF 0x10 +mat 2 +refs 3 +65 -0.345386 0.340164 +76 -0.347163 0.241803 +66 -0.186892 0.340164 +SURF 0x10 +mat 2 +refs 3 +77 -0.190491 0.241803 +66 -0.186892 0.340164 +76 -0.347163 0.241803 +SURF 0x10 +mat 2 +refs 3 +66 -0.186892 0.340164 +77 -0.190491 0.241803 +56 -0.127807 0.340164 +SURF 0x10 +mat 2 +refs 3 +67 -0.132086 0.241803 +56 -0.127807 0.340164 +77 -0.190491 0.241803 +SURF 0x10 +mat 2 +refs 3 +67 -1 0.241803 +78 -1 0.0901639 +68 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +79 -1 0.0901639 +68 -1 0.241803 +78 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +68 -1 0.241803 +79 -1 0.0901639 +69 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +80 -1 0.0901639 +69 -1 0.241803 +79 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +69 -1 0.241803 +80 -1 0.0901639 +70 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +81 -1 0.0901639 +70 -1 0.241803 +80 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +70 -1 0.241803 +81 -1 0.0901639 +71 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +82 -1 0.0901639 +71 -1 0.241803 +81 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +71 -1 0.241803 +82 -1 0.0901639 +72 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +83 -1 0.0901639 +72 -1 0.241803 +82 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +72 -1 0.241803 +83 -1 0.0901639 +73 -0.853011 0.241803 +SURF 0x10 +mat 2 +refs 3 +84 -0.807859 0.0901639 +73 -0.853011 0.241803 +83 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +73 -0.853011 0.241803 +84 -0.807859 0.0901639 +74 -0.740933 0.241803 +SURF 0x10 +mat 2 +refs 3 +85 -0.710116 0.0901639 +74 -0.740933 0.241803 +84 -0.807859 0.0901639 +SURF 0x10 +mat 2 +refs 3 +74 -0.740933 0.241803 +85 -0.710116 0.0901639 +75 -0.55236 0.241803 +SURF 0x10 +mat 2 +refs 3 +86 -0.545663 0.0901639 +75 -0.55236 0.241803 +85 -0.710116 0.0901639 +SURF 0x10 +mat 2 +refs 3 +75 -0.55236 0.241803 +86 -0.545663 0.0901639 +76 -0.347163 0.241803 +SURF 0x10 +mat 2 +refs 3 +87 -0.366712 0.0901639 +76 -0.347163 0.241803 +86 -0.545663 0.0901639 +SURF 0x10 +mat 2 +refs 3 +76 -0.347163 0.241803 +87 -0.366712 0.0901639 +77 -0.190491 0.241803 +SURF 0x10 +mat 2 +refs 3 +88 -0.230079 0.0901639 +77 -0.190491 0.241803 +87 -0.366712 0.0901639 +SURF 0x10 +mat 2 +refs 3 +77 -0.190491 0.241803 +88 -0.230079 0.0901639 +67 -0.132086 0.241803 +SURF 0x10 +mat 2 +refs 3 +78 -0.179144 0.0901639 +67 -0.132086 0.241803 +88 -0.230079 0.0901639 +SURF 0x10 +mat 2 +refs 3 +78 -1 0.0901639 +89 -1 0.00819672 +79 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +90 -1 0.00819672 +79 -1 0.0901639 +89 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +79 -1 0.0901639 +90 -1 0.00819672 +80 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +91 -1 0.00819672 +80 -1 0.0901639 +90 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +80 -1 0.0901639 +91 -1 0.00819672 +81 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +92 -1 0.00819672 +81 -1 0.0901639 +91 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +81 -1 0.0901639 +92 -1 0.00819672 +82 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +93 -1 0.00819672 +82 -1 0.0901639 +92 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +82 -1 0.0901639 +93 -1 0.00819672 +83 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +94 -1 0.00819672 +83 -1 0.0901639 +93 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +83 -1 0.0901639 +94 -1 0.00819672 +84 -0.807859 0.0901639 +SURF 0x10 +mat 2 +refs 3 +95 -0.643667 0.00819672 +84 -0.807859 0.0901639 +94 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +84 -0.807859 0.0901639 +95 -0.643667 0.00819672 +85 -0.710116 0.0901639 +SURF 0x10 +mat 2 +refs 3 +96 -0.598054 0.00819672 +85 -0.710116 0.0901639 +95 -0.643667 0.00819672 +SURF 0x10 +mat 2 +refs 3 +85 -0.710116 0.0901639 +96 -0.598054 0.00819672 +86 -0.545663 0.0901639 +SURF 0x10 +mat 2 +refs 3 +97 -0.521309 0.00819672 +86 -0.545663 0.0901639 +96 -0.598054 0.00819672 +SURF 0x10 +mat 2 +refs 3 +86 -0.545663 0.0901639 +97 -0.521309 0.00819672 +87 -0.366712 0.0901639 +SURF 0x10 +mat 2 +refs 3 +98 -0.437799 0.00819672 +87 -0.366712 0.0901639 +97 -0.521309 0.00819672 +SURF 0x10 +mat 2 +refs 3 +87 -0.366712 0.0901639 +98 -0.437799 0.00819672 +88 -0.230079 0.0901639 +SURF 0x10 +mat 2 +refs 3 +99 -0.374037 0.00819672 +88 -0.230079 0.0901639 +98 -0.437799 0.00819672 +SURF 0x10 +mat 2 +refs 3 +88 -0.230079 0.0901639 +99 -0.374037 0.00819672 +78 -0.179144 0.0901639 +SURF 0x10 +mat 2 +refs 3 +89 -0.350267 0.00819672 +78 -0.179144 0.0901639 +99 -0.374037 0.00819672 +SURF 0x10 +mat 0 +refs 3 +100 0 0 +101 0 0 +102 0 0 +SURF 0x10 +mat 0 +refs 3 +103 0 0 +102 0 0 +101 0 0 +SURF 0x10 +mat 0 +refs 3 +102 0 0 +103 0 0 +104 0 0 +SURF 0x10 +mat 0 +refs 3 +105 0 0 +104 0 0 +103 0 0 +SURF 0x10 +mat 0 +refs 3 +104 0 0 +105 0 0 +106 0 0 +SURF 0x10 +mat 0 +refs 2 +105 0 0 +106 0 0 +SURF 0x10 +mat 0 +refs 2 +105 0 0 +106 0 0 +SURF 0x10 +mat 0 +refs 3 +106 0 0 +105 0 0 +104 0 0 +SURF 0x10 +mat 0 +refs 3 +103 0 0 +104 0 0 +105 0 0 +SURF 0x10 +mat 0 +refs 3 +104 0 0 +103 0 0 +102 0 0 +SURF 0x10 +mat 0 +refs 3 +107 0 0 +108 0 0 +109 0 0 +SURF 0x10 +mat 0 +refs 3 +110 0 0 +109 0 0 +108 0 0 +SURF 0x10 +mat 0 +refs 3 +109 0 0 +110 0 0 +111 0 0 +SURF 0x10 +mat 0 +refs 3 +112 0 0 +111 0 0 +110 0 0 +SURF 0x10 +mat 0 +refs 3 +111 0 0 +112 0 0 +113 0 0 +SURF 0x10 +mat 0 +refs 2 +112 0 0 +113 0 0 +SURF 0x10 +mat 0 +refs 2 +112 0 0 +113 0 0 +SURF 0x10 +mat 0 +refs 3 +113 0 0 +112 0 0 +111 0 0 +SURF 0x10 +mat 0 +refs 3 +110 0 0 +111 0 0 +112 0 0 +SURF 0x10 +mat 0 +refs 3 +111 0 0 +110 0 0 +109 0 0 +SURF 0x10 +mat 2 +refs 3 +89 -1 0.00819672 +114 -1 0 +90 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +90 -1 0.00819672 +114 -1 0 +91 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +91 -1 0.00819672 +114 -1 0 +92 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +92 -1 0.00819672 +114 -1 0 +93 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +93 -1 0.00819672 +114 -1 0 +94 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +94 -1 0.00819672 +114 -1 0 +95 -0.643667 0.00819672 +SURF 0x10 +mat 2 +refs 3 +95 -0.643667 0.00819672 +114 -0.5 0 +96 -0.598054 0.00819672 +SURF 0x10 +mat 2 +refs 3 +96 -0.598054 0.00819672 +114 -0.5 0 +97 -0.521309 0.00819672 +SURF 0x10 +mat 2 +refs 3 +97 -0.521309 0.00819672 +114 -0.5 0 +98 -0.437799 0.00819672 +SURF 0x10 +mat 2 +refs 3 +98 -0.437799 0.00819672 +114 -0.5 0 +99 -0.374037 0.00819672 +SURF 0x10 +mat 2 +refs 3 +99 -0.374037 0.00819672 +114 -0.5 0 +89 -0.350267 0.00819672 +kids 0 +OBJECT poly +name "tuxbeak" +loc -0.0328128 0.372259 0.086667 +texture "Penguin_beak.rgb" +numvert 17 +0.0565685 0.514 0.1 +1.11759e-08 0.5 0.125 +0.08 0.5 0.1 +1.11759e-08 0.528 0.1 +-0.0565685 0.514 0.1 +-0.08 0.5 0.1 +-0.0565685 0.486 0.1 +1.11759e-08 0.472 0.1 +0.0565685 0.486 0.1 +0.16 0.5 -0.125 +0.113137 0.556 -0.125 +1.11759e-08 0.612 -0.125 +-0.113137 0.556 -0.125 +-0.16 0.5 -0.125 +-0.113137 0.444 -0.125 +1.11759e-08 0.388 -0.125 +0.113137 0.444 -0.125 +numsurf 24 +SURF 0x10 +mat 2 +refs 3 +0 -0.342865 -0.342865 +1 -0.5 -0.5 +2 -0.277778 -0.5 +SURF 0x10 +mat 2 +refs 3 +3 -0.5 -0.277778 +1 -0.5 -0.5 +0 -0.342865 -0.342865 +SURF 0x10 +mat 2 +refs 3 +4 -0.657135 -0.342865 +1 -0.5 -0.5 +3 -0.5 -0.277778 +SURF 0x10 +mat 2 +refs 3 +5 -0.722222 -0.5 +1 -0.5 -0.5 +4 -0.657135 -0.342865 +SURF 0x10 +mat 2 +refs 3 +6 -0.657135 -0.657135 +1 -0.5 -0.5 +5 -0.722222 -0.5 +SURF 0x10 +mat 2 +refs 3 +7 -0.5 -0.722222 +1 -0.5 -0.5 +6 -0.657135 -0.657135 +SURF 0x10 +mat 2 +refs 3 +8 -0.342865 -0.657135 +1 -0.5 -0.5 +7 -0.5 -0.722222 +SURF 0x10 +mat 2 +refs 3 +2 -0.277778 -0.5 +1 -0.5 -0.5 +8 -0.342865 -0.657135 +SURF 0x10 +mat 2 +refs 3 +2 -0.277778 -0.5 +9 -0.0555556 -0.5 +0 -0.342865 -0.342865 +SURF 0x10 +mat 2 +refs 3 +10 -0.18573 -0.18573 +0 -0.342865 -0.342865 +9 -0.0555556 -0.5 +SURF 0x10 +mat 2 +refs 3 +0 -0.342865 -0.342865 +10 -0.18573 -0.18573 +3 -0.5 -0.277778 +SURF 0x10 +mat 2 +refs 3 +11 -0.5 -0.0555556 +3 -0.5 -0.277778 +10 -0.18573 -0.18573 +SURF 0x10 +mat 2 +refs 3 +3 -0.5 -0.277778 +11 -0.5 -0.0555556 +4 -0.657135 -0.342865 +SURF 0x10 +mat 2 +refs 3 +12 -0.81427 -0.18573 +4 -0.657135 -0.342865 +11 -0.5 -0.0555556 +SURF 0x10 +mat 2 +refs 3 +4 -0.657135 -0.342865 +12 -0.81427 -0.18573 +5 -0.722222 -0.5 +SURF 0x10 +mat 2 +refs 3 +13 -0.944444 -0.5 +5 -0.722222 -0.5 +12 -0.81427 -0.18573 +SURF 0x10 +mat 2 +refs 3 +5 -0.722222 -0.5 +13 -0.944444 -0.5 +6 -0.657135 -0.657135 +SURF 0x10 +mat 2 +refs 3 +14 -0.81427 -0.81427 +6 -0.657135 -0.657135 +13 -0.944444 -0.5 +SURF 0x10 +mat 2 +refs 3 +6 -0.657135 -0.657135 +14 -0.81427 -0.81427 +7 -0.5 -0.722222 +SURF 0x10 +mat 2 +refs 3 +15 -0.5 -0.944444 +7 -0.5 -0.722222 +14 -0.81427 -0.81427 +SURF 0x10 +mat 2 +refs 3 +7 -0.5 -0.722222 +15 -0.5 -0.944444 +8 -0.342865 -0.657135 +SURF 0x10 +mat 2 +refs 3 +16 -0.18573 -0.81427 +8 -0.342865 -0.657135 +15 -0.5 -0.944444 +SURF 0x10 +mat 2 +refs 3 +8 -0.342865 -0.657135 +16 -0.18573 -0.81427 +2 -0.277778 -0.5 +SURF 0x10 +mat 2 +refs 3 +9 -0.0555556 -0.5 +2 -0.277778 -0.5 +16 -0.18573 -0.81427 +kids 0 diff --git a/examples/src/ssg/tux/data/wood.rgb b/examples/src/ssg/tux/data/wood.rgb new file mode 100644 index 0000000..3094af0 Binary files /dev/null and b/examples/src/ssg/tux/data/wood.rgb differ diff --git a/examples/src/ssg/tux/tux_example.cxx b/examples/src/ssg/tux/tux_example.cxx new file mode 100644 index 0000000..d767ad7 --- /dev/null +++ b/examples/src/ssg/tux/tux_example.cxx @@ -0,0 +1,228 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: tux_example.cxx 2099 2006-11-03 20:04:40Z fayjf $ +*/ + + +#include +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +static ssgRoot *scene = NULL ; +static ssgTransform *penguin = NULL ; +static ssgTransform *pedestal = NULL ; + + +/* + Something to make some interesting motion + for both Tux and the camera. +*/ + +static void update_motion () +{ + static int frameno = 0 ; + + frameno++ ; + + sgCoord campos ; + sgCoord tuxpos ; + + /* + Spin Tux, make the camera pan sinusoidally left and right + */ + + sgSetCoord ( & campos, 0.0f, -5.0f, 1.0f, 25.0f * (float)sin(frameno/100.0), 0.0f, 0.0f ) ; + sgSetCoord ( & tuxpos, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, frameno/100.0f ) ; + + ssgSetCamera ( & campos ) ; + penguin -> setTransform ( & tuxpos ) ; +} + + + +/* + The GLUT window reshape event +*/ + +static void reshape ( int w, int h ) +{ + glViewport ( 0, 0, w, h ) ; +} + + + +/* + The GLUT keyboard event +*/ + +static void keyboard ( unsigned char, int, int ) +{ + exit ( 0 ) ; +} + + + +/* + The GLUT redraw event +*/ + +static void redraw () +{ + update_motion () ; + + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + ssgCullAndDraw ( scene ) ; + + glutPostRedisplay () ; + glutSwapBuffers () ; +} + + + +static void init_graphics () +{ + int fake_argc = 1 ; + char *fake_argv[3] ; + fake_argv[0] = "ssgExample" ; + fake_argv[1] = "Simple Scene Graph : Example Program." ; + fake_argv[2] = NULL ; + + /* + Initialise GLUT + */ + + glutInitWindowPosition ( 0, 0 ) ; + glutInitWindowSize ( 640, 480 ) ; + glutInit ( &fake_argc, fake_argv ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + glutCreateWindow ( fake_argv[1] ) ; + glutDisplayFunc ( redraw ) ; + glutReshapeFunc ( reshape ) ; + glutKeyboardFunc ( keyboard ) ; + + /* + Initialise SSG + */ + + ssgInit () ; + + /* + Some basic OpenGL setup + */ + + glClearColor ( 0.2f, 0.7f, 1.0f, 1.0f ) ; + glEnable ( GL_DEPTH_TEST ) ; + + /* + Set up the viewing parameters + */ + + ssgSetFOV ( 60.0f, 0.0f ) ; + ssgSetNearFar ( 1.0f, 700.0f ) ; + + /* + Set up the Sun. + */ + + sgVec3 sunposn ; + sgSetVec3 ( sunposn, 0.2f, -0.5f, 0.5f ) ; + ssgGetLight ( 0 ) -> setPosition ( sunposn ) ; +} + + +/* + Load a simple database +*/ + +static void load_database () +{ + /* + Set up the path to the data files + */ + + ssgModelPath ( "data" ) ; + ssgTexturePath ( "data" ) ; + + /* + Create a root node - and a transform to position + the pedestal - and another to position the penguin + beneath that (in the tree that is). + */ + + scene = new ssgRoot ; + pedestal = new ssgTransform ; + penguin = new ssgTransform ; + + /* + Load the models - optimise them a bit + and then add them into the scene. + */ + + ssgEntity *ped_obj = ssgLoadAC ( "pedestal.ac" ) ; + ssgEntity *tux_obj = ssgLoadAC ( "tuxedo.ac" ) ; + + penguin -> addKid ( tux_obj ) ; + pedestal -> addKid ( ped_obj ) ; + + ssgFlatten ( tux_obj ) ; + ssgFlatten ( ped_obj ) ; + ssgStripify ( penguin ) ; + ssgStripify ( pedestal ) ; + + pedestal -> addKid ( penguin ) ; + scene -> addKid ( pedestal ) ; +} + + + +/* + The works. +*/ + +int main ( int, char ** ) +{ + init_graphics () ; + load_database () ; + glutMainLoop () ; + return 0 ; +} + + + diff --git a/examples/src/ssg/tux/tux_example.dsp b/examples/src/ssg/tux/tux_example.dsp new file mode 100644 index 0000000..4615389 --- /dev/null +++ b/examples/src/ssg/tux/tux_example.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="tux_example" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=tux_example - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "tux_example.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "tux_example.mak" CFG="tux_example - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "tux_example - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "tux_example - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "tux_example - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg.lib sg.lib ul.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /machine:I386 /out:"tux_example.exe" /libpath:"..\..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "tux_example - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg_d.lib sg_d.lib ul_d.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /debug /machine:I386 /out:"tux_example.exe" /pdbtype:sept /libpath:"..\..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "tux_example - Win32 Release" +# Name "tux_example - Win32 Debug" +# Begin Source File + +SOURCE=.\tux_example.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/ssg/tween_test/Makefile.am b/examples/src/ssg/tween_test/Makefile.am new file mode 100644 index 0000000..dcfaafd --- /dev/null +++ b/examples/src/ssg/tween_test/Makefile.am @@ -0,0 +1,12 @@ +if BUILD_SSG + +noinst_PROGRAMS = tween_test + +tween_test_SOURCES = tween_test.cxx + +tween_test_LDADD = -lplibssgaux -lplibssg -lplibsg -lplibpw -lplibul $(OGL_LIBS) + +endif + +EXTRA_DIST = tween_test.dsp + diff --git a/examples/src/ssg/tween_test/tween_test.cxx b/examples/src/ssg/tween_test/tween_test.cxx new file mode 100644 index 0000000..b9f23cc --- /dev/null +++ b/examples/src/ssg/tween_test/tween_test.cxx @@ -0,0 +1,255 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: tween_test.cxx 2099 2006-11-03 20:04:40Z fayjf $ +*/ + + +#include +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include +#include +#include +#include +#include +#include + +static ssgRoot *scene = NULL ; +static ssgTweenController *tween_ctrl = NULL ; + + +/* + Something to make some interesting motion +*/ + +static void update_motion () +{ + static int frameno = 0 ; + + frameno++ ; + + sgCoord campos ; + + /* + Make the camera pan sinusoidally left and right + morphing the sphere/spike as we go. + */ + + tween_ctrl -> selectBank ( (float)fabs(sin(frameno/100.0)) ) ; + + sgSetCoord ( & campos, 0.0f, -5.0f, 0.0f, 25.0f * (float)sin(frameno/100.0), 0.0f, 0.0f ) ; + ssgSetCamera ( & campos ) ; +} + + +/* + The GLUT redraw event +*/ + +static void redraw () +{ + glClearColor ( 0.5f, 0.1f, 0.1f, 1.0 ) ; + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + update_motion () ; + + ssgCullAndDraw ( scene ) ; +} + + +static void init_graphics () +{ + pwInit ( 100, 100, 640, 480, false, "PLIB Window Demo", true, 0 ) ; + pwSetCallbacks ( NULL, NULL, NULL, NULL, NULL ) ; + + /* + Initialise SSG + */ + + ssgInit () ; + + /* + Some basic OpenGL setup + */ + + glClearColor ( 0.2f, 0.7f, 1.0f, 1.0f ) ; + glEnable ( GL_DEPTH_TEST ) ; + + /* + Set up the viewing parameters + */ + + ssgSetFOV ( 60.0f, 0.0f ) ; + ssgSetNearFar ( 1.0f, 700.0f ) ; + + /* + Set up the Sun. + */ + + sgVec4 black = { 0,0,0,1 } ; + sgVec3 sunposn ; + sgSetVec3 ( sunposn, 0.2f, -0.0f, 0.5f ) ; + ssgGetLight ( 0 ) -> setPosition ( sunposn ) ; + ssgGetLight ( 0 ) -> setColour ( GL_SPECULAR, black ) ; +} + + +/* + Load a simple database +*/ + +static void load_database () +{ + /* + Create a root node with a Tween controller beneath it. + */ + + scene = new ssgRoot ; + tween_ctrl = new ssgTweenController ; + scene -> addKid ( tween_ctrl ) ; + + /* + Construct a sphere (which we'll use as a template + and then discard + */ + + ssgaSphere *sp = new ssgaSphere ( 100 ) ; + + /* + For each ssgVtxTable within the sphere, generate + an ssgTween node + */ + + for ( int i = 0 ; i < sp -> getNumKids () ; i++ ) + { + ssgVtxTable *vt = (ssgVtxTable *)( sp -> getKid ( i ) ) ; + + assert ( vt -> isAKindOf ( ssgTypeVtxTable () ) ) ; + + /* + Make two new sets of vertex array. + */ + + ssgVertexArray *v0 = new ssgVertexArray ; + ssgNormalArray *n0 = new ssgNormalArray ; + ssgTexCoordArray *t0 = new ssgTexCoordArray ; + ssgColourArray *c0 = new ssgColourArray ; + + ssgVertexArray *v1 = new ssgVertexArray ; + ssgNormalArray *n1 = new ssgNormalArray ; + ssgTexCoordArray *t1 = new ssgTexCoordArray ; + ssgColourArray *c1 = new ssgColourArray ; + + /* + For every vertex in the sphere's VtxTable... + */ + + for ( int i = 0 ; i < vt -> getNumVertices () ; i++ ) + { + /* + Copy the sphere's vertex (unmolested) into + the vertex arrays that are destined to become + bank zero. + */ + + v0 -> add ( vt -> getVertex (i) ) ; + n0 -> add ( vt -> getNormal (i) ) ; + t0 -> add ( vt -> getTexCoord (i) ) ; + c0 -> add ( vt -> getColour (i) ) ; + + /* + For bank one, make some vertices half + the usual size - and others twice the + usual size. This is a spikey ball. + */ + + sgVec3 vx ; + sgVec4 co ; + + sgCopyVec3 ( vx, vt -> getVertex (i) ) ; + sgScaleVec3 ( vx, (i&7) ? 0.5f : 2.0f ) ; + + /* + Put random colours on the vertices. + */ + + sgSetVec4 ( co, (float)(rand()&0xFF)/255.0f, + (float)(rand()&0xFF)/255.0f, + (float)(rand()&0xFF)/255.0f, 1.0f ) ; + + /* + Cheat and make the normals and texture coords be + the same as the sphere. + */ + + v1 -> add ( vx ) ; + n1 -> add ( vt -> getNormal (i) ) ; + t1 -> add ( vt -> getTexCoord (i) ) ; + c1 -> add ( co ) ; + } + + /* + For each VtxTable in the sphere, create a + Tween node that morphs between the sphere + and the spikey sphere. + */ + + ssgTween *tw = new ssgTween ( GL_TRIANGLE_STRIP ) ; + tw -> newBank ( v0, n0, t0, c0 ) ; + tw -> newBank ( v1, n1, t1, c1 ) ; + + /* + Add it into the tween controller + (although there could be a lot of hierarchy + between the two if you wanted that) + */ + + tween_ctrl -> addKid ( tw ) ; + } +} + + + +/* + The works. +*/ + +int main ( int, char ** ) +{ + init_graphics () ; + load_database () ; + + while ( 1 ) + { + ulMilliSecondSleep ( 16 ) ; + redraw () ; + pwSwapBuffers () ; + } + + return 0 ; +} + diff --git a/examples/src/ssg/tween_test/tween_test.dsp b/examples/src/ssg/tween_test/tween_test.dsp new file mode 100644 index 0000000..490a3b5 --- /dev/null +++ b/examples/src/ssg/tween_test/tween_test.dsp @@ -0,0 +1,90 @@ +# Microsoft Developer Studio Project File - Name="tween_test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=tween_test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "tween_test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "tween_test.mak" CFG="tween_test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "tween_test - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "tween_test - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "tween_test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg.lib sg.lib ul.lib pw.lib winmm.lib opengl32.lib glu32.lib glut32.lib ssgAux.lib /nologo /subsystem:console /machine:I386 /out:"tween_test.exe" /libpath:"..\..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "tween_test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg_d.lib ssgAux_d.lib sg_d.lib ul_d.lib pw_d.lib winmm.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /debug /machine:I386 /out:"tween_test.exe" /pdbtype:sept /libpath:"..\..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "tween_test - Win32 Release" +# Name "tween_test - Win32 Debug" +# Begin Source File + +SOURCE=.\tween_test.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/ssg/viewer/Makefile.am b/examples/src/ssg/viewer/Makefile.am new file mode 100644 index 0000000..8550a6e --- /dev/null +++ b/examples/src/ssg/viewer/Makefile.am @@ -0,0 +1,17 @@ +if BUILD_SSG + +noinst_PROGRAMS = viewer pview + +viewer_SOURCES = viewer.cxx + +pview_SOURCES = pview.cxx + +viewer_LDADD = -lplibssg -lplibpuaux -lplibpu -lplibfnt -lplibsg -lplibul $(GLUT_LIBS) \ + $(OGL_LIBS) + +pview_LDADD = -lplibssg -lplibpu -lplibfnt -lplibsg -lplibul $(GLUT_LIBS) $(OGL_LIBS) + +endif + +EXTRA_DIST = viewer.dsp + diff --git a/examples/src/ssg/viewer/data/NOTES b/examples/src/ssg/viewer/data/NOTES new file mode 100644 index 0000000..e5b4ddb --- /dev/null +++ b/examples/src/ssg/viewer/data/NOTES @@ -0,0 +1,10 @@ +This directory contains sample VRML scenes made at the IICM. +Distribute them freely as long as you mention their origin. +They are also available at http://hgiicm.tu-graz.ac.at/C3d. + +Most of the scenes were created with Wavefont's Advanced Visualizer +and converted with scripts into SDF, the (old) native format of the +Harmony 3D scene viewer. VRweb was used to convert these files into +VRML. + +mpichler@iicm.tu-graz.ac.at diff --git a/examples/src/ssg/viewer/data/Pbody.rgb b/examples/src/ssg/viewer/data/Pbody.rgb new file mode 100644 index 0000000..1ba0f4b Binary files /dev/null and b/examples/src/ssg/viewer/data/Pbody.rgb differ diff --git a/examples/src/ssg/viewer/data/Penguin_beak.rgb b/examples/src/ssg/viewer/data/Penguin_beak.rgb new file mode 100644 index 0000000..b1e0e79 Binary files /dev/null and b/examples/src/ssg/viewer/data/Penguin_beak.rgb differ diff --git a/examples/src/ssg/viewer/data/Penguin_body.rgb b/examples/src/ssg/viewer/data/Penguin_body.rgb new file mode 100644 index 0000000..1ba0f4b Binary files /dev/null and b/examples/src/ssg/viewer/data/Penguin_body.rgb differ diff --git a/examples/src/ssg/viewer/data/animated.ASE b/examples/src/ssg/viewer/data/animated.ASE new file mode 100644 index 0000000..b4ad7a8 --- /dev/null +++ b/examples/src/ssg/viewer/data/animated.ASE @@ -0,0 +1,299 @@ +*3DSMAX_ASCIIEXPORT 200 +*COMMENT "AsciiExport Version 2.00 - Sun Oct 24 23:45:37 2004" +*SCENE { + *SCENE_FILENAME "" + *SCENE_FIRSTFRAME 0 + *SCENE_LASTFRAME 100 + *SCENE_FRAMESPEED 30 + *SCENE_TICKSPERFRAME 160 + *SCENE_BACKGROUND_STATIC 0.0000 0.0000 0.0000 + *SCENE_AMBIENT_STATIC 0.0000 0.0000 0.0000 +} +*MATERIAL_LIST { + *MATERIAL_COUNT 2 + *MATERIAL 0 { + *MATERIAL_NAME "Brown" + *MATERIAL_CLASS "Standard" + *MATERIAL_AMBIENT 0.5020 0.5020 0.5020 + *MATERIAL_DIFFUSE 0.5020 0.5020 0.5020 + *MATERIAL_SPECULAR 0.5020 0.5020 0.5020 + *MATERIAL_SHINE 0.2500 + *MATERIAL_SHINESTRENGTH 0.0500 + *MATERIAL_TRANSPARENCY 0.0000 + *MATERIAL_WIRESIZE 1.0000 + *MATERIAL_SHADING Blinn + *MATERIAL_XP_FALLOFF 0.0000 + *MATERIAL_SELFILLUM 0.0000 + *MATERIAL_FALLOFF In + *MATERIAL_XP_TYPE Filter + *MAP_DIFFUSE { + *MAP_NAME "Map #11" + *MAP_CLASS "Bitmap" + *MAP_SUBNO 1 + *MAP_AMOUNT 1.0000 + *BITMAP "brown.bmp" + *MAP_TYPE Screen + *UVW_U_OFFSET 0.0000 + *UVW_V_OFFSET 0.0000 + *UVW_U_TILING 1.0000 + *UVW_V_TILING 1.0000 + *UVW_ANGLE 0.0000 + *UVW_BLUR 1.0000 + *UVW_BLUR_OFFSET 0.0000 + *UVW_NOUSE_AMT 1.0000 + *UVW_NOISE_SIZE 1.0000 + *UVW_NOISE_LEVEL 1 + *UVW_NOISE_PHASE 0.0000 + *BITMAP_FILTER Pyramidal + } + } + *MATERIAL 1 { + *MATERIAL_NAME "Grey" + *MATERIAL_CLASS "Standard" + *MATERIAL_AMBIENT 0.5020 0.5020 0.5020 + *MATERIAL_DIFFUSE 0.5020 0.5020 0.5020 + *MATERIAL_SPECULAR 0.5020 0.5020 0.5020 + *MATERIAL_SHINE 0.2500 + *MATERIAL_SHINESTRENGTH 0.0500 + *MATERIAL_TRANSPARENCY 0.0000 + *MATERIAL_WIRESIZE 1.0000 + *MATERIAL_SHADING Blinn + *MATERIAL_XP_FALLOFF 0.0000 + *MATERIAL_SELFILLUM 0.0000 + *MATERIAL_FALLOFF In + *MATERIAL_XP_TYPE Filter + *MAP_DIFFUSE { + *MAP_NAME "Map #12" + *MAP_CLASS "Bitmap" + *MAP_SUBNO 1 + *MAP_AMOUNT 1.0000 + *BITMAP "gray.bmp" + *MAP_TYPE Screen + *UVW_U_OFFSET 0.0000 + *UVW_V_OFFSET 0.0000 + *UVW_U_TILING 1.0000 + *UVW_V_TILING 1.0000 + *UVW_ANGLE 0.0000 + *UVW_BLUR 1.0000 + *UVW_BLUR_OFFSET 0.0000 + *UVW_NOUSE_AMT 1.0000 + *UVW_NOISE_SIZE 1.0000 + *UVW_NOISE_LEVEL 1 + *UVW_NOISE_PHASE 0.0000 + *BITMAP_FILTER Pyramidal + } + } +} +*GEOMOBJECT { + *NODE_NAME "Box01" + *NODE_TM { + *NODE_NAME "Box01" + *INHERIT_POS 0 0 0 + *INHERIT_ROT 0 0 0 + *INHERIT_SCL 0 0 0 + *TM_ROW0 1.0000 0.0000 0.0000 + *TM_ROW1 0.0000 1.0000 0.0000 + *TM_ROW2 0.0000 0.0000 1.0000 + *TM_ROW3 0.0000 0.0000 0.0000 + *TM_POS 0.0000 0.0000 0.0000 + *TM_ROTAXIS 0.0000 0.0000 0.0000 + *TM_ROTANGLE 0.0000 + *TM_SCALE 1.0000 1.0000 1.0000 + *TM_SCALEAXIS 0.0000 0.0000 0.0000 + *TM_SCALEAXISANG 0.0000 + } + *MESH { + *TIMEVALUE 0 + *MESH_NUMVERTEX 8 + *MESH_NUMFACES 12 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 -5.0000 -5.0000 0.0000 + *MESH_VERTEX 1 5.0000 -5.0000 0.0000 + *MESH_VERTEX 2 -5.0000 5.0000 0.0000 + *MESH_VERTEX 3 5.0000 5.0000 0.0000 + *MESH_VERTEX 4 -5.0000 -5.0000 2.0000 + *MESH_VERTEX 5 5.0000 -5.0000 2.0000 + *MESH_VERTEX 6 -5.0000 5.0000 2.0000 + *MESH_VERTEX 7 5.0000 5.0000 2.0000 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 3: A: 7 B: 6 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 1 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 5: A: 5 B: 4 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 6: A: 1 B: 3 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 7: A: 7 B: 5 C: 1 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 8: A: 3 B: 2 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 9: A: 6 B: 7 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 10: A: 2 B: 0 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 11: A: 4 B: 6 C: 2 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + } + *MESH_NUMTVERTEX 0 + *MESH_NORMALS { + *MESH_FACENORMAL 0 0.0000 0.0000 -1.0000 + *MESH_VERTEXNORMAL 0 0.0000 0.0000 -1.0000 + *MESH_VERTEXNORMAL 2 0.0000 0.0000 -1.0000 + *MESH_VERTEXNORMAL 3 0.0000 0.0000 -1.0000 + *MESH_FACENORMAL 1 0.0000 0.0000 -1.0000 + *MESH_VERTEXNORMAL 3 0.0000 0.0000 -1.0000 + *MESH_VERTEXNORMAL 1 0.0000 0.0000 -1.0000 + *MESH_VERTEXNORMAL 0 0.0000 0.0000 -1.0000 + *MESH_FACENORMAL 2 0.0000 0.0000 1.0000 + *MESH_VERTEXNORMAL 4 0.0000 0.0000 1.0000 + *MESH_VERTEXNORMAL 5 0.0000 0.0000 1.0000 + *MESH_VERTEXNORMAL 7 0.0000 0.0000 1.0000 + *MESH_FACENORMAL 3 0.0000 0.0000 1.0000 + *MESH_VERTEXNORMAL 7 0.0000 0.0000 1.0000 + *MESH_VERTEXNORMAL 6 0.0000 0.0000 1.0000 + *MESH_VERTEXNORMAL 4 0.0000 0.0000 1.0000 + *MESH_FACENORMAL 4 0.0000 -1.0000 0.0000 + *MESH_VERTEXNORMAL 0 0.0000 -1.0000 0.0000 + *MESH_VERTEXNORMAL 1 0.0000 -1.0000 0.0000 + *MESH_VERTEXNORMAL 5 0.0000 -1.0000 0.0000 + *MESH_FACENORMAL 5 0.0000 -1.0000 0.0000 + *MESH_VERTEXNORMAL 5 0.0000 -1.0000 0.0000 + *MESH_VERTEXNORMAL 4 0.0000 -1.0000 0.0000 + *MESH_VERTEXNORMAL 0 0.0000 -1.0000 0.0000 + *MESH_FACENORMAL 6 1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 1 1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 3 1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 7 1.0000 0.0000 0.0000 + *MESH_FACENORMAL 7 1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 7 1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 5 1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 1 1.0000 0.0000 0.0000 + *MESH_FACENORMAL 8 0.0000 1.0000 0.0000 + *MESH_VERTEXNORMAL 3 0.0000 1.0000 0.0000 + *MESH_VERTEXNORMAL 2 0.0000 1.0000 0.0000 + *MESH_VERTEXNORMAL 6 0.0000 1.0000 0.0000 + *MESH_FACENORMAL 9 0.0000 1.0000 0.0000 + *MESH_VERTEXNORMAL 6 0.0000 1.0000 0.0000 + *MESH_VERTEXNORMAL 7 0.0000 1.0000 0.0000 + *MESH_VERTEXNORMAL 3 0.0000 1.0000 0.0000 + *MESH_FACENORMAL 10 -1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 2 -1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 0 -1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 4 -1.0000 0.0000 0.0000 + *MESH_FACENORMAL 11 -1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 4 -1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 6 -1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 2 -1.0000 0.0000 0.0000 + } + } + *PROP_MOTIONBLUR 0 + *PROP_CASTSHADOW 1 + *PROP_RECVSHADOW 1 + *WIREFRAME_COLOR 0.5255 0.0235 0.0235 +} +*GEOMOBJECT { + *NODE_NAME "Box02" + *NODE_TM { + *NODE_NAME "Box02" + *INHERIT_POS 0 0 0 + *INHERIT_ROT 0 0 0 + *INHERIT_SCL 0 0 0 + *TM_ROW0 1.0000 0.0000 0.0000 + *TM_ROW1 0.0000 1.0000 0.0000 + *TM_ROW2 0.0000 0.0000 1.0000 + *TM_ROW3 5.0000 0.0000 0.0000 + *TM_POS 5.0000 0.0000 0.0000 + *TM_ROTAXIS 0.0000 0.0000 0.0000 + *TM_ROTANGLE 0.0000 + *TM_SCALE 1.0000 1.0000 1.0000 + *TM_SCALEAXIS 0.0000 0.0000 0.0000 + *TM_SCALEAXISANG 0.0000 + } + *MESH { + *TIMEVALUE 0 + *MESH_NUMVERTEX 8 + *MESH_NUMFACES 12 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 5.0000 -5.0000 0.0000 + *MESH_VERTEX 1 15.0000 -5.0000 0.0000 + *MESH_VERTEX 2 5.0000 5.0000 0.0000 + *MESH_VERTEX 3 15.0000 5.0000 0.0000 + *MESH_VERTEX 4 5.0000 -5.0000 2.0000 + *MESH_VERTEX 5 15.0000 -5.0000 2.0000 + *MESH_VERTEX 6 5.0000 5.0000 2.0000 + *MESH_VERTEX 7 15.0000 5.0000 2.0000 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 3: A: 7 B: 6 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 1 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 5: A: 5 B: 4 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 6: A: 1 B: 3 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 7: A: 7 B: 5 C: 1 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 8: A: 3 B: 2 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 9: A: 6 B: 7 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 10: A: 2 B: 0 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 11: A: 4 B: 6 C: 2 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + } + *MESH_NUMTVERTEX 0 + *MESH_NORMALS { + *MESH_FACENORMAL 0 0.0000 0.0000 -1.0000 + *MESH_VERTEXNORMAL 0 0.0000 0.0000 -1.0000 + *MESH_VERTEXNORMAL 2 0.0000 0.0000 -1.0000 + *MESH_VERTEXNORMAL 3 0.0000 0.0000 -1.0000 + *MESH_FACENORMAL 1 0.0000 0.0000 -1.0000 + *MESH_VERTEXNORMAL 3 0.0000 0.0000 -1.0000 + *MESH_VERTEXNORMAL 1 0.0000 0.0000 -1.0000 + *MESH_VERTEXNORMAL 0 0.0000 0.0000 -1.0000 + *MESH_FACENORMAL 2 0.0000 0.0000 1.0000 + *MESH_VERTEXNORMAL 4 0.0000 0.0000 1.0000 + *MESH_VERTEXNORMAL 5 0.0000 0.0000 1.0000 + *MESH_VERTEXNORMAL 7 0.0000 0.0000 1.0000 + *MESH_FACENORMAL 3 0.0000 0.0000 1.0000 + *MESH_VERTEXNORMAL 7 0.0000 0.0000 1.0000 + *MESH_VERTEXNORMAL 6 0.0000 0.0000 1.0000 + *MESH_VERTEXNORMAL 4 0.0000 0.0000 1.0000 + *MESH_FACENORMAL 4 0.0000 -1.0000 0.0000 + *MESH_VERTEXNORMAL 0 0.0000 -1.0000 0.0000 + *MESH_VERTEXNORMAL 1 0.0000 -1.0000 0.0000 + *MESH_VERTEXNORMAL 5 0.0000 -1.0000 0.0000 + *MESH_FACENORMAL 5 0.0000 -1.0000 0.0000 + *MESH_VERTEXNORMAL 5 0.0000 -1.0000 0.0000 + *MESH_VERTEXNORMAL 4 0.0000 -1.0000 0.0000 + *MESH_VERTEXNORMAL 0 0.0000 -1.0000 0.0000 + *MESH_FACENORMAL 6 1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 1 1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 3 1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 7 1.0000 0.0000 0.0000 + *MESH_FACENORMAL 7 1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 7 1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 5 1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 1 1.0000 0.0000 0.0000 + *MESH_FACENORMAL 8 0.0000 1.0000 0.0000 + *MESH_VERTEXNORMAL 3 0.0000 1.0000 0.0000 + *MESH_VERTEXNORMAL 2 0.0000 1.0000 0.0000 + *MESH_VERTEXNORMAL 6 0.0000 1.0000 0.0000 + *MESH_FACENORMAL 9 0.0000 1.0000 0.0000 + *MESH_VERTEXNORMAL 6 0.0000 1.0000 0.0000 + *MESH_VERTEXNORMAL 7 0.0000 1.0000 0.0000 + *MESH_VERTEXNORMAL 3 0.0000 1.0000 0.0000 + *MESH_FACENORMAL 10 -1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 2 -1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 0 -1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 4 -1.0000 0.0000 0.0000 + *MESH_FACENORMAL 11 -1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 4 -1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 6 -1.0000 0.0000 0.0000 + *MESH_VERTEXNORMAL 2 -1.0000 0.0000 0.0000 + } + } + *PROP_MOTIONBLUR 0 + *PROP_CASTSHADOW 1 + *PROP_RECVSHADOW 1 + *TM_ANIMATION { + *NODE_NAME "Box02" + *CONTROL_ROT_TCB { + *CONTROL_TCB_ROT_KEY 0 1.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 + *CONTROL_TCB_ROT_KEY 1600 0.0000 -1.0000 -0.0000 0.3491 0.0000 0.0000 0.0000 0.0000 0.0000 + } + } + *WIREFRAME_COLOR 0.2235 0.0314 0.5333 +} diff --git a/examples/src/ssg/viewer/data/ant_vr.wrl b/examples/src/ssg/viewer/data/ant_vr.wrl new file mode 100644 index 0000000..9a7d554 --- /dev/null +++ b/examples/src/ssg/viewer/data/ant_vr.wrl @@ -0,0 +1,571 @@ +#VRML V1.0 ascii + +Separator { + + DEF SceneInfo Info { + string "Converted by wcvt2pov v2.6c and the datafat munger" + } + DEF RearBody Separator { + Material { + diffuseColor 0.36 0.20 0.09 + ambientColor 0.03 0.02 0 + } + Coordinate3 { + point [ +-0.08 0.17 0.70, +-0.08 0.01 0.70, +-0.24 -0.15 0.52, +-0.24 0.34 0.52, +0.08 0.01 0.70, +0.24 -0.15 0.52, +0.08 0.17 0.70, +0.24 0.34 0.52, +-0.21 -0.12 0.19, +-0.21 0.31 0.19, +0.21 -0.12 0.19, +0.21 0.31 0.19, +-0.08 0.01 0, +-0.08 0.17 0, +0.08 0.01 0, +0.08 0.17 0, +-0 0.09 0.70, +-0 0.09 0 + ] + } + + IndexedFaceSet { + coordIndex [ +2, 1, 0, -1, +3, 2, 0, -1, +5, 4, 1, -1, +2, 5, 1, -1, +7, 6, 4, -1, +5, 7, 4, -1, +3, 0, 6, -1, +7, 3, 6, -1, +8, 2, 3, -1, +9, 8, 3, -1, +10, 5, 2, -1, +8, 10, 2, -1, +11, 7, 5, -1, +10, 11, 5, -1, +9, 3, 7, -1, +11, 9, 7, -1, +12, 8, 9, -1, +13, 12, 9, -1, +14, 10, 8, -1, +12, 14, 8, -1, +15, 11, 10, -1, +14, 15, 10, -1, +13, 9, 11, -1, +15, 13, 11, -1, +16, 0, 1, -1, +16, 1, 4, -1, +16, 4, 6, -1, +16, 6, 0, -1, +17, 12, 13, -1, +17, 14, 12, -1, +17, 15, 14, -1, +17, 13, 15, -1 + ] + } + } + DEF MidBody Separator { + Material { + diffuseColor 0.36 0.20 0.09 + ambientColor 0.03 0.02 0 + } + Coordinate3 { + point [ +-0.10 -0 -0.29, +-0.10 0.19 -0.29, +-0.13 0.22 -0.14, +-0.13 -0.03 -0.14, +0.09 0.19 -0.29, +0.13 0.22 -0.14, +0.09 -0 -0.29, +0.13 -0.03 -0.14, +-0.10 0.19 0, +-0.10 -0 0, +0.09 0.19 0, +0.09 -0 0, +-0 0.09 -0.29, +-0 0.09 0 + ] + } + + IndexedFaceSet { + coordIndex [ +2, 1, 0, -1, +3, 2, 0, -1, +5, 4, 1, -1, +2, 5, 1, -1, +7, 6, 4, -1, +5, 7, 4, -1, +3, 0, 6, -1, +7, 3, 6, -1, +8, 2, 3, -1, +9, 8, 3, -1, +10, 5, 2, -1, +8, 10, 2, -1, +11, 7, 5, -1, +10, 11, 5, -1, +9, 3, 7, -1, +11, 9, 7, -1, +12, 0, 1, -1, +12, 1, 4, -1, +12, 4, 6, -1, +12, 6, 0, -1, +13, 8, 9, -1, +13, 10, 8, -1, +13, 11, 10, -1, +13, 9, 11, -1 + ] + } + } + DEF Head Separator { + Material { + diffuseColor 0.36 0.20 0.09 + ambientColor 0.03 0.02 0 + } + Coordinate3 { + point [ +-0.10 0.19 -0.30, +-0.15 0.25 -0.41, +0.10 0.19 -0.30, +0.15 0.25 -0.41, +-0.10 -0.01 -0.30, +-0.15 -0.06 -0.41, +0.10 -0.01 -0.30, +0.15 -0.06 -0.41, +-0.10 0.19 -0.52, +0.10 0.19 -0.52, +-0.05 0.02 -0.65, +0.05 0.02 -0.65, +-0 0.09 -0.30, +-0 0.11 -0.59 + ] + } + + IndexedFaceSet { + coordIndex [ +2, 1, 0, -1, +2, 3, 1, -1, +0, 5, 4, -1, +0, 1, 5, -1, +4, 7, 6, -1, +4, 5, 7, -1, +6, 3, 2, -1, +6, 7, 3, -1, +3, 8, 1, -1, +3, 9, 8, -1, +1, 10, 5, -1, +1, 8, 10, -1, +5, 11, 7, -1, +5, 10, 11, -1, +7, 9, 3, -1, +7, 11, 9, -1, +0, 12, 2, -1, +4, 12, 0, -1, +6, 12, 4, -1, +2, 12, 6, -1, +9, 13, 8, -1, +8, 13, 10, -1, +10, 13, 11, -1, +11, 13, 9, -1 + ] + } + } + DEF RightFrontLeg Separator { + Material { + diffuseColor 0.36 0.20 0.09 + ambientColor 0.03 0.02 0 + } + Coordinate3 { + point [ +-0.61 -0.34 -0.70, +-0.61 -0.34 -0.70, +-0.55 -0.09 -0.67, +-0.57 -0.09 -0.64, +-0.61 -0.34 -0.70, +-0.52 -0.11 -0.65, +-0.61 -0.34 -0.70, +-0.55 -0.11 -0.62, +-0.29 0.10 -0.46, +-0.32 0.10 -0.42, +-0.27 0.06 -0.45, +-0.30 0.06 -0.41, +-0.04 0.10 -0.25, +-0.07 0.10 -0.22, +-0.04 0.05 -0.25, +-0.07 0.05 -0.22, +-0.61 -0.34 -0.70, +-0.06 0.08 -0.24 + ] + } + + IndexedFaceSet { + coordIndex [ +2, 1, 0, -1, +3, 2, 0, -1, +5, 4, 1, -1, +2, 5, 1, -1, +7, 6, 4, -1, +5, 7, 4, -1, +3, 0, 6, -1, +7, 3, 6, -1, +8, 2, 3, -1, +9, 8, 3, -1, +10, 5, 2, -1, +8, 10, 2, -1, +11, 7, 5, -1, +10, 11, 5, -1, +9, 3, 7, -1, +11, 9, 7, -1, +12, 8, 9, -1, +13, 12, 9, -1, +14, 10, 8, -1, +12, 14, 8, -1, +15, 11, 10, -1, +14, 15, 10, -1, +13, 9, 11, -1, +15, 13, 11, -1, +16, 0, 1, -1, +16, 1, 4, -1, +16, 4, 6, -1, +16, 6, 0, -1, +17, 12, 13, -1, +17, 14, 12, -1, +17, 15, 14, -1, +17, 13, 15, -1 + ] + } + } + DEF Right3rdLeg Separator { + Material { + diffuseColor 0.36 0.20 0.09 + ambientColor 0.03 0.02 0 + } + Coordinate3 { + point [ +-0.80 -0.34 0.01, +-0.80 -0.34 0.01, +-0.73 -0.09 -0.01, +-0.72 -0.09 0.01, +-0.80 -0.34 0.01, +-0.70 -0.11 -0.01, +-0.79 -0.34 0.01, +-0.69 -0.11 0.01, +-0.40 0.10 -0.07, +-0.40 0.10 -0.03, +-0.38 0.06 -0.08, +-0.37 0.06 -0.03, +-0.09 0.10 -0.13, +-0.08 0.10 -0.08, +-0.09 0.05 -0.13, +-0.08 0.05 -0.08, +-0.80 -0.34 0.01, +-0.08 0.08 -0.11 + ] + } + + IndexedFaceSet { + coordIndex [ +2, 1, 0, -1, +3, 2, 0, -1, +5, 4, 1, -1, +2, 5, 1, -1, +7, 6, 4, -1, +5, 7, 4, -1, +3, 0, 6, -1, +7, 3, 6, -1, +8, 2, 3, -1, +9, 8, 3, -1, +10, 5, 2, -1, +8, 10, 2, -1, +11, 7, 5, -1, +10, 11, 5, -1, +9, 3, 7, -1, +11, 9, 7, -1, +12, 8, 9, -1, +13, 12, 9, -1, +14, 10, 8, -1, +12, 14, 8, -1, +15, 11, 10, -1, +14, 15, 10, -1, +13, 9, 11, -1, +15, 13, 11, -1, +16, 0, 1, -1, +16, 1, 4, -1, +16, 4, 6, -1, +16, 6, 0, -1, +17, 12, 13, -1, +17, 14, 12, -1, +17, 15, 14, -1, +17, 13, 15, -1 + ] + } + } + DEF RightRearLeg Separator { + Material { + diffuseColor 0.36 0.20 0.09 + ambientColor 0.03 0.02 0 + } + Coordinate3 { + point [ +-0.62 -0.34 0.41, +-0.63 -0.34 0.41, +-0.58 -0.09 0.35, +-0.56 -0.09 0.38, +-0.62 -0.34 0.41, +-0.56 -0.11 0.33, +-0.62 -0.34 0.41, +-0.54 -0.11 0.36, +-0.33 0.10 0.13, +-0.30 0.10 0.17, +-0.31 0.06 0.12, +-0.28 0.06 0.15, +-0.09 0.10 -0.06, +-0.06 0.10 -0.03, +-0.09 0.05 -0.06, +-0.06 0.05 -0.03, +-0.62 -0.34 0.41, +-0.07 0.08 -0.05 + ] + } + + IndexedFaceSet { + coordIndex [ +2, 1, 0, -1, +3, 2, 0, -1, +5, 4, 1, -1, +2, 5, 1, -1, +7, 6, 4, -1, +5, 7, 4, -1, +3, 0, 6, -1, +7, 3, 6, -1, +8, 2, 3, -1, +9, 8, 3, -1, +10, 5, 2, -1, +8, 10, 2, -1, +11, 7, 5, -1, +10, 11, 5, -1, +9, 3, 7, -1, +11, 9, 7, -1, +12, 8, 9, -1, +13, 12, 9, -1, +14, 10, 8, -1, +12, 14, 8, -1, +15, 11, 10, -1, +14, 15, 10, -1, +13, 9, 11, -1, +15, 13, 11, -1, +16, 0, 1, -1, +16, 1, 4, -1, +16, 4, 6, -1, +16, 6, 0, -1, +17, 12, 13, -1, +17, 14, 12, -1, +17, 15, 14, -1, +17, 13, 15, -1 + ] + } + } + DEF LeftFrontLeg Separator { + Material { + diffuseColor 0.36 0.20 0.09 + ambientColor 0.03 0.02 0 + } + Coordinate3 { + point [ +0.55 -0.09 -0.67, +0.61 -0.34 -0.70, +0.61 -0.34 -0.70, +0.57 -0.09 -0.64, +0.52 -0.11 -0.65, +0.61 -0.34 -0.70, +0.55 -0.11 -0.62, +0.61 -0.34 -0.70, +0.29 0.10 -0.46, +0.32 0.10 -0.42, +0.27 0.06 -0.45, +0.30 0.06 -0.41, +0.04 0.10 -0.25, +0.07 0.10 -0.22, +0.04 0.05 -0.25, +0.07 0.05 -0.22, +0.61 -0.34 -0.70, +0.06 0.08 -0.24 + ] + } + + IndexedFaceSet { + coordIndex [ +2, 1, 0, -1, +2, 0, 3, -1, +1, 5, 4, -1, +1, 4, 0, -1, +5, 7, 6, -1, +5, 6, 4, -1, +7, 2, 3, -1, +7, 3, 6, -1, +3, 0, 8, -1, +3, 8, 9, -1, +0, 4, 10, -1, +0, 10, 8, -1, +4, 6, 11, -1, +4, 11, 10, -1, +6, 3, 9, -1, +6, 9, 11, -1, +9, 8, 12, -1, +9, 12, 13, -1, +8, 10, 14, -1, +8, 14, 12, -1, +10, 11, 15, -1, +10, 15, 14, -1, +11, 9, 13, -1, +11, 13, 15, -1, +1, 2, 16, -1, +5, 1, 16, -1, +7, 5, 16, -1, +2, 7, 16, -1, +13, 12, 17, -1, +12, 14, 17, -1, +14, 15, 17, -1, +15, 13, 17, -1 + ] + } + } + DEF Left3rdLeg Separator { + Material { + diffuseColor 0.36 0.20 0.09 + ambientColor 0.03 0.02 0 + } + Coordinate3 { + point [ +0.73 -0.09 -0.01, +0.80 -0.34 0.01, +0.80 -0.34 0.01, +0.72 -0.09 0.01, +0.70 -0.11 -0.01, +0.80 -0.34 0.01, +0.69 -0.11 0.01, +0.79 -0.34 0.01, +0.40 0.10 -0.07, +0.40 0.10 -0.03, +0.38 0.06 -0.08, +0.37 0.06 -0.03, +0.09 0.10 -0.13, +0.08 0.10 -0.08, +0.09 0.05 -0.13, +0.08 0.05 -0.08, +0.80 -0.34 0.01, +0.08 0.08 -0.11 + ] + } + + IndexedFaceSet { + coordIndex [ +2, 1, 0, -1, +2, 0, 3, -1, +1, 5, 4, -1, +1, 4, 0, -1, +5, 7, 6, -1, +5, 6, 4, -1, +7, 2, 3, -1, +7, 3, 6, -1, +3, 0, 8, -1, +3, 8, 9, -1, +0, 4, 10, -1, +0, 10, 8, -1, +4, 6, 11, -1, +4, 11, 10, -1, +6, 3, 9, -1, +6, 9, 11, -1, +9, 8, 12, -1, +9, 12, 13, -1, +8, 10, 14, -1, +8, 14, 12, -1, +10, 11, 15, -1, +10, 15, 14, -1, +11, 9, 13, -1, +11, 13, 15, -1, +1, 2, 16, -1, +5, 1, 16, -1, +7, 5, 16, -1, +2, 7, 16, -1, +13, 12, 17, -1, +12, 14, 17, -1, +14, 15, 17, -1, +15, 13, 17, -1 + ] + } + } + DEF LeftRearLeg Separator { + Material { + diffuseColor 0.36 0.20 0.09 + ambientColor 0.03 0.02 0 + } + Coordinate3 { + point [ +0.58 -0.09 0.35, +0.63 -0.34 0.41, +0.62 -0.34 0.41, +0.56 -0.09 0.38, +0.56 -0.11 0.33, +0.62 -0.34 0.41, +0.54 -0.11 0.36, +0.62 -0.34 0.41, +0.33 0.10 0.13, +0.30 0.10 0.17, +0.31 0.06 0.12, +0.28 0.06 0.15, +0.09 0.10 -0.06, +0.06 0.10 -0.03, +0.09 0.05 -0.06, +0.06 0.05 -0.03, +0.62 -0.34 0.41, +0.07 0.08 -0.05 + ] + } + + IndexedFaceSet { + coordIndex [ +2, 1, 0, -1, +2, 0, 3, -1, +1, 5, 4, -1, +1, 4, 0, -1, +5, 7, 6, -1, +5, 6, 4, -1, +7, 2, 3, -1, +7, 3, 6, -1, +3, 0, 8, -1, +3, 8, 9, -1, +0, 4, 10, -1, +0, 10, 8, -1, +4, 6, 11, -1, +4, 11, 10, -1, +6, 3, 9, -1, +6, 9, 11, -1, +9, 8, 12, -1, +9, 12, 13, -1, +8, 10, 14, -1, +8, 14, 12, -1, +10, 11, 15, -1, +10, 15, 14, -1, +11, 9, 13, -1, +11, 13, 15, -1, +1, 2, 16, -1, +5, 1, 16, -1, +7, 5, 16, -1, +2, 7, 16, -1, +13, 12, 17, -1, +12, 14, 17, -1, +14, 15, 17, -1, +15, 13, 17, -1 + ] + } + } + +} + diff --git a/examples/src/ssg/viewer/data/brown.bmp b/examples/src/ssg/viewer/data/brown.bmp new file mode 100644 index 0000000..d268439 Binary files /dev/null and b/examples/src/ssg/viewer/data/brown.bmp differ diff --git a/examples/src/ssg/viewer/data/default.txf b/examples/src/ssg/viewer/data/default.txf new file mode 100644 index 0000000..dfcb438 Binary files /dev/null and b/examples/src/ssg/viewer/data/default.txf differ diff --git a/examples/src/ssg/viewer/data/door.ase b/examples/src/ssg/viewer/data/door.ase new file mode 100644 index 0000000..b30f7e4 --- /dev/null +++ b/examples/src/ssg/viewer/data/door.ase @@ -0,0 +1,2978 @@ +*3DSMAX_ASCIIEXPORT 200 +*COMMENT "AsciiExport Version 2.00 - Tue Aug 08 13:10:03 2000" +*SCENE { + *SCENE_FILENAME "DragonsCaveDoor808c.max" + *SCENE_FIRSTFRAME 0 + *SCENE_LASTFRAME 12 + *SCENE_FRAMESPEED 30 + *SCENE_TICKSPERFRAME 160 + *SCENE_BACKGROUND_STATIC 0.5020 0.5020 0.5020 + *SCENE_AMBIENT_STATIC 0.0000 0.0000 0.0000 +} +*MATERIAL_LIST { + *MATERIAL_COUNT 2 + *MATERIAL 0 { + *MATERIAL_NAME "Brown" + *MATERIAL_CLASS "Standard" + *MATERIAL_AMBIENT 0.5020 0.5020 0.5020 + *MATERIAL_DIFFUSE 0.5020 0.5020 0.5020 + *MATERIAL_SPECULAR 0.5020 0.5020 0.5020 + *MATERIAL_SHINE 0.2500 + *MATERIAL_SHINESTRENGTH 0.0500 + *MATERIAL_TRANSPARENCY 0.0000 + *MATERIAL_WIRESIZE 1.0000 + *MATERIAL_SHADING Blinn + *MATERIAL_XP_FALLOFF 0.0000 + *MATERIAL_SELFILLUM 0.0000 + *MATERIAL_FALLOFF In + *MATERIAL_XP_TYPE Filter + *MAP_DIFFUSE { + *MAP_NAME "Map #11" + *MAP_CLASS "Bitmap" + *MAP_SUBNO 1 + *MAP_AMOUNT 1.0000 + *BITMAP "brown.bmp" + *MAP_TYPE Screen + *UVW_U_OFFSET 0.0000 + *UVW_V_OFFSET 0.0000 + *UVW_U_TILING 1.0000 + *UVW_V_TILING 1.0000 + *UVW_ANGLE 0.0000 + *UVW_BLUR 1.0000 + *UVW_BLUR_OFFSET 0.0000 + *UVW_NOUSE_AMT 1.0000 + *UVW_NOISE_SIZE 1.0000 + *UVW_NOISE_LEVEL 1 + *UVW_NOISE_PHASE 0.0000 + *BITMAP_FILTER Pyramidal + } + } + *MATERIAL 1 { + *MATERIAL_NAME "Grey" + *MATERIAL_CLASS "Standard" + *MATERIAL_AMBIENT 0.5020 0.5020 0.5020 + *MATERIAL_DIFFUSE 0.5020 0.5020 0.5020 + *MATERIAL_SPECULAR 0.5020 0.5020 0.5020 + *MATERIAL_SHINE 0.2500 + *MATERIAL_SHINESTRENGTH 0.0500 + *MATERIAL_TRANSPARENCY 0.0000 + *MATERIAL_WIRESIZE 1.0000 + *MATERIAL_SHADING Blinn + *MATERIAL_XP_FALLOFF 0.0000 + *MATERIAL_SELFILLUM 0.0000 + *MATERIAL_FALLOFF In + *MATERIAL_XP_TYPE Filter + *MAP_DIFFUSE { + *MAP_NAME "Map #12" + *MAP_CLASS "Bitmap" + *MAP_SUBNO 1 + *MAP_AMOUNT 1.0000 + *BITMAP "gray.bmp" + *MAP_TYPE Screen + *UVW_U_OFFSET 0.0000 + *UVW_V_OFFSET 0.0000 + *UVW_U_TILING 1.0000 + *UVW_V_TILING 1.0000 + *UVW_ANGLE 0.0000 + *UVW_BLUR 1.0000 + *UVW_BLUR_OFFSET 0.0000 + *UVW_NOUSE_AMT 1.0000 + *UVW_NOISE_SIZE 1.0000 + *UVW_NOISE_LEVEL 1 + *UVW_NOISE_PHASE 0.0000 + *BITMAP_FILTER Pyramidal + } + } +} +*GEOMOBJECT { + *NODE_NAME "FrontDoor" + *NODE_TM { + *NODE_NAME "FrontDoor" + *INHERIT_POS 0 0 0 + *INHERIT_ROT 0 0 0 + *INHERIT_SCL 0 0 0 + *TM_ROW0 1.0000 -0.0000 0.0000 + *TM_ROW1 -0.0000 0.0000 1.0000 + *TM_ROW2 -0.0000 -1.0000 0.0000 + *TM_ROW3 0.0299 1.4813 0.0034 + *TM_POS 0.0299 1.4813 0.0034 + *TM_ROTAXIS -1.0000 0.0000 0.0000 + *TM_ROTANGLE 1.5708 + *TM_SCALE 1.0000 1.0000 1.0000 + *TM_SCALEAXIS 0.0000 0.0000 0.0000 + *TM_SCALEAXISANG 0.0000 + } + *MESH { + *TIMEVALUE 0 + *MESH_NUMVERTEX 24 + *MESH_NUMFACES 44 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 -4.7153 -23.8849 -0.3323 + *MESH_VERTEX 1 4.7776 -23.8849 -0.3323 + *MESH_VERTEX 2 -4.7153 -22.3465 -1.5943 + *MESH_VERTEX 3 4.7776 -22.3465 -1.5943 + *MESH_VERTEX 4 -4.7153 -24.0885 -0.0147 + *MESH_VERTEX 5 -4.9945 -23.5694 -0.3323 + *MESH_VERTEX 6 -4.9945 -22.0310 -1.5942 + *MESH_VERTEX 7 -4.7153 -21.9659 -1.9097 + *MESH_VERTEX 8 4.7776 -21.9659 -1.9097 + *MESH_VERTEX 9 5.0568 -22.0310 -1.5943 + *MESH_VERTEX 10 5.0568 -23.5694 -0.3323 + *MESH_VERTEX 11 4.7776 -24.0885 -0.0147 + *MESH_VERTEX 12 -4.7153 1.3696 0.0001 + *MESH_VERTEX 13 -4.9945 1.3696 -0.3322 + *MESH_VERTEX 14 -4.9945 1.3696 -1.5942 + *MESH_VERTEX 15 -4.7153 1.3696 -1.9097 + *MESH_VERTEX 16 4.7776 1.3696 -1.9097 + *MESH_VERTEX 17 5.0568 1.3696 -1.5942 + *MESH_VERTEX 18 5.0568 1.3696 -0.3322 + *MESH_VERTEX 19 4.7776 1.3696 0.0001 + *MESH_VERTEX 20 4.7776 1.4947 -1.5943 + *MESH_VERTEX 21 -4.7153 1.4947 -1.5943 + *MESH_VERTEX 22 4.7776 1.4947 -0.3323 + *MESH_VERTEX 23 -4.7153 1.4947 -0.3323 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 1: A: 0 B: 3 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 2: A: 0 B: 4 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 3: A: 0 B: 5 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 6 C: 2 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 5: A: 2 B: 6 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 6: A: 2 B: 7 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 7: A: 2 B: 8 C: 3 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 8: A: 3 B: 8 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 9: A: 3 B: 9 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 10: A: 3 B: 10 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 11: A: 1 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 12: A: 1 B: 11 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 13: A: 1 B: 4 C: 0 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 14: A: 4 B: 12 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 15: A: 4 B: 13 C: 5 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 16: A: 5 B: 13 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 17: A: 5 B: 14 C: 6 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 18: A: 6 B: 14 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 19: A: 6 B: 15 C: 7 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 20: A: 7 B: 15 C: 16 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 21: A: 7 B: 16 C: 8 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 22: A: 8 B: 16 C: 17 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 23: A: 8 B: 17 C: 9 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 24: A: 9 B: 17 C: 18 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 25: A: 9 B: 18 C: 10 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 26: A: 10 B: 18 C: 19 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 27: A: 10 B: 19 C: 11 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 28: A: 11 B: 19 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 29: A: 11 B: 12 C: 4 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 30: A: 12 B: 23 C: 13 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 31: A: 13 B: 23 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 32: A: 13 B: 21 C: 14 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 33: A: 14 B: 21 C: 15 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 34: A: 15 B: 21 C: 20 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 35: A: 15 B: 20 C: 16 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 36: A: 16 B: 20 C: 17 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 37: A: 17 B: 20 C: 22 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 38: A: 17 B: 22 C: 18 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 39: A: 18 B: 22 C: 19 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 40: A: 19 B: 22 C: 23 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 41: A: 19 B: 23 C: 12 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 42: A: 22 B: 20 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 43: A: 22 B: 21 C: 23 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 24 + *MESH_CVERTLIST { + *MESH_VERTCOL 0 0.4236 0.4236 0.4236 + *MESH_VERTCOL 1 0.4202 0.4202 0.4202 + *MESH_VERTCOL 2 0.3837 0.3837 0.3837 + *MESH_VERTCOL 3 0.3717 0.3717 0.3717 + *MESH_VERTCOL 4 0.6691 0.6691 0.6691 + *MESH_VERTCOL 5 0.5788 0.5788 0.5788 + *MESH_VERTCOL 6 0.4225 0.4225 0.4225 + *MESH_VERTCOL 7 0.2765 0.2765 0.2765 + *MESH_VERTCOL 8 0.3049 0.3049 0.3049 + *MESH_VERTCOL 9 0.5108 0.5108 0.5108 + *MESH_VERTCOL 10 0.6195 0.6195 0.6195 + *MESH_VERTCOL 11 0.7210 0.7210 0.7210 + *MESH_VERTCOL 12 0.6054 0.6054 0.6054 + *MESH_VERTCOL 13 0.7167 0.7167 0.7167 + *MESH_VERTCOL 14 0.5792 0.5792 0.5792 + *MESH_VERTCOL 15 0.3464 0.3464 0.3464 + *MESH_VERTCOL 16 0.2693 0.2693 0.2693 + *MESH_VERTCOL 17 0.4903 0.4903 0.4903 + *MESH_VERTCOL 18 0.6958 0.6958 0.6958 + *MESH_VERTCOL 19 0.6274 0.6274 0.6274 + *MESH_VERTCOL 20 0.4361 0.4361 0.4361 + *MESH_VERTCOL 21 0.5644 0.5644 0.5644 + *MESH_VERTCOL 22 0.5445 0.5445 0.5445 + *MESH_VERTCOL 23 0.6008 0.6008 0.6008 + } + *MESH_NUMCVFACES 44 + *MESH_CFACELIST { + *MESH_CFACE 0 0 2 3 + *MESH_CFACE 1 0 3 1 + *MESH_CFACE 2 0 4 5 + *MESH_CFACE 3 0 5 6 + *MESH_CFACE 4 0 6 2 + *MESH_CFACE 5 2 6 7 + *MESH_CFACE 6 2 7 8 + *MESH_CFACE 7 2 8 3 + *MESH_CFACE 8 3 8 9 + *MESH_CFACE 9 3 9 10 + *MESH_CFACE 10 3 10 1 + *MESH_CFACE 11 1 10 11 + *MESH_CFACE 12 1 11 4 + *MESH_CFACE 13 1 4 0 + *MESH_CFACE 14 4 12 13 + *MESH_CFACE 15 4 13 5 + *MESH_CFACE 16 5 13 14 + *MESH_CFACE 17 5 14 6 + *MESH_CFACE 18 6 14 15 + *MESH_CFACE 19 6 15 7 + *MESH_CFACE 20 7 15 16 + *MESH_CFACE 21 7 16 8 + *MESH_CFACE 22 8 16 17 + *MESH_CFACE 23 8 17 9 + *MESH_CFACE 24 9 17 18 + *MESH_CFACE 25 9 18 10 + *MESH_CFACE 26 10 18 19 + *MESH_CFACE 27 10 19 11 + *MESH_CFACE 28 11 19 12 + *MESH_CFACE 29 11 12 4 + *MESH_CFACE 30 12 23 13 + *MESH_CFACE 31 13 23 21 + *MESH_CFACE 32 13 21 14 + *MESH_CFACE 33 14 21 15 + *MESH_CFACE 34 15 21 20 + *MESH_CFACE 35 15 20 16 + *MESH_CFACE 36 16 20 17 + *MESH_CFACE 37 17 20 22 + *MESH_CFACE 38 17 22 18 + *MESH_CFACE 39 18 22 19 + *MESH_CFACE 40 19 22 23 + *MESH_CFACE 41 19 23 12 + *MESH_CFACE 42 22 20 21 + *MESH_CFACE 43 22 21 23 + } + } + *PROP_MOTIONBLUR 0 + *PROP_CASTSHADOW 1 + *PROP_RECVSHADOW 1 + *MATERIAL_REF 0 + *MESH_ANIMATION { + *MESH { + *TIMEVALUE 0 + *MESH_NUMVERTEX 24 + *MESH_NUMFACES 44 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 -4.7153 -23.8849 -0.3323 + *MESH_VERTEX 1 4.7776 -23.8849 -0.3323 + *MESH_VERTEX 2 -4.7153 -22.3465 -1.5943 + *MESH_VERTEX 3 4.7776 -22.3465 -1.5943 + *MESH_VERTEX 4 -4.7153 -24.0885 -0.0147 + *MESH_VERTEX 5 -4.9945 -23.5694 -0.3323 + *MESH_VERTEX 6 -4.9945 -22.0310 -1.5942 + *MESH_VERTEX 7 -4.7153 -21.9659 -1.9097 + *MESH_VERTEX 8 4.7776 -21.9659 -1.9097 + *MESH_VERTEX 9 5.0568 -22.0310 -1.5943 + *MESH_VERTEX 10 5.0568 -23.5694 -0.3323 + *MESH_VERTEX 11 4.7776 -24.0885 -0.0147 + *MESH_VERTEX 12 -4.7153 1.3696 0.0001 + *MESH_VERTEX 13 -4.9945 1.3696 -0.3322 + *MESH_VERTEX 14 -4.9945 1.3696 -1.5942 + *MESH_VERTEX 15 -4.7153 1.3696 -1.9097 + *MESH_VERTEX 16 4.7776 1.3696 -1.9097 + *MESH_VERTEX 17 5.0568 1.3696 -1.5942 + *MESH_VERTEX 18 5.0568 1.3696 -0.3322 + *MESH_VERTEX 19 4.7776 1.3696 0.0001 + *MESH_VERTEX 20 4.7776 1.4947 -1.5943 + *MESH_VERTEX 21 -4.7153 1.4947 -1.5943 + *MESH_VERTEX 22 4.7776 1.4947 -0.3323 + *MESH_VERTEX 23 -4.7153 1.4947 -0.3323 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 1: A: 0 B: 3 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 2: A: 0 B: 4 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 3: A: 0 B: 5 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 6 C: 2 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 5: A: 2 B: 6 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 6: A: 2 B: 7 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 7: A: 2 B: 8 C: 3 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 8: A: 3 B: 8 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 9: A: 3 B: 9 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 10: A: 3 B: 10 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 11: A: 1 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 12: A: 1 B: 11 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 13: A: 1 B: 4 C: 0 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 14: A: 4 B: 12 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 15: A: 4 B: 13 C: 5 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 16: A: 5 B: 13 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 17: A: 5 B: 14 C: 6 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 18: A: 6 B: 14 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 19: A: 6 B: 15 C: 7 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 20: A: 7 B: 15 C: 16 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 21: A: 7 B: 16 C: 8 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 22: A: 8 B: 16 C: 17 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 23: A: 8 B: 17 C: 9 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 24: A: 9 B: 17 C: 18 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 25: A: 9 B: 18 C: 10 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 26: A: 10 B: 18 C: 19 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 27: A: 10 B: 19 C: 11 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 28: A: 11 B: 19 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 29: A: 11 B: 12 C: 4 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 30: A: 12 B: 23 C: 13 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 31: A: 13 B: 23 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 32: A: 13 B: 21 C: 14 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 33: A: 14 B: 21 C: 15 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 34: A: 15 B: 21 C: 20 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 35: A: 15 B: 20 C: 16 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 36: A: 16 B: 20 C: 17 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 37: A: 17 B: 20 C: 22 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 38: A: 17 B: 22 C: 18 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 39: A: 18 B: 22 C: 19 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 40: A: 19 B: 22 C: 23 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 41: A: 19 B: 23 C: 12 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 42: A: 22 B: 20 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 43: A: 22 B: 21 C: 23 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 24 + *MESH_CVERTLIST { + *MESH_VERTCOL 0 0.4236 0.4236 0.4236 + *MESH_VERTCOL 1 0.4202 0.4202 0.4202 + *MESH_VERTCOL 2 0.3837 0.3837 0.3837 + *MESH_VERTCOL 3 0.3717 0.3717 0.3717 + *MESH_VERTCOL 4 0.6691 0.6691 0.6691 + *MESH_VERTCOL 5 0.5788 0.5788 0.5788 + *MESH_VERTCOL 6 0.4225 0.4225 0.4225 + *MESH_VERTCOL 7 0.2765 0.2765 0.2765 + *MESH_VERTCOL 8 0.3049 0.3049 0.3049 + *MESH_VERTCOL 9 0.5108 0.5108 0.5108 + *MESH_VERTCOL 10 0.6195 0.6195 0.6195 + *MESH_VERTCOL 11 0.7210 0.7210 0.7210 + *MESH_VERTCOL 12 0.6054 0.6054 0.6054 + *MESH_VERTCOL 13 0.7167 0.7167 0.7167 + *MESH_VERTCOL 14 0.5792 0.5792 0.5792 + *MESH_VERTCOL 15 0.3464 0.3464 0.3464 + *MESH_VERTCOL 16 0.2693 0.2693 0.2693 + *MESH_VERTCOL 17 0.4903 0.4903 0.4903 + *MESH_VERTCOL 18 0.6958 0.6958 0.6958 + *MESH_VERTCOL 19 0.6274 0.6274 0.6274 + *MESH_VERTCOL 20 0.4361 0.4361 0.4361 + *MESH_VERTCOL 21 0.5644 0.5644 0.5644 + *MESH_VERTCOL 22 0.5445 0.5445 0.5445 + *MESH_VERTCOL 23 0.6008 0.6008 0.6008 + } + *MESH_NUMCVFACES 44 + *MESH_CFACELIST { + *MESH_CFACE 0 0 2 3 + *MESH_CFACE 1 0 3 1 + *MESH_CFACE 2 0 4 5 + *MESH_CFACE 3 0 5 6 + *MESH_CFACE 4 0 6 2 + *MESH_CFACE 5 2 6 7 + *MESH_CFACE 6 2 7 8 + *MESH_CFACE 7 2 8 3 + *MESH_CFACE 8 3 8 9 + *MESH_CFACE 9 3 9 10 + *MESH_CFACE 10 3 10 1 + *MESH_CFACE 11 1 10 11 + *MESH_CFACE 12 1 11 4 + *MESH_CFACE 13 1 4 0 + *MESH_CFACE 14 4 12 13 + *MESH_CFACE 15 4 13 5 + *MESH_CFACE 16 5 13 14 + *MESH_CFACE 17 5 14 6 + *MESH_CFACE 18 6 14 15 + *MESH_CFACE 19 6 15 7 + *MESH_CFACE 20 7 15 16 + *MESH_CFACE 21 7 16 8 + *MESH_CFACE 22 8 16 17 + *MESH_CFACE 23 8 17 9 + *MESH_CFACE 24 9 17 18 + *MESH_CFACE 25 9 18 10 + *MESH_CFACE 26 10 18 19 + *MESH_CFACE 27 10 19 11 + *MESH_CFACE 28 11 19 12 + *MESH_CFACE 29 11 12 4 + *MESH_CFACE 30 12 23 13 + *MESH_CFACE 31 13 23 21 + *MESH_CFACE 32 13 21 14 + *MESH_CFACE 33 14 21 15 + *MESH_CFACE 34 15 21 20 + *MESH_CFACE 35 15 20 16 + *MESH_CFACE 36 16 20 17 + *MESH_CFACE 37 17 20 22 + *MESH_CFACE 38 17 22 18 + *MESH_CFACE 39 18 22 19 + *MESH_CFACE 40 19 22 23 + *MESH_CFACE 41 19 23 12 + *MESH_CFACE 42 22 20 21 + *MESH_CFACE 43 22 21 23 + } + } + *MESH { + *TIMEVALUE 160 + *MESH_NUMVERTEX 24 + *MESH_NUMFACES 44 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 -4.7153 -23.7810 2.3211 + *MESH_VERTEX 1 4.7776 -23.7810 2.3211 + *MESH_VERTEX 2 -4.7153 -22.3829 0.9052 + *MESH_VERTEX 3 4.7776 -22.3829 0.9052 + *MESH_VERTEX 4 -4.7153 -23.9504 2.6582 + *MESH_VERTEX 5 -4.9945 -23.4673 2.2881 + *MESH_VERTEX 6 -4.9945 -22.0692 0.8722 + *MESH_VERTEX 7 -4.7153 -22.0374 0.5516 + *MESH_VERTEX 8 4.7776 -22.0374 0.5516 + *MESH_VERTEX 9 5.0568 -22.0692 0.8722 + *MESH_VERTEX 10 5.0568 -23.4673 2.2881 + *MESH_VERTEX 11 4.7776 -23.9503 2.6582 + *MESH_VERTEX 12 -4.7153 1.3698 0.0118 + *MESH_VERTEX 13 -4.9945 1.3351 -0.3187 + *MESH_VERTEX 14 -4.9945 1.2032 -1.5738 + *MESH_VERTEX 15 -4.7153 1.1702 -1.8875 + *MESH_VERTEX 16 4.7776 1.1702 -1.8875 + *MESH_VERTEX 17 5.0568 1.2032 -1.5738 + *MESH_VERTEX 18 5.0568 1.3351 -0.3187 + *MESH_VERTEX 19 4.7776 1.3698 0.0118 + *MESH_VERTEX 20 4.7776 1.3276 -1.5869 + *MESH_VERTEX 21 -4.7153 1.3276 -1.5869 + *MESH_VERTEX 22 4.7776 1.4595 -0.3318 + *MESH_VERTEX 23 -4.7153 1.4595 -0.3318 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 1: A: 0 B: 3 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 2: A: 0 B: 4 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 3: A: 0 B: 5 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 6 C: 2 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 5: A: 2 B: 6 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 6: A: 2 B: 7 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 7: A: 2 B: 8 C: 3 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 8: A: 3 B: 8 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 9: A: 3 B: 9 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 10: A: 3 B: 10 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 11: A: 1 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 12: A: 1 B: 11 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 13: A: 1 B: 4 C: 0 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 14: A: 4 B: 12 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 15: A: 4 B: 13 C: 5 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 16: A: 5 B: 13 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 17: A: 5 B: 14 C: 6 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 18: A: 6 B: 14 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 19: A: 6 B: 15 C: 7 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 20: A: 7 B: 15 C: 16 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 21: A: 7 B: 16 C: 8 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 22: A: 8 B: 16 C: 17 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 23: A: 8 B: 17 C: 9 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 24: A: 9 B: 17 C: 18 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 25: A: 9 B: 18 C: 10 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 26: A: 10 B: 18 C: 19 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 27: A: 10 B: 19 C: 11 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 28: A: 11 B: 19 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 29: A: 11 B: 12 C: 4 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 30: A: 12 B: 23 C: 13 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 31: A: 13 B: 23 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 32: A: 13 B: 21 C: 14 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 33: A: 14 B: 21 C: 15 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 34: A: 15 B: 21 C: 20 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 35: A: 15 B: 20 C: 16 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 36: A: 16 B: 20 C: 17 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 37: A: 17 B: 20 C: 22 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 38: A: 17 B: 22 C: 18 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 39: A: 18 B: 22 C: 19 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 40: A: 19 B: 22 C: 23 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 41: A: 19 B: 23 C: 12 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 42: A: 22 B: 20 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 43: A: 22 B: 21 C: 23 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 24 + *MESH_CVERTLIST { + *MESH_VERTCOL 0 0.4236 0.4236 0.4236 + *MESH_VERTCOL 1 0.4202 0.4202 0.4202 + *MESH_VERTCOL 2 0.3837 0.3837 0.3837 + *MESH_VERTCOL 3 0.3717 0.3717 0.3717 + *MESH_VERTCOL 4 0.6691 0.6691 0.6691 + *MESH_VERTCOL 5 0.5788 0.5788 0.5788 + *MESH_VERTCOL 6 0.4225 0.4225 0.4225 + *MESH_VERTCOL 7 0.2765 0.2765 0.2765 + *MESH_VERTCOL 8 0.3049 0.3049 0.3049 + *MESH_VERTCOL 9 0.5108 0.5108 0.5108 + *MESH_VERTCOL 10 0.6195 0.6195 0.6195 + *MESH_VERTCOL 11 0.7210 0.7210 0.7210 + *MESH_VERTCOL 12 0.6054 0.6054 0.6054 + *MESH_VERTCOL 13 0.7167 0.7167 0.7167 + *MESH_VERTCOL 14 0.5792 0.5792 0.5792 + *MESH_VERTCOL 15 0.3464 0.3464 0.3464 + *MESH_VERTCOL 16 0.2693 0.2693 0.2693 + *MESH_VERTCOL 17 0.4903 0.4903 0.4903 + *MESH_VERTCOL 18 0.6958 0.6958 0.6958 + *MESH_VERTCOL 19 0.6274 0.6274 0.6274 + *MESH_VERTCOL 20 0.4361 0.4361 0.4361 + *MESH_VERTCOL 21 0.5644 0.5644 0.5644 + *MESH_VERTCOL 22 0.5445 0.5445 0.5445 + *MESH_VERTCOL 23 0.6008 0.6008 0.6008 + } + *MESH_NUMCVFACES 44 + *MESH_CFACELIST { + *MESH_CFACE 0 0 2 3 + *MESH_CFACE 1 0 3 1 + *MESH_CFACE 2 0 4 5 + *MESH_CFACE 3 0 5 6 + *MESH_CFACE 4 0 6 2 + *MESH_CFACE 5 2 6 7 + *MESH_CFACE 6 2 7 8 + *MESH_CFACE 7 2 8 3 + *MESH_CFACE 8 3 8 9 + *MESH_CFACE 9 3 9 10 + *MESH_CFACE 10 3 10 1 + *MESH_CFACE 11 1 10 11 + *MESH_CFACE 12 1 11 4 + *MESH_CFACE 13 1 4 0 + *MESH_CFACE 14 4 12 13 + *MESH_CFACE 15 4 13 5 + *MESH_CFACE 16 5 13 14 + *MESH_CFACE 17 5 14 6 + *MESH_CFACE 18 6 14 15 + *MESH_CFACE 19 6 15 7 + *MESH_CFACE 20 7 15 16 + *MESH_CFACE 21 7 16 8 + *MESH_CFACE 22 8 16 17 + *MESH_CFACE 23 8 17 9 + *MESH_CFACE 24 9 17 18 + *MESH_CFACE 25 9 18 10 + *MESH_CFACE 26 10 18 19 + *MESH_CFACE 27 10 19 11 + *MESH_CFACE 28 11 19 12 + *MESH_CFACE 29 11 12 4 + *MESH_CFACE 30 12 23 13 + *MESH_CFACE 31 13 23 21 + *MESH_CFACE 32 13 21 14 + *MESH_CFACE 33 14 21 15 + *MESH_CFACE 34 15 21 20 + *MESH_CFACE 35 15 20 16 + *MESH_CFACE 36 16 20 17 + *MESH_CFACE 37 17 20 22 + *MESH_CFACE 38 17 22 18 + *MESH_CFACE 39 18 22 19 + *MESH_CFACE 40 19 22 23 + *MESH_CFACE 41 19 23 12 + *MESH_CFACE 42 22 20 21 + *MESH_CFACE 43 22 21 23 + } + } + *MESH { + *TIMEVALUE 320 + *MESH_NUMVERTEX 24 + *MESH_NUMFACES 44 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 -4.7153 -22.7471 7.5228 + *MESH_VERTEX 1 4.7776 -22.7471 7.5228 + *MESH_VERTEX 2 -4.7153 -21.6740 5.8471 + *MESH_VERTEX 3 4.7776 -21.6740 5.8471 + *MESH_VERTEX 4 -4.7153 -22.8427 7.8877 + *MESH_VERTEX 5 -4.9945 -22.4471 7.4253 + *MESH_VERTEX 6 -4.9945 -21.3739 5.7496 + *MESH_VERTEX 7 -4.7153 -21.4095 5.4295 + *MESH_VERTEX 8 4.7776 -21.4095 5.4295 + *MESH_VERTEX 9 5.0568 -21.3739 5.7496 + *MESH_VERTEX 10 5.0568 -22.4471 7.4253 + *MESH_VERTEX 11 4.7776 -22.8427 7.8877 + *MESH_VERTEX 12 -4.7153 1.3740 0.0348 + *MESH_VERTEX 13 -4.9945 1.2714 -0.2812 + *MESH_VERTEX 14 -4.9945 0.8814 -1.4815 + *MESH_VERTEX 15 -4.7153 0.7839 -1.7815 + *MESH_VERTEX 16 4.7776 0.7839 -1.7815 + *MESH_VERTEX 17 5.0568 0.8814 -1.4815 + *MESH_VERTEX 18 5.0568 1.2714 -0.2812 + *MESH_VERTEX 19 4.7776 1.3740 0.0348 + *MESH_VERTEX 20 4.7776 1.0003 -1.5202 + *MESH_VERTEX 21 -4.7153 1.0003 -1.5202 + *MESH_VERTEX 22 4.7776 1.3903 -0.3200 + *MESH_VERTEX 23 -4.7153 1.3903 -0.3200 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 1: A: 0 B: 3 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 2: A: 0 B: 4 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 3: A: 0 B: 5 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 6 C: 2 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 5: A: 2 B: 6 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 6: A: 2 B: 7 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 7: A: 2 B: 8 C: 3 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 8: A: 3 B: 8 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 9: A: 3 B: 9 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 10: A: 3 B: 10 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 11: A: 1 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 12: A: 1 B: 11 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 13: A: 1 B: 4 C: 0 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 14: A: 4 B: 12 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 15: A: 4 B: 13 C: 5 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 16: A: 5 B: 13 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 17: A: 5 B: 14 C: 6 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 18: A: 6 B: 14 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 19: A: 6 B: 15 C: 7 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 20: A: 7 B: 15 C: 16 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 21: A: 7 B: 16 C: 8 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 22: A: 8 B: 16 C: 17 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 23: A: 8 B: 17 C: 9 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 24: A: 9 B: 17 C: 18 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 25: A: 9 B: 18 C: 10 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 26: A: 10 B: 18 C: 19 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 27: A: 10 B: 19 C: 11 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 28: A: 11 B: 19 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 29: A: 11 B: 12 C: 4 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 30: A: 12 B: 23 C: 13 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 31: A: 13 B: 23 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 32: A: 13 B: 21 C: 14 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 33: A: 14 B: 21 C: 15 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 34: A: 15 B: 21 C: 20 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 35: A: 15 B: 20 C: 16 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 36: A: 16 B: 20 C: 17 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 37: A: 17 B: 20 C: 22 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 38: A: 17 B: 22 C: 18 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 39: A: 18 B: 22 C: 19 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 40: A: 19 B: 22 C: 23 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 41: A: 19 B: 23 C: 12 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 42: A: 22 B: 20 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 43: A: 22 B: 21 C: 23 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 24 + *MESH_CVERTLIST { + *MESH_VERTCOL 0 0.4236 0.4236 0.4236 + *MESH_VERTCOL 1 0.4202 0.4202 0.4202 + *MESH_VERTCOL 2 0.3837 0.3837 0.3837 + *MESH_VERTCOL 3 0.3717 0.3717 0.3717 + *MESH_VERTCOL 4 0.6691 0.6691 0.6691 + *MESH_VERTCOL 5 0.5788 0.5788 0.5788 + *MESH_VERTCOL 6 0.4225 0.4225 0.4225 + *MESH_VERTCOL 7 0.2765 0.2765 0.2765 + *MESH_VERTCOL 8 0.3049 0.3049 0.3049 + *MESH_VERTCOL 9 0.5108 0.5108 0.5108 + *MESH_VERTCOL 10 0.6195 0.6195 0.6195 + *MESH_VERTCOL 11 0.7210 0.7210 0.7210 + *MESH_VERTCOL 12 0.6054 0.6054 0.6054 + *MESH_VERTCOL 13 0.7167 0.7167 0.7167 + *MESH_VERTCOL 14 0.5792 0.5792 0.5792 + *MESH_VERTCOL 15 0.3464 0.3464 0.3464 + *MESH_VERTCOL 16 0.2693 0.2693 0.2693 + *MESH_VERTCOL 17 0.4903 0.4903 0.4903 + *MESH_VERTCOL 18 0.6958 0.6958 0.6958 + *MESH_VERTCOL 19 0.6274 0.6274 0.6274 + *MESH_VERTCOL 20 0.4361 0.4361 0.4361 + *MESH_VERTCOL 21 0.5644 0.5644 0.5644 + *MESH_VERTCOL 22 0.5445 0.5445 0.5445 + *MESH_VERTCOL 23 0.6008 0.6008 0.6008 + } + *MESH_NUMCVFACES 44 + *MESH_CFACELIST { + *MESH_CFACE 0 0 2 3 + *MESH_CFACE 1 0 3 1 + *MESH_CFACE 2 0 4 5 + *MESH_CFACE 3 0 5 6 + *MESH_CFACE 4 0 6 2 + *MESH_CFACE 5 2 6 7 + *MESH_CFACE 6 2 7 8 + *MESH_CFACE 7 2 8 3 + *MESH_CFACE 8 3 8 9 + *MESH_CFACE 9 3 9 10 + *MESH_CFACE 10 3 10 1 + *MESH_CFACE 11 1 10 11 + *MESH_CFACE 12 1 11 4 + *MESH_CFACE 13 1 4 0 + *MESH_CFACE 14 4 12 13 + *MESH_CFACE 15 4 13 5 + *MESH_CFACE 16 5 13 14 + *MESH_CFACE 17 5 14 6 + *MESH_CFACE 18 6 14 15 + *MESH_CFACE 19 6 15 7 + *MESH_CFACE 20 7 15 16 + *MESH_CFACE 21 7 16 8 + *MESH_CFACE 22 8 16 17 + *MESH_CFACE 23 8 17 9 + *MESH_CFACE 24 9 17 18 + *MESH_CFACE 25 9 18 10 + *MESH_CFACE 26 10 18 19 + *MESH_CFACE 27 10 19 11 + *MESH_CFACE 28 11 19 12 + *MESH_CFACE 29 11 12 4 + *MESH_CFACE 30 12 23 13 + *MESH_CFACE 31 13 23 21 + *MESH_CFACE 32 13 21 14 + *MESH_CFACE 33 14 21 15 + *MESH_CFACE 34 15 21 20 + *MESH_CFACE 35 15 20 16 + *MESH_CFACE 36 16 20 17 + *MESH_CFACE 37 17 20 22 + *MESH_CFACE 38 17 22 18 + *MESH_CFACE 39 18 22 19 + *MESH_CFACE 40 19 22 23 + *MESH_CFACE 41 19 23 12 + *MESH_CFACE 42 22 20 21 + *MESH_CFACE 43 22 21 23 + } + } + *MESH { + *TIMEVALUE 480 + *MESH_NUMVERTEX 24 + *MESH_NUMFACES 44 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 -4.7153 -19.9754 13.5373 + *MESH_VERTEX 1 4.7776 -19.9754 13.5373 + *MESH_VERTEX 2 -4.7153 -19.3725 11.6410 + *MESH_VERTEX 3 4.7776 -19.3725 11.6410 + *MESH_VERTEX 4 -4.7153 -19.9732 13.9146 + *MESH_VERTEX 5 -4.9945 -19.7108 13.3655 + *MESH_VERTEX 6 -4.9945 -19.1079 11.4692 + *MESH_VERTEX 7 -4.7153 -19.2252 11.1692 + *MESH_VERTEX 8 4.7776 -19.2252 11.1692 + *MESH_VERTEX 9 5.0568 -19.1079 11.4692 + *MESH_VERTEX 10 5.0568 -19.7108 13.3655 + *MESH_VERTEX 11 4.7776 -19.9732 13.9146 + *MESH_VERTEX 12 -4.7153 1.3858 0.0615 + *MESH_VERTEX 13 -4.9945 1.2049 -0.2172 + *MESH_VERTEX 14 -4.9945 0.5175 -1.2756 + *MESH_VERTEX 15 -4.7153 0.3457 -1.5402 + *MESH_VERTEX 16 4.7776 0.3457 -1.5402 + *MESH_VERTEX 17 5.0568 0.5175 -1.2756 + *MESH_VERTEX 18 5.0568 1.2049 -0.2172 + *MESH_VERTEX 19 4.7776 1.3858 0.0615 + *MESH_VERTEX 20 4.7776 0.6223 -1.3438 + *MESH_VERTEX 21 -4.7153 0.6223 -1.3438 + *MESH_VERTEX 22 4.7776 1.3097 -0.2854 + *MESH_VERTEX 23 -4.7153 1.3097 -0.2854 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 1: A: 0 B: 3 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 2: A: 0 B: 4 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 3: A: 0 B: 5 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 6 C: 2 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 5: A: 2 B: 6 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 6: A: 2 B: 7 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 7: A: 2 B: 8 C: 3 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 8: A: 3 B: 8 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 9: A: 3 B: 9 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 10: A: 3 B: 10 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 11: A: 1 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 12: A: 1 B: 11 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 13: A: 1 B: 4 C: 0 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 14: A: 4 B: 12 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 15: A: 4 B: 13 C: 5 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 16: A: 5 B: 13 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 17: A: 5 B: 14 C: 6 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 18: A: 6 B: 14 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 19: A: 6 B: 15 C: 7 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 20: A: 7 B: 15 C: 16 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 21: A: 7 B: 16 C: 8 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 22: A: 8 B: 16 C: 17 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 23: A: 8 B: 17 C: 9 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 24: A: 9 B: 17 C: 18 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 25: A: 9 B: 18 C: 10 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 26: A: 10 B: 18 C: 19 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 27: A: 10 B: 19 C: 11 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 28: A: 11 B: 19 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 29: A: 11 B: 12 C: 4 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 30: A: 12 B: 23 C: 13 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 31: A: 13 B: 23 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 32: A: 13 B: 21 C: 14 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 33: A: 14 B: 21 C: 15 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 34: A: 15 B: 21 C: 20 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 35: A: 15 B: 20 C: 16 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 36: A: 16 B: 20 C: 17 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 37: A: 17 B: 20 C: 22 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 38: A: 17 B: 22 C: 18 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 39: A: 18 B: 22 C: 19 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 40: A: 19 B: 22 C: 23 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 41: A: 19 B: 23 C: 12 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 42: A: 22 B: 20 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 43: A: 22 B: 21 C: 23 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 24 + *MESH_CVERTLIST { + *MESH_VERTCOL 0 0.4236 0.4236 0.4236 + *MESH_VERTCOL 1 0.4202 0.4202 0.4202 + *MESH_VERTCOL 2 0.3837 0.3837 0.3837 + *MESH_VERTCOL 3 0.3717 0.3717 0.3717 + *MESH_VERTCOL 4 0.6691 0.6691 0.6691 + *MESH_VERTCOL 5 0.5788 0.5788 0.5788 + *MESH_VERTCOL 6 0.4225 0.4225 0.4225 + *MESH_VERTCOL 7 0.2765 0.2765 0.2765 + *MESH_VERTCOL 8 0.3049 0.3049 0.3049 + *MESH_VERTCOL 9 0.5108 0.5108 0.5108 + *MESH_VERTCOL 10 0.6195 0.6195 0.6195 + *MESH_VERTCOL 11 0.7210 0.7210 0.7210 + *MESH_VERTCOL 12 0.6054 0.6054 0.6054 + *MESH_VERTCOL 13 0.7167 0.7167 0.7167 + *MESH_VERTCOL 14 0.5792 0.5792 0.5792 + *MESH_VERTCOL 15 0.3464 0.3464 0.3464 + *MESH_VERTCOL 16 0.2693 0.2693 0.2693 + *MESH_VERTCOL 17 0.4903 0.4903 0.4903 + *MESH_VERTCOL 18 0.6958 0.6958 0.6958 + *MESH_VERTCOL 19 0.6274 0.6274 0.6274 + *MESH_VERTCOL 20 0.4361 0.4361 0.4361 + *MESH_VERTCOL 21 0.5644 0.5644 0.5644 + *MESH_VERTCOL 22 0.5445 0.5445 0.5445 + *MESH_VERTCOL 23 0.6008 0.6008 0.6008 + } + *MESH_NUMCVFACES 44 + *MESH_CFACELIST { + *MESH_CFACE 0 0 2 3 + *MESH_CFACE 1 0 3 1 + *MESH_CFACE 2 0 4 5 + *MESH_CFACE 3 0 5 6 + *MESH_CFACE 4 0 6 2 + *MESH_CFACE 5 2 6 7 + *MESH_CFACE 6 2 7 8 + *MESH_CFACE 7 2 8 3 + *MESH_CFACE 8 3 8 9 + *MESH_CFACE 9 3 9 10 + *MESH_CFACE 10 3 10 1 + *MESH_CFACE 11 1 10 11 + *MESH_CFACE 12 1 11 4 + *MESH_CFACE 13 1 4 0 + *MESH_CFACE 14 4 12 13 + *MESH_CFACE 15 4 13 5 + *MESH_CFACE 16 5 13 14 + *MESH_CFACE 17 5 14 6 + *MESH_CFACE 18 6 14 15 + *MESH_CFACE 19 6 15 7 + *MESH_CFACE 20 7 15 16 + *MESH_CFACE 21 7 16 8 + *MESH_CFACE 22 8 16 17 + *MESH_CFACE 23 8 17 9 + *MESH_CFACE 24 9 17 18 + *MESH_CFACE 25 9 18 10 + *MESH_CFACE 26 10 18 19 + *MESH_CFACE 27 10 19 11 + *MESH_CFACE 28 11 19 12 + *MESH_CFACE 29 11 12 4 + *MESH_CFACE 30 12 23 13 + *MESH_CFACE 31 13 23 21 + *MESH_CFACE 32 13 21 14 + *MESH_CFACE 33 14 21 15 + *MESH_CFACE 34 15 21 20 + *MESH_CFACE 35 15 20 16 + *MESH_CFACE 36 16 20 17 + *MESH_CFACE 37 17 20 22 + *MESH_CFACE 38 17 22 18 + *MESH_CFACE 39 18 22 19 + *MESH_CFACE 40 19 22 23 + *MESH_CFACE 41 19 23 12 + *MESH_CFACE 42 22 20 21 + *MESH_CFACE 43 22 21 23 + } + } + *MESH { + *TIMEVALUE 640 + *MESH_NUMVERTEX 24 + *MESH_NUMFACES 44 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 -4.7153 -15.7415 18.6296 + *MESH_VERTEX 1 4.7776 -15.7415 18.6296 + *MESH_VERTEX 2 -4.7153 -15.6499 16.6418 + *MESH_VERTEX 3 4.7776 -15.6499 16.6418 + *MESH_VERTEX 4 -4.7153 -15.6417 18.9934 + *MESH_VERTEX 5 -4.9945 -15.5304 18.3951 + *MESH_VERTEX 6 -4.9945 -15.4388 16.4074 + *MESH_VERTEX 7 -4.7153 -15.6297 16.1479 + *MESH_VERTEX 8 4.7776 -15.6297 16.1479 + *MESH_VERTEX 9 5.0568 -15.4388 16.4074 + *MESH_VERTEX 10 5.0568 -15.5303 18.3951 + *MESH_VERTEX 11 4.7776 -15.6417 18.9934 + *MESH_VERTEX 12 -4.7153 1.4041 0.0842 + *MESH_VERTEX 13 -4.9945 1.1572 -0.1382 + *MESH_VERTEX 14 -4.9945 0.2193 -0.9826 + *MESH_VERTEX 15 -4.7153 -0.0151 -1.1937 + *MESH_VERTEX 16 4.7776 -0.0151 -1.1937 + *MESH_VERTEX 17 5.0568 0.2193 -0.9826 + *MESH_VERTEX 18 5.0568 1.1572 -0.1382 + *MESH_VERTEX 19 4.7776 1.4041 0.0842 + *MESH_VERTEX 20 4.7776 0.3029 -1.0756 + *MESH_VERTEX 21 -4.7153 0.3029 -1.0756 + *MESH_VERTEX 22 4.7776 1.2408 -0.2312 + *MESH_VERTEX 23 -4.7153 1.2408 -0.2312 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 1: A: 0 B: 3 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 2: A: 0 B: 4 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 3: A: 0 B: 5 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 6 C: 2 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 5: A: 2 B: 6 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 6: A: 2 B: 7 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 7: A: 2 B: 8 C: 3 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 8: A: 3 B: 8 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 9: A: 3 B: 9 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 10: A: 3 B: 10 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 11: A: 1 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 12: A: 1 B: 11 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 13: A: 1 B: 4 C: 0 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 14: A: 4 B: 12 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 15: A: 4 B: 13 C: 5 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 16: A: 5 B: 13 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 17: A: 5 B: 14 C: 6 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 18: A: 6 B: 14 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 19: A: 6 B: 15 C: 7 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 20: A: 7 B: 15 C: 16 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 21: A: 7 B: 16 C: 8 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 22: A: 8 B: 16 C: 17 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 23: A: 8 B: 17 C: 9 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 24: A: 9 B: 17 C: 18 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 25: A: 9 B: 18 C: 10 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 26: A: 10 B: 18 C: 19 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 27: A: 10 B: 19 C: 11 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 28: A: 11 B: 19 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 29: A: 11 B: 12 C: 4 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 30: A: 12 B: 23 C: 13 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 31: A: 13 B: 23 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 32: A: 13 B: 21 C: 14 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 33: A: 14 B: 21 C: 15 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 34: A: 15 B: 21 C: 20 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 35: A: 15 B: 20 C: 16 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 36: A: 16 B: 20 C: 17 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 37: A: 17 B: 20 C: 22 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 38: A: 17 B: 22 C: 18 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 39: A: 18 B: 22 C: 19 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 40: A: 19 B: 22 C: 23 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 41: A: 19 B: 23 C: 12 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 42: A: 22 B: 20 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 43: A: 22 B: 21 C: 23 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 24 + *MESH_CVERTLIST { + *MESH_VERTCOL 0 0.4236 0.4236 0.4236 + *MESH_VERTCOL 1 0.4202 0.4202 0.4202 + *MESH_VERTCOL 2 0.3837 0.3837 0.3837 + *MESH_VERTCOL 3 0.3717 0.3717 0.3717 + *MESH_VERTCOL 4 0.6691 0.6691 0.6691 + *MESH_VERTCOL 5 0.5788 0.5788 0.5788 + *MESH_VERTCOL 6 0.4225 0.4225 0.4225 + *MESH_VERTCOL 7 0.2765 0.2765 0.2765 + *MESH_VERTCOL 8 0.3049 0.3049 0.3049 + *MESH_VERTCOL 9 0.5108 0.5108 0.5108 + *MESH_VERTCOL 10 0.6195 0.6195 0.6195 + *MESH_VERTCOL 11 0.7210 0.7210 0.7210 + *MESH_VERTCOL 12 0.6054 0.6054 0.6054 + *MESH_VERTCOL 13 0.7167 0.7167 0.7167 + *MESH_VERTCOL 14 0.5792 0.5792 0.5792 + *MESH_VERTCOL 15 0.3464 0.3464 0.3464 + *MESH_VERTCOL 16 0.2693 0.2693 0.2693 + *MESH_VERTCOL 17 0.4903 0.4903 0.4903 + *MESH_VERTCOL 18 0.6958 0.6958 0.6958 + *MESH_VERTCOL 19 0.6274 0.6274 0.6274 + *MESH_VERTCOL 20 0.4361 0.4361 0.4361 + *MESH_VERTCOL 21 0.5644 0.5644 0.5644 + *MESH_VERTCOL 22 0.5445 0.5445 0.5445 + *MESH_VERTCOL 23 0.6008 0.6008 0.6008 + } + *MESH_NUMCVFACES 44 + *MESH_CFACELIST { + *MESH_CFACE 0 0 2 3 + *MESH_CFACE 1 0 3 1 + *MESH_CFACE 2 0 4 5 + *MESH_CFACE 3 0 5 6 + *MESH_CFACE 4 0 6 2 + *MESH_CFACE 5 2 6 7 + *MESH_CFACE 6 2 7 8 + *MESH_CFACE 7 2 8 3 + *MESH_CFACE 8 3 8 9 + *MESH_CFACE 9 3 9 10 + *MESH_CFACE 10 3 10 1 + *MESH_CFACE 11 1 10 11 + *MESH_CFACE 12 1 11 4 + *MESH_CFACE 13 1 4 0 + *MESH_CFACE 14 4 12 13 + *MESH_CFACE 15 4 13 5 + *MESH_CFACE 16 5 13 14 + *MESH_CFACE 17 5 14 6 + *MESH_CFACE 18 6 14 15 + *MESH_CFACE 19 6 15 7 + *MESH_CFACE 20 7 15 16 + *MESH_CFACE 21 7 16 8 + *MESH_CFACE 22 8 16 17 + *MESH_CFACE 23 8 17 9 + *MESH_CFACE 24 9 17 18 + *MESH_CFACE 25 9 18 10 + *MESH_CFACE 26 10 18 19 + *MESH_CFACE 27 10 19 11 + *MESH_CFACE 28 11 19 12 + *MESH_CFACE 29 11 12 4 + *MESH_CFACE 30 12 23 13 + *MESH_CFACE 31 13 23 21 + *MESH_CFACE 32 13 21 14 + *MESH_CFACE 33 14 21 15 + *MESH_CFACE 34 15 21 20 + *MESH_CFACE 35 15 20 16 + *MESH_CFACE 36 16 20 17 + *MESH_CFACE 37 17 20 22 + *MESH_CFACE 38 17 22 18 + *MESH_CFACE 39 18 22 19 + *MESH_CFACE 40 19 22 23 + *MESH_CFACE 41 19 23 12 + *MESH_CFACE 42 22 20 21 + *MESH_CFACE 43 22 21 23 + } + } + *MESH { + *TIMEVALUE 800 + *MESH_NUMVERTEX 24 + *MESH_NUMFACES 44 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 -4.7153 -10.3338 22.4525 + *MESH_VERTEX 1 4.7776 -10.3338 22.4525 + *MESH_VERTEX 2 -4.7153 -10.7598 20.5088 + *MESH_VERTEX 3 4.7776 -10.7598 20.5088 + *MESH_VERTEX 4 -4.7153 -10.1433 22.7781 + *MESH_VERTEX 5 -4.9945 -10.1906 22.1713 + *MESH_VERTEX 6 -4.9945 -10.6166 20.2276 + *MESH_VERTEX 7 -4.7153 -10.8682 20.0265 + *MESH_VERTEX 8 4.7776 -10.8682 20.0265 + *MESH_VERTEX 9 5.0568 -10.6166 20.2276 + *MESH_VERTEX 10 5.0568 -10.1906 22.1713 + *MESH_VERTEX 11 4.7776 -10.1433 22.7781 + *MESH_VERTEX 12 -4.7153 1.4276 0.1014 + *MESH_VERTEX 13 -4.9945 1.1316 -0.0495 + *MESH_VERTEX 14 -4.9945 0.0071 -0.6224 + *MESH_VERTEX 15 -4.7153 -0.2740 -0.7656 + *MESH_VERTEX 16 4.7776 -0.2740 -0.7656 + *MESH_VERTEX 17 5.0568 0.0071 -0.6224 + *MESH_VERTEX 18 5.0568 1.1316 -0.0494 + *MESH_VERTEX 19 4.7776 1.4276 0.1014 + *MESH_VERTEX 20 4.7776 0.0638 -0.7338 + *MESH_VERTEX 21 -4.7153 0.0638 -0.7338 + *MESH_VERTEX 22 4.7776 1.1883 -0.1609 + *MESH_VERTEX 23 -4.7153 1.1883 -0.1609 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 1: A: 0 B: 3 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 2: A: 0 B: 4 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 3: A: 0 B: 5 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 6 C: 2 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 5: A: 2 B: 6 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 6: A: 2 B: 7 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 7: A: 2 B: 8 C: 3 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 8: A: 3 B: 8 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 9: A: 3 B: 9 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 10: A: 3 B: 10 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 11: A: 1 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 12: A: 1 B: 11 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 13: A: 1 B: 4 C: 0 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 14: A: 4 B: 12 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 15: A: 4 B: 13 C: 5 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 16: A: 5 B: 13 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 17: A: 5 B: 14 C: 6 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 18: A: 6 B: 14 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 19: A: 6 B: 15 C: 7 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 20: A: 7 B: 15 C: 16 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 21: A: 7 B: 16 C: 8 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 22: A: 8 B: 16 C: 17 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 23: A: 8 B: 17 C: 9 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 24: A: 9 B: 17 C: 18 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 25: A: 9 B: 18 C: 10 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 26: A: 10 B: 18 C: 19 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 27: A: 10 B: 19 C: 11 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 28: A: 11 B: 19 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 29: A: 11 B: 12 C: 4 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 30: A: 12 B: 23 C: 13 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 31: A: 13 B: 23 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 32: A: 13 B: 21 C: 14 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 33: A: 14 B: 21 C: 15 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 34: A: 15 B: 21 C: 20 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 35: A: 15 B: 20 C: 16 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 36: A: 16 B: 20 C: 17 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 37: A: 17 B: 20 C: 22 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 38: A: 17 B: 22 C: 18 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 39: A: 18 B: 22 C: 19 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 40: A: 19 B: 22 C: 23 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 41: A: 19 B: 23 C: 12 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 42: A: 22 B: 20 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 43: A: 22 B: 21 C: 23 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 24 + *MESH_CVERTLIST { + *MESH_VERTCOL 0 0.4236 0.4236 0.4236 + *MESH_VERTCOL 1 0.4202 0.4202 0.4202 + *MESH_VERTCOL 2 0.3837 0.3837 0.3837 + *MESH_VERTCOL 3 0.3717 0.3717 0.3717 + *MESH_VERTCOL 4 0.6691 0.6691 0.6691 + *MESH_VERTCOL 5 0.5788 0.5788 0.5788 + *MESH_VERTCOL 6 0.4225 0.4225 0.4225 + *MESH_VERTCOL 7 0.2765 0.2765 0.2765 + *MESH_VERTCOL 8 0.3049 0.3049 0.3049 + *MESH_VERTCOL 9 0.5108 0.5108 0.5108 + *MESH_VERTCOL 10 0.6195 0.6195 0.6195 + *MESH_VERTCOL 11 0.7210 0.7210 0.7210 + *MESH_VERTCOL 12 0.6054 0.6054 0.6054 + *MESH_VERTCOL 13 0.7167 0.7167 0.7167 + *MESH_VERTCOL 14 0.5792 0.5792 0.5792 + *MESH_VERTCOL 15 0.3464 0.3464 0.3464 + *MESH_VERTCOL 16 0.2693 0.2693 0.2693 + *MESH_VERTCOL 17 0.4903 0.4903 0.4903 + *MESH_VERTCOL 18 0.6958 0.6958 0.6958 + *MESH_VERTCOL 19 0.6274 0.6274 0.6274 + *MESH_VERTCOL 20 0.4361 0.4361 0.4361 + *MESH_VERTCOL 21 0.5644 0.5644 0.5644 + *MESH_VERTCOL 22 0.5445 0.5445 0.5445 + *MESH_VERTCOL 23 0.6008 0.6008 0.6008 + } + *MESH_NUMCVFACES 44 + *MESH_CFACELIST { + *MESH_CFACE 0 0 2 3 + *MESH_CFACE 1 0 3 1 + *MESH_CFACE 2 0 4 5 + *MESH_CFACE 3 0 5 6 + *MESH_CFACE 4 0 6 2 + *MESH_CFACE 5 2 6 7 + *MESH_CFACE 6 2 7 8 + *MESH_CFACE 7 2 8 3 + *MESH_CFACE 8 3 8 9 + *MESH_CFACE 9 3 9 10 + *MESH_CFACE 10 3 10 1 + *MESH_CFACE 11 1 10 11 + *MESH_CFACE 12 1 11 4 + *MESH_CFACE 13 1 4 0 + *MESH_CFACE 14 4 12 13 + *MESH_CFACE 15 4 13 5 + *MESH_CFACE 16 5 13 14 + *MESH_CFACE 17 5 14 6 + *MESH_CFACE 18 6 14 15 + *MESH_CFACE 19 6 15 7 + *MESH_CFACE 20 7 15 16 + *MESH_CFACE 21 7 16 8 + *MESH_CFACE 22 8 16 17 + *MESH_CFACE 23 8 17 9 + *MESH_CFACE 24 9 17 18 + *MESH_CFACE 25 9 18 10 + *MESH_CFACE 26 10 18 19 + *MESH_CFACE 27 10 19 11 + *MESH_CFACE 28 11 19 12 + *MESH_CFACE 29 11 12 4 + *MESH_CFACE 30 12 23 13 + *MESH_CFACE 31 13 23 21 + *MESH_CFACE 32 13 21 14 + *MESH_CFACE 33 14 21 15 + *MESH_CFACE 34 15 21 20 + *MESH_CFACE 35 15 20 16 + *MESH_CFACE 36 16 20 17 + *MESH_CFACE 37 17 20 22 + *MESH_CFACE 38 17 22 18 + *MESH_CFACE 39 18 22 19 + *MESH_CFACE 40 19 22 23 + *MESH_CFACE 41 19 23 12 + *MESH_CFACE 42 22 20 21 + *MESH_CFACE 43 22 21 23 + } + } + *MESH { + *TIMEVALUE 960 + *MESH_NUMVERTEX 24 + *MESH_NUMFACES 44 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 -4.7153 -4.1210 24.7455 + *MESH_VERTEX 1 4.7776 -4.1210 24.7455 + *MESH_VERTEX 2 -4.7153 -5.0355 22.9783 + *MESH_VERTEX 3 4.7776 -5.0355 22.9783 + *MESH_VERTEX 4 -4.7153 -3.8527 25.0107 + *MESH_VERTEX 5 -4.9945 -4.0554 24.4369 + *MESH_VERTEX 6 -4.9945 -4.9699 22.6697 + *MESH_VERTEX 7 -4.7153 -5.2650 22.5405 + *MESH_VERTEX 8 4.7776 -5.2650 22.5405 + *MESH_VERTEX 9 5.0568 -4.9700 22.6697 + *MESH_VERTEX 10 5.0568 -4.0554 24.4369 + *MESH_VERTEX 11 4.7776 -3.8527 25.0107 + *MESH_VERTEX 12 -4.7153 1.4548 0.1120 + *MESH_VERTEX 13 -4.9945 1.1298 0.0429 + *MESH_VERTEX 14 -4.9945 -0.1046 -0.2195 + *MESH_VERTEX 15 -4.7153 -0.4132 -0.2851 + *MESH_VERTEX 16 4.7776 -0.4132 -0.2851 + *MESH_VERTEX 17 5.0568 -0.1046 -0.2195 + *MESH_VERTEX 18 5.0568 1.1298 0.0429 + *MESH_VERTEX 19 4.7776 1.4548 0.1120 + *MESH_VERTEX 20 4.7776 -0.0787 -0.3419 + *MESH_VERTEX 21 -4.7153 -0.0787 -0.3419 + *MESH_VERTEX 22 4.7776 1.1557 -0.0795 + *MESH_VERTEX 23 -4.7153 1.1557 -0.0795 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 1: A: 0 B: 3 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 2: A: 0 B: 4 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 3: A: 0 B: 5 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 6 C: 2 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 5: A: 2 B: 6 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 6: A: 2 B: 7 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 7: A: 2 B: 8 C: 3 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 8: A: 3 B: 8 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 9: A: 3 B: 9 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 10: A: 3 B: 10 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 11: A: 1 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 12: A: 1 B: 11 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 13: A: 1 B: 4 C: 0 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 14: A: 4 B: 12 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 15: A: 4 B: 13 C: 5 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 16: A: 5 B: 13 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 17: A: 5 B: 14 C: 6 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 18: A: 6 B: 14 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 19: A: 6 B: 15 C: 7 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 20: A: 7 B: 15 C: 16 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 21: A: 7 B: 16 C: 8 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 22: A: 8 B: 16 C: 17 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 23: A: 8 B: 17 C: 9 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 24: A: 9 B: 17 C: 18 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 25: A: 9 B: 18 C: 10 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 26: A: 10 B: 18 C: 19 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 27: A: 10 B: 19 C: 11 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 28: A: 11 B: 19 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 29: A: 11 B: 12 C: 4 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 30: A: 12 B: 23 C: 13 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 31: A: 13 B: 23 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 32: A: 13 B: 21 C: 14 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 33: A: 14 B: 21 C: 15 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 34: A: 15 B: 21 C: 20 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 35: A: 15 B: 20 C: 16 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 36: A: 16 B: 20 C: 17 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 37: A: 17 B: 20 C: 22 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 38: A: 17 B: 22 C: 18 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 39: A: 18 B: 22 C: 19 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 40: A: 19 B: 22 C: 23 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 41: A: 19 B: 23 C: 12 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 42: A: 22 B: 20 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 43: A: 22 B: 21 C: 23 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 24 + *MESH_CVERTLIST { + *MESH_VERTCOL 0 0.4236 0.4236 0.4236 + *MESH_VERTCOL 1 0.4202 0.4202 0.4202 + *MESH_VERTCOL 2 0.3837 0.3837 0.3837 + *MESH_VERTCOL 3 0.3717 0.3717 0.3717 + *MESH_VERTCOL 4 0.6691 0.6691 0.6691 + *MESH_VERTCOL 5 0.5788 0.5788 0.5788 + *MESH_VERTCOL 6 0.4225 0.4225 0.4225 + *MESH_VERTCOL 7 0.2765 0.2765 0.2765 + *MESH_VERTCOL 8 0.3049 0.3049 0.3049 + *MESH_VERTCOL 9 0.5108 0.5108 0.5108 + *MESH_VERTCOL 10 0.6195 0.6195 0.6195 + *MESH_VERTCOL 11 0.7210 0.7210 0.7210 + *MESH_VERTCOL 12 0.6054 0.6054 0.6054 + *MESH_VERTCOL 13 0.7167 0.7167 0.7167 + *MESH_VERTCOL 14 0.5792 0.5792 0.5792 + *MESH_VERTCOL 15 0.3464 0.3464 0.3464 + *MESH_VERTCOL 16 0.2693 0.2693 0.2693 + *MESH_VERTCOL 17 0.4903 0.4903 0.4903 + *MESH_VERTCOL 18 0.6958 0.6958 0.6958 + *MESH_VERTCOL 19 0.6274 0.6274 0.6274 + *MESH_VERTCOL 20 0.4361 0.4361 0.4361 + *MESH_VERTCOL 21 0.5644 0.5644 0.5644 + *MESH_VERTCOL 22 0.5445 0.5445 0.5445 + *MESH_VERTCOL 23 0.6008 0.6008 0.6008 + } + *MESH_NUMCVFACES 44 + *MESH_CFACELIST { + *MESH_CFACE 0 0 2 3 + *MESH_CFACE 1 0 3 1 + *MESH_CFACE 2 0 4 5 + *MESH_CFACE 3 0 5 6 + *MESH_CFACE 4 0 6 2 + *MESH_CFACE 5 2 6 7 + *MESH_CFACE 6 2 7 8 + *MESH_CFACE 7 2 8 3 + *MESH_CFACE 8 3 8 9 + *MESH_CFACE 9 3 9 10 + *MESH_CFACE 10 3 10 1 + *MESH_CFACE 11 1 10 11 + *MESH_CFACE 12 1 11 4 + *MESH_CFACE 13 1 4 0 + *MESH_CFACE 14 4 12 13 + *MESH_CFACE 15 4 13 5 + *MESH_CFACE 16 5 13 14 + *MESH_CFACE 17 5 14 6 + *MESH_CFACE 18 6 14 15 + *MESH_CFACE 19 6 15 7 + *MESH_CFACE 20 7 15 16 + *MESH_CFACE 21 7 16 8 + *MESH_CFACE 22 8 16 17 + *MESH_CFACE 23 8 17 9 + *MESH_CFACE 24 9 17 18 + *MESH_CFACE 25 9 18 10 + *MESH_CFACE 26 10 18 19 + *MESH_CFACE 27 10 19 11 + *MESH_CFACE 28 11 19 12 + *MESH_CFACE 29 11 12 4 + *MESH_CFACE 30 12 23 13 + *MESH_CFACE 31 13 23 21 + *MESH_CFACE 32 13 21 14 + *MESH_CFACE 33 14 21 15 + *MESH_CFACE 34 15 21 20 + *MESH_CFACE 35 15 20 16 + *MESH_CFACE 36 16 20 17 + *MESH_CFACE 37 17 20 22 + *MESH_CFACE 38 17 22 18 + *MESH_CFACE 39 18 22 19 + *MESH_CFACE 40 19 22 23 + *MESH_CFACE 41 19 23 12 + *MESH_CFACE 42 22 20 21 + *MESH_CFACE 43 22 21 23 + } + } + *MESH { + *TIMEVALUE 1120 + *MESH_NUMVERTEX 24 + *MESH_NUMFACES 44 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 -4.7153 -10.3338 22.4525 + *MESH_VERTEX 1 4.7776 -10.3338 22.4525 + *MESH_VERTEX 2 -4.7153 -10.7598 20.5088 + *MESH_VERTEX 3 4.7776 -10.7598 20.5088 + *MESH_VERTEX 4 -4.7153 -10.1433 22.7781 + *MESH_VERTEX 5 -4.9945 -10.1906 22.1713 + *MESH_VERTEX 6 -4.9945 -10.6166 20.2276 + *MESH_VERTEX 7 -4.7153 -10.8682 20.0265 + *MESH_VERTEX 8 4.7776 -10.8682 20.0265 + *MESH_VERTEX 9 5.0568 -10.6166 20.2276 + *MESH_VERTEX 10 5.0568 -10.1906 22.1713 + *MESH_VERTEX 11 4.7776 -10.1433 22.7781 + *MESH_VERTEX 12 -4.7153 1.4276 0.1014 + *MESH_VERTEX 13 -4.9945 1.1316 -0.0495 + *MESH_VERTEX 14 -4.9945 0.0071 -0.6224 + *MESH_VERTEX 15 -4.7153 -0.2740 -0.7656 + *MESH_VERTEX 16 4.7776 -0.2740 -0.7656 + *MESH_VERTEX 17 5.0568 0.0071 -0.6224 + *MESH_VERTEX 18 5.0568 1.1316 -0.0494 + *MESH_VERTEX 19 4.7776 1.4276 0.1014 + *MESH_VERTEX 20 4.7776 0.0638 -0.7338 + *MESH_VERTEX 21 -4.7153 0.0638 -0.7338 + *MESH_VERTEX 22 4.7776 1.1883 -0.1609 + *MESH_VERTEX 23 -4.7153 1.1883 -0.1609 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 1: A: 0 B: 3 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 2: A: 0 B: 4 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 3: A: 0 B: 5 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 6 C: 2 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 5: A: 2 B: 6 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 6: A: 2 B: 7 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 7: A: 2 B: 8 C: 3 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 8: A: 3 B: 8 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 9: A: 3 B: 9 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 10: A: 3 B: 10 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 11: A: 1 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 12: A: 1 B: 11 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 13: A: 1 B: 4 C: 0 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 14: A: 4 B: 12 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 15: A: 4 B: 13 C: 5 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 16: A: 5 B: 13 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 17: A: 5 B: 14 C: 6 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 18: A: 6 B: 14 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 19: A: 6 B: 15 C: 7 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 20: A: 7 B: 15 C: 16 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 21: A: 7 B: 16 C: 8 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 22: A: 8 B: 16 C: 17 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 23: A: 8 B: 17 C: 9 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 24: A: 9 B: 17 C: 18 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 25: A: 9 B: 18 C: 10 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 26: A: 10 B: 18 C: 19 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 27: A: 10 B: 19 C: 11 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 28: A: 11 B: 19 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 29: A: 11 B: 12 C: 4 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 30: A: 12 B: 23 C: 13 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 31: A: 13 B: 23 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 32: A: 13 B: 21 C: 14 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 33: A: 14 B: 21 C: 15 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 34: A: 15 B: 21 C: 20 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 35: A: 15 B: 20 C: 16 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 36: A: 16 B: 20 C: 17 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 37: A: 17 B: 20 C: 22 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 38: A: 17 B: 22 C: 18 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 39: A: 18 B: 22 C: 19 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 40: A: 19 B: 22 C: 23 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 41: A: 19 B: 23 C: 12 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 42: A: 22 B: 20 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 43: A: 22 B: 21 C: 23 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 24 + *MESH_CVERTLIST { + *MESH_VERTCOL 0 0.4236 0.4236 0.4236 + *MESH_VERTCOL 1 0.4202 0.4202 0.4202 + *MESH_VERTCOL 2 0.3837 0.3837 0.3837 + *MESH_VERTCOL 3 0.3717 0.3717 0.3717 + *MESH_VERTCOL 4 0.6691 0.6691 0.6691 + *MESH_VERTCOL 5 0.5788 0.5788 0.5788 + *MESH_VERTCOL 6 0.4225 0.4225 0.4225 + *MESH_VERTCOL 7 0.2765 0.2765 0.2765 + *MESH_VERTCOL 8 0.3049 0.3049 0.3049 + *MESH_VERTCOL 9 0.5108 0.5108 0.5108 + *MESH_VERTCOL 10 0.6195 0.6195 0.6195 + *MESH_VERTCOL 11 0.7210 0.7210 0.7210 + *MESH_VERTCOL 12 0.6054 0.6054 0.6054 + *MESH_VERTCOL 13 0.7167 0.7167 0.7167 + *MESH_VERTCOL 14 0.5792 0.5792 0.5792 + *MESH_VERTCOL 15 0.3464 0.3464 0.3464 + *MESH_VERTCOL 16 0.2693 0.2693 0.2693 + *MESH_VERTCOL 17 0.4903 0.4903 0.4903 + *MESH_VERTCOL 18 0.6958 0.6958 0.6958 + *MESH_VERTCOL 19 0.6274 0.6274 0.6274 + *MESH_VERTCOL 20 0.4361 0.4361 0.4361 + *MESH_VERTCOL 21 0.5644 0.5644 0.5644 + *MESH_VERTCOL 22 0.5445 0.5445 0.5445 + *MESH_VERTCOL 23 0.6008 0.6008 0.6008 + } + *MESH_NUMCVFACES 44 + *MESH_CFACELIST { + *MESH_CFACE 0 0 2 3 + *MESH_CFACE 1 0 3 1 + *MESH_CFACE 2 0 4 5 + *MESH_CFACE 3 0 5 6 + *MESH_CFACE 4 0 6 2 + *MESH_CFACE 5 2 6 7 + *MESH_CFACE 6 2 7 8 + *MESH_CFACE 7 2 8 3 + *MESH_CFACE 8 3 8 9 + *MESH_CFACE 9 3 9 10 + *MESH_CFACE 10 3 10 1 + *MESH_CFACE 11 1 10 11 + *MESH_CFACE 12 1 11 4 + *MESH_CFACE 13 1 4 0 + *MESH_CFACE 14 4 12 13 + *MESH_CFACE 15 4 13 5 + *MESH_CFACE 16 5 13 14 + *MESH_CFACE 17 5 14 6 + *MESH_CFACE 18 6 14 15 + *MESH_CFACE 19 6 15 7 + *MESH_CFACE 20 7 15 16 + *MESH_CFACE 21 7 16 8 + *MESH_CFACE 22 8 16 17 + *MESH_CFACE 23 8 17 9 + *MESH_CFACE 24 9 17 18 + *MESH_CFACE 25 9 18 10 + *MESH_CFACE 26 10 18 19 + *MESH_CFACE 27 10 19 11 + *MESH_CFACE 28 11 19 12 + *MESH_CFACE 29 11 12 4 + *MESH_CFACE 30 12 23 13 + *MESH_CFACE 31 13 23 21 + *MESH_CFACE 32 13 21 14 + *MESH_CFACE 33 14 21 15 + *MESH_CFACE 34 15 21 20 + *MESH_CFACE 35 15 20 16 + *MESH_CFACE 36 16 20 17 + *MESH_CFACE 37 17 20 22 + *MESH_CFACE 38 17 22 18 + *MESH_CFACE 39 18 22 19 + *MESH_CFACE 40 19 22 23 + *MESH_CFACE 41 19 23 12 + *MESH_CFACE 42 22 20 21 + *MESH_CFACE 43 22 21 23 + } + } + *MESH { + *TIMEVALUE 1280 + *MESH_NUMVERTEX 24 + *MESH_NUMFACES 44 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 -4.7153 -15.7415 18.6296 + *MESH_VERTEX 1 4.7776 -15.7415 18.6296 + *MESH_VERTEX 2 -4.7153 -15.6499 16.6418 + *MESH_VERTEX 3 4.7776 -15.6499 16.6418 + *MESH_VERTEX 4 -4.7153 -15.6417 18.9934 + *MESH_VERTEX 5 -4.9945 -15.5304 18.3951 + *MESH_VERTEX 6 -4.9945 -15.4388 16.4074 + *MESH_VERTEX 7 -4.7153 -15.6297 16.1479 + *MESH_VERTEX 8 4.7776 -15.6297 16.1479 + *MESH_VERTEX 9 5.0568 -15.4388 16.4074 + *MESH_VERTEX 10 5.0568 -15.5303 18.3951 + *MESH_VERTEX 11 4.7776 -15.6417 18.9934 + *MESH_VERTEX 12 -4.7153 1.4041 0.0842 + *MESH_VERTEX 13 -4.9945 1.1572 -0.1382 + *MESH_VERTEX 14 -4.9945 0.2193 -0.9826 + *MESH_VERTEX 15 -4.7153 -0.0151 -1.1937 + *MESH_VERTEX 16 4.7776 -0.0151 -1.1937 + *MESH_VERTEX 17 5.0568 0.2193 -0.9826 + *MESH_VERTEX 18 5.0568 1.1572 -0.1382 + *MESH_VERTEX 19 4.7776 1.4041 0.0842 + *MESH_VERTEX 20 4.7776 0.3029 -1.0756 + *MESH_VERTEX 21 -4.7153 0.3029 -1.0756 + *MESH_VERTEX 22 4.7776 1.2408 -0.2312 + *MESH_VERTEX 23 -4.7153 1.2408 -0.2312 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 1: A: 0 B: 3 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 2: A: 0 B: 4 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 3: A: 0 B: 5 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 6 C: 2 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 5: A: 2 B: 6 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 6: A: 2 B: 7 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 7: A: 2 B: 8 C: 3 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 8: A: 3 B: 8 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 9: A: 3 B: 9 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 10: A: 3 B: 10 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 11: A: 1 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 12: A: 1 B: 11 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 13: A: 1 B: 4 C: 0 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 14: A: 4 B: 12 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 15: A: 4 B: 13 C: 5 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 16: A: 5 B: 13 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 17: A: 5 B: 14 C: 6 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 18: A: 6 B: 14 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 19: A: 6 B: 15 C: 7 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 20: A: 7 B: 15 C: 16 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 21: A: 7 B: 16 C: 8 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 22: A: 8 B: 16 C: 17 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 23: A: 8 B: 17 C: 9 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 24: A: 9 B: 17 C: 18 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 25: A: 9 B: 18 C: 10 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 26: A: 10 B: 18 C: 19 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 27: A: 10 B: 19 C: 11 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 28: A: 11 B: 19 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 29: A: 11 B: 12 C: 4 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 30: A: 12 B: 23 C: 13 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 31: A: 13 B: 23 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 32: A: 13 B: 21 C: 14 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 33: A: 14 B: 21 C: 15 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 34: A: 15 B: 21 C: 20 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 35: A: 15 B: 20 C: 16 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 36: A: 16 B: 20 C: 17 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 37: A: 17 B: 20 C: 22 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 38: A: 17 B: 22 C: 18 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 39: A: 18 B: 22 C: 19 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 40: A: 19 B: 22 C: 23 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 41: A: 19 B: 23 C: 12 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 42: A: 22 B: 20 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 43: A: 22 B: 21 C: 23 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 24 + *MESH_CVERTLIST { + *MESH_VERTCOL 0 0.4236 0.4236 0.4236 + *MESH_VERTCOL 1 0.4202 0.4202 0.4202 + *MESH_VERTCOL 2 0.3837 0.3837 0.3837 + *MESH_VERTCOL 3 0.3717 0.3717 0.3717 + *MESH_VERTCOL 4 0.6691 0.6691 0.6691 + *MESH_VERTCOL 5 0.5788 0.5788 0.5788 + *MESH_VERTCOL 6 0.4225 0.4225 0.4225 + *MESH_VERTCOL 7 0.2765 0.2765 0.2765 + *MESH_VERTCOL 8 0.3049 0.3049 0.3049 + *MESH_VERTCOL 9 0.5108 0.5108 0.5108 + *MESH_VERTCOL 10 0.6195 0.6195 0.6195 + *MESH_VERTCOL 11 0.7210 0.7210 0.7210 + *MESH_VERTCOL 12 0.6054 0.6054 0.6054 + *MESH_VERTCOL 13 0.7167 0.7167 0.7167 + *MESH_VERTCOL 14 0.5792 0.5792 0.5792 + *MESH_VERTCOL 15 0.3464 0.3464 0.3464 + *MESH_VERTCOL 16 0.2693 0.2693 0.2693 + *MESH_VERTCOL 17 0.4903 0.4903 0.4903 + *MESH_VERTCOL 18 0.6958 0.6958 0.6958 + *MESH_VERTCOL 19 0.6274 0.6274 0.6274 + *MESH_VERTCOL 20 0.4361 0.4361 0.4361 + *MESH_VERTCOL 21 0.5644 0.5644 0.5644 + *MESH_VERTCOL 22 0.5445 0.5445 0.5445 + *MESH_VERTCOL 23 0.6008 0.6008 0.6008 + } + *MESH_NUMCVFACES 44 + *MESH_CFACELIST { + *MESH_CFACE 0 0 2 3 + *MESH_CFACE 1 0 3 1 + *MESH_CFACE 2 0 4 5 + *MESH_CFACE 3 0 5 6 + *MESH_CFACE 4 0 6 2 + *MESH_CFACE 5 2 6 7 + *MESH_CFACE 6 2 7 8 + *MESH_CFACE 7 2 8 3 + *MESH_CFACE 8 3 8 9 + *MESH_CFACE 9 3 9 10 + *MESH_CFACE 10 3 10 1 + *MESH_CFACE 11 1 10 11 + *MESH_CFACE 12 1 11 4 + *MESH_CFACE 13 1 4 0 + *MESH_CFACE 14 4 12 13 + *MESH_CFACE 15 4 13 5 + *MESH_CFACE 16 5 13 14 + *MESH_CFACE 17 5 14 6 + *MESH_CFACE 18 6 14 15 + *MESH_CFACE 19 6 15 7 + *MESH_CFACE 20 7 15 16 + *MESH_CFACE 21 7 16 8 + *MESH_CFACE 22 8 16 17 + *MESH_CFACE 23 8 17 9 + *MESH_CFACE 24 9 17 18 + *MESH_CFACE 25 9 18 10 + *MESH_CFACE 26 10 18 19 + *MESH_CFACE 27 10 19 11 + *MESH_CFACE 28 11 19 12 + *MESH_CFACE 29 11 12 4 + *MESH_CFACE 30 12 23 13 + *MESH_CFACE 31 13 23 21 + *MESH_CFACE 32 13 21 14 + *MESH_CFACE 33 14 21 15 + *MESH_CFACE 34 15 21 20 + *MESH_CFACE 35 15 20 16 + *MESH_CFACE 36 16 20 17 + *MESH_CFACE 37 17 20 22 + *MESH_CFACE 38 17 22 18 + *MESH_CFACE 39 18 22 19 + *MESH_CFACE 40 19 22 23 + *MESH_CFACE 41 19 23 12 + *MESH_CFACE 42 22 20 21 + *MESH_CFACE 43 22 21 23 + } + } + *MESH { + *TIMEVALUE 1440 + *MESH_NUMVERTEX 24 + *MESH_NUMFACES 44 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 -4.7153 -19.9754 13.5373 + *MESH_VERTEX 1 4.7776 -19.9754 13.5373 + *MESH_VERTEX 2 -4.7153 -19.3725 11.6410 + *MESH_VERTEX 3 4.7776 -19.3725 11.6410 + *MESH_VERTEX 4 -4.7153 -19.9732 13.9146 + *MESH_VERTEX 5 -4.9945 -19.7108 13.3655 + *MESH_VERTEX 6 -4.9945 -19.1079 11.4692 + *MESH_VERTEX 7 -4.7153 -19.2252 11.1692 + *MESH_VERTEX 8 4.7776 -19.2252 11.1692 + *MESH_VERTEX 9 5.0568 -19.1079 11.4692 + *MESH_VERTEX 10 5.0568 -19.7108 13.3655 + *MESH_VERTEX 11 4.7776 -19.9732 13.9146 + *MESH_VERTEX 12 -4.7153 1.3858 0.0615 + *MESH_VERTEX 13 -4.9945 1.2049 -0.2172 + *MESH_VERTEX 14 -4.9945 0.5175 -1.2756 + *MESH_VERTEX 15 -4.7153 0.3457 -1.5402 + *MESH_VERTEX 16 4.7776 0.3457 -1.5402 + *MESH_VERTEX 17 5.0568 0.5175 -1.2756 + *MESH_VERTEX 18 5.0568 1.2049 -0.2172 + *MESH_VERTEX 19 4.7776 1.3858 0.0615 + *MESH_VERTEX 20 4.7776 0.6223 -1.3438 + *MESH_VERTEX 21 -4.7153 0.6223 -1.3438 + *MESH_VERTEX 22 4.7776 1.3097 -0.2854 + *MESH_VERTEX 23 -4.7153 1.3097 -0.2854 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 1: A: 0 B: 3 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 2: A: 0 B: 4 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 3: A: 0 B: 5 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 6 C: 2 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 5: A: 2 B: 6 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 6: A: 2 B: 7 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 7: A: 2 B: 8 C: 3 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 8: A: 3 B: 8 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 9: A: 3 B: 9 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 10: A: 3 B: 10 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 11: A: 1 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 12: A: 1 B: 11 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 13: A: 1 B: 4 C: 0 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 14: A: 4 B: 12 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 15: A: 4 B: 13 C: 5 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 16: A: 5 B: 13 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 17: A: 5 B: 14 C: 6 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 18: A: 6 B: 14 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 19: A: 6 B: 15 C: 7 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 20: A: 7 B: 15 C: 16 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 21: A: 7 B: 16 C: 8 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 22: A: 8 B: 16 C: 17 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 23: A: 8 B: 17 C: 9 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 24: A: 9 B: 17 C: 18 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 25: A: 9 B: 18 C: 10 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 26: A: 10 B: 18 C: 19 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 27: A: 10 B: 19 C: 11 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 28: A: 11 B: 19 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 29: A: 11 B: 12 C: 4 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 30: A: 12 B: 23 C: 13 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 31: A: 13 B: 23 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 32: A: 13 B: 21 C: 14 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 33: A: 14 B: 21 C: 15 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 34: A: 15 B: 21 C: 20 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 35: A: 15 B: 20 C: 16 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 36: A: 16 B: 20 C: 17 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 37: A: 17 B: 20 C: 22 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 38: A: 17 B: 22 C: 18 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 39: A: 18 B: 22 C: 19 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 40: A: 19 B: 22 C: 23 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 41: A: 19 B: 23 C: 12 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 42: A: 22 B: 20 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 43: A: 22 B: 21 C: 23 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 24 + *MESH_CVERTLIST { + *MESH_VERTCOL 0 0.4236 0.4236 0.4236 + *MESH_VERTCOL 1 0.4202 0.4202 0.4202 + *MESH_VERTCOL 2 0.3837 0.3837 0.3837 + *MESH_VERTCOL 3 0.3717 0.3717 0.3717 + *MESH_VERTCOL 4 0.6691 0.6691 0.6691 + *MESH_VERTCOL 5 0.5788 0.5788 0.5788 + *MESH_VERTCOL 6 0.4225 0.4225 0.4225 + *MESH_VERTCOL 7 0.2765 0.2765 0.2765 + *MESH_VERTCOL 8 0.3049 0.3049 0.3049 + *MESH_VERTCOL 9 0.5108 0.5108 0.5108 + *MESH_VERTCOL 10 0.6195 0.6195 0.6195 + *MESH_VERTCOL 11 0.7210 0.7210 0.7210 + *MESH_VERTCOL 12 0.6054 0.6054 0.6054 + *MESH_VERTCOL 13 0.7167 0.7167 0.7167 + *MESH_VERTCOL 14 0.5792 0.5792 0.5792 + *MESH_VERTCOL 15 0.3464 0.3464 0.3464 + *MESH_VERTCOL 16 0.2693 0.2693 0.2693 + *MESH_VERTCOL 17 0.4903 0.4903 0.4903 + *MESH_VERTCOL 18 0.6958 0.6958 0.6958 + *MESH_VERTCOL 19 0.6274 0.6274 0.6274 + *MESH_VERTCOL 20 0.4361 0.4361 0.4361 + *MESH_VERTCOL 21 0.5644 0.5644 0.5644 + *MESH_VERTCOL 22 0.5445 0.5445 0.5445 + *MESH_VERTCOL 23 0.6008 0.6008 0.6008 + } + *MESH_NUMCVFACES 44 + *MESH_CFACELIST { + *MESH_CFACE 0 0 2 3 + *MESH_CFACE 1 0 3 1 + *MESH_CFACE 2 0 4 5 + *MESH_CFACE 3 0 5 6 + *MESH_CFACE 4 0 6 2 + *MESH_CFACE 5 2 6 7 + *MESH_CFACE 6 2 7 8 + *MESH_CFACE 7 2 8 3 + *MESH_CFACE 8 3 8 9 + *MESH_CFACE 9 3 9 10 + *MESH_CFACE 10 3 10 1 + *MESH_CFACE 11 1 10 11 + *MESH_CFACE 12 1 11 4 + *MESH_CFACE 13 1 4 0 + *MESH_CFACE 14 4 12 13 + *MESH_CFACE 15 4 13 5 + *MESH_CFACE 16 5 13 14 + *MESH_CFACE 17 5 14 6 + *MESH_CFACE 18 6 14 15 + *MESH_CFACE 19 6 15 7 + *MESH_CFACE 20 7 15 16 + *MESH_CFACE 21 7 16 8 + *MESH_CFACE 22 8 16 17 + *MESH_CFACE 23 8 17 9 + *MESH_CFACE 24 9 17 18 + *MESH_CFACE 25 9 18 10 + *MESH_CFACE 26 10 18 19 + *MESH_CFACE 27 10 19 11 + *MESH_CFACE 28 11 19 12 + *MESH_CFACE 29 11 12 4 + *MESH_CFACE 30 12 23 13 + *MESH_CFACE 31 13 23 21 + *MESH_CFACE 32 13 21 14 + *MESH_CFACE 33 14 21 15 + *MESH_CFACE 34 15 21 20 + *MESH_CFACE 35 15 20 16 + *MESH_CFACE 36 16 20 17 + *MESH_CFACE 37 17 20 22 + *MESH_CFACE 38 17 22 18 + *MESH_CFACE 39 18 22 19 + *MESH_CFACE 40 19 22 23 + *MESH_CFACE 41 19 23 12 + *MESH_CFACE 42 22 20 21 + *MESH_CFACE 43 22 21 23 + } + } + *MESH { + *TIMEVALUE 1600 + *MESH_NUMVERTEX 24 + *MESH_NUMFACES 44 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 -4.7153 -22.7471 7.5228 + *MESH_VERTEX 1 4.7776 -22.7471 7.5228 + *MESH_VERTEX 2 -4.7153 -21.6739 5.8471 + *MESH_VERTEX 3 4.7776 -21.6739 5.8471 + *MESH_VERTEX 4 -4.7153 -22.8427 7.8877 + *MESH_VERTEX 5 -4.9945 -22.4471 7.4253 + *MESH_VERTEX 6 -4.9945 -21.3739 5.7496 + *MESH_VERTEX 7 -4.7153 -21.4095 5.4295 + *MESH_VERTEX 8 4.7776 -21.4095 5.4295 + *MESH_VERTEX 9 5.0568 -21.3739 5.7496 + *MESH_VERTEX 10 5.0568 -22.4471 7.4253 + *MESH_VERTEX 11 4.7776 -22.8426 7.8877 + *MESH_VERTEX 12 -4.7153 1.3740 0.0348 + *MESH_VERTEX 13 -4.9945 1.2714 -0.2812 + *MESH_VERTEX 14 -4.9945 0.8814 -1.4815 + *MESH_VERTEX 15 -4.7153 0.7839 -1.7815 + *MESH_VERTEX 16 4.7776 0.7839 -1.7815 + *MESH_VERTEX 17 5.0568 0.8814 -1.4815 + *MESH_VERTEX 18 5.0568 1.2714 -0.2812 + *MESH_VERTEX 19 4.7776 1.3740 0.0348 + *MESH_VERTEX 20 4.7776 1.0003 -1.5202 + *MESH_VERTEX 21 -4.7153 1.0003 -1.5202 + *MESH_VERTEX 22 4.7776 1.3903 -0.3200 + *MESH_VERTEX 23 -4.7153 1.3903 -0.3200 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 1: A: 0 B: 3 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 2: A: 0 B: 4 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 3: A: 0 B: 5 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 6 C: 2 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 5: A: 2 B: 6 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 6: A: 2 B: 7 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 7: A: 2 B: 8 C: 3 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 8: A: 3 B: 8 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 9: A: 3 B: 9 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 10: A: 3 B: 10 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 11: A: 1 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 12: A: 1 B: 11 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 13: A: 1 B: 4 C: 0 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 14: A: 4 B: 12 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 15: A: 4 B: 13 C: 5 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 16: A: 5 B: 13 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 17: A: 5 B: 14 C: 6 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 18: A: 6 B: 14 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 19: A: 6 B: 15 C: 7 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 20: A: 7 B: 15 C: 16 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 21: A: 7 B: 16 C: 8 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 22: A: 8 B: 16 C: 17 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 23: A: 8 B: 17 C: 9 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 24: A: 9 B: 17 C: 18 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 25: A: 9 B: 18 C: 10 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 26: A: 10 B: 18 C: 19 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 27: A: 10 B: 19 C: 11 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 28: A: 11 B: 19 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 29: A: 11 B: 12 C: 4 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 30: A: 12 B: 23 C: 13 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 31: A: 13 B: 23 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 32: A: 13 B: 21 C: 14 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 33: A: 14 B: 21 C: 15 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 34: A: 15 B: 21 C: 20 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 35: A: 15 B: 20 C: 16 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 36: A: 16 B: 20 C: 17 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 37: A: 17 B: 20 C: 22 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 38: A: 17 B: 22 C: 18 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 39: A: 18 B: 22 C: 19 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 40: A: 19 B: 22 C: 23 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 41: A: 19 B: 23 C: 12 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 42: A: 22 B: 20 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 43: A: 22 B: 21 C: 23 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 24 + *MESH_CVERTLIST { + *MESH_VERTCOL 0 0.4236 0.4236 0.4236 + *MESH_VERTCOL 1 0.4202 0.4202 0.4202 + *MESH_VERTCOL 2 0.3837 0.3837 0.3837 + *MESH_VERTCOL 3 0.3717 0.3717 0.3717 + *MESH_VERTCOL 4 0.6691 0.6691 0.6691 + *MESH_VERTCOL 5 0.5788 0.5788 0.5788 + *MESH_VERTCOL 6 0.4225 0.4225 0.4225 + *MESH_VERTCOL 7 0.2765 0.2765 0.2765 + *MESH_VERTCOL 8 0.3049 0.3049 0.3049 + *MESH_VERTCOL 9 0.5108 0.5108 0.5108 + *MESH_VERTCOL 10 0.6195 0.6195 0.6195 + *MESH_VERTCOL 11 0.7210 0.7210 0.7210 + *MESH_VERTCOL 12 0.6054 0.6054 0.6054 + *MESH_VERTCOL 13 0.7167 0.7167 0.7167 + *MESH_VERTCOL 14 0.5792 0.5792 0.5792 + *MESH_VERTCOL 15 0.3464 0.3464 0.3464 + *MESH_VERTCOL 16 0.2693 0.2693 0.2693 + *MESH_VERTCOL 17 0.4903 0.4903 0.4903 + *MESH_VERTCOL 18 0.6958 0.6958 0.6958 + *MESH_VERTCOL 19 0.6274 0.6274 0.6274 + *MESH_VERTCOL 20 0.4361 0.4361 0.4361 + *MESH_VERTCOL 21 0.5644 0.5644 0.5644 + *MESH_VERTCOL 22 0.5445 0.5445 0.5445 + *MESH_VERTCOL 23 0.6008 0.6008 0.6008 + } + *MESH_NUMCVFACES 44 + *MESH_CFACELIST { + *MESH_CFACE 0 0 2 3 + *MESH_CFACE 1 0 3 1 + *MESH_CFACE 2 0 4 5 + *MESH_CFACE 3 0 5 6 + *MESH_CFACE 4 0 6 2 + *MESH_CFACE 5 2 6 7 + *MESH_CFACE 6 2 7 8 + *MESH_CFACE 7 2 8 3 + *MESH_CFACE 8 3 8 9 + *MESH_CFACE 9 3 9 10 + *MESH_CFACE 10 3 10 1 + *MESH_CFACE 11 1 10 11 + *MESH_CFACE 12 1 11 4 + *MESH_CFACE 13 1 4 0 + *MESH_CFACE 14 4 12 13 + *MESH_CFACE 15 4 13 5 + *MESH_CFACE 16 5 13 14 + *MESH_CFACE 17 5 14 6 + *MESH_CFACE 18 6 14 15 + *MESH_CFACE 19 6 15 7 + *MESH_CFACE 20 7 15 16 + *MESH_CFACE 21 7 16 8 + *MESH_CFACE 22 8 16 17 + *MESH_CFACE 23 8 17 9 + *MESH_CFACE 24 9 17 18 + *MESH_CFACE 25 9 18 10 + *MESH_CFACE 26 10 18 19 + *MESH_CFACE 27 10 19 11 + *MESH_CFACE 28 11 19 12 + *MESH_CFACE 29 11 12 4 + *MESH_CFACE 30 12 23 13 + *MESH_CFACE 31 13 23 21 + *MESH_CFACE 32 13 21 14 + *MESH_CFACE 33 14 21 15 + *MESH_CFACE 34 15 21 20 + *MESH_CFACE 35 15 20 16 + *MESH_CFACE 36 16 20 17 + *MESH_CFACE 37 17 20 22 + *MESH_CFACE 38 17 22 18 + *MESH_CFACE 39 18 22 19 + *MESH_CFACE 40 19 22 23 + *MESH_CFACE 41 19 23 12 + *MESH_CFACE 42 22 20 21 + *MESH_CFACE 43 22 21 23 + } + } + *MESH { + *TIMEVALUE 1760 + *MESH_NUMVERTEX 24 + *MESH_NUMFACES 44 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 -4.7153 -23.7810 2.3211 + *MESH_VERTEX 1 4.7776 -23.7810 2.3211 + *MESH_VERTEX 2 -4.7153 -22.3829 0.9052 + *MESH_VERTEX 3 4.7776 -22.3829 0.9052 + *MESH_VERTEX 4 -4.7153 -23.9504 2.6582 + *MESH_VERTEX 5 -4.9945 -23.4673 2.2881 + *MESH_VERTEX 6 -4.9945 -22.0692 0.8722 + *MESH_VERTEX 7 -4.7153 -22.0374 0.5516 + *MESH_VERTEX 8 4.7776 -22.0374 0.5516 + *MESH_VERTEX 9 5.0568 -22.0692 0.8722 + *MESH_VERTEX 10 5.0568 -23.4673 2.2881 + *MESH_VERTEX 11 4.7776 -23.9503 2.6582 + *MESH_VERTEX 12 -4.7153 1.3698 0.0118 + *MESH_VERTEX 13 -4.9945 1.3351 -0.3187 + *MESH_VERTEX 14 -4.9945 1.2032 -1.5738 + *MESH_VERTEX 15 -4.7153 1.1702 -1.8875 + *MESH_VERTEX 16 4.7776 1.1702 -1.8875 + *MESH_VERTEX 17 5.0568 1.2032 -1.5738 + *MESH_VERTEX 18 5.0568 1.3351 -0.3187 + *MESH_VERTEX 19 4.7776 1.3698 0.0118 + *MESH_VERTEX 20 4.7776 1.3276 -1.5869 + *MESH_VERTEX 21 -4.7153 1.3276 -1.5869 + *MESH_VERTEX 22 4.7776 1.4595 -0.3318 + *MESH_VERTEX 23 -4.7153 1.4595 -0.3318 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 1: A: 0 B: 3 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 2: A: 0 B: 4 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 3: A: 0 B: 5 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 6 C: 2 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 5: A: 2 B: 6 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 6: A: 2 B: 7 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 7: A: 2 B: 8 C: 3 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 8: A: 3 B: 8 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 9: A: 3 B: 9 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 10: A: 3 B: 10 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 11: A: 1 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 12: A: 1 B: 11 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 13: A: 1 B: 4 C: 0 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 14: A: 4 B: 12 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 15: A: 4 B: 13 C: 5 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 16: A: 5 B: 13 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 17: A: 5 B: 14 C: 6 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 18: A: 6 B: 14 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 19: A: 6 B: 15 C: 7 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 20: A: 7 B: 15 C: 16 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 21: A: 7 B: 16 C: 8 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 22: A: 8 B: 16 C: 17 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 23: A: 8 B: 17 C: 9 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 24: A: 9 B: 17 C: 18 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 25: A: 9 B: 18 C: 10 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 26: A: 10 B: 18 C: 19 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 27: A: 10 B: 19 C: 11 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 28: A: 11 B: 19 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 29: A: 11 B: 12 C: 4 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 30: A: 12 B: 23 C: 13 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 31: A: 13 B: 23 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 32: A: 13 B: 21 C: 14 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 33: A: 14 B: 21 C: 15 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 34: A: 15 B: 21 C: 20 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 35: A: 15 B: 20 C: 16 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 36: A: 16 B: 20 C: 17 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 37: A: 17 B: 20 C: 22 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 38: A: 17 B: 22 C: 18 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 39: A: 18 B: 22 C: 19 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 40: A: 19 B: 22 C: 23 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 41: A: 19 B: 23 C: 12 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 42: A: 22 B: 20 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 43: A: 22 B: 21 C: 23 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 24 + *MESH_CVERTLIST { + *MESH_VERTCOL 0 0.4236 0.4236 0.4236 + *MESH_VERTCOL 1 0.4202 0.4202 0.4202 + *MESH_VERTCOL 2 0.3837 0.3837 0.3837 + *MESH_VERTCOL 3 0.3717 0.3717 0.3717 + *MESH_VERTCOL 4 0.6691 0.6691 0.6691 + *MESH_VERTCOL 5 0.5788 0.5788 0.5788 + *MESH_VERTCOL 6 0.4225 0.4225 0.4225 + *MESH_VERTCOL 7 0.2765 0.2765 0.2765 + *MESH_VERTCOL 8 0.3049 0.3049 0.3049 + *MESH_VERTCOL 9 0.5108 0.5108 0.5108 + *MESH_VERTCOL 10 0.6195 0.6195 0.6195 + *MESH_VERTCOL 11 0.7210 0.7210 0.7210 + *MESH_VERTCOL 12 0.6054 0.6054 0.6054 + *MESH_VERTCOL 13 0.7167 0.7167 0.7167 + *MESH_VERTCOL 14 0.5792 0.5792 0.5792 + *MESH_VERTCOL 15 0.3464 0.3464 0.3464 + *MESH_VERTCOL 16 0.2693 0.2693 0.2693 + *MESH_VERTCOL 17 0.4903 0.4903 0.4903 + *MESH_VERTCOL 18 0.6958 0.6958 0.6958 + *MESH_VERTCOL 19 0.6274 0.6274 0.6274 + *MESH_VERTCOL 20 0.4361 0.4361 0.4361 + *MESH_VERTCOL 21 0.5644 0.5644 0.5644 + *MESH_VERTCOL 22 0.5445 0.5445 0.5445 + *MESH_VERTCOL 23 0.6008 0.6008 0.6008 + } + *MESH_NUMCVFACES 44 + *MESH_CFACELIST { + *MESH_CFACE 0 0 2 3 + *MESH_CFACE 1 0 3 1 + *MESH_CFACE 2 0 4 5 + *MESH_CFACE 3 0 5 6 + *MESH_CFACE 4 0 6 2 + *MESH_CFACE 5 2 6 7 + *MESH_CFACE 6 2 7 8 + *MESH_CFACE 7 2 8 3 + *MESH_CFACE 8 3 8 9 + *MESH_CFACE 9 3 9 10 + *MESH_CFACE 10 3 10 1 + *MESH_CFACE 11 1 10 11 + *MESH_CFACE 12 1 11 4 + *MESH_CFACE 13 1 4 0 + *MESH_CFACE 14 4 12 13 + *MESH_CFACE 15 4 13 5 + *MESH_CFACE 16 5 13 14 + *MESH_CFACE 17 5 14 6 + *MESH_CFACE 18 6 14 15 + *MESH_CFACE 19 6 15 7 + *MESH_CFACE 20 7 15 16 + *MESH_CFACE 21 7 16 8 + *MESH_CFACE 22 8 16 17 + *MESH_CFACE 23 8 17 9 + *MESH_CFACE 24 9 17 18 + *MESH_CFACE 25 9 18 10 + *MESH_CFACE 26 10 18 19 + *MESH_CFACE 27 10 19 11 + *MESH_CFACE 28 11 19 12 + *MESH_CFACE 29 11 12 4 + *MESH_CFACE 30 12 23 13 + *MESH_CFACE 31 13 23 21 + *MESH_CFACE 32 13 21 14 + *MESH_CFACE 33 14 21 15 + *MESH_CFACE 34 15 21 20 + *MESH_CFACE 35 15 20 16 + *MESH_CFACE 36 16 20 17 + *MESH_CFACE 37 17 20 22 + *MESH_CFACE 38 17 22 18 + *MESH_CFACE 39 18 22 19 + *MESH_CFACE 40 19 22 23 + *MESH_CFACE 41 19 23 12 + *MESH_CFACE 42 22 20 21 + *MESH_CFACE 43 22 21 23 + } + } + *MESH { + *TIMEVALUE 1920 + *MESH_NUMVERTEX 24 + *MESH_NUMFACES 44 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 -4.7153 -23.8849 -0.3323 + *MESH_VERTEX 1 4.7776 -23.8849 -0.3323 + *MESH_VERTEX 2 -4.7153 -22.3465 -1.5943 + *MESH_VERTEX 3 4.7776 -22.3465 -1.5943 + *MESH_VERTEX 4 -4.7153 -24.0885 -0.0147 + *MESH_VERTEX 5 -4.9945 -23.5694 -0.3323 + *MESH_VERTEX 6 -4.9945 -22.0310 -1.5942 + *MESH_VERTEX 7 -4.7153 -21.9659 -1.9097 + *MESH_VERTEX 8 4.7776 -21.9659 -1.9097 + *MESH_VERTEX 9 5.0568 -22.0310 -1.5943 + *MESH_VERTEX 10 5.0568 -23.5694 -0.3323 + *MESH_VERTEX 11 4.7776 -24.0885 -0.0147 + *MESH_VERTEX 12 -4.7153 1.3696 0.0001 + *MESH_VERTEX 13 -4.9945 1.3696 -0.3322 + *MESH_VERTEX 14 -4.9945 1.3696 -1.5942 + *MESH_VERTEX 15 -4.7153 1.3696 -1.9097 + *MESH_VERTEX 16 4.7776 1.3696 -1.9097 + *MESH_VERTEX 17 5.0568 1.3696 -1.5942 + *MESH_VERTEX 18 5.0568 1.3696 -0.3322 + *MESH_VERTEX 19 4.7776 1.3696 0.0001 + *MESH_VERTEX 20 4.7776 1.4947 -1.5943 + *MESH_VERTEX 21 -4.7153 1.4947 -1.5943 + *MESH_VERTEX 22 4.7776 1.4947 -0.3323 + *MESH_VERTEX 23 -4.7153 1.4947 -0.3323 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 1: A: 0 B: 3 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 2: A: 0 B: 4 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 3: A: 0 B: 5 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 6 C: 2 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 5: A: 2 B: 6 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 6: A: 2 B: 7 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 7: A: 2 B: 8 C: 3 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 8: A: 3 B: 8 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 9: A: 3 B: 9 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 10: A: 3 B: 10 C: 1 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 11: A: 1 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 12: A: 1 B: 11 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 13: A: 1 B: 4 C: 0 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 14: A: 4 B: 12 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 15: A: 4 B: 13 C: 5 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 16: A: 5 B: 13 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 17: A: 5 B: 14 C: 6 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 18: A: 6 B: 14 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 19: A: 6 B: 15 C: 7 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 20: A: 7 B: 15 C: 16 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 21: A: 7 B: 16 C: 8 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 22: A: 8 B: 16 C: 17 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 23: A: 8 B: 17 C: 9 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 24: A: 9 B: 17 C: 18 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 25: A: 9 B: 18 C: 10 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 26: A: 10 B: 18 C: 19 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 27: A: 10 B: 19 C: 11 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 28: A: 11 B: 19 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 29: A: 11 B: 12 C: 4 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 30: A: 12 B: 23 C: 13 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 31: A: 13 B: 23 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 32: A: 13 B: 21 C: 14 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 33: A: 14 B: 21 C: 15 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 34: A: 15 B: 21 C: 20 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 35: A: 15 B: 20 C: 16 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 36: A: 16 B: 20 C: 17 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 37: A: 17 B: 20 C: 22 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 38: A: 17 B: 22 C: 18 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 39: A: 18 B: 22 C: 19 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 40: A: 19 B: 22 C: 23 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 41: A: 19 B: 23 C: 12 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 42: A: 22 B: 20 C: 21 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 1 *MESH_MTLID 0 + *MESH_FACE 43: A: 22 B: 21 C: 23 AB: 0 BC: 1 CA: 1 *MESH_SMOOTHING 1 *MESH_MTLID 0 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 24 + *MESH_CVERTLIST { + *MESH_VERTCOL 0 0.4236 0.4236 0.4236 + *MESH_VERTCOL 1 0.4202 0.4202 0.4202 + *MESH_VERTCOL 2 0.3837 0.3837 0.3837 + *MESH_VERTCOL 3 0.3717 0.3717 0.3717 + *MESH_VERTCOL 4 0.6691 0.6691 0.6691 + *MESH_VERTCOL 5 0.5788 0.5788 0.5788 + *MESH_VERTCOL 6 0.4225 0.4225 0.4225 + *MESH_VERTCOL 7 0.2765 0.2765 0.2765 + *MESH_VERTCOL 8 0.3049 0.3049 0.3049 + *MESH_VERTCOL 9 0.5108 0.5108 0.5108 + *MESH_VERTCOL 10 0.6195 0.6195 0.6195 + *MESH_VERTCOL 11 0.7210 0.7210 0.7210 + *MESH_VERTCOL 12 0.6054 0.6054 0.6054 + *MESH_VERTCOL 13 0.7167 0.7167 0.7167 + *MESH_VERTCOL 14 0.5792 0.5792 0.5792 + *MESH_VERTCOL 15 0.3464 0.3464 0.3464 + *MESH_VERTCOL 16 0.2693 0.2693 0.2693 + *MESH_VERTCOL 17 0.4903 0.4903 0.4903 + *MESH_VERTCOL 18 0.6958 0.6958 0.6958 + *MESH_VERTCOL 19 0.6274 0.6274 0.6274 + *MESH_VERTCOL 20 0.4361 0.4361 0.4361 + *MESH_VERTCOL 21 0.5644 0.5644 0.5644 + *MESH_VERTCOL 22 0.5445 0.5445 0.5445 + *MESH_VERTCOL 23 0.6008 0.6008 0.6008 + } + *MESH_NUMCVFACES 44 + *MESH_CFACELIST { + *MESH_CFACE 0 0 2 3 + *MESH_CFACE 1 0 3 1 + *MESH_CFACE 2 0 4 5 + *MESH_CFACE 3 0 5 6 + *MESH_CFACE 4 0 6 2 + *MESH_CFACE 5 2 6 7 + *MESH_CFACE 6 2 7 8 + *MESH_CFACE 7 2 8 3 + *MESH_CFACE 8 3 8 9 + *MESH_CFACE 9 3 9 10 + *MESH_CFACE 10 3 10 1 + *MESH_CFACE 11 1 10 11 + *MESH_CFACE 12 1 11 4 + *MESH_CFACE 13 1 4 0 + *MESH_CFACE 14 4 12 13 + *MESH_CFACE 15 4 13 5 + *MESH_CFACE 16 5 13 14 + *MESH_CFACE 17 5 14 6 + *MESH_CFACE 18 6 14 15 + *MESH_CFACE 19 6 15 7 + *MESH_CFACE 20 7 15 16 + *MESH_CFACE 21 7 16 8 + *MESH_CFACE 22 8 16 17 + *MESH_CFACE 23 8 17 9 + *MESH_CFACE 24 9 17 18 + *MESH_CFACE 25 9 18 10 + *MESH_CFACE 26 10 18 19 + *MESH_CFACE 27 10 19 11 + *MESH_CFACE 28 11 19 12 + *MESH_CFACE 29 11 12 4 + *MESH_CFACE 30 12 23 13 + *MESH_CFACE 31 13 23 21 + *MESH_CFACE 32 13 21 14 + *MESH_CFACE 33 14 21 15 + *MESH_CFACE 34 15 21 20 + *MESH_CFACE 35 15 20 16 + *MESH_CFACE 36 16 20 17 + *MESH_CFACE 37 17 20 22 + *MESH_CFACE 38 17 22 18 + *MESH_CFACE 39 18 22 19 + *MESH_CFACE 40 19 22 23 + *MESH_CFACE 41 19 23 12 + *MESH_CFACE 42 22 20 21 + *MESH_CFACE 43 22 21 23 + } + } + } +} +*GEOMOBJECT { + *NODE_NAME "Chain1" + *NODE_TM { + *NODE_NAME "Chain1" + *INHERIT_POS 0 0 0 + *INHERIT_ROT 0 0 0 + *INHERIT_SCL 0 0 0 + *TM_ROW0 1.0000 -0.0000 0.0000 + *TM_ROW1 -0.0000 0.8192 0.5736 + *TM_ROW2 -0.0000 -0.5736 0.8192 + *TM_ROW3 6.0480 -21.8398 -0.6886 + *TM_POS 6.0480 -21.8398 -0.6886 + *TM_ROTAXIS -1.0000 0.0000 0.0000 + *TM_ROTANGLE 0.6109 + *TM_SCALE 1.0000 1.0000 1.0000 + *TM_SCALEAXIS 0.0000 0.0000 0.0000 + *TM_SCALEAXISANG 0.0000 + } + *MESH { + *TIMEVALUE 0 + *MESH_NUMVERTEX 16 + *MESH_NUMFACES 24 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 5.0645 -22.0380 -1.5503 + *MESH_VERTEX 1 5.6493 -22.0380 -1.5503 + *MESH_VERTEX 2 5.0645 2.6351 15.7672 + *MESH_VERTEX 3 5.6493 2.6351 15.7672 + *MESH_VERTEX 4 5.0645 -22.7418 -0.5451 + *MESH_VERTEX 5 5.6493 -22.7418 -0.5451 + *MESH_VERTEX 6 5.0645 1.9312 16.7724 + *MESH_VERTEX 7 5.6493 1.9312 16.7724 + *MESH_VERTEX 8 -5.5472 -22.0380 -1.5503 + *MESH_VERTEX 9 -4.9624 -22.0380 -1.5503 + *MESH_VERTEX 10 -5.5472 2.6351 15.7672 + *MESH_VERTEX 11 -4.9624 2.6351 15.7672 + *MESH_VERTEX 12 -5.5472 -22.7418 -0.5451 + *MESH_VERTEX 13 -4.9624 -22.7418 -0.5451 + *MESH_VERTEX 14 -5.5472 1.9312 16.7724 + *MESH_VERTEX 15 -4.9624 1.9312 16.7724 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 3: A: 7 B: 6 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 1 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 5: A: 5 B: 4 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 6: A: 1 B: 3 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 7: A: 7 B: 5 C: 1 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 8: A: 3 B: 2 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 9: A: 6 B: 7 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 10: A: 2 B: 0 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 11: A: 4 B: 6 C: 2 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 12: A: 8 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 13: A: 11 B: 9 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 14: A: 12 B: 13 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 15: A: 15 B: 14 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 16: A: 8 B: 9 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 17: A: 13 B: 12 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 18: A: 9 B: 11 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 19: A: 15 B: 13 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 20: A: 11 B: 10 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 21: A: 14 B: 15 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 22: A: 10 B: 8 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 23: A: 12 B: 14 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 0 + } + *PROP_MOTIONBLUR 0 + *PROP_CASTSHADOW 1 + *PROP_RECVSHADOW 1 + *MATERIAL_REF 1 + *MESH_ANIMATION { + *MESH { + *TIMEVALUE 0 + *MESH_NUMVERTEX 16 + *MESH_NUMFACES 24 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 5.0645 -22.0380 -1.5503 + *MESH_VERTEX 1 5.6493 -22.0380 -1.5503 + *MESH_VERTEX 2 5.0645 2.6351 15.7672 + *MESH_VERTEX 3 5.6493 2.6351 15.7672 + *MESH_VERTEX 4 5.0645 -22.7418 -0.5451 + *MESH_VERTEX 5 5.6493 -22.7418 -0.5451 + *MESH_VERTEX 6 5.0645 1.9312 16.7724 + *MESH_VERTEX 7 5.6493 1.9312 16.7724 + *MESH_VERTEX 8 -5.5472 -22.0380 -1.5503 + *MESH_VERTEX 9 -4.9624 -22.0380 -1.5503 + *MESH_VERTEX 10 -5.5472 2.6351 15.7672 + *MESH_VERTEX 11 -4.9624 2.6351 15.7672 + *MESH_VERTEX 12 -5.5472 -22.7418 -0.5451 + *MESH_VERTEX 13 -4.9624 -22.7418 -0.5451 + *MESH_VERTEX 14 -5.5472 1.9312 16.7724 + *MESH_VERTEX 15 -4.9624 1.9312 16.7724 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 3: A: 7 B: 6 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 1 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 5: A: 5 B: 4 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 6: A: 1 B: 3 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 7: A: 7 B: 5 C: 1 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 8: A: 3 B: 2 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 9: A: 6 B: 7 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 10: A: 2 B: 0 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 11: A: 4 B: 6 C: 2 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 12: A: 8 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 13: A: 11 B: 9 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 14: A: 12 B: 13 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 15: A: 15 B: 14 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 16: A: 8 B: 9 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 17: A: 13 B: 12 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 18: A: 9 B: 11 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 19: A: 15 B: 13 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 20: A: 11 B: 10 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 21: A: 14 B: 15 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 22: A: 10 B: 8 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 23: A: 12 B: 14 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 0 + } + *MESH { + *TIMEVALUE 160 + *MESH_NUMVERTEX 16 + *MESH_NUMFACES 24 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 5.0645 -22.0266 0.8322 + *MESH_VERTEX 1 5.6493 -22.0266 0.8322 + *MESH_VERTEX 2 5.0645 2.6683 15.6438 + *MESH_VERTEX 3 5.6493 2.6683 15.6438 + *MESH_VERTEX 4 5.0645 -22.6586 1.8841 + *MESH_VERTEX 5 5.6493 -22.6586 1.8841 + *MESH_VERTEX 6 5.0645 2.0362 16.6957 + *MESH_VERTEX 7 5.6493 2.0362 16.6957 + *MESH_VERTEX 8 -5.5472 -22.0266 0.8322 + *MESH_VERTEX 9 -4.9624 -22.0266 0.8322 + *MESH_VERTEX 10 -5.5472 2.6683 15.6438 + *MESH_VERTEX 11 -4.9624 2.6683 15.6438 + *MESH_VERTEX 12 -5.5472 -22.6586 1.8841 + *MESH_VERTEX 13 -4.9624 -22.6586 1.8841 + *MESH_VERTEX 14 -5.5472 2.0362 16.6957 + *MESH_VERTEX 15 -4.9624 2.0362 16.6957 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 3: A: 7 B: 6 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 1 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 5: A: 5 B: 4 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 6: A: 1 B: 3 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 7: A: 7 B: 5 C: 1 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 8: A: 3 B: 2 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 9: A: 6 B: 7 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 10: A: 2 B: 0 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 11: A: 4 B: 6 C: 2 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 12: A: 8 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 13: A: 11 B: 9 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 14: A: 12 B: 13 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 15: A: 15 B: 14 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 16: A: 8 B: 9 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 17: A: 13 B: 12 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 18: A: 9 B: 11 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 19: A: 15 B: 13 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 20: A: 11 B: 10 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 21: A: 14 B: 15 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 22: A: 10 B: 8 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 23: A: 12 B: 14 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 0 + } + *MESH { + *TIMEVALUE 320 + *MESH_NUMVERTEX 16 + *MESH_NUMFACES 24 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 5.0645 -21.4047 5.7018 + *MESH_VERTEX 1 5.6493 -21.4047 5.7018 + *MESH_VERTEX 2 5.0645 2.2307 15.1920 + *MESH_VERTEX 3 5.6493 2.2307 15.1920 + *MESH_VERTEX 4 5.0645 -21.8644 6.8396 + *MESH_VERTEX 5 5.6493 -21.8644 6.8396 + *MESH_VERTEX 6 5.0645 1.7710 16.3298 + *MESH_VERTEX 7 5.6493 1.7710 16.3298 + *MESH_VERTEX 8 -5.5472 -21.4047 5.7018 + *MESH_VERTEX 9 -4.9624 -21.4047 5.7018 + *MESH_VERTEX 10 -5.5472 2.2307 15.1920 + *MESH_VERTEX 11 -4.9624 2.2307 15.1920 + *MESH_VERTEX 12 -5.5472 -21.8644 6.8396 + *MESH_VERTEX 13 -4.9624 -21.8644 6.8396 + *MESH_VERTEX 14 -5.5472 1.7710 16.3298 + *MESH_VERTEX 15 -4.9624 1.7710 16.3298 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 3: A: 7 B: 6 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 1 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 5: A: 5 B: 4 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 6: A: 1 B: 3 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 7: A: 7 B: 5 C: 1 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 8: A: 3 B: 2 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 9: A: 6 B: 7 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 10: A: 2 B: 0 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 11: A: 4 B: 6 C: 2 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 12: A: 8 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 13: A: 11 B: 9 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 14: A: 12 B: 13 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 15: A: 15 B: 14 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 16: A: 8 B: 9 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 17: A: 13 B: 12 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 18: A: 9 B: 11 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 19: A: 15 B: 13 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 20: A: 11 B: 10 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 21: A: 14 B: 15 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 22: A: 10 B: 8 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 23: A: 12 B: 14 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 0 + } + *MESH { + *TIMEVALUE 480 + *MESH_NUMVERTEX 16 + *MESH_NUMFACES 24 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 5.0645 -19.0583 11.4505 + *MESH_VERTEX 1 5.6493 -19.0583 11.4505 + *MESH_VERTEX 2 5.0645 2.0099 14.9183 + *MESH_VERTEX 3 5.6493 2.0099 14.9183 + *MESH_VERTEX 4 5.0645 -19.2608 12.6608 + *MESH_VERTEX 5 5.6493 -19.2608 12.6608 + *MESH_VERTEX 6 5.0645 1.8073 16.1286 + *MESH_VERTEX 7 5.6493 1.8073 16.1286 + *MESH_VERTEX 8 -5.5472 -19.0583 11.4505 + *MESH_VERTEX 9 -4.9624 -19.0583 11.4505 + *MESH_VERTEX 10 -5.5472 2.0099 14.9183 + *MESH_VERTEX 11 -4.9624 2.0099 14.9183 + *MESH_VERTEX 12 -5.5472 -19.2608 12.6608 + *MESH_VERTEX 13 -4.9624 -19.2608 12.6608 + *MESH_VERTEX 14 -5.5472 1.8073 16.1286 + *MESH_VERTEX 15 -4.9624 1.8073 16.1286 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 3: A: 7 B: 6 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 1 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 5: A: 5 B: 4 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 6: A: 1 B: 3 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 7: A: 7 B: 5 C: 1 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 8: A: 3 B: 2 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 9: A: 6 B: 7 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 10: A: 2 B: 0 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 11: A: 4 B: 6 C: 2 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 12: A: 8 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 13: A: 11 B: 9 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 14: A: 12 B: 13 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 15: A: 15 B: 14 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 16: A: 8 B: 9 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 17: A: 13 B: 12 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 18: A: 9 B: 11 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 19: A: 15 B: 13 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 20: A: 11 B: 10 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 21: A: 14 B: 15 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 22: A: 10 B: 8 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 23: A: 12 B: 14 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 0 + } + *MESH { + *TIMEVALUE 640 + *MESH_NUMVERTEX 16 + *MESH_NUMFACES 24 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 5.0645 -15.4384 16.3669 + *MESH_VERTEX 1 5.6493 -15.4384 16.3669 + *MESH_VERTEX 2 5.0645 1.9927 14.5226 + *MESH_VERTEX 3 5.6493 1.9927 14.5226 + *MESH_VERTEX 4 5.0645 -15.3101 17.5873 + *MESH_VERTEX 5 5.6493 -15.3101 17.5873 + *MESH_VERTEX 6 5.0645 2.1209 15.7431 + *MESH_VERTEX 7 5.6493 2.1209 15.7431 + *MESH_VERTEX 8 -5.5472 -15.4384 16.3669 + *MESH_VERTEX 9 -4.9624 -15.4384 16.3669 + *MESH_VERTEX 10 -5.5472 1.9927 14.5226 + *MESH_VERTEX 11 -4.9624 1.9927 14.5226 + *MESH_VERTEX 12 -5.5472 -15.3101 17.5873 + *MESH_VERTEX 13 -4.9624 -15.3101 17.5873 + *MESH_VERTEX 14 -5.5472 2.1209 15.7431 + *MESH_VERTEX 15 -4.9624 2.1209 15.7431 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 3: A: 7 B: 6 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 1 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 5: A: 5 B: 4 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 6: A: 1 B: 3 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 7: A: 7 B: 5 C: 1 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 8: A: 3 B: 2 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 9: A: 6 B: 7 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 10: A: 2 B: 0 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 11: A: 4 B: 6 C: 2 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 12: A: 8 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 13: A: 11 B: 9 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 14: A: 12 B: 13 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 15: A: 15 B: 14 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 16: A: 8 B: 9 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 17: A: 13 B: 12 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 18: A: 9 B: 11 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 19: A: 15 B: 13 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 20: A: 11 B: 10 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 21: A: 14 B: 15 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 22: A: 10 B: 8 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 23: A: 12 B: 14 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 0 + } + *MESH { + *TIMEVALUE 800 + *MESH_NUMVERTEX 16 + *MESH_NUMFACES 24 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 5.0645 -10.6435 20.1926 + *MESH_VERTEX 1 5.6493 -10.6435 20.1926 + *MESH_VERTEX 2 5.0645 1.9791 13.9747 + *MESH_VERTEX 3 5.6493 1.9791 13.9747 + *MESH_VERTEX 4 5.0645 -10.1055 21.2956 + *MESH_VERTEX 5 5.6493 -10.1055 21.2956 + *MESH_VERTEX 6 5.0645 2.5170 15.0777 + *MESH_VERTEX 7 5.6493 2.5170 15.0777 + *MESH_VERTEX 8 -5.5472 -10.6435 20.1926 + *MESH_VERTEX 9 -4.9624 -10.6435 20.1926 + *MESH_VERTEX 10 -5.5472 1.9791 13.9747 + *MESH_VERTEX 11 -4.9624 1.9791 13.9747 + *MESH_VERTEX 12 -5.5472 -10.1055 21.2956 + *MESH_VERTEX 13 -4.9624 -10.1055 21.2956 + *MESH_VERTEX 14 -5.5472 2.5170 15.0777 + *MESH_VERTEX 15 -4.9624 2.5170 15.0777 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 3: A: 7 B: 6 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 1 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 5: A: 5 B: 4 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 6: A: 1 B: 3 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 7: A: 7 B: 5 C: 1 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 8: A: 3 B: 2 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 9: A: 6 B: 7 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 10: A: 2 B: 0 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 11: A: 4 B: 6 C: 2 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 12: A: 8 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 13: A: 11 B: 9 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 14: A: 12 B: 13 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 15: A: 15 B: 14 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 16: A: 8 B: 9 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 17: A: 13 B: 12 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 18: A: 9 B: 11 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 19: A: 15 B: 13 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 20: A: 11 B: 10 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 21: A: 14 B: 15 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 22: A: 10 B: 8 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 23: A: 12 B: 14 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 0 + } + *MESH { + *TIMEVALUE 960 + *MESH_NUMVERTEX 16 + *MESH_NUMFACES 24 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 5.0645 -4.9514 22.6719 + *MESH_VERTEX 1 5.6493 -4.9514 22.6719 + *MESH_VERTEX 2 5.0645 2.4486 10.9225 + *MESH_VERTEX 3 5.6493 2.4486 10.9225 + *MESH_VERTEX 4 5.0645 -3.8580 23.2290 + *MESH_VERTEX 5 5.6493 -3.8580 23.2290 + *MESH_VERTEX 6 5.0645 3.5420 11.4797 + *MESH_VERTEX 7 5.6493 3.5420 11.4797 + *MESH_VERTEX 8 -5.5472 -4.9514 22.6718 + *MESH_VERTEX 9 -4.9624 -4.9514 22.6719 + *MESH_VERTEX 10 -5.5472 2.4486 10.9225 + *MESH_VERTEX 11 -4.9624 2.4486 10.9225 + *MESH_VERTEX 12 -5.5472 -3.8580 23.2290 + *MESH_VERTEX 13 -4.9624 -3.8580 23.2290 + *MESH_VERTEX 14 -5.5472 3.5420 11.4797 + *MESH_VERTEX 15 -4.9624 3.5420 11.4797 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 3: A: 7 B: 6 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 1 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 5: A: 5 B: 4 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 6: A: 1 B: 3 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 7: A: 7 B: 5 C: 1 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 8: A: 3 B: 2 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 9: A: 6 B: 7 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 10: A: 2 B: 0 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 11: A: 4 B: 6 C: 2 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 12: A: 8 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 13: A: 11 B: 9 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 14: A: 12 B: 13 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 15: A: 15 B: 14 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 16: A: 8 B: 9 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 17: A: 13 B: 12 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 18: A: 9 B: 11 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 19: A: 15 B: 13 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 20: A: 11 B: 10 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 21: A: 14 B: 15 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 22: A: 10 B: 8 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 23: A: 12 B: 14 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 0 + } + *MESH { + *TIMEVALUE 1120 + *MESH_NUMVERTEX 16 + *MESH_NUMFACES 24 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 5.0645 -10.6435 20.1926 + *MESH_VERTEX 1 5.6493 -10.6435 20.1926 + *MESH_VERTEX 2 5.0645 1.9791 13.9747 + *MESH_VERTEX 3 5.6493 1.9791 13.9747 + *MESH_VERTEX 4 5.0645 -10.1055 21.2956 + *MESH_VERTEX 5 5.6493 -10.1055 21.2956 + *MESH_VERTEX 6 5.0645 2.5170 15.0777 + *MESH_VERTEX 7 5.6493 2.5170 15.0777 + *MESH_VERTEX 8 -5.5472 -10.6435 20.1926 + *MESH_VERTEX 9 -4.9624 -10.6435 20.1926 + *MESH_VERTEX 10 -5.5472 1.9791 13.9747 + *MESH_VERTEX 11 -4.9624 1.9791 13.9747 + *MESH_VERTEX 12 -5.5472 -10.1055 21.2956 + *MESH_VERTEX 13 -4.9624 -10.1055 21.2956 + *MESH_VERTEX 14 -5.5472 2.5170 15.0777 + *MESH_VERTEX 15 -4.9624 2.5170 15.0777 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 3: A: 7 B: 6 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 1 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 5: A: 5 B: 4 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 6: A: 1 B: 3 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 7: A: 7 B: 5 C: 1 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 8: A: 3 B: 2 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 9: A: 6 B: 7 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 10: A: 2 B: 0 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 11: A: 4 B: 6 C: 2 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 12: A: 8 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 13: A: 11 B: 9 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 14: A: 12 B: 13 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 15: A: 15 B: 14 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 16: A: 8 B: 9 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 17: A: 13 B: 12 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 18: A: 9 B: 11 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 19: A: 15 B: 13 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 20: A: 11 B: 10 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 21: A: 14 B: 15 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 22: A: 10 B: 8 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 23: A: 12 B: 14 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 0 + } + *MESH { + *TIMEVALUE 1280 + *MESH_NUMVERTEX 16 + *MESH_NUMFACES 24 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 5.0645 -15.4384 16.3669 + *MESH_VERTEX 1 5.6493 -15.4384 16.3669 + *MESH_VERTEX 2 5.0645 1.9927 14.5226 + *MESH_VERTEX 3 5.6493 1.9927 14.5226 + *MESH_VERTEX 4 5.0645 -15.3101 17.5873 + *MESH_VERTEX 5 5.6493 -15.3101 17.5873 + *MESH_VERTEX 6 5.0645 2.1209 15.7431 + *MESH_VERTEX 7 5.6493 2.1209 15.7431 + *MESH_VERTEX 8 -5.5472 -15.4384 16.3669 + *MESH_VERTEX 9 -4.9624 -15.4384 16.3669 + *MESH_VERTEX 10 -5.5472 1.9927 14.5226 + *MESH_VERTEX 11 -4.9624 1.9927 14.5226 + *MESH_VERTEX 12 -5.5472 -15.3101 17.5873 + *MESH_VERTEX 13 -4.9624 -15.3101 17.5873 + *MESH_VERTEX 14 -5.5472 2.1209 15.7431 + *MESH_VERTEX 15 -4.9624 2.1209 15.7431 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 3: A: 7 B: 6 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 1 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 5: A: 5 B: 4 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 6: A: 1 B: 3 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 7: A: 7 B: 5 C: 1 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 8: A: 3 B: 2 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 9: A: 6 B: 7 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 10: A: 2 B: 0 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 11: A: 4 B: 6 C: 2 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 12: A: 8 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 13: A: 11 B: 9 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 14: A: 12 B: 13 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 15: A: 15 B: 14 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 16: A: 8 B: 9 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 17: A: 13 B: 12 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 18: A: 9 B: 11 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 19: A: 15 B: 13 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 20: A: 11 B: 10 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 21: A: 14 B: 15 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 22: A: 10 B: 8 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 23: A: 12 B: 14 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 0 + } + *MESH { + *TIMEVALUE 1440 + *MESH_NUMVERTEX 16 + *MESH_NUMFACES 24 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 5.0645 -19.0583 11.4505 + *MESH_VERTEX 1 5.6493 -19.0583 11.4505 + *MESH_VERTEX 2 5.0645 2.0099 14.9183 + *MESH_VERTEX 3 5.6493 2.0099 14.9183 + *MESH_VERTEX 4 5.0645 -19.2608 12.6608 + *MESH_VERTEX 5 5.6493 -19.2608 12.6608 + *MESH_VERTEX 6 5.0645 1.8073 16.1286 + *MESH_VERTEX 7 5.6493 1.8073 16.1286 + *MESH_VERTEX 8 -5.5472 -19.0583 11.4505 + *MESH_VERTEX 9 -4.9624 -19.0583 11.4505 + *MESH_VERTEX 10 -5.5472 2.0099 14.9183 + *MESH_VERTEX 11 -4.9624 2.0099 14.9183 + *MESH_VERTEX 12 -5.5472 -19.2608 12.6608 + *MESH_VERTEX 13 -4.9624 -19.2608 12.6608 + *MESH_VERTEX 14 -5.5472 1.8073 16.1286 + *MESH_VERTEX 15 -4.9624 1.8073 16.1286 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 3: A: 7 B: 6 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 1 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 5: A: 5 B: 4 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 6: A: 1 B: 3 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 7: A: 7 B: 5 C: 1 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 8: A: 3 B: 2 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 9: A: 6 B: 7 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 10: A: 2 B: 0 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 11: A: 4 B: 6 C: 2 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 12: A: 8 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 13: A: 11 B: 9 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 14: A: 12 B: 13 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 15: A: 15 B: 14 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 16: A: 8 B: 9 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 17: A: 13 B: 12 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 18: A: 9 B: 11 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 19: A: 15 B: 13 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 20: A: 11 B: 10 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 21: A: 14 B: 15 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 22: A: 10 B: 8 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 23: A: 12 B: 14 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 0 + } + *MESH { + *TIMEVALUE 1600 + *MESH_NUMVERTEX 16 + *MESH_NUMFACES 24 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 5.0645 -21.4047 5.7018 + *MESH_VERTEX 1 5.6493 -21.4047 5.7018 + *MESH_VERTEX 2 5.0645 2.2307 15.1920 + *MESH_VERTEX 3 5.6493 2.2307 15.1920 + *MESH_VERTEX 4 5.0645 -21.8644 6.8396 + *MESH_VERTEX 5 5.6493 -21.8644 6.8396 + *MESH_VERTEX 6 5.0645 1.7710 16.3298 + *MESH_VERTEX 7 5.6493 1.7710 16.3298 + *MESH_VERTEX 8 -5.5472 -21.4047 5.7018 + *MESH_VERTEX 9 -4.9624 -21.4047 5.7018 + *MESH_VERTEX 10 -5.5472 2.2307 15.1920 + *MESH_VERTEX 11 -4.9624 2.2307 15.1920 + *MESH_VERTEX 12 -5.5472 -21.8644 6.8396 + *MESH_VERTEX 13 -4.9624 -21.8644 6.8396 + *MESH_VERTEX 14 -5.5472 1.7710 16.3298 + *MESH_VERTEX 15 -4.9624 1.7710 16.3298 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 3: A: 7 B: 6 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 1 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 5: A: 5 B: 4 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 6: A: 1 B: 3 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 7: A: 7 B: 5 C: 1 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 8: A: 3 B: 2 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 9: A: 6 B: 7 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 10: A: 2 B: 0 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 11: A: 4 B: 6 C: 2 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 12: A: 8 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 13: A: 11 B: 9 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 14: A: 12 B: 13 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 15: A: 15 B: 14 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 16: A: 8 B: 9 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 17: A: 13 B: 12 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 18: A: 9 B: 11 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 19: A: 15 B: 13 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 20: A: 11 B: 10 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 21: A: 14 B: 15 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 22: A: 10 B: 8 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 23: A: 12 B: 14 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 0 + } + *MESH { + *TIMEVALUE 1760 + *MESH_NUMVERTEX 16 + *MESH_NUMFACES 24 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 5.0645 -22.0266 0.8322 + *MESH_VERTEX 1 5.6493 -22.0266 0.8322 + *MESH_VERTEX 2 5.0645 2.6683 15.6438 + *MESH_VERTEX 3 5.6493 2.6683 15.6438 + *MESH_VERTEX 4 5.0645 -22.6586 1.8841 + *MESH_VERTEX 5 5.6493 -22.6586 1.8841 + *MESH_VERTEX 6 5.0645 2.0362 16.6957 + *MESH_VERTEX 7 5.6493 2.0362 16.6957 + *MESH_VERTEX 8 -5.5472 -22.0266 0.8322 + *MESH_VERTEX 9 -4.9624 -22.0266 0.8322 + *MESH_VERTEX 10 -5.5472 2.6683 15.6438 + *MESH_VERTEX 11 -4.9624 2.6683 15.6438 + *MESH_VERTEX 12 -5.5472 -22.6586 1.8841 + *MESH_VERTEX 13 -4.9624 -22.6586 1.8841 + *MESH_VERTEX 14 -5.5472 2.0362 16.6957 + *MESH_VERTEX 15 -4.9624 2.0362 16.6957 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 3: A: 7 B: 6 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 1 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 5: A: 5 B: 4 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 6: A: 1 B: 3 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 7: A: 7 B: 5 C: 1 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 8: A: 3 B: 2 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 9: A: 6 B: 7 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 10: A: 2 B: 0 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 11: A: 4 B: 6 C: 2 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 12: A: 8 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 13: A: 11 B: 9 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 14: A: 12 B: 13 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 15: A: 15 B: 14 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 16: A: 8 B: 9 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 17: A: 13 B: 12 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 18: A: 9 B: 11 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 19: A: 15 B: 13 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 20: A: 11 B: 10 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 21: A: 14 B: 15 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 22: A: 10 B: 8 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 23: A: 12 B: 14 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 0 + } + *MESH { + *TIMEVALUE 1920 + *MESH_NUMVERTEX 16 + *MESH_NUMFACES 24 + *MESH_VERTEX_LIST { + *MESH_VERTEX 0 5.0645 -22.0380 -1.5503 + *MESH_VERTEX 1 5.6493 -22.0380 -1.5503 + *MESH_VERTEX 2 5.0645 2.6351 15.7672 + *MESH_VERTEX 3 5.6493 2.6351 15.7672 + *MESH_VERTEX 4 5.0645 -22.7418 -0.5451 + *MESH_VERTEX 5 5.6493 -22.7418 -0.5451 + *MESH_VERTEX 6 5.0645 1.9312 16.7724 + *MESH_VERTEX 7 5.6493 1.9312 16.7724 + *MESH_VERTEX 8 -5.5472 -22.0380 -1.5503 + *MESH_VERTEX 9 -4.9624 -22.0380 -1.5503 + *MESH_VERTEX 10 -5.5472 2.6351 15.7672 + *MESH_VERTEX 11 -4.9624 2.6351 15.7672 + *MESH_VERTEX 12 -5.5472 -22.7418 -0.5451 + *MESH_VERTEX 13 -4.9624 -22.7418 -0.5451 + *MESH_VERTEX 14 -5.5472 1.9312 16.7724 + *MESH_VERTEX 15 -4.9624 1.9312 16.7724 + } + *MESH_FACE_LIST { + *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 3: A: 7 B: 6 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 4: A: 0 B: 1 C: 5 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 5: A: 5 B: 4 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 6: A: 1 B: 3 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 7: A: 7 B: 5 C: 1 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 8: A: 3 B: 2 C: 6 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 9: A: 6 B: 7 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 10: A: 2 B: 0 C: 4 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 11: A: 4 B: 6 C: 2 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 12: A: 8 B: 10 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 13: A: 11 B: 9 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 + *MESH_FACE 14: A: 12 B: 13 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 15: A: 15 B: 14 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 + *MESH_FACE 16: A: 8 B: 9 C: 13 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 17: A: 13 B: 12 C: 8 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 4 *MESH_MTLID 4 + *MESH_FACE 18: A: 9 B: 11 C: 15 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 19: A: 15 B: 13 C: 9 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 5 *MESH_MTLID 3 + *MESH_FACE 20: A: 11 B: 10 C: 14 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 21: A: 14 B: 15 C: 11 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 6 *MESH_MTLID 5 + *MESH_FACE 22: A: 10 B: 8 C: 12 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + *MESH_FACE 23: A: 12 B: 14 C: 10 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 7 *MESH_MTLID 2 + } + *MESH_NUMTVERTEX 0 + *MESH_NUMCVERTEX 0 + } + } +} diff --git a/examples/src/ssg/viewer/data/embossed_herring.bmp b/examples/src/ssg/viewer/data/embossed_herring.bmp new file mode 100644 index 0000000..795e5d1 Binary files /dev/null and b/examples/src/ssg/viewer/data/embossed_herring.bmp differ diff --git a/examples/src/ssg/viewer/data/gray.bmp b/examples/src/ssg/viewer/data/gray.bmp new file mode 100644 index 0000000..3c4376b Binary files /dev/null and b/examples/src/ssg/viewer/data/gray.bmp differ diff --git a/examples/src/ssg/viewer/data/pedestal.ac b/examples/src/ssg/viewer/data/pedestal.ac new file mode 100644 index 0000000..3c112e2 --- /dev/null +++ b/examples/src/ssg/viewer/data/pedestal.ac @@ -0,0 +1,81 @@ +AC3Db +MATERIAL "" rgb 1 1 1 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "" rgb 1 1 1 amb 0.2 0.2 0.2 emis 1 1 1 spec 0.502 0.502 0.502 shi 0 trans 0 +OBJECT world +kids 2 +OBJECT poly +name "box" +texture "wood.rgb" +texrep 5 5 +numvert 8 +-1.29615 -0.6 -1.29615 +-1 0 -1 +1 0 -1 +1.3 -0.6 -1.29615 +-1.29615 -0.6 1.3 +-1 0 1 +1 0 1 +1.3 -0.6 1.3 +numsurf 6 +SURF 0x0 +mat 0 +refs 4 +0 0 0 +1 0.114074 0.114074 +2 0.884445 0.114074 +3 1 0 +SURF 0x0 +mat 0 +refs 4 +6 0.884445 0.884445 +7 1 1 +3 1 0 +2 0.884445 0.114074 +SURF 0x0 +mat 0 +refs 4 +7 1 1 +6 0.884445 0.884445 +5 0.114074 0.884445 +4 0 1 +SURF 0x0 +mat 0 +refs 4 +4 0 1 +5 0.114074 0.884445 +1 0.114074 0.114074 +0 0 0 +SURF 0x0 +mat 0 +refs 4 +1 0.114074 0.114074 +5 0.114074 0.884445 +6 0.884445 0.884445 +2 0.884445 0.114074 +SURF 0x0 +mat 0 +refs 4 +4 0 1 +0 0 0 +3 1 0 +7 1 1 +kids 0 +OBJECT poly +name "rect" +loc -0.0500002 0 -2.5 +texture "embossed_herring.bmp" +texrep 20 30 +numvert 4 +-17.95 -0.7 -18.6 +17.95 -0.7 -18.6 +17.95 -0.7 18.6 +-17.95 -0.7 18.6 +numsurf 1 +SURF 0x0 +mat 1 +refs 4 +3 0 0 +2 1 0 +1 1 1 +0 0 1 +kids 0 diff --git a/examples/src/ssg/viewer/data/plane.3ds b/examples/src/ssg/viewer/data/plane.3ds new file mode 100644 index 0000000..b1482f8 Binary files /dev/null and b/examples/src/ssg/viewer/data/plane.3ds differ diff --git a/examples/src/ssg/viewer/data/plib.ac b/examples/src/ssg/viewer/data/plib.ac new file mode 100644 index 0000000..17e479f --- /dev/null +++ b/examples/src/ssg/viewer/data/plib.ac @@ -0,0 +1,589 @@ +AC3Db +MATERIAL "ac3dmat3" rgb 1 0 0 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "ac3dmat5" rgb 1 1 0 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "ac3dmat6" rgb 0 1 0 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "ac3dmat9" rgb 0 0 1 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +OBJECT world +kids 1 +OBJECT poly +name "poly" +loc 0.05 -0.05 0.15 +numvert 64 +-1.85 -0.25 1.05 +-1.45 -0.25 0.45 +-1.45 -0.25 1.05 +-1.15 -0.25 0.35 +-0.85 -0.25 -0.15 +-0.95 -0.25 0.15 +-0.85 -0.25 -0.45 +-1.45 0.25 1.05 +-1.45 0.25 0.45 +-1.85 0.25 1.05 +-0.95 0.25 0.15 +-0.85 0.25 -0.15 +-1.15 0.25 0.35 +-0.85 0.25 -0.45 +0.05 -0.25 0.75 +-0.35 -0.25 0.75 +0.05 -0.25 1.05 +-0.75 -0.25 1.05 +0.05 0.25 1.05 +-0.35 0.25 0.75 +0.05 0.25 0.75 +-0.75 0.25 1.05 +0.25 -0.25 1.05 +0.25 0.25 1.05 +0.65 0.25 1.05 +0.65 -0.25 1.05 +0.85 -0.25 1.05 +0.85 0.25 1.05 +1.25 0.25 1.05 +1.25 -0.25 1.05 +1.55 0.25 0.95 +1.55 -0.25 0.95 +1.75 0.25 0.75 +1.75 -0.25 0.75 +1.85 0.25 0.45 +1.85 -0.25 0.45 +1.85 0.25 0.15 +1.85 -0.25 0.15 +1.75 0.25 -0.15 +1.75 -0.25 -0.15 +1.55 0.25 -0.35 +1.55 -0.25 -0.35 +1.25 0.25 -0.45 +1.25 -0.25 -0.45 +-1.85 -0.25 -1.05 +-1.45 -0.25 -1.05 +-0.95 -0.25 -0.75 +-1.15 -0.25 -0.95 +-1.85 0.25 -1.05 +-1.45 0.25 -1.05 +-1.15 0.25 -0.95 +-0.95 0.25 -0.75 +-0.35 -0.25 -1.05 +-0.75 -0.25 -1.05 +-0.75 0.25 -1.05 +-0.35 0.25 -1.05 +0.65 -0.25 -1.05 +0.25 -0.25 -1.05 +0.65 0.25 -1.05 +0.25 0.25 -1.05 +1.25 -0.25 -1.05 +0.85 -0.25 -1.05 +1.25 0.25 -1.05 +0.85 0.25 -1.05 +numsurf 80 +SURF 0x20 +mat 0 +refs 3 +0 0 -5.67663e-08 +1 0.4 0.285714 +2 0.4 -5.67663e-08 +SURF 0x20 +mat 0 +refs 3 +3 0.7 0.333333 +4 1 0.571429 +5 0.9 0.428571 +SURF 0x20 +mat 0 +refs 3 +1 0.4 0.285714 +4 1 0.571429 +3 0.7 0.333333 +SURF 0x20 +mat 0 +refs 3 +1 0.4 0.285714 +6 1 0.714286 +4 1 0.571429 +SURF 0x20 +mat 0 +refs 3 +7 0 0 +8 0 0 +9 0 0 +SURF 0x20 +mat 0 +refs 3 +10 0 0 +11 0 0 +12 0 0 +SURF 0x20 +mat 0 +refs 3 +12 0 0 +11 0 0 +8 0 0 +SURF 0x20 +mat 0 +refs 3 +11 0 0 +13 0 0 +8 0 0 +SURF 0x20 +mat 0 +refs 4 +1 0 0 +8 0 0 +7 0 0 +2 0 0 +SURF 0x20 +mat 0 +refs 4 +2 0 0 +7 0 0 +9 0 0 +0 0 0 +SURF 0x20 +mat 0 +refs 4 +4 0 0 +11 0 0 +10 0 0 +5 0 0 +SURF 0x20 +mat 0 +refs 4 +5 0 0 +10 0 0 +12 0 0 +3 0 0 +SURF 0x20 +mat 0 +refs 4 +3 0 0 +12 0 0 +8 0 0 +1 0 0 +SURF 0x20 +mat 0 +refs 4 +6 0 0 +13 0 0 +11 0 0 +4 0 0 +SURF 0x20 +mat 1 +refs 3 +14 1 0.142857 +15 0.5 0.142857 +16 1 -5.67663e-08 +SURF 0x20 +mat 1 +refs 3 +16 1 -5.67663e-08 +15 0.5 0.142857 +17 0 -5.67663e-08 +SURF 0x20 +mat 1 +refs 3 +18 0 0 +19 0 0 +20 0 0 +SURF 0x20 +mat 1 +refs 3 +21 0 0 +19 0 0 +18 0 0 +SURF 0x20 +mat 1 +refs 4 +14 0 0 +20 0 0 +19 0 0 +15 0 0 +SURF 0x20 +mat 1 +refs 4 +16 0 0 +18 0 0 +20 0 0 +14 0 0 +SURF 0x20 +mat 1 +refs 4 +17 0 0 +21 0 0 +18 0 0 +16 0 0 +SURF 0x20 +mat 2 +refs 4 +22 0 0 +23 0 0 +24 0 0 +25 0 0 +SURF 0x20 +mat 3 +refs 4 +26 0 0 +27 0 0 +28 0 0 +29 0 0 +SURF 0x20 +mat 3 +refs 4 +29 0 0 +28 0 0 +30 0 0 +31 0 0 +SURF 0x20 +mat 3 +refs 4 +31 0 0 +30 0 0 +32 0 0 +33 0 0 +SURF 0x20 +mat 3 +refs 4 +33 0 0 +32 0 0 +34 0 0 +35 0 0 +SURF 0x20 +mat 3 +refs 4 +35 0 0 +34 0 0 +36 0 0 +37 0 0 +SURF 0x20 +mat 3 +refs 4 +37 0 0 +36 0 0 +38 0 0 +39 0 0 +SURF 0x20 +mat 3 +refs 4 +39 0 0 +38 0 0 +40 0 0 +41 0 0 +SURF 0x20 +mat 3 +refs 4 +41 0 0 +40 0 0 +42 0 0 +43 0 0 +SURF 0x20 +mat 3 +refs 3 +26 0 1 +29 0.4 1 +43 0.4 0.285714 +SURF 0x20 +mat 3 +refs 3 +31 0.7 0.952381 +33 0.9 0.857143 +29 0.4 1 +SURF 0x20 +mat 3 +refs 3 +29 0.4 1 +33 0.9 0.857143 +43 0.4 0.285714 +SURF 0x20 +mat 3 +refs 3 +41 0.7 0.333333 +43 0.4 0.285714 +39 0.9 0.428571 +SURF 0x20 +mat 3 +refs 3 +39 0.9 0.428571 +43 0.4 0.285714 +37 1 0.571429 +SURF 0x20 +mat 3 +refs 3 +37 1 0.571429 +43 0.4 0.285714 +35 1 0.714286 +SURF 0x20 +mat 3 +refs 3 +33 0.9 0.857143 +35 1 0.714286 +43 0.4 0.285714 +SURF 0x20 +mat 3 +refs 3 +42 0 0 +28 0 0 +27 0 0 +SURF 0x20 +mat 3 +refs 3 +28 0 0 +32 0 0 +30 0 0 +SURF 0x20 +mat 3 +refs 3 +42 0 0 +32 0 0 +28 0 0 +SURF 0x20 +mat 3 +refs 3 +38 0 0 +42 0 0 +40 0 0 +SURF 0x20 +mat 3 +refs 3 +36 0 0 +42 0 0 +38 0 0 +SURF 0x20 +mat 3 +refs 3 +34 0 0 +42 0 0 +36 0 0 +SURF 0x20 +mat 3 +refs 3 +42 0 0 +34 0 0 +32 0 0 +SURF 0x20 +mat 0 +refs 3 +44 0 1 +1 0.4 0.285714 +0 0 -5.67663e-08 +SURF 0x20 +mat 0 +refs 3 +45 0.4 1 +1 0.4 0.285714 +44 0 1 +SURF 0x20 +mat 0 +refs 3 +46 0.9 0.857143 +45 0.4 1 +47 0.7 0.952381 +SURF 0x20 +mat 0 +refs 3 +46 0.9 0.857143 +1 0.4 0.285714 +45 0.4 1 +SURF 0x20 +mat 0 +refs 3 +46 0.9 0.857143 +6 1 0.714286 +1 0.4 0.285714 +SURF 0x20 +mat 0 +refs 3 +9 0 0 +8 0 0 +48 0 0 +SURF 0x20 +mat 0 +refs 3 +48 0 0 +8 0 0 +49 0 0 +SURF 0x20 +mat 0 +refs 3 +50 0 0 +49 0 0 +51 0 0 +SURF 0x20 +mat 0 +refs 3 +49 0 0 +8 0 0 +51 0 0 +SURF 0x20 +mat 0 +refs 3 +8 0 0 +13 0 0 +51 0 0 +SURF 0x20 +mat 0 +refs 4 +0 0 0 +9 0 0 +48 0 0 +44 0 0 +SURF 0x20 +mat 0 +refs 4 +44 0 0 +48 0 0 +49 0 0 +45 0 0 +SURF 0x20 +mat 0 +refs 4 +45 0 0 +49 0 0 +50 0 0 +47 0 0 +SURF 0x20 +mat 0 +refs 4 +47 0 0 +50 0 0 +51 0 0 +46 0 0 +SURF 0x20 +mat 0 +refs 4 +46 0 0 +51 0 0 +13 0 0 +6 0 0 +SURF 0x20 +mat 1 +refs 3 +52 0.5 1 +53 0 1 +15 0.5 0.142857 +SURF 0x20 +mat 1 +refs 3 +15 0.5 0.142857 +53 0 1 +17 0 -5.67663e-08 +SURF 0x20 +mat 1 +refs 3 +19 0 0 +54 0 0 +55 0 0 +SURF 0x20 +mat 1 +refs 3 +21 0 0 +54 0 0 +19 0 0 +SURF 0x20 +mat 1 +refs 4 +52 0 0 +55 0 0 +54 0 0 +53 0 0 +SURF 0x20 +mat 1 +refs 4 +15 0 0 +19 0 0 +55 0 0 +52 0 0 +SURF 0x20 +mat 1 +refs 4 +53 0 0 +54 0 0 +21 0 0 +17 0 0 +SURF 0x20 +mat 2 +refs 3 +25 1 -5.67663e-08 +56 1 1 +22 0 -5.67663e-08 +SURF 0x20 +mat 2 +refs 3 +56 1 1 +57 0 1 +22 0 -5.67663e-08 +SURF 0x20 +mat 2 +refs 3 +23 0 0 +58 0 0 +24 0 0 +SURF 0x20 +mat 2 +refs 3 +23 0 0 +59 0 0 +58 0 0 +SURF 0x20 +mat 2 +refs 4 +25 0 0 +24 0 0 +58 0 0 +56 0 0 +SURF 0x20 +mat 2 +refs 4 +56 0 0 +58 0 0 +59 0 0 +57 0 0 +SURF 0x20 +mat 2 +refs 4 +57 0 0 +59 0 0 +23 0 0 +22 0 0 +SURF 0x20 +mat 3 +refs 3 +60 0.4 -5.67663e-08 +61 0 -5.67663e-08 +43 0.4 0.285714 +SURF 0x20 +mat 3 +refs 3 +61 0 -5.67663e-08 +26 0 1 +43 0.4 0.285714 +SURF 0x20 +mat 3 +refs 3 +62 0 0 +63 0 0 +42 0 0 +SURF 0x20 +mat 3 +refs 3 +63 0 0 +27 0 0 +42 0 0 +SURF 0x20 +mat 3 +refs 4 +61 0 0 +63 0 0 +27 0 0 +26 0 0 +SURF 0x20 +mat 3 +refs 4 +43 0 0 +42 0 0 +62 0 0 +60 0 0 +SURF 0x20 +mat 3 +refs 4 +60 0 0 +62 0 0 +63 0 0 +61 0 0 +kids 0 diff --git a/examples/src/ssg/viewer/data/sorority.txf b/examples/src/ssg/viewer/data/sorority.txf new file mode 100644 index 0000000..8b457aa Binary files /dev/null and b/examples/src/ssg/viewer/data/sorority.txf differ diff --git a/examples/src/ssg/viewer/data/test.ac b/examples/src/ssg/viewer/data/test.ac new file mode 100644 index 0000000..3c112e2 --- /dev/null +++ b/examples/src/ssg/viewer/data/test.ac @@ -0,0 +1,81 @@ +AC3Db +MATERIAL "" rgb 1 1 1 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "" rgb 1 1 1 amb 0.2 0.2 0.2 emis 1 1 1 spec 0.502 0.502 0.502 shi 0 trans 0 +OBJECT world +kids 2 +OBJECT poly +name "box" +texture "wood.rgb" +texrep 5 5 +numvert 8 +-1.29615 -0.6 -1.29615 +-1 0 -1 +1 0 -1 +1.3 -0.6 -1.29615 +-1.29615 -0.6 1.3 +-1 0 1 +1 0 1 +1.3 -0.6 1.3 +numsurf 6 +SURF 0x0 +mat 0 +refs 4 +0 0 0 +1 0.114074 0.114074 +2 0.884445 0.114074 +3 1 0 +SURF 0x0 +mat 0 +refs 4 +6 0.884445 0.884445 +7 1 1 +3 1 0 +2 0.884445 0.114074 +SURF 0x0 +mat 0 +refs 4 +7 1 1 +6 0.884445 0.884445 +5 0.114074 0.884445 +4 0 1 +SURF 0x0 +mat 0 +refs 4 +4 0 1 +5 0.114074 0.884445 +1 0.114074 0.114074 +0 0 0 +SURF 0x0 +mat 0 +refs 4 +1 0.114074 0.114074 +5 0.114074 0.884445 +6 0.884445 0.884445 +2 0.884445 0.114074 +SURF 0x0 +mat 0 +refs 4 +4 0 1 +0 0 0 +3 1 0 +7 1 1 +kids 0 +OBJECT poly +name "rect" +loc -0.0500002 0 -2.5 +texture "embossed_herring.bmp" +texrep 20 30 +numvert 4 +-17.95 -0.7 -18.6 +17.95 -0.7 -18.6 +17.95 -0.7 18.6 +-17.95 -0.7 18.6 +numsurf 1 +SURF 0x0 +mat 1 +refs 4 +3 0 0 +2 1 0 +1 1 1 +0 0 1 +kids 0 diff --git a/examples/src/ssg/viewer/data/tuxedo.ac b/examples/src/ssg/viewer/data/tuxedo.ac new file mode 100644 index 0000000..12e4754 --- /dev/null +++ b/examples/src/ssg/viewer/data/tuxedo.ac @@ -0,0 +1,1695 @@ +AC3Db +MATERIAL "" rgb 0 0 0 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0 +MATERIAL "" rgb 1 0.702 0 amb 1 0.702 0 emis 0 0 0 spec 0 0 0 shi 0 trans 0 +MATERIAL "" rgb 1 1 1 amb 1 1 1 emis 0 0 0 spec 0 0 0 shi 0 trans 0 +OBJECT world +kids 1 +OBJECT group +name "Tuxedo.T.Penguin" +kids 3 +OBJECT poly +name "tuxfeet" +loc 0.0203744 -0.479517 0.101666 +numvert 14 +-0.0744405 0.473224 0.119889 +0.100559 0.473224 -0.200111 +0.175559 0.473224 0.199889 +0.250559 0.473224 -0.200111 +0.425559 0.473224 0.119889 +0.250559 0.523224 -0.200111 +0.100559 0.523224 -0.200111 +-0.425559 0.476776 0.120111 +-0.25056 0.476776 -0.199889 +-0.17556 0.476776 0.200111 +-0.100559 0.476776 -0.199889 +0.0744405 0.476776 0.120111 +-0.100559 0.526776 -0.199889 +-0.25056 0.526776 -0.199889 +numsurf 12 +SURF 0x0 +mat 1 +refs 3 +0 0 0.1 +1 0.9 0 +2 0 0.8 +SURF 0x0 +mat 1 +refs 3 +3 1 0.1 +2 0 0.8 +1 0.9 0 +SURF 0x0 +mat 1 +refs 3 +2 0 0.8 +3 1 0.1 +4 0.5 1 +SURF 0x0 +mat 1 +refs 3 +4 0.5 1 +5 1 0.1 +2 0 0.8 +SURF 0x0 +mat 1 +refs 3 +6 0.9 0 +2 0 0.8 +5 1 0.1 +SURF 0x0 +mat 1 +refs 3 +2 0 0.8 +6 0.9 0 +0 0 0.1 +SURF 0x0 +mat 1 +refs 3 +7 0 0.1 +8 0.9 0 +9 0 0.8 +SURF 0x0 +mat 1 +refs 3 +10 1 0.1 +9 0 0.8 +8 0.9 0 +SURF 0x0 +mat 1 +refs 3 +9 0 0.8 +10 1 0.1 +11 0.5 1 +SURF 0x0 +mat 1 +refs 3 +11 0.5 1 +12 1 0.1 +9 0 0.8 +SURF 0x0 +mat 1 +refs 3 +13 0.9 0 +9 0 0.8 +12 1 0.1 +SURF 0x0 +mat 1 +refs 3 +9 0 0.8 +13 0.9 0 +7 0 0.1 +kids 0 +OBJECT poly +name "tuxbody" +loc 0.0124385 0.107258 -0.188333 +texture "Penguin_body.rgb" +numvert 115 +0.097524 1.07 -0.0756895 +-0.0202512 1.11 0 +0.119749 1.07 0 +0.0379068 1.07 -0.127348 +-0.0401753 1.07 -0.138575 +-0.111932 1.07 -0.105805 +-0.154581 1.07 -0.0394426 +-0.154581 1.07 0.0394426 +-0.111932 1.07 0.105805 +-0.0401753 1.07 0.138575 +0.0379068 1.07 0.127348 +0.097524 1.07 0.0756895 +0.184749 0.975 0 +0.152205 0.975 -0.110831 +0.064909 0.975 -0.186475 +-0.0494259 0.975 -0.202913 +-0.154498 0.975 -0.154929 +-0.216947 0.975 -0.057755 +-0.216947 0.975 0.057755 +-0.154498 0.975 0.154929 +-0.0494259 0.975 0.202913 +0.064909 0.975 0.186475 +0.152205 0.975 0.110831 +0.199749 0.68 0 +0.164825 0.68 -0.118941 +0.07114 0.68 -0.200119 +-0.0515605 0.68 -0.217761 +-0.16432 0.68 -0.166265 +-0.231339 0.68 -0.061981 +-0.231339 0.68 0.061981 +-0.16432 0.68 0.166265 +-0.0515605 0.68 0.217761 +0.07114 0.68 0.200119 +0.164825 0.68 0.118941 +0.284749 0.555 0 +0.236331 0.555 -0.164896 +0.10645 0.555 -0.277438 +-0.0636575 0.555 -0.301895 +-0.219984 0.555 -0.230503 +-0.312897 0.555 -0.0859285 +-0.312897 0.555 0.0859285 +-0.219984 0.555 0.230503 +-0.0636575 0.555 0.301895 +0.10645 0.555 0.277438 +0.236331 0.555 0.164896 +0.369749 0.43 0 +0.307837 0.43 -0.21085 +0.14176 0.43 -0.354757 +-0.075754 0.43 -0.38603 +-0.275647 0.43 -0.294742 +-0.394453 0.43 -0.109876 +-0.394453 0.43 0.109876 +-0.275647 0.43 0.294742 +-0.075754 0.43 0.38603 +0.14176 0.43 0.354757 +0.307837 0.43 0.21085 +0.414749 0.305 0 +0.345694 0.305 -0.235179 +0.160454 0.305 -0.39569 +-0.0821585 0.305 -0.430573 +-0.305115 0.305 -0.328751 +-0.437631 0.305 -0.122553 +-0.437631 0.305 0.122553 +-0.305115 0.305 0.328751 +-0.0821585 0.305 0.430573 +0.160454 0.305 0.39569 +0.345694 0.305 0.235179 +0.409749 0.185 0 +0.341488 0.185 -0.232476 +0.158377 0.185 -0.391142 +-0.081447 0.185 -0.425623 +-0.301841 0.185 -0.324973 +-0.432833 0.185 -0.121145 +-0.432833 0.185 0.121145 +-0.301841 0.185 0.324973 +-0.081447 0.185 0.425623 +0.158377 0.185 0.391142 +0.341488 0.185 0.232476 +0.354748 2.23517e-08 0 +0.295219 2.23517e-08 -0.202741 +0.135529 2.23517e-08 -0.341112 +-0.0736195 2.23517e-08 -0.371183 +-0.265824 2.23517e-08 -0.283406 +-0.380061 2.23517e-08 -0.10565 +-0.380061 2.23517e-08 0.10565 +-0.265824 2.23517e-08 0.283406 +-0.0736195 2.23517e-08 0.371183 +0.135529 2.23517e-08 0.341112 +0.295219 2.23517e-08 0.202741 +0.154748 -0.1 0 +0.126968 -0.1 -0.094612 +0.052446 -0.1 -0.159185 +-0.0451563 -0.1 -0.173219 +-0.134852 -0.1 -0.132256 +-0.188163 -0.1 -0.0493032 +-0.188163 -0.1 0.0493032 +-0.134852 -0.1 0.132256 +-0.0451564 -0.1 0.173219 +0.052446 -0.1 0.159185 +0.126968 -0.1 0.094612 +0.211872 0.567025 0.1 +0.211872 0.567025 -0.1 +0.316872 0.532025 0.1 +0.316872 0.532025 -0.1 +0.456872 0.392025 0.1 +0.456872 0.392025 -0.1 +0.56187 0.217025 0 +-0.211873 0.58637 0.1 +-0.211873 0.58637 -0.1 +-0.316873 0.55137 0.1 +-0.316873 0.55137 -0.1 +-0.456872 0.41137 0.1 +-0.456872 0.41137 -0.1 +-0.56187 0.23637 0 +-0.0202512 -0.11 0 +numsurf 218 +SURF 0x10 +mat 2 +refs 3 +0 -1 0.967213 +1 -1 1 +2 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +3 -1 0.967213 +1 -1 1 +0 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +4 -1 0.967213 +1 -1 1 +3 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +5 -1 0.967213 +1 -1 1 +4 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +6 -1 0.967213 +1 -1 1 +5 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +7 -0.614934 0.967213 +1 -0.5 1 +6 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +8 -0.578443 0.967213 +1 -0.5 1 +7 -0.614934 0.967213 +SURF 0x10 +mat 2 +refs 3 +9 -0.517047 0.967213 +1 -0.5 1 +8 -0.578443 0.967213 +SURF 0x10 +mat 2 +refs 3 +10 -0.450239 0.967213 +1 -0.5 1 +9 -0.517047 0.967213 +SURF 0x10 +mat 2 +refs 3 +11 -0.39923 0.967213 +1 -0.5 1 +10 -0.450239 0.967213 +SURF 0x10 +mat 2 +refs 3 +2 -0.380214 0.967213 +1 -0.5 1 +11 -0.39923 0.967213 +SURF 0x10 +mat 2 +refs 3 +2 -1 0.967213 +12 -1 0.889344 +0 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +13 -1 0.889344 +0 -1 0.967213 +12 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +0 -1 0.967213 +13 -1 0.889344 +3 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +14 -1 0.889344 +3 -1 0.967213 +13 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +3 -1 0.967213 +14 -1 0.889344 +4 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +15 -1 0.889344 +4 -1 0.967213 +14 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +4 -1 0.967213 +15 -1 0.889344 +5 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +16 -1 0.889344 +5 -1 0.967213 +15 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +5 -1 0.967213 +16 -1 0.889344 +6 -1 0.967213 +SURF 0x10 +mat 2 +refs 3 +17 -1 0.889344 +6 -1 0.967213 +16 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +6 -1 0.967213 +17 -1 0.889344 +7 -0.614934 0.967213 +SURF 0x10 +mat 2 +refs 3 +18 -0.668296 0.889344 +7 -0.614934 0.967213 +17 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +7 -0.614934 0.967213 +18 -0.668296 0.889344 +8 -0.578443 0.967213 +SURF 0x10 +mat 2 +refs 3 +19 -0.614863 0.889344 +8 -0.578443 0.967213 +18 -0.668296 0.889344 +SURF 0x10 +mat 2 +refs 3 +8 -0.578443 0.967213 +19 -0.614863 0.889344 +9 -0.517047 0.967213 +SURF 0x10 +mat 2 +refs 3 +20 -0.524962 0.889344 +9 -0.517047 0.967213 +19 -0.614863 0.889344 +SURF 0x10 +mat 2 +refs 3 +9 -0.517047 0.967213 +20 -0.524962 0.889344 +10 -0.450239 0.967213 +SURF 0x10 +mat 2 +refs 3 +21 -0.427136 0.889344 +10 -0.450239 0.967213 +20 -0.524962 0.889344 +SURF 0x10 +mat 2 +refs 3 +10 -0.450239 0.967213 +21 -0.427136 0.889344 +11 -0.39923 0.967213 +SURF 0x10 +mat 2 +refs 3 +22 -0.352443 0.889344 +11 -0.39923 0.967213 +21 -0.427136 0.889344 +SURF 0x10 +mat 2 +refs 3 +11 -0.39923 0.967213 +22 -0.352443 0.889344 +2 -0.380214 0.967213 +SURF 0x10 +mat 2 +refs 3 +12 -0.324599 0.889344 +2 -0.380214 0.967213 +22 -0.352443 0.889344 +SURF 0x10 +mat 2 +refs 3 +12 -1 0.889344 +23 -1 0.647541 +13 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +24 -1 0.647541 +13 -1 0.889344 +23 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +13 -1 0.889344 +24 -1 0.647541 +14 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +25 -1 0.647541 +14 -1 0.889344 +24 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +14 -1 0.889344 +25 -1 0.647541 +15 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +26 -1 0.647541 +15 -1 0.889344 +25 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +15 -1 0.889344 +26 -1 0.647541 +16 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +27 -1 0.647541 +16 -1 0.889344 +26 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +16 -1 0.889344 +27 -1 0.647541 +17 -1 0.889344 +SURF 0x10 +mat 2 +refs 3 +28 -1 0.647541 +17 -1 0.889344 +27 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +17 -1 0.889344 +28 -1 0.647541 +18 -0.668296 0.889344 +SURF 0x10 +mat 2 +refs 3 +29 -0.68061 0.647541 +18 -0.668296 0.889344 +28 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +18 -0.668296 0.889344 +29 -0.68061 0.647541 +19 -0.614863 0.889344 +SURF 0x10 +mat 2 +refs 3 +30 -0.623268 0.647541 +19 -0.614863 0.889344 +29 -0.68061 0.647541 +SURF 0x10 +mat 2 +refs 3 +19 -0.614863 0.889344 +30 -0.623268 0.647541 +20 -0.524962 0.889344 +SURF 0x10 +mat 2 +refs 3 +31 -0.526789 0.647541 +20 -0.524962 0.889344 +30 -0.623268 0.647541 +SURF 0x10 +mat 2 +refs 3 +20 -0.524962 0.889344 +31 -0.526789 0.647541 +21 -0.427136 0.889344 +SURF 0x10 +mat 2 +refs 3 +32 -0.421804 0.647541 +21 -0.427136 0.889344 +31 -0.526789 0.647541 +SURF 0x10 +mat 2 +refs 3 +21 -0.427136 0.889344 +32 -0.421804 0.647541 +22 -0.352443 0.889344 +SURF 0x10 +mat 2 +refs 3 +33 -0.341646 0.647541 +22 -0.352443 0.889344 +32 -0.421804 0.647541 +SURF 0x10 +mat 2 +refs 3 +22 -0.352443 0.889344 +33 -0.341646 0.647541 +12 -0.324599 0.889344 +SURF 0x10 +mat 2 +refs 3 +23 -0.311765 0.647541 +12 -0.324599 0.889344 +33 -0.341646 0.647541 +SURF 0x10 +mat 2 +refs 3 +23 -1 0.647541 +34 -1 0.545082 +24 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +35 -1 0.545082 +24 -1 0.647541 +34 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +24 -1 0.647541 +35 -1 0.545082 +25 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +36 -1 0.545082 +25 -1 0.647541 +35 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +25 -1 0.647541 +36 -1 0.545082 +26 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +37 -1 0.545082 +26 -1 0.647541 +36 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +26 -1 0.647541 +37 -1 0.545082 +27 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +38 -1 0.545082 +27 -1 0.647541 +37 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +27 -1 0.647541 +38 -1 0.545082 +28 -1 0.647541 +SURF 0x10 +mat 2 +refs 3 +39 -1 0.545082 +28 -1 0.647541 +38 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +28 -1 0.647541 +39 -1 0.545082 +29 -0.68061 0.647541 +SURF 0x10 +mat 2 +refs 3 +40 -0.750392 0.545082 +29 -0.68061 0.647541 +39 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +29 -0.68061 0.647541 +40 -0.750392 0.545082 +30 -0.623268 0.647541 +SURF 0x10 +mat 2 +refs 3 +41 -0.670894 0.545082 +30 -0.623268 0.647541 +40 -0.750392 0.545082 +SURF 0x10 +mat 2 +refs 3 +30 -0.623268 0.647541 +41 -0.670894 0.545082 +31 -0.526789 0.647541 +SURF 0x10 +mat 2 +refs 3 +42 -0.537139 0.545082 +31 -0.526789 0.647541 +41 -0.670894 0.545082 +SURF 0x10 +mat 2 +refs 3 +31 -0.526789 0.647541 +42 -0.537139 0.545082 +32 -0.421804 0.647541 +SURF 0x10 +mat 2 +refs 3 +43 -0.391592 0.545082 +32 -0.421804 0.647541 +42 -0.537139 0.545082 +SURF 0x10 +mat 2 +refs 3 +32 -0.421804 0.647541 +43 -0.391592 0.545082 +33 -0.341646 0.647541 +SURF 0x10 +mat 2 +refs 3 +44 -0.280464 0.545082 +33 -0.341646 0.647541 +43 -0.391592 0.545082 +SURF 0x10 +mat 2 +refs 3 +33 -0.341646 0.647541 +44 -0.280464 0.545082 +23 -0.311765 0.647541 +SURF 0x10 +mat 2 +refs 3 +34 -0.239037 0.545082 +23 -0.311765 0.647541 +44 -0.280464 0.545082 +SURF 0x10 +mat 2 +refs 3 +34 -1 0.545082 +45 -1 0.442623 +35 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +46 -1 0.442623 +35 -1 0.545082 +45 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +35 -1 0.545082 +46 -1 0.442623 +36 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +47 -1 0.442623 +36 -1 0.545082 +46 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +36 -1 0.545082 +47 -1 0.442623 +37 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +48 -1 0.442623 +37 -1 0.545082 +47 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +37 -1 0.545082 +48 -1 0.442623 +38 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +49 -1 0.442623 +38 -1 0.545082 +48 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +38 -1 0.545082 +49 -1 0.442623 +39 -1 0.545082 +SURF 0x10 +mat 2 +refs 3 +50 -1 0.442623 +39 -1 0.545082 +49 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +39 -1 0.545082 +50 -1 0.442623 +40 -0.750392 0.545082 +SURF 0x10 +mat 2 +refs 3 +51 -0.820173 0.442623 +40 -0.750392 0.545082 +50 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +40 -0.750392 0.545082 +51 -0.820173 0.442623 +41 -0.670894 0.545082 +SURF 0x10 +mat 2 +refs 3 +52 -0.71852 0.442623 +41 -0.670894 0.545082 +51 -0.820173 0.442623 +SURF 0x10 +mat 2 +refs 3 +41 -0.670894 0.545082 +52 -0.71852 0.442623 +42 -0.537139 0.545082 +SURF 0x10 +mat 2 +refs 3 +53 -0.547489 0.442623 +42 -0.537139 0.545082 +52 -0.71852 0.442623 +SURF 0x10 +mat 2 +refs 3 +42 -0.537139 0.545082 +53 -0.547489 0.442623 +43 -0.391592 0.545082 +SURF 0x10 +mat 2 +refs 3 +54 -0.36138 0.442623 +43 -0.391592 0.545082 +53 -0.547489 0.442623 +SURF 0x10 +mat 2 +refs 3 +43 -0.391592 0.545082 +54 -0.36138 0.442623 +44 -0.280464 0.545082 +SURF 0x10 +mat 2 +refs 3 +55 -0.219282 0.442623 +44 -0.280464 0.545082 +54 -0.36138 0.442623 +SURF 0x10 +mat 2 +refs 3 +44 -0.280464 0.545082 +55 -0.219282 0.442623 +34 -0.239037 0.545082 +SURF 0x10 +mat 2 +refs 3 +45 -0.16631 0.442623 +34 -0.239037 0.545082 +55 -0.219282 0.442623 +SURF 0x10 +mat 2 +refs 3 +45 -1 0.442623 +56 -1 0.340164 +46 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +57 -1 0.340164 +46 -1 0.442623 +56 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +46 -1 0.442623 +57 -1 0.340164 +47 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +58 -1 0.340164 +47 -1 0.442623 +57 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +47 -1 0.442623 +58 -1 0.340164 +48 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +59 -1 0.340164 +48 -1 0.442623 +58 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +48 -1 0.442623 +59 -1 0.340164 +49 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +60 -1 0.340164 +49 -1 0.442623 +59 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +49 -1 0.442623 +60 -1 0.340164 +50 -1 0.442623 +SURF 0x10 +mat 2 +refs 3 +61 -1 0.340164 +50 -1 0.442623 +60 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +50 -1 0.442623 +61 -1 0.340164 +51 -0.820173 0.442623 +SURF 0x10 +mat 2 +refs 3 +62 -0.857116 0.340164 +51 -0.820173 0.442623 +61 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +51 -0.820173 0.442623 +62 -0.857116 0.340164 +52 -0.71852 0.442623 +SURF 0x10 +mat 2 +refs 3 +63 -0.743734 0.340164 +52 -0.71852 0.442623 +62 -0.857116 0.340164 +SURF 0x10 +mat 2 +refs 3 +52 -0.71852 0.442623 +63 -0.743734 0.340164 +53 -0.547489 0.442623 +SURF 0x10 +mat 2 +refs 3 +64 -0.552969 0.340164 +53 -0.547489 0.442623 +63 -0.743734 0.340164 +SURF 0x10 +mat 2 +refs 3 +53 -0.547489 0.442623 +64 -0.552969 0.340164 +54 -0.36138 0.442623 +SURF 0x10 +mat 2 +refs 3 +65 -0.345386 0.340164 +54 -0.36138 0.442623 +64 -0.552969 0.340164 +SURF 0x10 +mat 2 +refs 3 +54 -0.36138 0.442623 +65 -0.345386 0.340164 +55 -0.219282 0.442623 +SURF 0x10 +mat 2 +refs 3 +66 -0.186892 0.340164 +55 -0.219282 0.442623 +65 -0.345386 0.340164 +SURF 0x10 +mat 2 +refs 3 +55 -0.219282 0.442623 +66 -0.186892 0.340164 +45 -0.16631 0.442623 +SURF 0x10 +mat 2 +refs 3 +56 -0.127807 0.340164 +45 -0.16631 0.442623 +66 -0.186892 0.340164 +SURF 0x10 +mat 2 +refs 3 +56 -1 0.340164 +67 -1 0.241803 +57 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +68 -1 0.241803 +57 -1 0.340164 +67 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +57 -1 0.340164 +68 -1 0.241803 +58 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +69 -1 0.241803 +58 -1 0.340164 +68 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +58 -1 0.340164 +69 -1 0.241803 +59 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +70 -1 0.241803 +59 -1 0.340164 +69 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +59 -1 0.340164 +70 -1 0.241803 +60 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +71 -1 0.241803 +60 -1 0.340164 +70 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +60 -1 0.340164 +71 -1 0.241803 +61 -1 0.340164 +SURF 0x10 +mat 2 +refs 3 +72 -1 0.241803 +61 -1 0.340164 +71 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +61 -1 0.340164 +72 -1 0.241803 +62 -0.857116 0.340164 +SURF 0x10 +mat 2 +refs 3 +73 -0.853011 0.241803 +62 -0.857116 0.340164 +72 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +62 -0.857116 0.340164 +73 -0.853011 0.241803 +63 -0.743734 0.340164 +SURF 0x10 +mat 2 +refs 3 +74 -0.740933 0.241803 +63 -0.743734 0.340164 +73 -0.853011 0.241803 +SURF 0x10 +mat 2 +refs 3 +63 -0.743734 0.340164 +74 -0.740933 0.241803 +64 -0.552969 0.340164 +SURF 0x10 +mat 2 +refs 3 +75 -0.55236 0.241803 +64 -0.552969 0.340164 +74 -0.740933 0.241803 +SURF 0x10 +mat 2 +refs 3 +64 -0.552969 0.340164 +75 -0.55236 0.241803 +65 -0.345386 0.340164 +SURF 0x10 +mat 2 +refs 3 +76 -0.347163 0.241803 +65 -0.345386 0.340164 +75 -0.55236 0.241803 +SURF 0x10 +mat 2 +refs 3 +65 -0.345386 0.340164 +76 -0.347163 0.241803 +66 -0.186892 0.340164 +SURF 0x10 +mat 2 +refs 3 +77 -0.190491 0.241803 +66 -0.186892 0.340164 +76 -0.347163 0.241803 +SURF 0x10 +mat 2 +refs 3 +66 -0.186892 0.340164 +77 -0.190491 0.241803 +56 -0.127807 0.340164 +SURF 0x10 +mat 2 +refs 3 +67 -0.132086 0.241803 +56 -0.127807 0.340164 +77 -0.190491 0.241803 +SURF 0x10 +mat 2 +refs 3 +67 -1 0.241803 +78 -1 0.0901639 +68 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +79 -1 0.0901639 +68 -1 0.241803 +78 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +68 -1 0.241803 +79 -1 0.0901639 +69 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +80 -1 0.0901639 +69 -1 0.241803 +79 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +69 -1 0.241803 +80 -1 0.0901639 +70 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +81 -1 0.0901639 +70 -1 0.241803 +80 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +70 -1 0.241803 +81 -1 0.0901639 +71 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +82 -1 0.0901639 +71 -1 0.241803 +81 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +71 -1 0.241803 +82 -1 0.0901639 +72 -1 0.241803 +SURF 0x10 +mat 2 +refs 3 +83 -1 0.0901639 +72 -1 0.241803 +82 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +72 -1 0.241803 +83 -1 0.0901639 +73 -0.853011 0.241803 +SURF 0x10 +mat 2 +refs 3 +84 -0.807859 0.0901639 +73 -0.853011 0.241803 +83 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +73 -0.853011 0.241803 +84 -0.807859 0.0901639 +74 -0.740933 0.241803 +SURF 0x10 +mat 2 +refs 3 +85 -0.710116 0.0901639 +74 -0.740933 0.241803 +84 -0.807859 0.0901639 +SURF 0x10 +mat 2 +refs 3 +74 -0.740933 0.241803 +85 -0.710116 0.0901639 +75 -0.55236 0.241803 +SURF 0x10 +mat 2 +refs 3 +86 -0.545663 0.0901639 +75 -0.55236 0.241803 +85 -0.710116 0.0901639 +SURF 0x10 +mat 2 +refs 3 +75 -0.55236 0.241803 +86 -0.545663 0.0901639 +76 -0.347163 0.241803 +SURF 0x10 +mat 2 +refs 3 +87 -0.366712 0.0901639 +76 -0.347163 0.241803 +86 -0.545663 0.0901639 +SURF 0x10 +mat 2 +refs 3 +76 -0.347163 0.241803 +87 -0.366712 0.0901639 +77 -0.190491 0.241803 +SURF 0x10 +mat 2 +refs 3 +88 -0.230079 0.0901639 +77 -0.190491 0.241803 +87 -0.366712 0.0901639 +SURF 0x10 +mat 2 +refs 3 +77 -0.190491 0.241803 +88 -0.230079 0.0901639 +67 -0.132086 0.241803 +SURF 0x10 +mat 2 +refs 3 +78 -0.179144 0.0901639 +67 -0.132086 0.241803 +88 -0.230079 0.0901639 +SURF 0x10 +mat 2 +refs 3 +78 -1 0.0901639 +89 -1 0.00819672 +79 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +90 -1 0.00819672 +79 -1 0.0901639 +89 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +79 -1 0.0901639 +90 -1 0.00819672 +80 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +91 -1 0.00819672 +80 -1 0.0901639 +90 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +80 -1 0.0901639 +91 -1 0.00819672 +81 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +92 -1 0.00819672 +81 -1 0.0901639 +91 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +81 -1 0.0901639 +92 -1 0.00819672 +82 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +93 -1 0.00819672 +82 -1 0.0901639 +92 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +82 -1 0.0901639 +93 -1 0.00819672 +83 -1 0.0901639 +SURF 0x10 +mat 2 +refs 3 +94 -1 0.00819672 +83 -1 0.0901639 +93 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +83 -1 0.0901639 +94 -1 0.00819672 +84 -0.807859 0.0901639 +SURF 0x10 +mat 2 +refs 3 +95 -0.643667 0.00819672 +84 -0.807859 0.0901639 +94 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +84 -0.807859 0.0901639 +95 -0.643667 0.00819672 +85 -0.710116 0.0901639 +SURF 0x10 +mat 2 +refs 3 +96 -0.598054 0.00819672 +85 -0.710116 0.0901639 +95 -0.643667 0.00819672 +SURF 0x10 +mat 2 +refs 3 +85 -0.710116 0.0901639 +96 -0.598054 0.00819672 +86 -0.545663 0.0901639 +SURF 0x10 +mat 2 +refs 3 +97 -0.521309 0.00819672 +86 -0.545663 0.0901639 +96 -0.598054 0.00819672 +SURF 0x10 +mat 2 +refs 3 +86 -0.545663 0.0901639 +97 -0.521309 0.00819672 +87 -0.366712 0.0901639 +SURF 0x10 +mat 2 +refs 3 +98 -0.437799 0.00819672 +87 -0.366712 0.0901639 +97 -0.521309 0.00819672 +SURF 0x10 +mat 2 +refs 3 +87 -0.366712 0.0901639 +98 -0.437799 0.00819672 +88 -0.230079 0.0901639 +SURF 0x10 +mat 2 +refs 3 +99 -0.374037 0.00819672 +88 -0.230079 0.0901639 +98 -0.437799 0.00819672 +SURF 0x10 +mat 2 +refs 3 +88 -0.230079 0.0901639 +99 -0.374037 0.00819672 +78 -0.179144 0.0901639 +SURF 0x10 +mat 2 +refs 3 +89 -0.350267 0.00819672 +78 -0.179144 0.0901639 +99 -0.374037 0.00819672 +SURF 0x10 +mat 0 +refs 3 +100 0 0 +101 0 0 +102 0 0 +SURF 0x10 +mat 0 +refs 3 +103 0 0 +102 0 0 +101 0 0 +SURF 0x10 +mat 0 +refs 3 +102 0 0 +103 0 0 +104 0 0 +SURF 0x10 +mat 0 +refs 3 +105 0 0 +104 0 0 +103 0 0 +SURF 0x10 +mat 0 +refs 3 +104 0 0 +105 0 0 +106 0 0 +SURF 0x10 +mat 0 +refs 2 +105 0 0 +106 0 0 +SURF 0x10 +mat 0 +refs 2 +105 0 0 +106 0 0 +SURF 0x10 +mat 0 +refs 3 +106 0 0 +105 0 0 +104 0 0 +SURF 0x10 +mat 0 +refs 3 +103 0 0 +104 0 0 +105 0 0 +SURF 0x10 +mat 0 +refs 3 +104 0 0 +103 0 0 +102 0 0 +SURF 0x10 +mat 0 +refs 3 +107 0 0 +108 0 0 +109 0 0 +SURF 0x10 +mat 0 +refs 3 +110 0 0 +109 0 0 +108 0 0 +SURF 0x10 +mat 0 +refs 3 +109 0 0 +110 0 0 +111 0 0 +SURF 0x10 +mat 0 +refs 3 +112 0 0 +111 0 0 +110 0 0 +SURF 0x10 +mat 0 +refs 3 +111 0 0 +112 0 0 +113 0 0 +SURF 0x10 +mat 0 +refs 2 +112 0 0 +113 0 0 +SURF 0x10 +mat 0 +refs 2 +112 0 0 +113 0 0 +SURF 0x10 +mat 0 +refs 3 +113 0 0 +112 0 0 +111 0 0 +SURF 0x10 +mat 0 +refs 3 +110 0 0 +111 0 0 +112 0 0 +SURF 0x10 +mat 0 +refs 3 +111 0 0 +110 0 0 +109 0 0 +SURF 0x10 +mat 2 +refs 3 +89 -1 0.00819672 +114 -1 0 +90 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +90 -1 0.00819672 +114 -1 0 +91 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +91 -1 0.00819672 +114 -1 0 +92 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +92 -1 0.00819672 +114 -1 0 +93 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +93 -1 0.00819672 +114 -1 0 +94 -1 0.00819672 +SURF 0x10 +mat 2 +refs 3 +94 -1 0.00819672 +114 -1 0 +95 -0.643667 0.00819672 +SURF 0x10 +mat 2 +refs 3 +95 -0.643667 0.00819672 +114 -0.5 0 +96 -0.598054 0.00819672 +SURF 0x10 +mat 2 +refs 3 +96 -0.598054 0.00819672 +114 -0.5 0 +97 -0.521309 0.00819672 +SURF 0x10 +mat 2 +refs 3 +97 -0.521309 0.00819672 +114 -0.5 0 +98 -0.437799 0.00819672 +SURF 0x10 +mat 2 +refs 3 +98 -0.437799 0.00819672 +114 -0.5 0 +99 -0.374037 0.00819672 +SURF 0x10 +mat 2 +refs 3 +99 -0.374037 0.00819672 +114 -0.5 0 +89 -0.350267 0.00819672 +kids 0 +OBJECT poly +name "tuxbeak" +loc -0.0328128 0.372259 0.086667 +texture "Penguin_beak.rgb" +numvert 17 +0.0565685 0.514 0.1 +1.11759e-08 0.5 0.125 +0.08 0.5 0.1 +1.11759e-08 0.528 0.1 +-0.0565685 0.514 0.1 +-0.08 0.5 0.1 +-0.0565685 0.486 0.1 +1.11759e-08 0.472 0.1 +0.0565685 0.486 0.1 +0.16 0.5 -0.125 +0.113137 0.556 -0.125 +1.11759e-08 0.612 -0.125 +-0.113137 0.556 -0.125 +-0.16 0.5 -0.125 +-0.113137 0.444 -0.125 +1.11759e-08 0.388 -0.125 +0.113137 0.444 -0.125 +numsurf 24 +SURF 0x10 +mat 2 +refs 3 +0 -0.342865 -0.342865 +1 -0.5 -0.5 +2 -0.277778 -0.5 +SURF 0x10 +mat 2 +refs 3 +3 -0.5 -0.277778 +1 -0.5 -0.5 +0 -0.342865 -0.342865 +SURF 0x10 +mat 2 +refs 3 +4 -0.657135 -0.342865 +1 -0.5 -0.5 +3 -0.5 -0.277778 +SURF 0x10 +mat 2 +refs 3 +5 -0.722222 -0.5 +1 -0.5 -0.5 +4 -0.657135 -0.342865 +SURF 0x10 +mat 2 +refs 3 +6 -0.657135 -0.657135 +1 -0.5 -0.5 +5 -0.722222 -0.5 +SURF 0x10 +mat 2 +refs 3 +7 -0.5 -0.722222 +1 -0.5 -0.5 +6 -0.657135 -0.657135 +SURF 0x10 +mat 2 +refs 3 +8 -0.342865 -0.657135 +1 -0.5 -0.5 +7 -0.5 -0.722222 +SURF 0x10 +mat 2 +refs 3 +2 -0.277778 -0.5 +1 -0.5 -0.5 +8 -0.342865 -0.657135 +SURF 0x10 +mat 2 +refs 3 +2 -0.277778 -0.5 +9 -0.0555556 -0.5 +0 -0.342865 -0.342865 +SURF 0x10 +mat 2 +refs 3 +10 -0.18573 -0.18573 +0 -0.342865 -0.342865 +9 -0.0555556 -0.5 +SURF 0x10 +mat 2 +refs 3 +0 -0.342865 -0.342865 +10 -0.18573 -0.18573 +3 -0.5 -0.277778 +SURF 0x10 +mat 2 +refs 3 +11 -0.5 -0.0555556 +3 -0.5 -0.277778 +10 -0.18573 -0.18573 +SURF 0x10 +mat 2 +refs 3 +3 -0.5 -0.277778 +11 -0.5 -0.0555556 +4 -0.657135 -0.342865 +SURF 0x10 +mat 2 +refs 3 +12 -0.81427 -0.18573 +4 -0.657135 -0.342865 +11 -0.5 -0.0555556 +SURF 0x10 +mat 2 +refs 3 +4 -0.657135 -0.342865 +12 -0.81427 -0.18573 +5 -0.722222 -0.5 +SURF 0x10 +mat 2 +refs 3 +13 -0.944444 -0.5 +5 -0.722222 -0.5 +12 -0.81427 -0.18573 +SURF 0x10 +mat 2 +refs 3 +5 -0.722222 -0.5 +13 -0.944444 -0.5 +6 -0.657135 -0.657135 +SURF 0x10 +mat 2 +refs 3 +14 -0.81427 -0.81427 +6 -0.657135 -0.657135 +13 -0.944444 -0.5 +SURF 0x10 +mat 2 +refs 3 +6 -0.657135 -0.657135 +14 -0.81427 -0.81427 +7 -0.5 -0.722222 +SURF 0x10 +mat 2 +refs 3 +15 -0.5 -0.944444 +7 -0.5 -0.722222 +14 -0.81427 -0.81427 +SURF 0x10 +mat 2 +refs 3 +7 -0.5 -0.722222 +15 -0.5 -0.944444 +8 -0.342865 -0.657135 +SURF 0x10 +mat 2 +refs 3 +16 -0.18573 -0.81427 +8 -0.342865 -0.657135 +15 -0.5 -0.944444 +SURF 0x10 +mat 2 +refs 3 +8 -0.342865 -0.657135 +16 -0.18573 -0.81427 +2 -0.277778 -0.5 +SURF 0x10 +mat 2 +refs 3 +9 -0.0555556 -0.5 +2 -0.277778 -0.5 +16 -0.18573 -0.81427 +kids 0 diff --git a/examples/src/ssg/viewer/data/wood.rgb b/examples/src/ssg/viewer/data/wood.rgb new file mode 100644 index 0000000..3094af0 Binary files /dev/null and b/examples/src/ssg/viewer/data/wood.rgb differ diff --git a/examples/src/ssg/viewer/pview.cxx b/examples/src/ssg/viewer/pview.cxx new file mode 100644 index 0000000..899bab3 --- /dev/null +++ b/examples/src/ssg/viewer/pview.cxx @@ -0,0 +1,191 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pview.cxx 2048 2005-09-30 18:14:09Z fayjf $ +*/ + +/* + * pview.cxx + * + * By Bram Stolk. + * Minimalistic plib viewer with a proper 'virtual ball' interface. + * LMB for orbiting model, MMB for translation, RMB for approaching model. + */ + +#include +#include + +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846264338327950f +#endif + +static float aspectratio=1.0; +static int winw, winh; +static ssgRoot *scene=0; +static ssgContext *context=0; +static sgMat4 camtrf; + + +static void idle(void) +{ + context->setCamera(camtrf); + glutPostRedisplay () ; +} + + +static void redraw(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + glMatrixMode(GL_MODELVIEW); + if (scene) ssgCullAndDraw(scene); + glutSwapBuffers () ; +} + + +static int prevx=0; +static int prevy=0; +static int prevbutton=-1; + +static void mouse(int button, int state, int x, int y) +{ + prevx=x; + prevy=y; + prevbutton=button; +} + +static void motion(int x, int y) +{ + const float vel=220.0; + float dx = vel * (x-prevx) / winw; + float dy = vel * (y-prevy) / winh; + prevx = x; prevy = y; + + if (prevbutton==0) + { + sgQuat hq, vq; + sgAngleAxisToQuat(hq, -dx, camtrf[2]); + sgAngleAxisToQuat(vq, -dy, camtrf[0]); + sgQuat totalq; + sgMultQuat(totalq, vq, hq); + sgNormalizeQuat(totalq); + sgMat4 m; + sgQuatToMatrix(m, totalq); + sgPostMultMat4(camtrf, m); + return; + } + if (prevbutton==1) + { + float curdist = sgLengthVec3(camtrf[3]); + sgAddScaledVec3(camtrf[3], camtrf[2], dy*curdist/200.0f); + sgAddScaledVec3(camtrf[3], camtrf[0], -dx*curdist/200.0f); + return; + } + if (prevbutton==2) + { + float curdist = sgLengthVec3(camtrf[3]); + sgAddScaledVec3(camtrf[3], camtrf[1], -dy*curdist/80.0f); + return; + } +} + + +static void reshape(int w, int h) +{ + glViewport ( 0, 0, w, h ) ; + + aspectratio = w / (float) h; + winw=w; winh=h; + float fovy = 60.0f * M_PI / 180.0f; + float nearPlaneDistance = 0.4f; + float farPlaneDistance = 2500.0; + float y = (float)tan(0.5 * fovy) * nearPlaneDistance; + float x = aspectratio * y; + context->setFrustum(-x,x,-y,y,nearPlaneDistance,farPlaneDistance); +} + + +static void keyboard(unsigned char k, int, int) +{ + if (k==27) + { + exit(0); + } +} + + +int main(int argc, char *argv[]) +{ + if (argc<2) + { + fprintf(stderr,"Usage: %s model0 [model1] .. [modeln]\n", argv[0]); + return -1; + } + glutInitWindowSize(512,512); + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE); + glutCreateWindow(argv[1]); + glutDisplayFunc(redraw); + glutReshapeFunc(reshape); + glutKeyboardFunc(keyboard); + glutMouseFunc(mouse); + glutIdleFunc(idle); + glutMotionFunc(motion); + + ssgInit(); + + glClearColor(0.3f,0.3f,0.55f,1.0f); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + scene = new ssgRoot(); + + float amb[4]={0.2f, 0.2f, 0.2f, 1.0f}; + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb); + + ssgTransform *trf = new ssgTransform(); + scene->addKid(trf); + + for (int i=1; iaddKid(ssgLoad(argv[i])); + + context = new ssgContext(); + context->makeCurrent(); + + sgVec3 off; + sgZeroVec3(off); + sgSubVec3(off, scene->getBSphere()->getCenter()); + + trf->setTransform(off); + SGfloat radius = scene->getBSphere()->getRadius(); + float d = 1.8f*radius; + if (d<0.5) d=0.5; // avoid placing near-plane beyond model + sgMakeTransMat4(camtrf, 0, -d, 0); + + ssgLight *light=ssgGetLight(0); + light->setColour(GL_AMBIENT,0,0,0); + light->setPosition(0,0,radius); + light->on(); + + glutMainLoop(); + + return 0; +} + diff --git a/examples/src/ssg/viewer/pview.dsp b/examples/src/ssg/viewer/pview.dsp new file mode 100755 index 0000000..1888441 --- /dev/null +++ b/examples/src/ssg/viewer/pview.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="pview" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=pview - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "pview.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "pview.mak" CFG="pview - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "pview - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "pview - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "pview - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /I "..\..\..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "FREEGLUT_STATIC" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg_d.lib sg_d.lib fnt_d.lib pui_d.lib ul_d.lib opengl32.lib glu32.lib /nologo /subsystem:console /machine:I386 /out:"pview.exe" /libpath:"..\..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "pview - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /I "..\..\..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "FREEGLUT_STATIC" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg_d.lib sg_d.lib fnt_d.lib pui_d.lib ul_d.lib opengl32.lib glu32.lib /nologo /subsystem:console /debug /machine:I386 /out:"pview.exe" /pdbtype:sept /libpath:"..\..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "pview - Win32 Release" +# Name "pview - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\pview.cxx +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/examples/src/ssg/viewer/viewer.cxx b/examples/src/ssg/viewer/viewer.cxx new file mode 100644 index 0000000..e4a3f27 --- /dev/null +++ b/examples/src/ssg/viewer/viewer.cxx @@ -0,0 +1,859 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: viewer.cxx 2099 2006-11-03 20:04:40Z fayjf $ +*/ + +/**** +* NAME +* viewer - SSG model viewer +* +* DESCRIPTION +* using a PUI interface, allow user to load a model, +* animate the model, and manipulate the camera. +* several models can be loaded at the same time. +* +* MODIFICATION HISTORY +* Sep-2000 Dave McClurg Created +* Sep-2001 Dave McClurg Added wireframe toggle +****/ + +#include +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include + +#ifdef FREEGLUT_IS_PRESENT +# include +#else +# ifdef __APPLE__ +# include +# else +# include +# endif +#endif + +#include +#include +#include +#include + +#define ARROWS_USED 1 +/* +!!!FIXME!!! +Defines what type of arrows to uses with puFileSelector +0 - No arrows +1 - Single move arrows +2 - Single move and Jump 10 moves +*/ + + + +/* +scene graph +*/ +static ssgRoot *scene = NULL ; +static ssgContext *context = NULL ; +static ssgEntity* camera_object = NULL ; + +/* +font vars +*/ +static fntRenderer *text ; +static fntTexFont *font ; + +static puaFileSelector* file_selector = 0 ; + +/* +frame rate vars +*/ +static int frame_counter = 0; +static float fps = 0; + +/* +animation vars +*/ +#define MAX_SPEED 60 +static const int speed_tab [] = +{ 0, 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60 }; + +static int speed_index = 1 ; +//static int anim_frame ; +static int num_anim_frames ; + +/* +wire vars +*/ +static int wire_flag = 0 ; +static sgVec4 wire_colour = { 1.0f, 1.0f, 1.0f, 1.0f } ; + +/* +spinner vars +*/ +static int downx, downy; /* for tracking mouse position */ +static int downb = -1; /* and button status */ + +static GLfloat downDist, downEl, downAz, /* for saving state of things */ +downEx, downEy, downEz; /* when button is pressed */ + +static GLfloat dAz, dEl, lastAz, lastEl; /* to calculate spinning w/ polar motion */ +static GLfloat AzSpin = 0.0f, ElSpin = 0.0f; +static int AdjustingAzEl = 0; + +/* Minimum spin to allow in polar (lower forced to zero) */ +#define MIN_AZSPIN 0.1f +#define MIN_ELSPIN 0.1f + +/* Factors used in computing dAz and dEl (which determine AzSpin, ElSpin) */ +#define SLOW_DAZ 0.90f +#define SLOW_DEL 0.90f +#define PREV_DAZ 0.80f +#define PREV_DEL 0.80f +#define CUR_DAZ 0.20f +#define CUR_DEL 0.20f + +/* +* polar movement parameters +*/ +static GLfloat EyeDist= 100.0f; +static GLfloat EyeAz = 0.0f; +static GLfloat EyeEl = 30.0f; +static GLfloat Ex = 0.0f; +static GLfloat Ey = 0.0f; +static GLfloat Ez = 0.0f; + +#define FOVY 45.0f +#define FOV_NEAR 0.1f +#define FOV_FAR 10000.0f + +#ifndef M_PI +#define M_PI 3.14159265358979323846264338327950f +#endif + +static int getWindowHeight () { return glutGet ( (GLenum) GLUT_WINDOW_HEIGHT ) ; } +static int getWindowWidth () { return glutGet ( (GLenum) GLUT_WINDOW_WIDTH ) ; } + +static void begin2d ( void ) +{ + int w = getWindowWidth () ; + int h = getWindowHeight () ; + + glDisable ( GL_LIGHTING ) ; + glDisable ( GL_TEXTURE_2D ) ; + glDisable ( GL_DEPTH_TEST ) ; + glDisable ( GL_CULL_FACE ) ; + glEnable ( GL_ALPHA_TEST ) ; + glEnable ( GL_BLEND ) ; + glAlphaFunc ( GL_GREATER, 0.1f ) ; + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; + + //create an projection that acts like a 2D screen + glMatrixMode ( GL_PROJECTION ) ; + glPushMatrix () ; + glLoadIdentity () ; + glOrtho ( 0, w, 0, h, 0, 1 ) ; + glMatrixMode ( GL_MODELVIEW ) ; + glPushMatrix () ; + glLoadIdentity () ; +} + +static void end2d ( void ) +{ + glMatrixMode ( GL_PROJECTION ) ; + glPopMatrix () ; + glMatrixMode ( GL_MODELVIEW ) ; + glPopMatrix () ; + + glDisable ( GL_ALPHA_TEST ) ; + glDisable ( GL_BLEND ) ; + glAlphaFunc ( GL_ALWAYS, 0.0 ) ; + glBlendFunc ( GL_ONE, GL_ZERO ) ; +} + + +static void count_anim_frames( ssgEntity *e ) +{ + if ( e -> isAKindOf ( ssgTypeBranch() ) ) + { + ssgBranch *br = (ssgBranch *) e ; + + for ( int i = 0 ; i < br -> getNumKids () ; i++ ) + count_anim_frames ( br -> getKid ( i ) ) ; + + if ( e -> isAKindOf ( ssgTypeSelector() ) ) + { + ssgSelector* p = (ssgSelector*) e ; + int num = p -> getMaxKids () ; + if ( num > num_anim_frames ) + num_anim_frames = num ; + } + else if ( e -> isAKindOf ( ssgTypeTransform() ) ) + { + ssgBase* data = e -> getUserData () ; + if ( data != NULL && data -> isAKindOf ( ssgTypeTransformArray() ) ) + { + ssgTransformArray* ta = (ssgTransformArray*) data ; + int num = ta -> getNum () ; + if ( num > num_anim_frames ) + num_anim_frames = num ; + } + } + } + else if ( e -> isAKindOf ( ssgTypeLeaf() ) ) + { + ssgLeaf* leaf = (ssgLeaf *) e ; + ssgState* st = leaf -> getState () ; + + if ( st && st -> isAKindOf ( ssgTypeStateSelector() ) ) + { + ssgStateSelector* ss = (ssgStateSelector*) st ; + + int num = ss -> getNumSteps () ; + if ( num > num_anim_frames ) + num_anim_frames = num ; + } + } +} + + + +// You need to have a object with animation loaded into memory for the following function to make sense. +// Animation can be discreet (in steps) or "smooth" (fluid). +// If you loaded an animation made of several meshes, it will use a selector and therefore always be "discreet" +// If you loaded some transformation matrices like some rotations to rotate the flap of a plane, +// the define DISCREET_STEPS will determine whether the animation is smooth (new code, WK) or +// in steps ("old" code, Dave McClurg). +// +// The anim_frame is for discreet animation and an index determining which matrix / which selector will be used. +// +// typically, you will call set_anim_frame directly before you call ssgCullAndDraw +static void set_anim_frame( ssgEntity *e, int anim_frame ) +{ + if ( e -> isAKindOf ( ssgTypeBranch() ) ) + { + ssgBranch *br = (ssgBranch *) e ; + + for ( int i = 0 ; i < br -> getNumKids () ; i++ ) + set_anim_frame ( br -> getKid ( i ), anim_frame ) ; + + if ( e -> isAKindOf ( ssgTypeSelector() ) ) + { + ssgSelector* p = (ssgSelector*) e ; + int num = p -> getMaxKids () ; + if ( num > 0 ) + { + int frame = anim_frame ; + frame %= num ; + p -> selectStep ( frame ) ; + } + } + } + else if ( e -> isAKindOf ( ssgTypeLeaf() ) ) + { + ssgLeaf* leaf = (ssgLeaf *) e ; + ssgState* st = leaf -> getState () ; + + if ( st && st -> isAKindOf ( ssgTypeStateSelector() ) ) + { + ssgStateSelector* ss = (ssgStateSelector*) st ; + int num = ss -> getNumSteps () ; + if ( num > 0 ) + { + int frame = anim_frame ; + frame %= num ; + ss -> selectStep ( frame ) ; + } + } + } +} + + + +static int wire_draw ( ssgEntity* e ) +{ + if ( e -> isAKindOf ( ssgTypeLeaf() ) ) + { + ssgLeaf* leaf = (ssgLeaf*) e ; + leaf -> drawHighlight ( wire_colour ) ; + } + return 1 ; +} + + +static void wire_update ( ssgEntity *e, int flag ) +{ + if ( e -> isAKindOf ( ssgTypeBranch() ) ) + { + ssgBranch *br = (ssgBranch *) e ; + + for ( int i = 0 ; i < br -> getNumKids () ; i++ ) + wire_update ( br -> getKid ( i ), flag ) ; + } + else if ( e -> isAKindOf ( ssgTypeLeaf() ) ) + { + ssgLeaf* leaf = (ssgLeaf *) e ; + leaf -> setCallback ( SSG_CALLBACK_POSTDRAW, flag? wire_draw: NULL ) ; + } +} + + +static void make_matrix( sgMat4 mat ) +{ + SGfloat angle = -EyeAz * SG_DEGREES_TO_RADIANS ; + sgVec3 eye ; + eye[0] = (SGfloat) cos (angle) * EyeDist + Ex ; + eye[1] = (SGfloat) sin (angle) * EyeDist + Ey ; + angle = EyeEl * SG_DEGREES_TO_RADIANS ; + eye[2] = (SGfloat) sin (angle) * EyeDist + Ez ; + + sgVec3 center ; + sgSetVec3 ( center, Ex, Ey, Ez ) ; + + sgVec3 up ; + sgSetVec3 ( up, 0.0f, 0.0f, 0.1f ) ; + + sgMakeLookAtMat4 ( mat, eye, center, up ) ; +} + + +static bool get_camera_dir ( ssgEntity* e, sgVec3 eye, sgVec3 target ) +{ + if ( e -> isAKindOf ( ssgTypeBranch() ) ) + { + ssgBranch *br = (ssgBranch *) e ; + for ( int i = 0 ; i < br -> getNumKids () ; i++ ) + { + if ( get_camera_dir ( br -> getKid ( i ), eye, target ) ) + return true ; + } + } + else if ( e -> isAKindOf ( ssgTypeLeaf() ) ) + { + ssgLeaf* leaf = (ssgLeaf *) e ; + if ( leaf -> getNumVertices () >= 2 ) + { + sgCopyVec3 ( eye, leaf -> getVertex ( 0 ) ) ; + sgCopyVec3 ( target, leaf -> getVertex ( 1 ) ) ; + return true ; + } + } + return false ; +} + + +static void follow_camera ( sgMat4 mat ) +{ + if ( camera_object != NULL ) + { + sgVec3 v1, v2 ; + if ( camera_object -> isAKindOf ( ssgTypeTransform() ) && + get_camera_dir ( camera_object, v1, v2 ) ) + { + ssgTransform* tr = (ssgTransform*) camera_object ; + sgMat4 m ; + tr -> getTransform ( m ) ; + + sgVec3 up = { 0.0f, 0.0f, 1.0f } ; + sgVec3 eye, target ; + sgXformPnt3 ( eye, v1, m ) ; + sgXformPnt3 ( target, v2, m ) ; + sgMakeLookAtMat4 ( mat, eye, target, up ) ; + } + } +} + + +/* + The GLUT window reshape event + Fixed to properly maintain aspect ratio. +*/ + +static void reshape ( int w, int h ) +{ + glViewport ( 0, 0, w, h ) ; + + float aspect = w / (float)h; + float angle = 0.5f * FOVY * M_PI / 180.0f; + float y = FOV_NEAR * (float)tan(angle); + float x = aspect * y; + + context->setFrustum(-x,x,-y,y,FOV_NEAR,FOV_FAR); +} + + + +/* + The GLUT display event +*/ + +static void display(void) +{ + glClearColor ( 0.2f, 0.7f, 1.0f, 1.0f ) ; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + sgMat4 mat ; + make_matrix ( mat ) ; + follow_camera ( mat ) ; + + context->setCamera ( mat ); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glEnable( GL_DEPTH_TEST ) ; + + /* + update virtual time, from "real" time and speed. + */ + static int last_time = 0; + int curr_time = glutGet((GLenum)GLUT_ELAPSED_TIME); + if (last_time != 0) + // calculate the "virtual time" + _ssgGlobTime += 0.001f*(curr_time-last_time)*speed_tab[ speed_index ]; + + last_time = curr_time; + + //set_anim_frame ( scene, _ssgGlobTime); // currently not needed by our sample data + + /* + figure out how fast this bus is going + */ + static int last_time2 = 0; + if (curr_time >= last_time2 + 2000) { + fps = frame_counter * 1000.0f / (curr_time - last_time2); + frame_counter = 0; + last_time2 = curr_time; + } + + ssgCullAndDraw ( scene ) ; + + /* + do the interface stuff + */ + + int h = getWindowHeight () ; + + begin2d () ; + + text -> setFont ( font ) ; + text -> setPointSize ( 12 ) ; + + if ( scene -> getNumKids() == 0 ) + { + text -> begin () ; + glColor3f ( 0.0f, 0.0f, 0.0f ) ; + text -> start2f ( 4.0f, (float)(h-16) ) ; + text -> puts ( "controls\n" ); + text -> puts ( " : exit\n" ) ; + text -> puts ( " c : clear\n" ) ; + text -> puts ( " l : load a shape or sequence\n" ) ; + text -> puts ( " w : toggle wireframe\n" ) ; + text -> puts ( " : faster animation\n" ) ; + text -> puts ( " : slower animation\n" ) ; + text -> puts ( " : rotate\n" ) ; + text -> puts ( " : zoom\n" ) ; + text -> end () ; + } + else if ( fps > 0 ) + { + + char buffer [ PUSTRING_MAX ] ; + text -> begin () ; + glColor3f ( 0.0f, 0.0f, 0.0f ) ; + text -> start2f ( 4.0f, (float)(h-16) ) ; + sprintf ( buffer, "fps : %.02f\n", fps ) ; + text -> puts ( buffer ) ; + sprintf ( buffer, "dist : %.02f\n", EyeDist ) ; + text -> puts ( buffer ) ; + sprintf ( buffer, "anim_speed : %d fps\n", speed_tab[ speed_index ] ) ; + text -> puts ( buffer ) ; + sprintf ( buffer, "time : %-4d\n", curr_time ) ; + text -> puts ( buffer ) ; + text -> end () ; + + } + + glColor3f ( 1.0f, 1.0f, 1.0f ) ; + end2d () ; + + frame_counter ++; + + puDisplay () ; + + glutPostRedisplay () ; + glutSwapBuffers () ; +} + +/* +* keep them vertical; I think this makes a lot of things easier, +* but maybe it wouldn't be too hard to adapt things to let you go +* upside down +*/ +static int ConstrainEl(void) +{ + if (EyeEl <= -90) { + EyeEl = -89.99f; + return 1; + } else if (EyeEl >= 90) { + EyeEl = 89.99f; + return 1; + } + return 0; +} + +/* What to multiply number of pixels mouse moved by to get rotation amount */ +#define EL_SENS 0.5f +#define AZ_SENS 0.5f + +static void motion(int x, int y) +{ + puMouse ( x, y ) ; + + int deltax = x - downx, deltay = y - downy; + + // if ( scene -> getNumKids() > 0 && !file_selector ) + if ( !file_selector ) + + switch (downb) { + case GLUT_LEFT_BUTTON: + EyeEl = downEl + EL_SENS * deltay; + ConstrainEl(); + EyeAz = downAz + AZ_SENS * deltax; + dAz = PREV_DAZ*dAz + CUR_DAZ*(lastAz - EyeAz); + dEl = PREV_DEL*dEl + CUR_DEL*(lastEl - EyeEl); + lastAz = EyeAz; + lastEl = EyeEl; + break; + case GLUT_RIGHT_BUTTON: + { + float mult = 0.01f; + if ( fabs(downDist) > 1.0f ) + mult = float( 0.001 * fabs(downDist) ); + EyeDist = downDist + mult*deltay; + break; + } + case GLUT_MIDDLE_BUTTON: + { + float mult = 0.01f; + if ( fabs(EyeDist) > 1.0f ) + mult = float( 0.0005f * fabs(EyeDist) ); + + sgMat4 mat ; + make_matrix( mat ) ; + + sgVec3 off; + sgSetVec3( off, mult*deltax, 0, -mult*deltay ); + sgXformVec3( off, mat ); + + Ex -= off[0]; + Ey -= off[1]; + Ez -= off[2]; + } + break; + } +} + +static void mouse(int button, int state, int x, int y) +{ + puMouse ( button, state, x, y ) ; + + if (state == GLUT_DOWN && downb == -1) { + downx = x; + downy = y; + downb = button; + + // if ( scene -> getNumKids() > 0 && !file_selector ) + if (!file_selector ) + switch ( button ) + { + case GLUT_LEFT_BUTTON: + lastEl = downEl = EyeEl; + lastAz = downAz = EyeAz; + AzSpin = ElSpin = dAz = dEl = 0; + AdjustingAzEl = 1; + break; + case GLUT_RIGHT_BUTTON: + downDist = EyeDist; + break; + case GLUT_MIDDLE_BUTTON: + downEx = Ex; + downEy = Ey; + downEz = Ez; + break; + } + } else if (state == GLUT_UP && button == downb) { + downb = -1; + + // if ( scene -> getNumKids() > 0 && !file_selector ) + if ( !file_selector ) + switch ( button ) + { + case GLUT_LEFT_BUTTON: + AzSpin = -dAz; + if (AzSpin < MIN_AZSPIN && AzSpin > -MIN_AZSPIN) + AzSpin = 0; + ElSpin = -dEl; + if (ElSpin < MIN_ELSPIN && ElSpin > -MIN_ELSPIN) + ElSpin = 0; + AdjustingAzEl = 0; + break; + } + } +} + +static void special(int key, int x, int y) +{ + puKeyboard ( key + PU_KEY_GLUT_SPECIAL_OFFSET, PU_DOWN ) ; + + switch ( key ) + { + case GLUT_KEY_LEFT: + case GLUT_KEY_UP: + case GLUT_KEY_RIGHT: + case GLUT_KEY_DOWN: + case GLUT_KEY_PAGE_UP: + case GLUT_KEY_PAGE_DOWN: + case GLUT_KEY_HOME: + case GLUT_KEY_END: + break; + } +} + +static void pick_cb ( puObject * ) +{ + char* str ; + file_selector -> getValue ( &str ) ; + + char fname [PUSTRING_MAX]; + strcpy ( fname, str ) ; + + puDeleteObject ( file_selector ) ; + file_selector = 0 ; + + ssgEntity *obj = ssgLoad ( (char*)fname ); //"test_Med.ase" ) ; + +#if 0 + ssgSaveSSG ( "temp.ssg", obj ) ; + delete obj ; + obj = ssgLoadSSG ( "temp.ssg" ) ; +#endif + +#if 0 + ssgSaveDXF ( "temp.dxf", obj ) ; + delete obj ; + obj = ssgLoadDXF ( "temp.dxf" ) ; +#endif + + if ( !obj ) + return; + + scene -> addKid ( obj ) ; + + num_anim_frames = 0 ; + count_anim_frames ( scene ) ; + wire_update ( scene, wire_flag ) ; + + SGfloat radius = scene->getBSphere()->getRadius(); + EyeDist = float( radius * 1.5f / tan( float( FOVY/2 * SG_DEGREES_TO_RADIANS ) ) ); + if (EyeDist < FOV_NEAR*2) + EyeDist = FOV_NEAR*2; + + sgSphere sp = *( scene -> getBSphere() ) ; + if ( sp.isEmpty() ) + { + Ex = 0.0f ; + Ey = 0.0f ; + Ez = 0.0f ; + } + else + { + Ex = sp.getCenter()[ 0 ] ; + Ey = sp.getCenter()[ 1 ] ; + Ez = sp.getCenter()[ 2 ] ; + } + + /* try to find the animated camera */ + camera_object = scene -> getByName ( "FlyCam" ) ; +} + + + +/* + The GLUT keyboard event +*/ + +static void keyboard(unsigned char key, int, int) +{ + puKeyboard ( key, PU_DOWN ) ; + + switch ( key ) + { + case 0x1b: //escape + exit(0); + break; + case '+': + if ( speed_tab[ speed_index ] != MAX_SPEED ) + speed_index ++ ; + break; + case '-': + if ( speed_tab[ speed_index ] != 0 ) + speed_index -- ; + break; + case ' ': + Ex = 0; + Ey = 0; + Ez = 0; + break; + case 'l': + if ( !file_selector ) + { + file_selector = new puaFileSelector ( ( 640 - 320 ) / 2, ( 480 - 270 ) / 2, 320, 270, ARROWS_USED, "data" ) ; + file_selector -> setCallback ( pick_cb ) ; + } + break; + case 'w': + wire_flag = !wire_flag ; + wire_update ( scene, wire_flag ) ; + break ; + case 'c': + //scene -> removeKid ( obj ); + scene -> removeAllKids () ; + break ; + } +} + +static void idle(void) +{ + EyeEl += ElSpin; + EyeAz += AzSpin; + + /* + * weird spin thing to make things look + * look better when you are kept from going + * upside down while spinning - Isn't great + */ + if (ConstrainEl()) { + ElSpin = -ElSpin; + if (fabs(ElSpin) > fabs(AzSpin)) + AzSpin = float( fabs(ElSpin) * ((AzSpin > 0) ? 1 : -1) ); + } + + if (AdjustingAzEl) { + dAz *= SLOW_DAZ; + dEl *= SLOW_DEL; + } +} + +static void init_graphics () +{ + int fake_argc = 1 ; + char *fake_argv[3] ; + fake_argv[0] = "Viewer" ; + fake_argv[1] = "Simple Scene Graph : Viewer Program." ; + fake_argv[2] = NULL ; + + /* + Initialise GLUT + */ + + glutInit ( &fake_argc, fake_argv ) ; + glutInitWindowSize ( 640, 480 ) ; + glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ; + glutCreateWindow ( fake_argv[1] ) ; + glutDisplayFunc ( display ) ; + glutReshapeFunc ( reshape ) ; + glutKeyboardFunc ( keyboard ) ; + glutMouseFunc ( mouse ) ; + glutMotionFunc ( motion ) ; + glutSpecialFunc ( special ) ; + glutIdleFunc ( idle ) ; + + /* + Some basic OpenGL setup + */ + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glDepthFunc(GL_LESS); + glEnable(GL_DEPTH_TEST); + glShadeModel(GL_SMOOTH); + + /* + Initialise PLIB + */ + + ssgInit () ; + puInit () ; + + /* + Set up the Sun. + */ + + sgVec3 sunposn ; + sgSetVec3 ( sunposn, 200.0f, -500.0f, 500.0f ) ; + ssgGetLight ( 0 ) -> setPosition ( sunposn ) ; + + + + /* + Set up the path to the data files + */ + + ssgModelPath ( "." ) ; + ssgTexturePath ( "." ) ; + + /* + Create a root node + */ + + scene = new ssgRoot ; + context = new ssgContext ; + context->setCullface( true ) ; + context->makeCurrent ( ) ; + + /* + ** Set up PU + */ + text = new fntRenderer () ; + font = new fntTexFont ( "data/default.txf" ) ; + + puFont font1 ( font, 12 ) ; + puFont font2 ( font, 15 ) ; + puSetDefaultFonts ( font1, font2 ) ; + puSetDefaultStyle ( PUSTYLE_SMALL_SHADED ) ; + puSetDefaultColourScheme ( 0.7f, 0.7f, 0.7f, 1.0f ) ; +} + + +int main(int argc, char** argv) +{ + init_graphics (); + glutMainLoop(); + return 0; /* ANSI C requires main to return int. */ +} + diff --git a/examples/src/ssg/viewer/viewer.dsp b/examples/src/ssg/viewer/viewer.dsp new file mode 100644 index 0000000..88102d7 --- /dev/null +++ b/examples/src/ssg/viewer/viewer.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="viewer" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=viewer - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "viewer.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "viewer.mak" CFG="viewer - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "viewer - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "viewer - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "viewer - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib fnt.lib pui.lib puAux.lib ssg.lib sg.lib ul.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /machine:I386 /out:"viewer.exe" /libpath:"..\..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "viewer - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ssg_d.lib sg_d.lib fnt_d.lib pui_d.lib puAux_d.lib ul_d.lib opengl32.lib glu32.lib glut32.lib /nologo /subsystem:console /debug /machine:I386 /out:"viewer.exe" /pdbtype:sept /libpath:"..\..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "viewer - Win32 Release" +# Name "viewer - Win32 Debug" +# Begin Source File + +SOURCE=.\viewer.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/ssg/water/Makefile.am b/examples/src/ssg/water/Makefile.am new file mode 100644 index 0000000..56a16de --- /dev/null +++ b/examples/src/ssg/water/Makefile.am @@ -0,0 +1,12 @@ +if BUILD_SSG + +noinst_PROGRAMS = water + +water_SOURCES = water.cxx + +water_LDADD = -lplibpw -lplibpuaux -lplibpu -lplibfnt -lplibssgaux -lplibssg -lplibsg -lplibul $(OGL_LIBS) + +endif + +EXTRA_DIST = water.dsp README + diff --git a/examples/src/ssg/water/README b/examples/src/ssg/water/README new file mode 100644 index 0000000..28a1478 --- /dev/null +++ b/examples/src/ssg/water/README @@ -0,0 +1,56 @@ + +Designing Waves. +~~~~~~~~~~~~~~~~ + +The PLIB ssgAux library contains a class for handling +water waves. + + class ssgaWaveSystem ; + +This generates a large polygonal mesh which it distorts in +realtime to simulate water waves. + +The simulation uses between one and sixteen "Wave Trains" - each +using a class: + + class ssgaWaveTrain ; + +The program in this directory demonstrates this system and allows +you to play with the wave train parameters. + +Use the 'Edit Wave Train Number' widget to select which of the +16 wave trains you want to play with. There is a button just +below that to enable or disable that particular wave train - and +for convenience, there is a button to disable ALL wave trains. + +It's often convenient to turn on just one wave train at a time +and set it's parameters - then combine two, three or more to +produce the final effect. + +Each wave train has a direction in which the waves are travelling, +a speed, a wave length (which also affects the shape of the wave), +the height of the wave and a 'curl' term (which controls how much +the tops of the waves bend over). + +The appearance of waves varies greatly with the depth of the +water - and this simulation produces the correct effects. There +are a number of preset water depths that you can select between, +notice that the effect of varying the depth is more pronounced +for long Wave Lengths. + +There are also controls to set the eyepoint pan/tilt/range and to +toggle the system into wireframe. + +You can determine the number of polygons used to render +the patch of waves, the size of the wave patch and the amount +of texture repetition with the three sliders in the bottom right. + +Hitting the space bar toggles the GUI on and off so you can see +your creation without any clutter on the screen. + +Finally, when you have your waves exactly how you like them, hit +the 'Write C++' button and a C++ subroutine to recreate the +exact same-looking waves will be written to stdout. + + + diff --git a/examples/src/ssg/water/data/droplet.rgb b/examples/src/ssg/water/data/droplet.rgb new file mode 100644 index 0000000..2ac0055 Binary files /dev/null and b/examples/src/ssg/water/data/droplet.rgb differ diff --git a/examples/src/ssg/water/data/ocean.rgb b/examples/src/ssg/water/data/ocean.rgb new file mode 100644 index 0000000..a72795b Binary files /dev/null and b/examples/src/ssg/water/data/ocean.rgb differ diff --git a/examples/src/ssg/water/data/pattern.rgb b/examples/src/ssg/water/data/pattern.rgb new file mode 100644 index 0000000..13885fc Binary files /dev/null and b/examples/src/ssg/water/data/pattern.rgb differ diff --git a/examples/src/ssg/water/data/pavement.rgb b/examples/src/ssg/water/data/pavement.rgb new file mode 100644 index 0000000..a6d1d9d Binary files /dev/null and b/examples/src/ssg/water/data/pavement.rgb differ diff --git a/examples/src/ssg/water/data/sorority.txf b/examples/src/ssg/water/data/sorority.txf new file mode 100644 index 0000000..8b457aa Binary files /dev/null and b/examples/src/ssg/water/data/sorority.txf differ diff --git a/examples/src/ssg/water/water.cxx b/examples/src/ssg/water/water.cxx new file mode 100644 index 0000000..6a45f32 --- /dev/null +++ b/examples/src/ssg/water/water.cxx @@ -0,0 +1,991 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: water.cxx 2077 2006-04-13 16:21:42Z bram $ +*/ + +#define PU_USE_PW + +#ifndef GL_GLEXT_PROTOTYPES +#define GL_GLEXT_PROTOTYPES +#endif + +#include +#include +#include +#include +#ifdef WIN32 +# include +#else +# include +#endif +#include +#include +#include +#include +#include +#include + +#ifndef GL_VERSION_1_3 +// ARB_multitexture +#define GL_TEXTURE0 GL_TEXTURE0_ARB +#define GL_TEXTURE1 GL_TEXTURE1_ARB +#define glActiveTexture glActiveTextureARB +#endif + +#define GUI_BASE 90 +#define VIEW_GUI_BASE 30 +#define FONT_COLOUR 1,1,1,1 + +static puSlider *trainLengthSlider = (puSlider *) NULL ; +static puSlider *trainSpeedSlider = (puSlider *) NULL ; +static puSlider *trainLambdaSlider = (puSlider *) NULL ; +static puSlider *trainHeightSlider = (puSlider *) NULL ; +static puButton *trainEnableButton = (puButton *) NULL ; +static puOneShot *trainDisableButton = (puOneShot *) NULL ; +static puDial *trainHeadingDial = (puDial *) NULL ; +static puaSelectBox *trainSelectBox = (puaSelectBox *) NULL ; +static puText *timeText = (puText *) NULL ; + +static puaSelectBox *depthSelectBox = (puaSelectBox *) NULL ; + +static puDial *viewHeadingDial = (puDial *) NULL ; +static puDial *viewPitchDial = (puDial *) NULL ; +static puSlider *viewRangeSlider = (puSlider *) NULL ; +static puButton *viewWireframeButton= (puButton *) NULL ; +static puButton *viewEnvMapButton = (puButton *) NULL ; + +static puOneShot *writeButton = (puOneShot *) NULL ; + +static puSlider *waveTextureSlider = (puSlider *) NULL ; +static puSlider *waveSizeSlider = (puSlider *) NULL ; +static puSlider *wavePolycountSlider= (puSlider *) NULL ; + +static ssgRoot *scene = NULL ; +static ssgaLensFlare *sun_obj = NULL ; +static ssgTransform *sun = NULL ; +static ssgTransform *teapot = NULL ; +static ssgTransform *fire = NULL ; +static ssgTransform *pedestal = NULL ; +static ssgaWaveSystem *ocean = NULL ; +static ssgaParticleSystem *fountain = NULL ; +static ssgaCube *ped_obj = NULL ; +static ssgaTeapot *tpt_obj = NULL ; +static ssgaFire *fire_obj = NULL ; + +static ssgSimpleState *sea_state = NULL ; +static ssgSimpleState *splash_state = NULL ; +static ssgSimpleState *teapot_state = NULL ; +static ssgSimpleState *plinth_state = NULL ; + +static ssgContext *context = NULL ; + +static ssgaWaveTrain trains [ 16 ] ; + +static char *trainNameList[] = +{ + "Train 0" , "Train 1" , "Train 2" , "Train 3" , "Train 4" , + "Train 5" , "Train 6" , "Train 7" , "Train 8" , "Train 9" , + "Train 10", "Train 11", "Train 12", "Train 13", "Train 14", + "Train 15", + NULL +} ; + +static int quit = FALSE; + +static int curr_train = 0 ; +static int curr_depthfunc = 0 ; +static int wireframe = FALSE ; +static int displayGUI = TRUE ; +static float cam_range = 25.0f ; + +static sgCoord campos = { { 0, -20, 8 }, { 0, -30, 0 } } ; +static sgVec3 sunpos = { 400, 300, 50 } ; + +static int enableTexGen ( ssgEntity * ) +{ +#ifdef GL_ARB_multitexture + int tx ; + glGetIntegerv ( GL_TEXTURE_BINDING_2D, &tx ) ; + glActiveTexture ( GL_TEXTURE1 ) ; +#endif + glTexGeni ( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP ) ; + glTexGeni ( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP ) ; + glEnable ( GL_TEXTURE_GEN_S ) ; + glEnable ( GL_TEXTURE_GEN_T ) ; +#ifdef GL_ARB_multitexture + glEnable ( GL_TEXTURE_2D ) ; /* Enables the second texture map. */ + glBindTexture ( GL_TEXTURE_2D, tx ) ; + glActiveTexture ( GL_TEXTURE0 ) ; +#endif + return TRUE ; +} + +static int disableTexGen ( ssgEntity * ) +{ +#ifdef GL_ARB_multitexture + glActiveTexture ( GL_TEXTURE1 ) ; +#endif + glDisable ( GL_TEXTURE_GEN_S ) ; + glDisable ( GL_TEXTURE_GEN_T ) ; +#ifdef GL_ARB_multitexture + glDisable ( GL_TEXTURE_2D ) ; /* Disables the second texture map */ + glActiveTexture ( GL_TEXTURE0 ) ; +#endif + return TRUE ; +} + +static void writeCplusplusCode () +{ + if ( viewEnvMapButton -> getIntegerValue () ) + { + printf ( "\n" ) ; + printf ( "static int enableTexGen ( ssgEntity * )\n" ) ; + printf ( "{\n" ) ; + printf ( "#ifdef GL_ARB_multitexture\n" ) ; + printf ( " int tx ;\n" ) ; + printf ( " glGetIntegerv ( GL_TEXTURE_BINDING_2D, &tx ) ;\n" ) ; + printf ( " glActiveTextureARB ( GL_TEXTURE1_ARB ) ;\n" ) ; + printf ( "#endif\n" ) ; + printf ( " glTexGeni ( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP ) ;\n" ) ; + printf ( " glTexGeni ( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP ) ;\n" ) ; + printf ( " glEnable ( GL_TEXTURE_GEN_S ) ;\n" ) ; + printf ( " glEnable ( GL_TEXTURE_GEN_T ) ;\n" ) ; + printf ( " glEnable ( GL_TEXTURE_2D ) ;\n" ) ; + printf ( "#ifdef GL_ARB_multitexture\n" ) ; + printf ( " glBindTexture ( GL_TEXTURE_2D, tx ) ;\n" ) ; + printf ( " glActiveTextureARB ( GL_TEXTURE0_ARB ) ;\n" ) ; + printf ( "#endif\n" ) ; + printf ( " return TRUE ;\n" ) ; + printf ( "} \n" ) ; + printf ( "\n" ) ; + printf ( "static int disableTexGen ( ssgEntity * )\n" ) ; + printf ( "{\n" ) ; + printf ( "#ifdef GL_ARB_multitexture\n" ) ; + printf ( " glActiveTextureARB ( GL_TEXTURE1_ARB ) ;\n" ) ; + printf ( "#endif\n" ) ; + printf ( " glDisable ( GL_TEXTURE_GEN_S ) ;\n" ) ; + printf ( " glDisable ( GL_TEXTURE_GEN_T ) ;\n" ) ; + printf ( " glDisable ( GL_TEXTURE_2D ) ;\n" ) ; + printf ( "#ifdef GL_ARB_multitexture\n" ) ; + printf ( " glActiveTextureARB ( GL_TEXTURE0_ARB ) ;\n" ) ; + printf ( "#endif\n" ) ; + printf ( " return TRUE ;\n" ) ; + printf ( "}\n" ) ; + printf ( "\n" ) ; + } + + printf ( "\n" ) ; + printf ( "ssgaWaveSystem *makeWaveSystem ( ssgState *state )\n" ) ; + printf ( "{\n" ) ; + printf ( " ssgaWaveTrain *wavetrain ;\n" ) ; + printf ( " ssgaWaveSystem *ocean ;\n" ) ; + printf ( " ocean = new ssgaWaveSystem ( %d ) ;\n", ocean->getNumTris() ) ; + printf ( " ocean -> setSize ( %g ) ;\n", ocean->getSize()[0] ) ; + printf ( " ocean -> setKidState ( state ) ;\n" ) ; + printf ( " ocean -> setTexScale ( %g, %g ) ;\n", + ocean->getTexScaleU (), + ocean->getTexScaleV () ) ; + printf ( " ocean -> setWindSpeed ( 10.0f ) ;\n\n" ) ; + + for ( int i = 0 ; i < SSGA_MAX_WAVETRAIN ; i++ ) + { + if ( ocean -> getWaveTrain ( i ) != NULL ) + { + printf ( " wavetrain = new ssgaWaveTrain () ;\n" ) ; + + printf ( " wavetrain->setSpeed ( %g ) ;\n",trains[i].getSpeed ()); + printf ( " wavetrain->setLength ( %g ) ;\n",trains[i].getLength ()); + printf ( " wavetrain->setLambda ( %g ) ;\n",trains[i].getLambda ()); + printf ( " wavetrain->setHeading ( %g ) ;\n",trains[i].getHeading ()); + printf ( " wavetrain->setWaveHeight ( %g ) ;\n",trains[i].getWaveHeight()); + + printf ( " ocean -> setWaveTrain ( %d, wavetrain ) ;\n\n", i ) ; + } + } + + if ( viewEnvMapButton -> getIntegerValue () ) + { + printf ( " ocean -> setKidCallback ( SSG_CALLBACK_PREDRAW , enableTexGen ) ;\n" ) ; + printf ( " ocean -> setKidCallback ( SSG_CALLBACK_POSTDRAW, disableTexGen ) ;\n" ) ; + } + printf ( " ocean -> regenerate () ;\n" ) ; + printf ( " return ocean ;\n" ) ; + printf ( "}\n" ) ; + printf ( "\n" ) ; +} + + +static void waveTextureSlider_cb ( puObject *ob ) +{ + ocean -> setTexScale ( ob -> getFloatValue (), + ob -> getFloatValue () ) ; +} + + +static void waveSizeSlider_cb ( puObject *ob ) +{ + cam_range = ob -> getFloatValue () ; + ocean -> setSize ( ob -> getFloatValue () ) ; +} + + +static void wavePolycountSlider_cb ( puObject *ob ) +{ + ocean -> setNumTris ( ob -> getIntegerValue () ) ; +} + + +static void viewHeadingDial_cb ( puObject *ob ) +{ + campos.hpr[0] = ob -> getFloatValue () ; + + sgVec3 r = { 0, -cam_range, 0 } ; + sgMat4 mat ; + + sgMakeRotMat4 ( mat, campos.hpr ) ; + sgXformVec3 ( campos.xyz, r, mat ) ; +} + + +static void viewPitchDial_cb ( puObject *ob ) +{ + campos . hpr [ 1 ] = ob -> getFloatValue () ; + + sgVec3 r = { 0, -cam_range, 0 } ; + sgMat4 mat ; + + sgMakeRotMat4 ( mat, campos.hpr ) ; + sgXformVec3 ( campos.xyz, r, mat ) ; +} + + +static void viewRangeSlider_cb ( puObject *ob ) +{ + cam_range = ob -> getFloatValue () ; + + sgVec3 r = { 0, -cam_range, 0 } ; + sgMat4 mat ; + + sgMakeRotMat4 ( mat, campos.hpr ) ; + sgXformVec3 ( campos.xyz, r, mat ) ; +} + + +static void viewWireframeButton_cb ( puObject *ob ) +{ + wireframe = ob -> getIntegerValue () ; +} + + +static void viewEnvMapButton_cb ( puObject *ob ) +{ + if ( ob -> getIntegerValue () ) + { + ocean -> setKidCallback ( SSG_CALLBACK_PREDRAW , enableTexGen ) ; + ocean -> setKidCallback ( SSG_CALLBACK_POSTDRAW, disableTexGen ) ; + ocean -> regenerate () ; + } + else + { + ocean -> setKidCallback ( SSG_CALLBACK_PREDRAW , NULL ) ; + ocean -> setKidCallback ( SSG_CALLBACK_POSTDRAW, NULL ) ; + ocean -> regenerate () ; + } +} + + +static void trainLengthSlider_cb ( puObject *ob ) +{ + trains[curr_train].setLength ( ob -> getFloatValue () ) ; + ob -> setLegend ( ob -> getStringValue () ) ; +} + + +static void trainSpeedSlider_cb ( puObject *ob ) +{ + trains[curr_train].setSpeed ( ob -> getFloatValue () ) ; + ob -> setLegend ( ob -> getStringValue () ) ; +} + + +static void trainLambdaSlider_cb ( puObject *ob ) +{ + trains[curr_train].setLambda ( ob -> getFloatValue () ) ; + ob -> setLegend ( ob -> getStringValue () ) ; +} + + +static void trainHeightSlider_cb ( puObject *ob ) +{ + trains[curr_train].setWaveHeight ( ob -> getFloatValue () ) ; + ob -> setLegend ( ob -> getStringValue () ) ; +} + +static void trainDisableButton_cb ( puObject *ob ) +{ + for ( int i = 0 ; i < SSGA_MAX_WAVETRAIN ; i++ ) + ocean -> setWaveTrain ( i, NULL ) ; + + trainEnableButton -> setValue ( 0 ) ; +} + +static void writeButton_cb ( puObject *ob ) +{ + if ( ob -> getIntegerValue () ) + writeCplusplusCode () ; +} + +static void trainEnableButton_cb ( puObject *ob ) +{ + if ( ob -> getIntegerValue () ) + ocean -> setWaveTrain ( curr_train, & trains [ curr_train ] ) ; + else + ocean -> setWaveTrain ( curr_train, NULL ) ; +} + +static void trainHeadingDial_cb ( puObject *ob ) +{ + trains[curr_train].setHeading ( ob -> getFloatValue () ) ; + ob -> setLegend ( ob -> getStringValue () ) ; +} + +static void trainSelectBox_cb ( puObject *ob ) +{ + curr_train = ((puaSelectBox *) ob) -> getCurrentItem () ; + + if ( curr_train < 0 ) + curr_train = 0 ; + + if ( curr_train >= SSGA_MAX_WAVETRAIN ) + curr_train = SSGA_MAX_WAVETRAIN - 1 ; + + trainEnableButton -> setValue ( + ocean -> getWaveTrain ( curr_train ) != NULL ) ; + + trainLengthSlider -> setValue ( trains[curr_train].getLength () ) ; + trainSpeedSlider -> setValue ( trains[curr_train].getSpeed () ) ; + trainLambdaSlider -> setValue ( trains[curr_train].getLambda () ) ; + trainHeightSlider -> setValue ( trains[curr_train].getWaveHeight () ) ; + trainHeadingDial -> setValue ( trains[curr_train].getHeading () ) ; +} + + +static float halfMeterEverywhere ( float x, float y ) +{ + return 0.5f ; +} + + +static float oneMeterEverywhere ( float x, float y ) +{ + return 1.0f ; +} + + +static float twoMeterEverywhere ( float x, float y ) +{ + return 1.5f ; +} + + +static float gentleSlope ( float x, float y ) +{ + return (1.0f + x / (ocean -> getSize ()[0] / 2.0f)) * 2.0f ; +} + + +static float steepSlope ( float x, float y ) +{ + return (1.0f + x / (ocean -> getSize ()[0] / 2.0f)) * 10.0f ; +} + + +static float stepFunction ( float x, float y ) +{ + return (x < 0.0f ) ? 0.5f : 20000.0f ; +} + + +static float twoBeaches ( float x, float y ) +{ + return (float) fabs ( sin( x / ocean->getSize()[0]) * + sin(2.0f * y / ocean->getSize()[1]) * 1.5 + 0.5 ) ; +} + +static const ssgaWSDepthCallback depthFuncs [] = +{ + NULL, /* Infinite depth */ + halfMeterEverywhere, + oneMeterEverywhere, + twoMeterEverywhere, + gentleSlope, + steepSlope, + stepFunction, + twoBeaches, + NULL, +} ; + +static char *depthNames [] = +{ + "Infinite Depth", + "Half Meter Deep", + "One Meter Deep", + "Two Meters Deep", + "Gentle Slope", + "Steep Slope", + "Step Function", + "Two Curved Beaches", + NULL, +} ; + +static void depthSelectBox_cb ( puObject *ob ) +{ + curr_depthfunc = ((puaSelectBox *) ob) -> getCurrentItem () ; + + if ( curr_depthfunc < 0 ) + curr_depthfunc = 0 ; + + if ( curr_depthfunc >= (int)(sizeof(depthFuncs)/sizeof(ssgaWSDepthCallback))) + curr_depthfunc = (int)(sizeof(depthFuncs)/sizeof(ssgaWSDepthCallback)) - 1 ; + + ocean -> setDepthCallback ( depthFuncs [ curr_depthfunc ] ) ; +} + + + +static void update_motion () +{ + static ulClock ck ; + static char s [ 128 ] ; + + ck . update () ; + + double t = ck . getAbsTime () ; + float dt = (float) ck . getDeltaTime () ; + + ocean -> setWindDirn ( (float)( 25.0 * sin ( t / 100.0 ) ) ) ; + ocean -> updateAnimation ( (float) t ) ; + + fountain -> update ( dt ) ; + fire_obj -> update ( dt ) ; + + dt = (float) ck . getDeltaTime () ; + + sprintf ( s, "CalcTime=%1.1fms", dt * 1000.0 ) ; + timeText->setLabel ( s ) ; + sgCoord tptpos ; + + context -> setCamera ( & campos ) ; + + sgSetCoord ( & tptpos, 0.0f, 0.0f, 0.6f, (float)(t * 60), 0.0f, 0.0f ) ; + teapot -> setTransform ( & tptpos ) ; + sgSetCoord ( & tptpos, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f ) ; + fire -> setTransform ( & tptpos ) ; +} + + + +/* + The PW window reshape event +*/ + +static void reshape ( int w, int h ) +{ + glViewport ( 0, 0, w, h ) ; +} + + + +/* + The PW keyboard/mouse events +*/ + +static void keyboard ( int key, int updown, int, int ) +{ + if ( ! puKeyboard ( key, updown ) && ( updown == PU_DOWN ) ) + { + switch ( key ) + { + case 0x03 : + case 0x1B : + case 'q' : + exit ( 0 ) ; + + case ' ' : + default : + displayGUI = ! displayGUI ; + break ; + } + } +} + +static void motionfn ( int x, int y ) +{ + if ( displayGUI ) + puMouse ( x, y ) ; +} + +static void mousefn ( int button, int updown, int x, int y ) +{ + if ( displayGUI ) + puMouse ( button, updown, x, y ) ; +} + + + +/* + The redraw function +*/ + +static void main_loop () +{ + while ( !quit ) + { + update_motion () ; + + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; + + if ( wireframe ) + glPolygonMode ( GL_FRONT_AND_BACK, GL_LINE ) ; + else + glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL ) ; + + ssgCullAndDraw ( scene ) ; + + glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL ) ; + + if ( displayGUI ) + puDisplay () ; + + pwSwapBuffers () ; + } + + pwCleanup () ; +} + + + +static void init_graphics () +{ + /* + Initialise PW + */ + pwInit ( 50, 50, 640, 480, FALSE, "Simple Scene Graph : Water Example Program.", TRUE, 0) ; + pwSetCallbacks ( keyboard, mousefn, motionfn, reshape ) ; + + puInit () ; + ssgInit () ; + + /* + Some basic OpenGL setup + */ + + glClearColor ( 0.2f, 0.7f, 1.0f, 1.0f ) ; + glEnable ( GL_DEPTH_TEST ) ; + + /* + Set up the viewing parameters + */ + context = new ssgContext () ; + context -> setFOV ( 60.0f, 0.0f ) ; + context -> setNearFar ( 1.0f, 700.0f ) ; + context -> makeCurrent () ; + + /* + Set up the Sun. + */ + + ssgGetLight ( 0 ) -> setPosition ( sunpos ) ; +} + + +/* + Particle system definitions for the fountain. +*/ + +#define SPS ssgaParticleSystem /* Too much typing! */ + +static void droplet_create ( SPS *, int, ssgaParticle *p ) +{ + float c = ((float)(rand()%100)/100.0f) * (256.0f-163.0f)/255.0f ; + + sgSetVec4 ( p -> col, 96.0f/255.0f+c, 147.0f/255.0f+c, 163.0f/255.0f+c, 0.5); + sgSetVec3 ( p -> pos, -2.4f, -0.1f, 1.9f ) ; + sgSetVec3 ( p -> vel, + -(float)(rand()%1000)/200.0f, + (float)(rand()%1000 - 500)/400.0f, + (float)(rand()%1000)/1000.0f + 3.0f ) ; + sgAddScaledVec3 ( p -> pos, p -> vel, (float)(rand()%1000)/20000.0f ) ; + sgSetVec3 ( p -> acc, 0, 0, -9.8f ) ; + p -> time_to_live = 1 ; +} + + +static void init_states () +{ + plinth_state = new ssgSimpleState () ; + plinth_state -> setTexture ( "data/pavement.rgb" ) ; + plinth_state -> enable ( GL_TEXTURE_2D ) ; + plinth_state -> setShadeModel ( GL_SMOOTH ) ; + plinth_state -> enable ( GL_CULL_FACE ) ; + plinth_state -> enable ( GL_BLEND ) ; + plinth_state -> enable ( GL_LIGHTING ) ; + plinth_state -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + plinth_state -> setMaterial ( GL_EMISSION, 0, 0, 0, 1 ) ; + plinth_state -> setMaterial ( GL_SPECULAR, 1, 1, 1, 1 ) ; + plinth_state -> setShininess ( 2 ) ; + + teapot_state = new ssgSimpleState () ; + teapot_state -> setTexture ( "data/pattern.rgb" ) ; + teapot_state -> enable ( GL_TEXTURE_2D ) ; + teapot_state -> setShadeModel ( GL_SMOOTH ) ; + teapot_state -> enable ( GL_CULL_FACE ) ; + teapot_state -> enable ( GL_BLEND ) ; + teapot_state -> enable ( GL_LIGHTING ) ; + teapot_state -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + teapot_state -> setMaterial ( GL_EMISSION, 0, 0, 0, 1 ) ; + teapot_state -> setMaterial ( GL_SPECULAR, 1, 1, 1, 1 ) ; + teapot_state -> setShininess ( 2 ) ; + + sea_state = new ssgSimpleState () ; + sea_state -> setTexture ( "data/ocean.rgb" ) ; + sea_state -> setTranslucent () ; + sea_state -> enable ( GL_TEXTURE_2D ) ; + sea_state -> setShadeModel ( GL_SMOOTH ) ; + sea_state -> enable ( GL_CULL_FACE ) ; + sea_state -> enable ( GL_BLEND ) ; + sea_state -> enable ( GL_LIGHTING ) ; + sea_state -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + sea_state -> setMaterial ( GL_EMISSION, 0, 0, 0, 1 ) ; + sea_state -> setMaterial ( GL_SPECULAR, 1, 1, 1, 1 ) ; + sea_state -> setShininess ( 5 ) ; + + splash_state = new ssgSimpleState () ; + splash_state -> setTexture ( "data/droplet.rgb" ) ; + splash_state -> setTranslucent () ; + splash_state -> enable ( GL_TEXTURE_2D ) ; + splash_state -> setShadeModel ( GL_SMOOTH ) ; + splash_state -> enable ( GL_CULL_FACE ) ; + splash_state -> enable ( GL_BLEND ) ; + splash_state -> enable ( GL_LIGHTING ) ; + splash_state -> setColourMaterial ( GL_EMISSION ) ; + splash_state -> setMaterial ( GL_AMBIENT, 0, 0, 0, 1 ) ; + splash_state -> setMaterial ( GL_DIFFUSE, 0, 0, 0, 1 ) ; + splash_state -> setMaterial ( GL_SPECULAR, 0, 0, 0, 1 ) ; + splash_state -> setShininess ( 0 ) ; +} + + + + +static void load_database () +{ + /* Set up the path to the data files */ + + ssgModelPath ( "data" ) ; + ssgTexturePath ( "data" ) ; + + /* Load the states */ + + init_states () ; + + sgVec4 TRANSLUCENT_WHITE = { 1.0f, 1.0f, 1.0f, 0.8f } ; + sgVec3 pos = { 0, 0, 0 } ; + sgCoord pedpos = { { 0, 0, -1.5 }, { 0, 0, 0 } } ; + + /* Create a the scene content. */ + + fountain = new ssgaParticleSystem ( 1000, 100, 500, TRUE, + 0.2f, 1000, + droplet_create ) ; + fountain -> setState ( splash_state ) ; + + /* Set up some interesting defaults. */ + + trains[0] . setSpeed ( 3.1f ) ; + trains[0] . setLength ( 0.8f ) ; + trains[0] . setLambda ( 0.6f ) ; + trains[0] . setHeading ( 47.0f ) ; + trains[0] . setWaveHeight ( 0.2f ) ; + + trains[1] . setSpeed ( 4.6f ) ; + trains[1] . setLength ( 0.8f ) ; + trains[1] . setLambda ( 1.0f ) ; + trains[1] . setHeading ( 36.0f ) ; + trains[1] . setWaveHeight ( 0.1f ) ; + + trains[2] . setSpeed ( 8.5f ) ; + trains[2] . setLength ( 0.6f ) ; + trains[2] . setLambda ( 1.0f ) ; + trains[2] . setHeading ( 65.0f ) ; + trains[2] . setWaveHeight ( 0.1f ) ; + + ocean = new ssgaWaveSystem ( 10000 ) ; + ocean -> setColour ( TRANSLUCENT_WHITE ) ; + ocean -> setSize ( 100 ) ; + ocean -> setTexScale ( 3, 3 ) ; + ocean -> setCenter ( pos ) ; + ocean -> setDepthCallback ( depthFuncs [ curr_depthfunc ] ) ; + ocean -> setKidState ( sea_state ) ; + ocean -> setWindSpeed ( 10.0f ) ; + ocean -> setWaveTrain ( 0, & trains[0] ) ; + ocean -> setWaveTrain ( 1, & trains[1] ) ; + ocean -> setWaveTrain ( 2, & trains[2] ) ; + + ped_obj = new ssgaCube () ; + ped_obj -> setSize ( 4 ) ; + ped_obj -> setKidState ( plinth_state ) ; + ped_obj -> regenerate () ; + + tpt_obj = new ssgaTeapot ( 1000 ) ; + tpt_obj -> setSize ( 2 ) ; + tpt_obj -> setKidState ( teapot_state ) ; + tpt_obj -> regenerate () ; + + fire_obj = new ssgaFire ( 200 ) ; + + /* Build the scene graph */ + + teapot = new ssgTransform ; + teapot -> addKid ( tpt_obj ) ; + teapot -> addKid ( fountain ) ; + + pedestal = new ssgTransform ; + pedestal -> setTransform ( & pedpos ) ; + pedestal -> addKid ( ped_obj ) ; + + sun_obj = new ssgaLensFlare () ; + + sun = new ssgTransform ; + sun -> setTransform ( sunpos ) ; + sun -> addKid ( sun_obj ) ; + + fire = new ssgTransform ; + fire -> addKid ( fire_obj ) ; + + scene = new ssgRoot ; + scene -> addKid ( ocean ) ; + scene -> addKid ( fire ) ; + scene -> addKid ( pedestal ) ; + scene -> addKid ( teapot ) ; + scene -> addKid ( sun ) ; +} + + +static void init_gui () +{ + static puFont *sorority ; + static fntTexFont *fnt ; + + fnt = new fntTexFont () ; + fnt -> load ( "data/sorority.txf" ) ; + sorority = new puFont ( fnt, 12 ) ; + + puSetDefaultFonts ( *sorority, *sorority ) ; + puSetDefaultStyle ( PUSTYLE_SMALL_SHADED ) ; + puSetDefaultColourScheme ( 0.2f, 0.5f, 0.2f, 0.5f ) ; + + puGroup *window_group = new puGroup ( 0, 0 ) ; + + trainLengthSlider = new puSlider ( 200, GUI_BASE+28, 90, false, 20 ) ; + trainLengthSlider->setMaxValue ( 20.0f ) ; + trainLengthSlider->setMinValue ( 0.1f ) ; + trainLengthSlider->setStepSize ( 0.1f ) ; + trainLengthSlider->setCBMode ( PUSLIDER_ALWAYS ) ; + trainLengthSlider->setCallback ( trainLengthSlider_cb ) ; + trainLengthSlider->setLabel ( "Wave Length" ) ; + trainLengthSlider->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; + trainLengthSlider->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + trainSpeedSlider = new puSlider ( 200, GUI_BASE+56, 90, false, 20 ) ; + trainSpeedSlider->setMaxValue ( 20.0f ) ; + trainSpeedSlider->setMinValue ( 0.0f ) ; + trainSpeedSlider->setStepSize ( 0.1f ) ; + trainSpeedSlider->setCBMode ( PUSLIDER_ALWAYS ) ; + trainSpeedSlider->setCallback ( trainSpeedSlider_cb ) ; + trainSpeedSlider->setLabel ( "Wave Speed" ) ; + trainSpeedSlider->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; + trainSpeedSlider->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + trainLambdaSlider = new puSlider ( 300, GUI_BASE+28, 90, false, 20 ) ; + trainLambdaSlider->setMaxValue ( 2.0f ) ; + trainLambdaSlider->setMinValue ( 0.0f ) ; + trainLambdaSlider->setStepSize ( 0.1f ) ; + trainLambdaSlider->setCBMode ( PUSLIDER_ALWAYS ) ; + trainLambdaSlider->setCallback ( trainLambdaSlider_cb ) ; + trainLambdaSlider->setLabel ( "Wave Curl" ) ; + trainLambdaSlider->setLabelPlace ( PUPLACE_CENTERED_RIGHT ) ; + trainLambdaSlider->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + trainHeightSlider = new puSlider ( 300, GUI_BASE+56, 90, false, 20 ) ; + trainHeightSlider->setMaxValue ( 5.0f ) ; + trainHeightSlider->setMinValue ( 0.0f ) ; + trainHeightSlider->setStepSize ( 0.1f ) ; + trainHeightSlider->setCBMode ( PUSLIDER_ALWAYS ) ; + trainHeightSlider->setCallback ( trainHeightSlider_cb ) ; + trainHeightSlider->setLabel ( "Wave Height (meters)" ) ; + trainHeightSlider->setLabelPlace ( PUPLACE_CENTERED_RIGHT ) ; + trainHeightSlider->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + trainEnableButton = new puButton ( 200, GUI_BASE+84, " " ) ; + trainEnableButton->setStyle ( PUSTYLE_RADIO ) ; + trainEnableButton->setCallback ( trainEnableButton_cb ) ; + trainEnableButton->setLabel ( "Enable this Wave Train" ) ; + trainEnableButton->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; + trainEnableButton->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + trainDisableButton = new puOneShot( 450, GUI_BASE+120, + "Disable All WaveTrains" ) ; + trainDisableButton->setCallback ( trainDisableButton_cb ) ; + + trainHeadingDial = new puDial ( 300, GUI_BASE+82, 50 ) ; + trainHeadingDial->setWrap ( 1 ) ; + trainHeadingDial->setMaxValue ( 360 ) ; + trainHeadingDial->setMinValue ( 0 ) ; + trainHeadingDial->setStepSize ( 1 ) ; + trainHeadingDial->setCBMode ( PUSLIDER_ALWAYS ) ; + trainHeadingDial->setCallback ( trainHeadingDial_cb ) ; + trainHeadingDial->setLabel ( "Wave Direction" ) ; + trainHeadingDial->setLabelPlace ( PUPLACE_CENTERED_RIGHT ) ; + trainHeadingDial->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + trainHeadingDial->setLegendPlace ( PUPLACE_BOTTOM_CENTERED ) ; + + trainSelectBox = new puaSelectBox ( 200, GUI_BASE+109, 300, GUI_BASE+139, + trainNameList ) ; + trainSelectBox->setCallback ( trainSelectBox_cb ) ; + trainSelectBox->setCurrentItem ( 0 ) ; + trainSelectBox->setLabel ( "Edit Wave Train Number" ) ; + trainSelectBox->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; + trainSelectBox->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + /* Set everything up on the first time around */ + trainSelectBox_cb ( trainSelectBox ) ; + + depthSelectBox = new puaSelectBox ( 200, GUI_BASE, 400, GUI_BASE+20, + depthNames ) ; + depthSelectBox->setCallback ( depthSelectBox_cb ) ; + depthSelectBox->setCurrentItem ( 0 ) ; + depthSelectBox->setLabel ( "Water Depth" ) ; + depthSelectBox->setLabelPlace ( PUPLACE_CENTERED_LEFT ) ; + depthSelectBox->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + /* Set everything up on the first time around */ + depthSelectBox_cb ( depthSelectBox ) ; + + viewHeadingDial = new puDial ( 50, VIEW_GUI_BASE, 50 ) ; + viewHeadingDial->setValue ( 0.0f ) ; + viewHeadingDial->setWrap ( 1 ) ; + viewHeadingDial->setMaxValue ( 360 ) ; + viewHeadingDial->setMinValue ( 0 ) ; + viewHeadingDial->setStepSize ( 0 ) ; + viewHeadingDial->setCBMode ( PUSLIDER_ALWAYS ) ; + viewHeadingDial->setCallback ( viewHeadingDial_cb ) ; + viewHeadingDial->setLabel ( "Pan" ) ; + viewHeadingDial->setLabelPlace ( PUPLACE_BOTTOM_CENTERED ) ; + viewHeadingDial->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + viewPitchDial = new puDial ( 100, VIEW_GUI_BASE, 50 ) ; + viewPitchDial ->setValue ( -45.0f ) ; + viewPitchDial ->setWrap ( 1 ) ; + viewPitchDial ->setMaxValue ( 360 ) ; + viewPitchDial ->setMinValue ( 0 ) ; + viewPitchDial ->setStepSize ( 0 ) ; + viewPitchDial ->setCBMode ( PUSLIDER_ALWAYS ) ; + viewPitchDial ->setCallback ( viewPitchDial_cb ) ; + viewPitchDial ->setLabel ( "Tilt" ) ; + viewPitchDial ->setLabelPlace ( PUPLACE_BOTTOM_CENTERED ) ; + viewPitchDial ->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + viewRangeSlider = new puSlider ( 150, VIEW_GUI_BASE, 90, false, 20 ) ; + viewRangeSlider->setValue ( 25.0f ) ; + viewRangeSlider->setMaxValue ( 150.0f ) ; + viewRangeSlider->setMinValue ( 0.0f ) ; + viewRangeSlider->setStepSize ( 0 ) ; + viewRangeSlider->setCBMode ( PUSLIDER_ALWAYS ) ; + viewRangeSlider->setCallback ( viewRangeSlider_cb ) ; + viewRangeSlider->setLabel ( "Range" ) ; + viewRangeSlider->setLabelPlace ( PUPLACE_BOTTOM_CENTERED ) ; + viewRangeSlider->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + viewWireframeButton= new puButton ( 400, VIEW_GUI_BASE, "Wireframe" ) ; + viewWireframeButton->setCallback ( viewWireframeButton_cb ) ; + viewWireframeButton->setValue ( FALSE ) ; + + viewEnvMapButton= new puButton ( 300, VIEW_GUI_BASE, "Env.Map" ) ; + viewEnvMapButton->setCallback ( viewEnvMapButton_cb ) ; + viewEnvMapButton->setValue ( FALSE ) ; + + writeButton = new puOneShot ( 400, VIEW_GUI_BASE + 30, "Write C++" ) ; + writeButton->setCallback ( writeButton_cb ) ; + writeButton->setValue ( FALSE ) ; + + waveTextureSlider = new puSlider ( 500, VIEW_GUI_BASE , 90, false, 20 ) ; + waveTextureSlider->setValue ( 1.0f ) ; + waveTextureSlider->setMaxValue ( 50.0f ) ; + waveTextureSlider->setMinValue ( 0.01f ) ; + waveTextureSlider->setStepSize ( 0 ) ; + waveTextureSlider->setCBMode ( PUSLIDER_ALWAYS ) ; + waveTextureSlider->setCallback ( waveTextureSlider_cb ) ; + waveTextureSlider->setLabel ( "Texture" ) ; + waveTextureSlider->setLabelPlace ( PUPLACE_CENTERED_RIGHT ) ; + waveTextureSlider->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + waveSizeSlider = new puSlider ( 500, VIEW_GUI_BASE+30, 90, false, 20 ) ; + waveSizeSlider->setValue ( 25.0f ) ; + waveSizeSlider->setMaxValue ( 500.0f ) ; + waveSizeSlider->setMinValue ( 10.0f ) ; + waveSizeSlider->setStepSize ( 0 ) ; + waveSizeSlider->setCBMode ( PUSLIDER_ALWAYS ) ; + waveSizeSlider->setCallback ( waveSizeSlider_cb ) ; + waveSizeSlider->setLabel ( "Size" ) ; + waveSizeSlider->setLabelPlace ( PUPLACE_CENTERED_RIGHT ) ; + waveSizeSlider->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + wavePolycountSlider= new puSlider ( 500, VIEW_GUI_BASE+60, 90, false, 20 ) ; + wavePolycountSlider->setValue ( 10000 ) ; + wavePolycountSlider->setMaxValue ( 50000 ) ; + wavePolycountSlider->setMinValue ( 4000 ) ; + wavePolycountSlider->setStepSize ( 0 ) ; + wavePolycountSlider->setCBMode ( PUSLIDER_ALWAYS ) ; + wavePolycountSlider->setCallback ( wavePolycountSlider_cb ) ; + wavePolycountSlider->setLabel ( "Polygons" ) ; + wavePolycountSlider->setLabelPlace ( PUPLACE_CENTERED_RIGHT ) ; + wavePolycountSlider->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + timeText = new puText ( 500, VIEW_GUI_BASE+80 ) ; + timeText->setColour( PUCOL_LABEL, FONT_COLOUR ) ; + + window_group->close () ; +} + +/* + The works. +*/ + +int main ( int, char ** ) +{ + init_graphics () ; + load_database () ; + init_gui () ; + main_loop () ; + return 0 ; +} + diff --git a/examples/src/ssg/water/water.dsp b/examples/src/ssg/water/water.dsp new file mode 100644 index 0000000..068188d --- /dev/null +++ b/examples/src/ssg/water/water.dsp @@ -0,0 +1,90 @@ +# Microsoft Developer Studio Project File - Name="water" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=water - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "water.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "water.mak" CFG="water - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "water - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "water - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "water - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib pw.lib pui.lib puAux.lib fnt.lib ssgAux.lib ssg.lib sg.lib ul.lib winmm.lib opengl32.lib glu32.lib /nologo /subsystem:console /machine:I386 /out:"water.exe" /libpath:"..\..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "water - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib pw_d.lib pui_d.lib puAux_d.lib fnt_d.lib ssgAux_d.lib ssg_d.lib sg_d.lib ul_d.lib winmm.lib opengl32.lib glu32.lib /nologo /subsystem:console /debug /machine:I386 /out:"water.exe" /pdbtype:sept /libpath:"..\..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "water - Win32 Release" +# Name "water - Win32 Debug" +# Begin Source File + +SOURCE=.\water.cxx +# End Source File +# End Target +# End Project diff --git a/examples/src/util/Makefile.am b/examples/src/util/Makefile.am new file mode 100644 index 0000000..45ae8b8 --- /dev/null +++ b/examples/src/util/Makefile.am @@ -0,0 +1,12 @@ +if BUILD_UL + +noinst_PROGRAMS = test_dir + +test_dir_SOURCES = test_dir.cxx + +test_dir_LDADD = -lplibul + +endif + +EXTRA_DIST = test_dir.dsp + diff --git a/examples/src/util/test_dir.cxx b/examples/src/util/test_dir.cxx new file mode 100644 index 0000000..a863737 --- /dev/null +++ b/examples/src/util/test_dir.cxx @@ -0,0 +1,65 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: test_dir.cxx 1551 2002-09-01 12:04:53Z ude $ +*/ + + +#include + +void list_files( const char* dirname ) +{ + static int level=-1; + level++; + + ulDir* dirp = ulOpenDir(dirname); + if ( dirp != NULL ) + { + ulDirEnt* dp; + while ( (dp = ulReadDir(dirp)) != NULL ) + { + for ( int i=0; id_name ); + if ( dp->d_isdir ) + printf("/"); + printf("\n"); + + if ( dp->d_isdir && + strcmp (dp->d_name, ".") && + strcmp (dp->d_name, "..")) + { + char path[ UL_NAME_MAX+1 ]; + strcpy (path, dirname); + strcat (path, "/"); + strcat (path, dp->d_name); + + list_files( path ); + } + } + ulCloseDir(dirp); + } + level--; +} + +int main(int argc, char* argv[]) +{ + list_files("."); + return 0; +} diff --git a/examples/src/util/test_dir.dsp b/examples/src/util/test_dir.dsp new file mode 100644 index 0000000..fad9195 --- /dev/null +++ b/examples/src/util/test_dir.dsp @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="test_dir" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=test_dir - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "test_dir.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "test_dir.mak" CFG="test_dir - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "test_dir - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "test_dir - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "test_dir - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ul.lib /nologo /subsystem:console /machine:I386 /out:"test_dir.exe" /libpath:"..\..\..\..\plib" + +!ELSEIF "$(CFG)" == "test_dir - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ul_d.lib /nologo /subsystem:console /debug /machine:I386 /out:"test_dir.exe" /pdbtype:sept /libpath:"..\..\..\..\plib" + +!ENDIF + +# Begin Target + +# Name "test_dir - Win32 Release" +# Name "test_dir - Win32 Debug" +# Begin Source File + +SOURCE=.\test_dir.cxx +# End Source File +# End Target +# End Project diff --git a/plib.dsp b/plib.dsp new file mode 100644 index 0000000..1261733 --- /dev/null +++ b/plib.dsp @@ -0,0 +1,61 @@ +# Microsoft Developer Studio Project File - Name="plib" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Generic Project" 0x010a + +CFG=plib - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "plib.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "plib.mak" CFG="plib - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "plib - Win32 Release" (based on "Win32 (x86) Generic Project") +!MESSAGE "plib - Win32 Debug" (based on "Win32 (x86) Generic Project") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +MTL=midl.exe + +!IF "$(CFG)" == "plib - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "plib - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "plib___Win32_Debug" +# PROP BASE Intermediate_Dir "plib___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "plib - Win32 Release" +# Name "plib - Win32 Debug" +# End Target +# End Project diff --git a/plib.dsw b/plib.dsw new file mode 100644 index 0000000..797e524 --- /dev/null +++ b/plib.dsw @@ -0,0 +1,209 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "fnt"=".\src\fnt\fnt.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "js"=".\src\js\js.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "net"=".\src\net\net.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "plib"=".\plib.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name fnt + End Project Dependency + Begin Project Dependency + Project_Dep_Name js + End Project Dependency + Begin Project Dependency + Project_Dep_Name sg + End Project Dependency + Begin Project Dependency + Project_Dep_Name sl + End Project Dependency + Begin Project Dependency + Project_Dep_Name ssg + End Project Dependency + Begin Project Dependency + Project_Dep_Name psl + End Project Dependency + Begin Project Dependency + Project_Dep_Name pui + End Project Dependency + Begin Project Dependency + Project_Dep_Name ul + End Project Dependency + Begin Project Dependency + Project_Dep_Name ssgAux + End Project Dependency + Begin Project Dependency + Project_Dep_Name net + End Project Dependency + Begin Project Dependency + Project_Dep_Name pw + End Project Dependency + Begin Project Dependency + Project_Dep_Name puAux + End Project Dependency +}}} + +############################################################################### + +Project: "psl"=".\src\psl\psl.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "puAux"=".\src\puAux\puAux.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "pui"=".\src\pui\pui.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "pw"=".\src\pw\pw.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "sg"=".\src\sg\sg.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "sl"=".\src\sl\sl.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "ssg"=".\src\ssg\ssg.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "ssgAux"=".\src\ssgAux\ssgAux.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "ul"=".\src\util\ul.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..ad49fb4 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = util js sl pui puAux sg ssg fnt ssgAux net psl pw diff --git a/src/fnt/Makefile.am b/src/fnt/Makefile.am new file mode 100644 index 0000000..d0ef3ca --- /dev/null +++ b/src/fnt/Makefile.am @@ -0,0 +1,14 @@ +if BUILD_FNT + +lib_LIBRARIES = libplibfnt.a + +include_HEADERS = fnt.h + +libplibfnt_a_SOURCES = fnt.cxx fntTXF.cxx fntLocal.h fntBitmap.cxx + +INCLUDES = -I$(top_srcdir)/src/sg -I$(top_srcdir)/src/util + +endif + +EXTRA_DIST = fnt.dsp + diff --git a/src/fnt/fnt.cxx b/src/fnt/fnt.cxx new file mode 100644 index 0000000..3faaccd --- /dev/null +++ b/src/fnt/fnt.cxx @@ -0,0 +1,252 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: fnt.cxx 1939 2004-08-05 00:41:53Z puggles $ +*/ + +#include "fntLocal.h" + +fntFont:: fntFont () {} +fntFont::~fntFont () {} + +int fntTexFont::load ( const char *fname, GLenum mag, GLenum min ) +{ + const char *p ; + + for ( p = & fname [ strlen ( fname ) -1 ] ; + p != fname && *p != '.' && *p != '/' ; p-- ) + /* Do nothing */ ; + + if ( strcmp ( p, ".txf" ) == 0 ) { + return loadTXF ( fname, mag, min ) ; + } + else + { + ulSetError ( UL_WARNING, + "fnt::load: Error - Unrecognised file format for '%s'", fname ) ; + return FNT_FALSE ; + } +} + + + +float fntTexFont::low_putch ( sgVec3 curpos, float pointsize, + float italic, char c ) +{ + unsigned int cc = (unsigned char) c ; + + /* Auto case-convert if character is absent from font. */ + + if ( ! exists [ cc ] ) + { + if ( cc >= 'A' && cc <= 'Z' ) + cc = cc - 'A' + 'a' ; + else + if ( cc >= 'a' && cc <= 'z' ) + cc = cc - 'a' + 'A' ; + + if ( cc == ' ' ) + { + curpos [ 0 ] += pointsize / 2.0f ; + return pointsize / 2.0f ; + } + } + + /* + We might want to consider making some absent characters from + others (if they exist): lowercase 'l' could be made into digit '1' + or letter 'O' into digit '0'...or vice versa. We could also + make 'b', 'd', 'p' and 'q' by mirror-imaging - this would + save a little more texture memory in some fonts. + */ + + if ( ! exists [ cc ] ) + return 0.0f ; + + glBegin ( GL_TRIANGLE_STRIP ) ; + glTexCoord2f ( t_left [cc], t_bot[cc] ) ; + glVertex3f ( curpos[0] + v_left [cc] * pointsize, + curpos[1] + v_bot [cc] * pointsize, + curpos[2] ) ; + + glTexCoord2f ( t_left [cc], t_top[cc] ) ; + glVertex3f ( curpos[0] + (italic + v_left [cc]) * pointsize, + curpos[1] + v_top [cc] * pointsize, + curpos[2] ) ; + + glTexCoord2f ( t_right[cc], t_bot[cc] ) ; + glVertex3f ( curpos[0] + v_right[cc] * pointsize, + curpos[1] + v_bot [cc] * pointsize, + curpos[2] ) ; + + glTexCoord2f ( t_right[cc], t_top[cc] ) ; + glVertex3f ( curpos[0] + (italic + v_right[cc]) * pointsize, + curpos[1] + v_top [cc] * pointsize, + curpos[2] ) ; + glEnd () ; + + float ww = ( gap + ( fixed_pitch ? width : widths[cc] ) ) * pointsize ; + curpos[0] += ww ; + return ww ; +} + + + +void fntTexFont::setGlyph ( char c, float wid, + float tex_left, float tex_right, + float tex_bot , float tex_top , + float vtx_left, float vtx_right, + float vtx_bot , float vtx_top ) +{ + unsigned int cc = (unsigned char) c ; + + exists[cc] = FNT_TRUE ; + + widths[cc] = wid; + + t_left[cc] = tex_left ; t_right[cc] = tex_right ; + t_bot [cc] = tex_bot ; t_top [cc] = tex_top ; + + v_left[cc] = vtx_left ; v_right[cc] = vtx_right ; + v_bot [cc] = vtx_bot ; v_top [cc] = vtx_top ; +} + + +int fntTexFont::getGlyph ( char c, float* wid, + float *tex_left, float *tex_right, + float *tex_bot , float *tex_top , + float *vtx_left, float *vtx_right, + float *vtx_bot , float *vtx_top ) +{ + unsigned int cc = (unsigned char) c ; + + if ( ! exists[cc] ) return FNT_FALSE ; + + if ( wid != NULL ) *wid = widths [cc] ; + + if ( tex_left != NULL ) *tex_left = t_left [cc] ; + if ( tex_right != NULL ) *tex_right = t_right[cc] ; + if ( tex_bot != NULL ) *tex_bot = t_bot [cc] ; + if ( tex_top != NULL ) *tex_top = t_top [cc] ; + + if ( vtx_left != NULL ) *vtx_left = v_left [cc] ; + if ( vtx_right != NULL ) *vtx_right = v_right[cc] ; + if ( vtx_bot != NULL ) *vtx_bot = v_bot [cc] ; + if ( vtx_top != NULL ) *vtx_top = v_top [cc] ; + + return FNT_TRUE ; +} + + +void fntTexFont::getBBox ( const char *s, + float pointsize, float italic, + float *left, float *right, + float *bot , float *top ) +{ + float h_pos = 0.0f ; + float v_pos = 0.0f ; + float l, r, b, t ; + + l = r = b = t = 0.0f ; + + while ( *s != '\0' ) + { + if ( *s == '\n' ) + { + h_pos = 0.0f ; + v_pos -= 1.333f ; + s++ ; + continue ; + } + + unsigned int cc = (unsigned char) *(s++) ; + + if ( ! exists [ cc ] ) + { + if ( cc >= 'A' && cc <= 'Z' ) + cc = cc - 'A' + 'a' ; + else + if ( cc >= 'a' && cc <= 'z' ) + cc = cc - 'a' + 'A' ; + + if ( cc == ' ' ) + { + r += 0.5f ; + h_pos += 0.5f ; + + continue ; + } + } + + if ( ! exists [ cc ] ) + continue ; + + if ( italic >= 0 ) + { + if ( l > h_pos + v_left [cc] ) l = h_pos + v_left [cc] ; + if ( r < gap + h_pos + v_right[cc]+italic ) r = gap + h_pos + v_right[cc] + italic ; + } + else + { + if ( l > h_pos + v_left [cc]+italic ) l = h_pos + v_left [cc] + italic ; + if ( r < gap + h_pos + v_right[cc] ) r = gap + h_pos + v_right[cc] ; + } + + + if ( b > v_pos + v_bot [cc] ) b = v_pos + v_bot [cc] ; + if ( t < v_pos + v_top [cc] ) t = v_pos + v_top [cc] ; + + h_pos += gap + ( fixed_pitch ? width : widths[cc] ) ; + } + + if ( left != NULL ) *left = l * pointsize ; + if ( right != NULL ) *right = r * pointsize ; + if ( top != NULL ) *top = t * pointsize ; + if ( bot != NULL ) *bot = b * pointsize ; +} + + +void fntTexFont::puts ( sgVec3 curpos, float pointsize, float italic, const char *s ) +{ + SGfloat origx = curpos[0] ; + + if ( ! bound ) + bind_texture () ; + + while ( *s != '\0' ) + { + if (*s == '\n') + { + curpos[0] = origx ; + curpos[1] -= pointsize ; + } + else + low_putch ( curpos, pointsize, italic, *s ) ; + + s++ ; + } +} + +void fntInit () +{ + /* Empty right now */ +} + + diff --git a/src/fnt/fnt.dsp b/src/fnt/fnt.dsp new file mode 100644 index 0000000..470d346 --- /dev/null +++ b/src/fnt/fnt.dsp @@ -0,0 +1,114 @@ +# Microsoft Developer Studio Project File - Name="fnt" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=fnt - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "fnt.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "fnt.mak" CFG="fnt - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "fnt - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "fnt - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "fnt - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "..\sg" /I "..\util" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy release\*.lib ..\..\*.* copy fnt.h ..\..\fnt.h +# End Special Build Tool + +!ELSEIF "$(CFG)" == "fnt - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I "..\sg" /I "..\util" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\fnt_d.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy debug\*.lib ..\..\*.* copy fnt.h ..\..\fnt.h +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "fnt - Win32 Release" +# Name "fnt - Win32 Debug" +# Begin Source File + +SOURCE=.\fnt.cxx +# End Source File +# Begin Source File + +SOURCE=.\fnt.h +# End Source File +# Begin Source File + +SOURCE=.\fntLocal.h +# End Source File +# Begin Source File + +SOURCE=.\fntTXF.cxx +# End Source File +# Begin Source File + +SOURCE=.\fntBitmap.cxx +# End Source File +# End Target +# End Project diff --git a/src/fnt/fnt.h b/src/fnt/fnt.h new file mode 100644 index 0000000..22da92b --- /dev/null +++ b/src/fnt/fnt.h @@ -0,0 +1,361 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: fnt.h 1923 2004-04-06 12:53:17Z sjbaker $ +*/ + + +#ifndef _FNT_H_ +#define _FNT_H_ 1 + +#include +#include "sg.h" + +#ifdef UL_MAC_OSX +# include +#else +# include +#endif + + +#define FNTMAX_CHAR 256 +#define FNT_TRUE 1 +#define FNT_FALSE 0 + + +class fntFont +{ +public: + fntFont () ; + + virtual ~fntFont () ; + + virtual void getBBox ( const char *s, float pointsize, float italic, + float *left, float *right, + float *bot , float *top ) = 0 ; + virtual void putch ( sgVec3 curpos, float pointsize, float italic, char c ) = 0 ; + virtual void puts ( sgVec3 curpos, float pointsize, float italic, const char *s ) = 0 ; + virtual void begin () = 0 ; + virtual void end () = 0 ; + + virtual int load ( const char *fname, GLenum mag = GL_NEAREST, + GLenum min = GL_LINEAR_MIPMAP_LINEAR ) = 0 ; + + virtual void setFixedPitch ( int fix ) = 0 ; + virtual int isFixedPitch () const = 0 ; + + virtual void setWidth ( float w ) = 0 ; + virtual void setGap ( float g ) = 0 ; + + virtual float getWidth () const = 0 ; + virtual float getGap () const = 0 ; + + virtual int hasGlyph ( char c ) const = 0 ; +} ; + + +class fntTexFont : public fntFont +{ +private: + GLuint texture ; + int bound ; + int fixed_pitch ; + + float width ; /* The width of a character in fixed-width mode */ + float gap ; /* Set the gap between characters */ + + int exists [ FNTMAX_CHAR ] ; /* TRUE if character exists in tex-map */ + + /* + The quadrilaterals that describe the characters + in the font are drawn with the following texture + and spatial coordinates. The texture coordinates + are in (S,T) space, with (0,0) at the bottom left + of the image and (1,1) at the top-right. + + The spatial coordinates are relative to the current + 'cursor' position. They should be scaled such that + 1.0 represent the height of a capital letter. Hence, + characters like 'y' which have a descender will be + given a negative v_bot. Most capitals will have + v_bot==0.0 and v_top==1.0. + */ + + /* Nominal baseline widths */ + + float widths [ FNTMAX_CHAR ] ; + + /* Texture coordinates */ + + float t_top [ FNTMAX_CHAR ] ; /* Top edge of each character [0..1] */ + float t_bot [ FNTMAX_CHAR ] ; /* Bottom edge of each character [0..1] */ + float t_left [ FNTMAX_CHAR ] ; /* Left edge of each character [0..1] */ + float t_right [ FNTMAX_CHAR ] ; /* Right edge of each character [0..1] */ + + /* Vertex coordinates. */ + + float v_top [ FNTMAX_CHAR ] ; + float v_bot [ FNTMAX_CHAR ] ; + float v_left [ FNTMAX_CHAR ] ; + float v_right [ FNTMAX_CHAR ] ; + + void bind_texture () + { + glEnable ( GL_TEXTURE_2D ) ; +#ifdef GL_VERSION_1_1 + glBindTexture ( GL_TEXTURE_2D, texture ) ; +#else + /* For ancient SGI machines */ + glBindTextureEXT ( GL_TEXTURE_2D, texture ) ; +#endif + } + + float low_putch ( sgVec3 curpos, float pointsize, float italic, char c ) ; + + int loadTXF ( const char *fname, GLenum mag = GL_NEAREST, + GLenum min = GL_LINEAR_MIPMAP_LINEAR ) ; +public: + + fntTexFont () + { + bound = FNT_FALSE ; + fixed_pitch = FNT_TRUE ; + texture = 0 ; + width = 1.0f ; + gap = 0.1f ; + + memset ( exists, FNT_FALSE, FNTMAX_CHAR * sizeof(int) ) ; + } + + fntTexFont ( const char *fname, GLenum mag = GL_NEAREST, + GLenum min = GL_LINEAR_MIPMAP_LINEAR ) : fntFont () + { + bound = FNT_FALSE ; + fixed_pitch = FNT_TRUE ; + texture = 0 ; + width = 1.0f ; + gap = 0.1f ; + + memset ( exists, FNT_FALSE, FNTMAX_CHAR * sizeof(int) ) ; + load ( fname, mag, min ) ; + } + + ~fntTexFont () + { + if ( texture != 0 ) + { +#ifdef GL_VERSION_1_1 + glDeleteTextures ( 1, &texture ) ; +#else + /* For ancient SGI machines */ + glDeleteTexturesEXT ( 1, &texture ) ; +#endif + } + } + + int load ( const char *fname, GLenum mag = GL_NEAREST, + GLenum min = GL_LINEAR_MIPMAP_LINEAR ) ; + + void setFixedPitch ( int fix ) { fixed_pitch = fix ; } + int isFixedPitch () const { return fixed_pitch ; } + + void setWidth ( float w ) { width = w ; } + void setGap ( float g ) { gap = g ; } + + float getWidth () const { return width ; } + float getGap () const { return gap ; } + + + void setGlyph ( char c, float wid, + float tex_left, float tex_right, + float tex_bot , float tex_top , + float vtx_left, float vtx_right, + float vtx_bot , float vtx_top ) ; + void setGlyph ( char c, + float tex_left, float tex_right, + float tex_bot , float tex_top , + float vtx_left, float vtx_right, + float vtx_bot , float vtx_top ) /* deprecated */ + { + setGlyph ( c, vtx_right, + tex_left, tex_right, tex_bot, tex_top, + vtx_left, vtx_right, vtx_bot, vtx_top ) ; + } + + int getGlyph ( char c, float* wid, + float *tex_left = NULL, float *tex_right = NULL, + float *tex_bot = NULL, float *tex_top = NULL, + float *vtx_left = NULL, float *vtx_right = NULL, + float *vtx_bot = NULL, float *vtx_top = NULL) ; + int getGlyph ( char c, + float *tex_left = NULL, float *tex_right = NULL, + float *tex_bot = NULL, float *tex_top = NULL, + float *vtx_left = NULL, float *vtx_right = NULL, + float *vtx_bot = NULL, float *vtx_top = NULL) /* deprecated */ + { + return getGlyph ( c, NULL, + tex_left, tex_right, tex_bot, tex_top, + vtx_left, vtx_right, vtx_bot, vtx_top ) ; + } + + int hasGlyph ( char c ) const { return exists[ (GLubyte) c ] ; } + + void getBBox ( const char *s, float pointsize, float italic, + float *left, float *right, + float *bot , float *top ) ; + + void begin () + { + bind_texture () ; + bound = FNT_TRUE ; + } + + void end () + { + bound = FNT_FALSE ; + } + + void puts ( sgVec3 curpos, float pointsize, float italic, const char *s ) ; + + void putch ( sgVec3 curpos, float pointsize, float italic, char c ) + { + if ( ! bound ) + bind_texture () ; + + low_putch ( curpos, pointsize, italic, c ) ; + } + +} ; + + + +class fntBitmapFont : public fntFont +{ + protected: + + const GLubyte **data; + int first; + int count; + int height; + float xorig, yorig; + int fix; + float wid, gap; + + public: + + // data is a null-terminated list of glyph images: + // data[i][0] - image width + // data[i][1..n] - packed bitmap + + fntBitmapFont ( const GLubyte **data, int first, int height, + float xorig, float yorig ) ; + + virtual ~fntBitmapFont () ; + + virtual void getBBox ( const char *s, float pointsize, float italic, + float *left, float *right, + float *bot , float *top ) ; + + virtual void putch ( sgVec3 curpos, float pointsize, float italic, char c ) ; + virtual void puts ( sgVec3 curpos, float pointsize, float italic, const char *s ) ; + + virtual void begin () ; + virtual void end () ; + + virtual int load ( const char *fname, GLenum mag, GLenum min ) { return -1; } + + virtual void setFixedPitch ( int f ) { fix = f; } + virtual int isFixedPitch () const { return fix; } + + virtual void setWidth ( float w ) { wid = w; } + virtual void setGap ( float g ) { gap = g; } + + virtual float getWidth () const { return wid; } + virtual float getGap () const { return gap; } + + virtual int hasGlyph ( char c ) const ; +}; + + +/* Builtin Bitmap Fonts */ + +#define FNT_BITMAP_8_BY_13 0 +#define FNT_BITMAP_9_BY_15 1 +#define FNT_BITMAP_HELVETICA_10 2 +#define FNT_BITMAP_HELVETICA_12 3 +#define FNT_BITMAP_HELVETICA_18 4 +#define FNT_BITMAP_TIMES_ROMAN_10 5 +#define FNT_BITMAP_TIMES_ROMAN_24 6 + +fntBitmapFont *fntGetBitmapFont(int id); + + + +class fntRenderer +{ + fntFont *font ; + + sgVec3 curpos ; + + float pointsize ; + float italic ; + +public: + fntRenderer () + { + start2f ( 0.0f, 0.0f ) ; + font = NULL ; + pointsize = 10 ; + italic = 0 ; + } + + void start3fv ( sgVec3 pos ) { sgCopyVec3 ( curpos, pos ) ; } + void start2fv ( sgVec2 pos ) { sgCopyVec2 ( curpos, pos ) ; curpos[2]=0.0f ; } + void start2f ( float x, float y ) { sgSetVec3 ( curpos, x, y, 0.0f ) ; } + void start3f ( float x, float y, float z ) { sgSetVec3 ( curpos, x, y, z ) ; } + + void getCursor ( float *x, float *y, float *z ) const + { + if ( x != NULL ) *x = curpos [ 0 ] ; + if ( y != NULL ) *y = curpos [ 1 ] ; + if ( z != NULL ) *z = curpos [ 2 ] ; + } + + void setFont ( fntFont *f ) { font = f ; } + fntFont *getFont () const { return font ; } + + void setSlant ( float i ) { italic = i ; } + void setPointSize ( float p ) { pointsize = p ; } + + float getSlant () const { return italic ; } + float getPointSize () const { return pointsize ; } + + void begin () { font->begin () ; } + void end () { font->end () ; } + + void putch ( char c ) { font->putch ( curpos, pointsize, italic, c ) ; } + void puts ( const char *s ) { font->puts ( curpos, pointsize, italic, s ) ; } +} ; + + +void fntInit () ; + +#endif + diff --git a/src/fnt/fntBitmap.cxx b/src/fnt/fntBitmap.cxx new file mode 100644 index 0000000..1976d6f --- /dev/null +++ b/src/fnt/fntBitmap.cxx @@ -0,0 +1,1017 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: fntBitmap.cxx 2036 2005-07-14 16:37:55Z fayjf $ +*/ + + +#include "fnt.h" + + +fntBitmapFont::fntBitmapFont( const GLubyte **_data, int _first, int _height, + float _xorig, float _yorig ) +{ + data = _data; + first = _first; + count = 0; + height = _height; + xorig = _xorig; + yorig = _yorig; + fix = 0; + wid = 0; + gap = 0; + + while (data[count] != NULL) + count++; +} + + +fntBitmapFont::~fntBitmapFont() +{ +} + + +void fntBitmapFont::begin () +{ + glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); +} + + +void fntBitmapFont::end () +{ + glPopClientAttrib(); +} + + +void fntBitmapFont::putch ( sgVec3 curpos, float pointsize, float italic, char c ) +{ + if (c == '\n') { + curpos[1] -= height; + } else { + glRasterPos2i(0,0); // beware - coordinate may be negative + glBitmap(0, 0, 0, 0, curpos[0], curpos[1], NULL); + int i = (GLubyte) c - first; + if (i >= 0 && i < count) { + glBitmap(data[i][0], height, xorig, yorig, (float) data[i][0], 0, data[i] + 1); + curpos[0] += data[i][0]; + } + } +} + + +void fntBitmapFont::puts ( sgVec3 curpos, float pointsize, float italic, const char *s ) +{ + float x0 = curpos[0]; + glRasterPos2i(0,0); // beware - coordinate may be negative + glBitmap(0, 0, 0, 0, curpos[0], curpos[1], NULL); + for (int i = 0; s[i] != '\0'; i++) { + if (s[i] == '\n') { + curpos[0] = x0; + curpos[1] -= height; + glRasterPos2i(0,0); // beware - coordinate may be negative + glBitmap(0, 0, 0, 0, curpos[0], curpos[1], NULL); + } else { + int j = (GLubyte) s[i] - first; + if (j >= 0 && j < count) { + glBitmap(data[j][0], height, xorig, yorig, (float) data[j][0], 0, data[j] + 1); + curpos[0] += data[j][0]; + } + } + } +} + + +int fntBitmapFont::hasGlyph ( char c ) const +{ + int i = (GLubyte) c - first; + return i >= 0 && i < count && data[i][0] > 0; +} + + +void fntBitmapFont::getBBox ( const char *s, float pointsize, float italic, + float *left, float *right, + float *bot , float *top ) +{ + float l, r, b, t; + + if (count > 0) { + int x1 = 0, y1 = 0, x = 0, y = 0; + for (int i = 0; s[i] != '\0'; i++) { + if (s[i] == '\n') { + if (x > x1) x1 = x; + y -= height; + x = 0; + } else { + int j = (GLubyte) s[i] - first; + if (j >= 0 && j < count && data[j][0] > 0) { + x += data[j][0]; + y1 = y; + } + } + } + if (x > x1) x1 = x; + l = - xorig; + r = (float) x1 - xorig; + b = (float) y1 - yorig; + t = (float) height - yorig; + } else { + l = r = b = t = 0.0f; + } + + if (left != NULL) *left = l; + if (right != NULL) *right = r; + if (bot != NULL) *bot = b; + if (top != NULL) *top = t; +} + + + +// This is to match the FreeGLUT definitions below + +struct SFG_Font { + char* Name; /* The source font name */ + int Quantity; /* Number of chars in font */ + int Height; /* Height of the characters */ + const GLubyte** Characters; /* The characters mapping */ + + float xorig, yorig; /* Relative origin of the character */ +}; + + +/* + * Below is the font data taken from FreeGLUT. Nothing is changed except + * the structures are made "static" to avoid namespace pollution. + */ + + +/* + * freeglut_font_data.c + * + * This file has been automatically generated by the genfonts utility. + * + * Copyright (c) 1999-2000 by Pawel W. Olszta + * Written by Pawel W. Olszta, + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Sotware. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * Following fonts are defined in this file: + * + * 1. fgFontFixed8x13 <-misc-fixed-medium-r-normal--13-120-75-75-C-80-iso8859-1> + * 2. fgFontFixed9x15 <-misc-fixed-medium-r-normal--15-140-75-75-C-90-iso8859-1> + * 3. fgFontHelvetica10 <-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1> + * 4. fgFontHelvetica12 <-adobe-helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1> + * 5. fgFontHelvetica18 <-adobe-helvetica-medium-r-normal--18-180-75-75-p-98-iso8859-1> + * 6. fgFontTimesRoman10 <-adobe-times-medium-r-normal--10-100-75-75-p-54-iso8859-1> + * 7. fgFontTimesRoman24 <-adobe-times-medium-r-normal--24-240-75-75-p-124-iso8859-1> + */ + +static const GLubyte Fixed8x13_Character_032[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* blank */ +static const GLubyte Fixed8x13_Character_097[] = { 8, 0, 0,116,140,132,124, 4,120, 0, 0, 0, 0, 0}; /* "a" */ +static const GLubyte Fixed8x13_Character_098[] = { 8, 0, 0,184,196,132,132,196,184,128,128,128, 0, 0}; +static const GLubyte Fixed8x13_Character_099[] = { 8, 0, 0,120,132,128,128,132,120, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_100[] = { 8, 0, 0,116,140,132,132,140,116, 4, 4, 4, 0, 0}; +static const GLubyte Fixed8x13_Character_101[] = { 8, 0, 0,120,132,128,252,132,120, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_102[] = { 8, 0, 0, 64, 64, 64, 64,248, 64, 64, 68, 56, 0, 0}; +static const GLubyte Fixed8x13_Character_103[] = { 8,120,132,120,128,112,136,136,116, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_104[] = { 8, 0, 0,132,132,132,132,196,184,128,128,128, 0, 0}; +static const GLubyte Fixed8x13_Character_105[] = { 8, 0, 0,248, 32, 32, 32, 32, 96, 0, 32, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_106[] = { 8,112,136,136, 8, 8, 8, 8, 24, 0, 8, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_107[] = { 8, 0, 0,132,136,144,224,144,136,128,128,128, 0, 0}; +static const GLubyte Fixed8x13_Character_108[] = { 8, 0, 0,248, 32, 32, 32, 32, 32, 32, 32, 96, 0, 0}; +static const GLubyte Fixed8x13_Character_109[] = { 8, 0, 0,130,146,146,146,146,236, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_110[] = { 8, 0, 0,132,132,132,132,196,184, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_111[] = { 8, 0, 0,120,132,132,132,132,120, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_112[] = { 8,128,128,128,184,196,132,196,184, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_113[] = { 8, 4, 4, 4,116,140,132,140,116, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_114[] = { 8, 0, 0, 64, 64, 64, 64, 68,184, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_115[] = { 8, 0, 0,120,132, 24, 96,132,120, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_116[] = { 8, 0, 0, 56, 68, 64, 64, 64,248, 64, 64, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_117[] = { 8, 0, 0,116,136,136,136,136,136, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_119[] = { 8, 0, 0, 68,170,146,146,130,130, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_118[] = { 8, 0, 0, 32, 80, 80,136,136,136, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_120[] = { 8, 0, 0,132, 72, 48, 48, 72,132, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_121[] = { 8,120,132, 4,116,140,132,132,132, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_122[] = { 8, 0, 0,252, 64, 32, 16, 8,252, 0, 0, 0, 0, 0}; /* "z" */ +static const GLubyte Fixed8x13_Character_065[] = { 8, 0, 0,132,132,132,252,132,132,132, 72, 48, 0, 0}; /* "A" */ +static const GLubyte Fixed8x13_Character_066[] = { 8, 0, 0,252, 66, 66, 66,124, 66, 66, 66,252, 0, 0}; +static const GLubyte Fixed8x13_Character_067[] = { 8, 0, 0,120,132,128,128,128,128,128,132,120, 0, 0}; +static const GLubyte Fixed8x13_Character_068[] = { 8, 0, 0,252, 66, 66, 66, 66, 66, 66, 66,252, 0, 0}; +static const GLubyte Fixed8x13_Character_069[] = { 8, 0, 0,252,128,128,128,240,128,128,128,252, 0, 0}; +static const GLubyte Fixed8x13_Character_070[] = { 8, 0, 0,128,128,128,128,240,128,128,128,252, 0, 0}; +static const GLubyte Fixed8x13_Character_071[] = { 8, 0, 0,116,140,132,156,128,128,128,132,120, 0, 0}; +static const GLubyte Fixed8x13_Character_072[] = { 8, 0, 0,132,132,132,132,252,132,132,132,132, 0, 0}; +static const GLubyte Fixed8x13_Character_073[] = { 8, 0, 0,248, 32, 32, 32, 32, 32, 32, 32,248, 0, 0}; +static const GLubyte Fixed8x13_Character_074[] = { 8, 0, 0,112,136, 8, 8, 8, 8, 8, 8, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_075[] = { 8, 0, 0,132,136,144,160,192,160,144,136,132, 0, 0}; +static const GLubyte Fixed8x13_Character_076[] = { 8, 0, 0,252,128,128,128,128,128,128,128,128, 0, 0}; +static const GLubyte Fixed8x13_Character_077[] = { 8, 0, 0,130,130,130,146,146,170,198,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_078[] = { 8, 0, 0,132,132,132,140,148,164,196,132,132, 0, 0}; +static const GLubyte Fixed8x13_Character_079[] = { 8, 0, 0,120,132,132,132,132,132,132,132,120, 0, 0}; +static const GLubyte Fixed8x13_Character_080[] = { 8, 0, 0,128,128,128,128,248,132,132,132,248, 0, 0}; +static const GLubyte Fixed8x13_Character_081[] = { 8, 0, 4,120,148,164,132,132,132,132,132,120, 0, 0}; +static const GLubyte Fixed8x13_Character_082[] = { 8, 0, 0,132,136,144,160,248,132,132,132,248, 0, 0}; +static const GLubyte Fixed8x13_Character_083[] = { 8, 0, 0,120,132, 4, 4,120,128,128,132,120, 0, 0}; +static const GLubyte Fixed8x13_Character_084[] = { 8, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16,254, 0, 0}; +static const GLubyte Fixed8x13_Character_085[] = { 8, 0, 0,120,132,132,132,132,132,132,132,132, 0, 0}; +static const GLubyte Fixed8x13_Character_087[] = { 8, 0, 0, 68,170,146,146,146,130,130,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_086[] = { 8, 0, 0, 16, 40, 40, 40, 68, 68, 68,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_088[] = { 8, 0, 0,130,130, 68, 40, 16, 40, 68,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_089[] = { 8, 0, 0, 16, 16, 16, 16, 16, 40, 68,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_090[] = { 8, 0, 0,252,128,128, 64, 32, 16, 8, 4,252, 0, 0}; /* "Z" */ +static const GLubyte Fixed8x13_Character_048[] = { 8, 0, 0, 48, 72,132,132,132,132,132, 72, 48, 0, 0}; /* "0" */ +static const GLubyte Fixed8x13_Character_049[] = { 8, 0, 0,248, 32, 32, 32, 32, 32,160, 96, 32, 0, 0}; +static const GLubyte Fixed8x13_Character_050[] = { 8, 0, 0,252,128, 64, 48, 8, 4,132,132,120, 0, 0}; +static const GLubyte Fixed8x13_Character_051[] = { 8, 0, 0,120,132, 4, 4, 56, 16, 8, 4,252, 0, 0}; +static const GLubyte Fixed8x13_Character_052[] = { 8, 0, 0, 8, 8,252,136,136, 72, 40, 24, 8, 0, 0}; +static const GLubyte Fixed8x13_Character_053[] = { 8, 0, 0,120,132, 4, 4,196,184,128,128,252, 0, 0}; +static const GLubyte Fixed8x13_Character_054[] = { 8, 0, 0,120,132,132,196,184,128,128, 64, 56, 0, 0}; +static const GLubyte Fixed8x13_Character_055[] = { 8, 0, 0, 64, 64, 32, 32, 16, 16, 8, 4,252, 0, 0}; +static const GLubyte Fixed8x13_Character_056[] = { 8, 0, 0,120,132,132,132,120,132,132,132,120, 0, 0}; +static const GLubyte Fixed8x13_Character_057[] = { 8, 0, 0,112, 8, 4, 4,116,140,132,132,120, 0, 0}; /* "9" */ +static const GLubyte Fixed8x13_Character_096[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 16, 96,224, 0, 0}; /* "`" */ +static const GLubyte Fixed8x13_Character_126[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,144,168, 72, 0, 0}; /* "~" */ +static const GLubyte Fixed8x13_Character_033[] = { 8, 0, 0,128, 0,128,128,128,128,128,128,128, 0, 0}; /* "!" */ +static const GLubyte Fixed8x13_Character_064[] = { 8, 0, 0,120,128,148,172,164,156,132,132,120, 0, 0}; /* "@" */ +static const GLubyte Fixed8x13_Character_035[] = { 8, 0, 0, 0, 72, 72,252, 72,252, 72, 72, 0, 0, 0}; /* "#" */ +static const GLubyte Fixed8x13_Character_036[] = { 8, 0, 0, 0, 32,240, 40,112,160,120, 32, 0, 0, 0}; /* "$" */ +static const GLubyte Fixed8x13_Character_037[] = { 8, 0, 0,136, 84, 72, 32, 16, 16, 72,164, 68, 0, 0}; /* "%" */ +static const GLubyte Fixed8x13_Character_094[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,136, 80, 32, 0, 0}; /* "^" */ +static const GLubyte Fixed8x13_Character_038[] = { 8, 0, 0,116,136,148, 96,144,144, 96, 0, 0, 0, 0}; /* "&" */ +static const GLubyte Fixed8x13_Character_042[] = { 8, 0, 0, 0, 0, 72, 48,252, 48, 72, 0, 0, 0, 0}; /* "*" */ +static const GLubyte Fixed8x13_Character_040[] = { 8, 0, 0, 32, 64, 64,128,128,128, 64, 64, 32, 0, 0}; /* "(" */ +static const GLubyte Fixed8x13_Character_041[] = { 8, 0, 0,128, 64, 64, 32, 32, 32, 64, 64,128, 0, 0}; /* ")" */ +static const GLubyte Fixed8x13_Character_045[] = { 8, 0, 0, 0, 0, 0, 0,252, 0, 0, 0, 0, 0, 0}; /* "-" */ +static const GLubyte Fixed8x13_Character_095[] = { 8, 0,254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "_" */ +static const GLubyte Fixed8x13_Character_061[] = { 8, 0, 0, 0, 0,252, 0, 0,252, 0, 0, 0, 0, 0}; /* "=" */ +static const GLubyte Fixed8x13_Character_043[] = { 8, 0, 0, 0, 0, 32, 32,248, 32, 32, 0, 0, 0, 0}; /* "+" */ +static const GLubyte Fixed8x13_Character_091[] = { 8, 0, 0,240,128,128,128,128,128,128,128,240, 0, 0}; /* "[" */ +static const GLubyte Fixed8x13_Character_123[] = { 8, 0, 0, 56, 64, 64, 32,192, 32, 64, 64, 56, 0, 0}; /* "{" */ +static const GLubyte Fixed8x13_Character_125[] = { 8, 0, 0,224, 16, 16, 32, 24, 32, 16, 16,224, 0, 0}; /* "}" */ +static const GLubyte Fixed8x13_Character_093[] = { 8, 0, 0,240, 16, 16, 16, 16, 16, 16, 16,240, 0, 0}; /* "]" */ +static const GLubyte Fixed8x13_Character_059[] = { 8, 0,128, 96,112, 0, 0, 32,112, 32, 0, 0, 0, 0}; /* ";" */ +static const GLubyte Fixed8x13_Character_058[] = { 8, 0, 64,224, 64, 0, 0, 64,224, 64, 0, 0, 0, 0}; /* ":" */ +static const GLubyte Fixed8x13_Character_044[] = { 8, 0,128, 96,112, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "," */ +static const GLubyte Fixed8x13_Character_046[] = { 8, 0, 64,224, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "." */ +static const GLubyte Fixed8x13_Character_060[] = { 8, 0, 0, 8, 16, 32, 64,128, 64, 32, 16, 8, 0, 0}; /* "<" */ +static const GLubyte Fixed8x13_Character_062[] = { 8, 0, 0,128, 64, 32, 16, 8, 16, 32, 64,128, 0, 0}; /* ">" */ +static const GLubyte Fixed8x13_Character_047[] = { 8, 0, 0,128,128, 64, 32, 16, 8, 4, 2, 2, 0, 0}; /* "/" */ +static const GLubyte Fixed8x13_Character_063[] = { 8, 0, 0, 16, 0, 16, 16, 8, 4,132,132,120, 0, 0}; /* "?" */ +static const GLubyte Fixed8x13_Character_092[] = { 8, 0, 0, 2, 2, 4, 8, 16, 32, 64,128,128, 0, 0}; /* "\" */ +static const GLubyte Fixed8x13_Character_034[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0,144,144,144, 0, 0}; /* """ */ + +/* Missing Characters filled in by John Fay by hand ... */ +static const GLubyte Fixed8x13_Character_039[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 32, 0, 0}; /* """ */ +static const GLubyte Fixed8x13_Character_124[] = { 8, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0}; /* """ */ + + +/* The font characters mapping: */ +static const GLubyte* Fixed8x13_Character_Map[] = {Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_032,Fixed8x13_Character_033,Fixed8x13_Character_034,Fixed8x13_Character_035,Fixed8x13_Character_036,Fixed8x13_Character_037,Fixed8x13_Character_038,Fixed8x13_Character_039,Fixed8x13_Character_040, + Fixed8x13_Character_041,Fixed8x13_Character_042,Fixed8x13_Character_043,Fixed8x13_Character_044,Fixed8x13_Character_045,Fixed8x13_Character_046,Fixed8x13_Character_047,Fixed8x13_Character_048,Fixed8x13_Character_049,Fixed8x13_Character_050,Fixed8x13_Character_051,Fixed8x13_Character_052,Fixed8x13_Character_053,Fixed8x13_Character_054,Fixed8x13_Character_055,Fixed8x13_Character_056,Fixed8x13_Character_057,Fixed8x13_Character_058,Fixed8x13_Character_059,Fixed8x13_Character_060,Fixed8x13_Character_061,Fixed8x13_Character_062,Fixed8x13_Character_063,Fixed8x13_Character_064,Fixed8x13_Character_065,Fixed8x13_Character_066,Fixed8x13_Character_067,Fixed8x13_Character_068,Fixed8x13_Character_069,Fixed8x13_Character_070,Fixed8x13_Character_071,Fixed8x13_Character_072,Fixed8x13_Character_073,Fixed8x13_Character_074,Fixed8x13_Character_075,Fixed8x13_Character_076,Fixed8x13_Character_077,Fixed8x13_Character_078,Fixed8x13_Character_079,Fixed8x13_Character_080,Fixed8x13_Character_081,Fixed8x13_Character_082, + Fixed8x13_Character_083,Fixed8x13_Character_084,Fixed8x13_Character_085,Fixed8x13_Character_086,Fixed8x13_Character_087,Fixed8x13_Character_088,Fixed8x13_Character_089,Fixed8x13_Character_090,Fixed8x13_Character_091,Fixed8x13_Character_092,Fixed8x13_Character_093,Fixed8x13_Character_094,Fixed8x13_Character_095,Fixed8x13_Character_096,Fixed8x13_Character_097,Fixed8x13_Character_098,Fixed8x13_Character_099,Fixed8x13_Character_100,Fixed8x13_Character_101,Fixed8x13_Character_102,Fixed8x13_Character_103,Fixed8x13_Character_104,Fixed8x13_Character_105,Fixed8x13_Character_106,Fixed8x13_Character_107,Fixed8x13_Character_108,Fixed8x13_Character_109,Fixed8x13_Character_110,Fixed8x13_Character_111,Fixed8x13_Character_112,Fixed8x13_Character_113,Fixed8x13_Character_114,Fixed8x13_Character_115,Fixed8x13_Character_116,Fixed8x13_Character_117,Fixed8x13_Character_118,Fixed8x13_Character_119,Fixed8x13_Character_120,Fixed8x13_Character_121,Fixed8x13_Character_122,Fixed8x13_Character_123,Fixed8x13_Character_124, + Fixed8x13_Character_125,Fixed8x13_Character_126,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042, + Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042, + Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042, + Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,Fixed8x13_Character_042,NULL}; + +/* The font structure: */ +static const SFG_Font fgFontFixed8x13 = { "-misc-fixed-medium-r-normal--13-120-75-75-C-80-iso8859-1", 93, 13, Fixed8x13_Character_Map, -1.0f, 2.0f }; + +static const GLubyte Fixed9x15_Character_032[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* blank */ +static const GLubyte Fixed9x15_Character_097[] = { 9, 0, 0, 0, 0, 0, 0,122, 0,134, 0,130, 0,126, 0, 2, 0, 2, 0,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "a" */ +static const GLubyte Fixed9x15_Character_098[] = { 9, 0, 0, 0, 0, 0, 0,188, 0,194, 0,130, 0,130, 0,130, 0,194, 0,188, 0,128, 0,128, 0,128, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_099[] = { 9, 0, 0, 0, 0, 0, 0,124, 0,130, 0,128, 0,128, 0,128, 0,130, 0,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_100[] = { 9, 0, 0, 0, 0, 0, 0,122, 0,134, 0,130, 0,130, 0,130, 0,134, 0,122, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_101[] = { 9, 0, 0, 0, 0, 0, 0,124, 0,128, 0,128, 0,254, 0,130, 0,130, 0,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_102[] = { 9, 0, 0, 0, 0, 0, 0, 32, 0, 32, 0, 32, 0, 32, 0,248, 0, 32, 0, 32, 0, 34, 0, 34, 0, 28, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_103[] = { 9,124, 0,130, 0,130, 0,124, 0,128, 0,120, 0,132, 0,132, 0,132, 0,122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_104[] = { 9, 0, 0, 0, 0, 0, 0,130, 0,130, 0,130, 0,130, 0,130, 0,194, 0,188, 0,128, 0,128, 0,128, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_105[] = { 9, 0, 0, 0, 0, 0, 0,248, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0,224, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_106[] = { 9,120, 0,132, 0,132, 0,132, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_107[] = { 9, 0, 0, 0, 0, 0, 0,130, 0,140, 0,176, 0,192, 0,176, 0,140, 0,130, 0,128, 0,128, 0,128, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_108[] = { 9, 0, 0, 0, 0, 0, 0,248, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0,224, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_109[] = { 9, 0, 0, 0, 0, 0, 0,130, 0,146, 0,146, 0,146, 0,146, 0,146, 0,236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_110[] = { 9, 0, 0, 0, 0, 0, 0,130, 0,130, 0,130, 0,130, 0,130, 0,194, 0,188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_111[] = { 9, 0, 0, 0, 0, 0, 0,124, 0,130, 0,130, 0,130, 0,130, 0,130, 0,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_112[] = { 9,128, 0,128, 0,128, 0,188, 0,194, 0,130, 0,130, 0,130, 0,194, 0,188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_113[] = { 9, 2, 0, 2, 0, 2, 0,122, 0,134, 0,130, 0,130, 0,130, 0,134, 0,122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_114[] = { 9, 0, 0, 0, 0, 0, 0, 64, 0, 64, 0, 64, 0, 64, 0, 66, 0, 98, 0,156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_115[] = { 9, 0, 0, 0, 0, 0, 0,124, 0,130, 0, 2, 0,124, 0,128, 0,130, 0,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_116[] = { 9, 0, 0, 0, 0, 0, 0, 28, 0, 34, 0, 32, 0, 32, 0, 32, 0, 32, 0,252, 0, 32, 0, 32, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_117[] = { 9, 0, 0, 0, 0, 0, 0,122, 0,132, 0,132, 0,132, 0,132, 0,132, 0,132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_119[] = { 9, 0, 0, 0, 0, 0, 0, 68, 0,170, 0,146, 0,146, 0,146, 0,130, 0,130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_118[] = { 9, 0, 0, 0, 0, 0, 0, 16, 0, 40, 0, 40, 0, 68, 0, 68, 0,130, 0,130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_120[] = { 9, 0, 0, 0, 0, 0, 0,130, 0, 68, 0, 40, 0, 16, 0, 40, 0, 68, 0,130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_121[] = { 9,120, 0,132, 0, 4, 0,116, 0,140, 0,132, 0,132, 0,132, 0,132, 0,132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_122[] = { 9, 0, 0, 0, 0, 0, 0,254, 0, 64, 0, 32, 0, 16, 0, 8, 0, 4, 0,254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "z" */ +static const GLubyte Fixed9x15_Character_065[] = { 9, 0, 0, 0, 0, 0, 0,130, 0,130, 0,130, 0,254, 0,130, 0,130, 0,130, 0, 68, 0, 40, 0, 16, 0, 0, 0, 0, 0}; /* "A" */ +static const GLubyte Fixed9x15_Character_066[] = { 9, 0, 0, 0, 0, 0, 0,252, 0, 66, 0, 66, 0, 66, 0, 66, 0,124, 0, 66, 0, 66, 0, 66, 0,252, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_067[] = { 9, 0, 0, 0, 0, 0, 0,124, 0,130, 0,128, 0,128, 0,128, 0,128, 0,128, 0,128, 0,130, 0,124, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_068[] = { 9, 0, 0, 0, 0, 0, 0,252, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0, 66, 0,252, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_069[] = { 9, 0, 0, 0, 0, 0, 0,254, 0, 64, 0, 64, 0, 64, 0, 64, 0,120, 0, 64, 0, 64, 0, 64, 0,254, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_070[] = { 9, 0, 0, 0, 0, 0, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0,120, 0, 64, 0, 64, 0, 64, 0,254, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_071[] = { 9, 0, 0, 0, 0, 0, 0,124, 0,130, 0,130, 0,130, 0,142, 0,128, 0,128, 0,128, 0,130, 0,124, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_072[] = { 9, 0, 0, 0, 0, 0, 0,130, 0,130, 0,130, 0,130, 0,130, 0,254, 0,130, 0,130, 0,130, 0,130, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_073[] = { 9, 0, 0, 0, 0, 0, 0,248, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0,248, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_074[] = { 9, 0, 0, 0, 0, 0, 0,120, 0,132, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 30, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_075[] = { 9, 0, 0, 0, 0, 0, 0,130, 0,132, 0,136, 0,144, 0,160, 0,224, 0,144, 0,136, 0,132, 0,130, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_076[] = { 9, 0, 0, 0, 0, 0, 0,254, 0,128, 0,128, 0,128, 0,128, 0,128, 0,128, 0,128, 0,128, 0,128, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_077[] = { 9, 0, 0, 0, 0, 0, 0,130, 0,130, 0,130, 0,146, 0,146, 0,170, 0,170, 0,198, 0,130, 0,130, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_078[] = { 9, 0, 0, 0, 0, 0, 0,130, 0,130, 0,130, 0,134, 0,138, 0,146, 0,162, 0,194, 0,130, 0,130, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_079[] = { 9, 0, 0, 0, 0, 0, 0,124, 0,130, 0,130, 0,130, 0,130, 0,130, 0,130, 0,130, 0,130, 0,124, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_080[] = { 9, 0, 0, 0, 0, 0, 0,128, 0,128, 0,128, 0,128, 0,128, 0,252, 0,130, 0,130, 0,130, 0,252, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_081[] = { 9, 0, 0, 6, 0, 8, 0,124, 0,146, 0,162, 0,130, 0,130, 0,130, 0,130, 0,130, 0,130, 0,124, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_082[] = { 9, 0, 0, 0, 0, 0, 0,130, 0,130, 0,132, 0,136, 0,144, 0,252, 0,130, 0,130, 0,130, 0,252, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_083[] = { 9, 0, 0, 0, 0, 0, 0,124, 0,130, 0,130, 0, 2, 0, 12, 0,112, 0,128, 0,130, 0,130, 0,124, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_084[] = { 9, 0, 0, 0, 0, 0, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0,254, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_085[] = { 9, 0, 0, 0, 0, 0, 0,124, 0,130, 0,130, 0,130, 0,130, 0,130, 0,130, 0,130, 0,130, 0,130, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_087[] = { 9, 0, 0, 0, 0, 0, 0, 68, 0,170, 0,146, 0,146, 0,146, 0,146, 0,130, 0,130, 0,130, 0,130, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_086[] = { 9, 0, 0, 0, 0, 0, 0, 16, 0, 40, 0, 40, 0, 40, 0, 68, 0, 68, 0, 68, 0,130, 0,130, 0,130, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_088[] = { 9, 0, 0, 0, 0, 0, 0,130, 0,130, 0, 68, 0, 40, 0, 16, 0, 16, 0, 40, 0, 68, 0,130, 0,130, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_089[] = { 9, 0, 0, 0, 0, 0, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 40, 0, 68, 0,130, 0,130, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_090[] = { 9, 0, 0, 0, 0, 0, 0,254, 0,128, 0,128, 0, 64, 0, 32, 0, 16, 0, 8, 0, 4, 0, 2, 0,254, 0, 0, 0, 0, 0}; /* "Z" */ +static const GLubyte Fixed9x15_Character_048[] = { 9, 0, 0, 0, 0, 0, 0, 56, 0, 68, 0,130, 0,130, 0,130, 0,130, 0,130, 0,130, 0, 68, 0, 56, 0, 0, 0, 0, 0}; /* "0" */ +static const GLubyte Fixed9x15_Character_049[] = { 9, 0, 0, 0, 0, 0, 0,254, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0,144, 0, 80, 0, 48, 0, 16, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_050[] = { 9, 0, 0, 0, 0, 0, 0,254, 0,128, 0, 64, 0, 48, 0, 8, 0, 4, 0, 2, 0,130, 0,130, 0,124, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_051[] = { 9, 0, 0, 0, 0, 0, 0,124, 0,130, 0, 2, 0, 2, 0, 2, 0, 28, 0, 8, 0, 4, 0, 2, 0,254, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_052[] = { 9, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 4, 0,254, 0,132, 0, 68, 0, 36, 0, 20, 0, 12, 0, 4, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_053[] = { 9, 0, 0, 0, 0, 0, 0,124, 0,130, 0, 2, 0, 2, 0, 2, 0,194, 0,188, 0,128, 0,128, 0,254, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_054[] = { 9, 0, 0, 0, 0, 0, 0,124, 0,130, 0,130, 0,130, 0,194, 0,188, 0,128, 0,128, 0, 64, 0, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_055[] = { 9, 0, 0, 0, 0, 0, 0, 64, 0, 64, 0, 32, 0, 32, 0, 16, 0, 8, 0, 4, 0, 2, 0, 2, 0,254, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_056[] = { 9, 0, 0, 0, 0, 0, 0, 56, 0, 68, 0,130, 0,130, 0, 68, 0, 56, 0, 68, 0,130, 0, 68, 0, 56, 0, 0, 0, 0, 0}; +static const GLubyte Fixed9x15_Character_057[] = { 9, 0, 0, 0, 0, 0, 0,120, 0, 4, 0, 2, 0, 2, 0,122, 0,134, 0,130, 0,130, 0,130, 0,124, 0, 0, 0, 0, 0}; /* "9" */ +static const GLubyte Fixed9x15_Character_096[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 32, 0, 64, 0,192, 0, 0, 0, 0, 0}; /* "`" */ +static const GLubyte Fixed9x15_Character_126[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 0,146, 0, 98, 0, 0, 0, 0, 0}; /* "~" */ +static const GLubyte Fixed9x15_Character_033[] = { 9, 0, 0, 0, 0, 0, 0,128, 0,128, 0, 0, 0, 0, 0,128, 0,128, 0,128, 0,128, 0,128, 0,128, 0,128, 0, 0, 0}; /* "!" */ +static const GLubyte Fixed9x15_Character_064[] = { 9, 0, 0, 0, 0, 0, 0,124, 0,128, 0,128, 0,154, 0,166, 0,162, 0,158, 0,130, 0,130, 0,124, 0, 0, 0, 0, 0}; /* "@" */ +static const GLubyte Fixed9x15_Character_035[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 72, 0,252, 0, 72, 0, 72, 0,252, 0, 72, 0, 72, 0, 0, 0, 0, 0, 0, 0}; /* "#" */ +static const GLubyte Fixed9x15_Character_036[] = { 9, 0, 0, 0, 0, 16, 0,124, 0,146, 0, 18, 0, 18, 0, 20, 0, 56, 0, 80, 0,144, 0,146, 0,124, 0, 16, 0, 0, 0}; /* "$" */ +static const GLubyte Fixed9x15_Character_037[] = { 9, 0, 0, 0, 0, 0, 0,132, 0, 74, 0, 74, 0, 36, 0, 16, 0, 16, 0, 72, 0,164, 0,164, 0, 66, 0, 0, 0, 0, 0}; /* "%" */ +static const GLubyte Fixed9x15_Character_094[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,130, 0, 68, 0, 40, 0, 16, 0, 0, 0, 0, 0}; /* "^" */ +static const GLubyte Fixed9x15_Character_038[] = { 9, 0, 0, 0, 0, 0, 0, 98, 0,148, 0,136, 0,148, 0, 98, 0, 96, 0,144, 0,144, 0,144, 0, 96, 0, 0, 0, 0, 0}; /* "&" */ +static const GLubyte Fixed9x15_Character_042[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0,146, 0, 84, 0, 56, 0, 84, 0,146, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "*" */ +static const GLubyte Fixed9x15_Character_040[] = { 9, 0, 0, 0, 0, 32, 0, 64, 0, 64, 0,128, 0,128, 0,128, 0,128, 0,128, 0,128, 0, 64, 0, 64, 0, 32, 0, 0, 0}; /* "(" */ +static const GLubyte Fixed9x15_Character_041[] = { 9, 0, 0, 0, 0,128, 0, 64, 0, 64, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 64, 0, 64, 0,128, 0, 0, 0}; /* ")" */ +static const GLubyte Fixed9x15_Character_045[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "-" */ +static const GLubyte Fixed9x15_Character_095[] = { 9, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "_" */ +static const GLubyte Fixed9x15_Character_061[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254, 0, 0, 0, 0, 0,254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "=" */ +static const GLubyte Fixed9x15_Character_043[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 16, 0, 16, 0,254, 0, 16, 0, 16, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "+" */ +static const GLubyte Fixed9x15_Character_091[] = { 9, 0, 0, 0, 0,240, 0,128, 0,128, 0,128, 0,128, 0,128, 0,128, 0,128, 0,128, 0,128, 0,128, 0,240, 0, 0, 0}; /* "[" */ +static const GLubyte Fixed9x15_Character_123[] = { 9, 0, 0, 0, 0, 56, 0, 64, 0, 64, 0, 64, 0, 32, 0,192, 0,192, 0, 32, 0, 64, 0, 64, 0, 64, 0, 56, 0, 0, 0}; /* "{" */ +static const GLubyte Fixed9x15_Character_125[] = { 9, 0, 0, 0, 0,224, 0, 16, 0, 16, 0, 16, 0, 32, 0, 24, 0, 24, 0, 32, 0, 16, 0, 16, 0, 16, 0,224, 0, 0, 0}; /* "}" */ +static const GLubyte Fixed9x15_Character_093[] = { 9, 0, 0, 0, 0,240, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0,240, 0, 0, 0}; /* "]" */ +static const GLubyte Fixed9x15_Character_059[] = { 9,128, 0, 64, 0, 64, 0,192, 0,192, 0, 0, 0, 0, 0, 0, 0,192, 0,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* ";" */ +static const GLubyte Fixed9x15_Character_058[] = { 9, 0, 0, 0, 0, 0, 0,192, 0,192, 0, 0, 0, 0, 0, 0, 0,192, 0,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* ":" */ +static const GLubyte Fixed9x15_Character_044[] = { 9,128, 0, 64, 0, 64, 0,192, 0,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "," */ +static const GLubyte Fixed9x15_Character_046[] = { 9, 0, 0, 0, 0, 0, 0,192, 0,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "." */ +static const GLubyte Fixed9x15_Character_060[] = { 9, 0, 0, 0, 0, 0, 0, 8, 0, 16, 0, 32, 0, 64, 0,128, 0,128, 0, 64, 0, 32, 0, 16, 0, 8, 0, 0, 0, 0, 0}; /* "<" */ +static const GLubyte Fixed9x15_Character_062[] = { 9, 0, 0, 0, 0, 0, 0,128, 0, 64, 0, 32, 0, 16, 0, 8, 0, 8, 0, 16, 0, 32, 0, 64, 0,128, 0, 0, 0, 0, 0}; /* ">" */ +static const GLubyte Fixed9x15_Character_047[] = { 9, 0, 0, 0, 0, 0, 0,128, 0, 64, 0, 64, 0, 32, 0, 16, 0, 16, 0, 8, 0, 4, 0, 4, 0, 2, 0, 0, 0, 0, 0}; /* "/" */ +static const GLubyte Fixed9x15_Character_063[] = { 9, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 0, 8, 0, 4, 0, 2, 0,130, 0,130, 0,124, 0, 0, 0, 0, 0}; /* "?" */ +static const GLubyte Fixed9x15_Character_092[] = { 9, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 4, 0, 8, 0, 16, 0, 16, 0, 32, 0, 64, 0, 64, 0,128, 0, 0, 0, 0, 0}; /* "\" */ +static const GLubyte Fixed9x15_Character_034[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,144, 0,144, 0,144, 0, 0, 0, 0, 0}; /* """ */ + +/* Missing Characters filled in by John Fay by hand ... */ +static const GLubyte Fixed9x15_Character_039[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 32, 0, 32, 0, 32, 0, 0, 0, 0, 0}; /* "'" */ +static const GLubyte Fixed9x15_Character_124[] = { 9, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 0, 0, 0, 0}; /* "|" */ + + +/* The font characters mapping: */ +static const GLubyte* Fixed9x15_Character_Map[] = {Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_032,Fixed9x15_Character_033,Fixed9x15_Character_034,Fixed9x15_Character_035,Fixed9x15_Character_036,Fixed9x15_Character_037,Fixed9x15_Character_038,Fixed9x15_Character_039,Fixed9x15_Character_040, + Fixed9x15_Character_041,Fixed9x15_Character_042,Fixed9x15_Character_043,Fixed9x15_Character_044,Fixed9x15_Character_045,Fixed9x15_Character_046,Fixed9x15_Character_047,Fixed9x15_Character_048,Fixed9x15_Character_049,Fixed9x15_Character_050,Fixed9x15_Character_051,Fixed9x15_Character_052,Fixed9x15_Character_053,Fixed9x15_Character_054,Fixed9x15_Character_055,Fixed9x15_Character_056,Fixed9x15_Character_057,Fixed9x15_Character_058,Fixed9x15_Character_059,Fixed9x15_Character_060,Fixed9x15_Character_061,Fixed9x15_Character_062,Fixed9x15_Character_063,Fixed9x15_Character_064,Fixed9x15_Character_065,Fixed9x15_Character_066,Fixed9x15_Character_067,Fixed9x15_Character_068,Fixed9x15_Character_069,Fixed9x15_Character_070,Fixed9x15_Character_071,Fixed9x15_Character_072,Fixed9x15_Character_073,Fixed9x15_Character_074,Fixed9x15_Character_075,Fixed9x15_Character_076,Fixed9x15_Character_077,Fixed9x15_Character_078,Fixed9x15_Character_079,Fixed9x15_Character_080,Fixed9x15_Character_081,Fixed9x15_Character_082, + Fixed9x15_Character_083,Fixed9x15_Character_084,Fixed9x15_Character_085,Fixed9x15_Character_086,Fixed9x15_Character_087,Fixed9x15_Character_088,Fixed9x15_Character_089,Fixed9x15_Character_090,Fixed9x15_Character_091,Fixed9x15_Character_092,Fixed9x15_Character_093,Fixed9x15_Character_094,Fixed9x15_Character_095,Fixed9x15_Character_096,Fixed9x15_Character_097,Fixed9x15_Character_098,Fixed9x15_Character_099,Fixed9x15_Character_100,Fixed9x15_Character_101,Fixed9x15_Character_102,Fixed9x15_Character_103,Fixed9x15_Character_104,Fixed9x15_Character_105,Fixed9x15_Character_106,Fixed9x15_Character_107,Fixed9x15_Character_108,Fixed9x15_Character_109,Fixed9x15_Character_110,Fixed9x15_Character_111,Fixed9x15_Character_112,Fixed9x15_Character_113,Fixed9x15_Character_114,Fixed9x15_Character_115,Fixed9x15_Character_116,Fixed9x15_Character_117,Fixed9x15_Character_118,Fixed9x15_Character_119,Fixed9x15_Character_120,Fixed9x15_Character_121,Fixed9x15_Character_122,Fixed9x15_Character_123,Fixed9x15_Character_124, + Fixed9x15_Character_125,Fixed9x15_Character_126,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042, + Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042, + Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042, + Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,Fixed9x15_Character_042,NULL}; + +/* The font structure: */ +static const SFG_Font fgFontFixed9x15 = { "-misc-fixed-medium-r-normal--15-140-75-75-C-90-iso8859-1", 93, 15, Fixed9x15_Character_Map, -1.0f, 3.0f }; + +static const GLubyte Helvetica10_Character_032[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* " " */ +static const GLubyte Helvetica10_Character_097[] = { 5, 0, 0,104,144,144,112, 16,224, 0, 0, 0, 0, 0}; /* "a" */ +static const GLubyte Helvetica10_Character_098[] = { 6, 0, 0,176,200,136,136,200,176,128,128, 0, 0, 0}; /* "b" */ +static const GLubyte Helvetica10_Character_099[] = { 5, 0, 0, 96,144,128,128,144, 96, 0, 0, 0, 0, 0}; /* "c" */ +static const GLubyte Helvetica10_Character_100[] = { 6, 0, 0,104,152,136,136,152,104, 8, 8, 0, 0, 0}; /* "d" */ +static const GLubyte Helvetica10_Character_101[] = { 5, 0, 0, 96,144,128,240,144, 96, 0, 0, 0, 0, 0}; /* "e" */ +static const GLubyte Helvetica10_Character_102[] = { 4, 0, 0, 64, 64, 64, 64, 64,224, 64, 48, 0, 0, 0}; /* "f" */ +static const GLubyte Helvetica10_Character_103[] = { 6,112, 8,104,152,136,136,152,104, 0, 0, 0, 0, 0}; /* "g" */ +static const GLubyte Helvetica10_Character_104[] = { 6, 0, 0,136,136,136,136,200,176,128,128, 0, 0, 0}; /* "h" */ +static const GLubyte Helvetica10_Character_105[] = { 2, 0, 0,128,128,128,128,128,128, 0,128, 0, 0, 0}; /* "i" */ +static const GLubyte Helvetica10_Character_106[] = { 2, 0,128,128,128,128,128,128,128, 0,128, 0, 0, 0}; /* "j" */ +static const GLubyte Helvetica10_Character_107[] = { 5, 0, 0,144,144,160,192,160,144,128,128, 0, 0, 0}; /* "k" */ +static const GLubyte Helvetica10_Character_108[] = { 2, 0, 0,128,128,128,128,128,128,128,128, 0, 0, 0}; /* "l" */ +static const GLubyte Helvetica10_Character_109[] = { 8, 0, 0,146,146,146,146,146,236, 0, 0, 0, 0, 0}; /* "m" */ +static const GLubyte Helvetica10_Character_110[] = { 6, 0, 0,136,136,136,136,200,176, 0, 0, 0, 0, 0}; /* "n" */ +static const GLubyte Helvetica10_Character_111[] = { 6, 0, 0,112,136,136,136,136,112, 0, 0, 0, 0, 0}; /* "o" */ +static const GLubyte Helvetica10_Character_112[] = { 6,128,128,176,200,136,136,200,176, 0, 0, 0, 0, 0}; /* "p" */ +static const GLubyte Helvetica10_Character_113[] = { 6, 8, 8,104,152,136,136,152,104, 0, 0, 0, 0, 0}; /* "q" */ +static const GLubyte Helvetica10_Character_114[] = { 4, 0, 0,128,128,128,128,192,160, 0, 0, 0, 0, 0}; /* "r" */ +static const GLubyte Helvetica10_Character_115[] = { 5, 0, 0, 96,144, 16, 96,144, 96, 0, 0, 0, 0, 0}; /* "s" */ +static const GLubyte Helvetica10_Character_116[] = { 4, 0, 0, 96, 64, 64, 64, 64,224, 64, 64, 0, 0, 0}; /* "t" */ +static const GLubyte Helvetica10_Character_117[] = { 5, 0, 0,112,144,144,144,144,144, 0, 0, 0, 0, 0}; /* "u" */ +static const GLubyte Helvetica10_Character_118[] = { 6, 0, 0, 32, 32, 80, 80,136,136, 0, 0, 0, 0, 0}; /* "v" */ +static const GLubyte Helvetica10_Character_119[] = { 8, 0, 0, 40, 40, 84, 84,146,146, 0, 0, 0, 0, 0}; /* "w" */ +static const GLubyte Helvetica10_Character_120[] = { 6, 0, 0,136,136, 80, 32, 80,136, 0, 0, 0, 0, 0}; /* "x" */ +static const GLubyte Helvetica10_Character_121[] = { 5,128, 64, 64, 96,160,160,144,144, 0, 0, 0, 0, 0}; /* "y" */ +static const GLubyte Helvetica10_Character_122[] = { 5, 0, 0,240,128, 64, 32, 16,240, 0, 0, 0, 0, 0}; /* "z" */ +static const GLubyte Helvetica10_Character_065[] = { 7, 0, 0,130,130,124, 68, 40, 40, 16, 16, 0, 0, 0}; /* "A" */ +static const GLubyte Helvetica10_Character_066[] = { 7, 0, 0,240,136,136,136,240,136,136,240, 0, 0, 0}; /* "B" */ +static const GLubyte Helvetica10_Character_067[] = { 8, 0, 0,120,132,128,128,128,128,132,120, 0, 0, 0}; /* "C" */ +static const GLubyte Helvetica10_Character_068[] = { 8, 0, 0,240,136,132,132,132,132,136,240, 0, 0, 0}; /* "D" */ +static const GLubyte Helvetica10_Character_069[] = { 7, 0, 0,248,128,128,128,248,128,128,248, 0, 0, 0}; /* "E" */ +static const GLubyte Helvetica10_Character_070[] = { 6, 0, 0,128,128,128,128,240,128,128,248, 0, 0, 0}; /* "F" */ +static const GLubyte Helvetica10_Character_071[] = { 8, 0, 0,116,140,132,140,128,128,132,120, 0, 0, 0}; /* "G" */ +static const GLubyte Helvetica10_Character_072[] = { 8, 0, 0,132,132,132,132,252,132,132,132, 0, 0, 0}; /* "H" */ +static const GLubyte Helvetica10_Character_073[] = { 3, 0, 0,128,128,128,128,128,128,128,128, 0, 0, 0}; /* "I" */ +static const GLubyte Helvetica10_Character_074[] = { 5, 0, 0, 96,144, 16, 16, 16, 16, 16, 16, 0, 0, 0}; /* "J" */ +static const GLubyte Helvetica10_Character_075[] = { 7, 0, 0,136,136,144,144,224,160,144,136, 0, 0, 0}; /* "K" */ +static const GLubyte Helvetica10_Character_076[] = { 6, 0, 0,240,128,128,128,128,128,128,128, 0, 0, 0}; /* "L" */ +static const GLubyte Helvetica10_Character_077[] = { 9, 0, 0, 0, 0,146, 0,146, 0,146, 0,170, 0,170, 0,198, 0,198, 0,130, 0, 0, 0, 0, 0, 0, 0}; /* "M" */ +static const GLubyte Helvetica10_Character_078[] = { 8, 0, 0,140,140,148,148,164,164,196,196, 0, 0, 0}; /* "N" */ +static const GLubyte Helvetica10_Character_079[] = { 8, 0, 0,120,132,132,132,132,132,132,120, 0, 0, 0}; /* "O" */ +static const GLubyte Helvetica10_Character_080[] = { 7, 0, 0,128,128,128,128,240,136,136,240, 0, 0, 0}; /* "P" */ +static const GLubyte Helvetica10_Character_081[] = { 8, 0, 2,124,140,148,132,132,132,132,120, 0, 0, 0}; /* "Q" */ +static const GLubyte Helvetica10_Character_082[] = { 7, 0, 0,136,136,136,136,240,136,136,240, 0, 0, 0}; /* "R" */ +static const GLubyte Helvetica10_Character_083[] = { 7, 0, 0,112,136,136, 8,112,128,136,112, 0, 0, 0}; /* "S" */ +static const GLubyte Helvetica10_Character_084[] = { 5, 0, 0, 32, 32, 32, 32, 32, 32, 32,248, 0, 0, 0}; /* "T" */ +static const GLubyte Helvetica10_Character_085[] = { 8, 0, 0,120,132,132,132,132,132,132,132, 0, 0, 0}; /* "U" */ +static const GLubyte Helvetica10_Character_086[] = { 7, 0, 0, 16, 40, 40, 68, 68, 68,130,130, 0, 0, 0}; /* "V" */ +static const GLubyte Helvetica10_Character_087[] = { 9, 0, 0, 0, 0, 34, 0, 34, 0, 34, 0, 85, 0, 73, 0, 73, 0,136,128,136,128, 0, 0, 0, 0, 0, 0}; /* "W" */ +static const GLubyte Helvetica10_Character_088[] = { 7, 0, 0,136,136, 80, 80, 32, 80,136,136, 0, 0, 0}; /* "X" */ +static const GLubyte Helvetica10_Character_089[] = { 7, 0, 0, 16, 16, 16, 40, 40, 68, 68,130, 0, 0, 0}; /* "Y" */ +static const GLubyte Helvetica10_Character_090[] = { 7, 0, 0,248,128, 64, 32, 32, 16, 8,248, 0, 0, 0}; /* "Z" */ +static const GLubyte Helvetica10_Character_048[] = { 6, 0, 0,112,136,136,136,136,136,136,112, 0, 0, 0}; /* "0" */ +static const GLubyte Helvetica10_Character_049[] = { 6, 0, 0, 64, 64, 64, 64, 64, 64,192, 64, 0, 0, 0}; /* "1" */ +static const GLubyte Helvetica10_Character_050[] = { 6, 0, 0,248,128, 64, 48, 8, 8,136,112, 0, 0, 0}; /* "2" */ +static const GLubyte Helvetica10_Character_051[] = { 6, 0, 0,112,136, 8, 8, 48, 8,136,112, 0, 0, 0}; /* "3" */ +static const GLubyte Helvetica10_Character_052[] = { 6, 0, 0, 16, 16,248,144, 80, 80, 48, 16, 0, 0, 0}; /* "4" */ +static const GLubyte Helvetica10_Character_053[] = { 6, 0, 0,112,136, 8, 8,240,128,128,248, 0, 0, 0}; /* "5" */ +static const GLubyte Helvetica10_Character_054[] = { 6, 0, 0,112,136,136,200,176,128,136,112, 0, 0, 0}; /* "6" */ +static const GLubyte Helvetica10_Character_055[] = { 6, 0, 0, 64, 64, 32, 32, 16, 16, 8,248, 0, 0, 0}; /* "7" */ +static const GLubyte Helvetica10_Character_056[] = { 6, 0, 0,112,136,136,136,112,136,136,112, 0, 0, 0}; /* "8" */ +static const GLubyte Helvetica10_Character_057[] = { 6, 0, 0,112,136, 8,104,152,136,136,112, 0, 0, 0}; /* "9" */ +static const GLubyte Helvetica10_Character_096[] = { 3, 0, 0, 0, 0, 0, 0, 0,128,128, 64, 0, 0, 0}; /* "`" */ +static const GLubyte Helvetica10_Character_126[] = { 7, 0, 0, 0, 0, 0,152,100, 0, 0, 0, 0, 0, 0}; /* "~" */ +static const GLubyte Helvetica10_Character_033[] = { 3, 0, 0,128, 0,128,128,128,128,128,128, 0, 0, 0}; /* "!" */ +static const GLubyte Helvetica10_Character_064[] = { 11, 62, 0, 64, 0,155, 0,164,128,164,128,162, 64,146, 64, 77, 64, 32,128, 31, 0, 0, 0, 0, 0, 0, 0}; /* "@" */ +static const GLubyte Helvetica10_Character_035[] = { 6, 0, 0, 80, 80,248, 40,124, 40, 40, 0, 0, 0, 0}; /* "#" */ +static const GLubyte Helvetica10_Character_036[] = { 6, 0, 32,112,168, 40,112,160,168,112, 32, 0, 0, 0}; /* "$" */ +static const GLubyte Helvetica10_Character_037[] = { 9, 0, 0, 0, 0, 38, 0, 41, 0, 22, 0, 16, 0, 8, 0,104, 0,148, 0,100, 0, 0, 0, 0, 0, 0, 0}; /* "%" */ +static const GLubyte Helvetica10_Character_094[] = { 6, 0, 0, 0, 0, 0,136, 80, 80, 32, 32, 0, 0, 0}; /* "^" */ +static const GLubyte Helvetica10_Character_038[] = { 8, 0, 0,100,152,152,164, 96, 80, 80, 32, 0, 0, 0}; /* "&" */ +static const GLubyte Helvetica10_Character_042[] = { 4, 0, 0, 0, 0, 0, 0, 0,160, 64,160, 0, 0, 0}; /* "*" */ +static const GLubyte Helvetica10_Character_040[] = { 4, 32, 64, 64,128,128,128,128, 64, 64, 32, 0, 0, 0}; /* "(" */ +static const GLubyte Helvetica10_Character_041[] = { 4,128, 64, 64, 32, 32, 32, 32, 64, 64,128, 0, 0, 0}; /* ")" */ +static const GLubyte Helvetica10_Character_045[] = { 7, 0, 0, 0, 0, 0,248, 0, 0, 0, 0, 0, 0, 0}; /* "-" */ +static const GLubyte Helvetica10_Character_095[] = { 6,252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "_" */ +static const GLubyte Helvetica10_Character_061[] = { 5, 0, 0, 0, 0,240, 0,240, 0, 0, 0, 0, 0, 0}; /* "=" */ +static const GLubyte Helvetica10_Character_043[] = { 6, 0, 0, 0, 32, 32,248, 32, 32, 0, 0, 0, 0, 0}; /* "+" */ +static const GLubyte Helvetica10_Character_091[] = { 3,192,128,128,128,128,128,128,128,128,192, 0, 0, 0}; /* "[" */ +static const GLubyte Helvetica10_Character_123[] = { 3, 32, 64, 64, 64, 64,128, 64, 64, 64, 32, 0, 0, 0}; /* "{" */ +static const GLubyte Helvetica10_Character_125[] = { 3,128, 64, 64, 64, 64, 32, 64, 64, 64,128, 0, 0, 0}; /* "}" */ +static const GLubyte Helvetica10_Character_093[] = { 3,192, 64, 64, 64, 64, 64, 64, 64, 64,192, 0, 0, 0}; /* "]" */ +static const GLubyte Helvetica10_Character_059[] = { 3,128, 64, 64, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0}; /* ";" */ +static const GLubyte Helvetica10_Character_058[] = { 3, 0, 0,128, 0, 0, 0, 0,128, 0, 0, 0, 0, 0}; /* ":" */ +static const GLubyte Helvetica10_Character_044[] = { 3,128, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "," */ +static const GLubyte Helvetica10_Character_046[] = { 3, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "." */ +static const GLubyte Helvetica10_Character_060[] = { 6, 0, 0, 0, 32, 64,128, 64, 32, 0, 0, 0, 0, 0}; /* "<" */ +static const GLubyte Helvetica10_Character_062[] = { 6, 0, 0, 0,128, 64, 32, 64,128, 0, 0, 0, 0, 0}; /* ">" */ +static const GLubyte Helvetica10_Character_047[] = { 3, 0, 0,128,128, 64, 64, 64, 64, 32, 32, 0, 0, 0}; /* "/" */ +static const GLubyte Helvetica10_Character_063[] = { 6, 0, 0, 64, 0, 64, 64, 32, 16,144, 96, 0, 0, 0}; /* "?" */ +static const GLubyte Helvetica10_Character_092[] = { 3, 0, 0, 32, 32, 64, 64, 64, 64,128,128, 0, 0, 0}; /* "\" */ +static const GLubyte Helvetica10_Character_034[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0,160,160, 0, 0, 0}; /* """ */ + +/* Missing Characters filled in by John Fay by hand ... */ +static const GLubyte Helvetica10_Character_039[] = { 3, 0, 0, 0, 0, 0, 0, 0,128, 64, 64, 0, 0, 0}; /* "'" */ +static const GLubyte Helvetica10_Character_124[] = { 3, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0}; /* "|" */ + + +/* The font characters mapping: */ +static const GLubyte* Helvetica10_Character_Map[] = {Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_032,Helvetica10_Character_033,Helvetica10_Character_034,Helvetica10_Character_035,Helvetica10_Character_036,Helvetica10_Character_037, + Helvetica10_Character_038,Helvetica10_Character_039,Helvetica10_Character_040,Helvetica10_Character_041,Helvetica10_Character_042,Helvetica10_Character_043,Helvetica10_Character_044,Helvetica10_Character_045,Helvetica10_Character_046,Helvetica10_Character_047,Helvetica10_Character_048,Helvetica10_Character_049,Helvetica10_Character_050,Helvetica10_Character_051,Helvetica10_Character_052,Helvetica10_Character_053,Helvetica10_Character_054,Helvetica10_Character_055,Helvetica10_Character_056,Helvetica10_Character_057,Helvetica10_Character_058,Helvetica10_Character_059,Helvetica10_Character_060,Helvetica10_Character_061,Helvetica10_Character_062,Helvetica10_Character_063,Helvetica10_Character_064,Helvetica10_Character_065,Helvetica10_Character_066,Helvetica10_Character_067,Helvetica10_Character_068,Helvetica10_Character_069,Helvetica10_Character_070,Helvetica10_Character_071,Helvetica10_Character_072,Helvetica10_Character_073,Helvetica10_Character_074,Helvetica10_Character_075,Helvetica10_Character_076, + Helvetica10_Character_077,Helvetica10_Character_078,Helvetica10_Character_079,Helvetica10_Character_080,Helvetica10_Character_081,Helvetica10_Character_082,Helvetica10_Character_083,Helvetica10_Character_084,Helvetica10_Character_085,Helvetica10_Character_086,Helvetica10_Character_087,Helvetica10_Character_088,Helvetica10_Character_089,Helvetica10_Character_090,Helvetica10_Character_091,Helvetica10_Character_092,Helvetica10_Character_093,Helvetica10_Character_094,Helvetica10_Character_095,Helvetica10_Character_096,Helvetica10_Character_097,Helvetica10_Character_098,Helvetica10_Character_099,Helvetica10_Character_100,Helvetica10_Character_101,Helvetica10_Character_102,Helvetica10_Character_103,Helvetica10_Character_104,Helvetica10_Character_105,Helvetica10_Character_106,Helvetica10_Character_107,Helvetica10_Character_108,Helvetica10_Character_109,Helvetica10_Character_110,Helvetica10_Character_111,Helvetica10_Character_112,Helvetica10_Character_113,Helvetica10_Character_114,Helvetica10_Character_115, + Helvetica10_Character_116,Helvetica10_Character_117,Helvetica10_Character_118,Helvetica10_Character_119,Helvetica10_Character_120,Helvetica10_Character_121,Helvetica10_Character_122,Helvetica10_Character_123,Helvetica10_Character_124,Helvetica10_Character_125,Helvetica10_Character_126,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042, + Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042, + Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042, + Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,Helvetica10_Character_042,NULL}; + +/* The font structure: */ +static const SFG_Font fgFontHelvetica10 = { "-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1", 93, 13, Helvetica10_Character_Map, -1.0f, 2.0f }; + +static const GLubyte Helvetica12_Character_032[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* " " */ +static const GLubyte Helvetica12_Character_097[] = { 7, 0, 0, 0,116,136,136,120, 8,136,112, 0, 0, 0, 0, 0}; /* "a" */ +static const GLubyte Helvetica12_Character_098[] = { 7, 0, 0, 0,176,200,136,136,136,200,176,128,128, 0, 0, 0}; /* "b" */ +static const GLubyte Helvetica12_Character_099[] = { 7, 0, 0, 0,112,136,128,128,128,136,112, 0, 0, 0, 0, 0}; /* "c" */ +static const GLubyte Helvetica12_Character_100[] = { 7, 0, 0, 0,104,152,136,136,136,152,104, 8, 8, 0, 0, 0}; /* "d" */ +static const GLubyte Helvetica12_Character_101[] = { 7, 0, 0, 0,112,136,128,248,136,136,112, 0, 0, 0, 0, 0}; /* "e" */ +static const GLubyte Helvetica12_Character_102[] = { 4, 0, 0, 0, 64, 64, 64, 64, 64, 64,224, 64, 48, 0, 0, 0}; /* "f" */ +static const GLubyte Helvetica12_Character_103[] = { 7,112,136, 8,104,152,136,136,136,152,104, 0, 0, 0, 0, 0}; /* "g" */ +static const GLubyte Helvetica12_Character_104[] = { 7, 0, 0, 0,136,136,136,136,136,200,176,128,128, 0, 0, 0}; /* "h" */ +static const GLubyte Helvetica12_Character_105[] = { 3, 0, 0, 0,128,128,128,128,128,128,128, 0,128, 0, 0, 0}; /* "i" */ +static const GLubyte Helvetica12_Character_106[] = { 4,128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 0, 0, 0}; /* "j" */ +static const GLubyte Helvetica12_Character_107[] = { 6, 0, 0, 0,136,144,160,192,192,160,144,128,128, 0, 0, 0}; /* "k" */ +static const GLubyte Helvetica12_Character_108[] = { 3, 0, 0, 0,128,128,128,128,128,128,128,128,128, 0, 0, 0}; /* "l" */ +static const GLubyte Helvetica12_Character_109[] = { 9, 0, 0, 0, 0, 0, 0,146, 0,146, 0,146, 0,146, 0,146, 0,218, 0,164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "m" */ +static const GLubyte Helvetica12_Character_110[] = { 7, 0, 0, 0,136,136,136,136,136,200,176, 0, 0, 0, 0, 0}; /* "n" */ +static const GLubyte Helvetica12_Character_111[] = { 7, 0, 0, 0,112,136,136,136,136,136,112, 0, 0, 0, 0, 0}; /* "o" */ +static const GLubyte Helvetica12_Character_112[] = { 7,128,128,128,176,200,136,136,136,200,176, 0, 0, 0, 0, 0}; /* "p" */ +static const GLubyte Helvetica12_Character_113[] = { 7, 8, 8, 8,104,152,136,136,136,152,104, 0, 0, 0, 0, 0}; /* "q" */ +static const GLubyte Helvetica12_Character_114[] = { 4, 0, 0, 0,128,128,128,128,128,192,160, 0, 0, 0, 0, 0}; /* "r" */ +static const GLubyte Helvetica12_Character_115[] = { 6, 0, 0, 0, 96,144, 16, 96,128,144, 96, 0, 0, 0, 0, 0}; /* "s" */ +static const GLubyte Helvetica12_Character_116[] = { 4, 0, 0, 0, 96, 64, 64, 64, 64, 64,224, 64, 64, 0, 0, 0}; /* "t" */ +static const GLubyte Helvetica12_Character_117[] = { 7, 0, 0, 0,104,152,136,136,136,136,136, 0, 0, 0, 0, 0}; /* "u" */ +static const GLubyte Helvetica12_Character_118[] = { 7, 0, 0, 0, 32, 32, 80, 80,136,136,136, 0, 0, 0, 0, 0}; /* "v" */ +static const GLubyte Helvetica12_Character_119[] = { 10, 0, 0, 0, 0, 0, 0, 34, 0, 34, 0, 85, 0, 73, 0, 73, 0,136,128,136,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "w" */ +static const GLubyte Helvetica12_Character_120[] = { 6, 0, 0, 0,132,132, 72, 48, 48, 72,132, 0, 0, 0, 0, 0}; /* "x" */ +static const GLubyte Helvetica12_Character_121[] = { 7,128, 64, 32, 32, 80, 80,144,136,136,136, 0, 0, 0, 0, 0}; /* "y" */ +static const GLubyte Helvetica12_Character_122[] = { 6, 0, 0, 0,240,128, 64, 64, 32, 16,240, 0, 0, 0, 0, 0}; /* "z" */ +static const GLubyte Helvetica12_Character_065[] = { 9, 0, 0, 0, 0, 0, 0,130, 0,130, 0,130, 0,124, 0, 68, 0, 68, 0, 40, 0, 40, 0, 16, 0, 0, 0, 0, 0, 0, 0}; /* "A" */ +static const GLubyte Helvetica12_Character_066[] = { 8, 0, 0, 0,248,132,132,132,248,132,132,132,248, 0, 0, 0}; /* "B" */ +static const GLubyte Helvetica12_Character_067[] = { 9, 0, 0, 0, 0, 0, 0, 60, 0, 66, 0,128, 0,128, 0,128, 0,128, 0,128, 0, 66, 0, 60, 0, 0, 0, 0, 0, 0, 0}; /* "C" */ +static const GLubyte Helvetica12_Character_068[] = { 9, 0, 0, 0, 0, 0, 0,248, 0,132, 0,130, 0,130, 0,130, 0,130, 0,130, 0,132, 0,248, 0, 0, 0, 0, 0, 0, 0}; /* "D" */ +static const GLubyte Helvetica12_Character_069[] = { 8, 0, 0, 0,252,128,128,128,252,128,128,128,252, 0, 0, 0}; /* "E" */ +static const GLubyte Helvetica12_Character_070[] = { 8, 0, 0, 0,128,128,128,128,248,128,128,128,252, 0, 0, 0}; /* "F" */ +static const GLubyte Helvetica12_Character_071[] = { 9, 0, 0, 0, 0, 0, 0, 58, 0, 70, 0,130, 0,130, 0,142, 0,128, 0,128, 0, 66, 0, 60, 0, 0, 0, 0, 0, 0, 0}; /* "G" */ +static const GLubyte Helvetica12_Character_072[] = { 9, 0, 0, 0, 0, 0, 0,130, 0,130, 0,130, 0,130, 0,254, 0,130, 0,130, 0,130, 0,130, 0, 0, 0, 0, 0, 0, 0}; /* "H" */ +static const GLubyte Helvetica12_Character_073[] = { 3, 0, 0, 0,128,128,128,128,128,128,128,128,128, 0, 0, 0}; /* "I" */ +static const GLubyte Helvetica12_Character_074[] = { 7, 0, 0, 0,112,136,136, 8, 8, 8, 8, 8, 8, 0, 0, 0}; /* "J" */ +static const GLubyte Helvetica12_Character_075[] = { 8, 0, 0, 0,130,132,136,144,224,160,144,136,132, 0, 0, 0}; /* "K" */ +static const GLubyte Helvetica12_Character_076[] = { 7, 0, 0, 0,248,128,128,128,128,128,128,128,128, 0, 0, 0}; /* "L" */ +static const GLubyte Helvetica12_Character_077[] = { 11, 0, 0, 0, 0, 0, 0,136,128,136,128,148,128,148,128,162,128,162,128,193,128,193,128,128,128, 0, 0, 0, 0, 0, 0}; /* "M" */ +static const GLubyte Helvetica12_Character_078[] = { 9, 0, 0, 0, 0, 0, 0,130, 0,134, 0,138, 0,138, 0,146, 0,162, 0,162, 0,194, 0,130, 0, 0, 0, 0, 0, 0, 0}; /* "N" */ +static const GLubyte Helvetica12_Character_079[] = { 10, 0, 0, 0, 0, 0, 0, 60, 0, 66, 0,129, 0,129, 0,129, 0,129, 0,129, 0, 66, 0, 60, 0, 0, 0, 0, 0, 0, 0}; /* "O" */ +static const GLubyte Helvetica12_Character_080[] = { 8, 0, 0, 0,128,128,128,128,248,132,132,132,248, 0, 0, 0}; /* "P" */ +static const GLubyte Helvetica12_Character_081[] = { 10, 0, 0, 0, 0, 0, 0, 61, 0, 66, 0,133, 0,137, 0,129, 0,129, 0,129, 0, 66, 0, 60, 0, 0, 0, 0, 0, 0, 0}; /* "Q" */ +static const GLubyte Helvetica12_Character_082[] = { 8, 0, 0, 0,132,132,132,136,248,132,132,132,248, 0, 0, 0}; /* "R" */ +static const GLubyte Helvetica12_Character_083[] = { 8, 0, 0, 0,120,132,132, 4, 24, 96,128,132,120, 0, 0, 0}; /* "S" */ +static const GLubyte Helvetica12_Character_084[] = { 7, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16,254, 0, 0, 0}; /* "T" */ +static const GLubyte Helvetica12_Character_085[] = { 8, 0, 0, 0,120,132,132,132,132,132,132,132,132, 0, 0, 0}; /* "U" */ +static const GLubyte Helvetica12_Character_086[] = { 9, 0, 0, 0, 0, 0, 0, 16, 0, 16, 0, 40, 0, 40, 0, 68, 0, 68, 0, 68, 0,130, 0,130, 0, 0, 0, 0, 0, 0, 0}; /* "V" */ +static const GLubyte Helvetica12_Character_087[] = { 11, 0, 0, 0, 0, 0, 0, 34, 0, 34, 0, 34, 0, 85, 0, 85, 0, 73, 0,136,128,136,128,136,128, 0, 0, 0, 0, 0, 0}; /* "W" */ +static const GLubyte Helvetica12_Character_088[] = { 9, 0, 0, 0, 0, 0, 0,130, 0, 68, 0, 68, 0, 40, 0, 16, 0, 40, 0, 68, 0, 68, 0,130, 0, 0, 0, 0, 0, 0, 0}; /* "X" */ +static const GLubyte Helvetica12_Character_089[] = { 9, 0, 0, 0, 0, 0, 0, 16, 0, 16, 0, 16, 0, 16, 0, 40, 0, 68, 0, 68, 0,130, 0,130, 0, 0, 0, 0, 0, 0, 0}; /* "Y" */ +static const GLubyte Helvetica12_Character_090[] = { 9, 0, 0, 0, 0, 0, 0,254, 0,128, 0, 64, 0, 32, 0, 16, 0, 8, 0, 4, 0, 2, 0,254, 0, 0, 0, 0, 0, 0, 0}; /* "Z" */ +static const GLubyte Helvetica12_Character_048[] = { 7, 0, 0, 0,112,136,136,136,136,136,136,136,112, 0, 0, 0}; /* "0" */ +static const GLubyte Helvetica12_Character_049[] = { 7, 0, 0, 0, 32, 32, 32, 32, 32, 32, 32,224, 32, 0, 0, 0}; /* "1" */ +static const GLubyte Helvetica12_Character_050[] = { 7, 0, 0, 0,248,128,128, 64, 32, 16, 8,136,112, 0, 0, 0}; /* "2" */ +static const GLubyte Helvetica12_Character_051[] = { 7, 0, 0, 0,112,136,136, 8, 8, 48, 8,136,112, 0, 0, 0}; /* "3" */ +static const GLubyte Helvetica12_Character_052[] = { 7, 0, 0, 0, 8, 8,252,136, 72, 40, 40, 24, 8, 0, 0, 0}; /* "4" */ +static const GLubyte Helvetica12_Character_053[] = { 7, 0, 0, 0,112,136,136, 8, 8,240,128,128,248, 0, 0, 0}; /* "5" */ +static const GLubyte Helvetica12_Character_054[] = { 7, 0, 0, 0,112,136,136,136,200,176,128,136,112, 0, 0, 0}; /* "6" */ +static const GLubyte Helvetica12_Character_055[] = { 7, 0, 0, 0, 64, 64, 32, 32, 32, 16, 16, 8,248, 0, 0, 0}; /* "7" */ +static const GLubyte Helvetica12_Character_056[] = { 7, 0, 0, 0,112,136,136,136,136,112,136,136,112, 0, 0, 0}; /* "8" */ +static const GLubyte Helvetica12_Character_057[] = { 7, 0, 0, 0,112,136, 8, 8,120,136,136,136,112, 0, 0, 0}; /* "9" */ +static const GLubyte Helvetica12_Character_096[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,128, 64, 0, 0, 0}; /* "`" */ +static const GLubyte Helvetica12_Character_126[] = { 8, 0, 0, 0, 0, 0, 0,152,100, 0, 0, 0, 0, 0, 0, 0}; /* "~" */ +static const GLubyte Helvetica12_Character_033[] = { 3, 0, 0, 0,128, 0,128,128,128,128,128,128,128, 0, 0, 0}; /* "!" */ +static const GLubyte Helvetica12_Character_064[] = { 12, 0, 0, 0, 0, 62, 0, 64, 0,155, 0,166,128,162, 64,162, 64,146, 64, 77, 64, 96,128, 31, 0, 0, 0, 0, 0, 0, 0}; /* "@" */ +static const GLubyte Helvetica12_Character_035[] = { 7, 0, 0, 0, 80, 80, 80,252, 40,252, 40, 40, 0, 0, 0, 0}; /* "#" */ +static const GLubyte Helvetica12_Character_036[] = { 7, 0, 0, 32,112,168,168, 40,112,160,168,112, 32, 0, 0, 0}; /* "$" */ +static const GLubyte Helvetica12_Character_037[] = { 11, 0, 0, 0, 0, 0, 0, 35, 0, 20,128, 20,128, 19, 0, 8, 0,104, 0,148, 0,148, 0, 98, 0, 0, 0, 0, 0, 0, 0}; /* "%" */ +static const GLubyte Helvetica12_Character_094[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0,136, 80, 32, 0, 0, 0, 0}; /* "^" */ +static const GLubyte Helvetica12_Character_038[] = { 9, 0, 0, 0, 0, 0, 0,114, 0,140, 0,132, 0,138, 0, 80, 0, 48, 0, 72, 0, 72, 0, 48, 0, 0, 0, 0, 0, 0, 0}; /* "&" */ +static const GLubyte Helvetica12_Character_042[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 64,160, 0, 0, 0}; /* "*" */ +static const GLubyte Helvetica12_Character_040[] = { 4, 32, 64, 64,128,128,128,128,128,128, 64, 64, 32, 0, 0, 0}; /* "(" */ +static const GLubyte Helvetica12_Character_041[] = { 4,128, 64, 64, 32, 32, 32, 32, 32, 32, 64, 64,128, 0, 0, 0}; /* ")" */ +static const GLubyte Helvetica12_Character_045[] = { 8, 0, 0, 0, 0, 0, 0,248, 0, 0, 0, 0, 0, 0, 0, 0}; /* "-" */ +static const GLubyte Helvetica12_Character_095[] = { 7, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "_" */ +static const GLubyte Helvetica12_Character_061[] = { 7, 0, 0, 0, 0, 0,248, 0,248, 0, 0, 0, 0, 0, 0, 0}; /* "=" */ +static const GLubyte Helvetica12_Character_043[] = { 7, 0, 0, 0, 0, 32, 32,248, 32, 32, 0, 0, 0, 0, 0, 0}; /* "+" */ +static const GLubyte Helvetica12_Character_091[] = { 3,192,128,128,128,128,128,128,128,128,128,128,192, 0, 0, 0}; /* "[" */ +static const GLubyte Helvetica12_Character_123[] = { 4, 48, 64, 64, 64, 64, 64,128, 64, 64, 64, 64, 48, 0, 0, 0}; /* "{" */ +static const GLubyte Helvetica12_Character_125[] = { 4,192, 32, 32, 32, 32, 32, 16, 32, 32, 32, 32,192, 0, 0, 0}; /* "}" */ +static const GLubyte Helvetica12_Character_093[] = { 3,192, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,192, 0, 0, 0}; /* "]" */ +static const GLubyte Helvetica12_Character_059[] = { 3, 0,128, 64, 64, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0}; /* ";" */ +static const GLubyte Helvetica12_Character_058[] = { 3, 0, 0, 0,128, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0}; /* ":" */ +static const GLubyte Helvetica12_Character_044[] = { 4, 0,128, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "," */ +static const GLubyte Helvetica12_Character_046[] = { 3, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "." */ +static const GLubyte Helvetica12_Character_060[] = { 7, 0, 0, 0, 0, 12, 48,192, 48, 12, 0, 0, 0, 0, 0, 0}; /* "<" */ +static const GLubyte Helvetica12_Character_062[] = { 7, 0, 0, 0, 0,192, 48, 12, 48,192, 0, 0, 0, 0, 0, 0}; /* ">" */ +static const GLubyte Helvetica12_Character_047[] = { 4, 0, 0, 0,128,128,128, 64, 64, 64, 32, 32, 32, 0, 0, 0}; /* "/" */ +static const GLubyte Helvetica12_Character_063[] = { 7, 0, 0, 0, 32, 0, 32, 32, 16, 16,136,136,112, 0, 0, 0}; /* "?" */ +static const GLubyte Helvetica12_Character_092[] = { 4, 0, 0, 0, 32, 32, 32, 64, 64, 64,128,128,128, 0, 0, 0}; /* "\" */ +static const GLubyte Helvetica12_Character_034[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0, 0,160,160,160, 0, 0, 0}; /* """ */ + +/* Missing Characters filled in by John Fay by hand ... */ +static const GLubyte Helvetica12_Character_039[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 64, 64, 0, 0}; /* "'" */ +static const GLubyte Helvetica12_Character_124[] = { 3, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0}; /* "|" */ + + +/* The font characters mapping: */ +static const GLubyte* Helvetica12_Character_Map[] = {Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_032,Helvetica12_Character_033,Helvetica12_Character_034,Helvetica12_Character_035,Helvetica12_Character_036,Helvetica12_Character_037, + Helvetica12_Character_038,Helvetica12_Character_039,Helvetica12_Character_040,Helvetica12_Character_041,Helvetica12_Character_042,Helvetica12_Character_043,Helvetica12_Character_044,Helvetica12_Character_045,Helvetica12_Character_046,Helvetica12_Character_047,Helvetica12_Character_048,Helvetica12_Character_049,Helvetica12_Character_050,Helvetica12_Character_051,Helvetica12_Character_052,Helvetica12_Character_053,Helvetica12_Character_054,Helvetica12_Character_055,Helvetica12_Character_056,Helvetica12_Character_057,Helvetica12_Character_058,Helvetica12_Character_059,Helvetica12_Character_060,Helvetica12_Character_061,Helvetica12_Character_062,Helvetica12_Character_063,Helvetica12_Character_064,Helvetica12_Character_065,Helvetica12_Character_066,Helvetica12_Character_067,Helvetica12_Character_068,Helvetica12_Character_069,Helvetica12_Character_070,Helvetica12_Character_071,Helvetica12_Character_072,Helvetica12_Character_073,Helvetica12_Character_074,Helvetica12_Character_075,Helvetica12_Character_076, + Helvetica12_Character_077,Helvetica12_Character_078,Helvetica12_Character_079,Helvetica12_Character_080,Helvetica12_Character_081,Helvetica12_Character_082,Helvetica12_Character_083,Helvetica12_Character_084,Helvetica12_Character_085,Helvetica12_Character_086,Helvetica12_Character_087,Helvetica12_Character_088,Helvetica12_Character_089,Helvetica12_Character_090,Helvetica12_Character_091,Helvetica12_Character_092,Helvetica12_Character_093,Helvetica12_Character_094,Helvetica12_Character_095,Helvetica12_Character_096,Helvetica12_Character_097,Helvetica12_Character_098,Helvetica12_Character_099,Helvetica12_Character_100,Helvetica12_Character_101,Helvetica12_Character_102,Helvetica12_Character_103,Helvetica12_Character_104,Helvetica12_Character_105,Helvetica12_Character_106,Helvetica12_Character_107,Helvetica12_Character_108,Helvetica12_Character_109,Helvetica12_Character_110,Helvetica12_Character_111,Helvetica12_Character_112,Helvetica12_Character_113,Helvetica12_Character_114,Helvetica12_Character_115, + Helvetica12_Character_116,Helvetica12_Character_117,Helvetica12_Character_118,Helvetica12_Character_119,Helvetica12_Character_120,Helvetica12_Character_121,Helvetica12_Character_122,Helvetica12_Character_123,Helvetica12_Character_124,Helvetica12_Character_125,Helvetica12_Character_126,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042, + Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042, + Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042, + Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,Helvetica12_Character_042,NULL}; + +/* The font structure: */ +static const SFG_Font fgFontHelvetica12 = { "-adobe-helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1", 93, 15, Helvetica12_Character_Map, -1.0f, 3.0f }; + +static const GLubyte Helvetica18_Character_032[] = { 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* " " */ +static const GLubyte Helvetica18_Character_097[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,118, 0,238, 0,198, 0,198, 0,230, 0,126, 0, 14, 0,198, 0,238, 0,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "a" */ +static const GLubyte Helvetica18_Character_098[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,222, 0,255, 0,227, 0,193,128,193,128,193,128,193,128,227, 0,255, 0,222, 0,192, 0,192, 0,192, 0,192, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "b" */ +static const GLubyte Helvetica18_Character_099[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0,127, 0, 99, 0,192, 0,192, 0,192, 0,192, 0, 99, 0,127, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "c" */ +static const GLubyte Helvetica18_Character_100[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 61,128,127,128, 99,128,193,128,193,128,193,128,193,128, 99,128,127,128, 61,128, 1,128, 1,128, 1,128, 1,128, 0, 0, 0, 0, 0, 0, 0, 0}; /* "d" */ +static const GLubyte Helvetica18_Character_101[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0,127, 0,227, 0,192, 0,192, 0,255, 0,195, 0,195, 0,126, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "e" */ +static const GLubyte Helvetica18_Character_102[] = { 6, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48,252,252, 48, 48, 60, 28, 0, 0, 0, 0}; /* "f" */ +static const GLubyte Helvetica18_Character_103[] = { 11, 28, 0,127, 0, 99, 0, 1,128, 61,128,127,128, 99,128,193,128,193,128,193,128,193,128, 97,128,127,128, 61,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "g" */ +static const GLubyte Helvetica18_Character_104[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,195, 0,195, 0,195, 0,195, 0,195, 0,195, 0,195, 0,227, 0,223, 0,206, 0,192, 0,192, 0,192, 0,192, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "h" */ +static const GLubyte Helvetica18_Character_105[] = { 4, 0, 0, 0, 0,192,192,192,192,192,192,192,192,192,192, 0, 0,192,192, 0, 0, 0, 0}; /* "i" */ +static const GLubyte Helvetica18_Character_106[] = { 4,224,240, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, 0, 0, 0, 0}; /* "j" */ +static const GLubyte Helvetica18_Character_107[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,199, 0,198, 0,206, 0,204, 0,216, 0,248, 0,240, 0,216, 0,204, 0,198, 0,192, 0,192, 0,192, 0,192, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "k" */ +static const GLubyte Helvetica18_Character_108[] = { 4, 0, 0, 0, 0,192,192,192,192,192,192,192,192,192,192,192,192,192,192, 0, 0, 0, 0}; /* "l" */ +static const GLubyte Helvetica18_Character_109[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0,198, 48,198, 48,198, 48,198, 48,198, 48,198, 48,198, 48,231, 48,222,240,204, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "m" */ +static const GLubyte Helvetica18_Character_110[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,195, 0,195, 0,195, 0,195, 0,195, 0,195, 0,195, 0,227, 0,223, 0,206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "n" */ +static const GLubyte Helvetica18_Character_111[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0,127, 0, 99, 0,193,128,193,128,193,128,193,128, 99, 0,127, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "o" */ +static const GLubyte Helvetica18_Character_112[] = { 11,192, 0,192, 0,192, 0,192, 0,222, 0,255, 0,227, 0,193,128,193,128,193,128,193,128,227, 0,255, 0,222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "p" */ +static const GLubyte Helvetica18_Character_113[] = { 11, 1,128, 1,128, 1,128, 1,128, 61,128,127,128, 99,128,193,128,193,128,193,128,193,128, 99,128,127,128, 61,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "q" */ +static const GLubyte Helvetica18_Character_114[] = { 6, 0, 0, 0, 0,192,192,192,192,192,192,192,224,216,216, 0, 0, 0, 0, 0, 0, 0, 0}; /* "r" */ +static const GLubyte Helvetica18_Character_115[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,120, 0,252, 0,198, 0, 6, 0, 62, 0,252, 0,192, 0,198, 0,126, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "s" */ +static const GLubyte Helvetica18_Character_116[] = { 6, 0, 0, 0, 0, 24, 56, 48, 48, 48, 48, 48, 48,252,252, 48, 48, 48, 0, 0, 0, 0, 0}; /* "t" */ +static const GLubyte Helvetica18_Character_117[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,115, 0,251, 0,199, 0,195, 0,195, 0,195, 0,195, 0,195, 0,195, 0,195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "u" */ +static const GLubyte Helvetica18_Character_118[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 24, 0, 60, 0, 36, 0,102, 0,102, 0,102, 0,195, 0,195, 0,195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "v" */ +static const GLubyte Helvetica18_Character_119[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 25,128, 25,128, 57,192, 41, 64,105, 96,102, 96,102, 96,198, 48,198, 48,198, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "w" */ +static const GLubyte Helvetica18_Character_120[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,195, 0,231, 0,102, 0, 60, 0, 24, 0, 24, 0, 60, 0,102, 0,231, 0,195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "x" */ +static const GLubyte Helvetica18_Character_121[] = { 10,112, 0,112, 0, 24, 0, 24, 0, 24, 0, 24, 0, 60, 0, 36, 0,102, 0,102, 0,102, 0,195, 0,195, 0,195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "y" */ +static const GLubyte Helvetica18_Character_122[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,254, 0,254, 0,192, 0, 96, 0, 48, 0, 24, 0, 12, 0, 6, 0,254, 0,254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "z" */ +static const GLubyte Helvetica18_Character_065[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,192, 48,192, 48, 96, 96, 96, 96,127,224, 63,192, 48,192, 48,192, 25,128, 25,128, 15, 0, 15, 0, 6, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "A" */ +static const GLubyte Helvetica18_Character_066[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,255,128,255,192,192,224,192, 96,192, 96,192,224,255,192,255,128,193,128,192,192,192,192,193,192,255,128,255, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "B" */ +static const GLubyte Helvetica18_Character_067[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 15,128, 63,224,112,112, 96, 48,224, 0,192, 0,192, 0,192, 0,192, 0,224, 0, 96, 48,112,112, 63,224, 15,128, 0, 0, 0, 0, 0, 0, 0, 0}; /* "C" */ +static const GLubyte Helvetica18_Character_068[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,255, 0,255,128,193,192,192,192,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192,192,193,192,255,128,255, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "D" */ +static const GLubyte Helvetica18_Character_069[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,255,128,255,128,192, 0,192, 0,192, 0,192, 0,255, 0,255, 0,192, 0,192, 0,192, 0,192, 0,255,128,255,128, 0, 0, 0, 0, 0, 0, 0, 0}; /* "E" */ +static const GLubyte Helvetica18_Character_070[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0,192, 0,192, 0,192, 0,192, 0,192, 0,192, 0,255, 0,255, 0,192, 0,192, 0,192, 0,192, 0,255,128,255,128, 0, 0, 0, 0, 0, 0, 0, 0}; /* "F" */ +static const GLubyte Helvetica18_Character_071[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 15,176, 63,240,112,112, 96, 48,224, 48,193,240,193,240,192, 0,192, 0,224, 48, 96, 48,112,112, 63,224, 15,128, 0, 0, 0, 0, 0, 0, 0, 0}; /* "G" */ +static const GLubyte Helvetica18_Character_072[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96,255,224,255,224,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96, 0, 0, 0, 0, 0, 0, 0, 0}; /* "H" */ +static const GLubyte Helvetica18_Character_073[] = { 6, 0, 0, 0, 0,192,192,192,192,192,192,192,192,192,192,192,192,192,192, 0, 0, 0, 0}; /* "I" */ +static const GLubyte Helvetica18_Character_074[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0,126, 0,231, 0,195, 0,195, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "J" */ +static const GLubyte Helvetica18_Character_075[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,192,112,192,224,193,192,195,128,199, 0,206, 0,252, 0,248, 0,220, 0,206, 0,199, 0,195,128,193,192,192,224, 0, 0, 0, 0, 0, 0, 0, 0}; /* "K" */ +static const GLubyte Helvetica18_Character_076[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0,192, 0,192, 0,192, 0,192, 0,192, 0,192, 0,192, 0,192, 0,192, 0,192, 0,192,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "L" */ +static const GLubyte Helvetica18_Character_077[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0,195, 12,195, 12,199,140,196,140,204,204,204,204,216,108,216,108,240, 60,240, 60,224, 28,224, 28,192, 12,192, 12, 0, 0, 0, 0, 0, 0, 0, 0}; /* "M" */ +static const GLubyte Helvetica18_Character_078[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,192, 96,192,224,193,224,193,224,195, 96,198, 96,198, 96,204, 96,204, 96,216, 96,240, 96,240, 96,224, 96,192, 96, 0, 0, 0, 0, 0, 0, 0, 0}; /* "N" */ +static const GLubyte Helvetica18_Character_079[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 15,128, 63,224,112,112, 96, 48,224, 56,192, 24,192, 24,192, 24,192, 24,224, 56, 96, 48,112,112, 63,224, 15,128, 0, 0, 0, 0, 0, 0, 0, 0}; /* "O" */ +static const GLubyte Helvetica18_Character_080[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,192, 0,192, 0,192, 0,192, 0,192, 0,192, 0,255, 0,255,128,193,192,192,192,192,192,193,192,255,128,255, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "P" */ +static const GLubyte Helvetica18_Character_081[] = { 15, 0, 0, 0, 0, 0, 0, 0, 48, 15,176, 63,224,112,240, 97,176,225,184,192, 24,192, 24,192, 24,192, 24,224, 56, 96, 48,112,112, 63,224, 15,128, 0, 0, 0, 0, 0, 0, 0, 0}; /* "Q" */ +static const GLubyte Helvetica18_Character_082[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,192,192,192,192,192,192,192,192,193,128,193,128,255, 0,255,128,193,192,192,192,192,192,193,192,255,128,255, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "R" */ +static const GLubyte Helvetica18_Character_083[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0,127,192,224,224,192, 96, 0, 96, 0,224, 3,192, 31, 0,124, 0,224, 0,192, 96,224,224,127,192, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "S" */ +static const GLubyte Helvetica18_Character_084[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0, 12, 0,255,192,255,192, 0, 0, 0, 0, 0, 0, 0, 0}; /* "T" */ +static const GLubyte Helvetica18_Character_085[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0,127,192, 96,192,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96, 0, 0, 0, 0, 0, 0, 0, 0}; /* "U" */ +static const GLubyte Helvetica18_Character_086[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 15, 0, 15, 0, 25,128, 25,128, 25,128, 48,192, 48,192, 48,192, 96, 96, 96, 96, 96, 96,192, 48,192, 48, 0, 0, 0, 0, 0, 0, 0, 0}; /* "V" */ +static const GLubyte Helvetica18_Character_087[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 0, 24, 24, 0, 28, 56, 0, 52, 44, 0, 54,108, 0, 54,108, 0,102,102, 0,102,102, 0, 98, 70, 0, 99,198, 0,195,195, 0,193,131, 0,193,131, 0,193,131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "W" */ +static const GLubyte Helvetica18_Character_088[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0,192, 96,224,224, 96,192,113,192, 49,128, 27, 0, 14, 0, 14, 0, 27, 0, 49,128,113,192, 96,192,224,224,192, 96, 0, 0, 0, 0, 0, 0, 0, 0}; /* "X" */ +static const GLubyte Helvetica18_Character_089[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 15, 0, 25,128, 48,192, 48,192, 96, 96, 96, 96,192, 48,192, 48, 0, 0, 0, 0, 0, 0, 0, 0}; /* "Y" */ +static const GLubyte Helvetica18_Character_090[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0,255,192,255,192,192, 0, 96, 0, 48, 0, 24, 0, 28, 0, 12, 0, 6, 0, 3, 0, 1,128, 0,192,255,192,255,192, 0, 0, 0, 0, 0, 0, 0, 0}; /* "Z" */ +static const GLubyte Helvetica18_Character_048[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0,126, 0,102, 0,195, 0,195, 0,195, 0,195, 0,195, 0,195, 0,195, 0,102, 0,126, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "0" */ +static const GLubyte Helvetica18_Character_049[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0,248, 0,248, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "1" */ +static const GLubyte Helvetica18_Character_050[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0,192, 0,224, 0,112, 0, 56, 0, 28, 0, 14, 0, 7, 0, 3, 0,195, 0,254, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "2" */ +static const GLubyte Helvetica18_Character_051[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0,126, 0,199, 0,195, 0, 3, 0, 7, 0, 30, 0, 28, 0, 6, 0,195, 0,195, 0,126, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "3" */ +static const GLubyte Helvetica18_Character_052[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 3, 0,255,128,255,128,195, 0, 99, 0, 51, 0, 51, 0, 27, 0, 15, 0, 7, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "4" */ +static const GLubyte Helvetica18_Character_053[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,124, 0,254, 0,199, 0,195, 0, 3, 0, 3, 0,199, 0,254, 0,252, 0,192, 0,192, 0,254, 0,254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "5" */ +static const GLubyte Helvetica18_Character_054[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0,126, 0,227, 0,195, 0,195, 0,195, 0,254, 0,220, 0,192, 0,192, 0, 99, 0,127, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "6" */ +static const GLubyte Helvetica18_Character_055[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 96, 0, 48, 0, 48, 0, 48, 0, 24, 0, 24, 0, 12, 0, 12, 0, 6, 0, 3, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "7" */ +static const GLubyte Helvetica18_Character_056[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0,126, 0,231, 0,195, 0,195, 0,102, 0,126, 0,102, 0,195, 0,195, 0,231, 0,126, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "8" */ +static const GLubyte Helvetica18_Character_057[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,124, 0,254, 0,198, 0, 3, 0, 3, 0, 59, 0,127, 0,195, 0,195, 0,195, 0,199, 0,126, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "9" */ +static const GLubyte Helvetica18_Character_096[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,192,128,128, 64, 0, 0, 0, 0}; /* "`" */ +static const GLubyte Helvetica18_Character_126[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,204, 0,126, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "~" */ +static const GLubyte Helvetica18_Character_033[] = { 6, 0, 0, 0, 0,192,192, 0, 0,128,128,192,192,192,192,192,192,192,192, 0, 0, 0, 0}; /* "!" */ +static const GLubyte Helvetica18_Character_064[] = { 18, 0, 0, 0, 7,224, 0, 31,240, 0, 56, 0, 0,112, 0, 0,103,112, 0,207,248, 0,204,204, 0,204,102, 0,204,102, 0,204, 99, 0,198, 51, 0,103,115, 0, 99,179, 0, 48, 6, 0, 28, 14, 0, 15,252, 0, 3,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "@" */ +static const GLubyte Helvetica18_Character_035[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 36, 0, 36, 0,255,128,255,128, 18, 0, 18, 0, 18, 0,127,192,127,192, 9, 0, 9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "#" */ +static const GLubyte Helvetica18_Character_036[] = { 10, 0, 0, 0, 0, 8, 0, 8, 0, 62, 0,127, 0,235,128,201,128, 9,128, 15, 0, 62, 0,120, 0,232, 0,200, 0,203, 0,127, 0, 62, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "$" */ +static const GLubyte Helvetica18_Character_037[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0, 24,120, 24,252, 12,204, 12,204, 6,252, 6,120, 3, 0,123, 0,253,128,205,128,204,192,252,192,120, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "%" */ +static const GLubyte Helvetica18_Character_094[] = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,130, 0,198, 0,108, 0, 56, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "^" */ +static const GLubyte Helvetica18_Character_038[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 60,112,126,224,231,192,195,128,195,192,198,192,238,192,124, 0, 60, 0,102, 0,102, 0,126, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "&" */ +static const GLubyte Helvetica18_Character_042[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136,112,112,248, 32, 32, 0, 0, 0, 0}; /* "*" */ +static const GLubyte Helvetica18_Character_040[] = { 6, 16, 48, 96, 96,192,192,192,192,192,192,192,192,192,192, 96, 96, 48, 16, 0, 0, 0, 0}; /* "(" */ +static const GLubyte Helvetica18_Character_041[] = { 6,128,192, 96, 96, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 96, 96,192,128, 0, 0, 0, 0}; /* ")" */ +static const GLubyte Helvetica18_Character_045[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "-" */ +static const GLubyte Helvetica18_Character_095[] = { 10,255,248,255,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "_" */ +static const GLubyte Helvetica18_Character_061[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254, 0,254, 0, 0, 0, 0, 0,254, 0,254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "=" */ +static const GLubyte Helvetica18_Character_043[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 24, 0, 24, 0, 24, 0,255, 0,255, 0, 24, 0, 24, 0, 24, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "+" */ +static const GLubyte Helvetica18_Character_091[] = { 5,240,240,192,192,192,192,192,192,192,192,192,192,192,192,192,192,240,240, 0, 0, 0, 0}; /* "[" */ +static const GLubyte Helvetica18_Character_123[] = { 7, 12, 24, 48, 48, 48, 48, 48, 48, 96,192, 96, 48, 48, 48, 48, 48, 24, 12, 0, 0, 0, 0}; /* "{" */ +static const GLubyte Helvetica18_Character_125[] = { 7,192, 96, 48, 48, 48, 48, 48, 48, 24, 12, 24, 48, 48, 48, 48, 48, 96,192, 0, 0, 0, 0}; /* "}" */ +static const GLubyte Helvetica18_Character_093[] = { 5,240,240, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,240,240, 0, 0, 0, 0}; /* "]" */ +static const GLubyte Helvetica18_Character_059[] = { 5, 0,128, 64, 64,192,192, 0, 0, 0, 0, 0, 0,192,192, 0, 0, 0, 0, 0, 0, 0, 0}; /* ";" */ +static const GLubyte Helvetica18_Character_058[] = { 5, 0, 0, 0, 0,192,192, 0, 0, 0, 0, 0, 0,192,192, 0, 0, 0, 0, 0, 0, 0, 0}; /* ":" */ +static const GLubyte Helvetica18_Character_044[] = { 5, 0,128, 64, 64,192,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "," */ +static const GLubyte Helvetica18_Character_046[] = { 5, 0, 0, 0, 0,192,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "." */ +static const GLubyte Helvetica18_Character_060[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 15, 0, 60, 0,112, 0,192, 0,112, 0, 60, 0, 15, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "<" */ +static const GLubyte Helvetica18_Character_062[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0,192, 0,240, 0, 60, 0, 14, 0, 3, 0, 14, 0, 60, 0,240, 0,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* ">" */ +static const GLubyte Helvetica18_Character_047[] = { 5, 0, 0, 0, 0,192,192, 64, 64, 96, 96, 32, 32, 48, 48, 16, 16, 24, 24, 0, 0, 0, 0}; /* "/" */ +static const GLubyte Helvetica18_Character_063[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 48, 0, 0, 0, 0, 0, 48, 0, 48, 0, 48, 0, 56, 0, 28, 0, 14, 0,198, 0,198, 0,254, 0,124, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "?" */ +static const GLubyte Helvetica18_Character_092[] = { 5, 0, 0, 0, 0, 24, 24, 16, 16, 48, 48, 32, 32, 96, 96, 64, 64,192,192, 0, 0, 0, 0}; /* "\" */ +static const GLubyte Helvetica18_Character_034[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,144,144,216,216,216, 0, 0, 0, 0}; /* """ */ + +/* Missing Characters filled in by John Fay by hand ... */ +static const GLubyte Helvetica18_Character_039[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 64, 64,192,192, 0, 0, 0, 0}; /* "'" */ +static const GLubyte Helvetica18_Character_124[] = { 4, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96}; /* "|" */ + + +/* The font characters mapping: */ +static const GLubyte* Helvetica18_Character_Map[] = {Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_032,Helvetica18_Character_033,Helvetica18_Character_034,Helvetica18_Character_035,Helvetica18_Character_036,Helvetica18_Character_037, + Helvetica18_Character_038,Helvetica18_Character_039,Helvetica18_Character_040,Helvetica18_Character_041,Helvetica18_Character_042,Helvetica18_Character_043,Helvetica18_Character_044,Helvetica18_Character_045,Helvetica18_Character_046,Helvetica18_Character_047,Helvetica18_Character_048,Helvetica18_Character_049,Helvetica18_Character_050,Helvetica18_Character_051,Helvetica18_Character_052,Helvetica18_Character_053,Helvetica18_Character_054,Helvetica18_Character_055,Helvetica18_Character_056,Helvetica18_Character_057,Helvetica18_Character_058,Helvetica18_Character_059,Helvetica18_Character_060,Helvetica18_Character_061,Helvetica18_Character_062,Helvetica18_Character_063,Helvetica18_Character_064,Helvetica18_Character_065,Helvetica18_Character_066,Helvetica18_Character_067,Helvetica18_Character_068,Helvetica18_Character_069,Helvetica18_Character_070,Helvetica18_Character_071,Helvetica18_Character_072,Helvetica18_Character_073,Helvetica18_Character_074,Helvetica18_Character_075,Helvetica18_Character_076, + Helvetica18_Character_077,Helvetica18_Character_078,Helvetica18_Character_079,Helvetica18_Character_080,Helvetica18_Character_081,Helvetica18_Character_082,Helvetica18_Character_083,Helvetica18_Character_084,Helvetica18_Character_085,Helvetica18_Character_086,Helvetica18_Character_087,Helvetica18_Character_088,Helvetica18_Character_089,Helvetica18_Character_090,Helvetica18_Character_091,Helvetica18_Character_092,Helvetica18_Character_093,Helvetica18_Character_094,Helvetica18_Character_095,Helvetica18_Character_096,Helvetica18_Character_097,Helvetica18_Character_098,Helvetica18_Character_099,Helvetica18_Character_100,Helvetica18_Character_101,Helvetica18_Character_102,Helvetica18_Character_103,Helvetica18_Character_104,Helvetica18_Character_105,Helvetica18_Character_106,Helvetica18_Character_107,Helvetica18_Character_108,Helvetica18_Character_109,Helvetica18_Character_110,Helvetica18_Character_111,Helvetica18_Character_112,Helvetica18_Character_113,Helvetica18_Character_114,Helvetica18_Character_115, + Helvetica18_Character_116,Helvetica18_Character_117,Helvetica18_Character_118,Helvetica18_Character_119,Helvetica18_Character_120,Helvetica18_Character_121,Helvetica18_Character_122,Helvetica18_Character_123,Helvetica18_Character_124,Helvetica18_Character_125,Helvetica18_Character_126,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042, + Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042, + Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042, + Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,Helvetica18_Character_042,NULL}; + +/* The font structure: */ +static const SFG_Font fgFontHelvetica18 = { "-adobe-helvetica-medium-r-normal--18-180-75-75-p-98-iso8859-1", 93, 22, Helvetica18_Character_Map, -1.0f, 4.0f }; + +static const GLubyte TimesRoman10_Character_032[] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* " " */ +static const GLubyte TimesRoman10_Character_097[] = { 4, 0, 0, 0,224,160, 96, 32,192, 0, 0, 0, 0, 0}; /* "a" */ +static const GLubyte TimesRoman10_Character_098[] = { 5, 0, 0, 0,224,144,144,144,224,128,128, 0, 0, 0}; /* "b" */ +static const GLubyte TimesRoman10_Character_099[] = { 4, 0, 0, 0, 96,128,128,128, 96, 0, 0, 0, 0, 0}; /* "c" */ +static const GLubyte TimesRoman10_Character_100[] = { 5, 0, 0, 0,104,144,144,144,112, 16, 48, 0, 0, 0}; /* "d" */ +static const GLubyte TimesRoman10_Character_101[] = { 4, 0, 0, 0, 96,128,192,160, 96, 0, 0, 0, 0, 0}; /* "e" */ +static const GLubyte TimesRoman10_Character_102[] = { 4, 0, 0, 0,224, 64, 64, 64,224, 64, 48, 0, 0, 0}; /* "f" */ +static const GLubyte TimesRoman10_Character_103[] = { 5, 0,224,144, 96, 64,160,160,112, 0, 0, 0, 0, 0}; /* "g" */ +static const GLubyte TimesRoman10_Character_104[] = { 5, 0, 0, 0,216,144,144,144,224,128,128, 0, 0, 0}; /* "h" */ +static const GLubyte TimesRoman10_Character_105[] = { 3, 0, 0, 0, 64, 64, 64, 64,192, 0, 64, 0, 0, 0}; /* "i" */ +static const GLubyte TimesRoman10_Character_106[] = { 3, 0,128, 64, 64, 64, 64, 64,192, 0, 64, 0, 0, 0}; /* "j" */ +static const GLubyte TimesRoman10_Character_107[] = { 5, 0, 0, 0,152,144,224,160,144,128,128, 0, 0, 0}; /* "k" */ +static const GLubyte TimesRoman10_Character_108[] = { 4, 0, 0, 0,224, 64, 64, 64, 64, 64,192, 0, 0, 0}; /* "l" */ +static const GLubyte TimesRoman10_Character_109[] = { 8, 0, 0, 0,219,146,146,146,236, 0, 0, 0, 0, 0}; /* "m" */ +static const GLubyte TimesRoman10_Character_110[] = { 5, 0, 0, 0,216,144,144,144,224, 0, 0, 0, 0, 0}; /* "n" */ +static const GLubyte TimesRoman10_Character_111[] = { 5, 0, 0, 0, 96,144,144,144, 96, 0, 0, 0, 0, 0}; /* "o" */ +static const GLubyte TimesRoman10_Character_112[] = { 5, 0,192,128,224,144,144,144,224, 0, 0, 0, 0, 0}; /* "p" */ +static const GLubyte TimesRoman10_Character_113[] = { 5, 0, 56, 16,112,144,144,144,112, 0, 0, 0, 0, 0}; /* "q" */ +static const GLubyte TimesRoman10_Character_114[] = { 4, 0, 0, 0,224, 64, 64, 96,160, 0, 0, 0, 0, 0}; /* "r" */ +static const GLubyte TimesRoman10_Character_115[] = { 4, 0, 0, 0,224, 32, 96,128,224, 0, 0, 0, 0, 0}; /* "s" */ +static const GLubyte TimesRoman10_Character_116[] = { 4, 0, 0, 0, 48, 64, 64, 64,224, 64, 0, 0, 0, 0}; /* "t" */ +static const GLubyte TimesRoman10_Character_117[] = { 5, 0, 0, 0,104,144,144,144,144, 0, 0, 0, 0, 0}; /* "u" */ +static const GLubyte TimesRoman10_Character_118[] = { 5, 0, 0, 0, 32, 96, 80,144,216, 0, 0, 0, 0, 0}; /* "v" */ +static const GLubyte TimesRoman10_Character_119[] = { 8, 0, 0, 0, 40,108, 84,146,219, 0, 0, 0, 0, 0}; /* "w" */ +static const GLubyte TimesRoman10_Character_120[] = { 6, 0, 0, 0,216, 80, 32, 80,216, 0, 0, 0, 0, 0}; /* "x" */ +static const GLubyte TimesRoman10_Character_121[] = { 5, 0, 64, 64, 32, 48, 80, 72,220, 0, 0, 0, 0, 0}; /* "y" */ +static const GLubyte TimesRoman10_Character_122[] = { 5, 0, 0, 0,240,144, 64, 32,240, 0, 0, 0, 0, 0}; /* "z" */ +static const GLubyte TimesRoman10_Character_065[] = { 8, 0, 0, 0,238, 68,124, 40, 40, 56, 16, 0, 0, 0}; /* "A" */ +static const GLubyte TimesRoman10_Character_066[] = { 6, 0, 0, 0,240, 72, 72,112, 72, 72,240, 0, 0, 0}; /* "B" */ +static const GLubyte TimesRoman10_Character_067[] = { 7, 0, 0, 0,120,196,128,128,128,196,124, 0, 0, 0}; /* "C" */ +static const GLubyte TimesRoman10_Character_068[] = { 7, 0, 0, 0,248, 76, 68, 68, 68, 76,248, 0, 0, 0}; /* "D" */ +static const GLubyte TimesRoman10_Character_069[] = { 6, 0, 0, 0,248, 72, 64,112, 64, 72,248, 0, 0, 0}; /* "E" */ +static const GLubyte TimesRoman10_Character_070[] = { 6, 0, 0, 0,224, 64, 64,112, 64, 72,248, 0, 0, 0}; /* "F" */ +static const GLubyte TimesRoman10_Character_071[] = { 7, 0, 0, 0,120,196,132,156,128,196,124, 0, 0, 0}; /* "G" */ +static const GLubyte TimesRoman10_Character_072[] = { 8, 0, 0, 0,238, 68, 68,124, 68, 68,238, 0, 0, 0}; /* "H" */ +static const GLubyte TimesRoman10_Character_073[] = { 4, 0, 0, 0,224, 64, 64, 64, 64, 64,224, 0, 0, 0}; /* "I" */ +static const GLubyte TimesRoman10_Character_074[] = { 4, 0, 0, 0,192,160, 32, 32, 32, 32,112, 0, 0, 0}; /* "J" */ +static const GLubyte TimesRoman10_Character_075[] = { 7, 0, 0, 0,236, 72, 80, 96, 80, 72,236, 0, 0, 0}; /* "K" */ +static const GLubyte TimesRoman10_Character_076[] = { 6, 0, 0, 0,248, 72, 64, 64, 64, 64,224, 0, 0, 0}; /* "L" */ +static const GLubyte TimesRoman10_Character_077[] = { 10, 0, 0, 0, 0, 0, 0,235,128, 73, 0, 85, 0, 85, 0, 99, 0, 99, 0,227,128, 0, 0, 0, 0, 0, 0}; /* "M" */ +static const GLubyte TimesRoman10_Character_078[] = { 8, 0, 0, 0,228, 76, 76, 84, 84,100,238, 0, 0, 0}; /* "N" */ +static const GLubyte TimesRoman10_Character_079[] = { 7, 0, 0, 0,120,204,132,132,132,204,120, 0, 0, 0}; /* "O" */ +static const GLubyte TimesRoman10_Character_080[] = { 6, 0, 0, 0,224, 64, 64,112, 72, 72,240, 0, 0, 0}; /* "P" */ +static const GLubyte TimesRoman10_Character_081[] = { 7, 0, 12, 24,112,204,132,132,132,204,120, 0, 0, 0}; /* "Q" */ +static const GLubyte TimesRoman10_Character_082[] = { 7, 0, 0, 0,236, 72, 80,112, 72, 72,240, 0, 0, 0}; /* "R" */ +static const GLubyte TimesRoman10_Character_083[] = { 5, 0, 0, 0,224,144, 16, 96,192,144,112, 0, 0, 0}; /* "S" */ +static const GLubyte TimesRoman10_Character_084[] = { 6, 0, 0, 0,112, 32, 32, 32, 32,168,248, 0, 0, 0}; /* "T" */ +static const GLubyte TimesRoman10_Character_085[] = { 8, 0, 0, 0, 56,108, 68, 68, 68, 68,238, 0, 0, 0}; /* "U" */ +static const GLubyte TimesRoman10_Character_086[] = { 8, 0, 0, 0, 16, 16, 40, 40,108, 68,238, 0, 0, 0}; /* "V" */ +static const GLubyte TimesRoman10_Character_087[] = { 10, 0, 0, 0, 0, 0, 0, 34, 0, 34, 0, 85, 0, 85, 0,201,128,136,128,221,192, 0, 0, 0, 0, 0, 0}; /* "W" */ +static const GLubyte TimesRoman10_Character_088[] = { 8, 0, 0, 0,238, 68, 40, 16, 40, 68,238, 0, 0, 0}; /* "X" */ +static const GLubyte TimesRoman10_Character_089[] = { 8, 0, 0, 0, 56, 16, 16, 40, 40, 68,238, 0, 0, 0}; /* "Y" */ +static const GLubyte TimesRoman10_Character_090[] = { 6, 0, 0, 0,248,136, 64, 32, 16,136,248, 0, 0, 0}; /* "Z" */ +static const GLubyte TimesRoman10_Character_048[] = { 5, 0, 0, 0, 96,144,144,144,144,144, 96, 0, 0, 0}; /* "0" */ +static const GLubyte TimesRoman10_Character_049[] = { 5, 0, 0, 0,224, 64, 64, 64, 64,192, 64, 0, 0, 0}; /* "1" */ +static const GLubyte TimesRoman10_Character_050[] = { 5, 0, 0, 0,240, 64, 32, 32, 16,144, 96, 0, 0, 0}; /* "2" */ +static const GLubyte TimesRoman10_Character_051[] = { 5, 0, 0, 0,224, 16, 16, 96, 16,144, 96, 0, 0, 0}; /* "3" */ +static const GLubyte TimesRoman10_Character_052[] = { 5, 0, 0, 0, 16, 16,248,144, 80, 48, 16, 0, 0, 0}; /* "4" */ +static const GLubyte TimesRoman10_Character_053[] = { 5, 0, 0, 0,224,144, 16, 16,224, 64,112, 0, 0, 0}; /* "5" */ +static const GLubyte TimesRoman10_Character_054[] = { 5, 0, 0, 0, 96,144,144,144,224, 64, 48, 0, 0, 0}; /* "6" */ +static const GLubyte TimesRoman10_Character_055[] = { 5, 0, 0, 0, 64, 64, 64, 32, 32,144,240, 0, 0, 0}; /* "7" */ +static const GLubyte TimesRoman10_Character_056[] = { 5, 0, 0, 0, 96,144,144, 96,144,144, 96, 0, 0, 0}; /* "8" */ +static const GLubyte TimesRoman10_Character_057[] = { 5, 0, 0, 0,192, 32,112,144,144,144, 96, 0, 0, 0}; /* "9" */ +static const GLubyte TimesRoman10_Character_096[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0,192,128, 0, 0, 0}; /* "`" */ +static const GLubyte TimesRoman10_Character_126[] = { 7, 0, 0, 0, 0, 0,152,100, 0, 0, 0, 0, 0, 0}; /* "~" */ +static const GLubyte TimesRoman10_Character_033[] = { 3, 0, 0, 0,128, 0,128,128,128,128,128, 0, 0, 0}; /* "!" */ +static const GLubyte TimesRoman10_Character_064[] = { 9, 0, 0, 62, 0, 64, 0,146, 0,173, 0,165, 0,165, 0,157, 0, 66, 0, 60, 0, 0, 0, 0, 0, 0, 0}; /* "@" */ +static const GLubyte TimesRoman10_Character_035[] = { 5, 0, 0, 0, 80, 80,248, 80,248, 80, 80, 0, 0, 0}; /* "#" */ +static const GLubyte TimesRoman10_Character_036[] = { 5, 0, 0, 32,224,144, 16, 96,128,144,112, 32, 0, 0}; /* "$" */ +static const GLubyte TimesRoman10_Character_037[] = { 8, 0, 0, 0, 68, 42, 42, 86,168,164,126, 0, 0, 0}; /* "%" */ +static const GLubyte TimesRoman10_Character_094[] = { 5, 0, 0, 0, 0, 0, 0, 0,160,160, 64, 0, 0, 0}; /* "^" */ +static const GLubyte TimesRoman10_Character_038[] = { 8, 0, 0, 0,118,141,152,116,110, 80, 48, 0, 0, 0}; /* "&" */ +static const GLubyte TimesRoman10_Character_042[] = { 5, 0, 0, 0, 0, 0, 0, 0,160, 64,160, 0, 0, 0}; /* "*" */ +static const GLubyte TimesRoman10_Character_040[] = { 4, 0, 32, 64, 64,128,128,128, 64, 64, 32, 0, 0, 0}; /* "(" */ +static const GLubyte TimesRoman10_Character_041[] = { 4, 0,128, 64, 64, 32, 32, 32, 64, 64,128, 0, 0, 0}; /* ")" */ +static const GLubyte TimesRoman10_Character_045[] = { 7, 0, 0, 0, 0, 0,240, 0, 0, 0, 0, 0, 0, 0}; /* "-" */ +static const GLubyte TimesRoman10_Character_095[] = { 5,252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "_" */ +static const GLubyte TimesRoman10_Character_061[] = { 6, 0, 0, 0, 0,248, 0,248, 0, 0, 0, 0, 0, 0}; /* "=" */ +static const GLubyte TimesRoman10_Character_043[] = { 6, 0, 0, 0, 32, 32,248, 32, 32, 0, 0, 0, 0, 0}; /* "+" */ +static const GLubyte TimesRoman10_Character_091[] = { 3, 0,192,128,128,128,128,128,128,128,192, 0, 0, 0}; /* "[" */ +static const GLubyte TimesRoman10_Character_123[] = { 4, 0, 32, 64, 64, 64,128, 64, 64, 64, 32, 0, 0, 0}; /* "{" */ +static const GLubyte TimesRoman10_Character_125[] = { 4, 0,128, 64, 64, 64, 32, 64, 64, 64,128, 0, 0, 0}; /* "}" */ +static const GLubyte TimesRoman10_Character_093[] = { 3, 0,192, 64, 64, 64, 64, 64, 64, 64,192, 0, 0, 0}; /* "]" */ +static const GLubyte TimesRoman10_Character_059[] = { 3, 0,128,128,128, 0, 0, 0,128, 0, 0, 0, 0, 0}; /* ";" */ +static const GLubyte TimesRoman10_Character_058[] = { 3, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0, 0, 0}; /* ":" */ +static const GLubyte TimesRoman10_Character_044[] = { 3, 0,128,128,128, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "," */ +static const GLubyte TimesRoman10_Character_046[] = { 3, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "." */ +static const GLubyte TimesRoman10_Character_060[] = { 5, 0, 0, 0, 32, 64,128, 64, 32, 0, 0, 0, 0, 0}; /* "<" */ +static const GLubyte TimesRoman10_Character_062[] = { 5, 0, 0, 0,128, 64, 32, 64,128, 0, 0, 0, 0, 0}; /* ">" */ +static const GLubyte TimesRoman10_Character_047[] = { 3, 0, 0, 0,128,128, 64, 64, 64, 32, 32, 0, 0, 0}; /* "/" */ +static const GLubyte TimesRoman10_Character_063[] = { 4, 0, 0, 0, 64, 0, 64, 64, 32,160,224, 0, 0, 0}; /* "?" */ +static const GLubyte TimesRoman10_Character_092[] = { 3, 0, 0, 0, 32, 32, 64, 64, 64,128,128, 0, 0, 0}; /* "\" */ +static const GLubyte TimesRoman10_Character_034[] = { 4, 0, 0, 0, 0, 0, 0, 0, 0,160,160, 0, 0, 0}; /* """ */ + +/* Missing Characters filled in by John Fay by hand ... */ +static const GLubyte TimesRoman10_Character_039[] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 64, 64,192, 0, 0}; /* "'" */ +static const GLubyte TimesRoman10_Character_124[] = { 2,128,128,128,128,128,128,128,128,128,128,128,128,128}; /* "|" */ + + +/* The font characters mapping: */ +static const GLubyte* TimesRoman10_Character_Map[] = {TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_032,TimesRoman10_Character_033,TimesRoman10_Character_034,TimesRoman10_Character_035, +TimesRoman10_Character_036,TimesRoman10_Character_037,TimesRoman10_Character_038,TimesRoman10_Character_039,TimesRoman10_Character_040,TimesRoman10_Character_041,TimesRoman10_Character_042,TimesRoman10_Character_043,TimesRoman10_Character_044,TimesRoman10_Character_045,TimesRoman10_Character_046,TimesRoman10_Character_047,TimesRoman10_Character_048,TimesRoman10_Character_049,TimesRoman10_Character_050,TimesRoman10_Character_051,TimesRoman10_Character_052,TimesRoman10_Character_053,TimesRoman10_Character_054,TimesRoman10_Character_055,TimesRoman10_Character_056,TimesRoman10_Character_057,TimesRoman10_Character_058,TimesRoman10_Character_059,TimesRoman10_Character_060,TimesRoman10_Character_061,TimesRoman10_Character_062,TimesRoman10_Character_063,TimesRoman10_Character_064,TimesRoman10_Character_065,TimesRoman10_Character_066,TimesRoman10_Character_067,TimesRoman10_Character_068,TimesRoman10_Character_069,TimesRoman10_Character_070,TimesRoman10_Character_071,TimesRoman10_Character_072, +TimesRoman10_Character_073,TimesRoman10_Character_074,TimesRoman10_Character_075,TimesRoman10_Character_076,TimesRoman10_Character_077,TimesRoman10_Character_078,TimesRoman10_Character_079,TimesRoman10_Character_080,TimesRoman10_Character_081,TimesRoman10_Character_082,TimesRoman10_Character_083,TimesRoman10_Character_084,TimesRoman10_Character_085,TimesRoman10_Character_086,TimesRoman10_Character_087,TimesRoman10_Character_088,TimesRoman10_Character_089,TimesRoman10_Character_090,TimesRoman10_Character_091,TimesRoman10_Character_092,TimesRoman10_Character_093,TimesRoman10_Character_094,TimesRoman10_Character_095,TimesRoman10_Character_096,TimesRoman10_Character_097,TimesRoman10_Character_098,TimesRoman10_Character_099,TimesRoman10_Character_100,TimesRoman10_Character_101,TimesRoman10_Character_102,TimesRoman10_Character_103,TimesRoman10_Character_104,TimesRoman10_Character_105,TimesRoman10_Character_106,TimesRoman10_Character_107,TimesRoman10_Character_108,TimesRoman10_Character_109, +TimesRoman10_Character_110,TimesRoman10_Character_111,TimesRoman10_Character_112,TimesRoman10_Character_113,TimesRoman10_Character_114,TimesRoman10_Character_115,TimesRoman10_Character_116,TimesRoman10_Character_117,TimesRoman10_Character_118,TimesRoman10_Character_119,TimesRoman10_Character_120,TimesRoman10_Character_121,TimesRoman10_Character_122,TimesRoman10_Character_123,TimesRoman10_Character_124,TimesRoman10_Character_125,TimesRoman10_Character_126,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042, +TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042, +TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042, +TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,TimesRoman10_Character_042,NULL}; + +/* The font structure: */ +static const SFG_Font fgFontTimesRoman10 = { "-adobe-times-medium-r-normal--10-100-75-75-p-54-iso8859-1", 93, 13, TimesRoman10_Character_Map, 0.0f, 3.0f }; + +static const GLubyte TimesRoman24_Character_032[] = { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* " " */ +static const GLubyte TimesRoman24_Character_097[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,113,128,251, 0,199, 0,195, 0,195, 0, 99, 0, 59, 0, 15, 0, 3, 0, 99, 0,103, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "a" */ +static const GLubyte TimesRoman24_Character_098[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 0,115,128, 97,128, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192, 97,128,115,128,110, 0, 96, 0, 96, 0, 96, 0, 96, 0,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "b" */ +static const GLubyte TimesRoman24_Character_099[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0,127, 0,112,128,224, 0,192, 0,192, 0,192, 0,192, 0,192, 0, 65,128, 99,128, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "c" */ +static const GLubyte TimesRoman24_Character_100[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30,192,115,128, 97,128,193,128,193,128,193,128,193,128,193,128,193,128, 97,128,115,128, 29,128, 1,128, 1,128, 1,128, 1,128, 3,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "d" */ +static const GLubyte TimesRoman24_Character_101[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0,127, 0,112,128,224, 0,192, 0,192, 0,192, 0,255,128,193,128, 65,128, 99, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "e" */ +static const GLubyte TimesRoman24_Character_102[] = { 7, 0, 0, 0, 0, 0, 0,120, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,254, 48, 48, 48, 22, 14, 0, 0, 0, 0, 0}; /* "f" */ +static const GLubyte TimesRoman24_Character_103[] = { 12, 0, 0, 63, 0,241,192,192, 96,192, 32, 96, 96, 63,192,127, 0, 96, 0, 48, 0, 62, 0, 51, 0, 97,128, 97,128, 97,128, 97,128, 51, 0, 31,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "g" */ +static const GLubyte TimesRoman24_Character_104[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,241,224, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192,113,192,111,128,103, 0, 96, 0, 96, 0, 96, 0, 96, 0,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "h" */ +static const GLubyte TimesRoman24_Character_105[] = { 6, 0, 0, 0, 0, 0, 0,240, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,224, 0, 0, 0, 96, 96, 0, 0, 0, 0, 0}; /* "i" */ +static const GLubyte TimesRoman24_Character_106[] = { 6, 0,192,224, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,112, 0, 0, 0, 48, 48, 0, 0, 0, 0, 0}; /* "j" */ +static const GLubyte TimesRoman24_Character_107[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,243,224, 97,192, 99,128,103, 0,110, 0,108, 0,120, 0,104, 0,100, 0,102, 0, 99, 0,103,192, 96, 0, 96, 0, 96, 0, 96, 0,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "k" */ +static const GLubyte TimesRoman24_Character_108[] = { 6, 0, 0, 0, 0, 0, 0,240, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,224, 0, 0, 0, 0, 0}; /* "l" */ +static const GLubyte TimesRoman24_Character_109[] = { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,241,227,192, 96,193,128, 96,193,128, 96,193,128, 96,193,128, 96,193,128, 96,193,128, 96,193,128, 96,193,128,113,227,128,111,159, 0,231, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "m" */ +static const GLubyte TimesRoman24_Character_110[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,241,224, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192,113,192,111,128,231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "n" */ +static const GLubyte TimesRoman24_Character_111[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0,115,128, 97,128,192,192,192,192,192,192,192,192,192,192,192,192, 97,128,115,128, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "o" */ +static const GLubyte TimesRoman24_Character_112[] = { 12, 0, 0,240, 0, 96, 0, 96, 0, 96, 0, 96, 0,110, 0,115,128, 97,128, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192, 97,128,115,128,238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "p" */ +static const GLubyte TimesRoman24_Character_113[] = { 12, 0, 0, 3,192, 1,128, 1,128, 1,128, 1,128, 29,128,115,128, 97,128,193,128,193,128,193,128,193,128,193,128,193,128, 97,128,115,128, 29,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "q" */ +static const GLubyte TimesRoman24_Character_114[] = { 8, 0, 0, 0, 0, 0, 0,240, 96, 96, 96, 96, 96, 96, 96, 96,118,110,230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "r" */ +static const GLubyte TimesRoman24_Character_115[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 0,198, 0,131, 0, 3, 0, 7, 0, 30, 0,124, 0,112, 0,224, 0,194, 0,102, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "s" */ +static const GLubyte TimesRoman24_Character_116[] = { 7, 0, 0, 0, 0, 0, 0, 28, 50, 48, 48, 48, 48, 48, 48, 48, 48, 48,254,112, 48, 16, 0, 0, 0, 0, 0, 0, 0}; /* "t" */ +static const GLubyte TimesRoman24_Character_117[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28,224, 62,192,113,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192, 96,192,225,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "u" */ +static const GLubyte TimesRoman24_Character_118[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 14, 0, 14, 0, 26, 0, 25, 0, 25, 0, 49, 0, 48,128, 48,128, 96,128, 96,192,241,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "v" */ +static const GLubyte TimesRoman24_Character_119[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 16, 0, 14, 56, 0, 14, 56, 0, 26, 40, 0, 26,100, 0, 25,100, 0, 49,100, 0, 48,194, 0, 48,194, 0, 96,194, 0, 96,195, 0,241,231,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "w" */ +static const GLubyte TimesRoman24_Character_120[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,241,224, 96,192, 33,128, 51,128, 27, 0, 14, 0, 12, 0, 26, 0, 57, 0, 49,128, 96,192,241,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "x" */ +static const GLubyte TimesRoman24_Character_121[] = { 11, 0, 0,224, 0,240, 0, 24, 0, 8, 0, 12, 0, 4, 0, 14, 0, 14, 0, 26, 0, 25, 0, 25, 0, 49, 0, 48,128, 48,128, 96,128, 96,192,241,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "y" */ +static const GLubyte TimesRoman24_Character_122[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0,195, 0, 97, 0,112, 0, 48, 0, 56, 0, 24, 0, 28, 0, 14, 0,134, 0,195, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "z" */ +static const GLubyte TimesRoman24_Character_065[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31,128, 48, 6, 0, 16, 6, 0, 16, 12, 0, 24, 12, 0, 8, 12, 0, 15,248, 0, 12, 24, 0, 4, 24, 0, 4, 48, 0, 6, 48, 0, 2, 48, 0, 2, 96, 0, 1, 96, 0, 1,192, 0, 1,192, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "A" */ +static const GLubyte TimesRoman24_Character_066[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,224, 48,120, 48, 24, 48, 12, 48, 12, 48, 12, 48, 24, 48, 56, 63,224, 48, 64, 48, 48, 48, 24, 48, 24, 48, 24, 48, 48, 48,112,255,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "B" */ +static const GLubyte TimesRoman24_Character_067[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,224, 30, 56, 56, 8, 96, 4, 96, 0,192, 0,192, 0,192, 0,192, 0,192, 0,192, 0,192, 0, 96, 4, 96, 4, 56, 12, 28, 60, 7,228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "C" */ +static const GLubyte TimesRoman24_Character_068[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,192, 0, 48,112, 0, 48, 56, 0, 48, 12, 0, 48, 12, 0, 48, 6, 0, 48, 6, 0, 48, 6, 0, 48, 6, 0, 48, 6, 0, 48, 6, 0, 48, 6, 0, 48, 12, 0, 48, 12, 0, 48, 56, 0, 48,112, 0,255,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "D" */ +static const GLubyte TimesRoman24_Character_069[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,248, 48, 24, 48, 8, 48, 8, 48, 0, 48, 0, 48, 64, 48, 64, 63,192, 48, 64, 48, 64, 48, 0, 48, 0, 48, 16, 48, 16, 48, 48,255,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "E" */ +static const GLubyte TimesRoman24_Character_070[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 0, 48, 0, 48, 0, 48, 0, 48, 0, 48, 0, 48, 32, 48, 32, 63,224, 48, 32, 48, 32, 48, 0, 48, 0, 48, 16, 48, 16, 48, 48,255,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "F" */ +static const GLubyte TimesRoman24_Character_071[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,224, 0, 30, 56, 0, 56, 28, 0, 96, 12, 0, 96, 12, 0,192, 12, 0,192, 12, 0,192, 63, 0,192, 0, 0,192, 0, 0,192, 0, 0,192, 0, 0, 96, 4, 0, 96, 4, 0, 56, 12, 0, 28, 60, 0, 7,228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "G" */ +static const GLubyte TimesRoman24_Character_072[] = { 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31,128, 48, 6, 0, 48, 6, 0, 48, 6, 0, 48, 6, 0, 48, 6, 0, 48, 6, 0, 48, 6, 0, 63,254, 0, 48, 6, 0, 48, 6, 0, 48, 6, 0, 48, 6, 0, 48, 6, 0, 48, 6, 0, 48, 6, 0,252, 31,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "H" */ +static const GLubyte TimesRoman24_Character_073[] = { 8, 0, 0, 0, 0, 0, 0,252, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,252, 0, 0, 0, 0, 0}; /* "I" */ +static const GLubyte TimesRoman24_Character_074[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 0,204, 0,198, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 31,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "J" */ +static const GLubyte TimesRoman24_Character_075[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 31, 0, 48, 14, 0, 48, 28, 0, 48, 56, 0, 48,112, 0, 48,224, 0, 49,192, 0, 51,128, 0, 63, 0, 0, 62, 0, 0, 51, 0, 0, 49,128, 0, 48,192, 0, 48, 96, 0, 48, 48, 0, 48, 24, 0,252,126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "K" */ +static const GLubyte TimesRoman24_Character_076[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,248, 48, 24, 48, 8, 48, 8, 48, 0, 48, 0, 48, 0, 48, 0, 48, 0, 48, 0, 48, 0, 48, 0, 48, 0, 48, 0, 48, 0, 48, 0,252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "L" */ +static const GLubyte TimesRoman24_Character_077[] = { 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 33,248, 32, 96, 96, 32, 96, 96, 32,208, 96, 32,208, 96, 33,136, 96, 33,136, 96, 35, 8, 96, 35, 4, 96, 38, 4, 96, 38, 2, 96, 44, 2, 96, 44, 2, 96, 56, 1, 96, 56, 1, 96, 48, 0,224,240, 0,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "M" */ +static const GLubyte TimesRoman24_Character_078[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 12, 0, 32, 28, 0, 32, 28, 0, 32, 52, 0, 32,100, 0, 32,100, 0, 32,196, 0, 33,132, 0, 33,132, 0, 35, 4, 0, 38, 4, 0, 38, 4, 0, 44, 4, 0, 56, 4, 0, 56, 4, 0, 48, 4, 0,240, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "N" */ +static const GLubyte TimesRoman24_Character_079[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,224, 0, 28, 56, 0, 56, 28, 0, 96, 6, 0, 96, 6, 0,192, 3, 0,192, 3, 0,192, 3, 0,192, 3, 0,192, 3, 0,192, 3, 0,192, 3, 0, 96, 6, 0, 96, 6, 0, 56, 28, 0, 28, 56, 0, 7,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "O" */ +static const GLubyte TimesRoman24_Character_080[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 0, 48, 0, 48, 0, 48, 0, 48, 0, 48, 0, 48, 0, 48, 0, 63,192, 48,112, 48, 48, 48, 24, 48, 24, 48, 24, 48, 48, 48,112,255,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "P" */ +static const GLubyte TimesRoman24_Character_081[] = { 18, 0, 0, 0, 0, 15, 0, 0, 56, 0, 0,112, 0, 0,224, 0, 1,192, 0, 7,224, 0, 28, 56, 0, 56, 28, 0, 96, 6, 0, 96, 6, 0,192, 3, 0,192, 3, 0,192, 3, 0,192, 3, 0,192, 3, 0,192, 3, 0,192, 3, 0, 96, 6, 0, 96, 6, 0, 56, 28, 0, 28, 56, 0, 7,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "Q" */ +static const GLubyte TimesRoman24_Character_082[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 30, 48, 28, 48, 56, 48,112, 48, 96, 48,192, 49,192, 51,128, 63,192, 48,112, 48, 48, 48, 56, 48, 24, 48, 56, 48, 48, 48,112,255,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "R" */ +static const GLubyte TimesRoman24_Character_083[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,158, 0,241,128,192,192,128, 96,128, 96, 0, 96, 0,224, 3,192, 15,128, 30, 0,120, 0,224, 0,192, 64,192, 64,192,192, 99,192, 30, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "S" */ +static const GLubyte TimesRoman24_Character_084[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,192, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0,131, 4,131, 4,195, 12,255,252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "T" */ +static const GLubyte TimesRoman24_Character_085[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,224, 0, 28, 48, 0, 24, 8, 0, 48, 8, 0, 48, 4, 0, 48, 4, 0, 48, 4, 0, 48, 4, 0, 48, 4, 0, 48, 4, 0, 48, 4, 0, 48, 4, 0, 48, 4, 0, 48, 4, 0, 48, 4, 0, 48, 4, 0,252, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "U" */ +static const GLubyte TimesRoman24_Character_086[] = { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,128, 0, 1,128, 0, 1,128, 0, 3,192, 0, 3, 64, 0, 3, 96, 0, 6, 32, 0, 6, 32, 0, 6, 48, 0, 12, 16, 0, 12, 24, 0, 24, 8, 0, 24, 8, 0, 24, 12, 0, 48, 4, 0, 48, 6, 0,252, 31,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "V" */ +static const GLubyte TimesRoman24_Character_087[] = { 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,131, 0, 1,131, 0, 1,131,128, 3,135,128, 3, 70,128, 3, 70,192, 6, 70, 64, 6, 76, 64, 6, 76, 96, 12, 44, 96, 12, 44, 32, 24, 44, 32, 24, 24, 48, 24, 24, 16, 48, 24, 16, 48, 24, 24,252,126,126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "W" */ +static const GLubyte TimesRoman24_Character_088[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 15,192, 48, 3,128, 24, 7, 0, 8, 14, 0, 4, 12, 0, 6, 24, 0, 2, 56, 0, 1,112, 0, 0,224, 0, 0,192, 0, 1,192, 0, 3,160, 0, 3, 16, 0, 6, 8, 0, 14, 12, 0, 28, 6, 0,126, 15,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "X" */ +static const GLubyte TimesRoman24_Character_089[] = { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,224, 1,128, 1,128, 1,128, 1,128, 1,128, 1,128, 3,192, 3, 64, 6, 96, 6, 32, 12, 48, 28, 16, 24, 24, 56, 8, 48, 12,252, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "Y" */ +static const GLubyte TimesRoman24_Character_090[] = { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,248,224, 24,112, 8, 48, 8, 56, 0, 24, 0, 28, 0, 14, 0, 6, 0, 7, 0, 3, 0, 3,128, 1,192,128,192,128,224,192,112,255,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "Z" */ +static const GLubyte TimesRoman24_Character_048[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 51, 0, 97,128, 97,128,225,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, 97,128, 97,128, 51, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "0" */ +static const GLubyte TimesRoman24_Character_049[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0,120, 0, 24, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "1" */ +static const GLubyte TimesRoman24_Character_050[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,128,255,192, 96, 64, 48, 0, 24, 0, 12, 0, 4, 0, 6, 0, 3, 0, 3, 0, 1,128, 1,128,129,128,129,128, 67,128,127, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "2" */ +static const GLubyte TimesRoman24_Character_051[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120, 0,230, 0,195, 0, 1, 0, 1,128, 1,128, 1,128, 3,128, 7, 0, 30, 0, 12, 0, 6, 0,131, 0,131, 0, 71, 0,126, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "3" */ +static const GLubyte TimesRoman24_Character_052[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 3, 0, 3, 0,255,192,255,192,195, 0, 67, 0, 99, 0, 35, 0, 51, 0, 19, 0, 27, 0, 11, 0, 7, 0, 7, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "4" */ +static const GLubyte TimesRoman24_Character_053[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 0,227,128,193,128, 0,192, 0,192, 0,192, 0,192, 1,192, 3,128, 15,128,126, 0,120, 0, 96, 0, 32, 0, 32, 0, 31,128, 31,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "5" */ +static const GLubyte TimesRoman24_Character_054[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0,123,128, 97,128,224,192,192,192,192,192,192,192,192,192,193,128,243,128,238, 0, 96, 0,112, 0, 48, 0, 24, 0, 14, 0, 3,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "6" */ +static const GLubyte TimesRoman24_Character_055[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 24, 0, 12, 0, 12, 0, 12, 0, 4, 0, 6, 0, 6, 0, 2, 0, 3, 0, 3, 0, 1, 0, 1,128,129,128,192,192,255,192,127,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "7" */ +static const GLubyte TimesRoman24_Character_056[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0,115,128,225,128,192,192,192,192,192,192, 65,192, 97,128, 55, 0, 30, 0, 30, 0, 51, 0, 97,128, 97,128, 97,128, 51, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "8" */ +static const GLubyte TimesRoman24_Character_057[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 0, 28, 0, 6, 0, 3, 0, 3,128, 1,128, 29,128,115,192, 97,192,192,192,192,192,192,192,192,192,193,192, 97,128,119,128, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "9" */ +static const GLubyte TimesRoman24_Character_096[] = { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,224,128,192, 96, 0, 0, 0, 0, 0}; /* "`" */ +static const GLubyte TimesRoman24_Character_126[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,131,128,199,192,124, 96, 56, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "~" */ +static const GLubyte TimesRoman24_Character_033[] = { 8, 0, 0, 0, 0, 0, 0,192,192, 0, 0, 0,192,192,192,192,192,192,192,192,192,192,192,192, 0, 0, 0, 0, 0}; /* "!" */ +static const GLubyte TimesRoman24_Character_064[] = { 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,240, 0, 14, 12, 0, 24, 0, 0, 48, 0, 0, 97,222, 0, 99,123, 0,198, 57,128,198, 24,128,198, 24,192,198, 24, 64,198, 12, 64,195, 12, 64,195,140, 64,225,252, 64, 96,236,192,112, 0,128, 56, 1,128, 28, 3, 0, 15, 14, 0, 3,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "@" */ +static const GLubyte TimesRoman24_Character_035[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 34, 0, 34, 0, 34, 0, 34, 0,255,192,255,192, 17, 0, 17, 0, 17, 0,127,224,127,224, 8,128, 8,128, 8,128, 8,128, 8,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "#" */ +static const GLubyte TimesRoman24_Character_036[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 63, 0,229,192,196,192,132, 96,132, 96, 4, 96, 4,224, 7,192, 7,128, 30, 0, 60, 0,116, 0,100, 0,100, 32,100, 96, 52,224, 31,128, 4, 0, 4, 0, 0, 0, 0, 0, 0, 0}; /* "$" */ +static const GLubyte TimesRoman24_Character_037[] = { 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 60, 0, 24,114, 0, 12, 97, 0, 4, 96,128, 6, 96,128, 3, 48,128, 1, 25,128, 1,143, 0,120,192, 0,228, 64, 0,194, 96, 0,193, 48, 0,193, 16, 0, 97, 24, 0, 51,252, 0, 30, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "%" */ +static const GLubyte TimesRoman24_Character_094[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,128,193,128, 65, 0, 99, 0, 34, 0, 54, 0, 20, 0, 28, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "^" */ +static const GLubyte TimesRoman24_Character_038[] = { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 60, 0,127,126, 0,225,225, 0,192,192, 0,193,192, 0,193,160, 0, 99, 32, 0, 55, 16, 0, 30, 24, 0, 14, 62, 0, 15, 0, 0, 29,128, 0, 24,192, 0, 24, 64, 0, 24, 64, 0, 12,192, 0, 7,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "&" */ +static const GLubyte TimesRoman24_Character_042[] = { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 28, 0,201,128,235,128, 28, 0,235,128,201,128, 28, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "*" */ +static const GLubyte TimesRoman24_Character_040[] = { 8, 0, 4, 8, 16, 48, 32, 96, 96,192,192,192,192,192,192,192,192, 96, 96, 32, 48, 16, 8, 4, 0, 0, 0, 0, 0}; /* "(" */ +static const GLubyte TimesRoman24_Character_041[] = { 8, 0,128, 64, 32, 48, 16, 24, 24, 12, 12, 12, 12, 12, 12, 12, 12, 24, 24, 16, 48, 32, 64,128, 0, 0, 0, 0, 0}; /* ")" */ +static const GLubyte TimesRoman24_Character_045[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,240,255,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "-" */ +static const GLubyte TimesRoman24_Character_095[] = { 13, 0, 0,255,248,255,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "_" */ +static const GLubyte TimesRoman24_Character_061[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,240,255,240, 0, 0, 0, 0,255,240,255,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "=" */ +static const GLubyte TimesRoman24_Character_043[] = { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0,255,240,255,240, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "+" */ +static const GLubyte TimesRoman24_Character_091[] = { 8, 0, 0,248,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,248, 0, 0, 0, 0, 0}; /* "[" */ +static const GLubyte TimesRoman24_Character_123[] = { 10, 0, 0, 7, 0, 12, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 16, 0, 48, 0, 32, 0,192, 0, 32, 0, 48, 0, 16, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 12, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "{" */ +static const GLubyte TimesRoman24_Character_125[] = { 10, 0, 0,224, 0, 48, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 8, 0, 12, 0, 4, 0, 3, 0, 4, 0, 12, 0, 8, 0, 24, 0, 24, 0, 24, 0, 24, 0, 24, 0, 48, 0,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "}" */ +static const GLubyte TimesRoman24_Character_093[] = { 8, 0, 0,248, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,248, 0, 0, 0, 0, 0}; /* "]" */ +static const GLubyte TimesRoman24_Character_059[] = { 7, 0, 0, 0,192, 96, 32,224,192, 0, 0, 0, 0, 0, 0, 0,192,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* ";" */ +static const GLubyte TimesRoman24_Character_058[] = { 6, 0, 0, 0, 0, 0, 0,192,192, 0, 0, 0, 0, 0, 0, 0,192,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* ":" */ +static const GLubyte TimesRoman24_Character_044[] = { 7, 0, 0, 0,192, 96, 32,224,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "," */ +static const GLubyte TimesRoman24_Character_046[] = { 6, 0, 0, 0, 0, 0, 0,192,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "." */ +static const GLubyte TimesRoman24_Character_060[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 1,192, 7, 0, 28, 0,112, 0,192, 0,112, 0, 28, 0, 7, 0, 1,192, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "<" */ +static const GLubyte TimesRoman24_Character_062[] = { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 0,112, 0, 28, 0, 7, 0, 1,192, 0, 96, 1,192, 7, 0, 28, 0,112, 0,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* ">" */ +static const GLubyte TimesRoman24_Character_047[] = { 7, 0, 0, 0,192,192,192, 96, 96, 32, 48, 48, 16, 24, 24, 8, 12, 12, 4, 6, 6, 3, 3, 3, 0, 0, 0, 0, 0}; /* "/" */ +static const GLubyte TimesRoman24_Character_063[] = { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 48, 0, 0, 0, 0, 0, 16, 0, 16, 0, 16, 0, 24, 0, 24, 0, 12, 0, 14, 0, 7, 0,195, 0,195, 0,131, 0,198, 0,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* "?" */ +static const GLubyte TimesRoman24_Character_092[] = { 7, 0, 0, 0, 0, 0, 0, 6, 6, 4, 12, 12, 8, 24, 24, 16, 48, 48, 32, 96, 96, 64,192,192, 0, 0, 0, 0, 0}; /* "\" */ +static const GLubyte TimesRoman24_Character_034[] = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,136, 0,204, 0,204, 0,204, 0,204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* """ */ + +/* Missing Characters filled in by John Fay by hand ... */ +static const GLubyte TimesRoman24_Character_039[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 96, 32,224,192, 0, 0, 0, 0, 0}; /* "'" */ +static const GLubyte TimesRoman24_Character_124[] = { 6, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 0, 0}; /* "|" */ + + +/* The font characters mapping: */ +static const GLubyte* TimesRoman24_Character_Map[] = {TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_032,TimesRoman24_Character_033,TimesRoman24_Character_034,TimesRoman24_Character_035, +TimesRoman24_Character_036,TimesRoman24_Character_037,TimesRoman24_Character_038,TimesRoman24_Character_039,TimesRoman24_Character_040,TimesRoman24_Character_041,TimesRoman24_Character_042,TimesRoman24_Character_043,TimesRoman24_Character_044,TimesRoman24_Character_045,TimesRoman24_Character_046,TimesRoman24_Character_047,TimesRoman24_Character_048,TimesRoman24_Character_049,TimesRoman24_Character_050,TimesRoman24_Character_051,TimesRoman24_Character_052,TimesRoman24_Character_053,TimesRoman24_Character_054,TimesRoman24_Character_055,TimesRoman24_Character_056,TimesRoman24_Character_057,TimesRoman24_Character_058,TimesRoman24_Character_059,TimesRoman24_Character_060,TimesRoman24_Character_061,TimesRoman24_Character_062,TimesRoman24_Character_063,TimesRoman24_Character_064,TimesRoman24_Character_065,TimesRoman24_Character_066,TimesRoman24_Character_067,TimesRoman24_Character_068,TimesRoman24_Character_069,TimesRoman24_Character_070,TimesRoman24_Character_071,TimesRoman24_Character_072, +TimesRoman24_Character_073,TimesRoman24_Character_074,TimesRoman24_Character_075,TimesRoman24_Character_076,TimesRoman24_Character_077,TimesRoman24_Character_078,TimesRoman24_Character_079,TimesRoman24_Character_080,TimesRoman24_Character_081,TimesRoman24_Character_082,TimesRoman24_Character_083,TimesRoman24_Character_084,TimesRoman24_Character_085,TimesRoman24_Character_086,TimesRoman24_Character_087,TimesRoman24_Character_088,TimesRoman24_Character_089,TimesRoman24_Character_090,TimesRoman24_Character_091,TimesRoman24_Character_092,TimesRoman24_Character_093,TimesRoman24_Character_094,TimesRoman24_Character_095,TimesRoman24_Character_096,TimesRoman24_Character_097,TimesRoman24_Character_098,TimesRoman24_Character_099,TimesRoman24_Character_100,TimesRoman24_Character_101,TimesRoman24_Character_102,TimesRoman24_Character_103,TimesRoman24_Character_104,TimesRoman24_Character_105,TimesRoman24_Character_106,TimesRoman24_Character_107,TimesRoman24_Character_108,TimesRoman24_Character_109, +TimesRoman24_Character_110,TimesRoman24_Character_111,TimesRoman24_Character_112,TimesRoman24_Character_113,TimesRoman24_Character_114,TimesRoman24_Character_115,TimesRoman24_Character_116,TimesRoman24_Character_117,TimesRoman24_Character_118,TimesRoman24_Character_119,TimesRoman24_Character_120,TimesRoman24_Character_121,TimesRoman24_Character_122,TimesRoman24_Character_123,TimesRoman24_Character_124,TimesRoman24_Character_125,TimesRoman24_Character_126,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042, +TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042, +TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042, +TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,TimesRoman24_Character_042,NULL}; + +/* The font structure: */ +static const SFG_Font fgFontTimesRoman24 = { "-adobe-times-medium-r-normal--24-240-75-75-p-124-iso8859-1", 93, 28, TimesRoman24_Character_Map, -1.0f, 6.0f }; + + + +/* + * End of code from FreeGLUT. + */ + + +#define ARGS(X) (X.Characters, 1, X.Height, X.xorig, X.yorig) + +static fntBitmapFont fntFixed8x13 ARGS( fgFontFixed8x13 ); +static fntBitmapFont fntFixed9x15 ARGS( fgFontFixed9x15 ); +static fntBitmapFont fntHelvetica10 ARGS( fgFontHelvetica10 ); +static fntBitmapFont fntHelvetica12 ARGS( fgFontHelvetica12 ); +static fntBitmapFont fntHelvetica18 ARGS( fgFontHelvetica18 ); +static fntBitmapFont fntTimesRoman10 ARGS( fgFontTimesRoman10 ); +static fntBitmapFont fntTimesRoman24 ARGS( fgFontTimesRoman24 ); + + +fntBitmapFont *fntGetBitmapFont(int id) +{ + fntBitmapFont *fnt = NULL; + switch (id) { + case FNT_BITMAP_8_BY_13: fnt = &fntFixed8x13; break; + case FNT_BITMAP_9_BY_15: fnt = &fntFixed9x15; break; + case FNT_BITMAP_HELVETICA_10: fnt = &fntHelvetica10; break; + case FNT_BITMAP_HELVETICA_12: fnt = &fntHelvetica12; break; + case FNT_BITMAP_HELVETICA_18: fnt = &fntHelvetica18; break; + case FNT_BITMAP_TIMES_ROMAN_10: fnt = &fntTimesRoman10; break; + case FNT_BITMAP_TIMES_ROMAN_24: fnt = &fntTimesRoman24; break; + } + return fnt; +} diff --git a/src/fnt/fntLocal.h b/src/fnt/fntLocal.h new file mode 100644 index 0000000..6d48679 --- /dev/null +++ b/src/fnt/fntLocal.h @@ -0,0 +1,111 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: fntLocal.h 1727 2002-11-09 21:27:21Z ude $ +*/ + + +#include "fnt.h" + + +extern int _fntIsSwapped ; +extern FILE *_fntCurrImageFd ; + + +inline void _fnt_swab_short ( unsigned short *x ) +{ + if ( _fntIsSwapped ) + *x = (( *x >> 8 ) & 0x00FF ) | + (( *x << 8 ) & 0xFF00 ) ; +} + + +inline void _fnt_swab_int ( unsigned int *x ) +{ + if ( _fntIsSwapped ) + *x = (( *x >> 24 ) & 0x000000FF ) | + (( *x >> 8 ) & 0x0000FF00 ) | + (( *x << 8 ) & 0x00FF0000 ) | + (( *x << 24 ) & 0xFF000000 ) ; +} + + +inline void _fnt_swab_int_array ( int *x, int leng ) +{ + if ( ! _fntIsSwapped ) + return ; + + for ( int i = 0 ; i < leng ; i++ ) + { + *x = (( *x >> 24 ) & 0x000000FF ) | + (( *x >> 8 ) & 0x0000FF00 ) | + (( *x << 8 ) & 0x00FF0000 ) | + (( *x << 24 ) & 0xFF000000 ) ; + x++ ; + } +} + + +inline unsigned char _fnt_readByte () +{ + unsigned char x ; + fread ( & x, sizeof(unsigned char), 1, _fntCurrImageFd ) ; + return x ; +} + +inline unsigned short _fnt_readShort () +{ + unsigned short x ; + fread ( & x, sizeof(unsigned short), 1, _fntCurrImageFd ) ; + _fnt_swab_short ( & x ) ; + return x ; +} + +inline unsigned int _fnt_readInt () +{ + unsigned int x ; + fread ( & x, sizeof(unsigned int), 1, _fntCurrImageFd ) ; + _fnt_swab_int ( & x ) ; + return x ; +} + + +#define FNT_BYTE_FORMAT 0 +#define FNT_BITMAP_FORMAT 1 + +struct TXF_Glyph +{ + unsigned short ch ; + unsigned char w ; + unsigned char h ; + signed char x_off ; + signed char y_off ; + signed char step ; + signed char unknown ; + short x ; + short y ; + + sgVec2 tx0 ; sgVec2 vx0 ; + sgVec2 tx1 ; sgVec2 vx1 ; + sgVec2 tx2 ; sgVec2 vx2 ; + sgVec2 tx3 ; sgVec2 vx3 ; +} ; + + diff --git a/src/fnt/fntTXF.cxx b/src/fnt/fntTXF.cxx new file mode 100644 index 0000000..e664c90 --- /dev/null +++ b/src/fnt/fntTXF.cxx @@ -0,0 +1,363 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: fntTXF.cxx 1735 2002-12-01 18:21:48Z sjbaker $ +*/ + + +#include "fntLocal.h" + +#ifdef UL_MACINTOSH +# include +#elif defined(UL_MAC_OSX) +# include +#elif defined(UL_WIN32) + /* Nothing */ +#else +# include +#endif + +static bool glIsValidContext ( void ) +{ +#if defined(CONSOLE) + return true ; +#elif defined(UL_WIN32) + return ( wglGetCurrentContext () != NULL ) ; +#elif defined(UL_MACINTOSH) + return ( aglGetCurrentContext () != NULL ) ; +#elif defined(UL_MAC_OSX) + return ( CGLGetCurrentContext () != NULL ) ; +#else + return ( glXGetCurrentContext () != NULL ) ; +#endif +} + +FILE *_fntCurrImageFd ; +int _fntIsSwapped = FALSE ; + +static void tex_make_mip_maps ( GLubyte *image, int xsize, + int ysize, int zsize ) +{ + GLubyte *texels [ 20 ] ; /* One element per level of MIPmap */ + + for ( int l = 0 ; l < 20 ; l++ ) + texels [ l ] = NULL ; + + texels [ 0 ] = image ; + + int lev ; + + for ( lev = 0 ; (( xsize >> (lev+1) ) != 0 || + ( ysize >> (lev+1) ) != 0 ) ; lev++ ) + { + /* Suffix '1' is the higher level map, suffix '2' is the lower level. */ + + int l1 = lev ; + int l2 = lev+1 ; + int w1 = xsize >> l1 ; + int h1 = ysize >> l1 ; + int w2 = xsize >> l2 ; + int h2 = ysize >> l2 ; + + if ( w1 <= 0 ) w1 = 1 ; + if ( h1 <= 0 ) h1 = 1 ; + if ( w2 <= 0 ) w2 = 1 ; + if ( h2 <= 0 ) h2 = 1 ; + + texels [ l2 ] = new GLubyte [ w2 * h2 * zsize ] ; + + for ( int x2 = 0 ; x2 < w2 ; x2++ ) + for ( int y2 = 0 ; y2 < h2 ; y2++ ) + for ( int c = 0 ; c < zsize ; c++ ) + { + int x1 = x2 + x2 ; + int x1_1 = ( x1 + 1 ) % w1 ; + int y1 = y2 + y2 ; + int y1_1 = ( y1 + 1 ) % h1 ; + + int t1 = texels [ l1 ] [ (y1 * w1 + x1 ) * zsize + c ] ; + int t2 = texels [ l1 ] [ (y1_1 * w1 + x1 ) * zsize + c ] ; + int t3 = texels [ l1 ] [ (y1 * w1 + x1_1) * zsize + c ] ; + int t4 = texels [ l1 ] [ (y1_1 * w1 + x1_1) * zsize + c ] ; + + texels [ l2 ] [ (y2 * w2 + x2) * zsize + c ] = + ( t1 + t2 + t3 + t4 ) / 4 ; + } + } + + texels [ lev+1 ] = NULL ; + + if ( ! ((xsize & (xsize-1))==0) || + ! ((ysize & (ysize-1))==0) ) + { + ulSetError ( UL_FATAL, + "TXFloader: TXF Map is not a power-of-two in size!" ) ; + } + + glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ) ; + + int map_level = 0 ; + +#ifdef PROXY_TEXTURES_ARE_NOT_BROKEN + int ww ; + + do + { + glTexImage2D ( GL_PROXY_TEXTURE_2D, + map_level, zsize, xsize, ysize, FALSE /* Border */, + (zsize==1)?GL_LUMINANCE: + (zsize==2)?GL_LUMINANCE_ALPHA: + (zsize==3)?GL_RGB: + GL_RGBA, + GL_UNSIGNED_BYTE, NULL ) ; + + glGetTexLevelParameteriv ( GL_PROXY_TEXTURE_2D, 0,GL_TEXTURE_WIDTH, &ww ) ; + + if ( ww == 0 ) + { + delete [] texels [ 0 ] ; + xsize >>= 1 ; + ysize >>= 1 ; + + for ( int l = 0 ; texels [ l ] != NULL ; l++ ) + texels [ l ] = texels [ l+1 ] ; + + if ( xsize < 64 && ysize < 64 ) + { + ulSetError ( UL_FATAL, + "FNT: OpenGL will not accept a font texture?!?" ) ; + } + } + } while ( ww == 0 ) ; +#endif + + for ( int i = 0 ; texels [ i ] != NULL ; i++ ) + { + int w = xsize>>i ; + int h = ysize>>i ; + + if ( w <= 0 ) w = 1 ; + if ( h <= 0 ) h = 1 ; + + glTexImage2D ( GL_TEXTURE_2D, + map_level, zsize, w, h, FALSE /* Border */, + (zsize==1)?GL_LUMINANCE: + (zsize==2)?GL_LUMINANCE_ALPHA: + (zsize==3)?GL_RGB: + GL_RGBA, + GL_UNSIGNED_BYTE, (GLvoid *) texels[i] ) ; + map_level++ ; + delete [] texels [ i ] ; + } +} + + + +int fntTexFont::loadTXF ( const char *fname, GLenum mag, GLenum min ) +{ + if ( ! glIsValidContext () ) + { + ulSetError ( UL_FATAL, + "FNT font loader called without a valid OpenGL context."); + } + + FILE *fd ; + + if ( (fd = fopen ( fname, "rb" )) == NULL ) + { + ulSetError ( UL_WARNING, + "fntLoadTXF: Failed to open '%s' for reading.", fname ) ; + return FNT_FALSE ; + } + + _fntCurrImageFd = fd ; + + unsigned char magic [ 4 ] ; + + if ( (int)fread ( &magic, sizeof (unsigned int), 1, fd ) != 1 ) + { + ulSetError ( UL_WARNING, + "fntLoadTXF: '%s' an empty file!", fname ) ; + return FNT_FALSE ; + } + + if ( magic [ 0 ] != 0xFF || magic [ 1 ] != 't' || + magic [ 2 ] != 'x' || magic [ 3 ] != 'f' ) + { + ulSetError ( UL_WARNING, + "fntLoadTXF: '%s' is not a 'txf' font file.", fname ) ; + return FNT_FALSE ; + } + + _fntIsSwapped = FALSE ; + int endianness = _fnt_readInt () ; + + _fntIsSwapped = ( endianness != 0x12345678 ) ; + + int format = _fnt_readInt () ; + int tex_width = _fnt_readInt () ; + int tex_height = _fnt_readInt () ; + int max_height = _fnt_readInt () ; + _fnt_readInt () ; + int num_glyphs = _fnt_readInt () ; + + int w = tex_width ; + int h = tex_height ; + + float xstep = 0.5f / (float) w ; + float ystep = 0.5f / (float) h ; + + int i, j ; + + /* + Load the TXF_Glyph array + */ + + TXF_Glyph glyph ; + + for ( i = 0 ; i < num_glyphs ; i++ ) + { + glyph . ch = _fnt_readShort () ; + + glyph . w = _fnt_readByte () ; + glyph . h = _fnt_readByte () ; + glyph . x_off = _fnt_readByte () ; + glyph . y_off = _fnt_readByte () ; + glyph . step = _fnt_readByte () ; + glyph . unknown = _fnt_readByte () ; + glyph . x = _fnt_readShort () ; + glyph . y = _fnt_readShort () ; + + setGlyph ( (char) glyph.ch, + (float) glyph.step / (float) max_height, + (float) glyph.x / (float) w + xstep, + (float)( glyph.x + glyph.w ) / (float) w + xstep, + (float) glyph.y / (float) h + ystep, + (float)( glyph.y + glyph.h ) / (float) h + ystep, + (float) glyph.x_off / (float) max_height, + (float)( glyph.x_off + glyph.w ) / (float) max_height, + (float) glyph.y_off / (float) max_height, + (float)( glyph.y_off + glyph.h ) / (float) max_height ) ; + } + + exists [ ' ' ] = FALSE ; + + /* + Load the image part of the file + */ + + int ntexels = w * h ; + + unsigned char *teximage ; + unsigned char *texbitmap ; + + switch ( format ) + { + case FNT_BYTE_FORMAT: + { + unsigned char *orig = new unsigned char [ ntexels ] ; + + if ( (int)fread ( orig, 1, ntexels, fd ) != ntexels ) + { + ulSetError ( UL_WARNING, + "fntLoadTXF: Premature EOF in '%s'.", fname ) ; + return FNT_FALSE ; + } + + teximage = new unsigned char [ 2 * ntexels ] ; + + for ( i = 0 ; i < ntexels ; i++ ) + { + teximage [ i*2 ] = orig [ i ] ; + teximage [ i*2 + 1 ] = orig [ i ] ; + } + + delete [] orig ; + } + break ; + + case FNT_BITMAP_FORMAT: + { + int stride = (w + 7) >> 3; + + texbitmap = new unsigned char [ stride * h ] ; + + if ( (int)fread ( texbitmap, 1, stride * h, fd ) != stride * h ) + { + delete [] texbitmap ; + ulSetError ( UL_WARNING, + "fntLoadTXF: Premature EOF in '%s'.", fname ) ; + return FNT_FALSE ; + } + + teximage = new unsigned char [ 2 * ntexels ] ; + + for ( i = 0 ; i < 2 * ntexels ; i++ ) + teximage [ i ] = 0 ; + + for (i = 0; i < h; i++) + for (j = 0; j < w; j++) + if (texbitmap[i * stride + (j >> 3)] & (1 << (j & 7))) + { + teximage[(i * w + j) * 2 ] = 255; + teximage[(i * w + j) * 2 + 1] = 255; + } + + delete [] texbitmap ; + } + break ; + + default: + ulSetError ( UL_WARNING, + "fntLoadTXF: Unrecognised format type in '%s'.", fname ) ; + return FNT_FALSE ; + } + + fclose ( fd ) ; + + fixed_pitch = FALSE ; + +#ifdef GL_VERSION_1_1 + glGenTextures ( 1, & texture ) ; + glBindTexture ( GL_TEXTURE_2D, texture ) ; +#else + /* This is only useful on some ancient SGI hardware */ + glGenTexturesEXT ( 1, & texture ) ; + glBindTextureEXT ( GL_TEXTURE_2D, texture ) ; +#endif + + tex_make_mip_maps ( teximage, w, h, 2 ) ; + + glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ; + + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag ) ; + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min ) ; + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ) ; + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ) ; +#ifdef GL_VERSION_1_1 + glBindTexture ( GL_TEXTURE_2D, 0 ) ; +#else + glBindTextureEXT ( GL_TEXTURE_2D, 0 ) ; +#endif + + return FNT_TRUE ; +} + + diff --git a/src/js/Makefile.am b/src/js/Makefile.am new file mode 100644 index 0000000..df48950 --- /dev/null +++ b/src/js/Makefile.am @@ -0,0 +1,17 @@ +if BUILD_JS + +lib_LIBRARIES = libplibjs.a + +include_HEADERS = js.h + +libplibjs_a_SOURCES = js.cxx jsLinux.cxx jsLinuxOld.cxx jsMacOS.cxx \ + jsMacOSX.cxx jsWindows.cxx jsBSD.cxx \ + jsNone.cxx + +INCLUDES = -I$(top_srcdir)/src/util + +endif + +EXTRA_DIST = js.dsp + + diff --git a/src/js/README b/src/js/README new file mode 100644 index 0000000..99c9634 --- /dev/null +++ b/src/js/README @@ -0,0 +1,30 @@ + +Joystick interfaces are horribly non-portable. + +Using conditional compilation on a line-by-line basis +became FAR too complex after more than a couple of OS's +were supported so now there is on standard interface header: + + js.h + +...one set of common routines: + + js.cxx + + +...and a bunch of OS-specific code: + + + jsLinux.cxx + jsLinuxOld.cxx + jsWindows.cxx + jsBSD.cxx + jsMacOS.cxx + +...for OS's (eg IRIX and SOLARIS) without standard joystick +functionality, we add: + + jsNone.cxx + +...which safely returns error status with no buttons or axes provided. + diff --git a/src/js/js.cxx b/src/js/js.cxx new file mode 100644 index 0000000..6324e9f --- /dev/null +++ b/src/js/js.cxx @@ -0,0 +1,86 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + +*/ + +#include "js.h" + +float jsJoystick::fudge_axis ( float value, int axis ) const +{ + if ( value < center[axis] ) + { + float xx = ( value - center[ axis ] ) / + ( center [ axis ] - min [ axis ] ) ; + + if ( xx < -saturate [ axis ] ) + return -1.0f ; + + if ( xx > -dead_band [ axis ] ) + return 0.0f ; + + xx = ( xx + dead_band [ axis ] ) / + ( saturate [ axis ] - dead_band [ axis ] ) ; + + return ( xx < -1.0f ) ? -1.0f : xx ; + } + else + { + float xx = ( value - center [ axis ] ) / + ( max [ axis ] - center [ axis ] ) ; + + if ( xx > saturate [ axis ] ) + return 1.0f ; + + if ( xx < dead_band [ axis ] ) + return 0.0f ; + + xx = ( xx - dead_band [ axis ] ) / + ( saturate [ axis ] - dead_band [ axis ] ) ; + + return ( xx > 1.0f ) ? 1.0f : xx ; + } +} + + +void jsJoystick::read ( int *buttons, float *axes ) +{ + if ( error ) + { + if ( buttons ) + *buttons = 0 ; + + if ( axes ) + for ( int i = 0 ; i < num_axes ; i++ ) + axes[i] = 0.0f ; + + return ; + } + + float raw_axes [ _JS_MAX_AXES ] ; + + rawRead ( buttons, raw_axes ) ; + + if ( axes ) + for ( int i = 0 ; i < num_axes ; i++ ) + axes[i] = fudge_axis ( raw_axes[i], i ) ; +} + + + diff --git a/src/js/js.dsp b/src/js/js.dsp new file mode 100644 index 0000000..0d69e87 --- /dev/null +++ b/src/js/js.dsp @@ -0,0 +1,126 @@ +# Microsoft Developer Studio Project File - Name="js" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=js - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "js.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "js.mak" CFG="js - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "js - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "js - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "js - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\util" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy release\*.lib ..\..\*.* copy js.h ..\..\js.h +# End Special Build Tool + +!ELSEIF "$(CFG)" == "js - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\util" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\js_d.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy debug\*.lib ..\..\*.* copy js.h ..\..\js.h +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "js - Win32 Release" +# Name "js - Win32 Debug" +# Begin Source File + +SOURCE=.\js.cxx +# End Source File +# Begin Source File + +SOURCE=.\js.h +# End Source File +# Begin Source File + +SOURCE=.\jsBSD.cxx +# End Source File +# Begin Source File + +SOURCE=.\jsLinux.cxx +# End Source File +# Begin Source File + +SOURCE=.\jsMacOS.cxx +# End Source File +# Begin Source File + +SOURCE=.\jsMacOSX.cxx +# End Source File +# Begin Source File + +SOURCE=.\jsNone.cxx +# End Source File +# Begin Source File + +SOURCE=.\jsWindows.cxx +# End Source File +# End Target +# End Project diff --git a/src/js/js.h b/src/js/js.h new file mode 100644 index 0000000..2962b24 --- /dev/null +++ b/src/js/js.h @@ -0,0 +1,98 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: js.h 2067 2006-01-30 07:36:01Z bram $ +*/ + +#ifndef __INCLUDED_JS_H__ +#define __INCLUDED_JS_H__ 1 +#define JS_NEW + +#include "ul.h" + +#include +#include +#include // -dw- for memcpy + +#define _JS_MAX_AXES 16 +#define _JS_MAX_BUTTONS 32 +#define _JS_MAX_HATS 4 + +#define JS_TRUE 1 +#define JS_FALSE 0 + + +class jsJoystick +{ + int id ; +protected: + struct os_specific_s *os ; + friend struct os_specific_s ; + int error ; + char name [ 128 ] ; + int num_axes ; + int num_buttons ; + + float dead_band [ _JS_MAX_AXES ] ; + float saturate [ _JS_MAX_AXES ] ; + float center [ _JS_MAX_AXES ] ; + float max [ _JS_MAX_AXES ] ; + float min [ _JS_MAX_AXES ] ; + + void open () ; + void close () ; + + float fudge_axis ( float value, int axis ) const ; + +public: + + jsJoystick ( int ident = 0 ) ; + ~jsJoystick () { close () ; } + + const char* getName () const { return name ; } + int getNumAxes () const { return num_axes ; } + int getNumButtons () const { return num_buttons; } + int notWorking () const { return error ; } + void setError () { error = JS_TRUE ; } + + float getDeadBand ( int axis ) const { return dead_band [ axis ] ; } + void setDeadBand ( int axis, float db ) { dead_band [ axis ] = db ; } + + float getSaturation ( int axis ) const { return saturate [ axis ] ; } + void setSaturation ( int axis, float st ) { saturate [ axis ] = st ; } + + void setMinRange ( float *axes ) { memcpy ( min , axes, num_axes * sizeof(float) ) ; } + void setMaxRange ( float *axes ) { memcpy ( max , axes, num_axes * sizeof(float) ) ; } + void setCenter ( float *axes ) { memcpy ( center, axes, num_axes * sizeof(float) ) ; } + + void getMinRange ( float *axes ) const { memcpy ( axes, min , num_axes * sizeof(float) ) ; } + void getMaxRange ( float *axes ) const { memcpy ( axes, max , num_axes * sizeof(float) ) ; } + void getCenter ( float *axes ) const { memcpy ( axes, center, num_axes * sizeof(float) ) ; } + + void read ( int *buttons, float *axes ) ; + void rawRead ( int *buttons, float *axes ) ; + // bool SetForceFeedBack ( int axe, float force ); +} ; + +extern void jsInit () ; + +#endif + + diff --git a/src/js/jsBSD.cxx b/src/js/jsBSD.cxx new file mode 100644 index 0000000..5c510c4 --- /dev/null +++ b/src/js/jsBSD.cxx @@ -0,0 +1,522 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: jsBSD.cxx 2133 2008-07-18 14:32:22Z fayjf $ +*/ + +/* + * Inspired by the X-Mame USB HID joystick driver for NetBSD and + * FreeBSD by Krister Walfridsson . + * Incorporates the original analog joystick driver for BSD by + * Stephen Montgomery-Smith , with + * NetBSD mods courtesy of Rene Hexel. + * + * Bert Driehuis + * + * Notes: + * Hats are mapped to two axes for now. A cleaner implementation requires + * an API extension, and to be useful for my devious purposes, FlightGear + * would need to understand that. + */ + +#include "js.h" + +#if defined (UL_BSD) + +#if defined(__NetBSD__) || defined(__FreeBSD__) +#define HAVE_USB_JS 1 +#endif + +#include +#include +#include +#if defined(__FreeBSD__) +# include +#else +# include // For analog joysticks +#endif +#ifdef HAVE_USB_JS +#if defined(__NetBSD__) +#ifdef HAVE_USBHID_H +#include +#else +#include +#endif +#elif defined(__FreeBSD__) +extern "C" { +# if __FreeBSD_version < 500000 +# include +# else +# define HAVE_USBHID_H 1 +# include +# endif +} +#endif +#include +#include + +/* Compatibility with older usb.h revisions */ +#if !defined(USB_MAX_DEVNAMES) && defined(MAXDEVNAMES) +#define USB_MAX_DEVNAMES MAXDEVNAMES +#endif +#endif + +static int hatmap_x[9] = { 0, 0, 1, 1, 1, 0, -1, -1, -1 }; +static int hatmap_y[9] = { 0, 1, 1, 0, -1, -1, -1, 0, 1 }; +struct os_specific_s { + char fname [128 ]; + int fd; + int is_analog; + // The following structure members are specific to analog joysticks + struct joystick ajs; +#ifdef HAVE_USB_JS + // The following structure members are specific to USB joysticks + struct hid_item *hids; + int hid_dlen; + int hid_offset; + char *hid_data_buf; + int axes_usage [ _JS_MAX_AXES ] ; +#endif + // We keep button and axes state ourselves, as they might not be updated + // on every read of a USB device + int cache_buttons ; + float cache_axes [ _JS_MAX_AXES ] ; + float axes_minimum [ _JS_MAX_AXES ] ; + float axes_maximum [ _JS_MAX_AXES ] ; +}; + +// Idents lower than USB_IDENT_OFFSET are for analog joysticks. +#define USB_IDENT_OFFSET 2 + +#define USBDEV "/dev/usb" +#define UHIDDEV "/dev/uhid" +#define AJSDEV "/dev/joy" + +#ifdef HAVE_USB_JS +/* + * findusbdev (and its helper, walkusbdev) try to locate the full name + * of a USB device. If /dev/usbN isn't readable, we punt and return the + * uhidN device name. We warn the user of this situation once. + */ +static char * +walkusbdev(int f, char *dev, char *out, int outlen) +{ + struct usb_device_info di; + int i, a; + char *cp; + + for (a = 1; a < USB_MAX_DEVICES; a++) { + di.udi_addr = a; + if (ioctl(f, USB_DEVICEINFO, &di) != 0) + return NULL; + for (i = 0; i < USB_MAX_DEVNAMES; i++) + if (di.udi_devnames[i][0] && + strcmp(di.udi_devnames[i], dev) == 0) { + cp = new char[strlen(di.udi_vendor) + strlen(di.udi_product) + 2]; + strcpy(cp, di.udi_vendor); + strcat(cp, " "); + strcat(cp, di.udi_product); + strncpy(out, cp, outlen - 1); + out[outlen - 1] = 0; + delete cp; + return out; + } + } + return NULL; +} + +static int +findusbdev(char *name, char *out, int outlen) +{ + int i, f; + char buf[50]; + char *cp; + static int protection_warned = 0; + + for (i = 0; i < 16; i++) { + sprintf(buf, "%s%d", USBDEV, i); + f = open(buf, O_RDONLY); + if (f >= 0) { + cp = walkusbdev(f, name, out, outlen); + close(f); + if (cp) + return 1; + } else if (errno == EACCES) { + if (!protection_warned) { + fprintf(stderr, "Can't open %s for read!\n", + buf); + protection_warned = 1; + } + } + } + return 0; +} + +static int joy_initialize_hid(struct os_specific_s *os, + int *num_axes, int *num_buttons) +{ + int size, is_joystick; +#ifdef HAVE_USBHID_H + int report_id = 0; +#endif + struct hid_data *d; + struct hid_item h; + report_desc_t rd; + + if ((rd = hid_get_report_desc(os->fd)) == 0) + { + fprintf(stderr, "error: %s: %s", os->fname, strerror(errno)); + return FALSE; + } + + os->hids = NULL; + +#ifdef HAVE_USBHID_H + if (ioctl(os->fd, USB_GET_REPORT_ID, &report_id) < 0) + { + fprintf(stderr, "error: %s: %s", os->fname, strerror(errno)); + return FALSE; + } + + size = hid_report_size(rd, hid_input, report_id); +#else + size = hid_report_size(rd, 0, hid_input); +#endif + os->hid_data_buf = new char[size]; + os->hid_dlen = size; + + is_joystick = 0; +#ifdef HAVE_USBHID_H + d = hid_start_parse(rd, 1 << hid_input, report_id); +#else + d = hid_start_parse(rd, 1 << hid_input); +#endif + while (hid_get_item(d, &h)) + { + int usage, page, interesting_hid; + + page = HID_PAGE(h.usage); + usage = HID_USAGE(h.usage); + + /* This test is somewhat too simplistic, but this is how MicroSoft + * does, so I guess it works for all joysticks/game pads. */ + is_joystick = is_joystick || + (h.kind == hid_collection && + page == HUP_GENERIC_DESKTOP && + (usage == HUG_JOYSTICK || usage == HUG_GAME_PAD)); + + if (h.kind != hid_input) + continue; + + if (!is_joystick) + continue; + + interesting_hid = TRUE; + if (page == HUP_GENERIC_DESKTOP) + { + switch(usage) { + case HUG_X: + case HUG_RX: + case HUG_Y: + case HUG_RY: + case HUG_Z: + case HUG_RZ: + case HUG_SLIDER: + if (*num_axes < _JS_MAX_AXES) + { + os->axes_usage[*num_axes] = usage; + os->axes_minimum[*num_axes] = h.logical_minimum; + os->axes_maximum[*num_axes] = h.logical_maximum; + (*num_axes)++; + } + break; + case HUG_HAT_SWITCH: + if (*num_axes + 1 < _JS_MAX_AXES) // Allocate two axes for a hat + { + os->axes_usage[*num_axes] = usage; + (*num_axes)++; + os->axes_usage[*num_axes] = usage; + (*num_axes)++; + } + break; + default: + interesting_hid = FALSE; + } + } + else if (page == HUP_BUTTON) + { + interesting_hid = (usage > 0) && (usage <= _JS_MAX_BUTTONS); + + if (interesting_hid && usage - 1 > *num_buttons) + { + *num_buttons = usage - 1; + } + } + + if (interesting_hid) + { + h.next = os->hids; + os->hids = new struct hid_item; + *os->hids = h; + } + } + hid_end_parse(d); + + return (os->hids != NULL); +} +#endif + +void jsJoystick::open () +{ + char *cp; + + name [0] = '\0' ; + + for ( int i = 0 ; i < _JS_MAX_AXES ; i++ ) + os->cache_axes [ i ] = 0.0f ; + + os->cache_buttons = 0 ; + + os->fd = ::open ( os->fname, O_RDONLY | O_NONBLOCK) ; + + if (os->fd < 0 && errno == EACCES) + fprintf(stderr, "%s exists but is not readable by you\n", os->fname); + + error = ( os->fd < 0 ) ; + + if ( error ) + return ; + + num_axes = 0; + num_buttons = 0; + if ( os->is_analog ) + { + num_axes = 2 ; + num_buttons = 32 ; + FILE *joyfile ; + char joyfname [ 1024 ] ; + int noargs, in_no_axes ; + + float axes [ _JS_MAX_AXES ] ; + int buttons [ _JS_MAX_AXES ] ; + + rawRead ( buttons, axes ) ; + error = axes[0] < -1000000000.0f && axes[1] < -1000000000.0f ; + if ( error ) + return ; + + sprintf( joyfname, "%s/.joy%drc", ::getenv ( "HOME" ), id ) ; + + joyfile = fopen ( joyfname, "r" ) ; + error = ( joyfile == NULL ) ; + if ( error ) + { + ulSetError ( UL_WARNING, "unable to open calibration file %s (%s), joystick %i disabled (you can generate the calibration file with the plib-jscal utility)", + joyfname, strerror ( errno ), id + 1 ); + return ; + } + + noargs = fscanf ( joyfile, "%d%f%f%f%f%f%f", &in_no_axes, + &min [ 0 ], ¢er [ 0 ], &max [ 0 ], + &min [ 1 ], ¢er [ 1 ], &max [ 1 ] ) ; + error = noargs != 7 || in_no_axes != _JS_MAX_AXES ; + fclose ( joyfile ) ; + if ( error ) + return ; + + for ( int i = 0 ; i < _JS_MAX_AXES ; i++ ) + { + dead_band [ i ] = 0.0f ; + saturate [ i ] = 1.0f ; + } + + return; // End of analog code + } + +#ifdef HAVE_USB_JS + if ( !joy_initialize_hid(os, &num_axes, &num_buttons ) ) + { + ::close(os->fd); + error = 1; + return; + } + + cp = strrchr(os->fname, '/'); + if (cp) { + if (findusbdev(&cp[1], name, sizeof(name)) == 0) + strcpy(name, &cp[1]); + } + + if ( num_axes > _JS_MAX_AXES ) + num_axes = _JS_MAX_AXES ; + + for ( int i = 0 ; i < _JS_MAX_AXES ; i++ ) + { + if ( os->axes_usage [ i ] == HUG_HAT_SWITCH ) + { + max [ i ] = 1.0f ; + center [ i ] = 0.0f ; + min [ i ] = -1.0f ; + } + else + { + max [ i ] = os->axes_maximum [ i ]; + min [ i ] = os->axes_minimum [ i ]; + center [ i ] = (max [ i ] + min [ i ]) / 2; + } + dead_band [ i ] = 0.0f ; + saturate [ i ] = 1.0f ; + } +#endif +} + + + +void jsJoystick::close () +{ + if (os) { + if ( ! error ) + ::close ( os->fd ) ; +#ifdef HAVE_USB_JS + if (os->hids) + delete os->hids; + if (os->hid_data_buf) + delete os->hid_data_buf; +#endif + delete os; + } +} + + +jsJoystick::jsJoystick ( int ident ) +{ + id = ident ; + error = 0; + + os = new struct os_specific_s; + memset(os, 0, sizeof(struct os_specific_s)); + if (ident < USB_IDENT_OFFSET) + os->is_analog = 1; + if (os->is_analog) + sprintf(os->fname, "%s%d", AJSDEV, ident); + else + sprintf(os->fname, "%s%d", UHIDDEV, ident - USB_IDENT_OFFSET); + open () ; +} + + +void jsJoystick::rawRead ( int *buttons, float *axes ) +{ + int len, usage, page, d; + struct hid_item *h; + + if ( error ) + { + if ( buttons ) + *buttons = 0 ; + + if ( axes ) + for ( int i = 0 ; i < num_axes ; i++ ) + axes[i] = 1500.0f ; + + return ; + } + + if ( os->is_analog ) + { + int status = ::read ( os->fd, &os->ajs, sizeof(os->ajs) ); + if ( status != sizeof(os->ajs) ) { + perror ( os->fname ) ; + setError () ; + return ; + } + if ( buttons != NULL ) + *buttons = ( os->ajs.b1 ? 1 : 0 ) | ( os->ajs.b2 ? 2 : 0 ) ; + + if ( axes != NULL ) + { + if ( os->ajs.x >= -1000000000 ) + os->cache_axes[0] = os->ajs.x; + if ( os->ajs.y >= -1000000000 ) + os->cache_axes[1] = os->ajs.y; + + axes[0] = os->cache_axes[0]; + axes[1] = os->cache_axes[1]; + } + + return; + } + +#ifdef HAVE_USB_JS + while ((len = ::read(os->fd, os->hid_data_buf, os->hid_dlen)) == os->hid_dlen) + { + for (h = os->hids; h; h = h->next) + { + d = hid_get_data(os->hid_data_buf, h); + + page = HID_PAGE(h->usage); + usage = HID_USAGE(h->usage); + + if (page == HUP_GENERIC_DESKTOP) + { + for (int i = 0; i < num_axes; i++) + if (os->axes_usage[i] == usage) + { + if (usage == HUG_HAT_SWITCH) + { + if (d < 0 || d > 8) + d = 0; // safety + os->cache_axes[i] = (float)hatmap_x[d]; + os->cache_axes[i + 1] = (float)hatmap_y[d]; + } + else + { + os->cache_axes[i] = (float)d; + } + break; + } + } + else if (page == HUP_BUTTON) + { + if (usage > 0 && usage < _JS_MAX_BUTTONS + 1) + { + if (d) + os->cache_buttons |= (1 << usage - 1) ; + else + os->cache_buttons &= ~(1 << usage - 1) ; + } + } + } + } + if (len < 0 && errno != EAGAIN) + { + perror( os->fname ) ; + setError () ; + error = 1; + } + if ( buttons != NULL ) *buttons = os->cache_buttons ; + if ( axes != NULL ) + memcpy ( axes, os->cache_axes, sizeof(float) * num_axes ) ; +#endif +} + +void jsInit () {} + +#endif diff --git a/src/js/jsLinux.cxx b/src/js/jsLinux.cxx new file mode 100644 index 0000000..650f772 --- /dev/null +++ b/src/js/jsLinux.cxx @@ -0,0 +1,201 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: jsLinux.cxx 2017 2005-02-21 07:37:25Z bram $ +*/ + +#include "js.h" + +#if defined (UL_LINUX) + +#include + +#if defined(JS_VERSION) && JS_VERSION >= 0x010000 + +#include +#include +#include + +struct os_specific_s { + js_event js ; + int tmp_buttons ; + float tmp_axes [ _JS_MAX_AXES ] ; + char fname [ 128 ] ; + int fd ; +}; + +void jsInit () {} + +void jsJoystick::open () +{ + name [0] = '\0' ; + + for ( int i = 0 ; i < _JS_MAX_AXES ; i++ ) + os->tmp_axes [ i ] = 0.0f ; + + os->tmp_buttons = 0 ; + + os->fd = ::open ( os->fname, O_RDONLY ) ; + + error = ( os->fd < 0 ) ; + + if ( error ) + return ; + + /* + Set the correct number of axes for the linux driver + */ + + /* Melchior Franz's fixes for big-endian Linuxes since writing + * to the upper byte of an uninitialized word doesn't work. + * 9 April 2003 + */ + unsigned char u ; + ioctl ( os->fd, JSIOCGAXES , &u ) ; + num_axes = u ; + ioctl ( os->fd, JSIOCGBUTTONS, &u ) ; + num_buttons = u ; + ioctl ( os->fd, JSIOCGNAME ( sizeof(name) ), name ) ; + fcntl ( os->fd, F_SETFL , O_NONBLOCK ) ; + + int all_axes = num_axes; + if ( num_axes > _JS_MAX_AXES ) + num_axes = _JS_MAX_AXES ; + + // Remove any deadband value already done in the kernel. + // Since we have our own deadband management this is save to do so. + struct js_corr* corr = new js_corr[ all_axes ] ; + ioctl ( os->fd, JSIOCGCORR, corr ); + for ( int i = 0; i < num_axes ; ++i ) { + if ( corr[ i ] . type == JS_CORR_BROKEN ) { + int nodeadband = ( corr[ i ] . coef[ 0 ] + corr[ i ] . coef[ 1 ] ) / 2 ; + corr[ i ] . coef[ 0 ] = nodeadband ; + corr[ i ] . coef[ 1 ] = nodeadband ; + } + } + ioctl ( os->fd, JSIOCSCORR, corr ); + delete [] corr; + + for ( int i = 0 ; i < _JS_MAX_AXES ; i++ ) + { + max [ i ] = 32767.0f ; + center [ i ] = 0.0f ; + min [ i ] = -32767.0f ; + dead_band [ i ] = 0.0f ; + saturate [ i ] = 1.0f ; + } +} + + + +void jsJoystick::close () +{ + if ( ! error ) + ::close ( os->fd ) ; + delete os; +} + + +jsJoystick::jsJoystick ( int ident ) +{ + id = ident ; + os = new struct os_specific_s; + + sprintf ( os->fname, "/dev/input/js%d", ident ) ; + + if ( access ( os->fname, F_OK ) != 0 ) + sprintf ( os->fname, "/dev/js%d", ident ) ; + + open () ; +} + + +void jsJoystick::rawRead ( int *buttons, float *axes ) +{ + if ( error ) + { + if ( buttons ) + *buttons = 0 ; + + if ( axes ) + for ( int i = 0 ; i < num_axes ; i++ ) + axes[i] = 1500.0f ; + + return ; + } + + while (1) + { + int status = ::read ( os->fd, &(os->js), sizeof(js_event) ) ; + + if ( status != sizeof(js_event) ) + { + /* use the old values */ + + if ( buttons != NULL ) *buttons = os->tmp_buttons ; + if ( axes != NULL ) + memcpy ( axes, os->tmp_axes, sizeof(float) * num_axes ) ; + + if ( errno == EAGAIN ) + return ; + + perror( os->fname ) ; + setError () ; + return ; + } + + switch ( os->js.type & ~JS_EVENT_INIT ) + { + case JS_EVENT_BUTTON : + if ( os->js.value == 0 ) /* clear the flag */ + os->tmp_buttons &= ~(1 << os->js.number) ; + else + os->tmp_buttons |= (1 << os->js.number) ; + break ; + + case JS_EVENT_AXIS: + if ( os->js.number < num_axes ) + { + os->tmp_axes [ os->js.number ] = (float) os->js.value ; + + if ( axes ) + memcpy ( axes, os->tmp_axes, sizeof(float) * num_axes ) ; + } + break ; + + default: + ulSetError ( UL_WARNING, "PLIB_JS: Unrecognised /dev/js return!?!" ) ; + + /* use the old values */ + + if ( buttons != NULL ) *buttons = os->tmp_buttons ; + if ( axes != NULL ) + memcpy ( axes, os->tmp_axes, sizeof(float) * num_axes ) ; + + return ; + } + + if ( buttons != NULL ) + *buttons = os->tmp_buttons ; + } +} + +#endif +#endif diff --git a/src/js/jsLinuxOld.cxx b/src/js/jsLinuxOld.cxx new file mode 100644 index 0000000..961dd43 --- /dev/null +++ b/src/js/jsLinuxOld.cxx @@ -0,0 +1,146 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: jsLinuxOld.cxx 2039 2005-07-16 17:27:51Z fayjf $ +*/ + +#include "js.h" + +#if defined (UL_LINUX) + +#include + +#if !defined(JS_VERSION) || JS_VERSION < 0x010000 + +#include +#include + +struct os_specific_s { + JS_DATA_TYPE js ; + char fname [ 128 ] ; + int fd ; +}; + +void jsJoystick::open () +{ + name [0] = '\0' ; + + num_axes = 2 ; /* Default for older Linux systems. */ + num_buttons = 32 ; + + os->fd = ::open ( os->fname, O_RDONLY ) ; + + error = ( os->fd < 0 ) ; + + if ( error ) + return ; + + /* + The Linux driver seems to return 512 for all axes + when no stick is present - but there is a chance + that could happen by accident - so it's gotta happen + on both axes for at least 100 attempts. + */ + + int counter = 0 ; + + do + { + rawRead ( NULL, center ) ; + counter++ ; + } while ( ! error && + counter < 100 && + center[0] == 512.0f && + center[1] == 512.0f ) ; + + if ( counter >= 100 ) + setError() ; + + + for ( int i = 0 ; i < _JS_MAX_AXES ; i++ ) + { + max [ i ] = center [ i ] * 2.0f ; + min [ i ] = 0.0f ; + dead_band [ i ] = 0.0f ; + saturate [ i ] = 1.0f ; + } +} + + + +void jsJoystick::close () +{ + if ( ! error ) + ::close ( os->fd ) ; + delete os; +} + + +jsJoystick::jsJoystick ( int ident ) +{ + id = ident ; + os = new struct os_specific_s; + + sprintf ( os->fname, "/dev/input/js%d", ident ) ; + + if ( access ( os->fname, F_OK ) != 0 ) + sprintf ( os->fname, "/dev/js%d", ident ) ; + + open () ; +} + + +void jsJoystick::rawRead ( int *buttons, float *axes ) +{ + if ( error ) + { + if ( buttons ) + *buttons = 0 ; + + if ( axes ) + for ( int i = 0 ; i < num_axes ; i++ ) + axes[i] = 1500.0f ; + + return ; + } + + int status = ::read ( os->fd, &(os->js), JS_RETURN ) ; + + if ( status != JS_RETURN ) + { + perror ( os->fname ) ; + setError () ; + return ; + } + + if ( buttons != NULL ) + *buttons = os->js.buttons ; + + if ( axes != NULL ) + { + axes[0] = (float) os->js.x ; + axes[1] = (float) os->js.y ; + } +} + +void jsInit() {} + +#endif +#endif diff --git a/src/js/jsMacOS.cxx b/src/js/jsMacOS.cxx new file mode 100644 index 0000000..c1b4418 --- /dev/null +++ b/src/js/jsMacOS.cxx @@ -0,0 +1,210 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: jsMacOS.cxx 1960 2004-09-21 11:45:55Z smokydiamond $ +*/ + +#include "js.h" + +#if defined (UL_MACINTOSH) + +#include + +//#define _JS_MAX_AXES_MAC 9 +#define isp_num_axis 9 +#define isp_num_needs 41 + +struct os_specific_s { + ISpElementReference isp_elem [ isp_num_needs ] ; + ISpNeed isp_needs [ isp_num_needs ] ; +}; + +void jsJoystick::open () +{ + name [0] = '\0' ; + + /* + FIXME: get joystick name in Mac + */ + + OSStatus err ; + + err = ISpStartup () ; + + if ( err == noErr ) + { +#define ISP_CHECK_ERR(x) if ( x != noErr ) { setError () ; return ; } + + setError () ; + + // initialize the needs structure + ISpNeed temp_isp_needs[isp_num_needs] = + { + { "\pX-Axis", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + { "\pY-Axis", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + { "\pZ-Axis", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + { "\pR-Axis", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + { "\pAxis 4", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + { "\pAxis 5", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + { "\pAxis 6", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + { "\pAxis 7", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + { "\pAxis 8", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, + + { "\pButton 0", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 1", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 2", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 3", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 4", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 5", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 6", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 7", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 8", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 9", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 10", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 11", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 12", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 13", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 14", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 15", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 16", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 17", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 18", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 19", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 20", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 21", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 22", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 23", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 24", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 25", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 26", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 27", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 28", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 29", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 30", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + { "\pButton 31", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, + } ; + + memcpy ( os->isp_needs, temp_isp_needs, sizeof(temp_isp_needs) ) ; + + + // next two calls allow keyboard and mouse to emulate other input + // devices (gamepads, joysticks, etc) + + /* + err = ISpDevices_ActivateClass ( kISpDeviceClass_Keyboard ) ; + ISP_CHECK_ERR(err) + + + err = ISpDevices_ActivateClass ( kISpDeviceClass_Mouse ) ; + ISP_CHECK_ERR(err) + */ + + err = ISpElement_NewVirtualFromNeeds ( isp_num_needs, os->isp_needs, os->isp_elem, 0 ) ; + ISP_CHECK_ERR(err) + + err = ISpInit ( isp_num_needs, os->isp_needs, os->isp_elem, 'PLIB', nil, 0, 128, 0 ) ; + ISP_CHECK_ERR(err) + + num_buttons = isp_num_needs - isp_num_axis ; + num_axes = isp_num_axis ; + + for ( int i = 0 ; i < num_axes ; i++ ) + { + dead_band [ i ] = 0 ; + saturate [ i ] = 1 ; + center [ i ] = kISpAxisMiddle ; + max [ i ] = kISpAxisMaximum ; + min [ i ] = kISpAxisMinimum ; + } + + error = false ; + } + else + { + setError () ; + num_buttons = num_axes = 0 ; + } +} + + +void jsJoystick::close () +{ + ISpSuspend () ; + ISpStop () ; + ISpShutdown () ; + delete os; +} + + +jsJoystick::jsJoystick ( int ident ) +{ + id = ident ; + os = new struct os_specific_s; + // sprintf ( fname, "/dev/js%d", ident ) ; /* FIXME */ + open () ; +} + + +void jsJoystick::rawRead ( int *buttons, float *axes ) +{ + if ( error ) + { + if ( buttons ) + *buttons = 0 ; + + if ( axes ) + for ( int i = 0 ; i < num_axes ; i++ ) + axes[i] = 1500.0f ; + + return ; + } + + int i ; + int err ; + UInt32 state ; + + if ( buttons != NULL ) + { + *buttons = 0; + + for ( i = 0 ; i < num_buttons ; i++ ) + { + err = ISpElement_GetSimpleState ( os->isp_elem [ i + isp_num_axis ], &state) ; + ISP_CHECK_ERR(err) + + *buttons |= state << i ; + } + } + + if ( axes != NULL ) + { + for ( i = 0 ; i < num_axes ; i++ ) + { + err = ISpElement_GetSimpleState ( os->isp_elem [ i ], &state ) ; + ISP_CHECK_ERR(err) + + axes [i] = (float) state ; + } + } +} + +void jsInit() {} + +#endif diff --git a/src/js/jsMacOSX.cxx b/src/js/jsMacOSX.cxx new file mode 100644 index 0000000..0325d80 --- /dev/null +++ b/src/js/jsMacOSX.cxx @@ -0,0 +1,466 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: jsMacOSX.cxx 2165 2011-01-22 22:56:03Z fayjf $ +*/ + +#include "js.h" + +#if defined (UL_MAC_OSX) + +#include +#include +#include +#include +#include +#include +#include + +#ifdef MACOS_10_0_4 +# include +#else +/* The header was moved here in MacOS X 10.1 */ +# include +#endif + +static const int kNumDevices = 32; +static int numDevices = -1; +static io_object_t ioDevices[kNumDevices]; + +static int NS_hat[8] = {1, 1, 0, -1, -1, -1, 0, 1}; +static int WE_hat[8] = {0, 1, 1, 1, 0, -1, -1, -1}; + +struct os_specific_s { + IOHIDDeviceInterface ** hidDev; + IOHIDElementCookie buttonCookies[41]; + IOHIDElementCookie axisCookies[_JS_MAX_AXES]; + IOHIDElementCookie hatCookies[_JS_MAX_HATS]; + int num_hats; + long hat_min[_JS_MAX_HATS]; + long hat_max[_JS_MAX_HATS]; + + void enumerateElements(jsJoystick* joy, CFTypeRef element); + static void elementEnumerator( const void *element, void* vjs); + /// callback for CFArrayApply + void parseElement(jsJoystick* joy, CFDictionaryRef element); + void addAxisElement(jsJoystick* joy, CFDictionaryRef axis); + void addButtonElement(jsJoystick* joy, CFDictionaryRef button); + void addHatElement(jsJoystick* joy, CFDictionaryRef hat); +}; + +static void findDevices(mach_port_t); +static CFDictionaryRef getCFProperties(io_object_t); + + +void jsInit() +{ + if (numDevices < 0) { + numDevices = 0; + + mach_port_t masterPort; + IOReturn rv = IOMasterPort(bootstrap_port, &masterPort); + if (rv != kIOReturnSuccess) { + ulSetError(UL_WARNING, "error getting master Mach port"); + return; + } + + findDevices(masterPort); + } +} + +/** open the IOKit connection, enumerate all the HID devices, add their +interface references to the static array. We then use the array index +as the device number when we come to open() the joystick. */ +static void findDevices(mach_port_t masterPort) +{ + CFMutableDictionaryRef hidMatch = NULL; + IOReturn rv = kIOReturnSuccess; + io_iterator_t hidIterator; + + // build a dictionary matching HID devices + hidMatch = IOServiceMatching(kIOHIDDeviceKey); + + rv = IOServiceGetMatchingServices(masterPort, hidMatch, &hidIterator); + if (rv != kIOReturnSuccess || !hidIterator) { + ulSetError(UL_WARNING, "no joystick (HID) devices found"); + return; + } + + // iterate + io_object_t ioDev; + + while ((ioDev = IOIteratorNext(hidIterator))) { + // filter out keyboard and mouse devices + CFDictionaryRef properties = getCFProperties(ioDev); + long usage, page; + + CFTypeRef refPage = CFDictionaryGetValue (properties, CFSTR(kIOHIDPrimaryUsagePageKey)); + CFTypeRef refUsage = CFDictionaryGetValue (properties, CFSTR(kIOHIDPrimaryUsageKey)); + CFNumberGetValue((CFNumberRef) refUsage, kCFNumberLongType, &usage); + CFNumberGetValue((CFNumberRef) refPage, kCFNumberLongType, &page); + + // keep only joystick devices + if ( (page == kHIDPage_GenericDesktop) && + ((usage == kHIDUsage_GD_Joystick) || + (usage == kHIDUsage_GD_GamePad) + // || (usage == kHIDUsage_GD_MultiAxisController) + // || (usage == kHIDUsage_GD_Hatswitch) + ) + ) + { + // add it to the array + ioDevices[numDevices++] = ioDev; + } + } + + IOObjectRelease(hidIterator); +} + + +jsJoystick::jsJoystick(int ident) : + id(ident), + os(NULL), + error(JS_FALSE), + num_axes(0), + num_buttons(0) +{ + if (ident >= numDevices) { + setError(); + return; + } + + os = new struct os_specific_s; + os->num_hats = 0; + + // get the name now too + CFDictionaryRef properties = getCFProperties(ioDevices[id]); + CFTypeRef ref = CFDictionaryGetValue (properties, CFSTR(kIOHIDProductKey)); + if (!ref) + ref = CFDictionaryGetValue (properties, CFSTR("USB Product Name")); + + if (!ref || !CFStringGetCString ((CFStringRef) ref, name, 128, CFStringGetSystemEncoding ())) { + ulSetError(UL_WARNING, "error getting device name"); + name[0] = '\0'; + } + //printf("Joystick name: %s \n", name); + open(); +} + +void jsJoystick::open() +{ +#if 0 // test already done in the constructor + if (id >= numDevices) { + ulSetError(UL_WARNING, "device index out of range in jsJoystick::open"); + return; + } +#endif + + // create device interface + IOReturn rv; + SInt32 score; + IOCFPlugInInterface **plugin; + + rv = IOCreatePlugInInterfaceForService(ioDevices[id], + kIOHIDDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, + &plugin, &score); + + if (rv != kIOReturnSuccess) { + ulSetError(UL_WARNING, "error creting plugin for io device"); + return; + } + + HRESULT pluginResult = (*plugin)->QueryInterface(plugin, + CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (LPVOID*)&(os->hidDev) ); + + if (pluginResult != S_OK) + ulSetError(UL_WARNING, "QI-ing IO plugin to HID Device interface failed"); + + (*plugin)->Release(plugin); // don't leak a ref + if (os->hidDev == NULL) return; + + // store the interface in this instance + rv = (*(os->hidDev))->open(os->hidDev, 0); + if (rv != kIOReturnSuccess) { + ulSetError(UL_WARNING, "error opening device interface"); + return; + } + + CFDictionaryRef props = getCFProperties(ioDevices[id]); + + // recursively enumerate all the bits (buttons, axes, hats, ...) + CFTypeRef topLevelElement = + CFDictionaryGetValue (props, CFSTR(kIOHIDElementKey)); + os->enumerateElements(this, topLevelElement); + CFRelease(props); + + // for hats to be implemented as axes: must be the last axes: + for (int h = 0; h<2*os->num_hats; h++) + { + int index = num_axes++; + dead_band [ index ] = 0.0f ; + saturate [ index ] = 1.0f ; + center [ index ] = 0.0f; + max [ index ] = 1.0f; + min [ index ] = -1.0f; + } +} + +CFDictionaryRef getCFProperties(io_object_t ioDev) +{ + IOReturn rv; + CFMutableDictionaryRef cfProperties; + +#if 0 + // comment copied from darwin/SDL_sysjoystick.c + /* Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also + * get dictionary for usb properties: step up two levels and get CF dictionary for USB properties + */ + + io_registry_entry_t parent1, parent2; + + rv = IORegistryEntryGetParentEntry (ioDev, kIOServicePlane, &parent1); + if (rv != kIOReturnSuccess) { + ulSetError(UL_WARNING, "error getting device entry parent"); + return NULL; + } + + rv = IORegistryEntryGetParentEntry (parent1, kIOServicePlane, &parent2); + if (rv != kIOReturnSuccess) { + ulSetError(UL_WARNING, "error getting device entry parent 2"); + return NULL; + } + +#endif + rv = IORegistryEntryCreateCFProperties( ioDev /*parent2*/, + &cfProperties, kCFAllocatorDefault, kNilOptions); + if (rv != kIOReturnSuccess || !cfProperties) { + ulSetError(UL_WARNING, "error getting device properties"); + return NULL; + } + + return cfProperties; +} + +void jsJoystick::close() +{ + if (!os) + return; + if (os->hidDev != NULL) (*(os->hidDev))->close(os->hidDev); + if (os) delete os; +} + +/** element enumerator function : pass NULL for top-level*/ +void os_specific_s::enumerateElements(jsJoystick* joy, CFTypeRef element) +{ + assert(CFGetTypeID(element) == CFArrayGetTypeID()); + + CFRange range = {0, CFArrayGetCount ((CFArrayRef)element)}; + CFArrayApplyFunction((CFArrayRef) element, range, + &elementEnumerator, joy); +} + +void os_specific_s::elementEnumerator( const void *element, void* vjs) +{ + if (CFGetTypeID((CFTypeRef) element) != CFDictionaryGetTypeID()) { + ulSetError(UL_WARNING, "element enumerator passed non-dictionary value"); + return; + } + + static_cast(vjs)-> + os->parseElement( static_cast(vjs), (CFDictionaryRef) element); +} + +void os_specific_s::parseElement(jsJoystick* joy, CFDictionaryRef element) +{ + CFTypeRef refPage = CFDictionaryGetValue ((CFDictionaryRef) element, CFSTR(kIOHIDElementUsagePageKey)); + CFTypeRef refUsage = CFDictionaryGetValue ((CFDictionaryRef) element, CFSTR(kIOHIDElementUsageKey)); + + long type, page, usage; + + CFNumberGetValue((CFNumberRef) + CFDictionaryGetValue ((CFDictionaryRef) element, CFSTR(kIOHIDElementTypeKey)), + kCFNumberLongType, &type); + + switch (type) { + case kIOHIDElementTypeInput_Misc: + case kIOHIDElementTypeInput_Axis: + case kIOHIDElementTypeInput_Button: + //printf("got input element..."); + CFNumberGetValue((CFNumberRef) refUsage, kCFNumberLongType, &usage); + CFNumberGetValue((CFNumberRef) refPage, kCFNumberLongType, &page); + + if (page == kHIDPage_GenericDesktop) { + switch (usage) /* look at usage to determine function */ + { + case kHIDUsage_GD_X: + case kHIDUsage_GD_Y: + case kHIDUsage_GD_Z: + case kHIDUsage_GD_Rx: + case kHIDUsage_GD_Ry: + case kHIDUsage_GD_Rz: + case kHIDUsage_GD_Slider: // for throttle / trim controls + case kHIDUsage_GD_Dial: + //printf(" axis\n"); + /*joy->os->*/addAxisElement(joy, (CFDictionaryRef) element); + break; + + case kHIDUsage_GD_Hatswitch: + //printf(" hat\n"); + /*joy->os->*/addHatElement(joy, (CFDictionaryRef) element); + break; + + default: + ulSetError(UL_WARNING, "input type element has weird usage (%lx)\n", usage); + break; + } + } else if (page == kHIDPage_Simulation) { + switch (usage) /* look at usage to determine function */ + { + case kHIDUsage_Sim_Rudder: + case kHIDUsage_Sim_Throttle: + //printf(" axis\n"); + /*joy->os->*/addAxisElement(joy, (CFDictionaryRef) element); + break; + default: + ulSetError(UL_WARNING, "Simulation page input type element has weird usage (%lx)\n", usage); + } + } else if (page == kHIDPage_Button) { + //printf(" button\n"); + /*joy->os->*/addButtonElement(joy, (CFDictionaryRef) element); + } else if (page == kHIDPage_PID) { + ulSetError(UL_WARNING, "Force feedback and related data ignored\n", usage); + } else + ulSetError(UL_WARNING, "input type element has weird usage (%lx)\n", usage); + break; + + case kIOHIDElementTypeCollection: + /*joy->os->*/enumerateElements(joy, + CFDictionaryGetValue(element, CFSTR(kIOHIDElementKey)) + ); + break; + + default: + break; + } +} + +void os_specific_s::addAxisElement(jsJoystick* joy, CFDictionaryRef axis) +{ + long cookie, lmin, lmax; + CFNumberGetValue ((CFNumberRef) + CFDictionaryGetValue (axis, CFSTR(kIOHIDElementCookieKey)), + kCFNumberLongType, &cookie); + + int index = joy->num_axes++; + + /*joy->os->*/axisCookies[index] = (IOHIDElementCookie) cookie; + + CFNumberGetValue ((CFNumberRef) + CFDictionaryGetValue (axis, CFSTR(kIOHIDElementMinKey)), + kCFNumberLongType, &lmin); + + CFNumberGetValue ((CFNumberRef) + CFDictionaryGetValue (axis, CFSTR(kIOHIDElementMaxKey)), + kCFNumberLongType, &lmax); + + joy->min[index] = lmin; + joy->max[index] = lmax; + joy->dead_band[index] = 0.0; + joy->saturate[index] = 1.0; + joy->center[index] = (lmax - lmin) * 0.5 + lmin; +} + +void os_specific_s::addButtonElement(jsJoystick* joy, CFDictionaryRef button) +{ + long cookie; + CFNumberGetValue ((CFNumberRef) + CFDictionaryGetValue (button, CFSTR(kIOHIDElementCookieKey)), + kCFNumberLongType, &cookie); + + /*joy->os->*/buttonCookies[joy->num_buttons++] = (IOHIDElementCookie) cookie; + // anything else for buttons? +} + +void os_specific_s::addHatElement(jsJoystick* joy, CFDictionaryRef hat) +{ + long cookie, lmin, lmax; + CFNumberGetValue ((CFNumberRef) + CFDictionaryGetValue (hat, CFSTR(kIOHIDElementCookieKey)), + kCFNumberLongType, &cookie); + + int index = /*joy->*/num_hats++; + + /*joy->os->*/hatCookies[index] = (IOHIDElementCookie) cookie; + + CFNumberGetValue ((CFNumberRef) + CFDictionaryGetValue (hat, CFSTR(kIOHIDElementMinKey)), + kCFNumberLongType, &lmin); + + CFNumberGetValue ((CFNumberRef) + CFDictionaryGetValue (hat, CFSTR(kIOHIDElementMaxKey)), + kCFNumberLongType, &lmax); + + hat_min[index] = lmin; + hat_max[index] = lmax; + // do we map hats to axes or buttons? + // axes; there is room for that: Buttons are limited to 32. + // (a joystick with 2 hats will use 16 buttons!) +} + +void jsJoystick::rawRead(int *buttons, float *axes) +{ + if (buttons) + *buttons = 0; + + IOHIDEventStruct hidEvent; + + for (int b=0; bhidDev))->getElementValue(os->hidDev, os->buttonCookies[b], &hidEvent); + if (hidEvent.value && buttons) + *buttons |= 1 << b; + } + + // real axes: + int real_num_axes = num_axes - 2*os->num_hats; + for (int a=0; ahidDev))->getElementValue(os->hidDev, os->axisCookies[a], &hidEvent); + axes[a] = hidEvent.value; + } + + // hats: + for (int h=0; h < os->num_hats; ++h) { + (*(os->hidDev))->getElementValue(os->hidDev, os->hatCookies[h], &hidEvent); + long result = ( hidEvent.value - os->hat_min[h] ) * 8; + result /= ( os->hat_max[h] - os->hat_min[h] + 1 ); + if ( (result>=0) && (result<8) ) + { + axes[h+real_num_axes+1] = NS_hat[result]; + axes[h+real_num_axes] = WE_hat[result]; + } + else + { + axes[h+real_num_axes] = 0; + axes[h+real_num_axes+1] = 0; + } + } +} + +#endif diff --git a/src/js/jsNone.cxx b/src/js/jsNone.cxx new file mode 100644 index 0000000..300bdbc --- /dev/null +++ b/src/js/jsNone.cxx @@ -0,0 +1,59 @@ +/* + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: jsNone.cxx 1960 2004-09-21 11:45:55Z smokydiamond $ +*/ + +#include "js.h" + +#if defined(UL_IRIX) || defined(UL_SOLARIS) || defined (UL_HPUX) + +struct os_specific_s ; + + +void jsJoystick::open () +{ + error = TRUE ; + num_axes = num_buttons = 0 ; +} + + +void jsJoystick::close () +{ + error = TRUE ; +} + + +jsJoystick::jsJoystick ( int ident ) +{ + error = TRUE ; + num_axes = num_buttons = 0 ; + os = NULL; +} + + +void jsJoystick::rawRead ( int *buttons, float *axes ) +{ + if ( buttons != NULL ) *buttons = 0 ; +} + +void jsInit () {} + +#endif + diff --git a/src/js/jsWindows.cxx b/src/js/jsWindows.cxx new file mode 100644 index 0000000..33896ec --- /dev/null +++ b/src/js/jsWindows.cxx @@ -0,0 +1,273 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: jsWindows.cxx 2164 2011-01-22 22:47:30Z fayjf $ +*/ + +#include "js.h" + +#if defined (UL_WIN32) + +#define _JS_MAX_AXES_WIN 8 /* X,Y,Z,R,U,V,POV_X,POV_Y */ + +struct os_specific_s { + JOYCAPS jsCaps ; + JOYINFOEX js ; + UINT js_id ; + static bool getOEMProductName ( jsJoystick* joy, char *buf, int buf_sz ) ; +}; + + + +// Inspired by +// http://msdn.microsoft.com/archive/en-us/dnargame/html/msdn_sidewind3d.asp + +bool os_specific_s::getOEMProductName ( jsJoystick* joy, char *buf, int buf_sz ) +{ + if ( joy->error ) return false ; + + union + { + char key [ 256 ] ; + char value [ 256 ] ; + } ; + char OEMKey [ 256 ] ; + + HKEY hKey ; + DWORD dwcb ; + LONG lr ; + int hkcu = 0; + + // Open .. MediaResources\CurrentJoystickSettings + sprintf ( key, "%s\\%s\\%s", + REGSTR_PATH_JOYCONFIG, joy->os->jsCaps.szRegKey, + REGSTR_KEY_JOYCURR ) ; + + lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, key, 0, KEY_QUERY_VALUE, &hKey) ; + + if ( lr != ERROR_SUCCESS ) + { + hkcu = 1; + // XP/Vista/7 seem to have moved it to "current user" + lr = RegOpenKeyEx ( HKEY_CURRENT_USER, key, 0, KEY_QUERY_VALUE, &hKey) ; + if ( lr != ERROR_SUCCESS ) return false ; + } + + // Get OEM Key name + dwcb = sizeof(OEMKey) ; + + // JOYSTICKID1-16 is zero-based; registry entries for VJOYD are 1-based. + sprintf ( value, "Joystick%d%s", joy->os->js_id + 1, REGSTR_VAL_JOYOEMNAME ) ; + + lr = RegQueryValueEx ( hKey, value, 0, 0, (LPBYTE) OEMKey, &dwcb); + RegCloseKey ( hKey ) ; + + if ( lr != ERROR_SUCCESS ) return false ; + + // Open OEM Key from ...MediaProperties + sprintf ( key, "%s\\%s", REGSTR_PATH_JOYOEM, OEMKey ) ; + + if (!hkcu) + lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, key, 0, KEY_QUERY_VALUE, &hKey) ; + else + lr = RegOpenKeyEx ( HKEY_CURRENT_USER, key, 0, KEY_QUERY_VALUE, &hKey) ; + if ( lr != ERROR_SUCCESS ) + { + return false ; + } + + // Get OEM Name + dwcb = buf_sz ; + + lr = RegQueryValueEx ( hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, (LPBYTE) buf, + &dwcb ) ; + RegCloseKey ( hKey ) ; + + if ( lr != ERROR_SUCCESS ) return false ; + + return true ; +} + + +void jsJoystick::open () +{ + name [0] = '\0' ; + + os->js . dwFlags = JOY_RETURNALL ; + os->js . dwSize = sizeof ( os->js ) ; + + memset ( &(os->jsCaps), 0, sizeof(os->jsCaps) ) ; + + error = ( joyGetDevCaps( os->js_id, &(os->jsCaps), sizeof(os->jsCaps) ) + != JOYERR_NOERROR ) ; + num_buttons = os->jsCaps.wNumButtons ; + if ( os->jsCaps.wNumAxes == 0 ) + { + num_axes = 0 ; + setError () ; + } + else + { + // Device name from jsCaps is often "Microsoft PC-joystick driver", + // at least for USB. Try to get the real name from the registry. + if ( ! os->getOEMProductName ( this, name, sizeof(name) ) ) + { + ulSetError ( UL_WARNING, + "JS: Failed to read joystick name from registry" ) ; + + strncpy ( name, os->jsCaps.szPname, sizeof(name) ) ; + } + + // Windows joystick drivers may provide any combination of + // X,Y,Z,R,U,V,POV - not necessarily the first n of these. + if ( os->jsCaps.wCaps & JOYCAPS_HASPOV ) + { + num_axes = _JS_MAX_AXES_WIN ; + min [ 7 ] = -1.0 ; max [ 7 ] = 1.0 ; // POV Y + min [ 6 ] = -1.0 ; max [ 6 ] = 1.0 ; // POV X + } + else + num_axes = 6 ; + + min [ 5 ] = (float) os->jsCaps.wVmin ; max [ 5 ] = (float) os->jsCaps.wVmax ; + min [ 4 ] = (float) os->jsCaps.wUmin ; max [ 4 ] = (float) os->jsCaps.wUmax ; + min [ 3 ] = (float) os->jsCaps.wRmin ; max [ 3 ] = (float) os->jsCaps.wRmax ; + min [ 2 ] = (float) os->jsCaps.wZmin ; max [ 2 ] = (float) os->jsCaps.wZmax ; + min [ 1 ] = (float) os->jsCaps.wYmin ; max [ 1 ] = (float) os->jsCaps.wYmax ; + min [ 0 ] = (float) os->jsCaps.wXmin ; max [ 0 ] = (float) os->jsCaps.wXmax ; + } + + for ( int i = 0 ; i < num_axes ; i++ ) + { + center [ i ] = ( max[i] + min[i] ) / 2.0f ; + dead_band [ i ] = 0.0f ; + saturate [ i ] = 1.0f ; + } +} + + +void jsJoystick::close () +{ + delete os; +} + + + +jsJoystick::jsJoystick ( int ident ) +{ + id = ident ; + os = new struct os_specific_s; + + if (ident >= 0 && ident < (int)joyGetNumDevs()) { + os->js_id = JOYSTICKID1 + ident; + open(); + } + else { + num_axes = 0; + setError(); + } +} + + + +void jsJoystick::rawRead ( int *buttons, float *axes ) +{ + if ( error ) + { + if ( buttons ) + *buttons = 0 ; + + if ( axes ) + for ( int i = 0 ; i < num_axes ; i++ ) + axes[i] = 1500.0f ; + + return ; + } + + MMRESULT status = joyGetPosEx ( os->js_id, &(os->js) ) ; + + if ( status != JOYERR_NOERROR ) + { + setError() ; + return ; + } + + if ( buttons != NULL ) + *buttons = (int) os->js.dwButtons ; + + if ( axes != NULL ) + { + /* WARNING - Fall through case clauses!! */ + + switch ( num_axes ) + { + case 8: + // Generate two POV axes from the POV hat angle. + // Low 16 bits of js.dwPOV gives heading (clockwise from ahead) in + // hundredths of a degree, or 0xFFFF when idle. + + if ( ( os->js.dwPOV & 0xFFFF ) == 0xFFFF ) + { + axes [ 6 ] = 0.0 ; + axes [ 7 ] = 0.0 ; + } + else + { + // This is the contentious bit: how to convert angle to X/Y. + // wk: I know of no define for PI that we could use here: + // SG_PI would pull in sg, M_PI is undefined for MSVC + // But the accuracy of the value of PI is very unimportant at + // this point. + + float s = (float) sin ( ( os->js.dwPOV & 0xFFFF ) * ( 0.01 * 3.1415926535f / 180 ) ) ; + float c = (float) cos ( ( os->js.dwPOV & 0xFFFF ) * ( 0.01 * 3.1415926535f / 180 ) ) ; + + // Convert to coordinates on a square so that North-East + // is (1,1) not (.7,.7), etc. + // s and c cannot both be zero so we won't divide by zero. + if ( fabs ( s ) < fabs ( c ) ) + { + axes [ 6 ] = ( c < 0.0 ) ? -s/c : s/c ; + axes [ 7 ] = ( c < 0.0 ) ? -1.0f : 1.0f ; + } + else + { + axes [ 6 ] = ( s < 0.0 ) ? -1.0f : 1.0f ; + axes [ 7 ] = ( s < 0.0 ) ? -c/s : c/s ; + } + } + + case 6: axes[5] = (float) os->js . dwVpos ; + case 5: axes[4] = (float) os->js . dwUpos ; + case 4: axes[3] = (float) os->js . dwRpos ; + case 3: axes[2] = (float) os->js . dwZpos ; + case 2: axes[1] = (float) os->js . dwYpos ; + case 1: axes[0] = (float) os->js . dwXpos ; + break; + + default: + ulSetError ( UL_WARNING, "PLIB_JS: Wrong num_axes. Joystick input is now invalid" ) ; + } + } +} + +void jsInit() {} + +#endif diff --git a/src/net/Makefile.am b/src/net/Makefile.am new file mode 100644 index 0000000..48de5c7 --- /dev/null +++ b/src/net/Makefile.am @@ -0,0 +1,16 @@ +if BUILD_NET + +lib_LIBRARIES = libplibnet.a + +include_HEADERS = netBuffer.h netChannel.h netChat.h netMessage.h \ + netMonitor.h netSocket.h net.h + +libplibnet_a_SOURCES = netBuffer.cxx netChannel.cxx netChat.cxx \ + netMessage.cxx netMonitor.cxx netSocket.cxx + +INCLUDES = -I$(top_srcdir)/src/util + +endif + +EXTRA_DIST = net.dsp + diff --git a/src/net/README b/src/net/README new file mode 100644 index 0000000..6382629 --- /dev/null +++ b/src/net/README @@ -0,0 +1,47 @@ +PLIB Network Library +------------------- + +DESCRIPTION: + +This is a C++ library for making networked games. +It includes event-driven channels, support for +buffering and pipelining, a monitor server for remote +telnet admin, and binary messages. + +HISTORY + +Initial work by Dave McClurg +This library is based on from a high-performance +internet server architecture for Python called Medusa. + http://www.nightmare.com/medusa/medusa.html +Added binary messages and PLIB naming conventions + +LICENSING: + +This library is distributed with PLIB under the GNU LGPL. + + +MEDUSA COPYRIGHT: + +--- +Copyright 1996 by Sam Rushing + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that copyright notice and this permission +notice appear in supporting documentation, and that the name of Sam +Rushing not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN +NO EVENT SHALL SAM RUSHING BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +--- diff --git a/src/net/net.dsp b/src/net/net.dsp new file mode 100644 index 0000000..256d54d --- /dev/null +++ b/src/net/net.dsp @@ -0,0 +1,144 @@ +# Microsoft Developer Studio Project File - Name="net" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=net - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "net.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "net.mak" CFG="net - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "net - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "net - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "net - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\util" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy release\*.lib ..\..\*.* copy net.h ..\..\net.h copy netBuffer.h ..\..\netBuffer.h copy netChannel.h ..\..\netChannel.h copy netChat.h ..\..\netChat.h copy netMessage.h ..\..\netMessage.h copy netMonitor.h ..\..\netMonitor.h copy netSocket.h ..\..\netSocket.h +# End Special Build Tool + +!ELSEIF "$(CFG)" == "net - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\util" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\net_d.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy debug\*.lib ..\..\*.* copy net.h ..\..\net.h copy netBuffer.h ..\..\netBuffer.h copy netChannel.h ..\..\netChannel.h copy netChat.h ..\..\netChat.h copy netMessage.h ..\..\netMessage.h copy netMonitor.h ..\..\netMonitor.h copy netSocket.h ..\..\netSocket.h +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "net - Win32 Release" +# Name "net - Win32 Debug" +# Begin Source File + +SOURCE=.\netBuffer.cxx +# End Source File +# Begin Source File + +SOURCE=.\netBuffer.h +# End Source File +# Begin Source File + +SOURCE=.\netChannel.cxx +# End Source File +# Begin Source File + +SOURCE=.\netChannel.h +# End Source File +# Begin Source File + +SOURCE=.\netChat.cxx +# End Source File +# Begin Source File + +SOURCE=.\netChat.h +# End Source File +# Begin Source File + +SOURCE=.\netMessage.cxx +# End Source File +# Begin Source File + +SOURCE=.\netMessage.h +# End Source File +# Begin Source File + +SOURCE=.\netMonitor.cxx +# End Source File +# Begin Source File + +SOURCE=.\netMonitor.h +# End Source File +# Begin Source File + +SOURCE=.\netSocket.cxx +# End Source File +# Begin Source File + +SOURCE=.\netSocket.h +# End Source File +# End Target +# End Project diff --git a/src/net/net.h b/src/net/net.h new file mode 100644 index 0000000..e7b0c90 --- /dev/null +++ b/src/net/net.h @@ -0,0 +1,12 @@ +#ifndef __PLIB_NET_H__ +#define __PLIB_NET_H__ 1 + +#include +#include +#include +#include +#include +#include + +#endif + diff --git a/src/net/netBuffer.cxx b/src/net/netBuffer.cxx new file mode 100644 index 0000000..01db94a --- /dev/null +++ b/src/net/netBuffer.cxx @@ -0,0 +1,69 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: netBuffer.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + +#include "netBuffer.h" + +void +netBufferChannel::handleRead (void) +{ + int max_read = in_buffer.getMaxLength() - in_buffer.getLength() ; + if (max_read) + { + char* data = in_buffer.getData() + in_buffer.getLength() ; + int num_read = recv (data, max_read) ; + if (num_read > 0) + { + in_buffer.append (num_read) ; + //ulSetError ( UL_DEBUG, "netBufferChannel: %d read", num_read ) ; + } + } + if (in_buffer.getLength()) + { + handleBufferRead (in_buffer); + } +} + +void +netBufferChannel::handleWrite (void) +{ + if (out_buffer.getLength()) + { + if (isConnected()) + { + int length = out_buffer.getLength() ; + if (length>512) + length=512; + int num_sent = netChannel::send ( + out_buffer.getData(), length); + if (num_sent > 0) + { + out_buffer.remove (0, num_sent); + //ulSetError ( UL_DEBUG, "netBufferChannel: %d sent", num_sent ) ; + } + } + } + else if (should_close) + { + close(); + } +} diff --git a/src/net/netBuffer.h b/src/net/netBuffer.h new file mode 100644 index 0000000..c5ff59b --- /dev/null +++ b/src/net/netBuffer.h @@ -0,0 +1,234 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: netBuffer.h 1901 2004-03-21 18:19:11Z sjbaker $ +*/ + +/**** +* NAME +* netBuffer - network buffer class +* +* DESCRIPTION +* Clients and servers built on top of netBufferChannel +* automatically support pipelining. +* +* Pipelining refers to a protocol capability. Normally, +* a conversation with a server has a back-and-forth +* quality to it. The client sends a command, and +* waits for the response. If a client needs to send +* many commands over a high-latency connection, +* waiting for each response can take a long time. +* +* For example, when sending a mail message to many recipients +* with SMTP, the client will send a series of RCPT commands, one +* for each recipient. For each of these commands, the server will +* send back a reply indicating whether the mailbox specified is +* valid. If you want to send a message to several hundred recipients, +* this can be rather tedious if the round-trip time for each command +* is long. You'd like to be able to send a bunch of RCPT commands +* in one batch, and then count off the responses to them as they come. +* +* I have a favorite visual when explaining the advantages of +* pipelining. Imagine each request to the server is a boxcar on a train. +* The client is in Los Angeles, and the server is in New York. +* Pipelining lets you hook all your cars in one long chain; send +* them to New York, where they are filled and sent back to you. +* Without pipelining you have to send one car at a time. +* +* Not all protocols allow pipelining. Not all servers support it; +* Sendmail, for example, does not support pipelining because it tends +* to fork unpredictably, leaving buffered data in a questionable state. +* A recent extension to the SMTP protocol allows a server to specify +* whether it supports pipelining. HTTP/1.1 explicitly requires that +* a server support pipelining. +* +* NOTES +* When a user passes in a buffer object, it belongs to +* the user. When the library gives a buffer to the user, +* the user should copy it. +* +* AUTHORS +* Sam Rushing - original version for Medusa +* Dave McClurg - modified for use in PLIB +* +* CREATION DATE +* Dec-2000 +* +****/ + +#ifndef NET_BUFFER_H +#define NET_BUFFER_H + +#include "netChannel.h" + + +// =========================================================================== +// netName +// =========================================================================== + +enum { NET_MAX_NAME = 31 } ; +//eg. char name [ NET_MAX_NAME+1 ] ; + + +inline char* netCopyName ( char* dst, const char* src ) +{ + if ( src != NULL ) + { + strncpy ( dst, src, NET_MAX_NAME ) ; + dst [ NET_MAX_NAME ] = 0 ; + } + else + *dst = 0 ; + return dst ; +} + + +// =========================================================================== +// netBuffer +// =========================================================================== + +class netBuffer +{ +protected: + int length ; + int max_length ; + char* data ; + +public: + netBuffer ( int _max_length ) + { + length = 0 ; + max_length = _max_length ; + data = new char [ max_length+1 ] ; //for null terminator + } + + ~netBuffer () + { + delete[] data ; + } + + int getLength() const { return length ; } + int getMaxLength() const { return max_length ; } + + /* + ** getData() returns a pointer to the data + ** Note: a zero (0) byte is appended for convenience + ** but the data may have internal zero (0) bytes already + */ + char* getData() { data [length] = 0 ; return data ; } + const char* getData() const { ((char*)data) [length] = 0 ; return data ; } + + void remove () + { + length = 0 ; + } + + void remove (int pos, int n) + { + assert (pos>=0 && pos=0 && pos next_channel ) + { + if (ch == this) + { + ch = ch -> next_channel ; + if ( prev != NULL ) + prev -> next_channel = ch ; + else + channels = ch ; + next_channel = 0 ; + break; + } + prev = ch ; + } +} + +void +netChannel::setHandle (int handle, bool is_connected) +{ + close () ; + netSocket::setHandle ( handle ) ; + connected = is_connected ; + //if ( connected ) this->handleConnect(); + closed = false ; +} + +bool +netChannel::open (void) +{ + close(); + if (netSocket::open(true)) { + closed = false ; + setBlocking ( false ) ; + return true ; + } + return false ; +} + +int +netChannel::listen ( int backlog ) +{ + accepting = true ; + return netSocket::listen ( backlog ) ; +} + +int +netChannel::connect ( const char* host, int port ) +{ + int result = netSocket::connect ( host, port ) ; + if (result == 0) { + connected = true ; + //this->handleConnect(); + return 0; + } else if (isNonBlockingError ()) { + return 0; + } else { + // some other error condition + this->handleError (result); + close(); + return -1; + } +} + +int +netChannel::send (const void * buffer, int size, int flags) +{ + int result = netSocket::send (buffer, size, flags); + + if (result == (int)size) { + // everything was sent + write_blocked = false ; + return result; + } else if (result >= 0) { + // not all of it was sent, but no error + write_blocked = true ; + return result; + } else if (isNonBlockingError ()) { + write_blocked = true ; + return 0; + } else { + this->handleError (result); + close(); + return -1; + } + +} + +int +netChannel::recv (void * buffer, int size, int flags) +{ + int result = netSocket::recv (buffer, size, flags); + + if (result > 0) { + return result; + } else if (result == 0) { + close(); + return 0; + } else if (isNonBlockingError ()) { + return 0; + } else { + this->handleError (result); + close(); + return -1; + } +} + +void +netChannel::close (void) +{ + if ( !closed ) + { + this->handleClose(); + + closed = true ; + connected = false ; + accepting = false ; + write_blocked = false ; + } + + netSocket::close () ; +} + +void +netChannel::handleReadEvent (void) +{ + if (accepting) { + if (!connected) { + connected = true ; + //this->handleConnect(); + } + this->handleAccept(); + } else if (!connected) { + connected = true ; + //this->handleConnect(); + this->handleRead(); + } else { + this->handleRead(); + } +} + +void +netChannel::handleWriteEvent (void) +{ + if (!connected) { + connected = true ; + //this->handleConnect(); + } + write_blocked = false ; + this->handleWrite(); +} + +bool +netChannel::poll (unsigned int timeout) +{ + if (!channels) + return false ; + + enum { MAX_SOCKETS = 256 } ; + netSocket* reads [ MAX_SOCKETS+1 ] ; + netSocket* writes [ MAX_SOCKETS+1 ] ; + netSocket* deletes [ MAX_SOCKETS+1 ] ; + int nreads = 0 ; + int nwrites = 0 ; + int ndeletes = 0 ; + int nopen = 0 ; + netChannel* ch; + for ( ch = channels; ch != NULL; ch = ch -> next_channel ) + { + if ( ch -> should_delete ) + { + assert(ndeletes closed ) + { + nopen++ ; + if (ch -> readable()) { + assert(nreads writable()) { + assert(nwrites closed ) + ch -> handleReadEvent(); + } + + for ( i=0; writes[i]; i++ ) + { + ch = (netChannel*)writes[i]; + if ( ! ch -> closed ) + ch -> handleWriteEvent(); + } + + return true ; +} + +void +netChannel::loop (unsigned int timeout) +{ + while ( poll (timeout) ) ; +} + diff --git a/src/net/netChannel.h b/src/net/netChannel.h new file mode 100644 index 0000000..8da5e1e --- /dev/null +++ b/src/net/netChannel.h @@ -0,0 +1,116 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: netChannel.h 1899 2004-03-21 17:41:07Z sjbaker $ +*/ + +/**** +* NAME +* netChannel - network channel class +* +* DESCRIPTION +* netChannel is adds event-handling to the low-level +* netSocket class. Otherwise, it can be treated as +* a normal non-blocking socket object. +* +* The direct interface between the netPoll() loop and +* the channel object are the handleReadEvent and +* handleWriteEvent methods. These are called +* whenever a channel object 'fires' that event. +* +* The firing of these low-level events can tell us whether +* certain higher-level events have taken place, depending on +* the timing and state of the connection. +* +* AUTHORS +* Sam Rushing - original version for Medusa +* Dave McClurg - modified for use in PLIB +* +* CREATION DATE +* Dec-2000 +* +****/ + +#ifndef NET_CHANNEL_H +#define NET_CHANNEL_H + +#include "netSocket.h" + +class netChannel : public netSocket +{ + bool closed, connected, accepting, write_blocked, should_delete ; + netChannel* next_channel ; + + friend bool netPoll (unsigned int timeout); + +public: + + netChannel () ; + virtual ~netChannel () ; + + void setHandle (int s, bool is_connected = true); + bool isConnected () const { return connected; } + bool isClosed () const { return closed; } + void shouldDelete () { should_delete = true ; } + + // -------------------------------------------------- + // socket methods + // -------------------------------------------------- + + bool open ( void ) ; + void close ( void ) ; + int listen ( int backlog ) ; + int connect ( const char* host, int port ) ; + int send ( const void * buf, int size, int flags = 0 ) ; + int recv ( void * buf, int size, int flags = 0 ) ; + + // poll() eligibility predicates + virtual bool readable (void) { return (connected || accepting); } + virtual bool writable (void) { return (!connected || write_blocked); } + + // -------------------------------------------------- + // event handlers + // -------------------------------------------------- + + void handleReadEvent (void); + void handleWriteEvent (void); + + // These are meant to be overridden. + virtual void handleClose (void) { + //ulSetError(UL_WARNING,"Network: %d: unhandled close",getHandle()); + } + virtual void handleRead (void) { + ulSetError(UL_WARNING,"Network: %d: unhandled read",getHandle()); + } + virtual void handleWrite (void) { + ulSetError(UL_WARNING,"Network: %d: unhandled write",getHandle()); + } + virtual void handleAccept (void) { + ulSetError(UL_WARNING,"Network: %d: unhandled accept",getHandle()); + } + virtual void handleError (int error) { + ulSetError(UL_WARNING,"Network: %d: errno: %s(%d)",getHandle(),strerror(errno),errno); + } + + static bool poll (unsigned int timeout = 0 ) ; + static void loop (unsigned int timeout = 0 ) ; +}; + +#endif // NET_CHANNEL_H diff --git a/src/net/netChat.cxx b/src/net/netChat.cxx new file mode 100644 index 0000000..865407b --- /dev/null +++ b/src/net/netChat.cxx @@ -0,0 +1,125 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: netChat.cxx 2117 2007-09-13 23:21:09Z fayjf $ +*/ + +#include "netChat.h" + +void +netChat::setTerminator (const char* t) +{ + if (terminator) delete[] terminator; + terminator = ulStrDup(t); +} + +const char* +netChat::getTerminator (void) +{ + return terminator; +} + +// return the size of the largest prefix of needle at the end +// of haystack + +#define MAX(a,b) (((a)>(b))?(a):(b)) + +static int +find_prefix_at_end (const netBuffer& haystack, const char* needle) +{ + const char* hd = haystack.getData(); + int hl = haystack.getLength(); + int nl = strlen(needle); + + for (int i = MAX (nl-hl, 0); i < nl; i++) { + //if (haystack.compare (needle, hl-(nl-i), nl-i) == 0) { + if (memcmp(needle, &hd[hl-(nl-i)], nl-i) == 0) { + return (nl-i); + } + } + return 0; +} + +static int +find_terminator (const netBuffer& haystack, const char* needle) +{ + if (needle && *needle) + { + const char* data = haystack.getData(); + const char* ptr = strstr(data,needle); + if (ptr != NULL) + return(ptr-data); + } + return -1; +} + + +void +netChat::handleBufferRead (netBuffer& in_buffer) +{ + // Continue to search for terminator in in_buffer, + // while calling collect_incoming_data. The while loop is + // necessary because we might read several data+terminator combos + // with a single recv(). + + while (in_buffer.getLength()) { + + // special case where we're not using a terminator + if (terminator == 0 || *terminator == 0) { + collectIncomingData (in_buffer.getData(),in_buffer.getLength()); + in_buffer.remove (); + return; + } + + int terminator_len = strlen(terminator); + + int index = find_terminator ( in_buffer, terminator ) ; + + // 3 cases: + // 1) end of buffer matches terminator exactly: + // collect data, transition + // 2) end of buffer matches some prefix: + // collect data to the prefix + // 3) end of buffer does not match any prefix: + // collect data + + if (index != -1) { + // we found the terminator + collectIncomingData ( in_buffer.getData(), index ) ; + in_buffer.remove (0, index + terminator_len); + foundTerminator(); + } else { + // check for a prefix of the terminator + int num = find_prefix_at_end (in_buffer, terminator); + if (num) { + int bl = in_buffer.getLength(); + // we found a prefix, collect up to the prefix + collectIncomingData ( in_buffer.getData(), bl - num ) ; + in_buffer.remove (0, bl - num); + break; + } else { + // no prefix, collect it all + collectIncomingData (in_buffer.getData(), in_buffer.getLength()); + in_buffer.remove(); + } + } + } +} + diff --git a/src/net/netChat.h b/src/net/netChat.h new file mode 100644 index 0000000..db56e47 --- /dev/null +++ b/src/net/netChat.h @@ -0,0 +1,86 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: netChat.h 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + +/**** +* NAME +* netChat - network chat class +* +* DESCRIPTION +* This class adds support for 'chat' style protocols - +* where one side sends a 'command', and the other sends +* a response (examples would be the common internet +* protocols - smtp, nntp, ftp, etc..). +* +* The handle_buffer_read() method looks at the input +* stream for the current 'terminator' (usually '\r\n' +* for single-line responses, '\r\n.\r\n' for multi-line +* output), calling found_terminator() on its receipt. +* +* EXAMPLE +* Say you build an nntp client using this class. +* At the start of the connection, you'll have +* terminator set to '\r\n', in order to process +* the single-line greeting. Just before issuing a +* 'LIST' command you'll set it to '\r\n.\r\n'. +* The output of the LIST command will be accumulated +* (using your own 'collect_incoming_data' method) +* up to the terminator, and then control will be +* returned to you - by calling your found_terminator() +* +* AUTHORS +* Sam Rushing - original version for Medusa +* Dave McClurg - modified for use in PLIB +* +* CREATION DATE +* Dec-2000 +* +****/ + +#ifndef NET_CHAT_H +#define NET_CHAT_H + +#include "netBuffer.h" + +class netChat : public netBufferChannel +{ + char* terminator; + + virtual void handleBufferRead (netBuffer& buffer) ; + +public: + + netChat () : terminator (0) {} + + void setTerminator (const char* t); + const char* getTerminator (void); + + bool push (const char* s) + { + return bufferSend ( s, strlen(s) ) ; + } + + virtual void collectIncomingData (const char* s, int n) {} + virtual void foundTerminator (void) {} +}; + +#endif // NET_CHAT_H diff --git a/src/net/netMessage.cxx b/src/net/netMessage.cxx new file mode 100644 index 0000000..7bff3af --- /dev/null +++ b/src/net/netMessage.cxx @@ -0,0 +1,50 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: netMessage.cxx 1899 2004-03-21 17:41:07Z sjbaker $ +*/ + +#include "netMessage.h" + + +void +netMessageChannel::handleBufferRead (netBuffer& in_buffer) +{ + int n = in_buffer.getLength () ; + while ( n >= 2 ) + { + unsigned short msg_len = *( (unsigned short*)in_buffer.getData() ) ; + if ( n >= msg_len ) + { + //we have a complete message; handle it + netMessage msg(in_buffer.getData(),msg_len); + in_buffer.remove(0,msg_len); + handleMessage ( msg ); + + //ulSetError ( UL_DEBUG, "netMessageChannel: %d read", msg_len ) ; + n -= msg_len ; + } + else + { + //ulSetError ( UL_DEBUG, "netMessageChannel: %d waiting", n ) ; + break ; + } + } +} diff --git a/src/net/netMessage.h b/src/net/netMessage.h new file mode 100644 index 0000000..57a4a89 --- /dev/null +++ b/src/net/netMessage.h @@ -0,0 +1,294 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: netMessage.h 2112 2006-12-12 18:45:28Z fayjf $ +*/ + +/**** +* NAME +* netMessage - message buffer and channel classes +* +* DESCRIPTION +* messages are a binary format for sending buffers over a channel. +* message headers contain a type field and length. +* +* AUTHOR +* Dave McClurg +* +* CREATION DATE +* Dec-2000 +****/ + +#ifndef __NET_MESSAGE__ +#define __NET_MESSAGE__ + + +#include "netBuffer.h" + +// ntohs() etc prototypes +#ifdef UL_MSVC +#include +#else +#include +#endif + +#ifdef __FreeBSD__ +#include +#endif + + +class netGuid //Globally Unique IDentifier +{ +public: + unsigned char data [ 16 ] ; + + netGuid () {} + + netGuid ( unsigned int l, + unsigned short w1, unsigned short w2, + unsigned char b1, unsigned char b2, + unsigned char b3, unsigned char b4, + unsigned char b5, unsigned char b6, + unsigned char b7, unsigned char b8 ) + { + //store in network format (big-endian) + + data[ 0] = (unsigned char)(l>>24) ; + data[ 1] = (unsigned char)(l>>16) ; + data[ 2] = (unsigned char)(l>> 8) ; + data[ 3] = (unsigned char)(l ) ; + data[ 4] = (unsigned char)(w1>>8) ; + data[ 5] = (unsigned char)(w1 ) ; + data[ 6] = (unsigned char)(w2>>8) ; + data[ 7] = (unsigned char)(w2 ) ; + + data[ 8] = b1 ; + data[ 9] = b2 ; + data[10] = b3 ; + data[11] = b4 ; + data[12] = b5 ; + data[13] = b6 ; + data[14] = b7 ; + data[15] = b8 ; + } + + bool operator ==( const netGuid& guid ) const + { + return memcmp ( data, guid.data, sizeof(data) ) == 0 ; + } + + bool operator !=( const netGuid& guid ) const + { + return memcmp ( data, guid.data, sizeof(data) ) != 0 ; + } +} ; + + +class netMessage : public netBuffer +{ + int pos ; + + void seek ( int new_pos ) const + { + if ( new_pos < 0 ) + new_pos = 0 ; + else + if ( new_pos > length ) + new_pos = length ; + + //logical const-ness + + ((netMessage*)this) -> pos = new_pos ; + } + + void skip ( int off ) const + { + seek(pos+off); + } + +public: + + // incoming message; header is already there + netMessage ( const char* s, int n ) : netBuffer(n) + { + assert ( n >= 5 ) ; + append(s,n); + pos = 5 ; // seek past header + } + + // outgoing message + netMessage ( int type, int to_id, int from_id=0, int n=256 ) : netBuffer(n) + { + // output header + putw ( 0 ) ; //msg_len + putbyte ( type ) ; + putbyte ( to_id ) ; + putbyte ( from_id ) ; + } + + int getType () const { return ( (unsigned char*)data )[ 2 ] ; } + int getToID () const { return ( (unsigned char*)data )[ 3 ] ; } + int getFromID () const { return ( (unsigned char*)data )[ 4 ] ; } + void setFromID ( int from_id ) { ( (unsigned char*)data )[ 4 ] = (unsigned char)from_id; } + + void geta ( void* a, int n ) const + { + assert (pos>=0 && pos=0 && pospos++; + if (ch==0) + break; + } + *dst = 0 ; + } + void puts ( const char* s ) + { + puta(s,strlen(s)+1); + } + + void print ( FILE *fd = stderr ) const + { + fprintf ( fd, "netMessage: %p, length=%d\n", this, length ) ; + fprintf ( fd, " header (type,to,from) = (%d,%d,%d)\n", + getType(), getToID(), getFromID() ) ; + fprintf ( fd, " data = " ) ; + for ( int i=0; i active = 0 ; + } +} ; + + +// for now, we ignore any telnet option stuff sent to +// us, and we process the backspace key ourselves. +// gee, it would be fun to write a full-blown line-editing +// environment, etc... + +static void clean_line (char* line) +{ + char* dst = line ; + for ( char* src = line ; *src ; src ++ ) + { + char ch = *src ; + if (ch==8 || ch==127) + { + // backspace + if (dst != line) + dst -- ; + } + else if (ch<127) + { + *dst++ = *src ; + } + } + *dst = 0 ; +} + + +netMonitorChannel::netMonitorChannel ( netMonitorServer* _server ) : buffer(512) +{ + server = _server ; + setTerminator("\r\n"); + + if ( server -> password && server -> password [0] != 0 ) + { + authorized = false ; + push ("Enter password: ") ; + } + else + { + authorized = true ; + push ( netFormat("Connected to \"%s\"... Welcome!\r\n", server -> name ) ) ; + prompt(); + } +} + + +void netMonitorChannel::prompt () +{ + push ( server -> prompt ) ; +} + + +void netMonitorChannel::collectIncomingData (const char* s, int n) +{ + if ( !buffer.append(s,n) ) + { + // denial of service. + push ("BCNU\r\n"); + closeWhenDone(); + } +} + +void netMonitorChannel::foundTerminator (void) +{ + char* line = buffer.getData(); + clean_line ( line ) ; + + if (!authorized) + { + if (strcmp(line,server -> password) == 0) + { + authorized = true ; + push ( netFormat("Connected to \"%s\"... Welcome!\r\n",server -> name) ) ; + prompt () ; + } + else + { + close(); + } + } + else if (*line == 0) + { + prompt(); + } + else if (*line == 4 || strcmp(line,"exit") == 0) + { + push ("BCNU\r\n"); //Be seein' you + closeWhenDone(); + } + else + { + if ( server -> cmdfunc ) + { + server -> cmdfunc ( line ) ; + } + else + { + ulSetError(UL_DEBUG,"echo: %s",line); + + push(line); + push(getTerminator()); + } + + prompt(); + } + buffer.remove(); +} + + +void netMonitorServer::handleAccept (void) +{ + if ( !active ) + { + netAddress addr ; + int s = accept ( &addr ) ; + + ulSetError(UL_DEBUG, "%d: Client %s:%d connected",s,addr.getHost(),addr.getPort()); + + active = new netMonitorChannel ( this ) ; + active -> setHandle (s); + } +} + + +bool netMonitorServer::push (const char* s) +{ + if ( active ) + return active -> push ( s ) ; + return false ; +} diff --git a/src/net/netMonitor.h b/src/net/netMonitor.h new file mode 100644 index 0000000..d3cd6f5 --- /dev/null +++ b/src/net/netMonitor.h @@ -0,0 +1,106 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: netMonitor.h 1899 2004-03-21 17:41:07Z sjbaker $ +*/ + +/**** +* NAME +* netMonitor - network monitor server +* +* DESCRIPTION +* netMonitor is a telnet command port with +* password authorization. It can be paired +* with and used to remotely admin another server. +* +* AUTHORS +* Sam Rushing - original version for Medusa +* Dave McClurg - modified for use in PLIB +* +* CREATION DATE +* Dec-2000 +* +****/ + +#ifndef NET_MONITOR_H +#define NET_MONITOR_H + +#include "netChat.h" + + +class netMonitorServer : private netChannel +{ + char* name ; + char* password ; + char* prompt ; + void (*cmdfunc)(const char*) ; + class netMonitorChannel* active ; + + friend class netMonitorChannel ; + + virtual bool writable (void) { return false ; } + virtual void handleAccept (void) ; + +public: + + netMonitorServer( const char* _name, int port ) + { + name = ulStrDup(_name); + password = ulStrDup("") ; + prompt = ulStrDup(">>> "); + cmdfunc = 0 ; + active = 0 ; + + open () ; + bind ("", port); + listen (1); + + ulSetError(UL_DEBUG, "Monitor \"%s\" started on port %d",name,port); + } + + ~netMonitorServer() + { + delete[] name ; + delete[] password ; + delete[] prompt ; + } + + const char* getPassword () const { return password; } + void setPassword ( const char* string ) + { + delete[] password ; + password = ulStrDup ( string?string:"" ) ; + } + + void setPrompt ( const char* string ) + { + delete[] prompt ; + prompt = ulStrDup ( string?string:"" ) ; + } + + void setCommandFunc ( void (*func)(const char*) ) + { + cmdfunc = func ; + } + + bool push (const char* s) ; +} ; + +#endif // NET_MONITOR_H diff --git a/src/net/netSocket.cxx b/src/net/netSocket.cxx new file mode 100644 index 0000000..ad57ee7 --- /dev/null +++ b/src/net/netSocket.cxx @@ -0,0 +1,499 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: netSocket.cxx 2135 2008-11-10 15:40:28Z fayjf $ +*/ + +#include "netSocket.h" + +#if defined(UL_CYGWIN) || !defined (UL_WIN32) + +#include +#include +#include +#include +#include +#include /* Need both for Mandrake 8.0!! */ +#include +#include +#include + +#else + +#include +#include + +#endif + +#if defined(UL_MSVC) && !defined(socklen_t) +#define socklen_t int +#endif + +/* Paul Wiltsey says we need this for Solaris 2.8 */ + +#ifndef INADDR_NONE +#define INADDR_NONE ((unsigned long)-1) +#endif + +netAddress::netAddress ( const char* host, int port ) +{ + set ( host, port ) ; +} + + +void netAddress::set ( const char* host, int port ) +{ + memset(this, 0, sizeof(netAddress)); + + sin_family = AF_INET ; + sin_port = htons (port); + + /* Convert a string specifying a host name or one of a few symbolic + ** names to a numeric IP address. This usually calls gethostbyname() + ** to do the work; the names "" and "" are special. + */ + + if (host[0] == '\0') + sin_addr = INADDR_ANY; + else + if (host[0] == '<' && strcmp(host, "") == 0) + sin_addr = INADDR_BROADCAST; + else + { + sin_addr = inet_addr ( host ) ; + + if ( sin_addr == INADDR_NONE ) + { + struct hostent *hp = gethostbyname ( host ) ; + + if ( hp != NULL ) + memcpy ( (char *) &sin_addr, hp->h_addr, hp->h_length ) ; + else + { + perror ( "netAddress::set" ) ; + sin_addr = INADDR_ANY ; + } + } + } +} + + +/* Create a string object representing an IP address. + This is always a string of the form 'dd.dd.dd.dd' (with variable + size numbers). */ + +const char* netAddress::getHost () const +{ +#if 0 + const char* buf = inet_ntoa ( sin_addr ) ; +#else + static char buf [32]; + long x = ntohl(sin_addr); + sprintf(buf, "%d.%d.%d.%d", + (int) (x>>24) & 0xff, (int) (x>>16) & 0xff, + (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff ); +#endif + return buf; +} + +unsigned int netAddress::getIP () const +{ + return sin_addr; +} + +unsigned int netAddress::getPort() const +{ + return ntohs(sin_port); +} + +unsigned int netAddress::getFamily () const +{ + return sin_family; +} + +const char* netAddress::getLocalHost () +{ + //gethostbyname(gethostname()) + + char buf[256]; + memset(buf, 0, sizeof(buf)); + gethostname(buf, sizeof(buf)-1); + const hostent *hp = gethostbyname(buf); + + if (hp && *hp->h_addr_list) + { + in_addr addr = *((in_addr*)*hp->h_addr_list); + const char* host = inet_ntoa(addr); + + if ( host ) + return host ; + } + + return "127.0.0.1" ; +} + + +bool netAddress::getBroadcast () const +{ + return sin_addr == INADDR_BROADCAST; +} + + +netSocket::netSocket () +{ + handle = -1 ; +} + + +netSocket::~netSocket () +{ + close () ; +} + + +void netSocket::setHandle (int _handle) +{ + close () ; + handle = _handle ; +} + + +bool netSocket::open ( bool stream ) +{ + close () ; + handle = ::socket ( AF_INET, (stream? SOCK_STREAM: SOCK_DGRAM), 0 ) ; + return (handle != -1); +} + + +void netSocket::setBlocking ( bool blocking ) +{ + assert ( handle != -1 ) ; + +#if defined(UL_CYGWIN) || !defined (UL_WIN32) + + int delay_flag = ::fcntl (handle, F_GETFL, 0); + + if (blocking) + delay_flag &= (~O_NDELAY); + else + delay_flag |= O_NDELAY; + + ::fcntl (handle, F_SETFL, delay_flag); + +#else + + u_long nblocking = blocking? 0: 1; + ::ioctlsocket(handle, FIONBIO, &nblocking); + +#endif +} + + +void netSocket::setBroadcast ( bool broadcast ) +{ + assert ( handle != -1 ) ; + int result; + if ( broadcast ) { + int one = 1; +#ifdef UL_WIN32 + result = ::setsockopt( handle, SOL_SOCKET, SO_BROADCAST, (char*)&one, sizeof(one) ); +#else + result = ::setsockopt( handle, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one) ); +#endif + } else { + result = ::setsockopt( handle, SOL_SOCKET, SO_BROADCAST, NULL, 0 ); + } + if ( result < 0 ) { + perror("set broadcast:"); + } + assert ( result != -1 ); +} + + +int netSocket::bind ( const char* host, int port ) +{ + assert ( handle != -1 ) ; + netAddress addr ( host, port ) ; + return ::bind(handle,(const sockaddr*)&addr,sizeof(netAddress)); +} + + +int netSocket::listen ( int backlog ) +{ + assert ( handle != -1 ) ; + return ::listen(handle,backlog); +} + + +int netSocket::accept ( netAddress* addr ) +{ + assert ( handle != -1 ) ; + + if ( addr == NULL ) + { + return ::accept(handle,NULL,NULL); + } + else + { + socklen_t addr_len = (socklen_t) sizeof(netAddress) ; + return ::accept(handle,(sockaddr*)addr,&addr_len); + } +} + + +int netSocket::connect ( const char* host, int port ) +{ + assert ( handle != -1 ) ; + netAddress addr ( host, port ) ; + if ( addr.getBroadcast() ) { + setBroadcast( true ); + } + return ::connect(handle,(const sockaddr*)&addr,sizeof(netAddress)); +} + + +int netSocket::send (const void * buffer, int size, int flags) +{ + assert ( handle != -1 ) ; + return ::send (handle, (const char*)buffer, size, flags); +} + + +int netSocket::sendto ( const void * buffer, int size, + int flags, const netAddress* to ) +{ + assert ( handle != -1 ) ; + return ::sendto(handle,(const char*)buffer,size,flags, + (const sockaddr*)to,sizeof(netAddress)); +} + + +int netSocket::recv (void * buffer, int size, int flags) +{ + assert ( handle != -1 ) ; + return ::recv (handle, (char*)buffer, size, flags); +} + + +int netSocket::recvfrom ( void * buffer, int size, + int flags, netAddress* from ) +{ + assert ( handle != -1 ) ; + socklen_t fromlen = (socklen_t) sizeof(netAddress) ; + return ::recvfrom(handle,(char*)buffer,size,flags,(sockaddr*)from,&fromlen); +} + + +void netSocket::close (void) +{ + if ( handle != -1 ) + { +#if defined(UL_CYGWIN) || !defined (UL_WIN32) + ::close( handle ); +#else + ::closesocket( handle ); +#endif + handle = -1 ; + } +} + + +bool netSocket::isNonBlockingError () +{ +#if defined(UL_CYGWIN) || !defined (UL_WIN32) + switch (errno) { + case EWOULDBLOCK: // always == NET_EAGAIN? + case EALREADY: + case EINPROGRESS: + return true; + } + return false; +#else + int wsa_errno = WSAGetLastError(); + if ( wsa_errno != 0 ) + { + WSASetLastError(0); + ulSetError(UL_WARNING,"WSAGetLastError() => %d",wsa_errno); + switch (wsa_errno) { + case WSAEWOULDBLOCK: // always == NET_EAGAIN? + case WSAEALREADY: + case WSAEINPROGRESS: + return true; + } + } + return false; +#endif +} + + +////////////////////////////////////////////////////////////////////// +// +// modified version by os +// +////////////////////////////////////////////////////////////////////// +int netSocket::select ( netSocket** reads, netSocket** writes, int timeout ) +{ + fd_set r,w; + int retval; + + FD_ZERO (&r); + FD_ZERO (&w); + + int i, k ; + int num = 0 ; + + if ( reads ) + { + for ( i=0; reads[i]; i++ ) + { + int fd = reads[i]->getHandle(); + FD_SET (fd, &r); + num++; + } + } + + if ( writes ) + { + for ( i=0; writes[i]; i++ ) + { + int fd = writes[i]->getHandle(); + FD_SET (fd, &w); + num++; + } + } + + if (!num) + return num ; + + /* Set up the timeout */ + struct timeval tv ; + tv.tv_sec = timeout/1000; + tv.tv_usec = (timeout%1000)*1000; + + // It bothers me that select()'s first argument does not appear to + // work as advertised... [it hangs like this if called with + // anything less than FD_SETSIZE, which seems wasteful?] + + // Note: we ignore the 'exception' fd_set - I have never had a + // need to use it. The name is somewhat misleading - the only + // thing I have ever seen it used for is to detect urgent data - + // which is an unportable feature anyway. + + retval = ::select (FD_SETSIZE, &r, &w, 0, &tv); + + //remove sockets that had no activity + + num = 0 ; + + if ( reads ) + { + for ( k=i=0; reads[i]; i++ ) + { + int fd = reads[i]->getHandle(); + if ( FD_ISSET (fd, &r) ) + { + reads[k++] = reads[i]; + num++; + } + } + reads[k] = NULL ; + } + + if ( writes ) + { + for ( k=i=0; writes[i]; i++ ) + { + int fd = writes[i]->getHandle(); + if ( FD_ISSET (fd, &w) ) + { + writes[k++] = writes[i]; + num++; + } + } + writes[k] = NULL ; + } + + if (retval == 0) // timeout + return (-2); + if (retval == -1)// error + return (-1); + + return num ; +} + + +/* Init/Exit functions */ + +static void netExit ( void ) +{ +#if defined(UL_CYGWIN) || !defined (UL_WIN32) +#else + /* Clean up windows networking */ + if ( WSACleanup() == SOCKET_ERROR ) { + if ( WSAGetLastError() == WSAEINPROGRESS ) { + WSACancelBlockingCall(); + WSACleanup(); + } + } +#endif +} + + +int netInit ( int* argc, char** argv ) +{ + /* Legacy */ + + return netInit () ; +} + + +int netInit () +{ + assert ( sizeof(sockaddr_in) == sizeof(netAddress) ) ; + +#if defined(UL_CYGWIN) || !defined (UL_WIN32) +#else + /* Start up the windows networking */ + WORD version_wanted = MAKEWORD(1,1); + WSADATA wsaData; + + if ( WSAStartup(version_wanted, &wsaData) != 0 ) { + ulSetError(UL_WARNING,"Couldn't initialize Winsock 1.1"); + return(-1); + } +#endif + + atexit( netExit ) ; + return(0); +} + + +const char* netFormat ( const char* format, ... ) +{ + static char buffer[ 256 ]; + va_list argptr; + va_start(argptr, format); + vsprintf( buffer, format, argptr ); + va_end(argptr); + return( buffer ); +} + + diff --git a/src/net/netSocket.h b/src/net/netSocket.h new file mode 100644 index 0000000..80e65da --- /dev/null +++ b/src/net/netSocket.h @@ -0,0 +1,128 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: netSocket.h 2135 2008-11-10 15:40:28Z fayjf $ +*/ + +/**** +* NAME +* netSocket - network sockets +* +* DESCRIPTION +* netSocket is a thin C++ wrapper over bsd sockets to +* facilitate porting to other platforms +* +* AUTHOR +* Dave McClurg +* +* CREATION DATE +* Dec-2000 +* +****/ + +#ifndef NET_SOCKET_H +#define NET_SOCKET_H + +#include "ul.h" +#include + +#if defined(UL_MAC_OSX) +# include +#endif + +/* + * Socket address, internet style. + */ +class netAddress +{ + /* DANGER!!! This MUST match 'struct sockaddr_in' exactly! */ +#ifdef UL_MAC_OSX +// This member is added since OS X 10.5.2 ... I'm wondering how to handle this... + __uint8_t sin_len; + __uint8_t sin_family; + in_port_t sin_port; + in_addr_t sin_addr; + char sin_zero[8]; +#else + short sin_family ; + unsigned short sin_port ; + unsigned int sin_addr ; + char sin_zero [ 8 ] ; +#endif + +public: + netAddress () {} + netAddress ( const char* host, int port ) ; + + void set ( const char* host, int port ) ; + const char* getHost () const ; + unsigned int getPort() const ; + unsigned int getIP () const ; + unsigned int getFamily () const ; + static const char* getLocalHost () ; + + bool getBroadcast () const ; +}; + + +/* + * Socket type + */ +class netSocket +{ + int handle ; + +public: + + netSocket () ; + virtual ~netSocket () ; + + int getHandle () const { return handle; } + void setHandle (int handle) ; + + bool open ( bool stream=true ) ; + void close ( void ) ; + int bind ( const char* host, int port ) ; + int listen ( int backlog ) ; + int accept ( netAddress* addr ) ; + int connect ( const char* host, int port ) ; + int send ( const void * buffer, int size, int flags = 0 ) ; + int sendto ( const void * buffer, int size, int flags, const netAddress* to ) ; + int recv ( void * buffer, int size, int flags = 0 ) ; + int recvfrom ( void * buffer, int size, int flags, netAddress* from ) ; + + void setBlocking ( bool blocking ) ; + void setBroadcast ( bool broadcast ) ; + + static bool isNonBlockingError () ; + static int select ( netSocket** reads, netSocket** writes, int timeout ) ; +} ; + + +int netInit ( int* argc, char** argv = NULL ) ; /* Legacy */ + +int netInit () ; + + +const char* netFormat ( const char* fmt, ... ) ; + + +#endif // NET_SOCKET_H + diff --git a/src/psl/Makefile.am b/src/psl/Makefile.am new file mode 100644 index 0000000..6ba1169 --- /dev/null +++ b/src/psl/Makefile.am @@ -0,0 +1,20 @@ + +if BUILD_PSL + +lib_LIBRARIES = libplibpsl.a + +include_HEADERS = psl.h + +libplibpsl_a_SOURCES = psl.cxx pslCodeGen.cxx pslContext.cxx \ + pslCompiler.cxx pslSymbols.cxx pslToken.cxx \ + pslExpression.cxx pslProgram.cxx pslDump.cxx \ + pslError.cxx pslFileIO.cxx pslCompiler.h \ + pslContext.h pslFileIO.h pslLocal.h \ + pslOpcodes.h pslSymbol.h + +INCLUDES = -I$(top_srcdir)/src/util + +endif + +EXTRA_DIST = psl.dsp + diff --git a/src/psl/psl.cxx b/src/psl/psl.cxx new file mode 100644 index 0000000..c5a0856 --- /dev/null +++ b/src/psl/psl.cxx @@ -0,0 +1,66 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: psl.cxx 1708 2002-09-27 21:19:59Z ude $ +*/ + + +#include "pslLocal.h" + +int _pslInitialised = FALSE ; +static char *_pslScriptPath = NULL ; + +void pslInit () { _pslInitialised = TRUE ; } + +void pslScriptPath ( const char *path ) +{ + delete [] _pslScriptPath ; + _pslScriptPath = ulStrDup ( path ) ; +} + + +char* _pslMakeScriptPath ( char* path, const char* fname ) +{ + if ( fname != NULL && fname [ 0 ] != '\0' ) + { + if ( ! ulIsAbsolutePathName ( fname ) && + _pslScriptPath != NULL && _pslScriptPath[0] != '\0' ) + { + strcpy ( path, _pslScriptPath ) ; + strcat ( path, "/" ) ; + strcat ( path, fname ) ; + } + else + strcpy ( path, fname ) ; + + /* Convert backward slashes to forward slashes */ + + for ( char* ptr = path ; *ptr ; ptr ++ ) + if ( *ptr == '\\' ) + *ptr = '/' ; + } + else + path [0] = 0 ; + + return path ; +} + + + diff --git a/src/psl/psl.dsp b/src/psl/psl.dsp new file mode 100644 index 0000000..18ad01b --- /dev/null +++ b/src/psl/psl.dsp @@ -0,0 +1,166 @@ +# Microsoft Developer Studio Project File - Name="psl" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=psl - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "psl.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "psl.mak" CFG="psl - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "psl - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "psl - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "psl - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "..\util" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy release\*.lib ..\..\*.* copy psl.h ..\..\psl.h +# End Special Build Tool + +!ELSEIF "$(CFG)" == "psl - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I "..\util" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\psl_d.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy debug\*.lib ..\..\*.* copy psl.h ..\..\psl.h +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "psl - Win32 Release" +# Name "psl - Win32 Debug" +# Begin Source File + +SOURCE=.\pslCodeGen.cxx +# End Source File +# Begin Source File + +SOURCE=.\pslCompiler.cxx +# End Source File +# Begin Source File + +SOURCE=.\pslCompiler.h +# End Source File +# Begin Source File + +SOURCE=.\pslContext.cxx +# End Source File +# Begin Source File + +SOURCE=.\pslContext.h +# End Source File +# Begin Source File + +SOURCE=.\psl.cxx +# End Source File +# Begin Source File + +SOURCE=.\pslDump.cxx +# End Source File +# Begin Source File + +SOURCE=.\pslError.cxx +# End Source File +# Begin Source File + +SOURCE=.\pslExpression.cxx +# End Source File +# Begin Source File + +SOURCE=.\pslFileIO.cxx +# End Source File +# Begin Source File + +SOURCE=.\pslFileIO.h +# End Source File +# Begin Source File + +SOURCE=.\psl.h +# End Source File +# Begin Source File + +SOURCE=.\pslLocal.h +# End Source File +# Begin Source File + +SOURCE=.\pslOpcodes.h +# End Source File +# Begin Source File + +SOURCE=.\pslProgram.cxx +# End Source File +# Begin Source File + +SOURCE=.\pslSymbol.h +# End Source File +# Begin Source File + +SOURCE=.\pslSymbols.cxx +# End Source File +# Begin Source File + +SOURCE=.\pslToken.cxx +# End Source File +# End Target +# End Project diff --git a/src/psl/psl.h b/src/psl/psl.h new file mode 100644 index 0000000..67602f6 --- /dev/null +++ b/src/psl/psl.h @@ -0,0 +1,348 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: psl.h 2072 2006-03-25 00:35:57Z bram $ +*/ + +#ifndef _PSL_H +#define _PSL_H 1 + +#include +#include "ul.h" + +enum pslResult +{ + PSL_PROGRAM_END, + PSL_PROGRAM_PAUSE, + PSL_PROGRAM_CONTINUE +} ; + + +#define PSL_COMPILETIME_WARNING 1 +#define PSL_COMPILETIME_ERROR 2 +#define PSL_RUNTIME_WARNING 3 +#define PSL_RUNTIME_ERROR 4 + +typedef unsigned char pslOpcode ; +class pslContext ; +class pslCompiler ; +class pslProgram ; + + +enum pslType +{ + PSL_INT = 0, + PSL_FLOAT = 1, + PSL_STRING = 3, + PSL_VOID = 4 +} ; + + +class pslNumber +{ +protected: + + union + { + int i ; + float f ; + } ; + + char *s ; + + + pslType t ; + +public: + + pslNumber () { t = PSL_VOID ; s = NULL ; } + virtual ~pslNumber () { } + + virtual void set ( int ) = 0 ; + virtual void set ( float ) = 0 ; + virtual void set ( const char * ) = 0 ; + virtual void set ( const pslNumber * ) = 0 ; + + void reset () { t = PSL_VOID ; i = 0 ; delete [] s ; s = NULL ; } + + pslType getType () const { return t ; } + void setType ( pslType _type ) { t = _type ; } + + int getInt () const + { + switch ( t ) + { + case PSL_INT : return i ; + case PSL_FLOAT : return (int) f ; + case PSL_STRING : return (int) strtol(s,NULL,0) ; + case PSL_VOID : return 0 ; + } + return 0 ; + } + + float getFloat () const + { + switch ( t ) + { + case PSL_INT : return (float) i ; + case PSL_FLOAT : return f ; + case PSL_STRING : return (float) atof( s ) ; + case PSL_VOID : return 0.0f ; + } + return 0.0f ; + } + + char *getString () const + { + switch ( t ) + { + case PSL_STRING : return s ; + case PSL_INT : + case PSL_FLOAT : + case PSL_VOID : return NULL ; + } + return NULL ; + } + +} ; + + + +/* + psVariables can change value - but their type is + fixed once set. +*/ + +class pslVariable : public pslNumber +{ + pslVariable *array ; + int array_size ; +public: + + pslVariable () { array = NULL ; array_size = 0 ; } + virtual ~pslVariable () { } + + void setArrayType ( pslType _type, int arraysize ) + { + setType ( _type ) ; + delete [] array ; + array_size = arraysize ; + array = new pslVariable [ array_size ] ; + + for ( int i = 0 ; i < array_size ; i++ ) + { + array [ i ] . setType ( getType () ) ; + array [ i ] . set ( 0 ) ; + } + } + + virtual void set ( int v ) + { + switch ( t ) + { + case PSL_INT : i = v ; return ; + case PSL_FLOAT : f = (float) v ; return ; + case PSL_STRING : + case PSL_VOID : return ; + } + } + + virtual void set ( float v ) + { + switch ( t ) + { + case PSL_INT : i = (int) v ; return ; + case PSL_FLOAT : f = v ; return ; + case PSL_STRING : + case PSL_VOID : return ; + } + } + + virtual void set ( const char *v ) + { + switch ( t ) + { + case PSL_INT : i = (int) strtol ( v, NULL, 0 ) ; return ; + case PSL_FLOAT : f = (float) atof ( v ) ; return ; + case PSL_STRING : delete [] s ; + if ( v == NULL ) + s = ulStrDup ( "" ) ; + else + s = ulStrDup ( v ) ; + return ; + case PSL_VOID : return ; + } + } + + virtual void set ( const pslNumber *v ) + { + switch ( t ) + { + case PSL_INT : set ( v -> getInt () ) ; return ; + case PSL_FLOAT : set ( v -> getFloat () ) ; return ; + case PSL_STRING : set ( v -> getString () ) ; return ; + case PSL_VOID : return ; + } + } + + + pslVariable *getIndex ( int index ) + { + if ( index < 0 || index >= array_size || array == NULL ) + return this ; + + return & ( array [ index ] ) ; + } + + + virtual void set ( int v, int index ) + { + if ( index < 0 || index >= array_size || array == NULL ) + set ( v ) ; + + array [ index ] . set ( v ) ; + } + + virtual void set ( float v, int index ) + { + if ( index < 0 || index >= array_size || array == NULL ) + set ( v ) ; + + array [ index ] . set ( v ) ; + } + + virtual void set ( const char *v, int index ) + { + if ( index < 0 || index >= array_size || array == NULL ) + set ( v ) ; + + array [ index ] . set ( v ) ; + } + + virtual void set ( const pslNumber *v, int index ) + { + if ( index < 0 || index >= array_size || array == NULL ) + set ( v ) ; + + array [ index ] . set ( v ) ; + } + +} ; + + +/* + psValues can change their type as needed. +*/ + +class pslValue : public pslNumber +{ +public: + virtual ~pslValue () { } + virtual void set () { t = PSL_VOID ; } + virtual void set ( int v ) { t = PSL_INT ; i = v ; } + virtual void set ( float v ) { t = PSL_FLOAT ; f = v ; } + virtual void set ( const char *v ) { t = PSL_STRING ; + delete [] s ; + if ( v == NULL ) + s = ulStrDup ( "" ) ; + else + s = ulStrDup ( v ) ; } + + virtual void set ( const pslNumber *v ) + { + t = v -> getType () ; + + switch ( t ) + { + case PSL_INT : set ( v -> getInt () ) ; break ; + case PSL_FLOAT : set ( v -> getFloat () ) ; break ; + case PSL_STRING : set ( v -> getString () ) ; break ; + case PSL_VOID : break ; + } + } + +} ; + + +class pslExtension +{ +public: + const char *symbol ; + int argc ; + pslValue (*func) ( int, pslValue *, pslProgram *p ) ; +} ; + + + +class pslProgram +{ + pslOpcode *code ; + pslContext *context ; + pslCompiler *compiler ; + const pslExtension *extensions ; + + void *userData ; + + char *progName ; + + int force_trace ; + int force_stacktrace ; + +public: + + pslProgram ( const pslExtension *ext, const char *_progName = NULL ) ; + pslProgram ( pslProgram *src, const char *_progName = NULL ) ; + + ~pslProgram () ; + + pslContext *getContext () const { return context ; } + pslOpcode *getCode () const { return code ; } + pslCompiler *getCompiler () const { return compiler ; } + const pslExtension *getExtensions () const { return extensions ; } + + int getStackTraceFlag () const { return force_stacktrace ; } + + char *getProgName () const { return progName ; } + + void setProgName ( const char *nm ) + { + delete [] progName ; + progName = ulStrDup ( nm ) ; + } + + void *getUserData () const { return userData ; } + void setUserData ( void *ud ) { userData = ud ; } + + void dump () const ; + int compile ( const char *fname ) ; + int compile ( const char *memptr, const char *fname ) ; + int compile ( FILE *fd ) ; + void reset () ; + pslResult step () ; + pslResult trace () ; +} ; + + +void pslInit () ; +void pslScriptPath ( const char *path ) ; +void pslSetErrorCallback ( void (*CB) ( pslProgram *, int, char *, int, char * ) ) ; + +#endif + diff --git a/src/psl/pslCodeGen.cxx b/src/psl/pslCodeGen.cxx new file mode 100644 index 0000000..03a67cf --- /dev/null +++ b/src/psl/pslCodeGen.cxx @@ -0,0 +1,394 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pslCodeGen.cxx 1891 2004-03-18 22:09:07Z sjbaker $ +*/ + + +#include "pslLocal.h" + + +void pslCompiler::genCodeByte ( pslOpcode op ) +{ + if ( next_code >= MAX_CODE - 1 ) + error ( "Program too big!" ) ; + else + code [ next_code++ ] = op ; +} + + +void pslCompiler::genCodeAddr ( pslAddress a ) +{ + genCodeByte ( a & 0xFF ) ; + genCodeByte ( ( a >> 8 ) & 0xFF ) ; +} + + +void pslCompiler::genLineNumber ( int l ) +{ + genCodeByte ( OPCODE_LINE_NUMBER ) ; + genCodeByte ( l & 0xFF ) ; + genCodeByte ( ( l >> 8 ) & 0xFF ) ; +} + + +void pslCompiler::genCharConstant ( char c ) +{ + /* A bit wasteful but... */ + + genCodeByte ( OPCODE_PUSH_INT_CONSTANT ) ; + genCodeByte ( c ) ; + genCodeByte ( 0 ) ; + genCodeByte ( 0 ) ; + genCodeByte ( 0 ) ; +} + + +void pslCompiler::genConstant ( const char *c ) +{ + int isInteger = TRUE ; + + for ( const char *p = c ; *p != '\0' ; p++ ) + if ( *p == '.' || *p == 'f' || *p == 'F' ) + { + isInteger = FALSE ; + break ; + } + + if ( isInteger ) + genIntConstant ( c ) ; + else + genFloatConstant ( c ) ; +} + + +void pslCompiler::genStringConstant ( const char *c ) +{ + genCodeByte ( OPCODE_PUSH_STRING_CONSTANT ) ; + + for ( int i = 0 ; c [ i ] != '\0' ; i++ ) + genCodeByte ( (unsigned char)( c [ i ]) ) ; + + genCodeByte ( '\0' ) ; +} + + +void pslCompiler::genIntConstant ( int i ) +{ + char *ii = (char *) & i ; + + genCodeByte ( OPCODE_PUSH_INT_CONSTANT ) ; + genCodeByte ( ii [ 0 ] ) ; + genCodeByte ( ii [ 1 ] ) ; + genCodeByte ( ii [ 2 ] ) ; + genCodeByte ( ii [ 3 ] ) ; +} + +void pslCompiler::genIntConstant ( const char *c ) +{ + int i = (int) strtol ( c, NULL, 0 ) ; + genIntConstant ( i ) ; +} + +void pslCompiler::genFloatConstant ( const char *c ) +{ + float f = (float) atof ( c ) ; + char *ff = (char *) & f ; + + genCodeByte ( OPCODE_PUSH_FLOAT_CONSTANT ) ; + genCodeByte ( ff [ 0 ] ) ; + genCodeByte ( ff [ 1 ] ) ; + genCodeByte ( ff [ 2 ] ) ; + genCodeByte ( ff [ 3 ] ) ; +} + +void pslCompiler::genGetParameter ( pslAddress var, int argpos ) +{ + genCodeByte ( OPCODE_GET_PARAMETER ) ; + genCodeByte ( (unsigned char) var ) ; + genCodeByte ( argpos ) ; +} + +int pslCompiler::genMakeIntArray ( const char *c ) +{ + int a = getVarSymbol ( c ) ; + + genCodeByte ( OPCODE_SET_INT_ARRAY ) ; + genCodeByte ( a ) ; + return a ; +} + +int pslCompiler::genMakeFloatArray ( const char *c ) +{ + int a = getVarSymbol ( c ) ; + + genCodeByte ( OPCODE_SET_FLOAT_ARRAY ) ; + genCodeByte ( a ) ; + return a ; +} + +int pslCompiler::genMakeStringArray ( const char *c ) +{ + int a = getVarSymbol ( c ) ; + + genCodeByte ( OPCODE_SET_STRING_ARRAY ) ; + genCodeByte ( a ) ; + return a ; +} + +int pslCompiler::genMakeIntVariable ( const char *c ) +{ + int a = getVarSymbol ( c ) ; + + genCodeByte ( OPCODE_SET_INT_VARIABLE ) ; + genCodeByte ( a ) ; + return a ; +} + +int pslCompiler::genMakeFloatVariable ( const char *c ) +{ + int a = getVarSymbol ( c ) ; + + genCodeByte ( OPCODE_SET_FLOAT_VARIABLE ) ; + genCodeByte ( a ) ; + return a ; +} + +int pslCompiler::genMakeStringVariable ( const char *c ) +{ + int a = getVarSymbol ( c ) ; + + genCodeByte ( OPCODE_SET_STRING_VARIABLE ) ; + genCodeByte ( a ) ; + return a ; +} + + +void pslCompiler::genVariable ( const char *c, int array_ref ) +{ + int a = getVarSymbol ( c ) ; + + genIntConstant ( array_ref ) ; + genIntConstant ( a ) ; +} + +void pslCompiler::genFetch () +{ + genCodeByte ( OPCODE_FETCH ) ; +} + +void pslCompiler::genIncrementFetch () +{ + genCodeByte ( OPCODE_INCREMENT_FETCH ) ; +} + +void pslCompiler::genDecrementFetch () +{ + genCodeByte ( OPCODE_DECREMENT_FETCH ) ; +} + +void pslCompiler::genIncrementLValue () +{ + genCodeByte ( OPCODE_INCREMENT_LVALUE ) ; +} + +void pslCompiler::genDecrementLValue () +{ + genCodeByte ( OPCODE_DECREMENT_LVALUE ) ; +} + +void pslCompiler::genAssignment () +{ + genCodeByte ( OPCODE_POP_VARIABLE ) ; +} + +void pslCompiler::genAddAssignment () +{ + genCodeByte ( OPCODE_POP_ADD_VARIABLE ) ; +} + + +void pslCompiler::genSubAssignment () +{ + genCodeByte ( OPCODE_POP_SUB_VARIABLE ) ; +} + + +void pslCompiler::genMulAssignment () +{ + genCodeByte ( OPCODE_POP_MUL_VARIABLE ) ; +} + + +void pslCompiler::genModAssignment () +{ + genCodeByte ( OPCODE_POP_MOD_VARIABLE ) ; +} + + +void pslCompiler::genDivAssignment () +{ + genCodeByte ( OPCODE_POP_DIV_VARIABLE ) ; +} + + +void pslCompiler::genAndAssignment () +{ + genCodeByte ( OPCODE_POP_AND_VARIABLE ) ; +} + + +void pslCompiler::genOrAssignment () +{ + genCodeByte ( OPCODE_POP_OR_VARIABLE ) ; +} + + +void pslCompiler::genXorAssignment () +{ + genCodeByte ( OPCODE_POP_XOR_VARIABLE ) ; +} + + +void pslCompiler::genSHLAssignment () +{ + genCodeByte ( OPCODE_POP_SHL_VARIABLE ) ; +} + + +void pslCompiler::genSHRAssignment () +{ + genCodeByte ( OPCODE_POP_SHR_VARIABLE ) ; +} + + +void pslCompiler::genCall ( const char *c, int argc ) +{ + int ext = getExtensionSymbol ( c ) ; + + if ( ext < 0 ) + { + genIntConstant ( argc ) ; + genCodeByte ( OPCODE_CALL ) ; + + int a = getCodeSymbol ( c, next_code ) ; + + genCodeAddr ( a ) ; + genCodeByte ( argc ) ; + } + else + { + genCodeByte ( OPCODE_CALLEXT ) ; + genCodeByte ( ext ) ; + genCodeByte ( argc ) ; + } +} + +void pslCompiler::genExchange () { genCodeByte ( OPCODE_EXCHANGE ) ; } +void pslCompiler::genReturn () { genCodeByte ( OPCODE_RETURN ) ; } +void pslCompiler::genPop () { genCodeByte ( OPCODE_POP ) ; } +void pslCompiler::genSubtract () { genCodeByte ( OPCODE_SUB ) ; } +void pslCompiler::genAdd () { genCodeByte ( OPCODE_ADD ) ; } +void pslCompiler::genDivide () { genCodeByte ( OPCODE_DIV ) ; } +void pslCompiler::genMultiply () { genCodeByte ( OPCODE_MULT ) ; } +void pslCompiler::genModulo () { genCodeByte ( OPCODE_MOD ) ; } +void pslCompiler::genNegate () { genCodeByte ( OPCODE_NEG ) ; } +void pslCompiler::genNot () { genCodeByte ( OPCODE_NOT ) ; } +void pslCompiler::genTwiddle () { genCodeByte ( OPCODE_TWIDDLE ) ; } +void pslCompiler::genOrOr () { genCodeByte ( OPCODE_OROR ) ; } +void pslCompiler::genAndAnd () { genCodeByte ( OPCODE_ANDAND ) ; } +void pslCompiler::genOr () { genCodeByte ( OPCODE_OR ) ; } +void pslCompiler::genAnd () { genCodeByte ( OPCODE_AND ) ; } +void pslCompiler::genXor () { genCodeByte ( OPCODE_XOR ) ; } +void pslCompiler::genShiftLeft () { genCodeByte ( OPCODE_SHIFTLEFT ) ; } +void pslCompiler::genShiftRight () { genCodeByte ( OPCODE_SHIFTRIGHT ) ; } + +void pslCompiler::genLess () { genCodeByte ( OPCODE_LESS ) ; } +void pslCompiler::genLessEqual () { genCodeByte ( OPCODE_LESSEQUAL ) ; } +void pslCompiler::genGreater () { genCodeByte ( OPCODE_GREATER ) ; } +void pslCompiler::genGreaterEqual () { genCodeByte ( OPCODE_GREATEREQUAL); } +void pslCompiler::genNotEqual () { genCodeByte ( OPCODE_NOTEQUAL ) ; } +void pslCompiler::genEqual () { genCodeByte ( OPCODE_EQUAL ) ; } + +void pslCompiler::genStackDup () { genCodeByte ( OPCODE_STACK_DUPLICATE ) ; } + +int pslCompiler::genPeekJumpIfTrue ( int l ) +{ + genCodeByte ( OPCODE_PEEK_JUMP_TRUE ) ; + + int res = next_code ; + + genCodeAddr ( l ) ; + + return res ; +} + +int pslCompiler::genPeekJumpIfFalse ( int l ) +{ + genCodeByte ( OPCODE_PEEK_JUMP_FALSE ) ; + + int res = next_code ; + + genCodeAddr ( l ) ; + + return res ; +} + +int pslCompiler::genJumpIfTrue ( int l ) +{ + genCodeByte ( OPCODE_JUMP_TRUE ) ; + + int res = next_code ; + + genCodeAddr ( l ) ; + + return res ; +} + +int pslCompiler::genJumpIfFalse ( int l ) +{ + genCodeByte ( OPCODE_JUMP_FALSE ) ; + + int res = next_code ; + + genCodeAddr ( l ) ; + + return res ; +} + +int pslCompiler::genJump ( int l ) +{ + genCodeByte ( OPCODE_JUMP ) ; + + int res = next_code ; + + genCodeAddr ( l ) ; + + return res ; +} + + +int pslCompiler::genPauseStatement() +{ + genCodeByte ( OPCODE_PAUSE ) ; + return TRUE ; +} + + diff --git a/src/psl/pslCompiler.cxx b/src/psl/pslCompiler.cxx new file mode 100644 index 0000000..1e705f8 --- /dev/null +++ b/src/psl/pslCompiler.cxx @@ -0,0 +1,884 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pslCompiler.cxx 1745 2003-01-06 05:10:14Z sjbaker $ +*/ + + +#include "pslLocal.h" +#include "ul.h" + + +int pslCompiler::compile ( const char *fname ) +{ + char filename [ 1024 ] ; + _pslMakeScriptPath ( filename, fname ) ; + + FILE *fd = fopen ( filename, "ra" ) ; + + if ( fd == NULL ) + { + perror ( "PSL:" ) ; + ulSetError ( UL_WARNING, "PSL: Failed while opening '%s' for reading.", + filename ); + return FALSE ; + } + + return compile ( fd, fname ) ; +} + + +int pslCompiler::compile ( const char *memptr, const char *fname ) +{ + init () ; + + _pslPushDefaultFile ( memptr, (fname == NULL) ? progName : fname ) ; + genProgram () ; + _pslPopDefaultFile () ; + + return cleanup () ; +} + + +int pslCompiler::compile ( FILE *fd, const char *fname ) +{ + init () ; + + _pslPushDefaultFile ( fd, (fname == NULL) ? progName : fname ) ; + genProgram () ; + _pslPopDefaultFile () ; + + return cleanup () ; +} + + +int pslCompiler::cleanup () +{ + const char *dump_env = getenv ( "PSL_DUMP" ) ; + + if ( num_errors != 0 || num_warnings != 0 ) + fprintf ( stderr, "PSL: '%s' Compiled with %d Warnings, %d Fatal Errors\n", + progName, num_warnings, num_errors ) ; + + /* If there are errors, prevent the program from running. */ + + if ( num_errors != 0 ) + { + if ( dump_env != NULL && + ulStrEqual ( dump_env, "on_error" ) ) + dump () ; + + next_code = 0 ; + genCodeByte ( OPCODE_HALT ) ; + } + else + if ( dump_env != NULL && + ulStrEqual ( dump_env, "always" ) ) + dump () ; + + return num_errors ; +} + + + +int pslCompiler::genReturnStatement () +{ + char c [ MAX_TOKEN ] ; + + getToken ( c ) ; + + if ( c [ 0 ] == ';' ) /* Return without data == "return 0" */ + { + ungetToken ( c ) ; + genConstant ( "0.0" ) ; + } + else + { + ungetToken ( c ) ; + genExpression () ; + } + + genReturn () ; + return TRUE ; +} + + + +/* Administer the break/continue jump addresses */ + +void pslCompiler::pushBreakToLabel () +{ + if ( next_break >= MAX_LABEL-1 ) + error ( "Too many nested 'break' contexts" ) ; + else + breakToAddressStack [ next_break++ ] = next_tmp_label++ ; +} + +void pslCompiler::pushNoContinue () +{ + continueToAddressStack [ next_continue++ ] = -1 ; +} + +int pslCompiler::pushContinueToLabel () +{ + if ( next_continue >= MAX_LABEL-1 ) + error ( "Too many nested 'continue' contexts" ) ; + else + continueToAddressStack [ next_continue++ ] = next_tmp_label++ ; + + return next_tmp_label-1 ; +} + +void pslCompiler::setContinueToLabel ( int which ) +{ + char s [ 10 ] ; + sprintf ( s, "L%d", which ) ; + setCodeSymbol ( s, next_code ) ; +} + +void pslCompiler::popBreakToLabel () +{ + char s [ 10 ] ; + sprintf ( s, "L%d", breakToAddressStack[next_break-1] ) ; + setCodeSymbol ( s, next_code ) ; + next_break-- ; +} + +void pslCompiler::popContinueToLabel () +{ + next_continue-- ; +} + + + +/* Implement actual break and continue statements. */ + +int pslCompiler::genBreakStatement () +{ + if ( next_break <= 0 ) + return error ( "'break' statement is not inside a 'switch' or a loop." ) ; + + char s [ 10 ] ; + sprintf ( s, "L%d", breakToAddressStack [ next_break-1 ] ) ; + genJump ( getCodeSymbol ( s, next_code+1 ) ) ; + return TRUE ; +} + + +int pslCompiler::genContinueStatement () +{ + if ( next_break <= 0 ) + return error ( "'continue' statement is not inside a loop." ) ; + + if ( continueToAddressStack [ next_continue-1 ] < 0 ) + return error ( "'continue' statement not allowed inside a 'switch'." ) ; + + char s [ 10 ] ; + sprintf ( s, "L%d", continueToAddressStack [ next_continue-1 ] ) ; + genJump ( getCodeSymbol ( s, next_code+1 ) ) ; + return TRUE ; +} + + + + + +int pslCompiler::genSwitchStatement () +{ + if ( ! genExpression () ) + return error ( "Missing control expression for 'switch'" ) ; + + char c [ MAX_TOKEN ] ; + + getToken ( c ) ; /* Hopefully, the word 'while' */ + + if ( c [ 0 ] != '{' ) + return error ( "Missing '{' after 'switch'" ) ; + + int jumpToNextCase = genJump ( 0 ) ; + int jumpAfterTest = 0 ; + + pushBreakToLabel () ; + pushNoContinue () ; + + while ( TRUE ) + { + getToken ( c ) ; + + if ( strcmp ( c, "case" ) == 0 ) + { + jumpAfterTest = genJump ( 0 ) ; + + code [ jumpToNextCase ] = next_code & 0xFF ; + code [ jumpToNextCase+1 ] = ( next_code >> 8 ) & 0xFF ; + + genStackDup () ; + + if ( ! genExpression () ) + error ( "Missing expression after 'case'." ) ; + + getToken ( c ) ; + + if ( c[0] != ':' ) + error ( "Missing ':' after 'case' expression." ) ; + + genEqual () ; + + jumpToNextCase = genJumpIfFalse ( 0 ) ; + + code [ jumpAfterTest ] = next_code & 0xFF ; + code [ jumpAfterTest+1 ] = ( next_code >> 8 ) & 0xFF ; + } + else + if ( strcmp ( c, "default" ) == 0 ) + { + code [ jumpToNextCase ] = next_code & 0xFF ; + code [ jumpToNextCase+1 ] = ( next_code >> 8 ) & 0xFF ; + + getToken ( c ) ; + + if ( c[0] != ':' ) + error ( "Missing ':' after 'default'." ) ; + } + else + if ( strcmp ( c, "}" ) == 0 ) + { + ungetToken ( ";" ) ; + break ; + } + else + { + ungetToken ( c ) ; + + if ( ! genStatement () ) + error ( "Missing statement within switch." ) ; + + getToken ( c ) ; + + if ( c [ 0 ] != ';' ) + error ( "Missing semicolon." ) ; + } + } + + popBreakToLabel () ; + popContinueToLabel () ; + genPop () ; + return TRUE ; +} + + + +int pslCompiler::genDoWhileStatement () +{ + /* Remember place to jump back to */ + + int start_loc = next_code ; + + pushBreakToLabel () ; + setContinueToLabel ( pushContinueToLabel () ) ; + + if ( ! genStatement () ) + return error ( "Missing statement for 'do/while'" ) ; + + char c [ MAX_TOKEN ] ; + + getToken ( c ) ; /* The final ';' of the action */ + + getToken ( c ) ; /* Hopefully, the word 'while' */ + + if ( strcmp ( c, "while" ) != 0 ) + return error ( "Missing 'while' for 'do/while'" ) ; + + if ( ! genExpression () ) + return error ( "Missing expression for 'while' in a 'do/while'" ) ; + + genJumpIfTrue ( start_loc ) ; + + popBreakToLabel () ; + popContinueToLabel () ; + return TRUE ; +} + + +int pslCompiler::genForStatement () +{ + char c [ MAX_TOKEN ] ; + + pushLocality () ; + pushBreakToLabel () ; + int ct_lab = pushContinueToLabel () ; + + getToken ( c ) ; /* The initial '(' of the action */ + + if ( c [ 0 ] != '(' ) + { + popLocality () ; + return error ( "Missing '(' for 'for' loop" ) ; + } + + if ( ! genStatement () ) + { + popLocality () ; + return error ( "Missing initialiser for 'if'" ) ; + } + + getToken ( c ) ; /* The ';' after the initialiser */ + + if ( c [ 0 ] != ';' ) + { + popLocality () ; + return error ( "Missing ';' after 'for' loop initialisation" ) ; + } + + /* Remember place to jump back to */ + + int start_loc = next_code ; + + /* The test */ + + if ( ! genExpression () ) + return error ( "Missing test for 'for' loop" ) ; + + getToken ( c ) ; /* The ';' after the initialiser */ + + if ( c [ 0 ] != ';' ) + { + popLocality () ; + return error ( "Missing ';' after 'for' loop test" ) ; + } + + char saved [ MAX_UNGET ][ MAX_TOKEN ] ; + int next_saved = 0 ; + int paren_counter = 0 ; + + do + { + getToken ( saved [ next_saved ] ) ; + + if ( saved [ next_saved ][ 0 ] == '(' ) paren_counter++ ; + if ( saved [ next_saved ][ 0 ] == ')' ) paren_counter-- ; + + if ( next_saved >= MAX_UNGET-1 ) + { + popLocality () ; + return error ( "Too many tokens in 'increment' part of 'for' loop" ) ; + } + + next_saved++ ; + + } while ( paren_counter >= 0 ) ; + + next_saved-- ; /* Throw away the ')' */ + + int label_loc = genJumpIfFalse ( 0 ) ; + + if ( ! genStatement () ) + { + popLocality () ; + return error ( "Missing action body for 'for' loop" ) ; + } + + setContinueToLabel ( ct_lab ) ; + + getToken ( c ) ; /* Throw away the ';' */ + + /* Put the increment test back onto the token stream */ + + ungetToken ( ";" ) ; + + for ( int i = next_saved-1 ; i >= 0 ; i-- ) + ungetToken ( saved[i] ) ; + + if ( ! genStatement () ) + { + popLocality () ; + return error ( "Missing 'increment' part of 'for' loop" ) ; + } + + genJump ( start_loc ) ; + + code [ label_loc ] = next_code & 0xFF ; + code [ label_loc+1 ] = ( next_code >> 8 ) & 0xFF ; + + popBreakToLabel () ; + popContinueToLabel () ; + popLocality () ; + return TRUE ; +} + + +int pslCompiler::genWhileStatement () +{ + /* Remember place to jump back to */ + + pushBreakToLabel () ; + setContinueToLabel ( pushContinueToLabel () ) ; + + int start_loc = next_code ; + + if ( ! genExpression () ) + return error ( "Missing expression for 'while'" ) ; + + int label_loc = genJumpIfFalse ( 0 ) ; + + if ( ! genStatement () ) + return error ( "Missing statement for 'while'" ) ; + + genJump ( start_loc ) ; + + code [ label_loc ] = next_code & 0xFF ; + code [ label_loc+1 ] = ( next_code >> 8 ) & 0xFF ; + + popBreakToLabel () ; + popContinueToLabel () ; + + return TRUE ; +} + + +int pslCompiler::genIfStatement () +{ + if ( ! genExpression () ) + return error ( "Missing expression for 'if'" ) ; + + int else_loc = genJumpIfFalse ( 0 ) ; + + if ( ! genStatement () ) + return error ( "Missing statement for 'if'" ) ; + + char c [ MAX_TOKEN ] ; + + getToken ( c ) ; + + if ( c [ 0 ] != ';' ) + { + ungetToken ( c ) ; + return error ( "Missing ';' or 'else' after 'if' statement" ) ; + } + + getToken ( c ) ; + + if ( strcmp ( c, "else" ) != 0 ) + { + code [ else_loc ] = next_code & 0xFF ; + code [ else_loc+1 ] = ( next_code >> 8 ) & 0xFF ; + + ungetToken ( c ) ; + ungetToken ( ";" ) ; + return TRUE ; + } + + int label_loc = genJump ( 0 ) ; + + code [ else_loc ] = next_code & 0xFF ; + code [ else_loc+1 ] = ( next_code >> 8 ) & 0xFF ; + + if ( ! genStatement () ) + return error ( "Missing statement for 'else'" ) ; + + code [ label_loc ] = next_code & 0xFF ; + code [ label_loc+1 ] = ( next_code >> 8 ) & 0xFF ; + + return TRUE ; +} + + +int pslCompiler::genFunctionCall ( const char *var ) +{ + char c [ MAX_TOKEN ] ; + + getToken ( c ) ; + + /* + 'var' should be the name of a function, + 'c' should be an '(' + */ + + if ( c[0] != '(' ) + return error ( "Missing '(' in call to '%s'", var ) ; + + getToken ( c ) ; + + int argc = 0 ; + + while ( c[0] != ')' ) + { + ungetToken ( c ) ; + genExpression () ; + argc++ ; + getToken ( c ) ; + + if ( c[0] == ')' ) + break ; + + if ( c[0] != ',' ) + return error ( "Missing ')' or ',' in call to '%s'", var ) ; + + getToken ( c ) ; + } + + genCall ( var, argc ) ; + return TRUE ; +} + + +int pslCompiler::genCompoundStatement () +{ + char c [ MAX_TOKEN ] ; + + pushLocality () ; + + while ( genStatement () ) + { + getToken ( c ) ; + + if ( c[0] != ';' ) + { + popLocality () ; + return warning ( "Unexpected '%s' in Compound statement", c ) ; + } + } + + getToken ( c ) ; + + if ( c[0] == '}' ) + { + popLocality () ; + ungetToken ( ";" ) ; + return TRUE ; + } + + popLocality () ; + ungetToken ( c ) ; + return warning ( "Unexpected '%s' in Compound statement", c ) ; +} + + +int pslCompiler::genStatement () +{ + char c [ MAX_TOKEN ] ; + + if ( generate_line_numbers ) + genLineNumber ( _pslGetLineNo () ) ; + + getToken ( c ) ; + + if ( strcmp ( c, "static" ) == 0 ) return genStaticVarDecl () ; + if ( strcmp ( c, "string" ) == 0 ) return genLocalVarDecl ( PSL_STRING) ; + if ( strcmp ( c, "int" ) == 0 ) return genLocalVarDecl ( PSL_INT ) ; + if ( strcmp ( c, "float" ) == 0 ) return genLocalVarDecl ( PSL_FLOAT ) ; + if ( strcmp ( c, "return" ) == 0 ) return genReturnStatement () ; + if ( strcmp ( c, "break" ) == 0 ) return genBreakStatement () ; + if ( strcmp ( c, "continue" ) == 0 ) return genContinueStatement () ; + if ( strcmp ( c, "pause" ) == 0 ) return genPauseStatement () ; + if ( strcmp ( c, "for" ) == 0 ) return genForStatement () ; + if ( strcmp ( c, "do" ) == 0 ) return genDoWhileStatement () ; + if ( strcmp ( c, "switch" ) == 0 ) return genSwitchStatement () ; + if ( strcmp ( c, "while" ) == 0 ) return genWhileStatement () ; + if ( strcmp ( c, "if" ) == 0 ) return genIfStatement () ; + if ( strcmp ( c, "case" ) == 0 || strcmp ( c, "default" ) == 0 ) + return error ( "'%s' encountered - not inside 'switch' statement", c ) ; + + if ( c [ 0 ] == '{' ) return genCompoundStatement () ; + + ungetToken ( c ) ; + + if ( genExpression () ) + { + genPop () ; /* Discard result */ + return TRUE ; + } + + return FALSE ; +} + + +void pslCompiler::genProgram () +{ + char c [ MAX_TOKEN ] ; + + /* Compile the program */ + + while ( TRUE ) + { + getToken ( c ) ; + + if ( c[0] == '\0' ) + break ; + + ungetToken ( c ) ; + + genGlobalDeclaration () ; + } + + /* Have the program call 'main' and then halt */ + + genIntConstant ( 0 ) ; /* No arguments to main *YET* */ + + genCodeByte ( OPCODE_CALL ) ; + genCodeAddr ( getCodeSymbol ( "main", next_code ) ) ; + genCodeByte ( 0 ) ; /* Argc */ + genCodeByte ( OPCODE_HALT ) ; + + checkUnresolvedSymbols () ; +} + + + +int pslCompiler::genLocalVarDecl ( pslType t ) +{ + char c [ MAX_TOKEN ] ; + char s [ MAX_TOKEN ] ; + + getToken ( s ) ; + + setVarSymbol ( s ) ; + + getToken ( c ) ; + + if ( c[0] == '[' ) + { + genExpression () ; + + switch ( t ) + { + case PSL_FLOAT : genMakeFloatArray ( s ) ; break ; + case PSL_STRING : genMakeStringArray ( s ) ; break ; + default : genMakeIntArray ( s ) ; break ; + } + + getToken ( c ) ; + + if ( c[0] != ']' ) + return error ( "Missing ']' after array declaration" ) ; + + return TRUE ; + } + + switch ( t ) + { + case PSL_FLOAT : genMakeFloatVariable ( s ) ; break ; + case PSL_STRING : genMakeStringVariable ( s ) ; break ; + default : genMakeIntVariable ( s ) ; break ; + } + + if ( strcmp ( c, "=" ) == 0 ) + { + genVariable ( s, FALSE ) ; + genExpression () ; + genAssignment () ; + genPop () ; + return TRUE ; + } + + ungetToken ( c ) ; + return TRUE ; +} + + + +int pslCompiler::genStaticVarDecl () +{ + return error ( "Static Local Variables are Not Supported Yet." ) ; +} + + + +int pslCompiler::genGlobalVarDecl ( const char *s, pslType t ) +{ + char c [ MAX_TOKEN ] ; + + setVarSymbol ( s ) ; + + getToken ( c ) ; + + if ( c[0] == '[' ) + { + genExpression () ; + + switch ( t ) + { + case PSL_FLOAT : genMakeFloatArray ( s ) ; break ; + case PSL_STRING : genMakeStringArray ( s ) ; break ; + default : genMakeIntArray ( s ) ; break ; + } + + getToken ( c ) ; + + if ( c[0] != ']' ) + return error ( "Missing ']' after array declaration" ) ; + } + else + { + switch ( t ) + { + case PSL_FLOAT : genMakeFloatVariable ( s ) ; break ; + case PSL_STRING : genMakeStringVariable ( s ) ; break ; + default : genMakeIntVariable ( s ) ; break ; + } + + if ( strcmp ( c, "=" ) == 0 ) + { + genVariable ( s, FALSE ) ; + genExpression () ; + genAssignment () ; + genPop () ; + getToken ( c ) ; + } + } + + if ( c[0] != ';' ) + return error ( "Missing ';' after declaration of '%s'", s ) ; + + return TRUE ; +} + + + +int pslCompiler::genGlobalDeclaration () +{ + char c [ MAX_TOKEN ] ; + char fn [ MAX_TOKEN ] ; + + getToken ( c ) ; + + if ( strcmp ( c, "static" ) == 0 || + strcmp ( c, "extern" ) == 0 ) + { + /* Something complicated should probably happen here! */ + getToken ( c ) ; + } + + pslType t ; + + if ( strcmp ( c, "void" ) == 0 ) t = PSL_VOID ; else + if ( strcmp ( c, "int" ) == 0 ) t = PSL_INT ; else + if ( strcmp ( c, "float" ) == 0 ) t = PSL_FLOAT ; else + if ( strcmp ( c, "string" ) == 0 ) t = PSL_STRING ; else + return error ( "Expected declaration - but got '%s'", c ) ; + + getToken ( fn ) ; + + getToken ( c ) ; + + if ( c[0] == '(' ) + { + ungetToken ( c ) ; + return genFunctionDeclaration ( fn ) ; + } + + if ( c[0] == '[' || strcmp ( c, "=" ) == 0 || c[0] == ';' ) + { + ungetToken ( c ) ; + return genGlobalVarDecl ( fn, t ) ; + } + + return error ( "Expected a declaration - but got '%s'", c); +} + + +int pslCompiler::genFunctionDeclaration ( const char *fn ) +{ + char c [ MAX_TOKEN ] ; + + pslAddress jump_target = genJump ( 0 ) ; + + setCodeSymbol ( fn, next_code ) ; + + getToken ( c ) ; + + if ( c[0] != '(' ) + return error ( "Missing '(' in declaration of '%s'", fn ) ; + + pushLocality () ; + + int argpos = 0 ; + + while ( 1 ) + { + getToken ( c ) ; + + if ( c [ 0 ] == ')' || c [ 0 ] == '\0' ) + break ; + + char s [ MAX_TOKEN ] ; + + getToken ( s ) ; + + pslAddress a = setVarSymbol ( s ) ; + + if ( strcmp ( c, "int" ) == 0 ) genMakeIntVariable ( s ) ; else + if ( strcmp ( c, "float" ) == 0 ) genMakeFloatVariable ( s ) ; else + if ( strcmp ( c, "string" ) == 0 ) genMakeStringVariable ( s ) ; else + { + popLocality () ; + return error ( "Missing ')' in declaration of '%s'", fn ) ; + } + + genGetParameter ( a, argpos++ ) ; + + getToken ( c ) ; + + if ( c[0] == ',' ) + continue ; + + if ( c[0] == ')' ) + break ; + + popLocality () ; + return error ( "Missing ',' or ')' in declaration of '%s'", fn ) ; + } + + if ( c[0] != ')' ) + { + popLocality () ; + return error ( "Missing ')' in declaration of '%s'", fn ) ; + } + + getToken ( c ) ; + + if ( c [ 0 ] != '{' ) + { + popLocality () ; + return error ( "Missing '{' in function '%s'", fn ) ; + } + + if ( ! genCompoundStatement () ) + { + popLocality () ; + return error ( "Missing '}' in function '%s'", fn ) ; + } + + getToken ( c ) ; + + /* If we fall off the end of the function, we still need a return value */ + + genConstant ( "0.0" ) ; + genReturn () ; + + code [ jump_target ] = next_code & 0xFF ; + code [ jump_target+1 ] = (next_code >> 8) & 0xFF ; + + popLocality () ; + return TRUE ; +} + + + diff --git a/src/psl/pslCompiler.h b/src/psl/pslCompiler.h new file mode 100644 index 0000000..9658d4b --- /dev/null +++ b/src/psl/pslCompiler.h @@ -0,0 +1,414 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pslCompiler.h 1941 2004-08-05 00:57:38Z puggles $ +*/ + + +struct pslFwdRef +{ + char *symbol ; + pslAddress where ; + + void set ( const char *s, pslAddress w ) + { + symbol = ulStrDup ( s ) ; + where = w ; + } + + pslAddress getWhere () const { return where ; } + + int matches ( const char *s ) const + { + return symbol != NULL && strcmp ( s, symbol ) == 0 ; + } + + pslFwdRef () { symbol = NULL ; } + ~pslFwdRef () { delete [] symbol ; } +} ; + + + +class pslProgram ; + + +class pslCompiler +{ + int ref_count; // reference count. Clean up when this reaches zero + + /* File I/O and preprocessor */ + + int getChar () ; + + void doIncludeStatement () ; + void doDefineStatement () ; + void doIfdefStatement () ; + void doUndefStatement () ; + void doIfndefStatement () ; + void doElseStatement () ; + void doEndifStatement () ; + + int doPreProcessorCommand () ; + void getToken ( char *s, int define_sub = TRUE ) ; + void ungetToken ( const char *s ) ; + void skipToEOL () ; + + + /* Write data into Code space */ + + void genCodeByte ( unsigned char b ) ; + void genCodeAddr ( pslAddress a ) ; + int printOpcode ( FILE *fd, int addr ) const ; + + void genLineNumber ( int l ) ; + + /* Write single byte-coded instructions into code space. */ + + void genStackDup () ; + void genPop () ; + void genSubtract () ; + void genAdd () ; + void genDivide () ; + void genMultiply () ; + void genModulo () ; + void genNegate () ; + void genNot () ; + void genTwiddle () ; + void genOrOr () ; + void genAndAnd () ; + void genOr () ; + void genAnd () ; + void genXor () ; + void genShiftLeft () ; + void genShiftRight () ; + void genLess () ; + void genLessEqual () ; + void genGreater () ; + void genGreaterEqual () ; + void genNotEqual () ; + void genEqual () ; + void genExchange () ; + + int genPeekJumpIfFalse ( int l ) ; + int genPeekJumpIfTrue ( int l ) ; + int genJumpIfFalse ( int l ) ; + int genJumpIfTrue ( int l ) ; + int genJump ( int l ) ; + + void genGetParameter ( pslAddress var, int argpos ) ; + + int genMakeIntVariable ( const char *s ) ; + int genMakeFloatVariable ( const char *s ) ; + int genMakeStringVariable ( const char *s ) ; + + int genMakeIntArray ( const char *s ) ; + int genMakeFloatArray ( const char *s ) ; + int genMakeStringArray ( const char *s ) ; + + void genConstant ( const char *s ) ; + void genIntConstant ( const char *s ) ; + void genFloatConstant ( const char *s ) ; + void genStringConstant ( const char *s ) ; + void genCharConstant ( char c ) ; + void genIntConstant ( int i ) ; + + void genVoidConstant () ; + + void genFetch () ; + + void genIncrementLValue () ; + void genDecrementLValue () ; + void genIncrementFetch () ; + void genDecrementFetch () ; + + void genVariable ( const char *s, int dimension ) ; + void genAssignment () ; + void genAddAssignment () ; + void genSubAssignment () ; + void genMulAssignment () ; + void genModAssignment () ; + void genDivAssignment () ; + void genAndAssignment () ; + void genOrAssignment () ; + void genXorAssignment () ; + void genSHLAssignment () ; + void genSHRAssignment () ; + + void genCall ( const char *s, int argc ) ; + void genReturn () ; + + /* Expression parsers & code generators. */ + + int genLValue () ; + int genPrimitive () ; + int genBitwiseExpression () ; + int genMultExpression () ; + int genAddExpression () ; + int genShiftExpression () ; + int genRelExpression () ; + int genBoolExpression () ; + int genExpression () ; + + /* Statement-level parsers & code generators. */ + + int genBreakStatement () ; + int genContinueStatement() ; + int genReturnStatement () ; + int genPauseStatement () ; + int genSwitchStatement () ; + int genWhileStatement () ; + int genDoWhileStatement () ; + int genForStatement () ; + int genIfStatement () ; + int genFunctionCall ( const char *s ) ; + int genCompoundStatement() ; + int genStatement () ; + + int genLocalVarDecl ( pslType t ) ; + int genGlobalVarDecl ( const char *fn, pslType t ) ; + int genStaticVarDecl () ; + + /* Top level constructs */ + + int genFunctionDeclaration ( const char *fn ) ; + int genGlobalDeclaration () ; + void genProgram () ; + + /* The symbol tables for variables, code and define's */ + + int next_label ; + int next_code_symbol ; + int next_define ; + + int generate_line_numbers ; + + char *define_token [ MAX_SYMBOL ] ; + char *define_replacement [ MAX_SYMBOL ] ; + + int searchDefines ( const char *s ) const ; + + int skipOverride ; + int skippingFlag ; + int next_skippingLevel ; + + int skipping () const + { + return ! skipOverride && skippingFlag != 0 ; + } + + pslSymbol symtab [ MAX_SYMBOL ] ; + pslSymbol code_symtab [ MAX_SYMBOL ] ; + + pslAddress getVarSymbol ( const char *s ) ; + pslAddress setVarSymbol ( const char *s ) ; + + pslAddress getCodeSymbol ( const char *s, pslAddress fixupLoc ) ; + void setCodeSymbol ( const char *s, pslAddress v ) ; + + int getExtensionSymbol ( const char *s ) const ; + + const pslExtension *extensions ; + + /* Forward references to code symbols that are not yet defined */ + + int next_fwdref ; + pslFwdRef forward_ref [ MAX_SYMBOL ] ; + + int locality_stack [ MAX_NESTING ] ; + int locality_sp ; + + void fixup ( const char *s, pslAddress v ) ; + void addFwdRef ( const char *s, pslAddress where ) ; + void checkUnresolvedSymbols () ; + + int cleanup () ; /* Report errors, etc after a compile */ + + void pushLocality () + { + if ( locality_sp >= MAX_NESTING-1 ) + error ( "Too many nested {}'s" ) ; + else + locality_stack [ locality_sp++ ] = next_var ; + } + + void popLocality () + { + if ( locality_sp <= 0 ) + error ( "Locality stack underflow !!" ) ; + + /* Delete any local symbols */ + + for ( int i = locality_stack [ locality_sp-1 ] ; + i < next_var ; i++ ) + { + delete [] symtab [ i ] . symbol ; + symtab [ i ] . symbol = NULL ; + } + + /* Put the next_var pointer back where it belongs */ + + next_var = locality_stack [ --locality_sp ] ; + } + + /* Ikky stuff to remember where break and continue should jump */ + + int breakToAddressStack [ MAX_LABEL ] ; + int continueToAddressStack [ MAX_LABEL ] ; + int next_break ; + int next_tmp_label ; + int next_continue ; + + void pushBreakToLabel () ; + int pushContinueToLabel () ; + void setContinueToLabel ( int which ) ; + void pushNoContinue () ; + + void popBreakToLabel () ; + void popContinueToLabel () ; + + /* Error and warning handlers */ + + int num_errors ; + int num_warnings ; + + void bumpErrors () { num_errors++ ; } + void bumpWarnings () { num_warnings++ ; } + + int error ( const char *fmt, ... ) ; + int warning ( const char *fmt, ... ) ; + + /* Remember the name of the program for debug purposes */ + + char *progName ; + + char *getProgName () const { return progName ; } + + /* Major storage for symbols and byte-codes */ + + int next_var ; + int next_code ; + pslOpcode *code ; + pslContext *context ; + pslProgram *program ; + +public: + + pslCompiler ( pslProgram *prog, + pslOpcode *_code, + const pslExtension *_extn, + const char *_progName ) + { + ref_count = 1; + program = prog ; + progName = ulStrDup ( _progName ) ; + + generate_line_numbers = FALSE ; + code = _code ; + extensions = _extn ; + + for ( int i = 0 ; i < MAX_SYMBOL ; i++ ) + { + define_token [ i ] = NULL ; + define_replacement [ i ] = NULL ; + symtab [ i ] . symbol = NULL ; + forward_ref [ i ] . symbol = NULL ; + code_symtab [ i ] . symbol = NULL ; + } + + init () ; + } + + ~pslCompiler () + { + for ( int i = 0 ; i < MAX_SYMBOL ; i++ ) + { + delete [] define_token [ i ] ; + delete [] define_replacement [ i ] ; + delete [] symtab [ i ] . symbol ; symtab [ i ] . symbol = NULL ; + delete [] code_symtab [ i ] . symbol ; code_symtab [ i ] . symbol = NULL ; + delete [] forward_ref [ i ] . symbol ; forward_ref [ i ] . symbol = NULL ; + } + } + + void ref() + { + ref_count++; + } + + void deref() + { + ref_count--; + if(ref_count < 1) + { + delete [] code; + delete this; + } + } + + const pslExtension *getExtensions () const { return extensions ; } + + int printInstruction ( FILE *fd, int addr ) const ; + + + void generateLineNumbers () + { + generate_line_numbers = TRUE ; + } + + + void init () + { + int i ; + + for ( i = 0 ; i < MAX_CODE ; i++ ) code [ i ] = OPCODE_HALT ; + + for ( i = 0 ; i < MAX_SYMBOL ; i++ ) + { + delete [] define_token [ i ] ; define_token [ i ] = NULL ; + delete [] define_replacement [ i ] ; define_replacement [ i ] = NULL ; + delete [] symtab [ i ] . symbol ; symtab [ i ] . symbol = NULL ; + delete [] code_symtab [ i ] . symbol ; code_symtab [ i ] . symbol = NULL ; + delete [] forward_ref [ i ] . symbol ; forward_ref [ i ] . symbol = NULL ; + } + + num_errors = num_warnings = 0 ; + + locality_sp = 0 ; + + next_define = 0 ; + next_continue = 0 ; + next_break = 0 ; + next_tmp_label= 0 ; + next_fwdref = 0 ; + next_label = 0 ; + next_code_symbol = 0 ; + next_code = 0 ; + next_var = 0 ; + skippingFlag = 0 ; + next_skippingLevel = 1 ; + } + + void dump () const ; + int compile ( const char *fname ) ; + int compile ( FILE *fd, const char *fname = NULL ) ; + int compile ( const char *memptr, const char *prog_name ) ; +} ; + + diff --git a/src/psl/pslContext.cxx b/src/psl/pslContext.cxx new file mode 100644 index 0000000..7ef8ebf --- /dev/null +++ b/src/psl/pslContext.cxx @@ -0,0 +1,864 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pslContext.cxx 1703 2002-09-22 20:49:05Z ude $ +*/ + + +#include "pslLocal.h" + +pslVariable *pslContext::peekLValue () +{ + return ( stack[sp-2].getInt() == 0 ) ? + & ( variable [ stack[sp-1].getInt() ] ) : + variable [ stack[sp-1].getInt() ] . getIndex ( stack [ sp-3 ].getInt() ) ; +} + + +pslVariable *pslContext::popLValue () +{ + if ( stack[sp-2].getInt() == 0 ) + { + sp -= 2 ; + return & ( variable [ stack[sp+1].getInt() ] ) ; + } + else + { + sp -= 3 ; + return variable [ stack[sp+2].getInt() ] . + getIndex ( stack [ sp ].getInt() ) ; + } +} + + +pslResult pslContext::step () +{ + switch ( code [ pc ] ) + { + case OPCODE_BAD : + error ( "Suspicious opcode 0x00?!", code[pc] ) ; + pc++ ; + return PSL_PROGRAM_END ; + + case OPCODE_LINE_NUMBER : + line_no = code [ pc + 1 ] + ( code [ pc + 2 ] << 8 ) ; + pc+=3 ; + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_PUSH_INT_CONSTANT : + { + int ii ; + + memcpy ( & ii, & code [ pc+1 ], sizeof(int) ) ; + + pushInt ( ii ) ; + + pc += sizeof(int) + 1 ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_PUSH_FLOAT_CONSTANT : + { + float ff ; + + memcpy ( & ff, & code [ pc+1 ], sizeof(float) ) ; + + pushFloat ( ff ) ; + + pc += sizeof(float) + 1 ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_PUSH_STRING_CONSTANT : + { + char *ff = (char *) & code [ pc+1 ] ; + + pushString ( ff ) ; + + pc += strlen ( ff ) + 1 + 1 ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_GET_PARAMETER : + { + int var = code [ ++pc ] ; + int nargs = stack [ sp - 2 ] . getInt () ; + int off = sp - ( nargs + 2 ) + code [ ++pc ] ; + + variable [ var ] . set ( & stack [ off ] ) ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_POP : + popVoid() ; + pc++ ; + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_CALLEXT : + { + int ext = code [ ++pc ] ; + int argc = code [ ++pc ] ; + int required_argc = extensions [ ext ] . argc ; + + if ( required_argc >= 0 && argc != required_argc ) + { + warning ( "Wrong number of parameters for function %s\n", + extensions [ ext ] . symbol ) ; + } + + pslValue argv [ MAX_ARGS ] ; + + /* Pop args off the stack in reverse order */ + + for ( int i = argc-1 ; i >= 0 ; i-- ) + popNumber ( & argv[i] ) ; + + /* Euwww! */ + + pslValue v = (*(extensions [ ext ] . func)) (argc,argv,program) ; + + pushNumber ( & v ) ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_CALL : + pushInt ( pc+4 ) ; + memcpy ( & pc, & code [ pc+1 ], sizeof ( int ) ) ; + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_RETURN : + { + int nargs ; + pslValue result ; + + popNumber ( &result ) ; + pc = popInt () ; + nargs = popInt () ; + popVoid ( nargs ) ; + pushNumber ( &result ) ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_STACK_DUPLICATE : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pushNumber ( v1 ) ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_SUB : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + if ( v1->getType() == PSL_FLOAT || v2->getType() == PSL_FLOAT ) + v2 -> set ( v2 -> getFloat() - v1 -> getFloat() ) ; + else + v2 -> set ( v2 -> getInt() - v1 -> getInt() ) ; + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_SHIFTLEFT : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + v2 -> set ( v2 -> getInt () << v1 -> getInt () ) ; + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_SHIFTRIGHT : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + v2 -> set ( v2 -> getInt () >> v1 -> getInt () ) ; + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_ADD : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + if ( v1->getType() == PSL_FLOAT || v2->getType() == PSL_FLOAT ) + v2 -> set ( v2 -> getFloat() + v1 -> getFloat() ) ; + else + if ( v1->getType() == PSL_STRING && v2->getType() == PSL_STRING ) + { + int v1_len = strlen ( v1 -> getString () ) ; + int v2_len = strlen ( v2 -> getString () ) ; + char *s = new char [ v1_len + v2_len + 1 ] ; + + memcpy ( s, v2 -> getString (), v2_len ) ; + memcpy ( s+v2_len, v1 -> getString (), v1_len+1 ) ; + + v2 -> set ( s ) ; + delete [] s ; + } + else + v2 -> set ( v2 -> getInt () + v1 -> getInt () ) ; + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_NOT : + { + pslValue *v1 = & stack [ sp - 1 ] ; + + v1 -> set ( ! v1 -> getInt () ) ; + + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_TWIDDLE : + { + pslValue *v1 = & stack [ sp - 1 ] ; + + v1 -> set ( ~ v1 -> getInt () ) ; + + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_OROR : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + v2 -> set ( v2 -> getInt () || v1 -> getInt () ) ; + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_ANDAND : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + v2 -> set ( v2 -> getInt () && v1 -> getInt () ) ; + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_OR : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + v2 -> set ( v2 -> getInt () | v1 -> getInt () ) ; + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_AND : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + v2 -> set ( v2 -> getInt () & v1 -> getInt () ) ; + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_XOR : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + v2 -> set ( v2 -> getInt () ^ v1 -> getInt () ) ; + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + + case OPCODE_DIV : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + if ( v1->getType() == PSL_FLOAT || v2->getType() == PSL_FLOAT ) + { + if ( v1 -> getFloat() != 0.0f ) + v2 -> set ( v2 -> getFloat() / v1 -> getFloat() ) ; + else + warning ( "Floating Point Divide by Zero!" ) ; + } + else + { + if ( v1 -> getInt() != 0 ) + v2 -> set ( v2 -> getInt() / v1 -> getInt() ) ; + else + warning ( "Integer Divide by Zero!" ) ; + } + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_MOD : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + if ( v1->getType() == PSL_FLOAT || v2->getType() == PSL_FLOAT ) + { + warning ( "Floating Point Modulo!" ) ; + } + else + { + if ( v1 -> getInt() != 0 ) + v2 -> set ( v2 -> getInt () % v1 -> getInt () ) ; + else + warning ( "Integer Modulo Zero!" ) ; + } + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_MULT : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + if ( v1->getType() == PSL_FLOAT || v2->getType() == PSL_FLOAT ) + v2 -> set ( v2 -> getFloat() * v1 -> getFloat() ) ; + else + v2 -> set ( v2 -> getInt () * v1 -> getInt () ) ; + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_NEG : + { + pslValue *v1 = & stack [ sp - 1 ] ; + + if ( v1->getType() == PSL_FLOAT ) + v1 -> set ( - v1 -> getFloat() ) ; + else + v1 -> set ( - v1 -> getInt () ) ; + + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_LESS : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + if ( v1->getType() == PSL_FLOAT || v2->getType() == PSL_FLOAT ) + v2 -> set ( v2 -> getFloat() < v1 -> getFloat() ) ; + else + v2 -> set ( v2 -> getInt () < v1 -> getInt () ) ; + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_LESSEQUAL : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + if ( v1->getType() == PSL_FLOAT || v2->getType() == PSL_FLOAT ) + v2 -> set ( v2 -> getFloat() <= v1 -> getFloat() ) ; + else + v2 -> set ( v2 -> getInt () <= v1 -> getInt () ) ; + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_GREATER : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + if ( v1->getType() == PSL_FLOAT || v2->getType() == PSL_FLOAT ) + v2 -> set ( v2 -> getFloat() > v1 -> getFloat() ) ; + else + v2 -> set ( v2 -> getInt () > v1 -> getInt () ) ; + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_GREATEREQUAL : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + if ( v1->getType() == PSL_FLOAT || v2->getType() == PSL_FLOAT ) + v2 -> set ( v2 -> getFloat() >= v1 -> getFloat() ) ; + else + v2 -> set ( v2 -> getInt () >= v1 -> getInt () ) ; + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_NOTEQUAL : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + if ( v1->getType() == PSL_FLOAT || v2->getType() == PSL_FLOAT ) + v2 -> set ( v2 -> getFloat() != v1 -> getFloat() ) ; + else + v2 -> set ( v2 -> getInt () != v1 -> getInt () ) ; + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_EQUAL : + { + pslValue *v1 = & stack [ sp - 1 ] ; + pslValue *v2 = & stack [ sp - 2 ] ; + + if ( v1->getType() == PSL_FLOAT || v2->getType() == PSL_FLOAT ) + v2 -> set ( v2 -> getFloat() == v1 -> getFloat() ) ; + else + v2 -> set ( v2 -> getInt () == v1 -> getInt () ) ; + + popVoid () ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_PAUSE : + pc++ ; + return PSL_PROGRAM_PAUSE ; + + case OPCODE_HALT : + return PSL_PROGRAM_END ; /* Note: PC is *NOT* incremented. */ + + case OPCODE_PEEK_JUMP_TRUE : + if ( peekInt () ) + pc = code [ pc + 1 ] + ( code [ pc + 2 ] << 8 ) ; + else + { + sp-- ; + pc += 3 ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_PEEK_JUMP_FALSE : + if ( peekInt () ) + { + sp-- ; + pc += 3 ; + } + else + pc = code [ pc + 1 ] + ( code [ pc + 2 ] << 8 ) ; + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_JUMP_TRUE : + if ( popInt () ) + pc = code [ pc + 1 ] + ( code [ pc + 2 ] << 8 ) ; + else + pc += 3 ; + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_JUMP_FALSE : + if ( popInt () ) + pc += 3 ; + else + pc = code [ pc + 1 ] + ( code [ pc + 2 ] << 8 ) ; + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_JUMP : + pc = code [ pc + 1 ] + ( code [ pc + 2 ] << 8 ) ; + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_PUSH_VARIABLE : + pushNumber ( & variable [ code[++pc] ] ) ; + pc++ ; + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_EXCHANGE : + { + pslValue n = stack [ sp - 1 ] ; + stack [ sp - 1 ] = stack [ sp - 2 ] ; + stack [ sp - 2 ] = n ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_POP_ADD_VARIABLE : + { + pslValue *s = & stack[--sp] ; + pslVariable *v = popLValue () ; + + if ( v -> getType () == PSL_INT ) + v -> set ( v -> getInt() + s -> getInt() ) ; + else + if ( v -> getType () == PSL_STRING ) + { + int s1_len = strlen ( v -> getString () ) ; + int s2_len = strlen ( s -> getString () ) ; + char *str = new char [ s1_len + s2_len + 1 ] ; + + memcpy ( str, v -> getString (), s1_len ) ; + memcpy ( str+s1_len, s -> getString (), s2_len+1 ) ; + + v -> set ( str ) ; + delete [] str ; + } + else + v -> set ( v -> getFloat() + s -> getFloat() ) ; + + pc++ ; + pushNumber ( v ) ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_POP_SUB_VARIABLE : + { + pslValue *s = & stack[--sp] ; + pslVariable *v = popLValue () ; + + if ( v -> getType () == PSL_INT ) + v -> set ( v -> getInt() - s -> getInt() ) ; + else + v -> set ( v -> getFloat() - s -> getFloat() ) ; + + pc++ ; + pushNumber ( v ) ; + } + return PSL_PROGRAM_CONTINUE ; + + + case OPCODE_POP_MUL_VARIABLE : + { + pslValue *s = & stack[--sp] ; + pslVariable *v = popLValue () ; + + if ( v -> getType () == PSL_INT ) + v -> set ( v -> getInt() * s -> getInt() ) ; + else + v -> set ( v -> getFloat() * s -> getFloat() ) ; + + pc++ ; + pushNumber ( v ) ; + } + return PSL_PROGRAM_CONTINUE ; + + + case OPCODE_POP_MOD_VARIABLE : + { + pslValue *s = & stack[--sp] ; + pslVariable *v = popLValue () ; + + if ( v -> getType () == PSL_INT ) + { + if ( s -> getInt () != 0 ) + v -> set ( v -> getInt() % s -> getInt() ) ; + else + warning ( "Integer Modulo by Zero!" ) ; + } + else + warning ( "Floating Point Modulo!" ) ; + + pc++ ; + pushNumber ( v ) ; + } + return PSL_PROGRAM_CONTINUE ; + + + case OPCODE_POP_DIV_VARIABLE : + { + pslValue *s = & stack[--sp] ; + pslVariable *v = popLValue () ; + + if ( v -> getType () == PSL_INT ) + { + if ( s -> getInt () != 0 ) + v -> set ( v -> getInt() / s -> getInt() ) ; + else + warning ( "Integer Divide by Zero!" ) ; + } + else + { + if ( s -> getFloat () != 0.0f ) + v -> set ( v -> getFloat() / s -> getFloat() ) ; + else + warning ( "Floating Point Divide by Zero!" ) ; + } + + pc++ ; + pushNumber ( v ) ; + } + return PSL_PROGRAM_CONTINUE ; + + + case OPCODE_POP_AND_VARIABLE : + { + pslValue *s = & stack[--sp] ; + pslVariable *v = popLValue () ; + + v -> set ( v -> getInt() & s -> getInt() ) ; + + pc++ ; + pushNumber ( v ) ; + } + return PSL_PROGRAM_CONTINUE ; + + + case OPCODE_POP_OR_VARIABLE : + { + pslValue *s = & stack[--sp] ; + pslVariable *v = popLValue () ; + + v -> set ( v -> getInt() | s -> getInt() ) ; + + pc++ ; + pushNumber ( v ) ; + } + return PSL_PROGRAM_CONTINUE ; + + + case OPCODE_POP_XOR_VARIABLE : + { + pslValue *s = & stack[--sp] ; + pslVariable *v = popLValue () ; + + v -> set ( v -> getInt() ^ s -> getInt() ) ; + + pc++ ; + pushNumber ( v ) ; + } + return PSL_PROGRAM_CONTINUE ; + + + case OPCODE_POP_SHL_VARIABLE : + { + pslValue *s = & stack[--sp] ; + pslVariable *v = popLValue () ; + + v -> set ( v -> getInt() << s -> getInt() ) ; + + pc++ ; + pushNumber ( v ) ; + } + return PSL_PROGRAM_CONTINUE ; + + + case OPCODE_POP_SHR_VARIABLE : + { + pslValue *s = & stack[--sp] ; + pslVariable *v = popLValue () ; + + v -> set ( v -> getInt() >> s -> getInt() ) ; + + pc++ ; + pushNumber ( v ) ; + } + return PSL_PROGRAM_CONTINUE ; + + + case OPCODE_POP_VARIABLE : + { + pslValue *s = & stack[--sp] ; + pslVariable *v = popLValue () ; + + if ( v -> getType () == PSL_INT ) + v -> set ( s -> getInt () ) ; + else + if ( v -> getType () == PSL_FLOAT ) + v -> set ( s -> getFloat () ) ; + else + v -> set ( s -> getString () ) ; + + pc++ ; + pushNumber ( v ) ; + } + return PSL_PROGRAM_CONTINUE ; + + + case OPCODE_SET_INT_ARRAY : + variable [ code[++pc] ] . setArrayType ( PSL_INT, + stack[--sp].getInt() ) ; + pc++ ; + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_SET_FLOAT_ARRAY : + variable [ code[++pc] ] . setArrayType ( PSL_FLOAT, + stack[--sp].getInt() ) ; + pc++ ; + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_SET_STRING_ARRAY : + variable [ code[++pc] ] . setArrayType ( PSL_STRING, + stack[--sp].getInt() ) ; + pc++ ; + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_SET_INT_VARIABLE : + { + pslVariable *v = & ( variable [ code[++pc] ] ) ; + v -> setType ( PSL_INT ) ; + v -> set ( 0 ) ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_SET_FLOAT_VARIABLE : + { + pslVariable *v = & ( variable [ code[++pc] ] ) ; + v -> setType ( PSL_FLOAT ) ; + v -> set ( 0.0f ) ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_SET_STRING_VARIABLE : + { + pslVariable *v = & ( variable [ code[++pc] ] ) ; + v -> setType ( PSL_STRING ) ; + v -> set ( "" ) ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_FETCH : + { + pslVariable *v = popLValue () ; + pushNumber ( v ) ; + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_INCREMENT_LVALUE : + { + pslVariable *v = peekLValue () ; + + if ( v -> getType () == PSL_INT ) + v -> set ( v -> getInt () + 1 ) ; + else + v -> set ( v -> getFloat () + 1 ) ; + + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_DECREMENT_LVALUE : + { + pslVariable *v = peekLValue () ; + + if ( v -> getType () == PSL_INT ) + v -> set ( v -> getInt () - 1 ) ; + else + v -> set ( v -> getFloat () - 1 ) ; + + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_INCREMENT_FETCH : + { + pslVariable *v = popLValue () ; + pushNumber ( v ) ; + + if ( v -> getType () == PSL_INT ) + v -> set ( v -> getInt () + 1 ) ; + else + v -> set ( v -> getFloat () + 1 ) ; + + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + case OPCODE_DECREMENT_FETCH : + { + pslVariable *v = popLValue () ; + pushNumber ( v ) ; + + if ( v -> getType () == PSL_INT ) + v -> set ( v -> getInt () - 1 ) ; + else + v -> set ( v -> getFloat () - 1 ) ; + + pc++ ; + } + return PSL_PROGRAM_CONTINUE ; + + + default : + error ( "Suspicious opcode 0x02x?!", code[pc] ) ; + return PSL_PROGRAM_END ; + } +} + + +void pslContext::printStack ( FILE *fd ) const +{ + fprintf ( fd, "STACK [%d deep] : ", sp ) ; + + if ( sp >= 8 ) fprintf ( stderr, "..." ) ; + + for ( int i = (sp<8)? 0 : (sp-8) ; i < sp ; i++ ) + switch ( stack[i].getType () ) + { + case PSL_INT : fprintf ( fd, "%d " , stack[i].getInt () ) ; break ; + case PSL_FLOAT : fprintf ( fd, "%gf " , stack[i].getFloat () ) ; break ; + case PSL_STRING : fprintf ( fd, "'%s' ", stack[i].getString() ) ; break ; + case PSL_VOID : fprintf ( fd, " " ) ; break ; + } + + fprintf ( fd, "\n" ) ; +} + + diff --git a/src/psl/pslContext.h b/src/psl/pslContext.h new file mode 100644 index 0000000..02bb9c4 --- /dev/null +++ b/src/psl/pslContext.h @@ -0,0 +1,106 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pslContext.h 1703 2002-09-22 20:49:05Z ude $ +*/ + + +class pslContext +{ + pslOpcode *code ; + const pslExtension *extensions ; + pslProgram *program ; + + pslVariable variable [ MAX_VARIABLE ] ; + pslValue stack [ MAX_STACK ] ; + int sp ; + pslAddress pc ; + + int num_errors ; + int num_warnings ; + int line_no ; + + void bumpErrors () { num_errors++ ; } + void bumpWarnings () { num_warnings++ ; } + + char *getProgName () const { return program -> getProgName () ; } + + void error ( const char *fmt, ... ) ; + void warning ( const char *fmt, ... ) ; + + pslVariable *popLValue () ; + pslVariable *peekLValue () ; + +public: + + pslContext ( pslProgram *p ) + { + code = p -> getCode () ; + extensions = p -> getExtensions () ; + program = p ; + + reset () ; + } + + ~pslContext () {} ; + + int getLineNo () const { return line_no ; } + + void printStack ( FILE *fd ) const ; + + void pushInt ( int x ) { stack [ sp++ ] . set ( x ) ; } + void pushFloat ( float x ) { stack [ sp++ ] . set ( x ) ; } + void pushString ( const char *x ) { stack [ sp++ ] . set ( x ) ; } + void pushNumber ( const pslNumber *x ) { stack [ sp++ ] . set ( x ) ; } + + int peekInt () const { return stack [ sp-1 ] . getInt () ; } + float peekFloat () const { return stack [ sp-1 ] . getFloat () ; } + char *peekString () const { return stack [ sp-1 ] . getString () ; } + + void popVoid ( int n = 1 ) { sp -= n ; } + int popInt () { return stack [ --sp ] . getInt () ; } + float popFloat () { return stack [ --sp ] . getFloat () ; } + char *popString () { return stack [ --sp ] . getString () ; } + + void popNumber ( pslNumber *v ) { v -> set ( & stack [ --sp ] ) ; } + + pslResult step () ; + + pslResult trace () + { + if ( program -> getStackTraceFlag () ) printStack ( stdout ) ; + program -> getCompiler () -> printInstruction ( stdout, pc ) ; + fflush ( stdout ) ; + return step () ; + } + + void reset () + { + for ( int i = 0 ; i < MAX_VARIABLE ; i++ ) + variable [ i ] . reset () ; + + line_no = -1 ; + + sp = 0 ; + pc = 0 ; + } +} ; + + diff --git a/src/psl/pslDump.cxx b/src/psl/pslDump.cxx new file mode 100644 index 0000000..7f645bd --- /dev/null +++ b/src/psl/pslDump.cxx @@ -0,0 +1,288 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pslDump.cxx 1700 2002-09-22 18:25:16Z sjbaker $ +*/ + + +#include "pslLocal.h" + + +struct OpcodeDecode +{ + const char *s ; + unsigned char opcode ; + int numArgBytes ; +} ; + + + +static const OpcodeDecode opcodeDecode [] = +{ + { "**BAD_INSTRUCTION**", OPCODE_BAD , 0 }, + + { "SOURCE LINE NUMBER:", OPCODE_LINE_NUMBER, 2 }, + + /* Stack operations */ + + { "PUSH_INT_CONSTANT" , OPCODE_PUSH_INT_CONSTANT , sizeof(int) }, + { "PUSH_FLOAT_CONSTANT", OPCODE_PUSH_FLOAT_CONSTANT, sizeof(float) }, + { "PUSH_STRING_CONSTANT",OPCODE_PUSH_STRING_CONSTANT, 0 }, + { "PUSH_VARIABLE" , OPCODE_PUSH_VARIABLE , 1 }, + + { "STACK_DUPLICATE" , OPCODE_STACK_DUPLICATE , 0 }, + + { "POP_VARIABLE" , OPCODE_POP_VARIABLE , 0 }, + { "POP" , OPCODE_POP , 0 }, + + { "FETCH" , OPCODE_FETCH , 0 }, + { "INCREMENT_FETCH" , OPCODE_INCREMENT_FETCH , 0 }, + { "DECREMENT_FETCH" , OPCODE_DECREMENT_FETCH , 0 }, + { "INCREMENT_LVALUE" , OPCODE_INCREMENT_LVALUE , 0 }, + { "DECREMENT_LVALUE" , OPCODE_DECREMENT_LVALUE , 0 }, + + /* Variable creation */ + + { "SET_INT_ARRAY" , OPCODE_SET_INT_ARRAY , 1 }, + { "SET_FLOAT_ARRAY" , OPCODE_SET_FLOAT_ARRAY , 1 }, + { "SET_STRING_ARRAY" , OPCODE_SET_STRING_ARRAY , 1 }, + { "SET_INT_VARIABLE" , OPCODE_SET_INT_VARIABLE , 1 }, + { "SET_FLOAT_VARIABLE" , OPCODE_SET_FLOAT_VARIABLE , 1 }, + { "SET_STRING_VARIABLE", OPCODE_SET_STRING_VARIABLE, 1 }, + { "GET_PARAMETER" , OPCODE_GET_PARAMETER , 2 }, + + /* Flow Control */ + + { "CALLEXT", OPCODE_CALLEXT , 2 }, + { "CALL", OPCODE_CALL , 3 }, + { "RETURN", OPCODE_RETURN , 0 }, + { "PEEK_JUMP_FALSE", OPCODE_PEEK_JUMP_FALSE, 2 }, + { "PEEK_JUMP_TRUE", OPCODE_PEEK_JUMP_TRUE , 2 }, + { "JUMP_FALSE", OPCODE_JUMP_FALSE , 2 }, + { "JUMP_TRUE", OPCODE_JUMP_TRUE , 2 }, + { "JUMP", OPCODE_JUMP , 2 }, + { "PAUSE", OPCODE_PAUSE , 0 }, + { "HALT", OPCODE_HALT , 0 }, + + /* Math operators */ + + { "SUB", OPCODE_SUB , 0 }, + { "ADD", OPCODE_ADD , 0 }, + { "DIV", OPCODE_DIV , 0 }, + { "MULT", OPCODE_MULT , 0 }, + { "MOD", OPCODE_MOD , 0 }, + { "NEG", OPCODE_NEG , 0 }, + { "EXCHG", OPCODE_EXCHANGE , 0 }, + + /* Bitwise operators */ + + { "NOT", OPCODE_NOT , 0 }, + { "TWIDDLE", OPCODE_TWIDDLE , 0 }, + + { "OROR", OPCODE_OROR , 0 }, + { "ANDAND", OPCODE_ANDAND , 0 }, + + { "OR", OPCODE_OR , 0 }, + { "AND", OPCODE_AND , 0 }, + { "XOR", OPCODE_XOR , 0 }, + + { "SHIFT_LEFT", OPCODE_SHIFTLEFT , 0 }, + { "SHIFT_RIGHT", OPCODE_SHIFTRIGHT , 0 }, + + /* Boolean operators */ + + { "LESS", OPCODE_LESS , 0 }, + { "LESSEQUAL", OPCODE_LESSEQUAL , 0 }, + { "GREATER", OPCODE_GREATER , 0 }, + { "GREATEREQUAL", OPCODE_GREATEREQUAL, 0 }, + { "NOTEQUAL", OPCODE_NOTEQUAL , 0 }, + { "EQUAL", OPCODE_EQUAL , 0 }, + + { "POP_ADD_VARIABLE", OPCODE_POP_ADD_VARIABLE, 0 }, + { "POP_SUB_VARIABLE", OPCODE_POP_SUB_VARIABLE, 0 }, + { "POP_MUL_VARIABLE", OPCODE_POP_MUL_VARIABLE, 0 }, + { "POP_MOD_VARIABLE", OPCODE_POP_MOD_VARIABLE, 0 }, + { "POP_DIV_VARIABLE", OPCODE_POP_DIV_VARIABLE, 0 }, + { "POP_AND_VARIABLE", OPCODE_POP_AND_VARIABLE, 0 }, + { "POP_OR_VARIABLE" , OPCODE_POP_OR_VARIABLE , 0 }, + { "POP_XOR_VARIABLE", OPCODE_POP_XOR_VARIABLE, 0 }, + { "POP_SHL_VARIABLE", OPCODE_POP_SHL_VARIABLE, 0 }, + { "POP_SHR_VARIABLE", OPCODE_POP_SHR_VARIABLE, 0 }, + + { NULL, 0, 0 } +} ; + + +int pslCompiler::printOpcode ( FILE *fd, int addr ) const +{ + fprintf ( fd, "%3d: 0x%02x ", addr, (unsigned int)( code [ addr ] ) ) ; + + unsigned char op = code [ addr ] ; + + for ( int i = 0 ; opcodeDecode [ i ] . s != NULL ; i++ ) + if ( opcodeDecode [ i ] . opcode == op ) + { + for ( int j = 0 ; j < 4 ; j++ ) + if ( j < opcodeDecode [ i ] . numArgBytes ) + fprintf ( fd, "0x%02x ", code [ addr + j + 1 ] ) ; + else + fprintf ( fd, " " ) ; + + fprintf ( fd, " %s", opcodeDecode [ i ] . s ) ; + return 1 + opcodeDecode [ i ] . numArgBytes ; + } + + fprintf ( fd, "**** UNRECOGNISED OPCODE **** " ) ; + return 1 ; +} + + +void pslCompiler::dump () const +{ + int i ; + + printf ( "\n" ) ; + printf ( "Bytecode:\n" ) ; + + for ( i = 0 ; i < next_code ; ) + i += printInstruction ( stdout, i ) ; + + printf ( "\n" ) ; + printf ( "Global Variables:\n" ) ; + + for ( i = 0 ; i < MAX_SYMBOL ; i++ ) + if ( symtab [ i ] . symbol != NULL ) + { + printf ( "\t%5s => %4d", symtab[i].symbol, + symtab[i].address ) ; + + if ( i & 1 ) + printf ( "\n" ) ; + else + printf ( " " ) ; + } + + printf ( "\n" ) ; + printf ( "Functions:\n" ) ; + + for ( i = 0 ; i < MAX_SYMBOL ; i++ ) + if ( code_symtab [ i ] . symbol != NULL ) + { + printf ( "\t%5s => %4d", code_symtab[i].symbol, + code_symtab[i].address ) ; + + if ( i & 1 ) + printf ( "\n" ) ; + else + printf ( " " ) ; + } + + printf ( "\n" ) ; + + if ( num_errors > 0 ) + printf ( "PROGRAM FAILED TO COMPILE WITH %d WARNINGS AND %d ERRORS\n", + num_warnings, num_errors ) ; + else + if ( num_warnings > 0 ) + printf ( "PROGRAM COMPILED WITH %d WARNINGS\n", num_warnings ) ; + else + printf ( "PROGRAM COMPILED OK\n" ) ; + + printf ( "\n" ) ; +} + + +int pslCompiler::printInstruction ( FILE *fd, int addr ) const +{ + int skip = printOpcode ( fd, addr ) ; + + switch ( code [ addr ] ) + { + case OPCODE_LINE_NUMBER : + fprintf ( fd, "%d =====================", + code[addr+1] + ( code[addr+2] << 8 ) ) ; + break ; + + case OPCODE_SET_INT_ARRAY : + case OPCODE_SET_FLOAT_ARRAY : + case OPCODE_SET_STRING_ARRAY : + case OPCODE_SET_INT_VARIABLE : + case OPCODE_SET_FLOAT_VARIABLE : + case OPCODE_SET_STRING_VARIABLE : + case OPCODE_PUSH_VARIABLE : + fprintf ( fd, "\t\t[%d]", code [ addr+1 ] ) ; + break ; + + case OPCODE_GET_PARAMETER : + fprintf ( fd, "\t\t[%d],off=%d", code [ addr+1 ], code [ addr+2 ] ) ; + break ; + + case OPCODE_PUSH_INT_CONSTANT : + { + int f ; + memcpy ( &f, &code[addr+1], sizeof(int) ) ; + fprintf ( fd, "\t%d", f ) ; + } + break ; + + case OPCODE_PUSH_FLOAT_CONSTANT : + { + float f ; + memcpy ( &f, &code[addr+1], sizeof(float) ) ; + fprintf ( fd, "\t%f", f ) ; + } + break ; + + case OPCODE_PUSH_STRING_CONSTANT : + { + fprintf ( fd, "\t\"%s\"", &code[addr+1] ) ; + skip += strlen ( (char *) &code[addr+1] ) + 1 ; + } + break ; + + case OPCODE_CALLEXT : + fprintf ( fd, "\t\t\t%s,nargs=%d", + extensions[code[addr+1]].symbol, code[addr+2] ); + break ; + + case OPCODE_CALL : + fprintf ( fd, "\t\t\t%d,nargs=%d", code[addr+1] + ( code[addr+2] << 8 ), + code[addr+3] ) ; + break ; + + case OPCODE_PEEK_JUMP_FALSE : + case OPCODE_PEEK_JUMP_TRUE : + case OPCODE_JUMP_FALSE : + case OPCODE_JUMP_TRUE : + fprintf ( fd, "\t\t%d", code[addr+1] + ( code[addr+2] << 8 ) ) ; + break ; + + case OPCODE_JUMP : + fprintf ( fd, "\t\t\t%d", code[addr+1] + ( code[addr+2] << 8 ) ) ; + break ; + + default : break ; + } + + fprintf ( fd, "\n" ) ; + return skip ; +} + + diff --git a/src/psl/pslError.cxx b/src/psl/pslError.cxx new file mode 100644 index 0000000..2ef7f56 --- /dev/null +++ b/src/psl/pslError.cxx @@ -0,0 +1,126 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pslError.cxx 1685 2002-09-15 14:32:53Z ude $ +*/ + + +#include "pslLocal.h" + +static char _pslErrorBuffer [ 1024 ] = { '\0' } ; + + +void (*_pslErrorCB) ( pslProgram *p, int severity, const char *progname, + int line_no , const char *message ) = NULL ; + + +void pslSetErrorCallback ( void (*CB) ( pslProgram *, int, const char *, + int, const char * ) ) +{ + _pslErrorCB = CB ; +} + + + +int pslCompiler::warning ( const char *fmt, ... ) +{ + va_list argp; + va_start ( argp, fmt ) ; + vsprintf ( _pslErrorBuffer, fmt, argp ) ; + va_end ( argp ) ; + + if ( _pslErrorCB != NULL ) + (*_pslErrorCB)( program, PSL_COMPILETIME_WARNING, + _pslGetFname(), _pslGetLineNo(), _pslErrorBuffer ) ; + else + fprintf ( stderr, "PSL: \"%s\" line %3d: WARNING - %s\n", + _pslGetFname(), _pslGetLineNo(), _pslErrorBuffer ) ; + + bumpWarnings () ; + return FALSE ; +} + + + +int pslCompiler::error ( const char *fmt, ... ) +{ + va_list argp; + va_start ( argp, fmt ) ; + vsprintf ( _pslErrorBuffer, fmt, argp ) ; + va_end ( argp ) ; + + if ( _pslErrorCB != NULL ) + (*_pslErrorCB)( program, PSL_COMPILETIME_ERROR, + _pslGetFname(), _pslGetLineNo(), _pslErrorBuffer ) ; + else + fprintf ( stderr, "PSL: \"%s\" line %3d: *ERROR* - %s\n", + _pslGetFname(), _pslGetLineNo(), _pslErrorBuffer ) ; + + bumpErrors () ; + return FALSE ; +} + + + +void pslContext::warning ( const char *fmt, ... ) +{ + va_list argp; + va_start ( argp, fmt ) ; + vsprintf ( _pslErrorBuffer, fmt, argp ) ; + va_end ( argp ) ; + + if ( _pslErrorCB != NULL ) + (*_pslErrorCB)( program, PSL_RUNTIME_WARNING, + getProgName(), getLineNo(), _pslErrorBuffer ) ; + else + if ( getLineNo () >= 0 ) + fprintf ( stderr, "PSL: \"%s\" Line %d: WARNING - %s\n", + getProgName(), getLineNo(), _pslErrorBuffer ) ; + else + fprintf ( stderr, "PSL: \"%s\": WARNING - %s\n", + getProgName(), _pslErrorBuffer ) ; + + bumpWarnings () ; +} + + + +void pslContext::error ( const char *fmt, ... ) +{ + va_list argp; + va_start ( argp, fmt ) ; + vsprintf ( _pslErrorBuffer, fmt, argp ) ; + va_end ( argp ) ; + + if ( _pslErrorCB != NULL ) + (*_pslErrorCB)( program, PSL_RUNTIME_ERROR, + getProgName(), getLineNo(), _pslErrorBuffer ) ; + else + if ( getLineNo () >= 0 ) + fprintf ( stderr, "PSL: \"%s\" Line %d: *ERROR* - %s\n", + getProgName(), getLineNo(), _pslErrorBuffer ) ; + else + fprintf ( stderr, "PSL: \"%s\": *ERROR* - %s\n", + getProgName(), _pslErrorBuffer ) ; + + bumpErrors () ; +} + + diff --git a/src/psl/pslExpression.cxx b/src/psl/pslExpression.cxx new file mode 100644 index 0000000..3fb7792 --- /dev/null +++ b/src/psl/pslExpression.cxx @@ -0,0 +1,519 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pslExpression.cxx 1700 2002-09-22 18:25:16Z sjbaker $ +*/ + + +#include "pslLocal.h" + + + +int pslCompiler::genLValue () +{ + /* + Expect: + + variable ...or... + arrayname [ expression ] ...or... + structure . lvalue ...or... + structure -> lvalue + */ + + char c [ MAX_TOKEN ] ; + char n [ MAX_TOKEN ] ; + getToken ( c ) ; + getToken ( n ) ; + + int isArray = ( n[0] == '[' ) ; + int isStruct = ( strcmp ( n, "." ) == 0 || + strcmp ( n, "->" ) == 0 ) ; + + if ( ! isArray && ! isStruct ) + { + ungetToken ( n ) ; + genVariable ( c, FALSE ) ; + return TRUE ; + } + + if ( isStruct ) + return error ( "Structures are not supported yet." ) ; + + /* An array + index */ + + if ( ! genExpression () ) + return error ( "Missing expression for array index." ) ; + + getToken ( n ) ; + + if ( n[0] != ']' ) + return error ( "Missing ']' after array index." ) ; + + genVariable ( c, TRUE ) ; + return TRUE ; +} + + + + +int pslCompiler::genPrimitive () +{ + /* Expect: + + 'x' ...or... + "xxxxxx" ...or... + number ...or... + ( expression ) ...or... + + primitive ...or... + - primitive ...or... + ! primitive ...or... + ~ primitive ...or... + ++ lvalue ...or... + -- lvalue ...or... + function ( expression ) ...or... + lvalue ...or... + lvalue ++ ...or... + lvalue -- ...or... + lvalue = expression ...or... + lvalue += expression ...or... + lvalue -= expression + (etc) + */ + + char c [ MAX_TOKEN ] ; + getToken ( c ) ; + + /* Constant ? */ + + if ( c [ 0 ] == '\'' ) { genCharConstant ( c [ 1 ] ) ; return TRUE ; } + if ( c [ 0 ] == '"' ) { genStringConstant ( & c [ 1 ] ) ; return TRUE ; } + if ((c [ 0 ] == '.' && c [ 1 ] != '\0' ) || + isdigit ( c[0] ) ) { genConstant ( c ) ; return TRUE ; } + + + /* Bracketed expression */ + + if ( strcmp ( c, "(" ) == 0 ) + { + if ( ! genExpression () ) + { + ungetToken ( c ) ; + return error ( "Missing expression after '('" ) ; + } + + getToken ( c ) ; + + if ( strcmp ( c, ")" ) != 0 ) + { + ungetToken ( c ) ; + return error ( "Missing ')' (found '%s')", c ); + } + + return TRUE ; + } + + /* Various unary operators */ + + if ( strcmp ( c, "+" ) == 0 ) /* Skip over redundant unary '+' symbol */ + { + if ( genPrimitive () ) { /* Nothing */ return TRUE ; } + else { ungetToken ( c ) ; return FALSE ; } + } + + if ( strcmp ( c, "-" ) == 0 ) /* Unary '-' symbol */ + { + if ( genPrimitive () ) { genNegate () ; return TRUE ; } + else { ungetToken ( c ) ; return FALSE ; } + } + + if ( strcmp ( c, "!" ) == 0 ) /* Unary '!' symbol */ + { + if ( genPrimitive () ) { genNot () ; return TRUE ; } + else { ungetToken ( c ) ; return FALSE ; } + } + + if ( strcmp ( c, "~" ) == 0 ) /* Unary '~' symbol */ + { + if ( genPrimitive () ) { genTwiddle () ; return TRUE ; } + else { ungetToken ( c ) ; return FALSE ; } + } + + /* Pre-increment and pre-decrement */ + + if ( strcmp ( c, "++" ) == 0 ) + { + genLValue () ; + genIncrementLValue () ; + genFetch () ; + return TRUE ; + } + + if ( strcmp ( c, "--" ) == 0 ) + { + genLValue () ; + genDecrementLValue () ; + genFetch () ; + return TRUE ; + } + + /* Something illegal ?!? */ + + if ( ! isalpha ( c [ 0 ] ) && c [ 0 ] != '_' ) + { + ungetToken ( c ) ; + return FALSE ; + } + + /* + An LValue or a function call... + */ + + char n [ MAX_TOKEN ] ; + getToken ( n ) ; + + if ( n[0] == '(' ) + { + ungetToken ( n ) ; + genFunctionCall ( c ) ; + return TRUE ; + } + + /* + An LValue. + */ + + ungetToken ( n ) ; + ungetToken ( c ) ; + + if ( ! genLValue () ) + return error ( "Illegal expression." ) ; + + getToken ( n ) ; + + if ( strcmp ( n, "++" ) == 0 ) + { genIncrementFetch () ; return TRUE ; } + + if ( strcmp ( n, "--" ) == 0 ) + { genDecrementFetch () ; return TRUE ; } + + if ( strcmp ( n, "=" ) == 0 ) + { if ( genExpression () ) { genAssignment () ; return TRUE ; } + else return FALSE ; } + + if ( strcmp ( n, "+=" ) == 0 ) + { if ( genExpression () ) { genAddAssignment () ; return TRUE ; } + else return FALSE ; } + + if ( strcmp ( n, "-=" ) == 0 ) + { if ( genExpression () ) { genSubAssignment () ; return TRUE ; } + else return FALSE ; } + + if ( strcmp ( n, "*=" ) == 0 ) + { if ( genExpression () ) { genMulAssignment () ; return TRUE ; } + else return FALSE ; } + + if ( strcmp ( n, "%=" ) == 0 ) + { if ( genExpression () ) { genModAssignment () ; return TRUE ; } + else return FALSE ; } + + if ( strcmp ( n, "/=" ) == 0 ) + { if ( genExpression () ) { genDivAssignment () ; return TRUE ; } + else return FALSE ; } + + if ( strcmp ( n, "&=" ) == 0 ) + { if ( genExpression () ) { genAndAssignment () ; return TRUE ; } + else return FALSE ; } + + if ( strcmp ( n, "|=" ) == 0 ) + { if ( genExpression () ) { genOrAssignment () ; return TRUE ; } + else return FALSE ; } + + if ( strcmp ( n, "^=" ) == 0 ) + { if ( genExpression () ) { genXorAssignment () ; return TRUE ; } + else return FALSE ; } + + if ( strcmp ( n, "<<=" ) == 0 ) + { if ( genExpression () ) { genSHLAssignment () ; return TRUE ; } + else return FALSE ; } + + if ( strcmp ( n, ">>=" ) == 0 ) + { if ( genExpression () ) { genSHRAssignment () ; return TRUE ; } + else return FALSE ; } + + ungetToken ( n ) ; + genFetch () ; + return TRUE ; +} + + + +int pslCompiler::genMultExpression () +{ + /* Expect: + + primitive ...or... + primitive * primitive + primitive / primitive + primitive % primitive + */ + + if ( ! genPrimitive () ) + return FALSE ; + + while ( TRUE ) + { + char c [ MAX_TOKEN ] ; + + getToken ( c ) ; + + if ( strcmp ( c, "*" ) != 0 && + strcmp ( c, "/" ) != 0 && + strcmp ( c, "%" ) != 0 ) + { + ungetToken ( c ) ; + return TRUE ; + } + + if ( ! genPrimitive () ) + return FALSE ; + + if ( strcmp ( c, "*" ) == 0 ) + genMultiply () ; + else + if ( strcmp ( c, "/" ) == 0 ) + genDivide () ; + else + genModulo () ; + } +} + + + + +int pslCompiler::genAddExpression () +{ + /* Expect: + + multExp ...or... + multExp + multExp + multExp - multExp + */ + + if ( ! genMultExpression () ) + return FALSE ; + + while ( TRUE ) + { + char c [ MAX_TOKEN ] ; + + getToken ( c ) ; + + if ( strcmp ( c, "+" ) != 0 && + strcmp ( c, "-" ) != 0 ) + { + ungetToken ( c ) ; + return TRUE ; + } + + if ( ! genMultExpression () ) + return FALSE ; + + if ( strcmp ( c, "+" ) == 0 ) + genAdd () ; + else + genSubtract () ; + } +} + + + + +int pslCompiler::genShiftExpression () +{ + /* Expect: + + addExp ...or... + addExp << addExp + addExp >> addExp + */ + + if ( ! genAddExpression () ) + return FALSE ; + + while ( TRUE ) + { + char c [ MAX_TOKEN ] ; + + getToken ( c ) ; + + if ( strcmp ( c, "<<" ) != 0 && + strcmp ( c, ">>" ) != 0 ) + { + ungetToken ( c ) ; + return TRUE ; + } + + if ( ! genAddExpression () ) + return FALSE ; + + if ( strcmp ( c, "<<" ) == 0 ) + genShiftLeft () ; + else + genShiftRight () ; + } +} + + + +int pslCompiler::genBitwiseExpression () +{ + /* Expect: + + shiftExp ...or... + shiftExp & shiftExp + shiftExp | shiftExp + shiftExp ^ shiftExp + */ + + if ( ! genShiftExpression () ) + return FALSE ; + + while ( TRUE ) + { + char c [ MAX_TOKEN ] ; + + getToken ( c ) ; + + if ( strcmp ( c, "|" ) != 0 && + strcmp ( c, "&" ) != 0 && + strcmp ( c, "^" ) != 0 ) + { + ungetToken ( c ) ; + return TRUE ; + } + + if ( ! genShiftExpression () ) + return FALSE ; + + if ( strcmp ( c, "|" ) == 0 ) + genOr () ; + else + if ( strcmp ( c, "&" ) == 0 ) + genAnd () ; + else + genXor () ; + } +} + + + + +int pslCompiler::genRelExpression () +{ + /* Expect: + + bitwiseExp ...or... + bitwiseExp < bitwiseExp + bitwiseExp > bitwiseExp + bitwiseExp == bitwiseExp + bitwiseExp <= bitwiseExp + bitwiseExp >= bitwiseExp + bitwiseExp != bitwiseExp + */ + + if ( ! genBitwiseExpression () ) + return FALSE ; + + while ( TRUE ) + { + char c [ MAX_TOKEN ] ; + + getToken ( c ) ; + + if ( strcmp ( c, "<" ) != 0 && + strcmp ( c, ">" ) != 0 && + strcmp ( c, "<=" ) != 0 && + strcmp ( c, ">=" ) != 0 && + strcmp ( c, "!=" ) != 0 && + strcmp ( c, "==" ) != 0 ) + { + ungetToken ( c ) ; + return TRUE ; + } + + if ( ! genBitwiseExpression () ) + return FALSE ; + + if ( strcmp ( c, "<" ) == 0 ) genLess () ; else + if ( strcmp ( c, ">" ) == 0 ) genGreater () ; else + if ( strcmp ( c, "<=" ) == 0 ) genLessEqual () ; else + if ( strcmp ( c, ">=" ) == 0 ) genGreaterEqual () ; else + if ( strcmp ( c, "!=" ) == 0 ) genNotEqual () ; else + if ( strcmp ( c, "==" ) == 0 ) genEqual () ; + } +} + + + +int pslCompiler::genBoolExpression () +{ + /* Expect: + + relExp ...or... + relExp && boolExp ...or... + relExp || boolExp + */ + + if ( ! genRelExpression () ) + return FALSE ; + + char c [ MAX_TOKEN ] ; + int shortcut ; + + getToken ( c ) ; + + if ( strcmp ( c, "&&" ) == 0 ) + shortcut = genPeekJumpIfFalse ( 0 ) ; + else + if ( strcmp ( c, "||" ) == 0 ) + shortcut = genPeekJumpIfTrue ( 0 ) ; + else + { + ungetToken ( c ) ; + return TRUE ; + } + + if ( ! genBoolExpression () ) + return error ( "Missing expression following '&&' or '||'" ) ; + + code [ shortcut ] = next_code & 0xFF ; + code [ shortcut+1 ] = ( next_code >> 8 ) & 0xFF ; + + return TRUE ; +} + + +int pslCompiler::genExpression () +{ + /* All expressions can be bool expressions */ + return genBoolExpression () ; +} + + diff --git a/src/psl/pslFileIO.cxx b/src/psl/pslFileIO.cxx new file mode 100644 index 0000000..fa833eb --- /dev/null +++ b/src/psl/pslFileIO.cxx @@ -0,0 +1,206 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pslFileIO.cxx 1745 2003-01-06 05:10:14Z sjbaker $ +*/ + +#include "pslLocal.h" + +class pslFile ; + +static pslFile *defaultFileStack [ MAX_INCLUDE_DEPTH ] ; +static int fileStackPointer = 0 ; + +class pslFile +{ + FILE *fd ; + const char *memptr ; + char *fname ; + + int ungetStack [ MAX_UNGET_CHAR ] ; + int ungetSP ; + + int line_no ; + + void init () + { + ungetSP = 0 ; + line_no = 0 ; + + if ( fileStackPointer >= MAX_INCLUDE_DEPTH - 1 ) + fprintf ( stderr, "PSL: ERROR - Too many nested #includes" ) ; + else + defaultFileStack [ fileStackPointer++ ] = this ; + + /* + This is a kludge to get preprocessor directives to see + a '#' as the very first character in the file as if it came + immediately after a newline...also accounted for by line_no + starting at zero instead of 1. + */ + + unGetChar ( '\n' ) ; + line_no = 0 ; + } + +public: + + pslFile ( const char *_memptr, const char *_fname ) + { + fname = ulStrDup ( _fname ) ; + memptr = _memptr ; + fd = NULL ; + init () ; + } + + pslFile ( FILE *_fd, const char *_fname ) + { + fname = ulStrDup ( _fname ) ; + memptr = NULL ; + fd = _fd ; + init () ; + } + + ~pslFile () + { + if ( fileStackPointer <= 0 ) + fprintf ( stderr, "PSL: ERROR - #include stack underflow?!?" ) ; + else + { + if ( defaultFileStack [ --fileStackPointer ] != this ) + fprintf ( stderr, "PSL: ERROR - #include nesting problem?!?" ) ; + else + if ( fd != NULL ) + fclose ( fd ) ; + } + + delete [] fname ; + } + + void unGetChar ( int c ) + { + if ( ungetSP < MAX_UNGET_CHAR-1 ) + ungetStack [ ungetSP++ ] = c ; + else + fprintf ( stderr, "PSL: ERROR - Too many ungotten characters?!?" ) ; + + if ( c == '\n' ) line_no-- ; + } + + int getChar () + { + int c ; + + /* + Get a new character - either from the 'undo' stack or + from the file or from the memory pointer. + + Return -1 on EOF. + */ + + if ( ungetSP > 0 ) + c = ungetStack [ --ungetSP ] ; + else + if ( fd != NULL ) + c = getc ( fd ) ; + else + if ( memptr != NULL ) + { + c = (int)((unsigned char)(*(memptr++))) ; + + if ( c == '\0' ) + { + memptr = NULL ; + c = -1 ; + } + } + else + c = -1 ; + + if ( c == '\n' ) line_no++ ; + + return c ; + } + + int getLineNo () const { return line_no ; } + char *getFname () const { return fname ; } +} ; + + +char *_pslGetFname () + { return defaultFileStack [ fileStackPointer - 1 ] -> getFname () ; } +int _pslGetLineNo () + { return defaultFileStack [ fileStackPointer - 1 ] -> getLineNo () ; } + +void _pslPopDefaultFile () { delete defaultFileStack [ fileStackPointer - 1 ] ; } +void _pslPushDefaultFile ( FILE *fd, const char *fname ) { new pslFile ( fd, fname ) ; } +void _pslPushDefaultFile ( const char *memptr, const char *fname ) { new pslFile ( memptr, fname ) ; } + +void _pslPushDefaultFile ( const char *fname ) +{ + char filename [ 1024 ] ; + _pslMakeScriptPath ( filename, fname ) ; + + FILE *fd = fopen ( filename, "ra" ) ; + + if ( fd == NULL ) + { + fprintf ( stderr, + "PSL: ERROR - Can't open #include'ed file '%s'", filename ) ; + return ; + } + + _pslPushDefaultFile ( fd, fname ) ; +} + + + +int _pslGetChar () +{ + /* WARNING -- RECURSIVE -- WARNING -- RECURSIVE -- WARNING -- RECURSIVE */ + + int c = defaultFileStack [ fileStackPointer-1 ] -> getChar () ; + + /* + If we hit the end of the current file, then if this is an + included file, just pop the file stack and carry on reading + from the place we left off. Otherwise just return an EOF. + */ + + if ( c < 0 ) /* EOF */ + { + if ( fileStackPointer > 1 ) + { + _pslPopDefaultFile () ; + return _pslGetChar () ; + } + + return -1 ; + } + + return c ; +} + + +void _pslUnGetChar ( int c ) +{ + defaultFileStack [ fileStackPointer-1 ] -> unGetChar ( c ) ; +} + diff --git a/src/psl/pslFileIO.h b/src/psl/pslFileIO.h new file mode 100644 index 0000000..59e17da --- /dev/null +++ b/src/psl/pslFileIO.h @@ -0,0 +1,35 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pslFileIO.h 1745 2003-01-06 05:10:14Z sjbaker $ +*/ + +char *_pslGetFname () ; +int _pslGetLineNo () ; + +void _pslPopDefaultFile () ; +void _pslPushDefaultFile ( FILE *fd, const char *fname ) ; +void _pslPushDefaultFile ( const char *memptr, const char *fname ) ; +void _pslPushDefaultFile ( const char *fname ) ; + +void _pslUnGetChar ( int c ) ; +int _pslGetChar () ; + + diff --git a/src/psl/pslLocal.h b/src/psl/pslLocal.h new file mode 100644 index 0000000..a4bfa57 --- /dev/null +++ b/src/psl/pslLocal.h @@ -0,0 +1,63 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pslLocal.h 1707 2002-09-27 15:45:06Z sjbaker $ +*/ + + +#include +#include +#include +#include + +#include "psl.h" +#include "ul.h" + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +/* Limits */ + +#define MAX_ARGS 64 +#define MAX_VARIABLE 256 +#define MAX_LABEL 256 +#define MAX_TOKEN 1024 +#define MAX_CODE 65536 +#define MAX_STACK 256 +#define MAX_NESTING 32 +#define MAX_UNGET 64 +#define MAX_UNGET_CHAR 1024 +#define MAX_SYMBOL (MAX_VARIABLE + MAX_LABEL) +#define MAX_INCLUDE_DEPTH 8 + +typedef unsigned short pslAddress ; + +extern int _pslInitialised ; + +#include "pslFileIO.h" +#include "pslOpcodes.h" +#include "pslSymbol.h" +#include "pslCompiler.h" +#include "pslContext.h" + +char* _pslMakeScriptPath ( char* path, const char* fname ) ; + diff --git a/src/psl/pslOpcodes.h b/src/psl/pslOpcodes.h new file mode 100644 index 0000000..8e22e75 --- /dev/null +++ b/src/psl/pslOpcodes.h @@ -0,0 +1,100 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pslOpcodes.h 1700 2002-09-22 18:25:16Z sjbaker $ +*/ + + +/* Code Opcodes */ + +#define OPCODE_BAD 0x00 +#define OPCODE_PUSH_INT_CONSTANT 0x01 +#define OPCODE_PUSH_FLOAT_CONSTANT 0x02 +#define OPCODE_PUSH_STRING_CONSTANT 0x03 +#define OPCODE_CALL 0x04 +#define OPCODE_SUB 0x05 +#define OPCODE_ADD 0x06 +#define OPCODE_DIV 0x07 +#define OPCODE_MULT 0x08 +#define OPCODE_MOD 0x09 +#define OPCODE_NEG 0x0A +#define OPCODE_NOT 0x0B +#define OPCODE_TWIDDLE 0x0C +#define OPCODE_OROR 0x0D +#define OPCODE_ANDAND 0x0E +#define OPCODE_SHIFTLEFT 0x0F + +#define OPCODE_SHIFTRIGHT 0x10 +#define OPCODE_OR 0x11 +#define OPCODE_AND 0x12 +#define OPCODE_XOR 0x13 +#define OPCODE_LESS 0x14 +#define OPCODE_LESSEQUAL 0x15 +#define OPCODE_GREATER 0x16 +#define OPCODE_GREATEREQUAL 0x17 +#define OPCODE_NOTEQUAL 0x18 +#define OPCODE_EQUAL 0x19 +#define OPCODE_JUMP_FALSE 0x1A +#define OPCODE_JUMP_TRUE 0x1B +#define OPCODE_JUMP 0x1C +#define OPCODE_POP 0x1D +#define OPCODE_HALT 0x1E +#define OPCODE_CALLEXT 0x1F + +#define OPCODE_PAUSE 0x20 +#define OPCODE_RETURN 0x21 +#define OPCODE_PUSH_VARIABLE 0x22 +#define OPCODE_POP_VARIABLE 0x23 +#define OPCODE_SET_INT_VARIABLE 0x24 +#define OPCODE_SET_FLOAT_VARIABLE 0x25 +#define OPCODE_SET_STRING_VARIABLE 0x26 +#define OPCODE_STACK_DUPLICATE 0x27 +#define OPCODE_GET_PARAMETER 0x28 + +#define OPCODE_PEEK_JUMP_FALSE 0x2B +#define OPCODE_PEEK_JUMP_TRUE 0x2C +#define OPCODE_LINE_NUMBER 0x2D + + + +#define OPCODE_POP_ADD_VARIABLE 0x30 +#define OPCODE_POP_SUB_VARIABLE 0x31 +#define OPCODE_POP_MUL_VARIABLE 0x32 +#define OPCODE_POP_MOD_VARIABLE 0x33 +#define OPCODE_POP_DIV_VARIABLE 0x34 +#define OPCODE_POP_AND_VARIABLE 0x35 +#define OPCODE_POP_OR_VARIABLE 0x36 +#define OPCODE_POP_XOR_VARIABLE 0x37 +#define OPCODE_POP_SHL_VARIABLE 0x38 +#define OPCODE_POP_SHR_VARIABLE 0x39 +#define OPCODE_EXCHANGE 0x3A +#define OPCODE_SET_INT_ARRAY 0x3B +#define OPCODE_SET_FLOAT_ARRAY 0x3C +#define OPCODE_SET_STRING_ARRAY 0x3D + + + +#define OPCODE_FETCH 0x40 +#define OPCODE_INCREMENT_FETCH 0x41 +#define OPCODE_DECREMENT_FETCH 0x42 +#define OPCODE_INCREMENT_LVALUE 0x43 +#define OPCODE_DECREMENT_LVALUE 0x44 + + diff --git a/src/psl/pslProgram.cxx b/src/psl/pslProgram.cxx new file mode 100644 index 0000000..ca956cb --- /dev/null +++ b/src/psl/pslProgram.cxx @@ -0,0 +1,127 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pslProgram.cxx 1941 2004-08-05 00:57:38Z puggles $ +*/ + + +#include "pslLocal.h" + +pslProgram::pslProgram ( const pslExtension *ext, const char *_prgnm ) +{ + if ( ! _pslInitialised ) + ulSetError ( UL_FATAL, + "PSL: You didn't call pslInit() before using PSL functions." ) ; + + code = new pslOpcode [ MAX_CODE ] ; + + extensions = ext ; + + progName = NULL ; + + if ( _prgnm == NULL ) _prgnm = "PSLprogram" ; + + setProgName ( _prgnm ) ; + + compiler = new pslCompiler ( this, code, ext, getProgName () ) ; + context = new pslContext ( this ) ; + + compiler-> init () ; + context -> reset () ; + + const char *force_trace_env = getenv ( "PSL_TRACE" ) ; + const char *force_stack_env = getenv ( "PSL_STACK" ) ; + + force_trace = ( force_trace_env != NULL && + ulStrEqual ( force_trace_env, "always" ) ) ; + force_stacktrace = ( force_stack_env != NULL && + ulStrEqual ( force_stack_env, "always" ) ) ; + + if ( force_trace ) + compiler -> generateLineNumbers () ; +} + + +pslProgram::pslProgram ( pslProgram *src, const char *_prgnm ) +{ + progName = NULL ; + + if ( _prgnm == NULL ) _prgnm = src -> getProgName () ; + + setProgName ( _prgnm ) ; + + /* This will fail if this pslProgram is ever deleted */ + /* We need ref-counting on code/compiler */ + + code = src -> getCode () ; + compiler = src -> getCompiler () ; + extensions = src -> getExtensions () ; + userData = src -> getUserData () ; + + context = new pslContext ( this ) ; + context -> reset () ; +} + + +pslProgram::~pslProgram () +{ + /* This will fail if this pslProgram was copy-constructed */ + /* We need ref-counting on code/compiler */ + /* DEBUG-ME! */ + delete [] progName ; + delete context ; + compiler -> ref(); +} + + +void pslProgram::dump () const { compiler-> dump () ; } +void pslProgram::reset () { context -> reset () ; } +pslResult pslProgram::step () { return force_trace ? + context -> trace () : + context -> step () ; } +pslResult pslProgram::trace () { return context -> trace () ; } + + + +int pslProgram::compile ( const char *memptr, const char *fname ) +{ + if ( strcmp ( getProgName(), "PSLprogram" ) == 0 ) + setProgName ( fname ) ; + + return compiler -> compile ( memptr, fname ) ; +} + + +int pslProgram::compile ( const char *fname ) +{ + if ( strcmp ( getProgName(), "PSLprogram" ) == 0 ) + setProgName ( fname ) ; + + return compiler -> compile ( fname ) ; +} + + +int pslProgram::compile ( FILE *fd ) +{ + return compiler -> compile ( fd ) ; +} + + + diff --git a/src/psl/pslSymbol.h b/src/psl/pslSymbol.h new file mode 100644 index 0000000..e5f1a33 --- /dev/null +++ b/src/psl/pslSymbol.h @@ -0,0 +1,49 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pslSymbol.h 1612 2002-09-06 19:17:23Z ude $ +*/ + + +class pslSymbol +{ +public: + char *symbol ; + pslAddress address ; + int locality ; + + pslSymbol () + { + symbol = NULL ; + address = 0 ; + locality = 0 ; + } + + void set ( const char *s, pslAddress v, int loc ) + { + symbol = ulStrDup ( s ) ; + address = v ; + locality = loc ; + } + + ~pslSymbol () { delete [] symbol ; } +} ; + + diff --git a/src/psl/pslSymbols.cxx b/src/psl/pslSymbols.cxx new file mode 100644 index 0000000..653c3f6 --- /dev/null +++ b/src/psl/pslSymbols.cxx @@ -0,0 +1,168 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pslSymbols.cxx 1626 2002-09-08 22:17:32Z sjbaker $ +*/ + + +#include "pslLocal.h" + + +pslAddress pslCompiler::setVarSymbol ( const char *s ) +{ + for ( int i = 0 ; i < next_var ; i++ ) + if ( strcmp ( s, symtab [ i ] . symbol ) == 0 && + symtab [ i ] . locality >= locality_sp ) + { + error ( "Multiple definition of '%s'.", s ) ; + return symtab [ i ] . address ; + } + + if ( next_var >= MAX_VARIABLE-1 ) + { + error ( "Too many variables." ) ; + next_var-- ; + } + + symtab [ next_var ] . set ( s, next_var, locality_sp ) ; + + return symtab [ next_var++ ] . address ; +} + + + +pslAddress pslCompiler::getVarSymbol ( const char *s ) +{ + /* Search Backwards so most local variable shows up first */ + + for ( int i = next_var-1 ; i >= 0 ; i-- ) + if ( strcmp ( s, symtab [ i ] . symbol ) == 0 ) + return symtab [ i ] . address ; + + error ( "Undefined symbol '%s'.", s ) ; + + return setVarSymbol ( s ) ; +} + + +int pslCompiler::getExtensionSymbol ( const char *s ) const +{ + for ( int i = 0 ; extensions [ i ] . symbol != NULL ; i++ ) + if ( strcmp ( s, extensions [ i ] . symbol ) == 0 ) + return i ; + + return -1 ; +} + + +void pslCompiler::addFwdRef ( const char *s, pslAddress where ) +{ + for ( int i = 0 ; i < next_fwdref ; i++ ) + { + if ( forward_ref [ i ] . symbol == NULL ) + { + forward_ref [ i ] . set ( s, where ) ; + return ; + } + } + + if ( next_fwdref >= MAX_SYMBOL ) + { + error ( "Too many unresolved forward references." ) ; + return ; + } + + forward_ref [ next_fwdref++ ] . set ( s, where ) ; +} + + + +void pslCompiler::fixup ( const char *s, pslAddress v ) +{ + for ( int i = 0 ; i < next_fwdref ; i++ ) + { + if ( forward_ref [ i ] . matches ( s ) ) + { + pslAddress p = forward_ref [ i ] . getWhere () ; + + code [ p ] = v & 0xFF ; + code [ p+1 ] = (v >> 8) & 0xFF ; + + delete [] forward_ref[i].symbol ; + forward_ref[i].symbol = NULL ; + } + } +} + + + +void pslCompiler::checkUnresolvedSymbols () +{ + for ( int i = 0 ; i < next_fwdref ; i++ ) + { + if ( forward_ref [ i ] . symbol != NULL ) + { + error ( "'%s' does not exist.", forward_ref [ i ] . symbol ) ; + + /* Prevent multiple errors for same symbol */ + + fixup ( forward_ref [ i ] . symbol, 0 ) ; + } + } +} + + + +pslAddress pslCompiler::getCodeSymbol ( const char *s, pslAddress where ) +{ + for ( int i = 0 ; i < next_code_symbol ; i++ ) + if ( strcmp ( s, code_symtab [ i ] . symbol ) == 0 ) + return code_symtab [ i ] . address ; + + /* Symbol is undefined - so make a forward reference to it */ + + addFwdRef ( s, where ) ; + + return 0 ; +} + + + +void pslCompiler::setCodeSymbol ( const char *s, pslAddress v ) +{ + for ( int i = 0 ; i < next_code_symbol ; i++ ) + if ( strcmp ( s, code_symtab [ i ] . symbol ) == 0 ) + { + error ( "Multiple definition of '%s'.", s ) ; + return ; + } + + if ( next_code_symbol >= MAX_VARIABLE-1 ) + { + error ( "Too many labels." ) ; + next_code_symbol-- ; + } + + code_symtab [ next_code_symbol++ ] . set ( s, v, locality_sp ) ; + + fixup ( s, v ) ; +} + + diff --git a/src/psl/pslToken.cxx b/src/psl/pslToken.cxx new file mode 100644 index 0000000..fb9de45 --- /dev/null +++ b/src/psl/pslToken.cxx @@ -0,0 +1,608 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pslToken.cxx 1686 2002-09-15 17:45:53Z sjbaker $ +*/ + + +#include "pslLocal.h" + +static char ungotten_token [ MAX_UNGET ][ MAX_TOKEN ] ; +static int unget_token_stack_depth = 0 ; + +void pslCompiler::skipToEOL () +{ + int c ; + + do + { + c = getChar () ; + } while ( c != '\n' && c != -1 ) ; +} + + + +int pslCompiler::getChar () +{ + int c ; + + /* Skip characters so long as the 'skipping' flag is set */ + + do + { + /* + If we got a newline then we have to test to see whether + a '#' preprocessor directive is on this line. + */ + + c = _pslGetChar () ; + + if ( c == '\n' ) + { + int d = _pslGetChar () ; + + if ( d == '#' ) + { + skipOverride = TRUE ; + c = doPreProcessorCommand () ; + skipOverride = FALSE ; + + if ( ! skipping () ) + return c ; + } + else + _pslUnGetChar ( d ) ; + } + } while ( skipping () && c != -1 ) ; + + /* + All done - return the character. + */ + + return c ; +} + + + +int pslCompiler::searchDefines ( const char *token ) const +{ + if ( ( token[0] < 'a' || token[0] > 'z' ) && + ( token[0] < 'A' || token[0] > 'Z' ) && + token[0] != '_' ) + return -1 ; + + for ( int i = 0 ; i < next_define ; i++ ) + if ( define_token [ i ] != NULL && + strcmp ( token, define_token [ i ] ) == 0 ) + return i ; + + return -1 ; +} + + +void pslCompiler::doUndefStatement () +{ + char token [ MAX_TOKEN ] ; + + /* + It's tempting to just getToken to get the undefined token + but that doesn't work because it get's define-processed. + */ + + getToken ( token, FALSE ) ; + + if ( ( token[0] < 'a' || token[0] > 'z' ) && + ( token[0] < 'A' || token[0] > 'Z' ) && + token[0] != '_' ) + { + error ( "#undef token is not a legal identifier" ) ; + skipToEOL () ; + return ; + } + + skipToEOL () ; + + int def = searchDefines ( token ) ; + + if ( def == -1 ) return ; /* Not an error to have undefined undef's */ + + if ( ! skipping () ) + { + delete define_token [ def ] ; + delete define_replacement [ def ] ; + define_token [ def ] = NULL ; + define_replacement [ def ] = NULL ; + } +} + + +void pslCompiler::doIfdefStatement () +{ + char token [ MAX_TOKEN ] ; + + getToken ( token, FALSE ) ; + + if ( next_skippingLevel >= 30 ) + { + error ( "Too many levels of #ifdef/#ifndef processing." ) ; + skipToEOL () ; + return ; + } + + if ( searchDefines ( token ) == -1 ) + skippingFlag |= ( 1 << next_skippingLevel++ ) ; + else + skippingFlag &= ~( 1 << next_skippingLevel++ ) ; +} + + +void pslCompiler::doIfndefStatement () +{ + char token [ MAX_TOKEN ] ; + + getToken ( token, FALSE ) ; + + if ( next_skippingLevel >= 30 ) + { + error ( "Too many levels of #ifdef/#ifndef processing." ) ; + skipToEOL () ; + return ; + } + + if ( searchDefines ( token ) == -1 ) + skippingFlag &= ~( 1 << next_skippingLevel++ ) ; + else + skippingFlag |= ( 1 << next_skippingLevel++ ) ; + + skipToEOL () ; +} + + +void pslCompiler::doElseStatement () +{ + if ( next_skippingLevel <= 1 ) + error ( "#else without prior matching #ifdef/#ifndef." ) ; + + skipToEOL () ; + skippingFlag ^= ( 1 << (next_skippingLevel-1) ) ; +} + + + +void pslCompiler::doEndifStatement () +{ + if ( next_skippingLevel <= 1 ) + error ( "#endif without prior matching #ifdef/#ifndef." ) ; + + skipToEOL () ; + skippingFlag &= ~( 1 << (--next_skippingLevel) ) ; +} + + +void pslCompiler::doDefineStatement () +{ + char token [ MAX_TOKEN ] ; + char subst [ 1024 ] ; + char *p ; + + getToken ( token, FALSE ) ; + + if ( ( token[0] < 'a' || token[0] > 'z' ) && + ( token[0] < 'A' || token[0] > 'Z' ) && + token[0] != '_' ) + { + error ( "#define token is not a legal identifier" ) ; + skipToEOL () ; + return ; + } + + int c ; + + p = subst ; + + do + { + c = getChar () ; + + *(p++) = c ; + } while ( c != -1 && c != '\n' ) ; + + *(p-1) = '\0' ; + + if ( ! skipping () ) + { + if ( searchDefines ( token ) != -1 ) + error ( "Attempt to re-#define %s", token ) ; + else + if ( next_define >= MAX_SYMBOL - 1 ) + error ( "Too many #define's\n" ) ; + else + { + define_token [ next_define ] = ulStrDup ( token ) ; + define_replacement [ next_define ] = ulStrDup ( subst ) ; + next_define++ ; + } + } +} + +void pslCompiler::doIncludeStatement () +{ + char token [ MAX_TOKEN ] ; + char *p ; + + getToken ( token ) ; + + if ( token[0] == '"' ) + p = token + 1 ; + else + if ( token[0] == '<' ) + { + p = token ; + + do + { + *p = getChar () ; + + } while ( *(p++) != '>' ) ; + + *(p-1) = '\0' ; + + p = token ; + } + else + { + error ( "Illegal character after '#include'" ) ; + skipToEOL () ; + return ; + } + + /* + Skip to the end of this line of text BEFORE we hand + control over to the next file. + */ + + skipToEOL () ; + + if ( ! skipping () ) + _pslPushDefaultFile ( p ) ; +} + + + +int pslCompiler::doPreProcessorCommand () +{ + char token [ MAX_TOKEN ] ; + + getToken ( token ) ; + + if ( strcmp ( token, "include" ) == 0 ) + { + doIncludeStatement () ; + return getChar () ; + } + + if ( strcmp ( token, "undef" ) == 0 ) + { + doUndefStatement () ; + return '\n' ; + } + + if ( strcmp ( token, "define" ) == 0 ) + { + doDefineStatement () ; + return '\n' ; + } + + if ( strcmp ( token, "ifndef" ) == 0 ) + { + doIfndefStatement () ; + return getChar () ; + } + + if ( strcmp ( token, "ifdef" ) == 0 ) + { + doIfdefStatement () ; + return getChar () ; + } + + if ( strcmp ( token, "endif" ) == 0 ) + { + doEndifStatement () ; + return getChar () ; + } + + if ( strcmp ( token, "else" ) == 0 ) + { + doElseStatement () ; + return getChar () ; + } + + error ( "Unrecognised preprocessor directive '%s'", token ) ; + + skipToEOL () ; + return '\n' ; +} + + +void pslCompiler::getToken ( char *res, int define_sub ) +{ + /* WARNING -- RECURSIVE -- WARNING -- RECURSIVE -- WARNING -- RECURSIVE */ + + if ( unget_token_stack_depth > 0 ) + { + strcpy ( res, ungotten_token [ --unget_token_stack_depth ] ) ; + return ; + } + + int c ; + + do + { + c = getChar () ; + + if ( c < 0 ) + { + res [ 0 ] = '\0' ; + return ; + } + + if ( c == '/' ) + { + int d = getChar () ; + + if ( d == '/' ) /* C++ style comment */ + { + do + { + d = getChar () ; + } while ( d != '\n' && d != -1 ) ; + + c = ' ' ; + } + else + if ( d == '*' ) /* C style comment */ + { + /* + YUK! This is *so* horrible to get right. + Just think about this case! ==> **/ + + do + { + /* Search for a star or an EOF */ + + do + { + d = getChar () ; + } while ( d != '*' && d != -1 ) ; + + c = getChar () ; + + /* If you get two stars in a row - unget the second one */ + + if ( c == '*' ) + _pslUnGetChar ( '*' ) ; + + } while ( c != '/' ) ; + + c = ' ' ; + } + else + _pslUnGetChar ( d ) ; + } + } while ( isspace ( c ) ) ; + + int tp = 0 ; + + if ( c == '"' ) + { + int isBkSlash = FALSE ; + + do + { + if ( c == '\\' ) + { + if ( isBkSlash ) + { + isBkSlash = FALSE ; + res [ tp++ ] = c ; + } + else + isBkSlash = TRUE ; + } + else + if ( isBkSlash ) + { + switch ( c ) + { + case '0' : res [ tp++ ] = '\0' ; break ; + case 'r' : res [ tp++ ] = '\r' ; break ; + case 't' : res [ tp++ ] = '\t' ; break ; + case 'n' : res [ tp++ ] = '\n' ; break ; + case 'f' : res [ tp++ ] = '\f' ; break ; + case 'b' : res [ tp++ ] = '\b' ; break ; + case 'a' : res [ tp++ ] = '\a' ; break ; + default : res [ tp++ ] = c ; break ; + } + + isBkSlash = FALSE ; + } + else + res [ tp++ ] = c ; + + c = getChar () ; + + if ( tp >= MAX_TOKEN - 1 ) + { + error ( "Input string is bigger than %d characters!", + MAX_TOKEN - 1 ) ; + tp-- ; + } + } while ( ( isBkSlash || c != '"' ) && c != -1 ) ; + + if ( c == -1 ) + error ( "Missing \\\" character" ) ; + + /* The trailing quotes character is not included into the string */ + res [ tp ] = '\0' ; + return ; + } + + if ( c == '\'' ) + { + res [ tp++ ] = '\'' ; + + c = getChar () ; + + if ( c == '\\' ) + { + c = getChar () ; + + switch ( c ) + { + case '0' : res [ tp++ ] = '\0' ; break ; + case 'r' : res [ tp++ ] = '\r' ; break ; + case 't' : res [ tp++ ] = '\t' ; break ; + case 'n' : res [ tp++ ] = '\n' ; break ; + case 'f' : res [ tp++ ] = '\f' ; break ; + case 'b' : res [ tp++ ] = '\b' ; break ; + case 'a' : res [ tp++ ] = '\a' ; break ; + default : res [ tp++ ] = c ; break ; + } + } + else + res [ tp++ ] = c ; + + c = getChar () ; + + if ( c != '\'' ) + error ( "Missing \\' character" ) ; + + /* The trailing quote character is not included into the string */ + res [ tp ] = '\0' ; + return ; + } + + if ( isalnum ( c ) || c == '.' || c == '_' ) /* variables and numbers */ + { + while ( isalnum ( c ) || c == '.' || c == '_' ) + { + res [ tp++ ] = c ; + c = getChar () ; + + if ( tp >= MAX_TOKEN - 1 ) + { + error ( "Input string is bigger than %d characters!", + MAX_TOKEN - 1 ) ; + tp-- ; + } + } + + _pslUnGetChar ( c ) ; + } + else + + /* Deal with: + <<, >>, <<=, >>=, + /=, +=, -=, *=, %=, &=, |=, + <=, >=, ==, !=, ++, -- + */ + + if ( c == '*' || c == '/' || c == '%' || + c == '<' || c == '>' || c == '=' || + c == '!' || c == '&' || c == '|' || + c == '+' || c == '-' ) + { + res [ tp++ ] = c ; + + int c2 = getChar () ; + + if ( c2 == '=' || ( c == '>' && c2 == '>' ) || + ( c == '<' && c2 == '<' ) || + ( c == '&' && c2 == '&' ) || + ( c == '|' && c2 == '|' ) || + ( c == '+' && c2 == '+' ) || + ( c == '-' && c2 == '-' ) ) + { + res [ tp++ ] = c2 ; + + if ( ( c == '<' && c2 == '<' ) || + ( c == '>' && c2 == '>' ) ) + { + int c3 = getChar () ; + + if ( c3 == '=' ) + res [ tp++ ] = c3 ; + else + _pslUnGetChar ( c3 ) ; + } + } + else + _pslUnGetChar ( c2 ) ; + } + else + { + res [ 0 ] = c ; + tp = 1 ; + } + + res [ tp ] = '\0' ; + + /* + Don't do define substituting if told not to + */ + + if ( ! define_sub ) + return ; + + /* Do #define expansion. */ + + int def = searchDefines ( res ) ; + + if ( def == -1 ) + return ; + + /* + If there is a replacement for this token, un-get it so it's the + next thing we'll read. + */ + + for ( int i = strlen ( define_replacement [ def ] ) - 1 ; i >= 0 ; i-- ) + _pslUnGetChar ( define_replacement [ def ][ i ] ) ; + + /* + Then have another try at reading the token. + */ + + getToken ( res ) ; +} + + +void pslCompiler::ungetToken ( const char *s ) +{ + if ( unget_token_stack_depth >= MAX_UNGET-1 ) + { + error ( "Too many ungetTokens! This must be an *UGLY* PSL program!" ) ; + exit ( -1 ) ; + } + + strcpy ( ungotten_token[unget_token_stack_depth++], s ) ; +} + + diff --git a/src/puAux/Makefile.am b/src/puAux/Makefile.am new file mode 100644 index 0000000..3fc6939 --- /dev/null +++ b/src/puAux/Makefile.am @@ -0,0 +1,32 @@ +if BUILD_PUAUX + +lib_LIBRARIES = libplibpuaux.a + +include_HEADERS = puAux.h puAuxLocal.h + +libplibpuaux_a_SOURCES = puAux.cxx \ + puAuxBiSlider.cxx \ + puAuxBiSliderWithEnds.cxx \ + puAuxComboBox.cxx \ + puAuxCompass.cxx \ + puAuxFileSelector.cxx \ + puAuxLargeInput.cxx \ + puAuxList.cxx \ + puAuxScrollBar.cxx \ + puAuxSelectBox.cxx \ + puAuxSliderWithInput.cxx \ + puAuxSpinBox.cxx \ + puAuxTriSlider.cxx \ + puAuxVerticalMenu.cxx \ + puAuxChooser.cxx + +INCLUDES = -I$(top_srcdir)/src/sg \ + -I$(top_srcdir)/src/pui \ + -I$(top_srcdir)/src/fnt \ + -I$(top_srcdir)/src/util + +endif + +EXTRA_DIST = puAux.dsp + + diff --git a/src/puAux/puAux.cxx b/src/puAux/puAux.cxx new file mode 100644 index 0000000..0d226cc --- /dev/null +++ b/src/puAux/puAux.cxx @@ -0,0 +1,31 @@ + +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puAux.cxx 1902 2004-03-21 19:03:23Z sjbaker $ +*/ + + +#include "puAuxLocal.h" + +void puaInit () +{ + /* Nothing to see here - move along. */ +} diff --git a/src/puAux/puAux.dsp b/src/puAux/puAux.dsp new file mode 100644 index 0000000..56a7ea4 --- /dev/null +++ b/src/puAux/puAux.dsp @@ -0,0 +1,160 @@ +# Microsoft Developer Studio Project File - Name="puAux" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=puAux - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "puAux.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "puAux.mak" CFG="puAux - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "puAux - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "puAux - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "puAux - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "..\fnt" /I "..\sg" /I "..\util" /I ".." /I "..\pui" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "PU_USE_NONE" /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy release\*.lib ..\..\*.* copy puAux.h ..\..\puAux.h +# End Special Build Tool + +!ELSEIF "$(CFG)" == "puAux - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I "..\fnt" /I "..\sg" /I "..\util" /I ".." /I "..\pui" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "PU_USE_NONE" /FR /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\puAux_d.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy debug\*.lib ..\..\*.* copy puAux.h ..\..\puAux.h +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "puAux - Win32 Release" +# Name "puAux - Win32 Debug" +# Begin Source File + +SOURCE=.\puAux.cxx +# End Source File +# Begin Source File + +SOURCE=.\puAux.h +# End Source File +# Begin Source File + +SOURCE=.\puAuxBiSlider.cxx +# End Source File +# Begin Source File + +SOURCE=.\puAuxBiSliderWithEnds.cxx +# End Source File +# Begin Source File + +SOURCE=.\puAuxComboBox.cxx +# End Source File +# Begin Source File + +SOURCE=.\puAuxCompass.cxx +# End Source File +# Begin Source File + +SOURCE=.\puAuxFileSelector.cxx +# End Source File +# Begin Source File + +SOURCE=.\puAuxLargeInput.cxx +# End Source File +# Begin Source File + +SOURCE=.\puAuxList.cxx +# End Source File +# Begin Source File + +SOURCE=.\puAuxLocal.h +# End Source File +# Begin Source File + +SOURCE=.\puAuxScrollBar.cxx +# End Source File +# Begin Source File + +SOURCE=.\puAuxSelectBox.cxx +# End Source File +# Begin Source File + +SOURCE=.\puAuxSliderWithInput.cxx +# End Source File +# Begin Source File + +SOURCE=.\puAuxSpinBox.cxx +# End Source File +# Begin Source File + +SOURCE=.\puAuxTriSlider.cxx +# End Source File +# Begin Source File + +SOURCE=.\puAuxVerticalMenu.cxx +# End Source File +# End Target +# End Project diff --git a/src/puAux/puAux.h b/src/puAux/puAux.h new file mode 100644 index 0000000..b2c8898 --- /dev/null +++ b/src/puAux/puAux.h @@ -0,0 +1,944 @@ +/* + PUI Auxiliary Widget Library + Derived from PLIB, the Portable Game Library by Steve Baker. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puAux.h 2160 2010-02-27 03:48:23Z fayjf $ +*/ + +#ifndef _PUI_AUX_WIDGETS_H_ +#define _PUI_AUX_WIDGETS_H_ 1 + +#include "pu.h" + +// Widget Class Bit Patterns +// PUI classes take up 0x00000001 through 0x00020000 + +#define PUCLASS_FILESELECTOR 0x00040000 /* Because FilePicker is obsolete */ +#define PUCLASS_BISLIDER 0x00080000 +#define PUCLASS_TRISLIDER 0x00100000 +#define PUCLASS_VERTMENU 0x00200000 +#define PUCLASS_LARGEINPUT 0x00400000 +#define PUCLASS_COMBOBOX 0x00800000 +#define PUCLASS_SELECTBOX 0x01000000 +#define PUCLASS_SPINBOX 0x02000000 +#define PUCLASS_SCROLLBAR 0x04000000 +#define PUCLASS_BISLIDERWITHENDS 0x08000000 +#define PUCLASS_SLIDERWITHINPUT 0x10000000 +#define PUCLASS_COMPASS 0x20000000 +#define PUCLASS_CHOOSER 0x40000000 +#define PUCLASS_LIST 0x80000000 + + +// Widget Declarations +class puaSpinBox ; +class puaFileSelector ; +class puaBiSlider ; +class puaTriSlider ; +class puaVerticalMenu ; +class puaLargeInput ; +class puaComboBox ; +class puaSelectBox ; +class puaScrollBar ; +class puaBiSliderWithEnds ; +class puaCompass ; +class puaSliderWithInput ; +class puaChooser ; +class puaList ; + + +// A File selector widget +class puaFileSelector : public puDialogBox +{ + UL_TYPE_DATA + +protected: + char** files ; + char* dflag ; + int num_files ; + int arrow_count ; + + char *startDir ; + + void find_files ( void ) ; + static void handle_select ( puObject* ) ; + static void input_entered ( puObject* ) ; + + puFrame *frame ; + puListBox *list_box ; + puSlider *slider ; + puOneShot *cancel_button ; + puOneShot *ok_button ; + puInput *input ; + puArrowButton *up_arrow ; + puArrowButton *down_arrow ; + puArrowButton *fastup_arrow ; + puArrowButton *fastdown_arrow ; + + void puaFileSelectorInit ( int x, int y, int w, int h, + int arrows, const char *dir, const char *title ) ; + +public: + + puaFileSelector ( int x, int y, int w, int h, int arrows, + const char *dir, const char *title = "Pick a file" ) : + puDialogBox ( x, y ) + { + puaFileSelectorInit ( x, y, w, h, arrows, dir, title ) ; + } + + puaFileSelector ( int x, int y, int w, int h, + const char *dir, const char *title = "Pick a file" ) : + puDialogBox ( x, y ) + { + puaFileSelectorInit ( x, y, w, h, 1, dir, title ) ; + } + + puaFileSelector ( int x, int y, int arrows, + const char *dir, const char *title = "Pick a file" ) : + puDialogBox ( x, y ) + { + puaFileSelectorInit ( x, y, 220, 170, arrows, dir, title ) ; + } + + puaFileSelector ( int x, int y, + const char *dir, const char *title = "Pick a file" ) : + puDialogBox ( x, y ) + { + puaFileSelectorInit ( x, y, 220, 170, 1, dir, title ) ; + } + + ~puaFileSelector () ; + + /* Not for application use!! */ + puInput *__getInput ( void ) const { return input ; } + char *__getStartDir ( void ) const { return (char *) startDir ; } + + void setInitialValue ( const char *fname ) ; + void setSize ( int w, int h ) ; +} ; + + +// An input box that takes an arbitrary number of lines of input +class puaLargeInput : public puInputBase, public puGroup +{ + UL_TYPE_DATA + +protected: + int num_lines ; // Number of lines of text in the box + int lines_in_window ; // Number of lines showing in the window + int top_line_in_window ; // Number of the first line in the window + int max_width ; // Width of longest line of text in box, in pixels + int slider_width ; + int line_height ; // Text height + interline gap + int vgap ; // Gap on top and bottom + int hgap ; // Gap on the left and right side + int input_width ; // Width of display area (widget minus gaps & slider) + int input_height ; // Height of display area + + puFrame *frame ; + puFrame *plug ; // Little square in the bottom right corner + + puaScrollBar *bottom_slider ; // Horizontal slider at bottom of window + puaScrollBar *right_slider ; // Vertical slider at right of window + + int arrow_count ; // Number of up/down arrows above and below the right slider + + void normalizeCursors ( void ) ; + void removeSelectRegion ( void ) ; + void updateGeometry ( void ) ; + + char *wrapText ( int target_width = 0, int *numlines = 0, int *maxwidth = 0 ) ; + void getTextProperties(int *numlines, int *maxwidth) ; + char *getText () { return bottom_slider ? getStringValue () : getDisplayedText () ; } + +public: + puaLargeInput ( int x, int y, int w, int h, int arrows, int sl_width, int wrap_text = FALSE ) ; + ~puaLargeInput () + { + if ( puActiveWidget() == this ) + puDeactivateWidget () ; + } + + void setSize ( int w, int h ) ; + void setLegendFont ( puFont f ) { puGroup::setLegendFont ( f ) ; updateGeometry () ; } + + int getNumLines ( void ) const { return num_lines ; } + int getLinesInWindow ( void ) const { return lines_in_window ; } + void setTopLineInWindow ( int val ) { top_line_in_window = (val<0) ? 0 : ( (val>num_lines-2) ? num_lines-2 : val ) ; } + void setSliderPosition ( float fraction ) ; + + void draw ( int dx, int dy ) ; + int checkHit ( int button, int updown, int x, int y ) ; + void doHit ( int button, int updown, int x, int y ) ; + int checkKey ( int key, int updown ) ; + + void setSelectRegion ( int s, int e ) ; + void selectEntireLine ( void ) ; + + void invokeDownCallback ( void ) + { + rejectInput () ; + normalizeCursors () ; + if ( down_cb != NULL ) (*down_cb)(this) ; + } + + void setValue ( const char *s ) ; + void addNewLine ( const char *l ) ; + void addText ( const char *l ) ; + void appendText ( const char *l ) ; + void removeText ( int start, int end ) ; + char *getDisplayedText ( void ) + { + return ( displayed_text == NULL ? getStringValue () : displayed_text ) ; + } +} ; + + +// A box that contains a set of alternatives that drop down when the user clicks on the down-arrow +// Defined constants telling how the callback got triggered. This is needed for +// cases in which the user has deleted the entry in the input box and wants that +// entry deleted from the list of items. +#define PUACOMBOBOX_CALLBACK_NONE 0 +#define PUACOMBOBOX_CALLBACK_INPUT 1 +#define PUACOMBOBOX_CALLBACK_ARROW 2 +class puaComboBox : public puGroup +{ + UL_TYPE_DATA + +protected: + char ** list ; + int num_items ; + + int curr_item ; + + puInput *input ; + puArrowButton *arrow_btn ; + puPopupMenu *popup_menu ; + + int callback_source ; + + static void input_cb ( puObject *inp ) ; + static void input_active_cb ( puObject *inp ) ; + static void input_down_cb ( puObject *inp ) ; + static void handle_arrow ( puObject *arrow ) ; + static void handle_popup ( puObject *popupm ) ; + + void update_widgets ( void ) ; + void update_current_item ( void ) ; + void setCallbackSource ( int s ) { callback_source = s ; } + +public: + /* Not for application use ! */ + puPopupMenu * __getPopupMenu ( void ) const { return popup_menu ; } + + void newList ( char ** _list ) ; + int getNumItems ( void ) const { return num_items ; } + char *getNewEntry ( void ) const { return input->getStringValue () ; } + + int getCurrentItem ( void ) ; + void setCurrentItem ( int item ) + { + if ( ( item >= 0 ) && ( item < num_items ) ) + { + curr_item = item ; + update_widgets () ; + + callback_source = PUACOMBOBOX_CALLBACK_ARROW ; + invokeCallback () ; + } + } + + void setCurrentItem ( const char *item_ptr ) ; + + void setPosition ( int x, int y ) + { + puGroup::setPosition ( x, y ) ; + + /* Ensure that popup menu will show up at the right place */ + newList ( list ) ; + } + + void setSize ( int w, int h ) ; + + void setValue ( float f ) { puValue::setValue ( f ) ; input->setValue ( f ) ; } + void setValue ( int i ) { puValue::setValue ( i ) ; input->setValue ( i ) ; } + void setValue ( const char *s ) { puValue::setValue ( s ) ; input->setValue ( s ) ; } + void setValue ( puValue *pv ) { puValue::setValue ( pv ) ; input->setValue ( pv ) ; } + + void draw ( int dx, int dy ) ; + int checkHit ( int button, int updown, int x, int y ) ; + int checkKey ( int key, int updown ) ; + + int getCallbackSource ( void ) const { return callback_source ; } + + virtual void setColourScheme ( float r, float g, float b, float a = 1.0f ) ; + virtual void setColour ( int which, float r, float g, float b, float a = 1.0f ) ; + + puaComboBox ( int minx, int miny, int maxx, int maxy, + char **list, int editable = TRUE ) ; + + ~puaComboBox () + { + int i ; + for ( i = 0; i < num_items; i++ ) + delete [] list[i] ; + + delete [] list ; + } +} ; + + +// Like a menu bar, but the selections are one above the other +class puaVerticalMenu : public puGroup +{ + UL_TYPE_DATA + +protected: +public: + puaVerticalMenu ( int x = -1, int y = -1 ) : + + puGroup ( x < 0 ? puGetWindowWidth() - + ( puGetDefaultLegendFont().getStringWidth ( " " ) + + PUSTR_TGAP + PUSTR_BGAP ) : x, + + y < 0 ? puGetWindowHeight() - + ( puGetDefaultLegendFont().getStringHeight () + + PUSTR_TGAP + PUSTR_BGAP ) : y) + { + type |= PUCLASS_VERTMENU ; + floating = TRUE ; // DEPRECATED! -- we need to replace this code. + if ( y < 0 ) { setVStatus( TRUE ) ; } /* It is now supposed to stick to the top left - JCJ*/ + } + + void add_submenu ( const char *str, char *items[], puCallback _cb[], + void *_user_data[] = NULL ) ; + void close ( void ) ; +} ; + + +// Not sure what this one does ... +class puaSelectBox : public puGroup +{ + UL_TYPE_DATA + +protected: + char ** list ; + int num_items ; + + int curr_item ; + + puInput *input ; + puArrowButton *down_arrow ; + puArrowButton *up_arrow ; + + static void handle_arrow ( puObject *arrow ) ; + + void update_widgets ( void ) ; + +public: + void newList ( char ** _list ) ; + int getNumItems ( void ) const { return num_items ; } + + int getCurrentItem ( void ) const { return curr_item ; } + void setCurrentItem ( int item ) + { + if ( ( item >= 0 ) && ( item < num_items ) ) + { + curr_item = item ; + update_widgets () ; + + invokeCallback () ; + } + } + + void setSize ( int w, int h ) ; + void draw ( int dx, int dy ) ; + int checkKey ( int key, int updown ) ; + + virtual void setColourScheme ( float r, float g, float b, float a = 1.0f ) ; + virtual void setColour ( int which, float r, float g, float b, float a = 1.0f ) ; + + puaSelectBox ( int minx, int miny, int maxx, int maxy, + char **list ) ; +} ; + + +// A slider with up- and down-arrows on its ends +class puaScrollBar : public puSlider +{ + UL_TYPE_DATA + +protected: + int arrow_count ; + int active_arrow ; + float line_step_size ; + enum { NONE = 0, FASTDOWN = 1, DOWN = 2, UP = 4, FASTUP = 8 }; + +public: + void doHit ( int button, int updown, int x, int y ) ; + void draw ( int dx, int dy ) ; + int checkHit ( int button, int updown, int x, int y ) ; + puaScrollBar ( int minx, int miny, int sz, int arrows, int vertical = FALSE ) : + puSlider ( minx, miny, sz, vertical ) + { + type |= PUCLASS_SCROLLBAR ; + arrow_count = arrows ; + active_arrow = NONE ; + line_step_size = 0.0f ; + } + + /* Alternate constructor which lets you explicitly set width */ + + puaScrollBar ( int minx, int miny, int sz, int arrows, int vertical, int width ) : + puSlider ( minx, miny, sz, vertical, width ) + { + type |= PUCLASS_SCROLLBAR ; + arrow_count = arrows ; + active_arrow = NONE ; + line_step_size = 0.0f ; + } + + void setMaxValue ( float f ) + { + maximum_value = f ; + slider_fraction = 1.0f / ( getMaxValue() - getMinValue() + 1.0f ) ; + puPostRefresh () ; + } + + + void setMinValue ( float i ) + { + minimum_value = i ; + slider_fraction = 1.0f / ( getMaxValue() - getMinValue() + 1.0f ) ; + puPostRefresh () ; + } + + void setLineStepSize ( float s ) { line_step_size = s ; } + float getLineStepSize ( void ) const { return line_step_size ; } +} ; + + + +// A puSlider with two slide boxes instead of one +class puaBiSlider : public puSlider +{ + UL_TYPE_DATA + +protected: + float current_max ; + float current_min ; + + int active_button ; // Zero for none, one for min, two for max +public: + void doHit ( int button, int updown, int x, int y ) ; + void draw ( int dx, int dy ) ; + puaBiSlider ( int minx, int miny, int sz, int vertical = FALSE ) : + puSlider ( minx, miny, sz, vertical ) + { + type |= PUCLASS_BISLIDER ; + setMaxValue ( 1.0f ) ; + setMinValue ( 0.0f ) ; + setStepSize ( 1.0f ) ; + current_max = 1.0f ; + current_min = 0.0f ; + active_button = 0 ; + } + + /* Alternate constructor which lets you explicitly set width */ + + puaBiSlider ( int minx, int miny, int sz, int vertical, int width ) : + puSlider ( minx, miny, sz, vertical, width ) + { + type |= PUCLASS_BISLIDER ; + setMaxValue ( 1.0f ) ; + setMinValue ( 0.0f ) ; + setStepSize ( 1.0f ) ; + current_max = 1.0f ; + current_min = 0.0f ; + active_button = 0 ; + } + + void setMaxValue ( float i ) + { + maximum_value = i ; + slider_fraction = 1.0f / ( getMaxValue() - getMinValue() + 1.0f ) ; + puPostRefresh () ; + } + + + void setMinValue ( float i ) + { + minimum_value = i ; + slider_fraction = 1.0f / ( getMaxValue() - getMinValue() + 1.0f ) ; + puPostRefresh () ; + } + + void setCurrentMax ( int i ) { current_max = (float) i ; puPostRefresh () ; } /* DEPRECATED */ + void setCurrentMax ( float f ) { current_max = f ; puPostRefresh () ; } + float getCurrentMax ( void ) const { return current_max ; } + + void setCurrentMin ( int i ) { current_min = (float) i ; puPostRefresh () ; } /* DEPRECATED */ + void setCurrentMin ( float f ) { current_min = f ; puPostRefresh () ; } + float getCurrentMin ( void ) const { return current_min ; } + + void setActiveButton ( int i ) { active_button = i ; } + int getActiveButton ( void ) const { return active_button ; } +} ; + + +// A puSlider with three slide boxes + +class puaTriSlider : public puaBiSlider +{ + UL_TYPE_DATA + +protected: + // "active_button" is now zero for none, one for min, two for middle, three for max + int freeze_ends ; // true to make end sliders unmovable +public: + void doHit ( int button, int updown, int x, int y ) ; + void draw ( int dx, int dy ) ; + puaTriSlider ( int minx, int miny, int sz, int vertical = FALSE ) : + puaBiSlider ( minx, miny, sz, vertical ) + { + type |= PUCLASS_TRISLIDER ; + freeze_ends = TRUE ; + } + + /* Alternate constructor which lets you explicitly set width */ + + puaTriSlider ( int minx, int miny, int sz, int vertical, int width ) : + puaBiSlider ( minx, miny, sz, vertical, width ) + { + type |= PUCLASS_TRISLIDER ; + freeze_ends = TRUE ; + } + + int getFreezeEnds ( void ) const { return freeze_ends ; } + void setFreezeEnds ( int val ) { freeze_ends = val ; puPostRefresh () ; } +} ; + + +// A vertical puBiSlider with a puInput box above it showing the current maximum +// value and a puInput box below it showing the current minimum value + +class puaBiSliderWithEnds : public puGroup +{ + UL_TYPE_DATA + +protected: + puaBiSlider *slider ; + puInput *max_box ; + puInput *min_box ; + + static void handle_slider ( puObject *obj ) ; + static void handle_max ( puObject *obj ) ; + static void handle_min ( puObject *obj ) ; + static void input_down_callback ( puObject *obj ) ; + + void update_widgets ( void ) ; + +public: + // For internal use only: + void __setMax ( float f ) { max_box->setValue ( f ) ; } + void __setMin ( float f ) { min_box->setValue ( f ) ; } + + // For public use: + + void draw ( int dx, int dy ) ; + int checkHit ( int button, int updown, int x, int y ) + { + return puGroup::checkHit ( button, updown, x, y ) ; + } + + int checkKey ( int key, int updown ) ; + + puaBiSliderWithEnds ( int minx, int miny, int maxx, int maxy ) ; + + void setSize ( int w, int h ) ; + + void setMaxValue ( float f ) { slider->setMaxValue ( f ) ; } + float getMaxValue ( void ) const { return slider->getMaxValue () ; } + void setMinValue ( float f ) { slider->setMinValue ( f ) ; } + float getMinValue ( void ) const { return slider->getMinValue () ; } + + void setCurrentMax ( float f ) + { + slider->setCurrentMax ( f ) ; + max_box->setValue ( f ) ; + } + + float getCurrentMax ( void ) const { return slider->getCurrentMax () ; } + + void setCurrentMin ( float f ) + { + slider->setCurrentMin ( f ) ; + min_box->setValue ( f ) ; + } + + float getCurrentMin ( void ) const { return slider->getCurrentMin () ; } + + void setActiveButton ( int i ) { slider->setActiveButton ( i ) ; } + int getActiveButton ( void ) const { return slider->getActiveButton () ; } + + char *getValidData ( void ) const { return max_box->getValidData () ; } + void setValidData ( char *data ) { max_box->setValidData ( data ) ; min_box->setValidData ( data ) ; } + void addValidData ( char *data ) { max_box->addValidData ( data ) ; min_box->addValidData ( data ) ; } + + void setCBMode ( int m ) { slider->setCBMode ( m ) ; } + int getCBMode ( void ) const { return slider->getCBMode () ; } + + void setDelta ( float f ) { slider->setDelta ( f ) ; } + float getDelta ( void ) const { return slider->getDelta () ; } + + float getStepSize ( void ) const { return slider->getStepSize () ; } + void setStepSize ( float f ) { slider->setStepSize ( f ) ; } +} ; + + +// A vertical puSlider with a puInput box above or below it showing its value + +class puaSliderWithInput : public puGroup +{ + UL_TYPE_DATA + +protected: + puSlider *slider ; + puInput *input_box ; + int input_position ; + + static void handle_slider ( puObject *obj ) ; + static void handle_input ( puObject *obj ) ; + static void input_down_callback ( puObject *obj ) ; + + void update_widgets ( void ) ; + +public: + // For internal use only: + void __setInputBox ( float f ) { input_box->setValue ( f ) ; } + + // For public use: + + void draw ( int dx, int dy ) ; + int checkHit ( int button, int updown, int x, int y ) + { + return puGroup::checkHit ( button, updown, x, y ) ; + } + + int checkKey ( int key, int updown ) ; + + puaSliderWithInput ( int minx, int miny, int maxx, int maxy, int above = 0 ) ; + + void setSize ( int w, int h ) ; + + void setMaxValue ( float f ) { slider->setMaxValue ( f ) ; } + float getMaxValue ( void ) const { return slider->getMaxValue () ; } + void setMinValue ( float f ) { slider->setMinValue ( f ) ; } + float getMinValue ( void ) const { return slider->getMinValue () ; } + + void setValue ( int i ) { slider->setValue ( i ) ; input_box->setValue ( i ) ; } + void setValue ( float f ) { slider->setValue ( f ) ; input_box->setValue ( f ) ; } + virtual void setValue ( const char *s ) { slider->setValue ( s ) ; } + virtual void setValue ( bool b ) { slider->setValue ( b ) ; } + + int getIntegerValue ( void ) { return slider->getIntegerValue () ; } + float getFloatValue ( void ) { return slider->getFloatValue () ; } + char getCharValue ( void ) { return slider->getCharValue () ; } + char *getStringValue ( void ) { return slider->getStringValue () ; } + bool getBooleanValue ( void ) { return slider->getBooleanValue () ; } + + char *getValidData ( void ) const { return input_box->getValidData () ; } + void setValidData ( char *data ) { input_box->setValidData ( data ) ; } + void addValidData ( char *data ) { input_box->addValidData ( data ) ; } + + void setCBMode ( int m ) { slider->setCBMode ( m ) ; } + int getCBMode ( void ) const { return slider->getCBMode () ; } + + void setDelta ( float f ) { slider->setDelta ( f ) ; } + float getDelta ( void ) const { return slider->getDelta () ; } + + float getStepSize ( void ) const { return slider->getStepSize () ; } + void setStepSize ( float f ) { slider->setStepSize ( f ) ; } +} ; + +class puaSpinBox : public puRange, public puGroup +{ + UL_TYPE_DATA + +protected : + puInput *input_box ; + puArrowButton *up_arrow ; + puArrowButton *down_arrow ; + + int arrow_position ; + +public : + /* Whether the arrows are on the LEFT of the input box (0) or RIGHT (1 DEFAULT) */ + int getArrowPosition ( void ) const { return arrow_position ; } + /* Offered as a proportion of the input box height. Default = 0.5 */ + void setArrowHeight ( float height ) + { + puBox ibox = *(input_box->getABox()) ; + int size = int(height * ( ibox.max[1] - ibox.min[1] )) ; + up_arrow->setSize ( size, size ) ; + down_arrow->setSize ( size, size ) ; + int xpos = getArrowPosition () ? ibox.max[0] : ibox.min[0] - size ; + int ymid = ( ibox.max[1] + ibox.min[1] ) / 2 ; + if ( getArrowPosition () == 0 ) /* Arrows are on the left, adjust the x-position of the input box */ + { + ibox.min[0] -= xpos ; + input_box->setPosition ( ibox.min[0], ibox.min[1] ) ; + abox.min[0] += xpos ; + xpos = 0 ; + } + + if ( height > 0.5f ) /* Adjust the input box to be up from the bottom */ + { + input_box->setPosition ( ibox.min[0], ibox.min[1] + size - ymid ) ; + abox.min[1] += ymid - size ; + ymid = size ; + } + else /* Input box is at the bottom of the group area */ + { + input_box->setPosition ( ibox.min[0], 0 ) ; + abox.min[1] += ibox.min[1] ; + } + + up_arrow->setPosition ( xpos, ymid ) ; + down_arrow->setPosition ( xpos, ymid - size ) ; + recalc_bbox() ; + } + + float getArrowHeight ( void ) const + { + int awid, ahgt, iwid, ihgt ; + input_box->getSize ( &iwid, &ihgt ) ; + up_arrow->getSize ( &awid, &ahgt ) ; + return float(ahgt) / float(ihgt) ; + } + + puaSpinBox ( int minx, int miny, int maxx, int maxy, int arrow_pos = 1 ) ; + + void setValue ( float f ) { puValue::setValue ( f ) ; input_box->setValue ( f ) ; } + void setValue ( int i ) { puValue::setValue ( i ) ; input_box->setValue ( i ) ; } + void setValue ( const char *s ) { puValue::setValue ( s ) ; input_box->setValue ( s ) ; } + void setValue ( puValue *pv ) { puValue::setValue ( pv ) ; input_box->setValue ( pv ) ; } +} ; + + +/* + * Widget that looks like a 3-d coordinate system with quarter-circles in the coordinate planes. + * It is used in 3-d modeling to translate and rotate the scene. The coordinates rotate with + * the scene but do not translate. Defined values are: + * 0 - Nothing active + * 1 - Dot at origin active: reset (usually) + * 2 - X-axis dot active: rotate about y- and z-axes + * 3 - Y-axis dot active: rotate about z- and x-axes + * 4 - Z-axis dot active: rotate about x- and y-axes + * 5 - X-axis bar active: translate along x-axis + * 6 - Y-axis bar active: translate along y-axis + * 7 - Z-axis bar active: translate along z-axis + * 8 - XY-plane arc active: rotate about z-axis + * 9 - YZ-plane arc active: rotate about x-axis + * 10 - ZX-plane arc active: rotate about y-axis + * 11 - X-axis, Y-axis, and XY-arc active: translate in xy-plane + * 12 - Y-axis, Z-axis, and YZ-arc active: translate in yz-plane + * 13 - Z-axis, X-axis, and ZX-arc active: translate in zx-plane + */ +#define PUACOMPASS_INACTIVE 0 +#define PUACOMPASS_RESET 1 +#define PUACOMPASS_ROTATE_Y_Z 2 +#define PUACOMPASS_ROTATE_Z_X 3 +#define PUACOMPASS_ROTATE_X_Y 4 +#define PUACOMPASS_TRANSLATE_X 5 +#define PUACOMPASS_TRANSLATE_Y 6 +#define PUACOMPASS_TRANSLATE_Z 7 +#define PUACOMPASS_ROTATE_Z 8 +#define PUACOMPASS_ROTATE_X 9 +#define PUACOMPASS_ROTATE_Y 10 +#define PUACOMPASS_TRANSLATE_X_Y 11 +#define PUACOMPASS_TRANSLATE_Y_Z 12 +#define PUACOMPASS_TRANSLATE_Z_X 13 + +class puaCompass : public puObject +{ + UL_TYPE_DATA + +protected : + sgQuat rotation ; + sgVec3 translation ; + float point_size ; + int button_state ; + int trigger_button ; + float mouse_x, mouse_y, mouse_z ; + float translation_sensitivity ; + + float xint, yint, zint ; + float prev_angle ; + sgQuat prev_rotation ; + +public : + puaCompass ( int minx, int miny, int maxx, int maxy ) : puObject ( minx, miny, maxx, maxy ) + { + setValue ( PUACOMPASS_INACTIVE ) ; + +// sgSetQuat ( rotation, 1.0f, 0.0f, 0.0f, 0.0f ) ; +// sgSetQuat ( rotation, 0.707107f, 0.707107f, 0.0f, 0.0f ) ; +// sgSetQuat ( rotation, 0.5f, -0.5f, 0.5f, 0.5f ) ; +// sgSetQuat ( rotation, 0.866025f, -0.166667f, 0.166667f, 0.166667f ) ; + sgSetQuat ( rotation, 0.866025f, -0.408248f, 0.288675f, 0.0f ) ; + sgSetVec3 ( translation, 0.0f, 0.0f, 0.0f ) ; + + point_size = 10.0f ; + + button_state = PU_UP ; + trigger_button = active_mouse_button ; + mouse_x = mouse_y = mouse_z = 0.0f ; + translation_sensitivity = 1.0f ; + + xint = yint = zint = 0.0f ; + prev_angle = 0.0f ; + sgCopyQuat ( prev_rotation, rotation ) ; + } + + void draw ( int dx, int dy ) ; + void doHit ( int button, int updown, int x, int y ) ; + + // Accessors and mutators + void getRotation ( sgQuat q ) const { memcpy ( q, rotation, 4 * sizeof(sgFloat) ) ; } + void setRotation ( sgQuat q ) { memcpy ( rotation, q, 4 * sizeof(sgFloat) ) ; } + void setRotation ( sgFloat t, sgFloat x, sgFloat y, sgFloat z ) + { + sgFloat sinth = sgSin ( t / 2.0f ) ; + sgFloat norm = sgSqrt ( x * x + y * y + z * z ) ; + if ( norm == 0.0 ) norm = 1.0 ; + rotation[SG_W] = sgCos ( t / 2.0f ) ; + rotation[SG_X] = sinth * x / norm ; + rotation[SG_Y] = sinth * y / norm ; + rotation[SG_Z] = sinth * z / norm ; + } + + void getTranslation ( sgVec3 t ) const { memcpy ( t, translation, 3 * sizeof(sgFloat) ) ; } + void setTranslation ( sgVec3 t ) { memcpy ( translation, t, 3 * sizeof(sgFloat) ) ; } + void setTranslation ( sgFloat x, sgFloat y, sgFloat z ) { translation[SG_X] = x ; translation[SG_Y] = y ; translation[SG_Z] = z ; } + + float getPointSize () const { return point_size ; } + void setPointSize ( float p ) { point_size = p ; } + + int getTriggerButton () const { return trigger_button ; } + void setTriggerButton ( int b ) { trigger_button = b ; } + + float getTranslationSensitivity () const { return translation_sensitivity ; } + void setTranslationSensitivity ( float t ) { translation_sensitivity = t ; } +} ; + + +class puaChooser +{ + UL_TYPE_DATA + + puButton *chooser_button ; + puPopupMenu *popup_menu ; + + int x1, y1, x2, y2 ; + + static void static_popup_cb ( puObject * ) ; + static void static_menu_cb ( puObject * ) ; + +public: + + virtual ~puaChooser () + { + delete chooser_button ; + delete popup_menu ; + } + + puaChooser ( int _x1, int _y1, int _x2, int _y2, char *legend ) ; + + void add_item ( char *str, puCallback _cb, void *_user_data = NULL ) ; + void close () ; + + void popup_cb () ; + + void menuCleanup ( const char *s ) ; + + void hide () { chooser_button -> hide () ; popup_menu -> hide () ; } + void reveal () { chooser_button -> reveal () ; popup_menu -> hide () ; } + + static void menuCleanup ( puObject * ) ; +} ; + + +/** + * A scrolling list for PUI. + * + * Believe it or not, PUI does not have one of these. + * + * This widget consists of a puListBox, a slider and two + * arrow buttons. This makes the ListBox scrollable, + * very handy if the box is too small to show all items + * at once. + * + * (Original code taken from FlightGear 0.9.6 sources, + * modified by Jan Reucker) + */ +class puaList : public puGroup +{ + UL_TYPE_DATA + + char ** _contents; + puFrame * _frame; + puSlider * _slider; + puArrowButton * _up_arrow; + puArrowButton * _down_arrow; + int _style; + int _sw; // slider width + int _width, _height; + +protected: + virtual void init (int w, int h, short transparent); + puListBox * _list_box; + +public: + puaList (int x, int y, int w, int h, int sl_width = 20); + puaList (int x, int y, int w, int h, char ** contents, int sl_width = 20); + puaList (int x, int y, int w, int h, short transparent, int sl_width = 20); + puaList (int x, int y, int w, int h, short transparent, char ** contents, int sl_width = 20); + virtual ~puaList (); + + virtual void newList (char ** contents); + + virtual char * getStringValue (); + virtual int getIntegerValue (); + virtual void getValue (char **ps); + virtual void getValue (int *i); + + virtual void setColourScheme (float r, float g, float b, float a); + virtual void setColour (int which, float r, float g, float b, float a); + virtual void setSize (int w, int h); + + int checkHit ( int button, int updown, int x, int y ); + int getNumVisible ( void ) const { return _list_box->getNumVisible(); } + int getNumItems ( void ) const { return _list_box->getNumItems(); } + int getTopItem ( void ) const { return _list_box->getTopItem(); } + void setTopItem ( int item_index ); +}; + +#endif + diff --git a/src/puAux/puAuxBiSlider.cxx b/src/puAux/puAuxBiSlider.cxx new file mode 100644 index 0000000..13bd2fa --- /dev/null +++ b/src/puAux/puAuxBiSlider.cxx @@ -0,0 +1,170 @@ +/* + PUI Auxiliary Widget Library + Derived from PLIB, the Portable Game Library by Steve Baker. + Copyright (C) 1998,2002,2004 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puAuxBiSlider.cxx 2022 2005-05-06 18:39:18Z fayjf $ +*/ + + +#include "puAuxLocal.h" + +UL_RTTI_DEF1(puaBiSlider,puSlider) + + +void puaBiSlider::draw ( int dx, int dy ) +{ + if ( !visible || ( window != puGetWindow () ) ) return ; + + // Draw the slider box itself + + if ( ( style == PUSTYLE_BEVELLED ) || + ( style == PUSTYLE_SHADED ) ) + abox.draw ( dx, dy, -PUSTYLE_BOXED, colour, FALSE, 2 ) ; + else + abox.draw ( dx, dy, -style, colour, FALSE, border_thickness ) ; + + if ( r_cb ) + r_cb ( this, dx, dy, render_data ) ; + else + { + // Draw the current_max slider and label it + + float val ; + + if ( getMaxValue() > getMinValue() ) + val = (float)(getCurrentMax() - getMinValue()) / (float)(getMaxValue() - getMinValue()) ; + else + val = 1.0f ; + + char str_value[10] ; + sprintf (str_value, "%g", getCurrentMax() ) ; + + draw_slider_box ( dx, dy, abox, val, str_value ) ; + + // Draw the current_min slider and label it + + if ( getMaxValue() > getMinValue() ) + val = (float)(getCurrentMin() - getMinValue()) / (float)(getMaxValue() - getMinValue()) ; + else + val = 0.0f ; + + sprintf (str_value, "%g", getCurrentMin() ) ; + + draw_slider_box ( dx, dy, abox, val, str_value ) ; + + draw_legend ( dx, dy ) ; + } + + draw_label ( dx, dy ) ; +} + + +void puaBiSlider::doHit ( int button, int updown, int x, int y ) +{ + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + if ( updown != PU_DRAG ) + puMoveToLast ( this ); + + if ( ( button == active_mouse_button ) && ( updown == PU_UP ) ) + { + setActiveButton ( 0 ) ; + puDeactivateWidget () ; + return ; + } + + if ( button == active_mouse_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 ; + + float new_value = getMinValue() + next_value * ( getMaxValue() - getMinValue() ) ; + + if ( ( getActiveButton() == 0 ) || ( updown == PU_DOWN ) ) // No currently-active slider, set whichever is closest + { + if ( (new_value-getCurrentMin()) < (getCurrentMax()-new_value) ) // Closest to current_min + { + setCurrentMin ( checkStep(new_value) ) ; + setActiveButton ( 1 ) ; + } + else // Closest to current_max + { + setCurrentMax ( checkStep(new_value) ) ; + setActiveButton ( 2 ) ; + } + } + else if ( getActiveButton() == 1 ) // Currently moving current_min + { + setCurrentMin ( checkStep(new_value) ) ; + if ( getCurrentMax() < getCurrentMin() ) setCurrentMax ( getCurrentMin() ) ; + } + else if ( getActiveButton() == 2 ) // Currently moving current_max + { + setCurrentMax ( checkStep(new_value) ) ; + if ( getCurrentMax() < getCurrentMin() ) setCurrentMin ( getCurrentMax() ) ; + } + + + switch ( cb_mode ) + { + case PUSLIDER_CLICK : + if ( updown == active_mouse_edge ) + { + last_cb_value = next_value ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + } + break ; + + case PUSLIDER_DELTA :/* Deprecated! */ + if ( fabs ( last_cb_value - next_value ) >= cb_delta ) + { + last_cb_value = next_value ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + } + break ; + + case PUSLIDER_ALWAYS : + default : + last_cb_value = next_value ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + break ; + } + } +} diff --git a/src/puAux/puAuxBiSliderWithEnds.cxx b/src/puAux/puAuxBiSliderWithEnds.cxx new file mode 100644 index 0000000..47df508 --- /dev/null +++ b/src/puAux/puAuxBiSliderWithEnds.cxx @@ -0,0 +1,99 @@ +/* + PUI Auxiliary Widget Library + Derived from PLIB, the Portable Game Library by Steve Baker. + Copyright (C) 1998,2002,2004 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puAuxBiSliderWithEnds.cxx 2076 2006-04-13 16:20:23Z bram $ +*/ + +#include "puAuxLocal.h" + +UL_RTTI_DEF1(puaBiSliderWithEnds,puGroup) + +void puaBiSliderWithEnds::handle_slider ( puObject *obj ) +{ + puaBiSliderWithEnds *bisl = (puaBiSliderWithEnds *)obj->getUserData () ; + bisl->__setMax ( ((puaBiSlider *)obj)->getCurrentMax () ) ; + bisl->__setMin ( ((puaBiSlider *)obj)->getCurrentMin () ) ; + bisl->invokeCallback () ; +} + +void puaBiSliderWithEnds::handle_max ( puObject *obj ) +{ + puaBiSliderWithEnds *bisl = (puaBiSliderWithEnds *)obj->getUserData () ; + bisl->setCurrentMax ( obj->getFloatValue () ) ; + bisl->invokeCallback () ; +} + +void puaBiSliderWithEnds::handle_min ( puObject *obj ) +{ + puaBiSliderWithEnds *bisl = (puaBiSliderWithEnds *)obj->getUserData () ; + bisl->setCurrentMin ( obj->getFloatValue () ) ; + bisl->invokeCallback () ; +} + +puaBiSliderWithEnds::puaBiSliderWithEnds ( int minx, int miny, int maxx, int maxy ) : + puGroup ( minx, miny ) +{ + type |= PUCLASS_BISLIDERWITHENDS ; + slider = new puaBiSlider ( (maxx - minx)/2-10, 22, maxy-miny-44, TRUE ) ; + min_box = new puInput ( 0, 0, maxx-minx, 20 ) ; + max_box = new puInput ( 0, maxy-miny-20, maxx-minx, maxy-miny ) ; + min_box->setValue ( 0 ) ; + max_box->setValue ( 1 ) ; + slider->setUserData ( this ) ; + slider->setCallback ( handle_slider ) ; + max_box->setUserData ( this ) ; + max_box->setCallback ( handle_max ) ; + min_box->setUserData ( this ) ; + min_box->setCallback ( handle_min ) ; + close () ; +} + + +void puaBiSliderWithEnds::setSize ( int w, int h ) +{ + slider->setSize ( 20, h-44 ) ; + slider->setPosition ( w/2-10, 22 ) ; + + min_box->setSize ( w, 20 ) ; + + max_box->setSize ( w, 20 ) ; + max_box->setPosition ( 0, h-20 ) ; +} + + +void puaBiSliderWithEnds::draw ( int dx, int dy ) +{ + if ( !visible || ( window != puGetWindow () ) ) return ; + + draw_label ( dx, dy ) ; + + puGroup::draw ( dx, dy ) ; +} + + +int puaBiSliderWithEnds::checkKey ( int key, int updown ) +{ + if ( ! isVisible () || ! isActive () || ( window != puGetWindow () ) ) + return FALSE ; + + return ( max_box->checkKey ( key, updown ) + min_box->checkKey ( key, updown ) ) ; +} + diff --git a/src/puAux/puAuxChooser.cxx b/src/puAux/puAuxChooser.cxx new file mode 100644 index 0000000..ac4c986 --- /dev/null +++ b/src/puAux/puAuxChooser.cxx @@ -0,0 +1,104 @@ +/* + PUI Auxiliary Widget Library + Derived from PLIB, the Portable Game Library by Steve Baker. + Copyright (C) 1998,2002,2004 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puAuxChooser.cxx 1942 2004-08-05 01:03:49Z puggles $ +*/ + + +#include "puAuxLocal.h" + +UL_RTTI_DEF(puaChooser) + + + +puaChooser::puaChooser ( int _x1, int _y1, int _x2, int _y2, char *legend ) +{ + x1 = _x1 ; x2 = _x2 ; y1 = _y1 ; y2 = _y2 ; + + chooser_button = new puButton ( x1, y1, x2, y2 ) ; + chooser_button->setValue ( FALSE ) ; + chooser_button->setLegend ( legend ) ; + chooser_button->setUserData ( this ) ; + chooser_button->setCallback ( static_popup_cb ) ; + + popup_menu = new puPopupMenu ( x1, y1 ) ; + popup_menu -> setUserData ( this ) ; + popup_menu -> setCallback ( static_menu_cb ) ; +} + + +void puaChooser::add_item ( char *str, puCallback _cb, void *_user_data ) +{ + popup_menu -> add_item ( str, _cb, _user_data ) ; +} + + +void puaChooser::close () +{ + popup_menu -> close () ; + // int x, y, w, h ; + // popup_menu -> getPosition ( &x, &y ) ; + // popup_menu -> getSize ( &w, &h ) ; + popup_menu -> setPosition ( x1, y2 ) ; +} + + +void puaChooser::popup_cb () +{ + chooser_button -> setValue ( TRUE ) ; + + if ( popup_menu -> isVisible () ) + popup_menu -> hide () ; + else + popup_menu -> reveal () ; +} + + +void puaChooser::menuCleanup ( const char *s ) +{ + popup_menu -> hide () ; + chooser_button -> setValue ( FALSE ) ; + + if ( s != NULL ) + chooser_button -> setLegend ( s ) ; +} + + +void puaChooser::menuCleanup ( puObject *ob ) +{ + puObject *p = ob -> getParent () ; + ((puaChooser*)( p -> getUserData () )) -> menuCleanup ( ob -> getLegend () ) ; +} + + +void puaChooser::static_popup_cb ( puObject *ob ) +{ + ((puaChooser*)( ob -> getUserData () )) -> popup_cb () ; +} + + + +void puaChooser::static_menu_cb ( puObject *ob ) +{ + ((puaChooser*)( ob -> getUserData () )) -> menuCleanup ( (const char *)NULL ) ; +} + + diff --git a/src/puAux/puAuxComboBox.cxx b/src/puAux/puAuxComboBox.cxx new file mode 100644 index 0000000..8b71ff0 --- /dev/null +++ b/src/puAux/puAuxComboBox.cxx @@ -0,0 +1,377 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puAuxComboBox.cxx 2050 2005-11-10 20:07:08Z fayjf $ +*/ + + +#include "puAuxLocal.h" + +UL_RTTI_DEF1(puaComboBox,puGroup) + + +void puaComboBox::input_cb ( puObject *inp ) +{ + puaComboBox *cbox = (puaComboBox *) inp -> getUserData () ; + + if ( strcmp ( inp->getStringValue (), cbox->getStringValue () ) ) + { + cbox->update_current_item () ; + cbox->setCallbackSource ( PUACOMBOBOX_CALLBACK_INPUT ) ; + cbox -> invokeCallback () ; + } +} + +void puaComboBox::input_active_cb ( puObject *inp ) +{ + puaComboBox *cbox = (puaComboBox *) inp -> getUserData () ; + + cbox->update_current_item () ; + cbox->setCallbackSource ( PUACOMBOBOX_CALLBACK_INPUT ) ; + cbox -> invokeActiveCallback () ; +} + +void puaComboBox::input_down_cb ( puObject *inp ) +{ + puaComboBox *cbox = (puaComboBox *) inp -> getUserData () ; + + cbox->update_current_item () ; + cbox->setCallbackSource ( PUACOMBOBOX_CALLBACK_INPUT ) ; + cbox -> invokeCallback () ; +} + +void puaComboBox::handle_arrow ( puObject *arrow ) +{ + puaComboBox *cbox = (puaComboBox *) arrow -> getUserData () ; + + if ( ! cbox -> __getPopupMenu () -> isVisible () ) + cbox -> __getPopupMenu () -> reveal () ; + else + cbox -> __getPopupMenu () -> hide () ; + + /* arrow -> setStyle ( - arrow -> getStyle () ) ; */ +} + +void puaComboBox::handle_popup ( puObject *popupm ) +{ + puaComboBox *cbox = (puaComboBox *) popupm -> getUserData () ; + + cbox -> setCurrentItem ( popupm -> getLegend () ) ; +} + + +void puaComboBox::update_widgets ( void ) +{ + if ( curr_item >= 0 ) + /* There are some items */ + { + setValue ( list[curr_item] ) ; + + arrow_btn -> activate () ; + } + else + /* There aren't any items */ + { + setValue ( "" ) ; + + arrow_btn -> greyOut () ; + } + + input->setValue ( getStringValue () ) ; +} + + +void puaComboBox::update_current_item ( void ) +{ + if ( strcmp ( getStringValue (), input->getStringValue () ) ) + { + /* User has typed in an arbitrary string; see if it is in the list */ + int i ; + for ( i = 0 ; i < num_items ; i++ ) + { + if ( !strcmp ( list[i], input->getStringValue () ) ) + { + /* ... yes, it is ! */ + curr_item = i ; + break ; + } + } + + if ( ( i == num_items ) || ( num_items == 0 ) ) + { + /* Didn't find it in the list--or the list is empty */ + char **old_list = list ; + list = new char * [ num_items + 2 ] ; + for ( i = 0; i < num_items; i++ ) /* Copy over the old list */ + list[i] = old_list[i] ; + + delete old_list ; + + num_items++ ; + int len = strlen ( input->getStringValue () ) + 1 ; + curr_item = num_items - 1 ; + list[curr_item] = new char [ len ] ; + memcpy ( list[curr_item], input->getStringValue (), len ) ; + list[num_items] = NULL ; + newList ( list ) ; + update_widgets () ; + } + + setValue ( input->getStringValue () ) ; + } +} + + +void puaComboBox::newList ( char ** _list ) +{ + // Delete the existing list--if it has not been passed in as the argument + int i ; + if ( list && ( list != _list ) ) + { + for ( i = 0; i < num_items; i++ ) + delete list[i] ; + + delete list ; + list = NULL ; + } + + popup_menu -> empty () ; + + if ( _list == NULL ) + num_items = 0 ; + else + { + for ( num_items = 0 ; _list[num_items] != NULL ; num_items++ ) + /* Count number of items */ ; + + if ( num_items > 0 ) + { + if ( list != _list ) + { + list = new char * [ num_items + 1 ] ; /* '+ 1' to capture the trailing NULL */ + for ( i = 0; i < num_items; i++ ) + { + int len = strlen ( _list[i] ) + 1 ; /* "+ 1" to capture the \0 */ + list[i] = new char [ len ] ; + memcpy ( list[i], _list[i], len * sizeof(char) ) ; + } + + list[num_items] = NULL ; + } + + int dummy, h ; + int old_height = abox.max[1] - abox.min[1] ; + + puPushGroup ( popup_menu ) ; + + for ( i = (num_items - 1) ; i >= 0 ; i-- ) + { + puObject *menu_item = popup_menu -> add_item ( list[i], handle_popup ) ; + + menu_item -> setUserData ( this ) ; + menu_item -> getSize ( &dummy, &h ) ; + menu_item -> setSize ( abox.max[0] - abox.min[0], h ) ; + } + + popup_menu -> close() ; + + /* Position popup menu correctly */ + + popup_menu -> getSize ( &dummy, &h ) ; + + if ( (abox.min[1] - h) >= 0 ) + { + popup_menu -> setPosition ( 0, 0 - h ) ; + + arrow_btn -> setArrowType ( PUARROW_DOWN ) ; + } + else + { + popup_menu -> setPosition ( 0, old_height ) ; + + arrow_btn -> setArrowType ( PUARROW_UP ) ; + } + } + } + + if ( ( curr_item >= num_items ) || ( curr_item < 0 ) ) + { + curr_item = ( num_items > 0 ? 0 : - 1 ) ; + update_widgets () ; + } +} + +int puaComboBox::getCurrentItem ( void ) +{ + update_current_item () ; + + return curr_item ; +} + +void puaComboBox::setCurrentItem ( const char *item_ptr ) +{ + int i ; + + for ( i = 0 ; i < num_items ; i++ ) + { + if ( list[i] == item_ptr ) + { + setCurrentItem ( i ) ; + + break ; + } + } +} + + +void puaComboBox::draw ( int dx, int dy ) +{ + if ( !visible || ( window != puGetWindow () ) ) return ; + + draw_label ( dx, dy ) ; + + puGroup::draw ( dx, dy ) ; +} + +int puaComboBox::checkHit ( int button, int updown, int x, int y ) +{ + if ( input -> checkHit ( button, updown, x-abox.min[0], y-abox.min[1] ) ) + { + popup_menu -> hide () ; + puSetActiveWidget ( this, x, y ) ; + + return TRUE ; + } + else + return puGroup::checkHit ( button, updown, x, y ) ; +} + +int puaComboBox::checkKey ( int key, int updown ) +{ + if ( updown == PU_UP || ! input -> isAcceptingInput () || + ! isVisible () || ! isActive () || ( window != puGetWindow () ) ) + return FALSE ; + + switch ( key ) + { + case PU_KEY_HOME : + setCurrentItem ( 0 ) ; + break ; + + case PU_KEY_END : + setCurrentItem ( num_items - 1 ) ; + break ; + + case PU_KEY_UP : + setCurrentItem ( getCurrentItem () + 1 ) ; + break ; + + case PU_KEY_DOWN : + setCurrentItem ( getCurrentItem () - 1 ) ; + break ; + + case PU_KEY_PAGE_UP : + case PU_KEY_PAGE_DOWN : + if ( ! popup_menu -> isVisible () ) + popup_menu -> reveal () ; + else + popup_menu -> hide () ; + + break ; + + default : + return input -> checkKey ( key, updown ) ; + break ; + } + + return TRUE ; +} + +void puaComboBox::setColourScheme ( float r, float g, float b, float a ) +{ + puObject::setColourScheme ( r, g, b, a ) ; + setChildColourScheme( PUCLASS_INPUT, + colour [ PUCOL_EDITFIELD ][0], + colour [ PUCOL_EDITFIELD ][1], + colour [ PUCOL_EDITFIELD ][2], + colour [ PUCOL_EDITFIELD ][3] ) ; +} + +void puaComboBox::setColour ( int which, float r, float g, float b, float a ) +{ + if (which == PUCOL_EDITFIELD) + input->setColourScheme ( r, g, b, a ) ; + else + puObject::setColour ( which, r, g, b, a ) ; +} + + +puaComboBox::puaComboBox ( int minx, int miny, int maxx, int maxy, + char **entries, int editable ) : + puGroup( minx, miny ) +{ + type |= PUCLASS_COMBOBOX ; + + char *stringval ; + int arrow_width = (int) ( (maxy-miny) / 1.5f ) ; + + input = new puInput ( 0, 0, maxx-minx - arrow_width, maxy-miny ) ; + input -> setUserData ( this ) ; + input -> setCallback ( input_cb ) ; + input -> setActiveCallback ( input_active_cb ) ; + input -> setDownCallback ( input_down_cb ) ; + + input -> setStyle ( PUSTYLE_SMALL_SHADED ) ; + + if ( ! editable ) + input -> disableInput () ; + + /* Share 'string' value with input box */ + input -> getValue ( &stringval ) ; +// setValuator ( stringval ) ; + + arrow_btn = new puArrowButton ( maxx-minx - arrow_width, 0, + maxx-minx, maxy-miny, + PUARROW_DOWN ) ; + arrow_btn -> setStyle ( PUSTYLE_SMALL_SHADED ) ; + arrow_btn -> setUserData ( this ) ; + arrow_btn -> setCallback ( handle_arrow ) ; + + popup_menu = new puPopupMenu ( 0, 0 ) ; + popup_menu -> close () ; + + close () ; + + list = NULL ; + curr_item = 0 ; + num_items = 0 ; + callback_source = PUACOMBOBOX_CALLBACK_NONE ; + newList ( entries ) ; + update_widgets () ; +} + +void puaComboBox::setSize ( int w, int h ) +{ + int arrow_width = (int) ( float(h) / 1.5f ) ; + input->setSize ( w - arrow_width, h ) ; + arrow_btn->setPosition ( w - arrow_width, 0 ) ; + arrow_btn->setSize ( arrow_width, h ) ; +} + diff --git a/src/puAux/puAuxCompass.cxx b/src/puAux/puAuxCompass.cxx new file mode 100644 index 0000000..85aa2f6 --- /dev/null +++ b/src/puAux/puAuxCompass.cxx @@ -0,0 +1,564 @@ +/* + PUI Auxiliary Widget Library + Derived from PLIB, the Portable Game Library by Steve Baker. + Copyright (C) 1998,2002,2004 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puAuxCompass.cxx 1942 2004-08-05 01:03:49Z puggles $ +*/ + + +#include "puAuxLocal.h" + +#ifdef UL_MAC_OSX +# include +#else +# include +#endif + +UL_RTTI_DEF1(puaCompass,puObject) + +#define SET_ARC_COLOUR1(value) \ + if ( getIntegerValue () == value ) \ + glColor4fv ( colour [ PUCOL_LEGEND ] ) ; \ + else \ + glColor4fv ( colour [ PUCOL_FOREGROUND ] ) + +#define SET_ARC_COLOUR2(value1,value2) \ + if ( ( getIntegerValue () == value1 ) || ( getIntegerValue () == value2 ) ) \ + glColor4fv ( colour [ PUCOL_LEGEND ] ) ; \ + else \ + glColor4fv ( colour [ PUCOL_FOREGROUND ] ) + +#define SET_ARC_COLOUR3(value1,value2,value3) \ + if ( ( getIntegerValue () == value1 ) || ( getIntegerValue () == value2 ) || ( getIntegerValue () == value3 ) ) \ + glColor4fv ( colour [ PUCOL_LEGEND ] ) ; \ + else \ + glColor4fv ( colour [ PUCOL_FOREGROUND ] ) + +void puaCompass::draw ( int dx, int dy ) +{ + if ( !visible || ( window != puGetWindow () ) ) return ; + + // Draw the frame surrounding the compass + +// if ( ( style == PUSTYLE_BEVELLED ) || +// ( style == PUSTYLE_SHADED ) ) +// abox.draw ( dx, dy, -PUSTYLE_BOXED, colour, FALSE, 2 ) ; +// else +// abox.draw ( dx, dy, -style, colour, FALSE, border_thickness ) ; + + if ( r_cb ) + r_cb ( this, dx, dy, render_data ) ; + else + { + float xsize = float(abox.max[0] - abox.min[0]) ; + float ysize = float(abox.max[1] - abox.min[1]) ; + float xcenter = float(dx + abox.min[0]) + xsize / 2.0f ; + float ycenter = float(dy + abox.min[1]) + ysize / 2.0f ; + float size = ( ( xsize > ysize ) ? ysize : xsize ) / 2.5f ; + + glMatrixMode ( GL_MODELVIEW ) ; + glPushMatrix () ; + glLoadIdentity () ; + glTranslatef ( xcenter, ycenter, 0 ) ; + glScalef ( size, size, size ) ; + + /* Make the points circular instead of square */ + glEnable ( GL_POINT_SMOOTH ) ; + glPointSize ( point_size ) ; + + /* Ideally, we would be able to use a "glRotate" to rotate the compass. + * Unfortunately, PUI widgets are all 2-d and so our z-coordinate will cause + * the widget to be clipped. Our solution is to rotate all the compass + * components into the widget plane and just plot with a z-coordinate of zero. + */ + glColor4fv ( colour [ PUCOL_LEGEND ] ) ; + + sgVec3 pt ; + /* The points */ + glBegin ( GL_POINTS ) ; + SET_ARC_COLOUR1 ( PUACOMPASS_RESET ) ; + glVertex3f ( 0.0, 0.0, 0.0 ) ; /* the origin */ + SET_ARC_COLOUR1 ( PUACOMPASS_ROTATE_Y_Z ) ; + if ( getIntegerValue () != PUACOMPASS_ROTATE_Y_Z ) // Set x-point red for now since point size doesn't seem to work + glColor4f ( 1.0, 0.0, 0.0, 1.0 ) ; + sgSetVec3 ( pt, 1.0, 0.0, 0.0 ) ; /* x-axis point */ + sgRotateVecQuat ( pt, rotation ) ; + glVertex3f ( pt[SG_X], pt[SG_Y], 0.0f ) ; + SET_ARC_COLOUR1 ( PUACOMPASS_ROTATE_Z_X ) ; + if ( getIntegerValue () != PUACOMPASS_ROTATE_Z_X ) // Set y-point green for now since point size doesn't seem to work + glColor4f ( 0.0, 1.0, 0.0, 1.0 ) ; + sgSetVec3 ( pt, 0.0, 1.0, 0.0 ) ; /* y-axis point */ + sgRotateVecQuat ( pt, rotation ) ; + glVertex3f ( pt[SG_X], pt[SG_Y], 0.0f ) ; + SET_ARC_COLOUR1 ( PUACOMPASS_ROTATE_X_Y ) ; + if ( getIntegerValue () != PUACOMPASS_ROTATE_X_Y ) // Set z-point blue for now since point size doesn't seem to work + glColor4f ( 0.0, 0.0, 1.0, 1.0 ) ; + sgSetVec3 ( pt, 0.0, 0.0, 1.0 ) ; /* z-axis point */ + sgRotateVecQuat ( pt, rotation ) ; + glVertex3f ( pt[SG_X], pt[SG_Y], 0.0f ) ; + glEnd () ; + + glLineWidth ( 3 ) ; + + /* The axis lines */ + glBegin ( GL_LINES ) ; + SET_ARC_COLOUR3 ( PUACOMPASS_TRANSLATE_X, PUACOMPASS_TRANSLATE_X_Y, PUACOMPASS_TRANSLATE_Z_X ) ; + sgSetVec3 ( pt, 0.0, 0.0, 0.0 ) ; + sgRotateVecQuat ( pt, rotation ) ; + glVertex3f ( pt[SG_X], pt[SG_Y], 0.0f ) ; + sgSetVec3 ( pt, 1.0, 0.0, 0.0 ) ; /* x-axis */ + sgRotateVecQuat ( pt, rotation ) ; + glVertex3f ( pt[SG_X], pt[SG_Y], 0.0f ) ; + SET_ARC_COLOUR3 ( PUACOMPASS_TRANSLATE_Y, PUACOMPASS_TRANSLATE_X_Y, PUACOMPASS_TRANSLATE_Y_Z ) ; + sgSetVec3 ( pt, 0.0, 0.0, 0.0 ) ; + sgRotateVecQuat ( pt, rotation ) ; + glVertex3f ( pt[SG_X], pt[SG_Y], 0.0f ) ; + sgSetVec3 ( pt, 0.0, 1.0, 0.0 ) ; /* y-axis */ + sgRotateVecQuat ( pt, rotation ) ; + glVertex3f ( pt[SG_X], pt[SG_Y], 0.0f ) ; + SET_ARC_COLOUR3 ( PUACOMPASS_TRANSLATE_Z, PUACOMPASS_TRANSLATE_Y_Z, PUACOMPASS_TRANSLATE_Z_X ) ; + sgSetVec3 ( pt, 0.0, 0.0, 0.0 ) ; + sgRotateVecQuat ( pt, rotation ) ; + glVertex3f ( pt[SG_X], pt[SG_Y], 0.0f ) ; + sgSetVec3 ( pt, 0.0, 0.0, 1.0 ) ; /* z-axis */ + sgRotateVecQuat ( pt, rotation ) ; + glVertex3f ( pt[SG_X], pt[SG_Y], 0.0f ) ; + glEnd () ; + + /* The quarter-arcs */ + int num_points = 13 ; + float coords[13] = { .000000f, .130526f, .258819f, .382683f, .500000f, .608761f, + .707107f, .793353f, .866025f, .923879f, .965926f, .991445f, 1.0f } ; + int i ; + glBegin ( GL_LINE_STRIP ) ; + SET_ARC_COLOUR2 ( PUACOMPASS_ROTATE_Z, PUACOMPASS_TRANSLATE_X_Y ) ; + for ( i = 0; i < num_points; i++ ) + { + sgSetVec3 ( pt, coords[i], coords[num_points-1-i], 0.0 ) ; + sgRotateVecQuat ( pt, rotation ) ; + glVertex3f ( pt[SG_X], pt[SG_Y], 0.0f ) ; + } + glEnd () ; + + glBegin ( GL_LINE_STRIP ) ; + SET_ARC_COLOUR2 ( PUACOMPASS_ROTATE_Y, PUACOMPASS_TRANSLATE_Z_X ) ; + for ( i = 0; i < num_points; i++ ) + { + sgSetVec3 ( pt, coords[i], 0.0, coords[num_points-1-i] ) ; + sgRotateVecQuat ( pt, rotation ) ; + glVertex3f ( pt[SG_X], pt[SG_Y], 0.0f ) ; + } + glEnd () ; + + glBegin ( GL_LINE_STRIP ) ; + SET_ARC_COLOUR2 ( PUACOMPASS_ROTATE_X, PUACOMPASS_TRANSLATE_Y_Z ) ; + for ( i = 0; i < num_points; i++ ) + { + sgSetVec3 ( pt, 0.0, coords[i], coords[num_points-1-i] ) ; + sgRotateVecQuat ( pt, rotation ) ; + glVertex3f ( pt[SG_X], pt[SG_Y], 0.0f ) ; + } + glEnd () ; + + glMatrixMode ( GL_MODELVIEW ) ; + glPopMatrix () ; + + draw_legend ( dx, dy ) ; + } + + draw_label ( dx, dy ) ; +} + + +void puaCompass::doHit ( int button, int updown, int x, int y ) +{ + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + float xsize = float(abox.max[0] - abox.min[0]) ; + float ysize = float(abox.max[1] - abox.min[1]) ; + float size = ( ( xsize > ysize ) ? ysize : xsize ) / 2.5f ; + + /* Set the "prev_rotation" quaternion. This will stop being updated after the downclick. + * We use it in the transformation so that the transformation "freezes" on the downclick. + * In the meantime, the actual rotation continues to change and updates the widget "look." + */ + if ( button_state == PU_UP ) + sgCopyQuat ( prev_rotation, rotation ) ; + + /* The mouse position forms a line in 3-space. The equation of this line in window + * coordinates is (xm,ym,0) + u k, where "xm" and "ym" are the mouse position (x and y), + * "u" is a parametric coordinate along the line, and "k" is the unit vector in the z- + * direction. We rotate these into the compass coordinate system to get the mouse click + * somewhere on a line R = R0 + u T, where R0 is (xm,ym,0) rotated and T is "k" rotated. + */ + sgLine3 mouse_click_line ; + mouse_click_line.direction_vector[0] = 2.0f * ( -prev_rotation[SG_W] * prev_rotation[SG_Y] + prev_rotation[SG_X] * prev_rotation[SG_Z] ) ; + mouse_click_line.direction_vector[1] = 2.0f * ( prev_rotation[SG_W] * prev_rotation[SG_X] + prev_rotation[SG_Y] * prev_rotation[SG_Z] ) ; + mouse_click_line.direction_vector[2] = prev_rotation[SG_W] * prev_rotation[SG_W] + prev_rotation[SG_Z] * prev_rotation[SG_Z] - prev_rotation[SG_X] * prev_rotation[SG_X] - prev_rotation[SG_Y] * prev_rotation[SG_Y] ; + + float xm = float(x - abox.min[0]) - xsize / 2.0f ; + float ym = float(y - abox.min[1]) - ysize / 2.0f ; + sgSetVec3 ( mouse_click_line.point_on_line, xm, ym, 0.0f ) ; + sgRotateCoordQuat ( mouse_click_line.point_on_line, prev_rotation ) ; + + /* If the button state is up (whether moving or down-clicking), find the + * nearest element in the compass (if any) to activate it. + */ + if ( button_state == PU_UP ) + { + /* Set the widget value to zero. Then perform thirteen tests, each one figuring out whether + * the mouse is over (or has clicked on) so that we can activate the appropriate part of + * the widget. + */ + setValue ( PUACOMPASS_INACTIVE ) ; + + sgVec3 point ; + /* Minimum distance (squared) from the points (1,0,0), (0,1,0), and (0,0,1) to the mouse click line */ + sgSetVec3 ( point, size, 0.0, 0.0 ) ; + float dmin2 = sgDistSquaredToLineVec3 ( mouse_click_line, point ) ; + if ( dmin2 < point_size * point_size ) + setValue ( PUACOMPASS_ROTATE_Y_Z ) ; + + if ( getIntegerValue () == PUACOMPASS_INACTIVE ) + { + sgSetVec3 ( point, 0.0, size, 0.0 ) ; + dmin2 = sgDistSquaredToLineVec3 ( mouse_click_line, point ) ; + if ( dmin2 < point_size * point_size ) + setValue ( PUACOMPASS_ROTATE_Z_X ) ; + } + + if ( getIntegerValue () == PUACOMPASS_INACTIVE ) + { + sgSetVec3 ( point, 0.0, 0.0, size ) ; + dmin2 = sgDistSquaredToLineVec3 ( mouse_click_line, point ) ; + if ( dmin2 < point_size * point_size ) + setValue ( PUACOMPASS_ROTATE_X_Y ) ; + } + + /* Minimum distance (squared) from the origin */ + if ( getIntegerValue () == PUACOMPASS_INACTIVE ) + { + sgSetVec3 ( point, 0.0, 0.0, 0.0 ) ; + dmin2 = sgDistSquaredToLineVec3 ( mouse_click_line, point ) ; + if ( dmin2 < point_size * point_size ) + setValue ( PUACOMPASS_RESET ) ; + } + + /* Minimum distance (squared) from the three axis segments */ + sgLineSegment3 axis ; + sgSetVec3 ( axis.a, 0.0, 0.0, 0.0 ) ; + if ( getIntegerValue () == PUACOMPASS_INACTIVE ) + { + sgSetVec3 ( axis.b, size, 0.0, 0.0 ) ; + dmin2 = sgDistSquaredToLineLineSegment ( axis, mouse_click_line ) ; + if ( dmin2 < point_size * point_size ) + setValue ( PUACOMPASS_TRANSLATE_X ) ; + } + + if ( getIntegerValue () == PUACOMPASS_INACTIVE ) + { + sgSetVec3 ( axis.b, 0.0, size, 0.0 ) ; + dmin2 = sgDistSquaredToLineLineSegment ( axis, mouse_click_line ) ; + if ( dmin2 < point_size * point_size ) + setValue ( PUACOMPASS_TRANSLATE_Y ) ; + } + + if ( getIntegerValue () == PUACOMPASS_INACTIVE ) + { + sgSetVec3 ( axis.b, 0.0, 0.0, size ) ; + dmin2 = sgDistSquaredToLineLineSegment ( axis, mouse_click_line ) ; + if ( dmin2 < point_size * point_size ) + setValue ( PUACOMPASS_TRANSLATE_Z ) ; + } + + /* Project the mouse click line on to each of the coordinate planes. If it intersects + * within the given radius (size +- point_size) of the origin, highlight the arc. + */ + sgFloat xydist2 = 0.0 ; + sgFloat xyplane_xint = 0.0, xyplane_yint = 0.0 ; + if ( ( getIntegerValue () == PUACOMPASS_INACTIVE ) && ( mouse_click_line.direction_vector[2] != 0.0 ) ) + { + xyplane_xint = mouse_click_line.point_on_line[0] - mouse_click_line.point_on_line[2] * mouse_click_line.direction_vector[0] / mouse_click_line.direction_vector[2] ; + xyplane_yint = mouse_click_line.point_on_line[1] - mouse_click_line.point_on_line[2] * mouse_click_line.direction_vector[1] / mouse_click_line.direction_vector[2] ; + xydist2 = xyplane_xint * xyplane_xint + xyplane_yint * xyplane_yint ; + if ( ( xyplane_xint > 0.0 ) && ( xyplane_yint > 0.0 ) ) + { + if ( fabs ( xydist2 - size * size ) < 2.0f * size * point_size ) + { + setValue ( PUACOMPASS_ROTATE_Z ) ; + xint = xyplane_xint ; + yint = xyplane_yint ; + } + } + } + + sgFloat yzdist2 = 0.0 ; + sgFloat yzplane_yint = 0.0, yzplane_zint = 0.0 ; + if ( ( getIntegerValue () == PUACOMPASS_INACTIVE ) && ( mouse_click_line.direction_vector[0] != 0.0 ) ) + { + yzplane_yint = mouse_click_line.point_on_line[1] - mouse_click_line.point_on_line[0] * mouse_click_line.direction_vector[1] / mouse_click_line.direction_vector[0] ; + yzplane_zint = mouse_click_line.point_on_line[2] - mouse_click_line.point_on_line[0] * mouse_click_line.direction_vector[2] / mouse_click_line.direction_vector[0] ; + yzdist2 = yzplane_yint * yzplane_yint + yzplane_zint * yzplane_zint ; + if ( ( yzplane_yint > 0.0 ) && ( yzplane_zint > 0.0 ) ) + { + if ( fabs ( yzdist2 - size * size ) < 2.0f * size * point_size ) + { + setValue ( PUACOMPASS_ROTATE_X ) ; + yint = yzplane_yint ; + zint = yzplane_zint ; + } + } + } + + sgFloat zxdist2 = 0.0 ; + sgFloat zxplane_zint = 0.0, zxplane_xint = 0.0 ; + if ( ( getIntegerValue () == PUACOMPASS_INACTIVE ) && ( mouse_click_line.direction_vector[1] != 0.0 ) ) + { + zxplane_zint = mouse_click_line.point_on_line[2] - mouse_click_line.point_on_line[1] * mouse_click_line.direction_vector[2] / mouse_click_line.direction_vector[1] ; + zxplane_xint = mouse_click_line.point_on_line[0] - mouse_click_line.point_on_line[1] * mouse_click_line.direction_vector[0] / mouse_click_line.direction_vector[1] ; + zxdist2 = zxplane_zint * zxplane_zint + zxplane_xint * zxplane_xint ; + if ( ( zxplane_zint > 0.0 ) && ( zxplane_xint > 0.0 ) ) + { + if ( fabs ( zxdist2 - size * size ) < 2.0f * size * point_size ) + { + setValue ( PUACOMPASS_ROTATE_Y ) ; + zint = zxplane_zint ; + xint = zxplane_xint ; + } + } + } + + /* If we missed the arc (meaning that the value is still INACTIVE), check whether we + * got inside the quadrants. + */ + if ( ( getIntegerValue () == PUACOMPASS_INACTIVE ) && ( mouse_click_line.direction_vector[2] != 0.0 ) ) + { + if ( ( xydist2 < size * size ) && ( xyplane_xint > 0.0 ) && ( xyplane_yint > 0.0 ) ) + { + setValue ( PUACOMPASS_TRANSLATE_X_Y ) ; + xint = xyplane_xint ; + yint = xyplane_yint ; + } + } + + if ( ( getIntegerValue () == PUACOMPASS_INACTIVE ) && ( mouse_click_line.direction_vector[0] != 0.0 ) ) + { + if ( ( yzdist2 < size * size ) && ( yzplane_yint > 0.0 ) && ( yzplane_zint > 0.0 ) ) + { + setValue ( PUACOMPASS_TRANSLATE_Y_Z ) ; + yint = yzplane_yint ; + zint = yzplane_zint ; + } + } + + if ( ( getIntegerValue () == PUACOMPASS_INACTIVE ) && ( mouse_click_line.direction_vector[1] != 0.0 ) ) + { + if ( ( zxdist2 < size * size ) && ( zxplane_zint > 0.0 ) && ( zxplane_xint > 0.0 ) ) + { + setValue ( PUACOMPASS_TRANSLATE_Z_X ) ; + zint = zxplane_zint ; + xint = zxplane_xint ; + } + } + } + + if ( button != getTriggerButton () ) + return ; + + if ( updown == PU_DOWN ) + { + if ( getIntegerValue () == PUACOMPASS_ROTATE_X ) + prev_angle = sgATan2 ( zint, yint ) ; + else if ( getIntegerValue () == PUACOMPASS_ROTATE_Y ) + prev_angle = sgATan2 ( xint, zint ) ; + else if ( getIntegerValue () == PUACOMPASS_ROTATE_Z ) + prev_angle = sgATan2 ( yint, xint ) ; + + mouse_x = xm ; + mouse_y = ym ; + button_state = PU_DOWN ; + + // If we are rotating about two axes, we need to mouse z-coordinate for future reference. + if ( ( getIntegerValue () == PUACOMPASS_ROTATE_Y_Z ) || + ( getIntegerValue () == PUACOMPASS_ROTATE_Z_X ) || + ( getIntegerValue () == PUACOMPASS_ROTATE_X_Y ) ) + { + sgVec3 temp ; + sgCopyVec3 ( temp, mouse_click_line.point_on_line ) ; + // Parametric coordinate of point on line closest to origin + float u_origin = -sgScalarProductVec3 ( temp, mouse_click_line.direction_vector ) ; + float u = 0.0 ; + + if ( getIntegerValue () == PUACOMPASS_ROTATE_Y_Z ) + { + temp[SG_X] -= size ; + u = -sgScalarProductVec3 ( temp, mouse_click_line.direction_vector ) ; + } + else if ( getIntegerValue () == PUACOMPASS_ROTATE_Z_X ) + { + temp[SG_Y] -= size ; + u = -sgScalarProductVec3 ( temp, mouse_click_line.direction_vector ) ; + } + else if ( getIntegerValue () == PUACOMPASS_ROTATE_X_Y ) + { + temp[SG_Z] -= size ; + u = -sgScalarProductVec3 ( temp, mouse_click_line.direction_vector ) ; + } + + mouse_z = size * size - xm * xm - ym * ym ; + if ( mouse_z < 0.0 ) mouse_z = 0.0 ; + mouse_z = sgSqrt ( mouse_z ) ; + if ( u < u_origin ) mouse_z = -mouse_z ; + } + } + else if ( updown == PU_UP ) + { + if ( getIntegerValue () == PUACOMPASS_RESET ) + { + sgSetQuat ( rotation, 1.0f, 0.0f, 0.0f, 0.0f ) ; + sgSetQuat ( prev_rotation, 1.0f, 0.0f, 0.0f, 0.0f ) ; + sgSetVec3 ( translation, 0.0f, 0.0f, 0.0f ) ; + setValue ( PUACOMPASS_INACTIVE ) ; + } + + button_state = PU_UP ; + } + else if ( updown == PU_DRAG ) + { + float zm = size * size - xm * xm - ym * ym ; + if ( zm < 0.0 ) zm = 0.0 ; + zm = ( mouse_z >= 0.0 ) ? sgSqrt ( zm ) : -sgSqrt ( zm ) ; + float new_size = sgSqrt ( xm * xm + ym * ym + zm * zm ) ; + float cosang = ( xm * mouse_x + ym * mouse_y + zm * mouse_z ) / ( size * new_size ) ; + cosang = sgSqrt ( ( 1.0f + cosang ) / 2.0f ) ; + + sgVec3 displacement ; + sgSetVec3 ( displacement, xm - mouse_x, ym - mouse_y, 0.0f ) ; + sgRotateVecQuat ( displacement, prev_rotation ) ; + + sgQuat rot ; + sgSetQuat ( rot, 2.0f, 2.0f, 2.0f, 2.0f ) ; /* Values will change if we have a rotation */ + + sgFloat angle = prev_angle ; + + switch ( getIntegerValue () ) + { + case PUACOMPASS_INACTIVE : + break ; + case PUACOMPASS_RESET : + break ; + case PUACOMPASS_ROTATE_Y_Z : +// rot[SG_X] = 0.0 ; +// rot[SG_Y] = -displacement[2] / size ; +// rot[SG_Z] = displacement[1] / size ; +// rot[SG_W] = sgSqrt ( 1.0f - rot[SG_Y] * rot[SG_Y] - rot[SG_Z] * rot[SG_Z] ) ; +// sgPostMultQuat ( rotation, rot ) ; +// break ; + case PUACOMPASS_ROTATE_Z_X : +// rot[SG_X] = displacement[2] / size ; +// rot[SG_Y] = 0.0 ; +// rot[SG_Z] = -displacement[0] / size ; +// rot[SG_W] = sgSqrt ( 1.0f - rot[SG_X] * rot[SG_X] - rot[SG_Z] * rot[SG_Z] ) ; +// sgPostMultQuat ( rotation, rot ) ; +// break ; + case PUACOMPASS_ROTATE_X_Y : +// rot[SG_X] = -displacement[1] / size ; +// rot[SG_Y] = displacement[0] / size ; +// rot[SG_Z] = 0.0 ; +// rot[SG_W] = sgSqrt ( 1.0f - rot[SG_X] * rot[SG_X] - rot[SG_Y] * rot[SG_Y] ) ; + rot[SG_W] = cosang ; + rot[SG_X] = ( mouse_y * zm - mouse_z * ym ) * 0.5f / ( size * new_size * cosang ) ; + rot[SG_Y] = ( mouse_z * xm - mouse_x * zm ) * 0.5f / ( size * new_size * cosang ) ; + rot[SG_Z] = ( mouse_x * ym - mouse_y * xm ) * 0.5f / ( size * new_size * cosang ) ; + sgRotateVecQuat ( rot, prev_rotation ) ; + printf ( "Rotation %f %f %f %f %f %f %f %f\n", prev_angle, xm, ym, zm, rot[SG_W], rot[SG_X], rot[SG_Y], rot[SG_Z] ) ; + sgPreMultQuat ( rotation, rot ) ; + break ; + case PUACOMPASS_TRANSLATE_X : + translation[0] += translation_sensitivity * displacement[0] ; + break ; + case PUACOMPASS_TRANSLATE_Y : + translation[1] += translation_sensitivity * displacement[1] ; + break ; + case PUACOMPASS_TRANSLATE_Z : + translation[2] += translation_sensitivity * displacement[2] ; + break ; + case PUACOMPASS_ROTATE_Z : + xint = mouse_click_line.point_on_line[0] - mouse_click_line.point_on_line[2] * mouse_click_line.direction_vector[0] / mouse_click_line.direction_vector[2] ; + yint = mouse_click_line.point_on_line[1] - mouse_click_line.point_on_line[2] * mouse_click_line.direction_vector[1] / mouse_click_line.direction_vector[2] ; + angle = sgATan2 ( yint, xint ) - prev_angle ; + rot[SG_X] = 0.0 ; + rot[SG_Y] = 0.0 ; + rot[SG_Z] = sgSin ( angle / 2.0f ) ; + rot[SG_W] = sgCos ( angle / 2.0f ) ; + sgPostMultQuat ( rotation, rot ) ; + prev_angle += angle ; + break ; + case PUACOMPASS_ROTATE_X : + yint = mouse_click_line.point_on_line[1] - mouse_click_line.point_on_line[0] * mouse_click_line.direction_vector[1] / mouse_click_line.direction_vector[0] ; + zint = mouse_click_line.point_on_line[2] - mouse_click_line.point_on_line[0] * mouse_click_line.direction_vector[2] / mouse_click_line.direction_vector[0] ; + angle = sgATan2 ( zint, yint ) - prev_angle ; + rot[SG_X] = sgSin ( angle / 2.0f ) ; + rot[SG_Y] = 0.0 ; + rot[SG_Z] = 0.0 ; + rot[SG_W] = sgCos ( angle / 2.0f ) ; + sgPostMultQuat ( rotation, rot ) ; + prev_angle += angle ; + break ; + case PUACOMPASS_ROTATE_Y : + zint = mouse_click_line.point_on_line[2] - mouse_click_line.point_on_line[1] * mouse_click_line.direction_vector[2] / mouse_click_line.direction_vector[1] ; + xint = mouse_click_line.point_on_line[0] - mouse_click_line.point_on_line[1] * mouse_click_line.direction_vector[0] / mouse_click_line.direction_vector[1] ; + angle = sgATan2 ( xint, zint ) - prev_angle ; + rot[SG_X] = 0.0 ; + rot[SG_Y] = sgSin ( angle / 2.0f ) ; + rot[SG_Z] = 0.0 ; + rot[SG_W] = sgCos ( angle / 2.0f ) ; + sgPostMultQuat ( rotation, rot ) ; + prev_angle += angle ; + break ; + case PUACOMPASS_TRANSLATE_X_Y : + translation[0] += translation_sensitivity * displacement[0] ; + translation[1] += translation_sensitivity * displacement[1] ; + break ; + case PUACOMPASS_TRANSLATE_Y_Z : + translation[1] += translation_sensitivity * displacement[1] ; + translation[2] += translation_sensitivity * displacement[2] ; + break ; + case PUACOMPASS_TRANSLATE_Z_X : + translation[2] += translation_sensitivity * displacement[2] ; + translation[0] += translation_sensitivity * displacement[0] ; + break ; + } + + mouse_x = xm * size / new_size ; + mouse_y = ym * size / new_size ; + mouse_z = zm * size / new_size ; +// if ( rot[0] < 1.5 ) +// { +// sgPostMultQuat ( rotation, rot ) ; +// prev_angle += angle ; +// printf ( "Rotation %f %f %f %f %f\n", prev_angle, rotation[SG_W], rotation[SG_X], rotation[SG_Y], rotation[SG_Z] ) ; +// } + } +} diff --git a/src/puAux/puAuxFileSelector.cxx b/src/puAux/puAuxFileSelector.cxx new file mode 100644 index 0000000..261222a --- /dev/null +++ b/src/puAux/puAuxFileSelector.cxx @@ -0,0 +1,692 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puAuxFileSelector.cxx 1902 2004-03-21 19:03:23Z sjbaker $ +*/ + +/**** +* NAME +* puaFileSelector +* +* DESCRIPTION +* PUI dialog for selecting files +* +* AUTHOR +* Dave McClurg +* +* CREATION DATE +* August 2000 +* +* MODIFICATION HISTORY +* John Fay - many improvements +* Steve Baker - moved from FilePicker to FileSelector due to +* key API change. +****/ + + +#include "puAuxLocal.h" + +UL_RTTI_DEF1(puaFileSelector,puDialogBox) + + +#ifdef UL_MSVC +#define DOTDOTSLASH "..\\" +#define SLASH "\\" +#else +#define DOTDOTSLASH "../" +#define SLASH "/" +#endif +#define SLASH_LEN 1 + +static void puaFileSelectorHandleSlider ( puObject * slider ) +{ + float val ; + slider -> getValue ( &val ) ; + val = 1.0f - val ; + + puListBox* list_box = (puListBox*) slider -> getUserData () ; + int idx = int ( list_box -> getNumItems () * val ) ; + list_box -> setTopItem ( idx ) ; +} + +static void puaFileSelectorHandleArrow ( puObject *arrow ) +{ + puSlider *slider = (puSlider *) arrow->getUserData () ; + puListBox* list_box = (puListBox*) slider -> getUserData () ; + + int type = ((puArrowButton *)arrow)->getArrowType() ; + int inc = ( type == PUARROW_DOWN ) ? 1 : + ( type == PUARROW_UP ) ? -1 : + ( type == PUARROW_FASTDOWN ) ? 10 : + ( type == PUARROW_FASTUP ) ? -10 : 0 ; + + float val ; + slider -> getValue ( &val ) ; + val = 1.0f - val ; + int num_items = list_box->getNumItems () - 1 ; + if ( num_items > 0 ) + { + int idx = int ( num_items * val + 0.5f ) + inc ; + if ( idx > num_items ) idx = num_items ; + if ( idx < 0 ) idx = 0 ; + + slider -> setValue ( 1.0f - (float)idx / num_items ) ; + list_box -> setTopItem ( idx ) ; + } +} + + +static bool is_slash ( char ch ) +{ +#ifdef UL_WIN32 + /* win32 can use back or forward slash */ + return ch == '\\' || ch == '/' ; +#else + return ch == SLASH[0] ; +#endif +} + + +static void chop_file ( char *fname ) +{ + /* removes everything back to the last '/' */ + + for ( int i = strlen(fname)-1 ; ! is_slash ( fname[i] ) && i >= 0 ; i-- ) + fname[i] = '\0' ; +} + + +static void go_up_one_directory ( char *fname ) +{ + /* removes everything back to the last but one '/' */ + + chop_file ( fname ) ; + + if ( fname[0] == '\0' ) + { + /* Empty string! We must be at the root. */ + + strcpy ( fname, SLASH ) ; + return ; + } + + /* Otherwise, just delete the last element of the path. */ + + /* Remove the trailing slash - then remove the rest as + if it was a file name */ + + fname [ strlen(fname)-1 ] = '\0' ; + chop_file ( fname ) ; +} + + +void puaFileSelector::input_entered ( puObject* inp ) +{ + puaFileSelector* file_selector = (puaFileSelector*) (inp -> getUserData ()) ; + + /* + If the input selector is empty - do nothing + */ + + if ( inp -> getStringValue() [ 0 ] == '\0' ) + return ; + + if ( ulIsAbsolutePathName ( inp -> getStringValue () ) ) + file_selector -> setValue ( inp -> getStringValue () ) ; + else + { + char *s = new char [ strlen ( file_selector->__getStartDir() ) + + strlen ( SLASH ) + + strlen ( inp -> getStringValue () ) + + 1 ] ; + + ulMakePath ( s, file_selector -> __getStartDir(), + inp -> getStringValue () ) ; + file_selector -> setValue ( s ) ; + + delete [] s ; + } + + /* + If he typed a valid directory name - then + refresh the contents of the browser window + */ + + ulDir *d = ulOpenDir ( file_selector->getStringValue() ) ; + ulCloseDir ( d ) ; + + if ( d != NULL ) + file_selector -> find_files () ; +} + + +void puaFileSelector::handle_select ( puObject* l_box ) +{ + puaFileSelector* file_selector = (puaFileSelector*) l_box -> getUserData () ; + + int selected ; + l_box -> getValue ( &selected ) ; + + if ( selected >= 0 && selected < file_selector -> num_files ) + { + char *dst = file_selector -> getStringValue () ; + char *src = file_selector -> files [ selected ] ; + + chop_file ( dst ) ; + + if ( strcmp ( src, "[..]" ) == 0 ) + { + /* Do back up one level - so refresh. */ + + go_up_one_directory ( dst ) ; + file_selector -> find_files () ; + file_selector -> __getInput() -> setValue ( dst ) ; + return ; + } + + if ( file_selector -> dflag [ selected ] ) + { + /* If this is a directory - then descend into it and refresh */ + + src++ ; /* Remove leading '[' */ + + int dst_len = strlen ( dst ) ; + int src_len = strlen ( src ) ; + char *new_dst = new char [ dst_len + src_len + 1 ] ; + + memcpy ( new_dst, dst, dst_len ) ; + memcpy ( new_dst + dst_len, src, src_len + 1 ) ; /* Copy trailing '\0' */ + + /* Replace trailing ']' with slash */ + new_dst [ dst_len + src_len - 1 ] = SLASH[0] ; + + file_selector -> __getInput() -> setValue ( new_dst ) ; + file_selector -> setValue ( new_dst ) ; + + delete [] new_dst ; + file_selector -> find_files () ; + return ; + } + + /* If this is a regular file - then just append it to the string */ + + int dst_len = strlen ( dst ) ; + int src_len = strlen ( src ) ; + char *new_dst = new char [ dst_len + src_len + 1 ] ; + + memcpy ( new_dst, dst, dst_len ) ; + memcpy ( new_dst + dst_len, src, src_len + 1 ) ; /* Copy trailing '\0' */ + + file_selector -> __getInput() -> setValue ( new_dst ) ; + file_selector -> setValue ( new_dst ) ; + + delete [] new_dst ; + } + else + { + /* + The user clicked on blank screen - maybe we should + refresh just in case some other process created the + file. + */ + + file_selector -> find_files () ; + } +} + + +static void puaFileSelectorHandleCancel ( puObject* b ) +{ + puaFileSelector* file_selector = (puaFileSelector*) b -> getUserData () ; + file_selector -> setValue ( "" ) ; + file_selector -> invokeCallback () ; +} + +static void puaFileSelectorHandleOk ( puObject* b ) +{ + puaFileSelector* file_selector = (puaFileSelector*) b -> getUserData () ; + + file_selector -> invokeCallback () ; +} + +void puaFileSelector::setSize ( int w, int h ) +{ + // Resize the frame widget + frame->setSize ( w, h ) ; + + // Resize and position the slider + slider->setPosition ( w-30, 40+20*arrow_count ) ; + slider->setSize ( 20, h-60-40*arrow_count ) ; + + // Position the arrow buttons + if ( up_arrow ) + { + up_arrow->setPosition ( w-30, h-20-20*arrow_count ) ; + down_arrow->setPosition ( w-30, 20+20*arrow_count ) ; + } + + if ( fastup_arrow ) + { + fastup_arrow->setPosition ( w-30, h-40 ) ; + fastdown_arrow->setPosition ( w-30, 40 ) ; + } + + // Resize the list box + list_box->setSize ( w-40, h-80 ) ; + + // Resoze and position the buttons + cancel_button->setSize ( (w<170)?(w/2-15):70, 20 ) ; + ok_button->setSize ( (w<170)?(w/2-15):70, 20 ) ; + ok_button->setPosition ( (w<170)?(w/2+5):90, 10 ) ; +} + +puaFileSelector::~puaFileSelector () +{ + delete [] startDir ; + + if ( files != NULL ) + { + for ( int i=0; i 2 ) arrows = 2 ; + if ( arrows < 0 ) arrows = 0 ; + arrow_count = arrows ; + + frame = new puFrame ( 0, 0, w, h ); + + slider = new puSlider (w-30,40+20*arrows,h-60-40*arrows,TRUE,20); + slider->setValue(1.0f); + slider->setSliderFraction (0.2f) ; + slider->setCBMode( PUSLIDER_DELTA ); + + list_box = new puListBox ( 10, 60, w-40, h-20 ) ; + list_box -> setLabel ( title ); + list_box -> setLabelPlace ( PUPLACE_TOP_LEFT ) ; + list_box -> setStyle ( -PUSTYLE_SMALL_SHADED ) ; + list_box -> setUserData ( this ) ; + list_box -> setCallback ( handle_select ) ; + list_box -> setValue ( 0 ) ; + + find_files () ; + + handle_select ( list_box ) ; + + slider -> setUserData ( list_box ) ; + slider -> setCallback ( puaFileSelectorHandleSlider ) ; + + input = new puInput ( 10, 40, w-40, 60 ) ; + input -> setValue ( startDir ) ; + input -> setUserData ( this ) ; + input -> setCallback ( input_entered ) ; + input -> setDownCallback ( input_entered ) ; + + cancel_button = new puOneShot ( 10, 10, (w<170)?(w/2-5):80, 30 ) ; + cancel_button -> setLegend ( "Cancel" ) ; + cancel_button -> setUserData ( this ) ; + cancel_button -> setCallback ( puaFileSelectorHandleCancel ) ; + + ok_button = new puOneShot ( (w<170)?(w/2+5):90, 10, (w<170)?(w-10):160, 30 ) ; + ok_button -> setLegend ( "Ok" ) ; + ok_button -> setUserData ( this ) ; + ok_button -> setCallback ( puaFileSelectorHandleOk ) ; + + up_arrow = down_arrow = NULL ; + fastup_arrow = fastdown_arrow = NULL ; + + if ( arrows > 0 ) + { + down_arrow = new puArrowButton ( w-30, 20+20*arrows, w-10, 40+20*arrows, PUARROW_DOWN ) ; + down_arrow->setUserData ( slider ) ; + down_arrow->setCallback ( puaFileSelectorHandleArrow ) ; + + up_arrow = new puArrowButton ( w-30, h-20-20*arrows, w-10, h-20*arrows, PUARROW_UP ) ; + up_arrow->setUserData ( slider ) ; + up_arrow->setCallback ( puaFileSelectorHandleArrow ) ; + } + + if ( arrows == 2 ) + { + fastdown_arrow = new puArrowButton ( w-30, 40, w-10, 60, PUARROW_FASTDOWN ) ; + fastdown_arrow->setUserData ( slider ) ; + fastdown_arrow->setCallback ( puaFileSelectorHandleArrow ) ; + + fastup_arrow = new puArrowButton ( w-30, h-40, w-10, h-20, PUARROW_FASTUP ) ; + fastup_arrow->setUserData ( slider ) ; + fastup_arrow->setCallback ( puaFileSelectorHandleArrow ) ; + } + + close () ; + reveal () ; +} + +static int puaFileSelectorStringCompare ( const char *s1, const char *s2, + const char f1, const char f2 ) +{ + if ( f1 > f2 ) /* Directories before regular files. */ + return -1 ; + + if ( f1 < f2 ) + return 1 ; + + while ( 1 ) + { + char c1 = s1? (*s1++): 0 ; + char c2 = s2? (*s2++): 0 ; + + //end of string? + if ( !c1 || !c2 ) + { + if ( c1 ) + return 1 ; //s1 is longer + if ( c2 ) + return -1 ; //s1 is shorter + return 0 ; + } + + if ( c1 == c2 ) + continue ; + + /* + Windoze users are case-insensitive - so they presumably + want case ignored in the sorting. + + UNIX users, however, do things like calling their makefiles + 'Makefile' so as to force them to the start of the directory + listing. + */ + +#ifdef UL_MSVC + if ( c1 >= 'a' && c1 <= 'z' ) + c1 = c1 - ('a'-'A') ; + + if ( c2 >= 'a' && c2 <= 'z' ) + c2 = c2 - ('a'-'A') ; +#endif + + if ( c1 != c2 ) + { + if ( c1 < c2 ) + return -1 ; + return 1 ; + } + } + return 0 ; +} + + +void puaFileSelector::setInitialValue ( const char *s ) +{ + if ( ulIsAbsolutePathName ( s ) ) + { + input -> setValue ( s ) ; + input -> invokeCallback () ; + } + else + { + int str_val_len = strlen ( input->getStringValue () ) ; + int s_len = strlen ( s ) ; + char *s_new = new char [ str_val_len + s_len + 1 ] ; + + memcpy ( s_new, input->getStringValue (), str_val_len ) ; + memcpy ( s_new + str_val_len, s, s_len + 1 ) ; /* Plus one to get the final '\0' */ + + input->setValue ( s_new ) ; + delete [] s_new ; + input -> invokeCallback () ; + } +} + + +static void puaFileSelectorSort ( char** list, char *flags, int size ) +// +// comb sort - a modified bubble sort +// taken from BYTE, April 1991, ppg 315-320 +// +{ + int switches ; + int gap = size ; + + do + { + gap = ((gap * 197) >> 8); // gap /= 1.3; + + switch (gap) + { + case 0: // the smallest gap is 1 -- bubble sort + gap = 1; + break; + + case 9: // this is what makes this Combsort11 + case 10: + gap = 11; + break; + } + + switches = 0 ; // dirty pass flag + + int top = size - gap; + + for ( int i=0; i 0 ) + { + char* temp = list[i] ; + list[i] = list[j] ; + list[j] = temp ; + + char tmp2 = flags[i] ; + flags[i] = flags[j] ; + flags[j] = tmp2 ; + + ++switches; + } + } + } while ( switches || gap > 1 ) ; +} + + +void puaFileSelector::find_files ( void ) +{ + if ( files != NULL ) + { + for ( int i = 0 ; i < num_files ; i++ ) + delete [] files[i] ; + + delete [] files ; + delete [] dflag ; + } + + num_files = 0 ; + + int str_val_len = strlen ( getStringValue () ) ; + + if ( ! is_slash ( getStringValue () [ str_val_len - 1 ] ) ) + /* Someone forgot a trailing '/' */ + { + char *new_dir = new char [ str_val_len + SLASH_LEN + 1 ] ; + + memcpy ( new_dir, getStringValue (), str_val_len ) ; + memcpy ( new_dir + str_val_len, SLASH, SLASH_LEN + 1 ) ; /* Plus one to include the trailing '\0' */ + setValue ( new_dir ) ; + delete [] new_dir ; + } + + int ifile = 0 ; + + char *dir = getStringValue () ; + ulDir *dirp = ulOpenDir ( dir ) ; + ulDirEnt *dp ; + + if ( dirp == NULL ) + { + perror ("puaFileSelector") ; + ulSetError ( UL_WARNING, "PUI:puaFileSelector - can't open directory '%s'", dir ) ; + num_files = 0 ; + return ; + } + + /* Count the number of files - skipping "." */ + + while ( ( dp = ulReadDir(dirp) ) != NULL ) + if ( strcmp ( dp->d_name, "." ) != 0 ) + ifile++ ; + + ulCloseDir ( dirp ) ; + + num_files = ifile ; + if ( num_files > 5 ) + slider -> setDelta ( 0.5f / num_files ) ; + else + slider -> setDelta ( 0.1f ) ; + + if ( num_files == 0 ) + { + ulSetError ( UL_WARNING, + "PUI:puaFileSelector - no entries in directory '%s'?!", dir ) ; + return ; + } + + files = new char* [ num_files+1 ] ; + dflag = new char [ num_files+1 ] ; + + dirp = ulOpenDir ( dir ) ; + + if ( dirp == NULL ) + { + perror ("puaFileSelector") ; + ulSetError ( UL_WARNING, + "PUI:puaFileSelector - can't re-open directory '%s'", dir ) ; + num_files = 0 ; + return ; + } + + ifile = 0 ; + + while ( (dp = ulReadDir(dirp)) != NULL && ifile < num_files ) + { + /* Skip over the "." entry... */ + + if ( strcmp ( dp->d_name, "." ) != 0 ) + { + dflag[ ifile ] = dp->d_isdir ; + + int name_len = strlen ( dp->d_name ) ; + if ( dflag[ ifile ] ) + { + files[ ifile ] = new char[ name_len + 3 ] ; + + files [ ifile ] [ 0 ] = '[' ; + memcpy ( files [ ifile ] + 1, dp->d_name, name_len ) ; + strcpy ( files [ ifile ] + 1 + name_len, "]" ) ; + } + else + { + files[ ifile ] = new char[ name_len + 1 ] ; + memcpy ( files [ ifile ], dp->d_name, name_len + 1 ) ; /* Plus one to include the final '\0' */ + } + + ifile++ ; + } + } + + files [ ifile ] = NULL ; + + ulCloseDir ( dirp ) ; + + puaFileSelectorSort( files, dflag, num_files ) ; + + list_box -> newList ( files ) ; +} + diff --git a/src/puAux/puAuxLargeInput.cxx b/src/puAux/puAuxLargeInput.cxx new file mode 100644 index 0000000..6dceb29 --- /dev/null +++ b/src/puAux/puAuxLargeInput.cxx @@ -0,0 +1,1313 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puAuxLargeInput.cxx 2161 2010-02-27 04:06:53Z fayjf $ +*/ + + +#include "puAuxLocal.h" + +UL_RTTI_DEF2(puaLargeInput,puInputBase,puGroup) + + +// Callbacks from the internal widgets + +static void puaLargeInputHandleRightSlider ( puObject *slider ) +{ + puaLargeInput* text = (puaLargeInput*) slider->getUserData () ; + text->setSliderPosition ( 1 - slider->getFloatValue () ) ; +} + +// Private function from the widget itself + +void puaLargeInput::normalizeCursors ( void ) +{ + puInputBase::normalizeCursors () ; + + // Set the top line in the window so that the last line is at the bottom of the window + if ( top_line_in_window > num_lines - lines_in_window + 2 ) + top_line_in_window = num_lines - lines_in_window + 2 ; + + if ( top_line_in_window < 0 ) top_line_in_window = 0 ; +} + +void puaLargeInput::removeSelectRegion ( void ) +{ + puInputBase::removeSelectRegion () ; + updateGeometry () ; +} + + +// Public functions from the widget itself + +puaLargeInput::puaLargeInput ( int x, int y, int w, int h, int arrows, int sl_width, int wrap_text ) : + puInputBase (), puGroup ( x, y ) +{ + setColour ( PUCOL_MISC, 0.1f, 0.1f, 1.0f ) ; // Colour of the 'I' bar cursor + + // Set the variables + + type |= PUCLASS_LARGEINPUT ; + num_lines = 1 ; + slider_width = sl_width ; + top_line_in_window = 0 ; + lines_in_window = 1 ; + max_width = 0 ; + widget = this ; + + // Set up the widgets + + frame = new puFrame ( 0, 0, w, h ) ; + + // filler for the little square in the lower right corner when both sliders are visible + plug = new puFrame ( 0, 0, slider_width, slider_width ) ; + plug->setStyle ( -PUSTYLE_SMALL_BEVELLED ) ; + plug->setBorderThickness ( 2 ) ; + + if (wrap_text ) + bottom_slider = NULL ; + else + { + bottom_slider = new puaScrollBar ( 0, 0, slider_width, (arrows / 10) & 3, FALSE, slider_width ) ; + bottom_slider->setValue ( 0.0f ) ; // All the way to the left + } + + right_slider = new puaScrollBar ( 0, 0, slider_width, (arrows % 10) & 3, TRUE, slider_width ) ; + right_slider->setValue ( 1.0f ) ; // All the way to the top + right_slider->setUserData ( this ) ; + right_slider->setCallback ( puaLargeInputHandleRightSlider ) ; + + setValue ( "" ) ; + setSize ( w, h ) ; + + close () ; + reveal () ; +} + +void puaLargeInput::setSize ( int w, int h ) +{ + puGroup::setSize ( w, h ) ; + if ( w < 2 * slider_width ) w = 2 * slider_width ; + if ( h < 2 * line_height ) h = 2 * line_height ; + frame->setSize ( w, h ) ; + abox.max[0] = abox.min[0] + w ; + abox.max[1] = abox.min[1] + h ; + updateGeometry () ; +} + +void puaLargeInput::setSliderPosition ( float fraction ) +{ + if ( num_lines > lines_in_window ) + top_line_in_window = int ( ( num_lines - lines_in_window ) * fraction + 0.5f ) ; + else + top_line_in_window = 0 ; + updateGeometry () ; +} + +void puaLargeInput::updateGeometry ( void ) +{ + enum { HORIZONTAL = 1, VERTICAL = 2, BOTH = 3 } ; + int w = abox.max[0] - abox.min[0] ; + int h = abox.max[1] - abox.min[1] ; + + int frame_width = getStyle() == PUSTYLE_BOXED ? getBorderThickness() : 0 ; + hgap = int(legendFont.getFloatStringWidth(" ")) + frame_width ; + vgap = int(legendFont.getStringHeight()) / 2 + frame_width ; + line_height = legendFont.getStringHeight() + legendFont.getStringDescender() + 1 ; + input_width = w - hgap - hgap - frame_width ; + input_height = h - vgap - vgap - frame_width ; + + // determine which sliders are necessary + int slider = 0 ; + if ( bottom_slider ) { // no line wrapping + if ( max_width > input_width ) { + slider |= HORIZONTAL ; + input_height -= slider_width ; + } + if ( num_lines > input_height / line_height ) { + slider |= VERTICAL ; + input_width -= slider_width ; + } + if ( max_width > input_width && !(slider & HORIZONTAL) ) { + slider |= HORIZONTAL ; + input_height -= slider_width ; + } + if ( num_lines > input_height / line_height && !(slider & VERTICAL) ) { + slider |= VERTICAL ; + input_height -= slider_width ; + } + + } else { // with line wrapping + delete [] displayed_text ; + displayed_text = wrapText ( input_width, &num_lines, &max_width ) ; + + if ( num_lines > input_height / line_height ) { + slider |= VERTICAL ; + input_width -= slider_width ; + + delete [] displayed_text ; + displayed_text = wrapText( input_width, &num_lines, &max_width ) ; + } + } + + // horizontal slider + if ( bottom_slider ) { + bottom_slider->setSize ( w - ( slider & VERTICAL ? slider_width : 0 ), slider_width ) ; + float page_step = 1.0f, line_step = 1.0f ; + if ( max_width > input_width ) { + page_step = float(input_width) / ( max_width - input_width ) ; + line_step = legendFont.getFloatStringWidth( "M" ) / ( max_width - input_width ) ; + bottom_slider->setSliderFraction ( float(input_width) / max_width ) ; + } else { + bottom_slider->setSliderFraction ( 1.0f ) ; + bottom_slider->setValue ( 0.0f ); + } + + bottom_slider->setPageStepSize ( page_step ) ; + bottom_slider->setLineStepSize ( line_step ) ; + + if ( slider & HORIZONTAL ) + bottom_slider->reveal () ; + else + bottom_slider->hide () ; + } + + // vertical slider + lines_in_window = input_height / line_height ; + + // if the slider was in bottom position, make sure the last line is shown after lines were added + if ( right_slider->getFloatValue() <= 0.0f && right_slider->getSliderFraction() < 1.0f ) + top_line_in_window = num_lines ; + + if ( top_line_in_window + lines_in_window > num_lines ) + top_line_in_window = num_lines - lines_in_window ; + + if ( top_line_in_window < 0 ) + top_line_in_window = 0 ; + + right_slider->setPosition ( w - slider_width, slider & HORIZONTAL ? slider_width : 0 ) ; + right_slider->setSize ( slider_width, h - ( slider & HORIZONTAL ? slider_width : 0 ) ) ; + right_slider->setSliderFraction ( float(lines_in_window) / num_lines ) ; + float page_step = 1.0f ; + if ( num_lines > lines_in_window ) + page_step = float(lines_in_window) / ( num_lines - lines_in_window ) ; + + right_slider->setPageStepSize ( page_step ) ; + right_slider->setLineStepSize ( page_step / lines_in_window ) ; + + float val = 0.0f ; + if ( num_lines > lines_in_window ) + val = 1.0f - float(top_line_in_window) / (num_lines - lines_in_window ) ; + right_slider->setValue (val) ; + + if ( slider & VERTICAL ) + right_slider->reveal () ; + else + right_slider->hide () ; + + // corner filler + plug->setPosition ( w - slider_width, 0 ) ; + if ( slider == BOTH ) + plug->reveal () ; + else + plug->hide () ; +} + +void puaLargeInput::setSelectRegion ( int s, int e ) +{ + select_start_position = s ; + select_end_position = e ; + char *lin_ptr = getText() ; + char *text_start = lin_ptr ; + + if ( num_lines > lines_in_window ) + { + int select_start_line = 0 ; + while ( lin_ptr && ( lin_ptr <= text_start + select_start_position ) ) // Count the lines + { + select_start_line++ ; + lin_ptr = strchr ( lin_ptr+1, '\n' ) ; + } + + int select_end_line = select_start_line ; + while ( lin_ptr && ( lin_ptr <= text_start + select_end_position ) ) // Count the lines + { + select_end_line++ ; + lin_ptr = strchr ( lin_ptr+1, '\n' ) ; + } + + if ( select_end_line > top_line_in_window + lines_in_window ) + top_line_in_window = select_end_line - lines_in_window - 1 ; + + if ( select_start_line < top_line_in_window ) + top_line_in_window = select_start_line - 1 ; + + if ( top_line_in_window < 0 ) top_line_in_window = 0 ; + + right_slider->setValue ( num_lines - lines_in_window - top_line_in_window ) ; + } +} + +void puaLargeInput::selectEntireLine ( void ) +{ + char *temp_text = getText() ; + + if ( select_start_position < 0 ) + select_start_position = 0 ; + + if ( ( *(temp_text + select_start_position + 1) != '\n' ) && + ( *(temp_text + select_start_position) != '\0' ) ) + select_start_position ++ ; + + while ( ( select_start_position > 0 ) && ( *(temp_text + select_start_position) != '\n' ) ) + select_start_position -- ; + + if ( select_start_position > 0 ) + select_start_position++ ; + + select_end_position = int ( strchr ( temp_text + select_end_position, '\n' ) + 1 - temp_text) ; + if ( select_end_position <= 1 ) select_end_position = strlen ( temp_text ) ; + //else select_end_position = int ( select_end_position - temp_text ) ;/** Needs real fixing **/ + + puPostRefresh () ; +} + +void puaLargeInput::addNewLine ( const char *l ) +{ + char *text = getStringValue () ; + if ( cursor_position > 0 ) // If not at start of line, go to start of next line + cursor_position = int (strchr ( text + cursor_position - 1, '\n' ) - text + 1) ; + + select_end_position = select_start_position = cursor_position ; + addText ( l ) ; +} + +void puaLargeInput::addText ( const char *l ) +{ + char *text = getStringValue () ; + + if ( l == NULL ) return ; + + int l_len = strlen ( l ) ; + int text_len = strlen ( text ) ; + int length = l_len + text_len /* Length of the final string */ + + select_start_position - select_end_position + 2 ; + if ( *(l+l_len-1) == '\n' ) length -- ; // Decrement "length" for each final + if ( text[select_end_position] == '\n' ) length -- ; // carriage return already there + + char *temp_text = new char [ length ] ; + + memcpy ( temp_text, text, select_start_position ) ; + memcpy ( temp_text + select_start_position, l, l_len + 1 ) ; /* Plus one to get the final '\0' */ + int temp_text_len = select_start_position + l_len ; + + if ( ( *(l+l_len-1) == '\n' ) && ( text[select_end_position] == '\n' ) ) + { + temp_text[temp_text_len-1] = '\0' ; /* Erase the duplicate carriage return */ + temp_text_len -- ; + } + else if ( ( *(l+l_len-1) != '\n' ) && ( text[select_end_position] != '\n' ) ) + { + strcpy ( temp_text + temp_text_len, "\n" ) ; /* Add a carriage return */ + temp_text_len ++ ; + } + + memcpy ( temp_text + temp_text_len, text + select_end_position, text_len - select_end_position + 1 ) ; + int temp_select_start = select_start_position ; + setValue ( temp_text ) ; + delete [] temp_text ; + setSelectRegion ( temp_select_start, + temp_select_start + strlen(l) ) ; + setCursor ( select_end_position ) ; +} + +void puaLargeInput::appendText ( const char *l ) +{ + if ( !l ) return ; + + int str_val_len = strlen ( getStringValue () ) ; + int l_len = strlen ( l ) ; + if ( str_val_len == 1 ) str_val_len = 0 ; /* Don't want null line at the beginning */ + int length = str_val_len + l_len + 2 ; + if ( *(l+l_len-1) == '\n' ) length -- ; /* Already have a trailing carriage return, decrement the length */ + + char *temp_text = new char [ length ] ; + int temp_text_len ; + + if ( str_val_len > 0 ) /* More than just the empty carriage return */ + { + memcpy ( temp_text, getStringValue (), str_val_len ) ; + temp_text_len = str_val_len ; + } + else + temp_text_len = 0 ; + + memcpy ( temp_text + temp_text_len, l, l_len + 1 ) ; /* Plus one to get the final '\0' */ + temp_text_len += l_len ; + if ( *(l+l_len-1) != '\n' ) + { + strcpy ( temp_text + temp_text_len, "\n" ) ; + temp_text_len ++ ; + } + + setValue ( temp_text ) ; + setSelectRegion ( str_val_len, temp_text_len ) ; + setCursor ( str_val_len ) ; + delete [] temp_text ; +} + +void puaLargeInput::removeText ( int start, int end ) +{ + int str_val_len = strlen ( getStringValue () ) ; + char *temp_text = new char [ str_val_len + start - end + 1 ] ; + memcpy ( temp_text, getStringValue (), start ) ; + memcpy ( temp_text + start, getStringValue ()+end, str_val_len - end + 1 ) ; /* Plus one to get the final '\0' */ + setValue ( temp_text ) ; + setCursor ( start ) ; + setSelectRegion ( start, start ) ; + delete [] temp_text ; +} + +void puaLargeInput::setValue ( const char *s ) +{ + if (!s || !*s) { + puValue::setValue ( "\n" ) ; + cursor_position = select_start_position = select_end_position = 0 ; + + } else { + int len = strlen(s); + if (s[len - 1] == '\n') { + puValue::setValue ( s ) ; + + } else { + char *buf = new char [ len + 2 ] ; + strcpy ( buf, s ) ; + strcat ( buf, "\n" ) ; + puValue::setValue ( buf ) ; + delete [] buf ; + } + } + + if ( bottom_slider ) + getTextProperties ( &num_lines, &max_width ) ; + + updateGeometry () ; + normalizeCursors () ; +} + + +void puaLargeInput::draw ( int dx, int dy ) +{ + if ( !visible || ( window != puGetWindow () ) ) return ; + normalizeCursors () ; + + // 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, border_thickness ) ; + plug->draw ( abox.min[0] + dx, abox.min[1] + dy ) ; + + if ( r_cb ) + r_cb ( this, dx, dy, render_data ) ; + else + { + // Calculate window parameters: + + int xwidget = abox.min[0] + dx ; + int ywidget = abox.min[1] + dy ; + + int xx = hgap; + int yy = abox.max[1] - abox.min[1] - legendFont.getStringHeight () - vgap ; + + float bottom_value = bottom_slider ? bottom_slider->getFloatValue () : 0.0f ; + + int beg_pos // Position in window of start of line, in pixels + = int(( input_width - max_width ) * bottom_value ) ; +//// int end_pos // Position in window of end of line, in pixels +//// = beg_pos + max_width - 1 ; + if ( top_line_in_window < 0 ) top_line_in_window = 0 ; + int end_lin // Position on line count of bottom of window, in lines + = top_line_in_window + lines_in_window ; + + char *val = getText () ; + + // Highlight the select area + + if ( select_end_position > 0 && select_end_position != select_start_position ) + { + // First: find the positions on the window of the selection start and end + + char temp_char = val[ select_start_position ] ; + val [ select_start_position ] = '\0' ; + + xx = dx + abox.min[0] + hgap ; + yy = abox.max[1] - abox.min[1] - legendFont.getStringHeight () - vgap + + top_line_in_window * line_height ; // Offset y-coord for unprinted lines + + char *end_of_line = strchr ( val, '\n' ) ; + char *start_of_line = val ; + + // Step down the lines until you reach the line with the selection start + + int select_start_line = 0 ; + + while ( end_of_line ) + { + select_start_line++ ; + start_of_line = end_of_line + 1 ; + yy -= line_height ; + end_of_line = strchr ( start_of_line, '\n' ) ; + } + + int start_pos = int(legendFont.getFloatStringWidth ( start_of_line )) + xx + + beg_pos ; // Start of selection + + val [ select_start_position ] = temp_char ; + + // Now repeat the process for the end of the selection. + + temp_char = val[ select_end_position ] ; + val [ select_end_position ] = '\0' ; + + end_of_line = strchr ( start_of_line, '\n' ) ; + + // Step down the lines until you reach the line with the selection end + + int select_end_line = select_start_line ; + + while ( end_of_line ) + { + select_end_line++ ; + start_of_line = end_of_line + 1 ; + end_of_line = strchr ( start_of_line, '\n' ) ; + } + + int end_pos = int(legendFont.getFloatStringWidth ( start_of_line )) + xx + + beg_pos ; // End of selection + + val [ select_end_position ] = temp_char ; + + // Now draw the selection area. + + for ( int line_count = select_start_line ; ( ( line_count <= select_end_line ) && ( line_count < end_lin ) ) ; + line_count++ ) + { + if ( line_count >= top_line_in_window ) + { + int x_start, x_end ; + + if ( line_count == select_start_line ) + x_start = ( start_pos > xx ) ? start_pos : xx ; + else + x_start = xx ; + + x_start = ( x_start < abox.max[0] + dx ) ? x_start : abox.max[0] + dx ; + + if ( line_count == select_end_line ) + x_end = ( end_pos < abox.max[0] + dx ) ? end_pos : abox.max[0] + dx ; + else + x_end = abox.max[0] + dx ; + + x_end = ( x_end > xx ) ? x_end : xx ; + + int top = dy + abox.min[1] + yy + legendFont.getStringHeight () ; + int bot = dy + abox.min[1] + yy - legendFont.getStringDescender() ; + + glColor3f ( 1.0f, 1.0f, 0.7f ) ; + glRecti ( x_start, bot, x_end, top ) ; + } + + yy -= line_height ; + if ( line_count == end_lin ) break ; + } + } + + + // Draw the text + + { + // If greyed out then halve the opacity when drawing the text + + 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 = getText () ; // Pointer to the actual text in the box + + if ( val ) + { + char *end_of_line = strchr (val, '\n') ; + int line_count = 0; + + xx = hgap; + yy = abox.max[1] - abox.min[1] - legendFont.getStringHeight () - vgap + 1 ; + + while ( end_of_line ) // While there is a carriage return in the string + { + if ( line_count < top_line_in_window ) + { // Before the start of the window + val = end_of_line + 1 ; + end_of_line = strchr (val, '\n') ; // Just go to the next line + } + else if ( line_count < end_lin ) // Within the window, draw it + { + char temp_char = *end_of_line ; // Temporary holder for last char on line + + *end_of_line = '\0' ; // Make end-of-line be an end-of-string + + int start_pos = beg_pos ; + int end_pos // Position in window of end of line, in pixels + = start_pos + int(legendFont.getFloatStringWidth ( val )) ; + + if ( end_pos > start_pos ) // If we actually have text in the line + { + char * lastonleft = val ; + char * firstonright = end_of_line ; + int leftpos = start_pos ; + int rightpos = end_pos ; + while ( lastonleft < firstonright - 1 ) + { + int chpos = -leftpos * ( firstonright - lastonleft ) / ( rightpos - leftpos ) + 1; + if ( chpos >= firstonright - lastonleft ) chpos = firstonright - lastonleft - 1 ; + char placeholder = *(lastonleft + chpos) ; + *(lastonleft + chpos) = '\0' ; + int strwidth = legendFont.getStringWidth ( val ) ; + *(lastonleft + chpos) = placeholder ; + if ( strwidth + start_pos < 0 ) /* Still to the left of the window */ + { + lastonleft = lastonleft + chpos ; + placeholder = *lastonleft ; + *lastonleft = '\0' ; + leftpos = start_pos + legendFont.getStringWidth ( val ) ; + *lastonleft = placeholder ; + } + else + { + firstonright = lastonleft + chpos ; + placeholder = *firstonright ; + *firstonright = '\0' ; + rightpos = start_pos + legendFont.getStringWidth ( val ) ; + *firstonright = placeholder ; + } + } + if ( leftpos >= 0 ) + { + val = lastonleft ; + start_pos = leftpos ; + } + else + { + val = firstonright ; + start_pos = rightpos ; + } + } + + while ( end_pos > input_width ) // Step up the line until it is in the window + { + *end_of_line = temp_char ; + end_of_line-- ; + temp_char = *end_of_line ; + *end_of_line = '\0' ; + end_pos = start_pos + legendFont.getStringWidth ( val ) ; + } + + if ( val < end_of_line ) // If any text shows in the window, + legendFont.drawString ( val, // draw it. + dx + abox.min[0] + xx + start_pos, + dy + abox.min[1] + yy ) ; + + *end_of_line = temp_char ; // Restore the end-of-line character + + if ( temp_char != '\n' ) // If we had to step up from the end of + end_of_line = strchr (val, '\n') ; // the line, go back to the actual end + + yy -= line_height ; + val = end_of_line + 1 ; + end_of_line = strchr (val, '\n') ; // On to the next line + } + else if ( line_count >= end_lin ) // Have gone beyond window, end process + end_of_line = NULL ; + + line_count++ ; + + } // while ( end_of_line ) + } // if ( val ) + } + + if ( accepting ) + { + char *val = getText () ; // Pointer to the actual text in the box + + // Draw the 'I' bar cursor. + + if ( val && ( cursor_position >= 0 ) ) + { + char temp_char = val[ cursor_position ] ; + val [ cursor_position ] = '\0' ; + + xx = hgap ; + yy = abox.max[1] - abox.min[1] - legendFont.getStringHeight () - vgap + + top_line_in_window * line_height ; // Offset y-coord for unprinted lines + + char *end_of_line = strchr ( val, '\n' ) ; + char *start_of_line = val ; + + // Step down the lines until you reach the line with the cursor + + int line_count = 1 ; + + while ( end_of_line ) + { + line_count++ ; + start_of_line = end_of_line + 1 ; + yy -= line_height ; + end_of_line = strchr ( start_of_line, '\n' ) ; + } + + if ( ( line_count > top_line_in_window ) && ( line_count <= end_lin ) ) + { + int begpos // Position in window of start of line, in pixels + = int( ( input_width - max_width ) * bottom_value ) ; + int cpos = int( legendFont.getFloatStringWidth ( start_of_line ) + xx + + abox.min[0] + begpos ) ; + int top = int( abox.min[1] + yy + legendFont.getStringHeight () ) ; + int bot = int( abox.min[1] + yy - legendFont.getStringDescender () ) ; + if ( ( cpos > abox.min[0] ) && ( cpos < abox.max[0] ) ) + { + glColor4fv ( colour [ PUCOL_MISC ] ) ; + glBegin ( GL_LINES ) ; + glVertex2i ( dx + cpos , dy + bot ) ; + glVertex2i ( dx + cpos , dy + top ) ; + glVertex2i ( dx + cpos - 1, dy + bot ) ; + glVertex2i ( dx + cpos - 1, dy + top ) ; + glVertex2i ( dx + cpos - 4, dy + bot ) ; + glVertex2i ( dx + cpos + 3, dy + bot ) ; + glVertex2i ( dx + cpos - 4, dy + top ) ; + glVertex2i ( dx + cpos + 3, dy + top ) ; + glEnd () ; + } + } + + val[ cursor_position ] = temp_char ; + } + } + + // Draw the other widgets in the large input box + + if ( bottom_slider ) bottom_slider->draw ( xwidget, ywidget ) ; + right_slider->draw ( xwidget, ywidget ) ; + } + + draw_label ( dx, dy ) ; +} + + +int puaLargeInput::checkHit ( int button, int updown, int x, int y ) +{ + if ( ( button == PU_SCROLL_UP_BUTTON || button == PU_SCROLL_DOWN_BUTTON ) && isHit( x, y ) ) + { + int sx, sy; + right_slider->getPosition ( &sx, &sy ); + return right_slider->checkHit ( button, updown, ++sx, ++sy ) ; + } + + int xwidget = x - abox.min[0] ; + int ywidget = y - abox.min[1] ; + + if ( bottom_slider ) + { + if ( bottom_slider->checkHit ( button, updown, xwidget, ywidget ) ) return TRUE ; + } + + if ( right_slider->checkHit ( button, updown, xwidget, ywidget ) ) return TRUE ; + + // If the user has clicked within the bottom slider or to its right, don't activate. + + if ( y < slider_width ) return FALSE ; + + if ( puObject::checkHit ( button, updown, x, y ) ) + return TRUE ; + + return FALSE ; +} + + +void puaLargeInput::doHit ( int button, int updown, int x, int y ) +{ + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + // Active widget exists and is not this one; call its down callback if it exists + + puActiveWidget()->invokeDownCallback () ; + puDeactivateWidget () ; + } + + if ( updown != PU_DRAG ) + puMoveToLast ( this ) ; + + if ( button == active_mouse_button ) + { + // Most GUI's activate a button on button-UP not button-DOWN. + + // Text and window parameters: + + float bottom_value = bottom_slider ? bottom_slider->getFloatValue () : 0.0f ; + + int beg_pos // Position in window of start of line, in pixels + = int( ( input_width - max_width ) * bottom_value ) ; +// int end_pos // Position in window of end of line, in pixels +// = (int)( beg_pos + max_width - 1 ) ; + if ( top_line_in_window < 0 ) top_line_in_window = 0 ; +// int end_lin // Position on line count of bottom of window, in lines +// = top_line_in_window + lines_in_window - 1 ; + +// int xx = legendFont.getStringWidth ( " " ) ; + int yy = int( abox.max[1] - legendFont.getStringHeight () - vgap + + top_line_in_window * line_height ) ; // Offset y-coord for unprinted lines + + // Get the line number and position on the line of the mouse + char *tmpval = ulStrDup ( getText() ) ; + + int i = strlen ( tmpval ) ; + + char *end_of_line = strchr ( tmpval, '\n' ) ; + char *start_of_line = tmpval ; + + // Step down the lines until the y-coordinate is less than the mouse + + int line_count = 0 ; + + while ( ( yy > y ) && end_of_line ) + { + line_count++ ; + start_of_line = end_of_line + 1 ; + yy -= line_height ; + end_of_line = strchr ( start_of_line, '\n' ) ; + } + + if ( end_of_line ) + { + *end_of_line = '\0' ; + + i = strlen ( tmpval ) ; + + int length, prev_length = 0 ; + while ( x <= (length = legendFont.getStringWidth ( start_of_line ) + + abox.min[0] + beg_pos) && + i > 0 ) + { + prev_length = length ; + tmpval[--i] = '\0' ; + } + + if ( ( x - length ) < ( prev_length - x ) ) + i-- ; // Mouse is closer to previous character than next character + } + + // Now process the mouse click itself. + + if ( updown == active_mouse_edge || active_mouse_edge == PU_UP_AND_DOWN ) + { + lowlight () ; + + accepting = TRUE ; + cursor_position = i ; + normalizeCursors () ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + } + else if ( updown == PU_DOWN ) + { + // We get here if the active edge is not down but the mouse button has + // been pressed. Start a selection. + + select_start_position = i ; + select_end_position = i ; + } + else if ( updown == PU_DRAG ) + { + // Drag -- extend the selection. + + if ( (select_end_position - i) > (i - select_start_position) ) + select_start_position = i ; // Cursor closer to start than to end + else + select_end_position = i ; // Cursor closer to end than to start + + if (select_start_position > select_end_position) + { + i = select_end_position ; + select_end_position = select_start_position ; + select_start_position = i ; + } + } + else + highlight () ; + + delete [] tmpval ; + } + else + lowlight () ; +} + +int puaLargeInput::checkKey ( int key, int updown ) +{ + if ( updown == PU_UP || !isAcceptingInput () || !isActive () || + !isVisible () || ( window != puGetWindow () ) ) + return FALSE ; + + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + // Active widget exists and is not this one; call its down callback if it exists + + puActiveWidget()->invokeDownCallback () ; + puDeactivateWidget () ; + } + + normalizeCursors () ; + + //char *old_text = getStringValue () ; + char *old_text = getText () ; + int lines_in_window = getLinesInWindow () ; /* Added lines_in_window and num_lines to allow for "END" */ + int num_lines = getNumLines () ; /* and PGUP/DOWN to work properly - JCJ 20 Jun 2002 */ + int line_width = 0 ; /* Width of current line (for bottomslider) */ + int line_width_to_cursor = 0 ; /* Width of current line up to the cursor position */ + int prev_line_width = 0 ; /* Width of previous line (for left mouse arrow) */ + int i = 1; /* Happy useful variable */ + int line_counter = 0 ; /* Happy useful variable #2 */ + int tmp_cursor_position = cursor_position ; /* Temporary cursor position for counting without moving the cursor */ + int bottom_line_in_window = 0; /* # of bottom line in window */ + int current_line_in_window = 0; /* Current line # in window */ + char *line_end = 0 ; + char* p = new char[ strlen(old_text)+1 ] ; + float bottom_value = bottom_slider ? bottom_slider->getFloatValue () : 0.0f ; /* Value of the bottom slider */ + if ( old_text[1] != '\0' ) /* Ensure that we don't delete something that doesn't exist! - JCJ 22 July 2002 */ + { + /*Count how many characters from the beginning of the line the cursor is*/ + while ( ( old_text [ cursor_position - i ] != '\n' ) && + ( i < cursor_position ) ) + i++ ; /* Step back to the beginning of the line */ + if ( i < cursor_position ) i-- ; + + /*Find the length of the current line*/ + while ( ( old_text [ tmp_cursor_position ] != '\n' ) && + ( tmp_cursor_position > 0) ) + tmp_cursor_position-- ; + + strcpy ( p, ( old_text + tmp_cursor_position + 1 ) ) ; + if ( bottom_slider ) + { + line_end = strchr ( p, '\n' ) ; + if ( line_end ) // Found an end-of-line + { + *line_end = '\0' ; // Temporary break in line + line_width = int(legendFont.getFloatStringWidth ( p )) ; + *line_end = '\n' ; // Reset the carriage return + } + /*Now delete all characters in the string beyond i, and re-find its width*/ + p [i+1] = '\0' ; + line_width_to_cursor = int(legendFont.getFloatStringWidth ( p )) ; + } + + /* Now find the length of the previous line */ + tmp_cursor_position-- ; + while ( ( old_text [ tmp_cursor_position ] != '\n' ) && + ( tmp_cursor_position > 0) ) + tmp_cursor_position-- ; + + strcpy ( p, ( old_text + tmp_cursor_position + 1 ) ) ; + if ( bottom_slider ) + { + line_end = strchr ( p, '\n' ) ; + if ( line_end ) /*Actually, we KNOW there's a line after this one, but hey, let's be safe, eh? - JCJ 21 Jun 2002 */ + { + *line_end = '\0' ; // Temporary break in line + prev_line_width = legendFont.getStringWidth ( p ) ; + *line_end = '\n' ; // Reset the carriage return + } + } + + delete [] p ; + p = NULL ; + } + + bool done = true ; + + switch ( key ) + { + case PU_KEY_PAGE_UP : + while ( old_text [ cursor_position ] != '\0' ) /* Move the cursor to the top of the data */ + cursor_position-- ; + select_start_position = select_end_position = cursor_position ; + setTopLineInWindow ( top_line_in_window - lines_in_window + 2 ) ; + right_slider->setValue (1.0f - float(top_line_in_window) / num_lines ) ; + break; + case PU_KEY_PAGE_DOWN : + while ( old_text [ cursor_position ] != '\0' ) /* Move the cursor to the end of the data */ + cursor_position++ ; + select_start_position = select_end_position = cursor_position ; + setTopLineInWindow ( top_line_in_window + lines_in_window - 2 ) ; /* Plus two for consistency - JCJ 20 Jun 2002 */ + right_slider->setValue (1.0f - float(top_line_in_window) / num_lines ) ; + break; + case PU_KEY_INSERT : return FALSE ; + + case PU_KEY_UP : + case PU_KEY_DOWN : + /* Determine the current line, the line at the top of the window, and the line at the bottom.*/ + bottom_line_in_window = top_line_in_window + getLinesInWindow() ; + while ( line_counter < cursor_position) { + if ( old_text [ line_counter ] == '\n' ) current_line_in_window++ ; + line_counter++ ; + } + if ( key == PU_KEY_UP ) + { + // Step backwards to the beginning of the previous line + cursor_position -= (i + 2) ; + while ( ( old_text [ cursor_position ] != '\n' ) && + ( cursor_position > 0 ) ) + cursor_position-- ; + if ( cursor_position > 0 ) cursor_position++ ; + + // Step down the line "i" spaces or to the end of the line + while ( ( old_text [ cursor_position ] != '\n' ) && + ( i > 0 ) ) + { + cursor_position++ ; + i-- ; + } + if (current_line_in_window <= top_line_in_window) { + setTopLineInWindow ( top_line_in_window - 1 ); /* Go up - JCJ 21 Jun 2002 */ + right_slider->setValue (1.0f - float(top_line_in_window) / num_lines ) ; + } + } + else // Down-arrow key + { + // Skip to beginning of next line + while ( old_text [ cursor_position ] != '\n' && old_text [ cursor_position ] != '\0' ) + cursor_position++ ; + cursor_position++ ; + + // Step down the line "i" spaces or to the end of the line + // or to the end of the text + + while ( ( old_text [ cursor_position ] != '\n' ) && + ( cursor_position < (int)strlen ( old_text ) ) && + ( i > 0 ) ) + { + cursor_position++ ; + i-- ; + } + if ((current_line_in_window+1) >= bottom_line_in_window) { + setTopLineInWindow ( top_line_in_window + 1 ); /* Go down - JCJ 21 Jun 2002 */ + right_slider->setValue (1.0f - float(top_line_in_window) / num_lines ) ; + } + } + + select_start_position = select_end_position = cursor_position ; + break ; + + case 0x1B : // ESC + case '\t' : // TAB -- End of input + rejectInput () ; + normalizeCursors () ; + invokeCallback () ; + puDeactivateWidget () ; + break ; + + case PU_KEY_HOME : + while ( ( old_text [ cursor_position-1 ] != '\n' ) && + ( cursor_position > 0 ) ) /* Move the cursor to the start of the line, but minus one so */ + cursor_position-- ; /* it does not find a \n immediately if located at the end. */ + select_start_position = select_end_position = cursor_position ; /* Also corrects overshoots. - JCJ 20 Jun 2002 */ + if ( bottom_slider ) bottom_slider->setValue ( 0.0f ) ; + break ; + case PU_KEY_END : + if (bottom_slider) + { + bottom_slider->setValue ( ( (line_width - input_width)<0 ) ? 0.0f : float(line_width+10) / max_width); + } + while ( old_text [ cursor_position ] != '\n' ) /* Move the cursor to the end of the line - JCJ 20 Jun 2002 */ + cursor_position++ ; + select_start_position = select_end_position = cursor_position ; + break ; + + case PU_KEY_LEFT : + case PU_KEY_RIGHT : + if ( key == PU_KEY_LEFT ) + { + /* This stops it crashing out sometimes when wrappable text is used. + * Since there is no bottom scrollbar when wrapped text is turned on, the bottom + * slider code could make the application die when the user pressed the left + * cursor key before they began the first line. + * Fix by Simon */ + cursor_position-- ; /* Left key pressed */ + if ( bottom_slider ) + { + if (old_text [ cursor_position ] == '\n') + bottom_slider->setValue( ( (prev_line_width - input_width)<0 ) ? 0.0f : float(prev_line_width+10) /max_width); + /* If the cursor is going off the left edge of the box, scroll left. */ + else if ((bottom_value*max_width) > line_width_to_cursor+5) { + bottom_slider->setValue( ((bottom_value*max_width)-(input_width/2)-5)<0 ? 0.0f : + ((bottom_value*max_width)-(input_width/2)-5)/max_width ) ; + } + } + } else { + cursor_position++ ; /* Right key pressed */ + if ( bottom_slider ) { + if (old_text [ cursor_position-1 ] == '\n') + bottom_slider->setValue(0.0f) ; + else if ((bottom_value*max_width)+(input_width) < line_width_to_cursor+5) { + bottom_slider->setValue( ((bottom_value*max_width)+(input_width/2)+5)/max_width ) ; + } + } + } + select_start_position = select_end_position = cursor_position ; + break ; + + default : + done = false ; + break ; + } + + if ( ! done && ! input_disabled ) + { + char *p = NULL ; + int temp_cursor = cursor_position ; + + switch ( key ) + { + case '\b' : // Backspace + if ( select_start_position != select_end_position ) + removeSelectRegion () ; + else if ( cursor_position > 0 ) + { + p = new char [ strlen(old_text) ] ; + memcpy ( p, old_text, cursor_position ) ; + --cursor_position ; + strcpy ( p + cursor_position, old_text + cursor_position + 1 ) ; + setValue ( p ) ; + setCursor ( temp_cursor - 1 ) ; + delete [] p ; + } + + break ; + + case 0x7F : // DEL + if ( select_start_position != select_end_position ) + removeSelectRegion () ; + else if (cursor_position != (int)strlen ( old_text ) ) + { + p = new char [ strlen(old_text) ] ; + memcpy ( p, old_text, cursor_position ) ; + strcpy ( p + cursor_position, old_text + cursor_position + 1 ) ; + setValue ( p ) ; + setCursor ( temp_cursor ) ; + delete [] p ; + } + + break ; + + case 0x15 /* ^U */ : getStringValue () [ 0 ] = '\0' ; break ; + case 0x03 /* ^C */ : + case 0x18 /* ^X */ : /* Cut or copy selected text */ + if ( select_start_position != select_end_position ) + { + extern void puSetPasteBuffer ( const char *ch ) ; + p = getStringValue () ; + char ch = p[select_end_position] ; + p[select_end_position] = '\0' ; + puSetPasteBuffer ( p + select_start_position ) ; + p[select_end_position] = ch ; + + if ( key == 0x18 ) /* Cut, remove text from string */ + removeSelectRegion () ; + } + + break ; + + case 0x16 /* ^V */ : /* Paste buffer into text */ + { + extern char *puGetPasteBuffer () ; + if ( select_start_position != select_end_position ) + removeSelectRegion () ; + + if ( puGetPasteBuffer () ) // Make sure something has been cut previously! + { + int str_val_len = strlen ( getStringValue () ) ; + int paste_len = strlen ( puGetPasteBuffer () ) ; + p = new char [ str_val_len + paste_len + 1 ] ; + memcpy ( p, getStringValue (), cursor_position ) ; + memcpy ( p + cursor_position, puGetPasteBuffer (), paste_len ) ; + memcpy ( p + cursor_position + paste_len, getStringValue() + cursor_position, str_val_len - cursor_position + 1 ) ; + temp_cursor += paste_len ; + setValue ( p ) ; + setCursor ( temp_cursor ) ; + delete [] p ; + } + } + + break ; + + default: + if ( ( key < ' ' || key > 127 ) && ( key != '\n' ) + && ( key != '\r' ) ) return FALSE ; + + if ( key == '\r' ) key = '\n' ; + + if ( valid_data ) + { + if ( !strchr ( valid_data, key ) ) return TRUE ; + } + + if ( select_start_position != select_end_position ) // remove selected text + { + temp_cursor -= ( select_end_position - select_start_position ) ; + removeSelectRegion () ; + } + + p = new char [ strlen(old_text) + 2 ] ; + + memcpy ( p, old_text, cursor_position ) ; + + p [ cursor_position ] = key ; + + strcpy ( p + cursor_position + 1, ( old_text + cursor_position ) ) ; + bottom_line_in_window = top_line_in_window + getLinesInWindow() ; + + /* If running off the screen, scroll right. - JCJ 28 Jun 2002 */ + if ((bottom_value*max_width)+(input_width) < line_width_to_cursor+5) { + bottom_slider->setValue( ((bottom_value*max_width)+(input_width/2)+5)/max_width ) ; + } + + if (key == '\n') { + /* If pressing enter, figure out which line this is. */ + while ( line_counter < cursor_position) { + if ( old_text [ line_counter ] == '\n' ) current_line_in_window++ ; + line_counter++ ; + } + /* If hitting enter at the bottom of the screen, scroll down. - JCJ 28 Jun 2002 */ + if ( (current_line_in_window+1) >= bottom_line_in_window ) { + setTopLineInWindow ( top_line_in_window + 1 ); + right_slider->setValue (1.0f - float(top_line_in_window) / num_lines ) ; + } + } + + setValue ( p ) ; + setCursor ( temp_cursor + 1 ) ; + delete [] p ; + + break ; + } + } + + normalizeCursors () ; + return TRUE ; +} + +void puaLargeInput::getTextProperties(int *numlines, int *maxwidth) +{ + int num = 0, max = 0 ; + char *buf = ulStrDup ( getStringValue () ), *s = buf ; + while ( *s ) { + char *cr = strchr ( s, '\n' ) ; + if ( cr ) + *cr = '\0' ; + int w = legendFont.getStringWidth (s) ; + if ( w > max ) + max = w ; + num++ ; + if ( cr ) + s = ++cr ; + } + *numlines = num ; + *maxwidth = max ; + delete [] buf ; +} + +char *puaLargeInput::wrapText ( int target_width, int *numlines, int *maxwidth ) +{ + char *buf = ulStrDup ( getStringValue () ) ; + int numl = 0 ; + int maxw = 0 ; + + char *displayed_text_wp = buf, + *space_ptr, + *old_space_ptr ; + + /* Somewhat inspired by tuxracer */ + while ( *displayed_text_wp != '\0' ) + { + old_space_ptr = NULL ; + space_ptr = strchr ( displayed_text_wp, ' ' ) ; + + while (1) + { + if ( space_ptr != NULL ) + *space_ptr = '\0' ; + + int w = legendFont.getStringWidth ( displayed_text_wp ) ; + if ( w > target_width ) + break ; + + if ( w > maxw ) maxw = w ; + old_space_ptr = space_ptr ; + + if ( space_ptr == NULL ) + /* Entire string fits in widget */ + break ; + + // Check for carriage return in the original string + for (char *s = 0; (s = strchr ( displayed_text_wp, '\n' )); displayed_text_wp = s + 1) + numl++; + + *space_ptr = ' ' ; + + space_ptr = strchr ( space_ptr+1, ' ' ) ; + } + + numl++ ; + if ( old_space_ptr == NULL ) + /* Either string is too wide for area, or the entire remaining portion + of string fits in area (space_ptr == NULL). */ + { + displayed_text_wp += strlen (displayed_text_wp) ; + + if ( space_ptr != NULL ) + /* Advance past the NULL since there's more string left */ + displayed_text_wp += 1 ; + } + else + { + if ( space_ptr != NULL ) + *space_ptr = ' ' ; + *old_space_ptr = '\n' ; + + displayed_text_wp = old_space_ptr + 1 ; + } + } + if (numlines) *numlines = numl ; + if (maxwidth) *maxwidth = maxw ; + return buf ; +} + + diff --git a/src/puAux/puAuxList.cxx b/src/puAux/puAuxList.cxx new file mode 100644 index 0000000..2e3d570 --- /dev/null +++ b/src/puAux/puAuxList.cxx @@ -0,0 +1,317 @@ +/* + PUI Auxiliary Widget Library + Derived from PLIB, the Portable Game Library by Steve Baker. + Copyright (C) 1998,2002,2004 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puAuxList.cxx 2161 2010-02-27 04:06:53Z fayjf $ +*/ + + +#include "puAuxLocal.h" + +UL_RTTI_DEF1(puaList,puGroup) +// puAuxList.cxx - implementation of a scrolling list box. + +#include "puAux.h" + + +/** + * Static function: handle slider movements. + */ +static void +handle_slider (puObject * slider) +{ + puListBox * list_box = (puListBox *)slider->getUserData(); + + int total = list_box->getNumItems(); + int visible = list_box->getNumVisible(); + // negative numbers are OK -- setTopItem() clamps anyway + int index = int((total - visible) * (1.0 - slider->getFloatValue())); + list_box->setTopItem(index); +} + + +/** + * Static function: handle list entry selection. + */ +static void +handle_list_entry (puObject * listbox) +{ + puaList * box = (puaList *)listbox->getUserData(); + box->invokeCallback(); +} + + +/** + * Static function: handle arrow clicks. + */ +static void +handle_arrow (puObject * arrow) +{ + puSlider * slider = (puSlider *)arrow->getUserData(); + puListBox * list_box = (puListBox *)slider->getUserData(); + puaList * list = (puaList *)list_box->getUserData(); + + int step; + switch (((puArrowButton *)arrow)->getArrowType()) { + case PUARROW_DOWN: + step = 1; + break; + case PUARROW_UP: + step = -1; + break; + default: + step = 0; + break; + } + + int index = list->getTopItem(); + list->setTopItem(index + step); + slider->setValue(1.0f - float(list->getTopItem()) / (list->getNumItems() - list->getNumVisible())); +} + +/* Create an empty list box. */ +puaList::puaList (int x, int y, int w, int h, int sl_width) : + puGroup(x, y), + _sw(sl_width) +{ + type |= PUCLASS_LIST; + init(w, h, 1); +} + +/* Create a filled list box. */ +puaList::puaList (int x, int y, int w, int h, char ** contents, int sl_width) : + puGroup(x, y), + _sw(sl_width) +{ + type |= PUCLASS_LIST; + init(w, h, 1); + newList(contents); +} + +/* Create an empty list box. */ +puaList::puaList (int x, int y, int w, int h, short transparent, int sl_width) : + puGroup(x, y), + _sw(sl_width) +{ + type |= PUCLASS_LIST; + init(w, h, transparent); +} + +/* Create a filled list box. */ +puaList::puaList (int x, int y, int w, int h, short transparent, + char ** contents, int sl_width) : + puGroup(x, y), + _sw(sl_width) +{ + type |= PUCLASS_LIST; + init(w, h, transparent); + newList(contents); +} + +puaList::~puaList () +{ +} + +void +puaList::newList (char ** contents) +{ + _list_box->newList(contents); + _contents = contents; + + // new size calculation to consider slider visibility + setSize(_width, _height); +} + +void +puaList::setTopItem (int item_index) +{ + _list_box->setTopItem(item_index); + item_index = _list_box->getTopItem(); + // read clamped value back in, and only set slider if it doesn't match the new + // index to avoid jumps + int slider_index = int((1.0f - _slider->getFloatValue()) * (getNumItems() - getNumVisible())); + if (slider_index != item_index) + _slider->setValue(1.0f - float(getTopItem()) / (getNumItems() - getNumVisible())); +} + +/* + * Return a pointer to a character string with the + * contents of the selected entry. + */ +char * +puaList::getStringValue () +{ + int currElem = _list_box->getIntegerValue(); + if (currElem < 0) + { + return NULL; + } + else + { + return _contents[currElem]; + } +} + +/* + * Set a pointer to a character string with the + * contents of the selected entry + */ +void +puaList::getValue(char **ps) +{ + int currElem = _list_box->getIntegerValue(); + if (currElem < 0) + { + *ps = NULL; + } + else + { + *ps = _contents[currElem]; + } +} + + +/* + * Set the integer pointed to by "i" to + * the index of the currently selected entry. + */ +void +puaList::getValue(int *i) +{ + *i = _list_box->getIntegerValue(); +} + +/* Return the index of the currently selected entry. */ +int +puaList::getIntegerValue() +{ + return _list_box->getIntegerValue(); +} + +void +puaList::setColourScheme (float r, float g, float b, float a) +{ + puObject::setColourScheme(r, g, b, a); + _list_box->setColourScheme(r, g, b, a); +} + +void +puaList::setColour (int which, float r, float g, float b, float a) +{ + puObject::setColour(which, r, g, b, a); + _list_box->setColour(which, r, g, b, a); +} + +void +puaList::setSize (int w, int h) +{ + _width = w; + _height = h; + puObject::setSize(w, h); + if (_frame) + _frame->setSize(w, h); + + int total = getNumItems(); + int visible = getNumVisible(); + + if (total > visible) + { + if (!_slider->isVisible()) + { + _slider->setValue(1.0f); + _slider->reveal(); + _up_arrow->reveal(); + _down_arrow->reveal(); + } + _list_box->setSize(w-_sw, h); + + _slider->setPosition(w-_sw, _sw); + _slider->setSize(_sw, h-2*_sw); + _slider->setSliderFraction(float(visible) / total); + _slider->setPageStepSize(float(visible) / (total - visible)); + + _down_arrow->setPosition(w-_sw, 0); + _up_arrow->setPosition(w-_sw, h-_sw); + + } + else + { + if (_slider->isVisible()) + { + _slider->hide(); + _up_arrow->hide(); + _down_arrow->hide(); + } + _list_box->setSize(w, h); + } +} + +int +puaList::checkHit (int button, int updown, int x, int y) +{ + if (updown == PU_UP && isHit(x, y)) + { + if (button == PU_SCROLL_UP_BUTTON) + { + _up_arrow->invokeCallback(); + return TRUE; + } + if (button == PU_SCROLL_DOWN_BUTTON) + { + _down_arrow->invokeCallback(); + return TRUE; + } + } + return puGroup::checkHit(button, updown, x, y); +} + +void +puaList::init (int w, int h, short transparent) +{ + if ( transparent ) + _frame = NULL ; + else + _frame = new puFrame(0, 0, w, h); + + _list_box = new puListBox(0, 0, w-_sw, h); + _list_box->setStyle(-PUSTYLE_SMALL_SHADED); + _list_box->setUserData(this); + _list_box->setCallback(handle_list_entry); + _list_box->setValue(0); + + _slider = new puSlider(w-_sw, _sw, h-2*_sw, true, _sw); + _slider->setValue(1.0f); + _slider->setUserData(_list_box); + _slider->setCallback(handle_slider); + _slider->setCBMode(PUSLIDER_ALWAYS); + + _down_arrow = new puArrowButton(w-_sw, 0, w, _sw, PUARROW_DOWN) ; + _down_arrow->setUserData(_slider); + _down_arrow->setCallback(handle_arrow); + + _up_arrow = new puArrowButton(w-_sw, h-_sw, w, h, PUARROW_UP); + _up_arrow->setUserData(_slider); + _up_arrow->setCallback(handle_arrow); + + setSize(w, h); + close(); +} + +// end of puAuxList.cxx diff --git a/src/puAux/puAuxLocal.h b/src/puAux/puAuxLocal.h new file mode 100644 index 0000000..3d9526f --- /dev/null +++ b/src/puAux/puAuxLocal.h @@ -0,0 +1,4 @@ + +#define PU_USE_NONE 1 +#include "puAux.h" + diff --git a/src/puAux/puAuxScrollBar.cxx b/src/puAux/puAuxScrollBar.cxx new file mode 100644 index 0000000..309e9e9 --- /dev/null +++ b/src/puAux/puAuxScrollBar.cxx @@ -0,0 +1,278 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puAuxScrollBar.cxx 2161 2010-02-27 04:06:53Z fayjf $ +*/ + + +#include "puAuxLocal.h" + +UL_RTTI_DEF1(puaScrollBar,puSlider) + + +void puaScrollBar::draw ( int dx, int dy ) +{ + extern void puDrawArrowButtonTriangle ( int pos_x, int pos_y, int size_x, int size_y, + puColour colour, int arrow_type, int active ) ; + + if ( !visible || ( window != puGetWindow () ) ) return ; + + if ( r_cb ) + r_cb ( this, dx, dy, render_data ) ; + else + { + puBox box = abox ; + + int width = isVertical () ? abox.max[0] - abox.min[0] : abox.max[1] - abox.min[1] ; + + /* Draw the arrow buttons */ + + if ( arrow_count == 2 ) /* Double-arrow buttons */ + { + if ( isVertical () ) + { + box.min[1] = abox.max[1] - width ; + box.draw ( dx, dy, style, colour, FALSE, border_thickness ) ; + puDrawArrowButtonTriangle ( dx+box.min[0]+width/2, dy+box.min[1]+width/2, width, width, colour [ PUCOL_MISC ], + PUARROW_FASTUP, active_arrow & FASTUP ) ; + box.min[1] = abox.min[1] ; + box.max[1] = box.min[1] + width ; + box.draw ( dx, dy, style, colour, FALSE, border_thickness ) ; + puDrawArrowButtonTriangle ( dx+box.min[0]+width/2, dy+box.min[1]+width/2, width, width, colour [ PUCOL_MISC ], + PUARROW_FASTDOWN, active_arrow & FASTDOWN ) ; + } + else + { + box.min[0] = abox.max[0] - width ; + box.draw ( dx, dy, style, colour, FALSE, border_thickness ) ; + puDrawArrowButtonTriangle ( dx+box.min[0]+width/2, dy+box.min[1]+width/2, width, width, colour [ PUCOL_MISC ], + PUARROW_FASTRIGHT, active_arrow & FASTUP ) ; + box.min[0] = abox.min[0] ; + box.max[0] = box.min[0] + width ; + box.draw ( dx, dy, style, colour, FALSE, border_thickness ) ; + puDrawArrowButtonTriangle ( dx+box.min[0]+width/2, dy+box.min[1]+width/2, width, width, colour [ PUCOL_MISC ], + PUARROW_FASTLEFT, active_arrow & FASTDOWN ) ; + } + } + + if ( arrow_count > 0 ) /* Single-arrow buttons */ + { + if ( isVertical () ) + { + box.min[1] = abox.max[1] - arrow_count * width ; + box.max[1] = box.min[1] + width ; + box.draw ( dx, dy, style, colour, FALSE, border_thickness ) ; + puDrawArrowButtonTriangle ( dx+box.min[0]+width/2, dy+box.min[1]+width/2, width, width, colour [ PUCOL_MISC ], + PUARROW_UP, active_arrow & UP ) ; + box.max[1] = abox.min[1] + arrow_count * width ; + box.min[1] = box.max[1] - width ; + box.draw ( dx, dy, style, colour, FALSE, border_thickness ) ; + puDrawArrowButtonTriangle ( dx+box.min[0]+width/2, dy+box.min[1]+width/2, width, width, colour [ PUCOL_MISC ], + PUARROW_DOWN, active_arrow & DOWN ) ; + } + else + { + box.min[0] = abox.max[0] - arrow_count * width ; + box.max[0] = box.min[0] + width ; + box.draw ( dx, dy, style, colour, FALSE, border_thickness ) ; + puDrawArrowButtonTriangle ( dx+box.min[0]+width/2, dy+box.min[1]+width/2, width, width, colour [ PUCOL_MISC ], + PUARROW_RIGHT, active_arrow & UP ) ; + box.max[0] = abox.min[0] + arrow_count * width ; + box.min[0] = box.max[0] - width ; + box.draw ( dx, dy, style, colour, FALSE, border_thickness ) ; + puDrawArrowButtonTriangle ( dx+box.min[0]+width/2, dy+box.min[1]+width/2, width, width, colour [ PUCOL_MISC ], + PUARROW_LEFT, active_arrow & DOWN ) ; + } + } + + /* Draw the surrounding box */ + + box.min[0] = abox.min[0] + ( isVertical () ? 0 : arrow_count * width ) ; + box.max[0] = abox.max[0] - ( isVertical () ? 0 : arrow_count * width ) ; + box.min[1] = abox.min[1] + ( isVertical () ? arrow_count * width : 0 ) ; + box.max[1] = abox.max[1] - ( isVertical () ? arrow_count * width : 0 ) ; + + if ( ( style == PUSTYLE_BEVELLED ) || + ( style == PUSTYLE_SHADED ) ) + box.draw ( dx, dy, -PUSTYLE_BOXED, colour, FALSE, 2 ) ; + else + box.draw ( dx, dy, -style, colour, FALSE, border_thickness ) ; + + /* Draw the slider box */ + + float val = getFloatValue () ; + + draw_slider_box ( dx, dy, box, ( val - getMinValue () ) / ( getMaxValue () - getMinValue () ) ) ; + + draw_legend ( dx, dy ) ; + } + + draw_label ( dx, dy ) ; +} + +int puaScrollBar::checkHit ( int button, int updown, int x, int y ) +{ + if ( updown == PU_UP && ( button == PU_SCROLL_UP_BUTTON || button == PU_SCROLL_DOWN_BUTTON ) && isHit ( x, y ) ) + { + float last_value = clamp ( getFloatValue () ), next_value = last_value ; + float range = maximum_value - minimum_value ; + float line_step = line_step_size ; + if ( line_step <= 0.0f ) line_step = range / 10.0f ; + if ( button == PU_SCROLL_UP_BUTTON ) + next_value += line_step; + else + next_value -= line_step; + setValue ( checkStep ( clamp ( next_value ) ) ) ; + if ( next_value != last_value ) invokeCallback () ; + return TRUE; + } + return puSlider::checkHit ( button, updown, x, y ) ; +} + +void puaScrollBar::doHit ( int button, int updown, int x, int y ) +{ + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + if ( updown != PU_DRAG ) + puMoveToLast ( this ); + + if ( button != active_mouse_button ) + return; + + if ( updown == PU_UP ) + { + active_arrow = NONE ; + puDeactivateWidget () ; + return ; + } + + int sd = isVertical() ; + int coord = sd ? y : x ; + float range = maximum_value - minimum_value ; + float last_value = clamp ( getFloatValue () ), next_value = last_value ; + float norm_value = ( last_value - minimum_value ) / range ; + int width = abox.max[!sd] - abox.min[!sd] ; + int box_len = abox.max [sd] - abox.min [sd] - arrow_count * width * 2 ; + + if ( updown == PU_DOWN ) { + int lower = abox.min [sd] + int(float(box_len) * (1.0 - slider_fraction) * norm_value) + + arrow_count * width ; + int upper = lower + int(float(box_len) * slider_fraction) ; // upper/lower slider margin in pixels + + float line_step = line_step_size ; + float page_step = page_step_size ; + if ( line_step <= 0.0f ) line_step = range / 10.0f ; + if ( page_step <= 0.0f ) page_step = range ; + + start_offset = -1 ; + if ( arrow_count && coord < abox.min[sd] + width ) { // lowest button + if (arrow_count == 2) { + next_value -= page_step ; + active_arrow |= FASTDOWN ; + } else { + next_value -= line_step ; + active_arrow |= DOWN ; + } + + } else if ( arrow_count == 2 && coord < abox.min[sd] + 2 * width ) { // 2nd low button + next_value -= line_step ; + active_arrow |= DOWN ; + + } else if ( arrow_count && coord > abox.max[sd] - width ) { // highest button + if (arrow_count == 2) { + next_value += page_step ; + active_arrow |= FASTUP ; + } else { + next_value += line_step ; + active_arrow |= UP ; + } + + } else if ( arrow_count == 2 && coord > abox.max[sd] - 2 * width ) { // 2nd high button + next_value += line_step ; + active_arrow |= UP ; + + } else if ( page_step_size <= 0.0f ) { // old slider behavior (jumping) + start_offset = int(float(box_len) * slider_fraction * 0.5f) + 2 * arrow_count * width ; + updown = PU_DRAG ; + + } else if (coord < lower) { // lower background + next_value -= page_step ; + + } else if (coord > upper) { // upper background + next_value += page_step ; + + } else { // slider handle (new behavior) + start_offset = coord + arrow_count * width - abox.min [sd] + - int(float(box_len) * (1.0f - slider_fraction) * norm_value) ; + puSetActiveWidget ( this, x, y ) ; + return; + } + } + + if ( updown == PU_DRAG && start_offset >= 0 ) { + if ( box_len == 0 ) { + norm_value = 0.5f ; + } else if ( slider_fraction >= 1.0f ) { + norm_value = 0.0f ; + } else { + norm_value = ( coord + arrow_count * width - abox.min[sd] - start_offset ) + / ( box_len * (1.0f - slider_fraction) ) ; + } + next_value = norm_value * range + minimum_value ; + } + + setValue ( checkStep ( clamp ( next_value ) ) ) ; + + if ( next_value == last_value ) return ; + + switch ( cb_mode ) + { + case PUSLIDER_CLICK : + if ( updown == active_mouse_edge ) + { + last_cb_value = next_value ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + } + break ; + + case PUSLIDER_DELTA : /* Deprecated! */ + if ( fabs ( last_cb_value - next_value ) >= cb_delta ) + { + last_cb_value = next_value ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + } + break ; + + case PUSLIDER_ALWAYS : + default : + last_cb_value = next_value ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + break ; + } +} + + diff --git a/src/puAux/puAuxSelectBox.cxx b/src/puAux/puAuxSelectBox.cxx new file mode 100644 index 0000000..b1ac285 --- /dev/null +++ b/src/puAux/puAuxSelectBox.cxx @@ -0,0 +1,206 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puAuxSelectBox.cxx 2084 2006-05-02 16:28:07Z bram $ +*/ + + +#include "puAuxLocal.h" + +UL_RTTI_DEF1(puaSelectBox,puGroup) + + +void puaSelectBox::handle_arrow ( puObject *arrow ) +{ + puaSelectBox *selbox = (puaSelectBox *) arrow -> getUserData () ; + int arrow_type = ((puArrowButton*) arrow) -> getArrowType () ; + + if ( arrow_type == PUARROW_DOWN ) + selbox -> setCurrentItem ( selbox -> getCurrentItem () - 1 ) ; + else if ( arrow_type == PUARROW_UP ) + selbox -> setCurrentItem ( selbox -> getCurrentItem () + 1 ) ; +} + + +void puaSelectBox::update_widgets ( void ) +{ + if ( curr_item >= 0 ) + /* There are some items */ + { + setValue ( list[curr_item] ) ; + input->setValue( list[curr_item] ); + + if ( curr_item == 0 ) + /* Current item is first item, deactivate 'down' button */ + down_arrow -> greyOut () ; + else + down_arrow -> activate () ; + + if ( curr_item == (num_items - 1) ) + /* Current item is last item, deactivate 'up' button */ + up_arrow -> greyOut () ; + else + up_arrow -> activate () ; + } + else + /* There aren't any items */ + { + setValue ( "" ) ; + + down_arrow -> greyOut () ; + up_arrow -> greyOut () ; + } +} + + +void puaSelectBox::newList ( char ** _list ) +{ + list = _list ; + + if ( list == NULL ) + num_items = 0 ; + else + { + for ( num_items = 0 ; list[num_items] != NULL ; num_items++ ) + /* Count number of items */ ; + } + + curr_item = ( num_items > 0 ? 0 : - 1 ) ; + update_widgets () ; +} + + +void puaSelectBox::setSize ( int w, int h ) +{ + int arrow_size = h / 2 ; + + /* Resize the puInput widget */ + + input -> setSize ( w - arrow_size, h ) ; + + /* Resize and reposition the arrow buttons */ + + down_arrow -> setPosition ( w - arrow_size, 0 ) ; + down_arrow -> setSize ( arrow_size, arrow_size ) ; + + up_arrow -> setPosition ( w - arrow_size, arrow_size ) ; + up_arrow -> setSize ( arrow_size, arrow_size ) ; +} + +void puaSelectBox::draw ( int dx, int dy ) +{ + if ( !visible || ( window != puGetWindow () ) ) return ; + + draw_label ( dx, dy ) ; + + puGroup::draw ( dx, dy ) ; +} + +int puaSelectBox::checkKey ( int key, int updown ) +{ + if ( updown == PU_UP || ! input -> isAcceptingInput () || + ! isVisible () || ! isActive () || ( window != puGetWindow () ) ) + return FALSE ; + + switch ( key ) + { + case PU_KEY_HOME : + setCurrentItem ( 0 ) ; + break ; + + case PU_KEY_END : + setCurrentItem ( num_items - 1 ) ; + break ; + + case PU_KEY_UP : + case PU_KEY_PAGE_UP : + setCurrentItem ( curr_item + 1 ) ; + break ; + + case PU_KEY_DOWN : + case PU_KEY_PAGE_DOWN : + setCurrentItem ( curr_item - 1 ) ; + break ; + + default : + /* We might decide to make the input box editable on request + in future - and it does not hurt ... */ + return input -> checkKey ( key, updown ) ; + break ; + } + + return TRUE ; +} + +void puaSelectBox::setColourScheme ( float r, float g, float b, float a ) +{ + puObject::setColourScheme ( r, g, b, a ) ; + setChildColourScheme( PUCLASS_INPUT, + colour [ PUCOL_EDITFIELD ][0], + colour [ PUCOL_EDITFIELD ][1], + colour [ PUCOL_EDITFIELD ][2], + colour [ PUCOL_EDITFIELD ][3] ) ; +} + +void puaSelectBox::setColour ( int which, float r, float g, float b, float a ) +{ + if (which == PUCOL_EDITFIELD) + input->setColourScheme ( r, g, b, a ) ; + else + puObject::setColour ( which, r, g, b, a ) ; +} + + +puaSelectBox::puaSelectBox ( int minx, int miny, int maxx, int maxy, + char **entries ) : + puGroup( minx, miny ) +{ + type |= PUCLASS_SELECTBOX ; + + char *stringval ; + int arrow_size = (maxy - miny) / 2 ; + + input = new puInput ( 0, 0, maxx-minx - arrow_size, maxy-miny ) ; + input -> setStyle ( PUSTYLE_SMALL_SHADED ) ; + input -> disableInput () ; + + /* Share 'string' value with input box */ + input -> getValue ( &stringval ) ; + setValuator ( stringval ) ; + + down_arrow = new puArrowButton ( maxx-minx - arrow_size, 0, + maxx-minx, arrow_size, + PUARROW_DOWN ) ; + down_arrow -> setStyle ( PUSTYLE_SMALL_SHADED ) ; + down_arrow -> setUserData ( this ) ; + down_arrow -> setCallback ( handle_arrow ) ; + + up_arrow = new puArrowButton ( maxx-minx - arrow_size, arrow_size, + maxx-minx, maxy-miny, + PUARROW_UP ) ; + up_arrow -> setStyle ( PUSTYLE_SMALL_SHADED ) ; + up_arrow -> setUserData ( this ) ; + up_arrow -> setCallback ( handle_arrow ) ; + + newList ( entries ) ; + + close () ; +} + diff --git a/src/puAux/puAuxSliderWithInput.cxx b/src/puAux/puAuxSliderWithInput.cxx new file mode 100644 index 0000000..713109f --- /dev/null +++ b/src/puAux/puAuxSliderWithInput.cxx @@ -0,0 +1,89 @@ +/* + PUI Auxiliary Widget Library + Derived from PLIB, the Portable Game Library by Steve Baker. + Copyright (C) 1998,2002,2004 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puAuxSliderWithInput.cxx 1902 2004-03-21 19:03:23Z sjbaker $ +*/ + +#include "puAuxLocal.h" + +UL_RTTI_DEF1(puaSliderWithInput,puGroup) + +void puaSliderWithInput::handle_slider ( puObject *obj ) +{ + puaSliderWithInput *sl = (puaSliderWithInput *)obj->getUserData () ; + sl->setValue ( obj->getFloatValue () ) ; + sl->__setInputBox ( obj->getFloatValue () ) ; + + sl->invokeCallback () ; +} + +void puaSliderWithInput::handle_input ( puObject *obj ) +{ + puaSliderWithInput *sl = (puaSliderWithInput *)obj->getUserData () ; + sl->setValue ( obj->getFloatValue () ) ; + sl->invokeCallback () ; +} + +puaSliderWithInput::puaSliderWithInput ( int minx, int miny, int maxx, int maxy, int above ) : + puGroup ( minx, miny ) +{ + type |= PUCLASS_SLIDERWITHINPUT ; + slider = new puSlider ( (maxx - minx)/2-10, above ? 0 : 20, maxy-miny-20, TRUE ) ; + input_box = new puInput ( 0, above ? maxy - miny - 20 : 0, maxx-minx, above ? maxy - miny : 20 ) ; + input_box->setValue ( 0 ) ; + slider->setUserData ( this ) ; + slider->setCallback ( handle_slider ) ; + input_box->setUserData ( this ) ; + input_box->setCallback ( handle_input ) ; + close () ; + + input_position = above ; +} + + +void puaSliderWithInput::setSize ( int w, int h ) +{ + slider->setSize ( 20, h-40 ) ; + slider->setPosition ( w/2-10, input_position ? 0 : 20 ) ; + + input_box->setSize ( w, 20 ) ; + input_box->setPosition ( 0, input_position ? h-20 : 0 ) ; +} + + +void puaSliderWithInput::draw ( int dx, int dy ) +{ + if ( !visible || ( window != puGetWindow () ) ) return ; + + draw_label ( dx, dy ) ; + + puGroup::draw ( dx, dy ) ; +} + + +int puaSliderWithInput::checkKey ( int key, int updown ) +{ + if ( ! isVisible () || ! isActive () || ( window != puGetWindow () ) ) + return FALSE ; + + return ( input_box->checkKey ( key, updown ) ) ; +} + diff --git a/src/puAux/puAuxSpinBox.cxx b/src/puAux/puAuxSpinBox.cxx new file mode 100644 index 0000000..8bfacbf --- /dev/null +++ b/src/puAux/puAuxSpinBox.cxx @@ -0,0 +1,97 @@ +/* + PUI Auxiliary Widget Library + Derived from PLIB, the Portable Game Library by Steve Baker. + Copyright (C) 1998,2002,2004 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puAuxSpinBox.cxx 1902 2004-03-21 19:03:23Z sjbaker $ +*/ + + +#include "puAuxLocal.h" + +UL_RTTI_DEF2(puaSpinBox,puRange,puGroup) + + +puaSpinBox::puaSpinBox ( int minx, int miny, int maxx, int maxy, int arrow_pos ) : + puRange ( 1.0f, 10.0f, 1.0f ), puGroup ( minx, miny ) +{ + extern void puaSpinBox_handle_input ( puObject* ob ) ; + extern void puaSpinBox_handle_input_active ( puObject* ob ) ; + extern void puaSpinBox_handle_arrow ( puObject* ob ) ; + type |= PUCLASS_SPINBOX ; + arrow_position = arrow_pos ; + int arrow_size = ( maxy - miny ) / 2 ; + if ( arrow_pos == 1 ) + input_box = new puInput ( 0, 0, maxx - minx - arrow_size, maxy - miny ) ; + else + input_box = new puInput ( arrow_size, 0, maxx - minx, maxy - miny ) ; + + input_box->setCallback ( puaSpinBox_handle_input ) ; + input_box->setActiveCallback ( puaSpinBox_handle_input_active ) ; + input_box->setDownCallback ( puaSpinBox_handle_input ) ; + input_box->setUserData ( this ) ; + + up_arrow = new puArrowButton ( arrow_position?maxx-minx-arrow_size:0, arrow_size, + arrow_position?maxx-minx:arrow_size, maxy-miny, PUARROW_UP ) ; + up_arrow->setCallback ( puaSpinBox_handle_arrow ) ; + up_arrow->setUserData ( this ) ; + + down_arrow = new puArrowButton ( arrow_position?maxx-minx-arrow_size:0, 0, + arrow_position?maxx-minx:arrow_size, arrow_size, PUARROW_DOWN ) ; + down_arrow->setCallback ( puaSpinBox_handle_arrow ) ; + down_arrow->setUserData ( this ) ; + + close () ; +} + +void puaSpinBox_handle_arrow ( puObject *ob ) +{ + puaSpinBox *master = (puaSpinBox *)(ob->getUserData ()) ; + float val = master->getFloatValue () ; + if ( ((puArrowButton *)ob)->getArrowType () == PUARROW_UP ) + val += master->getStepSize () ; + else + val -= master->getStepSize () ; + + if ( val > master->getMaxValue () ) val = master->getMaxValue () ; + if ( val < master->getMinValue () ) val = master->getMinValue () ; + master->setValue ( val ) ; + master->invokeCallback () ; +} + +void puaSpinBox_handle_input ( puObject *ob ) +{ + puaSpinBox *master = (puaSpinBox *)(ob->getUserData ()) ; + float val = ob->getFloatValue () ; + if ( val > master->getMaxValue () ) val = master->getMaxValue () ; + if ( val < master->getMinValue () ) val = master->getMinValue () ; + master->setValue ( val ) ; + master->invokeCallback () ; +} + +void puaSpinBox_handle_input_active ( puObject *ob ) +{ + puaSpinBox *master = (puaSpinBox *)(ob->getUserData ()) ; + float val = ob->getFloatValue () ; + if ( val > master->getMaxValue () ) val = master->getMaxValue () ; + if ( val < master->getMinValue () ) val = master->getMinValue () ; + master->setValue ( val ) ; + master->invokeActiveCallback () ; +} + diff --git a/src/puAux/puAuxTriSlider.cxx b/src/puAux/puAuxTriSlider.cxx new file mode 100644 index 0000000..51539a6 --- /dev/null +++ b/src/puAux/puAuxTriSlider.cxx @@ -0,0 +1,211 @@ +/* + PUI Auxiliary Widget Library + Derived from PLIB, the Portable Game Library by Steve Baker. + Copyright (C) 1998,2002,2004 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puAuxTriSlider.cxx 2022 2005-05-06 18:39:18Z fayjf $ +*/ + + +#include "puAuxLocal.h" + +UL_RTTI_DEF1(puaTriSlider,puaBiSlider) + + +void puaTriSlider::draw ( int dx, int dy ) +{ + if ( !visible || ( window != puGetWindow () ) ) return ; + + // Draw the slider box itself + + if ( ( style == PUSTYLE_BEVELLED ) || + ( style == PUSTYLE_SHADED ) ) + abox.draw ( dx, dy, -PUSTYLE_BOXED, colour, FALSE, 2 ) ; + else + abox.draw ( dx, dy, -style, colour, FALSE, border_thickness ) ; + + if ( r_cb ) + r_cb ( this, dx, dy, render_data ) ; + else + { + // Draw the central slider and label it + + float val; + if ( getMaxValue() > getMinValue() ) + val = (float)(getFloatValue () - getMinValue()) / (float)(getMaxValue() - getMinValue()) ; + else + val = 0.5f ; + + char str_value[10] ; + sprintf (str_value, "%g", getFloatValue () ) ; + + draw_slider_box ( dx, dy, abox, val, str_value ) ; + + if ( val < 0.0f ) val = 0.0f ; + if ( val > 1.0f ) val = 1.0f ; + + // Draw the current_max slider and label it + + if ( getMaxValue() > getMinValue() ) + val = (float)(getCurrentMax() - getMinValue()) / (float)(getMaxValue() - getMinValue()) ; + else + val = 1.0f ; + + sprintf (str_value, "%g", getCurrentMax() ) ; + + draw_slider_box ( dx, dy, abox, val, str_value ) ; + + // Draw the current_min slider and label it + + if ( getMaxValue() > getMinValue() ) + val = (float)(getCurrentMin() - getMinValue()) / (float)(getMaxValue() - getMinValue()) ; + else + val = 0.0f ; + + sprintf (str_value, "%g", getCurrentMin() ) ; + + draw_slider_box ( dx, dy, abox, val, str_value ) ; + + draw_legend ( dx, dy ) ; + } + + draw_label ( dx, dy ) ; +} + + +void puaTriSlider::doHit ( int button, int updown, int x, int y ) +{ + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + if ( updown != PU_DRAG ) + { + puMoveToLast ( this ); + /* Bug Fixed: If you moved a slider while dragging the mouse (click and drag), then move */ + /* the cursor outside of the widget and released the mouse button, the active_button would */ + /* be locked to the last slider you moved, and unable to release. - JCJ 11 June 2002 */ + setActiveButton ( 0 ) ; + } + + if ( ( button == active_mouse_button ) && ( updown == PU_UP ) ) + { + setActiveButton ( 0 ) ; + puDeactivateWidget () ; + return ; + } + + if ( button == active_mouse_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 ; + + float new_value = getMinValue() + next_value * ( getMaxValue() - getMinValue() ) ; + + if ( getFreezeEnds() ) // Cannot move end sliders, must move middle one + { + setActiveButton ( 2 ) ; + setValue ( checkStep(new_value) ) ; /* Ensure that the middle slider can't move beyond the barriers - JCJ 10 Jun 2002 */ + if ( new_value < getCurrentMin() ) setValue ( getCurrentMin() ) ; + if ( new_value > getCurrentMax() ) setValue ( getCurrentMax() ) ; + } + else + { + if ( getActiveButton() == 0 ) // No currently-active slider, set whichever is closest + { + if ( (new_value-getCurrentMin()) < (getFloatValue()-new_value) ) // Closest to current_min + { + setCurrentMin ( checkStep(new_value) ) ; + setActiveButton ( 1 ) ; + } + else if ( (new_value-getFloatValue()) > (getCurrentMax()-new_value) ) // Closest to current_max + { + setCurrentMax ( checkStep(new_value) ) ; + setActiveButton ( 3 ) ; + } + else // closest to the center slider -- ties go to the center slider + { + setValue ( checkStep(new_value) ) ; + setActiveButton ( 2 ) ; + } + } + else if ( getActiveButton() == 1 ) // Currently moving current_min + { + setCurrentMin ( checkStep(new_value) ) ; + if ( getFloatValue() < getCurrentMin() ) setValue ( getCurrentMin() ) ; + if ( getCurrentMax() < getCurrentMin() ) setCurrentMax ( getCurrentMin() ) ; + } + else if ( getActiveButton() == 2 ) // Currently moving central value + { + setValue ( checkStep(new_value) ) ; + if ( getCurrentMin() > new_value ) setCurrentMin ( new_value ) ; + if ( getCurrentMax() < new_value ) setCurrentMax ( new_value ) ; + } + else if ( getActiveButton() == 3 ) // Currently moving current_max + { + setCurrentMax ( checkStep(new_value) ) ; + if ( getFloatValue() > getCurrentMax() ) setValue ( getCurrentMax() ) ; + if ( getCurrentMax() < getCurrentMin() ) setCurrentMin ( getCurrentMax() ) ; + } + } + + switch ( cb_mode ) + { + case PUSLIDER_CLICK : + if ( updown == active_mouse_edge ) + { + last_cb_value = next_value ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + } + break ; + + case PUSLIDER_DELTA :/* Deprecated! */ + if ( fabs ( last_cb_value - next_value ) >= cb_delta ) + { + last_cb_value = next_value ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + } + break ; + + case PUSLIDER_ALWAYS : + default : + last_cb_value = next_value ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + break ; + } + } +} diff --git a/src/puAux/puAuxVerticalMenu.cxx b/src/puAux/puAuxVerticalMenu.cxx new file mode 100644 index 0000000..e18dda5 --- /dev/null +++ b/src/puAux/puAuxVerticalMenu.cxx @@ -0,0 +1,174 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puAuxVerticalMenu.cxx 2022 2005-05-06 18:39:18Z fayjf $ +*/ + + +#include "puAuxLocal.h" + +UL_RTTI_DEF1(puaVerticalMenu,puGroup) + + +extern void puMenuBar_drop_down_the_menu ( puObject *b ); + +/* If there is only one entry in a vmenu, just act as if clicking the menu clicks the oneshot underneath it. */ +void puaVerticalMenu::add_submenu ( const char *str, char *items[], + puCallback _cb[], void *_user_data[] ) +{ + int w, h ; + getSize ( &w, &h ) ; + + if (items[1] != NULL) + { + + // More than one entry in the submenu, set the callback to drop down the menu + // and make the mouse activation edge up or down. Create the popup menu + // and load the items into it. + + 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 ( puMenuBar_drop_down_the_menu ) ; + b -> setActiveDirn ( PU_UP_AND_DOWN ) ; + + puPopupMenu *p = new puPopupMenu ( w+10, 0 ) ; + p->setActiveButton ( active_mouse_button ) ; + + b -> setUserData ( p ) ; + + if ( _user_data != NULL ) + for ( int i = 0 ; items[i] != NULL ; i++ ) + p -> add_item ( items[i], _cb[i], _user_data[i] ) ; + else + for ( int i = 0 ; items[i] != NULL ; i++ ) + p -> add_item ( items[i], _cb[i] ) ; + + p->close () ; + } + else + { + // Only one entry in the submenu, set the callback to the entry's callback + // and make the mouse activation edge up only. Set the user data to null. + + 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 ( _cb[0] ); + b -> setActiveDirn ( PU_UP ) ; + + b -> setUserData ( NULL ) ; + } + + recalc_bbox () ; +} + +void puaVerticalMenu::close (void) +{ + puGroup::close () ; + + if ( dlist == NULL ) + return ; + + int height = 0 ; + int fullheight; + puObject *ob ; + + // Use alternate objects - which gets the puOneShot/puPopupMenu pairs + // If the "puOneShot" has a user data of null, it is a single entry and its + // puPopup item is missing. + + for ( ob = dlist ; ob != NULL ; ob = ob -> getNextObject() ) + { + int w, h ; + + // Reposition the button so it looks nice + + ob -> getSize ( &w, &h ) ; + ob -> setPosition ( 0, height ) ; + + if (ob -> getUserData () ) + { + + ob = ob -> getNextObject() ; + + // Reposition the submenu so it sits under the button + + int w2, h2 ; + ob -> getSize ( &w2, &h2 ) ; + ob -> setPosition ( 0, height-h2 ) ; + } + + // Next please! + fullheight = height; + height -= h ; + } + + // Now step through the list again, adding the final value of "height" to + // all the vertical positions so that the (0,0) point will be the lower left- + // hand corner. + + for ( ob = dlist ; ob != NULL ; ob = ob -> getNextObject() ) + { + int x, y ; + + // Reposition the button so it looks nice + + ob -> getPosition ( &x, &y ) ; + ob -> setPosition ( x, y-fullheight ) ; + + if (ob -> getUserData () ) + { + + ob = ob -> getNextObject() ; + + // Reposition the submenu so it sits under the button + + ob -> getPosition ( &x, &y ) ; + ob -> setPosition ( x, y-fullheight ) ; + } + } + + recalc_bbox () ; + + // If in its own window (its window number is not the same as its parent's + // window number), then resize the window + + if (window != parent -> getWindow () ) + { + int temp_window = puGetWindow () ; + puSetWindow ( window ) ; + puSetWindowSize ( bbox.max[0] - bbox.min[0], bbox.max[1] - bbox.min[1] ) ; + setPosition ( 0, 0 ) ; + + puSetWindow ( temp_window ) ; + } + +} + + diff --git a/src/pui/Makefile.am b/src/pui/Makefile.am new file mode 100644 index 0000000..d695d81 --- /dev/null +++ b/src/pui/Makefile.am @@ -0,0 +1,23 @@ +if BUILD_PUI + +lib_LIBRARIES = libplibpu.a + +include_HEADERS = pu.h puGLUT.h puFLTK.h puSDL.h puNative.h puPW.h + +libplibpu_a_SOURCES = \ + pu.cxx puBox.cxx puButton.cxx puButtonBox.cxx \ + puArrowButton.cxx puDialogBox.cxx puFrame.cxx puGroup.cxx \ + puInput.cxx puInterface.cxx puLocal.h puMenuBar.cxx \ + puObject.cxx puOneShot.cxx puPopup.cxx puPopupMenu.cxx \ + puListBox.cxx puSlider.cxx puText.cxx \ + puValue.cxx puFont.cxx \ + puDial.cxx \ + puRange.cxx \ + puInputBase.cxx + +AM_CPPFLAGS = -I$(top_srcdir)/src/sg -I$(top_srcdir)/src/fnt +AM_CPPFLAGS += -I$(top_srcdir)/src/util + +endif + +EXTRA_DIST = pui.dsp diff --git a/src/pui/pu.cxx b/src/pui/pu.cxx new file mode 100644 index 0000000..2e3728f --- /dev/null +++ b/src/pui/pu.cxx @@ -0,0 +1,482 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pu.cxx 2030 2005-05-23 21:24:26Z fayjf $ +*/ + +#include "puLocal.h" + +#if defined(UL_AGL) +# include +#elif defined(UL_CGL) +# include +#elif defined(UL_GLX) +# include +#endif + + +int puRefresh = TRUE ; + + +static puGetWindowCallback cbGetWindow; +static puSetWindowCallback cbSetWindow; +static puGetWindowSizeCallback cbGetWindowSize; +static puSetWindowSizeCallback cbSetWindowSize; + + +void puSetWindowFuncs ( puGetWindowCallback getWindow, + puSetWindowCallback setWindow, + puGetWindowSizeCallback getWindowSize, + puSetWindowSizeCallback setWindowSize ) +{ + cbGetWindow = getWindow; + cbSetWindow = setWindow; + cbGetWindowSize = getWindowSize; + cbSetWindowSize = setWindowSize; +} + + +int puGetWindow () +{ + if ( !cbGetWindow ) + ulSetError ( UL_FATAL, "puGetWindow: Callbacks not initialized." ) ; + return ( *cbGetWindow ) () ; +} + +void puSetWindow ( int window ) +{ + if ( !cbSetWindow ) + ulSetError ( UL_WARNING, "puSetWindow: Cannot set window (null callback)." ) ; + else + ( *cbSetWindow ) ( window ) ; +} + +void puGetWindowSize ( int *width, int *height ) +{ + if ( !cbGetWindowSize ) + ulSetError ( UL_FATAL, "puGetWindowSize: Callbacks not initialized." ) ; + ( *cbGetWindowSize ) ( width, height ) ; +} + +void puSetWindowSize ( int width, int height ) +{ + if ( !cbSetWindowSize ) + ulSetError ( UL_WARNING, "puSetWindowSize: Cannot change size (null callback)." ) ; + else + ( *cbSetWindowSize ) ( width, height ) ; +} + +int puGetWindowWidth () +{ + int w, h ; + puGetWindowSize ( &w, &h ) ; + return w ; +} + +int puGetWindowHeight () +{ + int w, h ; + puGetWindowSize ( &w, &h ) ; + return h ; +} + + + +static bool glIsValidContext ( void ) +{ +#if defined(UL_WGL) + return ( wglGetCurrentContext () != NULL ) ; +#elif defined(UL_AGL) + return ( aglGetCurrentContext () != NULL ) ; +#elif defined(UL_CGL) + return ( CGLGetCurrentContext () != NULL ) ; +#elif defined(UL_GLX) + return ( glXGetCurrentContext () != NULL ) ; +#else + return true ; +#endif +} + + +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 ; +} + + +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 () ; +} + + +// Pointer to linked list of objects to delete +// as a result of keyboarding or mouse clicking + +static puObject *objects_to_delete = NULL; + + +void puDeleteObject ( puObject *ob ) +{ + if ( ob == NULL ) + return ; + + puGroup *parent = ob->getParent () ; + + /* Add object to linked list to be deleted */ + if ( objects_to_delete == NULL ) + objects_to_delete = ob ; + else + { + /* Ensure that objects are deleted in the order of puDeleteObject calls */ + + puObject *last ; + + for ( last = objects_to_delete ; + last -> getNextObject() != NULL ; + last = last -> getNextObject() ) + /* Find last object. */ ; + + last -> setNextObject ( ob ) ; + } + + /* Remove from parent interface */ + + if ( parent != ob && parent != NULL ) + parent -> remove ( ob ) ; /* Sets object's next and previous pointers to null as well */ +} + + +void puCleanUpJunk ( void ) +{ + puObject * local_objects_to_delete = objects_to_delete ; + objects_to_delete = NULL ; + /* Step through the linked list of objects to delete, removing them. */ + while ( local_objects_to_delete != NULL ) + { + puObject *next_ob = local_objects_to_delete -> getNextObject() ; + delete local_objects_to_delete ; + local_objects_to_delete = next_ob ; + + /* If we've reached the end of the list, start over (in case we've deleted a group and + * it has put new widgets on the delete list) + */ + if ( local_objects_to_delete == NULL ) + { + local_objects_to_delete = objects_to_delete ; + objects_to_delete = NULL ; + } + } +} + + +static puObject *active_widget ; /* Widget which is currently receiving user input */ +static char *input_paste_buffer ; /* Cut/Copy/Paste buffer for input widgets */ + +static int firsttime = TRUE ; + +void puRealInit ( void ) +{ + if ( firsttime ) + { + if ( ! glIsValidContext () ) + { + ulSetError ( UL_FATAL, + "puInit called without a valid OpenGL context."); + } + + new puInterface ( 0, 0 ) ; + + active_widget = NULL ; + input_paste_buffer = NULL ; + + firsttime = FALSE ; + } +} + +void puExit ( void ) +{ + if ( firsttime ) + ulSetError ( UL_FATAL, "puExit called without a previous call to puInit." ) ; + + delete puGetBaseLiveInterface () ; + firsttime = TRUE ; +} + +static void puSetOpenGLState ( void ) +{ + int w, h ; + + puGetWindowSize ( &w, &h ) ; + + glPushAttrib ( GL_ENABLE_BIT | GL_VIEWPORT_BIT | GL_TRANSFORM_BIT | GL_LIGHTING_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 () ; + glOrtho ( 0, w, 0, h, -1, 1 ) ; + glMatrixMode ( GL_MODELVIEW ) ; + glPushMatrix () ; + glLoadIdentity () ; +} + +static void puRestoreOpenGLState ( void ) +{ + glMatrixMode ( GL_PROJECTION ) ; + glPopMatrix () ; + glMatrixMode ( GL_MODELVIEW ) ; + glPopMatrix () ; + glPopAttrib () ; +} + + +void puDisplay ( void ) +{ + puCleanUpJunk () ; + + puSetOpenGLState () ; + puGetUltimateLiveInterface () -> draw ( 0, 0 ) ; + + int h = puGetWindowHeight () ; + + if ( _puCursor_enable ) + puDrawCursor ( _puCursor_x, + h - _puCursor_y ) ; + + puRestoreOpenGLState () ; + + puRefresh = FALSE ; +} + + +void puDisplay ( int window_number ) /* Deprecated */ +{ + if ( window_number == puGetWindow () ) + puDisplay () ; +} + + +int puKeyboard ( int key, int updown, int, int ) +{ + return puKeyboard ( key, updown ) ; +} + + +int puKeyboard ( int key, int updown ) +{ + int return_value = puGetBaseLiveInterface () -> checkKey ( key, updown ) ; + + puCleanUpJunk () ; + + return return_value ; +} + + +static int last_buttons = 0 ; +static int pu_mouse_x = 0 ; +static int pu_mouse_y = 0 ; +static int pu_mouse_offset_x = 0 ; +static int pu_mouse_offset_y = 0 ; + +int puGetPressedButton () +{ + return last_buttons ; +} + +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 ) ; + + pu_mouse_x = x ; + pu_mouse_y = h - y ; + + puObject *active = puActiveWidget () ; + + if ( ( last_buttons != 0 ) && ( active != NULL ) ) + { + int x_offset, y_offset ; + active -> getAbsolutePosition ( &x_offset, &y_offset ) ; + + x_offset -= active -> getABox () -> min [0] ; + y_offset -= active -> getABox () -> min [1] ; + + if ( ( ! active -> isHit ( pu_mouse_x - x_offset, pu_mouse_y - y_offset ) ) && + ( active -> getWhenToDeactivate () == PUDEACTIVATE_ON_MOUSE_CLICK ) ) + { + active -> invokeDownCallback () ; + puDeactivateWidget () ; + } + } + + int return_value = puGetBaseLiveInterface () -> checkHit ( button, + updown, pu_mouse_x, pu_mouse_y ) ; + + puCleanUpJunk () ; + + return return_value ; +} + + +int puMouse ( int x, int y ) +{ + puCursor ( x, y ) ; + + // Pick buttons in order of descending priority: Left, Right, Middle + int button = + (last_buttons & (1<checkHit(button, PU_DRAG, pu_mouse_x - pu_mouse_offset_x, + pu_mouse_y - pu_mouse_offset_y) ) + return TRUE ; + else + return FALSE ; + } + + int return_value = puGetBaseLiveInterface () -> checkHit ( button, + PU_DRAG, pu_mouse_x, pu_mouse_y ) ; + + puCleanUpJunk () ; + + return return_value ; +} + +void puMoveToLast (puObject *ob) +{ + puGroup *parent = ob -> getParent () ; + + /* If no parent interface, return. */ + + if ( ! parent ) return; + + /* Remove "ob" from present place in the "dlist" list */ + + parent -> remove (ob) ; + + /* Place at the end of the list */ + + parent -> add (ob) ; + + /* + Now repeat the process for the parent interface so that the interface will + be drawn last of all interfaces. + */ + + puMoveToLast ( parent ); +} + +void puDeactivateWidget ( void ) { active_widget = NULL ; } +void puSetActiveWidget ( puObject *w, int x, int y ) +{ + active_widget = w ; + pu_mouse_offset_x = pu_mouse_x - x ; + pu_mouse_offset_y = pu_mouse_y - y ; +} + +puObject *puActiveWidget ( void ) { return active_widget ; } + +void puSetPasteBuffer ( const char *ch ) +{ + delete [] input_paste_buffer ; + input_paste_buffer = ulStrDup ( ch ) ; +} + +char *puGetPasteBuffer ( void ) { return input_paste_buffer ; } + +int puNeedRefresh ( void ) { return puRefresh ; } +void puPostRefresh ( void ) { puRefresh = TRUE ; } + + +void puSetResizeMode ( int mode ) +{ + static int last = 0; + if ( last == 0 && mode != 0 ) + ulSetError ( UL_WARNING, "puSetResizeMode is deprecated!" ) ; + last = mode ; +} diff --git a/src/pui/pu.h b/src/pui/pu.h new file mode 100644 index 0000000..ba81a9e --- /dev/null +++ b/src/pui/pu.h @@ -0,0 +1,1615 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pu.h 2160 2010-02-27 03:48:23Z fayjf $ +*/ + +#ifndef _PU_H_ +#define _PU_H_ 1 + +#include +#include "fnt.h" +#include "ulRTTI.h" + +/* + Configuration +*/ + +#define PU_NOBUTTON -1 +#define PU_LEFT_BUTTON 0 +#define PU_MIDDLE_BUTTON 1 +#define PU_RIGHT_BUTTON 2 +#define PU_SCROLL_UP_BUTTON 3 +#define PU_SCROLL_DOWN_BUTTON 4 +#define PU_DOWN 0 +#define PU_UP 1 + +class puFont +{ +protected: + fntFont * fnt_font_handle ; + float pointsize ; + float slant ; + +public: + + puFont () ; + + puFont ( fntFont *tfh, float ps = 13, float sl = 0 ) + { + initialize ( tfh, ps, sl ) ; + } + + void initialize ( fntFont *tfh, float ps, float sl = 0 ) + { + fnt_font_handle = tfh ; + pointsize = ps ; + slant = sl ; + } + + float getPointSize ( ) const { return pointsize; } + + int getStringDescender ( void ) const ; + int getStringHeight ( const char *str ) const ; + int getStringHeight ( void ) const { return getStringHeight ( "" ) ; } + + float getFloatStringWidth ( const char *str ) const ; + int getStringWidth ( const char *str ) const /* Deprecated ? */ + { + return (int) getFloatStringWidth ( str ) ; + } + + void drawString ( const char *str, int x, int y ) ; +} ; + + +extern puFont PUFONT_8_BY_13 ; +extern puFont PUFONT_9_BY_15 ; +extern puFont PUFONT_TIMES_ROMAN_10 ; +extern puFont PUFONT_TIMES_ROMAN_24 ; +extern puFont PUFONT_HELVETICA_10 ; +extern puFont PUFONT_HELVETICA_12 ; +extern puFont PUFONT_HELVETICA_18 ; + +#define PU_UP_AND_DOWN 254 +#define PU_DRAG 255 +#define PU_CONTINUAL PU_DRAG + +/* + WARNING: These have to be the same as PW_KEY_whatever and also + the same as (GLUT_KEY_whatever+256) +*/ + +#define PU_KEY_GLUT_SPECIAL_OFFSET 256 + +#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) + +#define PUARROW_UP 0 +#define PUARROW_DOWN 1 +#define PUARROW_FASTUP 2 +#define PUARROW_FASTDOWN 3 +#define PUARROW_LEFT 4 +#define PUARROW_RIGHT 5 +#define PUARROW_FASTLEFT 6 +#define PUARROW_FASTRIGHT 7 + +#define PUBUTTON_NORMAL 0 +#define PUBUTTON_RADIO 1 +#define PUBUTTON_CIRCLE 2 +#define PUBUTTON_VCHECK 3 /* v-shaped checkmark */ +#define PUBUTTON_XCHECK 4 /* X checkmark */ + +/* Rational Definitions of PUI Legend and Label Places */ +#define PUPLACE_TOP_LEFT 0 +#define PUPLACE_TOP_CENTERED 1 +#define PUPLACE_TOP_RIGHT 2 + +#define PUPLACE_CENTERED_LEFT 3 +#define PUPLACE_CENTERED_RIGHT 4 + +#define PUPLACE_BOTTOM_LEFT 5 +#define PUPLACE_BOTTOM_CENTERED 6 +#define PUPLACE_BOTTOM_RIGHT 7 + +/* Additional definitions for PUI Legend places */ +#define PUPLACE_CENTERED_CENTERED 8 + +/* Additional definitions for PUI Label places */ +#define PUPLACE_ABOVE_LEFT 9 +#define PUPLACE_ABOVE_RIGHT 10 + +#define PUPLACE_BELOW_LEFT 11 +#define PUPLACE_BELOW_RIGHT 12 + +#define PUPLACE_UPPER_LEFT 13 +#define PUPLACE_UPPER_RIGHT 14 + +#define PUPLACE_LOWER_LEFT 15 +#define PUPLACE_LOWER_RIGHT 16 + +/* Default places */ +#define PUPLACE_LABEL_DEFAULT PUPLACE_LOWER_RIGHT +#define PUPLACE_LEGEND_DEFAULT PUPLACE_CENTERED_CENTERED + +/* Keep these for backwards compatibility but deprecate them */ +#define PUPLACE_ABOVE PUPLACE_TOP_LEFT +#define PUPLACE_BELOW PUPLACE_BOTTOM_LEFT +#define PUPLACE_LEFT PUPLACE_LOWER_LEFT +#define PUPLACE_RIGHT PUPLACE_LOWER_RIGHT +#define PUPLACE_CENTERED PUPLACE_CENTERED_CENTERED +#define PUPLACE_TOP_CENTER PUPLACE_TOP_CENTERED +#define PUPLACE_BOTTOM_CENTER PUPLACE_BOTTOM_CENTERED +#define PUPLACE_LEFT_CENTER PUPLACE_CENTERED_LEFT +#define PUPLACE_RIGHT_CENTER PUPLACE_CENTERED_RIGHT + +#define PUPLACE_DEFAULT PUPLACE_LABEL_DEFAULT + +#define PUCOL_FOREGROUND 0 +#define PUCOL_BACKGROUND 1 +#define PUCOL_HIGHLIGHT 2 +#define PUCOL_LABEL 3 +#define PUCOL_LEGEND 4 +#define PUCOL_MISC 5 +#define PUCOL_EDITFIELD 6 +#define PUCOL_MAX 7 + +#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 /* deprecated ! */ +#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 PU_RADIO_BUTTON_SIZE 16 + +/* When to deactivate a widget and call its down callback */ +#define PUDEACTIVATE_ON_MOUSE_CLICK 0 +#define PUDEACTIVATE_ON_NEXT_WIDGET_ACTIVATION 1 + +extern int puRefresh ; /* Should not be used directly by applications any + longer. Instead, use puPostRefresh () and + puNeedRefresh (). */ + +#define PUCLASS_VALUE 0x00000001 +#define PUCLASS_OBJECT 0x00000002 +#define PUCLASS_GROUP 0x00000004 +#define PUCLASS_INTERFACE 0x00000008 +#define PUCLASS_FRAME 0x00000010 +#define PUCLASS_TEXT 0x00000020 +#define PUCLASS_BUTTON 0x00000040 +#define PUCLASS_ONESHOT 0x00000080 +#define PUCLASS_POPUP 0x00000100 +#define PUCLASS_POPUPMENU 0x00000200 +#define PUCLASS_MENUBAR 0x00000400 +#define PUCLASS_INPUT 0x00000800 +#define PUCLASS_BUTTONBOX 0x00001000 +#define PUCLASS_SLIDER 0x00002000 +#define PUCLASS_DIALOGBOX 0x00004000 +#define PUCLASS_ARROW 0x00008000 +#define PUCLASS_LISTBOX 0x00010000 +#define PUCLASS_DIAL 0x00020000 + +class puValue ; +class puObject ; +class puGroup ; +class puInterface ; +class puButtonBox ; +class puFrame ; +class puText ; +class puButton ; +class puOneShot ; +class puPopup ; +class puPopupMenu ; +class puMenuBar ; +class puInput ; +class puSlider ; +class puListBox ; +class puArrowButton ; +class puDial ; + +// Global function to move active object to the end of the "dlist" +// so it is displayed in front of everything else + +void puMoveToLast ( puObject *ob ) ; + +typedef float puColour [ 4 ] ; /* RGBA */ +typedef puColour puColor ; + +struct puBox +{ + int min [ 2 ] ; + int max [ 2 ] ; + + void draw ( int dx, int dy, int style, puColour colour[], int am_default, int border ) ; + void extend ( puBox *bx ) ; + + void empty ( void ) { min[0]=min[1]=1000000 ; max[0]=max[1]=-1000000 ; } + int isEmpty ( void ) const { return min[0]>max[0] || min[1]>max[1] ; } +} ; + +#define PUSTRING_MAX 256 + +/* With many memory managers, allocating powers of two is more efficient */ +#define PUSTRING_INITIAL 64 + + +inline void puSetColour ( puColour dst, const puColour src ) +{ + dst[0] = src[0] ; dst[1] = src[1] ; dst[2] = src[2] ; dst[3] = src[3] ; +} +inline void puSetColor ( puColour dst, const 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 ; +} +inline void puSetColor ( puColour c, float r, float g, float b, float a = 1.0f ) +{ + c [ 0 ] = r ; c [ 1 ] = g ; c [ 2 ] = b ; c [ 3 ] = a ; +} + + +// puInit () -- is a macro, see below +void puRealInit ( void ) ; +void puExit ( void ) ; +void puDisplay ( void ) ; +void puDisplay ( int window_number ) ; /* Deprecated */ +int puMouse ( int button, int updown, int x, int y ) ; +int puMouse ( int x, int y ) ; +int puKeyboard ( int key, int updown, int x, int y ) ; /* For PW */ +int puKeyboard ( int key, int updown ) ; +void puHideCursor ( void ) ; +void puShowCursor ( void ) ; +int puCursorIsHidden ( void ) ; +void puDeleteObject ( puObject *ob ) ; + +int puNeedRefresh ( void ) ; +void puPostRefresh ( void ) ; + +int puGetWindow ( void ) ; +void puGetWindowSize ( int *width, int *height ) ; +int puGetWindowWidth ( void ) ; +int puGetWindowHeight ( void ) ; + +void puSetWindow ( int w ) ; // don't use it! +void puSetWindowSize ( int width, int height ) ; // don't use it! + +void puSetResizeMode ( int mode ) ; // DEPRECATED + + +// Active widget functions + +void puDeactivateWidget ( void ) ; +void puSetActiveWidget ( puObject *w, int x, int y ) ; +puObject *puActiveWidget ( void ) ; + +// Return the currently active mouse button +extern int puGetPressedButton () ; + + + +class puValue +{ + UL_TYPE_DATA + +protected: + int type ; + + int integer ; + float floater ; + char *string ; + bool boolean ; + + int *res_integer ; + float *res_floater ; + char *res_string ; + bool *res_bool ; + + int string_size ; + int res_string_sz ; + + int convert ; + + void re_eval ( void ) ; + void update_res ( void ) const { } /* Obsolete ! */ ; + + void copy_stringval ( const char *str ) ; + + int * getIntegerp ( void ) { return res_integer != NULL ? res_integer : &integer ; } + float * getFloaterp ( void ) { return res_floater != NULL ? res_floater : &floater ; } + char * getStringp ( void ) { return res_string != NULL ? res_string : string ; } + bool * getBooleanp ( void ) { return res_bool != NULL ? res_bool : &boolean ; } + + void enableConversion ( void ) { convert = TRUE ; } + void disableConversion ( void ) { convert = FALSE ; } + int conversionEnabled ( void ) const { return convert ; } + +public: + puValue () + { + convert = TRUE ; + + string_size = PUSTRING_INITIAL ; + string = new char [ string_size ] ; + + type = PUCLASS_VALUE ; + res_integer = NULL ; + res_floater = NULL ; + res_string = NULL ; + res_bool = NULL ; + clrValue () ; + } + + virtual ~puValue () { delete [] string ; } + + int getType ( void ) const { return type ; } + const char *getTypeString ( void ) const ; + void clrValue ( void ) { setValue ( "" ) ; } + + virtual void setValue ( puValue *pv ) + { + *getIntegerp () = pv -> getIntegerValue () ; + *getFloaterp () = pv -> getFloatValue () ; + copy_stringval ( pv -> getStringValue () ) ; + *getBooleanp () = pv -> getBooleanValue () ; + puPostRefresh () ; + } + + void setValuator ( int *i ) + { + res_integer = i ; + + if ( convert == TRUE ) + { + res_floater = NULL ; res_string = NULL ; res_bool = NULL ; + re_eval () ; + } + } + + void setValuator ( float *f ) + { + res_floater = f ; + + if ( convert == TRUE ) + { + res_integer = NULL ; res_string = NULL ; res_bool = NULL ; + re_eval () ; + } + } + + void setValuator ( char *s, int size ) + { + res_string = s ; + res_string_sz = size ; + + if ( convert == TRUE ) + { + res_integer = NULL ; res_floater = NULL ; res_bool = NULL ; + re_eval () ; + } + } + + void setValuator ( bool *b ) + { + res_bool = b ; + + if ( convert == TRUE ) + { + res_integer = NULL ; res_floater = NULL ; res_string = NULL ; + re_eval () ; + } + } + + /* Obsolete ! */ + void setValuator ( char *s ) { setValuator ( s, PUSTRING_MAX ) ; } + + virtual void setValue ( int i ) + { + *getIntegerp () = i ; + + if ( convert == TRUE ) + { + *getFloaterp () = (float) i ; sprintf ( getStringp (), "%d", i ) ; *getBooleanp () = ( i != 0 ) ; + } + + puPostRefresh () ; + } + + virtual void setValue ( float f ) + { + *getFloaterp () = f ; + + if ( convert == TRUE ) + { + *getIntegerp () = (int) f ; sprintf ( getStringp (), "%g", f ) ; *getBooleanp () = ( f != 0.0 ) ; + } + + puPostRefresh () ; + } + + virtual void setValue ( const char *s ) ; + + virtual void setValue ( bool b ) + { + *getBooleanp () = b ; + + if ( convert == TRUE ) + { + *getIntegerp () = b ? 1 : 0 ; *getFloaterp () = b ? 1.0f : 0.0f ; sprintf ( getStringp (), "%s", b ? "1" : "0" ) ; + } + + puPostRefresh () ; + } + + void getValue ( int *i ) { re_eval () ; *i = *getIntegerp () ; } + void getValue ( float *f ) { re_eval () ; *f = *getFloaterp () ; } + void getValue ( char **s ) { re_eval () ; *s = getStringp () ; } + void getValue ( char *s, int size ) + { + re_eval () ; + + /* Work around ANSI strncpy's null-fill behaviour */ + + s[0] = '\0' ; + strncat ( s, getStringp (), size-1 ) ; + } + + void getValue ( char *s ) { getValue ( s, PUSTRING_MAX ) ; } /* Obsolete ! */ + void getValue ( bool *b ) { re_eval () ; *b = *getBooleanp () ; } + + int getValue ( void ) { return getIntegerValue () ; } /* Obsolete ! */ + + virtual int getIntegerValue ( void ) { re_eval () ; return *getIntegerp () ; } + virtual float getFloatValue ( void ) { re_eval () ; return *getFloaterp () ; } + virtual char getCharValue ( void ) { re_eval () ; return getStringp ()[0]; } + virtual char *getStringValue ( void ) { re_eval () ; return getStringp () ; } + virtual bool getBooleanValue ( void ) { re_eval () ; return *getBooleanp () ; } + + /* RTTI */ + ulRTTItypeid getTypeInfo ( void ) const { return RTTI_vinfo () ; } +} ; + +typedef void (*puCallback)(class puObject *) ; +typedef void (*puRenderCallback)(class puObject *, int dx, int dy, void *) ; + +void puSetDefaultStyle ( int style ) ; +int puGetDefaultStyle ( void ) ; +void puSetDefaultBorderThickness ( int t ) ; +int puGetDefaultBorderThickness ( void ) ; +void puSetDefaultFonts ( puFont legendFont, puFont labelFont ) ; +void puGetDefaultFonts ( puFont *legendFont, puFont *labelFont ) ; + +puFont puGetDefaultLabelFont ( void ) ; +puFont puGetDefaultLegendFont ( void ) ; + +void puSetDefaultColourScheme ( float r, float g, float b, float a = 1.0f ) ; +inline void puSetDefaultColorScheme ( float r, float g, float b, float a = 1.0f ) +{ + puSetDefaultColourScheme ( r, g, b, a ) ; +} + +void puGetDefaultColourScheme ( float *r, float *g, float *b, float *a = NULL ); +inline void puGetDefaultColorScheme ( float *r, float *g, float *b, float *a = NULL ) +{ + puGetDefaultColourScheme ( r, g, b, a ) ; +} + +class puObject : public puValue +{ + UL_TYPE_DATA + +protected: + puValue default_value ; + + puBox bbox ; /* Bounding box of entire Object */ + puBox abox ; /* Active (clickable) area */ + puColour colour [ PUCOL_MAX ] ; + puGroup *parent ; + + int active_mouse_edge ; /* is it PU_UP or PU_DOWN (or both) that activates this? */ + int active_mouse_button ; /* which mouse button or buttons activate this */ + int style ; + int visible ; + int active ; + int highlighted ; + int am_default ; + int window ; /* Which window does the object appear in? */ + int v_status ; /* 1 if the Object should lock in the top left corner, 0 if not */ + + const char *label ; puFont labelFont ; int labelPlace ; + const char *legend ; puFont legendFont ; int legendPlace ; + + void *user_data ; + puCallback cb ; + puCallback active_cb ; + puCallback down_cb ; + puRenderCallback r_cb ; + void *render_data ; + int border_thickness ; + + short when_to_deactivate ; /* On next mouseclick or on next widget activation */ + + virtual void draw_legend ( int dx, int dy ) ; + virtual void draw_label ( int dx, int dy ) ; + +public: + virtual int isHit ( int x, int y ) const { return isVisible() && isActive() && + x > abox.min[0] && + x < abox.max[0] && + y > abox.min[1] && + y < abox.max[1] && + window == puGetWindow () ; } + + virtual void doHit ( int button, int updown, int x, int y ) ; + + puObject ( int minx, int miny, int maxx, int maxy ) ; + ~puObject () ; + + puObject *next ; /* Should not be used directly by applications any longer. */ + puObject *prev ; /* Instead, use the setNextObject and setPrevObject + methods. */ + + puBox *getBBox ( void ) const { return (puBox *) &bbox ; } + puBox *getABox ( void ) const { return (puBox *) &abox ; } + + void getAbsolutePosition ( int *x, int *y ) const ; + + virtual 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() ; puPostRefresh () ; + } + + virtual void setSize ( int w, int h ) + { + abox.max[0] = abox.min[0] + w ; + abox.max[1] = abox.min[1] + h ; + recalc_bbox() ; puPostRefresh () ; + } + + void getPosition ( int *x, int *y ) const + { + 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 ) const + { + 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 ; + + puGroup *getParent ( void ) const { return parent ; } + void setParent ( puGroup* p ) { parent = p ; } + + void setNextObject ( puObject *obj ) { next = obj ; } + puObject *getNextObject ( void ) const { return next ; } + void setPrevObject ( puObject *obj ) { prev = obj ; } + puObject *getPrevObject ( void ) const { return prev ; } + + void setCallback ( puCallback c ) { cb = c ; } + puCallback getCallback ( void ) const { return cb ; } + void invokeCallback ( void ) { if ( cb != NULL ) (*cb)(this) ; } + + void setActiveCallback ( puCallback c ) { active_cb = c ; } + puCallback getActiveCallback ( void ) const { return active_cb ; } + void invokeActiveCallback ( void ) { if ( active_cb != NULL ) (*active_cb)(this) ; } + + void setDownCallback ( puCallback c ) { down_cb = c ; } + puCallback getDownCallback ( void ) const { return down_cb ; } + virtual void invokeDownCallback ( void ) { if ( down_cb != NULL ) (*down_cb)(this) ; } + + void setRenderCallback ( puRenderCallback c, void *d = NULL ) { r_cb = c ; render_data = d ; } + puRenderCallback getRenderCallback ( void ) const { return r_cb ; } + void *getRenderCallbackData ( void ) const { return render_data ; } + void invokeRenderCallback ( int dx, int dy ) { if ( r_cb != NULL ) (*r_cb)(this, dx, dy, render_data) ; } + + void setBorderThickness ( int t ) { border_thickness = t ; puPostRefresh () ; } + int getBorderThickness ( void ) const { return border_thickness ; } + + void makeReturnDefault ( int def ) { am_default = def ; puPostRefresh () ; } + int isReturnDefault ( void ) const { return am_default ; } + + int getWindow ( void ) const { return window ; } + void setWindow ( int w ) { window = w ; puPostRefresh () ; } + + void setActiveDirn ( int e ) { active_mouse_edge = e ; } + int getActiveDirn ( void ) const { return active_mouse_edge ; } + + void setActiveButton ( int b ) { active_mouse_button = b ; } + int getActiveButton ( void ) const { return active_mouse_button ; } + + void setWhenToDeactivate ( short d ) { when_to_deactivate = d ; } + short getWhenToDeactivate ( void ) const { return when_to_deactivate ; } + + void setLegend ( const char *l ) { legend = l ; recalc_bbox() ; puPostRefresh () ; } + const char *getLegend ( void ) const { return legend ; } + + void setLegendFont ( puFont f ) { legendFont = f ; recalc_bbox() ; puPostRefresh () ; } + puFont getLegendFont ( void ) const { return legendFont ; } + + void setLegendPlace ( int lp ) { legendPlace = lp ; recalc_bbox() ; puPostRefresh () ; } + int getLegendPlace ( void ) const { return legendPlace ; } + + void setLabel ( const char *l ) { label = l ; recalc_bbox() ; puPostRefresh () ; } + const char *getLabel ( void ) const { return label ; } + + void setLabelFont ( puFont f ) { labelFont = f ; recalc_bbox() ; puPostRefresh () ; } + puFont getLabelFont ( void ) const { return labelFont ; } + + void setLabelPlace ( int lp ) { labelPlace = lp ; recalc_bbox() ; puPostRefresh () ; } + int getLabelPlace ( void ) const { return labelPlace ; } + + void activate ( void ) { if ( ! active ) { active = TRUE ; puPostRefresh () ; } } + void greyOut ( void ) { if ( active ) { active = FALSE ; puPostRefresh () ; } } + int isActive ( void ) const { return active ; } + + void highlight ( void ) { if ( ! highlighted ) { highlighted = TRUE ; puPostRefresh () ; } } + void lowlight ( void ) { if ( highlighted ) { highlighted = FALSE ; puPostRefresh () ; } } + int isHighlighted( void ) const { return highlighted ; } + + void reveal ( void ) { if ( ! visible ) { visible = TRUE ; puPostRefresh () ; } } + void hide ( void ) { if ( visible ) { visible = FALSE ; puPostRefresh () ; } } + int isVisible ( void ) const { return visible ; } + + void setStyle ( int which ) + { + style = which ; + + switch ( abs(style) ) + { + case PUSTYLE_SPECIAL_UNDERLINED : + border_thickness = 1 ; + break ; + + case PUSTYLE_SMALL_BEVELLED : + case PUSTYLE_SMALL_SHADED : + case PUSTYLE_BOXED : + border_thickness = 2 ; + break ; + + case PUSTYLE_BEVELLED : + case PUSTYLE_SHADED : + case PUSTYLE_DROPSHADOW : + border_thickness = 5 ; + break ; + } + + recalc_bbox () ; + puPostRefresh () ; + } + + int getStyle ( void ) const { return style ; } + + virtual void setColourScheme ( float r, float g, float b, float a = 1.0f ) ; + void setColorScheme ( float r, float g, float b, float a = 1.0f ) + { + setColourScheme ( r, g, b, a ) ; + } + + virtual void setColour ( int which, float r, float g, float b, float a = 1.0f ) + { + puSetColour ( colour [ which ], r, g, b, a ) ; + puPostRefresh () ; + } + void setColor ( int which, float r, float g, float b, float a = 1.0f ) + { + setColour ( which, r, g, b, a ) ; + } + + void getColour ( int which, float *r, float *g, float *b, float *a = NULL ) const + { + 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 getColor ( int which, float *r, float *g, float *b, float *a = NULL ) const + { + getColour ( which, r, g, b, a ); + } + + void setUserData ( void *data ) { user_data = data ; } + void *getUserData ( void ) const { 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 ( const 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 ) ; } + void getDefaultValue ( char *s ) { default_value.getValue ( s ) ; } + + int getDefaultValue ( void ) { return default_value.getValue () ; } /* Obsolete ! */ + + int getDefaultIntegerValue ( void ) { return default_value.getIntegerValue () ; } + float getDefaultFloatValue ( void ) { return default_value.getFloatValue () ; } + char *getDefaultStringValue ( void ) { return default_value.getStringValue () ; } + + int getVStatus ( void ) const { return v_status ; } /* JCJ 6 Jun 2002 */ + void setVStatus ( int vstat ) { v_status = vstat ; } +} ; + +/* + The 'live' interface stack is used for clicking and rendering. +*/ + +void puPushLiveInterface ( puInterface *in ) ; +void puPopLiveInterface ( puInterface *in = 0 ) ; +int puNoLiveInterface ( void ) ; +puInterface *puGetBaseLiveInterface ( void ) ; +puInterface *puGetUltimateLiveInterface ( void ) ; + +/* + The regular group stack is used for adding widgets +*/ + +void puPushGroup ( puGroup *in ) ; +void puPopGroup ( void ) ; +int puNoGroup ( void ) ; +puGroup *puGetCurrGroup ( void ) ; + +class puGroup : public puObject +{ + UL_TYPE_DATA + +protected: + int num_children ; + puObject *dlist ; + + int mouse_x ; // Coordinates of mouse when right button pressed for + int mouse_y ; // drag and drop + + int mouse_active; // Flag telling whether interface is presently being dragged + + void doHit ( int button, int updown, int x, int y ) ; + + int floating; // DEPRECATED! -- Flag telling whether the interface floats in the window or stays put + +public: + + puGroup ( int x, int y ) : puObject ( x, y, x, y ) + { + type |= PUCLASS_GROUP ; + dlist = NULL ; + num_children = 0 ; + mouse_x = 0 ; + mouse_y = 0 ; + mouse_active = FALSE ; + floating = FALSE ; // DEPRECATED! + puPushGroup ( this ) ; + } + + ~puGroup () ; + + void recalc_bbox ( void ) ; + virtual void add ( puObject *new_object ) ; + virtual void remove ( puObject *old_object ) ; + virtual void empty ( void ) ; + + 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 ) const { return dlist ; } + puObject *getLastChild ( void ) const + { + puObject *bo = dlist ; + + if ( bo != NULL ) + { + while ( bo -> getNextObject() != NULL ) + bo = bo -> getNextObject() ; + } + + return bo ; + } + int getNumChildren ( void ) const { return num_children ; } + + virtual void close ( void ) + { + if ( puGetCurrGroup () != this ) + ulSetError ( UL_WARNING, "PUI: puGroup::close() is mismatched!" ) ; + else + puPopGroup () ; + } + + void setFloating ( int value ) { floating = value ; } // DEPRECATED! + int getFloating ( void ) const { return floating ; } // DEPRECATED! + + void setChildStyle ( int childs, int which, int recursive = FALSE ) ; + void setChildBorderThickness ( int childs, int t, int recursive = FALSE ) ; + + void setChildColour ( int childs, int which, + float r, float g, float b, float a = 1.0f, + int recursive = FALSE ) ; + void setChildColor ( int childs, int which, + float r, float g, float b, float a = 1.0f, + int recursive = FALSE ) + { + setChildColour ( childs, which, r, g, b, a, recursive ) ; + } + + void setChildColourScheme ( int childs, + float r, float g, float b, float a = 1.0f, + int recursive = FALSE ) ; + void setChildColorScheme ( int childs, + float r, float g, float b, float a = 1.0f, + int recursive = FALSE ) + { + setChildColourScheme ( childs, r, g, b, a, recursive ) ; + } + + void setChildLegendFont ( int childs, puFont f, int recursive = FALSE ) ; + void setChildLabelFont ( int childs, puFont f, int recursive = FALSE ) ; +} ; + + +class puInterface : public puGroup +{ + UL_TYPE_DATA + +public: + + puInterface ( int x, int y ) : puGroup ( x, y ) + { + type |= PUCLASS_INTERFACE ; + puPushLiveInterface ( this ) ; + } + + ~puInterface () ; +} ; + + +class puFrame : public puObject +{ + UL_TYPE_DATA + +public: + void draw ( int dx, int dy ) ; + puFrame ( int minx, int miny, int maxx, int maxy ) : + puObject ( minx, miny, maxx, maxy ) + { + type |= PUCLASS_FRAME ; + } + + void doHit ( int button, int updown, int x, int y ) + { + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + // Active widget exists and is not this one; call its down callback if it exists + + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + if ( isHit ( x, y ) && ( updown != PU_DRAG ) ) + puMoveToLast ( this -> parent ); + } +} ; + + + +class puText : public puObject +{ + UL_TYPE_DATA + +public: + virtual int isHit ( int /* x */, int /* y */ ) const { return FALSE ; } + void draw ( int dx, int dy ) ; + puText ( int x, int y ) : puObject ( x, y, x, y ) + { + type |= PUCLASS_TEXT ; + } +} ; + + +class puButton : public puObject +{ + UL_TYPE_DATA + +protected: + int button_type ; + +public: + void doHit ( int button, int updown, int x, int y ) ; + void draw ( int dx, int dy ) ; + + int getButtonType ( void ) const { return button_type ; } + void setButtonType ( int btype ) { button_type = btype ; puPostRefresh () ; } + + puButton ( int minx, int miny, const char *l ) : + puObject ( minx, miny, + minx + puGetDefaultLegendFont().getStringWidth ( l ) + PUSTR_LGAP + PUSTR_RGAP, + miny + puGetDefaultLegendFont().getStringHeight ( l ) + puGetDefaultLegendFont().getStringDescender () + PUSTR_TGAP + PUSTR_BGAP ) + { + type |= PUCLASS_BUTTON ; + button_type = PUBUTTON_NORMAL ; + setLegend ( l ) ; + } + + puButton ( int minx, int miny, int maxx, int maxy, int btype = PUBUTTON_NORMAL ) : + puObject ( minx, miny, maxx, maxy ) + { + type |= PUCLASS_BUTTON ; + button_type = btype ; + } +} ; + + +class puOneShot : public puButton +{ + UL_TYPE_DATA + +protected: +public: + void doHit ( int button, int updown, int x, int y ) ; + + puOneShot ( int minx, int miny, const 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 puArrowButton : public puOneShot +{ + UL_TYPE_DATA + +protected: + int arrow_type ; + +public: + void draw ( int dx, int dy ) ; + + int getArrowType ( void ) const { return arrow_type ; } + void setArrowType ( int i ) { arrow_type = i ; puPostRefresh () ; } + + puArrowButton ( int minx, int miny, int maxx, int maxy, int ptype ) : + puOneShot ( minx, miny, maxx, maxy ) + { + type |= PUCLASS_ARROW ; + arrow_type = ptype ; + } +} ; + +class puRange +{ + UL_TYPE_DATA + +protected: + float minimum_value ; + float maximum_value ; + float step_size ; + float last_cb_value ; + float cb_delta ; + int cb_mode ; + + void puRange_init ( float minval, float maxval, float step ) + { + if ( maxval == minval ) + { + maxval = 1.0f ; + minval = 0.0f ; + } + + minimum_value = minval ; + maximum_value = maxval ; + step_size = step ; + last_cb_value = -1.0f ; + cb_delta = 0.1f ; + cb_mode = PUSLIDER_ALWAYS ; + } + + float clamp ( float f ) + { + if ( f < minimum_value ) return minimum_value ; + else if ( f > maximum_value ) return maximum_value ; + return f ; + } + +public: + puRange () + { + puRange_init ( 0.0f, 1.0f, 0.0f ) ; + } + + puRange ( float minval, float maxval, float step = 0.0f ) + { + puRange_init ( minval, maxval, step ) ; + } + + virtual ~puRange() + { + } + + float getMaxValue ( void ) const { return maximum_value ; } + virtual void setMaxValue ( float f ) { maximum_value = f ; } + + float getMinValue ( void ) const { return minimum_value ; } + virtual void setMinValue ( float f ) { minimum_value = f ; } + + float getStepSize ( void ) const { return step_size ; } + void setStepSize ( float f ) { step_size = f ; } + + float checkStep ( float val_to_check ) const + { + float step = val_to_check ; + + if ( getStepSize () > 0.0f ) + { + step = val_to_check - (float) fmod ( val_to_check, getStepSize () ) ; + + if ( ( val_to_check - step ) > ( step + getStepSize() - val_to_check ) ) + step += getStepSize () ; + } + + return step ; + } + + void setCBMode ( int m ) { cb_mode = m ; } + int getCBMode ( void ) const { return cb_mode ; } + + void setDelta ( float f ) { cb_delta = (f<=0.0f) ? 0.1f : (f>=1.0f) ? 0.9f : f ; } + float getDelta ( void ) const { return cb_delta ; } +} ; + +class puSlider : public puRange, public puObject +{ + UL_TYPE_DATA + +protected: + int vert ; + int start_offset ; + float slider_fraction ; + float page_step_size ; + void draw_slider_box ( int dx, int dy, const puBox &box, float val, const char *box_label = NULL ) ; + + void puSlider_init ( int vertical ) + { + type |= PUCLASS_SLIDER ; + vert = vertical ; + slider_fraction = 0.1f ; + page_step_size = 0.0f ; + } + +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 ) : + puRange (), + puObject ( minx, miny, vertical ? + ( minx + puGetDefaultLegendFont().getStringWidth ( "W" ) + + PUSTR_LGAP + PUSTR_RGAP ) : + ( minx + sz ), + vertical ? + ( miny + sz ) : + ( miny + puGetDefaultLegendFont().getStringHeight () + + puGetDefaultLegendFont().getStringDescender () + + PUSTR_TGAP + PUSTR_BGAP ) + ) + { + puSlider_init ( vertical ) ; + } + + /* Blake Friesen - alternate constructor which lets you explicitly set width */ + puSlider ( int minx, int miny, int sz, int vertical, int width ) : + puRange (), + puObject ( minx, miny, vertical ? + ( minx + width ) : + ( minx + sz ), + vertical ? + ( miny + sz ) : + ( miny + width ) + ) + { + puSlider_init ( vertical ) ; + } + + int isVertical ( void ) const { return vert ; } + + void setSliderFraction ( float f ) ; + float getSliderFraction ( void ) const { return slider_fraction ; } + void setPageStepSize ( float s ) { page_step_size = s ; } + float getPageStepSize ( void ) const { return page_step_size ; } +} ; + + +class puListBox : public puButton +{ + UL_TYPE_DATA + +protected: + char ** list ; + int num ; + int top ; + +public: + void doHit ( int button, int updown, int x, int y ) ; + void draw ( int dx, int dy ) ; + puListBox ( int minx, int miny, int maxx, int maxy, char** list = NULL ) ; + + void newList ( char ** _list ) ; + int getNumItems ( void ) const { return num ; } + int getNumVisible ( void ) const + { + int ysize = abox.max[1] - abox.min[1] + 1 ; + int yinc = legendFont.getStringHeight () + PUSTR_BGAP ; + return (ysize - PUSTR_BGAP) / yinc ; + } + + int getTopItem ( void ) const { return top ; } + void setTopItem ( int item_index ) ; +} ; + + +class puDial : public puRange, public puObject +{ + UL_TYPE_DATA + +protected: + int wrap ; // Flag telling whether you can wrap around the bottom of the dial +public: + void doHit ( int button, int updown, int x, int y ) ; + void draw ( int dx, int dy ) ; + + puDial ( int minx, int miny, int sz ) : + puRange (), puObject ( minx, miny, minx+sz, miny+sz ) + { + type |= PUCLASS_DIAL ; + setValue ( 0.0f ) ; + wrap = TRUE ; + } + + puDial ( int minx, int miny, int sz, float minval, float maxval, float step = 0.0f ) : + puRange ( minval, maxval, step ), + puObject ( minx, miny, minx+sz, miny+sz ) + { + type |= PUCLASS_DIAL ; + setValue ( 0.0f ) ; + wrap = TRUE ; + } + + void setWrap ( int in ) { wrap = in ; } + int getWrap ( void ) const { return wrap ; } +} ; + + + +class puPopup : public puInterface +{ + UL_TYPE_DATA + +protected: +public: + puPopup ( int x, int y ) : puInterface ( x, y ) + { + type |= PUCLASS_POPUP ; + hide () ; + } +} ; + + +class puPopupMenu : public puPopup +{ + UL_TYPE_DATA + +protected: +public: + puPopupMenu ( int x, int y ) : puPopup ( x, y ) + { + type |= PUCLASS_POPUPMENU ; + } + + puObject *add_item ( const char *str, puCallback _cb, + void *_user_data = NULL ) ; + int checkHit ( int button, int updown, int x, int y ) ; + int checkKey ( int key , int updown ) ; + void close ( void ) ; +} ; + + +class puMenuBar : public puInterface +{ + UL_TYPE_DATA + +protected: + int bar_height ; + +public: + puMenuBar ( int h = -1 ) : puInterface ( 0, 0 ) + { + type |= PUCLASS_MENUBAR ; + + bar_height = h ; + } + + void add_submenu ( const char *str, char *items[], puCallback _cb[], + void *_user_data[] = NULL ) ; + void close ( void ) ; +} ; + + +class puInputBase +{ + UL_TYPE_DATA + +protected: + int accepting ; + int cursor_position ; + int select_start_position ; + int select_end_position ; + char *valid_data ; + int input_disabled ; + + char *displayed_text ; // Pointer to text as it is displayed in the box (chopped or word-wrapped) + + puObject *widget ; /* Pointer to associated input box widget */ + + virtual void normalizeCursors ( void ) ; + virtual void removeSelectRegion ( void ) ; + +public: + int isAcceptingInput ( void ) const { return accepting ; } + void rejectInput ( void ) { accepting = FALSE ; puPostRefresh () ; } + + void acceptInput ( void ) + { + accepting = TRUE ; + cursor_position = strlen ( widget -> getStringValue () ) ; + select_start_position = select_end_position = -1 ; + puPostRefresh () ; + } + + int getCursor ( void ) const { return cursor_position ; } + void setCursor ( int c ) { cursor_position = c ; puPostRefresh () ; } + + virtual void setSelectRegion ( int s, int e ) + { + select_start_position = s ; + select_end_position = e ; + puPostRefresh () ; + } + + void getSelectRegion ( int *s, int *e ) const + { + if ( s ) *s = select_start_position ; + if ( e ) *e = select_end_position ; + } + + char *getValidData ( void ) const { return valid_data ; } + void setValidData ( const char *data ) + { + delete [] valid_data ; + valid_data = ( data != NULL ) ? ulStrDup ( data ) : NULL ; + } + + void addValidData ( const char *data ) ; + + int isValidCharacter ( char c ) const + { + if ( valid_data != NULL ) + return ( strchr ( valid_data, c ) != NULL ) ? 1 : 0 ; + else + return 1 ; + } + + void enableInput ( void ) { input_disabled = FALSE ; } + void disableInput ( void ) { input_disabled = TRUE ; } + int inputDisabled ( void ) const { return input_disabled ; } + + puInputBase ( void ) + { + accepting = FALSE ; + cursor_position = 0 ; + select_start_position = -1 ; + select_end_position = -1 ; + valid_data = NULL; + displayed_text = NULL ; + + widget = (puObject *)NULL ; + + input_disabled = FALSE ; + } + + virtual ~puInputBase () { delete [] valid_data ; delete [] displayed_text ; } +} ; + + +class puInput : public puInputBase, public puObject +{ + UL_TYPE_DATA + + int display_starting_point ; + + char *getDisplayedText ( void ) + { + return ( displayed_text == NULL ? getStringValue () : displayed_text ) ; + } + +public: + void draw ( int dx, int dy ) ; + void doHit ( int button, int updown, int x, int y ) ; + int checkKey ( int key, int updown ) ; + + void invokeDownCallback ( void ) + { + rejectInput () ; + normalizeCursors () ; + if ( down_cb != NULL ) (*down_cb)(this) ; + } + + puInput ( int minx, int miny, int maxx, int maxy ) : + puInputBase (), puObject ( minx, miny, maxx, maxy ) + { + type |= PUCLASS_INPUT ; + + display_starting_point = 0 ; + + setColourScheme ( colour [ PUCOL_EDITFIELD ][0], + colour [ PUCOL_EDITFIELD ][1], + colour [ PUCOL_EDITFIELD ][2], + colour [ PUCOL_EDITFIELD ][3] ) ; + setColour ( PUCOL_MISC, 0.1f, 0.1f, 1.0f ) ; /* Colour of 'I' bar cursor */ + + widget = this ; + } + + virtual void setValue ( puValue *pv ) + { + puValue::setValue ( pv ) ; + delete [] displayed_text ; displayed_text = NULL ; + } + + virtual void setValue ( int i ) + { + puValue::setValue ( i ) ; + delete [] displayed_text ; displayed_text = NULL ; + } + + virtual void setValue ( float f ) + { + puValue::setValue ( f ) ; + delete [] displayed_text ; displayed_text = NULL ; + } + + virtual void setValue ( const char *s ) + { + puValue::setValue ( s ) ; + delete [] displayed_text ; displayed_text = NULL ; + } + + virtual void setValue ( bool b ) + { + puValue::setValue ( b ) ; + delete [] displayed_text ; displayed_text = NULL ; + } +} ; + + +class puButtonBox : public puObject +{ + UL_TYPE_DATA + +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 ) const { return one_only ; } + + void newList ( char ** _list ) ; + int getNumItems ( void ) const { return num_kids ; } + + 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 +{ + UL_TYPE_DATA + +protected: +public: + + puDialogBox ( int x, int y ) : puPopup ( x, y ) + { + type |= PUCLASS_DIALOGBOX ; + } +} ; + + + +/* + * Window System Integration + * ------------------------- + * + * PUI has direct support for GLUT, PW, FLTK, SDL and GTK. All code is provided + * inline, making PUI itself independent. There are several ways to choose + * implementation, for instance: + * + * #include + * #include + * + * or simply: + * + * #include + * + * Note that both cases may fail if pu.h has been included earlier. + * A safer option is therefore to compile with -DPU_USE_FLTK. + * + * The default system is GLUT for backwards compability. + * + * To use PUI with an unsupported system, define PU_USE_NONE and + * provide your own callbacks (if needed, the defaults will work + * in many cases). + * + * When compiling the PUI library itself, PU_USE_NONE must be defined. + * + */ + +typedef int (*puGetWindowCallback) ( ) ; +typedef void (*puSetWindowCallback) ( int window ) ; +typedef void (*puGetWindowSizeCallback) ( int *width, int *height ) ; +typedef void (*puSetWindowSizeCallback) ( int width, int height ) ; + +void puSetWindowFuncs ( puGetWindowCallback, + puSetWindowCallback, + puGetWindowSizeCallback, + puSetWindowSizeCallback ) ; + + +// Choose implementation + +#if !defined(PU_USE_GLUT) && \ + !defined(PU_USE_PW) && \ + !defined(PU_USE_FLTK) && \ + !defined(PU_USE_SDL) && \ + !defined(PU_USE_NATIVE) && \ + !defined(PU_USE_NONE) + +// Nothing selected. Try to figure out which one to use. +#if defined(PW_IS_PRESENT) +# define PU_USE_PW +#elif defined(FL_MAJOR_VERSION) +# define PU_USE_FLTK +#elif defined(SDL_MAJOR_VERSION) +# define PU_USE_SDL +#else +# define PU_USE_GLUT +#endif + +#endif + + +// Roll out the code and define puInit + +#if defined(PU_USE_GLUT) +# include "puGLUT.h" +# define puInit puInitGLUT +#elif defined(PU_USE_PW) +# include "puPW.h" +# define puInit puInitPW +#elif defined(PU_USE_FLTK) +# include "puFLTK.h" +# define puInit puInitFLTK +#elif defined(PU_USE_SDL) +# include "puSDL.h" +# define puInit puInitSDL +#elif defined(PU_USE_NATIVE) +# include "puNative.h" +# define puInit puInitNative +#else +# define puInit +#endif + + +#endif diff --git a/src/pui/puArrowButton.cxx b/src/pui/puArrowButton.cxx new file mode 100644 index 0000000..0b77352 --- /dev/null +++ b/src/pui/puArrowButton.cxx @@ -0,0 +1,170 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puArrowButton.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF1(puArrowButton,puButton) + + +void puDrawArrowButtonTriangle ( int pos_x, int pos_y, int size_x, int size_y, + puColour colour, int arrow_type, int active ) +{ + /* + If greyed out then halve the opacity when drawing + the widget + */ + + if ( active ) + glColor4fv ( colour ) ; + else + glColor4f ( colour [0], + colour [1], + colour [2], + colour [3] / 2.0f ) ; // 50% more transparent + + switch ( arrow_type ) + { + case PUARROW_UP : + glBegin ( GL_TRIANGLES ) ; + glVertex2i ( pos_x - size_x/4, pos_y - size_y/4 ) ; + glVertex2i ( pos_x , pos_y + size_y/4 ) ; + glVertex2i ( pos_x + size_x/4, pos_y - size_y/4 ) ; + glEnd () ; + break; + + case PUARROW_DOWN : + glBegin ( GL_TRIANGLES ) ; + glVertex2i ( pos_x - size_x/4, pos_y + size_y/4 ) ; + glVertex2i ( pos_x , pos_y - size_y/4 ) ; + glVertex2i ( pos_x + size_x/4, pos_y + size_y/4 ) ; + glEnd () ; + break; + + case PUARROW_FASTUP : + glBegin ( GL_TRIANGLES ) ; + glVertex2i ( pos_x - size_x/4, pos_y - size_y/4 ) ; + glVertex2i ( pos_x , pos_y ) ; + glVertex2i ( pos_x + size_x/4, pos_y - size_y/4 ) ; + + glVertex2i ( pos_x - size_x/4, pos_y ) ; + glVertex2i ( pos_x , pos_y + size_y/4 ) ; + glVertex2i ( pos_x + size_x/4, pos_y ) ; + glEnd () ; + break; + + case PUARROW_FASTDOWN : + glBegin ( GL_TRIANGLES ) ; + glVertex2i ( pos_x - size_x/4, pos_y + size_y/4 ) ; + glVertex2i ( pos_x , pos_y ) ; + glVertex2i ( pos_x + size_x/4, pos_y + size_y/4 ) ; + + glVertex2i ( pos_x - size_x/4, pos_y ) ; + glVertex2i ( pos_x , pos_y - size_y/4 ) ; + glVertex2i ( pos_x + size_x/4, pos_y ) ; + glEnd () ; + break; + + case PUARROW_LEFT : + glBegin ( GL_TRIANGLES ) ; + glVertex2i ( pos_x + size_x/4, pos_y - size_y/4 ) ; + glVertex2i ( pos_x - size_x/4, pos_y ) ; + glVertex2i ( pos_x + size_x/4, pos_y + size_y/4 ) ; + glEnd () ; + break; + + case PUARROW_RIGHT : + glBegin ( GL_TRIANGLES ) ; + glVertex2i ( pos_x - size_x/4, pos_y - size_y/4 ) ; + glVertex2i ( pos_x + size_x/4, pos_y ) ; + glVertex2i ( pos_x - size_x/4, pos_y + size_y/4 ) ; + glEnd () ; + break; + + case PUARROW_FASTLEFT : + glBegin ( GL_TRIANGLES ) ; + glVertex2i ( pos_x + size_x/4, pos_y - size_y/4 ) ; + glVertex2i ( pos_x , pos_y ) ; + glVertex2i ( pos_x + size_x/4, pos_y + size_y/4 ) ; + + glVertex2i ( pos_x , pos_y - size_y/4 ) ; + glVertex2i ( pos_x - size_x/4, pos_y ) ; + glVertex2i ( pos_x , pos_y + size_y/4 ) ; + glEnd () ; + break; + + case PUARROW_FASTRIGHT : + glBegin ( GL_TRIANGLES ) ; + glVertex2i ( pos_x - size_x/4, pos_y - size_y/4 ) ; + glVertex2i ( pos_x , pos_y ) ; + glVertex2i ( pos_x - size_x/4, pos_y + size_y/4 ) ; + + glVertex2i ( pos_x , pos_y - size_y/4 ) ; + glVertex2i ( pos_x + size_x/4, pos_y ) ; + glVertex2i ( pos_x , pos_y + size_y/4 ) ; + glEnd () ; + break; + + default : + ulSetError ( UL_WARNING, "PUI: Unrecognised 'arrow_type' %d", arrow_type ) ; + break; + } +} + +void puArrowButton::draw ( int dx, int dy ) +{ + if ( !visible || ( window != puGetWindow () ) ) return ; + + /* + If arrow button is pushed or highlighted - + use inverse style for button itself + */ + + if ( getIntegerValue() ^ highlighted ) + { + if ( parent && ( ( parent->getType() & PUCLASS_POPUPMENU ) || + ( parent->getType() & PUCLASS_MENUBAR ) ) ) + abox.draw ( dx, dy, PUSTYLE_SMALL_SHADED, colour, isReturnDefault(), 2 ) ; + else + abox.draw ( dx, dy, -style, colour, isReturnDefault(), border_thickness ) ; + } + else + abox.draw ( dx, dy, style, colour, isReturnDefault(), border_thickness ) ; + + if ( r_cb ) + r_cb ( this, dx, dy, render_data ) ; + else + { + int size_x = abox.max[0] - abox.min[0] ; + int size_y = abox.max[1] - abox.min[1] ; + + int pos_x = dx + ( abox.max[0] + abox.min[0] ) / 2 ; + int pos_y = dy + ( abox.max[1] + abox.min[1] ) / 2 ; + + puDrawArrowButtonTriangle ( pos_x, pos_y, size_x, size_y, colour [ PUCOL_MISC ], arrow_type, active ) ; + } + + draw_label ( dx, dy ) ; +} + + diff --git a/src/pui/puBox.cxx b/src/pui/puBox.cxx new file mode 100644 index 0000000..1cd98ea --- /dev/null +++ b/src/pui/puBox.cxx @@ -0,0 +1,266 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puBox.cxx 1943 2004-08-05 01:05:48Z puggles $ +*/ + + +#include "puLocal.h" + +#define PU_DFLT_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 border ) +{ + int mid = PUCOL_FOREGROUND ; + int hi = PUCOL_HIGHLIGHT ; + int lo = PUCOL_BACKGROUND ; + + /* 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 : + hi = PUCOL_HIGHLIGHT ; + lo = PUCOL_LEGEND ; + break ; + + 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 : + ulSetError ( UL_WARNING, "PUI: Unrecognised 'style' %d", 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 : + case PUSTYLE_BEVELLED : + case PUSTYLE_SHADED : + glColor4fv ( colour [ hi ] ) ; + glBegin ( GL_QUAD_STRIP ) ; + glVertex2i ( dx + min[0] + border, dy + min[1] + border ) ; + glVertex2i ( dx + min[0], dy + min[1] ) ; + glVertex2i ( dx + min[0] + border, dy + max[1] - border ) ; + glVertex2i ( dx + min[0], dy + max[1] ) ; + glVertex2i ( dx + max[0] - border, dy + max[1] - border ) ; + 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] + border, dy + min[1] + border ) ; + glVertex2i ( dx + max[0], dy + min[1] ) ; + glVertex2i ( dx + max[0] - border, dy + min[1] + border ) ; + glVertex2i ( dx + max[0], dy + max[1] ) ; + glVertex2i ( dx + max[0] - border, dy + max[1] - border ) ; + glEnd () ; + + if ( ( abs(style) == PUSTYLE_SMALL_BEVELLED ) || + ( abs(style) == PUSTYLE_BEVELLED ) ) + { + glColor4fv ( colour [ mid ] ) ; + glRecti ( dx + min[0] + border, dy + min[1] + border, + dx + max[0] - border, dy + max[1] - border ) ; + } + else + { + glShadeModel ( GL_SMOOTH ) ; + glBegin ( GL_POLYGON ) ; + glColor4fv ( colour [ mid ] ) ; + glVertex2i ( dx + min[0] + border, dy + min[1] + border ) ; + if ( ( style == PUSTYLE_SMALL_SHADED ) || + ( 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] + border, dy + max[1] - border ) ; + glColor4fv ( colour [ mid ] ) ; + glVertex2i ( dx + max[0] - border, dy + max[1] - border ) ; + if ( ( style == -PUSTYLE_SMALL_SHADED ) || + ( 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] - border, dy + min[1] + border ) ; + glEnd () ; + glShadeModel (GL_FLAT) ; + + if ( ( style == -PUSTYLE_SMALL_SHADED ) || + ( style == -PUSTYLE_SHADED ) ) + { + glColor4fv ( colour [ lo ] ) ; + glBegin ( GL_QUAD_STRIP ) ; + glVertex2i ( dx + min[0] + border , dy + min[1] + border ) ; + glVertex2i ( dx + min[0] + border/2 , dy + min[1] + border/2 ) ; + glVertex2i ( dx + min[0] + border , dy + max[1] - border ) ; + glVertex2i ( dx + min[0] + border/2 , dy + max[1] - border/2 ) ; + glVertex2i ( dx + max[0] - border , dy + max[1] - border ) ; + glVertex2i ( dx + max[0] - border/2 , dy + max[1] - border/2 ) ; + glEnd () ; + glColor4fv ( colour [ hi ] ) ; + glBegin ( GL_QUAD_STRIP ) ; + glVertex2i ( dx + min[0] + border/2 , dy + min[1] + border/2 ) ; + glVertex2i ( dx + min[0] + border , dy + min[1] + border ) ; + glVertex2i ( dx + max[0] - border/2 , dy + min[1] + border/2 ) ; + glVertex2i ( dx + max[0] - border , dy + min[1] + border ) ; + glVertex2i ( dx + max[0] - border/2 , dy + max[1] - border/2 ) ; + glVertex2i ( dx + max[0] - border , dy + max[1] - border ) ; + 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]+border, dy + min[1]+border, + dx + max[0]-border, dy + max[1]-border ) ; + 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]+border ) ; + glColor4fv ( colour [ mid ] ) ; + glRecti ( dx + min[0], dy + min[1]+border, + dx + max[0], dy + max[1] ) ; + break ; + + case PUSTYLE_DROPSHADOW : + glColor4fv ( colour [ lo ] ) ; + glRecti ( dx + min[0] + border, dy + min[1] - border, + dx + max[0] + border, dy + max[1] - border ) ; + 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 ) ; + glVertex2f ( dx + min[0] + PU_DFLT_OFFSET + 0.5f, dy + min[1] + PU_DFLT_OFFSET + 0.5f ) ; + glVertex2f ( dx + min[0] + PU_DFLT_OFFSET + 0.5f, dy + max[1] - PU_DFLT_OFFSET - 0.5f ) ; + glVertex2f ( dx + max[0] - PU_DFLT_OFFSET - 0.5f, dy + max[1] - PU_DFLT_OFFSET - 0.5f ) ; + glVertex2f ( dx + max[0] - PU_DFLT_OFFSET - 0.5f, dy + min[1] + PU_DFLT_OFFSET + 0.5f ) ; + glEnd () ; + glDisable ( GL_LINE_STIPPLE ) ; + } +} + + + diff --git a/src/pui/puButton.cxx b/src/pui/puButton.cxx new file mode 100644 index 0000000..518dce0 --- /dev/null +++ b/src/pui/puButton.cxx @@ -0,0 +1,236 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puButton.cxx 2064 2006-01-05 21:32:59Z fayjf $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF1(puButton,puObject) + + +void puButton::draw ( int dx, int dy ) +{ + if ( !visible || ( window != puGetWindow () ) ) return ; + + if ( button_type == PUBUTTON_NORMAL ) + { + /* If button is pushed or highlighted - use inverse style */ + + if ( getIntegerValue() ^ highlighted ) + { + if ( parent && ( ( parent->getType() & PUCLASS_POPUPMENU ) || + ( parent->getType() & PUCLASS_MENUBAR ) ) ) + abox.draw ( dx, dy, active ? PUSTYLE_SMALL_SHADED : PUSTYLE_PLAIN, colour, + isReturnDefault(), active ? 2 : 0 ) ; + else + abox.draw ( dx, dy, -style, colour, isReturnDefault(), border_thickness ) ; + } + else + abox.draw ( dx, dy, style, colour, isReturnDefault(), border_thickness ) ; + } + else if ( ( button_type == PUBUTTON_VCHECK ) || + ( button_type == PUBUTTON_XCHECK ) ) + abox.draw ( dx, dy, PUSTYLE_BOXED, colour, isReturnDefault(), 1 ) ; + + if ( r_cb ) + r_cb ( this, dx, dy, render_data ) ; + else + { + switch ( button_type ) + { + case PUBUTTON_NORMAL : + draw_legend ( dx, dy ) ; + break ; + + case PUBUTTON_RADIO : + { + int btn_width = abox.max[0] - abox.min[0], + btn_height = abox.max[1] - abox.min[1] ; + + glColor4fv ( ( getIntegerValue () ^ highlighted ) ? + colour [ PUCOL_BACKGROUND ] : colour [ PUCOL_LEGEND ] ) ; + + glBegin ( GL_LINE_LOOP ) ; + glVertex2i ( dx+abox.min[0] + btn_width/2, dy+abox.min[1] ) ; + glVertex2i ( dx+abox.min[0] + btn_width, dy+abox.min[1] + btn_height/2 ) ; + glVertex2i ( dx+abox.min[0] + btn_width/2, dy+abox.min[1] + btn_height ) ; + glVertex2i ( dx+abox.min[0], dy+abox.min[1] + btn_height/2 ) ; + glEnd () ; + + if ( getIntegerValue () ^ highlighted ) + { + /* If greyed out then halve the opacity when drawing the widget */ + + if ( active ) + glColor4fv ( colour [ PUCOL_HIGHLIGHT ] ) ; + else + glColor4f ( colour [ PUCOL_HIGHLIGHT ][0], + colour [ PUCOL_HIGHLIGHT ][1], + colour [ PUCOL_HIGHLIGHT ][2], + colour [ PUCOL_HIGHLIGHT ][3] / 2.0f ) ; /* 50% more transparent */ + + glBegin ( GL_QUADS ) ; + glVertex2i ( dx+abox.min[0] + btn_width/2, + dy+abox.min[1] + 2 ) ; + glVertex2i ( dx+abox.min[0] + btn_width - 2, + dy+abox.min[1] + btn_height/2 ) ; + glVertex2i ( dx+abox.min[0] + btn_width/2, + dy+abox.min[1] + btn_height - 2 ) ; + glVertex2i ( dx+abox.min[0] + 2, + dy+abox.min[1] + btn_height/2 ) ; + glEnd () ; + } + + break ; + } + + case PUBUTTON_CIRCLE : + { + float rad = ( (abox.max[0]-abox.min[0]) < (abox.max[1]-abox.min[1]) ) ? + (abox.max[0]-abox.min[0])/2.0f : (abox.max[1]-abox.min[1])/2.0f ; + float dtheta = 2.0f / rad ; + float theta ; + + /* Draw the outer circle */ + + glColor4fv ( colour [ PUCOL_FOREGROUND ] ) ; + + glBegin ( GL_POLYGON ) ; + for ( theta = -SG_PI ; theta <= SG_PI ; theta += dtheta ) + glVertex2f ( dx + abox.min[0] + rad + (rad * float(cos ( theta ))), + dy + abox.min[1] + rad + (rad * float(sin ( theta ))) ) ; + glEnd () ; + + if ( getIntegerValue () ^ highlighted ) + /* If clicked, draw the inner circle with half the radius */ + { + rad /= 2 ; + dtheta = 2.0f / rad ; + + /* If greyed out then halve the opacity when drawing the widget */ + + if ( active ) + glColor4fv ( colour [ PUCOL_MISC ] ) ; + else + glColor4f ( colour [ PUCOL_MISC ][0], + colour [ PUCOL_MISC ][1], + colour [ PUCOL_MISC ][2], + colour [ PUCOL_MISC ][3] / 2.0f ) ; /* 50% more transparent */ + + glBegin ( GL_POLYGON ) ; + for ( theta = -SG_PI ; theta <= SG_PI ; theta += dtheta ) + glVertex2f ( dx + abox.min[0] + rad*2 + (rad * float(cos ( theta ))), + dy + abox.min[1] + rad*2 + (rad * float(sin ( theta ))) ) ; + glEnd () ; + } + + break ; + } + + case PUBUTTON_VCHECK : + case PUBUTTON_XCHECK : + if ( getIntegerValue () ^ highlighted ) + { + /* If greyed out then halve the opacity when drawing the widget */ + + if ( active ) + glColor4fv ( colour [ PUCOL_MISC ] ) ; + else + glColor4f ( colour [ PUCOL_MISC ][0], + colour [ PUCOL_MISC ][1], + colour [ PUCOL_MISC ][2], + colour [ PUCOL_MISC ][3] / 2.0f ) ; /* 50% more transparent */ + + glPushAttrib ( GL_LINE_BIT ) ; + + glLineWidth ( 2.0f ) ; + + if ( button_type == PUBUTTON_VCHECK ) + { + glBegin ( GL_LINE_STRIP ) ; + glVertex2i ( dx + abox.min[0], + dy + abox.min[1] + (abox.max[1] - abox.min[1])/2 ) ; + glVertex2i ( dx + abox.min[0] + (abox.max[0] - abox.min[0])/3, + dy + abox.min[1] ) ; + glVertex2i ( dx + abox.max[0], + dy + abox.max[1] ) ; + glEnd () ; + } + else if ( button_type == PUBUTTON_XCHECK ) + { + glBegin ( GL_LINES ) ; + glVertex2i ( dx + abox.min[0] + 1, dy + abox.min[1] + 1 ) ; + glVertex2i ( dx + abox.max[0] - 1, dy + abox.max[1] - 1 ) ; + glVertex2i ( dx + abox.max[0] - 1, dy + abox.min[1] + 1 ) ; + glVertex2i ( dx + abox.min[0] + 1, dy + abox.max[1] - 1 ) ; + glEnd () ; + } + + glPopAttrib () ; + } + + break ; + + default : + ulSetError ( UL_WARNING, "PUI: Unrecognised 'button_type' %d", button_type ) ; + break; + } + } + + draw_label ( dx, dy ) ; +} + + +void puButton::doHit ( int button, int updown, int x, int y ) +{ + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + if ( updown != PU_DRAG ) + puMoveToLast ( this ); + + if ( button == active_mouse_button ) + { + if ( ( updown == active_mouse_edge ) || ( active_mouse_edge == PU_UP_AND_DOWN ) ) + { + lowlight () ; + setValue ( (int) ! getIntegerValue () ) ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + } + else + { + /* If the mouse is over the widget, highlight it; otherwise lowlight it */ + if ( ( abox.min[0] <= x ) && ( abox.max[0] >= x ) && ( abox.min[1] <= y ) && ( abox.max[1] >= y ) ) + highlight () ; + else + lowlight () ; + } + } + else + lowlight () ; +} + + diff --git a/src/pui/puButtonBox.cxx b/src/pui/puButtonBox.cxx new file mode 100644 index 0000000..df33399 --- /dev/null +++ b/src/pui/puButtonBox.cxx @@ -0,0 +1,162 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puButtonBox.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF1(puButtonBox,puObject) + + +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 ; + + newList ( labels ) ; +} + + +void puButtonBox::newList ( char ** _list ) +{ + button_labels = _list ; + + if ( button_labels == NULL ) + num_kids = 0 ; + else + for ( num_kids = 0 ; button_labels [ num_kids ] != NULL ; num_kids++ ) + /* Count number of items */ ; + + puPostRefresh() ; +} + + +int puButtonBox::checkKey ( int key, int updown ) +{ + if ( updown == PU_UP || + ! isReturnDefault() || + ( key != '\r' && key != '\n' ) || ( window != puGetWindow () ) ) + return FALSE ; + + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + int v = getIntegerValue () ; + + if ( ! one_only ) + v = ~v ; + else + if ( ++v > num_kids ) + v = 0 ; + + setValue ( v ) ; +// puSetActiveWidget ( this, x, y ) ; + 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 ; + + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + if ( updown != PU_DRAG ) + puMoveToLast ( this ); + + 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 ( getIntegerValue () ^ ( 1 << i ) ) ; + + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + return TRUE ; +} + + +void puButtonBox::draw ( int dx, int dy ) +{ + if ( !visible || ( window != puGetWindow () ) ) return ; + + abox.draw ( dx, dy, style, colour, isReturnDefault(), border_thickness ) ; + + if ( r_cb ) + r_cb ( this, dx, dy, render_data ) ; + else + { + 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 == getIntegerValue() ) || + ( !one_only && ((1< 1.0f ) val = 1.0f ; + + val = ( 2.0f * val - 1.0f ) * SG_PI ; + + glBegin ( GL_LINES ) ; + + glVertex2f ( (float)x_cen, (float)y_cen ) ; + glVertex2f ( (float)x_cen + rad * (float)sin ( (double)val ), (float)y_cen + rad * (float)cos ( (double)val ) ) ; + + glEnd () ; + + glPopAttrib () ; + + draw_legend ( dx, dy ) ; + } + + draw_label ( dx, dy ) ; +} + + +void puDial::doHit ( int button, int updown, int x, int y ) +{ + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + if ( updown != PU_DRAG ) + puMoveToLast ( this ); + + if ( ( button == active_mouse_button ) && ( updown == PU_UP ) ) + { + puDeactivateWidget () ; + return ; + } + + if ( button == active_mouse_button ) + { + int x_cen = ( abox.max [0] + abox.min [0] ) / 2 ; + int y_cen = ( abox.max [1] + abox.min [1] ) / 2 ; + float angle = (float)atan2 ( (double)(x-x_cen), (double)(y-y_cen) ) / SG_PI ; + + // Move to within the (0,1) interval + + if ( angle < -1.0f ) + angle += 2.0f ; + else if (angle > 1.0f ) + angle -= 2.0f ; + + angle = ( angle + 1.0f ) / 2.0f ; + + // Check for hitting the limits (user has dragged the mouse around the bottom + // of the widget) + if ( !wrap ) + { + if ( ( angle > 0.75f ) && ( getFloatValue () < 0.25f ) ) + angle = 0.0f ; + else if ( ( angle < 0.25f ) && ( getFloatValue () > 0.75f ) ) + angle = 1.0f ; + } + + angle = angle * (maximum_value - minimum_value) + minimum_value ; + setValue( checkStep(angle) ) ; + + switch ( cb_mode ) + { + case PUSLIDER_CLICK : + if ( updown == active_mouse_edge ) + { + last_cb_value = angle ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + } + break ; + + case PUSLIDER_DELTA :/* Deprecated! */ + if ( fabs ( last_cb_value - angle ) >= cb_delta ) + { + last_cb_value = angle ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + } + break ; + + case PUSLIDER_ALWAYS : + default : + last_cb_value = angle ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + break ; + } + } +} + + diff --git a/src/pui/puDialogBox.cxx b/src/pui/puDialogBox.cxx new file mode 100644 index 0000000..a8b3cbf --- /dev/null +++ b/src/pui/puDialogBox.cxx @@ -0,0 +1,28 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puDialogBox.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF1(puDialogBox,puPopup) + diff --git a/src/pui/puFLTK.h b/src/pui/puFLTK.h new file mode 100644 index 0000000..e684864 --- /dev/null +++ b/src/pui/puFLTK.h @@ -0,0 +1,68 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puFLTK.h 1857 2004-02-16 13:49:03Z stromberg $ +*/ + +#ifndef _PU_FLTK_H_ +#define _PU_FLTK_H_ + +#ifndef PU_USE_FLTK +# define PU_USE_FLTK +#endif + +#include "pu.h" +#include + + +inline int puGetWindowFLTK () +{ + return (int) Fl_Window::current () ; +} + +inline void puSetWindowFLTK ( int window ) +{ + ((Fl_Gl_Window *) window) -> make_current () ; +} + +inline void puGetWindowSizeFLTK ( int *width, int *height ) +{ + Fl_Window * window = Fl_Window::current () ; + *width = window->w() ; + *height = window->h() ; +} + +inline void puSetWindowSizeFLTK ( int width, int height ) +{ + Fl_Window * window = Fl_Window::current () ; + window -> resize ( window->x(), window->y(), width, height ) ; +} + +inline void puInitFLTK () +{ + puSetWindowFuncs ( puGetWindowFLTK, + puSetWindowFLTK, + puGetWindowSizeFLTK, + puSetWindowSizeFLTK ) ; + puRealInit () ; +} + + +#endif diff --git a/src/pui/puFont.cxx b/src/pui/puFont.cxx new file mode 100644 index 0000000..f10799c --- /dev/null +++ b/src/pui/puFont.cxx @@ -0,0 +1,135 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puFont.cxx 1943 2004-08-05 01:05:48Z puggles $ +*/ + + +#include "puLocal.h" + + +puFont PUFONT_8_BY_13 ( fntGetBitmapFont( FNT_BITMAP_8_BY_13 ) ) ; +puFont PUFONT_9_BY_15 ( fntGetBitmapFont( FNT_BITMAP_9_BY_15 ) ) ; +puFont PUFONT_TIMES_ROMAN_10 ( fntGetBitmapFont( FNT_BITMAP_TIMES_ROMAN_10 ) ) ; +puFont PUFONT_TIMES_ROMAN_24 ( fntGetBitmapFont( FNT_BITMAP_TIMES_ROMAN_24 ) ) ; +puFont PUFONT_HELVETICA_10 ( fntGetBitmapFont( FNT_BITMAP_HELVETICA_10 ) ) ; +puFont PUFONT_HELVETICA_12 ( fntGetBitmapFont( FNT_BITMAP_HELVETICA_12 ) ) ; +puFont PUFONT_HELVETICA_18 ( fntGetBitmapFont( FNT_BITMAP_HELVETICA_18 ) ) ; + + +puFont::puFont () +{ + fnt_font_handle = fntGetBitmapFont( FNT_BITMAP_8_BY_13 ); + pointsize = 13 ; + slant = 0 ; +} + + +float puFont::getFloatStringWidth ( const char *str ) const +{ + if ( str == NULL ) + return 0.0f ; + + if ( fnt_font_handle != NULL ) + { + float r, l ; + fnt_font_handle -> getBBox ( str, pointsize, slant, &l, &r, NULL, NULL ) ; + return ( r - l ) ; + } + + return 0.0f ; +} + + +static int count_lines ( const char *str ) +{ + int k = 0 ; + + if ( str != NULL ) + { + for ( k = 1 ; *str != '\0' ; str++ ) + if ( *str == '\n' ) + k++ ; + } + + return k ; +} + + +int puFont::getStringHeight ( const char *s ) const +{ + if (!s || !fnt_font_handle) return 0 ; + + // The height of a single line is the ascender plus descender, not + // including whitespace above and below. Each additional line + // adds one point size, of course. Remember to round up to avoid + // overlapping artifacts. The bbox string is just a sample of + // "likely to be tall" glyphs. + float ascend; + fnt_font_handle -> getBBox ( "$lfKL", pointsize, slant, NULL, NULL, NULL, &ascend ) ; + float height = ascend + getStringDescender() ; + int lines = count_lines ( s ) ; + if ( lines > 1 ) + height += ( lines - 1 ) * pointsize ; + + return int ( height + 0.999 ) ; + // return int ( pointsize * count_lines ( s ) + 0.999 ) - getStringDescender(); +} + + +int puFont::getStringDescender ( void ) const +{ + if ( fnt_font_handle != NULL ) + { + float b ; + fnt_font_handle -> getBBox ( "y", pointsize, slant, NULL, NULL, &b, NULL ) ; + return (int) -b ; + } + + return 0 ; +} + + +void puFont::drawString ( const char *str, int x, int y ) +{ + if ( str == NULL ) + return ; + + if ( fnt_font_handle != NULL ) + { + sgVec3 curpos ; + sgSetVec3 ( curpos, (float)x, (float)y, 0.0f ) ; + + glPushAttrib( GL_COLOR_BUFFER_BIT ); // NHV + glEnable ( GL_ALPHA_TEST ) ; + glEnable ( GL_BLEND ) ; + glAlphaFunc ( GL_GREATER, 0.1f ) ; + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; + + fnt_font_handle -> begin () ; + fnt_font_handle -> puts ( curpos, pointsize, slant, str ) ; + fnt_font_handle -> end () ; + + glPopAttrib () ; + glDisable ( GL_TEXTURE_2D ) ; + return ; + } +} + diff --git a/src/pui/puFrame.cxx b/src/pui/puFrame.cxx new file mode 100644 index 0000000..8e17019 --- /dev/null +++ b/src/pui/puFrame.cxx @@ -0,0 +1,44 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puFrame.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF1(puFrame,puObject) + + +void puFrame::draw ( int dx, int dy ) +{ + if ( !visible || ( window != puGetWindow () ) ) return ; + + abox.draw ( dx, dy, style, colour, FALSE, border_thickness ) ; + + if ( r_cb ) + r_cb ( this, dx, dy, render_data ) ; + else + draw_legend ( dx, dy ) ; + + draw_label ( dx, dy ) ; +} + + diff --git a/src/pui/puGLUT.h b/src/pui/puGLUT.h new file mode 100644 index 0000000..bd564a0 --- /dev/null +++ b/src/pui/puGLUT.h @@ -0,0 +1,75 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puGLUT.h 2122 2007-09-15 12:34:36Z fayjf $ +*/ + +#ifndef _PU_GLUT_H_ +#define _PU_GLUT_H_ + +#ifndef PU_USE_GLUT +# define PU_USE_GLUT +#endif + +#include "pu.h" + +#ifdef UL_MAC_OSX +# include +#else +# ifdef FREEGLUT_IS_PRESENT /* for FreeGLUT like PLIB 1.6.1*/ +# include +# else +# include +# endif +#endif + + +inline int puGetWindowGLUT() +{ + return glutGetWindow () ; +} + +inline void puSetWindowGLUT ( int window ) +{ + glutSetWindow ( window ) ; +} + +inline void puGetWindowSizeGLUT ( int *width, int *height ) +{ + *width = glutGet ( (GLenum) GLUT_WINDOW_WIDTH ) ; + *height = glutGet ( (GLenum) GLUT_WINDOW_HEIGHT ) ; +} + +inline void puSetWindowSizeGLUT ( int width, int height ) +{ + glutReshapeWindow ( width, height ) ; +} + +inline void puInitGLUT () +{ + puSetWindowFuncs ( puGetWindowGLUT, + puSetWindowGLUT, + puGetWindowSizeGLUT, + puSetWindowSizeGLUT ) ; + puRealInit () ; +} + + +#endif diff --git a/src/pui/puGroup.cxx b/src/pui/puGroup.cxx new file mode 100644 index 0000000..e5d35b0 --- /dev/null +++ b/src/pui/puGroup.cxx @@ -0,0 +1,476 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puGroup.cxx 2076 2006-04-13 16:20:23Z bram $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF1(puGroup,puObject) + + +#define PUSTACK_MAX 100 + + /* + This is a stack of groups that are currently being filled with other widgets. + A group is pushed onto the stack when it is created and it is popped off the + stack when its "close" function is called. + */ + +static int currGroup = -1 ; +static puGroup *groupStack [ PUSTACK_MAX ] ; + +void puPushGroup ( puGroup *in ) +{ + if ( currGroup < PUSTACK_MAX ) + groupStack [ ++currGroup ] = in ; + else + ulSetError ( UL_WARNING, "PUI: Too many puGroups open at once!" ) ; +} + + +void puPopGroup ( void ) +{ + if ( currGroup > 0 ) + --currGroup ; + else + ulSetError ( UL_WARNING, "PUI: puGroup stack is empty!" ) ; +} + +int puNoGroup ( void ) +{ + return currGroup < 0 ; +} + + +puGroup *puGetCurrGroup ( void ) +{ + if ( currGroup < 0 ) + { + ulSetError ( UL_WARNING, "PUI: No Group!" ) ; + return NULL ; + } + + return groupStack [ currGroup ] ; +} + +void puGroup::remove ( puObject *obj ) +{ + if ( obj -> getParent () != this ) + return ; + + /* Are we the first object in the list */ + + if ( obj -> getPrevObject() == NULL ) + dlist = obj -> getNextObject() ; + else + obj -> getPrevObject() -> setNextObject( obj -> getNextObject() ) ; + + /* Are we the last object in the list */ + + if ( obj -> getNextObject() != NULL ) + obj -> getNextObject() -> setPrevObject( obj -> getPrevObject() ) ; + + obj -> setNextObject ( NULL ) ; + obj -> setPrevObject ( NULL ) ; + obj -> setParent ( NULL ) ; + + num_children-- ; + recalc_bbox () ; +} + +void puGroup::empty ( void ) +{ + puObject *obj = getLastChild () ; + while ( obj != NULL ) + { + if ( obj->getType () & PUCLASS_GROUP ) + { + puGroup *group = (puGroup *)obj ; + group->empty () ; + } + + puObject *temp = obj->getPrevObject () ; + delete obj ; + obj = temp ; + } + + dlist = NULL ; +} + +void puGroup::add ( puObject *new_obj ) +{ + if ( new_obj -> getParent () != NULL ) + new_obj -> getParent () -> remove ( new_obj ) ; + + new_obj -> setParent ( this ) ; + + if ( dlist == NULL ) + { + dlist = new_obj ; + new_obj -> setNextObject ( NULL ) ; + new_obj -> setPrevObject ( NULL ) ; + } + else + { + puObject *last ; + + for ( last = dlist ; + last -> getNextObject() != NULL ; + last = last -> getNextObject() ) + /* Search for end of list. */ ; + + last -> setNextObject ( new_obj ) ; + new_obj -> setPrevObject ( last ) ; + new_obj -> setNextObject ( NULL ) ; + } + + num_children++ ; + recalc_bbox () ; +} + +int puGroup::checkKey ( int key, int updown ) +{ + if ( updown == PU_UP || 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. + */ + + bo = getLastChild () ; + + for ( ; bo != NULL ; bo = bo -> getPrevObject() ) + if ( bo -> checkKey ( key, updown ) ) + return TRUE ; + + return FALSE ; +} + +int puGroup::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. + */ + + if ( !mouse_active ) + { + bo = getLastChild () ; + + for ( ; bo != NULL ; bo = bo -> getPrevObject() ) + { + /* If this is a menu bar and the mouse is over the button, highlight the button, if it's in the right window - JCJ 6 Jun 2002 */ + if ( ( getType () & PUCLASS_MENUBAR ) && ( bo->getType () & PUCLASS_ONESHOT ) && ( window == puGetWindow () ) ) + /* + Changing this statement to something like this: + if ( bo->getType () & PUCLASS_ONESHOT ) + Breaks a lot of stuff... like pressing buttons actually working in filepicker. Need + to just define everything that can be pressed passively above, and things should + be fröhlich. + */ + { + puBox *box = bo->getABox () ; + if ( ( x >= box->min[0] ) && ( x <= box->max[0] ) && + ( y >= box->min[1] ) && ( y <= box->max[1] ) ) + bo->highlight () ; + else + bo->lowlight () ; + } + + if ( bo -> checkHit ( button, updown, x, y ) ) + return TRUE ; + } + } + + /* + If right mouse button is pressed, save mouse coordinates for + dragging and dropping. Do this only if the "floating" flag is set. + */ + + if ( mouse_active || ( isHit ( x+abox.min[0], y+abox.min[1]) && + floating && ( button == PU_RIGHT_BUTTON ) ) ) // DEPRECATED! -- we need to replace this code. + { + puMoveToLast ( this ); + + /* + Return (x, y) to coordinates of parent interface to avoid "jumping" of + present interface as mouse drags + */ + + x += abox.min[0] ; + y += abox.min[1] ; + + if ( updown == PU_DOWN ) + { + mouse_x = x; /* Save mouse coordinates for dragging */ + mouse_y = y; + + mouse_active = TRUE ; + + return TRUE ; + } + else if ( updown == PU_DRAG ) + { + int curr_x, curr_y; + + getPosition ( &curr_x, &curr_y ); + setPosition ( curr_x+x-mouse_x, curr_y+y-mouse_y ); /* Move to new position */ + + mouse_x = x; /* Save new coordinates */ + mouse_y = y; + + return TRUE ; + } + else if ( updown == PU_UP ) + { + mouse_active = FALSE ; + + return TRUE ; + } + } + + return FALSE ; +} + + +void puGroup::draw ( int dx, int dy ) +{ + if ( ! isVisible () ) + return ; + + for ( puObject *bo = dlist ; bo != NULL ; bo = bo -> getNextObject() ) + { + /* June 16th, 98, Shammi : + * The next if statement checks if the object is + * a menu bar and makes sure it is repositioned + * correctly. + */ + + int x, y ; + int xdraw = dx + abox.min[0] ; + int ydraw = dy + abox.min[1] ; + bo -> getPosition (&x, &y) ; + + /* If the object is a menubar or a vertmenu and supposed to be locked to the top, */ + /* then move it there. - JCJ 6 June 2002 */ + if ( ( bo -> getType () & PUCLASS_MENUBAR ) && + ( bo -> getWindow () == puGetWindow () ) ) + { + int obWidth, obHeight ; + bo -> getSize ( &obWidth, &obHeight ) ; + bo -> setPosition ( 0, puGetWindowHeight() - obHeight ) ; + } + else + { + if ( ( y < 0 ) && ( bo->getType () & PUCLASS_POPUPMENU ) ) + { + /* IF the object's bottom left corner lies outside the window, THEN */ + /* move the object to the top left - JCJ and Fay 5 Jun 2002 */ + int absx, absy ; + bo -> getAbsolutePosition (&absx, &absy) ; + if ( absy < 0 ) + ydraw -= absy ; + } + } + + bo -> draw ( xdraw, ydraw ) ; + } + + if ( getWindow () == puGetWindow () ) draw_label ( dx, dy ) ; +} + + +void puGroup::recalc_bbox ( void ) +{ + puBox contents ; + contents . empty () ; + + for ( puObject *bo = dlist ; + bo != NULL ; + bo = bo -> getNextObject() ) + 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 puGroup::doHit ( int, int, int, int ) +{ +} + + +puGroup::~puGroup () +{ + void puCleanUpJunk ( void ) ; + + puObject *bo = getLastChild () ; + + while ( bo != NULL ) + { + dlist = bo ; + bo = bo -> getPrevObject() ; + puDeleteObject ( dlist ) ; + } + + // Since this is an object destructor, it should be okay to delete the child objects as well. + puCleanUpJunk () ; +} + + +void puGroup::setChildStyle ( int childs, int which, int recursive ) +{ + puObject *curr_obj ; + + for ( curr_obj = getFirstChild () ; + curr_obj != NULL ; + curr_obj = curr_obj->getNextObject () ) + { + if ( ( recursive == TRUE ) && ( curr_obj->getType () & PUCLASS_GROUP ) ) + ((puGroup*)curr_obj)->setChildStyle ( childs, style, TRUE ) ; + else + { + if ( curr_obj->getType () & childs ) + curr_obj->setStyle ( style ) ; + } + } +} + +void puGroup::setChildBorderThickness ( int childs, int t, int recursive ) +{ + puObject *curr_obj ; + + for ( curr_obj = getFirstChild () ; + curr_obj != NULL ; + curr_obj = curr_obj->getNextObject () ) + { + if ( ( recursive == TRUE ) && ( curr_obj->getType () & PUCLASS_GROUP ) ) + ((puGroup*)curr_obj)->setChildBorderThickness ( childs, t, TRUE ) ; + else + { + if ( curr_obj->getType () & childs ) + curr_obj->setBorderThickness ( t ) ; + } + } +} + +void puGroup::setChildColour ( int childs, int which, float r, float g, float b, float a, int recursive ) +{ + puObject *curr_obj ; + + for ( curr_obj = getFirstChild () ; + curr_obj != NULL ; + curr_obj = curr_obj->getNextObject () ) + { + if ( ( recursive == TRUE ) && ( curr_obj->getType () & PUCLASS_GROUP ) ) + ((puGroup*)curr_obj)->setChildColour ( childs, which, r, g, b, a, TRUE ) ; + else + { + if ( curr_obj->getType () & childs ) + curr_obj->setColour ( which, r, g, b, a ) ; + } + } +} + +void puGroup::setChildColourScheme ( int childs, float r, float g, float b, float a, int recursive ) +{ + puObject *curr_obj ; + + for ( curr_obj = getFirstChild () ; + curr_obj != NULL ; + curr_obj = curr_obj->getNextObject () ) + { + if ( ( recursive == TRUE ) && ( curr_obj->getType () & PUCLASS_GROUP ) ) + ((puGroup*)curr_obj)->setChildColourScheme ( childs, r, g, b, a, TRUE ) ; + else + { + if ( curr_obj->getType () & childs ) + curr_obj->setColourScheme ( r, g, b, a ) ; + } + } +} + +void puGroup::setChildLegendFont ( int childs, puFont f, int recursive ) +{ + puObject *curr_obj ; + + for ( curr_obj = getFirstChild () ; + curr_obj != NULL ; + curr_obj = curr_obj->getNextObject () ) + { + if ( ( recursive == TRUE ) && ( curr_obj->getType () & PUCLASS_GROUP ) ) + ((puGroup*)curr_obj)->setChildLegendFont ( childs, f, TRUE ) ; + else + { + if ( curr_obj->getType () & childs ) + curr_obj->setLegendFont ( f ) ; + } + } +} + +void puGroup::setChildLabelFont ( int childs, puFont f, int recursive ) +{ + puObject *curr_obj ; + + for ( curr_obj = getFirstChild () ; + curr_obj != NULL ; + curr_obj = curr_obj->getNextObject () ) + { + if ( ( recursive == TRUE ) && ( curr_obj->getType () & PUCLASS_GROUP ) ) + ((puGroup*)curr_obj)->setChildLabelFont ( childs, f, TRUE ) ; + else + { + if ( curr_obj->getType () & childs ) + curr_obj->setLabelFont ( f ) ; + } + } +} + diff --git a/src/pui/puInput.cxx b/src/pui/puInput.cxx new file mode 100644 index 0000000..b80fb2a --- /dev/null +++ b/src/pui/puInput.cxx @@ -0,0 +1,423 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puInput.cxx 2154 2009-02-09 14:55:47Z fayjf $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF2(puInput,puInputBase,puObject) + + +static char *chop_to_width ( puFont fnt, const char *s, int width, int cursor_position, int *display_starting_point ) +{ + int new_len = strlen ( s ) ; + char *res = new char [ new_len + 1 ] ; + int n = 0 ; + int w ; + + if ( new_len == 0 ) + { + *res = '\0' ; + if ( display_starting_point != NULL ) *display_starting_point = 0 ; + } + else + { + do + { + memcpy ( res, s + n, new_len + 1 ) ; + n++ ; + new_len -- ; + w = fnt.getStringWidth ( res ) + 2 * PUSTR_RGAP + PUSTR_LGAP ; + } while ( ( w >= width ) && ( n < cursor_position - 1 ) ) ; + + if ( display_starting_point != NULL ) *display_starting_point = n - 1 ; + + n = 0 ; + + while ( w >= width ) + { + res[new_len] = '\0' ; + n++ ; + new_len -- ; + w = fnt.getStringWidth ( res ) + 2 * PUSTR_RGAP + PUSTR_LGAP ; + } + } + + return res ; +} + +void puInput::draw ( int dx, int dy ) +{ + normalizeCursors () ; + + if ( !visible || ( window != puGetWindow () ) ) 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, border_thickness ) ; + + if ( r_cb ) + r_cb ( this, dx, dy, render_data ) ; + else + { + int xx = legendFont.getStringWidth ( " " ) ; + int yy = ( ( abox.max[1] - abox.min[1] - legendFont.getStringHeight () ) / 2 + + legendFont.getStringDescender () ) ; + + if ( !displayed_text ) + displayed_text = chop_to_width ( legendFont, getStringValue(), abox.max[0]-abox.min[0], getCursor (), &display_starting_point ) ; + + if ( accepting ) + { + /* Highlight the select area */ + + if ( select_end_position > 0 && + select_end_position != select_start_position ) + { + int sep = select_end_position - display_starting_point ; + int ssp = select_start_position - display_starting_point ; + + if ( sep < 0 ) sep = 0 ; + if ( ssp < 0 ) ssp = 0 ; + + if ( ssp < sep ) + { + char save_char = displayed_text [ sep ] ; + displayed_text [ sep ] = '\0' ; + int cpos2 = legendFont.getStringWidth ( displayed_text ) + + xx + dx + abox.min[0] ; + displayed_text [ sep ] = save_char ; + save_char = displayed_text [ ssp ] ; + displayed_text [ ssp ] = '\0' ; + int cpos1 = legendFont.getStringWidth ( displayed_text ) + + xx + dx + abox.min[0] ; + displayed_text [ ssp ] = save_char ; + + glColor3f ( 1.0f, 1.0f, 0.7f ) ; + glRecti ( cpos1, dy + abox.min[1] + 2 , + cpos2, dy + abox.max[1] - 2 ) ; + } + } + } + + /* Draw the text */ + + /* If greyed out then halve the opacity when drawing the text */ + + 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 transp */ + + legendFont.drawString ( displayed_text, + dx + abox.min[0] + xx, + dy + abox.min[1] + yy ) ; + + + if ( accepting ) + { + /* Draw the 'I' bar cursor. */ + + if ( cursor_position - display_starting_point >= 0 ) + { + char save_char = displayed_text [ cursor_position-display_starting_point ] ; + displayed_text [ cursor_position-display_starting_point ] = '\0' ; + + float cpos = 0.5f + legendFont.getStringWidth ( displayed_text ) + xx + dx + abox.min[0] ; + displayed_text [ cursor_position-display_starting_point ] = save_char ; + + float top = 0.5f + dy + abox.min[1] + yy + legendFont.getPointSize () ; + float bot = 0.5f + dy + abox.min[1] + yy - legendFont.getStringDescender() ; + + glColor4fv ( colour [ PUCOL_MISC ] ) ; + glBegin ( GL_LINES ) ; + glVertex2f ( cpos , bot ) ; + glVertex2f ( cpos , top ) ; + glVertex2f ( cpos - 1, bot ) ; + glVertex2f ( cpos - 1, top ) ; + glVertex2f ( cpos - 3, bot ) ; + glVertex2f ( cpos + 3, bot ) ; + glVertex2f ( cpos - 3, top ) ; + glVertex2f ( cpos + 3, top ) ; + glEnd () ; + } + } + } + + draw_label ( dx, dy ) ; +} + + +void puInput::doHit ( int button, int updown, int x, int y ) +{ + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + /* Active widget exists and is not this one; call its down callback if it exists */ + + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + if ( updown != PU_DRAG ) + puMoveToLast ( this ); + + if ( button == active_mouse_button ) + { + /* Most GUI's activate a button on button-UP not button-DOWN. */ + + /* Find the position of the mouse on the line of text */ + + if ( !displayed_text ) + displayed_text = chop_to_width ( legendFont, getStringValue(), + abox.max[0]-abox.min[0], getCursor (), &display_starting_point ) ; + int i = strlen ( displayed_text ) ; + + int length, prev_length ; + length = legendFont.getStringWidth ( displayed_text ) + abox.min[0] ; + prev_length = length ; + + while ( ( x <= prev_length ) && ( i > 0 ) ) + { + prev_length = length ; + displayed_text[--i] = '\0' ; + length = legendFont.getStringWidth ( displayed_text ) + abox.min[0] ; + } + + if ( ( x - length ) > ( prev_length - x ) ) + i++ ; /* Mouse is closer to next character than previous character */ + + i += display_starting_point ; + + /* Process the mouse click. */ + + if ( updown == active_mouse_edge || active_mouse_edge == PU_UP_AND_DOWN ) + { + lowlight () ; + + accepting = TRUE ; + cursor_position = i ; + normalizeCursors () ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + } + else if ( updown == PU_DOWN ) + { + /* + * We get here if the active edge is not down but the mouse button has + * been pressed. Start a selection if this isn't the initial activation + * of the widget. + */ + + if ( this == puActiveWidget() ) + { + select_start_position = i ; + select_end_position = i ; + } + } + else if ( updown == PU_DRAG ) + { + + if ( (select_end_position - i) > (i - select_start_position) ) + select_start_position = i ; /* Cursor closer to start than to end */ + else + select_end_position = i ; /* Cursor closer to end than to start */ + + if (select_start_position > select_end_position) + { + i = select_end_position ; + select_end_position = select_start_position ; + select_start_position = i ; + } + } + else + highlight () ; + + /* Required because we have pretty much destroyed "displayed_text" */ + delete [] displayed_text ; + displayed_text = chop_to_width ( legendFont, getStringValue(), + abox.max[0]-abox.min[0], getCursor (), &display_starting_point ) ; + } + else + lowlight () ; +} + + +int puInput::checkKey ( int key, int updown ) +{ + if ( updown == PU_UP || ! isAcceptingInput() || ! isActive () || ! isVisible () || ( window != puGetWindow () ) ) + return FALSE ; + + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + /* Active widget exists and is not this one; call its down callback if it exists */ + + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + normalizeCursors () ; + + char *p = NULL ; + + int char_used = TRUE ; + + 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 () ; + normalizeCursors () ; + invokeCallback () ; + puDeactivateWidget () ; + break ; + + case PU_KEY_HOME : cursor_position = 0 ; break ; + case PU_KEY_END : + cursor_position = strlen ( getStringValue () ) ; + break ; + case PU_KEY_LEFT : cursor_position-- ; break ; + case PU_KEY_RIGHT : cursor_position++ ; break ; + default : char_used = FALSE ; + } + + if ( ! input_disabled && ! char_used ) + { + switch ( key ) + { + case '\b' : /* Backspace */ + if ( select_start_position != select_end_position ) + removeSelectRegion () ; + else if ( cursor_position > 0 ) + { + p = new char [ strlen ( getStringValue () ) ] ; + strncpy ( p, getStringValue (), cursor_position - 1 ) ; + strcpy ( p + cursor_position - 1, + getStringValue () + cursor_position ) ; + cursor_position-- ; + } + + break ; + + case 0x7F : /* DEL */ + if ( select_start_position != select_end_position ) + removeSelectRegion () ; + else if ( cursor_position != (int)strlen ( getStringValue() ) ) + { + p = new char [ strlen ( getStringValue () ) ] ; + strncpy ( p, getStringValue (), cursor_position ) ; + strcpy ( p + cursor_position, + getStringValue () + cursor_position + 1 ) ; + } + + break ; + + case 0x15 /* ^U */ : setValue ( "\0" ) ; break ; + case 0x03 /* ^C */ : + case 0x18 /* ^X */ : /* Cut or copy selected text */ + if ( select_start_position != select_end_position ) + { + p = getStringValue () ; + char ch = p[select_end_position] ; + p[select_end_position] = '\0' ; + puSetPasteBuffer ( p + select_start_position ) ; + p[select_end_position] = ch ; + + if ( key == 0x18 ) /* Cut, remove text from string */ + removeSelectRegion () ; + + /* + So we don't set the widget to its value at the end of the + function + */ + + p = NULL ; + } + + break ; + + case 0x16 /* ^V */ : /* Paste buffer into text */ + { + if ( ! puGetPasteBuffer () ) + break ; + + if ( select_start_position != select_end_position ) + removeSelectRegion () ; + + int str_val_len = strlen ( getStringValue () ) ; + int paste_len = strlen ( puGetPasteBuffer () ) ; + p = new char [ str_val_len + paste_len + 1 ] ; + memcpy ( p, getStringValue (), cursor_position ) ; + memcpy ( p + cursor_position, puGetPasteBuffer (), paste_len ) ; + memcpy ( p + cursor_position + paste_len, getStringValue () + cursor_position, str_val_len - cursor_position + 1 ) ; + cursor_position += paste_len ; + } + + break ; + + default: + if ( key < ' ' || key > 127 ) return FALSE ; + if ( valid_data ) + { + if ( !strchr ( valid_data, key ) ) return TRUE ; + } + + if ( select_start_position != select_end_position ) // remove selected text + removeSelectRegion () ; + + p = new char [ strlen ( getStringValue () ) + 2 ] ; + strncpy ( p, getStringValue (), cursor_position ) ; + p[cursor_position] = key ; + strcpy ( p + cursor_position + 1, + getStringValue () + cursor_position ) ; + + cursor_position++ ; + break ; + } + + if ( p != NULL ) + setValue ( p ) ; /* Set the widget value to the new string */ + + delete [] p ; + } + + /* Since the keystroke has changed the text value, we need to change the displayed text as well. */ + delete [] displayed_text ; + displayed_text = NULL ; + + normalizeCursors () ; + return TRUE ; +} + + diff --git a/src/pui/puInputBase.cxx b/src/pui/puInputBase.cxx new file mode 100644 index 0000000..732d00d --- /dev/null +++ b/src/pui/puInputBase.cxx @@ -0,0 +1,88 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puInputBase.cxx 1709 2002-09-27 23:57:33Z ude $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF(puInputBase) + +void puInputBase::normalizeCursors ( void ) +{ + int sl = strlen ( widget -> getStringValue () ) ; + + /* Clamp the positions to the limits of the text. */ + + if ( cursor_position < 0 ) cursor_position = 0 ; + if ( select_start_position < 0 ) select_start_position = 0 ; + if ( select_end_position < 0 ) select_end_position = 0 ; + if ( cursor_position > 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 puInputBase::removeSelectRegion ( void ) +{ + char *text = widget -> getStringValue () ; + int text_len = strlen ( text ) ; + char *p = new char [ text_len + 1 - + ( select_end_position - select_start_position ) ] ; + + memcpy ( p, text, select_start_position ) ; + memcpy ( p + select_start_position, + text + select_end_position, + text_len - select_end_position + 1 ) ; + + widget -> setValue ( p ) ; + delete [] p ; + + cursor_position = select_end_position = select_start_position ; +} + + +void puInputBase::addValidData ( const char *data ) +{ + int valid_len = valid_data != NULL ? strlen ( valid_data ) : 0 ; + int data_len = data != NULL ? strlen ( data ) : 0 ; + int new_data_len = valid_len + data_len ; + + char *new_data = new char [ new_data_len + 1 ] ; + + if ( valid_len != 0 ) + memcpy ( new_data, valid_data, valid_len ) ; + if ( data_len != 0 ) + memcpy ( new_data + valid_len, data, data_len ) ; + + new_data [ new_data_len ] = '\0' ; + delete [] valid_data ; + valid_data = new_data ; +} + diff --git a/src/pui/puInterface.cxx b/src/pui/puInterface.cxx new file mode 100644 index 0000000..a666939 --- /dev/null +++ b/src/pui/puInterface.cxx @@ -0,0 +1,127 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puInterface.cxx 1834 2003-12-16 23:16:04Z puggles $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF1(puInterface,puGroup) + + +#define PUSTACK_MAX 100 + +static int currLiveInterface = -1 ; +static puInterface *liveInterfaceStack [ PUSTACK_MAX ] ; + +void puPushLiveInterface ( puInterface *in ) +{ + if ( currLiveInterface < PUSTACK_MAX - 1 ) + liveInterfaceStack [ ++currLiveInterface ] = in ; + else + ulSetError ( UL_WARNING, "PUI: Too many live puInterfaces open at once!\n" ) ; +} + +void puPopLiveInterface ( puInterface *in ) +{ + if ( currLiveInterface < 0 ) + { + ulSetError ( UL_WARNING, "PUI: Live puInterface stack is empty!\n" ) ; + return; + } + + if ( in == NULL ) + --currLiveInterface ; + else + { + for ( int i = currLiveInterface ; i >= 0 ; i-- ) + { + if ( in == liveInterfaceStack [ i ] ) + { + /* Handle interfaces that are buried in the stack */ + while ( i < currLiveInterface ) + { + liveInterfaceStack [ i ] = liveInterfaceStack [ i+1 ] ; + i++ ; + } + + --currLiveInterface ; + + break ; + } + } + } +} + +int puNoLiveInterface ( void ) +{ + return currLiveInterface < 0 ; +} + +puInterface *puGetUltimateLiveInterface ( void ) +{ + if ( currLiveInterface < 0 ) + ulSetError ( UL_FATAL, "PUI: No Live Interface! Forgot to call puInit ?\n" ) ; + + return liveInterfaceStack [ 0 ] ; +} + + +puInterface *puGetBaseLiveInterface ( void ) +{ + if ( currLiveInterface < 0 ) + ulSetError ( UL_FATAL, "PUI: No Live Interface! Forgot to call puInit ?\n" ) ; + + /* + 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::~puInterface () +{ + void puCleanUpJunk ( void ) ; + + puObject *bo = getLastChild () ; + + while ( bo != NULL ) + { + dlist = bo ; + bo = bo -> getPrevObject() ; + puDeleteObject ( dlist ) ; + } + + // Since this is an object destructor, it should be okay to delete the child objects as well. + puCleanUpJunk () ; + + dlist = NULL ; + + puPopLiveInterface ( this ) ; +} + diff --git a/src/pui/puListBox.cxx b/src/pui/puListBox.cxx new file mode 100644 index 0000000..60abbca --- /dev/null +++ b/src/pui/puListBox.cxx @@ -0,0 +1,201 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puListBox.cxx 2088 2006-10-16 08:11:16Z bram $ +*/ + +/**** +* NAME +* puListBox +* +* DESCRIPTION +* list of strings +* +* AUTHOR +* Dave McClurg +* +* CREATION DATE +* August 2000 +* +* MODIFICATION HISTORY +* John Fay - many improvements +****/ + +#include "puLocal.h" + +UL_RTTI_DEF1(puListBox,puButton) + + +puListBox::puListBox ( int minx, int miny, int maxx, int maxy, char** _list ) : + puButton ( minx, miny, maxx, maxy ) +{ + type |= PUCLASS_LISTBOX ; + + newList ( _list ) ; +} + + +void puListBox::newList ( char ** _list ) +{ + list = _list ; + + if ( list == NULL ) + num = 0 ; + else + for ( num = 0 ; list [ num ] != NULL ; num++ ) + /* Count number of items */ ; + + top = 0 ; + + /* Set index of selected item */ + setValue ( -1 ) ; + + puPostRefresh () ; +} + + +void puListBox::setTopItem( int item_index ) +{ + top = item_index ; + int visible = getNumVisible(); + if ( top < 0 || num <= visible ) + top = 0 ; + else if ( num > 0 && top > num-visible ) + top = num-visible; + + puPostRefresh () ; +} + + +void puListBox::draw ( int dx, int dy ) +{ + if ( !visible || ( window != puGetWindow () ) || list == NULL ) return ; + + abox.draw ( dx, dy, style, colour, isReturnDefault(), border_thickness ) ; + + /* If greyed out then halve the opacity when drawing the text */ + + 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 xsize = abox.max[0] - abox.min[0] + 1 ; + + if ( r_cb ) + r_cb ( this, dx, dy, render_data ) ; + else + { + int yinc = legendFont.getStringHeight () + PUSTR_BGAP ; + int num_vis = getNumVisible () ; + + int selected ; + getValue ( &selected ) ; + + for ( int i = top ; i < num && i < top + num_vis ; i++ ) + { + if ( i == selected ) + glColor4f ( (colour [ PUCOL_BACKGROUND ][0] + colour [ PUCOL_LABEL ][0]) / 2.0f, + (colour [ PUCOL_BACKGROUND ][1] + colour [ PUCOL_LABEL ][1]) / 2.0f, + (colour [ PUCOL_BACKGROUND ][2] + colour [ PUCOL_LABEL ][2]) / 2.0f, + (colour [ PUCOL_BACKGROUND ][3] + colour [ PUCOL_LABEL ][3]) / 2.0f ); + else + glColor4f ( colour [ PUCOL_LABEL ][0], + colour [ PUCOL_LABEL ][1], + colour [ PUCOL_LABEL ][2], + colour [ PUCOL_LABEL ][3] ) ; + + int x = PUSTR_LGAP ; + int y = yinc * ((i-top)+1) ; + + int xx = dx + abox.min[0] + x ; + int yy = dy + abox.max[1] - y ; + + int width ; + char str [ PUSTRING_MAX ] ; + strcpy ( str, list [ i ] ) ; + + /* + Does the string fit into the box? + + If not, chop it down one character at a time until + it does fit. + */ + + while ( 1 ) + { + width = legendFont.getStringWidth ( (char *)str ) + PUSTR_LGAP ; + + if ( width < xsize ) + break ; + + /* + Nibble off one character and try again + (Do that sneakily by replacing the last 4 characters with 3 dots) + */ + + strcpy ( & str [ strlen(str) - 4 ], "..." ) ; + } + + legendFont.drawString ( (char*)str, xx, yy ) ; + } + } + + draw_label ( dx, dy ) ; +} + + +void puListBox::doHit ( int button, int updown, int x, int y ) +{ + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + if ( button == active_mouse_button ) + { + if ( ( updown == active_mouse_edge ) || ( active_mouse_edge == PU_UP_AND_DOWN ) ) + { + lowlight () ; + + int yinc = legendFont.getStringHeight () + PUSTR_BGAP ; + int idx = top + ( abox.max[1] - PUSTR_BGAP - y ) / yinc; + if ( idx < 0 ) + idx = 0; + else if ( idx >= num ) + idx = num-1; + + setValue ( idx ) ; + + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + } + else + highlight () ; + } + else + lowlight () ; +} + + diff --git a/src/pui/puLocal.h b/src/pui/puLocal.h new file mode 100644 index 0000000..9ffdfcb --- /dev/null +++ b/src/pui/puLocal.h @@ -0,0 +1,31 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puLocal.h 1902 2004-03-21 19:03:23Z sjbaker $ +*/ + + +#define PU_USE_NONE 1 +#include "pu.h" + + +void puSetPasteBuffer ( const char *ch ) ; +char *puGetPasteBuffer () ; + diff --git a/src/pui/puMenuBar.cxx b/src/pui/puMenuBar.cxx new file mode 100644 index 0000000..8aefd54 --- /dev/null +++ b/src/pui/puMenuBar.cxx @@ -0,0 +1,179 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puMenuBar.cxx 2021 2005-05-06 18:31:27Z fayjf $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF1(puMenuBar,puInterface) + + +void puMenuBar_drop_down_the_menu ( puObject *b ) +{ + // Inputs: b = pointer to the button on the menu which has been pushed + // p = pointer to the popup menu which is b's submenu + + puPopupMenu *p = (puPopupMenu *) b -> getUserData () ; + + if ( b -> getIntegerValue () ) + { +/* + SJBL Test hack. +*/ + puDeactivateWidget () ; + + p->reveal () ; // Reveal the submenu + + // If the parent floats in its own window, and the submenu drops off the window, + // expand the window to fit. + +#if 1 + puGroup *parent = p -> getParent () ; + + if ( ( parent != parent -> getParent () ) && parent -> getFloating () ) // DEPRECATED! -- we need to replace this code. + { + int temp_window = puGetWindow () ; + puSetWindow ( parent -> getWindow () ) ; + + puBox *par_box = parent -> getBBox () ; + puBox *cur_box = p -> getBBox () ; + int x_min = (cur_box->min[0] < 0) ? par_box->min[0] + cur_box->min[0] : par_box->min[0] ; + int x_max = (par_box->max[0] > par_box->min[0] + cur_box->max[0]) ? + par_box->max[0] : par_box->min[0] + cur_box->max[0] ; + int y_min = (cur_box->min[1] < 0) ? par_box->min[1] + cur_box->min[1] : par_box->min[1] ; + int y_max = (par_box->max[1] > par_box->min[1] + cur_box->max[1]) ? + par_box->max[1] : par_box->min[1] + cur_box->max[1] ; + int x_siz, y_siz; + puGetWindowSize ( &x_siz, &y_siz ) ; + if ( x_siz < (x_max - x_min) ) x_siz = x_max - x_min ; // Adjust the present size + if ( y_siz < (y_max - y_min) ) y_siz = y_max - y_min ; + puSetWindowSize ( x_siz, y_siz ) ; + + x_min = par_box->min[0] - x_min ; + y_min = y_siz - ( par_box->max[1] - par_box->min[1] ) ; + + /* If the parent window is SUPPOSED to be stuck at the top of the screen, move it. + - JCJ 6 June 2002 */ + if (parent -> getVStatus () == 1) + parent -> setPosition ( x_min, y_min ) ; + + puSetWindow ( temp_window ) ; + } +#endif + } + else + p->hide () ; + + for ( puObject *child = b -> getParent () -> getFirstChild () ; + child != NULL ; child = child -> getNextObject() ) + { + if (( child -> getType() & PUCLASS_BUTTON ) != 0 && child != b ) child -> clrValue () ; + if (( child -> getType() & PUCLASS_POPUPMENU ) != 0 && child != p ) child -> hide () ; + } + + // Move the popup menu to the last item in the "dlist" so it is drawn last + // (in front of everything else). + + puMoveToLast ( p ); +} + +void puMenuBar::add_submenu ( const char *str, char *items[], puCallback _cb[], + void *_user_data[] ) +{ + int w, h ; + getSize ( &w, &h ) ; + + puOneShot *b ; + + if ( bar_height > 0 ) + { + b = new puOneShot ( w+10, + 0, + w+10 + PUSTR_LGAP + puGetDefaultLegendFont().getStringWidth ( str ) + PUSTR_RGAP, + bar_height ) ; + b -> setLegend ( str ) ; + } + else + 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 ( puMenuBar_drop_down_the_menu ) ; + b -> setActiveDirn ( PU_UP_AND_DOWN ) ; + + puPopupMenu *p = new puPopupMenu ( w+10, 0 ) ; + p->setActiveButton ( active_mouse_button ) ; + + b -> setUserData ( p ) ; + + if ( _user_data != NULL ) + for ( int i = 0 ; items[i] != NULL ; i++ ) + p -> add_item ( items[i], _cb[i], _user_data[i] ) ; + else + 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 -> getNextObject() ) + { + int w, h ; + + /* Reposition the button so it looks nice */ + + ob -> getSize ( &w, &h ) ; + ob -> setPosition ( width, 0 ) ; + ob = ob -> getNextObject() ; + + /* 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/src/pui/puNative.h b/src/pui/puNative.h new file mode 100644 index 0000000..0abbb4f --- /dev/null +++ b/src/pui/puNative.h @@ -0,0 +1,101 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puNative.h 1857 2004-02-16 13:49:03Z stromberg $ +*/ + +#ifndef _PU_NATIVE_H_ +#define _PU_NATIVE_H_ + +#ifndef PU_USE_NATIVE +# define PU_USE_NATIVE +#endif + +#include "pu.h" + +#if defined(UL_GLX) +# include +#elif defined(UL_WGL) +// nothing +#elif defined(UL_AGL) +# include +#elif defined(UL_CGL) +# include +#endif + + +inline int puGetWindowNative () +{ +#if defined(UL_GLX) + return (int) glXGetCurrentDrawable () ; +#elif defined(UL_WGL) + return (int) wglGetCurrentDC () ; +#elif defined(UL_AGL) + return (int) aglGetCurrentDrawable () ; +#elif defined(UL_CGL) + return (int) CGLGetCurrentContext () ; +#else + return 0 ; +#endif +} + + +inline void puGetWindowSizeNative ( int *width, int *height ) +{ +#if defined(UL_GLX) + + Window root ; + int x, y ; + unsigned int w, h, b, d ; + + XGetGeometry ( glXGetCurrentDisplay (), + glXGetCurrentDrawable (), + &root, &x, &y, &w, &h, &b, &d ) ; + *width = w ; + *height = h ; + +#elif defined(UL_WGL) + + RECT r ; + GetClientRect( WindowFromDC( wglGetCurrentDC() ), &r ); + *width = r.right ; + *height = r.bottom ; + +#else // Help! Need implementations for more systems. + + GLint vp[4] ; + glGetIntegerv ( GL_VIEWPORT, vp ) ; + *width = vp[0] + vp[2] ; + *height = vp[1] + vp[3] ; + // Note: puSetOpenGLState calls glViewport(0, 0, w, h). + +#endif +} + + +inline void puInitNative () +{ + puSetWindowFuncs ( puGetWindowNative, NULL, + puGetWindowSizeNative, NULL ) ; + puRealInit () ; +} + + +#endif diff --git a/src/pui/puObject.cxx b/src/pui/puObject.cxx new file mode 100644 index 0000000..060888a --- /dev/null +++ b/src/pui/puObject.cxx @@ -0,0 +1,520 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puObject.cxx 2051 2005-11-10 20:21:22Z fayjf $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF1(puObject,puValue) + + +static inline float clamp01 ( float x ) +{ + return (x >= 1.0f) ? 1.0f : x ; +} + +static 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_LEGEND */ + { 0.0f, 0.0f, 0.0f, 1.0f }, /* PUCOL_MISC */ + { 0.8f, 0.7f, 0.7f, 1.0f } /* PUCOL_EDITFIELD */ +} ; + + +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.0f, g/2.0f, b/2.0f, a ) ; + puSetColour ( col [ PUCOL_HIGHLIGHT ], clamp01(r*1.3f), clamp01(g*1.3f), + clamp01(b*1.3f), a ) ; + + if ( 4.0f * g + 3.0f * r + b > 4.0f ) + { + puSetColour ( col [ PUCOL_LEGEND ], 0.0f, 0.0f, 0.0f, a ) ; + puSetColour ( col [ PUCOL_MISC ], 0.0f, 0.0f, 0.0f, a ) ; + } + else + { + puSetColour ( col [ PUCOL_LEGEND ], 1.0f, 1.0f, 1.0f, a ) ; + puSetColour ( col [ PUCOL_MISC ], 1.0f, 1.0f, 1.0f, a ) ; + } +} + + +static int defaultStyle = PUSTYLE_DEFAULT ; +static int defaultBorderThickness = 5 ; +static puFont defaultLegendFont ; +static puFont defaultLabelFont ; +static float defaultColourScheme [ 4 ] ; + +void puSetDefaultStyle ( int style ) +{ + defaultStyle = style ; + + switch ( abs(style) ) + { + case PUSTYLE_SPECIAL_UNDERLINED : + defaultBorderThickness = 1 ; + break ; + + case PUSTYLE_SMALL_BEVELLED : + case PUSTYLE_SMALL_SHADED : + case PUSTYLE_BOXED : + defaultBorderThickness = 2 ; + break ; + + case PUSTYLE_BEVELLED : + case PUSTYLE_SHADED : + case PUSTYLE_DROPSHADOW : + defaultBorderThickness = 5 ; + break ; + } +} +int puGetDefaultStyle ( void ) { return defaultStyle ; } + +void puSetDefaultBorderThickness ( int t ) { defaultBorderThickness = t ; } +int puGetDefaultBorderThickness ( void ) { return defaultBorderThickness ; } + +void puSetDefaultFonts ( puFont legendFont, puFont labelFont ) +{ + defaultLegendFont = legendFont ; + defaultLabelFont = labelFont ; +} + +puFont puGetDefaultLabelFont ( void ) { return defaultLabelFont ; } +puFont puGetDefaultLegendFont ( void ) { return defaultLegendFont ; } + +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 ) ; + puPostRefresh () ; +} + +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 ; + active_mouse_button = PU_LEFT_BUTTON ; + style = defaultStyle ; + visible = active = TRUE ; + highlighted = FALSE ; + am_default = FALSE ; + window = puGetWindow () ; + v_status = 0 ; + + cb = NULL ; + active_cb = NULL ; + down_cb = NULL ; + r_cb = NULL ; + border_thickness = defaultBorderThickness ; + render_data = NULL ; + user_data = NULL ; + next = prev = NULL ; + label = NULL ; + labelPlace = PUPLACE_LABEL_DEFAULT ; + labelFont = defaultLabelFont ; + legend = NULL ; + legendFont = defaultLegendFont ; + legendPlace = PUPLACE_LEGEND_DEFAULT ; + + when_to_deactivate = PUDEACTIVATE_ON_MOUSE_CLICK ; + + for ( int i = 0 ; i < PUCOL_MAX ; i++ ) + puSetColour ( colour[i], _puDefaultColourTable[i] ) ; + + parent = NULL ; + + if ( ! puNoGroup() ) + puGetCurrGroup() -> add ( this ) ; + + puPostRefresh () ; +} + + +puObject::~puObject () +{ + if ( parent != this && parent != NULL ) + parent -> remove ( this ) ; + + if ( this == puActiveWidget () ) + puDeactivateWidget () ; + + puPostRefresh () ; +} + +void puObject::recalc_bbox ( void ) +{ + bbox = abox ; + + if ( label != NULL ) + { + switch ( labelPlace ) // Extend the bounding box left and right + { + case PUPLACE_ABOVE_LEFT : + case PUPLACE_UPPER_LEFT : + case PUPLACE_CENTERED_LEFT : + case PUPLACE_LOWER_LEFT : + case PUPLACE_BELOW_LEFT : + bbox.min[0] -= labelFont.getStringWidth ( label ) + PUSTR_LGAP ; + break ; + + case PUPLACE_ABOVE_RIGHT : + case PUPLACE_UPPER_RIGHT : + case PUPLACE_CENTERED_RIGHT : + case PUPLACE_LOWER_RIGHT : + case PUPLACE_BELOW_RIGHT : + bbox.max[0] += labelFont.getStringWidth ( label ) + PUSTR_RGAP ; + break ; + } + + switch ( labelPlace ) // Extend the bounding box up and down + { + case PUPLACE_ABOVE_LEFT : + case PUPLACE_TOP_LEFT : + case PUPLACE_TOP_CENTERED : + case PUPLACE_TOP_RIGHT : + case PUPLACE_ABOVE_RIGHT : + bbox.max[1] += labelFont.getStringHeight ( label ) + labelFont.getStringDescender () + + PUSTR_TGAP ; + break ; + + case PUPLACE_BELOW_LEFT : + case PUPLACE_BOTTOM_LEFT : + case PUPLACE_BOTTOM_CENTERED : + case PUPLACE_BOTTOM_RIGHT : + case PUPLACE_BELOW_RIGHT : + bbox.min[1] -= labelFont.getStringHeight ( label ) + labelFont.getStringDescender () + + PUSTR_BGAP ; + break ; + } + } + + if ( parent != NULL ) + parent -> recalc_bbox () ; +} + +void puObject::getAbsolutePosition ( int *x, int *y ) const +{ + puGroup *par ; + *x = abox.min[0] ; + *y = abox.min[1] ; + + for ( par = getParent () ; par != NULL ; par = par -> getParent () ) + { + int x_offset, y_offset ; + par -> getPosition ( &x_offset, &y_offset ) ; + + *x += x_offset ; + *y += y_offset ; + } +} + +void puObject::draw_legend ( int dx, int dy ) +{ + if ( legend == NULL ) + return ; + + int xx, yy ; + + int lgap = PUSTR_LGAP ; + int rgap = PUSTR_RGAP ; + int tgap = PUSTR_TGAP ; + int bgap = PUSTR_BGAP ; + + if ( ( abs(style) != PUSTYLE_NONE ) && + ( abs(style) != PUSTYLE_PLAIN ) && + ( abs(style) != PUSTYLE_DROPSHADOW ) ) + { + if ( abs(style) != PUSTYLE_SPECIAL_UNDERLINED ) + { + lgap += getBorderThickness () ; + rgap += getBorderThickness () ; + tgap += getBorderThickness () ; + } + bgap += getBorderThickness () ; + } + + /* If greyed out then halve the opacity when drawing the 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 */ + + switch ( getLegendPlace() ) + { + case PUPLACE_TOP_LEFT : + case PUPLACE_CENTERED_LEFT : + case PUPLACE_BOTTOM_LEFT : + case PUPLACE_LOWER_LEFT : + xx = lgap ; + break ; + + case PUPLACE_TOP_CENTERED : + case PUPLACE_CENTERED_CENTERED : + case PUPLACE_BOTTOM_CENTERED : + xx = ( abox.max[0] - abox.min[0] - legendFont.getStringWidth (legend) ) / 2 ; + break ; + + case PUPLACE_TOP_RIGHT : + case PUPLACE_CENTERED_RIGHT : + case PUPLACE_BOTTOM_RIGHT : + case PUPLACE_LOWER_RIGHT : + xx = abox.max[0] - abox.min[0] - legendFont.getStringWidth ( legend ) - rgap ; + break ; + + default : + ulSetError ( UL_WARNING, "PUI: Unrecognised LEGEND place %d", getLegendPlace() ) ; + return ; + } + + switch ( getLegendPlace() ) + { + case PUPLACE_TOP_LEFT : + case PUPLACE_TOP_CENTERED : + case PUPLACE_TOP_RIGHT : + yy = abox.max[1] - abox.min[1] - legendFont.getStringHeight ( legend ) - + legendFont.getStringDescender () - tgap ; + break ; + + case PUPLACE_CENTERED_LEFT : + case PUPLACE_CENTERED_CENTERED : + case PUPLACE_CENTERED_RIGHT : + case PUPLACE_LOWER_LEFT : /* Backwards compatibility to PUPLACE_LEFT */ + case PUPLACE_LOWER_RIGHT : /* Backwards compatibility to PUPLACE_RIGHT */ + default : + yy = ( abox.max[1] - abox.min[1] + - legendFont.getStringHeight ( legend ) ) / 2 + + legendFont.getStringDescender () ; + break ; + + case PUPLACE_BOTTOM_LEFT : + case PUPLACE_BOTTOM_CENTERED : + case PUPLACE_BOTTOM_RIGHT : + yy = bgap + legendFont.getStringDescender () ; + break ; + } + + legendFont.drawString ( legend, dx + abox.min[0] + xx, + dy + abox.min[1] + yy ) ; +} + +void puObject::draw_label ( int dx, int dy ) +{ + if ( label == NULL ) + return ; + + int xx, yy ; + + /* 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 ( getLabelPlace() ) + { + case PUPLACE_ABOVE_LEFT : + case PUPLACE_UPPER_LEFT : + case PUPLACE_CENTERED_LEFT : + case PUPLACE_LOWER_LEFT : + case PUPLACE_BELOW_LEFT : + xx = 0 ; + break ; + + case PUPLACE_TOP_LEFT : + case PUPLACE_BOTTOM_LEFT : + xx = abox.min[0] - bbox.min[0] + PUSTR_LGAP ; + break ; + + case PUPLACE_TOP_CENTERED : + case PUPLACE_BOTTOM_CENTERED : + xx = ( bbox.max[0] - bbox.min[0] - labelFont.getStringWidth ( label ) ) / 2 ; + break ; + + case PUPLACE_TOP_RIGHT : + case PUPLACE_BOTTOM_RIGHT : + xx = abox.max[0] - bbox.min[0] - labelFont.getStringWidth ( label ) - PUSTR_RGAP ; + break ; + + case PUPLACE_ABOVE_RIGHT : + case PUPLACE_UPPER_RIGHT : + case PUPLACE_CENTERED_RIGHT : + case PUPLACE_LOWER_RIGHT : + case PUPLACE_BELOW_RIGHT : + xx = bbox.max[0] - bbox.min[0] - labelFont.getStringWidth ( label ) ; + break ; + + default : + ulSetError ( UL_WARNING, "PUI: Unrecognised LABEL place %d", getLegendPlace() ) ; + return ; + } + + switch ( getLabelPlace() ) + { + case PUPLACE_ABOVE_LEFT : + case PUPLACE_TOP_LEFT : + case PUPLACE_TOP_CENTERED : + case PUPLACE_TOP_RIGHT : + case PUPLACE_ABOVE_RIGHT : + yy = bbox.max[1] - bbox.min[1] - labelFont.getStringHeight () - + labelFont.getStringDescender () ; + break ; + + case PUPLACE_UPPER_LEFT : + case PUPLACE_UPPER_RIGHT : + yy = abox.max[1] - bbox.min[1] - labelFont.getStringHeight ( label ) - PUSTR_TGAP ; + break ; + + case PUPLACE_CENTERED_LEFT : + case PUPLACE_CENTERED_RIGHT : + default : + yy = ( bbox.max[1] - bbox.min[1] - + labelFont.getStringHeight ( label ) ) / 2 + + labelFont.getStringDescender () ; + break ; + + case PUPLACE_LOWER_LEFT : + case PUPLACE_LOWER_RIGHT : + yy = abox.min[1] - bbox.min[1] + labelFont.getStringDescender () + PUSTR_BGAP ; + break ; + + case PUPLACE_BELOW_LEFT : + case PUPLACE_BOTTOM_LEFT : + case PUPLACE_BOTTOM_CENTERED : + case PUPLACE_BOTTOM_RIGHT : + case PUPLACE_BELOW_RIGHT : + yy = labelFont.getStringDescender () ; + break ; + } + + labelFont.drawString ( label, dx + bbox.min[0] + xx, + dy + bbox.min[1] + yy ) ; +} + + +int puObject::checkKey ( int key, int updown ) +{ + if ( updown == PU_UP ) + return FALSE ; + + if ( isReturnDefault() && ( key == '\r' || key == '\n' ) && ( window == puGetWindow () ) ) + { + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + checkHit ( active_mouse_button, PU_DOWN, (abox.min[0]+abox.max[0])/2, + (abox.min[1]+abox.max[1])/2 ) ; + checkHit ( active_mouse_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 ) +{ + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + if ( updown != PU_DRAG ) + puMoveToLast ( this ); + + if ( button == active_mouse_button ) + { + if ( ( updown == active_mouse_edge ) || ( active_mouse_edge == PU_UP_AND_DOWN ) ) + { + lowlight () ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + } + else + highlight () ; + } + else + lowlight () ; +} + +int puObject::checkHit ( int button, int updown, int x, int y ) +{ + if ( ( puGetPressedButton () || ( updown == PU_UP ) ) && isHit( x, y ) || + puGetPressedButton () && ( isHit( x, y ) || ( puActiveWidget () == this ) ) ) + { + doHit ( button, updown, x, y ) ; + return TRUE ; + } + + return FALSE ; +} + + diff --git a/src/pui/puOneShot.cxx b/src/pui/puOneShot.cxx new file mode 100644 index 0000000..16b9625 --- /dev/null +++ b/src/pui/puOneShot.cxx @@ -0,0 +1,35 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puOneShot.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF1(puOneShot,puButton) + + +void puOneShot::doHit ( int button, int updown, int x, int y ) +{ + puButton::doHit ( button, updown, x, y ) ; + setValue ( 0 ) ; +} + diff --git a/src/pui/puPW.h b/src/pui/puPW.h new file mode 100644 index 0000000..3b030ef --- /dev/null +++ b/src/pui/puPW.h @@ -0,0 +1,66 @@ + +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puPW.h 1863 2004-02-17 01:43:21Z sjbaker $ +*/ + +#ifndef _PU_PW_H_ +#define _PU_PW_H_ + +#include "pu.h" + +#define PUPW_WINDOW_MAGIC 0x3DEB4938 /* Random! */ + +inline int puGetWindowPW() +{ + return PUPW_WINDOW_MAGIC ; +} + +inline void puSetWindowPW ( int window ) +{ + // Not possible because PW is a single-window library. + // But we can at least check that the handle matches. + + assert ( window == PUPW_WINDOW_MAGIC ) ; +} + +inline void puGetWindowSizePW ( int *width, int *height ) +{ + pwGetSize ( width, height ) ; +} + +inline void puSetWindowSizePW ( int width, int height ) +{ + pwSetSize ( width, height ) ; +} + +inline void puInitPW () +{ + puSetWindowFuncs ( puGetWindowPW, + puSetWindowPW, + puGetWindowSizePW, + puSetWindowSizePW ) ; + puRealInit () ; +} + + +#endif + diff --git a/src/pui/puPopup.cxx b/src/pui/puPopup.cxx new file mode 100644 index 0000000..7fde9d2 --- /dev/null +++ b/src/pui/puPopup.cxx @@ -0,0 +1,28 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puPopup.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF1(puPopup,puInterface) + diff --git a/src/pui/puPopupMenu.cxx b/src/pui/puPopupMenu.cxx new file mode 100644 index 0000000..e5a49aa --- /dev/null +++ b/src/pui/puPopupMenu.cxx @@ -0,0 +1,245 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puPopupMenu.cxx 2021 2005-05-06 18:31:27Z fayjf $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF1(puPopupMenu,puPopup) + + +puObject *puPopupMenu::add_item ( const char *str, puCallback _cb, + void *_user_data ) +{ + 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 ) ; + b->setLegendPlace ( PUPLACE_LOWER_LEFT ) ; + b->setUserData ( _user_data ) ; + b->setActiveButton ( active_mouse_button ) ; + b->setWindow ( getWindow () ) ; + 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 -> getNextObject() ) + { + ob -> getSize ( &w, &h ) ; + + if ( w > widest ) widest = w ; + } + + for ( ob = dlist ; ob != NULL ; ob = ob -> getNextObject() ) + { + ob -> getSize ( &w, &h ) ; + ob -> setSize ( widest, h ) ; + } + + recalc_bbox () ; +} + + +int puPopupMenu::checkKey ( int key, int updown ) +{ + if ( dlist == NULL || ! isVisible () || ! isActive () || ( window != puGetWindow () ) ) + return FALSE ; + + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + if ( updown == PU_DOWN ) + { + hide () ; + + /* Turn everything off ready for next time. */ + + for ( puObject *bo = dlist ; bo != NULL ; bo = bo -> getNextObject() ) + 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 -> getNextObject() != NULL ; + bo = bo -> getNextObject() ) + /* Find the last object in our list. */ ; + + for ( ; bo != NULL ; bo = bo -> getPrevObject() ) + 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 () || ( window != puGetWindow () ) ) + return FALSE ; + + /* If an item is going to fall out the bottom of the window and puGroup will */ + /* move it upward (around line 303 of puGroup.cxx), then make sure checkhit */ + /* realizes the thing has moved -- JCJ and Fay 5 June 2002 */ + + int absx, absy ; + getAbsolutePosition (&absx, &absy) ; + if ( absy < 0 ) + y += absy ; + + /* Must test 'isHit' before making the menu invisible! */ + + /* + * 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. + */ + + int hit = isHit ( x, y ) ; + + /* If the mouse is clicked on another widget, hide the window - JCJ 18 Jun 2002 */ + if ( updown != PU_DRAG && !hit ) + hide () ; + + 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 -> getNextObject() ) + { + if ( ! hit ) + bo -> checkHit ( button, updown, x , y ) ; + + bo -> clrValue () ; + } + } + + if ( ! hit ) + return FALSE ; + + puObject *bo ; + int objecthit = FALSE ; + /* + 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 -> getNextObject() != NULL ; + bo = bo -> getNextObject() ) + if ( updown == PU_DRAG && ! bo -> checkHit ( button, updown, x, y ) ) + bo -> clrValue () ; + + /* Find the last object in our list. */ ; + + /* Following code permits highlighting and lowlighting */ + /* of oneshots underneath a PopupMenu. */ + /* - JCJ and Fay 31 May 2002 */ + + for ( ; bo != NULL ; bo = bo -> getPrevObject() ) + { + puBox *box = bo->getABox () ; + if ( ( x > box->min[0] ) && ( x < box->max[0] ) && + ( y > box->min[1] ) && ( y < box->max[1] ) ) + bo->highlight () ; + else + bo->lowlight () ; + /* Since actually RETURNing here would break the for loop early and kill the */ + /* correct lowlighting, just set a var to check later. - JCJ 3 Jun 2002 */ + if ( bo -> checkHit ( button, updown, x, y ) ) + objecthit = TRUE ; + } + + /* If the object was hit in the above for loop, then it.. was hit.*/ + if (objecthit) + return TRUE ; + + return FALSE ; +} + + diff --git a/src/pui/puRange.cxx b/src/pui/puRange.cxx new file mode 100644 index 0000000..3e107c0 --- /dev/null +++ b/src/pui/puRange.cxx @@ -0,0 +1,27 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF(puRange) + diff --git a/src/pui/puSDL.h b/src/pui/puSDL.h new file mode 100644 index 0000000..c9c48a8 --- /dev/null +++ b/src/pui/puSDL.h @@ -0,0 +1,55 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puSDL.h 2130 2007-11-18 21:46:37Z fayjf $ +*/ + +#ifndef _PU_SDL_H_ +#define _PU_SDL_H_ + +#ifndef PU_USE_SDL +# define PU_USE_SDL +#endif + +#include "pu.h" +#include "SDL.h" + + +inline int puGetWindowSDL () +{ + return 0; +} + +inline void puGetWindowSizeSDL ( int *width, int *height ) +{ + SDL_Surface *display = SDL_GetVideoSurface () ; + *width = display->w ; + *height = display->h ; +} + +inline void puInitSDL () +{ + puSetWindowFuncs ( puGetWindowSDL, NULL, + puGetWindowSizeSDL, NULL ) ; + puRealInit () ; +} + + +#endif diff --git a/src/pui/puSlider.cxx b/src/pui/puSlider.cxx new file mode 100644 index 0000000..0ffaa18 --- /dev/null +++ b/src/pui/puSlider.cxx @@ -0,0 +1,210 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puSlider.cxx 2148 2009-01-29 17:11:24Z fayjf $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF2(puSlider,puRange,puObject) + + +void puSlider::draw_slider_box ( int dx, int dy, const puBox &box, float val, const char *box_label ) +{ + int sd, od ; + if ( isVertical() ) { sd = 1 ; od = 0 ; } else { sd = 0 ; od = 1 ; } + + int sz = box.max [sd] - box.min [sd] ; // Size of slider box, in pixels + + 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 ] = box.min [ sd ] + (int) val ; + bx.max [ sd ] = (int) ( (float) bx.min [ sd ] + (float) sz * slider_fraction ) ; + bx.min [ od ] = box.min [ od ] + 2 ; + bx.max [ od ] = box.max [ od ] - 2 ; + + bx.draw ( dx, dy, PUSTYLE_SMALL_SHADED, colour, FALSE, 2 ) ; + + if ( box_label ) + { + int xx ; + int yy ; + if ( isVertical () ) // Vertical slider, text goes to the right of it + { + xx = bx.max[0] + PUSTR_LGAP ; + yy = ( bx.max[1] + bx.min[1] - legendFont.getStringHeight ( box_label ) ) / 2 ; + } + else // Horizontal slider, text goes above it + { + xx = ( bx.max[0] + bx.min[0] - legendFont.getStringWidth ( box_label ) ) / 2 ; + yy = bx.max[1] + PUSTR_BGAP ; + } + + /* 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 */ + + legendFont.drawString ( box_label, dx + xx, dy + yy ) ; + } +} + +void puSlider::draw ( int dx, int dy ) +{ + if ( !visible || ( window != puGetWindow () ) ) return ; + + if ( ( style == PUSTYLE_BEVELLED ) || + ( style == PUSTYLE_SHADED ) ) + abox.draw ( dx, dy, -PUSTYLE_BOXED, colour, FALSE, 2 ) ; + else + abox.draw ( dx, dy, -style, colour, FALSE, border_thickness ) ; + + if ( r_cb ) + r_cb ( this, dx, dy, render_data ) ; + else + { + float val = getFloatValue () ; + + draw_slider_box ( dx, dy, abox, ( val - minimum_value ) / ( maximum_value - minimum_value ) ) ; + + draw_legend ( dx, dy ) ; + } + + draw_label ( dx, dy ) ; +} + + +void puSlider::doHit ( int button, int updown, int x, int y ) +{ + if ( puActiveWidget() && ( this != puActiveWidget() ) ) + { + puActiveWidget() -> invokeDownCallback () ; + puDeactivateWidget () ; + } + + if ( updown != PU_DRAG ) + puMoveToLast ( this ); + + if ( button != active_mouse_button ) + return ; + + if ( updown == PU_UP ) + { + puDeactivateWidget () ; + return ; + } + + int sd = isVertical() ; + int coord = sd ? y : x ; + float range = maximum_value - minimum_value ; + float last_value = clamp ( getFloatValue () ); + float next_value = last_value ; + float norm_value = ( next_value - minimum_value ) / range ; + int box_len = abox.max [sd] - abox.min [sd] ; + + if ( updown == PU_DOWN ) { + int lower = abox.min [sd] + int(box_len * (1.0 - slider_fraction) * norm_value) ; + int upper = lower + int(box_len * slider_fraction) ; // upper/lower slider margin in pixels + float page_step = getPageStepSize () ; + + start_offset = -1 ; + if ( page_step_size <= 0.0f ) { // old slider behavior + start_offset = int(box_len * slider_fraction * 0.5f) ; + updown = PU_DRAG ; + + } else if ( coord < lower ) { + next_value -= page_step ; + + } else if ( coord > upper ) { + next_value += page_step ; + + } else { // new slider behavior + start_offset = coord - abox.min [sd] - int(box_len * (1.0 - slider_fraction) * norm_value) ; + puSetActiveWidget ( this, x, y ) ; + return; + } + } + + if ( updown == PU_DRAG && start_offset >= 0 ) { + if ( box_len == 0 ) { + norm_value = 0.5f ; + } else if ( slider_fraction >= 1.0f ) { + norm_value = 0.0f ; + } else { + norm_value = ( coord - abox.min[sd] - start_offset ) / ( box_len * (1.0f - slider_fraction) ) ; + } + next_value = norm_value * range + minimum_value ; + } + + setValue ( checkStep ( clamp ( next_value ) ) ) ; + + if ( next_value == last_value ) return ; + + switch ( cb_mode ) + { + case PUSLIDER_CLICK : + if ( updown == active_mouse_edge ) + { + last_cb_value = next_value ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + } + break ; + + case PUSLIDER_DELTA : /* Deprecated! */ + if ( fabs ( last_cb_value - next_value ) >= cb_delta ) + { + last_cb_value = next_value ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + } + break ; + + case PUSLIDER_ALWAYS : + default : + last_cb_value = next_value ; + puSetActiveWidget ( this, x, y ) ; + invokeCallback () ; + break ; + } +} + + +void puSlider::setSliderFraction ( float f ) +{ + int i = isVertical() ? 1 : 0 ; + int sz = abox.max [i] - abox.min [i] ; // Size of slider box, in pixels + float minf = 8.0f / sz ; // fraction that makes a 8px handle + + slider_fraction = (f1.0f) ? 1.0f : f ; + puPostRefresh () ; +} + diff --git a/src/pui/puText.cxx b/src/pui/puText.cxx new file mode 100644 index 0000000..217a44f --- /dev/null +++ b/src/pui/puText.cxx @@ -0,0 +1,39 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puText.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF1(puText,puObject) + + +void puText::draw ( int dx, int dy ) +{ + if ( !visible || ( window != puGetWindow () ) ) return ; + + if ( r_cb ) + r_cb ( this, dx, dy, render_data ) ; + + draw_label ( dx, dy ) ; +} + diff --git a/src/pui/puValue.cxx b/src/pui/puValue.cxx new file mode 100644 index 0000000..093008e --- /dev/null +++ b/src/pui/puValue.cxx @@ -0,0 +1,206 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: puValue.cxx 2076 2006-04-13 16:20:23Z bram $ +*/ + + +#include "puLocal.h" + +UL_RTTI_DEF(puValue) + + +static inline void skip_whitespace ( const char **str ) +{ + while ( isspace ( **str ) != 0 ) + (*str)++ ; +} + +static int strtoint ( const char *str ) +{ + skip_whitespace ( &str ) ; + + if ( *str == '\0') + return 0 ; + + int result ; + + if ( *str == '-' ) + { + result = -1 ; + skip_whitespace ( &(++str) ) ; + } + else + { + result = 1 ; + + if ( *str == '+' ) + skip_whitespace ( &(++str) ) ; + } + + if ( ulStrNEqual ( str, "0x", 2 ) == TRUE ) + result *= (int) strtol ( str + 2, NULL, 16 ) ; /* try hexadecimal */ + else if ( ulStrNEqual ( str, "0o", 2 ) == TRUE ) + result *= (int) strtol ( str + 2, NULL, 8 ) ; /* try octal */ + else if ( ulStrNEqual ( str, "0b", 2 ) == TRUE ) + result *= (int) strtol ( str + 2, NULL, 2 ) ; /* try binary */ + else + result *= (int) strtol ( str, NULL, 10 ) ; /* try decimal */ + + return result ; +} + + +void puValue::re_eval ( void ) +{ + if ( convert == FALSE ) + return ; + + if ( res_integer != NULL ) + { + floater = (float) *res_integer ; + + /* + Needed for puInput / puLargeInput: + Do not modify the string value unless necessary + */ + if ( *res_integer != strtoint ( string ) ) + sprintf ( string, "%d", *res_integer ) ; + + boolean = ( *res_integer != 0 ) ; + + puPostRefresh () ; + } + else if ( res_floater != NULL ) + { + integer = (int) *res_floater ; + + /* + Needed for puInput / puLargeInput: + Do not modify the string value unless necessary + */ + if ( *res_floater != strtod ( string, NULL ) ) + sprintf ( string, "%g", *res_floater ) ; + + boolean = ( *res_floater != 0.0f ) ; + + puPostRefresh () ; + } + else if ( res_string != NULL ) + { + integer = strtoint ( res_string ) ; + floater = (float) strtod ( res_string, NULL ) ; + boolean = ( strcmp ( res_string, "0" ) != 0 ) ; + puPostRefresh () ; + } + else if ( res_bool != NULL ) + { + integer = *res_bool ? 1 : 0 ; + floater = *res_bool ? 1.0f : 0.0f ; + + /* + Needed for puInput / puLargeInput: + Do not modify the string value unless necessary + */ + if ( *res_bool != ( strcmp ( string, "0" ) != 0 ) ) + sprintf ( string, "%d", *res_bool ? 1 : 0 ) ; + + puPostRefresh () ; + } +} + +void puValue::copy_stringval ( const char *str ) +{ + if ( res_string != NULL ) + { + /* Work around ANSI strncpy's null-fill behaviour */ + + res_string[0] = '\0' ; + strncat ( res_string, str, res_string_sz-1 ) ; + } + else + { + int str_len = strlen ( str ) ; + int new_size = string_size ; + + while ( new_size < str_len + 1 ) + /* While our array is too small, double it. */ + new_size += new_size ; + + while ( ( new_size > 4 * str_len + 1 ) && ( new_size > PUSTRING_INITIAL ) ) + /* While our array is too big, halve it */ + new_size /= 2 ; + + if ( new_size != string_size ) + /* If the array size has changed, allocate a new array */ + { + delete [] string ; + string = new char [ new_size ] ; + string_size = new_size ; + } + + memcpy ( string, str, str_len + 1 ) ; + } +} + +void puValue::setValue ( const char *s ) +{ + if ( s == NULL ) + s = "" ; + + copy_stringval ( s ) ; + + if ( convert == TRUE ) + { + *getIntegerp () = strtoint ( s ) ; + *getFloaterp () = (float) strtod ( s, NULL ) ; + *getBooleanp () = ( strcmp ( s, "0" ) != 0 ) ; + } + + puPostRefresh () ; +} + + +const char *puValue::getTypeString ( void ) const +{ + int i = getType () ; + + if ( i & PUCLASS_DIAL ) return "puDial" ; + if ( i & PUCLASS_LISTBOX ) return "puListBox" ; + if ( i & PUCLASS_ARROW ) return "puArrowButton" ; + 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_GROUP ) return "puGroup" ; + if ( i & PUCLASS_OBJECT ) return "puObject" ; + if ( i & PUCLASS_VALUE ) return "puValue" ; + + return "Unknown Object type." ; +} + diff --git a/src/pui/pui.dsp b/src/pui/pui.dsp new file mode 100644 index 0000000..e006280 --- /dev/null +++ b/src/pui/pui.dsp @@ -0,0 +1,218 @@ +# Microsoft Developer Studio Project File - Name="pui" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=pui - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "pui.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "pui.mak" CFG="pui - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "pui - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "pui - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "pui - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "..\fnt" /I "..\sg" /I "..\util" /I ".." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "PU_USE_NONE" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy release\*.lib ..\..\*.* copy pu.h ..\..\pu.h copy puGLUT.h "..\..\" copy puFLTK.h "..\..\" copy puSDL.h "..\..\" copy puNative.h "..\..\" copy puPW.h ..\..\ +# End Special Build Tool + +!ELSEIF "$(CFG)" == "pui - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I "..\fnt" /I "..\sg" /I "..\util" /I ".." /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "PU_USE_NONE" /FR /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\pui_d.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy debug\*.lib ..\..\*.* copy pu.h ..\..\pu.h copy puGLUT.h "..\..\" copy puFLTK.h "..\..\" copy puSDL.h "..\..\" copy puNative.h "..\..\" copy puPW.h ..\..\ +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "pui - Win32 Release" +# Name "pui - Win32 Debug" +# Begin Source File + +SOURCE=.\pu.cxx +# End Source File +# Begin Source File + +SOURCE=.\pu.h +# End Source File +# Begin Source File + +SOURCE=.\puArrowButton.cxx +# End Source File +# Begin Source File + +SOURCE=.\puBox.cxx +# End Source File +# Begin Source File + +SOURCE=.\puButton.cxx +# End Source File +# Begin Source File + +SOURCE=.\puButtonBox.cxx +# End Source File +# Begin Source File + +SOURCE=.\puDial.cxx +# End Source File +# Begin Source File + +SOURCE=.\puDialogBox.cxx +# End Source File +# Begin Source File + +SOURCE=.\puFLTK.h +# End Source File +# Begin Source File + +SOURCE=.\puFont.cxx +# End Source File +# Begin Source File + +SOURCE=.\puFrame.cxx +# End Source File +# Begin Source File + +SOURCE=.\puGLUT.h +# End Source File +# Begin Source File + +SOURCE=.\puGroup.cxx +# End Source File +# Begin Source File + +SOURCE=.\puInput.cxx +# End Source File +# Begin Source File + +SOURCE=.\puInputBase.cxx +# End Source File +# Begin Source File + +SOURCE=.\puInterface.cxx +# End Source File +# Begin Source File + +SOURCE=.\puListBox.cxx +# End Source File +# Begin Source File + +SOURCE=.\puLocal.h +# End Source File +# Begin Source File + +SOURCE=.\puMenuBar.cxx +# End Source File +# Begin Source File + +SOURCE=.\puNative.h +# End Source File +# Begin Source File + +SOURCE=.\puObject.cxx +# End Source File +# Begin Source File + +SOURCE=.\puOneShot.cxx +# End Source File +# Begin Source File + +SOURCE=.\puPopup.cxx +# End Source File +# Begin Source File + +SOURCE=.\puPopupMenu.cxx +# End Source File +# Begin Source File + +SOURCE=.\puPW.h +# End Source File +# Begin Source File + +SOURCE=.\puRange.cxx +# End Source File +# Begin Source File + +SOURCE=.\puSDL.h +# End Source File +# Begin Source File + +SOURCE=.\puSlider.cxx +# End Source File +# Begin Source File + +SOURCE=.\puText.cxx +# End Source File +# Begin Source File + +SOURCE=.\puValue.cxx +# End Source File +# End Target +# End Project diff --git a/src/pw/Makefile.am b/src/pw/Makefile.am new file mode 100644 index 0000000..151fbd3 --- /dev/null +++ b/src/pw/Makefile.am @@ -0,0 +1,14 @@ +if BUILD_PW + +lib_LIBRARIES = libplibpw.a + +include_HEADERS = pw.h + +libplibpw_a_SOURCES = pw.cxx pwX11.cxx pwWindows.cxx pwMacOSX.cxx + +INCLUDES = -I$(top_srcdir)/src/util + +endif + +EXTRA_DIST = pw.dsp + diff --git a/src/pw/pw.cxx b/src/pw/pw.cxx new file mode 100644 index 0000000..784363a --- /dev/null +++ b/src/pw/pw.cxx @@ -0,0 +1,6 @@ + +#include "ul.h" +#include "pw.h" + +/* This space intentionally left blank */ + diff --git a/src/pw/pw.dsp b/src/pw/pw.dsp new file mode 100644 index 0000000..d228464 --- /dev/null +++ b/src/pw/pw.dsp @@ -0,0 +1,106 @@ +# Microsoft Developer Studio Project File - Name="pw" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=pw - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "pw.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "pw.mak" CFG="pw - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "pw - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "pw - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "pw - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\util" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0xc09 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=copy release\*.lib ..\..\*.* copy pw.h ..\..\pw.h +# End Special Build Tool + +!ELSEIF "$(CFG)" == "pw - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\util" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0xc09 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\pw_d.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=copy debug\*.lib ..\..\*.* copy pw.h ..\..\pw.h +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "pw - Win32 Release" +# Name "pw - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\pwWindows.cxx +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\pw.h +# End Source File +# End Group +# End Target +# End Project diff --git a/src/pw/pw.h b/src/pw/pw.h new file mode 100644 index 0000000..626da03 --- /dev/null +++ b/src/pw/pw.h @@ -0,0 +1,111 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pw.h 1928 2004-04-06 23:45:19Z sjbaker $ +*/ + + +#ifndef _PW_H_ +#define _PW_H_ 1 + +#include + +#define PW_IS_PRESENT 1 + +typedef void pwResizeCB ( int w, int h ) ; +typedef void pwExitCB () ; +typedef void pwKeybdFunc ( int key, int updown, int x, int y ) ; +typedef void pwMouseFunc ( int key, int updown, int x, int y ) ; +typedef void pwMousePosFunc ( int x, int y ) ; + +void pwInit ( int multisample, int num_samples ) ; + +void pwInit ( int x, int y, int w, int h, + int multisample, + char *title, int border, int num_samples ) ; + +void pwSetCallbacks ( pwKeybdFunc *kb = NULL, pwMouseFunc *ms = NULL, + pwMousePosFunc *mp = NULL, pwResizeCB *rcb = NULL, + pwExitCB *ecb = NULL ) ; + +int pwGetModifiers () ; +void pwSwapBuffers () ; +void pwGetSize ( int *w, int *h ) ; +void pwSetSizeOrigin ( int x, int y, int w, int h ) ; +void pwSetSize ( int x, int y ) ; +void pwSetOrigin ( int w, int h ) ; +void pwSetCursor ( int c ) ; +void pwCleanup () ; +void pwSetAutoRepeatKey ( bool enable ) ; + +#define PW_CURSOR_NONE 0 +#define PW_CURSOR_RIGHT 1 +#define PW_CURSOR_LEFT 2 +#define PW_CURSOR_QUERY 3 +#define PW_CURSOR_AIM 4 +#define PW_CURSOR_CIRCLE 5 +#define PW_CURSOR_WAIT 6 +#define PW_CURSOR_CROSS 7 +#define PW_CURSOR_CUSTOM 8 + +/* + WARNING: These have to be the same as PU_KEY_whatever. +*/ + +#define PW_KEY_SPECIAL_OFFSET 256 + +#define PW_KEY_F1 (1 + PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_F2 (2 + PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_F3 (3 + PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_F4 (4 + PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_F5 (5 + PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_F6 (6 + PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_F7 (7 + PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_F8 (8 + PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_F9 (9 + PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_F10 (10 + PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_F11 (11 + PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_F12 (12 + PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_LEFT (100+ PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_UP (101+ PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_RIGHT (102+ PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_DOWN (103+ PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_PAGE_UP (104+ PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_PAGE_DOWN (105+ PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_HOME (106+ PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_END (107+ PW_KEY_SPECIAL_OFFSET) +#define PW_KEY_INSERT (108+ PW_KEY_SPECIAL_OFFSET) + +/* The three standard keyboard modifiers */ +#define PW_SHIFT 1 +#define PW_CTRL 2 +#define PW_ALT 4 + +/* Whether a button has been pressed (DOWN) or released (UP) */ +#define PW_DOWN 0 +#define PW_UP 1 + +/* Mouse Buttons */ +#define PW_LEFT_BUTTON 0 +#define PW_MIDDLE_BUTTON 1 +#define PW_RIGHT_BUTTON 2 + +#endif + diff --git a/src/pw/pwMacOSX.cxx b/src/pw/pwMacOSX.cxx new file mode 100644 index 0000000..ce76be0 --- /dev/null +++ b/src/pw/pwMacOSX.cxx @@ -0,0 +1,1034 @@ + +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pwMacOSX.cxx 2095 2006-10-29 07:42:41Z bram $ +*/ + + +#include "ul.h" + +/* ONLY COMPILE THIS FILE FOR MACINTOSH OR MACOSX SYSTEMS */ + +/* PLEASE DON'T REMOVE THIS LINE AGAIN!!! */ +#if defined(UL_MACINTOSH) || defined(UL_MAC_OSX) +/* YES - THAT MEANS YOU! */ + + +/* +* +* - the fullscreen mode is indeed a "game mode"; +* - the fullscreen mode does not change the resolution of the screen: +* it uses the resolution (width, height and depth) in use before entering pw; +* - it is possible to toggle between modes by calling pwCleanup() +* and calling again pwInit; +* - the "border" parameter in pwInit is not used; +* - the "about" menu shows a standard alert box with the current version of plib +* and with the url to the plib official site. +* +*----------------------------------------- +* +* - with Mac OS 8.6 to 9.2: +* - must be linked with the following libraries: +* InterfaceLib, accessors.o, AppearanceLib, DrawSprocketLib +* and OpenGL (agl is in OpenGL) +* +* - ACTIVE_SLEEPTIME must be defined to 0 for the fastest execution; +* but it will not let other app to get events. +* +* - with Mac OS X: must be linked with the following frameworks: +* Carbon, AGL +* +* +* - if not using Xcode, the following compiler falgs should be set to avoid errors or warnings +* CPPFLAGS = -fpascal-strings -funsigned-char +*/ + +/* version of 2004-04-03 +* - changes from previous version: +* - fullscreen also implemented with mac OS 8.6 and 9; +* - key up events are now reported in mac OS 8.6 to 9.2 +* (these events are disabled by default...) +* - multisample added for mac OS X; +* - no auto-key repeat event by default (can be set by pwSetAutoRepeatKey(bool on_off) ); +* - better error handling and use of ulSetError; +*/ + +#if defined (UL_MAC_OSX) +# define TARGET_API_MAC_CARBON 1 +# include +# include +#elif defined (UL_MACINTOSH) +//# define TARGET_API_MAC_CARBON 0 +# undef ACCESSOR_CALLS_ARE_FUNCTIONS // already defined by ul.h !!! +# define ACCESSOR_CALLS_ARE_FUNCTIONS 1 +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +//#else +//# error only for Mac OS (8.6 to OS X) operating system! +#endif + + +#include +#include +#include "pw.h" + + +/* Apple menu: */ +#define mApple 128 +#define iAbout 1 +/* File menu: */ +#ifdef UL_MAC_OSX +# define ACTIVE_SLEEPTIME 0 +# define INACTIVE_SLEEPTIME 10 +# define mFile 129 +# define iQuit 1 +#else // UL_MACINTOSH +# define ACTIVE_SLEEPTIME 1 // 0 is fastest, but does not let other app to catch events. + // set to 0 if you want your app only to have CPU time +# define INACTIVE_SLEEPTIME 10 +# define mFile 129 +# define iQuit 1 +#endif + +static bool pwInitialized = false ; +static int origin [2] = { 0, 0 } ; +static int size [2] = { 640, 480 } ; +static SInt16 horScrSze, verScrSze; // screen dimensions +static bool full_screen; +static bool auto_repeat_key = false ; +#if TARGET_API_MAC_CARBON +static bool pwQuitFlag ; +#endif +static int modifiers ; +static int click_modifiers ; +static SInt32 sleepTime = ACTIVE_SLEEPTIME; + +static pwResizeCB *resizeCB = NULL ; +static pwExitCB *exitCB = NULL ; +static pwKeybdFunc *kbCB = NULL ; +static pwMouseFunc *msCB = NULL ; +static pwMousePosFunc *mpCB = NULL ; + +#if TARGET_API_MAC_CARBON + static WindowPtr pwWindow = NULL ; +# define SETPORT(w) SetPortWindowPort(w) +# define GRAFPTR +#else + static CWindowPtr pwWindow = NULL ; +# define SETPORT(w) SetPort((GrafPtr)w) +# define GRAFPTR (GrafPtr) +#endif + +#ifdef UL_MACINTOSH +// DrawSprocket stuff: +static DSpContextReference dspContext; +#endif + +// generic OpenGL stuff +static AGLContext currContext = NULL ; + +static void HandleEvents(void); +static void Initialize(void); +static bool MakeWindow(int x, int y, int w, int h, char* title); +static void CreateContext(int multisample, int num_samples, bool fullscreen); +static void MakeMenu(void); +static void handleMenuEvent(long menuResult); +static void handleKeyEvent(EventRecord* eventPtr, int updown); +static void handleMouseMoveEvt(EventRecord* eventPtr); +#if TARGET_API_MAC_CARBON +static pascal OSErr QuitAppleEventHandler(const AppleEvent *appleEvt, AppleEvent* reply, long refcon); +#endif +static void pwAboutBox(void); +static void defaultExitFunc (); +#ifdef UL_MACINTOSH +static bool InitDSP(); +#endif + + +static void CtoPcpy( Str255 pstr, char *cstr ); + + +#if TARGET_API_MAC_CARBON +static pascal OSErr +QuitAppleEventHandler( const AppleEvent*, AppleEvent*, long ) +{ + pwQuitFlag = true; + return(noErr); +} +#endif + +static void Initialize() +{ + OSErr err = noErr; + BitMap scrBits; + +#if !TARGET_API_MAC_CARBON + InitGraf(&qd.thePort); + InitFonts(); + FlushEvents(everyEvent, 0); + InitWindows(); + InitMenus(); + InitDialogs(nil); + sleepTime = ACTIVE_SLEEPTIME; + SetEventMask(everyEvent); // to enable key up events !!! +#else + pwQuitFlag = false; + err = AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP(QuitAppleEventHandler), 0, false ); + // this funtion is to handle the "cmd+Q" event. This key event is not send as a keyDown event with carbon! + if (err != noErr) + { + ulSetError(UL_FATAL, "Error in initialization of the system." ); + } +#endif + InitCursor(); + exitCB = defaultExitFunc; + // get screen size: + GetQDGlobalsScreenBits(&scrBits); + horScrSze = scrBits.bounds.right - scrBits.bounds.left; + verScrSze = scrBits.bounds.bottom - scrBits.bounds.top; +} + +// Copy a C string into a Pascal string +static void CtoPcpy( Str255 pstr, char* cstr ) +{ + int i = 1; + while( (*cstr) && (i < 255) ) pstr[i++] = *cstr++; + pstr[0] = i - 1; +} + +static bool MakeWindow(int x, int y, int w, int h, char* title) +{ + Rect wRect; + Str255 pTitle; + + CtoPcpy( pTitle, title ); + SetRect(&wRect, x, y, w+x, h+y); +#if TARGET_API_MAC_CARBON + pwWindow = NewCWindow(nil, &wRect, pTitle, true, zoomNoGrow, (WindowPtr) -1, true, 0); +#else + if (full_screen) // use DrawSprocket + pwWindow = (CWindowPtr) NewCWindow (nil, &wRect, pTitle, true, plainDBox, (WindowPtr)-1, 0, 0); + else + pwWindow = (CWindowPtr) NewCWindow(nil, &wRect, pTitle, true, zoomNoGrow, (WindowPtr) -1, true, 0); +#endif + if (pwWindow == NULL) + { + ulSetError(UL_WARNING, "pw: can not open a window; will exit"); + return false; + } + SETPORT(pwWindow); + return true; +} + +static void CreateContext(int multisample, int num_samples, bool fullscreen) +{ + AGLPixelFormat aglPixFmt; + // Choose pixel format: + GLint attrib[10]; + GLint i = 0; + attrib[i++] = AGL_RGBA; + attrib[i++] = AGL_DOUBLEBUFFER; +#ifdef UL_MAC_OSX + if (fullscreen) attrib[i++] = AGL_FULLSCREEN; +#endif + attrib[i++] = AGL_DEPTH_SIZE; + attrib[i++] = 32; + //attrib[i++] = AGL_ALL_RENDERERS; + attrib[i++] = AGL_NONE; + + if (multisample) + { +#ifdef UL_MAC_OSX + i--; + attrib[i++] = AGL_SAMPLE_BUFFERS_ARB ; + attrib[i++] = 1 ; + attrib[i++] = AGL_SAMPLES_ARB ; + attrib[i++] = num_samples; + attrib[i++] = AGL_NONE; + aglPixFmt = aglChoosePixelFormat(NULL, 0, attrib); + if (aglPixFmt == NULL) + { + multisample = 0; // retry without + ulSetError(UL_WARNING, "pw: multisample pixel format not found"); + i -= 5; + attrib[i++] = AGL_NONE; + } +#else + multisample = 0; // retry without + ulSetError(UL_WARNING, "pw: multisample not implemented with MacOS 8 & 9"); +#endif + } + if (!multisample) + { + aglPixFmt = aglChoosePixelFormat(NULL, 0, attrib); + } + if (aglPixFmt == NULL) + { + ulSetError(UL_FATAL, "pw: can not find a pixel format"); + } + + // Create an AGL context + currContext = aglCreateContext(aglPixFmt, NULL); + aglDestroyPixelFormat ( aglPixFmt ); + if (currContext == NULL) + { + ulSetError(UL_FATAL, "pw: can not create an OpenGL context\n"); + } + // swap buffers only every k vertical retrace: + //long k = 100; + //aglSetInteger(currContext, AGL_SWAP_INTERVAL, &k); +} + +void MakeMenu() +{ + SInt32 response; + MenuRef menu; + CreateNewMenu(mApple, 0, &menu); + SetMenuTitleWithCFString( menu, CFSTR("Plib") ); + + InsertMenu(menu, 0); + InsertMenuItemTextWithCFString(menu, CFSTR("About Plib..."), 0, 0, iAbout); + +#if !TARGET_API_MAC_CARBON + AppendResMenu(menu, 'DRVR'); +#endif + + // If we not running on OS X then we need to add a File:Quit command: + Gestalt( gestaltMenuMgrAttr, &response ); + if ( ( response & gestaltMenuMgrAquaLayoutMask ) == 0 ) + { + menu = NewMenu (mFile, (ConstStr255Param) "File"); // new menu + InsertMenu (menu, 0); // add menu to end + AppendMenu (menu, (ConstStr255Param) "Quit"); // add items + } + + DrawMenuBar(); +} + +static void defaultExitFunc () +{ + pwCleanup () ; + exit(0); +} + +void pwSetCallbacks( pwKeybdFunc *kb, pwMouseFunc *ms, + pwMousePosFunc *mp, pwResizeCB *rcb, + pwExitCB *ecb ) +{ + resizeCB = rcb; + exitCB = (ecb == NULL) ? defaultExitFunc : ecb ; + kbCB = kb ; + msCB = ms ; + mpCB = mp ; +} + +int pwGetModifiers() +{ + return modifiers; +} + +void pwSetAutoRepeatKey( bool on_off ) +{ + auto_repeat_key = on_off; +} + +static void pwAboutBox() +{ + // show a dialog box with info on plib: + SInt16 outItemHit; + char version[32]; + Str255 Pversion; + char* about = "for more info see "; + Str255 Pabout; + sprintf(version, "PLIB v %i.%i.%i", PLIB_MAJOR_VERSION, PLIB_MINOR_VERSION, PLIB_TINY_VERSION ); + CtoPcpy( Pversion, version ); + CtoPcpy( Pabout, about ); + StandardAlert ( kAlertPlainAlert, + Pversion, + Pabout, + NULL, + &outItemHit ); +} + +static void handleMenuEvent(long menuCmd) +{ +#if !TARGET_API_MAC_CARBON + Str255 DAName; +#endif + int menuNum = HiWord(menuCmd); + int itemNum = LoWord(menuCmd); + switch (menuNum) + { + case mApple: // apple menu: + { + switch (itemNum) + { + case iAbout: pwAboutBox(); break; + default: +#if !TARGET_API_MAC_CARBON + GetMenuItemText(GetMenuHandle(mApple), itemNum, DAName); + OpenDeskAcc(DAName); +#endif + break; + } + break; + } + case mFile: // File menu: + { + switch (itemNum) + { + case iQuit: (*exitCB)(); break; + default: ; + } + } + } + HiliteMenu(0); // remove. the highlight on the selected menu. +} + +static int translateKey(int ch, int key) +{ + /* + if ( modifiers & PW_ALT ) + { + UInt32 state = 0; + long keyResult = KeyTranslate ( (void *) GetScriptManagerVariable (smKCHRCache), + (UInt16) key, &state ); + ch = 0xFF & keyResult; + } + */ + // special characters: + switch (ch) + { + case kLeftArrowCharCode: ch = PW_KEY_LEFT; break; + case kUpArrowCharCode: ch = PW_KEY_UP; break; + case kRightArrowCharCode: ch = PW_KEY_RIGHT; break; + case kDownArrowCharCode: ch = PW_KEY_DOWN; break; + case kPageUpCharCode: ch = PW_KEY_PAGE_UP; break; + case kPageDownCharCode: ch = PW_KEY_PAGE_DOWN; break; + case kHomeCharCode: ch = PW_KEY_HOME; break; + case kEndCharCode: ch = PW_KEY_END; break; + case kHelpCharCode: ch = PW_KEY_INSERT; break; + case kFunctionKeyCharCode: + // fonction keys: + switch(key) + { + case 0x7A: ch = PW_KEY_F1; break; + case 0x78: ch = PW_KEY_F2; break; + case 0x63: ch = PW_KEY_F3; break; + case 0x76: ch = PW_KEY_F4; break; + case 0x60: ch = PW_KEY_F5; break; + case 0x61: ch = PW_KEY_F6; break; + case 0x62: ch = PW_KEY_F7; break; + case 0x64: ch = PW_KEY_F8; break; + case 0x65: ch = PW_KEY_F9; break; + case 0x6D: ch = PW_KEY_F10; break; + case 0x67: ch = PW_KEY_F11; break; + case 0x6F: ch = PW_KEY_F12; break; + default: break; + } + break; + default: ; + } + return ch; +} + +static void handleKeyEvent(EventRecord* eventPtr, int updown) +{ + GrafPtr origPort; + + if ( ! kbCB ) return; + // handle key_events: + int ch = eventPtr->message & charCodeMask ; // character pressed + int key = (eventPtr->message & keyCodeMask) >> 8 ; // key pressed + ch = translateKey(ch, key); + GetPort(&origPort); + SETPORT(pwWindow); + GlobalToLocal(&eventPtr->where); + (*kbCB) ( ch, updown, eventPtr->where.h, eventPtr->where.v ) ; + SetPort(origPort); + return; +} + + +static void handleDrag(WindowPtr window, Point mouseloc) +{ + Point loc; + GrafPtr origPort; + Rect dragBounds, windowBounds; + + GetRegionBounds(GetGrayRgn(), &dragBounds); + + DragWindow(window, mouseloc, &dragBounds); + + GetPort (&origPort); // save Port + SETPORT(pwWindow); + + GetWindowPortBounds(window, &windowBounds); + loc.h = windowBounds.left; + loc.v = windowBounds.top; + + LocalToGlobal (&loc); + origin[0] = loc.h; // save new origin + origin[1] = loc.v; + + MoveWindow(GRAFPTR pwWindow, loc.h, loc.v, false); + // update OpenGL Context: + aglUpdateContext(currContext); + + //SETPORT(pwWindow); + SetPort (origPort); // restore Port +} + +static void handleGoAwayBox(WindowPtr window, Point mouseloc) +{ + GrafPtr origPort; + + GetPort(&origPort); + SETPORT(window); + + if( TrackGoAway(window, mouseloc) ) + { + (*exitCB)(); // quit... + } + + SetPort(origPort); +} + +static int last_m_h = 0; +static int last_m_v = 0; + +static void handleMouseMoveEvt(EventRecord* eventPtr) +{ + GrafPtr origPort; + + if ( ! mpCB ) return; + + int m_h = eventPtr->where.h; + int m_v = eventPtr->where.v; + if ( (m_v != last_m_v) || (m_h != last_m_h) ) + { + last_m_v = m_v ; last_m_h = m_h ; // screen coord. + GetPort(&origPort); + SETPORT(pwWindow); + GlobalToLocal(&eventPtr->where); + (*mpCB) ( eventPtr->where.h, eventPtr->where.v ) ; + SetPort(origPort); + } + return; +} + +static void HandleEvents() +{ + EventRecord event; + GrafPtr origPort; +// bool testNextEvent = true; + +#if TARGET_API_MAC_CARBON + if (pwQuitFlag) (*exitCB)(); // quit! +#endif + +// while ( testNextEvent ) +// { + WaitNextEvent(everyEvent, &event, sleepTime, nil) ; +#ifdef UL_MACINTOSH + if (full_screen) + { + Boolean dspEventProcessed; + DSpProcessEvent(&event, &dspEventProcessed); + if (dspEventProcessed) return; + } +#endif + int updown = PW_UP ; + + modifiers = 0; + if ( event.modifiers & (shiftKey | rightShiftKey) ) + modifiers |= PW_SHIFT ; + if ( event.modifiers & (optionKey | rightOptionKey) ) + modifiers |= PW_ALT ; + if ( event.modifiers & (controlKey | rightControlKey) ) + modifiers |= PW_CTRL ; + + switch ( event.what ) + { + case keyDown: + // test for a 'command' + key (menu): + if(event.modifiers & cmdKey) + { + char achar = (char) (event.message & charCodeMask); + handleMenuEvent( MenuKey(achar) ) ; + return; + } + // FALLTHROUGH (not a command) + handleKeyEvent(&event, PW_DOWN); + return; + case autoKey: + if ( ! auto_repeat_key ) + { // report a mouse move event, if any: + handleMouseMoveEvt(&event); + return; + } + // else report a key down event: + updown = PW_DOWN ; + case keyUp: + handleKeyEvent(&event, updown); + return; + + case mouseDown: + { + short part; + WindowPtr window; + + part = FindWindow(event.where, &window); + switch(part) + { + case inMenuBar: + handleMenuEvent( MenuSelect(event.where) ); + return; + #if !TARGET_API_MAC_CARBON + case inSysWindow: + SystemClick(&event, window); + break; + #endif + case inDrag: + handleDrag(window, event.where); + return; + case inGoAway: + handleGoAwayBox(window, event.where); + return; + case inContent: + if(!window) return; + if ( GRAFPTR pwWindow != FrontWindow() ) + { + SelectWindow (GRAFPTR pwWindow); + return; + } + } + // FALLTHROUGH (not a system click) + updown = PW_DOWN ; + click_modifiers = modifiers; + } + case mouseUp: + int button; + switch( click_modifiers ) + { + case PW_ALT : button = PW_RIGHT_BUTTON ; break ; + case PW_CTRL : button = PW_MIDDLE_BUTTON ; break ; + default : button = PW_LEFT_BUTTON ; break ; + } + GetPort(&origPort); + SETPORT(pwWindow); + GlobalToLocal(&event.where); + modifiers = 0; // reset modifiers with mouse events + if (msCB) (*msCB)( button, updown, event.where.h, event.where.v ); + SetPort(origPort); + return; + + case osEvt: + { + unsigned char subcode = event.message >> 24; + if (subcode == suspendResumeMessage) // Suspend/resume event + if (resumeFlag & event.message) // Resume + { + #ifdef UL_MACINTOSH + if (full_screen) sleepTime = 0; + else + #endif + sleepTime = ACTIVE_SLEEPTIME; + return; + } + else // suspend + sleepTime = INACTIVE_SLEEPTIME; + break; + } + case activateEvt: + if (event.modifiers & activeFlag) + { + #ifdef UL_MACINTOSH + if (full_screen) sleepTime = 0; + else + #endif + sleepTime = ACTIVE_SLEEPTIME; + return; + } + else sleepTime = INACTIVE_SLEEPTIME; + break; + + case updateEvt: + case nullEvent: // likely an idle event (i.e. no events) + // report mouse location, only if mouse has moved: + // (there is no mouse move events on Mac!) + handleMouseMoveEvt(&event); + return; + + default : /* printf ("event: %i \n", event.what); */ break; + + } // switch(event.what) +// } // while ( testNextEvent ) +} + + +#ifdef UL_MACINTOSH +bool InitDSP() +{ + DSpContextAttributes dspAttributes; + DisplayIDType displayID; + + if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) DSpStartup) + { + ulSetError(UL_WARNING, "DrawSprocket extension not found"); + return false; + } + // start DrawSprocket: + if (noErr != DSpStartup ()) + { + ulSetError(UL_WARNING, "Unable to start DrawSprocket"); + return false; + } + + // initialise to zero all fields of DSpContextAttributes: + BlockZero( &dspAttributes, sizeof (DSpContextAttributes) ); + dspAttributes.displayWidth = horScrSze; + dspAttributes.displayHeight = verScrSze; + dspAttributes.colorNeeds = kDSpColorNeeds_Require; + dspAttributes.displayDepthMask = kDSpDepthMask_16; + dspAttributes.displayBestDepth = 16; + dspAttributes.backBufferDepthMask = kDSpDepthMask_All; // must be specified even if only fornt buffer is needed + dspAttributes.backBufferBestDepth = 16; + dspAttributes.pageCount = 1; + //dspAttributes.contextOptions = 0 | kDSpContextOption_DontSyncVBL; // no page flipping and no VBL sync needed + // look for a DSp context: + dspContext = NULL; + OSStatus err = DSpFindBestContext(&dspAttributes, &dspContext); + ulSetError(UL_DEBUG, " display width = %li, height = %li, depth = %li, mask = %lX ", + dspAttributes.displayWidth, + dspAttributes.displayHeight, + dspAttributes.displayBestDepth, + dspAttributes.displayDepthMask ); + if (err != noErr) + { + if (err == kDSpContextNotFoundErr) + ulSetError(UL_WARNING, "Unable to find a DrawSprocket context"); + else + ulSetError(UL_WARNING, "DSpFindBestContext error"); + return false; + } + err = DSpContext_Reserve ( dspContext, &dspAttributes ); + if (noErr != err) + { + ulSetError(UL_WARNING, "Unable to set the display!"); + return false; + } + // activate DSp context: + //DSpContext_FadeGammaOut (NULL, NULL); // remove for debug + DSpContext_SetState (dspContext, kDSpContextState_Active); + if ( !MakeWindow( 0, 0, horScrSze, verScrSze, "" ) ) return false; + //DSpContext_FadeGammaIn (NULL, NULL); + return true; +} +#endif + +void pwInit ( int multisample, int num_samples ) +{ + pwInit ( 0,0,-1,-1, multisample, "", 0, num_samples ) ; +} + + +void pwInit ( int x, int y, int w, int h, int multisample, + char *title, int border, int num_samples ) +{ + if (pwInitialized) + { + ulSetError(UL_WARNING, "pwInit already called"); + return; + } + + full_screen = ( (w<0) || (h<0) ) ? true : false ; + Initialize(); + pwInitialized = true; + pwWindow = NULL; + + // Initialize OpenGL stuff (format, context, ...): + CreateContext(multisample, num_samples, full_screen); + + if (full_screen) + { + sleepTime = 0; +#ifdef UL_MACINTOSH + // initialisation of fullscreen mode with DrawSprocket + dspContext = NULL; + if ( ! InitDSP() ) + { + pwCleanup(); // releases GL contexts, windows, ... + exit(4); + } + // attach OpenGl to the screen: + aglSetDrawable(currContext, GetWindowPort (GRAFPTR pwWindow)); + /* + ulSetError(UL_DEBUG, "aglSetDrawable error: %s", + (const char*) aglErrorString(aglGetError()) ); + */ + // activate our GL context + aglSetCurrentContext(currContext); +#else + aglSetCurrentContext(currContext); + aglSetFullScreen (currContext, 0, 0, 0, 0); +#endif + // initialise origin and size of the window (for pwGetSize) + origin[0] = 0; + origin[1] = 0; + size[0] = horScrSze; + size[1] = verScrSze; + } + else // full_screen + { + if ( ! MakeWindow(x,y,w,h, title) ) + { + pwCleanup(); // releases GL contexts, windows, ... + exit(4); + } + // Attach the context to the window + aglSetDrawable(currContext, GetWindowPort (GRAFPTR pwWindow)); +#ifdef UL_MACINTOSH + { // because aglSetDrawable is slow... (not needed with OSX) + EventRecord event; + WaitNextEvent (everyEvent, &event, 2, NULL); + } +#endif + aglSetCurrentContext(currContext); + + // create a default menu bar (with the "quit" command): + MakeMenu(); + // initialise origin and size of the window (for pwGetSize) + origin[0] = x; + origin[1] = y; + size[0] = w; + size[1] = h; + } +} + + +void pwGetSize ( int *w, int *h ) +{ + *w = size[0]; + *h = size[1]; +} + +//special cursors: +static Cursor q_curs = // question mark cursor +{ + {0x0380, 0x07c0, 0x0c60, 0x1830, 0x1830, 0x0030, 0x0060, 0x00c0, + 0x0180, 0x0180, 0x0180, 0, 0, 0x0180, 0x0180, 0}, // data + {0x0380, 0x07e0, 0x0ff0, 0x1e38, 0x1c38, 0x1c38, 0x0078, 0x00f0, + 0x01e0, 0x01c0, 0x01c0, 0x01c0, 0, 0x01c0, 0x01c0, 0x01c0}, // mask + { 14, 7 } // hotspot +}; +static Cursor c_curs = // circle cursor +{ + {0, 0x03e0, 0x0c18, 0x1004, 0x2002, 0x2002, 0x4001, 0x4001, + 0x4001, 0x4001, 0x4001, 0x2002, 0x2002, 0x1004, 0x0c18, 0x03e0}, // data + {0, 0x03e0, 0x0ff8, 0x1c1c, 0x3006, 0x3006, 0x6003, 0x6003, + 0x6003, 0x6003, 0x6003, 0x3006, 0x3006, 0x1c1c, 0x0ff8, 0x03e0}, // mask + { 8, 8 } // hotspot +}; +static Cursor r_curs = // right arrow cursor +{ + {0, 0x0008, 0x0018, 0x0038, 0x0078, 0x00f8, 0x01f8, 0x03f8, + 0x07f8, 0x00f8, 0x00d8, 0x0188, 0x0180, 0x0300, 0x0300, 0}, // data + {0x000c, 0x001c, 0x003c, 0x007c, 0x00fc, 0x01fc, 0x03fc, 0x07fc, + 0x0ffc, 0x0ffc, 0x01fc, 0x03dc, 0x03cc, 0x0780, 0x0780, 0x0700}, // mask + { 1, 12 } // hotspot +}; +static Cursor x_curs = // circle + cross cursor +{ + {0, 0x03e0, 0x0c98, 0x1084, 0x2082, 0x2082, 0x4081, 0x4081, + 0x7fff, 0x4081, 0x4081, 0x2082, 0x2082, 0x1084, 0x0c98, 0x03e0}, // data + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, // mask + { 8, 8 } // hotspot +}; + + +void pwSetCursor ( int c ) +{ + UInt32 csr = 0xFFFF; + Cursor * csrPtr; + switch (c) + { + case PW_CURSOR_NONE : HideCursor(); return; + case PW_CURSOR_LEFT : csr = kThemeArrowCursor; break; + case PW_CURSOR_RIGHT : csrPtr = &r_curs; break; + case PW_CURSOR_AIM : csrPtr = &x_curs; break; + //case PW_CURSOR_CARET : csr = kThemeIBeamCursor; break; // ??? + case PW_CURSOR_WAIT : csr = kThemeWatchCursor; break; + case PW_CURSOR_CROSS : csr = kThemeCrossCursor; break; + case PW_CURSOR_QUERY : csrPtr = &q_curs; break; + case PW_CURSOR_CIRCLE : csrPtr = &c_curs; break; + case PW_CURSOR_CUSTOM : + default : csr = kThemeArrowCursor; + ulSetError(UL_WARNING, "Unknown or unavailable cursor type\n"); + } + if (csr==0xFFFF) SetCursor(csrPtr); + else SetThemeCursor(csr); + ShowCursor(); +} + + +void pwSetSize ( int w, int h ) +{ + if (!pwInitialized) + { + ulSetError(UL_WARNING, "call to pwSetSize without call to pwInit"); + return; + } + if ( full_screen ) + { + ulSetError(UL_WARNING, "call to pwSetSize in full screen mode"); + return; + } + if ( ( w == size[0] ) && ( h == size[1] ) ) return; + + GrafPtr origPort; + + if (w<50) w = 50; + if (w>horScrSze) w = horScrSze; + if (h<50) h = 50; + if (h>verScrSze) h = verScrSze; + + GetPort(&origPort); + + size[0] = w; // save size + size[1] = h; + + SizeWindow(GRAFPTR pwWindow, w, h, false); + // update OpenGL Context: + aglUpdateContext(currContext); + + if ( resizeCB != NULL ) (*resizeCB) ( w, h ) ; + + SetPort(origPort); +} + + +void pwSetOrigin ( int x, int y ) +{ + if (!pwInitialized) + { + ulSetError(UL_WARNING, "call to pwSetOrigin without call to pwInit"); + return; + } + if ( full_screen ) + { + ulSetError(UL_WARNING, "call to pwSetOrigin in full screen mode"); + return; + } + if ( ( x == origin[0] ) && ( y == origin[1] ) ) return; + + if ( (x + size[0]) < 10) x = 10 - size[0]; + if ( x > (horScrSze-10) ) x = horScrSze-10; + if ( (y + size[1]) < 60) y = 60 - size[1]; + if ( y > (verScrSze-10) ) y = verScrSze-10; + + MoveWindow(GRAFPTR pwWindow, x, y, false); + // update OpenGL Context: + aglUpdateContext(currContext); + + origin[0] = x; // save new origin + origin[1] = y; +} + + +void pwSetSizeOrigin ( int x, int y, int w, int h ) +{ + if (!pwInitialized) + { + ulSetError(UL_WARNING, "call to pwSetSizeOrigin without call to pwInit"); + return; + } + if ( full_screen ) + { + ulSetError(UL_WARNING, "call to pwSetSizeOrigin in full screen mode"); + return; + } + + pwSetOrigin( x, y ); + pwSetSize( w, h ); +} + + +void pwSwapBuffers () +{ + if (!pwInitialized) + { + ulSetError(UL_WARNING, "call to pwSwapBuffers without call to pwInit"); + return; + } + // glFlush () ; + aglSwapBuffers ( currContext ) ; + HandleEvents () ; +} + + +void pwCleanup () +{ + if (!pwInitialized) + { + ulSetError(UL_WARNING, "call to pwCleanup without call to pwInit"); + return; + } + + if (currContext != NULL) + { + aglSetDrawable (currContext, NULL); + aglSetCurrentContext (NULL); + aglDestroyContext ( currContext ); + } + if (pwWindow != NULL) DisposeWindow(GRAFPTR pwWindow); + +#ifdef UL_MACINTOSH + if (full_screen) + { + if (dspContext != NULL) + { + //DSpContext_FadeGammaOut (NULL, NULL); // remove for debug + DSpContext_SetState (dspContext, kDSpContextState_Inactive); + //DSpContext_FadeGammaIn (NULL, NULL); + + DSpContext_Release (dspContext); + } + + DSpShutdown (); + } +#endif + + pwInitialized = false; +} + +#endif diff --git a/src/pw/pwWindows.cxx b/src/pw/pwWindows.cxx new file mode 100644 index 0000000..76753e0 --- /dev/null +++ b/src/pw/pwWindows.cxx @@ -0,0 +1,490 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: pwWindows.cxx 2046 2005-09-02 21:03:43Z bram $ +*/ + + +#include "ul.h" + +/* ONLY COMPILE THIS FILE FOR MS-WINDOWS SYSTEMS */ + +#ifdef UL_WIN32 + +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include "pw.h" + +static int initialised = 0 ; +static int modifiers = 0 ; +static int origin [2] = { 0, 0 } ; +static int size [2] = { 640, 480 } ; + +static bool autoRepeat = false ; +static DWORD style = 0 ; + +static pwResizeCB *resizeCB = NULL ; +static pwExitCB *exitCB = NULL ; +static pwKeybdFunc *kbCB = NULL ; +static pwMouseFunc *msCB = NULL ; +static pwMousePosFunc *mpCB = NULL ; + +static HINSTANCE currInstance = NULL ; +static HWND currWnd = NULL ; +static HDC currDC = NULL ; +static HGLRC currGLRC = NULL ; + + +void defaultExitFunc () +{ + pwCleanup () ; + exit ( 0 ) ; +} + + +static void refreshModifiers () +{ + modifiers = 0 ; + + if( ( GetKeyState ( VK_SHIFT ) & 0x8000 ) != 0 ) modifiers |= PW_SHIFT ; + if( ( GetKeyState ( VK_CONTROL ) & 0x8000 ) != 0 ) modifiers |= PW_CTRL ; + if( ( GetKeyState ( VK_MENU ) & 0x8000 ) != 0 ) modifiers |= PW_ALT ; +} + +inline void clientSizeToWindowSize ( int& w, int& h, DWORD dwStyle ) +{ + RECT rect; + rect.left = 0 ; + rect.right = w ; + rect.top = 0 ; + rect.bottom = h ; + AdjustWindowRect( &rect, dwStyle, false ) ; + w = rect.right - rect.left ; + h = rect.bottom - rect.top ; +} + +LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + static int key = -1 ; + static int updown = PW_UP ; + static int old_key = -1 ; // We need this because "key" changes case + int button = -1 ; + static int mb = 0 ; + static int lastx = 0 ; + static int lasty = 0 ; + + refreshModifiers () ; + + switch (uMsg) + { + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + updown = PW_DOWN ; + if ( uMsg == WM_LBUTTONDOWN ) { button = PW_LEFT_BUTTON ; mb |= 1 ; } + else if ( uMsg == WM_MBUTTONDOWN ) { button = PW_MIDDLE_BUTTON ; mb |= 2 ; } + else { button = PW_RIGHT_BUTTON ; mb |= 4 ; } + SetCapture ( hWnd ) ; + lastx = SHORT ( LOWORD ( lParam ) ) ; + lasty = SHORT ( HIWORD ( lParam ) ) ; + if ( button != -1 && msCB ) + (*msCB) ( button, updown, lastx, lasty ) ; + break; + + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + updown = PW_UP ; + if ( uMsg == WM_LBUTTONUP ) { button = PW_LEFT_BUTTON ; mb &= ~1 ; } + else if ( uMsg == WM_MBUTTONUP ) { button = PW_MIDDLE_BUTTON ; mb &= ~2 ; } + else { button = PW_RIGHT_BUTTON ; mb &= ~4 ; } + if ( mb == 0 ) ReleaseCapture () ; + lastx = SHORT ( LOWORD ( lParam ) ) ; + lasty = SHORT ( HIWORD ( lParam ) ) ; + if ( button != -1 && msCB ) + (*msCB) ( button, updown, lastx, lasty ) ; + break; + + case WM_MOUSEMOVE: + lastx = SHORT ( LOWORD ( lParam ) ) ; + lasty = SHORT ( HIWORD ( lParam ) ) ; + if ( mpCB ) + (*mpCB) ( lastx, lasty ) ; + break; + + case WM_KEYDOWN: + /* If the key is already down, we are on auto-repeat. Break if the autorepeat is disabled. */ + if ( ( updown == PW_DOWN ) && ( int(wParam) == old_key ) ) + { + if ( autoRepeat ) + { + /* Disable CTRL, SHIFT, CapsLock keys from making a callback */ + if ( ( key == VK_CONTROL ) || ( key == VK_SHIFT ) || ( key == VK_CAPITAL ) ) + break ; + + if ( key != -1 && kbCB ) // Autorepeat enabled, call the callback with an "up" setting + (*kbCB) ( key, PW_UP, lastx, lasty ) ; + } + else + break ; // Autorepeat not enabled, just break + } + + updown = PW_DOWN ; + old_key = wParam ; + /* FALLTHROUGH */ + case WM_KEYUP: + if ( uMsg == WM_KEYUP ) updown = PW_UP ; + key = wParam ; + + /* Disable CTRL, SHIFT, CapsLock keys from making a callback */ + if ( ( key == VK_CONTROL ) || ( key == VK_SHIFT ) || ( key == VK_CAPITAL ) ) + break ; + + switch ( key ) + { + case VK_F1: key = PW_KEY_F1; break; + case VK_F2: key = PW_KEY_F2; break; + case VK_F3: key = PW_KEY_F3; break; + case VK_F4: key = PW_KEY_F4; break; + case VK_F5: key = PW_KEY_F5; break; + case VK_F6: key = PW_KEY_F6; break; + case VK_F7: key = PW_KEY_F7; break; + case VK_F8: key = PW_KEY_F8; break; + case VK_F9: key = PW_KEY_F9; break; + case VK_F10: key = PW_KEY_F10; break; + case VK_F11: key = PW_KEY_F11; break; + case VK_F12: key = PW_KEY_F12; break; + + case VK_LEFT: key = PW_KEY_LEFT; break; + case VK_RIGHT: key = PW_KEY_RIGHT; break; + case VK_UP: key = PW_KEY_UP; break; + case VK_DOWN: key = PW_KEY_DOWN; break; + + case VK_PRIOR: key = PW_KEY_PAGE_UP; break; + case VK_NEXT: key = PW_KEY_PAGE_DOWN; break; + case VK_HOME: key = PW_KEY_HOME; break; + case VK_END: key = PW_KEY_END; break; + case VK_INSERT: key = PW_KEY_INSERT; break; + + default: + // don't do this for WinCE + BYTE state[ 256 ]; + WORD code[ 2 ]; + + BOOL b = GetKeyboardState( state ); + assert(b); + + code [ 0 ] = 0; // WK: I need to do this, or on my Win2k box, the upper bits remain unchanged. + if( ToAscii( key, 0, state, code, 0 ) == 1 ) + if((0xFF00 & code[0]) == 0) // setting a high bit in key causes crashes later on (out of range array access) + key=code[ 0 ]; + + } + if ( key != -1 && kbCB ) + (*kbCB) ( key, updown, lastx, lasty ) ; + break; + + case WM_SIZE: + size[0] = LOWORD ( lParam ) ; + size[1] = HIWORD ( lParam ) ; + if ( resizeCB ) + (*resizeCB) ( size[0], size[1] ) ; + break; + + case WM_CLOSE: + (*exitCB)(); + break; + + default: + return ( DefWindowProc ( hWnd, uMsg, wParam, lParam ) ) ; + } + + return 0; +} + + +void pwSetAutoRepeatKey ( bool enable ) +{ + autoRepeat = enable ; +} + +void pwSetCallbacks ( pwKeybdFunc *kb, pwMouseFunc *ms, + pwMousePosFunc *mp, pwResizeCB *rcb, pwExitCB *ecb ) +{ + if ( ! initialised ) + { + fprintf ( stderr, "PW: You must not call pwSetCallbacks before pwInit.\n"); + exit ( 1 ) ; + } + + kbCB = kb ; + msCB = ms ; + mpCB = mp ; + resizeCB = rcb ; + exitCB = ecb ? ecb : defaultExitFunc ; +} + + +void pwInit ( int multisample, int num_samples ) +{ + pwInit ( 0, 0, -1, -1, multisample, "NoName", FALSE, num_samples ) ; +} + + +//typedef const char * wglGetExtensionsStringARBtype ( HDC hdc ) ; + +void pwInit ( int x, int y, int w, int h, int multisample, + char *title, int border, int num_samples ) +{ + currInstance = GetModuleHandleA( NULL ) ; + + /* Register the window class */ + WNDCLASS wc; + wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW ; + wc.lpfnWndProc = WndProc ; + wc.cbClsExtra = 0 ; + wc.cbWndExtra = 0 ; + wc.hInstance = currInstance ; + wc.hIcon = LoadIcon ( NULL, IDI_APPLICATION ) ; + wc.hCursor = LoadCursor ( NULL, IDC_ARROW ) ; + wc.hbrBackground = ( HBRUSH ) ( COLOR_WINDOW + 1 ) ; + wc.lpszMenuName = NULL ; + wc.lpszClassName = "PlibAppClass" ; + if ( !RegisterClass( &wc ) ) + { + fprintf ( stderr, "PW: Can't register window class" ) ; + exit ( 1 ) ; + } + + /* Setup window style */ + bool fullscn = (w == -1 && h == -1 ) ? true : false ; + + if ( w == -1 ) w = GetSystemMetrics( SM_CXSCREEN ) ; + if ( h == -1 ) h = GetSystemMetrics( SM_CYSCREEN ) ; + + origin [ 0 ] = x ; + origin [ 1 ] = y ; + size [ 0 ] = w ; + size [ 1 ] = h ; + + RECT rect ; + rect.left = x ; + rect.top = y ; + rect.right = rect.left + w ; + rect.bottom = rect.top + h ; + + if ( !fullscn ) + style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS ; + else + style = WS_POPUP ; + + AdjustWindowRect( &rect, style, false ) ; + + // The origin is really where the upper left of the window should be. + // rect is the setting for the window if the origin is for the client area. + // Adjust the window rect so that it will be located at the origin (x,y). + + int deltaX = x - rect.left ; + int deltaY = y - rect.top ; + + rect.left += deltaX ; + rect.right += deltaX ; + rect.top += deltaY ; + rect.bottom += deltaY ; + + /* Create the window */ + currWnd = CreateWindow( + "PlibAppClass", title, style, + rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, + NULL, NULL, currInstance, NULL ) ; + + if ( !currWnd ) + { + fprintf ( stderr, "PW: Can't create window" ) ; + exit ( 1 ) ; + } + + /* Get DC for this window */ + currDC = GetDC ( currWnd ) ; + if ( !currDC ) + { + fprintf ( stderr, "PW: Can't get window DC" ) ; + exit ( 1 ) ; + } + +// wglGetExtensionsStringARBtype *wglGetExtensionsStringARB = (wglGetExtensionsStringARBtype *)wglGetProcAddress ( "wglGetExtensionsStringARB" ) ; +// const char *extensionsString = wglGetExtensionsStringARB ( currDC ) ; + +// printf ( "%s %x %s\n", glGetString ( GL_EXTENSIONS ), wglGetExtensionsStringARB, extensionsString ) ; + +// if (!GLExtensionExists("WGL_ARB_multisample ")) +// return suggestedFormat; + + /* Set pixel format for DC */ + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */ + 1, /* version number */ + PFD_DRAW_TO_WINDOW | /* support window */ + PFD_SUPPORT_OPENGL | /* support OpenGL */ + PFD_DOUBLEBUFFER, /* double buffered */ + PFD_TYPE_RGBA, /* RGBA type */ + 24, /* 24-bit color depth */ + 0, 0, 0, 0, 0, 0, /* color bits ignored */ + 0, /* no alpha buffer */ + 0, /* shift bit ignored */ + 0, /* no accumulation buffer */ + 0, 0, 0, 0, /* accum bits ignored */ + 32, /* 32-bit z-buffer */ + 0, /* no stencil buffer */ + 0, /* no auxiliary buffer */ + PFD_MAIN_PLANE, /* main layer */ + 0, /* reserved */ + 0, 0, 0 /* layer masks ignored */ + }; + + /* Get best available match of pixel format for DC */ + int iPixelFormat = ChoosePixelFormat ( currDC, &pfd ) ; + if ( iPixelFormat == 0 ) + { + fprintf ( stderr, "PW: Can't get OpenGL pixel format" ) ; + exit ( 1 ) ; + } + + /* Set the pixel format of the DC */ + if ( !SetPixelFormat( currDC, iPixelFormat, &pfd ) ) + { + fprintf ( stderr, "PW: Can't set OpenGL pixel format" ) ; + exit ( 1 ) ; + } + + /* Show the window and paint its contents */ + ShowWindow ( currWnd, SW_SHOW ) ; + UpdateWindow ( currWnd ) ; + + /* Create openGL context and make it current */ + currGLRC = wglCreateContext ( currDC ) ; + if ( !currGLRC ) + { + fprintf ( stderr, "PW: Can't create OpenGL context" ) ; + exit ( 1 ) ; + } + if ( !wglMakeCurrent ( currDC, currGLRC ) ) + { + fprintf ( stderr, "PW: Can't make OpenGL context current" ) ; + exit ( 1 ) ; + } + + kbCB = NULL ; + msCB = NULL ; + mpCB = NULL ; + resizeCB = NULL ; + exitCB = defaultExitFunc ; + initialised = 1 ; + + glClear ( GL_COLOR_BUFFER_BIT ) ; + pwSwapBuffers () ; + glClear ( GL_COLOR_BUFFER_BIT ) ; + pwSwapBuffers () ; +} + + +void pwGetSize ( int *w, int *h ) +{ + if ( w ) *w = size[0] ; + if ( h ) *h = size[1] ; +} + + +void pwSetCursor ( int c ) +{ + LPCSTR cursor; + switch ( c ) + { + case PW_CURSOR_RIGHT : cursor = IDC_ARROW ; break ; + case PW_CURSOR_LEFT : cursor = IDC_ARROW ; break ; + case PW_CURSOR_QUERY : cursor = IDC_HELP ; break ; + /*case PW_CURSOR_AIM : cursor = ??? ; break ;*/ + case PW_CURSOR_CIRCLE : cursor = IDC_NO ; break ; + case PW_CURSOR_WAIT : cursor = IDC_WAIT ; break ; + case PW_CURSOR_CROSS : cursor = IDC_CROSS ; break ; + case PW_CURSOR_NONE : cursor = 0 ; break ; + default: + cursor = IDC_ARROW; + } + SetCursor( LoadCursor ( NULL, cursor ) ) ; +} + +void pwSetSize ( int w, int h ) +{ + clientSizeToWindowSize ( w, h, style ) ; + SetWindowPos ( currWnd, HWND_TOP, 0, 0, w, h, SWP_NOMOVE ) ; +} + + +void pwSetOrigin ( int x, int y ) +{ + SetWindowPos ( currWnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE ) ; +} + + +void pwSetSizeOrigin ( int x, int y, int w, int h ) +{ + clientSizeToWindowSize ( w, h, style ) ; + SetWindowPos ( currWnd, HWND_TOP, x, y, w, h, 0 ) ; +} + + +int pwGetModifiers () +{ + return modifiers ; +} + + +static void getEvents () +{ + MSG msg; + while ( PeekMessage( &msg, currWnd, 0, 0, PM_REMOVE ) ) + { + TranslateMessage( &msg ) ; + DispatchMessage ( &msg ) ; + } +} + + +void pwSwapBuffers () +{ + glFlush () ; + SwapBuffers ( currDC ) ; + getEvents () ; +} + + +void pwCleanup () +{ + wglMakeCurrent ( NULL, NULL ) ; + wglDeleteContext ( currGLRC ) ; + DestroyWindow ( currWnd ) ; +} + + +#endif + diff --git a/src/pw/pwX11.cxx b/src/pw/pwX11.cxx new file mode 100644 index 0000000..33488d7 --- /dev/null +++ b/src/pw/pwX11.cxx @@ -0,0 +1,651 @@ +#include "ul.h" + +/* ONLY COMPILE THIS FILE FOR GLX/X11 EQUIPPED SYSTEMS */ + +#ifdef UL_GLX + +#include "pw.h" + +#include +#include +#include +#include +#include + +extern "C" +{ +#include +#include +#include +#include +#include +#include +} + +#include +#include + +/* + These are supposed to be defined in /usr/include/GL/glxext.h + But at time of writing, they were missing. The OpenGL ARB + people have been informed by email. +*/ + +#ifndef GLX_SAMPLE_BUFFERS_ARB +#define GLX_SAMPLE_BUFFERS_ARB 100000 +#define GLX_SAMPLES_ARB 100001 +#endif + + +#ifdef HAVE_MOTIF + +extern "C" +{ +#include +} + +#else + +/* bit definitions for MwmHints.flags */ +#define MWM_HINTS_FUNCTIONS (1L << 0) +#define MWM_HINTS_DECORATIONS (1L << 1) +#define MWM_HINTS_INPUT_MODE (1L << 2) +#define MWM_HINTS_STATUS (1L << 3) + +/* bit definitions for MwmHints.decorations */ +#define MWM_DECOR_ALL (1L << 0) +#define MWM_DECOR_BORDER (1L << 1) +#define MWM_DECOR_RESIZEH (1L << 2) +#define MWM_DECOR_TITLE (1L << 3) +#define MWM_DECOR_MENU (1L << 4) +#define MWM_DECOR_MINIMIZE (1L << 5) +#define MWM_DECOR_MAXIMIZE (1L << 6) + +typedef struct +{ + unsigned long flags ; + unsigned long functions ; + unsigned long decorations ; + long inputMode ; + unsigned long status ; +} PropMotifWmHints ; + +#define PROP_MOTIF_WM_HINTS_ELEMENTS 5 + +#endif + +static bool initialised = false ; +static bool insideCallback = false ; +static int modifiers = 0 ; +static int origin [2] = { 0, 0 } ; +static int size [2] = { 640, 480 } ; +static int currScreen = 0 ; +static int currConnect = 0 ; +static int currCursor = PW_CURSOR_LEFT ; + +static pwResizeCB *resizeCB = NULL ; +static pwExitCB *exitCB = NULL ; +static pwKeybdFunc *kbCB = NULL ; +static pwMouseFunc *msCB = NULL ; +static pwMousePosFunc *mpCB = NULL ; + +static Display *currDisplay = NULL ; +static XVisualInfo *visualInfo = NULL ; +static Window currHandle ; +static GLXContext currContext ; +static Window rootWindow ; +static Atom delWinAtom ; + +static bool autoRepeat = false ; + +void pwSetAutoRepeatKey ( bool enable ) +{ + autoRepeat = enable ; +} + + +struct PixelFormat +{ + int num_samples ; + int bits_per_pixel ; ; + int z_bits ; +} ; + + +static PixelFormat preferred_pixel_formats [] = +{ + /* NumSamples, RGB_bits, Z_bits */ + + { 0, 24, 24 }, /* Progressively nastier image formats */ + { 0, 16, 24 }, + { 0, 16, 16 }, + { 0, 3, 16 }, + { 0, 3, 1 }, + { -1, -1, -1 } /* Magic end marker */ +} ; + + +void defaultExitFunc () +{ + pwCleanup () ; + exit ( 0 ) ; +} + + +static void chooseVisual ( PixelFormat *pf ) +{ + int attribs [ 100 ] ; + int n = 0 ; + + attribs [n++] = GLX_RGBA ; + + switch ( pf->bits_per_pixel ) + { + case 3 : + attribs [n++] = GLX_RED_SIZE ; attribs [n++] = 1 ; + attribs [n++] = GLX_GREEN_SIZE ; attribs [n++] = 1 ; + attribs [n++] = GLX_BLUE_SIZE ; attribs [n++] = 1 ; + break ; + + case 16 : + attribs [n++] = GLX_RED_SIZE ; attribs [n++] = 5 ; + attribs [n++] = GLX_GREEN_SIZE ; attribs [n++] = 6 ; + attribs [n++] = GLX_BLUE_SIZE ; attribs [n++] = 5 ; + break ; + + case 24 : + attribs [n++] = GLX_RED_SIZE ; attribs [n++] = 8 ; + attribs [n++] = GLX_GREEN_SIZE ; attribs [n++] = 8 ; + attribs [n++] = GLX_BLUE_SIZE ; attribs [n++] = 8 ; + break ; + } + + switch ( pf->z_bits ) + { + case 1 : attribs [n++] = GLX_DEPTH_SIZE ; attribs [n++] = 1 ; break ; + case 16 : attribs [n++] = GLX_DEPTH_SIZE ; attribs [n++] = 16 ; break ; + case 24 : attribs [n++] = GLX_DEPTH_SIZE ; attribs [n++] = 24 ; break ; + case 32 : attribs [n++] = GLX_DEPTH_SIZE ; attribs [n++] = 32 ; break ; + } + + if ( pf->num_samples > 0 ) + { + attribs [n++] = GLX_SAMPLE_BUFFERS_ARB ; attribs [n++] = 1 ; + attribs [n++] = GLX_SAMPLES_ARB ; attribs [n++] = pf->num_samples ; + } + + attribs [n++] = GLX_DOUBLEBUFFER ; + attribs [n++] = None ; + + visualInfo = glXChooseVisual ( currDisplay, currScreen, attribs ) ; +} + + +void pwInit ( int multisample, int num_samples ) +{ + pwInit ( 0, 0, -1, -1, multisample, "NoName", FALSE, num_samples ) ; +} + + +void pwSetCallbacks ( pwKeybdFunc *kb, pwMouseFunc *ms, + pwMousePosFunc *mp, pwResizeCB *rcb, + pwExitCB *ecb ) +{ + if ( ! initialised ) + { + fprintf ( stderr, "PW: You must not call pwSetCallbacks before pwInit.\n"); + exit ( 1 ) ; + } + + kbCB = kb ; + msCB = ms ; + mpCB = mp ; + resizeCB = rcb ; + exitCB = ecb ? ecb : defaultExitFunc ; +} + + +void pwInit ( int x, int y, int w, int h, int multisample, + char *title, int border, int num_samples ) +{ + char *displayName = getenv ( "DISPLAY" ) ; + + if ( displayName == NULL ) displayName = ":0.0" ; + + currDisplay = XOpenDisplay ( displayName ) ; + + if ( currDisplay == NULL ) + { + fprintf ( stderr, "PW: Can't open display '%s'", + XDisplayName ( displayName ) ) ; + exit ( 1 ) ; + } + + + /* OpenGL GLX extension availability? */ + + if ( ! glXQueryExtension ( currDisplay, NULL, NULL ) ) + { + fprintf ( stderr, "PW: GLX extension not available on display '%s'?!?", + XDisplayName ( displayName ) ) ; + exit ( 1 ) ; + } + + currScreen = DefaultScreen ( currDisplay ) ; + rootWindow = RootWindow ( currDisplay, currScreen ) ; + currConnect = ConnectionNumber ( currDisplay ) ; + delWinAtom = XInternAtom ( currDisplay, "WM_DELETE_WINDOW", 0 ) ; + + if ( w == -1 ) w = DisplayWidth ( currDisplay, currScreen ) ; + if ( h == -1 ) h = DisplayHeight ( currDisplay, currScreen ) ; + + origin [ 0 ] = x ; + origin [ 1 ] = y ; + size [ 0 ] = w ; + size [ 1 ] = h ; + + XSetWindowAttributes attribs ; + XTextProperty textProperty ; + XSizeHints sizeHints ; + XWMHints wmHints ; + unsigned int mask ; + PixelFormat pf ; + + for ( int i = 0 ; preferred_pixel_formats [ i ] . num_samples >= 0 ; i++ ) + { + pf = preferred_pixel_formats [ i ] ; + pf . num_samples = num_samples ; + + chooseVisual ( &pf ) ; + + if ( visualInfo != NULL ) + break ; + } + + if ( visualInfo == NULL ) + { + num_samples = 0 ; + + for ( int i = 0 ; preferred_pixel_formats [ i ] . num_samples >= 0 ; i++ ) + { + pf = preferred_pixel_formats [ i ] ; + pf . num_samples = num_samples ; + + chooseVisual ( &pf ) ; + + if ( visualInfo != NULL ) + break ; + } + + if ( visualInfo == NULL ) + { + fprintf ( stderr, "PW: Unable to open a suitable graphics window,\n" ) ; + exit ( 1 ) ; + } + } + + attribs.event_mask = StructureNotifyMask | ExposureMask | + ButtonPressMask | ButtonReleaseMask | + KeyPressMask | KeyReleaseMask | + EnterWindowMask | LeaveWindowMask | + PointerMotionMask | ButtonMotionMask | + VisibilityChangeMask ; + + attribs.background_pixmap = None ; + attribs.background_pixel = 0 ; + attribs.border_pixel = 0 ; + + attribs.colormap = XCreateColormap ( currDisplay, rootWindow, + visualInfo->visual, AllocNone ) ; + + mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask; + + currHandle = XCreateWindow ( currDisplay, rootWindow, + x, y, w, h, 0, visualInfo->depth, + InputOutput, visualInfo->visual, + mask, &attribs ) ; + + currContext = glXCreateContext ( currDisplay, visualInfo, NULL, 1 ) ; + + glXMakeCurrent ( currDisplay, currHandle, currContext ) ; + + if ( ! glXIsDirect ( currDisplay, glXGetCurrentContext() ) ) + { + fprintf ( stderr,"PW: This is an *INDIRECT* rendering context.") ; + fprintf ( stderr,"PW: That may be bad for performance." ) ; + } + + sizeHints.flags = 0 ; + + if ( x >= 0 && y >= 0 ) + sizeHints.flags |= USPosition ; + + sizeHints.flags |= USSize ; + + sizeHints.x = x ; sizeHints.y = y ; + sizeHints.width = w ; sizeHints.height = h ; + + wmHints.flags = StateHint; + wmHints.initial_state = NormalState ; + + PropMotifWmHints hints ; + Atom prop_t ; + Atom prop ; + + hints . flags = MWM_HINTS_DECORATIONS ; + hints . decorations = border ? MWM_DECOR_ALL : 0 ; + + prop_t = prop = XInternAtom ( currDisplay, "_MOTIF_WM_HINTS", True ) ; + + if ( prop != 0 ) + XChangeProperty ( currDisplay, currHandle, prop, prop_t, 32, + PropModeReplace, (unsigned char *) &hints, + PROP_MOTIF_WM_HINTS_ELEMENTS) ; + + XStringListToTextProperty ( (char **) &title, 1, &textProperty ) ; + + XSetWMProperties ( currDisplay, currHandle, + &textProperty, &textProperty, 0, 0, + &sizeHints, &wmHints, NULL ) ; + XSetWMProtocols ( currDisplay, currHandle, &delWinAtom , 1 ); + XMapWindow ( currDisplay, currHandle ) ; + glXMakeCurrent ( currDisplay, currHandle, currContext ) ; + + pwSetCursor ( PW_CURSOR_LEFT ) ; + +#ifdef GL_MULTISAMPLE_FILTER_HINT_NV + glHint ( GL_MULTISAMPLE_FILTER_HINT_NV, multisample ) ; +#endif + + kbCB = NULL ; + msCB = NULL ; + mpCB = NULL ; + resizeCB = NULL ; + exitCB = defaultExitFunc ; + + initialised = true ; + insideCallback = false ; + + glClear ( GL_COLOR_BUFFER_BIT ) ; + pwSwapBuffers () ; + glClear ( GL_COLOR_BUFFER_BIT ) ; + pwSwapBuffers () ; +} + + +void pwGetSize ( int *w, int *h ) +{ + if ( w ) *w = size[0] ; + if ( h ) *h = size[1] ; +} + + +void pwSetCursor ( int c ) +{ + switch ( c ) + { + case PW_CURSOR_RIGHT : currCursor = XC_right_ptr ; break ; + case PW_CURSOR_LEFT : currCursor = XC_left_ptr ; break ; + case PW_CURSOR_QUERY : currCursor = XC_question_arrow ; break ; + case PW_CURSOR_AIM : currCursor = XC_target ; break ; + case PW_CURSOR_CIRCLE : currCursor = XC_circle ; break ; + case PW_CURSOR_WAIT : currCursor = XC_watch ; break ; + case PW_CURSOR_CROSS : currCursor = XC_crosshair ; break ; + + case PW_CURSOR_NONE : + default: + { + Pixmap pix ; + char blank_cursor [ 16*16 ] = { 0 } ; + XColor bcol = { 0 } ; + + pix = XCreateBitmapFromData ( currDisplay, + rootWindow, + blank_cursor, 16, 16 ) ; + XDefineCursor ( currDisplay, currHandle, + XCreatePixmapCursor ( currDisplay, + pix, pix, &bcol, &bcol, 0, 0 ) ) ; + XFreePixmap ( currDisplay, pix ) ; + + currCursor = 0 ; + } + return ; + } + + XDefineCursor( currDisplay, currHandle, + XCreateFontCursor ( currDisplay, currCursor ) ) ; +} + + +void pwSetSize ( int w, int h ) +{ + XResizeWindow ( currDisplay, currHandle, w, h ) ; + XFlush ( currDisplay ) ; +} + + +void pwSetOrigin ( int x, int y ) +{ + XMoveWindow ( currDisplay, currHandle, x, y ) ; + XFlush ( currDisplay ) ; +} + + +void pwSetSizeOrigin ( int x, int y, int w, int h ) +{ + XMoveWindow ( currDisplay, currHandle, x, y ) ; + XResizeWindow ( currDisplay, currHandle, w, h ) ; + XFlush ( currDisplay ) ; +} + + +static void refreshModifiers( XEvent *event ) +{ + modifiers = 0 ; + + if( event->xkey.state & ( ShiftMask | LockMask ) ) modifiers |= PW_SHIFT ; + if( event->xkey.state & ControlMask ) modifiers |= PW_CTRL ; + if( event->xkey.state & Mod1Mask ) modifiers |= PW_ALT ; +} + + +int pwGetModifiers () +{ + return modifiers ; +} + + +static void getEvents () +{ + bool repeating = false ; + char keyflags [ 32 ] ; + XEvent event ; + + insideCallback = true ; + + while ( XPending ( currDisplay ) ) + { + int updown = PW_DOWN ; + + XNextEvent ( currDisplay, &event ) ; + + refreshModifiers ( &event ) ; + + switch ( event.type ) + { + case ClientMessage : (*exitCB)() ; break ; + case DestroyNotify : (*exitCB)() ; break ; + + case ConfigureNotify : + if ( currHandle == event.xconfigure.window && + ( size[0] != event.xconfigure.width || + size[1] != event.xconfigure.height ) ) + { + size[0] = event.xconfigure.width ; + size[1] = event.xconfigure.height ; + + glXMakeCurrent ( currDisplay, currHandle, currContext ) ; + glXWaitX () ; + + if ( resizeCB != NULL ) + (*resizeCB) ( size[0], size[1] ) ; + } + break; + + case MappingNotify: + XRefreshKeyboardMapping ( (XMappingEvent *) &event ) ; + break; + + case EnterNotify : + case LeaveNotify : + case VisibilityNotify: + case Expose : break ; + + case MotionNotify : + if ( mpCB ) + (*mpCB) ( event.xmotion.x, event.xmotion.y ) ; + break ; + + case ButtonRelease : + updown = PW_UP ; + /* FALLTHROUGH */ + + case ButtonPress : + { + int button = -1 ; + + switch ( event.xbutton.button ) + { + case 1 : button = PW_LEFT_BUTTON ; break ; + case 2 : button = PW_MIDDLE_BUTTON ; break ; + case 3 : button = PW_RIGHT_BUTTON ; break ; + } + + if ( button != -1 && msCB ) + (*msCB) ( button, updown, event.xbutton.x, event.xbutton.y ) ; + } + break ; + + case KeyRelease : + updown = PW_UP ; + + XQueryKeymap ( currDisplay, keyflags ) ; + + repeating = ( ( keyflags [ event.xkey.keycode >> 3 ] & + ( 1 << ( event.xkey.keycode & 7 ) ) ) != 0 ) ; + + /* FALLTHROUGH */ + + case KeyPress : + /* + Only generate a key up callback if the key is actually up + and not repeating. + */ + + if ( ! autoRepeat && repeating ) + break ; + + XComposeStatus composeStatus ; + char asciiCode [ 32 ] ; + KeySym keySym ; + + int len = XLookupString( &event.xkey, asciiCode, sizeof(asciiCode), + &keySym, &composeStatus ) ; + int result = -1 ; + + if( len > 0 ) + result = asciiCode[ 0 ] ; + else + { + switch( keySym ) + { + case XK_F1: result = PW_KEY_F1; break; + case XK_F2: result = PW_KEY_F2; break; + case XK_F3: result = PW_KEY_F3; break; + case XK_F4: result = PW_KEY_F4; break; + case XK_F5: result = PW_KEY_F5; break; + case XK_F6: result = PW_KEY_F6; break; + case XK_F7: result = PW_KEY_F7; break; + case XK_F8: result = PW_KEY_F8; break; + case XK_F9: result = PW_KEY_F9; break; + case XK_F10: result = PW_KEY_F10; break; + case XK_F11: result = PW_KEY_F11; break; + case XK_F12: result = PW_KEY_F12; break; + + case XK_Left: result = PW_KEY_LEFT; break; + case XK_Right: result = PW_KEY_RIGHT; break; + case XK_Up: result = PW_KEY_UP; break; + case XK_Down: result = PW_KEY_DOWN; break; + + case XK_KP_Prior: + case XK_Prior: result = PW_KEY_PAGE_UP; break; + case XK_KP_Next: + case XK_Next: result = PW_KEY_PAGE_DOWN; break; + case XK_KP_Home: + case XK_Home: result = PW_KEY_HOME; break; + case XK_KP_End: + case XK_End: result = PW_KEY_END; break; + case XK_KP_Insert: + case XK_Insert: result = PW_KEY_INSERT; break; + } + } + + if ( result != -1 && kbCB != NULL ) + (*kbCB) ( result, updown, event.xkey.x, event.xkey.y ) ; + + break ; + } + } + + insideCallback = false ; + + glXMakeCurrent ( currDisplay, currHandle, currContext ) ; +} + + +void pwSwapBuffers () +{ + if ( ! initialised ) + { + fprintf ( stderr, "PLIB/PW: FATAL - Application called pwSwapBuffers" + " before pwInit.\n" ) ; + exit ( 1 ) ; + } + + if ( insideCallback ) + { + fprintf ( stderr, "PLIB/PW: FATAL - Application called pwSwapBuffers" + " from inside a callback function.\n" ) ; + exit ( 1 ) ; + } + + glFlush () ; + glXSwapBuffers ( currDisplay, currHandle ) ; + getEvents () ; +} + + +#ifdef NEED_GAMMA +void pwSetGamma ( float g ) +{ + XF86VidModeGamma gamma ; + gamma.red = gamma.green = gamma.blue = g ; + XF86VidModeSetGamma ( currDisplay, currScreen, & gamma ) ; +} +#endif + + +void pwCleanup () +{ + if ( ! initialised ) + fprintf ( stderr, "PLIB/PW: WARNING - Application called pwCleanup" + " before pwInit.\n" ) ; + + glXDestroyContext ( currDisplay, currContext ) ; + XDestroyWindow ( currDisplay, currHandle ) ; + XFlush ( currDisplay ) ; +} + + +#endif + diff --git a/src/sg/Makefile.am b/src/sg/Makefile.am new file mode 100644 index 0000000..e3e4825 --- /dev/null +++ b/src/sg/Makefile.am @@ -0,0 +1,16 @@ +if BUILD_SG + +lib_LIBRARIES = libplibsg.a + +include_HEADERS = sg.h + +libplibsg_a_SOURCES = sg.cxx sgd.cxx \ + sgIsect.cxx sgdIsect.cxx \ + sgPerlinNoise.cxx + +INCLUDES = -I$(top_srcdir)/src/util + +endif + +EXTRA_DIST = sg.dsp + diff --git a/src/sg/sg.cxx b/src/sg/sg.cxx new file mode 100644 index 0000000..846e680 --- /dev/null +++ b/src/sg/sg.cxx @@ -0,0 +1,2080 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: sg.cxx 2163 2010-06-01 11:48:30Z fayjf $ +*/ + + +#include "sg.h" +#ifdef UL_WIN32 +# define isnan _isnan +# define finite _finite +#endif + + +sgVec3 _sgGravity = { 0.0f, 0.0f, -9.8f } ; + +void sgVectorProductVec3 ( sgVec3 dst, const sgVec3 a, const sgVec3 b ) +{ + dst[0] = a[1] * b[2] - a[2] * b[1] ; + dst[1] = a[2] * b[0] - a[0] * b[2] ; + dst[2] = a[0] * b[1] - a[1] * b[0] ; +} + +inline SGfloat _sgClampToUnity ( const SGfloat x ) +{ + if ( x > SG_ONE ) return SG_ONE ; + if ( x < -SG_ONE ) return -SG_ONE ; + return x ; +} + +int sgCompare3DSqdDist( const sgVec3 v1, const sgVec3 v2, const SGfloat sqd_dist ) +{ + sgVec3 tmp ; + + sgSubVec3 ( tmp, v2, v1 ) ; + + SGfloat sqdist = tmp[0] * tmp[0] + tmp[1] * tmp[1] + tmp[2] * tmp[2] ; + + if ( sqdist > sqd_dist ) return 1 ; + if ( sqdist < sqd_dist ) return -1 ; + return 0 ; +} + +void sgMakeRotMat4( sgMat4 mat, const SGfloat angle, const sgVec3 axis ) +{ + sgVec3 ax ; + sgNormalizeVec3 ( ax, axis ) ; + + SGfloat temp_angle = angle * SG_DEGREES_TO_RADIANS ; + SGfloat s = (SGfloat) sin ( temp_angle ) ; + SGfloat c = (SGfloat) cos ( temp_angle ) ; + SGfloat t = SG_ONE - c ; + + mat[0][0] = t * ax[0] * ax[0] + c ; + mat[0][1] = t * ax[0] * ax[1] + s * ax[2] ; + mat[0][2] = t * ax[0] * ax[2] - s * ax[1] ; + mat[0][3] = SG_ZERO ; + + mat[1][0] = t * ax[1] * ax[0] - s * ax[2] ; + mat[1][1] = t * ax[1] * ax[1] + c ; + mat[1][2] = t * ax[1] * ax[2] + s * ax[0] ; + mat[1][3] = SG_ZERO ; + + mat[2][0] = t * ax[2] * ax[0] + s * ax[1] ; + mat[2][1] = t * ax[2] * ax[1] - s * ax[0] ; + mat[2][2] = t * ax[2] * ax[2] + c ; + mat[2][3] = SG_ZERO ; + + mat[3][0] = SG_ZERO ; + mat[3][1] = SG_ZERO ; + mat[3][2] = SG_ZERO ; + mat[3][3] = SG_ONE ; +} + + + + +void sgMakePickMatrix( sgMat4 mat, sgFloat x, sgFloat y, + sgFloat width, sgFloat height, sgVec4 viewport ) +{ + sgFloat sx = viewport[2] / width ; + sgFloat sy = viewport[3] / height ; + sgFloat tx = ( viewport[2] + SG_TWO * (viewport[0] - x) ) / width ; + sgFloat ty = ( viewport[3] + SG_TWO * (viewport[1] - y) ) / height ; + + mat[0][0] = sx ; + mat[0][1] = SG_ZERO ; + mat[0][2] = SG_ZERO ; + mat[0][3] = SG_ZERO ; + + mat[1][0] = SG_ZERO ; + mat[1][1] = sy ; + mat[1][2] = SG_ZERO ; + mat[1][3] = SG_ZERO ; + + mat[2][0] = SG_ZERO ; + mat[2][1] = SG_ZERO ; + mat[2][2] = SG_ONE ; + mat[2][3] = SG_ZERO ; + + mat[3][0] = tx ; + mat[3][1] = ty ; + mat[3][2] = SG_ZERO ; + mat[3][3] = SG_ONE ; +} + + + +void sgMakeLookAtMat4 ( sgMat4 dst, const sgVec3 eye, + const sgVec3 center, + const sgVec3 up ) +{ + // Caveats: + // 1) In order to compute the line of sight, the eye point must not be equal + // to the center point. + // 2) The up vector must not be parallel to the line of sight from the eye + // to the center point. + + /* Compute the direction vectors */ + sgVec3 x,y,z; + + /* Y vector = center - eye */ + sgSubVec3 ( y, center, eye ) ; + + /* Z vector = up */ + sgCopyVec3 ( z, up ) ; + + /* X vector = Y cross Z */ + sgVectorProductVec3 ( x, y, z ) ; + + /* Recompute Z = X cross Y */ + sgVectorProductVec3 ( z, x, y ) ; + + /* Normalize everything */ + sgNormaliseVec3 ( x ) ; + sgNormaliseVec3 ( y ) ; + sgNormaliseVec3 ( z ) ; + + /* Build the matrix */ + sgSetVec4 ( dst[0], x[0], x[1], x[2], SG_ZERO ) ; + sgSetVec4 ( dst[1], y[0], y[1], y[2], SG_ZERO ) ; + sgSetVec4 ( dst[2], z[0], z[1], z[2], SG_ZERO ) ; + sgSetVec4 ( dst[3], eye[0], eye[1], eye[2], SG_ONE ) ; +} + +// -dw- inconsistent linkage! + +float sgTriArea( sgVec3 p0, sgVec3 p1, sgVec3 p2 ) +{ + /* + From comp.graph.algorithms FAQ + + 2A(P) = abs(N.(sum_{i=0}^{n-1}(v_i x v_{i+1}))) + This is an optimized version for a triangle + but easily extended for planar polygon's with more sides + by passing in the number of sides and the vv array + sgTriArea( int nsides, float **vv ) + and changing the normal calculation and the for loop appropriately + sgMakeNormal( norm, vv[0], vv[1], vv[2] ) + for( int i=0; i 0.99999 ) + deltaAngle = SG_PI*0.5; + else + deltaAngle = (SGfloat)asin((double)myNorm); + + // deltaAngle is in the range -SG_PI*0.5 to +SG_PI*0.5 here + // However, the correct result could also be + // deltaAngleS := pi - deltaAngle + // Please note that: + // cos(deltaAngleS)=cos(pi-deltaAngle)=-cos(deltaAngle) + // So, the question is whether + or - cos(deltaAngle) + // is sgScalarProductVec3(first, second) + + if ( deltaAngle < 0 ) + deltaAngle = deltaAngle + 2*SG_PI; // unnessecary? + + SProduct = sgScalarProductVec3(first, second); + myCos = (SGfloat) cos(deltaAngle); + + abs1 = SProduct - myCos; + abs2 = SProduct + myCos; + + if ( abs1 < 0 ) abs1 = -abs1 ; + if ( abs2 < 0 ) abs2 = -abs2 ; + + assert( (abs1 < 0.1) || (abs2 < 0.1) ) ; + + if ( abs2 < abs1 ) + { + // deltaAngleS is the correct result + + if ( deltaAngle <= SG_PI ) + deltaAngle = SG_PI - deltaAngle ; + else + deltaAngle = 3*SG_PI - deltaAngle ; + } + + assert ( deltaAngle >= 0.0 ) ; + assert ( deltaAngle <= 2.0*SG_PI ) ; + + return deltaAngle * SG_RADIANS_TO_DEGREES ; +} + + +SGfloat sgAngleBetweenVec3 ( sgVec3 v1, sgVec3 v2, sgVec3 normal ) +{ + // nornmal has to be normalized. + sgVec3 nv1, nv2 ; + + sgNormalizeVec3 ( nv1, v1 ) ; + sgNormalizeVec3 ( nv2, v2 ) ; + return sgAngleBetweenNormalizedVec3 ( nv1, nv2, normal ) ; +} + + +/*********************\ +* sgBox routines * +\*********************/ + + +void sgBox::extend ( const sgVec3 v ) +{ + if ( isEmpty () ) + { + sgCopyVec3 ( min, v ) ; + sgCopyVec3 ( max, v ) ; + } + else + { + if ( v[0] < min[0] ) min[0] = v[0] ; + if ( v[1] < min[1] ) min[1] = v[1] ; + if ( v[2] < min[2] ) min[2] = v[2] ; + if ( v[0] > max[0] ) max[0] = v[0] ; + if ( v[1] > max[1] ) max[1] = v[1] ; + if ( v[2] > max[2] ) max[2] = v[2] ; + } +} + + +void sgBox::extend ( const sgBox *b ) +{ + if ( b -> isEmpty () ) + return ; + + if ( isEmpty () ) + { + sgCopyVec3 ( min, b->getMin() ) ; + sgCopyVec3 ( max, b->getMax() ) ; + } + else + { + extend ( b->getMin() ) ; + extend ( b->getMax() ) ; + } +} + + +void sgBox::extend ( const sgSphere *s ) +{ + if ( s -> isEmpty () ) + return ; + + /* + In essence, this extends around a box around the sphere - which + is still a perfect solution because both boxes are axially aligned. + */ + + sgVec3 x ; + + sgSetVec3 ( x, s->getCenter()[0]+s->getRadius(), + s->getCenter()[1]+s->getRadius(), + s->getCenter()[2]+s->getRadius() ) ; + extend ( x ) ; + + sgSetVec3 ( x, s->getCenter()[0]-s->getRadius(), + s->getCenter()[1]-s->getRadius(), + s->getCenter()[2]-s->getRadius() ) ; + extend ( x ) ; +} + + +int sgBox::intersects ( const sgVec4 plane ) const +{ + /* + Save multiplies by not redoing Ax+By+Cz+D for each point. + */ + + SGfloat Ax_min = plane[0] * min[0] ; + SGfloat By_min = plane[1] * min[1] ; + SGfloat Cz_min_plus_D = plane[2] * min[2] + plane[3] ; + + SGfloat Ax_max = plane[0] * max[0] ; + SGfloat By_max = plane[1] * max[1] ; + SGfloat Cz_max_plus_D = plane[2] * max[2] + plane[3] ; + + /* + Count the number of vertices on the positive side of the plane. + */ + + int count = ( Ax_min + By_min + Cz_min_plus_D > SG_ZERO ) + + ( Ax_min + By_min + Cz_max_plus_D > SG_ZERO ) + + ( Ax_min + By_max + Cz_min_plus_D > SG_ZERO ) + + ( Ax_min + By_max + Cz_max_plus_D > SG_ZERO ) + + ( Ax_max + By_min + Cz_min_plus_D > SG_ZERO ) + + ( Ax_max + By_min + Cz_max_plus_D > SG_ZERO ) + + ( Ax_max + By_max + Cz_min_plus_D > SG_ZERO ) + + ( Ax_max + By_max + Cz_max_plus_D > SG_ZERO ) ; + + /* + The plane intersects the box unless all 8 are positive + or none of them are positive. + */ + + return count != 0 && count != 8 ; +} + + + +/**********************\ +* sgSphere routines * +\**********************/ + +void sgSphere::extend ( const sgVec3 v ) +{ + if ( isEmpty () ) + { + sgCopyVec3 ( center, v ) ; + radius = SG_ZERO ; + return ; + } + + SGfloat d = sgDistanceVec3 ( center, v ) ; + + if ( d <= radius ) /* Point is already inside sphere */ + return ; + + SGfloat new_radius = (radius + d) / SG_TWO ; /* Grow radius */ + + SGfloat ratio = (new_radius - radius) / d ; + + center[0] += (v[0]-center[0]) * ratio ; /* Move center */ + center[1] += (v[1]-center[1]) * ratio ; + center[2] += (v[2]-center[2]) * ratio ; + + radius = new_radius ; +} + + +void sgSphere::extend ( const sgBox *b ) +{ + if ( b -> isEmpty () ) + return ; + + if ( isEmpty() ) + { + sgAddVec3 ( center, b->getMin(), b->getMax() ) ; + sgScaleVec3 ( center, SG_HALF ) ; + radius = sgDistanceVec3 ( center, b->getMax() ) ; + return ; + } + + /* + I can't think of a faster way to get an + utterly minimal sphere. + + The tighter algorithm:- enclose each + of eight vertices of the box in turn - it + looks like being pretty costly. + [8 sqrt()'s] + + The looser algorithm:- enclose the box + with an empty sphere and then do a + sphere-extend-sphere. This algorithm + does well for close-to-cube boxes, but + makes very poor spheres for long, thin + boxes. + [2 sqrt()'s] + */ + +#ifdef DONT_REALLY_NEED_A_TIGHT_SPHERE_EXTEND_BOX + + /* LOOSER/FASTER sphere-around-sphere-around-box */ + sgSphere s ; + s.empty () ; + s.enclose ( b ) ; /* Fast because s is empty */ + enclose ( s ) ; + +#else + + /* TIGHTER/EXPENSIVE sphere-around-eight-points */ + sgVec3 x ; + extend ( b->getMin() ) ; + sgSetVec3 ( x, b->getMin()[0],b->getMin()[1],b->getMax()[2] ) ; extend ( x ) ; + sgSetVec3 ( x, b->getMin()[0],b->getMax()[1],b->getMin()[2] ) ; extend ( x ) ; + sgSetVec3 ( x, b->getMin()[0],b->getMax()[1],b->getMax()[2] ) ; extend ( x ) ; + sgSetVec3 ( x, b->getMax()[0],b->getMin()[1],b->getMin()[2] ) ; extend ( x ) ; + sgSetVec3 ( x, b->getMax()[0],b->getMin()[1],b->getMax()[2] ) ; extend ( x ) ; + sgSetVec3 ( x, b->getMax()[0],b->getMax()[1],b->getMin()[2] ) ; extend ( x ) ; + extend ( b->getMax() ) ; +#endif +} + + +void sgSphere::extend ( const sgSphere *s ) +{ + if ( s->isEmpty () ) + return ; + + if ( isEmpty () ) + { + sgCopyVec3 ( center, s->getCenter() ) ; + radius = s->getRadius() ; + return ; + } + + /* + d == The distance between the sphere centers + */ + + SGfloat d = sgDistanceVec3 ( center, s->getCenter() ) ; + + if ( d + s->getRadius() <= radius ) /* New sphere is already inside this one */ + return ; + + if ( d + radius <= s->getRadius() ) /* New sphere completely contains this one */ + { + sgCopyVec3 ( center, s->getCenter() ) ; + radius = s->getRadius() ; + return ; + } + + /* + Build a new sphere that completely contains the other two: + + The center point lies halfway along the line between + the furthest points on the edges of the two spheres. + Computing those two points is ugly - so we'll use similar + triangles + */ + + SGfloat new_radius = (radius + d + s->getRadius() ) / SG_TWO ; + + SGfloat ratio = ( new_radius - radius ) / d ; + + center[0] += ( s->getCenter()[0] - center[0] ) * ratio ; + center[1] += ( s->getCenter()[1] - center[1] ) * ratio ; + center[2] += ( s->getCenter()[2] - center[2] ) * ratio ; + radius = new_radius ; +} + + +int sgSphere::intersects ( const sgBox *b ) const +{ + sgVec3 closest ; + + if ( b->getMin()[0] > center[0] ) closest[0] = b->getMin()[0] ; else + if ( b->getMax()[0] < center[0] ) closest[0] = b->getMax()[0] ; else + closest[0] = center[0] ; + + if ( b->getMin()[1] > center[1] ) closest[1] = b->getMin()[1] ; else + if ( b->getMax()[1] < center[1] ) closest[1] = b->getMax()[1] ; else + closest[1] = center[1] ; + + if ( b->getMin()[2] > center[2] ) closest[2] = b->getMin()[2] ; else + if ( b->getMax()[2] < center[2] ) closest[2] = b->getMax()[2] ; else + closest[2] = center[2] ; + + return sgCompare3DSqdDist ( closest, center, sgSquare ( radius ) ) <= 0 ; +} + + +/************************\ +* sgFrustum routines * +\************************/ + +void sgFrustum::update () +{ + if ( fabs ( ffar - nnear ) < 0.1 ) + { + ulSetError ( UL_WARNING, "sgFrustum: Can't support depth of view <0.1 units."); + return ; + } + + if ( hfov != SG_ZERO && vfov != SG_ZERO ) + { + if ( fabs ( hfov ) < 0.1 || fabs ( vfov ) < 0.1 ) + { + ulSetError ( UL_WARNING, ortho ? + "sgFrustum: Can't support width or height <0.1 units." : + "sgFrustum: Can't support fields of view narrower than 0.1 degrees." ) ; + return ; + } + + if ( ortho ) + { + right = SG_HALF * hfov ; + top = SG_HALF * vfov ; + } + else + { + right = nnear * (SGfloat) tan ( hfov * SG_DEGREES_TO_RADIANS / SG_TWO ) ; + top = nnear * (SGfloat) tan ( vfov * SG_DEGREES_TO_RADIANS / SG_TWO ) ; + } + + left = -right ; + bot = -top ; + } + + + /* Compute the projection matrix */ + + SGfloat width = right - left ; + SGfloat height = top - bot ; + SGfloat depth = ffar - nnear ; + + if ( ortho ) + { + /* orthographic */ + + mat[0][0] = SG_TWO / width ; + mat[0][1] = SG_ZERO ; + mat[0][2] = SG_ZERO ; + mat[0][3] = SG_ZERO ; + + mat[1][0] = SG_ZERO ; + mat[1][1] = SG_TWO / height ; + mat[1][2] = SG_ZERO ; + mat[1][3] = SG_ZERO ; + + mat[2][0] = SG_ZERO ; + mat[2][1] = SG_ZERO ; + mat[2][2] = -SG_TWO / depth ; + mat[2][3] = SG_ZERO ; + + mat[3][0] = -( left + right ) / width ; + mat[3][1] = -( bot + top ) / height ; + mat[3][2] = -( nnear + ffar ) / depth ; + mat[3][3] = SG_ONE ; + } + else + { + /* perspective */ + + mat[0][0] = SG_TWO * nnear / width ; + mat[0][1] = SG_ZERO ; + mat[0][2] = SG_ZERO ; + mat[0][3] = SG_ZERO ; + + mat[1][0] = SG_ZERO ; + mat[1][1] = SG_TWO * nnear / height ; + mat[1][2] = SG_ZERO ; + mat[1][3] = SG_ZERO ; + + mat[2][0] = ( right + left ) / width ; + mat[2][1] = ( top + bot ) / height ; + mat[2][2] = -( ffar + nnear ) / depth ; + mat[2][3] = -SG_ONE ; + + mat[3][0] = SG_ZERO ; + mat[3][1] = SG_ZERO ; + mat[3][2] = -SG_TWO * nnear * ffar / depth ; + mat[3][3] = SG_ZERO ; + } + + + /* + * The clip planes are derived from the projection matrix. + * + * After projection (in clip coordinates), the clip planes are simply: + * + * left: ( 1, 0, 0, 1 ) + * right: ( -1, 0, 0, 1 ) + * bottom: ( 0, 1, 0, 1 ) + * top: ( 0, -1, 0, 1 ) + * near: ( 0, 0, 1, 1 ) + * far: ( 0, 0, -1, 1 ) + * + * These can easily be transformed *backwards* by + * multiplying by the transposed projection matrix, i.e: + * + * ( A ) ( A') + * ( B ) = mat^T ( B') + * ( C ) ( C') + * ( D ) ( D') + * + * where (A',B',C',D') represents a plane in clip coordinates, + * and (A,B,C,D) is the same plane expressed in eye coordinates. + */ + + sgSetVec4( plane[ SG_LEFT_PLANE ], SG_ONE, SG_ZERO, SG_ZERO, SG_ONE ); + sgSetVec4( plane[ SG_RIGHT_PLANE ], -SG_ONE, SG_ZERO, SG_ZERO, SG_ONE ); + sgSetVec4( plane[ SG_BOT_PLANE ], SG_ZERO, SG_ONE, SG_ZERO, SG_ONE ); + sgSetVec4( plane[ SG_TOP_PLANE ], SG_ZERO, -SG_ONE, SG_ZERO, SG_ONE ); + sgSetVec4( plane[ SG_NEAR_PLANE ], SG_ZERO, SG_ZERO, SG_ONE, SG_ONE ); + sgSetVec4( plane[ SG_FAR_PLANE ], SG_ZERO, SG_ZERO, -SG_ONE, SG_ONE ); + + for ( int i = 0 ; i < 6 ; i++ ) + { + sgVec4 tmp ; + + for ( int j = 0 ; j < 4 ; j++ ) + tmp[j] = sgScalarProductVec4 ( plane[i], mat[j] ) ; + + sgScaleVec4 ( plane[i], tmp, SG_ONE / sgLengthVec3 ( tmp ) ) ; + } +} + + + +#define OC_LEFT_SHIFT 0 +#define OC_RIGHT_SHIFT 1 +#define OC_TOP_SHIFT 2 +#define OC_BOT_SHIFT 3 +#define OC_NEAR_SHIFT 4 +#define OC_FAR_SHIFT 5 + +#define OC_ALL_ON_SCREEN 0x3F +#define OC_OFF_TRF ((1<= -tmp[3] ) << OC_LEFT_SHIFT ) | + (( tmp[1] <= tmp[3] ) << OC_TOP_SHIFT ) | + (( tmp[1] >= -tmp[3] ) << OC_BOT_SHIFT ) | + (( tmp[2] <= tmp[3] ) << OC_FAR_SHIFT ) | + (( tmp[2] >= -tmp[3] ) << OC_NEAR_SHIFT ) ; +} + +int sgFrustum::contains ( const sgVec3 pt ) const +{ + return getOutcode ( pt ) == OC_ALL_ON_SCREEN ; +} + + +int sgFrustum::contains ( const sgSphere *s ) const +{ + + const SGfloat *center = s->getCenter() ; + const SGfloat radius = s->getRadius() ; + + /* + Lop off half the database (roughly) with a quick near-plane test - and + lop off a lot more with a quick far-plane test + */ + + if ( -center[2] + radius < nnear || -center[2] - radius > ffar ) + return SG_OUTSIDE ; + + /* + OK, so the sphere lies between near and far. + + Measure the distance of the center point from the four sides of the frustum, + if it's outside by more than the radius then it's history. + + It's tempting to do a quick test to see if the center point is + onscreen using sgFrustumContainsPt - but that takes a matrix transform + which is 16 multiplies and 12 adds - versus this test which does the + whole task using only 12 multiplies and 8 adds. + */ + + /* + A few operations are saved by observing that certain values in the plane + equations are zero or one. These are specific to orthographic and perspective + projections respectively. + */ + + SGfloat sp1, sp2, sp3, sp4 ; + + if ( ortho ) + { + /* + left: ( 1, 0, 0, x ) + right: ( -1, 0, 0, x ) + bottom: ( 0, 1, 0, x ) + top: ( 0, -1, 0, x ) + */ + sp1 = plane[ SG_LEFT_PLANE ][3] + center[0] ; + sp2 = plane[ SG_RIGHT_PLANE ][3] - center[0] ; + sp3 = plane[ SG_BOT_PLANE ][3] + center[1] ; + sp4 = plane[ SG_TOP_PLANE ][3] - center[1] ; + } + else + { +#if 0 + /* + left: ( x, 0, x, 0 ) + right: ( x, 0, x, 0 ) + bottom: ( 0, x, x, 0 ) + top: ( 0, x, x, 0 ) + */ + sp1 = plane[ SG_LEFT_PLANE ][0] * center[0] + plane[ SG_LEFT_PLANE ][2] * center[2] ; + sp2 = plane[ SG_RIGHT_PLANE ][0] * center[0] + plane[ SG_RIGHT_PLANE ][2] * center[2] ; + sp3 = plane[ SG_BOT_PLANE ][1] * center[1] + plane[ SG_BOT_PLANE ][2] * center[2] ; + sp4 = plane[ SG_TOP_PLANE ][1] * center[1] + plane[ SG_TOP_PLANE ][2] * center[2] ; +#else + /* + Note: in the general case, we would have to do: + + sp1 = sgScalarProductVec3 ( left_plane, center ) + left_plane[3] ; + sp2 = sgScalarProductVec3 ( right_plane, center ) + right_plane[3] ; + ... + sp6 = sgScalarProductVec3 ( far_plane, center ) + far_plane[3] ; + */ + sp1 = sgScalarProductVec3 ( plane[ SG_LEFT_PLANE ], center ) + plane[ SG_LEFT_PLANE ][3] ; + sp2 = sgScalarProductVec3 ( plane[ SG_RIGHT_PLANE ], center ) + plane[ SG_RIGHT_PLANE ][3] ; + sp3 = sgScalarProductVec3 ( plane[ SG_BOT_PLANE ], center ) + plane[ SG_BOT_PLANE ][3] ; + sp4 = sgScalarProductVec3 ( plane[ SG_TOP_PLANE ], center ) + plane[ SG_TOP_PLANE ][3] ; +#endif + } + + if ( -sp1 > radius || -sp2 > radius || -sp3 > radius || -sp4 > radius ) + return SG_OUTSIDE ; + + /* + If it's inside by more than the radius then it's *completely* inside + and we can save time elsewhere if we know that for sure. + */ + + if ( sp1 >= radius && sp2 >= radius && sp3 >= radius && sp4 >= radius + && -center[2] - radius >= nnear && -center[2] + radius <= ffar ) + return SG_INSIDE ; + + return SG_STRADDLE ; +} + + +int sgFrustum::contains ( const sgBox *b ) const +{ + sgVec3 p[8] = { + { b->getMin()[0], b->getMin()[1], b->getMin()[2] }, + { b->getMax()[0], b->getMin()[1], b->getMin()[2] }, + { b->getMin()[0], b->getMax()[1], b->getMin()[2] }, + { b->getMax()[0], b->getMax()[1], b->getMin()[2] }, + { b->getMin()[0], b->getMin()[1], b->getMax()[2] }, + { b->getMax()[0], b->getMin()[1], b->getMax()[2] }, + { b->getMin()[0], b->getMax()[1], b->getMax()[2] }, + { b->getMax()[0], b->getMax()[1], b->getMax()[2] }, + } ; + + int all = -1 ; + int one = 0 ; + + for (int i = 0 ; i < 8 ; i++ ) + { + int tmp = ~ getOutcode ( p[i] ) ; + all &= tmp ; + one |= tmp ; + } + + return ( all ? SG_OUTSIDE : one ? SG_STRADDLE : SG_INSIDE ) ; +} + + + +SGfloat sgDistSquaredToLineVec3 ( const sgLine3 line, const sgVec3 pnt ) +{ + sgVec3 r ; sgSubVec3 ( r, pnt, line.point_on_line ) ; + + float projectedDistance = sgScalarProductVec3(r,line.direction_vector); + + return sgScalarProductVec3 ( r, r ) - + projectedDistance * projectedDistance; +} + + + +SGfloat sgDistSquaredToLineSegmentVec3 ( const sgLineSegment3 line, + const sgVec3 pnt ) +{ + sgVec3 v ; sgSubVec3 ( v, line.b, line.a ) ; + sgVec3 r1 ; sgSubVec3 ( r1, pnt, line.a ) ; + + SGfloat r1_dot_v = sgScalarProductVec3 ( r1, v ) ; + + if ( r1_dot_v <= 0 ) /* Off the "A" end */ + return sgScalarProductVec3 ( r1, r1 ) ; + + sgVec3 r2 ; sgSubVec3 ( r2, pnt, line.b ) ; + + SGfloat r2_dot_v = sgScalarProductVec3 ( r2, v ) ; + + if ( r2_dot_v >= 0 ) /* Off the "B" end */ + return sgScalarProductVec3 ( r2, r2 ) ; + + /* Closest point on line is on the line segment */ + + return sgScalarProductVec3 ( r1, r1 ) - r1_dot_v * r1_dot_v / sgScalarProductVec3 ( v, v ) ; +} + + + +void sgMakeCoordMat4 ( sgMat4 m, const SGfloat x, const SGfloat y, const SGfloat z, const SGfloat h, const SGfloat p, const SGfloat r ) +{ + SGfloat ch, sh, cp, sp, cr, sr, srsp, crsp, srcp ; + + if ( h == SG_ZERO ) + { + ch = SGD_ONE ; + sh = SGD_ZERO ; + } + else + { + sh = sgSin ( h ) ; + ch = sgCos ( h ) ; + } + + if ( p == SG_ZERO ) + { + cp = SGD_ONE ; + sp = SGD_ZERO ; + } + else + { + sp = sgSin ( p ) ; + cp = sgCos ( p ) ; + } + + if ( r == SG_ZERO ) + { + cr = SGD_ONE ; + sr = SGD_ZERO ; + srsp = SGD_ZERO ; + srcp = SGD_ZERO ; + crsp = sp ; + } + else + { + sr = sgSin ( r ) ; + cr = sgCos ( r ) ; + srsp = sr * sp ; + crsp = cr * sp ; + srcp = sr * cp ; + } + + m[0][0] = (SGfloat)( ch * cr - sh * srsp ) ; + m[1][0] = (SGfloat)( -sh * cp ) ; + m[2][0] = (SGfloat)( sr * ch + sh * crsp ) ; + m[3][0] = x ; + + m[0][1] = (SGfloat)( cr * sh + srsp * ch ) ; + m[1][1] = (SGfloat)( ch * cp ) ; + m[2][1] = (SGfloat)( sr * sh - crsp * ch ) ; + m[3][1] = y ; + + m[0][2] = (SGfloat)( -srcp ) ; + m[1][2] = (SGfloat)( sp ) ; + m[2][2] = (SGfloat)( cr * cp ) ; + m[3][2] = z ; + + m[0][3] = SG_ZERO ; + m[1][3] = SG_ZERO ; + m[2][3] = SG_ZERO ; + m[3][3] = SG_ONE ; +} + + +void sgMakeTransMat4 ( sgMat4 m, const sgVec3 xyz ) +{ + m[0][1] = m[0][2] = m[0][3] = + m[1][0] = m[1][2] = m[1][3] = + m[2][0] = m[2][1] = m[2][3] = SG_ZERO ; + m[0][0] = m[1][1] = m[2][2] = m[3][3] = SG_ONE ; + sgCopyVec3 ( m[3], xyz ) ; +} + + +void sgMakeTransMat4 ( sgMat4 m, const SGfloat x, const SGfloat y, const SGfloat z ) +{ + m[0][1] = m[0][2] = m[0][3] = + m[1][0] = m[1][2] = m[1][3] = + m[2][0] = m[2][1] = m[2][3] = SG_ZERO ; + m[0][0] = m[1][1] = m[2][2] = m[3][3] = SG_ONE ; + sgSetVec3 ( m[3], x, y, z ) ; +} + + +void sgSetCoord ( sgCoord *dst, const sgMat4 src ) +{ + sgCopyVec3 ( dst->xyz, src[3] ) ; + + sgMat4 mat ; + + SGfloat s = sgLengthVec3 ( src[0] ) ; + + if ( s <= 0.00001 ) + { + ulSetError ( UL_WARNING, "sgMat4ToCoord: ERROR - Bad Matrix." ) ; + sgSetVec3 ( dst -> hpr, SG_ZERO, SG_ZERO, SG_ZERO ) ; + return ; + } + + sgScaleMat4 ( mat, src, SG_ONE / s ) ; + + dst->hpr[1] = sgASin ( _sgClampToUnity ( mat[1][2] ) ) ; + + SGfloat cp = sgCos ( dst->hpr[1] ) ; + + /* If pointing nearly vertically up - then heading is ill-defined */ + + if ( cp > -0.00001 && cp < 0.00001 ) + { + SGfloat cr = _sgClampToUnity ( mat[0][1] ) ; + SGfloat sr = _sgClampToUnity (-mat[2][1] ) ; + + dst->hpr[0] = SG_ZERO ; + dst->hpr[2] = sgATan2 ( sr, cr ) ; + } + else + { + cp = SG_ONE / cp ; + SGfloat sr = _sgClampToUnity ( -mat[0][2] * cp ) ; + SGfloat cr = _sgClampToUnity ( mat[2][2] * cp ) ; + SGfloat sh = _sgClampToUnity ( -mat[1][0] * cp ) ; + SGfloat ch = _sgClampToUnity ( mat[1][1] * cp ) ; + + if ( (sh == SG_ZERO && ch == SG_ZERO) || (sr == SG_ZERO && cr == SG_ZERO) ) + { + cr = _sgClampToUnity ( mat[0][1] ) ; + sr = _sgClampToUnity (-mat[2][1] ) ; + + dst->hpr[0] = SG_ZERO ; + } + else + dst->hpr[0] = sgATan2 ( sh, ch ) ; + + dst->hpr[2] = sgATan2 ( sr, cr ) ; + } +} + + +void sgMakeNormal(sgVec2 dst, const sgVec2 a, const sgVec2 b ) +{ + sgSubVec2 ( dst, b, a ) ; + float tmp = dst [ 0 ] ; dst [ 0 ] = -dst [ 1 ] ; dst [ 1 ] = tmp ; + sgNormaliseVec2 ( dst ) ; +} + + +void sgMakeNormal(sgVec3 dst, const sgVec3 a, const sgVec3 b, const sgVec3 c ) +{ + sgVec3 ab ; sgSubVec3 ( ab, b, a ) ; + sgVec3 ac ; sgSubVec3 ( ac, c, a ) ; + sgVectorProductVec3 ( dst, ab,ac ) ; sgNormaliseVec3 ( dst ) ; +} + + +void sgPreMultMat4( sgMat4 dst, const sgMat4 src ) +{ + sgMat4 mat ; + sgMultMat4 ( mat, dst, src ) ; + sgCopyMat4 ( dst, mat ) ; +} + +void sgPostMultMat4( sgMat4 dst, const sgMat4 src ) +{ + sgMat4 mat ; + sgMultMat4 ( mat, src, dst ) ; + sgCopyMat4 ( dst, mat ) ; +} + +void sgMultMat4( sgMat4 dst, const sgMat4 m1, const sgMat4 m2 ) +{ + for ( int j = 0 ; j < 4 ; j++ ) + { + dst[0][j] = m2[0][0] * m1[0][j] + + m2[0][1] * m1[1][j] + + m2[0][2] * m1[2][j] + + m2[0][3] * m1[3][j] ; + + dst[1][j] = m2[1][0] * m1[0][j] + + m2[1][1] * m1[1][j] + + m2[1][2] * m1[2][j] + + m2[1][3] * m1[3][j] ; + + dst[2][j] = m2[2][0] * m1[0][j] + + m2[2][1] * m1[1][j] + + m2[2][2] * m1[2][j] + + m2[2][3] * m1[3][j] ; + + dst[3][j] = m2[3][0] * m1[0][j] + + m2[3][1] * m1[1][j] + + m2[3][2] * m1[2][j] + + m2[3][3] * m1[3][j] ; + } +} + + +void sgTransposeNegateMat4 ( sgMat4 dst, const sgMat4 src ) +{ + /* Poor man's invert - can be used when matrix is a simple rotate-translate */ + + dst[0][0] = src[0][0] ; + dst[1][0] = src[0][1] ; + dst[2][0] = src[0][2] ; + dst[3][0] = - sgScalarProductVec3 ( src[3], src[0] ) ; + + dst[0][1] = src[1][0] ; + dst[1][1] = src[1][1] ; + dst[2][1] = src[1][2] ; + dst[3][1] = - sgScalarProductVec3 ( src[3], src[1] ) ; + + dst[0][2] = src[2][0] ; + dst[1][2] = src[2][1] ; + dst[2][2] = src[2][2] ; + dst[3][2] = - sgScalarProductVec3 ( src[3], src[2] ) ; + + dst[0][3] = SG_ZERO ; + dst[1][3] = SG_ZERO ; + dst[2][3] = SG_ZERO ; + dst[3][3] = SG_ONE ; +} + + +void sgTransposeNegateMat4 ( sgMat4 dst ) +{ + sgMat4 src ; + sgCopyMat4 ( src, dst ) ; + sgTransposeNegateMat4 ( dst, src ) ; +} + + + +void sgInvertMat4 ( sgMat4 dst, const sgMat4 src ) +{ + sgMat4 tmp ; + + sgCopyMat4 ( tmp, src ) ; + sgMakeIdentMat4 ( dst ) ; + + for ( int i = 0 ; i != 4 ; i++ ) + { + SGfloat val = tmp[i][i] ; + int ind = i ; + int j ; + + for ( j = i + 1 ; j != 4 ; j++ ) + { + if ( fabs ( tmp[i][j] ) > fabs(val) ) + { + ind = j; + val = tmp[i][j] ; + } + } + + if ( ind != i ) + { /* swap columns */ + for ( j = 0 ; j != 4 ; j++ ) + { + SGfloat t ; + t = dst[j][i]; dst[j][i] = dst[j][ind]; dst[j][ind] = t ; + t = tmp[j][i]; tmp[j][i] = tmp[j][ind]; tmp[j][ind] = t ; + } + } + + // if ( val == SG_ZERO) + if ( fabs(val) <= FLT_EPSILON ) + { + ulSetError ( UL_WARNING, "sg: ERROR - Singular matrix, no inverse!" ) ; + sgMakeIdentMat4 ( dst ) ; /* Do *something* */ + return; + } + + SGfloat ival = SG_ONE / val ; + + for ( j = 0 ; j != 4 ; j++ ) + { + tmp[j][i] *= ival ; + dst[j][i] *= ival ; + } + + for (j = 0; j != 4; j++) + { + if ( j == i ) + continue ; + + val = tmp[i][j] ; + + for ( int k = 0 ; k != 4 ; k++ ) + { + tmp[k][j] -= tmp[k][i] * val ; + dst[k][j] -= dst[k][i] * val ; + } + } + } +} + + + +void sgXformVec3 ( sgVec3 dst, const sgVec3 src, const sgMat4 mat ) +{ + SGfloat t0 = src[ 0 ] ; + SGfloat t1 = src[ 1 ] ; + SGfloat t2 = src[ 2 ] ; + + dst[0] = t0 * mat[ 0 ][ 0 ] + + t1 * mat[ 1 ][ 0 ] + + t2 * mat[ 2 ][ 0 ] ; + + dst[1] = t0 * mat[ 0 ][ 1 ] + + t1 * mat[ 1 ][ 1 ] + + t2 * mat[ 2 ][ 1 ] ; + + dst[2] = t0 * mat[ 0 ][ 2 ] + + t1 * mat[ 1 ][ 2 ] + + t2 * mat[ 2 ][ 2 ] ; +} + + +void sgXformPnt3 ( sgVec3 dst, const sgVec3 src, const sgMat4 mat ) +{ + SGfloat t0 = src[ 0 ] ; + SGfloat t1 = src[ 1 ] ; + SGfloat t2 = src[ 2 ] ; + + dst[0] = t0 * mat[ 0 ][ 0 ] + + t1 * mat[ 1 ][ 0 ] + + t2 * mat[ 2 ][ 0 ] + + mat[ 3 ][ 0 ] ; + + dst[1] = t0 * mat[ 0 ][ 1 ] + + t1 * mat[ 1 ][ 1 ] + + t2 * mat[ 2 ][ 1 ] + + mat[ 3 ][ 1 ] ; + + dst[2] = t0 * mat[ 0 ][ 2 ] + + t1 * mat[ 1 ][ 2 ] + + t2 * mat[ 2 ][ 2 ] + + mat[ 3 ][ 2 ] ; +} + + +void sgXformPnt4 ( sgVec4 dst, const sgVec4 src, const sgMat4 mat ) +{ + SGfloat t0 = src[ 0 ] ; + SGfloat t1 = src[ 1 ] ; + SGfloat t2 = src[ 2 ] ; + SGfloat t3 = src[ 3 ] ; + + dst[0] = t0 * mat[ 0 ][ 0 ] + + t1 * mat[ 1 ][ 0 ] + + t2 * mat[ 2 ][ 0 ] + + t3 * mat[ 3 ][ 0 ] ; + + dst[1] = t0 * mat[ 0 ][ 1 ] + + t1 * mat[ 1 ][ 1 ] + + t2 * mat[ 2 ][ 1 ] + + t3 * mat[ 3 ][ 1 ] ; + + dst[2] = t0 * mat[ 0 ][ 2 ] + + t1 * mat[ 1 ][ 2 ] + + t2 * mat[ 2 ][ 2 ] + + t3 * mat[ 3 ][ 2 ] ; + + dst[3] = t0 * mat[ 0 ][ 3 ] + + t1 * mat[ 1 ][ 3 ] + + t2 * mat[ 2 ][ 3 ] + + t3 * mat[ 3 ][ 3 ] ; +} + + +void sgFullXformPnt3 ( sgVec3 dst, const sgVec3 src, const sgMat4 mat ) +{ + sgVec4 tmp ; + + tmp [ 0 ] = src [ 0 ] ; + tmp [ 1 ] = src [ 1 ] ; + tmp [ 2 ] = src [ 2 ] ; + tmp [ 3 ] = SG_ONE ; + + sgXformPnt4 ( tmp, tmp, mat ) ; + sgScaleVec3 ( dst, tmp, SG_ONE / tmp [ 3 ] ) ; +} + +void sgHPRfromVec3 ( sgVec3 hpr, const sgVec3 src ) +{ + sgVec3 tmp ; + sgCopyVec3 ( tmp, src ) ; + sgNormaliseVec3 ( tmp ) ; + hpr[0] = - sgATan2 ( tmp [ 0 ], tmp [ 1 ] ) ; + hpr[1] = - sgATan2 ( tmp [ 2 ], sgSqrt ( sgSquare ( tmp [ 0 ] ) + + sgSquare ( tmp [ 1 ] ) ) ) ; + hpr[2] = SG_ZERO ; +} + + + +/* + Quaternion routines are Copyright (C) 1999 + Kevin B. Thompson + Modified by Sylvan W. Clebsch + Largely rewritten by "Negative0" + More added by John Fay. +*/ + + +void sgQuatToAngleAxis ( SGfloat *angle, + SGfloat *x, SGfloat *y, SGfloat *z, + const sgQuat src ) +{ + sgVec3 axis ; + + sgQuatToAngleAxis ( angle, axis, src ) ; + + *x = axis [ 0 ] ; + *y = axis [ 1 ] ; + *z = axis [ 2 ] ; +} + + +void sgQuatToAngleAxis ( SGfloat *angle, sgVec3 axis, const sgQuat src ) +{ + SGfloat a = (SGfloat) acos ( src[SG_W] ) ; + if ( isnan(a) || !finite(a) ) { + ulSetError(UL_WARNING,"sgQuatToAngleAxis: acos(%f) %f",src[SG_W],a); + if ( src[SG_W] >= 1 ) a = 0; + else if ( src[SG_W] <= -1 ) a = SG_PI; + ulSetError(UL_WARNING," - recovered to %f\n",a); + } + + SGfloat s = (SGfloat) sin ( a ) ; + + *angle = a * SG_RADIANS_TO_DEGREES * SG_TWO ; + + if ( s == SG_ZERO ) + sgSetVec3 ( axis, SG_ZERO, SG_ZERO, SG_ONE ); + else + { + sgSetVec3 ( axis, src[SG_X], src[SG_Y], src[SG_Z] ) ; + sgScaleVec3 ( axis, SG_ONE / s ) ; + } +} + + +void sgAngleAxisToQuat ( sgQuat dst, + const SGfloat angle, + const SGfloat x, const SGfloat y, const SGfloat z ) +{ + sgVec3 axis ; + sgSetVec3 ( axis, x, y, z ) ; + sgAngleAxisToQuat ( dst, angle, axis ) ; +} + + +void sgAngleAxisToQuat ( sgQuat dst, const SGfloat angle, const sgVec3 axis ) +{ + SGfloat temp_angle = angle * SG_DEGREES_TO_RADIANS / SG_TWO ; + + sgVec3 ax ; + sgNormaliseVec3 ( ax, axis ) ; + + SGfloat s = - (SGfloat) sin ( temp_angle ) ; + + dst[SG_W] = (SGfloat) cos ( temp_angle ) ; + sgScaleVec3 ( dst, ax, s ) ; +} + + +//from gamasutra.com +//by nb + +void sgMatrixToQuat( sgQuat quat, const sgMat4 m ) +{ + SGfloat tr, s, q[4] ; + int i, j, k ; + + int nxt[3] = {1, 2, 0}; + + tr = m[0][0] + m[1][1] + m[2][2]; + + // check the diagonal + if (tr > SG_ZERO ) + { + s = (SGfloat) sgSqrt (tr + SG_ONE); + quat[SG_W] = s / SG_TWO; + s = SG_HALF / s; + quat[SG_X] = (m[1][2] - m[2][1]) * s; + quat[SG_Y] = (m[2][0] - m[0][2]) * s; + quat[SG_Z] = (m[0][1] - m[1][0]) * s; + } + else + { + // diagonal is negative + i = 0; + if (m[1][1] > m[0][0]) i = 1; + if (m[2][2] > m[i][i]) i = 2; + j = nxt[i]; + k = nxt[j]; + s = (SGfloat) sgSqrt ((m[i][i] - (m[j][j] + m[k][k])) + SG_ONE); + q[i] = s * SG_HALF; + + if (s != SG_ZERO) s = SG_HALF / s; + + q[3] = (m[j][k] - m[k][j]) * s; + q[j] = (m[i][j] + m[j][i]) * s; + q[k] = (m[i][k] + m[k][i]) * s; + + quat[SG_X] = q[0]; + quat[SG_Y] = q[1]; + quat[SG_Z] = q[2]; + quat[SG_W] = q[3]; + } + + // seems to yield the inverse rotation, so: + quat[SG_W] = - quat[SG_W]; +} + + +void sgMultQuat ( sgQuat dst, const sgQuat a, const sgQuat b ) +{ + /* [ ww' - v.v', vxv' + wv' + v'w ] */ + + SGfloat t[8]; + + t[0] = (a[SG_W] + a[SG_X]) * (b[SG_W] + b[SG_X]); + t[1] = (a[SG_Z] - a[SG_Y]) * (b[SG_Y] - b[SG_Z]); + t[2] = (a[SG_X] - a[SG_W]) * (b[SG_Y] + b[SG_Z]); + t[3] = (a[SG_Y] + a[SG_Z]) * (b[SG_X] - b[SG_W]); + t[4] = (a[SG_X] + a[SG_Z]) * (b[SG_X] + b[SG_Y]); + t[5] = (a[SG_X] - a[SG_Z]) * (b[SG_X] - b[SG_Y]); + t[6] = (a[SG_W] + a[SG_Y]) * (b[SG_W] - b[SG_Z]); + t[7] = (a[SG_W] - a[SG_Y]) * (b[SG_W] + b[SG_Z]); + + dst[SG_W] = t[1] + ((-t[4] - t[5] + t[6] + t[7]) * SG_HALF); + dst[SG_X] = t[0] - (( t[4] + t[5] + t[6] + t[7]) * SG_HALF); + dst[SG_Y] = -t[2] + (( t[4] - t[5] + t[6] - t[7]) * SG_HALF); + dst[SG_Z] = -t[3] + (( t[4] - t[5] - t[6] + t[7]) * SG_HALF); +} + +//from gamasutra.com +//by nb@netcom.ca + +void sgMultQuat2 ( sgQuat dst, const sgQuat a, const sgQuat b ) +{ + SGfloat A, B, C, D, E, F, G, H; + + A = (a[SG_W] + a[SG_X]) * (b[SG_W] + b[SG_X]) ; + B = (a[SG_Z] - a[SG_Y]) * (b[SG_Y] - b[SG_Z]) ; + C = (a[SG_X] - a[SG_W]) * (b[SG_Y] + b[SG_Z]) ; + D = (a[SG_Y] + a[SG_Z]) * (b[SG_X] - b[SG_W]) ; + E = (a[SG_X] + a[SG_Z]) * (b[SG_X] + b[SG_Y]) ; + F = (a[SG_X] - a[SG_Z]) * (b[SG_X] - b[SG_Y]) ; + G = (a[SG_W] + a[SG_Y]) * (b[SG_W] - b[SG_Z]) ; + H = (a[SG_W] - a[SG_Y]) * (b[SG_W] + b[SG_Z]) ; + + + dst[SG_W] = B + (-E - F + G + H) / SG_TWO ; + dst[SG_X] = A - ( E + F + G + H) / SG_TWO ; + dst[SG_Y] = -C + ( E - F + G - H) / SG_TWO ; + dst[SG_Z] = -D + ( E - F - G + H) / SG_TWO ; +} + +//from gamasutra.com +//by nb@netcom.ca + +void sgEulerToQuat(sgQuat quat, const sgVec3 hpr ) +{ + SGfloat cr, cp, cy, sr, sp, sy, cpcy, spsy; + +// calculate trig identities + cr = (SGfloat) cos(hpr[2]*SG_DEGREES_TO_RADIANS/SG_TWO); + cp = (SGfloat) cos(hpr[1]*SG_DEGREES_TO_RADIANS/SG_TWO); + cy = (SGfloat) cos(hpr[0]*SG_DEGREES_TO_RADIANS/SG_TWO); + + sr = (SGfloat) sin(hpr[2]*SG_DEGREES_TO_RADIANS/SG_TWO); + sp = (SGfloat) sin(hpr[1]*SG_DEGREES_TO_RADIANS/SG_TWO); + sy = (SGfloat) sin(hpr[0]*SG_DEGREES_TO_RADIANS/SG_TWO); + + cpcy = cp * cy; + spsy = sp * sy; + + quat[SG_W] = cr * cpcy + sr * spsy; + quat[SG_X] = sr * cpcy - cr * spsy; + quat[SG_Y] = cr * sp * cy + sr * cp * sy; + quat[SG_Z] = cr * cp * sy - sr * sp * cy; +} + +//from darwin3d.com +// jeffl@darwin3d.com + +void sgQuatToEuler( sgVec3 hpr, const sgQuat quat ) +{ + SGfloat matrix[3][3]; + SGfloat cx,sx; + SGfloat cy,sy; + SGfloat cz,sz; + + // CONVERT QUATERNION TO MATRIX - I DON'T REALLY NEED ALL OF IT + + matrix[0][0] = SG_ONE - (SG_TWO * quat[SG_Y] * quat[SG_Y]) + - (SG_TWO * quat[SG_Z] * quat[SG_Z]); +//matrix[0][1] = (SG_TWO * quat->x * quat->y) - (SG_TWO * quat->w * quat->z); +//matrix[0][2] = (SG_TWO * quat->x * quat->z) + (SG_TWO * quat->w * quat->y); + + matrix[1][0] = (SG_TWO * quat[SG_X] * quat[SG_Y]) + + (SG_TWO * quat[SG_W] * quat[SG_Z]); +//matrix[1][1] = SG_ONE - (SG_TWO * quat->x * quat->x) +// - (SG_TWO * quat->z * quat->z); +//matrix[1][2] = (SG_TWO * quat->y * quat->z) - (SG_TWO * quat->w * quat->x); + + matrix[2][0] = (SG_TWO * quat[SG_X] * quat[SG_Z]) - + (SG_TWO * quat[SG_W] * quat[SG_Y]); + matrix[2][1] = (SG_TWO * quat[SG_Y] * quat[SG_Z]) + + (SG_TWO * quat[SG_W] * quat[SG_X]); + matrix[2][2] = SG_ONE - (SG_TWO * quat[SG_X] * quat[SG_X]) + - (SG_TWO * quat[SG_Y] * quat[SG_Y]); + + sy = -matrix[2][0]; + cy = (SGfloat)sgSqrt(SG_ONE - (sy * sy)); + + hpr[1] = sgATan2 ( sy, cy ) ; + + // AVOID DIVIDE BY ZERO ERROR ONLY WHERE Y= +-90 or +-270 + // NOT CHECKING cy BECAUSE OF PRECISION ERRORS + if (sy != SG_ONE && sy != -SG_ONE) + { + cx = matrix[2][2] / cy; + sx = matrix[2][1] / cy; + hpr[0] = sgATan2 ( sx, cx ) ; + + cz = matrix[0][0] / cy; + sz = matrix[1][0] / cy; + hpr[2] = sgATan2 ( sz, cz ) ; + } + else + { + // SINCE Cos(Y) IS 0, I AM SCREWED. ADOPT THE STANDARD Z = 0 + // I THINK THERE IS A WAY TO FIX THIS BUT I AM NOT SURE. EULERS SUCK + // NEED SOME MORE OF THE MATRIX TERMS NOW + + matrix[1][1] = SG_ONE - (SG_TWO * quat[SG_X] * quat[SG_X]) + - (SG_TWO * quat[SG_Z] * quat[SG_Z]); + matrix[1][2] = (SG_TWO * quat[SG_Y] * quat[SG_Z]) - + (SG_TWO * quat[SG_W] * quat[SG_X]); + + cx = matrix[1][1]; + sx = -matrix[1][2]; + hpr[0] = sgATan2 ( sx, cx ) ; + + cz = SG_ONE ; + sz = SG_ZERO ; + hpr[2] = sgATan2 ( sz, cz ) ; + } +} + + +void sgQuatToMatrix ( sgMat4 dst, const sgQuat q ) +{ + SGfloat two_xx = q[SG_X] * (q[SG_X] + q[SG_X]) ; + SGfloat two_xy = q[SG_X] * (q[SG_Y] + q[SG_Y]) ; + SGfloat two_xz = q[SG_X] * (q[SG_Z] + q[SG_Z]) ; + + SGfloat two_wx = q[SG_W] * (q[SG_X] + q[SG_X]) ; + SGfloat two_wy = q[SG_W] * (q[SG_Y] + q[SG_Y]) ; + SGfloat two_wz = q[SG_W] * (q[SG_Z] + q[SG_Z]) ; + + SGfloat two_yy = q[SG_Y] * (q[SG_Y] + q[SG_Y]) ; + SGfloat two_yz = q[SG_Y] * (q[SG_Z] + q[SG_Z]) ; + + SGfloat two_zz = q[SG_Z] * (q[SG_Z] + q[SG_Z]) ; + + sgSetVec4 ( dst[0], SG_ONE-(two_yy+two_zz), two_xy-two_wz, two_xz+two_wy, SG_ZERO ) ; + sgSetVec4 ( dst[1], two_xy+two_wz, SG_ONE-(two_xx+two_zz), two_yz-two_wx, SG_ZERO ) ; + sgSetVec4 ( dst[2], two_xz-two_wy, two_yz+two_wx, SG_ONE-(two_xx+two_yy), SG_ZERO ) ; + sgSetVec4 ( dst[3], SG_ZERO, SG_ZERO, SG_ZERO, SG_ONE ) ; +} + + +//from gamasutra.com +//by nb@netcom.ca + +/***************************** + DEPRECATED...use sgQuatToMatrix instead. +*****************************/ + +void sgMakeRotMat42( sgMat4 m, sgQuat quat ){ + SGfloat wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2; + + // calculate coefficients + x2 = quat[SG_X] + quat[SG_X]; y2 = quat[SG_Y] + quat[SG_Y]; + z2 = quat[SG_Z] + quat[SG_Z]; + xx = quat[SG_X] * x2; xy = quat[SG_X] * y2; xz = quat[SG_X] * z2; + yy = quat[SG_Y] * y2; yz = quat[SG_Y] * z2; zz = quat[SG_Z] * z2; + wx = quat[SG_W] * x2; wy = quat[SG_W] * y2; wz = quat[SG_W] * z2; + + m[0][0] = SG_ONE- (yy + zz); m[0][1] = xy - wz; + m[0][2] = xz + wy; m[0][3] = SG_ZERO ; + + m[1][0] = xy + wz; m[1][1] = SG_ONE- (xx + zz); + m[1][2] = yz - wx; m[1][3] = SG_ZERO ; + + m[2][0] = xz - wy; m[2][1] = yz + wx; + m[2][2] = SG_ONE- (xx + yy); m[2][3] = SG_ZERO ; + + m[3][0] = 0; m[3][1] = 0; + m[3][2] = 0; m[3][3] = 1; +} + +//from gamasutra.com +//by nb@netcom.ca + +void sgSlerpQuat2( sgQuat dst, const sgQuat from, const sgQuat to, const SGfloat t ) +{ + SGfloat to1[4]; + SGfloat omega, cosom, sinom, scale0, scale1; + + // calc cosine + cosom = from[SG_X] * to[SG_X] + + from[SG_Y] * to[SG_Y] + + from[SG_Z] * to[SG_Z] + + from[SG_W] * to[SG_W]; + + // adjust signs (if necessary) + + if ( cosom < SG_ZERO ) + { + cosom = -cosom; + to1[0] = - to[SG_X]; + to1[1] = - to[SG_Y]; + to1[2] = - to[SG_Z]; + to1[3] = - to[SG_W]; + } + else + { + to1[0] = to[SG_X]; + to1[1] = to[SG_Y]; + to1[2] = to[SG_Z]; + to1[3] = to[SG_W]; + } + + // calculate coefficients +#define DELTA SG_ZERO + if ( (SG_ONE- cosom) > DELTA ) + { + // standard case (slerp) + omega = (SGfloat) acos(cosom); + sinom = (SGfloat) sin(omega); + scale0 = (SGfloat) sin((SG_ONE- t) * omega) / sinom; + scale1 = (SGfloat) sin(t * omega) / sinom; + } + else + { + // "from" and "to" quaternions are very close + // ... so we can do a linear interpolation + scale0 = SG_ONE- t; + scale1 = t; + } + + // calculate final values + dst[SG_X] = scale0 * from[SG_X] + scale1 * to1[0]; + dst[SG_Y] = scale0 * from[SG_Y] + scale1 * to1[1]; + dst[SG_Z] = scale0 * from[SG_Z] + scale1 * to1[2]; + dst[SG_W] = scale0 * from[SG_W] + scale1 * to1[3]; +} + +void sgSlerpQuat( sgQuat dst, const sgQuat from, const sgQuat to, const SGfloat t ) +{ + SGfloat co, scale0, scale1; + bool flip = false ; + + /* SWC - Interpolate between to quaternions */ + + co = sgScalarProductVec4 ( from, to ) ; + + if ( co < SG_ZERO ) + { + co = -co; + flip = true ; + } + + if ( co < SG_ONE - (SGfloat) 1e-6 ) + { + SGfloat o = (SGfloat) acos ( co ); + SGfloat so = SG_ONE / (SGfloat) sin ( o ); + + scale0 = (SGfloat) sin ( (SG_ONE - t) * o ) * so; + scale1 = (SGfloat) sin ( t * o ) * so; + } + else + { + scale0 = SG_ONE - t; + scale1 = t; + } + + if ( flip ) + { + scale1 = -scale1 ; + } + + dst[SG_X] = scale0 * from[SG_X] + scale1 * to[SG_X] ; + dst[SG_Y] = scale0 * from[SG_Y] + scale1 * to[SG_Y] ; + dst[SG_Z] = scale0 * from[SG_Z] + scale1 * to[SG_Z] ; + dst[SG_W] = scale0 * from[SG_W] + scale1 * to[SG_W] ; +} + + + +/* Function to rotate a vector through a given quaternion using the formula + * R = Q r Q-1 -- this gives the components of a ROTATED vector in a STATIONARY + * coordinate system. We assume that Q is a unit quaternion. + */ +void sgRotateVecQuat ( sgVec3 vec, sgQuat q ) +{ + sgVec3 rot ; + sgFloat qwqw = q[SG_W] * q[SG_W] ; + sgFloat qwqx = q[SG_W] * q[SG_X] ; + sgFloat qwqy = q[SG_W] * q[SG_Y] ; + sgFloat qwqz = q[SG_W] * q[SG_Z] ; + sgFloat qxqx = q[SG_X] * q[SG_X] ; + sgFloat qxqy = q[SG_X] * q[SG_Y] ; + sgFloat qxqz = q[SG_X] * q[SG_Z] ; + sgFloat qyqy = q[SG_Y] * q[SG_Y] ; + sgFloat qyqz = q[SG_Y] * q[SG_Z] ; + sgFloat qzqz = q[SG_Z] * q[SG_Z] ; + rot[SG_X] = ( qwqw + qxqx - qyqy - qzqz ) * vec[SG_X] + 2.0f * ( qxqy - qwqz ) * vec[SG_Y] + 2.0f * ( qxqz + qwqy ) * vec[SG_Z] ; + rot[SG_Y] = ( qwqw - qxqx + qyqy - qzqz ) * vec[SG_Y] + 2.0f * ( qyqz - qwqx ) * vec[SG_Z] + 2.0f * ( qxqy + qwqz ) * vec[SG_X] ; + rot[SG_Z] = ( qwqw - qxqx - qyqy + qzqz ) * vec[SG_Z] + 2.0f * ( qxqz - qwqy ) * vec[SG_X] + 2.0f * ( qyqz + qwqx ) * vec[SG_Y] ; + sgCopyVec3 ( vec, rot ) ; +} + +/* Function to rotate a vector through a given quaternion using the formula + * R = Q-1 r Q -- this gives the components of a STATIONARY vector in a ROTATED + * coordinate system. We assume that Q is a unit quaternion. + */ +void sgRotateCoordQuat ( sgVec3 vec, sgQuat q ) +{ + sgVec3 rot ; + sgFloat qwqw = q[SG_W] * q[SG_W] ; + sgFloat qwqx = q[SG_W] * q[SG_X] ; + sgFloat qwqy = q[SG_W] * q[SG_Y] ; + sgFloat qwqz = q[SG_W] * q[SG_Z] ; + sgFloat qxqx = q[SG_X] * q[SG_X] ; + sgFloat qxqy = q[SG_X] * q[SG_Y] ; + sgFloat qxqz = q[SG_X] * q[SG_Z] ; + sgFloat qyqy = q[SG_Y] * q[SG_Y] ; + sgFloat qyqz = q[SG_Y] * q[SG_Z] ; + sgFloat qzqz = q[SG_Z] * q[SG_Z] ; + rot[SG_X] = ( qwqw + qxqx - qyqy - qzqz ) * vec[SG_X] + 2.0f * ( qxqy + qwqz ) * vec[SG_Y] + 2.0f * ( qxqz - qwqy ) * vec[SG_Z] ; + rot[SG_Y] = ( qwqw - qxqx + qyqy - qzqz ) * vec[SG_Y] + 2.0f * ( qyqz + qwqx ) * vec[SG_Z] + 2.0f * ( qxqy - qwqz ) * vec[SG_X] ; + rot[SG_Z] = ( qwqw - qxqx - qyqy + qzqz ) * vec[SG_Z] + 2.0f * ( qxqz + qwqy ) * vec[SG_X] + 2.0f * ( qyqz - qwqx ) * vec[SG_Y] ; + sgCopyVec3 ( vec, rot ) ; +} + + +sgFloat sgDistSquaredToLineLineSegment ( const sgLineSegment3 seg, const sgLine3 line ) +{ + /* Convert the line segment to a line. We will deal with the segment limits later. */ + sgLine3 line2 ; + sgLineSegment3ToLine3 ( &line2, seg ) ; + + /* Get the dot product of the two direction vectors */ + sgFloat t1_dot_t2 = sgScalarProductVec3 ( line.direction_vector, line2.direction_vector ) ; + + /* If the lines are parallel, distance is just the distance from a point to the other line */ + if ( fabs ( t1_dot_t2 ) >= 1.0 ) + return sgDistSquaredToLineVec3 ( line, seg.a ) ; + + /* Get the parametric coordinates of the closest points on the two lines. The first line + * is parameterized by r = r1 + t1 u while the second is parameterized by r = r2 + t2 v. + * The square of the distance between them is [ ( r1 + t1 u ) - ( r2 + t2 v ) ] dot + * [ ( r1 + t1 u ) - ( r2 + t2 v ) ]. Differentiating this dot product with respect to + * u and v and setting the derivatives to zero gives a matrix equation: + * [ 1 -(t1 dot t2) ] [ u ] = [ ( r1 - r2 ) dot t1 ] + * [ -(t1 dot t2) 1 ] [ v ] [ -( r1 - r2 ) dot t2 ] + * We invert the matrix to get the equations below. + */ + sgVec3 r1_minus_r2 ; + sgSubVec3 ( r1_minus_r2, line.point_on_line, line2.point_on_line ) ; + + /* t1_t2_t2_minus_t1 = ( t1 dot t2 ) t2 - t1 + * t2_minus_t1_t2_t1 = t2 - ( t1 dot t2 ) t1 + */ + sgVec3 t1_t2_t2_minus_t1, t2_minus_t1_t2_t1 ; + sgAddScaledVec3 ( t1_t2_t2_minus_t1, line.direction_vector, line2.direction_vector, -t1_dot_t2 ) ; + sgNegateVec3 ( t1_t2_t2_minus_t1 ) ; + sgAddScaledVec3 ( t2_minus_t1_t2_t1, line2.direction_vector, line.direction_vector, -t1_dot_t2 ) ; + + sgFloat u = sgScalarProductVec3 ( r1_minus_r2, t1_t2_t2_minus_t1 ) / ( 1.0f - t1_dot_t2 * t1_dot_t2 ) ; + sgFloat v = sgScalarProductVec3 ( r1_minus_r2, t2_minus_t1_t2_t1 ) / ( 1.0f - t1_dot_t2 * t1_dot_t2 ) ; + + /* Since line 2 is a line segment, we limit "v" to between 0 and the distance between the points. */ + sgFloat length = sgDistanceVec3 ( seg.a, seg.b ) ; + if ( v < 0.0 ) v = 0.0 ; + if ( v > length ) v = length ; + + sgVec3 point1, point2 ; + sgAddScaledVec3 ( point1, line.point_on_line, line.direction_vector, u ) ; + sgAddScaledVec3 ( point2, line2.point_on_line, line2.direction_vector, v ) ; + return sgDistanceSquaredVec3 ( point1, point2 ) ; +} + + +void sgReflectInPlaneVec3 ( sgVec3 dst, const sgVec3 src, const sgVec4 plane ) +{ + SGfloat src_dot_norm = sgScalarProductVec3 ( src, plane ) ; + + sgVec3 tmp ; + + sgScaleVec3 ( tmp, plane, SG_TWO * src_dot_norm ) ; + sgSubVec3 ( dst, src, tmp ) ; +} + + + +int sgClassifyMat4 ( const sgMat4 m ) +{ + const SGfloat epsilon = 1e-6f ; + + int flags = 0 ; + + + SGfloat sx, sy, sz ; + + if ( m[0][1] == SG_ZERO && m[0][2] == SG_ZERO && + m[1][0] == SG_ZERO && m[1][2] == SG_ZERO && + m[2][0] == SG_ZERO && m[2][1] == SG_ZERO ) + { + + int n = ( m[0][0] < 0 ) + ( m[1][1] < 0 ) + ( m[2][2] < 0 ) ; + + if ( n > 1 ) + flags |= SG_ROTATION ; + + if ( n % 2 != 0 ) + flags |= SG_MIRROR ; + + sx = m[0][0] * m[0][0] ; + sy = m[1][1] * m[1][1] ; + sz = m[2][2] * m[2][2] ; + + } + else + { + + flags |= SG_ROTATION ; + + if ( sgAbs ( sgScalarProductVec3 ( m[1], m[2] ) ) > epsilon || + sgAbs ( sgScalarProductVec3 ( m[2], m[0] ) ) > epsilon || + sgAbs ( sgScalarProductVec3 ( m[0], m[1] ) ) > epsilon ) + { + flags |= SG_NONORTHO ; + } + + sgVec3 temp ; + sgVectorProductVec3 ( temp, m[0], m[1] ) ; + SGfloat det = sgScalarProductVec3 ( temp, m[2] ) ; + + if ( det < 0 ) + flags |= SG_MIRROR ; + + sx = sgScalarProductVec3 ( m[0], m[0] ) ; + sy = sgScalarProductVec3 ( m[1], m[1] ) ; + sz = sgScalarProductVec3 ( m[2], m[2] ) ; + + } + + + if ( sgAbs ( sx - sy ) > epsilon || + sgAbs ( sx - sz ) > epsilon ) + { + flags |= SG_NONORTHO ; + flags |= SG_GENERAL_SCALE ; // also set general scale bit, though it may be deleted in the future + } + else + { + if ( sgAbs ( sx - SG_ONE ) > epsilon ) + flags |= SG_SCALE ; + } + + + if ( m[3][0] != SG_ZERO || m[3][1] != SG_ZERO || m[3][2] != SG_ZERO ) + { + flags |= SG_TRANSLATION ; + } + + + if ( m[0][3] != SG_ZERO || m[1][3] != SG_ZERO || m[2][3] != SG_ZERO || + m[3][3] != SG_ONE ) + { + flags |= SG_PROJECTION ; + } + + + return flags ; +} + + +SGfloat sgTriangleSolver_ASAtoArea ( SGfloat angA, SGfloat lenB, SGfloat angC ) +{ + /* Get the third angle */ + + SGfloat angB = SG_180 - (angA + angC) ; + + /* Use Sine Rule to get length of a second side - then use SAStoArea. */ + + SGfloat sinB = sgSin ( angB ) ; + + if ( sinB == SG_ZERO ) + return SG_ZERO ; + + SGfloat lenA = lenB * sgSin(angA) / sinB ; + + return sgTriangleSolver_SAStoArea ( lenA, angC, lenB ) ; +} + + +SGfloat sgTriangleSolver_SAStoArea ( SGfloat lenA, SGfloat angB, SGfloat lenC ) +{ + return SG_HALF * lenC * lenA * sgSin ( angB ) ; +} + + +SGfloat sgTriangleSolver_SSStoArea ( SGfloat lenA, SGfloat lenB, SGfloat lenC ) +{ + /* Heron's formula */ + + SGfloat s = ( lenA + lenB + lenC ) / SG_TWO ; + SGfloat q = s * (s-lenA) * (s-lenB) * (s-lenC) ; + + /* Ikky illegal triangles generate zero areas. */ + + return ( q <= SG_ZERO ) ? SG_ZERO : sgSqrt ( q ) ; +} + + +SGfloat sgTriangleSolver_ASStoArea ( SGfloat angB, SGfloat lenA, SGfloat lenB, + int angA_is_obtuse ) +{ + SGfloat lenC ; + + sgTriangleSolver_ASStoSAA ( angB, lenA, lenB, angA_is_obtuse, + &lenC, NULL, NULL ) ; + + return sgTriangleSolver_SAStoArea ( lenA, angB, lenC ) ; +} + +SGfloat sgTriangleSolver_SAAtoArea ( SGfloat lenA, SGfloat angB, SGfloat angA ) +{ + SGfloat lenC ; + + sgTriangleSolver_SAAtoASS ( lenA, angB, angA, NULL, NULL, &lenC ) ; + + return sgTriangleSolver_SAStoArea ( lenA, angB, lenC ) ; +} + +void sgTriangleSolver_SSStoAAA ( SGfloat lenA, SGfloat lenB, SGfloat lenC, + SGfloat *angA, SGfloat *angB, SGfloat *angC ) +{ + SGfloat aa, bb, cc ; + + int flag = ( lenA == SG_ZERO ) | + (( lenB == SG_ZERO )<<1) | + (( lenC == SG_ZERO )<<2) ; + + /* Ikky zero-sized triangles generate zero/90 angles appropriately. */ + /* Ikky triangles with all lengths zero generate 60 degree angles. */ + /* Ikky impossible triangles generate all zero angles. */ + + switch ( flag ) + { + case 0 : /* no zero-lengthed sides */ + /* Cosine law */ + aa = sgACos (( lenB*lenB + lenC*lenC - lenA*lenA )/(SG_TWO*lenB*lenC)) ; + bb = sgACos (( lenA*lenA + lenC*lenC - lenB*lenB )/(SG_TWO*lenA*lenC)) ; + cc = sgACos (( lenA*lenA + lenB*lenB - lenC*lenC )/(SG_TWO*lenA*lenB)) ; + break ; + + case 1 : /* lenA is zero */ + aa = SG_ZERO ; + bb = cc = SG_90 ; + break ; + + case 2 : /* lenB is zero */ + bb = SG_ZERO ; + aa = cc = SG_90 ; + break ; + + case 4 : /* lenC is zero */ + cc = SG_ZERO ; + aa = bb = SG_90 ; + break ; + + case 3 : /* Two lengths are zero and the third isn't?!? */ + case 5 : + case 6 : + aa = bb = cc = SG_ZERO ; + break ; + + default : /* All three sides are zero length */ + aa = bb = cc = SG_60 ; + break ; + } + + if ( angA ) *angA = aa ; + if ( angB ) *angB = bb ; + if ( angC ) *angC = cc ; +} + +void sgTriangleSolver_SAStoASA ( SGfloat lenA, SGfloat angB, SGfloat lenC, + SGfloat *angA, SGfloat *lenB, SGfloat *angC ) +{ + /* Get third side using Cosine Rule */ + + SGfloat s = lenC * lenC + + lenA * lenA - SG_TWO * lenC * lenA * sgCos( angB ) ; + + SGfloat lb = ( s <= SG_ZERO ) ? SG_ZERO : (SGfloat) sqrt ( s ) ; + + if ( lenB ) *lenB = lb ; + + sgTriangleSolver_SSStoAAA ( lenA, lb, lenC, angA, NULL, angC ) ; +} + + +void sgTriangleSolver_ASAtoSAS ( SGfloat angA, SGfloat lenB, SGfloat angC, + SGfloat *lenA, SGfloat *angB, SGfloat *lenC ) +{ + /* Find the missing angle */ + + SGfloat bb = SG_180 - (angA + angC) ; + + if ( angB ) *angB = bb ; + + /* Use Sine Rule */ + + SGfloat sinB = sgSin ( bb ) ; + + if ( sinB == SG_ZERO ) + { + if ( lenA ) *lenA = lenB / SG_TWO ; /* One valid interpretation */ + if ( lenC ) *lenC = lenB / SG_TWO ; + } + else + { + if ( lenA ) *lenA = lenB * sgSin(angA) / sinB ; + if ( lenC ) *lenC = lenB * sgSin(angC) / sinB ; + } +} + + +void sgTriangleSolver_ASStoSAA ( SGfloat angB, SGfloat lenA, SGfloat lenB, + int angA_is_obtuse, + SGfloat *lenC, SGfloat *angA, SGfloat *angC ) +{ + /* Sine law */ + + SGfloat aa = (lenB == SG_ZERO ) ? SG_ZERO : sgASin (lenA * sgSin(angB)/lenB) ; + + if ( angA_is_obtuse ) + aa = SG_180 - aa ; + + if ( angA ) *angA = aa ; + + /* Find the missing angle */ + + SGfloat cc = SG_180 - (aa + angB) ; + + if ( angC ) *angC = cc ; + + /* Use SAStoASA to get the last length */ + + sgTriangleSolver_SAStoASA ( lenA, cc, lenB, NULL, lenC, NULL ) ; +} + + +void sgTriangleSolver_SAAtoASS ( SGfloat lenA, SGfloat angB, SGfloat angA, + SGfloat *angC, SGfloat *lenB, SGfloat *lenC ) +{ + /* Find the missing angle */ + + SGfloat cc = SG_180 - (angB + angA) ; + + if ( angC ) *angC = cc ; + + sgTriangleSolver_ASAtoSAS ( cc, lenA, angB, lenC, NULL, lenB ) ; +} + + diff --git a/src/sg/sg.dsp b/src/sg/sg.dsp new file mode 100644 index 0000000..ade896f --- /dev/null +++ b/src/sg/sg.dsp @@ -0,0 +1,118 @@ +# Microsoft Developer Studio Project File - Name="sg" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=sg - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "sg.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "sg.mak" CFG="sg - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "sg - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "sg - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "sg - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "..\util" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy release\*.lib ..\..\*.* copy sg.h ..\..\sg.h +# End Special Build Tool + +!ELSEIF "$(CFG)" == "sg - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I "..\util" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\sg_d.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy debug\*.lib ..\..\*.* copy sg.h ..\..\sg.h +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "sg - Win32 Release" +# Name "sg - Win32 Debug" +# Begin Source File + +SOURCE=.\sg.cxx +# End Source File +# Begin Source File + +SOURCE=.\sg.h +# End Source File +# Begin Source File + +SOURCE=.\sgd.cxx +# End Source File +# Begin Source File + +SOURCE=.\sgdIsect.cxx +# End Source File +# Begin Source File + +SOURCE=.\sgIsect.cxx +# End Source File +# Begin Source File + +SOURCE=.\sgPerlinNoise.cxx +# End Source File +# End Target +# End Project diff --git a/src/sg/sg.h b/src/sg/sg.h new file mode 100644 index 0000000..8b339a3 --- /dev/null +++ b/src/sg/sg.h @@ -0,0 +1,3102 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: sg.h 2121 2007-09-15 03:36:21Z fayjf $ +*/ + + +#ifndef SG_H +#define SG_H 1 + +#include +#include "ul.h" + +#define sgFloat float +#define SGfloat float + +#define SG_ZERO 0.0f +#define SG_HALF 0.5f +#define SG_ONE 1.0f +#define SG_TWO 2.0f +#define SG_THREE 3.0f +#define SG_FOUR 4.0f +#define SG_45 45.0f +#define SG_60 60.0f +#define SG_90 90.0f +#define SG_180 180.0f +#define SG_MAX FLT_MAX + +#define SG_X 0 +#define SG_Y 1 +#define SG_Z 2 +#define SG_W 3 + +#ifndef M_PI +#define SG_PI 3.1415926535f +#else +#define SG_PI ((SGfloat) M_PI) +#endif + +#define SG_DEGREES_TO_RADIANS (SG_PI/SG_180) +#define SG_RADIANS_TO_DEGREES (SG_180/SG_PI) + +/* + These are just convenient redefinitions of standard + math library functions to stop float/double warnings. +*/ + +inline SGfloat sgSqrt ( const SGfloat x ) { return (SGfloat) sqrt ( x ) ; } +inline SGfloat sgSquare ( const SGfloat x ) { return x * x ; } +inline SGfloat sgAbs ( const SGfloat a ) { return (axyz, src->hpr ) ; +} + +extern void sgMakeLookAtMat4 ( sgMat4 dst, + const sgVec3 eye, const sgVec3 center, const sgVec3 up ) ; + +extern void sgMakeRotMat4 ( sgMat4 dst, const SGfloat angle, const sgVec3 axis ) ; + +inline void sgMakeRotMat4 ( sgMat4 dst, const sgVec3 hpr ) +{ + sgMakeCoordMat4 ( dst, SG_ZERO, SG_ZERO, SG_ZERO, hpr[0], hpr[1], hpr[2] ) ; +} + +inline void sgMakeRotMat4 ( sgMat4 dst,const SGfloat h, const SGfloat p, const SGfloat r ) +{ + sgMakeCoordMat4 ( dst, SG_ZERO, SG_ZERO, SG_ZERO, h, p, r ) ; +} + +extern void sgMakeTransMat4 ( sgMat4 dst, const sgVec3 xyz ) ; +extern void sgMakeTransMat4 ( sgMat4 dst, const SGfloat x, const SGfloat y, const SGfloat z ) ; + + +extern void sgSetCoord ( sgCoord *coord, const sgMat4 src ) ; + +extern void sgMultMat4 ( sgMat4 dst, const sgMat4 a, const sgMat4 b ) ; +extern void sgPostMultMat4 ( sgMat4 dst, const sgMat4 a ) ; +extern void sgPreMultMat4 ( sgMat4 dst, const sgMat4 a ) ; + +extern void sgTransposeNegateMat4 ( sgMat4 dst ) ; +extern void sgTransposeNegateMat4 ( sgMat4 dst, const sgMat4 src ) ; +extern void sgInvertMat4 ( sgMat4 dst, const sgMat4 src ) ; +inline void sgInvertMat4 ( sgMat4 dst ) { sgInvertMat4 ( dst, dst ) ; } + +extern void sgXformVec3 ( sgVec3 dst, const sgVec3 src, const sgMat4 mat ) ; +extern void sgXformPnt3 ( sgVec3 dst, const sgVec3 src, const sgMat4 mat ) ; +extern void sgXformVec4 ( sgVec4 dst, const sgVec4 src, const sgMat4 mat ) ; +extern void sgXformPnt4 ( sgVec4 dst, const sgVec4 src, const sgMat4 mat ) ; +extern void sgFullXformPnt3 ( sgVec3 dst, const sgVec3 src, const sgMat4 mat ) ; +extern void sgFullXformPnt4 ( sgVec4 dst, const sgVec4 src, const sgMat4 mat ) ; + +inline void sgXformVec3 ( sgVec3 dst, const sgMat4 mat ) { sgXformVec3 ( dst, dst, mat ) ; } +inline void sgXformPnt3 ( sgVec3 dst, const sgMat4 mat ) { sgXformPnt3 ( dst, dst, mat ) ; } +inline void sgXformVec4 ( sgVec4 dst, const sgMat4 mat ) { sgXformVec4 ( dst, dst, mat ) ; } +inline void sgXformPnt4 ( sgVec4 dst, const sgMat4 mat ) { sgXformPnt4 ( dst, dst, mat ) ; } +inline void sgFullXformPnt3 ( sgVec3 dst, const sgMat4 mat ) { sgFullXformPnt3 ( dst, dst, mat ) ; } +inline void sgFullXformPnt4 ( sgVec4 dst, const sgMat4 mat ) { sgFullXformPnt4 ( dst, dst, mat ) ; } + + +/* Bits returned by sgClassifyMat4 */ + +#define SG_IDENTITY 0x00 // for clarity +#define SG_ROTATION 0x01 // includes a rotational component +#define SG_MIRROR 0x02 // changes handedness (det < 0) +#define SG_SCALE 0x04 // uniform scaling +#define SG_NONORTHO 0x10 // 3x3 not orthogonal +#define SG_TRANSLATION 0x20 // translates +#define SG_PROJECTION 0x40 // forth column not 0,0,0,1 + +/* Are these needed? sgClassifyMat4() does set the general scale bit for some matrices, + * but it is not easily defined. Use SG_NONORTHO instead (which is also set). */ +#define SG_UNIFORM_SCALE SG_SCALE +#define SG_GENERAL_SCALE 0x08 // x, y and z scaled differently + +extern int sgClassifyMat4 ( const sgMat4 mat ) ; + + + +/* + Basic low-level vector functions. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + For each of Vec2, Vec3 and Vec4, we provide inlines for + + Zero - set all elements to zero. + Set - set each element individually. + Add - add vectors element by element. + Sub - subtract vectors element by element. + Scale - multiply each element of a vector by a variable. + AddScaled - multiply second vector by a constant and add the + result to the first vector. + Negate - negate each element of a vector. + Compare - compare vectors element by element with optional tolerance. + (return TRUE if vectors are equal - within tolerances) + Equal - return TRUE if vectors are exactly equal. + Length - compute length of a vector. + Distance - compute distance between two points. + ScalarProduct - scalar (dot) product. + VectorProduct - vector (cross) product (3-element vectors ONLY!). + Normalise/Normalize - make vector be one unit long. +*/ + +inline void sgZeroVec2 ( sgVec2 dst ) { dst[0]=dst[1]=SG_ZERO ; } +inline void sgZeroVec3 ( sgVec3 dst ) { dst[0]=dst[1]=dst[2]=SG_ZERO ; } +inline void sgZeroVec4 ( sgVec4 dst ) { dst[0]=dst[1]=dst[2]=dst[3]=SG_ZERO ; } + + +inline void sgSetVec2 ( sgVec2 dst, const SGfloat x, const SGfloat y ) +{ + dst [ 0 ] = x ; + dst [ 1 ] = y ; +} + +inline void sgSetVec3 ( sgVec3 dst, const SGfloat x, const SGfloat y, const SGfloat z ) +{ + dst [ 0 ] = x ; + dst [ 1 ] = y ; + dst [ 2 ] = z ; +} + +inline void sgSetVec4 ( sgVec4 dst, const SGfloat x, const SGfloat y, const SGfloat z, const SGfloat w ) +{ + dst [ 0 ] = x ; + dst [ 1 ] = y ; + dst [ 2 ] = z ; + dst [ 3 ] = w ; +} + + +inline void sgCopyVec2 ( sgVec2 dst, const sgVec2 src ) +{ + dst [ 0 ] = src [ 0 ] ; + dst [ 1 ] = src [ 1 ] ; +} + +inline void sgCopyVec3 ( sgVec3 dst, const sgVec3 src ) +{ + dst [ 0 ] = src [ 0 ] ; + dst [ 1 ] = src [ 1 ] ; + dst [ 2 ] = src [ 2 ] ; +} + +inline void sgCopyVec4 ( sgVec4 dst, const sgVec4 src ) +{ + dst [ 0 ] = src [ 0 ] ; + dst [ 1 ] = src [ 1 ] ; + dst [ 2 ] = src [ 2 ] ; + dst [ 3 ] = src [ 3 ] ; +} + + +inline void sgAddVec2 ( sgVec2 dst, const sgVec2 src ) +{ + dst [ 0 ] += src [ 0 ] ; + dst [ 1 ] += src [ 1 ] ; +} + +inline void sgAddVec3 ( sgVec3 dst, const sgVec3 src ) +{ + dst [ 0 ] += src [ 0 ] ; + dst [ 1 ] += src [ 1 ] ; + dst [ 2 ] += src [ 2 ] ; +} + +inline void sgAddVec4 ( sgVec4 dst, const sgVec4 src ) +{ + dst [ 0 ] += src [ 0 ] ; + dst [ 1 ] += src [ 1 ] ; + dst [ 2 ] += src [ 2 ] ; + dst [ 3 ] += src [ 3 ] ; +} + + +inline void sgAddVec2 ( sgVec2 dst, const sgVec2 src1, const sgVec2 src2 ) +{ + dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] ; + dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] ; +} + +inline void sgAddVec3 ( sgVec3 dst, const sgVec3 src1, const sgVec3 src2 ) +{ + dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] ; + dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] ; + dst [ 2 ] = src1 [ 2 ] + src2 [ 2 ] ; +} + +inline void sgAddVec4 ( sgVec4 dst, const sgVec4 src1, const sgVec4 src2 ) +{ + dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] ; + dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] ; + dst [ 2 ] = src1 [ 2 ] + src2 [ 2 ] ; + dst [ 3 ] = src1 [ 3 ] + src2 [ 3 ] ; +} + + +inline void sgSubVec2 ( sgVec2 dst, const sgVec2 src ) +{ + dst [ 0 ] -= src [ 0 ] ; + dst [ 1 ] -= src [ 1 ] ; +} + +inline void sgSubVec3 ( sgVec3 dst, const sgVec3 src ) +{ + dst [ 0 ] -= src [ 0 ] ; + dst [ 1 ] -= src [ 1 ] ; + dst [ 2 ] -= src [ 2 ] ; +} + +inline void sgSubVec4 ( sgVec4 dst, const sgVec4 src ) +{ + dst [ 0 ] -= src [ 0 ] ; + dst [ 1 ] -= src [ 1 ] ; + dst [ 2 ] -= src [ 2 ] ; + dst [ 3 ] -= src [ 3 ] ; +} + +inline void sgSubVec2 ( sgVec2 dst, const sgVec2 src1, const sgVec2 src2 ) +{ + dst [ 0 ] = src1 [ 0 ] - src2 [ 0 ] ; + dst [ 1 ] = src1 [ 1 ] - src2 [ 1 ] ; +} + +inline void sgSubVec3 ( sgVec3 dst, const sgVec3 src1, const sgVec3 src2 ) +{ + dst [ 0 ] = src1 [ 0 ] - src2 [ 0 ] ; + dst [ 1 ] = src1 [ 1 ] - src2 [ 1 ] ; + dst [ 2 ] = src1 [ 2 ] - src2 [ 2 ] ; +} + +inline void sgSubVec4 ( sgVec4 dst, const sgVec4 src1, const sgVec4 src2 ) +{ + dst [ 0 ] = src1 [ 0 ] - src2 [ 0 ] ; + dst [ 1 ] = src1 [ 1 ] - src2 [ 1 ] ; + dst [ 2 ] = src1 [ 2 ] - src2 [ 2 ] ; + dst [ 3 ] = src1 [ 3 ] - src2 [ 3 ] ; +} + + +inline void sgNegateVec2 ( sgVec2 dst ) +{ + dst [ 0 ] = -dst [ 0 ] ; + dst [ 1 ] = -dst [ 1 ] ; +} + +inline void sgNegateVec3 ( sgVec3 dst ) +{ + dst [ 0 ] = -dst [ 0 ] ; + dst [ 1 ] = -dst [ 1 ] ; + dst [ 2 ] = -dst [ 2 ] ; +} + +inline void sgNegateVec4 ( sgVec4 dst ) +{ + dst [ 0 ] = -dst [ 0 ] ; + dst [ 1 ] = -dst [ 1 ] ; + dst [ 2 ] = -dst [ 2 ] ; + dst [ 3 ] = -dst [ 3 ] ; +} + + +inline void sgNegateVec2 ( sgVec2 dst, const sgVec2 src ) +{ + dst [ 0 ] = -src [ 0 ] ; + dst [ 1 ] = -src [ 1 ] ; +} + +inline void sgNegateVec3 ( sgVec3 dst, const sgVec3 src ) +{ + dst [ 0 ] = -src [ 0 ] ; + dst [ 1 ] = -src [ 1 ] ; + dst [ 2 ] = -src [ 2 ] ; +} + +inline void sgNegateVec4 ( sgVec4 dst, const sgVec4 src ) +{ + dst [ 0 ] = -src [ 0 ] ; + dst [ 1 ] = -src [ 1 ] ; + dst [ 2 ] = -src [ 2 ] ; + dst [ 3 ] = -src [ 3 ] ; +} + + +inline void sgScaleVec2 ( sgVec2 dst, const SGfloat s ) +{ + dst [ 0 ] *= s ; + dst [ 1 ] *= s ; +} + +inline void sgScaleVec3 ( sgVec3 dst, const SGfloat s ) +{ + dst [ 0 ] *= s ; + dst [ 1 ] *= s ; + dst [ 2 ] *= s ; +} + +inline void sgScaleVec4 ( sgVec4 dst, const SGfloat s ) +{ + dst [ 0 ] *= s ; + dst [ 1 ] *= s ; + dst [ 2 ] *= s ; + dst [ 3 ] *= s ; +} + +inline void sgScaleVec2 ( sgVec2 dst, const sgVec2 src, const SGfloat s ) +{ + dst [ 0 ] = src [ 0 ] * s ; + dst [ 1 ] = src [ 1 ] * s ; +} + +inline void sgScaleVec3 ( sgVec3 dst, const sgVec3 src, const SGfloat s ) +{ + dst [ 0 ] = src [ 0 ] * s ; + dst [ 1 ] = src [ 1 ] * s ; + dst [ 2 ] = src [ 2 ] * s ; +} + +inline void sgScaleVec4 ( sgVec4 dst, const sgVec4 src, const SGfloat s ) +{ + dst [ 0 ] = src [ 0 ] * s ; + dst [ 1 ] = src [ 1 ] * s ; + dst [ 2 ] = src [ 2 ] * s ; + dst [ 3 ] = src [ 3 ] * s ; +} + + +inline void sgAddScaledVec2 ( sgVec2 dst, const sgVec2 src, const SGfloat s ) +{ + dst [ 0 ] += src [ 0 ] * s ; + dst [ 1 ] += src [ 1 ] * s ; +} + +inline void sgAddScaledVec3 ( sgVec3 dst, const sgVec3 src, const SGfloat s ) +{ + dst [ 0 ] += src [ 0 ] * s ; + dst [ 1 ] += src [ 1 ] * s ; + dst [ 2 ] += src [ 2 ] * s ; +} + +inline void sgAddScaledVec4 ( sgVec4 dst, const sgVec4 src, const SGfloat s ) +{ + dst [ 0 ] += src [ 0 ] * s ; + dst [ 1 ] += src [ 1 ] * s ; + dst [ 2 ] += src [ 2 ] * s ; + dst [ 3 ] += src [ 3 ] * s ; +} + + +inline void sgAddScaledVec2 ( sgVec2 dst, const sgVec2 src1, const sgVec2 src2, const SGfloat s ) +{ + dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] * s ; + dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] * s ; +} + +inline void sgAddScaledVec3 ( sgVec3 dst, const sgVec3 src1, const sgVec3 src2, const SGfloat s ) +{ + dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] * s ; + dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] * s ; + dst [ 2 ] = src1 [ 2 ] + src2 [ 2 ] * s ; +} + +inline void sgAddScaledVec4 ( sgVec4 dst, const sgVec4 src1, const sgVec4 src2, const SGfloat s ) +{ + dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] * s ; + dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] * s ; + dst [ 2 ] = src1 [ 2 ] + src2 [ 2 ] * s ; + dst [ 3 ] = src1 [ 3 ] + src2 [ 3 ] * s ; +} + + +inline int sgCompareVec2 ( const sgVec2 a, const sgVec2 b, const SGfloat tol ) +{ + if ( sgCompareFloat( a[0], b[0], tol ) != 0 ) return FALSE ; + if ( sgCompareFloat( a[1], b[1], tol ) != 0 ) return FALSE ; + + return TRUE ; +} + +inline int sgCompareVec3 ( const sgVec3 a, const sgVec3 b, const SGfloat tol ) +{ + if ( sgCompareFloat( a[0], b[0], tol ) != 0 ) return FALSE ; + if ( sgCompareFloat( a[1], b[1], tol ) != 0 ) return FALSE ; + if ( sgCompareFloat( a[2], b[2], tol ) != 0 ) return FALSE ; + + return TRUE ; +} + +inline int sgCompareVec4 ( const sgVec4 a, const sgVec4 b, const SGfloat tol ) +{ + if ( sgCompareFloat( a[0], b[0], tol ) != 0 ) return FALSE ; + if ( sgCompareFloat( a[1], b[1], tol ) != 0 ) return FALSE ; + if ( sgCompareFloat( a[2], b[2], tol ) != 0 ) return FALSE ; + if ( sgCompareFloat( a[3], b[3], tol ) != 0 ) return FALSE ; + + return TRUE ; +} + + +inline int sgEqualVec2 ( const sgVec2 a, const sgVec2 b ) +{ + return a[0] == b[0] && + a[1] == b[1] ; +} + +inline int sgEqualVec3 ( const sgVec3 a, const sgVec3 b ) +{ + return a[0] == b[0] && + a[1] == b[1] && + a[2] == b[2] ; +} + +inline int sgEqualVec4 ( const sgVec4 a, const sgVec4 b ) +{ + return a[0] == b[0] && + a[1] == b[1] && + a[2] == b[2] && + a[3] == b[3] ; +} + + +inline SGfloat sgScalarProductVec2 ( const sgVec2 a, const sgVec2 b ) +{ + return a[0]*b[0] + a[1]*b[1] ; +} + +inline SGfloat sgScalarProductVec3 ( const sgVec3 a, const sgVec3 b ) +{ + return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] ; +} + +inline SGfloat sgScalarProductVec4 ( const sgVec4 a, const sgVec4 b ) +{ + return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3] ; +} + + +extern void sgVectorProductVec3 ( sgVec3 dst, const sgVec3 a, const sgVec3 b ) ; + +inline SGfloat sgLerp ( const SGfloat a, const SGfloat b, const SGfloat f ) +{ + return a + f * ( b - a ) ; +} + +inline void sgLerpVec4 ( sgVec4 dst, const sgVec4 a, const sgVec4 b, const SGfloat f ) +{ + dst[0] = a[0] + f * ( b[0] - a[0] ) ; + dst[1] = a[1] + f * ( b[1] - a[1] ) ; + dst[2] = a[2] + f * ( b[2] - a[2] ) ; + dst[3] = a[3] + f * ( b[3] - a[3] ) ; +} + + +inline void sgLerpVec3 ( sgVec3 dst, const sgVec3 a, const sgVec3 b, const SGfloat f ) +{ + dst[0] = a[0] + f * ( b[0] - a[0] ) ; + dst[1] = a[1] + f * ( b[1] - a[1] ) ; + dst[2] = a[2] + f * ( b[2] - a[2] ) ; +} + + +inline void sgLerpVec2 ( sgVec2 dst, const sgVec2 a, const sgVec2 b, const SGfloat f ) +{ + dst[0] = a[0] + f * ( b[0] - a[0] ) ; + dst[1] = a[1] + f * ( b[1] - a[1] ) ; +} + + +inline void sgLerpAnglesVec3 ( sgVec3 dst, const sgVec3 a, + const sgVec3 b, + const SGfloat f ) +{ + sgVec3 tmp ; + + if ( b[0] - a[0] > 180.0f ) tmp[0] = a[0] + 360.0f ; else + if ( b[0] - a[0] < -180.0f ) tmp[0] = a[0] - 360.0f ; else tmp[0] = a[0] ; + + if ( b[1] - a[1] > 180.0f ) tmp[1] = a[1] + 360.0f ; else + if ( b[1] - a[1] < -180.0f ) tmp[1] = a[1] - 360.0f ; else tmp[1] = a[1] ; + + if ( b[2] - a[2] > 180.0f ) tmp[2] = a[2] + 360.0f ; else + if ( b[2] - a[2] < -180.0f ) tmp[2] = a[2] - 360.0f ; else tmp[2] = a[2] ; + + dst[0] = tmp[0] + f * ( b[0] - tmp[0] ) ; + dst[1] = tmp[1] + f * ( b[1] - tmp[1] ) ; + dst[2] = tmp[2] + f * ( b[2] - tmp[2] ) ; +} + + + +inline SGfloat sgDistanceSquaredVec2 ( const sgVec2 a, const sgVec2 b ) +{ + return sgSquare ( a[0]-b[0] ) + sgSquare ( a[1]-b[1] ) ; +} + +inline SGfloat sgDistanceSquaredVec3 ( const sgVec3 a, const sgVec3 b ) +{ + return sgSquare ( a[0]-b[0] ) + sgSquare ( a[1]-b[1] ) + + sgSquare ( a[2]-b[2] ) ; +} + +inline SGfloat sgDistanceSquaredVec4 ( const sgVec4 a, const sgVec4 b ) +{ + return sgSquare ( a[0]-b[0] ) + sgSquare ( a[1]-b[1] ) + + sgSquare ( a[2]-b[2] ) + sgSquare ( a[3]-b[3] ) ; +} + +inline SGfloat sgDistanceVec2 ( const sgVec2 a, const sgVec2 b ) +{ + return sgSqrt ( sgSquare ( a[0]-b[0] ) + sgSquare ( a[1]-b[1] ) ) ; +} + +inline SGfloat sgDistanceVec3 ( const sgVec3 a, const sgVec3 b ) +{ + return sgSqrt ( sgSquare ( a[0]-b[0] ) + sgSquare ( a[1]-b[1] ) + + sgSquare ( a[2]-b[2] ) ) ; +} + +inline SGfloat sgDistanceVec4 ( const sgVec4 a, const sgVec4 b ) +{ + return sgSqrt ( sgSquare ( a[0]-b[0] ) + sgSquare ( a[1]-b[1] ) + + sgSquare ( a[2]-b[2] ) + sgSquare ( a[3]-b[3] ) ) ; +} + + +inline SGfloat sgLengthVec2 ( const sgVec2 src ) +{ + return sgSqrt ( sgScalarProductVec2 ( src, src ) ) ; +} + +inline SGfloat sgLengthVec3 ( const sgVec3 src ) +{ + return sgSqrt ( sgScalarProductVec3 ( src, src ) ) ; +} + +inline SGfloat sgLengthVec4 ( const sgVec4 src ) +{ + return sgSqrt ( sgScalarProductVec4 ( src, src ) ) ; +} + +inline SGfloat sgLengthSquaredVec2 ( sgVec2 const src ) +{ + return sgScalarProductVec2 ( src, src ) ; +} + +inline SGfloat sgLengthSquaredVec3 ( sgVec3 const src ) +{ + return sgScalarProductVec3 ( src, src ) ; +} + +inline SGfloat sgLengthSquaredVec4 ( sgVec4 const src ) +{ + return sgScalarProductVec4 ( src, src ) ; +} + + +/* Anglo-US spelling issues. */ +#define sgNormalizeVec2 sgNormaliseVec2 +#define sgNormalizeVec3 sgNormaliseVec3 +#define sgNormalizeVec4 sgNormaliseVec4 +#define sgNormalizeQuat sgNormaliseQuat + +inline void sgNormaliseVec2 ( sgVec2 dst ) +{ + sgScaleVec2 ( dst, SG_ONE / sgLengthVec2 ( dst ) ) ; +} + +inline void sgNormaliseVec3 ( sgVec3 dst ) +{ + sgScaleVec3 ( dst, SG_ONE / sgLengthVec3 ( dst ) ) ; +} + +inline void sgNormaliseVec4 ( sgVec4 dst ) +{ + sgScaleVec4 ( dst, SG_ONE / sgLengthVec4 ( dst ) ) ; +} + +inline void sgNormaliseVec2 ( sgVec2 dst, const sgVec2 src ) +{ + sgScaleVec2 ( dst, src, SG_ONE / sgLengthVec2 ( src ) ) ; +} + +inline void sgNormaliseVec3 ( sgVec3 dst, const sgVec3 src ) +{ + sgScaleVec3 ( dst, src, SG_ONE / sgLengthVec3 ( src ) ) ; +} + +inline void sgNormaliseVec4 ( sgVec4 dst, const sgVec4 src ) +{ + sgScaleVec4 ( dst, src, SG_ONE / sgLengthVec4 ( src ) ) ; +} + + +inline void sgZeroCoord ( sgCoord *dst ) +{ + sgSetVec3 ( dst->xyz, SG_ZERO, SG_ZERO, SG_ZERO ) ; + sgSetVec3 ( dst->hpr, SG_ZERO, SG_ZERO, SG_ZERO ) ; +} + +inline void sgSetCoord ( sgCoord *dst, const SGfloat x, const SGfloat y, const SGfloat z, + const SGfloat h, const SGfloat p, const SGfloat r ) +{ + sgSetVec3 ( dst->xyz, x, y, z ) ; + sgSetVec3 ( dst->hpr, h, p, r ) ; +} + +inline void sgSetCoord ( sgCoord *dst, const sgVec3 xyz, const sgVec3 hpr ) +{ + sgCopyVec3 ( dst->xyz, xyz ) ; + sgCopyVec3 ( dst->hpr, hpr ) ; +} + +inline void sgCopyCoord ( sgCoord *dst, const sgCoord *src ) +{ + sgCopyVec3 ( dst->xyz, src->xyz ) ; + sgCopyVec3 ( dst->hpr, src->hpr ) ; +} + + + +inline void sgCopyMat4 ( sgMat4 dst, const sgMat4 src ) +{ + sgCopyVec4 ( dst[ 0 ], src[ 0 ] ) ; + sgCopyVec4 ( dst[ 1 ], src[ 1 ] ) ; + sgCopyVec4 ( dst[ 2 ], src[ 2 ] ) ; + sgCopyVec4 ( dst[ 3 ], src[ 3 ] ) ; +} + + +inline void sgScaleMat4 ( sgMat4 dst, const sgMat4 src, const SGfloat scale ) +{ + sgScaleVec4 ( dst[0], src[0], scale ) ; + sgScaleVec4 ( dst[1], src[1], scale ) ; + sgScaleVec4 ( dst[2], src[2], scale ) ; + sgScaleVec4 ( dst[3], src[3], scale ) ; +} + + +inline void sgMakeIdentMat4 ( sgMat4 dst ) +{ + sgSetVec4 ( dst[0], SG_ONE , SG_ZERO, SG_ZERO, SG_ZERO ) ; + sgSetVec4 ( dst[1], SG_ZERO, SG_ONE , SG_ZERO, SG_ZERO ) ; + sgSetVec4 ( dst[2], SG_ZERO, SG_ZERO, SG_ONE , SG_ZERO ) ; + sgSetVec4 ( dst[3], SG_ZERO, SG_ZERO, SG_ZERO, SG_ONE ) ; +} + + +extern void sgMakePickMatrix( sgMat4 mat, sgFloat x, sgFloat y, + sgFloat width, sgFloat height, sgVec4 viewport ) ; + +extern int sgCompare3DSqdDist ( const sgVec3 a, const sgVec3 b, const SGfloat sqd_dist ) ; + +inline SGfloat sgDistToLineVec2 ( const sgVec3 line, const sgVec2 pnt ) +{ + return sgScalarProductVec2 ( line, pnt ) + line[2] ; +} + + +struct sgLineSegment3 /* Bounded line segment */ +{ + sgVec3 a ; + sgVec3 b ; +} ; + +struct sgLine3 /* Infinite line */ +{ + sgVec3 point_on_line ; + sgVec3 direction_vector ; /* Should be a unit vector */ +} ; + + +inline void sgLineSegment3ToLine3 ( sgLine3 *line, + const sgLineSegment3 lineseg ) +{ + sgCopyVec3 ( line->point_on_line , lineseg.a ) ; + sgSubVec3 ( line->direction_vector, lineseg.b, lineseg.a ) ; + sgNormaliseVec3 ( line->direction_vector ) ; +} + + +SGfloat sgDistSquaredToLineVec3 ( const sgLine3 line, + const sgVec3 pnt ) ; +SGfloat sgDistSquaredToLineSegmentVec3 ( const sgLineSegment3 line, + const sgVec3 pnt ) ; + + +inline SGfloat sgDistToLineVec3 ( const sgLine3 line, + const sgVec3 pnt ) +{ + return sgSqrt ( sgDistSquaredToLineVec3 ( line, pnt ) ); +} + + +inline SGfloat sgDistToLineSegmentVec3 ( const sgLineSegment3 line, + const sgVec3 pnt ) +{ + return sgSqrt ( sgDistSquaredToLineSegmentVec3(line,pnt) ) ; +} + + +inline SGfloat sgDistToPlaneVec3 ( const sgVec4 plane, const sgVec3 pnt ) +{ + return sgScalarProductVec3 ( plane, pnt ) + plane[3] ; +} + + +inline SGfloat sgHeightAbovePlaneVec3 ( const sgVec4 plane, const sgVec3 pnt ) +{ + return pnt[2] - sgHeightOfPlaneVec2 ( plane, pnt ) ; +} + +extern void sgReflectInPlaneVec3 ( sgVec3 dst, const sgVec3 src, const sgVec4 plane ) ; + +inline void sgReflectInPlaneVec3 ( sgVec3 dst, const sgVec4 plane ) +{ + sgReflectInPlaneVec3 ( dst, dst, plane ) ; +} + +extern void sgMakeNormal ( sgVec2 dst, const sgVec3 a, const sgVec3 b ) ; + + +extern void sgMakeNormal ( sgVec3 dst, const sgVec3 a, const sgVec3 b, const sgVec3 c ) ; + + +inline void sgMake2DLine ( sgVec3 dst, const sgVec2 a, const sgVec2 b ) +{ + dst[0] = b[1]-a[1] ; + dst[1] = -(b[0]-a[0]) ; + sgNormalizeVec2 ( dst ) ; + dst[2] = - ( dst[0]*a[0] + dst[1]*a[1] ) ; +} + +inline void sgMakePlane ( sgVec4 dst, const sgVec3 normal, const sgVec3 pnt ) +{ + sgCopyVec3 ( dst, normal ) ; + dst [ 3 ] = - sgScalarProductVec3 ( normal, pnt ) ; +} + +inline void sgMakePlane ( sgVec4 dst, const sgVec3 a, const sgVec3 b, const sgVec3 c ) +{ + /* + Ax + By + Cz + D == 0 ; + D = - ( Ax + By + Cz ) + = - ( A*a[0] + B*a[1] + C*a[2] ) + = - sgScalarProductVec3 ( normal, a ) ; + */ + + sgMakeNormal ( dst, a, b, c ) ; + + dst [ 3 ] = - sgScalarProductVec3 ( dst, a ) ; +} + +float sgTriArea( sgVec3 p0, sgVec3 p1, sgVec3 p2 ); + + +// Fast code. Result is in the range 0..180: +inline SGfloat sgAngleBetweenNormalizedVec3 ( sgVec3 v1, sgVec3 v2 ) +{ + float f = sgScalarProductVec3 ( v1, v2 ) ; + + return (float) acos ( ( f >= 1.0f ) ? 1.0f : + ( f <= -1.0f ) ? -1.0f : f ) * + SG_RADIANS_TO_DEGREES ; +} + +// Fast code. Result is in the range 0..180: + +SGfloat sgAngleBetweenVec3 ( sgVec3 v1, sgVec3 v2 ); + +// All three have to be normalized. Slow code. Result is in the range 0..360: + +SGfloat sgAngleBetweenNormalizedVec3 (sgVec3 first, sgVec3 second, sgVec3 normal); + +// Normal has to be normalized. Slow code. Result is in the range 0..360: + +SGfloat sgAngleBetweenVec3 ( sgVec3 v1, sgVec3 v2, sgVec3 normal ); + +class sgSphere +{ +public: + sgVec3 center ; + SGfloat radius ; + + + sgSphere () { empty () ; } + + const SGfloat *getCenter (void) const { return center ; } + + void setCenter ( const sgVec3 c ) + { + sgCopyVec3 ( center, c ) ; + } + + void setCenter ( const SGfloat x, const SGfloat y, const SGfloat z ) + { + sgSetVec3 ( center, x, y, z ) ; + } + + SGfloat getRadius (void) const { return radius ; } + void setRadius ( const SGfloat r ) { radius = r ; } + + int isEmpty (void) const { return radius < SG_ZERO ; } + void empty (void) { radius = - SG_ONE ; } + + void orthoXform ( const sgMat4 m ) + { + sgXformPnt3 ( center, center, m ) ; + // radius *= sgLengthVec3 ( m[0] ) ; -- degrades performance for non-scaled matrices ... + } + + void extend ( const sgSphere *s ) ; + void extend ( const sgBox *b ) ; + void extend ( const sgVec3 v ) ; + + int intersects ( const sgSphere *s ) const + { + return sgCompare3DSqdDist ( center, s->getCenter(), + sgSquare ( radius + s->getRadius() ) ) <= 0 ; + } + + int intersects ( const sgVec4 plane ) const + { + return sgAbs ( sgDistToPlaneVec3 ( plane, center ) ) <= radius ; + } + + int intersects ( const sgBox *b ) const ; +} ; + + +class sgBox +{ +public: + sgVec3 min ; + sgVec3 max ; + + + sgBox () { empty () ; } + + const SGfloat *getMin (void) const { return min ; } + const SGfloat *getMax (void) const { return max ; } + + void setMin ( const SGfloat x, const SGfloat y, const SGfloat z ) + { + sgSetVec3 ( min, x, y, z ) ; + } + + void setMin ( const sgVec3 src ) + { + sgCopyVec3 ( min, src ) ; + } + + void setMax ( const SGfloat x, const SGfloat y, const SGfloat z ) + { + sgSetVec3 ( max, x, y, z ) ; + } + + void setMax ( const sgVec3 src ) + { + sgCopyVec3 ( max, src ) ; + } + + int isEmpty(void) const + { + return ( min[0] > max[0] || + min[1] > max[1] || + min[2] > max[2] ) ; + } + + void empty (void) + { + sgSetVec3 ( min, SG_MAX, SG_MAX, SG_MAX ) ; + sgSetVec3 ( max, -SG_MAX, -SG_MAX, -SG_MAX ) ; + } + + void extend ( const sgSphere *s ) ; + void extend ( const sgBox *b ) ; + void extend ( const sgVec3 v ) ; + + int intersects ( const sgSphere *s ) const + { + return s -> intersects ( this ) ; + } + + int intersects ( const sgBox *b ) const + { + return min[0] <= b->getMax()[0] && max[0] >= b->getMin()[0] && + min[1] <= b->getMax()[1] && max[1] >= b->getMin()[1] && + min[2] <= b->getMax()[2] && max[2] >= b->getMin()[2] ; + } + + int intersects ( const sgVec4 plane ) const ; +} ; + + +#define SG_LEFT_PLANE 0 +#define SG_RIGHT_PLANE 1 +#define SG_BOT_PLANE 2 +#define SG_TOP_PLANE 3 +#define SG_NEAR_PLANE 4 +#define SG_FAR_PLANE 5 + +class sgFrustum +{ + /* Is the projection orthographic (or perspective)? */ + int ortho ; + + /* The parameters for glFrustum/glOrtho */ + + SGfloat left, right, bot, top, nnear, ffar ; + + /* The computed projection matrix for this frustum */ + + sgMat4 mat ; + + /* The A,B,C,D terms of the plane equations of the clip planes */ + /* A point (x,y,z) is inside the frustum iff Ax + By + Cz + D >= 0 for all planes */ + + sgVec4 plane [ 6 ] ; + + /* These two are only valid for simple frusta */ + /* Note that to convert to parameters for gluPerspective you do the following: + * "fovy" is "vfov" + * "aspect" is the ratio "hfov" / "vfov" + * Note also that the "hfov" and "vfov" variables are NOT automatically set. + */ + + SGfloat hfov ; /* Horizontal Field of View -or- Orthographic Width */ + SGfloat vfov ; /* Vertical Field of View -or- Orthographic Height */ + + void update (void) ; + int getOutcode ( const sgVec4 src ) const ; + +public: + + sgFrustum (void) + { + ortho = FALSE ; + nnear = SG_ONE ; + ffar = 1000000.0f ; + hfov = SG_45 ; + vfov = SG_45 ; + update () ; + } + + void setFrustum ( const SGfloat l, const SGfloat r, + const SGfloat b, const SGfloat t, + const SGfloat n, const SGfloat f ) + { + ortho = FALSE ; + left = l ; + right = r ; + bot = b ; + top = t ; + nnear = n ; + ffar = f ; + hfov = vfov = SG_ZERO ; + update () ; + } + + void setOrtho ( const SGfloat l, const SGfloat r, + const SGfloat b, const SGfloat t, + const SGfloat n, const SGfloat f ) + { + ortho = TRUE ; + left = l ; + right = r ; + bot = b ; + top = t ; + nnear = n ; + ffar = f ; + hfov = vfov = SG_ZERO ; + update () ; + } + + void getMat4 ( sgMat4 dst ) { sgCopyMat4 ( dst, mat ) ; } + + SGfloat getLeft (void) const { return left ; } + SGfloat getRight(void) const { return right ; } + SGfloat getBot (void) const { return bot ; } + SGfloat getTop (void) const { return top ; } + SGfloat getNear (void) const { return nnear ; } + SGfloat getFar (void) const { return ffar ; } + + const SGfloat *getPlane ( int i ) const { return plane [ i ] ; } + + SGfloat getHFOV (void) const { return hfov ; } + SGfloat getVFOV (void) const { return vfov ; } + + void getFOV ( SGfloat *h, SGfloat *v ) const + { + if ( h != (SGfloat *) 0 ) *h = hfov ; + if ( v != (SGfloat *) 0 ) *v = vfov ; + } + + void setFOV ( const SGfloat h, const SGfloat v ) + { + ortho = FALSE ; + hfov = ( h <= 0 ) ? ( v * SG_FOUR / SG_THREE ) : h ; + vfov = ( v <= 0 ) ? ( h * SG_THREE / SG_FOUR ) : v ; + update () ; + } + + void getOrtho ( SGfloat *w, SGfloat *h ) const + { + if ( w != (SGfloat *) 0 ) *w = right - left ; + if ( h != (SGfloat *) 0 ) *h = top - bot ; + } + + void setOrtho ( const SGfloat w, const SGfloat h ) + { + ortho = TRUE ; + hfov = ( w <= 0 ) ? ( h * SG_FOUR / SG_THREE ) : w ; + vfov = ( h <= 0 ) ? ( w * SG_FOUR / SG_THREE ) : h ; + update () ; + } + + void getNearFar ( SGfloat *n, SGfloat *f ) const + { + if ( n != (SGfloat *) 0 ) *n = nnear ; + if ( f != (SGfloat *) 0 ) *f = ffar ; + } + + void setNearFar ( const SGfloat n, const SGfloat f ) + { + nnear = n ; + ffar = f ; + update () ; + } + + int isOrtho (void) const { return ortho ; } + + int contains ( const sgVec3 p ) const ; + int contains ( const sgSphere *s ) const ; + int contains ( const sgBox *b ) const ; +} ; + + +/* + Quaternion routines are Copyright (C) 1999 + Kevin B. Thompson + Modified by Sylvan W. Clebsch + Largely rewritten by "Negative0" + Added to by John Fay +*/ + +/* + Quaternion structure w = real, (x, y, z) = vector + CHANGED sqQuat to float array so that syntax matches + vector and matrix routines +*/ + + +inline void sgMakeIdentQuat ( sgQuat dst ) +{ + sgSetVec4 ( dst, SG_ZERO, SG_ZERO, SG_ZERO, SG_ONE ) ; +} + + +inline void sgSetQuat ( sgQuat dst, + const SGfloat w, const SGfloat x, + const SGfloat y, const SGfloat z ) +{ + sgSetVec4 ( dst, x, y, z, w ) ; +} + +inline void sgCopyQuat ( sgQuat dst, const sgQuat src ) +{ + sgCopyVec4 ( dst, src ) ; +} + + +/* Construct a unit quaternion (length==1) */ + +inline void sgNormaliseQuat ( sgQuat dst, const sgQuat src ) +{ + SGfloat d = sgScalarProductVec4 ( src, src ) ; + + d = (d > SG_ZERO) ? (SG_ONE / sgSqrt ( d )) : SG_ONE ; + + sgScaleVec4 ( dst, src, d ) ; +} + + + +inline void sgNormaliseQuat ( sgQuat dst ) { sgNormaliseQuat ( dst, dst ) ; } + + +inline void sgInvertQuat ( sgQuat dst, const sgQuat src ) +{ + SGfloat d = sgScalarProductVec4 ( src, src ) ; + + d = ( d == SG_ZERO ) ? SG_ONE : ( SG_ONE / d ) ; + + dst[SG_W] = src[SG_W] * d ; + dst[SG_X] = -src[SG_X] * d ; + dst[SG_Y] = -src[SG_Y] * d ; + dst[SG_Z] = -src[SG_Z] * d ; +} + +inline void sgInvertQuat ( sgQuat dst ) { sgInvertQuat ( dst, dst ) ; } + + +/* Make an angle and axis of rotation from a Quaternion. */ + +void sgQuatToAngleAxis ( SGfloat *angle, sgVec3 axis, const sgQuat src ) ; +void sgQuatToAngleAxis ( SGfloat *angle, + SGfloat *x, SGfloat *y, SGfloat *z, + const sgQuat src ) ; + +/* Make a quaternion from a given angle and axis of rotation */ + +void sgAngleAxisToQuat ( sgQuat dst, const SGfloat angle, const sgVec3 axis ) ; +void sgAngleAxisToQuat ( sgQuat dst, + const SGfloat angle, + const SGfloat x, const SGfloat y, const SGfloat z ) ; + +/* Convert a matrix to/from a quat */ + +void sgMatrixToQuat ( sgQuat quat, const sgMat4 m ) ; +void sgQuatToMatrix ( sgMat4 m, const sgQuat quat ) ; + +/* Convert a set of eulers to/from a quat */ + +void sgQuatToEuler( sgVec3 hpr, const sgQuat quat ) ; +void sgEulerToQuat( sgQuat quat, const sgVec3 hpr ) ; + +inline void sgEulerToQuat( sgQuat dst, + SGfloat h, SGfloat p, SGfloat r ) +{ + sgVec3 hpr ; + + sgSetVec3 ( hpr, h, p, r ) ; + + sgEulerToQuat( dst, hpr ) ; +} + +inline void sgHPRToQuat ( sgQuat dst, SGfloat h, SGfloat p, SGfloat r ) +{ + sgVec3 hpr; + + hpr[0] = h * SG_DEGREES_TO_RADIANS ; + hpr[1] = p * SG_DEGREES_TO_RADIANS ; + hpr[2] = r * SG_DEGREES_TO_RADIANS ; + + sgEulerToQuat( dst, hpr ) ; +} + +inline void sgHPRToQuat ( sgQuat dst, const sgVec3 hpr ) +{ + sgVec3 tmp ; + + sgScaleVec3 ( tmp, hpr, SG_DEGREES_TO_RADIANS ) ; + + sgEulerToQuat ( dst, tmp ) ; +} + + +/* Multiply quaternions together (concatenate rotations) */ + +void sgMultQuat ( sgQuat dst, const sgQuat a, const sgQuat b ) ; + +inline void sgPostMultQuat ( sgQuat dst, const sgQuat q ) +{ + sgQuat r ; + + sgCopyQuat ( r, dst ) ; + sgMultQuat ( dst, r, q ) ; +} + +inline void sgPreMultQuat ( sgQuat dst, const sgQuat q ) +{ + sgQuat r ; + + sgCopyQuat ( r, dst ) ; + sgMultQuat ( dst, q, r ) ; +} + + +/* Rotate a quaternion by a given angle and axis (convenience function) */ + + +inline void sgPreRotQuat ( sgQuat dst, const SGfloat angle, const sgVec3 axis ) +{ + sgQuat q ; + sgAngleAxisToQuat ( q, angle, axis ) ; + sgPreMultQuat ( dst, q ) ; + sgNormaliseQuat ( dst ) ; +} + + +inline void sgPostRotQuat ( sgQuat dst, const SGfloat angle, const sgVec3 axis ) +{ + sgQuat q ; + sgAngleAxisToQuat ( q, angle, axis ) ; + sgPostMultQuat ( dst, q ) ; + sgNormaliseQuat ( dst ) ; +} + + +inline void sgPreRotQuat ( sgQuat dst, + const SGfloat angle, + const SGfloat x, const SGfloat y, const SGfloat z ) +{ + sgVec3 axis ; + + sgSetVec3 ( axis, x, y, z ) ; + sgPreRotQuat ( dst, angle, axis ) ; +} + +inline void sgPostRotQuat ( sgQuat dst, + const SGfloat angle, + const SGfloat x, const SGfloat y, const SGfloat z ) +{ + sgVec3 axis ; + + sgSetVec3 ( axis, x, y, z ) ; + sgPostRotQuat ( dst, angle, axis ) ; +} + + +/* more meaningful names */ +#define sgWorldRotQuat sgPostRotQuat +#define sgLocalRotQuat sgPreRotQuat + +/* for backwards compatibility */ +#define sgRotQuat sgPostRotQuat + + +/* SWC - Interpolate between to quaternions */ + +extern void sgSlerpQuat ( sgQuat dst, + const sgQuat from, const sgQuat to, + const SGfloat t ) ; + + + +/* + Intersection testing. +*/ + +int sgIsectPlanePlane ( sgVec3 point, sgVec3 dir, + sgVec4 plane1, sgVec4 plane2 ) ; +int sgIsectInfLinePlane ( sgVec3 dst, + sgVec3 l_org, sgVec3 l_vec, + sgVec4 plane ) ; +int sgIsectInfLineInfLine ( sgVec3 dst, + sgVec3 l1_org, sgVec3 l1_vec, + sgVec3 l2_org, sgVec3 l2_vec ) ; +SGfloat sgIsectLinesegPlane ( sgVec3 dst, + sgVec3 v1, sgVec3 v2, + sgVec4 plane ) ; + +bool sgPointInTriangle3 ( sgVec3 point, sgVec3 tri[3] ) ; +bool sgPointInTriangle2 ( sgVec2 point, sgVec2 tri[3] ) ; + +inline bool sgPointInTriangle ( sgVec3 point, sgVec3 tri[3] ) +{ + return sgPointInTriangle3 ( point, tri ) ; +} + + + +/**********************************************************************/ + +#define sgdFloat double +#define SGDfloat double + +#define SGD_ZERO 0.0 +#define SGD_HALF 0.5 +#define SGD_ONE 1.0 +#define SGD_TWO 2.0 +#define SGD_THREE 3.0 +#define SGD_FOUR 4.0 +#define SGD_45 45.0 +#define SGD_60 60.0 +#define SGD_90 90.0 +#define SGD_180 180.0 +#define SGD_MAX DBL_MAX + + +#define SGD_X 0 +#define SGD_Y 1 +#define SGD_Z 2 +#define SGD_W 3 + +#ifndef M_PI +#define SGD_PI 3.14159265358979323846 /* From M_PI under Linux/X86 */ +#else +#define SGD_PI M_PI +#endif + +#define SGD_DEGREES_TO_RADIANS (SGD_PI/SGD_180) +#define SGD_RADIANS_TO_DEGREES (SGD_180/SGD_PI) + +/* + These are just convenient redefinitions of standard + math library functions to stop float/double warnings. +*/ + +inline SGDfloat sgdSqrt ( const SGDfloat x ) { return sqrt ( x ) ; } +inline SGDfloat sgdSquare ( const SGDfloat x ) { return x * x ; } +inline SGDfloat sgdAbs ( const SGDfloat a ) { return ( a < SGD_ZERO ) ? -a : a ; } + +inline SGDfloat sgdASin ( SGDfloat s ) + { return (SGDfloat) asin ( s ) * SGD_RADIANS_TO_DEGREES ; } +inline SGDfloat sgdACos ( SGDfloat s ) + { return (SGDfloat) acos ( s ) * SGD_RADIANS_TO_DEGREES ; } +inline SGDfloat sgdATan ( SGDfloat s ) + { return (SGDfloat) atan ( s ) * SGD_RADIANS_TO_DEGREES ; } +inline SGDfloat sgdATan2 ( SGDfloat y, SGDfloat x ) + { return (SGDfloat) atan2 ( y,x ) * SGD_RADIANS_TO_DEGREES ; } +inline SGDfloat sgdSin ( SGDfloat s ) + { return (SGDfloat) sin ( s * SGD_DEGREES_TO_RADIANS ) ; } +inline SGDfloat sgdCos ( SGDfloat s ) + { return (SGDfloat) cos ( s * SGD_DEGREES_TO_RADIANS ) ; } +inline SGDfloat sgdTan ( SGDfloat s ) + { return (SGDfloat) tan ( s * SGD_DEGREES_TO_RADIANS ) ; } + +inline int sgdCompareFloat ( const SGDfloat a, const SGDfloat b, const SGDfloat tol ) +{ + if ( ( a + tol ) < b ) return -1 ; + if ( ( b + tol ) < a ) return 1 ; + return 0 ; +} + + +/* + Types used in SGD. +*/ + +typedef SGDfloat sgdVec2 [ 2 ] ; +typedef SGDfloat sgdVec3 [ 3 ] ; +typedef SGDfloat sgdVec4 [ 4 ] ; + +typedef sgdVec4 sgdQuat ; + +typedef SGDfloat sgdMat3 [3][3] ; +typedef SGDfloat sgdMat4 [4][4] ; + +struct sgdCoord +{ + sgdVec3 xyz ; + sgdVec3 hpr ; +} ; + +class sgdSphere ; +class sgdBox ; +class sgdFrustum ; + +/* + Some handy constants +*/ + +#define SGD_OUTSIDE FALSE +#define SGD_INSIDE TRUE +#define SGD_STRADDLE 2 + +inline SGDfloat sgdHeightOfPlaneVec2 ( const sgdVec4 plane, const sgdVec2 pnt ) +{ + if ( plane[2] == SGD_ZERO ) + return SGD_ZERO ; + else + return -( plane[0] * pnt[0] + plane[1] * pnt[1] + plane[3] ) / plane[2] ; +} + +/* + Convert a direction vector into a set of euler angles, + (with zero roll) +*/ + +extern void sgdHPRfromVec3 ( sgdVec3 hpr, const sgdVec3 src ) ; + +extern void sgdMakeCoordMat4 ( sgdMat4 dst, const SGDfloat x, const SGDfloat y, const SGDfloat z, + const SGDfloat h, const SGDfloat p, const SGDfloat r ) ; + +inline void sgdMakeCoordMat4( sgdMat4 dst, const sgdVec3 xyz, const sgdVec3 hpr ) +{ + sgdMakeCoordMat4 ( dst, xyz[0], xyz[1], xyz[2], + hpr[0], hpr[1], hpr[2] ) ; +} + +inline void sgdMakeCoordMat4( sgdMat4 dst, const sgdCoord *src ) +{ + sgdMakeCoordMat4 ( dst, src->xyz, src->hpr ) ; +} + +extern void sgdMakeRotMat4 ( sgdMat4 dst, const SGDfloat angle, const sgdVec3 axis ) ; + +inline void sgdMakeRotMat4 ( sgdMat4 dst, const sgdVec3 hpr ) +{ + sgdMakeCoordMat4 ( dst, SGD_ZERO, SGD_ZERO, SGD_ZERO, hpr[0], hpr[1], hpr[2] ) ; +} + +inline void sgdMakeRotMat4 ( sgdMat4 dst, const SGDfloat h, const SGDfloat p, const SGDfloat r ) +{ + sgdMakeCoordMat4 ( dst, SGD_ZERO, SGD_ZERO, SGD_ZERO, h, p, r ) ; +} + +extern void sgdMakeTransMat4 ( sgdMat4 dst, const sgdVec3 xyz ) ; +extern void sgdMakeTransMat4 ( sgdMat4 dst, const SGDfloat x, const SGDfloat y, const SGDfloat z ) ; + + +extern void sgdSetCoord ( sgdCoord *coord, const sgdMat4 src ) ; + +extern void sgdMultMat4 ( sgdMat4 dst, const sgdMat4 a, const sgdMat4 b ) ; +extern void sgdPostMultMat4 ( sgdMat4 dst, const sgdMat4 a ) ; +extern void sgdPreMultMat4 ( sgdMat4 dst, const sgdMat4 a ) ; + +extern void sgdTransposeNegateMat4 ( sgdMat4 dst ) ; +extern void sgdTransposeNegateMat4 ( sgdMat4 dst, const sgdMat4 src ) ; + +extern void sgdInvertMat4 ( sgdMat4 dst, const sgdMat4 src ) ; +inline void sgdInvertMat4 ( sgdMat4 dst ) { sgdInvertMat4 ( dst, dst ) ; } + +extern void sgdXformVec3 ( sgdVec3 dst, const sgdVec3 src, const sgdMat4 mat ) ; +extern void sgdXformPnt3 ( sgdVec3 dst, const sgdVec3 src, const sgdMat4 mat ) ; +extern void sgdXformVec4 ( sgdVec4 dst, const sgdVec4 src, const sgdMat4 mat ) ; +extern void sgdXformPnt4 ( sgdVec4 dst, const sgdVec4 src, const sgdMat4 mat ) ; +extern void sgdFullXformPnt3 ( sgdVec3 dst, const sgdVec3 src, const sgdMat4 mat ) ; +extern void sgdFullXformPnt4 ( sgdVec4 dst, const sgdVec4 src, const sgdMat4 mat ) ; + +inline void sgdXformVec3 ( sgdVec3 dst, const sgdMat4 mat ) { sgdXformVec3 ( dst, dst, mat ) ; } +inline void sgdXformPnt3 ( sgdVec3 dst, const sgdMat4 mat ) { sgdXformPnt3 ( dst, dst, mat ) ; } +inline void sgdXformVec4 ( sgdVec4 dst, const sgdMat4 mat ) { sgdXformVec4 ( dst, dst, mat ) ; } +inline void sgdXformPnt4 ( sgdVec4 dst, const sgdMat4 mat ) { sgdXformPnt4 ( dst, dst, mat ) ; } +inline void sgdFullXformPnt3 ( sgdVec3 dst, const sgdMat4 mat ) { sgdFullXformPnt3 ( dst, dst, mat ) ; } +inline void sgdFullXformPnt4 ( sgdVec4 dst, const sgdMat4 mat ) { sgdFullXformPnt4 ( dst, dst, mat ) ; } + +/* + Basic low-level vector functions. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + For each of Vec2, Vec3 and Vec4, we provide inlines for + + Zero - set all elements to zero. + Set - set each element individually. + Add - add vectors element by element. + Sub - subtract vectors element by element. + Scale - multiply each element of a vector by a variable. + Negate - negate each element of a vector. + Compare - compare vectors element by element with optional tolerance. + (return TRUE if vectors are equal - within tolerances) + Equal - return TRUE if vectors are exactly equal. + Length - compute length of a vector. + Distance - compute distance between two points. + LengthSquared - compute the square of the length of a vector. + DistanceSquared - compute the square of the distance between two points. + ScalarProduct - scalar (dot) product. + VectorProduct - vector (cross) product (3-element vectors ONLY!). + Normalise/Normalize - make vector be one unit long. + Lerp - linear interpolation by a fraction 'f'. +*/ + +inline void sgdZeroVec2 ( sgdVec2 dst ) { dst[0]=dst[1]=SGD_ZERO ; } +inline void sgdZeroVec3 ( sgdVec3 dst ) { dst[0]=dst[1]=dst[2]=SGD_ZERO ; } +inline void sgdZeroVec4 ( sgdVec4 dst ) { dst[0]=dst[1]=dst[2]=dst[3]=SGD_ZERO ; } + + +inline void sgdSetVec2 ( sgdVec2 dst, const SGDfloat x, const SGDfloat y ) +{ + dst [ 0 ] = x ; + dst [ 1 ] = y ; +} + +inline void sgdSetVec3 ( sgdVec3 dst, const SGDfloat x, const SGDfloat y, const SGDfloat z ) +{ + dst [ 0 ] = x ; + dst [ 1 ] = y ; + dst [ 2 ] = z ; +} + +inline void sgdSetVec4 ( sgdVec4 dst, const SGDfloat x, const SGDfloat y, const SGDfloat z, const SGDfloat w ) +{ + dst [ 0 ] = x ; + dst [ 1 ] = y ; + dst [ 2 ] = z ; + dst [ 3 ] = w ; +} + + +inline void sgdCopyVec2 ( sgdVec2 dst, const sgdVec2 src ) +{ + dst [ 0 ] = src [ 0 ] ; + dst [ 1 ] = src [ 1 ] ; +} + +inline void sgdCopyVec3 ( sgdVec3 dst, const sgdVec3 src ) +{ + dst [ 0 ] = src [ 0 ] ; + dst [ 1 ] = src [ 1 ] ; + dst [ 2 ] = src [ 2 ] ; +} + +inline void sgdCopyVec4 ( sgdVec4 dst, const sgdVec4 src ) +{ + dst [ 0 ] = src [ 0 ] ; + dst [ 1 ] = src [ 1 ] ; + dst [ 2 ] = src [ 2 ] ; + dst [ 3 ] = src [ 3 ] ; +} + + +inline void sgdAddVec2 ( sgdVec2 dst, const sgdVec2 src ) +{ + dst [ 0 ] += src [ 0 ] ; + dst [ 1 ] += src [ 1 ] ; +} + +inline void sgdAddVec3 ( sgdVec3 dst, const sgdVec3 src ) +{ + dst [ 0 ] += src [ 0 ] ; + dst [ 1 ] += src [ 1 ] ; + dst [ 2 ] += src [ 2 ] ; +} + +inline void sgdAddVec4 ( sgdVec4 dst, const sgdVec4 src ) +{ + dst [ 0 ] += src [ 0 ] ; + dst [ 1 ] += src [ 1 ] ; + dst [ 2 ] += src [ 2 ] ; + dst [ 3 ] += src [ 3 ] ; +} + + +inline void sgdAddVec2 ( sgdVec2 dst, const sgdVec2 src1, const sgdVec2 src2 ) +{ + dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] ; + dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] ; +} + +inline void sgdAddVec3 ( sgdVec3 dst, const sgdVec3 src1, const sgdVec3 src2 ) +{ + dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] ; + dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] ; + dst [ 2 ] = src1 [ 2 ] + src2 [ 2 ] ; +} + +inline void sgdAddVec4 ( sgdVec4 dst, const sgdVec4 src1, const sgdVec4 src2 ) +{ + dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] ; + dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] ; + dst [ 2 ] = src1 [ 2 ] + src2 [ 2 ] ; + dst [ 3 ] = src1 [ 3 ] + src2 [ 3 ] ; +} + + +inline void sgdSubVec2 ( sgdVec2 dst, const sgdVec2 src ) +{ + dst [ 0 ] -= src [ 0 ] ; + dst [ 1 ] -= src [ 1 ] ; +} + +inline void sgdSubVec3 ( sgdVec3 dst, const sgdVec3 src ) +{ + dst [ 0 ] -= src [ 0 ] ; + dst [ 1 ] -= src [ 1 ] ; + dst [ 2 ] -= src [ 2 ] ; +} + +inline void sgdSubVec4 ( sgdVec4 dst, const sgdVec4 src ) +{ + dst [ 0 ] -= src [ 0 ] ; + dst [ 1 ] -= src [ 1 ] ; + dst [ 2 ] -= src [ 2 ] ; + dst [ 3 ] -= src [ 3 ] ; +} + +inline void sgdSubVec2 ( sgdVec2 dst, const sgdVec2 src1, const sgdVec2 src2 ) +{ + dst [ 0 ] = src1 [ 0 ] - src2 [ 0 ] ; + dst [ 1 ] = src1 [ 1 ] - src2 [ 1 ] ; +} + +inline void sgdSubVec3 ( sgdVec3 dst, const sgdVec3 src1, const sgdVec3 src2 ) +{ + dst [ 0 ] = src1 [ 0 ] - src2 [ 0 ] ; + dst [ 1 ] = src1 [ 1 ] - src2 [ 1 ] ; + dst [ 2 ] = src1 [ 2 ] - src2 [ 2 ] ; +} + +inline void sgdSubVec4 ( sgdVec4 dst, const sgdVec4 src1, const sgdVec4 src2 ) +{ + dst [ 0 ] = src1 [ 0 ] - src2 [ 0 ] ; + dst [ 1 ] = src1 [ 1 ] - src2 [ 1 ] ; + dst [ 2 ] = src1 [ 2 ] - src2 [ 2 ] ; + dst [ 3 ] = src1 [ 3 ] - src2 [ 3 ] ; +} + + +inline void sgdNegateVec2 ( sgdVec2 dst ) +{ + dst [ 0 ] = -dst [ 0 ] ; + dst [ 1 ] = -dst [ 1 ] ; +} + +inline void sgdNegateVec3 ( sgdVec3 dst ) +{ + dst [ 0 ] = -dst [ 0 ] ; + dst [ 1 ] = -dst [ 1 ] ; + dst [ 2 ] = -dst [ 2 ] ; +} + +inline void sgdNegateVec4 ( sgdVec4 dst ) +{ + dst [ 0 ] = -dst [ 0 ] ; + dst [ 1 ] = -dst [ 1 ] ; + dst [ 2 ] = -dst [ 2 ] ; + dst [ 3 ] = -dst [ 3 ] ; +} + + +inline void sgdNegateVec2 ( sgdVec2 dst, const sgdVec2 src ) +{ + dst [ 0 ] = -src [ 0 ] ; + dst [ 1 ] = -src [ 1 ] ; +} + +inline void sgdNegateVec3 ( sgdVec3 dst, const sgdVec3 src ) +{ + dst [ 0 ] = -src [ 0 ] ; + dst [ 1 ] = -src [ 1 ] ; + dst [ 2 ] = -src [ 2 ] ; +} + +inline void sgdNegateVec4 ( sgdVec4 dst, const sgdVec4 src ) +{ + dst [ 0 ] = -src [ 0 ] ; + dst [ 1 ] = -src [ 1 ] ; + dst [ 2 ] = -src [ 2 ] ; + dst [ 3 ] = -src [ 3 ] ; +} + + +inline void sgdScaleVec2 ( sgdVec2 dst, const SGDfloat s ) +{ + dst [ 0 ] *= s ; + dst [ 1 ] *= s ; +} + +inline void sgdScaleVec3 ( sgdVec3 dst, const SGDfloat s ) +{ + dst [ 0 ] *= s ; + dst [ 1 ] *= s ; + dst [ 2 ] *= s ; +} + +inline void sgdScaleVec4 ( sgdVec4 dst, const SGDfloat s ) +{ + dst [ 0 ] *= s ; + dst [ 1 ] *= s ; + dst [ 2 ] *= s ; + dst [ 3 ] *= s ; +} + +inline void sgdScaleVec2 ( sgdVec2 dst, const sgdVec2 src, const SGDfloat s ) +{ + dst [ 0 ] = src [ 0 ] * s ; + dst [ 1 ] = src [ 1 ] * s ; +} + +inline void sgdScaleVec3 ( sgdVec3 dst, const sgdVec3 src, const SGDfloat s ) +{ + dst [ 0 ] = src [ 0 ] * s ; + dst [ 1 ] = src [ 1 ] * s ; + dst [ 2 ] = src [ 2 ] * s ; +} + +inline void sgdScaleVec4 ( sgdVec4 dst, const sgdVec4 src, const SGDfloat s ) +{ + dst [ 0 ] = src [ 0 ] * s ; + dst [ 1 ] = src [ 1 ] * s ; + dst [ 2 ] = src [ 2 ] * s ; + dst [ 3 ] = src [ 3 ] * s ; +} + + +inline void sgdAddScaledVec2 ( sgdVec2 dst, const sgdVec2 src, const SGDfloat s ) +{ + dst [ 0 ] += src [ 0 ] * s ; + dst [ 1 ] += src [ 1 ] * s ; +} + +inline void sgdAddScaledVec3 ( sgdVec3 dst, const sgdVec3 src, const SGDfloat s ) +{ + dst [ 0 ] += src [ 0 ] * s ; + dst [ 1 ] += src [ 1 ] * s ; + dst [ 2 ] += src [ 2 ] * s ; +} + +inline void sgdAddScaledVec4 ( sgdVec4 dst, const sgdVec4 src, const SGDfloat s ) +{ + dst [ 0 ] += src [ 0 ] * s ; + dst [ 1 ] += src [ 1 ] * s ; + dst [ 2 ] += src [ 2 ] * s ; + dst [ 3 ] += src [ 3 ] * s ; +} + + +inline void sgdAddScaledVec2 ( sgdVec2 dst, const sgdVec2 src1, const sgdVec2 src2, const SGDfloat s ) +{ + dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] * s ; + dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] * s ; +} + +inline void sgdAddScaledVec3 ( sgdVec3 dst, const sgdVec3 src1, const sgdVec3 src2, const SGDfloat s ) +{ + dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] * s ; + dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] * s ; + dst [ 2 ] = src1 [ 2 ] + src2 [ 2 ] * s ; +} + +inline void sgdAddScaledVec4 ( sgdVec4 dst, const sgdVec4 src1, const sgdVec4 src2, const SGDfloat s ) +{ + dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] * s ; + dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] * s ; + dst [ 2 ] = src1 [ 2 ] + src2 [ 2 ] * s ; + dst [ 3 ] = src1 [ 3 ] + src2 [ 3 ] * s ; +} + + + +inline int sgdCompareVec2 ( const sgdVec2 a, const sgdVec2 b, const SGDfloat tol ) +{ + int val = 0 ; + + if ( ( val = sgdCompareFloat( a[0], b[0], tol ) ) != 0 ) return val ; + if ( ( val = sgdCompareFloat( a[1], b[1], tol ) ) != 0 ) return val ; + + return 0 ; +} + +inline int sgdCompareVec3 ( const sgdVec3 a, const sgdVec3 b, const SGDfloat tol ) +{ + int val = 0 ; + + if ( ( val = sgdCompareFloat( a[0], b[0], tol ) ) != 0 ) return val ; + if ( ( val = sgdCompareFloat( a[1], b[1], tol ) ) != 0 ) return val ; + if ( ( val = sgdCompareFloat( a[2], b[2], tol ) ) != 0 ) return val ; + + return 0 ; +} + +inline int sgdCompareVec4 ( const sgdVec4 a, const sgdVec4 b, const SGDfloat tol ) +{ + int val = 0 ; + + if ( ( val = sgdCompareFloat( a[0], b[0], tol ) ) != 0 ) return val ; + if ( ( val = sgdCompareFloat( a[1], b[1], tol ) ) != 0 ) return val ; + if ( ( val = sgdCompareFloat( a[2], b[2], tol ) ) != 0 ) return val ; + if ( ( val = sgdCompareFloat( a[3], b[3], tol ) ) != 0 ) return val ; + + return 0 ; +} + + +inline int sgdEqualVec2 ( const sgdVec2 a, const sgdVec2 b ) +{ + return a[0] == b[0] && + a[1] == b[1] ; +} + +inline int sgdEqualVec3 ( const sgdVec3 a, const sgdVec3 b ) +{ + return a[0] == b[0] && + a[1] == b[1] && + a[2] == b[2] ; +} + +inline int sgdEqualVec4 ( const sgdVec4 a, const sgdVec4 b ) +{ + return a[0] == b[0] && + a[1] == b[1] && + a[2] == b[2] && + a[3] == b[3] ; +} + + +inline SGDfloat sgdScalarProductVec2 ( const sgdVec2 a, const sgdVec2 b ) +{ + return a[0]*b[0] + a[1]*b[1] ; +} + +inline SGDfloat sgdScalarProductVec3 ( const sgdVec3 a, const sgdVec3 b ) +{ + return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] ; +} + +inline SGDfloat sgdScalarProductVec4 ( const sgdVec4 a, const sgdVec4 b ) +{ + return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3] ; +} + + +extern void sgdVectorProductVec3 ( sgdVec3 dst, const sgdVec3 a, const sgdVec3 b ) ; + + +inline void sgdLerpVec4 ( sgdVec4 dst, const sgdVec4 a, const sgdVec4 b, const SGDfloat f ) +{ + dst[0] = a[0] + f * ( b[0] - a[0] ) ; + dst[1] = a[1] + f * ( b[1] - a[1] ) ; + dst[2] = a[2] + f * ( b[2] - a[2] ) ; + dst[3] = a[3] + f * ( b[3] - a[3] ) ; +} + +inline void sgdLerpVec3 ( sgdVec3 dst, const sgdVec3 a, const sgdVec3 b, const SGDfloat f ) +{ + dst[0] = a[0] + f * ( b[0] - a[0] ) ; + dst[1] = a[1] + f * ( b[1] - a[1] ) ; + dst[2] = a[2] + f * ( b[2] - a[2] ) ; +} + +inline void sgdLerpVec2 ( sgdVec2 dst, const sgdVec2 a, const sgdVec2 b, const SGDfloat f ) +{ + dst[0] = a[0] + f * ( b[0] - a[0] ) ; + dst[1] = a[1] + f * ( b[1] - a[1] ) ; +} + +inline void sgdLerpAnglesVec3 ( sgdVec3 dst, const sgdVec3 a, + const sgdVec3 b, + const SGDfloat f ) +{ + sgdVec3 tmp ; + + if ( b[0] - a[0] > 180.0 ) tmp[0] = a[0] + 360.0 ; else + if ( b[0] - a[0] < -180.0 ) tmp[0] = a[0] - 360.0 ; else tmp[0] = a[0] ; + + if ( b[1] - a[1] > 180.0 ) tmp[1] = a[1] + 360.0 ; else + if ( b[1] - a[1] < -180.0 ) tmp[1] = a[1] - 360.0 ; else tmp[1] = a[1] ; + + if ( b[2] - a[2] > 180.0 ) tmp[2] = a[2] + 360.0 ; else + if ( b[2] - a[2] < -180.0 ) tmp[2] = a[2] - 360.0 ; else tmp[2] = a[2] ; + + dst[0] = tmp[0] + f * ( b[0] - tmp[0] ) ; + dst[1] = tmp[1] + f * ( b[1] - tmp[1] ) ; + dst[2] = tmp[2] + f * ( b[2] - tmp[2] ) ; +} + + + + +inline SGDfloat sgdDistanceSquaredVec2 ( const sgdVec2 a, const sgdVec2 b ) +{ + return sgdSquare ( a[0]-b[0] ) + sgdSquare ( a[1]-b[1] ) ; +} + +inline SGDfloat sgdDistanceSquaredVec3 ( const sgdVec3 a, const sgdVec3 b ) +{ + return sgdSquare ( a[0]-b[0] ) + sgdSquare ( a[1]-b[1] ) + + sgdSquare ( a[2]-b[2] ) ; +} + +inline SGDfloat sgdDistanceSquaredVec4 ( const sgdVec4 a, const sgdVec4 b ) +{ + return sgdSquare ( a[0]-b[0] ) + sgdSquare ( a[1]-b[1] ) + + sgdSquare ( a[2]-b[2] ) + sgdSquare ( a[3]-b[3] ) ; +} + + +inline SGDfloat sgdDistanceVec2 ( const sgdVec2 a, const sgdVec2 b ) +{ + return sgdSqrt ( sgdSquare ( a[0]-b[0] ) + sgdSquare ( a[1]-b[1] ) ) ; +} + +inline SGDfloat sgdDistanceVec3 ( const sgdVec3 a, const sgdVec3 b ) +{ + return sgdSqrt ( sgdSquare ( a[0]-b[0] ) + sgdSquare ( a[1]-b[1] ) + + sgdSquare ( a[2]-b[2] ) ) ; +} + +inline SGDfloat sgdDistanceVec4 ( const sgdVec4 a, const sgdVec4 b ) +{ + return sgdSqrt ( sgdSquare ( a[0]-b[0] ) + sgdSquare ( a[1]-b[1] ) + + sgdSquare ( a[2]-b[2] ) + sgdSquare ( a[3]-b[3] ) ) ; +} + + +inline SGDfloat sgdLengthVec2 ( sgdVec2 const src ) +{ + return sgdSqrt ( sgdScalarProductVec2 ( src, src ) ) ; +} + +inline SGDfloat sgdLengthVec3 ( sgdVec3 const src ) +{ + return sgdSqrt ( sgdScalarProductVec3 ( src, src ) ) ; +} + +inline SGDfloat sgdLengthVec4 ( sgdVec4 const src ) +{ + return sgdSqrt ( sgdScalarProductVec4 ( src, src ) ) ; +} + +inline SGDfloat sgdLengthSquaredVec2 ( sgdVec2 const src ) +{ + return sgdScalarProductVec2 ( src, src ) ; +} + +inline SGDfloat sgdLengthSquaredVec3 ( sgdVec3 const src ) +{ + return sgdScalarProductVec3 ( src, src ) ; +} + +inline SGDfloat sgdLengthSquaredVec4 ( sgdVec4 const src ) +{ + return sgdScalarProductVec4 ( src, src ) ; +} + +/* Anglo-US spelling issues. */ +#define sgdNormalizeVec2 sgdNormaliseVec2 +#define sgdNormalizeVec3 sgdNormaliseVec3 +#define sgdNormalizeVec4 sgdNormaliseVec4 +#define sgdNormalizeQuat sgdNormaliseQuat + +inline void sgdNormaliseVec2 ( sgdVec2 dst ) +{ + sgdScaleVec2 ( dst, SGD_ONE / sgdLengthVec2 ( dst ) ) ; +} + +inline void sgdNormaliseVec3 ( sgdVec3 dst ) +{ + sgdScaleVec3 ( dst, SGD_ONE / sgdLengthVec3 ( dst ) ) ; +} + +inline void sgdNormaliseVec4 ( sgdVec4 dst ) +{ + sgdScaleVec4 ( dst, SGD_ONE / sgdLengthVec4 ( dst ) ) ; +} + +inline void sgdNormaliseVec2 ( sgdVec2 dst, const sgdVec2 src ) +{ + sgdScaleVec2 ( dst, src, SGD_ONE / sgdLengthVec2 ( src ) ) ; +} + +inline void sgdNormaliseVec3 ( sgdVec3 dst, const sgdVec3 src ) +{ + sgdScaleVec3 ( dst, src, SGD_ONE / sgdLengthVec3 ( src ) ) ; +} + +inline void sgdNormaliseVec4 ( sgdVec4 dst, const sgdVec4 src ) +{ + sgdScaleVec4 ( dst, src, SGD_ONE / sgdLengthVec4 ( src ) ) ; +} + + +inline void sgdZeroCoord ( sgdCoord *dst ) +{ + sgdSetVec3 ( dst->xyz, SGD_ZERO, SGD_ZERO, SGD_ZERO ) ; + sgdSetVec3 ( dst->hpr, SGD_ZERO, SGD_ZERO, SGD_ZERO ) ; +} + +inline void sgdSetCoord ( sgdCoord *dst, const SGDfloat x, const SGDfloat y, const SGDfloat z, + const SGDfloat h, const SGDfloat p, const SGDfloat r ) +{ + sgdSetVec3 ( dst->xyz, x, y, z ) ; + sgdSetVec3 ( dst->hpr, h, p, r ) ; +} + +inline void sgdSetCoord ( sgdCoord *dst, const sgdVec3 xyz, const sgdVec3 hpr ) +{ + sgdCopyVec3 ( dst->xyz, xyz ) ; + sgdCopyVec3 ( dst->hpr, hpr ) ; +} + +inline void sgdCopyCoord ( sgdCoord *dst, const sgdCoord *src ) +{ + sgdCopyVec3 ( dst->xyz, src->xyz ) ; + sgdCopyVec3 ( dst->hpr, src->hpr ) ; +} + + + +inline void sgdCopyMat4 ( sgdMat4 dst, const sgdMat4 src ) +{ + sgdCopyVec4 ( dst[ 0 ], src[ 0 ] ) ; + sgdCopyVec4 ( dst[ 1 ], src[ 1 ] ) ; + sgdCopyVec4 ( dst[ 2 ], src[ 2 ] ) ; + sgdCopyVec4 ( dst[ 3 ], src[ 3 ] ) ; +} + + +inline void sgdScaleMat4 ( sgdMat4 dst, const sgdMat4 src, const SGDfloat scale ) +{ + sgdScaleVec4 ( dst[0], src[0], scale ) ; + sgdScaleVec4 ( dst[1], src[1], scale ) ; + sgdScaleVec4 ( dst[2], src[2], scale ) ; + sgdScaleVec4 ( dst[3], src[3], scale ) ; +} + + +inline void sgdMakeIdentMat4 ( sgdMat4 dst ) +{ + sgdSetVec4 ( dst[0], SGD_ONE , SGD_ZERO, SGD_ZERO, SGD_ZERO ) ; + sgdSetVec4 ( dst[1], SGD_ZERO, SGD_ONE , SGD_ZERO, SGD_ZERO ) ; + sgdSetVec4 ( dst[2], SGD_ZERO, SGD_ZERO, SGD_ONE , SGD_ZERO ) ; + sgdSetVec4 ( dst[3], SGD_ZERO, SGD_ZERO, SGD_ZERO, SGD_ONE ) ; +} + + +extern void sgdMakeTransMat4 ( sgdMat4 m, const SGDfloat x, const SGDfloat y, const SGDfloat z ) ; +extern void sgdMakeTransMat4 ( sgdMat4 m, const sgdVec3 xyz ) ; +extern void sgdMakeCoordMat4 ( sgdMat4 m, const SGDfloat x, const SGDfloat y, const SGDfloat z, + const SGDfloat h, const SGDfloat p, const SGDfloat r ) ; +extern void sgdMakeCoordMat4 ( sgdMat4 m, const sgdCoord *c ) ; + +extern int sgdCompare3DSqdDist ( const sgdVec3 a, const sgdVec3 b, const SGDfloat sqd_dist ) ; + +inline SGDfloat sgdDistToLineVec2 ( const sgdVec3 line, const sgdVec2 pnt ) +{ + return sgdScalarProductVec2 ( line, pnt ) + line[2] ; +} + + +struct sgdLineSegment3 /* Bounded line segment */ +{ + sgdVec3 a ; + sgdVec3 b ; +} ; + +struct sgdLine3 /* Infinite line */ +{ + sgdVec3 point_on_line ; + sgdVec3 direction_vector ; /* Should be a unit vector */ +} ; + + +inline void sgdLineSegment3ToLine3 ( sgdLine3 *line, + const sgdLineSegment3 lineseg ) +{ + sgdCopyVec3 ( line->point_on_line , lineseg.a ) ; + sgdSubVec3 ( line->direction_vector, lineseg.b, lineseg.a ) ; + sgdNormaliseVec3 ( line->direction_vector ) ; +} + + +SGDfloat sgdDistSquaredToLineVec3 ( const sgdLine3 line, + const sgdVec3 pnt ) ; +SGDfloat sgdDistSquaredToLineSegmentVec3 ( const sgdLineSegment3 line, + const sgdVec3 pnt ) ; + + +inline SGDfloat sgdDistToLineVec3 ( const sgdLine3 line, + const sgdVec3 pnt ) +{ + return sgdSqrt ( sgdDistSquaredToLineVec3 ( line, pnt ) ); +} + + +inline SGDfloat sgdDistToLineSegmentVec3 ( const sgdLineSegment3 line, + const sgdVec3 pnt ) +{ + return sgdSqrt ( sgdDistSquaredToLineSegmentVec3(line,pnt) ) ; +} + +inline SGDfloat sgdDistToPlaneVec3 ( const sgdVec4 plane, const sgdVec3 pnt ) +{ + return sgdScalarProductVec3 ( plane, pnt ) + plane[3] ; +} + +inline SGDfloat sgdHeightAbovePlaneVec3 ( const sgdVec4 plane, const sgdVec3 pnt ) +{ + return pnt[2] - sgdHeightOfPlaneVec2 ( plane, pnt ) ; +} + +extern void sgdReflectInPlaneVec3 ( sgdVec3 dst, const sgdVec3 src, const sgdVec4 plane ) ; + +inline void sgdReflectInPlaneVec3 ( sgdVec3 dst, const sgdVec4 plane ) +{ + sgdReflectInPlaneVec3 ( dst, dst, plane ) ; +} + +extern void sgdMakeNormal ( sgdVec3 dst, const sgdVec3 a, const sgdVec3 b, const sgdVec3 c ) ; + +inline void sgdMake2DLine ( sgdVec3 dst, const sgdVec2 a, const sgdVec2 b ) +{ + dst[0] = b[1]-a[1] ; + dst[1] = -b[0]-a[0] ; + sgdNormalizeVec2 ( dst ) ; + dst[2] = - ( dst[0]*a[0] + dst[1]*a[1] ) ; +} + +inline void sgdMakePlane ( sgdVec4 dst, const sgdVec3 normal, const sgdVec3 pnt ) +{ + sgdCopyVec3 ( dst, normal ) ; + dst [ 3 ] = - sgdScalarProductVec3 ( normal, pnt ) ; +} + +inline void sgdMakePlane ( sgdVec4 dst, const sgdVec3 a, const sgdVec3 b, const sgdVec3 c ) +{ + /* + Ax + By + Cz + D == 0 ; + D = - ( Ax + By + Cz ) + = - ( A*a[0] + B*a[1] + C*a[2] ) + = - sgdScalarProductVec3 ( normal, a ) ; + */ + + sgdMakeNormal ( dst, a, b, c ) ; + + dst [ 3 ] = - sgdScalarProductVec3 ( dst, a ) ; +} + +SGDfloat sgdTriArea( sgdVec3 p0, sgdVec3 p1, sgdVec3 p2 ); + + +// Fast code. Result is in the range 0..180: +inline SGDfloat sgdAngleBetweenNormalizedVec3 ( sgdVec3 v1, sgdVec3 v2 ) +{ + SGDfloat f = sgdScalarProductVec3 ( v1, v2 ) ; + + return (float) acos ( ( f >= 1.0f ) ? 1.0f : + ( f <= -1.0f ) ? -1.0f : f ) * + SGD_RADIANS_TO_DEGREES ; +} + +// Fast code. Result is in the range 0..180: + +SGDfloat sgdAngleBetweenVec3 ( sgdVec3 v1, sgdVec3 v2 ); + +// All three have to be normalized. Slow code. Result is in the range 0..360: + +SGDfloat sgdAngleBetweenNormalizedVec3 (sgdVec3 first, sgdVec3 second, sgdVec3 normal); + +// Normal has to be normalized. Slow code. Result is in the range 0..360: + +SGDfloat sgdAngleBetweenVec3 ( sgdVec3 v1, sgdVec3 v2, sgdVec3 normal ); + + + +class sgdSphere +{ +public: + sgdVec3 center ; + SGDfloat radius ; + + + const SGDfloat *getCenter (void) const { return center ; } + + void setCenter ( const sgdVec3 c ) + { + sgdCopyVec3 ( center, c ) ; + } + + void setCenter ( const SGDfloat x, const SGDfloat y, const SGDfloat z ) + { + sgdSetVec3 ( center, x, y, z ) ; + } + + SGDfloat getRadius (void) const { return radius ; } + void setRadius ( const SGDfloat r ) { radius = r ; } + + int isEmpty (void) const { return radius < SGD_ZERO ; } + void empty (void) { radius = - SGD_ONE ; } + + void orthoXform ( const sgdMat4 m ) + { + sgdXformPnt3 ( center, center, m ) ; + // radius *= sgdLengthVec3 ( m[0] ) ; + } + + void extend ( const sgdSphere *s ) ; + void extend ( const sgdBox *b ) ; + void extend ( const sgdVec3 v ) ; + + int intersects ( const sgdSphere *s ) const + { + return sgdCompare3DSqdDist ( center, s->getCenter(), + sgdSquare ( radius + s->getRadius() ) ) <= 0 ; + } + + int intersects ( const sgdVec4 plane ) const + { + return sgdAbs ( sgdDistToPlaneVec3 ( plane, center ) ) <= radius ; + } + + int intersects ( const sgdBox *b ) const ; +} ; + + +class sgdBox +{ +public: + sgdVec3 min ; + sgdVec3 max ; + + + const SGDfloat *getMin (void) const { return min ; } + const SGDfloat *getMax (void) const { return max ; } + + void setMin ( const SGDfloat x, const SGDfloat y, const SGDfloat z ) + { + sgdSetVec3 ( min, x, y, z ) ; + } + + void setMin ( const sgdVec3 src ) + { + sgdCopyVec3 ( min, src ) ; + } + + void setMax ( const SGDfloat x, const SGDfloat y, const SGDfloat z ) + { + sgdSetVec3 ( max, x, y, z ) ; + } + + void setMax ( const sgdVec3 src ) + { + sgdCopyVec3 ( max, src ) ; + } + + int isEmpty(void) const + { + return ( min[0] > max[0] || + min[1] > max[1] || + min[2] > max[2] ) ; + } + + void empty (void) + { + sgdSetVec3 ( min, SGD_MAX, SGD_MAX, SGD_MAX ) ; + sgdSetVec3 ( max, -SGD_MAX, -SGD_MAX, -SGD_MAX ) ; + } + + void extend ( const sgdSphere *s ) ; + void extend ( const sgdBox *b ) ; + void extend ( const sgdVec3 v ) ; + + int intersects ( const sgdSphere *s ) const + { + return s -> intersects ( this ) ; + } + + int intersects ( const sgdBox *b ) const + { + return min[0] <= b->getMax()[0] && max[0] >= b->getMin()[0] && + min[1] <= b->getMax()[1] && max[1] >= b->getMin()[1] && + min[2] <= b->getMax()[2] && max[2] >= b->getMin()[2] ; + } + + int intersects ( const sgdVec4 plane ) const ; +} ; + + +class sgdFrustum +{ + /* Is the projection orthographic (or perspective)? */ + int ortho ; + + /* The parameters for glFrustum/glOrtho */ + + SGDfloat left, right, bot, top, nnear, ffar ; + + /* The computed projection matrix for this frustum */ + + sgdMat4 mat ; + + /* The A,B,C,D terms of the plane equations of the clip planes */ + /* A point (x,y,z) is inside the frustum iff Ax + By + Cz + D >= 0 for all planes */ + + sgdVec4 plane [ 6 ] ; + + /* These two are only valid for simple frusta */ + + SGDfloat hfov ; /* Horizontal Field of View -or- Orthographic Width */ + SGDfloat vfov ; /* Vertical Field of View -or- Orthographic Height */ + + void update (void) ; + int getOutcode ( const sgdVec4 src ) const ; + +public: + + sgdFrustum (void) + { + ortho = FALSE ; + nnear = SGD_ONE ; + ffar = 1000000.0f ; + hfov = SGD_45 ; + vfov = SGD_45 ; + update () ; + } + + void setFrustum ( const SGDfloat l, const SGDfloat r, + const SGDfloat b, const SGDfloat t, + const SGDfloat n, const SGDfloat f ) + { + ortho = FALSE ; + left = l ; + right = r ; + bot = b ; + top = t ; + nnear = n ; + ffar = f ; + hfov = vfov = SGD_ZERO ; + update () ; + } + + void setOrtho ( const SGDfloat l, const SGDfloat r, + const SGDfloat b, const SGDfloat t, + const SGDfloat n, const SGDfloat f ) + { + ortho = TRUE ; + left = l ; + right = r ; + bot = b ; + top = t ; + nnear = n ; + ffar = f ; + hfov = vfov = SGD_ZERO ; + update () ; + } + + void getMat4 ( sgdMat4 dst ) { sgdCopyMat4 ( dst, mat ) ; } + + SGDfloat getLeft (void) const { return left ; } + SGDfloat getRight(void) const { return right ; } + SGDfloat getBot (void) const { return bot ; } + SGDfloat getTop (void) const { return top ; } + SGDfloat getNear (void) const { return nnear ; } + SGDfloat getFar (void) const { return ffar ; } + + const SGDfloat *getPlane ( int i ) const { return plane [ i ] ; } + + SGDfloat getHFOV (void) const { return hfov ; } + SGDfloat getVFOV (void) const { return vfov ; } + + void getFOV ( SGDfloat *h, SGDfloat *v ) const + { + if ( h != (SGDfloat *) 0 ) *h = hfov ; + if ( v != (SGDfloat *) 0 ) *v = vfov ; + } + + void setFOV ( const SGDfloat h, const SGDfloat v ) + { + ortho = FALSE ; + hfov = ( h <= 0 ) ? ( v * SGD_FOUR / SGD_THREE ) : h ; + vfov = ( v <= 0 ) ? ( h * SGD_THREE / SGD_FOUR ) : v ; + update () ; + } + + void getOrtho ( SGDfloat *w, SGDfloat *h ) const + { + if ( w != (SGDfloat *) 0 ) *w = right - left ; + if ( h != (SGDfloat *) 0 ) *h = top - bot ; + } + + void setOrtho ( const SGDfloat w, const SGDfloat h ) + { + ortho = TRUE ; + hfov = ( w <= 0 ) ? ( h * SGD_FOUR / SGD_THREE ) : w ; + vfov = ( h <= 0 ) ? ( w * SGD_FOUR / SGD_THREE ) : h ; + update () ; + } + + void getNearFar ( SGDfloat *n, SGDfloat *f ) const + { + if ( n != (SGDfloat *) 0 ) *n = nnear ; + if ( f != (SGDfloat *) 0 ) *f = ffar ; + } + + void setNearFar ( const SGDfloat n, const SGDfloat f ) + { + nnear = n ; + ffar = f ; + update () ; + } + + int isOrtho (void) const { return ortho ; } + + int contains ( const sgdVec3 p ) const ; + int contains ( const sgdSphere *s ) const ; + int contains ( const sgdBox *b ) const ; +} ; + + +/* + Quaternion routines are Copyright (C) 1999 + Kevin B. Thompson + Modified by Sylvan W. Clebsch + Largely rewritten by "Negative0" +*/ + +/* + Quaternion structure w = real, (x, y, z) = vector + CHANGED sqQuat to float array so that syntax matches + vector and matrix routines +*/ + + +inline void sgdMakeIdentQuat ( sgdQuat dst ) +{ + sgdSetVec4 ( dst, SGD_ZERO, SGD_ZERO, SGD_ZERO, SGD_ONE ) ; +} + + +inline void sgdSetQuat ( sgdQuat dst, + const SGDfloat w, const SGDfloat x, + const SGDfloat y, const SGDfloat z ) +{ + sgdSetVec4 ( dst, x, y, z, w ) ; +} + +inline void sgdCopyQuat ( sgdQuat dst, const sgdQuat src ) +{ + sgdCopyVec4 ( dst, src ) ; +} + + +/* Construct a unit quaternion (length==1) */ + +inline void sgdNormaliseQuat ( sgdQuat dst, const sgdQuat src ) +{ + SGDfloat d = sgdScalarProductVec4 ( src, src ) ; + + d = (d > SGD_ZERO) ? (SGD_ONE / sgdSqrt ( d )) : SGD_ONE ; + + sgdScaleVec4 ( dst, src, d ) ; +} + + + +inline void sgdNormaliseQuat ( sgdQuat dst ) { sgdNormaliseQuat ( dst, dst ) ; } + + +inline void sgdInvertQuat ( sgdQuat dst, const sgdQuat src ) +{ + SGDfloat d = sgdScalarProductVec4 ( src, src ) ; + + d = ( d == SGD_ZERO ) ? SGD_ONE : ( SGD_ONE / d ) ; + + dst[SG_W] = src[SG_W] * d ; + dst[SG_X] = -src[SG_X] * d ; + dst[SG_Y] = -src[SG_Y] * d ; + dst[SG_Z] = -src[SG_Z] * d ; +} + +inline void sgdInvertQuat ( sgdQuat dst ) { sgdInvertQuat ( dst, dst ) ; } + + +/* Make an angle and axis of rotation from a Quaternion. */ + +void sgdQuatToAngleAxis ( SGDfloat *angle, sgdVec3 axis, const sgdQuat src ) ; +void sgdQuatToAngleAxis ( SGDfloat *angle, + SGDfloat *x, SGDfloat *y, SGDfloat *z, + const sgdQuat src ) ; + +/* Make a quaternion from a given angle and axis of rotation */ + +void sgdAngleAxisToQuat ( sgdQuat dst, + const SGDfloat angle, const sgdVec3 axis ) ; +void sgdAngleAxisToQuat ( sgdQuat dst, + const SGDfloat angle, + const SGDfloat x, const SGDfloat y, const SGDfloat z ); + +/* Convert a matrix to/from a quat */ + +void sgdMatrixToQuat ( sgdQuat quat, const sgdMat4 m ) ; +void sgdQuatToMatrix ( sgdMat4 m, const sgdQuat quat ) ; + +/* Convert a set of eulers to/from a quat */ + +void sgdQuatToEuler( sgdVec3 hpr, const sgdQuat quat ) ; +void sgdEulerToQuat( sgdQuat quat, const sgdVec3 hpr ) ; + +inline void sgdEulerToQuat( sgdQuat dst, + SGDfloat h, SGDfloat p, SGDfloat r ) +{ + sgdVec3 hpr ; + + sgdSetVec3 ( hpr, h, p, r ) ; + + sgdEulerToQuat( dst, hpr ) ; +} + +inline void sgdHPRToQuat ( sgdQuat dst, SGDfloat h, SGDfloat p, SGDfloat r ) +{ + sgdVec3 hpr; + + hpr[0] = h * SGD_DEGREES_TO_RADIANS ; + hpr[1] = p * SGD_DEGREES_TO_RADIANS ; + hpr[2] = r * SGD_DEGREES_TO_RADIANS ; + + sgdEulerToQuat( dst, hpr ) ; +} + +inline void sgdHPRToQuat ( sgdQuat dst, const sgdVec3 hpr ) +{ + sgdVec3 tmp ; + + sgdScaleVec3 ( tmp, hpr, SGD_DEGREES_TO_RADIANS ) ; + + sgdEulerToQuat ( dst, tmp ) ; +} + +/* Multiply quaternions together (concatenate rotations) */ + +void sgdMultQuat ( sgdQuat dst, const sgdQuat a, const sgdQuat b ) ; + +inline void sgdPostMultQuat ( sgdQuat dst, const sgdQuat q ) +{ + sgdQuat r ; + + sgdCopyQuat ( r, dst ) ; + sgdMultQuat ( dst, r, q ) ; +} + +inline void sgdPreMultQuat ( sgdQuat dst, const sgdQuat q ) +{ + sgdQuat r ; + + sgdCopyQuat ( r, dst ) ; + sgdMultQuat ( dst, q, r ) ; +} + + +/* Rotate a quaternion by a given angle and axis (convenience function) */ + + +inline void sgdRotQuat ( sgdQuat dst, const SGDfloat angle, const sgdVec3 axis ) +{ + sgdQuat q ; + + sgdAngleAxisToQuat ( q, angle, axis ) ; + sgdPostMultQuat ( dst, q ) ; + sgdNormaliseQuat ( dst ) ; +} + + +inline void sgdRotQuat ( sgdQuat dst, + const SGDfloat angle, + const SGDfloat x, const SGDfloat y, const SGDfloat z ) +{ + sgdVec3 axis ; + + sgdSetVec3 ( axis, x, y, z ) ; + sgdRotQuat ( dst, angle, axis ) ; +} + +/* SWC - Interpolate between to quaternions */ + +extern void sgdSlerpQuat ( sgdQuat dst, + const sgdQuat from, const sgdQuat to, + const SGDfloat t ) ; + + +/* Conversions between sg and sgd types. */ + +inline void sgSetVec2 ( sgVec2 dst, sgdVec2 src ) +{ + dst [ 0 ] = (SGfloat) src [ 0 ] ; + dst [ 1 ] = (SGfloat) src [ 1 ] ; +} + +inline void sgSetVec3 ( sgVec3 dst, sgdVec3 src ) +{ + dst [ 0 ] = (SGfloat) src [ 0 ] ; + dst [ 1 ] = (SGfloat) src [ 1 ] ; + dst [ 2 ] = (SGfloat) src [ 2 ] ; +} + +inline void sgSetVec4 ( sgVec4 dst, sgdVec4 src ) +{ + dst [ 0 ] = (SGfloat) src [ 0 ] ; + dst [ 1 ] = (SGfloat) src [ 1 ] ; + dst [ 2 ] = (SGfloat) src [ 2 ] ; + dst [ 3 ] = (SGfloat) src [ 3 ] ; +} + +inline void sgdSetVec2 ( sgdVec2 dst, sgVec2 src ) +{ + dst [ 0 ] = (SGDfloat) src [ 0 ] ; + dst [ 1 ] = (SGDfloat) src [ 1 ] ; +} + +inline void sgdSetVec3 ( sgdVec3 dst, sgVec3 src ) +{ + dst [ 0 ] = (SGDfloat) src [ 0 ] ; + dst [ 1 ] = (SGDfloat) src [ 1 ] ; + dst [ 2 ] = (SGDfloat) src [ 2 ] ; +} + +inline void sgdSetVec4 ( sgdVec4 dst, sgVec4 src ) +{ + dst [ 0 ] = (SGDfloat) src [ 0 ] ; + dst [ 1 ] = (SGDfloat) src [ 1 ] ; + dst [ 2 ] = (SGDfloat) src [ 2 ] ; + dst [ 3 ] = (SGDfloat) src [ 3 ] ; +} + + +inline void sgSetMat4 ( sgMat4 dst, sgdMat4 src ) +{ + sgSetVec4 ( dst [ 0 ], src [ 0 ] ) ; + sgSetVec4 ( dst [ 1 ], src [ 1 ] ) ; + sgSetVec4 ( dst [ 2 ], src [ 2 ] ) ; + sgSetVec4 ( dst [ 3 ], src [ 3 ] ) ; +} + + +inline void sgdSetMat4 ( sgdMat4 dst, sgMat4 src ) +{ + sgdSetVec4 ( dst [ 0 ], src [ 0 ] ) ; + sgdSetVec4 ( dst [ 1 ], src [ 1 ] ) ; + sgdSetVec4 ( dst [ 2 ], src [ 2 ] ) ; + sgdSetVec4 ( dst [ 3 ], src [ 3 ] ) ; +} + + +inline void sgSetCoord ( sgCoord *dst, sgdCoord *src ) +{ + sgSetVec3 ( dst->xyz, src->xyz ) ; + sgSetVec3 ( dst->hpr, src->hpr ) ; +} + + +inline void sgdSetCoord ( sgdCoord *dst, sgCoord *src ) +{ + sgdSetVec3 ( dst->xyz, src->xyz ) ; + sgdSetVec3 ( dst->hpr, src->hpr ) ; +} + +inline void sgSetQuat ( sgQuat dst, sgdQuat src ) +{ + sgSetVec4 ( dst, src ) ; +} + + + +inline void sgdSetQuat ( sgdQuat dst, sgQuat src ) +{ + sgdSetVec4 ( dst, src ) ; +} + + +/* Function to rotate a vector through a given quaternion using the formula + * R = Q r Q-1 -- this gives the components of a ROTATED vector in a STATIONARY + * coordinate system. We assume that Q is a unit quaternion. + */ + +void sgRotateVecQuat ( sgVec3 vec, sgQuat q ) ; +void sgdRotateVecQuat ( sgdVec3 vec, sgdQuat q ) ; + +/* Function to rotate a vector through a given quaternion using the formula + * R = Q-1 r Q -- this gives the components of a STATIONARY vector in a ROTATED + * coordinate system. We assume that Q is a unit quaternion. + */ + +void sgRotateCoordQuat ( sgVec3 vec, sgQuat q ) ; +void sgdRotateCoordQuat ( sgdVec3 vec, sgdQuat q ) ; + +sgFloat sgDistSquaredToLineLineSegment ( const sgLineSegment3 seg, const sgLine3 line ) ; +sgdFloat sgdDistSquaredToLineLineSegment ( const sgdLineSegment3 seg, const sgdLine3 line ) ; + + + +/* + Intersection testing. +*/ + +int sgdIsectPlanePlane ( sgdVec3 point, sgdVec3 dir, + sgdVec4 plane1, sgdVec4 plane2 ) ; +int sgdIsectInfLinePlane ( sgdVec3 dst, + sgdVec3 l_org, sgdVec3 l_vec, + sgdVec4 plane ) ; +int sgdIsectInfLineInfLine ( sgdVec3 dst, + sgdVec3 l1_org, sgdVec3 l1_vec, + sgdVec3 l2_org, sgdVec3 l2_vec ) ; +SGDfloat sgdIsectLinesegPlane ( sgdVec3 dst, + sgdVec3 v1, sgdVec3 v2, + sgdVec4 plane ) ; +bool sgdPointInTriangle ( sgdVec3 point, sgdVec3 tri[3] ); + + +/* + TRIANGLE SOLVERS - These work for any triangle. + + SSS == Side-lengths for all three sides. + SAS == Side-lengths for two sides - plus the angle between them. + ASA == Two angles plus the length of the Side between them. + Area == The area of the triangle. +*/ + +SGfloat sgTriangleSolver_ASAtoArea ( SGfloat angA, SGfloat lenB, SGfloat angC ); +SGfloat sgTriangleSolver_SAStoArea ( SGfloat lenA, SGfloat angB, SGfloat lenC ); +SGfloat sgTriangleSolver_SSStoArea ( SGfloat lenA, SGfloat lenB, SGfloat lenC ); +SGfloat sgTriangleSolver_SAAtoArea ( SGfloat lenA, SGfloat angB, SGfloat angA ); +SGfloat sgTriangleSolver_ASStoArea ( SGfloat angB, SGfloat lenA, SGfloat lenB, + int angA_is_obtuse ); + +void sgTriangleSolver_SSStoAAA ( SGfloat lenA, SGfloat lenB, SGfloat lenC, + SGfloat *angA, SGfloat *angB, SGfloat *angC ) ; +void sgTriangleSolver_SAStoASA ( SGfloat lenA, SGfloat angB, SGfloat lenC, + SGfloat *angA, SGfloat *lenB, SGfloat *angC ) ; +void sgTriangleSolver_ASAtoSAS ( SGfloat angA, SGfloat lenB, SGfloat angC, + SGfloat *lenA, SGfloat *angB, SGfloat *lenC ) ; +void sgTriangleSolver_SAAtoASS ( SGfloat lenA, SGfloat angB, SGfloat angA, + SGfloat *angC, SGfloat *lenB, SGfloat *lenC ) ; +void sgTriangleSolver_ASStoSAA ( SGfloat angB, SGfloat lenA, SGfloat lenB, + int angA_is_obtuse, + SGfloat *lenC, SGfloat *angA, SGfloat *angC ) ; + + +SGDfloat sgdTriangleSolver_ASAtoArea ( SGDfloat angA, SGDfloat lenB, SGDfloat angC ); +SGDfloat sgdTriangleSolver_SAStoArea ( SGDfloat lenA, SGDfloat angB, SGDfloat lenC ); +SGDfloat sgdTriangleSolver_SSStoArea ( SGDfloat lenA, SGDfloat lenB, SGDfloat lenC ); +SGDfloat sgdTriangleSolver_SAAtoArea ( SGDfloat lenA, SGDfloat angB, SGDfloat angA ); +SGDfloat sgdTriangleSolver_ASStoArea ( SGDfloat angB, SGDfloat lenA, SGDfloat lenB, + int angA_is_obtuse ); + +void sgdTriangleSolver_SSStoAAA ( SGDfloat lenA, SGDfloat lenB, SGDfloat lenC, + SGDfloat *angA, SGDfloat *angB, SGDfloat *angC ) ; +void sgdTriangleSolver_SAStoASA ( SGDfloat lenA, SGDfloat angB, SGDfloat lenC, + SGDfloat *angA, SGDfloat *lenB, SGDfloat *angC ) ; +void sgdTriangleSolver_ASAtoSAS ( SGDfloat angA, SGDfloat lenB, SGDfloat angC, + SGDfloat *lenA, SGDfloat *angB, SGDfloat *lenC ) ; +void sgdTriangleSolver_SAAtoASS ( SGDfloat lenA, SGDfloat angB, SGDfloat angA, + SGDfloat *angC, SGDfloat *lenB, SGDfloat *lenC ) ; +void sgdTriangleSolver_ASStoSAA ( SGDfloat angB, SGDfloat lenA, SGDfloat lenB, + int angA_is_obtuse, + SGDfloat *lenC, SGDfloat *angA, SGDfloat *angC ) ; + +/* + SPRING-MASS-DAMPER (with simple Euler integrator) +*/ + + +extern sgVec3 _sgGravity ; + +inline void sgSetGravity ( float g ) { sgSetVec3 ( _sgGravity, 0.0f, 0.0f, -g ) ; } +inline void sgSetGravityVec3 ( sgVec3 g ) { sgCopyVec3 ( _sgGravity, g ) ; } +inline float *sgGetGravityVec3 () { return _sgGravity ; } +inline float sgGetGravity () { return - _sgGravity[2] ; } + + +class sgParticle +{ + float ooMass ; /* One-over-mass */ + sgVec3 pos ; + sgVec3 vel ; + sgVec3 force ; + +public: + + sgParticle ( float mass, sgVec3 _pos ) + { + setMass ( mass ) ; + sgCopyVec3 ( pos, _pos ) ; + sgZeroVec3 ( vel ) ; + sgZeroVec3 ( force ) ; + } + + sgParticle ( float mass, float x = 0.0f, float y = 0.0f, float z = 0.0f ) + { + setMass ( mass ) ; + sgSetVec3 ( pos, x, y, z ) ; + sgZeroVec3 ( vel ) ; + sgZeroVec3 ( force ) ; + } + + SGfloat *getPos () { return pos ; } + SGfloat *getVel () { return vel ; } + SGfloat *getForce () { return force ; } + + const SGfloat *getPos () const { return pos ; } + const SGfloat *getVel () const { return vel ; } + const SGfloat *getForce () const { return force ; } + + float getOneOverMass () { return ooMass ; } + float getMass () { return 1.0f / ooMass ; } + + void setPos ( sgVec3 p ) { sgCopyVec3 ( pos , p ) ; } + void setVel ( sgVec3 v ) { sgCopyVec3 ( vel , v ) ; } + void setForce ( sgVec3 f ) { sgCopyVec3 ( force, f ) ; } + + void setPos ( float x, float y, float z ) { sgSetVec3 ( pos ,x,y,z ) ; } + void setVel ( float x, float y, float z ) { sgSetVec3 ( vel ,x,y,z ) ; } + void setForce ( float x, float y, float z ) { sgSetVec3 ( force,x,y,z ) ; } + + void setOneOverMass ( float oom ) { ooMass = oom ; } + + void setMass ( float m ) + { + assert ( m > 0.0f ) ; + ooMass = 1.0f / m ; + } + + void zeroForce () { sgZeroVec3 ( force ) ; } + void addForce ( sgVec3 f ) { sgAddVec3 ( force, f ) ; } + void subForce ( sgVec3 f ) { sgSubVec3 ( force, f ) ; } + void gravityOnly () { sgScaleVec3 ( force, sgGetGravityVec3 (), ooMass ) ; } + + void bounce ( sgVec3 normal, float coefRestitution ) + { + sgVec3 vn, vt ; + sgScaleVec3 ( vn, normal, + sgScalarProductVec3 ( normal, vel ) ) ; + sgSubVec3 ( vt, vel, vn ) ; + sgAddScaledVec3 ( vel, vt, vn, -coefRestitution ) ; + } + + void update ( float dt ) + { + sgAddScaledVec3 ( vel, force, dt * ooMass ) ; + sgAddScaledVec3 ( pos, vel, dt ) ; + } +} ; + + +class sgSpringDamper +{ + sgParticle *p0 ; + sgParticle *p1 ; + + float restLength ; + float stiffness ; + float damping ; + +public: + + sgSpringDamper () + { + p0 = p1 = NULL ; + stiffness = 1.0f ; + damping = 1.0f ; + restLength = 1.0f ; + } + + sgSpringDamper ( sgParticle *_p0, sgParticle *_p1, + float _stiffness, float _damping, + float _restLength = -1.0f ) + { + p0 = _p0 ; + p1 = _p1 ; + stiffness = _stiffness ; + damping = _damping ; + + if ( _restLength < 0.0f ) + { + if ( p0 != NULL && p1 != NULL ) + restLength = sgDistanceVec3 ( p0->getPos(), p1->getPos() ) ; + else + restLength = _restLength ; + } + else + restLength = 1.0f ; + } + + float getRestLength () { return restLength ; } + float getStiffness () { return stiffness ; } + float getDamping () { return damping ; } + + sgParticle *getParticle ( int which ) { return ( which == 0 ) ? p0 : p1 ; } + + + void setParticles ( sgParticle *_p0, sgParticle *_p1 ) { p0 = _p0 ; p1 = _p1 ; } + void setParticle ( int which, sgParticle *p ) { if ( which == 0 ) p0 = p ; else p1 = p ; } + + void setRestLength () { restLength = sgDistanceVec3 ( p0->getPos(), p1->getPos() ) ; } + + void setRestLength ( float l ) { restLength = l ; } + void setStiffness ( float s ) { stiffness = s ; } + void setDamping ( float d ) { damping = d ; } + + void update () + { + sgVec3 dP ; sgSubVec3 ( dP, p0->getPos(), p1->getPos() ) ; + sgVec3 dV ; sgSubVec3 ( dV, p0->getVel(), p1->getVel() ) ; + + float L = sgLengthVec3 ( dP ) ; if ( L == 0.0f ) L = 0.0000001f ; + float H = ( L - restLength ) * stiffness ; + float D = sgScalarProductVec3 ( dV, dP ) * damping / L ; + + sgVec3 F ; sgScaleVec3 ( F, dP, - ( H + D ) / L ) ; + + p0 -> addForce ( F ) ; + p1 -> subForce ( F ) ; + } + +} ; + + +/* + It must be true that (x % NOISE_WRAP_INDEX) == (x & NOISE_MOD_MASK) + so NOISE_WRAP_INDEX must be a power of two, and NOISE_MOD_MASK must be + that power of 2 - 1. as indices are implemented, as unsigned chars, + NOISE_WRAP_INDEX shoud be less than or equal to 256. + There's no good reason to change it from 256, really. + + NOISE_LARGE_PWR2 is a large power of 2, we'll go for 4096, to add to + negative numbers in order to make them positive +*/ + +#define SG_PERLIN_NOISE_WRAP_INDEX 256 +#define SG_PERLIN_NOISE_MOD_MASK 255 +#define SG_PERLIN_NOISE_LARGE_PWR2 4096 + + + +class sgPerlinNoise_1D +{ +private: + + SGfloat gradTable [ SG_PERLIN_NOISE_WRAP_INDEX * 2 + 2 ] ; + +public: + + sgPerlinNoise_1D () ; + + void regenerate () ; + + SGfloat getNoise ( SGfloat x ) ; +} ; + + + +class sgPerlinNoise_2D +{ +private: + + sgVec2 gradTable [ SG_PERLIN_NOISE_WRAP_INDEX * 2 + 2 ] ; + +public: + + sgPerlinNoise_2D () ; + + void regenerate () ; + + SGfloat getNoise ( sgVec2 pos ) ; + SGfloat getNoise ( SGfloat x, SGfloat y ) + { + sgVec2 p ; + sgSetVec2 ( p, x, y ) ; + return getNoise ( p ) ; + } +} ; + + + +class sgPerlinNoise_3D +{ +private: + + sgVec3 gradTable [ SG_PERLIN_NOISE_WRAP_INDEX * 2 + 2 ] ; + +public: + + sgPerlinNoise_3D () ; + + void regenerate () ; + + SGfloat getNoise ( sgVec3 pos ) ; + SGfloat getNoise ( SGfloat x, SGfloat y, SGfloat z ) + { + sgVec3 p ; + sgSetVec3 ( p, x, y, z ) ; + return getNoise ( p ) ; + } +} ; + + + +#endif + diff --git a/src/sg/sgIsect.cxx b/src/sg/sgIsect.cxx new file mode 100644 index 0000000..d7c4bd9 --- /dev/null +++ b/src/sg/sgIsect.cxx @@ -0,0 +1,390 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: sgIsect.cxx 1851 2004-02-02 01:35:15Z sjbaker $ +*/ + + +#include "sg.h" + +/* + Determine the origin and unit direction vector of a line + formed by the intersection of two planes. + Returned point will lie on axis that was used to + determine intersection. + Norman Vine - nhv@yahoo.com +*/ + +int sgIsectPlanePlane ( sgVec3 point, sgVec3 dir, + sgVec4 plane1, sgVec4 plane2 ) +{ + /* Determine intersection line direction. */ + + sgVectorProductVec3 ( dir, plane1, plane2 ) ; + + SGfloat dnorm = sgLengthVec3 ( dir ) ; + + /* If planes are parallel then fail */ + + if ( dnorm < FLT_EPSILON ) + { + sgZeroVec3 ( point ) ; + sgZeroVec3 ( dir ) ; + return FALSE ; + } + + /* Determine intersection point with the best suited coordinate plane. */ + + SGfloat abs ; + SGfloat maxabs = sgAbs(dir[0]); + int index = 0; + + if ((abs = sgAbs(dir[1])) > maxabs) { maxabs = abs ; index = 1; } + if ((abs = sgAbs(dir[2])) > maxabs) { maxabs = abs ; index = 2; } + + switch ( index ) + { + case 0: + sgSetVec3( point, + SG_ZERO, + (plane1[2] * plane2[3] - plane2[2] * plane1[3]) / dir[0], + (plane2[1] * plane1[3] - plane1[1] * plane2[3]) / dir[0] ); + break; + case 1: + sgSetVec3( point, + (plane2[2] * plane1[3] - plane1[2] * plane2[3]) / dir[1], + SG_ZERO, + (plane1[0] * plane2[3] - plane2[0] * plane1[3]) / dir[1] ); + break; + case 2: + sgSetVec3( point, + (plane1[1] * plane2[3] - plane2[1] * plane1[3]) / dir[2], + (plane2[0] * plane1[3] - plane1[0] * plane2[3]) / dir[2], + SG_ZERO ); + break; + default: return FALSE ; /* Impossible */ + } + + /* Normalize the direction */ + + sgScaleVec3( dir, SG_ONE / dnorm ); + return TRUE; +} + + + +/* + Find the intersection of an infinite line with a plane + (the line being defined by a point and direction). + + Norman Vine -- nhv@yahoo.com (with hacks by Steve) +*/ + +int sgIsectInfLinePlane( sgVec3 dst, sgVec3 l_org, sgVec3 l_vec, sgVec4 plane ) +{ + SGfloat tmp = sgScalarProductVec3 ( l_vec, plane ) ; + + /* Is line parallel to plane? */ + + if ( sgAbs ( tmp ) < FLT_EPSILON ) + return FALSE ; + + sgScaleVec3 ( dst, l_vec, -( sgScalarProductVec3 ( l_org, plane ) + + plane[3] ) / tmp ) ; + sgAddVec3 ( dst, l_org ) ; + + return TRUE ; +} + + + +/* + Given the origin and direction vector for two lines + find their intersection - or the point closest to + both lines if they don't intersect. + + Norman Vine -- nhv@yahoo.com +*/ + +int sgIsectInfLineInfLine( sgVec3 dst, + sgVec3 l1_org, sgVec3 l1_vec, + sgVec3 l2_org, sgVec3 l2_vec ) +{ + sgVec3 vec_l1, vec_l2 ; + + sgNormalizeVec3 ( vec_l1, l1_vec ) ; + sgNormalizeVec3 ( vec_l2, l2_vec ) ; + + /* Connecting line 'C' is perpendicular to both */ + + sgVec3 perp ; + sgVectorProductVec3 ( perp, vec_l1, vec_l2 ) ; + + /* check for near-parallel lines */ + + SGfloat dist = sgScalarProductVec3 ( perp, perp ) ; + + if ( dist < FLT_EPSILON ) + { + /* degenerate: lines parallel - any point will do. */ + + sgCopyVec3 ( dst, l2_org ) ; + return TRUE ; + } + + /* + Form a plane containing the line A and C, + and another containing B and C + */ + + sgScaleVec3 ( perp, SG_ONE / sgSqrt( dist ) ) ; + + sgVec4 pa ; + sgVec4 pb ; + sgVec3 tmp ; + + sgVectorProductVec3 ( tmp, perp, vec_l1 ) ; + sgNormalizeVec3 ( tmp ); + sgMakePlane ( pa, tmp, l1_org ) ; + + sgVectorProductVec3 ( tmp, perp, vec_l2 ) ; + sgNormalizeVec3 ( tmp ); + sgMakePlane ( pb, tmp, l2_org ) ; + + sgVec3 tmp_org, tmp_vec ; + + if ( ! sgIsectPlanePlane( tmp_org, tmp_vec, pa, pb ) ) + { + /* This *shouldn't* ever happen because we already + tested for parallel lines - but with roundoff + errors, it *might* in borderline cases so... + */ + + sgCopyVec3 ( dst, l2_org ) ; + return FALSE ; + } + + if ( ! sgIsectInfLinePlane ( dst, l2_org, vec_l2, pa ) ) + { + sgCopyVec3 ( dst, l2_org ) ; + return FALSE ; + } + + return TRUE ; +} + + +/* + Intersect the line segment from v1->v2 with the 'plane'. + 'dst' is the intersection point and the return + result is in the range 0..1 if the intersection lies + between v1 and v2, >1 if beyond v2 and <0 if before v1. + FLT_MAX is returned if the vector does not intersect + the plane. + + Steve Baker +*/ + +SGfloat sgIsectLinesegPlane ( sgVec3 dst, sgVec3 v1, sgVec3 v2, sgVec4 plane ) +{ + sgVec3 delta ; + + sgSubVec3 ( delta, v2, v1 ) ; + + SGfloat p = sgScalarProductVec3 ( plane, delta ) ; + + if ( p == SG_ZERO ) + { + dst [ 0 ] = dst [ 1 ] = dst [ 2 ] = FLT_MAX ; + return FLT_MAX ; + } + + float s = - ( sgScalarProductVec3 ( plane, v1 ) + plane[3] ) / p ; + + sgScaleVec3 ( dst, delta, s ) ; + sgAddVec3 ( dst, dst, v1 ) ; + + return s ; +} + + +// return the sign of a value + +static inline const int SG_SIGN( const SGfloat x ) +{ + return x < 0 ? -1 : 1; +} + + +// return the minimum of two values + +static inline SGfloat SG_MIN2( const SGfloat a, const SGfloat b ) +{ + return a < b ? a : b ; +} + + +// return the minimum of three values + +static inline SGfloat SG_MIN3 ( const SGfloat a, + const SGfloat b, const SGfloat c ) +{ + return ( a < b ? SG_MIN2(a, c) : SG_MIN2(b, c) ); +} + + +// return the minimum and maximum of three values + +static void SG_MIN_MAX3 ( SGfloat &min, SGfloat &max, const SGfloat &a, + const SGfloat &b, const SGfloat &c ) +{ + if( a > b ) + { + if( a > c ) { max = a; min = SG_MIN2( b, c ); } else + { max = c; min = SG_MIN2( a, b ); } + } + else + { + if( b > c ) { max = b; min = SG_MIN2( a, c ); } else + { max = c; min = SG_MIN2( a, b ); } + } +} + +/* + * Given a point and a triangle lying on the same plane + * check to see if the point is inside the triangle + */ + +bool sgPointInTriangle3 ( sgVec3 point, sgVec3 tri[3] ) +{ + sgVec3 dif ; + + /* Early-out if point is not in bounding cube of triangle */ + + for( int i = 0 ; i < 3 ; i++ ) + { + SGfloat min, max ; + + SG_MIN_MAX3 ( min, max, tri[0][i], tri[1][i], tri[2][i] ) ; + + if( point[i] < min || point[i] > max ) + return false ; + + dif[i] = max - min ; /* Calc size of bounding cube */ + } + + /* Drop the smallest dimension so we only have to work in 2d. */ + + sgVec2 p, a, b, c ; + + if ( dif[0] <= dif[1] && dif[0] <= dif[2] ) + { + p[0] = point[1] ; p[1] = point[2] ; + a[0] = tri[0][1] ; a[1] = tri[0][2] ; + b[0] = tri[1][1] ; b[1] = tri[1][2] ; + c[0] = tri[2][1] ; c[1] = tri[2][2] ; + } + else + if ( dif[1] <= dif[0] && dif[1] <= dif[2] ) + { + p[0] = point[0] ; p[1] = point[2] ; + a[0] = tri[0][0] ; a[1] = tri[0][2] ; + b[0] = tri[1][0] ; b[1] = tri[1][2] ; + c[0] = tri[2][0] ; c[1] = tri[2][2] ; + } + else + { + p[0] = point[0] ; p[1] = point[1] ; + a[0] = tri[0][0] ; a[1] = tri[0][1] ; + b[0] = tri[1][0] ; b[1] = tri[1][1] ; + c[0] = tri[2][0] ; c[1] = tri[2][1] ; + } + + /* + Check if the intersection point is on the same side of + each edge of the triangle as the remaining point. + */ + + sgVec3 le ; /* Line Equation */ + + sgMake2DLine ( le, a, b ) ; + + if ( SG_SIGN ( le[0]*c[0] + le[1]*c[1] + le[2] ) != + SG_SIGN ( le[0]*p[0] + le[1]*p[1] + le[2] ) ) return false ; + + sgMake2DLine ( le, b, c ) ; + + if ( SG_SIGN ( le[0]*a[0] + le[1]*a[1] + le[2] ) != + SG_SIGN ( le[0]*p[0] + le[1]*p[1] + le[2] ) ) return false ; + + sgMake2DLine ( le, c, a ) ; + + if ( SG_SIGN ( le[0]*b[0] + le[1]*b[1] + le[2] ) != + SG_SIGN ( le[0]*p[0] + le[1]*p[1] + le[2] ) ) return false ; + + return true ; +} + + + +bool sgPointInTriangle2 ( sgVec2 point, sgVec2 tri[3] ) +{ + SGfloat min, max ; + + /* Early-out if outside bounding box */ + + SG_MIN_MAX3 ( min, max, tri[0][0], tri[1][0], tri[2][0] ); + if ( point[0] < min || point[0] > max ) return false ; + + SG_MIN_MAX3 ( min, max, tri[0][1], tri[1][1], tri[2][1] ); + if ( point[1] < min || point[1] > max ) return false ; + + sgVec2 a, b, c ; + + sgCopyVec2 ( a, tri[0] ) ; + sgCopyVec2 ( b, tri[1] ) ; + sgCopyVec2 ( c, tri[2] ) ; + + /* + Check if the intersection point is on the same side of + each edge of the triangle as the remaining point. + */ + + sgVec3 le ; /* Line Equation */ + + sgMake2DLine ( le, a, b ) ; + + if ( SG_SIGN ( le[0]*c[0] + le[1]*c[1] + le[2] ) != + SG_SIGN ( le[0]*point[0] + le[1]*point[1] + le[2] ) ) return false ; + + sgMake2DLine ( le, b, c ) ; + + if ( SG_SIGN ( le[0]*a[0] + le[1]*a[1] + le[2] ) != + SG_SIGN ( le[0]*point[0] + le[1]*point[1] + le[2] ) ) return false ; + + sgMake2DLine ( le, c, a ) ; + + if ( SG_SIGN ( le[0]*b[0] + le[1]*b[1] + le[2] ) != + SG_SIGN ( le[0]*point[0] + le[1]*point[1] + le[2] ) ) return false ; + + return true ; +} + + diff --git a/src/sg/sgPerlinNoise.cxx b/src/sg/sgPerlinNoise.cxx new file mode 100644 index 0000000..bd7cbb0 --- /dev/null +++ b/src/sg/sgPerlinNoise.cxx @@ -0,0 +1,315 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + +*/ + + +/* + sgPerlinNoise + + This is a class to implement coherent noise over 1, 2, or 3 + dimensions. The implementation is based on the Ken Perlin's + noise function and borrows heavily from Matt Zucker's implementation. +*/ + + +#include +#include +#include +#include "sg.h" + +static unsigned int *permTable = NULL ; + + +static void initPermTable () +{ + int i ; + + if ( permTable != NULL ) + return ; + + permTable = new unsigned int [ SG_PERLIN_NOISE_WRAP_INDEX * 2 + 2 ] ; + + for ( i = 0 ; i < SG_PERLIN_NOISE_WRAP_INDEX ; i++ ) + permTable[i] = i ; + + /* Shuffle permutation table up to SG_PERLIN_NOISE_WRAP_INDEX */ + + for ( i = 0 ; i < SG_PERLIN_NOISE_WRAP_INDEX ; i++ ) + { + int j = rand () & SG_PERLIN_NOISE_MOD_MASK ; + + int temp = permTable [ i ] ; + permTable [ i ] = permTable [ j ] ; + permTable [ j ] = temp ; + } + + /* + Add the rest of the table entries in, duplicating + indices and entries so that they can effectively be indexed + by unsigned chars. I think. Ask Perlin what this is really doing. + */ + + for ( i = 0 ; i < SG_PERLIN_NOISE_WRAP_INDEX + 2 ; i++ ) + permTable [ SG_PERLIN_NOISE_WRAP_INDEX + i ] = permTable [ i ] ; +} + + + + + + +/* + S curve is (3x^2 - 2x^3) because it's quick to calculate + though -cos(x * PI) * 0.5 + 0.5 would work too +*/ + +inline SGfloat easeCurve ( SGfloat t ) { return (SGfloat) (t * t * (3.0 - 2.0 * t)) ; } + +inline SGfloat dot2 ( SGfloat rx, SGfloat ry, sgVec2 q ) +{ + return rx * q[0] + ry * q[1] ; +} + +inline SGfloat dot3 ( SGfloat rx, SGfloat ry, SGfloat rz, sgVec3 q ) +{ + return rx * q[0] + ry * q[1] + rz * q[2] ; +} + + +inline SGfloat randFloat () +{ + return (SGfloat)(( rand() % ( SG_PERLIN_NOISE_WRAP_INDEX + + SG_PERLIN_NOISE_WRAP_INDEX ) ) - + SG_PERLIN_NOISE_WRAP_INDEX ) / + SG_PERLIN_NOISE_WRAP_INDEX ; +} + + +inline void setupValues ( int axis, int *g0, int *g1, + SGfloat *d0, SGfloat *d1, SGfloat *pos ) +{ + SGfloat t = pos[axis] + SG_PERLIN_NOISE_LARGE_PWR2 ; + int it = (int) t ; + + *g0 = it & SG_PERLIN_NOISE_MOD_MASK ; + *g1 = (*g0 + 1) & SG_PERLIN_NOISE_MOD_MASK ; + *d0 = t - it ; + *d1 = *d0 - 1.0f ; +} + + + +SGfloat sgPerlinNoise_1D::getNoise ( SGfloat pos ) +{ + int gridL, gridR ; + SGfloat distL, distR ; + + /* + Find out neighboring grid points to pos and + signed distances from pos to them. + */ + + setupValues ( 0, &gridL, &gridR, + &distL , &distR , &pos ) ; + + return sgLerp ( distL * gradTable [ permTable [ gridL ] ], + distR * gradTable [ permTable [ gridR ] ], + easeCurve ( distL ) ) ; +} + + + +SGfloat sgPerlinNoise_2D::getNoise ( sgVec2 pos ) +{ + int gridL, gridR, + gridD, gridU ; + + SGfloat distL, distR, + distD, distU ; + + /* + Find out neighboring grid points to pos and + signed distances from pos to them. + */ + + setupValues ( 0, &gridL, &gridR, &distL, &distR, pos ) ; + setupValues ( 1, &gridD, &gridU, &distD, &distU, pos ) ; + + /* + Generate some temporary indexes associated with the left + and right grid values + */ + + int indexL = permTable [ gridL ] ; + int indexR = permTable [ gridR ] ; + + /* Generate indexes in the permutation table for all 4 corners */ + + int indexLD = permTable [ indexL + gridD ] ; + int indexRD = permTable [ indexR + gridD ] ; + int indexLU = permTable [ indexL + gridU ] ; + int indexRU = permTable [ indexR + gridU ] ; + + /* Get the s curves at the proper values */ + + SGfloat sX = easeCurve ( distL ) ; + SGfloat sY = easeCurve ( distD ) ; + + return sgLerp ( + sgLerp ( + dot2 ( distL, distD, gradTable [ indexLD ] ), + dot2 ( distR, distD, gradTable [ indexRD ] ), sX ), + sgLerp ( + dot2 ( distL, distU, gradTable [ indexLU ] ), + dot2 ( distR, distU, gradTable [ indexRU ] ), sX ), + sY ) ; +} + + +SGfloat sgPerlinNoise_3D::getNoise ( sgVec3 pos ) +{ + int gridL, gridR, + gridD, gridU, + gridB, gridF ; + + SGfloat distL, distR, + distD, distU, + distB, distF ; + + /* + Find out neighboring grid points to pos and signed + distances from pos to them. + */ + + setupValues ( 0, &gridL, &gridR, &distL, &distR, pos ) ; + setupValues ( 1, &gridD, &gridU, &distD, &distU, pos ) ; + setupValues ( 2, &gridB, &gridF, &distB, &distF, pos ) ; + + int indexL = permTable [ gridL ] ; + int indexR = permTable [ gridR ] ; + + int indexLD = permTable [ indexL + gridD ] ; + int indexRD = permTable [ indexR + gridD ] ; + int indexLU = permTable [ indexL + gridU ] ; + int indexRU = permTable [ indexR + gridU ] ; + + SGfloat sX = easeCurve ( distL ) ; + SGfloat sY = easeCurve ( distD ) ; + SGfloat sZ = easeCurve ( distB ) ; + + return sgLerp ( + sgLerp ( + sgLerp ( + dot3 ( distL, distD, distB, gradTable [ indexLD + gridB ] ), + dot3 ( distR, distD, distB, gradTable [ indexRD + gridB ] ), sX ), + sgLerp ( + dot3 ( distL, distU, distB, gradTable [ indexLU + gridB ] ), + dot3 ( distR, distU, distB, gradTable [ indexRU + gridB ] ), sX ), + sY ), + sgLerp ( + sgLerp ( + dot3 ( distL, distD, distF, gradTable [ indexLD + gridF ] ), + dot3 ( distR, distD, distF, gradTable [ indexRD + gridF ] ), sX ), + sgLerp ( + dot3 ( distL, distU, distF, gradTable [ indexLU + gridF ] ), + dot3 ( distR, distU, distF, gradTable [ indexRU + gridF ] ), sX ), + sY ), + sZ ) ; +} + + + + +sgPerlinNoise_1D::sgPerlinNoise_1D () +{ + regenerate () ; +} + + +void sgPerlinNoise_1D::regenerate () +{ + int i ; + + for ( i = 0 ; i < SG_PERLIN_NOISE_WRAP_INDEX ; i++ ) + gradTable [ i ] = randFloat () ; + + for ( i = 0 ; i < SG_PERLIN_NOISE_WRAP_INDEX + 2 ; i++ ) + gradTable [ SG_PERLIN_NOISE_WRAP_INDEX + i ] = gradTable [ i ] ; + + initPermTable () ; +} + + + +sgPerlinNoise_2D::sgPerlinNoise_2D () +{ + regenerate () ; +} + + +void sgPerlinNoise_2D::regenerate () +{ + int i ; + + for ( i = 0 ; i < SG_PERLIN_NOISE_WRAP_INDEX ; i++ ) + { + sgSetVec2 ( gradTable [ i ], randFloat(), randFloat() ) ; + sgNormalizeVec2 ( gradTable [ i ] ) ; + } + + for ( i = 0 ; i < SG_PERLIN_NOISE_WRAP_INDEX + 2 ; i++ ) + { + gradTable [ SG_PERLIN_NOISE_WRAP_INDEX + i ][ 0 ] = gradTable [ i ][ 0 ] ; + gradTable [ SG_PERLIN_NOISE_WRAP_INDEX + i ][ 1 ] = gradTable [ i ][ 1 ] ; + } + + initPermTable () ; +} + + + +sgPerlinNoise_3D::sgPerlinNoise_3D () +{ + regenerate () ; +} + + +void sgPerlinNoise_3D::regenerate () +{ + int i ; + + for ( i = 0 ; i < SG_PERLIN_NOISE_WRAP_INDEX ; i++ ) + { + sgSetVec3 ( gradTable [ i ], randFloat(), randFloat(), randFloat() ) ; + sgNormalizeVec3 ( gradTable [ i ] ) ; + } + + for ( i = 0 ; i < SG_PERLIN_NOISE_WRAP_INDEX + 2 ; i++ ) + { + gradTable [ SG_PERLIN_NOISE_WRAP_INDEX + i ][ 0 ] = gradTable [ i ][ 0 ] ; + gradTable [ SG_PERLIN_NOISE_WRAP_INDEX + i ][ 1 ] = gradTable [ i ][ 1 ] ; + gradTable [ SG_PERLIN_NOISE_WRAP_INDEX + i ][ 2 ] = gradTable [ i ][ 2 ] ; + } + + initPermTable () ; +} + + diff --git a/src/sg/sgd.cxx b/src/sg/sgd.cxx new file mode 100644 index 0000000..46b4c5c --- /dev/null +++ b/src/sg/sgd.cxx @@ -0,0 +1,2064 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: sgd.cxx 1944 2004-08-05 01:07:09Z puggles $ +*/ + + +#include "sg.h" + +sgdVec3 _sgdGravity = { 0.0f, 0.0f, -9.8f } ; + +void sgdVectorProductVec3 ( sgdVec3 dst, const sgdVec3 a, const sgdVec3 b ) +{ + dst[0] = a[1] * b[2] - a[2] * b[1] ; + dst[1] = a[2] * b[0] - a[0] * b[2] ; + dst[2] = a[0] * b[1] - a[1] * b[0] ; +} + +inline SGDfloat _sgdClampToUnity ( const SGDfloat x ) +{ + if ( x > SGD_ONE ) return SGD_ONE ; + if ( x < -SGD_ONE ) return -SGD_ONE ; + return x ; +} + +int sgdCompare3DSqdDist( const sgdVec3 v1, const sgdVec3 v2, const SGDfloat sqd_dist ) +{ + sgdVec3 tmp ; + + sgdSubVec3 ( tmp, v2, v1 ) ; + + SGDfloat sqdist = tmp[0] * tmp[0] + tmp[1] * tmp[1] + tmp[2] * tmp[2] ; + + if ( sqdist > sqd_dist ) return 1 ; + if ( sqdist < sqd_dist ) return -1 ; + return 0 ; +} + +void sgdMakeRotMat4( sgdMat4 mat, const SGDfloat angle, const sgdVec3 axis ) +{ + sgdVec3 ax ; + sgdNormalizeVec3 ( ax, axis ) ; + + SGDfloat temp_angle = angle * SGD_DEGREES_TO_RADIANS ; + SGDfloat s = sin ( temp_angle ) ; + SGDfloat c = cos ( temp_angle ) ; + SGDfloat t = SGD_ONE - c ; + + mat[0][0] = t * ax[0] * ax[0] + c ; + mat[0][1] = t * ax[0] * ax[1] + s * ax[2] ; + mat[0][2] = t * ax[0] * ax[2] - s * ax[1] ; + mat[0][3] = SGD_ZERO ; + + mat[1][0] = t * ax[1] * ax[0] - s * ax[2] ; + mat[1][1] = t * ax[1] * ax[1] + c ; + mat[1][2] = t * ax[1] * ax[2] + s * ax[0] ; + mat[1][3] = SGD_ZERO ; + + mat[2][0] = t * ax[2] * ax[0] + s * ax[1] ; + mat[2][1] = t * ax[2] * ax[1] - s * ax[0] ; + mat[2][2] = t * ax[2] * ax[2] + c ; + mat[2][3] = SGD_ZERO ; + + mat[3][0] = SGD_ZERO ; + mat[3][1] = SGD_ZERO ; + mat[3][2] = SGD_ZERO ; + mat[3][3] = SGD_ONE ; +} + + + + +void sgdMakePickMatrix( sgdMat4 mat, sgdFloat x, sgdFloat y, + sgdFloat width, sgdFloat height, sgdVec4 viewport ) +{ + sgdFloat sx = viewport[2] / width ; + sgdFloat sy = viewport[3] / height ; + sgdFloat tx = ( viewport[2] + SGD_TWO * (viewport[0] - x) ) / width ; + sgdFloat ty = ( viewport[3] + SGD_TWO * (viewport[1] - y) ) / height ; + + mat[0][0] = sx ; + mat[0][1] = SGD_ZERO ; + mat[0][2] = SGD_ZERO ; + mat[0][3] = SGD_ZERO ; + + mat[1][0] = SGD_ZERO ; + mat[1][1] = sy ; + mat[1][2] = SGD_ZERO ; + mat[1][3] = SGD_ZERO ; + + mat[2][0] = SGD_ZERO ; + mat[2][1] = SGD_ZERO ; + mat[2][2] = SGD_ONE ; + mat[2][3] = SGD_ZERO ; + + mat[3][0] = tx ; + mat[3][1] = ty ; + mat[3][2] = SGD_ZERO ; + mat[3][3] = SGD_ONE ; +} + + + +void sgdMakeLookAtMat4 ( sgdMat4 dst, const sgdVec3 eye, + const sgdVec3 center, + const sgdVec3 up ) +{ + // Caveats: + // 1) In order to compute the line of sight, the eye point must not be equal + // to the center point. + // 2) The up vector must not be parallel to the line of sight from the eye + // to the center point. + + /* Compute the direction vectors */ + sgdVec3 x,y,z; + + /* Y vector = center - eye */ + sgdSubVec3 ( y, center, eye ) ; + + /* Z vector = up */ + sgdCopyVec3 ( z, up ) ; + + /* X vector = Y cross Z */ + sgdVectorProductVec3 ( x, y, z ) ; + + /* Recompute Z = X cross Y */ + sgdVectorProductVec3 ( z, x, y ) ; + + /* Normalize everything */ + sgdNormaliseVec3 ( x ) ; + sgdNormaliseVec3 ( y ) ; + sgdNormaliseVec3 ( z ) ; + + /* Build the matrix */ + sgdSetVec4 ( dst[0], x[0], x[1], x[2], SGD_ZERO ) ; + sgdSetVec4 ( dst[1], y[0], y[1], y[2], SGD_ZERO ) ; + sgdSetVec4 ( dst[2], z[0], z[1], z[2], SGD_ZERO ) ; + sgdSetVec4 ( dst[3], eye[0], eye[1], eye[2], SGD_ONE ) ; +} + +// -dw- inconsistent linkage! + +sgdFloat sgdTriArea( sgdVec3 p0, sgdVec3 p1, sgdVec3 p2 ) +{ + /* + From comp.graph.algorithms FAQ + + 2A(P) = abs(N.(sum_{i=0}^{n-1}(v_i x v_{i+1}))) + This is an optimized version for a triangle + but easily extended for planar polygon's with more sides + by passing in the number of sides and the vv array + sgdTriArea( int nsides, float **vv ) + and changing the normal calculation and the for loop appropriately + sgdMakeNormal( norm, vv[0], vv[1], vv[2] ) + for( int i=0; i 0.99999 ) + deltaAngle = SGD_PI*0.5; + else + deltaAngle = (SGDfloat)asin((double)myNorm); + + // deltaAngle is in the range -SGD_PI*0.5 to +SGD_PI*0.5 here + // However, the correct result could also be + // deltaAngleS := pi - deltaAngle + // Please note that: + // cos(deltaAngleS)=cos(pi-deltaAngle)=-cos(deltaAngle) + // So, the question is whether + or - cos(deltaAngle) + // is sgdScalarProductVec3(first, second) + + if ( deltaAngle < 0 ) + deltaAngle = deltaAngle + 2*SGD_PI; // unnessecary? + + SProduct = sgdScalarProductVec3(first, second); + myCos = (SGDfloat) cos(deltaAngle); + + abs1 = SProduct - myCos; + abs2 = SProduct + myCos; + + if ( abs1 < 0 ) abs1 = -abs1 ; + if ( abs2 < 0 ) abs2 = -abs2 ; + + assert( (abs1 < 0.1) || (abs2 < 0.1) ) ; + + if ( abs2 < abs1 ) + { + // deltaAngleS is the correct result + + if ( deltaAngle <= SGD_PI ) + deltaAngle = SGD_PI - deltaAngle ; + else + deltaAngle = 3*SGD_PI - deltaAngle ; + } + + assert ( deltaAngle >= 0.0 ) ; + assert ( deltaAngle <= 2.0*SGD_PI ) ; + + return deltaAngle * SGD_RADIANS_TO_DEGREES ; +} + + +SGDfloat sgdAngleBetweenVec3 ( sgdVec3 v1, sgdVec3 v2, sgdVec3 normal ) +{ + // nornmal has to be normalized. + sgdVec3 nv1, nv2 ; + + sgdNormalizeVec3 ( nv1, v1 ) ; + sgdNormalizeVec3 ( nv2, v2 ) ; + return sgdAngleBetweenNormalizedVec3 ( nv1, nv2, normal ) ; +} + + +/*********************\ +* sgdBox routines * +\*********************/ + + +void sgdBox::extend ( const sgdVec3 v ) +{ + if ( isEmpty () ) + { + sgdCopyVec3 ( min, v ) ; + sgdCopyVec3 ( max, v ) ; + } + else + { + if ( v[0] < min[0] ) min[0] = v[0] ; + if ( v[1] < min[1] ) min[1] = v[1] ; + if ( v[2] < min[2] ) min[2] = v[2] ; + if ( v[0] > max[0] ) max[0] = v[0] ; + if ( v[1] > max[1] ) max[1] = v[1] ; + if ( v[2] > max[2] ) max[2] = v[2] ; + } +} + + +void sgdBox::extend ( const sgdBox *b ) +{ + if ( b -> isEmpty () ) + return ; + + if ( isEmpty () ) + { + sgdCopyVec3 ( min, b->getMin() ) ; + sgdCopyVec3 ( max, b->getMax() ) ; + } + else + { + extend ( b->getMin() ) ; + extend ( b->getMax() ) ; + } +} + + +void sgdBox::extend ( const sgdSphere *s ) +{ + if ( s -> isEmpty () ) + return ; + + /* + In essence, this extends around a box around the sphere - which + is still a perfect solution because both boxes are axially aligned. + */ + + sgdVec3 x ; + + sgdSetVec3 ( x, s->getCenter()[0]+s->getRadius(), + s->getCenter()[1]+s->getRadius(), + s->getCenter()[2]+s->getRadius() ) ; + extend ( x ) ; + + sgdSetVec3 ( x, s->getCenter()[0]-s->getRadius(), + s->getCenter()[1]-s->getRadius(), + s->getCenter()[2]-s->getRadius() ) ; + extend ( x ) ; +} + + +int sgdBox::intersects ( const sgdVec4 plane ) const +{ + /* + Save multiplies by not redoing Ax+By+Cz+D for each point. + */ + + SGDfloat Ax_min = plane[0] * min[0] ; + SGDfloat By_min = plane[1] * min[1] ; + SGDfloat Cz_min_plus_D = plane[2] * min[2] + plane[3] ; + + SGDfloat Ax_max = plane[0] * max[0] ; + SGDfloat By_max = plane[1] * max[1] ; + SGDfloat Cz_max_plus_D = plane[2] * max[2] + plane[3] ; + + /* + Count the number of vertices on the positive side of the plane. + */ + + int count = ( Ax_min + By_min + Cz_min_plus_D > SGD_ZERO ) + + ( Ax_min + By_min + Cz_max_plus_D > SGD_ZERO ) + + ( Ax_min + By_max + Cz_min_plus_D > SGD_ZERO ) + + ( Ax_min + By_max + Cz_max_plus_D > SGD_ZERO ) + + ( Ax_max + By_min + Cz_min_plus_D > SGD_ZERO ) + + ( Ax_max + By_min + Cz_max_plus_D > SGD_ZERO ) + + ( Ax_max + By_max + Cz_min_plus_D > SGD_ZERO ) + + ( Ax_max + By_max + Cz_max_plus_D > SGD_ZERO ) ; + + /* + The plane intersects the box unless all 8 are positive + or none of them are positive. + */ + + return count != 0 && count != 8 ; +} + + + +/**********************\ +* sgdSphere routines * +\**********************/ + +void sgdSphere::extend ( const sgdVec3 v ) +{ + if ( isEmpty () ) + { + sgdCopyVec3 ( center, v ) ; + radius = SGD_ZERO ; + return ; + } + + SGDfloat d = sgdDistanceVec3 ( center, v ) ; + + if ( d <= radius ) /* Point is already inside sphere */ + return ; + + SGDfloat new_radius = (radius + d) / SGD_TWO ; /* Grow radius */ + + SGDfloat ratio = (new_radius - radius) / d ; + + center[0] += (v[0]-center[0]) * ratio ; /* Move center */ + center[1] += (v[1]-center[1]) * ratio ; + center[2] += (v[2]-center[2]) * ratio ; + + radius = new_radius ; +} + + +void sgdSphere::extend ( const sgdBox *b ) +{ + if ( b -> isEmpty () ) + return ; + + if ( isEmpty() ) + { + sgdAddVec3 ( center, b->getMin(), b->getMax() ) ; + sgdScaleVec3 ( center, SGD_HALF ) ; + radius = sgdDistanceVec3 ( center, b->getMax() ) ; + return ; + } + + /* + I can't think of a faster way to get an + utterly minimal sphere. + + The tighter algorithm:- enclose each + of eight vertices of the box in turn - it + looks like being pretty costly. + [8 sqrt()'s] + + The looser algorithm:- enclose the box + with an empty sphere and then do a + sphere-extend-sphere. This algorithm + does well for close-to-cube boxes, but + makes very poor spheres for long, thin + boxes. + [2 sqrt()'s] + */ + +#ifdef DONT_REALLY_NEED_A_TIGHT_SPHERE_EXTEND_BOX + + /* LOOSER/FASTER sphere-around-sphere-around-box */ + sgdSphere s ; + s.empty () ; + s.enclose ( b ) ; /* Fast because s is empty */ + enclose ( s ) ; + +#else + + /* TIGHTER/EXPENSIVE sphere-around-eight-points */ + sgdVec3 x ; + extend ( b->getMin() ) ; + sgdSetVec3 ( x, b->getMin()[0],b->getMin()[1],b->getMax()[2] ) ; extend ( x ) ; + sgdSetVec3 ( x, b->getMin()[0],b->getMax()[1],b->getMin()[2] ) ; extend ( x ) ; + sgdSetVec3 ( x, b->getMin()[0],b->getMax()[1],b->getMax()[2] ) ; extend ( x ) ; + sgdSetVec3 ( x, b->getMax()[0],b->getMin()[1],b->getMin()[2] ) ; extend ( x ) ; + sgdSetVec3 ( x, b->getMax()[0],b->getMin()[1],b->getMax()[2] ) ; extend ( x ) ; + sgdSetVec3 ( x, b->getMax()[0],b->getMax()[1],b->getMin()[2] ) ; extend ( x ) ; + extend ( b->getMax() ) ; +#endif +} + + +void sgdSphere::extend ( const sgdSphere *s ) +{ + if ( s->isEmpty () ) + return ; + + if ( isEmpty () ) + { + sgdCopyVec3 ( center, s->getCenter() ) ; + radius = s->getRadius() ; + return ; + } + + /* + d == The distance between the sphere centers + */ + + SGDfloat d = sgdDistanceVec3 ( center, s->getCenter() ) ; + + if ( d + s->getRadius() <= radius ) /* New sphere is already inside this one */ + return ; + + if ( d + radius <= s->getRadius() ) /* New sphere completely contains this one */ + { + sgdCopyVec3 ( center, s->getCenter() ) ; + radius = s->getRadius() ; + return ; + } + + /* + Build a new sphere that completely contains the other two: + + The center point lies halfway along the line between + the furthest points on the edges of the two spheres. + Computing those two points is ugly - so we'll use similar + triangles + */ + + SGDfloat new_radius = (radius + d + s->getRadius() ) / SGD_TWO ; + + SGDfloat ratio = ( new_radius - radius ) / d ; + + center[0] += ( s->getCenter()[0] - center[0] ) * ratio ; + center[1] += ( s->getCenter()[1] - center[1] ) * ratio ; + center[2] += ( s->getCenter()[2] - center[2] ) * ratio ; + radius = new_radius ; +} + + +int sgdSphere::intersects ( const sgdBox *b ) const +{ + sgdVec3 closest ; + + if ( b->getMin()[0] > center[0] ) closest[0] = b->getMin()[0] ; else + if ( b->getMax()[0] < center[0] ) closest[0] = b->getMax()[0] ; else + closest[0] = center[0] ; + + if ( b->getMin()[1] > center[1] ) closest[1] = b->getMin()[1] ; else + if ( b->getMax()[1] < center[1] ) closest[1] = b->getMax()[1] ; else + closest[1] = center[1] ; + + if ( b->getMin()[2] > center[2] ) closest[2] = b->getMin()[2] ; else + if ( b->getMax()[2] < center[2] ) closest[2] = b->getMax()[2] ; else + closest[2] = center[2] ; + + return sgdCompare3DSqdDist ( closest, center, sgdSquare ( radius ) ) <= 0 ; +} + + +/************************\ +* sgdFrustum routines * +\************************/ + +void sgdFrustum::update () +{ + if ( fabs ( ffar - nnear ) < 0.1 ) + { + ulSetError ( UL_WARNING, "sgdFrustum: Can't support depth of view <0.1 units."); + return ; + } + + if ( hfov != SGD_ZERO && vfov != SGD_ZERO ) + { + if ( fabs ( hfov ) < 0.1 || fabs ( vfov ) < 0.1 ) + { + ulSetError ( UL_WARNING, ortho ? + "sgFrustum: Can't support width or height <0.1 units." : + "sgFrustum: Can't support fields of view narrower than 0.1 degrees." ) ; + return ; + } + + if ( ortho ) + { + right = SGD_HALF * hfov ; + top = SGD_HALF * vfov ; + } + else + { + right = nnear * tan ( hfov * SGD_DEGREES_TO_RADIANS / SGD_TWO ) ; + top = nnear * tan ( vfov * SGD_DEGREES_TO_RADIANS / SGD_TWO ) ; + } + + left = -right ; + bot = -top ; + } + + + /* Compute the projection matrix */ + + SGDfloat width = right - left ; + SGDfloat height = top - bot ; + SGDfloat depth = ffar - nnear ; + + if ( ortho ) + { + /* orthographic */ + + mat[0][0] = SGD_TWO / width ; + mat[0][1] = SGD_ZERO ; + mat[0][2] = SGD_ZERO ; + mat[0][3] = SGD_ZERO ; + + mat[1][0] = SGD_ZERO ; + mat[1][1] = SGD_TWO / height ; + mat[1][2] = SGD_ZERO ; + mat[1][3] = SGD_ZERO ; + + mat[2][0] = SGD_ZERO ; + mat[2][1] = SGD_ZERO ; + mat[2][2] = -SGD_TWO / depth ; + mat[2][3] = SGD_ZERO ; + + mat[3][0] = -( left + right ) / width ; + mat[3][1] = -( bot + top ) / height ; + mat[3][2] = -( nnear + ffar ) / depth ; + mat[3][3] = SGD_ONE ; + } + else + { + /* perspective */ + + mat[0][0] = SGD_TWO * nnear / width ; + mat[0][1] = SGD_ZERO ; + mat[0][2] = SGD_ZERO ; + mat[0][3] = SGD_ZERO ; + + mat[1][0] = SGD_ZERO ; + mat[1][1] = SGD_TWO * nnear / height ; + mat[1][2] = SGD_ZERO ; + mat[1][3] = SGD_ZERO ; + + mat[2][0] = ( right + left ) / width ; + mat[2][1] = ( top + bot ) / height ; + mat[2][2] = -( ffar + nnear ) / depth ; + mat[2][3] = -SGD_ONE ; + + mat[3][0] = SGD_ZERO ; + mat[3][1] = SGD_ZERO ; + mat[3][2] = -SGD_TWO * nnear * ffar / depth ; + mat[3][3] = SGD_ZERO ; + } + + + /* + * The clip planes are derived from the projection matrix. + * + * After projection (in clip coordinates), the clip planes are simply: + * + * left: ( 1, 0, 0, 1 ) + * right: ( -1, 0, 0, 1 ) + * bottom: ( 0, 1, 0, 1 ) + * top: ( 0, -1, 0, 1 ) + * near: ( 0, 0, 1, 1 ) + * far: ( 0, 0, -1, 1 ) + * + * These can easily be transformed *backwards* by + * multiplying by the transposed projection matrix, i.e: + * + * ( A ) ( A') + * ( B ) = mat^T ( B') + * ( C ) ( C') + * ( D ) ( D') + * + * where (A',B',C',D') represents a plane in clip coordinates, + * and (A,B,C,D) is the same plane expressed in eye coordinates. + */ + + sgdSetVec4( plane[ SG_LEFT_PLANE ], SGD_ONE, SGD_ZERO, SGD_ZERO, SGD_ONE ); + sgdSetVec4( plane[ SG_RIGHT_PLANE ], -SGD_ONE, SGD_ZERO, SGD_ZERO, SGD_ONE ); + sgdSetVec4( plane[ SG_BOT_PLANE ], SGD_ZERO, SGD_ONE, SGD_ZERO, SGD_ONE ); + sgdSetVec4( plane[ SG_TOP_PLANE ], SGD_ZERO, -SGD_ONE, SGD_ZERO, SGD_ONE ); + sgdSetVec4( plane[ SG_NEAR_PLANE ], SGD_ZERO, SGD_ZERO, SGD_ONE, SGD_ONE ); + sgdSetVec4( plane[ SG_FAR_PLANE ], SGD_ZERO, SGD_ZERO, -SGD_ONE, SGD_ONE ); + + for ( int i = 0 ; i < 6 ; i++ ) + { + sgdVec4 tmp ; + + for ( int j = 0 ; j < 4 ; j++ ) + tmp[j] = sgdScalarProductVec4 ( plane[i], mat[j] ) ; + + sgdScaleVec4 ( plane[i], tmp, SGD_ONE / sgdLengthVec3 ( tmp ) ) ; + } +} + + + +#define OC_LEFT_SHIFT 0 +#define OC_RIGHT_SHIFT 1 +#define OC_TOP_SHIFT 2 +#define OC_BOT_SHIFT 3 +#define OC_NEAR_SHIFT 4 +#define OC_FAR_SHIFT 5 + +#define OC_ALL_ON_SCREEN 0x3F +#define OC_OFF_TRF ((1<= -tmp[3] ) << OC_LEFT_SHIFT ) | + (( tmp[1] <= tmp[3] ) << OC_TOP_SHIFT ) | + (( tmp[1] >= -tmp[3] ) << OC_BOT_SHIFT ) | + (( tmp[2] <= tmp[3] ) << OC_FAR_SHIFT ) | + (( tmp[2] >= -tmp[3] ) << OC_NEAR_SHIFT ) ; +} + +int sgdFrustum::contains ( const sgdVec3 pt ) const +{ + return getOutcode ( pt ) == OC_ALL_ON_SCREEN ; +} + + +int sgdFrustum::contains ( const sgdSphere *s ) const +{ + + const SGDfloat *center = s->getCenter() ; + const SGDfloat radius = s->getRadius() ; + + /* + Lop off half the database (roughly) with a quick near-plane test - and + lop off a lot more with a quick far-plane test + */ + + if ( -center[2] + radius < nnear || -center[2] - radius > ffar ) + return SG_OUTSIDE ; + + /* + OK, so the sphere lies between near and far. + + Measure the distance of the center point from the four sides of the frustum, + if it's outside by more than the radius then it's history. + + It's tempting to do a quick test to see if the center point is + onscreen using sgdFrustumContainsPt - but that takes a matrix transform + which is 16 multiplies and 12 adds - versus this test which does the + whole task using only 12 multiplies and 8 adds. + */ + + /* + A few operations are saved by observing that certain values in the plane + equations are zero or one. These are specific to orthographic and perspective + projections respectively. + */ + + SGDfloat sp1, sp2, sp3, sp4 ; + + if ( ortho ) + { + /* + left: ( 1, 0, 0, x ) + right: ( -1, 0, 0, x ) + bottom: ( 0, 1, 0, x ) + top: ( 0, -1, 0, x ) + */ + sp1 = plane[ SG_LEFT_PLANE ][3] + center[0] ; + sp2 = plane[ SG_RIGHT_PLANE ][3] - center[0] ; + sp3 = plane[ SG_BOT_PLANE ][3] + center[1] ; + sp4 = plane[ SG_TOP_PLANE ][3] - center[1] ; + } + else + { + /* + left: ( x, 0, x, 0 ) + right: ( x, 0, x, 0 ) + bottom: ( 0, x, x, 0 ) + top: ( 0, x, x, 0 ) + */ + sp1 = plane[ SG_LEFT_PLANE ][0] * center[0] + plane[ SG_LEFT_PLANE ][2] * center[2] ; + sp2 = plane[ SG_RIGHT_PLANE ][0] * center[0] + plane[ SG_RIGHT_PLANE ][2] * center[2] ; + sp3 = plane[ SG_BOT_PLANE ][1] * center[1] + plane[ SG_BOT_PLANE ][2] * center[2] ; + sp4 = plane[ SG_TOP_PLANE ][1] * center[1] + plane[ SG_TOP_PLANE ][2] * center[2] ; + } + + /* + Note: in the general case, we would have to do: + + sp1 = sgdScalarProductVec3 ( left_plane, center ) + left_plane[3] ; + sp2 = sgdScalarProductVec3 ( right_plane, center ) + right_plane[3] ; + ... + sp6 = sgdScalarProductVec3 ( far_plane, center ) + far_plane[3] ; + */ + + + if ( -sp1 > radius || -sp2 > radius || -sp3 > radius || -sp4 > radius ) + return SG_OUTSIDE ; + + /* + If it's inside by more than the radius then it's *completely* inside + and we can save time elsewhere if we know that for sure. + */ + + if ( sp1 >= radius && sp2 >= radius && sp3 >= radius && sp4 >= radius + && -center[2] - radius >= nnear && -center[2] + radius <= ffar ) + return SG_INSIDE ; + + return SG_STRADDLE ; +} + + +int sgdFrustum::contains ( const sgdBox *b ) const +{ + sgdVec3 p[8] = { + { b->getMin()[0], b->getMin()[1], b->getMin()[2] }, + { b->getMax()[0], b->getMin()[1], b->getMin()[2] }, + { b->getMin()[0], b->getMax()[1], b->getMin()[2] }, + { b->getMax()[0], b->getMax()[1], b->getMin()[2] }, + { b->getMin()[0], b->getMin()[1], b->getMax()[2] }, + { b->getMax()[0], b->getMin()[1], b->getMax()[2] }, + { b->getMin()[0], b->getMax()[1], b->getMax()[2] }, + { b->getMax()[0], b->getMax()[1], b->getMax()[2] }, + } ; + + int all = -1 ; + int one = 0 ; + + for (int i = 0 ; i < 8 ; i++ ) + { + int tmp = ~ getOutcode ( p[i] ) ; + all &= tmp ; + one |= tmp ; + } + + return ( all ? SG_OUTSIDE : one ? SG_STRADDLE : SG_INSIDE ) ; +} + + + + +SGDfloat sgdDistSquaredToLineVec3 ( const sgdLine3 line, const sgdVec3 pnt ) +{ + sgdVec3 r ; sgdSubVec3 ( r, pnt, line.point_on_line ) ; + + return sgdScalarProductVec3 ( r, r ) - + sgdScalarProductVec3 ( r, line.direction_vector ) ; +} + + + +SGDfloat sgdDistSquaredToLineSegmentVec3 ( const sgdLineSegment3 line, + const sgdVec3 pnt ) +{ + sgdVec3 v ; sgdSubVec3 ( v, line.b, line.a ) ; + sgdVec3 r1 ; sgdSubVec3 ( r1, pnt, line.a ) ; + + SGDfloat r1_dot_v = sgdScalarProductVec3 ( r1, v ) ; + + if ( r1_dot_v <= 0 ) /* Off the "A" end */ + return sgdScalarProductVec3 ( r1, r1 ) ; + + sgdVec3 r2 ; sgdSubVec3 ( r2, pnt, line.b ) ; + + SGDfloat r2_dot_v = sgdScalarProductVec3 ( r2, v ) ; + + if ( r2_dot_v >= 0 ) /* Off the "B" end */ + return sgdScalarProductVec3 ( r2, r2 ) ; + + /* Closest point on line is on the line segment */ + + return sgdScalarProductVec3 ( r1, r1 ) - r1_dot_v * r1_dot_v / sgdScalarProductVec3 ( v, v ) ; +} + + + +void sgdMakeCoordMat4 ( sgdMat4 m, const SGDfloat x, const SGDfloat y, const SGDfloat z, const SGDfloat h, const SGDfloat p, const SGDfloat r ) +{ + SGDfloat ch, sh, cp, sp, cr, sr, srsp, crsp, srcp ; + + if ( h == SGD_ZERO ) + { + ch = SGD_ONE ; + sh = SGD_ZERO ; + } + else + { + sh = sgdSin( h ) ; + ch = sgdCos( h ) ; + } + + if ( p == SGD_ZERO ) + { + cp = SGD_ONE ; + sp = SGD_ZERO ; + } + else + { + sp = sgdSin( p ) ; + cp = sgdCos( p ) ; + } + + if ( r == SGD_ZERO ) + { + cr = SGD_ONE ; + sr = SGD_ZERO ; + srsp = SGD_ZERO ; + srcp = SGD_ZERO ; + crsp = sp ; + } + else + { + sr = sgdSin( r ) ; + cr = sgdCos( r ) ; + srsp = sr * sp ; + crsp = cr * sp ; + srcp = sr * cp ; + } + + m[0][0] = ch * cr - sh * srsp ; + m[1][0] = -sh * cp ; + m[2][0] = sr * ch + sh * crsp ; + m[3][0] = x ; + + m[0][1] = cr * sh + srsp * ch ; + m[1][1] = ch * cp ; + m[2][1] = sr * sh - crsp * ch ; + m[3][1] = y ; + + m[0][2] = -srcp ; + m[1][2] = sp ; + m[2][2] = cr * cp ; + m[3][2] = z ; + + m[0][3] = SGD_ZERO ; + m[1][3] = SGD_ZERO ; + m[2][3] = SGD_ZERO ; + m[3][3] = SGD_ONE ; +} + + +void sgdMakeTransMat4 ( sgdMat4 m, const sgdVec3 xyz ) +{ + m[0][1] = m[0][2] = m[0][3] = + m[1][0] = m[1][2] = m[1][3] = + m[2][0] = m[2][1] = m[2][3] = SGD_ZERO ; + m[0][0] = m[1][1] = m[2][2] = m[3][3] = SGD_ONE ; + sgdCopyVec3 ( m[3], xyz ) ; +} + + +void sgdMakeTransMat4 ( sgdMat4 m, const SGDfloat x, const SGDfloat y, const SGDfloat z ) +{ + m[0][1] = m[0][2] = m[0][3] = + m[1][0] = m[1][2] = m[1][3] = + m[2][0] = m[2][1] = m[2][3] = SGD_ZERO ; + m[0][0] = m[1][1] = m[2][2] = m[3][3] = SGD_ONE ; + sgdSetVec3 ( m[3], x, y, z ) ; +} + + +void sgdSetCoord ( sgdCoord *dst, const sgdMat4 src ) +{ + sgdCopyVec3 ( dst->xyz, src[3] ) ; + + sgdMat4 mat ; + + SGDfloat s = sgdLengthVec3 ( src[0] ) ; + + if ( s <= 0.00001 ) + { + ulSetError ( UL_WARNING, "sgdMat4ToCoord: ERROR - Bad Matrix." ) ; + sgdSetVec3 ( dst -> hpr, SGD_ZERO, SGD_ZERO, SGD_ZERO ) ; + return ; + } + + sgdScaleMat4 ( mat, src, SGD_ONE / s ) ; + + dst->hpr[1] = sgdASin ( _sgdClampToUnity ( mat[1][2] ) ) ; + + SGDfloat cp = sgdCos ( dst->hpr[1] ) ; + + /* If pointing nearly vertically up - then heading is ill-defined */ + + if ( cp > -0.00001 && cp < 0.00001 ) + { + SGDfloat cr = _sgdClampToUnity ( mat[0][1] ) ; + SGDfloat sr = _sgdClampToUnity (-mat[2][1] ) ; + + dst->hpr[0] = SGD_ZERO ; + dst->hpr[2] = sgdATan2 ( sr, cr ) ; + } + else + { + cp = SGD_ONE / cp ; + SGDfloat sr = _sgdClampToUnity ( -mat[0][2] * cp ) ; + SGDfloat cr = _sgdClampToUnity ( mat[2][2] * cp ) ; + SGDfloat sh = _sgdClampToUnity ( -mat[1][0] * cp ) ; + SGDfloat ch = _sgdClampToUnity ( mat[1][1] * cp ) ; + + if ( (sh == SGD_ZERO && ch == SGD_ZERO) || (sr == SGD_ZERO && cr == SGD_ZERO) ) + { + cr = _sgdClampToUnity ( mat[0][1] ) ; + sr = _sgdClampToUnity (-mat[2][1] ) ; + + dst->hpr[0] = SGD_ZERO ; + } + else + dst->hpr[0] = sgdATan2 ( sh, ch ) ; + + dst->hpr[2] = sgdATan2 ( sr, cr ) ; + } +} + + +void sgdMakeNormal(sgdVec2 dst, const sgdVec2 a, const sgdVec2 b ) +{ + sgdSubVec2 ( dst, b, a ) ; + SGDfloat tmp = dst [ 0 ] ; dst [ 0 ] = -dst [ 1 ] ; dst [ 1 ] = tmp ; + sgdNormaliseVec2 ( dst ) ; +} + + +void sgdMakeNormal(sgdVec3 dst, const sgdVec3 a, const sgdVec3 b, const sgdVec3 c ) +{ + sgdVec3 ab ; sgdSubVec3 ( ab, b, a ) ; + sgdVec3 ac ; sgdSubVec3 ( ac, c, a ) ; + sgdVectorProductVec3 ( dst, ab,ac ) ; sgdNormaliseVec3 ( dst ) ; +} + + +void sgdPreMultMat4( sgdMat4 dst, const sgdMat4 src ) +{ + sgdMat4 mat ; + sgdMultMat4 ( mat, dst, src ) ; + sgdCopyMat4 ( dst, mat ) ; +} + +void sgdPostMultMat4( sgdMat4 dst, const sgdMat4 src ) +{ + sgdMat4 mat ; + sgdMultMat4 ( mat, src, dst ) ; + sgdCopyMat4 ( dst, mat ) ; +} + +void sgdMultMat4( sgdMat4 dst, const sgdMat4 m1, const sgdMat4 m2 ) +{ + for ( int j = 0 ; j < 4 ; j++ ) + { + dst[0][j] = m2[0][0] * m1[0][j] + + m2[0][1] * m1[1][j] + + m2[0][2] * m1[2][j] + + m2[0][3] * m1[3][j] ; + + dst[1][j] = m2[1][0] * m1[0][j] + + m2[1][1] * m1[1][j] + + m2[1][2] * m1[2][j] + + m2[1][3] * m1[3][j] ; + + dst[2][j] = m2[2][0] * m1[0][j] + + m2[2][1] * m1[1][j] + + m2[2][2] * m1[2][j] + + m2[2][3] * m1[3][j] ; + + dst[3][j] = m2[3][0] * m1[0][j] + + m2[3][1] * m1[1][j] + + m2[3][2] * m1[2][j] + + m2[3][3] * m1[3][j] ; + } +} + + +void sgdTransposeNegateMat4 ( sgdMat4 dst, const sgdMat4 src ) +{ + /* Poor man's invert - can be used when matrix is a simple rotate-translate */ + + dst[0][0] = src[0][0] ; + dst[1][0] = src[0][1] ; + dst[2][0] = src[0][2] ; + dst[3][0] = - sgdScalarProductVec3 ( src[3], src[0] ) ; + + dst[0][1] = src[1][0] ; + dst[1][1] = src[1][1] ; + dst[2][1] = src[1][2] ; + dst[3][1] = - sgdScalarProductVec3 ( src[3], src[1] ) ; + + dst[0][2] = src[2][0] ; + dst[1][2] = src[2][1] ; + dst[2][2] = src[2][2] ; + dst[3][2] = - sgdScalarProductVec3 ( src[3], src[2] ) ; + + dst[0][3] = SGD_ZERO ; + dst[1][3] = SGD_ZERO ; + dst[2][3] = SGD_ZERO ; + dst[3][3] = SGD_ONE ; +} + + +void sgdTransposeNegateMat4 ( sgdMat4 dst ) +{ + sgdMat4 src ; + sgdCopyMat4 ( src, dst ) ; + sgdTransposeNegateMat4 ( dst, src ) ; +} + + + +void sgdInvertMat4 ( sgdMat4 dst, const sgdMat4 src ) +{ + sgdMat4 tmp ; + + sgdCopyMat4 ( tmp, src ) ; + sgdMakeIdentMat4 ( dst ) ; + + for ( int i = 0 ; i != 4 ; i++ ) + { + SGDfloat val = tmp[i][i] ; + int ind = i ; + int j ; + + for ( j = i + 1 ; j != 4 ; j++ ) + { + if ( fabs ( tmp[i][j] ) > fabs(val) ) + { + ind = j; + val = tmp[i][j] ; + } + } + + if ( ind != i ) + { /* swap columns */ + for ( j = 0 ; j != 4 ; j++ ) + { + SGDfloat t ; + t = dst[j][i]; dst[j][i] = dst[j][ind]; dst[j][ind] = t ; + t = tmp[j][i]; tmp[j][i] = tmp[j][ind]; tmp[j][ind] = t ; + } + } + + // if ( val == SG_ZERO) + if ( fabs(val) <= DBL_EPSILON ) + { + ulSetError ( UL_WARNING, "sg: ERROR - Singular matrix, no inverse!" ) ; + sgdMakeIdentMat4 ( dst ) ; /* Do *something* */ + return; + } + + SGDfloat ival = SGD_ONE / val ; + + for ( j = 0 ; j != 4 ; j++ ) + { + tmp[j][i] *= ival ; + dst[j][i] *= ival ; + } + + for (j = 0; j != 4; j++) + { + if ( j == i ) + continue ; + + val = tmp[i][j] ; + + for ( int k = 0 ; k != 4 ; k++ ) + { + tmp[k][j] -= tmp[k][i] * val ; + dst[k][j] -= dst[k][i] * val ; + } + } + } +} + + + +void sgdXformVec3 ( sgdVec3 dst, const sgdVec3 src, const sgdMat4 mat ) +{ + SGDfloat t0 = src[ 0 ] ; + SGDfloat t1 = src[ 1 ] ; + SGDfloat t2 = src[ 2 ] ; + + dst[0] = ( t0 * mat[ 0 ][ 0 ] + + t1 * mat[ 1 ][ 0 ] + + t2 * mat[ 2 ][ 0 ] ) ; + + dst[1] = ( t0 * mat[ 0 ][ 1 ] + + t1 * mat[ 1 ][ 1 ] + + t2 * mat[ 2 ][ 1 ] ) ; + + dst[2] = ( t0 * mat[ 0 ][ 2 ] + + t1 * mat[ 1 ][ 2 ] + + t2 * mat[ 2 ][ 2 ] ) ; +} + + +void sgdXformPnt3 ( sgdVec3 dst, const sgdVec3 src, const sgdMat4 mat ) +{ + SGDfloat t0 = src[ 0 ] ; + SGDfloat t1 = src[ 1 ] ; + SGDfloat t2 = src[ 2 ] ; + + dst[0] = ( t0 * mat[ 0 ][ 0 ] + + t1 * mat[ 1 ][ 0 ] + + t2 * mat[ 2 ][ 0 ] + + mat[ 3 ][ 0 ] ) ; + + dst[1] = ( t0 * mat[ 0 ][ 1 ] + + t1 * mat[ 1 ][ 1 ] + + t2 * mat[ 2 ][ 1 ] + + mat[ 3 ][ 1 ] ) ; + + dst[2] = ( t0 * mat[ 0 ][ 2 ] + + t1 * mat[ 1 ][ 2 ] + + t2 * mat[ 2 ][ 2 ] + + mat[ 3 ][ 2 ] ) ; +} + + +void sgdXformPnt4 ( sgdVec4 dst, const sgdVec4 src, const sgdMat4 mat ) +{ + SGDfloat t0 = src[ 0 ] ; + SGDfloat t1 = src[ 1 ] ; + SGDfloat t2 = src[ 2 ] ; + SGDfloat t3 = src[ 3 ] ; + + dst[0] = ( t0 * mat[ 0 ][ 0 ] + + t1 * mat[ 1 ][ 0 ] + + t2 * mat[ 2 ][ 0 ] + + t3 * mat[ 3 ][ 0 ] ) ; + + dst[1] = ( t0 * mat[ 0 ][ 1 ] + + t1 * mat[ 1 ][ 1 ] + + t2 * mat[ 2 ][ 1 ] + + t3 * mat[ 3 ][ 1 ] ) ; + + dst[2] = ( t0 * mat[ 0 ][ 2 ] + + t1 * mat[ 1 ][ 2 ] + + t2 * mat[ 2 ][ 2 ] + + t3 * mat[ 3 ][ 2 ] ) ; + + dst[3] = ( t0 * mat[ 0 ][ 3 ] + + t1 * mat[ 1 ][ 3 ] + + t2 * mat[ 2 ][ 3 ] + + t3 * mat[ 3 ][ 3 ] ) ; +} + + +void sgdFullXformPnt3 ( sgdVec3 dst, const sgdVec3 src, const sgdMat4 mat ) +{ + sgdVec4 tmp ; + + tmp [ 0 ] = src [ 0 ] ; + tmp [ 1 ] = src [ 1 ] ; + tmp [ 2 ] = src [ 2 ] ; + tmp [ 3 ] = SGD_ONE ; + + sgdXformPnt4 ( tmp, tmp, mat ) ; + sgdScaleVec3 ( dst, tmp, SGD_ONE / tmp [ 3 ] ) ; +} + +void sgdHPRfromVec3 ( sgdVec3 hpr, sgdVec3 src ) +{ + sgdVec3 tmp ; + sgdCopyVec3 ( tmp, src ) ; + sgdNormaliseVec3 ( tmp ) ; + hpr[0] = - sgdATan2 ( tmp [ 0 ], tmp [ 1 ] ) ; + hpr[1] = - sgdATan2 ( tmp [ 2 ], sgdSqrt ( sgdSquare ( tmp [ 0 ] ) + + sgdSquare ( tmp [ 1 ] ) ) ) ; + hpr[2] = SGD_ZERO ; +} + + + +/* + Quaternion routines are Copyright (C) 1999 + Kevin B. Thompson + Modified by Sylvan W. Clebsch + Largely rewritten by "Negative0" +*/ + + +void sgdQuatToAngleAxis ( SGDfloat *angle, + SGDfloat *x, SGDfloat *y, SGDfloat *z, + const sgdQuat src ) +{ + sgdVec3 axis ; + + sgdQuatToAngleAxis ( angle, axis, src ) ; + + *x = axis [ 0 ] ; + *y = axis [ 1 ] ; + *z = axis [ 2 ] ; +} + + +void sgdQuatToAngleAxis ( SGDfloat *angle, sgdVec3 axis, const sgdQuat src ) +{ + SGDfloat a = (SGDfloat) acos ( src[SGD_W] ) ; + SGDfloat s = (SGDfloat) sin ( a ) ; + + *angle = a * SGD_RADIANS_TO_DEGREES * SGD_TWO ; + + if ( s == SGD_ZERO ) + sgdSetVec3 ( axis, SGD_ZERO, SGD_ZERO, SGD_ONE ); + else + { + sgdSetVec3 ( axis, src[SGD_X], src[SGD_Y], src[SGD_Z] ) ; + sgdScaleVec3 ( axis, SGD_ONE / s ) ; + } +} + + +void sgdAngleAxisToQuat ( sgdQuat dst, + const SGDfloat angle, + const SGDfloat x, const SGDfloat y, const SGDfloat z ) +{ + sgdVec3 axis ; + sgdSetVec3 ( axis, x, y, z ) ; + sgdAngleAxisToQuat ( dst, angle, axis ) ; +} + + +void sgdAngleAxisToQuat ( sgdQuat dst, const SGDfloat angle, const sgdVec3 axis ) +{ + SGDfloat temp_angle = angle * SGD_DEGREES_TO_RADIANS / SGD_TWO ; + + sgdVec3 ax ; + sgdNormaliseVec3 ( ax, axis ) ; + + SGDfloat s = - (SGDfloat) sin ( temp_angle ) ; + + dst[SGD_W] = (SGDfloat) cos ( temp_angle ) ; + sgdScaleVec3 ( dst, ax, s ) ; +} + + +//from gamasutra.com +//by nb + +void sgdMatrixToQuat( sgdQuat quat, const sgdMat4 m ) +{ + SGDfloat tr, s, q[4] ; + int i, j, k ; + + int nxt[3] = {1, 2, 0}; + + tr = m[0][0] + m[1][1] + m[2][2]; + + // check the diagonal + if (tr > SGD_ZERO ) + { + s = (SGDfloat) sqrt (tr + SGD_ONE); + quat[SGD_W] = s / SGD_TWO; + s = SGD_HALF / s; + quat[SGD_X] = (m[1][2] - m[2][1]) * s; + quat[SGD_Y] = (m[2][0] - m[0][2]) * s; + quat[SGD_Z] = (m[0][1] - m[1][0]) * s; + } + else + { + // diagonal is negative + i = 0; + if (m[1][1] > m[0][0]) i = 1; + if (m[2][2] > m[i][i]) i = 2; + j = nxt[i]; + k = nxt[j]; + s = sqrt ((m[i][i] - (m[j][j] + m[k][k])) + SGD_ONE); + q[i] = s * SGD_HALF; + + if (s != SGD_ZERO) s = SGD_HALF / s; + + q[3] = (m[j][k] - m[k][j]) * s; + q[j] = (m[i][j] + m[j][i]) * s; + q[k] = (m[i][k] + m[k][i]) * s; + + quat[SGD_X] = q[0]; + quat[SGD_Y] = q[1]; + quat[SGD_Z] = q[2]; + quat[SGD_W] = q[3]; + } + + // seems to yield the inverse rotation, so: + quat[SG_W] = - quat[SG_W]; +} + + +void sgdMultQuat ( sgdQuat dst, const sgdQuat a, const sgdQuat b ) +{ + /* [ ww' - v.v', vxv' + wv' + v'w ] */ + + SGDfloat t[8]; + + t[0] = (a[SGD_W] + a[SGD_X]) * (b[SGD_W] + b[SGD_X]); + t[1] = (a[SGD_Z] - a[SGD_Y]) * (b[SGD_Y] - b[SGD_Z]); + t[2] = (a[SGD_X] - a[SGD_W]) * (b[SGD_Y] + b[SGD_Z]); + t[3] = (a[SGD_Y] + a[SGD_Z]) * (b[SGD_X] - b[SGD_W]); + t[4] = (a[SGD_X] + a[SGD_Z]) * (b[SGD_X] + b[SGD_Y]); + t[5] = (a[SGD_X] - a[SGD_Z]) * (b[SGD_X] - b[SGD_Y]); + t[6] = (a[SGD_W] + a[SGD_Y]) * (b[SGD_W] - b[SGD_Z]); + t[7] = (a[SGD_W] - a[SGD_Y]) * (b[SGD_W] + b[SGD_Z]); + + dst[SGD_W] = t[1] + ((-t[4] - t[5] + t[6] + t[7]) * SGD_HALF); + dst[SGD_X] = t[0] - (( t[4] + t[5] + t[6] + t[7]) * SGD_HALF); + dst[SGD_Y] = -t[2] + (( t[4] - t[5] + t[6] - t[7]) * SGD_HALF); + dst[SGD_Z] = -t[3] + (( t[4] - t[5] - t[6] + t[7]) * SGD_HALF); +} + +//from gamasutra.com +//by nb@netcom.ca + +void sgdMultQuat2 ( sgdQuat dst, const sgdQuat a, const sgdQuat b ) +{ + SGDfloat A, B, C, D, E, F, G, H; + + A = (a[SGD_W] + a[SGD_X]) * (b[SGD_W] + b[SGD_X]) ; + B = (a[SGD_Z] - a[SGD_Y]) * (b[SGD_Y] - b[SGD_Z]) ; + C = (a[SGD_X] - a[SGD_W]) * (b[SGD_Y] + b[SGD_Z]) ; + D = (a[SGD_Y] + a[SGD_Z]) * (b[SGD_X] - b[SGD_W]) ; + E = (a[SGD_X] + a[SGD_Z]) * (b[SGD_X] + b[SGD_Y]) ; + F = (a[SGD_X] - a[SGD_Z]) * (b[SGD_X] - b[SGD_Y]) ; + G = (a[SGD_W] + a[SGD_Y]) * (b[SGD_W] - b[SGD_Z]) ; + H = (a[SGD_W] - a[SGD_Y]) * (b[SGD_W] + b[SGD_Z]) ; + + + dst[SGD_W] = B + (-E - F + G + H) / SGD_TWO ; + dst[SGD_X] = A - ( E + F + G + H) / SGD_TWO ; + dst[SGD_Y] = -C + ( E - F + G - H) / SGD_TWO ; + dst[SGD_Z] = -D + ( E - F - G + H) / SGD_TWO ; +} + +//from gamasutra.com +//by nb@netcom.ca + +void sgdEulerToQuat(sgdQuat quat, const sgdVec3 hpr ) +{ + SGDfloat cr, cp, cy, sr, sp, sy, cpcy, spsy; + +// calculate trig identities + cr = (SGDfloat) cos(hpr[2]*SGD_DEGREES_TO_RADIANS/SGD_TWO); + cp = (SGDfloat) cos(hpr[1]*SGD_DEGREES_TO_RADIANS/SGD_TWO); + cy = (SGDfloat) cos(hpr[0]*SGD_DEGREES_TO_RADIANS/SGD_TWO); + + sr = (SGDfloat) sin(hpr[2]*SGD_DEGREES_TO_RADIANS/SGD_TWO); + sp = (SGDfloat) sin(hpr[1]*SGD_DEGREES_TO_RADIANS/SGD_TWO); + sy = (SGDfloat) sin(hpr[0]*SGD_DEGREES_TO_RADIANS/SGD_TWO); + + cpcy = cp * cy; + spsy = sp * sy; + + quat[SGD_W] = cr * cpcy + sr * spsy; + quat[SGD_X] = sr * cpcy - cr * spsy; + quat[SGD_Y] = cr * sp * cy + sr * cp * sy; + quat[SGD_Z] = cr * cp * sy - sr * sp * cy; +} + +//from darwin3d.com +// jeffl@darwin3d.com + +void sgdQuatToEuler( sgdVec3 hpr, const sgdQuat quat ) +{ + SGDfloat matrix[3][3]; + SGDfloat cx,sx; + SGDfloat cy,sy; + SGDfloat cz,sz; + + // CONVERT QUATERNION TO MATRIX - I DON'T REALLY NEED ALL OF IT + + matrix[0][0] = SGD_ONE - (SGD_TWO * quat[SGD_Y] * quat[SGD_Y]) + - (SGD_TWO * quat[SGD_Z] * quat[SGD_Z]); +//matrix[0][1] = (SGD_TWO * quat->x * quat->y) - (SGD_TWO * quat->w * quat->z); +//matrix[0][2] = (SGD_TWO * quat->x * quat->z) + (SGD_TWO * quat->w * quat->y); + + matrix[1][0] = (SGD_TWO * quat[SGD_X] * quat[SGD_Y]) + + (SGD_TWO * quat[SGD_W] * quat[SGD_Z]); +//matrix[1][1] = SGD_ONE - (SGD_TWO * quat->x * quat->x) +// - (SGD_TWO * quat->z * quat->z); +//matrix[1][2] = (SGD_TWO * quat->y * quat->z) - (SGD_TWO * quat->w * quat->x); + + matrix[2][0] = (SGD_TWO * quat[SGD_X] * quat[SGD_Z]) - + (SGD_TWO * quat[SGD_W] * quat[SGD_Y]); + matrix[2][1] = (SGD_TWO * quat[SGD_Y] * quat[SGD_Z]) + + (SGD_TWO * quat[SGD_W] * quat[SGD_X]); + matrix[2][2] = SGD_ONE - (SGD_TWO * quat[SGD_X] * quat[SGD_X]) + - (SGD_TWO * quat[SGD_Y] * quat[SGD_Y]); + + sy = -matrix[2][0]; + cy = sgdSqrt(SGD_ONE - (sy * sy)); + + hpr[1] = sgdATan2( sy, cy ); + + // AVOID DIVIDE BY ZERO ERROR ONLY WHERE Y= +-90 or +-270 + // NOT CHECKING cy BECAUSE OF PRECISION ERRORS + if (sy != SGD_ONE && sy != -SGD_ONE) + { + cx = matrix[2][2] / cy; + sx = matrix[2][1] / cy; + hpr[0] = sgdATan2 ( sx, cx ); + + cz = matrix[0][0] / cy; + sz = matrix[1][0] / cy; + hpr[2] = sgdATan2 ( sz, cz ); + } + else + { + // SINCE Cos(Y) IS 0, I AM SCREWED. ADOPT THE STANDARD Z = 0 + // I THINK THERE IS A WAY TO FIX THIS BUT I AM NOT SURE. EULERS SUCK + // NEED SOME MORE OF THE MATRIX TERMS NOW + + matrix[1][1] = SGD_ONE - (SGD_TWO * quat[SGD_X] * quat[SGD_X]) + - (SGD_TWO * quat[SGD_Z] * quat[SGD_Z]); + matrix[1][2] = (SGD_TWO * quat[SGD_Y] * quat[SGD_Z]) - + (SGD_TWO * quat[SGD_W] * quat[SGD_X]); + + cx = matrix[1][1]; + sx = -matrix[1][2]; + hpr[0] = sgdATan2 ( sx, cx ); + + cz = SGD_ONE ; + sz = SGD_ZERO ; + hpr[2] = sgdATan2 ( sz, cz ); + } +} + + +void sgdQuatToMatrix ( sgdMat4 dst, const sgdQuat q ) +{ + SGDfloat two_xx = q[SGD_X] * (q[SGD_X] + q[SGD_X]) ; + SGDfloat two_xy = q[SGD_X] * (q[SGD_Y] + q[SGD_Y]) ; + SGDfloat two_xz = q[SGD_X] * (q[SGD_Z] + q[SGD_Z]) ; + + SGDfloat two_wx = q[SGD_W] * (q[SGD_X] + q[SGD_X]) ; + SGDfloat two_wy = q[SGD_W] * (q[SGD_Y] + q[SGD_Y]) ; + SGDfloat two_wz = q[SGD_W] * (q[SGD_Z] + q[SGD_Z]) ; + + SGDfloat two_yy = q[SGD_Y] * (q[SGD_Y] + q[SGD_Y]) ; + SGDfloat two_yz = q[SGD_Y] * (q[SGD_Z] + q[SGD_Z]) ; + + SGDfloat two_zz = q[SGD_Z] * (q[SGD_Z] + q[SGD_Z]) ; + + sgdSetVec4 ( dst[0], SGD_ONE-(two_yy+two_zz), two_xy-two_wz, two_xz+two_wy, SGD_ZERO ) ; + sgdSetVec4 ( dst[1], two_xy+two_wz, SGD_ONE-(two_xx+two_zz), two_yz-two_wx, SGD_ZERO ) ; + sgdSetVec4 ( dst[2], two_xz-two_wy, two_yz+two_wx, SGD_ONE-(two_xx+two_yy), SGD_ZERO ) ; + sgdSetVec4 ( dst[3], SGD_ZERO, SGD_ZERO, SGD_ZERO, SGD_ONE ) ; +} + + +//from gamasutra.com +//by nb@netcom.ca + +/************************************ + DEPRECATED - use sgdQuatToMatrix instead. +*************************************/ + +void sgdMakeRotMat42( sgdMat4 m, sgdQuat quat ){ + SGDfloat wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2; + + // calculate coefficients + x2 = quat[SGD_X] + quat[SGD_X]; y2 = quat[SGD_Y] + quat[SGD_Y]; + z2 = quat[SGD_Z] + quat[SGD_Z]; + xx = quat[SGD_X] * x2; xy = quat[SGD_X] * y2; xz = quat[SGD_X] * z2; + yy = quat[SGD_Y] * y2; yz = quat[SGD_Y] * z2; zz = quat[SGD_Z] * z2; + wx = quat[SGD_W] * x2; wy = quat[SGD_W] * y2; wz = quat[SGD_W] * z2; + + m[0][0] = SGD_ONE- (yy + zz); m[0][1] = xy - wz; + m[0][2] = xz + wy; m[0][3] = SGD_ZERO ; + + m[1][0] = xy + wz; m[1][1] = SGD_ONE- (xx + zz); + m[1][2] = yz - wx; m[1][3] = SGD_ZERO ; + + m[2][0] = xz - wy; m[2][1] = yz + wx; + m[2][2] = SGD_ONE- (xx + yy); m[2][3] = SGD_ZERO ; + + m[3][0] = 0; m[3][1] = 0; + m[3][2] = 0; m[3][3] = 1; +} + +//from gamasutra.com +//by nb@netcom.ca + +void sgdSlerpQuat2( sgdQuat dst, const sgdQuat from, const sgdQuat to, const SGDfloat t ) +{ + SGDfloat to1[4]; + SGDfloat omega, cosom, sinom, scale0, scale1; + + // calc cosine + cosom = from[SGD_X] * to[SGD_X] + + from[SGD_Y] * to[SGD_Y] + + from[SGD_Z] * to[SGD_Z] + + from[SGD_W] * to[SGD_W]; + + // adjust signs (if necessary) + + if ( cosom < SG_ZERO ) + { + cosom = -cosom; + to1[0] = - to[SGD_X]; + to1[1] = - to[SGD_Y]; + to1[2] = - to[SGD_Z]; + to1[3] = - to[SGD_W]; + } + else + { + to1[0] = to[SGD_X]; + to1[1] = to[SGD_Y]; + to1[2] = to[SGD_Z]; + to1[3] = to[SGD_W]; + } + + // calculate coefficients +#define DELTA SGD_ZERO + if ( (SGD_ONE- cosom) > DELTA ) { + // standard case (slerp) + omega = acos(cosom); + sinom = sin(omega); + scale0 = sin((SGD_ONE- t) * omega) / sinom; + scale1 = sin(t * omega) / sinom; + + } + else + { + // "from" and "to" quaternions are very close + // ... so we can do a linear interpolation + scale0 = SGD_ONE- t; + scale1 = t; + } + + // calculate final values + dst[SGD_X] = scale0 * from[SGD_X] + scale1 * to1[0]; + dst[SGD_Y] = scale0 * from[SGD_Y] + scale1 * to1[1]; + dst[SGD_Z] = scale0 * from[SGD_Z] + scale1 * to1[2]; + dst[SGD_W] = scale0 * from[SGD_W] + scale1 * to1[3]; +} + +void sgdSlerpQuat( sgdQuat dst, const sgdQuat from, const sgdQuat to, const SGDfloat t ) +{ + SGDfloat co, scale0, scale1; + bool flip = false ; + + /* SWC - Interpolate between to quaternions */ + + co = sgdScalarProductVec4 ( from, to ) ; + + if ( co < SGD_ZERO ) + { + co = -co; + flip = true ; + } + + if ( co < SGD_ONE - (SGDfloat) 1e-6 ) + { + SGDfloat o = (SGDfloat) acos ( co ); + SGDfloat so = SGD_ONE / (SGDfloat) sin ( o ); + + scale0 = (SGDfloat) sin ( (SGD_ONE - t) * o ) * so; + scale1 = (SGDfloat) sin ( t * o ) * so; + } + else + { + scale0 = SGD_ONE - t; + scale1 = t; + } + + if ( flip ) + { + scale1 = -scale1 ; + } + + dst[SGD_X] = scale0 * from[SGD_X] + scale1 * to[SGD_X] ; + dst[SGD_Y] = scale0 * from[SGD_Y] + scale1 * to[SGD_Y] ; + dst[SGD_Z] = scale0 * from[SGD_Z] + scale1 * to[SGD_Z] ; + dst[SGD_W] = scale0 * from[SGD_W] + scale1 * to[SGD_W] ; +} + + + + +/* Function to rotate a vector through a given quaternion using the formula + * R = Q r Q-1 -- this gives the components of a ROTATED vector in a STATIONARY + * coordinate system. We assume that Q is a unit quaternion. + */ +void sgdRotateVecQuat ( sgdVec3 vec, sgdQuat q ) +{ + sgdVec3 rot ; + sgdFloat qwqw = q[SG_W] * q[SG_W] ; + sgdFloat qwqx = q[SG_W] * q[SG_X] ; + sgdFloat qwqy = q[SG_W] * q[SG_Y] ; + sgdFloat qwqz = q[SG_W] * q[SG_Z] ; + sgdFloat qxqx = q[SG_X] * q[SG_X] ; + sgdFloat qxqy = q[SG_X] * q[SG_Y] ; + sgdFloat qxqz = q[SG_X] * q[SG_Z] ; + sgdFloat qyqy = q[SG_Y] * q[SG_Y] ; + sgdFloat qyqz = q[SG_Y] * q[SG_Z] ; + sgdFloat qzqz = q[SG_Z] * q[SG_Z] ; + rot[SG_X] = ( qwqw + qxqx - qyqy - qzqz ) * vec[SG_X] + 2.0f * ( qxqy - qwqz ) * vec[SG_Y] + 2.0f * ( qxqz + qwqy ) * vec[SG_Z] ; + rot[SG_Y] = ( qwqw - qxqx + qyqy - qzqz ) * vec[SG_Y] + 2.0f * ( qyqz - qwqx ) * vec[SG_Z] + 2.0f * ( qxqy + qwqz ) * vec[SG_X] ; + rot[SG_Z] = ( qwqw - qxqx - qyqy + qzqz ) * vec[SG_Z] + 2.0f * ( qxqz - qwqy ) * vec[SG_X] + 2.0f * ( qyqz + qwqx ) * vec[SG_Y] ; + sgdCopyVec3 ( vec, rot ) ; +} + +/* Function to rotate a vector through a given quaternion using the formula + * R = Q-1 r Q -- this gives the components of a STATIONARY vector in a ROTATED + * coordinate system. We assume that Q is a unit quaternion. + */ +void sgdRotateCoordQuat ( sgdVec3 vec, sgdQuat q ) +{ + sgdVec3 rot ; + sgdFloat qwqw = q[SG_W] * q[SG_W] ; + sgdFloat qwqx = q[SG_W] * q[SG_X] ; + sgdFloat qwqy = q[SG_W] * q[SG_Y] ; + sgdFloat qwqz = q[SG_W] * q[SG_Z] ; + sgdFloat qxqx = q[SG_X] * q[SG_X] ; + sgdFloat qxqy = q[SG_X] * q[SG_Y] ; + sgdFloat qxqz = q[SG_X] * q[SG_Z] ; + sgdFloat qyqy = q[SG_Y] * q[SG_Y] ; + sgdFloat qyqz = q[SG_Y] * q[SG_Z] ; + sgdFloat qzqz = q[SG_Z] * q[SG_Z] ; + rot[SG_X] = ( qwqw + qxqx - qyqy - qzqz ) * vec[SG_X] + 2.0f * ( qxqy + qwqz ) * vec[SG_Y] + 2.0f * ( qxqz - qwqy ) * vec[SG_Z] ; + rot[SG_Y] = ( qwqw - qxqx + qyqy - qzqz ) * vec[SG_Y] + 2.0f * ( qyqz + qwqx ) * vec[SG_Z] + 2.0f * ( qxqy - qwqz ) * vec[SG_X] ; + rot[SG_Z] = ( qwqw - qxqx - qyqy + qzqz ) * vec[SG_Z] + 2.0f * ( qxqz + qwqy ) * vec[SG_X] + 2.0f * ( qyqz - qwqx ) * vec[SG_Y] ; + sgdCopyVec3 ( vec, rot ) ; +} + + +sgdFloat sgdDistSquaredToLineLineSegment ( const sgdLineSegment3 seg, const sgdLine3 line ) +{ + /* Convert the line segment to a line. We will deal with the segment limits later. */ + sgdLine3 line2 ; + sgdLineSegment3ToLine3 ( &line2, seg ) ; + + /* Get the dot product of the two direction vectors */ + sgdFloat t1_dot_t2 = sgdScalarProductVec3 ( line.direction_vector, line2.direction_vector ) ; + + /* If the lines are parallel, distance is just the distance from a point to the other line */ + if ( fabs ( t1_dot_t2 ) >= 1.0 ) + return sgdDistSquaredToLineVec3 ( line, seg.a ) ; + + /* Get the parametric coordinates of the closest points on the two lines. The first line + * is parameterized by r = r1 + t1 u while the second is parameterized by r = r2 + t2 v. + * The square of the distance between them is [ ( r1 + t1 u ) - ( r2 + t2 v ) ] dot + * [ ( r1 + t1 u ) - ( r2 + t2 v ) ]. Differentiating this dot product with respect to + * u and v and setting the derivatives to zero gives a matrix equation: + * [ 1 -(t1 dot t2) ] [ u ] = [ ( r1 - r2 ) dot t1 ] + * [ -(t1 dot t2) 1 ] [ v ] [ -( r1 - r2 ) dot t2 ] + * We invert the matrix to get the equations below. + */ + sgdVec3 r1_minus_r2 ; + sgdSubVec3 ( r1_minus_r2, line.point_on_line, line2.point_on_line ) ; + + /* t1_t2_t2_minus_t1 = ( t1 dot t2 ) t2 - t1 + * t2_minus_t1_t2_t1 = t2 - ( t1 dot t2 ) t1 + */ + sgdVec3 t1_t2_t2_minus_t1, t2_minus_t1_t2_t1 ; + sgdAddScaledVec3 ( t1_t2_t2_minus_t1, line.direction_vector, line2.direction_vector, -t1_dot_t2 ) ; + sgdNegateVec3 ( t1_t2_t2_minus_t1 ) ; + sgdAddScaledVec3 ( t2_minus_t1_t2_t1, line2.direction_vector, line.direction_vector, -t1_dot_t2 ) ; + + sgdFloat u = sgdScalarProductVec3 ( r1_minus_r2, t1_t2_t2_minus_t1 ) / ( 1.0f - t1_dot_t2 * t1_dot_t2 ) ; + sgdFloat v = sgdScalarProductVec3 ( r1_minus_r2, t2_minus_t1_t2_t1 ) / ( 1.0f - t1_dot_t2 * t1_dot_t2 ) ; + + /* Since line 2 is a line segment, we limit "v" to between 0 and the distance between the points. */ + sgdFloat length = sgdDistanceVec3 ( seg.a, seg.b ) ; + if ( v < 0.0 ) v = 0.0 ; + if ( v > length ) v = length ; + + sgdVec3 point1, point2 ; + sgdAddScaledVec3 ( point1, line.point_on_line, line.direction_vector, u ) ; + sgdAddScaledVec3 ( point2, line2.point_on_line, line2.direction_vector, v ) ; + return sgdDistanceSquaredVec3 ( point1, point2 ) ; +} + + + +void sgdReflectInPlaneVec3 ( sgdVec3 dst, const sgdVec3 src, const sgdVec4 plane ) +{ + SGDfloat src_dot_norm = sgdScalarProductVec3 ( src, plane ) ; + + sgdVec3 tmp ; + + sgdScaleVec3 ( tmp, plane, SGD_TWO * src_dot_norm ) ; + sgdSubVec3 ( dst, src, tmp ) ; +} + + + +int sgdClassifyMat4 ( const sgdMat4 m ) +{ + const SGDfloat epsilon = 1e-6 ; + + int flags = 0 ; + + + SGDfloat sx, sy, sz ; + + if ( m[0][1] == SGD_ZERO && m[0][2] == SGD_ZERO && + m[1][0] == SGD_ZERO && m[1][2] == SGD_ZERO && + m[2][0] == SGD_ZERO && m[2][1] == SGD_ZERO ) + { + + int n = ( m[0][0] < 0 ) + ( m[1][1] < 0 ) + ( m[2][2] < 0 ) ; + + if ( n > 1 ) + flags |= SG_ROTATION ; + + if ( n % 2 != 0 ) + flags |= SG_MIRROR ; + + sx = m[0][0] * m[0][0] ; + sy = m[1][1] * m[1][1] ; + sz = m[2][2] * m[2][2] ; + + } + else + { + + flags |= SG_ROTATION ; + + if ( sgdAbs ( sgdScalarProductVec3 ( m[1], m[2] ) ) > epsilon || + sgdAbs ( sgdScalarProductVec3 ( m[2], m[0] ) ) > epsilon || + sgdAbs ( sgdScalarProductVec3 ( m[0], m[1] ) ) > epsilon ) + { + flags |= SG_NONORTHO ; + } + + sgdVec3 temp ; + sgdVectorProductVec3 ( temp, m[0], m[1] ) ; + SGDfloat det = sgdScalarProductVec3 ( temp, m[2] ) ; + + if ( det < 0 ) + flags |= SG_MIRROR ; + + sx = sgdScalarProductVec3 ( m[0], m[0] ) ; + sy = sgdScalarProductVec3 ( m[1], m[1] ) ; + sz = sgdScalarProductVec3 ( m[2], m[2] ) ; + + } + + + if ( sgdAbs ( sx - sy ) > epsilon || + sgdAbs ( sx - sz ) > epsilon ) + { + flags |= SG_NONORTHO ; + flags |= SG_GENERAL_SCALE ; // also set general scale bit, though it may be deleted in the future + } + else + { + if ( sgdAbs ( sx - SGD_ONE ) > epsilon ) + flags |= SG_SCALE ; + } + + + if ( m[3][0] != SGD_ZERO || m[3][1] != SGD_ZERO || m[3][2] != SGD_ZERO ) + { + flags |= SG_TRANSLATION ; + } + + + if ( m[0][3] != SGD_ZERO || m[1][3] != SGD_ZERO || m[2][3] != SGD_ZERO || + m[3][3] != SGD_ONE ) + { + flags |= SG_PROJECTION ; + } + + + return flags ; +} + + +SGDfloat sgdTriangleSolver_ASAtoArea ( SGDfloat angA, SGDfloat lenB, SGDfloat angC ) +{ + /* Get the third angle */ + + SGDfloat angB = SGD_180 - (angA + angC) ; + + /* Use Sine Rule to get length of a second side - then use SAStoArea. */ + + SGDfloat sinB = sgdSin ( angB ) ; + + if ( sinB == SGD_ZERO ) + return SGD_ZERO ; + + SGDfloat lenA = lenB * sgdSin(angA) / sinB ; + + return sgdTriangleSolver_SAStoArea ( lenA, angC, lenB ) ; +} + + +SGDfloat sgdTriangleSolver_SAStoArea ( SGDfloat lenA, SGDfloat angB, SGDfloat lenC ) +{ + return SGD_HALF * lenC * lenA * sgdSin ( angB ) ; +} + + +SGDfloat sgdTriangleSolver_SSStoArea ( SGDfloat lenA, SGDfloat lenB, SGDfloat lenC ) +{ + /* Heron's formula */ + + SGDfloat s = ( lenA + lenB + lenC ) / SGD_TWO ; + SGDfloat q = s * (s-lenA) * (s-lenB) * (s-lenC) ; + + /* Ikky illegal triangles generate zero areas. */ + + return ( q <= SGD_ZERO ) ? SGD_ZERO : sgdSqrt ( q ) ; +} + + +SGDfloat sgdTriangleSolver_ASStoArea ( SGDfloat angB, SGDfloat lenA, SGDfloat lenB, + int angA_is_obtuse ) +{ + SGDfloat lenC ; + + sgdTriangleSolver_ASStoSAA ( angB, lenA, lenB, angA_is_obtuse, + &lenC, NULL, NULL ) ; + + return sgdTriangleSolver_SAStoArea ( lenA, angB, lenC ) ; +} + +SGDfloat sgdTriangleSolver_SAAtoArea ( SGDfloat lenA, SGDfloat angB, SGDfloat angA ) +{ + SGDfloat lenC ; + + sgdTriangleSolver_SAAtoASS ( lenA, angB, angA, NULL, NULL, &lenC ) ; + + return sgdTriangleSolver_SAStoArea ( lenA, angB, lenC ) ; +} + +void sgdTriangleSolver_SSStoAAA ( SGDfloat lenA, SGDfloat lenB, SGDfloat lenC, + SGDfloat *angA, SGDfloat *angB, SGDfloat *angC ) +{ + SGDfloat aa, bb, cc ; + + int flag = ( lenA == SGD_ZERO ) | + (( lenB == SGD_ZERO )<<1) | + (( lenC == SGD_ZERO )<<2) ; + + /* Ikky zero-sized triangles generate zero/90 angles appropriately. */ + /* Ikky triangles with all lengths zero generate 60 degree angles. */ + /* Ikky impossible triangles generate all zero angles. */ + + switch ( flag ) + { + case 0 : /* no zero-lengthed sides */ + /* Cosine law */ + aa = sgdACos (( lenB*lenB + lenC*lenC - lenA*lenA )/(SGD_TWO*lenB*lenC)) ; + bb = sgdACos (( lenA*lenA + lenC*lenC - lenB*lenB )/(SGD_TWO*lenA*lenC)) ; + cc = sgdACos (( lenA*lenA + lenB*lenB - lenC*lenC )/(SGD_TWO*lenA*lenB)) ; + break ; + + case 1 : /* lenA is zero */ + aa = SGD_ZERO ; + bb = cc = SGD_90 ; + break ; + + case 2 : /* lenB is zero */ + bb = SGD_ZERO ; + aa = cc = SGD_90 ; + break ; + + case 4 : /* lenC is zero */ + cc = SGD_ZERO ; + aa = bb = SGD_90 ; + break ; + + case 3 : /* Two lengths are zero and the third isn't?!? */ + case 5 : + case 6 : + aa = bb = cc = SGD_ZERO ; + break ; + + default : /* All three sides are zero length */ + aa = bb = cc = SGD_60 ; + break ; + } + + if ( angA ) *angA = aa ; + if ( angB ) *angB = bb ; + if ( angC ) *angC = cc ; +} + +void sgdTriangleSolver_SAStoASA ( SGDfloat lenA, SGDfloat angB, SGDfloat lenC, + SGDfloat *angA, SGDfloat *lenB, SGDfloat *angC ) +{ + /* Get third side using Cosine Rule */ + + SGDfloat s = lenC * lenC + + lenA * lenA - SGD_TWO * lenC * lenA * sgdCos( angB ) ; + + SGDfloat lb = ( s <= SGD_ZERO ) ? SGD_ZERO : (SGDfloat) sqrt ( s ) ; + + if ( lenB ) *lenB = lb ; + + sgdTriangleSolver_SSStoAAA ( lenA, lb, lenC, angA, NULL, angC ) ; +} + + +void sgdTriangleSolver_ASAtoSAS ( SGDfloat angA, SGDfloat lenB, SGDfloat angC, + SGDfloat *lenA, SGDfloat *angB, SGDfloat *lenC ) +{ + /* Find the missing angle */ + + SGDfloat bb = SGD_180 - (angA + angC) ; + + if ( angB ) *angB = bb ; + + /* Use Sine Rule */ + + SGDfloat sinB = sgdSin ( bb ) ; + + if ( sinB == SGD_ZERO ) + { + if ( lenA ) *lenA = lenB / SGD_TWO ; /* One valid interpretation */ + if ( lenC ) *lenC = lenB / SGD_TWO ; + } + else + { + if ( lenA ) *lenA = lenB * sgdSin(angA) / sinB ; + if ( lenC ) *lenC = lenB * sgdSin(angC) / sinB ; + } +} + + +void sgdTriangleSolver_ASStoSAA ( SGDfloat angB, SGDfloat lenA, SGDfloat lenB, + int angA_is_obtuse, + SGDfloat *lenC, SGDfloat *angA, SGDfloat *angC ) +{ + /* Sine law */ + + SGDfloat aa = (lenB == SGD_ZERO ) ? SGD_ZERO : sgdASin (lenA * sgdSin(angB)/lenB) ; + + if ( angA_is_obtuse ) + aa = SGD_180 - aa ; + + if ( angA ) *angA = aa ; + + /* Find the missing angle */ + + SGDfloat cc = SGD_180 - (aa + angB) ; + + if ( angC ) *angC = cc ; + + /* Use SAStoASA to get the last length */ + + sgdTriangleSolver_SAStoASA ( lenA, cc, lenB, NULL, lenC, NULL ) ; +} + + +void sgdTriangleSolver_SAAtoASS ( SGDfloat lenA, SGDfloat angB, SGDfloat angA, + SGDfloat *angC, SGDfloat *lenB, SGDfloat *lenC ) +{ + /* Find the missing angle */ + + SGDfloat cc = SGD_180 - (angB + angA) ; + + if ( angC ) *angC = cc ; + + sgdTriangleSolver_ASAtoSAS ( cc, lenA, angB, lenC, NULL, lenB ) ; +} + + + diff --git a/src/sg/sgdIsect.cxx b/src/sg/sgdIsect.cxx new file mode 100755 index 0000000..d6339c4 --- /dev/null +++ b/src/sg/sgdIsect.cxx @@ -0,0 +1,354 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: sgdIsect.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "sg.h" + +/* + Determine the origin and unit direction vector of a line + formed by the intersection of two planes. + Returned point will lie on axis that was used to + determine intersection. + Norman Vine - nhv@yahoo.com +*/ + +int sgdIsectPlanePlane ( sgdVec3 point, sgdVec3 dir, + sgdVec4 plane1, sgdVec4 plane2 ) +{ + /* Determine intersection line direction. */ + + sgdVectorProductVec3 ( dir, plane1, plane2 ) ; + + SGDfloat dnorm = sgdLengthVec3 ( dir ) ; + + /* If planes are parallel then fail */ + + if ( dnorm < DBL_EPSILON ) + { + sgdZeroVec3 ( point ) ; + sgdZeroVec3 ( dir ) ; + return FALSE ; + } + + /* Determine intersection point with the best suited coordinate plane. */ + + SGDfloat abs ; + SGDfloat maxabs = sgdAbs(dir[0]); + int index = 0; + + if ((abs = sgdAbs(dir[1])) > maxabs) { maxabs = abs ; index = 1; } + if ((abs = sgdAbs(dir[2])) > maxabs) { maxabs = abs ; index = 2; } + + switch ( index ) + { + case 0: + sgdSetVec3( point, + SGD_ZERO, + (plane1[2] * plane2[3] - plane2[2] * plane1[3]) / dir[0], + (plane2[1] * plane1[3] - plane1[1] * plane2[3]) / dir[0] ); + break; + case 1: + sgdSetVec3( point, + (plane2[2] * plane1[3] - plane1[2] * plane2[3]) / dir[1], + SGD_ZERO, + (plane1[0] * plane2[3] - plane2[0] * plane1[3]) / dir[1] ); + break; + case 2: + sgdSetVec3( point, + (plane1[1] * plane2[3] - plane2[1] * plane1[3]) / dir[2], + (plane2[0] * plane1[3] - plane1[0] * plane2[3]) / dir[2], + SGD_ZERO ); + break; + default: return FALSE ; /* Impossible */ + } + + /* Normalize the direction */ + + sgdScaleVec3( dir, SGD_ONE / dnorm ); + return TRUE; +} + + + +/* + Find the intersection of an infinite line with a plane + (the line being defined by a point and direction). + + Norman Vine -- nhv@yahoo.com (with hacks by Steve) +*/ + +int sgdIsectInfLinePlane( sgdVec3 dst, sgdVec3 l_org, sgdVec3 l_vec, sgdVec4 plane ) +{ + SGDfloat tmp = sgdScalarProductVec3 ( l_vec, plane ) ; + + /* Is line parallel to plane? */ + + if ( sgdAbs ( tmp ) < DBL_EPSILON ) + return FALSE ; + + sgdScaleVec3 ( dst, l_vec, -( sgdScalarProductVec3 ( l_org, plane ) + + plane[3] ) / tmp ) ; + sgdAddVec3 ( dst, l_org ) ; + + return TRUE ; +} + + + +/* + Given the origin and direction vector for two lines + find their intersection - or the point closest to + both lines if they don't intersect. + + Norman Vine -- nhv@yahoo.com +*/ + +int sgdIsectInfLineInfLine( sgdVec3 dst, + sgdVec3 l1_org, sgdVec3 l1_vec, + sgdVec3 l2_org, sgdVec3 l2_vec ) +{ + sgdVec3 vec_l1, vec_l2 ; + + sgdNormalizeVec3 ( vec_l1, l1_vec ) ; + sgdNormalizeVec3 ( vec_l2, l2_vec ) ; + + /* Connecting line 'C' is perpendicular to both */ + + sgdVec3 perp ; + sgdVectorProductVec3 ( perp, vec_l1, vec_l2 ) ; + + /* check for near-parallel lines */ + + SGDfloat dist = sgdScalarProductVec3 ( perp, perp ) ; + + if ( dist < DBL_EPSILON ) + { + /* degenerate: lines parallel - any point will do. */ + + sgdCopyVec3 ( dst, l2_org ) ; + return TRUE ; + } + + /* + Form a plane containing the line A and C, + and another containing B and C + */ + + sgdScaleVec3 ( perp, SGD_ONE / sgdSqrt( dist ) ) ; + + sgdVec4 pa ; + sgdVec4 pb ; + sgdVec3 tmp ; + + sgdVectorProductVec3 ( tmp, perp, vec_l1 ) ; + sgdNormalizeVec3 ( tmp ); + sgdMakePlane ( pa, tmp, l1_org ) ; + + sgdVectorProductVec3 ( tmp, perp, vec_l2 ) ; + sgdNormalizeVec3 ( tmp ); + sgdMakePlane ( pb, tmp, l2_org ) ; + + sgdVec3 tmp_org, tmp_vec ; + + if ( ! sgdIsectPlanePlane( tmp_org, tmp_vec, pa, pb ) ) + { + /* This *shouldn't* ever happen because we already + tested for parallel lines - but with roundoff + errors, it *might* in borderline cases so... + */ + + sgdCopyVec3 ( dst, l2_org ) ; + return FALSE ; + } + + if ( ! sgdIsectInfLinePlane ( dst, l2_org, vec_l2, pa ) ) + { + sgdCopyVec3 ( dst, l2_org ) ; + return FALSE ; + } + + return TRUE ; +} + + +/* + Intersect the line segment from v1->v2 with the 'plane'. + 'dst' is the intersection point and the return + result is in the range 0..1 if the intersection lies + between v1 and v2, >1 if beyond v2 and <0 if before v1. + FLT_MAX is returned if the vector does not intersect + the plane. + + Steve Baker +*/ + +SGDfloat sgdIsectLinesegPlane ( sgdVec3 dst, sgdVec3 v1, sgdVec3 v2, sgdVec4 plane ) +{ + sgdVec3 delta ; + + sgdSubVec3 ( delta, v2, v1 ) ; + + SGDfloat p = sgdScalarProductVec3 ( plane, delta ) ; + + if ( p == SGD_ZERO ) + { + dst [ 0 ] = dst [ 1 ] = dst [ 2 ] = FLT_MAX ; + return FLT_MAX ; + } + + float s = (float) (- ( sgdScalarProductVec3 ( plane, v1 ) + plane[3] ) / p) ; + + sgdScaleVec3 ( dst, delta, s ) ; + sgdAddVec3 ( dst, dst, v1 ) ; + + return s ; +} + + + +// return the sign of a value +static inline const int SGD_SIGN(const SGDfloat x) { + return x < 0 ? -1 : 1; +} + +// return the minimum of two values +static inline SGDfloat SGD_MIN2(const SGDfloat a, const SGDfloat b) { + return a < b ? a : b; +} + +// return the minimum of three values +static inline SGDfloat SGD_MIN3( const SGDfloat a, const SGDfloat b, const SGDfloat c) { + return (a < b ? SGD_MIN2 (a, c) : SGD_MIN2 (b, c)); +} + +// return the minimum and maximum of three values +static void SGD_MIN_MAX3 ( SGDfloat &min, SGDfloat &max, + const SGDfloat &a, const SGDfloat &b, + const SGDfloat &c) +{ + if( a > b ) { + if( a > c ) { + max = a; + min = SGD_MIN2( b, c ); + } else { + max = c; + min = SGD_MIN2( a, b ); + } + } else { + if( b > c ) { + max = b; + min = SGD_MIN2( a, c ); + } else { + max = c; + min = SGD_MIN2( a, b ); + } + } +} + +/* + * Given a point and a triangle lying on the same plane + * check to see if the point is inside the triangle + */ +bool sgdPointInTriangle( sgdVec3 point, sgdVec3 tri[3] ) +{ + sgdVec3 dif; + + int i; + for( i=0; i<3; i++ ) { + SGDfloat min, max; + SGD_MIN_MAX3 ( min, max, tri[0][i], tri[1][i], tri[2][i] ); + // punt if outside bouding cube + if( (point[i] < min) || (point[i] > max) ) + return false; + dif[i] = max - min; + } + + // drop the smallest dimension so we only have to work in 2d. + SGDfloat min_dim = SGD_MIN3 (dif[0], dif[1], dif[2]); + SGDfloat x1, y1, x2, y2, x3, y3, rx, ry; + if ( fabs(min_dim-dif[0]) <= DBL_EPSILON ) { + // x is the smallest dimension + x1 = point[1]; + y1 = point[2]; + x2 = tri[0][1]; + y2 = tri[0][2]; + x3 = tri[1][1]; + y3 = tri[1][2]; + rx = tri[2][1]; + ry = tri[2][2]; + } else if ( fabs(min_dim-dif[1]) <= DBL_EPSILON ) { + // y is the smallest dimension + x1 = point[0]; + y1 = point[2]; + x2 = tri[0][0]; + y2 = tri[0][2]; + x3 = tri[1][0]; + y3 = tri[1][2]; + rx = tri[2][0]; + ry = tri[2][2]; + } else if ( fabs(min_dim-dif[2]) <= DBL_EPSILON ) { + // z is the smallest dimension + x1 = point[0]; + y1 = point[1]; + x2 = tri[0][0]; + y2 = tri[0][1]; + x3 = tri[1][0]; + y3 = tri[1][1]; + rx = tri[2][0]; + ry = tri[2][1]; + } else { + // all dimensions are really small so lets call it close + // enough and return a successful match + return true; + } + + // check if intersection point is on the same side of p1 <-> p2 as p3 + SGDfloat tmp = (y2 - y3) / (x2 - x3); + int side1 = SGD_SIGN (tmp * (rx - x3) + y3 - ry); + int side2 = SGD_SIGN (tmp * (x1 - x3) + y3 - y1); + if ( side1 != side2 ) { + // printf("failed side 1 check\n"); + return false; + } + + // check if intersection point is on correct side of p2 <-> p3 as p1 + tmp = (y3 - ry) / (x3 - rx); + side1 = SGD_SIGN (tmp * (x2 - rx) + ry - y2); + side2 = SGD_SIGN (tmp * (x1 - rx) + ry - y1); + if ( side1 != side2 ) { + // printf("failed side 2 check\n"); + return false; + } + + // check if intersection point is on correct side of p1 <-> p3 as p2 + tmp = (y2 - ry) / (x2 - rx); + side1 = SGD_SIGN (tmp * (x3 - rx) + ry - y3); + side2 = SGD_SIGN (tmp * (x1 - rx) + ry - y1); + if ( side1 != side2 ) { + // printf("failed side 3 check\n"); + return false; + } + + return true; +} + diff --git a/src/sl/Makefile.am b/src/sl/Makefile.am new file mode 100644 index 0000000..97b3fb3 --- /dev/null +++ b/src/sl/Makefile.am @@ -0,0 +1,20 @@ +if BUILD_SL + +lib_LIBRARIES = libplibsl.a libplibsm.a + +include_HEADERS = sl.h slPortability.h sm.h + +libplibsl_a_SOURCES = \ + slDSP.cxx slSample.cxx slEnvelope.cxx \ + slPlayer.cxx slMODPlayer.cxx slSamplePlayer.cxx \ + slScheduler.cxx slMODdacio.cxx slMODfile.cxx \ + slMODinst.cxx slMODnote.cxx slMODPrivate.h slMODfile.h + +libplibsm_a_SOURCES = slPortability.h smMixer.cxx + +INCLUDES = -I$(top_srcdir)/src/util + +endif + +EXTRA_DIST = sl.dsp + diff --git a/src/sl/sl.dsp b/src/sl/sl.dsp new file mode 100644 index 0000000..9748bfd --- /dev/null +++ b/src/sl/sl.dsp @@ -0,0 +1,162 @@ +# Microsoft Developer Studio Project File - Name="sl" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=sl - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "sl.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "sl.mak" CFG="sl - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "sl - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "sl - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "sl - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /Zi /O2 /I "..\util" /I ".." /D "NDEBUG" /D "_LIB" /D "NEEDNAMESPACESTD" /D "HAVE_CONFIG_H" /D "HAVE_WINDOWS_H" /D "WIN32" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy release\*.lib ..\..\*.* copy sl.h ..\..\sl.h copy slPortability.h ..\..\slPortability.h copy sm.h ..\..\sm.h +# End Special Build Tool + +!ELSEIF "$(CFG)" == "sl - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I "..\util" /I ".." /D "_DEBUG" /D "_LIB" /D "NEEDNAMESPACESTD" /D "HAVE_CONFIG_H" /D "HAVE_WINDOWS_H" /D "WIN32" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\sl_d.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy debug\*.lib ..\..\*.* copy sl.h ..\..\sl.h copy slPortability.h ..\..\slPortability.h copy sm.h ..\..\sm.h +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "sl - Win32 Release" +# Name "sl - Win32 Debug" +# Begin Source File + +SOURCE=.\sl.h +# End Source File +# Begin Source File + +SOURCE=.\slDSP.cxx +# End Source File +# Begin Source File + +SOURCE=.\slEnvelope.cxx +# End Source File +# Begin Source File + +SOURCE=.\slMODdacio.cxx +# End Source File +# Begin Source File + +SOURCE=.\slMODfile.cxx +# End Source File +# Begin Source File + +SOURCE=.\slMODfile.h +# End Source File +# Begin Source File + +SOURCE=.\slMODinst.cxx +# End Source File +# Begin Source File + +SOURCE=.\slMODnote.cxx +# End Source File +# Begin Source File + +SOURCE=.\slMODPlayer.cxx +# End Source File +# Begin Source File + +SOURCE=.\slMODPrivate.h +# End Source File +# Begin Source File + +SOURCE=.\slPlayer.cxx +# End Source File +# Begin Source File + +SOURCE=.\slPortability.h +# End Source File +# Begin Source File + +SOURCE=.\slSample.cxx +# End Source File +# Begin Source File + +SOURCE=.\slSamplePlayer.cxx +# End Source File +# Begin Source File + +SOURCE=.\slScheduler.cxx +# End Source File +# Begin Source File + +SOURCE=.\sm.h +# End Source File +# Begin Source File + +SOURCE=.\smMixer.cxx +# End Source File +# End Target +# End Project diff --git a/src/sl/sl.h b/src/sl/sl.h new file mode 100644 index 0000000..65325eb --- /dev/null +++ b/src/sl/sl.h @@ -0,0 +1,731 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: sl.h 1924 2004-04-06 13:32:26Z sjbaker $ +*/ + + +#ifndef __SL_H__ +#define __SL_H__ 1 + +#include +#include "slPortability.h" + +#ifdef SL_USING_OSS_AUDIO +#define SLDSP_DEFAULT_DEVICE "/dev/dsp" +#elif defined(UL_WIN32) +#define SLDSP_DEFAULT_DEVICE "dsp" +#elif defined(UL_BSD) +#define SLDSP_DEFAULT_DEVICE "/dev/audio" +#elif defined(UL_IRIX) +#define SLDSP_DEFAULT_DEVICE "dsp" // dummy ... +#elif defined(UL_AIX) +#define SLDSP_DEFAULT_DEVICE "dsp" // dummy ... +#elif defined(UL_SOLARIS) +#define SLDSP_DEFAULT_DEVICE "/dev/audio" +#elif defined(UL_HPUX) +#define SLDSP_DEFAULT_DEVICE "/dev/audio" +#elif defined(UL_MACINTOSH) || defined(UL_MAC_OSX) +#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 slPlayer ; +class slSamplePlayer ; +class slEnvelope ; +class slScheduler ; +class slDSP ; + +extern const char *__slPendingError ; + +class slDSP +{ +private: + + int stereo ; + int rate ; + int bps ; + + int error ; + int fd ; + +#if defined(SL_USING_OSS_AUDIO) + audio_buf_info buff_info ; +#elif defined(UL_BSD) + audio_info_t ainfo; // ioctl structure + audio_offset_t audio_offset; // offset in audiostream + long counter; // counter-written packets +#elif defined(UL_SOLARIS) + audio_info_t ainfo; + long counter; +#elif defined(UL_IRIX) + ALconfig config; // configuration stuff + ALport port; // .. we are here +#elif defined(UL_MACINTOSH) || defined(UL_MAC_OSX) + +// Size of the data chunks written with write(). +// This should be a multiple of 1024. +#define BUFFER_SIZE 8192 + +// Size of storage space for sound data. +// This should be evenly divisible by BUFFER_SIZE. +#define VIRTUAL_BUFFER_SIZE 131072 + + SndChannelPtr sndChannel ; // sound channel we are using + ExtSoundHeader extSndHeader ; // sound header for bufferCmd + SndCommand currentCmd ; // command we are sending to chnl + OSErr osErr ; + + char *buf ; // buffer containing sound data + char *rpos ; // read position for buffer + char *wpos ; // write position for buffer + char *ptr ; // ptr to data from write() + + float bytesPerSample ; // conversions + float bytesPerSecond ; + float secondsPerPacket ; + + float secLeft ; // seconds left in buffer + float secUsed ; // seconds used in buffer + UnsignedWide lastTime ; // used for timing in secondsUsed() + UnsignedWide currTime ; + +#endif + + +#if !defined(UL_WIN32) && !defined(UL_MACINTOSH) && !defined(UL_MAC_OSX) + 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(UL_WIN32) + +#define BUFFER_COUNT (3*8) +#define BUFFER_SIZE (1024*1) + + friend void CALLBACK waveOutProc( HWAVEOUT hwo, UINT uMsg, + DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 ); + HWAVEOUT hWaveOut; // device handle + WAVEFORMATEX Format; // open needs this + MMTIME mmt; // timing + WAVEHDR *wavehdr[ BUFFER_COUNT ]; // for round robin .. + int curr_header; // index of actual wavehdr + int counter; // counter-written packets + DWORD written; // counter-written samples + +#endif + + void open ( const 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 ( const 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 ) ; } + + /* This was a typo - but people use it */ + int not_working() const { return error ; } + + int notWorking () const { return error ; } + + int getBps () const { return bps ; } + int getRate () const { return rate ; } + int getStereo() const { 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 ( const Uchar *buff, int leng ) + { + init () ; + setBuffer ( buff, leng ) ; + } + + slSample ( const char *fname, const class slDSP *dsp = NULL ) + { + if ( dsp != NULL && dsp->notWorking () ) + 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." ; + + delete [] buffer ; + } + + void ref () { ref_count++ ; } + void unRef () { ref_count-- ; } + + int getPlayCount () const { return ref_count ; } + + char *getComment () const { return comment ; } + + void setComment ( const char *nc ) + { + delete [] comment ; + comment = ulStrDup ( nc ) ; + } + + Uchar *getBuffer () const { return buffer ; } + int getLength () const { return length ; } + + void autoMatch ( const slDSP *dsp ) ; + + void setBuffer ( const 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 () const { return rate ; } + int getBps () const { return bps ; } + int getStereo () const { return stereo ; } + + float getDuration () const { return (float) getLength() / + (float) ( (getStereo()?2.0f:1.0f)* + (getBps()/8.0f)*getRate() ) ; } + + int loadFile ( const char *fname ) ; + + int loadRawFile ( const char *fname ) ; + int loadAUFile ( const char *fname ) ; + int loadWavFile ( const char *fname ) ; + + void changeRate ( int r ) ; + void changeBps ( int b ) ; + void changeStereo ( int s ) ; + void changeToUnsigned () ; + + void adjustVolume ( float vol ) ; + + void print ( FILE *fd ) const + { + 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 +{ +protected: + + float *time ; + float *value ; + int nsteps ; + int ref_count ; + float previous_value ; + unsigned char prev_pitchenv ; + slReplayMode replay_mode ; + + int getStepDelta ( float *_time, float *delta ) const ; + +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 ) ; + prev_pitchenv = 0x80 ; + previous_value = 0.0f ; + 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 ] ; + prev_pitchenv = 0x80 ; + previous_value = 0.0f ; + + 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 () const { return ref_count ; } + + void applyToLPFilter ( unsigned char *dst, + unsigned char *src, + int nframes, int start ) ; + + void setStep ( int n, float _time, float _value ) + { + if ( n >= 0 && n < nsteps ) + { + time [ n ] = _time ; + value [ n ] = _value ; + } + } + + float getStepValue ( int s ) const { return value [ s ] ; } + float getStepTime ( int s ) const { return time [ s ] ; } + + int getNumSteps () const { return nsteps ; } + + float getValue ( float _time ) const ; + + void applyToPitch ( Uchar *dst, slPlayer *src, int nframes, int start, int next_env ) ; + void applyToInvPitch ( Uchar *dst, slPlayer *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 32 +#define SL_MAX_CALLBACKS (SL_MAX_SAMPLES * 2) +#define SL_MAX_ENVELOPES 32 +#define SL_MAX_MIXERINPUTS 16 + +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 slPlayer +{ +protected: + + 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 ; + + virtual void low_read ( int nframes, Uchar *dest ) = 0 ; + virtual void skip ( int nframes ) = 0 ; + +public: + + slPlayer ( slReplayMode rp_mode = SL_SAMPLE_ONE_SHOT, + int pri = 0, slPreemptMode pr_mode = SL_SAMPLE_DELAY, + int _magic = 0, slCallBack cb = NULL ) + { + magic = _magic ; + callback = cb ; + + for ( int i = 0 ; i < SL_MAX_ENVELOPES ; i++ ) + { + env [ i ] = NULL ; + env_type [ i ] = SL_NULL_ENVELOPE ; + } + + status = SL_SAMPLE_WAITING ; + replay_mode = rp_mode ; + preempt_mode = pr_mode ; + priority = pri ; + } + + virtual ~slPlayer () ; + + slPreemptMode getPreemptMode () const { return preempt_mode ; } + + int getPriority () const + { + return ( isRunning() && + preempt_mode == SL_SAMPLE_CONTINUE ) ? (SL_MAX_PRIORITY+1) : + priority ; + } + + void addEnvelope ( int i, slEnvelope *_env, slEnvelopeType _type ) ; + + virtual void pause () + { + if ( status != SL_SAMPLE_DONE ) + status = SL_SAMPLE_PAUSED ; + } + + virtual void resume () + { + if ( status == SL_SAMPLE_PAUSED ) + status = SL_SAMPLE_RUNNING ; + } + + virtual void reset () + { + status = SL_SAMPLE_WAITING ; + } + + virtual void start () + { + status = SL_SAMPLE_RUNNING ; + } + + virtual void stop () + { + status = SL_SAMPLE_DONE ; + } + + int getMagic () const { return magic ; } + int isWaiting () const { return status == SL_SAMPLE_WAITING ; } + int isPaused () const { return status == SL_SAMPLE_PAUSED ; } + int isRunning () const { return status == SL_SAMPLE_RUNNING ; } + int isDone () const { return status == SL_SAMPLE_DONE ; } + + virtual int preempt ( int delay ) ; + + virtual slSample *getSample () const = 0 ; + + void read ( int nframes, Uchar *dest, int next_env = 0 ) ; +} ; + + +class MODfile ; + +class slMODPlayer : public slPlayer +{ + MODfile *mf ; + + void low_read ( int nframes, Uchar *dest ) ; + void init ( const char *fname ) ; +public: + + slMODPlayer ( const char *fname, slReplayMode rp_mode = SL_SAMPLE_ONE_SHOT, + int pri = 0, slPreemptMode pr_mode = SL_SAMPLE_DELAY, + int _magic = 0, slCallBack cb = NULL ) : + slPlayer ( rp_mode, pri, pr_mode, _magic, cb ) + { + init ( fname ) ; + reset () ; + } + + ~slMODPlayer () ; + + int preempt ( int delay ) ; + virtual slSample *getSample () const { return NULL ; } + + void skip ( int nframes ) ; +} ; + + +class slSamplePlayer : public slPlayer +{ + int lengthRemaining ; /* Sample frames remaining until repeat */ + Uchar *bufferPos ; /* Sample frame to replay next */ + slSample *sample ; + + 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 ) : + slPlayer ( rp_mode, pri, pr_mode, _magic, cb ) + { + sample = s ; + + if ( sample ) sample -> ref () ; + + reset () ; + } + + ~slSamplePlayer () ; + + int preempt ( int delay ) ; + + void reset () + { + slPlayer::reset () ; + + lengthRemaining = sample->getLength () ; + bufferPos = sample->getBuffer () ; + } + + void start () + { + slPlayer::start () ; + + lengthRemaining = sample->getLength () ; + bufferPos = sample->getBuffer () ; + } + + void stop () + { + slPlayer::stop () ; + + lengthRemaining = 0 ; + bufferPos = NULL ; + } + + slSample *getSample () const { return sample ; } + + void skip ( int nframes ) ; +} ; + + +class slScheduler : public slDSP +{ + slPendingCallBack pending_callback [ SL_MAX_CALLBACKS ] ; + int num_pending_callbacks ; + + float safety_margin ; + + int mixer_buffer_size, mixer_gain ; + float seconds_per_buffer; + + Uchar *mixer_buffer ; + Uchar *mixer_inputs [ SL_MAX_MIXERINPUTS + 1 ] ; + + Uchar *mixer ; + int amount_left ; + + slPlayer *player [ SL_MAX_SAMPLES ] ; + slPlayer *music ; + + void init () ; + + 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 ( const char *device, + int _rate = SL_DEFAULT_SAMPLING_RATE ) : slDSP ( device, _rate, SL_FALSE, 8 ) { init () ; } + ~slScheduler () ; + + static slScheduler *getCurrent () { return current ; } + + int getTimeNow () const { return now ; } + float getElapsedTime ( int then ) const { return (float)(now-then)/(float)getRate() ; } + + void setMaxConcurrent ( int mc ); + int getMaxConcurrent () const ; + + void flushCallBacks () ; + void addCallBack ( slCallBack c, slSample *s, slEvent e, int m ) ; + + void update () { realUpdate ( SL_FALSE ) ; } + void dumpUpdate () { realUpdate ( SL_TRUE ) ; } + + void resumeSample ( slSample *s = NULL, int magic = 0 ) ; + void resumeMusic ( int magic = 0 ) ; + void pauseSample ( slSample *s = NULL, int magic = 0 ) ; + void pauseMusic ( int magic = 0 ) ; + void stopSample ( slSample *s = NULL, int magic = 0 ) ; + void stopMusic ( int magic = 0 ) ; + + void addSampleEnvelope ( slSample *s = NULL, int magic = 0, + int slot = 1, slEnvelope *e = NULL, + slEnvelopeType t = SL_VOLUME_ENVELOPE ) ; + void addMusicEnvelope ( int magic = 0, + int slot = 1, slEnvelope *e = NULL, + slEnvelopeType t = SL_VOLUME_ENVELOPE ) ; + int loopSample ( slSample *s, int pri = 0, + slPreemptMode mode = SL_SAMPLE_MUTE, + int magic = 0, slCallBack cb = NULL ) ; + int loopMusic ( const char *fname, int pri = 0, + slPreemptMode mode = SL_SAMPLE_MUTE, + int magic = 0, slCallBack cb = NULL ) ; + int playSample ( slSample *s, int pri = 1, + slPreemptMode mode = SL_SAMPLE_ABORT, + int magic = 0, slCallBack cb = NULL ) ; + int playMusic ( const char *fname, int pri = 1, + slPreemptMode mode = SL_SAMPLE_ABORT, + int magic = 0, slCallBack cb = NULL ) ; + + void setSafetyMargin ( float seconds ) { safety_margin = seconds ; } +} ; + +#endif + diff --git a/src/sl/slDSP.cxx b/src/sl/slDSP.cxx new file mode 100644 index 0000000..933e20b --- /dev/null +++ b/src/sl/slDSP.cxx @@ -0,0 +1,1085 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: slDSP.cxx 1775 2003-07-04 14:33:03Z puggles $ +*/ + + +#include "sl.h" +#include + +static int init_bytes ; + +#ifdef SL_USING_OSS_AUDIO + +/* ------------------------------------------------------------ */ +/* OSSAUDIO - Linux, FreeBSD, etc */ +/* ------------------------------------------------------------ */ + +void slDSP::open ( const char *device, int _rate, int _stereo, int _bps ) +{ + fd = ::open ( device, O_WRONLY | O_NONBLOCK ) ; + + 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) */ + +errno = 0 ; + 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 ) ; + +if ( errno != 0 ) perror ( "slDSP: ioctl" ) ; + + 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 || (int)length <= 0 ) + return ; + + size_t nwritten = ::write ( fd, (const char *) buffer, length ) ; + + if ( (int)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 UL_WIN32 + +/* ------------------------------------------------------------ */ +/* win32 */ +/* ------------------------------------------------------------ */ + +static void wperror(MMRESULT num) +{ + char buffer[0xff]; // yes, this is hardcoded :-) + + waveOutGetErrorText( num, buffer, sizeof(buffer)-1); + + ulSetError ( UL_WARNING, "SlDSP: %s (%d)", buffer, num ); +} + + + +void CALLBACK waveOutProc( HWAVEOUT hwo, UINT uMsg, + DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 ) +{ + slDSP *pDsp = (slDSP *)dwInstance; + switch( uMsg ) + { + case WOM_CLOSE: + break; + + case WOM_OPEN: + break; + + case WOM_DONE: + pDsp->counter--; + break; + } +} + + +void slDSP::open ( const char *device, int _rate, int _stereo, int _bps ) +{ + MMRESULT result; + int i; + + hWaveOut = NULL; + curr_header = 0; + counter = 0; + written = 0; + for ( i = 0; i < BUFFER_COUNT; i++ ) wavehdr[i] = NULL; + + 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, 0, + 0L, WAVE_FORMAT_QUERY ); + + if ( result != MMSYSERR_NOERROR ) + { + wperror( result); + + error = SL_TRUE ; + stereo = SL_FALSE ; + bps = _bps ; + rate = _rate ; + init_bytes = 0 ; + + return; + } + +#if 0 + ulSetError ( UL_DEBUG, "Request: stereo=%d bps=%d rate=%d", + _stereo, _bps, _rate ); + ulSetError ( UL_DEBUG, "Result: channels=%d bps=%d rate=%d", + Format.nChannels, Format.wBitsPerSample, + Format.nSamplesPerSec ); +#endif + + // Now the hwaveouthandle "should" be valid + + if ( ( result = waveOutOpen( & hWaveOut, WAVE_MAPPER, + (WAVEFORMATEX *)& Format, (DWORD)waveOutProc, + (DWORD)this, 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 = BUFFER_SIZE; + + for ( i = 0; i < BUFFER_COUNT; i++ ) + { + Uchar *p = new Uchar[sizeof(WAVEHDR) + BUFFER_SIZE]; + + wavehdr[i] = (WAVEHDR*) p; + wavehdr[i]->lpData = (LPSTR) p + sizeof(WAVEHDR); + wavehdr[i]->dwBufferLength = (DWORD) BUFFER_SIZE; + wavehdr[i]->dwBytesRecorded = 0L; + wavehdr[i]->dwUser = 0; + wavehdr[i]->dwFlags = 0; + wavehdr[i]->dwLoops = 0; + wavehdr[i]->lpNext = 0; + wavehdr[i]->reserved = 0; + + result = waveOutPrepareHeader( hWaveOut, + wavehdr[i], sizeof(WAVEHDR) ); + + if ( result != MMSYSERR_NOERROR ) + { + wperror ( result ); + error = SL_TRUE; + return; + } + } + } +} + + +void slDSP::close () +{ + if ( hWaveOut != NULL ) + { + waveOutReset( hWaveOut ); + + for ( int i = 0; i < BUFFER_COUNT; i++ ) + { + waveOutUnprepareHeader( hWaveOut, wavehdr[i], sizeof(WAVEHDR) ); + + delete[] (Uchar*) wavehdr[i]; + } + + waveOutClose( hWaveOut ); + hWaveOut = NULL; + } +} + +int slDSP::getDriverBufferSize () +{ + if ( error ) + return 0 ; + + /* hmm ?! */ + + return BUFFER_SIZE; +} + +void slDSP::getBufferInfo () +{ + return ; +} + + +void slDSP::write ( void *buffer, size_t length ) +{ + MMRESULT result; + + if ( error || (int)length <= 0 ) + return ; + +#if 0 + ulSetError ( UL_DEBUG, "written=%ld counter=%d curr_header=%d", + written, counter, curr_header ); +#endif + + memcpy(wavehdr[curr_header]->lpData, buffer, length); + wavehdr[curr_header]->dwBufferLength = (DWORD) length; + + result = waveOutWrite(hWaveOut, wavehdr[curr_header], sizeof(WAVEHDR)); + + if ( result != MMSYSERR_NOERROR ) + { + wperror ( result ); + error = SL_TRUE; + } + + counter ++; + written += (DWORD) BUFFER_SIZE; + + curr_header = ( curr_header + 1 ) % BUFFER_COUNT; +} + + +float slDSP::secondsRemaining () +{ + if ( error ) + return 0.0f ; + + return 10.0f ; +} + + +float slDSP::secondsUsed () +{ + DWORD 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; + + if ( counter < BUFFER_COUNT ) + samples_used = written - mmt.u.cb ; + else + samples_used = BUFFER_COUNT * BUFFER_SIZE ; + + if ( stereo ) samples_used /= 2 ; + if ( bps == 16 ) samples_used /= 2 ; + + samp_time = (float) samples_used / (float) rate ; + +#if 0 + ulSetError ( UL_DEBUG, "%0.2f written packets=%ld stereo=%d bps=%d rate=%d", + samp_time, counter, stereo, bps, rate ); +#endif + + return samp_time; +} + + +void slDSP::sync () +{ +} + +void slDSP::stop () +{ + if ( error ) + return ; + + waveOutReset( hWaveOut ); + written = 0 ; +} + +/* ------------------------------------------------------------ */ +/* NetBSD/OpenBSD 2.3 this should be very close to SUN Audio */ +/* ------------------------------------------------------------ */ + +#elif (defined(UL_BSD) && !defined(__FreeBSD__)) || defined(UL_SOLARIS) +void slDSP::open ( const char *device, int _rate, int _stereo, int _bps ) +{ + + counter = 0; + + fd = ::open ( device, O_RDWR | O_NONBLOCK ) ; + + 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; + } + +#ifdef UL_SOLARIS + AUDIO_INITINFO(&ainfo); +#endif + + ainfo.play.sample_rate = _rate; + ainfo.play.precision = _bps; +#ifdef UL_SOLARIS + if ( ainfo.play.port == AUDIO_SPEAKER ) + ainfo.play.channels = 1; + else + ainfo.play.channels = _stereo ? 2 : 1; + + ainfo.play.encoding = AUDIO_ENCODING_ALAW; + +// if ( _bps < 16 ) +// { +// ainfo.play.encoding = AUDIO_ENCODING_LINEAR8; +// } +// else +// { +// ainfo.play.encoding = AUDIO_ENCODING_LINEAR; +// } +#else + ainfo.play.encoding = AUDIO_ENCODING_ULINEAR; +#endif + + 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 + +#ifdef UL_SOLARIS + return ainfo.play.buffer_size; +#else + return 1024 * 8; +#endif + +} + +void slDSP::getBufferInfo () +{ + if ( error ) + return ; + + if( ::ioctl( fd, AUDIO_GETINFO, &ainfo) < 0) + { + perror ( "slDSP: getBufferInfo" ) ; + error = SL_TRUE ; + return ; + } + +#ifndef UL_SOLARIS + if( ::ioctl( fd, AUDIO_GETOOFFS, &audio_offset ) < 0) + { + perror ( "slDSP: getBufferInfo" ) ; + error = SL_TRUE ; + return ; + } +#endif +} + + +void slDSP::write ( void *buffer, size_t length ) +{ + if ( error || (int)length <= 0 ) + return ; + + size_t nwritten = ::write ( fd, (const char *) buffer, length ) ; + + if ( (int)nwritten < 0 ) + perror ( "slDSP: write" ) ; + else if ( nwritten != length ) + perror ( "slDSP: short write" ) ; + + counter ++; /* hmmm */ +} + + +float slDSP::secondsRemaining () +{ + return 10.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; + +#ifdef UL_SOLARIS + samples_used = ( counter * init_bytes ) - ainfo.play.samples; +#else + samples_used = ( counter * init_bytes ) - audio_offset.samples; +#endif + + if ( stereo ) samples_used /= 2 ; + if ( bps == 16 ) samples_used /= 2 ; + + return (float) samples_used / (float) rate ; +} + + +void slDSP::sync () +{ +#ifdef UL_SOLARIS + if ( !error) ::ioctl ( fd, I_FLUSH, FLUSHRW ) ; +#else + if ( !error) ::ioctl ( fd, AUDIO_FLUSH , 0 ) ; +#endif +} + +void slDSP::stop () +{ + // nothing found yet +} + +/* ------------------------------------------------------------ */ +/* SGI IRIX audio */ +/* ------------------------------------------------------------ */ + +#elif defined(UL_IRIX) + +void slDSP::open ( const 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 * 4 ; + + config = ALnewconfig(); + + ALsetchannels ( config, _stereo ? AL_STEREO : AL_MONO ); + ALsetwidth ( config, _bps == 8 ? AL_SAMPLE_8 : AL_SAMPLE_16 ); + ALsetqueuesize( config, init_bytes * 2 ); + + 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 ) / 2 ; +} + +void slDSP::getBufferInfo () +{ + if ( error ) + return ; +} + + +void slDSP::write ( void *buffer, size_t length ) +{ + char *buf = (char *)buffer; + + if ( error || (int)length <= 0 ) + return ; + + for ( int i = 0; i < (int)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) ; + + return (float) samples_remain / (float) rate ; +} + + +float slDSP::secondsUsed () +{ + int samples_used; + + if ( error ) + return 0.0f ; + + samples_used = ALgetfilled(port) * 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 + + +#if defined(UL_MACINTOSH) || defined(UL_MAC_OSX) + + +// Print out debugging info when secondsUsed is called, +// track useful information, and used extended error checking. +//#define SL_MAC_DEBUG + +pascal void sndCallbackProc ( SndChannelPtr theChan, SndCommand *theCmd ); + void doError ( OSErr theError ); + +int bytesUsed; +bool playing; + +//SCStatus sndChanStatus; + +#ifdef SL_MAC_DEBUG + int underWrites; + int queued; + int writes; + int callBacks; + float roughTime; + int qLength; + int qHead; + int qTail; +#endif + +void doError( OSErr theError ) { + + const char* msg = 0 ; + + switch( theError ) { + + case 0: + msg = "No Error." ; + break; + case notEnoughHardwareErr: + msg = "Insufficient hardware available." ; + break; + case badChannel: + msg = "Channel is corrupt or unusable." ; + break; + case badFormat: + msg = "Resource is corrupt or unusable." ; + break; + case queueFull: + msg = "No room in the queue." ; + break; + case channelBusy: + msg = "Channel is busy." ; + break; + case siInvalidCompression: + msg = "Invalid compression type." ; + break; + case notEnoughBufferSpace: + msg = "Insufficient memory available." ; + break; + case buffersTooSmall: + msg = "Buffer is too small." ; + break; + case paramErr: + msg = "Invalid parameter specified." ; + break; + } + + if ( msg != 0 ) + ulSetError ( UL_WARNING, "OSErr : %s", msg ) ; + else + ulSetError ( UL_WARNING, "OSErr : Unknown Error : %d.", theError ); +} + +pascal void sndCallbackProc ( SndChannelPtr chan, SndCommand *cmd ) +{ + + //SndChannelStatus is a BIG waste of cpu time, but I don't know + //any other way to remedy this. I will leave it out for now. + //SndChannelStatus(chan, sizeof(SCStatus), &sndChanStatus); + //playing = sndChanStatus.scChannelBusy ? true : false; + + bytesUsed -= BUFFER_SIZE ; + +#ifdef SL_MAC_DEBUG + callBacks++; + queued--; + qLength = chan->qLength; + qTail = chan->qTail; + qHead = chan->qHead; +#endif +} + +void slDSP::open ( const char *device, int _rate, int _stereo, int _bps ) +{ + + // Check for valid ranges on inputs + if ( _rate > 65535 ) + { + ulSetError ( UL_WARNING, + "slDsp : Sample rate out of bounds! Setting to 44100hz."); + _rate = 44100; + } + + error = SL_FALSE; + stereo = _stereo; + rate = _rate; + bps = _bps; + osErr = noErr; + + bytesPerSample = (stereo ? 2:1) * (bps/8); + bytesPerSecond = bytesPerSample * rate; + secondsPerPacket = BUFFER_SIZE / bytesPerSecond; + secUsed = 0; + secLeft = 0; + playing = false; + + long initOptions = 0; // Channel init options + if ( stereo ) + initOptions += initStereo; + else + initOptions += initMono; + + // Extra init options available + //initOptions += initNoInterp; // No linear interpolation + //initOptions += initNoDrop; // No drop-sample conversion + //initOptions += initChanLeft; // Left stereo channel + //initOptions += initChanRight; // Right stereo channel + + // Define a call-back routine - invoked via callBackCmd + SndCallBackUPP callBackRoutine = NewSndCallBackUPP ( sndCallbackProc ); + + // Allocate a sound channel + sndChannel = new SndChannel; + sndChannel -> userInfo = 0; + sndChannel -> qLength = 128; // Queue as many as 128 packets at a time; + osErr = SndNewChannel( &sndChannel, sampledSynth, + initOptions, callBackRoutine ); + + if ( osErr != noErr ) + { + SndDisposeChannel( sndChannel, true ); + ulSetError ( UL_WARNING, + "slDSP::open() Problem creating sound channel" ); + doError (osErr); + error = SL_TRUE; + } + + // Format sound header structure + extSndHeader.numChannels = stereo ? 2 : 1; + extSndHeader.sampleRate = rate << 16; + extSndHeader.encode = extSH; + extSndHeader.sampleSize = bps; + + // Allocate the sound buffer + buf = new char [VIRTUAL_BUFFER_SIZE]; + if ( !buf ) + { + ulSetError ( UL_WARNING, + "slDSP::open() Not enough memory to allocate sound buffer." ); + SndDisposeChannel( sndChannel, true ); + error = SL_TRUE; + } + rpos = buf; + wpos = buf; +} + +void slDSP::close () +{ + SndDisposeChannel( sndChannel, true ); + delete [] buf; +} + +void slDSP::write ( void *buffer, size_t length ) +{ + + if ( error || (int)length <= 0 || length > VIRTUAL_BUFFER_SIZE ) + return; + + // Make sure data will fit into available space + if ( length >= VIRTUAL_BUFFER_SIZE - (rpos - buf) ) + wpos = buf; + + // Copy sound data into buffer + rpos = wpos; + ptr = (char*)buffer; + for ( int i = 0; i < length; i++ ) + *wpos++ = *ptr++; + + // Format the sound header + extSndHeader.samplePtr = rpos; + extSndHeader.numFrames = length / bytesPerSample; + + // Format the buffer command + currentCmd.cmd = bufferCmd; + currentCmd.param2 = (long)&extSndHeader; + + // Do the sound command + osErr = SndDoCommand (sndChannel, ¤tCmd, false); + +#ifdef SL_MAC_DEBUG + if ( osErr != noErr ) + { + ulSetError ( UL_WARNING, "Error slDsp::write - bufferCmd() : " ); + doError( osErr ); + error = SL_TRUE; + } +#endif + + // Issue a callBack command when the bufferCmd has finished + currentCmd.cmd = callBackCmd; + osErr = SndDoCommand (sndChannel, ¤tCmd, false); + +#ifdef SL_MAC_DEBUG + if ( osErr != noErr ) + { + ulSetError ( UL_WARNING, "Error slDsp::write - callBackCmd() : " ); + doError( osErr ); + error = SL_TRUE; + } +#endif + + // Add on time for this packet + secUsed += length / bytesPerSecond; + + // Add on bytes used + bytesUsed += BUFFER_SIZE; + + // Reset the timing for the buffer + if (!playing) + { + Microseconds(&lastTime); + playing = true; + } + +#ifdef SL_MAC_DEBUG + queued++; + writes++; +#endif + +} + +void slDSP::sync () +{ + if ( error ) return; + + // flushCmd will remove all queued commands in a channel, + // and the command in progress is not affected. + // This is not exactly what sync() is supposed to do! + currentCmd.cmd = flushCmd; + osErr = SndDoImmediate ( sndChannel, ¤tCmd ); + +#ifdef SL_MAC_DEBUG + if ( osErr != noErr ) + { + ulSetError ( UL_WARNING, "Error slDsp::sync() : " ); + doError( osErr ); + error = SL_TRUE; + } +#endif +} + +void slDSP::stop () +{ + if ( error ) return; + + currentCmd.cmd = quietCmd; + osErr = SndDoImmediate ( sndChannel, ¤tCmd ); + playing = false; + +#ifdef SL_MAC_DEBUG + if ( osErr != noErr ) + { + ulSetError ( UL_WARNING, "Error slDsp::stop() : " ); + doError( osErr ); + error = SL_TRUE; + } +#endif +} + +void slDSP::getBufferInfo () +{ + return; +} + +int slDSP::getDriverBufferSize () +{ + return BUFFER_SIZE; +} + +float slDSP::secondsRemaining () +{ + if ( error ) + return 0.0f; + + // sl doesn't use this, so I didn't write it! + return 10.0f; +} + +float slDSP::secondsUsed () +{ + if ( error || secUsed <= 0 ) + return secUsed = 0; + + Microseconds( &currTime ); + secUsed -= (currTime.lo - lastTime.lo) / 1000000.0; + Microseconds( &lastTime ); + + // This fixes inaccuracy with Microseconds + if ( secUsed > bytesUsed / bytesPerSecond + secondsPerPacket ) + secUsed -= secondsPerPacket; + +#ifdef SL_MAC_DEBUG + if (queued == 0) + underWrites++; + roughTime = bytesUsed / bytesPerSecond; + ulSetError ( UL_DEBUG, "%d\t%d\t%f\t%d\t%d\t%f\t%d\t%d\t%d\t%d", + bytesUsed, queued, secUsed, callBacks, + writes, roughTime, underWrites, qLength, qHead, qTail ); +#endif + + return secUsed; +} + +#endif + + diff --git a/src/sl/slEnvelope.cxx b/src/sl/slEnvelope.cxx new file mode 100644 index 0000000..b905603 --- /dev/null +++ b/src/sl/slEnvelope.cxx @@ -0,0 +1,219 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: slEnvelope.cxx 1926 2004-04-06 14:26:03Z sjbaker $ +*/ + + +#include "sl.h" + +float slEnvelope::getValue ( float _time ) const +{ + float delta ; + int step = getStepDelta ( &_time, &delta ) ; + + return delta * (_time - time[step]) + value[step] ; +} + + + +int slEnvelope::getStepDelta ( float *_time, float *delta ) const +{ + float tt ; + + if ( replay_mode == SL_SAMPLE_LOOP ) + { + tt = (float) 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, slPlayer *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 = prev_pitchenv; + + 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 ] ; + prev_pitchenv = last; + } + } +} + + +void slEnvelope::applyToInvPitch ( Uchar *dst, slPlayer *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.0f / _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::applyToLPFilter ( 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] ; + register float p_v = previous_value; + delta /= (float) slScheduler::getCurrent() -> getRate () ; + + while ( nframes-- ) + { + + register float c_v = (float) ((int)*(src++) - 0x80); + register float f=_value; + p_v = p_v*(1.0f - f)+ f*c_v; + register int res = (int)(p_v) + 0x80 ; + _value += delta ; + + *(dst++) = ( res > 255 ) ? 255 : ( res < 0 ) ? 0 : res ; + } + previous_value = p_v; +} + + +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.0f - _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/src/sl/slMODPlayer.cxx b/src/sl/slMODPlayer.cxx new file mode 100644 index 0000000..5e8ebc2 --- /dev/null +++ b/src/sl/slMODPlayer.cxx @@ -0,0 +1,101 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: slMODPlayer.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "sl.h" +#include "slMODPrivate.h" +#include "slMODfile.h" + +int slMODPlayer::preempt ( int delay ) +{ + return slPlayer::preempt ( delay ) ; +} + +void slMODPlayer::init ( const char *fname ) +{ + mf = new MODfile ( fname, slScheduler::getCurrent()->getRate (), SL_FALSE ) ; +} + +slMODPlayer::~slMODPlayer () +{ + delete mf ; +} + +void slMODPlayer::skip ( int /* nframes */ ) +{ +} + + +void slMODPlayer::low_read ( int nframes, Uchar *dst ) +{ + if ( isWaiting() ) start () ; + + int need_bytes = nframes ; + int all_done = 0 ; + + while ( need_bytes > 0 && !all_done ) + { + int new_bytes = dacioGetLen () ; + + /* Compute some more audio */ + + while ( new_bytes == 0 && !all_done ) + { + all_done = ! mf -> update () ; + new_bytes = dacioGetLen () ; + } + + /* How much did we get? */ + + if ( new_bytes > need_bytes ) /* oops! Too much */ + { + memcpy ( dst, dacioGetOutBuffer (), need_bytes ) ; + dacioSubtract ( need_bytes ) ; + dst += need_bytes ; + need_bytes = 0 ; + } + else + { + memcpy ( dst, dacioGetOutBuffer (), new_bytes ) ; + dacioEmpty () ; + dst += new_bytes ; + need_bytes -= new_bytes ; + } + } + + /* Pad with silence if not enough data */ + + if ( need_bytes > 0 ) + memset ( dst, 128, need_bytes ) ; + + if ( all_done ) + { + if ( replay_mode == SL_SAMPLE_ONE_SHOT ) + stop () ; + else + start () ; + } +} + + + diff --git a/src/sl/slMODPrivate.h b/src/sl/slMODPrivate.h new file mode 100644 index 0000000..143df19 --- /dev/null +++ b/src/sl/slMODPrivate.h @@ -0,0 +1,159 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: slMODPrivate.h 1732 2002-11-30 00:41:50Z sjbaker $ +*/ + + +#include "ul.h" +#include +#include +#include +#include +#include + +#ifdef UL_MSVC +#include +#include +#else +#include +#endif + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +int *dacioGetBuffer () ; +void dacioInit( int speed, int stereo ); +void dacioFlush(void); +void dacioIncomingBufLen(int len); +void dacioGlobalVol(int v); +void dacioOut(void); +void dacioEmpty () ; +void dacioSubtract ( int n ) ; +int dacioGetLen () ; +unsigned char *dacioGetOutBuffer () ; + +#define MAX_OUTRATE 65536 +#define MIN_TEMPO 32 +#define DEF_OUTRATE 44100 +#define DEF_TEMPO 125 +#define DEF_SPEED 6 + + +struct InstHirevInfo +{ + unsigned int w; /* omega: 65536 = 2*pi */ + unsigned int wAcc; /* w accumlator */ + unsigned char *ptr; + unsigned char *end; + unsigned char *loopBeg; + int x_or; + int volL; + int volR; + int fadeout; + int lastL; + int lastR; +} ; + +void _MOD_instHirevInit(void); +void _MOD_instHirevSetFrameLen(int l); +void _MOD_instHirevEraseBuf(void); +void _MOD_instHirevFlushBuf(void); +void _MOD_instHirevLoop(InstHirevInfo *ihip); + +/* sample info */ + +struct SampleInfo +{ + unsigned char *beg; + unsigned char *end; + int x_or; /* 0x80 (or 0x8000?) */ + unsigned char *loopBeg; + int c4spd; + int vol; + int mag; /* magnification */ +} ; + +void _MOD_instOutRate(unsigned int _or); +void _MOD_instSelectCh(int ch); +void _MOD_instClearPFW(void); +void _MOD_instDoPerFrameWorks(int frame); +void _MOD_instLoop(void); +void _MOD_instInit(void); +void _MOD_instNote(int n, int delay); +void _MOD_instMono(int n); +void _MOD_instVol(int v, int delay); +void _MOD_instTuning(int c4spd); +void _MOD_instSample(SampleInfo *sip, int delay); +void _MOD_instVolSlide(void); +void _MOD_instSetVolSlideParams(int d, int mul, int div, int nthFrame, int fine); +void _MOD_instSetVolSlideFast(int onOff); +void _MOD_instPeriodSlideUp(void); +void _MOD_instPeriodSlideDown(void); +void _MOD_instSetPeriodSlideParams(int speed, int fine); +void _MOD_instSetPeriodAmigaLimit(int onOff); +void _MOD_instPortamento(void); +void _MOD_instSetPortamentoTo(int to); +void _MOD_instSetPortamentoSpeed(int speed); +void _MOD_instSetPortamentoDefaultVol(void); +void _MOD_instSetPortamentoGlissando(int onOff); +void _MOD_instArpeggio(void); +void _MOD_instSetArpeggioParams(int plus1, int plus2); +void _MOD_instRetrig(void); +void _MOD_instSetRetrigParam(int nthFrame); +void _MOD_instSampleOffset(int offset); +void _MOD_instVibrato(void); +void _MOD_instSetVibratoParams(int d, int depth); +void _MOD_instSetVibratoWave(int type, int noRetrig); +void _MOD_instTremolo(void); +void _MOD_instSetTremoloParams(int d, int depth); +void _MOD_instSetTremoloWave(int type, int noRetrig); +void _MOD_instNoteCut(int frame); +void _MOD_instTremor(void); +void _MOD_instSetTremorParams(int onTime, int offTime); +void _MOD_instNoteOff(int delay); +int _MOD_instIsNoteOff(void); +void _MOD_instPanPosition(int pos); +void _MOD_instEmptyCmd(void); + + +struct Note +{ + unsigned char note ; + unsigned char ins ; + unsigned char vol ; + unsigned char cmd ; + unsigned char info ; +} ; + +void _MOD_playNoteSetMono(int m); +void _MOD_playNoteSetMasterVol(int mv); +void _MOD_playNoteSetGlobalVol(int gv); +void _MOD_playNoteSetSample(SampleInfo *sip); +void _MOD_playNoteInit(void); +void _MOD_playNoteSetOutRate(int _or); +void _MOD_playNoteSetTempo(int n); +void _MOD_playNoteSetSpeed(int n); +void _MOD_playNoteSetNote(int ch, Note *np); +void _MOD_playNoteSetPatRepeat(int n); +void _MOD_playNote(void); + diff --git a/src/sl/slMODdacio.cxx b/src/sl/slMODdacio.cxx new file mode 100644 index 0000000..6361e9b --- /dev/null +++ b/src/sl/slMODdacio.cxx @@ -0,0 +1,118 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: slMODdacio.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + +#include "slMODPrivate.h" + +static int stereo ; +static int glob_vol = 0x40 * 0x40 ; /* default g.v = m.v = 64 */ + +#define VOL_MAX (64*64*128) /* vol max * g.v max * m.v max */ +#define VOL_MAX_LOG ( 6 + 6 + 7 ) /* 1 << VOL_MAX_LOG == VOL_MAX */ +#define LEV_MAX (128*VOL_MAX) +#define MAX_FRAMELEN (MAX_OUTRATE * 60 / (MIN_TEMPO * 24)) + +static inline unsigned char to8bit ( int x ) +{ + int tmpvar = ( x * glob_vol + LEV_MAX ) >> VOL_MAX_LOG ; + + return (tmpvar & ~255) ? ~tmpvar >> 16 : tmpvar ; +} + + +struct ucharBuffer +{ + unsigned char data [ MAX_FRAMELEN * 4 ] ; + unsigned char *ptr ; + unsigned char *end ; + int size ; + +public: + + ucharBuffer () + { + ptr = data ; + size = sizeof ( data ) ; + end = data + size ; + } + + void copyFrom ( int *inbufp, int n ) + { + if ( n == 0 ) + return ; + + if ( stereo ) + for (; n > 0; n--) + { + *ptr++ = to8bit ( *inbufp++ ) ; /* L */ + *ptr++ = to8bit ( *inbufp++ ) ; /* R */ + } + else + for (; n > 0; n--) + { + *ptr++ = to8bit ( *inbufp ) ; + inbufp += 2 ; + } + } + + int getLen () { return ptr - data ; } + + unsigned char *getBuffer () { return data ; } + + void empty () + { + ptr = data ; + } + + void subtract ( int n ) + { + /* Delete n bytes from the front of the buffer */ + + /* WARNING - NOT memcpy OK? */ + memmove ( data, data+n, ptr - data - n ) ; + ptr -= n ; + } +} ; + + +struct intBuffer +{ + int data [ MAX_FRAMELEN * 2 ] ; + int len ; +} ; + + +static intBuffer inbuf ; +static ucharBuffer outbuf ; + +int *dacioGetBuffer () +{ + return inbuf.data ; +} + +void dacioIncomingBufLen ( int len ) { inbuf.len = len ; } +void dacioGlobalVol(int v) { glob_vol = v; } +int dacioGetLen () { return outbuf.getLen () ; } +void dacioOut ( void ) { outbuf.copyFrom ( inbuf.data, inbuf.len ) ; } +void dacioEmpty () { outbuf.empty (); } +void dacioSubtract ( int n ) { outbuf.subtract(n) ; } +unsigned char *dacioGetOutBuffer () { return outbuf.getBuffer() ; } diff --git a/src/sl/slMODfile.cxx b/src/sl/slMODfile.cxx new file mode 100644 index 0000000..ce58444 --- /dev/null +++ b/src/sl/slMODfile.cxx @@ -0,0 +1,687 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: slMODfile.cxx 1770 2003-06-02 23:49:44Z puggles $ +*/ + + +#include "slMODPrivate.h" +#include "slMODfile.h" + +#define NOTE_MAX (12*5-1) /* 5 octave */ +#define shift(x,n) ((n)>= 0 ? (x) << (n) : (x) >> -(n)) /* x * 2**n */ + +#define u16LittleEndian(x) (((unsigned char *)(x))[0] + \ + ((unsigned char *)(x))[1]*(unsigned short)256) +#define u16BigEndian(x) (((unsigned char *)(x))[0]*(unsigned short)256 + \ + ((unsigned char *)(x))[1]) + +static const char *transTab = "JFEGHLKRXODB.C" ; +static const char *transTabE = "SFESSSSSSQ..SSSS" ; +static const char transTabEX[] = { 0,0xF,0xF,1,3,2,0xB,4,8,0,0,0,0xC,0xD,0xE,0xF } ; +static int oct[12] = { 1712, 1616, 1524, 1440, 1356, 1280, + 1208, 1140, 1076, 1016, 960, 907 } ; +static int freq[16] = { 8363, 8413, 8463, 8529, 8581, 8651, 8723, 8757, + 7895, 7941, 7985, 8046, 8107, 8169, 8232, 8280 } ; +static unsigned char emptySample ; + +class SlmInfo ; + +static SlmInfo *top = NULL ; + +class SlmInfo +{ + char *data ; + SlmInfo *next ; +public: + + SlmInfo ( unsigned int size ) + { + data = new char [ size ] ; + next = top ; + top = this ; + } + + ~SlmInfo () + { + if ( this == top ) + top = NULL ; + + delete [] data ; + delete next ; + } + + void *get () { return (void *) data ; } +} ; + + +/* Allocate song-life memory */ + +static void *memSong ( unsigned size ) +{ + SlmInfo *sip = new SlmInfo ( size ) ; + return sip -> get () ; +} + +/* free all song-life memory */ + +static void memSongFree(void) +{ + delete top ; +} + + +/* LPF fc=fs/4 impulse response * Hamming window (N=19) */ +static int h2[][8] = /* h(n) = */ +{ + /* n = */ + /*-7 -5 -3 -1 1 3 5 7*/ + { -4, 15, -42, 158, 158, -42, 15, -4} +}; +/* LPF fc=fs/6 impulse response * Hamming window (N=29) */ +static int h3[][8] = +{ + /*-10 -7 -4 -1 2 5 8 11*/ + { -5, 16, -44, 209, 101, -31, 12, -3}, + /*-11 -8 -5 -2 1 4 7 10*/ + { -3, 12, -31, 101, 209, -44, 16, -5} +}; +/* LPF fc=fs/8 impulse response * Hamming window (N=35) */ +static int h4[][8] = +{ + /*-13 -9 -5 -1 3 7 11 15*/ + { -4, 13, -38, 229, 72, -22, 7, -2}, + /*-14 -10 -6 -2 2 6 10 14*/ + { -3, 13, -40, 158, 158, -40, 13, -3}, + /*-15 -11 -7 -3 1 5 9 13*/ + { -2, 7, -22, 72, 229, -38, 13, -4} +}; +static int (*hn[])[8] = { h2, h3, h4 }; + +static SampleInfo sis; + +static void convolute ( int mag, char *dp ) +{ + unsigned char *sp0; + int i,j; + + for (sp0 = sis.beg; sp0 < sis.end; sp0++) { + *dp++ = *sp0 ^ sis.x_or; + for (i = 0; i < mag-1; i++,dp++) { + int *hp = hn[mag-2][i]; + unsigned char *sp = sp0 - 3; + int sum = 0; + for (j = 8; j > 0; j--,sp++,hp++) { + if (sp < sis.beg) continue; + if (sp >= sis.end) { + if (sis.loopBeg) sp = sis.loopBeg; + else break; + } + sum += *hp * (signed char)(*sp ^ sis.x_or); + } + sum /= 256; + if (sum > 127) sum = 127; + else if (sum < -128) sum = -128; + *dp = sum; + } + } +} + + +static void perSampleWork(SampleInfo *sip, unsigned int c4req) +{ + static SampleInfo sid; + unsigned char *dp0; + unsigned int len; + int mag; + + mag = c4req / sip->c4spd; + + if (!mag) return; /* no need to oversampling */ + mag++; + if (mag > 4) mag = 4; /* currently max = 4x */ + sis = *sip; + len = sis.end - sis.beg; + if (len <= 2) return; /* too short sample */ + dp0 = (unsigned char *) memSong(len * mag); + sid.beg = dp0 ; + sid.end = dp0 + len*mag ; + convolute(mag, (char *)dp0); + sid.loopBeg = sis.loopBeg? (sid.beg + (sis.loopBeg - sis.beg)*mag) : (unsigned char *)NULL; + sid.x_or = 0; + sid.c4spd = sis.c4spd; + sid.vol = sis.vol; + sid.mag = sis.mag * mag; + *sip = sid; +} + +static void oversample ( int insNum, SampleInfo *sip, unsigned int c4req ) +{ + for ( ; insNum > 0 ; insNum--, sip++ ) + perSampleWork ( sip, c4req ) ; +} + +enum MagicType +{ + MAGIC_S3M, MAGIC_MOD ,MAGIC_MODX, MAGIC_MOD15, MAGIC_MTM +} ; + +/* stricter 15-sample mod checking */ + +static int isMod15(unsigned char *p0, int size) +{ + int ordNum, patNum ; + unsigned char *p ; + + if ( size < 20+30*15+130+1024 ) + return 0 ; /* check min length */ + + ordNum = p0[20+30*15] ; + + if (!ordNum || ordNum >= 128) + return 0 ; + + patNum = 0 ; + p = p0 + 20+30*15+2 ; /* pattern table */ + + for ( int i = 0 ; i < ordNum ; i++, p++ ) + if (patNum < *p) + patNum = *p ; + + if (patNum >= 64) + return 0 ; + + if (size < 20 + 30*15 + 130 + 1024 + 1024*patNum ) + return 0 ; + + /* sample length is not checked here */ + return 1 ; +} + + +struct MagicInfo +{ + const char *str ; + int off ; + MagicType type ; +} ; + + +MagicInfo magicInfo[] = +{ + {"SCRM", 0x2c , MAGIC_S3M } , + {"M.K.", 0x438 /*20+30*31+130=1080*/, MAGIC_MOD}, + {"M!K!", 0x438, MAGIC_MOD }, + {"FLT4", 0x438, MAGIC_MOD }, /* FLT8's pattern is different */ + {"#CHN", 0x438, MAGIC_MODX }, + {"##CH", 0x438, MAGIC_MODX }, /* dope.mod */ + {"MTM", 0 , MAGIC_MTM }, /* check after above patterns fail. */ + /* (A mod songname can be "MTMxxx") */ + {0} +} ; + + +#define isnum(x) ('0' <= (x) && (x) <= '9') + +static int magic(unsigned char *p, int size, MagicType *mtp, int *numChp) +{ + MagicInfo *mip; + int ch; + + for (mip = magicInfo; mip->str != 0; mip++) + { + const char *ss ; + char *sp ; + + if (mip->off + 16 >= size) + continue ; /* Magicinfo.str must < 16 */ + + sp = (char *)p + mip->off; + ch = 0; + + int got_it = FALSE ; + + for (ss = mip->str; *ss != 0; ss++,sp++) + { + if (*ss == '#') + { + if (isnum(*sp)) + { + ch = ch*10 + *sp - '0'; + continue ; + } + else + { + got_it = TRUE ; + break ; + } + } + + if (*sp != *ss) + { + got_it = TRUE ; + break ; + } + } + + if ( ! got_it ) + { + *mtp = mip->type ; + *numChp = ch ; + return 0 ; + } + } + + if ( isMod15 ( p, size ) ) + { + *mtp = MAGIC_MOD15 ; + return 0 ; + } + else + return 1 ; +} + +void MODfile::makeNoteTable(void) +{ + note = (short *) memSong ( (NOTE_MAX+1) * sizeof(short) ) ; + + for ( int i = 0 ; i <= NOTE_MAX ; i++ ) + note[i] = shift ( oct[i%12], -i/12 ) ; +} + + +int MODfile::roundToNote ( int p ) +{ + if ( p == 0 ) return 0 ; + if ( p >= note [ 0 ] ) return 0 ; + if ( p <= note [NOTE_MAX] ) return NOTE_MAX ; + + /* 32: =2**n, and 32*2 > NOTE_MAX */ + + int i, s ; + + for ( i = 0, s = 32 ; s > 0 ; s /= 2 ) + if ( i + s < NOTE_MAX && note[i+s] > p ) + i += s ; /* i < NOTE_MAX !! */ + + if ( note[i] - p > p - note[i+1] ) + i++ ; /* choose nearest */ + + return i ; +} + + +void MODfile::modToS3m(ModNote *mp, Note *np) +{ + int X = (*mp)[3] / 16 ; + int Y = (*mp)[3] % 16 ; + int XY = (*mp)[3] ; + + int n = roundToNote ( (*mp)[0]%16 * 256 + (*mp)[1] ) ; + + np->note = (n!=0) ?(n/12+2)*16 + n%12 : 255 ; + np->ins = ((*mp)[0] & 0xf0) | (*mp)[2]/16; + np->vol = 255 ; + np->cmd = 255 ; + np->info = 0 ; + + switch ( (*mp)[2] % 16 ) + { + case 0x0: if (X || Y) { np->cmd = 'J' - '@'; np->info = XY; } break; + case 0x1: + case 0x2: if (XY) { np->cmd = transTab[(*mp)[2]%16] - '@'; np->info = (XY >= 0xE0)? 0xdf : XY; } break; + case 0xA: if (!XY) break; + case 0xC: np->vol = XY>64? 64 : XY; np->cmd = 255; np->info = 0; break; + case 0xE: + switch (X) + { + case 0xA: if (Y) { np->cmd = 'D' - '@'; np->info = Y*16 + 15; } break ; + case 0xB: if (Y) { np->cmd = 'D' - '@'; np->info = 0xf0 + Y; } break ; + default: { np->cmd = transTabE[X] - '@'; np->info = transTabEX[X]*16 + Y; } break ; + } + break; + case 0xF: if (XY) { np->cmd = XY <= 32? 'A' - '@' : 'T' - '@'; np->info = XY? XY : 1; } break; + default : { np->cmd = transTab[(*mp)[2]%16] - '@'; np->info = XY ; } break ; + } +} + + +void MODfile::play_one ( int ppat ) +{ + ModNote *np = & pat [ chNum * ( 64 * ppat + play_row ) ] ; + + for ( int ch = 0 ; ch < chNum ; ch++, np++ ) + { + Note note ; + + modToS3m ( np, ¬e ) ; + _MOD_playNoteSetNote ( ch, ¬e ) ; + + switch ( note.cmd ) + { + case 'A' - '@': /* Set speed */ + _MOD_playNoteSetSpeed ( note.info ) ; + break; + + case 'B' - '@': + play_nextOrd = note.info | 0x100 ; + play_row = 64 ; + break ; + + case 'C' - '@': + play_row0 = note.info / 16 * 10 + note.info % 16 ; + play_row = 64 ; + break ; + + case 'S' - '@': + switch ( note.info / 16 ) + { + case 0xB: /* pattern loop */ + if ( note.info % 16 ) /* Jump to mark */ + { + if ( play_loopCnt < note.info % 16 ) + { + play_row = play_loopBeg - 1 ; + play_loopCnt++ ; + } + else + play_loopCnt = 0 ; + } + else /* Set mark */ + play_loopBeg = play_row ; + + break; + + case 0xE: /* Pattern delay */ + _MOD_playNoteSetPatRepeat ( note.info % 16 ) ; + break; + } + break; + + case 'T' - '@': /* Set tempo */ + _MOD_playNoteSetTempo ( note.info ) ; + break ; + } + } + + _MOD_playNote () ; +} + + + +void MODfile::tellChSettings( void ) +{ + for ( int i = 0; i < chNum; i++ ) + { + _MOD_instSelectCh ( i ) ; + + switch ( i % 4 ) + { + case 0 : + case 3 : _MOD_instPanPosition ( 3 * 64/15 ) ; break ; /* left */ + default : _MOD_instPanPosition (12 * 64/15 ) ; break ; /* right */ + } + } +} + + + +void MODfile::makeSampleInfo( int smp15 ) +{ + ModSample *msp ; + SampleInfo *p ; + unsigned char *sp ; + + p = sip = (SampleInfo *) memSong ( sizeof(SampleInfo) * insNum ) ; + sp = smp0p ; + msp = &smpInfop[0] ; + + for ( int i = 0; i < insNum; i++, p++, msp++) + { + unsigned int lOff = 0 ; + + p->beg = sp ; + + unsigned int len = u16BigEndian(*msp+22) * 2 ; /*len*/ + unsigned int lLen = u16BigEndian(*msp+28) ; /*loopLen*/ + + if (lLen > 1) + { + lLen *= smp15? 1:2; + lOff = u16BigEndian(*msp+26)*(smp15? 1:2); /*loopOffset*/ + p->loopBeg = sp + lOff; /*sp+loopOffset*/ + p->end = p->loopBeg + lLen; + } + else + { + p->loopBeg = NULL; + p->end = sp + len; /*sp+len*/ + } + + p->x_or = 0 ; + p->mag = 1 ; + p->c4spd = freq[(*msp)[24]%16] ; + p->vol = (*msp)[25] > 64 ? 64 : (*msp)[25] ; + + if (p->end > fileEnd) + { + if (p->beg >= fileEnd || p->loopBeg >= fileEnd) + { + ulSetError ( UL_WARNING, + "short file (assigned an empty sample for #%d)", i+1 ) ; + p->beg = &emptySample ; + p->end = &emptySample+1 ; + p->loopBeg = NULL ; + p->vol = 0 ; + } + else + { + ulSetError ( UL_WARNING, + "short file (sample #%d truncated)", i+1 ) ; + p->end = fileEnd ; + } + } + + sp += u16BigEndian(*msp+22) * 2; /*sp+len*/ + } +} + + +void MODfile::parseMod(unsigned char *pp0, int smp15) +{ + int i,n; + unsigned char *p; + + p = pp0; + p0 = songName = p ; + p += 20; + + smpInfop = (ModSample *) p ; + + if ( smp15 ) { p += 15*sizeof(ModSample); insNum = 15; } + else { p += 31*sizeof(ModSample); insNum = 31; } + + ordNum = *p ; p++ ; + rstOrd = *p ; p++ ; + + ord = p; + + for ( i = 0, n = 0 ; i < 128 ; i++ ) + if ( n < p[i] ) + n = p[i] ; /* find max pat */ + + patNum = n + 1 ; + p += 128 + ( smp15 ? 0 : 4 ) ; + pat = (ModNote *) p ; + smp0p = pat [ chNum * 64 * patNum ] ; +} + + +int MODfile::update () +{ + if ( broken ) + return FALSE ; + + if ( firsttime ) + { + play_ord = play_ord0 = 0 ; + memset ( repCounter, 0, ordNum ) ; + firsttime = FALSE ; + } + + play_one ( ord [ play_ord ] ) ; + + if ( ++play_row >= 64 ) + { + play_loopBeg = 0 ; + play_loopCnt = 0 ; + play_nextOrd = 0 ; + + play_row = play_row0 ; + play_row0 = 0 ; + + play_ord = (play_nextOrd==0) ? (play_ord+1) : (play_nextOrd & 0xff) ; + + if ( play_ord >= ordNum ) + { + play_ord0 = rstOrd ; + play_ord = play_ord0 ; + + if ( rstOrd > ordNum ) + { + firsttime = TRUE ; + return FALSE ; + } + } + } + + return TRUE ; /* Carry on playing! */ +} + + + +unsigned char *MODfile::read_whole_file ( const char *fname, int *len ) +{ + struct stat statbuf ; + + int l = 0 ; + + int fd = open ( fname, O_RDONLY ) ; + + if ( fd < 0 ) + { + perror ( "open" ) ; + ulSetError ( UL_WARNING, + "SL: Couldn't open MOD file '%s' for reading", fname ) ; + return NULL ; + } + + if ( fstat ( fd, &statbuf ) < 0 ) + { + perror ( "fstat" ) ; + return NULL ; + } + + l = statbuf.st_size ; + + unsigned char *p = new unsigned char [ l ] ; + read ( fd, (char *)p, l ) ; + close ( fd ) ; + + if ( len != NULL ) + *len = l ; + + return p ; +} + + + +MODfile::MODfile ( const char *fname, int speed, int stereo ) +{ + p0 = NULL ; songName = NULL ; ord = NULL ; + smpInfop = NULL ; smp0p = NULL ; pat = NULL ; + note = NULL ; fileEnd = NULL ; sip = NULL ; + repCounter = NULL ; + + play_nextOrd = play_loopBeg = play_loopCnt = play_row0 = + play_row = play_ord0 = play_ord = ordNum = insNum = + patNum = chNum = rstOrd = firsttime = broken = 0 ; + + MagicType mt ; + + int len = 0 ; + + buffer = read_whole_file ( fname, &len ) ; + + if ( buffer == NULL ) + { + broken = TRUE ; + return ; + } + + if ( magic ( buffer, len, &mt, &chNum ) ) + { + broken = TRUE ; + ulSetError ( UL_WARNING, "Unknown format" ) ; + return ; + } + + if ( mt == MAGIC_MOD || mt == MAGIC_MOD15 ) + chNum = 4 ; + else + if ( mt != MAGIC_MODX ) + { + ulSetError ( UL_WARNING, "Unknown format" ) ; + broken = TRUE ; + return ; + } + + _MOD_playNoteInit () ; + _MOD_playNoteSetOutRate ( speed ) ; + _MOD_playNoteSetMono ( !stereo ) ; + + fileEnd = & buffer [ len ] ; + repCounter = (unsigned char *) memSong ( 128 ) ; + parseMod ( buffer, mt == MAGIC_MOD15 ) ; + _MOD_instSetPeriodAmigaLimit ( 1 ) ; + tellChSettings () ; + + makeSampleInfo ( mt == MAGIC_MOD15 ) ; + + oversample ( insNum, sip, (unsigned int) speed ) ; + + _MOD_playNoteSetSample ( sip ) ; + _MOD_playNoteSetTempo ( 125 ) ; + _MOD_playNoteSetSpeed ( 6 ) ; + _MOD_playNoteSetMasterVol ( 0x30 ) ; + _MOD_playNoteSetGlobalVol ( 0x40 ) ; + makeNoteTable () ; +} + + +MODfile::~MODfile () +{ + if ( broken ) + return ; + + delete [] buffer ; + memSongFree () ; +} + diff --git a/src/sl/slMODfile.h b/src/sl/slMODfile.h new file mode 100644 index 0000000..6463598 --- /dev/null +++ b/src/sl/slMODfile.h @@ -0,0 +1,78 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: slMODfile.h 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +typedef unsigned char ModSample [ 30 ] ; +typedef unsigned char ModNote [ 4 ] ; +struct SampleInfo ; +struct Note ; + +class MODfile +{ + unsigned char *buffer ; + unsigned char *p0 ; + unsigned char *songName ; + + int ordNum ; + int insNum ; + int patNum ; + int chNum ; + int rstOrd ; + + unsigned char *ord ; + ModSample *smpInfop ; + unsigned char *smp0p ; + ModNote *pat ; + short *note ; + unsigned char *fileEnd ; + unsigned char *repCounter; + SampleInfo *sip ; + + int firsttime ; + int broken ; + + int play_nextOrd ; + int play_loopBeg ; + int play_loopCnt ; + int play_row0 ; + int play_row ; + int play_ord0 ; + int play_ord ; + + void makeNoteTable ( void ) ; + void tellChSettings ( void ) ; + int roundToNote ( int p ) ; + void modToS3m ( ModNote *mp, Note *np ) ; + void makeSampleInfo ( int smp15 ) ; + void parseMod ( unsigned char *pp0, int smp15 ) ; + void play_one ( int ppat ) ; + unsigned char *read_whole_file ( const char *fname, int *len ) ; + +public: + + MODfile ( const char *fname, int speed = 44100, int stereo = 0 ) ; + ~MODfile () ; + + int update () ; +} ; + diff --git a/src/sl/slMODinst.cxx b/src/sl/slMODinst.cxx new file mode 100644 index 0000000..242f82d --- /dev/null +++ b/src/sl/slMODinst.cxx @@ -0,0 +1,1096 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: slMODinst.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "slMODPrivate.h" + +/* note-period table */ + +#define NOTE_MAX (12*8-1) /* 8octave */ +static short *note ; + +#define shift(x,n) ((n) >= 0? (x) << (n) : (x) >> -(n)) /* x * 2**n */ + +static struct +{ + int *p0 ; + int *p ; + int len ; +} hirev_buf ; + +void _MOD_instHirevInit ( void ) +{ + hirev_buf.p0 = dacioGetBuffer () ; +} + +void _MOD_instHirevSetFrameLen ( int l ) +{ + dacioIncomingBufLen ( l ) ; + hirev_buf.len = l ; +} + +void _MOD_instHirevEraseBuf ( void ) +{ + memset ( hirev_buf.p0, 0, sizeof ( int ) * hirev_buf.len * 2 ) ; +} + +void _MOD_instHirevFlushBuf ( void ) +{ + dacioOut () ; +} + + +static void fadeout ( InstHirevInfo *ihip ) +{ + int lastL = ihip->lastL / 64 ; + int lastR = ihip->lastR / 64 ; + int f = ihip->fadeout ; + + if ( f > 63 ) + f = 63 ; + + if ( lastL || lastR ) + { + int *bufp = hirev_buf.p ; + int n = ( hirev_buf.p0 + hirev_buf.len - bufp ) / 2 ; + + if ( n > f ) n = f ; + + for ( ; n > 0 ; n--,f-- ) + { + *bufp++ += lastL * f ; + *bufp++ += lastR * f ; + } + } + + ihip->fadeout = f ; + + if ( !f ) + ihip->lastL = ihip->lastR = 0 ; +} + +/* vol zero optimization: just calculates phase progress within this frame */ + +static void vol0Opt ( InstHirevInfo *ihip ) +{ + if ( ihip->lastL || ihip->lastR ) + { + /* suddenly volume is turned to 0 -> click ( chi_mai.s3m ) */ + + ihip->fadeout = 256 ; + fadeout ( ihip ) ; + ihip->fadeout = 0 ; /* don't note off ( ambient_power.mod ) */ + } + + ihip->wAcc = ( unsigned int ) ( unsigned short ) ihip->wAcc + ( unsigned short )( ihip->w * hirev_buf.len ) ; + ihip->ptr += ( ihip->w >> 16 ) * hirev_buf.len + + ( ( unsigned short ) ihip->w * hirev_buf.len >> 16 ) + + ( ihip->wAcc >> 16 ) ; + + if ( ihip->ptr >= ihip->end ) + { + if ( ihip->loopBeg ) + ihip->ptr = ihip->loopBeg + ( ihip->ptr - ihip->end ) % ( ihip->end - ihip->loopBeg ) ; + else + ihip->ptr = NULL ; /* note off */ + } + + ihip->lastL = ihip->lastR = 0 ; +} + +static InstHirevInfo ihi ; /* cacheing */ + +static void hirevLoop0 ( unsigned int n ) +{ + int *bufp = hirev_buf.p ; + unsigned char *ihiPtr = ihi.ptr ; + unsigned int ihiWAcc = ihi.wAcc ; + + for ( ; n > 0 ; n-- ) + { + int d = ( signed char ) *ihiPtr ; + *bufp++ += d * ihi.volL ; + *bufp++ += d * ihi.volR ; + + ihiWAcc = ( unsigned short ) ihiWAcc + ihi.w ; /*ihiWAcc & 0xffff + w*/ + ihiPtr += ihiWAcc >> 16 ; + } + + hirev_buf.p = bufp ; + ihi.ptr = ihiPtr ; + ihi.wAcc = ihiWAcc ; +} + +static void hirevLoop80 ( unsigned int n ) +{ + int *bufp = hirev_buf.p ; + unsigned char *ihiPtr = ihi.ptr ; + unsigned int ihiWAcc = ihi.wAcc ; + + for ( ; n > 0 ; n-- ) + { + int d = ( signed char ) ( *ihiPtr ^ 0x80 ) ; + *bufp++ += d * ihi.volL ; + *bufp++ += d * ihi.volR ; + + ihiWAcc = ( unsigned short ) ihiWAcc + ihi.w ; /*ihiWAcc & 0xffff + w*/ + ihiPtr += ihiWAcc >> 16 ; + } + + hirev_buf.p = bufp ; + ihi.ptr = ihiPtr ; + ihi.wAcc = ihiWAcc ; +} + +#define hirevLoop(x) { if ( ihi.x_or ) hirevLoop80(x) ; else hirevLoop0(x) ; } + + +void _MOD_instHirevLoop ( InstHirevInfo *ihip ) +{ + unsigned int restF ; + unsigned int restS ; + int lastD ; + + if ( ihip->ptr == NULL ) + return ; /* note is off */ + + hirev_buf.p = hirev_buf.p0 ; + + if ( ihip->fadeout ) + { + fadeout ( ihip ) ; + + if ( !ihip->fadeout ) + ihip->ptr = NULL ; /* note off */ + + return ; + } + + if ( !ihip->volL && !ihip->volR ) { vol0Opt ( ihip ) ; return ; } + + ihi = *ihip ; /* load to cache */ + restF = hirev_buf.len ; + + do + { + int l8, l0 ; + + ihi.wAcc = ( unsigned short ) ihi.wAcc ; + + l8 = ( ihi.end - ihi.ptr ) << 8 ; + + if ( !l8 && !ihi.wAcc ) + { /* happens only on empty samples */ + + ihip->fadeout = 256 ; + fadeout ( ihip ) ; + + if ( !ihip->fadeout ) + ihip->ptr = NULL ; /* note off */ + + return ; + } + + if ( l8 <= 0 ) + { + ulSetError ( UL_WARNING, "bug: restF=%u",restF ) ; + ulSetError ( UL_WARNING, "end-ptr=%d w=%u",ihi.end-ihi.ptr,ihi.w ) ; + ulSetError ( UL_WARNING, "wAcc = %u",ihi.wAcc ) ; + } + + l0 = ihi.w - 1 - ihi.wAcc ; + l8 += l0 >> 8 ; + l0 &= 0xff ; + restS = ( ( l8 / ihi.w ) << 8 ) + ( ( ( l8 % ihi.w ) << 8 ) + l0 ) / ihi.w ; + + if ( restF < restS ) + { /* sample is longer than frame */ + + hirevLoop ( restF ) ; + lastD = ( signed char ) ( * ( ihi.ptr - ( ihi.wAcc >> 16 ) ) ^ ihi.x_or ) ; + + break ; + } + + /* restF >= restS */ + hirevLoop ( restS ) ; + lastD = ( signed char ) ( * ( ihi.ptr - ( ihi.wAcc >> 16 ) ) ^ ihi.x_or ) ; + + if ( ihi.ptr < ihi.end || ihi.end <= ihi.ptr - ( ihi.wAcc >> 16 ) ) + { + ulSetError ( UL_FATAL, "SL: Internal Error in _MOD_instHirevLoop." ) ; +/* + ulSetError ( UL_DEBUG, "bug: restS = %u restF=%u end-ptr = %d, ptr=%p", + restS, restF, ihi.end-ihi.ptr, ihi.ptr ) ; + ulSetError ( UL_DEBUG, "last ptr=%p", ( ihi.ptr - ( ihi.wAcc >> 16 ) ) ) ; +*/ + } + + restF -= restS ; + + if ( ihi.loopBeg ) + { + ihi.ptr = ihi.loopBeg + ( ihi.ptr - ihi.end ) % ( ihi.end - ihi.loopBeg ) ; + } + else + { + ihi.lastL = lastD * ihi.volL ; + ihi.lastR = lastD * ihi.volR ; + ihi.fadeout = 256 ; + + fadeout ( &ihi ) ; + + if ( !ihi.fadeout ) + ihi.ptr = NULL ; /* note off */ + + *ihip = ihi ; /* save cache */ + return ; + } + } while ( restF ) ; + + ihi.lastL = lastD * ihi.volL ; + ihi.lastR = lastD * ihi.volR ; + *ihip = ihi ; /* save cache */ +} + +static void makeNoteTable ( void ) +{ + static int oct4[] = + { + 1712, 1616, 1524, 1440, 1356, 1280, 1208, 1140, 1076, 1016, 960, 907 + } ; + + note = new short [ NOTE_MAX + 1 ] ; + + for ( int i = 0 ; i <= NOTE_MAX ; i++ ) + note[i] = shift ( oct4[i%12], 4-i/12 ) ; +} + +/* period -> nearest note */ + +static int normalizePeriod ( int *pp ) +{ + int i ; + int s ; + int p = *pp ; + + if ( p >= note [ 0 ] ) { *pp = note [ 0 ] ; return 0 ; } + if ( p <= note [ NOTE_MAX ] ) { *pp = note [ NOTE_MAX ] ; return NOTE_MAX ; } + + for ( i = 0, s = 64 ; s > 0 ; s /= 2 ) /* 64: =2**n, and 64*2 > NOTE_MAX */ + if ( i + s < NOTE_MAX && note [ i + s ] > p ) /* i < NOTE_MAX !! */ + i += s ; + + if ( note [ i ] - p > p - note [ i + 1 ] ) + i++ ; /* choose nearest */ + + *pp = note [ i ] ; + + return i ; +} + + + +struct ModulateInfo +{ + int type ; /* sine,ramp,square,... */ + int noRetrig ; + int phase ; + int d ; /* phase accumlates this for each frame */ + int depth ; /* org * table[phase] * depth/MAX_IN_TABLE = cur */ +} ; + + +/* output rate */ + +static unsigned int mclk ; + +#define MCLK0 ((unsigned int)3579545*4) + +void _MOD_instOutRate ( unsigned int rate ) +{ + mclk = MCLK0 / rate * 65536 + MCLK0 % rate * 65536 / rate ; +} + +#define PFW_MAX 3 /* note delay = note delay + sample delay + vol delay */ + +struct InstInfo +{ + InstHirevInfo hirev ; /* for hirev loop */ + + struct + { + int cur ; /* current period */ + int org ; /* original period */ + int note ; /* note */ + int notePer ; /* note period */ + int mclk ; /* master clock in Hz (c4spd * 1712) */ + + struct + { + int speed ; /* added/sub'ed for each frame */ + int fine ; /* fine slide */ + } slide ; + + struct + { + int speed ; + int glissando ; + int nextNote ; /* (glissando) next note */ + } port ; /* portamento */ + + ModulateInfo mod ; + + struct + { + int baseNote ; + int plus[2] ; /* baseNote + plus[n] halfnote is played */ + } rpgo ; /* arpeggio */ + + struct + { + int n ; + int newNote ; + } delay ; + + } per ; /* period */ + + struct + { + int cur ; /* current volume */ + int org ; + int pan ; /* 0(left)..64(right) */ + + struct + { + int d ; /* added for each frame */ + int mul ; /* multiply for each frame */ + int div ; /* divide for each frame */ + int nthFrame ; /* slide every nth frame */ + int fine ; /* fine slide */ + int count ; /* frame counter */ + } slide ; + + ModulateInfo mod ; + + struct + { + int onOff ; + int count ; + int onTime ; + int offTime ; + } tremor ; + + struct + { + int n ; + int newest ; + } delay ; + + } vol ; + + struct + { + int cur ; /* current frame */ + int count ; /* decrement counter, 0 starts next frame */ + } frame ; + + struct + { + struct + { + int nthFrame ; /* retrig every nth frame */ + int count ; /* frame counter */ + } retrig ; + + SampleInfo *sip ; + SampleInfo *newSip ; + int c4spd ; + + struct + { + int n ; + SampleInfo *sip ; + } delay ; + + int cutFrame ; + } smp ; + + struct + { + void (*func[PFW_MAX])(void) ; + int n ; + } pfw ; /* per frame works */ + +} ; + +static InstInfo *instBank ; +static InstInfo *instp ; + + +/* select channel */ + +void _MOD_instSelectCh(int ch) +{ + instp = &instBank[ch]; +} + + +/* per frame work */ + +void _MOD_instClearPFW(void) +{ + instp->pfw.n = 0; +} + +void _MOD_instDoPerFrameWorks(int frame) +{ + instp->frame.cur = frame; + + for (int i = 0; i < instp->pfw.n; i++) + (*instp->pfw.func[i])(); +} + +static void addPerFrameWork(void (*f)(void)) +{ + if (instp->pfw.n >= PFW_MAX) + { + ulSetError ( UL_FATAL, "Too many PFWs"); + } + + instp->pfw.func[instp->pfw.n++] = f; +} + + +/* hirev loop */ + +void _MOD_instLoop(void) +{ + _MOD_instHirevLoop(&instp->hirev); +} + + +/* initialize */ + +void _MOD_instInit(void) +{ + static SampleInfo si0 ; + + _MOD_instHirevInit () ; + makeNoteTable () ; + + instBank = new InstInfo [ 32 ] ; + + si0.beg = si0.end = NULL ; + si0.c4spd = 8363 ; + si0.mag = 1 ; + + for ( int i = 0 ; i < 32 ; i++ ) + { + /* prepare for "note w/o inst and volume" */ + instBank[i].smp.sip = instBank[i].smp.newSip = &si0 ; + instBank[i].smp.c4spd = 8363; /* dope.mod ch14 begins with GF0 */ + instBank[i].hirev.end = instBank[i].hirev.ptr = NULL; + instBank[i].vol.slide.div = 1; + } +} + + +static void setW(void) +{ + instp->hirev.w = (mclk * instp->smp.sip->mag) / + (instp->per.cur < 16? 16 : instp->per.cur); +} + +#define noteToPeriod(n) ((int)note[(n)] * 8363 / instp->smp.c4spd) + +static void setPeriod(void) +{ + if (instp->smp.sip != instp->smp.newSip) + { + /* actual sample switching is carried out here */ + instp->smp.sip = instp->smp.newSip ; + instp->hirev.end = instp->smp.sip->end ; + instp->hirev.loopBeg = instp->smp.sip->loopBeg ; + instp->hirev.x_or = instp->smp.sip->x_or ; + } + + instp->per.note = instp->per.delay.newNote; + instp->per.cur = + instp->per.org = + instp->per.notePer = noteToPeriod(instp->per.note); + + instp->hirev.ptr = instp->smp.sip->beg; /* key-on */ + instp->hirev.wAcc = 0; + instp->hirev.fadeout = 0; + + if ( ! instp->per.mod.noRetrig ) instp->per.mod.phase = 0 ; + if ( ! instp->vol.mod.noRetrig ) instp->vol.mod.phase = 0 ; + + setW () ; +} + +static void setPeriodPFW(void) +{ + if (instp->per.delay.n == instp->frame.cur) + setPeriod() ; +} + + +void _MOD_instNote(int n, int delay) +{ + instp->per.delay.newNote = n; + + if (delay == 0) + setPeriod(); + else + { + instp->per.delay.n = delay; + addPerFrameWork(setPeriodPFW); + } +} + + +/* set volume */ + +static int mono; + +void _MOD_instMono(int n) +{ + mono = n; +} + +static void setHirevVol(void) +{ + if ( mono ) + { + instp->hirev.volL = instp->vol.cur ; + return ; + } + + /* currently linear, which makes front sounds rather weaker */ + + if (instp->vol.pan >= 0) + { + instp->hirev.volL = instp->vol.cur * (64 - instp->vol.pan)/64; + instp->hirev.volR = instp->vol.cur * instp->vol.pan/64; + } + else + { /* surround!! */ + instp->hirev.volL = instp->vol.cur / 2; + instp->hirev.volR = -instp->vol.cur / 2; + } +} + +static void setVol(void) +{ + instp->vol.cur = instp->vol.org = instp->vol.delay.newest; + setHirevVol(); +} + +static void setVolPFW(void) +{ + if (instp->vol.delay.n == instp->frame.cur) setVol(); +} + +void _MOD_instVol(int v, int delay) +{ + instp->vol.delay.newest = v > 64? 64: v; + + if (delay == 0) + setVol(); + else + { + instp->vol.delay.n = delay; + addPerFrameWork(setVolPFW); + } +} + + +/* tuning */ + +void _MOD_instTuning(int c4spd) +{ + instp->smp.c4spd = c4spd; +} + + +/* set sample */ + +static void setSample() +{ + /* actual sample switching is not done here.. */ + + instp->smp.newSip = instp->smp.delay.sip; + + /* set smp's default vol.. */ + + instp->vol.cur = instp->vol.org = instp->smp.newSip->vol; + + /* set smp's c4spd.. */ + + instp->smp.c4spd = instp->smp.newSip->c4spd; + setHirevVol(); +} + + +static void setSamplePFW(void) +{ + if (instp->smp.delay.n == instp->frame.cur) setSample(); +} + +void _MOD_instSample(SampleInfo *sip, int delay) +{ + instp->smp.delay.sip = sip; + + if (delay) + { + instp->smp.delay.n = delay; + addPerFrameWork(setSamplePFW); + } else setSample(); +} + + +/* volume slide */ + +inline int limitVol ( int v ) +{ + if ( v > 64 ) + return 64 ; + + if ( v < 0 ) + return 0 ; + + return v ; +} + +static int fastVolSlide; + +static void volSlidePFW(void) +{ + if (!fastVolSlide && !instp->frame.cur) return; /* skip frame 0 */ + if (--instp->vol.slide.count <= 0) { + instp->vol.slide.count = instp->vol.slide.nthFrame; + instp->vol.cur = + instp->vol.cur * instp->vol.slide.mul / instp->vol.slide.div + + instp->vol.slide.d; + + instp->vol.cur = limitVol ( instp->vol.cur ) ; + setHirevVol(); + } +} + +void _MOD_instVolSlide(void) +{ + if (instp->vol.slide.fine) { + instp->vol.cur = + instp->vol.cur * instp->vol.slide.mul / instp->vol.slide.div + + instp->vol.slide.d; + + instp->vol.cur = limitVol ( instp->vol.cur ) ; + setHirevVol(); + } else addPerFrameWork(volSlidePFW); +} + +void _MOD_instSetVolSlideParams(int d, int mul, int div, int nthFrame, int fine) +{ + instp->vol.slide.d = d; + instp->vol.slide.mul = mul; + instp->vol.slide.div = div; + instp->vol.slide.nthFrame = instp->vol.slide.count = nthFrame; + instp->vol.slide.fine = fine; +} + +void _MOD_instSetVolSlideFast(int onOff) +{ + fastVolSlide = onOff; +} + + +/* period slide */ + +#define noteOff() { instp->hirev.fadeout = 256; } /* eventually note-off */ + +static int amigaLimit; + +static void limitPeriod(void) +{ +#define p instp->per.cur + if (amigaLimit) { + if ((p) > note[3*12]) (p) = note[3*12]; + else if ((p) < note[5*12+11]) (p) = note[5*12+11]; + } else { + if ((p) > 32000) (p) = 32000; + else if ((p) < 0) { (p) = 0; noteOff(); /*panic.s3m needs this*/ } + } +#undef p +} + +static void periodSlideUpPFW(void) +{ + if (!instp->frame.cur) return; /* skip frame 0 */ + instp->per.cur -= instp->per.slide.speed; /* ignore per.org */ + limitPeriod(/*instp->per.cur*/); + instp->per.org = instp->per.cur; + setW(); +} + +static void periodSlideDownPFW(void) +{ + if (!instp->frame.cur) return; /* skip frame 0 */ + instp->per.cur += instp->per.slide.speed; + limitPeriod(/*instp->per.cur*/); + instp->per.org = instp->per.cur; + setW(); +} + +void _MOD_instPeriodSlideUp(void) +{ + if (instp->per.slide.fine) { + instp->per.cur -= instp->per.slide.speed; + limitPeriod(/*instp->per.cur*/); + instp->per.org = instp->per.cur; + setW(); + } else addPerFrameWork(periodSlideUpPFW); +} + +void _MOD_instPeriodSlideDown(void) +{ + if (instp->per.slide.fine) { + instp->per.cur += instp->per.slide.speed; + limitPeriod(/*instp->per.cur*/); + instp->per.org = instp->per.cur; + setW(); + } else addPerFrameWork(periodSlideDownPFW); +} + +void _MOD_instSetPeriodSlideParams(int speed, int fine) +{ + instp->per.slide.speed = speed; + instp->per.slide.fine = fine; +} + +void _MOD_instSetPeriodAmigaLimit(int onOff) +{ + amigaLimit = onOff; +} + + +/* portamento */ + +static void portamentoPFW(void) +{ + if (!instp->frame.cur) return; /* which S3M slides at frame 0? */ + if (instp->per.org > instp->per.notePer) { /* port up now */ + instp->per.org -= instp->per.port.speed; + if (instp->per.org < instp->per.notePer) + instp->per.cur = instp->per.org = instp->per.notePer; + else { + instp->per.cur = instp->per.org; + if (instp->per.port.glissando) normalizePeriod(&instp->per.cur); + } + } else { /* port down now */ + instp->per.org += instp->per.port.speed; + if (instp->per.org > instp->per.notePer) + instp->per.cur = instp->per.org = instp->per.notePer; + else { + instp->per.cur = instp->per.org; + if (instp->per.port.glissando) normalizePeriod(&instp->per.cur); + } + } + setW(); +} + +void _MOD_instPortamento(void) +{ + addPerFrameWork(portamentoPFW); +} + +void _MOD_instSetPortamentoTo(int to) +{ + instp->per.note = to; + instp->per.notePer = noteToPeriod(to); +} + +void _MOD_instSetPortamentoSpeed(int speed) +{ + instp->per.port.speed = speed; +} + +void _MOD_instSetPortamentoDefaultVol(void) +{ + instp->vol.cur = instp->vol.org = instp->smp.sip->vol; + setHirevVol(); +} + +void _MOD_instSetPortamentoGlissando(int onOff) +{ + instp->per.port.glissando = onOff; +} + + +/* arpeggio */ + +static void arpeggioPFW(void) +{ + if (instp->frame.cur % 3) { + instp->per.cur = note[instp->per.note + + instp->per.rpgo.plus[instp->frame.cur%3 - 1]]; + } else instp->per.cur = instp->per.notePer; + setW(); +} + +void _MOD_instArpeggio(void) +{ + addPerFrameWork(arpeggioPFW); +} + +void _MOD_instSetArpeggioParams(int plus1, int plus2) +{ + instp->per.rpgo.plus[0] = plus1; + instp->per.rpgo.plus[1] = plus2; +} + + +/* retrig */ + +static void retrigPFW(void) +{ + if (--instp->smp.retrig.count <= 0) { + instp->smp.retrig.count = instp->smp.retrig.nthFrame; + instp->hirev.ptr = instp->smp.sip->beg; + setW(); + } +} + +void _MOD_instRetrig(void) +{ + addPerFrameWork(retrigPFW); +} + +void _MOD_instSetRetrigParam(int nthFrame) +{ + instp->smp.retrig.nthFrame = nthFrame; + instp->smp.retrig.count = 0; +} + + +/* sample offset */ + +void _MOD_instSampleOffset(int offset) +{ + instp->hirev.ptr = instp->smp.sip->beg + offset * instp->smp.sip->mag; + if (instp->hirev.ptr >= instp->hirev.end) { + if (instp->hirev.loopBeg) { + instp->hirev.ptr = + instp->hirev.loopBeg + + (instp->hirev.ptr - instp->hirev.end) % + (instp->hirev.end - instp->hirev.loopBeg); + } else { noteOff(); } + } +} + + +/* modulation */ + +static unsigned char sine[] = { + 000, 25, 50, 74, 98, 120, 142, 162, + 180, 197, 212, 225, 236, 244, 250, 254, + 255 +}; /* sin(x), 0 <= x < pi/4, max = 255 */ + + +static int wave(ModulateInfo *mip) +{ + int i; + + switch (mip->type) { + case 1: /* ramp up (period: down) */ + i = (255 * 2 * mip->phase)/63 - 255; + break; + case 2: /* square */ + i = (mip->phase < 32)? 255 : 0; /* yes, not 255/-255 */ + break; + default: /* sine */ + if (mip->phase < 16) i = sine[mip->phase]; + else if (mip->phase < 32) i = sine[32 - mip->phase]; + else if (mip->phase < 48) i = -sine[mip->phase - 32]; + else i = -sine[64 - mip->phase]; + } + return mip->depth * i / 255; +} + +static void vibratoPFW(void) +{ + if (!instp->frame.cur) return; /* skip frame 0 */ + instp->per.mod.phase += instp->per.mod.d; + instp->per.mod.phase %= 64; + /* per.org: no change.. */ + instp->per.cur = instp->per.org + wave(&instp->per.mod); + limitPeriod(/*instp->per.cur*/); + setW(); +} + +void _MOD_instVibrato(void) +{ + addPerFrameWork(vibratoPFW); +} + +/* depth = period */ +void _MOD_instSetVibratoParams(int d, int depth) +{ + if (d) instp->per.mod.d = d; + instp->per.mod.depth = depth; + /*if (!instp->per.mod.noRetrig) instp->per.mod.phase = 0;*/ +} + +void _MOD_instSetVibratoWave(int type, int noRetrig) +{ + if (type == 3) type = rand() % 3; + instp->per.mod.type = type; + instp->per.mod.noRetrig = noRetrig; +} + + +static void tremoloPFW(void) +{ + if (!instp->frame.cur) return; /* skip frame 0 */ + instp->vol.mod.phase += instp->vol.mod.d; + instp->vol.mod.phase %= 64; + instp->vol.cur = instp->vol.org + wave(&instp->vol.mod); + instp->vol.cur = limitVol ( instp->vol.cur ) ; + setHirevVol(); +} + +void _MOD_instTremolo(void) +{ + addPerFrameWork(tremoloPFW); +} + +void _MOD_instSetTremoloParams(int d, int depth) +{ + if (d) instp->vol.mod.d = d; + instp->vol.mod.depth = depth; + /*if (!instp->vol.mod.noRetrig) instp->vol.mod.phase = 0;*/ +} + +void _MOD_instSetTremoloWave(int type, int noRetrig) +{ + if (type == 3) type = rand() % 3; + instp->vol.mod.type = type; + instp->vol.mod.noRetrig = noRetrig; +} + + +/* note cut */ + +static void noteCutPFW(void) +{ + /* said to be vol := 0, but ST3 seems to key-off */ + if (instp->smp.cutFrame == instp->frame.cur) noteOff(); +} + +void _MOD_instNoteCut(int frame) +{ + if (frame) { + instp->smp.cutFrame = frame; + addPerFrameWork(noteCutPFW); + } else noteOff(); +} + + +/* tremor */ + +static void tremorPFW(void) +{ + if (--instp->vol.tremor.count <= 0) { + if (instp->vol.tremor.onOff) { + instp->vol.cur = 0; + setHirevVol(); + instp->vol.tremor.onOff = 0; + instp->vol.tremor.count = instp->vol.tremor.offTime; + } else { + instp->vol.cur = instp->vol.org; + setHirevVol(); + instp->vol.tremor.onOff = 1; + instp->vol.tremor.count = instp->vol.tremor.onTime; + } + } +} + +void _MOD_instTremor(void) +{ + addPerFrameWork(tremorPFW); +} + +void _MOD_instSetTremorParams(int onTime, int offTime) +{ + instp->vol.tremor.onTime = onTime; + instp->vol.tremor.offTime = offTime; + instp->vol.tremor.count = 0; + instp->vol.tremor.onOff = 0; +} + + +/* note off */ + +static void noteOffPFW(void) +{ + if (instp->per.delay.n == instp->frame.cur) noteOff(); +} + +void _MOD_instNoteOff(int delay) +{ + if (delay) { + instp->per.delay.n = delay; + addPerFrameWork(noteOffPFW); + } else { noteOff(); } +} + +int _MOD_instIsNoteOff(void) +{ + return instp->hirev.ptr == NULL; +} + + +/* pan position */ + +/* pos = 0(left)..64(right), -1(surround) */ + +void _MOD_instPanPosition(int pos) +{ + instp->vol.pan = pos; + setHirevVol(); +} + + +/* empty command */ + +void _MOD_instEmptyCmd(void) +{ + instp->per.cur = instp->per.org; + setW(); + /* empty command has some special meanings... + (when after glissando portamento or vibrato) */ +} + diff --git a/src/sl/slMODnote.cxx b/src/sl/slMODnote.cxx new file mode 100644 index 0000000..fe97662 --- /dev/null +++ b/src/sl/slMODnote.cxx @@ -0,0 +1,469 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: slMODnote.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "slMODPrivate.h" + +static SampleInfo *smp ; +static unsigned char chToPlay[32]; + +static int masterVol = 0x30 * 4/3; +static int globalVol = 0x40; +static int mono; +static int outRate = DEF_OUTRATE ; +static int tempo = DEF_TEMPO ; /* BPM = rows/minute/4 */ +static int speed = DEF_SPEED ; /* frames/row */ +static int frameLen = DEF_OUTRATE * 60 / ( DEF_TEMPO * 24 ) ; +static int patRepeat = 0 ; + + + +static void commonWork ( Note *np ) +{ + _MOD_instClearPFW(); + + if (np->ins) + _MOD_instSample(&smp[np->ins - 1], 0); + + if (np->note != 255) + if (np->note == 254) + _MOD_instNoteOff(0); + else + _MOD_instNote((np->note/16) * 12 + np->note%16, 0); + + if (np->vol != 255) + _MOD_instVol(np->vol, 0); +} + + +static void noEffect ( Note *np ) +{ + if ( np->cmd == 255 ) + _MOD_instEmptyCmd () ; + + commonWork ( np ) ; +} + + +static void unknownEffect ( Note *np ) +{ + ulSetError ( UL_WARNING, "Unknown effect: %c%02X", np->cmd + '@', np->info ) ; + commonWork ( np ) ; +} + +#define X (np->info/16) +#define Y (np->info%16) + +/* Dxy, Kxy, Lxy common work */ + +static void dklCommonWork ( Note *np ) +{ + if ( np->info ) + { + if ( Y == 0 ) /* Dx0=up */ + _MOD_instSetVolSlideParams ( X, 1, 1, 1, 0 ) ; + else + if ( X > 0 && Y == 0xf ) /* DxF=fine up */ + _MOD_instSetVolSlideParams ( X, 1, 1, 1, 1 ) ; + else + if ( X == 0xf ) /* DFy=fine down */ + _MOD_instSetVolSlideParams ( -Y, 1, 1, 1, 1 ) ; + else /* D0y=down, but also D46 or something is here */ + _MOD_instSetVolSlideParams ( -Y, 1, 1, 1, 0 ) ; + } + + _MOD_instVolSlide () ; +} + +/* Dxy = volume slide */ + +static void dCmd ( Note *np ) +{ + commonWork ( np ) ; + dklCommonWork ( np ) ; +} + +/* Exx, Fxx common work */ + +static void efCommonWork ( Note *np ) +{ + if (np->info) + { + switch (X) + { + case 0xf: /* [EF]Fx = fine */ + _MOD_instSetPeriodSlideParams((np->info%16)*4, 1); + break; + + case 0xe: /* [EF]Ex = extra fine */ + /* ST3 plays [EF]E0 and [EF]F0 differently */ + /* so it may be incompatible.. */ + _MOD_instSetPeriodSlideParams(np->info%16, 1); + break; + + default: + _MOD_instSetPeriodSlideParams(np->info*4, 0); + break; + } + } +} + +/* Exx = slide down */ + +static void eCmd(Note *np) +{ + commonWork(np); + efCommonWork(np); + _MOD_instPeriodSlideDown(); +} + +/* Fxx = slide up */ + +static void fCmd(Note *np) +{ + commonWork(np); + efCommonWork(np); + _MOD_instPeriodSlideUp(); +} + +/* Gxx = portamento */ + +static void gCmd(Note *np) +{ + _MOD_instClearPFW(); + + if (np->ins) _MOD_instSetPortamentoDefaultVol(); /* only set default volume */ + if (np->vol != 255) _MOD_instVol(np->vol, 0); + if (np->note < 254 ) _MOD_instSetPortamentoTo((np->note/16)*12 + np->note%16); + if (np->info) _MOD_instSetPortamentoSpeed(np->info*4); + + _MOD_instPortamento(); +} + +/* Hxy = vibrato */ + +static void hCmd(Note *np) +{ + commonWork(np); + if (np->info) _MOD_instSetVibratoParams(X, Y*8); + _MOD_instVibrato(); +} + +/* Ixy = tremor */ + +static void iCmd(Note *np) +{ + commonWork(np); + if (np->info) _MOD_instSetTremorParams(X+1, Y+1); + _MOD_instTremor(); +} + +/* Jxy = arpeggio */ + +static void jCmd(Note *np) +{ + commonWork(np); + if (np->info) _MOD_instSetArpeggioParams(X, Y); + _MOD_instArpeggio(); +} + +/* Kxy = H00 and Dxy */ + +static void kCmd(Note *np) +{ + commonWork(np); + _MOD_instVibrato(); /* H00 */ + dklCommonWork(np); +} + +/* Lxy = G00 and Dxy */ + +static void lCmd(Note *np) +{ + commonWork(np); + _MOD_instPortamento(); /* G00 */ + dklCommonWork(np); +} + +/* Oxx = sample offset */ + +static void oCmd(Note *np) +{ + commonWork(np); + _MOD_instSampleOffset(np->info * 0x100); +} + +/* Qxy = retrig + volumeslide */ + +static void qCmd(Note *np) +{ + static int add[16]={0,-1,-2,-4,-8,-16,0,0,0,1,2,4,8,16,0,0}; + static int mul[16]={1,1,1,1,1,1,2,1,1,1,1,1,1,1,3,2}; + static int div[16]={1,1,1,1,1,1,3,2,1,1,1,1,1,1,2,1}; + + commonWork(np); + + if (np->info) + { + _MOD_instSetVolSlideParams(add[X], mul[X], div[X], Y, 0); + _MOD_instSetRetrigParam(Y); + } + + _MOD_instVolSlide(); + _MOD_instRetrig(); +} + +/* Rxy = tremolo */ + +static void rCmd(Note *np) +{ + commonWork(np); + if (np->info) _MOD_instSetTremoloParams(X, Y*2); + _MOD_instTremolo(); +} + +/* Uxy = fine vibrato */ + +static void uCmd(Note *np) +{ + commonWork(np); + if (np->info) _MOD_instSetVibratoParams(X, Y*2); + _MOD_instVibrato(); +} + +/* Sxy = misc */ + +static void sCmd(Note *np) +{ + if (X == 0xd) /* notedelay */ + { + _MOD_instClearPFW(); + + if (np->ins) + _MOD_instSample(&smp[np->ins - 1], Y); + + if (np->note != 255) + if (np->note == 254) + _MOD_instNoteOff(Y); + else + _MOD_instNote((np->note/16) * 12 + np->note%16, Y); + + if (np->vol != 255) + _MOD_instVol(np->vol, Y); + } + else + { + commonWork ( np ) ; + + switch ( X ) + { + case 1: /* set glissando control */ + _MOD_instSetPortamentoGlissando(Y); + break; + case 2: /* set finetune */ + /* ...but not tested yet. which tune use this? */ + ulSetError ( UL_DEBUG, "Got it! Set Finetune"); + { + static int freq[16] = + { + 8363,8413,8463,8529,8581,8651,8723,8757, + 7895,7941,7985,8046,8107,8169,8232,8280 + }; + _MOD_instTuning(freq[Y]); + /* the tuning effects from next key-on */ + } + break; + case 3: /* set vibrato waveform */ + _MOD_instSetVibratoWave(Y%4, Y/4); + break; + case 4: /* set tremolo waveform */ + _MOD_instSetTremoloWave(Y%4, Y/4); + break; + case 8: /* set pan position */ + _MOD_instPanPosition(Y*64/15); + break; + case 0xc: /* notecut */ + _MOD_instNoteCut(Y); + break; + case 0xb: /* pattern loop */ + case 0xe: /* pattern delay */ + break; + default: + ulSetError ( UL_WARNING, "%c%02X not supported.", np->cmd+'@', np->info); + } + } +} + +/* Vxx = set global volume */ + + +static void setGlobalVol(void) +{ + dacioGlobalVol ( masterVol * globalVol ) ; +} + + +void _MOD_playNoteSetMono(int m) +{ + mono = m; + _MOD_instMono(m); +} + +void _MOD_playNoteSetMasterVol(int mv) +{ + masterVol = mono? mv : mv * 4 / 3; + setGlobalVol(); +} + +void _MOD_playNoteSetGlobalVol(int gv) +{ + globalVol = gv; + setGlobalVol(); +} + +static void vCmd(Note *np) +{ + commonWork(np); + _MOD_playNoteSetGlobalVol(np->info); +} + +/* Xxx = DMP style pan position */ + +static void xCmd(Note *np) +{ + commonWork(np); + + if (np->info <= 0x80) + _MOD_instPanPosition(np->info * 64 / 0x80); + else + if (np->info == 0xa4) + _MOD_instPanPosition(-1); /* surround */ + else + _MOD_instPanPosition(32); /* unknown -> center */ +} + + +static void (*cmdTbl[])( Note *np ) = +{ + /*@*/ unknownEffect, /*A*/ noEffect , /*B*/ noEffect, /*C*/noEffect, + /*D*/ dCmd , /*E*/ eCmd , /*F*/ fCmd , /*G*/gCmd, + /*H*/ hCmd , /*I*/ iCmd , /*J*/ jCmd , /*K*/kCmd, + /*L*/ lCmd , /*M*/ unknownEffect, /*N*/ unknownEffect, /*O*/oCmd, + /*P*/ unknownEffect, /*Q*/ qCmd , /*R*/ rCmd , /*S*/sCmd, + /*T*/ noEffect , /*U*/ uCmd , /*V*/ vCmd , /*W*/unknownEffect, + /*X*/ xCmd , /*Y*/ unknownEffect, /*Z*/ unknownEffect +} ; + + +void _MOD_playNoteSetSample ( SampleInfo *sip ) +{ + smp = sip ; +} + + +void _MOD_playNoteInit ( void ) +{ + _MOD_instInit () ; +} + +static void setFrameLen ( void ) +{ + frameLen = outRate * 60 / (tempo * 24) ; + _MOD_instHirevSetFrameLen ( frameLen ) ; +} + + +void _MOD_playNoteSetOutRate ( int _or ) +{ + if ( _or > MAX_OUTRATE ) + { + ulSetError ( UL_FATAL, "Too high output sample rate." ) ; + } + + _MOD_instOutRate ( _or ) ; + outRate = _or ; + setFrameLen () ; +} + + +void _MOD_playNoteSetTempo ( int n ) +{ + if ( n < MIN_TEMPO ) + { + ulSetError ( UL_WARNING, "Illegal tempo (%d) ignored.", n ) ; + return ; + } + + tempo = n ; + setFrameLen () ; +} + + +void _MOD_playNoteSetSpeed ( int n ) +{ + speed = n ; +} + + +void _MOD_playNoteSetNote ( int ch, Note *np ) +{ + chToPlay [ ch ] = 1 ; + _MOD_instSelectCh ( ch ) ; + + if ( np->cmd == 255 ) + noEffect ( np ) ; + else + (*cmdTbl[np->cmd]) ( np ) ; +} + + +void _MOD_playNoteSetPatRepeat ( int n ) +{ + patRepeat = n ; +} + +void _MOD_playNote ( void ) +{ + for ( int r = 0 ; r <= patRepeat ; r++ ) + for ( int f = 0 ; f < speed ; f++ ) + { + _MOD_instHirevEraseBuf () ; + + for ( int ch = 0 ; ch < 32 ; ch++ ) + if ( chToPlay [ ch ] ) + { + _MOD_instSelectCh ( ch ) ; + _MOD_instDoPerFrameWorks ( f ) ; + _MOD_instLoop () ; + } + + _MOD_instHirevFlushBuf () ; + } + + patRepeat = 0 ; + + for ( int ch = 0 ; ch < 32 ; ch++ ) + chToPlay [ ch ] = 0 ; +} + + diff --git a/src/sl/slPlayer.cxx b/src/sl/slPlayer.cxx new file mode 100644 index 0000000..4327c90 --- /dev/null +++ b/src/sl/slPlayer.cxx @@ -0,0 +1,139 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: slPlayer.cxx 1924 2004-04-06 13:32:26Z sjbaker $ +*/ + + +#include "sl.h" + +void slPlayer::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 slPlayer::preempt ( int delay ) +{ + 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 ; + default : break ; + } + + return SL_TRUE ; +} + +slPlayer::~slPlayer () +{ +} + + +void slPlayer::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 ) ; + env [ next_env ] -> applyToLPFilter ( dst, dst, nframes, + env_start_time [ next_env ] ) ; + 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 ; + + default : + break ; + } +} + diff --git a/src/sl/slPortability.h b/src/sl/slPortability.h new file mode 100644 index 0000000..a5ba64b --- /dev/null +++ b/src/sl/slPortability.h @@ -0,0 +1,95 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: slPortability.h 2013 2005-01-16 06:03:31Z sjbaker $ +*/ + + +#ifndef __SLPORTABILITY_H__ +#define __SLPORTABILITY_H__ 1 + +/* ------------------------------------------------------------- */ +/* OS specific includes and defines ... */ +/* ------------------------------------------------------------- */ + +#include "ul.h" +#include +#include + +#ifdef UL_MACINTOSH + #include + #include + #ifdef __MWERKS__ + #include + #endif +#endif + +#ifdef UL_MAC_OSX + #include +#endif + +#include +#include +#include +#include +#include + +#if (defined(UL_LINUX) || defined(UL_BSD)) && !defined(__NetBSD__) +#define SL_USING_OSS_AUDIO 1 +#endif + +#ifdef SL_USING_OSS_AUDIO +# if defined(UL_LINUX) +# include +# 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 UL_BSD +#ifndef __FreeBSD__ +# include +#endif +#endif + +/* Tom */ + +#ifdef UL_IRIX +# include +#endif + +#ifdef UL_SOLARIS +# include +# include +#endif + +#endif + diff --git a/src/sl/slSample.cxx b/src/sl/slSample.cxx new file mode 100644 index 0000000..4396781 --- /dev/null +++ b/src/sl/slSample.cxx @@ -0,0 +1,527 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: slSample.cxx 1853 2004-02-08 18:41:15Z stromberg $ +*/ + + +#include "sl.h" +#include + +void slSample::autoMatch ( const slDSP *dsp ) +{ + if ( dsp == NULL || dsp->notWorking () ) 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 length2 = (int) ( (float) length * ( (float) r / (float) rate ) ) ; + Uchar *buffer2 = new Uchar [ length2 ] ; + + int samps = length / (getBps() / 8) ; + int samps2 = length2 / (getBps() / 8) ; + + float step = (float) length / (float) length2 ; + + for ( int i = 0 ; i < samps2 ; 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>=samps)?samps-1:p1] : + (float) ((Ushort*)buffer)[(p1<0)?0:(p1>=samps)?samps-1:p1] ; + float b2 = (getBps()==8) ? + (float) buffer [(p2<0)?0:(p2>=samps)?samps-1:p2] : + (float) ((Ushort*)buffer)[(p2<0)?0:(p2>=samps)?samps-1:p2] ; + + float res = b1 * (1.0f-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 ( const char *fname ) +{ + if ( ulStrEqual ( & fname [ strlen ( fname ) - 4 ], ".wav" ) ) + return loadWavFile ( fname ) ; + + if ( ulStrEqual ( & fname [ strlen ( fname ) - 3 ], ".au" ) ) + return loadAUFile ( fname ) ; + + if ( ulStrEqual ( & fname [ strlen ( fname ) - 3 ], ".ub" ) ) + return loadRawFile ( fname ) ; + + ulSetError ( UL_WARNING, + "slSample:loadFile: Unknown file type for '%s'.", fname ) ; + return SL_FALSE ; +} + + +int slSample::loadWavFile ( const 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 ) + { + ulSetError ( UL_WARNING, + "slSample: loadWavFile: Cannot open '%s' for reading.", 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' ) + { + ulSetError ( UL_WARNING, "slWavSample: File '%s' has wrong magic number", fname ) ; + ulSetError ( UL_WARNING, " - it probably isn't in '.wav' format." ) ; + fclose ( fd ) ; + return SL_FALSE ; + } + + int leng1 ; + + if ( fread ( & leng1, sizeof(int), 1, fd ) == 0 ) + { + ulSetError ( UL_WARNING, "slSample: File '%s' has premature EOF in header", fname ) ; + fclose ( fd ) ; + return SL_FALSE ; + } + + fread ( magic, 4, 1, fd ) ; + + if ( magic[0] != 'W' || magic[1] != 'A' || + magic[2] != 'V' || magic[3] != 'E' ) + { + ulSetError ( UL_WARNING, "slSample: File '%s' has no WAVE tag.", 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 ) + { + ulSetError ( UL_WARNING, "slSample: File '%s' has premature EOF in header", fname ) ; + fclose ( fd ) ; + return SL_FALSE ; + } + + if ( leng1 > 65536 ) + { + needs_swabbing = SL_TRUE ; + swap_int ( & leng1 ) ; + } + + Ushort header [ 8 ] ; + + if ( leng1 != sizeof ( header ) ) + ulSetError ( UL_WARNING, + "slSample: File '%s' has unexpectedly long (%d byte) header", + fname, leng1 ) ; + + fread ( & header, sizeof(header), 1, fd ) ; + + for ( int junk = sizeof(header) ; junk < leng1 ; junk++ ) + getc ( 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 ) + { + ulSetError ( UL_WARNING, "slSample: File '%s' is not WAVE_FORMAT_PCM!", 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 ) + { + ulSetError ( UL_WARNING, "slSample: File '%s' has no data section", fname ) ; + fclose ( fd ) ; + return SL_FALSE ; + } + + if ( fread ( & length, sizeof(int), 1, fd ) == 0 ) + { + ulSetError ( UL_WARNING, "slSample: File '%s' has premature EOF in data", fname ) ; + fclose ( fd ) ; + return SL_FALSE ; + } + + if ( needs_swabbing ) + swap_int ( & length ) ; + + buffer = new Uchar [ length ] ; + + fread ( buffer, 1, length, fd ) ; + + if ( getBps () == 16 ) + { + changeToUnsigned () ; + } + + fclose ( fd ) ; + return SL_TRUE ; + } + } + + ulSetError ( UL_WARNING, "slSample: Premature EOF in '%s'.", fname ) ; + + fclose ( fd ) ; + return SL_FALSE ; +} + +int slSample::loadAUFile ( const char *fname ) +{ + delete [] buffer ; + buffer = NULL ; + length = 0 ; + + FILE *fd = fopen ( fname, "rb" ) ; + + if ( fd == NULL ) + { + ulSetError ( UL_WARNING, + "slSample: loadAUFile: Cannot open '%s' for reading.", + 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' ) + { + ulSetError ( UL_WARNING, "slSample: File '%s' has wrong magic number", fname ) ; + ulSetError ( UL_WARNING, " - it probably isn't in '.au' format." ) ; + 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 ) + { + ulSetError ( UL_WARNING, "slSample: File '%s' has premature EOF in header", 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 ) + { + ulSetError ( UL_WARNING, "slSample: File '%s' has a very strange header", fname ) ; + ulSetError ( UL_WARNING, " Header Length = %d", hdr_length ) ; + ulSetError ( UL_WARNING, " Data Length = %d", dat_length ) ; + ulSetError ( UL_WARNING, " Bytes/sample = %d", nbytes ) ; + ulSetError ( UL_WARNING, " Sampling Rate = %dHz",irate ) ; + ulSetError ( UL_WARNING, " Num Channels = %d", nchans ) ; + 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 ) + ulSetError ( UL_WARNING, "slAUSample: File '%s' has premature EOF in data.", fname ) ; + changeToUnsigned () ; + } + + fclose ( fd ) ; + return SL_TRUE ; +} + + +int slSample::loadRawFile ( const char *fname ) +{ + delete [] buffer ; + buffer = NULL ; + length = 0 ; + + FILE *fd = fopen ( fname, "rb" ) ; + + if ( fd == NULL ) + { + ulSetError ( UL_WARNING, + "slSample: loadRawFile: Cannot open '%s' for reading.", + fname ) ; + return SL_FALSE ; + } + + struct stat stat_buf ; + + if ( fstat ( fileno ( fd ), & stat_buf ) != 0 ) + { + ulSetError ( UL_WARNING, + "slSample: loadRawFile: Cannot get status for '%s'.", + 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/src/sl/slSamplePlayer.cxx b/src/sl/slSamplePlayer.cxx new file mode 100644 index 0000000..7e4da1c --- /dev/null +++ b/src/sl/slSamplePlayer.cxx @@ -0,0 +1,120 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: slSamplePlayer.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "sl.h" + +int slSamplePlayer::preempt ( int delay ) +{ + slScheduler::getCurrent() -> addCallBack ( callback, sample, SL_EVENT_PREEMPTED, magic ) ; + + return slPlayer::preempt ( delay ) ; +} + +slSamplePlayer::~slSamplePlayer () +{ + if ( sample ) + sample -> unRef () ; + + /* unRef() attached envelopes */ + for ( int i = 0 ; i < SL_MAX_ENVELOPES ; i++ ) + { + if ( env [ i ] != NULL ) + env [ i ] -> 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::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/src/sl/slScheduler.cxx b/src/sl/slScheduler.cxx new file mode 100644 index 0000000..9d066cf --- /dev/null +++ b/src/sl/slScheduler.cxx @@ -0,0 +1,545 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: slScheduler.cxx 1764 2003-05-18 13:45:04Z puggles $ +*/ + + +#include "sl.h" + +const char *__slPendingError = NULL ; + +slScheduler *slScheduler::current = NULL ; + +void slScheduler::init () +{ + int mi; + mixer = NULL ; + + mixer_buffer = NULL ; + /* Note there is a required null element on the end of array */ + for ( mi=0; mi <= SL_MAX_MIXERINPUTS; mi++ ) + mixer_inputs[mi] = NULL ; + + current = this ; + mixer_gain = 0x100 ; /* When we have to make sound quieter */ + + if ( notWorking () ) + { + ulSetError ( UL_WARNING, "slScheduler: soundcard init failed." ) ; + setError () ; + return ; + } + + if ( getBps() != 8 ) + { + ulSetError ( UL_WARNING, "slScheduler: Needs a sound card that supports 8 bits per sample." ) ; + setError () ; + return ; + } + + if ( getStereo() ) + { + ulSetError ( UL_WARNING, "slScheduler: Needs a sound card that supports monophonic replay." ) ; + setError () ; + return ; + } + + music = NULL ; + + for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ ) + player [ i ] = NULL ; + + amount_left = 0 ; + now = 0 ; + num_pending_callbacks = 0 ; + safety_margin = 1.0 ; + + initBuffers () ; +} + +void slScheduler::initBuffers () +{ + if ( notWorking () ) + return ; + + delete [] mixer_buffer ; + setMaxConcurrent ( 0 ); + + mixer_buffer_size = getDriverBufferSize () ; + int div = 1; + if ( getStereo() ) div *= 2 ; + if ( getBps() == 16 ) div *= 2 ; + seconds_per_buffer = (float)mixer_buffer_size / ( div * getRate() ) ; + + mixer_buffer = new Uchar [ mixer_buffer_size ] ; + memset ( mixer_buffer, 0x80, mixer_buffer_size ) ; + setMaxConcurrent ( 3 ); +} + +void slScheduler::setMaxConcurrent ( int mc ) +{ + int mi; + for ( mi = 0; mi < SL_MAX_MIXERINPUTS; mi ++ ) + if ( mi < mc ) + { if ( mixer_inputs[mi] == NULL ) + mixer_inputs[mi] = new Uchar [ mixer_buffer_size ] ; + } else + { if ( mixer_inputs[mi] != NULL ) + delete [] mixer_inputs[mi] ; + mixer_inputs[mi] = NULL; + } +} + +int slScheduler::getMaxConcurrent ( void ) const +{ + int mi, mc = 0; + for ( mi = 0; mi < SL_MAX_MIXERINPUTS; mi ++ ) + if ( NULL != mixer_inputs[mi] ) + mc ++; + return mc; +} + +slScheduler::~slScheduler () +{ + delete [] mixer_buffer ; + setMaxConcurrent(0); + if ( current == this ) + current = NULL ; +} + +void slScheduler::realUpdate ( int dump_first ) +{ + if ( notWorking () ) return ; + + if ( __slPendingError != NULL ) + { + ulSetError ( UL_FATAL, "%s", __slPendingError ) ; + } + + int i ; + + while ( ( secondsUsed() <= safety_margin ) && ( secondsRemaining() >= seconds_per_buffer ) ) + { + slPlayer *psp [ SL_MAX_MIXERINPUTS ] ; + int pri [ SL_MAX_MIXERINPUTS ] ; + int inputsused = 0 ; + int lowest = 0 ; /* makes it safe to reference before assignment below */ + + /* Decide who we're going to use */ + + for ( i = 0 ; i < SL_MAX_SAMPLES ; i++ ) + { + /* Ignore non-existent channels */ + + if ( player [ i ] == NULL ) + continue ; + + /* Clean up dead sample players */ + + if ( player [ i ] -> isDone () ) + { + if ( player [ i ] == music ) + music = NULL ; + + delete player [ i ] ; + player [ i ] = NULL ; + continue ; + } + + /* Skip paused players, but leave them alone */ + + if ( player [ i ] -> isPaused () ) + continue ; + + /* This one is viable, make sure we have room */ + + int mypri = player[i]->getPriority() ; + + if ( ( inputsused > 0 ) && + ( mixer_inputs[inputsused] == NULL ) && + ( mypri > pri[lowest] ) + ) + { /* Not enough room; get rid of someone */ + if ( player[lowest] != NULL ) + player[lowest] -> preempt ( mixer_buffer_size ) ; + + psp[lowest] = player[i] ; + pri[lowest] = mypri ; + int j; + for ( j = 0; j < inputsused; j++ ) + if ( pri[lowest] < pri[j] ) + lowest = j; + } + else if ( mixer_inputs[inputsused] != NULL ) + { /* Ok, we've got room, presumably, for another item */ + psp[inputsused] = player[i]; + pri[inputsused] = mypri; + if ( ( ( inputsused ++ ) == 0 ) || + ( pri[lowest] > mypri ) ) + lowest = inputsused; + } + else + { /* Oops, something very wrong. Shouldn't get here in normal use. + One obvious reason is if user specified zero channels to mix! */ + player[i] -> preempt ( mixer_buffer_size ) ; + } + } + + /* We've now chosen our sources. Previously we'd go back through + and figure out who to report as pre-empted. But we already did + that as part of getting our list of sources, so that disappeared. */ + + /* Now, we actually get the sound samples into the mixer_buffer. + All the versions here are fastpaths except the two last ones. + Just read the comments on the last one to understand it. */ + + + /* We put a minus sign on the number of inputs if we're attenuating */ + switch ( mixer_gain != 0x100 ? -inputsused : inputsused ) + { + + case 0: + /* No sound whatsoever, the attenuation is irrelevant */ + memset ( mixer_buffer, 0x80, mixer_buffer_size ) ; + amount_left = 0 ; + if ( mixer_gain < 0x100 ) mixer_gain ++; + break ; + + case 1: + /* One sample, so overflow is impossible. No legacy attenuation */ + psp[0] -> read ( mixer_buffer_size, mixer_buffer ) ; + break ; + + case 2: + { register int l = mixer_buffer_size ; + register Uchar *d = mixer_buffer, *a, *b ; + register int t, x = l / 100 ; + psp[0] -> read ( l, a = mixer_inputs [ 0 ] ) ; + psp[1] -> read ( l, b = mixer_inputs [ 1 ] ) ; + while ( l-- ) + { t = (*a++) - 0x80 + (*b++) ; + *d++ = ( t >= 0x100 ? x--, 0xff : + ( t <= 0x000 ? x--, 0x00 : t ) ); + } + if ( x < 0 ) mixer_gain -- ; + } break; + + case 3: + { register int l = mixer_buffer_size ; + register Uchar *d = mixer_buffer, *a, *b, *c ; + register int t, x = l / 100 ; + psp[0] -> read ( l, a = mixer_inputs [ 0 ] ) ; + psp[1] -> read ( l, b = mixer_inputs [ 1 ] ) ; + psp[2] -> read ( l, c = mixer_inputs [ 2 ] ) ; + while ( l-- ) *d++ = ( t = (*a++) - 0x100 + + (*b++) + + (*c++) ), + t >= 0x100 ? x--, 0xff : + t <= 0x000 ? x--, 0x00 : t; + if ( x < 0 ) mixer_gain -- ; + } break; + + default: + { /* How much data to get, and where to put it */ + int l = mixer_buffer_size ; + register Uchar *d = mixer_buffer ; + /* We compute one value in here, in the loop below */ + register int t ; + /* We need to determine the maximum range of values */ + int tmax = 0x80, tmin = 0x80; + /* A pointer to the element about to be added to "t" */ + register Uchar **p ; + /* Sound cards use offset binary, so do zero adjustment */ + int z = ( (int) 0x8000 / mixer_gain ) - ( inputsused * 0x80 ) ; + /* An array of pointers to keep in step with "d" above */ + register Uchar * s [ SL_MAX_MIXERINPUTS + 1 ] ; + /* First thing is to read individual channels into buffers */ + for ( i = 0; i < inputsused; i++ ) + psp[i] -> read ( l, s [ i ] = mixer_inputs [ i ] ); + /* Put a null on the end of "s" so we don't have to count */ + s [ inputsused ] = NULL; + /* This while loop is executed for each audio sample */ + while ( l-- ) + { /* Accumulation to zero, and point to first buffer item */ + t = z; + p = s; + /* Iterate through all buffers to do accumulation */ + while ( /* Add this buffer element, advance within buffer */ + t += *((*p)++), + /* Also advance to the next channel buffer */ + *(++p) + /* Make the while loop quit when we find NULL */ + ) { }; + /* Apply gain correction if needed */ + if ( mixer_gain != 0x100 ) + t = ( t * mixer_gain ) / 0x100 ; + /* Store accumulation, but force onscale */ + *(d++) = t >= 0x100 ? 0xff : + t <= 0x000 ? 0x00 : t ; + /* Figure out the maximum signal range */ + if ( tmax < t ) tmax = t ; + else + if ( tmin > t ) tmin = t ; + } + /* Consider changing the attenuation */ + if ( ( ( tmin < 0x00 ) || ( tmax > 0xFF ) ) + && ( mixer_gain > 1 ) ) + mixer_gain -- ; + else + if ( ( tmin * ( mixer_gain + 1 ) > 0x80 + 0x10 * mixer_gain ) + && ( tmax * ( mixer_gain + 1 ) < 0x80 + 0xE0 * mixer_gain ) + && ( mixer_gain < 0x100 ) ) + mixer_gain ++ ; + // printf ( "Gain=%03x, Range=%04x,%04x\n", mixer_gain, tmin, tmax ); + } break; + } + + /* We've created the next buffer of sound data ... now what ? */ + + 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 ( notWorking () ) return ; + + if ( num_pending_callbacks >= SL_MAX_CALLBACKS ) + { + ulSetError ( UL_WARNING, "slScheduler: Too many pending callback events!" ) ; + return ; + } + + slPendingCallBack *p = & ( pending_callback [ num_pending_callbacks++ ] ) ; + + p -> callback = c ; + p -> sample = s ; + p -> event = e ; + p -> magic = m ; +} + +void slScheduler::flushCallBacks () +{ + if ( notWorking () ) 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 ) ; + } +} + +void slScheduler::addSampleEnvelope ( slSample *s, int magic, + int slot, slEnvelope *e, + slEnvelopeType t) +{ + if ( notWorking () ) return ; + + for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ ) + if ( player [ i ] != NULL && player[i] != music && + ( s == NULL || player [ i ] -> getSample () == s ) && + ( magic == 0 || player [ i ] -> getMagic () == magic ) ) + player [ i ] -> addEnvelope ( slot, e, t ) ; +} + +void slScheduler::resumeSample ( slSample *s, int magic) +{ + if ( notWorking () ) return ; + + for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ ) + if ( player [ i ] != NULL && player[i] != music && + ( s == NULL || player [ i ] -> getSample () == s ) && + ( magic == 0 || player [ i ] -> getMagic () == magic ) ) + player [ i ] -> resume () ; +} + +void slScheduler::pauseSample ( slSample *s, int magic) +{ + if ( notWorking () ) return ; + + for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ ) + if ( player [ i ] != NULL && player[i] != music && + ( s == NULL || player [ i ] -> getSample () == s ) && + ( magic == 0 || player [ i ] -> getMagic () == magic ) ) + player [ i ] -> pause () ; +} + +void slScheduler::stopSample ( slSample *s, int magic ) +{ + if ( notWorking () ) return ; + + for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ ) + if ( player [ i ] != NULL && player[i] != music && + ( s == NULL || player [ i ] -> getSample () == s ) && + ( magic == 0 || player [ i ] -> getMagic () == magic ) ) + player [ i ] -> stop () ; +} + +int slScheduler::loopSample ( slSample *s, int pri, + slPreemptMode mode, + int magic, slCallBack cb ) +{ + if ( notWorking () ) return -1 ; + + for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ ) + if ( player [ i ] == NULL ) + { + player [ i ] = new slSamplePlayer ( s, SL_SAMPLE_LOOP, pri, mode, magic, cb ) ; + return i ; + } + + return -1 ; +} + +int slScheduler::playSample ( slSample *s, int pri, + slPreemptMode mode, + int magic, slCallBack cb) +{ + if ( notWorking () ) return SL_FALSE ; + + for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ ) + if ( player [ i ] == NULL ) + { + player [ i ] = new slSamplePlayer ( s, SL_SAMPLE_ONE_SHOT, pri, mode, magic, cb ) ; + return SL_TRUE ; + } + + return SL_FALSE ; +} + +void slScheduler::addMusicEnvelope ( int magic, + int slot, slEnvelope *e, + slEnvelopeType t) +{ + if ( notWorking () ) return ; + + if ( music != NULL && + ( magic == 0 || music -> getMagic () == magic ) ) + music -> addEnvelope ( slot, e, t ) ; +} + +void slScheduler::resumeMusic ( int magic) +{ + if ( notWorking () ) return ; + + if ( music != NULL && + ( magic == 0 || music -> getMagic () == magic ) ) + music -> resume () ; +} + +void slScheduler::pauseMusic ( int magic) +{ + if ( notWorking () ) return ; + + if ( music != NULL && + ( magic == 0 || music -> getMagic () == magic ) ) + music -> pause () ; +} + +void slScheduler::stopMusic ( int magic ) +{ + if ( notWorking () ) return ; + + if ( music != NULL && + ( magic == 0 || music -> getMagic () == magic ) ) + { + music -> stop () ; + + for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ ) + if ( player [ i ] == music ) + player [ i ] = NULL ; + + delete music ; + music = NULL ; + } +} + +int slScheduler::loopMusic ( const char *fname, int pri, + slPreemptMode mode, + int magic, slCallBack cb ) +{ + if ( notWorking () ) return -1 ; + + if ( music != NULL ) + { + ulSetError ( UL_WARNING, "slScheduler: Can't play two music tracks at once." ) ; + return -1 ; + } + + for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ ) + if ( player [ i ] == NULL ) + { + music = new slMODPlayer ( fname, SL_SAMPLE_LOOP, + pri, mode, magic, cb ) ; + player [ i ] = music ; + return i ; + } + + return -1 ; +} + +int slScheduler::playMusic ( const char *fname, int pri, + slPreemptMode mode, + int magic, slCallBack cb ) +{ + if ( notWorking () ) return SL_FALSE ; + + if ( music != NULL ) + { + ulSetError ( UL_WARNING, "slScheduler: Can't play two music tracks at once." ) ; + return SL_FALSE ; + } + + for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ ) + if ( player [ i ] == NULL ) + { + music = new slMODPlayer ( fname, SL_SAMPLE_ONE_SHOT, + pri, mode, magic, cb ) ; + player [ i ] = music ; + + return SL_TRUE ; + } + + return SL_FALSE ; +} + + diff --git a/src/sl/sm.h b/src/sl/sm.h new file mode 100644 index 0000000..236d60c --- /dev/null +++ b/src/sl/sm.h @@ -0,0 +1,111 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: sm.h 1732 2002-11-30 00:41:50Z sjbaker $ +*/ + + +#ifndef __SM_H__ +#define __SM_H__ 1 + +#include "slPortability.h" + +#ifdef SL_USING_OSS_AUDIO +#define SMMIXER_DEFAULT_DEVICE "/dev/mixer" +#elif defined(UL_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 + + 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 ( const char *device ) ; + void close () ; + +public: + + /* Tom */ + + smMixer (); + smMixer ( const char *device ); + ~smMixer (); + + int notWorking () const ; + int not_working () const { return notWorking () ; } /* Originally a typo! */ + + /* 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/src/sl/smMixer.cxx b/src/sl/smMixer.cxx new file mode 100644 index 0000000..9442a3f --- /dev/null +++ b/src/sl/smMixer.cxx @@ -0,0 +1,279 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: smMixer.cxx 1732 2002-11-30 00:41:50Z sjbaker $ +*/ + +#include "sm.h" + +#ifdef SL_USING_OSS_AUDIO +/* ------------------------------------------------------------ */ +/* OSSAUDIO - Linux, FreeBSD */ +/* ------------------------------------------------------------ */ + + +void smMixer::open ( const 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 ( const char *device ) +{ + open ( device ) ; +} + +smMixer::~smMixer () +{ + close () ; +} + +int smMixer::notWorking () const +{ + 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(UL_BSD) + +/* ------------------------------------------------------------ */ +/* NetBSD or OpenBSD 2.3 */ +/* ------------------------------------------------------------ */ + +void smMixer::open ( const char *device ) +{ +} + +void smMixer::close (){} + +smMixer::smMixer () {} +smMixer::smMixer ( const char * ) {} +smMixer::~smMixer () {} + +int smMixer::notWorking () const +{ + 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 ( const char * ) {} + +void smMixer::close (){} + +smMixer::smMixer () {} +smMixer::smMixer ( const char * ) {} +smMixer::~smMixer () {} + +int smMixer::notWorking () const +{ + 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/src/ssg/Makefile.am b/src/ssg/Makefile.am new file mode 100644 index 0000000..bdfeac8 --- /dev/null +++ b/src/ssg/Makefile.am @@ -0,0 +1,37 @@ +if BUILD_SSG + +lib_LIBRARIES = libplibssg.a + +include_HEADERS = ssg.h ssgconf.h ssgMSFSPalette.h ssgKeyFlier.h pcx.h + +libplibssg_a_SOURCES = ssg.cxx ssgAnimation.cxx ssgBase.cxx \ + ssgBaseTransform.cxx ssgBranch.cxx ssgContext.cxx ssgCutout.cxx \ + ssgDList.cxx ssgEntity.cxx ssgIsect.cxx ssgLeaf.cxx ssgList.cxx \ + ssgLoadDOF.cxx ssgLoadAC.cxx \ + ssgLocal.h ssgOptimiser.cxx ssgRoot.cxx ssgSaveAC.cxx \ + ssgSelector.cxx ssgSimpleState.cxx ssgState.cxx ssgStateTables.cxx \ + ssgStats.cxx ssgTween.cxx ssgTweenController.cxx \ + ssgTexTrans.cxx ssgTexture.cxx ssgTransform.cxx \ + ssgStateSelector.cxx ssgRangeSelector.cxx ssgLoadTexture.cxx \ + ssgLoadBMP.cxx ssgLoadSGI.cxx ssgLoadPNG.cxx ssgLoadTGA.cxx \ + ssgLoadPCX.cxx ssgInvisible.cxx ssgLoadSSG.cxx ssgVTable.cxx \ + ssgSimpleList.cxx ssgVtxTable.cxx ssgIO.cxx ssgLoad3ds.cxx \ + ssgSaveASE.cxx ssgLoadASE.cxx ssgParser.cxx ssgParser.h \ + ssgLoadDXF.cxx ssgSaveDXF.cxx ssgLoadTRI.cxx ssgSaveTRI.cxx \ + ssgLoadOBJ.cxx ssgSaveOBJ.cxx ssgVtxArray.cxx ssgLoadMD2.cxx \ + ssgLoadMDL.cxx ssgLoadX.cxx ssgSaveX.cxx ssgLoaderWriterStuff.cxx \ + ssgLoadFLT.cxx ssgLoadM.cxx ssgSaveM.cxx ssgLoadStrip.cxx \ + ssgLoadOFF.cxx ssgSaveOFF.cxx ssgSaveQHI.cxx ssgLoadVRML1.cxx \ + ssgSaveVRML1.cxx ssgLoaderWriterStuff.h ssgMSFSPalette.h ssg3ds.h \ + ssgLoadMDL.h ssgSave3ds.cxx ssgAxisTransform.cxx ssgLoadATG.cxx \ + ssgSaveFLT.cxx ssgSaveATG.cxx ssgLoadIV.cxx ssgLoad.cxx ssgLoadVRML.h \ + ssgLoadMDL_BGLTexture.cxx ssgLoadXPlaneObj.cxx ssgLoadASC.cxx ssgSaveASC.cxx \ + ssgSaveIV.cxx ssgAnimTransform.cxx\ + ssgVertSplitter.h ssgVertSplitter.cxx ssgStatistics.cxx + +INCLUDES = -I$(top_srcdir)/src/sg -I$(top_srcdir)/src/util + +endif + +EXTRA_DIST = ssg.dsp + diff --git a/src/ssg/pcx.h b/src/ssg/pcx.h new file mode 100644 index 0000000..66b4cc5 --- /dev/null +++ b/src/ssg/pcx.h @@ -0,0 +1,86 @@ +// Loading of the PCX texture file format +// +// This file is used for both PLIB and for BoB. +// +// Written by Wolfram Kuss in december 2003 +// +// This file is published as public domain + + +struct pcxHeaderType + { + char manufacturer; // always 10 + char version; // usually 5 + char encoding; // 1 = RLE + char bitsPerPixel; // number of bits to represent a pixel + short x, y; // upper left coordinates + short xmax, ymax; + short hDPI, vDPI; // DPI + char egaPalette[48]; // obsolete + char reserved; // unused, always 0 + char nColorPlanes; // number of color planes. not implemented yet? + short bytesPerLine; // bytes per scan line. not implemented yet? todo kludge + short paletteInfo; // colored or grey scale. not implemented yet? + short hScreenSize, cScreenSize; + char padding[54]; // reserved, always 0 + }; + + +#define READ_BYTE (buffer[0]); buffer++; +#define READ_SHORT ((((unsigned long)buffer[0])<<8) + buffer[1]); buffer += 2; +#define READ_LONG ((((unsigned long)buffer[0])<<24) + (((unsigned long)buffer[1])<<16) + (((unsigned long)buffer[2])<<8) + buffer[3]); buffer += 4; + + +// It is bad style to have a function inside a header file, but this way there is only one file +// I need to "synchronise" between PLIB and BoB. + +static int ReadPCXBody(UByte*& buffer, pcxHeaderType *ppcxHeader, UByte * pBody) +// returns TRUE on success. +// reads from buffer (which will normally just hold the file contents, but in memory, +// writes to pBody, which must have been allocated +{ + unsigned short x,y; + + if ((ppcxHeader->bitsPerPixel != 8) // unsupported pcx + || (ppcxHeader->encoding>1) // invalid PCX + // || (pcxHeader.nColorPlanes != 1) // unsupported pcx + || (ppcxHeader->manufacturer != 10)) // invalid pcx + return (FALSE); + + unsigned short width = ppcxHeader->xmax-ppcxHeader->x+1; + + x=0; y=0; // upper left coordinates + for(;;) + { + UByte color = READ_BYTE; + if ((color &0xC0) != 0xC0) // uncompressed? + { + *pBody++ = color; + x++; + if (x >= width) + { x=0; y++; // next line + if(y > ppcxHeader->ymax-ppcxHeader->y) + break; + } + } + else + { + UByte counter, length = color & 0x3F; // number of times next byte repeated + color = READ_BYTE; + for (counter=0; counter= width) + { x=0; y++; // next line + counter=length; + if(y > ppcxHeader->ymax-ppcxHeader->y) + break; // breaks for (counter=0; counte... + } + } + if(y > ppcxHeader->ymax-ppcxHeader->y) + break; // breaks for(;;) + } + } + return TRUE; +} diff --git a/src/ssg/ssg.cxx b/src/ssg/ssg.cxx new file mode 100644 index 0000000..fec2fce --- /dev/null +++ b/src/ssg/ssg.cxx @@ -0,0 +1,523 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssg.cxx 2171 2012-08-14 17:52:40Z wolfram_kuss $ +*/ + + +#define _UL_GENERATE_CODE_ +#include "ssgLocal.h" + +#if defined(UL_MACINTOSH) +# include +#elif defined(UL_MAC_OSX) +# include +#elif defined(UL_WIN32) + /* Nothing */ +#else +# include +#endif + +static bool glIsValidContext ( void ) +{ +#if defined(CONSOLE) + return true ; +#elif defined(UL_WIN32) + return ( wglGetCurrentContext () != NULL ) ; +#elif defined(UL_MACINTOSH) + return ( aglGetCurrentContext () != NULL ) ; +#elif defined(UL_MAC_OSX) + return ( CGLGetCurrentContext () != NULL ) ; +#else + return ( glXGetCurrentContext () != NULL ) ; +#endif +} + +sgMat4 _ssgOpenGLAxisSwapMatrix = +{ + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 1.0f } +} ; + +sgVec3 _ssgVertex000 = { 0.0f, 0.0f, 0.0f } ; +sgVec4 _ssgColourWhite = { 1.0f, 1.0f, 1.0f, 1.0f } ; +sgVec3 _ssgNormalUp = { 0.0f, 0.0f, 1.0f } ; +sgVec2 _ssgTexCoord00 = { 0.0f, 0.0f } ; +short _ssgIndex0 = 0; +bool _ssgBackFaceCollisions = false ; + +void ssgSetBackFaceCollisions ( bool b ) { _ssgBackFaceCollisions = b ; } + +static ssgLight _ssgLights [ 8 ] ; +static int _ssgFrameCounter = 0 ; + +int ssgGetFrameCounter () { return _ssgFrameCounter ; } +void ssgSetFrameCounter ( int fc ) { _ssgFrameCounter = fc ; } + +const char *ssgGetVersion () +{ +#ifdef VERSION + return VERSION ; +#else + return "Unknown" ; +#endif +} + +void ssgDeRefDelete ( ssgBase *s ) +{ + if ( s == NULL ) return ; + + s -> deRef () ; + + if ( s -> getRef () <= 0 ) + delete s ; +} + +void ssgDelete ( ssgBranch *br ) +{ + if ( br == NULL ) + return ; + + br -> removeAllKids () ; + delete br ; +} + +ssgLight *ssgGetLight ( int i ) +{ + return &_ssgLights [ i ] ; +} + +void ssgInit () +{ +#ifndef NO_GFX_DISPLAY + if ( ! glIsValidContext () ) + { + ulSetError ( UL_FATAL, "ssgInit called without a valid OpenGL context."); + } +#endif + + ssgTexturePath ( "." ) ; + ssgModelPath ( "." ) ; + +#ifndef NO_GFX_DISPLAY + _ssgLights [ 0 ] . setID ( 0 ) ; + _ssgLights [ 0 ] . on () ; + + for ( int i = 1 ; i < 8 ; i++ ) + { + _ssgLights [ i ] . setID ( i ) ; + _ssgLights [ i ] . off () ; + } +#endif + + + new ssgContext ; /* Sets the current context with defaults */ + + ssgAddModelFormat ( ".ssg", ssgLoadSSG , ssgSaveSSG ) ; + + ssgAddModelFormat ( ".3ds", ssgLoad3ds , ssgSave3ds ) ; + ssgAddModelFormat ( ".ac" , ssgLoadAC3D , ssgSaveAC ) ; + ssgAddModelFormat ( ".ase", ssgLoadASE , ssgSaveASE ) ; + ssgAddModelFormat ( ".dof", ssgLoadDOF , NULL ) ; + ssgAddModelFormat ( ".dxf", ssgLoadDXF , ssgSaveDXF ) ; + ssgAddModelFormat ( ".obj", ssgLoadOBJ , ssgSaveOBJ ) ; + ssgAddModelFormat ( ".tri", ssgLoadTRI , ssgSaveTRI ) ; + ssgAddModelFormat ( ".md2", ssgLoadMD2 , NULL ) ; + ssgAddModelFormat ( ".x" , ssgLoadX , ssgSaveX ) ; + ssgAddModelFormat ( ".flt", ssgLoadFLT , ssgSaveFLT ) ; + ssgAddModelFormat ( ".strip", ssgLoadStrip, NULL ) ; + ssgAddModelFormat ( ".m" , ssgLoadM , ssgSaveM ) ; + ssgAddModelFormat ( ".off" , ssgLoadOFF , ssgSaveOFF ) ; + ssgAddModelFormat ( ".atg" , ssgLoadATG , ssgSaveATG ) ; + ssgAddModelFormat ( ".qhi" , NULL , ssgSaveQHI ) ; + ssgAddModelFormat ( ".wrl", ssgLoadVRML1, ssgSaveVRML1 ) ; + ssgAddModelFormat ( ".iv", ssgLoadIV , ssgSaveIV ) ; + ssgAddModelFormat ( ".asc", ssgLoadASC , ssgSaveASC ) ; +//ssgAddModelFormat ( ".pov", NULL , ssgSavePOV ) ; + + +#ifdef SSG_LOAD_MDL_SUPPORTED + ssgAddModelFormat ( ".mdl", ssgLoadMDL , NULL ) ; +#endif + +#ifdef SSG_LOAD_TGA_SUPPORTED + ssgAddTextureFormat ( ".tga" , ssgLoadTGA ) ; +#endif + +#ifdef SSG_LOAD_BMP_SUPPORTED + ssgAddTextureFormat ( ".bmp" , ssgLoadBMP ) ; +#endif + +#ifdef SSG_LOAD_PNG_SUPPORTED + ssgAddTextureFormat ( ".png" , ssgLoadPNG ) ; +#endif + +#ifdef SSG_LOAD_PCX_SUPPORTED + ssgAddTextureFormat ( ".pcx" , ssgLoadPCX ) ; +#endif + +#ifdef SSG_LOAD_SGI_SUPPORTED + ssgAddTextureFormat ( ".rgb" , ssgLoadSGI ) ; + ssgAddTextureFormat ( ".rgba" , ssgLoadSGI ) ; + ssgAddTextureFormat ( ".int" , ssgLoadSGI ) ; + ssgAddTextureFormat ( ".inta" , ssgLoadSGI ) ; + ssgAddTextureFormat ( ".bw" , ssgLoadSGI ) ; +#endif + +#if defined(SSG_LOAD_MDL_SUPPORTED) || defined(SSG_LOAD_MDL_BGL_TEXTURE_SUPPORTED) + ssgAddTextureFormat ( ".0af" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".1af" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".2af" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".3af" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".4af" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".5af" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".6af" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".7af" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".8af" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".9af" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".aaf" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".baf" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".caf" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".daf" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".eaf" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".faf" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".gaf" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".haf" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".iaf" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".jaf" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".kaf" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".pat" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".r8" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".naz" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".ktx" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".oav" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".sky" , ssgLoadMDLTexture ) ; + ssgAddTextureFormat ( ".ngt" , ssgLoadMDLTexture ) ; +#endif + +#ifdef SSG_LOAD_XPL_SUPPORTED + ssgAddModelFormat ( ".xpl", ssgLoadXPlaneOBJ , NULL ) ; +#endif +} + + + +void ssgCullAndPick ( ssgBranch *r, sgVec2 botleft, sgVec2 topright ) +{ + if ( _ssgCurrentContext == NULL ) + { + ulSetError ( UL_FATAL, "ssg: No Current Context: Did you forgot to call ssgInit()?" ) ; + } + + ssgForceBasicState () ; + + GLint vp [ 4 ] ; + sgVec4 viewport ; + sgMat4 mat ; + + float w = (topright[0] - botleft[0]) ; + float h = (topright[1] - botleft[1]) ; + + float x = (botleft[0] + topright[0]) / 2.0f ; + float y = (botleft[1] + topright[1]) / 2.0f ; + + glGetIntegerv ( GL_VIEWPORT, vp ) ; + + sgSetVec4 ( viewport, (float)vp[0], (float)vp[1], + (float)vp[2], (float)vp[3] ) ; + sgMakePickMatrix ( mat, x, y, w, h, viewport ) ; + + glMatrixMode ( GL_PROJECTION ) ; + glLoadIdentity () ; + glMultMatrixf ( (float *) mat ) ; + + _ssgCurrentContext->pushProjectionMatrix () ; + + glMatrixMode ( GL_MODELVIEW ) ; + glLoadIdentity () ; + + int i ; + + for ( i = 0 ; i < 8 ; i++ ) + if ( _ssgLights [ i ] . isHeadlight () ) + _ssgLights [ i ] . setup () ; + + _ssgCurrentContext->loadModelviewMatrix () ; + + for ( i = 0 ; i < 8 ; i++ ) + if ( ! _ssgLights [ i ] . isHeadlight () ) + _ssgLights [ i ] . setup () ; + + _ssgCurrentContext->cull(r) ; + _ssgDrawDList () ; + + glMatrixMode ( GL_MODELVIEW ) ; + glLoadIdentity () ; +} + + +void ssgCullAndDraw ( ssgBranch *r ) +{ + if ( _ssgCurrentContext == NULL ) + { + ulSetError ( UL_FATAL, "ssg: No Current Context: Did you forgot to call ssgInit()?" ) ; + } + + _ssgStartOfFrameInit () ; + + ssgForceBasicState () ; + + glMatrixMode ( GL_PROJECTION ) ; + _ssgCurrentContext->loadProjectionMatrix () ; + + glMatrixMode ( GL_MODELVIEW ) ; + glLoadIdentity () ; + + int i ; + + for ( i = 0 ; i < 8 ; i++ ) + if ( _ssgLights [ i ] . isHeadlight () ) + _ssgLights [ i ] . setup () ; + + _ssgCurrentContext->loadModelviewMatrix () ; + _ssgCurrentContext->applyClipPlanes () ; + + for ( i = 0 ; i < 8 ; i++ ) + if ( ! _ssgLights [ i ] . isHeadlight () ) + _ssgLights [ i ] . setup () ; + + _ssgCurrentContext->cull(r) ; + _ssgDrawDList () ; + + _ssgCurrentContext->removeClipPlanes () ; + + glMatrixMode ( GL_MODELVIEW ) ; + glLoadIdentity () ; + + _ssgEndOfFrameCleanup () ; + _ssgFrameCounter++ ; +} + + +const char *ssgAxisTransform::getTypeName (void) { return "ssgAxisTransform" ; } +const char *ssgBase ::getTypeName (void) { return "ssgBase" ; } +const char *ssgTexture ::getTypeName (void) { return "ssgTexture" ; } +const char *ssgState ::getTypeName (void) { return "ssgState" ; } +const char *ssgSimpleState ::getTypeName (void) { return "ssgSimpleState" ; } +const char *ssgStateSelector::getTypeName (void) { return "ssgStateSelector" ; } +const char *ssgEntity ::getTypeName (void) { return "ssgEntity" ; } +const char *ssgLeaf ::getTypeName (void) { return "ssgLeaf" ; } +const char *ssgVTable ::getTypeName (void) { return "ssgVTable" ; } +const char *ssgVtxTable ::getTypeName (void) { return "ssgVtxTable" ; } +const char *ssgVtxArray ::getTypeName (void) { return "ssgVtxArray" ; } +const char *ssgBranch ::getTypeName (void) { return "ssgBranch" ; } +const char *ssgSelector ::getTypeName (void) { return "ssgSelector" ; } +const char *ssgRangeSelector::getTypeName (void) { return "ssgRangeSelector" ; } +const char *ssgTimedSelector::getTypeName (void) { return "ssgTimedSelector" ; } +const char *ssgBaseTransform::getTypeName (void) { return "ssgBaseTransform" ; } +const char *ssgTransform ::getTypeName (void) { return "ssgTransform" ; } +const char *ssgTexTrans ::getTypeName (void) { return "ssgTexTrans" ; } +const char *ssgCutout ::getTypeName (void) { return "ssgCutout" ; } +const char *ssgRoot ::getTypeName (void) { return "ssgRoot" ; } + +const char *ssgSimpleList ::getTypeName (void) { return "ssgSimpleList" ; } +const char *ssgColourArray ::getTypeName (void) { return "ssgColourArray" ; } +const char *ssgIndexArray ::getTypeName (void) { return "ssgIndexArray" ; } +const char *ssgTransformArray::getTypeName (void) { return "ssgTransformArray" ; } +const char *ssgTexCoordArray::getTypeName (void) { return "ssgTexCoordArray" ; } +const char *ssgVertexArray ::getTypeName (void) { return "ssgVertexArray" ; } +const char *ssgNormalArray ::getTypeName (void) { return "ssgNormalArray" ; } +const char *ssgInterleavedArray::getTypeName (void) { return "ssgInterleavedArray"; } + + + +static ssgBase *createBase () { return new ssgBase ; } + +//static ssgBase *createEntity () { return new ssgEntity ; } +//static ssgBase *createLeaf () { return new ssgLeaf ; } +static ssgBase *createVTable () { return new ssgVTable ; } +static ssgBase *createVtxTable () { return new ssgVtxTable ; } +static ssgBase *createVtxArray () { return new ssgVtxArray ; } +static ssgBase *createTween () { return new ssgTween ; } +static ssgBase *createBranch () { return new ssgBranch ; } +//static ssgBase *createBaseTransform () { return new ssgBaseTransform ; } +static ssgBase *createTransform () { return new ssgTransform ; } +static ssgBase *createTexTrans () { return new ssgTexTrans ; } +static ssgBase *createAnimTransform() { return new ssgAnimTransform ; } +static ssgBase *createAxisTransform() { return new ssgAxisTransform ; } +static ssgBase *createSelector () { return new ssgSelector ; } +static ssgBase *createRangeSelector () { return new ssgRangeSelector ; } +static ssgBase *createTimedSelector () { return new ssgTimedSelector ; } +static ssgBase *createTweenController () { return new ssgTweenController ; } +static ssgBase *createRoot () { return new ssgRoot ; } +static ssgBase *createCutout () { return new ssgCutout ; } +static ssgBase *createInvisible () { return new ssgInvisible ; } + +//static ssgBase *createState () { return new ssgState ; } +static ssgBase *createSimpleState () { return new ssgSimpleState ; } +static ssgBase *createStateSelector () { return new ssgStateSelector ; } + +static ssgBase *createSimpleList () { return new ssgSimpleList ; } +static ssgBase *createVertexArray () { return new ssgVertexArray ; } +static ssgBase *createNormalArray () { return new ssgNormalArray ; } +static ssgBase *createTexCoordArray () { return new ssgTexCoordArray ; } +static ssgBase *createColourArray () { return new ssgColourArray ; } +static ssgBase *createIndexArray () { return new ssgIndexArray ; } +static ssgBase *createTransformArray () { return new ssgTransformArray ; } +static ssgBase *createInterleavedArray () { return new ssgInterleavedArray ; } + +static ssgBase *createTexture () { return new ssgTexture ; } + + +static struct { + + int type ; + ssgBase * ( *func ) () ; + +} table[256] = { + + { ssgTypeBase () , createBase }, + +//{ ssgTypeEntity () , createEntity }, +//{ ssgTypeLeaf () , createLeaf }, + { ssgTypeVTable () , createVTable }, + { ssgTypeVtxTable () , createVtxTable }, + { ssgTypeVtxArray () , createVtxArray }, + { ssgTypeTween () , createTween }, + { ssgTypeBranch () , createBranch }, +//{ ssgTypeBaseTransform () , createBaseTransform }, + { ssgTypeTransform () , createTransform }, + { ssgTypeAnimTransform () , createAnimTransform }, + { ssgTypeTexTrans () , createTexTrans }, + { ssgTypeAxisTransform () , createAxisTransform }, + { ssgTypeSelector () , createSelector }, + { ssgTypeRangeSelector () , createRangeSelector }, + { ssgTypeTimedSelector () , createTimedSelector }, + { ssgTypeTweenController () , createTweenController }, + { ssgTypeRoot () , createRoot }, + { ssgTypeCutout () , createCutout }, + { ssgTypeInvisible () , createInvisible }, + +//{ ssgTypeState () , createState }, + { ssgTypeSimpleState () , createSimpleState }, + { ssgTypeStateSelector () , createStateSelector }, + + { ssgTypeSimpleList () , createSimpleList }, + { ssgTypeVertexArray () , createVertexArray }, + { ssgTypeNormalArray () , createNormalArray }, + { ssgTypeTexCoordArray () , createTexCoordArray }, + { ssgTypeColourArray () , createColourArray }, + { ssgTypeIndexArray () , createIndexArray }, + { ssgTypeTransformArray () , createTransformArray }, + { ssgTypeInterleavedArray () , createInterleavedArray }, + + { ssgTypeTexture () , createTexture }, + + { 0, NULL } + +}; + +void ssgRegisterType ( int type, ssgBase * ( *func ) () ) +{ + if ( type == 0 || func == NULL ) + { + ulSetError ( UL_WARNING, "ssgRegisterType: Bad arguments (type %#x, func %p).", + type, func ) ; + return ; + } + + int i ; + for ( i = 0 ; table[i].type != 0 && table[i].type != type ; i++ ) + ; + + if ( table[i].type == type && table[i].func != func ) + ulSetError ( UL_WARNING, "ssgRegisterType: Type %#x redefined differently.", type ) ; + + table[i].type = type ; + table[i].func = func ; +} + +ssgBase *ssgCreateOfType ( int type ) +{ + // XXX linear search + int i ; + + for ( i = 0 ; table[i].type != 0 && table[i].type != type ; i++ ) + ; + + if ( table[i].type == 0 ) + { + ulSetError ( UL_WARNING, "ssgCreateOfType: Unrecognized type %#x.", type ) ; + return NULL ; + } + + ssgBase *obj = (*table[i].func) () ; + + if ( obj == NULL ) + ulSetError ( UL_WARNING, "ssgCreateOfType: Got null object for type %#x.", type ) ; + else if ( obj -> getType () != type ) + ulSetError ( UL_WARNING, + "ssgCreateOfType: Created object has wrong type %#x (%s), expected %#x.", + obj -> getType (), obj -> getTypeName (), type ) ; + + return obj ; +} + +static bool ssgSearchExtensionString(char *extString, char *extName) +{ + // Returns GL_TRUE if the *extName string appears in the *extString string, + // surrounded by white spaces, or GL_FALSE otherwise. + + char *p, *end; + int n, extNameLen; + + if ( ( extString == NULL ) || ( extName == NULL ) ) + return false; + + extNameLen = strlen ( extName ); + + p = extString; + end = p + strlen ( p ); + + while ( p < end ) + { + n = strcspn ( p, " " ); + if ( ( extNameLen == n ) && ( strncmp ( extName, p, n ) == 0 ) ) + return GL_TRUE; + + p += (n + 1); + } + + return GL_FALSE; +} + +bool ssgIsExtensionSupported(char *extName) +{ + // Returns GL_TRUE if the OpenGL Extension whose name is *extName + // is supported by the system, or GL_FALSE otherwise. + + // The *extName string must follow the OpenGL extensions naming scheme + // (ie: "GL_type_extension", like GL_EXT_convolution) + + return ssgSearchExtensionString ( (char *)glGetString(GL_EXTENSIONS), extName ); +} + diff --git a/src/ssg/ssg.dsp b/src/ssg/ssg.dsp new file mode 100644 index 0000000..8643d3c --- /dev/null +++ b/src/ssg/ssg.dsp @@ -0,0 +1,466 @@ +# Microsoft Developer Studio Project File - Name="ssg" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=ssg - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ssg.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ssg.mak" CFG="ssg - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ssg - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "ssg - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ssg - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "..\sg" /I "..\util" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "PROXY_TEXTURES_ARE_NOT_BROKEN" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy release\*.lib ..\..\*.* copy ssg.h ..\..\ssg.h copy ssgconf.h ..\..\ssgconf.h copy ssgMSFSPalette.h ..\..\ssgMSFSPalette.h copy ssgKeyFlier.h ..\..\ssgKeyFlier.h +# End Special Build Tool + +!ELSEIF "$(CFG)" == "ssg - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I "..\sg" /I "..\util" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "PROXY_TEXTURES_ARE_NOT_BROKEN" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\ssg_d.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy debug\*.lib ..\..\*.* copy ssg.h ..\..\ssg.h copy ssgconf.h ..\..\ssgconf.h copy ssgMSFSPalette.h ..\..\ssgMSFSPalette.h copy ssgKeyFlier.h ..\..\ssgKeyFlier.h +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "ssg - Win32 Release" +# Name "ssg - Win32 Debug" +# Begin Source File + +SOURCE=.\ssg.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssg.h +# End Source File +# Begin Source File + +SOURCE=.\ssg3ds.h +# End Source File +# Begin Source File + +SOURCE=.\ssgAnimation.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgAnimTransform.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgAxisTransform.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgBase.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgBaseTransform.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgBranch.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgconf.h +# End Source File +# Begin Source File + +SOURCE=.\ssgContext.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgCutout.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgDList.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgEntity.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgInvisible.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgIO.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgIsect.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgKeyFlier.h +# End Source File +# Begin Source File + +SOURCE=.\ssgLeaf.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgList.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoad.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoad3ds.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadAC.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadASC.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadASE.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadATG.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadBMP.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadDOF.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadDXF.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoaderWriterStuff.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoaderWriterStuff.h +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadFLT.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadIV.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadM.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadMD2.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadMDL.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadMDL.h +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadMDL_BGLTexture.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadOBJ.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadOFF.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadPCX.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadPNG.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadSGI.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadSSG.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadStrip.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadTexture.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadTGA.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadTRI.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadVRML.h +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadVRML1.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadX.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLoadXPlaneObj.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgLocal.h +# End Source File +# Begin Source File + +SOURCE=.\ssgMSFSPalette.h +# End Source File +# Begin Source File + +SOURCE=.\ssgOptimiser.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgParser.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgParser.h +# End Source File +# Begin Source File + +SOURCE=.\ssgRangeSelector.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgRoot.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSave3ds.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSaveAC.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSaveASC.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSaveASE.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSaveATG.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSaveDXF.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSaveFLT.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSaveIV.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSaveM.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSaveOBJ.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSaveOFF.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSaveQHI.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSaveTRI.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSaveVRML1.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSaveX.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSelector.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSimpleList.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgSimpleState.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgState.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgStateSelector.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgStateTables.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgStatistics.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgStats.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgTexTrans.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgTexture.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgTransform.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgTween.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgTweenController.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgVertSplitter.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgVertSplitter.h +# End Source File +# Begin Source File + +SOURCE=.\ssgVTable.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgVtxArray.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgVtxTable.cxx +# End Source File +# End Target +# End Project diff --git a/src/ssg/ssg.h b/src/ssg/ssg.h new file mode 100644 index 0000000..77d089b --- /dev/null +++ b/src/ssg/ssg.h @@ -0,0 +1,2883 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssg.h 2173 2012-08-24 13:18:22Z wolfram_kuss $ +*/ + + +#ifndef _INCLUDED_SSG_H_ +#define _INCLUDED_SSG_H_ + +#include +#include "sg.h" + +#ifdef UL_MAC_OSX +# include +#else +# include +#endif + +#include "ssgconf.h" + +#ifndef _SSG_PUBLIC +#define _SSG_PUBLIC protected +#endif + +extern int sgebug ; + +enum ssgCullResult +{ + SSG_OUTSIDE = SG_OUTSIDE, + SSG_INSIDE = SG_INSIDE, + SSG_STRADDLE = SG_STRADDLE +} ; + +#define SSG_MAXPATH 50 + +#define SSGTRAV_CULL 1 +#define SSGTRAV_ISECT 2 +#define SSGTRAV_HOT 4 +#define SSGTRAV_LOS 8 + +class ssgList ; +class ssgKidList ; +class ssgBase ; +class ssgEntity ; +class ssgLeaf ; +class ssgVTable ; +class ssgVtxTable ; +class ssgVtxArray ; +class ssgTween ; +class ssgBranch ; +class ssgInvisible ; +class ssgBaseTransform ; +class ssgTransform ; +class ssgTexTrans ; +class ssgCutout ; +class ssgSelector ; +class ssgRangeSelector ; +class ssgTimedSelector ; +class ssgTweenController ; +class ssgRoot ; + +void ssgDeRefDelete ( ssgBase *br ) ; + +/* + Think twice before assigning new type bits, it is rather complicated. + Perhaps some kind of automatic assignment would be good? + */ + +#define _SSG_BACKWARDS_REFERENCE 0x0000000 /* For SSG format files */ + +#define _SSG_TYPE_BASE 0x00000001 + +/* ssgEntities */ +#define _SSG_TYPE_ENTITY 0x00000002 +#define _SSG_TYPE_LEAF 0x00000020 +#define _SSG_TYPE_VTABLE 0x00000080 +#define _SSG_TYPE_VTXTABLE 0x00000100 +#define _SSG_TYPE_VTXARRAY 0x00000200 +#define _SSG_TYPE_BRANCH 0x00000040 +#define _SSG_TYPE_BASETRANSFORM 0x00000080 +#define _SSG_TYPE_TRANSFORM 0x00001000 +#define _SSG_TYPE_TEXTRANS 0x00002000 +#define _SSG_TYPE_AXISTRANSFORM 0x00004000 +#define _SSG_TYPE_ANIMTRANSFORM 0x00008000 +#define _SSG_TYPE_SELECTOR 0x00000100 +#define _SSG_TYPE_RANGESELECTOR 0x00001000 +#define _SSG_TYPE_TIMEDSELECTOR 0x00002000 +#define _SSG_TYPE_TWEEN 0x00008000 +#define _SSG_TYPE_TWEENCONTROLLER 0x00010000 +#define _SSG_TYPE_ROOT 0x00000200 +#define _SSG_TYPE_CUTOUT 0x00000400 +#define _SSG_TYPE_INVISIBLE 0x00000800 + +/* ssgStates */ +#define _SSG_TYPE_STATE 0x00000004 +#define _SSG_TYPE_SIMPLESTATE 0x00000020 +#define _SSG_TYPE_STATESELECTOR 0x00000040 + +/* ssgSimpleLists */ +#define _SSG_TYPE_SIMPLELIST 0x00000008 +#define _SSG_TYPE_VERTEXARRAY 0x00000020 +#define _SSG_TYPE_NORMALARRAY 0x00000040 +#define _SSG_TYPE_TEXCOORDARRAY 0x00000080 +#define _SSG_TYPE_COLOURARRAY 0x00000100 +#define _SSG_TYPE_INDEXARRAY 0x00000200 +#define _SSG_TYPE_TRANSFORMARRAY 0x00000400 +#define _SSG_TYPE_INTERLEAVEDARRAY 0x00000800 + +/* ssgTextures */ +#define _SSG_TYPE_TEXTURE 0x00000010 + +#define SSG_FILE_VERSION 0x01 +#define SSG_FILE_MAGIC_NUMBER (('S'<<24)+('S'<<16)+('G'<<8)+SSG_FILE_VERSION) + + +inline int ssgTypeBase () { return _SSG_TYPE_BASE ; } + +inline int ssgTypeEntity () { return _SSG_TYPE_ENTITY | ssgTypeBase () ; } +inline int ssgTypeLeaf () { return _SSG_TYPE_LEAF | ssgTypeEntity () ; } +inline int ssgTypeVTable () { return _SSG_TYPE_VTABLE | ssgTypeLeaf () ; } +inline int ssgTypeVtxTable () { return _SSG_TYPE_VTXTABLE | ssgTypeLeaf () ; } +inline int ssgTypeVtxArray () { return _SSG_TYPE_VTXARRAY | ssgTypeVtxTable() ; } +inline int ssgTypeTween () { return _SSG_TYPE_TWEEN | ssgTypeVtxTable() ; } +inline int ssgTypeBranch () { return _SSG_TYPE_BRANCH | ssgTypeEntity () ; } +inline int ssgTypeTweenController(){ return _SSG_TYPE_TWEENCONTROLLER | ssgTypeBranch() ; } +inline int ssgTypeBaseTransform() { return _SSG_TYPE_BASETRANSFORM | ssgTypeBranch () ; } +inline int ssgTypeTransform () { return _SSG_TYPE_TRANSFORM | ssgTypeBaseTransform () ; } +inline int ssgTypeAnimTransform() { return _SSG_TYPE_ANIMTRANSFORM | ssgTypeTransform () ; } +inline int ssgTypeTexTrans () { return _SSG_TYPE_TEXTRANS | ssgTypeBaseTransform () ; } +inline int ssgTypeAxisTransform() { return _SSG_TYPE_AXISTRANSFORM | ssgTypeTransform () ; } +inline int ssgTypeSelector () { return _SSG_TYPE_SELECTOR | ssgTypeBranch () ; } +inline int ssgTypeRangeSelector() { return _SSG_TYPE_RANGESELECTOR | ssgTypeSelector () ; } +inline int ssgTypeTimedSelector() { return _SSG_TYPE_TIMEDSELECTOR | ssgTypeSelector () ; } +inline int ssgTypeRoot () { return _SSG_TYPE_ROOT | ssgTypeBranch () ; } +inline int ssgTypeCutout () { return _SSG_TYPE_CUTOUT | ssgTypeBranch () ; } +inline int ssgTypeInvisible () { return _SSG_TYPE_INVISIBLE | ssgTypeBranch () ; } + +inline int ssgTypeState () { return _SSG_TYPE_STATE | ssgTypeBase () ; } +inline int ssgTypeSimpleState () { return _SSG_TYPE_SIMPLESTATE | ssgTypeState () ; } +inline int ssgTypeStateSelector() { return _SSG_TYPE_STATESELECTOR | ssgTypeSimpleState () ; } + +inline int ssgTypeSimpleList () { return _SSG_TYPE_SIMPLELIST | ssgTypeBase () ; } +inline int ssgTypeVertexArray () { return _SSG_TYPE_VERTEXARRAY | ssgTypeSimpleList () ; } +inline int ssgTypeNormalArray () { return _SSG_TYPE_NORMALARRAY | ssgTypeSimpleList () ; } +inline int ssgTypeTexCoordArray() { return _SSG_TYPE_TEXCOORDARRAY | ssgTypeSimpleList () ; } +inline int ssgTypeColourArray () { return _SSG_TYPE_COLOURARRAY | ssgTypeSimpleList () ; } +inline int ssgTypeIndexArray () { return _SSG_TYPE_INDEXARRAY | ssgTypeSimpleList () ; } +inline int ssgTypeTransformArray() { return _SSG_TYPE_TRANSFORMARRAY | ssgTypeSimpleList () ; } +inline int ssgTypeInterleavedArray() { return _SSG_TYPE_INTERLEAVEDARRAY | ssgTypeSimpleList () ; } + +inline int ssgTypeTexture () { return _SSG_TYPE_TEXTURE | ssgTypeBase () ; } + +/* + It's critical that these numbers don't change without + some pretty pressing need because significant change to + ssgSimpleState.cxx and ssgStateTables.cxx would be needed. +*/ + +#define SSG_GL_TEXTURE_EN 0 +#define SSG_GL_CULL_FACE_EN 1 +#define SSG_GL_COLOR_MATERIAL_EN 2 +#define SSG_GL_BLEND_EN 3 +#define SSG_GL_ALPHA_TEST_EN 4 +#define SSG_GL_LIGHTING_EN 5 + +#define SSG_GL_TEXTURE 6 +#define SSG_GL_COLOR_MATERIAL 7 +#define SSG_GL_DIFFUSE 8 +#define SSG_GL_AMBIENT 9 +#define SSG_GL_SPECULAR 10 +#define SSG_GL_EMISSION 11 +#define SSG_GL_SHININESS 12 +#define SSG_GL_ALPHA_TEST 13 +#define SSG_GL_SHADE_MODEL 14 + +#define SSG_CLONE_RECURSIVE 1 +#define SSG_CLONE_GEOMETRY 2 +#define SSG_CLONE_USERDATA 4 +#define SSG_CLONE_STATE 8 +#define SSG_CLONE_STATE_RECURSIVE 16 +#define SSG_CLONE_TEXTURE 32 + +int ssgGetFrameCounter () ; +void ssgSetFrameCounter ( int fc ) ; + +// Returns GL_TRUE if the OpenGL Extension whose name is *extName +// is supported by the system, or GL_FALSE otherwise. +bool ssgIsExtensionSupported(char *extName); + +class ssgList +{ +protected: + unsigned int total ; /* The total number of entities in the list */ + unsigned int limit ; /* The current limit on number of entities */ + unsigned int next ; /* The next entity when we are doing getNext ops */ + + ssgEntity **entity_list ; /* The list. */ + + void sizeChk (void) ; + +public: + + ssgList ( int init_max = 1 ) ; + virtual ~ssgList (void) ; + + ssgEntity *getEntity ( unsigned int n ) + { + next = n + 1 ; + return ( n >= total ) ? (ssgEntity *) NULL : entity_list [ n ] ; + } + + virtual void addEntity ( ssgEntity *entity ) ; + virtual void removeEntity ( unsigned int n ) ; + + void removeAllEntities () ; + + void removeEntity ( ssgEntity *entity ) + { + removeEntity ( searchForEntity ( entity ) ) ; + } + + virtual void replaceEntity ( unsigned int n, ssgEntity *new_entity ) ; + + void replaceEntity ( ssgEntity *old_entity, ssgEntity *new_entity ) + { + replaceEntity ( searchForEntity ( old_entity ), new_entity ) ; + } + + int getNumEntities (void) { return total ; } + ssgEntity *getNextEntity (void) { return getEntity ( next ) ; } + int searchForEntity ( ssgEntity *entity ) ; +} ; + + +class ssgKidList : public ssgList +{ +public: + + ssgKidList ( int init_max = 1 ) ; + virtual ~ssgKidList (void) ; + + void addEntity ( ssgEntity *entity ) ; + void removeEntity ( unsigned int n ) ; + + void removeEntity ( ssgEntity *entity ) + { + removeEntity ( searchForEntity ( entity ) ) ; + } + + void replaceEntity ( unsigned int n, ssgEntity *new_entity ) ; + + void replaceEntity ( ssgEntity *old_entity, ssgEntity *new_entity ) + { + replaceEntity ( searchForEntity ( old_entity ), new_entity ) ; + } +} ; + + +class ssgBase +{ + int refc ; /* The number of references to this node */ + int unique ; /* A unique number for this node */ + +protected : + + int type ; + int spare ; /* This spare field is used in a bunch of short-term hacks */ + + char *name ; + ssgBase *user_data ; + virtual void copy_from ( ssgBase *src, int clone_flags ) ; + +public: + void *operator new ( size_t size ) ; + void operator delete ( void *ptr ) ; + + void deadBeefCheck () { assert ( type != (int) 0xDeadBeef ) ; } + + virtual void zeroSpareRecursive (); + virtual void zeroSpare () ; + virtual void incSpare () ; + virtual void setSpare ( int ss ) ; + virtual int getSpare () ; + + int getUnique () { return unique ; } + + ssgBase (void) ; + virtual ~ssgBase (void) ; + + void ref () { refc++ ; } + void deRef () { assert ( refc > 0 ) ; refc-- ; } + int getRef() { return refc ; } + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + + /* Type checking mechanism */ + + virtual const char *getTypeName(void) ; + + int getType (void) { return type ; } + int isA ( int ty ) { return getType() == ty ; } + int isAKindOf ( int ty ) { return ( getType() & ty ) == ty ; } + + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; + + ssgBase *getUserData () { return user_data ; } + + void setUserData ( ssgBase *s ) + { + ssgDeRefDelete ( user_data ) ; + + user_data = s ; + if ( s != NULL ) + s -> ref () ; + } + + void setName ( const char *nm ) ; + char *getName () { return name ; } + const char *getPrintableName () { return (name == NULL) ? "NoName" : name ; } +} ; + + + +class ssgSimpleList : public ssgBase +{ +protected: + + unsigned int total ; /* The total number of things in the list */ + unsigned int limit ; /* The current limit on number of things */ + unsigned int size_of ; /* The size of each thing */ + char *list ; /* The list. */ + bool own_mem ; /* Do we own the list memory ? */ + + void sizeChk ( unsigned int n ) + { + if ( (total+n) > limit ) + { + if ( ! own_mem ) + ulSetError( UL_FATAL, "ssgSimpleList: Cannot resize array." ); + + /* how big should we make the list? */ + limit += limit ; /* double it */ + if ( limit <= 0 ) + limit = 3; + if ( (total+n) > limit ) + limit = (total+n) ; + + /* re-allocate the list */ + char *nlist = new char [ limit * size_of ] ; + memmove ( nlist, list, total * size_of ) ; + delete [] list ; + list = nlist ; + } + } + + virtual void copy_from ( ssgSimpleList *src, int clone_flags ) ; + +_SSG_PUBLIC: + + ssgSimpleList () + { + type = ssgTypeSimpleList () ; + limit = 0 ; + size_of = 0 ; + total = 0 ; + list = NULL ; + own_mem = true ; + } + +public: + + ssgSimpleList ( int sz, int init = 3, char* things = 0 ) + { + type = ssgTypeSimpleList () ; + limit = init ; + size_of = sz ; + if ( things ) + { + total = init ; + list = things ; + own_mem = false ; + } + else + { + total = 0 ; + list = new char [ limit * size_of ] ; + own_mem = true ; + } + } + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + + virtual ~ssgSimpleList (void) + { + if ( own_mem ) + delete [] list ; + list = NULL ; + } ; + + char *raw_get ( unsigned int n ) + { + return ( n >= total ) ? ((char *) 0) : & list [ n * size_of ] ; + } + + void raw_add ( char *thing ) + { + sizeChk ( 1 ) ; + memcpy ( & list [ size_of * total++ ], thing, size_of ) ; + } ; + + void raw_add ( char *things, unsigned int n ) + { + sizeChk ( n ) ; + memcpy ( & list [ size_of * total ], things, size_of * n ) ; + total += n ; + } + + void raw_set ( char *thing, unsigned int n ) + { + memcpy ( & list [ size_of * n ], thing, size_of ) ; + } ; + + void removeLast () + { + if ( total > 0 ) + total-- ; + } + + void removeAll () + { + if ( own_mem ) + delete [] list ; + list = NULL ; + limit = total = 0 ; + } + + int compare(ssgSimpleList *other, int print_result=TRUE); + int getSizeOf (void) { return size_of ; } + int getNum (void) { return total ; } + + void rawSetNum ( unsigned int n ) /* Better know what you're doing!! */ + { + total = n ; + } + + void setNum ( unsigned int n ) + { + if ( total < n ) + { + sizeChk ( n ) ; + memset ( & list [ size_of * total ], 0, size_of * (n-total) ) ; + total = n ; + } + } + + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; + virtual const char *getTypeName(void) ; +} ; + + +class ssgVertexArray : public ssgSimpleList +{ +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgVertexArray ( int init = 3, sgVec3* things = 0 ) + : ssgSimpleList ( sizeof(sgVec3), init, (char*)things ) + { + type = ssgTypeVertexArray () ; + } + float *get ( unsigned int n ) { return (float *) raw_get ( n ) ; } + void add ( sgVec3 thing ) { raw_add ( (char *) thing ) ; } ; + void set ( sgVec3 thing, unsigned int n ) { raw_set ( (char *) thing, n ) ; } ; + void set ( float x, float y, float z, unsigned int n ) + { sgVec3 tmp = { x, y, z } ; raw_set ( (char *) tmp, n ) ; } ; + void add ( float x, float y, float z ) + { sgVec3 tmp = { x, y, z } ; raw_add ( (char *) tmp ) ; } ; + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; + virtual const char *getTypeName(void) ; +} ; + + +class ssgNormalArray : public ssgSimpleList +{ +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgNormalArray ( int init = 3, sgVec3* things = 0 ) + : ssgSimpleList ( sizeof(sgVec3), init, (char*)things ) + { + type = ssgTypeNormalArray () ; + } + float *get ( unsigned int n ) { return (float *) raw_get ( n ) ; } + void add ( sgVec3 thing ) { raw_add ( (char *) thing ) ; } ; + void set ( sgVec3 thing, unsigned int n ) { raw_set ( (char *) thing, n ) ; } ; + void set ( float x, float y, float z, unsigned int n ) + { sgVec3 tmp = { x, y, z } ; raw_set ( (char *) tmp, n ) ; } ; + void add ( float x, float y, float z ) + { sgVec3 tmp = { x, y, z } ; raw_add ( (char *) tmp ) ; } ; + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; + virtual const char *getTypeName(void) ; +} ; + + +class ssgTexCoordArray : public ssgSimpleList +{ +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgTexCoordArray ( int init = 3, sgVec2* things = 0 ) + : ssgSimpleList ( sizeof(sgVec2), init, (char*)things ) + { + type = ssgTypeTexCoordArray () ; + } + float *get ( unsigned int n ) { return (float *) raw_get ( n ) ; } + void add ( sgVec2 thing ) { raw_add ( (char *) thing ) ; } ; + void set ( sgVec2 thing, unsigned int n ) { raw_set ( (char *) thing, n ) ; } ; + void set ( float u, float v, unsigned int n ) + { sgVec2 tmp = { u, v } ; raw_set ( (char *) tmp, n ) ; } ; + void add ( float u, float v ) + { sgVec2 tmp = { u, v } ; raw_add ( (char *) tmp ) ; } ; + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; + virtual const char *getTypeName(void) ; +} ; + + +class ssgColourArray : public ssgSimpleList +{ +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgColourArray ( int init = 3, sgVec4* things = 0 ) + : ssgSimpleList ( sizeof(sgVec4), init, (char*)things ) + { + type = ssgTypeColourArray () ; + } + float *get ( unsigned int n ) { return (float *) raw_get ( n ) ; } + void add ( sgVec4 thing ) { raw_add ( (char *) thing ) ; } ; + void set ( sgVec4 thing, unsigned int n ) { raw_set ( (char *) thing, n ) ; } ; + void set ( float r, float g, float b, float a, unsigned int n ) + { sgVec4 tmp = { r,g,b,a } ; raw_set ( (char *) tmp, n ) ; } ; + void add ( float r, float g, float b, float a ) + { sgVec4 tmp = { r,g,b,a } ; raw_add ( (char *) tmp ) ; } ; + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; + virtual const char *getTypeName(void) ; +} ; + + +class ssgIndexArray : public ssgSimpleList +{ +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgIndexArray ( int init = 3, short* things = 0 ) + : ssgSimpleList ( sizeof(short), init, (char*)things ) + { + type = ssgTypeIndexArray () ; + } + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; + short *get ( unsigned int n ) { return (short *) raw_get ( n ) ; } + void add ( short thing ) { raw_add ( (char *) &thing ) ; } ; + void set ( short thing, unsigned int n ) { raw_set ( (char *) &thing, n ) ; } ; + virtual const char *getTypeName(void) ; +} ; + + +class ssgTransformArray : public ssgSimpleList +{ +public: + int selection ; /* used to remember last transform selected */ + + ssgTransformArray ( int init = 3, sgMat4* things = 0 ) + : ssgSimpleList ( sizeof(sgMat4), init, (char*)things ) + { + type = ssgTypeTransformArray () ; + selection = 0 ; + } + sgMat4 *get ( unsigned int n ) { return (sgMat4 *) raw_get ( n ) ; } + void add ( sgMat4 thing ) { raw_add ( (char *) thing ) ; } ; + virtual const char *getTypeName(void) ; +} ; + + +class ssgTexture ; +class ssgTextureArray : private ssgSimpleList +{ +public: + + ssgTextureArray ( int init = 3 ) + : ssgSimpleList ( sizeof(ssgTexture*), init ) + { + //type = ssgTypeTextureArray () ; + } + + int getNum (void) { return total ; } + ssgTexture* get ( unsigned int n ) + { return *( (ssgTexture**) raw_get ( n ) ) ; } + void add ( ssgTexture* thing ) ; + void removeAll () ; + ssgTexture* findByFilename ( const char* fname ) ; +} ; + + +class ssgSimpleState ; +class ssgSimpleStateArray : private ssgSimpleList +{ + void collect_recursive ( ssgEntity *e ); + +public: + + ssgSimpleStateArray ( int init = 3 ) + : ssgSimpleList ( sizeof(ssgSimpleState*), init ) + { + //type = ssgTypeSimpleStateArray () ; + } + + int getNum (void) { return total ; } + ssgSimpleState* get ( unsigned int n ) + { + assert(n getHandle () ; + return 0 ; + } + + virtual char *getTextureFilename(void) + { + if ( texture != NULL ) + return texture -> getFilename () ; + return NULL ; + } + + virtual ssgTexture* getTexture (void) + { + return texture ; + } + + virtual void setTexture ( ssgTexture *tex ) + { + ssgDeRefDelete ( texture ) ; + texture = tex ; + if ( texture != NULL ) + { + care_about ( SSG_GL_TEXTURE ) ; + texture -> ref () ; + } + else + { + dont_care_about ( SSG_GL_TEXTURE ) ; + } + } + + virtual void setTexture ( const char *fname, + int _wrapu = TRUE, int _wrapv = TRUE, int _mipmap = TRUE ) + { + mipmap = _mipmap ; + setTexture ( new ssgTexture ( fname, _wrapu, _wrapv, mipmap ) ) ; + } + + /* + WARNING - THIS FORM OF setTexture IS DEPRECATED + BECAUSE IT PREVENTS ssgSave FROM SAVING THE + TEXTURE FILENAME and it LEAKS texture handles! + */ + + virtual void setTexture ( GLuint tex ) + { + if ( !texture ) + setTexture ( new ssgTexture ) ; + + texture -> setHandle ( tex ) ; + texture -> setFilename ( NULL ) ; + } + + virtual void setTextureFilename ( const char *fname ) + { + if ( !texture ) + setTexture ( new ssgTexture ) ; + + texture -> setFilename ( fname ) ; + } + + virtual GLenum getColourMaterial () + { + return (GLenum) colour_material_mode ; + } + + virtual void setColourMaterial ( GLenum which ) + { + colour_material_mode = (int) which ; + care_about ( SSG_GL_COLOR_MATERIAL ) ; + } + + virtual void setMaterial ( GLenum which, float r, float g, + float b, float a = 1.0f ) + { + sgVec4 rgba ; + sgSetVec4 ( rgba, r, g, b, a ) ; + setMaterial ( which, rgba ) ; + } + + virtual void setMaterial ( GLenum which, sgVec4 rgba ) + { + switch ( which ) + { + case GL_EMISSION : sgCopyVec4 ( emission_colour, rgba ) ; + care_about ( SSG_GL_EMISSION ) ; + break ; + case GL_SPECULAR : sgCopyVec4 ( specular_colour, rgba ) ; + care_about ( SSG_GL_SPECULAR ) ; + break ; + case GL_AMBIENT : sgCopyVec4 ( ambient_colour , rgba ) ; + care_about ( SSG_GL_AMBIENT ) ; + break ; + case GL_DIFFUSE : sgCopyVec4 ( diffuse_colour , rgba ) ; + care_about ( SSG_GL_DIFFUSE ) ; + break ; + case GL_AMBIENT_AND_DIFFUSE : // in compliance with glMaterial + sgCopyVec4 ( ambient_colour , rgba ) ; + sgCopyVec4 ( diffuse_colour , rgba ) ; + care_about ( SSG_GL_AMBIENT | SSG_GL_DIFFUSE ) ; + break ; + default : break ; + } + } + + virtual float *getMaterial ( GLenum which ) + { + switch ( which ) + { + case GL_EMISSION : return emission_colour ; + case GL_SPECULAR : return specular_colour ; + case GL_AMBIENT : return ambient_colour ; + case GL_DIFFUSE : return diffuse_colour ; + default: break ; + } + + return NULL ; + } + + virtual float getShininess (void) + { + return shininess ; + } + + virtual void setShininess ( float sh ) + { + care_about ( SSG_GL_SHININESS ) ; + shininess = sh ; + } + + virtual void setShadeModel ( GLenum model ) + { + care_about ( SSG_GL_SHADE_MODEL ) ; + shade_model = model ; + } + + virtual void setAlphaClamp ( float clamp ) + { + care_about ( SSG_GL_ALPHA_TEST ) ; + alpha_clamp = clamp ; + } + + /*int getWrapU(); + int getWrapV();*/ + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; +} ; + + +class ssgStateSelector : public ssgSimpleState +{ + int nstates ; + int selection ; +_SSG_PUBLIC: + ssgSimpleState **statelist ; + +protected: + virtual void copy_from ( ssgStateSelector *src, int clone_flags ) ; + +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgStateSelector () ; + ssgStateSelector ( int ns ) ; + + virtual ~ssgStateSelector (void) ; + virtual const char *getTypeName(void) ; + + int getNumSteps ( void ) { return nstates ; } + void selectStep ( unsigned int s ) ; + unsigned int getSelectStep (void) ; + ssgSimpleState *getCurrentStep (void) ; + void setStep ( int i, ssgSimpleState *step ) ; + ssgSimpleState *getStep ( int i ) ; + + virtual int isTranslucent (void) ; + virtual void setTranslucent (void) ; + virtual void setOpaque (void) ; + void force (void) ; + void apply (void) ; + + void care_about ( int mode ) ; + void dont_care_about ( int mode ) ; + + int isEnabled ( GLenum mode ) ; + void disable ( GLenum mode ) ; + void enable ( GLenum mode ) ; + + char *getTextureFilename(void) ; + void setTextureFilename(char *fname) ; + + void setTexture ( char *fname, + int _wrapu = TRUE, + int _wrapv = TRUE, + int _mipmap = TRUE ) ; + GLuint getTextureHandle (void) ; + void setTexture ( ssgTexture *tex ) ; + + /* + WARNING - THIS FORM OF setTexture IS DEPRECATED + BECAUSE IT PREVENTS ssgSave FROM SAVING THE + TEXTURE FILENAME and LEAKS texture handles! + */ + + void setTexture ( GLuint tex ) ; + + void setColourMaterial(GLenum which); + void setMaterial ( GLenum which, float r, float g, + float b, float a = 1.0f ) ; + + void setMaterial ( GLenum which, sgVec4 rgba ) ; + float *getMaterial ( GLenum which ) ; + float getShininess (void) ; + void setShininess ( float sh ) ; + void setShadeModel ( GLenum model ) ; + void setAlphaClamp ( float clamp ) ; + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; +} ; + +struct ssgEntityBinding +{ + ssgEntity **entity ; + char *nameOrPath ; +} ; + + +class ssgEntity : public ssgBase +{ + ssgList parents ; + + int traversal_mask ; + ssgTravCallback preTravCB ; + ssgTravCallback postTravCB ; + +protected: + sgSphere bsphere ; + int bsphere_is_invalid ; + + void emptyBSphere () { bsphere.empty () ; } + void visualiseBSphere () ; + void extendBSphere ( sgSphere *s ) { bsphere.extend ( s ) ; } + void extendBSphere ( sgBox *b ) { bsphere.extend ( b ) ; } + void extendBSphere ( sgVec3 v ) { bsphere.extend ( v ) ; } + + virtual ssgCullResult cull_test ( sgFrustum *f, sgMat4 m, int test_needed ) ; + virtual ssgCullResult isect_test ( sgSphere *s, sgMat4 m, int test_needed ) ; + virtual ssgCullResult hot_test ( sgVec3 s, sgMat4 m, int test_needed ) ; + virtual ssgCullResult los_test ( sgVec3 s, sgMat4 m, int test_needed ) ; + + virtual void copy_from ( ssgEntity *src, int clone_flags ) ; +public: + + ssgEntity (void) ; + virtual ~ssgEntity (void) ; + + int getTraversalMask () { return traversal_mask ;} + void setTraversalMask ( int t ) { traversal_mask = t ; } + void setTraversalMaskBits ( int t ) { traversal_mask |= t ; } + void clrTraversalMaskBits ( int t ) { traversal_mask &= ~t ; } + + ssgTravCallback getTravCallback ( int cb_type ) + { + return ( cb_type == SSG_CALLBACK_PRETRAV ) ? preTravCB : postTravCB ; + } + + void setTravCallback ( int cb_type, ssgTravCallback cb ) + { + if ( cb_type == SSG_CALLBACK_PRETRAV ) + preTravCB = cb ; + else + postTravCB = cb ; + } + + int preTravTests ( int *test_needed, int which ) ; + void postTravTests ( int which ) ; + + virtual void getNetTransform ( sgMat4 xform ) ; + virtual void getLastNetTransform ( sgMat4 xform ) ; + + /* for backward compatibility */ + virtual ssgCallback getCallback ( int cb_type ) ; + virtual void setCallback ( int cb_type, ssgCallback cb ) ; + + virtual ssgEntity* getByName ( char *nm ) ; + virtual ssgEntity* getByPath ( char *path ) ; + int bindEntities ( ssgEntityBinding *bind ) ; + + virtual void recalcBSphere (void) = 0 ; + int isDirtyBSphere (void) { return bsphere_is_invalid ; } + void dirtyBSphere () ; + + sgSphere *getBSphere () + { + if ( isDirtyBSphere () ) + recalcBSphere () ; + + return & bsphere ; + } + + virtual int getNumKids (void) { return 0 ; } + int getNumParents () { return parents.getNumEntities () ; } + ssgBranch *getParent ( int p ) { return (ssgBranch *) parents.getEntity ( p ) ; } + ssgBranch *getNextParent () { return (ssgBranch *) parents.getNextEntity () ; } + void addParent ( ssgEntity *entity ) { parents.addEntity ( entity ) ; } + void removeParent ( ssgEntity *entity ) { parents.removeEntity ( entity ) ; } + + virtual const char *getTypeName(void) ; + + virtual void cull ( sgFrustum *f, sgMat4 m, int test_needed ) = 0 ; + virtual void isect ( sgSphere *s, sgMat4 m, int test_needed ) = 0 ; + virtual void hot ( sgVec3 s, sgMat4 m, int test_needed ) = 0 ; + virtual void los ( sgVec3 s, sgMat4 m, int test_needed ) = 0 ; + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; + virtual void getStats ( int *num_branches, int *num_leaves, int *num_tris, int *num_vertices ) = 0 ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; +} ; + + + +class ssgLeaf : public ssgEntity +{ + int cull_face ; + ssgState *state ; + +protected: + GLenum gltype ; + + ssgCallback preDrawCB ; + ssgCallback postDrawCB ; + +#ifdef _SSG_USE_DLIST + GLuint dlist ; +#endif + + virtual void draw_geometry () = 0 ; + + int preDraw () ; + + virtual void copy_from ( ssgLeaf *src, int clone_flags ) ; +public: + ssgLeaf (void) ; + virtual ~ssgLeaf (void) ; + + virtual void drawHighlight ( sgVec4 colour ) = 0 ; + virtual void drawHighlight ( sgVec4 colour, int i ) = 0 ; + virtual void pick ( int baseName ) = 0 ; + +#ifdef _SSG_USE_DLIST + void makeDList () ; + void deleteDList () ; + GLuint getDListIndex () { return dlist ; } +#endif + + int getExternalPropertyIndex () + { return state ? state->getExternalPropertyIndex() : 0 ; } + + int isTranslucent () { return state ? state->isTranslucent() : FALSE ; } + int hasState () { return state != NULL ; } + + ssgState *getState () { return state ; } + void setState ( ssgState *st ); //~~ T.G. Body extended & moved into CXX file + + virtual ssgCallback getCallback ( int cb_type ) + { + return ( cb_type == SSG_CALLBACK_PREDRAW ) ? preDrawCB : postDrawCB ; + } + + virtual void setCallback ( int cb_type, ssgCallback cb ) + { + if ( cb_type == SSG_CALLBACK_PREDRAW ) + preDrawCB = cb ; + else + postDrawCB = cb ; + } + + virtual void setPrimitiveType ( GLenum ty ) { gltype = ty ; } + virtual GLenum getPrimitiveType () { return gltype ; } + + /* For backwards compatibility only -- DEPRECATED */ + GLenum getGLtype () { return getPrimitiveType() ; } + + virtual int getNumVertices () { return 0 ; } + virtual int getNumNormals () { return 0 ; } + virtual int getNumColours () { return 0 ; } + virtual int getNumTexCoords () { return 0 ; } + + virtual float *getVertex ( int i ) = 0 ; + virtual float *getNormal ( int i ) = 0 ; + virtual float *getColour ( int i ) = 0 ; + virtual float *getTexCoord ( int i ) = 0 ; + virtual int getNumTriangles () = 0 ; + virtual void getTriangle ( int n, short *v1, short *v2, short *v3 ) = 0 ; + virtual int getNumLines () = 0 ; + virtual void getLine ( int n, short *v1, short *v2 ) = 0 ; + + virtual void transform ( const sgMat4 m ) = 0 ; + + void setCullFace ( int cf ) { cull_face = cf ; } + int getCullFace () { return cull_face ; } + + virtual void recalcBSphere () = 0 ; + virtual const char *getTypeName(void) ; + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; + virtual void getStats ( int *num_branches, int *num_leaves, int *num_tris, int *num_vertices ) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; + + virtual void cull ( sgFrustum *f, sgMat4 m, int test_needed ) ; + virtual void isect ( sgSphere *s, sgMat4 m, int test_needed ) ; + virtual void hot ( sgVec3 s, sgMat4 m, int test_needed ) ; + virtual void los ( sgVec3 s, sgMat4 m, int test_needed ) ; + virtual void isect_triangles ( sgSphere *s, sgMat4 m, int test_needed ) = 0 ; + virtual void hot_triangles ( sgVec3 s, sgMat4 m, int test_needed ) = 0 ; + virtual void los_triangles ( sgVec3 s, sgMat4 m, int test_needed ) = 0 ; + virtual void draw () = 0 ; +} ; + +extern sgVec3 _ssgVertex000 ; +extern sgVec4 _ssgColourWhite ; +extern sgVec3 _ssgNormalUp ; +extern sgVec2 _ssgTexCoord00 ; +extern short _ssgIndex0 ; +extern float _ssgGlobTime ; // used by ssgAnimTransform. Has to be set by the appliation! + + +class ssgVTable : public ssgLeaf +{ +protected: + sgBox bbox ; + int indexed ; + + sgVec3 *vertices ; int num_vertices ; unsigned short *v_index ; + sgVec3 *normals ; int num_normals ; unsigned short *n_index ; + sgVec2 *texcoords ; int num_texcoords ; unsigned short *t_index ; + sgVec4 *colours ; int num_colours ; unsigned short *c_index ; + + virtual void draw_geometry () ; + virtual void copy_from ( ssgVTable *src, int clone_flags ) ; + +_SSG_PUBLIC: + int isIndexed () { return indexed ; } + +public: + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgVTable () ; + ssgVTable ( GLenum ty, + int nv, unsigned short *vi, sgVec3 *vl, + int nn, unsigned short *ni, sgVec3 *nl, + int nt, unsigned short *ti, sgVec2 *tl, + int nc, unsigned short *ci, sgVec4 *cl ) ; + + ssgVTable ( GLenum ty, + int nv, sgVec3 *vl, + int nn, sgVec3 *nl, + int nt, sgVec2 *tl, + int nc, sgVec4 *cl ) ; + + virtual void drawHighlight ( sgVec4 colour ) ; + virtual void drawHighlight ( sgVec4 colour, int i ) ; + virtual void pick ( int baseName ) ; + virtual void transform ( const sgMat4 m ) ; + + int getNumVertices () { return num_vertices ; } + int getNumNormals () { return num_normals ; } + int getNumColours () { return num_colours ; } + int getNumTexCoords () { return num_texcoords ; } + int getNumTriangles () ; + void getTriangle ( int n, short *v1, short *v2, short *v3 ) ; + int getNumLines () ; + void getLine ( int n, short *v1, short *v2 ) ; + + void getColourList ( void **list, unsigned short **idx ) + { + *list = colours ; + *idx = c_index ; + } + + void getTexCoordList ( void **list, unsigned short **idx ) + { + *list = texcoords ; + *idx = t_index ; + } + + void getNormalList ( void **list, unsigned short **idx ) + { + *list = normals ; + *idx = n_index ; + } + + void getVertexList ( void **list, unsigned short **idx ) + { + *list = vertices ; + *idx = v_index ; + } + + float *getVertex (int i){ if(i>=num_vertices)i=num_vertices-1; + return (num_vertices<=0) ? _ssgVertex000 : + ((indexed)?vertices [v_index[i]]:vertices [i]);} + float *getColour (int i){ if(i>=num_colours)i=num_colours-1; + return (num_colours<=0) ? _ssgColourWhite : + ((indexed)?colours [c_index[i]]:colours [i]);} + float *getNormal (int i){ if(i>=num_normals)i=num_normals-1; + return (num_normals<=0) ? _ssgNormalUp : + ((indexed)?normals [n_index[i]]:normals [i]);} + float *getTexCoord(int i){ if(i>=num_texcoords)i=num_texcoords-1; + return (num_texcoords<=0) ? _ssgTexCoord00 : + ((indexed)?texcoords[t_index[i]]:texcoords[i]);} + + + virtual ~ssgVTable (void) ; + + virtual const char *getTypeName(void) ; + virtual void recalcBSphere () ; + virtual void draw () ; + + virtual void isect_triangles ( sgSphere *s, sgMat4 m, int test_needed ) ; + virtual void hot_triangles ( sgVec3 s, sgMat4 m, int test_needed ) ; + virtual void los_triangles ( sgVec3 s, sgMat4 m, int test_needed ) ; + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; +} ; + + +class ssgVtxTable : public ssgLeaf +{ +protected: + sgBox bbox ; + + virtual void draw_geometry () ; + virtual void copy_from ( ssgVtxTable *src, int clone_flags ) ; + +_SSG_PUBLIC: + + ssgVertexArray *vertices ; + ssgNormalArray *normals ; + ssgTexCoordArray *texcoords ; + ssgColourArray *colours ; + +public: + int compare(ssgVtxTable *other, int print_result=TRUE); + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgVtxTable () ; + + ssgVtxTable ( GLenum ty, ssgVertexArray *vl, + ssgNormalArray *nl, + ssgTexCoordArray *tl, + ssgColourArray *cl ) ; + + void textureMe(float uP, float vP) + { texcoords = new ssgTexCoordArray; + for(int i=vertices->getNum()-1; i>=0; i--) + { sgVec2 v; + v[0] = uP; v[1] = vP; + texcoords->add(v); + } + } + virtual void drawHighlight ( sgVec4 colour ) ; + virtual void drawHighlight ( sgVec4 colour, int i ) ; + virtual void pick ( int baseName ) ; + virtual void transform ( const sgMat4 m ) ; + + ssgVertexArray *getVertices () { return vertices ; } + ssgNormalArray *getNormals () { return normals ; } + ssgTexCoordArray *getTexCoords () { return texcoords ; } + ssgColourArray *getColours () { return colours ; } + + virtual void setVertices ( ssgVertexArray *vl ) ; + virtual void setNormals ( ssgNormalArray *nl ) ; + virtual void setTexCoords ( ssgTexCoordArray *tl ) ; + virtual void setColours ( ssgColourArray *cl ) ; + + int getNumVertices () { return vertices -> getNum () ; } + int getNumNormals () { return normals -> getNum () ; } + int getNumColours () { return colours -> getNum () ; } + int getNumTexCoords () { return texcoords -> getNum () ; } + + /* Don't call this unless you know what you are doing!! */ + void rawSetNumVertices ( unsigned int n ) { vertices -> rawSetNum ( n ) ; } + + int getNumTriangles () ; + void getTriangle ( int n, short *v1, short *v2, short *v3 ) ; + int getNumLines () ; + void getLine ( int n, short *v1, short *v2 ) ; + + void getVertexList ( void **list ) { *list = vertices -> get ( 0 ) ; } + void getNormalList ( void **list ) { *list = normals -> get ( 0 ) ; } + void getTexCoordList ( void **list ) { *list = texcoords -> get ( 0 ) ; } + void getColourList ( void **list ) { *list = colours -> get ( 0 ) ; } + + float *getVertex (int i){ int nv=getNumVertices(); if(i>=nv)i=nv-1; + return (nv<=0) ? _ssgVertex000:vertices->get(i);} + float *getNormal (int i){ int nn=getNumNormals(); if(i>=nn)i=nn-1; + return (nn<=0) ? _ssgNormalUp:normals->get(i);} + float *getTexCoord(int i){ int nc=getNumTexCoords(); if(i>=nc)i=nc-1; + return (nc<=0) ? _ssgTexCoord00:texcoords->get(i);} + float *getColour (int i){ int nc=getNumColours(); if(i>=nc)i=nc-1; + return (nc<=0) ? _ssgColourWhite:colours->get(i);} + + ssgVtxArray *getAs_ssgVtxArray (); + + virtual ~ssgVtxTable (void) ; + + virtual const char *getTypeName(void) ; + virtual void recalcBSphere () ; + virtual void draw () ; + + virtual void isect_triangles ( sgSphere *s, sgMat4 m, int test_needed ) ; + virtual void hot_triangles ( sgVec3 s, sgMat4 m, int test_needed ) ; + virtual void los_triangles ( sgVec3 s, sgMat4 m, int test_needed ) ; + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2); + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; + +} ; + + +class ssgTween : public ssgVtxTable +{ + virtual void copy_from ( ssgTween *src, int clone_flags ) ; + void init () ; +protected: +_SSG_PUBLIC: + + int curr_bank ; + + ssgVertexArray *render_vertices ; + ssgNormalArray *render_normals ; + ssgTexCoordArray *render_texcoords ; + ssgColourArray *render_colours ; + + ulList *banked_vertices ; + ulList *banked_normals ; + ulList *banked_texcoords ; + ulList *banked_colours ; + +public: + virtual ssgBase *clone ( int clone_flags = 0 ) ; + + ssgTween () ; + ssgTween ( GLenum ty ) ; + + virtual void setVertices ( ssgVertexArray *vl ) ; + virtual void setNormals ( ssgNormalArray *nl ) ; + virtual void setTexCoords ( ssgTexCoordArray *tl ) ; + virtual void setColours ( ssgColourArray *cl ) ; + + virtual void recalcBSphere () ; + virtual void draw () ; + virtual void transform ( const sgMat4 m ) ; + + virtual const char *getTypeName(void) ; + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2); + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; + + int getNumBanks () { return banked_vertices -> getNumEntities () ; } + + int newBank ( ssgVertexArray *vl, ssgNormalArray *nl, + ssgTexCoordArray *tl, ssgColourArray *cl ) ; + int newBank ( int newVertices , int newNormals, + int newTexCoords, int newColours ) ; + void setBank ( int bank ) ; + + virtual ~ssgTween (void) ; +} ; + + +class ssgVtxArray : public ssgVtxTable +{ +protected: + ssgIndexArray *indices; + + virtual void draw_geometry () ; + virtual void copy_from ( ssgVtxArray *src, int clone_flags ) ; + +public: + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgVtxArray () ; + + ssgVtxArray ( GLenum ty, ssgVertexArray *vl, + ssgNormalArray *nl, + ssgTexCoordArray *tl, + ssgColourArray *cl, + ssgIndexArray *il ) ; + + virtual void drawHighlight ( sgVec4 colour ) ; + virtual void drawHighlight ( sgVec4 colour, int i ) ; + virtual void pick ( int baseName ) ; + + void setIndices ( ssgIndexArray *il ) ; + void addIndex ( short i) { indices->add(i); } + + int getNumIndices () { return indices -> getNum () ; } + + int getNumTriangles () ; + void getTriangle ( int n, short *v1, short *v2, short *v3 ) ; + + int getNumLines () ; + void getLine ( int n, short *v1, short *v2 ) ; + + void getIndexList ( void **list ) { *list = indices -> get ( 0 ) ; } + + short *getIndex (int i){ int ni=getNumIndices();if(i>=ni)i=ni-1; + return (ni<=0) ? &_ssgIndex0 : indices->get(i);} + + void removeUnusedVertices(); + virtual ~ssgVtxArray (void) ; + + virtual const char *getTypeName(void) ; + + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; +} ; + + +// class ssgVtxInterleavedArray + + +class ssgBranch : public ssgEntity +{ + ssgKidList kids ; + +protected: + virtual void copy_from ( ssgBranch *src, int clone_flags ) ; + +public: + virtual void zeroSpareRecursive (); + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgBranch (void) ; + virtual ~ssgBranch (void) ; + + virtual int getNumKids (void) { return kids.getNumEntities() ; } + ssgEntity *getKid ( int n ) { return kids.getEntity ( n ) ; } + ssgEntity *getNextKid (void) { return kids.getNextEntity () ; } + int searchForKid ( ssgEntity *entity ) + { return kids.searchForEntity(entity); } + + void addKid ( ssgEntity *entity ) ; + void removeKid ( int n ) ; + void removeKid ( ssgEntity *entity ) ; + void removeAllKids (void) ; + void replaceKid ( int n, ssgEntity *new_entity ) ; + void replaceKid ( ssgEntity *old_entity, ssgEntity *new_entity ) ; + + void mergeHNodes(); + + virtual ssgEntity *getByName ( char *match ) ; + virtual ssgEntity *getByPath ( char *path ) ; + + virtual const char *getTypeName(void) ; + virtual void cull ( sgFrustum *f, sgMat4 m, int test_needed ) ; + virtual void isect ( sgSphere *s, sgMat4 m, int test_needed ) ; + virtual void hot ( sgVec3 s, sgMat4 m, int test_needed ) ; + virtual void los ( sgVec3 s, sgMat4 m, int test_needed ) ; + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; + virtual void getStats ( int *num_branches, int *num_leaves, int *num_tris, int *num_vertices ) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; + virtual void recalcBSphere () ; +} ; + + +#define SSGTWEEN_STOP_AT_END 0 +#define SSGTWEEN_REPEAT 1 + +class ssgTweenController : public ssgBranch +{ + float curr_bank ; + int mode ; /* STOP_AT_END or REPEAT */ + +protected: + + virtual void copy_from ( ssgTweenController *src, int clone_flags ) ; + +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgTweenController (void) ; + virtual ~ssgTweenController (void) ; + + void setMode ( int _mode ) { mode = _mode ; } + int getMode () { return mode ; } + + void selectBank ( float f ) { curr_bank = f ; } + float getCurrBank () { return curr_bank ; } + + virtual void cull ( sgFrustum *f, sgMat4 m, int test_needed ) ; + virtual const char *getTypeName(void) ; + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; +} ; + + + +class ssgInvisible : public ssgBranch +{ +protected: + + virtual void copy_from ( ssgInvisible *src, int clone_flags ) ; + +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgInvisible (void) ; + virtual ~ssgInvisible (void) ; + + virtual void cull ( sgFrustum *f, sgMat4 m, int test_needed ) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; +} ; + + + +class ssgSelector : public ssgBranch +{ + unsigned char* selection ; + +protected: + int max_kids ; + + virtual void copy_from ( ssgSelector *src, int clone_flags ) ; + +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgSelector ( int max_kids = 32 ) ; + virtual ~ssgSelector (void) ; + + void selectStep ( unsigned int s ) + { + memset ( selection, 0, max_kids ) ; + selection [s] = 1 ; + } + + void select ( unsigned int s ) + { + for ( int i=0; i= 0) ? getKid ( k ) : NULL ; + } + + int getMaxKids (void) const { return max_kids ; } + + virtual const char *getTypeName(void) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; + virtual void cull ( sgFrustum *f, sgMat4 m, int test_needed ) ; + virtual void isect ( sgSphere *s, sgMat4 m, int test_needed ) ; + virtual void hot ( sgVec3 s, sgMat4 m, int test_needed ) ; + virtual void los ( sgVec3 s, sgMat4 m, int test_needed ) ; +} ; + + +class ssgRangeSelector : public ssgSelector +{ + int additive ; + float rng_list [ 33 ] ; + +protected: + virtual void copy_from ( ssgRangeSelector *src, int clone_flags ) ; +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgRangeSelector (void) ; + virtual ~ssgRangeSelector (void) ; + + void setRanges ( float *ranges, unsigned int nranges ) + { + for ( unsigned int i = 0 ; i < 33 ; i++ ) + if ( i < nranges ) + rng_list [ i ] = ranges [ i ] ; + else + rng_list [ i ] = SG_MAX ; + } + + void setRange ( unsigned int which, float range ) + { + if ( which < 33 ) + rng_list [ which ] = range ; + } + + float *getRanges () + { + return rng_list ; + } + + float getRange ( unsigned int which ) + { + return ( which < 33 ) ? rng_list[which] : SG_MAX ; + } + + void setAdditive ( int add ) { additive = add ; } + int isAdditive () { return additive ; } + + virtual const char *getTypeName(void) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; + virtual void cull ( sgFrustum *f, sgMat4 m, int test_needed ) ; + virtual void isect ( sgSphere *s, sgMat4 m, int test_needed ) ; + virtual void hot ( sgVec3 s, sgMat4 m, int test_needed ) ; + virtual void los ( sgVec3 s, sgMat4 m, int test_needed ) ; +} ; + + +enum ssgAnimEnum +{ + SSG_ANIM_START, + SSG_ANIM_STOP, + SSG_ANIM_PAUSE, + SSG_ANIM_RESUME +} ; + +enum ssgAnimDirection +{ + SSG_ANIM_SWING, + SSG_ANIM_ONESHOT, + SSG_ANIM_SHUTTLE +} ; + +enum ssgAnimTimeMode +{ + SSG_ANIM_FRAME, + SSG_ANIM_CLOCK +}; + + +class ssgTimedSelector : public ssgSelector +{ +_SSG_PUBLIC: + ssgAnimEnum running ; + ssgAnimDirection mode ; + + double start_time ; + double pause_time ; + double loop_time ; + float *times ; + int curr ; + int start ; + int end ; + +protected: + ssgAnimTimeMode time_mode ; + static ulClock ck ; + + void compute_loop_time () + { + loop_time = 0 ; + + for ( int k = start ; k <= end ; k++ ) + loop_time += times [ k ] ; + } + + virtual void copy_from ( ssgTimedSelector *src, int clone_flags ) ; + + double get_time() const + { + if (time_mode == SSG_ANIM_FRAME) + return (double) ssgGetFrameCounter() ; + else + return ck.update(), ck.getAbsTime(); + } +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgTimedSelector ( int max_kids = 32 ) ; + virtual ~ssgTimedSelector (void) ; + + virtual const char *getTypeName(void) ; + + int getStep () ; + + ssgAnimTimeMode getTimeMode() const { return time_mode; } + + float getDuration ( int i = 0 ) { return times [ i ] ; } + + void setDuration ( float ti, int i = -1, ssgAnimTimeMode m = SSG_ANIM_FRAME ) + { + time_mode = m; + if ( i >= 0 && i < max_kids ) + times [ i ] = ti ; + else + for ( int j = 0 ; j < max_kids ; j++ ) + times [ j ] = ti ; + + compute_loop_time () ; + } + + void control ( ssgAnimEnum m ) + { + compute_loop_time () ; + + if ( m == SSG_ANIM_PAUSE ) + { + pause_time = get_time() ; + curr = getStep () ; + } + else + if ( m == SSG_ANIM_RESUME ) + { + start_time += get_time () - pause_time ; + + if ( running != SSG_ANIM_STOP ) + m = SSG_ANIM_START ; + } + else + if ( m == SSG_ANIM_START ) + { + start_time = get_time () ; + curr = getStep () ; + } + + running = m ; + } + + ssgAnimEnum getControl () { return running ; } + + void setMode ( ssgAnimDirection m ) { mode = m ; } + ssgAnimDirection getMode () { return mode ; } + + void setLimits ( int st, int en ) + { + curr = st ; + start = st ; + end = en ; + compute_loop_time () ; + } + + void getLimits ( int *st, int *en ) + { + if ( st != NULL ) *st = start ; + if ( en != NULL ) *en = end ; + } + + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; + virtual void cull ( sgFrustum *f, sgMat4 m, int test_needed ) ; + virtual void isect ( sgSphere *s, sgMat4 m, int test_needed ) ; + virtual void hot ( sgVec3 s, sgMat4 m, int test_needed ) ; + virtual void los ( sgVec3 s, sgMat4 m, int test_needed ) ; +} ; + + +class ssgBaseTransform : public ssgBranch +{ +protected: + + sgMat4 transform ; + sgMat4 last_transform ; + int last_updated ; + int first_time ; + virtual void copy_from ( ssgBaseTransform *src, int clone_flags ) ; +public: + + ssgBaseTransform (void) ; + virtual ~ssgBaseTransform (void) ; + + void firsttime () + { + if ( first_time ) + { + first_time = FALSE ; + updateTransform () ; + } + } + + void updateTransform () + { + sgCopyMat4 ( last_transform, transform ) ; + last_updated = ssgGetFrameCounter () ; + } + + void getLastTransform ( sgMat4 xform ) + { + /* + If the transform was not updated this - or last frame + then we need to equate the two transforms. + */ + + if ( last_updated < ssgGetFrameCounter () - 1 ) + updateTransform () ; + + sgCopyMat4 ( xform, last_transform ) ; + } + + void getTransform ( sgMat4 xform ) + { + sgCopyMat4 ( xform, transform ) ; + } + + virtual void setTransform ( sgVec3 xyz ) = 0 ; + virtual void setTransform ( sgCoord *xform ) = 0 ; + virtual void setTransform ( sgCoord *xform, float sx, float sy, float sz )=0; + virtual void setTransform ( sgMat4 xform ) = 0 ; + + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; + + virtual const char *getTypeName(void) ; + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; +} ; + + +class ssgTransform : public ssgBaseTransform +{ +protected: + virtual void copy_from ( ssgTransform *src, int clone_flags ) ; +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgTransform (void) ; + ssgTransform ( sgCoord *c ) ; + virtual ~ssgTransform (void) ; + + virtual void setTransform ( sgVec3 xyz ) ; + virtual void setTransform ( sgCoord *xform ) ; + virtual void setTransform ( sgCoord *xform, float sx, float sy, float sz ) ; + virtual void setTransform ( sgMat4 xform ) ; + + virtual void getNetTransform ( sgMat4 xform ) ; + virtual void getLastNetTransform ( sgMat4 xform ) ; + + virtual const char *getTypeName(void) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; + virtual void cull ( sgFrustum *f, sgMat4 m, int test_needed ) ; + virtual void isect ( sgSphere *s, sgMat4 m, int test_needed ) ; + virtual void hot ( sgVec3 s, sgMat4 m, int test_needed ) ; + virtual void los ( sgVec3 s, sgMat4 m, int test_needed ) ; + virtual void recalcBSphere () ; +} ; + +class ssgAnimTransform : public ssgTransform +{ + float curr_bank ; + int mode ; /* SSGTWEEN_STOP_AT_END or SSGTWEEN_REPEAT */ + class ssgTransformArray transformations; + +protected: + + virtual void copy_from ( ssgAnimTransform *src, int clone_flags ) ; + +public: + + void setNum ( unsigned int n ) { transformations.setNum( n ); } + void setATransform ( sgMat4 thing, unsigned int n ) { transformations.raw_set ( (char *) thing, n ) ; } ; + + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgAnimTransform (void) ; + virtual ~ssgAnimTransform (void) ; + + void setMode ( int _mode ) { mode = _mode ; } + int getMode () { return mode ; } + + void selectBank ( float f ) { curr_bank = f ; } + float getCurrBank () { return curr_bank ; } + + virtual void cull ( sgFrustum *f, sgMat4 m, int test_needed ) ; + virtual const char *getTypeName(void) ; + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; +} ; + + +class ssgAxisTransform : public ssgTransform +{ + sgVec3 rotation_axis ; + sgVec3 rotation_center ; + float limit_low ; + float limit_high ; +protected: + virtual void copy_from ( ssgAxisTransform *src, int clone_flags ) ; +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgAxisTransform (void) ; + ssgAxisTransform ( sgVec3 axis, sgVec3 center ) ; + virtual ~ssgAxisTransform (void) ; + + virtual void setAxis ( sgVec3 axis ) ; + virtual float *getAxis () ; + virtual void setCenter ( sgVec3 center ) ; + virtual float *getCenter () ; + virtual void setRotation ( float rot ) ; + + virtual void setRotationLimits ( float low, float high ) ; + virtual void setLinearRotation ( float rot ) ; + + virtual const char *getTypeName(void) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; +}; + + +class ssgTexTrans : public ssgBaseTransform +{ +protected: + virtual void copy_from ( ssgTexTrans *src, int clone_flags ) ; +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgTexTrans (void) ; + ssgTexTrans ( sgCoord *c ) ; + virtual ~ssgTexTrans (void) ; + + virtual void setTransform ( sgVec3 xyz ) ; + virtual void setTransform ( sgCoord *xform ) ; + virtual void setTransform ( sgCoord *xform, float sx, float sy, float sz ) ; + virtual void setTransform ( sgMat4 xform ) ; + + virtual const char *getTypeName(void) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; + virtual void cull ( sgFrustum *f, sgMat4 m, int test_needed ) ; +} ; + + +class ssgCutout : public ssgBranch +{ + int point_rotate ; +protected: + virtual void copy_from ( ssgCutout *src, int clone_flags ) ; +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgCutout (int pntrot=FALSE) ; + virtual ~ssgCutout (void) ; + + int isPointRotate (void) { return point_rotate ; } + + virtual const char *getTypeName(void) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; + virtual void cull ( sgFrustum *f, sgMat4 m, int test_needed ) ; + virtual void isect ( sgSphere *s, sgMat4 m, int test_needed ) ; + virtual void hot ( sgVec3 s, sgMat4 m, int test_needed ) ; + virtual void los ( sgVec3 s, sgMat4 m, int test_needed ) ; +} ; + + +class ssgRoot : public ssgBranch +{ +protected: + virtual void copy_from ( ssgRoot *src, int clone_flags ) ; +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgRoot (void) ; + virtual ~ssgRoot (void) ; + virtual const char *getTypeName(void) ; + virtual int load ( FILE *fd ) ; + virtual int save ( FILE *fd ) ; +} ; + + +class ssgLight +{ + int id ; + int is_headlight ; + int is_turned_on ; + + sgVec4 ambient ; + sgVec4 diffuse ; + sgVec4 specular ; + + sgVec4 position ; + + sgVec3 direction ; + float exponent ; + float cutoff ; + sgVec3 atten ; + +public: + + ssgLight () + { + id = 0 ; + is_turned_on = FALSE ; + is_headlight = FALSE ; + sgSetVec4 ( position, 0.0f, 0.0f, 1.0f, 0.0f ) ; + sgSetVec4 ( ambient , 0.2f, 0.2f, 0.2f, 1.0f ) ; + sgSetVec4 ( diffuse , 1.0f, 1.0f, 1.0f, 1.0f ) ; + sgSetVec4 ( specular, 1.0f, 1.0f, 1.0f, 1.0f ) ; + sgSetVec3 ( direction, 0.0f, 0.0f, -1.0f ) ; + exponent = 1.0f; + cutoff = 90.0f; + sgSetVec3 ( atten, 1.0f, 0.0f, 0.0f ) ; + } + + void setID ( int i ) { id = i ; } + int isOn () { return is_turned_on ; } + void on () { is_turned_on = TRUE ; } + void off () { is_turned_on = FALSE ; } + + void setPosition ( const sgVec3 pos ) { sgCopyVec3 ( position, pos ) ; } + void getPosition ( sgVec3 pos ) { sgCopyVec3 ( pos, position ) ; } + void setPosition ( float x, float y, float z ) { sgSetVec3 ( position, x, y, z ) ; } + + void setColour ( GLenum which, const sgVec4 col ) + { + switch ( which ) + { + case GL_AMBIENT : sgCopyVec4 ( ambient , col ) ; break ; + case GL_DIFFUSE : sgCopyVec4 ( diffuse , col ) ; break ; + case GL_SPECULAR : sgCopyVec4 ( specular, col ) ; break ; + default : break ; + } + } + + void getColour ( GLenum which, sgVec4 col ) + { + switch ( which ) + { + case GL_AMBIENT : sgCopyVec4 ( col , ambient ) ; break ; + case GL_DIFFUSE : sgCopyVec4 ( col , diffuse ) ; break ; + case GL_SPECULAR : sgCopyVec4 ( col, specular ) ; break ; + default : break ; + } + } + + void setColour ( GLenum which, float r, float g, float b ) + { + sgVec4 colour = { r, g, b, 1.0f }; + setColour(which, colour); + } + + void setHeadlight ( int head ) { is_headlight = head ; } + int isHeadlight () { return is_headlight ; } + + void setSpotlight ( int spot ) { position[3] = ( spot ? 1.0f : 0.0f ) ; } + int isSpotlight () { return position[3] != 0.0f; } + + void setSpotDirection ( const sgVec3 dir ) { sgCopyVec3 ( direction, dir ) ; } + void getSpotDirection ( sgVec3 dir ) { sgCopyVec3 ( dir, direction ) ; } + void setSpotDirection ( float x, float y, float z ) { sgSetVec3 ( direction, x, y, z ) ; } + + void setSpotDiffusion ( float exp, float cut = 90.0f ) + { + exponent = exp; + cutoff = cut; + } + + void getSpotDiffusion ( float *exp, float *cut = 0 ) + { + if (exp != 0) *exp = exponent; + if (cut != 0) *cut = cutoff; + } + + void setSpotAttenuation ( float constant, float linear, float quadratic ) + { + sgSetVec3( atten, constant, linear, quadratic ); + } + + void getSpotAttenuation ( float *constant, float *linear, float *quadratic ) + { + if (constant != 0) *constant = atten[0]; + if (linear != 0) *linear = atten[1]; + if (quadratic != 0) *quadratic = atten[2]; + } + + void setup () + { + if ( is_turned_on ) + { + glEnable ( (GLenum)(GL_LIGHT0+id) ) ; + glLightfv ( (GLenum)(GL_LIGHT0+id), GL_AMBIENT , ambient ) ; + glLightfv ( (GLenum)(GL_LIGHT0+id), GL_DIFFUSE , diffuse ) ; + glLightfv ( (GLenum)(GL_LIGHT0+id), GL_SPECULAR, specular ) ; + glLightfv ( (GLenum)(GL_LIGHT0+id), GL_POSITION, position ) ; + if ( isSpotlight() ) { + glLightfv ( (GLenum)(GL_LIGHT0+id), GL_SPOT_DIRECTION, direction ) ; + glLightf ( (GLenum)(GL_LIGHT0+id), GL_SPOT_EXPONENT, exponent ) ; + glLightf ( (GLenum)(GL_LIGHT0+id), GL_SPOT_CUTOFF, cutoff ) ; + glLightf ( (GLenum)(GL_LIGHT0+id), GL_CONSTANT_ATTENUATION, atten[0] ); + glLightf ( (GLenum)(GL_LIGHT0+id), GL_LINEAR_ATTENUATION, atten[1] ); + glLightf ( (GLenum)(GL_LIGHT0+id), GL_QUADRATIC_ATTENUATION, atten[2] ); + } + } + else + glDisable ( (GLenum)(GL_LIGHT0+id) ) ; + } + +} ; + +class ssgHit +{ +_SSG_PUBLIC: + + int num_entries ; + ssgEntity *path [ SSG_MAXPATH ] ; + +public: + ssgLeaf *leaf ; + int triangle ; + sgVec4 plane ; + sgMat4 matrix ; + + ssgHit () + { + leaf = NULL ; + init () ; + } ; + + void init () { num_entries = 0 ; } + + void addPath ( ssgEntity *e ) + { + if ( num_entries < SSG_MAXPATH ) + path [ num_entries++ ] = e ; + } + + int getNumPathEntries () { return num_entries ; } + + ssgEntity *getPathEntry ( int i ) + { + return ( i >= 0 && i < num_entries ) ? path[i] : (ssgEntity *) NULL ; + } +} ; + +class ssgContext +{ + protected: + + int enabledClipPlanes ; + sgVec4 clipPlane [ 6 ] ; + ssgSimpleState *currentState ; + ssgSimpleState *basicState ; + sgFrustum *frustum ; + + sgMat4 cameraMatrix ; + int cullFace ; + int ovTexture ; + int ovCullface ; + ssgState *ovState ; + +public: + + + ssgContext () ; + ~ssgContext () ; + + void forceBasicState () ; + + void applyClipPlanes () ; + void removeClipPlanes () ; + + void makeCurrent () ; + int isCurrent () ; + + void clrClipPlane ( int i ) + { + if ( i >= 0 && i < 6 ) + enabledClipPlanes &= ~(1<= 0 && i < 6 ) + { + sgCopyVec4 ( clipPlane [ i ], plane ) ; + enabledClipPlanes |= (1<=6)) ? NULL : clipPlane [i] ; + } + + void overrideState ( ssgState *s ) ; + void overrideTexture ( int on_off ) ; + void overrideCullface ( int on_off ) ; + + void setCullface ( int on_off ) + { + if ( cullFace == on_off || ovCullface ) + return ; + + cullFace = on_off ; + + if ( cullFace ) glEnable ( GL_CULL_FACE ) ; + else glDisable ( GL_CULL_FACE ) ; + } + + ssgState *overriddenState () { return ovState ; } + int stateOverridden () { return ovState != NULL ; } + int textureOverridden () { return ovTexture ; } + int cullfaceOverridden () { return ovCullface ; } + int cullfaceIsEnabled () { return cullFace ; } + + sgFrustum *getFrustum () { return frustum ; } + + // make a perspective projection + void setFrustum ( float l, float r, float b, float t, float n, float f ) ; + + // make an orthographic projection + void setOrtho ( float l, float r, float b, float t, float n, float f ) ; + + void getNearFar ( float *n, float *f ) ; + void getFOV ( float *w, float *h ) ; + void getOrtho ( float *w, float *h ) ; + + void setNearFar ( float n, float f ) ; + void setOrtho ( float w, float h ) ; // make orthographic + void setFOV ( float w, float h ) ; // make perspective + + int isOrtho () { return frustum -> isOrtho () ; } // is orthographic + + ssgSimpleState *getState () { return currentState ; } + void cull ( ssgBranch *r ) ; + + void getCameraPosition ( sgVec3 pos ) ; + void setCamera ( sgMat4 mat ) ; + void setCamera ( const sgCoord *coord ) ; + void setCameraLookAt ( const sgVec3 eye, const sgVec3 center, const sgVec3 up ) ; + void setCameraLookAt ( const sgVec3 eye, const sgVec3 center ) ; + + void loadProjectionMatrix () ; + void loadModelviewMatrix () ; + + void getProjectionMatrix ( sgMat4 dst ) ; + void getModelviewMatrix ( sgMat4 dst ) ; + + void pushProjectionMatrix () ; + void pushProjectionMatrix ( sgFrustum *f ) ; + void loadModelviewMatrix ( sgMat4 mat ) ; + +} ; + + + +/* Compatibility inlines for pre-ssgContext applications */ + +extern ssgContext *_ssgCurrentContext ; + +inline ssgContext *ssgGetCurrentContext () { return _ssgCurrentContext ; } + +inline void ssgGetCameraPosition ( sgVec3 pos ) +{ + _ssgCurrentContext -> getCameraPosition ( pos ) ; +} + +inline void ssgOverrideState ( ssgState *s ) +{ + _ssgCurrentContext->overrideState ( s ) ; +} + +inline void ssgOverrideTexture ( int on_off ) +{ + _ssgCurrentContext->overrideTexture ( on_off ) ; +} + +inline void ssgOverrideCullface ( int on_off ) +{ + _ssgCurrentContext->overrideCullface ( on_off ) ; +} + +inline void ssgGetNearFar ( float *n, float *f ) +{ + _ssgCurrentContext->getNearFar ( n, f ) ; +} + +inline void ssgGetFOV ( float *w, float *h ) +{ + _ssgCurrentContext->getFOV ( w, h ) ; +} + +inline void ssgGetOrtho ( float *w, float *h ) +{ + _ssgCurrentContext->getOrtho ( w, h ) ; +} + +inline void ssgSetFrustum ( float l, float r, float b, float t, float n, float f ) +{ + _ssgCurrentContext->setFrustum ( l, r, b, t, n, f ) ; +} + +inline void ssgSetOrtho ( float l, float r, float b, float t, float n, float f ) +{ + _ssgCurrentContext->setOrtho ( l, r, b, t, n, f ) ; +} + +inline void ssgSetFOV ( float w, float h ) +{ + _ssgCurrentContext->setFOV ( w, h ) ; +} + +inline void ssgSetOrtho ( float w, float h ) +{ + _ssgCurrentContext->setOrtho ( w, h ) ; +} + +inline void ssgSetNearFar ( float n, float f ) +{ + _ssgCurrentContext->setNearFar ( n, f ) ; +} + +inline void ssgSetCamera ( sgMat4 mat ) +{ + _ssgCurrentContext-> setCamera ( mat ) ; +} + +inline void ssgSetCamera ( sgCoord *coord ) +{ + _ssgCurrentContext-> setCamera ( coord ) ; +} + +inline void ssgSetCameraLookAt ( const sgVec3 eye, const sgVec3 center, const sgVec3 up ) +{ + _ssgCurrentContext-> setCameraLookAt ( eye, center, up ) ; +} + +inline void ssgSetCameraLookAt ( const sgVec3 eye, const sgVec3 center ) +{ + _ssgCurrentContext-> setCameraLookAt ( eye, center ) ; +} + +inline void ssgLoadProjectionMatrix () +{ + _ssgCurrentContext->loadProjectionMatrix () ; +} + +inline void ssgLoadProjectionMatrix ( sgFrustum *f ) +{ + glLoadIdentity () ; + _ssgCurrentContext->pushProjectionMatrix ( f ) ; +} + +inline void ssgGetProjectionMatrix ( sgMat4 dst ) +{ + _ssgCurrentContext->getProjectionMatrix ( dst ) ; +} + +inline void ssgGetModelviewMatrix ( sgMat4 dst ) +{ + _ssgCurrentContext->getModelviewMatrix ( dst ) ; +} + +inline void ssgLoadModelviewMatrix () +{ + _ssgCurrentContext->loadModelviewMatrix () ; +} + +inline void ssgLoadModelviewMatrix ( sgMat4 mat ) +{ + _ssgCurrentContext->loadModelviewMatrix ( mat ) ; +} + +inline void ssgForceBasicState () +{ + _ssgCurrentContext -> forceBasicState () ; +} + +inline sgFrustum *ssgGetFrustum () +{ + return _ssgCurrentContext -> getFrustum() ; +} + +void ssgInit () ; + +void ssgCullAndDraw ( ssgBranch *root ) ; +void ssgCullAndPick ( ssgBranch *root, sgVec2 botleft, sgVec2 topright ) ; +int ssgIsect ( ssgBranch *root, sgSphere*s,sgMat4 m, ssgHit **results ) ; +int ssgHOT ( ssgBranch *root, sgVec3 s, sgMat4 m, ssgHit **results ) ; +int ssgLOS ( ssgBranch *root, sgVec3 s, sgMat4 m, ssgHit **results ) ; + +/* Load/Save functions */ + +enum { + SSG_MD2_STAND, + SSG_MD2_RUN, + SSG_MD2_ATTACK, + SSG_MD2_PAIN_1, + SSG_MD2_PAIN_2, + SSG_MD2_PAIN_3, + SSG_MD2_JUMP, + SSG_MD2_FLIPOFF, + SSG_MD2_SALUTE, + SSG_MD2_TAUNT, + SSG_MD2_WAVE, + SSG_MD2_POINT, + SSG_MD2_CROUCH_STAND, + SSG_MD2_CROUCH_WALK, + SSG_MD2_CROUCH_PAIN, + SSG_MD2_CROUCH_DEATH, + SSG_MD2_DEATH_1, + SSG_MD2_DEATH_2, + SSG_MD2_DEATH_3, + SSG_MD2_ALL, + SSG_MD2_POSE +}; + +class ssgLoaderOptions +{ + //NOTES: we could add more later + //...model scale factor... + //...create normals or read them from the file?... + //...cutoff angle for smooth shading where there isn`t one in the file format... + //...which direction is front-facing in formats that don`t get it right... + //...etc... + +protected: + + + /* for backward compatibility */ + ssgState *(*create_state_cb)( char *) ; + ssgBranch *(*create_branch_cb)(char *) ; + + char* model_dir ; + char* texture_dir ; + + char* make_path ( char* path, const char* dir, const char* fname ) const ; + +public: + ssgSimpleStateArray shared_states ; + ssgTextureArray shared_textures ; + + ssgLoaderOptions () + { + model_dir = 0 ; + texture_dir = 0 ; + + /* for backward compatibility */ + create_state_cb = 0 ; + create_branch_cb = 0 ; + } + + virtual ~ssgLoaderOptions() + { + if (model_dir) + { + delete [] model_dir; + model_dir = 0; + } + + if (texture_dir) + { + delete [] texture_dir; + texture_dir = 0; + } + } + + const char* getModelDir ( void ) const { return model_dir ; } + const char* getTextureDir ( void ) const { return texture_dir ; } + void setModelDir ( const char *s ) ; + void setTextureDir ( const char *s ) ; + + // + // the idea is that you derive a class from ssgLoaderOptions and + // override these methods to customize how the loaders work + // + virtual void makeModelPath ( char* path, const char *fname ) const ; + virtual void makeTexturePath ( char* path, const char *fname ) const ; + + virtual ssgLeaf* createLeaf ( ssgLeaf* leaf, const char* parent_name ) ; + virtual ssgTexture* createTexture ( char* tfname, + int wrapu = TRUE, int wrapv = TRUE, + int mipmap = TRUE ) ; + virtual ssgTransform* createTransform ( ssgTransform* tr, + ssgTransformArray* ta ) const ; + virtual ssgSelector* createSelector ( ssgSelector* s ) const ; + virtual ssgBranch* createBranch ( char* text ) const + { + if ( create_branch_cb != NULL ) + return (*create_branch_cb)(text) ; + return NULL ; + } + virtual ssgState* createState ( char* tfname ) const + { + if ( create_state_cb != NULL ) + return (*create_state_cb)(tfname) ; + return NULL ; + } + virtual ssgSimpleState* createSimpleState ( char* tfname ) const + { + ssgState *st = createState ( tfname ) ; + if ( st != NULL ) + { + if ( st -> isAKindOf ( ssgTypeSimpleState() ) ) + { + return (ssgSimpleState*) st ; + } + else + { + ulSetError(UL_WARNING, "createState() did not return simple state"); + } + } + return NULL ; + } + + virtual void endLoad () + { + /* default behavior is to reset sharing after loading a model */ + shared_textures.removeAll () ; + shared_states.removeAll () ; + } + + // + // *** DEPRECATED INTERFACE *** + // for backward compatibility + // derive and use virtual methods to override + // + void setCreateBranchCallback ( ssgBranch *(*cb)(char *) ) + { + create_branch_cb = cb ; + } + void setCreateStateCallback ( ssgState *(*cb)(char *) ) + { + create_state_cb = cb ; + } +} ; + + +int ssgSave ( const char *fname, ssgEntity *ent ) ; +int ssgSaveAC ( const char *fname, ssgEntity *ent ) ; +int ssgSaveASE ( const char *fname, ssgEntity *ent ) ; +int ssgSaveSSG ( const char *fname, ssgEntity *ent ) ; +int ssgSaveDXF ( const char *fname, ssgEntity *ent ) ; +int ssgSaveTRI ( const char *fname, ssgEntity *ent ) ; +int ssgSaveOBJ ( const char *fname, ssgEntity *ent ) ; +int ssgSaveX ( const char *fname, ssgEntity *ent ) ; +int ssgSaveM ( const char *fname, ssgEntity *ent ) ; +int ssgSave3ds ( const char *fname, ssgEntity *ent ) ; +int ssgSaveFLT ( const char *fname, ssgEntity *ent ) ; +int ssgSaveOFF ( const char *fname, ssgEntity *ent ) ; +int ssgSaveQHI ( const char *fname, ssgEntity *ent ) ; +int ssgSaveATG ( const char *fname, ssgEntity *ent ) ; +int ssgSaveVRML1( const char *fname, ssgEntity *ent ) ; +int ssgSaveASC ( const char *fname, ssgEntity *ent ) ; +int ssgSaveIV ( const char *fname, ssgEntity *ent ) ; +int ssgSavePOV ( const char *fname, ssgEntity *ent ) ; + + +ssgEntity *ssgLoad ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoad3ds ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadAC3D ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadASC ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadSSG ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadASE ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadDOF ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadDXF ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadTRI ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadOBJ ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadMD2 ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadMDL ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadX ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadFLT ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadM ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadStrip( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadOFF ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadATG ( const char *fname, const ssgLoaderOptions *options = NULL ) ; +ssgEntity *ssgLoadVRML1( const char *fname, const ssgLoaderOptions* options = NULL ) ; +ssgEntity *ssgLoadIV ( const char *fname, const ssgLoaderOptions* options = NULL ) ; +ssgEntity *ssgLoadXPlaneOBJ ( const char *fname, const ssgLoaderOptions *options = NULL ) ; + + +typedef ssgEntity *ssgLoadFunc ( const char *, const ssgLoaderOptions * ) ; +typedef int ssgSaveFunc ( const char *, ssgEntity * ) ; + +void ssgAddModelFormat ( const char* extension, + ssgLoadFunc *loadfunc , ssgSaveFunc *savefunc ) ; + +/* current loader options */ + +extern ssgLoaderOptions* _ssgCurrentOptions ; + +inline ssgLoaderOptions* ssgGetCurrentOptions () +{ + return _ssgCurrentOptions ; +} + +inline void ssgSetCurrentOptions ( ssgLoaderOptions* options ) +{ + if ( options != NULL ) + _ssgCurrentOptions = options ; +} + +/* For backwards compatibility */ + +inline ssgEntity *ssgLoad ( char *fname, ssgBranch *(*cb)(char *)) +{ + _ssgCurrentOptions -> setCreateBranchCallback ( cb ) ; + return ssgLoad ( fname ) ; +} + +inline void ssgSetAppStateCallback ( ssgState *(*cb)(char *) ) +{ + _ssgCurrentOptions -> setCreateStateCallback ( cb ) ; +} + +inline void ssgModelPath ( const char *path ) +{ + _ssgCurrentOptions -> setModelDir ( path ) ; +} + +inline void ssgTexturePath ( const char *path ) +{ + _ssgCurrentOptions -> setTextureDir ( path ) ; +} + +ssgEntity *ssgLoadAC ( const char *fname, const ssgLoaderOptions *options = NULL ) ; + + +void ssgGetValuesFromLastATGFile(double *x, double *y, double *z, double *r); + + bool ssgConvertTexture( char * fname_output, char * fname_input ) ; + + +class ssgStatistics +{ + int vertex_count ; + int leaf_count ; + +public: + + void reset () ; + + void bumpVertexCount ( int i ) { vertex_count += i ; } + void bumpLeafCount ( int i ) { leaf_count += i ; } + + int getVertexCount () { return vertex_count ; } + int getLeafCount () { return leaf_count ; } + + ssgStatistics () + { + reset () ; + } +} ; + +ssgStatistics *ssgGetLatestStatistics () ; + +/* scene walkers */ + +void ssgFlatten ( ssgEntity *ent ) ; +void ssgStripify ( ssgEntity *ent ) ; +void ssgArrayTool ( ssgEntity *ent, float* vtol = 0, bool make_normals = false ) ; +void ssgTransTool ( ssgEntity *ent, const sgMat4 trans ) ; + +ssgLight *ssgGetLight ( int i ) ; + +char *ssgShowStats () ; +void ssgDelete ( ssgBranch *br ) ; +const char *ssgGetVersion () ; + +void ssgSetLoadOFFTranslucent ( int i ); + +void ssgRegisterType ( int type, ssgBase * ( *create_func ) () ) ; +ssgBase *ssgCreateOfType ( int type ) ; + +#define SSG_BACKFACE_COLLISIONS_SUPPORTED 1 +void ssgSetBackFaceCollisions ( bool b ) ; + +#if (_MSC_VER >= 1700) +// WK +#define SSG_SAVE_TEXT_FILE "wt" +#else +#define SSG_SAVE_TEXT_FILE "wa" +#endif +#endif + diff --git a/src/ssg/ssg3ds.h b/src/ssg/ssg3ds.h new file mode 100644 index 0000000..3247af5 --- /dev/null +++ b/src/ssg/ssg3ds.h @@ -0,0 +1,79 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssg3ds.h 2108 2006-12-11 20:42:05Z fayjf $ +*/ + +/******************************************************* + ** ssg3ds.h + ** + * Common data for ssgLoad3ds.cxx and ssgSave3ds.cxx + *******************************************************/ + +// 3ds chunk identifiers +static const int CHUNK_VERSION = 0x0002; +static const int CHUNK_RGB1 = 0x0010; // 3 floats of RGB +static const int CHUNK_RGB2 = 0x0011; // 3 bytes of RGB +static const int CHUNK_RGB3 = 0x0012; // 3 bytes of RGB (gamma) +static const int CHUNK_AMOUNT = 0x0030; +static const int CHUNK_MAIN = 0x4D4D; +static const int CHUNK_OBJMESH = 0x3D3D; +static const int CHUNK_ONEUNIT = 0x0100; +static const int CHUNK_BKGCOLOR = 0x1200; +static const int CHUNK_AMBCOLOR = 0x2100; +static const int CHUNK_OBJBLOCK = 0x4000; +static const int CHUNK_TRIMESH = 0x4100; +static const int CHUNK_VERTLIST = 0x4110; +static const int CHUNK_FACELIST = 0x4120; +static const int CHUNK_FACEMAT = 0x4130; +static const int CHUNK_MAPLIST = 0x4140; +static const int CHUNK_SMOOLIST = 0x4150; +static const int CHUNK_TRMATRIX = 0x4160; +static const int CHUNK_LIGHT = 0x4600; +static const int CHUNK_SPOTLIGHT = 0x4610; +static const int CHUNK_CAMERA = 0x4700; +static const int CHUNK_MATERIAL = 0xAFFF; +static const int CHUNK_MATNAME = 0xA000; +static const int CHUNK_AMBIENT = 0xA010; +static const int CHUNK_DIFFUSE = 0xA020; +static const int CHUNK_SPECULAR = 0xA030; +static const int CHUNK_SHININESS = 0xA040; +static const int CHUNK_SHINE_STRENGTH = 0xA041; +static const int CHUNK_TRANSPARENCY = 0xA050; +static const int CHUNK_TRANSP_FALLOFF = 0xA052; +static const int CHUNK_DOUBLESIDED = 0xA081; +static const int CHUNK_TEXTURE = 0xA200; +static const int CHUNK_BUMPMAP = 0xA230; +static const int CHUNK_MAPFILENAME = 0xA300; +static const int CHUNK_MAPOPTIONS = 0xA351; +static const int CHUNK_MAP_VSCALE = 0xA354; +static const int CHUNK_MAP_USCALE = 0xA356; +static const int CHUNK_MAP_UOFFST = 0xA358; +static const int CHUNK_MAP_VOFFST = 0xA35A; +static const int CHUNK_KEYFRAMER = 0xB000; +static const int CHUNK_FRAMES = 0xB008; +static const int CHUNK_KEYFRAME_MESH = 0xB002; +static const int CHUNK_FRAME_OBJNAME = 0xB010; +static const int CHUNK_FRAME_DUMMYNAME = 0xB011; +static const int CHUNK_FRAME_PIVOT = 0xB013; +static const int CHUNK_FRAME_POSITION = 0xB020; +static const int CHUNK_FRAME_ROTATION = 0xB021; +static const int CHUNK_FRAME_SCALE = 0xB022; +static const int CHUNK_FRAME_HIERARCHY = 0xB030; diff --git a/src/ssg/ssgAnimTransform.cxx b/src/ssg/ssgAnimTransform.cxx new file mode 100644 index 0000000..bcb0709 --- /dev/null +++ b/src/ssg/ssgAnimTransform.cxx @@ -0,0 +1,174 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998-2004 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgAnimTransform.cxx,v +*/ + +// Written by Wolfram Kuss in Oct 2004 + +#include "ssgLocal.h" + +float _ssgGlobTime = 0.0f; + +const char *ssgAnimTransform::getTypeName (void) { return "ssgAnimTransform" ; } + +void ssgAnimTransform::copy_from ( ssgAnimTransform *src, int clone_flags ) +{ + selectBank ( src->getCurrBank () ) ; + mode = src->mode; + //ARGH!!!!!!!!!!!!!!!!!!!! transformations.copy_from(static_cast(&src->transformations), clone_flags); + ssgBranch::copy_from ( src, clone_flags ) ; +} + +ssgBase *ssgAnimTransform::clone ( int clone_flags ) +{ + ssgAnimTransform *b = new ssgAnimTransform ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + + +ssgAnimTransform::ssgAnimTransform (void) +{ + type = ssgTypeAnimTransform () ; + curr_bank = 0.0f ; + mode = SSGTWEEN_REPEAT; +} + + +ssgAnimTransform::~ssgAnimTransform (void) +{ + removeAllKids () ; +} +// ********* done till here ************* + +void ssgAnimTransform::cull ( sgFrustum *f, sgMat4 m, int test_needed ) +{ + // calculate the transformation + +// comment is partly obsolete: +// You need to have a object with animation loaded into memory for the following function to make sense. +// Animation can be discreet (in steps) or "smooth" (fluid). +// If you loaded an animation made of several meshes, it will use a selector and therefore always be "discreet" +// If you loaded some transformation matrices like some rotations to rotate the flap of a plane, +// the define DISCREET_STEPS will determine whether the animation is smooth (new code, WK) or +// in steps ("old" code, Dave McClurg). +// +// The anim_frame is for discreet animation and an index determining which matrix / which selector will be used. +// For the smooth animation, the parameter curr_time_ms is used that should be the current time, +// Typically in MilliSeconds. However, you can speed up or slow down time. +// You could even stop changing curr_time_ms to freeze the animation. +// +// typically, you will call ssgSetAnimTime directly before you call ssgCullAndDraw +//void ssgSetAnimTime( ssgEntity *e, int anim_frame, long curr_time_ms ) + + + int num = transformations. getNum () ; + if ( num > 0 ) + { +#ifdef DISCREET_STEPS + int frame = curr_bank ; + if ( frame >= num ) + frame = num-1 ; + transformations. selection = frame ; + setTransform ( *( transformations. get ( transformations. selection ) ) ) ; +#else + /* fluid motion */ + ///// copied from ssgTween.cxx and changed var names + + //if(global_mode) + curr_bank = _ssgGlobTime; + + if ( curr_bank < 0.0f ) curr_bank = 0.0f ; + + int state1 = (int) floor ( curr_bank ) ; + int state2 = state1 + 1 ; + float tween = curr_bank - (float) state1 ; + + if ( mode == SSGTWEEN_REPEAT ) + { + state1 %= num ; + state2 %= num ; + } + else + { + if ( state1 >= num ) state1 = num - 1 ; + if ( state2 >= num ) state2 = num - 1 ; + } + + if ( state1 == state2 ) tween = 0.0f; + ///// + + sgMat4 XForm, *pmFrame1; + pmFrame1 = transformations. get ( state1 ); + sgMat4 *pmFrame2 = transformations. get ( state2 ); + for(int i=0;i<4;i++) + for(int j=0; j<4; j++) + XForm[i][j] = tween * ((*pmFrame1)[i][j]) + + (1.0f-tween) * ((*pmFrame2)[i][j]); + setTransform ( XForm ); +#endif + } + + ssgTransform::cull ( f, m, test_needed ) ; +} + + +// ********* below: done ************* + +int ssgAnimTransform::load ( FILE *fd ) +{ + _ssgReadFloat ( fd, & curr_bank ) ; + int int_mode; + _ssgReadInt ( fd, &int_mode ); + mode = int_mode; + transformations.load( fd ); + + return ssgBranch::load ( fd ) ; +} + + +int ssgAnimTransform::save ( FILE *fd ) +{ + _ssgWriteFloat ( fd, curr_bank ) ; + int int_mode = mode; + _ssgWriteInt ( fd, int_mode ); + transformations.save( fd ); + + return ssgBranch::save ( fd ) ; +} + + + +void ssgAnimTransform::print ( FILE *fd, char *indent, int how_much ) +{ + if ( how_much == 0 ) + return ; + + fprintf ( fd, "%sCurrent Bank = %f\n", indent, curr_bank ); + fprintf ( fd, "%sMode = %d\n", indent, (int)mode ); + if ( how_much > 1 ) + transformations.print( fd, indent, how_much ); + + ssgBranch::print ( fd, indent, how_much ) ; +} + + diff --git a/src/ssg/ssgAnimation.cxx b/src/ssg/ssgAnimation.cxx new file mode 100644 index 0000000..2d3b928 --- /dev/null +++ b/src/ssg/ssgAnimation.cxx @@ -0,0 +1,205 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgAnimation.cxx 1725 2002-11-08 18:35:07Z sjbaker $ +*/ + + +#include "ssgLocal.h" + +ulClock ssgTimedSelector::ck; + +void ssgTimedSelector::copy_from ( ssgTimedSelector *src, int clone_flags ) +{ + ssgSelector::copy_from ( src, clone_flags ) ; + + running = src -> running ; + mode = src -> mode ; + time_mode = src -> time_mode ; + + start_time = src -> start_time ; + pause_time = src -> pause_time ; + loop_time = src -> loop_time ; + + delete [] times ; + times = new float [ max_kids ] ; + for ( int i = 0 ; i < max_kids ; i++ ) + times [ i ] = src -> times [ i ] ; + + curr = src -> curr ; + start = src -> start ; + end = src -> end ; +} + + +ssgBase *ssgTimedSelector::clone ( int clone_flags ) +{ + ssgTimedSelector *b = new ssgTimedSelector ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgTimedSelector::ssgTimedSelector ( int max_kids ) : ssgSelector ( max_kids ) +{ + type = ssgTypeTimedSelector () ; + select ( 1 ) ; + running = SSG_ANIM_STOP ; + mode = SSG_ANIM_SHUTTLE ; + start_time = pause_time = 0.0 ; + loop_time = 1.0 ; + + times = new float [ max_kids ] ; + for ( int i = 0 ; i < max_kids ; i++ ) + times [ i ] = 1.0f ; + + curr = start = end = 0 ; + + time_mode = SSG_ANIM_FRAME ; + ck.reset() ; +} + + +void ssgTimedSelector::cull ( sgFrustum *f, sgMat4 m, int test_needed ) +{ + compute_loop_time () ; + selectStep ( getStep () ) ; + ssgSelector::cull ( f, m, test_needed ) ; +} + + +void ssgTimedSelector::hot ( sgVec3 sp, sgMat4 m, int test_needed ) +{ + selectStep ( getStep () ) ; + ssgSelector::hot ( sp, m, test_needed ) ; +} + +void ssgTimedSelector::los ( sgVec3 sp, sgMat4 m, int test_needed ) +{ + selectStep ( getStep () ) ; + ssgSelector::los ( sp, m, test_needed ) ; +} + +void ssgTimedSelector::isect ( sgSphere *sp, sgMat4 m, int test_needed ) +{ + selectStep ( getStep () ) ; + ssgSelector::isect ( sp, m, test_needed ) ; +} + + +int ssgTimedSelector::getStep () +{ + double t = get_time () ; + + if ( running == SSG_ANIM_STOP || running == SSG_ANIM_PAUSE ) + return curr ; + + /* SSG_ANIM_START */ + + t -= start_time ; /* t is time since start of run */ + + if ( mode == SSG_ANIM_ONESHOT ) + { + if ( t >= loop_time ) + { + running = SSG_ANIM_STOP ; + return end ; + } + } + else + if ( mode == SSG_ANIM_SHUTTLE ) + { + /* Compute time since start of this loop */ + + t = t - floor ( t / loop_time ) * loop_time ; + } + else + if ( mode == SSG_ANIM_SWING ) + { + /* Compute time since start of this swing loop */ + + t = t - floor ( t / (2.0 * loop_time) ) * (2.0 * loop_time) ; + + /* Are we on the reverse part of the loop? */ + if ( t >= loop_time ) + t = 2.0 * loop_time - t ; + } + + int k ; + + for ( k = start ; t > 0.0 && k <= end ; k++ ) + t -= (double) times [ k ] ; + +//DaveM: i removed this line because, in shuttle mode, start plays twice + k-- ; + + if ( k < start ) k = start ; + if ( k > end ) k = end ; + + curr = k ; + return curr ; +} + + + +ssgTimedSelector::~ssgTimedSelector (void) +{ + delete [] times ; +} + + + +int ssgTimedSelector::load ( FILE *fd ) +{ + _ssgReadInt ( fd, (int *) & running ) ; + _ssgReadInt ( fd, (int *) & mode ) ; +// _ssgReadDouble( fd, & start_time ) ; +// _ssgReadDouble( fd, & pause_time ) ; +// _ssgReadDouble( fd, & loop_time ) ; + _ssgReadInt ( fd, & max_kids ) ; + delete [] times ; + times = new float [ max_kids ] ; + _ssgReadFloat ( fd, max_kids, times ) ; + _ssgReadInt ( fd, & curr ) ; + _ssgReadInt ( fd, & start ) ; + _ssgReadInt ( fd, & end ) ; + _ssgReadInt ( fd, (int *) & time_mode ) ; + + return ssgSelector::load(fd) ; +} + +int ssgTimedSelector::save ( FILE *fd ) +{ + _ssgWriteInt ( fd, (int) running ) ; + _ssgWriteInt ( fd, (int) mode ) ; +// _ssgWriteFloat ( fd, start_time ) ; +// _ssgWriteFloat ( fd, pause_time ) ; +// _ssgWriteFloat ( fd, loop_time ) ; + _ssgWriteInt ( fd, max_kids ) ; + _ssgWriteFloat ( fd, max_kids, times ) ; + _ssgWriteInt ( fd, curr ) ; + _ssgWriteInt ( fd, start ) ; + _ssgWriteInt ( fd, end ) ; + _ssgWriteInt ( fd, (int) time_mode ) ; + + return ssgSelector::save(fd) ; +} + + diff --git a/src/ssg/ssgAxisTransform.cxx b/src/ssg/ssgAxisTransform.cxx new file mode 100644 index 0000000..c1c95bf --- /dev/null +++ b/src/ssg/ssgAxisTransform.cxx @@ -0,0 +1,128 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgAxisTransform.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "ssgLocal.h" + +void ssgAxisTransform::copy_from ( ssgAxisTransform *src, int clone_flags ) +{ + ssgBaseTransform::copy_from ( src, clone_flags ) ; + + sgCopyVec3 ( rotation_axis , src->rotation_axis ) ; + sgCopyVec3 ( rotation_center, src->rotation_center ) ; + limit_low = src->limit_low ; + limit_high = src->limit_high ; +} + +ssgBase *ssgAxisTransform::clone ( int clone_flags ) +{ + ssgAxisTransform *b = new ssgAxisTransform ; + b -> copy_from ( this, clone_flags ) ; + return b; +} + +ssgAxisTransform::ssgAxisTransform (void) +{ + type = ssgTypeAxisTransform () ; + sgZeroVec3 ( rotation_axis ) ; + limit_low = limit_high = 0.f; +} + +ssgAxisTransform::ssgAxisTransform ( sgVec3 axis, sgVec3 center ) +{ + type = ssgTypeAxisTransform () ; + setAxis ( axis ); + setCenter ( center ); + limit_low = limit_high = 0.f; +} + +ssgAxisTransform::~ssgAxisTransform (void) +{ +} + +void ssgAxisTransform::setAxis ( sgVec3 axis ) +{ + sgCopyVec3 ( rotation_axis, axis ) ; +} + +float *ssgAxisTransform::getAxis (void) +{ + return rotation_axis; +} + +void ssgAxisTransform::setCenter ( sgVec3 center ) +{ + sgCopyVec3 ( rotation_center, center ) ; +} + +float *ssgAxisTransform::getCenter (void) +{ + return rotation_center; +} + +void ssgAxisTransform::setRotation ( float rot ) +{ + sgMat4 rot_mat ; + sgMat4 trans1, trans2; + sgVec3 neg_center; + + sgNegateVec3 ( neg_center, rotation_center ) ; + + sgMakeTransMat4 ( trans1 , neg_center ) ; + sgMakeTransMat4 ( trans2 , rotation_center ) ; + sgMakeRotMat4 ( rot_mat, rot, rotation_axis ) ; + sgPreMultMat4 ( rot_mat, trans1 ) ; + sgPostMultMat4 ( rot_mat, trans2 ) ; + + setTransform ( rot_mat ) ; +} + +void ssgAxisTransform::setRotationLimits ( float low, float high ) +{ + limit_low = low ; + limit_high = high ; +} + +void ssgAxisTransform::setLinearRotation ( float rot ) +{ + assert( rot >= 0.0f && rot <= 1.0f ); + setRotation( limit_low + (limit_high - limit_low) * rot ) ; +} + +int ssgAxisTransform::load ( FILE *fd ) +{ + _ssgReadFloat ( fd, 3, rotation_axis ) ; + _ssgReadFloat ( fd, 3, rotation_center ) ; + _ssgReadFloat ( fd, & limit_low ) ; + _ssgReadFloat ( fd, & limit_high ) ; + return ssgTransform::load(fd) ; +} + +int ssgAxisTransform::save ( FILE *fd ) +{ + _ssgWriteFloat ( fd, 3, rotation_axis ) ; + _ssgWriteFloat ( fd, 3, rotation_center ) ; + _ssgWriteFloat ( fd, limit_low ) ; + _ssgWriteFloat ( fd, limit_high ) ; + return ssgTransform::save(fd) ; +} diff --git a/src/ssg/ssgBase.cxx b/src/ssg/ssgBase.cxx new file mode 100644 index 0000000..aac54cc --- /dev/null +++ b/src/ssg/ssgBase.cxx @@ -0,0 +1,138 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgBase.cxx 1673 2002-09-15 01:29:12Z ude $ +*/ + + +#include "ssgLocal.h" + +static int next_unique_id = 1 ; + +void *ssgBase::operator new ( size_t sz ) +{ + return malloc ( sz ) ; +} + +void ssgBase::operator delete ( void *ptr ) +{ + free ( ptr ) ; +} + +void ssgBase::copy_from ( ssgBase *src, int clone_flags ) +{ + if ( this == src ) + return ; /* Avoid corrupting userdata when copying to self */ + + // type = src -> getType () ; - cannot change the virtual function table... + spare = src -> getSpare () ; + // refc = 0 ; - okay? + + if ( clone_flags & SSG_CLONE_USERDATA ) + setUserData ( src -> getUserData () ) ; + else + setUserData ( NULL ) ; + + setName ( src -> getName () ) ; +} + + + +ssgBase *ssgBase::clone ( int /* clone_flags */ ) +{ + ulSetError ( UL_FATAL, "SSG: Can't clone abstract SSG class objects" ) ; + return NULL ; +} + +ssgBase:: ssgBase (void) +{ + spare = refc = 0 ; + type = ssgTypeBase () ; + unique = next_unique_id++ ; + user_data = NULL ; + name = NULL ; +} + +ssgBase::~ssgBase (void) +{ + ssgDeRefDelete ( user_data ) ; + + deadBeefCheck () ; + assert ( refc == 0 ) ; + + delete [] name ; + + /* + Set the type of deleted nodes to 0xDeadBeef so we'll + stand a chance of detecting re-use of deleted nodes. + */ + + type = (int) 0xDeadBeef ; +} + + +void ssgBase::setName ( const char *nm ) +{ + delete [] name ; + + if ( nm == NULL ) + name = NULL ; + else + name = ulStrDup ( nm ) ; +} + +void ssgBase::zeroSpareRecursive (){ zeroSpare () ; } +void ssgBase::zeroSpare () { spare = 0 ; } +void ssgBase::incSpare () { spare++ ; } +void ssgBase::setSpare ( int ss ) { spare = ss ; } +int ssgBase::getSpare () { return spare ; } + + +void ssgBase::print ( FILE *fd, char *indent, int how_much ) +{ + if ( how_much > 2 ) + { + fprintf ( fd, "%s%s: Ref Count=%d\n", indent, getTypeName(), getRef () ) ; + fprintf ( fd, "%s Name = \"%s\"\n", indent, getPrintableName() ) ; + } + else + fprintf ( fd, "%s%s: Name=%s\n", indent, getTypeName(), getPrintableName()); + + if ( how_much > 1 ) + fprintf ( fd, "%s Userdata = %p\n", indent, getUserData() ) ; + + deadBeefCheck () ; +} + +int ssgBase::load ( FILE *fd ) +{ + delete [] name ; + name = NULL ; + _ssgReadString ( fd, &name ) ; + return ! _ssgReadError () ; +} + +int ssgBase::save ( FILE *fd ) +{ + _ssgWriteString ( fd, name ) ; + return ! _ssgWriteError () ; +} + + diff --git a/src/ssg/ssgBaseTransform.cxx b/src/ssg/ssgBaseTransform.cxx new file mode 100644 index 0000000..d170ac9 --- /dev/null +++ b/src/ssg/ssgBaseTransform.cxx @@ -0,0 +1,79 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgBaseTransform.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "ssgLocal.h" + +void ssgBaseTransform::copy_from ( ssgBaseTransform *src, int clone_flags ) +{ + ssgBranch::copy_from ( src, clone_flags ) ; + + src -> getTransform ( transform ) ; + src -> getLastTransform ( last_transform ) ; + last_updated = src -> last_updated ; + first_time = src -> first_time ; +} + + + +ssgBaseTransform::ssgBaseTransform (void) +{ + type = ssgTypeBaseTransform () ; + last_updated = -9999999 ; + first_time = TRUE ; + sgMakeIdentMat4 ( transform ) ; + sgMakeIdentMat4 ( last_transform ) ; +} + +ssgBaseTransform::~ssgBaseTransform (void) +{ +} + + +int ssgBaseTransform::load ( FILE *fd ) +{ + _ssgReadMat4 ( fd, transform ) ; + updateTransform () ; + first_time = TRUE ; + return ssgBranch::load(fd) ; +} + +int ssgBaseTransform::save ( FILE *fd ) +{ + _ssgWriteMat4 ( fd, transform ) ; + return ssgBranch::save(fd) ; +} + + +void ssgBaseTransform::print ( FILE *fd, char *indent, int how_much ) +{ + ssgBranch::print ( fd, indent, how_much ) ; + + if ( how_much >= 2 ) + for ( int row = 0 ; row < 4 ; row++ ) + fprintf ( fd, "%s Transform[%d]= %f,%f,%f,%f\n", indent, row, + transform[row][0], transform[row][1], + transform[row][2], transform[row][3] ) ; +} + + diff --git a/src/ssg/ssgBranch.cxx b/src/ssg/ssgBranch.cxx new file mode 100644 index 0000000..db3708b --- /dev/null +++ b/src/ssg/ssgBranch.cxx @@ -0,0 +1,631 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgBranch.cxx 1860 2004-02-16 20:51:12Z stromberg $ +*/ + + +#include "ssgLocal.h" + +void ssgBranch::copy_from ( ssgBranch *src, int clone_flags ) +{ + ssgEntity::copy_from ( src, clone_flags ) ; + + for ( int i = 0 ; i < src -> getNumKids () ; i++ ) + { + ssgEntity *k = src -> getKid ( i ) ; + + if ( k != NULL && ( clone_flags & SSG_CLONE_RECURSIVE ) ) + addKid ( (ssgEntity *)( k -> clone ( clone_flags )) ) ; + else + addKid ( k ) ; + } +} + +ssgBase *ssgBranch::clone ( int clone_flags ) +{ + ssgBranch *b = new ssgBranch ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + + +ssgBranch::ssgBranch (void) +{ + type = ssgTypeBranch () ; +} + + +ssgBranch::~ssgBranch (void) +{ + removeAllKids () ; +} + + +void ssgBranch::zeroSpareRecursive () +{ + zeroSpare () ; + + for ( ssgEntity *k = getKid ( 0 ) ; k != NULL ; k = getNextKid () ) + k -> zeroSpareRecursive () ; +} + + +void ssgBranch::recalcBSphere (void) +{ + emptyBSphere () ; + + for ( ssgEntity *k = getKid ( 0 ) ; k != NULL ; k = getNextKid () ) + extendBSphere ( k -> getBSphere () ) ; + + bsphere_is_invalid = FALSE ; +} + + +void ssgBranch::addKid ( ssgEntity *entity ) +{ + kids. addEntity ( entity ) ; + entity -> addParent ( this ) ; + dirtyBSphere () ; +} + + +void ssgBranch::removeKid ( int n ) +{ + ssgEntity *k = kids.getEntity ( n ) ; + + if ( k != NULL ) { + k -> removeParent ( this ) ; + kids.removeEntity ( n ) ; + dirtyBSphere () ; + } +} + + +void ssgBranch::removeKid ( ssgEntity *entity ) +{ + removeKid( searchForKid( entity ) ); +} + + +void ssgBranch::removeAllKids (void) +{ + for ( int k = getNumKids() - 1; k >= 0; --k ) { + removeKid ( k ) ; + } +} + + +void ssgBranch::replaceKid ( int n, ssgEntity *new_entity ) +{ + if ( n >= 0 && n < getNumKids () ) + { + getKid ( n ) -> removeParent ( this ) ; + kids.replaceEntity ( n, new_entity ) ; + new_entity -> addParent ( this ) ; + dirtyBSphere () ; + } +} + +void ssgBranch::replaceKid ( ssgEntity *old_entity, ssgEntity *new_entity ) +{ + replaceKid ( searchForKid( old_entity ), new_entity ) ; +} + + +void ssgBranch::print ( FILE *fd, char *indent, int how_much ) +{ + ssgEntity::print ( fd, indent, how_much ) ; + fprintf ( fd, "%s Num Kids=%d\n", indent, getNumKids() ) ; + + if ( getNumParents() != getRef() ) + ulSetError ( UL_WARNING, "Ref count doesn't tally with parent count" ) ; + + if ( how_much > 1 ) + { if ( bsphere.isEmpty() ) + fprintf ( fd, "%s BSphere is Empty.\n", indent ) ; + else + fprintf ( fd, "%s BSphere R=%g, C=(%g,%g,%g)\n", indent, + bsphere.getRadius(), bsphere.getCenter()[0], bsphere.getCenter()[1], bsphere.getCenter()[2] ) ; + } + + char in [ 100 ] ; + sprintf ( in, "%s ", indent ) ; + + for ( ssgEntity *e = getKid ( 0 ) ; e != NULL ; e = getNextKid() ) + e -> print ( fd, in, how_much ) ; +} + + +void ssgBranch::getStats ( int *num_branches, int *num_leaves, int *num_tris, int *num_verts ) +{ + int nb, nl, nt, nv ; + + *num_branches = 1 ; /* this! */ + *num_leaves = 0 ; + *num_tris = 0 ; + *num_verts = 0 ; + + for ( int i = 0 ; i < getNumKids () ; i++ ) + { + ssgEntity *e = getKid ( i ) ; + + e -> getStats ( & nb, & nl, & nt, & nv ) ; + *num_branches += nb ; + *num_leaves += nl ; + *num_tris += nt ; + *num_verts += nv ; + } +} + + +ssgEntity *ssgBranch::getByName ( char *match ) +{ + if ( getName() != NULL && strcmp ( getName(), match ) == 0 ) + return this ; + + /* Otherwise check the kids for a match */ + + for ( ssgEntity* k = getKid ( 0 ) ; k != NULL ; k = getNextKid() ) + { + ssgEntity *e = k -> getByName ( match ) ; + + if ( e != NULL ) + return e ; + } + + return NULL ; +} + + +ssgEntity *ssgBranch::getByPath ( char *path ) +{ + /* Ignore leading '/' */ + + if ( *path == '/' ) + ++path ; + + char *n = getName () ; + + /* + If this node has no name then pass the request down the tree + */ + + if ( n == NULL ) + { + for ( ssgEntity* k = getKid ( 0 ) ; k != NULL ; k = getNextKid () ) + { + ssgEntity *e = k -> getByPath ( path ) ; + + if ( e != NULL ) + return e ; + } + + return NULL ; + } + + /* + If this node does have a name - but it doesn't match the + next part of the path then punt. + */ + + unsigned int l = strlen ( n ) ; + + if ( strlen ( path ) < l || strncmp ( n, path, l ) != 0 ) + return NULL ; + + /* + If the first part of the path is this ssgBranch, we + may have a winner. + */ + + char c = path [ l ] ; + + /* If we reached the end of the path - we win! */ + + if ( c == '\0' ) + return this ; + + if ( c == '/' ) + { + /* If the path continues, try to follow the path to the kids */ + + for ( ssgEntity* k = getKid ( 0 ) ; k != NULL ; k = getNextKid () ) + { + ssgEntity *e = k -> getByPath ( path + l ) ; + + if ( e != NULL ) + return e ; + } + } + + return NULL ; +} + + + +void ssgBranch::cull ( sgFrustum *f, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_CULL ) ) + return ; + + int cull_result = cull_test ( f, m, test_needed ) ; + + if ( cull_result == SSG_OUTSIDE ) + return ; + + for ( ssgEntity *e = getKid ( 0 ) ; e != NULL ; e = getNextKid() ) + e -> cull ( f, m, cull_result != SSG_INSIDE ) ; + + postTravTests ( SSGTRAV_CULL ) ; +} + + + +void ssgBranch::hot ( sgVec3 s, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_HOT ) ) + return ; + + int hot_result = hot_test ( s, m, test_needed ) ; + + if ( hot_result == SSG_OUTSIDE ) + return ; + + _ssgPushPath ( this ) ; + + for ( ssgEntity *e = getKid ( 0 ) ; e != NULL ; e = getNextKid() ) + e -> hot ( s, m, hot_result != SSG_INSIDE ) ; + + _ssgPopPath () ; + + postTravTests ( SSGTRAV_HOT ) ; +} + + + +void ssgBranch::los ( sgVec3 s, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_LOS ) ) + return ; + + int los_result = los_test ( s, m, test_needed ) ; + + if ( los_result == SSG_OUTSIDE ) + return ; + + _ssgPushPath ( this ) ; + + for ( ssgEntity *e = getKid ( 0 ) ; e != NULL ; e = getNextKid() ) + e -> los ( s, m, los_result != SSG_INSIDE ) ; + + _ssgPopPath () ; + + postTravTests ( SSGTRAV_LOS) ; +} + + +void ssgBranch::isect ( sgSphere *s, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_ISECT ) ) + return ; + + int isect_result = isect_test ( s, m, test_needed ) ; + + if ( isect_result == SSG_OUTSIDE ) + return ; + + _ssgPushPath ( this ) ; + + for ( ssgEntity *e = getKid ( 0 ) ; e != NULL ; e = getNextKid() ) + e -> isect ( s, m, isect_result != SSG_INSIDE ) ; + + _ssgPopPath () ; + + postTravTests ( SSGTRAV_ISECT ) ; +} + + +int ssgBranch::load ( FILE *fd ) +{ + int nkids ; + + _ssgReadInt ( fd, & nkids ) ; + + if ( ! ssgEntity::load ( fd ) ) + return FALSE ; + + for ( int i = 0 ; i < nkids ; i++ ) + { + ssgEntity *kid ; + + if ( ! _ssgLoadObject ( fd, (ssgBase **) &kid, ssgTypeEntity () ) ) + return FALSE ; + + addKid ( kid ) ; + } + + return TRUE ; +} + + +int ssgBranch::save ( FILE *fd ) +{ + _ssgWriteInt ( fd, getNumKids() ) ; + + if ( ! ssgEntity::save ( fd ) ) + return FALSE ; + + for ( int i = 0 ; i < getNumKids() ; i++ ) + { + if ( ! _ssgSaveObject ( fd, getKid ( i ) ) ) + return FALSE ; + } + + return TRUE ; +} + +// ----------------------- code by W.K for merging hierarchy nodes ------------------------------ + + +// #define VERBOSE +int maxTriangles = 100; // Thats a nice value for handling MDL files for BoB. + // You might want to assign another value, possibly -1 before calling mergeHNodes +int maxVertices = 195; // see maxTriangles + + + +static int noOfMergedNodes; // number of merged nodes + +void AddLeafToTriangles(ssgVtxArray *pSrc , ssgVtxArray *pDest) +// pDest must be of type GL_TRIANGLES +// So, this function adds the contents of a leaf to a GL_TRIANGLES node. +{ + // Add vertices and keep track of old to new indexes + if(pSrc->getNumTriangles()==0) return; // wk 14.7.2002 + int * aiOld2NewIndex = new int[pSrc->getNumVertices()]; + int iSrc; // iDest; + for(iSrc = 0; iSrc < pSrc->getNumVertices(); iSrc++) + { float * pfSrc = pSrc->getVertex(iSrc); + int bFound = FALSE; + /* test + for(iDest = 0; iDest < pDest->getNumVertices(); iDest++) + { float * pfDest = pDest->getVertex(iDest); +#define MYABS(x) ((x>0)?(x):(-(x))) + if (MYABS(pfSrc[0]-pfDest[0])+MYABS(pfSrc[1]-pfDest[1])+ + MYABS(pfSrc[2]-pfDest[2]) < 0.0001) + { bFound = TRUE; + aiOld2NewIndex[iSrc] = iDest; + } + }*/ + if(!bFound) + { aiOld2NewIndex[iSrc] = pDest->getNumVertices(); + pDest->vertices->add(pfSrc); + float * f = pSrc->getNormal(iSrc); + if (f) + pDest->normals->add(f); + else + { + pDest->normals->add(_ssgNormalUp); + } + f = pSrc->getTexCoord(iSrc); + if (f) + pDest->texcoords->add(f); + else + { + pDest->texcoords->add(_ssgTexCoord00); + } + // assert(pSrc->colours->getNum()==0); + } + + } + // Add faces + pDest->addIndex(aiOld2NewIndex[*pSrc->getIndex(0)]); + pDest->addIndex(aiOld2NewIndex[*pSrc->getIndex(1)]); + pDest->addIndex(aiOld2NewIndex[*pSrc->getIndex(2)]); + if(pSrc->getGLtype()==GL_TRIANGLE_FAN) + { + for(iSrc=1;iSrcgetNumTriangles();iSrc++) + { // add 0, i+1, i+2 + pDest->addIndex(aiOld2NewIndex[*pSrc->getIndex(0)]); + pDest->addIndex(aiOld2NewIndex[*pSrc->getIndex(iSrc+1)]); + pDest->addIndex(aiOld2NewIndex[*pSrc->getIndex(iSrc+2)]); + + } + } + else + { assert(pSrc->getGLtype()==GL_TRIANGLES); + for(iSrc=1;iSrcgetNumTriangles();iSrc++) + { // add 0, i+1, i+2 + pDest->addIndex(aiOld2NewIndex[*pSrc->getIndex(iSrc*3)]); + pDest->addIndex(aiOld2NewIndex[*pSrc->getIndex(iSrc*3+1)]); + pDest->addIndex(aiOld2NewIndex[*pSrc->getIndex(iSrc*3+2)]); + + } + } + + // State + pDest->setState(pSrc ->getState()); + delete aiOld2NewIndex ; +} + + + +void recursiveMergeHNodes ( ssgEntity *root, int delta ) +// This is the recursive part of "mergeHNodes". +// Walks the scene graph and looks for nodes to merge. +// Uses AddLeafToTriangles for the actual merging +{ + if ( root == NULL ) + return ; + + if ( root -> isAKindOf ( ssgTypeBranch() ) ) + { // see whether we can merge some of the kids + ssgBranch *b = (ssgBranch *) root ; + + int i1, // loop var. + oldnk=b -> getNumKids (), oldi1=-1 ; // for debug purpose only + i1 = 0 ; + while(i1 < b -> getNumKids () ) + { + // check that each loop increases i1 or decreases b -> getNumKids () + if(!((i1>oldi1) || (oldnk>b ->getNumKids ()))) + break; + assert((i1>oldi1) || (oldnk>b ->getNumKids ())); + oldi1=i1; + oldnk=b ->getNumKids (); + + ssgEntity * pThis = b -> getKid ( i1 ) ; + if ( pThis -> isAKindOf ( ssgTypeBranch() ) ) + { recursiveMergeHNodes ( pThis, delta ); // recursively go deeper into the scene graph + i1++; + } + else if(( pThis -> isAKindOf ( ssgTypeLeaf() ) ) && (i1+delta < b -> getNumKids ())) + { ssgEntity * pOther = b -> getKid ( i1+delta ); + if( pOther -> isAKindOf ( ssgTypeLeaf() ) ) + { ssgLeaf *l1 = (ssgLeaf *)pThis, *l2 = (ssgLeaf *)pOther; + // now: l1 = kid at i1, l2 = kid at i1+delta + if ( (l1->getState() == l2->getState()) && + ((maxTriangles < 0) || (l1->getNumTriangles()+l2->getNumTriangles()getNumVertices()+l2->getNumVertices()getPrintableName(), l2->getPrintableName())) + ) + { + if (((l1->getGLtype() == GL_TRIANGLE_FAN) || (l1->getGLtype() == GL_TRIANGLES)) && + ((l2->getGLtype() == GL_TRIANGLE_FAN) || (l2->getGLtype() == GL_TRIANGLES))) + { // For using MDL files, these are all the types that we need ... + + if (l1->isA(ssgTypeVtxTable())) + { l1 = ((ssgVtxTable *)l1)->getAs_ssgVtxArray(); // Kludge: mem leak + b->replaceKid ( i1, l1 ) ; + } + if (l2->isA(ssgTypeVtxTable())) + { l2 = ((ssgVtxTable *)l2)->getAs_ssgVtxArray(); // Kludge: mem leak + b->replaceKid ( i1+delta, l2 ) ; + } + assert(l1 -> isAKindOf ( ssgTypeVtxArray() )); + assert(l2 -> isAKindOf ( ssgTypeVtxArray() )); + if((l1->getNumTriangles()+l2->getNumTriangles())<1300) // ??? wk kludge + { +#ifdef VERBOSE + printf("I do sthg :-) %d\n", noOfMergedNodes++); +#else + noOfMergedNodes++; +#endif + if(l1->getGLtype() == GL_TRIANGLE_FAN) // convert to GL_TRIANGLES + { ssgVtxArray * pNewArray = new ssgVtxArray(GL_TRIANGLES, + new ssgVertexArray(), + new ssgNormalArray(), new ssgTexCoordArray(), + new ssgColourArray(), new ssgIndexArray()); + AddLeafToTriangles((ssgVtxArray *)l1, pNewArray); + pNewArray->setName(l1->getPrintableName()); + assert(l1==b->getKid(i1)); + b->removeKid(i1); + b->addKid(pNewArray); + pNewArray->dirtyBSphere (); + l1 = pNewArray; + } + // l1 is of type GL_TRIANGLES now. + { //ssgEntity *t= b->getKid(i1+delta); + //assert(l2==t); + } + AddLeafToTriangles((ssgVtxArray *)l2, (ssgVtxArray *)l1); + l1->dirtyBSphere (); + l2->dirtyBSphere (); // unnessesary ? + b->removeKid(l2); // kid(i1+delta) changed because of remove!?! i1+delta); + } + } + else + { i1++; + printf("wrong types: %ld, %ld, num Trias: %ld, %ld\n", + (long)l1->getGLtype(), (long)l1->getGLtype(), + (long)l1->getNumTriangles(), (long)l2->getNumTriangles()); + } + } + else + i1++; + } + else + i1++; + } + else + i1++; + } + + + +/* + int i1=0; + for ( i = 0 ; i < b -> getNumKids () ; i++ ) + { ssgEntity * pThis = b -> getKid ( i1 ) ; + if ( pThis -> isAKindOf ( ssgTypeBranch() ) ) + { recursiveMergeHNodes ( pThis ); + i1++; + } + else + { assert( pThis -> isAKindOf ( ssgTypeLeaf() ) ); + ssgLeaf *l1 = (ssgLeaf *)pThis; + assert(l1 -> isAKindOf ( ssgTypeVtxArray() )); + static int noOfMergedNodes=0; + printf("I could do sthg :-) %d\n", noOfMergedNodes++); + assert(l1->getGLtype() == GL_TRIANGLE_FAN); // convert to GL_TRIANGLES + ssgVtxArray * pNewArray = new ssgVtxArray(GL_TRIANGLES, + new ssgVertexArray(), new ssgNormalArray(), + new ssgTexCoordArray(), new ssgColourArray(), + new ssgIndexArray()); + AddLeafToTriangles((ssgVtxArray *)l1, pNewArray); + b->removeKid(i1); + pNewArray->dirtyBSphere (); + b->addKid(pNewArray); + + pNewArray->setName("meins!"); + } + + } + */ + } +} + + +void ssgBranch::mergeHNodes() +// merges hierarchy nodes if (not iff :-/): +// a) Both have the same state +// b) the same name +// c) the result would not have more than maxTriangles triangles (if maxTriangles is negative, this is not checked). +// d) the result would not have more than maxVertices vertices (if maxVertices is negative, this is not checked). +// e) both are of type GL_TRIANGLE_FAN or GL_TRIANGLES +{ + + +int deltas[] = { 1 ,2 ,1 ,3 ,2 ,1 ,2 ,4 ,2 ,1 ,5 ,1 ,2 ,6 ,2 ,1 ,2 ,7 ,2 ,1 ,2 ,1 ,8 ,1 ,2 ,1 ,2 ,9 ,2 ,1 ,2 ,1, + 10 ,1 ,2 ,1 ,2 ,11 ,1 ,12 ,1 ,2 ,13 ,1 ,2 ,14 ,2 ,1 ,1 ,15 ,1 ,16 ,1 ,17 ,2 ,1 ,18 ,1 ,22 ,2 ,25 , + 2 ,1 ,30 ,2 ,1 ,2 ,1 ,13 ,2 ,1 ,2 ,1 }; + noOfMergedNodes = 0; + for(unsigned i=0; i < sizeof(deltas)/sizeof(int); i++) + { + recursiveMergeHNodes ( this, deltas[i] ); +#ifdef VERBOSE + printf("############################################### ^%d\n". deltas[i]); +#endif + } + printf("%d nodes were merged!\n", noOfMergedNodes); +} + diff --git a/src/ssg/ssgContext.cxx b/src/ssg/ssgContext.cxx new file mode 100644 index 0000000..4d05bea --- /dev/null +++ b/src/ssg/ssgContext.cxx @@ -0,0 +1,292 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgContext.cxx 1736 2002-12-02 15:04:06Z sjbaker $ +*/ + + +#include "ssgLocal.h" + +ssgContext *_ssgCurrentContext = NULL ; + +ssgContext::~ssgContext () +{ + if ( isCurrent() ) + _ssgCurrentContext = NULL ; + + //~~ T.G. was ordinary delete before - must be derefed + ssgDeRefDelete ( currentState ); + ssgDeRefDelete ( basicState ); + + delete frustum ; +} + + +ssgContext::ssgContext () +{ + makeCurrent () ; + currentState = NULL ; + basicState = NULL ; + //orthographic = FALSE ; + cullFace = TRUE ; + ovTexture = FALSE ; + ovCullface = FALSE ; + ovState = NULL ; + sgCopyMat4 ( cameraMatrix, _ssgOpenGLAxisSwapMatrix ) ; + + frustum = new sgFrustum ; + frustum -> setNearFar ( 1.0, 10000.0 ) ; + frustum -> setFOV ( 60.0, 45.0 ) ; + + currentState = new ssgSimpleState ( 1 ) ; + currentState -> ref(); //~~ T.G. + + basicState = new ssgSimpleState ( 0 ) ; + basicState -> ref(); //~~ T.G. + + currentState -> force () ; + + /* The order of the two following lines is essential. + setTexture(NULL) currently sets the TEXTURE bit in + dont_care... not the desired effect here. /PL */ + + basicState->setTexture ( (ssgTexture*) NULL ) ; + basicState->dont_care = 0 ; + basicState->colour_material_mode = GL_AMBIENT_AND_DIFFUSE ; + sgSetVec4(basicState->specular_colour,1.0f,1.0f,1.0f,1.0f); + sgSetVec4(basicState->emission_colour,0.0f,0.0f,0.0f,1.0f); + sgSetVec4(basicState->ambient_colour, 1.0f,1.0f,1.0f,1.0f); + sgSetVec4(basicState->diffuse_colour, 1.0f,1.0f,1.0f,1.0f); + basicState->shade_model = GL_SMOOTH ; + basicState->shininess = 0.0f ; + basicState->alpha_clamp = 0.01f ; + + for ( int i = 0 ; i < 6 ; i++ ) + sgSetVec4 ( clipPlane[i], 0, 0, 1, 0 ) ; + + enabledClipPlanes = 0 ; + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} + + +int ssgContext::isCurrent () +{ + return _ssgCurrentContext == this ; +} + +void ssgContext::forceBasicState () +{ + if ( ! ovCullface ) + glEnable ( GL_CULL_FACE ) ; + + cullFace = TRUE ; + + if ( ovState != NULL ) + ovState -> force () ; + else + basicState -> force () ; +} + + +void ssgContext::makeCurrent () +{ + _ssgCurrentContext = this ; +} + +void ssgContext::getCameraPosition ( sgVec3 pos ) +{ + sgCopyVec3 ( pos, cameraMatrix [ 3 ] ) ; +} + +void ssgContext::overrideState ( ssgState *s ) +{ + ovState = s ; +} + +void ssgContext::overrideTexture ( int on_off ) +{ + ovTexture = on_off ; +} + +void ssgContext::overrideCullface ( int on_off ) +{ + ovCullface = on_off ; +} + + +void ssgContext::setFrustum ( float l, float r, float b, float t, float n, float f ) +{ + frustum -> setFrustum ( l, r, b, t, n, f ) ; +} + +void ssgContext::setOrtho ( float l, float r, float b, float t, float n, float f ) +{ + frustum -> setOrtho ( l, r, b, t, n, f ) ; +} + +void ssgContext::getNearFar ( float *n, float *f ) +{ + frustum -> getNearFar ( n, f ) ; +} + +void ssgContext::getFOV ( float *w, float *h ) +{ + frustum -> getFOV ( w, h ) ; +} + +void ssgContext::setNearFar ( float n, float f ) +{ + frustum -> setNearFar ( n, f ) ; +} + +void ssgContext::getOrtho ( float *w, float *h ) +{ + frustum -> getOrtho ( w, h ) ; +} + +void ssgContext::setOrtho ( float w, float h ) +{ + frustum -> setOrtho ( w, h ) ; +} + +void ssgContext::setFOV ( float w, float h ) +{ + frustum -> setFOV ( w, h ) ; +} + + +void ssgContext::setCamera ( sgMat4 mat ) +{ + sgMat4 viewmat ; + + sgTransposeNegateMat4 ( viewmat, mat ) ; + + sgCopyMat4 ( cameraMatrix, _ssgOpenGLAxisSwapMatrix ) ; + sgPreMultMat4 ( cameraMatrix, viewmat ) ; +} + +void ssgContext::setCamera ( const sgCoord *coord ) +{ + sgMat4 viewmat, mat ; + + sgMakeCoordMat4 ( mat, coord ) ; + sgTransposeNegateMat4 ( viewmat, mat ) ; + + sgCopyMat4 ( cameraMatrix, _ssgOpenGLAxisSwapMatrix ) ; + sgPreMultMat4 ( cameraMatrix, viewmat ) ; +} + +void ssgContext::setCameraLookAt ( const sgVec3 eye, const sgVec3 center, const sgVec3 up ) +{ + sgMat4 mat ; + sgMakeLookAtMat4 ( mat, eye, center, up ) ; + + setCamera ( mat ) ; +} + +void ssgContext::setCameraLookAt ( const sgVec3 eye, const sgVec3 center ) +{ + sgVec3 up ; + sgSetVec3 ( up, 0.0f, 0.0f, 1.0f ) ; + + sgMat4 mat ; + sgMakeLookAtMat4 ( mat, eye, center, up ) ; + + setCamera ( mat ) ; +} + +void ssgContext::loadProjectionMatrix() +{ + glLoadIdentity () ; + pushProjectionMatrix () ; +} + +void ssgContext::pushProjectionMatrix () +{ + pushProjectionMatrix ( frustum ) ; +} + +void ssgContext::pushProjectionMatrix ( sgFrustum *f ) +{ + if ( f -> isOrtho() ) + glOrtho ( f -> getLeft() , f -> getRight(), + f -> getBot () , f -> getTop (), + f -> getNear() , f -> getFar () ) ; + else + glFrustum ( f -> getLeft() , f -> getRight(), + f -> getBot () , f -> getTop (), + f -> getNear() , f -> getFar () ) ; +} + +void ssgContext::getProjectionMatrix ( sgMat4 dst ) +{ + frustum -> getMat4 ( dst ) ; +} + +void ssgContext::getModelviewMatrix ( sgMat4 dst ) +{ + sgCopyMat4 ( dst, cameraMatrix ) ; +} + +void ssgContext::loadModelviewMatrix () +{ + glLoadMatrixf ( (float *) cameraMatrix ) ; +} + +void ssgContext::loadModelviewMatrix ( sgMat4 mat ) +{ + glLoadMatrixf ( (float *) mat ) ; +} + +void ssgContext::cull ( ssgBranch *r ) +{ + r -> cull ( frustum, cameraMatrix, TRUE ) ; +} + + +void ssgContext::removeClipPlanes () +{ + for ( int i = 0 ; i < 6 ; i++ ) + glDisable ( (GLenum)( GL_CLIP_PLANE0 + i) ) ; +} + +void ssgContext::applyClipPlanes () +{ + if ( enabledClipPlanes == 0 ) + return ; + + for ( int i = 0 ; i < 6 ; i++ ) + { + if ( enabledClipPlanes & (1< isPointRotate () ; +} + +ssgBase *ssgCutout::clone ( int clone_flags ) +{ + ssgCutout *b = new ssgCutout ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgCutout::ssgCutout (int pntrot) +{ + point_rotate = pntrot ; + type = ssgTypeCutout () ; +} + +ssgCutout::~ssgCutout () +{ +} + + +void ssgCutout::cull ( sgFrustum *f, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_CULL ) ) + return ; + + sgMat4 tmp ; + + if ( point_rotate ) + { + /* + Trash the current viewpoint transform and replace it + with one that only contains the OpenGL axis swap + kludge along with the current translation. + + This prevents the object from rotating relative to the + screen so that the modelled X/Z axis are always parallel + to the screen X/Y axes. + */ + + sgCopyMat4 ( tmp, _ssgOpenGLAxisSwapMatrix ) ; + sgCopyVec3 ( tmp[3], m[3] ) ; + } + else + { + sgCopyMat4 ( tmp, m ) ; + + /* + Figure out where the Z axis of the model ends up - that + isn't changed by the billboarding process. + + Next, figure out where the X axis should go - which + will be at right angles to the Z axis - and at right + angles to the view vector. A cross product achieves + that. + + Finally, figure out where the Y axis should go - which + will be at right angles to the new X and Z axes. A second + cross product sorts that out. + + Notice that the SSG coordinate system's Z axis is really + GL's Y axis. + */ + + sgVec3 x_axis ; + sgVec3 y_axis ; + sgVec3 z_axis ; + + sgSetVec3 ( y_axis, 0.0f, 0.0f, -1.0f ) ; + sgCopyVec3 ( z_axis, tmp[ 2 ] ) ; + + sgVectorProductVec3 ( x_axis, y_axis, z_axis ) ; + sgVectorProductVec3 ( y_axis, z_axis, x_axis ) ; + + sgNormaliseVec3 ( x_axis ) ; + sgNormaliseVec3 ( y_axis ) ; /* Optional if your cutout is flat */ + + /* + Now we know where we want the three axes to end up, + change the matrix to make it so. + */ + + sgCopyVec3 ( tmp[0], x_axis ) ; + sgCopyVec3 ( tmp[1], y_axis ) ; + } + + _ssgPushMatrix ( tmp ) ; + + glPushMatrix () ; + glLoadMatrixf ( (float *) tmp ) ; + ssgBranch::cull ( f, tmp, test_needed ) ; + glPopMatrix () ; + + _ssgPopMatrix () ; + + postTravTests ( SSGTRAV_CULL ) ; +} + + +void ssgCutout::hot ( sgVec3 s, sgMat4 m, int test_needed ) +{ + ssgBranch::hot ( s, m, test_needed ) ; +} + +void ssgCutout::los ( sgVec3 s, sgMat4 m, int test_needed ) +{ + ssgBranch::los ( s, m, test_needed ) ; +} + + +void ssgCutout::isect ( sgSphere *s, sgMat4 m, int test_needed ) +{ + ssgBranch::isect ( s, m, test_needed ) ; +} + + + +int ssgCutout::load ( FILE *fd ) +{ + _ssgReadInt ( fd, & point_rotate ) ; + + return ssgBranch::load(fd) ; +} + +int ssgCutout::save ( FILE *fd ) +{ + _ssgWriteInt ( fd, point_rotate ) ; + + return ssgBranch::save(fd) ; +} + + + diff --git a/src/ssg/ssgDList.cxx b/src/ssg/ssgDList.cxx new file mode 100644 index 0000000..501c1de --- /dev/null +++ b/src/ssg/ssgDList.cxx @@ -0,0 +1,273 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgDList.cxx 1996 2004-12-29 07:19:40Z sjbaker $ +*/ + + +#include "ssgLocal.h" + + +enum _ssgDListType +{ + SSG_DLIST_LEAF, + SSG_DLIST_SET_TWEEN_STATE, + SSG_DLIST_LOAD_MATRIX, + SSG_DLIST_PUSH_MATRIX, + SSG_DLIST_POP_MATRIX, + SSG_DLIST_LOAD_TEX_MATRIX, + SSG_DLIST_UNLOAD_TEX_MATRIX, + SSG_DLIST_NOTHING +} ; + +class _ssgDList +{ +public: + _ssgDListType type ; + sgMat4 mat ; + ssgLeaf *leaf ; + float tween_state ; + int tween_mode ; + + _ssgDList () { setEmpty () ; } + + void setTweenState ( float _state, int _mode ) + { + type = SSG_DLIST_SET_TWEEN_STATE ; + tween_state = _state ; + tween_mode = _mode ; + } + + void setPopMatrix () + { + type = SSG_DLIST_POP_MATRIX ; + } + + void setLoadTexMatrix ( sgMat4 m ) + { + sgCopyMat4 ( mat, m ) ; + type = SSG_DLIST_LOAD_TEX_MATRIX ; + } + + void setUnloadTexMatrix () + { + type = SSG_DLIST_UNLOAD_TEX_MATRIX ; + } + + void setLoadMatrix ( sgMat4 m ) + { + sgCopyMat4 ( mat, m ) ; + type = SSG_DLIST_LOAD_MATRIX ; + } + + void setPushMatrix ( sgMat4 m ) + { + sgCopyMat4 ( mat, m ) ; + type = SSG_DLIST_PUSH_MATRIX ; + } + + void setDrawLeaf ( ssgLeaf *l ) + { + leaf = l ; + type = SSG_DLIST_LEAF ; + } + + void setEmpty () + { + type = SSG_DLIST_NOTHING ; + } + + void draw () + { + switch ( type ) + { + case SSG_DLIST_LEAF : + leaf -> draw () ; + break ; + + case SSG_DLIST_SET_TWEEN_STATE : + _ssgSetRealCurrentTweenSettings ( tween_state, tween_mode ) ; + break ; + + case SSG_DLIST_POP_MATRIX : + glPopMatrix () ; + break ; + + case SSG_DLIST_LOAD_TEX_MATRIX : + glMatrixMode ( GL_TEXTURE ) ; + glLoadMatrixf ( (float *) mat ) ; + glMatrixMode ( GL_MODELVIEW ) ; + break ; + + case SSG_DLIST_UNLOAD_TEX_MATRIX : + glMatrixMode ( GL_TEXTURE ) ; + glLoadIdentity () ; + glMatrixMode ( GL_MODELVIEW ) ; + break ; + + case SSG_DLIST_LOAD_MATRIX : + glLoadMatrixf ( (float *) mat ) ; + break ; + + case SSG_DLIST_PUSH_MATRIX : + glPushMatrix () ; + glLoadMatrixf ( (float *) mat ) ; + break ; + + default: break ; + } + + setEmpty () ; + } +} ; + + +#define MAX_DLIST 8192 +//4096 +//2048 + +static int next_dlist = 0 ; +static _ssgDList dlist [ MAX_DLIST ] ; + +void _ssgDrawDList () +{ + for ( int i = 0 ; i < next_dlist ; i++ ) + dlist [ i ] . draw () ; + + next_dlist = 0 ; +} + +void _ssgPushMatrix ( sgMat4 m ) +{ + /* + There is no point in having a pop/push sequence, + so optimise it to a simple load. + */ + + if ( next_dlist > 0 && + dlist [ next_dlist - 1 ] . type == SSG_DLIST_POP_MATRIX ) + { + next_dlist-- ; + _ssgLoadMatrix ( m ) ; + } + else + if ( next_dlist >= MAX_DLIST ) + ulSetError ( UL_WARNING, "DList stack overflow!" ) ; + else + dlist [ next_dlist++ ] . setPushMatrix ( m ) ; +} + + +void _ssgSetTweenState ( float state, int mode ) +{ + if ( next_dlist >= MAX_DLIST ) + ulSetError ( UL_WARNING, "DList stack overflow!" ) ; + else + dlist [ next_dlist++ ] . setTweenState ( state, mode ) ; +} + + +void _ssgPopMatrix () +{ + /* + There is no point in having a push/pop sequence, + so optimise it to a single load. + */ + + if ( next_dlist > 0 && + dlist [ next_dlist - 1 ] . type == SSG_DLIST_PUSH_MATRIX ) + next_dlist-- ; + else + if ( next_dlist >= MAX_DLIST ) + ulSetError ( UL_WARNING, "DList stack overflow!" ) ; + else + dlist [ next_dlist++ ] . setPopMatrix () ; +} + + +void _ssgLoadTexMatrix ( sgMat4 m ) +{ + /* + There is no point in having a unload/load or a load/load sequence, + so optimise it to a single load. + */ + + while ( next_dlist > 0 && + ( dlist [ next_dlist - 1 ] . type == SSG_DLIST_LOAD_TEX_MATRIX || + dlist [ next_dlist - 1 ] . type == SSG_DLIST_UNLOAD_TEX_MATRIX ) + ) + next_dlist-- ; + + if ( next_dlist >= MAX_DLIST ) + ulSetError ( UL_WARNING, "DList stack overflow!" ) ; + else + dlist [ next_dlist++ ] . setLoadTexMatrix ( m ) ; +} + + + +void _ssgUnloadTexMatrix () +{ + /* + There is no point in having a unload/unload or a load/unload sequence, + so optimise it to a single unload. + */ + + while ( next_dlist > 0 && + ( dlist [ next_dlist - 1 ] . type == SSG_DLIST_LOAD_TEX_MATRIX || + dlist [ next_dlist - 1 ] . type == SSG_DLIST_UNLOAD_TEX_MATRIX ) + ) + next_dlist-- ; + + if ( next_dlist >= MAX_DLIST ) + ulSetError ( UL_WARNING, "DList stack overflow!" ) ; + else + dlist [ next_dlist++ ] . setUnloadTexMatrix () ; +} + + + +void _ssgLoadMatrix ( sgMat4 m ) +{ + /* + There is no point in having a load/load sequence, + so optimise it to a single load. + */ + + while ( next_dlist > 0 && + dlist [ next_dlist - 1 ] . type == SSG_DLIST_LOAD_MATRIX ) + next_dlist-- ; + + if ( next_dlist >= MAX_DLIST ) + ulSetError ( UL_WARNING, "DList stack overflow!" ) ; + else + dlist [ next_dlist++ ] . setLoadMatrix ( m ) ; +} + + + +void _ssgDrawLeaf ( ssgLeaf *l ) +{ + if ( next_dlist >= MAX_DLIST ) + ulSetError ( UL_WARNING, "DList stack overflow!" ) ; + else + dlist [ next_dlist++ ] . setDrawLeaf ( l ) ; +} + diff --git a/src/ssg/ssgEntity.cxx b/src/ssg/ssgEntity.cxx new file mode 100644 index 0000000..ba98332 --- /dev/null +++ b/src/ssg/ssgEntity.cxx @@ -0,0 +1,464 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgEntity.cxx 1954 2004-09-13 11:49:36Z wolfram_kuss $ +*/ + + +#include "ssgLocal.h" + +void ssgEntity::copy_from ( ssgEntity *src, int clone_flags ) +{ + ssgBase::copy_from ( src, clone_flags ) ; + + traversal_mask = src -> getTraversalMask () ; + + setTravCallback( SSG_CALLBACK_PRETRAV, src->getTravCallback( SSG_CALLBACK_PRETRAV ) ); + setTravCallback( SSG_CALLBACK_POSTTRAV, src->getTravCallback( SSG_CALLBACK_POSTTRAV ) ); + + dirtyBSphere () ; +} + + +ssgEntity::ssgEntity (void) +{ + traversal_mask = 0xFFFFFFFF ; + type = ssgTypeEntity () ; + bsphere_is_invalid = TRUE ; + + preTravCB = NULL ; + postTravCB = NULL ; +} + + +ssgEntity::~ssgEntity (void) +{ +} + + +void ssgEntity::dirtyBSphere () +{ + if ( bsphere_is_invalid ) return ; + + bsphere_is_invalid = TRUE ; + + int np = getNumParents () ; + + for ( int i = 0 ; i < np ; i++ ) + getParent ( i ) -> dirtyBSphere () ; +} + +void ssgEntity::visualiseBSphere () +{ + if ( bsphere.isEmpty () ) + return ; + + glDisable ( GL_LIGHTING ) ; + + glTranslatef ( bsphere.getCenter()[0], + bsphere.getCenter()[1], + bsphere.getCenter()[2] ) ; + +#ifdef USE_GLUT_SPHERES + int spherebotch = (int)(this) % 9 ; + + switch ( spherebotch++ ) + { + case 0 : glutWireSphere(bsphere.getRadius(),10,10); break ; + case 1 : glutWireSphere(bsphere.getRadius(),11,10); break ; + case 2 : glutWireSphere(bsphere.getRadius(),12,10); break ; + case 3 : glutWireSphere(bsphere.getRadius(),10,11); break ; + case 4 : glutWireSphere(bsphere.getRadius(),11,11); break ; + case 5 : glutWireSphere(bsphere.getRadius(),12,11); break ; + case 6 : glutWireSphere(bsphere.getRadius(),10,12); break ; + case 7 : glutWireSphere(bsphere.getRadius(),11,12); break ; + case 8 : glutWireSphere(bsphere.getRadius(),12,12); spherebotch=0 ; break ; + } +#endif + + glTranslatef ( -bsphere.getCenter()[0], + -bsphere.getCenter()[1], + -bsphere.getCenter()[2] ) ; + + glEnable ( GL_LIGHTING ) ; +} + + +void ssgEntity::print ( FILE *fd, char *indent, int how_much ) +{ + ssgBase::print ( fd, indent, how_much ) ; + + if ( how_much > 1 ) + fprintf ( fd, "%s Num Parents=%d\n", indent, parents.getNumEntities () ) ; +} + + +/* + Get the entity whos name equals match (case sensitive) or 0 if there isn't + This will be overridden by descendant classes to search trees, etc. + This makes recovery of tagged parts of objects simple. + I envisage it being used to find axles, gimbals etc and to separate many objects + from a single loaded model file. The base version in ssgEntity returns the + ssgEntity if the name refers to this entity or 0 if not. +*/ + +ssgEntity* ssgEntity::getByName ( char *match ) +{ + return ( getName() != NULL && strcmp ( getName(), match ) == 0 ) ? + this : (ssgEntity *) NULL ; +} + + +/* + Get the entity specified by the path. A path is a series of names + separated by '/'. Each sub-unit is searched so long as the path matches. + A single leading '/' on the path is ignored. +*/ + +ssgEntity* ssgEntity::getByPath ( char *path ) +{ + /* ignore leading '/' */ + + if ( *path == '/' ) + ++path ; + + /* return this if the name is the path else NULL */ + + return ( getName() != NULL && strcmp ( getName(), path ) == 0 ) ? + this : (ssgEntity *) NULL ; +} + + +ssgCallback ssgEntity::getCallback ( int cb_type ) +{ + if ( isAKindOf ( ssgTypeLeaf() ) ) + return ((ssgLeaf*)this) -> getCallback ( cb_type ) ; + + /* + * Because of transparency sorting, having a pre/post draw callback + * doesn't make sense for anything but a leaf. + */ + + ulSetError ( UL_WARNING, "getCallback() ignored for non-leaf entity"); + + return NULL ; +} + + +void ssgEntity::setCallback ( int cb_type, ssgCallback cb ) +{ + if ( isAKindOf ( ssgTypeLeaf() ) ) + { + ((ssgLeaf*)this) -> setCallback ( cb_type, cb ) ; + } + else + { + /* + * Because of transparency sorting, having a pre/post draw callback + * doesn't make sense for anything but a leaf. + */ + + ulSetError ( UL_WARNING, "setCallback() ignored for non-leaf entity"); + } +} + + +int ssgEntity::preTravTests ( int *test_needed, int which ) +{ + if ( (getTraversalMask() & which) == 0 ) + { + if ( which & SSGTRAV_HOT ) + stats_hot_no_trav ++ ; + /* + if ( which & SSGTRAV_LOS ) + stats_hot_no_trav ++ ;*/ + return FALSE ; + } + + if ( preTravCB != NULL ) + { + int result = (*preTravCB)(this,which) ; + + if ( result == 0 ) return FALSE ; + if ( result == 2 ) *test_needed = 0 ; + } + + return TRUE ; +} + + +void ssgEntity::postTravTests ( int which ) +{ + if ( postTravCB != NULL ) + (*postTravCB)(this,which) ; +} + + +ssgCullResult ssgEntity::cull_test ( sgFrustum *f, sgMat4 m, int test_needed ) +{ + if ( ! test_needed ) + return SSG_INSIDE ; + + stats_cull_test++ ; + sgSphere tmp = *(getBSphere()) ; + + if ( tmp.isEmpty () ) + return SSG_OUTSIDE ; + + tmp . orthoXform ( m ) ; + + return (ssgCullResult) f -> contains ( &tmp ) ; +} + + +ssgCullResult ssgEntity::isect_test ( sgSphere *s, sgMat4 m, int test_needed ) +{ + if ( ! test_needed ) + return SSG_INSIDE ; + + stats_isect_test++ ; + sgSphere tmp = *(getBSphere()) ; + + if ( tmp.isEmpty () ) + return SSG_OUTSIDE ; + + tmp . orthoXform ( m ) ; + + /* Check axial distances for trivial reject */ + + sgVec3 center_vec ; + float sum_radii = s->getRadius() + tmp.getRadius() ; + + sgSubVec3 ( center_vec, s->getCenter(), tmp.getCenter() ) ; + + if ( sgAbs(center_vec[0]) > sum_radii || + sgAbs(center_vec[1]) > sum_radii || + sgAbs(center_vec[2]) > sum_radii ) + return SSG_OUTSIDE ; + + float separation_sqd = sgScalarProductVec3 ( center_vec, center_vec ) ; + + float tmp_radius_sqd = sgSquare ( tmp.getRadius() ) ; + float sph_radius_sqd = sgSquare ( s ->getRadius() ) ; + + float sum_radii_sqd = tmp_radius_sqd + sph_radius_sqd ; + + if ( separation_sqd >= sum_radii_sqd ) + return SSG_OUTSIDE ; + + if ( separation_sqd + tmp_radius_sqd <= sph_radius_sqd ) + return SSG_INSIDE ; + + return SSG_STRADDLE ; +} + + +/* + Places the addresses of the entities whose names or paths + are listed in bind into the variables whose addresses are + listed in bind. The bind array must terminate with a + NULL name. Returns TRUE if all names were found and + bound to variables. +*/ + +int ssgEntity::bindEntities ( ssgEntityBinding *bind ) +{ + int success = TRUE ; + + while ( bind -> nameOrPath != NULL ) + { + ssgEntity *e = NULL ; + + if ( strchr ( bind -> nameOrPath, '/' ) ) + e = getByPath ( bind -> nameOrPath ) ; + else + e = getByName ( bind -> nameOrPath ) ; + + if ( e != NULL ) + *( bind -> entity ) = e ; + else + success = FALSE ; + + ++bind ; + } + + return success ; +} + + +ssgCullResult ssgEntity::hot_test ( sgVec3 s, sgMat4 m, int test_needed ) +{ + /* Height-Off-Terrain Test */ + stats_hot_test++ ; + + if ( !test_needed ) + { + stats_hot_triv_accept++ ; + return SSG_INSIDE ; + } + + sgSphere tmp = *(getBSphere()) ; + + if ( tmp.isEmpty () ) + return SSG_OUTSIDE ; + + tmp . orthoXform ( m ) ; + + float d = sgSquare ( s[0] - tmp.getCenter()[0] ) + + sgSquare ( s[1] - tmp.getCenter()[1] ) ; + + if ( d > sgSquare ( tmp.getRadius() ) ) + { + stats_hot_radius_reject++ ; + return SSG_OUTSIDE ; + } + + stats_hot_straddle++ ; + return SSG_STRADDLE ; +} + + + +ssgCullResult ssgEntity::los_test ( sgVec3 s, sgMat4 m, int test_needed ) +{ + /* Line of Sight Test + * Determine whether a line of sight that starts at the origin and proceeds along the + * vector "s" intersects the B-sphere of this entity (I think that's right) + * Algorithm: (please bear with the vector calculus) + * Define the line of sight to be L = O + u S + * where "O" is the origin of the line of sight (always (0.0.0) for this application) + * "u" is a parametric coordinate which measures distance along the line of sight + * "S" is the direction vector, given by the variable "s" in this function + * Define the B-sphere as a sphere of radius "r" centered at a point "C". + * The vector from the center of the sphere to a point on the line is given by + * V = O + u S - C = ( O - C ) + u S + * The line of sight intersects the sphere if the shortest length of this vector is less + * than the radius of the sphere. We will work with the square of the length as it is + * easier and gives the same result. This distance-squared from the point on the line to + * the center of the sphere is given by the dot product of "V" with itself: + * d2 = V dot V = ( O - C ) dot ( O - C ) + 2 u * ( O - C ) dot S + u^2 * S dot S + * To get the shortest distance, differentiate "d2" with respect to "u" and set the + * derivative to zero: + * 2 ( O - C ) dot S + 2 u * S dot S = 0 + * u = - [ ( O - C ) dot S ] / [ S dot S ] + * For this value of "u", the distance squared becomes + * d2 = ( O - C ) dot ( O - C ) - [ ( O - C ) dot S ] ^2 / [ S dot S ] + * If d2 < radius of sphere squared, then the line of sight intersects the sphere. + */ + + stats_los_test++ ; + + if ( !test_needed ) + { + stats_los_triv_accept++ ; + return SSG_INSIDE ; + } + + sgSphere tmp = *(getBSphere()) ; + + /* If there is no B-sphere, the LOS is outside of it by definition */ + if ( tmp.isEmpty () ) + return SSG_OUTSIDE ; + + tmp . orthoXform ( m ) ; + + sgVec3 p1 ; /* End point at eye of Line-Of-Sight */ + + sgSetVec3 ( p1, 0.0, 0.0, 0.0 ) ; /* Eye point always at origin */ + + /* Get the center and square the radius of the sphere */ + sgFloat const *center = tmp.getCenter () ; + sgFloat radius2 = sgSquare ( tmp.getRadius () ) ; + + /* Calculate the distance from the line to the center of the sphere */ + sgVec3 oc ; + sgSubVec3 ( oc, p1, center ) ; + + /* Check whether the eyepoint is within the sphere */ + sgFloat eye_to_center_squared = sgSquare ( oc[0] ) + sgSquare ( oc[1] ) + sgSquare ( oc[2] ) ; + if ( eye_to_center_squared < radius2 ) + { + stats_los_straddle++ ; + return SSG_STRADDLE ; + } + + /* Calculate the dot product of the vector from the center to the eyepoint and the + * line of sight vector. If this dot product is positive or zero, then the point of + * closest approach to the sphere is behind the eyepoint or at the eyepoint. Since the + * eyepoint is outside the sphere, this means that the line of sight forward from the + * eyepoint will not intersect the sphere. + */ + sgFloat oc_dot_s = oc[0] * s[0] + oc[1] * s[1] + oc[2] * s[2] ; + if ( oc_dot_s >= 0.0 ) + { + stats_los_radius_reject++ ; + return SSG_OUTSIDE ; + } + + float dmin2 = eye_to_center_squared - sgSquare ( oc_dot_s ) / + ( sgSquare ( s[0] ) + sgSquare ( s[1] ) + sgSquare ( s[2] ) ) ; + + /* Compare minimum distance squared with sphere radius squared */ + if ( dmin2 > radius2 ) + { + stats_los_radius_reject++; + return SSG_OUTSIDE; + } + + stats_los_straddle++ ; + return SSG_STRADDLE ; +} + + +int ssgEntity::load ( FILE *fd ) +{ + dirtyBSphere(); + _ssgReadInt ( fd, &traversal_mask ) ; + return ssgBase::load(fd) ; +} + + + +int ssgEntity::save ( FILE *fd ) +{ + _ssgWriteInt ( fd, traversal_mask ) ; + return ssgBase::save(fd) ; +} + + + +void ssgEntity::getNetTransform ( sgMat4 xform ) +{ + if ( getNumParents () > 0 ) + getParent ( 0 ) -> getNetTransform ( xform ) ; + else + sgMakeIdentMat4 ( xform ) ; +} + + +void ssgEntity::getLastNetTransform ( sgMat4 xform ) +{ + if ( getNumParents () > 0 ) + getParent ( 0 ) -> getLastNetTransform ( xform ) ; + else + sgMakeIdentMat4 ( xform ) ; +} + + diff --git a/src/ssg/ssgIO.cxx b/src/ssg/ssgIO.cxx new file mode 100644 index 0000000..680b199 --- /dev/null +++ b/src/ssg/ssgIO.cxx @@ -0,0 +1,244 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgIO.cxx 1673 2002-09-15 01:29:12Z ude $ +*/ + + +#include "ssgLocal.h" + + +static int read_error = FALSE ; +static int write_error = FALSE ; + + +int _ssgReadError (void) { return read_error ; } +int _ssgWriteError (void) { return write_error ; } + + +void _ssgReadFloat ( FILE *fd, float *var ) +{ + if ( fread ( var, sizeof(float), 1, fd ) == 1 ) return ; + read_error = TRUE ; +} + + +void _ssgWriteFloat ( FILE *fd, const float var ) +{ + if ( fwrite ( & var, sizeof(float), 1, fd ) == 1 ) return ; + write_error = TRUE ; +} + + +void _ssgReadUInt ( FILE *fd, unsigned int *var ) +{ + if ( fread ( var, sizeof(unsigned int), 1, fd ) == 1 ) return ; + read_error = TRUE ; +} + + +void _ssgWriteUInt ( FILE *fd, const unsigned int var ) +{ + if ( fwrite ( & var, sizeof(unsigned int), 1, fd ) == 1 ) return ; + write_error = TRUE ; +} + + +void _ssgReadInt ( FILE *fd, int *var ) +{ + if ( fread ( var, sizeof(int), 1, fd ) == 1 ) return ; + read_error = TRUE ; +} + + +void _ssgWriteInt ( FILE *fd, const int var ) +{ + if ( fwrite ( & var, sizeof(int), 1, fd ) == 1 ) return ; + write_error = TRUE ; +} + + +void _ssgReadUShort ( FILE *fd, unsigned short *var ) +{ + if ( fread ( var, sizeof(unsigned short), 1, fd ) == 1 ) return ; + read_error = TRUE ; +} + + +void _ssgWriteUShort ( FILE *fd, const unsigned short var ) +{ + if ( fwrite ( & var, sizeof(unsigned short), 1, fd ) == 1 ) return ; + write_error = TRUE ; +} + + +void _ssgReadShort ( FILE *fd, short *var ) +{ + if ( fread ( var, sizeof(short), 1, fd ) == 1 ) return ; + read_error = TRUE ; +} + + +void _ssgWriteShort ( FILE *fd, const short var ) +{ + if ( fwrite ( & var, sizeof(short), 1, fd ) == 1 ) return ; + write_error = TRUE ; +} + + +void _ssgReadFloat ( FILE *fd, const unsigned int n, float *var ) +{ + if ( fread ( var, sizeof(float), n, fd ) == n ) return ; + read_error = TRUE ; +} + + +void _ssgWriteFloat ( FILE *fd, const unsigned int n, const float *var ) +{ + if ( fwrite ( var, sizeof(float), n, fd ) == n ) return ; + write_error = TRUE ; +} + +void _ssgReadBytes ( FILE *fd, const unsigned int n, void *var ) +{ + if ( n == 0) + return; + if ( fread ( var, n, 1, fd ) == 1 ) + return ; + read_error = TRUE ; +} + +void _ssgWriteBytes ( FILE *fd, const unsigned int n, const void *var ) +{ + if ( n == 0) + return; + if ( fwrite ( var, n, 1, fd ) == 1 ) + return ; + write_error = TRUE ; +} + + +void _ssgReadUShort ( FILE *fd, const unsigned int n, unsigned short *var ) +{ + if ( fread ( var, sizeof(unsigned short), n, fd ) == n ) return ; + read_error = TRUE ; +} + + +void _ssgWriteUShort ( FILE *fd, const unsigned int n, const unsigned short *var ) +{ + if ( fwrite ( var, sizeof(unsigned short), n, fd ) == n ) return ; + write_error = TRUE ; +} + + + +void _ssgReadShort ( FILE *fd, const unsigned int n, short *var ) +{ + if ( fread ( var, sizeof(short), n, fd ) == n ) return ; + read_error = TRUE ; +} + + +void _ssgWriteShort ( FILE *fd, const unsigned int n, const short *var ) +{ + if ( fwrite ( var, sizeof(short), n, fd ) == n ) return ; + write_error = TRUE ; +} + + +void _ssgReadUInt ( FILE *fd, const unsigned int n, unsigned int *var ) +{ + if ( fread ( var, sizeof(unsigned int), n, fd ) == n ) return ; + read_error = TRUE ; +} + + +void _ssgWriteUInt ( FILE *fd, const unsigned int n, const unsigned int *var ) +{ + if ( fwrite ( var, sizeof(unsigned int), n, fd ) == n ) return ; + write_error = TRUE ; +} + + + +void _ssgReadInt ( FILE *fd, const unsigned int n, int *var ) +{ + if ( fread ( var, sizeof(int), n, fd ) == n ) return ; + read_error = TRUE ; +} + + +void _ssgWriteInt ( FILE *fd, const unsigned int n, const int *var ) +{ + if ( fwrite ( var, sizeof(int), n, fd ) == n ) return ; + write_error = TRUE ; +} + + + +#define MAX_ENTITY_NAME_LENGTH 1024 + +void _ssgReadString ( FILE *fd, char **var ) +{ + int i ; + char s [ MAX_ENTITY_NAME_LENGTH ] ; + + for ( i = 0 ; i < MAX_ENTITY_NAME_LENGTH ; i++ ) + { + int c = getc ( fd ) ; + s [ i ] = c ; + + if ( c == '\0' ) + break ; + } + + if ( i >= MAX_ENTITY_NAME_LENGTH-1 ) + s [ MAX_ENTITY_NAME_LENGTH-1 ] = '\0' ; + + + if ( s[0] == '\0' ) + *var = NULL ; + else + *var = ulStrDup ( s ) ; +} + + +void _ssgWriteString ( FILE *fd, const char *var ) +{ + if ( var != NULL ) + fputs ( var, fd ) ; + + putc ( '\0', fd ) ; +} + + +void _ssgReadVec2 ( FILE *fd, sgVec2 var ) { _ssgReadFloat ( fd, 2, var ) ; } +void _ssgWriteVec2 ( FILE *fd, const sgVec2 var ) { _ssgWriteFloat ( fd, 2, var ) ; } + +void _ssgReadVec3 ( FILE *fd, sgVec3 var ) { _ssgReadFloat ( fd, 3, var ) ; } +void _ssgWriteVec3 ( FILE *fd, const sgVec3 var ) { _ssgWriteFloat ( fd, 3, var ) ; } + +void _ssgReadVec4 ( FILE *fd, sgVec4 var ) { _ssgReadFloat ( fd, 4, var ) ; } +void _ssgWriteVec4 ( FILE *fd, const sgVec4 var ) { _ssgWriteFloat ( fd, 4, var ) ; } + +void _ssgReadMat4 ( FILE *fd, sgMat4 var ) { _ssgReadFloat ( fd, 16, (float *)var ) ; } +void _ssgWriteMat4 ( FILE *fd, const sgMat4 var ) { _ssgWriteFloat ( fd, 16, (float *)var ) ; } + diff --git a/src/ssg/ssgInvisible.cxx b/src/ssg/ssgInvisible.cxx new file mode 100644 index 0000000..8404f54 --- /dev/null +++ b/src/ssg/ssgInvisible.cxx @@ -0,0 +1,67 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgInvisible.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "ssgLocal.h" + +void ssgInvisible::copy_from ( ssgInvisible *src, int clone_flags ) +{ + ssgBranch::copy_from ( src, clone_flags ) ; +} + +ssgBase *ssgInvisible::clone ( int clone_flags ) +{ + ssgInvisible *b = new ssgInvisible ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + + +ssgInvisible::ssgInvisible (void) +{ + type = ssgTypeInvisible () ; +} + + +ssgInvisible::~ssgInvisible (void) +{ +} + + +void ssgInvisible::cull ( sgFrustum *, sgMat4, int /* test_needed */ ) +{ +} + + + +int ssgInvisible::load ( FILE *fd ) +{ + return ssgBranch::load(fd) ; +} + +int ssgInvisible::save ( FILE *fd ) +{ + return ssgBranch::save(fd) ; +} + diff --git a/src/ssg/ssgIsect.cxx b/src/ssg/ssgIsect.cxx new file mode 100644 index 0000000..32b4b22 --- /dev/null +++ b/src/ssg/ssgIsect.cxx @@ -0,0 +1,107 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgIsect.cxx 1719 2002-10-26 19:00:56Z sjbaker $ +*/ + + +#include "ssgLocal.h" + +#define MAX_HITS 100 +static ssgHit hitlist [ MAX_HITS ] ; +static int next_hit = 0 ; +static ssgEntity *pathlist [ SSG_MAXPATH ] ; +static int next_path = 0 ; + +int _ssgIsHotTest = FALSE ; +int _ssgIsLosTest = FALSE ; + +void _ssgPushPath ( ssgEntity *e ) +{ + if ( next_path + 1 >= SSG_MAXPATH ) + { + next_path++ ; /* So pop works! */ + return ; + } + + pathlist [ next_path++ ] = e ; +} + + +void _ssgPopPath () +{ + next_path-- ; +} + + +void _ssgAddHit ( ssgLeaf *l, int trinum, sgMat4 mat, sgVec4 pl ) +{ + if ( next_hit + 1 >= MAX_HITS ) + return ; + + ssgHit *h = & hitlist [ next_hit++ ] ; + + h -> leaf = l ; + h -> triangle = trinum ; + + h -> num_entries = (next_path>=SSG_MAXPATH) ? SSG_MAXPATH : next_path ; + memcpy ( h -> path, pathlist, h->num_entries * sizeof ( ssgEntity * ) ) ; + + sgCopyMat4 ( h -> matrix, mat ) ; + sgCopyVec4 ( h -> plane, pl ) ; +} + + +int ssgIsect ( ssgBranch *root, sgSphere *s, sgMat4 mat, ssgHit **results ) +{ + _ssgIsHotTest = FALSE ; + _ssgIsLosTest = FALSE ; + next_hit = 0 ; + next_path = 0 ; + root -> isect ( s, mat, TRUE ) ; + *results = & hitlist [ 0 ] ; + return next_hit ; +} + + +int ssgHOT ( ssgBranch *root, sgVec3 s, sgMat4 mat, ssgHit **results ) +{ + _ssgIsHotTest = TRUE ; + _ssgIsLosTest = FALSE ; + next_hit = 0 ; + next_path = 0 ; + root -> hot ( s, mat, TRUE ) ; + *results = & hitlist [ 0 ] ; + return next_hit ; +} + + +int ssgLOS ( ssgBranch *root, sgVec3 s, sgMat4 mat, ssgHit **results ) +{ + _ssgIsHotTest = FALSE ; + _ssgIsLosTest = TRUE ; + next_hit = 0 ; + next_path = 0 ; + root -> los ( s, mat, TRUE ) ; + *results = & hitlist [ 0 ] ; + return next_hit ; +} + + diff --git a/src/ssg/ssgKeyFlier.h b/src/ssg/ssgKeyFlier.h new file mode 100644 index 0000000..cf64a03 --- /dev/null +++ b/src/ssg/ssgKeyFlier.h @@ -0,0 +1,265 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgKeyFlier.h 1924 2004-04-06 13:32:26Z sjbaker $ +*/ + + +#ifndef _SSG_KEYFLIER_H_ +#define _SSG_KEYFLIER_H_ + +/***********************************************\ +* * +* SSG_KEYFLIER.H * +* * +* This file contains inline functions that * +* provide an ESIG-like keyboard-driven * +* flying carpet flight mode. * +* * +* Simply declare an instance of this class * +* somewhere in your program - and call the * +* 'incoming_keystroke' routine every time a * +* relevent character is typed - call the * +* 'update' function once per frame and the * +* 'get_coord' function whenever you need new * +* coordinates. Other handy functions are also * +* available. * +* * +* It's handy to use the 'Keyboard' class in * +* 'tty_port.h' to provide the incoming keys. * +* * +\***********************************************/ + +typedef void (*queryFunc)(float,float,float,float,float,float) ; +typedef void (*exitFunc)(int) ; + +class ssgKeyFlier +{ +protected: + float tscale ; + float rscale ; + sgCoord curr_pos ; + sgCoord reset_pos ; + sgCoord last_pos ; + sgCoord curr_vel ; + sgCoord velocity ; + + queryFunc query_action ; + exitFunc exit_action ; + +public: + ssgKeyFlier () + { + query_action = NULL ; + exit_action = NULL ; + + tscale = 1.0 ; + rscale = 1.0 ; + sgZeroVec3 ( reset_pos.xyz ) ; sgZeroVec3 ( reset_pos.hpr ) ; + sgZeroVec3 ( last_pos.xyz ) ; sgZeroVec3 ( last_pos.hpr ) ; + sgZeroVec3 ( velocity.xyz ) ; sgZeroVec3 ( velocity.hpr ) ; + update () ; + } + + void set_query_action ( queryFunc f ) { query_action = f ; } + void set_exit_action ( exitFunc f ) { exit_action = f ; } + + void stop_some () + { + velocity.xyz[0]=velocity.xyz[2]=0.0 ; + sgZeroVec3 ( velocity.hpr ) ; + update () ; + } + + void stop_all () + { + sgZeroVec3 ( velocity.xyz ) ; sgZeroVec3 ( velocity.hpr ) ; + update () ; + } + + void reset () + { + stop_all () ; + sgCopyVec3 ( last_pos.xyz, reset_pos.xyz ) ; + sgCopyVec3 ( last_pos.hpr, reset_pos.hpr ) ; + update () ; + } + + void get_scale_factors ( float *translation_scale_factor, float *rotation_scale_factor ) + { + if ( rotation_scale_factor != NULL ) + *rotation_scale_factor = rscale ; + + if ( translation_scale_factor != NULL ) + *translation_scale_factor = tscale ; + } + + /* Scale factors are in meters-per-update and degrees-per-update */ + + void set_scale_factors ( float translation_scale_factor, float rotation_scale_factor ) + { + rscale = rotation_scale_factor ; + tscale = translation_scale_factor ; + } + + + void set_xyz_scale ( float translation_scale_factor ) + { + tscale = translation_scale_factor ; + } + + + void set_hpr_scale ( float rotation_scale_factor ) + { + rscale = rotation_scale_factor ; + } + + + void set_reset ( sgCoord *pos ) + { + sgCopyCoord ( & reset_pos, pos ) ; + } + + sgCoord *get_velocity () + { + sgCopyCoord ( & curr_vel, & velocity ) ; + return & curr_vel ; + } + + void set_velocity ( sgCoord *vel ) + { + stop_all () ; + sgCopyCoord ( & velocity, vel ) ; + update () ; + } + + sgCoord *get_coord () + { + sgCopyCoord ( & curr_pos, & last_pos ) ; + return & curr_pos ; + } + + void set_coord ( sgCoord *pos, int noStop = 0 ) + { + if ( ! noStop ) stop_all () ; + sgCopyCoord ( & last_pos, pos ) ; + update () ; + } + + void show_help ( FILE *fd = stderr ) + { + fprintf ( fd, "ssgKeyFlier HELP.\n" ) ; + fprintf ( fd, "=================\n\n" ) ; + fprintf ( fd, "f : Faster - Make translational controls more sensitive.\n" ) ; + fprintf ( fd, "F : Faster - Make rotational controls more sensitive.\n" ) ; + fprintf ( fd, "s : Slower - Make translational controls less sensitive.\n" ) ; + fprintf ( fd, "S : Slower - Make rotational controls less sensitive.\n" ) ; + fprintf ( fd, "*,/: Same as 'f' and 's'.\n" ) ; + fprintf ( fd, "r/R: Reset - Reset eyepoint to pre-defined position.\n" ) ; + fprintf ( fd, "h/H: Help - Display this help message.\n" ) ; + fprintf ( fd, "^C : - Exit.\n" ) ; + fprintf ( fd, "? : - Where am I?\n" ) ; + fprintf ( fd, "5 : Stop rotation & slew 0 : Stop all movement.\n"); + fprintf ( fd, "2 : Pitch Up 8 : Pitch Down \n"); + fprintf ( fd, "4 : Yaw Left 6 : Yaw Right\n"); + fprintf ( fd, "7 : Roll Left 9 : Roll Right \n"); + fprintf ( fd, "1 : Translate Left. 3 : Translate Right\n"); + fprintf ( fd, "+/,: Translate Down - : Translate Up\n"); + fprintf ( fd, " . : Translate Backwards ENTER : Translate Forwards\n"); + fprintf ( fd, "[Note: Some of these controls may be overridden by the\n"); + fprintf ( fd, " application program.].\n"); + } + + void incoming_keystroke ( char k ) + { + switch ( k ) + { + case 'h' : + case 'H' : show_help () ; break ; + case '/' : + case 'f' : tscale *= 2.0 ; break ; + case 'F' : rscale *= 2.0 ; break ; + case '*' : + case 's' : tscale /= 2.0 ; break ; + case 'S' : rscale /= 2.0 ; break ; + + case 0x03: if ( exit_action ) exit_action( 0 ) ; exit ( 1 ) ; + + case '?' : if ( query_action ) + query_action ( last_pos.xyz[0], last_pos.xyz[1], last_pos.xyz[2], + last_pos.hpr[0], last_pos.hpr[1], last_pos.hpr[2] ) ; + else + ulSetError ( UL_DEBUG, "ssgKeyFlier: XYZ=(%g,%g,%g), HPR=(%g,%g,%g)", + last_pos.xyz[0], last_pos.xyz[1], last_pos.xyz[2], + last_pos.hpr[0], last_pos.hpr[1], last_pos.hpr[2] ) ; + + break ; + case 'r' : + case 'R' : reset () ; break ; + case '5' : stop_some () ; break ; + case '0' : stop_all () ; break ; + + case '1' : velocity.xyz[0] -= tscale ; break ; + case '3' : velocity.xyz[0] += tscale ; break ; + case '.' : velocity.xyz[1] -= tscale ; break ; + case '\n' : + case '\r' : velocity.xyz[1] += tscale ; break ; + case '+' : velocity.xyz[2] -= tscale ; break ; + case '-' : velocity.xyz[2] += tscale ; break ; + + case '6' : velocity.hpr[0] -= rscale ; break ; + case '4' : velocity.hpr[0] += rscale ; break ; +/* Kludge to try to prevent *exact* +/-90 degree pitch terms */ + case '8' : velocity.hpr[1] -= rscale+0.00001f ; break ; + case '2' : velocity.hpr[1] += rscale+0.00001f ; break ; + + case '7' : velocity.hpr[2] -= rscale ; break ; + case '9' : velocity.hpr[2] += rscale ; break ; + } + } + + int isStationary () + { + return ( velocity.hpr[0] == 0.0 && + velocity.hpr[1] == 0.0 && + velocity.hpr[2] == 0.0 && + velocity.xyz[0] == 0.0 && + velocity.xyz[1] == 0.0 && + velocity.xyz[2] == 0.0 ) ; + } + + virtual void update () + { + sgMat4 mat ; + sgMat4 result ; + sgMat4 delta ; + + /* Form new matrix */ + + sgMakeCoordMat4 ( delta, & velocity ) ; + sgMakeCoordMat4 ( mat , & last_pos ) ; + sgMultMat4 ( result, mat, delta ) ; + sgSetCoord ( &last_pos, result ) ; + } +} ; + + +#endif + diff --git a/src/ssg/ssgLeaf.cxx b/src/ssg/ssgLeaf.cxx new file mode 100644 index 0000000..7b28741 --- /dev/null +++ b/src/ssg/ssgLeaf.cxx @@ -0,0 +1,247 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLeaf.cxx 1952 2004-09-13 11:33:58Z wolfram_kuss $ +*/ + + +#include "ssgLocal.h" + +//~~ T.G. moved hee from header amd ref counting accounted for + +void ssgLeaf::setState ( ssgState *st ) +{ + ssgDeRefDelete ( state ) ; + + state = st ; + + if ( state != NULL ) + state->ref() ; +} + +void ssgLeaf::copy_from ( ssgLeaf *src, int clone_flags ) +{ + ssgEntity::copy_from ( src, clone_flags ) ; + + cull_face = src -> getCullFace () ; + + ssgState *s = src -> getState () ; + + //~~ T.G. Deref + ssgDeRefDelete(state); + + if ( s != NULL && ( clone_flags & SSG_CLONE_STATE ) ) + state = (ssgState *)( s -> clone ( clone_flags ) ) ; + else + state = s ; + + //~~ T.G. increment ref counter + if (state != NULL) + state->ref(); + + setCallback( SSG_CALLBACK_PREDRAW, src->getCallback( SSG_CALLBACK_PREDRAW ) ); + setCallback( SSG_CALLBACK_POSTDRAW, src->getCallback( SSG_CALLBACK_POSTDRAW ) ); +} + + + +ssgLeaf::ssgLeaf (void) +{ + cull_face = TRUE ; + state = NULL ; + type = ssgTypeLeaf () ; + +#ifdef _SSG_USE_DLIST + dlist = 0 ; +#endif + + preDrawCB = NULL ; + postDrawCB = NULL ; +} + +ssgLeaf::~ssgLeaf (void) +{ + //~~ T.G. ssgDeRefDelete checks for null case + ssgDeRefDelete ( state ) ; + +#ifdef _SSG_USE_DLIST + deleteDList () ; +#endif +} + + +#ifdef _SSG_USE_DLIST +void ssgLeaf::deleteDList () +{ + if ( dlist != 0 ) + glDeleteLists ( dlist, 1 ) ; + + dlist = 0 ; +} + +void ssgLeaf::makeDList () +{ + deleteDList () ; /* Just to be sure */ + dlist = glGenLists ( 1 ) ; + glNewList ( dlist, GL_COMPILE ) ; + draw_geometry () ; + glEndList () ; +} +#endif // #ifdef _SSG_USE_DLIST + + +void ssgLeaf::cull ( sgFrustum *f, sgMat4 m, int test_needed ) +{ + int cull_result = cull_test ( f, m, test_needed ) ; + + if ( cull_result == SSG_OUTSIDE ) + return ; + + if ( isTranslucent () ) + _ssgDrawLeaf ( this ) ; + else + draw () ; +} + +void ssgLeaf::hot ( sgVec3 s, sgMat4 m, int test_needed ) +{ + int hot_result = hot_test ( s, m, test_needed ) ; + + if ( hot_result == SSG_OUTSIDE ) + return ; + + /* Add polygons to hit list! */ + + hot_triangles ( s, m, hot_result != SSG_INSIDE ) ; +} + +void ssgLeaf::los ( sgVec3 s, sgMat4 m, int test_needed ) +{ + int los_result = los_test ( s, m, test_needed ) ; + + if ( los_result == SSG_OUTSIDE ) + return ; + + /* Add polygons to hit list! */ + + los_triangles ( s, m, los_result != SSG_INSIDE ) ; +} + + + +void ssgLeaf::isect ( sgSphere *s, sgMat4 m, int test_needed ) +{ + int isect_result = isect_test ( s, m, test_needed ) ; + + if ( isect_result == SSG_OUTSIDE ) + return ; + + /* Add polygons to hit list! */ + + isect_triangles ( s, m, isect_result != SSG_INSIDE ) ; +} + + +void ssgLeaf::getStats ( int *num_branches, int *num_leaves, int *num_tris, int *num_verts ) +{ + *num_branches = 0 ; + *num_leaves = 1 ; /* this! */ + *num_tris = getNumTriangles () ; + *num_verts = getNumVertices () ; +} + + +void ssgLeaf::print ( FILE *fd, char *indent, int how_much ) +{ + if ( how_much == 0 ) + return ; + + ssgEntity::print ( fd, indent, how_much ) ; + + if ( getNumParents () != getRef () ) + fprintf ( fd, "****** WARNING: Ref count doesn't equal parent count!\n" ) ; + + if ( state != NULL ) + { + char in [ 100 ] ; + sprintf ( in, "%s ", indent ); + + if ( how_much == 1 ) + fprintf ( fd, "%s %s: %p\n", indent , state->getTypeName(), state) ; + else + state -> print ( fd, in, how_much ) ; + } + else + fprintf ( fd, "%s No State assigned to this node\n", indent ) ; +} + + +int ssgLeaf::preDraw () +{ + if ( preDrawCB != NULL && ! (*preDrawCB)(this) ) + return FALSE ; + + _ssgCurrentContext->setCullface ( getCullFace() ) ; + + return TRUE ; +} + + +int ssgLeaf::load ( FILE *fd ) +{ + _ssgReadInt ( fd, &cull_face ) ; + + ssgState *st; + + if ( ! _ssgLoadObject ( fd, (ssgBase **) &st, ssgTypeState () ) ) + return FALSE ; + + if ( st != NULL && st -> isAKindOf ( ssgTypeSimpleState () ) ) + { + ssgSimpleState *ss = (ssgSimpleState *) st ; + char *tfname = ss -> getTextureFilename () ; + + if ( tfname != NULL ) + { + ssgState *new_st = ssgGetCurrentOptions () -> createState ( tfname ) ; + + if ( new_st != NULL ) + st = new_st ; + } + } + + setState ( st ) ; + + return ssgEntity::load(fd) ; +} + + +int ssgLeaf::save ( FILE *fd ) +{ + _ssgWriteInt ( fd, cull_face ) ; + + if ( ! _ssgSaveObject ( fd, getState () ) ) + return FALSE ; + + return ssgEntity::save(fd) ; +} + + + diff --git a/src/ssg/ssgList.cxx b/src/ssg/ssgList.cxx new file mode 100644 index 0000000..cbace21 --- /dev/null +++ b/src/ssg/ssgList.cxx @@ -0,0 +1,133 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgList.cxx 1949 2004-09-13 11:16:43Z wolfram_kuss $ +*/ + + +#include "ssgLocal.h" + +ssgList::ssgList ( int init ) +{ + total = 0 ; + next = 0 ; + entity_list = new ssgEntity * [ limit = (init <= 0) ? 1 : init ] ; +} + + +ssgKidList::ssgKidList ( int init ) : ssgList ( init ) +{ +} + + +ssgList::~ssgList (void) +{ + removeAllEntities () ; + delete [] entity_list ; +} + + +ssgKidList::~ssgKidList (void) +{ +} + + +void ssgList::addEntity ( ssgEntity *entity ) +{ +entity->deadBeefCheck() ; + sizeChk () ; + entity_list [ total++ ] = entity ; +} + +void ssgKidList::addEntity ( ssgEntity *entity ) +{ +entity->deadBeefCheck() ; + entity -> ref () ; + ssgList::addEntity ( entity ) ; +} + +void ssgList::sizeChk (void) +{ + /* Room for one more Entity? */ + + if ( total >= limit ) + { + limit += limit ; + ssgEntity **nlist = new ssgEntity * [ limit ] ; + memmove ( nlist, entity_list, sizeof(ssgEntity *) * total ) ; + delete [] entity_list ; + entity_list = nlist ; + } +} + + +int ssgList::searchForEntity ( ssgEntity *entity ) +{ + for ( unsigned int i = 0 ; i < total ; i++ ) + if ( entity_list [ i ] == entity ) + return (int) i ; + + return -1 ; +} + + +void ssgList::removeAllEntities () +{ + while ( total > 0 ) + removeEntity ( (unsigned int) total-1 ) ; +} + +void ssgList::removeEntity ( unsigned int n ) +{ + memmove ( &(entity_list[n]), &(entity_list[n+1]), sizeof(ssgEntity *) * (total-n-1) ) ; + total-- ; + + if ( next >= n ) + next-- ; +} + + +void ssgKidList::removeEntity ( unsigned int n ) +{ +entity_list[n]->deadBeefCheck(); + ssgEntity *e = entity_list [ n ] ; + + ssgList::removeEntity ( n ) ; + + e -> deadBeefCheck () ; + // wk 20.4.2002 problems with mywalk... when merging hiearchy nodes: + ssgDeRefDelete ( e ) ; +} + + +void ssgList::replaceEntity ( unsigned int n, ssgEntity *new_entity ) +{ + new_entity -> deadBeefCheck () ; + entity_list [ n ] -> deadBeefCheck () ; + entity_list [ n ] = new_entity; +} + +void ssgKidList::replaceEntity ( unsigned int n, ssgEntity *new_entity ) +{ + ssgEntity *old_entity = entity_list [ n ] ; + new_entity -> ref () ; + ssgList::replaceEntity ( n, new_entity ) ; + ssgDeRefDelete ( old_entity ) ; +} diff --git a/src/ssg/ssgLoad.cxx b/src/ssg/ssgLoad.cxx new file mode 100644 index 0000000..7608075 --- /dev/null +++ b/src/ssg/ssgLoad.cxx @@ -0,0 +1,260 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoad.cxx 1848 2004-01-24 18:25:45Z wolfram_kuss $ +*/ + + +#include "ssgLocal.h" + + +static ssgLoaderOptions default_options ; + +ssgLoaderOptions *_ssgCurrentOptions = &default_options ; + + + +char* ssgLoaderOptions::make_path ( char* path, + const char* dir, const char* fname ) const +{ + if ( fname != NULL && fname [ 0 ] != '\0' ) + { + if ( ! ulIsAbsolutePathName ( fname ) && + dir != NULL && dir[0] != '\0' ) + { + strcpy ( path, dir ) ; + strcat ( path, "/" ) ; + strcat ( path, fname ) ; + } + else + strcpy ( path, fname ) ; + + //convert backward slashes to forward slashes + for ( char* ptr = path ; *ptr ; ptr ++ ) + { + if ( *ptr == '\\' ) + *ptr = '/' ; + } + } + else + path [0] = 0 ; + return( path ); +} + + +void ssgLoaderOptions::makeModelPath ( char *path, const char *fname ) const +{ + make_path ( path, model_dir, fname ) ; +} + + +void ssgLoaderOptions::makeTexturePath ( char *path, const char *fname ) const +{ + /* Remove all leading path information. */ + const char* seps = "\\/" ; + const char* fn = & fname [ strlen ( fname ) - 1 ] ; + for ( ; fn != fname && strchr(seps,*fn) == NULL ; fn-- ) + /* Search back for a seperator */ ; + if ( strchr(seps,*fn) != NULL ) + fn++ ; + fname = fn ; + + make_path ( path, texture_dir, fname ) ; +} + + +ssgLeaf* ssgLoaderOptions::createLeaf ( ssgLeaf* leaf, + const char* parent_name ) +{ + if ( leaf != NULL ) + { + /* try to do some state sharing */ + ssgState* st = leaf -> getState () ; + if ( st != NULL && st -> isA ( ssgTypeSimpleState () ) ) + { + ssgSimpleState *ss = (ssgSimpleState*) st ; + ssgSimpleState *match = shared_states.findMatch ( ss ) ; + if ( match != NULL ) + leaf -> setState ( match ) ; + else + shared_states.add ( ss ) ; + } + } + return leaf ; +} + + +ssgTexture* ssgLoaderOptions::createTexture ( char* tfname, + int wrapu, + int wrapv, + int mipmap ) +{ + + char filename [ 1024 ] ; + makeTexturePath ( filename, tfname ) ; + + ssgTexture *tex = shared_textures.findByFilename ( filename ) ; + if ( tex ) + return tex ; + + tex = new ssgTexture ( filename, wrapu, wrapv, mipmap ) ; + if ( tex ) + shared_textures.add ( tex ) ; + return tex ; +} + +ssgTransform* ssgLoaderOptions::createTransform ( ssgTransform* tr, + ssgTransformArray* ta ) const +{ + if ( ta != NULL ) + tr -> setUserData ( ta ) ; + return tr ; +} + +ssgSelector* ssgLoaderOptions::createSelector ( ssgSelector* s ) const +{ + return s ; +} + + +void ssgLoaderOptions::setModelDir ( const char *s ) +{ + delete [] model_dir ; + model_dir = ulStrDup ( s ) ; +} + +void ssgLoaderOptions::setTextureDir ( const char *s ) +{ + delete [] texture_dir ; + texture_dir = ulStrDup ( s ) ; +} + + +static const char *file_extension ( const char *fname ) +{ + const char *p = & ( fname [ strlen(fname) ] ) ; + + while ( p != fname && *p != '/' && *p != '.' ) + p-- ; + + return p ; +} + + +struct _ssgModelFormat +{ + const char *extension ; + ssgLoadFunc *loadfunc ; + ssgSaveFunc *savefunc ; +} ; + + +enum { MAX_FORMATS = 100 } ; + +static _ssgModelFormat formats [ MAX_FORMATS ] ; +static int num_formats = 0 ; + + +void ssgAddModelFormat ( const char* extension, + ssgLoadFunc *loadfunc , ssgSaveFunc *savefunc ) +{ + for ( int i = 0 ; i < num_formats ; i++ ) + { + if ( ulStrEqual ( formats [ i ] . extension, extension ) ) + { + formats [ i ] . extension = extension ; + formats [ i ] . loadfunc = loadfunc ; + formats [ i ] . savefunc = savefunc ; + return ; + } + } + + if ( num_formats < MAX_FORMATS ) + { + formats [ num_formats ] . extension = extension ; + formats [ num_formats ] . loadfunc = loadfunc ; + formats [ num_formats ] . savefunc = savefunc ; + num_formats ++ ; + } + else + { + ulSetError ( UL_WARNING, "ssgAddModelFormat: too many formats" ); + } +} + + + +ssgEntity *ssgLoad ( const char *fname, const ssgLoaderOptions* options ) +{ + if ( fname == NULL || *fname == '\0' ) + return NULL ; + + // find appropiate loader and call its loadfunc + const char *extn = file_extension ( fname ) ; + if ( *extn != '.' ) + { + ulSetError ( UL_WARNING, "ssgLoad: Cannot determine file type for '%s'", fname ); + return NULL ; + } + +extern int g_noLoDs; + g_noLoDs = 1; + + _ssgModelFormat *f = formats ; + for ( int i=0; iloadfunc != NULL && + ulStrEqual ( extn, f->extension ) ) + { + ssgEntity* entity = f -> loadfunc( fname, options ) ; + ssgGetCurrentOptions () -> endLoad () ; + return entity ; + } + } + + ulSetError ( UL_WARNING, "ssgLoad: Unrecognised file type '%s'", extn ) ; + return NULL ; +} + + +int ssgSave ( const char *fname, ssgEntity *ent ) +{ + if ( fname == NULL || ent == NULL || *fname == '\0' ) + return FALSE ; + + const char *extn = file_extension ( fname ) ; + + if ( *extn != '.' ) + { + ulSetError ( UL_WARNING, "ssgSave: Cannot determine file type for '%s'", fname ); + return FALSE ; + } + + _ssgModelFormat *f = formats ; + for ( int i=0; isavefunc != NULL && + ulStrEqual ( extn, f->extension ) ) + return f->savefunc( fname, ent ) ; + } + + ulSetError ( UL_WARNING, "ssgSave: Unrecognised file type '%s'", extn ) ; + return FALSE ; +} diff --git a/src/ssg/ssgLoad3ds.cxx b/src/ssg/ssgLoad3ds.cxx new file mode 100644 index 0000000..21ca8ff --- /dev/null +++ b/src/ssg/ssgLoad3ds.cxx @@ -0,0 +1,1315 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoad3ds.cxx 2110 2006-12-12 15:43:45Z fayjf $ +*/ + +/******************************************************* + ** ssgLoad3ds.cxx + ** + ** Written by Per Liedman (liedman@home.se) + ** Last updated: 2001-02-09 + ** + ** This was written to be a part of Stephen J Bakers + ** PLIB (http://plib.sourceforge.net) + *******************************************************/ + +/* KNOWN ISSUES: + + * Some models (one of the test cases) gets turned "inside out" - obviously + the triangle winding has been reversed so that all triangles that should be + culled are shown and vice versa. I don't know where this information can + be found in the file. + + * Models that uses double-sided materials sometimes look strange. My approach + to double sided materials is to add a copy of each triangle with the + winding reversed and also negate the normals...this seems to *almost* work. + + * The transformation matrix in the 3DS files is still a mystery to me - + whatever I do with it seems to make things worse than ignoring it, although + that doesn't work perfect either. I've taken a look at other loaders, and + it seems that no one really knows what to do with them. + +*/ + +#define USE_VTXARRAYS +const int maxFacesPerLeaf = 10922; // = 32768 / 3 + +#include "ssgLocal.h" +#include "ssg3ds.h" + +#define MAX_MATERIALS 512 + +#define PARSE_OK 1 +#define PARSE_ERROR 0 +#define CHUNK_HEADER_SIZE (2 + 4) + +#define IS_DOUBLESIDED 1 + +/* Define DEBUG if you want debug output + (this might be a nice way of looking at the + structure of a 3DS file). */ +//#define DEBUG 1 + + +#ifdef DEBUG +#define DEBUGPRINT(f, x, y, z) ulSetError(UL_DEBUG, f, debug_indent, x, y, z) +#else +#define DEBUGPRINT(f, x, y, z) +#endif + +#ifdef DEBUG +static char debug_indent[256]; +#endif + +/* this is the minimum value of the dot product for + to faces if their normals should be smoothed, if + they don't use smooth groups. */ +// Until we are able to route such param through the LoaderOptions mechanism, +// make it globally accessible +/*static const*/ float _ssg_smooth_threshold = 0.8f; + +// parsing functions for chunks that need separate treatment. +static int parse_material( unsigned int length); +static int parse_objblock( unsigned int length); +static int parse_rgb1( unsigned int length); +static int parse_rgb2( unsigned int length); +static int parse_material_name( unsigned int length); +static int parse_ambient( unsigned int length); +static int parse_diffuse( unsigned int length); +static int parse_specular( unsigned int length); +static int parse_shininess( unsigned int length); +static int parse_transparency( unsigned int length); +static int parse_doublesided( unsigned int length); +static int parse_vert_list( unsigned int length); +static int parse_face_list( unsigned int length); +static int parse_map_list( unsigned int length); +static int parse_tra_matrix( unsigned int length); +static int parse_trimesh( unsigned int length); +static int parse_smooth_list( unsigned int length); +static int parse_face_materials( unsigned int length); +static int parse_mapname( unsigned int length); +static int parse_mapoptions( unsigned int length); +static int parse_uscale( unsigned int length); +static int parse_vscale( unsigned int length); +static int parse_uoffst( unsigned int length); +static int parse_voffst( unsigned int length); +static int parse_oneunit( unsigned int length); +static int parse_version( unsigned int length); +static int parse_frame ( unsigned int length); +static int parse_frame_objname ( unsigned int length); +static int parse_frame_hierarchy( unsigned int length); +static int identify_face_materials( unsigned int length ); +static int parse_frame_dummyname( unsigned int length ); + +/* _ssg3dsChunk defines how a certain chunk is handled when encountered - + what subchunks it might have and what parse function should be used + for it. */ +struct _ssg3dsChunk { + unsigned short id; + _ssg3dsChunk *subchunks; + int (*parse_func) ( unsigned int ); +}; + +// following arrays define the structure of the chunks in the 3ds file. +static _ssg3dsChunk FaceListDataChunks[] = +{ { CHUNK_SMOOLIST, NULL, parse_smooth_list }, + { CHUNK_FACEMAT, NULL, identify_face_materials }, + { 0, NULL, NULL } +}; + +static _ssg3dsChunk FaceListChunks[] = +{ { CHUNK_FACEMAT, NULL, parse_face_materials }, + { 0, NULL, NULL } +}; + +static _ssg3dsChunk TriMeshDataChunks[] = +{ { CHUNK_VERTLIST, NULL, parse_vert_list }, + { CHUNK_MAPLIST, NULL, parse_map_list }, + { 0, NULL, NULL } +}; /* these chunks have to be known *before* we call parse_face_list + (see parse_trimesh for more info) */ + +static _ssg3dsChunk TriMeshChunks[] = +{ { CHUNK_FACELIST, FaceListChunks, parse_face_list }, + { CHUNK_TRMATRIX, NULL, parse_tra_matrix }, + { 0, NULL, NULL } +}; + +static _ssg3dsChunk ObjBlockChunks[] = +{ { CHUNK_TRIMESH, TriMeshChunks, parse_trimesh }, + { 0, NULL, NULL } +}; + +static _ssg3dsChunk TextureChunks[] = +{ { CHUNK_MAPFILENAME, NULL, parse_mapname }, + { CHUNK_MAP_USCALE, NULL, parse_uscale }, + { CHUNK_MAP_VSCALE, NULL, parse_vscale }, + { CHUNK_MAP_UOFFST, NULL, parse_uoffst }, + { CHUNK_MAP_VOFFST, NULL, parse_voffst }, + { CHUNK_MAPOPTIONS, NULL, parse_mapoptions }, + { 0, NULL, NULL } +}; + +static _ssg3dsChunk MaterialColourChunks[] = +{ { CHUNK_RGB1, NULL, parse_rgb1 }, + { CHUNK_RGB2, NULL, parse_rgb2 }, + { CHUNK_RGB3, NULL, parse_rgb2 }, + { 0, NULL, NULL } +}; + +static _ssg3dsChunk MaterialChunks[] = +{ { CHUNK_MATNAME, NULL, parse_material_name }, + { CHUNK_AMBIENT, MaterialColourChunks, parse_ambient }, + { CHUNK_DIFFUSE, MaterialColourChunks, parse_diffuse }, + { CHUNK_SPECULAR, MaterialColourChunks, parse_specular}, + { CHUNK_SHINE_STRENGTH, NULL, parse_shininess }, + { CHUNK_TRANSPARENCY, NULL, parse_transparency }, + { CHUNK_TEXTURE, TextureChunks, NULL }, + { CHUNK_DOUBLESIDED, NULL, parse_doublesided }, + { 0, NULL, NULL } +}; + +static _ssg3dsChunk ObjMeshChunks[] = +{ { CHUNK_MATERIAL, MaterialChunks, parse_material }, + { CHUNK_OBJBLOCK, ObjBlockChunks, parse_objblock }, + { CHUNK_ONEUNIT, NULL, parse_oneunit }, + { 0, NULL, NULL } +}; + +static _ssg3dsChunk FrameChunks[] = +{ { CHUNK_FRAME_OBJNAME , NULL, parse_frame_objname }, + { CHUNK_FRAME_HIERARCHY, NULL, parse_frame_hierarchy }, + { CHUNK_FRAME_DUMMYNAME, NULL, parse_frame_dummyname }, + { 0, NULL, NULL } +}; + +static _ssg3dsChunk KeyframerChunks[] = +{ { CHUNK_FRAMES , NULL , parse_frame }, + { CHUNK_KEYFRAME_MESH, FrameChunks, NULL }, + { 0, NULL, NULL } +}; + +static _ssg3dsChunk MainChunks[] = +{ { CHUNK_OBJMESH, ObjMeshChunks , NULL }, + { CHUNK_KEYFRAMER, KeyframerChunks, NULL }, + { CHUNK_VERSION, NULL, parse_version }, + { 0, NULL, NULL } +}; + +static _ssg3dsChunk TopChunk[] = +{ { CHUNK_MAIN, MainChunks, NULL }, + { 0, NULL, NULL } +}; + +/* The material properties are temporarily stored in this structure before + creating ssgSimpleStates out of them. */ +struct _3dsMat { + char *name ; + int flags; + sgVec3 colour[4]; + float shi, alpha; + + char *tex_name; + sgVec2 tex_scale, tex_offset; + bool wrap_s, wrap_t; +}; +/* + These are the indices used for identifying the materials colour-properties: +*/ +#define _3DSMAT_AMB 0 +#define _3DSMAT_DIF 1 +#define _3DSMAT_EMI 2 +#define _3DSMAT_SPE 3 + + +/* Some 3ds files does not have any materials defined. This material is + used in that case: */ +static _3dsMat default_material= { "ssgLoad3ds default material", + 0, + { { 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f }, + }, + 0.0f, 1.0f, + NULL, + {1.0f, 1.0f}, {0.0f, 0.0f}, + false, false }; + +/* A _ssg3dsStructureNode holds a mesh or a transformation node. All + geometry is collected into structure nodes before actually being assembled + into the scene-graph, since the hierarchy information is at the end of the + 3ds file. */ +struct _ssg3dsStructureNode { + _ssg3dsStructureNode() { + id = -1; + object = NULL; + has_been_used = false; + next = NULL; + } + + short id; + ssgBranch *object; + bool has_been_used; + _ssg3dsStructureNode *next; +}; + +static _ssg3dsStructureNode *findStructureNode( char *name ); +static _ssg3dsStructureNode *findStructureNode( short id ); + +static int parse_chunks( _ssg3dsChunk *chunk_list, unsigned int length); +static void add_leaf( _3dsMat *material, int listed_faces, + unsigned short *face_indices ); + +/* Each vertex in a mesh has a face list associated with it, which + contains all faces that use this vertex. This list is used when + smoothing normals, since the adjacent faces of each vertex is needed. */ +struct _ssg3dsFaceList { + int face_index; + _ssg3dsFaceList *next; +}; + +static _ssg3dsFaceList *addFaceListEntry( _ssg3dsFaceList *face_list, + int face_index ) { + _ssg3dsFaceList *new_entry = new _ssg3dsFaceList; + new_entry -> face_index = face_index; + new_entry -> next = face_list; + + return new_entry; +} + +static void freeFaceList( _ssg3dsFaceList *face_list ) { + for (_ssg3dsFaceList *i = face_list, *temp = NULL; i != NULL; i = temp) { + temp = i -> next; + delete i; + } +} + +// globals +static FILE *model; + +static int num_objects, num_materials, num_textures; +static int double_sided; // is there some double sided material? + +static ssgBranch *top_object, *current_branch; + +static ssgLoaderOptions* current_options = NULL ; + +static _3dsMat **materials, *current_material; + +static unsigned short *vertex_index, *normal_index, num_vertices, num_faces; +static unsigned int *smooth_list; +static _ssg3dsFaceList **face_lists; + +static ssgTransform *current_transform, *last_dummy_object; + +static sgVec3 *vertex_list; +static sgVec3 *face_normals, *vertex_normals; +static sgVec2 *texcrd_list; +static int smooth_found, facemat_found; + +static int colour_mode; + +static _ssg3dsStructureNode *object_list = NULL; +static short current_structure_id = -1; +static short dummy_id = 0; +static short last_id = 0; + +/* flag to control whether to use smooting groups found in the file + or not */ +// Until we are able to route such param through the LoaderOptions mechanism, +// make it globally accessible +int _3DS_use_smoothing_groups = 0; + +// convenient functions +static unsigned char get_byte() { + unsigned char b; + fread( &b, 1, 1, model ); + return b; +} + +/* NOTE: This string has to be freed by the caller + Also note: You can't fetch strings longer than 256 + characters! */ +static char* get_string() { + char *s = new char[256], read; + int c = 0; + + while ( (read = getc(model)) != 0 ) { + if (c < 255) + s[c++] = read; + } + s[c] = 0; + + return s; +} + +//========================================================== +// STRUCTURE NODE FUNCTIONS + +static _ssg3dsStructureNode *findStructureNode( char *name ) { + for ( _ssg3dsStructureNode *n = object_list; n != NULL; n = n->next ) { + if ( strcmp( n->object->getName(), name ) == 0 ) { + return n; + } + } + + return NULL; +} + +static _ssg3dsStructureNode *findStructureNode( short id ) { + for ( _ssg3dsStructureNode *n = object_list; n != NULL; n = n->next ) { + if ( n->id == id ) { + return n; + } + } + + return NULL; +} + +static void addStructureNode( _ssg3dsStructureNode *node ) { + if (object_list == NULL) { + object_list = node; + } else { + node -> next = object_list; + object_list = node; + } +} + +//========================================================== +// MATERIAL PARSERS +static int parse_mapname( unsigned int length ) +{ + current_material->tex_name = get_string(); + DEBUGPRINT("%sMap name: %s %s%s", current_material->tex_name, "", ""); + return PARSE_OK; +} + +static int parse_mapoptions( unsigned int length ) +{ + unsigned short value = ulEndianReadLittle16(model); + // bit 4: 0=tile (default), 1=do not tile (a single bit for both u and v) + current_material->wrap_s = current_material->wrap_t = ((value & 0x10) == 0); + DEBUGPRINT("%sMap options (wrap): %c %s%s", + (current_material->wrap_s)?'Y':'N', "", ""); + + return PARSE_OK; +} + +static int parse_uscale( unsigned int length ) +{ + current_material->tex_scale[1] = ulEndianReadLittleFloat(model); + DEBUGPRINT("%sU-scale: %.3f %s%s", current_material->tex_scale[1], "", ""); + return PARSE_OK; +} + +static int parse_vscale( unsigned int length ) +{ + current_material->tex_scale[0] = ulEndianReadLittleFloat(model); + DEBUGPRINT("%sV-scale: %.3f %s%s", current_material->tex_scale[0], "", ""); + return PARSE_OK; +} + +static int parse_uoffst( unsigned int length ) +{ + current_material->tex_offset[1] = ulEndianReadLittleFloat(model); + DEBUGPRINT("%sU-offset: %.3f %s%s", + current_material->tex_offset[1], "", ""); + return PARSE_OK; +} + +static int parse_voffst( unsigned int length ) +{ + current_material->tex_offset[0] = ulEndianReadLittleFloat(model); + DEBUGPRINT("%sV-offset: %.3f %s%s", + current_material->tex_offset[0], "", ""); + return PARSE_OK; +} + +static int parse_material( unsigned int length ) { + materials[num_materials] = current_material = new _3dsMat; + current_material->flags = 0; + current_material->tex_name = NULL; + num_materials++; + + /* set default value for material colours (taken from glMaterial man page) */ + sgSetVec3(current_material -> colour[_3DSMAT_AMB], 0.2f, 0.2f, 0.2f ); + sgSetVec3(current_material -> colour[_3DSMAT_DIF], 0.8f, 0.8f, 0.8f ); + sgSetVec3(current_material -> colour[_3DSMAT_SPE], 0.0f, 0.0f, 0.0f ); + sgSetVec3(current_material -> colour[_3DSMAT_EMI], 0.0f, 0.0f, 0.0f ); + current_material -> shi = 0.0f; + current_material -> alpha = 1.0f; + + /* set up texture info */ + sgSetVec2(current_material -> tex_scale , 1.0f, 1.0f); + sgSetVec2(current_material -> tex_offset, 0.0f, 0.0f); + current_material -> wrap_s = current_material -> wrap_t = true; + + DEBUGPRINT("%sNew material found.%s%s%s", "", "", ""); + return PARSE_OK; +} + +static int parse_material_name( unsigned int length ) { + current_material -> name = get_string(); + DEBUGPRINT("%sMaterial name:%s%s%s", current_material->name, "", ""); + + return PARSE_OK; +} + +static int parse_rgb1( unsigned int length ) { + float r, g, b; + + r = ulEndianReadLittleFloat(model); + g = ulEndianReadLittleFloat(model); + b = ulEndianReadLittleFloat(model); + DEBUGPRINT("%sColour: R:%.2f, G:%.2f, B:%.2f", r, g, b); + + sgSetVec3(current_material->colour[colour_mode], r, g, b); + + return PARSE_OK; +} + +static int parse_rgb2( unsigned int length ) { + float r, g, b; + + r = (float)get_byte() / 255.0f; + g = (float)get_byte() / 255.0f; + b = (float)get_byte() / 255.0f; + DEBUGPRINT("%sColour: R:%.2f, G:%.2f, B:%.2f", r, g, b); + + sgSetVec3(current_material->colour[colour_mode], r, g, b); + return PARSE_OK; +} + +static int parse_ambient( unsigned int length ) { + colour_mode = _3DSMAT_AMB; + DEBUGPRINT("%sAmbient colour%s%s%s", "", "", ""); + return PARSE_OK; +} + +static int parse_diffuse( unsigned int length ) { + colour_mode = _3DSMAT_DIF; + DEBUGPRINT("%sDiffuse colour%s%s%s", "", "", ""); + return PARSE_OK; +} + +static int parse_specular( unsigned int length ) { + colour_mode = _3DSMAT_SPE; + DEBUGPRINT("%sSpecular colour%s%s%s", "", "", ""); + return PARSE_OK; +} + +static int parse_shininess( unsigned int length ) { + // this chunk contains a percentage chunk, + // so just read that chunks header + ulEndianReadLittle16(model); ulEndianReadLittle32(model); + current_material -> shi = (float)ulEndianReadLittle16(model) * 128.0f / 100.0f; + DEBUGPRINT("%sShininess:%.1f%s%s", current_material->shi, "", ""); + return PARSE_OK; +} + +static int parse_transparency( unsigned int length ) { + // this chunk contains a percentage chunk, + // so just read that chunks header + ulEndianReadLittle16(model); ulEndianReadLittle32(model); + current_material->alpha = 1.0f - (float)ulEndianReadLittle16(model) / 100.0f; + DEBUGPRINT("%sAlpha:%.1f%s%s", current_material->alpha, "", ""); + return PARSE_OK; +} + +static int parse_doublesided( unsigned int length ) { + double_sided = current_material->flags |= IS_DOUBLESIDED; + + DEBUGPRINT("%sMaterial is double sided.%s%s%s", "", "", ""); + + return PARSE_OK; +} + +static ssgSimpleState *get_state( _3dsMat *mat ) { + + if ( mat -> name != NULL ) + { + ssgSimpleState *st = current_options -> createSimpleState ( mat -> name ) ; + if ( st != NULL ) + return st ; + } + + ssgSimpleState *st = new ssgSimpleState () ; + + st -> setName( mat -> name ); + + st -> setMaterial ( GL_AMBIENT, + mat->colour[_3DSMAT_AMB][0], + mat->colour[_3DSMAT_AMB][1], + mat->colour[_3DSMAT_AMB][2], mat->alpha ) ; + st -> setMaterial ( GL_DIFFUSE, + mat->colour[_3DSMAT_DIF][0], + mat->colour[_3DSMAT_DIF][1], + mat->colour[_3DSMAT_DIF][2], mat->alpha ) ; + st -> setMaterial ( GL_SPECULAR, + mat->colour[_3DSMAT_SPE][0], + mat->colour[_3DSMAT_SPE][1], + mat->colour[_3DSMAT_SPE][2], mat->alpha ) ; + st -> setMaterial ( GL_EMISSION, + mat->colour[_3DSMAT_EMI][0], + mat->colour[_3DSMAT_EMI][1], + mat->colour[_3DSMAT_EMI][2], mat->alpha ) ; + st -> setShininess( mat -> shi ) ; + + st -> disable ( GL_COLOR_MATERIAL ) ; + st -> enable ( GL_LIGHTING ) ; + st -> setShadeModel ( GL_SMOOTH ) ; + + if ( mat -> alpha < 0.99f ) + { + st -> disable ( GL_ALPHA_TEST ) ; + st -> enable ( GL_BLEND ) ; + st -> setTranslucent () ; + } + else + { + st -> disable ( GL_BLEND ) ; + st -> setOpaque () ; + } + + if (mat -> tex_name != NULL) { + st -> setTexture( current_options -> createTexture(mat->tex_name, + mat->wrap_s, + mat->wrap_t) ) ; + st -> enable( GL_TEXTURE_2D ); + } else { + st -> disable( GL_TEXTURE_2D ); + } + + // don't show specular if exponent is 0, more info at: + // http://sf.net/mailarchive/forum.php?thread_id=6481452&forum_id=4479 + if ( ! mat->shi ) + st -> setMaterial ( GL_SPECULAR, 0,0,0,1 ); + + return st ; +} + + +//========================================================== +// TRIMESH PARSERS + +static void free_trimesh() +{ + DEBUGPRINT("%sFreeing trimesh object%s%s%s", "","",""); + + if (vertex_list) + delete [] vertex_list; + + if (face_normals) + delete [] face_normals; + + if (vertex_normals) + delete [] vertex_normals; + + if (texcrd_list) + delete [] texcrd_list; + + if (smooth_list) + delete [] smooth_list; + + if (vertex_index) + delete [] vertex_index; + + if (face_lists) { + for (int i = 0; i < num_vertices; i++) { + freeFaceList( face_lists[i] ); + } + + delete [] face_lists; + } + + vertex_list = NULL; + face_normals = NULL; + vertex_normals = NULL; + texcrd_list = NULL; + smooth_list = NULL; + vertex_index = NULL; + face_lists = NULL; +} + +static int parse_trimesh( unsigned int length ) { + free_trimesh(); + +#if 0 + current_transform = new ssgTransform(); + current_branch -> addKid( current_transform ); +#else // avoid introducing a useless ssgTransform + current_transform = (ssgTransform*) current_branch; +#endif + + /* Before we parse CHUNK_FACEMAT, we have to know vertices and texture + coordinates. To ensure this, we make a special pass of the Trimesh + chunks, just extracting this information. + This is kind of a kludge, but it was the easiest way to solve this problem + */ + DEBUGPRINT("%sPrescanning sub-chunks for vertices and texture coords." \ + "%s%s%s", "","",""); +#ifdef DEBUG + strcat(debug_indent, " "); +#endif + + unsigned long p = ftell(model); + int parse_ok = parse_chunks( TriMeshDataChunks, length ); + fseek(model, p, SEEK_SET); + +#ifdef DEBUG + debug_indent[strlen(debug_indent)-4] = 0; +#endif + DEBUGPRINT("%sDone prescanning.%s%s%s", "","",""); + + return parse_ok; +} + +static int parse_vert_list( unsigned int length ) { + num_vertices = ulEndianReadLittle16(model); + vertex_list = new sgVec3[num_vertices]; + face_lists = new _ssg3dsFaceList*[num_vertices]; + + DEBUGPRINT("%sReading %d vertices.%s%s", num_vertices, "", ""); + + for (int i = 0; i < num_vertices; i++) { + vertex_list[i][0] = ulEndianReadLittleFloat(model); + vertex_list[i][1] = ulEndianReadLittleFloat(model); + vertex_list[i][2] = ulEndianReadLittleFloat(model); + + face_lists [i] = NULL; + } + + return PARSE_OK; +} + +static int parse_smooth_list( unsigned int length ) +{ + int i; + smooth_found = TRUE; + + smooth_list = new unsigned int[num_faces]; + DEBUGPRINT("%sReading smoothlist%s%s%s", "", "", ""); + + for (i = 0; i < num_faces; i++) + smooth_list[i] = ulEndianReadLittle32(model); + + return PARSE_OK; +} + +static void smooth_normals( int use_smooth_list ) { + for (int i = 0; i < num_faces; i++) { + for (int j = 0; j < 3; j++) { + int nindex = i * 3 +j; + int vindex = vertex_index[ nindex ]; + sgCopyVec3( vertex_normals[nindex], face_normals[i] ); + + // find all faces containing vertex vindex + for ( _ssg3dsFaceList *l = face_lists[vindex]; l != NULL; l = l->next ) { + int findex = l -> face_index; + + if ( findex != i ) { + int should_smooth; + if (use_smooth_list) { + should_smooth = (smooth_list[i] & smooth_list[findex]); + } else { + float scalar = sgScalarProductVec3( face_normals[i], + face_normals[findex] ); + should_smooth = ( scalar > _ssg_smooth_threshold ); + } + + if (should_smooth) { + sgAddVec3( vertex_normals[nindex], face_normals[findex] ); + } + } + } + + sgNormaliseVec3( vertex_normals[nindex] ); + } + } +} + +static int identify_face_materials( unsigned int length ) { + facemat_found = TRUE; + DEBUGPRINT("%sFace materials found.%s%s%s", "","",""); + + fseek( model, length, SEEK_CUR ); + + return PARSE_OK; +} + +static int parse_face_list( unsigned int length ) { + int i; + num_faces = ulEndianReadLittle16(model); + + DEBUGPRINT("%sReading %d faces.%s%s", num_faces, "", ""); + + vertex_index = new unsigned short[num_faces*3]; + face_normals = new sgVec3[num_faces]; + + vertex_normals = new sgVec3[num_faces * 3]; + + for (i = 0; i < num_faces; i++) { + int v1 = ulEndianReadLittle16(model); + int v2 = ulEndianReadLittle16(model); + int v3 = ulEndianReadLittle16(model); + vertex_index[i*3 ] = v1; + vertex_index[i*3 + 1] = v2; + vertex_index[i*3 + 2] = v3; + + face_lists[ v1 ] = addFaceListEntry( face_lists[ v1 ], i ); + face_lists[ v2 ] = addFaceListEntry( face_lists[ v2 ], i ); + face_lists[ v3 ] = addFaceListEntry( face_lists[ v3 ], i ); + + unsigned short flags = ulEndianReadLittle16(model); + + if (flags & 7 == 0) { // Triangle vertices order should be swapped + unsigned short tmp = vertex_index[i*3 + 1]; + vertex_index[i*3 + 1] = vertex_index[i*3 + 2]; + vertex_index[i*3 + 2] = tmp; + } + + sgMakeNormal( face_normals[i], vertex_list[vertex_index[i*3 ]], + vertex_list[vertex_index[i*3 + 1]], + vertex_list[vertex_index[i*3 + 2]] ); + + } + + /* this is a special "hack" for the face list chunk + because we HAVE to know the smooth list (if there is one) + before building the ssgVtxTable objects, this parsing has to + be done first...*ugh*/ + + smooth_found = FALSE; + facemat_found = FALSE; + DEBUGPRINT("%sPrescanning sub-chunks for smooth list...%s%s%s", "","",""); +#ifdef DEBUG + strcat(debug_indent, " "); +#endif + + unsigned long p = ftell(model); + parse_chunks( FaceListDataChunks, length - (2 + 8*num_faces) ); + fseek(model, p, SEEK_SET); + +#ifdef DEBUG + debug_indent[strlen(debug_indent)-4] = 0; +#endif + DEBUGPRINT("%sDone prescanning.%s%s%s", "","",""); + + /* now apply correct smoothing. If smooth list has been found, + use it, otherwise use threshold value. */ + smooth_normals( _3DS_use_smoothing_groups && smooth_found ); + + if (!facemat_found) { + DEBUGPRINT("%sNo CHUNK_FACEMAT found. Adding default faces of material " \ + "\"%s\"%s%s.", materials[0]->name, "", ""); + unsigned short *face_indices = new unsigned short[num_faces]; + for (i = 0; i < num_faces; i++) { + face_indices[i] = i; + } +#if 0 + add_leaf(materials[0], num_faces, face_indices); +#else + if( num_faces > maxFacesPerLeaf ) { + float num_objs = (float)num_faces / maxFacesPerLeaf; int int_num_objs = int(num_objs); + ulSetError( UL_DEBUG, "\tgeometry objects '%s' split into %d leaves", + current_branch->getName(), num_objs > int_num_objs ? int_num_objs+1 : int_num_objs); + } + for ( int il = 0; il < num_faces; il += maxFacesPerLeaf ) { + add_leaf(materials[0], ulMin(num_faces-il,maxFacesPerLeaf), &face_indices[il]); + } +#endif + } + + return PARSE_OK; +} + +static int parse_map_list( unsigned int length ) { + unsigned short num_v = ulEndianReadLittle16(model); + texcrd_list = new sgVec2[num_v]; + + DEBUGPRINT("%sReading %d texture coords.%s%s", num_v, "", ""); + + for (int i = 0; i < num_v; i++) { + texcrd_list[i][0] = ulEndianReadLittleFloat(model); + texcrd_list[i][1] = ulEndianReadLittleFloat(model); + } + + return PARSE_OK; +} + +static int parse_tra_matrix( unsigned int length ) { + sgMat4 m; + + sgMakeIdentMat4( m ); + + DEBUGPRINT("%sReading transformation matrix.%s%s%s", "","",""); + + /* Strange things seems to be going on with the + local coordinate system in 3ds - I have commented + this out, but things seems to work better without + it (which is odd).*/ + + int i, j; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 3; j++) { + m[j][i] = ulEndianReadLittleFloat(model); + } + } + +#if 0 + m[3][3] = 1.0f; + sgTransposeNegateMat4( m ); + +#ifdef DEBUG + for (int a = 0; a < 4; a++) { + fputs(debug_indent, stderr); + for (int b = 0; b < 4; b++) { + fprintf(stderr, "%.2f\t", m[b][a]); + } + putc('\n', stderr); + } +#endif + +// current_transform -> setTransform( m ); +#endif + return PARSE_OK; +} + +static void add_leaf( _3dsMat *material, int listed_faces, + unsigned short *face_indices ) { + int is_ds = material->flags & IS_DOUBLESIDED; + int has_texture = material->tex_name != NULL; + + ssgVertexArray *vertices = new ssgVertexArray(); + ssgNormalArray *normals = new ssgNormalArray(); + ssgTexCoordArray *texcrds = NULL; +#ifdef USE_VTXARRAYS + ssgIndexArray* indices = new ssgIndexArray(); +#endif + + if (has_texture) { + if (texcrd_list == NULL) { + ulSetError(UL_WARNING, "ssgLoad3ds: Texture coords missing."); + } else { + texcrds = new ssgTexCoordArray(); + } + } + + int tri_idx = 0; + + for (int i = 0; i < listed_faces; i++) { + unsigned short faceindex = face_indices[i]; + int v1 = faceindex * 3, + v2 = faceindex * 3 + 1, + v3 = faceindex * 3 + 2; + +#ifdef USE_VTXARRAYS + indices->add( tri_idx++ ); + indices->add( tri_idx++ ); + indices->add( tri_idx++ ); +#endif + + vertices->add( vertex_list[ vertex_index[v1] ] ); + vertices->add( vertex_list[ vertex_index[v2] ] ); + vertices->add( vertex_list[ vertex_index[v3] ] ); + + normals ->add( vertex_normals[ v1 ] ); + normals ->add( vertex_normals[ v2 ] ); + normals ->add( vertex_normals[ v3 ] ); + + if (has_texture && texcrd_list != NULL) { + int num_texcrds = 3; + sgVec2 _texcrds[6]; + sgCopyVec2( _texcrds[0], texcrd_list[ vertex_index[v1] ] ); + sgCopyVec2( _texcrds[1], texcrd_list[ vertex_index[v2] ] ); + sgCopyVec2( _texcrds[2], texcrd_list[ vertex_index[v3] ] ); + if (is_ds) { + num_texcrds = 6; + sgCopyVec2( _texcrds[3], texcrd_list[ vertex_index[v1] ] ); + sgCopyVec2( _texcrds[4], texcrd_list[ vertex_index[v3] ] ); + sgCopyVec2( _texcrds[5], texcrd_list[ vertex_index[v2] ] ); + } + + for (int j = 0; j < num_texcrds; j++) { + _texcrds[j][0] *= material->tex_scale[0]; + _texcrds[j][1] *= material->tex_scale[1]; + sgAddVec2( _texcrds[j], material->tex_offset ); + texcrds->add( _texcrds[j] ); + } + } + + if (is_ds) { + sgVec3 n[3]; /* we have to use the *negated* normals for back faces */ + + vertices->add( vertex_list[ vertex_index[v1] ] ); + vertices->add( vertex_list[ vertex_index[v3] ] ); + vertices->add( vertex_list[ vertex_index[v2] ] ); + + sgCopyVec3( n[0], vertex_normals[v1] ); + sgCopyVec3( n[1], vertex_normals[v3] ); + sgCopyVec3( n[2], vertex_normals[v2] ); + + for (int j = 0; j < 3; j++) { + sgNegateVec3( n[j] ); + normals->add( n[j] ); + } + +#ifdef USE_VTXARRAYS + indices->add( tri_idx++ ); + indices->add( tri_idx++ ); + indices->add( tri_idx++ ); +#endif + } + + } + +#ifdef USE_VTXARRAYS + ssgVtxArray* vtab = new ssgVtxArray ( GL_TRIANGLES, vertices, normals, texcrds, NULL, indices ); +#else + ssgVtxTable* vtab = new ssgVtxTable ( GL_TRIANGLES, vertices, normals, texcrds, NULL ) ; +#endif + vtab -> setState ( get_state( material ) ) ; + vtab -> setCullFace ( TRUE ) ; + + ssgLeaf* leaf = current_options -> createLeaf ( vtab, 0 ) ; + + if ( leaf ) + current_transform -> addKid( leaf ); +} + +static int parse_face_materials( unsigned int length ) { + int mat_num; + char *mat_name = get_string(); + _3dsMat *material = NULL; + + // find the material + for (mat_num = 0; mat_num < num_materials; mat_num++) { + if ( strcmp( mat_name, materials[mat_num]->name ) == 0 ) { + material = materials[mat_num]; + break; + } + } + + if (material == NULL) { + ulSetError(UL_WARNING, "ssgLoad3ds: Undefined reference to material " \ + "\"%s\" found.", mat_name); + return PARSE_ERROR; + } + + unsigned short listed_faces = ulEndianReadLittle16(model); + + DEBUGPRINT("%sFaces of \"%s\" list with %d faces.%s", + mat_name, listed_faces, ""); + + delete mat_name; // no longer needed + + unsigned short *face_indices = new unsigned short[listed_faces]; + for (int i = 0; i < listed_faces; i++) { + face_indices[i] = ulEndianReadLittle16(model); + } + +#if 0 + add_leaf(material, listed_faces, face_indices); +#else + if( listed_faces > maxFacesPerLeaf ) { + float num_objs = (float)listed_faces / maxFacesPerLeaf; int int_num_objs = int(num_objs); + ulSetError( UL_DEBUG, "\tgeometry objects '%s' split into %d leaves", + current_branch->getName(), num_objs > int_num_objs ? int_num_objs+1 : int_num_objs); + } + for ( int il = 0; il < listed_faces; il += maxFacesPerLeaf ) { + add_leaf(material, ulMin(listed_faces-il,maxFacesPerLeaf), &face_indices[il]); + } +#endif + + delete [] face_indices; + + return PARSE_OK; +} + +//========================================================== +// OBJBLOCK PARSER + +static int parse_objblock( unsigned int length ) { + char *object_name = get_string(); + current_branch = new ssgTransform; + current_branch -> setName( object_name ); + + _ssg3dsStructureNode *object_node = new _ssg3dsStructureNode; + object_node -> object = current_branch; + + addStructureNode( object_node ); + + DEBUGPRINT("%sObject block \"%s\"%s%s", object_name, "", ""); + delete object_name; + + return PARSE_OK; +} + +static int parse_oneunit( unsigned int length ) { +#ifdef DEBUG + float oneunit = ulEndianReadLittleFloat(model); + DEBUGPRINT("%sOne unit: %.3f%s%s", oneunit, "", ""); +#else + ulEndianReadLittleFloat(model) ; +#endif + + return PARSE_OK; +} + +static int parse_version( unsigned int length ) { +#ifdef DEBUG + unsigned int version = ulEndianReadLittle32(model); + DEBUGPRINT("%s3DS Version: %d%s%s", version, "", ""); +#else + ulEndianReadLittle32(model) ; +#endif + + return PARSE_OK; +} + +//========================================================== +// KEYFRAME CHUNK PARSER + +static int parse_frame( unsigned int length ) { + // this chunk is not used for anything right now +#ifdef DEBUG + DEBUGPRINT("%sFrame start: %d, end: %d%s", + ulEndianReadLittle32(model), ulEndianReadLittle32(model), ""); +#else + ulEndianReadLittle32(model); + ulEndianReadLittle32(model); +#endif + + return PARSE_OK; +} + + +static int parse_frame_dummyname( unsigned int length ) { + char *dummyname = get_string(); + if ( last_dummy_object != (ssgTransform*)NULL ) + last_dummy_object->setName( dummyname ); + delete dummyname; + + return PARSE_OK; +} + + +static int parse_frame_objname( unsigned int length ) { + /* This chunk defines a hierarchy elements name and its parent object's + identifier. + + This function assumes that the hierarchy is defined from + root to leaf, i.e. a nodes parent must have been declared before the + node itself is declared. */ + + char *objname = get_string(), dummyname[255]; + ulEndianReadLittle16(model); + ulEndianReadLittle16(model); + short parent_id = ulEndianReadLittle16(model); + int dummy = 0; + + DEBUGPRINT("%sObject name: %s, parent: %d%s", + objname, parent_id, ""); + + if ( strcmp(objname,"$$$DUMMY") == 0 ) { + sprintf( dummyname, "%s_%d", objname, dummy_id++ ); + objname = dummyname; + dummy = 1; + } + + _ssg3dsStructureNode *current_structure_node = findStructureNode( objname ); + + if ( current_structure_node == NULL ) { + current_structure_node = new _ssg3dsStructureNode; + current_structure_node -> object = last_dummy_object = new ssgTransform; + current_structure_node -> object -> setName( objname ); + + addStructureNode( current_structure_node ); + } + + if ( current_structure_id >= 0 ) { + current_structure_node -> id = current_structure_id; + current_structure_id = -1; + } + else + current_structure_node -> id = last_id++; + + if ( parent_id != -1 ) { + _ssg3dsStructureNode *parent = findStructureNode( parent_id ); + if (parent == NULL) { + ulSetError( UL_WARNING, "ssgLoad3ds: Hierarchy entry \"%d\" does "\ + "not match any defined objects.", parent_id ); + } else { + parent -> object -> addKid( current_structure_node -> object ); + current_structure_node -> has_been_used = true; + } + } else { + top_object -> addKid( current_structure_node -> object ); + current_structure_node -> has_been_used = true; + } + + if ( !dummy ) delete objname; + + return PARSE_OK; +} + +static int parse_frame_hierarchy( unsigned int length ) { + current_structure_id = ulEndianReadLittle16(model); + DEBUGPRINT("%sThis object's hierarchy id: %d.%s%s", + current_structure_id, "", ""); + + return PARSE_OK; +} + +//========================================================== +// GENERAL CHUNK PARSER + +static int parse_chunks( _ssg3dsChunk *chunk_list, unsigned int length ) +{ + int parse_ok = PARSE_OK; + unsigned short id; + unsigned int sub_length; + unsigned int p = 0; + _ssg3dsChunk *t; + + while (parse_ok && p < length) { + id = ulEndianReadLittle16(model); + sub_length = ulEndianReadLittle32(model); + + if (p + sub_length > length) { + ulSetError(UL_WARNING, "ssgLoad3ds: Illegal chunk %X of length %i. " \ + "Chunk is longer than parent chunk.", (int)id, sub_length); + return PARSE_ERROR; + } + + p += sub_length; + sub_length -= CHUNK_HEADER_SIZE; + + for (t = chunk_list; t->id != 0 && t->id != id; t++); + + if (t->id == id) { + DEBUGPRINT("%sFound chunk %X of length %d%s (known)", + id, sub_length,""); + // this is a known chunk + // do chunk-specific parsing if available + unsigned long cp = ftell(model); + + if (t->parse_func) + parse_ok = t->parse_func( sub_length ); + +#ifdef DEBUG + strcat(debug_indent, " "); +#endif + + // if chunk can have subchunks, parse these + if (t->subchunks && parse_ok) { + parse_ok = parse_chunks( t->subchunks, + sub_length - (ftell(model)-cp) ); + } + +#ifdef DEBUG + debug_indent[strlen(debug_indent)-4] = 0; +#endif + + } else { + DEBUGPRINT("%sFound chunk %X of length %d%s (unknown)", + id, sub_length,""); + fseek( model, sub_length, SEEK_CUR ); + } + + } + + return parse_ok; +} + + +ssgEntity *ssgLoad3ds( const char *filename, const ssgLoaderOptions* options ) { + int i; + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + current_options = ssgGetCurrentOptions () ; + + char filepath [ 1024 ] ; + current_options -> makeModelPath ( filepath, filename ) ; + + model = fopen ( filepath, "rb" ); + if ( model == NULL ) { + ulSetError(UL_WARNING, "ssgLoad3ds: Failed to open '%s' for reading", + filepath ) ; + return NULL ; + } + + fseek(model, 0, SEEK_END); + unsigned long size = ftell(model); + rewind(model); + + current_structure_id = -1; + dummy_id = last_id = 0; + last_dummy_object = (ssgTransform*)NULL; + num_objects = num_materials = num_textures = 0; + object_list = NULL; + vertex_list = NULL; + texcrd_list = NULL; + face_normals = NULL; + face_lists = NULL; + vertex_index = normal_index = NULL; + top_object = new ssgBranch(); + + // initialize some storage room for materials + // (ok, could be implemented as linked list, but...well I'm lazy) + materials = new _3dsMat*[MAX_MATERIALS]; + // strange enough, the 3ds file does not have to include any materials, + // in which case we will use this one. + materials[0] = & default_material; + + parse_chunks( TopChunk, size ); + + fclose(model); + + // clean up the materials array + for (i = 0; i < num_materials; i++) { + if (materials[i] -> name != NULL) { + delete [] materials[i] -> name; + } + if (materials[i] -> tex_name != NULL) { + delete [] materials[i] -> tex_name; + } + + delete materials[i]; + } + + for ( _ssg3dsStructureNode *n = object_list, *temp; n != NULL; n = temp ) { + if ( !n -> has_been_used ) { + top_object -> addKid( n -> object ); + } + temp = n -> next; + delete n; + } + + delete [] materials; + + free_trimesh(); + + return top_object; +} + + diff --git a/src/ssg/ssgLoadAC.cxx b/src/ssg/ssgLoadAC.cxx new file mode 100644 index 0000000..f060f45 --- /dev/null +++ b/src/ssg/ssgLoadAC.cxx @@ -0,0 +1,952 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadAC.cxx 2086 2006-09-30 08:41:21Z bram $ +*/ + + +#include "ssgLocal.h" +#include "ssgVertSplitter.h" + +static FILE *loader_fd ; + +struct _ssgMaterial +{ + sgVec4 rgba ; + sgVec4 spec ; + sgVec4 emis ; + sgVec4 amb ; + float shi ; +} ; + +static int num_materials = 0 ; + +static ssgLoaderOptions *current_options = NULL ; +static int current_materialind = 0 ; +static ssgBranch *current_branch = NULL ; +static ssgVertexArray *current_vertexarray = NULL ; +static ssgTexCoordArray *current_texcoordarray = NULL ; +static ssgIndexArray *current_triindexarray = NULL ; +static ssgIndexArray *current_matindexarray = NULL ; +static ssgIndexArray *current_flagsarray = NULL ; +static char *current_tfname = NULL ; +static char *current_data = NULL ; +static float current_crease = 61.0 ; + +#define MAX_MATERIALS 1000 /* This *ought* to be enough! */ +static _ssgMaterial *mlist [ MAX_MATERIALS ] ; + +static sgMat4 current_matrix ; +static sgVec2 texrep ; +static sgVec2 texoff ; + +static sgVec2 invalidTexture = { 1e30f, } ; +static sgVec3 zero = { 0.0, } ; + +static int do_material ( char *s ) ; +static int do_object ( char *s ) ; +static int do_name ( char *s ) ; +static int do_data ( char *s ) ; +static int do_texture ( char *s ) ; +static int do_texrep ( char *s ) ; +static int do_texoff ( char *s ) ; +static int do_crease ( char *s ) ; +static int do_rot ( char *s ) ; +static int do_loc ( char *s ) ; +static int do_url ( char *s ) ; +static int do_numvert ( char *s ) ; +static int do_numsurf ( char *s ) ; +static int do_surf ( char *s ) ; +static int do_mat ( char *s ) ; +static int do_refs ( char *s ) ; +static int do_kids ( char *s ) ; + +/*static int do_obj_world ( char *s ) ; +static int do_obj_poly ( char *s ) ; +static int do_obj_group ( char *s ) ; +static int do_obj_light ( char *s ) ;*/ + +#define PARSE_CONT 0 +#define PARSE_POP 1 + +struct Tag +{ + const char *token ; + int (*func) ( char *s ) ; +} ; + + +static void skip_spaces ( char **s ) +{ + while ( **s == ' ' || **s == '\t' ) + (*s)++ ; +} + + +static void skip_quotes ( char **s ) +{ + skip_spaces ( s ) ; + + if ( **s == '\"' ) + { + (*s)++ ; + + char *t = *s ; + + while ( *t != '\0' && *t != '\"' ) + t++ ; + + if ( *t != '\"' ) + ulSetError ( UL_WARNING, "ac_to_gl: Mismatched double-quote ('\"') in '%s'", *s ) ; + + *t = '\0' ; + } + else + ulSetError ( UL_WARNING, "ac_to_gl: Expected double-quote ('\"') in '%s'", *s ) ; +} + + + +static int search ( Tag *tags, char *s ) +{ + skip_spaces ( & s ) ; + + for ( int i = 0 ; tags[i].token != NULL ; i++ ) + if ( ulStrNEqual ( tags[i].token, s, strlen(tags[i].token) ) ) + { + s += strlen ( tags[i].token ) ; + + skip_spaces ( & s ) ; + + return (*(tags[i].func))( s ) ; + } + + ulSetError ( UL_FATAL, "ac_to_gl: Unrecognised token '%s'", s ) ; + + return 0 ; /* Should never get here */ +} + +static Tag top_tags [] = +{ + { "MATERIAL", do_material }, + { "OBJECT" , do_object }, + { NULL, NULL } +} ; + + +static Tag object_tags [] = +{ + { "name" , do_name }, + { "data" , do_data }, + { "texture" , do_texture }, + { "texrep" , do_texrep }, + { "texoff" , do_texoff }, + { "crease" , do_crease }, + { "rot" , do_rot }, + { "loc" , do_loc }, + { "url" , do_url }, + { "numvert" , do_numvert }, + { "numsurf" , do_numsurf }, + { "kids" , do_kids }, + { NULL, NULL } +} ; + +static Tag surf_tag [] = +{ + { "SURF" , do_surf }, + { NULL, NULL } +} ; + +static Tag surface_tags [] = +{ + { "mat" , do_mat }, + { "refs" , do_refs }, + { NULL, NULL } +} ; + +/*static Tag obj_type_tags [] = +{ + { "world", do_obj_world }, + { "poly" , do_obj_poly }, + { "group", do_obj_group }, + { "light", do_obj_light }, + { NULL, NULL } +} ;*/ + + +#define OBJ_WORLD 0 +#define OBJ_POLY 1 +#define OBJ_GROUP 2 +#define OBJ_LIGHT 3 + +/*static int do_obj_world ( char * ) { return OBJ_WORLD ; } +static int do_obj_poly ( char * ) { return OBJ_POLY ; } +static int do_obj_group ( char * ) { return OBJ_GROUP ; } +static int do_obj_light ( char * ) { return OBJ_LIGHT ; }*/ + +static int last_num_kids = -1 ; +static int current_flags = -1 ; + +static ssgState *get_state ( _ssgMaterial *mat ) +{ + if (current_tfname != NULL) { + ssgState *st = current_options -> createState ( current_tfname ) ; + if ( st != NULL ) + return st ; + } + + ssgSimpleState *st = new ssgSimpleState () ; + + st -> setMaterial ( GL_DIFFUSE, mat -> rgba ) ; + st -> setMaterial ( GL_AMBIENT, mat -> amb ) ; + st -> setMaterial ( GL_EMISSION, mat -> emis ) ; + st -> setMaterial ( GL_SPECULAR, mat -> spec ) ; + st -> setShininess ( mat -> shi ) ; + + st -> enable ( GL_COLOR_MATERIAL ) ; + st -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + + st -> enable ( GL_LIGHTING ) ; + st -> setShadeModel ( GL_SMOOTH ) ; + + bool has_alpha = false ; + + if ( current_tfname != NULL ) + { + ssgTexture *tex = current_options -> createTexture ( current_tfname ) ; + has_alpha = tex -> hasAlpha () ; + st -> setTexture( tex ) ; + st -> enable( GL_TEXTURE_2D ) ; + } + else + { + st -> disable( GL_TEXTURE_2D ) ; + } + + if ( mat -> rgba[3] < 0.99 || has_alpha ) + { + st -> disable ( GL_ALPHA_TEST ) ; + st -> enable ( GL_BLEND ) ; + st -> setTranslucent () ; + } + else + { + st -> disable ( GL_ALPHA_TEST ) ; + st -> disable ( GL_BLEND ) ; + st -> setOpaque () ; + } + + return st ; +} + + +static int do_material ( char *s ) +{ + char name [ 1024 ] ; + sgVec4 rgba ; + sgVec4 amb ; + sgVec4 emis ; + sgVec4 spec ; + int shi ; + float trans ; + + if ( sscanf ( s, + "%s rgb %f %f %f amb %f %f %f emis %f %f %f spec %f %f %f shi %d trans %f", + name, + &rgba [0], &rgba [1], &rgba [2], + &amb [0], &amb [1], &amb [2], + &emis[0], &emis[1], &emis[2], + &spec[0], &spec[1], &spec[2], + &shi, + &trans ) != 15 ) + { + ulSetError ( UL_WARNING, "ac_to_gl: Can't parse this MATERIAL:" ) ; + ulSetError ( UL_WARNING, "ac_to_gl: MATERIAL %s", s ) ; + } + else + { + char *nm = name ; + + skip_quotes ( &nm ) ; + + amb [ 3 ] = emis [ 3 ] = spec [ 3 ] = 1.0f ; + rgba [ 3 ] = 1.0f - trans ; + + mlist [ num_materials ] = new _ssgMaterial ; + _ssgMaterial *current_material ; + current_material = mlist [ num_materials ] ; + sgCopyVec4 ( current_material -> rgba , rgba ) ; + sgCopyVec4 ( current_material -> amb , amb ) ; + sgCopyVec4 ( current_material -> emis , emis ) ; + sgCopyVec4 ( current_material -> spec , spec ) ; + current_material -> shi = (float) shi ; + } + + num_materials++ ; + return PARSE_CONT ; +} + +static int do_object ( char * /* s */ ) +{ +/* + int obj_type = search ( obj_type_tags, s ) ; +*/ + + delete [] current_tfname ; + current_tfname = NULL ; + + char buffer [ 1024 ] ; + + sgSetVec2 ( texrep, 1.0f, 1.0f ) ; + sgSetVec2 ( texoff, 0.0f, 0.0f ) ; + + sgMakeIdentMat4 ( current_matrix ) ; + + ssgEntity *old_cb = current_branch ; + + ssgTransform *tr = new ssgTransform () ; + + tr -> setTransform ( current_matrix ) ; + + current_branch -> addKid ( tr ) ; + current_branch = tr ; + + current_matindexarray = new ssgIndexArray ; + current_flagsarray = new ssgIndexArray ; + current_texcoordarray = new ssgTexCoordArray ; + current_vertexarray = new ssgVertexArray ; + current_triindexarray = new ssgIndexArray ; + + while ( fgets ( buffer, 1024, loader_fd ) != NULL ) + if ( search ( object_tags, buffer ) == PARSE_POP ) + break ; + + // If he have read some surfaces belonging to that object, + // compute normals and distribute the triangels across the materials. + int ntris = current_triindexarray -> getNum () / 3; + if ( 0 < ntris ) { + int i; + int nvert = current_vertexarray -> getNum () ; + + // Put the triangles and the current crease angle into the vertex splitter ... + ssgVertSplitter split( nvert, ntris ); + split.setSharpAngle ( current_crease ); + + for ( i = 0 ; i < nvert ; i++ ) + sgCopyVec3 ( split.vert ( i ), current_vertexarray -> get ( i ) ) ; + for ( i = 0 ; i < ntris ; i++ ) + split.setTri ( i, + * ( current_triindexarray -> get ( 3*i ) ), + * ( current_triindexarray -> get ( 3*i+1 ) ), + * ( current_triindexarray -> get ( 3*i+2 ) ) ); + + // ... and let it compute the normals. + split.splitAndCalcNormals () ; + + // Cycle through all ssgState/colour combinations and emit leafs from them. + for ( int cullface = 0 ; cullface < 2 ; cullface++ ) { + for ( int material = 0 ; material < num_materials ; material++ ) { + ssgVertexArray* vertexarray = (ssgVertexArray *) current_vertexarray -> clone () ; + vertexarray -> ref () ; + ssgNormalArray* normalarray = new ssgNormalArray ( nvert ) ; + normalarray -> ref () ; + ssgTexCoordArray* texcoordarray = (ssgTexCoordArray *) current_texcoordarray -> clone () ; + texcoordarray -> ref () ; + ssgIndexArray* triindexarray = new ssgIndexArray ( nvert ) ; + triindexarray -> ref () ; + // Mark all normals as unset using a zero vector. + for ( i = 0 ; i < nvert ; i++ ) + normalarray -> add ( zero ) ; + + bool has_texture = current_tfname != NULL ; + + // For every material/state cycle through all triangles and pick + // out those ones with that maternial/state. + for ( int tri = 0 ; tri < ntris ; tri++ ) { + int triMatindex = * ( current_matindexarray -> get ( tri ) ) ; + int triFlags = * ( current_flagsarray -> get ( tri ) ) ; + int triCullface = ! ( triFlags & 0x20 ) ; + + if ( triMatindex == material && triCullface == cullface ) { + // get the original indices + int* triind = split.getTri ( tri ) ; + int origtriind[3]; + for ( int k = 0 ; k < 3 ; k++ ) + origtriind[k] = triind[k] < nvert ? triind[k] : split.origVert( triind[k] - nvert ) ; + + // Note that copying those values prevents us from a race condion + // which occurs when doing something like: + // texcoordarray -> add ( texcoordarray -> get ( origtriind[i] ) ) ; + + // make a local copy of texcoords ... + sgVec2 texcoords[3]; + for ( i = 0 ; i < 3 ; i++ ) + sgCopyVec2 ( texcoords[i], texcoordarray -> get ( origtriind[i] ) ) ; + + // ... of vertices ... + sgVec3 vertices[3]; + for ( i = 0 ; i < 3 ; i++ ) + sgCopyVec3 ( vertices[i], split.vert ( origtriind[i] ) ) ; + + int triSmooth = ( triFlags & 0x10 ) ; + + // ... and of normals. + sgVec3 normals[3]; + if ( triSmooth ) { + for ( i = 0 ; i < 3 ; i++ ) + sgCopyVec3 ( normals[i], split.norm ( triind[i] ) ) ; + } else { + // If we have flat shading, compute one normal for all. + sgSubVec3 ( normals[1], vertices[1], vertices[0] ) ; + sgSubVec3 ( normals[2], vertices[2], vertices[0] ) ; + sgVectorProductVec3 ( normals[0], normals[1], normals[2] ) ; + sgNormaliseVec3 ( normals[0] ) ; + sgCopyVec3 ( normals[1], normals[0] ) ; + sgCopyVec3 ( normals[2], normals[0] ) ; + } + + + for ( i = 0 ; i < 3 ; i++ ) { + + if ( sgEqualVec3 ( normalarray -> get ( origtriind[i] ), zero ) ) { + // Case: not yet initialized. + + sgCopyVec3 ( normalarray -> get ( origtriind[i] ), normals[i] ) ; + + triindexarray -> add ( origtriind[i] ) ; + + } else if ( sgEqualVec3 ( normalarray -> get ( origtriind[i] ), normals[i] ) ) { + // Case: initialized and the same as before. + + triindexarray -> add ( origtriind[i] ) ; + + } else { + // Case: initialized and different. + + // Scan for a vertex/normal/texcoord triple matching the required one. + // If there exist one, use that. + int num = vertexarray -> getNum () ; + int replind = -1 ; + for ( int l = nvert ; l < num ; l++ ) { + if ( sgEqualVec3( vertices[i], vertexarray -> get ( l ) ) && + ( !has_texture || sgEqualVec2( texcoordarray -> get ( origtriind[i] ), texcoordarray -> get ( l ) ) ) && + sgEqualVec3( normals[i], normalarray -> get ( l ) ) ) { + replind = l ; + } + } + + // If we have not yet the required triple in our dataset, add it. + if ( replind < 0 ) { + vertexarray -> add ( vertices[i] ) ; + normalarray -> add ( normals[i] ) ; + texcoordarray -> add ( texcoords[i] ) ; + replind = num ; + } + triindexarray -> add ( replind ) ; + } + } + } + } + + if ( 0 < triindexarray -> getNum () ) { + ssgColourArray *colour = new ssgColourArray ( 1 ) ; + colour -> add ( mlist [ material ] -> rgba ) ; + ssgVtxArray* v = new ssgVtxArray ( GL_TRIANGLES, + vertexarray, + normalarray, + has_texture ? texcoordarray : 0, + colour, + triindexarray ) ; + v -> removeUnusedVertices(); + v -> setState ( get_state ( mlist [ material ] ) ) ; + v -> setCullFace ( cullface ) ; + ssgLeaf* leaf = current_options -> createLeaf ( v, 0 ) ; + if ( leaf ) + tr -> addKid ( leaf ) ; + } + + ssgDeRefDelete ( vertexarray ) ; + ssgDeRefDelete ( normalarray ) ; + ssgDeRefDelete ( texcoordarray ) ; + ssgDeRefDelete ( triindexarray ) ; + } + } + } + + // Cleanup + delete current_matindexarray ; + current_matindexarray = NULL ; + delete current_flagsarray ; + current_flagsarray = NULL ; + delete current_vertexarray ; + current_vertexarray = NULL ; + delete current_texcoordarray ; + current_texcoordarray = NULL ; + delete current_triindexarray ; + current_triindexarray = NULL ; + + // Process child nodes + + int num_kids = last_num_kids ; + + for ( int i = 0 ; i < num_kids ; i++ ) + { + fgets ( buffer, 1024, loader_fd ) ; + search ( top_tags, buffer ) ; + } + + current_branch = (ssgBranch *) old_cb ; + + return PARSE_CONT ; +} + + +static int do_name ( char *s ) +{ + skip_quotes ( &s ) ; + + current_branch -> setName ( s ) ; + + return PARSE_CONT ; +} + + +static int do_data ( char *s ) +{ + int len = strtol ( s, NULL, 0 ) ; + + current_data = new char [ len + 1 ] ; + + for ( int i = 0 ; i < len ; i++ ) + current_data [ i ] = getc ( loader_fd ) ; + + current_data [ len ] = '\0' ; + + int c; + while ( ( c = getc( loader_fd ) ) != EOF ) /* Final RETURN */ + if ( c != '\r' && c != '\n' ) { + ungetc ( c, loader_fd ) ; + break ; + } + + ssgBranch *br = current_options -> createBranch ( current_data ) ; + + if ( br != NULL ) + { + current_branch -> addKid ( br ) ; + current_branch = br ; + } + + /* delete [] current_data ; */ + current_data = NULL ; + + return PARSE_CONT ; +} + + +static int do_texture ( char *s ) +{ + skip_quotes ( &s ) ; + + delete [] current_tfname ; + + if ( s == NULL || s[0] == '\0' ) + current_tfname = NULL ; + else + current_tfname = ulStrDup ( s ) ; + + return PARSE_CONT ; +} + + +static int do_texrep ( char *s ) +{ + if ( sscanf ( s, "%f %f", & texrep [ 0 ], & texrep [ 1 ] ) != 2 ) + ulSetError ( UL_WARNING, "ac_to_gl: Illegal texrep record." ) ; + + return PARSE_CONT ; +} + + +static int do_texoff ( char *s ) +{ + if ( sscanf ( s, "%f %f", & texoff [ 0 ], & texoff [ 1 ] ) != 2 ) + ulSetError ( UL_WARNING, "ac_to_gl: Illegal texoff record." ) ; + + return PARSE_CONT ; +} + +static int do_crease ( char *s ) +{ + // the crease angle is not yet used. However, reading the crease line correctly means + // *.ac lines with "crease" can now be read. + if ( sscanf ( s, "%f", & current_crease ) != 1 ) + ulSetError ( UL_WARNING, "ac_to_gl: Illegal crease angle." ) ; + + return PARSE_CONT ; +} + +static int do_rot ( char *s ) +{ + current_matrix [ 0 ][ 3 ] = current_matrix [ 1 ][ 3 ] = current_matrix [ 2 ][ 3 ] = + current_matrix [ 3 ][ 0 ] = current_matrix [ 3 ][ 1 ] = current_matrix [ 3 ][ 2 ] = 0.0f ; + current_matrix [ 3 ][ 3 ] = 1.0f ; + + if ( sscanf ( s, "%f %f %f %f %f %f %f %f %f", + & current_matrix [ 0 ] [ 0 ], & current_matrix [ 0 ] [ 1 ], & current_matrix [ 0 ] [ 2 ], + & current_matrix [ 1 ] [ 0 ], & current_matrix [ 1 ] [ 1 ], & current_matrix [ 1 ] [ 2 ], + & current_matrix [ 2 ] [ 0 ], & current_matrix [ 2 ] [ 1 ], & current_matrix [ 2 ] [ 2 ] ) != 9 ) + ulSetError ( UL_WARNING, "ac_to_gl: Illegal rot record." ) ; + + ((ssgTransform *)current_branch) -> setTransform ( current_matrix ) ; + return PARSE_CONT ; +} + +static int do_loc ( char *s ) +{ + if ( sscanf ( s, "%f %f %f", & current_matrix [ 3 ][ 0 ], & current_matrix [ 3 ][ 2 ], & current_matrix [ 3 ][ 1 ] ) != 3 ) + ulSetError ( UL_WARNING, "ac_to_gl: Illegal loc record." ) ; + + current_matrix [ 3 ][ 1 ] = - current_matrix [ 3 ][ 1 ] ; + current_matrix [ 3 ][ 3 ] = 1.0f ; + ((ssgTransform *)current_branch) -> setTransform ( current_matrix ) ; + + return PARSE_CONT ; +} + +static int do_url ( char *s ) +{ + skip_quotes ( & s ) ; + +#ifdef PRINT_URLS + ulSetError ( UL_DEBUG, "/* URL: \"%s\" */\n", s ) ; +#endif + + return PARSE_CONT ; +} + +static int do_numvert ( char *s ) +{ + char buffer [ 1024 ] ; + + int nv = strtol ( s, NULL, 0 ) ; + + for ( int i = 0 ; i < nv ; i++ ) + { + sgVec3 v; + fgets ( buffer, 1024, loader_fd ) ; + + if ( sscanf ( buffer, "%f %f %f", &v[0], &v[1], &v[2] ) != 3 ) + { + ulSetError ( UL_FATAL, "ac_to_gl: Illegal vertex record." ) ; + } + + float tmp = v[1] ; + v[1] = -v[2] ; + v[2] = tmp ; + + current_vertexarray -> add ( v ) ; + current_texcoordarray -> add ( invalidTexture ) ; + } + + return PARSE_CONT ; +} + +static int do_numsurf ( char *s ) +{ + int ns = strtol ( s, NULL, 0 ) ; + + for ( int i = 0 ; i < ns ; i++ ) + { + char buffer [ 1024 ] ; + + fgets ( buffer, 1024, loader_fd ) ; + search ( surf_tag, buffer ) ; + } + + return PARSE_CONT ; +} + +static int do_surf ( char *s ) +{ + current_flags = strtol ( s, NULL, 0 ) ; + + char buffer [ 1024 ] ; + + while ( fgets ( buffer, 1024, loader_fd ) != NULL ) + if ( search ( surface_tags, buffer ) == PARSE_POP ) + break ; + + return PARSE_CONT ; +} + + +static int do_mat ( char *s ) +{ + int mat = strtol ( s, NULL, 0 ) ; + + current_materialind = mat ; + + return PARSE_CONT ; +} + +static void add_textured_vertex_edge ( short ind, sgVec2 tex ) +{ + // Add a new triangle edge. For that, check for a vertex/texcoord + // pair already in the current dataset. Use the already present index if present. + + bool has_texture = current_tfname != NULL ; + if ( sgEqualVec2( tex, current_texcoordarray -> get ( ind ) ) || !has_texture ) { + // In this case, we have that vertex/texcoord pair already at the index + // within the ac file. + + current_triindexarray -> add ( ind ) ; + + } else if ( sgEqualVec2( invalidTexture, current_texcoordarray -> get ( ind ) ) ) { + // In this case, we have not yet stored a valid texture coordinate + // for the vertex at the given index. Just copy the texturecoordinate + // value into that place. + + sgCopyVec2( current_texcoordarray -> get ( ind ), tex ) ; + + current_triindexarray -> add ( ind ) ; + + } else { + // Texture coordinate do not match the prevous texcoords stored for this vertex. + // Search for a vertex/texcoord pair matching the requested one, if not + // yet present, add a new one. + + int num = current_vertexarray -> getNum () ; + for ( int i = 0 ; i < num ; i++ ) { + if ( ( !has_texture || sgEqualVec2( tex, current_texcoordarray -> get ( i ) ) ) && + sgEqualVec3( current_vertexarray -> get ( ind ), current_vertexarray -> get ( i ) ) ) { + current_triindexarray -> add ( i ) ; + return ; + } + } + + // Need to copy that before, else we run into a racecondition where + // we copy from an location which is already freed. + sgVec3 vertex ; + sgCopyVec3 ( vertex, current_vertexarray -> get ( ind ) ) ; + current_vertexarray -> add ( vertex ) ; + current_texcoordarray -> add ( tex ) ; + + current_triindexarray -> add ( num ) ; + } +} + +static int do_refs ( char *s ) +{ + int nrefs = strtol ( s, NULL, 0 ) ; + char buffer [ 1024 ] ; + + if ( nrefs == 0 ) + return PARSE_POP ; + + int type = ( current_flags & 0x0F ) ; + + // Handle line type objects by creating a single leaf for each line segment. + if ( type == 1 || type == 2 ) { + ssgIndexArray *ind = new ssgIndexArray ; + for ( int i = 0 ; i < nrefs ; i++ ) + { + fgets ( buffer, 1024, loader_fd ) ; + + int vtx ; + float dummy ; + + if ( sscanf ( buffer, "%d %f %f", &vtx, &dummy, &dummy ) != 3 ) + { + ulSetError ( UL_FATAL, "ac_to_gl: Illegal ref record." ) ; + } + + ind -> add ( vtx ) ; + } + + ssgColourArray *col = new ssgColourArray ( 1 ) ; + col -> add ( mlist [ current_materialind ] -> rgba ) ; + + GLenum gltype = ( type == 1 ) ? GL_LINE_LOOP : GL_LINE_STRIP ; + ssgVtxArray *va = new ssgVtxArray ( gltype, (ssgVertexArray *)current_vertexarray -> clone (), + 0, 0, col, ind ); + va -> removeUnusedVertices(); + va -> setState ( get_state ( mlist [ current_materialind ] ) ) ; + + ssgLeaf *leaf = current_options -> createLeaf ( va, 0 ) ; + if ( leaf ) + current_branch -> addKid ( leaf ) ; + } + + if ( type == 0 ) { + // Handle surface datatypes. + // Each surface is triangulated and each triangle is put + // into the index array current_triindexarray. + int first_vertind = -1 ; + int prev_vertind = 0 ; + sgVec2 first_texcoord ; + sgVec2 prev_texcoord ; + for ( int i = 0 ; i < nrefs ; i++ ) + { + fgets ( buffer, 1024, loader_fd ) ; + + int vertind ; + sgVec2 texcoord ; + + if ( sscanf ( buffer, "%d %f %f", &vertind, + &texcoord[0], + &texcoord[1] ) != 3 ) + { + ulSetError ( UL_FATAL, "ac_to_gl: Illegal ref record." ) ; + } + + texcoord[0] *= texrep[0] ; + texcoord[1] *= texrep[1] ; + texcoord[0] += texoff[0] ; + texcoord[1] += texoff[1] ; + + // Store the first index texcoord pair. + // This one is referenced for every triangle. + if ( first_vertind < 0 ) { + first_vertind = vertind ; + sgCopyVec2( first_texcoord, texcoord ); + } + + // When we have read the third vertex index we can emit the first triangle. + if ( 2 <= i ) { + // Store the edges of the triangle + add_textured_vertex_edge ( first_vertind, first_texcoord ) ; + add_textured_vertex_edge ( prev_vertind, prev_texcoord ) ; + add_textured_vertex_edge ( vertind, texcoord ) ; + + // Store the material and flags for this surface. + current_matindexarray -> add ( current_materialind ); + current_flagsarray -> add ( current_flags ); + } + + // Copy current -> previous + prev_vertind = vertind ; + sgCopyVec2( prev_texcoord, texcoord ); + } + } + + return PARSE_POP ; +} + +static int do_kids ( char *s ) +{ + last_num_kids = strtol ( s, NULL, 0 ) ; + + return PARSE_POP ; +} + + +ssgEntity *ssgLoadAC3D ( const char *fname, const ssgLoaderOptions* options ) +{ + ssgEntity *obj = ssgLoadAC ( fname, options ) ; + + if ( obj == NULL ) + return NULL ; + + /* Do some simple optimisations */ + + ssgBranch *model = new ssgBranch () ; + model -> addKid ( obj ) ; + ssgFlatten ( obj ) ; + return model ; +} + +/* + Original function for backwards compatibility... +*/ + +ssgEntity *ssgLoadAC ( const char *fname, const ssgLoaderOptions* options ) +{ + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + current_options = ssgGetCurrentOptions () ; + + char filename [ 1024 ] ; + current_options -> makeModelPath ( filename, fname ) ; + + num_materials = 0 ; + + current_tfname = NULL ; + current_branch = NULL ; + + current_crease = 61.0 ; + + sgSetVec2 ( texrep, 1.0, 1.0 ) ; + sgSetVec2 ( texoff, 0.0, 0.0 ) ; + + loader_fd = fopen ( filename, "r" ) ; + + if ( loader_fd == NULL ) + { + ulSetError ( UL_WARNING, "ssgLoadAC: Failed to open '%s' for reading", filename ) ; + return NULL ; + } + + char buffer [ 1024 ] ; + int firsttime = TRUE ; + + current_branch = new ssgTransform () ; + + while ( fgets ( buffer, 1024, loader_fd ) != NULL ) + { + char *s = buffer ; + + /* Skip leading whitespace */ + + skip_spaces ( & s ) ; + + /* Skip blank lines and comments */ + + if ( *s < ' ' && *s != '\t' ) continue ; + if ( *s == '#' || *s == ';' ) continue ; + + if ( firsttime ) + { + firsttime = FALSE ; + + if ( ! ulStrNEqual ( s, "AC3D", 4 ) ) + { + fclose ( loader_fd ) ; + ulSetError ( UL_WARNING, "ssgLoadAC: '%s' is not in AC3D format.", filename ) ; + return NULL ; + } + } + else + search ( top_tags, s ) ; + } + + for (int i = 0; i < num_materials; i++) + { + delete mlist[i]; + mlist[i]=0; + } + num_materials=0; + + delete [] current_tfname ; + current_tfname = NULL ; + fclose ( loader_fd ) ; + + return current_branch ; +} + diff --git a/src/ssg/ssgLoadASC.cxx b/src/ssg/ssgLoadASC.cxx new file mode 100644 index 0000000..d8eeea9 --- /dev/null +++ b/src/ssg/ssgLoadASC.cxx @@ -0,0 +1,1015 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + +*/ + +// +// .ASC loader for SSG/PLIB +// ASC = ascii files, used for example by 3DS R4 (the DOS version) +// Written by Wolfram Kuss (Wolfram.Kuss@t-online.de) on 3.10.2004 +// +#include "ssgLocal.h" +#include "ssgLoaderWriterStuff.h" +#include "ssgParser.h" + +#define u32 unsigned int + +// These functions return TRUE on success +typedef int AscHandlerFunctionType(); + + +static char *globEmpty=""; + +static ssgBranch *curr_branch_; + +struct AscEntityType +{ + const char * sName; + AscHandlerFunctionType *HandleEntity; + bool appearsInsideAMesh; +} ; + +void AscLinePreProcessor(char *line) +// there are lines like this +// Page 2 +// in *.asc files. They should be completely ignored. + +{ char *p = line; + while((*p == ' ') || (*p == 9)) + p++; + // p points to the first word (or the line end) now. + if(ulStrNEqual(p, "Page", strlen("Page"))) + { + // Since this loader ignores the line structure, + // we can also ignore the \n or \r and just "delete" the whole line + line[0] = 0; + } + if(ulStrNEqual(p, "Camera", strlen("Camera"))) + line[0] = 0; +} + + +static /* const */ ssgLoaderOptions* current_options = NULL ; + +static _ssgParserSpec parser_spec = +{ + "\r\n\t ", // delim_chars_skipable + "=:", // delim_chars_non_skipable so that things like "red=0.5" or "vertex 0:" work + AscLinePreProcessor, // pre_processor + "{", // open_brace_chars - unused + "}", // close_brace_chars - unused + '"', // quote_char + '#', // comment_char - I am not sure there are comments and if so which char starts them + "//" // comment_string - I am not sure there are comments and if so which string starts them +} ; + + +static _ssgParser parser; +static ssgBranch* top_branch; + +static int Ascii2Int(int &retVal, const char *token, const char* name ) +// returns TRUE on success +{ + char *endptr; + retVal = int(strtol( token, &endptr, 10)); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { parser.error("The field %s should contain an integer number but contains %s",name, token) ; + return FALSE; + } +} + +static int Ascii2UInt(unsigned int &retVal, const char *token, const char* name ) +// returns TRUE on success +{ + char *endptr; + retVal = (unsigned int)(strtol( token, &endptr, 10)); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { parser.error("The field %s should contain an integer number but contains %s",name, token) ; + return FALSE; + } +} + +static int Ascii2Float(SGfloat &retVal, const char *token, const char* name ) +// returns TRUE on success +{ + char *endptr; + retVal = SGfloat(strtod( token, &endptr)); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { parser.error("The field %s should contain an integer number but contains %s",name, token) ; + return FALSE; + } +} + + +struct MeshStatusType { + bool isvalid; // rest of this is valid, IOW I am inside reading a mesh + char *sName; + bool mapped; + bool materialed_but_not_mapped; // only defined if mapped = FALSE + bool hidden; // unused + int maxVertex, maxFace, curVertex, curFace; + void set_sName(char *s); + // material + smoothing is per poly!!! +} MeshStatus; + + +void MeshStatusType::set_sName(char *s) +{ + if(sName) + delete [] sName; + sName = new char[strlen(s)+1]; + strcpy(sName, s); +} + +void CheckIndex(int &i, int max) +{ + if((i<0) || (i>=max)) + { fprintf(stderr, "Mesh '%s': Index %d is not in the range 0 to %d!", MeshStatus.sName, i, max); + i = 0; + } +} + +void CheckWhetherMeshHasEnded(); +static int HandleMeshMaterialList(const char *firstToken); +static int HandleMaterialOld(const char *firstToken); +static int HandleTextureFileName(const char *firstToken); + +static int HandleAmbient(); +static int HandleSolid(); +static int HandleNamed(); +static int HandleTriMesh(); +static int HandleHidden(); +static int HandleMapped(); +static int HandleVertex(); +static int HandleFace(); +static int HandleMaterial(); +static int HandleSmoothing(); +static int HandleDirect(); +static int HandlePosition(); +static int HandleLight(); +static int HandleSpotlight(); +static int HandleHotspot (); +static int HandleFalloff (); +static int HandleGlobal (); +// unneeded static int HandleCamera(); +static int HandleTarget(); +static int HandleBank(); +static int HandleNear(); + +static AscEntityType aEntities[] = +{ + { "Spotlight", HandleSpotlight, FALSE}, + { "Hotspot", HandleHotspot , FALSE}, + { "Falloff", HandleFalloff , FALSE}, + { "Global", HandleGlobal , FALSE}, +// unneeded { "Camera", HandleCamera, FALSE}, + { "Target", HandleTarget, FALSE}, + { "Bank", HandleBank, FALSE}, + { "Near", HandleNear, FALSE}, + { "Ambient", HandleAmbient, FALSE}, + { "Solid", HandleSolid, FALSE}, + { "Named", HandleNamed, FALSE}, + { "Tri-mesh,", HandleTriMesh, TRUE}, + { "Hidden", HandleHidden, TRUE}, + { "Mapped", HandleMapped, TRUE}, + { "Vertex", HandleVertex, TRUE}, + { "Face", HandleFace, TRUE}, + { "Material", HandleMaterial, TRUE}, + { "Smoothing", HandleSmoothing}, + { "Direct", HandleDirect, FALSE}, + { "Position", HandlePosition, FALSE}, + { "Light", HandleLight, FALSE}, + { NULL, NULL} +}; + + +static int ParseEntity(char *token) +// called recursively +// copied from ssgLoadX; A bit (?) of overkill for *.asc. +{ int i=0; + + while(aEntities[i].sName!=NULL) + { if (!strcmp(token,aEntities[i].sName)) + { if (aEntities[i].HandleEntity != NULL) + { /*char *sNextToken, *sName=globEmpty; + sNextToken=parser.getNextToken(0); + if ( parser.eof ) + { parser.error("unexpected end of file\n"); + return FALSE; + }*/ + if(!aEntities[i].appearsInsideAMesh) + CheckWhetherMeshHasEnded(); + if (!aEntities[i].HandleEntity(/*sNextToken*/)) + return FALSE; + } + else + { + parser.error("I am sorry, but Entity-type '%s' is not yet implemented.", aEntities[i].sName); + return FALSE ; + } + + break; + } + i++; + } + if (aEntities[i].sName==NULL) + { + parser.error("unexpected token %s", token); + return FALSE ; + } + return TRUE; +} + +#define MAX_ASC_MATERIALS 1024 + +struct AscMaterialType { + char *sName; + ssgSimpleState *ss; +} AscMaterials[MAX_ASC_MATERIALS]; +static int noOfAscmaterials=0; + + +#define MAX_NO_VERTICES_PER_FACE 1000 + +static class ssgLoaderWriterMesh currentMesh; + +static ssgSimpleState *currentState; + +// we only need one of these, since obviously the texture name is the only materialproperty in asc: +static ssgSimpleState *untexturedState = NULL; + +extern sgVec4 currentDiffuse; + + +static int HandleDirect() +// example line: +// "Direct light" +{ + parser.expectNextToken("light"); + return TRUE; +} +/* not needed since handled via the PreProcessor +static int HandleCamera() +// example line: +// Camera (51.944435mm) +{ + float Dummy; + parser.expectNextToken("("); + if (!parser.getNextFloat(Dummy, "Camera")) return FALSE; + parser.expectNextToken("mm)"); + return TRUE; +} +*/ +static int HandleTarget() +// example line: +// Target: X:7.573029 Y:-989.009766 Z:6.24827() +{ + float Dummy; + parser.expectNextToken(":"); + parser.expectNextToken("X"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(Dummy, "Target X")) return FALSE; + parser.expectNextToken("Y"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(Dummy, "Target Y")) return FALSE; + parser.expectNextToken("Z"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(Dummy, "Target Z")) return FALSE; + return TRUE; +} + +static int HandleBank() +// example line: +// Bank angle: 0 degrees +{ + float Dummy; + parser.expectNextToken("angle"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(Dummy, "Bank angle")) return FALSE; + parser.expectNextToken("degrees"); + return TRUE; +} + +static int HandleNear() +// example line: +// Near 0 Far 1000 +{ + float Dummy; + if (!parser.getNextFloat(Dummy, "Near")) return FALSE; + parser.expectNextToken("Far"); + if (!parser.getNextFloat(Dummy, "Far")) return FALSE; + return TRUE; +} + +static int HandlePosition() +// example line: +// "Position: X:-534.261475 Y:484.437958 Z:203.464706" +{ + float Dummy; + parser.expectNextToken(":"); + parser.expectNextToken("X"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(Dummy, "light X")) return FALSE; + parser.expectNextToken("Y"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(Dummy, "light Y")) return FALSE; + parser.expectNextToken("Z"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(Dummy, "light Z")) return FALSE; + return TRUE; + +} + +static int HandleSpotlight() +// example line: +// "Spotlight to: X:-1.4 Y:-0.607239 Z:-16.277397" +{ + float Dummy; + parser.expectNextToken("to"); + parser.expectNextToken(":"); + parser.expectNextToken("X"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(Dummy, "Spotlight to X")) return FALSE; + parser.expectNextToken("Y"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(Dummy, "Spotlight to Y")) return FALSE; + parser.expectNextToken("Z"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(Dummy, "Spotlight to Z")) return FALSE; + return TRUE; +} + +static int HandleHotspot () +// example line: +// "Hotspot size: 54 degrees" +{ + float Dummy; + parser.expectNextToken("size"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(Dummy, "Hotspot size")) return FALSE; + parser.expectNextToken("degrees"); + return TRUE; +} + +static int HandleFalloff () +// example line: +// "Falloff size: 54.5 degrees" +{ + float Dummy; + parser.expectNextToken("size"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(Dummy, "Falloff size")) return FALSE; + parser.expectNextToken("degrees"); + return TRUE; +} + +static int HandleGlobal () +// example line: +// "Global Shadow" +{ + parser.expectNextToken("Shadow"); + return TRUE; +} + + +static int HandleLight() +// example line: +// "Light color: Red=1 Green=1 Blue=1" +{ + float Dummy; + parser.expectNextToken("color"); + parser.expectNextToken(":"); + parser.expectNextToken("Red"); + parser.expectNextToken("="); + if (!parser.getNextFloat(Dummy, "Light red")) return FALSE; + parser.expectNextToken("Green"); + parser.expectNextToken("="); + if (!parser.getNextFloat(Dummy, "Light Green")) return FALSE; + parser.expectNextToken("Blue"); + parser.expectNextToken("="); + if (!parser.getNextFloat(Dummy, "Light Blue")) return FALSE; + return TRUE; +} + + + +static int HandleAmbient() +// example line: +// "Ambient light color: Red=0.180392 Green=0.180392 Blue=0.180392" +{ + float Dummy; + parser.expectNextToken("light"); + parser.expectNextToken("color"); + parser.expectNextToken(":"); + parser.expectNextToken("Red"); + parser.expectNextToken("="); + if (!parser.getNextFloat(Dummy, "Ambient red")) return FALSE; + parser.expectNextToken("Green"); + parser.expectNextToken("="); + if (!parser.getNextFloat(Dummy, "Ambient green")) return FALSE; + parser.expectNextToken("Blue"); + parser.expectNextToken("="); + if (!parser.getNextFloat(Dummy, "Ambient blue")) return FALSE; + return TRUE; +} + +static int HandleSolid() +// example line: +// "Solid background color: Red=0.345098 Green=0.6 Blue=0.807843" +{ + parser.expectNextToken("background"); + parser.expectNextToken("color"); + parser.expectNextToken(":"); + parser.expectNextToken("Red"); + parser.expectNextToken("="); + float Dummy; + if (!parser.getNextFloat(Dummy, "Background red")) return FALSE; + parser.expectNextToken("Green"); + parser.expectNextToken("="); + if (!parser.getNextFloat(Dummy, "Background green")) return FALSE; + parser.expectNextToken("Blue"); + parser.expectNextToken("="); + if (!parser.getNextFloat(Dummy, "Background blue")) return FALSE; + return TRUE; +} + +static int HandleNamed() +// example line: +// "Named object: "EX1_A"" +{ + parser.expectNextToken("object"); + parser.expectNextToken(":"); +// assert(MeshStatus.isvalid); comes before trimesh ! + char *s; // cleaned up sName + s = parser.getNextToken("Mesh name"); + if(*s=='"') + s++; + if(s[strlen(s)-1]=='"') + s[strlen(s)-1]=0; + + MeshStatus.set_sName(s); + + return TRUE; +} + +static int HandleTriMesh() +// example line: +// "Tri-mesh, Vertices: 22 Faces: 18" +{ + parser.expectNextToken("Vertices"); + parser.expectNextToken(":"); + if (!parser.getNextInt(MeshStatus.maxVertex, "Number vertices")) return FALSE; + parser.expectNextToken("Faces"); + parser.expectNextToken(":"); + if (!parser.getNextInt(MeshStatus.maxFace, "Number faces")) return FALSE; + if(MeshStatus.isvalid) + { + fprintf(stderr, "MeshStatus.isvalid is TRUE. Probably, in the mesh preceding '%s', there are more faces than predicted", MeshStatus.sName); + return FALSE; + } + MeshStatus.isvalid = TRUE; + MeshStatus.curVertex = -1; + MeshStatus.curFace = -1; + MeshStatus.mapped = FALSE; + MeshStatus.materialed_but_not_mapped = FALSE; + MeshStatus.hidden = FALSE; // unused + noOfAscmaterials=0; + currentState = untexturedState; + + + currentMesh.reInit (); + currentMesh.setName( MeshStatus.sName ); + currentMesh.createVertices( MeshStatus.maxVertex ); + currentMesh.createFaces( MeshStatus.maxFace ); + + return TRUE; +} + +static int HandleHidden() +// example line: +// "Hidden" +{ + assert(MeshStatus.isvalid); + MeshStatus.hidden = TRUE; // unused + return TRUE; +} + +static int HandleMapped() +// example line: +// "Mapped" +{ + assert(MeshStatus.isvalid); + currentMesh.createPerVertexTextureCoordinates2( MeshStatus.maxVertex ) ; + currentMesh.createMaterials(); + currentMesh.createMaterialIndices( MeshStatus.maxFace ); + MeshStatus.mapped = TRUE; + return TRUE; +} + +static int HandleSmoothing() +// example line: +// "Smoothing: 1" +{ + int i; + parser.expectNextToken(":"); + if (!parser.getNextInt(i, "Smoothing")) return FALSE; + return TRUE; +} + + +int SetOrGetMaterial(char *sMatName) +// if exists, gets the index. Else sets sName and creates the ss +{ + char *s; // cleaned up sName + s = sMatName; + if(*s=='"') + s++; + if(s[strlen(s)-1]=='"') + s[strlen(s)-1]=0; + // **** search for it **** + for(int i=0; isetOpaque(); + currentState->disable(GL_BLEND); + currentState->disable(GL_ALPHA_TEST); + currentState->disable(GL_TEXTURE_2D); + currentState->enable(GL_COLOR_MATERIAL); + currentState->enable(GL_LIGHTING); + currentState->setShadeModel(GL_SMOOTH); + currentState->setMaterial(GL_AMBIENT , 0.7f, 0.7f, 0.7f, 1.0f); + currentState->setMaterial(GL_DIFFUSE , 0.7f, 0.7f, 0.7f, 1.0f); + currentState->setMaterial(GL_SPECULAR, 1.0f, 1.0f, 1.0f, 1.0f); + currentState->setMaterial(GL_EMISSION, 0.0f, 0.0f, 0.0f, 1.0f); + currentState->setShininess(50); + // set texture + currentState -> setTexture( current_options -> createTexture( s ) ); + currentState -> setName(s); + currentState -> enable( GL_TEXTURE_2D ); + currentMesh.addMaterial(¤tState); + return noOfAscmaterials-1; +} + + +static int HandleMaterial() +// example line: +// "Material:"BEXHUST"" +{ + parser.expectNextToken(":"); + if(!MeshStatus.mapped && !MeshStatus.materialed_but_not_mapped) + { + currentMesh.createMaterials(); + currentMesh.createMaterialIndices( MeshStatus.maxFace ); + MeshStatus.materialed_but_not_mapped = TRUE; + } + + + char *sMaterialName = parser.getNextToken("Material name"); + int i = SetOrGetMaterial(sMaterialName); + currentMesh.addMaterialIndex(i); + + return TRUE; +} + +static int HandleVertex() +// example line: +// "Vertex list:" +// *or* (!!) +// "Vertex 0: X:115.710701 Y:180.000305 Z:-60.796242 U:0.048042 V:0.996284" +{ + char *sNextToken = parser.peekAtNextToken( "vertex list?" ); + if(ulStrEqual("list", sNextToken)) + { + parser.expectNextToken("list"); + parser.expectNextToken(":"); + } + else + { + sgVec3 vert; + int i; + if (!parser.getNextInt(i, "vertex index")) return FALSE; + assert(MeshStatus.isvalid); + assert(MeshStatus.maxVertex > i); + assert(MeshStatus.curVertex == i-1); + MeshStatus.curVertex ++; + parser.expectNextToken(":"); + parser.expectNextToken("X"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(vert[0], "X")) return FALSE; + parser.expectNextToken("Y"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(vert[1], "Y")) return FALSE; + parser.expectNextToken("Z"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(vert[2], "Z")) return FALSE; + if(MeshStatus.mapped) + { + // read texture coordinates + sgVec2 tv; + parser.expectNextToken("U"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(tv[0], "U")) return FALSE; + parser.expectNextToken("V"); + parser.expectNextToken(":"); + if (!parser.getNextFloat(tv[1], "V")) return FALSE; + currentMesh.addPerVertexTextureCoordinate2( tv ) ; + } + currentMesh.addVertex(vert); + } + + return TRUE; +} + +static int HandleFace() +// example line: +// "Face list:" +// *or* (!!) +// "Face 0: A:0 B:10 C:7 AB:1 BC:1 CA:1" +{ + char *sNextToken = parser.peekAtNextToken( "Face list?" ); + if(ulStrEqual("list", sNextToken)) + { + parser.expectNextToken("list"); + parser.expectNextToken(":"); + } + else + { + int iFace, AB, _BC, CA; + int aiVertices[3]; + if (!parser.getNextInt(iFace, "Face index")) return FALSE; + assert(MeshStatus.isvalid); + assert(MeshStatus.maxFace > iFace); + assert(MeshStatus.curFace == iFace-1); + MeshStatus.curFace ++; + parser.expectNextToken(":"); + parser.expectNextToken("A"); + parser.expectNextToken(":"); + if (!parser.getNextInt(aiVertices[0], "A")) return FALSE; + CheckIndex(aiVertices[0], MeshStatus.maxVertex); + parser.expectNextToken("B"); + parser.expectNextToken(":"); + if (!parser.getNextInt(aiVertices[1], "B")) return FALSE; + CheckIndex(aiVertices[1], MeshStatus.maxVertex); + parser.expectNextToken("C"); + parser.expectNextToken(":"); + if (!parser.getNextInt(aiVertices[2], "C")) return FALSE; + CheckIndex(aiVertices[2], MeshStatus.maxVertex); + parser.expectNextToken("AB"); + parser.expectNextToken(":"); + if (!parser.getNextInt(AB, "AB")) return FALSE; + parser.expectNextToken("BC"); + parser.expectNextToken(":"); + if (!parser.getNextInt(_BC, "BC")) return FALSE; // "BC" is already used :-/ + parser.expectNextToken("CA"); + parser.expectNextToken(":"); + if (!parser.getNextInt(CA, "CA")) return FALSE; + currentMesh.addFaceFromIntegerArray(3, aiVertices); + } + return TRUE; +} + + +// end todo ############################################################## + + + +/////////////////////////////////////////////////// old +// start alt todo ############################################################## + + + + +static int HandleTextureFileName(const char *firstToken) +{/* + TextureFilename { + "../image/box_top.gif"; + } #TextureFilename + */ + char *filename_ptr, *filename = new char [ strlen(firstToken)+1 ] ; + assert(filename!=NULL); + strcpy ( filename, firstToken ) ; + filename_ptr = filename ; + + if ( filename_ptr[0] == '"' ) + filename_ptr++; + if (filename_ptr[strlen(filename_ptr)-1] == '"') + filename_ptr[strlen(filename_ptr)-1] = 0; + currentState -> setTexture( current_options -> createTexture( filename_ptr ) ); + currentState -> enable( GL_TEXTURE_2D ); + + + parser.expectNextToken(";"); + parser.expectNextToken("}"); + delete [] filename; + return TRUE; +} + +static int HandleMaterialOld(const char *firstToken) +// return TRUE on success +{ SGfloat power; + int bFoundTextureFileName = FALSE; + sgVec4 specularColour, EmissiveColour; + + // read body + if (! Ascii2Float(currentDiffuse[0], firstToken, "Facecolour R")) + return FALSE; + + parser.expectNextToken(";"); + if (!parser.getNextFloat(currentDiffuse[1], "Facecolour G")) return FALSE; + parser.expectNextToken(";"); + if (!parser.getNextFloat(currentDiffuse[2], "Facecolour B")) return FALSE; + parser.expectNextToken(";"); + if (!parser.getNextFloat(currentDiffuse[3], "Facecolour A")) return FALSE; + parser.expectNextToken(";"); + parser.expectNextToken(";"); + if (!parser.getNextFloat(power, "power")) return FALSE; + parser.expectNextToken(";"); + if (!parser.getNextFloat(specularColour[0], "Specular R")) return FALSE; + parser.expectNextToken(";"); + if (!parser.getNextFloat(specularColour[1], "Specular G")) return FALSE; + parser.expectNextToken(";"); + if (!parser.getNextFloat(specularColour[2], "Specular B")) return FALSE; + specularColour[3] = 0.0; + parser.expectNextToken(";"); + parser.expectNextToken(";"); + if (!parser.getNextFloat(EmissiveColour[0], "Emissive R")) return FALSE; + parser.expectNextToken(";"); + if (!parser.getNextFloat(EmissiveColour[1], "Emissive G")) return FALSE; + parser.expectNextToken(";"); + if (!parser.getNextFloat(EmissiveColour[2], "Emissive B")) return FALSE; + EmissiveColour[3] = 0.0; + parser.expectNextToken(";"); + parser.expectNextToken(";"); + + // create SimpleState + + currentState = new ssgSimpleState () ; + +// currentState -> setMaterial ( GL_AMBIENT, mat -> amb ) ; + currentState -> setMaterial ( GL_DIFFUSE, currentDiffuse) ; + currentState -> setMaterial ( GL_SPECULAR, specularColour) ; + currentState -> setMaterial ( GL_SPECULAR, specularColour[0], + specularColour[1], specularColour[2], currentDiffuse[3] ) ; + currentState -> setMaterial ( GL_EMISSION, EmissiveColour[0], + EmissiveColour[1], EmissiveColour[2], currentDiffuse[3] ) ; + + currentState -> setShininess ( power ) ; // Fixme, NIV14: Is that correct? + + currentState -> enable ( GL_COLOR_MATERIAL ) ; + currentState -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + + currentState -> enable ( GL_LIGHTING ) ; + currentState -> setShadeModel ( GL_SMOOTH ) ; + + if ( currentDiffuse[3] > 0.0f ) + { + currentState -> disable ( GL_ALPHA_TEST ) ; + currentState -> enable ( GL_BLEND ) ; + currentState -> setTranslucent () ; + } + else + { + currentState -> disable ( GL_BLEND ) ; + currentState -> setOpaque () ; + } + currentState -> disable( GL_TEXTURE_2D ); + + + + while(TRUE) + { char *nextToken =parser.getNextToken(0); + if (0==strcmp("}", nextToken)) + { currentMesh.addMaterial( ¤tState ); + return TRUE; // Material is finished. success + } + + if ( 0!= strcmp("TextureFilename", nextToken) ) + { parser.error("TextureFilename expected!\n"); + return FALSE; + } + if ( bFoundTextureFileName ) + { parser.error("Only one TextureFileName per Material please!\n"); + return FALSE; + } + if (!ParseEntity(nextToken)) // read "TextureFileName" + return FALSE; + bFoundTextureFileName = TRUE; + } + return TRUE; //lint !e527 +} + + +static int HandleMeshMaterialList(const char *firstToken) +{ + u32 i, nFaceIndexes, nMaterialsRead = 0, nMaterials; + + if (! Ascii2UInt(nMaterials, firstToken, "nMaterials")) + return FALSE; + + parser.expectNextToken(";"); + currentMesh.createMaterials( nMaterials ); + if (!parser.getNextUInt(nFaceIndexes, "number of Face Indexes")) + return FALSE; + currentMesh.createMaterialIndices( nFaceIndexes ) ; + parser.expectNextToken(";"); + + + if ( nFaceIndexes > currentMesh.getNumFaces()) + { parser.error("No of face indexes of materiallist (%d) is greater than then no " + "of faces (%d)!\n" + "Therefore the material list is ignored!", + ( int ) nFaceIndexes, ( int ) currentMesh.getNumFaces()); + return TRUE; // go on parsing + } + if ( nFaceIndexes > currentMesh.getNumFaces()) + parser.message("Informational: No of face indexes of materiallist (%d) is less than then no " + "of faces (%d)\n" , + ( int ) nFaceIndexes, ( int ) currentMesh.getNumFaces()); + for ( i=0 ; i= nMaterials ) + { parser.error("Too many Materials!\n"); + return FALSE; + } + if (!ParseEntity(nextToken)) // read "Material" + return FALSE; + nMaterialsRead++; + } + return TRUE; //lint !e527 +} + + + +// end alt todo ############################################################## + +void CheckWhetherMeshHasEnded() +{ if(MeshStatus.isvalid && + (MeshStatus.curFace == MeshStatus.maxFace-1) && + (MeshStatus.curVertex == MeshStatus.maxVertex-1)) + { + // end mesh PART FROM MATREEIAL AND SMOOTH + //u32 i, j, nNoOfVertices, nNoOfVerticesForThisFace, nNoOfFaces; + + + if ( currentState == NULL ) + { currentState = new ssgSimpleState(); + currentState->setOpaque(); + currentState->disable(GL_BLEND); + currentState->disable(GL_ALPHA_TEST); + currentState->disable(GL_TEXTURE_2D); + currentState->enable(GL_COLOR_MATERIAL); + currentState->enable(GL_LIGHTING); + currentState->setShadeModel(GL_SMOOTH); + currentState->setMaterial(GL_AMBIENT , 0.7f, 0.7f, 0.7f, 1.0f); + currentState->setMaterial(GL_DIFFUSE , 0.7f, 0.7f, 0.7f, 1.0f); + currentState->setMaterial(GL_SPECULAR, 1.0f, 1.0f, 1.0f, 1.0f); + currentState->setMaterial(GL_EMISSION, 0.0f, 0.0f, 0.0f, 1.0f); + currentState->setShininess(50); + /* + currentState -> setMaterial ( GL_AMBIENT, 0.5, 0.5, 0.5); + currentState -> setMaterial ( GL_DIFFUSE, 0.7, 0.7, 0.7); // light grey + currentState -> setMaterial ( GL_SPECULAR, 1.0, 1.0, 1.0); + currentState -> setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0); + + currentState -> setShininess ( 3 ) ; + + //currentState -> enable ( GL_COLOR_MATERIAL ) ; + //currentState -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + + currentState -> enable ( GL_LIGHTING ) ; + currentState -> setShadeModel ( GL_SMOOTH ) ; + + currentState -> disable ( GL_BLEND ) ; + currentState -> setOpaque () ; + currentState -> disable( GL_TEXTURE_2D ); + */ + } + + currentMesh.addToSSG( + currentState // Pfusch, kludge. NIV135 + , + current_options, + curr_branch_); + MeshStatus.isvalid = FALSE; + } +} + +static int parse() +{ + char* token; + token = parser.getNextToken(0); // getNextToken -> line structure is ignored (IOW line ends are ignored) + while (! parser.eof ) + { + if (!ParseEntity(token)) + return FALSE; + + token = parser.getNextToken(0); + } + CheckWhetherMeshHasEnded(); + return TRUE ; +} + + +ssgEntity *ssgLoadASC ( const char *fname, const ssgLoaderOptions* options ) +{ + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + current_options = ssgGetCurrentOptions () ; + + + MeshStatus.isvalid=FALSE; + MeshStatus.sName = NULL; + + + untexturedState = new ssgSimpleState; + untexturedState->setOpaque(); + untexturedState->disable(GL_BLEND); + untexturedState->disable(GL_ALPHA_TEST); + untexturedState->disable(GL_TEXTURE_2D); + untexturedState->enable(GL_COLOR_MATERIAL); + untexturedState->enable(GL_LIGHTING); + untexturedState->setShadeModel(GL_SMOOTH); + untexturedState->setMaterial(GL_AMBIENT , 0.7f, 0.7f, 0.7f, 1.0f); + untexturedState->setMaterial(GL_DIFFUSE , 0.7f, 0.7f, 0.7f, 1.0f); + untexturedState->setMaterial(GL_SPECULAR, 1.0f, 1.0f, 1.0f, 1.0f); + untexturedState->setMaterial(GL_EMISSION, 0.0f, 0.0f, 0.0f, 1.0f); + untexturedState->setShininess(50); + untexturedState->ref(); + + currentState = untexturedState; + top_branch = new ssgBranch ; + curr_branch_ = top_branch; + if ( !parser.openFile( fname, &parser_spec )) + { + delete top_branch ; + return 0; + } + if ( !parse() ) + { + delete top_branch ; + top_branch = 0 ; + } +// parse_free(); + parser.closeFile(); + + untexturedState->deRef(); + if(untexturedState->getRef()==0) + delete untexturedState; + return top_branch ; +} diff --git a/src/ssg/ssgLoadASE.cxx b/src/ssg/ssgLoadASE.cxx new file mode 100644 index 0000000..5b63a7f --- /dev/null +++ b/src/ssg/ssgLoadASE.cxx @@ -0,0 +1,1704 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadASE.cxx 1988 2004-10-29 22:41:37Z wolfram_kuss $ +*/ + +/**** +* NAME +* ssgLoadASE -- ASE model loader +* +* DESCRIPTION +* ssgLoadASE will load an ASE model exported from 3dsmax using +* the standard ascii export v2.00 plugin. +* +* The material list and geometry objects are parsed and converted +* into an SSG scene graph. shape, light, camera, and helper +* nodes are ignored. +* +* If the geometry has vertex colours (pre-lit) then lighting is +* disabled for that leaf. +* +* mesh animation creates ssgSelector entities. transform +* animation creates ssgTransform entities with ssgTransformArray +* user_data. see the viewer example for details on controlling +* animation. +* +* NOTE: be sure you _reset the transform_ of the top-level object +* in 3dsmax before exporting transform animation. +* +* Please report any bugs to the author. Complete information about +* the ASE format can be found in the 3dsmax SDK source code. +* +* AUTHOR +* Dave McClurg +* +* CREATION DATE +* Feb-2000 +* +* MODIFICATION HISTORY +* November 2000 - v1.1, Dave McClurg +* o support for transform animation samples +****/ + +#include "ssgLocal.h" +#include "ssgParser.h" + + +#define u32 unsigned int +#define f32 float +#define cchar const char + + +static ssgLoaderOptions* current_options = NULL ; + +struct aseVertexBuffer +{ + bool use_flag ; + int index ; + sgVec3 v ; + sgVec2 tv ; + sgVec3 cv ; +} ; + + +struct aseFace +{ + u32 v[3]; + u32 tv[3]; + u32 cv[3]; + u32 sub_index; + + // SAC: Additional vals to track normals for each face vertex. + // Since each vertex can supposedly have various normals if shared by two + // non-smoothed faces, we track them per face. I haven't checked this as + // good as I should have with smoothed & unsmoothed shapes :) + bool has_vertex_normals; + sgVec3 vn [3]; +}; + + +struct aseTransform +{ + sgVec3 pos ; + sgVec3 axis ; // axis of rotation (unit vector) + f32 angle ; // angle of rotation in radians (always >0) + sgVec3 scale ; +} ; + + +struct aseMesh +{ + u32 num_faces ; + u32 num_verts ; + u32 num_tverts ; + u32 num_cverts ; + + aseFace* faces ; + sgVec3* verts ; + sgVec2* tverts ; + sgVec3* cverts ; + + aseMesh(); + ~aseMesh(); +}; + + +struct aseObject +{ + enum Type { GEOM, HELPER, CAMERA } ; + int type ; + char* name ; + char* parent ; + bool inherit_pos [3] ; + sgVec3 pos ; + sgVec3 target ; + u32 mat_index ; + u32 num_tkeys ; + aseTransform* tkeys ; + + enum { MAX_FRAMES = 256 }; + aseMesh* mesh_list[ MAX_FRAMES ]; + int mesh_count ; + + aseObject( Type type ); + ~aseObject(); +}; + +struct aseMaterial +{ + char* name ; + u32 mat_index ; + u32 sub_index ; + bool sub_flag ; + + sgVec4 amb ; + sgVec4 diff ; + sgVec4 spec ; + f32 shine ; + f32 transparency ; + + char* tfname ; + sgVec2 texrep ; + sgVec2 texoff ; +}; + + +#define MAX_MATERIALS 1000 +static aseMaterial** materials ; +static u32 num_materials ; + +static u32 first_frame ; +static u32 last_frame ; +static u32 frame_speed ; +static u32 ticks_per_frame ; +static u32 num_frames=0 ; + +static _ssgParserSpec parser_spec = +{ + "\r\n\t ", // delim_chars_skipable + 0, // delim_chars_non_skipable + NULL, // pre_processor + "{", // open_brace_chars + "}", // close_brace_chars + '"', // quote_char + 0, // comment_char + 0 // comment_string +} ; + +static _ssgParser parser; +static ssgBranch* top_branch; + +aseMesh::aseMesh() +{ + memset(this,0,sizeof(aseMesh)); +} + + +aseMesh::~aseMesh() +{ + delete[] faces; + delete[] verts; + delete[] tverts; + delete[] cverts; +} + + +aseObject::aseObject( aseObject::Type _type ) +{ + memset(this,0,sizeof(aseObject)); + type = _type ; +} + + +aseObject::~aseObject() +{ + delete[] name; + delete[] parent; + delete[] tkeys; + for ( int i=0; imat_index == mat_index && mat->sub_flag ) + count ++; + } + return count ; +} + + +static aseMaterial* find_material( u32 mat_index, u32 sub_index ) +{ + u32 i; + + //find sub-material + for ( i=0; imat_index == mat_index && mat->sub_index == sub_index ) + return(mat); + } + + //just match material # + for ( i=0; imat_index == mat_index ) + return(mat); + } + + parser.error("unknown material #%d",mat_index); + return(0); +} + + +static ssgSimpleState* make_state( aseMaterial* mat, bool prelit ) +{ + if ( mat -> tfname != NULL) + { + ssgSimpleState *st = current_options -> createSimpleState ( mat -> tfname ) ; + if ( st != NULL ) + return st ; + } + + ssgSimpleState *st = new ssgSimpleState () ; + + bool has_alpha = false ; + + if (mat -> tfname != NULL) + { + ssgTexture* tex = current_options -> createTexture ( mat->tfname ) ; + has_alpha = tex -> hasAlpha () ; + + st -> setTexture ( tex ) ; + st -> enable ( GL_TEXTURE_2D ) ; + } + else + { + st -> disable( GL_TEXTURE_2D ) ; + } + + st -> disable ( GL_ALPHA_TEST ) ; + + if ( sgCompareFloat ( mat -> transparency, 0.0f, 0.01f ) > 0 || has_alpha ) + { + st -> enable ( GL_BLEND ) ; + st -> setTranslucent () ; + } + else + { + st -> disable ( GL_BLEND ) ; + st -> setOpaque () ; + } + + if ( prelit ) + { + st -> disable ( GL_LIGHTING ) ; + } + else + { + st -> setMaterial ( GL_AMBIENT, mat -> amb ) ; + st -> setMaterial ( GL_DIFFUSE, mat -> diff ) ; + st -> setMaterial ( GL_SPECULAR, mat -> spec ) ; + st -> setShininess ( mat -> shine ) ; + st -> disable ( GL_COLOR_MATERIAL ) ; + st -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + st -> enable ( GL_LIGHTING ) ; + } + + st -> setShadeModel ( GL_SMOOTH ) ; + + return st ; +} + + +static ssgSimpleState* get_state( aseMaterial* mat, bool prelit ) +{ + // is material an ifl (image file list) +#ifdef UL_WIN32 + if ( strnicmp ( "ifl_", mat -> name, 4 ) == 0 ) +#else + if ( strncasecmp ( "ifl_", mat -> name, 4 ) == 0 ) +#endif + { + u32 num_subs = count_sub_materials ( mat -> mat_index ); + if ( num_subs < 2 ) + parser.error("ifl material only has <2 frames: %s",mat -> name); + + ssgStateSelector* selector = new ssgStateSelector ( num_subs ) ; + for ( u32 i=0; i mat_index, i ) ; + assert ( mat2 != NULL ) ; + + ssgSimpleState* st = make_state ( mat2, prelit ) ; + selector -> setStep ( i, st ) ; + } + selector -> selectStep ( 0 ) ; + return selector ; + } + return make_state ( mat, prelit ) ; +} + + +static int parse_map( aseMaterial* mat ) +// return TRUE on success +{ + char* token; + int startLevel = parser.level; + while ((token = parser.getLine( startLevel )) != NULL) + { + if (!strcmp(token,"*BITMAP")) + { + if ( mat->tfname != NULL ) + parser.error("multiple textures for material: %s",mat->name); + else + { + char* fname; + if (! parser.parseString(fname, "bitmap filename") ) + return FALSE; + + //strip existing directory from fname + char* slash = strrchr ( fname, '/' ) ; + if ( !slash ) + slash = strrchr ( fname, '\\' ) ; //for dos + if ( slash ) + fname = slash + 1 ; + + mat->tfname = ulStrDup ( fname ) ; + } + } + else if (!strcmp(token,"*UVW_U_TILING")) + { + if (! parser.parseFloat(mat->texrep[0], "tiling.u")) + return FALSE; + } + else if (!strcmp(token,"*UVW_V_TILING")) + { + if (! parser.parseFloat(mat->texrep[1], "tiling.v")) + return FALSE; + } + else if (!strcmp(token,"*UVW_U_OFFSET")) + { + if (! parser.parseFloat(mat->texoff[0] , "offset.u")) + return FALSE; + } + else if (!strcmp(token,"*UVW_V_OFFSET")) + { + if (! parser.parseFloat(mat->texoff[1] , "offset.v")) + return FALSE; + } + } + return TRUE; +} + + +static int parse_material( u32 mat_index, u32 sub_index, cchar* mat_name ) +// return TRUE on success +{ + if ( num_materials >= MAX_MATERIALS ) + { + parser.error( "too many materials" ); + + // skip material definition + int startLevel = parser.level; + while (parser.getLine( startLevel ) != NULL) + ; + return TRUE; // go on parsing + } + aseMaterial* mat = new aseMaterial; + materials [ num_materials++ ] = mat ; + + memset ( mat, 0, sizeof(aseMaterial) ) ; + mat->mat_index = mat_index ; + mat->sub_index = sub_index ; + mat->sub_flag = ( mat_name != 0 ) ; + mat->texrep[0] = 1.0f ; + mat->texrep[1] = 1.0f ; + mat->texoff[0] = 0.0f ; + mat->texoff[1] = 0.0f ; + + char* token; + int startLevel = parser.level; + while ((token = parser.getLine( startLevel )) != NULL) + { + if (!strcmp(token,"*MATERIAL_NAME")) + { + char* name; + if (! parser.parseString(name, "mat name") ) + return FALSE; + + if ( mat->sub_flag ) + { + char buff [ 256 ] ; + sprintf( buff, "%s, sub#%d", mat_name, sub_index ); + + mat->name = ulStrDup ( buff ) ; + } + else + mat->name = ulStrDup ( name ) ; + } + else if (!strcmp(token,"*MATERIAL_AMBIENT")) + { + if (! parser.parseFloat(mat->amb[ 0 ], "amb.r")) + return FALSE; + if (! parser.parseFloat(mat->amb[ 1 ], "amb.g")) + return FALSE; + if (! parser.parseFloat(mat->amb[ 2 ], "amb.b")) + return FALSE; + mat->amb[ 3 ] = 1.0f; + } + else if (!strcmp(token,"*MATERIAL_DIFFUSE")) + { + if (! parser.parseFloat(mat->diff[ 0 ], "diff.r")) + return FALSE; + if (! parser.parseFloat(mat->diff[ 1 ], "diff.g")) + return FALSE; + if (! parser.parseFloat(mat->diff[ 2 ], "diff.b")) + return FALSE; + mat->diff[ 3 ] = 1.0f; + } + else if (!strcmp(token,"*MATERIAL_SPECULAR")) + { + if (! parser.parseFloat(mat->spec[ 0 ], "spec.r")) + return FALSE; + if (! parser.parseFloat(mat->spec[ 1 ], "spec.g")) + return FALSE; + if (! parser.parseFloat(mat->spec[ 2 ], "spec.b")) + return FALSE; + mat->spec[ 3 ] = 1.0f; + } + else if (!strcmp(token,"*MATERIAL_SHINE")) + { + if (! parser.parseFloat(mat->shine, "shine")) + return FALSE; + + // SAC: Shine seems off. If I load a 3ds of the same shape + // the shine is 256x as much and works better, so I'll tweak + // the val here :) I couldn't clarify the range used by + // MAX SDK anywhere in the docs (though this assumes 0 - 0.5). + // OpenGL is 0-128. + mat->shine = mat->shine * 256.0f; + if ( mat->shine > 128 ) + mat->shine = 128; + } + else if (!strcmp(token,"*MATERIAL_TRANSPARENCY")) + { + if (! parser.parseFloat(mat->transparency, "transparency")) + return FALSE; + } + else if (!strcmp(token,"*MAP_DIFFUSE")) + { + //Need: what about MAP_GENERIC, MAP_AMBIENT, etc?? + if (! parse_map( mat )) + return FALSE; + } + else if (!strcmp(token,"*SUBMATERIAL")) + { + u32 sub_index; + if (! parser.parseUInt(sub_index, "sub mat #")) + return FALSE; + if (! parse_material( mat_index, sub_index, mat->name )) + return FALSE; + } + } + + //parser.message("material: %s (%s)",mat->name,mat->tfname); + return TRUE; +} + + +static int parse_material_list() +// return TRUE on success +{ + if ( num_materials ) + parser.error("multiple material lists"); + + char* token; + int startLevel = parser.level; + while ((token = parser.getLine( startLevel )) != NULL) + { + if (!strcmp(token,"*MATERIAL")) + { + u32 mat_index; + if (! parser.parseUInt(mat_index, "mat #")) + return FALSE; + if (! parse_material( mat_index, 9999, NULL )) + return FALSE; + } + } + return TRUE; +} + + +static int parse_mesh( aseObject* obj ) +{ + aseMesh* mesh = NULL ; + u32 mesh_face_normal_index = 0x7fffffff; + u32 mesh_face_normal_count = 0; + + char* token; + int startLevel = parser.level; + while ((token = parser.getLine( startLevel )) != NULL) + { + if ( mesh == NULL ) + { + u32 frame = aseObject::MAX_FRAMES ; + + if (!strcmp(token,"*TIMEVALUE")) + { + u32 time; + if (! parser.parseUInt(time, "time")) + return FALSE; + frame = (time + (ticks_per_frame-1)) / ticks_per_frame - first_frame; + } + else + { + parser.error("missing *TIMEVALUE"); + frame = aseObject::MAX_FRAMES ; + } + + if ( frame >= aseObject::MAX_FRAMES || obj->mesh_list [ frame ] != NULL ) + { + //ignore this mesh + while (parser.getLine( startLevel )) ; + return TRUE; // go on parsing + } + + mesh = new aseMesh ; + obj->mesh_list [ frame ] = mesh ; + obj->mesh_count ++ ; + } + else if (!strcmp(token,"*MESH_NUMFACES")) + { + if (mesh -> faces) + parser.error("%s already seen",token); + else + { + if (! parser.parseUInt(mesh -> num_faces, "num_faces")) + return FALSE; + mesh -> faces = new aseFace[ mesh -> num_faces ]; + + // SAC: Help clear all the has_vertex_normals flags + memset ( mesh -> faces, 0, mesh -> num_faces * sizeof (aseFace) ); + } + } + else if (!strcmp(token,"*MESH_NUMTVFACES")) + { + u32 ntfaces; + if (! parser.parseUInt(ntfaces, "ntfaces")) + return FALSE; + if (ntfaces != mesh -> num_faces) + parser.error("NUMTFACES(%d) != NUMFACES(%d)",ntfaces,mesh -> num_faces); + } + else if (!strcmp(token,"*MESH_NUMCVFACES")) + { + u32 ncfaces; + if (! parser.parseUInt(ncfaces, "ncfaces")) + return FALSE; + if (ncfaces != mesh -> num_faces) + parser.error("NUMCFACES(%d) != NUMFACES(%d)",ncfaces,mesh -> num_faces); + } + else if (!strcmp(token,"*MESH_NUMVERTEX")) + { + if (mesh -> verts) + parser.error("%s already seen",token); + else + { + if (! parser.parseUInt(mesh -> num_verts, "num_verts")) + return FALSE; + mesh -> verts = new sgVec3[ mesh -> num_verts ]; + } + } + else if (!strcmp(token,"*MESH_NUMTVERTEX")) + { + if (mesh -> tverts) + parser.error("%s already seen",token); + else + { + if (! parser.parseUInt(mesh -> num_tverts, "num_tverts")) + return FALSE; + if (mesh -> num_tverts) + mesh -> tverts = new sgVec2[ mesh -> num_tverts ]; + } + } + else if (!strcmp(token,"*MESH_NUMCVERTEX")) + { + if (mesh -> cverts) + parser.error("%s already seen",token); + else + { + if (! parser.parseUInt(mesh -> num_cverts, "num_cverts")) + return FALSE; + if (mesh -> num_cverts) + mesh -> cverts = new sgVec3[ mesh -> num_cverts ]; + } + } + else if (!strcmp(token,"*MESH_FACE")) + { + u32 index; + // wk: The old parseInt converted a "3:" into 3, + // the new would give an error. Therefore I had to change this code: + char *my_endptr, *my_token = parser.parseToken("face #"); + if (my_token[strlen(my_token)-1]==':') + my_token[strlen(my_token)-1]=0; + + index = (unsigned int)(strtol( my_token, &my_endptr, 10)); + if ( (my_endptr != NULL) && (*my_endptr != 0)) + { parser.error("The field face # should contain an integer number but contains %s", my_token) ; + return FALSE; + } + + + if (index >= mesh -> num_faces) + parser.error("bad face #"); + else + { + aseFace& face = mesh -> faces[ index ]; + + parser.expect("A:"); + if (! parser.parseUInt(face.v[0], "face.v[0]")) + return FALSE; + parser.expect("B:"); + if (! parser.parseUInt(face.v[1], "face.v[1]")) + return FALSE; + parser.expect("C:"); + if (! parser.parseUInt(face.v[2], "face.v[2]")) + return FALSE; + + //search for other flags + token = parser.parseToken(0); + while ( ! parser.eol ) + { + if ( strcmp(token,"*MESH_MTLID") == 0 ) + { + if (! parser.parseUInt(face.sub_index, "mat #")) + return FALSE; + } + token = parser.parseToken(0); + } + } + } + else if (!strcmp(token,"*MESH_TFACE")) + { + u32 index; + if (! parser.parseUInt(index, "tface #")) + return FALSE; + if (index >= mesh -> num_faces) + parser.error("bad tface #"); + else + { + aseFace& face = mesh -> faces[ index ]; + + if (! parser.parseUInt(face.tv[0], "tface.tv[0]")) + return FALSE; + if (! parser.parseUInt(face.tv[1], "tface.tv[1]")) + return FALSE; + if (! parser.parseUInt(face.tv[2], "tface.tv[2]")) + return FALSE; + } + } + else if (!strcmp(token,"*MESH_CFACE")) + { + u32 index; + if (! parser.parseUInt(index, "cface #")) + return FALSE; + if (index >= mesh -> num_faces) + parser.error("bad cface #"); + else + { + aseFace& face = mesh -> faces[ index ]; + + if (! parser.parseUInt(face.cv[0], "tface.cv[0]")) + return FALSE; + if (! parser.parseUInt(face.cv[1], "tface.cv[1]")) + return FALSE; + if (! parser.parseUInt(face.cv[2], "tface.cv[2]")) + return FALSE; + } + } + // SAC: START OF VERTEX NORMAL PARSING SECTION + // NOTE: Assumes that three correctly-ordered *MESH_VERTEXNORMAL lines + // come after each *MESH_FACENORMAL line. Which seems to be the case + // in current exporter + else if (!strcmp(token,"*MESH_FACENORMAL")) + { + if (! parser.parseUInt(mesh_face_normal_index, "face normal #")) + return FALSE; + mesh_face_normal_count = 0; + } + else if (!strcmp(token,"*MESH_VERTEXNORMAL")) + { + //int nverts = mesh -> num_verts; + + if ( mesh_face_normal_index >= mesh -> num_faces ) + parser.error("bad mesh_face_normal_index #"); + if ( mesh_face_normal_count >= 3 ) + parser.error("bad mesh_face_normal_count"); + + aseFace& face = mesh -> faces[ mesh_face_normal_index ]; + sgVec3& vn = face . vn [ mesh_face_normal_count ]; + face.has_vertex_normals = true; + u32 vertex_index; + if (! parser.parseUInt(vertex_index, "vertex normal #")) + return FALSE; + if ( face.v [mesh_face_normal_count] != vertex_index ) + parser.error("bad MESH_VERTEXNORMAL entries out of order!"); + if (! parser.parseFloat(vn[0], "vertexNormal.x")) + return FALSE; + if (! parser.parseFloat(vn[1], "vertexNormal.y")) + return FALSE; + if (! parser.parseFloat(vn[2], "vertexNormal.z")) + return FALSE; + + // sgNormaliseVec3 ( vn ) ; + mesh_face_normal_count++; + } + // SAC: END OF VERTEX NORMAL PARSING SECTION + else if (!strcmp(token,"*MESH_VERTEX")) + { + u32 index; + if (! parser.parseUInt(index, "vertex #")) + return FALSE; + if (index >= mesh -> num_verts) + parser.error("bad vertex #"); + else + { + sgVec3& vert = mesh -> verts[ index ]; + + if (! parser.parseFloat(vert[0], "vert.x")) + return FALSE; + if (! parser.parseFloat(vert[1], "vert.y")) + return FALSE; + if (! parser.parseFloat(vert[2], "vert.z")) + return FALSE; + } + } + else if (!strcmp(token,"*MESH_TVERT")) + { + u32 index; + if (! parser.parseUInt(index, "tvertex #")) + return FALSE; + if (index >= mesh -> num_tverts) + parser.error("bad tvertex #"); + else + { + sgVec2& tvert = mesh -> tverts[ index ]; + + if (! parser.parseFloat(tvert[0], "tvert.x")) + return FALSE; + if (! parser.parseFloat(tvert[1], "tvert.y")) + return FALSE; + } + } + else if (!strcmp(token,"*MESH_VERTCOL")) + { + u32 index; + if (! parser.parseUInt(index, "cvertex #")) + return FALSE; + if (index >= mesh -> num_cverts) + parser.error("bad cvertex #"); + else + { + sgVec3& cvert = mesh -> cverts[ index ]; + + if (! parser.parseFloat(cvert[0], "cvert.x")) + return FALSE; + if (! parser.parseFloat(cvert[1], "cvert.y")) + return FALSE; + if (! parser.parseFloat(cvert[2], "cvert.z")) + return FALSE; + } + } + } + return TRUE; +} + + +static void get_texcoord ( aseMaterial* mat, sgVec2 tv ) +{ + //invert Y coordinate + tv[1] = 1.0f - tv[1] ; + + tv[0] *= mat->texrep[0] ; + tv[1] *= mat->texrep[1] ; + tv[0] += mat->texoff[0] ; + tv[1] += mat->texoff[1] ; +} + + +static ssgLeaf* add_points( aseObject* obj, aseMesh* mesh ) +{ + ssgVertexArray* vl = NULL ; + + if ( obj->type == aseObject::CAMERA ) + { + /* compute a normalized target vector */ + sgVec3 target ; + sgCopyVec3 ( target, obj->target ) ; + sgSubVec3 ( target, obj->pos ) ; + + SGfloat len = sgLengthVec3 ( target ) ; + if ( len == SG_ZERO ) + { + vl = new ssgVertexArray ( 1 ) ; + vl -> add ( obj->pos ) ; + } + else + { + vl = new ssgVertexArray ( 2 ) ; + + sgNormaliseVec3 ( target ) ; + sgAddVec3 ( target, obj->pos ) ; + + vl -> add ( obj->pos ) ; + vl -> add ( target ) ; + } + } + else if ( mesh != NULL ) + { + u32 num_verts = mesh -> num_verts ; + if ( num_verts == 0 ) + return NULL; + + vl = new ssgVertexArray ( num_verts ) ; + + //pass the data to ssg + sgVec3* vert = mesh -> verts ; + for ( u32 i=0; i < num_verts; i++, vert++ ) + vl -> add ( *vert ) ; + } + else + { + return NULL ; + } + + ssgVtxTable* leaf = new ssgVtxTable ( GL_POINTS, + vl, NULL, NULL, NULL ) ; + + if ( leaf != NULL ) + { + // leaves with no faces are used for game logic + // and should not be culled and rendered + leaf -> clrTraversalMaskBits ( SSGTRAV_CULL ) ; + } + + return ssgGetCurrentOptions () -> createLeaf ( leaf, obj -> name ) ; +} + + +static ssgLeaf* add_mesh( aseObject* obj, aseMesh* mesh, u32 sub_index ) +{ + u32 i ; + + aseMaterial* mat = find_material ( obj->mat_index, sub_index ) ; + if ( mat == NULL ) + return NULL ; + + //compute number of faces for this sub-material + u32 num_faces = mesh -> num_faces ; + if ( mat->sub_flag ) + { + num_faces = 0 ; + aseFace* face = mesh -> faces ; + for ( i=0; i num_faces; i++, face++ ) + { + if ( face->sub_index == mat->sub_index ) + num_faces ++ ; + } + } + if ( num_faces == 0 ) + return NULL ; + + if ( mesh -> cverts == NULL ) + { + u32 num_verts = num_faces * 3 ; + + //pass the data to ssg + ssgSimpleState* st = get_state ( mat, false ) ; + ssgColourArray* cl = new ssgColourArray ( 1 ) ; + ssgVertexArray* vl = new ssgVertexArray ( num_verts ) ; + ssgNormalArray* nl = new ssgNormalArray ( num_verts ) ; + ssgTexCoordArray* tl = 0 ; + if ( mesh -> tverts ) + tl = new ssgTexCoordArray ( num_verts ) ; + + //set the material colour + sgVec4 c ; + sgCopyVec3 ( c, mat -> diff ) ; + c[3] = 1.0f - mat -> transparency ; + cl -> add ( c ) ; + + aseFace* face = mesh -> faces ; + for ( i=0; i num_faces; i++, face++ ) + { + if ( mat->sub_flag && face->sub_index != mat->sub_index ) + continue ; + + sgVec3 n ; + sgMakeNormal ( n, + mesh -> verts[ face->v[0] ] , + mesh -> verts[ face->v[1] ] , + mesh -> verts[ face->v[2] ] ) ; + + for ( u32 j=0; j<3; j++ ) + { + vl -> add ( mesh -> verts[ face->v[j] ] ) ; + + // SAC: If per-vertex normals were found, use 'em. + // Else use the face normal computed above + if ( face -> has_vertex_normals ) + nl -> add ( face->vn [j] ) ; + else + nl -> add ( n ) ; + + if ( mesh -> tverts ) + { + sgVec2 tv ; + sgCopyVec2 ( tv, mesh -> tverts[ face->tv[j] ] ) ; + get_texcoord ( mat, tv ) ; + tl -> add ( tv ) ; + } + } + } + + ssgVtxTable* leaf = new ssgVtxTable ( GL_TRIANGLES, + vl, nl, tl, cl ) ; + leaf -> setCullFace ( TRUE ) ; + leaf -> setState ( st ) ; + return current_options -> createLeaf ( leaf, obj->name ) ; + } + + //allocate map_index array + int* map_index = new int [ mesh -> num_faces * 3 ] ; + + //allocate the vertex list + u32 max_verts = mesh -> num_verts + mesh -> num_faces * 3 ; + aseVertexBuffer* vert_list = new aseVertexBuffer [ max_verts ] ; + + //mark each vertex as *not* used + aseVertexBuffer* vert = vert_list ; + for ( i=0; i < max_verts; i++, vert++ ) + { + vert -> use_flag = false ; + } + + u32 extra_verts = 0 ; + + //build the vertex list + aseFace* face = mesh -> faces ; + for ( i=0; i num_faces; i++, face++ ) + { + if ( mat->sub_flag && face->sub_index != mat->sub_index ) + continue ; + + for ( u32 j=0; j<3; j++ ) + { + int k = i*3+j; + + map_index [k] = face->v[j] ; + vert = vert_list + map_index[k]; + + if ( vert -> use_flag ) + { + //check for match + bool match = true ; + if ( mesh -> tverts && + sgCompareVec2 ( vert -> tv, mesh -> tverts[ face->tv[j] ], 0.0f ) != 0 ) + match = false ; + else if ( mesh -> cverts && + sgCompareVec3 ( vert -> cv, mesh -> cverts[ face->cv[j] ], 0.0f ) != 0 ) + match = false ; + if ( match ) + continue ; //texcoord and color matches other vertex + + extra_verts ++ ; + + map_index [k] = mesh -> num_verts + k ; + vert = vert_list + map_index[k]; + } + + //add the vertex + vert -> use_flag = true; + sgCopyVec3 ( vert -> v, mesh -> verts[ face->v[j] ] ) ; + if ( mesh -> tverts ) + sgCopyVec2 ( vert -> tv, mesh -> tverts[ face->tv[j] ] ) ; + if ( mesh -> cverts ) + sgCopyVec3 ( vert -> cv, mesh -> cverts[ face->cv[j] ] ) ; + } + } + + //assign a unique index to each vertex + int num_verts = 0 ; + vert = vert_list; + for ( i=0; i < max_verts; i++, vert++ ) + { + if ( vert -> use_flag ) + vert -> index = num_verts ++; + } + + //if ( extra_verts > 0 ) + // ulSetError( UL_DEBUG, "%d verts; %d added", num_verts-extra_verts, extra_verts ); + //else + // ulSetError( UL_DEBUG, "%d verts", num_verts ); + + //pass the data to ssg + ssgSimpleState* st = get_state ( mat, ( mesh -> cverts != NULL ) ) ; + ssgIndexArray* il = new ssgIndexArray ( num_faces * 3 ) ; + ssgVertexArray* vl = new ssgVertexArray ( num_verts ) ; + ssgTexCoordArray* tl = 0 ; + ssgColourArray* cl = 0 ; + if ( mesh -> tverts ) + tl = new ssgTexCoordArray ( num_verts ) ; + if ( mesh -> cverts ) + cl = new ssgColourArray ( num_verts ) ; + + //build the index list + face = mesh -> faces ; + for ( i=0; i num_faces; i++, face++ ) + { + if ( mat->sub_flag && face->sub_index != mat->sub_index ) + continue ; + + for ( u32 j=0; j<3; j++ ) + { + int k = i*3+j; + vert = vert_list + map_index[k]; + + if ( ! vert -> use_flag ) + ulSetError ( UL_FATAL, "internal error" ) ; + + il -> add ( vert -> index ) ; + } + } + + //copy the vertex lists + vert = vert_list; + for ( i=0; i < max_verts; i++, vert++ ) + { + if ( vert -> use_flag ) + { + vl -> add ( vert -> v ) ; + + if ( mesh -> tverts ) + { + sgVec2 tv ; + sgCopyVec2 ( tv, vert -> tv ) ; + get_texcoord ( mat, tv ) ; + tl -> add ( tv ) ; + } + + if ( mesh -> cverts ) + { + sgVec4 c ; + sgCopyVec3 ( c, vert -> cv ) ; + c[3] = 1.0f - mat -> transparency ; + + cl -> add ( c ) ; + } + } + } + + delete[] vert_list ; + delete[] map_index ; + + ssgVtxArray* leaf = new ssgVtxArray ( GL_TRIANGLES, + vl, NULL, tl, cl, il ) ; + leaf -> setCullFace ( TRUE ) ; + leaf -> setState ( st ) ; + return current_options -> createLeaf ( leaf, obj -> name ) ; +} + + +static aseTransform* get_tkey( aseObject* obj, u32 time ) +{ + if ( obj->tkeys == NULL ) + { + obj->num_tkeys = 0; + obj->tkeys = new aseTransform [ num_frames ] ; + + //initialize + aseTransform* tkey = obj->tkeys ; + for ( u32 i=0; ipos, 0, 0, 0 ) ; + sgSetVec3 ( tkey->axis, 0, 0, 1 ) ; + tkey->angle = 0.0f ; + sgSetVec3 ( tkey->scale, 1, 1, 1 ) ; + } + } + + //compute frame number + u32 frame = time / ticks_per_frame - first_frame; + if ((time % ticks_per_frame) != 0 || frame >= num_frames) + parser.error("bad time"); + + if ( frame+1 > obj->num_tkeys ) + obj->num_tkeys = frame+1; + + return( &obj->tkeys[ frame ] ); +} + +#define MAX_TKEY_PER_MESH 256 + +static int parse_tkeys( aseObject* obj ) +{ + bool match = false ; + void *tkeys[MAX_TKEY_PER_MESH]; + int num_tkeys=0; + char* token; + int startLevel = parser.level; + while ((token = parser.getLine( startLevel )) != NULL) + { + if (!strcmp(token,"*NODE_NAME")) + { + char* name; + if (! parser.parseString(name, "obj name")) + return FALSE; + if ( obj->name && !strcmp(name,obj->name) ) + match = true ; + } + else if (match) + { + if (!strcmp(token,"*CONTROL_POS_SAMPLE")) + { + u32 time; + if (! parser.parseUInt(time, "time")) + return FALSE; + aseTransform* tkey = get_tkey( obj, time ); + + if (! parser.parseFloat(tkey->pos[0], "pos.x")) + return FALSE; + if (! parser.parseFloat(tkey->pos[1], "pos.y")) + return FALSE; + if (! parser.parseFloat(tkey->pos[2], "pos.z")) + return FALSE; + + if ( obj->parent == NULL ) + { + sgSubVec3 ( tkey->pos, obj->pos ) ; + } + else + { + for ( int i=0; i<3; i++ ) + { + if ( obj->inherit_pos[i] ) + tkey->pos[i] -= obj->pos[i] ; + } + } + + //copy the position forward + for ( u32 i=obj->num_tkeys; itkeys[ i ].pos, tkey->pos ) ; + } + else if (!strcmp(token,"*CONTROL_ROT_SAMPLE")) + { + u32 time; + if (!parser.parseUInt(time, "time")) + return FALSE; + aseTransform* tkey = get_tkey( obj, time ); + + if (! parser.parseFloat(tkey->axis[0], "axis.x")) + return FALSE; + if (! parser.parseFloat(tkey->axis[1], "axis.y")) + return FALSE; + if (! parser.parseFloat(tkey->axis[2], "axis.z")) + return FALSE; + if (! parser.parseFloat(tkey->angle, "angle")) + return FALSE; + } + else if (!strcmp(token,"*CONTROL_TCB_ROT_KEY")) + { + u32 time; + if (!parser.parseUInt(time, "time")) + return FALSE; + aseTransform* tkey = new aseTransform; + tkeys[num_tkeys++] = tkey; + assert(num_tkeys < MAX_TKEY_PER_MESH); + sgSetVec3 ( tkey->pos, 0, 0, 0 ) ; // "TCB": only rotation allowed :-/ + sgSetVec3 ( tkey->axis, 0, 0, 1 ) ; + tkey->angle = 0.0f ; + sgSetVec3 ( tkey->scale, 1, 1, 1 ) ; + +// *CONTROL_TCB_ROT_KEY 160 -0.9949 -0.0914 0.0434 3.1336 0.0000 0.0000 0.0000 0.0000 0.0000 + if (! parser.parseFloat(tkey->axis[0], "axis.x")) + return FALSE; + if (! parser.parseFloat(tkey->axis[1], "axis.y")) + return FALSE; + if (! parser.parseFloat(tkey->axis[2], "axis.z")) + return FALSE; + if (! parser.parseFloat(tkey->angle, "angle")) + return FALSE; + float dummy; + if (! parser.parseFloat(dummy, "tens")) + return FALSE; + if (! parser.parseFloat(dummy, "cont")) + return FALSE; + if (! parser.parseFloat(dummy, "bias")) + return FALSE; + if (! parser.parseFloat(dummy, "easeIn")) + return FALSE; + if (! parser.parseFloat(dummy, "easeOut")) + return FALSE; + } + else if (!strcmp(token,"*CONTROL_SCALE_SAMPLE")) + { + u32 time; + if (! parser.parseUInt(time, "time")) + return FALSE; + aseTransform* tkey = get_tkey( obj, time ); + + if (! parser.parseFloat(tkey->scale[0], "scale.x")) + return FALSE; + if (! parser.parseFloat(tkey->scale[1], "scale.y")) + return FALSE; + if (! parser.parseFloat(tkey->scale[2], "scale.z")) + return FALSE; + } + } + } + if(num_tkeys) + { + obj->num_tkeys = num_tkeys; + obj->tkeys = new aseTransform [ num_tkeys ] ; + for(int i=0; itkeys[i] = *((aseTransform *)tkeys[i]); + } + return TRUE; +} + + +static int parse_object( aseObject::Type type ) +{ + aseObject* obj = new aseObject ( type ) ; + + char* token; + int startLevel = parser.level; + while ((token = parser.getLine( startLevel )) != NULL) + { + if (!strcmp(token,"*NODE_NAME")) + { + if ( !obj->name ) + { + char* name; + if (! parser.parseString(name, "obj name")) + return FALSE; + + + obj->name = ulStrDup ( name ) ; + } + } + else if (!strcmp(token,"*NODE_PARENT")) + { + if ( !obj->parent ) + { + char* name; + if (! parser.parseString(name, "parent name")) + return FALSE; + + + obj->parent = ulStrDup ( name ) ; + } + } + else if (!strcmp(token,"*NODE_TM")) + { + bool target = false ; + bool match = false ; + int startLevel = parser.level; + while ((token = parser.getLine( startLevel )) != NULL) + { + if (!strcmp(token,"*NODE_NAME")) + { + char* name; + if (! parser.parseString(name, "obj name")) + return FALSE; + if ( obj->name && !strcmp(name,obj->name) ) + match = true ; + if ( strstr(name,".Target") != NULL ) + target = true ; + } + else if (match) + { + if (!strcmp(token,"*TM_POS")) + { + if (! parser.parseFloat(obj->pos[0], "pos.x")) + return FALSE; + if (! parser.parseFloat(obj->pos[1], "pos.y")) + return FALSE; + if (! parser.parseFloat(obj->pos[2], "pos.z")) + return FALSE; + sgCopyVec3 ( obj->target, obj->pos ) ; + } + else if (!strcmp(token,"*INHERIT_POS")) + { + int temp ; + if (! parser.parseInt(temp, "inherit_pos.x")) + return FALSE; + obj->inherit_pos[0] = ( temp != 0 ) ; + if (! parser.parseInt(temp, "inherit_pos.y")) + return FALSE; + obj->inherit_pos[1] = ( temp != 0 ) ; + if (! parser.parseInt(temp, "inherit_pos.z")) + return FALSE; + obj->inherit_pos[2] = ( temp != 0 ) ; + } + } + else if (target) + { + if (!strcmp(token,"*TM_POS")) + { + if (! parser.parseFloat(obj->target[0], "pos.x")) + return FALSE; + if (! parser.parseFloat(obj->target[1], "pos.y")) + return FALSE; + if (! parser.parseFloat(obj->target[2], "pos.z")) + return FALSE; + } + } + } + } + else if (!strcmp(token,"*MESH")) + { + if (! parse_mesh( obj )) + return FALSE; + } + else if (!strcmp(token,"*MESH_ANIMATION")) + { + int startLevel = parser.level; + while ((token = parser.getLine( startLevel )) != NULL) + { + if (!strcmp(token,"*MESH")) + { + if (! parse_mesh( obj )) + return FALSE; + } + } + } + else if (!strcmp(token,"*TM_ANIMATION")) + { + if (! parse_tkeys( obj )) + return FALSE; + } + else if (!strcmp(token,"*MATERIAL_REF")) + { + if (! parser.parseUInt(obj->mat_index, "mat #")) + return FALSE; + } + } + + //if ( obj->parent != NULL ) + // ulSetError( UL_DEBUG, "add_mesh: %s, parent=%s", obj->name, obj->parent ) ; + //else + // ulSetError( UL_DEBUG, "add_mesh: %s", obj->name ) ; + + ssgEntity* mesh_entity = NULL ; + + if ( obj->mesh_count > 1 ) + { + //how many frames? + int num_frames = 0 ; + int i ; + for ( i=0; imesh_list [ i ] ; + if ( mesh != NULL ) + num_frames ++ ; + } + + //allocate selector + ssgSelector* selector = new ssgSelector ( num_frames ) ; + + //init + for ( i=0; imesh_list [ i ] ; + if ( mesh == NULL ) + continue ; + + u32 num_subs = count_sub_materials ( obj->mat_index ); + if ( num_subs > 1 ) + { + //break apart the mesh for each sub material + ssgBranch* branch = new ssgBranch ; + for ( u32 sub_index=0; sub_index addKid ( leaf ) ; + } + selector -> addKid ( branch ) ; + } + else + { + ssgLeaf* leaf = add_mesh ( obj, mesh, 0 ) ; + if ( leaf ) + selector -> addKid ( leaf ) ; + } + } + + selector -> selectStep ( 0 ) ; + mesh_entity = current_options -> createSelector ( selector ) ; + } + else if ( obj->mesh_list [ 0 ] != NULL ) + { + aseMesh* mesh = obj->mesh_list [ 0 ] ; + ssgBranch* branch = new ssgBranch ; + + u32 num_faces = mesh -> num_faces ; + if ( num_faces == 0 ) + { + ssgLeaf* leaf = add_points( obj, mesh ) ; + if ( leaf ) + branch -> addKid ( leaf ) ; + } + else + { + u32 num_subs = count_sub_materials ( obj->mat_index ); + if ( num_subs > 1 ) + { + //break apart the mesh for each sub material + for ( u32 sub_index=0; sub_index addKid ( leaf ) ; + } + } + else + { + ssgLeaf* leaf = add_mesh ( obj, mesh, 0 ); + if ( leaf ) + branch -> addKid ( leaf ) ; + } + } + + mesh_entity = branch ; + } + else + { + ssgBranch* branch = new ssgBranch ; + ssgLeaf* leaf = add_points( obj, NULL ) ; + if ( leaf ) + branch -> addKid ( leaf ) ; + mesh_entity = branch ; + } + + if ( mesh_entity != NULL ) + { + //add to graph -- find parent branch + ssgBranch* parent_branch ; + if ( obj->parent ) + { + ssgEntity* found = top_branch -> getByName ( obj->parent ) ; + if ( found != NULL ) + { + assert ( found -> isAKindOf ( ssgTypeBranch() ) ) ; + parent_branch = (ssgBranch *) found ; + } + else + { + //parser.error("object %s: parent %s not seen",obj->name,obj->parent); + parent_branch = top_branch ; + } + } + else + { + parent_branch = top_branch ; + } + + if ( obj->num_tkeys > 0 ) + { + ssgAnimTransform * at = new ssgAnimTransform; + at->setNum( obj->num_tkeys ); + + /* + Build the transforms + */ + sgMat4 rmat; + sgMakeIdentMat4 ( rmat ) ; + at->setATransform ( rmat, 0); + + for ( u32 i = 1 ; i < obj->num_tkeys ; i++ ) + { + aseTransform* tkey = obj->tkeys + i ; + + sgVec3 pos ; + sgMat4 tmp ; + sgMat4 mat ; + + /* + * compute rmat + * the key rotation is additive to the last rotation + */ + sgMakeRotMat4 ( tmp, -tkey->angle * SG_RADIANS_TO_DEGREES, tkey->axis ) ; + sgPostMultMat4 ( rmat, tmp ) ; + + /* + * rotation is around the mesh pivot point (obj->pos) + * translate -obj->pos + */ + sgCopyVec3 ( pos, obj->pos ) ; + sgNegateVec3 ( pos ) ; + sgMakeTransMat4 ( mat, pos ) ; + + /* + * perform the rotation + */ + sgPostMultMat4 ( mat, rmat ) ; + + /* + * translate obj->pos + tkey->pos + */ + sgCopyVec3 ( pos, obj->pos ) ; + sgAddVec3 ( pos, tkey->pos ) ; + sgMakeTransMat4 ( tmp, pos ) ; + sgPostMultMat4 ( mat, tmp ) ; + + at->setATransform ( mat, i); + } + // insert the ssgAnimTransform into the scene graph: + at-> addKid ( mesh_entity ) ; + mesh_entity = at; + } + + parent_branch -> addKid ( mesh_entity ) ; + mesh_entity -> setName ( obj->name ) ; + } + + delete obj ; + return TRUE; +} + + +static bool parse() +{ + materials = new aseMaterial* [ MAX_MATERIALS ]; + if ( !materials ) + { + parser.error("not enough memory"); + return false ; + } + + num_materials = 0 ; + + first_frame = 0 ; + last_frame = 0 ; + frame_speed = 0 ; + ticks_per_frame = 0 ; + num_frames = 0 ; + + bool firsttime = true; + char* token; + int startLevel = parser.level; + while ((token = parser.getLine( startLevel )) != NULL) + { + if (firsttime) + { + if (strcmp(token,"*3DSMAX_ASCIIEXPORT")) + { + parser.error("not ASE format"); + return false ; + } + u32 version_number; + if (! parser.parseUInt(version_number, "version number") ) + return false ; + if ( version_number != 200) + { + parser.error("invalid %s version",token); + return false ; + } + firsttime = false; + } + else if (!strcmp(token,"*SCENE")) + { + int startLevel = parser.level; + while ((token = parser.getLine( startLevel )) != NULL) + { + if (!strcmp(token,"*SCENE_FIRSTFRAME")) + { + if (! parser.parseUInt(first_frame, "FIRSTFRAME #")) + return FALSE; + } + else if (!strcmp(token,"*SCENE_LASTFRAME")) + { + if (! parser.parseUInt(last_frame, "LASTFRAME #")) + return FALSE; + num_frames = last_frame - first_frame + 1; + } + else if (!strcmp(token,"*SCENE_FRAMESPEED")) + { + if (! parser.parseUInt(frame_speed, "FRAMESPEED #")) + return FALSE; + } + else if (!strcmp(token,"*SCENE_TICKSPERFRAME")) + { + if (! parser.parseUInt(ticks_per_frame, "TICKSPERFRAME #")) + return FALSE; + } + } + } + else if (!strcmp(token,"*MATERIAL_LIST")) + { + if (! parse_material_list()) + return FALSE; + } + else if (!strcmp(token,"*GEOMOBJECT")) + { + if (! parse_object( aseObject::GEOM )) + return FALSE; + } + else if (!strcmp(token,"*HELPEROBJECT")) + { + if (! parse_object( aseObject::HELPER )) + return FALSE; + } + else if (!strcmp(token,"*CAMERAOBJECT")) + { + if (! parse_object( aseObject::CAMERA )) + return FALSE; + } + } + return true ; +} + + +static void parse_free() +{ + u32 i ; + for ( i = 0 ; i < num_materials ; i++ ) + { + delete [] materials[ i ] -> name ; + delete [] materials[ i ] -> tfname ; + delete materials[ i ] ; + } + delete[] materials ; + materials = 0 ; +} + + +ssgEntity *ssgLoadASE ( const char *fname, const ssgLoaderOptions* options ) +{ + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + current_options = ssgGetCurrentOptions () ; + + top_branch = new ssgBranch ; + if ( !parser.openFile( fname, &parser_spec ) ) + { + delete top_branch ; + return 0; + } + if ( !parse() ) + { + delete top_branch ; + top_branch = 0 ; + } + parse_free(); + parser.closeFile(); + + return top_branch ; +} diff --git a/src/ssg/ssgLoadATG.cxx b/src/ssg/ssgLoadATG.cxx new file mode 100644 index 0000000..2ebc2ea --- /dev/null +++ b/src/ssg/ssgLoadATG.cxx @@ -0,0 +1,497 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadATG.cxx 1970 2004-10-04 08:11:26Z wolfram_kuss $ +*/ +/* + .scenery loader for SSG/PLIB + ATG = ascii Terra Gear + + Written by Wolfram Kuss (Wolfram.Kuss@t-online.de) in May 2001 + +*/ + +/* +General info on working with FG scenery files: + +If you want to add stuff to the scenery think about adding it via the *.ind files. +Editing the scenery manually is always "dangerous", since your effort is lost the +next time the scenery is re-generated. + +ssgLoadATG and ssgSaveATG are not finished at all and there are some known bugs: +- texture coordinate reading doesn't work 100%, writing is not implemented yet. +- Only faces with "f". TriStrips ("ts") and TriFans ("tf") not yet supported. + +First of all, make sure the FG textures are in your texture path. If +your FG is in, then add +C:/FG/Textures/$(...) +to the string in viewer.setTexturePath in .ppe_rc. +If you run PPE, it will tell you where you .pee_rc is (and create one if you don't have one). + + +As an example, say you want to add a tower to the airport KLVK. +It goes something like this: + +1. Unzip KLVK.gz, you get a file KLVK. +2. delete KLVK.gz or move it away so that it isn't used anymore. +3. Rename KLVK to KLV.atg. PLIB finds out the fileformat via the extension, + so PLIB can't handle files without extension. +4. Go into PPE (or another PLIB based program :-)) and load KLVK.atg. +5. Say "make everything visible". You can look at it from all sides via + the middle mouse button and move the camery via the numKeyPad. For more, see the PPE docu. +6. Now, using some magic like a future PPE-version, add whatever you want to add. + I tried this and by coding a few small functions, have succeeded partly. Some hints: + Pressing "w" gets you into a mode where you can get the 3D coordinates of stuff. + What I want to add is centred around 0,0,0, so writing a small, but non-trivial :-( + translateAllVertices, moved the other object that I load via "merge". The next problem + is that the tile is not axisparalell, so you have to rotate what you loaded a certain way. +7. Save the tile as KLVK.atg +8. From the original KLVK, get the line with "# gbs..." and copy it to KLVK.atg +9. Rename KLVK.atg to KLVK. You can now view it in FG by going to + this airport. The texture coords will be broken (see above). + + + + */ + +#include "ssgLocal.h" +#include "ssgLoaderWriterStuff.h" +#include "ssgParser.h" + + +extern sgVec4 currentDiffuse; + + +static /* const */ ssgLoaderOptions* current_options = NULL ; +static class ssgTexCoordArray *linearListTCPFAV=NULL; // TCPFAV = TextureCoordinatesPerFaceAndVertex + +static _ssgParserSpec parser_spec = +{ + "\r\n\t ", // delim_chars_skipable + NULL, // delim_chars_non_skipable + NULL, // pre_processor + NULL, // open_brace_chars + NULL, // close_brace_chars + '"', // quote_char. not used for scenery + 0, // comment_char # is handled in this module, since it may contain + // important info like the name of the material or the gbs + NULL // comment_string +} ; + + +static _ssgParser parser; +static ssgBranch* top_branch; + +static int Ascii2Int(int &retVal, const char *token, const char* name ) +// returns TRUE on success +{ + char *endptr; + retVal = int(strtol( token, &endptr, 10)); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { parser.error("The field %s should contain an integer number but contains %s",name, token) ; + return FALSE; + } +} + + + +#define MAX_NO_VERTICES_PER_FACE 10000 + +static class ssgLoaderWriterMesh _theMesh; + + + +static int _ssgNoFaces, _ssgNoVertices, _ssgNoVertexNormals, _ssgNoVertexTC; //lint !e551 + +static char * _current_usemtl = NULL, * _last_usemtl = NULL; +static int _current_material_index = -1; + +static double _ssg_gbs_x = 0.0, _ssg_gbs_y = 0.0, _ssg_gbs_z = 1.0, _ssg_gbs_r = 0.0; + +void ssgGetValuesFromLastATGFile(double *x, double *y, double *z, double *r) +// These values are the values from the "# gbs" line from the last loaded +// ATG file, or 0, 0, 1, 0 if there is no ATG file with a # gbs line loaded yet +// The values are the vector from the centre of the earth to the tile and +// a radius. +{ *x = _ssg_gbs_x; + *y = _ssg_gbs_y; + *z = _ssg_gbs_z; + *r = _ssg_gbs_r; +} + +static char* parser_getLine() +// replaces parser.getLine, but handles '#' +// Some "comment lines" starting with '#' have important info like material/texture name inside +// if this function finds a #-line with a materialname, it sets _current_usemtl +{ char *token; + token = parser.getLine(0); + if ( token == NULL ) + return NULL; + + while ( token[0] == '#' ) + { char * token0 = parser.parseToken( 0 ); + if ( ulStrEqual ("usemtl" , token0)) // name has to be 0 + { char * usemtl = parser.parseToken( 0 ); + if ( usemtl != NULL) + if ( 0 != usemtl[0] ) + { + if ( _current_usemtl != NULL ) + delete [] _current_usemtl ; + _current_usemtl = ulStrDup ( usemtl ) ; + } + } + //# gbs -2710586.16105 -4275323.15743 3867065.62925 7623.60 + else if ( ulStrEqual ("gbs" , token0)) // name has to be 0 + { char * temp; + temp = parser.parseToken( 0 ); + _ssg_gbs_x = atof (temp); + temp = parser.parseToken( 0 ); + _ssg_gbs_y = atof (temp); + temp = parser.parseToken( 0 ); + _ssg_gbs_z = atof (temp); + temp = parser.parseToken( 0 ); + _ssg_gbs_r = atof (temp); + } + token = parser.getLine(0); + if ( token == NULL ) + return NULL; + } + return token; +} + +static int reduce_numbers; // some ATG files (from BTG converted ones?) have vertex coordinates that include gbs, for example + // 2713547.89986. Others have coordinates excluding gbs, for example 2961.50684 +// I need to reduce the big numbers beacuse float a,b; a-b is dangerous if a large and b small. +// Therefore I reduce the numbers by gbs while I have vertex coords and gbs as double and add it back in using double in PPE + + +static int parse() +{ + // ************* Init ************************ + char* token; + _ssgNoFaces= 0; + _ssgNoVertices = 0; + _ssgNoVertexNormals = 0; + _ssgNoVertexTC = 0; + + _theMesh.reInit (); + _theMesh.createVertices(); + _theMesh.createFaces(); + _theMesh.createPerFaceAndVertexTextureCoordinates2(); + _theMesh.createMaterials(); + _theMesh.createMaterialIndices() ; + + token = parser_getLine(); + if ( token == NULL ) + { parser.error("The file seems to be empty"); + return FALSE; + } + // ****** read vertices ************ + int first = TRUE; + while ( 0 == strcmp( token, "v") ) + { + double vx, vy, vz; + if (! parser.parseDouble( vx, "vertex.x") ) + return FALSE; + if (! parser.parseDouble( vy, "vertex.y") ) + return FALSE; + if (! parser.parseDouble( vz, "vertex.z") ) + return FALSE; + if (first) + { first = FALSE; + +#ifndef ABS +#define ABS(x) (((x)>0)?(x):-(x)) +#endif + // Mega-kludge: + reduce_numbers = (ABS(vx)>50000); + } + if (reduce_numbers) + { assert( _ssg_gbs_x != 0.0); // kludge + vx += _ssg_gbs_x; + vy += _ssg_gbs_y; + vz += _ssg_gbs_z; + } + sgVec3 vert; + sgSetVec3( vert, (float) vx, (float) vy, (float) vz); + _theMesh.addVertex(vert); // add to mesh + _ssgNoVertices++; + token = parser_getLine(); + if ( token == NULL ) + { parser.error("There are only vertices in the scenery, no faces"); + return FALSE; + } + } + // ****** read vertex normals ************ + while ( 0 == strcmp( token, "vn") ) + { sgVec3 vert_norm; + + if (! parser.parseFloat( vert_norm[0], "vertex normal.x") ) + return FALSE; + if (! parser.parseFloat( vert_norm[1], "vertex normal.y") ) + return FALSE; + if (! parser.parseFloat( vert_norm[2], "vertex normal.z") ) + return FALSE; + //_theMesh.addVertex(vert); + _ssgNoVertexNormals++; + token = parser_getLine(); + if ( token == NULL ) + { parser.error("There are only vertices in the scenery, no faces"); + return FALSE; + } + } + /*if ( _ssgNoVertexNormals != _ssgNoVertices) + { parser.error("The number of vertex normals and vertices doesn't match"); + return FALSE; + }*/ + // ***************** read texture coords. ********************** + // this format has a "linear" list of texture coords, that is indexed from the faces. + while ( 0 == strcmp( token, "vt") ) + { sgVec2 vert_tc; + + if (! parser.parseFloat( vert_tc[0], "vertex texture.x") ) + return FALSE; + if (! parser.parseFloat( vert_tc[1], "vertex texture.y") ) + return FALSE; + linearListTCPFAV->add(vert_tc); + _ssgNoVertexTC++; + token = parser_getLine(); + if ( token == NULL ) + { parser.error("There are only vertices in the scenery, no faces"); + return FALSE; + } + } + /*if ( _ssgNoVertexTC != _ssgNoVertices) + { parser.error("The number of texture coords and vertices doesn't match"); + return FALSE; + }*/ + + // ********* Read Faces ********** + int aiVertices[MAX_NO_VERTICES_PER_FACE], aiTCs[MAX_NO_VERTICES_PER_FACE]; + unsigned int nNoOfVerticesForThisFace; + + while ( 0 == strcmp( token, "f") ) + { char *ptr, buffer[1024], *ptr2Slash; + + if ( !ulStrEqual (_current_usemtl, _last_usemtl)) + // ***************+ material has changed. *********** + { + // bring _last_usemtl up to date + if ( _last_usemtl != NULL ) + delete [] _last_usemtl; + _last_usemtl= ulStrDup ( _current_usemtl ) ; + + + // create SimpleState + + ssgSimpleState * currentState = new ssgSimpleState () ; // (0) ? + + currentState -> setMaterial ( GL_AMBIENT, 0.5, 0.5, 0.5, 1.0); + currentState -> setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0) ; // 0.8, 0.8, 1.0, 1.0f + currentState -> setMaterial ( GL_SPECULAR, 1.0, 1.0, 1.0, 1.0); + currentState -> setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 1.0); + currentState -> setShininess ( 20 ) ; // Fixme, NIV14: Is that correct? + + currentState -> disable ( GL_COLOR_MATERIAL ) ; + //currentState -> enable ( GL_COLOR_MATERIAL ) ; + //currentState -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + + currentState -> enable ( GL_LIGHTING ) ; + currentState -> setShadeModel ( GL_SMOOTH ) ; + + currentState ->disable(GL_ALPHA_TEST); //needed? + +/* if ( currentDiffuse[3] > 0.0f ) + { + currentState -> disable ( GL_ALPHA_TEST ) ; + currentState -> enable ( GL_BLEND ) ; + currentState -> setTranslucent () ; + } + else */ + { + currentState -> disable ( GL_BLEND ) ; + currentState -> setOpaque () ; + } + currentState -> disable( GL_TEXTURE_2D ); +// if (textured) + { + char * fileName = new char [ strlen ( _current_usemtl ) + 5 ] ; + assert( fileName != NULL ); + strcpy ( fileName, _current_usemtl ) ; + strcat( fileName, ".rgb" ); + + currentState -> setTexture( current_options -> createTexture( fileName ) ); + delete [] fileName; + currentState -> enable( GL_TEXTURE_2D ); + } + // add SimpleState + _theMesh.addMaterial( ¤tState ); + + // bring _current_material_index up to date + _current_material_index ++; + + } // if new material + + // ************* parse vertex and TC indices of this face ****************** + nNoOfVerticesForThisFace = 0; + ptr = parser.parseToken( "vertex index"); + while ( ptr != NULL ) + { strncpy(buffer, ptr, 1024); + ptr2Slash = strchr(buffer, '/'); + if ( ptr2Slash != NULL) + { *ptr2Slash = 0; + ptr2Slash++; + if ( ! Ascii2Int( aiTCs[ nNoOfVerticesForThisFace ], ptr2Slash, "texture coord. index")) + return FALSE; + } + else + aiTCs[ nNoOfVerticesForThisFace ]=0; + if ( ! Ascii2Int( aiVertices[ nNoOfVerticesForThisFace ], buffer, "vertex index")) + return FALSE; + nNoOfVerticesForThisFace++; + assert(nNoOfVerticesForThisFaceref(); + for(j=0;j<3;j++) + { + if ( ! linearListTCPFAV->get(aiTCs[l*3+j]) ) + { parser.error("Internal error while reading *.atg-file: aiTCs[j] == NULL \n"); + return FALSE; + } + sca->add(linearListTCPFAV->get(aiTCs[l*3+j])); + } + + // ****** add face to mesh ***** + _theMesh.addPerFaceAndVertexTextureCoordinate2( &sca ) ; + int carray[3]; + carray[0]=aiVertices[3*l+0]; + carray[1]=aiVertices[3*l+1]; + carray[2]=aiVertices[3*l+2]; + _theMesh.addFaceFromIntegerArray(3, carray); + _theMesh.addMaterialIndex ( _current_material_index ) ; + } +#else + unsigned int j; + ssgTexCoordArray * sca = new ssgTexCoordArray (nNoOfVerticesForThisFace); + sca->ref(); + for(j=0;jget(aiTCs[j]) ) + { parser.error("Internal error while reading *.atg-file: aiTCs[j] == NULL \n"); + return FALSE; + } + sca->add(linearListTCPFAV->get(aiTCs[j])); + } + + // ****** add face to mesh ***** + _theMesh.addPerFaceAndVertexTextureCoordinate2 ( &sca ) ; + _theMesh.addFaceFromIntegerArray(nNoOfVerticesForThisFace, aiVertices); + _theMesh.addMaterialIndex ( _current_material_index ) ; + +#endif + + token = parser_getLine(); + if ( token == NULL ) + break; + } // ******* end of reading faces ***** + if ( token != NULL ) + ulSetError ( UL_WARNING, "f expected, got %s\n", token); + + if (! parser.eof ) + ulSetError ( UL_WARNING, "Warning: no eof\n"); + + + // kludge. We need a state for add2SSG: + + ssgSimpleState * ss = new ssgSimpleState () ; // (0) ? + ss -> setMaterial ( GL_AMBIENT, 0.5, 0.5, 0.5, 1.0); + ss -> setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0) ; // 0.8, 0.8, 1.0, 1.0f + ss -> setMaterial ( GL_SPECULAR, 1.0, 1.0, 1.0, 1.0); + ss -> setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 1.0); + ss -> setShininess ( 20 ) ; // Fixme, NIV14: Is that correct? + + ss -> disable ( GL_COLOR_MATERIAL ) ; + //ss -> enable ( GL_COLOR_MATERIAL ) ; + //ss -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + + ss -> enable ( GL_LIGHTING ) ; + ss -> setShadeModel ( GL_SMOOTH ) ; + + ss ->disable(GL_ALPHA_TEST); //needed? + + ss -> disable ( GL_BLEND ) ; + ss -> setOpaque () ; + + ss -> disable( GL_TEXTURE_2D ); + _theMesh.checkMe(); //lint !e534 // For debug + _theMesh.addToSSG( + ss, // super kludge. NIV135 + current_options, + top_branch); + + return TRUE ; +} + + +ssgEntity *ssgLoadATG ( const char *fname, const ssgLoaderOptions* options ) +{ + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + current_options = ssgGetCurrentOptions () ; + + top_branch = new ssgBranch ; + _current_usemtl = NULL; + _last_usemtl = NULL; + _current_material_index = -1; + + + if ( !parser.openFile( fname, &parser_spec )) + { + delete top_branch ; + return 0; + } + linearListTCPFAV=new ssgTexCoordArray(); + if ( !parse() ) + { + delete linearListTCPFAV; + delete top_branch ; + top_branch = 0 ; + } + delete linearListTCPFAV; +// parse_free(); + parser.closeFile(); + + return top_branch ; +} diff --git a/src/ssg/ssgLoadBMP.cxx b/src/ssg/ssgLoadBMP.cxx new file mode 100644 index 0000000..4e20a50 --- /dev/null +++ b/src/ssg/ssgLoadBMP.cxx @@ -0,0 +1,383 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadBMP.cxx 2166 2011-03-22 12:00:57Z fayjf $ +*/ + + +#include "ssgLocal.h" + +#ifdef SSG_LOAD_BMP_SUPPORTED + +static FILE *curr_image_fd ; +static char curr_image_fname [ 512 ] ; +static int isSwapped ; + + +static void swab_short ( unsigned short *x ) +{ + if ( isSwapped ) + *x = (( *x >> 8 ) & 0x00FF ) | + (( *x << 8 ) & 0xFF00 ) ; +} + +static void swab_int ( unsigned int *x ) +{ + if ( isSwapped ) + *x = (( *x >> 24 ) & 0x000000FF ) | + (( *x >> 8 ) & 0x0000FF00 ) | + (( *x << 8 ) & 0x00FF0000 ) | + (( *x << 24 ) & 0xFF000000 ) ; +} + +/*static void swab_int_array ( int *x, int leng ) +{ + if ( ! isSwapped ) + return ; + + for ( int i = 0 ; i < leng ; i++ ) + { + *x = (( *x >> 24 ) & 0x000000FF ) | + (( *x >> 8 ) & 0x0000FF00 ) | + (( *x << 8 ) & 0x00FF0000 ) | + (( *x << 24 ) & 0xFF000000 ) ; + x++ ; + } +}*/ + + +static unsigned char readByte () +{ + unsigned char x ; + fread ( & x, sizeof(unsigned char), 1, curr_image_fd ) ; + return x ; +} + +static unsigned short readShort () +{ + unsigned short x ; + fread ( & x, sizeof(unsigned short), 1, curr_image_fd ) ; + swab_short ( & x ) ; + return x ; +} + +static unsigned int readInt () +{ + unsigned int x ; + fread ( & x, sizeof(unsigned int), 1, curr_image_fd ) ; + swab_int ( & x ) ; + return x ; +} + + +/* + Original source for BMP loader kindly + donated by "Sean L. Palmer" +*/ + + +struct BMPHeader +{ + unsigned short FileType ; + unsigned int FileSize ; + unsigned short Reserved1 ; + unsigned short Reserved2 ; + unsigned int OffBits ; + unsigned int Size ; + unsigned int Width ; + unsigned int Height ; + unsigned short Planes ; + unsigned short BitCount ; + unsigned int Compression ; + unsigned int SizeImage ; + unsigned int XPelsPerMeter ; + unsigned int YPelsPerMeter ; + unsigned int ClrUsed ; + unsigned int ClrImportant ; +} ; + + +struct RGBA +{ + unsigned char r,g,b,a ; +} ; + + +bool ssgLoadBMP ( const char *fname, ssgTextureInfo* info ) +{ + int w, h, bpp ; + int index=0; + bool old_format = false; + RGBA pal [ 256 ] ; + + BMPHeader bmphdr ; + + /* Open file & get size */ + + strcpy ( curr_image_fname, fname ) ; + + if ( ( curr_image_fd = fopen ( curr_image_fname, "rb" ) ) == NULL ) + { + char *p = strrchr(curr_image_fname,'_'); + if (p != 0) { + *p = '\0'; + p++; + index = atoi (p); + old_format = true; + if ( ( curr_image_fd = fopen(curr_image_fname, "rb")) == NULL) { + perror ( "ssgLoadTexture" ) ; + ulSetError( UL_WARNING, "ssgLoadTexture: Failed to load '%s' for reading.", curr_image_fname ); + return false ; + } + p--; + *p = '_'; + } + else { + perror ( "ssgLoadTexture" ) ; + ulSetError( UL_WARNING, "ssgLoadTexture: Failed to open '%s' for reading.", curr_image_fname ); + return false ; + } + } + + /* + Load the BMP piecemeal to avoid struct packing issues + */ + + isSwapped = FALSE ; + bmphdr.FileType = readShort () ; + + if ( bmphdr.FileType == ((int)'B' + ((int)'M'<<8)) ) + isSwapped = FALSE ; + else + if ( bmphdr.FileType == ((int)'M' + ((int)'B'<<8)) ) + isSwapped = TRUE ; + else + { + ulSetError ( UL_WARNING, "%s: Unrecognised magic number 0x%04x", + curr_image_fname, bmphdr.FileType ) ; + return false ; + } + + bmphdr.FileSize = readInt () ; + bmphdr.Reserved1 = readShort () ; + bmphdr.Reserved2 = readShort () ; + bmphdr.OffBits = readInt () ; + bmphdr.Size = readInt () ; + bmphdr.Width = readInt () ; + bmphdr.Height = readInt () ; + bmphdr.Planes = readShort () ; + bmphdr.BitCount = readShort () ; + bmphdr.Compression = readInt () ; + bmphdr.SizeImage = readInt () ; + bmphdr.XPelsPerMeter = readInt () ; + bmphdr.YPelsPerMeter = readInt () ; + bmphdr.ClrUsed = readInt () ; + bmphdr.ClrImportant = readInt () ; + + w = bmphdr.Width ; + h = bmphdr.Height ; + bpp = bmphdr.Planes * bmphdr.BitCount ; + + bool top_down = false ; + if ( h < 0 ) + { + top_down = true ; + h = -1 * h ; + } + +#ifdef PRINT_BMP_HEADER_DEBUG + ulSetError ( UL_DEBUG, "Filetype %04x", bmphdr.FileType ) ; + ulSetError ( UL_DEBUG, "Filesize %08x", bmphdr.FileSize ) ; + ulSetError ( UL_DEBUG, "R1 %04x", bmphdr.Reserved1 ) ; + ulSetError ( UL_DEBUG, "R2 %04x", bmphdr.Reserved2 ) ; + ulSetError ( UL_DEBUG, "Offbits %08x", bmphdr.OffBits ) ; + ulSetError ( UL_DEBUG, "Size %08x", bmphdr.Size ) ; + ulSetError ( UL_DEBUG, "Width %08x", bmphdr.Width ) ; + ulSetError ( UL_DEBUG, "Height %08x", bmphdr.Height ) ; + ulSetError ( UL_DEBUG, "Planes %04x", bmphdr.Planes ) ; + ulSetError ( UL_DEBUG, "Bitcount %04x", bmphdr.BitCount ) ; + ulSetError ( UL_DEBUG, "Compression %08x", bmphdr.Compression ) ; + ulSetError ( UL_DEBUG, "SizeImage %08x", bmphdr.SizeImage ) ; + ulSetError ( UL_DEBUG, "XPelsPerMeter %08x", bmphdr.XPelsPerMeter ) ; + ulSetError ( UL_DEBUG, "YPelsPerMeter %08x", bmphdr.YPelsPerMeter ) ; + ulSetError ( UL_DEBUG, "ClrUsed %08x", bmphdr.ClrUsed ) ; + ulSetError ( UL_DEBUG, "ClrImportant %08x", bmphdr.ClrImportant ) ; +#endif + + int isMonochrome = TRUE ; + int isOpaque = TRUE ; + + if ( bpp <= 8 ) + { + for ( int i = 0 ; i < 256 ; i++ ) + { + pal[i].b = readByte () ; + pal[i].g = readByte () ; + pal[i].r = readByte () ; + + /* According to BMP specs, this fourth value is not really alpha value + but just a filler byte, so it is ignored for now. */ + pal[i].a = readByte () ; + if (old_format == true) { + pal[i].a = (i= 0 ; y-- ) + { + GLubyte *row_ptr ; + if ( top_down ) + { + /* store flipped image */ + row_ptr = &data [ y * row_size ] ; + } + else + { + /* store without flipping */ + row_ptr = &data [ ( h - ( y + 1 ) ) * row_size ] ; + } + if ( fread ( row_ptr, 1, row_size, curr_image_fd ) != (unsigned)row_size ) + { + ulSetError ( UL_WARNING, "Premature EOF in '%s'", curr_image_fname ) ; + return false ; + } + // padding bytes + if ( pad ) + fread ( buff, 1, pad, curr_image_fd ); + } + } + + fclose ( curr_image_fd ) ; + + GLubyte *image ; + int z ; + + if ( bpp == 8 ) + { + int i ; + + // check for diffrent alpha values in the bitmap + // assume blending if that's the case + for ( i = 1 ; i < w * h ; i++ ) { + if (pal[data[i]].a != pal[data[i-1]].a) { + isOpaque = FALSE ; + break; + } + } + + if ( isMonochrome ) + z = isOpaque ? 1 : 2 ; + else + z = isOpaque ? 3 : 4 ; + + image = new GLubyte [ w * h * z ] ; + + for ( i = 0 ; i < w * h ; i++ ) + switch ( z ) + { + case 1 : image [ i ] = pal[data[i]].r ; break ; + case 2 : image [ i*2 ] = pal[data[i]].r ; + image [ i*2 + 1 ] = pal[data[i]].a ; break ; + case 3 : image [ i*3 ] = pal[data[i]].r ; + image [ i*3 + 1 ] = pal[data[i]].g ; + image [ i*3 + 2 ] = pal[data[i]].b ; break ; + case 4 : image [ i*4 ] = pal[data[i]].r ; + image [ i*4 + 1 ] = pal[data[i]].g ; + image [ i*4 + 2 ] = pal[data[i]].b ; + image [ i*4 + 3 ] = pal[data[i]].a ; break ; + default : break ; + } + + delete [] data ; + } + else + if ( bpp == 24 ) + { + z = 3 ; + isOpaque = TRUE ; + image = data ; + + /* BGR --> RGB */ + + for ( int i = 0 ; i < w * h ; i++ ) + { + GLubyte tmp = image [ 3 * i ] ; + image [ 3 * i ] = image [ 3 * i + 2 ]; + image [ 3 * i + 2 ] = tmp ; + } + } + else + if ( bpp == 32 ) + { + z = 4 ; + isOpaque = FALSE ; + image = data ; + + /* BGRA --> RGBA */ + + for ( int i = 0 ; i < w * h ; i++ ) + { + GLubyte tmp = image [ 4 * i ] ; + image [ 4 * i ] = image [ 4 * i + 2 ]; + image [ 4 * i + 2 ] = tmp ; + } + } + else + { + ulSetError ( UL_WARNING, "ssgLoadTexture: Can't load %d bpp BMP textures.", bpp ) ; + return false ; + } + + if ( info != NULL ) + { + info -> width = w ; + info -> height = h ; + info -> depth = z ; + info -> alpha = ( isOpaque == FALSE ) ; + } + + return ssgMakeMipMaps ( image, w, h, z ) ; +} + +#else + +bool ssgLoadBMP ( const char *fname, ssgTextureInfo* info ) +{ + ulSetError ( UL_WARNING, + "ssgLoadTexture: '%s' - BMP support not configured", fname ) ; + return false ; +} + +#endif diff --git a/src/ssg/ssgLoadDOF.cxx b/src/ssg/ssgLoadDOF.cxx new file mode 100644 index 0000000..7382dac --- /dev/null +++ b/src/ssg/ssgLoadDOF.cxx @@ -0,0 +1,638 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2003 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadDOF.cxx 1748 2003-01-29 19:33:41Z sjbaker $ +*/ + + +#include "ssgLocal.h" + +static ssgLoaderOptions* current_options = NULL ; + +struct _NameValuePair +{ + char *name ; + int value ; +} ; + +#define TOKEN_DOF1 1 +#define TOKEN_EDOF 2 +#define TOKEN_MATS 3 +#define TOKEN_GEOB 4 +#define TOKEN_MAT0 5 +#define TOKEN_GOB1 6 +#define TOKEN_MHDR 7 +#define TOKEN_MCOL 8 +#define TOKEN_MUVW 9 +#define TOKEN_MTRA 10 +#define TOKEN_MTEX 11 +#define TOKEN_MSUB 12 +#define TOKEN_MEND 13 +#define TOKEN_GHDR 14 +#define TOKEN_INDI 15 +#define TOKEN_VERT 16 +#define TOKEN_TVER 17 +#define TOKEN_NORM 18 +#define TOKEN_BRST 19 +#define TOKEN_GEND 20 +#define TOKEN_ILLEGAL 998 +#define TOKEN_EOF 999 + + +static _NameValuePair tags [] = +{ + { "DOF1", TOKEN_DOF1 }, + { "EDOF", TOKEN_EDOF }, + { "MATS", TOKEN_MATS }, + { "GEOB", TOKEN_GEOB }, + { "MAT0", TOKEN_MAT0 }, + { "GOB1", TOKEN_GOB1 }, + { "MHDR", TOKEN_MHDR }, + { "MCOL", TOKEN_MCOL }, + { "MUVW", TOKEN_MUVW }, + { "MTRA", TOKEN_MTRA }, + { "MTEX", TOKEN_MTEX }, + { "MSUB", TOKEN_MSUB }, + { "MEND", TOKEN_MEND }, + { "GHDR", TOKEN_GHDR }, + { "INDI", TOKEN_INDI }, + { "VERT", TOKEN_VERT }, + { "TVER", TOKEN_TVER }, + { "NORM", TOKEN_NORM }, + { "BRST", TOKEN_BRST }, + { "GEND", TOKEN_GEND }, + { NULL, 0 } +} ; + + +struct dofMaterial +{ + char *name ; + char *className ; + + sgVec4 ambient ; + sgVec4 diffuse ; + sgVec4 specular ; + sgVec4 emission ; + float shininess ; + + float uvwUoffset ; + float uvwVoffset ; + float uvwUtiling ; + float uvwVtiling ; + float uvwAngle ; + float uvwBlur ; + float uvwBlurOffset ; + + float transparency ; /* Unused */ + int blendMode ; /* 0 == No blend, + 1 == BLEND_SRC_ALPHA, + 2 == BLEND_CONST (unused) */ + + int textures ; + char **mapName ; + + int subMaterials ; /* Should be zero */ + dofMaterial *MAT0 ; /* Should be unused */ + + ssgSimpleState *ssg_material ; +} ; + + +static ulList *materials ; + + +static int getToken ( FILE *fd ) +{ + char s [ 5 ] ; + + if ( fread ( s, 1, 4, fd ) != 4 ) + return TOKEN_EOF ; + + s [ 4 ] = '\0' ; + + for ( int i = 0 ; tags [ i ] . name != 0 ; i++ ) + if ( strcmp ( tags[i].name, s ) == 0 ) + return tags[i].value ; + + ulSetError ( UL_WARNING, "Illegal token '%s'", s ) ; + return TOKEN_ILLEGAL ; +} + + +static short getShort ( FILE *fd ) +{ + short val ; + + if ( fread ( & val, sizeof(short), 1, fd ) != 1 ) + return 0 ; + + val = ulEndianLittle16 ( (unsigned short) val ) ; + return val ; +} + + +static void getColour ( FILE *fd, float *colour ) +{ + if ( fread ( colour, sizeof(float), 4, fd ) != 4 ) + return ; + + ulEndianLittleArrayFloat ( colour, 4 ) ; +} + + +static float getFloat ( FILE *fd ) +{ + float val ; + + if ( fread ( & val, sizeof(float), 1, fd ) != 1 ) + return 0 ; + + val = ulEndianLittleFloat ( val ) ; + return val ; +} + + +static int getInteger ( FILE *fd ) +{ + int val ; + + if ( fread ( & val, sizeof(int), 1, fd ) != 1 ) + return 0 ; + + val = ulEndianLittle32 ( (unsigned int) val ) ; + return val ; +} + + +static int getLength ( FILE *fd ) +{ + return getInteger ( fd ) ; +} + + +static int getTokenAndLength ( FILE *fd, int *len ) +{ + int tok = getToken ( fd ) ; + + if ( tok == TOKEN_EOF ) + { + *len = 0 ; + return tok ; + } + + *len = getLength ( fd ) ; + return tok ; +} + + +static char *getQString ( FILE *fd, int *l ) +{ + short len = getShort ( fd ) ; + + (*l) -= len + sizeof ( short ) ; + + char *res = new char [ len + 1 ] ; + + fread ( res, sizeof(char), len, fd ) ; + res [ len ] = '\0' ; + + return res ; +} + + +static void getMAT0 ( FILE *fd ) +{ + dofMaterial *mat = new dofMaterial ; + + mat -> ssg_material = new ssgSimpleState () ; + + materials -> addEntity ( mat ) ; + + while ( 1 ) + { + int len ; + + switch ( getToken ( fd ) ) + { + case TOKEN_MHDR : + { + len = getLength ( fd ) ; + mat -> name = getQString ( fd, &len ) ; + mat -> className = getQString ( fd, &len ) ; +fprintf ( stderr, "MAT0: Name='%s', className='%s'\n", + mat -> name, mat -> className ) ; + + } + break ; + + case TOKEN_MTEX : + { + len = getLength ( fd ) ; + mat -> textures = getInteger ( fd ) ; + len -= sizeof ( int ) ; + mat -> mapName = new char * [ mat -> textures ] ; + for ( int i = 0 ; i < mat -> textures ; i++ ) + mat -> mapName [ i ] = getQString ( fd, & len ) ; + } + break ; + + case TOKEN_MCOL : + { + len = getLength ( fd ) ; + getColour ( fd, mat -> ambient ) ; + getColour ( fd, mat -> diffuse ) ; + getColour ( fd, mat -> specular ) ; + getColour ( fd, mat -> emission ) ; + mat -> shininess = getFloat ( fd ) ; + len -= 17 * sizeof(float) ; + } + break ; + + case TOKEN_MUVW : + len = getLength ( fd ) ; + mat -> uvwUoffset = getFloat ( fd ) ; + mat -> uvwVoffset = getFloat ( fd ) ; + mat -> uvwUtiling = getFloat ( fd ) ; + mat -> uvwVtiling = getFloat ( fd ) ; + mat -> uvwAngle = getFloat ( fd ) ; + mat -> uvwBlur = getFloat ( fd ) ; + mat -> uvwBlurOffset = getFloat ( fd ) ; + len -= 7 * sizeof(float) ; + break ; + + case TOKEN_MTRA : + len = getLength ( fd ) ; + mat -> transparency = getFloat ( fd ) ; + mat -> blendMode = getInteger ( fd ) ; + len -= sizeof(float) + sizeof(int) ; + break ; + + case TOKEN_MSUB : + { + len = getLength ( fd ) ; + + mat -> subMaterials = getInteger ( fd ) ; + + if ( mat -> subMaterials != 0 ) + ulSetError ( UL_WARNING, + "ssgLoadDOF: Sub-Materials are not supported." ) ; + + len -= sizeof ( int ) ; + } + break ; + + case TOKEN_MEND : + { + ssgSimpleState *m = mat -> ssg_material ; + + if ( mat -> textures > 0 ) + { + m -> enable ( GL_TEXTURE_2D ) ; + m -> setTexture ( mat -> mapName[0] ) ; + } + else + m -> disable ( GL_TEXTURE_2D ) ; + + m -> disable ( GL_COLOR_MATERIAL ) ; + m -> setMaterial ( GL_AMBIENT , mat -> ambient ) ; + m -> setMaterial ( GL_DIFFUSE , mat -> diffuse ) ; + m -> setMaterial ( GL_SPECULAR, mat -> specular ) ; + m -> setMaterial ( GL_EMISSION, mat -> emission ) ; + m -> setShininess ( mat -> shininess ) ; + } + return ; + + case TOKEN_EOF : return ; + + default : + { + ulSetError ( UL_WARNING, + "ssgLoadDOF: Material contains an unrecognised token?!?" ) ; + + len = getLength ( fd ) ; + } + break ; + } + + for ( int i = 0 ; i < len ; i++ ) getc ( fd ) ; + } +} + + +static void getMaterials ( FILE *fd, int howMany ) +{ +ulSetError ( UL_WARNING, "Getting %d materials", howMany ) ; + + for ( int i = 0 ; i < howMany ; i++ ) + { + int len ; + + switch ( getToken ( fd ) ) + { + case TOKEN_MAT0 : + len = getLength ( fd ) ; + getMAT0 ( fd ) ; + break ; + + + case TOKEN_EOF : return ; + + default : + { + ulSetError ( UL_WARNING, + "ssgLoadDOF: Material contains an unrecognised token?!?" ) ; + + len = getLength ( fd ) ; + + for ( int i = 0 ; i < len ; i++ ) + getc ( fd ) ; + } + return ; + } + } +} + + +static ssgEntity *getGOB1 ( FILE *fd ) +{ + int flags = 0 ; + int paintflags = 0 ; + int materialRef = 0 ; + int indices = 0 ; short *index = NULL ; + int vertices = 0 ; float *vertex = NULL ; + int tvertices = 0 ; float *tvertex = NULL ; + int normals = 0 ; float *normal = NULL ; + int bursts = 0 ; + int *burstStart = NULL ; + int *burstCount = NULL ; + int *burstMtlID = NULL ; + int *burstVperP = NULL ; + + while ( 1 ) + { + int len ; + + switch ( getToken ( fd ) ) + { + case TOKEN_GHDR : + { + len = getLength ( fd ) ; + + flags = getInteger ( fd ) ; + paintflags = getInteger ( fd ) ; + materialRef = getInteger ( fd ) ; + + len -= 3 * sizeof ( int ) ; + } + break ; + + case TOKEN_INDI : + { + len = getLength ( fd ) ; + indices = getInteger ( fd ) ; + index = new short [ indices ] ; + fread ( index, sizeof(short), indices, fd ) ; + ulEndianLittleArray16 ( (unsigned short *) index, indices ) ; + len -= sizeof(int) + sizeof(short) * indices ; + } + break ; + + case TOKEN_VERT : + { + len = getLength ( fd ) ; + vertices = getInteger ( fd ) ; + vertex = new float [ vertices * 3 ] ; + fread ( vertex, sizeof(float), vertices * 3, fd ) ; + ulEndianLittleArrayFloat ( vertex, vertices * 3 ) ; + len -= sizeof(int) + sizeof(float) * vertices * 3 ; + } + break ; + + case TOKEN_TVER : + { + len = getLength ( fd ) ; + tvertices = getInteger ( fd ) ; + tvertex = new float [ tvertices * 2 ] ; + fread ( tvertex, sizeof(float), tvertices * 2, fd ) ; + ulEndianLittleArrayFloat ( tvertex, tvertices * 2 ) ; + len -= sizeof(int) + sizeof(float) * tvertices * 2 ; + } + break ; + + case TOKEN_NORM : + { + len = getLength ( fd ) ; + normals = getInteger ( fd ) ; + normal = new float [ normals * 3 ] ; + fread ( normal, sizeof(float), normals * 3, fd ) ; + ulEndianLittleArrayFloat ( normal, normals * 3 ) ; + len -= sizeof(int) + sizeof(float) * normals * 3 ; + } + break ; + + case TOKEN_BRST : + { + len = getLength ( fd ) ; + bursts = getInteger ( fd ) ; + burstStart = new int [ bursts ] ; + burstCount = new int [ bursts ] ; + burstMtlID = new int [ bursts ] ; + burstVperP = new int [ bursts ] ; + fread ( burstStart, sizeof(int), bursts, fd ) ; + fread ( burstCount, sizeof(int), bursts, fd ) ; + fread ( burstMtlID, sizeof(int), bursts, fd ) ; + fread ( burstVperP, sizeof(int), bursts, fd ) ; + ulEndianLittleArray32 ( (unsigned int *) burstStart, bursts ) ; + ulEndianLittleArray32 ( (unsigned int *) burstCount, bursts ) ; + ulEndianLittleArray32 ( (unsigned int *) burstMtlID, bursts ) ; + ulEndianLittleArray32 ( (unsigned int *) burstVperP, bursts ) ; + + len -= sizeof(int) + sizeof(int) * bursts * 4 ; + } + break ; + + case TOKEN_GEND : + { + float *colours = new float [ vertices * 4 ] ; + + for ( int i = 0 ; i < vertices ; i++ ) + { + colours [ i*4 + 0 ] = 0.5f ; + colours [ i*4 + 1 ] = 0.5f ; + colours [ i*4 + 2 ] = 0.5f ; + colours [ i*4 + 3 ] = 1.0f ; + + float tmp ; + tmp = vertex [ i*3 + 1 ] ; + vertex [ i*3 + 1 ] = -vertex [ i*3 + 2 ] ; + vertex [ i*3 + 2 ] = tmp ; + tmp = normal [ i*3 + 1 ] ; + normal [ i*3 + 1 ] = -normal [ i*3 + 2 ] ; + normal [ i*3 + 2 ] = tmp ; + } + ssgVertexArray *vx = new ssgVertexArray ( vertices , (sgVec3 *) vertex ) ; + ssgColourArray *co = new ssgColourArray ( vertices , (sgVec4 *) colours ) ; + ssgNormalArray *nm = new ssgNormalArray ( normals , (sgVec3 *) normal ) ; + ssgTexCoordArray *tx = new ssgTexCoordArray ( tvertices, (sgVec2 *) tvertex ) ; + ssgIndexArray *ix = new ssgIndexArray ( indices , index ) ; + + ssgVtxArray *va = new ssgVtxArray ( GL_TRIANGLES, + vx, nm, tx, co, ix ) ; + + va -> setState ( ( (dofMaterial *) + ( materials -> getEntity ( materialRef ) ) + ) -> ssg_material ) ; + delete [] burstStart ; + delete [] burstCount ; + delete [] burstMtlID ; + delete [] burstVperP ; + + return va ; + } + + case TOKEN_EOF : return NULL ; + + default : + { + ulSetError ( UL_WARNING, + "ssgLoadDOF: GOB1 contains an unrecognised token?!?" ) ; + + len = getLength ( fd ) ; + } + break ; + } + + for ( int i = 0 ; i < len ; i++ ) getc ( fd ) ; + } +} + + + +static ssgBranch *getGeode ( FILE *fd, int howMany ) +{ + ssgBranch *br = new ssgBranch () ; + +ulSetError ( UL_WARNING, "Getting %d geodes", howMany ) ; + + for ( int i = 0 ; i < howMany ; i++ ) + { + int len ; + + switch ( getToken ( fd ) ) + { + case TOKEN_GOB1 : + len = getLength ( fd ) ; + + br -> addKid ( getGOB1 ( fd ) ) ; + + break ; + + case TOKEN_EOF : return br ; + + default : + { + ulSetError ( UL_WARNING, + "ssgLoadDOF: Geode contains an unrecognised token?!?" ) ; + + len = getLength ( fd ) ; + + for ( int i = 0 ; i < len ; i++ ) + getc ( fd ) ; + } + return br ; + } + } + + return br ; +} + + +static void cleanUp () +{ + for ( int i = 0 ; i < materials -> getNumEntities () ; i++ ) + delete (dofMaterial *) ( materials -> getEntity ( i ) ) ; + delete materials ; +} + + +ssgEntity *ssgLoadDOF ( const char *fname, const ssgLoaderOptions* options ) +{ + ssgBranch *model ; + + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + current_options = ssgGetCurrentOptions () ; + + char filename [ 1024 ] ; + current_options -> makeModelPath ( filename, fname ) ; + + FILE *fd = fopen ( filename, "ra" ) ; + + if ( fd == NULL ) + { + ulSetError ( UL_WARNING, + "ssgLoadDOF: Failed to open '%s' for reading", filename ) ; + return NULL ; + } + + int len ; + + if ( getTokenAndLength ( fd, &len ) != TOKEN_DOF1 ) + { + ulSetError ( UL_WARNING, + "ssgLoadDOF: '%s' does not start with 'DOF1'?!?", filename ) ; + return NULL ; + } + + materials = new ulList () ; + model = new ssgBranch () ; + + while ( 1 ) + { + switch ( getToken ( fd ) ) + { + case TOKEN_MATS : + getLength ( fd ) ; + getMaterials ( fd, getInteger ( fd ) ) ; + break ; + + case TOKEN_GEOB : + getLength ( fd ) ; + model -> addKid ( getGeode ( fd, getInteger ( fd ) ) ) ; + break ; + + case TOKEN_EDOF : + cleanUp () ; + return model ; + + case TOKEN_EOF : + cleanUp () ; + return NULL ; + + default : + ulSetError ( UL_WARNING, + "ssgLoadDOF: '%s' contains an unrecognised token?!?", filename ) ; + cleanUp () ; + return NULL ; + } + } +} + + diff --git a/src/ssg/ssgLoadDXF.cxx b/src/ssg/ssgLoadDXF.cxx new file mode 100644 index 0000000..b23b8e3 --- /dev/null +++ b/src/ssg/ssgLoadDXF.cxx @@ -0,0 +1,952 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadDXF.cxx 1673 2002-09-15 01:29:12Z ude $ +*/ + +// +// DXF loader for SSG/PLIB +// Ported from IVCON by Dave McClurg (dpm@efn.org) in March-2000 +// IVCON::dxf_read() by John Burkardt, 23 May 1999 +// Added better support for meshes, August 2001 +// Added support for colors, blocks and block references, September 2001 +// + +#include "ssgLocal.h" + + +#define MAX_LINE_LEN 1024 + +class dxfVert { +public: + sgVec3 pos ; + int color_index ; + int isEqual ( class dxfVert * other ); +} ; + +class dxfVertArray : public ssgSimpleList +{ +public: + dxfVertArray () : ssgSimpleList ( sizeof(dxfVert), 0, NULL ) {} + dxfVert *get ( unsigned int n ) { return (dxfVert *) raw_get ( n ) ; } + void add ( const dxfVert* thing ) { raw_add ( (char *) thing ) ; } ; +} ; + +struct dxfMesh +{ + int flags; + int size[2]; + int vlist[4]; + int vnum; +} ; + +enum Entities { + ENT_NONE, + ENT_LINE, + ENT_FACE, + ENT_POLYLINE, + ENT_VERTEX, + ENT_INSERT +}; + +static int ent_type = ENT_NONE ; + +static const ssgLoaderOptions* current_options = NULL ; +static ssgState* current_state = NULL ; +static ssgBranch* top_branch = NULL ; +static ssgBranch* current_block = NULL ; +static ssgBranch* blocks = NULL ; + +static int num_line; +static int num_face; +static dxfVertArray tempvert; +static dxfVertArray linevert; +static dxfVertArray facevert; +static dxfVertArray meshvert; +static dxfMesh mesh; + +static int cflags; +static sgVec3 cvec; +static sgVec3 scale_vec; +static float rot_angle; +static char* block_name; +static int color_index ; + +static float dxf_colors [256][3] = +{ + { 0.0000f, 0.0000f, 0.0000f }, + { 1.0000f, 0.0000f, 0.0000f }, + { 1.0000f, 1.0000f, 0.0000f }, + { 0.0000f, 1.0000f, 0.0000f }, + { 0.0000f, 1.0000f, 1.0000f }, + { 0.0000f, 0.0000f, 1.0000f }, + { 1.0000f, 0.0000f, 1.0000f }, + { 0.0000f, 0.0000f, 0.0000f }, + { 0.0000f, 0.0000f, 0.0000f }, + { 0.0000f, 0.0000f, 0.0000f }, + { 1.0000f, 0.0000f, 0.0000f }, + { 1.0000f, 0.5000f, 0.5000f }, + { 0.6500f, 0.0000f, 0.0000f }, + { 0.6500f, 0.3250f, 0.3250f }, + { 0.5000f, 0.0000f, 0.0000f }, + { 0.5000f, 0.2500f, 0.2500f }, + { 0.3000f, 0.0000f, 0.0000f }, + { 0.3000f, 0.1500f, 0.1500f }, + { 0.1500f, 0.0000f, 0.0000f }, + { 0.1500f, 0.0750f, 0.0750f }, + { 1.0000f, 0.2500f, 0.0000f }, + { 1.0000f, 0.6250f, 0.5000f }, + { 0.6500f, 0.1625f, 0.0000f }, + { 0.6500f, 0.4063f, 0.3250f }, + { 0.5000f, 0.1250f, 0.0000f }, + { 0.5000f, 0.3125f, 0.2500f }, + { 0.3000f, 0.0750f, 0.0000f }, + { 0.3000f, 0.1875f, 0.1500f }, + { 0.1500f, 0.0375f, 0.0000f }, + { 0.1500f, 0.0938f, 0.0750f }, + { 1.0000f, 0.5000f, 0.0000f }, + { 1.0000f, 0.7500f, 0.5000f }, + { 0.6500f, 0.3250f, 0.0000f }, + { 0.6500f, 0.4875f, 0.3250f }, + { 0.5000f, 0.2500f, 0.0000f }, + { 0.5000f, 0.3750f, 0.2500f }, + { 0.3000f, 0.1500f, 0.0000f }, + { 0.3000f, 0.2250f, 0.1500f }, + { 0.1500f, 0.0750f, 0.0000f }, + { 0.1500f, 0.1125f, 0.0750f }, + { 1.0000f, 0.7500f, 0.0000f }, + { 1.0000f, 0.8750f, 0.5000f }, + { 0.6500f, 0.4875f, 0.0000f }, + { 0.6500f, 0.5688f, 0.3250f }, + { 0.5000f, 0.3750f, 0.0000f }, + { 0.5000f, 0.4375f, 0.2500f }, + { 0.3000f, 0.2250f, 0.0000f }, + { 0.3000f, 0.2625f, 0.1500f }, + { 0.1500f, 0.1125f, 0.0000f }, + { 0.1500f, 0.1313f, 0.0750f }, + { 1.0000f, 1.0000f, 0.0000f }, + { 1.0000f, 1.0000f, 0.5000f }, + { 0.6500f, 0.6500f, 0.0000f }, + { 0.6500f, 0.6500f, 0.3250f }, + { 0.5000f, 0.5000f, 0.0000f }, + { 0.5000f, 0.5000f, 0.2500f }, + { 0.3000f, 0.3000f, 0.0000f }, + { 0.3000f, 0.3000f, 0.1500f }, + { 0.1500f, 0.1500f, 0.0000f }, + { 0.1500f, 0.1500f, 0.0750f }, + { 0.7500f, 1.0000f, 0.0000f }, + { 0.8750f, 1.0000f, 0.5000f }, + { 0.4875f, 0.6500f, 0.0000f }, + { 0.5688f, 0.6500f, 0.3250f }, + { 0.3750f, 0.5000f, 0.0000f }, + { 0.4375f, 0.5000f, 0.2500f }, + { 0.2250f, 0.3000f, 0.0000f }, + { 0.2625f, 0.3000f, 0.1500f }, + { 0.1125f, 0.1500f, 0.0000f }, + { 0.1313f, 0.1500f, 0.0750f }, + { 0.5000f, 1.0000f, 0.0000f }, + { 0.7500f, 1.0000f, 0.5000f }, + { 0.3250f, 0.6500f, 0.0000f }, + { 0.4875f, 0.6500f, 0.3250f }, + { 0.2500f, 0.5000f, 0.0000f }, + { 0.3750f, 0.5000f, 0.2500f }, + { 0.1500f, 0.3000f, 0.0000f }, + { 0.2250f, 0.3000f, 0.1500f }, + { 0.0750f, 0.1500f, 0.0000f }, + { 0.1125f, 0.1500f, 0.0750f }, + { 0.2500f, 1.0000f, 0.0000f }, + { 0.6250f, 1.0000f, 0.5000f }, + { 0.1625f, 0.6500f, 0.0000f }, + { 0.4063f, 0.6500f, 0.3250f }, + { 0.1250f, 0.5000f, 0.0000f }, + { 0.3125f, 0.5000f, 0.2500f }, + { 0.0750f, 0.3000f, 0.0000f }, + { 0.1875f, 0.3000f, 0.1500f }, + { 0.0375f, 0.1500f, 0.0000f }, + { 0.0938f, 0.1500f, 0.0750f }, + { 0.0000f, 1.0000f, 0.0000f }, + { 0.5000f, 1.0000f, 0.5000f }, + { 0.0000f, 0.6500f, 0.0000f }, + { 0.3250f, 0.6500f, 0.3250f }, + { 0.0000f, 0.5000f, 0.0000f }, + { 0.2500f, 0.5000f, 0.2500f }, + { 0.0000f, 0.3000f, 0.0000f }, + { 0.1500f, 0.3000f, 0.1500f }, + { 0.0000f, 0.1500f, 0.0000f }, + { 0.0750f, 0.1500f, 0.0750f }, + { 0.0000f, 1.0000f, 0.2500f }, + { 0.5000f, 1.0000f, 0.6250f }, + { 0.0000f, 0.6500f, 0.1625f }, + { 0.3250f, 0.6500f, 0.4063f }, + { 0.0000f, 0.5000f, 0.1250f }, + { 0.2500f, 0.5000f, 0.3125f }, + { 0.0000f, 0.3000f, 0.0750f }, + { 0.1500f, 0.3000f, 0.1875f }, + { 0.0000f, 0.1500f, 0.0375f }, + { 0.0750f, 0.1500f, 0.0938f }, + { 0.0000f, 1.0000f, 0.5000f }, + { 0.5000f, 1.0000f, 0.7500f }, + { 0.0000f, 0.6500f, 0.3250f }, + { 0.3250f, 0.6500f, 0.4875f }, + { 0.0000f, 0.5000f, 0.2500f }, + { 0.2500f, 0.5000f, 0.3750f }, + { 0.0000f, 0.3000f, 0.1500f }, + { 0.1500f, 0.3000f, 0.2250f }, + { 0.0000f, 0.1500f, 0.0750f }, + { 0.0750f, 0.1500f, 0.1125f }, + { 0.0000f, 1.0000f, 0.7500f }, + { 0.5000f, 1.0000f, 0.8750f }, + { 0.0000f, 0.6500f, 0.4875f }, + { 0.3250f, 0.6500f, 0.5688f }, + { 0.0000f, 0.5000f, 0.3750f }, + { 0.2500f, 0.5000f, 0.4375f }, + { 0.0000f, 0.3000f, 0.2250f }, + { 0.1500f, 0.3000f, 0.2625f }, + { 0.0000f, 0.1500f, 0.1125f }, + { 0.0750f, 0.1500f, 0.1313f }, + { 0.0000f, 1.0000f, 1.0000f }, + { 0.5000f, 1.0000f, 1.0000f }, + { 0.0000f, 0.6500f, 0.6500f }, + { 0.3250f, 0.6500f, 0.6500f }, + { 0.0000f, 0.5000f, 0.5000f }, + { 0.2500f, 0.5000f, 0.5000f }, + { 0.0000f, 0.3000f, 0.3000f }, + { 0.1500f, 0.3000f, 0.3000f }, + { 0.0000f, 0.1500f, 0.1500f }, + { 0.0750f, 0.1500f, 0.1500f }, + { 0.0000f, 0.7500f, 1.0000f }, + { 0.5000f, 0.8750f, 1.0000f }, + { 0.0000f, 0.4875f, 0.6500f }, + { 0.3250f, 0.5688f, 0.6500f }, + { 0.0000f, 0.3750f, 0.5000f }, + { 0.2500f, 0.4375f, 0.5000f }, + { 0.0000f, 0.2250f, 0.3000f }, + { 0.1500f, 0.2625f, 0.3000f }, + { 0.0000f, 0.1125f, 0.1500f }, + { 0.0750f, 0.1313f, 0.1500f }, + { 0.0000f, 0.5000f, 1.0000f }, + { 0.5000f, 0.7500f, 1.0000f }, + { 0.0000f, 0.3250f, 0.6500f }, + { 0.3250f, 0.4875f, 0.6500f }, + { 0.0000f, 0.2500f, 0.5000f }, + { 0.2500f, 0.3750f, 0.5000f }, + { 0.0000f, 0.1500f, 0.3000f }, + { 0.1500f, 0.2250f, 0.3000f }, + { 0.0000f, 0.0750f, 0.1500f }, + { 0.0750f, 0.1125f, 0.1500f }, + { 0.0000f, 0.2500f, 1.0000f }, + { 0.5000f, 0.6250f, 1.0000f }, + { 0.0000f, 0.1625f, 0.6500f }, + { 0.3250f, 0.4063f, 0.6500f }, + { 0.0000f, 0.1250f, 0.5000f }, + { 0.2500f, 0.3125f, 0.5000f }, + { 0.0000f, 0.0750f, 0.3000f }, + { 0.1500f, 0.1875f, 0.3000f }, + { 0.0000f, 0.0375f, 0.1500f }, + { 0.0750f, 0.0938f, 0.1500f }, + { 0.0000f, 0.0000f, 1.0000f }, + { 0.5000f, 0.5000f, 1.0000f }, + { 0.0000f, 0.0000f, 0.6500f }, + { 0.3250f, 0.3250f, 0.6500f }, + { 0.0000f, 0.0000f, 0.5000f }, + { 0.2500f, 0.2500f, 0.5000f }, + { 0.0000f, 0.0000f, 0.3000f }, + { 0.1500f, 0.1500f, 0.3000f }, + { 0.0000f, 0.0000f, 0.1500f }, + { 0.0750f, 0.0750f, 0.1500f }, + { 0.2500f, 0.0000f, 1.0000f }, + { 0.6250f, 0.5000f, 1.0000f }, + { 0.1625f, 0.0000f, 0.6500f }, + { 0.4063f, 0.3250f, 0.6500f }, + { 0.1250f, 0.0000f, 0.5000f }, + { 0.3125f, 0.2500f, 0.5000f }, + { 0.0397f, 0.0000f, 0.3000f }, + { 0.1875f, 0.1500f, 0.3000f }, + { 0.0375f, 0.0000f, 0.1500f }, + { 0.0938f, 0.0750f, 0.1500f }, + { 0.5000f, 0.0000f, 1.0000f }, + { 0.7500f, 0.5000f, 1.0000f }, + { 0.3250f, 0.0000f, 0.6500f }, + { 0.4875f, 0.3250f, 0.6500f }, + { 0.2500f, 0.0000f, 0.5000f }, + { 0.3750f, 0.2500f, 0.5000f }, + { 0.1500f, 0.0000f, 0.3000f }, + { 0.2250f, 0.1500f, 0.3000f }, + { 0.0750f, 0.0000f, 0.1500f }, + { 0.1125f, 0.0750f, 0.1500f }, + { 0.7500f, 0.0000f, 1.0000f }, + { 0.8750f, 0.5000f, 1.0000f }, + { 0.4875f, 0.0000f, 0.6500f }, + { 0.5688f, 0.3250f, 0.6500f }, + { 0.3750f, 0.0000f, 0.5000f }, + { 0.4375f, 0.2500f, 0.5000f }, + { 0.2250f, 0.0000f, 0.3000f }, + { 0.2625f, 0.1500f, 0.3000f }, + { 0.1125f, 0.0000f, 0.1500f }, + { 0.1313f, 0.0750f, 0.1500f }, + { 1.0000f, 0.0000f, 1.0000f }, + { 1.0000f, 0.5000f, 1.0000f }, + { 0.6500f, 0.0000f, 0.6500f }, + { 0.6500f, 0.3250f, 0.6500f }, + { 0.5000f, 0.0000f, 0.5000f }, + { 0.5000f, 0.2500f, 0.5000f }, + { 0.3000f, 0.0000f, 0.3000f }, + { 0.3000f, 0.1500f, 0.3000f }, + { 0.1500f, 0.0000f, 0.1500f }, + { 0.1500f, 0.0750f, 0.1500f }, + { 1.0000f, 0.0000f, 0.7500f }, + { 1.0000f, 0.5000f, 0.8750f }, + { 0.6500f, 0.0000f, 0.4875f }, + { 0.6500f, 0.3250f, 0.5688f }, + { 0.5000f, 0.0000f, 0.3750f }, + { 0.5000f, 0.2500f, 0.4375f }, + { 0.3000f, 0.0000f, 0.2250f }, + { 0.3000f, 0.1500f, 0.2625f }, + { 0.1500f, 0.0000f, 0.1125f }, + { 0.1500f, 0.0750f, 0.1313f }, + { 1.0000f, 0.0000f, 0.5000f }, + { 1.0000f, 0.5000f, 0.7500f }, + { 0.6500f, 0.0000f, 0.3250f }, + { 0.6500f, 0.3250f, 0.4875f }, + { 0.5000f, 0.0000f, 0.2500f }, + { 0.5000f, 0.2500f, 0.3750f }, + { 0.3000f, 0.0000f, 0.1500f }, + { 0.3000f, 0.1500f, 0.2250f }, + { 0.1500f, 0.0000f, 0.0750f }, + { 0.1500f, 0.0750f, 0.1125f }, + { 1.0000f, 0.0000f, 0.2500f }, + { 1.0000f, 0.5000f, 0.6250f }, + { 0.6500f, 0.0000f, 0.1625f }, + { 0.6500f, 0.3250f, 0.4063f }, + { 0.5000f, 0.0000f, 0.1250f }, + { 0.5000f, 0.2500f, 0.3125f }, + { 0.3000f, 0.0000f, 0.0750f }, + { 0.3000f, 0.1500f, 0.1875f }, + { 0.1500f, 0.0000f, 0.0375f }, + { 0.1500f, 0.0750f, 0.0938f }, + { 0.3300f, 0.3300f, 0.3300f }, + { 0.4640f, 0.4640f, 0.4640f }, + { 0.5980f, 0.5980f, 0.5980f }, + { 0.7320f, 0.7320f, 0.7320f }, + { 0.8660f, 0.8660f, 0.8660f }, + { 1.0000f, 1.0000f, 1.0000f }, +}; + +int dxfVert::isEqual ( class dxfVert * other ) +// compares strictly (without epsilon) +{ + if ( color_index != other->color_index ) + return FALSE; + return sgCompareVec3 ( pos, other->pos, 0.0 ); + +} + +/*static void copy_vert ( dxfVert& dst, const dxfVert& src ) +{ + dst.color_index = src.color_index ; + sgCopyVec3 ( dst.pos, src.pos ) ; +}*/ + +static void add_tri ( const dxfVert* p, const dxfVert* q, const dxfVert* r ) +{ + facevert.add ( p ) ; + facevert.add ( q ) ; + facevert.add ( r ) ; + num_face ++; +} + +static void add_face ( void ) +{ + int num_vert = tempvert.getNum() ; + + if ( num_vert >= 4 ) //quad? + if ( tempvert.get(3)->isEqual ( tempvert.get(2) ) ) + // pseudo quad. + num_vert=3; + + if ( num_vert >= 3 ) + { + if ( num_vert >= 4 ) //quad? + { + add_tri ( tempvert.get(0), tempvert.get(1), tempvert.get(3) ) ; + add_tri ( tempvert.get(3), tempvert.get(1), tempvert.get(2) ) ; + } + else //triangle + { + add_tri ( tempvert.get(0), tempvert.get(1), tempvert.get(2) ) ; + } + } +} + +static void dxf_flush ( void ) +{ + int num_vert = tempvert.getNum() ; + if ( ent_type == ENT_LINE ) + { + if ( num_vert >= 2 ) + { + linevert.add( tempvert.get(0) ) ; + linevert.add( tempvert.get(1) ) ; + num_line ++; + } + } + else if ( ent_type == ENT_FACE ) + { + add_face () ; + } + else if ( ent_type == ENT_POLYLINE ) + { + mesh.flags = cflags; + meshvert.removeAll(); + mesh.size[0] = mesh.vlist[0]; + mesh.size[1] = mesh.vlist[1]; + } + else if ( ent_type == ENT_INSERT ) + { + if ( block_name != NULL ) + { + //block_name + ssgEntity* found = blocks -> getByName ( block_name ) ; + if ( found != NULL ) + { + //cvec + //scale_vec + //rot_angle + + sgMat4 mat, tmp; + sgVec3 axis = { 0.0f, 0.0f, 1.0f }; + sgMakeRotMat4 ( mat, rot_angle, axis ) ; + + sgMakeIdentMat4 ( tmp ) ; + sgScaleVec4 ( tmp[0], scale_vec[0] ); + sgScaleVec4 ( tmp[1], scale_vec[1] ); + sgScaleVec4 ( tmp[2], scale_vec[2] ); + sgPostMultMat4 ( mat, tmp ) ; + + sgMakeTransMat4 ( tmp, cvec ) ; + sgPostMultMat4 ( mat, tmp ) ; + + //printf("cvec(%.2f,%.2f,%.2f), scale(%.2f,%.2f,%.2f), rot(%.2f)\n", + // cvec[0], cvec[1], cvec[2], cvec[0], cvec[1], cvec[2], rot_angle ) ; + //found -> print ( stderr, "", 99 ); + + ssgTransform* block_tr = new ssgTransform ; + block_tr -> setName ( block_name ) ; + block_tr -> setTransform ( mat ) ; + block_tr -> addKid ( found ) ; + top_branch -> addKid ( block_tr ) ; + } + } + } + else if ( ent_type == ENT_VERTEX ) + { + if ( (mesh.flags & 8) != 0 ) + { + //This is a 3D Polyline + if ( (cflags & 32) != 0 ) + { + //This is a 3D Polyline vertex + meshvert.add ( tempvert.get(0) ) ; + } + } + else if ( (mesh.flags & 16) != 0 ) + { + //This is a 3D polygon MxN mesh. (uniform grid) + if ( (cflags & 64) != 0 ) + { + //This is a 3D polygon mesh vertex + meshvert.add ( tempvert.get(0) ) ; + } + } + else if ( (mesh.flags & 64) != 0 ) + { + //This Polyline is a polyface mesh. + if ( (cflags & 128) != 0 ) + { + if ( (cflags & 64) != 0 ) + { + //This is a 3D polygon mesh vertex + meshvert.add ( tempvert.get(0) ) ; + } + else if ( mesh.vnum >= 3 ) + { + //copy each vertex where the first is numbered 1 + tempvert.removeAll(); + int error = 0; + for ( int i=0; i 0 && ival <= meshvert.getNum() ) + tempvert.add ( meshvert.get(ival-1) ) ; + else + error = 1; + } + + if ( error == 0 ) + add_face () ; + } + } + } + } + + cflags = 0; + cvec[0] = 0.0f; + cvec[1] = 0.0f; + cvec[2] = 0.0f; + scale_vec[0] = 1.0f; + scale_vec[1] = 1.0f; + scale_vec[2] = 1.0f; + rot_angle = 0.0f; + color_index = 7 ; + + tempvert.removeAll(); + + mesh.vnum = 0 ; + mesh.vlist[0] = 0; + mesh.vlist[1] = 0; + mesh.vlist[2] = 0; + mesh.vlist[3] = 0; + + delete[] block_name; + block_name = NULL; +} + + +static void dxf_free () +{ + tempvert.removeAll(); + linevert.removeAll() ; + facevert.removeAll() ; + meshvert.removeAll() ; + + num_line = 0; + num_face = 0; + + ent_type = ENT_NONE; +} + + +static sgVec4& get_color ( int ci ) +{ + if ( ci < 0 ) + ci = 0 ; + else if ( ci > 255 ) + ci = 255 ; + float* rgb = dxf_colors[ci]; + static sgVec4 color ; + sgSetVec4 ( color, rgb[0], rgb[1], rgb[2], 1.0f ) ; + return color ; +} + + +static void dxf_create ( ssgBranch* br ) +{ + dxf_flush () ; + + //create ssg nodes + if ( num_face ) + { + int num_vert = facevert.getNum () ; + ssgVertexArray* vlist = new ssgVertexArray ( num_vert ) ; + ssgColourArray* clist = new ssgColourArray ( num_vert ) ; + ssgNormalArray* nlist = new ssgNormalArray ( num_vert ) ; + sgVec3 normal ; + for ( int i=0; i pos, + facevert.get(i+1) -> pos, + facevert.get(i+2) -> pos ) ; + } + + vlist -> add ( facevert.get(i) -> pos ) ; + nlist -> add ( normal ) ; + clist -> add ( get_color( facevert.get(i) -> color_index ) ) ; + } + ssgVtxTable *vtab = new ssgVtxTable ( GL_TRIANGLES, vlist, nlist, 0, clist ); + vtab -> setState ( current_state ) ; + br -> addKid ( vtab ) ; + } + + if ( num_line ) + { + int num_vert = linevert.getNum () ; + ssgVertexArray* vlist = new ssgVertexArray ( num_vert ) ; + ssgColourArray* clist = new ssgColourArray ( num_vert ) ; + for ( int i=0; i add ( linevert.get(i) -> pos ) ; + clist -> add ( get_color(linevert.get(i) -> color_index) ) ; + } + ssgVtxTable *vtab = new ssgVtxTable ( GL_LINES, vlist, 0, 0, clist ); + vtab -> setState ( current_state ) ; + br -> addKid ( vtab ) ; + } + + dxf_free () ; +} + + +static int dxf_read ( FILE *filein ) +{ + dxf_free () ; + +/* + Read the next two lines of the file into INPUT1 and INPUT2. +*/ + for ( ;; ) { + + int count; + int code; + int width; + char input1[MAX_LINE_LEN]; + char input2[MAX_LINE_LEN]; + +/* + INPUT1 should contain a single integer, which tells what INPUT2 + will contain. +*/ + if ( fgets ( input1, MAX_LINE_LEN, filein ) == NULL ) { + break; + } + + count = sscanf ( input1, "%d%n", &code, &width ); + if ( count <= 0 ) { + break; + } +/* + Read the second line, and interpret it according to the code. +*/ + if ( fgets ( input2, MAX_LINE_LEN, filein ) == NULL ) { + break; + } + + if ( code == 0 ) { + + dxf_flush () ; + + //set ent_type + if ( strncmp( input2, "LINE", 4 ) == 0 ) + ent_type = ENT_LINE ; + else if ( strncmp( input2, "3DFACE", 6 ) == 0 ) + ent_type = ENT_FACE ; + else if ( strncmp( input2, "POLYLINE", 8 ) == 0 ) + ent_type = ENT_POLYLINE ; + else if ( strncmp( input2, "VERTEX", 6 ) == 0 ) + ent_type = ENT_VERTEX; + else if ( strncmp( input2, "INSERT", 6 ) == 0 ) + ent_type = ENT_INSERT; + else if ( strncmp( input2, "BLOCK", 5 ) == 0 ) { + if ( current_block == NULL ) { + current_block = new ssgBranch ; + blocks -> addKid ( current_block ) ; + } + } + else if ( strncmp( input2, "ENDBLK", 6 ) == 0 ) { + if ( current_block != NULL ) { + dxf_create ( current_block ) ; + current_block = NULL ; + } + } + else if ( strncmp( input2, "SEQEND", 6 ) == 0 ) { + +#define PL_CLOSED_IN_M 0x01 +#define PL_CURVE_FIT_ADDED 0x02 +#define PL_SPLINE_FIT_ADDED 0x04 +#define PL_3D_POLYLINE 0x08 +#define PL_3D_MESH 0x10 +#define PL_CLOSED_IN_N 0x20 +#define PL_POLYFACE_MESH 0x40 +#define PL_USE_LINETYPE 0x80 + + int polyline_flags = mesh.flags ; + + if ( (polyline_flags & PL_3D_POLYLINE) != 0 ) { + + //This is a 3D Polyline + int last = 0; + int i = 1; + int num_vert = meshvert.getNum () ; + + if ( (polyline_flags & (PL_CLOSED_IN_M|PL_CLOSED_IN_N)) != 0 ) { + + //Polyline is closed + last = num_vert - 1; + i = 0; + } + + for ( ; i= ( mesh.size[0] * mesh.size[1] ) ) { + + int mesh_m = mesh.size[0]; + int mesh_n = mesh.size[1]; + + dxfVert *buff[2]; + buff[0] = meshvert.get(0); + buff[1] = meshvert.get(mesh_n); + + /* create triangles */ + int i,j; + for (i=1;igetName() == NULL ) { + char* name = ulStrDup ( input2 ) ; + current_block->setName( name ) ; + } + } + } + else if ( ch == '0' || ch == '1' || ch == '2' || ch == '3' ) { + + float rval; + count = sscanf ( input2, "%e%n", &rval, &width ); + + switch ( input1[cpos] ) + { + case '1': + cvec[0] = rval; + break; + + case '2': + cvec[1] = rval; + break; + + case '3': + cvec[2] = rval; + + { + dxfVert vert ; + vert.color_index = color_index ; + sgCopyVec3 ( vert.pos, cvec ) ; + + tempvert.add ( &vert ) ; + } + break; + } + } + } + else if ( input1[cpos] == '4' ) { + + float rval; + count = sscanf ( input2, "%e%n", &rval, &width ); + + switch ( input1[cpos+1] ) + { + case '1': + scale_vec[0] = rval; + break; + + case '2': + scale_vec[1] = rval; + break; + + case '3': + scale_vec[2] = rval; + break; + } + } + else if ( input1[cpos] == '5' ) { + + char ch = input1[cpos+1]; + if ( ch == '0' ) { + + count = sscanf ( input2, "%e%n", &rot_angle, &width ); + } + } + else if ( input1[cpos] == '6' ) { + + if ( input1[cpos+1] == '2' ) { + + count = sscanf ( input2, "%d%n", &color_index, &width ); + } + } + else if ( input1[cpos] == '7' ) { + + int ival ; + count = sscanf ( input2, "%d%n", &ival, &width ); + + switch ( input1[cpos+1] ) + { + case '0': + cflags = ival; + break; + + case '1': + mesh.vlist[0] = ival; + mesh.vnum = 1; + break; + + case '2': + mesh.vlist[1] = ival; + mesh.vnum = 2; + break; + + case '3': + mesh.vlist[2] = ival; + mesh.vnum = 3; + break; + + case '4': + mesh.vlist[3] = ival; + mesh.vnum = 4; + break; + } + } + } + } + + dxf_create ( top_branch ) ; + + return TRUE; +} + + +static ssgState *make_state () +{ + ssgSimpleState *st = new ssgSimpleState () ; + + sgVec4 spec = { 0.0f, 0.0f, 0.0f, 1.0f }; + sgVec4 emis = { 0.0f, 0.0f, 0.0f, 1.0f } ; + float shi = { 0.0f } ; + + st -> setMaterial ( GL_SPECULAR, spec ) ; + st -> setMaterial ( GL_EMISSION, emis ) ; + st -> setShininess ( shi ) ; + st -> enable ( GL_COLOR_MATERIAL ) ; + st -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + st -> enable ( GL_LIGHTING ) ; + st -> setShadeModel ( GL_SMOOTH ) ; + + st -> disable ( GL_BLEND ) ; + st -> setOpaque () ; + st -> disable( GL_TEXTURE_2D ) ; + + return st ; +} + + +ssgEntity *ssgLoadDXF ( const char *fname, const ssgLoaderOptions* options ) +{ + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + current_options = ssgGetCurrentOptions () ; + + top_branch = NULL ; + + char filename [ 1024 ] ; + current_options -> makeModelPath ( filename, fname ) ; + + FILE *loader_fd = fopen ( filename, "ra" ) ; + + if ( loader_fd == NULL ) + { + ulSetError ( UL_WARNING, "ssgLoadDXF: Failed to open '%s' for reading", filename ) ; + return NULL ; + } + + top_branch = new ssgTransform () ; + + blocks = new ssgBranch ; + current_state = make_state () ; + + blocks -> ref () ; + current_state -> ref () ; + + dxf_read ( loader_fd ) ; + + fclose ( loader_fd ) ; + + ssgDeRefDelete ( current_state ) ; + ssgDeRefDelete ( blocks ) ; + + return top_branch ; +} diff --git a/src/ssg/ssgLoadFLT.cxx b/src/ssg/ssgLoadFLT.cxx new file mode 100644 index 0000000..0a088d0 --- /dev/null +++ b/src/ssg/ssgLoadFLT.cxx @@ -0,0 +1,3173 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadFLT.cxx 2134 2008-09-29 18:44:27Z fayjf $ +*/ + +// +// $Id: ssgLoadFLT.cxx 2134 2008-09-29 18:44:27Z fayjf $ +// +// +// OpenFlight loader for SSG +// +// +// The loading of FLT files can to some degree be controlled by +// setting environment variables: +// +// FLTNOCLEAN - if set disables all kinds of scene graph optimisations +// FLTNOEXT - ignore external references +// FLTNOTEX - disables textures altogether +// FLTNOMIPMAP - configure textures for bilinear filtering (no mipmaps) +// +// +// Some known issues: +// +// 1. The color table in v14.0 and earlier is defined differently and +// cannot be parsed. It may consist of 16 colours of 16 brightnesses +// each, and the RGB values are passed as shorts. +// +// 2. Geometry in v11.0 and earlier are defined using obsolete records +// (opcodes 6, 7, 8 and 9). Need specifications to parse them. +// +// 3. How to find external files properly. Some loaders (most notably +// IRIS Performer and MultiGen) uses the variable FLTEXTERNPATH. +// (MultiGen also uses FLTPATH and TXTPATH I think). +// +// 4. How to do mmap on Mac and PS2. +// +// 5. No optimisations are done on the geometry. New triangle strip +// generation code planned for SSG, and should be used when ready. +// +// 6. Optimisation done on the scene graph level are minimal. +// +// +// +/* + * Another OpenFlight loader for Performer + * Copyright (C) 1998-2000 Marten Stromberg + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "ssg.h" +#include "ssgLoaderWriterStuff.h" + +/* define this to compile against older versions of SSG */ +/*#define NO_LOADER_OPTIONS*/ + +/* debug */ +/*#define NO_LIGHTING*/ +/*#define NO_TEXTURES*/ +/*#define NO_COLORS*/ + +/* Try to figure out how to do mmap. */ +#ifdef UL_WIN32 +# define USE_WIN32_MMAP +#else +# include +# ifdef _POSIX_MAPPED_FILES +# define USE_POSIX_MMAP +# endif +#endif + +#include +#include +#include +#include +#ifdef UL_IRIX +# include +#endif +#ifdef USE_POSIX_MMAP +# include +# include /* Need both for Mandrake 8.0 !! */ +# include +# include +#endif +#ifdef UL_MSVC +# include +#endif + + +#ifndef O_BINARY +# define O_BINARY 0 +#endif + +#ifndef R_OK +# define R_OK 4 +#endif + +#ifndef ABS +# define ABS(x) ((x)>=0?(x):-(x)) +#endif +#ifndef MIN +# define MIN(a,b) ((a)<=(b)?(a):(b)) +#endif +#ifndef MAX +# define MAX(a,b) ((a)>=(b)?(a):(b)) +#endif +#define MIN3(a,b,c) ((a)<=(b)?MIN(a,c):MIN(b,c)) +#define MAX3(a,b,c) ((a)>=(b)?MAX(a,c):MAX(b,c)) +#define CLAMP(x,lo,hi) ((x)<=(lo)?(lo):(x)>=(hi)?(hi):(x)) + +#define template _template /* trams */ + +typedef unsigned char ubyte; + +#if defined(UL_WIN32) || defined(UL_MAC_OSX) +typedef unsigned short ushort; +typedef unsigned int uint; +#endif + +// 525 = negative identation, 539= did not expect positive identation +//lint -save -e525 -e539 + +/* + * byte sex + */ + +/* XXX what about PDP_ENDIAN? */ + +/* Help! Is this correct? */ +#if (!defined(BYTE_ORDER) && defined(UL_WIN32) && !defined(NOT_INTEL_BYTE_ORDER)) +# define LITTLE_ENDIAN 1234 +# define BIG_ENDIAN 4321 +# define BYTE_ORDER LITTLE_ENDIAN +#endif + +/* #undef BYTE_ORDER */ + +#if !defined(BYTE_ORDER) || BYTE_ORDER != BIG_ENDIAN + +#if !defined(BYTE_ORDER) +static void _swab16(const void *src, void *dst, int n) +{ + ushort *s = (ushort *)src; + ushort *d = (ushort *)dst; + while (n--) { + ushort t = *s++; + *d++ = (((t & 0xff00U) >> 8) | + ((t & 0x00ffU) << 8)); + } +} +#endif + +static void _swab32(const void *src, void *dst, int n) +{ + uint *s = (uint *)src; + uint *d = (uint *)dst; + while (n--) { + uint t = *s++; + *d++ = (((t & 0xff000000U) >> 24) | + ((t & 0x00ff0000U) >> 8) | + ((t & 0x0000ff00U) << 8) | + ((t & 0x000000ffU) << 24)); + } +} + +static void _swab64(const void *src, void *dst, int n) +{ + /* XXX how to check if 64-bit integers are available?? */ + uint *s = (uint *)src; + uint *d = (uint *)dst; + while (n--) { + uint t0 = *s++; + uint t1 = *s++; + *d++ = (((t1 & 0xff000000U) >> 24) | + ((t1 & 0x00ff0000U) >> 8) | + ((t1 & 0x0000ff00U) << 8) | + ((t1 & 0x000000ffU) << 24)); + *d++ = (((t0 & 0xff000000U) >> 24) | + ((t0 & 0x00ff0000U) >> 8) | + ((t0 & 0x0000ff00U) << 8) | + ((t0 & 0x000000ffU) << 24)); + } +} + +#endif + +#if !defined(BYTE_ORDER) || BYTE_ORDER != LITTLE_ENDIAN + +static void _copy16(const void *src, void *dst, int n) +{ + memcpy(dst, src, 2*n); +} + +static void _copy32(const void *src, void *dst, int n) +{ + memcpy(dst, src, 4*n); +} + +static void _copy64(const void *src, void *dst, int n) +{ + memcpy(dst, src, 8*n); +} + +#endif + + +#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN + +/* big endian */ + +inline uint get16u(const void *ptr) +{ + return *(ushort *)ptr; +} + +inline uint get32u(const void *ptr) +{ + return *(uint *)ptr; +} + +#define get16v _copy16 +#define get32v _copy32 +#define get64v _copy64 + +#elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN + +/* little endian */ + +inline uint get16u(const void *ptr) +{ + ushort tmp = *(ushort *)ptr; + return (((tmp & 0xff00U) >> 8) | + ((tmp & 0x00ffU) << 8)); +} + +inline uint get32u(const void *ptr) +{ + uint tmp = *(uint *)ptr; + return (((tmp & 0xff000000U) >> 24) | + ((tmp & 0x00ff0000U) >> 8) | + ((tmp & 0x0000ff00U) << 8) | + ((tmp & 0x000000ffU) << 24)); +} + +#define get16v _swab16 +#define get32v _swab32 +#define get64v _swab64 + +#else + +/* any endian */ + +inline uint get16u(const void *ptr) +{ + ubyte *u = (ubyte *)ptr; + return (((uint)u[0] << 8) | + ((uint)u[1] << 0)); +} + +inline uint get32u(const void *ptr) +{ + ubyte *u = (ubyte *)ptr; + return (((uint)u[0] << 24) | + ((uint)u[1] << 16) | + ((uint)u[2] << 8) | + ((uint)u[3] << 0)); +} + +static void (*get16v)(const void *, void *, int); +static void (*get32v)(const void *, void *, int); +static void (*get64v)(const void *, void *, int); + +#define PROBE_ENDIAN 1 + +#endif + +#define get16i(ptr) (short)get16u(ptr) +#define get32i(ptr) (int)get32u(ptr) + + +/* splay trees + * + * for further details, see "Self-adjusting Binary Search Trees" + * by Sleator and Tarjan, JACM Volume 32, No 3, July 1985, pp 652-686. + */ + +struct snode { + struct snode *left, *right; + void *key; + void *data; +}; + +typedef int (*sfunc)(const void *key1, const void *key2); + +static struct snode *splay(struct snode *t, const void *key, sfunc comp) +{ + struct snode N, *l, *r, *y; + + if (t == NULL) return t; + N.left = N.right = NULL; + l = r = &N; + + for (;;) { + if (comp(key, t->key) < 0) { + if (t->left == NULL) break; + if (comp(key, t->left->key) < 0) { + y = t->left; /* rotate right */ + t->left = y->right; + y->right = t; + t = y; + if (t->left == NULL) break; + } + r->left = t; /* link right */ + r = t; + t = t->left; + } + else if (comp(key, t->key) > 0) { + if (t->right == NULL) break; + if (comp(key, t->right->key) > 0) { + y = t->right; /* rotate left */ + t->right = y->left; + y->left = t; + t = y; + if (t->right == NULL) break; + } + l->right = t; /* link left */ + l = t; + t = t->right; + } + else { + break; + } + } + + l->right = t->left; /* assemble */ + r->left = t->right; + t->left = N.right; + t->right = N.left; + + return t; +} + +static struct snode *sinsert(struct snode *root, void *key, size_t size, sfunc comp) +{ + struct snode *t, *x; + t = splay(root, key, comp); + if (t != NULL && comp(t->key, key) == 0) + return t; + //x = (struct snode *)malloc(sizeof(struct snode)); + x = new snode; + assert( x != NULL ); + if (t == NULL) { + x->left = x->right = NULL; + } + else if (comp(key, t->key) < 0) { + x->left = t->left; + x->right = t; + t->left = NULL; + } + else { + x->right = t->right; + x->left = t; + t->right = NULL; + } + if (size > 0) { + //x->key = malloc(size); + x->key = new ubyte[size]; + memcpy(x->key, key, size); + } + else { + x->key = key; + } + x->data = (void *)-1; + return x; +} + +#define S_KEY 1 /* free key */ +#define S_DATA 2 /* free data */ +#define S_TREE 4 /* delete scene graph (SSG special) */ + +static void deltree(ssgEntity *node) +{ + if (node->getRef() <= 1 && node->isAKindOf(ssgTypeBranch())) { + ssgBranch *grp = (ssgBranch *)node; + int n = grp->getNumKids(); + while (n--) { + deltree(grp->getKid(n)); + grp->removeKid(n); // delete kid (iff ref == 0) + } + } +} + +static void sfree(struct snode *x, int flags) +{ + if (x) { + sfree(x->left, flags); + sfree(x->right, flags); + if ((flags & S_KEY)) + //free(x->key); + delete [] (ubyte *)x->key; + if (x->data != (void *)-1 && x->data != 0) { + if ((flags & S_DATA)) + //free(x->data); + delete [] (ubyte *)x->data; + if ((flags & S_TREE)) { + deltree((ssgEntity *)x->data); + ssgDeRefDelete((ssgEntity *)x->data); + } + } + } +} + +static int ptrcmp(const void *key1, const void *key2) +{ + return (const char *)key1 - (const char *)key2; +} + + +static void hexdump(enum ulSeverity severity, const ubyte *buf, int size, int offset) +{ +#define COLS 16 + char line[1024], *lp; + while (size > 0) { + int i, n = MIN(size, COLS); + lp = line; + lp += sprintf(lp, "%04x ", offset); + for (i = 0; i < n; i++) + lp += sprintf(lp, " %02x", buf[i]); + for (; i < COLS; i++) + lp += sprintf(lp, " "); + *lp++ = ' '; + *lp++ = ' '; + for (i = 0; i < n; i++) + *lp++ = (buf[i] & 0x7f) < 0x20 ? '.' : buf[i]; + *lp = 0; + ulSetError(severity, line); + buf += COLS; + offset += COLS; + size -= COLS; + } +} + + + +#define MAXDEPTH 256 + +#define UNPACK_ABGR(dst, src) \ + ((dst)[0] = (1.0f/255.0f)*(src)[3], \ + (dst)[1] = (1.0f/255.0f)*(src)[2], \ + (dst)[2] = (1.0f/255.0f)*(src)[1], \ + (dst)[3] = 1.0f) + +#define UNPACK_ABGR2(dst, src, intensity) \ + ((dst)[0] = (1.0f/255.0f/127.0f)*(src)[3]*(intensity), \ + (dst)[1] = (1.0f/255.0f/127.0f)*(src)[2]*(intensity), \ + (dst)[2] = (1.0f/255.0f/127.0f)*(src)[1]*(intensity), \ + (dst)[3] = 1.0f) + +/* triangle flags */ +#define TRI_COLOR_MATERIAL 0x01 /* --> apply material on vertex colors */ +#define TRI_TRANSLUCENT 0x02 +#define TRI_SUBFACE 0x04 /* offset geometry */ +#define TRI_BBOARD_AXIAL 0x08 +#define TRI_BBOARD_POINT 0x10 +/*#define TRI_WIREFRAME 0x20*/ +#define TRI_BBOARD (TRI_BBOARD_AXIAL | TRI_BBOARD_POINT) + +/* vertex bind */ +#define BIND_COLOR 0x01 +#define BIND_NORMAL 0x02 +#define BIND_TEXCOORD 0x04 +#define BIND_FLAT_COLOR 0x08 +#define BIND_FLAT_NORMAL 0x10 +#define BIND_FLAT (BIND_FLAT_COLOR | BIND_FLAT_NORMAL) + +struct fltTriangle { + + ssgState *state; + + ubyte flags; + ubyte bind; + +#if 0 + short priority; /* affects the ordering within the geoset */ + ushort transparency; /* eventually applied to colors when done */ +#endif + + int index[3]; + sgVec4 color; /* face color *or* material contributions to vertex colors */ + +}; + +struct fltTexture { + char *file; + ssgState *state; /* user-defined state */ + ssgTexture *tex; + int alpha; +}; + +struct fltState { + + fltState() { + memset(this, 0, sizeof(*this)); + notex_state = (ssgState *)-1; + atris = 256; + //tris = (fltTriangle *)malloc(sizeof(fltTriangle) * atris); + tris = new fltTriangle[atris]; + } + + ~fltState() { + sfree(texs, S_DATA); + sfree(mtls, S_DATA); + sfree(refs, S_TREE); + if (vtab) { + delete [] offset; + delete [] bind; + delete [] coord; + delete [] color; + delete [] normal; + delete [] texcoord; + } + //free(tris); + delete [] tris; + } + + const char *filename; + int revision; + int major; + int minor; + + /* Vertex Table */ + ubyte *vtab; /* start of vertex table */ + int vnum; + int *offset; /* chunk offset (used as index) */ + ubyte *bind; /* 1 - color, 2 - normal, 4 - texcoord */ + sgVec3 *coord; + sgVec4 *color; + sgVec3 *normal; + sgVec2 *texcoord; + + /* Other Tables (these may be sparse, that is why arrays are not used) */ + struct snode *mtls; /* index --> float[14] */ + struct snode *texs; /* index --> fltTexture */ + struct snode *refs; /* index --> ssgEntity */ + ubyte (*ctab)[4]; /* packed ABGR color table */ + int cnum; + ssgState *notex_state; /* special user-defined state if no texture */ + + /* Collected Geometry */ + fltTriangle *tris; + int ntris, atris; + fltTriangle *temp; + char *parent_name; +}; + +struct fltNodeAttr { + + /* allocated using new/delete for convenience */ + fltNodeAttr() { + memset(this, 0, sizeof(*this)); + } + ~fltNodeAttr() { + if (name) delete name; + if (mask_words) delete mask_words; + } + + /* properies that are not applied immediately */ + + char *name; + + int replicate; + int transform; + int islod; + + sgMat4 mat; + sgVec2 range; + sgVec3 center; + + /* switch record info */ + int num_masks; + int num_words; + uint *mask_words; + int current_mask; + +}; + +static int Inited = 0; +static int NoTextures = 0; +static int NoMipmaps = 0; +static int NoExternals = 0; +static int NoClean = 0; + +#ifndef NO_LOADER_OPTIONS +static ssgLoaderOptions *LoaderOptions; +#endif + +static struct snode *TexCache; /* filename --> fltTexture */ + +static fltTexture *LoadTex(char *fname) +{ + TexCache = sinsert(TexCache, fname, strlen(fname) + 1, (sfunc)strcmp); + if (TexCache->data == (void *)-1) { + //fltTexture *tex = (fltTexture *)malloc(sizeof(fltTexture)); + fltTexture *tex = new fltTexture; + assert ( tex != NULL ); + tex->file = fname; +#ifdef NO_LOADER_OPTIONS + tex->state = 0; + tex->tex = new ssgTexture(fname, 1, 1, !NoMipmaps); +#else + tex->state = LoaderOptions->createState(fname); + tex->tex = tex->state ? 0 : LoaderOptions->createTexture(fname, 1, 1, !NoMipmaps); +#endif + tex->alpha = tex->tex ? tex->tex->hasAlpha() : 0; + TexCache->data = tex; + } + return (fltTexture *)TexCache->data; +} + +struct StateInfo { + int cf; /* cull face */ + int tr; /* translucent */ + int cm; /* color material */ + ssgTexture *tex; + float *mtl; + float alpha; +}; + +static int StateCompare(const void *key1, const void *key2) +{ + const StateInfo *s1 = (const StateInfo *)key1; + const StateInfo *s2 = (const StateInfo *)key2; + int d; + d = s1->cf - s2->cf; + if (d == 0) { + d = s1->tr - s2->tr; + if (d == 0) { + d = s1->cm - s2->cm; + if (d == 0) { + d = (char *)s1->tex - (char *)s2->tex; + if (d == 0) { + if (s1->mtl == 0 || s2->mtl == 0) + d = (char *)s1->mtl - (char *)s2->mtl; + else { + int i = s1->cm ? 6 : 0; + for (; i < 12 && d == 0; i++) + if (s1->mtl[i] < s2->mtl[i] - 0.01f) + d = -1; + else if (s1->mtl[i] > s2->mtl[i] + 0.01f) + d = 1; + if (d == 0) { + if (s1->alpha < s2->alpha - 0.01f) + d = -1; + else if (s1->alpha > s2->alpha + 0.01f) + d = 1; + } + } + } + } + } + } + return d; +} + +static struct snode *StateCache; /* StateInfo --> ssgSimpleState */ + +static ssgSimpleState *ConstructState(StateInfo *key) +{ + StateCache = sinsert(StateCache, key, sizeof(StateInfo), StateCompare); + if (StateCache->data == (void *)-1) { + ssgSimpleState *s; + + /*ulSetError(UL_DEBUG, "new state --");*/ + + s = new ssgSimpleState; + + if (key->cf) { + s->enable(GL_CULL_FACE); + } + else { + s->disable(GL_CULL_FACE); + /*ulSetError(UL_DEBUG, " two-sided");*/ + } + + if (key->tr) { + s->setTranslucent(); + s->enable(GL_BLEND); /* XXX what about multisampling? */ + /*ulSetError(UL_DEBUG, " transparent");*/ + } + else { + s->setOpaque(); + s->disable(GL_BLEND); + } + /* leave the alpha test to the application */ + + if (key->mtl) { + float *m = key->mtl; + sgVec4 c; + /*ulSetError(UL_DEBUG, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %d", + m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], key->cm);*/ + if (key->cm) { + s->enable(GL_COLOR_MATERIAL); + s->setColourMaterial(GL_AMBIENT_AND_DIFFUSE); + //ulSetError(UL_DEBUG, " color material"); + } + else { + s->disable(GL_COLOR_MATERIAL); + sgSetVec4(c, m[0], m[1], m[2], key->alpha); s->setMaterial(GL_AMBIENT, c); + sgSetVec4(c, m[3], m[4], m[5], key->alpha); s->setMaterial(GL_DIFFUSE, c); + //ulSetError(UL_DEBUG, " ambient %.2f %.2f %.2f", m[0], m[1], m[2]); + //ulSetError(UL_DEBUG, " diffuse %.2f %.2f %.2f", m[3], m[4], m[5]); + } + sgSetVec4(c, m[6], m[7], m[8], key->alpha); s->setMaterial(GL_SPECULAR, c); + sgSetVec4(c, m[9], m[10], m[11], key->alpha); s->setMaterial(GL_EMISSION, c); + //ulSetError(UL_DEBUG, " specular %.2f %.2f %.2f", m[6], m[7], m[8]); + //ulSetError(UL_DEBUG, " emission %.2f %.2f %.2f", m[9], m[10], m[11]); + //ulSetError(UL_DEBUG, " alpha %.2f", key->alpha); + s->setShininess(m[12]); + s->enable(GL_LIGHTING); + } + else { + s->disable(GL_LIGHTING); + /*ulSetError(UL_DEBUG, " no lighting");*/ + } + + if (key->tex) { + s->enable(GL_TEXTURE_2D); + s->setTexture(key->tex); + /*ulSetError(UL_DEBUG, " texture %s", key->tex->getFilename());*/ + } + else { + s->disable(GL_TEXTURE_2D); + } + + s->setShadeModel(GL_SMOOTH); + + s->ref(); + + StateCache->data = s; + } + return (ssgSimpleState *)StateCache->data; +} + +static int tricmp(const void *a, const void *b) +{ + /* this comparison is used to sort the list of triangles in order to + * generate as few geosets as possible. + */ + fltTriangle *ta = (fltTriangle *)a; + fltTriangle *tb = (fltTriangle *)b; + int d = (char *)ta->state - (char *)tb->state; + if (d == 0) { + d = ta->flags - tb->flags; + if (d == 0) + d = ta->bind - tb->bind; + } + return d; +} + +#if 0 /* no longer needed since this is now the default blend equation */ +static int PreDrawTranslucent(ssgEntity *) +{ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + return 1; +} +#endif + +static int PreDrawSubface(ssgEntity *) +{ +#ifdef GL_VERSION_1_1 + glPolygonOffset(-2.0f, -1.0f); + glEnable(GL_POLYGON_OFFSET_FILL); +#else + glPolygonOffsetEXT(-0.1f, -0.002f); + glEnable(GL_POLYGON_OFFSET_EXT); +#endif + return 1; +} + +static int PostDrawSubface(ssgEntity *) +{ +#ifdef GL_VERSION_1_1 + glDisable(GL_POLYGON_OFFSET_FILL); +#else + glDisable(GL_POLYGON_OFFSET_EXT); +#endif + return 1; +} + +/* convert a list of triangles to geosets using the pfdMesher + * need a seperate geostate for each comb of tex/mtl/bind + */ +static ssgEntity *Build(fltState *state) +{ + /*const char t[9] = "plsTQSfFP";*/ + ssgBranch *grp = 0; + ssgCutout *bboard1 = 0; + ssgCutout *bboard2 = 0; + ssgLeaf *leaf = 0; + fltTriangle *arr; + int num, i, j, k, m, n; + + //int *index; + //int *vertex; + + arr = state->tris; + num = state->ntris; + state->ntris = 0; + if (num == 0) + return 0; + + /* sort the triangles (put them in bins according to their attributes) + * one geoset will be generated for each such bin + */ + qsort(arr, num, sizeof(fltTriangle), tricmp); + + int *index = new int [ state->vnum ]; + int *vertex = new int [ 32768 ]; + + for (i = 0; i < num; ) { + + ssgVertexArray *va; + ssgColourArray *ca = 0; + ssgNormalArray *na = 0; + ssgTexCoordArray *ta = 0; + ssgVtxTable *geom; + + int flags = arr[i].flags; + int bind = arr[i].bind; + + /* see how many tris that belong to this group */ + for (j = i + 1; (j < num && + arr[j].state == arr[i].state && + arr[j].flags == flags && + arr[j].bind == bind + ); j++) + ; + /*fprintf(stderr, " %d", j - i);*/ + + /* simply construct a triangle soup */ + /* XXX fixme! */ + + if ((bind & BIND_FLAT) || (flags & TRI_COLOR_MATERIAL)) { + + n = 3*(j - i); + + va = new ssgVertexArray(n); + for (k = i; k < j; k++) { + va->add(state->coord[arr[k].index[0]]); + va->add(state->coord[arr[k].index[1]]); + va->add(state->coord[arr[k].index[2]]); + } + + if ((bind & BIND_FLAT_COLOR)) { + ca = new ssgColourArray(n); + for (k = i; k < j; k++) { + ca->add(arr[k].color); + ca->add(arr[k].color); + ca->add(arr[k].color); + } + } + else if ((bind & BIND_COLOR)) { + ca = new ssgColourArray(n); + if ((flags & TRI_COLOR_MATERIAL)) { + for (k = i; k < j; k++) { + for (m = 0; m < 3; m++) { + sgVec4 color; + float *mtl_color = arr[k].color; + float *vtx_color = state->color[arr[k].index[m]]; + color[0] = mtl_color[0] * vtx_color[0]; + color[1] = mtl_color[1] * vtx_color[1]; + color[2] = mtl_color[2] * vtx_color[2]; + color[3] = mtl_color[3] * vtx_color[3]; + ca->add(color); + } + } + } + else { + for (k = i; k < j; k++) { + ca->add(state->color[arr[k].index[0]]); + ca->add(state->color[arr[k].index[1]]); + ca->add(state->color[arr[k].index[2]]); + } + } + } + else if ((flags & TRI_TRANSLUCENT)) { + ca = new ssgColourArray(1); + ca->add(arr[i].color); + } + + if ((bind & BIND_FLAT_NORMAL)) { + na = new ssgNormalArray(n); + for (k = i; k < j; k++) { + sgVec3 a, b, normal; + int *w = arr[k].index; + sgSubVec3(a, state->coord[w[1]], state->coord[w[0]]); + sgSubVec3(b, state->coord[w[2]], state->coord[w[0]]); + sgVectorProductVec3(normal, a, b); + sgNormalizeVec3(normal); + na->add(normal); + na->add(normal); + na->add(normal); + } + } + else if ((bind & BIND_NORMAL)) { + na = new ssgNormalArray(n); + for (k = i; k < j; k++) { + na->add(state->normal[arr[k].index[0]]); + na->add(state->normal[arr[k].index[1]]); + na->add(state->normal[arr[k].index[2]]); + } + } + + if ((bind & BIND_TEXCOORD)) { + ta = new ssgTexCoordArray(n); + for (k = i; k < j; k++) { + ta->add(state->texcoord[arr[k].index[0]]); + ta->add(state->texcoord[arr[k].index[1]]); + ta->add(state->texcoord[arr[k].index[2]]); + } + } + + geom = new ssgVtxTable(GL_TRIANGLES, va, na, ta, ca); + + } + else { + + ssgIndexArray *ia = new ssgIndexArray(3*(j - i)); + + memset(index, -1, sizeof(index[0]) * state->vnum); + n = 0; + for (k = i; k < j; k++) { + int *tri = arr[k].index; + int save = n; + for (m = 0; m < 3; m++) { + if (index[tri[m]] == -1) { + if (n == 65536) { + ulSetError(UL_DEBUG, "[flt] More than 65536 vertices, split forced."); + n = save; + j = k; + //goto hopp; + break; + } + vertex[n] = tri[m]; + index[tri[m]] = n++; + } + ia->add((short)index[tri[m]]); + } + if (m < 3) break; + } + //hopp: + + va = new ssgVertexArray(n); + for (k = 0; k < n; k++) + va->add(state->coord[vertex[k]]); + + if ((bind & BIND_COLOR)) { + ca = new ssgColourArray(n); + for (k = 0; k < n; k++) + ca->add(state->color[vertex[k]]); + } + else if ((flags & TRI_TRANSLUCENT)) { + ca = new ssgColourArray(1); + ca->add(arr[i].color); + } + + if ((bind & BIND_NORMAL)) { + na = new ssgNormalArray(n); + for (k = 0; k < n; k++) + na->add(state->normal[vertex[k]]); + } + + if ((bind & BIND_TEXCOORD)) { + ta = new ssgTexCoordArray(n); + for (k = 0; k < n; k++) + ta->add(state->texcoord[vertex[k]]); + } + + if (n == 3*(j - i)) { + + delete ia; + + geom = new ssgVtxTable(GL_TRIANGLES, va, na, ta, ca); + } + else { + + geom = new ssgVtxArray(GL_TRIANGLES, va, na, ta, ca, ia); + } + + } + + geom->setState(arr[i].state); + + /*ulSetError(UL_DEBUG, "build: [%d..%d] %02x %d indices, %d vertices", + i, j - 1, bind, + 3*(j - i), n);*/ + + if (leaf) { + if (grp == 0) + grp = new ssgBranch; + grp->addKid(leaf); + } + + leaf = geom; + +#if 0 + if ((flags & TRI_TRANSLUCENT)) { + leaf->setCallback(SSG_CALLBACK_PREDRAW, PreDrawTranslucent); + } + else +#endif + if ((flags & TRI_SUBFACE)) { + leaf->setCallback(SSG_CALLBACK_PREDRAW, PreDrawSubface); + leaf->setCallback(SSG_CALLBACK_POSTDRAW, PostDrawSubface); + } + +#ifndef NO_LOADER_OPTIONS + leaf = LoaderOptions->createLeaf(leaf, state->parent_name); +#endif + + if ((flags & TRI_BBOARD)) { + if ((flags & TRI_BBOARD_AXIAL)) { + if (bboard1 == 0) + bboard1 = new ssgCutout(0); + bboard1->addKid(leaf); + } + else { + if (bboard2 == 0) + bboard2 = new ssgCutout(1); + bboard2->addKid(leaf); + } + leaf = 0; + } + + i = j; + } + + delete [] vertex; + delete [] index; + + if (((leaf != 0) + (bboard1 != 0) + (bboard2 != 0)) > 1 && !grp) //lint !e514 Lint warning "unusual use of a boolean" + grp = new ssgBranch; + + if (grp) { + if (bboard1) + grp->addKid(bboard1); + if (bboard2) + grp->addKid(bboard2); + if (leaf) + grp->addKid(leaf); + return grp; + } + + if (bboard1) + return bboard1; + + if (bboard2) + return bboard2; + + return leaf; +} + +/* add a triangle */ +static void AddTri(fltState *state, int v0, int v1, int v2) +{ + fltTriangle *tri; + if (state->ntris == state->atris) { + state->atris += state->atris; + //state->tris = (fltTriangle *)realloc(state->tris, sizeof(fltTriangle) * state->atris); + fltTriangle *old = state->tris; + state->tris = new fltTriangle[state->atris]; + memcpy(state->tris, old, sizeof(fltTriangle) * state->atris / 2); + delete [] old; + } + tri = state->tris + state->ntris++; + memcpy(tri, state->temp, sizeof(fltTriangle)); + tri->index[0] = v0; + tri->index[1] = v1; + tri->index[2] = v2; +} + +static void Triangulate(int *w, int n, fltState *state) +{ + int buf[3 * (16 - 2)]; + int *tris = (n > 16) ? new int [ 3 * (n - 2) ] : buf; + int num_tris = _ssgTriangulate(state->coord, w, n, tris); + for (int i = 0; i < num_tris; i++) + AddTri(state, tris[3*i + 0], tris[3*i + 1], tris[3*i + 2]); + if (tris != buf) + delete [] tris; +} + +static int ObsoleteFlag; +static int NotImplementedFlag; + +static void Obsolete(int op) +{ + if (!ObsoleteFlag) { + ulSetError(UL_WARNING, "[flt] This file is probably rather old (obsolete opcodes ignored)."); + ObsoleteFlag = 1; + } + //printf("op %d obsolete\n", op); +} + +static void NotImplemented(int op) +{ + if (!NotImplementedFlag) { + ulSetError(UL_WARNING, "[flt] This file contains opcodes that are not implemented."); + NotImplementedFlag = 1; + } + //printf("op %d not implemented\n", op); +} + +static void ReportBadChunk(const ubyte *ptr, const char *name) +{ + int op = get16u(ptr); + int len = get16u(ptr + 2); + ulSetError(UL_WARNING, "[flt] Bad record, opcode %d (%s), length %d:", op, name, len); + hexdump(UL_WARNING, ptr, len, 0); + ulSetError(UL_WARNING, "Please report this, either at http://plib.sourceforge.net/,"); + ulSetError(UL_WARNING, "or by email to plib-devel@lists.sourceforge.net. Thanks."); +} + +#define BAD_CHUNK(ptr, name)\ + do {\ + static int first = 1;\ + if (first) {\ + ReportBadChunk(ptr, name);\ + first = 0;\ + }\ + } while (0) + +static int intcmp(const void *a, const void *b) +{ + return *(int *)a - *(int *)b; +} + +/* polygon chunks */ +static int GeomChunks(ubyte *ptr0, ubyte *end, fltState *state, ssgEntity **nodep, int objflags, int objtrans) +{ + ubyte *ptr = ptr0; + int sp = 0, op, len, done = 0, triflg = 0; + int w[512]; /* enough? */ + fltTriangle tri; + StateInfo info; + int subface = 0; + char long_id[256] = {0}; + + state->temp = &tri; + memset(&tri, 0, sizeof(tri)); + + /* read as many polygon chunks as possible. + * can be done since objects may not contain groups. + * color table etc should also be defined before any polygon. + * (the purpose is to keep the switch(op) relatively small to speed up this "inner loop") + */ + + do { + + if (ptr + 4 > end) + break; + op = get16u(ptr); + len = get16u(ptr+2); + if (len < 4 || (len & 3) != 0 || ptr + len > end) + break; + + switch (op) { + + case 5: { /* Face (appearence) */ + + /* + * Face Record Format + * + * Int 0 2 Face Opcode 5 + * Unsigned 2 2 Length of the record + * Char 4 8 7 char ASCII ID; 0 terminates + * Int 12 4 IR color code + * Int 16 2 Relative priority + * Int 18 1 Draw type + * 0 = Draw solid with backface culling + * 1 = Draw solid, no backface culling + * 2 = Draw wireframe + * 3 = Draw wireframe and close + * 4 = Surround with wireframe in alternate color + * 8 = Omnidirectional light + * 9 = Unidirectional light + * 10 = Bidirectional light + * Int 19 1 Texture white = if TRUE, draw textured face white + * Unsigned 20 2 Color name index + * Unsigned 22 2 Alternate color name index + * Int 24 1 Reserved + * Int 25 1 Template (billboard) + * 0 = Fixed, no alpha blending + * 1 = Fixed, alpha blending + * 2 = Axial rotate + * 4 = Point rotate + * Int 26 2 Detail texture pattern index, -1 if none + * Int 28 2 Texture pattern index, -1 if none + * Int 30 2 Material index, -1 if none + * Int 32 2 Surface material code (for DFAD) + * Int 34 2 Feature ID (for DFAD) + * Int 36 4 IR material code + * Unsigned 40 2 Transparency 0 = Opaque 65535 = Totally clear + * Unsigned 42 1 LOD generation control + * Unsigned 43 1 Line style index + * Boolean 44 4 Flags (bits from left to right) + * 0 = Terrain + * 1 = No color + * 2 = No alternate color + * 3 = Packed color + * 4 = Terrain culture cutout (footprint) + * 5 = Hidden, not drawn + * 6-31 = Spare + * Unsigned 48 1 Light mode + * 0 = Use face color, not illuminated + * 1 = Use vertex colors, not illuminated + * 2 = Use face color and vertex normal + * 3 = Use vertex color and vertex normal + * Unsigned 49 1 Reserved + * Unsigned 50 2 Reserved + * Boolean 52 4 Reserved + * Unsigned 56 4 Packed color, primary (A, B, G, R) + * Unsigned 60 4 Packed color, alternate (A, B, G, R) + * Int 64 2 Texture mapping index + * Int 66 2 Reserved + * Unsigned 68 4 Primary color index + * Unsigned 72 4 Alternate color index + * Int 76 2 Reserved + * Int 78 2 Reserved + * + */ + + static float default_mtl[14] = { + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, + 8.0f, 1.0f + }; + int flags = len < 48 ? 0 : get32i(ptr + 44); + int drawtype = ptr[18]; + + if (drawtype > 4 || (flags & (1 << 5)) || len < 32) { + triflg = 0; + } + else { + int index; + struct snode *t; + int tex_alpha = 0; + + tri.state = 0; + tri.flags = 0; + +#ifdef NO_TEXTURES + info.tex = 0; +#else + /* texture */ + info.tex = 0; + index = get16i(ptr + 28); /* texture index */ + t = 0; + if (index != -1) { + state->texs = t = splay(state->texs, (void *)index, ptrcmp); + if (t == 0 || t->key != (void *)index) { + /*ulSetError(UL_DEBUG, "[flt] undefined texture %d", index);*/ + t = 0; + } + } + if (t) { + fltTexture *tex = (fltTexture *)t->data; + if (tex->state == (ssgState *)-1) { + fltTexture *tmp = LoadTex(tex->file); + tex->state = tmp->state; + tex->tex = tmp->tex; + tex->alpha = tmp->alpha; + } + tri.state = tex->state; + info.tex = tex->tex; + tex_alpha = tex->alpha; + } +#ifndef NO_LOADER_OPTIONS + else { + if (state->notex_state == (ssgState *)-1) + state->notex_state = LoaderOptions->createState(0); + tri.state = state->notex_state; + } +#endif +#endif + + if (tri.state) { + + tri.bind = BIND_COLOR | BIND_NORMAL | BIND_TEXCOORD; + + } + else { + + int template = ptr[25]; + int white = ptr[19] || template > 1; /* OK ?? */ + int lmode = len >= 49 ? ptr[48] : 3; + int trans = get16u(ptr + 40); + + //ulSetError(UL_DEBUG, "light mode %d", lmode); + + /*lmode = 0;*/ + + /* wireframe */ + /*tri.wireframe = (drawtype > 1);*/ + + /* backface culling */ + info.cf = (drawtype == 0); + + /* alpha component */ +#if 0 + if (state->major >= 15) { + /* this is according to the spec, but it sure is suspicious */ + int a = trans >> 1; + int b = objtrans >> 1; + info.alpha = 1.0f - 1.0f/(32767*32767) * (a * b); + } + else +#endif + { + info.alpha = 1.0f - 1.0f/65535.0f * trans; + } + sgSetVec4(tri.color, 1, 1, 1, info.alpha); + +#ifdef NO_LIGHTING + info.mtl = 0; +#else + /* material */ + if (/*lmode < 2 ||*/ /* (objflags & (1 << 3)) || */ white) { + info.mtl = 0; + } + else { + index = get16i(ptr + 30); /* material index */ + state->mtls = t = splay(state->mtls, (void *)index, ptrcmp); + if (t && t->key == (void *)index) { + info.mtl = (float *)t->data; + } + else { + info.mtl = default_mtl; + } + info.alpha *= info.mtl[13]; + tri.color[3] = 1.0f; + } +#endif + + /* transparency */ + info.tr = (tex_alpha > 0 || info.alpha < 0.999f); /* && template > 0 */ + if (info.tr) + tri.flags |= TRI_TRANSLUCENT; + + /* initial bindings */ + tri.bind = 0; + if ((lmode & 1) && !white) + tri.bind |= BIND_COLOR; + if (info.mtl) { + tri.bind |= BIND_NORMAL; + if (!(lmode & 2) || (objflags & (1 << 4))) + tri.bind |= BIND_FLAT_NORMAL; + } + if (info.tex) + tri.bind |= BIND_TEXCOORD; + +#ifdef NO_COLORS + tri.bind &= ~BIND_COLOR; +#else + + /* face color */ + if (!(lmode & 1) && !(flags & 2) && !white && state->major >= 14) { /* will probably not work with old files */ + if ((flags & 8) && len >= 60) { + UNPACK_ABGR(tri.color, ptr + 56); /* packed ABGR */ + tri.bind |= BIND_FLAT_COLOR; + } + else if (state->revision > 1400) { + int color; + if (state->revision > 1500 && len >= 72) + color = get32i(ptr + 68); + else { + color = get16u(ptr + 20); + if (color == 65535) + color = -1; + } + int index = color / 128; + int intensity = color % 128; + if (color >= 0 && state->ctab && index < state->cnum) { + UNPACK_ABGR2(tri.color, state->ctab[index], intensity); + tri.bind |= BIND_FLAT_COLOR; + } + else if (color != -1) + ulSetError(UL_DEBUG, "[flt] Bad face color %d.", color); + } + tri.color[3] = info.alpha; + } +#endif + + /* + if (tri.bind & BIND_COLOR) + ulSetError(UL_DEBUG, "use vertex colors"); + if (tri.bind & BIND_FLAT_COLOR) + ulSetError(UL_DEBUG, "face color %.2f %.2f %.2f", + tri.color[0], tri.color[1], tri.color[2]); + */ + + /* billboard */ + if (template == 4) + tri.flags |= TRI_BBOARD_POINT; + else if (template == 2) + tri.flags |= TRI_BBOARD_AXIAL; + + /* cannot create the state yet, + * need to know the vertex bindings. */ + } + + triflg = 1; + } + ptr += len; + break; + } + + case 72: /* Vertex List (aka polygon) */ + if (triflg) { + int i, n = (len - 4) >> 2; + if (state->vtab && n > 2 && n < 512) { /* silently ignore if suspicious.. */ + int bind = tri.bind; + ubyte *p = ptr + 4; + for (i = 0; i < n; ++i) { + /* could this be done any faster? */ + /* it is tempting to reparse the vertex at the given offset */ + int offset = get32i(p), *ptr; + ptr = (int *)bsearch(&offset, state->offset, state->vnum, + sizeof(int), intcmp); + if (!ptr) { + ulSetError(UL_DEBUG, "[flt] Bad vertex offset %i.", offset); + break; + } + w[i] = ptr - state->offset; + bind &= state->bind[w[i]] | BIND_FLAT; + p += 4; + } + if (i == n) { + + tri.bind = bind; + + if (subface) + tri.flags |= TRI_SUBFACE; + else + tri.flags &= ~TRI_SUBFACE; + + if (tri.state) { + + Triangulate(w, n, state); + + } + else { + /* finalize state */ + + /* setup color material */ + if ((bind & (BIND_COLOR | BIND_FLAT_COLOR)) && + (bind & (BIND_NORMAL | BIND_FLAT_NORMAL))) { + sgVec4 color; + color[0] = 0.2f*info.mtl[0] + 0.8f*info.mtl[3]; + color[1] = 0.2f*info.mtl[1] + 0.8f*info.mtl[4]; + color[2] = 0.2f*info.mtl[2] + 0.8f*info.mtl[5]; + color[3] = info.alpha; + if ((tri.bind & BIND_FLAT_COLOR)) { + tri.color[0] *= color[0]; + tri.color[1] *= color[1]; + tri.color[2] *= color[2]; + tri.color[3] *= color[3]; + } + else { + sgCopyVec4(tri.color, color); /* apply to vertex colors */ + } + info.cm = 1; + tri.flags |= TRI_COLOR_MATERIAL; + } + else { + info.cm = 0; + tri.flags &= ~TRI_COLOR_MATERIAL; + } + + tri.state = ConstructState(&info); + + Triangulate(w, n, state); + + tri.state = 0; + } + } + } + } + ptr += len; + break; + + case 89: /* Morph Vertex List */ + ptr += len; + break; + + case 10: /* Push */ + sp++; + ptr += len; + break; + + case 11: /* Pop */ + if (sp == 0) { + done = 1; + break; + } + sp--; + ptr += len; + /*if (sp == 0) + done = 1;*/ + break; + + case 19: /* Push Subface */ + subface++; + ptr += len; + break; + + case 20: /* Pop Subface */ + subface--; + ptr += len; + break; + + case 33: /* Long ID */ + if (long_id[0] == 0) { + int n = CLAMP(len - 4, 0, 255); + memcpy(long_id, ptr + 4, n); + long_id[n] = 0; + } + ptr += len; + break; + + case 31: /* Text Comment */ + case 50: /* Vector (for light points) */ + case 21: /* Push Extension */ + case 22: /* Pop Extension */ + case 97: /* Line Style Record */ + case 122: /* Push Attribute */ + case 123: /* Pop Attribute */ + ptr += len; + break; + + case 6: /* Vertex with ID (obsolete) */ + case 7: /* Short Vertex (obsolete) */ + case 8: /* Vertex with Color (obsolete) */ + case 9: /* Vertex with Color and Normal (obsolete) */ + Obsolete(op); + ptr += len; + break; + + default: + if (sp == 0) { /* you never know what this might be. better let someone else take car of it. */ + done = 1; + break; + } + NotImplemented(op); + ptr += len; + } + + } while (!done); + + *nodep = Build(state); + + if (long_id[0] != 0 && *nodep != NULL) + (*nodep)->setName(long_id); + + return ptr - ptr0; +} + +struct LODInfo { + ssgTransform *scs; + ssgRangeSelector *lod; +}; + +static int LODCompare(const void *a, const void *b) +{ + float d = ((LODInfo *)a)->lod->getRange(0) - ((LODInfo *)b)->lod->getRange(0); + return d < 0 ? -1 : d > 0 ? 1 : 0; +} + +static void MergeLODs(ssgBranch *grp) +{ + LODInfo info[64]; + int i, j, k, m, n; + + n = grp->getNumKids(); + if (n <= 1) + return; + + m = 0; + for (i = 0; i < n && m < 64; i++) { + ssgEntity *kid; + kid = grp->getKid(i); + info[m].scs = 0; + if (kid->isA(ssgTypeTransform()) && kid->getNumParents() == 1) { + info[m].scs = (ssgTransform *)kid; + if (info[m].scs->getNumKids() != 1) + continue; + kid = info[m].scs->getKid(0); + } + if (!kid->isA(ssgTypeRangeSelector()) || kid->getNumParents() != 1) + continue; + info[m].lod = (ssgRangeSelector *)kid; + m++; + } + + if (m > 1) { + + qsort(info, m, sizeof(info[0]), LODCompare); + + //grp->print(); + + for (i = 0; i < m; i++) { + sgMat4 mat1, mat2; + float ranges[33], range2; + int num1, num2; + int flag = 0; + + if (info[i].lod == 0) + continue; + + if (info[i].scs) + info[i].scs->getTransform(mat1); + else + sgMakeIdentMat4(mat1); + num1 = info[i].lod->getNumKids(); + for (k = 0; k <= num1; k++) + ranges[k] = info[i].lod->getRange(k); + + for (j = i + 1; j < m; j++) { + + if (info[j].lod == 0) + continue; + + if (info[j].scs) + info[j].scs->getTransform(mat2); + else + sgMakeIdentMat4(mat2); + num2 = info[j].lod->getNumKids(); + range2 = info[j].lod->getRange(0); + + if (sgDistanceVec3(mat1[3], mat2[3]) > 0.1f * range2) /* XXX */ + continue; + if (num1 + num2 > 32) /* XXX */ + continue; + if (ABS(ranges[num1] - range2) > 0.1f * range2) /* XXX */ + continue; + + for (k = 0; k < num2; k++) { + info[i].lod->addKid(info[j].lod->getKid(k)); + ranges[num1 + k + 1] = info[j].lod->getRange(k + 1); + num1++; + } + + if (info[j].scs == 0 || info[j].scs->getRef() == 1) { + if (info[j].lod->getRef() == 1) { + while (num2--) + info[j].lod->removeKid(num2); + } + if (info[j].scs) + info[j].scs->removeKid(info[j].lod); // delete info[j].lod + else + grp->removeKid(info[j].lod); + } + if (info[j].scs) + grp->removeKid(info[j].scs); // delete info[j].scs + + info[j].lod = 0; + flag = 1; + } + + if (flag) { + info[i].lod->setRanges(ranges, num1 + 1); + assert(info[i].scs == 0 || !info[i].scs->isA(0xDeadBeef)); + assert(!info[i].lod->isA(0xDeadBeef)); + } + } + } +} + +static ssgEntity *PostClean(ssgEntity *node, fltNodeAttr *attr) +{ + + if (node && attr && attr->name) + node->setName(attr->name); + +#if 1 + /* remove empty or redundant groups */ + while (!NoClean && node && node->isA(ssgTypeBranch())) { + ssgBranch *grp = (ssgBranch *)node; + int num = grp->getNumKids(); + if (num > 1) + break; + if (num == 1) { + ssgEntity *kid = grp->getKid(0); + if (grp->getName()) { + if (kid->getName()) + break; + kid->setName(grp->getName()); + } + if (grp->getRef() == 0) { + kid->ref(); + grp->removeKid(0); + kid->deRef(); + delete grp; + } + node = kid; + assert(!node->isA(0xDeadBeef)); + } + else { + if (grp->getRef() == 0) + delete grp; + node = 0; + } + } +#endif + +#if 1 + /* see if we can merge LOD nodes */ + if (node && node->isAKindOf(ssgTypeBranch()) && + !node->isAKindOf(ssgTypeSelector())) { + MergeLODs((ssgBranch *)node); + assert(!node->isA(0xDeadBeef)); + } +#endif + + /* set limits on animated nodes */ + if (node && node->isA(ssgTypeTimedSelector())) { + ssgTimedSelector *sw = (ssgTimedSelector *) node; + if (sw->getNumKids() > 1) { + sw->setDuration(30.0f); + sw->setLimits(0, sw->getNumKids() - 1); + sw->control(SSG_ANIM_START); + } + } + + /* apply node attributes */ + if (node && attr) { + + if (attr->transform) { + + ssgTransform *scs = new ssgTransform; + scs->setTransform(attr->mat); + scs->addKid(node); + + if (attr->replicate > 0) { + ssgBranch *grp; + sgMat4 mat; + int i; + grp = new ssgBranch; + grp->addKid(scs); + sgCopyMat4(mat, attr->mat); +#if 0 + ulSetError(UL_DEBUG, "replicating %d times", attr->replicate); + for (i = 0; i < 4; i++) + ulSetError(UL_DEBUG, " %6.2f %6.2f %6.2f %6.2f", mat[i][0], mat[i][1], mat[i][2], mat[i][3]); +#endif + for (i = 0; i < attr->replicate; ++i) { + sgPostMultMat4(mat, attr->mat); + scs = new ssgTransform; + scs->setTransform(mat); + scs->addKid(node); + grp->addKid(scs); + } + node = grp; /* there's no point in cleaning this construction */ + /*ulSetError(UL_DEBUG, "[flt] replicated %d times", attr->replicate);*/ + } + else { + node = scs; // PostClean(scs, 0); + /*ulSetError(UL_DEBUG, "[flt] added transformation");*/ + } + } + + /* apply level of detail */ + if (attr->islod) { + float ranges[2]; + ranges[0] = MIN(attr->range[0], attr->range[1]); + ranges[1] = MAX(attr->range[0], attr->range[1]); + if (ranges[1] > MAX(0, ranges[0])) { + ssgRangeSelector *lod = new ssgRangeSelector; + lod->setRanges(ranges, 2); + + if (sgLengthVec3(attr->center) > 0.01f) { /* XXX */ + ssgTransform *t1, *t2; + sgMat4 mat; + sgMakeTransMat4(mat, attr->center[0], attr->center[1], attr->center[2]); + t1 = new ssgTransform; + t1->setTransform(mat); + sgMakeTransMat4(mat, -attr->center[0], -attr->center[1], -attr->center[2]); + t2 = new ssgTransform; + t2->setTransform(mat); + t1->addKid(lod); + lod->addKid(t2); + t2->addKid(node); + node = t1; + } + else { + lod->addKid(node); + node = lod; + } + } + } + + /* setup switch records */ + if (attr->num_masks > 0) { + ssgTimedSelector *sw = new ssgTimedSelector; + int n = ((ssgBranch *) node) -> getNumKids(); + if (n > 32 * attr->num_words) n = 32 * attr->num_words; + for (int i = 0; i < attr->num_masks; i++) { + ssgBranch *br = new ssgBranch; + for (int j = 0; j < n; j++) { + if (attr->mask_words[j / 32] & (1u << (j % 32))) + br -> addKid(((ssgBranch *) node) -> getKid(j)); + } + sw -> addKid(br); + } + if (node->getRef() == 0) { + ((ssgBranch *) node) -> removeAllKids(); + delete node; + } + sw->setMode(SSG_ANIM_SHUTTLE); + sw->setDuration(30.0f); + sw->setLimits(0, attr->num_masks - 1); + sw->control(SSG_ANIM_START); + node = sw; + } + } + + if (attr) + delete attr; + + assert(node == 0 || !node->isA(0xDeadBeef)); + + return node; +} + +/* link nodes while removing crap (post traversal) */ +static void PostLink(ssgEntity **stack, fltNodeAttr **attr, + int instance, fltState *state) +{ +#if 0 + ulSetError(UL_DEBUG, "PostLink: %s %s <-- %s %s", + stack[0] ? pfGetTypeName(stack[0]) : "0", stack[0] ? pfGetNodeName(stack[0]) : "0", + stack[1] ? pfGetTypeName(stack[1]) : "0", stack[1] ? pfGetNodeName(stack[1]) : "0"); +#endif + + if (stack[1] == 0) { + if (attr[1]) { + delete attr[1]; + attr[1] = 0; + } + return; + } + assert(!stack[1]->isA(0xDeadBeef)); + + stack[1] = PostClean(stack[1], attr[1]); + + if (stack[1] && instance >= 0) { + state->refs = sinsert(state->refs, (void *)instance, 0, ptrcmp); + if (state->refs->data != (void *)-1) { + ulSetError(UL_WARNING, "[flt] Instance %d redefined.", instance); + ssgDeRefDelete((ssgEntity *) state->refs->data); + } + state->refs->data = stack[1]; + stack[1]->ref(); + } + + if (stack[0] == 0) { + stack[0] = stack[1]; + if (attr[0]) { + delete attr[0]; + attr[0] = 0; + } + } + else { + assert(!stack[0]->isA(0xDeadBeef)); + if (stack[1]) { + if (stack[0]->isAKindOf(ssgTypeBranch())) { + ((ssgBranch *)stack[0])->addKid(stack[1]); + } + else { + ssgBranch *grp = new ssgBranch; + grp->addKid(stack[0]); + grp->addKid(stack[1]); + stack[0] = PostClean(grp, 0); + } + } + } + + stack[1] = 0; + attr[1] = 0; +} + +/* group/object ancillary chunks */ +static int AttrChunks(ubyte *ptr0, ubyte *end, fltNodeAttr **attrp) +{ + ubyte *ptr = ptr0; + int op, len, done = 0; + fltNodeAttr *attr; + + attr = *attrp; + + while (!done) { + + if (ptr + 4 > end) + break; + op = get16u(ptr); + len = get16u(ptr + 2); + if (len < 4 || (len & 3) != 0 || ptr + len > end) + break; + + switch (op) { + + case 31: /* Comment */ + ptr += len; + break; + + case 33: { /* Long ID */ + int n = len - 4; + if (n > 0 && n < 256) { + if (attr == 0) + attr = new fltNodeAttr; + //attr->name = (char *)malloc(n + 1); + attr->name = new char[n + 1]; + memcpy(attr->name, ptr + 4, n); + attr->name[n] = 0; + } + ptr += len; + break; + } + + case 60: { /* Replicate */ + if (attr == 0) + attr = new fltNodeAttr; + attr->replicate = get16u(ptr + 4); + ptr += len; + break; + } + + case 49: { /* Transfomation Matrix */ + sgMat4 mat; + int i, j; + get32v(ptr + 4, mat, 16); + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + float d = mat[i][j] - (i == j ? 1.0f : 0.0f); + if (ABS(d) > 0.001f) + break; + } + if (j < 4) + break; + } + if (i < 4) { + if (attr == 0) + attr = new fltNodeAttr; + attr->transform = 1; + sgCopyMat4(attr->mat, mat); + } + ptr += len; + break; + } + + case 12: /* Translate (obsolete) */ + case 40: /* Translate (obsolete) */ + case 41: /* Rotate about Point (obsolete) */ + case 42: /* Rotate about Edge (obsolete) */ + case 43: /* Scale (obsolete) */ + case 44: /* Translate (obsolete) */ + case 45: /* Scale (obsolete) */ + case 46: /* Rotate about Point (obsolete) */ + case 47: /* Rotate and/or Scale about Point (obsolete) */ + case 48: /* Put Transform (obsolete) */ + case 51: /* Bounding Box (obsolete) */ + case 77: /* Scale (obsolete) */ + case 110: /* Histogram Bounding Volume (obsolete) */ + Obsolete(op); + ptr += len; + break; + + case 74: /* Bounding Box */ + case 76: /* Rotate about Edge */ + case 78: /* Translate */ + case 79: /* Scale */ + case 80: /* Rotate about Point */ + case 81: /* Rotate and/or Scale */ + case 82: /* Put */ + case 88: /* Road Zone */ + case 94: /* General Matrix */ + case 100: /* Extension Attribute */ + case 105: /* Bounding Sphere */ + case 106: /* Bounding Cylinder */ + case 108: /* Bounding Volume Center */ + case 109: /* Bounding Volume Orientation */ + case 116: /* CAT Data */ + /* these are safe to ignore */ + ptr += len; + break; + + default: + done = 1; + break; + } + } + + *attrp = attr; + + return ptr - ptr0; +} + +static ssgEntity *LoadFLT(const char *path); + +/* object hierarchy chunks */ +static ssgEntity *HierChunks(ubyte *ptr, ubyte *end, fltState *state) +{ + ssgEntity *stack[MAXDEPTH + 1]; + fltNodeAttr *attr[MAXDEPTH + 1]; + int instance[MAXDEPTH + 1]; + int sp, op, len, k; + + stack[0] = new ssgBranch; + stack[0]->setName("reserved"); + attr[0] = 0; + instance[0] = -1; + stack[1] = 0; + attr[1] = 0; + instance[1] = -1; + sp = 1; + + for (;;) { + + if (ptr + 4 > end) + break; + op = get16u(ptr); + if (op < 1 || op > 150) + break; + len = get16u(ptr + 2); + if (len < 4 || (len & 3) != 0 || ptr + len > end) + break; + +#if 0 + for (int i = 0; i < sp; i++) + putchar('\t'); + printf("op %d\n", op); +#endif + + switch (op) { + + case 10: /* Push */ + if (stack[sp] && !stack[sp]->isAKindOf(ssgTypeBranch())) { + /* shouldn't happen */ + ulSetError(UL_DEBUG, "[flt] Objects are not allowed to contain other objects or groups."); + PostLink(stack + sp - 1, attr + sp - 1, instance[sp], state); + instance[sp] = -1; + } + if (sp >= MAXDEPTH) { + ulSetError(UL_WARNING, "[flt] Stack overflow."); + } + else { + sp++; + stack[sp] = 0; + attr[sp] = 0; + instance[sp] = -1; + } + ptr += len; + break; + + case 11: /* Pop */ + if (sp == 1) + ulSetError(UL_WARNING, "[flt] Stack underflow."); + else { + PostLink(stack + sp - 1, attr + sp - 1, instance[sp], state); + sp--; + } + ptr += len; + break; + + case 4: { /* Object */ + + /* + * Object Record Format + * + * Int 0 2 Object Opcode 4 + * Unsigned 2 2 Length of the record + * Char 4 8 7 char ASCII ID; 0 terminates + * Boolean 12 4 Flags (bits from to right) + * 0 = Don't display in daylight + * 1 = Don't display at dusk + * 2 = Don't display at night + * 3 = Don't illuminate + * 4 = Flat shaded + * 5 = Group's shadow object + * 6-31 = Spare + * Int 16 2 Relative priority + * Unsigned 18 2 Transparency + * 0 = Opaque + * 65535 = Totally clear + * Int 20 2 Special effect ID1 - application defined + * Int 22 2 Special effect ID2 - application defined + * Int 24 2 Significance + * Int 26 2 Spare + * + */ + + int flags = get32i(ptr + 12); + int trans = get16u(ptr + 18); + PostLink(stack + sp - 1, attr + sp - 1, instance[sp], state); + instance[sp] = -1; + ptr += len; + ptr += AttrChunks(ptr, end, &attr[sp]); + state->parent_name = (char *)ptr + 4; /* OK?? */ + ptr += GeomChunks(ptr, end, state, &stack[sp], flags, trans); + state->parent_name = 0; + if (stack[sp] && stack[sp]->getName() == 0 && ptr[4]) + stack[sp]->setName((char *)ptr + 4); + break; + } + + case 5: /* Face */ + /* polygons are not allowed to be outside objects, but this rule is not always respected */ + //ulSetError(UL_DEBUG, "[flt] Implicit object."); + PostLink(stack + sp - 1, attr + sp - 1, instance[sp], state); + instance[sp] = -1; + ptr += GeomChunks(ptr, end, state, &stack[sp], 0, 0); + break; + + case 2: /* Group */ + case 14: /* Degree of Freedom */ + case 73: /* Level of Detail */ + case 96: /* Switch */ + case 98: /* Clip Region */ + + PostLink(stack + sp - 1, attr + sp - 1, instance[sp], state); + instance[sp] = -1; + + switch (op) { + + case 2: { /* Group */ +#if 0 /* group animation - seems wrong... */ + int flags = (len >= 20) ? get32i(ptr + 16) : 0; + if ((flags & 3) != 0) { + ssgTimedSelector *sw = new ssgTimedSelector; + sw->setMode((flags & 2) ? SSG_ANIM_SWING : SSG_ANIM_SHUTTLE); + stack[sp] = sw; + } + else +#endif + { + stack[sp] = new ssgBranch; + } + break; + } + + case 14: { /* Degree of Freedom */ + stack[sp] = new ssgTransform; + break; + } + + case 73: { /* Level of Detail */ + fltNodeAttr *a; + double v[3]; + attr[sp] = a = new fltNodeAttr; + a->islod = 1; + get64v(ptr + 16, v, 2); + sgSetVec2(a->range, (float)v[0], (float)v[1]); + get64v(ptr + 40, v, 3); + sgSetVec3(a->center, (float)v[0], (float)v[1], (float)v[2]); + stack[sp] = new ssgBranch; + break; + } + + case 96: { /* Switch */ + int num_words = (len > 28) ? get32i(ptr + 20) : -1; + int num_masks = (len > 28) ? get32i(ptr + 24) : -1; + if (num_words <= 0 || num_masks <= 0 || len < 28 + 4 * num_words * num_masks) { + ulSetError(UL_DEBUG, "[flt] Incomplete switch record."); + } + else { + fltNodeAttr *a = new fltNodeAttr; + a->current_mask = get32i(ptr + 16); + a->num_masks = num_masks; + a->num_words = num_words; + a->mask_words = new uint [ num_masks * num_words ]; + get32v(ptr + 28, a->mask_words, num_masks * num_words); + attr[sp] = a; + } + stack[sp] = new ssgBranch; + break; + } + + default: { /* Others (i.e. 98 Clip Region) */ + stack[sp] = new ssgBranch; + break; + } + + } + + if (ptr[4]) + stack[sp]->setName((char *)ptr + 4); + + ptr += len; + ptr += AttrChunks(ptr, end, &attr[sp]); + + break; + + case 61: /* Instance Reference */ + k = get16u(ptr + 6); + if (k != instance[sp]) { // current instance inserted by default + PostLink(stack + sp - 1, attr + sp - 1, instance[sp], state); + instance[sp] = -1; + if (state->refs) { + state->refs = splay(state->refs, (void *)k, ptrcmp); + if (state->refs->key == (void *)k) { + stack[sp] = (ssgEntity *)state->refs->data; + } + } + } + ptr += len; + ptr += AttrChunks(ptr, end, &attr[sp]); + break; + + case 62: /* Instance Definition */ + k = get16u(ptr + 6); +#if 0 + if (stack[sp]) { + state->refs = sinsert(state->refs, (void *)k, 0, ptrcmp); + if (state->refs->data == (void *)-1) { + state->refs->data = stack[sp]; + stack[sp]->ref(); + } + } + else + { + ulSetError(UL_DEBUG, "[flt] yeah, but the node is empty!"); + } +#else + instance[sp] = k; +#endif + ptr += len; + break; + + case 63: /* External Reference */ + /*ulSetError(UL_DEBUG, "external reference %s", ptr + 4);*/ + PostLink(stack + sp - 1, attr + sp - 1, instance[sp], state); + instance[sp] = -1; + if (!NoExternals) { + char *file = (char *)ptr + 4, *p; + if ((p = strrchr(file, '/'))) + file = p + 1; + //stack[sp] = LoadFLT(file); + stack[sp] = ssgLoad (file); + } + ptr += len; + ptr += AttrChunks(ptr, end, &attr[sp]); + break; + + case 31: /* Text Comment */ + case 21: /* Push Extension */ + case 22: /* Pop Extension */ + case 55: /* Binary Separating Plane */ + case 87: /* Road Segment */ + case 90: /* Linkage */ + case 91: /* Sound Bead */ + case 92: /* Path Bead */ + case 95: /* Text */ + case 101: /* Light Source Bead */ + case 122: /* Push Attribute */ + case 123: /* Pop Attribute */ + //printf("op %d ignored\n", op); + ptr += len; + break; + + case 3: /* Level of Detail (obsolete) */ + case 13: /* Degree of Freedom (obsolete) */ + case 16: /* Instance Reference (obsolete) */ + case 17: /* Instance Definition (obsolete) */ + Obsolete(op); + ptr += len; + break; + + default: + NotImplemented(op); + ptr += len; + } + } + + /* pop stack (expected one iteration but may be more for incomplete databases) */ + while (sp-- > 0) + PostLink(stack + sp, attr + sp, -1, 0); + + if (stack[0]) + stack[0] = PostClean(stack[0], attr[0]); + else if (attr[0]) + delete attr[0]; // possible? + + return stack[0]; +} + +/* parse the vertex table */ +static int VertexTable(ubyte *ptr0, ubyte *end, fltState *state) +{ + int len, size, num, i; + ubyte *ptr = ptr0; + + assert(get16u(ptr) == 67); /* vtx tab op code */ + len = get16u(ptr + 2); + + size = get32i(ptr + 4); + /*ulSetError(UL_DEBUG, "vertex table header len %d, total size %d", len, size);*/ + num = (size - len)/40; /* max # of vertices */ + if (num <= 0 || state->vtab) { + if (state->vtab) + ulSetError(UL_WARNING, "[flt] Multiple vertex tables not allowed."); + return size; + } + state->vtab = ptr; + end = MIN(end, ptr + size); + ptr += len; + + state->offset = new int [num]; + state->bind = new ubyte [num]; + state->coord = new sgVec3 [num]; + state->color = new sgVec4 [num]; + state->normal = new sgVec3 [num]; + state->texcoord = new sgVec2 [num]; + + for (i = 0; i < num && ptr + 40 <= end; ++i) { + double tmp[3]; + ubyte *p = ptr; + int op = get16u(p); + int len = get16u(p + 2); + int flags = get16u(p + 6); + int bind = 0; + if (ptr + len > end) + break; + state->offset[i] = ptr - ptr0; + get64v(p + 8, tmp, 3); + sgSetVec3(state->coord[i], (float)tmp[0], (float)tmp[1], (float)tmp[2]); + sgSetVec4(state->color[i], 1, 1, 1, 1); + sgSetVec3(state->normal[i], 0, 0, 1); + sgSetVec2(state->texcoord[i], 0, 0); + p += 32; + if (op == 69 || op == 70) { + get32v(p, state->normal[i], 3); + sgNormalizeVec3(state->normal[i]); + p += 12; + bind |= BIND_NORMAL; + } + if (op == 70 || op == 71) { + get32v(p, state->texcoord[i], 2); + p += 8; + bind |= BIND_TEXCOORD; + } + if (!(flags & 4)) { + if ((flags & 8) && p + 4 <= ptr + len) { + UNPACK_ABGR(state->color[i], p); + //ulSetError(UL_DEBUG, "packed ABGR: %d %d %d %d", p[0], p[1], p[2], p[3]); + bind |= BIND_COLOR; + } + else if (state->revision > 1400) { + int color; + if (state->revision > 1500 && p + 8 <= ptr + len) { + color = get32i(p + 4); + } + else { + color = get16u(ptr + 4); + if (color == 65535) + color = -1; + } + int index = color / 128; + int intensity = color % 128; + if (color >= 0 && state->ctab && index < state->cnum) { + //ulSetError(UL_DEBUG, "colour %d: index %d, intensity %d", color, index, intensity); + UNPACK_ABGR2(state->color[i], state->ctab[index], intensity); + bind |= BIND_COLOR; + } + } + } + /* + if (bind & BIND_COLOR) + ulSetError(UL_DEBUG, "vertex #%d color %.2f %.2f %.2f", i, + state->color[i][0], + state->color[i][1], + state->color[i][2]); + */ + state->bind[i] = bind; + ptr += len; + } + /*ulSetError(UL_DEBUG, "got %d vertices", i);*/ + + state->vnum = i; + + return size; +} + +/* header ancillary chunks */ +static int TableChunks(ubyte *ptr0, ubyte *end, fltState *state) +{ + ubyte *ptr = ptr0; + int op, len, index, done = 0; + + while (!done) { + + if (ptr + 4 > end) + break; + op = get16u(ptr); + len = get16u(ptr + 2); + if (len < 4 || (len & 3) != 0 || ptr + len > end) + break; + + switch (op) { + + case 32: /* Color Table */ + if (len < 132 + 4 * 512) { + /* note: in older files it appears that the + * color table is stored as 16-bit integers. + * i have no documentation on this. + * maybe 16 x 16 colors (rather than 512 or 1024 x 128). + */ + if (state->revision <= 1400) { + ulSetError(UL_WARNING, "[flt] Color table ignored (unknown format)."); + /*hexdump(UL_DEBUG, ptr, len, 0);*/ + } + else + BAD_CHUNK(ptr, "Color Table"); + } + else if (state->ctab == 0) { + int max = (len - 132) / 4; + state->ctab = (ubyte (*)[4])(ptr + 132); + state->cnum = MIN(state->revision > 1500 ? 1024 : 512, max); +#if 0 + int i; + for (i = 0; i < state->cnum; i++) + ulSetError(UL_DEBUG, "%d %02x %02x %02x %02x", i, + state->ctab[i][0], state->ctab[i][1], + state->ctab[i][2], state->ctab[i][3]); +#endif + } + else { + ulSetError(UL_WARNING, "[flt] Multiple color tables are not allowed."); + } + ptr += len; + break; + + case 64: /* Texture Reference */ + if (!NoTextures) { + if (len == 96 || len == 216) { + char *file = (char *)ptr + 4, *p; + if ((p = strrchr(file, '/'))) + file = p + 1; + index = get32i(ptr + len - 12); + state->texs = sinsert(state->texs, (void *)index, 0, ptrcmp); + if (state->texs->data == (void *)-1) { + //fltTexture *tex = (fltTexture *)malloc(sizeof(fltTexture)); + fltTexture *tex = new fltTexture; + assert ( tex != NULL ); + tex->file = file; + tex->state = (ssgState *)-1; + tex->tex = (ssgTexture *)-1; + state->texs->data = tex; + } + } + else { + BAD_CHUNK(ptr, "Texture Reference"); + } + } + ptr += len; + break; + + case 66: /* Material Table */ + if ((len - 4) % 184 != 0) { + BAD_CHUNK(ptr, "Material Table"); + } + else if (state->mtls == 0) { + ubyte *p = ptr + 4; + int i, j, n = (len - 4) / 184; + for (i = 0; i < n; ++i) { + float *mtl; + state->mtls = sinsert(state->mtls, (void *)i, 0, ptrcmp); + //state->mtls->data = malloc(sizeof(float)*14); + state->mtls->data = new float[14]; + mtl = (float *)state->mtls->data; + get32v(p, mtl, 14); + for (j = 0; j < 12; j++) + mtl[j] = CLAMP(mtl[j], 0, 1); + mtl[12] = CLAMP(mtl[12], 8, 128); + mtl[13] = CLAMP(mtl[13], 0, 1); +#if 0 + float r, g, b, s; + r = mtl[0] + mtl[3] + mtl[6] + mtl[9]; + g = mtl[1] + mtl[4] + mtl[7] + mtl[10]; + b = mtl[2] + mtl[5] + mtl[8] + mtl[11]; + s = MAX3(r, g, b); + if (s > 1.0f) { + s = 1.0f/s; + for (j = 0; j < 12; j++) + mtl[j] *= s; + } +#endif + p += 184; + } + } + else { + ulSetError(UL_WARNING, "[flt] Multiple material tables are not allowed"); + } + ptr += len; + break; + + case 67: /* Vertex Table (header) */ + ptr += VertexTable(ptr, end, state); + break; + + case 113: /* Material */ + index = get32i(ptr + 4); + state->mtls = sinsert(state->mtls, (void *)index, 0, ptrcmp); + if (state->mtls->data == (void *)-1) { + float *mtl; + int i; + //state->mtls->data = malloc(sizeof(float)*14); + state->mtls->data = new float[14]; + mtl = (float *)state->mtls->data; + get32v(ptr + 24, mtl, 14); + for (i = 0; i < 12; i++) + mtl[i] = CLAMP(mtl[i], 0, 1); + mtl[12] = CLAMP(mtl[12], 8, 128); + mtl[13] = CLAMP(mtl[13], 0, 1); +#if 0 + float r, g, b, s; + r = mtl[0] + mtl[3] + mtl[6] + mtl[9]; + g = mtl[1] + mtl[4] + mtl[7] + mtl[10]; + b = mtl[2] + mtl[5] + mtl[8] + mtl[11]; + s = MAX3(r, g, b); + if (s > 1.0f) { + s = 1.0f/s; + for (i = 0; i < 12; i++) + mtl[i] *= s; + } +#endif + } + ptr += len; + break; + + case 65: /* Eyepoint Palette (obsolete) */ + Obsolete(op); + ptr += len; + break; + + case 31: /* Text Comment */ + case 83: /* Eyepoint and Trackplane */ + case 90: /* Linkage Palette */ + case 93: /* Sound Palette */ + case 97: /* Line Style Palette */ + case 102: /* Light Source Palette */ + case 103: /* Reserved */ + case 104: /* Reserved */ + case 112: /* Texture Mapping */ + case 114: /* Name Table */ + /* these are safe to ignore */ + ptr += len; + break; + + default: + //printf("op %d: end of table chunks\n", op); + done = 1; + } + } + + return ptr - ptr0; +} + +static int CheckHeader(ubyte *ptr, ubyte *end, fltState *state) +{ + /*const char *unit[9] = {"meters", "kilometers", "", "", "feet", "inches", "", "", "nautical miles"};*/ + int len, k; + if (get16u(ptr) != 1) { + ulSetError(UL_WARNING, "[flt] Wrong header opcode (%d).", get16i(ptr)); + return -1; + } + len = get16u(ptr + 2); + if (len < 128 || len > 1024) { + ulSetError(UL_WARNING, "[flt] Suspicious header record length (%d).", len); + return -1; + } + k = get32i(ptr + 12); + if (k < 100) { + state->revision = 100 * k; + state->major = k; + state->minor = 0; + } + else { + state->revision = k; + state->major = k / 100; + state->minor = k % 100; + } + if (state->major < 11 || state->major > 16) { + ulSetError(UL_WARNING, "[flt] Suspicious format revision number (%d).", k); + return -1; + } +/* + ulSetError(UL_DEBUG, "[flt] Loading %s %sFlight v%d.%d", + state->filename, + state->major > 13 ? "Open" : "", + state->major, + state->minor); +*/ + return len; +} + +#if 0 +struct snode *refs; +static int nrefs; + +static void ptree(ssgEntity *node, FILE *f, int d) +{ + int i; + for (i = 0; i < d; ++i) + fprintf(f, " "); + { + const char *p = node->getName(); + fprintf(f, "%s \"%s\"", node->getTypeName(), p ? p : ""); + } + if (node->getNumParents() > 1) { + refs = sinsert(refs, node, 0, ptrcmp); + if (refs->data == (void *)-1) { + fprintf(f, " (%d)", nrefs); + refs->data = (void *)nrefs++; + } + else { + fprintf(f, " (%d) ...\n", (int)refs->data); + return; + } + } + assert(!node->isA(0xDeadBeef)); + if (node->isAKindOf(ssgTypeLeaf())) { + ssgLeaf *leaf = (ssgLeaf *)node; + ssgState *st = leaf->getState(); + fprintf(f, " %d tris", leaf->getNumTriangles()); + if (st && st->isAKindOf(ssgTypeSimpleState())) { + ssgSimpleState *ss = (ssgSimpleState *)st; + char *file = ss->getTextureFilename(); + if (file) { + char *p; + if ((p = strrchr(file, '/'))) + file = p + 1; + fprintf(f, " %s", file); + } + } + } + if (node->isAKindOf(ssgTypeTransform())) { + sgMat4 mat; + ((ssgTransform *)node)->getTransform(mat); + fprintf(f, " pos %.2f %.2f %.2f", mat[3][0], mat[3][1], mat[3][2]); + } + if (node->isAKindOf(ssgTypeRangeSelector())) { + ssgRangeSelector *lod = (ssgRangeSelector *)node; + fprintf(f, " ranges"); + for (i = 0; i <= lod->getNumKids(); i++) + fprintf(f, " %.2f", lod->getRange(i)); + } + putc('\n', f); + if (node->isAKindOf(ssgTypeBranch())) { + ssgBranch *grp = (ssgBranch *)node; + int n = grp->getNumKids(); + for (i = 0; i < n; ++i) + ptree(grp->getKid(i), f, d+1); + } +} +#endif + +static const char *FindFile(const char *file) +{ + /* XXX fixme! */ + static char path[1024]; + + if (ulFileExists((char *)file)) + return file; + + ssgGetCurrentOptions () -> makeModelPath ( path, file ) ; + if (ulFileExists(path)) + return path; + + ulSetError(UL_WARNING, "[flt] %s not found.", file); + + return 0; +} + +static struct snode *FltCache; + +#ifdef UL_WIN32 + +static void win32_perror(const char *s) +{ + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + fprintf(stderr, "%s: %s\n", s, lpMsgBuf); + LocalFree( lpMsgBuf ); +} + +#endif + +static ssgEntity *LoadFLT(const char *file) +{ + struct snode *cache; + cache = FltCache = sinsert(FltCache, (void *)file, strlen(file) + 1, (sfunc)strcmp); + if (cache->data == (void *)-1) { + cache->data = NULL; /* avoid looping */ + + fltState *state = 0; + int size = 0, len; + ubyte *ptr = 0, *end; + ssgEntity *node = 0; + +#ifdef USE_WIN32_MMAP + + HANDLE fd = INVALID_HANDLE_VALUE; + HANDLE map = 0; + +#else + + int fd = -1; +#ifdef USE_POSIX_MMAP + struct stat st; +#else + ubyte buf[256]; +#endif + +#endif + + do { /* dummy loop */ + + const char *path, *name; + + path = FindFile(file); + if (path == 0) + break; + +#ifdef USE_WIN32_MMAP + + fd = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, 0); + if (fd == INVALID_HANDLE_VALUE) { + win32_perror(path); + break; + } + + size = GetFileSize(fd, NULL); + if (size < 256) + break; + + map = CreateFileMapping(fd, NULL, PAGE_READONLY, 0, size, NULL); + if (map == 0) { + win32_perror(path); + break; + } + + ptr = (ubyte *)MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0); + if (ptr == 0) { + win32_perror(path); + break; + } + +#else /* USE_WIN32_MAP */ + + if ((fd = open(path, O_RDONLY|O_BINARY)) == -1) { + perror(path); + break; + } + +#ifdef USE_POSIX_MMAP + if (fstat(fd, &st)) { + perror(file); + break; + } + size = st.st_size; + if (size < 256) + break; + ptr = (ubyte *)mmap(0, size, PROT_READ, MAP_SHARED, fd, 0); + if (ptr == (ubyte *)-1) { + perror(file); + break; + } + close(fd); + fd = -1; +#else /* USE_POSIX_MMAP */ + if (read(fd, buf, 256) != 256) { + perror(file); + break; + } + ptr = buf; +#endif /* ! USE_POSIX_MMAP */ + +#endif /* ! USE_WIN32_MMAP */ + + /*putc('\n', stderr);*/ + + name = strrchr(file, '/'); + if (name) + name++; + else + name = file; + + state = new fltState; + state->filename = name; + + len = CheckHeader(ptr, ptr + 256, state); + if (len == -1) + break; + +#if !defined(USE_POSIX_MMAP) && !defined(USE_WIN32_MMAP) + + if ((size = lseek(fd, 0, SEEK_END)) == -1) { + perror(file); + break; + } + //ptr = (ubyte *)malloc(size); + ptr = new ubyte[size]; + lseek(fd, 0, SEEK_SET); + if (read(fd, ptr, size) != size) { + perror(file); + break; + } + close(fd); + fd = -1; + +#endif + + end = ptr + size; + len += TableChunks(ptr + len, end, state); + node = HierChunks(ptr + len, end, state); + + if (node) + node->setName((char *)name); + + } while (0); + + delete state; + +#ifdef USE_WIN32_MMAP + + if (ptr) + UnmapViewOfFile(ptr); + if (map) + CloseHandle(map); + if (fd != INVALID_HANDLE_VALUE) + CloseHandle(fd); + +#else /* USE_WIN32_MMAP */ + + if (fd != -1) + close(fd); + +#ifdef USE_POSIX_MMAP + if (ptr != 0 && ptr != (ubyte *)-1) + munmap((char *)ptr, size); +#else + if (ptr != 0 && ptr != buf) + //free(ptr); + delete [] ptr; +#endif + +#endif /* ! USE_WIN32_MMAP */ + + cache->data = node; + if (node) node->ref(); + } + + return (ssgEntity *)cache->data; +} + +#if 0 +static struct snode *Flattened; + +static ssgEntity *Flatten(ssgEntity *node, float (*mat)[4]) +{ + if (node == 0) + return 0; + + assert(!node->isA(0xDeadBeef)); + + /* some nodes cannot be flattened. only types that may be + * generated by the loader are considered here. + */ + if (node->getRef() > 0 || + node->isAKindOf(ssgTypeRangeSelector()) || + node->isAKindOf(ssgTypeCutout())) { + if (node->isAKindOf(ssgTypeBranch())) { + /* see if we have flattened beyond this node already */ + int completed = 0; + if (node->getNumParents() > 0) { + Flattened = sinsert(Flattened, node, 0, ptrcmp); + if (Flattened->data == (void *)-1) { + Flattened->data = 0; + } + else { + completed = 1; + } + } + if (!completed) { + /* traverse */ + ssgBranch *grp = (ssgBranch *)node; + int i, n = grp->getNumKids(); + if (n > 0) { + ssgEntity *kids[32]; + for (i = n; i--;) { + kids[i] = grp->getKid(i); + kids[i]->ref(); grp->removeKid(i); kids[i]->deRef(); + kids[i] = Flatten(kids[i], 0); + assert(kids[i] == 0 || !kids[i]->isA(0xDeadBeef)); + } + for (i = 0; i < n; i++) + if (kids[i]) + grp->addKid(kids[i]); + grp->recalcBSphere(); + } + } + } + /* insert a transform if required */ + if (mat) { + ssgTransform *scs = new ssgTransform; + scs->setTransform(mat); + scs->addKid(node); + node = scs; + } + return node; + } + + assert(node->getNumParents() == 0); + + /* accumulate transformations */ + if (node->isAKindOf(ssgTypeTransform())) { + ssgTransform *scs = (ssgTransform *)node; + int i, n = scs->getNumKids(); + if (n <= 0) { + delete scs; + return 0; + } + else { + sgMat4 tmp; + scs->getTransform(tmp); + if (mat) + sgPostMultMat4(tmp, mat); + if (n == 1) { + node = scs->getKid(0); + node->ref(); scs->removeKid(0); node->deRef(); + delete scs; + assert(!node->isA(0xDeadBeef)); + return Flatten(node, tmp); + } + else { + ssgBranch *grp = new ssgBranch; + grp->setName(scs->getName()); + for (i = 0; i < n; i++) + grp->addKid(scs->getKid(i)); + while (n--) + scs->removeKid(n); + delete scs; + return Flatten(grp, tmp); + } + } + } + + /* recurse the scene graph */ + if (node->isAKindOf(ssgTypeBranch())) { + ssgBranch *grp = (ssgBranch *)node; + int i, n = grp->getNumKids(); + if (n <= 0) { + delete grp; + return 0; + } + else if (n == 1 && grp->isA(ssgTypeBranch())) { + ssgEntity *kid = grp->getKid(0); + kid->ref(); grp->removeKid(0); kid->deRef(); + delete grp; + assert(!kid->isA(0xDeadBeef)); + return Flatten(kid, mat); + } + else { + ssgEntity *kids[32]; + for (i = n; i--;) { + kids[i] = grp->getKid(i); + kids[i]->ref(); grp->removeKid(i); kids[i]->deRef(); + kids[i] = Flatten(kids[i], mat); + assert(kids[i] == 0 || !kids[i]->isA(0xDeadBeef)); + } + assert(!grp->isA(0xDeadBeef)); + for (i = 0; i < n; i++) { + if (kids[i]) { + assert(!kids[i]->isA(0xDeadBeef)); + grp->addKid(kids[i]); + } + } + grp->recalcBSphere(); + return grp; + } + } + + /* transform geometry */ + if (node->isAKindOf(ssgTypeVtxTable()) && mat) { + ssgVtxTable *g = (ssgVtxTable *)node; + sgVec3 *a; + int i, n; + n = g->getNumVertices(); + if (n > 0) { + g->getVertexList((void **)&a); + for (i = 0; i < n; i++) + sgXformPnt3(a[i], a[i], mat); + } + n = g->getNumNormals(); + if (n > 0) { + g->getNormalList((void **)&a); + for (i = 0; i < n; i++) + sgXformVec3(a[i], a[i], mat); + } + g->recalcBSphere(); + } + assert(!node->isA(0xDeadBeef)); + return node; +} +#endif + +static void Init(void) +{ + if (Inited) + return; + Inited = 1; + +#if !defined(USE_POSIX_MMAP) && !defined(USE_WIN32_MMAP) + ulSetError(UL_DEBUG, "[flt] Memory mapped files not enabled, please check source code."); +#endif + +#ifdef PROBE_ENDIAN + { + short tmp = 42; + if (*(char *)&tmp == 42) { + /* little endian */ + get16v = _swab16; + get32v = _swab32; + get64v = _swab64; + ulSetError(UL_DEBUG, "[flt] Little endian architecture."); + } + else { + /* big endian */ + get16v = _copy16; + get32v = _copy32; + get64v = _copy64; + ulSetError(UL_DEBUG, "[flt] Big endian architecture."); + } + } +#endif + + if (getenv("FLTNOTEX")) NoTextures = 1; + if (getenv("FLTNOMIPMAP")) NoMipmaps = 1; + if (getenv("FLTNOEXT")) NoExternals = 1; + if (getenv("FLTNOCLEAN")) NoClean = 1; + + return; +} + +ssgEntity *ssgLoadFLT(const char *filename, +#ifdef NO_LOADER_OPTIONS + ssgHookFunc +#else + const ssgLoaderOptions *options +#endif + ) +{ + static int depth = 0; + ssgEntity *node; + + if (depth == 0) { + + Init(); + + ObsoleteFlag = 0; + NotImplementedFlag = 0; + + TexCache = 0; + StateCache = 0; + FltCache = 0; + +#ifndef NO_LOADER_OPTIONS + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + LoaderOptions = ssgGetCurrentOptions () ; +#endif + + } + + // no longjmp()'s please! (or this recursion test will fail) + + depth++; + + node = LoadFLT(filename); + + depth--; + + if (depth == 0) { + + sfree(TexCache, S_KEY | S_DATA); + sfree(StateCache, S_KEY); + + if (node) node->ref(); // prevent this node from being deleted! + sfree(FltCache, S_KEY | S_TREE); + if (node) node->deRef(); + + } + +#if 0 + if (node && !NoClean) { + Flattened = 0; + node = Flatten(node, 0); + sfree(Flattened, 0); + } +#endif + +#if 0 /* debug */ + if (node && getenv("FLTDUMP")) { + const char *file = "/tmp/tree.txt"; + FILE *f = fopen(file, "w"); + if (f == 0) + perror(file); + else { + refs = 0; + nrefs = 0; + ptree(node, f, 0); + sfree(refs, 0); + fclose(f); + ulSetError(UL_DEBUG, "wrote %s", file); + } + } +#endif + + return node; +} +//lint -restore diff --git a/src/ssg/ssgLoadIV.cxx b/src/ssg/ssgLoadIV.cxx new file mode 100644 index 0000000..633b962 --- /dev/null +++ b/src/ssg/ssgLoadIV.cxx @@ -0,0 +1,381 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 William Lachance, Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net +*/ + +#include "ssgLocal.h" +#include "ssgParser.h" +#include "ssgLoaderWriterStuff.h" + +#include "ssgLoadVRML.h" + +static _ssgParserSpec parser_spec = +{ + "\r\n\t, ", // delim_chars_skipable + 0, // delim_chars_non_skipable + NULL, // pre_processor + "{[", // open_brace_chars + "}]", // close_brace_chars + '"', // quote_char + '#', // comment_char + 0 // comment_string +}; + +static ssgLoaderOptions* currentOptions = NULL ; +static _nodeIndex *definedNodes = NULL; + +static bool iv_parseSeparator( ssgBranch *parentBranch, _traversalState *parentData, char *defName ); +static bool iv_parseSwitch( ssgBranch *parentBranch, _traversalState *parentData, char *defName ); +static bool iv_parseIndexedFaceSet( ssgBranch *parentBranch, _traversalState *parentData, char *defName ); +static bool iv_parseTexture2( ssgBranch *parentBranch, _traversalState *currentData, char *defName ); + +static _parseTag ivTags [] = +{ + { "Separator", iv_parseSeparator }, + { "Switch", iv_parseSwitch }, + { "IndexedFaceSet", iv_parseIndexedFaceSet }, + { "Coordinate3", vrml1_parseCoordinate3 }, + { "TextureCoordinate2", vrml1_parseTextureCoordinate2 }, + { "Texture2", iv_parseTexture2 }, + { "ShapeHints", vrml1_parseShapeHints }, + { "MatrixTransform", vrml1_parseMatrixTransform }, + { "Scale", vrml1_parseScale }, + { "Rotation", vrml1_parseRotation }, + { "Translation", vrml1_parseTranslation }, + { NULL, NULL }, +}; + +ssgEntity *ssgLoadIV( const char *fname, const ssgLoaderOptions* options ) +{ + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + currentOptions = ssgGetCurrentOptions () ; + + if ( !vrmlParser.openFile( fname, &parser_spec ) ) { + ulSetError ( UL_WARNING, "ssgLoadIV: Failed to open '%s' for reading", fname ) ; + return 0; + } + + definedNodes = new _nodeIndex(); + + // check for a valid header header + char *token; + if( !(token = vrmlParser.getRawLine()) ) + return 0; + if( strstr( token, "#Inventor V2.1 ascii" ) == NULL ) // should we handle different flavours of inventor? + { + ulSetError ( UL_WARNING, "ssgLoadIV: valid iv header not found" ); + return 0; + } + + // creating a root node.. + ssgBranch *rootBranch = new ssgBranch(); + + vrmlParser.expectNextToken( "Separator" ); + + if( !iv_parseSeparator( rootBranch, NULL, NULL ) ) + { + ulSetError ( UL_WARNING, "ssgLoadVRML: Failed to extract valid object(s) from %s", fname ) ; + delete( rootBranch ); + delete( definedNodes ); + return NULL ; + } + + vrmlParser.closeFile(); + delete( definedNodes ); + + return rootBranch ; +} + +static bool iv_parseSeparator( ssgBranch *parentBranch, _traversalState *parentData, char *defName ) +{ + char *childDefName = NULL; + + char *token; + + vrmlParser.expectNextToken( "{" ); + + // create a branch for this node + ssgBranch *currentBranch = new ssgBranch(); + + if( defName != NULL ) + { + currentBranch->setName( defName ); + definedNodes->insert( currentBranch ); + } + + _traversalState *currentData; + if( parentData == NULL ) + currentData = new _traversalState(); + else + currentData = parentData->clone(); + + token = vrmlParser.getNextToken( NULL ); + while( strcmp( token, "}" ) ) + { + int i=0; bool tokenFound = FALSE; + while( ivTags[i].token != NULL && !tokenFound ) + { + if( !strcmp( token, ivTags[i].token ) ) + { + if( !(ivTags[i].func( currentBranch, currentData, childDefName ) ) ) + { + delete( currentBranch ); + delete( currentData ); + return FALSE; + } + tokenFound = TRUE; + } + + i++; + } + if( !tokenFound ) + parseUnidentified(); + + token = vrmlParser.getNextToken( NULL ); + } + + parentBranch->addKid( currentBranch ); + + delete( currentData ); // delete the currentData structure (we may use its content, but not its form) + + return TRUE; +} + +static bool iv_parseSwitch( ssgBranch *parentBranch, _traversalState *parentData, char *defName ) +// UNSUPPORTED BEHAVIOUR: does not do a check for a whichChild parameter. Assumes that a switch +// "hides" all of its children. +{ + char *childDefName = NULL; + + char *token; + + vrmlParser.expectNextToken( "{" ); + + // create a branch for this node + ssgBranch *currentBranch = new ssgSelector(); + ((ssgSelector *)currentBranch)->select( 0 ); // fixme: allow for children to be traversed + + + if( defName != NULL ) + { + currentBranch->setName( defName ); + definedNodes->insert( currentBranch ); + } + + _traversalState *currentData; + if( parentData == NULL ) + currentData = new _traversalState(); + else + currentData = parentData->clone(); + + token = vrmlParser.getNextToken( NULL ); + + while( strcmp( token, "}" ) ) + { + int i=0; bool tokenFound = FALSE; + while( ivTags[i].token != NULL && !tokenFound ) + { + if( !strcmp( token, ivTags[i].token ) ) + { + if( !(ivTags[i].func( currentBranch, currentData, childDefName ) ) ) + { + delete( currentBranch ); + delete( currentData ); + return FALSE; + } + + tokenFound = TRUE; + } + i++; + } + if( !tokenFound ) + parseUnidentified(); + + token = vrmlParser.getNextToken( NULL ); + } + + parentBranch->addKid( currentBranch ); + + delete( currentData ); // delete the currentData structure (we may use its content, but not its form) + + return TRUE; +} + +static bool iv_parseIndexedFaceSet( ssgBranch *parentBranch, _traversalState *currentData, char *defName ) +{ + char *token; + bool texCoordIndexGiven = FALSE; + + ssgBranch *currentBranch = new ssgBranch(); + if( defName != NULL ) + { + currentBranch->setName( defName ); + definedNodes->insert( currentBranch ); + } + + ssgLoaderWriterMesh *loaderMesh = new ssgLoaderWriterMesh(); + loaderMesh->createFaces(); + loaderMesh->setVertices( currentData->getVertices() ); + if( currentData->getTexture() != NULL && currentData->getTextureCoordinates() != NULL ) + loaderMesh->createPerFaceAndVertexTextureCoordinates2(); + + vrmlParser.expectNextToken("{"); + + token = vrmlParser.peekAtNextToken( NULL ); + while( strcmp( token, "}" ) ) + { + if( !strcmp( token, "coordIndex" ) ) + { + vrmlParser.expectNextToken("coordIndex"); + if( !vrml1_parseCoordIndex( loaderMesh, currentData ) ) + { + delete( loaderMesh ); + return FALSE; + } + } + + else if( !strcmp( token, "textureCoordIndex" ) ) + { + texCoordIndexGiven = TRUE; + vrmlParser.expectNextToken("textureCoordIndex"); + if( !vrml1_parseTextureCoordIndex( loaderMesh, currentData ) ) + { + delete( loaderMesh ); + return FALSE; + } + } + else + token = vrmlParser.getNextToken( NULL ); + + token = vrmlParser.peekAtNextToken( NULL ); + } + + //ulSetError(UL_DEBUG, "Level: %i. Found %i faces here.\n", vrmlParser.level, numFaces); + + vrmlParser.expectNextToken( "}" ); + + // ------------------------------------------------------- + // add the face set to ssg + // ------------------------------------------------------- + + // kludge. We need a state for addToSSG: + ssgSimpleState * ss = new ssgSimpleState () ; // (0) ? + ss -> setMaterial ( GL_AMBIENT, 0.5, 0.5, 0.5, 1.0); + ss -> setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0) ; // 0.8, 0.8, 1.0, 1.0f + ss -> setMaterial ( GL_SPECULAR, 1.0, 1.0, 1.0, 1.0); + ss -> setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 1.0); + ss -> setShininess ( 20 ) ; // Fixme, NIV14: Is that correct? + + // ------------------------------------------------------- + // texturing stuff + // ------------------------------------------------------- + // todo: give an implicit mapping if texture coordinates are not given + // todo: add support for per-vertex texturing + if( currentData->getTexture() != NULL && currentData->getTextureCoordinates() != NULL && texCoordIndexGiven ) + { + ss -> setTexture ( currentData->getTexture() ); + ss -> enable( GL_TEXTURE_2D ); + } + else + ss -> disable( GL_TEXTURE_2D ); + + ss -> disable ( GL_COLOR_MATERIAL ) ; + //ss -> enable ( GL_COLOR_MATERIAL ) ; + //ss -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + + ss -> enable ( GL_LIGHTING ) ; + ss -> setShadeModel ( GL_SMOOTH ) ; + + ss ->disable(GL_ALPHA_TEST); //needed? + + ss -> disable ( GL_BLEND ) ; + + ss -> setOpaque () ; + + if( !currentData->getEnableCullFace() ) + ss->disable( GL_CULL_FACE ); + + if( !loaderMesh->checkMe() ) + { + delete( loaderMesh ); + return FALSE; + } + + if( currentData->getTransform() != NULL ) + { + currentBranch->addKid( currentData->getTransform() ); // FIXME: in case we're reusing transforms, perhaps they should be reinstanced? (currently we don't allow this) + loaderMesh->addToSSG( ss, currentOptions, currentData->getTransform() ); + } + else + loaderMesh->addToSSG( ss, currentOptions, currentBranch ); + + parentBranch->addKid( currentBranch ); + + return TRUE; +} + +static bool iv_parseTexture2( ssgBranch *parentBranch, _traversalState *currentData, char *defName ) +{ + char *token; + char *fileName = NULL; bool wrapU = FALSE, wrapV = FALSE; + + vrmlParser.expectNextToken("{"); + + token = vrmlParser.peekAtNextToken( NULL ); + while( strcmp( token, "}" ) ) + { + if( !strcmp( token, "filename") ) + { + vrmlParser.expectNextToken("filename"); + if( !vrmlParser.getNextString( token, NULL ) ) + return FALSE; + fileName = ulStrDup ( token ) ; + } + else if( !strcmp( token, "wrapS") ) + { + vrmlParser.expectNextToken("wrapS"); + token = vrmlParser.getNextToken( NULL ); + if( !strcmp( token, "REPEAT") ) + wrapU = TRUE; + } + else if( !strcmp( token, "wrapT") ) + { + vrmlParser.expectNextToken("wrapT"); + token = vrmlParser.getNextToken( NULL ); + if( !strcmp( token, "REPEAT") ) + wrapV = TRUE; + } + else + token = vrmlParser.getNextToken( NULL ); + + token = vrmlParser.peekAtNextToken( NULL ); + } + + if( fileName == NULL ) + return FALSE; + + //ssgTexture *currentTexture = new ssgTexture( fileName, wrapU, wrapV ); + ssgTexture *currentTexture = currentOptions -> createTexture ( fileName, wrapU, wrapV ); + currentData->setTexture( currentTexture ); + vrmlParser.expectNextToken("}"); + + delete [] fileName; + + return TRUE; +} diff --git a/src/ssg/ssgLoadM.cxx b/src/ssg/ssgLoadM.cxx new file mode 100644 index 0000000..a2dad41 --- /dev/null +++ b/src/ssg/ssgLoadM.cxx @@ -0,0 +1,152 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadM.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + +#include +#include "ssgLocal.h" + +static ssgLoaderOptions* current_options; + +ssgEntity* ssgLoadM( const char* fname, + const ssgLoaderOptions* options ) { + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + current_options = ssgGetCurrentOptions () ; + + char filename [ 1024 ] ; + current_options -> makeModelPath ( filename, fname ) ; + + FILE* model_file = fopen(filename, "r"); + if(!model_file) { + ulSetError(UL_WARNING, "ssgLoadM: Couldn't open file '%s'.", + filename); + return NULL; + } + + ssgVertexArray* vertices = new ssgVertexArray; + ssgNormalArray* normals = new ssgNormalArray; + ssgIndexArray* indices = new ssgIndexArray; + + int i, index; + char line[256]; + sgVec3 zero = {0.0f, 0.0f, 0.0f}; + + fgets(line, 256, model_file); + while ( !feof(model_file) ) { + char* token; + + switch (line[0]) { + case '#': // comment, skip this line + break; + case 'V': + sgVec3 vtx; + token = strtok(line, " "); // token should now be "Vertex" + token = strtok(NULL, " "); // token is vertex index now + + index = atoi(token) - 1; + + // fill out non-declared vertices with zero vectors + while (index > vertices->getNum()) { + vertices->add(zero); + normals ->add(zero); + } + + // get vertex coordinate + for (i = 0; i < 3; i++) { + token = strtok(NULL, " "); + vtx[i] = (float) atof(token); + } + + vertices->add(vtx) ; + normals ->add(zero); + + break; + + case 'F': // face + token = strtok(line, " "); // token should now be "Face" + token = strtok(NULL, " "); // face index, ignored + + for (i = 0; i < 3; i++) { + token = strtok(NULL, " "); + indices->add( atoi(token)-1 ); + } + + break; + + case 'E': // Edge, ignored + break; + + default: + ulSetError(UL_WARNING, "ssgLoadM: Syntax error on line \"%s\".", line); + } + + fgets(line, 256, model_file); + } + + ssgSimpleState* state = new ssgSimpleState(); + state->setOpaque(); + state->disable(GL_BLEND); + state->disable(GL_ALPHA_TEST); + state->disable(GL_TEXTURE_2D); + state->enable(GL_COLOR_MATERIAL); + state->enable(GL_LIGHTING); + state->setShadeModel(GL_SMOOTH); + state->setMaterial(GL_AMBIENT , 0.7f, 0.7f, 0.0f, 1.0f); + state->setMaterial(GL_DIFFUSE , 0.7f, 0.7f, 0.0f, 1.0f); + state->setMaterial(GL_SPECULAR, 1.0f, 1.0f, 1.0f, 1.0f); + state->setMaterial(GL_EMISSION, 0.0f, 0.0f, 0.0f, 1.0f); + state->setShininess(50); + + // now calculate smooth normals (this code belongs elsewhere) + for (i = 0; i < indices->getNum(); i += 3) { + short idx0 = *indices->get(i ); + short idx1 = *indices->get(i + 1); + short idx2 = *indices->get(i + 2); + + sgVec3 normal; + sgMakeNormal( normal, + vertices->get(idx0), + vertices->get(idx1), + vertices->get(idx2) ); + + sgAddVec3( normals->get(idx0), normal ); + sgAddVec3( normals->get(idx1), normal ); + sgAddVec3( normals->get(idx2), normal ); + } + + for (i = 0; i < vertices->getNum(); i++) { + sgNormaliseVec3( normals->get(i) ); + } + + ssgVtxArray* leaf = new ssgVtxArray( GL_TRIANGLES, + vertices, + normals, + NULL, + NULL, + indices ); + + leaf->setCullFace( TRUE ); + leaf->setState( state ); + + ssgLeaf* model = current_options -> createLeaf( leaf, NULL ); + + return model; +} diff --git a/src/ssg/ssgLoadMD2.cxx b/src/ssg/ssgLoadMD2.cxx new file mode 100644 index 0000000..99a18a1 --- /dev/null +++ b/src/ssg/ssgLoadMD2.cxx @@ -0,0 +1,402 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadMD2.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + +/*************************************************************************** + ssgloadmd2.cpp - description + ------------------- + begin : Thu Sep 7 2000 + copyright : (C) 2000 by Jon Anderson + email : janderson@onelink.com + ***************************************************************************/ +/******************************************************* + ** This was written to be a part of Stephen J Bakers + ** PLIB (http://plib.sourceforge.net) + *******************************************************/ + +#include "ssgLocal.h" + +//defaults +#define FRAME_DELAY 3 +#define NUM_SEQUENCES 22 + +/** + MD2 file loader for SSG. + + ssgLoadMD2 loads a given MD2 file into an + ssgSelector hiearchy. Each animation sequence is + loaded into a ssgTimedSelector. Each sequence is + then put into a top level ssgSelector. In addition, + all the skins are loaded into a ssgStateSelector that + is attached to each frame's ssgVtxTable. Animation + sequences can then be played by: + + ssgSelector::selectStep ( SSG_MD2_STAND ); + ssgTimedSelector *ts = (ssgTimedSelector *)s -> getKid ( i ); + ts -> setMode ( SSG_ANIM_SHUTTLE ); + ts -> control ( SSG_ANIM_START ); + + + Notes: + -Not all md2 files will contain the complete animation + sequences. + -Not all md2 files contain skin info/locations. + -By default, it displays each animation frame for + 3 screen frames. MD2 animations were designed to be + played at ~ 10hz + + MD2 File format documentaion: + http://www.ugrad.cs.jhu.edu/~dansch/md2 + + MD2 Frames documentation: + http://www.planetquake.com/polycount/resources/quake2/q2frameslist.shtml + + MD2 Models: + http://www.planetquake.com/polycount/ + +*/ + + +/* +int seq_sizes[][2] = { + { SSG_MD2_STAND, 40 }, + { SSG_Md2_RUN, 6 }, + { SSG_MD2_ATTACK, 8 }, + { SSG_MD2_PAIN_1, 4 }, + { SSG_MD2_PAIN_2, 4 }, + { SSG_MD2_PAIN_3, 4 }, + { SSG_MD2_JUMP, 6 }, + { SSG_MD2_FLIPOFF,12 }, + { SSG_MD2_SALUTE, 11 }, + { SSG_MD2_TAUNT, 17 }, + { SSG_MD2_WAVE, 11 }, + { SSG_MD2_POINT, 12 }, + { SSG_MD2_CROUCH_STAND, 19 }, + { SSG_MD2_CROUCH_WALK, 9 }, + { SSG_MD2_CROUCH_ATTACK, 9 }, + { SSG_MD2_CROUCH_PAIN, 4 }, + { SSG_MD2_CROUCH_DEATH, 5 }, + { SSG_MD2_DEATH_1, 6 }, + { SSG_MD2_DEATH_2, 6 }, + { SSG_MD2_DEATH_3, 6 }, + { SSG_MD2_ALL, 1 }, + { SSG_MD2_POSE, 1 } +}; + +*/ + +static int seq_frames[] = { + 40, + 6, + 8, + 4, + 4, + 4, + 6, + 12, + 11, + 17, + 11, + 12, + 19, + 9, + 9, + 4, + 5, + 6, + 6, + 6, + 1, //this may or may not be in the file. + 1 //this may or may not be in the file. +}; + + +typedef struct +{ + int magic; + int version; + int skinWidth; + int skinHeight; + int frameSize; + int numSkins; + int numVertices; + int numTexCoords; + int numTriangles; + int numGlCommands; + int numFrames; + int offsetSkins; + int offsetTexCoords; + int offsetTriangles; + int offsetFrames; + int offsetGlCommands; + int offsetEnd; +} t_model; + +typedef struct +{ + unsigned char vertex[3]; + unsigned char lightNormalIndex; +} t_vertex; + + +typedef struct +{ + short vertexIndices[3]; + short textureIndices[3]; + +} t_triangle; + +typedef struct +{ + short s, t; +} t_tcoord; + +typedef struct +{ + float s, t; + int vertexIndex; +} t_glCommandVertex; + +typedef struct +{ + float scale[3]; + float translate[3]; + char name[16]; +} t_frame; + + +static int is_little_endian; + +static ssgLoaderOptions* current_options = NULL ; +static FILE *loader_fd; + +static t_tcoord *uvs; +static t_frame *frames; +static t_vertex **vertices; +static t_triangle *triangles; +static char skins[32][1024]; +static t_model header; + + +static void read_header() +{ + fread(&header, sizeof(t_model), 1, loader_fd); +} + +static void read_frames(int offset) +{ + fseek(loader_fd, offset, SEEK_SET); + + frames = new t_frame[header.numFrames]; + vertices = new t_vertex* [header.numFrames]; + + for(int i=0; i enable ( GL_TEXTURE_2D ); + //state -> setTexture( filepath ) ; + state -> setTexture( current_options -> createTexture ( skins[i] ) ); + states -> setStep ( i, state ); + } + + /**Activate the first state*/ + if(stated) + states -> selectStep( 0 ); + else { + ulSetError(UL_WARNING, "ssgLoadMD2: No skins specified in MD2 file!"); + ssgSimpleState *state = new ssgSimpleState(); + state -> disable ( GL_TEXTURE_2D ); + states -> setStep(0, state); + states -> selectStep( 0 ); + } + + ssgSelector *sequences; + + if(header.numFrames == 200) + sequences = new ssgSelector(NUM_SEQUENCES); + else + sequences = new ssgSelector(NUM_SEQUENCES - 2); + + int current_sequence_num = 0; + int current_sequence_frame = 0; + + ssgTimedSelector *current_sequence = new ssgTimedSelector(seq_frames[current_sequence_num]); + sequences->addKid(current_sequence); + + for(i=0; i-1; k--){ + int vert_index = triangles[j].vertexIndices[k]; + + int bx = vertices[i][vert_index].vertex[0]; + int by = vertices[i][vert_index].vertex[1]; + int bz = vertices[i][vert_index].vertex[2]; + + vert[0] = ((float)bx)*frames[i].scale[0] + frames[i].translate[0]; + vert[1] = ((float)by)*frames[i].scale[1] + frames[i].translate[1]; + vert[2] = ((float)bz)*frames[i].scale[2] + frames[i].translate[2]; + + uv[0] = ((float)uvs[triangles[j].textureIndices[k]].s)/header.skinWidth; + uv[1] = 1 - ((float)uvs[triangles[j].textureIndices[k]].t)/header.skinHeight; + + vlist -> add( vert ); + tlist -> add( uv ); + } + } + ssgVtxTable *vtab = new ssgVtxTable ( GL_TRIANGLES, vlist, 0, tlist, 0 ) ; + vtab -> setState(states); + + current_sequence ->addKid(vtab); + current_sequence_frame++; + + if( current_sequence_frame > seq_frames[current_sequence_num] -1){ + current_sequence -> setLimits( 0, seq_frames[current_sequence_num]-1 ); + current_sequence -> setDuration( FRAME_DELAY ); + current_sequence -> setMode ( SSG_ANIM_ONESHOT ); + + current_sequence_num ++; + current_sequence_frame = 0; + current_sequence = new ssgTimedSelector(seq_frames[current_sequence_num]); + sequences -> addKid( current_sequence ); + } + + } + + sequences -> selectStep( 0 ); + return sequences; + +} + + +ssgEntity * ssgLoadMD2( const char *filename, const ssgLoaderOptions* options) +{ + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + current_options = ssgGetCurrentOptions () ; + + int j = 1 ; + is_little_endian = *((char *) &j ); + + char filepath [ 1024 ] ; + current_options -> makeModelPath ( filepath, filename ) ; + + loader_fd = fopen ( filepath, "rb" ); + + if ( loader_fd == NULL ) { + ulSetError ( UL_WARNING, "ssgLoadMD2: Failed to open '%s' for reading", filepath ) ; + return NULL ; + } + + + read_header(); + read_skins(header.offsetSkins); + read_uvcoords(header.offsetTexCoords); + read_triangles(header.offsetTriangles); + read_frames(header.offsetFrames); + read_glcommands(header.offsetGlCommands); + + + ssgEntity * model = convert_to_ssg(); + + //clean up the memory used by the MD2 structure; + delete[] uvs; + delete[] frames; + delete[] triangles; + for(int i=0; i +// +// Revision: $Id: ssgLoadMDL.cxx 2012 2005-01-15 20:36:46Z sjbaker $ +// +// Description: +// +//=========================================================================== +// Copyright (c) 2000 Thomas E. Sevaldrud +//=========================================================================== + +#include "ssgLocal.h" + +// kludge: global +int g_noLoDs =1; + +#ifdef SSG_LOAD_MDL_SUPPORTED + +#include "ssgLoadMDL.h" + +#define DEF_SHININESS 50 + +//#define DEBUG + +#ifdef DEBUG +#include +#define DEBUGPRINT(x) std::cerr << x +#else +#define DEBUGPRINT(x) +#endif + +static ssgLoaderOptions *current_options; + +// Temporary vertex arrays +static ssgVertexArray *curr_vtx_; +static ssgNormalArray *curr_norm_; +static ssgIndexArray *curr_index_; + +// Vertex arrays +static ssgVertexArray *vertex_array_; +static ssgNormalArray *normal_array_; +static ssgTexCoordArray *tex_coords_; + +// Current part (index array) +static ssgLeaf *curr_part_; +static ssgBranch *model_; + +// Moving parts +static ssgBranch *ailerons_grp_, *elevator_grp_, *rudder_grp_; +static ssgBranch *gear_grp_, *spoilers_grp_, *flaps_grp_; +static ssgBranch *prop_grp_; + +static sgMat4 curr_matrix_; +static sgVec3 curr_rot_pt_; +static sgVec4 curr_col_; +static char *curr_tex_name_; +static ssgAxisTransform *curr_xfm_; + +int noGT=0, noLT=0, no0=0; + +#define EXPERIMENTAL_CULL_FACE_CODE +#ifdef EXPERIMENTAL_CULL_FACE_CODE +static bool curr_cull_face_; +#endif + +// File Address Stack +static const int MAX_STACK_DEPTH = 128; // wk: 32 is too small +static long stack_ [MAX_STACK_DEPTH]; // adress part +static short lod_ [MAX_STACK_DEPTH]; // lod part of the stack +static int stack_depth_; +static short noLoDs; +static short curr_lod; + +// static sgMat4 matrix_stack_ [MAX_STACK_DEPTH]; +// static char *textures_ [MAX_STACK_DEPTH]; +// static ssgBranch *groups_ [MAX_STACK_DEPTH]; + +static int start_idx_, last_idx_; +static int curr_var_; + +static bool has_normals_, vtx_dirty_, tex_vtx_dirty_; +//static bool join_children_, override_normals_; + +//static char *tex_fmt_; + +//=========================================================================== + +/*static void initLoader() +{ + start_idx_ = 0; + join_children_ = true; + override_normals_ = true; + tex_fmt_ = "tif"; + stack_depth_ = 0; +#ifdef EXPERIMENTAL_CULL_FACE_CODE + curr_cull_face_ = false ; +#endif +}*/ + +#ifdef DEBUG +FILE *wkfp; + +#define PRINT_STRUCTURE(a, b) fprintf(wkfp, a, b); +#define PRINT_STRUCTURE1(a ) fprintf(wkfp, a); + +#else + +#define PRINT_STRUCTURE(a, b) +#define PRINT_STRUCTURE1(a ) + +#endif + +//=========================================================================== + +static void newPart() +{ + vtx_dirty_ = true; + tex_vtx_dirty_ = true; + curr_tex_name_ = NULL; + sgSetVec4( curr_col_, 1.0f, 1.0f, 1.0f, 1.0f ); + + delete curr_vtx_; + delete curr_norm_; + curr_vtx_ = new ssgVertexArray ; + curr_norm_ = new ssgNormalArray ; +} + +//=========================================================================== + +static void push_stack( long entry, short lod ) { + assert( stack_depth_ < MAX_STACK_DEPTH - 1 ); + + lod_ [stack_depth_] = lod; + stack_[stack_depth_++] = entry; +} + +static long pop_stack(short &lod) { + assert( stack_depth_ > 0 ); + + lod = lod_[--stack_depth_]; + return stack_[stack_depth_]; +} + +//=========================================================================== + +static void recalcNormals() { + DEBUGPRINT( "Calculating normals." << std::endl); + sgVec3 n; + + for (int i = 0; i < curr_index_->getNum() - 2; i++) { + unsigned short ix0 = *curr_index_->get(i ); + unsigned short ix1 = *curr_index_->get(i + 1); + unsigned short ix2 = *curr_index_->get(i + 2); + + sgMakeNormal( n, + vertex_array_->get(ix0), + vertex_array_->get(ix1), + vertex_array_->get(ix2) ); + + sgCopyVec3( normal_array_->get(ix0), n ); + sgCopyVec3( normal_array_->get(ix1), n ); + sgCopyVec3( normal_array_->get(ix2), n ); + } +} + +//=========================================================================== + +static void readPoint(FILE* fp, sgVec3 p) +{ + short x_int, y_int, z_int; + y_int = ulEndianReadLittle16(fp); + z_int = ulEndianReadLittle16(fp); + x_int = ulEndianReadLittle16(fp); + + // Convert from .MDL units (ca 2mm) to meters + p[0] = -x_int/512.0f; + p[1] = y_int/512.0f; + p[2] = z_int/512.0f; +} + +//=========================================================================== + +// MtkPoint3D readPoint(FILE* fp) +// { +// short x_int, y_int, z_int; +// fread(&x_int, 2, 1, fp); +// fread(&y_int, 2, 1, fp); +// fread(&z_int, 2, 1, fp); + +// // Convert from .MDL units (ca 2mm) to meters +// MtkPoint3D p; +// p.x() = (double)x_int/512.0; +// p.y() = (double)y_int/512.0; +// p.z() = (double)z_int/512.0; + +// /* +// for(list::iterator i = matrix_stack_.begin(); +// i != matrix_stack_.end(); i++) +// { +// p = p*(*i); +// p += (*i).getCol(3); +// } +// */ + +// if(matrix_stack_.size() > 0) +// { +// MtkTransMatrix3D m = matrix_stack_.front(); +// p -= m.getCol(3); +// p = p*m; +// } + +// MtkPoint3D r; +// r.y() = p.x(); +// r.z() = -p.y(); +// r.x() = p.z(); + +// return r; +// } + +//=========================================================================== + +static void readVector(FILE* fp, sgVec3 v) +{ + short x_int, y_int, z_int; + y_int = ulEndianReadLittle16(fp); + z_int = ulEndianReadLittle16(fp); + x_int = ulEndianReadLittle16(fp); + + v[0] = -(float)x_int; + v[1] = (float)y_int; + v[2] = (float)z_int; + + sgNormaliseVec3( v ); +} + +//=========================================================================== +// for new lists, especially vertex list: + +struct oneVertex { + sgVec3 p, n; // point position, normal + sgVec2 tc; // texture coords +}; + +struct oneVertex *TheVertexList; // array. Kludge: only one allowed + +struct oneTexture { + char fname[64]; +}; + +struct oneTexture *TheTextureList; // array. Kludge: only one allowed +//=========================================================================== + +static void createTriangIndices(ssgIndexArray *ixarr, + int numverts, const sgVec3 s_norm, long dist) +{ + sgVec3 v1, v2, cross; + + if ( numverts > ixarr->getNum() ) { + ulSetError( UL_WARNING, "ssgLoadMDL: Index array with too few entries." ); + return; + } + + // triangulate polygons + if(numverts == 1) + { + unsigned short ix0 = *ixarr->get(0); + if ( ix0 >= vertex_array_->getNum() ) { + ulSetError(UL_WARNING, "ssgLoadMDL: Index out of bounds (%d/%d).", + ix0, vertex_array_->getNum() ); + return; + } + + curr_index_->add(ix0); + curr_index_->add(ix0); + curr_index_->add(ix0); + } + + else if(numverts == 2) + { + unsigned short ix0 = *ixarr->get(0); + unsigned short ix1 = *ixarr->get(1); + if ( ix0 >= vertex_array_->getNum() || + ix1 >= vertex_array_->getNum() ) { + ulSetError(UL_WARNING, "ssgLoadMDL: Index out of bounds. (%d,%d / %d", + ix0, ix1, vertex_array_->getNum() ); + return; + } + + curr_index_->add(ix0); + curr_index_->add(ix1); + curr_index_->add(ix0); + } + + else if(numverts == 3) + { + unsigned short ix0 = *ixarr->get(0); + unsigned short ix1 = *ixarr->get(1); + unsigned short ix2 = *ixarr->get(2); + if ( ix0 >= vertex_array_->getNum() || + ix1 >= vertex_array_->getNum() || + ix2 >= vertex_array_->getNum() ) { + ulSetError(UL_WARNING, "ssgLoadMDL: Index out of bounds. " \ + "(%d,%d,%d / %d)", ix0, ix1, ix2, vertex_array_->getNum()); + return; + } + + sgSubVec3(v1, + vertex_array_->get(ix1), + vertex_array_->get(ix0)); + sgSubVec3(v2, + vertex_array_->get(ix2), + vertex_array_->get(ix0)); + + sgVectorProductVec3(cross, v1, v2); + + if(sgScalarProductVec3(cross, s_norm) >= 0.0f) + { + curr_index_->add(ix0); + curr_index_->add(ix1); + curr_index_->add(ix2); + } + else + { + curr_index_->add(ix0); + curr_index_->add(ix2); + curr_index_->add(ix1); + } + } + + else + { + unsigned short ix0 = *ixarr->get(0); + unsigned short ix1 = *ixarr->get(1); + unsigned short ix2 = *ixarr->get(2); + if ( ix0 >= vertex_array_->getNum() || + ix1 >= vertex_array_->getNum() || + ix2 >= vertex_array_->getNum() ) { + ulSetError(UL_WARNING, "ssgLoadMDL: Index out of bounds. " \ + "(%d,%d,%d / %d)", ix0, ix1, ix2, vertex_array_->getNum()); + return; + } + + // Ensure counter-clockwise ordering + sgMakeNormal(cross, + vertex_array_->get(ix0), + vertex_array_->get(ix1), + vertex_array_->get(ix2)); + bool flip = (sgScalarProductVec3(cross, s_norm) < 0.0); + + curr_index_->add(ix0); + char tsA[99999]; + int bWrong=FALSE; + // a lot of debug output follows - sorry! + sprintf(tsA, "------- %ld %f\n%f, %f, %f\n", + dist, ((float)dist)/(512.0f*32767.0f), s_norm[0], s_norm[1], s_norm[2]); + for(int i = 1; i < numverts; i++) + { + ix1 = *ixarr->get( flip ? numverts-i : i); +// + SGfloat f = sgScalarProductVec3(s_norm, vertex_array_->get(ix1)); + sprintf(tsA, "%s%f, ", tsA, f); + f = f - ((float)dist)/(512.0f*32767.0f); + if((f<-0.5f) || (f>0.5f)) + bWrong = TRUE; +// + if ( ix1 >= vertex_array_->getNum() ) { + ulSetError(UL_WARNING, "ssgLoadMDL: Index out of bounds. (%d/%d)", + ix1, vertex_array_->getNum()); + continue; + } + + curr_index_->add(ix1); + } + if (bWrong) + printf("%s\n-------\n", tsA); + + } +} + +//=========================================================================== + +static bool readTexIndices(FILE *fp, int numverts, const sgVec3 s_norm, bool flip_y, long dist) +{ + ssgIndexArray temp_index_; + + if(numverts <= 0) + return false; + + if(tex_coords_->getNum() < + vertex_array_->getNum()) + { + sgVec2 dummy_pt; + sgSetVec2(dummy_pt, FLT_MAX, FLT_MAX); + for(int i = tex_coords_->getNum(); + i < vertex_array_->getNum(); i++) + tex_coords_->add(dummy_pt); + } + + // Read index values and texture coordinates + for(int v = 0; v < numverts; v++) + { + unsigned short ix; + short tx_int, ty_int; + + ix = ulEndianReadLittle16(fp); + tx_int = ulEndianReadLittle16(fp); + ty_int = ulEndianReadLittle16(fp); + + if (flip_y) { + ty_int = 255 - ty_int; + } + + int tex_idx = ix - start_idx_ + last_idx_; + + sgVec2 tc; + sgSetVec2(tc, tx_int/255.0f, ty_int/255.0f); + + sgVec2 curr_tc; + + if ( tex_idx >= 0 && tex_idx < tex_coords_->getNum() ) { + sgCopyVec2(curr_tc, tex_coords_->get(tex_idx)); + } else { + ulSetError( UL_WARNING, "ssgLoadMDL: Texture coord out of range (%d).", + tex_idx ); + continue; + } + + double dist = sgDistanceVec2(curr_tc, tc); + + if((curr_tc[0] >= FLT_MAX - 1 && curr_tc[1] >= FLT_MAX - 1)) + { + //DEBUGPRINT( "." ); + sgCopyVec2(tex_coords_->get(tex_idx), tc); + } + + else if(dist > 0.0001) + { + // We have a different texture coordinate for an existing vertex, + // so we have to copy this vertex and create a new index for it + // to get the correct texture mapping. + + //DEBUGPRINT( "duplicating texture coordinate!\n"); + + int idx = ix - start_idx_ + last_idx_; + tex_idx = vertex_array_->getNum(); + + ssgVertexArray* vtx_arr = vertex_array_; //curr_vtx_; + ssgNormalArray* norm_arr = normal_array_; //curr_norm_; + + sgVec3 vtx, nrm; + sgCopyVec3( vtx, vtx_arr ->get(idx) ); + sgCopyVec3( nrm, norm_arr->get(idx) ); + vtx_arr ->add(vtx); + norm_arr->add(nrm); + + tex_coords_->add(tc); + } + + temp_index_.add(tex_idx); + +#ifdef DEBUG + int check_index = *temp_index_.get(v); + float *check_tc = tex_coords_->get(check_index); + DEBUGPRINT( "ix[" << v << "] = " << check_index << + " (u=" << check_tc[0] << ", v=" << + check_tc[1] << ")" << std::endl); +#endif + + } + + createTriangIndices(&temp_index_, numverts, s_norm, dist); + + return true; +} + +//=========================================================================== + +static bool readIndices(FILE* fp, int numverts, const sgVec3 s_norm, long dist) +{ + ssgIndexArray temp_index_; + + if(numverts <= 0) + return false; + + // Read index values + for(int v = 0; v < numverts; v++) + { + unsigned short ix; + ix = ulEndianReadLittle16(fp); + temp_index_.add(ix - start_idx_ + last_idx_); + DEBUGPRINT( "ix[" << v << "] = " << *temp_index_.get(v) << std::endl); + } + + createTriangIndices(&temp_index_, numverts, s_norm, dist); + + return true; +} + +//=========================================================================== + +static void setColor(int color, int pal_id) +{ + if(pal_id == 0x68) + { + curr_col_[0] = fsAltPalette[color].r / 255.0f; + curr_col_[1] = fsAltPalette[color].g / 255.0f; + curr_col_[2] = fsAltPalette[color].b / 255.0f; + curr_col_[3] = 0.2f; + } + else + { + curr_col_[0] = fsAcPalette[color].r / 255.0f; + curr_col_[1] = fsAcPalette[color].g / 255.0f; + curr_col_[2] = fsAcPalette[color].b / 255.0f; + curr_col_[3] = 1.0f; + } +} + +//=========================================================================== + +static void setColor(int r, int g, int b, int attr) +{ + curr_col_[0] = r / 255.0f; + curr_col_[1] = g / 255.0f; + curr_col_[2] = b / 255.0f; + if(attr < 239) + curr_col_[3] = 0.2f; +} + +//=========================================================================== + +static bool setTexture(char* name) +{ + curr_tex_name_ = name; + + return true; +} + +//=========================================================================== + +static ssgSimpleState *createState(bool use_texture) +{ + DEBUGPRINT("new State: col = " << curr_col_[0] << ", " << curr_col_[1] << + ", " << curr_col_[2] << ", " << curr_col_[3]); + if ( curr_tex_name_ == NULL ) + DEBUGPRINT(", tex = " << std::endl); + else + DEBUGPRINT(", tex = " << curr_tex_name_ << std::endl); + + ssgSimpleState *state = new ssgSimpleState(); + + state->setShininess(DEF_SHININESS); + state->setShadeModel(GL_SMOOTH); + + state->enable (GL_LIGHTING); + state->enable (GL_CULL_FACE); + state->disable (GL_COLOR_MATERIAL); + + if(curr_col_[3] < 0.99f) + { + state->setTranslucent(); + state->enable(GL_BLEND); + state->enable(GL_ALPHA_TEST); + } + else + { + state->setOpaque(); + state->disable(GL_BLEND); + state->disable(GL_ALPHA_TEST); + } + + if(curr_tex_name_ != NULL && use_texture) + { + state->setMaterial( GL_AMBIENT, 1.0f, 1.0f, 1.0f, curr_col_[3]); + state->setMaterial( GL_DIFFUSE, 1.0f, 1.0f, 1.0f, curr_col_[3]); + state->enable(GL_TEXTURE_2D); + state->setTexture( current_options -> + createTexture(curr_tex_name_, FALSE, FALSE) ) ; + } + else + { + state->setMaterial( GL_AMBIENT, curr_col_); + state->setMaterial( GL_DIFFUSE, curr_col_); + state->disable(GL_TEXTURE_2D); + } + + state->setMaterial( GL_SPECULAR, 1.0f, 1.0f, 1.0f, curr_col_[3] ); + state->setMaterial( GL_EMISSION, 0.0f, 0.0f, 0.0f, 1.0f ); + + return state; +} + +static ssgBranch *getCurrGroup() { + //Find the correct parent for the new group + if(curr_xfm_) + return curr_xfm_; + else + { + return model_; + } +} + +//=========================================================================== + +// wk : It's not completely clear to me whether the following two functions can not be merged; Oh well. +// CreateAndAddLeaf1 is called then faces are created and then CreateAndAddLeaf2 is called + + +static void CreateAndAddLeaf1(GLenum ty, ssgTexCoordArray *tex_coords_P, bool use_texture) +{ + curr_index_ = new ssgIndexArray(); + curr_part_ = new ssgVtxArray( ty, vertex_array_, + normal_array_, + tex_coords_P, + NULL, + curr_index_ ); + curr_part_->setState( createState(true) ); + char sName[10]; + sprintf(sName, "lod %d", (int)curr_lod); + curr_part_->setName(sName); +} + +static void CreateAndAddLeaf2() +{ + ssgBranch* grp = getCurrGroup(); + ((ssgVtxArray *)curr_part_)->removeUnusedVertices(); + grp->addKid( current_options -> createLeaf(curr_part_, NULL) ); +} + + + +//=========================================================================== + +static ssgBranch *getMPGroup(int var) +{ + + switch(var) + { + case 0x4c: // Rudder + if(!rudder_grp_) + { + rudder_grp_ = new ssgBranch(); + rudder_grp_->setName("rudder"); + model_->addKid(rudder_grp_); + } + return rudder_grp_; + break; + + case 0x4e: // Elevator + if(!elevator_grp_) + { + elevator_grp_ = new ssgBranch(); + elevator_grp_->setName("elevator"); + model_->addKid(elevator_grp_); + } + return elevator_grp_; + break; + + case 0x6a: // Ailerons + if(!ailerons_grp_) + { + ailerons_grp_ = new ssgBranch(); + ailerons_grp_->setName("ailerons"); + model_->addKid(ailerons_grp_); + } + return ailerons_grp_; + break; + + case 0x6c: // Flaps + if(!flaps_grp_) + { + flaps_grp_ = new ssgBranch(); + flaps_grp_->setName("flaps"); + model_->addKid(flaps_grp_); + } + return flaps_grp_; + break; + + case 0x6e: // Gear + if(!gear_grp_) + { + gear_grp_ = new ssgBranch(); + gear_grp_->setName("gear"); + model_->addKid(gear_grp_); + } + return gear_grp_; + break; + + case 0x7c: // Spoilers + if(!spoilers_grp_) + { + spoilers_grp_ = new ssgBranch(); + spoilers_grp_->setName("spoilers"); + model_->addKid(spoilers_grp_); + } + return spoilers_grp_; + break; + + case 0x58: + case 0x7a: // Propeller + if(!prop_grp_) + { + prop_grp_ = new ssgBranch(); + prop_grp_->setName("propeller"); + model_->addKid(prop_grp_); + } + return prop_grp_; + break; + + default: + return model_; + } + return NULL; +} + +//=========================================================================== + +static void getMPLimits(int var, float *min, float *max) +{ + switch(var) + { + case 0x4c: // Rudder + *min = -30.0; + *max = 30.0; + break; + + case 0x4e: // Elevator + *min = -30.0; + *max = 30.0; + break; + + case 0x6a: // Ailerons + *min = -30.0; + *max = 30.0; + break; + + case 0x6c: // Flaps + *min = 0.0; + *max = 70.0; + break; + + case 0x6e: // Gear + *min = 0.0; + *max = -90.0; + break; + + case 0x7c: // Spoilers + *min = 0.0; + *max = 90.0; + break; + + case 0x58: + case 0x7a: // Propeller + *min = 0.0; + *max = 360.0; + break; + } +} + + + +void ParseBGL(FILE *fp) // "traversing" through the file +{ + bool done = false; + while(!feof(fp) && !done) + { + unsigned int skip_offset = 0; + + PRINT_STRUCTURE( "offset %lx\n", (long)ftell(fp)) + unsigned short opcode = ulEndianReadLittle16(fp); + + DEBUGPRINT( "opcode = " << std::hex << opcode << std::dec << " at address" << ftell(fp)-2 // -2 since opcode has already been read + << std::endl ); + + switch(opcode) + { + case 0x23: // BGL_CALL + { + short offset; + offset = ulEndianReadLittle16(fp); + long addr = ftell(fp); + DEBUGPRINT( "BGL_CALL(" << offset << ")\n" ); + push_stack(addr, curr_lod); + long dst = addr + offset - 4; + fseek(fp, dst, SEEK_SET); + + + PRINT_STRUCTURE( "call %lx\n", (long)offset) + } + break; + + case 0x8a: // BGL_CALL32 + { + int offset; + offset = ulEndianReadLittle32(fp); + long addr = ftell(fp); + DEBUGPRINT( "BGL_CALL32(" << offset << ")\n" ); + PRINT_STRUCTURE( "call32 %lx\n", (long)offset) + push_stack(addr, curr_lod); + long dst = addr + offset - 6; + fseek(fp, dst, SEEK_SET); + } + break; + + case 0x0d: // BGL_JUMP + { + short offset; + offset = ulEndianReadLittle16(fp); + PRINT_STRUCTURE( "jump %lx\n", (long)offset) + long addr = ftell(fp); + long dst = addr + offset - 4; + fseek(fp, dst, SEEK_SET); + DEBUGPRINT( "BGL_JUMP(" << offset << ")\n" ); + } + break; + + case 0x88: // BGL_JUMP32 + { + int offset; + offset = ulEndianReadLittle32(fp); + long addr = ftell(fp); + DEBUGPRINT( "BGL_JUMP32(" << offset << ")\n" ); + PRINT_STRUCTURE( "jump32 %lx\n", (long)offset) + long dst = addr + offset - 6; + fseek(fp, dst, SEEK_SET); + } + break; + + case 0x8e: // BGL_VFILE_MARKER + { + short offset; + offset = ulEndianReadLittle16(fp); + DEBUGPRINT( "vars: " << offset << std::endl); + break; + } + + case 0x39: // BGL_IFMSK + { + short offset, var, mask; + offset = ulEndianReadLittle16(fp); + var = ulEndianReadLittle16(fp); + mask = ulEndianReadLittle16(fp); + long addr = ftell(fp); + long dst = addr + offset - 8; + DEBUGPRINT( "BGL_IFMSK(" << offset << ", 0x" << std::hex << var << + ", 0x" << mask << std::dec << ")\n" ); + // if(var & mask == 0) + PRINT_STRUCTURE( "if msk %lx\n", (long)offset) + switch(var) + { + case 0x7e: + fseek(fp, dst, SEEK_SET); + break; + + default: + break; + } + } + break; + + case 0x24: // BGL_IFIN1 + { + short offset, lo, hi; + unsigned short var; + offset = ulEndianReadLittle16(fp); + var = ulEndianReadLittle16(fp); + lo = ulEndianReadLittle16(fp); + hi = ulEndianReadLittle16(fp); + DEBUGPRINT( "BGL_IFIN1(" << offset << ", 0x" << std::hex << var << + ", " << std::dec << lo << ", " << hi << ")\n" ); + PRINT_STRUCTURE( "ifin1 %lx\n", (long)offset) + curr_var_ = var; + } + break; + + case 0x46: // BGL_POINT_VICALL + { + short offset, var_rot_x, var_rot_y, var_rot_z; + unsigned short int_rot_x, int_rot_y, int_rot_z; + offset = ulEndianReadLittle16(fp); + sgVec3 ctr; + readPoint(fp, ctr); + + int_rot_y = ulEndianReadLittle16(fp); + var_rot_y = ulEndianReadLittle16(fp); + + int_rot_x = ulEndianReadLittle16(fp); + var_rot_x = ulEndianReadLittle16(fp); + + int_rot_z = ulEndianReadLittle16(fp); + var_rot_z = ulEndianReadLittle16(fp); + + float rx = 360.0f*(float)int_rot_x/0xffff; + float ry = 360.0f*(float)int_rot_y/0xffff; + float rz = 360.0f*(float)int_rot_z/0xffff; + + // We build a rotation matrix by adding all constant + // rotations (int_rot_*) to current_matrix_. As soon as we reach + // the actual variable rotation, we multiply + // the axis of the variable rotation with our current matrix. + // This will be the axis of rotation in the original coordinate + // system. This can now be inserted into a GngLinearControl + // transform. + if(var_rot_x > 0 || var_rot_y > 0 || var_rot_z > 0) + { + ssgAxisTransform* tmp = NULL; + if(curr_xfm_) + tmp = curr_xfm_; + curr_xfm_ = new ssgAxisTransform(); + curr_xfm_->setCenter(curr_rot_pt_); + + int var = 0; + if(var_rot_x > 0) + var = var_rot_x; + else if(var_rot_y > 0) + var = var_rot_y; + else if(var_rot_z > 0) + var = var_rot_z; + + float min_limit, max_limit; + getMPLimits(var, & min_limit, & max_limit); + + sgVec3 axis = { (float)var_rot_y, (float)var_rot_z, + (float)var_rot_x }; + sgNormaliseVec3( axis ) ; + sgXformVec3( axis, curr_matrix_ ) ; + sgNegateVec3(axis); + curr_xfm_->setAxis(axis); + curr_xfm_->setRotationLimits(min_limit, max_limit); + + char name[256]; + sprintf(name, "ssgAxisRotation(%x)", var); + curr_xfm_->setName(name); + if(tmp) + tmp->addKid(curr_xfm_); + else + { + ssgBranch* grp = getMPGroup(var); + grp->addKid(curr_xfm_); + } + } + + // Build up the constant rotations + sgMat4 rot_mat; + sgMakeRotMat4( rot_mat, ry, rz, rx ); + sgPostMultMat4( curr_matrix_, rot_mat ); + sgAddVec3( curr_rot_pt_, ctr ); + + long addr = ftell(fp); + long dst = addr + offset - 22; + fseek(fp, dst, SEEK_SET); + push_stack(addr, curr_lod); + + break; + } + + case 0x5f: // BGL_IFSIZEV + { + short offset; + unsigned short real_size, pixels_ref; + offset = ulEndianReadLittle16(fp); + real_size = ulEndianReadLittle16(fp); + pixels_ref = ulEndianReadLittle16(fp); + DEBUGPRINT("BGL_IFSIZEV: jmp = " << offset << ", sz = " << + real_size << ", px = " << pixels_ref << std::endl); + PRINT_STRUCTURE( "ifsizev!! %lx\n", (long)offset) + long addr = ftell(fp); + long dst = addr + offset - 8; + fseek(fp, dst, SEEK_SET); + push_stack(addr, ++noLoDs); + break; + } + + case 0x3b: // BGL_VINSTANCE + { + short offset, var; + offset = ulEndianReadLittle16(fp); + var = ulEndianReadLittle16(fp); + long addr = ftell(fp); + long var_abs = addr + var - 6; + fseek(fp, var_abs, SEEK_SET); + float p = 360.0f * (float)ulEndianReadLittle32(fp) / 0xffffffff; + float r = 360.0f * (float)ulEndianReadLittle32(fp) / 0xffffffff; + float h = 360.0f * (float)ulEndianReadLittle32(fp) / 0xffffffff; + sgMat4 rot_mat; + sgMakeRotMat4(rot_mat, h, p, r); + sgPostMultMat4(curr_matrix_, rot_mat); + DEBUGPRINT( "BGL_VINSTANCE(" << offset << ", h=" << h << ", p=" << + p << ", r=" << r << ")\n"); + long dst = addr + offset - 6; + fseek(fp, dst, SEEK_SET); + } + break; + + case 0x0: // EOF + case 0x22: // BGL return + { + curr_xfm_ = NULL; + sgMakeIdentMat4( curr_matrix_ ); + sgZeroVec3( curr_rot_pt_ ); + curr_var_ = 0; + DEBUGPRINT( "BGL return\n\n"); + PRINT_STRUCTURE1("return\n"); + if(stack_depth_ == 0) + done = true; + else + { + long addr = pop_stack(curr_lod); + fseek(fp, addr, SEEK_SET); + } + } + break; + + case 0x1a: // RESLIST (point list with no normals) + { + newPart(); + has_normals_ = false; + + start_idx_ = ulEndianReadLittle16(fp); + unsigned short numpoints = ulEndianReadLittle16(fp); + + DEBUGPRINT( "New group (unlit): start_idx = " << start_idx_ + << ", num vertices = " << numpoints << std::endl); + + sgVec3 null_normal; + sgZeroVec3( null_normal ); + + for(int i = 0; i < numpoints; i++) + { + sgVec3 p; + readPoint(fp, p); + curr_vtx_->add(p); + curr_norm_->add(null_normal); + } + } + break; + + case 0x29: // GORAUD RESLIST (point list with normals) + { + newPart(); + has_normals_ = true; + + start_idx_ = ulEndianReadLittle16(fp); + unsigned short numpoints = ulEndianReadLittle16(fp); + + DEBUGPRINT( "New group (goraud): start_idx = " << start_idx_ + << ", num vertices = " << numpoints << std::endl); + + for(int i = 0; i < numpoints; i++) + { + sgVec3 p; + readPoint(fp, p); + sgVec3 v; + readVector(fp, v); + curr_vtx_->add(p); + curr_norm_->add(v); + } + } + break; + + case 0x0f: // STRRES: Start line definition + { + unsigned short idx = ulEndianReadLittle16(fp); + DEBUGPRINT( "Start line: idx = " << idx << std::endl); + if(vtx_dirty_) + { + last_idx_ = vertex_array_->getNum(); + for(int i = 0; i < curr_vtx_->getNum(); i++) + { + vertex_array_->add(curr_vtx_ ->get(i)); + normal_array_->add(curr_norm_->get(i)); + } + vtx_dirty_ = false; + } + CreateAndAddLeaf1(GL_LINES, NULL, false); +#ifdef EXPERIMENTAL_CULL_FACE_CODE + curr_part_->setCullFace ( curr_cull_face_ ) ; +#endif + + curr_index_->add(idx - start_idx_ + last_idx_); + ssgBranch *grp = getCurrGroup(); + grp->addKid(curr_part_); + + //assert(curr_part_->getState()->getTexture() == NULL); + } + break; + + case 0x10: // CNTRES: Continue line definition + { + unsigned short idx = ulEndianReadLittle16(fp); + DEBUGPRINT( "Cont. line: idx = " << idx << std::endl); + curr_index_->add(idx - start_idx_ + last_idx_); + } + break; + + case 0x20: + case 0x7a: // Goraud shaded Texture-mapped ABCD Facet + { + if(tex_vtx_dirty_) + { + last_idx_ = vertex_array_->getNum(); + for(int i = 0; i < curr_vtx_->getNum(); i++) + { + vertex_array_->add(curr_vtx_ ->get(i)); + normal_array_->add(curr_norm_->get(i)); + } + tex_vtx_dirty_ = false; + } + CreateAndAddLeaf1(GL_TRIANGLE_FAN, tex_coords_, true); + + //assert(curr_part_->getState()->getTexture() != NULL); + + unsigned short numverts = ulEndianReadLittle16(fp); + DEBUGPRINT( "New part: (goraud/texture), num indices = " << + numverts << std::endl); + + // Normal vector + sgVec3 v; + readVector(fp, v); + + // Dot product reference +#ifdef EXPERIMENTAL_CULL_FACE_CODE + long l = ulEndianReadLittle32(fp) ; + if(l>0) + noGT++; + else if (l<0) + noLT++; + if((v[0]==0) && (v[1]==0) && (v[2]==0)) + no0++; + //rr_part_->setCullFace ( curr_cull_face_ ) ; + +#else + ulEndianReadLittle32(fp); +#endif + // Read vertex indices and texture coordinates + bool flip_y = FALSE; + if(curr_tex_name_!=NULL) + { char *texture_extension = + curr_tex_name_ + strlen(curr_tex_name_) - 3; + flip_y = ulStrEqual( texture_extension, "BMP" ) != 0 ; + } + /*old: + char *texture_extension = + curr_tex_name_ + strlen(curr_tex_name_) - 3; + bool flip_y = ulStrEqual( texture_extension, "BMP" ); + */ + readTexIndices(fp, numverts, v, flip_y, l); // adds stuff to curr_index_ + + if(!has_normals_) + { + while (normal_array_->getNum() < vertex_array_->getNum()) + normal_array_->add(v); + recalcNormals(); + } + CreateAndAddLeaf2(); + } + break; + + case 0x60: // BGL_FACE_TMAP + { + if(tex_vtx_dirty_) + { + last_idx_ = vertex_array_->getNum(); + for(int i = 0; i < curr_vtx_->getNum(); i++) + { + vertex_array_->add(curr_vtx_ ->get(i)); + normal_array_->add(curr_norm_->get(i)); + } + tex_vtx_dirty_ = false; + } + + CreateAndAddLeaf1(GL_TRIANGLE_FAN, tex_coords_, true); + +#ifdef EXPERIMENTAL_CULL_FACE_CODE + curr_part_->setCullFace ( curr_cull_face_ ) ; +#endif + //assert(curr_part_->getState()->getTexture() != NULL); + + unsigned short numverts = ulEndianReadLittle16(fp); + DEBUGPRINT( "New part: (goraud/texture), num indices = " << + numverts << std::endl); + + // Point in polygon + sgVec3 p; + readPoint(fp, p); + + // Normal vector + sgVec3 v; + readVector(fp, v); + + // Read vertex inidices and texture coordinates + bool flip_y = FALSE; + if(curr_tex_name_!=NULL) + { char *texture_extension = + curr_tex_name_ + strlen(curr_tex_name_) - 3; + flip_y = ulStrEqual( texture_extension, "BMP" ) != 0 ; + } + /* + char *texture_extension = + curr_tex_name_ + strlen(curr_tex_name_) - 3; + bool flip_y = ulStrEqual( texture_extension, "BMP" ); + */ + readTexIndices(fp, numverts, v, flip_y, -11); + + if(!has_normals_) + { + while (normal_array_->getNum() < vertex_array_->getNum()) + normal_array_->add(v); + recalcNormals(); + } + + CreateAndAddLeaf2(); + } + break; + + case 0x1d: // BGL_FACE + { + if(vtx_dirty_) + { + last_idx_ = vertex_array_->getNum(); + for(int i = 0; i < curr_vtx_->getNum(); i++) + { + vertex_array_->add(curr_vtx_->get(i)); + normal_array_->add(curr_norm_->get(i)); + } + vtx_dirty_ = false; + } + + CreateAndAddLeaf1(GL_TRIANGLE_FAN, NULL, false); + +#ifdef EXPERIMENTAL_CULL_FACE_CODE + curr_part_->setCullFace ( curr_cull_face_ ) ; +#endif + //assert(curr_part_->getState()->getTexture() == NULL); + + unsigned short numverts = ulEndianReadLittle16(fp); + DEBUGPRINT( "BGL_FACE: num indices = " << numverts << std::endl); + + sgVec3 p; + readPoint(fp, p); + // Surface normal + sgVec3 v; + readVector(fp, v); + + // Read vertex indices + readIndices(fp, numverts, v, -11); + + if(!has_normals_) + { + while (normal_array_->getNum() < vertex_array_->getNum()) + normal_array_->add(v); + recalcNormals(); + } + + CreateAndAddLeaf2(); + } + break; + + case 0x3e: // FACETN (no texture) + case 0x2a: // Goraud shaded ABCD Facet + { + if(vtx_dirty_) + { + last_idx_ = vertex_array_->getNum(); + for(int i = 0; i < curr_vtx_->getNum(); i++) + { + vertex_array_->add(curr_vtx_->get(i)); + normal_array_->add(curr_norm_->get(i)); + } + vtx_dirty_ = false; + } + + CreateAndAddLeaf1(GL_TRIANGLE_FAN, NULL, false); + + //assert(curr_part_->getState()->getTexture() == NULL); + + unsigned short numverts = ulEndianReadLittle16(fp); + DEBUGPRINT( "BGL_FACETN: num indices = " << numverts << std::endl); + + // Surface normal + sgVec3 v; + readVector(fp, v); + + // dot-ref +#ifdef EXPERIMENTAL_CULL_FACE_CODE + long l = ulEndianReadLittle32(fp) ; + if(l>0) + noGT++; + else if (l<0) + noLT++; + if((v[0]==0) && (v[1]==0) && (v[2]==0)) + no0++; + //rr_part_->setCullFace ( curr_cull_face_ ) ; + +#else + ulEndianReadLittle32(fp); +#endif + // Read vertex indices + readIndices(fp, numverts, v, l); + + if(!has_normals_) + { + while (normal_array_->getNum() < vertex_array_->getNum()) + normal_array_->add(v); + recalcNormals(); + } + + CreateAndAddLeaf2(); + } + break; + + case 0x18: // Set texture + { + unsigned short id, dx, scale, dy; + id = ulEndianReadLittle16(fp); + dx = ulEndianReadLittle16(fp); + scale = ulEndianReadLittle16(fp); + dy = ulEndianReadLittle16(fp); + char tex_name[14]; + fread(tex_name, 1, 14, fp); + static char tex_filename[14]; + int j = 0; + for(int i = 0; i < 14; i++) + { + if(!isspace(tex_name[i])) + tex_filename[j++] = tolower(tex_name[i]); + } + tex_filename[j] = '\0'; + DEBUGPRINT( "Set texture: name = " << tex_filename << ", id = " << id + << ", dx = " << dx << ", dy = " << dy << ", scale = " << + scale << std::endl); + setTexture(tex_filename); + } + break; + + case 0x43: // TEXTURE2 + { + unsigned short length, idx; + unsigned char flags, chksum; + unsigned int color; + static char tex_filename[128]; + length = ulEndianReadLittle16(fp); + idx = ulEndianReadLittle16(fp); + fread(&flags, 1, 1, fp); + fread(&chksum, 1, 1, fp); + color = ulEndianReadLittle32(fp); + if(chksum != 0) + { + DEBUGPRINT( "warning: TEXTURE2 Checksum != 0\n"); + } + + char c; + int i = 0; + while((c = getc(fp)) != 0) + { + if(!isspace(c)) + tex_filename[i++] = tolower(c); + } + tex_filename[i] = '\0'; + + // Padding byte + if((strlen(tex_filename) + 1) % 2) + c = getc(fp); + + DEBUGPRINT( "TEXTURE2: Set texture: name = " << tex_filename << + std::endl); + setTexture(tex_filename); + break; + } + + case 0x50: // GCOLOR (Goraud shaded color) + case 0x51: // LCOLOR (Line color) + case 0x52: // SCOLOR (Light source shaded surface color) + { + unsigned char color, param; + fread(&color, 1, 1, fp); + fread(¶m, 1, 1, fp); + DEBUGPRINT( "Set color = " << (int)color << " (" << std::hex << + (int)param << std::dec << ")\n"); + setColor((int)color, (int)param); + } + break; + + case 0x2D: // BGL_SCOLOR24 + { + unsigned char col[4]; + fread(col, 1, 4, fp); + DEBUGPRINT( "color = " << (int)col[0] << ", " << (int)col[2] << + ", " << (int)col[3] << ", " << (int)col[1] << std::endl); + setColor(col[0], col[2], col[3], col[1]); + break; + } + + + //------------------------------------------- + // The next code is either ignored + // or for experimental use.. + //------------------------------------------- + + case 0x03: + { + //DEBUGPRINT( "BGL_CASE\n" ); + unsigned short number_cases = ulEndianReadLittle16(fp); + skip_offset = 6 + 2 * number_cases; + PRINT_STRUCTURE1("case :-( !!\n"); + } + break; + + case 0xB0: //BGLOP_CRASH_OCTTREE + { +/* from scdis code by Takuya Murakami: + + 2 Jump Offset + 2 Crash Type (See CRASH_FLAG_xxx in makemdl.exe) + 2 # of nodes + 4*3 box x/y/z + 4*3 box w/h/d + 1*8 ? + 1*8*(# of nodes) ? +*/ + + ulEndianReadLittle32(fp); // ignore jump offset / crash type + int count = ulEndianReadLittle16(fp); + //fseek(fp, 4*3+4*3+1*8+1*8*count, SEEK_CUR); + fseek(fp, 5*8+8*count, SEEK_CUR); // completely experimental + } + break; + + case 0xB2: //light + { +/*from scdis code by Takuya Murakami: + Format: + 2 type + 4*3 offset (x,y,z, real4) + 4 intensity + 4 linear attenuation factor (real4) + 4 squared attenuation factor (real4) + 4 color (BGRA : strange byte order...) + 4*3 direction(x,y,z real4) +*/ + fseek(fp, 2+4*10, SEEK_CUR); + } + break; + + case 0xB3: //ifinf(1) + { + // long offset = ulEndianReadLittle32(fp); + // unsigned short v = ulEndianReadLittle16(fp); + // float low = ulEndianReadLittleFloat(fp); + // float high = ulEndianReadLittleFloat(fp); + ulEndianReadLittle32(fp); + ulEndianReadLittle16(fp); + ulEndianReadLittleFloat(fp); + ulEndianReadLittleFloat(fp); + + } + break; + //------------------------------------------- + // The next codes are CFS2 specific + //------------------------------------------- + + case 0xB5: //, VertexList, anaVertexList, 0 ) // VERTEX_LIST_BEGIN + { + + newPart(); + int count = ulEndianReadLittle16(fp); + ulEndianReadLittle32(fp); // dummy +#ifdef UL_WIN32 + if(TheVertexList) + ::MessageBox(0, "More than one vertexlist", "Warning:", 0); +#endif + TheVertexList = new oneVertex[count]; // kludge: TheVertexList is unused?? +// 4*8 x,y,z,nx,ny,nz,tu,tv (real4) + + for (int i = 0; i < count; i++) + { + TheVertexList[i].p[0] = ulEndianReadLittleFloat(fp); // / 1E6; + TheVertexList[i].p[1] = ulEndianReadLittleFloat(fp); // / 1E6; + TheVertexList[i].p[2] = ulEndianReadLittleFloat(fp); // / 1E6; + TheVertexList[i].n[0] = ulEndianReadLittleFloat(fp); + TheVertexList[i].n[1] = ulEndianReadLittleFloat(fp); + TheVertexList[i].n[2] = ulEndianReadLittleFloat(fp); + TheVertexList[i].tc[0]= ulEndianReadLittleFloat(fp); + TheVertexList[i].tc[1]= ulEndianReadLittleFloat(fp); + + curr_vtx_->add(TheVertexList[i].p); + curr_norm_->add(TheVertexList[i].n); + tex_coords_->add(TheVertexList[i].tc); + + } + } + break; + + case 0xB6: //, MaterialList, anaMaterialList, 0 ) // MATERIAL_LIST_BEGIN + { + + int count = ulEndianReadLittle16(fp); + ulEndianReadLittle32(fp); // dummy + fseek(fp, count*4*17, SEEK_CUR); + } + + break; + + case 0xB7: //, TextureList, anaTextureList, 0 ) // TEXTURE_LIST_BEGIN/TEXTURE_DEF/TEXTURE_LIST_END + { + + int count = ulEndianReadLittle16(fp); + ulEndianReadLittle32(fp); // dummy +#ifdef UL_WIN32 + if(TheTextureList) + ::MessageBox(0, "More than one texturelist", "Warning:", 0); +#endif + TheTextureList = new oneTexture[count]; // kludge: TheVertexList is unused?? + for(int i=0;igetNum(); + for(int i = 0; i < curr_vtx_->getNum(); i++) + { + vertex_array_->add(curr_vtx_ ->get(i)); + normal_array_->add(curr_norm_->get(i)); + } + tex_vtx_dirty_ = false; + } + + + + ssgVertexArray *vertex_array_bu = (ssgVertexArray *)vertex_array_->clone(); + + for(int i=0;igetNum();i++) + sgXformPnt3(vertex_array_->get(i), curr_matrix_); + + CreateAndAddLeaf1(GL_TRIANGLES, tex_coords_, true); + //delete vertex_array_; kludge!! + vertex_array_ = vertex_array_bu; // to undo the transformation + + //assert(curr_part_->getState()->getTexture() != NULL); + + int base = ulEndianReadLittle16(fp); + // int vertexcount = ulEndianReadLittle16(fp); + ulEndianReadLittle16(fp); + int wkcount = ulEndianReadLittle16(fp); + wkcount = wkcount / 3; // tri + assert(wkcount>0); + + DEBUGPRINT( "New part: (DrawTriList), num tris = " << wkcount << std::endl); + if(tex_coords_->getNum() != vertex_array_->getNum()) + { + printf("tex_coords_->getNum() = %d, vertex_array_->getNum() = %d\n", tex_coords_->getNum(), vertex_array_->getNum()); + assert(FALSE); + } + assert(tex_coords_->getNum() == normal_array_->getNum()); + for(int j=0;j=tex_coords_->getNum()) + { + printf("i1+base = %d, i1 = %d, base = %d, tex_coords_->getNum() = %d\n", i1+base, i1, base, tex_coords_->getNum()); + assert(FALSE); + } + assert(i2+basegetNum()); + assert(i3+basegetNum()); + + curr_index_->add(i1+base); + curr_index_->add(i2+base); + curr_index_->add(i3+base); + } + CreateAndAddLeaf2(); + } + break; + + case 0xBA: //, DrawLineList, anaDrawLineList, 0 ) + { + // int base = ulEndianReadLittle16(fp); + // int dummycount = ulEndianReadLittle16(fp); + ulEndianReadLittle16(fp); + ulEndianReadLittle16(fp); + + int wkcount = ulEndianReadLittle16(fp); + wkcount = wkcount / 2; + fseek(fp, 2*2*wkcount, SEEK_CUR); + } + break; + + case 0xBB: //, DrawPointList, anaDrawPointList, 0 ) + { + // int base = ulEndianReadLittle16(fp); + // int dummycount = ulEndianReadLittle16(fp); + ulEndianReadLittle16(fp); + ulEndianReadLittle16(fp); + + int wkcount = ulEndianReadLittle16(fp); + wkcount = wkcount / 1; + fseek(fp, 2*1*wkcount, SEEK_CUR); + } + break; + + case 0xBC: // BGL_BEGIN / BGLVersion + { + // long v = ulEndianReadLittle32(fp); + ulEndianReadLittle32(fp); + + PRINT_STRUCTURE("BGLVersion %lx\n", v) + } + break; + case 0xB8: // SetMaterial + { + ulEndianReadLittle16(fp); // word + short TheTextureIndex = ulEndianReadLittle16(fp); // word + if (TheTextureIndex != -1) + { + char *s = TheTextureList[TheTextureIndex].fname; + int j = 0; + static char tex_filename[64]; + + for(int i = 0; i < 64; i++) + { + if(!isspace(s[i])) + tex_filename[j++] = tolower(s[i]); + } + tex_filename[j] = '\0'; + //DEBUGPRINT( "Set texture: name = " << tex_filename << std::endl); + setTexture(tex_filename); + } + else + curr_tex_name_ = NULL; + } + break; + case 0xB4: // TextureSize + ulEndianReadLittle32(fp); // float + break; + case 0xBD: // BGL_END / EndVersion + break; + case 0xAE: // BGL_TRANSFORM_END + sgMakeIdentMat4( curr_matrix_ ); + + break; + case 0xAF: // BGL_TRANSFORM_MATRIX + { + sgMat4 this_mat; + this_mat[3][0] = ulEndianReadLittleFloat(fp); + this_mat[3][1] = ulEndianReadLittleFloat(fp); + this_mat[3][2] = ulEndianReadLittleFloat(fp); + this_mat[0][0] = ulEndianReadLittleFloat(fp); + this_mat[0][1] = ulEndianReadLittleFloat(fp); + this_mat[0][2] = ulEndianReadLittleFloat(fp); + this_mat[1][0] = ulEndianReadLittleFloat(fp); + this_mat[1][1] = ulEndianReadLittleFloat(fp); + this_mat[1][2] = ulEndianReadLittleFloat(fp); + this_mat[2][0] = ulEndianReadLittleFloat(fp); + this_mat[2][1] = ulEndianReadLittleFloat(fp); + this_mat[2][2] = ulEndianReadLittleFloat(fp); + DEBUGPRINT( "***** Matrix: " << std::endl << "x, y, z = " << + this_mat[3][0] << ", " << this_mat[3][1] << ", " << this_mat[3][2] << std::endl << "3 x 3 matrix:" << std::endl << + this_mat[0][0] << ", " << this_mat[0][1] << ", " << this_mat[0][2] << std::endl << + this_mat[1][0] << ", " << this_mat[1][1] << ", " << this_mat[1][2] << std::endl << + this_mat[2][0] << ", " << this_mat[2][1] << ", " << this_mat[2][2] << std::endl); + this_mat[0][3] = SG_ZERO ; + this_mat[1][3] = SG_ZERO ; + this_mat[2][3] = SG_ZERO ; + this_mat[3][3] = SG_ONE ; + sgPostMultMat4( curr_matrix_, this_mat); + + } + break; + + default: // Unknown opcode + { + if (opcode < 256) + { + if ( opcodes[opcode].size != -1) + { + DEBUGPRINT( "** " << opcodes[opcode].name << " (size " << + opcodes[opcode].size << ")" << std::endl ); + skip_offset = opcodes[opcode].size - 2; // opcode already read + } + else + { + DEBUGPRINT( "Unhandled opcode " << opcodes[opcode].name + << " (" << std::hex << opcode << std::dec << ")" << + std::endl ); + } + } + else + { + DEBUGPRINT( "Op-code out of range: " << std::hex << opcode << + std::dec << std::endl ); + } + } // default + break; + } // switch + + if (skip_offset > 0) + fseek( fp, skip_offset, SEEK_CUR ); + + } // while !feof... +} +//=========================================================================== + +#define MYMAKEFOURCC(a, b, c, d) \ + ((unsigned long)(a) | ((unsigned long)(b) << 8) | \ + ((unsigned long)(c) << 16) | ((unsigned long)(d) << 24 )) + +static unsigned long lRIFF = MYMAKEFOURCC('R', 'I', 'F', 'F'); +static unsigned long lMDL8 = MYMAKEFOURCC('M', 'D', 'L', '8'); + +void FindBGLBeginRIFF(FILE *fp) +// place file cursor on the first BGL command. +// if none found, places it on the file end +// This function is for RIFF format used in MSFS2k2 and 2k4 and CFS2 (and other MS sims?) +{ + unsigned int l; + while ((lRIFF != (l = ulEndianReadLittle32(fp))) && (!feof(fp))) + ; + if (lRIFF != l) // RIFF not found + { + assert(feof(fp)); + return; + } + ulEndianReadLittle32(fp); // ignore file length + l = ulEndianReadLittle32(fp); + if (l != MYMAKEFOURCC('M', 'D', 'L', '8')) + printf("Warning: Not a 'MDL8' RIFF file\n"); + else + printf("RIFF file, subtype 'MDL8' recognised\n"); + while(!feof(fp)) + { + char buffer[5]; + buffer[4] = 0; + fread(buffer, 4, 1, fp); + unsigned long offset = ulEndianReadLittle32(fp); + if (offset & 1L) + offset++; // if offset is odd, add one pad byte + printf("RIFF Chunk '%s' found, data length = %ld\n", buffer, offset); + if (0==strcmp(buffer, "BGL ")) + { + // Great!! + return; + } + fseek(fp, offset, SEEK_CUR); + } +} + +void FindBGLBeginOldVersion(FILE *fp) +// place file cursor on the first BGL command. +// if none found, places it on the file end +// This function is for old MDL files (for FS98, for example) +{ + unsigned short op1, op2; + op1 = ulEndianReadLittle16(fp); + + while(!feof(fp)) + { + op2 = ulEndianReadLittle16(fp); + if(op1 == 0x76 && op2 == 0x3a) + { + fseek(fp, -4, SEEK_CUR); + break; + } + op1 = op2; + } +} + + + +ssgEntity *ssgLoadMDL(const char *fname, const ssgLoaderOptions *options) +{ + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + current_options = ssgGetCurrentOptions () ; + + ailerons_grp_ = NULL; + elevator_grp_ = NULL; + rudder_grp_ = NULL; + gear_grp_ = NULL; + spoilers_grp_ = NULL; + flaps_grp_ = NULL; + prop_grp_ = NULL; + TheVertexList = NULL; + TheTextureList = NULL; + + char filename [ 1024 ] ; + current_options -> makeModelPath ( filename, fname ) ; + + FILE *fp = fopen(filename, "rb"); + if(!fp) + { + ulSetError( UL_WARNING, "ssgLoadMDL: Couldn't open MDL file '%s'!", + filename ); + return NULL; + } + + // Find beginning of BGL Code segment + unsigned long l = ulEndianReadLittle32(fp); + fseek(fp, 0, SEEK_SET); + if (l == lRIFF) // This is somewhat of a kludge, since ther "RIFF" is mostly at the beginning of the file, but not always. + FindBGLBeginRIFF(fp); + else + { FindBGLBeginOldVersion(fp); + if(feof(fp)) + { // Ok - so it is not "RIFF" at the beginning of the file and it is not an old file format - + // so search for RIFF anywhere + // I know of at least one file (the Wellesly V1.4, where the V1.4 is important) + // that had two "RIFF"s and ionyl the second one is the one we want. + // So we have to search for a place with "RIFF" + fseek(fp, 0, SEEK_SET); + l = ulEndianReadLittle32(fp); + while(!feof(fp)) + { + unsigned char c = fgetc(fp); + l = (l >> 8) | (c << 24); + if ( l == lRIFF ) + { // check whether it is a red herring... + ulEndianReadLittle32(fp); // ignore length + unsigned long ll = ulEndianReadLittle32(fp); + if (ll == lMDL8) + { // found it !! + fseek(fp, -12, SEEK_CUR); + unsigned long addr = ftell(fp); + if(addr&1L) + printf("strange... found RIFF, but on an odd adress %lx\n", addr); + else + printf("found a good RIFF header at address %lx\n", addr); + FindBGLBeginRIFF(fp); + break; // breaks the while(!feof(fp)) + } + } + } + } + } + + if(feof(fp)) + { + ulSetError( UL_WARNING, "ssgLoadMDL: No BGL Code found in file '%s'!", + filename ); + fclose(fp); + return NULL; + } + // end find begin + + + // Initialize object graph + model_ = new ssgBranch(); + char* model_name = new char[128]; + char *ptr = (char*)&fname[strlen(fname) - 1]; + while(ptr != &fname[0] && *ptr != '/') ptr--; + if(*ptr == '/') ptr++; + strcpy(model_name, ptr); + ptr = &model_name[strlen(model_name)]; + while(*ptr != '.' && ptr != &model_name[0]) ptr--; + *ptr = '\0'; + model_->setName(model_name); + + // Create group nodes for textured and non-textured objects + curr_vtx_ = new ssgVertexArray(); + curr_norm_ = new ssgNormalArray(); + + vertex_array_ = new ssgVertexArray(); + normal_array_ = new ssgNormalArray(); + + tex_coords_ = new ssgTexCoordArray(); + + start_idx_ = 0; + last_idx_ = 0; + curr_var_ = 0; + stack_depth_ = 0; + noLoDs = 1; // if there is no "branch" and no "++noLoDs" is called, we have 1 LoD. + // If there is one branch, we have 2, etc. + curr_lod = 0; + sgMakeIdentMat4(curr_matrix_); + + // Parse opcodes +#ifdef DEBUG +#ifdef _MSC_VER + wkfp=fopen("c:\\mdl_file_structure.txt", "wt"); +#else + wkfp=fopen("mdl_file_structure.txt", "wt"); +#endif +#endif + + ParseBGL(fp); // "traversing" through the file + + + fclose(fp); +#ifdef DEBUG + fclose(wkfp); +#endif +// :-((( delete curr_vtx_; + delete curr_norm_; + + DEBUGPRINT("\n" << vertex_array_->getNum() << " vertices\n"); + printf("NoLoDs = %d\n", (int)noLoDs); + printf("noGT=%d, noLT=%d, no0=%d\n", noGT, noLT, no0); + g_noLoDs = noLoDs; + + return model_; +} + +#else + +bool ssgLoadMDLTexture ( const char *fname, ssgTextureInfo* info ) +{ + ulSetError ( UL_WARNING, + "ssgLoadTexture: '%s' - MDL support not configured", fname ) ; + return false ; +} + + +#endif + diff --git a/src/ssg/ssgLoadMDL.h b/src/ssg/ssgLoadMDL.h new file mode 100644 index 0000000..b623f00 --- /dev/null +++ b/src/ssg/ssgLoadMDL.h @@ -0,0 +1,504 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadMDL.h 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + +//=========================================================================== +// +// File: fsPalettes.h +// +// Created: Fri Oct 1 15:34:29 1999 +// +// Author: Thomas Engh Sevaldrud +// +// Revision: $Id: ssgLoadMDL.h 1568 2002-09-02 06:05:49Z sjbaker $ +// +// Description: +// +//=========================================================================== +// Copyright (c) 1999 Thomas E. Sevaldrud +//=========================================================================== + +#ifndef _SSGLOADMDL_H +#define _SSGLOADMDL_H + + + +//=========================================================================== +// Aircraft color palette. The aircraft in MSFS has +// a different palette than the default fs5.pal file. +// Entries with (?) means that I am not sure of the +// values. Entries with (L), means that the color is +// emissive (bright at night). + +struct acColor +{ + unsigned char r, g, b, emissive; +}; + +static const acColor fsAcPalette[53] = { + { 0, 0, 0 , 0 }, // Black + { 89, 89, 89 , 0 }, // Dark gray + { 169, 169, 169 , 0 }, // Gray + { 211, 211, 211 , 0 }, // Light gray + { 255, 255, 255 , 0 }, // White + { 255, 0, 0 , 0 }, // Red + { 0, 255, 0 , 0 }, // Green + { 0, 0, 255 , 0 }, // Blue + { 255, 165, 0 , 0 }, // Orange + { 255, 255, 0 , 0 }, // Yellow + { 165, 42, 42 , 0 }, // Brown + { 210, 180, 140 , 0 }, // Tan + { 255, 69, 0 , 0 }, // Rust (?) + { 107, 142, 35 , 0 }, // Olive (?) + { 0, 87, 112 , 0 }, // Water + { 255, 0, 0 , 1 }, // Red (L) + { 0, 255, 0 , 1 }, // Green (L) + { 0, 0, 255 , 1 }, // Blue (L) + { 57, 57, 112 , 1 }, // Aqua (L) (?) + { 255, 165, 0 , 1 }, // Orange (L) + { 255, 255, 0 , 1 }, // Yellow (L) + { 255, 255, 255 , 1 }, // White (L) + { 255, 255, 255 , 1 }, // White (L) + { 139, 0, 0 , 0 }, // Dark red + { 0, 100, 0 , 0 }, // Dark green + { 0, 0, 139 , 0 }, // Dark blue + { 205, 120, 0 , 0 }, // Dark orange + { 139, 100, 0 , 0 }, // Dark yellow (?) + { 82, 21, 21 , 0 }, // Dark brown (?) + { 105, 90, 70 , 0 }, // Dark tan + { 128, 35, 0 , 0 }, // Dark rust (?) + { 53, 71, 17 , 0 }, // Dark olive (?) + { 205, 0, 0 , 0 }, // Medium red + { 0, 179, 0 , 0 }, // Medium green + { 0, 0, 205 , 0 }, // Medium blue + { 255, 140, 0 , 0 }, // Medium orange (?) + { 205, 179, 0 , 0 }, // Medium yellow (?) + { 120, 32, 32 , 0 }, // Medium brown (?) + { 155, 135, 105 , 0 }, // Medium tan (?) + { 186, 52, 0 , 0 }, // Medium rust (?) + { 80, 106, 25 , 0 }, // Medium olive (?) + { 238, 173, 173 , 0 }, // Light red (?) + { 144, 238, 144 , 0 }, // Light green + { 173, 216, 230 , 0 }, // Light Blue + { 255, 162, 68 , 0 }, // Light Orange (?) + { 255, 255, 224 , 0 }, // Light Yellow + { 255, 130, 58 , 0 }, // Light Brown (?) + { 255, 220, 180 , 0 }, // Light Tan (?) + { 255, 137, 0 , 0 }, // Light rust (?) + { 157, 200, 54 , 0 }, // Light olive (?) + { 89, 89, 89 , 1 }, // Dark gray (?) (L) + { 169, 169, 169 , 1 }, // Gray (L) + { 211, 211, 211 , 1 } // Light Gray (L) +}; + +//=========================================================================== +// Alternative palette for transparent colors (?) +// (same as in fs5.pal?) + +static const acColor fsAltPalette[113] = { + { 0, 0, 0}, + { 8, 8, 8}, + { 16, 16, 16}, + { 24, 24, 24}, + { 32, 32, 32}, + { 40, 40, 40}, + { 48, 48, 48}, + { 56, 56, 56}, + { 65, 65, 65}, + { 73, 73, 73}, + { 81, 81, 81}, + { 89, 89, 89}, + { 97, 97, 97}, + { 105, 105, 105}, + { 113, 113, 113}, + { 121, 121, 121}, + { 130, 130, 130}, + { 138, 138, 138}, + { 146, 146, 146}, + { 154, 154, 154}, + { 162, 162, 162}, + { 170, 170, 170}, + { 178, 178, 178}, + { 186, 186, 186}, + { 195, 195, 195}, + { 203, 203, 203}, + { 211, 211, 211}, + { 219, 219, 219}, + { 227, 227, 227}, + { 235, 235, 235}, + { 247, 247, 247}, + { 255, 255, 255}, + { 21, 5, 5}, + { 42, 10, 10}, + { 63, 15, 15}, + { 84, 20, 20}, + { 105, 25, 25}, + { 126, 30, 30}, + { 147, 35, 35}, + { 168, 40, 40}, + { 189, 45, 45}, + { 210, 50, 50}, + { 231, 55, 55}, + { 252, 60, 60}, + { 5, 21, 5}, + { 10, 42, 10}, + { 15, 63, 15}, + { 20, 84, 20}, + { 25, 105, 25}, + { 30, 126, 30}, + { 35, 147, 35}, + { 40, 168, 40}, + { 45, 189, 45}, + { 50, 210, 50}, + { 55, 231, 55}, + { 60, 252, 60}, + { 0, 7, 23}, + { 0, 15, 40}, + { 0, 23, 58}, + { 0, 40, 84}, + { 0, 64, 104}, + { 0, 71, 122}, + { 0, 87, 143}, + { 0, 99, 156}, + { 0, 112, 179}, + { 0, 128, 199}, + { 0, 143, 215}, + { 0, 153, 230}, + { 28, 14, 0}, + { 56, 28, 0}, + { 84, 42, 0}, + { 112, 56, 0}, + { 140, 70, 0}, + { 168, 84, 0}, + { 196, 98, 0}, + { 224, 112, 0}, + { 252, 126, 0}, + { 28, 28, 0}, + { 56, 56, 0}, + { 84, 84, 0}, + { 112, 112, 0}, + { 140, 140, 0}, + { 168, 168, 0}, + { 196, 196, 0}, + { 224, 224, 0}, + { 252, 252, 0}, + { 25, 21, 16}, + { 50, 42, 32}, + { 75, 63, 48}, + { 100, 84, 64}, + { 125, 105, 80}, + { 150, 126, 96}, + { 175, 147, 112}, + { 200, 168, 128}, + { 225, 189, 144}, + { 28, 11, 7}, + { 56, 22, 14}, + { 84, 33, 21}, + { 112, 44, 28}, + { 140, 55, 35}, + { 168, 66, 42}, + { 196, 77, 49}, + { 224, 88, 56}, + { 252, 99, 63}, + { 17, 22, 9}, + { 34, 44, 18}, + { 51, 66, 27}, + { 68, 88, 36}, + { 85, 110, 45}, + { 102, 132, 54}, + { 119, 154, 63}, + { 136, 176, 72}, + { 153, 198, 81} +}; + +struct _ssgBGLOpCode { + unsigned short opcode; + const char *name; + int size; /* size includes opcode (2 bytes) + -1 indicates that special treatment is needed + to find the size */ + +}; + +static const _ssgBGLOpCode opcodes[] = { + { 0x00, "BGL_EOF" , 2 }, + { 0x01, "OBSOLETE 0x01" , 2 }, + { 0x02, "BGL_NOOP" , 2 }, + { 0x03, "BGL_CASE" , -1 }, + { 0x04, "RESERVED 0x04" , 2 }, + { 0x05, "BGL_SURFACE - Area" , 2 }, + { 0x06, "BGL_SPNT" , 8 }, + { 0x07, "BGL_CPNT" , 8 }, + { 0x08, "BLG_CLOSURE" , 2 }, + { 0x09, "OBSOLETE 0x09" , 2 }, + { 0x0a, "OBSOLETE 0x0a" , 10 }, + { 0x0b, "OBSOLETE 0x0b" , 10 }, + { 0x0c, "OBSOLETE 0x0c" , 2 }, + { 0x0d, "BGL_JUMP" , 4 }, + { 0x0e, "BGL_DEFRES" , 8 }, + { 0x0f, "BGL_STRRES" , 4 }, + { 0x10, "BGL_CNTRES" , 4 }, + { 0x11, "OBSOLETE 0x11" , 10 }, + { 0x12, "OBSOLETE 0x12" , 4 }, + { 0x13, "OBSOLETE 0x13" , 4 }, + { 0x14, "BGL_SCOLOR" , 4 }, + { 0x15, "BGL_ELEVATION_MAP" , -1 }, + { 0x16, "RESERVED 0x16" , -1 }, + { 0x17, "BGL_TEXTURE_ENABLE" , 4 }, + { 0x18, "BGL_TEXTURE" , 24 }, + { 0x19, "BGL_PALETTE" , 16 }, + { 0x1a, "BGL_RESLIST" , -1 }, + { 0x1b, "BGL_IFIN_BOX_RAW_PLANE" , 22 }, + { 0x1c, "BGL_IFIN2" , 16 }, + { 0x1d, "BGL_FACE" , -1 }, + { 0x1e, "BGL_HAZE" , 4 }, + { 0x1f, "RESERVED 0x1f" , 4 }, + { 0x20, "BGL_FACET_TMAP" , -1 }, + { 0x21, "BGL_IFIN3" , 22 }, + { 0x22, "BGL_RETURN - Return" , 2 }, + { 0x23, "BGL_CALL" , 4 }, + { 0x24, "BGL_IFIN1" , 10 }, + { 0x25, "BGL_SEPARATION_PLANE" , 14 }, + { 0x26, "BGL_SETWRD" , 6 }, + { 0x27, "OBSOLETE 0x27" , -1 }, + { 0x28, "OBSOLETE 0x28" , 10 }, + { 0x29, "BGL_GRESLIST" , -1 }, + { 0x2a, "BGL_GFACET" , -1 }, + { 0x2b, "BGL_ADDOBJ32" , 6 }, + { 0x2c, "BGL_REJECT" , 12 }, + { 0x2d, "BGL_SCOLOR24" , 6 }, + { 0x2e, "BGL_LCOLOR24" , 6 }, + { 0x2f, "BGL_SCALE" , 32 }, + { 0x30, "OBSOLETE 0x30" , 4 }, + { 0x31, "BGL_RESROW" , 18 }, + { 0x32, "BGL_ADDOBJ - PerspectiveCall" , 4 }, + { 0x33, "BGL_INSTANCE - RotatedCall" , 10 }, + { 0x34, "BGL_SUPER_SCALE" , 10 }, + { 0x35, "BGL_PNTROW" , 16 }, + { 0x36, "OBSOLETE 0x36" , -1 }, + { 0x37, "BGL_POINT" , 8 }, + { 0x38, "BGL_CONCAVE" , 2 }, + { 0x39, "BGL_IFMSK" , 8 }, + { 0x3a, "BGL_VPOSITION" , 12 }, + { 0x3b, "BGL_VINSTANCE" , 6 }, + { 0x3c, "BGL_POSITION" , 28 }, + { 0x3d, "BGL_SEED" , 24 }, + { 0x3e, "BGL_FACET" , -1 }, + { 0x3f, "BGL_SHADOW_CALL" , 4 }, + { 0x40, "BGL_SHADOW_VPOSITION" , 12 }, + { 0x41, "BGL_SHADOW_VICALL" , 6 }, + { 0x42, "BGL_POLYGON_RUNWAY" , 40 }, + { 0x43, "BGL_TEXTURE2" , -1 }, + { 0x44, "BGL_TEXTURE_RUNWAY" , 64 }, // 40 + { 0x45, "OBSOLETE 0x45" , 16 }, + { 0x46, "BGL_POINT_VICALL" , 22 }, + { 0x47, "RESERVED" , 4 }, + { 0x48, "BGL_VAR_SEG" , 4 }, + { 0x49, "BGL_BUILDING" , 18 }, + { 0x4a, "OBSOLETE 0x4A" , 22 }, + { 0x4b, "OBSOLETE 0x4B" , -1 }, + { 0x4c, "BGL_VSCALE" , 16 }, + { 0x4d, "BGL_MOVEL2G" , 6 }, + { 0x4e, "BGL_MOVEG2L" , 6 }, + { 0x4f, "BGL_MOVEWORD" , 6 }, + { 0x50, "BGL_GCOLOR" , 4 }, + { 0x51, "BGL_NEW_LCOLOR" , 4 }, + { 0x52, "BGL_NEW_SCOLOR" , 4 }, + { 0x53, "OBSOLETE 0x53" , 4 }, + { 0x54, "OBSOLETE 0x54" , 6 }, + { 0x55, "BGL_SURFACE_TYPE" , 10 }, + { 0x56, "BGL_SET_WEATHER" , 4 }, + { 0x57, "BGL_SET_WEATHER" , 10 }, + { 0x58, "BLG_TEXTURE_BOUNDS" , 10 }, + { 0x59, "OBSOLETE 0x59" , 4 }, + { 0x5a, "OBSOLETE 0x5a" , 4 }, + { 0x5b, "OBSOLETE 0x5b" , 4 }, + { 0x5c, "OBSOLETE 0x5c" , 6 }, + { 0x5d, "BGL_TEXTURE_REPEAT" , 8 }, + { 0x5e, "OBSOLETE 0x5e" , 4 }, + { 0x5f, "BGL_IFSIZEV" , 8 }, + { 0x60, "BGL_FACE_TMAP" , -1 }, + { 0x61, "RESERVED 0x53" , 6 }, + { 0x62, "BGL_IFVIS" , -1 }, + { 0x63, "BGL_LIBRARY_CALL" , 20 }, + { 0x64, "BGL_LIST" , -1 }, + { 0x65, "BGL_VSCOLOR" , 4 }, + { 0x66, "BGL_VGCOLOR" , 4 }, + { 0x67, "BGL_VLCOLOR" , 4 }, + { 0x68, "OBSOLETE" , 8 }, + { 0x69, "BGL_ROAD_START" , 10 }, + { 0x6a, "BGL_ROAD_CONT" , 8 }, + { 0x6b, "BGL_RIVER_START" , 10 }, + { 0x6c, "BGL_RIVER_CONT" , 8 }, + { 0x6d, "BGL_IFSIZEH" , 8 }, + { 0x6e, "BGL_TAXIWAY_START" , 10 }, + { 0x6f, "BGL_TAXIWAY_CONT" , 8 }, + { 0x70, "BGL_AREA_SENSE" , -1 }, + { 0x71, "BGL_ALTITUDE_SET" , 4 }, + { 0x72, "OBSOLETE 0x72" , 20 }, + { 0x73, "BGL_IFINBOXP" , 16 }, + { 0x74, "BGL_ADDCAT" , 6 }, + { 0x75, "BGL_ADDMNT" , 4 }, + { 0x76, "BGL_BGL - Perspective" , 2 }, + { 0x77, "BGL_SCALE_AGL - RefPoint" , 32 }, + { 0x78, "BGL_ROAD_CONTW" , 10 }, + { 0x79, "BGL_RIVER_CONTW" , 10 }, + { 0x7a, "BGL_GFACET_TMAP" , -1 }, + { 0x7b, "OBSOLETE 0x7b" , -1 }, + { 0x7c, "BGL_SELECT" , 10 }, + { 0x7d, "BGL_PERSPECTIVE" , 2 }, + { 0x7e, "BGL_SETWRD_GLOBAL" , 6 }, + { 0x7f, "OBSOLETE 0x7f" , 2 }, + { 0x80, "BGL_RESPNT" , 4 }, + { 0x81, "OBSOLETE 0x81" , 4 }, + { 0x82, "OBSOLETE 0x82" , 28 }, + { 0x83, "BGL_RESCALE" , 32 }, + { 0x84, "OBSOLETE 0x84" , 8 }, + { 0x85, "OBSOLETE 0x85" , 2 }, + { 0x86, "OBSOLETE 0x86" , 3 }, + { 0x87, "BGL_FIXED_COLORS" , 4 }, + { 0x88, "BGL_JUMP32" , 6 }, + { 0x89, "BGL_VAR_BASE32" , 6 }, + { 0x8a, "BGL_CALL32" , 6 }, + { 0x8b, "BGL_ADDCAT32" , 8 }, + { 0x8c, "RESERVED 0x8c" , 6 }, + { 0x8d, "RESERVED 0x8d" , 6 }, + { 0x8e, "BGL_VFILE_MARKER" , 4 }, + { 0x8f, "BGL_ALPHA" , 6 }, + { 0x90, "RESERVED 0x90" , -1 }, + { 0x91, "BGL_TEXT" , 12 }, + { 0x92, "OBSOLETE 0x92" , 4 }, + { 0x93, "RESERVED 0x93" , 4 }, + { 0x94, "BGL_CRASH" , 12 }, + { 0x95, "BGL_CRASH_INDIRECT" , 10 }, + { 0x96, "BGL_CRASH_START" , 6 }, + { 0x97, "BGL_CRASH_SPHERE" , 6 }, + { 0x98, "BGL_CRASH_BOX" , 22 }, + { 0x99, "BGL_SET_CRASH" , 4 }, + { 0x9a, "OBSOLETE 0x9a" , -1 }, + { 0x9b, "RESERVED 0x9b" , 8 }, + { 0x9c, "RESERVED 0x9c" , 6 }, + { 0x9d, "RESERVED 0x9d" , 14 }, + { 0x9e, "BGL_INTERPOLATE" , 20 }, + { 0x9f, "BGL_OVERRIDE" , 6 }, + { 0xa0, "BGL_OBJECT" , -1 }, + { 0xa1, "OBSOLETE 0xA1" , 10 }, + { 0xa2, "OBSOLETE 0xA2" , 8 }, + { 0xa3, "OBSOLETE 0xA3" , -1 }, + { 0xa4, "BGL_VALPHA" , 4 }, + { 0xa5, "OBSOLETE 0xA5" , 4 }, + { 0xa6, "OBSOLETE 0xA6" , 8 }, + { 0xa7, "BGL_SPRITE_VCALL" , 22 }, + { 0xa8, "BGL_TEXTURE_ROAD_START" , 12}, + { 0xa9, "BGL_IFIN_INSTANCE_BOX_PLANE" , 22}, + { 0xaa, "BGL_NEW_RUNWAY" , -1 }, + { 0xab, "RESERVED 0xAB" , 38 }, + { 0xac, "BGL_ZBIAS" , 4 }, + { 0xad, "BGL_ANIMATE" , 30 }, + { 0xae, "BGL_TRANSFORM_END" , 2 }, + { 0xaf, "BGL_TRANSFORM_MATRIX" , 50 }, + { 0xb0, "UNKNOWN 0xB0" , -1 }, + { 0xb1, "UNKNOWN 0xB1" , -1 }, + { 0xb2, "BGL_LIGHT" , 44 }, + { 0xb3, "BGL_IFINF1" , 14 }, + { 0xb4, "UNKNOWN 0xB4" , -1 }, + { 0xb5, "UNKNOWN 0xB5" , -1 }, + { 0xb6, "UNKNOWN 0xB6" , -1 }, + { 0xb7, "UNKNOWN 0xB7" , -1 }, + { 0xb8, "UNKNOWN 0xB8" , -1 }, + { 0xb9, "UNKNOWN 0xB9" , -1 }, + { 0xba, "UNKNOWN 0xBA" , -1 }, + { 0xbb, "UNKNOWN 0xBB" , -1 }, + { 0xbc, "UNKNOWN 0xBC" , -1 }, + { 0xbd, "UNKNOWN 0xBD" , -1 }, + { 0xbe, "UNKNOWN 0xBE" , -1 }, + { 0xbf, "UNKNOWN 0xBF" , -1 }, + { 0xc0, "UNKNOWN 0xC0" , -1 }, + { 0xc1, "UNKNOWN 0xC1" , -1 }, + { 0xc2, "UNKNOWN 0xC2" , -1 }, + { 0xc3, "UNKNOWN 0xC3" , -1 }, + { 0xc4, "UNKNOWN 0xC4" , -1 }, + { 0xc5, "UNKNOWN 0xC5" , -1 }, + { 0xc6, "UNKNOWN 0xC6" , -1 }, + { 0xc7, "UNKNOWN 0xC7" , -1 }, + { 0xc8, "UNKNOWN 0xC8" , -1 }, + { 0xc9, "UNKNOWN 0xC9" , -1 }, + { 0xca, "UNKNOWN 0xCA" , -1 }, + { 0xcb, "UNKNOWN 0xCB" , -1 }, + { 0xcc, "UNKNOWN 0xCC" , -1 }, + { 0xcd, "UNKNOWN 0xCD" , -1 }, + { 0xce, "UNKNOWN 0xCE" , -1 }, + { 0xcf, "UNKNOWN 0xCF" , -1 }, + { 0xd0, "UNKNOWN 0xD0" , -1 }, + { 0xd1, "UNKNOWN 0xD1" , -1 }, + { 0xd2, "UNKNOWN 0xD2" , -1 }, + { 0xd3, "UNKNOWN 0xD3" , -1 }, + { 0xd4, "UNKNOWN 0xD4" , -1 }, + { 0xd5, "UNKNOWN 0xD5" , -1 }, + { 0xd6, "UNKNOWN 0xD6" , -1 }, + { 0xd7, "UNKNOWN 0xD7" , -1 }, + { 0xd8, "UNKNOWN 0xD8" , -1 }, + { 0xd9, "UNKNOWN 0xD9" , -1 }, + { 0xda, "UNKNOWN 0xDA" , -1 }, + { 0xdb, "UNKNOWN 0xDB" , -1 }, + { 0xdc, "UNKNOWN 0xDC" , -1 }, + { 0xdd, "UNKNOWN 0xDD" , -1 }, + { 0xde, "UNKNOWN 0xDE" , -1 }, + { 0xdf, "UNKNOWN 0xDF" , -1 }, + { 0xe0, "UNKNOWN 0xE0" , -1 }, + { 0xe1, "UNKNOWN 0xE1" , -1 }, + { 0xe2, "UNKNOWN 0xE2" , -1 }, + { 0xe3, "UNKNOWN 0xE3" , -1 }, + { 0xe4, "UNKNOWN 0xE4" , -1 }, + { 0xe5, "UNKNOWN 0xE5" , -1 }, + { 0xe6, "UNKNOWN 0xE6" , -1 }, + { 0xe7, "UNKNOWN 0xE7" , -1 }, + { 0xe8, "UNKNOWN 0xE8" , -1 }, + { 0xe9, "UNKNOWN 0xE9" , -1 }, + { 0xea, "UNKNOWN 0xEA" , -1 }, + { 0xeb, "UNKNOWN 0xEB" , -1 }, + { 0xec, "UNKNOWN 0xEC" , -1 }, + { 0xed, "UNKNOWN 0xED" , -1 }, + { 0xee, "UNKNOWN 0xEE" , -1 }, + { 0xef, "UNKNOWN 0xEF" , -1 }, + { 0xf0, "UNKNOWN 0xF0" , -1 }, + { 0xf1, "UNKNOWN 0xF1" , -1 }, + { 0xf2, "UNKNOWN 0xF2" , -1 }, + { 0xf3, "UNKNOWN 0xF3" , -1 }, + { 0xf4, "UNKNOWN 0xF4" , -1 }, + { 0xf5, "UNKNOWN 0xF5" , -1 }, + { 0xf6, "UNKNOWN 0xF6" , -1 }, + { 0xf7, "UNKNOWN 0xF7" , -1 }, + { 0xf8, "UNKNOWN 0xF8" , -1 }, + { 0xf9, "UNKNOWN 0xF9" , -1 }, + { 0xfa, "UNKNOWN 0xFA" , -1 }, + { 0xfb, "UNKNOWN 0xFB" , -1 }, + { 0xfc, "UNKNOWN 0xFC" , -1 }, + { 0xfd, "UNKNOWN 0xFD" , -1 }, + { 0xfe, "UNKNOWN 0xFE" , -1 }, + { 0xff, "UNKNOWN 0xFF" , -1 } +}; + +//=========================================================================== + +#endif // _SSGLOADMDL_H + diff --git a/src/ssg/ssgLoadMDL_BGLTexture.cxx b/src/ssg/ssgLoadMDL_BGLTexture.cxx new file mode 100644 index 0000000..eddd6f5 --- /dev/null +++ b/src/ssg/ssgLoadMDL_BGLTexture.cxx @@ -0,0 +1,384 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadMDL_BGLTexture.cxx 2117 2007-09-13 23:21:09Z fayjf $ +*/ + +//=========================================================================== +// +// File: ssgLoadMDL_BGLTexture.cxx +// +// Created: Jun 1 22:20:31 2002 +// +// Author: Thomas Engh Sevaldrud +// Juergen Marquardt +// +// Revision: $Id: ssgLoadMDL_BGLTexture.cxx 2117 2007-09-13 23:21:09Z fayjf $ +// +// Description: +// +// Changes: by Juergen Marquardt +// - separated from ssgLoadMDL +// it's now used by ssgLoadMDL and ssgLoadBGL +// - added support for translucatant textures +// - rindex replaced by strrchr +// +//=========================================================================== + +#include "ssgLocal.h" +#include "ssgMSFSPalette.h" + +//=========================================================================== +// Texture palette values (from fs5.pal) +// Alpha channel added for more efficient +// rendering on 3dfx hardware. + +unsigned const char ssgFsTexPalette[1024] = { + 0x00, 0x00, 0x00, 0xff, + 0x08, 0x08, 0x08, 0xff, + 0x10, 0x10, 0x10, 0xff, + 0x18, 0x18, 0x18, 0xff, + 0x20, 0x20, 0x20, 0xff, + 0x28, 0x28, 0x28, 0xff, + 0x30, 0x30, 0x30, 0xff, + 0x38, 0x38, 0x38, 0xff, + 0x41, 0x41, 0x41, 0xff, + 0x49, 0x49, 0x49, 0xff, + 0x51, 0x51, 0x51, 0xff, + 0x59, 0x59, 0x59, 0xff, + 0x61, 0x61, 0x61, 0xff, + 0x69, 0x69, 0x69, 0xff, + 0x71, 0x71, 0x71, 0xff, + 0x79, 0x79, 0x79, 0xff, + 0x82, 0x82, 0x82, 0xff, + 0x8a, 0x8a, 0x8a, 0xff, + 0x92, 0x92, 0x92, 0xff, + 0x9a, 0x9a, 0x9a, 0xff, + 0xa2, 0xa2, 0xa2, 0xff, + 0xaa, 0xaa, 0xaa, 0xff, + 0xb2, 0xb2, 0xb2, 0xff, + 0xba, 0xba, 0xba, 0xff, + 0xc3, 0xc3, 0xc3, 0xff, + 0xcb, 0xcb, 0xcb, 0xff, + 0xd3, 0xd3, 0xd3, 0xff, + 0xdb, 0xdb, 0xdb, 0xff, + 0xe3, 0xe3, 0xe3, 0xff, + 0xeb, 0xeb, 0xeb, 0xff, + 0xf7, 0xf7, 0xf7, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x15, 0x05, 0x05, 0xff, + 0x2a, 0x0a, 0x0a, 0xff, + 0x3f, 0x0f, 0x0f, 0xff, + 0x54, 0x14, 0x14, 0xff, + 0x69, 0x19, 0x19, 0xff, + 0x7e, 0x1e, 0x1e, 0xff, + 0x93, 0x23, 0x23, 0xff, + 0xa8, 0x28, 0x28, 0xff, + 0xbd, 0x2d, 0x2d, 0xff, + 0xd2, 0x32, 0x32, 0xff, + 0xe7, 0x37, 0x37, 0xff, + 0xfc, 0x3c, 0x3c, 0xff, + 0x05, 0x15, 0x05, 0xff, + 0x0a, 0x2a, 0x0a, 0xff, + 0x0f, 0x3f, 0x0f, 0xff, + 0x14, 0x54, 0x14, 0xff, + 0x19, 0x69, 0x19, 0xff, + 0x1e, 0x7e, 0x1e, 0xff, + 0x23, 0x93, 0x23, 0xff, + 0x28, 0xa8, 0x28, 0xff, + 0x2d, 0xbd, 0x2d, 0xff, + 0x32, 0xd2, 0x32, 0xff, + 0x37, 0xe7, 0x37, 0xff, + 0x3c, 0xfc, 0x3c, 0xff, + 0x00, 0x07, 0x17, 0xff, + 0x00, 0x0f, 0x28, 0xff, + 0x00, 0x17, 0x3a, 0xff, + 0x00, 0x28, 0x54, 0xff, + 0x00, 0x40, 0x68, 0xff, + 0x00, 0x47, 0x7a, 0xff, + 0x00, 0x57, 0x8f, 0xff, + 0x00, 0x63, 0x9c, 0xff, + 0x00, 0x70, 0xb3, 0xff, + 0x00, 0x80, 0xc7, 0xff, + 0x00, 0x8f, 0xd7, 0xff, + 0x00, 0x99, 0xe6, 0xff, + 0x1c, 0x0e, 0x00, 0xff, + 0x38, 0x1c, 0x00, 0xff, + 0x54, 0x2a, 0x00, 0xff, + 0x70, 0x38, 0x00, 0xff, + 0x8c, 0x46, 0x00, 0xff, + 0xa8, 0x54, 0x00, 0xff, + 0xc4, 0x62, 0x00, 0xff, + 0xe0, 0x70, 0x00, 0xff, + 0xfc, 0x7e, 0x00, 0xff, + 0x1c, 0x1c, 0x00, 0xff, + 0x38, 0x38, 0x00, 0xff, + 0x54, 0x54, 0x00, 0xff, + 0x70, 0x70, 0x00, 0xff, + 0x8c, 0x8c, 0x00, 0xff, + 0xa8, 0xa8, 0x00, 0xff, + 0xc4, 0xc4, 0x00, 0xff, + 0xe0, 0xe0, 0x00, 0xff, + 0xfc, 0xfc, 0x00, 0xff, + 0x19, 0x15, 0x10, 0xff, + 0x32, 0x2a, 0x20, 0xff, + 0x4b, 0x3f, 0x30, 0xff, + 0x64, 0x54, 0x40, 0xff, + 0x7d, 0x69, 0x50, 0xff, + 0x96, 0x7e, 0x60, 0xff, + 0xaf, 0x93, 0x70, 0xff, + 0xc8, 0xa8, 0x80, 0xff, + 0xe1, 0xbd, 0x90, 0xff, + 0x1c, 0x0b, 0x07, 0xff, + 0x38, 0x16, 0x0e, 0xff, + 0x54, 0x21, 0x15, 0xff, + 0x70, 0x2c, 0x1c, 0xff, + 0x8c, 0x37, 0x23, 0xff, + 0xa8, 0x42, 0x2a, 0xff, + 0xc4, 0x4d, 0x31, 0xff, + 0xe0, 0x58, 0x38, 0xff, + 0xfc, 0x63, 0x3f, 0xff, + 0x11, 0x16, 0x09, 0xff, + 0x22, 0x2c, 0x12, 0xff, + 0x33, 0x42, 0x1b, 0xff, + 0x44, 0x58, 0x24, 0xff, + 0x55, 0x6e, 0x2d, 0xff, + 0x66, 0x84, 0x36, 0xff, + 0x77, 0x9a, 0x3f, 0xff, + 0x88, 0xb0, 0x48, 0xff, + 0x99, 0xc6, 0x51, 0xff, + 0x00, 0x3a, 0x68, 0xff, + 0x00, 0x57, 0x70, 0xff, + 0x2b, 0x70, 0x80, 0xff, + 0xff, 0x00, 0x00, 0xff, + 0x40, 0xff, 0x40, 0xff, + 0x00, 0x00, 0xc0, 0xff, + 0x00, 0x69, 0x69, 0xff, + 0xff, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x51, 0x51, 0x51, 0xff, + 0x79, 0x79, 0x79, 0xff, + 0x92, 0x92, 0x92, 0xff, + 0xaa, 0xaa, 0xaa, 0xff, + 0xc3, 0xc3, 0xc3, 0xff, + 0xe3, 0xe3, 0xe3, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xff, 0xff, + 0xc8, 0xc8, 0xff, 0xff, + 0xd0, 0xd0, 0xff, 0xff, + 0xd8, 0xd8, 0xff, 0xff, + 0xe0, 0xe0, 0xff, 0xff, + 0xe8, 0xe8, 0xff, 0xff, + 0xf0, 0xf0, 0xff, 0xff, + 0xf8, 0xf8, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x10, 0x48, 0x10, 0xff, + 0x20, 0x50, 0x20, 0xff, + 0x30, 0x58, 0x30, 0xff, + 0x40, 0x60, 0x40, 0xff, + 0x50, 0x68, 0x50, 0xff, + 0x60, 0x70, 0x60, 0xff, + 0x70, 0x78, 0x70, 0xff, + 0x78, 0x7c, 0x78, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x21, 0x8c, 0xbd, 0xff, + 0x39, 0x84, 0xa5, 0xff, + 0xbd, 0x42, 0x42, 0xff, + 0x9c, 0x42, 0x42, 0xff, + 0x84, 0x4a, 0x4a, 0xff, + 0x21, 0x52, 0x6b, 0xff, + 0xd6, 0x5a, 0x52, 0xff, + 0xbd, 0x5a, 0x52, 0xff, + 0xa5, 0x5a, 0x52, 0xff, + 0x7b, 0x39, 0x31, 0xff, + 0x63, 0x39, 0x31, 0xff, + 0x6b, 0x4a, 0x42, 0xff, + 0x7b, 0x5a, 0x52, 0xff, + 0xb5, 0x5a, 0x42, 0xff, + 0x4a, 0x31, 0x29, 0xff, + 0xbd, 0x73, 0x5a, 0xff, + 0x8c, 0x5a, 0x31, 0xff, + 0x21, 0x31, 0x4a, 0xff, + 0xb5, 0x73, 0x31, 0xff, + 0x63, 0x42, 0x21, 0xff, + 0xa5, 0x73, 0x42, 0xff, + 0x31, 0x29, 0x21, 0xff, + 0xa5, 0x8c, 0x73, 0xff, + 0xbd, 0xa5, 0x8c, 0xff, + 0x39, 0x63, 0x7b, 0xff, + 0xb5, 0x6b, 0x18, 0xff, + 0xce, 0x7b, 0x21, 0xff, + 0x9c, 0x63, 0x21, 0xff, + 0x94, 0x6b, 0x31, 0xff, + 0x6b, 0x52, 0x31, 0xff, + 0x21, 0x21, 0x39, 0xff, + 0x21, 0x73, 0xa5, 0xff, + 0xd6, 0xd6, 0x21, 0xff, + 0xad, 0xad, 0x21, 0xff, + 0xc6, 0xc6, 0x29, 0xff, + 0x8c, 0x8c, 0x21, 0xff, + 0x73, 0x73, 0x21, 0xff, + 0xbd, 0xbd, 0x39, 0xff, + 0x9c, 0x9c, 0x31, 0xff, + 0xad, 0xad, 0x39, 0xff, + 0x7b, 0x7b, 0x31, 0xff, + 0x7b, 0x7b, 0x42, 0xff, + 0x4a, 0x4a, 0x31, 0xff, + 0x7b, 0x7b, 0x5a, 0xff, + 0x29, 0x29, 0x21, 0xff, + 0x5a, 0x63, 0x39, 0xff, + 0x6b, 0x73, 0x4a, 0xff, + 0x7b, 0x94, 0x52, 0xff, + 0x8c, 0xad, 0x63, 0xff, + 0x84, 0x9c, 0x63, 0xff, + 0x31, 0x42, 0x29, 0xff, + 0x63, 0xa5, 0x5a, 0xff, + 0x4a, 0xd6, 0x4a, 0xff, + 0x39, 0x8c, 0x39, 0xff, + 0x4a, 0xb5, 0x4a, 0xff, + 0x5a, 0xc6, 0x5a, 0xff, + 0x39, 0x7b, 0x39, 0xff, + 0x31, 0x63, 0x31, 0xff, + 0x5a, 0xa5, 0x5a, 0xff, + 0x52, 0x94, 0x52, 0xff, + 0x4a, 0x63, 0x4a, 0xff, + 0x39, 0x73, 0x84, 0xff, + 0x21, 0x63, 0x7b, 0xff, + 0x4a, 0x73, 0x84, 0xff +}; + +#ifdef SSG_LOAD_MDL_BGL_TEXTURE_SUPPORTED +// This really simple (raw paletted) format is used by older MSFS for textures +bool ssgLoadMDLTexture ( const char *fname, ssgTextureInfo* info ) +{ + FILE *tfile; + int index = 0; + if ( (tfile = fopen(fname, "rb")) == NULL) { + char *dupfname = strdup( fname); + char *p = strrchr( dupfname,'_'); + if (p != 0) { + *p = '\0'; + p++; + index = atoi (p); + if ( (tfile = fopen(dupfname, "rb")) == NULL) { + ulSetError( UL_WARNING, "ssgLoadTexture: Failed to load '%s'.", dupfname ); + free( dupfname); + return false ; + } + free( dupfname); + } + else { + ulSetError( UL_WARNING, "ssgLoadTexture: Failed to load '%s'.", fname ); + free( dupfname); + return false ; + } + } + + fseek(tfile, 0, SEEK_END); + unsigned long file_length = ftell(tfile); + + if (file_length != 65536) { + // this is not a MSFS-formatted texture, so it's probably a BMP + fclose(tfile); + return ssgLoadBMP( fname, info ); + } else { + fseek(tfile, 0, SEEK_SET); + + unsigned char *texels = new unsigned char[256 * 256 * 4]; + int c = 0; + for (int y = 0; y < 256; y++) { + for (int x = 0; x < 256; x++) { + unsigned char b; + fread(&b, 1, 1, tfile); + texels[c++] = ssgFsTexPalette[b*4 ]; + texels[c++] = ssgFsTexPalette[b*4 + 1]; + texels[c++] = ssgFsTexPalette[b*4 + 2]; + texels[c++] = (b width = 256 ; + info -> height = 256 ; + info -> depth = 4 ; + info -> alpha = TRUE ; //?? + } + + return ssgMakeMipMaps ( texels, 256, 256, 4 ) ; + } +} +#else + +bool ssgLoadMDLTexture ( const char *fname, ssgTextureInfo* info ) +{ + ulSetError ( UL_WARNING, + "ssgLoadTexture: '%s' - MDL/BGL Texture support not configured", fname ) ; + return false ; +} + +#endif diff --git a/src/ssg/ssgLoadOBJ.cxx b/src/ssg/ssgLoadOBJ.cxx new file mode 100644 index 0000000..10848a9 --- /dev/null +++ b/src/ssg/ssgLoadOBJ.cxx @@ -0,0 +1,761 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadOBJ.cxx 2020 2005-03-25 01:04:04Z wolfram_kuss $ +*/ + +// +// Wavefront OBJ import for SSG/PLIB +// Ported from IVCON by Dave McClurg (dpm@efn.org) in March-2000 +// Updated by Dave McClurg in April-2000 (added textures) +// +/* + Purpose: + + OBJ_READ reads a Wavefront OBJ file. + + Example: + + # magnolia.obj + + mtllib ./vp.mtl + + g + v -3.269770 -39.572201 0.876128 + v -3.263720 -39.507999 2.160890 + ... + v 0.000000 -9.988540 0.000000 + g stem + s 1 + usemtl brownskn + f 8 9 11 10 + f 12 13 15 14 + ... + f 788 806 774 + + Modified: + + 20 October 1998 + + Author: + + John Burkardt +*/ + +#include "ssgLocal.h" + +#define MAX_LINE_LEN 1024 +#define MAX_LINE 100000 +#define MAX_FACE 100000 +#define MAX_VERT 100000 +#define MAX_MATERIALS 1000 + + +struct faceData +{ + int vlist [3] ; + int tlist [3] ; + int nlist [3] ; + int mat_index ; +} ; + + +struct matData +{ + char* name ; + sgVec4 amb ; + sgVec4 diff ; + sgVec4 spec ; + float shine ; + float trans ; + char* tfname ; +} ; + + +static int num_line ; +static int* line_dex ; + +static int num_face ; +static faceData* face ; + +static int num_vert ; +static int num_vert_tex ; +static int num_vert_normal ; +static sgVec3* vert ; +static sgVec3* vert_tex ; +static sgVec3* vert_normal ; + +static int num_mat ; +static matData* materials ; + +static ssgBranch *current_branch = NULL ; + +static ssgState* get_state( matData* mat ) +{ + if (mat->tfname != NULL) + { + ssgState *st = ssgGetCurrentOptions () -> createState ( mat->tfname ) ; + if ( st != NULL ) + return st ; + } + + ssgSimpleState *st = new ssgSimpleState () ; + + st -> setMaterial ( GL_AMBIENT, mat -> amb ) ; + st -> setMaterial ( GL_DIFFUSE, mat -> diff ) ; + st -> setMaterial ( GL_SPECULAR, mat -> spec ) ; + st -> setShininess ( mat -> shine ) ; + + st -> enable ( GL_COLOR_MATERIAL ) ; + st -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + + st -> enable ( GL_LIGHTING ) ; + st -> setShadeModel ( GL_SMOOTH ) ; + + if ( mat -> trans < 0.99f ) + { + st -> disable ( GL_ALPHA_TEST ) ; + st -> enable ( GL_BLEND ) ; + st -> setTranslucent () ; + } + else + { + st -> disable ( GL_BLEND ) ; + st -> setOpaque () ; + } + + if (mat->tfname != NULL) + { + st -> setTexture( ssgGetCurrentOptions () -> createTexture(mat->tfname) ) ; + st -> enable( GL_TEXTURE_2D ) ; + } + else + { + st -> disable( GL_TEXTURE_2D ) ; + } + + return st ; +} + +static int leqi ( const char* string1, const char* string2 ) +//LEQI compares two strings for equality, disregarding case. +{ + int i; + int nchar; + int nchar1; + int nchar2; + + nchar1 = strlen ( string1 ); + nchar2 = strlen ( string2 ); + + if ( nchar1 < nchar2 ) { + nchar = nchar1; + } + else { + nchar = nchar2; + } +/* + The strings are not equal if they differ over their common length. +*/ + for ( i = 0; i < nchar; i++ ) { + + if ( toupper ( string1[i] ) != toupper ( string2[i] ) ) { + return FALSE; + } + } +/* + The strings are not equal if the longer one includes nonblanks + in the tail. +*/ + if ( nchar1 > nchar ) { + for ( i = nchar; i < nchar1; i++ ) { + if ( string1[i] != ' ' ) { + return FALSE; + } + } + } + else if ( nchar2 > nchar ) { + for ( i = nchar; i < nchar2; i++ ) { + if ( string2[i] != ' ' ) { + return FALSE; + } + } + } + return TRUE; +} + +static char filename [ 1024 ] ; + + +static void load_materials ( const char* fname ) +{ + num_mat = 0 ; + + char path [ 1024 ] ; + ssgGetCurrentOptions () -> makeModelPath ( path, fname ) ; + + FILE* filein = fopen (path,"r") ; + if ( filein == 0 ) + { + char mtl_filename[ 1024 ]; + strcpy(mtl_filename, filename); + if(NULL!=strrchr(mtl_filename, '/')) + *strrchr(mtl_filename, '/') = 0; + if(NULL!=strrchr(mtl_filename, '\\')) + *strrchr(mtl_filename, '\\') = 0; + strncat(mtl_filename, "\\", 1024); + strncat(mtl_filename, fname, 1024); + + filein = fopen (mtl_filename,"r") ; + if ( filein == 0 ) + return ; // give up finding the material file + } + + int index = -1 ; + + char input[MAX_LINE_LEN]; + while ( fgets ( input, MAX_LINE_LEN, filein ) != NULL ) + { + char *next; + for ( next = input; *next != '\0' && isspace(*next); next++ ) + ; + if ( *next == '\0' ) + continue; + if ( *next == '#' || *next == '$' ) + continue; + + char token[MAX_LINE_LEN]; + int width; + int count; + float r1,r2,r3; + + sscanf ( next, "%s%n", token, &width ) ; + next = next + width ; + + if ( leqi ( token, "NEWMTL" ) == TRUE ) { + + char name[MAX_LINE_LEN]; + count = sscanf ( next, "%s%n", name, &width ) ; + + if ( count == 1 ) { + index ++ ; + memset( &materials[ index ], 0, sizeof(matData) ) ; + materials[ index ].name = ulStrDup ( name ) ; + materials[ index ].amb[3] = 1.0f ; + materials[ index ].diff[3] = 1.0f ; + materials[ index ].spec[3] = 1.0f ; + materials[ index ].shine = 0.0f ; + materials[ index ].trans = 1.0f ; + } + } + else if ( leqi ( token, "Ka" ) == TRUE ) { + + count = sscanf ( next, "%e %e %e", &r1, &r2, &r3 ) ; + + if ( count == 3 && index >= 0 ) { + materials[ index ].amb[0] = r1 ; + materials[ index ].amb[1] = r2 ; + materials[ index ].amb[2] = r3 ; + } + } + else if ( leqi ( token, "Kd" ) == TRUE ) { + + count = sscanf ( next, "%e %e %e", &r1, &r2, &r3 ) ; + + if ( count == 3 && index >= 0 ) { + materials[ index ].diff[0] = r1 ; + materials[ index ].diff[1] = r2 ; + materials[ index ].diff[2] = r3 ; + } + } + else if ( leqi ( token, "Ks" ) == TRUE ) { + + count = sscanf ( next, "%e %e %e", &r1, &r2, &r3 ) ; + + if ( count == 3 && index >= 0 ) { + materials[ index ].spec[0] = r1 ; + materials[ index ].spec[1] = r2 ; + materials[ index ].spec[2] = r3 ; + } + } + else if ( leqi ( token, "map_Kd" ) == TRUE ) { + + char tfname[MAX_LINE_LEN]; + count = sscanf ( next, "%s%n", tfname, &width ) ; + + if ( count == 1 && index >= 0 ) + materials[ index ].tfname = ulStrDup ( tfname ) ; + } + } + + fclose (filein) ; + + num_mat = (index+1) ; +} + + +static void add_mesh ( int mat_index ) +{ + int i ; + + //count faces with same material + int num = 0 ; + for ( i=0; i add ( vert[ face[i].vlist[j] ] ) ; + if ( num_vert_tex ) + tlist -> add ( vert_tex[ face[i].tlist[j] ] ) ; + if ( num_vert_normal ) + nlist -> add ( vert_normal[ face[i].nlist[j] ] ) ; + } + } + } + + ssgState *st = NULL ; + if ( mat_index < num_mat ) { + matData* mat = &materials[ mat_index ]; + if ( mat->tfname != 0 ) + st = ssgGetCurrentOptions() -> createState ( mat->tfname ) ; + if ( st == NULL ) + st = get_state ( mat ) ; + } + + ssgVtxTable *vtab = new ssgVtxTable ( GL_TRIANGLES, + vlist, nlist, tlist, 0 ) ; + + vtab -> setCullFace ( TRUE ); + if ( st ) + vtab -> setState ( st ) ; + + current_branch -> addKid ( vtab ) ; +} + +static int obj_read ( FILE *filein ) +{ + int count; + char *next; + char *next2; + char *next3; + int node; + float r1; + float r2; + float r3; + char input[MAX_LINE_LEN]; + char token[MAX_LINE_LEN]; + char token2[MAX_LINE_LEN]; + int width; + int mat_current = 0 ; +/* + Initialize. +*/ + num_line = 0 ; + line_dex = new int[ MAX_LINE ] ; + + num_face = 0 ; + face = new faceData[ MAX_FACE ] ; + + num_vert = 0 ; + num_vert_tex = 0 ; + num_vert_normal = 0 ; + vert = new sgVec3[ MAX_VERT ] ; + vert_tex = new sgVec3[ MAX_VERT ] ; + vert_normal = new sgVec3[ MAX_VERT ] ; + + num_mat = 0 ; + materials = new matData [ MAX_MATERIALS ] ; + +/* + Read the next line of the file into INPUT. +*/ + while ( fgets ( input, MAX_LINE_LEN, filein ) != NULL ) { + + for ( next = input; *next != '\0' && isspace(*next); next++ ) + ; + if ( *next == '\0' ) + continue; + if ( *next == '#' || *next == '$' ) + continue; + + sscanf ( next, "%s%n", token, &width ); + next = next + width; + +/* + F V1 V2 V3 + or + F V1/VT1/VN1 V2/VT2/VN2 ... + or + F V1//VN1 V2//VN2 ... + + Face. + A face is defined by the vertices. + Optionally, slashes may be used to include the texture vertex + and vertex normal indices. + + OBJ line node indices are 1 based rather than 0 based. + So we have to decrement them before loading them into FACE. +*/ + + if ( leqi ( token, "F" ) == TRUE ) { + + int vlist [4] ; + int tlist [4] ; + int nlist [4] ; + int ivert = 0 ; +/* + Read each item in the F definition as a token, and then + take it apart. +*/ + for ( ;; ) { + + count = sscanf ( next, "%s%n", token2, &width ); + next = next + width; + + if ( count != 1 ) { + break; + } + + count = sscanf ( token2, "%d%n", &node, &width ); + next2 = token2 + width; + + if ( count != 1 ) { + break; + } + + if ( ivert >= 4 ) { + break; + } + + vlist[ivert] = 0 ; + tlist[ivert] = 0 ; + nlist[ivert] = 0 ; + + if ( 0 < node && node <= num_vert ) { + vlist[ivert] = node-1; + } +/* + If there's a slash, extract the index of the texture vector. + If there's another slash, extract the index of the normal vector. +*/ + if ( *next2 == '/' ) { + + next3 = next2 + 1; + count = sscanf ( next3, "%d%n", &node, &width ); + + if ( 0 < node && node <= num_vert_tex ) { + tlist[ivert] = node-1; + } + + for ( ; next3 < token2 + MAX_LINE_LEN; next3++ ) { + + if ( *next3 == '/' ) { + next3 = next3 + 1; + count = sscanf ( next3, "%d%n", &node, &width ); + + if ( 0 < node && node <= num_vert_normal ) { + nlist[ivert] = node-1; + } + break; + } + } + } + ivert = ivert + 1; + } + + if ( ivert >= 3 ) { + + //quad? + if ( ivert == 4 ) { + if ( num_face+1 < MAX_FACE ) { + //0,1,3 + face[num_face].vlist[0] = vlist[0] ; + face[num_face].tlist[0] = tlist[0] ; + face[num_face].nlist[0] = nlist[0] ; + face[num_face].vlist[1] = vlist[1] ; + face[num_face].tlist[1] = tlist[1] ; + face[num_face].nlist[1] = nlist[1] ; + face[num_face].vlist[2] = vlist[3] ; + face[num_face].tlist[2] = tlist[3] ; + face[num_face].nlist[2] = nlist[3] ; + face[num_face].mat_index = mat_current ; + num_face = num_face + 1; + //3,1,2 + face[num_face].vlist[0] = vlist[3] ; + face[num_face].tlist[0] = tlist[3] ; + face[num_face].nlist[0] = nlist[3] ; + face[num_face].vlist[1] = vlist[1] ; + face[num_face].tlist[1] = tlist[1] ; + face[num_face].nlist[1] = nlist[1] ; + face[num_face].vlist[2] = vlist[2] ; + face[num_face].tlist[2] = tlist[2] ; + face[num_face].nlist[2] = nlist[2] ; + face[num_face].mat_index = mat_current ; + num_face = num_face + 1; + } + } + else { + if ( num_face < MAX_FACE ) { + for ( int i = 0 ; i < 3 ; i ++ ) { + face[num_face].vlist[i] = vlist[i] ; + face[num_face].tlist[i] = tlist[i] ; + face[num_face].nlist[i] = nlist[i] ; + } + face[num_face].mat_index = mat_current ; + num_face = num_face + 1; + } + } + } + } + +/* + G + Group name. +*/ + + else if ( leqi ( token, "G" ) == TRUE ) { + continue; + } +/* + L + I believe OBJ line node indices are 1 based rather than 0 based. + So we have to decrement them before loading them into LINE_DEX. +*/ + + else if ( leqi ( token, "L" ) == TRUE ) { + + int lastnode = -1 ; + + for ( ;; ) { + + count = sscanf ( next, "%d%n", &node, &width ); + next = next + width; + + if ( count != 1 ) { + break; + } + + if ( lastnode != -1 && num_line + 2 <= MAX_LINE ) { + + line_dex[num_line] = lastnode-1; + num_line = num_line + 1; + line_dex[num_line] = node-1; + num_line = num_line + 1; + } + + lastnode = node ; + } + } + +/* + LOD + Level of detail. +*/ + else if ( leqi ( token, "LOD" ) == TRUE ) { + continue; + } +/* + MG + Merging group. +*/ + else if ( leqi ( token, "MG" ) == TRUE ) { + continue; + } +/* + MTLLIB + Material library. +*/ + + else if ( leqi ( token, "MTLLIB" ) == TRUE ) { + + count = sscanf ( next, "%s%n", token2, &width ); + next = next + width; + + if ( count != 1 ) { + continue; + } + + load_materials ( token2 ) ; + mat_current = 0 ; + } +/* + USEMTL + Material name. +*/ + else if ( leqi ( token, "USEMTL" ) == TRUE ) { + + mat_current = 0 ; + + count = sscanf ( next, "%s%n", token2, &width ); + next = next + width; + + if ( count != 1 ) { + continue; + } + + for ( int i = 0 ; i < num_mat ; i ++ ) + if ( strcmp ( token2, materials[ i ].name ) == 0 ) + { + mat_current = i ; + break ; + } + } +/* + O + Object name. +*/ + else if ( leqi ( token, "O" ) == TRUE ) { + continue; + } +/* + P + Point. +*/ + else if ( leqi ( token, "P" ) == TRUE ) { + continue; + } +/* + SURF + Surface. +*/ + else if ( leqi ( token, "SURF" ) == TRUE ) { + continue; + } +/* + V X Y Z W + Geometric vertex. + W is optional, a weight for rational curves and surfaces. + The default for W is 1. +*/ + else if ( leqi ( token, "V" ) == TRUE ) { + + sscanf ( next, "%e %e %e", &r1, &r2, &r3 ); + + if ( num_vert < MAX_VERT ) { + vert[num_vert][0] = r1; + vert[num_vert][1] = r2; + vert[num_vert][2] = r3; + + num_vert = num_vert + 1; + } + } +/* + VT + Vertex texture. +*/ + else if ( leqi ( token, "VT" ) == TRUE ) { + + sscanf ( next, "%e %e %e", &r1, &r2, &r3 ); + + if ( num_vert_tex < MAX_VERT ) { + vert_tex[num_vert_tex][0] = r1; + vert_tex[num_vert_tex][1] = r2; + vert_tex[num_vert_tex][2] = r3; + + num_vert_tex = num_vert_tex + 1; + } + } +/* + VN + Vertex normals. +*/ + else if ( leqi ( token, "VN" ) == TRUE ) { + + sscanf ( next, "%e %e %e", &r1, &r2, &r3 ); + + if ( num_vert_normal < MAX_VERT ) { + vert_normal[num_vert_normal][0] = r1; + vert_normal[num_vert_normal][1] = r2; + vert_normal[num_vert_normal][2] = r3; + + num_vert_normal = num_vert_normal + 1; + } + } + } + + //create ssg nodes + if ( num_face ) + { + if ( num_mat ) { + for ( int i=0; i add ( vert[ line_dex[i] ] ) ; + ssgVtxTable *vtab = new ssgVtxTable ( GL_LINES, vlist, 0, 0, 0 ); + current_branch -> addKid ( vtab ) ; + } + + delete[] materials ; + delete[] vert ; + delete[] vert_tex ; + delete[] vert_normal ; + delete[] face ; + delete[] line_dex ; + + return TRUE; +} + +ssgEntity *ssgLoadOBJ ( const char *fname, const ssgLoaderOptions* options ) +{ + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + const ssgLoaderOptions* current_options = ssgGetCurrentOptions () ; + + current_branch = NULL ; + + current_options -> makeModelPath ( filename, fname ) ; + + FILE *loader_fd = fopen ( filename, "ra" ) ; + + if ( loader_fd == NULL ) + { + ulSetError ( UL_WARNING, "ssgLoadOBJ: Failed to open '%s' for reading", filename ) ; + return NULL ; + } + + current_branch = new ssgTransform () ; + + obj_read ( loader_fd ) ; + + fclose ( loader_fd ) ; + + return current_branch ; +} diff --git a/src/ssg/ssgLoadOFF.cxx b/src/ssg/ssgLoadOFF.cxx new file mode 100644 index 0000000..deab960 --- /dev/null +++ b/src/ssg/ssgLoadOFF.cxx @@ -0,0 +1,344 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadOFF.cxx 1970 2004-10-04 08:11:26Z wolfram_kuss $ +*/ + +// +// .off loader for SSG/PLIB +// Warning: There are two formats called OFF +// +// There is Geomview off, see http://www.neuro.sfc.keio.ac.jp/~aly/polygon/format/off.html +// and http://www.graphics.cornell.edu/~gordon/peek/old/off.html +// This is the format implmented in this file. +// +// And there is off (Object File Format) by Digital Equipment Corporation, Workstation Systems Engineering +// (WSE), see for ex. http://www.dcs.ed.ac.uk/home/mxr/gfx/3d/OFF.spec. +// and http://www.landfield.com/faqs/graphics/fileformats-faq/part3/section-95.html +// We don't support this format. + +// Written by Wolfram Kuss (Wolfram.Kuss@t-online.de) in February 2001 +// +// We only support 2D and 3D data + +#include "ssgLocal.h" +#include "ssgLoaderWriterStuff.h" +#include "ssgParser.h" + +#define u32 unsigned int + +static int _ssgLoadTranslucent=TRUE; + +extern sgVec4 currentDiffuse; + +void ssgSetLoadOFFTranslucent ( int i ) +// this is a kludge. +// it might be removed/replaced later on. +{ + _ssgLoadTranslucent = i; +} + + +static /* const */ ssgLoaderOptions* current_options = NULL ; + +static _ssgParserSpec parser_spec = +{ + "\r\n\t ", // delim_chars_skipable + ",;", // delim_chars_non_skipable + NULL, // pre_processor + "", // open_brace_chars + "", // close_brace_chars + '"', // quote_char. not used for OFF + '#', // comment_char + "%" // comment_string +} ; + + +static _ssgParser parser; +static ssgBranch* top_branch; + +/*static int Ascii2Int(int &retVal, const char *token, const char* name ) +// returns TRUE on success +{ + char *endptr; + retVal = int(strtol( token, &endptr, 10)); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { parser.error("The field %s should contain an integer number but contains %s",name, token) ; + return FALSE; + } +}*/ + +static int Ascii2UInt(unsigned int &retVal, const char *token, const char* name ) +// returns TRUE on success +{ + char *endptr; + retVal = (unsigned int)(strtol( token, &endptr, 10)); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { parser.error("The field %s should contain an integer number but contains %s",name, token) ; + return FALSE; + } +} + +static int Ascii2Float(SGfloat &retVal, const char *token, const char* name ) +// returns TRUE on success +{ + char *endptr; + retVal = SGfloat(strtod( token, &endptr)); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { parser.error("The field %s should contain an integer number but contains %s",name, token) ; + return FALSE; + } +} + + + + +#define MAX_NO_VERTICES_PER_FACE 1000 + +static class ssgLoaderWriterMesh theMesh; + + + + + +static int _ssgNoFacesToRead=-1, _ssgNoVerticesToRead; + +static int thereIs_ST=FALSE, thereIs_C=FALSE, thereIs_N=FALSE, + thereIs_4=FALSE, thereIs_n=TRUE; +static unsigned int dimension; // may be 2 or 3 + +static int parse() +{ + char* token; + + token = parser.getLine( 0 ); + if ( token == NULL ) + { parser.error("The file seems to be empty"); + return FALSE; + } + // If first line is "off", swallow it + if ( strlen(token) >= 3 ) + { char *p = token; + p += strlen(token)-3; + if (0==strcmp("OFF", p) ) + { if ( strlen(token) > 3 ) + // parse line + { thereIs_ST = ( NULL != strstr( token, "ST" )); + thereIs_C = ( NULL != strstr( token, "C" )); + thereIs_N = ( NULL != strstr( token, "N" )); + thereIs_4 = ( NULL != strstr( token, "4" )); + thereIs_n = ( NULL != strstr( token, "n" )); + if ( thereIs_ST || thereIs_C || thereIs_N ) + { parser.error("This is a \"ST\"- \"C\"- or \"N\"-OFF. These are not supoorted, sorry."); + return FALSE; + } + if ( thereIs_4 && !thereIs_n ) + { parser.error("This is a 4D-OFF file. We only support 3D data, sorry."); + return FALSE; + } + } + token = parser.getLine( 0 ); + assert( token != NULL ); + } + } + if ( thereIs_n ) + { + if ( ! Ascii2UInt(dimension, token, "Dimension" )) + return FALSE; + if ( thereIs_4 && thereIs_n ) + dimension++; + if ( (dimension != 3) && (dimension != 2)) + { parser.error("This is a %udD-OFF file. We only support 2D and 3D data, sorry.", dimension); + return FALSE; + } + token = parser.getLine( 0 ); // read space dimension + assert( token != NULL ); + } + // ****** read NVertices, NFaces and NEdges ************ + + unsigned int uInt; + int i; + if ( ! Ascii2UInt(uInt, token, "NVertices")) + return FALSE; + _ssgNoVerticesToRead = uInt; + + token = parser.parseToken( "NFaces" ); + if ( ! Ascii2UInt(uInt, token, "NFaces")) + return FALSE; + _ssgNoFacesToRead = uInt; + + token = parser.parseToken( "NEdges" ); + if ( ! Ascii2UInt(uInt, token, "NEdges")) + return FALSE; + + // **** init theMesh *** + theMesh.reInit (); + theMesh.createVertices( _ssgNoVerticesToRead ); + theMesh.createFaces ( _ssgNoFacesToRead ); + + + // ***** read Vertex Coords + for ( i = 0; i < _ssgNoVerticesToRead ; i++ ) + { + sgVec3 vert; + token = parser.getLine( ); // may return NULL? + assert(token!=NULL); + + if (!Ascii2Float(vert[0], token, "x")) + return FALSE; + if (!parser.parseFloat(vert[1], "y")) + return FALSE; + if ( dimension == 2 ) + vert[2] = 0.0; + else + if (!parser.parseFloat(vert[2], "z")) + return FALSE; + theMesh.addVertex(vert); + } + // ********* Read Faces ********** + int iVertex, aiVertices[MAX_NO_VERTICES_PER_FACE]; + unsigned int nNoOfVerticesForThisFace, j; + + for(i=0;i<_ssgNoFacesToRead ;i++) + { token = parser.getLine( ); // may return NULL? + assert(token!=NULL); + if (!Ascii2UInt(nNoOfVerticesForThisFace , token, "number of vertices for this face")) + return FALSE; + assert(nNoOfVerticesForThisFace setTranslucent () ; + ss -> disable ( GL_ALPHA_TEST ) ; + ss -> enable ( GL_BLEND ) ; + + //new + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + ss->setAlphaClamp(0.1f); + } + float *ssf=ss->getMaterial ( GL_DIFFUSE ); + ssf[0]=0.8f; + ssf[1]=0.8f; + ssf[2]=1.0f; + if ( _ssgLoadTranslucent ) + ssf[3]=0.4f; + else + ssf[3]=1.0f; + sgCopyVec4 ( currentDiffuse, ssf ); + + ssf=ss->getMaterial ( GL_EMISSION ); + ssf[0]=0.0f; + ssf[1]=0.0f; + ssf[2]=0.0f; + ssf[3]=1.0f; + ssf=ss->getMaterial ( GL_SPECULAR ); + ssf[0]=1.0f; + ssf[1]=1.0f; + ssf[2]=1.0f; + ssf[3]=1.0f; + ssf=ss->getMaterial ( GL_AMBIENT ); + ssf[0]=0.3f; + ssf[1]=0.3f; + ssf[2]=0.3f; + ssf[3]=1.0f; + + + if ( !_ssgLoadTranslucent ) + // This code has simply been copyied over from ssgLoadM, where it works + { ss->setOpaque(); + ss->disable(GL_BLEND); + ss->disable(GL_ALPHA_TEST); + ss->disable(GL_TEXTURE_2D); + ss->enable(GL_COLOR_MATERIAL); + ss->enable(GL_LIGHTING); + ss->setShadeModel(GL_SMOOTH); + ss->setMaterial(GL_AMBIENT , 0.7f, 0.7f, 0.0f, 1.0f); + ss->setMaterial(GL_DIFFUSE , 0.7f, 0.7f, 0.0f, 1.0f); + ss->setMaterial(GL_SPECULAR, 1.0f, 1.0f, 1.0f, 1.0f); + ss->setMaterial(GL_EMISSION, 0.0f, 0.0f, 0.0f, 1.0f); + ss->setShininess(50); + } + + + theMesh.createMaterials( 1 ); + theMesh.addMaterial( &ss ); + theMesh.createMaterialIndices( _ssgNoFacesToRead ) ; + for(i=0;i<_ssgNoFacesToRead ;i++) + theMesh.addMaterialIndex ( 0 ) ; + + + theMesh.addToSSG( + ss, // kludge. NIV135 + current_options, + top_branch); + + return TRUE ; +} + + +ssgEntity *ssgLoadOFF ( const char *fname, const ssgLoaderOptions* options ) +{ + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + current_options = ssgGetCurrentOptions () ; + + top_branch = new ssgBranch ; + if ( !parser.openFile( fname, &parser_spec )) + { + delete top_branch ; + return 0; + } + if ( !parse() ) + { + delete top_branch ; + top_branch = 0 ; + } +// parse_free(); + parser.closeFile(); + + return top_branch ; +} diff --git a/src/ssg/ssgLoadPCX.cxx b/src/ssg/ssgLoadPCX.cxx new file mode 100644 index 0000000..8ccd2a4 --- /dev/null +++ b/src/ssg/ssgLoadPCX.cxx @@ -0,0 +1,188 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 2001 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadPCX.cxx 1963 2004-09-26 09:27:28Z bram $ +*/ + +//=========================================================================== +// +// File: ssgLoadPCX.cxx +// +// Created: 12.12.2003 +// +// Author: Wolfram Kuss +// +// Revision: $Id: ssgLoadPCX.cxx 1963 2004-09-26 09:27:28Z bram $ +// +// Description: Loads PCX texture files. Only 8 bit indexed for now. +// +// +//=========================================================================== + +#include "ssgLocal.h" +typedef unsigned char UByte,*UByteP; +#include "pcx.h" + + +#ifdef SSG_LOAD_PCX_SUPPORTED + +int ReadFileIntoBuffer(const char *fname, UByte *&buffer, UByte *&bufferorig, unsigned long &file_length) +// Opens the file, allocates buffer of correct size to hold the file, reads it, closes it +{ + // **** open file **** + FILE *tfile; + if ( (tfile = fopen(fname, "rb")) == NULL) { + ulSetError( UL_WARNING, "ssgLoadTexture: Failed to open file '%s' for reading.", fname ); + return false ; + } + + // **** allocate buffer, read file into it and close file **** + fseek(tfile, 0, SEEK_END); + file_length = ftell(tfile); + fseek(tfile, 0, SEEK_SET); + + buffer = new UByte[file_length]; + bufferorig = buffer; + + fread(buffer, file_length, 1, tfile); + fclose(tfile); + return true; +} + +bool ssgLoadPCX ( const char *fname, ssgTextureInfo* info ) +{ + UByte *buffer, *bufferorig; + unsigned long file_length; + if(!ReadFileIntoBuffer(fname, buffer, bufferorig, file_length)) + return false ; + // **** "read" header and "analyse" it **** + pcxHeaderType *ppcxHeader = (pcxHeaderType *) buffer; + buffer += sizeof(pcxHeaderType); + + short width = ppcxHeader->xmax-ppcxHeader->x+1; + short height = ppcxHeader->ymax-ppcxHeader->y+1; + //p->isMasked = ((p->resOfRowanTexture & 0x200) != 0) ? 1 : 0; + + if ( info != NULL ) + { + info -> width = width ; + info -> height = height ; + info -> depth = 4 ; + info -> alpha = TRUE ; //I think we have to set it to true always, since we always generate 4 bytes per pixel + } + + // **** read body´; Do error checking **** + long size = ((long)width)*height; + UByte *pAlfa = NULL, * pBody = new UByte [size]; // 1 byte per texel + UByte * pBodyorig = pBody; + + if(!ReadPCXBody(buffer, ppcxHeader, pBody)) +// writes to pBody, which must have been allocated + { + delete [] buffer; + delete [] pBody; + ulSetError ( UL_WARNING, + "ssgLoadTexture: '%s' - unsupported or broken PCX texture file", fname ) ; + return false ; + } + if(*buffer++ != 12) + { ulSetError ( UL_WARNING, "ssgLoadTexture: '%s' - PCX files needs a '12' byte", fname ) ; + return false ; + } + assert(bufferorig + file_length - 768 == buffer); + // starting at "buffer", you can find the palette, 256 entrys with 3 bytes each + // only true for version 5 (and possible later versions)= + +// start alfa handling + // PCX does not allow alfa, so to enable alfa, you need two files :-(, + // one for the body, for example abc.pcx and one for the alfa component, for example abc_trans.pcx + if(fname[strlen(fname)-4]=='.') + { + char *t, *s = new char[strlen(fname)+15]; + strcpy(s, fname); + t=&(s[strlen(s)-4]); + strcpy(t, "_trans.pcx"); + if(ulFileExists(s)) + { + UByte *alfaBuffer, *alfaBufferorig; + if(!ReadFileIntoBuffer(s, alfaBuffer, alfaBufferorig, file_length)) + return false ; + // **** "read" header and "analyse" it **** + ppcxHeader = (pcxHeaderType *) alfaBuffer; + alfaBuffer += sizeof(pcxHeaderType); + + if(width != ppcxHeader->xmax-ppcxHeader->x+1) + ulSetError ( UL_WARNING, "ssgLoadTexture: '%s' - Width does not agree to 'body' width, so alfa is ignored", s ) ; + else + { + + if (height != ppcxHeader->ymax-ppcxHeader->y+1) + ulSetError ( UL_WARNING, "ssgLoadTexture: '%s' - Height does not agree to 'body' height, so alfa is ignored", s ) ; + else + { + // **** read body´; Do error checking **** + pAlfa = new UByte [size]; // 1 byte per texel + + if(!ReadPCXBody(alfaBuffer, ppcxHeader, pAlfa)) + // writes to pBody, which must have been allocated + { + delete [] buffer; + delete [] pAlfa; + ulSetError ( UL_WARNING, + "ssgLoadTexture: '%s' - unsupported or broken PCX texture file", fname ) ; + return false ; + } + } + } + } + } +// end alfa handling + + UByte *texels = new UByte [size * 4]; // 4 bytes per texel + int c = 0; + int iRunningIndex = 0; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + UByte a = pAlfa?pAlfa[iRunningIndex]:255; + UByte b = pBody[iRunningIndex++]; + texels[c++] = buffer[b*3 ]; + texels[c++] = buffer[b*3 + 1]; + texels[c++] = buffer[b*3 + 2]; + texels[c++] = a; + } + } + + delete [] pBodyorig; + delete [] bufferorig; + if (pAlfa) + delete [] pAlfa; + return ssgMakeMipMaps ( texels, width, height, 4 ) ; +} +#else + +bool ssgLoadPCX ( const char *fname, ssgTextureInfo* info ) +{ + ulSetError ( UL_WARNING, + "ssgLoadTexture: '%s' - PCX texture support not configured", fname ) ; + return false ; +} + +#endif + diff --git a/src/ssg/ssgLoadPNG.cxx b/src/ssg/ssgLoadPNG.cxx new file mode 100644 index 0000000..774e2d0 --- /dev/null +++ b/src/ssg/ssgLoadPNG.cxx @@ -0,0 +1,57 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadPNG.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "ssgLocal.h" + +#ifdef SSG_LOAD_PNG_SUPPORTED + +#include + +bool ssgLoadPNG ( const char *fname, ssgTextureInfo* info ) +{ + pngInfo png_info; + if (!pngLoad(fname, PNG_BUILDMIPMAP, PNG_ALPHA, &png_info)) { + ulSetError ( UL_WARNING, "ssgLoadTexture: Failed to load '%s'.", fname ) ; + return false ; + } + if ( info != NULL ) + { + info -> width = png_info.Width ; + info -> height = png_info.Height ; + info -> depth = png_info.Depth ; + info -> alpha = png_info.Alpha ; + } + return true ; +} + +#else + +bool ssgLoadPNG ( const char *fname, ssgTextureInfo* info ) +{ + ulSetError ( UL_WARNING, "ssgLoadTexture: '%s' - you need glpng for PNG format support", + fname ) ; + return false ; +} + +#endif diff --git a/src/ssg/ssgLoadSGI.cxx b/src/ssg/ssgLoadSGI.cxx new file mode 100644 index 0000000..8727b3a --- /dev/null +++ b/src/ssg/ssgLoadSGI.cxx @@ -0,0 +1,538 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadSGI.cxx 2081 2006-04-16 17:45:33Z bram $ +*/ + + +#include "ssgLocal.h" + +/* Some magic constants in the file header. */ + +#define SGI_IMG_MAGIC 0x01DA +#define SGI_IMG_SWABBED_MAGIC 0xDA01 /* This is how it appears on a PC */ +#define SGI_IMG_VERBATIM 0 +#define SGI_IMG_RLE 1 + +class ssgSGIHeader +{ +public: /* Yuk! Need to hide some of this public stuff! */ + unsigned short magic ; + int max ; + int min ; + int colormap ; + char type ; + char bpp ; + unsigned int *start ; + int *leng ; + unsigned short dim ; + unsigned short xsize ; + unsigned short ysize ; + unsigned short zsize ; + int tablen ; + /* added by J. Nathan Matias */ + FILE *image_fd; + char image_fname [ 512 ]; + int isSwapped; + unsigned char *rle_temp; + bool loadSGI_bool; + + + ssgSGIHeader () ; + ssgSGIHeader(const char *fname, ssgTextureInfo* info ); + ~ssgSGIHeader () ; + + bool openFile(const char *fname); + void makeConsistant () ; + void getRow ( unsigned char *buf, int y, int z ) ; + void getPlane ( unsigned char *buf, int z ) ; + void getImage ( unsigned char *buf ) ; + void readHeader () ; + +protected: + void swab_short ( unsigned short *x ); + void swab_int ( unsigned int *x ); + void swab_int_array ( int *x, int leng ); + unsigned char readByte (); + unsigned short readShort (); + unsigned int readInt (); + +} ; + + +#ifdef SSG_LOAD_SGI_SUPPORTED + +void ssgSGIHeader::makeConsistant () +{ + /* + Sanity checks - and a workaround for buggy RGB files generated by + the MultiGen Paint program because it will sometimes get confused + about the way to represent maps with more than one component. + + eg Y > 1, Number of dimensions == 1 + Z > 1, Number of dimensions == 2 + */ + + if ( ysize > 1 && dim < 2 ) dim = 2 ; + if ( zsize > 1 && dim < 3 ) dim = 3 ; + if ( dim < 1 ) ysize = 1 ; + if ( dim < 2 ) zsize = 1 ; + if ( dim > 3 ) dim = 3 ; + if ( zsize < 1 && ysize == 1 ) dim = 1 ; + if ( zsize < 1 && ysize != 1 ) dim = 2 ; + if ( zsize >= 1 ) dim = 3 ; + + /* + A very few SGI image files have 2 bytes per component - this + library cannot deal with those kinds of files. + */ + + if ( bpp == 2 ) + { + ulSetError ( UL_FATAL, "ssgLoadTexture: Can't work with SGI images with %d bpp", bpp ) ; + } + + bpp = 1 ; + min = 0 ; + max = 255 ; + magic = SGI_IMG_MAGIC ; + colormap = 0 ; +} + + +void ssgSGIHeader::swab_short ( unsigned short *x ) +{ + if ( isSwapped ) + *x = (( *x >> 8 ) & 0x00FF ) | + (( *x << 8 ) & 0xFF00 ) ; +} + +void ssgSGIHeader::swab_int ( unsigned int *x ) +{ + if ( isSwapped ) + *x = (( *x >> 24 ) & 0x000000FF ) | + (( *x >> 8 ) & 0x0000FF00 ) | + (( *x << 8 ) & 0x00FF0000 ) | + (( *x << 24 ) & 0xFF000000 ) ; +} + +void ssgSGIHeader::swab_int_array ( int *x, int leng ) +{ + if ( ! isSwapped ) + return ; + + for ( int i = 0 ; i < leng ; i++ ) + { + *x = (( *x >> 24 ) & 0x000000FF ) | + (( *x >> 8 ) & 0x0000FF00 ) | + (( *x << 8 ) & 0x00FF0000 ) | + (( *x << 24 ) & 0xFF000000 ) ; + x++ ; + } +} + + +unsigned char ssgSGIHeader::readByte () +{ + unsigned char x ; + fread ( & x, sizeof(unsigned char), 1, image_fd ) ; + return x ; +} + +unsigned short ssgSGIHeader::readShort () +{ + unsigned short x ; + fread ( & x, sizeof(unsigned short), 1, image_fd ) ; + swab_short ( & x ) ; + return x ; +} + +unsigned int ssgSGIHeader::readInt () +{ + unsigned int x ; + fread ( & x, sizeof(unsigned int), 1, image_fd ) ; + swab_int ( & x ) ; + return x ; +} + + +void ssgSGIHeader::getRow ( unsigned char *buf, int y, int z ) +{ + if ( y >= ysize ) y = ysize - 1 ; + if ( z >= zsize ) z = zsize - 1 ; + + fseek ( image_fd, start [ z * ysize + y ], SEEK_SET ) ; + + if ( type == SGI_IMG_RLE ) + { + unsigned char *tmpp = rle_temp ; + unsigned char *bufp = buf ; + int length = leng [ z * ysize + y ]; + + fread ( rle_temp, 1, length, image_fd ) ; + + unsigned char pixel, count ; + + while ( tmpp < rle_temp + length ) + { + pixel = *tmpp++ ; + + count = ( pixel & 0x7f ) ; + + if ( count == 0 ) + break ; + + if ( pixel & 0x80 ) + { + while ( count-- ) + *bufp++ = *tmpp++ ; + } + else + { + pixel = *tmpp++ ; + + while ( count-- ) + *bufp++ = pixel ; + } + } + } + else + fread ( buf, 1, xsize, image_fd ) ; +} + + +void ssgSGIHeader::getPlane ( unsigned char *buf, int z ) +{ + if ( image_fd == NULL ) + return ; + + if ( z >= zsize ) z = zsize - 1 ; + + for ( int y = 0 ; y < ysize ; y++ ) + getRow ( & buf [ y * xsize ], y, z ) ; +} + + + +void ssgSGIHeader::getImage ( unsigned char *buf ) +{ + if ( image_fd == NULL ) + return ; + + for ( int y = 0 ; y < ysize ; y++ ) + for ( int z = 0 ; z < zsize ; z++ ) + getRow ( & buf [ ( z * ysize + y ) * xsize ], y, z ) ; +} + + +ssgSGIHeader::ssgSGIHeader () +{ + dim = 0 ; + start = NULL ; + leng = NULL ; + rle_temp = NULL ; + image_fd = NULL ; +} + +ssgSGIHeader::ssgSGIHeader ( const char *fname, ssgTextureInfo* info ) +{ + ssgSGIHeader *sgihdr = this ; + + start = NULL ; + leng = NULL ; + rle_temp = NULL ; + + bool success=openFile(fname); + + if ( !success ) + { + loadSGI_bool = false ; + return ; + } + + GLubyte *image = new GLubyte [ sgihdr->xsize * + sgihdr->ysize * + sgihdr->zsize ] ; + + GLubyte *ptr = image ; + + unsigned char *rbuf = new unsigned char [ sgihdr->xsize ] ; + unsigned char *gbuf = (sgihdr->zsize>1) ? new unsigned char [ sgihdr->xsize ] : (unsigned char *) NULL ; + unsigned char *bbuf = (sgihdr->zsize>2) ? new unsigned char [ sgihdr->xsize ] : (unsigned char *) NULL ; + unsigned char *abuf = (sgihdr->zsize>3) ? new unsigned char [ sgihdr->xsize ] : (unsigned char *) NULL ; + + for ( int y = 0 ; y < sgihdr->ysize ; y++ ) + { + int x ; + + switch ( sgihdr->zsize ) + { + case 1 : + sgihdr->getRow ( rbuf, y, 0 ) ; + + for ( x = 0 ; x < sgihdr->xsize ; x++ ) + *ptr++ = rbuf [ x ] ; + + break ; + + case 2 : + sgihdr->getRow ( rbuf, y, 0 ) ; + sgihdr->getRow ( gbuf, y, 1 ) ; + + for ( x = 0 ; x < sgihdr->xsize ; x++ ) + { + *ptr++ = rbuf [ x ] ; + *ptr++ = gbuf [ x ] ; + } + break ; + + case 3 : + sgihdr->getRow ( rbuf, y, 0 ) ; + sgihdr->getRow ( gbuf, y, 1 ) ; + sgihdr->getRow ( bbuf, y, 2 ) ; + + for ( x = 0 ; x < sgihdr->xsize ; x++ ) + { + *ptr++ = rbuf [ x ] ; + *ptr++ = gbuf [ x ] ; + *ptr++ = bbuf [ x ] ; + } + break ; + + case 4 : + sgihdr->getRow ( rbuf, y, 0 ) ; + sgihdr->getRow ( gbuf, y, 1 ) ; + sgihdr->getRow ( bbuf, y, 2 ) ; + sgihdr->getRow ( abuf, y, 3 ) ; + + for ( x = 0 ; x < sgihdr->xsize ; x++ ) + { + *ptr++ = rbuf [ x ] ; + *ptr++ = gbuf [ x ] ; + *ptr++ = bbuf [ x ] ; + *ptr++ = abuf [ x ] ; + } + break ; + } + } + + fclose ( image_fd ) ; + image_fd = NULL ; + + delete [] rbuf ; + delete [] gbuf ; + delete [] bbuf ; + delete [] abuf ; + + if ( info != NULL ) + { + info -> width = sgihdr->xsize ; + info -> height = sgihdr->ysize ; + info -> depth = sgihdr->zsize ; + info -> alpha = ( sgihdr->zsize == 2 || sgihdr->zsize == 4 ) ; + } + + bool result = + ssgMakeMipMaps ( image, sgihdr->xsize, sgihdr->ysize, sgihdr->zsize ) ; + + + loadSGI_bool= result ; +} + + + +ssgSGIHeader::~ssgSGIHeader() +{ + if (start != NULL) + delete [] start; + + if (leng != NULL) + delete [] leng; + + if (image_fd != NULL) + fclose(image_fd); + + if (rle_temp != NULL) + delete [] rle_temp; +} + + +void ssgSGIHeader::readHeader () +{ + isSwapped = FALSE ; + + magic = readShort () ; + + if ( magic != SGI_IMG_MAGIC && magic != SGI_IMG_SWABBED_MAGIC ) + { + ulSetError ( UL_FATAL, "%s: Unrecognised magic number 0x%04x", + image_fname, magic ) ; + } + + if ( magic == SGI_IMG_SWABBED_MAGIC ) + { + isSwapped = TRUE ; + swab_short ( & magic ) ; + } + + type = readByte () ; + bpp = readByte () ; + dim = readShort () ; + + /* + This is a backstop test - if for some reason the magic number isn't swabbed, this + test will still catch a swabbed file. Of course images with more than 256 dimensions + are not catered for :-) + */ + + if ( dim > 255 ) + { + ulSetError ( UL_WARNING, "%s: Bad swabbing?!?", image_fname ) ; + isSwapped = ! isSwapped ; + swab_short ( & dim ) ; + magic = SGI_IMG_MAGIC ; + } + + xsize = readShort () ; + ysize = readShort () ; + zsize = readShort () ; + min = readInt () ; + max = readInt () ; + readInt () ; /* Dummy field */ + + int i ; + + for ( i = 0 ; i < 80 ; i++ ) + readByte () ; /* Name field */ + + colormap = readInt () ; + + for ( i = 0 ; i < 404 ; i++ ) + readByte () ; /* Dummy field */ + + makeConsistant () ; + + tablen = ysize * zsize ; + start = new unsigned int [ tablen ] ; + leng = new int [ tablen ] ; +} + +bool ssgSGIHeader::openFile(const char *fname) +{ + ssgSGIHeader *sgihdr=this; + + strcpy ( image_fname, fname ) ; + image_fd = fopen ( image_fname, "rb" ) ; + + if ( image_fd == NULL ) + { + /* perror ( "ssgLoadTexture" ) ;*/ + ulSetError ( UL_WARNING, "ssgSGIHeader::: Failed to open '%s' for reading.", image_fname ) ; + return false ; + } + + sgihdr -> readHeader () ; + + if ( sgihdr -> type == SGI_IMG_RLE ) + { + fread ( sgihdr->start, sizeof (unsigned int), sgihdr->tablen, image_fd ) ; + fread ( sgihdr->leng , sizeof (int), sgihdr->tablen, image_fd ) ; + swab_int_array ( (int *) sgihdr->start, sgihdr->tablen ) ; + swab_int_array ( (int *) sgihdr->leng , sgihdr->tablen ) ; + + int maxlen = 0 ; + + for ( int i = 0 ; i < sgihdr->tablen ; i++ ) + if ( sgihdr->leng [ i ] > maxlen ) + maxlen = sgihdr->leng [ i ] ; + + rle_temp = new unsigned char [ maxlen ] ; + } + else + { + rle_temp = NULL ; + + for ( int i = 0 ; i < sgihdr->zsize ; i++ ) + for ( int j = 0 ; j < sgihdr->ysize ; j++ ) + { + sgihdr->start [ i * sgihdr->ysize + j ] = sgihdr->xsize * ( i * sgihdr->ysize + j ) + 512 ; + sgihdr->leng [ i * sgihdr->ysize + j ] = sgihdr->xsize ; + } + } + + if ( sgihdr->zsize <= 0 || sgihdr->zsize > 4 ) + { + ulSetError ( UL_FATAL, "ssgLoadTexture: '%s' is corrupted.", image_fname ) ; + } + + return true ; +} + + +//wrapper function that does the same job as the previous one +//except we now have a better architecture + +bool ssgLoadSGI ( const char *fname, ssgTextureInfo* info ) +{ + ssgSGIHeader *sgihdr=new ssgSGIHeader( fname, info); + bool returnval=sgihdr->loadSGI_bool; + delete sgihdr; + return returnval; +} + + +#else + + /*if there's no SGI support, allow things to compile, but print an error*/ +ssgSGIHeader::ssgSGIHeader() +{ + ulSetError ( UL_WARNING, + "ssgLoadTexture: '%s' - SGI support not configured", fname ) ; + return; +} + + +ssgSGIHeader::ssgSGIHeader(const char *fname, ssgTextureInfo* info ) +{ + ulSetError ( UL_WARNING, + "ssgLoadTexture: '%s' - SGI support not configured", fname ) ; + return; +} + +void SGIHeader::makeConsistant (){return;} +void SGIHeader::getRow ( unsigned char *buf, int y, int z ) {return;} +void SGIHeader::getPlane ( unsigned char *buf, int z ) {return;} +void SGIHeader::getImage ( unsigned char *buf ) {return;} +void SGIHeader::readHeader () {return;} +void SGIHeader::swab_short ( unsigned short *x ){return;} +void SGIHeader::swab_int ( unsigned int *x ){return;} +void SGIHeader::swab_int_array ( int *x, int leng ){return;} +unsigned char SGIHeader::readByte (){return;} +unsigned short SGIHeader::readShort (){return;} +unsigned int SGIHeader::readInt (){return;} + +bool ssgLoadSGI ( const char *fname, ssgTextureInfo* info ) +{ + ulSetError ( UL_WARNING, + "ssgLoadTexture: '%s' - SGI support not configured", fname ) ; + return false ; +} + +#endif diff --git a/src/ssg/ssgLoadSSG.cxx b/src/ssg/ssgLoadSSG.cxx new file mode 100644 index 0000000..b249848 --- /dev/null +++ b/src/ssg/ssgLoadSSG.cxx @@ -0,0 +1,277 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadSSG.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + +// code for loading and writing .ssg files + +#include "ssgLocal.h" + +// used for reading only: +int _ssgFileVersionNumber = 0 ; + +// simple list of ssgBase derived objects: +class _ssgBaseList : public ssgSimpleList +{ +public: + + _ssgBaseList() : ssgSimpleList( sizeof(ssgBase *), 16 ) {} + + ~_ssgBaseList() {} + + ssgBase *get ( unsigned n ) + { + return n < total ? ((ssgBase **) list) [ n ] : NULL; + } + + void add ( ssgBase *obj ) + { + sizeChk ( 1 ) ; + ((ssgBase **) list) [ total++ ] = obj ; + } + + int find ( ssgBase *obj ) + { + for ( unsigned i = 0 ; i < total ; i++ ) + if ( ((ssgBase **) list) [ i ] == obj ) + return i ; + return -1 ; + } + +}; + +// list of ssgBase objects for instance referencing: +static _ssgBaseList *_ssgInstanceList ; + + +int _ssgLoadObject ( FILE *f, ssgBase **objp, int type_mask ) +{ + int type = 0, key = 0; + ssgBase *obj; + + _ssgReadInt ( f, &type ) ; + + if ( type == _SSG_BACKWARDS_REFERENCE ) + { + _ssgReadInt ( f, &key ) ; + + obj = _ssgInstanceList -> get ( key ) ; + if ( obj == NULL ) + { + if ( key != 0 ) + { + ulSetError ( UL_WARNING, + "ssgLoadObject: Unexpected null object for key %d.", key ) ; + return FALSE ; + } + } + else if ( ! obj -> isAKindOf ( type_mask ) ) + { + ulSetError ( UL_WARNING, "ssgLoadObject: Bad type %#x (%s), expected %#x.", + obj -> getType (), obj -> getTypeName (), type_mask ) ; + return FALSE ; + } + } + else + { + if ( ( type & type_mask ) != type_mask ) + { + ulSetError ( UL_WARNING, "ssgLoadObject: Bad type %#x, expected %#x.", + type, type_mask ) ; + return FALSE ; + } + + obj = ssgCreateOfType ( type ) ; + if ( obj == NULL ) + return FALSE ; + + _ssgInstanceList -> add ( obj ) ; + + if ( ! obj -> load ( f ) ) + { + ulSetError ( UL_DEBUG, "ssgLoadObject: Failed to load object of type %s.", + obj -> getTypeName () ) ; + return FALSE ; + } + + if ( obj -> isAKindOf ( ssgTypeEntity () ) ) + { + ((ssgEntity *) obj) -> recalcBSphere () ; + } + } + + if ( _ssgReadError () ) + { + ulSetError ( UL_WARNING, "ssgLoadObject: Read error." ) ; + return FALSE ; + } + + *objp = obj ; + + return TRUE ; +} + + +int _ssgSaveObject ( FILE *f, ssgBase *obj ) +{ + int key = _ssgInstanceList -> find ( obj ) ; + + if ( key >= 0 ) + { + _ssgWriteInt ( f, _SSG_BACKWARDS_REFERENCE ) ; + _ssgWriteInt ( f, key ) ; + } + else + { + _ssgWriteInt ( f, obj -> getType () ) ; + + _ssgInstanceList -> add ( obj ) ; + + if ( ! obj -> save ( f ) ) + { + ulSetError ( UL_DEBUG, "ssgSaveObject: Failed to save object of type %s.", + obj -> getTypeName () ) ; + return FALSE ; + } + } + + if ( _ssgWriteError () ) + { + ulSetError ( UL_WARNING, "ssgSaveObject: Write error." ) ; + return FALSE ; + } + + return TRUE ; +} + + +ssgEntity *ssgLoadSSG ( const char *fname, const ssgLoaderOptions* options ) +{ + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + const ssgLoaderOptions* current_options = ssgGetCurrentOptions () ; + + char filename [ 1024 ] ; + current_options -> makeModelPath ( filename, fname ) ; + + FILE *fd = fopen ( filename, "rb" ) ; + + if ( fd == NULL ) + { + perror ( filename ) ; + ulSetError ( UL_WARNING, + "ssgLoadSSG: Failed to open '%s' for reading.", filename ) ; + return NULL ; + } + + int magic ; + ssgEntity *kid ; + + _ssgReadInt ( fd, & magic ) ; + + if ( ( magic & 0xFFFFFF00 ) != ( SSG_FILE_MAGIC_NUMBER & 0xFFFFFF00 ) ) + { + if (((magic & 0x0000FF)>> 0)==((SSG_FILE_MAGIC_NUMBER & 0xFF000000)>>24) && + ((magic & 0x00FF00)>> 8)==((SSG_FILE_MAGIC_NUMBER & 0x00FF0000)>>16) && + ((magic & 0xFF0000)>>16)==((SSG_FILE_MAGIC_NUMBER & 0x0000FF00)>> 8) ) + ulSetError ( UL_WARNING, "ssgLoadSSG: File appears to be byte swapped!" ) ; + else + ulSetError ( UL_WARNING, "ssgLoadSSG: File has incorrect magic number!" ) ; + + return NULL ; + } + + /* + Save the old version number so we can do recursive loads + */ + + int oldFileVersion = _ssgFileVersionNumber ; + _ssgFileVersionNumber = ( magic & 0xFF ) ; + + if ( _ssgFileVersionNumber == 0 ) + { + ulSetError ( UL_WARNING, + "ssgLoadSSG: SSG file format version zero is no longer supported, sorry! For more, see the docs." ) ; + _ssgFileVersionNumber = oldFileVersion ; + return NULL ; + } + + if ( _ssgFileVersionNumber > SSG_FILE_VERSION ) + { + ulSetError ( UL_WARNING, + "ssgLoadSSG: This version of SSG is too old to load this file!" ) ; + _ssgFileVersionNumber = oldFileVersion ; + return NULL ; + } + + _ssgBaseList *oldInstanceList = _ssgInstanceList ; // in case of recursive loads + _ssgInstanceList = new _ssgBaseList ; + _ssgInstanceList -> add ( NULL ) ; // index 0 --> NULL + + int success = _ssgLoadObject ( fd, (ssgBase **) &kid, ssgTypeEntity () ) ; + + if ( ! success ) + { + ulSetError ( UL_WARNING, "ssgLoadSSG: Failed to load object." ) ; + kid = NULL ; + } + + delete _ssgInstanceList ; + _ssgInstanceList = oldInstanceList ; + _ssgFileVersionNumber = oldFileVersion ; + + fclose ( fd ) ; + + return kid ; +} + + +int ssgSaveSSG ( const char *filename, ssgEntity *ent ) +{ + FILE *fd = fopen ( filename, "wb" ) ; + + if ( fd == NULL ) + { + perror ( filename ) ; + ulSetError ( UL_WARNING, + "ssgSaveSSG: Failed to open '%s' for writing.", filename ) ; + return FALSE ; + } + + _ssgBaseList *oldInstanceList = _ssgInstanceList ; // for recursive saves + _ssgInstanceList = new _ssgBaseList ; + _ssgInstanceList -> add ( NULL ) ; // index 0 --> NULL + + _ssgWriteInt ( fd, SSG_FILE_MAGIC_NUMBER ) ; + + int success = _ssgSaveObject ( fd, ent ) ; + + if ( ! success ) + ulSetError ( UL_WARNING, "ssgSaveSSG: Failed to write object." ) ; + + delete _ssgInstanceList ; + _ssgInstanceList = oldInstanceList ; + + fclose ( fd ) ; + + return success ; +} + + diff --git a/src/ssg/ssgLoadStrip.cxx b/src/ssg/ssgLoadStrip.cxx new file mode 100644 index 0000000..3b91a48 --- /dev/null +++ b/src/ssg/ssgLoadStrip.cxx @@ -0,0 +1,119 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadStrip.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + +#include "ssgLocal.h" + +static ssgLoaderOptions* current_options; + +ssgEntity* ssgLoadStrip( const char* fname, const ssgLoaderOptions* options ) { + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + current_options = ssgGetCurrentOptions () ; + + char filename [ 1024 ] ; + current_options -> makeModelPath ( filename, fname ) ; + + FILE* model_file = fopen(filename, "r"); + + if (model_file == NULL) { + ulSetError(UL_WARNING, "ssgLoadStrip: Couldn't open file '%s'.", filename); + return NULL; + } + + ssgSimpleState* state = new ssgSimpleState(); + state->setOpaque(); + state->disable(GL_BLEND); + state->disable(GL_ALPHA_TEST); + state->disable(GL_TEXTURE_2D); + state->enable(GL_COLOR_MATERIAL); + state->enable(GL_LIGHTING); + state->setShadeModel(GL_SMOOTH); + state->setMaterial(GL_AMBIENT , 0.7f, 0.7f, 0.0f, 1.0f); + state->setMaterial(GL_DIFFUSE , 0.7f, 0.7f, 0.0f, 1.0f); + state->setMaterial(GL_SPECULAR, 1.0f, 1.0f, 1.0f, 1.0f); + state->setMaterial(GL_EMISSION, 0.0f, 0.0f, 0.0f, 1.0f); + state->setShininess(50); + + int i; + int num_vertices = ulEndianReadLittle32(model_file); + ssgBranch* model = new ssgBranch(); + ssgVertexArray* vertices = new ssgVertexArray(); + ssgNormalArray* normals = new ssgNormalArray(); + + for (i = 0; i < num_vertices; i++) { + sgVec3 new_vec; + int j; + + for (j = 0; j < 3; j++) { + new_vec[j] = ulEndianReadLittleFloat(model_file); + } + vertices->add(new_vec); + + for (j = 0; j < 3; j++) { + new_vec[j] = ulEndianReadLittleFloat(model_file); + } + normals->add(new_vec); + } + + int num_strips = ulEndianReadLittle32(model_file); + for (i = 0; i < num_strips; i++) { + int num_indices = ulEndianReadLittle32(model_file); + + ssgIndexArray* strip_indices = new ssgIndexArray(num_indices); + + for (int j = 0; j < num_indices; j++) { + strip_indices->add( ulEndianReadLittle16(model_file) ); + } + + ssgVtxArray* varr = new ssgVtxArray( GL_TRIANGLE_STRIP, + vertices, + normals, + NULL, + NULL, + strip_indices ); + varr->setState( state ); + varr->setCullFace( TRUE ); + + ssgLeaf* leaf = current_options->createLeaf(varr, NULL); + model->addKid(leaf); + } + + int num_indices = ulEndianReadLittle32(model_file); + ssgIndexArray* indices = new ssgIndexArray(num_indices); + for (i = 0; i < num_indices; i++) { + indices->add( ulEndianReadLittle16(model_file) ); + } + + ssgVtxArray* varr = new ssgVtxArray( GL_TRIANGLES, + vertices, + normals, + NULL, + NULL, + indices ); + varr->setState( state ); + varr->setCullFace( TRUE ); + + ssgLeaf* leaf = current_options->createLeaf(varr, NULL); + model->addKid(leaf); + + return model; +} diff --git a/src/ssg/ssgLoadTGA.cxx b/src/ssg/ssgLoadTGA.cxx new file mode 100644 index 0000000..825eab9 --- /dev/null +++ b/src/ssg/ssgLoadTGA.cxx @@ -0,0 +1,452 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadTGA.cxx 1749 2003-01-30 00:51:59Z stromberg $ +*/ + + +#include "ssgLocal.h" + +#ifdef SSG_LOAD_TGA_SUPPORTED + +//#include + +/* + * Submitted by Sam Stickland : sam@spacething.org + * Targe loading code based on code written Dave Gay : f00Dave@bigfoot.com, http://personal.nbnet.nb.ca/daveg/ + * + * Jan 29, 2003: + * Added support for other image types, as well as run-length encoding. + * /marten (stromberg@users.sf.net) + */ + + +inline int get16u(const GLubyte *ptr) // little endian +{ + return (ptr[0] | (ptr[1] << 8)); +} + + +bool ssgLoadTGA ( const char *fname, ssgTextureInfo* info ) +{ + +#if 1 // new loader: + + + /* TGA file layout: + * + * ============================= + * Header: + * Ofs Sz Desc + * ---------------- + * 0 1 Image ID Length + * 1 1 Colormap Type + * 2 1 Image Type + * 3 2 Colormap Origin + * 5 2 Colormap Length + * 7 1 Colormap Entry Size + * 8 2 X Origin of Image + * 10 2 Y Origin of Image + * 12 2 Image Width + * 14 2 Image Height + * 16 1 Image Pixel Size + * 17 1 Image Descriptor + * ============================= + * Image Identification + * ============================= + * Colormap Data + * ============================= + * Image Data + * ============================= + */ + + + GLubyte header[18]; + + FILE *f = fopen(fname, "rb"); + + if ( f == NULL ) + { + ulSetError( UL_WARNING, "ssgLoadTGA: Failed to open '%s' for reading.", fname ); + return false; + } + + if ( fread(header, 18, 1, f) != 1 ) + { + ulSetError( UL_WARNING, "ssgLoadTGA: Failed to read header of '%s'.", fname ); + fclose(f); + return false; + } + + // colormap info + int cm_type = header[1]; + int cm_first = get16u(header + 3); + int cm_count = get16u(header + 5); + int cm_bits = header[7]; + + // image info + int type = header[2]; + int xsize = get16u(header + 12); + int ysize = get16u(header + 14); + int bits = header[16]; + + /* image types: + * + * 0 - no image + * 1 - colormap + * 2 - RGB + * 3 - grayscale + * 9 - colormap, RLE + * 10 - RGB, RLE + * 11 - grayscale, RLE + * + */ + + if ( cm_type > 1 || (type & ~(8+3)) != 0 || (type & 3) == 0 || ((type & 3) == 1 && cm_type == 0) ) + { + ulSetError( UL_WARNING, "ssgLoadTGA: '%s' is not a TGA image.", fname ); + fclose(f); + return false; + } + + if ( (type & 3) == 1 && cm_bits != 8 && cm_bits != 16 && cm_bits != 24 && cm_bits != 32 ) + { + ulSetError( UL_WARNING, "ssgLoadTGA: Unsupported colormap depth %d.", cm_bits ); + fclose(f); + return false; + } + + if ( ((type & 3) != 2 && bits != 8) || // colormap and grayscale must be 8-bit + ((type & 3) == 2 && bits != 16 && bits != 24 && bits != 32) ) // RGB may not be 8-bit + { + ulSetError( UL_WARNING, "ssgLoadTGA: Unsupported depth %d for image type %d.", bits, type ); + fclose(f); + return false; + } + + ulSetError( UL_DEBUG, "ssgLoadTGA: Loading '%s', %s %dx%d-%d%s.", + fname, + (type & 3) == 1 ? "colormap" : (type & 3) == 2 ? "RGB" : "grayscale", + xsize, ysize, bits, + (type & 8) != 0 ? " RLE" : ""); + + + bool eof = false; + + + // skip image identification + + if (fseek(f, header[0], SEEK_CUR) != 0) + eof = true; + + + // read colormap + + GLubyte *cm_data = 0; + + if (cm_type != 0) + { + cm_data = new GLubyte [ (cm_bits / 8) * cm_count ]; + if (fread(cm_data, (cm_bits / 8) * cm_count, 1, f) != 1) + eof = true; + } + + + // read image data + + GLubyte *image = new GLubyte [ (bits / 8) * xsize * ysize ]; + + if ((type & 8) != 0) + { + // unpack RLE data + + int comp = (bits / 8); + int current = 0; + + for (;;) + { + int code = getc(f); + + if (code == EOF) { + eof = true; + break; + } + + int length = (code & 0x7f) + 1; + + if (current + length > xsize * ysize) + { + ulSetError( UL_WARNING, "ssgLoadTGA: RLE unpack problems." ); + fclose(f); + delete [] cm_data; + delete [] image; + return false; + } + + if ((code & 0x80) == 0) + { + // raw packet + if (fread(image + current * comp, length * comp, 1, f) != 1) { + eof = true; + break; + } + current += length; + } + else + { + // run-length packet + GLubyte data[4]; + if (fread(data, comp, 1, f) != 1) { + eof = true; + break; + } + for (int i = 0; i < length; i++) + memcpy(image + (current++) * comp, data, comp); + } + + if (current == xsize * ysize) + break; + } + } + else + { + if (fread(image, (bits / 8) * xsize * ysize, 1, f) != 1) + eof = true; + } + + if (eof || ferror(f)) + { + ulSetError( UL_WARNING, "ssgLoadTGA: %s.", + ferror(f) ? "Read error" : "Unexpected end of file" ); + fclose(f); + delete [] cm_data; + delete [] image; + return false; + } + + fclose(f); + + + // apply colormap + + if ((type & 3) == 1) + { + int comp = (cm_bits / 8); + + GLubyte *source = image; + GLubyte *target = new GLubyte [ comp * xsize * ysize ]; + + for (int i = 0; i < xsize * ysize; i++) + { + int index = source[i] - cm_first; + if (index < 0 || index > cm_count) + memset(target + i * comp, 0, comp); + else + memcpy(target + i * comp, cm_data + index * comp, comp); + } + + delete [] source; + + image = target; + bits = cm_bits; + } + + delete [] cm_data; + + + // convert image to plain GL_LUMINANCE, GL_RGB or GL_RGBA + + int zsize = (bits == 8) ? 1 : (bits == 24) ? 3 : 4; + + GLubyte *pixels = new GLubyte [ xsize * ysize * zsize ]; + + for (int i = 0; i < xsize * ysize; i++) + { + switch (bits) { + + case 8: + pixels[i] = image[i]; + break; + + case 16: + { + int temp = get16u(image + 2*i); // ARRR RRGG GGGB BBBB + pixels[4*i + 0] = (temp & 0x7c00) >> 7; + pixels[4*i + 1] = (temp & 0x03e0) >> 2; + pixels[4*i + 2] = (temp & 0x001f) << 3; + pixels[4*i + 3] = (temp & 0x8000) ? 255 : 0; + break; + } + + case 24: + pixels[3*i + 0] = image[3*i + 2]; + pixels[3*i + 1] = image[3*i + 1]; + pixels[3*i + 2] = image[3*i + 0]; + break; + + case 32: + pixels[4*i + 0] = image[4*i + 2]; + pixels[4*i + 1] = image[4*i + 1]; + pixels[4*i + 2] = image[4*i + 0]; + pixels[4*i + 3] = image[4*i + 3]; + break; + } + } + + delete [] image; + +#if 0 + if (zsize == 3) + { + printf("writing 'out.ppm'...\n"); + FILE *f = fopen("out.ppm", "wb"); + fprintf(f, "P6\n%d %d\n255\n", xsize, ysize); + fwrite(pixels, 3 * xsize * ysize, 1, f); + fclose(f); + } +#endif + + if ( info != NULL ) + { + info -> width = xsize; + info -> height = ysize; + info -> depth = zsize; + info -> alpha = (zsize == 4); + } + + return ssgMakeMipMaps ( pixels, xsize, ysize, zsize ); + + +#else // old loader: + + +#define DEF_targaHeaderLength 12 +#define DEF_targaHeaderContent "\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + struct stat fileinfo; + int bytesRead, width, height, maxLen; + char *pData = NULL; + + if ( stat(fname, &fileinfo) == -1 ) { + ulSetError ( UL_WARNING, "ssgLoadTexture: Failed to load '%s'.", fname); + return false ; + } + + FILE *tfile; + if( (tfile = fopen(fname, "rb")) == NULL) { + ulSetError ( UL_WARNING, "ssgLoadTexture: Failed to load '%s'.", fname); + return false ; + } + + maxLen = fileinfo.st_size; + pData = new char [maxLen]; + fread (pData, maxLen, 1, tfile); + fclose (tfile); + pData[0] = 0x00; + + if( memcmp( pData, DEF_targaHeaderContent, DEF_targaHeaderLength ) != 0 ) { + ulSetError ( UL_WARNING, "ssgLoadTexture: Failed to load '%s'. Not a targa (apparently).", fname); + delete[] pData; + return false ; + } + + unsigned char smallArray[ 2 ]; + + memcpy( smallArray, pData + DEF_targaHeaderLength + 0, 2 ); + width = smallArray[ 0 ] + smallArray[ 1 ] * 0x0100; + + memcpy( smallArray, pData + DEF_targaHeaderLength + 2, 2 ); + height = smallArray[ 0 ] + smallArray[ 1 ] * 0x0100; + + memcpy( smallArray, pData + DEF_targaHeaderLength + 4, 2 ); + int depth = smallArray[ 0 ]; + // + smallArray[ 1 ] * 0x0100; + + if( ( width <= 0 ) || ( height <= 0 ) ) + { + ulSetError ( UL_WARNING, "ssgLoadTexture: Failed to load '%s'. Width and height < 0.", fname); + delete[] pData; + return false ; + } + + // Only allow 24-bit and 32-bit! + bool is24Bit( depth == 24 ); + bool is32Bit( depth == 32 ); + + if( !( is24Bit || is32Bit ) ) + { + ulSetError ( UL_WARNING, "ssgLoadTexture: Failed to load '%s'. Not 24 or 32 bit.", fname); + delete[] pData; + return false ; + } + + // Make it a BGRA array for now. + int bodySize( width * height * 4 ); + unsigned char * texels = new unsigned char[ bodySize ]; + if( is32Bit ) + { + // Texture is 32 bit + // Easy, just copy it. + memcpy( texels, pData + DEF_targaHeaderLength + 6, bodySize ); + } + else if( is24Bit ) + { + // Texture is 24 bit + bytesRead = DEF_targaHeaderLength + 6; + for( int loop = 0; loop < bodySize; loop += 4, bytesRead += 3 ) + { + memcpy( texels + loop, pData + bytesRead, 3 ); + texels[ loop + 3 ] = 255; // Force alpha to max. + } + } + + // Swap R & B (convert to RGBA). + for( int loop = 0; loop < bodySize; loop += 4 ) + { + unsigned char tempC = texels[ loop + 0 ]; + texels[ loop + 0 ] = texels[ loop + 2 ]; + texels[ loop + 2 ] = tempC; + } + + delete[] pData; + + if ( info != NULL ) + { + info -> width = width ; + info -> height = height ; + info -> depth = 4 ; + info -> alpha = is32Bit? 1: 0 ; + } + return ssgMakeMipMaps ( texels, width, height, 4) ; + + +#endif +} + +#else + +bool ssgLoadTGA ( const char *fname, ssgTextureInfo* info ) +{ + ulSetError ( UL_WARNING, + "ssgLoadTexture: '%s' - TGA support not configured", fname ) ; + return false ; +} + +#endif diff --git a/src/ssg/ssgLoadTRI.cxx b/src/ssg/ssgLoadTRI.cxx new file mode 100644 index 0000000..3b4bbe6 --- /dev/null +++ b/src/ssg/ssgLoadTRI.cxx @@ -0,0 +1,128 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadTRI.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + +// +// TRI ( AC3D triangle file ) import for SSG/PLIB +// Written by Dave McClurg (dpm@efn.org) in March-2000 +// + +#include "ssgLocal.h" + +#define MAX_TRI 100000 + +struct triData +{ + sgVec3 v[3] ; + int color ; +} ; + +/******************************************************************************/ + +ssgEntity *ssgLoadTRI ( const char *fname, const ssgLoaderOptions* options ) + +/******************************************************************************/ + +/* + Purpose: + + reads an AC3D triangle file. + + Example: + + Each line contains 9 floating point values and a 1 hex value for color. + the 9 floating point values represent 3 vertices of a triangle + the color format is 0xRRGGBB (eg 0xffffff is white) + + 0.0 0.0 0.0 1.0 0.0 0.0 1.0 1.0 0.0 0xffffff + +*/ +{ + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + const ssgLoaderOptions* current_options = ssgGetCurrentOptions () ; + + //open the file + char filename [ 1024 ] ; + current_options -> makeModelPath ( filename, fname ) ; + + FILE *loader_fd = fopen ( filename, "ra" ) ; + + if ( loader_fd == NULL ) + { + ulSetError ( UL_WARNING, "ssgLoadTRI: Failed to open '%s' for reading", filename ) ; + return NULL ; + } + + //read the data + triData* tri = new triData [ MAX_TRI ] ; + int num_tri = 0 ; + + char buffer [ 1024 ] ; + + while ( fgets ( buffer, 1024, loader_fd ) != NULL ) + { + float coord [9] ; + int color ; + + if ( sscanf ( buffer, "%e %e %e %e %e %e %e %e %e %d", + &coord[0], &coord[1], &coord[2], + &coord[3], &coord[4], &coord[5], + &coord[6], &coord[7], &coord[8], + &color ) != 10 ) + { + ulSetError ( UL_WARNING, "ssgLoadTRI: Can't parse triangle: %s", buffer ) ; + } + else if ( num_tri < MAX_TRI ) + { + float* cp = coord; + for ( int i=0; i<3; i++ ) + for ( int j=0; j<3; j++ ) + tri[ num_tri ].v[ i ][ j ] = *cp++; + + tri[ num_tri ].color = color ; + num_tri ++ ; + } + else + { + break; + } + } + + fclose ( loader_fd ) ; + + ssgBranch* current_branch = NULL ; + + if ( num_tri ) + { + ssgVertexArray* vlist = new ssgVertexArray ( num_tri * 3 ) ; + for ( int i=0; i add ( tri[ i ].v[ j ] ) ; + ssgVtxTable *vtab = new ssgVtxTable ( GL_TRIANGLES, vlist, 0, 0, 0 ); + current_branch = new ssgTransform () ; + current_branch -> addKid ( vtab ) ; + } + + delete[] tri ; + + return current_branch ; +} diff --git a/src/ssg/ssgLoadTexture.cxx b/src/ssg/ssgLoadTexture.cxx new file mode 100644 index 0000000..785a435 --- /dev/null +++ b/src/ssg/ssgLoadTexture.cxx @@ -0,0 +1,364 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadTexture.cxx 2137 2009-01-01 19:10:32Z fayjf $ +*/ + + +#include "ssgLocal.h" +#include + + +struct _ssgTextureFormat +{ + const char *extension ; + bool (*loadfunc) ( const char *, ssgTextureInfo* info ) ; +} ; + + +enum { MAX_FORMATS = 100 } ; + +static _ssgTextureFormat formats [ MAX_FORMATS ] ; +static int num_formats = 0 ; + +static int total_texels_loaded = 0 ; + + +int ssgGetNumTexelsLoaded () +{ + return total_texels_loaded ; +} + + +bool ssgMakeMipMaps ( GLubyte *image, int xsize, int ysize, int zsize, bool freeData ) +{ + bool non_power_of_two_tex_supported = ssgIsExtensionSupported( "GL_ARB_texture_non_power_of_two" ); + + if ( !non_power_of_two_tex_supported && + ( ! ((xsize & (xsize-1))==0) || + ! ((ysize & (ysize-1))==0) ) ) + { + ulSetError ( UL_WARNING, "Map is not a power-of-two in size!" ) ; + return false ; + } + + GLubyte *texels [ 20 ] ; /* One element per level of MIPmap */ + + for ( int l = 0 ; l < 20 ; l++ ) + texels [ l ] = NULL ; + + texels [ 0 ] = image ; + + int lev ; + + for ( lev = 0 ; (( xsize >> (lev+1) ) != 0 || + ( ysize >> (lev+1) ) != 0 ) ; lev++ ) + { + /* Suffix '1' is the higher level map, suffix '2' is the lower level. */ + + int l1 = lev ; + int l2 = lev+1 ; + int w1 = xsize >> l1 ; + int h1 = ysize >> l1 ; + int w2 = xsize >> l2 ; + int h2 = ysize >> l2 ; + + if ( w1 <= 0 ) w1 = 1 ; + if ( h1 <= 0 ) h1 = 1 ; + if ( w2 <= 0 ) w2 = 1 ; + if ( h2 <= 0 ) h2 = 1 ; + + texels [ l2 ] = new GLubyte [ w2 * h2 * zsize ] ; + + for ( int x2 = 0 ; x2 < w2 ; x2++ ) + for ( int y2 = 0 ; y2 < h2 ; y2++ ) + for ( int c = 0 ; c < zsize ; c++ ) + { + int x1 = x2 + x2 ; + int x1_1 = ( x1 + 1 ) % w1 ; + int y1 = y2 + y2 ; + int y1_1 = ( y1 + 1 ) % h1 ; + + int t1 = texels [ l1 ] [ (y1 * w1 + x1 ) * zsize + c ] ; + int t2 = texels [ l1 ] [ (y1_1 * w1 + x1 ) * zsize + c ] ; + int t3 = texels [ l1 ] [ (y1 * w1 + x1_1) * zsize + c ] ; + int t4 = texels [ l1 ] [ (y1_1 * w1 + x1_1) * zsize + c ] ; + +if ( c == 3 ) /* Alpha */ +{ + int a = t1 ; + if ( t2 > a ) a = t2 ; + if ( t3 > a ) a = t3 ; + if ( t4 > a ) a = t4 ; + texels [ l2 ] [ (y2 * w2 + x2) * zsize + c ] = a ; +} +else + texels [ l2 ] [ (y2 * w2 + x2) * zsize + c ] = + ( t1 + t2 + t3 + t4 ) / 4 ; + } + } + + texels [ lev+1 ] = NULL ; + + glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ) ; + + int map_level = 0 ; + +#ifndef PROXY_TEXTURES_ARE_BROKEN + GLint ww ; + + do + { + glTexImage2D ( GL_PROXY_TEXTURE_2D, + map_level, zsize, xsize, ysize, FALSE /* Border */, + (zsize==1)?GL_LUMINANCE: + (zsize==2)?GL_LUMINANCE_ALPHA: + (zsize==3)?GL_RGB: + GL_RGBA, + GL_UNSIGNED_BYTE, NULL ) ; + + glGetTexLevelParameteriv ( GL_PROXY_TEXTURE_2D, 0,GL_TEXTURE_WIDTH, &ww ) ; + + if ( ww == 0 ) + { + if ( freeData ) + delete [] texels [ 0 ] ; + else + delete [] texels [ 1 ] ; /* User does not want input image freed, but we need to free all the rest of them */ + + xsize >>= 1 ; + ysize >>= 1 ; + + for ( int l = 0 ; texels [ l ] != NULL ; l++ ) + texels [ l ] = texels [ l+1 ] ; + + if ( xsize < 64 && ysize < 64 ) + { + ulSetError ( UL_FATAL, + "SSG: OpenGL will not accept a downsized version ?!?" ) ; + } + } + } while ( ww == 0 ) ; +#endif + + for ( int i = 0 ; texels [ i ] != NULL ; i++ ) + { + int w = xsize>>i ; + int h = ysize>>i ; + + if ( w <= 0 ) w = 1 ; + if ( h <= 0 ) h = 1 ; + + total_texels_loaded += w * h ; + + glTexImage2D ( GL_TEXTURE_2D, + map_level, zsize, w, h, FALSE /* Border */, + (zsize==1)?GL_LUMINANCE: + (zsize==2)?GL_LUMINANCE_ALPHA: + (zsize==3)?GL_RGB: + GL_RGBA, + GL_UNSIGNED_BYTE, (GLvoid *) texels[i] ) ; + map_level++ ; + if ( freeData || ( i > 0 ) ) + delete [] texels [ i ] ; + } + + return true ; +} + + +static void ssgLoadDummyTexture ( ssgTextureInfo* info ) +{ + GLubyte *image = new GLubyte [ 2 * 2 * 3 ] ; + + /* Red and white chequerboard */ + + image [ 0 ] = 255 ; image [ 1 ] = 0 ; image [ 2 ] = 0 ; + image [ 3 ] = 255 ; image [ 4 ] = 255 ; image [ 5 ] = 255 ; + image [ 6 ] = 255 ; image [ 7 ] = 255 ; image [ 8 ] = 255 ; + image [ 9 ] = 255 ; image [ 10] = 0 ; image [ 11] = 0 ; + + if ( info != NULL ) + { + info -> width = 2 ; + info -> height = 2 ; + info -> depth = 3 ; + info -> alpha = 0 ; + } + + ssgMakeMipMaps ( image, 2, 2, 3 ) ; +} + + +void ssgAddTextureFormat ( const char* extension, + bool (*loadfunc) (const char*, ssgTextureInfo* info) ) +{ + for ( int i = 0 ; i < num_formats ; i++ ) + { + if ( ulStrEqual ( formats [ i ] . extension, extension ) ) + { + formats [ i ] . extension = extension ; + formats [ i ] . loadfunc = loadfunc ; + return ; + } + } + + if ( num_formats < MAX_FORMATS ) + { + formats [ num_formats ] . extension = extension ; + formats [ num_formats ] . loadfunc = loadfunc ; + num_formats ++ ; + } + else + { + ulSetError ( UL_WARNING, "ssgAddTextureFormat: too many formats" ); + } +} + + +static int fileMTimeCmp( const char *fname_input, const char *fname_output ) +// Compare the two input file names against their modification time +// -1: fname_input newer than fname_output +// 1: fname_input older than fname_output +// 0: stat error +{ +#if defined(UL_WIN32) && !defined(UL_CYGWIN) +#define stat _stat +#endif + struct stat buffer_in, buffer_out; + + if ( stat( fname_input, &buffer_in ) == 0 && stat( fname_output, &buffer_out ) == 0 ) + return buffer_in.st_mtime > buffer_out.st_mtime ? -1 : 1; + else + return 0; +} + + +bool ssgConvertTexture( char * fname_output, const char * fname_input ) +// converts file to .rgb (Silicon Graphics) format +// returns true if the file has been converted to rgb, or already exists as rgb +// if it returns false, then it has already output an error message +{ + char *extension ; + + strcpy( fname_output, fname_input); // copy so that a) there is enough room for .rgb and b) we don't change the buffer of fname_input + extension = strrchr(fname_output, '.'); + if ( extension == NULL ) + { + ulSetError(UL_WARNING, "There is no extension in the texture '%s'.", fname_input); + return false; // no extension -> give up + } + extension[1] = 'r'; + extension[2] = 'g'; + extension[3] = 'b'; + extension[4] = 0; + + if ( ulFileExists ( fname_output ) ) + return true; // found *.rgb-file + + // look for original, non-rgb - file + if ( !ulFileExists ( fname_input ) ) + { + ulSetError(UL_WARNING, "Can't find the texture file '%s'.", fname_input); + return false; // no input file => we can't convert it + } + + if ( ulFileExists ( fname_output ) && fileMTimeCmp( fname_input, fname_output ) != -1 ) + return true; // found *.rgb-file, and it's newer than fname_input, so no conversion is needed + + // ****** found original file. convert it. ****** + char command [ 1024 ] ; + char *conv_cmd = +#ifdef UL_WIN32 + "imconvert"; +#else + "convert"; +#endif + sprintf(command, "%s -verbose %s sgi:%s", conv_cmd, fname_input, fname_output); + + if ( system( command ) < 0 || !ulFileExists ( fname_output ) ) + { + ulSetError(UL_WARNING, "Couldn't convert texture '%s'. Did you install ImageMagick?" + " You may also convert it manually to '%s' and reload the model.", + fname_input, fname_output); + return false; + } + + return true; +} + + + +bool ssgLoadTexture ( const char * filename, ssgTextureInfo* info ) +{ + if ( info != NULL ) + { + info -> width = 0 ; + info -> height = 0 ; + info -> depth = 0 ; + info -> alpha = 0 ; + } + + if ( filename == NULL || *filename == '\0' ) + return false ; + + //find extension + const char *extn = & ( filename [ strlen(filename) ] ) ; + while ( extn != filename && *extn != '/' && *extn != '.' ) + extn-- ; + + if ( *extn != '.' ) + { + ulSetError ( UL_WARNING, "ssgLoadTexture: Cannot determine file type for '%s'", filename ); + ssgLoadDummyTexture ( info ) ; + return false ; + } + + _ssgTextureFormat *f = formats ; + for ( int i=0; iloadfunc != NULL && + ulStrNEqual ( extn, f->extension, strlen(f->extension) ) ) + { + if ( f->loadfunc( filename, info ) ) + return true ; + + ssgLoadDummyTexture ( info ) ; /* fail */ + return false ; + } + } +#ifdef SSG_LOAD_SGI_SUPPORTED + char * fname_output = new char [ strlen(filename) + 4 ]; // +4 as reserve for .rgb + if ( ssgConvertTexture( fname_output, filename) ) + if ( ssgLoadSGI ( fname_output, info ) ) + { delete [] fname_output; + return true; + } + delete [] fname_output; + +#else + ulSetError ( UL_WARNING, "ssgLoadTexture: Unrecognised file type '%s'", extn ) ; +#endif + + ssgLoadDummyTexture ( info ) ; + return false ; +} + + diff --git a/src/ssg/ssgLoadVRML.h b/src/ssg/ssgLoadVRML.h new file mode 100644 index 0000000..275dbcb --- /dev/null +++ b/src/ssg/ssgLoadVRML.h @@ -0,0 +1,150 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002, 2002 William Lachance, Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net +*/ + +class ssgListOfNodes : public ssgSimpleList +// list of POINTERs to ssgBase +// used for storing/querying DEF'd info +{ +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) { return NULL; }; // Fixme NIV14: 2do + ssgListOfNodes ( int init = 3 ) : ssgSimpleList ( sizeof(ssgBase*), init ) {} + class ssgBase *get ( unsigned int n ) { return *( (class ssgBase **) raw_get ( n ) ) ; } + void add ( class ssgBase *thing ) { raw_add ( (char *) &thing ) ; } ; + void replace( class ssgBase *thing, unsigned int n ) { raw_set( (char *) &thing, n); } + + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) {}; // Fixme NIV14: 2do +}; + + +class _nodeIndex +{ + private: + ssgListOfNodes *nodeList; + public: + _nodeIndex() + { + nodeList = new ssgListOfNodes(); + } + ~_nodeIndex() + { + for( int i=0; igetNum(); i++ ) + { + ssgBase *extractedThing = nodeList->get( i ); + if( extractedThing->getRef() == 0 ) + delete( extractedThing ); + } + } + + void insert( ssgBase *thing ) + { + // replace the node if a node with an identical tag already exists + for( int i=0; igetNum(); i++ ) + { + ssgBase *tempThing = nodeList->get( i ); + if( !strcmp( tempThing->getName(), thing->getName() ) ) + { + nodeList->replace( thing, i ); + ulSetError(UL_DEBUG, "Replaced element %i.", i); + return; + } + } + // otherwise add it to end of list + nodeList->add( thing ); + } + + ssgBase * extract( char *defName ) + { + for( int i=0; igetNum(); i++ ) + { + ssgBase *extractedThing = nodeList->get( i ); + if( !strcmp( extractedThing->getName(), defName ) ) + return extractedThing; + } + + return NULL; + } +}; + +// the current properties for a certain point in scene traversal +class _traversalState +{ + private: + ssgVertexArray *vertices; + ssgTexCoordArray *textureCoordinates; + ssgTransform *transform; + ssgTexture *texture; + bool textureCoordinatesArePerFaceAndVertex; + GLenum frontFace; + bool enableCullFace; + + public: + + bool getEnableCullFace() { return enableCullFace; } + void setEnableCullFace( bool newEnableCullFace ) { enableCullFace = newEnableCullFace; } + + GLenum getFrontFace( void ) { return frontFace; } + void setFrontFace( GLenum newFrontFace ) { frontFace = newFrontFace; } + + ssgTransform * getTransform( void ) { return transform; } + void setTransform( ssgTransform *newTransform ) { transform = newTransform; } + + ssgVertexArray * getVertices( void ) { return vertices; } + void setVertices( ssgVertexArray *newVertices ) { vertices = newVertices; } + + ssgTexCoordArray *getTextureCoordinates( void ) { return textureCoordinates; } + void setTextureCoordinates( ssgTexCoordArray *newTextureCoordinates ) { textureCoordinates = newTextureCoordinates; } + + ssgTexture * getTexture( void ) { return texture; } + void setTexture( ssgTexture *newTexture ) { texture = newTexture; } + + bool areTextureCoordinatesArePerFaceAndVertex( void ) { return textureCoordinatesArePerFaceAndVertex; } + + _traversalState *clone() { return new _traversalState(*this); } + _traversalState() { vertices = NULL; textureCoordinates = NULL; transform = NULL; texture = NULL; textureCoordinatesArePerFaceAndVertex = TRUE; enableCullFace = FALSE; } +}; + +// tags for functions which may actually modify the scene graph +struct _parseTag +{ + const char *token ; + bool (*func) ( ssgBranch *parentBranch, _traversalState *parentData, char *defName ) ; +} ; + +// the vrml1 common subset that is shared with inventor +bool vrml1_parseCoordinate3( ssgBranch *parentBranch, _traversalState *currentData, char *defName ); +bool vrml1_parseTextureCoordinate2( ssgBranch *parentBranch, _traversalState *currentData, char *defName ); +bool vrml1_parseShapeHints( ssgBranch *parentBranch, _traversalState *currentData, char *defName ); +bool vrml1_parseMatrixTransform( ssgBranch *parentBranch, _traversalState *currentData, char *defName ); +bool vrml1_parseScale( ssgBranch *parentBranch, _traversalState *currentData, char *defName ); +bool vrml1_parseRotation( ssgBranch *parentBranch, _traversalState *currentData, char *defName ); +bool vrml1_parseTranslation( ssgBranch *parentBranch, _traversalState *currentData, char *defName ); +bool vrml1_parseUseDirective( ssgBranch *parentBranch, _traversalState *currentData, char *useName, char *defName ); +bool vrml1_parseCoordIndex( ssgLoaderWriterMesh *loaderMesh, _traversalState *currentData ); +bool vrml1_parseTextureCoordIndex( ssgLoaderWriterMesh *loaderMesh, _traversalState *currentData ); +bool parseUnidentified(); + +void applyTransform( ssgTransform *currentTransform, _traversalState *currentData ); +void mergeTransformNodes( ssgTransform *newTransform, ssgTransform *oldTransform1, ssgTransform *oldTransform2 ); +bool parseVec( SGfloat *v, int vSize ); +ssgIndexArray * parseIndexArray( _traversalState *currentData ); + +extern _ssgParser vrmlParser; diff --git a/src/ssg/ssgLoadVRML1.cxx b/src/ssg/ssgLoadVRML1.cxx new file mode 100644 index 0000000..4f96f2a --- /dev/null +++ b/src/ssg/ssgLoadVRML1.cxx @@ -0,0 +1,932 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 William Lachance, Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net +*/ + +// ssgLoadVRML1: loads vrml1 files into the scenegraph +// Written by William Lachance (wlach@interlog.com) +// known bugs/limitations: +// - implicit texture mapping is not supported +// - explicit normal definitions not supported (they are calculated automatically) +// - only a very small subset of the inventor spec is supported +// - there is no support for primitives (cubes, spheres, cylinders, or cones) +// - no support for materials +// - no support for weblinks in vrml(well, this isn't much of a tragedy) :-) +// .. +// this loader borrows, to some extent, from the previous vrml file loader: +// - array based token identification +// - flipping the axises so that z is up + +#include "ssgLocal.h" +#include "ssgParser.h" +#include "ssgLoaderWriterStuff.h" + +#include "ssgLoadVRML.h" + +static _ssgParserSpec parser_spec = +{ + "\r\n\t, ", // delim_chars_skipable + 0, // delim_chars_non_skipable + NULL, // pre_processor + "{[", // open_brace_chars + "}]", // close_brace_chars + '"', // quote_char + '#', // comment_char + 0 // comment_string +}; + +_ssgParser vrmlParser; +static ssgLoaderOptions* currentOptions = NULL ; +static _nodeIndex *definedNodes = NULL; + +static bool vrml1_parseSeparator( ssgBranch *parentBranch, _traversalState *parentData, char *defName ); +static bool vrml1_parseSwitch( ssgBranch *parentBranch, _traversalState *parentData, char *defName ); +static bool vrml1_parseIndexedFaceSet( ssgBranch *parentBranch, _traversalState *currentData, char *defName ); +static bool vrml1_parseTexture2( ssgBranch *parentBranch, _traversalState *currentData, char *defName ); + +static _parseTag vrmlTags [] = +{ + { "Separator", vrml1_parseSeparator }, + { "Switch", vrml1_parseSwitch }, + { "IndexedFaceSet", vrml1_parseIndexedFaceSet }, + { "Coordinate3", vrml1_parseCoordinate3 }, + { "TextureCoordinate2", vrml1_parseTextureCoordinate2 }, + { "Texture2", vrml1_parseTexture2 }, + { "ShapeHints", vrml1_parseShapeHints }, + { "MatrixTransform", vrml1_parseMatrixTransform }, + { "Scale", vrml1_parseScale }, + { "Rotation", vrml1_parseRotation }, + { "Translation", vrml1_parseTranslation }, + { NULL, NULL }, +}; + +ssgEntity *ssgLoadVRML1( const char *fname, const ssgLoaderOptions* options ) +{ + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + currentOptions = ssgGetCurrentOptions () ; + + if ( !vrmlParser.openFile( fname, &parser_spec ) ) { + ulSetError ( UL_WARNING, "ssgLoadVRML1: Failed to open '%s' for reading", fname ) ; + return 0; + } + + definedNodes = new _nodeIndex(); + + // check for a valid header header + char *token; + if( !(token = vrmlParser.getRawLine()) ) + return 0; + if( strstr( token, "#VRML V1.0 ascii" ) == NULL ) + { + ulSetError ( UL_WARNING, "ssgLoadVRML1: valid vrml1 header not found" ); + return 0; + } + + // creating a root node.. (a transform that changes Zup with Yup) + ssgBranch *rootTransform = new ssgTransform(); + sgCoord *tmpCoord = new sgCoord(); + sgSetCoord( tmpCoord, 0.0f, 0.0f, 0.0f, 0.0f, 90.0f, 0.0f ); + ((ssgTransform *)rootTransform)->setTransform( tmpCoord ); + + vrmlParser.expectNextToken( "Separator" ); + + if( !vrml1_parseSeparator( (ssgBranch *)rootTransform, NULL, NULL ) ) + { + ulSetError ( UL_WARNING, "ssgLoadVRML: Failed to extract valid object(s) from %s", fname ) ; + delete( definedNodes ); + delete( rootTransform ); + return NULL ; + } + + vrmlParser.closeFile(); + delete( definedNodes ); + + return (ssgBranch *)rootTransform; +} + +static bool vrml1_parseSeparator( ssgBranch *parentBranch, _traversalState *parentData, char *defName ) +{ + char *childDefName = NULL; + + char *token; + + vrmlParser.expectNextToken( "{" ); + + // create a branch for this node + ssgBranch *currentBranch = new ssgBranch(); + + if( defName != NULL ) + { + currentBranch->setName( defName ); + definedNodes->insert( currentBranch ); + } + + _traversalState *currentData; + if( parentData == NULL ) + currentData = new _traversalState(); + else + currentData = parentData->clone(); + + token = vrmlParser.getNextToken( NULL ); + while( strcmp( token, "}" ) ) + { + if( !strcmp( token, "DEF" ) ) + { + token = vrmlParser.getNextToken( NULL ); + ulSetError(UL_DEBUG, "DEF: Found an object definition %s.", token); + childDefName = new char[50]; + strncpy( childDefName, token, 50); + } + else if( !strcmp( token, "USE" ) ) + { + token = vrmlParser.getNextToken( NULL ); + ulSetError(UL_DEBUG, "USE: Found a use directive %s.", token); + if( !vrml1_parseUseDirective( currentBranch, currentData, token, childDefName ) ) + { + delete( currentBranch ); + delete( currentData ); + if( childDefName != NULL ) + delete [] childDefName; + return FALSE; + } + } + else + { + int i=0; bool tokenFound = FALSE; + while( vrmlTags[i].token != NULL && !tokenFound ) + { + if( !strcmp( token, vrmlTags[i].token ) ) + { + if( !(vrmlTags[i].func( currentBranch, currentData, childDefName ) ) ) + { + delete( currentBranch ); + delete( currentData ); + if( childDefName != NULL ) + delete [] childDefName; + return FALSE; + } + + tokenFound = TRUE; + } + i++; + } + if( !tokenFound ) + parseUnidentified(); + } + token = vrmlParser.getNextToken( NULL ); + } + + parentBranch->addKid( currentBranch ); + + // delete the currentData structure (we may use its content, but not its form) + delete( currentData ); + + return TRUE; +} + +static bool vrml1_parseSwitch( ssgBranch *parentBranch, _traversalState *parentData, char *defName ) +// UNSUPPORTED BEHAVIOUR: does not do a check for a whichChild parameter. Assumes that a switch +// "hides" all of its children. +{ + char *childDefName = NULL; + + char *token; + + vrmlParser.expectNextToken( "{" ); + + // create a branch for this node + ssgBranch *currentBranch = new ssgSelector(); + ((ssgSelector *)currentBranch)->select( 0 ); // fixme: allow for children to be traversed + + + if( defName != NULL ) + { + currentBranch->setName( defName ); + definedNodes->insert( currentBranch ); + } + + _traversalState *currentData; + if( parentData == NULL ) + currentData = new _traversalState(); + else + currentData = parentData->clone(); + + token = vrmlParser.getNextToken( NULL ); + + while( strcmp( token, "}" ) ) + { + if( !strcmp( token, "DEF" ) ) + { + token = vrmlParser.getNextToken( NULL ); + ulSetError(UL_DEBUG, "DEF: Found an object definition %s.", token); + if( childDefName != NULL ) + delete [] childDefName; + childDefName = ulStrDup ( token ) ; + } + else if( !strcmp( token, "USE" ) ) + { + token = vrmlParser.getNextToken( NULL ); + ulSetError(UL_DEBUG, "USE: Found a use directive %s.", token); + if( !vrml1_parseUseDirective( currentBranch, currentData, token, childDefName ) ) + { + delete( currentBranch ); + delete( currentData ); + if( childDefName != NULL ) + delete [] childDefName; + return FALSE; + } + } + else + { + int i=0; bool tokenFound = FALSE; + while( vrmlTags[i].token != NULL && !tokenFound ) + { + if( !strcmp( token, vrmlTags[i].token ) ) + { + if( !(vrmlTags[i].func( currentBranch, currentData, childDefName ) ) ) + { + delete( currentBranch ); + delete( currentData ); + if( childDefName != NULL ) + delete [] childDefName; + return FALSE; + } + + tokenFound = TRUE; + } + i++; + } + if( !tokenFound ) + parseUnidentified(); + } + + token = vrmlParser.getNextToken( NULL ); + } + + parentBranch->addKid( currentBranch ); + + delete( currentData ); // delete the currentData structure (we may use its content, but not its form) + + return TRUE; +} + + +// parseVec: tries to parse a vec (of vSize), returns true if successful, false otherwise +bool parseVec( SGfloat *v, int vSize ) +{ + for( int i=0; iadd( index ); + else + return NULL; + + token = vrmlParser.peekAtNextToken( NULL ); + } + vrmlParser.expectNextToken( "-1" ); + + // we have to reverse vertex ordering if vertices are in clockwise order + if( currentData->getFrontFace() == GL_CW ) + { + // so return something else that goes in reverse order + ssgIndexArray *reversedIndexArray = new ssgIndexArray( indexArray->getNum() ); + for( int i=(indexArray->getNum()-1); i>=0; i-- ) + { + int newIndex = (int)*indexArray->get( i ); + reversedIndexArray->add( newIndex ); + } + delete( indexArray ); + return reversedIndexArray; + } + + return indexArray; +} + +// parseCoordinate3: parses a list of 3d coordinates, adds them to the current +// vertice array +bool vrml1_parseCoordinate3( ssgBranch *parentBranch, _traversalState *currentData, char *defName ) +{ + char *token; + int numVertices = 0; + + // Ok, now we can allocate a new vertex table + //ssgVertexArray *currentVertices = new ssgVertexArray(); + ssgVertexArray *currentVertices = new ssgVertexArray(); + if( defName != NULL ) + { + currentVertices->setName( defName ); + definedNodes->insert( currentVertices ); + } + + vrmlParser.expectNextToken("{"); + vrmlParser.expectNextToken("point"); + + // an array? most likely.. + token = vrmlParser.peekAtNextToken( NULL ); + if( !strcmp( token, "[" ) ) + { + vrmlParser.expectNextToken("["); + // begin parsing vertices + token = vrmlParser.peekAtNextToken( NULL ); + + while( strcmp( token, "]" ) ) + { + sgVec3 v; + if( ! parseVec( v, 3 ) ) + return FALSE; + numVertices++; + currentVertices->add( v ); + + token = vrmlParser.peekAtNextToken( NULL ); + } + vrmlParser.expectNextToken("]"); + } + + // otherwise it must be a singular value + else + { + sgVec3 v; + if( ! parseVec( v, 3 ) ) + return FALSE; + numVertices++; + currentVertices->add( v ); + } + + ulSetError(UL_DEBUG, "Level: %i. Found %i vertices here.", vrmlParser.level, numVertices); + + vrmlParser.expectNextToken("}"); + + currentData->setVertices( currentVertices ); + + return TRUE; +} + +bool vrml1_parseTextureCoordinate2( ssgBranch *parentBranch, _traversalState *currentData, char *defName ) +{ + char *token; + int numTextureCoordinates = 0; + + ssgTexCoordArray *currentTextureCoordinates = new ssgTexCoordArray(); + if( defName != NULL ) + { + currentTextureCoordinates->setName( defName ); + definedNodes->insert( currentTextureCoordinates ); + } + + vrmlParser.expectNextToken("{"); + vrmlParser.expectNextToken("point"); + + // an array? most likely.. + token = vrmlParser.peekAtNextToken( NULL ); + if( !strcmp( token, "[" ) ) + { + vrmlParser.expectNextToken("["); + // begin parsing TexCoords + token = vrmlParser.peekAtNextToken( NULL ); + + while( strcmp( token, "]" ) ) + { + sgVec2 v; + if( ! parseVec( v, 2 ) ) + return FALSE; + numTextureCoordinates++; + currentTextureCoordinates->add( v ); + + token = vrmlParser.peekAtNextToken( NULL ); + } + vrmlParser.expectNextToken("]"); + } + + // otherwise it must be a singular value + else + { + sgVec2 v; + if( ! parseVec( v, 2 ) ) + return FALSE; + numTextureCoordinates++; + currentTextureCoordinates->add( v ); + } + + ulSetError(UL_DEBUG, "Level: %i. Found %i TexCoords here.", vrmlParser.level, numTextureCoordinates); + + vrmlParser.expectNextToken("}"); + + currentData->setTextureCoordinates( currentTextureCoordinates ); + + return TRUE; +} + +static bool vrml1_parseIndexedFaceSet( ssgBranch *parentBranch, _traversalState *currentData, char *defName ) +{ + char *token; + bool texCoordIndexGiven = FALSE; + + ssgBranch *currentBranch = new ssgBranch(); + if( defName != NULL ) + { + currentBranch->setName( defName ); + definedNodes->insert( currentBranch ); + } + + ssgLoaderWriterMesh *loaderMesh = new ssgLoaderWriterMesh(); + loaderMesh->createFaces(); + loaderMesh->setVertices( currentData->getVertices() ); + if( currentData->getTexture() != NULL && currentData->getTextureCoordinates() != NULL ) + loaderMesh->createPerFaceAndVertexTextureCoordinates2(); + + vrmlParser.expectNextToken("{"); + + token = vrmlParser.peekAtNextToken( NULL ); + while( strcmp( token, "}" ) ) + { + if( !strcmp( token, "coordIndex" ) ) + { + vrmlParser.expectNextToken("coordIndex"); + if( !vrml1_parseCoordIndex( loaderMesh, currentData ) ) + { + delete( currentBranch ); + delete( loaderMesh ); + return FALSE; + } + + } + + else if( !strcmp( token, "textureCoordIndex" ) ) + { + texCoordIndexGiven = TRUE; + vrmlParser.expectNextToken("textureCoordIndex"); + if( !vrml1_parseTextureCoordIndex( loaderMesh, currentData ) ) + { + delete( currentBranch ); + delete( loaderMesh ); + return FALSE; + } + + } + else + token = vrmlParser.getNextToken( NULL ); + + token = vrmlParser.peekAtNextToken( NULL ); + } + + //ulSetError(UL_DEBUG, "Level: %i. Found %i faces here.", vrmlParser.level, numFaces); + + vrmlParser.expectNextToken( "}" ); + + // ------------------------------------------------------- + // add the face set to ssg + // ------------------------------------------------------- + + // kludge. We need a state for addToSSG: + ssgSimpleState * ss = new ssgSimpleState () ; // (0) ? + ss -> setMaterial ( GL_AMBIENT, 0.5, 0.5, 0.5, 1.0); + ss -> setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0) ; // 0.8, 0.8, 1.0, 1.0f + ss -> setMaterial ( GL_SPECULAR, 1.0, 1.0, 1.0, 1.0); + ss -> setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 1.0); + ss -> setShininess ( 20 ) ; // Fixme, NIV14: Is that correct? + + // ------------------------------------------------------- + // texturing stuff + // ------------------------------------------------------- + // todo: give an implicit mapping if texture coordinates are not given + // todo: add support for per-vertex texturing + if( currentData->getTexture() != NULL && currentData->getTextureCoordinates() != NULL && texCoordIndexGiven ) + { + ss -> setTexture ( currentData->getTexture() ); + ss -> enable( GL_TEXTURE_2D ); + } + else + ss -> disable( GL_TEXTURE_2D ); + + ss -> disable ( GL_COLOR_MATERIAL ) ; + //ss -> enable ( GL_COLOR_MATERIAL ) ; + //ss -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + + ss -> enable ( GL_LIGHTING ) ; + ss -> setShadeModel ( GL_SMOOTH ) ; + + ss ->disable(GL_ALPHA_TEST); //needed? + + ss -> disable ( GL_BLEND ) ; + + ss -> setOpaque () ; + + if( !currentData->getEnableCullFace() ) + ss->disable( GL_CULL_FACE ); + + if( !loaderMesh->checkMe() ) + { + delete( currentBranch ); + delete( loaderMesh ); + return FALSE; + } + + if( currentData->getTransform() != NULL ) + { + currentBranch->addKid( currentData->getTransform() ); // FIXME: in case we're reusing transforms, perhaps they should be reinstanced? (currently we don't allow transforms to be defed) + loaderMesh->addToSSG( ss, currentOptions, currentData->getTransform() ); + } + else + loaderMesh->addToSSG( ss, currentOptions, currentBranch ); + + parentBranch->addKid( currentBranch ); + + delete( loaderMesh ); + + return TRUE; +} + +static bool vrml1_parseTexture2( ssgBranch *parentBranch, _traversalState *currentData, char *defName ) +{ + char *token; + char *fileName = NULL; bool wrapU = FALSE, wrapV = FALSE; + + vrmlParser.expectNextToken("{"); + + token = vrmlParser.peekAtNextToken( NULL ); + while( strcmp( token, "}" ) ) + { + if( !strcmp( token, "filename") ) + { + vrmlParser.expectNextToken("filename"); + token = vrmlParser.getNextToken( NULL ); + fileName = new char[ strlen( token ) + 1]; + strcpy( fileName, token ); + } + else if( !strcmp( token, "wrapS") ) + { + vrmlParser.expectNextToken("wrapS"); + token = vrmlParser.getNextToken( NULL ); + if( !strcmp( token, "REPEAT") ) + wrapU = TRUE; + } + else if( !strcmp( token, "wrapT") ) + { + vrmlParser.expectNextToken("wrapT"); + token = vrmlParser.getNextToken( NULL ); + if( !strcmp( token, "REPEAT") ) + wrapV = TRUE; + } + else + token = vrmlParser.getNextToken( NULL ); + + token = vrmlParser.peekAtNextToken( NULL ); + } + + + if( fileName == NULL ) + return FALSE; + + //ssgTexture *currentTexture = new ssgTexture( fileName, wrapU, wrapV ); + ssgTexture *currentTexture = currentOptions -> createTexture ( fileName, wrapU, wrapV ); + currentData->setTexture( currentTexture ); + vrmlParser.expectNextToken("}"); + + delete [] fileName; + + return TRUE; +} + +bool vrml1_parseShapeHints( ssgBranch *parentBranch, _traversalState *currentData, char *defName ) +{ + char *token; + vrmlParser.expectNextToken("{"); + + token = vrmlParser.peekAtNextToken( NULL ); + while( strcmp( token, "}" ) ) + { + if( !strcmp( token, "vertexOrdering") ) + { + vrmlParser.expectNextToken("vertexOrdering"); + token = vrmlParser.getNextToken( NULL ); + if( !strcmp( token, "CLOCKWISE") ) + { + currentData->setEnableCullFace( TRUE ); + currentData->setFrontFace( GL_CW ); + } + else if( !strcmp( token, "COUNTERCLOCKWISE") ) + { + currentData->setEnableCullFace( TRUE ); + currentData->setFrontFace( GL_CCW ); + } + else if( !strcmp( token, "UNKNOWN_ORDERING") ) + currentData->setEnableCullFace( FALSE ); + else + { + ulSetError ( UL_WARNING, "ssgLoadVRML: invalid vertex ordering directive" ) ; + return FALSE; + } + + } + else + token = vrmlParser.getNextToken( NULL ); + + token = vrmlParser.peekAtNextToken( NULL ); + } + vrmlParser.expectNextToken("}"); + + return TRUE; +} + +bool vrml1_parseMatrixTransform( ssgBranch *parentBranch, _traversalState *currentData, char *defName ) +{ + ssgTransform *currentTransform = new ssgTransform(); + sgMat4 transformMat; + + vrmlParser.expectNextToken("{"); + vrmlParser.expectNextToken("matrix"); + for( unsigned int i=0; i<4; i++ ) + for( unsigned int j=0; j<4; j++ ) + { + if( !vrmlParser.getNextFloat( transformMat[i][j], NULL ) ) + { + ulSetError ( UL_WARNING, "ssgLoadVRML: Expected a float for a matrix, didn't get it." ) ; + return FALSE; + } + } + vrmlParser.expectNextToken("}"); + + currentTransform->setTransform( transformMat ); + + applyTransform( currentTransform, currentData ); + + //ulSetError(UL_DEBUG, "Found a Matrix Transform (%f, %f, %f %f), (%f, %f, %f %f), (%f, %f, %f %f), (%f, %f, %f %f)", xForm[0][0], xForm[1][0], xForm[2][0], xForm[3][0], + // xForm[0][1], xForm[1][1], xForm[2][1], xForm[3][1], + // xForm[0][2], xForm[1][2], xForm[2][2], xForm[3][2], + // xForm[0][3], xForm[1][3], xForm[2][3], xForm[3][3] ); + + return TRUE; +} + +bool vrml1_parseScale( ssgBranch *parentBranch, _traversalState *currentData, char *defName ) +{ + ssgTransform *currentTransform = new ssgTransform(); + sgVec3 scaleFactor; + + sgCoord moveFactor; sgZeroCoord( &moveFactor ); + + vrmlParser.expectNextToken("{"); + vrmlParser.expectNextToken("scaleFactor"); + if( !parseVec( scaleFactor, 3 ) ) + return FALSE; + vrmlParser.expectNextToken("}"); + + currentTransform->setTransform( &moveFactor, scaleFactor[0], scaleFactor[1], scaleFactor[2] ); + + applyTransform( currentTransform, currentData ); + + ulSetError(UL_DEBUG, "Found a scale transform: %f %f %f", scaleFactor[0], scaleFactor[1], scaleFactor[2] ); + + return TRUE; +} + +bool vrml1_parseRotation( ssgBranch *parentBranch, _traversalState *currentData, char *defName ) +{ + ssgTransform *currentTransform = new ssgTransform(); + sgVec3 axis; + SGfloat angle; + sgMat4 rotation; + + vrmlParser.expectNextToken("{"); + vrmlParser.expectNextToken("rotation"); + if( !parseVec( axis, 3 ) ) + return FALSE; + if( !vrmlParser.getNextFloat( angle, NULL ) ) + return FALSE; + vrmlParser.expectNextToken("}"); + + angle *= SG_RADIANS_TO_DEGREES; + + sgMakeRotMat4( rotation, angle, axis ) ; + currentTransform->setTransform( rotation ); + + applyTransform( currentTransform, currentData ); + + ulSetError(UL_DEBUG, "Found a rotation: %f %f %f %f", axis[0], axis[1], axis[2], angle ); + + return TRUE; +} + +bool vrml1_parseTranslation( ssgBranch *parentBranch, _traversalState *currentData, char *defName ) +{ + ssgTransform *currentTransform = new ssgTransform(); + sgVec3 transform; + + vrmlParser.expectNextToken("{"); + vrmlParser.expectNextToken("translation"); + if( !parseVec( transform, 3 ) ) + return FALSE; + vrmlParser.expectNextToken("}"); + + currentTransform->setTransform( transform ); + + applyTransform( currentTransform, currentData ); + + ulSetError(UL_DEBUG, "Found a translation: %f %f %f", transform[0], transform[1], transform[2] ); + + return TRUE; +} + + +bool vrml1_parseUseDirective( ssgBranch *parentBranch, _traversalState *currentData, char *useName, char *defName ) +{ + // find the node within the list of defined nodes + ssgBase *node = definedNodes->extract( useName ); + + if( node==NULL ) + return TRUE; + + if( node->isA( ssgTypeBranch() ) ) + { + ssgBranch *currentBranch = NULL; + if( currentData->getTransform() != NULL ) + { + currentBranch = currentData->getTransform(); + currentBranch->addKid( (ssgEntity *)node ); + } + else + currentBranch = (ssgBranch *)node; + + parentBranch->addKid( currentBranch ); + + return TRUE; + } + + return TRUE; +} + + +// parseUnidentified: A node that we either don't support or isn't part of the +// VRML/IV spec. Just skip it. +bool parseUnidentified() +{ + char *token; + + int startLevel = vrmlParser.level; + int currentLevel = startLevel + 1; + + vrmlParser.expectNextToken("{"); + + while( currentLevel != startLevel ) + { + token = vrmlParser.getNextToken( NULL ); + + if( !strcmp( token, "{" ) ) + currentLevel++; + else if( !strcmp( token, "}" ) ) + currentLevel--; + } + + return TRUE; +} + +void applyTransform( ssgTransform *currentTransform, _traversalState *currentData ) +{ + if( currentData->getTransform() == NULL ) + currentData->setTransform( currentTransform ); + else + { + ssgTransform *newTransform = new ssgTransform(); + mergeTransformNodes( newTransform, currentTransform, currentData->getTransform() ); + // this will have to be changed when we allow use declarations on transforms + delete( currentTransform ); + currentData->setTransform( newTransform ); + } +} + +bool vrml1_parseCoordIndex( ssgLoaderWriterMesh *loaderMesh, _traversalState *currentData ) +{ + char *token = vrmlParser.peekAtNextToken( NULL ); + int numFaces = 0; + + // an array? most likely.. + if( !strcmp( token, "[" ) ) + { + vrmlParser.expectNextToken("["); + token = vrmlParser.peekAtNextToken( NULL ); + while( strcmp( token, "]" ) ) + { + ssgIndexArray *currentFaceIndices = parseIndexArray( currentData ); + if( currentFaceIndices == NULL ) + { + ulSetError ( UL_WARNING, "ssgLoadVRML1: invalid index list" ) ; + return FALSE; + } + loaderMesh->addFace( (ssgIndexArray **) ¤tFaceIndices ); + //ulSetError(UL_DEBUG, "Level: %i. Added a face with %i vertices", vrmlParser.level, numVerticesInFace ); + numFaces++; + + token = vrmlParser.peekAtNextToken( NULL ); + } + vrmlParser.expectNextToken( "]" ); + } + + // otherwise a single point + else + { + ssgIndexArray *currentFaceIndices = parseIndexArray( currentData ); + if( currentFaceIndices == NULL ) + { + ulSetError ( UL_WARNING, "ssgLoadVRML1: invalid index list" ) ; + return FALSE; + } + loaderMesh->addFace( (ssgIndexArray **) ¤tFaceIndices ); + numFaces++; + + vrmlParser.expectNextToken( "-1" ); + } + + return TRUE; +} + +bool vrml1_parseTextureCoordIndex( ssgLoaderWriterMesh *loaderMesh, _traversalState *currentData ) +{ + char *token = vrmlParser.peekAtNextToken( NULL ); + + // an array? most likely.. + if( !strcmp( token, "[" ) ) + { + vrmlParser.expectNextToken("["); + token = vrmlParser.peekAtNextToken( NULL ); + while( strcmp( token, "]" ) ) + { + ssgIndexArray *currentTextureCoordinateIndices = parseIndexArray( currentData ); + if( currentTextureCoordinateIndices == NULL ) + return FALSE; + ssgTexCoordArray *currentPerFaceAndVertexTextureCoordinateList = new ssgTexCoordArray( currentTextureCoordinateIndices->getNum() ); + for( int i=0; igetNum(); i++ ) + currentPerFaceAndVertexTextureCoordinateList->add( (currentData->getTextureCoordinates())->get( (unsigned int)*currentTextureCoordinateIndices->get( i ) ) ); + loaderMesh->addPerFaceAndVertexTextureCoordinate2( (ssgTexCoordArray **) ¤tPerFaceAndVertexTextureCoordinateList ); + + delete( currentTextureCoordinateIndices ); + //ulSetError(UL_DEBUG, "Level: %i. Added a face with %i vertices", vrmlParser.level, numVerticesInFace ); + + token = vrmlParser.peekAtNextToken( NULL ); + } + vrmlParser.expectNextToken( "]" ); + } + // otherwise a single point + else + { + ssgIndexArray *currentTextureCoordinateIndices = parseIndexArray( currentData ); + if( currentTextureCoordinateIndices == NULL ) + return FALSE; + ssgTexCoordArray *currentPerFaceAndVertexTextureCoordinateList = new ssgTexCoordArray( currentTextureCoordinateIndices->getNum() ); + for( int i=0; igetNum(); i++ ) + currentPerFaceAndVertexTextureCoordinateList->add( (currentData->getTextureCoordinates())->get( (unsigned int)*currentTextureCoordinateIndices->get( i ) ) ); + loaderMesh->addPerFaceAndVertexTextureCoordinate2( (ssgTexCoordArray **) ¤tPerFaceAndVertexTextureCoordinateList ); + + delete( currentTextureCoordinateIndices ); + //ulSetError(UL_DEBUG, "Level: %i. Added a face with %i vertices", vrmlParser.level, numVerticesInFace ); + } + + return TRUE; +} + + +void mergeTransformNodes( ssgTransform *newTransform, ssgTransform *oldTransform1, ssgTransform *oldTransform2 ) +{ + sgMat4 oldTransformMat1; + sgMat4 oldTransformMat2; + sgMat4 newTransformMat; + + oldTransform1->getTransform( oldTransformMat1 ); + oldTransform2->getTransform( oldTransformMat2 ); + sgMultMat4( newTransformMat, oldTransformMat1, oldTransformMat2 ) ; + newTransform->setTransform( newTransformMat ); +} diff --git a/src/ssg/ssgLoadX.cxx b/src/ssg/ssgLoadX.cxx new file mode 100644 index 0000000..3df5ea1 --- /dev/null +++ b/src/ssg/ssgLoadX.cxx @@ -0,0 +1,757 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadX.cxx 2172 2012-08-14 17:56:51Z wolfram_kuss $ +*/ + +// +// .X loader for SSG/PLIB +// .X is the 3D file format for Micro$ofts directX. +// Written by Wolfram Kuss (Wolfram.Kuss@t-online.de) in Oct/Nov of 2000 +// +#include "ssgLocal.h" +#include "ssgLoaderWriterStuff.h" +#include "ssgParser.h" + +#define u32 unsigned int + +// These functions return TRUE on success +typedef int HandlerFunctionType(const char *sName, const char *firstToken); + + +static char *globEmpty=""; + +static ssgBranch *curr_branch_; + +struct EntityType +{ + const char * sName; + HandlerFunctionType *HandleEntity; + int bMayBeIgnored; +} ; + + + +static /* const */ ssgLoaderOptions* current_options = NULL ; + +static _ssgParserSpec parser_spec = +{ + "\r\n\t ", // delim_chars_skipable + ",;", // delim_chars_non_skipable + NULL, // pre_processor + "{", // open_brace_chars + "}", // close_brace_chars + '"', // quote_char + '#', // comment_char + "//" // comment_string +} ; + + +static _ssgParser parser; +static ssgBranch* top_branch; + +static int Ascii2Int(int &retVal, const char *token, const char* name ) +// returns TRUE on success +{ + char *endptr; + retVal = int(strtol( token, &endptr, 10)); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { parser.error("The field %s should contain an integer number but contains %s",name, token) ; + return FALSE; + } +} + +static int Ascii2UInt(unsigned int &retVal, const char *token, const char* name ) +// returns TRUE on success +{ + char *endptr; + retVal = (unsigned int)(strtol( token, &endptr, 10)); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { parser.error("The field %s should contain an integer number but contains %s",name, token) ; + return FALSE; + } +} + +static int Ascii2Float(SGfloat &retVal, const char *token, const char* name ) +// returns TRUE on success +{ + char *endptr; + retVal = SGfloat(strtod( token, &endptr)); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { parser.error("The field %s should contain an integer number but contains %s",name, token) ; + return FALSE; + } +} + +static int HandleHeader(const char * /* sName */, const char *firstToken) +{ + //parser.expectNextToken("{"); + int Dummy; + if (! Ascii2Int(Dummy, firstToken, "Header.major")) + return FALSE; + + parser.expectNextToken(";"); + if (!parser.getNextInt(Dummy, "Header.minor")) + return FALSE; + parser.expectNextToken(";"); + if (!parser.getNextInt(Dummy, "Header.flags")) + return FALSE; + parser.expectNextToken(";"); + parser.expectNextToken("}"); + return TRUE; +} + +static void IgnoreEntity(int startLevel) +// startLevel should be 0 when you are "in front of the {" (normally) +// or 1 when you have already parsed the "{" +{ + int Level = startLevel; + char *token; + + while ( TRUE) + { token = parser.getNextToken(0); + if ( parser.eof ) + { parser.error("unexpected end of file\n"); + return ; //FALSE; + } + + assert(token!=NULL); + if ( ulStrEqual (token,"{") ) + Level++; + else if ( ulStrEqual (token,"}") ) + { assert(Level>0); // Fixme, NIV14: Handle this gracefully. + if (Level==1) + return; // found THE closing brace of entitiy + Level--; // Found A closing brace + } + } +} + +static int HandleMesh(const char *sName, const char *firstToken); +static int HandleMeshMaterialList(const char *sName, const char *firstToken); +static int HandleTextureCoords(const char *sName, const char *firstToken); +static int HandleMaterial(const char *sName, const char *firstToken); +static int HandleTextureFileName(const char *sName, const char *firstToken); + + +static EntityType aEntities[] = +{ + { "Header", HandleHeader, FALSE}, + { "Vector", NULL, FALSE}, + { "Coords2d", NULL, FALSE}, + { "Quaternion", NULL, FALSE}, + { "Matrix4x4", NULL, FALSE}, + { "ColorRGBA", NULL, FALSE}, + { "ColorRGB", NULL, FALSE}, + { "Indexed Color", NULL, FALSE}, + { "Boolean", NULL, FALSE}, + { "Boolean2d", NULL, FALSE}, + { "Material", HandleMaterial, FALSE}, + { "TextureFilename", HandleTextureFileName, FALSE}, + { "MeshFace", NULL, FALSE}, + { "MeshFaceWraps", NULL, FALSE}, + { "MeshTextureCoords", HandleTextureCoords, FALSE}, + { "MeshNormals", NULL, TRUE}, + { "MeshVertexColors", NULL, FALSE}, + { "MeshMaterialList", HandleMeshMaterialList, FALSE}, + { "Mesh", HandleMesh, FALSE}, + { "FrameTransformMatrix", NULL, FALSE}, + { "Frame", NULL, FALSE}, + { "FloatKeys", NULL, FALSE}, + { "TimedFloatKeys", NULL, FALSE}, + { "AnimationKey", NULL, FALSE}, + { "AnimationOptions", NULL, FALSE}, + { "Animation", NULL, FALSE}, + { "AnimationSet", NULL, FALSE}, + { "template", NULL, TRUE}, + { NULL, NULL, FALSE} +}; + + +static int ParseEntity(char *token) +// called recursively +{ int i=0; + + while(aEntities[i].sName!=NULL) + { if (ulStrEqual (token,aEntities[i].sName)) + { if (aEntities[i].HandleEntity) + { char *sNextToken, *sName=globEmpty; + sNextToken=parser.getNextToken(0); + if ( parser.eof ) + { parser.error("unexpected end of file\n"); + return FALSE; + } + // if entity is named, read the name. skip "{": + sName = NULL; + if (0 != strcmp(sNextToken, "{")) + { sName = new char[ strlen(sNextToken) + 1 ]; + assert ( sName ); + strcpy(sName, sNextToken); + sNextToken = parser.getNextToken(0); + if (0 != strcmp(sNextToken, "{")) + parser.error("\"{\" expected\n"); + } + sNextToken = parser.getNextToken(0); + + if(sNextToken[0] == '<') // UUID + sNextToken = parser.getNextToken(0); + if ( parser.eof ) + { parser.error("unexpected end of file\n"); + return FALSE; + } + + if (!aEntities[i].HandleEntity(sName, sNextToken)) + return FALSE; + if ( sName ) + delete [] sName; + } + else + if (aEntities[i].bMayBeIgnored) + IgnoreEntity ( 0 ); + else + { + parser.error("I am sorry, but Entity-type '%s' is not yet implemented.", aEntities[i].sName); + return FALSE ; + } + + break; + } + i++; + } + if (aEntities[i].sName==NULL) + { + parser.error("unexpected token %s", token); + return FALSE ; + } + return TRUE; +} + + + +#define MAX_NO_VERTICES_PER_FACE 1000 + +static class ssgLoaderWriterMesh currentMesh; + +static ssgSimpleState *currentState; +extern sgVec4 currentDiffuse; + +static int HandleTextureFileName(const char * /*sName*/, const char *firstToken) +{/* + TextureFilename { + "../image/box_top.gif"; + } #TextureFilename + */ + char *filename_ptr, *filename = new char [ strlen(firstToken)+1 ] ; + assert(filename!=NULL); + strcpy ( filename, firstToken ) ; + filename_ptr = filename ; + + if ( filename_ptr[0] == '"' ) + filename_ptr++; + if (filename_ptr[strlen(filename_ptr)-1] == '"') + filename_ptr[strlen(filename_ptr)-1] = 0; + currentState -> setTexture( current_options -> createTexture( filename_ptr ) ); + currentState -> enable( GL_TEXTURE_2D ); + + + parser.expectNextToken(";"); + parser.expectNextToken("}"); + delete [] filename; + return TRUE; +} + +static class ssgSimpleStateList *globalMaterialList; +static int HandleMaterial(const char * sName, const char *firstToken) +// return TRUE on success +{ SGfloat power; + int bFoundTextureFileName = FALSE; + sgVec4 specularColour, EmissiveColour; + + // read body + if (! Ascii2Float(currentDiffuse[0], firstToken, "Facecolour R")) + return FALSE; + + parser.expectNextToken(";"); + if (!parser.getNextFloat(currentDiffuse[1], "Facecolour G")) return FALSE; + parser.expectNextToken(";"); + if (!parser.getNextFloat(currentDiffuse[2], "Facecolour B")) return FALSE; + parser.expectNextToken(";"); + if (!parser.getNextFloat(currentDiffuse[3], "Facecolour A")) return FALSE; + parser.expectNextToken(";"); + parser.expectNextToken(";"); + if (!parser.getNextFloat(power, "power")) return FALSE; + parser.expectNextToken(";"); + if (!parser.getNextFloat(specularColour[0], "Specular R")) return FALSE; + parser.expectNextToken(";"); + if (!parser.getNextFloat(specularColour[1], "Specular G")) return FALSE; + parser.expectNextToken(";"); + if (!parser.getNextFloat(specularColour[2], "Specular B")) return FALSE; + specularColour[3] = 0.0; + parser.expectNextToken(";"); + parser.expectNextToken(";"); + if (!parser.getNextFloat(EmissiveColour[0], "Emissive R")) return FALSE; + parser.expectNextToken(";"); + if (!parser.getNextFloat(EmissiveColour[1], "Emissive G")) return FALSE; + parser.expectNextToken(";"); + if (!parser.getNextFloat(EmissiveColour[2], "Emissive B")) return FALSE; + EmissiveColour[3] = 0.0; + parser.expectNextToken(";"); + parser.expectNextToken(";"); + + // create SimpleState + + currentState = new ssgSimpleState () ; + +// currentState -> setMaterial ( GL_AMBIENT, mat -> amb ) ; + currentState -> setMaterial ( GL_DIFFUSE, currentDiffuse) ; + currentState -> setMaterial ( GL_SPECULAR, specularColour) ; + currentState -> setMaterial ( GL_SPECULAR, specularColour[0], + specularColour[1], specularColour[2], currentDiffuse[3] ) ; + currentState -> setMaterial ( GL_EMISSION, EmissiveColour[0], + EmissiveColour[1], EmissiveColour[2], currentDiffuse[3] ) ; + + currentState -> setShininess ( power ) ; // Fixme, NIV14: Is that correct? + + currentState -> enable ( GL_COLOR_MATERIAL ) ; + currentState -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + + currentState -> enable ( GL_LIGHTING ) ; + currentState -> setShadeModel ( GL_SMOOTH ) ; + + if ( currentDiffuse[3] > 0.0f ) + { + currentState -> disable ( GL_ALPHA_TEST ) ; + currentState -> enable ( GL_BLEND ) ; + currentState -> setTranslucent () ; + } + else + { + currentState -> disable ( GL_BLEND ) ; + currentState -> setOpaque () ; + } + currentState -> disable( GL_TEXTURE_2D ); + + currentState -> setName ( sName ) ; + + while(TRUE) + { char *nextToken =parser.getNextToken(0); + if (0==strcmp("}", nextToken)) + { + + /*if(currentMesh.theMaterialsExists()) + currentMesh.addMaterial( ¤tState ); + else*/ + { + if(!globalMaterialList) + globalMaterialList = new ssgSimpleStateList(3); + + globalMaterialList->add(¤tState); + } + return TRUE; // Material is finished. success + } + + if (! ulStrEqual ( "TextureFilename", nextToken) ) + { parser.error("TextureFilename expected!\n"); + return FALSE; + } + if ( bFoundTextureFileName ) + { parser.error("Only one TextureFileName per Material please!\n"); + return FALSE; + } + if (!ParseEntity(nextToken)) // read "TextureFileName" + return FALSE; + bFoundTextureFileName = TRUE; + } + return TRUE; //lint !e527 +} + +static int HandleTextureCoords(const char * /* sName */, const char *firstToken) +{ + u32 nNoOfVertices, i; + + + if (! Ascii2UInt(nNoOfVertices, firstToken, "nNoOfVertices")) + return FALSE; + + if ( nNoOfVertices != currentMesh.getNumVertices()) + { parser.error("No of vertices of mesh (%d) and no " + "of texture coordinates (%d) do not match!\n" + "Therefore the texture coordinates are ignored!", + ( int ) currentMesh.getNumVertices(), ( int ) nNoOfVertices ); + IgnoreEntity ( 1 ); // ignores TC. + return FALSE; + } + currentMesh.createPerVertexTextureCoordinates2( nNoOfVertices ) ; + + parser.expectNextToken(";"); + for(i=0;i currentMesh.getNumFaces()) + { parser.error("No of face indexes of materiallist (%d) is greater than then no " + "of faces (%d)!\n" + "Therefore the material list is ignored!", + ( int ) nFaceIndexes, ( int ) currentMesh.getNumFaces()); + IgnoreEntity ( 1 ); // ignores TC. + return TRUE; // go on parsing + } + if ( nFaceIndexes > currentMesh.getNumFaces()) + parser.message("Informational: No of face indexes of materiallist (%d) is less than then no " + "of faces (%d)\n" , + ( int ) nFaceIndexes, ( int ) currentMesh.getNumFaces()); + for ( i=0 ; igetNum(); i++) + { + currentMesh.addMaterial(globalMaterialList->get(i)); + } + return TRUE; // Mesh is finished. success + } + if(ulStrEqual ("{", nextToken) ) + { // reference to global material + nextToken =parser.getNextToken(0); // name of material + parser.expectNextToken("}"); + // search for "name" in global list + if(globalMaterialList == NULL) + { + parser.error("No global materials defined, but used!\n"); + return FALSE; + } + for(int i=0; igetNum(); i++) + { + ssgSimpleState * ss = *(globalMaterialList->get(i)); + if(ulStrEqual(nextToken, ss->getName())) + break; + } + } + else + { + if ( !ulStrEqual ("Material", nextToken) ) + { parser.error("Material expected!\n"); + return FALSE; + } + if ( nMaterialsRead >= nMaterials ) + { parser.error("Too many Materials!\n"); + return FALSE; + } + if (!ParseEntity(nextToken)) // read "Material" + return FALSE; + } + nMaterialsRead++; + } + return TRUE; //lint !e527 +} + + +static int HandleMesh(const char * sName, const char *firstToken) +{ u32 i, j, nNoOfVertices, nNoOfVerticesForThisFace, nNoOfFaces; + int iVertex, aiVertices[MAX_NO_VERTICES_PER_FACE]; + + //char *sMeshName = parser.getNextToken("Mesh name"); + //parser.expectNextToken("{"); + if (! Ascii2UInt(nNoOfVertices, firstToken, "nNoOfVertices")) + return FALSE; + + //parser.getNextInt("number of vertices"); + + currentMesh.reInit (); + currentMesh.setName( sName ); + currentMesh.createVertices( nNoOfVertices ); + + parser.expectNextToken(";"); + for(i=0;isetOpaque(); + currentState->disable(GL_BLEND); + currentState->disable(GL_ALPHA_TEST); + currentState->disable(GL_TEXTURE_2D); + currentState->enable(GL_COLOR_MATERIAL); + currentState->enable(GL_LIGHTING); + currentState->setShadeModel(GL_SMOOTH); + currentState->setMaterial(GL_AMBIENT , 0.7f, 0.7f, 0.7f, 1.0f); + currentState->setMaterial(GL_DIFFUSE , 0.7f, 0.7f, 0.7f, 1.0f); + currentState->setMaterial(GL_SPECULAR, 1.0f, 1.0f, 1.0f, 1.0f); + currentState->setMaterial(GL_EMISSION, 0.0f, 0.0f, 0.0f, 1.0f); + currentState->setShininess(50); +/* + currentState -> setMaterial ( GL_AMBIENT, 0.5, 0.5, 0.5); + currentState -> setMaterial ( GL_DIFFUSE, 0.7, 0.7, 0.7); // light grey + currentState -> setMaterial ( GL_SPECULAR, 1.0, 1.0, 1.0); + currentState -> setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0); + + currentState -> setShininess ( 3 ) ; + + //currentState -> enable ( GL_COLOR_MATERIAL ) ; + //currentState -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ; + + currentState -> enable ( GL_LIGHTING ) ; + currentState -> setShadeModel ( GL_SMOOTH ) ; + + currentState -> disable ( GL_BLEND ) ; + currentState -> setOpaque () ; + currentState -> disable( GL_TEXTURE_2D ); + */ + } + + currentMesh.addToSSG( + currentState // Pfusch, kludge. NIV135 + , + current_options, + curr_branch_); + return TRUE; +} + +inline int TwoCharsToInt(char char1, char char2) +{ + return ((int)(char1-'0'))*256+char2-'0'; +} + +static int HeaderIsValid(char *firstToken) +{ // xof 0302txt 0064 + if (!ulStrEqual (firstToken,"xof")) + { + parser.error("not X format, invalid Header"); + return FALSE ; + } + char* token = parser.getNextToken("2nd Header field"); + if (strlen(token)!=7) + { + parser.error("not X format, invalid Header"); + return FALSE ; + } + char *sp=&(token[4]); + if (!ulStrEqual (sp,"txt")) + { + if (!ulStrEqual (sp,"bin")) + parser.error("not X format, invalid Header"); + else + parser.error("Binary X format files are not supported. If you have access to Windows, " + "please use Microsofts conversion-utility convx from the directX-SDK " + "to convert to ascii."); + return FALSE ; + } + if (strncmp(token, "0302", 4)) + parser.message("This loader is written for X-file-format version 3.2.\n" + "AFAIK this is the only documented version.\n" + "Your file has version %d.%d\n" + "Use the file at your own risk\n", + TwoCharsToInt(token[0], token[1]), + TwoCharsToInt(token[2], token[3])); + token = parser.getNextToken("3rd Header field"); + if (!ulStrEqual(token,"0032") && !ulStrEqual (token,"0064")) + { + parser.error("not X format, invalid Header"); + return FALSE ; + } + return TRUE; +} + +static int parse() +{ + int firsttime = TRUE; + char* token; + //int startLevel = parser.level; + token = parser.getNextToken(0); + while (! parser.eof ) + { + if (firsttime) + { + if(!HeaderIsValid(token)) + return FALSE; + firsttime = FALSE; + } + else + { if (!ParseEntity(token)) + return FALSE; + } + token = parser.getNextToken(0); + } + return TRUE ; +} + + +ssgEntity *ssgLoadX ( const char *fname, const ssgLoaderOptions* options ) +{ + ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ; + current_options = ssgGetCurrentOptions () ; + + currentState = NULL; + globalMaterialList = NULL; + top_branch = new ssgBranch ; + curr_branch_ = top_branch; + if ( !parser.openFile( fname, &parser_spec )) + { + delete top_branch ; + return 0; + } + if ( !parse() ) + { + delete top_branch ; + top_branch = 0 ; + } +// parse_free(); + parser.closeFile(); + + delete globalMaterialList; + return top_branch ; +} diff --git a/src/ssg/ssgLoadXPlaneObj.cxx b/src/ssg/ssgLoadXPlaneObj.cxx new file mode 100644 index 0000000..e327d81 --- /dev/null +++ b/src/ssg/ssgLoadXPlaneObj.cxx @@ -0,0 +1,463 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoadXPlaneObj.cxx 1728 2002-11-09 21:38:28Z sjbaker $ +*/ + +/* + * XPlane object loader for PLIB. + * Written by Bernie Bright , Sept 2002. + * + * KNOWN ISSUES + * + * Only version 1 objects are handled. + * + * The .obj XPlane custom object file extension clashes with Wavefront objects. + * For the moment, XPlane objects must be renamed with a .xpl extension. + * + * Point objects are not handled. + */ + +#include +#include + +#include "ssgLocal.h" + +/** + * XPlane .obj loader. + */ +class ObjLoader +{ +public: + ObjLoader( const ssgLoaderOptions* options ); + + ~ObjLoader(); + + ssgEntity* load( const char* fname ); + +private: + ssgState* get_state( const char* tfname ); + char* fgets( char* s, int size, FILE* fp ); + char* getline( char* line, size_t n, FILE* fp ); + char* getTextureName( const char* p, char* tname, size_t n ); + const char* file_extension( const char* fname ); + +private: + ssgLoaderOptions* options; + ssgBranch* root; +}; + +ObjLoader::ObjLoader( const ssgLoaderOptions* options_ ) + : options(0) + , root(0) +{ + ssgSetCurrentOptions( const_cast(options_) ); + this->options = ssgGetCurrentOptions(); +} + +ObjLoader::~ObjLoader() +{ +} + +ssgState* +ObjLoader::get_state( const char* tfname ) +{ + if (tfname != 0) + { + ssgState* st = options->createState( const_cast(tfname) ); + if (st != 0) + return st; + } + + ssgSimpleState* st = new ssgSimpleState; + st->setName( tfname ); + st->setMaterial( GL_SPECULAR, 0.0f, 0.0f, 0.0f ); + st->setMaterial( GL_EMISSION, 0.0f, 0.0f, 0.0f ); + st->setMaterial( GL_AMBIENT, 0.0f, 0.0f, 0.0f ); + st->setMaterial( GL_DIFFUSE, 0.0f, 0.0f, 0.0f ); + st->enable( GL_LIGHTING ); + st->setShadeModel( GL_SMOOTH ); + + bool has_alpha = false; + if (tfname != 0) + { + ssgTexture* tex = options->createTexture( const_cast(tfname) ); + has_alpha = tex->hasAlpha(); + st->setTexture(tex); + st->enable( GL_TEXTURE_2D ); + } + else + { + st->disable( GL_TEXTURE_2D ); + } + + if (has_alpha) + { + st->disable( GL_ALPHA_TEST ); + st->enable( GL_BLEND ); + st->setTranslucent(); + } + else + { + st->disable( GL_ALPHA_TEST ); + st->disable( GL_BLEND ); + st->setOpaque(); + } + + return st; +} + +/** + * XPlane object files have either IBM (\r\n) or Apple (\r) line endings. + * Handle both here. + */ +char* +ObjLoader::fgets( char* s, int size, FILE* fp ) +{ + char* p = s; + int n = 0; + int c = 0; + + for (--size; n < size; ++n) + { + c = getc(fp); + if (c == EOF) + return 0; + + if (c == '\r') + break; + *p++ = c; + } + + *p = 0; + + c = getc(fp); + if (c != '\n') + ungetc( c, fp ); + + return s; +} + +/** + * Read the next non-blank line. + * Returns pointer to first non-whitespace character or NULL on error or EOF. + */ +char* +ObjLoader::getline( char* line, size_t n, FILE* fp ) +{ + for (;;) + { + char* p = fgets( line, n, fp ); + if (p == 0) + return 0; + + // Skip leading whitespace. + while (*p != 0 && isspace(*p)) + ++p; + + if (*p != 0) + return p; + } +} + +/** + * + */ +char* +ObjLoader::getTextureName( const char* p, char* buf, size_t bufsize ) +{ + if (p == 0 || buf == 0) + return 0; + + while (*p != 0 && isspace(*p)) + ++p; + + size_t n = 0; + char* bp = buf; + for ( ; *p != 0 && n < bufsize && !isspace(*p); ++n, ++bp, ++p) + { + // Replace ':' path separator with '/'. + *bp = *p == ':' ? '/' : *p; + } + + if (n < bufsize) + *bp = 0; + + return const_cast(p); +} + +const char* +ObjLoader::file_extension( const char *fname ) +{ + const char* p = fname + strlen(fname); + + while (p != fname && *p != '/' && *p != '.' ) + --p; + + return p; +} + +ssgEntity* +ObjLoader::load( const char* fname ) +{ + char mname[1024]; + options->makeModelPath( mname, fname ); + + FILE* fp = fopen( fname, "r" ); + if (fp == 0) + { + ulSetError( UL_WARNING, + "ssgLoadXPlaneObj: Failed to open '%s' for reading.", + fname ); + return 0; + } + + char line[ 1024 ]; + + // Read obj header. + char* p = getline( line, sizeof(line), fp ); + if (p == 0) + { + ulSetError( UL_WARNING, "ssgLoadXPlaneObj: expected header." ); + fclose(fp); + return 0; + } + + if (*p != 'I' && *p != 'A') + { + ulSetError( UL_WARNING, + "ssgLoadXPlaneObj: invalid header, expected 'I' or 'A'" ); + fclose(fp); + return 0; + } + + p = getline( line, sizeof(line), fp ); + if (p == 0) + { + ulSetError( UL_WARNING, + "ssgLoadXPlaneObj: unexpected EOF while reading header." ); + fclose(fp); + return 0; + } + + root = new ssgTransform(); + root->setName( fname ); + + if (*p == '2') + { + // Version 2 obj file. + ulSetError( UL_WARNING, + "ssgLoadXPlaneObj: Version 2 not yet implemented" ); + + fclose( fp ); + delete root; + return 0; + + // TODO: implement V2. + } + else + { + // Version 1 obj file. + + // Version number is optional. + if (*p == '1') + { + // get TextureDef + p = getline( line, sizeof(line), fp ); + if (p == 0) + { + ulSetError( UL_WARNING, + "ssgLoadXPlaneObj: unexpected EOF " + "while reading data." ); + fclose(fp); + return 0; + } + } + + int type = 0; + char* endp; + do + { + type = strtol( p, &endp, 10 ); + switch (type) + { + case 4: + { + // Get texture filename. + // Allow room for extension and terminator. + char tname[ 251 + 4 + 1 ]; + endp = getTextureName( endp, tname, 251 ); + if (endp == 0) + { + ulSetError( UL_WARNING, + "ssgLoadXPlaneObj: Error reading TextureDef" ); + delete root; + fclose( fp ); + return 0; + } + + strcat( tname, ".bmp" ); + + // TODO: check for comment following texture name. + + sgVec3* vc = new sgVec3[4]; + sgVec2* tc = new sgVec2[4]; + sgVec4* cc = new sgVec4[1]; + + for (int i = 0; i < 4; ++i) + { + p = getline( line, sizeof(line), fp ); + // Read vertices, swapping y and z. + sscanf( p, "%f%f%f", &vc[i][0], &vc[i][2], &vc[i][1] ); + } + + sgSetVec2( tc[0], 1.0f, 1.0f ); + sgSetVec2( tc[1], 1.0f, 0.0f ); + sgSetVec2( tc[2], 0.0f, 0.0f ); + sgSetVec2( tc[3], 0.0f, 1.0f ); + + sgSetVec4( cc[0], 1.0f, 1.0f, 1.0f, 1.0f ); + + ssgVertexArray* vl = new ssgVertexArray( 4, vc ); + ssgTexCoordArray* tl = new ssgTexCoordArray( 4, tc ); + ssgNormalArray* nl = new ssgNormalArray(); + ssgColourArray* cl = new ssgColourArray( 1, cc ); + + ssgVtxTable* vtab = new ssgVtxTable( GL_POLYGON, + vl, nl, tl, cl ); + vtab->setState( get_state( tname ) ); + root->addKid( vtab ); + } + break; + + case 3: + { + // Get texture filename. + // Allow room for extension and terminator. + char tname[ 251 + 4 + 1 ]; + endp = getTextureName( endp, tname, 251 ); + strcat( tname, ".bmp" ); + + sgVec3* vc = new sgVec3[3]; + sgVec2* tc = new sgVec2[3]; + sgVec4* cc = new sgVec4[1]; + + for (int i = 0; i < 3; ++i) + { + p = getline( line, sizeof(line), fp ); + // Read vertices, swapping y and z. + sscanf( p, "%f%f%f", &vc[i][0], &vc[i][2], &vc[i][1] ); + } + + sgSetVec2( tc[0], 1.0f, 1.0f ); + sgSetVec2( tc[1], 1.0f, 0.0f ); + sgSetVec2( tc[2], 0.0f, 0.0f ); + + sgSetVec4( cc[0], 1.0f, 1.0f, 1.0f, 1.0f ); + + ssgVertexArray* vl = new ssgVertexArray( 3, vc ); + ssgTexCoordArray* tl = new ssgTexCoordArray( 3, tc ); + ssgNormalArray* nl = new ssgNormalArray(); + ssgColourArray* cl = new ssgColourArray( 1, cc ); + + ssgVtxTable* vtab = new ssgVtxTable( GL_POLYGON, + vl, nl, tl, cl ); + vtab->setState( get_state( tname ) ); + root->addKid( vtab ); + } + break; + + case 2: + { + float r, g, b; + sscanf( endp, "%f%f%f", &r, &g, &b ); + + sgVec3* vc = new sgVec3[2]; + sgVec4* cc = new sgVec4[1]; + for (int i = 0; i < 2; ++i) + { + p = getline( line, sizeof(line), fp ); + // Read vertices, swapping y and z. + sscanf( p, "%f%f%f", &vc[i][0], &vc[i][2], &vc[i][1] ); + } + + // Scale rgb values to range 0..1 + sgSetVec4( cc[0], r/10.f, g/10.f, b/10.f, 1.0f ); + + ssgVertexArray* vl = new ssgVertexArray( 2, vc ); + ssgTexCoordArray* tl = new ssgTexCoordArray(); + ssgNormalArray* nl = new ssgNormalArray(); + ssgColourArray* cl = new ssgColourArray( 1, cc ); + + ssgVtxTable* vtab = new ssgVtxTable( GL_LINES, + vl, nl, tl, cl ); + ssgSimpleState* st = new ssgSimpleState; + st->setMaterial( GL_SPECULAR, 0.0f, 0.0f, 0.0f ); + st->setMaterial( GL_EMISSION, 0.0f, 0.0f, 0.0f ); + st->setMaterial( GL_AMBIENT, 0.0f, 0.0f, 0.0f ); + st->setMaterial( GL_DIFFUSE, 0.0f, 0.0f, 0.0f ); + st->enable( GL_LIGHTING ); + st->setShadeModel( GL_SMOOTH ); + st->disable( GL_TEXTURE_2D ); + st->disable( GL_ALPHA_TEST ); + st->disable( GL_BLEND ); + st->setOpaque(); + vtab->setState( st ); + root->addKid( vtab ); + } + break; + + case 1: + { + int r, g, b; + sscanf( endp, "%d%d%d", &r, &g, &b ); + p = getline( line, sizeof(line), fp ); + float x, y, z; + sscanf( p, "%f%f%f", &x, &z, &y ); + + // TODO: create appropriate ssgEntity. + } + break; + + case 99: + break; + + default: + ulSetError( UL_WARNING, + "ssgLoadXPlaneObj: invalid line, '%s'", line ); + fclose(fp); + delete root; + return 0; + } + } + while ((p = getline( line, sizeof(line), fp )) != 0 && type != 99); + } + + fclose( fp ); + return root; +} + +ssgEntity* +ssgLoadXPlaneOBJ( const char* fname, const ssgLoaderOptions* options ) +{ + ObjLoader loader( options ); + return loader.load( fname ); +} + diff --git a/src/ssg/ssgLoaderWriterStuff.cxx b/src/ssg/ssgLoaderWriterStuff.cxx new file mode 100644 index 0000000..691ed98 --- /dev/null +++ b/src/ssg/ssgLoaderWriterStuff.cxx @@ -0,0 +1,914 @@ + +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoaderWriterStuff.cxx 2060 2006-01-05 20:54:15Z fayjf $ +*/ + +// ssgLoaderWriterStuff.cxx +// Here you will find classes and functions you can use to +// implement loaders and writers for ssg +// Also, there is the parser for loading ASCII files, which +// has its own file ssgParser.cxx and there are functions like +// the stripifier that are usefull not only for loaders/writers. +// +// 1. Version written by Wolfram Kuss (Wolfram.Kuss@t-online.de) +// in Nov of 2000 +// Distributed with Steve Bakers plib under the LGPL licence + +#include "ssgLocal.h" +#include "ssgLoaderWriterStuff.h" + + +#undef ABS +#undef MIN +#undef MAX +#define ABS(x) ((x) >= 0 ? (x) : -(x)) +#define MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define MAX(a,b) ((a) >= (b) ? (a) : (b)) +#define MIN3(a,b,c) ((a) <= (b) ? MIN(a,c) : MIN(b,c)) +#define MAX3(a,b,c) ((a) >= (b) ? MAX(a,c) : MAX(b,c)) + +// texture coord epsilon +#define TC_EPSILON 0.01 + + +sgVec4 currentDiffuse; + +// *********************************************************************** +// ******************** small utility functions ************************ +// *********************************************************************** + +void ssgAccumVerticesAndFaces( ssgEntity* node, sgMat4 transform, ssgVertexArray* vertices, + ssgIndexArray* indices, SGfloat epsilon, ssgSimpleStateArray* ssa, + ssgIndexArray* materialIndices, ssgTexCoordArray *texCoordArray) +// Accumulates all vertices and Faces (indexes of vertices making up faces) +// from node and any node below. +// Calls itself recursively. +// If indices is NULL, no face info is accumulated +// if epsilon is < 0.0, it is ignored. Else vertices are only accumulated if +// there is no vertex inside epsilon yet +{ + + assert( vertices != NULL ); + assert( (epsilon < 0.0) || (indices == NULL) ); // sorry: using epsilon AND using indices not implemented + if ( ssa != NULL ) { assert( indices != NULL ); } + assert ( ((ssa==NULL) && (materialIndices==NULL)) || ((ssa!=NULL) && (materialIndices!=NULL))); + if ( node->isAKindOf( ssgTypeTransform() ) ) { + sgMat4 local_transform; + ssgTransform *t_node = (ssgTransform*)node; + + t_node->getTransform(local_transform); + sgPostMultMat4( local_transform, transform ); + + for (ssgEntity* kid = t_node->getKid(0); kid != NULL; + kid = t_node->getNextKid()) { + ssgAccumVerticesAndFaces( kid, local_transform, vertices, indices, epsilon, ssa, materialIndices, texCoordArray); + } + } + else if ( node->isAKindOf( ssgTypeBranch() ) ) { + ssgBranch *b_node = (ssgBranch*)node; + for (ssgEntity* kid = b_node->getKid(0); kid != NULL; + kid = b_node->getNextKid()) { + ssgAccumVerticesAndFaces( kid, transform, vertices, indices, epsilon, ssa, materialIndices, texCoordArray); + } + } + else if ( node->isAKindOf( ssgTypeLeaf() ) ) { + ssgLeaf* l_node = (ssgLeaf*)node; + int i, vert_low = vertices->getNum(); + + int useTexture = FALSE; + if ( texCoordArray ) + if ( l_node->getState() ) + if (l_node->getState()->isAKindOf(ssgTypeSimpleState())) + { + ssgSimpleState * ss = (ssgSimpleState *) l_node->getState(); + if ( ss->isEnabled ( GL_TEXTURE_2D ) ) +// wk kludge!!! if ( l_node -> getNumTexCoords () == l_node -> getNumVertices() ) + useTexture = TRUE; + } + + for (i = 0; i < l_node->getNumVertices(); i++) { + sgVec3 new_vertex; + sgXformVec3(new_vertex, l_node->getVertex(i), transform); + + if ( epsilon < 0.0 ) + { + vertices->add(new_vertex); + if ( useTexture ) + texCoordArray ->add ( l_node->getTexCoord(i) ); + else if ( texCoordArray ) + texCoordArray ->add ( _ssgTexCoord00 ); + } + else + { + int j, bFound = FALSE, nv1 = vertices -> getNum (); + for ( j = 0; j < nv1; j++) + { + float *oldvertex = vertices -> get(j); + if (( new_vertex[0] - oldvertex[0] > -epsilon) && + ( new_vertex[0] - oldvertex[0] < epsilon) && + ( new_vertex[1] - oldvertex[1] > -epsilon) && + ( new_vertex[1] - oldvertex[1] < epsilon) && + ( new_vertex[2] - oldvertex[2] > -epsilon) && + ( new_vertex[2] - oldvertex[2] < epsilon)) + { + float *f = 0; + if ( useTexture ) + { + assert( texCoordArray ); // if texCoordArray would be NULL, useTexture would not be set. + f = texCoordArray -> get(j); + } + if ( !useTexture || ((l_node->getTexCoord(i)[0] == f[0]) && + (l_node->getTexCoord(i)[1] == f[1]))) + { + bFound = TRUE; + break; + } + } + } + if ( ! bFound ) + { + vertices -> add ( new_vertex ); + if ( useTexture ) + texCoordArray ->add ( l_node->getTexCoord(i) ); + else if ( texCoordArray ) + texCoordArray ->add ( _ssgTexCoord00 ); + } + } + } + + if ( indices != NULL ) + { + int index=-1; + if ( ssa != NULL ) + { + ssgState *s = l_node->getState(); + if ( s != NULL ) + { index = ssa->findIndex (reinterpret_cast (s) ); + if ( index < 0 ) + { ssa -> add(reinterpret_cast (s) ); + index = ssa->getNum()-1; + } + } + } + for (i = 0; i < l_node->getNumTriangles(); i++) { + short v1, v2, v3; + l_node->getTriangle(i, &v1, &v2, &v3); + indices->add( vert_low + v1 ); + indices->add( vert_low + v2 ); + indices->add( vert_low + v3 ); + if ( materialIndices != NULL ) + materialIndices->add(index); // index is -1 for leafs without state + } + } + } + if ( texCoordArray ) + { + assert( vertices->getNum() == texCoordArray->getNum() ); + } +} ; + + +/* + ssgTriangulate - triangulate a simple polygon. +*/ + +static int triangulateConcave(sgVec3 *coords, int *w, int n, int x, int y, int *tris) +{ + struct Vtx { + int index; + float x, y; + Vtx *next; + }; + + Vtx buf[16], *arr, *p0, *p1, *p2, *m0, *m1, *m2, *t; + int i, chk, num_tris; + float a0, a1, a2, b0, b1, b2, c0, c1, c2; + + /* construct a circular linked list of the vertices */ + arr = (n > 16) ? new Vtx [ n ] : buf; + p0 = &arr[0]; + p0->index = w ? w[0] : 0; + p0->x = coords[p0->index][x]; + p0->y = coords[p0->index][y]; + p1 = p0; + p2 = 0; + for (i = 1; i < n; i++) { + p2 = &arr[i]; + p2->index = w ? w[i] : i; + p2->x = coords[p2->index][x]; + p2->y = coords[p2->index][y]; + p1->next = p2; + p1 = p2; + } + p2->next = p0; + + m0 = p0; + m1 = p1 = p0->next; + m2 = p2 = p1->next; + chk = 0; + num_tris = 0; + + while (p0 != p2->next) { + if (chk && m0 == p0 && m1 == p1 && m2 == p2) { + /* no suitable vertex found.. */ + ulSetError(UL_WARNING, "ssgTriangulate: Self-intersecting polygon."); + if (arr != buf) + delete [] arr; + return 0; + } + chk = 1; + + a0 = p1->y - p2->y; + a1 = p2->y - p0->y; + a2 = p0->y - p1->y; + b0 = p2->x - p1->x; + b1 = p0->x - p2->x; + b2 = p1->x - p0->x; + + if (b0 * a2 - b2 * a0 < 0) { + /* current angle is concave */ + p0 = p1; + p1 = p2; + p2 = p2->next; + } + else { + /* current angle is convex */ + float xmin = MIN3(p0->x, p1->x, p2->x); + float xmax = MAX3(p0->x, p1->x, p2->x); + float ymin = MIN3(p0->y, p1->y, p2->y); + float ymax = MAX3(p0->y, p1->y, p2->y); + + c0 = p1->x * p2->y - p2->x * p1->y; + c1 = p2->x * p0->y - p0->x * p2->y; + c2 = p0->x * p1->y - p1->x * p0->y; + + for (t = p2->next; t != p0; t = t->next) { + /* see if the triangle contains this vertex */ + if (xmin <= t->x && t->x <= xmax && + ymin <= t->y && t->y <= ymax && + a0 * t->x + b0 * t->y + c0 > 0 && + a1 * t->x + b1 * t->y + c1 > 0 && + a2 * t->x + b2 * t->y + c2 > 0) + break; + } + + if (t != p0) { + p0 = p1; + p1 = p2; + p2 = p2->next; + } + else { + /* extract this triangle */ + tris[3 * num_tris + 0] = p0->index; + tris[3 * num_tris + 1] = p1->index; + tris[3 * num_tris + 2] = p2->index; + num_tris++; + + p0->next = p1 = p2; + p2 = p2->next; + + m0 = p0; + m1 = p1; + m2 = p2; + chk = 0; + } + } + } + + tris[3 * num_tris + 0] = p0->index; + tris[3 * num_tris + 1] = p1->index; + tris[3 * num_tris + 2] = p2->index; + num_tris++; + + if (arr != buf) + delete [] arr; + + return num_tris; +} + +int _ssgTriangulate( sgVec3 *coords, int *w, int n, int *tris ) +{ + float *a, *b; + int i, x, y; + + /* trivial case */ + if (n <= 3) { + if (n == 3) { + tris[0] = w ? w[0] : 0; + tris[1] = w ? w[1] : 1; + tris[2] = w ? w[2] : 2; + return 1; + } + ulSetError(UL_WARNING, "ssgTriangulate: Invalid number of vertices (%d).", n); + return 0; + } + + /* compute areas */ + { + float s[3], t[3]; + int swap; + + s[0] = s[1] = s[2] = 0; + b = coords[w ? w[n - 1] : n - 1]; + + for (i = 0; i < n; i++) { + a = b; + b = coords[w ? w[i] : i]; + s[0] += a[1] * b[2] - a[2] * b[1]; + s[1] += a[2] * b[0] - a[0] * b[2]; + s[2] += a[0] * b[1] - a[1] * b[0]; + } + + /* select largest area */ + t[0] = ABS(s[0]); + t[1] = ABS(s[1]); + t[2] = ABS(s[2]); + i = t[0] > t[1] ? t[0] > t[2] ? 0 : 2 : t[1] > t[2] ? 1 : 2; + swap = (s[i] < 0); /* swap coordinates if clockwise */ + x = (i + 1 + swap) % 3; + y = (i + 2 - swap) % 3; + } + + /* concave check */ + { + float x0, y0, x1, y1; + + a = coords[w ? w[n - 2] : n - 2]; + b = coords[w ? w[n - 1] : n - 1]; + x1 = b[x] - a[x]; + y1 = b[y] - a[y]; + + for (i = 0; i < n; i++) { + a = b; + b = coords[w ? w[i] : i]; + x0 = x1; + y0 = y1; + x1 = b[x] - a[x]; + y1 = b[y] - a[y]; + if (x0 * y1 - x1 * y0 < 0) + return triangulateConcave(coords, w, n, x, y, tris); + } + } + + /* convert to triangles */ + { + int v0 = 0, v1 = 1, v = n - 1; + int even = 1; + for (i = 0; i < n - 2; i++) { + if (even) { + tris[3 * i + 0] = w ? w[v0] : v0; + tris[3 * i + 1] = w ? w[v1] : v1; + tris[3 * i + 2] = w ? w[v] : v; + v0 = v1; + v1 = v; + v = v0 + 1; + } + else { + tris[3 * i + 0] = w ? w[v1] : v1; + tris[3 * i + 1] = w ? w[v0] : v0; + tris[3 * i + 2] = w ? w[v] : v; + v0 = v1; + v1 = v; + v = v0 - 1; + } + even = !even; + } + } + return n - 2; +} + + + +// *********************************************************************** +// ******************** class ssgLoaderWriterMesh ************************ +// *********************************************************************** + +void ssgLoaderWriterMesh::reInit(void) // was: ReInit +{ + theVertices = NULL ; + materialIndices = NULL ; + theFaces = NULL ; + perFaceAndVertexTextureCoordinate2Lists = NULL ; + theMaterials = NULL ; + perVertexTextureCoordinates2 = NULL ; + name = NULL ; + textureCoordinatesArePerVertex = TRUE ; +} + +ssgLoaderWriterMesh::ssgLoaderWriterMesh() +{ + reInit(); +} + +ssgLoaderWriterMesh::~ssgLoaderWriterMesh() +{} + +void ssgLoaderWriterMesh::deletePerFaceAndVertexTextureCoordinates2() // was: deleteTCPFAV +{} + +// creation stuff: + +void ssgLoaderWriterMesh::createVertices( int numReservedVertices ) // was: ThereAreNVertices +{ + assert( theVertices == NULL ); + theVertices = new ssgVertexArray ( numReservedVertices ); +} + +void ssgLoaderWriterMesh::addVertex( sgVec3 v ) +{ + assert( theVertices!=NULL ); + theVertices->add ( v ); +} + +void ssgLoaderWriterMesh::setVertices( class ssgVertexArray *vertexArray ) +{ + assert( theVertices == NULL ); + theVertices = vertexArray; +} + +void ssgLoaderWriterMesh::setPerVertexTextureCoordinates2( class ssgTexCoordArray *texCoordArray ) +{ + assert( perVertexTextureCoordinates2 == NULL ); + perVertexTextureCoordinates2 = texCoordArray; +} + +void ssgLoaderWriterMesh::createFaces( int numReservedFaces ) // was: ThereAreNFaces +{ + assert( theFaces == NULL ); + theFaces = new ssgListOfLists ( numReservedFaces ); +} + +void ssgLoaderWriterMesh::addFace( ssgIndexArray **indexArray ) +{ + assert( theFaces!=NULL ); + theFaces->add ( (ssgSimpleList **)indexArray ); +} + +void ssgLoaderWriterMesh::addFaceFromIntegerArray( int numVertices, int *vertices ) +{ + int j; + class ssgIndexArray *oneFace = new ssgIndexArray( numVertices ); + oneFace->ref(); + for( j=0; jadd( vertices[j] ); + + addFace( (ssgIndexArray **) &oneFace ); +} + +void ssgLoaderWriterMesh::createPerFaceAndVertexTextureCoordinates2( int numReservedTextureCoordinateLists ) // was: ThereAreNTCPFAV +{ + assert( perFaceAndVertexTextureCoordinate2Lists == NULL ); + perFaceAndVertexTextureCoordinate2Lists = new ssgListOfLists( numReservedTextureCoordinateLists ); +} + +void ssgLoaderWriterMesh::addPerFaceAndVertexTextureCoordinate2( ssgTexCoordArray **textureCoordinates2 ) // was: addTCPFAV +{ + assert( perFaceAndVertexTextureCoordinate2Lists != NULL ); + perFaceAndVertexTextureCoordinate2Lists->add( (ssgSimpleList **)textureCoordinates2 ); +} + +void ssgLoaderWriterMesh::createPerVertexTextureCoordinates2( int numReservedTextureCoordinates ) +{ + assert( perVertexTextureCoordinates2 == NULL ); + perVertexTextureCoordinates2 = new ssgTexCoordArray ( numReservedTextureCoordinates ); +} + +void ssgLoaderWriterMesh::addPerVertexTextureCoordinate2( sgVec2 textureCoordinate ) +{ + assert( perVertexTextureCoordinates2 != NULL ); + perVertexTextureCoordinates2->add ( textureCoordinate ); +} + +void ssgLoaderWriterMesh::createMaterialIndices( int numReservedMaterialIndices ) // ThereAreNMaterialIndexes +{ + assert( materialIndices == NULL ); + materialIndices = new ssgIndexArray ( numReservedMaterialIndices ); +} + +void ssgLoaderWriterMesh::addMaterialIndex( short materialIndex ) +{ + assert( materialIndices != NULL ); + materialIndices->add ( materialIndex ); +} + +void ssgLoaderWriterMesh::createMaterials( int numReservedMaterials ) // ThereAreNMaterials( int n ) +{ + assert( theMaterials == NULL ); + theMaterials = new ssgSimpleStateList( numReservedMaterials ); +} + +void ssgLoaderWriterMesh::addMaterial ( class ssgSimpleState **simpleState ) +{ + assert( theMaterials != NULL ); + theMaterials->add( simpleState ); +} + +static void recalcNormals( ssgIndexArray* indexList, ssgVertexArray* vertexList, ssgNormalArray *normalList ) +// wl: modified to use more code from sg +{ + sgVec3 v1, v2, n; + + for (int i = 0; i < indexList->getNum() / 3; i++) { + short indices[3] = { *indexList->get( i*3 ), *indexList->get( i*3 + 1), *indexList->get( i*3 + 2) }; + + sgSubVec3(v1, vertexList->get(indices[1]), vertexList->get(indices[0])); + sgSubVec3(v2, vertexList->get(indices[2]), vertexList->get(indices[0])); + + sgVectorProductVec3( n, v1, v2 ); + SGfloat normalLength = sgLengthVec3( n ); + if( normalLength > 0.00001 ) + sgNormaliseVec3( n ); + + sgCopyVec3( normalList->get( indices[0] ), n ); + sgCopyVec3( normalList->get( indices[1] ), n ); + sgCopyVec3( normalList->get( indices[2] ), n ); + } + } + +// addOneNodeToSSGFromPerFaceAndVertexTextureCoordinates: this function replicates each vertex (based on face usage) and +// assigns the appropriate texture coordinates to them (based on the per-face texture indices) +void ssgLoaderWriterMesh::addOneNodeToSSGFromPerFaceAndVertexTextureCoordinates2( class ssgVertexArray *theVertices, + class ssgListOfLists *thePerFaceAndVertexTextureCoordinates2, + class ssgListOfLists *theFaces, + class ssgSimpleState *currentState,// Pfusch, kludge. NIV135 + class ssgLoaderOptions* current_options, + class ssgBranch *curr_branch_) // was: AddOneNode2SSGFromCPFAV + +{ + int i, j; + + assert( theVertices!=NULL ); + assert( theFaces!=NULL ); + + // note: I am changing theVertices here, but that is allowed. + class ssgTexCoordArray *perVertexTextureCoordinates2 = new ssgTexCoordArray( theVertices->getNum() ); + sgVec2 unUsed; + unUsed[0]=-99999; // FixMe: It would be nicer to have an extra array of booleans + unUsed[1]=-99999; + for( i=0; igetNum(); i++) + perVertexTextureCoordinates2->add( unUsed ); + for( i=0; igetNum(); i++) + { + class ssgIndexArray *oneFace = *((class ssgIndexArray **) theFaces->get( i )); + class ssgTexCoordArray *textureCoordsForOneFace = *( (ssgTexCoordArray **) thePerFaceAndVertexTextureCoordinates2->get( i ) ); + if ( textureCoordsForOneFace != NULL ) // It is allowed that some or even all faces are untextured. + { + for( j=0; jgetNum(); j++ ) + { + short *ps = oneFace->get(j); + float *newTextureCoordinate2 = textureCoordsForOneFace->get( j ); + float *oldTextureCoordinate2 = perVertexTextureCoordinates2->get( *ps ); + + assert( oldTextureCoordinate2 != NULL ); + if ((oldTextureCoordinate2[0]==-99999) && (oldTextureCoordinate2[1]==-99999)) // tc unused until now. Use it + { + sgVec2 pv; // FixMe: mem leak? + pv[0]=newTextureCoordinate2[0]; + pv[1]=newTextureCoordinate2[1]; + perVertexTextureCoordinates2->set( pv, *ps ); + } + else + { // can we simply use the "old" value? + if ( TC_EPSILON < ABS ( newTextureCoordinate2[0]-oldTextureCoordinate2[0] ) + + ABS ( newTextureCoordinate2[1]-oldTextureCoordinate2[1] )) + { // NO, we can't. Duplicate vertex + // not allowed: theVertices->add(theVertices->get(*ps)); + // create duplicate 3D. FixMe: clone needed? + + float * f = theVertices->get(*ps); + sgVec3 v; + v[0] = f[0]; v[1] = f[1]; v[2] = f[2]; + theVertices->add( v ); + sgVec2 pv; + pv[0]=newTextureCoordinate2[0]; + pv[1]=newTextureCoordinate2[1]; + perVertexTextureCoordinates2->add( pv ); // create duplicate 2D + *ps=theVertices->getNum()-1; // use duplicate + assert ( *oneFace->get(j) == theVertices->getNum()-1); + } + } + } + } + } + addOneNodeToSSGFromPerVertexTextureCoordinates2(theVertices, perVertexTextureCoordinates2, theFaces, currentState, + current_options, curr_branch_); +} + +void ssgLoaderWriterMesh::addOneNodeToSSGFromPerVertexTextureCoordinates2( class ssgVertexArray *theVertices, + class ssgTexCoordArray *theTextureCoordinates2, + class ssgListOfLists *theFaces, + class ssgSimpleState *currentState,// kludge NIV135 + class ssgLoaderOptions* current_options, + class ssgBranch *curr_branch_) // was: AddOneNode2SSGFromCPV +{ + int i, j; + //start Normals, FixMe, kludge NIV135 + + ssgNormalArray *normalList = new ssgNormalArray( theVertices->getNum() ); + sgVec3 kludge; + for( i=0; igetNum(); i++ ) + normalList->add(kludge); //currentMesh.vl->get(i)); + + class ssgIndexArray* indexList = new ssgIndexArray ( theFaces->getNum() * 3 ) ; // there are MINIMAL n * 3 indexes + + for( i=0; igetNum(); i++ ) + { + class ssgIndexArray *oneFace = *((class ssgIndexArray **) theFaces->get( i )); + if ( oneFace->getNum() >= 3 ) + { + for(j=0;jgetNum();j++) + { + if (j<3) + indexList->add(*oneFace->get(j)); + else // add a complete triangle + { + indexList->add(*oneFace->get(0)); + indexList->add(*oneFace->get(j-1)); + indexList->add(*oneFace->get(j)); + } + } + } + } + recalcNormals( indexList, theVertices, normalList ); // Fixme, NIV14: only do this if there are no normals in the file + + ssgColourArray* colours = NULL ; + + if ( currentState -> isEnabled ( GL_LIGHTING ) ) + { + if ( colours == NULL ) + { + colours = new ssgColourArray ( 1 ) ; + sgVec4 currentDiffuseColour; + sgCopyVec4(currentDiffuseColour, currentState->getMaterial(GL_DIFFUSE)); + colours -> add ( currentDiffuseColour ) ; + } + } + ssgVtxArray* leaf = new ssgVtxArray ( GL_TRIANGLES, theVertices, normalList, theTextureCoordinates2, colours, indexList ) ; + leaf -> setCullFace ( TRUE ) ; + leaf -> setState ( currentState ) ; + + ssgEntity *model = current_options -> createLeaf ( leaf, NULL) ; + assert( model != NULL ); + model->setName(name); + curr_branch_->addKid(model); +} + +void ssgLoaderWriterMesh::setName( const char *meshName ) +{ + delete [] name; + if ( !meshName ) + name = NULL; + else + name = ulStrDup(meshName); +} + + +void ssgLoaderWriterMesh::addToSSG( + class ssgSimpleState *currentState,// FixMe, kludge. NIV135 + class ssgLoaderOptions* current_options, + class ssgBranch *curr_branch_ ) +{ + int i, j, k; + unsigned short oldVertexIndex, newVertexIndex; + class ssgIndexArray *thisFace; + +#ifdef WRITE_MESH_TO_STDOUT + if ( theMaterials == NULL ) + ulSetError(UL_DEBUG, "( theMaterials == NULL )"); + else + { + ulSetError(UL_DEBUG, "%d Materials:", theMaterials->getNum()); + for(i=0;igetNum();i++) + { ulSetError(UL_DEBUG, "%ld", (long)theMaterials->get(i)); + } + } + if ( materialIndices == NULL ) + ulSetError(UL_DEBUG, "( materialIndices == NULL )"); + else + { + ulSetError(UL_DEBUG, "%d Material Indexes:", materialIndices->getNum()); + for(i=0;igetNum();i++) + { short s=*(materialIndices->get(i)); + ulSetError(UL_DEBUG, "%ld", (long)s); + } + } +#endif + if ( theMaterials == NULL ) + { + if ( perFaceAndVertexTextureCoordinate2Lists == NULL ) + addOneNodeToSSGFromPerVertexTextureCoordinates2( theVertices, perVertexTextureCoordinates2 /* may be NULL */, theFaces, currentState, current_options, curr_branch_); + else + addOneNodeToSSGFromPerFaceAndVertexTextureCoordinates2(theVertices, perFaceAndVertexTextureCoordinate2Lists, theFaces, currentState, + current_options, curr_branch_); + } + else + { + assert( theVertices != NULL ); + assert( theFaces != NULL ); + // FixMe: What about faces without state? They should have material -1 + for( i=0; i < theMaterials->getNum(); i++ ) + { + // I often allocate too much; This is wastefull on memory, but fast since it never "resizes": + class ssgVertexArray *newVertices = new ssgVertexArray ( theVertices->getNum() ); + class ssgListOfLists *newFaces = new ssgListOfLists ( theFaces->getNum() ); + class ssgIndexArray *oldVertexIndexToNewVertexIndex = new ssgIndexArray ( theVertices->getNum() ); + class ssgListOfLists *newPerFaceAndVertexTextureCoordinate2Lists = NULL; + class ssgTexCoordArray *newPerVertexTextureCoordinates2 = NULL; + + if( perFaceAndVertexTextureCoordinate2Lists != NULL ) + newPerFaceAndVertexTextureCoordinate2Lists = new ssgListOfLists(); + if ( perVertexTextureCoordinates2 != NULL ) + newPerVertexTextureCoordinates2 = new ssgTexCoordArray(); + + for (j=0; jgetNum(); j++) + oldVertexIndexToNewVertexIndex->add ( short(0xFFFF) ); // 0xFFFF stands for "unused in new Mesh" + + // Go through all the old Faces, look for the correct material and copy those + // faces and indexes into the new + // FixMe, 2do, NIV135: if the Materials just differ through the colour, one would not need + // several meshes, but could use the colour array. However, this is not possible, + // if they differ by for example the texture + assert( materialIndices != NULL ); + for ( j=0; jgetNum(); j++ ) + if ( i == *(materialIndices->get( + // for *.x-files, there may be less materialIndices than faces. I then simply repeat + // the last index all the time: + jgetNum() ? j : materialIndices->getNum()-1 )) + ) + { + // take this face + thisFace = *((class ssgIndexArray **) theFaces->get( j )); + newFaces->add( (class ssgSimpleList **)&thisFace); + //thisFace = *((class ssgIndexArray **) newFaces->get( newFaces->getNum()-1 )); + + if( perFaceAndVertexTextureCoordinate2Lists != NULL ) + newPerFaceAndVertexTextureCoordinate2Lists ->add( perFaceAndVertexTextureCoordinate2Lists -> get( j ) ); + + for( k=0; k < thisFace->getNum(); k++ ) + { + oldVertexIndex = * thisFace->get(k); + newVertexIndex = *oldVertexIndexToNewVertexIndex->get( oldVertexIndex ); + + if ( 0xFFFF == newVertexIndex ) + { + newVertexIndex = newVertices->getNum(); + newVertices->add( theVertices->get( oldVertexIndex ) ); + oldVertexIndexToNewVertexIndex->set( newVertexIndex, oldVertexIndex ); + + if ( perVertexTextureCoordinates2 != NULL ) + newPerVertexTextureCoordinates2 -> add( perVertexTextureCoordinates2->get( oldVertexIndex ) ); + } + // From here on the indexes in thisFace are only valid in relation to + // newVertices and newtextureCoordinatePerVertex. Since this face will not be used for any + // further material, this doesn't lead to problems. + thisFace->set( newVertexIndex, k ); + } + } +#ifdef WRITE_MESH_TO_STDOUT + ulSetError(UL_DEBUG, "NumVert: %d", newVertices->getNum()); + for(j=0;jgetNum();j++) + { float *f=newVertices->get(j); + ulSetError(UL_DEBUG, "%f, %f, %f",f[0], f[1], f[2]); + } + for(j=0;jgetNum();j++) + { + thisFace = *((class ssgIndexArray **) newFaces->get( j )); + fprintf(stderr, "%d EP:", thisFace->getNum()); + for(k=0;kgetNum();k++) + { + oldVertexIndex = * thisFace->get(k); + fprintf(stderr, "%d, ", oldVertexIndex); + } + putc('\n', stderr); + } +#endif + if ( newFaces->getNum() > 0 ) + { + currentState = *theMaterials->get(i); + if ( perFaceAndVertexTextureCoordinate2Lists == NULL ) + // FixMe: textureCoordinatePerVertex-indices are not compatible to newVertices-indices?!? + addOneNodeToSSGFromPerVertexTextureCoordinates2( newVertices, newPerVertexTextureCoordinates2 /* may be NULL */, newFaces, currentState, current_options, curr_branch_); + else + addOneNodeToSSGFromPerFaceAndVertexTextureCoordinates2(newVertices, newPerFaceAndVertexTextureCoordinate2Lists, newFaces, currentState, + current_options, curr_branch_); + } + } + } +} + +int ssgLoaderWriterMesh::checkMe() +// returns TRUE; if ok. +// Writes out errors by calling ulSetError with severity UL_WARNING, +// and a bit of debug info as UL_DEBUG +// May stop on first error. + +// FixMe; todo: textureCoordinatePerVertex and tCPFAV. NIV135 +{ + int i, oneIndex; + class ssgIndexArray * vertexIndsForOneFace; + class ssgTexCoordArray * textureCoordsForOneFace; + + // **** check theVertices ***** + if ( theVertices == NULL ) + { if (( materialIndices == NULL ) && + (theFaces == NULL ) && + ( perFaceAndVertexTextureCoordinate2Lists == NULL )) + { ulSetError( UL_DEBUG, "LoaderWriterMesh::checkMe(): The mesh is empty\n"); + return TRUE; + } + else + { ulSetError( UL_WARNING, "LoaderWriterMesh::checkMe(): No theVertices is NULL; but not the rest!\n"); + return FALSE; + } + + } + // **** check materialIndices and theMaterials ***** + /* FixMe; kludge: 2do. NIV135 + // one index per face: + class ssgIndexArray *materialIndices; + + theMaterials + */ + if ((( theMaterials == NULL ) && ( materialIndices != NULL )) || + (( theMaterials != NULL ) && ( materialIndices == NULL ))) + { ulSetError( UL_WARNING, "LoaderWriterMesh::checkMe(): " + "One of theMaterials and materialIndices was NULL and the other != NULL!\n"); + return FALSE; + } + if ( materialIndices != NULL ) + { for (i=0;igetNum();i++) + { oneIndex = *materialIndices->get(i); + assert(theMaterials!=NULL); + if (( oneIndex < 0 ) || ( oneIndex >= theMaterials->getNum())) + { ulSetError( UL_WARNING, "LoaderWriterMesh::checkMe(): " + "Material index out of range. Index = %d, " + "theMaterials->getNum() = %d.\n", + oneIndex, theMaterials->getNum()); + return FALSE; + } + } + } + + + // **** check theFaces ***** + // Each sublist is of type ssgIndexArray and contains the indexes of the vertices: + if ( theFaces == NULL ) + { ulSetError( UL_WARNING, "LoaderWriterMesh::checkMe(): There are vertices but no faces.\n"); + return FALSE; + } + for(i=0;igetNum();i++) + { + vertexIndsForOneFace = *((ssgIndexArray **) theFaces->get ( i )); + if ( vertexIndsForOneFace == NULL ) + { ulSetError( UL_WARNING, "LoaderWriterMesh::checkMe(): the vertexindexes for one face are NULL!\n"); + return FALSE; + } + } + // **** check textureCoordinates ***** + // Each sublist is of type ssgTexCoordArray and contains the texture coordinates + if ( perFaceAndVertexTextureCoordinate2Lists != NULL ) // may be NULL + { if ( theFaces->getNum() != perFaceAndVertexTextureCoordinate2Lists->getNum()) + { ulSetError( UL_WARNING, "LoaderWriterMesh::checkMe(): " + "There must be as many faces in theFaces as in textureCoordinates. But " + "theFaces->getNum() =%d, tCPFAV->getNum() = %d!\n", + theFaces->getNum(), perFaceAndVertexTextureCoordinate2Lists->getNum()); + return FALSE; + } + for(i=0;igetNum();i++) + { + textureCoordsForOneFace = *((ssgTexCoordArray **) perFaceAndVertexTextureCoordinate2Lists->get ( i )); + if ( textureCoordsForOneFace != NULL ) // It is allowed that some or even all faces are untextured. + { + vertexIndsForOneFace = *((ssgIndexArray **) theFaces->get ( i )); + if ( textureCoordsForOneFace->getNum() != vertexIndsForOneFace ->getNum()) + { + ulSetError( UL_WARNING, "LoaderWriterMesh::checkMe(): Face %d: " + "Each face must have as many texture corrdinates (or none) as vertices. But " + "textureCoordsForOneFace->getNum() =%d, vertexIndsForOneFace ->getNum() = %d!\n", + i, textureCoordsForOneFace->getNum(), vertexIndsForOneFace ->getNum()); + return FALSE; + } + } + } + } + return TRUE; // success +} diff --git a/src/ssg/ssgLoaderWriterStuff.h b/src/ssg/ssgLoaderWriterStuff.h new file mode 100644 index 0000000..2a42979 --- /dev/null +++ b/src/ssg/ssgLoaderWriterStuff.h @@ -0,0 +1,161 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLoaderWriterStuff.h 1935 2004-05-04 12:37:33Z wolfram_kuss $ +*/ + +//#include "ssgLocal.h" + +// ******************** small utility functions ************************ + +void ssgAccumVerticesAndFaces( ssgEntity* node, sgMat4 transform, ssgVertexArray* vertices, + ssgIndexArray* indices, SGfloat epsilon, + ssgSimpleStateArray* ssa = NULL, + ssgIndexArray* materialIndices = NULL, + ssgTexCoordArray *texCoordArray = NULL); + +/* + ssgTriangulate - + Triangulate a simple polygon (possibly concave, but not self-intersecting). + The number of triangles written to 'triangles' is returned, which is always + less than or equal to num - 2. The polygon index array 'indices' may be null, + in which case an identity mapping is assumed. + Note that the implementation is optimized for small polygons, and since + the algorithm is O(num^2) it is not efficient on large polygons. +*/ +int _ssgTriangulate( sgVec3 *vertices, int *indices, int num, int *triangles ); + + +// ******************** class ssgLoaderWriterMesh ************************ + +class ssgListOfLists : public ssgSimpleList +// list of POINTERs to ssgSimpleLists +{ +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) { return NULL; }; // Fixme NIV14: 2do + ssgListOfLists ( int init = 3 ) : ssgSimpleList ( sizeof(ssgSimpleList*), init ) {} + class ssgSimpleList **get ( unsigned int n ) { return (class ssgSimpleList **) raw_get ( n ) ; } + void add ( class ssgSimpleList **thing ) { raw_add ( (char *) thing ) ; } ; + void set ( class ssgSimpleList **thing, unsigned int n ) { raw_set ( (char *) thing, n ) ; } ; + + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) {}; // Fixme NIV14: 2do +} ; + +//ssgSimpleState* + +class ssgSimpleStateList : public ssgSimpleList +// list of POINTERs to ssgSimpleStates +{ +public: + + virtual ssgBase *clone ( int clone_flags = 0 ) { return NULL; }; // Fixme NIV14: 2do + ssgSimpleStateList( int init = 3 ) : ssgSimpleList ( sizeof(ssgSimpleState*), init ) {} + class ssgSimpleState **get ( unsigned int n ) { return (class ssgSimpleState **) raw_get ( n ) ; } + void add ( class ssgSimpleState **thing ) { raw_add ( (char *) thing ) ; } ; + void set ( class ssgSimpleState **thing, unsigned int n ) { raw_set ( (char *) thing, n ) ; } ; + virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) {}; // Fixme NIV14: 2do +} ; + +class ssgLoaderWriterMesh +{ + // ***** general **** + char *name; + // array of Vec3s: + class ssgVertexArray *theVertices; + // one index per face: + class ssgIndexArray *materialIndices; + + // Each sublist is of type ssgIndexArray and contains the indexes of the vertices: + class ssgListOfLists *theFaces; + // material list: + class ssgSimpleStateList *theMaterials; + + // ***** mode switches ***** + int textureCoordinatesArePerVertex; // and not per vertex and face (bTCs_are_per_vertex) + // ***** complicated (texture coordinates are per face and vertex) mode ***** + // Each sublist is of type ssgTexCoordArray and contains the texture coordinates + class ssgListOfLists *perFaceAndVertexTextureCoordinate2Lists; // was: tCPFAV = TextureCoordinatesPerFaceAndVertex + + // ***** easy (texture coordinates are per vertex) mode ********* + class ssgTexCoordArray *perVertexTextureCoordinates2; // was: tCPV = TextureCoordinatesPerVertex + + void addOneNodeToSSGFromPerVertexTextureCoordinates2( class ssgVertexArray *theVertices, + class ssgTexCoordArray *theTextureCoordinates2, + class ssgListOfLists *theFaces, + class ssgSimpleState *currentState,// Pfusch, kludge. NIV135 + class ssgLoaderOptions* current_options, + class ssgBranch *curr_branch_ ); // was: AddOneNode2SSGFromCPV + void addOneNodeToSSGFromPerFaceAndVertexTextureCoordinates2( class ssgVertexArray *theVertices, + class ssgListOfLists *theTextureCoordinate2Lists, + class ssgListOfLists *theFaces, + class ssgSimpleState *currentState,// Pfusch, kludge. NIV135 + class ssgLoaderOptions* current_options, + class ssgBranch *curr_branch_ ); // was: AddOneNodeToSSGFromCPFAV + + public: + + class ssgVertexArray *getVertices(void) { return theVertices; } + void setVertices( class ssgVertexArray *vertexArray ); + class ssgTexCoordArray *getPerVertexTextureCoordinates2(void) { return perVertexTextureCoordinates2; } + void setPerVertexTextureCoordinates2( class ssgTexCoordArray *texCoordArray ); + void setName( const char *meshName ); + + void addToSSG( + class ssgSimpleState *currentstate, + class ssgLoaderOptions* currentOptions, + class ssgBranch *curr_branch_ ); + + // construction/destruction: + ssgLoaderWriterMesh(); + ~ssgLoaderWriterMesh(); + void reInit(void); + void deletePerFaceAndVertexTextureCoordinates2(); // was: deleteTCPFAV + + // creation: + void createVertices( int numReservedVertices = 8 ) ; // was: ThereAreNVertices + void addVertex( sgVec3 v ) ; + + void createFaces( int numReservedFaces = 3 ) ; // was: ThereAreNFaces + void addFace( ssgIndexArray **indexArray ) ; + void addFaceFromIntegerArray( int numVertices, int *vertices );// AddFaceFromCArray + + void createPerFaceAndVertexTextureCoordinates2( int numReservedTextureCoordinate2Lists = 3 ) ; // ThereAreNTCPFAV + void addPerFaceAndVertexTextureCoordinate2( ssgTexCoordArray **textureCoordinateArray ) ; // addTCPFAV + + void createPerVertexTextureCoordinates2( int numReservedTextureCoordinates2 = 3 ); // was: ThereAreNTCPV + void addPerVertexTextureCoordinate2( sgVec2 textureCoordinate ); // was; addTCPV + + void createMaterialIndices( int numReservedMaterialIndices = 3 ); // ThereAreNMaterialIndexes + void addMaterialIndex( short materialIndex ) ; + + void createMaterials( int numReservedMaterials = 3 ); // was: ThereAreNMaterials + void addMaterial( class ssgSimpleState **simpleState ) ; + + unsigned int getNumVertices(void) { return theVertices->getNum(); } ; + unsigned int getNumFaces (void) { return theFaces->getNum(); } ; + unsigned int getNumMaterials(void) { return theMaterials->getNum(); } ; + + + // tools: + int checkMe(); +}; + + diff --git a/src/ssg/ssgLocal.h b/src/ssg/ssgLocal.h new file mode 100644 index 0000000..17d3e8e --- /dev/null +++ b/src/ssg/ssgLocal.h @@ -0,0 +1,136 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgLocal.h 1996 2004-12-29 07:19:40Z sjbaker $ +*/ + + +#define _SSG_PUBLIC public + +#include "ssg.h" + +void _ssgStartOfFrameInit () ; +void _ssgEndOfFrameCleanup () ; + + +extern void (*__ssgEnableTable[64])() ; +extern void (*__ssgDisableTable[64])() ; + +extern sgMat4 _ssgOpenGLAxisSwapMatrix ; +extern int _ssgIsHotTest ; +extern int _ssgIsLosTest ; +extern int _ssgFileVersionNumber ; + +void _ssgForceLineState () ; + +void _ssgDrawDList () ; +void _ssgSetTweenState ( float state, int mode ) ; +void _ssgPushMatrix ( sgMat4 m ) ; +void _ssgPopMatrix () ; +void _ssgLoadMatrix ( sgMat4 m ) ; +void _ssgLoadTexMatrix ( sgMat4 m ) ; +void _ssgUnloadTexMatrix () ; +void _ssgDrawLeaf ( ssgLeaf *l ) ; + +void _ssgAddHit ( ssgLeaf *l, int trinum, sgMat4 mat, sgVec4 pl ) ; +void _ssgPushPath ( ssgEntity *l ) ; +void _ssgPopPath () ; + +extern int stats_num_vertices ; +extern int stats_num_leaves ; +extern int stats_isect_triangles ; +extern int stats_cull_test ; +extern int stats_isect_test ; +extern int stats_bind_textures ; + +extern int stats_hot_triangles ; +extern int stats_hot_test ; +extern int stats_hot_no_trav ; +extern int stats_hot_radius_reject ; +extern int stats_hot_triv_accept ; +extern int stats_hot_straddle ; + +extern int stats_los_triangles ; +extern int stats_los_test ; +extern int stats_los_no_trav ; +extern int stats_los_radius_reject ; +extern int stats_los_triv_accept ; +extern int stats_los_straddle ; + +extern ssgState *( *_ssgGetAppState)( char *) ; + +void _ssgReadFloat ( FILE *fd, float *var ) ; +void _ssgWriteFloat ( FILE *fd, const float var ) ; +void _ssgReadUInt ( FILE *fd, unsigned int *var ) ; +void _ssgWriteUInt ( FILE *fd, const unsigned int var ) ; +void _ssgReadInt ( FILE *fd, int *var ) ; +void _ssgWriteInt ( FILE *fd, const int var ) ; +void _ssgReadUShort ( FILE *fd, unsigned short *var ) ; +void _ssgWriteUShort ( FILE *fd, const unsigned short var ) ; +void _ssgReadShort ( FILE *fd, short *var ) ; +void _ssgWriteShort ( FILE *fd, const short var ) ; + +void _ssgReadFloat ( FILE *fd, const unsigned int n, float *var ) ; +void _ssgWriteFloat ( FILE *fd, const unsigned int n, const float *var ) ; +void _ssgReadUInt ( FILE *fd, const unsigned int n, unsigned int *var ) ; +void _ssgWriteUInt ( FILE *fd, const unsigned int n, const unsigned int *var ) ; +void _ssgReadInt ( FILE *fd, const unsigned int n, int *var ) ; +void _ssgWriteInt ( FILE *fd, const unsigned int n, const int *var ) ; +void _ssgReadUShort ( FILE *fd, const unsigned int n, unsigned short *var ) ; +void _ssgWriteUShort ( FILE *fd, const unsigned int n, const unsigned short *var ) ; +void _ssgReadShort ( FILE *fd, const unsigned int n, short *var ) ; +void _ssgWriteShort ( FILE *fd, const unsigned int n, const short *var ) ; +void _ssgReadBytes ( FILE *fd, const unsigned int n, void *var ) ; +void _ssgWriteBytes ( FILE *fd, const unsigned int n, const void *var ) ; + +void _ssgReadString ( FILE *fd, char **var ) ; +void _ssgWriteString ( FILE *fd, const char *var ) ; + +void _ssgReadVec2 ( FILE *fd, sgVec2 var ) ; +void _ssgWriteVec2 ( FILE *fd, const sgVec2 var ) ; +void _ssgReadVec3 ( FILE *fd, sgVec3 var ) ; +void _ssgWriteVec3 ( FILE *fd, const sgVec3 var ) ; +void _ssgReadVec4 ( FILE *fd, sgVec4 var ) ; +void _ssgWriteVec4 ( FILE *fd, const sgVec4 var ) ; + +void _ssgReadMat4 ( FILE *fd, sgMat4 var ) ; +void _ssgWriteMat4 ( FILE *fd, const sgMat4 var ) ; + +int _ssgReadError ( void ) ; +int _ssgWriteError ( void ) ; + +float _ssgGetCurrentTweenState () ; +int _ssgGetCurrentTweenMode () ; +void _ssgSetCurrentTweenSettings ( float tweenstate, int tweenmode ) ; +void _ssgSetRealCurrentTweenSettings ( float tweenstate, int tweenmode ) ; + +/* + Routines for storing arbitrary ssgBase derived objects within SSG files. + Both functions return 1 on success, and 0 on failure. + If an object is encountered that is not derived from type_mask, then + the loading is aborted and 0 returned. +*/ +int _ssgSaveObject ( FILE * , ssgBase * ) ; +int _ssgLoadObject ( FILE * , ssgBase ** , int type_mask = 0 ) ; + +extern class ssgStatistics _ssgCurrStatistics ; +extern bool _ssgBackFaceCollisions ; + + diff --git a/src/ssg/ssgMSFSPalette.h b/src/ssg/ssgMSFSPalette.h new file mode 100644 index 0000000..449e15c --- /dev/null +++ b/src/ssg/ssgMSFSPalette.h @@ -0,0 +1,29 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgMSFSPalette.h 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + +#ifndef __SSGMSFSPALETTE +#define __SSGMSFSPALETTE + +extern unsigned const char ssgFsTexPalette[] ; + +#endif // __SSGMSFSPALETTE diff --git a/src/ssg/ssgOptimiser.cxx b/src/ssg/ssgOptimiser.cxx new file mode 100644 index 0000000..eb0fd23 --- /dev/null +++ b/src/ssg/ssgOptimiser.cxx @@ -0,0 +1,1108 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgOptimiser.cxx 1999 2005-01-09 13:10:08Z bram $ +*/ + + +#include "ssgLocal.h" + +#include "ssgVertSplitter.h" + +static float optimise_vtol [3] = +{ + 0.001f, /* DISTANCE_SLOP = One millimeter */ + 0.04f, /* COLOUR_SLOP = Four percent */ + 0.004f, /* TEXCOORD_SLOP = One texel on a 256 map */ +} ; + +static float* current_vtol = 0 ; + +#define DISTANCE_SLOP current_vtol[0] +#define COLOUR_SLOP current_vtol[1] +#define TEXCOORD_SLOP current_vtol[2] + +inline float frac ( float x ) +{ + return x - (float) floor(x) ; +} + +struct OptVertex +{ + sgVec3 vertex ; + sgVec3 normal ; + sgVec2 texcoord ; + sgVec4 colour ; + int counter ; + + void print () { ulSetError ( UL_DEBUG, "%d:(%g,%g,%g):(%g,%g):(%g,%g,%g,%g):(%g,%g,%g)", + counter, + vertex[0],vertex[1],vertex[2], + texcoord[0],texcoord[1], + colour[0],colour[1],colour[2],colour[3], + normal[0],normal[1],normal[2] ) ; } + + OptVertex ( sgVec3 v, sgVec2 t, sgVec4 c ) + { + sgCopyVec3 ( vertex , v ) ; + sgCopyVec2 ( texcoord, t ) ; + sgCopyVec4 ( colour , c ) ; + sgSetVec3 ( normal , 0.0f, 0.0f, 0.0f ) ; + counter = 1 ; + } + + OptVertex ( OptVertex* cloneFrom ) + { + sgCopyVec3 ( vertex , cloneFrom -> vertex ) ; + sgCopyVec2 ( texcoord, cloneFrom -> texcoord ) ; + sgCopyVec4 ( colour , cloneFrom -> colour ) ; + sgSetVec3 ( normal , 0.0f, 0.0f, 0.0f ) ; + counter = 1 ; + } + + int equal ( sgVec3 v, sgVec2 t, sgVec4 c, int tex_frac ) + { + if ( ! sgCompareVec3 ( vertex , v, DISTANCE_SLOP ) || + ! sgCompareVec4 ( colour , c, COLOUR_SLOP ) ) + return FALSE ; + + if ( ! tex_frac ) + return sgCompareVec2 ( texcoord, t, TEXCOORD_SLOP ) ; + + return ( fabs ( frac ( texcoord[0] ) - frac ( t[0] ) ) <= TEXCOORD_SLOP && + fabs ( frac ( texcoord[1] ) - frac ( t[1] ) ) <= TEXCOORD_SLOP ) ; + } + + void bump () { counter++ ; } + void dent () { counter-- ; } + int getCount () { return counter ; } +} ; + + +#define MAX_OPT_VERTEX_LIST 10000 + +class OptVertexList +{ +public: + short vnum, tnum ; + OptVertex **vlist ; + short *tlist ; + ssgState *state ; + int cullface ; + + OptVertexList ( ssgState *s, int cf ) + { + /* + Have to dynamically allocate these to get + around Mac's CodeWarrior restriction on + 32Kb as max structure size. + */ + + vlist = new OptVertex* [ MAX_OPT_VERTEX_LIST ] ; + tlist = new short [ MAX_OPT_VERTEX_LIST * 3 ] ; + state = s ; + if (state != NULL) state -> ref(); //~T.G. + cullface = cf ; + vnum = tnum = 0 ; + } + + ~OptVertexList () + { + for ( int i = 0 ; i < vnum ; i++ ) + delete vlist [ i ] ; + + delete [] vlist ; + delete [] tlist ; + + if (state != NULL) ssgDeRefDelete(state); //~T.G. + } + + short find ( sgVec3 v, sgVec2 t, sgVec4 c, int tex_fraction_only = FALSE ) ; + + short add ( sgVec3 v1, sgVec2 t1, sgVec4 c1, + sgVec3 v2, sgVec2 t2, sgVec4 c2, + sgVec3 v3, sgVec2 t3, sgVec4 c3 ) ; + short add ( sgVec3 v, sgVec2 t, sgVec4 c ) ; + short add ( short v1, short v2, short v3 ) ; + void add ( ssgLeaf *l ) ; + + void makeNormals () ; + + void print () + { + ulSetError ( UL_DEBUG, "LIST: %d unique vertices and %d triangles", + vnum, tnum ) ; + } + + void follow ( int tri, int v1, int v2, int backwards, int *len, short *list, short *next ) ; + + int getLeastConnected ( short *t, short *v ) + { + int least = 32767 ; + *v = 0 ; + + /* Find the least connected vertex that *is* connected */ + + int i ; + + for ( i = 0 ; i < vnum ; i++ ) + { + int c = vlist [ i ] -> getCount () ; + + if ( c > 0 && c < least ) + { + least = c ; + *v = i ; + } + } + + if ( least == 32767 ) /* Didn't find an unused vertex - so punt. */ + return FALSE ; + + least = 32767 ; + *t = 32767 ; + + for ( i = 0 ; i < tnum ; i++ ) + if ( tlist[i*3+0] == *v || tlist[i*3+1] == *v || tlist[i*3+2] == *v ) + { + int c = vlist [ tlist[i*3+0] ] -> getCount () + + vlist [ tlist[i*3+1] ] -> getCount () + + vlist [ tlist[i*3+2] ] -> getCount () ; + + if ( c < least ) + { + least = c ; + *t = i ; + } + } + + if ( least == 32767 ) /* Didn't find an unused vertex - so punt. */ + return FALSE ; + + return TRUE ; /* Got it! */ + } + + void sub ( short t ) + { + vlist [ tlist[t*3+0] ] -> dent () ; + vlist [ tlist[t*3+1] ] -> dent () ; + vlist [ tlist[t*3+2] ] -> dent () ; + + tlist[t*3+0] = -1 ; + tlist[t*3+1] = -1 ; + tlist[t*3+2] = -1 ; + } +} ; + + +short OptVertexList::add ( sgVec3 v1, sgVec2 t1, sgVec4 c1, + sgVec3 v2, sgVec2 t2, sgVec4 c2, + sgVec3 v3, sgVec2 t3, sgVec4 c3 ) +{ + // If possible, this routine moves the texturecoordinates of + // all three vertices of a Tria so that one needs less vertices. + // This doesn't affect looks, but enhances the speed a bit. + // This is not possible, if warpu or wrapv is FALSE + + int bWrapsInBothDirections = FALSE; + short vi1, vi2, vi3; +/* + if ( state->isAKindOf( ssgTypeSimpleState() ) ) + bWrapsInBothDirections = + ( (((ssgSimpleState *)state)->getWrapU()) && + (((ssgSimpleState *)state)->getWrapV()) ); + */ + if (!bWrapsInBothDirections) + { + /* Find which (if any) of the vertices are a match for one in the list */ + + vi1 = add ( v1, t1, c1 ) ; + vi2 = add ( v2, t2, c2 ) ; + vi3 = add ( v3, t3, c3 ) ; + } + else + { + /* + Sharing vertices is tricky because of texture coordinates + that have the same all-important fractional part - but + differ in their integer parts. + */ + + sgVec2 adjust ; + + /* Find which (if any) of the vertices are a match for one in the list */ + + vi1 = find ( v1, t1, c1, TRUE ) ; + vi2 = find ( v2, t2, c2, TRUE ) ; + vi3 = find ( v3, t3, c3, TRUE ) ; + + /* Compute texture offset coordinates (if needed) to make everything match */ + + if ( vi1 >= 0 ) + sgSubVec2 ( adjust, t1, vlist[vi1]->texcoord ) ; + else + if ( vi2 >= 0 ) + sgSubVec2 ( adjust, t2, vlist[vi2]->texcoord ) ; + else + if ( vi3 >= 0 ) + sgSubVec2 ( adjust, t3, vlist[vi3]->texcoord ) ; + else + { + /* + OK, there was no match - so just remove + any large numbers from the texture coords + */ + + adjust [ 0 ] = (float) floor ( t1[0] ) ; + adjust [ 1 ] = (float) floor ( t1[1] ) ; + } + + /* + Now adjust the texture coordinates and add them into the list + */ + sgVec2 tmp ; + sgSubVec2 ( tmp, t1, adjust ) ; vi1 = add ( v1, tmp, c1 ) ; + sgSubVec2 ( tmp, t2, adjust ) ; vi2 = add ( v2, tmp, c2 ) ; + sgSubVec2 ( tmp, t3, adjust ) ; vi3 = add ( v3, tmp, c3 ) ; + } + return add ( vi1, vi2, vi3 ) ; +} + + +short OptVertexList::add ( short v1, short v2, short v3 ) +{ + if ( v1 == v2 || v2 == v3 || v3 == v1 ) /* Toss degenerate triangles */ + { + vlist [ v1 ] -> dent () ; /* Un-reference their vertices */ + vlist [ v2 ] -> dent () ; + vlist [ v3 ] -> dent () ; + return -1 ; + } + + tlist [ tnum*3+ 0 ] = v1 ; + tlist [ tnum*3+ 1 ] = v2 ; + tlist [ tnum*3+ 2 ] = v3 ; + + return tnum++ ; +} + +// +// Splits vertices across "sharp" edges to improve the normal +// direction. +// +void OptVertexList::makeNormals () +{ + int i, j ; + ssgVertSplitter vs ( vnum, tnum ) ; + + // Copy in the vertex and triangle data + for ( i = 0 ; i < vnum ; i ++ ) + sgCopyVec3 ( vs.vert ( i ), vlist[ i ] -> vertex ) ; + + for ( i = 0 ; i < tnum ; i ++ ) { + short* t = tlist + 3 * i ; + vs.setTri ( i , t[0], t[1], t[2] ); + } + + // Run the algorithm. Get the "sharp" angle from somewhere + // intelligent, instead of hardcoding it. + vs.splitAndCalcNormals () ; + + // Generate the new vertices by cloning their originals + int newVerts = vs.newVerts () ; + if ( vnum + newVerts > MAX_OPT_VERTEX_LIST ) + return; // Oh well. No harm done, at least. + + for ( i = 0 ; i < newVerts ; i++ ) { + OptVertex *ov = vlist[ vs.origVert ( i ) ] ; + vlist[ i + vnum ] = new OptVertex ( ov ); + } + vnum += newVerts; + + // Copy out the new, optimized normal data + for(i=0; inormal, vs.norm(i)); + + // Zero out the reference counts for the vertices; they will have + // changed during the split and will be recalculated below. This + // is an ugly hack -- a more elegant solution would be to do the + // bump()/dent() calls inside the ssgVertSplitter code as each vertex + // is duplicated. + for ( i = 0 ; i < vnum ; i++ ) + while ( vlist [ i ] -> getCount () ) + vlist [ i ] -> dent () ; + + // Copy out the possibly changed vertices for the triangles + for (i = 0 ; i < tnum ; i++ ) { + short* oldtri = tlist + 3 * i ; + int* newtri = vs.getTri ( i ) ; + for ( j = 0 ; j < 3 ; j++ ) { + oldtri [ j ] = newtri [ j ] ; + vlist[ newtri [ j ] ] -> bump (); + } + } +} + +short OptVertexList::find ( sgVec3 v, sgVec2 t, sgVec4 c, int tex_frac ) +{ + for ( short i = 0 ; i < vnum ; i++ ) + { + if ( vlist[i] -> equal ( v, t, c, tex_frac ) ) + return i ; + } + return -1 ; +} + +short OptVertexList::add ( sgVec3 v, sgVec2 t, sgVec4 c ) +{ + short i = find ( v, t, c, FALSE ) ; + + if ( i >= 0 ) + { + vlist [ i ] -> bump () ; + return i ; + } + + vlist [ vnum ] = new OptVertex ( v, t, c ) ; + return vnum++ ; +} + +void OptVertexList::add ( ssgLeaf *l ) +{ + int j ; + + for ( j = 0 ; j < l -> getNumTriangles () ; j ++ ) + { + short v1, v2, v3 ; + l -> getTriangle ( j, &v1, &v2, &v3 ) ; + add ( l->getVertex ( v1 ), l->getTexCoord ( v1 ), l->getColour ( v1 ), + l->getVertex ( v2 ), l->getTexCoord ( v2 ), l->getColour ( v2 ), + l->getVertex ( v3 ), l->getTexCoord ( v3 ), l->getColour ( v3 ) ) ; + } +} + + +void OptVertexList::follow ( int tri, int v1, int v2, int backwards, int *len, + short *new_vlist, short *new_vc ) +{ + /* WARNING - RECURSIVE !! */ + + v1 = tlist [ tri*3+ v1 ] ; + v2 = tlist [ tri*3+ v2 ] ; + + /* + This triangle's work is done - dump it. + */ + + (*len)++ ; + sub ( tri ) ; + + /* + If the exit edge vertices don't *both* have a reference + then we are done. + */ + + if ( vlist [ v1 ] -> getCount () <= 0 || + vlist [ v2 ] -> getCount () <= 0 ) + return ; + + /* + Search for a polygon that shares that edge in the correct + direction - and follow it. + */ + + for ( int i = 0 ; i < tnum ; i++ ) + { + if ( tlist [ i*3+ 0 ] < 0 ) /* Deleted triangle */ + continue ; + + if ( backwards ) + { + /* If the previous polygon was backwards */ + + if ( tlist [ i*3+ 0 ] == v1 && tlist [ i*3+ 2 ] == v2 ) + { + new_vlist [ (*new_vc)++ ] = tlist [ i*3+ 1 ] ; + follow ( i, 0, 1, !backwards, len, new_vlist, new_vc ) ; + return ; + } + else + if ( tlist [ i*3+ 1 ] == v1 && tlist [ i*3+ 0 ] == v2 ) + { + new_vlist [ (*new_vc)++ ] = tlist [ i*3+ 2 ] ; + follow ( i, 1, 2, !backwards, len, new_vlist, new_vc ) ; + return ; + } + else + if ( tlist [ i*3+ 2 ] == v1 && tlist [ i*3+ 1 ] == v2 ) + { + new_vlist [ (*new_vc)++ ] = tlist [ i*3+ 0 ] ; + follow ( i, 2, 0, !backwards, len, new_vlist, new_vc ) ; + return ; + } + } + else + { + /* If the previous polygon was forwards... */ + + if ( tlist [ i*3+ 0 ] == v1 && tlist [ i*3+ 2 ] == v2 ) + { + new_vlist [ (*new_vc)++ ] = tlist [ i*3+ 1 ] ; + follow ( i, 1, 2, !backwards, len, new_vlist, new_vc ) ; + return ; + } + else + if ( tlist [ i*3+ 1 ] == v1 && tlist [ i*3+ 0 ] == v2 ) + { + new_vlist [ (*new_vc)++ ] = tlist [ i*3+ 2 ] ; + follow ( i, 2, 0, !backwards, len, new_vlist, new_vc ) ; + return ; + } + else + if ( tlist [ i*3+ 2 ] == v1 && tlist [ i*3+ 1 ] == v2 ) + { + new_vlist [ (*new_vc)++ ] = tlist [ i*3+ 0 ] ; + follow ( i, 0, 1, !backwards, len, new_vlist, new_vc ) ; + return ; + } + } + } +} + + +static ssgLeaf** build_leaf_list ( ssgEntity *ent, ssgLeaf** leaf_list=0 ) +{ + enum { MAX_LEAF_COUNT = 10000 } ; + static int leaf_count ; + + if ( leaf_list == NULL ) + { + leaf_list = new ssgLeaf* [ MAX_LEAF_COUNT+1 ] ; + leaf_count = 0 ; + leaf_list [ leaf_count ] = NULL ; + } + + if ( ent -> isAKindOf ( ssgTypeBranch () ) ) + { + ssgBranch *b_ent = (ssgBranch *) ent ; + for ( ssgEntity *k = b_ent -> getKid ( 0 ) ; k != NULL ; + k = b_ent -> getNextKid () ) + { + build_leaf_list ( k, leaf_list ) ; + } + } + else if ( ent -> isAKindOf ( ssgTypeLeaf () ) ) + { + ssgLeaf *l = (ssgLeaf *) ent ; + + bool found = false ; + for ( int i = 0 ; leaf_list [ i ] != NULL ; i ++ ) + { + if ( leaf_list [ i ] == l ) + { + found = true ; + break ; + } + } + + if ( !found && leaf_count < MAX_LEAF_COUNT ) + { + leaf_list [ leaf_count ++ ] = l ; + leaf_list [ leaf_count ] = NULL ; + } + } + + return leaf_list ; +} + +/* +* NAME +* ssgArrayTool +* +* DESCRIPTION +* Process the graph and convert all leaf entities into vertex arrays. +* +* Each vertex is described by a single index (instead of different +* indices into the v, vc, vt-arrays). This may introduce new redundant +* vertex data into the data set, which may seem silly. However, when +* rendering through OpenGL, it is in most cases the optimal solution +* to use indexed vertex arrays, which only have ONE index for all +* the vertex data. +* +* INPUTS +* +* ent - the entity to process +* +* vtol - an array of 3 floats used to specify tolerances +* vtol[0] - tolerance value for vertices +* vtol[1] - tolerance for colours +* vtol[2] - tolerance for texture coordinates +* +* make_normals - if true then averaged vertex normals are computed +*/ +void ssgArrayTool ( ssgEntity *ent, float* vtol, bool make_normals ) +{ + current_vtol = vtol? vtol: optimise_vtol ; + + ssgLeaf** leaf_list = build_leaf_list ( ent ) ; + for ( int i = 0 ; leaf_list [ i ] != NULL ; i ++ ) + { + ssgLeaf *l = leaf_list [ i ] ; + ssgState *s = l -> getState() ; + int cf = l -> getCullFace() ; + + OptVertexList list ( s, cf ) ; + list . add ( l ) ; + + if ( list . tnum > 0 ) /* If all the triangles are degenerate maybe */ + { + ssgIndexArray *new_index = new ssgIndexArray ( list . tnum * 3 ) ; + ssgVertexArray *new_coords = new ssgVertexArray ( list . vnum ) ; + ssgTexCoordArray *new_texcoords = new ssgTexCoordArray ( list . vnum ) ; + ssgColourArray *new_colours = new ssgColourArray ( list . vnum ) ; + ssgNormalArray *new_normals = 0 ; + + if ( make_normals ) + { + list . makeNormals () ; + new_normals = new ssgNormalArray ( list . vnum ) ; + } + + for ( int t = 0 ; t < list . tnum ; t++ ) + { + new_index -> add ( list . tlist [ t*3+ 0 ] ) ; + new_index -> add ( list . tlist [ t*3+ 1 ] ) ; + new_index -> add ( list . tlist [ t*3+ 2 ] ) ; + } + + for ( int v = 0 ; v < list . vnum ; v++ ) + { + new_coords -> add ( list . vlist[ v ]->vertex ) ; + new_texcoords-> add ( list . vlist[ v ]->texcoord ) ; + new_colours -> add ( list . vlist[ v ]->colour ) ; + if ( make_normals ) + new_normals -> add ( list . vlist[ v ]->normal ) ; + } + + ssgVtxArray *new_varray = new ssgVtxArray ( GL_TRIANGLES, + new_coords, new_normals, new_texcoords, new_colours, new_index ) ; + new_varray -> setState ( list.state ) ; + new_varray -> setCullFace ( list.cullface ) ; + + ssgBranch *p ; + + /* + Add the new leaf + */ + for ( p = l -> getParent ( 0 ) ; p != NULL ; + p = l -> getNextParent () ) + p -> addKid ( new_varray ) ; + + /* + Remove the old leaf + */ + for ( p = new_varray -> getParent ( 0 ) ; p != NULL ; + p = new_varray -> getNextParent () ) + p -> removeKid ( l ) ; + } + } + delete[] leaf_list ; + + ent -> recalcBSphere () ; +} + +void ssgStripify ( ssgEntity *ent ) +{ + current_vtol = optimise_vtol ; + + /* + Walk down until we find a leaf node, then + back up one level, collect all the ssgVtxTables + into one big heap and triangulate them. + */ + + if ( ent -> isAKindOf ( ssgTypeLeaf () ) ) + return ; + + ssgBranch *b_ent = (ssgBranch *) ent ; + + /* + Count number of unique materials (and cull-facedness) + - make a list of them. Recursively stripify non-leaf nodes. + */ + + int stot = 0 ; + ssgState **slist = new ssgState *[ b_ent -> getNumKids () ] ; + int *cflist = new int [ b_ent -> getNumKids () ] ; + + for ( ssgEntity *k = b_ent -> getKid ( 0 ) ; k != NULL ; + k = b_ent -> getNextKid () ) + { + if ( k -> isAKindOf ( ssgTypeVtxTable () ) ) + { + GLenum thisType = ((ssgVtxTable *)k)->getPrimitiveType (); + if ((thisType != GL_POINTS) && (thisType != GL_LINES) && + (thisType != GL_LINE_STRIP) && (thisType != GL_LINE_LOOP)) + { + int i ; + ssgState *s = ((ssgLeaf *) k ) -> getState() ; + int c = ((ssgLeaf *) k ) -> getCullFace() ; + + for ( i = 0 ; i < stot ; i++ ) + if ( s == slist [ i ] && c == cflist [ i ] ) + break ; + + if ( i >= stot ) + { + slist [ i ] = s ; + cflist [ i ] = c ; + stot++ ; + } + } + } + else + if ( k -> isAKindOf ( ssgTypeBranch () ) ) + ssgStripify ( k ) ; + } + + /* + Now, for each unique state, grab all the VtxTable leaf nodes + and smoosh them into one. + */ + + for ( int i = 0 ; i < stot ; i++ ) + { + /* + Put it into a triangle-oriented structure and + then do stripifying and average normal generation. + + Ick! + */ + + OptVertexList list ( slist [ i ], cflist [ i ] ) ; + + ssgEntity *k = b_ent -> getKid ( 0 ) ; + + while ( k != NULL ) + { + if ( k -> isAKindOf ( ssgTypeVtxTable () ) && + ((ssgLeaf *) k ) -> getState() == slist [ i ] && + ((ssgLeaf *) k ) -> getCullFace() == cflist [ i ] ) + { + GLenum thisType = ((ssgVtxTable *)k)->getPrimitiveType (); + if ((thisType != GL_POINTS) && (thisType != GL_LINES) && + (thisType != GL_LINE_STRIP) && (thisType != GL_LINE_LOOP)) + { list . add ( (ssgVtxTable *) k ) ; + b_ent -> removeKid ( k ) ; + k = b_ent -> getKid ( 0 ) ; + } + else + k = b_ent -> getNextKid () ; + } + else + k = b_ent -> getNextKid () ; + } + + if ( list . tnum == 0 ) /* If all the triangles are degenerate maybe */ + continue ; + + /* + So, now we have all the important information sucked out of + all those nodes and safely tucked away in the OptVertexList + + Let's take this opportunity to compute vertex normals. + */ + + list . makeNormals () ; + + /* + Find the least connected triangle. + Use it as the starting point. + */ + + short tleast, nleast ; + + while ( list . getLeastConnected ( & tleast, & nleast ) ) + { + /* OK, we have our starting point - follow where it + leads - but which way to start? We need two vertices + with at least two references - and not the least + referenced vertex please. */ + + short *new_vlist = new short [ list.tnum * 3 ] ; + short new_vc = 0 ; + + int striplength = 0 ; + + if ( nleast == list.tlist[tleast*3+0] ) + { + new_vlist [ new_vc++ ] = list.tlist [ tleast*3+ 0 ] ; + new_vlist [ new_vc++ ] = list.tlist [ tleast*3+ 1 ] ; + new_vlist [ new_vc++ ] = list.tlist [ tleast*3+ 2 ] ; + list . follow ( tleast, 1, 2, FALSE, &striplength, new_vlist, & new_vc ) ; + } + else + if ( nleast == list.tlist[tleast*3+1] ) + { + new_vlist [ new_vc++ ] = list.tlist [ tleast*3+ 1 ] ; + new_vlist [ new_vc++ ] = list.tlist [ tleast*3+ 2 ] ; + new_vlist [ new_vc++ ] = list.tlist [ tleast*3+ 0 ] ; + list . follow ( tleast, 2, 0, FALSE, &striplength, new_vlist, & new_vc ) ; + } + else + if ( nleast == list.tlist[tleast*3+2] ) + { + new_vlist [ new_vc++ ] = list.tlist [ tleast*3+ 2 ] ; + new_vlist [ new_vc++ ] = list.tlist [ tleast*3+ 0 ] ; + new_vlist [ new_vc++ ] = list.tlist [ tleast*3+ 1 ] ; + list . follow ( tleast, 0, 1, FALSE, &striplength, new_vlist, & new_vc ) ; + } + else + ulSetError ( UL_WARNING, "Tleast doesn't contain nleast!" ) ; + + ssgVertexArray *new_coords = new ssgVertexArray ( new_vc ) ; + ssgNormalArray *new_normals = new ssgNormalArray ( new_vc ) ; + ssgTexCoordArray *new_texcoords = new ssgTexCoordArray ( new_vc ) ; + ssgColourArray *new_colours = new ssgColourArray ( new_vc ) ; + + for ( int m = 0 ; m < new_vc ; m++ ) + { + new_coords -> add ( list.vlist[new_vlist[m]]->vertex ) ; + new_normals -> add ( list.vlist[new_vlist[m]]->normal ) ; + new_texcoords-> add ( list.vlist[new_vlist[m]]->texcoord ) ; + new_colours -> add ( list.vlist[new_vlist[m]]->colour ) ; + } + + delete [] new_vlist ; + + ssgVtxTable *new_vtable = new ssgVtxTable ( GL_TRIANGLE_STRIP, + new_coords, new_normals, new_texcoords, new_colours ) ; + new_vtable -> setState ( list.state ) ; + new_vtable -> setCullFace ( list.cullface ) ; + + b_ent -> addKid ( new_vtable ) ; + } + } + + delete [] slist ; + delete [] cflist ; +} + + +/* + These routines are essentially non-realtime tree optimisations. +*/ + +static void safe_replace_kid ( ssgBranch *parent, ssgEntity *old_kid, ssgEntity *new_kid ) +{ + /* + Replace old_kid by new_kid in a "safe" manner. + new_kid may be null, in which case old_kid is removed. + If parent is null then loop over all parents of old_kid. + */ + + if ( old_kid == new_kid ) + return ; + + if ( parent == NULL ) + { + int n = old_kid -> getNumParents () ; + while ( n-- > 0 ) + safe_replace_kid ( old_kid -> getParent ( 0 ), old_kid, new_kid ) ; + return ; + } + + // assert ( parent -> searchForKid ( old_kid ) >= 0 ) ; + + if ( new_kid == NULL ) + { + if ( parent -> isAKindOf ( ssgTypeSelector () ) ) + { + /* cannot remove kids from selectors */ + parent -> replaceKid ( old_kid, new ssgInvisible ) ; + } + else + { + parent -> removeKid ( old_kid ) ; + } + } + else + { + parent -> replaceKid ( old_kid, new_kid ) ; + } +} + +static void strip ( ssgEntity *ent ) +{ + /* + Strip off all branches with no kids - and snip out all + simple branches with just one kid. + A node with user data is always left unchanged. + */ + + if ( ! ent -> isAKindOf ( ssgTypeBranch () ) ) + return ; + + ssgBranch *b_ent = (ssgBranch *) ent ; + + for ( ssgEntity *k = b_ent -> getKid ( 0 ) ; k != NULL ; + k = b_ent -> getNextKid () ) + strip ( k ) ; + + switch ( b_ent -> getNumKids () ) + { + case 0: + if ( b_ent -> getUserData() == NULL && b_ent -> getName () == NULL ) + safe_replace_kid ( NULL, b_ent, NULL ) ; + break; + + case 1: + if ( b_ent -> isA ( ssgTypeBranch () ) && + b_ent -> getUserData () == NULL ) + { + ssgEntity *k = b_ent -> getKid ( 0 ) ; + if ( b_ent -> getName () != NULL && k -> getName () != NULL ) + break; + if ( b_ent -> getName () != NULL ) + k -> setName ( b_ent -> getName () ) ; + + safe_replace_kid ( NULL, b_ent, k ) ; + } + else if ( ! b_ent -> isAKindOf ( ssgTypeSelector () ) && + b_ent -> getKid ( 0 ) -> isA ( ssgTypeBranch () ) && + b_ent -> getKid ( 0 ) -> getUserData () == NULL ) + { + ssgBranch *b_kid = (ssgBranch *) b_ent -> getKid ( 0 ) ; + for ( ssgEntity *k = b_kid -> getKid ( 0 ) ; k != NULL ; + k = b_kid -> getNextKid () ) + b_ent -> addKid ( k ) ; + b_ent -> removeKid ( b_kid ) ; + b_ent -> recalcBSphere () ; + } + break; + + default: + if ( b_ent -> isDirtyBSphere () ) + b_ent -> recalcBSphere () ; + } +} + +void flatten ( ssgBranch *parent, ssgEntity *ent, sgMat4 mat ) +{ + /* + Move all transforms down to the leaf nodes and + then multiply them out. You need to strip() the + tree after calling this. + */ + + sgMat4 mat2 ; + + /* + The following nodes may (currently) not be flattened: + - ssgCutout, + - ssgRangeSelector, and + - ssgTransform with user data. + */ + if ( ent -> isAKindOf ( ssgTypeCutout () ) || + ent -> isAKindOf ( ssgTypeRangeSelector () ) || + ( ent -> isA ( ssgTypeTransform () ) && + ent -> getUserData () != NULL ) ) + { + /* Insert a transform node if needed. */ + if ( mat != NULL ) { + ssgTransform *tr = new ssgTransform ; + tr -> setTransform ( mat ) ; + tr -> addKid ( ent ) ; + safe_replace_kid ( parent, ent, tr ) ; + } + + /* Traverse as usual. */ + if ( ent -> isAKindOf ( ssgTypeBranch () ) ) + { + ssgBranch *b_ent = (ssgBranch *) ent ; + for ( ssgEntity *k = b_ent -> getKid ( 0 ) ; k != NULL ; + k = b_ent -> getNextKid () ) + flatten ( b_ent, k, NULL ) ; + } + + return ; + } + + /* + Clone the node if needed (there is no need to clone it recursively, + especially not past unflattable nodes). + */ + if ( ent -> getRef () > 1 && mat != NULL ) + { + ssgEntity *clone = (ssgEntity *) ent -> clone ( SSG_CLONE_GEOMETRY | + SSG_CLONE_USERDATA ) ; + safe_replace_kid ( parent, ent, clone ) ; + ent = clone ; + } + + /* + Apply the transformation on leaf nodes. + */ + if ( ent -> isAKindOf ( ssgTypeLeaf () ) ) + { + if ( mat != NULL ) + ((ssgLeaf *) ent) -> transform ( mat ) ; + return ; + } + + /* + Replace transform nodes with simple branches. + */ + if ( ent -> isAKindOf ( ssgTypeTransform () ) ) + { + ssgTransform *t_ent = (ssgTransform *) ent ; + + t_ent -> getTransform ( mat2 ) ; + if ( mat != NULL ) + sgPostMultMat4 ( mat2, mat ) ; + + mat = sgClassifyMat4 ( mat2 ) != 0 ? mat2 : NULL ; + + ssgBranch *br = new ssgBranch ; + /* + FIXME! It would have been very neat to do: + br -> copy_from ( t_ent, 0 ) ; + */ + br -> setName ( t_ent -> getName () ) ; + for ( ssgEntity *k = t_ent -> getKid ( 0 ) ; k != NULL ; + k = t_ent -> getNextKid () ) + br -> addKid ( k ) ; + t_ent -> removeAllKids () ; + + safe_replace_kid ( NULL, ent, br ) ; + ent = br ; + } + + /* + Finally traverse the kids. + */ + if ( ent -> isAKindOf ( ssgTypeBranch () ) ) + { + ssgBranch *b_ent = (ssgBranch *) ent ; + for ( ssgEntity *k = b_ent -> getKid ( 0 ) ; k != NULL ; + k = b_ent -> getNextKid () ) + flatten ( b_ent, k, mat ) ; + } + +} + +void ssgFlatten ( ssgEntity *ent ) +{ + if ( ! ent -> isAKindOf ( ssgTypeBranch () ) ) + return ; + + ssgBranch *b_ent = (ssgBranch *) ent ; + sgVec4 *mat = NULL ; + sgMat4 xform, ident ; + + /* + If the top level node is a ssgTransform, then do not replace it; + instead load an identity transform and multiply out the matrix. + */ + + if ( b_ent -> isA ( ssgTypeTransform () ) && + b_ent -> getUserData () == NULL ) + { + sgMakeIdentMat4 ( ident ) ; + ((ssgTransform *) b_ent) -> getTransform ( xform ) ; + ((ssgTransform *) b_ent) -> setTransform ( ident ) ; + mat = xform ; + } + + /* + Since the top level node may not be removed, loop over the kids. + Done in two passes because *kid* may be removed. + */ + ssgEntity *kid; + + for ( kid = b_ent -> getKid ( 0 ) ; kid != NULL ; + kid = b_ent -> getNextKid () ) + flatten ( b_ent, kid, mat ) ; + + for ( kid = b_ent -> getKid ( 0 ) ; kid != NULL ; + kid = b_ent -> getNextKid () ) + strip ( kid ) ; + + if ( b_ent -> isDirtyBSphere () ) + b_ent -> recalcBSphere () ; +} + + +/* +* NAME +* ssgTransTool +* +* DESCRIPTION +* Apply a transform (translate, rotate, scale) to all verticies of a graph. +* +* INPUTS +* ent -- the entity to process +* trans -- transform +*/ +void ssgTransTool ( ssgEntity *ent, const sgMat4 trans ) +{ + if ( ent -> isAKindOf ( ssgTypeLeaf () ) ) + { + ((ssgLeaf *) ent) -> transform ( trans ) ; + return ; + } + + if ( ! ent -> isAKindOf ( ssgTypeBranch () ) ) + return ; + + ssgBranch *b_ent = (ssgBranch *) ent ; + sgMat4 mat, ident, xform ; + + sgCopyMat4 ( mat, trans ) ; + + if ( b_ent -> isA ( ssgTypeTransform () ) && + b_ent -> getUserData () == NULL ) + { + sgMakeIdentMat4 ( ident ) ; + ((ssgTransform *) b_ent) -> getTransform ( xform ) ; + ((ssgTransform *) b_ent) -> setTransform ( ident ) ; + sgPreMultMat4 ( mat, xform ) ; + } + + else if ( b_ent -> isAKindOf ( ssgTypeTransform () ) || + b_ent -> isAKindOf ( ssgTypeCutout () ) || + b_ent -> isAKindOf ( ssgTypeRangeSelector () ) ) + { + ulSetError ( UL_WARNING, + "ssgTransTool: Cannot handle this kind of node at top level." ) ; + return ; + } + + ssgEntity *kid; + for ( kid = b_ent -> getKid ( 0 ) ; kid != NULL ; + kid = b_ent -> getNextKid () ) + flatten ( b_ent, kid, mat ) ; + + for ( kid = b_ent -> getKid ( 0 ) ; kid != NULL ; + kid = b_ent -> getNextKid () ) + strip ( kid ) ; + + b_ent -> recalcBSphere () ; +} diff --git a/src/ssg/ssgParser.cxx b/src/ssg/ssgParser.cxx new file mode 100644 index 0000000..2557237 --- /dev/null +++ b/src/ssg/ssgParser.cxx @@ -0,0 +1,531 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgParser.cxx 2117 2007-09-13 23:21:09Z fayjf $ +*/ + +// +// File parser for SSG/PLIB +// Written by Dave McClurg (dpm@efn.org) in Feb-2000 +// extended by Wolfram Kuss (w_kuss@rz-online.de) in Nov-2000 + +// This is mainly an lexical analyzer that extracts tokens from ascii-files + +// Be sure to read the ssg-documentation, especially the chapter +// on loaders/writers + + +#define AM_IN_SSGPARSER_CXX 1 + +#include "ssgLocal.h" +#include "ssgParser.h" + + +static _ssgParserSpec default_spec = +{ + "\r\n\t ", // delim_chars_skipable + 0, // delim_chars_non_skipable + NULL, // pre_processor + 0, // open_brace_chars + 0, // close_brace_chars + '"', // quote_char + 0, // comment_char + "//" // comment_string +} ; + + +// Output an error +void _ssgParser::error( const char *format, ... ) +{ + char msgbuff[ 255 ]; + va_list argp; + + char* msgptr = msgbuff; + if (linenum) + { + msgptr += sprintf ( msgptr,"%s, line %d: ", + path, linenum ); + } + + va_start( argp, format ); + vsprintf( msgptr, format, argp ); + va_end( argp ); + + ulSetError ( UL_WARNING, "%s", msgbuff ) ; +} + + +// Output a message +void _ssgParser::message( const char *format, ... ) +{ + char msgbuff[ 255 ]; + va_list argp; + + char* msgptr = msgbuff; + if (linenum) + { + msgptr += sprintf ( msgptr,"%s, line %d: ", + path, linenum ); + } + + va_start( argp, format ); + vsprintf( msgptr, format, argp ); + va_end( argp ); + + ulSetError ( UL_DEBUG, "%s", msgbuff ) ; +} + +// Opens the file and does a few internal calculations based on the spec. +int _ssgParser::openFile( const char* fname, const _ssgParserSpec* _spec ) +// returns TRUE on success +{ + if ( !_spec ) _spec = &default_spec ; + + if ( _spec->comment_string != NULL ) + { assert ( _spec->comment_string [0] != 0 ); + } + + memset(this,0,sizeof(_ssgParser)); + memcpy( &spec, _spec, sizeof(spec) ); + ssgGetCurrentOptions () -> makeModelPath ( path, fname ) ; + fileptr = fopen( path, "rb" ); + if ( ! fileptr ) + { + error("cannot open file: %s",path); + return FALSE; + } + eof = FALSE; + // Calculate anyDelimiter and return. + anyDelimiter[0] = 0; + int length = 0; + if ( spec.delim_chars_skipable != NULL ) + { length +=strlen ( spec.delim_chars_skipable); + strcat(anyDelimiter, spec.delim_chars_skipable); + } + if ( spec.delim_chars_non_skipable != NULL ) + { length += strlen ( spec.delim_chars_non_skipable ) ; + strcat ( anyDelimiter, spec.delim_chars_non_skipable ) ; + } + if ( spec.open_brace_chars != NULL ) + { length +=strlen ( spec.open_brace_chars ); + strcat ( anyDelimiter, spec.open_brace_chars ); + } + if ( spec.close_brace_chars != NULL ) + { length +=strlen ( spec.close_brace_chars ) ; + strcat ( anyDelimiter, spec.close_brace_chars ) ; + } + assert ( length < MAX_DELIMITER_CHARS ); + return TRUE; +} + + +void _ssgParser::closeFile() +{ + fclose( fileptr ) ; + fileptr = 0 ; +} + +static char *EOF_string = "EOF reached"; +static char *EOL_string = "EOL reached"; + +char* _ssgParser::getNextToken( const char* name ) +// Fetches next token, even if it has to read over some empty or comment-only lines to get to it. +// Never returns NULL. Returns EOF_string on EOF. +{ + while(!( curtok < numtok )) + { //int startLevel = level; + //ulSetError(UL_DEBUG, "Forcing!"); + if(getLine( -999 ) == NULL) // -999 + { if ( name ) + error("missing %s",name) ; + return EOF_string; + } + assert(curtok==1); + curtok=0; // redo the get one token that getLine does + } + char* token = 0 ; + assert ( curtok < numtok ); + token = tokptr [ curtok++ ] ; + return(token) ; +} + +char *_ssgParser::peekAtNextToken( const char* name ) +// Like getNextToken, but doesn't remove the token from the input stream +{ + while(!( curtok < numtok )) + { //int startLevel = level; + //ulSetError(UL_DEBUG, "Forcing!"); + if(getLine( -999 ) == NULL) // -999 + { if ( name ) + error("missing %s",name) ; + return EOF_string; + } + assert(curtok==1); + curtok=0; // redo the get one token that getLine does + } + char* token = 0 ; + assert ( curtok < numtok ); + token = tokptr [ curtok ] ; + return(token) ; +} + + + +int _ssgParser::getNextFloat( SGfloat &retVal, const char* name ) +// returns TRUE on success +{ + char *endptr, *token = getNextToken(name); + retVal = SGfloat(strtod( token, &endptr)); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { error("The field %s should contain a floating point number but contains %s",name, token) ; + return FALSE; + } +} + +int _ssgParser::getNextInt( int & retVal, const char* name ) +// returns TRUE on success +{ + char *endptr, *token = getNextToken(name); + retVal = int(strtol( token, &endptr, 10)); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { error("The field %s should contain an integer number but contains %s",name, token) ; + return FALSE; + } +} + +int _ssgParser::getNextString(char *&retVal, const char* name ) // returns TRUE on success +// wk: This is only for strings where we know they are inside spec.quote_chars, correct? +{ + char *token = getNextToken( NULL ); + + if ( spec.quote_char && *token == spec.quote_char ) + { + //knock off the quotes + token++ ; + int len = strlen( token ) ; + if (len > 0 && token[len-1] == spec.quote_char) + token[len-1] = 0; + } + + if( name != NULL && strcmp( token, name ) ) + { + error("Expected %s but got %s instead", name, token) ; + return FALSE; + } + + retVal = token; + return TRUE; +} + +int _ssgParser::getNextUInt( unsigned int & retVal, const char* name ) +// returns TRUE on success +{ char *endptr, *token = getNextToken(name); + retVal = (unsigned int)(strtol( token, &endptr, 10)); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { error("The field %s should contain an integer number but contains %s",name, token) ; + return FALSE; + } +} + + +void _ssgParser::expectNextToken( const char* name ) +// Swallows the next token. If it is not name, then there is an error message +{ + char* token = getNextToken(name); + if (strcmp(token,name)) + error("missing %s",name) ; +} + +// internal function. A token consisting of a single char has been found. +// This is copied to a new buffer, so that I have the space to add the 0. +void _ssgParser::addOneCharToken ( char *ptr ) +{ + assert( (long)onechartokenbuf_ptr- (long)onechartokenbuf < 4096 ) ; // Buffer overflow + + onechartokenbuf_ptr [ 0 ] = *ptr; + onechartokenbuf_ptr [ 1 ] = 0; + tokptr [ numtok++ ] = onechartokenbuf_ptr; + onechartokenbuf_ptr += 2; // prepare for nect onechartoken +} + +static const char *mystrchr( const char *string, int c ) +// like strchr, but string may be NULL +{ + if (string == NULL ) + return NULL; + else + return strchr( string, c ); +} + + +// gets the next line (no matter where it is), without tokenizing it +// useful for parsing text-formatted files which are identified by +// comments at the very beginning +char* _ssgParser::getRawLine() +// return NULL on eof +{ + tokbuf[0]=0; + + //get the next line with something on it + if ( fgets ( linebuf, sizeof(linebuf), fileptr ) == NULL ) + { + eol = TRUE; + eof = TRUE; + return(0) ; + } + + memcpy( tokbuf, linebuf, sizeof(linebuf) ) ; + + return tokbuf; +} + +// wk: This works and is IMHO robust. +// However, I feel it could be smaller, more elegant and readable. +char* _ssgParser::getLine( int startLevel ) +// return NULL on eof or if (level < startLevel) +{ + // throw away old tokens + tokbuf [ 0 ] = 0 ; + numtok = 0 ; + curtok = 0 ; + eol = FALSE; + onechartokenbuf_ptr = onechartokenbuf ; + + //get the next line with something on it + char* ptr = tokbuf , *tptr; + while ( *ptr == 0 ) + { + linenum++ ; + if ( fgets ( linebuf, sizeof(linebuf), fileptr ) == NULL ) + { eol = TRUE; + eof = TRUE; + return(0) ; + } + if(spec.pre_processor != NULL) + spec.pre_processor (linebuf); + memcpy( tokbuf, linebuf, sizeof(linebuf) ) ; + ptr = tokbuf ; + + // check for comments + tptr=strchr(tokbuf, spec.comment_char); + if ( tptr != NULL ) + *tptr = 0; + if ( spec.comment_string != NULL ) + { + tptr=strstr(tokbuf, spec.comment_string); + if ( tptr != NULL ) + *tptr = 0; + } + + //skip delim_chars + if ( spec.delim_chars_skipable != NULL ) + while ( *ptr && strchr(spec.delim_chars_skipable,*ptr) ) + ptr++ ; + } + + //tokenize the line + numtok = 0 ; + while ( *ptr ) + { + //skip delim_chars + if ( spec.delim_chars_skipable != NULL ) + while ( *ptr && strchr(spec.delim_chars_skipable,*ptr) ) + ptr++ ; + + if ( *ptr == 0 ) + break; // only skipable stuff left, dont create another token. + + // now unnessary?: + if ( *ptr == spec.comment_char ) + { + *ptr = 0 ; + break; + } + + //count the token + tokptr [ numtok++ ] = ptr ; + + //handle quoted string + if ( spec.quote_char && *ptr == spec.quote_char ) + { + ptr++ ; + while ( *ptr && *ptr != spec.quote_char ) + ptr++ ; + } + + //adjust level + if ( spec.open_brace_chars && *ptr && mystrchr(spec.open_brace_chars,*ptr) ) + level++ ; + else if ( spec.close_brace_chars && *ptr && mystrchr(spec.close_brace_chars,*ptr) ) + level-- ; + else + //find end of token + while ( *ptr && !strchr(anyDelimiter,*ptr) ) + ptr++ ; + + if ( *ptr != 0 ) + if ( ptr == tokptr [ numtok-1 ] ) + { // we dont want tokens of length zero + assert(NULL==mystrchr(spec.delim_chars_skipable,*ptr)); + // ptr is non-skipable, return it as token of length one + numtok--; // remove zero-length token + addOneCharToken ( ptr ) ; // and add new token instead + *ptr++ = 0; + continue; + } + + //mark end of token + if( *ptr && ( mystrchr(spec.delim_chars_non_skipable,*ptr) + || mystrchr(spec.open_brace_chars,*ptr) + || mystrchr(spec.close_brace_chars,*ptr) ) ) + { + // ptr is non-skipable, return it as token of length one + // additional to the one already in tokptr [ numtok-1 ]. + addOneCharToken ( ptr ) ; + *ptr++ = 0; + } + if ( spec.delim_chars_skipable != NULL ) + while ( *ptr && strchr(spec.delim_chars_skipable,*ptr) ) + *ptr++ = 0 ; + } + if (level >= startLevel) + return parseToken (0) ; + return 0 ; +} + + +char* _ssgParser::parseToken( const char* name ) +// returns the next token from the current line. +// Never returns NULL, but may return EOL_string +{ + char* token = EOL_string ; + if ( curtok < numtok ) + token = tokptr [ curtok++ ] ; + else + { eol = TRUE; + if ( name ) + error("missing %s",name) ; + } + return(token) ; +} + + +int _ssgParser::parseString(char *&retVal, const char* name ) // returns TRUE on success +// wk: This is only for strings where we know they are inside spec.quote_chars, correct? +{ + char* token = EOL_string ; + retVal = EOL_string ; + + if ( curtok >= numtok ) + { eol = TRUE; + if ( name ) + error("missing %s",name) ; + return FALSE; + } + + if ( numtok > 0 && spec.quote_char && *tokptr [ curtok ] == spec.quote_char ) + { + token = tokptr [ curtok++ ] ; + + //knock off the quotes + token++ ; + int len = strlen (token) ; + if (len > 0 && token[len-1] == spec.quote_char) + token[len-1] = 0 ; + } + else + { if ( name ) + error("missing %s",name) ; + return FALSE; + } + retVal = token; + return TRUE; +} + +int _ssgParser::parseDouble( double &retVal, const char* name ) +// returns TRUE on success +{ + char *endptr, *token = parseToken(name); + retVal = strtod( token, &endptr); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { error("The field %s should contain a floating point number but contains %s",name, token) ; + return FALSE; + } +} + +int _ssgParser::parseFloat( SGfloat &retVal, const char* name ) +// returns TRUE on success +{ + char *endptr, *token = parseToken(name); + retVal = SGfloat(strtod( token, &endptr)); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { error("The field %s should contain a floating point number but contains %s",name, token) ; + return FALSE; + } +} + +int _ssgParser::parseInt(int &retVal, const char* name ) +// returns TRUE on success +{ + char *endptr, *token = parseToken(name); + retVal = int(strtol( token, &endptr, 10)); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { error("The field %s should contain an integer number but contains %s",name, token) ; + return FALSE; + } +} + +int _ssgParser::parseUInt(unsigned int &retVal, const char* name ) +// returns TRUE on success +{ + char *endptr, *token = parseToken(name); + long l = strtol( token, &endptr, 10); + if (l<0) + message("The field %s should contain an UNSIGNED integer number but contains %s",name, token) ; + retVal = (unsigned int)(l); + if ( (endptr == NULL) || (*endptr == 0)) + return TRUE; + else + { error("The field %s should contain an integer number but contains %s",name, token) ; + return FALSE; + } +} + + + +void _ssgParser::expect( const char* name ) +// Swallows the next token. If it is not name, then there is an error message +{ + char* token = parseToken(name); + if (strcmp(token,name)) + error("missing %s",name) ; +} diff --git a/src/ssg/ssgParser.h b/src/ssg/ssgParser.h new file mode 100644 index 0000000..1f74c7a --- /dev/null +++ b/src/ssg/ssgParser.h @@ -0,0 +1,116 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgParser.h 1970 2004-10-04 08:11:26Z wolfram_kuss $ +*/ + + +#ifndef _INCLUDED_SSGPARSER_H_ +#define _INCLUDED_SSGPARSER_H_ + + +// Be sure to read the ssg-documentation, especially the chapter +// on loaders/writers + + +typedef void PreProcessorFunctionType(char *line); + +// The _ssgParserSpec contains the rules how to extract the tokens: + +struct _ssgParserSpec +{ // delimiters; Thats is, chars that delimit tokens: + const char* delim_chars_skipable ; // these are "swallowed" by the parser + const char* delim_chars_non_skipable ; // These are handed to the app. + PreProcessorFunctionType *pre_processor; // After reading a line, it is first given to the preprocessor to tweak it in place. + const char* open_brace_chars ; + const char* close_brace_chars ; + char quote_char ; + char comment_char ; // For ex. ';' or '#' + const char* comment_string; // For example "//" +} ; + + +class _ssgParser +{ + enum { MAX_TOKENS = 50000 } ; + enum { MAX_DELIMITER_CHARS = 5000 } ; + + char path[ 256 ] ; + _ssgParserSpec spec ; + FILE* fileptr ; + + int linenum ; + char linebuf[ 50000 ] ; + char tokbuf[ 50000 ] ; + char anyDelimiter [ MAX_DELIMITER_CHARS ] ; + char* tokptr[ MAX_TOKENS ] ; + int numtok ; + int curtok ; + + char onechartokenbuf [ 50000 ]; + char *onechartokenbuf_ptr; + void addOneCharToken ( char *ptr ) ; + +public : +// ************************** general ************************** + int openFile( const char* fname, const _ssgParserSpec* spec = 0 ); // TRUE = success + void closeFile(); + + void error( const char *format, ... ); + void message( const char *format, ... ); + + int eof ; // end of file reached yet? + int eol ; // end of line reached yet? +// ************************** line-by-line API ************************** + int level; + + char* getLine( int startLevel=0 ); // may return NULL + char* getRawLine(); + // All the name -parameters are only for error-messages + + // The parse... - functions get the next token from the current line + // that was fetched with getLine and return the token as + // char*, SGfloat, int, unsigned int or char* + + char* parseToken( const char* name ); + // These return TRUE on success: + int parseFloat( SGfloat &retVal, const char* name ); + int parseDouble( double &retVal, const char* name ); + int parseInt(int &retVal, const char* name ); + int parseUInt(unsigned int &retVal, const char* name ); + int parseString(char *&retVal, const char* name ); + + void expect( const char* name ); + +// ************************** line structure independant API ************************** + + // These six functions get the next token - regardless of what line it is on + char *getNextToken( const char* name ); + char *peekAtNextToken( const char* name ); + // These return TRUE on success: + int getNextFloat( SGfloat &retVal, const char* name ); + int getNextInt( int & retVal, const char* name ); + int getNextString(char *&retVal, const char* name ); + int getNextUInt( unsigned int & retVal, const char* name ); + void expectNextToken( const char* name ); + } ; + + +#endif diff --git a/src/ssg/ssgRangeSelector.cxx b/src/ssg/ssgRangeSelector.cxx new file mode 100644 index 0000000..3577dbe --- /dev/null +++ b/src/ssg/ssgRangeSelector.cxx @@ -0,0 +1,200 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgRangeSelector.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "ssgLocal.h" + +void ssgRangeSelector::copy_from ( ssgRangeSelector *src, int clone_flags ) +{ + ssgSelector::copy_from ( src, clone_flags ) ; + + additive = src -> isAdditive () ; + + for ( unsigned int i = 0 ; i < 33 ; i++ ) + rng_list [ i ] = src -> getRange ( i ) ; +} + + +ssgBase *ssgRangeSelector::clone ( int clone_flags ) +{ + ssgRangeSelector *b = new ssgRangeSelector ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgRangeSelector::ssgRangeSelector (void) +{ + type = ssgTypeRangeSelector () ; + additive = FALSE ; + rng_list[0] = 0.0f ; + + for ( int i = 1 ; i < 33 ; i++ ) + rng_list[i] = SG_MAX ; +} + +ssgRangeSelector::~ssgRangeSelector (void) +{ +} + +void ssgRangeSelector::cull ( sgFrustum *f, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_CULL ) ) + return ; + + int cull_result = cull_test ( f, m, test_needed ) ; + + if ( cull_result == SSG_OUTSIDE ) + return ; + + float range = sgLengthVec3 ( m [ 3 ] ) ; + + if ( range < rng_list [ 0 ] ) /* Too close */ + { + select ( 0 ) ; + return ; + } + + unsigned int sel = 0 ; + + for ( int i = 1 ; i < 33 ; i++ ) + { + ssgEntity *e = getKid ( i-1 ) ; + + if ( e == NULL || rng_list [ i ] == SG_MAX ) + { + select ( 0 ) ; + return ; + } + + if ( e != NULL && range < rng_list [ i ] ) + { + e -> cull ( f, m, cull_result != SSG_INSIDE ) ; + sel |= 1 << (i-1) ; + + if ( ! additive ) + { + selectStep ( i-1 ) ; + return ; + } + } + } + + select ( sel ) ; + + postTravTests ( SSGTRAV_CULL ) ; +} + + +void ssgRangeSelector::hot ( sgVec3 sp, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_HOT ) ) + return ; + + if ( additive ) + ssgBranch::hot ( sp, m, test_needed ) ; + else + { + /* No point in testing this node since it only has one child */ + + _ssgPushPath ( this ) ; + + ssgEntity *e = getKid ( 0 ) ; + + if ( e != NULL ) + e -> hot ( sp, m, test_needed ) ; + + _ssgPopPath () ; + } + + postTravTests ( SSGTRAV_HOT ) ; +} + + +void ssgRangeSelector::los ( sgVec3 sp, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_LOS ) ) + return ; + + if ( additive ) + ssgBranch::los ( sp, m, test_needed ) ; + else + { + /* No point in testing this node since it only has one child */ + + _ssgPushPath ( this ) ; + + ssgEntity *e = getKid ( 0 ) ; + + if ( e != NULL ) + e -> los ( sp, m, test_needed ) ; + + _ssgPopPath () ; + } + + postTravTests ( SSGTRAV_LOS ) ; +} + +void ssgRangeSelector::isect ( sgSphere *sp, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_ISECT ) ) + return ; + + if ( additive ) + ssgBranch::isect ( sp, m, test_needed ) ; + else + { + /* No point in testing this node since it only has one child */ + + _ssgPushPath ( this ) ; + + ssgEntity *e = getKid ( 0 ) ; + + if ( e != NULL ) + e -> isect ( sp, m, test_needed ) ; + + _ssgPopPath () ; + } + + postTravTests ( SSGTRAV_ISECT ) ; +} + + + +int ssgRangeSelector::load ( FILE *fd ) +{ + _ssgReadInt ( fd, & additive ) ; + _ssgReadFloat ( fd, 33, rng_list ) ; + + return ssgSelector::load(fd) ; +} + +int ssgRangeSelector::save ( FILE *fd ) +{ + _ssgWriteInt ( fd, additive ) ; + _ssgWriteFloat ( fd, 33, rng_list ) ; + + return ssgSelector::save(fd) ; +} + + diff --git a/src/ssg/ssgRoot.cxx b/src/ssg/ssgRoot.cxx new file mode 100644 index 0000000..a94e594 --- /dev/null +++ b/src/ssg/ssgRoot.cxx @@ -0,0 +1,61 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgRoot.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "ssgLocal.h" + +void ssgRoot::copy_from ( ssgRoot *src, int clone_flags ) +{ + ssgBranch::copy_from ( src, clone_flags ) ; +} + +ssgBase *ssgRoot::clone ( int clone_flags ) +{ + ssgRoot *b = new ssgRoot ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgRoot::ssgRoot (void) +{ + type = ssgTypeRoot () ; +} + +ssgRoot::~ssgRoot (void) +{ +} + + +int ssgRoot::load ( FILE *fd ) +{ + return ssgBranch::load(fd) ; +} + +int ssgRoot::save ( FILE *fd ) +{ + return ssgBranch::save(fd) ; +} + + + diff --git a/src/ssg/ssgSave3ds.cxx b/src/ssg/ssgSave3ds.cxx new file mode 100644 index 0000000..8db1dc3 --- /dev/null +++ b/src/ssg/ssgSave3ds.cxx @@ -0,0 +1,511 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgSave3ds.cxx 2108 2006-12-11 20:42:05Z fayjf $ +*/ + +/******************************************************* + ** ssgSave3ds.cxx + ** + ** Written by Per Liedman (liedman@home.se) + ** Last updated: 2001-02-25 + ** + ** This was written to be a part of Stephen J Bakers + ** PLIB (http://plib.sourceforge.net) + *******************************************************/ + +/* This writer is highly experimental. It has *not* been tested with + 3D Studio. Please note that this writer does not save hierarchal + information */ + +#include +#include "ssgLocal.h" +#include "ssg3ds.h" + +static FILE* save_fd; + +static const int MAX_MATERIALS = 128; +static ssgSimpleState* mat[MAX_MATERIALS]; +static int mat_count; + +static void writeChunkHeader( unsigned short id, unsigned int length ) { + ulEndianWriteLittle16( save_fd, id ); + ulEndianWriteLittle32( save_fd, length ); +} + +class _ssgSave3dsData { +public: + _ssgSave3dsData( void* ptr, size_t memb_size, size_t nmemb ) : + swabbed(false), memb_size(memb_size), nmemb(nmemb), ptr(ptr), next(NULL) + { } + ~_ssgSave3dsData() { + if (next != NULL) { + delete next; + } + + free(ptr); + } + + unsigned int size() { + unsigned int s = memb_size*nmemb; + if (next != NULL) { + s += next->size(); + } + return s; + } + + void write() { + if (!swabbed) { + switch (memb_size) { + case 2: + ulEndianLittleArray16( (unsigned short*)ptr, nmemb ); + break; + case 4: + ulEndianLittleArray32( (unsigned int*)ptr, nmemb ); + break; + default: + break; + } + + swabbed = true; + } + + fwrite( ptr, memb_size, nmemb, save_fd ); + if (next != NULL) { + next->write(); + } + } + + void append( _ssgSave3dsData* next ) { + this->next = next; + } + +protected: + bool swabbed; + + size_t memb_size, nmemb; + void* ptr; + _ssgSave3dsData* next; +}; + +class _ssgSave3dsChunk { +public: + _ssgSave3dsChunk( unsigned short id ) : + id(id), first_data(NULL), last_data(NULL), next_sibling(NULL), + first_kid(NULL), last_kid(NULL) {} + + ~_ssgSave3dsChunk() { + if (first_data != NULL) + delete first_data; + if (next_sibling != NULL) + delete next_sibling; + if (first_kid != NULL) + delete first_kid; + } + + void addData( _ssgSave3dsData* data ) { + if (first_data == NULL) { + first_data = last_data = data; + } else { + last_data->append(data); + last_data = data; + } + } + + void addKid( _ssgSave3dsChunk* kid ) { + if (first_kid == NULL) { + first_kid = last_kid = kid; + } else { + last_kid->next_sibling = kid; + last_kid = kid; + } + } + + void addSibling( _ssgSave3dsChunk* sibling ) { + sibling->next_sibling = next_sibling; + next_sibling = sibling; + } + + unsigned int size() { + unsigned int s = 6; + if (first_data != NULL) + s += first_data->size(); + + _ssgSave3dsChunk* kid = first_kid; + while (kid != NULL) { + s += kid->size(); + kid = kid->next_sibling; + } + + return s; + } + + void write() { + unsigned int s = size(); + writeChunkHeader(id, s); + + if (first_data != NULL) { + first_data->write(); + } + + _ssgSave3dsChunk* kid = first_kid; + while (kid != NULL) { + kid->write(); + kid = kid->next_sibling; + } + } + +protected: + unsigned short id; + _ssgSave3dsData *first_data, *last_data; + _ssgSave3dsChunk *next_sibling; + _ssgSave3dsChunk *first_kid, *last_kid; +}; + +static char* get_material_name( ssgSimpleState *state ) { + static char matnamebuff[16]; + + if (state->getName() != NULL) { + return state->getName(); + } else { + for (int i = 0; i < mat_count; i++) { + if (state == mat[i]) { + sprintf(matnamebuff, "Material #%d", i+1); + return matnamebuff; + } + } + + ulSetError(UL_WARNING, "ssgSave3ds: Material not found."); + return NULL; + } +} + +static _ssgSave3dsChunk* create_vertex_chunk( ssgLeaf* leaf, + sgMat4 transform ) { + _ssgSave3dsChunk* vertexlist = new _ssgSave3dsChunk( CHUNK_VERTLIST ); + + unsigned short *num_verts; + _ssgSave3dsData *nverts; + float* vdata; + + num_verts = new unsigned short; + *num_verts = leaf->getNumVertices(); + nverts = new _ssgSave3dsData(num_verts, 2, 1); + + vdata = new float[ *num_verts * 3]; + for (int i = 0; i < *num_verts; i++) { + sgXformPnt3(&vdata[i*3], leaf->getVertex(i), transform); + } + _ssgSave3dsData *vertices = new _ssgSave3dsData(vdata, 4, + *num_verts * 3); + vertexlist->addData(nverts); + vertexlist->addData(vertices); + + return vertexlist; +} + +static _ssgSave3dsChunk* create_maplist_chunk( ssgLeaf* leaf ) { + _ssgSave3dsChunk* maplist = new _ssgSave3dsChunk( CHUNK_MAPLIST ); + + unsigned short *num_verts; + _ssgSave3dsData *nverts; + float* vdata; + + num_verts = new unsigned short; + *num_verts = leaf->getNumTexCoords(); + nverts = new _ssgSave3dsData(num_verts, 2, 1); + + vdata = new float[ *num_verts * 2]; + for (int i = 0; i < *num_verts; i++) { + sgCopyVec2(&vdata[i*2], leaf->getTexCoord(i)); + } + _ssgSave3dsData *mapdata = new _ssgSave3dsData(vdata, 4, + *num_verts * 2); + maplist->addData(nverts); + maplist->addData(mapdata); + + return maplist; +} + +static _ssgSave3dsChunk* create_facemat_chunk( ssgLeaf* leaf ) { + char* matname = get_material_name( (ssgSimpleState*)leaf->getState() ); + char* namecopy = ulStrDup ( matname ) ; + + _ssgSave3dsData* namedata = new _ssgSave3dsData(namecopy, 1, + strlen(matname) + 1); + + unsigned short *fmdata = new unsigned short[ leaf->getNumTriangles() + 1 ]; + fmdata[0] = leaf->getNumTriangles(); + for (int i = 0; i < leaf->getNumTriangles(); i++) { + fmdata[i+1] = i; + } + + _ssgSave3dsData* fmlist = new _ssgSave3dsData(fmdata, 2, + leaf->getNumTriangles() + 1); + + _ssgSave3dsChunk* facemat = new _ssgSave3dsChunk( CHUNK_FACEMAT ); + facemat->addData(namedata); + facemat->addData(fmlist ); + + return facemat; +} + +static _ssgSave3dsChunk* create_facelist_chunk( ssgLeaf* leaf ) { + _ssgSave3dsChunk* facelist = new _ssgSave3dsChunk( CHUNK_FACELIST ); + + short* fdata = new short[leaf->getNumTriangles() * 4 + 1]; + fdata[0] = leaf->getNumTriangles(); + + for (int i = 0; i < leaf->getNumTriangles(); i++) { + leaf->getTriangle(i, + &fdata[i * 4 + 1], + &fdata[i * 4 + 2], + &fdata[i * 4 + 3]); + fdata[i * 4 + 4] = 7; // flag indicating anti-clockwise ordering (?) + } + _ssgSave3dsData *facedata = new _ssgSave3dsData(fdata, 2, + leaf->getNumTriangles()*4 + 1); + facelist->addData(facedata); + + facelist->addKid( create_facemat_chunk(leaf) ); + + return facelist; +} + +static _ssgSave3dsChunk* create_transform_chunk() { + // creates an identity transform + _ssgSave3dsChunk* transform = new _ssgSave3dsChunk( CHUNK_TRMATRIX ); + + float* matrix = new float[12]; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 3; j++) { + matrix[i * 3 + j] = (i == j) ? 1.0f : 0.0f; + } + } + + _ssgSave3dsData* matdata = new _ssgSave3dsData( matrix, 4, 12 ); + transform->addData(matdata); + + return transform; +} + +static void traverse_objects( ssgEntity* node, _ssgSave3dsChunk *parent, + sgMat4 transform ) { + if ( node->isAKindOf( ssgTypeTransform() ) ) { + sgMat4 local_transform; + ssgTransform *t_node = (ssgTransform*)node; + + t_node->getTransform(local_transform); + sgPostMultMat4( local_transform, transform ); + + for (ssgEntity* kid = t_node->getKid(0); kid != NULL; + kid = t_node->getNextKid()) { + traverse_objects( kid, parent, local_transform ); + } + } else if ( node->isAKindOf( ssgTypeBranch() ) ) { + ssgBranch *b_node = (ssgBranch*)node; + for (ssgEntity* kid = b_node->getKid(0); kid != NULL; + kid = b_node->getNextKid()) { + traverse_objects( kid, parent, transform ); + } + } else if ( node->isAKindOf( ssgTypeLeaf() ) ) { + ssgLeaf* l_node = (ssgLeaf*)node; + + _ssgSave3dsChunk *mesh = new _ssgSave3dsChunk(CHUNK_TRIMESH ); + + mesh -> addKid( create_vertex_chunk (l_node, transform) ); + mesh -> addKid( create_facelist_chunk(l_node) ); + mesh -> addKid( create_transform_chunk() ); + if (l_node->getNumTexCoords() > 0) { + mesh -> addKid( create_maplist_chunk(l_node) ); + } + + parent->addKid(mesh); + } +} + +static void create_objects_chunk( ssgEntity* ent, _ssgSave3dsChunk* parent ) { + _ssgSave3dsChunk* objs = new _ssgSave3dsChunk(CHUNK_OBJBLOCK); + static const char const_objname[] = "Object written by ssgSave3ds"; + + char *objname = ulStrDup ( const_objname ) ; + objs->addData( new _ssgSave3dsData(objname, 1, strlen(objname)+1) ); + parent->addKid(objs); + + sgMat4 ident; + sgMakeIdentMat4( ident ); + + traverse_objects( ent, objs, ident ); +} + +static _ssgSave3dsChunk *create_colour_chunk( unsigned short id, + float* colour ) { + _ssgSave3dsChunk *chunk = new _ssgSave3dsChunk(id); + + _ssgSave3dsChunk *rgbchunk = new _ssgSave3dsChunk(CHUNK_RGB1); + float *colvec = new sgVec3; + sgCopyVec3(colvec, colour); + _ssgSave3dsData *coldata = new _ssgSave3dsData(colvec, 4, 3); + rgbchunk->addData(coldata); + + chunk->addKid(rgbchunk); + return chunk; +} + +static _ssgSave3dsChunk *create_shininess_chunk( float shininess ) { + _ssgSave3dsChunk *chunk = new _ssgSave3dsChunk(CHUNK_SHINE_STRENGTH); + + _ssgSave3dsChunk *percent = new _ssgSave3dsChunk(CHUNK_AMOUNT); + unsigned short *amount = new unsigned short; + *amount = (unsigned short)(shininess * 100.0f / 128.0f); + _ssgSave3dsData *sdata = new _ssgSave3dsData(amount, 2, 1); + percent->addData(sdata); + + chunk->addKid(percent); + return chunk; +} + +static _ssgSave3dsChunk *create_mapparam_chunk( unsigned short id, float val ) { + _ssgSave3dsChunk *chunk = new _ssgSave3dsChunk( id ); + float *f = new float; + *f = val; + chunk -> addData( new _ssgSave3dsData(f, 4, 1) ); + return chunk; +} + +static _ssgSave3dsChunk *create_map_chunk( ssgSimpleState *state ) { + _ssgSave3dsChunk *map_chunk = new _ssgSave3dsChunk(CHUNK_TEXTURE); + + _ssgSave3dsChunk *mapname_chunk = new _ssgSave3dsChunk(CHUNK_MAPFILENAME); + char *mapname = ulStrDup(state->getTextureFilename()); + mapname_chunk -> addData( new _ssgSave3dsData(mapname, 1, + strlen(mapname) + 1) ); + map_chunk -> addKid(mapname_chunk); + + map_chunk -> addKid( create_mapparam_chunk( CHUNK_MAP_USCALE, 1.0f ) ); + map_chunk -> addKid( create_mapparam_chunk( CHUNK_MAP_VSCALE, 1.0f ) ); + map_chunk -> addKid( create_mapparam_chunk( CHUNK_MAP_UOFFST, 0.0f ) ); + map_chunk -> addKid( create_mapparam_chunk( CHUNK_MAP_VOFFST, 0.0f ) ); + + return map_chunk; +} + +static _ssgSave3dsChunk *create_material_chunk( ssgSimpleState *state ) { + _ssgSave3dsChunk *mat = new _ssgSave3dsChunk(CHUNK_MATERIAL); + + _ssgSave3dsChunk *matname_chunk = new _ssgSave3dsChunk(CHUNK_MATNAME); + char *matname; + if (state->getName() != NULL) + matname = ulStrDup(state->getName()); + else { + matname = new char[16]; + sprintf(matname, "Material #%d", mat_count); + } + _ssgSave3dsData *matname_data = new _ssgSave3dsData(matname, 1, + strlen(matname) + 1); + matname_chunk->addData(matname_data); + mat->addKid(matname_chunk); + + mat->addKid( create_colour_chunk( CHUNK_AMBIENT, + state->getMaterial(GL_AMBIENT) ) ); + mat->addKid( create_colour_chunk( CHUNK_DIFFUSE, + state->getMaterial(GL_DIFFUSE) ) ); + mat->addKid( create_colour_chunk( CHUNK_SPECULAR, + state->getMaterial(GL_SPECULAR) ) ); + mat->addKid( create_shininess_chunk( state->getShininess() ) ); + + if (state->isEnabled(GL_COLOR_MATERIAL)) { + ulSetError(UL_WARNING, + "State \"%s\" has GL_COLOR_MATERIAL enabled, which " \ + "is not supported by 3DS format. Data will be lost.", + matname); + } + + if (state->getTextureFilename() != NULL) { + mat->addKid( create_map_chunk(state) ); + } + + return mat; +} + +static void traverse_materials( ssgEntity* node, _ssgSave3dsChunk* parent ) { + if ( node->isAKindOf( ssgTypeBranch() ) ) { + ssgBranch *b_node = (ssgBranch*)node; + for (ssgEntity* kid = b_node->getKid(0); kid != NULL; + kid = b_node->getNextKid()) { + traverse_materials( kid, parent ); + } + } else if ( node->isAKindOf( ssgTypeLeaf() ) ) { + ssgLeaf* l_node = (ssgLeaf*)node; + ssgSimpleState *state = (ssgSimpleState*)l_node->getState(); + + for (int i = 0; i < mat_count; i++) { + if (state == mat[i]) + return; + } + + assert(mat_count < MAX_MATERIALS); + + mat[mat_count++] = state; + parent->addKid( create_material_chunk(state) ); + } +} + +static void create_materials_chunk( ssgEntity* ent, _ssgSave3dsChunk* parent ) { + mat_count = 0; + for (int i = 0; i < MAX_MATERIALS; i++) { + mat[i] = NULL; + } + + traverse_materials( ent, parent ); +} + +int ssgSave3ds( const char* filename, ssgEntity* ent ) { + save_fd = fopen( filename, "wb" ); + + if (save_fd == NULL) { + ulSetError( UL_WARNING, "ssgSave3ds: Failed to open '%s' for writing", + filename ); + return FALSE; + } + + _ssgSave3dsChunk *top_chunk = new _ssgSave3dsChunk( CHUNK_MAIN ); + _ssgSave3dsChunk *main_chunk = new _ssgSave3dsChunk( CHUNK_OBJMESH ); + + _ssgSave3dsChunk *version_chunk = new _ssgSave3dsChunk( CHUNK_VERSION ); + unsigned int *version = new unsigned int; + *version = 3; + _ssgSave3dsData *versiondata = new _ssgSave3dsData(version, 4, 1); + version_chunk -> addData(versiondata); + + top_chunk -> addKid( main_chunk ); + top_chunk -> addKid( version_chunk ); + + create_materials_chunk (ent, main_chunk); + create_objects_chunk (ent, main_chunk); + top_chunk->write(); + + delete top_chunk; + + fclose(save_fd); + + return TRUE; +} diff --git a/src/ssg/ssgSaveAC.cxx b/src/ssg/ssgSaveAC.cxx new file mode 100644 index 0000000..76ce9a3 --- /dev/null +++ b/src/ssg/ssgSaveAC.cxx @@ -0,0 +1,257 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgSaveAC.cxx 2169 2012-08-14 17:28:50Z wolfram_kuss $ +*/ + + +#include "ssgLocal.h" +#include "ssgLoaderWriterStuff.h" + +static ssgSimpleStateArray gSSL ; +static const int writeTextureWithoutPath = TRUE ; + +struct saveTriangle +{ + int v [ 3 ] ; + sgVec2 t [ 3 ] ; +} ; + +static FILE *save_fd ; +static sgVec3 *vlist ; +static saveTriangle *tlist ; + + +static int ssgSaveLeaf ( ssgEntity *ent ) +{ int i; + assert ( ent -> isAKindOf ( ssgTypeLeaf() ) ) ; + + ssgLeaf *vt = (ssgLeaf *) ent ; + + int num_verts = vt -> getNumVertices () ; + int num_tris = vt -> getNumTriangles () ; + + vlist = new sgVec3 [ num_verts ] ; + tlist = new saveTriangle [ num_tris ] ; + + for ( i = 0 ; i < num_verts; i++ ) + sgCopyVec3 ( vlist[i], vt->getVertex ( i ) ) ; + + for ( i = 0 ; i < num_tris ; i++ ) + { + short vv0, vv1, vv2 ; + + vt -> getTriangle ( i, &vv0, &vv1, &vv2 ) ; + + tlist[i].v[0] = vv0 ; + tlist[i].v[1] = vv1 ; + tlist[i].v[2] = vv2 ; + + sgCopyVec2 ( tlist[i].t[0], vt->getTexCoord ( vv0 ) ) ; + sgCopyVec2 ( tlist[i].t[1], vt->getTexCoord ( vv1 ) ) ; + sgCopyVec2 ( tlist[i].t[2], vt->getTexCoord ( vv2 ) ) ; + } + + fprintf ( save_fd, "OBJECT poly\n" ) ; + fprintf ( save_fd, "name \"%s\"\n", ent->getPrintableName() ) ; + + ssgState* st = vt -> getState () ; + + if ( st && st -> isAKindOf ( ssgTypeSimpleState() ) ) + { + ssgSimpleState* ss = (ssgSimpleState*) vt -> getState () ; + + if ( ss -> isEnabled ( GL_TEXTURE_2D ) ) + { + const char* tfname = ss -> getTextureFilename () ; + + if (( tfname != NULL ) && ( tfname[0] != 0 )) + { + if ( writeTextureWithoutPath ) + { + + const char *s = strrchr ( tfname, '\\' ) ; + if ( s == NULL ) + s = strrchr ( tfname, '/' ) ; + + if ( s == NULL ) + fprintf ( save_fd, "texture \"%s\"\n", tfname ) ; + else + fprintf ( save_fd, "texture \"%s\"\n", ++s ) ; + } + else + fprintf ( save_fd, "texture \"%s\"\n", tfname ) ; + } + } + } + + fprintf ( save_fd, "numvert %d\n", num_verts ) ; + + for ( i = 0 ; i < num_verts ; i++ ) + fprintf ( save_fd, "%g %g %g\n", vlist[i][0],vlist[i][2],-vlist[i][1] ) ; + + fprintf ( save_fd, "numsurf %d\n", num_tris ) ; + + for ( i = 0 ; i < num_tris ; i++ ) + { + fprintf ( save_fd, "SURF 0x0%x\n", (! vt -> getCullFace () ) << 5 ) ; + ssgState *s = vt->getState (); + + int istate = 0; + + if ( s != NULL ) + if ( s -> isAKindOf ( ssgTypeSimpleState() ) ) + { + istate = gSSL.findIndex ( (ssgSimpleState *) s ) ; + assert ( istate >= 0 ) ; + } + + fprintf ( save_fd, "mat %d\n", istate ) ; + fprintf ( save_fd, "refs 3\n" ) ; + fprintf ( save_fd, "%d %g %g\n", + tlist[i].v[0],tlist[i].t[0][0],tlist[i].t[0][1] ) ; + fprintf ( save_fd, "%d %g %g\n", + tlist[i].v[1],tlist[i].t[1][0],tlist[i].t[1][1] ) ; + fprintf ( save_fd, "%d %g %g\n", + tlist[i].v[2],tlist[i].t[2][0],tlist[i].t[2][1] ) ; + } + + fprintf ( save_fd, "kids 0\n" ) ; + + delete [] vlist ; + delete [] tlist ; + + return TRUE ; +} + + + +static int ssgSaveACInner ( ssgEntity *ent ) +{ + /* WARNING - RECURSIVE! */ + + if ( ent -> isAKindOf ( ssgTypeBranch() ) ) + { + ssgBranch *br = (ssgBranch *) ent ; + + fprintf ( save_fd, "OBJECT group\n" ) ; + fprintf ( save_fd, "kids %d\n", ent->getNumKids() ) ; + + for ( int i = 0 ; i < br -> getNumKids () ; i++ ) + if ( ! ssgSaveACInner( br -> getKid ( i ) ) ) + return FALSE ; + + return TRUE ; + } + + return ssgSaveLeaf ( ent ) ; +} + + + + +int ssgSaveAC ( const char *filename, ssgEntity *ent ) +{ + int i ; + + save_fd = fopen ( filename, SSG_SAVE_TEXT_FILE ) ; + + if ( save_fd == NULL ) + { + ulSetError ( UL_WARNING, + "ssgSaveAC: Failed to open '%s' for writing", filename ) ; + return FALSE ; + } + + fprintf ( save_fd, "AC3Db\n" ) ; + + gSSL.collect( ent ); + + /* + There is a *huge* problem here. + + The AC3D format doesn't support per-vertex or even + per-polygon colours. + + You *must* use materials. + + Hence what we really should do is to collect together + all the per-vertex colours in the SSG model and make + a material from each one (possibly more if that colour + is on many polygons which have different ssgSimpleState's. + + For now, I'll cheat and set the GL_COLORMATERIAL colours + to white - which works *reasonably* well for most heavily + textured models...well, at least you don't get uninitialised + colours coming from SSG. + */ + + for (i = 0 ; i < gSSL.getNum(); i++) + { + sgVec4 white = { 1, 1, 1, 1 } ; + + ssgSimpleState * ss = gSSL.get(i); + + float *em = ss->getMaterial (GL_EMISSION ); + float *sp = ss->getMaterial (GL_SPECULAR ); + float *am = ss->getMaterial (GL_AMBIENT ); + float *di = ss->getMaterial (GL_DIFFUSE ); + + if ( ss->isEnabled ( GL_COLOR_MATERIAL ) ) + { + switch ( ss->getColourMaterial () ) + { + case GL_AMBIENT_AND_DIFFUSE : am = di = white ; break ; + case GL_EMISSION : em = white ; break ; + case GL_SPECULAR : sp = white ; break ; + case GL_AMBIENT : am = white ; break ; + case GL_DIFFUSE : di = white ; break ; + } + } + + int shiny = (int) ss->getShininess (); + + fprintf ( save_fd, "MATERIAL \"%s\"" + " rgb %f %f %f" + " amb %f %f %f" + " emis %f %f %f" + " spec %f %f %f" + " shi %d trans %f\n", + ss->getPrintableName(), + di[0], di[1], di[2], + am[0], am[1], am[2], + em[0], em[1], em[2], + sp[0], sp[1], sp[2], + shiny, 1.0-di[3] ) ; + } + + fprintf ( save_fd, "OBJECT world\n" ) ; + fprintf ( save_fd, "kids 1\n" ) ; + + int bReturn = ssgSaveACInner ( ent ) ; + + gSSL.removeAll () ; + + fclose ( save_fd ) ; + + return bReturn ; +} + + diff --git a/src/ssg/ssgSaveASC.cxx b/src/ssg/ssgSaveASC.cxx new file mode 100644 index 0000000..917d4d4 --- /dev/null +++ b/src/ssg/ssgSaveASC.cxx @@ -0,0 +1,234 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + +*/ + +// +// ASC (ascii files, used for example by 3DS R4 (the DOS version)) export for SSG/PLIB +// Written by Wolfram Kuss in Mar-2003 +// + +#include "ssgLocal.h" +#include "ssgLoaderWriterStuff.h" + +static FILE *save_fd ; +static ssgSimpleStateArray gSSL; + +float save_scale = 1.0f; +int calledByTheHuman = TRUE; + +static void save_vtx_table ( ssgVtxTable *vt ) +{ + GLenum mode = vt -> getPrimitiveType () ; + if ( mode != GL_TRIANGLES && + mode != GL_TRIANGLE_FAN && + mode != GL_TRIANGLE_STRIP ) + { + //only triangle export + return; + } + +/* + Named object: +*/ + int j ; + + + int istate = gSSL.findIndex ( (ssgSimpleState*)vt->getState () ) ; + int num_vert = vt -> getNumVertices () ; + int num_face = vt -> getNumTriangles () ; + + ssgSimpleState* st = ( istate != -1 )? gSSL.get( istate ): 0; + bool mapped = ( st && st -> isEnabled ( GL_TEXTURE_2D ) && + vt -> getNumTexCoords () == num_vert ); + + fprintf ( save_fd, "Named object: \"%s\"\n", vt->getPrintableName()); + fprintf ( save_fd, "Tri-mesh, Vertices: %d Faces: %d\n", num_vert, num_face ); + if(mapped) + fprintf ( save_fd, "Mapped\n"); + +/* + Vertex list: +*/ + fprintf ( save_fd, "Vertex list:\n"); + const char *material = "PALGREY27"; + ssgState *s = vt->getState(); + if (s) + if(s->isAKindOf(ssgTypeSimpleState())) + { + + ssgTexture * t = ((ssgSimpleState *)s)->getTexture(); + if(t) + { + char *fn = t->getFilename(); + if (fn) + { + char *tsA = new char [strlen(fn)+1]; // kludge: mem leak! + strcpy(tsA, fn); + + char *t = strrchr(tsA, '\\'); + if (!t) + t = tsA; + else + t++; + char *t1 = strrchr(t, '/'); + if (!t1) + t1 = t; + else + t1++; + + char *t2 = strrchr(t1, '.'); + if (t2) + { + // special handling for *.0af .. *.9af to be able to differntiate between them: + if((t2[2]=='a') && (t2[3]=='f')) + *t2='_'; + else + *t2=0; + } + + material = t1; + } + } + } + for ( j = 0; j < num_vert; j++ ) + { + sgVec3 v; + sgCopyVec3 ( v, vt->getVertex ( j ) ) ; + + fprintf ( save_fd, "Vertex %d: X:%f Y:%f Z:%f", j, save_scale*v[0], save_scale*v[1], save_scale*v[2] ); + if(mapped) + { + sgVec2 tv ; + sgCopyVec2 ( tv, vt->getTexCoord ( j ) ) ; + // *************************************************** + // WK: Originally I did not have the "U:" and "V:" !!! + // Strange !! Maybe there are two formats?? + // *************************************************** + fprintf ( save_fd, " U:%f V:%f\n", tv[0], tv[1]); // 1.0f - tv[1]); + } + else + fprintf ( save_fd, "\n"); + } + +/* + Face list: +*/ + if(num_face > 0) + fprintf ( save_fd, "Face list:\n"); + for ( j = 0; j < num_face; j++ ) + { + short i1,i2,i3; + vt -> getTriangle ( j, &i1, &i2, &i3 ) ; + + fprintf ( save_fd, "Face %d: A:%d B:%d C:%d AB:1 BC:1 CA:1\n", j, i1, i2, i3 ); + fprintf ( save_fd, "Material:\"%s\"\n", material ); + } + fprintf ( save_fd, "\n"); // empty line after the named object + +/* + Item MESH_NUMTVERTEX. +*/ + + fflush ( save_fd ) ; +/* + Item NUMCVERTEX. +*/ + //fprintf ( save_fd, " *MESH_NUMCVERTEX 0\n" ); + + //if ( st ) fprintf ( save_fd, " *MATERIAL_REF %d\n", gSSL.findIndex ( st ) ); + +} + +// wk: Kludge !!! +// if the "calling app" like PPE sets this, then only nodes with spare ==1 are saved !! +int bUseSpare=FALSE; + +static void save_geom ( ssgEntity *e ) +{ + if ( e -> isAKindOf ( ssgTypeBranch() ) ) + { + ssgBranch *br = (ssgBranch *) e ; + for (int i = 0 ; i < br -> getNumKids () ; i++ ) + save_geom ( br -> getKid ( i ) ) ; + } + else + if ( e -> isAKindOf ( ssgTypeVtxTable() ) ) + { int bSaveIt = TRUE; + if(bUseSpare) + if( 1 != e->getSpare() ) + bSaveIt = FALSE; + + if ( bSaveIt ) + { + ssgVtxTable *vt = (ssgVtxTable *) e ; + save_vtx_table ( vt ) ; + } + } +} + + +int ssgSaveASC ( FILE* fileout, ssgEntity *ent ) +{ + save_fd = fileout ; + +/* + Write the header. +*/ + fprintf ( save_fd, "Ambient light color: Red=0.039216 Green=0.039216 Blue=0.039216\n" ); + fprintf ( save_fd, "Solid background color: Red=0.372549 Green=0.454902 Blue=0.639216\n" ); + + + gSSL.collect ( ent ) ; + //save_states () ; + save_geom ( ent ) ; + gSSL.removeAll(); + + fflush ( save_fd ) ; + + return TRUE ; +} + + +int ssgSaveASC ( const char *filename, ssgEntity *ent ) +{ + save_fd = fopen ( filename, "wa" ) ; + + if ( save_fd == NULL ) + { + ulSetError ( UL_WARNING, "ssgSaveASC: Failed to open '%s' for writing", filename ) ; + return FALSE ; + } + if(calledByTheHuman) + if(save_scale!=1.0f) + { +#ifdef WIN32 + char temp[999]; + sprintf(temp, "Applying a scale factor of %f", save_scale); + ::MessageBox(0, temp, "For your info:", 0); +#else + printf("Applying a scale factor of %f", save_scale); +#endif + } + int result = ssgSaveASC ( save_fd, ent ) ; + + fclose ( save_fd ) ; + return result ; +} diff --git a/src/ssg/ssgSaveASE.cxx b/src/ssg/ssgSaveASE.cxx new file mode 100644 index 0000000..533e07b --- /dev/null +++ b/src/ssg/ssgSaveASE.cxx @@ -0,0 +1,343 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgSaveASE.cxx 2169 2012-08-14 17:28:50Z wolfram_kuss $ +*/ + +// +// ASE ( 3DSMAX ASCII EXPORT Version 2.00 ) export for SSG/PLIB +// Written by Dave McClurg (dpm@efn.org) in Feb-2000 +// + +#include "ssgLocal.h" +#include "ssgLoaderWriterStuff.h" + +static FILE *save_fd ; +static ssgSimpleStateArray gSSL; + +static void save_state ( ssgSimpleState* st, int istate ) +{ + + float* amb = st -> getMaterial ( GL_AMBIENT ) ; + float* diff = st -> getMaterial ( GL_DIFFUSE ) ; + float* spec = st -> getMaterial ( GL_SPECULAR ) ; + float shine = st -> getShininess () ; + float trans = st -> isTranslucent () ? 1.0f : 0.0f ; + + fprintf ( save_fd, " *MATERIAL %d {\n", istate ); + fprintf ( save_fd, " *MATERIAL_NAME \"Material #%d\"\n", istate ); + fprintf ( save_fd, " *MATERIAL_CLASS \"Standard\"\n" ); + fprintf ( save_fd, " *MATERIAL_AMBIENT %f %f %f\n", amb[0], amb[1], amb[2] ) ; + fprintf ( save_fd, " *MATERIAL_DIFFUSE %f %f %f\n", diff[0], diff[1], diff[2] ) ; + fprintf ( save_fd, " *MATERIAL_SPECULAR %f %f %f\n", spec[0], spec[1], spec[2] ) ; + fprintf ( save_fd, " *MATERIAL_SHINE %f\n", shine ) ; + fprintf ( save_fd, " *MATERIAL_SHINESTRENGTH %f\n", shine ) ; + fprintf ( save_fd, " *MATERIAL_TRANSPARENCY %f\n", trans ) ; + fprintf ( save_fd, " *MATERIAL_WIRESIZE 1.0000\n" ); + fprintf ( save_fd, " *MATERIAL_SHADING Blinn\n" ); + fprintf ( save_fd, " *MATERIAL_XP_FALLOFF 0.0000\n" ); + fprintf ( save_fd, " *MATERIAL_SELFILLUM 0.0000\n" ); + fprintf ( save_fd, " *MATERIAL_TWOSIDED\n" ); + fprintf ( save_fd, " *MATERIAL_FALLOFF In\n" ); + fprintf ( save_fd, " *MATERIAL_SOFTEN\n" ); + fprintf ( save_fd, " *MATERIAL_XP_TYPE Filter\n" ) ; + + if ( st -> isEnabled ( GL_TEXTURE_2D ) ) + { + const char* tfname = st -> getTextureFilename() ; + + fprintf ( save_fd, " *MAP_DIFFUSE {\n" ); + fprintf ( save_fd, " *MAP_NAME \"Map #%d\"\n", istate ) ; + fprintf ( save_fd, " *MAP_CLASS \"Bitmap\"\n" ) ; + fprintf ( save_fd, " *MAP_SUBNO 1\n" ) ; + fprintf ( save_fd, " *MAP_AMOUNT 1.0000\n" ) ; + fprintf ( save_fd, " *BITMAP \"%s\"\n", tfname ) ; + fprintf ( save_fd, " *MAP_TYPE Spherical\n" ) ; + fprintf ( save_fd, " *UVW_U_OFFSET 0.0000\n" ) ; + fprintf ( save_fd, " *UVW_V_OFFSET 0.0000\n" ) ; + fprintf ( save_fd, " *UVW_U_TILING 1.0000\n" ) ; + fprintf ( save_fd, " *UVW_V_TILING 1.0000\n" ) ; + fprintf ( save_fd, " *UVW_ANGLE 0.0000\n" ) ; + fprintf ( save_fd, " *UVW_BLUR 1.0000\n" ) ; + fprintf ( save_fd, " *UVW_BLUR_OFFSET 0.0000\n" ) ; + fprintf ( save_fd, " *UVW_NOUSE_AMT 1.0000\n" ) ; + fprintf ( save_fd, " *UVW_NOISE_SIZE 1.0000\n" ) ; + fprintf ( save_fd, " *UVW_NOISE_LEVEL 1\n" ) ; + fprintf ( save_fd, " *UVW_NOISE_PHASE 0.0000\n" ) ; + fprintf ( save_fd, " *BITMAP_FILTER Pyramidal\n" ) ; + fprintf ( save_fd, " }\n" ); + } + + fprintf ( save_fd, " }\n" ); +} + + +static void save_states () +{ + fprintf ( save_fd, "*MATERIAL_LIST {\n" ) ; + fprintf ( save_fd, " *MATERIAL_COUNT %d\n", gSSL.getNum() ) ; + + for ( int i=0; i < gSSL.getNum(); i++ ) + save_state ( gSSL.get(i) , i ) ; + + fprintf ( save_fd, "}\n" ); +} + + +static void save_vtx_table ( ssgVtxTable *vt ) +{ + GLenum mode = vt -> getPrimitiveType () ; + if ( mode != GL_TRIANGLES && + mode != GL_TRIANGLE_FAN && + mode != GL_TRIANGLE_STRIP ) + { + //only triangle export + return; + } + + const char* name = vt->getPrintableName() ; + int j ; + + int istate = gSSL.findIndex ( (ssgSimpleState*)vt->getState () ) ; + ssgSimpleState* st = ( istate != -1 )? gSSL.get( istate ): 0; + +/* + Begin the big geometry block. +*/ + fprintf ( save_fd, "*GEOMOBJECT {\n" ); + fprintf ( save_fd, " *NODE_NAME \"%s\"\n", name ); + +/* + Sub block NODE_TM: +*/ + fprintf ( save_fd, " *NODE_TM {\n" ); + fprintf ( save_fd, " *NODE_NAME \"%s\"\n", name ); + fprintf ( save_fd, " *INHERIT_POS 0 0 0\n" ); + fprintf ( save_fd, " *INHERIT_ROT 0 0 0\n" ); + fprintf ( save_fd, " *INHERIT_SCL 0 0 0\n" ); + fprintf ( save_fd, " *TM_ROW0 1.0000 0.0000 0.0000\n" ); + fprintf ( save_fd, " *TM_ROW1 0.0000 1.0000 0.0000\n" ); + fprintf ( save_fd, " *TM_ROW2 0.0000 0.0000 1.0000\n" ); + fprintf ( save_fd, " *TM_ROW3 0.0000 0.0000 0.0000\n" ); + fprintf ( save_fd, " *TM_POS 0.0000 0.0000 0.0000\n" ); + fprintf ( save_fd, " *TM_ROTAXIS 0.0000 0.0000 0.0000\n" ); + fprintf ( save_fd, " *TM_ROTANGLE 0.0000\n" ); + fprintf ( save_fd, " *TM_SCALE 1.0000 1.0000 1.0000\n" ); + fprintf ( save_fd, " *TM_SCALEAXIS 0.0000 0.0000 0.0000\n" ); + fprintf ( save_fd, " *TM_SCALEAXISANG 0.0000\n" ); + fprintf ( save_fd, " }\n" ); + +/* + Sub block MESH: + Items +*/ + int num_vert = vt -> getNumVertices () ; + int num_face = vt -> getNumTriangles () ; + fprintf ( save_fd, " *MESH {\n" ); + fprintf ( save_fd, " *TIMEVALUE 0\n" ); + fprintf ( save_fd, " *MESH_NUMVERTEX %d\n", num_vert ); + fprintf ( save_fd, " *MESH_NUMFACES %d\n", num_face ); + +/* + Sub sub block MESH_VERTEX_LIST +*/ + fprintf ( save_fd, " *MESH_VERTEX_LIST {\n" ); + for ( j = 0; j < num_vert; j++ ) + { + sgVec3 v; + sgCopyVec3 ( v, vt->getVertex ( j ) ) ; + fprintf ( save_fd, " *MESH_VERTEX %d %f %f %f\n", + j, v[0], v[1], v[2] ); + } + fprintf ( save_fd, " }\n" ); + +/* + Sub sub block MESH_FACE_LIST + Items MESH_FACE +*/ + fprintf ( save_fd, " *MESH_FACE_LIST {\n" ); + for ( j = 0; j < num_face; j++ ) + { + short i1,i2,i3; + vt -> getTriangle ( j, &i1, &i2, &i3 ) ; + + fprintf ( save_fd, " *MESH_FACE %d: A: %d B: %d C: %d", j, i1, i2, i3 ); + fprintf ( save_fd, " AB: 1 BC: 1 CA: 1 *MESH_SMOOTHING *MESH_MTLID 1\n" ); + } + fprintf ( save_fd, " }\n" ); + +/* + Item MESH_NUMTVERTEX. +*/ + if ( st && st -> isEnabled ( GL_TEXTURE_2D ) && + vt -> getNumTexCoords () == num_vert ) + { + fprintf ( save_fd, " *MESH_NUMTVERTEX %d\n", num_vert ); + fprintf ( save_fd, " *MESH_TVERTLIST {\n" ); + for ( j = 0; j < num_vert; j++ ) + { + sgVec2 tv ; + sgCopyVec2 ( tv, vt->getTexCoord ( j ) ) ; + fprintf ( save_fd, " *MESH_TVERT %d %f %f %f\n", + j, tv[0], 1.0f - tv[1], 1.0f ); + } + fprintf ( save_fd, " }\n" ); + fprintf ( save_fd, " *MESH_NUMTVFACES %d\n", num_face ); + fprintf ( save_fd, " *MESH_TFACELIST {\n" ); + for ( j = 0; j < num_face; j++ ) + { + short i1,i2,i3; + vt -> getTriangle ( j, &i1, &i2, &i3 ) ; + + fprintf ( save_fd, " *MESH_TFACE %d %d %d %d\n", j, i1, i2, i3 ); + } + fprintf ( save_fd, " }\n" ); + } + else + { + fprintf ( save_fd, " *MESH_NUMTVERTEX 0\n" ); + } + + fprintf ( save_fd, "done\n" ) ; + fflush ( save_fd ) ; +/* + Item NUMCVERTEX. +*/ + fprintf ( save_fd, " *MESH_NUMCVERTEX 0\n" ); + +#if 0 +/* + Sub block MESH_NORMALS + Items MESH_FACENORMAL, MESH_VERTEXNORMAL (repeated) +*/ + fprintf ( save_fd, " *MESH_NORMALS {\n" ); + for ( j = 0; j < num_face; j++ ) { + + fprintf ( save_fd, " *MESH_FACENORMAL %d %f %f %f\n", + iface, face_normal[0][j], face_normal[1][j], face_normal[2][j] ); + + for ( ivert = 0; ivert < face_order[j]; ivert++ ) { + fprintf ( save_fd, " *MESH_VERTEXNORMAL %d %f %f %f\n", + face[ivert][iface], vertex_normal[0][ivert][iface], + vertex_normal[1][ivert][j], vertex_normal[2][ivert][j] ); + } + } + fprintf ( save_fd, " }\n" ); +#endif + +/* + Close the MESH object. +*/ + fprintf ( save_fd, " }\n" ); + +/* + A few closing parameters. +*/ + fprintf ( save_fd, " *PROP_MOTIONBLUR 0\n" ); + fprintf ( save_fd, " *PROP_CASTSHADOW 1\n" ); + fprintf ( save_fd, " *PROP_RECVSHADOW 1\n" ); + + if ( st ) + fprintf ( save_fd, " *MATERIAL_REF %d\n", gSSL.findIndex ( st ) ); + +/* + Close the GEOM object. +*/ + fprintf ( save_fd, "}\n" ); +} + + +static void save_geom ( ssgEntity *e ) +{ + if ( e -> isAKindOf ( ssgTypeBranch() ) ) + { + ssgBranch *br = (ssgBranch *) e ; + + if ( br -> isAKindOf ( ssgTypeSelector() ) ) + { + for ( int i = 0 ; i < br -> getNumKids () ; i++ ) + save_geom ( br -> getKid ( i ) ) ; + } + else + { + for ( int i = 0 ; i < br -> getNumKids () ; i++ ) + save_geom ( br -> getKid ( i ) ) ; + } + } + else + if ( e -> isAKindOf ( ssgTypeVtxTable() ) ) + { + ssgVtxTable *vt = (ssgVtxTable *) e ; + save_vtx_table ( vt ) ; + } +} + + +int ssgSaveASE ( FILE* fileout, ssgEntity *ent ) +{ + save_fd = fileout ; + +/* + Write the header. +*/ + fprintf ( save_fd, "*3DSMAX_ASCIIEXPORT 200\n" ); + fprintf ( save_fd, "*COMMENT \"created by SSG.\"\n" ); + +/* + Write the scene block. +*/ + fprintf ( save_fd, "*SCENE {\n" ); + fprintf ( save_fd, " *SCENE_FILENAME \"\"\n" ); + fprintf ( save_fd, " *SCENE_FIRSTFRAME 0\n" ); + fprintf ( save_fd, " *SCENE_LASTFRAME 100\n" ); + fprintf ( save_fd, " *SCENE_FRAMESPEED 30\n" ); + fprintf ( save_fd, " *SCENE_TICKSPERFRAME 160\n" ); + fprintf ( save_fd, " *SCENE_BACKGROUND_STATIC 0.0000 0.0000 0.0000\n" ); + fprintf ( save_fd, " *SCENE_AMBIENT_STATIC 0.0431 0.0431 0.0431\n" ); + fprintf ( save_fd, "}\n" ); + + + gSSL.collect ( ent ) ; + save_states () ; + save_geom ( ent ) ; + gSSL.removeAll(); + + fflush ( save_fd ) ; + + return TRUE ; +} + + +int ssgSaveASE ( const char *filename, ssgEntity *ent ) +{ + save_fd = fopen ( filename, SSG_SAVE_TEXT_FILE ) ; + + if ( save_fd == NULL ) + { + ulSetError ( UL_WARNING, "ssgSaveASE: Failed to open '%s' for writing", filename ) ; + return FALSE ; + } + + int result = ssgSaveASE ( save_fd, ent ) ; + + fclose ( save_fd ) ; + + return result ; +} diff --git a/src/ssg/ssgSaveATG.cxx b/src/ssg/ssgSaveATG.cxx new file mode 100644 index 0000000..cf8b8fc --- /dev/null +++ b/src/ssg/ssgSaveATG.cxx @@ -0,0 +1,160 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgSaveATG.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ +/* + .scenery writer for SSG/PLIB + ATG = ascii Terra Gear + + Written by Wolfram Kuss (Wolfram.Kuss@t-online.de) in May 2001 + +*/ + +#include +#include "ssgLocal.h" +#include "ssgLoaderWriterStuff.h" + + + +int ssgSaveATG( const char* fname, ssgEntity *ent ) { + FILE *fd = fopen ( fname, "w" ) ; + int i; + + if ( fd == NULL ) { + ulSetError ( UL_WARNING, "ssgSaveATG: Failed to open '%s' for writing", + fname ); + return FALSE ; + } + + ssgVertexArray* vertices = new ssgVertexArray(); + ssgIndexArray* indices = new ssgIndexArray (); + + fprintf(fd, "# Created by ssgSaveATG. Original graph structure was:\n"); + ent->print(fd, "#", 0); + + sgMat4 ident; + sgMakeIdentMat4( ident ); + ssgSimpleStateArray ssa; // = new ssgSimpleStateArray(); + ssgIndexArray* materialIndices = new ssgIndexArray(); + ssgTexCoordArray * texCoordArray = new ssgTexCoordArray(); + + ssgAccumVerticesAndFaces( ent, ident, vertices, indices, /* epsilon = */ -1, &ssa, + materialIndices, texCoordArray); + assert ( vertices->getNum() == texCoordArray->getNum() ); + for (i = 0; i < vertices->getNum(); i++) { + fprintf(fd, "v %f %f %f\n", vertices->get(i)[0], + vertices->get(i)[1], + vertices->get(i)[2]); + } +// hack calc normal + + ssgNormalArray *na=new ssgNormalArray (vertices->getNum()); + sgVec3 myVec3; + myVec3[0]=0.0; myVec3[1]=0.0; myVec3[2]=1.0; + sgVec3 n; + int ind1, ind2, ind3; + for (i = 0; i < vertices->getNum(); i++) + na->add(myVec3); + + + for (i = 0; i < indices->getNum(); i += 3) { + ind1 = *indices->get(i); + ind2 = *indices->get(i + 1); + ind3 = *indices->get(i + 2); + if ((vertices->get(ind1)!=NULL) && (vertices->get(ind2)!=NULL) && + (vertices->get(ind3)!=NULL)) // wk: kludge: why can it be NULL? + { sgMakeNormal( n, + vertices->get(ind1), + vertices->get(ind2), + vertices->get(ind3) ); + + sgCopyVec3( na->get(ind1), n ); + sgCopyVec3( na->get(ind2), n ); + sgCopyVec3( na->get(ind3), n ); + } + } + + + + + + + + for (i = 0; i < vertices->getNum(); i++) + { float *f = na->get(i); + fprintf(fd, "vn %f %f %f\n", f[0], f[1], f[2]); + } + for (i = 0; i < texCoordArray->getNum(); i++) + fprintf(fd, "vt %f %f\n", texCoordArray->get(i)[0], texCoordArray->get(i)[1]); + + // output all faces + int runningIndex=0, lastIndex = -1; + for (i = 0; i < indices->getNum(); i += 3) { + + // output material + int matIndex = *(materialIndices->get(runningIndex++)); + if (( matIndex >= 0 ) && ( lastIndex != matIndex )) + { ssgSimpleState * ss = ssa.get( matIndex ); + if ( ss->getTextureFilename() != NULL) + { // remove .rgb + char *s1, *s2, * s = new char [ strlen(ss->getTextureFilename()) +1 ]; + assert ( s != NULL ); + strcpy(s, ss->getTextureFilename()); + char *p = strrchr(s, '.'); + if ( p != NULL ) + { + if (((p[2]=='a') || (p[2]=='A')) && ((p[3]=='f') || (p[3]=='F'))) + // *.?af textures are special: + // the name before the ':' is not unique, you have to use the first character of the extension as + // well. The tool af2rgb, which converts *.?af into rgb-files, also appends this char to the filename. + { p[0]=p[1]; + p[1]=0; + } + else + *p = 0; + } + s2 = s; + s1 = strrchr(s, '/'); + if ( s1 != NULL ) + s2 = ++s1; + s1 = strrchr(s2, '\\'); + if ( s1 != NULL ) + s2 = ++s1; + fprintf(fd, "# usemtl %s\n", s2); + delete [] s; + } + lastIndex = matIndex; + } + // output face + fprintf(fd, "f %d/%d %d/%d %d/%d\n", *indices->get(i), *indices->get(i), + *indices->get(i + 1), *indices->get(i + 1), + *indices->get(i + 2), *indices->get(i + 2) ); + } + assert ( runningIndex == materialIndices->getNum() ); + delete materialIndices; + + fclose( fd ) ; + + delete vertices; + delete indices ; + + return TRUE; +} diff --git a/src/ssg/ssgSaveDXF.cxx b/src/ssg/ssgSaveDXF.cxx new file mode 100644 index 0000000..15f2967 --- /dev/null +++ b/src/ssg/ssgSaveDXF.cxx @@ -0,0 +1,179 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgSaveDXF.cxx 2169 2012-08-14 17:28:50Z wolfram_kuss $ +*/ + +// +// DXF export for SSG/PLIB +// Ported from IVCON by Dave McClurg (dpm@efn.org) in March-2000 +// + +#include "ssgLocal.h" + +static FILE *fileout ; + +static void save_vtx_table ( ssgVtxTable *vt ) +{ + GLenum mode = vt -> getPrimitiveType () ; + if (( mode == GL_LINES ) || ( mode == GL_LINE_LOOP) || ( mode == GL_LINE_STRIP)) + { + int num_vert = vt -> getNumVertices () ; + num_vert = num_vert - ( num_vert & 1 ) ; //discard odd vertex + int local_num_lines = vt -> getNumLines(); + + for ( int j = 0; j < local_num_lines ; j ++ ) + { + sgVec3 vert1, vert2; + short iv1, iv2; + vt -> getLine (j, &iv1, &iv2); + + sgCopyVec3 ( vert1, vt->getVertex ( iv1 ) ) ; + sgCopyVec3 ( vert2, vt->getVertex ( iv2 ) ) ; + + fprintf ( fileout, "0\n" ); + fprintf ( fileout, "LINE\n" ); + fprintf ( fileout, "8\n" ); + fprintf ( fileout, "0\n" ); + fprintf ( fileout, "10\n" ); + fprintf ( fileout, "%f\n", vert1[0] ); + fprintf ( fileout, "20\n" ); + fprintf ( fileout, "%f\n", vert1[1] ); + fprintf ( fileout, "30\n" ); + fprintf ( fileout, "%f\n", vert1[2] ); + fprintf ( fileout, "11\n" ); + fprintf ( fileout, "%f\n", vert2[0] ); + fprintf ( fileout, "21\n" ); + fprintf ( fileout, "%f\n", vert2[1] ); + fprintf ( fileout, "31\n" ); + fprintf ( fileout, "%f\n", vert2[2] ); + } + } + else if ( mode == GL_TRIANGLES || + mode == GL_TRIANGLE_FAN || + mode == GL_TRIANGLE_STRIP ) + { + int num_face = vt -> getNumTriangles () ; + for ( int j = 0; j < num_face; j++ ) + { + short face[3]; + vt -> getTriangle ( j, &face[0], &face[1], &face[2] ) ; + + fprintf ( fileout, "0\n" ); + fprintf ( fileout, "3DFACE\n" ); + fprintf ( fileout, "8\n" ); + fprintf ( fileout, "Cube\n" ); + + sgVec3 vert; + for ( int ivert = 0; ivert < 3; ivert++ ) { + + sgCopyVec3 ( vert, vt->getVertex ( face[ivert] ) ) ; + + fprintf ( fileout, "1%d\n", ivert ); + fprintf ( fileout, "%f\n", vert[0] ); + fprintf ( fileout, "2%d\n", ivert ); + fprintf ( fileout, "%f\n", vert[1] ); + fprintf ( fileout, "3%d\n", ivert ); + fprintf ( fileout, "%f\n", vert[2] ); + } + fprintf ( fileout, "13\n"); + fprintf ( fileout, "%f\n", vert[0] ); + fprintf ( fileout, "23\n"); + fprintf ( fileout, "%f\n", vert[1] ); + fprintf ( fileout, "33\n"); + fprintf ( fileout, "%f\n", vert[2] ); + } + } + else + ulSetError ( UL_WARNING, "ssgSaveDXF: OpenGL mode %d not implmented yet. Parts or all of the model are ignored!' for writing", (int)mode ) ; +} + + +static void save_entities ( ssgEntity *e ) +{ + if ( e -> isAKindOf ( ssgTypeBranch() ) ) + { + ssgBranch *br = (ssgBranch *) e ; + + for ( int i = 0 ; i < br -> getNumKids () ; i++ ) + save_entities ( br -> getKid ( i ) ) ; + } + else + if ( e -> isAKindOf ( ssgTypeVtxTable() ) ) + { + ssgVtxTable *vt = (ssgVtxTable *) e ; + save_vtx_table ( vt ) ; + } +} + + +int ssgSaveDXF ( const char *filename, ssgEntity *ent ) +{ + fileout = fopen ( filename, SSG_SAVE_TEXT_FILE); + + if ( fileout == NULL ) + { + ulSetError ( UL_WARNING, "ssgSaveDXF: Failed to open '%s' for writing", filename ) ; + return FALSE ; + } + +/* + Initialize. +*/ + fprintf ( fileout, "0\n" ); + fprintf ( fileout, "SECTION\n" ); + fprintf ( fileout, "2\n" ); + fprintf ( fileout, "HEADER\n" ); + fprintf ( fileout, "999\n" ); + fprintf ( fileout, "%s created by SSG.\n", filename ); + fprintf ( fileout, "0\n" ); + fprintf ( fileout, "ENDSEC\n" ); + + fprintf ( fileout, "0\n" ); + fprintf ( fileout, "SECTION\n" ); + fprintf ( fileout, "2\n" ); + fprintf ( fileout, "TABLES\n" ); + fprintf ( fileout, "0\n" ); + fprintf ( fileout, "ENDSEC\n" ); + + fprintf ( fileout, "0\n" ); + fprintf ( fileout, "SECTION\n" ); + fprintf ( fileout, "2\n" ); + fprintf ( fileout, "BLOCKS\n" ); + fprintf ( fileout, "0\n" ); + fprintf ( fileout, "ENDSEC\n" ); + + fprintf ( fileout, "0\n" ); + fprintf ( fileout, "SECTION\n" ); + fprintf ( fileout, "2\n" ); + fprintf ( fileout, "ENTITIES\n" ); + + save_entities ( ent ) ; + + fprintf ( fileout, "0\n" ); + fprintf ( fileout, "ENDSEC\n" ); + fprintf ( fileout, "0\n" ); + fprintf ( fileout, "EOF\n" ); +/* + Close. +*/ + fclose ( fileout ) ; + return TRUE; +} diff --git a/src/ssg/ssgSaveFLT.cxx b/src/ssg/ssgSaveFLT.cxx new file mode 100644 index 0000000..0f03f76 --- /dev/null +++ b/src/ssg/ssgSaveFLT.cxx @@ -0,0 +1,680 @@ + +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgSaveFLT.cxx 1744 2003-01-04 02:55:56Z sjbaker $ +*/ + +/******************************************************* + ** ssgSaveFLT.cxx + ** + ** Written by Steve Baker + ** Last updated: 2002-10-15 + ** + ** This was written to be a part of Stephen J Bakers + ** PLIB (http://plib.sourceforge.net) + *******************************************************/ + +#include +#include "ssgLocal.h" + + +struct FLT_texture +{ + char fname [ 200 ] ; /* 200 is the OpenFlight limit - don't increase it! */ +} ; + + +struct FLT_vertex +{ + sgVec3 vert ; + sgVec3 norm ; + sgVec4 col ; + sgVec2 tex ; +} ; + + +static ulList *texList = NULL ; +static ulList *vtxList = NULL ; +static FILE *save_fd = NULL ; +static int max_bank = 1 ; +static int curr_bank = 0 ; + +static int addToTexturePool ( char *tex ) +{ + int max = texList -> getNumEntities () ; + + for ( int p = strlen(tex) ; p >= 0 ; p-- ) + if ( tex[p] == '/' ) + { + tex = & tex[p+1] ; + break ; + } + + for ( int i = 0 ; i < max ; i++ ) + { + FLT_texture *target = (FLT_texture *)( texList -> getEntity ( i ) ) ; + + if ( strcmp ( target->fname, tex ) == 0 ) + return i ; + } + + FLT_texture *add = new FLT_texture ; + + strncpy ( add->fname, tex, 199 ) ; + + texList -> addEntity ( add ) ; + return max ; +} + + +static int addToVertexPool ( FLT_vertex *vert ) +{ + int max = vtxList -> getNumEntities () ; + + for ( int i = 0 ; i < max ; i++ ) + { + FLT_vertex *target = (FLT_vertex *)( vtxList -> getEntity ( i ) ) ; + + if ( memcmp ( target, vert, sizeof ( FLT_vertex ) ) == 0 ) + return i ; + } + + FLT_vertex *add = new FLT_vertex ; + + *add = *vert ; + + vtxList -> addEntity ( add ) ; + return max ; +} + + +static int writeChar ( char val ) +{ + fwrite ( & val, sizeof(char), 1, save_fd ) ; + return sizeof(char) ; +} + + +static int writeShort ( short val ) +{ + writeChar ( (val >> 8) & 0xFF ) ; + writeChar ( val & 0xFF ) ; + return sizeof(short) ; +} + + +static int writeInt( int val ) +{ + writeChar ( (val >> 24) & 0xFF ) ; + writeChar ( (val >> 16) & 0xFF ) ; + writeChar ( (val >> 8 ) & 0xFF ) ; + writeChar ( val & 0xFF ) ; + return sizeof(int) ; +} + + +static void swabInt ( int *x ) +{ + unsigned int t = (unsigned int) *x ; + + *x = ((t & 0x000000FF) << 24) | + ((t & 0x0000FF00) << 8) | + ((t & 0x00FF0000) >> 8) | + ((t & 0xFF000000) >> 24) ; +} + + +static void swabFloat ( float *x ) +{ + int *a = (int *) x ; + + swabInt ( a ) ; +} + + +static void swabDouble ( double *x ) +{ + int *a = (int *) x ; + int *b = a+1 ; + + swabInt ( a ) ; + swabInt ( b ) ; + + *a = *a ^ *b ; + *b = *a ^ *b ; + *a = *a ^ *b ; +} + + + +static int writeFloat ( float val ) +{ + if ( ulIsLittleEndian ) + swabFloat ( & val ) ; + + fwrite ( & val, sizeof(float), 1, save_fd ) ; + return sizeof(float) ; +} + + +static int writeDouble( double val ) +{ + if ( ulIsLittleEndian ) + swabDouble ( & val ) ; + + fwrite ( & val, sizeof(double), 1, save_fd ) ; + return sizeof(double) ; +} + + +static int writeString( char *str, int slen ) +{ + fwrite ( str, sizeof(char), slen, save_fd ) ; + return slen ; +} + + + +static void writeHeader () +{ + int len = 0; + + len += writeShort ( 1 ) ; + len += writeShort ( 2+2+8+4+4+32+2+2+2+2+2+1+1+4+4+ + 4+4+4+4+4+4+4+4+4+4+4+4+4+2+2+ + 4+8+8+8+8+2+2+4+4+2+2+2+2+4+8+ + 8+8+8+8+8+8+8+2+2+2+2+2+2+2+2+ + 4+2+2+2+8+8+2+2 ) ; + + len += writeString( " ", 8 ) ; /* ID */ + len += writeInt ( 1570 ) ; /* Format Rev level 15.70 */ + len += writeInt ( 0 ) ; /* Edit rev level */ + len += writeString( "Unknown Date. ", 32 ) ; /* Date/Time */ + len += writeShort ( 0 ) ; /* Next Group Node */ + len += writeShort ( 0 ) ; /* Next LOD Node */ + len += writeShort ( 0 ) ; /* Next Object Node */ + len += writeShort ( 0 ) ; /* Next Face node */ + len += writeShort ( 1 ) ; /* Unit multiplier */ + len += writeChar ( 0 ) ; /* Unit type Meters */ + len += writeChar ( 0 ) ; /* TexWhite */ + len += writeInt ( 0 ) ; /* Flags */ + + len += writeInt ( 0 ) ; /* Reserved */ + len += writeInt ( 0 ) ; /* Reserved */ + len += writeInt ( 0 ) ; /* Reserved */ + len += writeInt ( 0 ) ; /* Reserved */ + len += writeInt ( 0 ) ; /* Reserved */ + len += writeInt ( 0 ) ; /* Reserved */ + len += writeInt ( 0 ) ; /* Projection Type */ + len += writeInt ( 0 ) ; /* Reserved */ + len += writeInt ( 0 ) ; /* Reserved */ + len += writeInt ( 0 ) ; /* Reserved */ + len += writeInt ( 0 ) ; /* Reserved */ + len += writeInt ( 0 ) ; /* Reserved */ + len += writeInt ( 0 ) ; /* Reserved */ + len += writeInt ( 0 ) ; /* Reserved */ + + len += writeShort ( 0 ) ; /* Next DOF node */ + len += writeShort ( 1 ) ; /* Vertex storage type (DOUBLE!) */ + len += writeInt ( 100 ) ; /* Database Origin */ + + len += writeDouble( 0 ) ; /* SW DB X */ + len += writeDouble( 0 ) ; /* SW DB Y */ + len += writeDouble( 0 ) ; /* Delta X */ + len += writeDouble( 0 ) ; /* Delta Y */ + + len += writeShort ( 0 ) ; /* Next Sound node */ + len += writeShort ( 0 ) ; /* Next Path node */ + + len += writeInt ( 0 ) ; /* Reserved */ + len += writeInt ( 0 ) ; /* Reserved */ + + len += writeShort ( 0 ) ; /* Next Clip node */ + len += writeShort ( 0 ) ; /* Next Text node */ + len += writeShort ( 0 ) ; /* Next BSP node */ + len += writeShort ( 0 ) ; /* Next Switch node */ + + len += writeInt ( 0 ) ; /* Reserved */ + + len += writeDouble( 0 ) ; /* SW Corner lat */ + len += writeDouble( 0 ) ; /* SW Corner lon */ + len += writeDouble( 0 ) ; /* NE Corner lat */ + len += writeDouble( 0 ) ; /* NE Corner lon */ + len += writeDouble( 0 ) ; /* Org Lat */ + len += writeDouble( 0 ) ; /* Org Lon */ + len += writeDouble( 0 ) ; /* Lambert upper lat */ + len += writeDouble( 0 ) ; /* Lambert upper lon */ + len += writeShort ( 0 ) ; /* Next Light source */ + len += writeShort ( 0 ) ; /* Next Light Point */ + len += writeShort ( 0 ) ; /* Next Road */ + len += writeShort ( 0 ) ; /* Next CAT */ + len += writeShort ( 0 ) ; /* Reserved */ + len += writeShort ( 0 ) ; /* Reserved */ + len += writeShort ( 0 ) ; /* Reserved */ + len += writeShort ( 0 ) ; /* Reserved */ + len += writeInt ( 0 ) ; /* Earth Ellipsoidal model (==WGS84) */ + len += writeShort ( 0 ) ; /* Next Adaptive node */ + len += writeShort ( 0 ) ; /* Next Curve node */ + len += writeShort ( 0 ) ; /* Reserved */ + len += writeDouble( 0 ) ; /* Delta Z to place */ + len += writeDouble( 0 ) ; /* Radius Z to place */ + len += writeShort ( 0 ) ; /* Next Mesh node */ + len += writeShort ( 0 ) ; /* Reserved */ +} + + +static void writePush () { writeShort ( 10 ) ; writeShort ( 4 ) ; } +static void writePop () { writeShort ( 11 ) ; writeShort ( 4 ) ; } + +static void writeObject () +{ + writeShort ( 4 ) ; + writeShort ( 2+2+8+4+2+2+2+2+2+2 ) ; + + static int next_name = 0 ; + char name [ 8 ] ; + sprintf ( name, "O%d", next_name++ ) ; + writeString ( name, 8 ) ; /* Name */ + writeInt ( 0x00000000 ) ; /* Flags */ + writeShort ( 0 ) ; /* Relative Priority */ + writeShort ( 0 ) ; /* Transparency (1-Alpha) */ + writeShort ( 0 ) ; /* Special ID 1 */ + writeShort ( 0 ) ; /* Special ID 2 */ + writeShort ( 0 ) ; /* Significance */ + writeShort ( 0 ) ; /* Layer */ +} + + + +static void writeFace ( ssgLeaf *leaf, int isLine ) +{ + writeShort ( 5 ) ; + writeShort ( 2+2+8+4+2+1+1+2+2+1+1+2+2+2+2+2+4+2+1+1+ + 4+1+1+2+4+4+4+2+2+4+4+2+2 ) ; + + static int next_name = 0 ; + char name [ 8 ] ; + sprintf ( name, "F%d", next_name++ ) ; + writeString ( name, 8 ) ; /* Name */ + writeInt ( 0 ) ; /* IR color code */ + writeShort ( 0 ) ; /* Relative Priority */ + writeChar ( isLine ? 2 : 0 ) ; /* Draw Type */ + writeChar ( 0 ) ; /* Texture-White */ + writeShort ( 0 ) ; /* Color name index */ + writeShort ( 0 ) ; /* Alternate Color name index */ + writeChar ( 0 ) ; + writeChar ( 0 ) ; /* Billboard */ + writeShort (-1 ) ; /* Detail Texture */ + + ssgSimpleState *s = (ssgSimpleState *)( leaf -> getState () ) ; + + if ( s != NULL && s -> getTextureFilename () != NULL ) + writeShort ( addToTexturePool ( s -> getTextureFilename () ) ) ; + else + writeShort (-1 ) ; /* No Texture */ + + writeShort (-1 ) ; /* Material */ + writeShort ( 0 ) ;/* XXXX */ /* SMC */ + writeShort ( 0 ) ; /* DFAD FID */ + writeInt ( 0 ) ; /* IR Material Code */ + writeShort ( 0 ) ; /* Transparent */ + writeChar ( 0 ) ; /* LOD generation control */ + writeChar ( 0 ) ; /* Line Style */ + writeInt ( 0x60000000 ) ; /* Flags == No Colour */ + writeChar ( 3 ) ; /* Light mode == Use Vertex colour & Normal */ + writeChar ( 0 ) ; + writeShort ( 0 ) ; + writeInt ( 0 ) ; + writeInt ( 0xFFFFFFFF ) ; /* Packed Color */ + writeInt ( 0xFFFFFFFF ) ; /* Packed Alt Color */ + writeShort ( 0 ) ; /* Texture mapping index */ + writeShort ( 0 ) ; + writeInt ( 0 ) ; /* Primary Color Index */ + writeInt ( 0 ) ; /* Secondary Color Index */ + writeShort ( 0 ) ; + writeShort ( 0 ) ; +} + +static void writeLeaf ( ssgLeaf *leaf ) +{ + int i ; + + writeObject () ; + writePush () ; + + for ( i = 0 ; i < leaf -> getNumLines () ; i++ ) + { + writeFace ( leaf, TRUE ) ; + + writePush () ; + writeShort ( 72 ) ; /* Vertex List */ + writeShort ( 2+2+4*2 ) ; + + short vv [ 2 ] ; + + leaf -> getLine ( i, &vv[0], &vv[1] ) ; + + for ( int j = 0 ; j < 2 ; j++ ) + { + FLT_vertex vert ; + sgCopyVec3 ( vert.vert, leaf -> getVertex ( vv[j] ) ) ; + sgCopyVec3 ( vert.norm, leaf -> getNormal ( vv[j] ) ) ; + sgCopyVec4 ( vert.col , leaf -> getColour ( vv[j] ) ) ; + sgCopyVec2 ( vert.tex , leaf -> getTexCoord ( vv[j] ) ) ; + + writeInt ( addToVertexPool ( & vert ) * 60 + 8 ) ; + } + + writePop () ; + } + + for ( i = 0 ; i < leaf -> getNumTriangles () ; i++ ) + { + writeFace ( leaf, FALSE ) ; + + writePush () ; + writeShort ( 72 ) ; /* Vertex List */ + writeShort ( 2+2+4*3 ) ; + + short vv [ 3 ] ; + + leaf -> getTriangle ( i, &vv[0], &vv[1], &vv[2] ) ; + + for ( int j = 0 ; j < 3 ; j++ ) + { + FLT_vertex vert ; + sgCopyVec3 ( vert.vert, leaf -> getVertex ( vv[j] ) ) ; + sgCopyVec3 ( vert.norm, leaf -> getNormal ( vv[j] ) ) ; + sgCopyVec4 ( vert.col , leaf -> getColour ( vv[j] ) ) ; + sgCopyVec2 ( vert.tex , leaf -> getTexCoord ( vv[j] ) ) ; + + writeInt ( addToVertexPool ( & vert ) * 60 + 8 ) ; + } + + writePop () ; + } + + writePop () ; +} + + +static void writeAnimationGroup () +{ + writeShort ( 2 ) ; + writeShort ( 2+2+8+2+2+4+2+2+2+1+1+4 ) ; + writeString ( "Animate", 8 ) ; /* Name */ + writeShort ( 0 ) ; /* Relative Priority */ + writeShort ( 0 ) ; + writeInt ( 0x40000000 ) ; /* Flags = Animate forwards */ + writeShort ( 100 ) ;/* Special ID 1 */ + writeShort ( 0 ) ; /* Special ID 2 */ + writeShort ( 0 ) ; /* Significance */ + writeChar ( 0 ) ; /* Layer */ + writeChar ( 0 ) ; + writeInt ( 0 ) ; +} + + +static void writeVanillaGroup () +{ + writeShort ( 2 ) ; + writeShort ( 2+2+8+2+2+4+2+2+2+1+1+4 ) ; + + static int next_name = 0 ; + char name [ 8 ] ; + sprintf ( name, "Q%d", next_name++ ) ; + writeString ( name, 8 ) ; /* Name */ + writeShort ( 0 ) ; /* Relative Priority */ + writeShort ( 0 ) ; + writeInt ( 0 ) ; /* Flags */ + writeShort ( 0 ) ; /* Special ID 1 */ + writeShort ( 0 ) ; /* Special ID 2 */ + writeShort ( 0 ) ; /* Significance */ + writeChar ( 0 ) ; /* Layer */ + writeChar ( 0 ) ; + writeInt ( 0 ) ; +} + + +static void writeGroup ( ssgBranch *bra ) +{ + writeShort ( 2 ) ; + writeShort ( 2+2+8+2+2+4+2+2+2+1+1+4 ) ; + + static int next_name = 0 ; + char name [ 8 ] ; + sprintf ( name, "G%d", next_name++ ) ; + writeString ( name, 8 ) ; /* Name */ + writeShort ( 0 ) ; /* Relative Priority */ + writeShort ( 0 ) ; + writeInt ( 0 ) ; /* Flags */ + writeShort ( 0 ) ; /* Special ID 1 */ + writeShort ( 0 ) ; /* Special ID 2 */ + writeShort ( 0 ) ; /* Significance */ + writeChar ( 0 ) ; /* Layer */ + writeChar ( 0 ) ; + writeInt ( 0 ) ; +} + + +static void writeEntity ( ssgEntity *ent ) +{ + if ( ent == NULL ) + return ; + + if ( ! ent -> isAKindOf ( ssgTypeBranch () ) ) + { + if ( ent -> isAKindOf ( ssgTypeTween () ) ) + ((ssgTween *)ent) -> setBank ( curr_bank ) ; + + writeLeaf ( (ssgLeaf *)ent ) ; + + if ( ent -> isAKindOf ( ssgTypeTween () ) ) + ((ssgTween *)ent) -> setBank ( 0 ) ; + + return ; + } + + if ( ((ssgBranch *)ent) -> getNumKids() == 0 ) + return ; + + writeGroup ( (ssgBranch *)ent ) ; + writePush () ; + + for ( int i = 0 ; i < ((ssgBranch *)ent) -> getNumKids() ; i++ ) + writeEntity ( ((ssgBranch *)ent) -> getKid ( i ) ) ; + + writePop () ; +} + + +static void collectPalettesFromLeaf ( ssgLeaf *leaf ) +{ + ssgSimpleState *s = (ssgSimpleState *)( leaf -> getState () ) ; + + if ( s != NULL && s -> getTextureFilename () != NULL ) + addToTexturePool ( s -> getTextureFilename () ) ; + + if ( leaf -> isAKindOf ( ssgTypeTween () ) ) + { + ssgTween *t = (ssgTween *) leaf ; + + if ( t -> getNumBanks () > max_bank ) max_bank = t -> getNumBanks () ; + + for ( int i = 0 ; i < t->getNumBanks() ; i++ ) + { + t -> setBank ( i ) ; + + for ( int i = 0 ; i < t -> getNumVertices () ; i++ ) + { + FLT_vertex vert ; + sgCopyVec3 ( vert.vert, t -> getVertex ( i ) ) ; + sgCopyVec3 ( vert.norm, t -> getNormal ( i ) ) ; + sgCopyVec4 ( vert.col , t -> getColour ( i ) ) ; + sgCopyVec2 ( vert.tex , t -> getTexCoord ( i ) ) ; + addToVertexPool ( & vert ) ; + } + } + + t -> setBank ( 0 ) ; + } + + for ( int i = 0 ; i < leaf -> getNumVertices () ; i++ ) + { + FLT_vertex vert ; + sgCopyVec3 ( vert.vert, leaf -> getVertex ( i ) ) ; + sgCopyVec3 ( vert.norm, leaf -> getNormal ( i ) ) ; + sgCopyVec4 ( vert.col , leaf -> getColour ( i ) ) ; + sgCopyVec2 ( vert.tex , leaf -> getTexCoord ( i ) ) ; + addToVertexPool ( & vert ) ; + } +} + +static void collectPalettes ( ssgEntity *ent ) +{ + if ( ent == NULL ) + return ; + + if ( ! ent -> isAKindOf ( ssgTypeBranch () ) ) + { + collectPalettesFromLeaf ( (ssgLeaf *)ent ) ; + return ; + } + + for ( int i = 0 ; i < ((ssgBranch *)ent) -> getNumKids() ; i++ ) + collectPalettes ( ((ssgBranch *)ent) -> getKid ( i ) ) ; +} + +static void writePalettes ( ssgEntity *root ) +{ + int i ; + + max_bank = 1 ; + + collectPalettes ( root ) ; + + for ( i = 0 ; i < texList -> getNumEntities () ; i++ ) + { + writeShort ( 64 ) ; /* Texture Palette */ + writeShort ( 2+2+200+4+4+4 ) ; + writeString ( ((FLT_texture *)(texList -> getEntity ( i )))->fname, 200 ) ; + writeInt ( i ) ; + writeInt ( i % 16 ) ; + writeInt ( i / 16 ) ; + } + + writeShort ( 67 ) ; /* Vertex Palette header. */ + writeShort ( 2+2+4 ) ; + writeInt ( 2+2+4 + + ( 2+2+2+2+8+8+8+4*3+4*2+4+4 ) * vtxList -> getNumEntities () ) ; + + for ( i = 0 ; i < vtxList -> getNumEntities () ; i++ ) + { + FLT_vertex *vv = (FLT_vertex *)(vtxList -> getEntity ( i )) ; + + writeShort ( 70 ) ; /* Vertex Palette with Normal and Texture */ + writeShort ( 2+2+2+2+8+8+8+4*3+4*2+4+4 ) ; + writeShort ( 0 ) ; /* Colour name index */ + writeShort ( 0x1000 ) ; /* Flags == Use Packed Colour */ + writeDouble ( vv -> vert [ 0 ] ) ; + writeDouble ( vv -> vert [ 1 ] ) ; + writeDouble ( vv -> vert [ 2 ] ) ; + writeFloat ( vv -> norm [ 0 ] ) ; + writeFloat ( vv -> norm [ 1 ] ) ; + writeFloat ( vv -> norm [ 2 ] ) ; + writeFloat ( vv -> tex [ 0 ] ) ; + writeFloat ( vv -> tex [ 1 ] ) ; + writeInt ( ( (int) ( vv -> col [ 3 ] * 255.0f ) << 24 ) + + ( (int) ( vv -> col [ 2 ] * 255.0f ) << 16 ) + + ( (int) ( vv -> col [ 1 ] * 255.0f ) << 8 ) + + ( (int) ( vv -> col [ 0 ] * 255.0f ) << 0 ) ) ; + writeInt ( 0 ) ; + } +} + + + +int ssgSaveFLT ( const char *fname, ssgEntity *root ) +{ + if ( ( save_fd = fopen ( fname, "wb") ) == NULL ) + { + fprintf ( stderr, "Could not open file '%s' for writing.\n", fname ) ; + return FALSE ; + } + + writeHeader () ; + + if ( texList == NULL ) texList = new ulList ( 20 ) ; + if ( vtxList == NULL ) vtxList = new ulList ( 200 ) ; + + writePalettes ( root ) ; + + writePush () ; + writeVanillaGroup () ; + writePush () ; + + if ( max_bank > 1 ) + { + writeAnimationGroup () ; + writePush () ; + } + + for ( int i = 0 ; i < max_bank ; i++ ) + { + curr_bank = i ; + writeEntity ( root ) ; + } + + if ( max_bank > 1 ) + writePop () ; + + writePop () ; + writePop () ; + + fclose ( save_fd ) ; + + /* Cleanup */ + +// This block is commented out because it +// seems to screw things up elsewhere. +// However, it needs to be there to avoid +// a memory leak. +// !! DEBUG ME!! +#ifdef PREVENT_MEMORY_LEAK + int max, i ; + + max = texList -> getNumEntities () ; + + for ( i = 0 ; i < max ; i++ ) + delete (FLT_texture *) texList -> getEntity ( i ) ; + delete texList ; + + max = vtxList -> getNumEntities () ; + + for ( i = 0 ; i < max ; i++ ) + delete (FLT_vertex *) vtxList -> getEntity ( i ) ; + delete vtxList ; +#endif + + return TRUE ; +} + + diff --git a/src/ssg/ssgSaveIV.cxx b/src/ssg/ssgSaveIV.cxx new file mode 100644 index 0000000..60e3a66 --- /dev/null +++ b/src/ssg/ssgSaveIV.cxx @@ -0,0 +1,301 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgSaveIV.cxx 2011 2005-01-15 17:59:31Z sjbaker $ +*/ + +// +// IV ( Open Inventor ASCII ) export for SSG/PLIB +// Written by Bram Stolk (bram at sara.nl) +// +// Keep in mind that: +// ssg's Transform's are non-leaf nodes, which correspond to Inventor's +// Transform nodes which are leaf nodes. +// Inventor's Material nodes are scene graph leaf nodes. +// The corresponding State objects from ssg however, are not scene graph nodes. +// +// DONE: +// scene graph hierarchy +// transformation +// states +// colour per vertex +// normal per vertex +// textures +// texture coordinates +// alpha transparency +// +// TODO: +// lights +// rendermodes +// + + +#include + +#include "ssgLocal.h" + + +// auxiliary stuff for indenting the inventor file. +static int indentLevel ; +static void indent ( FILE *f ) +{ + for ( int i=0; igetTransform( m ) ; + fprintf + ( + f, + "MatrixTransform { matrix %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f }\n", + m[0][0], m[0][1], m[0][2], m[0][3], + m[1][0], m[1][1], m[1][2], m[1][3], + m[2][0], m[2][1], m[2][2], m[2][3], + m[3][0], m[3][1], m[3][2], m[3][3] + ) ; +} + + +// ssg leaf nodes contain the geometry, which we will convert to +// Inventor's IndexedFaceSet. +static void writeLeaf ( ssgLeaf *leaf, FILE *f ) +{ + int cnt = leaf->getNumTriangles() ; + int nv = leaf->getNumVertices() ; + int nn = leaf->getNumNormals() ; + int nc = leaf->getNumColours() ; + int nt = leaf->getNumTexCoords() ; + + ssgState *st = leaf->getState() ; + ssgSimpleState *state = 0 ; + char *textureName = 0 ; + int i; + + indent( f ); + fprintf( f, "# %d triangles, %d verts, %d normals, %d colours, %d texturecoords\n", cnt, nv,nn,nc,nt ) ; + + if ( st && st -> isAKindOf ( ssgTypeSimpleState() ) ) + { + state = (ssgSimpleState*) st ; + textureName = state->getTextureFilename(); + } + else + state = NULL ; + + if ( state || nc ) + { + indent( f ) ; + fprintf( f, "Material {\n" ) ; + indentLevel++ ; + + indent( f ) ; + fprintf( f, "diffuseColor " ) ; + if ( nc ) + { + // multiple colour values: colour-per-vertex + fprintf( f, "[ " ) ; + for ( i=0; igetColour( i ) ; + fprintf( f,"%f %f %f, ", col[0],col[1],col[2] ) ; + } + fprintf( f, "]\n" ) ; + } + else + { + // single colour value + float r=0, g=0, b=0; + if ( state ) + { + r = state->diffuse_colour[ 0 ] ; + g = state->diffuse_colour[ 1 ] ; + b = state->diffuse_colour[ 2 ] ; + } + fprintf( f, "%f %f %f\n", r,g,b ) ; + } + if ( state ) + { + indent( f ); + fprintf( f,"ambientColor %f %f %f\n", state->ambient_colour[0], state->ambient_colour[1], state->ambient_colour[2] ) ; + indent( f ); + fprintf( f,"specularColor %f %f %f\n", state->specular_colour[0], state->specular_colour[1], state->specular_colour[2] ) ; + indent( f ); + fprintf( f,"emissiveColor %f %f %f\n", state->emission_colour[0], state->emission_colour[1], state->emission_colour[2] ) ; + indent( f ); + fprintf( f, "shininess %f\n", state->shininess ) ; + if ( state->isEnabled( GL_BLEND ) ) + { + float a = state->diffuse_colour[ 3 ] ; + indent( f ) ; + fprintf( f, "transparency %f\n", 1.0-a ); + } + } + + indentLevel-- ; + indent( f ) ; + fprintf( f, "}\n" ) ; + } + + if ( textureName ) + { + indent( f ) ; + fprintf( f, "Texture2 { filename %c%s%c }\n", '"', textureName, '"' ) ; + } + + if ( nn ) + { + indent( f ) ; + fprintf( f, "Normal {\n") ; + indentLevel++ ; + + indent( f ) ; + fprintf( f, "vector [ " ) ; + for ( i=0; igetNormal( i ) ; + fprintf( f, "%f %f %f, ", nrm[ 0 ], nrm[ 1 ], nrm[ 2 ] ); + } + fprintf( f, " ]\n" ); + indentLevel-- ; + + indent( f ) ; + fprintf( f, "}\n" ) ; + } + + if ( nt && textureName ) + { + indent( f ) ; + fprintf( f, "SoTextureCoordinate2 { point [ " ) ; + for ( i=0; igetTexCoord( i ) ; + fprintf( f, "%f %f, ", t[ 0 ], t[ 1 ] ) ; + } + fprintf( f, " ] }\n" ) ; + } + + indent( f ) ; + fprintf( f, "Coordinate3 { point [ " ) ; + for ( i=0; igetVertex( i ) ; + assert( v ) ; + fprintf( f, "%f %f %f, ", v[ 0 ], v[ 1 ], v[ 2 ] ) ; + } + fprintf( f, " ] }\n" ) ; + + indent( f ) ; + fprintf( f, "IndexedFaceSet {\n" ) ; + + indent( f ) ; + fprintf( f, " coordIndex [ " ) ; + for ( i=0; igetTriangle( i, &idx0, &idx1, &idx2 ) ; + fprintf( f, "%d,%d,%d,-1,", idx0, idx1, idx2 ) ; + } + + fprintf( f, " ]\n" ) ; + indent( f ) ; + fprintf( f, "}\n" ) ; +} + + +// Handles pre-order traversal of the ssg hierarchy. +static void preHandle ( ssgEntity *ent, FILE *f ) +{ + // Put some comments in the inventor output file. + indent( f ) ; + const char *name = ent->getName() ; + fprintf( f, "# %s (%s)\n", ent->getTypeName(), (name)?name:"unnamed") ; + + if ( ent && ent -> isAKindOf ( ssgTypeBranch () ) ) + { + ssgBranch *branch = (ssgBranch*) ent ; + + // ssg's branch nodes are translated to inventor's separator node. + indent( f ) ; + fprintf( f,"Separator {\n" ) ; + indentLevel++ ; + + if ( branch -> isAKindOf ( ssgTypeTransform() ) ) + writeTransform( (ssgTransform*) branch, f ) ; + } + else + writeLeaf( (ssgLeaf*) ent, f ) ; +} + + +// Handles post-order traversal of the ssg hierarchy. +static void postHandle ( ssgEntity *ent, FILE *f ) +{ + if ( ent && ent -> isAKindOf ( ssgTypeBranch() ) ) + { + // For branches, we use IV's Seperator, which we need to close now. + indentLevel-- ; + indent( f ) ; + fprintf( f, "}\n" ) ; + } +} + + +// Traverses ssg hierarchy. +static void walkTree ( ssgEntity *ent, FILE *f ) +{ + preHandle( ent, f ) ; + if ( ent && ent -> isAKindOf ( ssgTypeBranch() ) ) + { + ssgBranch *branch = (ssgBranch*) ent ; + + for ( int i=0; igetNumKids(); i++ ) + { + ssgEntity *kid = branch->getKid( i ); + assert( kid ) ; + walkTree( kid, f ) ; + } + } + postHandle( ent, f ) ; +} + + +// Entry point: save ssg hierarchy as an OpenInventor file. +int ssgSaveIV ( const char *filename, ssgEntity *ent ) +{ + FILE *f = fopen( filename, "w" ) ; + if ( !f ) + return FALSE ; + fprintf( f, "#Inventor V2.1 ascii\n" ) ; + fprintf + ( + f, + "#Export from plib version %d.%d.%d\n\n", + PLIB_MAJOR_VERSION, PLIB_MINOR_VERSION, PLIB_TINY_VERSION + ) ; + indentLevel = 0 ; + walkTree( ent, f ) ; + return TRUE ; +} + diff --git a/src/ssg/ssgSaveM.cxx b/src/ssg/ssgSaveM.cxx new file mode 100644 index 0000000..ee81636 --- /dev/null +++ b/src/ssg/ssgSaveM.cxx @@ -0,0 +1,70 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgSaveM.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + +#include +#include "ssgLocal.h" +#include "ssgLoaderWriterStuff.h" + + + +int ssgSaveM( const char* fname, ssgEntity *ent ) { + FILE *fd = fopen ( fname, "w" ) ; + int i; + + if ( fd == NULL ) { + ulSetError ( UL_WARNING, "ssgSaveM: Failed to open '%s' for writing", + fname ); + return FALSE ; + } + + ssgVertexArray* vertices = new ssgVertexArray(); + ssgIndexArray* indices = new ssgIndexArray (); + + fprintf(fd, "# Model output by ssgSaveM. Original graph structure was:\n"); + ent->print(fd, "#", 0); + + sgMat4 ident; + sgMakeIdentMat4( ident ); + ssgAccumVerticesAndFaces( ent, ident, vertices, indices, -1 ); + + for (i = 0; i < vertices->getNum(); i++) { + fprintf(fd, "Vertex %d %f %f %f\n", i+1, + vertices->get(i)[0], + vertices->get(i)[1], + vertices->get(i)[2]); + } + + for (i = 0; i < indices->getNum(); i += 3) { + fprintf(fd, "Face %d %d %d %d\n", (i/3)+1, + *indices->get(i ) + 1, + *indices->get(i + 1) + 1, + *indices->get(i + 2) + 1); + } + + fclose( fd ) ; + + delete vertices; + delete indices ; + + return TRUE; +} diff --git a/src/ssg/ssgSaveOBJ.cxx b/src/ssg/ssgSaveOBJ.cxx new file mode 100644 index 0000000..2f36715 --- /dev/null +++ b/src/ssg/ssgSaveOBJ.cxx @@ -0,0 +1,349 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgSaveOBJ.cxx 2170 2012-08-14 17:51:34Z wolfram_kuss $ +*/ + +// +// Wavefront OBJ export for SSG/PLIB +// Ported from IVCON by Dave McClurg (dpm@efn.org) in March-2000 +// + +#include "ssgLocal.h" + +static FILE *fileout ; +static int total_vert ; +static int total_texture ; +static int total_normal ; +static ssgSimpleStateArray gSSL; + +/* unused +static void MakeIdentifier( char *Dest, const char *Source ) +// pDest is a buffer that is at least of size strlen(pSource)+1 +{ + char *pDest; + const char *pSource; + pDest = Dest; + pSource = Source; + + while ( *pSource != '\0' ) + { + if ((*pSource != '\\') && (*pSource != '.') && (*pSource != '/') && (*pSource != ' ')) + *pDest++ = *pSource++; + else + pSource++; + } + *pDest = '\0'; +}*/ + +static void save_vtx_table ( ssgVtxTable *vt ) +{ + float w = 1.0f ; + short iv1, iv2; + + GLenum mode = vt -> getPrimitiveType () ; + //fprintf ( fileout, "g test\n" ); wk: Pfusch fixme: is this necessary? NIV135 + char *s = vt->getName() ; + fprintf ( fileout, "\ng %s\n\n", s == NULL ? "Object" : s); + + + if (( mode == GL_LINES ) || ( mode == GL_LINE_LOOP) || ( mode == GL_LINE_STRIP)) + { + int num_vert = vt -> getNumVertices () ; + + // V: vertex coordinates. + for ( int i = 0; i < num_vert; i++ ) { + sgVec3 vert ; + sgCopyVec3 ( vert, vt -> getVertex ( i ) ) ; + fprintf ( fileout, "v %f %f %f %f\n", + vert[0], vert[1], vert[2], w ); + } + + + + // L: lines. + fprintf ( fileout, "\n" ); + int num_lines = vt -> getNumLines () ; + for ( int j = 0; j < num_lines; j ++ ) + { vt -> getLine ( j, &iv1, &iv2 ) ; + fprintf ( fileout, "l %d %d\n", + total_vert + j + 1, + total_vert + j + 2 ); + } + + total_vert += num_vert ; + } + else if ( mode == GL_TRIANGLES || + mode == GL_TRIANGLE_FAN || + mode == GL_TRIANGLE_STRIP ) + { + int num_vert = vt -> getNumVertices () ; + bool haveTexture = FALSE; + + ssgSimpleState* st = (ssgSimpleState*) vt->getState(); + if ( st ) + { + if ( NULL == gSSL.findMatch(st, TRUE) ) + gSSL.add(st); + haveTexture = TRUE; + fprintf ( fileout, "usemtl %s\n", st -> getName() ); + } + + // V: vertex coordinates. + for ( int i = 0; i < num_vert; i++ ) { + sgVec3 vert ; + sgCopyVec3 ( vert, vt -> getVertex ( i ) ) ; + fprintf ( fileout, "v %f %f %f %f\n", + vert[0], vert[1], vert[2], w ); + } + + if ( haveTexture ) + // VT: vertex coordinates. + { + long ntc = vt->getNumTexCoords(); + fprintf ( fileout, "\n" ); + //fprintf ( fileout, "# num_vert = %ld, NumTexCoords = %ld\n", (long)num_vert, ntc); + for ( int i = 0; i < num_vert; i++ ) { + sgVec2 tc ; + sgCopyVec2 ( tc, vt -> getTexCoord( i ) ) ; + fprintf ( fileout, "vt %f %f\n", + tc[0], tc[1] ); + } + } + + + // VN: Vertex face normal vectors. + bool haveNormals = ( vt -> getNumNormals () >= num_vert ) ; + if ( haveNormals ) + { + fprintf ( fileout, "\n" ); + for ( int i = 0; i < num_vert; i++ ) { + sgVec3 vert ; + sgCopyVec3 ( vert, vt -> getNormal ( i ) ) ; + fprintf ( fileout, "vn %f %f %f\n", + vert[0], vert[1], vert[2] ); + } + } + + // F: faces. + fprintf ( fileout, "\n" ); + int num_face = vt -> getNumTriangles () ; + for ( int j = 0; j < num_face; j++ ) + { + short face[3]; + vt -> getTriangle ( j, &face[0], &face[1], &face[2] ) ; + + fprintf ( fileout, "f" ); + for ( int ivert = 0; ivert < 3; ivert++ ) { + if ( haveNormals ) + { + if ( haveTexture ) + fprintf ( fileout, " %d/%d/%d", + total_vert + face[ivert] + 1, + total_texture + face[ivert] + 1, + total_normal + face[ivert] + 1 ); + else + fprintf ( fileout, " %d//%d", + total_vert + face[ivert] + 1, + total_normal + face[ivert] + 1 ); + } + else + fprintf ( fileout, " %d", + total_vert + face[ivert] + 1 ); + } + fprintf ( fileout, "\n" ); + } + + total_vert += num_vert ; + if ( haveNormals ) + total_normal += num_vert ; + if ( haveTexture ) + total_texture += num_vert ; + } +} + + +static void save_entities ( ssgEntity *e ) +{ + if ( e -> isAKindOf ( ssgTypeBranch() ) ) + { + ssgBranch *br = (ssgBranch *) e ; + + for ( int i = 0 ; i < br -> getNumKids () ; i++ ) + save_entities ( br -> getKid ( i ) ) ; + } + else + if ( e -> isAKindOf ( ssgTypeVtxTable() ) ) + { + ssgVtxTable *vt = (ssgVtxTable *) e ; + save_vtx_table ( vt ) ; + } +} + + +/******************************************************************************/ + +int ssgSaveOBJ ( const char *filename, ssgEntity *ent ) + +/******************************************************************************/ + +/* + Purpose: + + OBJ_WRITE writes a Wavefront OBJ file. + + Example: + + # magnolia.obj + + mtllib ./vp.mtl + + g + v -3.269770 -39.572201 0.876128 + v -3.263720 -39.507999 2.160890 + ... + v 0.000000 -9.988540 0.000000 + g stem + s 1 + usemtl brownskn + f 8 9 11 10 + f 12 13 15 14 + ... + f 788 806 774 + + Modified: + + 01 September 1998 + + Author: + + John Burkardt +*/ +{ + fileout = fopen ( filename, SSG_SAVE_TEXT_FILE ) ; + + if ( fileout == NULL ) + { + ulSetError ( UL_WARNING, "ssgSaveOBJ: Failed to open '%s' for writing", filename ) ; + return FALSE ; + } + +/* + Initialize. +*/ + fprintf ( fileout, "# %s created by SSG.\n", filename ); + fprintf ( fileout, "\n" ); + + + int i; + char *MTL_FileName; + + if( strlen( filename ) > 4 ) + { + // decide on name for the MTL (material) file. Write a reference to the MTL file into the obj file (fileout) + + char *p, *p1; + MTL_FileName = new char[ strlen(filename)+1 ]; + strcpy ( MTL_FileName, filename ); + p = MTL_FileName + strlen ( MTL_FileName ) -4; // should point to '.' now + strcpy (p, ".mtl"); + + // Experiment tells that mtllib may not contain a path. + p = strrchr( MTL_FileName, '\\' ); + p1 = strrchr( MTL_FileName, '/' ); + if (( p == NULL) || (p < p1)) + p = p1; + if ( !p ) // MTL_FileName seems to contain no path + p = MTL_FileName; + else + p++; + + fprintf ( fileout, "mtllib %s\n", p ); // Kludge: Unused if nothing is textured + } + + total_vert = 0 ; + total_texture = 0; + total_normal = 0 ; + + save_entities ( ent ) ; + +/* + Close OBJ. +*/ + fclose ( fileout ) ; + // write MTL file + if ((gSSL.getNum() > 0) && ( strlen(filename) > 4)) + { + // open the file + fileout = fopen ( MTL_FileName, SSG_SAVE_TEXT_FILE ) ; + delete [] MTL_FileName; + + for(i = 0; i < gSSL.getNum(); i++) + { + ssgSimpleState *ss = gSSL.get(i); + fprintf ( fileout, "\n\nnewmtl %s\n", ss->getName()); + + /* From IT5 sample: + newmtl sitzkissen + Ka 0.300000 0.300000 0.300000 + Kd 0.700000 0.700000 0.700000 + Ks 0.735000 0.735000 0.735000 + Ns 20.000000 + Tr 0.000000 + illum 2 + map_Kd chair_demo_texture2.jpg + + */ + fprintf ( fileout, "Ka 0.7 0.7 0.7\n"); + fprintf ( fileout, "Kd 0.3 0.3 0.3\n"); + fprintf ( fileout, "Ks 1 1 1\n"); + fprintf ( fileout, "illum 2\n"); + fprintf ( fileout, "Ns 32\n"); // specular exponent + // Tr 0.000000 + + if (ss -> isEnabled ( GL_TEXTURE_2D ) ) + { + char *TextureName = ss->getTextureFilename(); + char *p = TextureName; + if ((p[0] == '.') && (p[1] == '/')) + p += 2; + //char *p = new char [ strlen(TextureName) + 1 ]; + //MakeIdentifier( p, TextureName ); + fprintf ( fileout, "map_Kd %s\n", p); + //delete [] p; + } + + /*fprintf ( fileout, "map_bump\n"); + fprintf ( fileout, "bump\n"); + fprintf ( fileout, "map_opacity\n"); + fprintf ( fileout, "map_d\n"); + fprintf ( fileout, "refl\n"); + fprintf ( fileout, "map_kS\n"); + fprintf ( fileout, "map_kA\n"); + fprintf ( fileout, "map_Ns\n");*/ + } + // close the MTL + fclose ( fileout ) ; + } + + gSSL.removeAll(); + + return TRUE; +} diff --git a/src/ssg/ssgSaveOFF.cxx b/src/ssg/ssgSaveOFF.cxx new file mode 100644 index 0000000..be63298 --- /dev/null +++ b/src/ssg/ssgSaveOFF.cxx @@ -0,0 +1,79 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgSaveOFF.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ +/* + .off writer for SSG/PLIB + Warning: There are two formats called OFF, see comment in ssgLoadOFF + + Written by Wolfram Kuss (Wolfram.Kuss@t-online.de) in February 2001 + + We only support 2D and 3D data +*/ + +#include +#include "ssgLocal.h" +#include "ssgLoaderWriterStuff.h" + + + +int ssgSaveOFF( const char* fname, ssgEntity *ent ) { + FILE *fd = fopen ( fname, "w" ) ; + int i; + + if ( fd == NULL ) { + ulSetError ( UL_WARNING, "ssgSaveOFF: Failed to open '%s' for writing", + fname ); + return FALSE ; + } + + ssgVertexArray* vertices = new ssgVertexArray(); + ssgIndexArray* indices = new ssgIndexArray (); + + fprintf(fd, "# Model output by ssgSaveOFF. Original graph structure was:\n"); + ent->print(fd, "#", 0); + + sgMat4 ident; + sgMakeIdentMat4( ident ); + ssgAccumVerticesAndFaces( ent, ident, vertices, indices, -1 ); + + fprintf(fd, "nOFF\n3\n"); // 3 dimensions + fprintf(fd, "%d %d 0\n", vertices->getNum(), indices->getNum()/3 ); + + for (i = 0; i < vertices->getNum(); i++) { + fprintf(fd, "%f %f %f\n", vertices->get(i)[0], + vertices->get(i)[1], + vertices->get(i)[2]); + } + + for (i = 0; i < indices->getNum(); i += 3) { + fprintf(fd, "3 %d %d %d\n", *indices->get(i ) , + *indices->get(i + 1) , + *indices->get(i + 2) ); + } + + fclose( fd ) ; + + delete vertices; + delete indices ; + + return TRUE; +} diff --git a/src/ssg/ssgSaveQHI.cxx b/src/ssg/ssgSaveQHI.cxx new file mode 100644 index 0000000..aca69e7 --- /dev/null +++ b/src/ssg/ssgSaveQHI.cxx @@ -0,0 +1,63 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgSaveQHI.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + +#include +#include "ssgLocal.h" +#include "ssgLoaderWriterStuff.h" + + + +int ssgSaveQHI( const char* fname, ssgEntity *ent ) { + FILE *fd = fopen ( fname, "w" ) ; + int i; + + if ( fd == NULL ) { + ulSetError ( UL_WARNING, "ssgSaveQHI: Failed to open '%s' for writing", + fname ); + return FALSE ; + } + + ssgVertexArray* vertices = new ssgVertexArray(); + + + sgMat4 ident; + sgMakeIdentMat4( ident ); + ssgAccumVerticesAndFaces( ent, ident, vertices, NULL, 0.0001f ); + + fprintf(fd, "3\n"); // Dimension + fprintf(fd, "%d\n", vertices->getNum()); // No of points + + // Points: + for (i = 0; i < vertices->getNum(); i++) { + fprintf(fd, "%f %f %f\n", vertices->get(i)[0], + vertices->get(i)[1], + vertices->get(i)[2]); + } + + + fclose( fd ) ; + + delete vertices; + + return TRUE; +} diff --git a/src/ssg/ssgSaveTRI.cxx b/src/ssg/ssgSaveTRI.cxx new file mode 100644 index 0000000..40b9bca --- /dev/null +++ b/src/ssg/ssgSaveTRI.cxx @@ -0,0 +1,111 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgSaveTRI.cxx 2169 2012-08-14 17:28:50Z wolfram_kuss $ +*/ + +// +// TRI ( AC3D triangle file ) export for SSG/PLIB +// Written by Dave McClurg (dpm@efn.org) in March-2000 +// + +#include "ssgLocal.h" + +static FILE *fileout ; + + +static void save_vtx_table ( ssgVtxTable *vt ) +{ + GLenum mode = vt -> getPrimitiveType () ; + if ( mode == GL_TRIANGLES || + mode == GL_TRIANGLE_FAN || + mode == GL_TRIANGLE_STRIP ) + { + int num_tri = vt -> getNumTriangles () ; + for ( int i = 0; i < num_tri; i++ ) + { + short tri[3]; + vt -> getTriangle ( i, &tri[0], &tri[1], &tri[2] ) ; + + for ( int j = 0; j < 3; j ++ ) + { + sgVec3 vert; + sgCopyVec3 ( vert, vt->getVertex ( tri[j] ) ) ; + fprintf ( fileout, "%f %f %f ", vert[0], vert[1], vert[2] ) ; + } + + fprintf ( fileout, "0xFFFFFF\n" ) ; + } + } +} + + +static void save_entities ( ssgEntity *e ) +{ + if ( e -> isAKindOf ( ssgTypeBranch() ) ) + { + ssgBranch *br = (ssgBranch *) e ; + + for ( int i = 0 ; i < br -> getNumKids () ; i++ ) + save_entities ( br -> getKid ( i ) ) ; + } + else + if ( e -> isAKindOf ( ssgTypeVtxTable() ) ) + { + ssgVtxTable *vt = (ssgVtxTable *) e ; + save_vtx_table ( vt ) ; + } +} + + +/******************************************************************************/ + +int ssgSaveTRI ( const char *filename, ssgEntity *ent ) + +/******************************************************************************/ + +/* + Purpose: + + writes an AC3D triangle file. + + Example: + + Each line contains 9 floating point values and a 1 hex value for color. + the 9 floating point values represent 3 vertices of a triangle + the color format is 0xRRGGBB (eg 0xffffff is white) + + 0.0 0.0 0.0 1.0 0.0 0.0 1.0 1.0 0.0 0xffffff + +*/ +{ + fileout = fopen ( filename, SSG_SAVE_TEXT_FILE ) ; + + if ( fileout == NULL ) + { + ulSetError ( UL_WARNING, "ssgSaveTRI: Failed to open '%s' for writing", filename ) ; + return FALSE ; + } + + save_entities ( ent ) ; + + fclose ( fileout ) ; + return TRUE; +} diff --git a/src/ssg/ssgSaveVRML1.cxx b/src/ssg/ssgSaveVRML1.cxx new file mode 100644 index 0000000..b5a37d5 --- /dev/null +++ b/src/ssg/ssgSaveVRML1.cxx @@ -0,0 +1,449 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgSaveVRML1.cxx 1568 2002-09-02 06:05:49Z sjbaker $ + + -------------------------------------------------------------------- + + This save routine was written by Warren Wilbur to support a sub-set + of the standard Virtual Reality Modelling Language v1.0 (i.e. VRML1.0). + The Version 1.0 Specification, 9-Nov-95 was used and should be available + at www.vrml.org + + When reporting bugs/difficulties please mention 'VRML' in the subject + of your email and post to the plib developers mailing list. +*/ + +#include +#include "ssgLocal.h" +#include "ssgLoaderWriterStuff.h" + +/* Function name: SaveVRML1MaterialNode + * + * Limitations: Before calling this function you must verify that + * at least one material exists whose textureName + * matches the one passed in to this function, + * otherwise you might save a empty Material node! + * + * Notes: Saving empty Material notes will create an + * unnecessary choking hazard for VRML loaders :( + */ + +static void SaveVRML1MaterialNode(FILE *fd, ssgIndexArray *materials_ptr, + ssgSimpleStateArray *ssa_ptr, + char *textureName, bool saveDiffuse, + bool saveAmbient, bool saveEmission, + bool saveSpecular) +{ + ssgSimpleState *ss_ptr; + int i; + + /* Tell VRML loaders that we are providing a single color for each + * face in the array of indices written below. */ + + fprintf(fd, " MaterialBinding { value PER_FACE }\n"); + fprintf(fd, " Material {\n"); + + if (saveDiffuse) + { + fprintf(fd, " diffuseColor [\n"); + for (i = 0; i < materials_ptr->getNum(); i++) + { + ss_ptr = ssa_ptr->get(*(materials_ptr->get(i))); + + /* If we are trying to save all untextured materials then check + * if either ptr is NULL */ + + if ( ( (textureName == NULL)&& + ((ss_ptr == NULL)||(ss_ptr->getTextureFilename() == NULL)) )|| + + /* If we are trying to save all materials that are textured by + * a specific texture then check if the texture filename matches */ + + ( (textureName != NULL)&&(ss_ptr != NULL)&& + (ss_ptr->getTextureFilename() != NULL)&& + (!strcmp(textureName, ss_ptr->getTextureFilename())) ) ) + { + float diffuse0, diffuse1, diffuse2; + + diffuse0 = ss_ptr->diffuse_colour[0]; + diffuse1 = ss_ptr->diffuse_colour[1]; + diffuse2 = ss_ptr->diffuse_colour[2]; + +#ifdef EXPERIMENTAL_ADD_AMBIENT_TO_DIFFUSE + diffuse0 += ss_ptr->ambient_colour[0]; + diffuse1 += ss_ptr->ambient_colour[1]; + diffuse2 += ss_ptr->ambient_colour[2]; +#endif //EXPERIMENTAL_ADD_AMBIENT_TO_DIFFUSE + +#ifdef EXPERIMENTAL_ADD_EMISSION_TO_DIFFUSE + diffuse0 += ss_ptr->emission_colour[0]; + diffuse1 += ss_ptr->emission_colour[1]; + diffuse2 += ss_ptr->emission_colour[2]; +#endif //EXPERIMENTAL_ADD_EMISSION_TO_DIFFUSE + +#ifdef EXPERIMENTAL_ADD_SPECULAR_TO_DIFFUSE + diffuse0 += ss_ptr->specular_colour[0]; + diffuse1 += ss_ptr->specular_colour[1]; + diffuse2 += ss_ptr->specular_colour[2]; +#endif //EXPERIMENTAL_ADD_SPECULAR_TO_DIFFUSE + + /* OpenGL caps the maximum RGB value for a colour to 1.0 when it + * calculates colours in a scene. If we don't cap the value OpenGL + * will do it for us. */ + + fprintf(fd, " %f %f %f,\n", diffuse0 > 1.0 ? 1.0:diffuse0, + diffuse1 > 1.0 ? 1.0:diffuse1, diffuse2 > 1.0 ? 1.0:diffuse2); + } + } + fprintf(fd, " ]\n"); //close diffuseColor array + } + + if (saveAmbient) + { + fprintf(fd, " ambientColor [\n"); + for (i = 0; i < materials_ptr->getNum(); i++) + { + ss_ptr = ssa_ptr->get(*(materials_ptr->get(i))); + + /* If we are trying to save all untextured materials then check + * if either ptr is NULL */ + + if ( ( (textureName == NULL)&& + ((ss_ptr == NULL)||(ss_ptr->getTextureFilename() == NULL)) )|| + + /* If we are trying to save all materials that are textured by + * a specific texture then check if the texture filename matches */ + + ( (textureName != NULL)&&(ss_ptr != NULL)&& + (ss_ptr->getTextureFilename() != NULL)&& + (!strcmp(textureName, ss_ptr->getTextureFilename())) ) ) + { + fprintf(fd, " %f %f %f,\n", ss_ptr->ambient_colour[0], + ss_ptr->ambient_colour[1], ss_ptr->ambient_colour[2]); + } + fprintf(fd, " ]\n"); //close ambientColor array + } + } + + if(saveEmission) + { + fprintf(fd, " emissiveColor [\n"); + for (i = 0; i < materials_ptr->getNum(); i++) + { + ss_ptr = ssa_ptr->get(*(materials_ptr->get(i))); + + /* If we are trying to save all untextured materials then check + * if either ptr is NULL */ + + if ( ( (textureName == NULL)&& + ((ss_ptr == NULL)||(ss_ptr->getTextureFilename() == NULL)) )|| + + /* If we are trying to save all materials that are textured by + * a specific texture then check if the texture filename matches */ + + ( (textureName != NULL)&&(ss_ptr != NULL)&& + (ss_ptr->getTextureFilename() != NULL)&& + (!strcmp(textureName, ss_ptr->getTextureFilename())) ) ) + { + fprintf(fd, " %f %f %f,\n", ss_ptr->emission_colour[0], + ss_ptr->emission_colour[1], ss_ptr->emission_colour[2]); + } + fprintf(fd, " ]\n"); //close emissionColor array + } + } + + if(saveSpecular) + { + fprintf(fd, " specularColor [\n"); + for (i = 0; i < materials_ptr->getNum(); i++) + { + ss_ptr = ssa_ptr->get(*(materials_ptr->get(i))); + + /* If we are trying to save all untextured materials then check + * if either ptr is NULL */ + + if ( ( (textureName == NULL)&& + ((ss_ptr == NULL)||(ss_ptr->getTextureFilename() == NULL)) )|| + + /* If we are trying to save all materials that are textured by + * a specific texture then check if the texture filename matches */ + + ( (textureName != NULL)&&(ss_ptr != NULL)&& + (ss_ptr->getTextureFilename() != NULL)&& + (!strcmp(textureName, ss_ptr->getTextureFilename())) ) ) + { + fprintf(fd, " %f %f %f,\n", ss_ptr->specular_colour[0], + ss_ptr->specular_colour[1], ss_ptr->specular_colour[2]); + } + fprintf(fd, " ]\n"); //close specularColor array + } + } + + fprintf(fd, " }\n"); //close Material node + return; +} + +/* The 'main' entry point for saving a model in VRML1.0 */ + +int ssgSaveVRML1( const char* fname, ssgEntity *ent ) { + ssgVertexArray *vertices_ptr; + ssgIndexArray *indices_ptr; + FILE *fd; + ssgSimpleStateArray ssa; + ssgTexCoordArray *texcoord_ptr; + ssgIndexArray *materials_ptr; + bool textured_faces_found, untextured_faces_found, + textureFacesAlreadySaved; + int i, j, index1, index2, index3; + ssgSimpleState *ss_ptr, *ss_ptr2; + + fd = fopen ( fname, "w" ) ; + if ( fd == NULL ) + { + ulSetError ( UL_WARNING, "ssgSaveVRML1: Failed to open '%s' for writing", + fname ); + return FALSE ; + } + + vertices_ptr = new ssgVertexArray(); + indices_ptr = new ssgIndexArray(); + materials_ptr = new ssgIndexArray(); + texcoord_ptr = new ssgTexCoordArray(); + + sgMat4 ident; + sgMakeIdentMat4( ident ); + ssgAccumVerticesAndFaces( ent, ident, vertices_ptr, indices_ptr, -1.0f, + &ssa, materials_ptr, texcoord_ptr); + + /* The spec requires every file to begin with these characters */ + + fprintf(fd, "#VRML V1.0 ascii\n\n"); + + /* Since a VRML file contains only one parent node we must use a + * node type that can have several child 'nodes' so we can save + * the materials, texture coordinates, vertices, and indices each + * as (seperate) child nodes. */ + + fprintf(fd, "Separator {\n"); + + /* Save all the individual vertices used in the model. It doesn't + * matter if there are duplicates... */ + + fprintf(fd, " Coordinate3 {\n point [\n"); + + for (i = 0; i < vertices_ptr->getNum(); i++) + { + fprintf(fd, " %f %f %f,\n", vertices_ptr->get(i)[0], + vertices_ptr->get(i)[1], vertices_ptr->get(i)[2]); + } + + fprintf(fd, " ]\n }\n"); //close point array and + //Coordinate3 + + /* Chcck if the model is textured at all. This test will help us parse + * out how to save the model since it may be totally textured, partially + * textured, or not textured at all. */ + + textured_faces_found = false; + untextured_faces_found = false; + for (i = 0; i < materials_ptr->getNum(); i++) + { + ss_ptr = ssa.get(*(materials_ptr->get(i))); + if ( (ss_ptr != NULL)&&(ss_ptr->getTextureFilename() != NULL) ) + { + textured_faces_found = true; + } + else + { + untextured_faces_found = true; + } + } + + if (untextured_faces_found) + { + /* Save all the material node fields which VRML supports. Note that the + * VRML spec discourages complicated uses of the Material Node. We + * cannot expect VRML implementations to support the full syntax + * of the Material Node including ambient, diffuse, specular, emissive, + * shininess, and transparency. We should be always be okay if we just + * use diffuse. */ + + SaveVRML1MaterialNode(fd, materials_ptr, &ssa, NULL, + true, false, false, false); + + /* Save all faces that are not textured in a single IndexedFaceSet node */ + + fprintf(fd, " IndexedFaceSet {\n coordIndex [\n"); + for (i = 0; i < indices_ptr->getNum(); i+=3) + { + ss_ptr = ssa.get(*(materials_ptr->get(i/3))); + + /* Make sure this face doesn't have a texture associated with it */ + + if ( (ss_ptr == NULL)||(ss_ptr->getTextureFilename() == NULL) ) + { + index1 = *indices_ptr->get(i); + index2 = *indices_ptr->get(i+1); + index3 = *indices_ptr->get(i+2); + + /* Check for index overflow since PLIB stores it as a short */ + + if ( (index1 < 0)||(index2 < 0)||(index3 < 0) ) + { + ulSetError(UL_WARNING, "ssgSaveVRML1: Save error: index overflow, " + "value won't fit in 16bits."); + } + else + { + fprintf(fd, " %d, %d, %d, -1,\n", index1, index2, + index3); + } + } + } + fprintf(fd, " ]\n }\n"); //close coordIndex array and + //IndexedFaceSet + } + + if (textured_faces_found) + { + /* Save all texture coordinates (per-vertex) for all the textures in + * the model. It doesn't matter if there is one texture or more than + * one since we will specify which texture to use with the coordinates + * before saving the portion of the indexed face set which uses that + * texture. */ + + fprintf(fd, " TextureCoordinate2 {\n point [\n"); + for (i = 0; i < texcoord_ptr->getNum(); i++) + { + +/* In VrmlView Pro 3.0 (Linux) textured models appear correct Left-Right + * but the texture is reversed Top-Bottom. Enabling the INVERSE_REPEAT + * macro fixes the problem for VrmlView. I don't want to enable this until + * I figure out where the problem really is!? */ + +//#define INVERSE_REPEAT(a) (a > 0.0 ? 1.0 - a:a + 1.0) +#define INVERSE_REPEAT(a) a + + fprintf(fd, " %f %f,\n", texcoord_ptr->get(i)[0], + INVERSE_REPEAT(texcoord_ptr->get(i)[1])); + } + fprintf(fd, " ]\n }\n"); + + /* Now save separate Texture2 and IndexedFaceSet node pairs for each + * texture used in the model. Each of the IndexedFaceSet(s) will + * reference back to the initial vertices, materials, and texture + * coordinates (due to the lack of Seperator nodes in between). + * Find the first textured face starting at the i'th face. In this + * manner we will find the next texture used in the model and save + * all faces that are textured with it. */ + + for (i = 0; i < indices_ptr->getNum(); i+=3) + { + ss_ptr = ssa.get(*(materials_ptr->get(i/3))); + if ( (ss_ptr != NULL)&&(ss_ptr->getTextureFilename() != NULL) ) + { + /* We've found the next textured face. Since we save all + * faces using a texture when we find the first face using + * that texture we must check if the faces for this texture + * have already been saved. If we can find a face using + * this texture earlier in the list of faces then we know + * that it has already been saved. */ + + textureFacesAlreadySaved = false; + for (j = 0; j < i; j+=3) + { + ss_ptr2 = ssa.get(*(materials_ptr->get(j/3))); + if ( (ss_ptr2 != NULL)&& + (ss_ptr2->getTextureFilename() != NULL)&& + (!strcmp(ss_ptr->getTextureFilename(), + ss_ptr2->getTextureFilename())) ) + { + textureFacesAlreadySaved = true; + break; + } + } + + if (!textureFacesAlreadySaved) + { + fprintf(fd, " Texture2 {\n"); + fprintf(fd, " filename %s\n", ss_ptr->getTextureFilename()); +//TODO: support CLAMP mode as well. + fprintf(fd, " wrapS REPEAT\n"); + fprintf(fd, " wrapT REPEAT\n"); + fprintf(fd, " }\n"); + + /* Save all the materials needed by this following indexed face + * set. This will save all materials that have the same texture + * filename specified below. */ + + SaveVRML1MaterialNode(fd, materials_ptr, &ssa, + ss_ptr->getTextureFilename(), + true, false, false, false); + + fprintf(fd, " IndexedFaceSet {\n coordIndex [\n"); + for (j = i; j < indices_ptr->getNum(); j+=3) + { + /* Save each face which is textured by the Texture2 node defined + * above. */ + + ss_ptr2 = ssa.get(*(materials_ptr->get(j/3))); + if ( (ss_ptr2 != NULL)&& + (ss_ptr2->getTextureFilename() != NULL)&& + (!strcmp(ss_ptr->getTextureFilename(), + ss_ptr2->getTextureFilename())) ) + { + index1 = *indices_ptr->get(j); + index2 = *indices_ptr->get(j+1); + index3 = *indices_ptr->get(j+2); + + /* Check for index overflow since PLIB stores it as a + * short */ + + if ( (index1 < 0)||(index2 < 0)||(index3 < 0) ) + { + ulSetError(UL_WARNING, "ssgSaveVRML1: Save error: index " + "overflow, value won't fit in 16bits."); + } + else + { + fprintf(fd, " %d, %d, %d, -1,\n", + index1, index2, index3); + } + } + } + fprintf(fd, " ]\n }\n"); //close coordIndex array and + //IndexedFaceSet + } + } + } + } + + fprintf(fd, "}\n"); //close Seperator + fclose( fd ) ; + + delete vertices_ptr; + delete indices_ptr; + delete materials_ptr; + delete texcoord_ptr; + return TRUE; +} + + diff --git a/src/ssg/ssgSaveX.cxx b/src/ssg/ssgSaveX.cxx new file mode 100644 index 0000000..e712d5d --- /dev/null +++ b/src/ssg/ssgSaveX.cxx @@ -0,0 +1,39 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgSaveX.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + +// +// .X loader for SSG/PLIB +// .X is the 3D file format for Micro$ofts directX retained mode. +// Written by Wolfram Kuss (Wolfram.Kuss@t-online.de) in Oct/Nov of 2000 +// + +#include "ssgLocal.h" + + + +int ssgSaveX ( const char *filename, ssgEntity *ent ) +{ + ulSetError ( UL_WARNING, "ssgSaveX: Not implemented yet" ) ; + + return FALSE; +} diff --git a/src/ssg/ssgSelector.cxx b/src/ssg/ssgSelector.cxx new file mode 100644 index 0000000..bf1f308 --- /dev/null +++ b/src/ssg/ssgSelector.cxx @@ -0,0 +1,172 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgSelector.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "ssgLocal.h" + +void ssgSelector::copy_from ( ssgSelector *src, int clone_flags ) +{ + ssgBranch::copy_from ( src, clone_flags ) ; + + max_kids = src -> max_kids ; + selection = new unsigned char [ max_kids ] ; + memcpy ( selection, src -> selection, max_kids ) ; +} + + +ssgBase *ssgSelector::clone ( int clone_flags ) +{ + ssgSelector *b = new ssgSelector ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgSelector::ssgSelector ( int _max_kids ) +{ + type = ssgTypeSelector () ; + + max_kids = _max_kids ; + selection = new unsigned char [ max_kids ] ; + memset ( selection, 1, max_kids ) ; +} + +ssgSelector::~ssgSelector (void) +{ + delete [] selection ; +} + +void ssgSelector::cull ( sgFrustum *f, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_CULL ) ) + return ; + + int cull_result = cull_test ( f, m, test_needed ) ; + + if ( cull_result == SSG_OUTSIDE ) + return ; + + int s = 0 ; + + for ( ssgEntity *e = getKid ( 0 ) ; e != NULL ; e = getNextKid(), s++ ) + if ( selection [s] ) + e -> cull ( f, m, cull_result != SSG_INSIDE ) ; + + postTravTests ( SSGTRAV_CULL ) ; +} + +void ssgSelector::hot ( sgVec3 sp, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_HOT ) ) + return ; + + int hot_result = hot_test ( sp, m, test_needed ) ; + + if ( hot_result == SSG_OUTSIDE ) + return ; + + int s = 0 ; + + _ssgPushPath ( this ) ; + + for ( ssgEntity *e = getKid ( 0 ) ; e != NULL ; e = getNextKid(), s++ ) + if ( selection [s] ) + e -> hot ( sp, m, hot_result != SSG_INSIDE ) ; + + _ssgPopPath () ; + + postTravTests ( SSGTRAV_HOT ) ; +} + + +void ssgSelector::los ( sgVec3 sp, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_LOS ) ) + return ; + + int los_result = los_test ( sp, m, test_needed ) ; + + if ( los_result == SSG_OUTSIDE ) + return ; + + int s = 0 ; + + _ssgPushPath ( this ) ; + + for ( ssgEntity *e = getKid ( 0 ) ; e != NULL ; e = getNextKid(), s++ ) + if ( selection [s] ) + e -> los ( sp, m, los_result != SSG_INSIDE ) ; + + _ssgPopPath () ; + + postTravTests ( SSGTRAV_LOS ) ; +} + + +void ssgSelector::isect ( sgSphere *sp, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_ISECT ) ) + return ; + + int isect_result = isect_test ( sp, m, test_needed ) ; + + if ( isect_result == SSG_OUTSIDE ) + return ; + + int s = 0 ; + + _ssgPushPath ( this ) ; + + for ( ssgEntity *e = getKid ( 0 ) ; e != NULL ; e = getNextKid(), s++ ) + if ( selection [s] ) + e -> isect ( sp, m, isect_result != SSG_INSIDE ) ; + + _ssgPopPath () ; + + postTravTests ( SSGTRAV_ISECT ) ; +} + + +int ssgSelector::load ( FILE *fd ) +{ + _ssgReadInt ( fd, & max_kids ) ; + delete [] selection ; + selection = new unsigned char [ max_kids ] ; + for ( int i=0; i getSizeOf () ; + total = src -> getNum () ; + limit = total ; + list = new char [ limit * size_of ] ; + own_mem = true ; + memcpy ( list, src->raw_get ( 0 ), limit * size_of ) ; +} + +ssgBase *ssgSimpleList::clone ( int clone_flags ) +{ + ssgSimpleList *b = new ssgSimpleList () ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + +ssgBase *ssgNormalArray::clone ( int clone_flags ) +{ + ssgNormalArray *b = new ssgNormalArray () ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + +ssgBase *ssgVertexArray::clone ( int clone_flags ) +{ + ssgVertexArray *b = new ssgVertexArray () ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + +ssgBase *ssgTexCoordArray::clone ( int clone_flags ) +{ + ssgTexCoordArray *b = new ssgTexCoordArray () ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + +ssgBase *ssgColourArray::clone ( int clone_flags ) +{ + ssgColourArray *b = new ssgColourArray () ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + +ssgBase *ssgIndexArray::clone ( int clone_flags ) +{ + ssgIndexArray *b = new ssgIndexArray () ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + + + +void ssgVertexArray::print ( FILE *fd, char *indent, int how_much ) +{ + ssgSimpleList::print ( fd, indent, how_much ) ; + + if ( how_much < 4 ) + return; + + for ( unsigned int i = 0 ; i < total ; i++ ) + fprintf ( fd, "%s V%d) { %f, %f, %f }\n", indent, i, + get(i)[0], get(i)[1], get(i)[2] ) ; +} + + + + +void ssgNormalArray::print ( FILE *fd, char *indent, int how_much ) +{ + ssgSimpleList::print ( fd, indent, how_much ) ; + + if ( how_much < 4 ) + return; + + for ( unsigned int i = 0 ; i < total ; i++ ) + fprintf ( fd, "%s N%d) { %f, %f, %f }\n", indent, i, + get(i)[0], get(i)[1], get(i)[2] ) ; +} + + + +void ssgIndexArray::print ( FILE *fd, char *indent, int how_much ) +{ + ssgSimpleList::print ( fd, indent, how_much ) ; + + if ( how_much < 4 ) + return; + + for ( unsigned int i = 0 ; i < total ; i++ ) + fprintf ( fd, "%s I%d) { %d }\n", indent, i, + (int) (*get(i)) ) ; +} + +void ssgTexCoordArray::print ( FILE *fd, char *indent, int how_much ) +{ + ssgSimpleList::print ( fd, indent, how_much ) ; + + if ( how_much < 4 ) + return; + + for ( unsigned int i = 0 ; i < total ; i++ ) + fprintf ( fd, "%s T%d) { S=%f, T=%f }\n", indent, i, + get(i)[0], get(i)[1] ) ; +} + + + + +void ssgColourArray::print ( FILE *fd, char *indent, int how_much ) +{ + ssgSimpleList::print ( fd, indent, how_much ) ; + + if ( how_much < 4 ) + return; + + for ( unsigned int i = 0 ; i < total ; i++ ) + fprintf ( fd, "%s C%d) { R=%f, G=%f, B=%f, A=%f }\n", indent, i, + get(i)[0], get(i)[1], get(i)[2], get(i)[3] ) ; +} + + + +void ssgSimpleList::print ( FILE *fd, char *indent, int how_much ) +{ + ssgBase::print ( fd, indent, how_much ) ; + + fprintf ( fd, "%s Total # items = %d\n", indent, total ) ; + + if ( how_much < 3 ) + return; + + fprintf ( fd, "%s Size of items = %d bytes\n", indent, size_of ) ; +} + + + +int ssgSimpleList::load ( FILE *fd ) +{ + delete [] list ; + _ssgReadUInt ( fd, &size_of ) ; + _ssgReadUInt ( fd, &total ) ; + limit = total ; + list = new char [ limit * size_of ] ; + assert(list!=NULL); + // wk: The old code: + //_ssgReadFloat ( fd, limit * size_of / sizeof(float), (float *)list ) ; + // doesn't work since some ssgSimpleLists consist of shorts, so + // limit * size_of may not be divisible by sizeof(float). + // The new code works, but I am not 100% sure what we want in + // the event that there are machines with another sizeof(float). + _ssgReadBytes ( fd, limit * size_of , list) ; + + return ! _ssgReadError () ; +} + + + +int ssgSimpleList::save ( FILE *fd ) +{ + _ssgWriteUInt ( fd, size_of ) ; + _ssgWriteUInt ( fd, total ) ; + // see comment in ssgSimpleList::load + // _ssgWriteFloat( fd, total * size_of / sizeof(float), (float *)list ) ; + _ssgWriteBytes ( fd, total * size_of, list); + return ! _ssgWriteError () ; +} + + diff --git a/src/ssg/ssgSimpleState.cxx b/src/ssg/ssgSimpleState.cxx new file mode 100644 index 0000000..514cf46 --- /dev/null +++ b/src/ssg/ssgSimpleState.cxx @@ -0,0 +1,649 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgSimpleState.cxx 2167 2012-08-14 17:24:50Z wolfram_kuss $ +*/ + + +#include "ssgLocal.h" + +void ssgSimpleState::copy_from ( ssgSimpleState *src, int clone_flags ) +{ + ssgState::copy_from ( src, clone_flags ) ; + + ssgTexture *tex = src -> getTexture () ; + + ssgDeRefDelete(texture); + + if ( tex != NULL && ( clone_flags & SSG_CLONE_TEXTURE ) ) + texture = (ssgTexture *)( tex -> clone ( clone_flags ) ) ; + else + texture = tex ; + + if (texture != NULL) + texture->ref(); + + dont_care = src -> dont_care ; + enables = src -> enables ; + + colour_material_mode = src -> colour_material_mode ; + + sgCopyVec4 ( specular_colour, src -> specular_colour ) ; + sgCopyVec4 ( emission_colour, src -> emission_colour ) ; + sgCopyVec4 ( ambient_colour, src -> ambient_colour ) ; + sgCopyVec4 ( diffuse_colour, src -> diffuse_colour ) ; + + shade_model = src -> shade_model ; + shininess = src -> shininess ; + alpha_clamp = src -> alpha_clamp ; +} + +ssgBase *ssgSimpleState::clone ( int clone_flags ) +{ + ssgSimpleState *b = new ssgSimpleState ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +void _ssgForceLineState () +{ + _ssgCurrentContext->getState()->enables &= ~((1<getState()->enables & 0x3F ; + (*(__ssgDisableTable[turn_off]))() ; + _ssgCurrentContext->getState()->enables &= ~turn_off ; + + if ( ~ dont_care & ( (1<getState()->colour_material_mode != colour_material_mode ) + { + glColorMaterial ( GL_FRONT_AND_BACK, (GLenum) colour_material_mode ) ; + _ssgCurrentContext->getState()->colour_material_mode = colour_material_mode ; + indeterminate |= _ssgCurrentContext->getState()->enables & (1<getState()->specular_colour, -1.0f, -1.0f, -1.0f ) ; + sgSetVec3 ( _ssgCurrentContext->getState()->emission_colour, -1.0f, -1.0f, -1.0f ) ; + sgSetVec3 ( _ssgCurrentContext->getState()->ambient_colour, -1.0f, -1.0f, -1.0f ) ; + sgSetVec4 ( _ssgCurrentContext->getState()->diffuse_colour, -1.0f, -1.0f, -1.0f, -1.0f ) ; + } + } + + if ( ~ dont_care & ( (1<getState()->shininess != shininess ) + { + glMaterialf ( GL_FRONT_AND_BACK, GL_SHININESS, shininess ) ; + _ssgCurrentContext->getState()->shininess = shininess ; + } + + if ( ( ~ dont_care & (1<getState()->specular_colour, specular_colour ) ) + { + glMaterialfv ( GL_FRONT_AND_BACK, GL_SPECULAR, specular_colour ) ; + sgCopyVec3 ( _ssgCurrentContext->getState()->specular_colour, specular_colour ) ; + } + + if ( ( ~ dont_care & (1<getState()->emission_colour, emission_colour ) ) + { + glMaterialfv ( GL_FRONT_AND_BACK, GL_EMISSION, emission_colour ) ; + sgCopyVec3 ( _ssgCurrentContext->getState()->emission_colour, emission_colour ) ; + } + + if ( ( ~ dont_care & (1<getState()->ambient_colour, ambient_colour ) ) + { + glMaterialfv ( GL_FRONT_AND_BACK, GL_AMBIENT, ambient_colour ) ; + sgCopyVec3 ( _ssgCurrentContext->getState()->ambient_colour, ambient_colour ) ; + } + + if ( ( ~ dont_care & (1<getState()->diffuse_colour, diffuse_colour ) ) + { + glMaterialfv ( GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse_colour ) ; + sgCopyVec4 ( _ssgCurrentContext->getState()->diffuse_colour, diffuse_colour ) ; + } + } + + if ( ( ~ dont_care & (1<getState()->getTexture() != getTexture() ) + { + stats_bind_textures++ ; +#ifdef GL_VERSION_1_1 + glBindTexture ( GL_TEXTURE_2D, getTextureHandle() ) ; +#else + /* For ancient SGI machines */ + glBindTextureEXT ( GL_TEXTURE_2D, getTextureHandle() ) ; +#endif + _ssgCurrentContext->getState()->setTexture ( getTexture () ) ; + } + + if ( ( ~ dont_care & (1<getState()->shade_model != shade_model ) + { + glShadeModel ( shade_model ) ; + _ssgCurrentContext->getState()->shade_model = shade_model ; + } + + if ( ( ~ dont_care & (1<getState()->alpha_clamp != alpha_clamp ) + { + glAlphaFunc ( GL_GREATER, alpha_clamp ) ; + _ssgCurrentContext->getState()->alpha_clamp = alpha_clamp ; + } + + int turn_on = ~dont_care & enables & ~_ssgCurrentContext->getState()->enables & 0x3F ; + (*(__ssgEnableTable [turn_on ]))() ; + _ssgCurrentContext->getState()->enables |= turn_on ; + + preDraw () ; +} + +void ssgSimpleState::force (void) +{ + preApply () ; + int turn_off = ~dont_care & ~enables & 0x3F ; + (*(__ssgDisableTable[turn_off]))() ; + _ssgCurrentContext->getState()->enables &= ~turn_off ; + + /* invalidate the material colours, since we do not know what the current mode is */ + sgSetVec3 ( _ssgCurrentContext->getState()->specular_colour, -1.0f, -1.0f, -1.0f ) ; + sgSetVec3 ( _ssgCurrentContext->getState()->emission_colour, -1.0f, -1.0f, -1.0f ) ; + sgSetVec3 ( _ssgCurrentContext->getState()->ambient_colour, -1.0f, -1.0f, -1.0f ) ; + sgSetVec4 ( _ssgCurrentContext->getState()->diffuse_colour, -1.0f, -1.0f, -1.0f, -1.0f ) ; + + if ( ~ dont_care & ( (1<getState()->colour_material_mode = colour_material_mode ; + } + + if ( ~ dont_care & (1<getState()->shininess = shininess ; + } + + if ( ~ dont_care & (1<getState()->diffuse_colour, diffuse_colour ) ; + } + + if ( ~ dont_care & (1<getState()->emission_colour, emission_colour ) ; + } + + if ( ~ dont_care & (1<getState()->ambient_colour, ambient_colour ) ; + } + + if ( ~ dont_care & (1<getState()->specular_colour, specular_colour ) ; + } + } + + if ( ~ dont_care & (1<getState()->setTexture ( getTexture () ) ; + } + + if ( ~ dont_care & (1<getState()->shade_model = shade_model ; + } + + if ( ~ dont_care & (1<getState()->alpha_clamp = alpha_clamp ; + } + + int turn_on = ~dont_care & enables & 0x3F ; + (*(__ssgEnableTable [turn_on ]))() ; + _ssgCurrentContext->getState()->enables |= turn_on ; + preDraw () ; +} + + + +int ssgSimpleState::isEnabled ( GLenum mode ) +{ + switch ( mode ) + { + case GL_TEXTURE_2D : + return enables & (1< ref () ; + + return ssgState::load(fd) ; +} + + +int ssgSimpleState::save ( FILE *fd ) +{ + _ssgWriteInt ( fd, dont_care ) ; + _ssgWriteInt ( fd, enables ) ; + _ssgWriteInt ( fd, colour_material_mode ) ; + _ssgWriteVec4 ( fd, specular_colour ) ; + _ssgWriteVec4 ( fd, emission_colour ) ; + _ssgWriteVec4 ( fd, ambient_colour ) ; + _ssgWriteVec4 ( fd, diffuse_colour ) ; + _ssgWriteInt ( fd, (int) shade_model ) ; + _ssgWriteFloat ( fd, shininess ) ; + _ssgWriteFloat ( fd, alpha_clamp ) ; + + if ( ! _ssgSaveObject ( fd, texture ) ) + return FALSE ; + + return ssgState::save(fd) ; +} + +/* +wk: not implemented yet +Is ssgSimpleState the right place to do this? +use gkGetTexParamiv or so. + +int ssgSimpleState::getWrapU() +{ + int wrapu = TRUE, wrapv = TRUE ; + + if ( filename == NULL ) + return TRUE; + if ( filename[0] == 0 ) + return TRUE; + + GLuint texture_handle = getTextureHandle () ; +} +*/ + + +static void printStateString ( FILE *fd, unsigned int bits ) +{ + if ( bits & (1<" : getTextureFilename() ) ; + fprintf ( fd, "%s Shade Model = %d\n", indent, shade_model ) ; + fprintf ( fd, "%s Shininess = %f\n", indent, shininess ) ; + fprintf ( fd, "%s AlphaClamp = %f\n", indent, alpha_clamp ) ; + fprintf ( fd, "%s ColourMatMode= %s\n", indent, + (colour_material_mode == GL_AMBIENT) ? "GL_AMBIENT" : + (colour_material_mode == GL_DIFFUSE) ? "GL_DIFFUSE" : + (colour_material_mode == GL_AMBIENT_AND_DIFFUSE) ? + "GL_AMBIENT_AND_DIFFUSE" : + (colour_material_mode == GL_SPECULAR) ? "GL_SPECULAR" : + (colour_material_mode == GL_EMISSION) ? "GL_EMISSION" : "?????" ) ; + + fprintf ( fd, "%s Ambient : (%f,%f,%f,%f)\n", indent, + ambient_colour[0], ambient_colour[1], + ambient_colour[2], ambient_colour[3] ) ; + fprintf ( fd, "%s Diffuse : (%f,%f,%f,%f)\n", indent, + diffuse_colour[0], diffuse_colour[1], + diffuse_colour[2], diffuse_colour[3] ) ; + fprintf ( fd, "%s Specular : (%f,%f,%f,%f)\n", indent, + specular_colour[0], specular_colour[1], + specular_colour[2], specular_colour[3] ) ; + fprintf ( fd, "%s Emission : (%f,%f,%f,%f)\n", indent, + emission_colour[0], emission_colour[1], + emission_colour[2], emission_colour[3] ) ; +} + +// *********************************************************************** +// ******************** class ssgSimpleStateArray ************************ +// *********************************************************************** + + +int ssgSimpleStateArray::findIndex ( ssgSimpleState* st ) +{ + for ( int i = 0; i < getNum (); i++ ) + if ( get (i) == st ) + return i ; + return -1 ; +} + + +void ssgSimpleStateArray::collect ( ssgEntity *e ) +{ + removeAll () ; + collect_recursive (e); +} + + +void ssgSimpleStateArray::collect_recursive ( ssgEntity *e ) +{ + if ( e -> isAKindOf ( ssgTypeBranch() ) ) + { + ssgBranch *br = (ssgBranch *) e ; + + for ( int i = 0 ; i < br -> getNumKids () ; i++ ) + collect_recursive ( br -> getKid ( i ) ) ; + } + else + if ( e -> isAKindOf ( ssgTypeVtxTable() ) ) + { + ssgVtxTable* vt = (ssgVtxTable *) e ; + ssgState* st = vt -> getState () ; + if ( st && st -> isAKindOf ( ssgTypeSimpleState() ) ) + { + ssgSimpleState* ss = (ssgSimpleState*) vt -> getState () ; + if ( findIndex ( ss ) == -1 ) + add ( ss ) ; + } + } +} + + +void ssgSimpleStateArray::add ( ssgSimpleState* ss ) +{ + if ( ss ) + { + ss -> ref () ; + raw_add ( (char *) &ss ) ; + } +} + + +void ssgSimpleStateArray::removeAll () +{ + for ( int i = 0; i < getNum (); i++ ) + ssgDeRefDelete ( get (i) ) ; + ssgSimpleList::removeAll () ; +} + + +ssgSimpleState* ssgSimpleStateArray::findMatch ( ssgSimpleState* st, bool testNamesAsWell ) +{ + if ( st == NULL ) + return NULL ; + + for ( int i = 0; i < getNum (); i++ ) + { + ssgSimpleState *st2 = get (i) ; + + if ( st == st2 ) + return NULL ; //same pointer -- don't change state + + if (testNamesAsWell && ( 0 != strcmp(st->getName(), st2->getName())) ) + continue ; + + + if ( st->isEnabled ( GL_TEXTURE_2D ) != st2->isEnabled ( GL_TEXTURE_2D ) ) + continue ; + + if ( st->isEnabled ( GL_TEXTURE_2D ) && + st -> getTextureHandle () != st2 -> getTextureHandle () ) + continue ; + + if ( st->isEnabled ( GL_TEXTURE_2D ) && + (st -> getTextureHandle () == 0) && + (st2-> getTextureHandle () == 0) && + 0 != strcmp( st->getTextureFilename(), st2->getTextureFilename())) + continue ; + + if ( st->getCareAbout (SSG_GL_SPECULAR) != st2->getCareAbout (SSG_GL_SPECULAR) || + st->getCareAbout (SSG_GL_EMISSION) != st2->getCareAbout (SSG_GL_EMISSION) || + st->getCareAbout (SSG_GL_AMBIENT) != st2->getCareAbout (SSG_GL_AMBIENT) || + st->getCareAbout (SSG_GL_DIFFUSE) != st2->getCareAbout (SSG_GL_DIFFUSE) ) + continue ; + + if ( ! st->getCareAbout (SSG_GL_SPECULAR) && + ! sgEqualVec4 ( st->getMaterial (GL_SPECULAR), st2->getMaterial (GL_SPECULAR) ) ) + continue ; + + if ( ! st->getCareAbout (SSG_GL_EMISSION) && + ! sgEqualVec4 ( st->getMaterial (GL_EMISSION), st2->getMaterial (GL_EMISSION) ) ) + continue ; + + if ( ! st->getCareAbout (SSG_GL_AMBIENT) && + ! sgEqualVec4 ( st->getMaterial (GL_AMBIENT), st2->getMaterial (GL_AMBIENT) ) ) + continue ; + + if ( ! st->getCareAbout (SSG_GL_DIFFUSE) && + ! sgEqualVec4 ( st->getMaterial (GL_DIFFUSE), st2->getMaterial (GL_DIFFUSE) ) ) + continue ; + + if ( st -> isTranslucent () != st2 -> isTranslucent () || + st -> getShininess () != st2 -> getShininess () ) + continue ; + + return st2 ; + } + return NULL ; +} diff --git a/src/ssg/ssgState.cxx b/src/ssg/ssgState.cxx new file mode 100644 index 0000000..b4ff931 --- /dev/null +++ b/src/ssg/ssgState.cxx @@ -0,0 +1,136 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgState.cxx 1810 2003-11-20 14:01:05Z stromberg $ +*/ + + +#include "ssgLocal.h" + +static ssgStateCallback _ssgPendingPostDrawCB = NULL ; +static ssgState *_ssgPreviousState = NULL ; + +void ssgState::preApply () +{ + if ( _ssgPendingPostDrawCB ) + (*_ssgPendingPostDrawCB)(_ssgPreviousState) ; + + if ( preApplyCB ) (*preApplyCB)(this) ; +} + + +void ssgState::preDraw () +{ + if ( preDrawCB ) + { + (*preDrawCB)(this) ; + _ssgPendingPostDrawCB = postDrawCB ; + _ssgPreviousState = this ; + } +} + +void _ssgStartOfFrameInit () +{ + _ssgPendingPostDrawCB = NULL ; + _ssgPreviousState = NULL ; +} + +void _ssgEndOfFrameCleanup () +{ + if ( _ssgPendingPostDrawCB ) (*_ssgPendingPostDrawCB)(_ssgPreviousState) ; + + _ssgPendingPostDrawCB = NULL ; + _ssgPreviousState = NULL ; +} + +void ssgState::copy_from ( ssgState *src, int clone_flags ) +{ + ssgBase::copy_from ( src, clone_flags ) ; + setExternalPropertyIndex ( src -> getExternalPropertyIndex () ) ; + + if ( src -> isTranslucent () ) + setTranslucent () ; + else + setOpaque () ; + + setStateCallback( SSG_CALLBACK_PREDRAW, src->getStateCallback( SSG_CALLBACK_PREDRAW ) ); + setStateCallback( SSG_CALLBACK_POSTDRAW, src->getStateCallback( SSG_CALLBACK_POSTDRAW ) ); + setStateCallback( SSG_CALLBACK_PREAPPLY, src->getStateCallback( SSG_CALLBACK_PREAPPLY ) ); +} + + + +ssgState::ssgState (void) +{ + type = ssgTypeState () ; + + preApplyCB = NULL ; + preDrawCB = NULL ; + postDrawCB = NULL ; + + setOpaque () ; + setExternalPropertyIndex ( 0 ) ; +} + +ssgState::~ssgState (void) +{ + if ( _ssgPreviousState == this ) + { + _ssgPendingPostDrawCB = NULL ; + _ssgPreviousState = NULL ; + } +} + + +void ssgState::print ( FILE *fd, char *indent, int how_much ) +{ + ssgBase::print ( fd, indent, how_much ) ; + + if ( how_much < 2 ) + return; + + fprintf ( fd, "%s Translucent = %s\n", indent, translucent?"True":"False"); + fprintf ( fd, "%s ExternalProp = %d\n", indent, external_property_index ) ; +} + + +int ssgState::load ( FILE *fd ) +{ + _ssgReadInt ( fd, & translucent ) ; + _ssgReadInt ( fd, & external_property_index ) ; + + preApplyCB = NULL ; + preDrawCB = NULL ; + postDrawCB = NULL ; + + return ssgBase::load ( fd ) ; +} + + +int ssgState::save ( FILE *fd ) +{ + _ssgWriteInt ( fd, translucent ) ; + _ssgWriteInt ( fd, external_property_index ) ; + return ssgBase::save ( fd ) ; +} + + + + diff --git a/src/ssg/ssgStateSelector.cxx b/src/ssg/ssgStateSelector.cxx new file mode 100644 index 0000000..4d79990 --- /dev/null +++ b/src/ssg/ssgStateSelector.cxx @@ -0,0 +1,426 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgStateSelector.cxx 1950 2004-09-13 11:28:34Z wolfram_kuss $ +*/ + + +#include "ssgLocal.h" + +void ssgStateSelector::copy_from ( ssgStateSelector *src, int clone_flags ) +{ + ssgSimpleState::copy_from ( src, clone_flags ) ; + + nstates = src -> getNumSteps () ; + selection = src -> getSelectStep () ; + statelist = new ssgSimpleState * [ nstates ] ; + + for ( int i = 0 ; i < nstates ; i++ ) + { + ssgSimpleState *s = src -> getStep ( i ) ; + + if ( s != NULL && (clone_flags & SSG_CLONE_STATE_RECURSIVE) ) + statelist [ i ] = (ssgSimpleState *)( s -> clone ( clone_flags )) ; + else + statelist [ i ] = s ; + + //~~ T.G. needs ref count incremented + if (statelist [ i ] != NULL ) + statelist [ i ] -> ref(); + + } +} + + +ssgBase *ssgStateSelector::clone ( int clone_flags ) +{ + ssgStateSelector *b = new ssgStateSelector ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgStateSelector::ssgStateSelector () +{ + type = ssgTypeStateSelector () ; + nstates = 0 ; + selection = -1 ; + statelist = NULL ; +} + +ssgStateSelector::ssgStateSelector ( int ns ) +{ + type = ssgTypeStateSelector () ; + nstates = ns ; + selection = -1 ; + statelist = new ssgSimpleState * [ nstates ] ; + + for ( int i = 0 ; i < nstates ; i++ ) + statelist [ i ] = NULL ; +} + +ssgStateSelector::~ssgStateSelector (void) +{ + //~~ T.G. deref states before deleting list + for ( int i = 0 ; i < nstates ; i++ ) + ssgDeRefDelete( statelist [ i ] ); + delete [] statelist ; +} + +void ssgStateSelector::selectStep ( unsigned int s ) +{ + selection = s ; +} + +unsigned int ssgStateSelector::getSelectStep (void) +{ + return selection ; +} + +ssgSimpleState *ssgStateSelector::getCurrentStep (void) +{ + return ( selection < 0 || + selection >= nstates || + statelist [ selection ] == NULL ) ? this : statelist[selection] ; +} + +ssgSimpleState *ssgStateSelector::getStep ( int i ) +{ + return ( i < 0 || + i >= nstates || + statelist [ i ] == NULL ) ? this : statelist[i] ; +} + + + + +void ssgStateSelector::setStep (int i, ssgSimpleState *step) +{ + if ( i < 0 || i >= nstates ) return ; + + //~~ T.G. removed null test -- not necessary + ssgDeRefDelete ( statelist[i] ) ; + + statelist [ i ] = step ; + + if ( step != NULL ) + step -> ref () ; +} + + +int ssgStateSelector::isTranslucent (void) +{ + return getCurrentStep()->isTranslucent() ; +} + + +void ssgStateSelector::setTranslucent (void) +{ + getCurrentStep()->setTranslucent() ; +} + + + +void ssgStateSelector::setOpaque (void) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + ssgSimpleState::setOpaque() ; + else + s -> setOpaque() ; +} + + +void ssgStateSelector::force (void) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + ssgSimpleState::force() ; + else + s -> force() ; +} + +void ssgStateSelector::apply (void) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + ssgSimpleState::apply() ; + else + s -> apply() ; +} + + +void ssgStateSelector:: care_about ( int mode ) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + ssgSimpleState::care_about (mode) ; + else + s -> care_about (mode); +} + + +void ssgStateSelector::dont_care_about ( int mode ) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + ssgSimpleState::dont_care_about(mode) ; + else + s -> dont_care_about(mode); +} + + +int ssgStateSelector::isEnabled ( GLenum mode ) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + return ssgSimpleState::isEnabled(mode) ; + else + return s -> isEnabled(mode) ; +} + +void ssgStateSelector::disable ( GLenum mode ) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + ssgSimpleState::disable(mode) ; + else + s -> disable(mode) ; +} + +void ssgStateSelector::enable ( GLenum mode ) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + ssgSimpleState::enable(mode) ; + else + s -> enable(mode) ; +} + + +void ssgStateSelector::setTexture ( char *fname, int _wrapu, int _wrapv, + int _mipmap ) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + ssgSimpleState::setTexture ( fname, _wrapu, _wrapv, _mipmap ) ; + else + s -> setTexture ( fname, _wrapu, _wrapv, _mipmap ) ; +} + +char *ssgStateSelector::getTextureFilename (void) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + return ssgSimpleState::getTextureFilename() ; + else + return s -> getTextureFilename(); +} + +GLuint ssgStateSelector::getTextureHandle (void) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + return ssgSimpleState::getTextureHandle() ; + else + return s -> getTextureHandle() ; +} + +void ssgStateSelector::setTexture ( ssgTexture *tex ) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + ssgSimpleState::setTexture(tex) ; + else + s -> setTexture(tex) ; +} + +void ssgStateSelector::setTextureFilename ( char *fname ) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + ssgTexture* texture ; + if ( s == this ) + texture = ssgSimpleState::getTexture () ; + else + texture = s -> getTexture () ; + + if ( texture != NULL ) + texture -> setFilename ( fname ) ; +} + +void ssgStateSelector::setTexture ( GLuint tex ) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + ssgTexture* texture ; + if ( s == this ) + texture = ssgSimpleState::getTexture () ; + else + texture = s -> getTexture () ; + + if ( texture != NULL ) + texture -> setHandle (tex) ; +} + +void ssgStateSelector::setColourMaterial(GLenum which) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + ssgSimpleState::setColourMaterial(which) ; + else + s -> setColourMaterial(which) ; +} + +void ssgStateSelector::setMaterial ( GLenum which, float r, float g, + float b, float a ) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + ssgSimpleState::setMaterial(which,r,g,b,a) ; + else + s -> setMaterial(which,r,g,b,a) ; +} + + +void ssgStateSelector::setMaterial ( GLenum which, sgVec4 rgba ) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + ssgSimpleState::setMaterial(which,rgba) ; + else + s -> setMaterial(which,rgba) ; +} + +float *ssgStateSelector::getMaterial ( GLenum which ) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + return ssgSimpleState::getMaterial(which) ; + else + return s -> getMaterial(which) ; +} + +float ssgStateSelector::getShininess (void) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + return ssgSimpleState::getShininess() ; + else + return s -> getShininess() ; +} + +void ssgStateSelector::setShininess ( float sh ) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + ssgSimpleState::setShininess(sh) ; + else + s -> setShininess(sh) ; +} + +void ssgStateSelector::setShadeModel ( GLenum model ) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + ssgSimpleState::setShadeModel(model) ; + else + s -> setShadeModel(model) ; +} + +void ssgStateSelector::setAlphaClamp ( float clamp ) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + ssgSimpleState::setAlphaClamp(clamp) ; + else + s -> setAlphaClamp(clamp) ; +} + +void ssgStateSelector::print ( FILE *fd, char *indent, int how_much ) +{ + ssgStateSelector * s = (ssgStateSelector *) getCurrentStep() ; + + if ( s == this ) + ssgSimpleState::print(fd, indent, how_much) ; + else + s -> print(fd, indent, how_much) ; +} + + +int ssgStateSelector::load ( FILE *fd ) +{ + int i ; + + _ssgReadInt ( fd, & nstates ) ; + _ssgReadInt ( fd, & selection ) ; + + if (statelist != NULL) + { + for ( i = 0 ; i < nstates ; i++ ) + ssgDeRefDelete( statelist [ i ] ); + delete [] statelist ; + } + + statelist = new ssgSimpleState * [ nstates ] ; + for ( i = 0 ; i < nstates ; i++ ) + { + if ( ! _ssgLoadObject ( fd, (ssgBase **) &statelist[i], ssgTypeState () ) ) + return FALSE ; + } + + return ssgSimpleState::load(fd) ; +} + + +int ssgStateSelector::save ( FILE *fd ) +{ + + _ssgWriteInt ( fd, nstates ) ; + _ssgWriteInt ( fd, selection ) ; + for ( int i = 0 ; i < nstates ; i++ ) + { + if ( ! _ssgSaveObject ( fd, statelist[i] ) ) + return FALSE ; + } + + return ssgSimpleState::save(fd) ; +} + diff --git a/src/ssg/ssgStateTables.cxx b/src/ssg/ssgStateTables.cxx new file mode 100644 index 0000000..746f1fd --- /dev/null +++ b/src/ssg/ssgStateTables.cxx @@ -0,0 +1,221 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgStateTables.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "ssgLocal.h" + +/* + Well, it would be nice to say that these tables + were automatically generated - but they weren't. + + So, there is some particularly nasty Macro-processing + going on to save my poor aching fingers. +*/ + +#define E0 { if ( ! _ssgCurrentContext->textureOverridden ()) glEnable ( GL_TEXTURE_2D ) ; } +#define E1 { if ( ! _ssgCurrentContext->cullfaceOverridden()) glEnable ( GL_CULL_FACE ) ; } +#define E2 glEnable ( GL_COLOR_MATERIAL ) ; +#define E3 glEnable ( GL_BLEND ) ; +#define E4 glEnable ( GL_ALPHA_TEST ) ; +#define E5 glEnable ( GL_LIGHTING ) ; + +#define D0 glDisable ( GL_TEXTURE_2D ) ; +#define D1 glDisable ( GL_CULL_FACE ) ; +#define D2 glDisable ( GL_COLOR_MATERIAL ) ; +#define D3 glDisable ( GL_BLEND ) ; +#define D4 glDisable ( GL_ALPHA_TEST ) ; +#define D5 glDisable ( GL_LIGHTING ) ; + +/* Do any combination of useful glEnable/glDisable commands */ + +static void enable_00 () { } +static void enable_01 () { E0 } +static void enable_02 () { E1 } +static void enable_03 () { E0 E1 } +static void enable_04 () { E2 } +static void enable_05 () { E0 E2 } +static void enable_06 () { E1 E2 } +static void enable_07 () { E0 E1 E2 } +static void enable_08 () { E3 } +static void enable_09 () { E0 E3 } +static void enable_10 () { E1 E3 } +static void enable_11 () { E0 E1 E3 } +static void enable_12 () { E2 E3 } +static void enable_13 () { E0 E2 E3 } +static void enable_14 () { E1 E2 E3 } +static void enable_15 () { E0 E1 E2 E3 } +static void enable_16 () { E4 } +static void enable_17 () { E0 E4 } +static void enable_18 () { E1 E4 } +static void enable_19 () { E0 E1 E4 } +static void enable_20 () { E2 E4 } +static void enable_21 () { E0 E2 E4 } +static void enable_22 () { E1 E2 E4 } +static void enable_23 () { E0 E1 E2 E4 } +static void enable_24 () { E3 E4 } +static void enable_25 () { E0 E3 E4 } +static void enable_26 () { E1 E3 E4 } +static void enable_27 () { E0 E1 E3 E4 } +static void enable_28 () { E2 E3 E4 } +static void enable_29 () { E0 E2 E3 E4 } +static void enable_30 () { E1 E2 E3 E4 } +static void enable_31 () { E0 E1 E2 E3 E4 } + +static void enable_32 () { E5 } +static void enable_33 () { E0 E5 } +static void enable_34 () { E1 E5 } +static void enable_35 () { E0 E1 E5 } +static void enable_36 () { E2 E5 } +static void enable_37 () { E0 E2 E5 } +static void enable_38 () { E1 E2 E5 } +static void enable_39 () { E0 E1 E2 E5 } +static void enable_40 () { E3 E5 } +static void enable_41 () { E0 E3 E5 } +static void enable_42 () { E1 E3 E5 } +static void enable_43 () { E0 E1 E3 E5 } +static void enable_44 () { E2 E3 E5 } +static void enable_45 () { E0 E2 E3 E5 } +static void enable_46 () { E1 E2 E3 E5 } +static void enable_47 () { E0 E1 E2 E3 E5 } +static void enable_48 () { E4 E5 } +static void enable_49 () { E0 E4 E5 } +static void enable_50 () { E1 E4 E5 } +static void enable_51 () { E0 E1 E4 E5 } +static void enable_52 () { E2 E4 E5 } +static void enable_53 () { E0 E2 E4 E5 } +static void enable_54 () { E1 E2 E4 E5 } +static void enable_55 () { E0 E1 E2 E4 E5 } +static void enable_56 () { E3 E4 E5 } +static void enable_57 () { E0 E3 E4 E5 } +static void enable_58 () { E1 E3 E4 E5 } +static void enable_59 () { E0 E1 E3 E4 E5 } +static void enable_60 () { E2 E3 E4 E5 } +static void enable_61 () { E0 E2 E3 E4 E5 } +static void enable_62 () { E1 E2 E3 E4 E5 } +static void enable_63 () { E0 E1 E2 E3 E4 E5 } + +static void disable_00 () { } +static void disable_01 () { D0 } +static void disable_02 () { D1 } +static void disable_03 () { D0 D1 } +static void disable_04 () { D2 } +static void disable_05 () { D0 D2 } +static void disable_06 () { D1 D2 } +static void disable_07 () { D0 D1 D2 } +static void disable_08 () { D3 } +static void disable_09 () { D0 D3 } +static void disable_10 () { D1 D3 } +static void disable_11 () { D0 D1 D3 } +static void disable_12 () { D2 D3 } +static void disable_13 () { D0 D2 D3 } +static void disable_14 () { D1 D2 D3 } +static void disable_15 () { D0 D1 D2 D3 } +static void disable_16 () { D4 } +static void disable_17 () { D0 D4 } +static void disable_18 () { D1 D4 } +static void disable_19 () { D0 D1 D4 } +static void disable_20 () { D2 D4 } +static void disable_21 () { D0 D2 D4 } +static void disable_22 () { D1 D2 D4 } +static void disable_23 () { D0 D1 D2 D4 } +static void disable_24 () { D3 D4 } +static void disable_25 () { D0 D3 D4 } +static void disable_26 () { D1 D3 D4 } +static void disable_27 () { D0 D1 D3 D4 } +static void disable_28 () { D2 D3 D4 } +static void disable_29 () { D0 D2 D3 D4 } +static void disable_30 () { D1 D2 D3 D4 } +static void disable_31 () { D0 D1 D2 D3 D4 } + +static void disable_32 () { D5 } +static void disable_33 () { D0 D5 } +static void disable_34 () { D1 D5 } +static void disable_35 () { D0 D1 D5 } +static void disable_36 () { D2 D5 } +static void disable_37 () { D0 D2 D5 } +static void disable_38 () { D1 D2 D5 } +static void disable_39 () { D0 D1 D2 D5 } +static void disable_40 () { D3 D5 } +static void disable_41 () { D0 D3 D5 } +static void disable_42 () { D1 D3 D5 } +static void disable_43 () { D0 D1 D3 D5 } +static void disable_44 () { D2 D3 D5 } +static void disable_45 () { D0 D2 D3 D5 } +static void disable_46 () { D1 D2 D3 D5 } +static void disable_47 () { D0 D1 D2 D3 D5 } +static void disable_48 () { D4 D5 } +static void disable_49 () { D0 D4 D5 } +static void disable_50 () { D1 D4 D5 } +static void disable_51 () { D0 D1 D4 D5 } +static void disable_52 () { D2 D4 D5 } +static void disable_53 () { D0 D2 D4 D5 } +static void disable_54 () { D1 D2 D4 D5 } +static void disable_55 () { D0 D1 D2 D4 D5 } +static void disable_56 () { D3 D4 D5 } +static void disable_57 () { D0 D3 D4 D5 } +static void disable_58 () { D1 D3 D4 D5 } +static void disable_59 () { D0 D1 D3 D4 D5 } +static void disable_60 () { D2 D3 D4 D5 } +static void disable_61 () { D0 D2 D3 D4 D5 } +static void disable_62 () { D1 D2 D3 D4 D5 } +static void disable_63 () { D0 D1 D2 D3 D4 D5 } + + +void (*__ssgEnableTable[64])() = +{ + enable_00, enable_01, enable_02, enable_03, enable_04, + enable_05, enable_06, enable_07, enable_08, enable_09, + enable_10, enable_11, enable_12, enable_13, enable_14, + enable_15, enable_16, enable_17, enable_18, enable_19, + enable_20, enable_21, enable_22, enable_23, enable_24, + enable_25, enable_26, enable_27, enable_28, enable_29, + enable_30, enable_31, + + enable_32, enable_33, enable_34, enable_35, enable_36, + enable_37, enable_38, enable_39, enable_40, enable_41, + enable_42, enable_43, enable_44, enable_45, enable_46, + enable_47, enable_48, enable_49, enable_50, enable_51, + enable_52, enable_53, enable_54, enable_55, enable_56, + enable_57, enable_58, enable_59, enable_60, enable_61, + enable_62, enable_63 +} ; + +void (*__ssgDisableTable[64])() = +{ + disable_00, disable_01, disable_02, disable_03, disable_04, + disable_05, disable_06, disable_07, disable_08, disable_09, + disable_10, disable_11, disable_12, disable_13, disable_14, + disable_15, disable_16, disable_17, disable_18, disable_19, + disable_20, disable_21, disable_22, disable_23, disable_24, + disable_25, disable_26, disable_27, disable_28, disable_29, + disable_30, disable_31, + + disable_32, disable_33, disable_34, disable_35, disable_36, + disable_37, disable_38, disable_39, disable_40, disable_41, + disable_42, disable_43, disable_44, disable_45, disable_46, + disable_47, disable_48, disable_49, disable_50, disable_51, + disable_52, disable_53, disable_54, disable_55, disable_56, + disable_57, disable_58, disable_59, disable_60, disable_61, + disable_62, disable_63 +} ; + diff --git a/src/ssg/ssgStatistics.cxx b/src/ssg/ssgStatistics.cxx new file mode 100644 index 0000000..03a30b1 --- /dev/null +++ b/src/ssg/ssgStatistics.cxx @@ -0,0 +1,18 @@ + +#include "ssgLocal.h" + + +ssgStatistics _ssgCurrStatistics ; + +void ssgStatistics::reset () +{ + vertex_count = leaf_count = 0 ; +} + + +ssgStatistics *ssgGetLatestStatistics () +{ + return & _ssgCurrStatistics ; +} + + diff --git a/src/ssg/ssgStats.cxx b/src/ssg/ssgStats.cxx new file mode 100644 index 0000000..b61ab46 --- /dev/null +++ b/src/ssg/ssgStats.cxx @@ -0,0 +1,95 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgStats.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + +#include "ssgLocal.h" + +int stats_num_vertices = 0 ; +int stats_isect_triangles = 0 ; +int stats_isect_test = 0 ; +int stats_cull_test = 0 ; +int stats_bind_textures = 0 ; +int stats_num_leaves = 0 ; + +int stats_hot_triangles = 0 ; +int stats_hot_test = 0 ; +int stats_hot_no_trav = 0 ; +int stats_hot_radius_reject=0 ; +int stats_hot_triv_accept = 0 ; +int stats_hot_straddle = 0 ; + +int stats_los_triangles = 0 ; +int stats_los_test = 0 ; +int stats_los_no_trav = 0 ; +int stats_los_radius_reject=0 ; +int stats_los_triv_accept = 0 ; +int stats_los_straddle = 0 ; + +static char stats_string [ 1024 ] ; + +char *ssgShowStats () +{ + sprintf ( stats_string, "V=%4d, L=%3d H=%3d IS=%3d IT=%3d HT=%3d CT=%3d BT=%3d\n", + stats_num_vertices , + stats_num_leaves , + stats_hot_triangles , + stats_isect_triangles, + stats_isect_test , + stats_hot_test , + stats_cull_test , + stats_bind_textures ) ; +/* + sprintf ( stats_string, "Tri=%d, Tst=%d NoTr=%d Rej=%d Acp=%d Str=%d\n", + stats_hot_triangles , + stats_hot_test , + stats_hot_no_trav , + stats_hot_radius_reject, + stats_hot_triv_accept , + stats_hot_straddle ) ; +*/ + + stats_num_vertices = 0 ; + stats_num_leaves = 0 ; + stats_isect_triangles = 0 ; + stats_isect_test = 0 ; + stats_cull_test = 0 ; + stats_bind_textures = 0 ; + + stats_hot_triangles = 0 ; + stats_hot_test = 0 ; + stats_hot_no_trav = 0 ; + stats_hot_radius_reject=0 ; + stats_hot_triv_accept = 0 ; + stats_hot_straddle = 0 ; + + stats_los_triangles = 0 ; + stats_los_test = 0 ; + stats_los_no_trav = 0 ; + stats_los_radius_reject=0 ; + stats_los_triv_accept = 0 ; + stats_los_straddle = 0 ; + + return stats_string ; +} + + + diff --git a/src/ssg/ssgTexTrans.cxx b/src/ssg/ssgTexTrans.cxx new file mode 100644 index 0000000..19c683e --- /dev/null +++ b/src/ssg/ssgTexTrans.cxx @@ -0,0 +1,117 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgTexTrans.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "ssgLocal.h" + +void ssgTexTrans::copy_from ( ssgTexTrans *src, int clone_flags ) +{ + ssgBaseTransform::copy_from ( src, clone_flags ) ; +} + +ssgBase *ssgTexTrans::clone ( int clone_flags ) +{ + ssgTexTrans *b = new ssgTexTrans ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgTexTrans::ssgTexTrans ( sgCoord *c ) +{ + type = ssgTypeTexTrans () ; + setTransform ( c ) ; +} + +ssgTexTrans::ssgTexTrans (void) +{ + type = ssgTypeTexTrans () ; +} + +ssgTexTrans::~ssgTexTrans (void) +{ +} + +void ssgTexTrans::setTransform ( sgVec3 xyz ) +{ + sgMakeTransMat4 ( transform, xyz ) ; +} + +void ssgTexTrans::setTransform ( sgCoord *xform, float sx, float sy, float sz ) +{ + sgMakeCoordMat4 ( transform, xform ) ; + sgScaleVec3 ( transform[0], sx ) ; + sgScaleVec3 ( transform[1], sy ) ; + sgScaleVec3 ( transform[2], sz ) ; +} + +void ssgTexTrans::setTransform ( sgCoord *xform ) +{ + sgMakeCoordMat4 ( transform, xform ) ; +} + +void ssgTexTrans::setTransform ( sgMat4 xform ) +{ + sgCopyMat4 ( transform, xform ) ; +} + +void ssgTexTrans::cull ( sgFrustum *f, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_CULL ) ) + return ; + + int cull_result = cull_test ( f, m, test_needed ) ; + + if ( cull_result == SSG_OUTSIDE ) + return ; + + _ssgLoadTexMatrix ( transform ) ; + glMatrixMode ( GL_TEXTURE ) ; + glLoadMatrixf ( (float *) transform ) ; + glMatrixMode ( GL_MODELVIEW ) ; + + for ( ssgEntity *e = getKid ( 0 ) ; e != NULL ; e = getNextKid() ) + e -> cull ( f, m, cull_result != SSG_INSIDE ) ; + + glMatrixMode ( GL_TEXTURE ) ; + glLoadIdentity () ; + glMatrixMode ( GL_MODELVIEW ) ; + _ssgUnloadTexMatrix () ; + + postTravTests ( SSGTRAV_CULL ) ; +} + + + +int ssgTexTrans::load ( FILE *fd ) +{ + return ssgBaseTransform::load(fd) ; +} + +int ssgTexTrans::save ( FILE *fd ) +{ + return ssgBaseTransform::save(fd) ; +} + + + diff --git a/src/ssg/ssgTexture.cxx b/src/ssg/ssgTexture.cxx new file mode 100644 index 0000000..e996918 --- /dev/null +++ b/src/ssg/ssgTexture.cxx @@ -0,0 +1,267 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgTexture.cxx 2123 2007-09-15 13:24:45Z fayjf $ +*/ + + +#include "ssgLocal.h" + + +void ssgTexture::copy_from ( ssgTexture *src, int clone_flags ) +{ + if ( this != src ) + { + /* Avoid meaningless assignments (OK) and corrupting file name (important) when copying to self */ + ssgBase::copy_from ( src, clone_flags ) ; + + wrapu = src -> wrapu ; + wrapv = src -> wrapv ; + mipmap = src -> mipmap ; + + setFilename ( src -> getFilename () ) ; + } + + alloc_handle () ; + ssgTextureInfo info ; + ssgLoadTexture( filename, &info ) ; + has_alpha = (info.alpha != 0) ; + setDefaultGlParams(wrapu, wrapv, mipmap); +} + + +ssgBase *ssgTexture::clone ( int clone_flags ) +{ + ssgTexture *b = new ssgTexture ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +void ssgTexture::setDefaultGlParams(int wrapu, int wrapv, int mipmap) +{ + glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ; + + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ) ; + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR ) ; + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + wrapu ? GL_REPEAT : GL_CLAMP ) ; + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + wrapv ? GL_REPEAT : GL_CLAMP ) ; + +#ifdef GL_VERSION_1_1 + glBindTexture ( GL_TEXTURE_2D, 0 ) ; +#else + glBindTextureEXT ( GL_TEXTURE_2D, 0 ) ; +#endif +} + + +ssgTexture::ssgTexture () +{ + type = ssgTypeTexture () ; + + filename = NULL ; + + own_handle = FALSE ; + handle = 0 ; + + wrapu = TRUE ; + wrapv = TRUE ; + mipmap = TRUE ; + has_alpha = false ; +} + + +ssgTexture::ssgTexture ( const char *fname, GLubyte *image, + int xsize, int ysize, int zsize, + int _wrapu, int _wrapv ) +// fname is used when saving the ssgSimpleState to disk. +// If there is no associated file, you can use a dummy name. +{ + type = ssgTypeTexture () ; + + filename = NULL ; + + own_handle = FALSE ; + handle = 0 ; + + wrapu = _wrapu ; + wrapv = _wrapv ; + mipmap = TRUE ; + + setFilename ( fname ) ; + + alloc_handle () ; +#if 0 + ssgTextureInfo info ; + ssgLoadTexture( filename, &info ) ; + has_alpha = (info.alpha != 0) ; +#else + has_alpha = (zsize == 4) ; + ssgMakeMipMaps ( image, xsize, ysize, zsize ); +#endif + setDefaultGlParams(wrapu, wrapv, TRUE); +} + + +ssgTexture::ssgTexture ( const char *fname, int _wrapu, int _wrapv, int _mipmap ) +{ + type = ssgTypeTexture () ; + + filename = NULL ; + + own_handle = FALSE ; + handle = 0 ; + + wrapu = _wrapu ; + wrapv = _wrapv ; + mipmap = _mipmap ; + + setFilename ( fname ) ; + + alloc_handle () ; + ssgTextureInfo info ; + ssgLoadTexture( filename, &info ) ; + has_alpha = (info.alpha != 0) ; + setDefaultGlParams(wrapu, wrapv, mipmap); +} + + +ssgTexture::~ssgTexture (void) +{ + setFilename ( NULL ) ; + free_handle () ; +} + + +void ssgTexture::alloc_handle () +{ + free_handle () ; + + own_handle = TRUE ; + +#ifdef GL_VERSION_1_1 + glGenTextures ( 1, & handle ) ; + glBindTexture ( GL_TEXTURE_2D, handle ) ; +#else + /* This is only useful on some ancient SGI hardware */ + glGenTexturesEXT ( 1, & handle ) ; + glBindTextureEXT ( GL_TEXTURE_2D, handle ) ; +#endif +} + + +void ssgTexture::free_handle () +{ + if ( handle != 0 ) + { + if ( own_handle ) + { +#ifdef GL_VERSION_1_1 + glDeleteTextures ( 1, & handle ) ; +#else + /* This is only useful on some ancient SGI hardware */ + glDeleteTexturesEXT ( 1, & handle ) ; +#endif + } + + own_handle = FALSE ; + handle = 0 ; + } +} + + +void ssgTexture::setHandle ( GLuint _handle ) +{ + free_handle () ; + + own_handle = FALSE ; + handle = _handle ; +} + + +void ssgTexture::print ( FILE *fd, char *ident, int how_much ) +{ + fprintf ( fd, "%s%s: %s\n", ident, getTypeName (), getFilename () ) ; +} + + +int ssgTexture::load ( FILE *fd ) +{ + delete [] filename ; + + _ssgReadString ( fd, & filename ) ; + _ssgReadInt ( fd, & wrapu ) ; + _ssgReadInt ( fd, & wrapv ) ; + _ssgReadInt ( fd, & mipmap ) ; + + alloc_handle () ; + ssgTextureInfo info ; + ssgLoadTexture( filename, &info ) ; + has_alpha = (info.alpha != 0) ; + setDefaultGlParams(wrapu, wrapv, mipmap); + + return ssgBase::load ( fd ) ; +} + + +int ssgTexture::save ( FILE *fd ) +{ + _ssgWriteString ( fd, filename ) ; + _ssgWriteInt ( fd, wrapu ) ; + _ssgWriteInt ( fd, wrapv ) ; + _ssgWriteInt ( fd, mipmap ) ; + + return ssgBase::save ( fd ) ; +} + + +void ssgTextureArray::add ( ssgTexture* tex ) +{ + if ( tex ) + { + tex -> ref () ; + raw_add ( (char *) &tex ) ; + } +} + + +void ssgTextureArray::removeAll () +{ + for ( int i = 0; i < getNum (); i++ ) + ssgDeRefDelete ( get (i) ) ; + ssgSimpleList::removeAll () ; +} + + +ssgTexture* ssgTextureArray::findByFilename ( const char* fname ) +{ + for ( int i = 0; i < getNum (); i++ ) + { + ssgTexture *tex = get (i) ; + if ( ulStrEqual ( fname, tex->getFilename() ) ) + return tex ; + } + return NULL ; +} + + diff --git a/src/ssg/ssgTransform.cxx b/src/ssg/ssgTransform.cxx new file mode 100644 index 0000000..f4bce4d --- /dev/null +++ b/src/ssg/ssgTransform.cxx @@ -0,0 +1,242 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgTransform.cxx 1992 2004-12-01 08:28:05Z wolfram_kuss $ +*/ + + +#include "ssgLocal.h" + +void ssgTransform::copy_from ( ssgTransform *src, int clone_flags ) +{ + ssgBaseTransform::copy_from ( src, clone_flags ) ; +} + +ssgBase *ssgTransform::clone ( int clone_flags ) +{ + ssgTransform *b = new ssgTransform ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgTransform::ssgTransform ( sgCoord *c ) +{ + type = ssgTypeTransform () ; + setTransform ( c ) ; +} + +ssgTransform::ssgTransform (void) +{ + type = ssgTypeTransform () ; +} + +ssgTransform::~ssgTransform (void) +{ +} + +void ssgTransform::recalcBSphere (void) +{ + ssgBranch::recalcBSphere () ; + + if ( ! bsphere . isEmpty () ) + bsphere . orthoXform ( transform ) ; +} + +void ssgTransform::cull ( sgFrustum *f, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_CULL ) ) + return ; + + int cull_result = cull_test ( f, m, test_needed ) ; + + if ( cull_result == SSG_OUTSIDE ) + return ; + + sgMat4 tmp ; + + sgCopyMat4 ( tmp, m ) ; + sgPreMultMat4 ( tmp, transform ) ; + + _ssgPushMatrix ( tmp ) ; + glPushMatrix () ; + glLoadMatrixf ( (float *) tmp ) ; + + for ( ssgEntity *e = getKid ( 0 ) ; e != NULL ; e = getNextKid() ) + e -> cull ( f, tmp, cull_result != SSG_INSIDE ) ; + + glPopMatrix () ; + _ssgPopMatrix () ; + + postTravTests ( SSGTRAV_CULL ) ; +} + +void ssgTransform::hot ( sgVec3 s, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_HOT ) ) + return ; + + int hot_result = hot_test ( s, m, test_needed ) ; + + if ( hot_result == SSG_OUTSIDE ) + return ; + + sgMat4 tmp ; + + sgCopyMat4 ( tmp, m ) ; + sgPreMultMat4 ( tmp, transform ) ; + + _ssgPushPath ( this ) ; + + for ( ssgEntity *e = getKid ( 0 ) ; e != NULL ; e = getNextKid() ) + e -> hot ( s, tmp, hot_result != SSG_INSIDE ) ; + + _ssgPopPath () ; + + postTravTests ( SSGTRAV_HOT ) ; +} + +void ssgTransform::los ( sgVec3 s, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_LOS ) ) + return ; + + int los_result = los_test ( s, m, test_needed ) ; + + if ( los_result == SSG_OUTSIDE ) + return ; + + sgMat4 tmp ; + + sgCopyMat4 ( tmp, m ) ; + sgPreMultMat4 ( tmp, transform ) ; + + _ssgPushPath ( this ) ; + + for ( ssgEntity *e = getKid ( 0 ) ; e != NULL ; e = getNextKid() ) + e -> los ( s, tmp, los_result != SSG_INSIDE ) ; + + _ssgPopPath () ; + + postTravTests ( SSGTRAV_LOS ) ; +} + +void ssgTransform::isect ( sgSphere *s, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests ( &test_needed, SSGTRAV_ISECT ) ) + return ; + + int isect_result = isect_test ( s, m, test_needed ) ; + + if ( isect_result == SSG_OUTSIDE ) + return ; + + sgMat4 tmp ; + + sgCopyMat4 ( tmp, m ) ; + sgPreMultMat4 ( tmp, transform ) ; + + _ssgPushPath ( this ) ; + + for ( ssgEntity *e = getKid ( 0 ) ; e != NULL ; e = getNextKid() ) + e -> isect ( s, tmp, isect_result != SSG_INSIDE ) ; + + _ssgPopPath () ; + + postTravTests ( SSGTRAV_ISECT ) ; +} + +void ssgTransform::setTransform ( sgVec3 xyz ) +{ + sgMat4 tmp_trans; + sgMakeTransMat4 ( tmp_trans, xyz ) ; + setTransform ( tmp_trans ) ; +} + +void ssgTransform::setTransform ( sgCoord *xform ) +{ + sgMat4 tmp_trans; + sgMakeCoordMat4 ( tmp_trans, xform ) ; + setTransform ( tmp_trans ) ; +} + +void ssgTransform::setTransform ( sgCoord *xform, float sx, float sy, float sz ) +{ + sgMat4 tmp_trans; + sgMakeCoordMat4 ( tmp_trans, xform ) ; + sgScaleVec3 ( tmp_trans[0], sx ) ; + sgScaleVec3 ( tmp_trans[1], sy ) ; + sgScaleVec3 ( tmp_trans[2], sz ) ; + setTransform ( tmp_trans ); +} + +void ssgTransform::setTransform ( sgMat4 xform ) +{ + if ( sgEqualVec4( xform[0], transform[0] ) && + sgEqualVec4( xform[1], transform[1] ) && + sgEqualVec4( xform[2], transform[2] ) && + sgEqualVec4( xform[3], transform[3] ) ) + return; + + updateTransform () ; + sgCopyMat4 ( transform, xform ) ; + firsttime () ; + dirtyBSphere () ; +} + + +void ssgTransform::getNetTransform ( sgMat4 xform ) +{ + if ( getNumParents () > 0 ) + { + getParent ( 0 ) -> getNetTransform ( xform ) ; + sgPreMultMat4 ( xform, transform ) ; + } + else + sgCopyMat4 ( xform, transform ) ; +} + + +void ssgTransform::getLastNetTransform ( sgMat4 xform ) +{ + sgMat4 last_xform ; + getLastTransform ( last_xform ) ; + + if ( getNumParents () > 0 ) + { + getParent ( 0 ) -> getLastNetTransform ( xform ) ; + sgPreMultMat4 ( xform, last_xform ) ; + } + else + sgCopyMat4 ( xform, last_xform ) ; +} + + +int ssgTransform::load ( FILE *fd ) +{ + return ssgBaseTransform::load(fd) ; +} + +int ssgTransform::save ( FILE *fd ) +{ + return ssgBaseTransform::save(fd) ; +} + + diff --git a/src/ssg/ssgTween.cxx b/src/ssg/ssgTween.cxx new file mode 100644 index 0000000..751e895 --- /dev/null +++ b/src/ssg/ssgTween.cxx @@ -0,0 +1,500 @@ + +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgTween.cxx 1996 2004-12-29 07:19:40Z sjbaker $ +*/ + + +#include "ssgLocal.h" +#include "ul.h" + +static float current_tween_state = 0.0f ; +static int current_tween_mode = SSGTWEEN_STOP_AT_END ; + +const char *ssgTween::getTypeName (void) { return "ssgTween" ; } + +int _ssgGetCurrentTweenMode () { return current_tween_mode ; } +float _ssgGetCurrentTweenState () { return current_tween_state ; } + + +void _ssgSetCurrentTweenSettings ( float state, int mode ) +{ + _ssgSetRealCurrentTweenSettings ( state, mode ) ; + _ssgSetTweenState ( state, mode ) ; /* Add it into the Dlist for later */ +} + + +void _ssgSetRealCurrentTweenSettings ( float state, int mode ) +{ + current_tween_mode = mode ; + current_tween_state = state ; +} + + +void ssgTween::copy_from ( ssgTween *src, int clone_flags ) +{ + ssgLeaf::copy_from ( src, clone_flags ) ; + + gltype = src -> getPrimitiveType () ; + + if ( src->vertices != NULL && ( clone_flags & SSG_CLONE_GEOMETRY ) ) + vertices = (ssgVertexArray *)( src -> vertices -> clone ( clone_flags )) ; + else + vertices = src -> vertices ; + + if ( src->normals != NULL && ( clone_flags & SSG_CLONE_GEOMETRY ) ) + normals = (ssgNormalArray *)( src -> normals -> clone ( clone_flags )) ; + else + normals = src -> normals ; + + if ( src->texcoords != NULL && ( clone_flags & SSG_CLONE_GEOMETRY ) ) + texcoords = (ssgTexCoordArray *)( src -> texcoords -> clone ( clone_flags )) ; + else + texcoords = src -> texcoords ; + + if ( src->colours != NULL && ( clone_flags & SSG_CLONE_GEOMETRY ) ) + colours = (ssgColourArray *)( src -> colours -> clone ( clone_flags )) ; + else + colours = src -> colours ; + + if ( vertices != NULL ) vertices -> ref () ; + if ( normals != NULL ) normals -> ref () ; + if ( texcoords != NULL ) texcoords -> ref () ; + if ( colours != NULL ) colours -> ref () ; + + recalcBSphere () ; +} + +ssgBase *ssgTween::clone ( int clone_flags ) +{ + ssgTween *b = new ssgTween ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +void ssgTween::init () +{ + curr_bank = 0 ; + type = ssgTypeTween () ; + + render_vertices = new ssgVertexArray () ; + render_normals = new ssgNormalArray () ; + render_texcoords = new ssgTexCoordArray () ; + render_colours = new ssgColourArray () ; + + render_vertices -> ref () ; + render_normals -> ref () ; + render_texcoords -> ref () ; + render_colours -> ref () ; + + banked_vertices = new ulList ( 2 ) ; + banked_normals = new ulList ( 2 ) ; + banked_texcoords = new ulList ( 2 ) ; + banked_colours = new ulList ( 2 ) ; + + vertices = render_vertices ; + normals = render_normals ; + texcoords = render_texcoords ; + colours = render_colours ; + + recalcBSphere () ; +} + + +ssgTween::ssgTween () +{ + init () ; + gltype = GL_POINTS ; +} + + +ssgTween::ssgTween ( GLenum ty ) +{ + init () ; + gltype = ty ; +} + + +int ssgTween::newBank ( ssgVertexArray *vl, ssgNormalArray *nl, + ssgTexCoordArray *tl, ssgColourArray *cl ) +{ + int bank = banked_vertices -> getNumEntities () ; + + banked_vertices -> addEntity ( vl != NULL ? vl : + ( banked_vertices -> getEntity(bank-1) ) ) ; + + banked_normals -> addEntity ( nl != NULL ? nl : + ( banked_normals -> getEntity(bank-1) ) ) ; + + banked_texcoords -> addEntity ( tl != NULL ? tl : + ( banked_texcoords -> getEntity(bank-1) ) ) ; + + banked_colours -> addEntity ( cl != NULL ? cl : + ( banked_colours -> getEntity(bank-1) ) ) ; + + setBank ( bank ) ; + + vertices -> ref () ; + normals -> ref () ; + texcoords -> ref () ; + colours -> ref () ; + + dirtyBSphere () ; /* Cause parents to redo their bspheres */ + return bank ; +} + + + +int ssgTween::newBank ( int newVertices , int newNormals, + int newTexCoords, int newColours ) +{ + return newBank ( newVertices ? ( new ssgVertexArray () ) : NULL, + newNormals ? ( new ssgNormalArray () ) : NULL, + newTexCoords ? ( new ssgTexCoordArray () ) : NULL, + newColours ? ( new ssgColourArray () ) : NULL ) ; +} + + +void ssgTween::setBank ( int bank ) +{ + assert ( bank < banked_vertices -> getNumEntities () ) ; + + curr_bank = bank ; + + vertices = (ssgVertexArray *) banked_vertices -> getEntity ( bank ) ; + normals = (ssgNormalArray *) banked_normals -> getEntity ( bank ) ; + texcoords = (ssgTexCoordArray *) banked_texcoords -> getEntity ( bank ) ; + colours = (ssgColourArray *) banked_colours -> getEntity ( bank ) ; +} + + +void ssgTween::setVertices ( ssgVertexArray *vl ) +{ + banked_vertices -> replaceEntity ( curr_bank, vl ) ; + ssgVtxTable::setVertices ( vl ) ; + dirtyBSphere () ; /* Cause parents to redo their bspheres */ +} + +void ssgTween::setNormals ( ssgNormalArray *nl ) +{ + banked_normals -> replaceEntity ( curr_bank, nl ) ; + ssgVtxTable::setNormals ( nl ) ; + dirtyBSphere () ; /* Cause parents to redo their bspheres */ +} + +void ssgTween::setTexCoords ( ssgTexCoordArray *tl ) +{ + banked_texcoords -> replaceEntity ( curr_bank, tl ) ; + ssgVtxTable::setTexCoords ( tl ) ; + dirtyBSphere () ; /* Cause parents to redo their bspheres */ +} + +void ssgTween::setColours ( ssgColourArray *cl ) +{ + banked_colours -> replaceEntity ( curr_bank, cl ) ; + ssgVtxTable::setColours ( cl ) ; + dirtyBSphere () ; /* Cause parents to redo their bspheres */ +} + +ssgTween::~ssgTween () +{ + /* Need to ref these one more time to avoid problems when the base class destructor + deletes them */ + + vertices -> ref () ; + normals -> ref () ; + texcoords -> ref () ; + colours -> ref () ; + + for ( int i = 0 ; i < getNumBanks () ; i++ ) + { + ssgDeRefDelete ( (ssgVertexArray *) banked_vertices -> getEntity (i)) ; + ssgDeRefDelete ( (ssgNormalArray *) banked_normals -> getEntity (i)) ; + ssgDeRefDelete ( (ssgTexCoordArray *) banked_texcoords -> getEntity (i)) ; + ssgDeRefDelete ( (ssgColourArray *) banked_colours -> getEntity (i)) ; + } + + delete banked_vertices ; + delete banked_normals ; + delete banked_texcoords ; + delete banked_colours ; + + ssgDeRefDelete ( render_vertices ) ; + ssgDeRefDelete ( render_normals ) ; + ssgDeRefDelete ( render_texcoords ) ; + ssgDeRefDelete ( render_colours ) ; +} + + +void ssgTween::recalcBSphere () +{ + emptyBSphere () ; + bbox . empty () ; + + for ( int b = 0 ; b < banked_vertices -> getNumEntities () ; b++ ) + { + ssgVertexArray *va = (ssgVertexArray *) banked_vertices -> getEntity ( b ) ; + + for ( int i = 0 ; i < va -> getNum() ; i++ ) + bbox . extend ( va->get(i) ) ; + } + + extendBSphere ( & bbox ) ; + dirtyBSphere () ; /* Cause parents to redo their bspheres */ +} + + +void ssgTween::draw () +{ + if ( ! preDraw () ) + return ; + + if ( _ssgCurrentContext-> stateOverridden () ) + _ssgCurrentContext -> overriddenState () -> apply () ; + else + if ( hasState () ) + getState () -> apply () ; + + stats_num_leaves++ ; + stats_num_vertices += getNumVertices() ; + + float tstate = _ssgGetCurrentTweenState () ; + int num_banks = banked_vertices -> getNumEntities () ; + + if ( tstate < 0.0f ) tstate = 0.0f ; + + int state1 = (int) floor ( tstate ) ; + int state2 = state1 + 1 ; + float tween = tstate - (float) state1 ; + + if ( _ssgGetCurrentTweenMode () == SSGTWEEN_REPEAT ) + { + state1 %= num_banks ; + state2 %= num_banks ; + } + else + { + if ( state1 >= num_banks ) state1 = num_banks - 1 ; + if ( state2 >= num_banks ) state2 = num_banks - 1 ; + } + + if ( state1 == state2 ) tween = 0.0f ; + + int l1, l2 ; + + /* Lerp the vertices... */ + + ssgVertexArray *v1 = (ssgVertexArray *) banked_vertices->getEntity (state1) ; + ssgVertexArray *v2 = (ssgVertexArray *) banked_vertices->getEntity (state2) ; + l1 = v1 -> getNum () ; + l2 = v2 -> getNum () ; + + assert ( l1 == l2 ) ; + + if ( render_vertices -> getNum () < l1 ) + render_vertices -> setNum ( l1 ) ; + + if ( v1 == v2 ) + vertices = v1 ; + else + { + vertices = render_vertices ; + + for ( int i = 0 ; i < l1 ; i++ ) + sgLerpVec3 ( vertices->get(i),v1->get(i),v2->get(i), tween ) ; + } + + /* Lerp the normals */ + + ssgNormalArray *n1 = (ssgNormalArray *) banked_normals->getEntity (state1) ; + ssgNormalArray *n2 = (ssgNormalArray *) banked_normals->getEntity (state2) ; + l1 = n1 -> getNum () ; + l2 = n2 -> getNum () ; + + assert ( l1 == l2 ) ; + + if ( render_normals -> getNum () < l1 ) + render_normals -> setNum ( l1 ) ; + + if ( n1 == n2 ) + normals = n1 ; + else + { + normals = render_normals ; + + for ( int i = 0 ; i < l1 ; i++ ) + sgLerpVec3 ( normals->get(i),n1->get(i),n2->get(i), tween ) ; + } + + /* Lerp the texcoords */ + + ssgTexCoordArray *t1 = (ssgTexCoordArray *) banked_texcoords->getEntity (state1) ; + ssgTexCoordArray *t2 = (ssgTexCoordArray *) banked_texcoords->getEntity (state2) ; + l1 = t1 -> getNum () ; + l2 = t2 -> getNum () ; + + assert ( l1 == l2 ) ; + + if ( render_texcoords -> getNum () < l1 ) + render_texcoords -> setNum ( l1 ) ; + + if ( t1 == t2 ) + texcoords = t1 ; + else + { + texcoords = render_texcoords ; + + for ( int i = 0 ; i < l1 ; i++ ) + sgLerpVec2 ( texcoords->get(i),t1->get(i),t2->get(i), tween ) ; + } + + /* Lerp the colours */ + + ssgColourArray *c1 = (ssgColourArray *) banked_colours->getEntity (state1) ; + ssgColourArray *c2 = (ssgColourArray *) banked_colours->getEntity (state2) ; + l1 = c1 -> getNum () ; + l2 = c2 -> getNum () ; + + assert ( l1 == l2 ) ; + + if ( render_colours -> getNum () < l1 ) + render_colours -> setNum ( l1 ) ; + + if ( c1 == c2 ) + colours = c1 ; + else + { + colours = render_colours ; + + for ( int i = 0 ; i < l1 ; i++ ) + sgLerpVec4 ( colours->get(i),c1->get(i),c2->get(i), tween ) ; + } + + draw_geometry () ; + + setBank ( state1 ) ; + + if ( postDrawCB != NULL ) + (*postDrawCB)(this) ; +} + + + +void ssgTween::transform ( const sgMat4 m ) +{ + int prev_bank = curr_bank ; + + for ( int i = 0 ; i < getNumBanks(); i++ ) + { + // see if this bank has been transformed already + // (it is really a deeper problem, but this will work in simple cases) + int j ; + for ( j = 0 ; j < i ; j++ ) + if ( banked_vertices -> getEntity ( i ) == banked_vertices -> getEntity ( j ) ) + break; + if ( j == i ) + { + setBank ( i ) ; + ssgVtxTable::transform ( m ) ; + } + } + + setBank ( prev_bank ) ; +} + + + +int ssgTween::load ( FILE *fd ) +{ + sgVec3 temp; + int num_banks ; + + _ssgReadVec3 ( fd, temp ); bbox.setMin( temp ) ; + _ssgReadVec3 ( fd, temp ); bbox.setMax( temp ) ; + _ssgReadInt ( fd, (int *)(&gltype) ) ; + _ssgReadInt ( fd, & num_banks ) ; + + if ( ! ssgLeaf::load(fd) ) + return FALSE ; + + for ( int i = 0 ; i < num_banks ; i++ ) + { + if ( ! _ssgLoadObject (fd,(ssgBase **)&vertices, ssgTypeVertexArray() ) || + ! _ssgLoadObject (fd,(ssgBase **)&normals, ssgTypeNormalArray() ) || + ! _ssgLoadObject (fd,(ssgBase **)&texcoords, ssgTypeTexCoordArray()) || + ! _ssgLoadObject (fd,(ssgBase **)&colours, ssgTypeColourArray() ) ) + return FALSE ; + + newBank ( vertices, normals, texcoords, colours ) ; + } + + return TRUE ; +} + + +int ssgTween::save ( FILE *fd ) +{ + int num_banks = banked_vertices -> getNumEntities () ; + _ssgWriteVec3 ( fd, bbox.getMin() ) ; + _ssgWriteVec3 ( fd, bbox.getMax() ) ; + _ssgWriteInt ( fd, (int) gltype ) ; + _ssgWriteInt ( fd, num_banks ) ; + + if ( ! ssgLeaf::save(fd) ) + return FALSE ; + + for ( int i = 0 ; i < num_banks ; i++ ) + { + setBank ( i ) ; + + if ( ! _ssgSaveObject ( fd, vertices ) || + ! _ssgSaveObject ( fd, normals ) || + ! _ssgSaveObject ( fd, texcoords ) || + ! _ssgSaveObject ( fd, colours ) ) + return FALSE ; + } + + return TRUE ; +} + + + + +void ssgTween::print ( FILE *fd, char *indent, int how_much ) +{ + char in [ 100 ] ; + + if ( how_much == 0 ) + return ; + + sprintf ( in, "%s ", indent ); + + ssgLeaf ::print ( fd, indent, how_much ) ; + + vertices -> print ( fd, in, how_much ) ; + normals -> print ( fd, in, how_much ) ; + texcoords -> print ( fd, in, how_much ) ; + colours -> print ( fd, in, how_much ) ; +} + + + diff --git a/src/ssg/ssgTweenController.cxx b/src/ssg/ssgTweenController.cxx new file mode 100644 index 0000000..623e85c --- /dev/null +++ b/src/ssg/ssgTweenController.cxx @@ -0,0 +1,98 @@ + +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgTweenController.cxx 1996 2004-12-29 07:19:40Z sjbaker $ +*/ + + +#include "ssgLocal.h" + +const char *ssgTweenController::getTypeName (void) { return "ssgTweenController" ; } + +void ssgTweenController::copy_from ( ssgTweenController *src, int clone_flags ) +{ + selectBank ( src->getCurrBank () ) ; + ssgBranch::copy_from ( src, clone_flags ) ; +} + +ssgBase *ssgTweenController::clone ( int clone_flags ) +{ + ssgTweenController *b = new ssgTweenController ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + + +ssgTweenController::ssgTweenController (void) +{ + type = ssgTypeTweenController () ; + curr_bank = 0.0f ; +} + + +ssgTweenController::~ssgTweenController (void) +{ + removeAllKids () ; +} + + +void ssgTweenController::cull ( sgFrustum *f, sgMat4 m, int test_needed ) +{ + float old_state = _ssgGetCurrentTweenState () ; + int old_mode = _ssgGetCurrentTweenMode () ; + + _ssgSetCurrentTweenSettings ( curr_bank, mode ) ; + + ssgBranch::cull ( f, m, test_needed ) ; + + _ssgSetCurrentTweenSettings ( old_state, old_mode ) ; +} + + + +int ssgTweenController::load ( FILE *fd ) +{ + _ssgReadFloat ( fd, & curr_bank ) ; + + return ssgBranch::load ( fd ) ; +} + + +int ssgTweenController::save ( FILE *fd ) +{ + _ssgWriteFloat ( fd, curr_bank ) ; + return ssgBranch::save ( fd ) ; +} + + + +void ssgTweenController::print ( FILE *fd, char *indent, int how_much ) +{ + if ( how_much == 0 ) + return ; + + fprintf ( fd, "%sCurrent Bank = %f\n", indent, curr_bank ); + + ssgBranch::print ( fd, indent, how_much ) ; +} + + diff --git a/src/ssg/ssgVTable.cxx b/src/ssg/ssgVTable.cxx new file mode 100644 index 0000000..3098eb6 --- /dev/null +++ b/src/ssg/ssgVTable.cxx @@ -0,0 +1,869 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgVTable.cxx 1938 2004-06-24 16:30:55Z sjbaker $ +*/ + + +#include "ssgLocal.h" + +void ssgVTable::copy_from ( ssgVTable *src, int clone_flags ) +{ + ssgLeaf::copy_from ( src, clone_flags ) ; + + gltype = src -> getPrimitiveType () ; + indexed = src -> isIndexed () ; + + num_vertices = src -> getNumVertices () ; + num_normals = src -> getNumNormals () ; + num_colours = src -> getNumColours () ; + num_texcoords = src -> getNumTexCoords () ; + + /* + I should probably copy these arrays if SSG_CLONE_GEOMETRY + is set - but life is short and ssgVTable is obsolete - + and the inability to free the space that would create + was the main reason to obsolete ssgVTable. + */ + + src -> getVertexList ( (void **) & vertices , & v_index ) ; + src -> getNormalList ( (void **) & normals , & n_index ) ; + src -> getTexCoordList ( (void **) & texcoords, & t_index ) ; + src -> getColourList ( (void **) & colours , & c_index ) ; + + recalcBSphere () ; +} + + +ssgBase *ssgVTable::clone ( int clone_flags ) +{ + ssgVTable *b = new ssgVTable ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgVTable::ssgVTable () +{ + type = ssgTypeVTable () ; + gltype = GL_POINTS ; + indexed = FALSE ; + num_vertices = 0 ; v_index = NULL ; vertices = NULL ; + num_normals = 0 ; n_index = NULL ; normals = NULL ; + num_texcoords = 0 ; t_index = NULL ; texcoords = NULL ; + num_colours = 0 ; c_index = NULL ; colours = NULL ; +} + + +ssgVTable::ssgVTable ( GLenum ty, + int nv, unsigned short *vi, sgVec3 *vl, + int nn, unsigned short *ni, sgVec3 *nl, + int nt, unsigned short *ti, sgVec2 *tl, + int nc, unsigned short *ci, sgVec4 *cl ) +{ + type = ssgTypeVTable () ; + gltype = ty ; + + indexed = TRUE ; + num_vertices = nv ; v_index = vi ; vertices = vl ; + num_normals = nn ; n_index = ni ; normals = nl ; + num_texcoords = nt ; t_index = ti ; texcoords = tl ; + num_colours = nc ; c_index = ci ; colours = cl ; + + recalcBSphere () ; +} + + + +ssgVTable::ssgVTable ( GLenum ty, + int nv, sgVec3 *vl, + int nn, sgVec3 *nl, + int nt, sgVec2 *tl, + int nc, sgVec4 *cl ) +{ + gltype = ty ; + type = ssgTypeVTable () ; + + indexed = FALSE ; + num_vertices = nv ; vertices = vl ; + num_normals = nn ; normals = nl ; + num_texcoords = nt ; texcoords = tl ; + num_colours = nc ; colours = cl ; + + recalcBSphere () ; +} + + +ssgVTable::~ssgVTable () +{ +} + + +void ssgVTable::getTriangle ( int n, short *v1, short *v2, short *v3 ) +{ + switch ( getPrimitiveType () ) + { + case GL_POLYGON : + case GL_TRIANGLE_FAN : + *v1 = 0 ; + *v2 = n+1 ; + *v3 = n+2 ; + return ; + + case GL_TRIANGLES : + *v1 = n*3 ; + *v2 = n*3+1 ; + *v3 = n*3+2 ; + return ; + + case GL_TRIANGLE_STRIP : + case GL_QUAD_STRIP : + if ( n & 1 ) + { + *v3 = n ; + *v2 = n+1 ; + *v1 = n+2 ; + } + else + { + *v1 = n ; + *v2 = n+1 ; + *v3 = n+2 ; + } + return ; + + case GL_QUADS : + *v1 = (n/2)*4 + (n&1) + 0 ; + *v2 = (n/2)*4 + (n&1) + 1 ; + *v3 = (n/2)*4 + (n&1) + 2 ; + return ; + + default : return ; + } +} + + +int ssgVTable::getNumTriangles () +{ + switch ( getPrimitiveType () ) + { + case GL_POLYGON : + case GL_TRIANGLE_FAN : + return getNumVertices() - 2 ; + + case GL_TRIANGLES : + return getNumVertices() / 3 ; + + case GL_TRIANGLE_STRIP : + return getNumVertices() - 2 ; + + case GL_QUADS : + return ( getNumVertices() / 4 ) * 2 ; + + case GL_QUAD_STRIP : + return ( ( getNumVertices() - 2 ) / 2 ) * 2 ; + + default : break ; + } + + return 0 ; +} + +int ssgVTable::getNumLines () +{ + switch ( getPrimitiveType () ) + { + case GL_POLYGON : + case GL_TRIANGLE_FAN : + case GL_TRIANGLES : + case GL_TRIANGLE_STRIP : + case GL_QUADS : + case GL_QUAD_STRIP : + case GL_POINTS : + return 0; + case GL_LINES : + // wk: FIXME: check the 3 following formulas. I don't have an OpenGL bokk at hand currently :-( + return getNumVertices()/2; + case GL_LINE_LOOP : + return getNumVertices(); + case GL_LINE_STRIP : + return getNumVertices()-1; + default : break ; + } + assert(false); /* Should never get here */ + return 0 ; +} + +void ssgVTable::getLine ( int n, short *v1, short *v2 ) +{ + assert( n>=0 ); + switch ( getPrimitiveType () ) + { + case GL_POLYGON : + case GL_TRIANGLE_FAN : + case GL_TRIANGLES : + case GL_TRIANGLE_STRIP : + case GL_QUADS : + case GL_QUAD_STRIP : + case GL_POINTS : + assert(false); + case GL_LINES : + // wk: FIXME: check the 3 following formulas. I don't have an OpenGL bokk at hand currently :-( + assert ( 2*n+1 < getNumVertices() ); + *v1 = 2*n; + *v2 = 2*n+1 ; + return ; + case GL_LINE_LOOP : + assert ( n < getNumVertices() ); + *v1 = n; + if ( n == getNumVertices()-1 ) + *v2 = 0; + else + *v2 = n+1; + return ; + case GL_LINE_STRIP : + assert ( n < getNumVertices()-1 ); + *v1 = n; + *v2 = n+1; + return; + default : + break ; + } + assert(false); /* Should never get here */ + return ; +} + +void ssgVTable::transform ( const sgMat4 m ) +{ + int i ; + + for ( i = 0 ; i < num_vertices ; i++ ) + sgXformPnt3 ( vertices[i], vertices[i], m ) ; + + for ( i = 0 ; i < num_normals ; i++ ) + sgXformVec3 ( normals[i], normals[i], m ) ; + + recalcBSphere () ; +} + + +void ssgVTable::recalcBSphere () +{ + emptyBSphere () ; + bbox . empty () ; + + int i ; + + if ( indexed ) + for ( i = 0 ; i < num_vertices ; i++ ) + bbox . extend ( vertices [ v_index [ i ] ] ) ; + else + for ( i = 0 ; i < num_vertices ; i++ ) + bbox . extend ( vertices [ i ] ) ; + + extendBSphere ( & bbox ) ; + dirtyBSphere () ; /* Cause parents to redo their bspheres */ + bsphere_is_invalid = FALSE ; +} + + +void ssgVTable::draw () +{ + if ( ! preDraw () ) + return ; + + if ( _ssgCurrentContext-> stateOverridden () ) + _ssgCurrentContext -> overriddenState () -> apply () ; + else + if ( hasState () ) + getState () -> apply () ; + + stats_num_leaves++ ; + stats_num_vertices += num_vertices ; + +#ifdef _SSG_USE_DLIST + if ( dlist ) + glCallList ( dlist ) ; + else +#endif + draw_geometry () ; + + if ( postDrawCB != NULL ) + (*postDrawCB)(this) ; +} + +void ssgVTable::drawHighlight ( sgVec4 /* colour */, int /* vertex id */ ) +{ +} + +void ssgVTable::drawHighlight ( sgVec4 /* colour */ ) +{ +} + +void ssgVTable::pick ( int baseName ) +{ + int i ; + + glPushName ( baseName ) ; + + if ( indexed ) + { + glBegin ( gltype ) ; + + for ( i = 0 ; i < num_vertices ; i++ ) + glVertex3fv( vertices [ v_index [ i ]] ) ; + + glEnd () ; + + /* Then test each vertex in turn */ + + for ( i = 0 ; i < num_vertices ; i++ ) + { + glLoadName ( baseName + i + 1 ) ; + glBegin ( GL_POINTS ) ; + glVertex3fv( vertices [ v_index [ i ]] ) ; + glEnd () ; + } + } + else + { + glBegin ( gltype ) ; + + for ( i = 0 ; i < num_vertices ; i++ ) + { + glLoadName ( baseName + i + 1 ) ; + glVertex3fv( vertices [ i ] ) ; + } + + glEnd () ; + + /* Then test each vertex in turn */ + + for ( i = 0 ; i < num_vertices ; i++ ) + { + glLoadName ( baseName + i + 1 ) ; + glBegin ( GL_POINTS ) ; + glVertex3fv( vertices [ i ] ) ; + glEnd () ; + } + } + + glPopName () ; +} + +void ssgVTable::draw_geometry () +{ + _ssgCurrStatistics . bumpVertexCount ( num_vertices ) ; + _ssgCurrStatistics . bumpLeafCount ( 1 ) ; + + if ( indexed ) + { + glBegin ( gltype ) ; + + if ( num_colours == 0 ) glColor4f ( 1.0f, 1.0f, 1.0f, 1.0f ) ; + if ( num_colours == 1 ) glColor4fv ( colours [ c_index [ 0 ]] ) ; + if ( num_normals == 1 ) glNormal3fv ( normals [ n_index [ 0 ]] ) ; + + for ( int i = 0 ; i < num_vertices ; i++ ) + { + if ( num_colours > 1 ) glColor4fv ( colours [ c_index [ i ]] ) ; + if ( num_normals > 1 ) glNormal3fv ( normals [ n_index [ i ]] ) ; + if ( num_texcoords > 1 ) glTexCoord2fv ( texcoords [ t_index [ i ]] ) ; + + glVertex3fv ( vertices [ v_index [ i ]] ) ; + } + + glEnd () ; + } + else + { + glBegin ( gltype ) ; + + if ( num_colours == 0 ) glColor4f ( 1.0f, 1.0f, 1.0f, 1.0f ) ; + if ( num_colours == 1 ) glColor4fv ( colours [ 0 ] ) ; + if ( num_normals == 1 ) glNormal3fv ( normals [ 0 ] ) ; + + for ( int i = 0 ; i < num_vertices ; i++ ) + { + if ( num_colours > 1 ) glColor4fv ( colours [ i ] ) ; + if ( num_normals > 1 ) glNormal3fv ( normals [ i ] ) ; + if ( num_texcoords > 1 ) glTexCoord2fv ( texcoords [ i ] ) ; + + glVertex3fv ( vertices [ i ] ) ; + } + + glEnd () ; + } +} + + + +void ssgVTable::hot_triangles ( sgVec3 s, sgMat4 m, int /* test_needed */ ) +{ + int nt = getNumTriangles () ; + + stats_hot_triangles += nt ; + + for ( int i = 0 ; i < nt ; i++ ) + { + short v1, v2, v3 ; + sgVec3 vv1, vv2, vv3 ; + sgVec4 plane ; + + if ( _ssgBackFaceCollisions ) + getTriangle ( i, &v1, &v3, &v2 ) ; + else + getTriangle ( i, &v1, &v2, &v3 ) ; + + sgXformPnt3 ( vv1, getVertex(v1), m ) ; + sgXformPnt3 ( vv2, getVertex(v2), m ) ; + sgXformPnt3 ( vv3, getVertex(v3), m ) ; + + /* + Does the X/Y coordinate lie outside the triangle's bbox, or + does the Z coordinate lie beneath the bbox ? + */ + + if ( ( s[0] < vv1[0] && s[0] < vv2[0] && s[0] < vv3[0] ) || + ( s[1] < vv1[1] && s[1] < vv2[1] && s[1] < vv3[1] ) || + ( s[0] > vv1[0] && s[0] > vv2[0] && s[0] > vv3[0] ) || + ( s[1] > vv1[1] && s[1] > vv2[1] && s[1] > vv3[1] ) || + ( s[2] < vv1[2] && s[2] < vv2[2] && s[2] < vv3[2] ) ) + continue ; + + sgMakePlane ( plane, vv1, vv2, vv3 ) ; + + if ( _ssgIsHotTest ) + { + /* No HOT from upside-down or vertical triangles */ + + if ( getCullFace() && plane [ 2 ] <= 0 ) + continue ; + + /* Find the point vertically below the text point + as it crosses the plane of the polygon */ + + float z = sgHeightOfPlaneVec2 ( plane, s ) ; + + /* No HOT from below the triangle */ + + if ( z > s[2] ) + continue ; + + /* Outside the vertical extent of the triangle? */ + + if ( ( z < vv1[2] && z < vv2[2] && z < vv3[2] ) || + ( z > vv1[2] && z > vv2[2] && z > vv3[2] ) ) + continue ; + } + + /* + Now it gets messy - the isect point is inside + the bbox of the triangle - but that's not enough. + Is it inside the triangle itself? + */ + + float e1 = s [0] * vv1[1] - s [1] * vv1[0] ; + float e2 = s [0] * vv2[1] - s [1] * vv2[0] ; + float e3 = s [0] * vv3[1] - s [1] * vv3[0] ; + float ep1 = vv1[0] * vv2[1] - vv1[1] * vv2[0] ; + float ep2 = vv2[0] * vv3[1] - vv2[1] * vv3[0] ; + float ep3 = vv3[0] * vv1[1] - vv3[1] * vv1[0] ; + + float ap = (float) fabs ( ep1 + ep2 + ep3 ) ; + float ai = (float) ( fabs ( e1 + ep1 - e2 ) + + fabs ( e2 + ep2 - e3 ) + + fabs ( e3 + ep3 - e1 ) ) ; + + if ( ai > ap * 1.01 ) + continue ; + + _ssgAddHit ( this, i, m, plane ) ; + } +} + +void ssgVTable::los_triangles ( sgVec3 s, sgMat4 m, int /* test_needed */ ) +{ + int nt = getNumTriangles () ; + + stats_los_triangles += nt ; + + for ( int i = 0 ; i < nt ; i++ ) + { + short v1, v2, v3 ; + sgVec3 vv1, vv2, vv3 ; + sgVec4 plane ; + + SGfloat edge1[3], edge2[3], tvec[3], pvec[3], qvec[3]; + SGfloat det,inv_det; + SGfloat /*t,*/u,v; + + if ( _ssgBackFaceCollisions ) + getTriangle ( i, &v1, &v3, &v2 ) ; + else + getTriangle ( i, &v1, &v2, &v3 ) ; + + sgXformPnt3 ( vv1, getVertex(v1), m ) ; + sgXformPnt3 ( vv2, getVertex(v2), m ) ; + sgXformPnt3 ( vv3, getVertex(v3), m ) ; + sgVec3 cam; + cam[0] = m[0][3]; + cam[1] = m[1][3]; + cam[2] = m[2][3]; + //if ( _ssgIsLosTest ) + //{ + + /* find vectors for two edges sharing vert0 */ + sgSubVec3(edge1, vv2, vv1); + sgSubVec3(edge2, vv3, vv1); + + /* begin calculating determinant - also used to calculate U parameter */ + sgVectorProductVec3(pvec, s, edge2); + + /* if determinant is near zero, ray lies in plane of triangle */ + det = sgScalarProductVec3(edge1, pvec); + + if (det > -0.0000001 && det < 0.0000001) continue; + inv_det = (float)1.0 / det; + + /* calculate distance from vert0 to ray origin */ + sgSubVec3(tvec, cam, vv1); + + /* calculate U parameter and test bounds */ + u = sgScalarProductVec3(tvec, pvec) * inv_det; + if (u < 0.0 || u > 1.0) + continue; + + /* prepare to test V parameter */ + sgVectorProductVec3(qvec, tvec, edge1); + + /* calculate V parameter and test bounds */ + v = sgScalarProductVec3(s, qvec) * inv_det; + if (v < 0.0 || u + v > 1.0) + continue; + + /* calculate t, ray intersects triangle */ + //t = sgScalarProductVec3(edge2, qvec) * inv_det; + //} + + sgMakePlane ( plane, vv1, vv2, vv3 ) ; + _ssgAddHit ( this, i, m, plane ) ; + } +} + +void ssgVTable::isect_triangles ( sgSphere *s, sgMat4 m, int test_needed ) +{ + int nt = getNumTriangles () ; + + stats_isect_triangles += nt ; + + for ( int i = 0 ; i < nt ; i++ ) + { + short v1, v2, v3 ; + sgVec3 vv1, vv2, vv3 ; + sgVec4 plane ; + + if ( _ssgBackFaceCollisions ) + getTriangle ( i, &v1, &v3, &v2 ) ; + else + getTriangle ( i, &v1, &v2, &v3 ) ; + + sgXformPnt3 ( vv1, getVertex(v1), m ) ; + sgXformPnt3 ( vv2, getVertex(v2), m ) ; + sgXformPnt3 ( vv3, getVertex(v3), m ) ; + + sgMakePlane ( plane, vv1, vv2, vv3 ) ; + + if ( ! test_needed ) + { + _ssgAddHit ( this, i, m, plane ) ; + continue ; + } + + float dp = (float) fabs ( sgDistToPlaneVec3 ( plane, s->getCenter() ) ) ; + + if ( dp > s->getRadius() ) + continue ; + + /* + The BSphere touches the plane containing + the triangle - but does it actually touch + the triangle itself? Let's erect some + vertical walls around the triangle. + */ + + /* + Construct a 'wall' as a plane through + two vertices and a third vertex made + by adding the surface normal to the + first of those two vertices. + */ + + sgVec3 vvX ; + sgVec4 planeX ; + + sgAddVec3 ( vvX, plane, vv1 ) ; + sgMakePlane ( planeX, vv1, vv2, vvX ) ; + float dp1 = sgDistToPlaneVec3 ( planeX, s->getCenter() ) ; + + if ( dp1 > s->getRadius() ) + continue ; + + sgAddVec3 ( vvX, plane, vv2 ) ; + sgMakePlane ( planeX, vv2, vv3, vvX ) ; + float dp2 = sgDistToPlaneVec3 ( planeX, s->getCenter() ) ; + + if ( dp2 > s->getRadius() ) + continue ; + + sgAddVec3 ( vvX, plane, vv3 ) ; + sgMakePlane ( planeX, vv3, vv1, vvX ) ; + float dp3 = sgDistToPlaneVec3 ( planeX, s->getCenter() ) ; + + if ( dp3 > s->getRadius() ) + continue ; + + /* + OK, so we now know that the sphere + intersects the plane of the triangle + and is not more than one radius outside + the walls. However, you can still get + close enough to the wall and to the + triangle itself and *still* not + intersect the triangle itself. + + However, if the center is inside the + triangle then we don't need that + costly test. + */ + + if ( dp1 <= 0 && dp2 <= 0 && dp3 <= 0 ) + { + _ssgAddHit ( this, i, m, plane ) ; + continue ; + } + + /* + ...now we really need that costly set of tests... + + If the sphere penetrates the plane of the triangle + and the plane of the wall, then we can use pythagoras + to determine if the sphere actually intersects that + edge between the wall and the triangle. + + if ( dp_sqd + dp1_sqd > radius_sqd ) ...in! else ...out! + */ + + float r2 = s->getRadius() * s->getRadius() - dp * dp ; + + if ( dp1 * dp1 <= r2 || + dp2 * dp2 <= r2 || + dp3 * dp3 <= r2 ) + { + _ssgAddHit ( this, i, m, plane ) ; + continue ; + } + } +} + + +void ssgVTable::print ( FILE *fd, char *indent, int how_much ) +{ + ssgLeaf::print ( fd, indent, how_much ) ; +} + + + +int ssgVTable::load ( FILE *fd ) +{ + sgVec3 temp; + + _ssgReadVec3 ( fd, temp ); bbox.setMin( temp ) ; + _ssgReadVec3 ( fd, temp ); bbox.setMax( temp ) ; + _ssgReadInt ( fd, &indexed ) ; + _ssgReadInt ( fd, (int *)(&gltype) ) ; + + _ssgReadInt ( fd, &num_vertices ) ; + _ssgReadInt ( fd, &num_normals ) ; + _ssgReadInt ( fd, &num_texcoords) ; + _ssgReadInt ( fd, &num_colours ) ; + + int i ; + int max ; + + /* Vertices */ + + if ( indexed ) + { + v_index = new unsigned short [ num_vertices ] ; + _ssgReadUShort ( fd, num_vertices, v_index ) ; + + max = 0 ; + + for ( i = 0 ; i < num_vertices ; i++ ) + if ( v_index [ i ] > max ) max = v_index[i] ; + } + else + max = num_vertices ; + + vertices = new sgVec3 [ max ] ; + _ssgReadFloat ( fd, max * 3, (float *) vertices ) ; + + /* Normals */ + + if ( indexed ) + { + n_index = new unsigned short [ num_normals ] ; + _ssgReadUShort ( fd, num_normals, n_index ) ; + + max = 0 ; + + for ( i = 0 ; i < num_normals ; i++ ) + if ( n_index [ i ] > max ) max = n_index[i] ; + } + else + max = num_normals ; + + normals = new sgVec3 [ max ] ; + _ssgReadFloat ( fd, max * 3, (float *) normals ) ; + + /* Texture Coordinates */ + + if ( indexed ) + { + t_index = new unsigned short [ num_texcoords ] ; + _ssgReadUShort ( fd, num_texcoords, t_index ) ; + + max = 0 ; + + for ( i = 0 ; i < num_texcoords ; i++ ) + if ( t_index [ i ] > max ) max = t_index[i] ; + } + else + max = num_texcoords ; + + texcoords = new sgVec2 [ max ] ; + _ssgReadFloat ( fd, max * 2, (float *) texcoords ) ; + + /* Colours */ + + if ( indexed ) + { + c_index = new unsigned short [ num_colours ] ; + _ssgReadUShort ( fd, num_colours, c_index ) ; + + max = 0 ; + + for ( i = 0 ; i < num_colours ; i++ ) + if ( c_index [ i ] > max ) max = c_index[i] ; + } + else + max = num_colours ; + + colours = new sgVec4 [ max ] ; + _ssgReadFloat ( fd, max * 4, (float *) colours ) ; + + return ssgLeaf::load(fd) ; +} + +int ssgVTable::save ( FILE *fd ) +{ + _ssgWriteVec3 ( fd, bbox.getMin() ) ; + _ssgWriteVec3 ( fd, bbox.getMax() ) ; + _ssgWriteInt ( fd, indexed ) ; + _ssgWriteInt ( fd, (int) gltype ) ; + + _ssgWriteInt ( fd, num_vertices ) ; + _ssgWriteInt ( fd, num_normals ) ; + _ssgWriteInt ( fd, num_texcoords) ; + _ssgWriteInt ( fd, num_colours ) ; + + int i ; + int max ; + + /* Vertices */ + + if ( indexed ) + { + max = 0 ; + + for ( i = 0 ; i < num_vertices ; i++ ) + if ( v_index [ i ] > max ) max = v_index[i] ; + + _ssgWriteUShort ( fd, num_vertices, v_index ) ; + } + else + max = num_vertices ; + + _ssgWriteFloat ( fd, max * 3, (float *)vertices ) ; + + /* Normals */ + + if ( indexed ) + { + max = 0 ; + + for ( i = 0 ; i < num_normals ; i++ ) + if ( n_index [ i ] > max ) max = n_index[i] ; + + _ssgWriteUShort ( fd, num_normals, n_index ) ; + } + else + max = num_normals ; + + _ssgWriteFloat ( fd, max * 3, (float *)normals ) ; + + /* Texture Coordinates */ + + if ( indexed ) + { + max = 0 ; + + for ( i = 0 ; i < num_texcoords ; i++ ) + if ( t_index [ i ] > max ) max = t_index[i] ; + + _ssgWriteUShort ( fd, num_texcoords, t_index ) ; + } + else + max = num_texcoords ; + + _ssgWriteFloat ( fd, max * 2, (float *)texcoords ) ; + + /* Colours */ + + if ( indexed ) + { + max = 0 ; + + for ( i = 0 ; i < num_colours ; i++ ) + if ( c_index [ i ] > max ) max = c_index[i] ; + + _ssgWriteUShort ( fd, num_colours, c_index ) ; + } + else + max = num_colours ; + + _ssgWriteFloat ( fd, max * 4, (float *)colours ) ; + + return ssgLeaf::save(fd) ; +} + + + diff --git a/src/ssg/ssgVertSplitter.cxx b/src/ssg/ssgVertSplitter.cxx new file mode 100644 index 0000000..e23e608 --- /dev/null +++ b/src/ssg/ssgVertSplitter.cxx @@ -0,0 +1,351 @@ +//////////////////////////////////////////////////////////////////////// +// +// Copyright 2003, Andrew Ross +// +// Walk through an indexed triangle list, splitting vertices that +// share "sharp" edges, and calculate normals for the resulting mesh. +// +// This code should really live inside the OptVertexList class in +// ssgOptimizer.cxx, whose data model is almost 1:1 compatible with +// the indexed triangle representation here. It is a separate file +// because it comes from separate code that Andy Ross wrote for a +// different project, and this was the cleanest way to do the port. +// +//////////////////////////////////////////////////////////////////////// + +#include "ssgVertSplitter.h" + +#include +#include "sg.h" + +// +//////////////////////////////////////////////////////////////////////// + +int ssgVertSplitter::origVert(int i) +{ + return _newVertMap[i]; +} + +ssgVertSplitter::ssgVertSplitter(int nVerts, int nTris) +{ + setSharpAngle(61); + _nVerts = _origVerts = _vertsAlloced = nVerts; + _verts = new float[3*_nVerts]; + _norms = new float[3*_nVerts]; + _nTris = nTris; + _tris = new Tri[3*_nTris]; + _triNorms = new float[3*_nTris]; + _geomVerts = new int[_nVerts]; + + _newVertMap = 0; +} + +ssgVertSplitter::~ssgVertSplitter() +{ + delete[] _verts; + delete[] _norms; + delete[] _tris; + delete[] _triNorms; + delete[] _newVertMap; + delete[] _geomVerts; +} + +void ssgVertSplitter::setTri(int tidx, int va, int vb, int vc) +{ + _tris[tidx].verts[0] = _tris[tidx].oVerts[0] = va; + _tris[tidx].verts[1] = _tris[tidx].oVerts[1] = vb; + _tris[tidx].verts[2] = _tris[tidx].oVerts[2] = vc; + _tris[tidx].degenerate = false; +} + +int* ssgVertSplitter::getTri(int t) +{ + return &(_tris[t].verts[0]); +} + +void ssgVertSplitter::setSharpAngle(float deg) +{ + _threshold = (float) cos(deg*SG_DEGREES_TO_RADIANS); +} + +int ssgVertSplitter::findTriWithVert(int fidx, int vidx, int* tris, int ntris) +{ + // check each triangle in the list for a matching edge + for(int t=0; tverts[i] == oldIdx) { + t->verts[i] = newIdx; + return; + } + } +} + +// Find geometrically identical vertices and fixup triangle indices to +// point to the first one. +void ssgVertSplitter::condenseGeometry() +{ + for(int i=0; i<_nVerts; i++) { + _geomVerts[i] = i; + for(int j=0; j= 0) continue; + + // No existing record, make one. + if(!used[sv] && sv >= _origVerts) fv = sv; + else if(!used[ov]) fv = ov; + else { fv = _nVerts++; _nextNewVert++; } + + int r = nvrecs++; + vrecs[r].sv = sv; + vrecs[r].ov = ov; + vrecs[r].fv = fv; + // __builtin_printf("s %d o %d f %d\n", sv, ov, fv); + + sgCopyVec3(vert(fv), vert(sv)); + sgCopyVec3(norm(fv), norm(sv)); + if(fv >= _origVerts) + _newVertMap[fv - _origVerts] = ov; + used[fv] = true; + _tris[i].verts[j] = fv; + } + } + delete[] vrecs; + delete[] used; +} + +void ssgVertSplitter::splitAndCalcNormals() +{ + int i, j; + float zero[] = {0,0,0}; + for(i=0; i<_nVerts; i++) sgCopyVec3(norm(i), zero); + + // First, find duplicate vertices and coalesce the geometry + condenseGeometry(); + + // Calculate a normal for each face, and count the number of + // references to each vertex. + float* faceNorms = _triNorms; + int* vCounts = new int[_nVerts]; + for(i=0; i<_nVerts; i++) + vCounts[i] = 0; + for(i=0; i<_nTris; i++) { + sgVec3 a, b; + float *fnorm = faceNorms + 3*i; + int* verts = _tris[i].verts ; + sgCopyVec3(a, vert(verts[1])); + sgSubVec3(a, vert(verts[0])); + sgCopyVec3(b, vert(verts[2])); + sgSubVec3(b, vert(verts[0])); + sgVectorProductVec3(fnorm, a, b); + sgNormaliseVec3(fnorm); + vCounts[verts[0]]++; + vCounts[verts[1]]++; + vCounts[verts[2]]++; + + if(verts[0]==verts[1] || verts[1]==verts[2] || verts[2]==verts[0]) + { + _tris[i].degenerate = true; + fnorm[0] = fnorm[1] = 0; + fnorm[2] = 1; + } + } + + // Build a table mapping vertices to arrays of triangle indices + // vTris[v] is a pointer to a list of vCounts[v] triangle indices. + int* vtspace = new int[3*_nTris]; + int** vTris = new int*[_nVerts]; + int* vtptr = vtspace; + for(i=0; i<3*_nTris; i++) vtspace[i] = -1; + for(i=0; i<_nVerts; i++) { + vTris[i] = vtptr; + vtptr += vCounts[i]; + } + int *vctmp = new int[_nVerts]; + for(i=0; i<_nVerts; i++) vctmp[i] = 0; + for(i=0; i<_nTris; i++) { + if(_tris[i].degenerate) continue; + for(int v=0; v<3; v++) + vTris[_tris[i].verts[v]][vctmp[_tris[i].verts[v]]++] = i; + } + delete[] vctmp; + + // Make some temp space for new vertices and their normals + int maxNewVerts = 8*_nVerts; + _newVertMap = new int[maxNewVerts]; + float* newNorms = new float[3*maxNewVerts]; + _nextNewVert = 0; + + // Now the hard part. For each vertex, pick a face. Walk forward + // and backwards from that face until you hit a sharp edge or + // already-done face, summing normals along the way and marking + // off the face as "done". If there are faces left, split off a + // *new* vertex for the remaining ones, pick a remaining face, and + // repeat. Repeat until we run out of faces. + for(int vidx=0; vidx<_nVerts; vidx++) { + while(1) { + // Pick a face + int fidx = -1; + bool someDone = false; + for(int face=0; face= 0) { + float* n = faceNorms + 3*vTris[vidx][nextidx]; + if(sgScalarProductVec3(n, lastNorm) < _threshold) break; + lastNorm = n; + sgAddVec3(fnorm, n); + int oldnext = nextidx; + nextidx = nextTri(nextidx, vidx, vTris[vidx], vCounts[vidx]); + if(someDone) + fixVidx(_tris + vTris[vidx][oldnext], vidx, realvert); + vTris[vidx][oldnext] = -1; + } + lastNorm = lastNorm0; + while(previdx >= 0) { + if(vTris[vidx][previdx] < 0) break; + float* n = faceNorms + 3*vTris[vidx][previdx]; + if(sgScalarProductVec3(n, lastNorm) < _threshold) break; + lastNorm = n; + sgAddVec3(fnorm, faceNorms + 3*vTris[vidx][previdx]); + int oldprev = previdx; + previdx = prevTri(previdx, vidx, vTris[vidx], vCounts[vidx]); + if(someDone) + fixVidx(_tris + vTris[vidx][oldprev], vidx, realvert); + vTris[vidx][oldprev] = -1; + } + } + }; + + // Reallocate the new vertex/normal tables. + _vertsAlloced = _nVerts + maxNewVerts; + float* newVerts = new float[3*_vertsAlloced]; + for(i=0; i<3*_nVerts; i++) + newVerts[i] = _verts[i]; + for(i=0; i<_nextNewVert; i++) + for(j=0; j<3; j++) + newVerts[3*(_nVerts+i)+j] = _verts[3*_newVertMap[i]+j]; + delete[] _verts; + _verts = newVerts; + + float* tmpnorms = new float[3*_vertsAlloced]; + for(i=0; i<3*_nVerts; i++) + tmpnorms[i] = _norms[i]; + for(i=0; i<3*_nextNewVert; i++) + tmpnorms[3*_nVerts+i] = newNorms[i]; + delete[] _norms; + _norms = tmpnorms; + + _nVerts += _nextNewVert; + + // Finally, renormalize everything + for(i=0; i<_nVerts; i++) + if(i >= _origVerts || _geomVerts[i] == i) sgNormaliseVec3(norm(i)); + for(i=0; i<_origVerts; i++) + if(_geomVerts[i] != i) sgCopyVec3(norm(i), norm(_geomVerts[i])); + + // Now, if necessary, duplicate the vertices that got "condensed" + // earlier by creating a new vertex and cloning the normal. + expandDuplicates(); + +#if 0 + static int allOrig = 0; + static int allFinal = 0; + allOrig += _origVerts; + allFinal += _nVerts; + fprintf(stderr, "%d -> %d (%d/%d)\n", _origVerts, _nVerts, + allOrig, allFinal); +#endif + + delete[] vCounts; + delete[] vtspace; + delete[] vTris; + delete[] newNorms; +} diff --git a/src/ssg/ssgVertSplitter.h b/src/ssg/ssgVertSplitter.h new file mode 100644 index 0000000..8a99aab --- /dev/null +++ b/src/ssg/ssgVertSplitter.h @@ -0,0 +1,78 @@ +//////////////////////////////////////////////////////////////////////// +// +// Copyright 2003, Andrew Ross +// +// Walk through an indexed triangle list, splitting vertices that +// share "sharp" edges, and calculate normals for the resulting mesh. +// +// This code should really live inside the OptVertexList class in +// ssgOptimizer.cxx, whose data model is almost 1:1 compatible with +// the indexed triangle representation here. It is a separate file +// because it comes from separate code that Andy Ross wrote for a +// different project, and this was the cleanest way to do the port. +// +//////////////////////////////////////////////////////////////////////// + +#ifndef _SSGA_VERTSPLITTER_H +#define _SSGA_VERTSPLITTER_H + +class ssgVertSplitter { +public: + ssgVertSplitter(int nVerts, int nTris); + virtual ~ssgVertSplitter(); + void setSharpAngle(float deg); + + float* vert(int i) { return _verts + 3*i; } + float* norm(int i) { return _norms + 3*i; } + + // Initialize a triangle. The vertex indices might change. + void setTri(int tidx, int va, int vb, int vc); + + // Grab the new/different indices post-split + int* getTri(int t); + + // Number of new vertices (indices start after the original list) + int newVerts() { return _nextNewVert; } + + // Original vertex associated with a given "new" vertex + int origVert(int i); + + void splitAndCalcNormals(); + +private: + struct Tri { + int verts[3]; + int oVerts[3]; + bool degenerate; + }; + + void condenseGeometry(); + void expandDuplicates(); + + int findTriWithVert(int fidx, int vidx, int* tris, int ntris); + int nextTri(int fidx, int vidx, int* tris, int ntris); + int prevTri(int fidx, int vidx, int* tris, int ntris); + static void fixVidx(Tri* t, int oldIdx, int newIdx); + + float _threshold; + + int _origVerts; + int _vertsAlloced; + + int _nVerts; + float* _verts; + float* _norms; + + int _nTris; + Tri* _tris; + float* _triNorms; + + int* _newVertMap; + int _nextNewVert; + + int* _geomVerts; + + void DUMP(); +}; + +#endif // _SSGA_VERTSPLITTER_H diff --git a/src/ssg/ssgVtxArray.cxx b/src/ssg/ssgVtxArray.cxx new file mode 100644 index 0000000..ac61af4 --- /dev/null +++ b/src/ssg/ssgVtxArray.cxx @@ -0,0 +1,433 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgVtxArray.cxx 1992 2004-12-01 08:28:05Z wolfram_kuss $ +*/ + + +#include "ssgLocal.h" + +#define HL_DELTA 0.04f + +void ssgVtxArray::copy_from ( ssgVtxArray *src, int clone_flags ) +{ + ssgVtxTable::copy_from ( src, clone_flags ) ; + + ssgDeRefDelete ( indices ) ; + + if ( src->indices != NULL && ( clone_flags & SSG_CLONE_GEOMETRY ) ) + indices = (ssgIndexArray *)( src -> indices -> clone ( clone_flags )) ; + else + indices = src -> indices ; + + if ( indices != NULL ) + indices -> ref () ; +} + +ssgBase *ssgVtxArray::clone ( int clone_flags ) +{ + ssgVtxArray *b = new ssgVtxArray ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgVtxArray::ssgVtxArray () : ssgVtxTable() +{ + type = ssgTypeVtxArray () ; + indices = NULL ; +} + + +ssgVtxArray::ssgVtxArray ( GLenum ty, + ssgVertexArray *vl, + ssgNormalArray *nl, + ssgTexCoordArray *tl, + ssgColourArray *cl, + ssgIndexArray *il ) : ssgVtxTable( ty, vl, nl, tl, cl ) +{ + type = ssgTypeVtxArray () ; + + indices = (il!=NULL) ? il : new ssgIndexArray () ; + + indices -> ref () ; +} + + +ssgVtxArray::~ssgVtxArray () +{ + ssgDeRefDelete ( indices ) ; +} + + +void ssgVtxArray::setIndices ( ssgIndexArray *il ) +{ + ssgDeRefDelete ( indices ) ; + indices = il ; + + if ( indices != NULL ) + indices -> ref () ; +} + + +void ssgVtxArray::drawHighlight ( sgVec4 colour ) +{ + _ssgForceLineState () ; + + glPushClientAttrib ( GL_CLIENT_VERTEX_ARRAY_BIT ) ; + + glDisableClientState ( GL_COLOR_ARRAY ) ; + glDisableClientState ( GL_NORMAL_ARRAY ) ; + glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ; + glEnableClientState ( GL_VERTEX_ARRAY ) ; + + glVertexPointer ( 3, GL_FLOAT, 0, vertices->get(0) ) ; + + glPushAttrib ( GL_POLYGON_BIT ) ; + glPolygonMode ( GL_FRONT_AND_BACK, GL_LINE ) ; + glColor4fv ( colour ) ; + int i = getNumIndices (); + short *ii = indices->get(0); + glDrawElements ( gltype, i, GL_UNSIGNED_SHORT, ii ) ; + glPopAttrib () ; + glPopClientAttrib () ; + glEnable ( GL_DEPTH_TEST ) ; +} + + +void ssgVtxArray::drawHighlight ( sgVec4 colour, int i ) +{ + _ssgForceLineState () ; + + if ( i < 0 || i >= getNumIndices () ) + return ; + + int ii = *( indices->get(i) ); + sgVec3 *vx = (sgVec3 *) vertices -> get(ii) ; + + float x = vx[0][0] ; + float y = vx[0][1] ; + float z = vx[0][2] ; + + sgVec3 t[6] ; + sgSetVec3 ( t[0], x-HL_DELTA,y,z ) ; + sgSetVec3 ( t[1], x+HL_DELTA,y,z ) ; + sgSetVec3 ( t[2], x,y-HL_DELTA,z ) ; + sgSetVec3 ( t[3], x,y+HL_DELTA,z ) ; + sgSetVec3 ( t[4], x,y,z-HL_DELTA ) ; + sgSetVec3 ( t[5], x,y,z+HL_DELTA ) ; + + glPushClientAttrib ( GL_CLIENT_VERTEX_ARRAY_BIT ) ; + glDisableClientState ( GL_COLOR_ARRAY ) ; + glDisableClientState ( GL_NORMAL_ARRAY ) ; + glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ; + glEnableClientState ( GL_VERTEX_ARRAY ) ; + + glVertexPointer ( 3, GL_FLOAT, 0, t ) ; + glColor4fv ( colour ) ; + glLineWidth ( 4.0f ) ; + glDrawArrays ( GL_LINES, 0, 6 ) ; + glLineWidth ( 1.0f ) ; + glPopClientAttrib ( ) ; + glEnable ( GL_DEPTH_TEST ) ; +} + + + +void ssgVtxArray::pick ( int baseName ) +{ + int i ; + int num_vertices = getNumIndices () ; + + glPushClientAttrib ( GL_CLIENT_VERTEX_ARRAY_BIT ) ; + glEnableClientState ( GL_VERTEX_ARRAY ) ; + glVertexPointer ( 3, GL_FLOAT, 0, vertices->get(0) ) ; + + /* Test the entire primitive. */ + + glPushName ( baseName ) ; + short *ii = indices->get(0); + glDrawElements ( gltype, num_vertices, GL_UNSIGNED_SHORT, ii ) ; + + /* Then test each vertex in turn */ + + for ( i = 0 ; i < num_vertices ; i++ ) + { + int ii = *( indices->get(i) ); + glLoadName ( baseName + i + 1 ) ; + glBegin ( GL_POINTS ) ; + glArrayElement ( ii ) ; + glEnd () ; + } + + glPopName () ; + + glPopClientAttrib ( ) ; +} + +void ssgVtxArray::removeUnusedVertices() +// this removes any vertices (including normal, TexCoords and colour) +// that are not referenced by the index array +{ + + bool doNormals = FALSE, doTexCoords = FALSE, doColours = FALSE; + + assert(vertices); + if(!indices) + { ulSetError( UL_WARNING, "indices == NULL\n"); + return; + } + if(normals) + if(1 < normals->getNum()) + doNormals = TRUE; + if(texcoords) + if(1 < texcoords->getNum()) + doTexCoords = TRUE; + if(colours) + if(1 < colours->getNum()) + doColours = TRUE; + + long * oldIndex2NewIndex = new long[vertices->getNum()]; + int i; + short oldIndex, newIndex; + for(i=0;igetNum();i++) + oldIndex2NewIndex[i]=-1; // marker for "not used" + + ssgVertexArray *newVL= new ssgVertexArray(); + ssgNormalArray *newNL = NULL; + ssgTexCoordArray *newTL = NULL; + ssgColourArray *newCL = NULL; + + if(doNormals) + newNL = new ssgNormalArray(); + if (doTexCoords) + newTL = new ssgTexCoordArray(); + if (doColours) + newCL = new ssgColourArray(); + + for(i=0; igetNum(); i++) + { oldIndex = *indices->get(i); + if (oldIndex2NewIndex[ oldIndex ] != -1) + indices->set(static_cast(oldIndex2NewIndex[ oldIndex ]), i); + else + { newIndex = newVL->getNum(); + indices->set(newIndex , i); + oldIndex2NewIndex[ oldIndex ] = newIndex; + newVL->add(vertices->get(oldIndex)); + if(doNormals) + newNL->add(normals->get(oldIndex)); + if (doTexCoords) + newTL->add(texcoords->get(oldIndex)); + if (doColours) + newCL->add(colours->get(oldIndex)); + } + } + vertices->deRef(); //ssgDeRefDelete(vertices); + vertices = newVL; + newVL->ref(); + + if(doNormals) + { normals->deRef(); //ssgDeRefDelete(normals); + normals = newNL; + newNL->ref(); + + } + if (doTexCoords) + { texcoords->deRef(); //ssgDeRefDelete(texcoords); + texcoords = newTL; + newTL->ref(); + } + if (doColours) + { colours->deRef(); //ssgDeRefDelete(colours); + colours = newCL; + newCL->ref(); + } + delete [] oldIndex2NewIndex; +} + +void ssgVtxArray::draw_geometry () +{ + int num_colours = getNumColours () ; + int num_normals = getNumNormals () ; + int num_texcoords = getNumTexCoords () ; + + sgVec3 *nm = (sgVec3 *) normals -> get(0) ; + sgVec4 *cl = (sgVec4 *) colours -> get(0) ; + + if ( num_colours == 0 ) glColor4f ( 1.0f, 1.0f, 1.0f, 1.0f ) ; + if ( num_colours == 1 ) glColor4fv ( cl [ 0 ] ) ; + if ( num_normals == 1 ) glNormal3fv ( nm [ 0 ] ) ; + + glPushClientAttrib ( GL_CLIENT_VERTEX_ARRAY_BIT ) ; + + if ( num_colours > 1 ) + { + glEnableClientState ( GL_COLOR_ARRAY ) ; + glColorPointer ( 4, GL_FLOAT, 0, colours->get(0) ) ; + } + if ( num_normals > 1 ) + { + glEnableClientState ( GL_NORMAL_ARRAY ) ; + glNormalPointer ( GL_FLOAT, 0, normals->get(0) ) ; + } + if ( num_texcoords > 1 ) + { + glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ; + glTexCoordPointer ( 2, GL_FLOAT, 0, texcoords->get(0) ) ; + } + glEnableClientState ( GL_VERTEX_ARRAY ) ; + glVertexPointer ( 3, GL_FLOAT, 0, vertices->get(0) ) ; + + int i = getNumIndices (); + short *ii = indices->get(0); + + _ssgCurrStatistics . bumpVertexCount ( i ) ; + _ssgCurrStatistics . bumpLeafCount ( 1 ) ; + + glDrawElements ( gltype, i, GL_UNSIGNED_SHORT, ii ) ; + + glPopClientAttrib ( ) ; +} + + +void ssgVtxArray::getTriangle ( int n, short *v1, short *v2, short *v3 ) +{ + short vv1, vv2, vv3 ; + + ssgVtxTable::getTriangle ( n, &vv1, &vv2, &vv3 ) ; + + *v1 = *( indices -> get ( vv1 ) ) ; + *v2 = *( indices -> get ( vv2 ) ) ; + *v3 = *( indices -> get ( vv3 ) ) ; +} + + +int ssgVtxArray::getNumTriangles () +{ + switch ( getPrimitiveType () ) + { + case GL_POLYGON : + case GL_TRIANGLE_FAN : return getNumIndices() - 2 ; + case GL_TRIANGLES : return getNumIndices() / 3 ; + case GL_TRIANGLE_STRIP : return getNumIndices() - 2 ; + case GL_QUADS : return ( getNumIndices() / 4 ) * 2 ; + case GL_QUAD_STRIP : return ( ( getNumIndices() - 2 ) / 2 ) * 2 ; + + default : break ; + } + + return 0 ; +} + +int ssgVtxArray::getNumLines () +{ + switch ( getPrimitiveType () ) + { + case GL_POLYGON : + case GL_TRIANGLE_FAN : + case GL_TRIANGLES : + case GL_TRIANGLE_STRIP : + case GL_QUADS : + case GL_QUAD_STRIP : + case GL_POINTS : return 0 ; + case GL_LINES : return getNumIndices () / 2 ; + case GL_LINE_LOOP : return getNumIndices () ; + case GL_LINE_STRIP : return getNumIndices () - 1 ; + default : break ; + } + assert(false); /* Should never get here */ + return 0 ; +} + +void ssgVtxArray::getLine ( int n, short *v1, short *v2 ) +{ + assert( n>=0 ); + switch ( getPrimitiveType () ) + { + case GL_POLYGON : + case GL_TRIANGLE_FAN : + case GL_TRIANGLES : + case GL_TRIANGLE_STRIP : + case GL_QUADS : + case GL_QUAD_STRIP : + case GL_POINTS : + assert(false); + case GL_LINES : + assert ( 2*n+1 < getNumIndices() ); + *v1 = *getIndex( 2*n ); + *v2 = *getIndex( 2*n+1 ); + return ; + case GL_LINE_LOOP : + assert ( n < getNumIndices() ); + *v1 = *getIndex( n ); + if ( n == getNumIndices()-1 ) + *v2 = *getIndex( 0 ); + else + *v2 = *getIndex( n+1 ); + return ; + case GL_LINE_STRIP : + assert ( n < getNumIndices()-1 ); + *v1 = *getIndex( n ); + *v2 = *getIndex( n+1 ); + return; + default : + break ; + } + assert(false); /* Should never get here */ + return ; +} + + +void ssgVtxArray::print ( FILE *fd, char *indent, int how_much ) +{ + char in [ 100 ] ; + + if ( how_much == 0 ) + return; // dont print anything + + sprintf ( in, "%s ", indent ); + + ssgVtxTable::print ( fd, indent, how_much ) ; + indices -> print ( fd, in, how_much ) ; +} + + +int ssgVtxArray::load ( FILE *fd ) +{ + if ( ! ssgVtxTable::load(fd) || + ! _ssgLoadObject ( fd, (ssgBase **) &indices, ssgTypeIndexArray () ) ) + return FALSE ; + + if ( indices != NULL) + indices -> ref () ; + + return TRUE ; +} + + +int ssgVtxArray::save ( FILE *fd ) +{ + if ( ! ssgVtxTable::save(fd) || + ! _ssgSaveObject ( fd, indices ) ) + return FALSE ; + + return TRUE ; +} + diff --git a/src/ssg/ssgVtxTable.cxx b/src/ssg/ssgVtxTable.cxx new file mode 100644 index 0000000..ba00e87 --- /dev/null +++ b/src/ssg/ssgVtxTable.cxx @@ -0,0 +1,1018 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgVtxTable.cxx 1992 2004-12-01 08:28:05Z wolfram_kuss $ +*/ + + +#include "ssgLocal.h" + +#define HL_DELTA 0.04f + +int ssgSimpleList::compare(ssgSimpleList *other, int print_result) +{ + int result = TRUE; + if (total !=other->total ) + { result = FALSE; + if(print_result) + printf("ERROR: total \n"); + } + else + if(print_result) + printf("Ok: total \n"); + if (size_of !=other->size_of ) + { result = FALSE; + if(print_result) + printf("ERROR: size_of \n"); + } + else + if(print_result) + printf("Ok: size_of \n"); + if (memcmp(list, other->list, total*size_of)) + { result = FALSE; + if(print_result) + printf("ERROR: list \n"); + } + else + if(print_result) + printf("Ok: list \n"); + + return result; +} + + +int ssgVtxTable::compare(ssgVtxTable *other, int print_result) +// returns TRUE, if equal. +// prints stuff to stdout. +{ + int result = TRUE; + if(print_result) + printf("comparing vertices\n"); + if(!vertices->compare(other->vertices, print_result)) + result=FALSE; + if(print_result) + printf("comparing normals\n"); + if(!normals->compare(other->normals, print_result)) + result=FALSE; + if(print_result) + printf("comparing texcoords\n"); + if(!texcoords->compare(other->texcoords, print_result)) + result=FALSE; + if(print_result) + printf("comparing colours \n"); + if(!colours ->compare(other->colours, print_result)) + result=FALSE; + // could be in ssgLeaf: + if(getState () == other->getState ()) + { + if(print_result) + printf("Ok: state\n"); + } + else + if(print_result) + printf("WARNING: state pointers differ. state contents is not investigated\n"); + + if (getNumVertices ()!=other->getNumVertices ()) + { result = FALSE; + if(print_result) + printf("ERROR: getNumVertices ()\n"); + } + else + if(print_result) + printf("Ok: getNumVertices ()\n"); + if (getNumNormals ()!=other->getNumNormals ()) + { result = FALSE; + if(print_result) + printf("ERROR: getNumNormals ()\n"); + } + else + if(print_result) + printf("Ok: getNumNormals ()\n"); + if (getNumColours ()!=other->getNumColours ()) + { result = FALSE; + if(print_result) + printf("ERROR: getNumColours ()\n"); + } + else + if(print_result) + printf("Ok: getNumColours ()\n"); + if (getNumTexCoords ()!=other->getNumTexCoords ()) + { result = FALSE; + if(print_result) + printf("ERROR: getNumTexCoords ()\n"); + } + else + if(print_result) + printf("Ok: getNumTexCoords ()\n"); + // end could be in leaf + return result; +} + +void ssgVtxTable::copy_from ( ssgVtxTable *src, int clone_flags ) +{ + ssgLeaf::copy_from ( src, clone_flags ) ; + + gltype = src -> getPrimitiveType () ; + + if ( src->vertices != NULL && ( clone_flags & SSG_CLONE_GEOMETRY ) ) + vertices = (ssgVertexArray *)( src -> vertices -> clone ( clone_flags )) ; + else + vertices = src -> vertices ; + + if ( src->normals != NULL && ( clone_flags & SSG_CLONE_GEOMETRY ) ) + normals = (ssgNormalArray *)( src -> normals -> clone ( clone_flags )) ; + else + normals = src -> normals ; + + if ( src->texcoords != NULL && ( clone_flags & SSG_CLONE_GEOMETRY ) ) + texcoords = (ssgTexCoordArray *)( src -> texcoords -> clone ( clone_flags )) ; + else + texcoords = src -> texcoords ; + + if ( src->colours != NULL && ( clone_flags & SSG_CLONE_GEOMETRY ) ) + colours = (ssgColourArray *)( src -> colours -> clone ( clone_flags )) ; + else + colours = src -> colours ; + + if ( vertices != NULL ) vertices -> ref () ; + if ( normals != NULL ) normals -> ref () ; + if ( texcoords != NULL ) texcoords -> ref () ; + if ( colours != NULL ) colours -> ref () ; + + recalcBSphere () ; +} + +ssgBase *ssgVtxTable::clone ( int clone_flags ) +{ + ssgVtxTable *b = new ssgVtxTable ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgVtxTable::ssgVtxTable () +{ + type = ssgTypeVtxTable () ; + gltype = GL_POINTS ; + vertices = NULL ; + normals = NULL ; + texcoords = NULL ; + colours = NULL ; +} + + +ssgVtxTable::ssgVtxTable ( GLenum ty, + ssgVertexArray *vl, + ssgNormalArray *nl, + ssgTexCoordArray *tl, + ssgColourArray *cl ) +{ + gltype = ty ; + type = ssgTypeVtxTable () ; + + vertices = (vl!=NULL) ? vl : new ssgVertexArray () ; + normals = (nl!=NULL) ? nl : new ssgNormalArray () ; + texcoords = (tl!=NULL) ? tl : new ssgTexCoordArray () ; + colours = (cl!=NULL) ? cl : new ssgColourArray () ; + + vertices -> ref () ; + normals -> ref () ; + texcoords -> ref () ; + colours -> ref () ; + + recalcBSphere () ; +} + +void ssgVtxTable::setVertices ( ssgVertexArray *vl ) +{ + ssgDeRefDelete ( vertices ) ; + vertices = vl ; + + if ( vertices != NULL ) + vertices -> ref () ; + + recalcBSphere () ; +} + +void ssgVtxTable::setNormals ( ssgNormalArray *nl ) +{ + ssgDeRefDelete ( normals ) ; + normals = nl ; + + if ( normals != NULL ) + normals -> ref () ; +} + +void ssgVtxTable::setTexCoords ( ssgTexCoordArray *tl ) +{ + ssgDeRefDelete ( texcoords ) ; + texcoords = tl ; + + if ( texcoords != NULL ) + texcoords -> ref () ; +} + +void ssgVtxTable::setColours ( ssgColourArray *cl ) +{ + ssgDeRefDelete ( colours ) ; + colours = cl ; + + if ( colours != NULL ) + colours -> ref () ; +} + +ssgVtxTable::~ssgVtxTable () +{ + ssgDeRefDelete ( vertices ) ; + ssgDeRefDelete ( normals ) ; + ssgDeRefDelete ( texcoords ) ; + ssgDeRefDelete ( colours ) ; +} + + +void ssgVtxTable::getTriangle ( int n, short *v1, short *v2, short *v3 ) +{ + switch ( getPrimitiveType () ) + { + case GL_POLYGON : + case GL_TRIANGLE_FAN : + *v1 = 0 ; + *v2 = n+1 ; + *v3 = n+2 ; + return ; + + case GL_TRIANGLES : + *v1 = n*3 ; + *v2 = n*3+1 ; + *v3 = n*3+2 ; + return ; + + case GL_TRIANGLE_STRIP : + case GL_QUAD_STRIP : + if ( n & 1 ) + { + *v3 = n ; + *v2 = n+1 ; + *v1 = n+2 ; + } + else + { + *v1 = n ; + *v2 = n+1 ; + *v3 = n+2 ; + } + return ; + + case GL_QUADS : + *v1 = n*2 + 0 ; + *v2 = n*2 + 1 ; + *v3 = n*2 + 2 - (n&1)*4 ; + return ; + + default : return ; + } +} + + +int ssgVtxTable::getNumTriangles () +{ + switch ( getPrimitiveType () ) + { + case GL_POLYGON : + case GL_TRIANGLE_FAN : + return getNumVertices() - 2 ; + + case GL_TRIANGLES : + return getNumVertices() / 3 ; + + case GL_TRIANGLE_STRIP : + return getNumVertices() - 2 ; + + case GL_QUADS : + return ( getNumVertices() / 4 ) * 2 ; + + case GL_QUAD_STRIP : + return ( ( getNumVertices() - 2 ) / 2 ) * 2 ; + + case GL_POINTS : + case GL_LINES : + case GL_LINE_LOOP : + case GL_LINE_STRIP : + return 0; + default : break ; + } + + return 0 ; /* Should never get here...but you never know! */ +} + +int ssgVtxTable::getNumLines () +{ + switch ( getPrimitiveType () ) + { + case GL_POLYGON : + case GL_TRIANGLE_FAN : + case GL_TRIANGLES : + case GL_TRIANGLE_STRIP : + case GL_QUADS : + case GL_QUAD_STRIP : + case GL_POINTS : + return 0; + case GL_LINES : + // wk: FIXME: check the 3 following formulas. I don't have an OpenGL bokk at hand currently :-( + return getNumVertices()/2; + case GL_LINE_LOOP : + return getNumVertices(); + case GL_LINE_STRIP : + return getNumVertices()-1; + default : break ; + } + assert(false); /* Should never get here */ + return 0 ; +} + +void ssgVtxTable::getLine ( int n, short *v1, short *v2 ) +{ + assert( n>=0 ); + switch ( getPrimitiveType () ) + { + case GL_POLYGON : + case GL_TRIANGLE_FAN : + case GL_TRIANGLES : + case GL_TRIANGLE_STRIP : + case GL_QUADS : + case GL_QUAD_STRIP : + case GL_POINTS : + assert(false); + case GL_LINES : + // wk: FIXME: check the 3 following formulas. I don't have an OpenGL bokk at hand currently :-( + assert ( 2*n+1 < getNumVertices() ); + *v1 = 2*n; + *v2 = 2*n+1 ; + return ; + case GL_LINE_LOOP : + assert ( n < getNumVertices() ); + *v1 = n; + if ( n == getNumVertices()-1 ) + *v2 = 0; + else + *v2 = n+1; + return ; + case GL_LINE_STRIP : + assert ( n < getNumVertices()-1 ); + *v1 = n; + *v2 = n+1; + return; + default : + break ; + } + assert(false); /* Should never get here */ + return ; +} + + +void ssgVtxTable::transform ( const sgMat4 m ) +{ + int i ; + int flags = sgClassifyMat4 ( m ) ; + + if ( flags == 0 ) + return ; + + + if ( ( flags & SG_PROJECTION ) ) + ulSetError ( UL_WARNING, "ssgVtxTable: Projection matrices currently not supported." ) ; + /* + note: it is possible to handle projections, but for each normal we would + have to know the corresponding vertex coordinates. setting: + n[3] = dot(v, n) / v[3] + and then transforming with the full 4x4 transposed inverse matrix would do it. + see the OpenGL spec. + */ + + + int num_vertices = getNumVertices () ; + int num_normals = getNumNormals () ; + for ( i = 0 ; i < num_vertices ; i++ ) + sgXformPnt3 ( vertices->get(i), vertices->get(i), m ) ; + + + + + if ( ( flags & ( SG_SCALE | SG_MIRROR | SG_NONORTHO ) ) ) + { + sgMat4 w ; + if ( ( flags & SG_NONORTHO ) ) + { + // use the transposed adjoint matrix (only the upper 3x3 is needed) + sgVectorProductVec3 ( w[0], m[1], m[2] ) ; + sgVectorProductVec3 ( w[1], m[2], m[0] ) ; + sgVectorProductVec3 ( w[2], m[0], m[1] ) ; + } + else + { + SGfloat scale = SG_ONE ; + + if ( ( flags & SG_SCALE ) ) + { + // prescale matrix to avoid renormalisation + scale = scale / sgLengthVec3 ( m[0] ) ; + } + + if ( ( flags & SG_MIRROR ) ) + { + // negate to keep normals consistent with triangle orientations + scale = - scale ; + } + + sgScaleVec3 ( w[0], m[0], scale ) ; + sgScaleVec3 ( w[1], m[1], scale ) ; + sgScaleVec3 ( w[2], m[2], scale ) ; + } + + for ( i = 0 ; i < num_normals ; i++ ) + sgXformVec3 ( normals->get(i), normals->get(i), w ) ; + } + else + for ( i = 0 ; i < num_normals ; i++ ) + sgXformVec3 ( normals->get(i), normals->get(i), m ) ; + + + if ( ( flags & SG_NONORTHO ) ) + { + for ( i = 0 ; i < num_normals ; i++ ) + sgNormaliseVec3 ( normals->get(i) ) ; + } + + + recalcBSphere () ; +} + + +void ssgVtxTable::recalcBSphere () +{ + emptyBSphere () ; + bbox . empty () ; + + int num_vertices = getNumVertices () ; + for ( int i = 0 ; i < num_vertices ; i++ ) + bbox . extend ( vertices->get(i) ) ; + + extendBSphere ( & bbox ) ; + dirtyBSphere () ; /* Cause parents to redo their bspheres */ + bsphere_is_invalid = FALSE ; +} + + +void ssgVtxTable::drawHighlight ( sgVec4 colour ) +{ + _ssgForceLineState () ; + + int i ; + int num_vertices = getNumVertices () ; + + sgVec3 *vx = (sgVec3 *) vertices -> get(0) ; + + glPushAttrib ( GL_POLYGON_BIT ) ; + glPolygonMode ( GL_FRONT_AND_BACK, GL_LINE ) ; + glColor4fv ( colour ) ; + glBegin ( gltype ) ; + for ( i = 0 ; i < num_vertices ; i++ ) + glVertex3fv ( vx [ i ] ) ; + glEnd () ; + glPopAttrib () ; + glEnable ( GL_DEPTH_TEST ) ; +} + + +void ssgVtxTable::drawHighlight ( sgVec4 colour, int v ) +{ + _ssgForceLineState () ; + + int num_vertices = getNumVertices () ; + + if ( v < 0 || v >= num_vertices ) + return ; + + sgVec3 *vx = (sgVec3 *) vertices -> get(v) ; + + float x = vx[0][0] ; + float y = vx[0][1] ; + float z = vx[0][2] ; + + sgVec3 t[6] ; + sgSetVec3 ( t[0], x-HL_DELTA,y,z ) ; + sgSetVec3 ( t[1], x+HL_DELTA,y,z ) ; + sgSetVec3 ( t[2], x,y-HL_DELTA,z ) ; + sgSetVec3 ( t[3], x,y+HL_DELTA,z ) ; + sgSetVec3 ( t[4], x,y,z-HL_DELTA ) ; + sgSetVec3 ( t[5], x,y,z+HL_DELTA ) ; + glColor4fv ( colour ) ; + glLineWidth ( 4.0f ) ; + glBegin ( GL_LINES ) ; + glVertex3fv ( t[0] ) ; + glVertex3fv ( t[1] ) ; + glVertex3fv ( t[2] ) ; + glVertex3fv ( t[3] ) ; + glVertex3fv ( t[4] ) ; + glVertex3fv ( t[5] ) ; + glEnd () ; + glLineWidth ( 1.0f ) ; + glEnable ( GL_DEPTH_TEST ) ; +} + + +void ssgVtxTable::draw () +{ + if ( ! preDraw () ) + return ; + + if ( _ssgCurrentContext-> stateOverridden () ) + _ssgCurrentContext -> overriddenState () -> apply () ; + else + if ( hasState () ) + getState () -> apply () ; + + stats_num_leaves++ ; + stats_num_vertices += getNumVertices() ; + +#ifdef _SSG_USE_DLIST + if ( dlist ) + glCallList ( dlist ) ; + else +#endif + draw_geometry () ; + + if ( postDrawCB != NULL ) + (*postDrawCB)(this) ; +} + + +void ssgVtxTable::pick ( int baseName ) +{ + int i ; + int num_vertices = getNumVertices () ; + + sgVec3 *vx = (sgVec3 *) vertices -> get(0) ; + + /* Test the entire primitive. */ + + glPushName ( baseName ) ; + glBegin ( gltype ) ; + + for ( i = 0 ; i < num_vertices ; i++ ) + glVertex3fv ( vx [ i ] ) ; + + glEnd () ; + + /* Then test each vertex in turn */ + + for ( i = 0 ; i < num_vertices ; i++ ) + { + glLoadName ( baseName + i + 1 ) ; + glBegin ( GL_POINTS ) ; + glVertex3fv ( vx [ i ] ) ; + glEnd () ; + } + + glPopName () ; +} + + +void ssgVtxTable::draw_geometry () +{ + int num_vertices = getNumVertices () ; + int num_colours = getNumColours () ; + int num_normals = getNumNormals () ; + int num_texcoords = getNumTexCoords () ; + + if ( num_colours == 0 ) glColor4f ( 1.0f, 1.0f, 1.0f, 1.0f ) ; + if ( num_colours == 1 ) glColor4fv ( colours -> get(0) ) ; + if ( num_normals == 1 ) glNormal3fv ( normals -> get(0) ) ; + + glPushClientAttrib ( GL_CLIENT_VERTEX_ARRAY_BIT ) ; + + if ( num_colours > 1 ) + { + glEnableClientState ( GL_COLOR_ARRAY ) ; + glColorPointer ( 4, GL_FLOAT, 0, colours->get(0) ) ; + } + + if ( num_normals > 1 ) + { + glEnableClientState ( GL_NORMAL_ARRAY ) ; + glNormalPointer ( GL_FLOAT, 0, normals->get(0) ) ; + } + + if ( num_texcoords > 1 ) + { + glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ; + glTexCoordPointer ( 2, GL_FLOAT, 0, texcoords->get(0) ) ; + } + + glEnableClientState ( GL_VERTEX_ARRAY ) ; + glVertexPointer ( 3, GL_FLOAT, 0, vertices->get(0) ) ; + + _ssgCurrStatistics . bumpVertexCount ( num_vertices ) ; + _ssgCurrStatistics . bumpLeafCount ( 1 ) ; + + glDrawArrays ( gltype, 0, num_vertices ) ; + + glPopClientAttrib () ; +} + + + +void ssgVtxTable::hot_triangles ( sgVec3 s, sgMat4 m, int /* test_needed */ ) +{ + int nt = getNumTriangles () ; + + stats_hot_triangles += nt ; + + for ( int i = 0 ; i < nt ; i++ ) + { + short v1, v2, v3 ; + sgVec3 vv1, vv2, vv3 ; + sgVec4 plane ; + + if ( _ssgBackFaceCollisions ) + getTriangle ( i, &v1, &v3, &v2 ) ; + else + getTriangle ( i, &v1, &v2, &v3 ) ; + + sgXformPnt3 ( vv1, getVertex(v1), m ) ; + sgXformPnt3 ( vv2, getVertex(v2), m ) ; + sgXformPnt3 ( vv3, getVertex(v3), m ) ; + + /* + Does the X/Y coordinate lie outside the triangle's bbox, or + does the Z coordinate lie beneath the bbox ? + */ + + if ( ( s[0] < vv1[0] && s[0] < vv2[0] && s[0] < vv3[0] ) || + ( s[1] < vv1[1] && s[1] < vv2[1] && s[1] < vv3[1] ) || + ( s[0] > vv1[0] && s[0] > vv2[0] && s[0] > vv3[0] ) || + ( s[1] > vv1[1] && s[1] > vv2[1] && s[1] > vv3[1] ) || + ( s[2] < vv1[2] && s[2] < vv2[2] && s[2] < vv3[2] ) ) + continue ; + + sgMakePlane ( plane, vv1, vv2, vv3 ) ; + + if ( _ssgIsHotTest ) + { + /* No HOT from upside-down or vertical triangles */ + + if ( getCullFace() && plane [ 2 ] <= 0 ) + continue ; + + /* Find the point vertically below the text point + as it crosses the plane of the polygon */ + + float z = sgHeightOfPlaneVec2 ( plane, s ) ; + + /* No HOT from below the triangle */ + + if ( z > s[2] ) + continue ; + + /* Outside the vertical extent of the triangle? */ + + if ( ( z < vv1[2] && z < vv2[2] && z < vv3[2] ) || + ( z > vv1[2] && z > vv2[2] && z > vv3[2] ) ) + continue ; + } + + /* + Now it gets messy - the isect point is inside + the bbox of the triangle - but that's not enough. + Is it inside the triangle itself? + */ + + float e1 = s [0] * vv1[1] - s [1] * vv1[0] ; + float e2 = s [0] * vv2[1] - s [1] * vv2[0] ; + float e3 = s [0] * vv3[1] - s [1] * vv3[0] ; + float ep1 = vv1[0] * vv2[1] - vv1[1] * vv2[0] ; + float ep2 = vv2[0] * vv3[1] - vv2[1] * vv3[0] ; + float ep3 = vv3[0] * vv1[1] - vv3[1] * vv1[0] ; + + float ap = (float) fabs ( ep1 + ep2 + ep3 ) ; + float ai = (float) ( fabs ( e1 + ep1 - e2 ) + + fabs ( e2 + ep2 - e3 ) + + fabs ( e3 + ep3 - e1 ) ) ; + + if ( ai > ap * 1.01 ) + continue ; + + _ssgAddHit ( this, i, m, plane ) ; + } +} + +void ssgVtxTable::los_triangles ( sgVec3 s, sgMat4 m, int /* test_needed */ ) +{ + int nt = getNumTriangles () ; + + stats_los_triangles += nt ; + + for ( int i = 0 ; i < nt ; i++ ) + { + short v1, v2, v3 ; + sgVec3 vv1, vv2, vv3 ; + sgVec4 plane ; + + SGfloat edge1[3], edge2[3], tvec[3], pvec[3], qvec[3]; + SGfloat det,inv_det; + SGfloat /*t,*/u,v; + + if ( _ssgBackFaceCollisions ) + getTriangle ( i, &v1, &v3, &v2 ) ; + else + getTriangle ( i, &v1, &v2, &v3 ) ; + + sgXformPnt3 ( vv1, getVertex(v1), m ) ; + sgXformPnt3 ( vv2, getVertex(v2), m ) ; + sgXformPnt3 ( vv3, getVertex(v3), m ) ; + sgVec3 cam; + cam[0] = m[0][3]; + cam[1] = m[1][3]; + cam[2] = m[2][3]; + //if ( _ssgIsLosTest ) + //{ + + /* find vectors for two edges sharing vert0 */ + sgSubVec3(edge1, vv2, vv1); + sgSubVec3(edge2, vv3, vv1); + + /* begin calculating determinant - also used to calculate U parameter */ + sgVectorProductVec3(pvec, s, edge2); + + /* if determinant is near zero, ray lies in plane of triangle */ + det = sgScalarProductVec3(edge1, pvec); + + if (det > -0.0000001 && det < 0.0000001) continue; + inv_det = (float)1.0 / det; + + /* calculate distance from vert0 to ray origin */ + sgSubVec3(tvec, cam, vv1); + + /* calculate U parameter and test bounds */ + u = sgScalarProductVec3(tvec, pvec) * inv_det; + if (u < 0.0 || u > 1.0) + continue; + + /* prepare to test V parameter */ + sgVectorProductVec3(qvec, tvec, edge1); + + /* calculate V parameter and test bounds */ + v = sgScalarProductVec3(s, qvec) * inv_det; + if (v < 0.0 || u + v > 1.0) + continue; + + /* calculate t, ray intersects triangle */ + //t = sgScalarProductVec3(edge2, qvec) * inv_det; + //} + + sgMakePlane ( plane, vv1, vv2, vv3 ) ; + _ssgAddHit ( this, i, m, plane ) ; + } +} + + +ssgVtxArray *ssgVtxTable::getAs_ssgVtxArray() +{ + + ssgIndexArray *indices = new ssgIndexArray (); + int i, no = 0; + switch ( getPrimitiveType () ) + { + case GL_POLYGON : + case GL_TRIANGLE_FAN : + case GL_TRIANGLE_STRIP : + no = getNumTriangles() + 2 ; + break; + + case GL_TRIANGLES : + no = getNumTriangles() * 3 ; + } + for(i=0;iadd(i); + + + ssgState * state = getState(); + char * name = getName(); + ssgVtxArray * s = new ssgVtxArray ( getGLtype(), + vertices, normals, texcoords, colours, indices); + s->setName(name); + s->setState(state); + return s; +} + + +void ssgVtxTable::isect_triangles ( sgSphere *s, sgMat4 m, int test_needed ) +{ + int nt = getNumTriangles () ; + + stats_isect_triangles += nt ; + + for ( int i = 0 ; i < nt ; i++ ) + { + short v1, v2, v3 ; + sgVec3 vv1, vv2, vv3 ; + sgVec4 plane ; + + if ( _ssgBackFaceCollisions ) + getTriangle ( i, &v1, &v3, &v2 ) ; + else + getTriangle ( i, &v1, &v2, &v3 ) ; + + sgXformPnt3 ( vv1, getVertex(v1), m ) ; + sgXformPnt3 ( vv2, getVertex(v2), m ) ; + sgXformPnt3 ( vv3, getVertex(v3), m ) ; + + sgMakePlane ( plane, vv1, vv2, vv3 ) ; + + if ( ! test_needed ) + { + _ssgAddHit ( this, i, m, plane ) ; + continue ; + } + + float dp = (float) fabs ( sgDistToPlaneVec3 ( plane, s->getCenter() ) ) ; + + if ( dp > s->getRadius() ) + continue ; + + /* + The BSphere touches the plane containing + the triangle - but does it actually touch + the triangle itself? Let's erect some + vertical walls around the triangle. + */ + + /* + Construct a 'wall' as a plane through + two vertices and a third vertex made + by adding the surface normal to the + first of those two vertices. + */ + + sgVec3 vvX ; + sgVec4 planeX ; + + sgAddVec3 ( vvX, plane, vv1 ) ; + sgMakePlane ( planeX, vv1, vv2, vvX ) ; + float dp1 = sgDistToPlaneVec3 ( planeX, s->getCenter() ) ; + + if ( dp1 > s->getRadius() ) + continue ; + + sgAddVec3 ( vvX, plane, vv2 ) ; + sgMakePlane ( planeX, vv2, vv3, vvX ) ; + float dp2 = sgDistToPlaneVec3 ( planeX, s->getCenter() ) ; + + if ( dp2 > s->getRadius() ) + continue ; + + sgAddVec3 ( vvX, plane, vv3 ) ; + sgMakePlane ( planeX, vv3, vv1, vvX ) ; + float dp3 = sgDistToPlaneVec3 ( planeX, s->getCenter() ) ; + + if ( dp3 > s->getRadius() ) + continue ; + + /* + OK, so we now know that the sphere + intersects the plane of the triangle + and is not more than one radius outside + the walls. However, you can still get + close enough to the wall and to the + triangle itself and *still* not + intersect the triangle itself. + + However, if the center is inside the + triangle then we don't need that + costly test. + */ + + if ( dp1 <= 0 && dp2 <= 0 && dp3 <= 0 ) + { + _ssgAddHit ( this, i, m, plane ) ; + continue ; + } + + /* + ...now we really need that costly set of tests... + + If the sphere penetrates the plane of the triangle + and the plane of the wall, then we can use pythagoras + to determine if the sphere actually intersects that + edge between the wall and the triangle. + + if ( dp_sqd + dp1_sqd > radius_sqd ) ...in! else ...out! + */ + + float r2 = s->getRadius() * s->getRadius() - dp * dp ; + + if ( dp1 * dp1 <= r2 || + dp2 * dp2 <= r2 || + dp3 * dp3 <= r2 ) + { + _ssgAddHit ( this, i, m, plane ) ; + continue ; + } + } +} + + +void ssgVtxTable::print ( FILE *fd, char *indent, int how_much ) +{ + char in [ 100 ] ; + + if ( how_much == 0 ) + return ; + + sprintf ( in, "%s ", indent ); + + ssgLeaf ::print ( fd, indent, how_much ) ; + + if ( vertices == NULL ) + fprintf ( fd, "%s No Vertices!\n", indent ) ; + else + vertices -> print ( fd, in, how_much ) ; + + if ( normals == NULL ) + fprintf ( fd, "%s No Normals!\n", indent ) ; + else + normals -> print ( fd, in, how_much ) ; + + if ( texcoords == NULL ) + fprintf ( fd, "%s No Texcoords!\n", indent ) ; + else + texcoords -> print ( fd, in, how_much ) ; + + if ( colours == NULL ) + fprintf ( fd, "%s No Colours!\n", indent ) ; + else + colours -> print ( fd, in, how_much ) ; +} + + + +int ssgVtxTable::load ( FILE *fd ) +{ + sgVec3 temp; + + _ssgReadVec3 ( fd, temp ); bbox.setMin( temp ) ; + _ssgReadVec3 ( fd, temp ); bbox.setMax( temp ) ; + _ssgReadInt ( fd, (int *)(&gltype) ) ; + + if ( ! ssgLeaf::load(fd) ) + return FALSE ; + + if ( ! _ssgLoadObject ( fd, (ssgBase **)&vertices, ssgTypeVertexArray () ) || + ! _ssgLoadObject ( fd, (ssgBase **)&normals, ssgTypeNormalArray () ) || + ! _ssgLoadObject ( fd, (ssgBase **)&texcoords, ssgTypeTexCoordArray () ) || + ! _ssgLoadObject ( fd, (ssgBase **)&colours, ssgTypeColourArray () ) ) + return FALSE ; + + if ( vertices != NULL ) vertices -> ref () ; + if ( normals != NULL ) normals -> ref () ; + if ( texcoords != NULL ) texcoords -> ref () ; + if ( colours != NULL ) colours -> ref () ; + + return TRUE ; +} + + +int ssgVtxTable::save ( FILE *fd ) +{ + _ssgWriteVec3 ( fd, bbox.getMin() ) ; + _ssgWriteVec3 ( fd, bbox.getMax() ) ; + _ssgWriteInt ( fd, (int) gltype ) ; + + if ( ! ssgLeaf::save(fd) ) + return FALSE ; + + if ( ! _ssgSaveObject ( fd, vertices ) || + ! _ssgSaveObject ( fd, normals ) || + ! _ssgSaveObject ( fd, texcoords ) || + ! _ssgSaveObject ( fd, colours ) ) + return FALSE ; + + return TRUE ; +} diff --git a/src/ssg/ssgconf.h b/src/ssg/ssgconf.h new file mode 100644 index 0000000..11b3cf0 --- /dev/null +++ b/src/ssg/ssgconf.h @@ -0,0 +1,55 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgconf.h 1959 2004-09-14 12:19:05Z wolfram_kuss $ +*/ + +#ifndef _INCLUDED_SSGCONF_H_ +#define _INCLUDED_SSGCONF_H_ + +/* ssgconf.h - machine configurable file for libssg */ + +#define _SSG_USE_DLIST 1 + +/* The following defines give you the ability to remove code from the + * library that you will not be using. I wish I could figure out how to + * automate this, but I can't do that without making it seriously hard + * on the users. So if you are not using an ability, change the #define + * to an #undef, and that part of the library will not be compiled. If + * your linker can't find a function, you may want to make sure the + * ability is defined here. + */ + +/* + For optional use of PNG textures, download the glpng library from + http://www.wyatt100.freeserve.co.uk/download.htm and + change the #undef to a #define in the following line. + */ + +#undef SSG_LOAD_PNG_SUPPORTED + +#define SSG_LOAD_SGI_SUPPORTED +#define SSG_LOAD_TGA_SUPPORTED +#define SSG_LOAD_BMP_SUPPORTED +#define SSG_LOAD_MDL_SUPPORTED +#define SSG_LOAD_MDL_BGL_TEXTURE_SUPPORTED +#define SSG_LOAD_XPL_SUPPORTED +#define SSG_LOAD_PCX_SUPPORTED +#endif diff --git a/src/ssgAux/Makefile.am b/src/ssgAux/Makefile.am new file mode 100644 index 0000000..0d42cac --- /dev/null +++ b/src/ssgAux/Makefile.am @@ -0,0 +1,41 @@ +if BUILD_SSGAUX + +lib_LIBRARIES = libplibssgaux.a + +include_HEADERS = ssgAux.h \ + ssgaShapes.h \ + ssgaLensFlare.h \ + ssgaParticleSystem.h \ + ssgaWaveSystem.h \ + ssgaScreenDump.h \ + ssgaSky.h \ + ssgaSphere.h \ + ssgaFire.h \ + ssgaBillboards.h + +libplibssgaux_a_SOURCES = ssgAux.cxx \ + ssgaShapes.cxx \ + ssgaPatch.cxx \ + ssgaParticleSystem.cxx \ + ssgaWaveSystem.cxx \ + ssgaLensFlare.cxx \ + ssgaLensFlareTexture.cxx \ + ssgaFire.cxx \ + ssgaScreenDump.cxx \ + ssgaSphere.cxx \ + ssgaCelestialBody.cxx \ + ssgaCloudLayer.cxx \ + ssgaStars.cxx \ + ssgaSkyDome.cxx \ + ssgaSky.cxx \ + ssgaTeapot.cxx \ + ssgaBillboards.cxx + +INCLUDES = -I$(top_srcdir)/src/sg -I$(top_srcdir)/src/ssg +INCLUDES += -I$(top_srcdir)/src/util + +endif + +EXTRA_DIST = ssgAux.dsp + + diff --git a/src/ssgAux/ssgAux.cxx b/src/ssgAux/ssgAux.cxx new file mode 100644 index 0000000..2d20796 --- /dev/null +++ b/src/ssgAux/ssgAux.cxx @@ -0,0 +1,36 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgAux.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "ssgAux.h" + +static ssgBase *createCube () { return new ssgaCube ( 0 ) ; } +static ssgBase *createSphere () { return new ssgaSphere ( 0 ) ; } +static ssgBase *createCylinder () { return new ssgaCylinder ( 0 ) ; } + +void ssgaInit () +{ + ssgRegisterType ( ssgaTypeCube () , createCube ) ; + ssgRegisterType ( ssgaTypeSphere () , createSphere ) ; + ssgRegisterType ( ssgaTypeCylinder () , createCylinder ) ; +} diff --git a/src/ssgAux/ssgAux.dsp b/src/ssgAux/ssgAux.dsp new file mode 100644 index 0000000..156ea88 --- /dev/null +++ b/src/ssgAux/ssgAux.dsp @@ -0,0 +1,205 @@ +# Microsoft Developer Studio Project File - Name="ssgAux" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=ssgAux - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ssgAux.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ssgAux.mak" CFG="ssgAux - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ssgAux - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "ssgAux - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ssgAux - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "..\sg" /I "..\util" /I "..\ssg" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy release\*.lib ..\..\*.* copy ssgAux.h ..\..\ssgAux.h copy ssgaFire.h ..\..\ssgaFire.h copy ssgaLensFlare.h ..\..\ssgaLensFlare.h copy ssgaParticleSystem.h ..\..\ssgaParticleSystem.h copy ssgaShapes.h ..\..\ssgaShapes.h copy ssgaWaveSystem.h ..\..\ssgaWaveSystem.h copy ssgaSky.h ..\..\ssgaSky.h copy ssgaScreenDump.h ..\..\ssgaScreenDump.h +# End Special Build Tool + +!ELSEIF "$(CFG)" == "ssgAux - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I "..\sg" /I "..\util" /I "..\ssg" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\ssgAux_d.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy debug\*.lib ..\..\*.* copy ssgAux.h ..\..\ssgAux.h copy ssgaFire.h ..\..\ssgaFire.h copy ssgaLensFlare.h ..\..\ssgaLensFlare.h copy ssgaParticleSystem.h ..\..\ssgaParticleSystem.h copy ssgaShapes.h ..\..\ssgaShapes.h copy ssgaWaveSystem.h ..\..\ssgaWaveSystem.h copy ssgaSky.h ..\..\ssgaSky.h copy ssgaScreenDump.h ..\..\ssgaScreenDump.h + +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "ssgAux - Win32 Release" +# Name "ssgAux - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\ssgaCelestialBody.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgaCloudLayer.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgaFire.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgaLensFlare.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgaLensFlareTexture.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgaParticleSystem.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgaPatch.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgaScreenDump.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgaShapes.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgaSky.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgaSkyDome.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgaSphere.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgaStars.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgaTeapot.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgAux.cxx +# End Source File +# Begin Source File + +SOURCE=.\ssgaWaveSystem.cxx +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\ssgaFire.h +# End Source File +# Begin Source File + +SOURCE=.\ssgaLensFlare.h +# End Source File +# Begin Source File + +SOURCE=.\ssgaParticleSystem.h +# End Source File +# Begin Source File + +SOURCE=.\ssgaScreenDump.h +# End Source File +# Begin Source File + +SOURCE=.\ssgaShapes.h +# End Source File +# Begin Source File + +SOURCE=.\ssgaSky.h +# End Source File +# Begin Source File + +SOURCE=.\ssgaSphere.h +# End Source File +# Begin Source File + +SOURCE=.\ssgAux.h +# End Source File +# Begin Source File + +SOURCE=.\ssgaWaveSystem.h +# End Source File +# End Group +# End Target +# End Project diff --git a/src/ssgAux/ssgAux.h b/src/ssgAux/ssgAux.h new file mode 100644 index 0000000..4292b6a --- /dev/null +++ b/src/ssgAux/ssgAux.h @@ -0,0 +1,63 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgAux.h 1772 2003-06-27 08:15:15Z sjbaker $ +*/ + + +#ifndef _SSGAUX_H_ +#define _SSGAUX_H_ 1 + +#include "ssg.h" +#include "ssgaShapes.h" +#include "ssgaParticleSystem.h" +#include "ssgaFire.h" +#include "ssgaWaveSystem.h" +#include "ssgaLensFlare.h" +#include "ssgaScreenDump.h" + + +#define _SSGA_TYPE_SHAPE 0x00008000 +#define _SSGA_TYPE_CUBE 0x00004000 +#define _SSGA_TYPE_SPHERE 0x00002000 +#define _SSGA_TYPE_CYLINDER 0x00001000 +#define _SSGA_TYPE_PATCH 0x00010000 +#define _SSGA_TYPE_TEAPOT 0x00020000 +#define _SSGA_TYPE_PARTICLESYSTEM 0x00040000 +#define _SSGA_TYPE_WAVESYSTEM 0x00080000 +#define _SSGA_TYPE_LENSFLARE 0x00100000 + +inline int ssgaTypeShape () { return _SSGA_TYPE_SHAPE | ssgTypeBranch ();} +inline int ssgaTypeCube () { return _SSGA_TYPE_CUBE | ssgaTypeShape ();} +inline int ssgaTypeSphere () { return _SSGA_TYPE_SPHERE | ssgaTypeShape ();} +inline int ssgaTypeCylinder() { return _SSGA_TYPE_CYLINDER | ssgaTypeShape ();} +inline int ssgaTypePatch () { return _SSGA_TYPE_PATCH | ssgaTypeShape ();} +inline int ssgaTypeTeapot () { return _SSGA_TYPE_TEAPOT | ssgaTypeShape ();} +inline int ssgaTypeParticleSystem () + { return _SSGA_TYPE_PARTICLESYSTEM | ssgaTypeShape ();} +inline int ssgaTypeWaveSystem () + { return _SSGA_TYPE_WAVESYSTEM | ssgaTypeShape ();} +inline int ssgaTypeLensFlare () + { return _SSGA_TYPE_LENSFLARE | ssgaTypeShape ();} + +void ssgaInit () ; + +#endif + diff --git a/src/ssgAux/ssgaBillboards.cxx b/src/ssgAux/ssgaBillboards.cxx new file mode 100644 index 0000000..14b2d4a --- /dev/null +++ b/src/ssgAux/ssgaBillboards.cxx @@ -0,0 +1,405 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgaBillboards.cxx 1878 2004-02-25 15:39:34Z sjbaker $ +*/ + + +#include +#include "ssgaBillboards.h" + + +int ssgaBillboards::total_drawn = 0; + + +inline float max3f(const float v[3]) +{ + float tmp = v[0] >= v[1] ? v[0] : v[1]; + return tmp >= v[2] ? tmp : v[2]; +} + + +inline double random_value() +{ +#ifdef UL_WIN32 + return (double) rand() / RAND_MAX; +#else + return drand48(); +#endif +} + + + +ssgaBillboards::ssgaBillboards() + : array(16) +{ + sgSetVec3(up, 0, 0, 1); + + width = 1; + height = 1; + clip_dist = -1; + fade_dist = -1; + near_dist = -1; + draw_num = -1; + fade_num = -1; + alpha_ref = 0.1f; + + ssgSimpleState *ss = new ssgSimpleState; + ss->disable(GL_LIGHTING); + ss->disable(GL_BLEND); + ss->enable(GL_ALPHA_TEST); + ss->enable(GL_TEXTURE_2D); + setState(ss); +} + + + +ssgaBillboards::~ssgaBillboards() +{ +} + + + +void ssgaBillboards::recalcBSphere() +{ + int i; + sgBox box; + box.empty(); + for (i = 0; i < getNum(); i++) + box.extend(get(i)); + sgAddVec3(bsphere.center, box.min, box.max); + sgScaleVec3(bsphere.center, 0.5f); + sgSubVec3(box.max, box.min); + bsphere.radius = 0.5f * max3f(box.max); + for (i = 0; i < getNum(); i++) { + sgSphere sph; + sgCopyVec3(sph.center, get(i)); + float s = get(i)[3]; + sph.radius = 0.5f * s * width; + bsphere.extend(&sph); + sgAddScaledVec3(sph.center, up, s * height); + bsphere.extend(&sph); + } + bsphere_is_invalid = 0; +} + + +// static +void ssgaBillboards::initTexAlpha(GLuint texture, float athres) +{ + const GLenum format[] = { GL_NONE, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA }; + + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glBindTexture(GL_TEXTURE_2D, texture); + + for (int level = 0;; level++) { + GLint width = 0, height = 0, red = 0, alpha = 0; + int icomp, ocomp; + + glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, &width ); + glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_HEIGHT, &height); + glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_RED_SIZE, &red ); + glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_ALPHA_SIZE, &alpha ); + + if (width <= 0 || height <= 0) + break; + + if (red > 0) { + icomp = 3 + (alpha > 0); + ocomp = 4; + } else { + icomp = 1 + (alpha > 0); + ocomp = 2; + } + + GLubyte *pixels = new GLubyte [ width * height * ocomp ]; + + glGetTexImage(GL_TEXTURE_2D, level, format[icomp], GL_UNSIGNED_BYTE, pixels); + + for (int y = height; y--;) { + for (int x = width; x--;) { + float af = icomp % 2 ? 1.0f : (1.0f / 256.0f) * pixels[(y * width + x + 1) * icomp - 1]; + // default alpha_ref is 0.1, so match that: + af = af > athres ? 0.1f + 0.9f * random_value() : 0; + int a = (int) (256.0f * af); + pixels[(y * width + x + 1) * ocomp - 1] = a >= 255 ? 255 : a; + if (ocomp > icomp) + for (int k = 0; k < icomp; k++) + pixels[(y * width + x) * ocomp + k] = pixels[(y * width + x) * icomp + k]; + } + } + + glTexImage2D(GL_TEXTURE_2D, level, format[ocomp], width, height, 0, + format[ocomp], GL_UNSIGNED_BYTE, pixels); + + delete [] pixels; + + if (width == 1 && height == 1) + break; + } +} + + + +void ssgaBillboards::cull(sgFrustum *f, sgMat4 m, int test_needed) +{ + int cull_result = cull_test(f, m, test_needed); + + if (cull_result == SSG_OUTSIDE) + return; + + draw(m); +} + + +void ssgaBillboards::draw() +{ + sgMat4 m; + + glGetFloatv(GL_MODELVIEW_MATRIX, &m[0][0]); + + draw(m); +} + + +void ssgaBillboards::draw(const sgMat4 m) +{ + if (!draw_num) + return; + + sgVec4 z_axis = { m[0][2], m[1][2], m[2][2], m[3][2] }; + float dist = -1; + + if (clip_dist >= 0) { + const sgSphere *s = getBSphere(); + + float z = sgScalarProductVec3(s->getCenter(), z_axis) + z_axis[3]; + dist = -z - s->getRadius(); + + if (dist >= clip_dist) + return; + } + + if (preDrawCB != NULL && !(*preDrawCB)(this)) + return; + + + float aref = alpha_ref; + + if (fade_dist >= 0 && fade_dist < clip_dist && dist > fade_dist) + aref += (1.0f - alpha_ref) * (dist - fade_dist) / (clip_dist - fade_dist); + + + _ssgCurrentContext->setCullface(0); + getState()->apply(); + + glPushAttrib(GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glAlphaFunc(GL_GEQUAL, aref); + + glBegin(GL_QUADS); + + + int n = getNum(); + const float *p = get(0); + + if (draw_num > 0 && draw_num < n) + n = draw_num; + + if (fade_num >= 0 && fade_num < n && clip_dist > near_dist && near_dist > 1e-6f) { + float far_dist = fade_dist >= 0 && fade_dist < clip_dist ? fade_dist : clip_dist; + if (dist > near_dist) { + if (dist < far_dist) { + float fn = 1.0f / near_dist; + float ff = 1.0f / far_dist; + float fd = 1.0f / dist; + float s = (fd - fn) / (ff - fn); + n -= (int) ((n - fade_num) * s + 0.5f); + } else { + n = fade_num; + } + } + } + + if (up[2] == 1) { + + // fast path when Z is up + + float wx, wy, heightz, len; + + wx = z_axis[1]; + wy = -z_axis[0]; + len = sgHypot(wx, wy); + + if (len > 1e-6f) { + + wx *= 0.5f * width / len; + wy *= 0.5f * width / len; + heightz = height; + + for (int i = 0; i < n; i++) { + float x, y, z, s, dx, dy; + + x = *p++; + y = *p++; + z = *p++; + s = *p++; + + dx = s * wx; + dy = s * wy; + + glTexCoord2f(0, 0); + glVertex3f(x - dx, y - dy, z); + + glTexCoord2f(1, 0); + glVertex3f(x + dx, y + dy, z); + + z += s * heightz; + + glTexCoord2f(1, 1); + glVertex3f(x + dx, y + dy, z); + + glTexCoord2f(0, 1); + glVertex3f(x - dx, y - dy, z); + } + + total_drawn += n; + } + + } else { + + sgVec3 xy; + sgVectorProductVec3(xy, z_axis, up); + float len = sgLengthVec3(xy); + + if (len > 1e-6f) { + float wx, wy, wz, heightx, heighty, heightz; + + wx = 0.5f * width * xy[0] / len; + wy = 0.5f * width * xy[1] / len; + wz = 0.5f * width * xy[2] / len; + + heightx = height * up[0]; + heighty = height * up[1]; + heightz = height * up[2]; + + for (int i = 0; i < n; i++) { + float x, y, z, s, dx, dy, dz; + + x = *p++; + y = *p++; + z = *p++; + s = *p++; + + dx = s * wx; + dy = s * wy; + dz = s * wz; + + glTexCoord2f(0, 0); + glVertex3f(x - dx, y - dy, z - dz); + + glTexCoord2f(1, 0); + glVertex3f(x + dx, y + dy, z + dz); + + x += s * heightx; + y += s * heighty; + z += s * heightz; + + glTexCoord2f(1, 1); + glVertex3f(x + dx, y + dy, z + dz); + + glTexCoord2f(0, 1); + glVertex3f(x - dx, y - dy, z - dz); + } + + total_drawn += n; + } + } + + + glEnd(); + + glPopAttrib(); + + if (postDrawCB != NULL) + (*postDrawCB)(this); +} + + + +float *ssgaBillboards::getVertex(int i) +{ + if (i < 0 || i >= 4 * getNum()) + return _ssgVertex000; + + // pick any orientation + sgVec3 xy, axis = { 0, 0, 0 }; + axis[ sgAbs(up[0]) > sgAbs(up[1]) ] = 1; + sgVectorProductVec3(xy, up, axis); + sgNormaliseVec3(xy); + + const sgVec3 tab[4] = { {-0.5f,0.0f}, {0.5f,0.0f}, {0.5f,1.0f}, {-0.5f,1.0f} }; + const float *p = array.get(i / 4); + const float *d = tab[i % 4]; + static sgVec3 v; + for (i = 0; i < 3; i++) + v[0] = p[i] + p[3] * (width * xy[i] * d[0] + height * up[i] * d[1]); + return v; +} + + +float *ssgaBillboards::getTexCoord(int i) +{ + static sgVec2 t[4] = { {0,0}, {1,0}, {1,1}, {0,1} }; + return t[i & 3]; +} + + +void ssgaBillboards::getTriangle(int n, short *v1, short *v2, short *v3) +{ + *v1 = 2*n + 0; + *v2 = 2*n + 1; + *v3 = 2*n + 2 - 4*(n&1); +} + + +void ssgaBillboards::transform(const sgMat4 m) +{ + float scale = sgLengthVec3(m[0]); + for (int i = 0; i < getNum(); i++) + sgXformPnt3(array.get(i), array.get(i), m); + sgXformVec3(up, up, m); + sgNormaliseVec3(up); + width *= scale; + height *= scale; +} + + + +/* + Local Variables: + mode: C++ + c-basic-offset: 4 + c-file-offsets: ((substatement-open 0) (case-label 0)) + End: +*/ diff --git a/src/ssgAux/ssgaBillboards.h b/src/ssgAux/ssgaBillboards.h new file mode 100644 index 0000000..d863cb8 --- /dev/null +++ b/src/ssgAux/ssgaBillboards.h @@ -0,0 +1,227 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgaBillboards.h 1844 2004-01-21 16:30:20Z stromberg $ +*/ + +/* + * ssgaBillboards + * + * Each billboard is represented by four values: X, Y, Z and scale. + * They are drawn as GL_QUADS using the texture defined in the state. + * + * Set the basic billboard size (each can be individually scaled): + * + * bb->setWidth(3.0f); + * bb->setHeight(8.0f); + * + * Set a texture image: + * + * bb->initTexAlpha(texture, 0.3f); // only once per texture, choose a suitable alpha threshold + * bb->setTexture(texture); + * + * Instantiate some billboards: + * + * for (i = 0; i < 1000; i++) + * bb->add( (drand48() - 0.5) * WORLD_SIZE_X, + * (drand48() - 0.5) * WORLD_SIZE_Y, + * Z, 0.75 + 0.5 * drand48() ); + * + * + * The billboards can be faded: + * + * bb->setClipRange(300.0f); // i.e. far clip + * bb->setFadeRange(200.0f); // starting fade here + * + * or, equivalently: + * + * bb->setFarRange(300.0f, 200.0f); // clip, fade + * + * + * The number of billboards drawn can be a function of distance: + * + * bb->setNearRange(50.0f); // draw all at this distance + * bb->setFadeNum(100); // number drawn at the fade distance (or clip distance if unset) + * + * Limit the number at the near range (defaults to all): + * + * bb->setDrawNum(500); + * + * + * Example code: plib/examples/src/ssg/shrubs/shrubs.cxx + * + * + * November 2003, Marten Stromberg + * + */ + + +#include "ssg.h" + + +class ssgaBillboards : public ssgLeaf +{ +protected: + + sgVec3 up; // vector pointing up (default: 0, 0, 1) + ssgColourArray array; // position and scale for each billboard + int draw_num; // only draw this many (-1 for all) + float width, height; // basic size of billboard + float clip_dist; // far clip distance (-1 disables) + float fade_dist; // fade-out distance (fade iff fade_dist < d < clip_dist) + float near_dist; // near distance for adjusting number of trees + int fade_num; // optionally adjust number of trees as a function of distance + float alpha_ref; // default 0.1 (initTexAlpha relies on that) + +public: + + ssgaBillboards(); + ~ssgaBillboards(); + + void setUp(const sgVec3 v) { sgNormaliseVec3(up, v); } + void setUp(float x, float y, float z) { sgVec3 v = { x, y, z }; setUp(v); } + const float *getUp() const { return up; } + + int getNum() { return array.getNum(); } // const + const float *get(int i) { return array.get((unsigned) i); } // const + + inline void add(float x, float y, float z, float scale = 1.0f); + inline void add(const sgVec4 xyzs); + + void removeLast() { array.removeLast(); dirtyBSphere(); } + void removeAll() { array.removeAll(); dirtyBSphere(); } + + void setWidth(float w) { width = w; } + float getWidth() const { return width; } + void setHeight(float h) { height = h; } + float getHeight() const { return height; } + + void setClipRange(float d) { clip_dist = d; } + float getClipRange() const { return clip_dist; } + void setFadeRange(float d) { fade_dist = d; } + float getFadeRange() const { return fade_dist; } + void setNearRange(float d) { near_dist = d; } + float getNearRange() const { return near_dist; } + + void setFarRange(float clip, float fade) { setFadeRange(fade); setClipRange(clip); } + void setFarRange(float clip) { setFarRange(clip, 0.75f * clip); } + void setNearFarRange(float near_, float clip, float fade) { setNearRange(near_); setFarRange(clip, fade); } + void setNearFarRange(float near_, float clip) { setNearRange(near_); setFarRange(clip); } + + void setDrawNum(int n) { draw_num = n; } + int getDrawNum() const { return draw_num; } + void setFadeNum(int n) { fade_num = n; } + int getFadeNum() const { return fade_num; } + + inline void setTexture(ssgTexture *tex); + inline ssgTexture *getTexture(); // const + + void setAlphaRef(float aref) { alpha_ref = aref; } // only when not using initTexAlpha + float getAlphaRef() const { return alpha_ref; } + + static void initTexAlpha(GLuint handle, float aref = 0.3f); // initialize alpha channel for smooth fading + static void initTexAlpha(ssgTexture *tex, float aref = 0.3f) { initTexAlpha(tex->getHandle(), aref); } + + + /* methods derived from ssgEntity and ssgLeaf */ + + virtual void recalcBSphere(); + + virtual void cull(sgFrustum *, sgMat4, int); + virtual void draw(); + + void draw(const sgMat4 m); + + virtual void draw_geometry() {} + virtual void pick(int) {} + + virtual void drawHighlight(sgVec4) {} + virtual void drawHighlight(sgVec4, int) {} + + virtual void isect_triangles(sgSphere *, sgMat4, int) {} + virtual void hot_triangles(sgVec3, sgMat4, int) {} + virtual void los_triangles(sgVec3, sgMat4, int) {} + + virtual const char *getTypeName() { return "ssgaBillboards"; } + + virtual GLenum getPrimitiveType() { return GL_QUADS; } + + virtual int getNumVertices() { return 4 * getNum(); } + virtual int getNumTexCoords() { return 4 * getNum(); } + virtual int getNumNormals() { return 0; } + virtual int getNumColours() { return 0; } + + virtual float *getVertex(int i); + virtual float *getTexCoord(int i); + virtual float *getNormal(int) { return _ssgNormalUp; } + virtual float *getColour(int) { return _ssgColourWhite; } + + virtual int getNumTriangles() { return 2 * getNum(); } + virtual void getTriangle(int n, short *v1, short *v2, short *v3); + virtual int getNumLines() { return 0; } + virtual void getLine(int, short *v1, short *v2) {} + + virtual void transform(const sgMat4 m); + + + // incremented each draw, use it as you like + static int total_drawn; + +}; + + + +inline void ssgaBillboards::add(float x, float y, float z, float w) +{ + array.add(x, y, z, w); + dirtyBSphere(); +} + + +inline void ssgaBillboards::add(const sgVec4 xyzs) +{ + array.add((float *) xyzs); + dirtyBSphere(); +} + + +inline void ssgaBillboards::setTexture(ssgTexture *tex) +{ + ssgSimpleState *ss = (ssgSimpleState *) getState(); + assert( ss && ss->isAKindOf( ssgTypeSimpleState() )); + ss->setTexture(tex); +} + + +inline ssgTexture *ssgaBillboards::getTexture() +{ + ssgSimpleState *ss = (ssgSimpleState *) getState(); + assert( ss && ss->isAKindOf( ssgTypeSimpleState() )); + return ss->getTexture(); +} + + +/* + Local Variables: + mode: C++ + c-basic-offset: 4 + c-file-offsets: ((substatement-open 0) (case-label 0)) + End: +*/ diff --git a/src/ssgAux/ssgaCelestialBody.cxx b/src/ssgAux/ssgaCelestialBody.cxx new file mode 100644 index 0000000..7e855fe --- /dev/null +++ b/src/ssgAux/ssgaCelestialBody.cxx @@ -0,0 +1,406 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgaCelestialBody.cxx 1798 2003-09-26 14:54:20Z sjbaker $ +*/ + +// Written by Durk Talsma. Originally started October 1997, for distribution +// with the FlightGear project. Version 2 was written in August and +// September 1998. This code is based upon algorithms and data kindly +// provided by Mr. Paul Schlyter. (pausch@saaf.se). +// +// Separated out rendering pieces and converted to ssg by Curt Olson, +// March 2000 +// +// Moved into ssgAux, July 2003. + +#include +#include "ssgaSky.h" +#include "ssgaSphere.h" + + +static int ssgaCelestialBodyOrbPreDraw( ssgEntity *e ) +{ + ssgLeaf *f = (ssgLeaf *)e; + if ( f -> hasState () ) f->getState()->apply() ; + + glPushAttrib( GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT ); + + //glDisable( GL_DEPTH_TEST ); + glDisable( GL_FOG ); + glBlendFunc ( GL_SRC_ALPHA, GL_ONE ) ; + + return true; +} + + +static int ssgaCelestialBodyOrbPostDraw( ssgEntity *e ) +{ + glPopAttrib(); + + return true; +} + + +static int ssgaCelestialBodyHaloPreDraw( ssgEntity *e ) +{ + ssgLeaf *f = (ssgLeaf *)e; + if ( f -> hasState () ) f->getState()->apply() ; + + glPushAttrib( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_FOG_BIT ); + + glDisable( GL_DEPTH_TEST ); + glDisable( GL_FOG ); + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; + + return true; +} + + +static int ssgaCelestialBodyHaloPostDraw( ssgEntity *e ) +{ + glPopAttrib(); + + return true; +} + + +ssgaCelestialBody::ssgaCelestialBody( void ) +{ + transform = 0; + body_angle = 0; + body_rotation = 0; + body_right_ascension = 0; + body_declination = 0; + body_dist = 0; +} + + +ssgaCelestialBody::~ssgaCelestialBody( void ) +{ + ssgDeRefDelete( transform ); +} + + +ssgBranch * ssgaCelestialBody::build( const char* body_tex_path, const char* halo_tex_path, double body_size ) +{ + ssgSimpleState *orb_state = NULL; + ssgSimpleState *halo_state = NULL; + + // set up the orb state + orb_state = new ssgSimpleState(); + if (body_tex_path) { + orb_state->setTexture( body_tex_path ); + orb_state->setShadeModel( GL_SMOOTH ); + orb_state->enable( GL_LIGHTING ); + orb_state->enable( GL_CULL_FACE ); + orb_state->enable( GL_TEXTURE_2D ); + orb_state->enable( GL_COLOR_MATERIAL ); + orb_state->setColourMaterial( GL_DIFFUSE ); + orb_state->setMaterial( GL_AMBIENT, 0, 0, 0, 1 ); + orb_state->setMaterial( GL_EMISSION, 0, 0, 0, 1 ); + orb_state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 ); + orb_state->enable( GL_BLEND ); + orb_state->enable( GL_ALPHA_TEST ); + orb_state->setAlphaClamp( 0.01f ); + } + else { + orb_state->setShadeModel( GL_SMOOTH ); + orb_state->disable( GL_LIGHTING ); + orb_state->enable( GL_CULL_FACE ); + orb_state->disable( GL_TEXTURE_2D ); + orb_state->enable( GL_COLOR_MATERIAL ); + orb_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE ); + orb_state->setMaterial( GL_EMISSION, 0, 0, 0, 1 ); + orb_state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 ); + orb_state->disable( GL_BLEND ); + orb_state->disable( GL_ALPHA_TEST ); + } + + if (halo_tex_path) { + + // build the halo + // GLuint texid; + // GLubyte *texbuf; + // texbuf = new GLubyte[64*64*3]; + // texid = makeHalo( texbuf, 64 ); + // my_glWritePPMFile("halo.ppm", texbuf, 64, 64, RGB); + + // set up the halo state + halo_state = new ssgSimpleState(); + halo_state->setTexture( halo_tex_path ); + halo_state->enable( GL_TEXTURE_2D ); + halo_state->disable( GL_LIGHTING ); + halo_state->setShadeModel( GL_SMOOTH ); + halo_state->disable( GL_CULL_FACE ); + halo_state->enable( GL_COLOR_MATERIAL ); + halo_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE ); + halo_state->setMaterial( GL_EMISSION, 0, 0, 0, 1 ); + halo_state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 ); + halo_state->enable( GL_ALPHA_TEST ); + halo_state->setAlphaClamp(0.01f); + halo_state->enable ( GL_BLEND ) ; + } + + return build( orb_state, halo_state, body_size ); +} + + +ssgBranch * ssgaCelestialBody::build( ssgSimpleState *orb_state, ssgSimpleState *halo_state, double body_size ) +{ + ssgVertexArray *halo_vl; + ssgTexCoordArray *halo_tl; + + // clean-up previous + ssgDeRefDelete( transform ); + + // build the ssg scene graph sub tree for the sky and connected + // into the provide scene graph branch + transform = new ssgTransform; + transform->ref(); + + cl = new ssgColourArray( 1 ); + sgVec4 color; + sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 ); + cl->add( color ); + + ssgBranch *orb = ssgaMakeSphere( orb_state, cl, (float)body_size, 15, 15, + ssgaCelestialBodyOrbPreDraw, ssgaCelestialBodyOrbPostDraw ); + + transform->addKid( orb ); + + // force a repaint of the colors with arbitrary defaults + repaint( 0.0 ); + + if (halo_state) { + + // Build ssg structure + float size = float(body_size * 10.0); + sgVec3 v3; + halo_vl = new ssgVertexArray; + sgSetVec3( v3, -size, 0.0, -size ); + halo_vl->add( v3 ); + sgSetVec3( v3, size, 0.0, -size ); + halo_vl->add( v3 ); + sgSetVec3( v3, -size, 0.0, size ); + halo_vl->add( v3 ); + sgSetVec3( v3, size, 0.0, size ); + halo_vl->add( v3 ); + + sgVec2 v2; + halo_tl = new ssgTexCoordArray; + sgSetVec2( v2, 0.0f, 0.0f ); + halo_tl->add( v2 ); + sgSetVec2( v2, 1.0, 0.0 ); + halo_tl->add( v2 ); + sgSetVec2( v2, 0.0, 1.0 ); + halo_tl->add( v2 ); + sgSetVec2( v2, 1.0, 1.0 ); + halo_tl->add( v2 ); + + ssgLeaf *halo = + new ssgVtxTable ( GL_TRIANGLE_STRIP, halo_vl, NULL, halo_tl, cl ); + halo->setState( halo_state ); + + halo->setCallback( SSG_CALLBACK_PREDRAW, ssgaCelestialBodyHaloPreDraw ); + halo->setCallback( SSG_CALLBACK_POSTDRAW, ssgaCelestialBodyHaloPostDraw ); + + transform->addKid( halo ); + } + + return transform; +} + + +bool ssgaCelestialBody::reposition( sgVec3 p, double angle, double rightAscension, double declination, double sol_dist ) +{ + sgMat4 T1, T2, GST, RA, DEC; + sgVec3 axis; + sgVec3 v; + + sgMakeTransMat4( T1, p ); + + sgSetVec3( axis, 0.0, 0.0, -1.0 ); + sgMakeRotMat4( GST, (float)angle, axis ); + + sgSetVec3( axis, 0.0, 0.0, 1.0 ); + sgMakeRotMat4( RA, (float)((rightAscension * SGD_RADIANS_TO_DEGREES) - 90.0), axis ); + + sgSetVec3( axis, 1.0, 0.0, 0.0 ); + sgMakeRotMat4( DEC, (float)(declination * SGD_RADIANS_TO_DEGREES), axis ); + + sgSetVec3( v, 0.0, (float)sol_dist, 0.0 ); + sgMakeTransMat4( T2, v ); + + sgMat4 TRANSFORM; + sgCopyMat4( TRANSFORM, T1 ); + sgPreMultMat4( TRANSFORM, GST ); + sgPreMultMat4( TRANSFORM, RA ); + sgPreMultMat4( TRANSFORM, DEC ); + sgPreMultMat4( TRANSFORM, T2 ); + + sgCoord skypos; + sgSetCoord( &skypos, TRANSFORM ); + + transform->setTransform( &skypos ); + + return true; +} + + +bool ssgaCelestialBody::repaint( double angle ) +{ + static double prev_angle = 9999.0; + + if (prev_angle != angle) { + + prev_angle = angle; + + double factor = 4*cos(angle); + + if (factor > 1) factor = 1.0; + if (factor < -1) factor = -1.0; + factor = factor/2 + 0.5f; + + sgVec4 color; + color[0] = (float)pow(factor, 0.25); + color[1] = (float)pow(factor, 0.50); + color[2] = (float)pow(factor, 4.0); + color[3] = 1.0; + + ssgaGammaCorrectRGB( color ); + + float *ptr; + ptr = cl->get( 0 ); + sgCopyVec4( ptr, color ); + } + + return true; +} + + +#if 0 +static GLuint makeHalo( GLubyte *texbuf, int width ) +{ + int texSize; + GLuint texid; + GLubyte *p; + int i,j; + double radius; + + // create a texture id +#ifdef GL_VERSION_1_1 + glGenTextures(1, &texid); + glBindTexture(GL_TEXTURE_2D, texid); +#elif GL_EXT_texture_object + glGenTexturesEXT(1, &texid); + glBindTextureEXT(GL_TEXTURE_2D, texid); +#else +# error port me +#endif + + glPixelStorei( GL_UNPACK_ALIGNMENT, 4 ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ; + + // create the actual texture contents + texSize = width * width; + + if ( !texbuf ) { + cout << "ouch ..." << endl; + exit(-1); // Ugly! + } + + p = texbuf; + + radius = (double)(width / 2); + + GLubyte value; + double x, y, d; + for ( i = 0; i < width; i++ ) { + for ( j = 0; j < width; j++ ) { + x = fabs((double)(i - (width / 2))); + y = fabs((double)(j - (width / 2))); + d = sqrt((x * x) + (y * y)); + if (d < radius) { + // t is 1.0 at center, 0.0 at edge + double t = 1.0 - (d / radius); + + // inverse square looks nice + value = (int)((double) 0xff * (t*t)); + } else { + value = 0x00; + } + *p = value; + *(p+1) = value; + *(p+2) = value; + // *(p+3) = value; + + p += 3; + } + } + + /* glTexImage2D( GL_TEXTURE_2D, + 0, + GL_RGBA, + width, width, + 0, + GL_RGBA, GL_UNSIGNED_BYTE, + texbuf ); */ + + return texid; +} + + +#define RGB 3 // 3 bytes of color info per pixel +#define RGBA 4 // 4 bytes of color+alpha info +void my_glWritePPMFile(const char *filename, GLubyte *buffer, int win_width, int win_height, int mode) +{ + int i, j, k, q; + unsigned char *ibuffer; + FILE *fp; + int pixelSize = mode==GL_RGBA?4:3; + + ibuffer = (unsigned char *) malloc(win_width*win_height*RGB); + + fp = fopen(filename, "wb"); + fprintf(fp, "P6\n# CREATOR: glReadPixel()\n%d %d\n%d\n", + win_width, win_height, UCHAR_MAX); + q = 0; + for (i = 0; i < win_height; i++) { + for (j = 0; j < win_width; j++) { + for (k = 0; k < RGB; k++) { + ibuffer[q++] = (unsigned char) + *(buffer + (pixelSize*((win_height-1-i)*win_width+j)+k)); + } + } + } + + // *(buffer + (pixelSize*((win_height-1-i)*win_width+j)+k)); + + fwrite(ibuffer, sizeof(unsigned char), RGB*win_width*win_height, fp); + fclose(fp); + free(ibuffer); + + printf("wrote file (%d x %d pixels, %d bytes)\n", + win_width, win_height, RGB*win_width*win_height); +} +#endif diff --git a/src/ssgAux/ssgaCloudLayer.cxx b/src/ssgAux/ssgaCloudLayer.cxx new file mode 100644 index 0000000..64a5579 --- /dev/null +++ b/src/ssgAux/ssgaCloudLayer.cxx @@ -0,0 +1,524 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgaCloudLayer.cxx 1793 2003-08-26 21:36:53Z nmcevoy $ +*/ + +// Written by Curtis Olson, started June 2000. +// +// Moved into ssgAux, July 2003. + +#include "ssgaSky.h" + +/* Nautical Miles to Meters */ +#define SG_NM_TO_METER 1852.0000 + +/* Radians to Nautical Miles. 1 nm = 1/60 of a degree */ +#define SG_NM_TO_RAD 0.00029088820866572159 + +/* Nautical Miles to Radians */ +#define SG_RAD_TO_NM 3437.7467707849392526 + +/* For divide by zero avoidance, this will be close enough to zero */ +#define SG_EPSILON 0.0000001 + +void calc_gc_course_dist( const sgVec2& start, const sgVec2& dest, double *course, double *dist ); + +// make an ssgSimpleState for a cloud layer given the named texture +ssgSimpleState *sgCloudMakeState( const char* path ); + + +ssgaCloudLayer::ssgaCloudLayer( void ) : + layer_root(new ssgRoot), + layer_transform(new ssgTransform), + enabled(true), + layer_span(0.0), + layer_asl(0.0), + layer_thickness(0.0), + layer_transition(0.0), + scale(4000.0), + speed(0.0), + direction(0.0), + last_lon(0.0), + last_lat(0.0), + last_x(0.0), + last_y(0.0) +{ + cl[0] = cl[1] = cl[2] = cl[3] = NULL; + vl[0] = vl[1] = vl[2] = vl[3] = NULL; + tl[0] = tl[1] = tl[2] = tl[3] = NULL; + layer[0] = layer[1] = layer[2] = layer[3] = NULL; + + layer_root->addKid(layer_transform); +} + + +ssgaCloudLayer::~ssgaCloudLayer() +{ + delete layer_root; // deletes layer_transform and layer as well +} + + +void +ssgaCloudLayer::build( const char *cloud_tex_path, float span, float elevation, float thickness, float transition ) +{ + ssgSimpleState *cloud_state = sgCloudMakeState( cloud_tex_path ); + build(cloud_state, span, elevation, thickness, transition); +} + + +void +ssgaCloudLayer::build( ssgSimpleState *cloud_state, float span, float elevation, float thickness, float transition ) +{ + layer_span = span; + layer_asl = elevation; + layer_thickness = thickness; + layer_transition = transition; + + scale = 4000.0; + last_lon = last_lat = -999.0f; + last_x = last_y = 0.0f; + + sgVec2 base; + sgSetVec2( base, (float)ssgaRandom(), (float)ssgaRandom() ); + + // build the cloud layer + sgVec4 color; + sgVec3 vertex; + sgVec2 tc; + + const float layer_scale = layer_span / scale; + const float mpi = SG_PI/4; + const float alt_diff = layer_asl * 1.5f; + + for (int i = 0; i < 4; i++) { + if ( layer[i] != NULL ) { + layer_transform->removeKid(layer[i]); // automatic delete + } + + vl[i] = new ssgVertexArray( 10 ); + cl[i] = new ssgColourArray( 10 ); + tl[i] = new ssgTexCoordArray( 10 ); + + sgSetVec3( vertex, layer_span*(i-2)/2, -layer_span, + (float)(alt_diff * (sin(i*mpi) - 2)) ); + + sgSetVec2( tc, base[0] + layer_scale * i/4, base[1] ); + + sgSetVec4( color, 1.0f, 1.0f, 1.0f, (i == 0) ? 0.0f : 0.15f ); + + cl[i]->add( color ); + vl[i]->add( vertex ); + tl[i]->add( tc ); + + for (int j = 0; j < 4; j++) { + + sgSetVec3( vertex, layer_span*(i-1)/2, layer_span*(j-2)/2, + (float)(alt_diff * (sin((i+1)*mpi) + sin(j*mpi) - 2)) ); + + sgSetVec2( tc, base[0] + layer_scale * (i+1)/4, + base[1] + layer_scale * j/4 ); + + sgSetVec4( color, 1.0f, 1.0f, 1.0f, + ( (j == 0) || (i == 3)) ? + ( (j == 0) && (i == 3)) ? 0.0f : 0.15f : 1.0f ); + + cl[i]->add( color ); + vl[i]->add( vertex ); + tl[i]->add( tc ); + + sgSetVec3( vertex, layer_span*(i-2)/2, layer_span*(j-1)/2, + (float)(alt_diff * (sin(i*mpi) + sin((j+1)*mpi) - 2)) ); + + sgSetVec2( tc, base[0] + layer_scale * i/4, + base[1] + layer_scale * (j+1)/4 ); + + sgSetVec4( color, 1.0f, 1.0f, 1.0f, + ((j == 3) || (i == 0)) ? + ((j == 3) && (i == 0)) ? 0.0f : 0.15f : 1.0f ); + cl[i]->add( color ); + vl[i]->add( vertex ); + tl[i]->add( tc ); + } + + sgSetVec3( vertex, layer_span*(i-1)/2, layer_span, + (float)(alt_diff * (sin((i+1)*mpi) - 2)) ); + + sgSetVec2( tc, base[0] + layer_scale * (i+1)/4, + base[1] + layer_scale ); + + sgSetVec4( color, 1.0f, 1.0f, 1.0f, (i == 3) ? 0.0f : 0.15f ); + + cl[i]->add( color ); + vl[i]->add( vertex ); + tl[i]->add( tc ); + + layer[i] = new ssgVtxTable(GL_TRIANGLE_STRIP, vl[i], NULL, tl[i], cl[i]); + layer_transform->addKid( layer[i] ); + + layer[i]->setState( cloud_state ); + } + + // force a repaint of the sky colors with arbitrary defaults + repaint( color ); +} + + +bool ssgaCloudLayer::repositionFlat( sgVec3 p, double dt ) +{ + sgMat4 T1; + + // combine p and asl (meters) to get translation offset + sgVec3 asl_offset; + if ( p[SG_Z] <= layer_asl ) { + sgSetVec3( asl_offset, p[SG_X], p[SG_Y], layer_asl ); + } + else { + sgSetVec3( asl_offset, p[SG_X], p[SG_Y], layer_asl + layer_thickness ); + } + + // Translate to elevation + sgMakeTransMat4( T1, asl_offset ); + + sgMat4 TRANSFORM; + sgCopyMat4( TRANSFORM, T1 ); + + sgCoord layerpos; + sgSetCoord( &layerpos, TRANSFORM ); + + layer_transform->setTransform( &layerpos ); + + // now calculate update texture coordinates + double sp_dist = speed*dt; + + if ( p[SG_X] != last_x || p[SG_Y] != last_y || sp_dist != 0 ) { + + // calculate cloud movement + double ax = 0.0, ay = 0.0, bx = 0.0, by = 0.0; + + ax = p[SG_X] - last_x; + ay = p[SG_Y] - last_y; + + if (sp_dist > 0) { + bx = cos(-direction * SGD_DEGREES_TO_RADIANS) * sp_dist; + by = sin(-direction * SGD_DEGREES_TO_RADIANS) * sp_dist; + } + + float xoff = (float)((ax + bx) / (2 * scale)); + float yoff = (float)((ay + by) / (2 * scale)); + + const float layer_scale = layer_span / scale; + + float *base, *tc; + + base = tl[0]->get( 0 ); + base[0] += xoff; + + // the while loops can lead to *long* pauses if base[0] comes + // with a bogus value. + // while ( base[0] > 1.0 ) { base[0] -= 1.0; } + // while ( base[0] < 0.0 ) { base[0] += 1.0; } + if ( base[0] > -10.0 && base[0] < 10.0 ) { + base[0] -= (int)base[0]; + } + else { + base[0] = 0.0; + ulSetError(UL_WARNING, "Warning: base1\n"); + } + + base[1] += yoff; + // the while loops can lead to *long* pauses if base[0] comes + // with a bogus value. + // while ( base[1] > 1.0 ) { base[1] -= 1.0; } + // while ( base[1] < 0.0 ) { base[1] += 1.0; } + if ( base[1] > -10.0 && base[1] < 10.0 ) { + base[1] -= (int)base[1]; + } + else { + base[1] = 0.0; + ulSetError(UL_WARNING, "Warning: base2\n"); + } + + for (int i = 0; i < 4; i++) { + tc = tl[i]->get( 0 ); + sgSetVec2( tc, base[0] + layer_scale * i/4, base[1] ); + + for (int j = 0; j < 4; j++) { + tc = tl[i]->get( j*2+1 ); + sgSetVec2( tc, base[0] + layer_scale * (i+1)/4, + base[1] + layer_scale * j/4 ); + + tc = tl[i]->get( (j+1)*2 ); + sgSetVec2( tc, base[0] + layer_scale * i/4, + base[1] + layer_scale * (j+1)/4 ); + } + + tc = tl[i]->get( 9 ); + sgSetVec2( tc, base[0] + layer_scale * (i+1)/4, + base[1] + layer_scale ); + } + + last_x = p[SG_X]; + last_y = p[SG_Y]; + } + + return true; +} + + +bool ssgaCloudLayer::reposition( sgVec3 p, sgVec3 up, double lon, double lat, double alt, double dt ) +{ + sgMat4 T1, LON, LAT; + sgVec3 axis; + + // combine p and asl (meters) to get translation offset + sgVec3 asl_offset; + sgCopyVec3( asl_offset, up ); + sgNormalizeVec3( asl_offset ); + if ( alt <= layer_asl ) { + sgScaleVec3( asl_offset, layer_asl ); + } + else { + sgScaleVec3( asl_offset, layer_asl + layer_thickness ); + } + sgAddVec3( asl_offset, p ); + + // Translate to zero elevation + sgMakeTransMat4( T1, asl_offset ); + + // Rotate to proper orientation + sgSetVec3( axis, 0.0, 0.0, 1.0 ); + sgMakeRotMat4( LON, (float)(lon * SGD_RADIANS_TO_DEGREES), axis ); + + sgSetVec3( axis, 0.0, 1.0, 0.0 ); + sgMakeRotMat4( LAT, (float)(90.0 - lat * SGD_RADIANS_TO_DEGREES), axis ); + + sgMat4 TRANSFORM; + + sgCopyMat4( TRANSFORM, T1 ); + sgPreMultMat4( TRANSFORM, LON ); + sgPreMultMat4( TRANSFORM, LAT ); + + sgCoord layerpos; + sgSetCoord( &layerpos, TRANSFORM ); + + layer_transform->setTransform( &layerpos ); + + // now calculate update texture coordinates + if ( last_lon < -900 ) { + last_lon = lon; + last_lat = lat; + } + + double sp_dist = speed*dt; + + if ( lon != last_lon || lat != last_lat || sp_dist != 0 ) { + + double course = 0.0, dist = 0.0; + if ( lon != last_lon || lat != last_lat ) { + sgVec2 start, dest; + sgSetVec2(start, (float)last_lon, (float)last_lat); + sgSetVec2(dest, (float)lon, (float)lat); + calc_gc_course_dist( dest, start, &course, &dist ); + } + + // calculate cloud movement + double ax = 0.0, ay = 0.0, bx = 0.0, by = 0.0; + + if (dist > 0.0) { + ax = cos(course) * dist; + ay = sin(course) * dist; + } + + if (sp_dist > 0) { + bx = cos(-direction * SGD_DEGREES_TO_RADIANS) * sp_dist; + by = sin(-direction * SGD_DEGREES_TO_RADIANS) * sp_dist; + } + + float xoff = (float)((ax + bx) / (2 * scale)); + float yoff = (float)((ay + by) / (2 * scale)); + + const float layer_scale = layer_span / scale; + + float *base, *tc; + + base = tl[0]->get( 0 ); + base[0] += xoff; + + // the while loops can lead to *long* pauses if base[0] comes + // with a bogus value. + // while ( base[0] > 1.0 ) { base[0] -= 1.0; } + // while ( base[0] < 0.0 ) { base[0] += 1.0; } + if ( base[0] > -10.0 && base[0] < 10.0 ) { + base[0] -= (int)base[0]; + } + else { + base[0] = 0.0; + ulSetError(UL_WARNING, "Warning: base1\n"); + } + + base[1] += yoff; + // the while loops can lead to *long* pauses if base[0] comes + // with a bogus value. + // while ( base[1] > 1.0 ) { base[1] -= 1.0; } + // while ( base[1] < 0.0 ) { base[1] += 1.0; } + if ( base[1] > -10.0 && base[1] < 10.0 ) { + base[1] -= (int)base[1]; + } + else { + base[1] = 0.0; + ulSetError(UL_WARNING, "Warning: base2\n"); + } + + for (int i = 0; i < 4; i++) { + tc = tl[i]->get( 0 ); + sgSetVec2( tc, base[0] + layer_scale * i/4, base[1] ); + + for (int j = 0; j < 4; j++) { + tc = tl[i]->get( j*2+1 ); + sgSetVec2( tc, base[0] + layer_scale * (i+1)/4, + base[1] + layer_scale * j/4 ); + + tc = tl[i]->get( (j+1)*2 ); + sgSetVec2( tc, base[0] + layer_scale * i/4, + base[1] + layer_scale * (j+1)/4 ); + } + + tc = tl[i]->get( 9 ); + sgSetVec2( tc, base[0] + layer_scale * (i+1)/4, + base[1] + layer_scale ); + } + + last_lon = lon; + last_lat = lat; + } + + return true; +} + + +bool ssgaCloudLayer::repaint( sgVec3 fog_color ) +{ + float *color; + + for ( int i = 0; i < 4; i++ ) + for ( int j = 0; j < 10; ++j ) { + color = cl[i]->get( j ); + sgCopyVec3( color, fog_color ); + } + + return true; +} + + +void ssgaCloudLayer::draw() +{ + if (!enabled) + return; + + ssgCullAndDraw( layer_root ); +} + + +ssgSimpleState *sgCloudMakeState( const char* path ) +{ + ssgSimpleState *state = new ssgSimpleState(); + + state->setTexture( path ); + state->setShadeModel( GL_SMOOTH ); + state->disable( GL_LIGHTING ); + state->disable( GL_CULL_FACE ); + state->enable( GL_TEXTURE_2D ); + state->enable( GL_COLOR_MATERIAL ); + state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE ); + state->setMaterial( GL_EMISSION, 0, 0, 0, 1 ); + state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 ); + state->enable( GL_BLEND ); + state->enable( GL_ALPHA_TEST ); + state->setAlphaClamp( 0.01f ); + + return state; +} + + +void calc_gc_course_dist( const sgVec2& start, const sgVec2& dest, double *course, double *dist ) +{ + // d = 2*asin(sqrt((sin((lat1-lat2)/2))^2 + + // cos(lat1)*cos(lat2)*(sin((lon1-lon2)/2))^2)) + double cos_start_y = cos( start[SG_Y] ); + volatile double tmp1 = sin( (start[SG_Y] - dest[SG_Y]) * 0.5 ); + volatile double tmp2 = sin( (start[SG_X] - dest[SG_X]) * 0.5 ); + double d = 2.0 * asin( sqrt( tmp1 * tmp1 + + cos_start_y * cos(dest[SG_Y]) * tmp2 * tmp2)); + + *dist = d * SG_RAD_TO_NM * SG_NM_TO_METER; + + // We obtain the initial course, tc1, (at point 1) from point 1 to + // point 2 by the following. The formula fails if the initial + // point is a pole. We can special case this with: + // + // IF (cos(lat1) < EPS) // EPS a small number ~ machine precision + // IF (lat1 > 0) + // tc1= pi // starting from N pole + // ELSE + // tc1= 0 // starting from S pole + // ENDIF + // ENDIF + // + // For starting points other than the poles: + // + // IF sin(lon2-lon1)<0 + // tc1=acos((sin(lat2)-sin(lat1)*cos(d))/(sin(d)*cos(lat1))) + // ELSE + // tc1=2*pi-acos((sin(lat2)-sin(lat1)*cos(d))/(sin(d)*cos(lat1))) + // ENDIF + + // if ( cos(start[SG_Y]) < SG_EPSILON ) { + // doing it this way saves a transcendental call + double sin_start_y = sin( start[SG_Y] ); + if ( fabs(1.0-sin_start_y) < SG_EPSILON ) { + // EPS a small number ~ machine precision + if ( start[SG_Y] > 0 ) { + *course = SGD_PI; // starting from N pole + } else { + *course = 0; // starting from S pole + } + } else { + // For starting points other than the poles: + // double tmp3 = sin(d)*cos_start_y); + // double tmp4 = sin(dest[SG_Y])-sin(start[SG_Y])*cos(d); + // double tmp5 = acos(tmp4/tmp3); + + // Doing this way gaurentees that the temps are + // not stored into memory + double tmp5 = acos( (sin(dest[SG_Y]) - sin_start_y * cos(d)) / + (sin(d) * cos_start_y) ); + + // if ( sin( dest[SG_X] - start[SG_X] ) < 0 ) { + // the sin of the negative angle is just the opposite sign + // of the sin of the angle so tmp2 will have the opposite + // sign of sin( dest[SG_X] - start[SG_X] ) + if ( tmp2 >= 0 ) { + *course = tmp5; + } else { + *course = 2 * SGD_PI - tmp5; + } + } +} diff --git a/src/ssgAux/ssgaFire.cxx b/src/ssgAux/ssgaFire.cxx new file mode 100644 index 0000000..315651d --- /dev/null +++ b/src/ssgAux/ssgaFire.cxx @@ -0,0 +1,256 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + +*/ + +#include "ssg.h" +#include "ssgAux.h" + +#define EMBER_SCALE 3.0f + +void _ssgaFireParticleCreate ( ssgaParticleSystem *ps, + int idx, ssgaParticle *p ) +{ + ((ssgaFire *) ps) -> createParticle ( idx, p ) ; +} + + + +void _ssgaFireParticleUpdate ( float, ssgaParticleSystem *ps, + int idx, ssgaParticle *p ) +{ + ((ssgaFire *) ps) -> updateParticle ( idx, p ) ; +} + + + + +void ssgaFire::reInit () +{ + setCreationRate ( (float)(getNumParticles()) / max_ttl ) ; + + delete colourTable ; + delete sizeTable ; + + tableSize = (int)( 10.0f * max_ttl ) ; + + colourTable = new float [ tableSize * 4 ] ; + sizeTable = new float [ tableSize ] ; + + sgCopyVec4 ( & colourTable [ 0 ], hot_colour ) ; + sizeTable [ 0 ] = start_size ; + + for ( int i = 1 ; i < tableSize ; i++ ) + { + sizeTable [ i ] = sizeTable [ i-1 ] * 1.06f ; + + if ( sizeTable [ i ] >= 1.5 ) sizeTable [ i ] = 1.5 ; + + sgScaleVec3 ( & colourTable [ i * 4 ], + & colourTable [ (i-1)* 4 ], 0.90f ) ; + + colourTable [ i * 4 + 3 ] = 1.0f ; + } +} + + +void ssgaFire::createParticle ( int idx, ssgaParticle *p ) +{ + float xx = (float)(rand()%1000)/500.0f * radius - radius ; + float yy = (float)sqrt ( radius * radius - xx * xx ) ; + + yy = (float)(rand()%1000)/500.0f * yy - yy ; + + p -> time_to_live = max_ttl ; + p -> size = sizeTable [ 0 ] ; + + sgCopyVec4 ( p -> col, & colourTable [ 0 ] ) ; + + if ( (idx & 3) != 0 ) + { + sgSetVec3 ( p -> pos, xx, yy, -p->size ) ; + sgSetVec3 ( p -> vel, 0, 0, upward_speed ) ; + } + else + { + p->size *= EMBER_SCALE ; + + sgSetVec3 ( p -> pos, xx, yy, 0.0f ) ; + sgSetVec3 ( p -> vel, 0, 0, 0 ) ; + } + + sgSetVec3 ( p -> acc, 0, 0, 0 ) ; +} + + + + +void ssgaFire::updateParticle ( int idx, ssgaParticle *p ) +{ + int tick = (int)( ( max_ttl - p->time_to_live ) * 10.0f ) ; + + if ( tick >= tableSize ) + { + p->time_to_live = 0.0f ; + return ; + } + + if ( (idx & 3) != 0 ) + p -> size = sizeTable [ tick ] ; + else + p -> size = sizeTable [ tick ] * EMBER_SCALE ; + + sgCopyVec4 ( p -> col, & colourTable [ tick * 4 ] ) ; +} + + +static ssgSimpleState *fireState = NULL ; +static ssgTexture *fireTexture = NULL ; +static bool isfogged = true ; +static int preFireDraw ( ssgEntity * ) +{ + isfogged = ( glIsEnabled ( GL_FOG ) == GL_TRUE ) ; + + if ( isfogged ) + glDisable ( GL_FOG ) ; + + glBlendFunc ( GL_ONE, GL_ONE ) ; + return TRUE ; +} + + +static int postFireDraw ( ssgEntity * ) +{ + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; + + if ( isfogged ) + glEnable ( GL_FOG ) ; + + return TRUE ; +} + +ssgaFire::ssgaFire ( int num, + float _radius, + float height, + float speed ) + : ssgaParticleSystem ( num/2, + 0, 0, // <== Don't Change this!! + TRUE, 1.0f, height * 2.0f, + _ssgaFireParticleCreate, + _ssgaFireParticleUpdate ) +{ + radius = _radius ; + upward_speed = speed ; + start_size = 0.6f ; + + if ( fireState == NULL ) + { + /* + The texture constructor deletes the texture from + main memory after it's finished with it!! YIKES!! + */ + + unsigned char *t = new unsigned char [ 32 * 32 ] ; + memcpy ( t, _ssgaGetFireTexture(), 32 * 32 ) ; + + fireTexture = new ssgTexture ( "NONE", t, 32, 32, 1 ) ; + + fireState = new ssgSimpleState () ; + fireState -> setTexture ( fireTexture ) ; + fireState -> setTranslucent () ; + fireState -> enable ( GL_TEXTURE_2D ) ; + fireState -> enable ( GL_BLEND ) ; + fireState -> disable ( GL_LIGHTING ) ; + fireState -> ref () ; + } + + + tableSize = 0 ; + colourTable = NULL ; + sizeTable = NULL ; + + sgSetVec4 ( hot_colour, 1.0f, 0.2f, 0.1f, 1.0f ) ; + + setHeight ( height ) ; /* Forces a reInit */ + + setState ( fireState ) ; + setCallback ( SSG_CALLBACK_PREDRAW , preFireDraw ) ; + setCallback ( SSG_CALLBACK_POSTDRAW, postFireDraw ) ; + update ( 2.0f * max_ttl / (float)(getNumParticles()) ) ; +} + +void ssgaFire::update ( float t ) +{ + ssgaParticleSystem::update ( t ) ; +} + + +unsigned char *_ssgaGetFireTexture () ; + + +ssgaFire::~ssgaFire () +{ + tableSize = 0 ; + delete [] colourTable ; + delete [] sizeTable ; +} + + + + +static unsigned char fuzzyBlob [] = +{ + 0,0,0,0,0,0,0,0,0,0,0,0,1,3,4,5,5,4,3,1,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,1,5,9,14,17,19,20,20,20,17,14,10,5,1,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,1,5,12,19,25,29,33,35,36,37,36,33,30,25,20,13,6,1,0,0,0,0,0,0,0, + 0,0,0,0,0,0,2,10,19,27,34,40,45,48,51,52,53,51,49,45,40,35,28,20,11,3,0,0,0,0,0,0, + 0,0,0,0,0,4,13,23,33,41,48,55,60,64,67,69,69,67,65,61,56,49,42,34,25,15,5,0,0,0,0,0, + 0,0,0,0,4,14,26,36,46,55,63,70,75,80,83,85,85,83,80,76,70,64,56,47,37,27,16,5,0,0,0,0, + 0,0,0,2,13,26,37,48,59,68,77,84,91,95,99,101,101,99,96,91,85,78,69,60,50,39,27,15,3,0,0,0, + 0,0,1,10,23,36,48,60,71,81,90,99,105,111,115,117,117,115,111,106,100,92,82,72,61,50,38,25,12,1,0,0, + 0,0,5,19,33,46,59,71,83,94,104,113,120,126,130,133,133,131,127,121,114,105,95,84,72,60,47,34,21,7,0,0, + 0,1,12,27,41,55,68,81,94,105,116,126,134,141,146,149,149,147,142,135,127,118,107,95,83,70,56,43,29,14,2,0, + 0,5,19,34,48,63,77,90,104,116,128,139,148,156,162,165,165,162,157,149,140,129,118,105,92,78,64,50,36,21,6,0, + 0,9,25,40,55,70,84,99,113,126,139,151,161,170,177,181,181,178,171,163,152,140,128,114,100,86,72,57,42,27,11,0, + 1,14,29,45,60,75,91,105,120,134,148,161,173,184,192,196,197,193,185,175,163,150,136,122,107,92,77,62,47,31,16,2, + 3,17,33,48,64,80,95,111,126,141,156,170,184,196,206,212,212,207,197,185,172,158,143,128,113,97,82,66,50,35,19,4, + 4,19,35,51,67,83,99,115,130,146,162,177,192,206,219,227,228,220,208,194,179,163,148,132,117,101,85,69,53,37,21,5, + 5,20,36,52,69,85,101,117,133,149,165,181,196,212,227,241,242,229,214,198,182,167,151,135,119,103,87,71,54,38,22,6, + 5,20,37,53,69,85,101,117,133,149,165,181,197,212,228,242,243,230,214,199,183,167,151,135,119,103,87,71,55,39,22,6, + 4,20,36,51,67,83,99,115,131,147,162,178,193,207,220,229,230,221,209,194,179,164,148,133,117,101,85,69,53,38,22,6, + 3,17,33,49,65,80,96,111,127,142,157,171,185,197,208,214,214,209,199,187,173,159,144,129,113,98,82,67,51,35,19,4, + 1,14,30,45,61,76,91,106,121,135,149,163,175,185,194,198,199,194,187,176,164,151,137,123,108,93,78,63,47,32,16,2, + 0,10,25,40,56,70,85,100,114,127,140,152,163,172,179,182,183,179,173,164,154,142,129,115,101,87,72,57,42,27,12,1, + 0,5,20,35,49,64,78,92,105,118,129,140,150,158,163,167,167,164,159,151,142,131,119,106,93,79,65,51,36,22,7,0, + 0,1,13,28,42,56,69,82,95,107,118,128,136,143,148,151,151,148,144,137,129,119,108,96,84,71,57,44,30,15,2,0, + 0,0,6,20,34,47,60,72,84,95,105,114,122,128,132,135,135,133,129,123,115,106,96,85,74,61,49,35,22,8,0,0, + 0,0,1,11,25,37,50,61,72,83,92,100,107,113,117,119,119,117,113,108,101,93,84,74,63,51,39,26,13,2,0,0, + 0,0,0,3,15,27,39,50,60,70,78,86,92,97,101,103,103,101,98,93,87,79,71,61,51,40,28,16,4,0,0,0, + 0,0,0,0,5,16,27,38,47,56,64,72,77,82,85,87,87,85,82,78,72,65,57,49,39,28,17,6,0,0,0,0, + 0,0,0,0,0,5,15,25,34,43,50,57,62,66,69,71,71,69,67,63,57,51,44,35,26,16,6,0,0,0,0,0, + 0,0,0,0,0,0,3,12,21,29,36,42,47,50,53,54,55,53,51,47,42,36,30,22,13,4,0,0,0,0,0,0, + 0,0,0,0,0,0,0,1,7,14,21,27,31,35,37,38,39,38,35,32,27,22,15,8,2,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,2,6,11,16,19,21,22,22,22,19,16,12,7,2,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,2,4,5,6,6,6,4,2,1,0,0,0,0,0,0,0,0,0,0,0 +} ; + + +unsigned char *_ssgaGetFireTexture () { return fuzzyBlob ; } + diff --git a/src/ssgAux/ssgaFire.h b/src/ssgAux/ssgaFire.h new file mode 100644 index 0000000..5ac4b0f --- /dev/null +++ b/src/ssgAux/ssgaFire.h @@ -0,0 +1,77 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net */ + + + +#include "ssgAux.h" + + +class ssgaFire : public ssgaParticleSystem +{ + int tableSize ; + float *colourTable ; + float *sizeTable ; + + sgVec4 hot_colour ; + float max_ttl ; + float start_size ; + float upward_speed ; + float radius ; + + void reInit () ; + +public: + + void createParticle ( int idx, ssgaParticle *p ) ; + void updateParticle ( int idx, ssgaParticle *p ) ; + + ssgaFire ( int num_tris, float _radius = 1.0f, + float height = 5.0f, + float speed = 2.0f ) ; + + virtual ~ssgaFire () ; + + virtual void update ( float t ) ; + + void setUpwardSpeed ( float spd ) + { + upward_speed = spd ; + } + + void setHeight ( float hgt ) + { + max_ttl = hgt / upward_speed ; + getBSphere () -> setRadius ( hgt * 2.0f ) ; + getBSphere () -> setCenter ( 0, 0, 0 ) ; + reInit () ; + } + + void setHotColour ( sgVec4 col ) + { + sgCopyVec4 ( hot_colour, col ) ; + reInit () ; + } + + void getHotColour ( sgVec4 col ) { sgCopyVec4 ( col, hot_colour ) ; } + +} ; + +unsigned char *_ssgaGetFireTexture () ; + diff --git a/src/ssgAux/ssgaLensFlare.cxx b/src/ssgAux/ssgaLensFlare.cxx new file mode 100644 index 0000000..caa32b2 --- /dev/null +++ b/src/ssgAux/ssgaLensFlare.cxx @@ -0,0 +1,330 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + +*/ + +#include "ssgAux.h" + +#undef _SSG_PUBLIC +#include "../ssg/ssgLocal.h" + +/* + Lens flares are an effect that happens in the + lens - your eye or a camera lens. As such, they + are completely invisible if the light itself is + not visible - which should mean that if the light + is culled then so is the lens flare. This suggests + that the bsphere center should be at the light point + and the radius should be tiny. + + However, if you have a multi-facetted display, + pretending to be a single display rather than + a lot of separate 'cameras' then you may want to + set the SSGA_CONTINUOUS_DISPLAY_SURFACE flag. + + This should probably be realtime settable - but + to do it 'right', you'd need to know which edges + of the screen were 'shared' with other screens + and only allow the lens flare to cross those. +*/ + +// #define CONTINUOUS_DISPLAY_SURFACE 1 + + + + +sgMat4 _ssgaIdentity = +{ + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 1.0f } +} ; + +/* + This is based on code written by Stephen Coy - subsequently + re-written by Mark Kilgard - and now re-re-written by me. + Actually, only the original numbers for the dimensions of + the flare planes are from the original code. All the rest + is a complete rewrite because it has to work within a scene + graph API. +*/ + +struct _ssgaFlarePlane +{ + int type ; /* flare texture index, 0..5 */ + float loc ; /* postion on flare_axis */ + float scale ; + sgVec4 color ; +} ; + + +static _ssgaFlarePlane flare [] = +{ + { -1, 0.00f, 0.20f, { 0 , 0, 1, 1 }}, + { -1, 0.00f, 0.10f, { 0 , 1, 0, 1 }}, + { -1, 0.00f, 0.12f, { 1.0f, 0, 0, 1 }}, + { 1, 0.50f, 0.20f, { 0.3f, 0, 0, 1 }}, + { 2, -0.20f, 0.04f, { 0.6f, 0, 0, 1 }}, + { 3, 0.00f, 0.10f, { 0.4f, 0, 0, 1 }}, + { 3, 0.30f, 0.03f, { 0.3f, 0, 0, 1 }}, + { 3, 0.80f, 0.05f, { 0.3f, 0, 0, 1 }}, + { 0, 1.00f, 0.04f, { 0.3f, 0, 0, 1 }}, + { 4, 1.25f, 0.07f, { 0.5f, 0, 0, 1 }}, + { 5, 1.40f, 0.02f, { 0.6f, 0, 0, 1 }}, + { 5, 1.60f, 0.04f, { 0.4f, 0, 0, 1 }}, + { 5, 2.00f, 0.03f, { 0.2f, 0, 0, 1 }}, + { -999, 0, 0, { 0, 0, 0, 0 } } /* End marker */ +} ; + + +static float shineTexCoords [ 12 ][ 4 ][ 2 ] = +{ + { { 0.00, 0.00 }, { 0.25, 0.00 }, { 0.25, 0.50 }, { 0.00, 0.50 } }, + { { 0.25, 0.00 }, { 0.50, 0.00 }, { 0.50, 0.50 }, { 0.25, 0.50 } }, + { { 0.50, 0.00 }, { 0.75, 0.00 }, { 0.75, 0.50 }, { 0.50, 0.50 } }, + { { 0.00, 0.50 }, { 0.25, 0.50 }, { 0.25, 0.00 }, { 0.00, 0.00 } }, + { { 0.25, 0.50 }, { 0.50, 0.50 }, { 0.50, 0.00 }, { 0.25, 0.00 } }, + { { 0.50, 0.50 }, { 0.75, 0.50 }, { 0.75, 0.00 }, { 0.50, 0.00 } }, + { { 0.25, 0.00 }, { 0.00, 0.00 }, { 0.00, 0.50 }, { 0.25, 0.50 } }, + { { 0.50, 0.00 }, { 0.25, 0.00 }, { 0.25, 0.50 }, { 0.50, 0.50 } }, + { { 0.75, 0.00 }, { 0.50, 0.00 }, { 0.50, 0.50 }, { 0.75, 0.50 } }, + { { 0.25, 0.50 }, { 0.00, 0.50 }, { 0.00, 0.00 }, { 0.25, 0.00 } }, + { { 0.50, 0.50 }, { 0.25, 0.50 }, { 0.25, 0.00 }, { 0.50, 0.00 } }, + { { 0.75, 0.50 }, { 0.50, 0.50 }, { 0.50, 0.00 }, { 0.75, 0.00 } } +} ; + + +static float flareTexCoords [ 6 ][ 4 ][ 2 ] = +{ + { { 0.00f, 0.50f }, { 0.25f, 0.50f }, { 0.25f, 1.00f }, { 0.00f, 1.00f } }, + { { 0.25f, 0.50f }, { 0.50f, 0.50f }, { 0.50f, 1.00f }, { 0.25f, 1.00f } }, + { { 0.27f, 0.70f }, { 0.48f, 0.70f }, { 0.48f, 0.80f }, { 0.27f, 0.80f } }, + { { 0.50f, 0.50f }, { 0.75f, 0.50f }, { 0.75f, 1.00f }, { 0.50f, 1.00f } }, + { { 0.75f, 0.50f }, { 1.00f, 0.50f }, { 1.00f, 1.00f }, { 0.75f, 1.00f } }, + { { 0.75f, 0.00f }, { 1.00f, 0.00f }, { 1.00f, 0.50f }, { 0.75f, 0.50f } } +} ; + + +void ssgaLensFlare::copy_from ( ssgaLensFlare *src, int clone_flags ) +{ + ssgaShape::copy_from ( src, clone_flags ) ; +} + +ssgBase *ssgaLensFlare::clone ( int clone_flags ) +{ + ssgaLensFlare *b = new ssgaLensFlare ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgaLensFlare::ssgaLensFlare (void):ssgaShape () +{ + type = ssgaTypeLensFlare () ; + regenerate () ; +} + +ssgaLensFlare::ssgaLensFlare (int nt):ssgaShape (nt) +{ + type = ssgaTypeLensFlare () ; + regenerate () ; +} + +ssgaLensFlare::~ssgaLensFlare (void) {} + +static ssgSimpleState *flareState = NULL ; +static ssgTexture *flareTexture = NULL ; + +const char *ssgaLensFlare::getTypeName(void) { return "ssgaLensFlare" ; } + +static int preDraw ( ssgEntity * ) +{ + glDisable ( GL_DEPTH_TEST ) ; + glBlendFunc ( GL_ONE, GL_ONE ) ; + return TRUE ; +} + + +static int postDraw ( ssgEntity * ) +{ + glEnable ( GL_DEPTH_TEST ) ; + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; + return TRUE ; +} + + +void ssgaLensFlare::regenerate () +{ + if ( kidState != NULL ) kidState -> ref () ; + removeAllKids () ; + if ( kidState != NULL ) kidState -> deRef () ; + + for ( ntriangles = 0 ; flare[ntriangles/2].type >= -1 ; ntriangles += 2 ) + /* Count the number of triangles */ ; + + vt = new ssgVtxTable () ; + v0 = new ssgVertexArray ( 2 * ntriangles ) ; + n0 = new ssgNormalArray ( 2 * ntriangles ) ; + c0 = new ssgColourArray ( 2 * ntriangles ) ; + t0 = new ssgTexCoordArray ( 2 * ntriangles ) ; + + vt -> setPrimitiveType ( GL_QUADS ) ; + + addKid ( vt ) ; + + if ( flareState == NULL ) + { + /* + The texture constructor deletes the texture from + main memory after it's finished with it!! YIKES!! + */ + + unsigned char *t = new unsigned char [ 256 * 128 ] ; + memcpy ( t, _ssgaGetLensFlareTexture(), 256 * 128 ) ; + + flareTexture = new ssgTexture ( "NONE", t, 256, 128, 1 ) ; + + flareState = new ssgSimpleState () ; + flareState -> setTexture ( flareTexture ) ; + flareState -> setTranslucent () ; + flareState -> enable ( GL_TEXTURE_2D ) ; + flareState -> enable ( GL_BLEND ) ; + flareState -> disable ( GL_LIGHTING ) ; + flareState -> ref () ; + setKidState ( flareState ) ; + } + + + vt -> setState ( getKidState () ) ; + vt -> setCallback ( SSG_CALLBACK_PREDRAW , preDraw /* getKidPreDrawCB */ ); + vt -> setCallback ( SSG_CALLBACK_POSTDRAW, postDraw /* getKidPostDrawCB*/ ); + + sgVec3 v ; sgVec3 n ; sgVec2 t ; sgVec4 c ; + + for ( int i = 0 ; i < ntriangles * 2 ; i++ ) + { + sgSetVec3 ( v, 0, 0, 0 ) ; v0->add ( v ) ; + sgSetVec3 ( n, 0, -1, 0 ) ; n0->add ( n ) ; + sgSetVec4 ( c, 1,1,1,1 ) ; c0->add ( c ) ; + sgSetVec2 ( t, 0, 0 ) ; t0->add ( t ) ; + } + + vt -> setVertices ( v0 ) ; + vt -> setNormals ( n0 ) ; + vt -> setColours ( c0 ) ; + vt -> setTexCoords ( t0 ) ; + +#ifndef CONTINUOUS_DISPLAY_SURFACE + vt -> getBSphere () -> setCenter ( 0, 0, 0 ) ; + vt -> getBSphere () -> setRadius ( 0.1f ) ; + getBSphere () -> setCenter ( 0, 0, 0 ) ; + getBSphere () -> setRadius ( 0.1f ) ; +#else + vt -> recalcBSphere () ; + recalcBSphere () ; +#endif +} + + +void ssgaLensFlare::update ( sgMat4 mat ) +{ + static int shine_tic = 0 ; + + sgVec3 flare_axis ; + + float *texCoords ; + + sgVec3 light_pos ; + float znear ; + + ssgGetNearFar ( & znear, NULL ) ; + sgNormalizeVec3 ( light_pos, mat[3] ) ; + sgScaleVec3 ( light_pos, znear * 2.0f ) ; /* To avoid being near-clipped */ + + sgSetVec3 ( flare_axis, -light_pos[0], -light_pos[1], 0.0 ) ; + + int vv = 0 ; + + for ( int i = 0 ; flare[ i ].type >= -1 ; i++ ) + { + sgVec3 position ; + float sz ; + + sz = flare[i].scale * znear * 2.0f ; + + sgAddScaledVec3 ( position, light_pos, flare_axis, flare[i].loc ) ; + + if ( flare[i].type < 0 ) + { + shine_tic = (shine_tic + 1) % 12 ; + + texCoords = & ( shineTexCoords [ shine_tic ][ 0 ][ 0 ] ) ; + } + else + texCoords = & ( flareTexCoords [ flare[i].type ][ 0 ][ 0 ] ) ; + + sgVec3 vx ; + + sgSetVec3 ( vx, position[0]+sz, position[1]-sz, position[2] ) ; + c0 -> set ( flare[i].color, vv ) ; + t0 -> set ( & texCoords[0], vv ) ; + v0 -> set ( vx, vv++ ) ; + + sgSetVec3 ( vx, position[0]+sz, position[1]+sz, position[2] ) ; + c0 -> set ( flare[i].color, vv ) ; + t0 -> set ( & texCoords[2], vv ) ; + v0 -> set ( vx, vv++ ) ; + + sgSetVec3 ( vx, position[0]-sz, position[1]+sz, position[2] ) ; + c0 -> set ( flare[i].color, vv ) ; + t0 -> set ( & texCoords[4], vv ) ; + v0 -> set ( vx, vv++ ) ; + + sgSetVec3 ( vx, position[0]-sz, position[1]-sz, position[2] ) ; + c0 -> set ( flare[i].color, vv ) ; + t0 -> set ( & texCoords[6], vv ) ; + v0 -> set ( vx, vv++ ) ; + } +} + + +void ssgaLensFlare::cull ( sgFrustum *f, sgMat4 m, int /* test_needed */ ) +{ + /* + Lens flares are best generated in eye-space (because they actually + occur inside the lens of your eye). Hence we call 'update' with + the current modelview matrix - it generates the geometry in eye-space - + which means that we have to render it with the identity matrix on the + stack. + */ + + update ( m ) ; + + _ssgPushMatrix ( _ssgaIdentity ) ; + + glPushMatrix () ; + glLoadMatrixf ( (float *) _ssgaIdentity ) ; + ssgBranch::cull ( f, _ssgaIdentity, FALSE ) ; + glPopMatrix () ; + + _ssgPopMatrix () ; +} + diff --git a/src/ssgAux/ssgaLensFlare.h b/src/ssgAux/ssgaLensFlare.h new file mode 100644 index 0000000..10b1be0 --- /dev/null +++ b/src/ssgAux/ssgaLensFlare.h @@ -0,0 +1,52 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net */ + + + +#include "ssgaShapes.h" + +class ssgaLensFlare : public ssgaShape +{ + ssgVtxTable *vt ; + ssgVertexArray *v0 ; + ssgNormalArray *n0 ; + ssgColourArray *c0 ; + ssgTexCoordArray *t0 ; + + void update ( sgMat4 m ) ; + +protected: + virtual void copy_from ( ssgaLensFlare *src, int clone_flags ) ; +public: + + ssgaLensFlare () ; + ssgaLensFlare ( int nt ) ; + + virtual ~ssgaLensFlare () ; + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + virtual void regenerate () ; + virtual const char *getTypeName ( void ) ; + virtual void cull ( sgFrustum *f, sgMat4 m, int test_needed ) ; +} ; + +unsigned char *_ssgaGetLensFlareTexture () ; + + diff --git a/src/ssgAux/ssgaLensFlareTexture.cxx b/src/ssgAux/ssgaLensFlareTexture.cxx new file mode 100644 index 0000000..741ec20 --- /dev/null +++ b/src/ssgAux/ssgaLensFlareTexture.cxx @@ -0,0 +1,2076 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + +*/ + +static unsigned char lens_flare_texture [] = +{ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,2,12,19,24,30,36,36, +35,26,20,12,3,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,10,29,54,77,96,112,123,131,135,137, +132,126,113,99,81,60,35,14,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,24,60,92,124,149,173,191,207,222,228,231,231, +229,224,214,199,177,155,131,100,68,32,7,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,4,30,73,114,151,187,219,233,242,239,235,231,227,227,227, +227,229,234,238,242,235,225,195,162,123,84,39,7,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +20,68,116,162,204,233,241,233,225,218,212,207,204,202,201,201, +201,203,206,211,217,223,231,240,237,214,172,128,81,30,3,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,46, +101,154,203,238,238,227,216,207,199,193,187,182,179,177,175,175, +176,178,182,186,191,197,205,214,224,235,239,215,166,115,60,11, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,12,66,128, +183,229,239,226,214,202,192,183,176,169,164,159,157,153,152,152, +153,156,159,163,168,174,181,189,199,210,222,236,239,197,141,82, +24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,8, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,21,81,143,207, +240,231,216,202,190,180,170,161,154,148,143,139,135,134,133,133, +134,135,136,142,147,152,160,168,177,187,199,212,227,241,220,159, +97,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,15, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,16,3,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,24,89,156,221,241, +225,209,194,180,170,158,149,142,134,128,124,120,119,114,113,112, +114,118,120,123,128,133,140,147,156,166,178,190,203,219,236,231, +173,107,36,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, +0,7,0,0,0,12,0,0,0,0,0,0,9,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,12,10,2,3,6,0,12, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,21,89,159,224,237,219, +203,187,172,162,149,139,131,124,118,112,106,104,102,96,96,96, +96,99,104,105,112,116,122,129,138,147,157,171,185,197,214,234, +236,178,107,34,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,3, +0,0,0,0,5,21,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0, +3,0,0,0,7,10,0,0,0,0,0,11,10,0,0,2, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,8,21,5,8,12,2,16, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,12,81,156,224,236,218,199, +182,170,155,142,131,124,114,108,102,96,90,88,86,82,80,80, +82,84,88,90,96,99,106,112,122,130,139,153,163,179,195,211, +231,237,174,102,27,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,30,33, +0,0,0,0,14,20,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,2, +0,0,0,0,0,0,0,0,0,0,0,0,0,16,11,19, +26,12,0,0,17,10,0,0,0,0,5,22,2,0,0,10, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,0,0,0,0,0,0,21,10,21,15,7,36, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,8, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,5,66,143,221,237,218,197,179, +163,150,139,126,116,108,100,93,87,81,79,73,72,71,70,70, +70,72,72,76,80,86,91,98,106,115,124,133,147,163,179,195, +211,233,231,165,88,14,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,10,0,0,0,0,0,18,40, +0,0,0,0,32,17,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,3,13,5, +8,0,0,0,0,0,0,0,0,0,0,0,0,17,11,23, +50,58,0,0,20,3,0,0,0,0,25,9,0,5,13,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,7,7,0,0,0,0,0,23,18,26,19,9,48, +0,0,0,0,0,3,12,0,0,0,0,0,0,8,8,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,46,128,207,241,219,199,179,163, +147,134,124,113,102,93,86,79,73,68,64,63,58,57,56,56, +56,58,62,64,68,72,79,85,91,100,109,122,131,147,163,179, +195,213,235,223,145,66,5,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,2,0,0,19,8,0,0,0,0,34,55, +0,0,0,10,49,10,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0, +13,16,0,0,0,0,0,0,0,0,0,0,0,14,14,30, +39,24,0,11,28,0,12,2,0,17,24,0,3,25,5,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,18,7,0,0,0,0,16,32,36,38,17,20, +0,0,0,0,0,14,11,0,0,11,6,0,13,26,3,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,20,101,183,240,225,203,182,163,147, +133,123,109,99,89,81,73,68,63,57,55,50,48,48,46,46, +47,48,49,53,56,60,65,72,79,87,97,107,117,131,147,163, +179,197,219,241,204,123,36,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,6,6,0,10,21,0,0,3,3,25,62, +0,0,0,27,56,3,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,2,8,3,0,0, +23,28,19,2,0,0,0,14,2,0,0,0,0,16,23,9, +53,30,0,21,21,4,11,0,6,36,5,4,23,7,0,0, +0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,4,27,5,0,0,0,3,42,39,55,26,52, +0,0,0,0,0,27,4,0,3,12,0,9,32,5,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,4,68,154,229,231,209,187,170,150,134, +123,108,98,87,78,70,63,57,52,47,43,41,39,38,37,36, +38,39,40,43,47,51,55,62,68,76,85,94,107,117,131,147, +163,181,203,225,241,174,90,12,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, +8,0,0,0,0,0,13,3,0,30,10,0,8,12,18,70, +0,0,6,61,47,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,3,15,11,0, +6,32,37,24,8,0,0,12,15,0,0,0,0,19,41,24, +78,50,0,38,15,21,10,0,35,18,3,33,17,0,0,0, +3,11,3,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,16,28,2,0,0,0,35,41,68,40,62, +0,0,0,0,13,27,0,3,17,2,6,38,10,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,30,116,203,239,216,194,172,155,139,124, +109,98,85,77,68,60,54,47,43,39,35,33,31,30,28,28, +29,30,32,35,37,41,47,52,58,66,74,83,93,107,120,133, +149,170,188,210,233,223,138,51,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +10,13,3,0,0,0,3,26,3,18,28,0,9,29,22,118, +6,3,35,93,24,0,0,6,0,0,3,16,9,22,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,3,16,23, +3,7,37,32,46,15,0,7,34,5,0,0,0,10,44,55, +82,42,5,44,7,29,0,25,36,3,34,23,0,0,0,13, +15,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,29,23,0,0,0,22,53,87,62,62, +5,0,10,0,29,15,0,21,16,5,39,18,0,0,0,0, +0,0,3,15,6,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,4,73,162,238,226,202,180,162,142,126,113, +99,87,77,67,58,51,45,39,35,31,28,26,23,22,22,22, +22,23,25,28,30,35,38,43,50,56,64,74,85,96,108,124, +139,155,175,196,220,241,184,95,14,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,13,27,5,0,0,0,17,25,3,38,9,2,50,34,130, +19,11,90,101,6,0,10,13,0,0,14,20,38,9,0,0, +0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17, +33,10,6,43,58,62,15,3,44,39,0,6,7,3,50,65, +92,44,23,39,24,21,8,49,7,30,33,0,0,6,21,22, +3,2,5,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,11,6,0,0, +0,4,17,3,0,0,4,42,14,0,0,5,55,94,84,72, +30,14,18,7,43,3,10,34,6,40,26,0,4,5,0,0, +3,25,24,8,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,24,114,204,238,214,190,170,149,131,116,102, +89,78,68,58,50,43,37,32,28,25,21,20,18,18,16,16, +17,18,20,21,24,27,31,37,42,48,56,65,75,87,99,114, +129,146,164,186,208,232,225,136,45,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,12,35,12,0,0,2,35,27,30,33,0,59,53,149, +21,24,132,82,0,4,24,5,16,26,26,37,11,0,0,0, +0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +10,37,23,8,49,78,72,12,22,76,21,11,18,6,52,86, +104,45,39,32,43,5,44,26,29,43,3,4,14,38,19,3, +13,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,12,21,7, +0,0,7,26,9,0,0,12,44,6,0,0,48,101,113,84, +48,19,14,30,28,3,39,13,38,36,0,8,16,3,0,20, +47,30,3,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,60,151,233,227,202,180,158,139,124,108,93, +81,70,60,51,43,37,32,27,21,20,17,14,12,12,12,12, +12,12,13,16,19,21,26,29,35,42,49,58,67,79,91,104, +120,135,154,174,196,220,241,175,83,5,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,7,38,22,0,0,9,53,31,51,7,53,72,149, +68,54,161,51,0,27,16,19,54,77,67,11,0,0,0,0, +10,21,12,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,4,33,41,12,52,96,82,11,65,79,12,32,19,50,102, +119,48,57,40,32,29,48,26,50,6,13,42,43,15,14,24, +10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,25, +20,5,0,5,32,17,3,3,30,43,0,0,30,101,133,86, +77,44,21,58,13,28,34,34,48,3,20,28,3,14,52,58, +16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,10,92,187,241,216,192,170,149,131,114,100,86, +73,63,54,45,37,32,27,21,19,13,12,11,10,5,4,4, +4,10,11,12,13,16,20,24,29,35,43,51,60,71,83,96, +111,128,144,164,186,210,235,211,116,22,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,5,40,31,3,0,28,72,53,36,38,93,138, +58,88,166,20,18,35,28,77,101,78,9,0,0,0,11,28, +24,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,25,50,27,55,117,88,24,118,53,37,46,49,130, +161,61,61,51,22,60,34,58,12,27,56,44,18,30,24,3, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2, +17,33,21,3,5,38,41,27,6,48,31,0,12,96,147,98, +104,66,54,60,13,51,35,56,10,32,30,23,53,75,42,5, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,29,124,219,233,207,183,161,142,124,108,93,79, +68,57,47,39,32,27,21,19,13,12,8,4,0,0,0,0, +0,0,2,6,11,12,16,20,25,31,37,45,55,65,76,89, +104,120,136,156,177,201,226,233,147,52,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,5,43,46,6,2,59,78,70,32,99,137, +91,135,124,5,44,38,97,128,80,9,0,0,11,33,33,10, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,14,52,44,66,131,90,66,134,63,70,62,154, +195,80,71,51,55,52,63,31,56,80,50,42,40,13,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, +0,5,31,42,16,4,37,59,40,14,61,16,0,72,171,127, +125,83,94,41,51,47,63,19,44,46,64,91,69,17,0,0, +0,0,7,7,12,2,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,54,149,233,225,199,176,154,134,118,102,87,73, +63,52,43,35,28,21,19,13,11,5,0,0,0,0,0,0, +0,0,0,0,4,11,12,16,21,27,33,41,49,60,71,83, +97,112,129,150,170,193,218,242,173,78,3,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,5,56,66,18,36,98,100,66,103,163, +131,166,67,34,56,115,153,84,7,0,12,38,42,21,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0, +0,0,0,0,8,26,52,62,77,176,109,121,119,103,83,171, +205,114,85,58,73,70,51,96,100,73,73,32,3,0,0,0, +0,0,4,6,13,14,2,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,2,8,13,12, +5,0,0,15,45,40,14,32,75,55,36,63,7,41,176,166, +149,104,99,43,67,72,36,64,80,116,107,38,3,0,0,7, +18,26,22,6,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,2,77,173,242,218,193,169,148,128,112,96,81,68, +57,47,39,31,25,20,13,12,5,0,0,0,0,0,0,0, +0,0,0,0,0,4,11,13,19,23,29,37,45,55,65,79, +92,106,125,143,163,187,212,238,197,102,13,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,9,63,88,45,75,135,120,110,210, +165,161,45,75,138,189,84,6,7,38,53,27,3,0,0,0, +0,0,0,0,3,13,10,9,12,4,0,0,0,0,0,0, +0,0,0,0,0,0,0,2,10,19,19,12,9,0,0,0, +4,14,11,3,0,14,38,66,81,110,188,133,155,137,118,178, +212,135,85,84,85,80,125,118,94,66,14,0,0,0,0,14, +22,30,19,6,3,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,15, +27,30,18,5,3,28,54,39,35,92,78,60,52,20,163,213, +181,125,82,80,89,84,103,139,144,75,13,0,16,34,45,41, +26,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,12,96,191,239,212,187,164,143,124,106,90,79,64, +55,43,35,28,21,17,12,8,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,5,12,14,20,27,33,41,51,63,73, +88,104,120,136,158,181,205,233,216,120,24,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,8,7,3,0,0,0,0,5,58,116,83,122,169,145,227, +189,133,75,150,202,80,12,39,60,35,6,0,0,0,0,0, +11,22,26,36,36,27,10,5,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,3,11,23,34,41,49,42, +25,10,12,26,30,22,12,37,88,115,141,189,179,188,166,193, +224,145,109,114,113,160,139,92,35,2,0,5,21,33,44,34, +18,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,5,6,2,0,0,0, +0,13,29,43,35,20,10,44,64,52,101,107,87,37,130,246, +205,144,97,118,137,181,178,125,35,19,51,87,96,71,36,6, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,19,112,207,235,207,182,159,139,120,104,88,73,63, +50,41,33,26,20,14,11,4,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,2,10,12,19,24,31,39,48,58,72, +84,98,116,134,154,176,202,227,228,135,39,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,5,8,24,32,22,15,2,0,2,48,133,145,195,200,223, +213,126,157,189,77,49,76,48,9,0,0,5,22,28,44,48, +46,33,21,12,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,6,12,36,61, +85,95,78,56,48,49,65,57,47,78,135,181,226,235,224,217, +239,172,151,151,185,142,62,9,12,28,48,53,42,23,6,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,5,10,20,24,20,16, +16,12,0,4,21,43,56,40,39,64,78,126,141,102,92,235, +242,159,151,185,227,180,93,67,107,137,121,72,26,9,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,24,123,222,231,204,179,157,135,119,102,86,72,58, +48,39,31,23,18,12,10,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,6,12,17,22,29,37,46,56,68, +80,96,112,131,151,174,197,224,232,147,49,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,3,2,3,10,6,9,2, +0,0,0,0,10,22,40,53,56,44,22,28,130,225,243,241, +221,187,188,108,110,117,58,42,48,58,68,67,65,45,36,16, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,5,16,35,25,50,36,57, +54,61,75,93,107,100,92,95,102,90,90,146,225,251,251,247, +247,224,211,203,122,48,40,69,93,86,68,40,27,16,10,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,3,11,13, +26,46,50,56,46,32,34,41,60,67,81,116,154,177,137,213, +246,219,233,222,171,147,160,151,105,44,13,3,9,10,0,2, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,30,131,228,227,202,177,153,134,114,96,82,71,57, +48,38,30,22,18,12,5,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,12,14,20,28,36,45,56,66, +80,96,112,128,149,171,195,220,236,155,57,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,3,2,3,16,16,44,34, +59,72,64,66,61,50,42,39,54,83,107,107,85,149,237,251, +246,227,183,204,187,153,157,154,143,117,89,51,38,23,16,6, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,5,13,10,38,24,70, +94,105,122,129,139,140,154,158,158,163,173,171,190,235,251,251, +251,246,201,136,133,151,141,135,109,79,50,26,13,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,10,38,58,88,119,123,107,105,108,144,191,223,231,236, +251,251,245,216,192,153,89,47,38,43,36,32,22,13,0,2, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,36,135,231,227,201,175,152,133,113,96,80,70,56, +46,37,28,22,16,12,4,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,12,14,20,28,34,44,54,64, +80,96,112,128,148,169,194,219,239,161,61,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +16,31,44,59,76,88,102,114,124,129,147,204,230,221,242,251, +251,245,249,232,194,169,141,98,70,63,44,21,18,16,3,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,15,27,38,50,75,93,105,130,164,184,205,229,249,251, +251,242,200,189,179,118,61,27,3,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,18, +18,18,18,24,30,30,47,70,97,121,135,169,237,251,251,251, +251,251,251,249,212,160,142,127,124,114,98,79,74,39,19,24, +33,26,16,3,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,36,137,231,227,201,175,152,133,112,96,80,70,56, +46,36,28,22,16,12,4,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,12,14,20,27,34,44,54,64, +80,96,112,128,148,169,193,219,239,162,61,0,0,0,0,0, +0,0,0,0,0,0,0,0,6,6,0,0,0,0,0,6, +35,35,40,63,73,68,84,116,127,139,170,214,243,251,251,251, +251,247,212,157,129,129,142,150,138,125,106,57,47,59,43,24, +10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,3,17,29,60,89,120,144,174,203,215,239,245, +251,247,214,165,113,64,42,27,8,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,18, +18,18,20,37,53,56,64,88,120,139,180,219,248,251,251,251, +251,251,242,243,243,208,181,166,151,130,117,102,83,68,57,48, +47,24,16,3,0,0,4,0,0,0,0,0,0,0,0,0, +0,0,0,35,132,229,227,201,176,153,134,114,96,82,70,56, +47,38,29,22,17,12,4,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,12,14,20,28,35,44,55,65, +80,96,112,128,149,170,195,220,238,156,59,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,3,27,41,56,76,106,158,193,193,183,210,248,251,251, +251,235,240,208,159,96,46,23,18,25,28,26,25,30,33,29, +36,18,16,24,0,2,3,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5, +23,42,67,88,112,154,163,202,237,247,232,189,150,177,163,218, +251,250,231,175,125,103,96,94,87,82,62,45,30,11,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,6,7,22, +31,36,42,44,51,50,57,85,132,167,212,211,215,213,232,251, +251,251,229,170,155,147,143,134,135,129,124,104,82,65,37,25, +9,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,26,126,224,229,203,178,156,135,118,99,84,72,58, +48,39,30,23,18,12,10,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,12,17,22,28,36,46,56,68, +80,96,112,129,151,172,196,223,233,150,51,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,6, +18,26,29,48,62,75,96,107,109,106,113,137,214,245,239,251, +251,206,153,179,174,145,122,102,64,32,12,0,0,0,0,0, +0,0,0,6,0,2,3,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,2,8,10,25,42,68,80, +99,114,117,122,122,140,150,170,158,127,76,91,162,107,109,191, +247,244,194,148,124,78,49,42,40,42,47,58,76,79,55,30, +14,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,6,7,12, +11,3,0,0,6,31,60,102,128,126,128,147,137,171,245,251, +245,239,243,175,104,58,58,61,52,53,56,47,45,52,42,36, +23,16,3,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,20,113,214,234,206,182,159,136,120,104,88,72,62, +49,40,32,25,20,13,11,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,10,12,18,23,30,39,48,57,71, +82,98,114,134,152,176,200,227,231,137,40,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,6, +15,21,38,50,43,28,32,49,68,79,101,143,215,204,214,218, +233,237,112,75,130,136,111,81,88,82,68,49,26,11,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,2,2,20,18,14,24,28,31,30, +40,48,77,96,94,81,64,43,18,22,101,153,80,30,132,158, +229,203,192,94,76,100,72,37,18,16,14,0,0,4,18,19, +21,21,20,9,4,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,14,32,52,71,82,65,58,80,84,52,110,209,234,221, +226,199,225,189,123,86,38,12,14,18,14,10,9,4,0,0, +6,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,12,99,199,238,211,186,163,142,123,105,90,76,64, +53,43,35,28,21,16,12,6,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,4,12,14,20,26,33,41,49,61,72, +88,104,120,136,158,180,204,231,223,124,24,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,12, +23,15,14,3,12,37,53,48,59,62,83,145,174,141,222,157, +159,225,158,35,48,88,97,99,63,49,60,60,50,44,38,20, +8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,3,8,21,43, +48,57,52,27,14,0,2,3,35,100,106,40,3,78,94,152, +238,153,181,127,56,28,60,61,43,21,3,0,0,0,0,0, +0,0,0,3,4,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8, +18,18,37,57,52,33,20,35,56,26,8,68,131,165,178,144, +174,173,152,192,135,88,71,34,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,3,81,177,242,217,191,168,147,128,112,96,80,68, +56,47,37,30,24,19,13,11,4,0,0,0,0,0,0,0, +0,0,0,0,0,2,11,12,18,22,29,35,45,55,64,78, +90,106,123,142,163,185,210,236,202,105,16,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,2, +0,0,10,31,43,27,33,50,30,48,95,121,117,127,222,105, +82,184,164,89,7,34,69,55,79,68,33,30,46,44,34,25, +32,26,13,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,3,16,21,25,26, +17,8,0,0,0,0,9,48,81,58,16,0,20,106,38,168, +243,144,156,133,95,39,6,38,46,33,25,10,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16, +31,42,37,20,3,17,36,22,3,3,50,84,110,129,106,74, +127,168,103,141,146,102,65,58,43,7,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,60,155,235,223,197,174,152,133,116,99,86,72, +60,51,41,35,27,21,16,12,11,4,0,0,0,0,0,0, +0,0,0,0,2,8,12,16,20,27,32,39,48,57,70,81, +96,112,128,147,168,191,217,242,179,84,5,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +9,25,32,16,13,37,34,6,26,74,78,126,62,145,190,76, +51,133,164,104,45,0,24,60,36,45,62,47,15,17,34,38, +20,12,16,20,9,2,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,8,8,7,2,0, +0,0,0,0,0,14,48,58,21,5,0,0,68,65,19,178, +195,171,102,161,86,71,28,0,18,38,22,16,6,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,2,12,26,34, +21,5,0,3,22,20,5,0,0,42,54,58,87,86,56,52, +99,139,102,85,117,100,77,50,37,45,18,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,35,131,225,231,205,181,160,140,122,106,91,79, +65,55,47,38,31,26,20,16,12,11,5,2,0,0,0,0, +0,0,0,4,11,12,16,20,24,29,37,44,53,63,75,88, +102,118,135,154,176,199,224,236,155,60,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,19, +21,11,2,20,33,14,0,7,53,52,110,58,57,130,146,57, +25,87,139,91,74,16,0,16,54,27,16,31,45,31,5,8, +22,32,19,7,2,2,2,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,10,35,33,5,0,0,0,16,96,15,26,150, +144,177,54,155,98,63,60,20,0,5,24,25,3,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,2,9,22,18,11,0, +0,0,4,9,5,0,0,0,31,48,26,58,54,58,28,40, +81,100,108,52,86,86,67,59,41,18,38,24,3,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,14,100,195,240,214,189,168,147,129,112,98,85, +72,62,52,43,37,29,24,20,16,13,12,10,6,4,4,4, +4,4,10,12,12,16,20,24,29,35,42,49,58,69,81,94, +109,126,142,162,184,208,233,219,124,29,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,6,10,6, +0,4,23,18,3,0,5,45,36,76,71,18,57,117,117,35, +14,52,110,88,63,50,3,0,7,46,27,3,8,24,34,17, +2,3,12,22,12,7,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,20,12,2,0,0,0,0,62,66,0,26,123, +98,135,42,87,127,59,46,50,12,0,0,10,14,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,8,6,2,0,0,0, +0,0,0,0,0,0,0,25,45,10,37,44,42,35,16,22, +60,89,102,42,60,70,59,54,43,37,8,22,32,5,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,68,162,237,224,199,177,156,138,122,106,91, +79,68,58,50,42,35,29,25,21,19,14,12,12,12,12,12, +12,12,12,14,18,20,24,29,35,40,48,56,65,77,89,102, +116,133,152,172,194,217,241,183,92,10,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +4,13,4,0,0,3,35,27,46,76,11,20,55,98,82,28, +9,27,72,89,52,52,27,0,0,5,36,26,2,0,5,20, +25,8,0,0,3,8,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,2,6,0,0,0,0,0,14,96,19,0,28,106, +80,102,56,26,124,65,48,31,46,7,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,18,40,5,20,33,27,42,16,4,5, +32,81,79,66,24,57,65,36,50,31,28,5,10,20,13,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,32,123,214,235,210,187,166,147,130,115,100, +87,76,66,56,48,42,35,31,27,23,20,19,17,14,14,14, +14,17,18,20,22,27,29,35,40,46,54,63,73,85,97,110, +126,142,162,181,204,230,231,146,55,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,3,32,21,24,72,22,0,16,42,94,59,24, +7,18,55,74,56,36,43,5,0,0,3,25,28,3,0,0, +7,21,12,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,58,70,0,0,35,90, +75,77,52,12,76,96,33,41,23,37,3,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,12,37,6,5,15,24,15,39,0,0,0, +14,80,52,79,18,49,43,62,21,47,22,12,0,3,12,6, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,7,84,172,239,222,199,178,157,139,124,109, +97,85,74,64,56,49,43,37,33,29,27,24,22,20,20,20, +20,22,23,26,29,32,37,42,48,54,62,72,82,93,107,122, +137,154,172,194,216,241,195,105,19,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,28,22,9,56,34,0,0,14,38,98,38,22, +0,10,39,59,61,27,30,31,0,0,0,0,18,25,3,0, +0,0,6,9,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,9,89,22,0,0,40,78, +62,63,37,15,28,95,43,29,23,20,29,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,5,32,5,0,5,10,13,21,21,0,0,0, +0,78,42,69,35,16,48,33,39,14,41,7,2,3,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,39,128,215,236,212,190,171,153,133,122, +107,94,83,74,65,58,51,45,41,37,33,31,29,28,28,27, +28,28,30,33,35,39,44,49,56,63,72,82,92,104,116,131, +147,164,186,206,230,230,149,62,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,18,19,3,38,34,3,0,2,11,39,94,19,16, +0,0,20,41,58,32,17,30,11,0,0,0,0,12,13,3, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,45,63,0,0,0,34,47, +56,55,34,12,4,60,62,13,32,10,19,20,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,2,25,5,0,0,0,10,2,28,9,0,0,0, +0,72,40,60,47,3,36,23,29,17,15,35,5,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,7,81,166,239,227,203,185,163,147,131, +117,107,93,85,75,67,60,55,49,45,41,39,37,36,34,34, +35,36,39,41,45,48,53,58,65,73,82,92,102,116,129,145, +162,179,198,221,240,187,102,20,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,11,14,0,22,33,3,0,0,0,12,41,82,3,0, +0,0,15,28,45,40,9,9,28,2,0,0,0,0,3,15, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,7,66,15,0,0,0,16,16, +42,44,33,12,0,24,56,19,8,26,0,15,6,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,2,3,0,0,0,0,0,7,20,0,0,0,0, +0,56,38,45,51,17,7,40,7,25,5,16,28,3,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,30,115,197,241,219,197,179,163,147, +131,117,107,96,87,79,71,65,60,55,51,48,46,45,44,44, +44,46,48,49,55,57,63,69,77,85,93,104,116,128,140,155, +173,195,213,237,218,134,52,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,7,7,0,8,29,5,0,0,0,0,10,39,56,0,0, +0,0,5,15,34,42,10,0,15,14,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,34,44,0,0,0,3,29,16, +28,29,21,11,0,4,40,34,3,10,8,0,5,6,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,9,0,0,0,0,0,0,0,8,8,0,0,0,0, +0,40,46,27,44,28,0,22,23,5,19,0,13,16,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,3,60,141,220,236,214,195,179,163, +147,131,120,108,99,91,83,76,71,65,63,58,56,56,54,54, +55,56,57,61,64,70,75,81,89,97,107,116,129,140,155,171, +189,211,231,232,161,80,8,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,6,0,2,22,3,0,0,0,0,0,10,31,28,0,0, +0,0,0,0,27,33,23,0,0,10,2,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,5,53,12,0,0,0,0,5,3, +0,14,14,0,0,0,16,32,9,0,12,5,0,5,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0, +0,27,51,17,40,34,3,3,32,5,3,2,0,0,6,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,11,82,159,231,234,211,195,179, +163,147,133,124,114,104,96,89,83,79,73,72,68,66,64,64, +65,68,71,72,78,81,88,94,102,110,122,131,145,155,171,188, +207,227,240,179,104,27,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,15,7,0,0,0,0,0,0,0,25,12,0,0, +0,0,0,0,14,20,35,0,0,3,5,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,23,34,0,0,0,0,0,0,0, +0,14,20,0,0,0,3,21,16,0,0,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,12,45,2,36,25,14,0,15,19,0,0,0,0,11,7, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,24,97,173,236,231,211,195, +179,163,149,139,129,120,111,104,97,92,88,84,80,80,80,80, +80,80,82,88,90,96,102,109,116,126,137,147,162,173,189,207, +227,239,191,118,39,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,6,7,0,0,0,0,0,0,0,0,21,3,0,0, +0,0,0,0,3,12,27,13,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,3,34,6,0,0,0,0,0,0,0, +0,7,13,0,0,0,0,10,16,2,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,30,3,29,22,11,0,0,23,7,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,33,107,178,237,233,213, +197,181,170,155,146,135,128,120,112,106,104,98,96,96,96,96, +96,96,98,104,106,112,118,126,133,142,154,164,179,195,211,227, +239,195,125,51,3,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,2,11,0,0,0, +0,0,0,0,0,6,12,23,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,12,18,0,0,0,0,0,0,0,0, +0,3,18,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,16,6,15,20,14,3,0,7,12,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,36,107,174,231,235, +219,203,188,175,164,154,144,136,129,125,120,116,112,112,112,112, +112,112,114,120,123,128,135,142,152,162,172,186,198,213,231,240, +191,125,54,5,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,27,3,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,16,3,0,0,0,0,0,0,0,0, +16,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,10,8,5,23,8,7,0,0,9,5,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,34,102,165,223, +241,225,210,196,186,174,164,156,150,143,136,134,131,128,128,128, +128,129,134,136,142,147,154,162,172,181,194,206,221,237,232,179, +118,51,5,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,12,9,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0, +16,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,2,0,20,4,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,27,88,145, +204,241,233,220,208,196,186,177,170,163,158,154,151,149,148,148, +149,151,152,158,163,168,176,184,194,204,216,230,240,218,161,104, +39,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,2,11,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0, +12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,2,0,10,7,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,66, +123,174,223,241,232,220,210,201,193,187,181,176,174,171,169,169, +170,172,176,180,185,191,199,208,217,230,241,230,187,134,80,27, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5, +36,90,138,184,225,241,235,226,218,212,205,202,197,195,194,193, +195,196,200,204,210,217,224,233,241,231,195,149,102,52,8,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,12,51,95,136,175,211,233,242,238,233,227,224,220,219,219, +220,223,227,231,236,242,236,219,183,146,105,62,20,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,14,45,83,116,147,173,197,216,228,232,236,239,239, +238,233,231,223,202,179,155,124,92,55,19,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,5,22,52,78,102,120,135,147,155,161,162, +156,150,137,124,105,84,60,29,10,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,3,13,24,39,49,57,61,61, +59,51,40,24,16,5,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,4,6,8,10,10,10,10, +10,10,10,6,5,2,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,4,8,11,13,14,16,17,18,18,18,18, +18,18,18,16,15,13,11,8,5,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,8,11,14,17,19,20,22,24,25,26,26,26,26, +26,26,25,24,22,21,19,17,15,12,8,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,8,12,15,19,21,24,26,28,30,32,33,34,34,34,34, +34,34,33,32,30,29,27,25,22,19,17,13,8,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,2,6,6,5, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6, +12,16,19,23,26,29,31,34,36,38,40,40,42,42,42,42, +42,42,41,40,38,36,35,32,29,27,23,20,17,13,8,2, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,3,15,28,48,63,73,83,85,86,84, +77,64,50,31,18,5,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,2,12,19,24,30,36,36, +35,26,20,12,3,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,2,11,15, +19,23,27,30,33,36,39,42,44,46,47,48,50,50,50,50, +50,50,49,48,46,44,42,39,37,34,31,27,24,20,16,11, +5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,2,18,44,76,102,126,143,159,172,180,186,187,182, +174,163,149,129,108,84,52,22,5,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,10,29,54,77,96,112,123,131,135,137, +132,126,113,99,81,60,35,14,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,6,13,17,21, +27,29,33,37,41,44,47,49,51,53,55,56,58,58,58,58, +58,58,57,56,54,52,50,47,45,41,38,35,31,27,23,19, +13,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,5,28,69,107,139,171,197,222,226,225,227,222,218,218,220, +227,227,227,222,203,179,147,116,77,38,7,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,24,60,92,124,149,173,191,207,222,228,231,231, +229,224,214,199,177,155,131,100,68,32,7,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,8,13,19,24,28, +33,37,41,45,47,51,54,57,59,61,63,64,66,66,66,66, +66,66,64,63,62,60,57,55,52,49,45,41,37,33,29,25, +20,15,11,2,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2, +28,73,119,158,196,226,227,209,183,161,144,133,124,117,117,123, +129,143,159,177,203,225,227,207,168,128,84,36,5,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,4,30,73,114,151,187,219,236,247,247,246,245,243,243,243, +243,245,245,247,246,238,225,195,162,123,84,39,7,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,9,15,20,25,29,35, +39,43,47,51,55,59,61,65,67,69,71,72,74,74,74,74, +74,74,72,71,69,67,65,62,59,55,53,49,45,40,36,31, +27,21,16,11,2,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,59, +111,159,206,229,212,175,141,114,88,65,48,32,25,22,22,24, +31,44,62,82,108,133,167,203,228,216,171,124,72,23,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +20,68,116,162,204,235,247,245,242,239,238,236,233,233,233,233, +233,233,235,237,239,241,244,247,239,214,172,128,81,30,3,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,9,16,21,27,32,37,41, +45,51,55,59,62,66,69,71,75,77,78,80,82,82,82,82, +82,82,80,79,77,75,73,69,67,63,59,55,51,47,43,37, +32,27,21,16,11,2,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,28,87,142, +195,228,207,163,121,84,50,22,8,0,0,0,0,0,0,0, +0,0,0,4,18,42,76,112,152,196,231,210,156,101,42,5, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,46, +101,154,203,239,246,242,239,236,232,230,228,225,224,223,223,223, +223,223,225,227,230,231,234,238,242,246,244,215,166,115,60,11, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,9,16,21,27,32,37,43,48, +53,57,61,65,69,73,76,79,82,84,86,88,89,90,90,90, +90,90,88,87,85,83,80,77,74,70,67,62,59,53,49,44, +38,34,28,22,16,11,2,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4, +4,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,3,42,105,167,220, +218,170,121,74,32,6,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,3,24,63,109,156,210,226,181,121,58, +7,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,12,66,128, +183,231,248,242,238,234,230,226,223,220,217,215,215,214,213,213, +213,215,215,217,220,222,225,229,232,236,241,246,240,197,141,82, +24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,6,14,21,27,32,37,43,48,53, +59,64,68,72,77,80,83,87,89,92,94,96,97,98,98,98, +98,98,96,94,92,90,87,84,81,77,73,69,65,60,55,51, +45,40,34,28,21,16,11,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,4,7,10,10,10,10,10, +10,10,10,8,4,4,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,5,53,120,183,231,197, +139,85,35,5,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,24,72,126,183,229,199,135, +71,9,0,0,0,0,0,0,0,0,0,0,0,0,10,0, +0,0,0,0,0,0,0,0,0,0,0,0,21,81,143,207, +245,244,238,234,229,224,220,216,214,210,208,207,205,204,203,203, +203,205,206,207,210,213,216,220,224,228,232,238,243,246,220,159, +97,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,5,13,19,26,32,37,43,50,54,60, +65,69,75,79,83,87,91,94,97,100,102,104,105,106,106,106, +106,105,104,102,100,98,95,91,88,84,80,75,71,67,61,56, +51,45,40,34,27,21,15,6,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,4,8,10,12,12,12,12,12,12,12, +12,12,12,12,12,10,8,4,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,5,55,125,192,230,177,119, +58,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,5,44,104,161,222,209, +142,72,9,0,0,0,0,0,0,0,0,0,0,0,8,0, +0,0,0,0,0,0,0,0,0,0,0,24,89,156,221,248, +242,236,230,225,220,216,211,207,204,200,199,197,194,193,193,193, +193,194,196,198,200,203,206,210,214,219,224,229,234,240,246,233, +173,107,36,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,2,11,19,24,31,37,43,49,54,61,67, +71,77,81,85,91,93,98,101,105,107,109,111,113,114,114,114, +114,113,112,110,108,105,102,99,95,91,87,83,77,72,67,61, +56,51,45,38,32,27,19,13,5,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,4,8,11,12,12,12,14,14,18,18,18,18, +18,18,15,14,13,12,12,11,8,4,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,48,123,194,225,168,104,39, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,27,88,152,218, +212,140,68,7,0,0,0,0,0,0,0,0,0,0,3,0, +0,0,0,0,0,0,0,0,0,0,21,89,159,225,247,240, +234,228,222,216,211,206,202,198,194,191,189,186,184,183,183,183, +183,184,186,188,191,194,198,200,206,210,215,220,226,232,239,245, +237,178,107,34,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,8,16,23,29,35,43,48,54,61,67,72, +77,83,88,92,97,101,105,109,111,115,117,119,121,122,122,122, +122,121,120,118,115,113,109,106,101,99,93,88,83,78,73,67, +61,56,50,43,37,31,24,18,11,2,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,5,11,12,12,13,16,18,20,20,20,20,22,22, +21,20,20,20,19,18,14,12,12,11,8,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,35,113,190,227,167,97,30,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,18,80,148, +219,207,133,56,3,0,0,0,0,0,0,0,0,0,4,0, +0,0,0,0,0,0,0,0,0,12,81,156,225,247,239,233, +226,220,214,208,203,198,193,190,184,182,179,176,175,174,173,173, +174,175,176,178,182,184,188,192,196,202,206,212,218,224,231,237, +244,237,174,102,27,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,5,13,21,27,34,40,47,53,59,66,72,77, +83,88,93,99,103,108,112,116,119,122,125,127,128,129,129,129, +129,128,127,125,123,119,117,113,109,104,100,95,90,85,78,73, +67,61,55,48,43,35,29,21,15,8,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,8,12,12,13,16,19,20,21,23,26,26,28,28,28, +28,27,26,24,22,20,20,18,14,12,12,8,4,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,21,96,175,231,173,99,29,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,81, +153,223,195,118,36,0,0,0,0,0,0,0,0,0,10,0, +0,0,0,0,0,0,0,0,5,66,143,221,247,239,231,225, +218,212,206,200,194,189,184,180,176,172,169,167,165,164,163,163, +164,165,167,168,172,175,179,184,188,193,198,204,210,217,223,231, +237,245,233,165,88,14,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,11,17,25,31,37,45,51,59,64,70,77,83, +88,94,99,105,109,115,119,123,126,128,131,134,135,137,137,137, +137,136,134,132,130,127,123,120,115,111,107,101,96,91,85,78, +72,67,59,53,46,40,33,27,19,12,2,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,8,12,12,14,19,20,22,26,28,28,30,32,34,34,34, +34,32,30,29,28,26,23,20,19,16,13,12,11,5,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,6,74,155,227,185,111,33,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20, +90,167,231,175,95,16,0,0,0,0,0,0,0,0,11,0, +0,0,0,0,0,0,0,0,46,128,207,248,240,233,225,218, +211,204,198,192,186,180,176,171,167,163,160,158,156,153,153,153, +153,155,157,159,162,166,170,174,179,184,190,196,203,209,217,223, +231,238,246,223,145,66,5,0,0,0,0,0,0,0,0,0, +0,0,0,2,14,21,28,35,43,49,56,63,69,75,83,88, +93,100,106,111,116,121,125,128,132,136,139,141,143,145,145,145, +145,143,142,140,137,134,130,127,123,117,112,107,101,96,90,83, +77,71,64,57,51,44,37,29,23,15,8,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2, +8,12,13,16,20,21,25,28,29,33,35,37,38,40,40,40, +40,39,37,36,34,31,28,26,21,20,18,13,12,11,5,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,43,128,211,208,128,48,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +28,107,188,224,148,64,3,0,0,0,0,0,0,0,6,0, +0,0,0,0,0,0,0,20,101,183,245,242,234,226,218,211, +204,197,190,184,178,172,166,162,158,154,150,148,145,143,143,143, +143,145,148,150,152,156,160,166,171,176,182,189,195,202,209,217, +224,232,240,248,204,123,36,0,0,0,0,0,0,0,0,0, +0,0,0,0,16,25,32,39,45,53,60,67,73,80,87,93, +99,106,112,117,123,127,131,136,140,144,146,149,151,153,153,153, +153,151,149,147,144,140,136,132,128,123,117,112,107,101,94,88, +83,75,69,61,55,48,41,34,27,19,12,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,8, +12,13,16,20,22,27,29,33,36,39,42,44,46,48,48,48, +48,46,45,43,39,37,35,29,28,24,20,19,13,12,11,4, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,14,92,179,226,154,71,6,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,51,132,218,200,115,29,0,0,0,0,0,0,0,3,0, +0,0,0,0,0,0,4,68,154,231,244,236,228,220,212,204, +197,189,183,176,170,164,158,153,148,144,142,138,135,135,133,133, +135,135,137,140,144,148,152,157,162,168,175,181,188,195,202,210, +218,226,234,242,244,174,90,12,0,0,0,0,0,0,0,0, +0,0,0,0,15,28,35,43,50,57,64,71,77,85,91,98, +104,110,117,123,128,132,138,142,146,150,154,156,159,160,161,161, +161,159,157,154,152,148,143,138,133,129,123,117,112,106,99,93, +85,79,73,65,59,51,45,37,29,23,15,5,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,12, +12,16,20,24,28,31,35,39,43,45,49,52,54,56,56,56, +56,55,53,50,47,43,40,36,32,28,24,20,19,13,12,8, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,51,139,223,187,102,23,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,7,81,165,229,161,73,5,0,0,0,0,0,0,2,0, +0,0,0,0,0,0,30,116,203,248,238,230,222,214,206,198, +190,183,175,169,162,156,150,144,140,136,132,128,127,126,124,124, +126,127,128,130,134,138,144,149,154,161,167,173,181,188,196,204, +212,220,228,236,245,223,138,51,0,0,0,0,0,0,0,0, +0,0,0,0,12,31,39,45,53,61,67,75,82,89,95,102, +109,115,122,128,132,138,143,148,154,158,161,164,166,168,169,169, +169,167,164,162,158,154,150,146,140,135,129,123,117,110,104,97, +91,83,77,69,62,55,47,41,33,26,18,11,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,5,11,12, +16,20,24,28,32,36,40,45,49,53,57,61,64,65,66,66, +65,64,61,58,55,51,45,43,37,32,28,24,20,16,12,12, +5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,13,94,184,224,140,53,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,33,119,207,206,116,27,0,0,0,0,0,0,4,0, +0,0,0,0,0,4,73,162,239,242,234,225,216,208,200,192, +184,176,169,161,155,148,142,136,131,127,123,120,118,115,114,114, +114,117,119,122,127,130,135,140,147,153,159,167,175,182,190,198, +206,214,222,232,240,245,184,95,14,0,0,0,0,0,0,0, +0,0,0,0,8,34,41,49,57,63,71,78,85,93,99,107, +113,120,126,132,138,143,149,155,160,164,168,172,174,176,177,177, +177,175,172,170,164,162,156,151,146,140,133,128,122,115,108,101, +94,87,80,73,65,59,51,43,36,28,21,13,2,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,2,10,12,14, +19,21,27,32,36,42,46,51,57,61,65,71,73,75,78,78, +75,73,71,67,63,58,53,48,43,37,32,28,24,20,16,12, +11,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,42,132,220,187,97,15,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,5,74,164,229,156,64,0,0,0,0,0,0,3,0, +0,0,0,0,0,24,114,204,246,238,229,220,211,203,194,186, +178,170,162,155,147,141,134,128,123,119,113,111,107,105,104,104, +105,107,110,113,117,122,127,133,139,146,153,160,168,176,184,192, +200,209,218,226,236,244,225,136,45,0,0,0,0,0,0,0, +0,0,0,0,5,37,44,52,59,67,74,81,89,96,103,111, +117,124,130,137,143,149,155,161,166,171,175,179,182,184,185,185, +184,182,180,176,172,167,162,156,151,145,138,132,125,119,112,105, +98,91,83,76,69,61,53,46,38,31,23,15,6,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,5,12,12,18, +20,27,29,36,41,46,53,59,65,70,76,80,84,87,88,88, +88,85,81,77,71,66,60,54,48,43,37,32,27,21,19,13, +12,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,3,76,170,227,147,56,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,33,125,218,194,100,14,0,0,0,0,0,3,0, +0,0,0,0,0,60,151,235,242,234,224,216,206,198,189,180, +172,164,156,148,141,133,128,121,115,110,105,101,97,96,95,94, +96,97,101,104,109,114,120,126,132,139,146,154,162,170,178,187, +196,204,214,222,231,240,246,175,83,5,0,0,0,0,0,0, +0,0,0,0,5,39,46,54,62,69,77,84,92,99,107,114, +121,128,134,140,148,154,161,167,172,178,182,186,189,192,193,193, +192,190,187,183,178,173,167,162,156,149,143,136,130,123,115,109, +101,93,86,79,71,63,56,49,41,33,25,18,10,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,2,10,12,14,20, +24,28,35,40,45,53,59,66,72,79,86,91,96,98,102,102, +98,96,92,87,81,74,68,61,54,48,41,36,29,26,20,16, +12,11,4,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,18,108,203,204,112,22,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,10,91,181,223,131,35,0,0,0,0,0,3,0, +0,0,0,0,10,92,187,247,239,230,220,211,202,193,184,176, +166,158,150,142,134,128,120,114,107,101,97,92,88,86,85,84, +86,88,91,95,100,106,112,118,126,132,140,148,156,165,174,182, +191,200,208,218,227,236,246,211,116,22,0,0,0,0,0,0, +0,0,0,0,5,41,49,56,64,72,79,87,95,102,109,117, +124,130,138,146,152,159,165,172,178,183,188,194,196,199,201,201, +200,197,194,190,185,179,173,167,160,154,146,140,132,126,119,111, +104,97,89,81,74,66,58,51,43,35,27,20,12,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,4,12,12,18,21, +27,31,37,44,51,58,66,73,81,88,95,103,108,112,113,113, +112,110,104,97,90,83,75,67,60,53,45,39,33,28,22,19, +13,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,42,137,227,173,80,5,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,56,149,227,161,66,0,0,0,0,0,2,0, +0,0,0,0,29,124,219,245,236,226,216,207,198,190,180,171, +162,153,144,136,128,121,114,106,99,93,87,83,79,77,74,74, +75,79,81,87,92,98,104,112,119,127,134,142,152,160,168,178, +186,196,206,214,224,232,242,235,147,52,0,0,0,0,0,0, +0,0,0,0,5,43,50,58,66,74,82,89,97,105,112,119, +127,134,141,148,156,163,170,176,183,188,194,199,204,207,209,209, +208,204,201,196,191,185,178,172,164,158,150,142,136,128,122,114, +107,99,91,83,76,68,60,52,44,37,29,21,13,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,8,12,14,20,23, +28,35,41,47,55,63,71,80,89,98,107,115,121,127,128,128, +128,122,117,109,100,92,82,74,65,57,49,43,36,29,26,20, +16,12,10,2,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,65,161,227,147,52,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,29,124,219,185,90,8,0,0,0,0,2,0, +0,0,0,0,54,149,236,242,232,223,214,204,194,184,176,167, +158,148,140,131,123,115,107,99,92,85,79,74,70,66,64,64, +65,69,73,78,84,90,98,105,113,121,128,138,146,156,164,174, +183,192,202,211,221,230,239,245,173,78,3,0,0,0,0,0, +0,0,0,0,5,44,52,60,68,76,83,91,99,107,114,122, +129,136,144,152,158,166,174,180,188,194,200,205,210,214,217,217, +215,212,207,202,196,188,182,176,168,161,154,146,138,131,124,116, +108,101,93,85,77,70,62,54,46,38,30,22,14,4,0,0, +0,0,0,0,0,0,0,0,0,0,2,10,12,16,20,26, +30,37,44,51,59,68,78,87,97,107,117,127,134,141,143,143, +143,135,128,120,110,100,89,79,71,61,53,45,39,33,27,21, +18,12,11,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,7,88,183,222,126,29,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,14,101,198,207,112,19,0,0,0,0,1,0, +0,0,0,2,77,173,247,239,230,220,210,200,191,182,172,163, +154,144,136,127,119,110,101,93,85,78,72,65,61,57,55,55, +56,59,64,70,76,83,91,99,108,116,125,134,142,152,160,170, +180,190,199,208,217,228,238,247,197,102,13,0,0,0,0,0, +0,0,0,0,6,45,53,61,69,77,84,92,100,108,116,124, +131,139,146,154,162,169,177,184,192,198,204,212,218,222,224,225, +222,218,212,207,200,194,186,178,171,163,156,148,140,133,126,118, +110,102,94,86,78,71,63,55,47,39,32,24,16,6,0,0, +0,0,0,0,0,0,0,0,0,0,4,11,12,18,21,28, +33,39,47,55,63,73,83,94,105,117,128,138,148,157,160,160, +159,150,140,130,119,108,97,86,75,65,57,49,41,35,28,22, +19,13,12,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,16,104,199,201,104,16,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,3,80,177,223,128,31,0,0,0,0,0,0, +0,0,0,12,96,191,247,238,228,217,208,199,189,179,169,160, +150,142,132,123,113,105,97,87,79,72,64,57,52,47,46,45, +47,51,56,62,69,77,85,95,103,112,121,128,138,148,158,167, +176,186,196,206,215,225,234,245,216,120,24,0,0,0,0,0, +0,0,0,0,6,46,54,62,70,78,86,94,102,110,118,125, +132,140,148,155,163,171,179,187,194,202,210,216,223,228,232,233, +229,224,218,211,204,196,188,181,173,165,157,150,142,134,127,119, +112,104,96,88,80,72,64,56,48,40,32,24,16,6,0,0, +0,0,0,0,0,0,0,0,0,0,4,12,13,19,22,28, +35,42,49,57,67,77,88,100,112,125,137,149,163,173,179,179, +175,164,154,140,127,115,103,89,80,69,59,51,43,36,30,25, +20,14,12,7,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,21,119,215,187,89,8,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,64,163,227,142,44,0,0,0,0,1,0, +0,0,0,19,112,207,246,236,225,215,207,197,186,176,167,158, +148,138,128,120,111,101,92,83,74,65,57,50,43,39,35,34, +37,42,48,56,63,71,81,89,99,108,118,127,135,145,154,165, +175,184,193,204,214,223,233,243,229,135,39,0,0,0,0,0, +0,0,0,0,6,46,54,62,70,78,86,94,102,110,118,126, +133,141,149,157,165,173,181,189,196,204,212,219,227,234,239,240, +236,228,221,214,206,198,191,183,175,167,159,151,143,135,128,120, +112,104,96,88,80,72,64,56,48,40,32,24,16,6,0,0, +0,0,0,0,0,0,0,0,0,0,5,12,14,20,23,29, +36,43,51,59,70,80,90,104,118,129,145,161,175,187,198,199, +192,179,163,149,134,120,106,95,82,72,62,53,45,37,30,26, +20,14,12,10,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,27,128,226,176,79,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,54,152,226,152,53,0,0,0,0,0,0, +0,0,0,24,123,222,245,233,224,215,205,194,184,175,165,156, +145,135,127,118,107,97,88,79,70,61,52,43,36,29,25,24, +28,34,42,49,58,67,77,87,96,105,114,125,134,143,152,162, +173,183,192,201,213,222,231,241,236,147,49,0,0,0,0,0, +0,0,0,0,6,46,54,62,70,78,86,94,102,110,118,126, +133,141,149,157,165,173,181,189,197,205,213,221,229,237,244,246, +239,231,223,215,207,199,191,183,175,167,159,151,143,135,128,120, +112,104,96,88,80,72,64,56,48,40,32,24,16,6,0,0, +0,0,0,0,0,0,0,0,0,0,7,12,14,20,25,30, +36,44,52,62,72,81,95,105,120,135,151,167,185,203,218,220, +205,189,173,154,137,124,111,96,86,73,64,54,46,38,32,26, +20,15,12,10,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,35,132,226,170,71,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,45,146,226,158,60,0,0,0,0,0,0, +0,0,0,30,131,228,243,233,223,214,204,193,183,174,164,153, +143,135,126,115,105,96,86,77,66,57,47,39,29,22,16,16, +20,27,36,45,55,64,73,83,94,104,112,122,132,142,151,161, +171,181,191,201,211,221,231,241,239,155,57,0,0,0,0,0, +0,0,0,0,6,46,54,62,70,78,86,94,102,110,118,126, +133,141,149,157,165,173,181,189,197,205,212,220,228,235,242,242, +236,230,222,214,206,199,191,183,175,167,159,151,143,135,128,120, +112,104,96,88,80,72,64,56,48,40,32,24,16,6,0,0, +0,0,0,0,0,0,0,0,0,0,7,12,14,20,26,30, +36,44,52,62,72,82,96,107,120,135,151,170,191,210,231,236, +215,195,175,159,143,128,112,96,86,74,64,54,46,38,32,26, +20,18,12,10,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,36,137,227,165,68,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,44,141,227,162,62,0,0,0,0,2,0, +0,0,0,36,135,231,243,233,223,213,203,193,183,173,163,153, +143,133,124,114,104,95,85,74,64,55,46,35,25,16,6,5, +15,23,32,42,53,62,72,82,92,102,112,122,131,141,151,160, +170,181,191,199,209,221,231,239,241,161,61,0,0,0,0,0, +0,0,0,0,6,46,54,62,70,78,86,94,102,110,118,126, +133,140,148,156,164,172,179,187,195,202,210,218,224,229,234,235, +231,226,219,212,204,197,189,181,173,166,158,150,142,135,128,120, +112,104,96,88,80,72,64,56,48,40,32,24,16,6,0,0, +0,0,0,0,0,0,0,0,0,0,7,12,14,20,26,30, +36,44,52,62,72,81,95,106,120,135,151,168,186,205,221,225, +211,192,174,157,139,126,112,96,86,73,64,54,46,38,32,26, +20,17,12,10,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,36,135,227,170,69,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,44,143,227,159,60,0,0,0,0,2,0, +0,0,0,36,137,231,243,233,223,213,203,193,183,173,163,153, +143,133,124,114,104,94,84,74,64,55,45,34,24,16,5,2, +13,23,32,42,52,62,72,82,92,102,112,122,131,141,151,160, +169,181,191,199,209,221,231,239,241,162,61,0,0,0,0,0, +0,0,0,0,6,46,54,61,69,77,85,93,100,108,116,124, +131,139,147,154,162,170,178,185,192,200,206,212,218,223,226,227, +224,220,214,208,202,194,187,179,172,164,156,149,141,133,126,118, +110,102,95,87,79,71,63,56,48,40,32,24,16,6,0,0, +0,0,0,0,0,0,0,0,0,0,7,12,14,20,24,29, +36,44,51,60,70,80,92,104,119,132,147,163,179,193,202,206, +195,181,166,151,135,120,108,96,82,72,63,54,45,38,30,26, +20,14,12,10,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,30,129,226,174,77,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,51,150,227,154,55,0,0,0,0,2,0, +0,0,0,35,132,229,243,233,223,213,203,193,183,174,164,153, +143,135,126,114,105,96,86,75,65,56,47,37,28,20,15,13, +18,26,35,45,54,64,73,83,93,103,112,122,132,141,151,161, +171,181,191,201,211,221,231,240,241,156,59,0,0,0,0,0, +0,0,0,0,5,44,52,60,68,76,84,92,99,107,115,123, +129,137,145,152,160,167,174,182,188,195,202,207,212,216,219,219, +217,213,209,203,196,190,184,176,169,162,154,146,139,131,124,117, +109,101,93,86,78,70,62,54,46,38,30,22,15,5,0,0, +0,0,0,0,0,0,0,0,0,0,4,12,13,20,22,28, +35,42,50,58,67,79,88,100,113,127,139,153,164,177,183,184, +179,169,155,142,128,117,104,92,80,71,61,52,44,36,30,25, +20,14,12,8,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,24,120,219,184,88,7,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,63,159,225,144,47,0,0,0,0,2,0, +0,0,0,26,126,224,245,233,223,215,205,194,184,175,165,155, +145,135,127,117,107,97,88,79,69,59,51,42,34,27,23,23, +26,32,40,49,57,67,75,85,95,104,114,124,133,143,152,162, +173,183,191,201,212,222,231,241,237,150,51,0,0,0,0,0, +0,0,0,0,5,43,51,59,66,74,82,90,97,105,113,121, +128,134,142,149,156,164,170,178,184,191,196,202,206,209,211,211, +209,206,202,197,191,186,179,172,166,158,152,144,136,129,122,115, +107,99,92,84,76,68,60,53,45,37,29,22,14,4,0,0, +0,0,0,0,0,0,0,0,0,0,4,12,12,18,22,28, +34,40,47,55,64,73,84,95,107,119,130,140,152,160,167,167, +161,155,144,132,121,109,97,87,76,67,57,49,42,35,28,22, +20,14,12,5,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,16,106,207,199,102,14,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,2,78,175,227,131,31,0,0,0,0,3,0, +0,0,0,20,113,214,245,235,225,215,206,196,186,176,167,157, +148,137,128,119,110,101,91,81,73,64,56,48,42,36,32,32, +35,40,46,54,62,71,79,89,97,107,117,127,135,144,154,164, +174,183,193,204,213,223,232,242,232,137,40,0,0,0,0,0, +0,0,0,0,5,41,49,57,65,72,80,87,95,103,110,117, +125,132,139,146,154,160,166,172,179,185,190,194,198,201,203,203, +202,200,196,191,186,180,175,168,162,154,148,140,133,127,119,112, +105,97,89,82,74,67,59,51,43,36,28,20,12,0,0,0, +0,0,0,0,0,0,0,0,0,0,2,10,12,18,20,26, +31,37,45,53,61,70,79,89,99,109,120,129,137,143,149,151, +145,139,131,123,112,102,92,81,71,63,55,47,39,33,28,21, +18,12,12,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,8,90,189,215,120,24,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,11,96,191,214,114,20,0,0,0,0,4,0, +0,0,0,12,99,199,247,237,227,217,207,198,188,178,168,159, +150,140,130,122,113,104,95,87,78,70,62,56,49,45,42,42, +45,49,54,60,68,76,84,93,102,111,120,128,138,148,157,167, +176,185,196,206,215,224,234,245,223,124,24,0,0,0,0,0, +0,0,0,0,5,39,47,55,62,70,77,85,93,100,107,115, +122,128,135,142,148,156,162,167,173,179,184,188,191,194,195,195, +194,192,188,185,180,175,170,164,156,150,144,138,130,124,117,109, +101,94,87,79,72,64,57,49,41,34,26,18,10,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,8,12,14,20,24, +29,36,42,49,57,65,73,82,92,101,109,117,125,128,133,134, +129,127,119,111,102,94,84,76,67,59,51,43,37,30,26,20, +16,12,10,2,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,72,167,226,141,46,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,23,118,213,191,96,12,0,0,0,0,2,0, +0,0,0,3,81,177,246,239,230,220,210,200,191,182,172,162, +152,144,134,127,117,109,100,92,84,76,69,63,58,55,53,52, +54,57,62,68,74,82,90,98,106,115,124,132,142,150,160,169, +178,188,198,207,217,226,237,247,202,105,16,0,0,0,0,0, +0,0,0,0,4,37,45,52,60,67,75,83,89,97,104,111, +118,125,131,138,144,151,156,162,167,172,178,180,184,186,187,187, +186,184,182,178,174,170,164,158,152,146,140,132,127,120,113,106, +99,91,84,77,69,61,54,47,39,31,24,16,8,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,5,12,13,19,21, +28,33,38,45,51,59,67,75,83,91,99,105,112,114,120,120, +116,112,107,100,93,85,77,69,61,53,47,40,35,28,22,20, +14,12,8,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,48,143,228,169,74,3,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,50,145,228,167,72,0,0,0,0,0,3,0, +0,0,0,0,60,155,238,241,231,222,213,203,194,184,175,166, +156,148,138,130,122,114,106,98,90,83,77,71,67,64,62,62, +64,67,71,76,82,88,96,104,112,120,128,136,145,154,164,173, +182,191,200,210,220,230,239,246,179,84,5,0,0,0,0,0, +0,0,0,0,4,35,42,50,57,65,71,79,86,93,101,107, +115,121,128,132,140,146,151,156,162,166,170,173,176,178,179,179, +178,177,174,171,167,162,157,153,146,140,135,128,123,116,109,101, +95,88,81,73,67,59,51,44,37,29,21,14,4,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,2,10,12,16,20, +24,29,35,41,47,53,61,68,74,81,87,95,97,103,104,104, +104,100,95,89,84,76,70,62,56,49,43,36,30,27,20,18, +12,11,4,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,22,116,211,195,104,18,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,5,80,173,227,139,44,0,0,0,0,0,3,0, +0,0,0,0,35,131,225,244,234,225,216,206,198,188,179,170, +160,152,144,135,127,120,112,104,98,91,85,81,77,73,72,72, +73,75,79,84,90,96,102,110,118,126,133,142,150,158,168,176, +186,195,204,214,223,232,242,239,155,60,0,0,0,0,0,0, +0,0,0,0,4,31,39,47,53,61,69,75,83,89,97,103, +109,117,123,128,134,140,146,150,155,159,163,166,168,170,171,171, +171,169,166,164,160,156,151,146,140,135,130,125,117,112,105,99, +91,85,77,70,63,55,49,41,34,27,19,11,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,5,12,13,19, +21,27,31,37,43,48,54,61,67,73,78,82,87,89,90,90, +89,88,84,79,73,68,62,56,50,44,37,32,28,22,20,14, +12,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,5,84,179,225,139,47,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,26,116,207,202,108,18,0,0,0,0,0,2,0, +0,0,0,0,14,100,195,247,238,229,220,210,200,192,184,174, +166,157,149,140,133,126,118,112,105,99,95,89,87,83,82,82, +83,85,89,93,98,104,110,117,124,131,138,147,155,164,172,181, +190,199,208,216,226,236,246,219,124,29,0,0,0,0,0,0, +0,0,0,0,3,29,36,43,51,58,65,72,79,85,93,99, +105,112,117,123,129,134,139,144,148,152,156,158,161,162,163,163, +163,161,159,156,154,148,146,140,135,130,125,120,113,107,101,93, +87,81,73,67,59,53,45,37,31,23,16,8,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,2,10,12,14, +20,23,28,32,37,43,48,53,59,63,68,72,76,79,80,80, +79,77,73,69,65,60,55,50,44,38,35,28,24,20,16,12, +11,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,51,142,226,176,87,9,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,64,154,228,164,75,3,0,0,0,0,0,2,0, +0,0,0,0,0,68,162,239,242,232,224,214,206,196,188,179, +171,162,154,147,139,132,126,119,113,108,103,99,96,94,92,92, +93,95,97,102,106,112,118,124,130,137,145,152,160,168,177,186, +194,203,212,222,230,239,246,183,92,10,0,0,0,0,0,0, +0,0,0,0,3,25,33,40,47,53,61,68,75,81,88,94, +101,107,112,117,123,128,132,138,141,145,148,151,153,155,155,155, +155,153,152,149,146,142,138,134,130,125,120,115,108,101,96,89, +83,77,69,63,56,49,42,35,27,20,13,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,5,12,12, +16,20,24,28,32,37,43,47,51,55,59,63,65,67,70,70, +68,66,64,61,57,53,48,43,38,35,29,26,20,19,13,12, +8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,18,104,193,218,129,42,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,23,108,196,216,127,34,0,0,0,0,0,0,2,0, +0,0,0,0,0,32,123,214,246,236,228,219,210,202,193,184, +176,168,161,153,146,139,132,127,121,116,112,108,105,104,102,102, +103,104,107,111,115,120,126,131,137,143,151,159,166,174,182,191, +200,208,216,226,234,244,233,146,55,0,0,0,0,0,0,0, +0,0,0,0,2,22,29,36,43,51,57,63,69,77,83,89, +96,101,107,112,117,123,127,130,134,138,140,143,145,147,147,147, +147,145,144,141,138,136,132,128,123,119,114,109,102,96,91,85, +78,72,65,59,52,45,37,31,24,17,8,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,2,8,12, +13,19,20,24,28,32,36,40,44,47,51,54,56,58,58,58, +58,57,55,52,49,45,41,37,33,29,27,21,19,13,12,10, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,63,150,227,175,90,12,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,4,68,154,229,173,84,7,0,0,0,0,0,0,1,0, +0,0,0,0,0,7,84,172,244,241,232,224,215,206,198,190, +182,175,167,159,153,146,140,134,128,125,121,118,114,112,112,112, +112,114,117,120,124,128,133,138,145,151,159,165,173,180,188,196, +205,213,222,230,238,248,195,105,19,0,0,0,0,0,0,0, +0,0,0,0,2,19,25,32,39,45,53,59,66,72,77,84, +91,96,101,107,111,116,121,125,128,130,133,136,137,139,139,139, +139,138,136,134,131,128,125,121,117,112,107,102,97,91,85,80, +74,67,61,53,47,41,35,27,20,13,2,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,10, +12,13,19,20,24,28,31,35,37,41,44,46,48,50,50,50, +50,48,47,44,42,38,35,32,28,24,21,19,14,12,11,5, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,20,105,191,222,140,57,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,35,120,203,212,126,38,0,0,0,0,0,0,0,2,0, +0,0,0,0,0,0,39,128,215,246,238,229,220,212,204,196, +189,181,173,167,160,154,148,142,138,134,128,127,125,122,122,122, +122,124,127,128,132,136,142,147,152,159,165,172,179,187,194,202, +210,218,227,235,244,232,149,62,0,0,0,0,0,0,0,0, +0,0,0,0,1,15,21,28,35,41,48,54,61,67,72,78, +85,91,95,100,105,109,113,117,121,124,127,128,129,131,131,131, +131,130,128,127,125,122,119,115,111,107,101,96,91,85,80,75, +69,62,56,50,43,37,29,23,16,8,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5, +11,12,13,18,20,22,27,28,31,35,36,38,40,42,42,42, +42,41,39,37,35,33,29,27,24,20,19,14,12,11,5,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,55,140,221,194,113,33,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +18,94,174,230,162,77,7,0,0,0,0,0,0,0,2,0, +0,0,0,0,0,0,7,81,166,240,243,234,226,218,210,203, +195,188,181,175,168,162,156,152,146,142,138,135,134,132,131,131, +132,133,135,138,142,145,150,155,160,166,173,179,186,193,201,209, +216,224,232,240,245,187,102,20,0,0,0,0,0,0,0,0, +0,0,0,0,0,11,17,24,30,37,43,50,56,61,67,74, +78,84,89,93,99,103,107,110,114,117,119,121,122,124,124,124, +124,123,122,119,117,115,111,107,103,99,95,91,85,80,75,69, +63,57,51,45,38,32,25,19,12,2,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +5,11,12,13,16,20,21,24,27,28,30,33,34,35,36,36, +35,34,33,30,28,27,25,21,20,18,13,12,11,5,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,12,87,169,231,173,95,21,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8, +73,151,223,190,108,28,0,0,0,0,0,0,0,0,2,0, +0,0,0,0,0,0,0,30,115,197,246,240,232,224,217,209, +202,195,188,182,176,170,165,160,156,152,148,145,143,142,141,141, +141,143,144,148,150,154,158,164,168,174,180,187,193,201,207,215, +223,230,238,246,218,134,52,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,2,13,19,26,32,38,45,51,56,61,67, +72,77,83,87,91,96,99,103,107,109,111,113,115,116,116,116, +116,115,114,112,109,107,103,101,97,93,88,84,79,75,69,64, +58,51,45,40,34,27,21,14,6,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,5,10,12,12,14,18,20,21,22,26,27,28,28,28,28, +28,28,27,26,23,21,20,19,16,12,12,11,5,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,33,112,191,223,157,82,16,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,64, +137,215,209,133,52,0,0,0,0,0,0,0,0,0,2,0, +0,0,0,0,0,0,0,3,60,141,220,246,239,231,223,217, +209,202,196,190,184,178,174,168,164,160,158,154,152,151,151,151, +151,152,154,157,160,164,168,172,177,182,188,194,201,207,215,221, +229,236,244,234,161,80,8,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,6,14,21,27,33,39,45,51,56,61, +67,72,77,81,85,89,93,95,99,101,104,106,107,108,108,108, +108,107,106,104,102,99,97,93,90,85,83,77,73,68,62,58, +52,46,40,35,29,22,16,9,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,8,11,12,12,14,18,20,20,20,22,22,22,22, +22,22,20,20,20,18,16,13,12,12,8,4,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,2,52,128,206,219,150,80,17,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,7,62,132, +204,219,149,72,7,0,0,0,0,0,0,0,0,0,2,0, +0,0,0,0,0,0,0,0,11,82,159,233,245,237,231,223, +217,210,204,198,192,187,182,178,174,170,167,165,162,161,160,160, +161,162,164,167,169,173,176,181,186,191,196,202,209,215,221,228, +236,243,242,179,104,27,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,9,16,21,27,34,40,45,51,56, +61,65,69,75,77,82,85,89,91,94,96,98,99,100,100,100, +100,100,98,96,94,92,89,86,83,79,75,71,67,61,56,51, +45,40,35,29,24,18,11,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,5,10,12,12,12,14,14,18,18,18,20,20, +19,18,18,16,14,12,12,12,10,5,2,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,6,65,140,212,217,150,86,23, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,12,68,134,202, +222,158,85,14,0,0,0,0,0,0,0,0,0,0,3,0, +0,0,0,0,0,0,0,0,0,24,97,173,237,244,237,231, +224,218,212,206,200,196,191,186,183,180,176,175,173,171,170,169, +171,173,174,176,178,182,186,190,194,200,205,210,216,223,229,236, +243,244,191,118,39,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,2,11,16,22,28,34,39,44,49, +53,59,63,67,71,75,78,81,84,86,88,90,91,92,92,92, +92,92,90,89,87,84,82,79,75,72,68,64,59,55,51,45, +40,35,29,24,19,12,2,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,2,5,10,11,12,12,12,12,12,13,14, +12,12,12,12,12,12,10,5,2,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,9,72,142,211,220,159,96, +36,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,27,82,143,207,222, +159,90,22,0,0,0,0,0,0,0,0,0,0,0,1,0, +0,0,0,0,0,0,0,0,0,0,33,107,178,237,245,238, +232,226,220,214,209,204,200,196,192,190,186,184,183,181,181,181, +181,183,183,185,188,191,195,199,203,208,213,218,224,230,236,243, +244,195,125,51,3,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,11,16,22,27,33,37,43, +47,52,56,60,64,67,71,74,76,78,80,82,83,84,84,84, +84,84,82,81,79,77,75,71,68,65,61,57,53,49,44,39, +35,29,24,19,13,3,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,2,4,7,10,10,11,12,12,12, +12,12,10,10,8,4,2,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,9,71,137,201,228,175, +120,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,12,51,105,161,219,217,153, +88,23,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +0,0,0,0,0,0,0,0,0,0,0,36,107,174,233,246, +240,234,228,222,218,214,208,206,202,199,196,193,192,191,191,191, +191,191,193,196,198,200,204,208,212,216,222,227,232,238,244,242, +191,125,54,5,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,2,11,16,21,27,32,37, +41,45,49,53,57,60,63,66,69,71,73,74,76,76,76,76, +76,76,74,73,71,69,67,64,61,58,54,51,46,43,37,33, +28,23,18,13,3,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,2,4,4,4,4, +4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,8,64,128,185,231, +202,148,100,52,16,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,10,41,87,136,188,231,201,142,80, +20,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +0,0,0,0,0,0,0,0,0,0,0,0,34,102,165,223, +248,242,236,232,226,222,218,214,211,208,206,204,201,201,199,199, +201,201,204,206,207,210,214,216,222,226,230,235,240,246,234,179, +118,51,5,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,2,11,16,21,25,29, +35,39,43,46,50,53,56,59,61,63,65,66,68,68,68,68, +68,68,66,65,64,61,59,57,53,51,47,43,39,35,31,27, +21,17,11,3,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,5,48,106,163, +218,226,185,140,99,60,28,10,0,0,0,0,0,0,0,0, +0,0,0,0,5,20,52,89,129,174,219,221,176,121,64,9, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,27,88,145, +204,244,245,240,236,231,227,224,221,217,215,214,213,211,209,209, +211,212,213,215,217,220,223,226,230,234,238,244,245,218,161,104, +39,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,2,8,13,19,23, +27,31,35,39,43,45,49,51,53,55,57,58,60,60,60,60, +60,60,59,58,56,54,52,49,46,43,39,37,33,29,24,20, +15,11,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,80, +131,181,224,224,190,154,119,90,64,40,24,17,12,10,10,11, +16,22,36,58,84,111,143,180,219,228,193,145,93,38,5,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,66, +123,174,223,245,244,240,236,232,230,228,225,223,222,221,221,221, +221,222,223,224,226,230,232,236,239,244,248,232,187,134,80,27, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,6,12,17, +21,25,29,31,35,38,41,43,46,48,49,50,52,52,52,52, +52,52,51,50,48,46,44,42,39,36,33,29,25,21,17,13, +8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7, +46,95,139,182,220,228,211,185,159,137,120,108,99,93,92,97, +105,120,135,153,179,205,228,223,192,150,106,60,16,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5, +36,90,138,184,225,246,246,242,239,238,234,233,231,231,231,231, +231,231,232,234,237,239,242,246,246,233,195,149,102,52,8,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,11, +13,17,21,25,28,31,33,36,38,40,42,42,44,44,44,44, +44,44,43,42,40,38,36,34,31,29,25,22,19,15,11,5, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,15,50,91,129,163,195,221,226,227,219,207,198,194,193,196, +204,215,227,226,223,203,171,138,101,60,20,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,12,51,95,136,175,211,235,245,247,245,243,241,241,239,239, +240,241,242,245,247,246,239,219,183,146,105,62,20,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +5,11,13,17,21,23,26,28,30,32,34,35,36,36,36,36, +36,36,35,34,32,31,29,27,24,21,19,15,11,5,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,11,35,68,100,126,149,167,183,197,204,211,211,207, +199,187,174,153,131,108,76,44,16,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,14,45,83,116,147,173,197,216,229,236,239,241,241, +241,237,232,223,202,179,155,124,92,55,19,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,5,10,13,15,18,20,22,24,26,27,28,28,28,28, +28,28,27,26,25,23,21,19,17,13,11,5,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,14,30,52,72,88,98,107,110,112,108, +101,89,74,56,35,18,3,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,5,22,52,78,102,120,135,147,155,161,162, +156,150,137,124,105,84,60,29,10,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,2,6,11,13,15,16,18,19,20,20,20,20, +20,20,20,18,17,15,13,11,8,4,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,7,12,16,18,18,17, +13,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,3,13,24,39,49,57,61,61, +59,51,40,24,16,5,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,2,5,6,10,11,12,12,11,10, +10,10,10,8,7,4,3,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,2,5,8,7,4, +3,3,2,2,2,1,0,0,0,0,2,8,12,14,10,5, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +} ; + +unsigned char *_ssgaGetLensFlareTexture () { return lens_flare_texture ; } + diff --git a/src/ssgAux/ssgaParticleSystem.cxx b/src/ssgAux/ssgaParticleSystem.cxx new file mode 100644 index 0000000..d613bab --- /dev/null +++ b/src/ssgAux/ssgaParticleSystem.cxx @@ -0,0 +1,205 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + +*/ + +#include "ssgAux.h" + +ssgaParticleSystem::ssgaParticleSystem ( int num, int initial_num, + float _create_rate, int _ttf, + float sz, float bsphere_size, + ssgaParticleCreateFunc _particle_create, + ssgaParticleUpdateFunc _particle_update, + ssgaParticleDeleteFunc _particle_delete ) : + ssgVtxTable ( GL_QUADS, + new ssgVertexArray ( num * 4, new sgVec3 [ num * 4 ] ), + new ssgNormalArray ( num * 4, new sgVec3 [ num * 4 ] ), + new ssgTexCoordArray ( num * 4, new sgVec2 [ num * 4 ] ), + new ssgColourArray ( num * 4, new sgVec4 [ num * 4 ] ) ) +{ + turn_to_face = _ttf ; + create_error = 0 ; + create_rate = _create_rate ; + particle_create = _particle_create ; + particle_update = _particle_update ; + particle_delete = _particle_delete ; + + size = sz ; + + num_particles = num ; + num_verts = num * 4 ; + + getBSphere () -> setRadius ( bsphere_size ) ; + getBSphere () -> setCenter ( 0, 0, 0 ) ; + + particle = new ssgaParticle [ num ] ; + + int i ; + + for ( i = 0 ; i < num_verts ; i++ ) + { + sgSetVec3 ( getNormal ( i ), 0, -1, 0 ) ; + sgSetVec4 ( getColour ( i ), 1, 1, 1, 1 ) ; + sgZeroVec3 ( getVertex ( i ) ) ; + } + + for ( i = 0 ; i < num_particles ; i++ ) + { + sgSetVec2 ( getTexCoord ( i*4+0 ), 0, 0 ) ; + sgSetVec2 ( getTexCoord ( i*4+1 ), 1, 0 ) ; + sgSetVec2 ( getTexCoord ( i*4+2 ), 1, 1 ) ; + sgSetVec2 ( getTexCoord ( i*4+3 ), 0, 1 ) ; + } + + num_active = 0 ; + + if ( particle_create ) + for ( i = 0 ; i < initial_num ; i++ ) + (*particle_create) ( this, i, & particle [ i ] ) ; +} + + +void ssgaParticleSystem::draw_geometry () +{ + sgVec3 nxny, xxny, xxyy, nxyy ; + + float sz = size / 2.0f ; + + if ( turn_to_face ) + { + sgMat4 mat ; + + glGetFloatv ( GL_MODELVIEW_MATRIX, (float *) mat ) ; + + sgVec3 xx, yy ; + + sgSetVec3 ( xx, mat[0][0] * sz, mat[1][0] * sz, mat[2][0] * sz ) ; + sgSetVec3 ( yy, mat[0][1] * sz, mat[1][1] * sz, mat[2][1] * sz ) ; + + sgSetVec3 ( nxny, -xx[0]-yy[0], -xx[1]-yy[1], -xx[2]-yy[2] ) ; + sgSetVec3 ( nxyy, -xx[0]+yy[0], -xx[1]+yy[1], -xx[2]+yy[2] ) ; + sgSetVec3 ( xxny, xx[0]-yy[0], xx[1]-yy[1], xx[2]-yy[2] ) ; + sgSetVec3 ( xxyy, xx[0]+yy[0], xx[1]+yy[1], xx[2]+yy[2] ) ; + } + else + { + sgSetVec3 ( xxny , sz, 0, -sz ) ; + sgSetVec3 ( nxny , -sz, 0, -sz ) ; + sgSetVec3 ( nxyy , -sz, 0, sz ) ; + sgSetVec3 ( xxyy, sz, 0, sz ) ; + } + + int j = 0 ; + + for ( int i = 0 ; i < num_particles ; i++ ) + { + /* Make them disappear if not needed */ + + if ( particle[i].time_to_live <= 0.0f ) + continue ; + + sgCopyVec4 ( getColour ( j + 0 ), particle[i].col ) ; + sgCopyVec4 ( getColour ( j + 1 ), particle[i].col ) ; + sgCopyVec4 ( getColour ( j + 2 ), particle[i].col ) ; + sgCopyVec4 ( getColour ( j + 3 ), particle[i].col ) ; + + sgAddScaledVec3 ( getVertex ( j + 0 ), particle[i].pos, + nxny, particle[i].size ) ; + sgAddScaledVec3 ( getVertex ( j + 1 ), particle[i].pos, + xxny, particle[i].size ) ; + sgAddScaledVec3 ( getVertex ( j + 2 ), particle[i].pos, + xxyy, particle[i].size ) ; + sgAddScaledVec3 ( getVertex ( j + 3 ), particle[i].pos, + nxyy, particle[i].size ) ; + + j += 4 ; + } + + rawSetNumVertices ( j ) ; /* Avoid drawing more than 'j' vertices. */ + + if ( j > 0 ) + { + glDisable ( GL_CULL_FACE ) ; + glDepthMask ( 0 ) ; + + ssgVtxTable::draw_geometry () ; + + glDepthMask ( 1 ) ; + glEnable ( GL_CULL_FACE ) ; + } +} + + +ssgaParticleSystem::~ssgaParticleSystem () +{ + if ( particle_delete ) + for ( int i = 0 ; i < num_particles ; i++ ) + if ( particle [ i ] . time_to_live >= 0.0 ) + (*particle_delete) ( this, i, & particle [ i ] ) ; + + delete [] particle ; +} + + +void ssgaParticleSystem::update ( float t ) +{ + int i ; + + create_error += create_rate * t ; + + num_active = 0 ; + + /* Call the update routine for all the particles */ + + if ( particle_update ) + { + for ( i = 0 ; i < num_particles ; i++ ) + if ( particle [ i ] . time_to_live > 0.0f ) + { + particle [ i ] . update ( t ) ; + (*particle_update) ( t, this, i, & particle [ i ] ) ; + } + } + else + for ( i = 0 ; i < num_particles ; i++ ) + if ( particle [ i ] . time_to_live > 0.0f ) + particle [ i ] . update ( t ) ; + + /* Check for death of particles */ + + for ( i = 0 ; i < num_particles ; i++ ) + if ( particle [ i ] . time_to_live <= 0.0 ) + { + if ( particle_delete ) + (*particle_delete) ( this, i, & particle [ i ] ) ; + + particle [ i ] . pos [ 2 ] = -1000000.0f ; + + if ( create_error >= 1.0f && particle_create ) + { + (*particle_create) ( this, i, & particle [ i ] ) ; + create_error -= 1.0f ; + } + } + else + num_active++ ; +} + + diff --git a/src/ssgAux/ssgaParticleSystem.h b/src/ssgAux/ssgaParticleSystem.h new file mode 100644 index 0000000..a55ed5c --- /dev/null +++ b/src/ssgAux/ssgaParticleSystem.h @@ -0,0 +1,115 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net */ + + + +class ssgaParticle +{ +public: + + sgVec4 col ; + sgVec3 pos ; + sgVec3 vel ; + sgVec3 acc ; + + float size ; + + float time_to_live ; + void *userData ; + + void update ( float dt ) + { + sgAddScaledVec3 ( vel, acc, dt ) ; + sgAddScaledVec3 ( pos, vel, dt ) ; + time_to_live -= dt ; + } + + ssgaParticle () + { + sgSetVec4 ( col, 1, 1, 1, 1 ) ; + sgZeroVec3 ( pos ) ; + sgZeroVec3 ( vel ) ; + sgZeroVec3 ( acc ) ; + time_to_live = 0 ; + userData = NULL ; + size = 1.0f ; + } + +} ; + + +class ssgaParticleSystem ; + + +typedef void (* ssgaParticleCreateFunc) ( ssgaParticleSystem *ps, + int index, + ssgaParticle *p ) ; + +typedef void (* ssgaParticleUpdateFunc) ( float deltaTime, + ssgaParticleSystem *ps, + int index, + ssgaParticle *p ) ; + +typedef void (* ssgaParticleDeleteFunc) ( ssgaParticleSystem *ps, + int index, + ssgaParticle *p ) ; + +class ssgaParticleSystem : public ssgVtxTable +{ + int num_particles ; + int num_verts ; + int turn_to_face ; + int num_active ; + ssgaParticle *particle ; + + float create_error ; + float create_rate ; + + float size ; + + ssgaParticleCreateFunc particle_create ; + ssgaParticleUpdateFunc particle_update ; + ssgaParticleDeleteFunc particle_delete ; + +public: + + ssgaParticleSystem ( int num, int initial_num, + float _create_rate, int _turn_to_face, + float sz, float bsphere_size, + ssgaParticleCreateFunc _particle_create, + ssgaParticleUpdateFunc _particle_update = NULL, + ssgaParticleDeleteFunc _particle_delete = NULL ) ; + + virtual ~ssgaParticleSystem () ; + virtual void update ( float t ) ; + + void setSize ( float sz ) { size = sz ; } + float getSize () { return size ; } + + void draw_geometry () ; + + void setCreationRate ( float cr ) { create_rate = cr ; } + float getCreationRate () { return create_rate ; } + + int getNumParticles () { return num_particles ; } + int getNumActiveParticles () { return num_active ; } +} ; + + diff --git a/src/ssgAux/ssgaPatch.cxx b/src/ssgAux/ssgaPatch.cxx new file mode 100644 index 0000000..3d46dc4 --- /dev/null +++ b/src/ssgAux/ssgaPatch.cxx @@ -0,0 +1,238 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgaPatch.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "ssgAux.h" +#include + +typedef float sgVec9 [9] ; + +void ssgaPatch::regenerate () +{ + if ( kidState != NULL ) kidState -> ref () ; + removeAllKids () ; + if ( kidState != NULL ) kidState -> deRef () ; + + if ( ntriangles <= 2 ) levels = -1 ; else + if ( ntriangles <= 18 ) levels = 0 ; else + if ( ntriangles <= 4*18 ) levels = 1 ; else + if ( ntriangles <= 16*18 ) levels = 2 ; else + if ( ntriangles <= 64*18 ) levels = 3 ; else + if ( ntriangles <= 256*18 ) levels = 4 ; else + if ( ntriangles <= 1024*18 ) levels = 5 ; else + if ( ntriangles <= 4096*18 ) levels = 6 ; else levels = 7 ; + + if ( ntriangles == 0 || control_points == NULL ) + return ; + + makePatch ( control_points, levels ) ; + + /* + vt0 -> setState ( getKidState () ) ; + vt0 -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB () ) ; + vt0 -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ; + vt0 -> recalcBSphere () ; + */ + + recalcBSphere () ; +} + + +static float *sgMidPointVec9 ( sgVec9 a, sgVec9 b ) +{ + static sgVec9 r ; + + r[0] = (a[0] + b[0])/2.0f ; + r[1] = (a[1] + b[1])/2.0f ; + r[2] = (a[2] + b[2])/2.0f ; + r[3] = (a[3] + b[3])/2.0f ; + r[4] = (a[4] + b[4])/2.0f ; + r[5] = (a[5] + b[5])/2.0f ; + r[6] = (a[6] + b[6])/2.0f ; + r[7] = (a[7] + b[7])/2.0f ; + r[8] = (a[8] + b[8])/2.0f ; + + return r ; +} + + +void ssgaPatch::makeHSpline ( sgVec9 points[4], sgVec9 newVts[7] ) +{ + sgVec9 temp ; + + memcpy ( newVts[0], points[0],sizeof(sgVec9)); + memcpy ( newVts[1], sgMidPointVec9 ( points[0], points[1] ),sizeof(sgVec9)); + memcpy ( temp , sgMidPointVec9 ( points[1], points[2] ),sizeof(sgVec9)); + memcpy ( newVts[2], sgMidPointVec9 ( newVts[1], temp ),sizeof(sgVec9)); + memcpy ( newVts[5], sgMidPointVec9 ( points[2], points[3] ),sizeof(sgVec9)); + memcpy ( newVts[4], sgMidPointVec9 ( temp , newVts[5] ),sizeof(sgVec9)); + memcpy ( newVts[3], sgMidPointVec9 ( newVts[2], newVts[4] ),sizeof(sgVec9)); + memcpy ( newVts[6], points[3],sizeof(sgVec9)); +} + + +void ssgaPatch::makeVSplines ( sgVec9 hv[4][7], sgVec9 nv[7][7] ) +{ + sgVec9 temp ; + + for ( int col = 0 ; col < 7 ; col++ ) + { + memcpy ( nv[0][col], hv[0][col], sizeof(sgVec9) ) ; + memcpy ( nv[1][col],sgMidPointVec9(hv[0][col], hv[1][col]), sizeof(sgVec9)); + memcpy ( temp ,sgMidPointVec9(hv[1][col], hv[2][col]), sizeof(sgVec9)); + memcpy ( nv[2][col],sgMidPointVec9(nv[1][col], temp ), sizeof(sgVec9)); + memcpy ( nv[5][col],sgMidPointVec9(hv[2][col], hv[3][col]), sizeof(sgVec9)); + memcpy ( nv[4][col],sgMidPointVec9(temp , nv[5][col]), sizeof(sgVec9)); + memcpy ( nv[3][col],sgMidPointVec9(nv[2][col], nv[4][col]), sizeof(sgVec9)); + memcpy ( nv[6][col], hv[3][col], sizeof(sgVec9) ) ; + } +} + + +void ssgaPatch::writePatch ( sgVec9 points[4][4] ) +{ + sgVec3 nn = { 0,0,1 } ; + + /* + Write three strips of 8 vertices each + */ + + for ( int i = 0 ; i < 3 ; i++ ) + { + ssgVertexArray *va = new ssgVertexArray ( 8 ) ; + ssgTexCoordArray *ta = new ssgTexCoordArray ( 8 ) ; + ssgColourArray *ca = new ssgColourArray ( 8 ) ; + ssgNormalArray *na = new ssgNormalArray ( 8 ) ; + + for ( int j = 0 ; j < 4 ; j++ ) + { + sgVec3 vv ; + + sgSetVec3 ( vv, points [ i ][j][0] * size[0] + center[0], + points [ i ][j][1] * size[1] + center[1], + points [ i ][j][2] * size[2] + center[2] ) ; + + va -> add ( vv ) ; + ta -> add ( & ( points [ i ][j][ 3 ] ) ) ; + ca -> add ( & ( points [ i ][j][ 5 ] ) ) ; + na -> add ( nn ) ; + + sgSetVec3 ( vv, points [i+1][j][0] * size[0] + center[0], + points [i+1][j][1] * size[1] + center[1], + points [i+1][j][2] * size[2] + center[2] ) ; + + va -> add ( vv ) ; + ta -> add ( & ( points [i+1][j][ 3 ] ) ) ; + ca -> add ( & ( points [i+1][j][ 5 ] ) ) ; + na -> add ( nn ) ; + } + + ssgVtxTable *vt = new ssgVtxTable ( GL_TRIANGLE_STRIP, va,na,ta,ca ) ; + vt -> setState ( getKidState () ) ; + vt -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB () ) ; + vt -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ; + + addKid ( vt ) ; + } +} + + + +void ssgaPatch::makePatch ( float points[4][4][9], int level ) +{ + if ( level <= 0 ) + { + writePatch ( points ) ; + return ; + } + + sgVec9 newHVerts [ 4 ][ 7 ] ; + sgVec9 newVertices [ 7 ][ 7 ] ; + + makeHSpline ( points[0], newHVerts[0] ) ; + makeHSpline ( points[1], newHVerts[1] ) ; + makeHSpline ( points[2], newHVerts[2] ) ; + makeHSpline ( points[3], newHVerts[3] ) ; + + makeVSplines ( newHVerts, newVertices ) ; + + sgVec9 patch[4][4] ; + int i ; + + for ( i = 0 ; i < 16 ; i++ ) + memcpy ( patch[i>>2][i&3], newVertices[i>>2][i&3], 9*sizeof(float) ) ; + + makePatch ( patch, level-1 ) ; + + for ( i = 0 ; i < 16 ; i++ ) + memcpy ( patch[i>>2][i&3], newVertices[i>>2][3+(i&3)], 9*sizeof(float) ) ; + + makePatch ( patch, level-1 ) ; + + for ( i = 0 ; i < 16 ; i++ ) + memcpy ( patch[i>>2][i&3], newVertices[3+(i>>2)][i&3], 9*sizeof(float) ) ; + + makePatch ( patch, level-1 ) ; + + for ( i = 0 ; i < 16 ; i++ ) + memcpy ( patch[i>>2][i&3], newVertices[3+(i>>2)][3+(i&3)], 9*sizeof(float)); + + makePatch ( patch, level-1 ) ; +} + + +void ssgaPatch::setControlPoint ( int s, int t, + float x, float y, float z, + float u, float v, + float r, float g, float b, float a ) +{ + control_points[s][t][0] = x ; + control_points[s][t][1] = y ; + control_points[s][t][2] = z ; + control_points[s][t][3] = u ; + control_points[s][t][4] = v ; + control_points[s][t][5] = r ; + control_points[s][t][6] = g ; + control_points[s][t][7] = b ; + control_points[s][t][8] = a ; +} + + +void ssgaPatch::setControlPoint ( int s, int t, + sgVec3 xyz, sgVec2 uv, sgVec4 rgba ) +{ + memcpy ( &(control_points[s][t][0]), xyz , sizeof(sgVec3) ) ; + memcpy ( &(control_points[s][t][3]), uv , sizeof(sgVec2) ) ; + memcpy ( &(control_points[s][t][5]), rgba, sizeof(sgVec4) ) ; +} + + +void ssgaPatch::getControlPoint ( int s, int t, + sgVec3 xyz, sgVec2 uv, sgVec4 rgba ) +{ + memcpy ( xyz, &(control_points[s][t][0]), sizeof(sgVec3) ) ; + memcpy ( uv , &(control_points[s][t][3]), sizeof(sgVec2) ) ; + memcpy ( rgba, &(control_points[s][t][5]), sizeof(sgVec4) ) ; +} + + diff --git a/src/ssgAux/ssgaScreenDump.cxx b/src/ssgAux/ssgaScreenDump.cxx new file mode 100644 index 0000000..3b3a43c --- /dev/null +++ b/src/ssgAux/ssgaScreenDump.cxx @@ -0,0 +1,204 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgaScreenDump.cxx 1996 2004-12-29 07:19:40Z sjbaker $ +*/ + + +#include "ssgAux.h" +#include + + +#include "ul.h" + +static void writeByte ( FILE *fd, unsigned char x ) +{ + fwrite ( & x, sizeof(unsigned char), 1, fd ) ; +} + + +static void writeShort ( FILE *fd, unsigned short x ) +{ + x = ulEndianBig16 ( x ) ; + fwrite ( & x, sizeof(unsigned short), 1, fd ) ; +} + + +static void writeInt ( FILE *fd, unsigned int x ) +{ + x = ulEndianBig32 ( x ) ; + fwrite ( & x, sizeof(unsigned int), 1, fd ) ; +} + + +void ssgaScreenDepthDump ( char *filename, + int xsize, int ysize, int frontBuffer ) +{ + FILE *fd = fopen ( filename, "wb" ) ; + + if ( fd == NULL ) + { + fprintf ( stderr, "Failed to open '%s' for writing screendepthdump.\n", + filename ) ; + return ; + } + + unsigned char *row = new unsigned char [ xsize ] ; + unsigned int *buffer = ssgaScreenDepthDump ( xsize, ysize, frontBuffer ) ; + + char type = 0 /* RGB_IMG_VERBATIM */ ; + short dim = 3 ; + short zsize = 3 ; + char bpp = 1 ; + int min = 0 ; + int max = 255 ; + short magic = 0x01DA /* RGB_IMG_MAGIC */ ; + int colormap = 0 ; + int i ; + + writeShort ( fd, magic ) ; + writeByte ( fd, type ) ; + writeByte ( fd, bpp ) ; + writeShort ( fd, dim ) ; + writeShort ( fd, xsize ) ; + writeShort ( fd, ysize ) ; + writeShort ( fd, zsize ) ; + writeInt ( fd, min ) ; + writeInt ( fd, max ) ; + writeInt ( fd, 0 ) ; /* Dummy field */ + + for ( i = 0 ; i < 80 ; i++ ) + writeByte ( fd, '\0' ) ; /* Name field */ + + writeInt ( fd, colormap ) ; + + for ( i = 0 ; i < 404 ; i++ ) + writeByte ( fd, 0 ) ; /* Dummy field */ + + for ( int z = 0 ; z < 3 ; z++ ) + for ( int y = 0 ; y < ysize ; y++ ) + { + for ( i = 0 ; i < xsize ; i++ ) + row [ i ] = ((buffer [ y * xsize + i ] >> (8*z)) & 0xFF) ; + + fseek ( fd, ( z * ysize + y ) * xsize + 512, SEEK_SET ) ; + fwrite ( row, 1, xsize, fd ) ; + } + + fclose ( fd ) ; + + delete row ; + delete buffer ; +} + + +void ssgaScreenDump ( char *filename, int xsize, int ysize, int frontBuffer ) +{ + FILE *fd = fopen ( filename, "wb" ) ; + + if ( fd == NULL ) + { + fprintf ( stderr, "Failed to open '%s' for writing screendump.\n", + filename ) ; + return ; + } + + unsigned char *row = new unsigned char [ xsize ] ; + unsigned char *buffer = ssgaScreenDump ( xsize, ysize, frontBuffer ) ; + + char type = 0 /* RGB_IMG_VERBATIM */ ; + short dim = 3 ; + short zsize = 3 ; + char bpp = 1 ; + int min = 0 ; + int max = 255 ; + short magic = 0x01DA /* RGB_IMG_MAGIC */ ; + int colormap = 0 ; + int i ; + + writeShort ( fd, magic ) ; + writeByte ( fd, type ) ; + writeByte ( fd, bpp ) ; + writeShort ( fd, dim ) ; + writeShort ( fd, xsize ) ; + writeShort ( fd, ysize ) ; + writeShort ( fd, zsize ) ; + writeInt ( fd, min ) ; + writeInt ( fd, max ) ; + writeInt ( fd, 0 ) ; /* Dummy field */ + + for ( i = 0 ; i < 80 ; i++ ) + writeByte ( fd, '\0' ) ; /* Name field */ + + writeInt ( fd, colormap ) ; + + for ( i = 0 ; i < 404 ; i++ ) + writeByte ( fd, 0 ) ; /* Dummy field */ + + for ( int z = 0 ; z < 3 ; z++ ) + for ( int y = 0 ; y < ysize ; y++ ) + { + for ( i = 0 ; i < xsize ; i++ ) + row [ i ] = buffer [ ( y * xsize + i ) * 3 + z ] ; + + fseek ( fd, ( z * ysize + y ) * xsize + 512, SEEK_SET ) ; + fwrite ( row, 1, xsize, fd ) ; + } + + fclose ( fd ) ; + + delete row ; + delete buffer ; +} + + +unsigned char *ssgaScreenDump ( int xsize, int ysize, int frontBuffer ) +{ + unsigned char *buffer = new unsigned char [ xsize * ysize * 3 ] ; + + if ( frontBuffer ) + glReadBuffer ( GL_FRONT ) ; + + glReadPixels( 0, 0, xsize, ysize, GL_RGB, GL_UNSIGNED_BYTE, + (void *) buffer ) ; + if ( frontBuffer ) + glReadBuffer ( GL_BACK ) ; + + return buffer ; +} + + + +unsigned int *ssgaScreenDepthDump ( int xsize, int ysize, int frontBuffer ) +{ + unsigned int *buffer = new unsigned int [ xsize * ysize ] ; + + if ( frontBuffer ) + glReadBuffer ( GL_FRONT ) ; + + glReadPixels( 0, 0, xsize, ysize, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, + (void *) buffer ) ; + if ( frontBuffer ) + glReadBuffer ( GL_BACK ) ; + + return buffer ; +} + + diff --git a/src/ssgAux/ssgaScreenDump.h b/src/ssgAux/ssgaScreenDump.h new file mode 100644 index 0000000..38c8616 --- /dev/null +++ b/src/ssgAux/ssgaScreenDump.h @@ -0,0 +1,21 @@ + +/* Dump to disk in '.rgb' format */ + +void ssgaScreenDump ( char *filename, + int width, int height, + int frontBuffer = TRUE ) ; + +/* Put low order 24 bits to disk (R=lsb, G=middle byte, B=msb) */ + +void ssgaScreenDepthDump ( char *filename, + int width, int height, + int frontBuffer = TRUE ) ; + +/* Dump to a memory buffer - three bytes per pixel */ + +unsigned char *ssgaScreenDump ( int width, int height, + int frontBuffer = TRUE ) ; + +unsigned int *ssgaScreenDepthDump ( int width, int height, + int frontBuffer = TRUE ) ; + diff --git a/src/ssgAux/ssgaShapes.cxx b/src/ssgAux/ssgaShapes.cxx new file mode 100644 index 0000000..d0db7cd --- /dev/null +++ b/src/ssgAux/ssgaShapes.cxx @@ -0,0 +1,860 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgaShapes.cxx 2015 2005-02-02 15:48:09Z sjbaker $ +*/ + + +#include "ssgAux.h" +#include + +#define SIN(x) ((float)(sin(x))) +#define COS(x) ((float)(cos(x))) +#define ATAN2(x, y) ((float)(atan2(x, y))) + + +void ssgaShape::copy_from ( ssgaShape *src, int clone_flags ) +{ + ssgBranch::copy_from ( src, clone_flags ) ; + if ( src -> isCorrupt () ) makeCorrupt () ; + sgCopyVec4 ( colour, src->colour ) ; + sgCopyVec3 ( center, src->center ) ; + sgCopyVec3 ( size , src->size ) ; + ntriangles = src -> ntriangles ; + kidState = src -> getKidState () ; + kidPreDrawCB = src -> getKidPreDrawCB () ; + kidPostDrawCB = src -> getKidPostDrawCB () ; +} + + +void ssgaCube ::copy_from ( ssgaCube *src, int clone_flags ) { ssgaShape::copy_from ( src, clone_flags ) ;} +void ssgaSphere ::copy_from ( ssgaSphere *src, int clone_flags ) { ssgaShape::copy_from ( src, clone_flags ) ;} +void ssgaCylinder::copy_from ( ssgaCylinder *src, int clone_flags ) { ssgaShape::copy_from ( src, clone_flags ) ;} +void ssgaPatch ::copy_from ( ssgaPatch *src, int clone_flags ) { ssgaShape::copy_from ( src, clone_flags ) ;} +void ssgaTeapot ::copy_from ( ssgaTeapot *src, int clone_flags ) { ssgaShape::copy_from ( src, clone_flags ) ;} + + + +ssgBase *ssgaShape ::clone ( int clone_flags ) +{ +/* + ssgaShape *b = new ssgaShape ; + b -> copy_from ( this, clone_flags ) ; + return b ; +*/ + return NULL ; +} + + +ssgBase *ssgaCube ::clone ( int clone_flags ) +{ + ssgaCube *b = new ssgaCube ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgBase *ssgaSphere ::clone ( int clone_flags ) +{ + ssgaSphere *b = new ssgaSphere ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgBase *ssgaTeapot::clone ( int clone_flags ) +{ + ssgaTeapot *b = new ssgaTeapot ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgBase *ssgaPatch::clone ( int clone_flags ) +{ + ssgaPatch *b = new ssgaPatch ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgBase *ssgaCylinder::clone ( int clone_flags ) +{ + ssgaCylinder *b = new ssgaCylinder ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgaShape::ssgaShape (void) +{ + ntriangles = 50 ; + init () ; +} + +ssgaShape::ssgaShape ( int np ) +{ + ntriangles = np ; + init () ; +} + +void ssgaShape::init () +{ + type = ssgaTypeShape () ; + corrupted = FALSE ; + sgZeroVec3 ( center ) ; + sgSetVec4 ( colour, 1.0f, 1.0f, 1.0f, 1.0f ) ; + sgSetVec3 ( size, 1.0f, 1.0f, 1.0f ) ; + kidState = NULL ; + kidPreDrawCB = NULL ; + kidPostDrawCB = NULL ; +} + +ssgaCube ::ssgaCube ( void ):ssgaShape () {type=ssgaTypeCube ();regenerate();} +ssgaCube ::ssgaCube (int nt):ssgaShape (nt){type=ssgaTypeCube ();regenerate();} +ssgaPatch::ssgaPatch( void ):ssgaShape () {type=ssgaTypePatch();regenerate();} +ssgaPatch::ssgaPatch(int nt):ssgaShape (nt){type=ssgaTypePatch();regenerate();} +ssgaTeapot::ssgaTeapot( void ):ssgaShape () {type=ssgaTypeTeapot();regenerate();} +ssgaTeapot::ssgaTeapot(int nt):ssgaShape (nt){type=ssgaTypeTeapot();regenerate();} + +ssgaSphere ::ssgaSphere ( void ) : ssgaShape () +{ + type = ssgaTypeSphere () ; + latlong_style = TRUE ; + regenerate () ; +} + + +ssgaSphere ::ssgaSphere (int nt) : ssgaShape ( nt ) +{ + type = ssgaTypeSphere () ; + latlong_style = TRUE ; + regenerate () ; +} + + +ssgaCylinder::ssgaCylinder ( void ) : ssgaShape () +{ + type = ssgaTypeCylinder () ; + capped = TRUE ; + regenerate () ; +} + + +ssgaCylinder::ssgaCylinder (int nt) : ssgaShape ( nt ) +{ + type = ssgaTypeCylinder () ; + capped = TRUE ; + regenerate () ; +} + + +ssgaShape ::~ssgaShape (void) {} +ssgaCube ::~ssgaCube (void) {} +ssgaPatch ::~ssgaPatch (void) {} +ssgaTeapot ::~ssgaTeapot (void) {} +ssgaSphere ::~ssgaSphere (void) {} +ssgaCylinder::~ssgaCylinder (void) {} + +const char *ssgaShape ::getTypeName(void) { return "ssgaShape" ; } +const char *ssgaCube ::getTypeName(void) { return "ssgaCube" ; } +const char *ssgaSphere ::getTypeName(void) { return "ssgaSphere" ; } +const char *ssgaCylinder::getTypeName(void) { return "ssgaCylinder" ; } +const char *ssgaPatch ::getTypeName(void) { return "ssgaPatch" ; } +const char *ssgaTeapot ::getTypeName(void) { return "ssgaTeapot" ; } + + +void ssgaCube ::regenerate () +{ + if ( kidState != NULL ) kidState -> ref () ; + removeAllKids () ; + if ( kidState != NULL ) kidState -> deRef () ; + + if ( ntriangles == 0 ) + return ; + + ssgVtxTable *vt0 = new ssgVtxTable () ; + ssgVtxTable *vt1 = new ssgVtxTable () ; + + ssgVertexArray *v0 = new ssgVertexArray ( 8 ) ; + ssgVertexArray *v1 = new ssgVertexArray ( 8 ) ; + ssgNormalArray *n0 = new ssgNormalArray ( 8 ) ; + ssgNormalArray *n1 = new ssgNormalArray ( 8 ) ; + ssgColourArray *c0 = new ssgColourArray ( 8 ) ; + ssgColourArray *c1 = new ssgColourArray ( 8 ) ; + ssgTexCoordArray *t0 = new ssgTexCoordArray ( 8 ) ; + ssgTexCoordArray *t1 = new ssgTexCoordArray ( 8 ) ; + + vt0 -> setPrimitiveType ( GL_TRIANGLE_STRIP ) ; + vt1 -> setPrimitiveType ( GL_TRIANGLE_STRIP ) ; + + addKid ( vt0 ) ; addKid ( vt1 ) ; + + vt0 -> setState ( getKidState () ) ; + vt1 -> setState ( getKidState () ) ; + vt0 -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB () ) ; + vt1 -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB () ) ; + vt0 -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ; + vt1 -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ; + + sgVec3 v ; sgVec3 n ; sgVec2 t ; + + sgSetVec3 ( v, center[0]+size[0]/2.0f, center[1]-size[1]/2.0f, center[2]+size[2]/2.0f ) ; v0->add ( v ) ; + sgSetVec3 ( n, 1 , 0 , 0 ) ; n0->add ( n ) ; + c0->add ( colour ) ; + sgSetVec2 ( t, 0 , 1 ) ; t0->add ( t ) ; + + sgSetVec3 ( v, center[0]+size[0]/2.0f, center[1]-size[1]/2.0f, center[2]-size[2]/2.0f ) ; v0->add ( v ) ; + sgSetVec3 ( n, 1 , 0 , 0 ) ; n0->add ( n ) ; + c0->add ( colour ) ; + sgSetVec2 ( t, 0 , 0 ) ; t0->add ( t ) ; + + sgSetVec3 ( v, center[0]+size[0]/2.0f, center[1]+size[1]/2.0f, center[2]+size[2]/2.0f ) ; v0->add ( v ) ; + sgSetVec3 ( n, 1 , 0 , 0 ) ; n0->add ( n ) ; + c0->add ( colour ) ; + sgSetVec2 ( t, 1 , 1 ) ; t0->add ( t ) ; + + sgSetVec3 ( v, center[0]+size[0]/2.0f, center[1]+size[1]/2.0f, center[2]-size[2]/2.0f ) ; v0->add ( v ) ; + sgSetVec3 ( n, 1 , 0 , 0 ) ; n0->add ( n ) ; + c0->add ( colour ) ; + sgSetVec2 ( t, 1 , 0 ) ; t0->add ( t ) ; + + sgSetVec3 ( v, center[0]-size[0]/2.0f, center[1]+size[1]/2.0f, center[2]+size[2]/2.0f ) ; v0->add ( v ) ; + sgSetVec3 ( n, 0 , 1 , 0 ) ; n0->add ( n ) ; + c0->add ( colour ) ; + sgSetVec2 ( t, 2 , 1 ) ; t0->add ( t ) ; + + sgSetVec3 ( v, center[0]-size[0]/2.0f, center[1]+size[1]/2.0f, center[2]-size[2]/2.0f ) ; v0->add ( v ) ; + sgSetVec3 ( n, 0 , 1 , 0 ) ; n0->add ( n ) ; + c0->add ( colour ) ; + sgSetVec2 ( t, 2 , 0 ) ; t0->add ( t ) ; + + sgSetVec3 ( v, center[0]-size[0]/2.0f, center[1]-size[1]/2.0f, center[2]+size[2]/2.0f ) ; v0->add ( v ) ; + sgSetVec3 ( n, -1 , 0 , 0 ) ; n0->add ( n ) ; + c0->add ( colour ) ; + sgSetVec2 ( t, 3 , 1 ) ; t0->add ( t ) ; + + sgSetVec3 ( v, center[0]-size[0]/2.0f, center[1]-size[1]/2.0f, center[2]-size[2]/2.0f ) ; v0->add ( v ) ; + sgSetVec3 ( n, -1 , 0 , 0 ) ; n0->add ( n ) ; + c0->add ( colour ) ; + sgSetVec2 ( t, 3 , 0 ) ; t0->add ( t ) ; + + vt0 -> setVertices ( v0 ) ; + vt0 -> setNormals ( n0 ) ; + vt0 -> setColours ( c0 ) ; + vt0 -> setTexCoords ( t0 ) ; + + vt0 -> recalcBSphere () ; + + sgSetVec3 ( v, center[0]-size[0]/2.0f, center[1]+size[1]/2.0f, center[2]-size[2]/2.0f ) ; v1->add ( v ) ; + sgSetVec3 ( n, 0 , 0 , -1 ) ; n1->add ( n ) ; + c1->add ( colour ) ; + sgSetVec2 ( t, 0 , 0 ) ; t1->add ( t ) ; + + sgSetVec3 ( v, center[0]+size[0]/2.0f, center[1]+size[1]/2.0f, center[2]-size[2]/2.0f ) ; v1->add ( v ) ; + sgSetVec3 ( n, 0 , 0 , -1 ) ; n1->add ( n ) ; + c1->add ( colour ) ; + sgSetVec2 ( t, 1 , 0 ) ; t1->add ( t ) ; + + sgSetVec3 ( v, center[0]-size[0]/2.0f, center[1]-size[1]/2.0f, center[2]-size[2]/2.0f ) ; v1->add ( v ) ; + sgSetVec3 ( n, 0 , 0 , -1 ) ; n1->add ( n ) ; + c1->add ( colour ) ; + sgSetVec2 ( t, 0 , 1 ) ; t1->add ( t ) ; + + sgSetVec3 ( v, center[0]+size[0]/2.0f, center[1]-size[1]/2.0f, center[2]-size[2]/2.0f ) ; v1->add ( v ) ; + sgSetVec3 ( n, 0 , 0 , -1 ) ; n1->add ( n ) ; + c1->add ( colour ) ; + sgSetVec2 ( t, 1 , 1 ) ; t1->add ( t ) ; + + sgSetVec3 ( v, center[0]-size[0]/2.0f, center[1]-size[1]/2.0f, center[2]+size[2]/2.0f ) ; v1->add ( v ) ; + sgSetVec3 ( n, 0 , -1 , 0 ) ; n1->add ( n ) ; + c1->add ( colour ) ; + sgSetVec2 ( t, 0 , 2 ) ; t1->add ( t ) ; + + sgSetVec3 ( v, center[0]+size[0]/2.0f, center[1]-size[1]/2.0f, center[2]+size[2]/2.0f ) ; v1->add ( v ) ; + sgSetVec3 ( n, 0 , -1 , 0 ) ; n1->add ( n ) ; + c1->add ( colour ) ; + sgSetVec2 ( t, 1 , 2 ) ; t1->add ( t ) ; + + sgSetVec3 ( v, center[0]-size[0]/2.0f, center[1]+size[1]/2.0f, center[2]+size[2]/2.0f ) ; v1->add ( v ) ; + sgSetVec3 ( n, 0 , 0 , 1 ) ; n1->add ( n ) ; + c1->add ( colour ) ; + sgSetVec2 ( t, 0 , 3 ) ; t1->add ( t ) ; + + sgSetVec3 ( v, center[0]+size[0]/2.0f, center[1]+size[1]/2.0f, center[2]+size[2]/2.0f ) ; v1->add ( v ) ; + sgSetVec3 ( n, 0 , 0 , 1 ) ; n1->add ( n ) ; + c1->add ( colour ) ; + sgSetVec2 ( t, 1 , 3 ) ; t1->add ( t ) ; + + vt1 -> setVertices ( v1 ) ; + vt1 -> setNormals ( n1 ) ; + vt1 -> setColours ( c1 ) ; + vt1 -> setTexCoords ( t1 ) ; + + vt1 -> recalcBSphere () ; + + recalcBSphere () ; +} + + +/* + This code is 'inspired' by the function 'sphere' written by + David Blythe for GLUT 3.5 and uses his values for the coordinates + of the initial Icosahedron. +*/ + +#define CZ 0.89442719099991f /* 2/sqrt(5) */ +#define SZ 0.44721359549995f /* 1/sqrt(5) */ +#define C1 0.951056516f /* cos(18) */ +#define S1 0.309016994f /* sin(18) */ +#define C2 0.587785252f /* cos(54) */ +#define S2 0.809016994f /* sin(54) */ +#define X1 (C1*CZ) +#define Y1 (S1*CZ) +#define X2 (C2*CZ) +#define Y2 (S2*CZ) + +#define P0 { 0, 0, 1 } +#define P1 { -X2, -Y2, SZ } +#define P2 { X2, -Y2, SZ } +#define P3 { X1, Y1, SZ } +#define P4 { 0, CZ, SZ } +#define P5 { -X1, Y1, SZ } +#define P6 { -X1, -Y1, -SZ } +#define P7 { 0, -CZ, -SZ } +#define P8 { X1, -Y1, -SZ } +#define P9 { X2, Y2, -SZ } +#define PA { -X2, Y2, -SZ } +#define PB { 0, 0, -1 } + +struct Triangle +{ + sgVec3 v0, v1, v2 ; +} ; + + +static Triangle icosahedron [ 20 ] = +{ + { P0, P1, P2 }, { P0, P5, P1 }, { P0, P4, P5 }, { P0, P3, P4 }, { P0, P2, P3 }, + { P1, P6, P7 }, { P6, P1, P5 }, { P5, PA, P6 }, { PA, P5, P4 }, { P4, P9, PA }, + { P9, P4, P3 }, { P3, P8, P9 }, { P8, P3, P2 }, { P2, P7, P8 }, { P7, P2, P1 }, + { P9, P8, PB }, { PA, P9, PB }, { P6, PA, PB }, { P7, P6, PB }, { P8, P7, PB } +} ; + + + +void ssgaSphere::regenerateTessellatedIcosahedron () +{ + int tris_per_strip = 1 ; + int nstrips = 1 ; + int nt = 20 ; + + while ( nt < ntriangles ) + { + nstrips++ ; + tris_per_strip += 2 ; + nt += tris_per_strip * 20 ; + } + + /* 20 sides of an Icosahedron */ + + for ( int s = 0 ; s < 20 ; s++ ) + { + Triangle *tri = & icosahedron [ s ] ; + + for ( int i = 0 ; i < nstrips ; i++ ) + { + /* + Create a tri-strip for each row + The number of triangles in each strip is two greater + than the last one. + */ + + sgVec3 v0, v1, v2, v3, va, vb ; + + /* + t->v[0] + /\ + / \ + /____\v1 + /\ /\ + / \ / \ + /____\/vb__\v0 + /\ /\ /\ + / \ / \ / \ + /____\/____\/va__\ + /\ /\ /\ /\ + / \ / \ / \ / \ + t->v[2] /____\/____\/____\/____\ t->v[1] + v3 v2 + */ + + /* + This should be a spherical interpolation - but that's slow and + nobody can tell the difference anyway + */ + + ssgVtxTable *vt = new ssgVtxTable ; + ssgVertexArray *vv = new ssgVertexArray ( i + 3 ) ; + ssgNormalArray *nn = new ssgNormalArray ( i + 3 ) ; + ssgColourArray *cc = new ssgColourArray ( i + 3 ) ; + ssgTexCoordArray *tt = new ssgTexCoordArray ( i + 3 ) ; + + addKid ( vt ) ; + + vt -> setState ( getKidState () ) ; + vt -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB () ) ; + vt -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ; + + sgVec3 v ; sgVec3 n ; sgVec2 t ; + + vt -> setPrimitiveType ( GL_TRIANGLE_STRIP ) ; + + sgLerpVec3 ( v0, tri->v1, tri->v0, (float)(i+1) / (float) nstrips ) ; + sgLerpVec3 ( v1, tri->v1, tri->v0, (float) i / (float) nstrips ) ; + sgLerpVec3 ( v2, tri->v1, tri->v2, (float)(i+1) / (float) nstrips ) ; + sgLerpVec3 ( v3, tri->v1, tri->v2, (float) i / (float) nstrips ) ; + + sgNormalizeVec3 ( v0 ) ; + sgNormalizeVec3 ( v1 ) ; + sgNormalizeVec3 ( v2 ) ; + sgNormalizeVec3 ( v3 ) ; + + sgSetVec3 ( v, center[0]+size[0]*v0[0]/2.0f, + center[1]+size[1]*v0[1]/2.0f, + center[2]+size[2]*v0[2]/2.0f ) ; + sgSetVec3 ( n, size[0]*v0[0], + size[1]*v0[1], + size[2]*v0[2] ) ; + sgNormalizeVec3 ( n ) ; + sgSetVec2 ( t, ATAN2(n[0],n[1])/(SG_PI*2.0f)+0.5f, 0.5f+v0[2]/2.0f ) ; + vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ; + + sgSetVec3 ( v, center[0]+size[0]*v1[0]/2.0f, + center[1]+size[1]*v1[1]/2.0f, + center[2]+size[2]*v1[2]/2.0f ) ; + sgSetVec3 ( n, size[0]*v1[0], + size[1]*v1[1], + size[2]*v1[2] ) ; + sgNormalizeVec3 ( n ) ; + sgSetVec2 ( t, ATAN2(n[0],n[1])/(SG_PI*2.0f)+0.5f, 0.5f+v1[2]/2.0f ) ; + vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ; + + for ( int j = 0 ; j < i ; j++ ) + { + sgLerpVec3 ( va, v0, v2, (float)(j+1) / (float) (i+1) ) ; + sgLerpVec3 ( vb, v1, v3, (float)(j+1) / (float) i ) ; + sgNormalizeVec3 ( va ) ; + sgNormalizeVec3 ( vb ) ; + + sgSetVec3 ( v, center[0]+size[0]*va[0]/2.0f, + center[1]+size[1]*va[1]/2.0f, + center[2]+size[2]*va[2]/2.0f ) ; + sgSetVec3 ( n, size[0]*va[0], + size[1]*va[1], + size[2]*va[2] ) ; + sgNormalizeVec3 ( n ) ; + sgSetVec2 ( t, ATAN2(n[0],n[1])/(SG_PI*2.0f)+0.5f, 0.5f+va[2]/2.0f ) ; + vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ; + + sgSetVec3 ( v, center[0]+size[0]*vb[0]/2.0f, + center[1]+size[1]*vb[1]/2.0f, + center[2]+size[2]*vb[2]/2.0f ) ; + sgSetVec3 ( n, size[0]*vb[0], + size[1]*vb[1], + size[2]*vb[2] ) ; + sgNormalizeVec3 ( n ) ; + sgSetVec2 ( t, ATAN2(n[0],n[1])/(SG_PI*2.0f)+0.5f, 0.5f+vb[2]/2.0f ) ; + vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ; + } + + sgSetVec3 ( v, center[0]+size[0]*v2[0]/2.0f, + center[1]+size[1]*v2[1]/2.0f, + center[2]+size[2]*v2[2]/2.0f ) ; + sgSetVec3 ( n, size[0]*v2[0], + size[1]*v2[1], + size[2]*v2[2] ) ; + sgNormalizeVec3 ( n ) ; + sgSetVec2 ( t, ATAN2(n[0],n[1])/(SG_PI*2.0f)+0.5f, 0.5f+v2[2]/2.0f ) ; + vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ; + + vt -> setVertices ( vv ) ; + vt -> setNormals ( nn ) ; + vt -> setColours ( cc ) ; + vt -> setTexCoords ( tt ) ; + + vt -> recalcBSphere () ; + } + } + + recalcBSphere () ; +} + + +void ssgaSphere::regenerateLatLong () +{ + int stacks = (int) sqrt ( (double) ntriangles / 2.0f ) ; + + if ( stacks < 2 ) stacks = 2 ; + + int slices = ntriangles / stacks ; + + if ( slices < 3 ) slices = 3 ; + + for ( int i = 0 ; i < stacks ; i++ ) + { + ssgVtxTable *vt = new ssgVtxTable ; + ssgVertexArray *vv = new ssgVertexArray ( (slices+1)*2 ) ; + ssgNormalArray *nn = new ssgNormalArray ( (slices+1)*2 ) ; + ssgColourArray *cc = new ssgColourArray ( (slices+1)*2 ) ; + ssgTexCoordArray *tt = new ssgTexCoordArray ( (slices+1)*2 ) ; + + addKid ( vt ) ; + + vt -> setState ( getKidState () ) ; + vt -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB () ) ; + vt -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ; + + sgVec3 v ; sgVec3 n ; sgVec2 t ; + + if ( i == stacks-1 ) /* North Pole */ + { + vt -> setPrimitiveType ( GL_TRIANGLE_FAN ) ; + + sgSetVec3 ( v, center[0], center[1], center[2]+size[2]/2.0f ) ; + sgSetVec3 ( n, 0, 0, 1 ) ; + sgSetVec2 ( t, 0.5f, 1 ) ; + vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ; + + for ( int j = slices ; j >= 0 ; j-- ) + { + float a = (j==0 || j==slices) ? 0.0f : (float) j * SG_PI * 2.0f / (float) slices ; + float b = (float) i * SG_PI / (float) stacks ; + + sgSetVec3 ( v, center[0] + size[0]*SIN(a)*SIN(b)/2.0f, + center[1] + size[1]*COS(a)*SIN(b)/2.0f, + center[2] - size[2]* COS(b)/2.0f ) ; + sgSetVec3 ( n, SIN(a)*SIN(b)*size[0], + COS(a)*SIN(b)*size[1], + -COS(b)*size[2] ) ; + sgNormalizeVec3 ( n ) ; + sgSetVec2 ( t, (float)j/(float)slices, (float) i /(float)stacks ) ; + vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ; + } + } + else + if ( i == 0 ) /* South Pole */ + { + vt -> setPrimitiveType ( GL_TRIANGLE_FAN ) ; + + sgSetVec3 ( v, center[0], center[1], center[2]-size[2]/2.0f ) ; + sgSetVec3 ( n, 0, 0, -1 ) ; + sgSetVec2 ( t, 0.5, 0 ) ; + vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ; + + for ( int j = 0 ; j < slices+1 ; j++ ) + { + float a = (j==0 || j==slices) ? 0.0f : (float) j * SG_PI * 2.0f / (float) slices ; + float b = (float)(i+1) * SG_PI / (float) stacks ; + + sgSetVec3 ( v, center[0] + size[0]*SIN(a)*SIN(b)/2.0f, + center[1] + size[1]*COS(a)*SIN(b)/2.0f, + center[2] - size[2]* COS(b)/2.0f ) ; + sgSetVec3 ( n, SIN(a)*SIN(b)*size[0], + COS(a)*SIN(b)*size[1], + -COS(b)*size[2] ) ; + sgNormalizeVec3 ( n ) ; + sgSetVec2 ( t, (float)j/(float)slices, + (float)(i+1)/(float)stacks ) ; + vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ; + } + } + else + { + vt -> setPrimitiveType ( GL_TRIANGLE_STRIP ) ; + + for ( int j = 0 ; j < slices+1 ; j++ ) + { + float a = (j==0 || j==slices) ? 0.0f : (float) j * SG_PI * 2.0f / (float) slices ; + float b0 = (float) i * SG_PI / (float) stacks ; + float b1 = (float)(i+1) * SG_PI / (float) stacks ; + + sgSetVec3 ( v, center[0] + size[0]*SIN(a)*SIN(b0)/2.0f, + center[1] + size[1]*COS(a)*SIN(b0)/2.0f, + center[2] - size[2]* COS(b0)/2.0f ) ; + sgSetVec3 ( n, SIN(a)*SIN(b0)*size[0], + COS(a)*SIN(b0)*size[1], + -COS(b0)*size[2] ) ; + sgNormalizeVec3 ( n ) ; + sgSetVec2 ( t, (float)j/(float)slices, + (float)i/(float)stacks ) ; + vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ; + + sgSetVec3 ( v, center[0] + size[0]*SIN(a)*SIN(b1)/2.0f, + center[1] + size[1]*COS(a)*SIN(b1)/2.0f, + center[2] - size[2]* COS(b1)/2.0f ) ; + sgSetVec3 ( n, SIN(a)*SIN(b1)*size[0], + COS(a)*SIN(b1)*size[1], + -COS(b1)*size[2] ) ; + sgNormalizeVec3 ( n ) ; + sgSetVec2 ( t, (float)j/(float)slices, + (float)(i+1)/(float)stacks ) ; + vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ; + + } + } + + vt -> setVertices ( vv ) ; + vt -> setNormals ( nn ) ; + vt -> setColours ( cc ) ; + vt -> setTexCoords ( tt ) ; + + vt -> recalcBSphere () ; + } + + recalcBSphere () ; +} + + +void ssgaSphere::regenerate () +{ + if ( kidState != NULL ) kidState -> ref () ; + removeAllKids () ; + if ( kidState != NULL ) kidState -> deRef () ; + + if ( ntriangles == 0 ) + return ; + + if ( latlong_style ) + regenerateLatLong () ; + else + regenerateTessellatedIcosahedron () ; +} + + + +void ssgaCylinder::regenerate () +{ + if ( kidState != NULL ) kidState -> ref () ; + removeAllKids () ; + if ( kidState != NULL ) kidState -> deRef () ; + + if ( ntriangles == 0 ) + return ; + + int slices = 1 + ntriangles / 4 ; + + if ( slices < 3 ) slices = 3 ; + + ssgVtxTable *vt = new ssgVtxTable ; + ssgVertexArray *vv = new ssgVertexArray ( (slices+1)*2 ) ; + ssgNormalArray *nn = new ssgNormalArray ( (slices+1)*2 ) ; + ssgColourArray *cc = new ssgColourArray ( (slices+1)*2 ) ; + ssgTexCoordArray *tt = new ssgTexCoordArray ( (slices+1)*2 ) ; + + addKid ( vt ) ; + + vt -> setState ( getKidState () ) ; + vt -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB () ) ; + vt -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ; + + sgVec3 v ; sgVec3 n ; sgVec2 t ; + + vt -> setPrimitiveType ( GL_TRIANGLE_STRIP ) ; + + for ( int j = 0 ; j < slices+1 ; j++ ) + { + float a = (j==0 || j==slices) ? 0.0f : (float) j * SG_PI * 2.0f / (float) slices ; + + sgSetVec3 ( v, center[0] + size[0]*SIN(a)/2.0f, + center[1] + size[1]*COS(a)/2.0f, + center[2] - size[2] / 2.0f ) ; + sgSetVec3 ( n, -SIN(a) * size[0], -COS(a) * size[1], 0 ) ; + sgNormalizeVec3 ( n ) ; + sgSetVec2 ( t, (float)j/(float)slices, 0 ) ; + vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ; + + sgSetVec3 ( v, center[0] + size[0]*SIN(a)/2.0f, + center[1] + size[1]*COS(a)/2.0f, + center[2] + size[2] / 2.0f ) ; + sgSetVec3 ( n, -SIN(a) * size[0], -COS(a) * size[1], 0 ) ; + sgNormalizeVec3 ( n ) ; + sgSetVec2 ( t, (float)j/(float)slices, 1 ) ; + vv->add(v) ; nn->add(n) ; cc->add(colour) ; tt->add(t) ; + + } + + vt -> setVertices ( vv ) ; + vt -> setNormals ( nn ) ; + vt -> setColours ( cc ) ; + vt -> setTexCoords ( tt ) ; + vt -> recalcBSphere () ; + + if ( capped ) + { + ssgVtxTable *vt0 = new ssgVtxTable ; + ssgVtxTable *vt1 = new ssgVtxTable ; + + ssgVertexArray *vv0 = new ssgVertexArray ( slices ) ; + ssgNormalArray *nn0 = new ssgNormalArray ( slices ) ; + ssgColourArray *cc0 = new ssgColourArray ( slices ) ; + ssgTexCoordArray *tt0 = new ssgTexCoordArray ( slices ) ; + + ssgVertexArray *vv1 = new ssgVertexArray ( slices ) ; + ssgNormalArray *nn1 = new ssgNormalArray ( slices ) ; + ssgColourArray *cc1 = new ssgColourArray ( slices ) ; + ssgTexCoordArray *tt1 = new ssgTexCoordArray ( slices ) ; + + addKid ( vt0 ) ; + addKid ( vt1 ) ; + + vt0 -> setState ( getKidState () ) ; + vt0 -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB () ) ; + vt0 -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ; + + vt1 -> setState ( getKidState () ) ; + vt1 -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB () ) ; + vt1 -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ; + + sgVec3 v ; sgVec3 n ; sgVec2 t ; + + vt0 -> setPrimitiveType ( GL_TRIANGLE_FAN ) ; + vt1 -> setPrimitiveType ( GL_TRIANGLE_FAN ) ; + + for ( int j = 0 ; j < slices ; j++ ) + { + float a0 = (float)(1+slices-j) * SG_PI * 2.0f / (float) slices ; + float a1 = (float) j * SG_PI * 2.0f / (float) slices ; + + /* Top */ + + sgSetVec3 ( v, center[0] + size[0]*SIN(a0)/2.0f, + center[1] + size[1]*COS(a0)/2.0f, + center[2] + size[2] / 2.0f ) ; + sgSetVec3 ( n, 0, 0, 1 ) ; + sgSetVec2 ( t, 0.5f + SIN(a0)/2.0f, 0.5f + COS(a0)/2.0f ) ; + vv0->add(v) ; nn0->add(n) ; cc0->add(colour) ; tt0->add(t) ; + + /* Bottom */ + + sgSetVec3 ( v, center[0] + size[0]*SIN(a1)/2.0f, + center[1] + size[1]*COS(a1)/2.0f, + center[2] - size[2] / 2.0f ) ; + sgSetVec3 ( n, 0, 0, -1 ) ; + sgSetVec2 ( t, 0.5f + SIN(a1)/2.0f, 0.5f + COS(a1)/2.0f ) ; + vv1->add(v) ; nn1->add(n) ; cc1->add(colour) ; tt1->add(t) ; + } + + vt0 -> setVertices ( vv0 ) ; vt1 -> setVertices ( vv1 ) ; + vt0 -> setNormals ( nn0 ) ; vt1 -> setNormals ( nn1 ) ; + vt0 -> setColours ( cc0 ) ; vt1 -> setColours ( cc1 ) ; + vt0 -> setTexCoords ( tt0 ) ; vt1 -> setTexCoords ( tt1 ) ; + vt0 -> recalcBSphere () ; vt1 -> recalcBSphere () ; + } + + recalcBSphere () ; +} + + +// XXX really need these (and ssgLocal.h is not accessible): +extern int _ssgLoadObject ( FILE *, ssgBase **, int ) ; +extern int _ssgSaveObject ( FILE *, ssgBase * ) ; + + +#define load_field(fp, name) (fread(&(name), 1, sizeof(name), fp) == sizeof(name)) +#define save_field(fp, name) (fwrite(&(name), 1, sizeof(name), fp) == sizeof(name)) + + +int ssgaShape::load ( FILE *fp ) +{ + return ( load_field ( fp, corrupted ) && + load_field ( fp, colour ) && + load_field ( fp, center ) && + load_field ( fp, size ) && + load_field ( fp, ntriangles ) && + _ssgLoadObject ( fp, (ssgBase **) &kidState, ssgTypeState () ) && + ssgBranch::load ( fp ) ) ; +} + +int ssgaShape::save ( FILE *fp ) +{ + return ( save_field ( fp, corrupted ) && + save_field ( fp, colour ) && + save_field ( fp, center ) && + save_field ( fp, size ) && + save_field ( fp, ntriangles ) && + _ssgSaveObject ( fp, kidState ) && + ssgBranch::save ( fp ) ) ; +} + + +int ssgaSphere::load ( FILE *fp ) +{ + return ( load_field ( fp, latlong_style ) && + ssgaShape::load ( fp ) ) ; +} + +int ssgaSphere::save ( FILE *fp ) +{ + return ( save_field ( fp, latlong_style ) && + ssgaShape::save ( fp ) ) ; +} + + +int ssgaTeapot::load ( FILE *fp ) +{ + return ssgaShape::load ( fp ) ; +} + +int ssgaTeapot::save ( FILE *fp ) +{ + return ssgaShape::save ( fp ) ; +} + + + +int ssgaPatch::load ( FILE *fp ) +{ + return ( load_field ( fp, levels ) && + fread(control_points, 1, 16*9*sizeof(float), fp) == 16*9*sizeof(float) && + ssgaShape::load ( fp ) ) ; +} + +int ssgaPatch::save ( FILE *fp ) +{ + return ( save_field ( fp, levels ) && + fwrite(control_points, 1, 16*9*sizeof(float), fp) == 16*9*sizeof(float) && + ssgaShape::save ( fp ) ) ; +} + + +int ssgaCylinder::load ( FILE *fp ) +{ + return ( load_field ( fp, capped ) && + ssgaShape::load ( fp ) ) ; +} + +int ssgaCylinder::save ( FILE *fp ) +{ + return ( save_field ( fp, capped ) && + ssgaShape::save ( fp ) ) ; +} + + diff --git a/src/ssgAux/ssgaShapes.h b/src/ssgAux/ssgaShapes.h new file mode 100644 index 0000000..b68463a --- /dev/null +++ b/src/ssgAux/ssgaShapes.h @@ -0,0 +1,222 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgaShapes.h 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#ifndef _SSGASHAPES_H_ +#define _SSGASHAPES_H_ 1 + +#include "ssg.h" + +typedef float sgVec9 [ 9 ] ; /* Needed for ssgaPatch */ + +class ssgaShape : public ssgBranch +{ + int corrupted ; + +protected: + virtual void copy_from ( ssgaShape *src, int clone_flags ) ; + + sgVec4 colour ; + sgVec3 center ; + sgVec3 size ; + + int ntriangles ; + + ssgState *kidState ; + ssgCallback kidPreDrawCB ; + ssgCallback kidPostDrawCB ; + + void init () ; + +protected: + + ssgState *getKidState () { return kidState ; } + ssgCallback getKidPreDrawCB () { return kidPreDrawCB ; } + ssgCallback getKidPostDrawCB () { return kidPostDrawCB ; } + +public: + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgaShape (void) ; + ssgaShape ( int numtris ) ; + virtual ~ssgaShape (void) ; + virtual const char *getTypeName(void) ; + + void makeCorrupt () { corrupted = TRUE ; } + int isCorrupt () { return corrupted ; } + + float *getCenter () { return center ; } + float *getSize () { return size ; } + int getNumTris () { return ntriangles ; } + + void setColour ( sgVec4 c ) { sgCopyVec4 ( colour, c ) ; regenerate () ; } + void setCenter ( sgVec3 c ) { sgCopyVec3 ( center, c ) ; regenerate () ; } + void setSize ( sgVec3 s ) { sgCopyVec3 ( size , s ) ; regenerate () ; } + void setSize ( float s ) { sgSetVec3 ( size,s,s,s) ; regenerate () ; } + void setNumTris ( int ntri ) { ntriangles = ntri ; regenerate () ; } + + void setKidState ( ssgState *s ) + { + kidState = s ; + + for ( int i = 0 ; i < getNumKids() ; i++ ) + ((ssgLeaf *)getKid(i)) -> setState ( s ) ; + } + + void setKidCallback ( int cb_type, ssgCallback cb ) + { + if ( cb_type == SSG_CALLBACK_PREDRAW ) + kidPreDrawCB = cb ; + else + kidPostDrawCB = cb ; + + for ( int i = 0 ; i < getNumKids() ; i++ ) + ((ssgLeaf *)getKid(i)) -> setCallback ( cb_type, cb ) ; + } + + virtual void regenerate () = 0 ; + + virtual int load ( FILE * ) ; + virtual int save ( FILE * ) ; +} ; + + + +class ssgaCube : public ssgaShape +{ +protected: + virtual void copy_from ( ssgaCube *src, int clone_flags ) ; +public: + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgaCube (void) ; + ssgaCube ( int numtris ) ; + virtual ~ssgaCube (void) ; + virtual const char *getTypeName(void) ; + virtual void regenerate () ; +} ; + + + +#define SSGA_HAVE_PATCH 1 + +class ssgaPatch : public ssgaShape +{ + int levels ; + sgVec9 control_points[4][4] ; + void makePatch ( sgVec9 points[4][4], int levels ) ; + void writePatch ( sgVec9 points[4][4] ) ; + void makeHSpline ( sgVec9 points[4] , sgVec9 nv[7] ) ; + void makeVSplines ( sgVec9 points[4][7], sgVec9 nv[7][7] ) ; + + +protected: + virtual void copy_from ( ssgaPatch *src, int clone_flags ) ; +public: + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgaPatch (void) ; + ssgaPatch ( int numtris ) ; + + void setControlPoint ( int s, int t, sgVec3 xyz, sgVec2 uv, sgVec4 rgba ) ; + void setControlPoint ( int s, int t, + float x, float y, float z, + float u, float v, + float r, float g, float b, float a ) ; + void getControlPoint ( int s, int t, sgVec3 xyz, sgVec2 uv, sgVec4 rgba ) ; + + virtual ~ssgaPatch (void) ; + virtual const char *getTypeName(void) ; + virtual void regenerate () ; + + virtual int load ( FILE * ) ; + virtual int save ( FILE * ) ; +} ; + + + +#define SSGA_HAVE_TEAPOT 1 + +class ssgaTeapot : public ssgaShape +{ +protected: + virtual void copy_from ( ssgaTeapot *src, int clone_flags ) ; +public: + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgaTeapot (void) ; + ssgaTeapot ( int numtris ) ; + virtual ~ssgaTeapot (void) ; + virtual const char *getTypeName(void) ; + virtual void regenerate () ; + + virtual int load ( FILE * ) ; + virtual int save ( FILE * ) ; +} ; + + + +class ssgaSphere : public ssgaShape +{ + int latlong_style ; + + void regenerateLatLong () ; + void regenerateTessellatedIcosahedron () ; +protected: + virtual void copy_from ( ssgaSphere *src, int clone_flags ) ; +public: + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgaSphere (void) ; + ssgaSphere ( int numtris ) ; + virtual ~ssgaSphere (void) ; + virtual const char *getTypeName(void) ; + virtual void regenerate () ; + + void setLatLongStyle ( int ll ) { latlong_style = ll ; regenerate () ; } + int isLatLongStyle () { return latlong_style ; } + + virtual int load ( FILE * ) ; + virtual int save ( FILE * ) ; +} ; + + + +class ssgaCylinder : public ssgaShape +{ + int capped ; + +protected: + virtual void copy_from ( ssgaCylinder *src, int clone_flags ) ; +public: + virtual ssgBase *clone ( int clone_flags = 0 ) ; + ssgaCylinder (void) ; + ssgaCylinder ( int numtris ) ; + virtual ~ssgaCylinder (void) ; + virtual const char *getTypeName(void) ; + virtual void regenerate () ; + + void makeCapped ( int c ) { capped = c ; regenerate () ; } + int isCapped () { return capped ; } + + virtual int load ( FILE * ) ; + virtual int save ( FILE * ) ; +} ; + +#endif + diff --git a/src/ssgAux/ssgaSky.cxx b/src/ssgAux/ssgaSky.cxx new file mode 100644 index 0000000..13ec67b --- /dev/null +++ b/src/ssgAux/ssgaSky.cxx @@ -0,0 +1,402 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgaSky.cxx 1798 2003-09-26 14:54:20Z sjbaker $ +*/ + +// Written by Curtis Olson, started December 1997. +// SSG-ified by Curtis Olson, February 2000. +// +// Moved into ssgAux, July 2003. + +#include "ssgaSky.h" + + +// Used for rise/set effects (flat earth - no rotation of skydome considered here ) +void calc_celestial_angles( const sgVec3 body, const sgVec3 view, double& angle, double& rotation ) +{ + sgVec3 pos; + sgSubVec3(pos, body, view); + angle = (90*SGD_DEGREES_TO_RADIANS) - atan2(pos[2], sqrt(pos[0]*pos[0] + pos[1]*pos[1])); + rotation = (90*SGD_DEGREES_TO_RADIANS) - atan2(pos[0], pos[1]); +} + + +ssgaSky::ssgaSky( void ) +{ + dome = 0; + planets = 0; + stars = 0; + sol_ref = 0; + pre_root = 0; + post_root = 0; + + effective_visibility = visibility = 10000.0; + + // near cloud visibility state variables + in_puff = false; + puff_length = 0; + puff_progression = 0; + ramp_up = 0.15; + ramp_down = 0.15; +} + + +ssgaSky::~ssgaSky( void ) +{ + delete dome; + delete planets; + delete stars; + delete pre_root; + delete post_root; +} + + +void ssgaSky::build( double h_radius, double v_radius, + int nplanets, sgdVec3 *planet_data, + int nstars, sgdVec3 *star_data ) +{ + // clean-up previous + delete dome; + delete planets; + delete stars; + delete pre_root; + delete post_root; + bodies.removeAll(); + clouds.removeAll(); + + // build new + pre_root = new ssgRoot; + post_root = new ssgRoot; + + pre_selector = new ssgSelector; + post_selector = new ssgSelector; + + pre_transform = new ssgTransform; + post_transform = new ssgTransform; + + bodies_transform = new ssgTransform; + stars_transform = new ssgTransform; + + dome = new ssgaSkyDome; + pre_transform -> addKid( dome->build( h_radius, v_radius ) ); + + planets = new ssgaStars; + stars_transform -> addKid( planets->build( nplanets, planet_data, h_radius ) ); + + stars = new ssgaStars; + stars_transform -> addKid( stars->build( nstars, star_data, h_radius ) ); + + pre_transform -> addKid( bodies_transform ); + pre_transform -> addKid( stars_transform ); + + pre_selector->addKid( pre_transform ); + pre_selector->clrTraversalMaskBits( SSGTRAV_HOT ); + + post_selector->addKid( post_transform ); + post_selector->clrTraversalMaskBits( SSGTRAV_HOT ); + + pre_root->addKid( pre_selector ); + post_root->addKid( post_selector ); +} + + +ssgaCelestialBody* +ssgaSky::addBody( const char *body_tex_path, const char *halo_tex_path, double size, double dist, bool sol ) +{ + ssgaCelestialBody* body = new ssgaCelestialBody; + bodies_transform->addKid( body->build( body_tex_path, halo_tex_path, size ) ); + bodies.add( body ); + + body -> setDist( dist ); + + if ( sol ) + sol_ref = body; + + return body; +} + + +ssgaCelestialBody* +ssgaSky::addBody( ssgSimpleState *orb_state, ssgSimpleState *halo_state, double size, double dist, bool sol ) +{ + ssgaCelestialBody* body = new ssgaCelestialBody; + bodies_transform->addKid( body->build( orb_state, halo_state, size ) ); + bodies.add( body ); + + body -> setDist( dist ); + + if ( sol ) + sol_ref = body; + + return body; +} + + +ssgaCloudLayer* +ssgaSky::addCloud( const char *cloud_tex_path, float span, float elevation, float thickness, float transition ) +{ + ssgaCloudLayer* cloud = new ssgaCloudLayer; + cloud->build ( cloud_tex_path, span, elevation, thickness, transition ); + clouds.add( cloud ); + return cloud; +} + + +ssgaCloudLayer* +ssgaSky::addCloud( ssgSimpleState *cloud_state, float span, float elevation, float thickness, float transition ) +{ + ssgaCloudLayer* cloud = new ssgaCloudLayer; + cloud->build ( cloud_state, span, elevation, thickness, transition ); + clouds.add( cloud ); + return cloud; +} + + +bool ssgaSky::repositionFlat( sgVec3 view_pos, double spin, double dt ) +{ + int i; + double angle; + double rotation; + sgCoord pos; + + for ( i = 0; i < bodies.getNum (); i++ ) { + ssgaCelestialBody *body = bodies.get(i); + body->reposition( view_pos, 0 ); + + // Calc angles for rise/set effects + body->getPosition ( & pos ); + calc_celestial_angles( pos.xyz, view_pos, angle, rotation ); + body->setAngle( angle ); + body->setRotation( rotation ); + } + + for ( i = 0; i < clouds.getNum (); i++ ) { + clouds.get(i)->repositionFlat( view_pos, dt ); + } + + planets->reposition( view_pos, 0 ); + stars->reposition( view_pos, 0 ); + + if ( sol_ref ) { + dome->repositionFlat( view_pos, sol_ref->getRotation() ); + } + else { + dome->repositionFlat( view_pos, spin ); + } + + return true; +} + + +bool ssgaSky::reposition( sgVec3 view_pos, sgVec3 zero_elev, sgVec3 view_up, double lon, double lat, double alt, double spin, double gst, double dt ) +{ + int i; + + double angle = gst * 15; // degrees + + dome->reposition( zero_elev, lon, lat, spin ); + + for ( i = 0; i < bodies.getNum (); i++ ) + bodies.get(i)->reposition( view_pos, angle ); + + for ( i = 0; i < clouds.getNum (); i++ ) + clouds.get(i)->reposition( zero_elev, view_up, lon, lat, alt, dt ); + + planets->reposition( view_pos, angle ); + stars->reposition( view_pos, angle ); + + return true; +} + + +bool ssgaSky::repaint( sgVec4 sky_color, sgVec4 fog_color, sgVec4 cloud_color, double sol_angle, + int nplanets, sgdVec3 *planet_data, + int nstars, sgdVec3 *star_data ) +{ + int i; + + if ( effective_visibility > 1000.0 ) { + // turn on sky + enable(); + + dome->repaint( sky_color, fog_color, sol_angle, effective_visibility ); + + for ( i = 0; i < bodies.getNum (); i++ ) + bodies.get(i)->repaint(); + + for ( i = 0; i < clouds.getNum (); i++ ) + clouds.get(i)->repaint( cloud_color ); + + planets->repaint( sol_angle, nplanets, planet_data ); + stars->repaint( sol_angle, nstars, star_data ); + } + else { + // turn off sky + disable(); + } + + return true; +} + + +void ssgaSky::preDraw() +{ + ssgCullAndDraw( pre_root ); +} + + +void ssgaSky::postDraw( float alt ) +{ + // Sort clouds in order of distance from alt (furthest to closest) + int i, j; + int num = clouds.getNum (); + if ( num > 0 ) { + + // Initialise cloud index + int *index = new int [ num ]; + for ( i = 0; i < num; i++ ) { + index [i] = i; + } + + // Sort cloud index + int temp; // holding variable + for ( i = 0; i < ( num - 1 ); i++ ) // to represent element to be compared + { + for( j = ( i + 1 ); j < num; j++ ) // to represent the rest of the elements + { + float d1 = (float)(fabs(alt - clouds.get(i)->getElevation())); + float d2 = (float)(fabs(alt - clouds.get(j)->getElevation())); + + if (d1 < d2) + { + temp = index[i]; + index[i] = index[j]; + index[j] = temp; + } + } + } + + float slop = 5.0; // if we are closer than this to a cloud layer, don't draw cloud + + for ( int i = 0; i < num; i++ ) { + + ssgaCloudLayer *cloud = clouds.get(index[i]); + + float asl = cloud->getElevation(); + float thickness = cloud->getThickness(); + + // draw cloud only if below or above cloud layer + if ( alt < asl - slop || alt > asl + thickness + slop ) + cloud->draw(); + } + + delete [] index; + } +} + + +void ssgaSky::modifyVisibility( float alt, float time_factor ) +{ + float effvis = visibility; + + for ( int i = 0; i < clouds.getNum (); ++i ) { + + ssgaCloudLayer *cloud = clouds.get(i); + + if ( cloud->isEnabled() ) { + + float asl = cloud->getElevation(); + float thickness = cloud->getThickness(); + float transition = cloud->getTransition(); + + float ratio = 1.0; + + if ( alt < asl - transition ) { + // below cloud layer + ratio = 1.0; + } + else if ( alt < asl ) { + // in lower transition + ratio = (asl - alt) / transition; + } + else if ( alt < asl + thickness ) { + // in cloud layer + ratio = 0.0; + } + else if ( alt < asl + thickness + transition ) { + // in upper transition + ratio = (alt - (asl + thickness)) / transition; + } + else { + // above cloud layer + ratio = 1.0; + } + + // accumulate effects from multiple cloud layers + effvis *= ratio; + + if ( ratio < 1.0 ) { + if ( ! in_puff ) { + // calc chance of entering cloud puff + double rnd = ssgaRandom(); + double chance = rnd * rnd * rnd; + if ( chance > 0.95 ) { // * (diff - 25) / 50.0 + in_puff = true; + puff_length = ssgaRandom() * 2.0; // up to 2 seconds + puff_progression = 0.0; + } + } + + if ( in_puff ) { + // modify actual_visibility based on puff envelope + if ( puff_progression <= ramp_up ) { + double x = 0.5 * SGD_PI * puff_progression / ramp_up; + double factor = 1.0 - sin( x ); + effvis = (float)(effvis * factor); + } + else if ( puff_progression >= ramp_up + puff_length ) { + double x = 0.5 * SGD_PI * + (puff_progression - (ramp_up + puff_length)) / + ramp_down; + double factor = sin( x ); + effvis = (float)(effvis * factor); + } + else { + effvis = 0.0; + } + + puff_progression += time_factor; + + if ( puff_progression > puff_length + ramp_up + ramp_down) { + in_puff = false; + } + } + + // never let visibility drop below 25 meters + if ( effvis <= 25.0 ) { + effvis = 25.0; + } + } + } + } // for + + effective_visibility = effvis; +} diff --git a/src/ssgAux/ssgaSky.h b/src/ssgAux/ssgaSky.h new file mode 100644 index 0000000..2d9287a --- /dev/null +++ b/src/ssgAux/ssgaSky.h @@ -0,0 +1,397 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgaSky.h 2073 2006-03-27 08:09:54Z bram $ +*/ + +// Written by Curtis Olson, started December 1997. +// SSG-ified by Curtis Olson, February 2000. +// +// Moved into ssgAux, July 2003. + +#ifndef _INCLUDED_SSGASKY_H_ +#define _INCLUDED_SSGASKY_H_ + +#include "ssg.h" + +class ssgaCelestialBody; +class ssgaCelestialBodyList; +class ssgaCloudLayer; +class ssgaCloudLayerList; +class ssgaStars; +class ssgaSkyDome; +class ssgaSky; + + +class ssgaCelestialBody +{ +private: + + ssgTransform *transform; + ssgColourArray *cl; + + // used by repaint for rise/set effects + double body_angle; + double body_rotation; + + // used by reposition + double body_right_ascension; + double body_declination; + double body_dist; + +public: + + ssgaCelestialBody( void ); + ~ssgaCelestialBody( void ); + + ssgBranch *build( const char* body_tex_path, const char* halo_tex_path, double body_size ); + ssgBranch *build( ssgSimpleState *orb_state, ssgSimpleState *halo_state, double body_size ); + + bool reposition( sgVec3 p, double angle ) { + return reposition ( p, angle, body_right_ascension, body_declination, body_dist ); } + bool reposition( sgVec3 p, double angle, double rightAscension, double declination, double dist ); + + bool repaint() { return repaint ( body_angle ); } + bool repaint( double angle ); + + void getPosition ( sgCoord* p ) + { + sgMat4 Xform; + transform->getTransform(Xform); + sgSetCoord(p, Xform); + } + + void setAngle ( double angle ) { body_angle = angle; } + double getAngle () { return body_angle; } + + void setRotation ( double rotation ) { body_rotation = rotation; } + double getRotation () { return body_rotation; } + + void setRightAscension ( double ra ) { body_right_ascension = ra; } + double getRightAscension () { return body_right_ascension; } + + void setDeclination ( double decl ) { body_declination = decl; } + double getDeclination () { return body_declination; } + + void setDist ( double dist ) { body_dist = dist; } + double getDist () { return body_dist; } + + inline float *getColor() { return cl->get( 0 ); } +} ; + + +class ssgaCelestialBodyList : private ssgSimpleList +{ +public: + + ssgaCelestialBodyList ( int init = 3 ) + : ssgSimpleList ( sizeof(ssgaCelestialBody*), init ) { } + + ~ssgaCelestialBodyList () { removeAll(); } + + int getNum (void) { return total ; } + + ssgaCelestialBody* get ( unsigned int n ) + { + assert(nselect( 1 ); + post_selector->select( 1 ); + } + + // disable the sky + inline void disable() { + pre_selector->select( 0 ); + post_selector->select( 0 ); + } + + // current effective visibility + inline float getVisibility() const { return effective_visibility; } + inline void setVisibility( float v ) { + effective_visibility = visibility = v; + } +} ; + + +// return a random number between [0.0, 1.0) +inline double ssgaRandom(void) +{ + return(rand() / (double)RAND_MAX); +} + +//#if defined( macintosh ) +//const float system_gamma = 1.4; +//#elif defined (sgi) +//const float system_gamma = 1.7; +//#else // others +const float system_gamma = 2.5; +//#endif + +// simple architecture independant gamma correction function. +inline void ssgaGammaCorrectRGB(float *color, float reff = 2.5, float system = system_gamma) +{ + color[0] = (float)pow(color[0], reff/system); + color[1] = (float)pow(color[1], reff/system); + color[2] = (float)pow(color[2], reff/system); +}; + +inline void ssgaGammaCorrectC(float *color, float reff = 2.5, float system = system_gamma) +{ + *color = (float)pow(*color, reff/system); +}; + +inline void ssgaGammaRestoreRGB(float *color, float reff = 2.5, float system = system_gamma) +{ + color[0] = (float)pow(color[0], system/reff); + color[1] = (float)pow(color[1], system/reff); + color[2] = (float)pow(color[2], system/reff); +}; + +inline void ssgaGammaRestoreC(float *color, float reff = 2.5, float system = system_gamma) +{ + *color = (float)pow(*color, system/reff); +}; + +#endif diff --git a/src/ssgAux/ssgaSkyDome.cxx b/src/ssgAux/ssgaSkyDome.cxx new file mode 100644 index 0000000..ca343ed --- /dev/null +++ b/src/ssgAux/ssgaSkyDome.cxx @@ -0,0 +1,504 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgaSkyDome.cxx 1798 2003-09-26 14:54:20Z sjbaker $ +*/ + +// Written by Curtis Olson, started December 1997. +// SSG-ified by Curtis Olson, February 2000. +// +// Moved into ssgAux, July 2003. + +#include +#include "ssgaSky.h" + + +// proportions of max dimensions fed to the build() routine +static const float center_elev = 1.0f; + +static const float upper_radius = 0.6f; +static const float upper_elev = 0.15f; + +static const float middle_radius = 0.9f; +static const float middle_elev = 0.08f; + +static const float lower_radius = 1.0f; +static const float lower_elev = 0.0f; + +static const float bottom_radius = 0.8f; +static const float bottom_elev = -0.1f; + + +static int ssgaSkyDomePreDraw( ssgEntity *e ) +{ + ssgLeaf *f = (ssgLeaf *)e; + if ( f -> hasState () ) f->getState()->apply() ; + + glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_FOG_BIT ); + + glDisable( GL_DEPTH_TEST ); + glDisable( GL_FOG ); + + return true; +} + + +static int ssgaSkyDomePostDraw( ssgEntity *e ) +{ + glPopAttrib(); + + return true; +} + + +ssgaSkyDome::ssgaSkyDome( void ) +{ + dome_transform = 0; +} + + +ssgaSkyDome::~ssgaSkyDome( void ) +{ + ssgDeRefDelete( dome_transform ); +} + + +// initialize the sky object and connect it into our scene graph +ssgBranch * ssgaSkyDome::build( double hscale, double vscale ) +{ + sgVec4 color; + double theta; + int i; + + // clean-up previous + ssgDeRefDelete( dome_transform ); + + // create new + dome_transform = new ssgTransform; + dome_transform->ref(); + + // set up the state + dome_state = new ssgSimpleState(); + dome_state->setShadeModel( GL_SMOOTH ); + dome_state->disable( GL_LIGHTING ); + dome_state->disable( GL_CULL_FACE ); + dome_state->disable( GL_TEXTURE_2D ); + dome_state->enable( GL_COLOR_MATERIAL ); + dome_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE ); + dome_state->setMaterial( GL_EMISSION, 0, 0, 0, 1 ); + dome_state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 ); + dome_state->disable( GL_BLEND ); + dome_state->disable( GL_ALPHA_TEST ); + + // initialize arrays + center_disk_vl = new ssgVertexArray( 14 ); + center_disk_cl = new ssgColourArray( 14 ); + + upper_ring_vl = new ssgVertexArray( 26 ); + upper_ring_cl = new ssgColourArray( 26 ); + + middle_ring_vl = new ssgVertexArray( 26 ); + middle_ring_cl = new ssgColourArray( 26 ); + + lower_ring_vl = new ssgVertexArray( 26 ); + lower_ring_cl = new ssgColourArray( 26 ); + + // initially seed to all blue + sgSetVec4( color, 0.0, 0.0, 1.0, 1.0 ); + + // generate the raw vertex data + sgVec3 center_vertex; + sgVec3 upper_vertex[12]; + sgVec3 middle_vertex[12]; + sgVec3 lower_vertex[12]; + sgVec3 bottom_vertex[12]; + + sgSetVec3( center_vertex, 0.0, 0.0, (float)(center_elev * vscale) ); + + for ( i = 0; i < 12; i++ ) { + theta = (i * 30.0) * SGD_DEGREES_TO_RADIANS; + + sgSetVec3( upper_vertex[i], + (float)(cos(theta) * upper_radius * hscale), + (float)(sin(theta) * upper_radius * hscale), + (float)(upper_elev * vscale)); + + sgSetVec3( middle_vertex[i], + (float)(cos(theta) * middle_radius * hscale), + (float)(sin(theta) * middle_radius * hscale), + (float)(middle_elev * vscale)); + + sgSetVec3( lower_vertex[i], + (float)(cos(theta) * lower_radius * hscale), + (float)(sin(theta) * lower_radius * hscale), + (float)(lower_elev * vscale)); + + sgSetVec3( bottom_vertex[i], + (float)(cos(theta) * bottom_radius * hscale), + (float)(sin(theta) * bottom_radius * hscale), + (float)(bottom_elev * vscale)); + } + + // generate the center disk vertex/color arrays + center_disk_vl->add( center_vertex ); + center_disk_cl->add( color ); + for ( i = 11; i >= 0; i-- ) { + center_disk_vl->add( upper_vertex[i] ); + center_disk_cl->add( color ); + } + center_disk_vl->add( upper_vertex[11] ); + center_disk_cl->add( color ); + + // generate the upper ring + for ( i = 0; i < 12; i++ ) { + upper_ring_vl->add( middle_vertex[i] ); + upper_ring_cl->add( color ); + + upper_ring_vl->add( upper_vertex[i] ); + upper_ring_cl->add( color ); + } + upper_ring_vl->add( middle_vertex[0] ); + upper_ring_cl->add( color ); + + upper_ring_vl->add( upper_vertex[0] ); + upper_ring_cl->add( color ); + + // generate middle ring + for ( i = 0; i < 12; i++ ) { + middle_ring_vl->add( lower_vertex[i] ); + middle_ring_cl->add( color ); + + middle_ring_vl->add( middle_vertex[i] ); + middle_ring_cl->add( color ); + } + middle_ring_vl->add( lower_vertex[0] ); + middle_ring_cl->add( color ); + + middle_ring_vl->add( middle_vertex[0] ); + middle_ring_cl->add( color ); + + // generate lower ring + for ( i = 0; i < 12; i++ ) { + lower_ring_vl->add( bottom_vertex[i] ); + lower_ring_cl->add( color ); + + lower_ring_vl->add( lower_vertex[i] ); + lower_ring_cl->add( color ); + } + lower_ring_vl->add( bottom_vertex[0] ); + lower_ring_cl->add( color ); + + lower_ring_vl->add( lower_vertex[0] ); + lower_ring_cl->add( color ); + + // force a repaint of the sky colors with ugly defaults + sgVec3 fog_color; + sgSetVec3( fog_color, 1.0, 1.0, 1.0 ); + repaint( color, fog_color, 0.0, 5000.0 ); + + // build the ssg scene graph sub tree for the sky and connected + // into the provide scene graph branch + ssgVtxTable *center_disk, *upper_ring, *middle_ring, *lower_ring; + + center_disk = new ssgVtxTable( GL_TRIANGLE_FAN, + center_disk_vl, NULL, NULL, center_disk_cl ); + + upper_ring = new ssgVtxTable( GL_TRIANGLE_STRIP, + upper_ring_vl, NULL, NULL, upper_ring_cl ); + + middle_ring = new ssgVtxTable( GL_TRIANGLE_STRIP, + middle_ring_vl, NULL, NULL, middle_ring_cl ); + + lower_ring = new ssgVtxTable( GL_TRIANGLE_STRIP, + lower_ring_vl, NULL, NULL, lower_ring_cl ); + + center_disk->setState( dome_state ); + upper_ring->setState( dome_state ); + middle_ring->setState( dome_state ); + lower_ring->setState( dome_state ); + + dome_transform->addKid( center_disk ); + dome_transform->addKid( upper_ring ); + dome_transform->addKid( middle_ring ); + dome_transform->addKid( lower_ring ); + + // not entirely satisfying. We are depending here that the first + // thing we add to a parent is the first drawn + center_disk->setCallback( SSG_CALLBACK_PREDRAW, ssgaSkyDomePreDraw ); + center_disk->setCallback( SSG_CALLBACK_POSTDRAW, ssgaSkyDomePostDraw ); + + upper_ring->setCallback( SSG_CALLBACK_PREDRAW, ssgaSkyDomePreDraw ); + upper_ring->setCallback( SSG_CALLBACK_POSTDRAW, ssgaSkyDomePostDraw ); + + middle_ring->setCallback( SSG_CALLBACK_PREDRAW, ssgaSkyDomePreDraw ); + middle_ring->setCallback( SSG_CALLBACK_POSTDRAW, ssgaSkyDomePostDraw ); + + lower_ring->setCallback( SSG_CALLBACK_PREDRAW, ssgaSkyDomePreDraw ); + lower_ring->setCallback( SSG_CALLBACK_POSTDRAW, ssgaSkyDomePostDraw ); + + return dome_transform; +} + + +bool ssgaSkyDome::repositionFlat( sgVec3 p, double spin ) +{ + sgMat4 T, SPIN; + sgVec3 axis; + + // Translate to view position + sgMakeTransMat4( T, p ); + + // Rotate to proper orientation + sgSetVec3( axis, 0.0, 0.0, 1.0 ); + sgMakeRotMat4( SPIN, (float)(spin * SGD_RADIANS_TO_DEGREES), axis ); + + sgMat4 TRANSFORM; + + sgCopyMat4( TRANSFORM, T ); + sgPreMultMat4( TRANSFORM, SPIN ); + + sgCoord skypos; + sgSetCoord( &skypos, TRANSFORM ); + + dome_transform->setTransform( &skypos ); + + return true; +} + + +bool ssgaSkyDome::reposition( sgVec3 p, double lon, double lat, double spin ) +{ + sgMat4 T, LON, LAT, SPIN; + sgVec3 axis; + + // Translate to view position + sgMakeTransMat4( T, p ); + + // Rotate to proper orientation + sgSetVec3( axis, 0.0, 0.0, 1.0 ); + sgMakeRotMat4( LON, (float)(lon * SGD_RADIANS_TO_DEGREES), axis ); + + sgSetVec3( axis, 0.0, 1.0, 0.0 ); + sgMakeRotMat4( LAT, (float)(90.0 - lat * SGD_RADIANS_TO_DEGREES), axis ); + + sgSetVec3( axis, 0.0, 0.0, 1.0 ); + sgMakeRotMat4( SPIN, (float)(spin * SGD_RADIANS_TO_DEGREES), axis ); + + sgMat4 TRANSFORM; + + sgCopyMat4( TRANSFORM, T ); + sgPreMultMat4( TRANSFORM, LON ); + sgPreMultMat4( TRANSFORM, LAT ); + sgPreMultMat4( TRANSFORM, SPIN ); + + sgCoord skypos; + sgSetCoord( &skypos, TRANSFORM ); + + dome_transform->setTransform( &skypos ); + + return true; +} + + +bool ssgaSkyDome::repaint( sgVec4 sky_color, sgVec4 fog_color, double sol_angle, double vis ) +{ + double diff; + sgVec3 outer_param, outer_amt, outer_diff; + sgVec3 middle_param, middle_amt, middle_diff; + int i, j; + + sol_angle *= SGD_RADIANS_TO_DEGREES; + + // Check for sunrise/sunset condition + if ( (sol_angle > 80.0) ) { // && (sol_angle < 100.0) ) + // 0.0 - 0.4 + sgSetVec3( outer_param, + (float)((10.0 - fabs(90.0 - sol_angle)) / 20.0), + (float)((10.0 - fabs(90.0 - sol_angle)) / 40.0), + (float)(-(10.0 - fabs(90.0 - sol_angle)) / 30.0)); + + sgSetVec3( middle_param, + (float)((10.0 - fabs(90.0 - sol_angle)) / 40.0), + (float)((10.0 - fabs(90.0 - sol_angle)) / 80.0), + 0.0 ); + + sgScaleVec3( outer_diff, outer_param, 1.0f / 6.0f ); + + sgScaleVec3( middle_diff, middle_param, 1.0f / 6.0f ); + } + else { + sgSetVec3( outer_param, 0.0, 0.0, 0.0 ); + sgSetVec3( middle_param, 0.0, 0.0, 0.0 ); + + sgSetVec3( outer_diff, 0.0, 0.0, 0.0 ); + sgSetVec3( middle_diff, 0.0, 0.0, 0.0 ); + } + + // calculate transition colors between sky and fog + sgCopyVec3( outer_amt, outer_param ); + sgCopyVec3( middle_amt, middle_param ); + + // + // First, recalulate the basic colors + // + + sgVec4 center_color; + sgVec4 upper_color[12]; + sgVec4 middle_color[12]; + sgVec4 lower_color[12]; + sgVec4 bottom_color[12]; + + double vis_factor; + + if ( vis < 3000.0 ) { + vis_factor = (vis - 1000.0) / 2000.0; + if ( vis_factor < 0.0 ) { + vis_factor = 0.0; + } + } + else { + vis_factor = 1.0; + } + + for ( j = 0; j < 3; j++ ) { + diff = sky_color[j] - fog_color[j]; + center_color[j] = sky_color[j] - (float)(diff * ( 1.0 - vis_factor )); + } + + for ( i = 0; i < 6; i++ ) { + for ( j = 0; j < 3; j++ ) { + diff = sky_color[j] - fog_color[j]; + + upper_color[i][j] = sky_color[j] - (float)(diff * ( 1.0 - vis_factor * 0.7)); + middle_color[i][j] = sky_color[j] - (float)(diff * ( 1.0 - vis_factor * 0.1)) + middle_amt[j]; + lower_color[i][j] = fog_color[j] + outer_amt[j]; + + if ( upper_color[i][j] > 1.0 ) { upper_color[i][j] = 1.0; } + if ( upper_color[i][j] < 0.0 ) { upper_color[i][j] = 0.0; } + if ( middle_color[i][j] > 1.0 ) { middle_color[i][j] = 1.0; } + if ( middle_color[i][j] < 0.0 ) { middle_color[i][j] = 0.0; } + if ( lower_color[i][j] > 1.0 ) { lower_color[i][j] = 1.0; } + if ( lower_color[i][j] < 0.0 ) { lower_color[i][j] = 0.0; } + } + upper_color[i][3] = middle_color[i][3] = lower_color[i][3] = 1.0; + + for ( j = 0; j < 3; j++ ) { + outer_amt[j] -= outer_diff[j]; + middle_amt[j] -= middle_diff[j]; + } + } + + sgSetVec3( outer_amt, 0.0, 0.0, 0.0 ); + sgSetVec3( middle_amt, 0.0, 0.0, 0.0 ); + + for ( i = 6; i < 12; i++ ) { + for ( j = 0; j < 3; j++ ) { + diff = sky_color[j] - fog_color[j]; + + upper_color[i][j] = sky_color[j] - (float)(diff * ( 1.0 - vis_factor * 0.7)); + middle_color[i][j] = sky_color[j] - (float)(diff * ( 1.0 - vis_factor * 0.1)) + middle_amt[j]; + lower_color[i][j] = fog_color[j] + outer_amt[j]; + + if ( upper_color[i][j] > 1.0 ) { upper_color[i][j] = 1.0; } + if ( upper_color[i][j] < 0.0 ) { upper_color[i][j] = 0.0; } + if ( middle_color[i][j] > 1.0 ) { middle_color[i][j] = 1.0; } + if ( middle_color[i][j] < 0.0 ) { middle_color[i][j] = 0.0; } + if ( lower_color[i][j] > 1.0 ) { lower_color[i][j] = 1.0; } + if ( lower_color[i][j] < 0.0 ) { lower_color[i][j] = 0.0; } + } + upper_color[i][3] = middle_color[i][3] = lower_color[i][3] = 1.0; + + for ( j = 0; j < 3; j++ ) { + outer_amt[j] += outer_diff[j]; + middle_amt[j] += middle_diff[j]; + } + } + + for ( i = 0; i < 12; i++ ) { + sgCopyVec4( bottom_color[i], fog_color ); + } + + // + // Second, assign the basic colors to the object color arrays + // + + float *slot; + int counter; + + // update the center disk color arrays + counter = 0; + slot = center_disk_cl->get( counter++ ); + // sgVec4 red; + // sgSetVec4( red, 1.0, 0.0, 0.0, 1.0 ); + sgCopyVec4( slot, center_color ); + for ( i = 11; i >= 0; i-- ) { + slot = center_disk_cl->get( counter++ ); + sgCopyVec4( slot, upper_color[i] ); + } + slot = center_disk_cl->get( counter++ ); + sgCopyVec4( slot, upper_color[11] ); + + // generate the upper ring + counter = 0; + for ( i = 0; i < 12; i++ ) { + slot = upper_ring_cl->get( counter++ ); + sgCopyVec4( slot, middle_color[i] ); + + slot = upper_ring_cl->get( counter++ ); + sgCopyVec4( slot, upper_color[i] ); + } + slot = upper_ring_cl->get( counter++ ); + sgCopyVec4( slot, middle_color[0] ); + + slot = upper_ring_cl->get( counter++ ); + sgCopyVec4( slot, upper_color[0] ); + + // generate middle ring + counter = 0; + for ( i = 0; i < 12; i++ ) { + slot = middle_ring_cl->get( counter++ ); + sgCopyVec4( slot, lower_color[i] ); + + slot = middle_ring_cl->get( counter++ ); + sgCopyVec4( slot, middle_color[i] ); + } + slot = middle_ring_cl->get( counter++ ); + sgCopyVec4( slot, lower_color[0] ); + + slot = middle_ring_cl->get( counter++ ); + sgCopyVec4( slot, middle_color[0] ); + + // generate lower ring + counter = 0; + for ( i = 0; i < 12; i++ ) { + slot = lower_ring_cl->get( counter++ ); + sgCopyVec4( slot, bottom_color[i] ); + + slot = lower_ring_cl->get( counter++ ); + sgCopyVec4( slot, lower_color[i] ); + } + slot = lower_ring_cl->get( counter++ ); + sgCopyVec4( slot, bottom_color[0] ); + + slot = lower_ring_cl->get( counter++ ); + sgCopyVec4( slot, lower_color[0] ); + + return true; +} diff --git a/src/ssgAux/ssgaSphere.cxx b/src/ssgAux/ssgaSphere.cxx new file mode 100644 index 0000000..4f2f65e --- /dev/null +++ b/src/ssgAux/ssgaSphere.cxx @@ -0,0 +1,125 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgaSphere.cxx 2015 2005-02-02 15:48:09Z sjbaker $ +*/ + +// Pulled straight out of MesaGLU/quadratic.c +// +// Original gluSphere code is Copyright (C) 1999-2000 Brian Paul and +// licensed under the GPL +// +// Moved into ssgAux, July 2003. + +#include "ul.h" +#include "ssgaSphere.h" + + +ssgBranch *ssgaMakeSphere( + ssgSimpleState *state, ssgColourArray *cl, + float radius, int slices, int stacks, + ssgCallback predraw, ssgCallback postdraw ) +{ + double rho, drho, theta, dtheta; + float x, y, z; + float s, t, ds, dt; + int i, j, imin, imax; + float nsign = 1.0; + ssgBranch *sphere = new ssgBranch; + sgVec2 vec2; + sgVec3 vec3; + + drho = SGD_PI / stacks; + dtheta = (2.0 * SGD_PI) / slices; + + /* texturing: s goes from 0.0/0.25/0.5/0.75/1.0 at +y/+x/-y/-x/+y + axis t goes from -1.0/+1.0 at z = -radius/+radius (linear along + longitudes) cannot use triangle fan on texturing (s coord. at + top/bottom tip varies) */ + + ds = 1.0f / slices; + dt = 1.0f / stacks; + t = 1.0; /* because loop now runs from 0 */ + imin = 0; + imax = stacks; + + /* build slices as quad strips */ + for ( i = imin; i < imax; i++ ) { + ssgVertexArray *vl = new ssgVertexArray(); + ssgNormalArray *nl = new ssgNormalArray(); + ssgTexCoordArray *tl = new ssgTexCoordArray(); + + rho = i * drho; + s = 0.0; + for ( j = 0; j <= slices; j++ ) { + theta = (j == slices) ? 0.0 : j * dtheta; + x = (float)(-sin(theta) * sin(rho)); + y = (float)(cos(theta) * sin(rho)); + z = (float)(nsign * cos(rho)); + + sgSetVec3( vec3, x*nsign, y*nsign, z*nsign ); + sgNormalizeVec3( vec3 ); + nl->add( vec3 ); + + sgSetVec2( vec2, s, t ); + tl->add( vec2 ); + + sgSetVec3( vec3, x*radius, y*radius, z*radius ); + vl->add( vec3 ); + + x = (float)(-sin(theta) * sin(rho+drho)); + y = (float)(cos(theta) * sin(rho+drho)); + z = (float)(nsign * cos(rho+drho)); + + sgSetVec3( vec3, x*nsign, y*nsign, z*nsign ); + sgNormalizeVec3( vec3 ); + nl->add( vec3 ); + + sgSetVec2( vec2, s, t-dt ); + tl->add( vec2 ); + s += ds; + + sgSetVec3( vec3, x*radius, y*radius, z*radius ); + vl->add( vec3 ); + } + + ssgLeaf *slice = + new ssgVtxTable ( GL_TRIANGLE_STRIP, vl, nl, tl, cl ); + + if ( vl->getNum() != nl->getNum() ) { + ulSetError(UL_FATAL, "bad sphere1\n"); + exit(-1); + } + if ( vl->getNum() != tl->getNum() ) { + ulSetError(UL_FATAL, "bad sphere2\n"); + exit(-1); + } + slice->setState( state ); + slice->setCallback( SSG_CALLBACK_PREDRAW, predraw ); + slice->setCallback( SSG_CALLBACK_POSTDRAW, postdraw ); + + sphere->addKid( slice ); + + t -= dt; + } + + return sphere; +} + diff --git a/src/ssgAux/ssgaSphere.h b/src/ssgAux/ssgaSphere.h new file mode 100644 index 0000000..cebdce8 --- /dev/null +++ b/src/ssgAux/ssgaSphere.h @@ -0,0 +1,33 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgaSphere.h 2000 2005-01-09 13:13:12Z bram $ +*/ + + +#include "ssg.h" + + +// return a sphere object as an ssgBranch (connected to the specified ssgSimpleState) +ssgBranch *ssgaMakeSphere( + ssgSimpleState *state, ssgColourArray *cl, + float radius, int slices, int stacks, + ssgCallback predraw, ssgCallback postdraw ); + diff --git a/src/ssgAux/ssgaStars.cxx b/src/ssgAux/ssgaStars.cxx new file mode 100644 index 0000000..052cc64 --- /dev/null +++ b/src/ssgAux/ssgaStars.cxx @@ -0,0 +1,242 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgaStars.cxx 1798 2003-09-26 14:54:20Z sjbaker $ +*/ + +// Written by Durk Talsma. Originally started October 1997, for distribution +// with the FlightGear project. Version 2 was written in August and +// September 1998. This code is based upon algorithms and data kindly +// provided by Mr. Paul Schlyter. (pausch@saaf.se). +// +// Separated out rendering pieces and converted to ssg by Curt Olson, +// March 2000 +// +// Moved into ssgAux, July 2003. + +#include "ssgaSky.h" + + +static int ssgaStarPreDraw( ssgEntity *e ) +{ + ssgLeaf *f = (ssgLeaf *)e; + if ( f -> hasState () ) f->getState()->apply() ; + + glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_FOG_BIT ); + + //glDisable( GL_DEPTH_TEST ); + glDisable( GL_FOG ); + // glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; + + return true; +} + + +static int ssgaStarPostDraw( ssgEntity *e ) +{ + glPopAttrib(); + + return true; +} + + +ssgaStars::ssgaStars( void ) : + stars_transform(0), + old_phase(-1) +{ +} + + +ssgaStars::~ssgaStars( void ) +{ + ssgDeRefDelete( stars_transform ); +} + + +ssgBranch * ssgaStars::build( int num, sgdVec3 *star_data, double star_dist ) +{ + sgVec4 color; + + // clean-up previous + ssgDeRefDelete( stars_transform ); + + // create new + stars_transform = new ssgTransform; + stars_transform->ref(); + + if ( star_data == NULL ) + ulSetError(UL_WARNING, "null star data passed to ssgaStars::build()"); + + // set up the orb state + state = new ssgSimpleState(); + state->disable( GL_LIGHTING ); + state->disable( GL_CULL_FACE ); + state->disable( GL_TEXTURE_2D ); + state->enable( GL_COLOR_MATERIAL ); + state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE ); + state->setMaterial( GL_EMISSION, 0, 0, 0, 1 ); + state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 ); + state->enable( GL_BLEND ); + state->disable( GL_ALPHA_TEST ); + + vl = new ssgVertexArray( num ); + cl = new ssgColourArray( num ); + // cl = new ssgColourArray( 1 ); + // sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 ); + // cl->add( color ); + + // Build ssg structure + sgVec3 p; + for ( int i = 0; i < num; ++i ) { + // position seeded to arbitrary values + sgSetVec3( p, + (float)( star_dist * cos( star_data[i][0] ) + * cos( star_data[i][1] )), + (float)( star_dist * sin( star_data[i][0] ) + * cos( star_data[i][1] )), + (float)( star_dist * sin( star_data[i][1] ))); + vl->add( p ); + + // color (magnitude) + sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 ); + cl->add( color ); + } + + ssgLeaf *stars_obj = + new ssgVtxTable ( GL_POINTS, vl, NULL, NULL, cl ); + stars_obj->setState( state ); + stars_obj->setCallback( SSG_CALLBACK_PREDRAW, ssgaStarPreDraw ); + stars_obj->setCallback( SSG_CALLBACK_POSTDRAW, ssgaStarPostDraw ); + + stars_transform->addKid( stars_obj ); + + return stars_transform; +} + + +bool ssgaStars::reposition( sgVec3 p, double angle ) +{ + sgMat4 T1, GST; + sgVec3 axis; + + sgMakeTransMat4( T1, p ); + + sgSetVec3( axis, 0.0, 0.0, -1.0 ); + sgMakeRotMat4( GST, (float)angle, axis ); + + sgMat4 TRANSFORM; + sgCopyMat4( TRANSFORM, T1 ); + sgPreMultMat4( TRANSFORM, GST ); + + sgCoord skypos; + sgSetCoord( &skypos, TRANSFORM ); + + stars_transform->setTransform( &skypos ); + + return true; +} + + +bool ssgaStars::repaint( double sol_angle, int num, sgdVec3 *star_data ) +{ + double mag, nmag, alpha, factor, cutoff; + float *color; + + int phase; + + // determine which star structure to draw + if ( sol_angle > (0.5 * SGD_PI + 10.0 * SGD_DEGREES_TO_RADIANS ) ) { + // deep night + factor = 1.0; + cutoff = 4.5; + phase = 0; + } + else if ( sol_angle > (0.5 * SGD_PI + 8.8 * SGD_DEGREES_TO_RADIANS ) ) { + factor = 1.0; + cutoff = 3.8; + phase = 1; + } + else if ( sol_angle > (0.5 * SGD_PI + 7.5 * SGD_DEGREES_TO_RADIANS ) ) { + factor = 0.95; + cutoff = 3.1; + phase = 2; + } + else if ( sol_angle > (0.5 * SGD_PI + 7.0 * SGD_DEGREES_TO_RADIANS ) ) { + factor = 0.9; + cutoff = 2.4; + phase = 3; + } + else if ( sol_angle > (0.5 * SGD_PI + 6.5 * SGD_DEGREES_TO_RADIANS ) ) { + factor = 0.85; + cutoff = 1.8; + phase = 4; + } + else if ( sol_angle > (0.5 * SGD_PI + 6.0 * SGD_DEGREES_TO_RADIANS ) ) { + factor = 0.8; + cutoff = 1.2; + phase = 5; + } + else if ( sol_angle > (0.5 * SGD_PI + 5.5 * SGD_DEGREES_TO_RADIANS ) ) { + factor = 0.75; + cutoff = 0.6; + phase = 6; + } + else { + // early dusk or late dawn + factor = 0.7; + cutoff = 0.0; + phase = 7; + } + + if( phase != old_phase ) { + old_phase = phase; + for ( int i = 0; i < num; ++i ) { + // if ( star_data[i][2] < min ) { min = star_data[i][2]; } + // if ( star_data[i][2] > max ) { max = star_data[i][2]; } + + // magnitude ranges from -1 (bright) to 4 (dim). The + // range of star and planet magnitudes can actually go + // outside of this, but for our purpose, if it is brighter + // that -1, we'll color it full white/alpha anyway and 4 + // is a convenient cutoff point which keeps the number of + // stars drawn at about 500. + + // color (magnitude) + mag = star_data[i][2]; + if ( mag < cutoff ) { + nmag = ( 4.5 - mag ) / 5.5; // translate to 0 ... 1.0 scale + // alpha = nmag * 0.7 + 0.3; // translate to a 0.3 ... 1.0 scale + alpha = nmag * 0.85 + 0.15; // translate to a 0.15 ... 1.0 scale + alpha *= factor; // dim when the sun is brighter + } + else { + alpha = 0.0; + } + + if (alpha > 1.0) { alpha = 1.0; } + if (alpha < 0.0) { alpha = 0.0; } + + color = cl->get( i ); + sgSetVec4( color, 1.0, 1.0, 1.0, (float)alpha ); + } + } + + return true; +} diff --git a/src/ssgAux/ssgaTeapot.cxx b/src/ssgAux/ssgaTeapot.cxx new file mode 100644 index 0000000..9099002 --- /dev/null +++ b/src/ssgAux/ssgaTeapot.cxx @@ -0,0 +1,342 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgaTeapot.cxx 2015 2005-02-02 15:48:09Z sjbaker $ +*/ + + +#include "ssgAux.h" +#include + +static int patch [][ 17 ] = +{ + /* Rim: */ + { 2, 102, 103, 104, 105, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15 }, + /* Body: */ + { 2, 12, 13, 14, 15, + 16, 17, 18, 19, + 20, 21, 22, 23, + 24, 25, 26, 27 }, + { 2, 24, 25, 26, 27, + 29, 30, 31, 32, + 33, 34, 35, 36, + 37, 38, 39, 40 }, + /* Lid: */ + { 2, 96, 96, 96, 96, + 97, 98, 99, 100, + 101, 101, 101, 101, + 0, 1, 2, 3 }, + { 2, 0, 1, 2, 3, + 106, 107, 108, 109, + 110, 111, 112, 113, + 114, 115, 116, 117 }, + /* Handle: */ + { 1, 41, 42, 43, 44, + 45, 46, 47, 48, + 49, 50, 51, 52, + 53, 54, 55, 56 }, + { 1, 53, 54, 55, 56, + 57, 58, 59, 60, + 61, 62, 63, 64, + 28, 65, 66, 67 }, + /* Spout: */ + { 1, 68, 69, 70, 71, + 72, 73, 74, 75, + 76, 77, 78, 79, + 80, 81, 82, 83 }, + { 1, 80, 81, 82, 83, + 84, 85, 86, 87, + 88, 89, 90, 91, + 92, 93, 94, 95 }, + /* Bottom: */ + { 2, 118, 118, 118, 118, + 124, 122, 119, 121, + 123, 126, 125, 120, + 40, 39, 38, 37 }, + + /* End Marker: */ + { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 } +} ; + +static sgVec3 vertex [] = +{ + { 0.2000f, 0.0000f, 2.70000f }, /* 00 */ + { 0.2000f, -0.1120f, 2.70000f }, + { 0.1120f, -0.2000f, 2.70000f }, + { 0.0000f, -0.2000f, 2.70000f }, + { 1.3375f, 0.0000f, 2.53125f }, + { 1.3375f, -0.7490f, 2.53125f }, + { 0.7490f, -1.3375f, 2.53125f }, + { 0.0000f, -1.3375f, 2.53125f }, + { 1.4375f, 0.0000f, 2.53125f }, + { 1.4375f, -0.8050f, 2.53125f }, + + { 0.8050f, -1.4375f, 2.53125f }, /* 10 */ + { 0.0000f, -1.4375f, 2.53125f }, + { 1.5000f, 0.0000f, 2.40000f }, + { 1.5000f, -0.8400f, 2.40000f }, + { 0.8400f, -1.5000f, 2.40000f }, + { 0.0000f, -1.5000f, 2.40000f }, + { 1.7500f, 0.0000f, 1.87500f }, + { 1.7500f, -0.9800f, 1.87500f }, + { 0.9800f, -1.7500f, 1.87500f }, + { 0.0000f, -1.7500f, 1.87500f }, + + { 2.0000f, 0.0000f, 1.35000f }, /* 20 */ + { 2.0000f, -1.1200f, 1.35000f }, + { 1.1200f, -2.0000f, 1.35000f }, + { 0.0000f, -2.0000f, 1.35000f }, + { 2.0000f, 0.0000f, 0.90000f }, + { 2.0000f, -1.1200f, 0.90000f }, + { 1.1200f, -2.0000f, 0.90000f }, + { 0.0000f, -2.0000f, 0.90000f }, + { -2.0000f, 0.0000f, 0.90000f }, + { 2.0000f, 0.0000f, 0.45000f }, + + { 2.0000f, -1.1200f, 0.45000f }, /* 30 */ + { 1.1200f, -2.0000f, 0.45000f }, + { 0.0000f, -2.0000f, 0.45000f }, + { 1.5000f, 0.0000f, 0.22500f }, + { 1.5000f, -0.8400f, 0.22500f }, + { 0.8400f, -1.5000f, 0.22500f }, + { 0.0000f, -1.5000f, 0.22500f }, + { 1.5000f, 0.0000f, 0.15000f }, + { 1.5000f, -0.8400f, 0.15000f }, + { 0.8400f, -1.5000f, 0.15000f }, + + { 0.0000f, -1.5000f, 0.15000f }, /* 40 */ + { -1.6000f, 0.0000f, 2.02500f }, + { -1.6000f, -0.3000f, 2.02500f }, + { -1.5000f, -0.3000f, 2.25000f }, + { -1.5000f, 0.0000f, 2.25000f }, + { -2.3000f, 0.0000f, 2.02500f }, + { -2.3000f, -0.3000f, 2.02500f }, + { -2.5000f, -0.3000f, 2.25000f }, + { -2.5000f, 0.0000f, 2.25000f }, + { -2.7000f, 0.0000f, 2.02500f }, + + { -2.7000f, -0.3000f, 2.02500f }, /* 50 */ + { -3.0000f, -0.3000f, 2.25000f }, + { -3.0000f, 0.0000f, 2.25000f }, + { -2.7000f, 0.0000f, 1.80000f }, + { -2.7000f, -0.3000f, 1.80000f }, + { -3.0000f, -0.3000f, 1.80000f }, + { -3.0000f, 0.0000f, 1.80000f }, + { -2.7000f, 0.0000f, 1.57500f }, + { -2.7000f, -0.3000f, 1.57500f }, + { -3.0000f, -0.3000f, 1.35000f }, + + { -3.0000f, 0.0000f, 1.35000f }, /* 60 */ + { -2.5000f, 0.0000f, 1.12500f }, + { -2.5000f, -0.3000f, 1.12500f }, + { -2.6500f, -0.3000f, 0.93750f }, + { -2.6500f, 0.0000f, 0.93750f }, + { -2.0000f, -0.3000f, 0.90000f }, + { -1.9000f, -0.3000f, 0.60000f }, + { -1.9000f, 0.0000f, 0.60000f }, + { 1.7000f, 0.0000f, 1.42500f }, + { 1.7000f, -0.6600f, 1.42500f }, + + { 1.7000f, -0.6600f, 0.60000f }, /* 70 */ + { 1.7000f, 0.0000f, 0.60000f }, + { 2.6000f, 0.0000f, 1.42500f }, + { 2.6000f, -0.6600f, 1.42500f }, + { 3.1000f, -0.6600f, 0.82500f }, + { 3.1000f, 0.0000f, 0.82500f }, + { 2.3000f, 0.0000f, 2.10000f }, + { 2.3000f, -0.2500f, 2.10000f }, + { 2.4000f, -0.2500f, 2.02500f }, + { 2.4000f, 0.0000f, 2.02500f }, + + { 2.7000f, 0.0000f, 2.40000f }, /* 80 */ + { 2.7000f, -0.2500f, 2.40000f }, + { 3.3000f, -0.2500f, 2.40000f }, + { 3.3000f, 0.0000f, 2.40000f }, + { 2.8000f, 0.0000f, 2.47500f }, + { 2.8000f, -0.2500f, 2.47500f }, + { 3.5250f, -0.2500f, 2.49375f }, + { 3.5250f, 0.0000f, 2.49375f }, + { 2.9000f, 0.0000f, 2.47500f }, + { 2.9000f, -0.1500f, 2.47500f }, + + { 3.4500f, -0.1500f, 2.51250f }, /* 90 */ + { 3.4500f, 0.0000f, 2.51250f }, + { 2.8000f, 0.0000f, 2.40000f }, + { 2.8000f, -0.1500f, 2.40000f }, + { 3.2000f, -0.1500f, 2.40000f }, + { 3.2000f, 0.0000f, 2.40000f }, + { 0.0000f, 0.0000f, 3.15000f }, + { 0.8000f, 0.0000f, 3.15000f }, + { 0.8000f, -0.4500f, 3.15000f }, + { 0.4500f, -0.8000f, 3.15000f }, + + { 0.0000f, -0.8000f, 3.15000f }, /* 100 */ + { 0.0000f, 0.0000f, 2.85000f }, + { 1.4000f, 0.0000f, 2.40000f }, + { 1.4000f, -0.7840f, 2.40000f }, + { 0.7840f, -1.4000f, 2.40000f }, + { 0.0000f, -1.4000f, 2.40000f }, + { 0.4000f, 0.0000f, 2.55000f }, + { 0.4000f, -0.2240f, 2.55000f }, + { 0.2240f, -0.4000f, 2.55000f }, + { 0.0000f, -0.4000f, 2.55000f }, + + { 1.3000f, 0.0000f, 2.55000f }, /* 110 */ + { 1.3000f, -0.7280f, 2.55000f }, + { 0.7280f, -1.3000f, 2.55000f }, + { 0.0000f, -1.3000f, 2.55000f }, /* Next four verts kludged to make lid fit */ + { 1.4000f, 0.0000f, 2.40000f }, /* { 1.3000, 0.0000, 2.40000 }, */ + { 1.4000f, -0.7840f, 2.40000f }, /* { 1.3000, -0.7280, 2.40000 }, */ + { 0.7840f, -1.4000f, 2.40000f }, /* { 0.7280, -1.3000, 2.40000 }, */ + { 0.0000f, -1.4000f, 2.40000f }, /* { 0.0000, -1.3000, 2.40000 }, */ + { 0.0000f, 0.0000f, 0.00000f }, + { 1.4250f, -0.7980f, 0.00000f }, + + { 1.5000f, 0.0000f, 0.07500f }, /* 120 */ + { 1.4250f, 0.0000f, 0.00000f }, + { 0.7980f, -1.4250f, 0.00000f }, + { 0.0000f, -1.5000f, 0.07500f }, + { 0.0000f, -1.4250f, 0.00000f }, + { 1.5000f, -0.8400f, 0.07500f }, + { 0.8400f, -1.5000f, 0.07500f } +} ; + + +void ssgaTeapot::regenerate () +{ + if ( kidState != NULL ) kidState -> ref () ; + removeAllKids () ; + if ( kidState != NULL ) kidState -> deRef () ; + + for ( int i = 0 ; patch[i][0] >= 0 ; i++ ) + { + ssgaPatch *p = new ssgaPatch ( ntriangles / 32 ) ; + int j ; + + for ( j = 0 ; j < 16 ; j++ ) + { + sgVec3 xyz ; + sgVec2 uv ; + + uv [ 0 ] = (float)(j&3)/3.0f ; + uv [ 1 ] = (float)(j>>2)/3.0f ; + + sgScaleVec3 ( xyz, vertex[patch[i][j+1]], 1.0f/2.5f ) ; + xyz [ 0 ] *= -1.0f ; + + p -> setControlPoint ( j>>2, j&3, xyz, uv, colour ) ; + } + + p -> setKidState ( getKidState () ) ; + p -> setKidCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB () ) ; + p -> setKidCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ; + p -> setColour ( colour ) ; + p -> setCenter ( getCenter () ) ; + p -> setSize ( getSize () ) ; + p -> regenerate () ; + + /* Make a mirror image in the Y axis */ + + sgVec3 xyz ; + sgVec2 uv ; + sgVec4 rgba ; + + ssgaPatch *p2 = new ssgaPatch ( ntriangles / 32 ) ; + + for ( j = 0 ; j < 16 ; j++ ) + { + p -> getControlPoint ( j>>2, 3-(j&3), xyz, uv, rgba ) ; + xyz [ 1 ] *= -1.0f ; + p2 -> setControlPoint ( j>>2, j&3, xyz, uv, rgba ) ; + } + + p2 -> setKidState ( getKidState () ) ; + p2 -> setKidCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB () ) ; + p2 -> setKidCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ; + p2 -> setColour ( colour ) ; + p2 -> setCenter ( getCenter () ) ; + p2 -> setSize ( getSize () ) ; + p2 -> regenerate () ; + + if ( patch[i][0] == 2 ) + { + /* Make a mirror images in the X axis */ + + ssgaPatch *p3 = new ssgaPatch ( ntriangles / 32 ) ; + ssgaPatch *p4 = new ssgaPatch ( ntriangles / 32 ) ; + + for ( j = 0 ; j < 16 ; j++ ) + { + p -> getControlPoint ( j>>2, 3-(j&3), xyz, uv, rgba ) ; + xyz [ 0 ] *= -1.0f ; + p3 -> setControlPoint ( j>>2, j&3, xyz, uv, rgba ) ; + + p2 -> getControlPoint ( j>>2, 3-(j&3), xyz, uv, rgba ) ; + xyz [ 0 ] *= -1.0f ; + p4 -> setControlPoint ( j>>2, j&3, xyz, uv, rgba ) ; + } + + p3 -> setKidState ( getKidState () ) ; + p3 -> setKidCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB () ) ; + p3 -> setKidCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ; + p3 -> setColour ( colour ) ; + p3 -> setCenter ( getCenter () ) ; + p3 -> setSize ( getSize () ) ; + p3 -> regenerate () ; + + p4 -> setKidState ( getKidState () ) ; + p4 -> setKidCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB () ) ; + p4 -> setKidCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ; + p4 -> setColour ( colour ) ; + p4 -> setCenter ( getCenter () ) ; + p4 -> setSize ( getSize () ) ; + p4 -> regenerate () ; + + for ( j = 0 ; j < p3 -> getNumKids () ; j++ ) + { + addKid ( p3->getKid(j) ) ; + addKid ( p4->getKid(j) ) ; + } + + p3 -> removeAllKids () ; + p4 -> removeAllKids () ; + delete p3 ; + delete p4 ; + } + + for ( j = 0 ; j < p -> getNumKids () ; j++ ) + { + addKid ( p->getKid(j) ) ; + addKid ( p2->getKid(j) ) ; + } + + p -> removeAllKids () ; + p2 -> removeAllKids () ; + delete p ; + delete p2 ; + } + + recalcBSphere () ; +} + + diff --git a/src/ssgAux/ssgaWaveSystem.cxx b/src/ssgAux/ssgaWaveSystem.cxx new file mode 100644 index 0000000..261cf48 --- /dev/null +++ b/src/ssgAux/ssgaWaveSystem.cxx @@ -0,0 +1,347 @@ + +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ssgaWaveSystem.cxx 1772 2003-06-27 08:15:15Z sjbaker $ +*/ + + +#include "ssgAux.h" +#include + +#define G 9.8f + +void ssgaWaveSystem::updateAnimation ( float tim ) +{ + if ( ntriangles <= 0 || + normals == NULL || colours == NULL || + texcoords == NULL || vertices == NULL || + orig_vertices == NULL ) + return ; + + int i ; + + float adjSpeed [ SSGA_MAX_WAVETRAIN ] ; + float sinHeading [ SSGA_MAX_WAVETRAIN ] ; + float cosHeading [ SSGA_MAX_WAVETRAIN ] ; + float length [ SSGA_MAX_WAVETRAIN ] ; + float lambda [ SSGA_MAX_WAVETRAIN ] ; + float height [ SSGA_MAX_WAVETRAIN ] ; + + /* Pre-adjust speed's to allow for wind speed. */ + + int num_trains = 0 ; + + for ( i = 0 ; i < SSGA_MAX_WAVETRAIN ; i++ ) + if ( train [ i ] != NULL ) + { + adjSpeed [num_trains] = train [ i ] -> getSpeed () * G * + tim / windSpeed ; + sinHeading [num_trains] = (float) -sin ( train[i]->getHeading () * + SG_DEGREES_TO_RADIANS ) ; + cosHeading [num_trains] = (float) cos ( train[i]->getHeading () * + SG_DEGREES_TO_RADIANS ) ; + length [num_trains] = train [ i ] -> getLength () ; + lambda [num_trains] = train [ i ] -> getLambda () ; + height [num_trains] = train [ i ] -> getWaveHeight () ; + num_trains++ ; + } + + for ( i = 0 ; i <= nstrips ; i++ ) + { + float fade_i = (i<2) ? 0.0f : (i<7) ? (float)(i-2)/5.0f : + (i>nstrips-2) ? 0.0f : + (i>nstrips-7) ? (float)(nstrips-i-2)/5.0f : 1.0f ; + + for ( int j = 0 ; j <= nstacks ; j++ ) + { + float fade_j = (j<2) ? 0.0f : (j<7) ? (float)(j-2)/5.0f : + (j>nstacks-2) ? 0.0f : + (j>nstacks-7) ? (float)(nstacks-j-2)/5.0f : 1.0f ; + + float edge_fade = fade_i * fade_j ; + + int idx = i * (nstrips+1) + j ; + + float xx = orig_vertices [idx][0] + center[0] ; + float yy = orig_vertices [idx][1] + center[1] ; + float zz = center[2] ; + + float x0 = xx + offset[0] ; + float y0 = yy + offset[1] ; + float z0 = vertices [idx][2] ; + + float depth = (gridGetter==NULL) ? 1000000.0f : gridGetter ( x0, y0 ) ; + + for ( int t = 0 ; t < num_trains ; t++ ) + { + float adjHeight = height [ t ] * edge_fade ; + float adjLength = ( depth < 0.2f ) ? 0.2f : + ( depth > length[t] ) ? length[t] : depth ; + + float phase = ( x0 * sinHeading[t] + y0 * cosHeading[t] ) / adjLength - + adjSpeed[t] - lambda[t] * z0 ; + + float delta = adjHeight * (float) sin ( phase ) ; + + xx += delta * sinHeading [ t ] ; + yy += delta * cosHeading [ t ] ; + zz += adjHeight * (float) -cos ( phase ) ; + } + + sgSetVec3 ( vertices [idx], xx, yy, zz ) ; + sgSetVec2 ( texcoords [idx], tu * x0 / size[0], tv * y0 /size[1] ) ; + } + } + + for ( i = 0 ; i < nstrips ; i++ ) + { + int i1 = i * (nstrips+1) ; + int i2 = (i+1) * (nstrips+1) ; + + for ( int j = 0 ; j < nstacks ; j++ ) + { + int idx1 = i1 + j ; + int idx2 = i2 + j ; + int idx3 = i1 + (j+1) ; + + sgVec3 ab ; sgSubVec3 ( ab, vertices[idx3], vertices[idx1] ) ; + sgVec3 ac ; sgSubVec3 ( ac, vertices[idx2], vertices[idx1] ) ; + + float nx = ab[1] * ac[2] - ab[2] * ac[1] ; + float ny = ab[2] * ac[0] - ab[0] * ac[2] ; + float nz = ab[0] * ac[1] - ab[1] * ac[0] ; + + /* About 10% of execution time is in this instruction! */ + float rlen = 1.0f / (float) sqrt ( nx * nx + ny * ny + nz * nz ) ; + + normals[idx1][0] = nx * rlen ; + normals[idx1][1] = ny * rlen ; + normals[idx1][2] = nz * rlen ; + } + } + + for ( i = 0 ; i < nstrips ; i++ ) + { + ssgVtxTable *vt = (ssgVtxTable *) getKid ( i ) ; + ssgVertexArray *vv = vt -> getVertices () ; + ssgNormalArray *nn = vt -> getNormals () ; + ssgColourArray *cc = vt -> getColours () ; + ssgTexCoordArray *tt = vt -> getTexCoords () ; + + int i1 = (i+1) * (nstrips+1) ; + int i2 = i * (nstrips+1) ; + + for ( int j = 0, jj = 0 ; j < nstacks + 1 ; j++, jj += 2, i1++, i2++ ) + { + vv -> set ( vertices [i1], jj ) ; vv -> set ( vertices [i2], jj+1 ) ; + nn -> set ( normals [i1], jj ) ; nn -> set ( normals [i2], jj+1 ) ; + cc -> set ( colours [i1], jj ) ; cc -> set ( colours [i2], jj+1 ) ; + tt -> set ( texcoords[i1], jj ) ; tt -> set ( texcoords[i2], jj+1 ) ; + } + } +} + + +void ssgaWaveSystem::copy_from ( ssgaWaveSystem *src, int clone_flags ) +{ + ssgaShape::copy_from ( src, clone_flags ) ; + + setDepthCallback ( src -> getDepthCallback () ) ; + setWindSpeed ( src -> getWindSpeed () ) ; + setWindDirn ( src -> getWindDirn () ) ; + setEdgeFlatten ( src -> getEdgeFlatten () ) ; +} + + +ssgBase *ssgaWaveSystem::clone ( int clone_flags ) +{ + ssgaWaveSystem *b = new ssgaWaveSystem ( getNumTris() ) ; + b -> copy_from ( this, clone_flags ) ; + return b ; +} + + +ssgaWaveSystem::ssgaWaveSystem ( int np ) : ssgaShape ( np ) +{ + type=ssgaTypeWaveSystem (); + + setDepthCallback ( NULL ) ; + setWindSpeed ( 1.0f ) ; + setWindDirn ( 0.0f ) ; + setEdgeFlatten ( 0.0f ) ; + + nstrips = nstacks = 0 ; + + offset [ 0 ] = offset [ 1 ] = 0.0f ; + + normals = NULL ; + colours = NULL ; + texcoords = NULL ; + vertices = NULL ; + orig_vertices = NULL ; + + tu = tv = 1.0f ; + + for ( int i = 0 ; i < SSGA_MAX_WAVETRAIN ; i++ ) + train [ i ] = NULL ; + + regenerate(); +} + + +ssgaWaveSystem::~ssgaWaveSystem (void) {} + +const char *ssgaWaveSystem::getTypeName(void) { return "ssgaWaveSystem" ; } + + +void ssgaWaveSystem::regenerate () +{ + delete[] normals ; + delete[] colours ; + delete[] texcoords ; + delete[] vertices ; + delete[] orig_vertices ; + + normals = NULL ; + colours = NULL ; + texcoords = NULL ; + vertices = NULL ; + orig_vertices = NULL ; + + nstrips = nstacks = 0 ; + + if ( kidState != NULL ) kidState -> ref () ; + removeAllKids () ; + if ( kidState != NULL ) kidState -> deRef () ; + + if ( ntriangles <= 0 ) + return ; + + int gridSize = (int) sqrt ( (float) ntriangles / 2.0f ) ; + + nstacks = gridSize ; + nstrips = gridSize ; + + if ( nstacks < 1 ) nstacks = 1 ; + if ( nstrips < 1 ) nstrips = 1 ; + + normals = new sgVec3 [ (nstacks+1) * (nstrips+1) ] ; + colours = new sgVec4 [ (nstacks+1) * (nstrips+1) ] ; + texcoords = new sgVec2 [ (nstacks+1) * (nstrips+1) ] ; + vertices = new sgVec3 [ (nstacks+1) * (nstrips+1) ] ; + orig_vertices = new sgVec3 [ (nstacks+1) * (nstrips+1) ] ; + + int i; + for ( i = 0 ; i <= nstrips ; i++ ) + for ( int j = 0 ; j <= nstacks ; j++ ) + { + int idx = i * (nstrips+1) + j ; + + float x = (float) j / (float) nstacks ; + float y = (float) i / (float) nstrips ; + + // if ( j == 0 ) x = -500.0f ; + // if ( j == nstacks ) x = 500.0f ; + // if ( i == 0 ) y = -500.0f ; + // if ( i == nstacks ) y = 500.0f ; + + sgSetVec3 ( vertices [idx], (x-0.5f) * size[0], + (y-0.5f) * size[1], 0.0f ) ; + sgSetVec3 ( normals [idx], 0.0f, 0.0f, 1.0f ) ; + sgSetVec2 ( texcoords[idx], x * tu, y * tv ) ; + sgCopyVec4 ( colours [idx], colour ) ; + sgCopyVec3 ( orig_vertices [ idx ], vertices [idx] ) ; + } + + for ( i = 0 ; i < nstrips ; i++ ) + { + ssgVtxTable *vt = new ssgVtxTable ; + ssgVertexArray *vv = new ssgVertexArray ( nstacks * 2 + 2 ) ; + ssgNormalArray *nn = new ssgNormalArray ( nstacks * 2 + 2 ) ; + ssgColourArray *cc = new ssgColourArray ( nstacks * 2 + 2 ) ; + ssgTexCoordArray *tt = new ssgTexCoordArray ( nstacks * 2 + 2 ) ; + + addKid ( vt ) ; + + vt -> setState ( getKidState () ) ; + vt -> setCallback ( SSG_CALLBACK_PREDRAW , getKidPreDrawCB () ) ; + vt -> setCallback ( SSG_CALLBACK_POSTDRAW, getKidPostDrawCB () ) ; + + vt -> setPrimitiveType ( GL_TRIANGLE_STRIP ) ; + + for ( int j = 0 ; j < nstacks + 1 ; j++ ) + { + int idx = (i+1) * (nstrips+1) + j ; + + vv -> add ( vertices [ idx ] ) ; nn -> add ( normals [ idx ] ) ; + cc -> add ( colours [ idx ] ) ; tt -> add ( texcoords[ idx ] ) ; + + idx = i * (nstrips+1) + j ; + + vv -> add ( vertices [ idx ] ) ; nn -> add ( normals [ idx ] ) ; + cc -> add ( colours [ idx ] ) ; tt -> add ( texcoords[ idx ] ) ; + } + + vt -> setVertices ( vv ) ; + vt -> setNormals ( nn ) ; + vt -> setColours ( cc ) ; + vt -> setTexCoords ( tt ) ; + + vt -> recalcBSphere () ; + } + + recalcBSphere () ; +} + + +// XXX really need these (and ssgLocal.h is not accessible): +extern int _ssgLoadObject ( FILE *, ssgBase **, int ) ; +extern int _ssgSaveObject ( FILE *, ssgBase * ) ; + + +#define load_field(fp, name) (fread(&(name), 1, sizeof(name), fp) == sizeof(name)) +#define save_field(fp, name) (fwrite(&(name), 1, sizeof(name), fp) == sizeof(name)) + + +int ssgaWaveSystem::load ( FILE *fp ) +{ + return ( load_field ( fp, windSpeed ) && + load_field ( fp, windHeading ) && + load_field ( fp, edgeFlatten ) && + load_field ( fp, tu ) && + load_field ( fp, tv ) && + ssgaShape::load ( fp ) ) ; +} + + + +int ssgaWaveSystem::save ( FILE *fp ) +{ + return ( save_field ( fp, windSpeed ) && + save_field ( fp, windHeading ) && + save_field ( fp, edgeFlatten ) && + save_field ( fp, tu ) && + save_field ( fp, tv ) && + ssgaShape::save ( fp ) ) ; +} + + + diff --git a/src/ssgAux/ssgaWaveSystem.h b/src/ssgAux/ssgaWaveSystem.h new file mode 100644 index 0000000..0e349f8 --- /dev/null +++ b/src/ssgAux/ssgaWaveSystem.h @@ -0,0 +1,131 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net */ + + + +#include "ssgaShapes.h" + +typedef float (* ssgaWSDepthCallback ) ( float x, float y ) ; + +#define SSGA_MAX_WAVETRAIN 16 + +class ssgaWaveTrain +{ + float height ; + float length ; + float lambda ; + float speed ; + float heading; + +public: + + ssgaWaveTrain () + { + height = 0.5f ; + length = 0.8f ; + lambda = 1.0f ; + speed = (float) sqrt ( 2.0f/3.0f ) ; + heading = 0.0f ; + } + + float getSpeed () { return speed ; } + void setSpeed ( float h ) { speed = h ; } + + float getLength () { return length ; } + void setLength ( float h ) { length = h ; } + + float getLambda () { return lambda ; } + void setLambda ( float h ) { lambda = h ; } + + float getHeading () { return heading ; } + void setHeading ( float h ) { heading = h ; } + + float getWaveHeight () { return height ; } + void setWaveHeight ( float h ) { height = h ; } +} ; + +class ssgaWaveSystem : public ssgaShape +{ + ssgaWSDepthCallback gridGetter ; + + sgVec2 offset ; + sgVec3 *normals ; + sgVec4 *colours ; + sgVec2 *texcoords ; + sgVec3 *vertices ; + sgVec3 *orig_vertices ; + + ssgaWaveTrain *train [ SSGA_MAX_WAVETRAIN ] ; + + float windSpeed ; + float windHeading ; + float edgeFlatten ; + + float tu, tv ; + + int nstrips ; + int nstacks ; + +protected: + virtual void copy_from ( ssgaWaveSystem *src, int clone_flags ) ; +public: + + ssgaWaveSystem ( int ntri ) ; + + virtual ~ssgaWaveSystem () ; + + virtual ssgBase *clone ( int clone_flags = 0 ) ; + virtual void regenerate () ; + virtual const char *getTypeName ( void ) ; + + virtual int load ( FILE * ) ; + virtual int save ( FILE * ) ; + + ssgaWSDepthCallback getDepthCallback () { return gridGetter ; } + + ssgaWaveTrain *getWaveTrain ( int i ) + { + return ( i < 0 || i >= SSGA_MAX_WAVETRAIN ) ? NULL : train [ i ] ; + } + + void setWaveTrain ( int i, ssgaWaveTrain *t ) + { + assert ( i >= 0 && i < SSGA_MAX_WAVETRAIN ) ; + train [ i ] = t ; + } + + float getWindSpeed () { return windSpeed ; } + float getWindDirn () { return windHeading ; } + float getEdgeFlatten () { return edgeFlatten ; } + float getTexScaleU () { return tu ; } + float getTexScaleV () { return tv ; } + + void setDepthCallback ( ssgaWSDepthCallback cb ) { gridGetter = cb ; } + void setWindSpeed ( float speed ) { windSpeed = speed ; } + void setWindDirn ( float dirn ) { windHeading = dirn ; } + void setEdgeFlatten ( float dist ) { edgeFlatten = dist ; } + void setTexScale ( float u, float v ) { tu = u ; tv = v ; } + + void setOffset ( sgVec2 _offset ) { sgCopyVec2 ( offset, _offset ) ; } + + void updateAnimation ( float t ) ; +} ; + + diff --git a/src/util/Makefile.am b/src/util/Makefile.am new file mode 100644 index 0000000..4000358 --- /dev/null +++ b/src/util/Makefile.am @@ -0,0 +1,13 @@ +if BUILD_UL + +lib_LIBRARIES = libplibul.a + +include_HEADERS = ul.h ulRTTI.h + +libplibul_a_SOURCES = ul.cxx ulClock.cxx ulError.cxx ulLinkedList.cxx \ + ulList.cxx ulLocal.h ulRTTI.cxx + +endif + +EXTRA_DIST = ul.dsp + diff --git a/src/util/ul.cxx b/src/util/ul.cxx new file mode 100644 index 0000000..b0743f8 --- /dev/null +++ b/src/util/ul.cxx @@ -0,0 +1,544 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ul.cxx 2129 2007-10-16 00:45:26Z fayjf $ +*/ + + +#include "ul.h" + +#include +#include + +#ifdef UL_MSVC +#include +#else +#include +#endif + +#ifdef UL_MSVC +#define SLASH "\\" +#else +#define SLASH "/" +#endif + + +struct _ulDir +{ + char dirname [ UL_NAME_MAX+1 ]; + ulDirEnt curr ; + +#ifdef UL_MSVC + WIN32_FIND_DATA data ; + HANDLE hFind ; + bool first ; + bool done ; +#else + DIR *dirp ; +#endif +} ; + + +void ulInit () +{ +} + + +ulDir* ulOpenDir ( const char* dirname ) +{ + ulDir* dir = new ulDir; + if ( dir != NULL ) + { + strcpy( dir->dirname, dirname ) ; + +#ifdef UL_MSVC + char search[_MAX_PATH]; + strcpy(search,dirname); + + //munch the directory seperator + int len = strlen(search); + if ( len>0 && strchr("/\\",search[len-1]) ) + search[len-1] = 0; + + //add the wildcard + strcat(search,"/*.*"); + + dir->first = true; + dir->done = false; + dir->hFind = FindFirstFile(search, &dir->data); + if (dir->hFind == INVALID_HANDLE_VALUE) + { + delete dir; + dir = NULL; + } +#else + dir->dirp = opendir(dirname) ; + + if ( dir->dirp == NULL ) + { + delete dir ; + dir = NULL ; + } +#endif + } + return dir; +} + + +ulDirEnt* ulReadDir ( ulDir* dir ) +{ + //read the next entry from the directory +#ifdef UL_MSVC + //update state + if ( dir->first ) + dir->first = false ; + else if ( !dir->done && !FindNextFile(dir->hFind,&dir->data) ) + dir->done = true ; + if ( dir->done ) + return NULL ; + + strcpy( dir->curr.d_name, dir->data.cFileName ) ; +#else + struct dirent* direntp = readdir( dir->dirp ); + if ( !direntp ) + return NULL ; + + strcpy( dir->curr.d_name, direntp->d_name ); +#endif + + //determine if this entry is a directory +#ifdef UL_MSVC + dir->curr.d_isdir = ( dir->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) != 0; + #else + char path[ 1000 + UL_NAME_MAX+1 ]; + sprintf( path, "%s/%s", dir->dirname, dir->curr.d_name ); + struct stat buf ; + if ( stat(path,&buf) == 0 ) + dir->curr.d_isdir = (buf.st_mode & S_IFDIR) != 0 ; + else + dir->curr.d_isdir = false ; +#endif + + return( &dir->curr ) ; +} + + + +void ulCloseDir ( ulDir* dir ) +{ + if ( dir != NULL ) + { +#ifdef UL_MSVC + FindClose(dir->hFind); +#else + closedir ( dir->dirp ) ; +#endif + delete dir ; + } +} + +bool ulFileExists ( const char *fileName ) +{ +#ifdef UL_MSVC + struct _stat buf ; + + if ( _stat ( fileName, &buf ) < 0 ) + return false ; + + return ((S_IFREG & buf.st_mode ) !=0) ; +#else + struct stat buf ; + + if ( stat ( fileName, &buf ) < 0 ) + return false ; + + return ((S_ISREG ( buf.st_mode )) != 0) ; +#endif +} + +char* ulMakePath( char* path, const char* dir, const char* fname ) +{ + if ( fname ) + { + if ( !ulIsAbsolutePathName (fname) && + dir != NULL && dir[0] != '\0' ) + { + strcpy ( path, dir ) ; + strcat ( path, SLASH ) ; + strcat ( path, fname ) ; + } + else + strcpy ( path, fname ) ; + } + else + path [0] = 0 ; + return( path ); +} + + +static int recursiveFindFileInSubDirs ( char * filenameOutput, + const char * tPath, const char * tfnameInput ) +{ + int bFound = FALSE; + char tempString [ 1024 ]; + + ulMakePath ( filenameOutput, tPath, tfnameInput ) ; + + if ( ulFileExists ( filenameOutput ) ) + return TRUE; + + ulDir* dirp = ulOpenDir(tPath); + + if ( dirp != NULL ) + { + ulDirEnt* dp; + + while ( ! bFound && ((dp = ulReadDir(dirp)) != NULL ) ) + { + // I am doing recursive ulOpenDir/ulReadDirs here. + // I know this works under Windo$. + if ( dp->d_isdir && + strcmp( dp->d_name, ".") != 0 && + strcmp( dp->d_name, "..") != 0 ) + { + ulMakePath ( tempString, tPath, dp->d_name) ; + bFound = recursiveFindFileInSubDirs ( filenameOutput, + tempString, tfnameInput ); + } + + } + ulCloseDir ( dirp ) ; + } + + return bFound; +} + + + +void ulFindFile( char *filenameOutput, const char *path, + const char * tfnameInput, const char *sAPOM ) +/* + adds tfnameInput to the path and puts this into the buffer filenameOutput. + sAPOM is used iff path contains "$(APOM)" + + handles special chars in path: + + ";;" is replaced by ";" + "$$" is replaced by "$" + "$(APOM)" is replaced by sAPOM + + If there are ";" in path, the path-variable is interpreted as several + paths "segments", delimited by ";". The first file found by this function + is returned. + + It looks from left to right. + + A segment may end in $(...). ulFindFile will then look in in this + path and recursively in all the sub-paths + + Some examples: + + for loading *.MDl-models, it is very nice to set the texture path to + + $(APOM);$(APOM)/texture;$(APOM)/../texture + + This consits of three segments and tells ulFindFile to look in the + path of the model, in a subpath texture and in a path texture "besides" + the path of the model. Some *.mdl-models are shipped in a directory which + conatins a "texture"-directory, a "Model"-directory and others. In this + case you find the texture in $(APOM)/../texture + + Another example: You have all your textures in a directory-structure + under /roomplan. For example brick is under /roomplan/bricks, wood is + under /roomplan/wood, oak is under /roomplan/wood/oak. Then you should + use the following texture path: + + "/roomplan/$(...)" + + If you dont want all of the bells and whistles, just call: + _ssgMakePath ( filenameOutput, path, tfnameInput ) ; +*/ + +{ + + char temp_texture_path[1024], *s_ptr, *s_ptr1, *current_path; + + strncpy(temp_texture_path, path, 1024); + current_path = temp_texture_path; + s_ptr = temp_texture_path; + + while ( *s_ptr != 0 ) + { + if ( *s_ptr == ';' ) + { + if ( s_ptr [ 1 ] == ';' ) + { + // replace ";;" with ";" + s_ptr1 = ++s_ptr; // both pointers on second ";" + + while ( *s_ptr1 != 0) + { s_ptr1 [ 0 ] = s_ptr1 [ 1 ]; + s_ptr1++; + } + } + else + { + // found a single ';'. This delimits paths + *s_ptr++ = 0; + ulMakePath ( filenameOutput, current_path, tfnameInput ) ; + + if ( ulFileExists ( filenameOutput ) ) + return; // success! + + // this path doesnt hold the texture. Try next one + current_path = s_ptr; + } + } + else if ( *s_ptr == '$' ) + { + if ( s_ptr [ 1 ] == '$' ) + { + // replace "$$" with "$" + s_ptr1 = ++s_ptr; // both pointers on second "$" + + while ( *s_ptr1 != 0) + { + s_ptr1 [ 0 ] = s_ptr1 [ 1 ]; + s_ptr1++; + } + } + else + if ( 0 == strncmp( s_ptr, "$(APOM)", strlen("$(APOM)" ) ) ) + { + // replace "$(APOM)" by sAPOM + char temp_buffer[1024]; + * s_ptr = 0; + s_ptr += strlen ( "$(APOM)" ); + strcpy ( temp_buffer, s_ptr ); + strcat ( current_path, sAPOM); + s_ptr = & current_path [ strlen(current_path) ] ; // onto the 0 + strcat ( current_path, temp_buffer ); + } + else + if ( 0 == strncmp( s_ptr, "$(...)", strlen("$(...)" ) ) ) + { + //strcpy(temp_texture_path_for_recursion, current_path); + + char * nextPath=s_ptr; + nextPath += strlen("$(...)" ); + + while (*nextPath != 0 ) + { + if ( *nextPath == ';' ) + { + if ( nextPath[1] == ';' ) + nextPath++; // so its "add 2 " togehter with the ++ further down + else + { + *nextPath = 0; + break; // breaks the while + } + } + nextPath++; + } + + // This segment of the path ends with a 0 now + // ***** + + char tPath [ 1024 ]; + strcpy ( tPath, current_path ) ; + tPath [ (long) (s_ptr - current_path) ] = 0; + + // So, lets recurse into the sub-dirs: + // Here I just assume that the "$(...)" is the last thing in + // this segment + + if ( recursiveFindFileInSubDirs ( filenameOutput, + tPath, tfnameInput ) ) + return ; // success + + // ***** + // we handled the path-segment current_path containing the $(...) and + // didnt find the file, so go on to the nect segment + + current_path = nextPath; // points to a 0 if this was the last segment + s_ptr = current_path; + } + else + s_ptr++; + } + else // neither ';' nor '$' + s_ptr++; + } + + ulMakePath ( filenameOutput, current_path, tfnameInput ) ; // pfusch? kludge? +} + +///////////////////// string handling /////////////////////////////// + +/* + Strdup is *evil* - use this instead... +*/ + +char *ulStrDup ( const char *s ) +{ + int s_sz = strlen ( s ) + 1 ; + char *ret = new char [ s_sz ] ; + + memcpy ( ret, s, s_sz ) ; + return ret ; +} + + + +// string comparisons that are *not* case sensitive: + +/* + + + I'm sick of half the machines on the planet supporting + strncasecmp and the other half strnicmp - so here is my own + offering. + + **** ATTENTION **** + WK: If you used strnicmp, make sure you realise the completely + changed meaning of the return value - 0 means not equal! +*/ + +int ulStrNEqual ( const char *s1, const char *s2, int len ) +{ + int l1 = (s1==NULL) ? 0 : strlen ( s1 ) ; + int l2 = (s2==NULL) ? 0 : strlen ( s2 ) ; + + if ( l1 > len ) l1 = len ; + + if ( l2 < l1 || l1 < len ) + return FALSE ; + + for ( int i = 0 ; i < l1 ; i++ ) + { + char c1 = s1[i] ; + char c2 = s2[i] ; + + if ( c1 == c2 ) + continue ; + + if ( c1 >= 'a' && c1 <= 'z' ) + c1 = c1 - ('a'-'A') ; + + if ( c2 >= 'a' && c2 <= 'z' ) + c2 = c2 - ('a'-'A') ; + + if ( c1 != c2 ) + return FALSE ; + } + + return TRUE ; +} + + +/* + I'm sick of half the machines on the planet supporting + strcasecmp and the other half stricmp - so here is my own + offering. + + **** ATTENTION **** + WK: If you used stricmp, make sure you realise the completely + changed meaning of the return value - 0 means not equal! +*/ + +int ulStrEqual ( const char *s1, const char *s2 ) +{ + int l1 = (s1==NULL) ? 0 : strlen ( s1 ) ; + int l2 = (s2==NULL) ? 0 : strlen ( s2 ) ; + + if ( l1 != l2 ) return FALSE ; + + for ( int i = 0 ; i < l1 ; i++ ) + { + char c1 = s1[i] ; + char c2 = s2[i] ; + + if ( c1 == c2 ) + continue ; + + if ( c1 >= 'a' && c1 <= 'z' ) + c1 -= ('a'-'A') ; + + if ( c2 >= 'a' && c2 <= 'z' ) + c2 -= ('a'-'A') ; + + if ( c1 != c2 ) + return FALSE ; + } + + return TRUE ; +} + + +int ulIsAbsolutePathName ( const char *pathname ) +{ + /* + Is this an absolute pathname or a relative one? + */ + + if ( (pathname == NULL) || (pathname [0] == 0) ) + return FALSE; + +#ifdef UL_MSVC + + /* + Under WinDOS, it's an absolute path if it starts + with a slash *or* if it starts with a drive letter, + a colon and a slash. + */ + + return ( pathname[0] == SLASH[0] || pathname[0] == '/' ) || + ( + ( + ( pathname[0] >= 'a' && pathname[0] <= 'z' ) || + ( pathname[0] >= 'A' && pathname[0] <= 'Z' ) + ) && + pathname[1] == ':' && + ( pathname[2] == SLASH[0] || pathname[2] == '/' ) + ) ; +#elif defined(UL_MACINTOSH) + return (pathname [0] != ':' && strchr( pathname, ':') != NULL ); +#else + return pathname [0] == SLASH[0] ; +#endif +} + + +char *ulGetCWD ( char *result, int maxlength ) +{ + /* + Return the current working directory into 'result' - which + has enough space for 'maxlength-1' characters and a '\0'. + */ + +#ifdef UL_MSVC + return _getcwd ( result, maxlength ) ; +#else + return getcwd ( result, maxlength ) ; +#endif +} + + diff --git a/src/util/ul.dsp b/src/util/ul.dsp new file mode 100644 index 0000000..d48303f --- /dev/null +++ b/src/util/ul.dsp @@ -0,0 +1,130 @@ +# Microsoft Developer Studio Project File - Name="ul" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=ul - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ul.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ul.mak" CFG="ul - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ul - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "ul - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ul - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy release\*.lib ..\..\*.* copy ul.h ..\..\ul.h copy ulRTTI.h ..\..\ulRTTI.h +# End Special Build Tool + +!ELSEIF "$(CFG)" == "ul - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\ul_d.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy Library to plib directory +PostBuild_Cmds=copy debug\*.lib ..\..\*.* copy ul.h ..\..\ul.h copy ulRTTI.h ..\..\ulRTTI.h +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "ul - Win32 Release" +# Name "ul - Win32 Debug" +# Begin Source File + +SOURCE=.\ul.cxx +# End Source File +# Begin Source File + +SOURCE=.\ul.h +# End Source File +# Begin Source File + +SOURCE=.\ulClock.cxx +# End Source File +# Begin Source File + +SOURCE=.\ulError.cxx +# End Source File +# Begin Source File + +SOURCE=.\ulLinkedList.cxx +# End Source File +# Begin Source File + +SOURCE=.\ulList.cxx +# End Source File +# Begin Source File + +SOURCE=.\ulLocal.h +# End Source File +# Begin Source File + +SOURCE=.\ulRTTI.cxx +# End Source File +# Begin Source File + +SOURCE=.\ulRTTI.h +# End Source File +# End Target +# End Project diff --git a/src/util/ul.h b/src/util/ul.h new file mode 100644 index 0000000..f01ba01 --- /dev/null +++ b/src/util/ul.h @@ -0,0 +1,851 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ul.h 2131 2008-03-11 02:23:50Z sjbaker $ +*/ + +// +// UL - utility library +// +// Contains: +// - necessary system includes +// - basic types +// - error message routines +// - high performance clocks +// - ulList +// - ulLinkedList +// - more to come (endian support, version ID) +// + +#ifndef _INCLUDED_UL_H_ +#define _INCLUDED_UL_H_ + +#include +#include +#include +#include +#include +#include + +/**********************\ +* * +* Determine OS type * +* * +\**********************/ + +#if defined(__CYGWIN__) + +#define UL_WIN32 1 +#define UL_CYGWIN 1 /* Windoze AND Cygwin. */ + +#elif defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) + +#define UL_WIN32 1 +#define UL_MSVC 1 /* Windoze AND MSVC. */ + +#elif defined(__BEOS__) + +#define UL_BEOS 1 + +#elif defined( macintosh ) + +#define UL_MACINTOSH 1 + +#elif defined(__APPLE__) + +#define UL_MAC_OSX 1 + +#elif defined(__linux__) + +#define UL_LINUX 1 + +#elif defined(__sgi) + +#define UL_IRIX 1 + +#elif defined(_AIX) + +#define UL_AIX 1 + +#elif defined(SOLARIS) || defined(sun) + +#define UL_SOLARIS 1 + +#elif defined(hpux) + +#define UL_HPUX 1 + +#elif (defined(__unix__) || defined(unix)) && !defined(USG) + +#define UL_BSD 1 + +#endif + + +/* + Add specialised includes/defines... +*/ + +#ifdef UL_WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#define UL_WGL 1 +#endif + +#ifdef UL_CYGWIN +#include +#define UL_WGL 1 +#endif + +#ifdef UL_BEOS +#include +#define UL_GLX 1 +#endif + +#ifdef UL_MACINTOSH +#include +#include +#define UL_AGL 1 +#endif + +#ifdef UL_MAC_OSX +#include +#define UL_CGL 1 +#endif + +#if defined(UL_LINUX) || defined(UL_BSD) || defined(UL_IRIX) || defined(UL_SOLARIS) || defined(UL_AIX) +#include +#include +#include +#define UL_GLX 1 +#endif + +#if defined(UL_BSD) +#include +#define UL_GLX 1 +#endif + +#include +#include +#include +#include +#include + +/* PLIB version macros */ + +#define PLIB_MAJOR_VERSION 1 +#define PLIB_MINOR_VERSION 8 +#define PLIB_TINY_VERSION 5 + +#define PLIB_VERSION (PLIB_MAJOR_VERSION*100 \ + +PLIB_MINOR_VERSION*10 \ + +PLIB_TINY_VERSION) + +/* SGI machines seem to suffer from a lack of FLT_EPSILON so... */ + +#ifndef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07f +#endif + +#ifndef DBL_EPSILON +#define DBL_EPSILON 1.19209290e-07f +#endif + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +/* SUNWspro 4.2 and earlier need bool to be defined */ + +#if defined(__SUNPRO_CC) && __SUNPRO_CC < 0x500 +typedef int bool ; +const int true = 1 ; +const int false = 0 ; +#endif + +/* Let's define our own "min" and "max" so that different operating systems + * don't complain + */ +#define ulMax(a,b) ((a)>(b)?(a):(b)) +#define ulMin(a,b) ((a)<(b)?(a):(b)) + + +/* + Basic Types +*/ + + +/* + High precision clocks. +*/ + +class ulClock +{ + double start ; + double now ; + double delta ; + double last_time ; + double max_delta ; + +#ifdef UL_WIN32 + static double res ; + static int perf_timer ; + void initPerformanceTimer () ; +#endif + + double getRawTime () const ; + +public: + + ulClock () { reset () ; } + + void reset () + { +#ifdef UL_WIN32 + initPerformanceTimer () ; +#endif + start = getRawTime () ; + now = 0.0 ; + max_delta = 0.2 ; + delta = 0.0000001 ; /* Faked so stoopid programs won't div0 */ + last_time = 0.0 ; + } + + void setMaxDelta ( double maxDelta ) { max_delta = maxDelta ; } + double getMaxDelta () const { return max_delta ; } + void update () ; + double getAbsTime () const { return now ; } + double getDeltaTime () const { return delta ; } + double getFrameRate () const { return 1.0 / delta ; } +} ; + + +inline void ulSleep ( int seconds ) +{ + if ( seconds >= 0 ) + { +#ifdef UL_WIN32 + Sleep ( 1000 * seconds ) ; +#else + sleep ( seconds ) ; +#endif + } +} + + +inline void ulMilliSecondSleep ( int milliseconds ) +{ + if ( milliseconds >= 0 ) + { +#ifdef UL_WIN32 + Sleep ( milliseconds ) ; +#else + usleep ( milliseconds * 1000 ) ; +#endif + } +} + + +/* + This is extern C to enable 'configure.in' to + find it with a C-coded probe. +*/ + +extern "C" void ulInit () ; + +/* + Error handler. +*/ + +enum ulSeverity +{ + UL_DEBUG, // Messages that can safely be ignored. + UL_WARNING, // Messages that are important. + UL_FATAL, // Errors that we cannot recover from. + UL_MAX_SEVERITY +} ; + + +typedef void (*ulErrorCallback) ( enum ulSeverity severity, char* msg ) ; + +void ulSetError ( enum ulSeverity severity, const char *fmt, ... ) ; +char* ulGetError ( void ) ; +void ulClearError ( void ) ; +ulErrorCallback ulGetErrorCallback ( void ) ; +void ulSetErrorCallback ( ulErrorCallback cb ) ; + +/* + Directory Reading +*/ + +#define UL_NAME_MAX 256 +typedef struct _ulDir ulDir ; +struct ulDirEnt +{ + char d_name [ UL_NAME_MAX+1 ]; + bool d_isdir ; +} ; + +int ulIsAbsolutePathName ( const char *pathname ) ; +char *ulGetCWD ( char *result, int maxlength ) ; + +ulDir* ulOpenDir ( const char* dirname ) ; +ulDirEnt* ulReadDir ( ulDir* dir ) ; +void ulCloseDir ( ulDir* dir ) ; + +// file handling + +char* ulMakePath( char* path, const char* dir, const char* fname ); + +bool ulFileExists ( const char *fileName ) ; + +void ulFindFile( char *filenameOutput, const char *path, + const char * tfnameInput, const char *sAPOM ) ; + + +/* + Endian handling +*/ + +static const int _ulEndianTest = 1; +#define ulIsLittleEndian (*((char *) &_ulEndianTest ) != 0) +#define ulIsBigEndian (*((char *) &_ulEndianTest ) == 0) + +inline void ulEndianSwap(unsigned int *x) +{ + *x = (( *x >> 24 ) & 0x000000FF ) | + (( *x >> 8 ) & 0x0000FF00 ) | + (( *x << 8 ) & 0x00FF0000 ) | + (( *x << 24 ) & 0xFF000000 ) ; +} + + +inline void ulEndianSwap(unsigned short *x) +{ + *x = (( *x >> 8 ) & 0x00FF ) | + (( *x << 8 ) & 0xFF00 ) ; +} + + +inline void ulEndianSwap(float *x) { ulEndianSwap((unsigned int *)x); } +inline void ulEndianSwap(int *x) { ulEndianSwap((unsigned int *)x); } +inline void ulEndianSwap(short *x) { ulEndianSwap((unsigned short *)x); } + + +inline unsigned short ulEndianLittle16(unsigned short x) { + if (ulIsLittleEndian) { + return x; + } else { + ulEndianSwap(&x); + return x; + } +} + +inline unsigned int ulEndianLittle32(unsigned int x) { + if (ulIsLittleEndian) { + return x; + } else { + ulEndianSwap(&x); + return x; + } +} + +inline float ulEndianLittleFloat(float x) { + if (ulIsLittleEndian) { + return x; + } else { + ulEndianSwap(&x); + return x; + } +} + +inline void ulEndianLittleArray16(unsigned short *x, int length) { + if (ulIsLittleEndian) { + return; + } else { + for (int i = 0; i < length; i++) { + ulEndianSwap(x++); + } + } +} + +inline void ulEndianLittleArray32(unsigned int *x, int length) { + if (ulIsLittleEndian) { + return; + } else { + for (int i = 0; i < length; i++) { + ulEndianSwap(x++); + } + } +} + +inline void ulEndianLittleArrayFloat(float *x, int length) { + if (ulIsLittleEndian) { + return; + } else { + for (int i = 0; i < length; i++) { + ulEndianSwap(x++); + } + } +} + +inline void ulEndianBigArray16(unsigned short *x, int length) { + if (ulIsBigEndian) { + return; + } else { + for (int i = 0; i < length; i++) { + ulEndianSwap(x++); + } + } +} + +inline void ulEndianBigArray32(unsigned int *x, int length) { + if (ulIsBigEndian) { + return; + } else { + for (int i = 0; i < length; i++) { + ulEndianSwap(x++); + } + } +} + +inline void ulEndianBigArrayFloat(float *x, int length) { + if (ulIsBigEndian) { + return; + } else { + for (int i = 0; i < length; i++) { + ulEndianSwap(x++); + } + } +} + +inline unsigned short ulEndianBig16(unsigned short x) { + if (ulIsBigEndian) { + return x; + } else { + ulEndianSwap(&x); + return x; + } +} + +inline unsigned int ulEndianBig32(unsigned int x) { + if (ulIsBigEndian) { + return x; + } else { + ulEndianSwap(&x); + return x; + } +} + +inline float ulEndianBigFloat(float x) { + if (ulIsBigEndian) { + return x; + } else { + ulEndianSwap(&x); + return x; + } +} + +inline unsigned short ulEndianReadLittle16(FILE *f) { + unsigned short x; + fread(&x, 2, 1, f); + return ulEndianLittle16(x); +} + +inline unsigned int ulEndianReadLittle32(FILE *f) { + unsigned int x; + fread(&x, 4, 1, f); + return ulEndianLittle32(x); +} + +inline float ulEndianReadLittleFloat(FILE *f) { + float x; + fread(&x, 4, 1, f); + return ulEndianLittleFloat(x); +} + +inline unsigned short ulEndianReadBig16(FILE *f) { + unsigned short x; + fread(&x, 2, 1, f); + return ulEndianBig16(x); +} + +inline unsigned int ulEndianReadBig32(FILE *f) { + unsigned int x; + fread(&x, 4, 1, f); + return ulEndianBig32(x); +} + +inline float ulEndianReadBigFloat(FILE *f) { + float x; + fread(&x, 4, 1, f); + return ulEndianBigFloat(x); +} + +inline size_t ulEndianWriteLittle16(FILE *f, unsigned short x) { + x = ulEndianLittle16(x); + return fwrite( &x, 2, 1, f ); +} + +inline size_t ulEndianWriteLittle32(FILE *f, unsigned int x) { + x = ulEndianLittle32(x); + return fwrite( &x, 4, 1, f ); +} + +inline size_t ulEndianWriteLittleFloat(FILE *f, float x) { + x = ulEndianLittleFloat(x); + return fwrite( &x, 4, 1, f ); +} + +inline size_t ulEndianWriteBig16(FILE *f, unsigned short x) { + x = ulEndianBig16(x); + return fwrite( &x, 2, 1, f ); +} + +inline size_t ulEndianWriteBig32(FILE *f, unsigned int x) { + x = ulEndianBig32(x); + return fwrite( &x, 4, 1, f ); +} + +inline size_t ulEndianWriteBigFloat(FILE *f, float x) { + x = ulEndianBigFloat(x); + return fwrite( &x, 4, 1, f ); +} + + +/* + Windoze/BEOS code based on contribution from Sean L. Palmer +*/ + + +#ifdef UL_WIN32 + +class ulDynamicLibrary +{ + HMODULE handle ; + +public: + + ulDynamicLibrary ( const char *libname ) + { + char dllname[1024]; + strcpy ( dllname, libname ) ; + strcat ( dllname, ".dll" ) ; + handle = (HMODULE) LoadLibrary ( dllname ) ; + } + + void *getFuncAddress ( const char *funcname ) + { + return (void *) GetProcAddress ( handle, funcname ) ; //lint !e611 + } + + ~ulDynamicLibrary () + { + if ( handle != NULL ) + FreeLibrary ( handle ) ; + } +} ; + +#elif defined (UL_MACINTOSH) + +class ulDynamicLibrary +{ + CFragConnectionID connection; + OSStatus error; + +public: + + ulDynamicLibrary ( const char *libname ) + { + Str63 pstr; + int sz; + + sz = strlen (libname); + + if (sz < 64) { + + pstr[0] = sz; + memcpy (pstr+1, libname, sz); + + error = GetSharedLibrary (pstr, kPowerPCCFragArch, kReferenceCFrag, + &connection, NULL, NULL); + } + else + error = 1; + } + + ~ulDynamicLibrary () + { + if ( ! error ) + CloseConnection (&connection); + } + + void* getFuncAddress ( const char *funcname ) + { + if ( ! error ) { + + char* addr; + Str255 sym; + int sz; + + sz = strlen (funcname); + if (sz < 256) { + + sym[0] = sz; + memcpy (sym+1, funcname, sz); + + error = FindSymbol (connection, sym, &addr, 0); + if ( ! error ) + return addr; + } + } + + return NULL; + } +}; + +#elif defined (UL_MAC_OSX) + + +class ulDynamicLibrary +{ + + public: + + ulDynamicLibrary ( const char *libname ) + { + } + + ~ulDynamicLibrary () + { + } + + void* getFuncAddress ( const char *funcname ) + { + ulSetError ( UL_WARNING, "ulDynamicLibrary unsuppored on Mac OS X" ); + return NULL; + } +}; + +#elif defined (__BEOS__) + +class ulDynamicLibrary +{ + image_id *handle ; + +public: + + ulDynamicLibrary ( const char *libname ) + { + char addonname[1024] ; + strcpy ( addonname, libname ) ; + strcat ( addonname, ".so" ) ; + handle = new image_id ; + + *handle = load_add_on ( addonname ) ; + + if ( *handle == B_ERROR ) + { + delete handle ; + handle = NULL ; + } + } + + void *getFuncAddress ( const char *funcname ) + { + void *sym = NULL ; + + if ( handle && + get_image_symbol ( handle, "funcname", + B_SYMBOL_TYPE_TEXT, &sym ) == B_NO_ERROR ) + return sym ; + + return NULL ; + } + + ~ulDynamicLibrary () + { + if ( handle != NULL ) + unload_add_on ( handle ) ; + + delete handle ; + } +} ; + +# else + +/* + Linux/UNIX +*/ + +class ulDynamicLibrary +{ + void *handle ; + +public: + + ulDynamicLibrary ( const char *libname ) + { + char dsoname [ 1024 ] ; + strcpy ( dsoname, libname ) ; + strcat ( dsoname, ".so" ) ; + handle = (void *) dlopen ( dsoname, RTLD_NOW | RTLD_GLOBAL ) ; + + if ( handle == NULL ) + ulSetError ( UL_WARNING, "ulDynamicLibrary: %s\n", dlerror() ) ; + } + + void *getFuncAddress ( const char *funcname ) + { + return (handle==NULL) ? NULL : dlsym ( handle, funcname ) ; + } + + ~ulDynamicLibrary () + { + if ( handle != NULL ) + dlclose ( handle ) ; + } +} ; + +#endif + + +class ulList +{ +protected: + unsigned int total ; /* The total number of entities in the list */ + unsigned int limit ; /* The current limit on number of entities */ + unsigned int next ; /* The next entity when we are doing getNext ops */ + + void **entity_list ; /* The list. */ + + void sizeChk (void) ; + +public: + + ulList ( int init_max = 1 ) ; + virtual ~ulList (void) ; + + void *getEntity ( unsigned int n ) + { + next = n + 1 ; + return ( n >= total ) ? (void *) NULL : entity_list [ n ] ; + } + + virtual void addEntity ( void *entity ) ; + virtual void addEntityBefore ( int n, void *entity ) ; + virtual void removeEntity ( unsigned int n ) ; + + void removeAllEntities () ; + + void removeEntity ( void *entity ) + { + removeEntity ( searchForEntity ( entity ) ) ; + } + + virtual void replaceEntity ( unsigned int n, void *new_entity ) ; + + void replaceEntity ( void *old_entity, void *new_entity ) + { + replaceEntity ( searchForEntity ( old_entity ), new_entity ) ; + } + + void *getNextEntity (void) { return getEntity ( next ) ; } + + int getNumEntities (void) const { return total ; } + int searchForEntity ( void *entity ) const ; +} ; + + +typedef bool (*ulIterateFunc)( const void *data, void *user_data ) ; +typedef int (*ulCompareFunc)( const void *data1, const void *data2 ) ; + +/* + Linked list. +*/ + +class ulListNode ; + +class ulLinkedList +{ +protected: + + ulListNode *head ; + ulListNode *tail ; + + int nnodes ; + bool sorted ; + + void unlinkNode ( ulListNode *prev, ulListNode *node ) ; + + bool isValidPosition ( int pos ) const + { + if ( ( pos < 0 ) || ( pos >= nnodes ) ) + { + ulSetError ( UL_WARNING, "ulLinkedList: Invalid 'pos' %u", pos ) ; + return false ; + } + return true ; + } + +public: + + ulLinkedList () + { + head = tail = NULL ; + nnodes = 0 ; + sorted = true ; + } + + ~ulLinkedList () { empty () ; } + + int getNumNodes ( void ) const { return nnodes ; } + bool isSorted ( void ) const { return sorted ; } + + int getNodePosition ( void *data ) const ; + + void insertNode ( void *data, int pos ) ; + void prependNode ( void *data ) { insertNode ( data, 0 ) ; } + void appendNode ( void *data ) ; + + int insertSorted ( void *data, ulCompareFunc comparefn ) ; + + void removeNode ( void *data ) ; + void * removeNode ( int pos ) ; + + void * getNodeData ( int pos ) const ; + + void * forEach ( ulIterateFunc fn, void *user_data = NULL ) const ; + + void empty ( ulIterateFunc destroyfn = NULL, void *user_data = NULL ) ; +} ; + + +extern char *ulStrDup ( const char *s ) ; +extern int ulStrNEqual ( const char *s1, const char *s2, int len ); +extern int ulStrEqual ( const char *s1, const char *s2 ); + +//lint -restore + +#endif + diff --git a/src/util/ulClock.cxx b/src/util/ulClock.cxx new file mode 100644 index 0000000..f218385 --- /dev/null +++ b/src/util/ulClock.cxx @@ -0,0 +1,117 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ulClock.cxx 1735 2002-12-01 18:21:48Z sjbaker $ +*/ + + +#include +#include +#include "ul.h" + +#ifdef UL_CYGWIN + typedef long long _int64; + #define LARGEINTEGER _int64 +#endif + +#ifndef UL_WIN32 +# include +#endif + +#include + +#ifdef UL_WIN32 + +double ulClock::res ; +int ulClock::perf_timer = -1; + +void ulClock::initPerformanceTimer () +{ + if ( perf_timer == -1 ) + { + /* Use Performance Timer if it's available, mmtimer if not. */ + + __int64 frequency ; + + perf_timer = QueryPerformanceFrequency ( (LARGE_INTEGER *) & frequency ) ; + + if ( perf_timer ) + { + res = 1.0 / (double) frequency ; + perf_timer = 1 ; + } + } +} +#endif + +double ulClock::getRawTime () const +{ +#ifdef UL_WIN32 + + /* Use Performance Timer if it's available, mmtimer if not. */ + + if ( perf_timer ) + { + __int64 t ; + + QueryPerformanceCounter ( (LARGE_INTEGER *) &t ) ; + + return res * (double) t ; + } + + return (double) timeGetTime() * 0.001 ; + +#else + timeval tv ; + + gettimeofday ( & tv, NULL ) ; + + return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0 ; +#endif +} + + +void ulClock::update () +{ + now = getRawTime() - start ; + + delta = now - last_time ; + + /* + KLUDGE: If the frame rate drops below ~5Hz, then + control will be very difficult. It's + actually easier to give up and slow + down the action. max_delta defaults to + 200ms for that reason. + + KLUDGE: If update is called very rapidly, then + delta can be zero which causes some + programs to div0. So we'll clamp to + a millionth of a second. + */ + + if ( delta > max_delta ) delta = max_delta ; + if ( delta <= 0.0 ) delta = 0.0000001 ; + + last_time = now ; +} + + + diff --git a/src/util/ulError.cxx b/src/util/ulError.cxx new file mode 100644 index 0000000..c30c737 --- /dev/null +++ b/src/util/ulError.cxx @@ -0,0 +1,90 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ulError.cxx 1967 2004-10-02 12:20:43Z wolfram_kuss $ +*/ + + +#include "ul.h" + +static char _ulErrorBuffer [ 1024 ] = { '\0' } ; +static ulErrorCallback _ulErrorCB = 0 ; + +static const char* _ulSeverityText [ UL_MAX_SEVERITY ] = +{ + "DEBUG", + "WARNING", + "FATAL", +}; + + +void ulSetError ( enum ulSeverity severity, const char *fmt, ... ) +{ + va_list argp; + va_start ( argp, fmt ) ; + vsprintf ( _ulErrorBuffer, fmt, argp ) ; + va_end ( argp ) ; + + if ( _ulErrorCB ) + { + (*_ulErrorCB)( severity, _ulErrorBuffer ) ; + } + else + { + fprintf ( stderr, "%s: %s\n", + _ulSeverityText[ severity ], _ulErrorBuffer ) ; + if ( severity == UL_FATAL ) + { +#ifdef WIN32 + // A Windows user that does not start the program from the command line + // will not see output to stderr + ::MessageBox(0, _ulErrorBuffer, "fatal error!:", 0); +#endif + exit (1) ; + } + } +} + + +char* ulGetError ( void ) +{ + return _ulErrorBuffer ; +} + + +void ulClearError ( void ) +{ + _ulErrorBuffer [0] = 0 ; +} + + +ulErrorCallback ulGetErrorCallback ( void ) +{ + return _ulErrorCB ; +} + + +void ulSetErrorCallback ( ulErrorCallback cb ) +{ + _ulErrorCB = cb ; +} + + + diff --git a/src/util/ulLinkedList.cxx b/src/util/ulLinkedList.cxx new file mode 100644 index 0000000..96c246b --- /dev/null +++ b/src/util/ulLinkedList.cxx @@ -0,0 +1,272 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ulLinkedList.cxx 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + + +#include "ulLocal.h" + +void ulLinkedList::unlinkNode ( ulListNode *prev, ulListNode *node ) +{ + /* Is this the first node ? */ + if ( prev == NULL ) + head = node -> getNext () ; + else + prev -> setNext ( node -> getNext () ) ; + + /* Is this the last node ? */ + if ( node -> getNext () == NULL ) + tail = prev ; +} + + +int ulLinkedList::getNodePosition ( void *data ) const +{ + ulListNode *curr = head ; + int pos = 0 ; + + while ( curr != NULL ) + { + if ( curr -> getData () == data ) + return pos ; + + pos++ ; + curr = curr -> getNext () ; + } + + return -1 ; +} + + +void ulLinkedList::appendNode ( void *data ) +{ + ulListNode *new_node = new ulListNode ( data, NULL ) ; + + if ( head == NULL ) + head = new_node ; + else + tail -> setNext ( new_node ) ; + + tail = new_node ; + + if ( ++nnodes > 1 ) + sorted = false ; +} + +void ulLinkedList::insertNode ( void *data, int pos ) +{ + if ( pos == 0 ) + { + head = new ulListNode ( data, head ) ; + + if ( tail == NULL ) + tail = head ; + } + else + { + if ( ! isValidPosition ( pos ) ) + return ; + else + { + ulListNode *prev = head ; + + while ( --pos > 0 ) + prev = prev -> getNext () ; + + prev -> setNext ( new ulListNode ( data, prev -> getNext () ) ) ; + } + } + + if ( ++nnodes > 1 ) + sorted = false ; +} + + +int ulLinkedList::insertSorted ( void *data, ulCompareFunc comparefn ) +{ + if ( comparefn != NULL ) + { + if ( sorted ) + { + int pos = 0 ; + + if ( head == NULL ) + head = tail = new ulListNode ( data, NULL ) ; + else + { + ulListNode *curr = head, *prev = NULL ; + + while ( (*comparefn)( curr -> getData (), data ) < 0 ) + { + prev = curr ; + curr = curr -> getNext () ; + + pos++ ; + + if ( curr == NULL ) + { + tail = new ulListNode ( data, curr ) ; + prev -> setNext ( tail ) ; + + nnodes++ ; + return pos ; + } + } + + if ( prev == NULL ) + head = new ulListNode ( data, head ) ; + else + prev -> setNext ( new ulListNode ( data, curr ) ) ; + } + + nnodes++ ; + return pos ; + } + else + ulSetError ( UL_WARNING, + "ulLinkedList::insertSorted: This is not a sorted list !" ) ; + } + + return -1 ; +} + + +void ulLinkedList::removeNode ( void *data ) +{ + ulListNode *curr = head, *prev = NULL ; + + while ( curr != NULL ) + { + if ( curr -> getData () == data ) + { + unlinkNode ( prev, curr ) ; + + delete curr ; + + if ( --nnodes <= 0 ) + sorted = true ; + + return ; + } + + prev = curr ; + curr = curr -> getNext () ; + } + + ulSetError ( UL_WARNING, "ulLinkedList::removeNode: No such node" ) ; +} + +void * ulLinkedList::removeNode ( int pos ) +{ + if ( ! isValidPosition ( pos ) ) + return NULL ; + + ulListNode *curr = head, *prev = NULL ; + + while ( pos-- > 0 ) + { + prev = curr ; + curr = curr -> getNext () ; + } + + unlinkNode ( prev, curr ) ; + + void *datap = curr -> getData () ; + + delete curr ; + + if ( --nnodes <= 1 ) + sorted = true ; + + return datap ; +} + + +void * ulLinkedList::getNodeData ( int pos ) const +{ + if ( ! isValidPosition ( pos ) ) + return NULL ; + + ulListNode *node ; + + if ( pos == nnodes - 1 ) + node = tail ; + else + { + node = head ; + + while ( pos-- > 0 ) + node = node -> getNext () ; + } + + return node -> getData () ; +} + + +void * ulLinkedList::forEach ( ulIterateFunc fn, void *user_data ) const +{ + if ( fn != NULL ) + { + ulListNode *curr ; + + for ( curr = head ; curr != NULL ; curr = curr -> getNext () ) + { + if ( (*fn)( curr -> getData (), user_data ) == false ) + return curr -> getData () ; + } + } + + return NULL ; +} + + +void ulLinkedList::empty ( ulIterateFunc destroyfn, void *user_data ) +{ + ulListNode *curr = head ; + + if ( destroyfn != NULL ) + { + while ( curr != NULL ) + { + ulListNode *next = curr -> getNext () ; + + (*destroyfn) ( curr -> getData (), user_data ) ; + + delete curr ; + curr = next ; + } + } + else + { + while ( curr != NULL ) + { + ulListNode *next = curr -> getNext () ; + + delete curr ; + curr = next ; + } + } + + head = tail = NULL ; + nnodes = 0 ; + sorted = true ; +} + diff --git a/src/util/ulList.cxx b/src/util/ulList.cxx new file mode 100644 index 0000000..c6b6abf --- /dev/null +++ b/src/util/ulList.cxx @@ -0,0 +1,109 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ulList.cxx 1732 2002-11-30 00:41:50Z sjbaker $ +*/ + + +#include "ul.h" + + +ulList::ulList ( int init ) +{ + total = 0 ; + next = 0 ; + entity_list = new void * [ limit = (init <= 0) ? 1 : init ] ; +} + + +ulList::~ulList (void) +{ + removeAllEntities () ; + delete [] entity_list ; +} + + +void ulList::addEntity ( void *entity ) +{ + sizeChk () ; + entity_list [ total++ ] = entity ; +} + + +void ulList::addEntityBefore ( int i, void *entity ) +{ + sizeChk () ; + memmove ( &entity_list[i+1], &entity_list[i], sizeof(void *) * (total-i) ) ; + entity_list [ i ] = entity ; + total++ ; +} + + +void ulList::sizeChk (void) +{ + /* Room for one more Entity? */ + + if ( total >= limit ) + { + limit += limit ; + void **nlist = new void * [ limit ] ; + memmove ( nlist, entity_list, sizeof(void *) * total ) ; + delete [] entity_list ; + entity_list = nlist ; + } +} + + +int ulList::searchForEntity ( void *entity ) const +{ + for ( unsigned int i = 0 ; i < total ; i++ ) + if ( entity_list [ i ] == entity ) + return (int) i ; + + return -1 ; +} + +void ulList::removeAllEntities () +{ + while ( total > 0 ) + removeEntity ( (unsigned int) 0 ) ; +} + +void ulList::removeEntity ( unsigned int n ) +{ + memmove ( &(entity_list[n]), &(entity_list[n+1]), + sizeof(void *) * (total-n-1) ) ; + total-- ; + + if ( next >= n ) + next-- ; +} + + + +void ulList::replaceEntity ( unsigned int n, void *new_entity ) +{ + if ( n >= 0 ) + entity_list [ n ] = new_entity; + else + addEntity ( new_entity ) ; +} + + diff --git a/src/util/ulLocal.h b/src/util/ulLocal.h new file mode 100644 index 0000000..e7e7cea --- /dev/null +++ b/src/util/ulLocal.h @@ -0,0 +1,52 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net + + $Id: ulLocal.h 1568 2002-09-02 06:05:49Z sjbaker $ +*/ + +#ifndef _UL_LOCAL_H_ +#define _UL_LOCAL_H_ 1 + +#include "ul.h" + +class ulListNode +{ +protected: + + ulListNode *next ; + void *data ; + +public: + + ulListNode ( void *dt, ulListNode *next_node ) + { + data = dt ; + next = next_node ; + } + + void * getData ( void ) const { return data ; } + void setData ( void *d ) { data = d ; } + + ulListNode * getNext ( void ) const { return next ; } + void setNext ( ulListNode *n ) { next = n ; } +} ; + +#endif + diff --git a/src/util/ulRTTI.cxx b/src/util/ulRTTI.cxx new file mode 100644 index 0000000..8d82626 --- /dev/null +++ b/src/util/ulRTTI.cxx @@ -0,0 +1,109 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net */ + + +#include "ulRTTI.h" + +/* Originally written by: Alexandru C. Telea */ + + +static const ulRTTITypeinfo *RTTI_base_null_type [] = { 0 } ; + +const ulRTTITypeinfo* ulRTTIdyntypeid::a[] = { 0 } ; + +const ulRTTITypeinfo ulRTTITypeinfo::null_type ( "NULL", RTTI_base_null_type, + 0, 0 ) ; + + +ulRTTITypeinfo::ulRTTITypeinfo ( const char *name, const ulRTTITypeinfo *bb[], + void* (*f1)(int,void*),void* (*f2)() ) +{ + /* Create default ulRTTITypeinfo */ + n = ulStrDup ( name ) ; + + b = bb ; /* ns = 0 ; subtypes = 0 ; */ + + cast = f1 ; /* Attach casting func */ + new_obj = f2 ; /* Attach creation func */ + + for ( int i = 0 ; b[i] ; i++ ) + /* Add this as subtype to all its basetypes */ + /* REMARK: Harmless const castaway */ + ((ulRTTITypeinfo**)b)[i]->add_subtype ( this ) ; +} + +ulRTTITypeinfo::~ulRTTITypeinfo () +{ + delete [] n ; + for ( int i = 0 ; b[i] ; i++ ) + /* Del this subtype from all its basetypes */ + /* REMARK: Harmless const castaway */ + ((ulRTTITypeinfo**)b)[i]->del_subtype ( this ) ; +} + +void ulRTTITypeinfo::add_subtype ( const ulRTTITypeinfo *t ) +/* + Adds t as last ulRTTITypeinfo in the 'subtypes' list. For this, the list is + realloc'd with one extra entry. +*/ +{ + const ulRTTITypeinfo **ptr = new const ulRTTITypeinfo*[ns+1] ; + int i ; for ( i = 0 ; i < ns ; i++ ) ptr[i] = subtypes[i] ; + ptr[i] = t ; + ns++ ; + delete[] subtypes ; + subtypes = ptr ; +} + +void ulRTTITypeinfo::del_subtype ( const ulRTTITypeinfo* t ) +/* Searches for t in the subtypes list of this and removes it, if found. */ +{ + int i ; for ( i = 0 ; i < ns && subtypes[i] != t ; i++ ) ; + if ( i < ns ) + for(; i < ns-1 ; i++ ) subtypes[i] = subtypes[i+1] ; +} + +void * ulRTTITypeinfo::create ( const ulRTTITypeinfo* bt, const char *c ) const +/* + Tries to create an obj of type-name given by char*. Searches for this type + in the type-DAG rooted by this, creates it and returns it as cast to 'bt', + where bt is either this or a direct base of this. +*/ +{ + void *p = NULL ; int i ; + + if ( !strcmp ( c, n ) ) /* Want to create an obj of this type ? */ + /* Yes, do it if this type is instantiable. */ + p = (new_obj) ? new_obj () : 0 ; + else /* No, try with subclasses... */ + for ( i = 0 ; i < ns && + !( ( p = subtypes[i]->create ( this, c ) ) ) ; i++ ) ; + /* Succeeded creating on ith subclass branch ? */ + if ( !p ) return 0 ; /* Couldn't create it in any way, abort. */ + if ( bt == this ) + i = -1 ; /* Must cast to this's own type (i==-1) */ + else + /* Search to which base of this we should cast */ + for ( i = 0 ; b[i] && b[i] != bt ; i++ ) ; + + /* Found: cast to ith base of this */ + return cast(i,p) ; /* Cast to ith base of to this, return as void* */ +} + diff --git a/src/util/ulRTTI.h b/src/util/ulRTTI.h new file mode 100644 index 0000000..e8c5216 --- /dev/null +++ b/src/util/ulRTTI.h @@ -0,0 +1,420 @@ +/* + PLIB - A Suite of Portable Game Libraries + Copyright (C) 1998,2002 Steve Baker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For further information visit http://plib.sourceforge.net */ + + +/* + Originally written by: Alexandru C. Telea +*/ + +/* + This file provides support for RTTI and generalized (virtual-base to derived + and separate hierarchy branches) casting. There is also support for RT obj + creation from type names. + + In order to enable these features for a class, two things should be done: + + 1) insert the text UL_TYPE_DATA (without ';') in the class-decl. + 2) in the .C file where the class's implementation resides, insert the + following (without';'): + + UL_RTTI_DEF(classname) + if the class has no bases with RTTI + + UL_RTTI_DEFn(classname,b1,...bn) + if the class has bases b1,...bn with RTTI + + Use UL_RTTI_DEF_INST instead of UL_RTTI_DEF if you want to enable RT + obj creation for classname. You should provide then a public default + ctor. + + RTTI is used via a class called ulRTTItypeid. A typeid describes a type of a + class. [..] They should provide all necessary support for any kind of + RTTI/casting [..]. + + [..] + + REMARK: There are two classes related to RTTI: ulRTTItypeid and + ======= ulRTTITypeinfo. A ulRTTItypeid is, as it says, an 'id for a + type'. It actually wraps a ulRTTITypeinfo*, where a + ulRTTITypeinfo contains the actual encoding of a class type. + You can freely create/copy/destroy/manipulate ulRTTItypeid's, + but you should NEVER deal directly with ulRTTITypeinfo. A + ulRTTITypeinfo should actually be created ONLY by the + UL_TYPE_DATA macros, as part of a class definition, since the + ulRTTITypeinfo encodes a type info for an EXISTING class [..]. + All type-related stuff should be therefore handled via + ulRTTItypeid's. +*/ + +#ifndef _UL_RTTI_H_ +#define _UL_RTTI_H_ + +#include +#include "ul.h" + + +class ulRTTITypeinfo +/* Implementation of type-related info */ +{ +private: + + char *n ; /* type name */ + + /* + base types (NULL-ended array of ulRTTITypeinfo's for this's direct bases) + */ + const ulRTTITypeinfo** b ; + + int ns ; /* #subtypes of this type */ + const ulRTTITypeinfo **subtypes ; /* types derived from this type */ + + /* convenience type info for a 'null' type */ + static const ulRTTITypeinfo null_type ; + + void* (*new_obj)() ; /* func to create a new obj of this type */ + void* (*cast)(int,void*) ; /* + func to cast an obj of this type to ith + baseclass of it or to itself + */ + + /* adds a subtype to this's subtypes[] */ + void add_subtype ( const ulRTTITypeinfo * ) ; + + /* dels a subtype from this's subtypes[] */ + void del_subtype ( const ulRTTITypeinfo* ) ; + + friend class ulRTTItypeid ; /* for null_type */ + +public: + + ulRTTITypeinfo ( const char* name, const ulRTTITypeinfo* bb[], + void* (*)(int,void*),void* (*)() ) ; + ~ulRTTITypeinfo () ; + + /* Returns name of this ulRTTITypeinfo */ + const char* getname () const { return n ; } + + /* Compares 2 ulRTTITypeinfo objs */ + bool same ( const ulRTTITypeinfo *p ) const + { + /* + First, try to see if it's the same 'physical' ulRTTITypeinfo (which + should be the case, since we create them per-class and not per-obj). + */ + return ( this == p ) || !strcmp ( n, p->n ) ; + } + + /* true if the arg can be cast to this, else false */ + bool can_cast ( const ulRTTITypeinfo *p ) const + { + return same ( p ) || p->has_base ( this ) ; + } + + /* true if this has the arg as some base, else false */ + bool has_base ( const ulRTTITypeinfo *p ) const + { + for ( int i = 0 ; b[i] != NULL ; i++ ) /* for all bases of this... */ + /* match found, return 1 or no match, search deeper */ + if ( p->same ( b[i] ) || b[i]->has_base ( p ) ) return true ; + return false ; /* no match at all, return false */ + } + + /* get i-th subclass of this, if any, else NULL */ + const ulRTTITypeinfo * subclass ( int i = 0 ) const + { + return ( i >= 0 && i < ns ) ? subtypes[i] : NULL ; + } + + int num_subclasses () const { return ns ; } /* get # subclasses of this */ + + /* + search for a subclass named char*, create obj of it and return it cast to + the ulRTTITypeinfo* type, which is either this or a direct base of this. + */ + void * create ( const ulRTTITypeinfo *, const char * ) const ; + + /* Returns true if this type has a default ctor, else false */ + bool can_create () const { return new_obj != NULL ; } +} ; + + +class ulRTTItypeid +/* Main class for RTTI interface */ +{ +protected: + + /* ulRTTItypeid implementation (the only data-member) */ + const ulRTTITypeinfo* id ; + +public: + + /* Not for application use ! */ + const ulRTTITypeinfo* get_info () const { return id ; } + + ulRTTItypeid ( const ulRTTITypeinfo* p ) : id ( p ) { } + ulRTTItypeid () : id ( &ulRTTITypeinfo::null_type ) { } + + /* Compares 2 ulRTTItypeid objs */ + bool isSame ( ulRTTItypeid i ) const { return id->same ( i.id ) ; } + + /* true if the arg can be cast to this, else false */ + bool canCast ( ulRTTItypeid i ) const { return id->can_cast ( i.id ) ; } + + const char * getName () const { return id->getname () ; } + + /* Return # subclasses of this */ + int getNumSubclasses () const { return id->num_subclasses () ; } + + /* Return ith subclass of this */ + ulRTTItypeid getSubclass ( int i ) const { return id->subclass ( i ) ; } + + /* Return # baseclasses of this */ + int getNumBaseclasses () const + { + int i ; for ( i = 0 ; id->b[i] != NULL ; i++ ) ; + return i ; + } + + /* Return ith baseclass of this */ + ulRTTItypeid getBaseclass ( int i ) const { return id->b[i] ; } + + /* + Tries to create an instance of a subclass of this having of type given + by the ulRTTItypeid arg. If ok, it returns it casted to the class-type of + this and then to void* + */ + void * create ( ulRTTItypeid t ) const + { + return id->create ( id, t.getName () ) ; + } + + /* Returns true if this type is instantiable, else false */ + bool canCreate () const { return id->can_create () ; } +} ; + + +class ulRTTIdyntypeid : public ulRTTItypeid +/* + Class for dynamic type creation from user strings. Useful for creating + typeids at RT for comparison purposes. +*/ +{ +private: + + static const ulRTTITypeinfo *a[] ; + +public: + + ulRTTIdyntypeid ( const char *c ) : + /* create a dummy ulRTTITypeinfo */ + ulRTTItypeid ( new ulRTTITypeinfo ( c, a, NULL, NULL ) ) { } + + ~ulRTTIdyntypeid () { delete id ; /* delete the dummy ulRTTITypeinfo */ } +} ; + + + +/* + Macros +*/ + +/* + 'ulRTTItypeid' + UL_STATIC_TYPE_INFO(T) T=RTTI-class name. + Returns a ulRTTItypeid with T's type. If T + hasn't RTTI, a compile-time error occurs. +*/ + +#define UL_STATIC_TYPE_INFO(T) T::RTTI_sinfo() + + +/* + 'T*' + UL_PTR_CAST(T,p) T=RTTI-class, p=RTTI-class ptr. + Returns p cast to the type T as a T*, if cast is + possible, else returns NULL. If *p or T have no RTTI, + a compile-time error occurs. Note that p can point to + virtual base classes. Casting between separat branches + of a class hierarchy is also supported, as long as all + classes have RTTI. Therefore UL_PTR_CAST is a fully + general and safe operator. If p==NULL, the operator + returns NULL. +*/ + +#define UL_PTR_CAST(T,p) ((p != NULL)? (T*)((p)->RTTI_cast(UL_STATIC_TYPE_INFO(T))) : NULL) + + +/* 'T*' + UL_TYPE_NEW(T,t) T=RTTI-class, t=ulRTTItypeid + Returns a new object of type t cast to the type T as + a T*. t must represent a type identical to or derived + from T. If t is not a type derived from T or not an + instantiable type having a default constructor, NULL is + returned. */ + +#define UL_TYPE_NEW(T,t) ((T*)t.create(T)) + + + +/* + Definition of TYPE_DATA for a RTTI-class: introduces one static + ulRTTITypeinfo data-member and a couple of virtuals. +*/ + +#define UL_TYPE_DATA \ + protected: \ + static const ulRTTITypeinfo RTTI_obj; \ + static void* RTTI_scast(int,void*); \ + static void* RTTI_new(); \ + virtual ulRTTItypeid RTTI_vinfo() const { return &RTTI_obj; }\ + public: \ + static ulRTTItypeid RTTI_sinfo() { return &RTTI_obj; }\ + virtual void* RTTI_cast(ulRTTItypeid); + + + +/* + Definition of auxiliary data-structs supporting RTTI for a class: defines + the static ulRTTITypeinfo object of that class and its associated virtuals. +*/ + +/* Auxiliary definition of the construction method: */ +#define UL_RTTI_NEW(cls) void* cls::RTTI_new() { return new cls; } \ + const ulRTTITypeinfo cls::RTTI_obj(#cls,RTTI_base_ ## cls,cls::RTTI_scast,cls::RTTI_new); + +#define UL_RTTI_NO_NEW(cls) const ulRTTITypeinfo cls::RTTI_obj(#cls,RTTI_base_ ## cls,cls::RTTI_scast,NULL); + + + +/* + Top-level macros: +*/ + +#define UL_RTTI_DEF_BASE(cls) \ + static const ulRTTITypeinfo* RTTI_base_ ## cls [] = { NULL }; \ + void* cls::RTTI_cast(ulRTTItypeid t) \ + { \ + if (t.isSame(&RTTI_obj)) return this; \ + return NULL; \ + } \ + void* cls::RTTI_scast(int i,void* p) \ + { cls* ptr = (cls*)p; return ptr; } + + +#define UL_RTTI_DEF1_BASE(cls,b1) \ + static const ulRTTITypeinfo* RTTI_base_ ## cls [] = \ + { UL_STATIC_TYPE_INFO(b1).get_info(), NULL }; \ + void* cls::RTTI_cast(ulRTTItypeid t) \ + { \ + if (t.isSame(&RTTI_obj)) return this; \ + void* ptr; \ + if ((ptr=b1::RTTI_cast(t))) return ptr; \ + return NULL; \ + } \ + void* cls::RTTI_scast(int i,void* p) \ + { cls* ptr = (cls*)p; \ + switch(i) \ + { case 0: return (b1*)ptr; } \ + return ptr; \ + } + + +#define UL_RTTI_DEF2_BASE(cls,b1,b2) \ + static const ulRTTITypeinfo* RTTI_base_ ## cls [] = \ + { UL_STATIC_TYPE_INFO(b1).get_info(), \ + UL_STATIC_TYPE_INFO(b2).get_info(), NULL }; \ + void* cls::RTTI_cast(ulRTTItypeid t) \ + { \ + if (t.isSame(&RTTI_obj)) return this; \ + void* ptr; \ + if ((ptr=b1::RTTI_cast(t))) return ptr; \ + if ((ptr=b2::RTTI_cast(t))) return ptr; \ + return NULL; \ + } \ + void* cls::RTTI_scast(int i,void* p) \ + { cls* ptr = (cls*)p; \ + switch(i) \ + { case 0: return (b1*)ptr; \ + case 1: return (b2*)ptr; \ + } \ + return ptr; \ + } + +#define UL_RTTI_DEF3_BASE(cls,b1,b2,b3) \ + static const ulRTTITypeinfo* RTTI_base_ ## cls [] = \ + { UL_STATIC_TYPE_INFO(b1).get_info(), \ + UL_STATIC_TYPE_INFO(b2).get_info(), \ + UL_STATIC_TYPE_INFO(b3).get_info(), NULL }; \ + void* cls::RTTI_cast(ulRTTItypeid t) \ + { \ + if (t.isSame(&RTTI_obj)) return this; \ + void* ptr; \ + if ((ptr=b1::RTTI_cast(t))) return ptr; \ + if ((ptr=b2::RTTI_cast(t))) return ptr; \ + if ((ptr=b3::RTTI_cast(t))) return ptr; \ + return NULL; \ + } \ + void* cls::RTTI_scast(int i,void* p) \ + { cls* ptr = (cls*)p; \ + switch(i) \ + { case 0: return (b1*)ptr; \ + case 1: return (b2*)ptr; \ + case 2: return (b3*)ptr; \ + } \ + return ptr; \ + } + + + +#define UL_RTTI_DEF_INST(cls) \ + UL_RTTI_DEF_BASE(cls) \ + UL_RTTI_NEW(cls) + +#define UL_RTTI_DEF(cls) \ + UL_RTTI_DEF_BASE(cls) \ + UL_RTTI_NO_NEW(cls) + +#define UL_RTTI_DEF1_INST(cls,b1) \ + UL_RTTI_DEF1_BASE(cls,b1) \ + UL_RTTI_NEW(cls) + +#define UL_RTTI_DEF1(cls,b1) \ + UL_RTTI_DEF1_BASE(cls,b1) \ + UL_RTTI_NO_NEW(cls) + +#define UL_RTTI_DEF2_INST(cls,b1,b2) \ + UL_RTTI_DEF2_BASE(cls,b1,b2) \ + UL_RTTI_NEW(cls) + +#define UL_RTTI_DEF2(cls,b1,b2) \ + UL_RTTI_DEF2_BASE(cls,b1,b2) \ + UL_RTTI_NO_NEW(cls) + +#define UL_RTTI_DEF3_INST(cls,b1,b2,b3) \ + UL_RTTI_DEF3_BASE(cls,b1,b2,b3) \ + UL_RTTI_NEW(cls) + +#define UL_RTTI_DEF3(cls,b1,b2,b3) \ + UL_RTTI_DEF3_BASE(cls,b1,b2,b3) \ + UL_RTTI_NO_NEW(cls) + + +#endif + diff --git a/tools/AUTHORS b/tools/AUTHORS new file mode 100644 index 0000000..72ce79c --- /dev/null +++ b/tools/AUTHORS @@ -0,0 +1,62 @@ +PLIB was originally written by Steve Baker as a solo project - but +has subsequently been greatly enhanced and expanded by a 'cast of +thousands'. + +Most important of all - the 'official' PLIB developers: + + Alex Perry + Curtis Olson + Ben Woodhead + Dave McClurg + Gerard Decatrel + Gil Carter + Giancarlo Niccolai + James Jones + John Fay ("Mr. PUI") + Juergen Marquardt + Mark Vallevand + Marten Stromberg + Nathan Matias + Norman Vine + Per Liedman + Sam Stickland + Sebastian Ude + Steve Baker <--- Hmmm - must sort this list by SECOND name! + Will Lachance + Wolfram Kuss + +Apologies to anyone I've left out - please let me know +who you are and I'll add you in. + + Christopher St.John + Christian Mayer + Darrell Walisser + Dave Heil + Erik Hofman + Kevin Thompson + Karl Kremer + Negative0 <---- Who? Some kind of 1's complement arithmetic fanatic? + Mark Danks + Michael Kurth + Sean Palmer + Simon Britnell + Themie Gouthas + Tony Knienieder + Trent Gamblin + +Special mention must go to: + + Daryll Strauss (GLIDE port to Linux) + David Bucciarelli (Mesa -> GLIDE interface) + Brian Paul (Mesa) + Curtis Olson (FlightGear guru and all-round "Mr Nice Guy", + who nagged me into writing most of this stuff!) + Vasily Lewis (Tireless maintainer and sysadmin at Woodsoup + where PLIB was first hosted) + Toru Egashira (Who wrote a program called 'NSPmod' which was + the original basis of the SL 'MOD' player - + although the original code has been almost + entirely rewritten in the process of merging + it with SL. + Everyone at OPENGL-GAMEDEV-L and 3Dfx.glide.linux + diff --git a/tools/COPYING b/tools/COPYING new file mode 100644 index 0000000..eeb586b --- /dev/null +++ b/tools/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/tools/ChangeLog b/tools/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/tools/INSTALL b/tools/INSTALL new file mode 100644 index 0000000..b42a17a --- /dev/null +++ b/tools/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/tools/Makefile.am b/tools/Makefile.am new file mode 100644 index 0000000..5010b14 --- /dev/null +++ b/tools/Makefile.am @@ -0,0 +1,8 @@ +SUBDIRS = src + +EXTRA_DIST = autogen.sh README tools.dsw + +dist-hook: + tar cf - doc \ + | ( cd $(distdir) ; tar xf - ) + diff --git a/tools/NEWS b/tools/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/tools/README b/tools/README new file mode 100644 index 0000000..e69de29 diff --git a/tools/autogen.sh b/tools/autogen.sh new file mode 100755 index 0000000..02a1eb9 --- /dev/null +++ b/tools/autogen.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +OSTYPE=`uname -s` + +AMFLAGS="--add-missing" +if test "$OSTYPE" = "IRIX" -o "$OSTYPE" = "IRIX64"; then + AMFLAGS=$AMFLAGS" --include-deps"; +fi + +echo "Running aclocal" +aclocal +echo "Running automake" +automake $AMFLAGS +echo "Running autoconf" +autoconf + +echo "======================================" +echo "Now you are ready to run './configure'" +echo "======================================" diff --git a/tools/configure.in b/tools/configure.in new file mode 100644 index 0000000..1efd2a4 --- /dev/null +++ b/tools/configure.in @@ -0,0 +1,161 @@ +dnl Process this file with autoconf to produce a configure script. + +AC_INIT(src/af2rgb/af2rgb.cxx) +AM_INIT_AUTOMAKE(plib_tools, 1.7.0) + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_CPP +AC_PROG_CXX +AC_PROG_CXXCPP +AC_PROG_INSTALL + +AC_LANG_CPLUSPLUS + + +dnl Command line arguments. + +dnl Don't use AC_HELP_STRING here as old versions of autoconf do not +dnl understand it. +AC_ARG_WITH(GL, +[ --with-GL=DIR set the prefix directory where GL resides], +GL_PREFIX=$withval, GL_PREFIX=auto) + +if test "x$GL_PREFIX" != "xauto"; then + LDFLAGS="$LDFLAGS -L$GL_PREFIX/lib" + CPPFLAGS="$CPPFLAGS -I$GL_PREFIX/include" +fi + + +CPPFLAGS="$CPPFLAGS -I/usr/local/include" +LDFLAGS="$LDFLAGS -L/usr/local/lib" + +dnl Checks for library functions. +dnl check for OpenGL related libraries + +AC_CANONICAL_HOST + +case "${host}" in +*-*-cygwin* | *-*-mingw32*) + dnl CygWin under Windoze. + + LIBS="$LIBS -lwinmm -lglut32 -lglu32 -lopengl32" + ;; +*-apple-darwin*) + dnl Mac OS X + + LIBS="$LIBS -framework GLUT -lobjc -framework OpenGL -framework Carbon" + ;; +*) + dnl Check for X11 + + AC_PATH_XTRA + + LDFLAGS="$LDFLAGS $X_LIBS" + + LIBS="$LIBS $X_PRE_LIBS -lXi -lXmu -lXext -lX11 $X_EXTRA_LIBS -lm" + + dnl Reasonable stuff non-windoze variants ... :-) + + AC_CHECK_LIB(pthread, pthread_create) + + AC_CHECK_LIB(GL, glNewList) + if test "x$ac_cv_lib_GL_glNewList" = "xno" ; then + dnl if no GL, check for MesaGL + AC_CHECK_LIB(MesaGL, glNewList,, + AC_MSG_ERROR([could not find working GL library])) + fi + + AC_CHECK_LIB(GLU, gluLookAt) + if test "x$ac_cv_lib_GLU_gluLookAt" = "xno" ; then + dnl if no GLU, check for MesaGLU + AC_CHECK_LIB(MesaGLU, gluLookAt,, + AC_MSG_ERROR([could not find working GLU library])) + fi + + dnl check for glut...or freeglut + AC_CHECK_LIB(freeglut, glutGetModifiers) + if test "x$ac_cv_lib_freeglut_glutGetModifiers" = "xno" ; then + dnl if no freeglut, check for Real GLUT + AC_CHECK_LIB(glut, glutGetModifiers,, + AC_MSG_ERROR([could not find working GLUT library])) + fi + + AC_CHECK_LIB(dl, dlclose) + + dnl Check SGI audio library + AC_CHECK_LIB(audio, ALopenport, SND_LIBS="-laudio") + ;; +esac + +dnl Check PLIB library +AC_CHECK_LIB(plibul, ulInit, true, +AC_MSG_ERROR([there seems to be a problem with the PLIB libraries])) + + +dnl Checks for header files. + +AC_HEADER_STDC +AC_CHECK_HEADER(windows.h, AC_DEFINE(WIN32)) + +case "${host}" in +*-*-cygwin* | *-*-mingw32*) + dnl CygWin under Windoze. + + AC_CHECK_HEADERS(GL/gl.h GL/glu.h,, + AC_MSG_ERROR([OpenGL header files not found])) + + AC_CHECK_HEADER(GL/glut.h, AC_DEFINE(GLUT_IS_PRESENT), + AC_MSG_ERROR([GLUT header file not found])) + ;; +*-apple-darwin*) + dnl Mac OS X + + AC_CHECK_HEADERS(OpenGL/gl.h OpenGL/glu.h,, + AC_MSG_ERROR([OpenGL header files not found])) + + AC_CHECK_HEADER(GLUT/glut.h, AC_DEFINE(GLUT_IS_PRESENT), + AC_MSG_ERROR([GLUT header file not found])) + ;; +*) + AC_CHECK_HEADERS(GL/gl.h GL/glu.h,, + AC_MSG_ERROR([OpenGL header files not found])) + + if test "x$ac_cv_lib_freeglut_glutGetModifiers" = "xyes"; then + AC_CHECK_HEADER(GL/freeglut.h, AC_DEFINE(FREEGLUT_IS_PRESENT), + AC_MSG_ERROR([freeglut header file not found])) + else + AC_CHECK_HEADER(GL/glut.h, AC_DEFINE(GLUT_IS_PRESENT), + AC_MSG_ERROR([GLUT header file not found])) + fi + ;; +esac + +AC_CHECK_HEADER(plib/ul.h,, AC_MSG_ERROR([PLIB header files not found])) + + +dnl Warning flags +WFLAG="-Wall" +case "$host" in +mips-sgi-irix*) + if test "x$CXX" = "xCC"; then + WFLAG="-fullwarn"; + fi + ;; +*) + if test "x$CXX" = "xicpc" || test "x$CXX" = "xicc"; then + WFLAG="-w1" + fi + ;; +esac + +CFLAGS="$CFLAGS $WFLAG" +CXXFLAGS="$CXXFLAGS $WFLAG" + + +AC_OUTPUT( \ + Makefile \ + src/Makefile \ + src/af2rgb/Makefile \ + ) + diff --git a/tools/doc/index.html b/tools/doc/index.html new file mode 100644 index 0000000..15323d2 --- /dev/null +++ b/tools/doc/index.html @@ -0,0 +1,65 @@ + + + + + PLIB Tools Home Page + + + + + + + + + +
+PLIB Logo +
+
+
+

+ STEVE'S + PORTABLE + GAME + TOOLS + PAGE. +

+
+
+
    +When the only tool you have is a hammer
    +every problem starts to look like a nail. +
+
+ +Sourceforge Logo +
+
+ +

Useful Utility Tools for PLIB Applications.

+This is a suite of tools that will hopefully prove useful for the +developers or users of PLIB-based applications. Currently, there is only one tool: +

The "af2rgb" texture converter.

+This portable utility converts textures, that is 2D bitmaps. It converts *.?af files as used with (old) Micro$oft +Flightsimulator into .rgb files that are understood by all plib versions. New plib versions can handle +*.?af textures, so this tool is only needed if you want to use the textures +with an old (for example 1.2.0) version of plib. +

+The usage is very simple:
+Go into the path of the textures you want to convert and call af2rgb. +The program will handle all *.?af files in that path (and ignore all other files). +As a parameter, give it the path where the new textures shall be placed. +If you don't give it a path, then they will be written into the current dir. +The new filename is always lowercase, so that the case is defined for the Un*x crowd. +The first letter of the extension is added to the filename, so that it is unique. +For example, lets say you have navion.1af and Navion.2af in your path. Af2rgb will create files +called navion1.rgb and navion2.rgb. + +
+
+ +Steve J. Baker. +<sjbaker1@airmail.net> +
+ + diff --git a/tools/src/Makefile.am b/tools/src/Makefile.am new file mode 100644 index 0000000..639093c --- /dev/null +++ b/tools/src/Makefile.am @@ -0,0 +1,10 @@ + +SUBDIRS = af2rgb + +bin_PROGRAMS = plibconvert + +plibconvert_SOURCES = plibconvert.cxx + +plibconvert_LDADD = -lplibssg -lplibsg -lplibul + + diff --git a/tools/src/af2rgb/Makefile.am b/tools/src/af2rgb/Makefile.am new file mode 100644 index 0000000..92dbb79 --- /dev/null +++ b/tools/src/af2rgb/Makefile.am @@ -0,0 +1,8 @@ +noinst_PROGRAMS = af2rgb + +af2rgb_SOURCES = af2rgb.cxx + +af2rgb_LDADD = -lplibssg -lplibsg -lplibul + +EXTRA_DIST = af2rgb.dsp + diff --git a/tools/src/af2rgb/af2rgb.cxx b/tools/src/af2rgb/af2rgb.cxx new file mode 100644 index 0000000..946c666 --- /dev/null +++ b/tools/src/af2rgb/af2rgb.cxx @@ -0,0 +1,206 @@ +// Convert textures made for MSFS to rgb textures. + + +// Written by Wolfram Kuss (w_kus@rz-online.de) in dec 2000 / jan 2001 +// with some help by Marten Strömberg. +// +// Published as part of Steve Baker's PLIB +// License is GPL + +#include +#include +#include +#include + + +// *.?af textures are always 256 x 256: +#define XSIZE 256 +#define YSIZE 256 +#define ZSIZE 4 + +static unsigned char texelsR [ XSIZE * YSIZE ]; +static unsigned char texelsG [ XSIZE * YSIZE ]; +static unsigned char texelsB [ XSIZE * YSIZE ]; +static unsigned char texelsA [ XSIZE * YSIZE ]; + +static FILE *fd; + +static size_t writeByte (unsigned char x ) +{ + return fwrite ( & x, sizeof(unsigned char), 1, fd ) ; +} + +static size_t writeShort (unsigned short x ) +{ + + if (ulIsLittleEndian) // this is the other way round compared to normally. + // obviously, this is because the .rgb format comes from SGI. + ulEndianSwap(&x); + + + return fwrite( & x, sizeof(unsigned short), 1, fd ) ; +} + +static size_t writeInt (unsigned int x) +{ + if (ulIsLittleEndian) // this is the other way round compared to normally. + // obviously, this is because the .rgb format comes from SGI. + ulEndianSwap(&x); + + return fwrite( & x, sizeof(unsigned int), 1, fd ) ; +} + + + + +#define SGI_IMG_MAGIC 0x01DA + +static int writeTexelsIntoSGI ( const char *fname ) +{ + + fd = fopen ( fname, "wb" ) ; + size_t NoWritten = 0; + + if ( fd == NULL ) + { + ulSetError(UL_WARNING, "ssgLoadTexture: Failed to open '%s' for writing.", fname ) ; + return false; + } + + // ******* write the header ***************** + + NoWritten += writeShort (SGI_IMG_MAGIC) ; + + NoWritten += writeByte (0) ; // don't use RLE + NoWritten += writeByte (1) ; // bpp + NoWritten += writeShort (3) ; // dimension + + NoWritten += writeShort ( XSIZE ) ; + NoWritten += writeShort ( YSIZE ) ; + NoWritten += writeShort ( ZSIZE ) ; + NoWritten += writeInt ( 0 ) ; + NoWritten += writeInt ( 255 ) ; + NoWritten += writeInt ( 0 ) ; /* Dummy field */ + + int i ; + + for ( i = 0 ; i < 80 ; i++ ) + NoWritten += writeByte ( 0 ) ; /* Name field */ + + NoWritten += writeInt ( 0 ) ; // colormap + + for ( i = 0 ; i < 404 ; i++ ) + NoWritten += writeByte ( 0 ) ; /* Dummy field */ + + // ************ write the body **************** + + NoWritten += fwrite ( texelsR, XSIZE, YSIZE, fd ) ; + NoWritten += fwrite ( texelsG, XSIZE, YSIZE, fd ) ; + NoWritten += fwrite ( texelsB, XSIZE, YSIZE, fd ) ; + NoWritten += fwrite ( texelsA, XSIZE, YSIZE, fd ) ; + + if(NoWritten!=91+404+4*YSIZE) + { ulSetError(UL_WARNING, "Only %ld records written instead of %d. Proceed at your own risc\n", + (long)NoWritten, 91+404+4*YSIZE); + + return false; + } + fclose ( fd ) ; + return true; +} + + + +int loadMDLIntoTexels ( const char *fname ) +// returns TRUE on success +{ + FILE *tfile; + if ( (tfile = fopen(fname, "rb")) == NULL) { + ulSetError(UL_WARNING, "ssgLoadTexture: Failed to load '%s'.", fname ); + return false; + } + + fseek(tfile, 0, SEEK_END); + unsigned long file_length = ftell(tfile); + + if (file_length != 65536) { + ulSetError(UL_WARNING, "ssgLoadTexture: Wrong size of '%s'.", fname ); + return false; + } else { + fseek(tfile, 0, SEEK_SET); + + int c = 0; + for (int y = 0; y < 256; y++) { + for (int x = 0; x < 256; x++) { + unsigned char b; + if ( fread(&b, 1, 1, tfile) != 1) + return false; + texelsR[c] = ssgFsTexPalette[b*4 ]; + texelsG[c] = ssgFsTexPalette[b*4 + 1]; + texelsB[c] = ssgFsTexPalette[b*4 + 2]; + texelsA[c] = ssgFsTexPalette[b*4 + 3]; + c++; + } + } + fclose(tfile); + } + return true; +} + +void DoAllFiles( char *sDirectoryP ) +{ char newname [ 1024 ], sDirectory[1024], sFullPath[1024]; // todo fixme + + strcpy( sDirectory, sDirectoryP); + if ( ( sDirectoryP[ strlen(sDirectoryP)-1 ] != '\\') && + ( sDirectoryP[ strlen(sDirectoryP)-1 ] != '/') ) + strcat( sDirectory, "/"); +// ************** For all *.?af files in the current dir ************ + ulDir* dirp = ulOpenDir("."); + if ( dirp != NULL ) + { + ulDirEnt* dp; + while ( (dp = ulReadDir(dirp)) != NULL ) + { + if ( !dp->d_isdir ) + { size_t len = strlen(dp->d_name ); + if ( len >4 ) + if ((dp->d_name[len-1] == 'f') || (dp->d_name[len-1] == 'F')) + if ((dp->d_name[len-2] == 'a') || (dp->d_name[len-2] == 'A')) + if ((dp->d_name[len-4] == '.') || (dp->d_name[len-4] == '.')) + { strcpy( newname, dp->d_name ); + unsigned int i; + for (i=0; id_name, newname); + // ********** convert it ************** + if ( loadMDLIntoTexels ( dp->d_name )) + { strcpy(sFullPath, sDirectory); + strcat(sFullPath, newname); + writeTexelsIntoSGI ( sFullPath ); //lint !e534 + } + } + } + } + ulCloseDir(dirp); + } +} + +// converts all *.?af files from the current dir to *.rgb in the dir givven in the argument +int main(int argc, char* argv[]) +{ + if ( argc > 2 ) + ulSetError(UL_WARNING, "All arguments after the first are ignored!" ); + if ( argc >= 2 ) + DoAllFiles( argv[1] ); + else + DoAllFiles("."); + return 0; +} + diff --git a/tools/src/af2rgb/af2rgb.dsp b/tools/src/af2rgb/af2rgb.dsp new file mode 100644 index 0000000..6e219ca --- /dev/null +++ b/tools/src/af2rgb/af2rgb.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="af2rgb" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=af2rgb - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "af2rgb.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "af2rgb.mak" CFG="af2rgb - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "af2rgb - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "af2rgb - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "af2rgb - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sg.lib ssg.lib ul.lib opengl32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\\" + +!ELSEIF "$(CFG)" == "af2rgb - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sg_d.lib ssg_d.lib ul_d.lib opengl32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\\" + +!ENDIF + +# Begin Target + +# Name "af2rgb - Win32 Release" +# Name "af2rgb - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\af2rgb.cxx +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/tools/src/afm2txf/README b/tools/src/afm2txf/README new file mode 100644 index 0000000..66be37e --- /dev/null +++ b/tools/src/afm2txf/README @@ -0,0 +1,18 @@ +It's definitely a tool of the "duct tape and fishing line" variety. :) +It expects to find a ghostscript interpreter and ImageMagick's "mogrify" +program on the command line, takes a .afm font metrics file as its sole +argument, and expects that the font therein is accessible to ghostscript. +Basically, it should work out of the box on most linux distributions, +and nowhere else without a lot of work. + +If you have a TrueType font that you want to generate: + + export GS_FONTPATH= + ttf2afm yourfont.ttf > whatever.afm + font.pl whatever.afm + +Wait for a while (at 16x downsampling, this takes 1-2 minutes on my +Athlon 1800+), and the .txf file will appear in the current directory. +It will have the Postscript language name of the font. + +Andy diff --git a/tools/src/afm2txf/afm2txf.pl b/tools/src/afm2txf/afm2txf.pl new file mode 100755 index 0000000..baf1a51 --- /dev/null +++ b/tools/src/afm2txf/afm2txf.pl @@ -0,0 +1,283 @@ +#!/usr/bin/perl -w + +# afm2txf.pl 0.2 +# +# Generates .txf font textures from Type 1 fonts +# Requirements: Ghostscript, ImageMagick +# +# Usage: +# afm2txf.pl whatever.afm +# +# Changelog: +# 0.2 (06/28/2002): Generate fonts with proper padding +# 0.1 (06/28/2002): Initial version +# +# Copyright (C) 2002 Andrew James Ross +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. + +use strict; + +my $METRICS = shift or die; # AFM file + +# Texture size +my $TEXSIZ = 256; + +# Padding around each character, for mipmap separation +my $PADDING = 4; + +# Antialiasing multiplier. Should be 16 for production work. As low +# as 4 works well for testing. +my $DOWNSAMPLE = 16; + +# The 94 printable ASCII characters (and the space) and their +# postscript glyph names. We use names because not all postscript +# fonts are encoded using ASCII. AFM metrics generated by ttf2afm, in +# fact, don't have any numerical character IDs at all. In principle, +# this mechanism will work for any 8 bit font encoding, you just have +# to do the legwork of figuring out the name to ID mapping. +my %CHARS = ('space'=>32, 'exclam'=>33, 'quotedbl'=>34, + 'numbersign'=>35, 'dollar'=>36, 'percent'=>37, + 'ampersand'=>38, 'quotesingle'=>39, 'parenleft'=>40, + 'parenright'=>41, 'asterisk'=>42, 'plus'=>43, + 'comma'=>44, 'hyphen'=>45, 'period'=>46, 'slash'=>47, + 'zero'=>48, 'one'=>49, 'two'=>50, 'three'=>51, + 'four'=>52, 'five'=>53, 'six'=>54, 'seven'=>55, + 'eight'=>56, 'nine'=>57, 'colon'=>58, 'semicolon'=>59, + 'less'=>60, 'equal'=>61, 'greater'=>62, 'question'=>63, + 'at'=>64, 'A'=>65, 'B'=>66, 'C'=>67, 'D'=>68, 'E'=>69, + 'F'=>70, 'G'=>71, 'H'=>72, 'I'=>73, 'J'=>74, 'K'=>75, + 'L'=>76, 'M'=>77, 'N'=>78, 'O'=>79, 'P'=>80, 'Q'=>81, + 'R'=>82, 'S'=>83, 'T'=>84, 'U'=>85, 'V'=>86, 'W'=>87, + 'X'=>88, 'Y'=>89, 'Z'=>90, 'bracketleft'=>91, + 'backslash'=>92, 'bracketright'=>93, 'asciicircum'=>94, + 'underscore'=>95, 'grave'=>96, 'a'=>97, 'b'=>98, 'c'=>99, + 'd'=>100, 'e'=>101, 'f'=>102, 'g'=>103, 'h'=>104, + 'i'=>105, 'j'=>106, 'k'=>107, 'l'=>108, 'm'=>109, + 'n'=>110, 'o'=>111, 'p'=>112, 'q'=>113, 'r'=>114, + 's'=>115, 't'=>116, 'u'=>117, 'v'=>118, 'w'=>119, + 'x'=>120, 'y'=>121, 'z'=>122, 'braceleft'=>123, + 'bar'=>124, 'braceright'=>125, 'asciitilde'=>126); + +my %metrics = (); +my %positions = (); + +# +# Parse the font metrics. This is a 5 element array. All numbers are +# expressed as a fraction of the line spacing. +# 0: nominal width (distance to the next character) +# 1, 2: Coordinates of the lower left corner of the bounding box, +# relative to the nominal position. +# 3, 4: Size of the bounding box +# +print STDERR "Reading font metrics...\n"; +my $FONT; +my @lines = `cat $METRICS` + or die "Couldn't read metrics"; +foreach my $m (grep {/^(C|FontName) /} @lines) { + chomp $m; + if($m =~ /^FontName ([^\s]*)/) { $FONT = $1; next; } + + die "No name: $m" if $m !~ /N\s+([^\s]+)\s+;/; + my $name = $1; + + die "No box: $m" + if $m !~ /B\s+([-0-9]+)\s+([-0-9]+)\s+([-0-9]+)\s+([-0-9]+)\s+;/; + my ($left, $bottom, $right, $top) = ($1/1000, $2/1000, $3/1000, $4/1000); + + die "No width: $m" if $m !~ /WX\s+([-0-9]+)/; + my $nomwid = $1/1000; # nominal, not physical width! + + # The coordinates of the corner relative to the character + # "position" + my ($x, $y) = (-$left, -$bottom); + my ($w, $h) = ($right-$left, $top-$bottom); + + $metrics{$name} = [$nomwid, $x, $y, $w, $h]; +} + +die "No FontName found in metrics" if not defined $FONT; + +# +# Find the height of the tallest character, and print some warnings +# +my $maxhgt = 0; +foreach my $c (keys %CHARS) { + if(!defined $metrics{$c}) { + print STDERR "% WARNING: no metrics for char $c. Skipping.\n"; + next; + } + if($metrics{$c}->[4] > $maxhgt) { $maxhgt = $metrics{$c}->[4]; } +} +if($maxhgt == 0) { + print STDERR "No usable characters found. Bailing out.\n"; + exit 1; +} + +# +# Do the layout. Keep increasing the row count until the characters +# just fit. This isn't terribly elegant, but it's simple. +# +print STDERR "Laying out"; +my $rows = 1; +my $PS; +my $LINEHGT; +while(!defined ($PS = genPostscript($rows))) { $rows++; } +print STDERR " ($rows rows)\n"; + +# +# Call ghostscript to render +# +print STDERR "Rendering Postscript...\n"; +my $res = $TEXSIZ * $DOWNSAMPLE; +my $pid = open PS, "|gs -r$res -g${res}x${res} -sDEVICE=ppm -sOutputFile=$FONT.ppm > /dev/null"; +die "Couldn't spawn ghostscript interpreter" if !defined $pid; +print PS join("\n", @$PS), "\n"; +close PS; +waitpid($pid, 0); + +# +# Downsample with ImageMagick +# +print STDERR "Antialiasing image...\n"; +system("mogrify -geometry ${TEXSIZ}x${TEXSIZ} $FONT.ppm") == 0 + or die "Couldn't rescale $FONT.ppm"; + +# +# Generate the .txf file +# +print STDERR "Generating textured font file...\n"; + +# Prune undefined glyphs +foreach my $c (keys %metrics) { + delete $metrics{$c} if !defined $CHARS{$c}; +} + +sub round { sprintf "%.0f", $_[0] } +open TXF, ">$FONT.txf" or die; +print TXF pack "V", 0x667874ff; +print TXF pack "V", 0x12345678; +print TXF pack "V", 0; +print TXF pack "V", $TEXSIZ; +print TXF pack "V", $TEXSIZ; +print TXF pack "V", round($TEXSIZ * $LINEHGT); +print TXF pack "V", 0; +print TXF pack "V", scalar(keys(%metrics)); +my @chars = sort { $CHARS{$a} <=> $CHARS{$b} } (keys %metrics); +foreach my $c (@chars) { + my $m = $metrics{$c}; + my $p = $positions{$c}; + my $step = round($m->[0] * $LINEHGT * $TEXSIZ); + + # Pad the bounding box, to handle areas that outside. This can + # happen due to thick lines in the font path, or be an artifact of + # the downsampling. + my $w = round($m->[3] * $LINEHGT * $TEXSIZ + 2*$PADDING); + my $h = round($m->[4] * $LINEHGT * $TEXSIZ + 2*$PADDING); + my $xoff = -round($m->[1] * $LINEHGT * $TEXSIZ - $PADDING); + my $yoff = -round($m->[2] * $LINEHGT * $TEXSIZ - $PADDING); + my $x = round($p->[0] * $TEXSIZ - $PADDING); + my $y = round($p->[1] * $TEXSIZ - $PADDING); + + print TXF pack "v", $CHARS{$c}; + print TXF pack "C", $w; + print TXF pack "C", $h; + print TXF pack "c", $xoff; + print TXF pack "c", $yoff; + print TXF pack "C", $step; + print TXF pack "C", 0; + print TXF pack "v", $x; + print TXF pack "v", $y; +} + +# Read in the .ppm file, dump the duplicate color values (ghostscript +# won't generate pgm's) and write to the end of the .txf. Remember to +# swap the order of the rows; OpenGL textures are bottom-up. +open PPM, "$FONT.ppm" or die; +seek PPM, -3*$TEXSIZ*$TEXSIZ, 2 or die; +my @rows = (); +my $pixel; +for(my $r=0; $r<$TEXSIZ; $r++) { + my @row = (); + for(my $c=0; $c<$TEXSIZ; $c++) { + read PPM, $pixel, 3 or die; + push @row, substr($pixel, 0, 1); + } + push @rows, \@row; +} +close PPM; +for(my $r=(@rows - 1); $r>=0; $r--) { + print TXF join('', @{$rows[$r]}); +} +close TXF; + +# Clean up +#system("rm $FONT.ppm"); + +######################################################################## +######################################################################## +######################################################################## + +sub genPostscript { + my $rows = shift; + my $rowhgt = 1/$rows; + + my @PS = (); + + # The canonical "point size" number, in texture space + $LINEHGT = ($rowhgt - 2*$PADDING/$TEXSIZ) / $maxhgt; + + # Get to where we want. Draw the whole thing in a 1 inch square at + # the bottom left of the "page". + push @PS, "72 72 scale"; + + # Fill the square with black + push @PS, "0 setgray"; + push @PS, "-1 -1 moveto"; + push @PS, "-1 1 lineto 1 1 lineto 1 -1 lineto"; + push @PS, "closepath"; + push @PS, "fill"; + + # Draw in white + push @PS, "1 setgray"; + + # Generate our PUSH @PS, font + push @PS, "/$FONT findfont $LINEHGT scalefont setfont"; + + my $x = $PADDING/$TEXSIZ; + my $y = 1 - $rowhgt + $PADDING/$TEXSIZ; + my @chars = sort { $CHARS{$a} <=> $CHARS{$b} } (keys %CHARS); + foreach my $c (@chars) { + my $m = $metrics{$c}; + next if !defined $m; + + my $id = sprintf "%2.2x", $CHARS{$c}; + + # No space? + my $w = $m->[3]*$LINEHGT; + if($x + $w + $PADDING/$TEXSIZ > 1) { + $x = $PADDING/$TEXSIZ; + $y -= $rowhgt; + return undef if $y < 0; + } + + # Record where in the texture the box ended up + $positions{$c} = [$x, $y]; + + my $vx = $x + $m->[1]*$LINEHGT; + my $vy = $y + $m->[2]*$LINEHGT; + + push @PS, "$vx $vy moveto"; + push @PS, "<$id> show"; + + # Next box... + $x += $w + 2*$PADDING/$TEXSIZ; + } + + push @PS, "showpage"; + + return \@PS; +} + diff --git a/tools/src/plibconvert.cxx b/tools/src/plibconvert.cxx new file mode 100644 index 0000000..cd8d0a4 --- /dev/null +++ b/tools/src/plibconvert.cxx @@ -0,0 +1,99 @@ +// plibconvert.cxx +// +// Written by Bram Stolk +// Published as part of Steve Baker's PLIB under GPL +// +// Build with : +// g++ -o plibconvert plibconvert.cxx -lplibssg -lplibsg -lplibul -lGL + + +#include +#include +#include + +#include + +#include + + +int main(int argc, char *argv[]) +{ + if (argc!=3) + { + fprintf(stderr,"Usage: %s source destination\n", argv[0]); + exit(1); + } + + assert(strcmp(argv[1], argv[2])); + +#ifdef GLX_VERSION_1_3 + // Although we will not be doing any rendering, we must create + // a valid rendering context before we can call ssgInit() + Display *dpy = XOpenDisplay(0); + int scn=DefaultScreen(dpy); + int cnt; + GLXFBConfig *configs = glXGetFBConfigs(dpy, scn, &cnt); + if (!configs) + { + perror("glXGetFBConfigs"); + exit(1); + } + fprintf(stderr,"glXGetFBConfigs returned %p (%d matches)\n", configs, cnt); + assert(cnt); + GLXFBConfig fbc = configs[0]; + XVisualInfo *vinf = glXGetVisualFromFBConfig(dpy, fbc); + if (!vinf) + { + perror("glXGetVisualFromFBConfig"); + exit(1); + } + fprintf + ( + stderr, + "visualid=0x%lx (depth=%d,R/G/B=%lx/%lx/%lx)\n", + vinf->visualid, + vinf->depth, + vinf->red_mask, + vinf->green_mask, + vinf->blue_mask + ); + GLXContext cx = glXCreateNewContext(dpy, fbc, GLX_RGBA_TYPE, 0, GL_TRUE); + if (!cx) + { + perror("glXCreateNewContext"); + exit(1); + } + else + { + fprintf(stderr,"glX context created\n"); + } + int attrlist[] = + { + GLX_PBUFFER_WIDTH, 1, + GLX_PBUFFER_HEIGHT, 1, + 0 + }; + GLXPbuffer pBuffer = glXCreatePbuffer(dpy, fbc, attrlist); + fprintf(stderr,"pBuffer = %lx\n", pBuffer); + + bool ok=glXMakeContextCurrent(dpy, pBuffer, pBuffer, cx); + if (!ok) + { + perror("glXMakeContextCurrent"); + exit(1); + } + + // Initialize plib + fprintf(stderr,"Initializing plib...\n"); + ssgInit(); + ssgTexturePath ( "." ) ; + ssgModelPath ( "." ) ; + + ssgEntity *e = ssgLoad(argv[1]); // Load + e->print(stdout); // Inform + ssgSave(argv[2], e); // Store +#else + fprintf(stderr,"This util uses a pbuffer as context for plib. To build the source, you need glx protocol 1.3 or higher.\n"); +#endif +} + diff --git a/tools/src/txfdump/txfdump.pl b/tools/src/txfdump/txfdump.pl new file mode 100755 index 0000000..401280a --- /dev/null +++ b/tools/src/txfdump/txfdump.pl @@ -0,0 +1,93 @@ +#!/usr/bin/perl -w +use strict; + +## txfdump.pl - A .txf font file parser and image extractor +## +## Usage: txfdump.pl blahblah.txf +## +## Human readable font metric information will be printed to stdout, +## and a blahblah.pgm file will be written containing the texture +## image from the file. Note that the resulting image will be +## vertically reflected, owing to the difference between cartesian x/y +## coordinates used by .txf and the screen raster convention of the +## .pgm format (well, and the author's laziness). Load it up in your +## favorite viewer and flip it if you care. +## +## Copyright (C) 2002 Andrew James Ross +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License version 2 as +## published by the Free Software Foundation. + +my $file = shift or die; +open TXF, $file or die; + +# Start out assuming intel byte order +# These get used in the getshort/getint functions below +my $shortType = "v"; +my $longType = "V"; + +sub getsbyte { my $v=getbyte(); if($v>127) { $v-=256; } return $v; } +sub getbyte { my $val; read TXF, $val, 1 or die; return ord $val; } +sub getshort { my $val; read TXF, $val, 2 or die; return unpack $shortType, $val; } +sub getint { my $val; read TXF, $val, 4 or die; return unpack $longType, $val; } + +# Check the magic number; it is endian-independant +my $magic = sprintf "0x%8.8x", getint(); +die "Bad magic number ($magic)" if $magic ne "0x667874ff"; + +# Read the next four bytes to determine endianness +my $endian = sprintf "0x%8.8x", getint(); +if($endian eq "0x12345678") { +} elsif($endian eq "0x78563412") { + # Network byte order + $shortType = "n"; + $longType = "N"; +} else { + die "Bad endianness tag ($endian)"; +} + +# Read the rest of the header +my $format = getint(); +my $texwid = getint(); +my $texhgt = getint(); +my $linehgt = getint(); +my $unk = getint(); +my $nglyph = getint(); + +printf "Magic $magic Endian $endian Format 0x%8.8x\n", $format; +print "Texture: ${texwid}x$texhgt Line: $linehgt Glyphs: $nglyph Unk: $unk\n"; + +# Read each glyph's metadata +for(my $i=0; $i<$nglyph; $i++) { + print "Glyph $i\n"; + my $c = getshort(); + print " char: $c ('", chr($c), "')\n"; + print " width: ", getbyte(), "\n"; + print " height: ", getbyte(), "\n"; + print " xoff: ", getsbyte(), "\n"; + print " yoff: ", getsbyte(), "\n"; + print " step: ", getbyte(), "\n"; + print " unk: ", getbyte(), "\n"; + print " X: ", getshort(), "\n"; + print " Y: ", getshort(), "\n"; +} + +# The rest of the file is an image. Write it out as a .pgm file with +# the same name as the font file. + +$file =~ s/\.txf$/.pgm/; +open PGM, ">$file" or die; +print PGM "P2\n$texwid $texhgt\n255\n"; + +if($format == 0) { + for(my $i=0; $i<($texwid*$texhgt); $i++) { print PGM getbyte(), " "; } +} else { + for(my $i=0; $i<($texwid*$texhgt/8); $i++) { + my $byte = getbyte(); + for(my $j=0; $j<8; $j++) { + print PGM ($byte & (1<<$j)) ? "255 " : "0 "; + } + } +} + diff --git a/tools/tools.dsw b/tools/tools.dsw new file mode 100644 index 0000000..7d23fe9 --- /dev/null +++ b/tools/tools.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "af2rgb"=.\SRC\AF2RGB\af2rgb.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/transferCvs2WebSite b/transferCvs2WebSite new file mode 100644 index 0000000..8aa19a8 --- /dev/null +++ b/transferCvs2WebSite @@ -0,0 +1,82 @@ +# transferCvs2WebSite for plib +# +# you must already be logged in !! +# That means, you must do the following ONCE (once is enough for a lifetime :-)): +# cvs -d:pserver:anonymous@cvs1:/cvsroot/plib login +# +# export doesnt create the "cvs"-directories. Update would. Therefore I use export + + +echo running cd +cd /home/groups/p/pl/plib/htdocs + +echo handling "sg" +rm -R sg +cvs -d:pserver:anonymous@cvs1:/cvsroot/plib export -Dtoday -d sg plib/doc/sg >/dev/null 2>&1 + +echo handling "ssg" +rm -R ssg +cvs -d:pserver:anonymous@cvs1:/cvsroot/plib export -Dtoday -d ssg plib/doc/ssg >/dev/null 2>&1 + +echo handling "sl" +rm -R sl +cvs -d:pserver:anonymous@cvs1:/cvsroot/plib export -Dtoday -d sl plib/doc/sl >/dev/null 2>&1 + +echo handling "js" +rm -R js +cvs -d:pserver:anonymous@cvs1:/cvsroot/plib export -Dtoday -d js plib/doc/js >/dev/null 2>&1 + +echo handling "fnt" +rm -R fnt +cvs -d:pserver:anonymous@cvs1:/cvsroot/plib export -Dtoday -d fnt plib/doc/fnt >/dev/null 2>&1 + +echo handling "pw" +rm -R pw +cvs -d:pserver:anonymous@cvs1:/cvsroot/plib export -Dtoday -d pw plib/doc/pw >/dev/null 2>&1 + +echo handling "psl" +rm -R psl +cvs -d:pserver:anonymous@cvs1:/cvsroot/plib export -Dtoday -d psl plib/doc/psl >/dev/null 2>&1 + +echo handling "puAux" +rm -R puAux +cvs -d:pserver:anonymous@cvs1:/cvsroot/plib export -Dtoday -d puAux plib/doc/puAux >/dev/null 2>&1 + +echo handling "ssgAux" +rm -R ssgAux +cvs -d:pserver:anonymous@cvs1:/cvsroot/plib export -Dtoday -d ssgAux plib/doc/ssgAux >/dev/null 2>&1 + +echo handling "util" +rm -R util +cvs -d:pserver:anonymous@cvs1:/cvsroot/plib export -Dtoday -d util plib/doc/util >/dev/null 2>&1 + +echo handling "pui" +rm -R pui +cvs -d:pserver:anonymous@cvs1:/cvsroot/plib export -Dtoday -d pui plib/doc/pui >/dev/null 2>&1 + +echo handling "net" +rm -R net +cvs -d:pserver:anonymous@cvs1:/cvsroot/plib export -Dtoday -d net plib/doc/net >/dev/null 2>&1 + +chmod -R u=rwX,g=rwX,o=rX /home/groups/p/pl/plib/htdocs/sg +chmod -R u=rwX,g=rwX,o=rX /home/groups/p/pl/plib/htdocs/ssg +chmod -R u=rwX,g=rwX,o=rX /home/groups/p/pl/plib/htdocs/sl +chmod -R u=rwX,g=rwX,o=rX /home/groups/p/pl/plib/htdocs/js +chmod -R u=rwX,g=rwX,o=rX /home/groups/p/pl/plib/htdocs/fnt +chmod -R u=rwX,g=rwX,o=rX /home/groups/p/pl/plib/htdocs/puAux +chmod -R u=rwX,g=rwX,o=rX /home/groups/p/pl/plib/htdocs/ssgAux +chmod -R u=rwX,g=rwX,o=rX /home/groups/p/pl/plib/htdocs/util +chmod -R u=rwX,g=rwX,o=rX /home/groups/p/pl/plib/htdocs/pui +chmod -R u=rwX,g=rwX,o=rX /home/groups/p/pl/plib/htdocs/psl +chmod -R u=rwX,g=rwX,o=rX /home/groups/p/pl/plib/htdocs/pw +chmod -R u=rwX,g=rwX,o=rX /home/groups/p/pl/plib/htdocs/net + +echo done. + + + + + + + +