From 0e2e8209f950a0a99bc08a0a6cc6896d304a7958 Mon Sep 17 00:00:00 2001 From: Eleni Hikiko Date: Fri, 18 Jul 2014 07:13:36 +0300 Subject: [PATCH] initial commit, eq circuit emulator --- COPYING | 674 +++++++++ Makefile | 32 + README | 19 + RUN | 13 + data/7seg.png | Bin 0 -> 122691 bytes data/7seg_glow.png | Bin 0 -> 26364 bytes data/device.mtl | 56 + data/device.obj | 2255 ++++++++++++++++++++++++++++ data/envmap.png | Bin 0 -> 24615 bytes data/labels.png | Bin 0 -> 19042 bytes libs/libimago/COPYING | 674 +++++++++ libs/libimago/COPYING.LESSER | 165 ++ libs/libimago/Makefile.in | 76 + libs/libimago/README | 8 + libs/libimago/build/vcconfig.bat | 14 + libs/libimago/configure | 27 + libs/libimago/imago-vs2012.sln | 26 + libs/libimago/imago-vs2012.vcxproj | 173 +++ libs/libimago/imago-vs2012.vcxproj.filters | 51 + libs/libimago/imago.sln | 20 + libs/libimago/imago.vcproj | 211 +++ libs/libimago/install.bat | 5 + libs/libimago/src/conv.c | 260 ++++ libs/libimago/src/file_jpeg.c | 294 ++++ libs/libimago/src/file_png.c | 261 ++++ libs/libimago/src/file_ppm.c | 153 ++ libs/libimago/src/file_rgbe.c | 501 ++++++ libs/libimago/src/ftype_module.c | 118 ++ libs/libimago/src/ftype_module.h | 39 + libs/libimago/src/imago2.c | 449 ++++++ libs/libimago/src/imago2.h | 222 +++ libs/libimago/src/imago_gl.c | 223 +++ libs/libimago/test/Makefile | 19 + libs/libimago/test/test.c | 63 + src/bvol.cc | 80 + src/bvol.h | 54 + src/dev.cc | 218 +++ src/dev.h | 34 + src/fblur.cc | 138 ++ src/fblur.h | 32 + src/main.cc | 677 +++++++++ src/material.cc | 147 ++ src/material.h | 53 + src/mesh.cc | 174 +++ src/mesh.h | 60 + src/object.cc | 52 + src/object.h | 45 + src/objfile.cc | 583 +++++++ src/scene.cc | 107 ++ src/scene.h | 55 + src/timer.cc | 38 + src/timer.h | 25 + src/vmath.h | 99 ++ 53 files changed, 9772 insertions(+) create mode 100644 COPYING create mode 100644 Makefile create mode 100644 README create mode 100755 RUN create mode 100644 data/7seg.png create mode 100644 data/7seg_glow.png create mode 100644 data/device.mtl create mode 100644 data/device.obj create mode 100644 data/envmap.png create mode 100644 data/labels.png create mode 100644 libs/libimago/COPYING create mode 100644 libs/libimago/COPYING.LESSER create mode 100644 libs/libimago/Makefile.in create mode 100644 libs/libimago/README create mode 100644 libs/libimago/build/vcconfig.bat create mode 100755 libs/libimago/configure create mode 100644 libs/libimago/imago-vs2012.sln create mode 100644 libs/libimago/imago-vs2012.vcxproj create mode 100644 libs/libimago/imago-vs2012.vcxproj.filters create mode 100644 libs/libimago/imago.sln create mode 100644 libs/libimago/imago.vcproj create mode 100644 libs/libimago/install.bat create mode 100644 libs/libimago/src/conv.c create mode 100644 libs/libimago/src/file_jpeg.c create mode 100644 libs/libimago/src/file_png.c create mode 100644 libs/libimago/src/file_ppm.c create mode 100644 libs/libimago/src/file_rgbe.c create mode 100644 libs/libimago/src/ftype_module.c create mode 100644 libs/libimago/src/ftype_module.h create mode 100644 libs/libimago/src/imago2.c create mode 100644 libs/libimago/src/imago2.h create mode 100644 libs/libimago/src/imago_gl.c create mode 100644 libs/libimago/test/Makefile create mode 100644 libs/libimago/test/test.c create mode 100644 src/bvol.cc create mode 100644 src/bvol.h create mode 100644 src/dev.cc create mode 100644 src/dev.h create mode 100644 src/fblur.cc create mode 100644 src/fblur.h create mode 100644 src/main.cc create mode 100644 src/material.cc create mode 100644 src/material.h create mode 100644 src/mesh.cc create mode 100644 src/mesh.h create mode 100644 src/object.cc create mode 100644 src/object.h create mode 100644 src/objfile.cc create mode 100644 src/scene.cc create mode 100644 src/scene.h create mode 100644 src/timer.cc create mode 100644 src/timer.h create mode 100644 src/vmath.h diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + 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 +state 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 3 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, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program 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, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU 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 Lesser General +Public License instead of this License. But first, please read +. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d10b33c --- /dev/null +++ b/Makefile @@ -0,0 +1,32 @@ +src = $(wildcard src/*.cc) +obj = $(src:.cc=.o) +dep = $(obj:.o=.d) +bin = eqemu + +libimago_path = libs/libimago +libimago = $(libimago_path)/libimago.a + +CFLAGS = -pedantic -Wall -g -I$(libimago_path)/src +CXXFLAGS = $(CFLAGS) +LDFLAGS = -lGL -lGLU -lGLEW -lX11 -lm -lpthread -L$(libimago_path) -limago -lpng -ljpeg -lz + +$(bin): $(obj) $(libimago) + $(CXX) -o $@ $(obj) $(LDFLAGS) + +-include $(dep) + +%.d: %.cc + @$(CPP) $< $(CXXFLAGS) -MM -MT $(@:.d=.o) >$@ + +.PHONY: $(libimago) +$(libimago): + cd $(libimago_path) && ./configure --disable-debug --enable-opt + $(MAKE) -C $(libimago_path) + +.PHONY: clean +clean: + rm -f $(obj) $(bin) + +.PHONY: clean-libs +clean-libs: + $(MAKE) -C $(libimago_path) clean diff --git a/README b/README new file mode 100644 index 0000000..a1ff5f0 --- /dev/null +++ b/README @@ -0,0 +1,19 @@ +equeue emulator usage +--------------------- +- execute the included RUN script to start a pseudoterminal pair and connect the + emulator to one end. +- then make sure your program connects to the pseudoterminal /tmp/ttyeqemu. + +For testing you can run minicom thus: minicom -D /tmp/ttyeqemu + + +build instructions +------------------ +dependencies: +- OpenGL +- GLEW +- libpng +- libjpeg +- zlib + +After installing all necessary depdencies, just type make. diff --git a/RUN b/RUN new file mode 100755 index 0000000..5616e12 --- /dev/null +++ b/RUN @@ -0,0 +1,13 @@ +#!/bin/sh + +socat PTY,link=emuport PTY,link=/tmp/ttyeqemu & +if [ $? != 0 ]; then + echo "failed to create PTY pair" >&2 + exit 1 +fi + +echo 'starting equeue system emulator. connect to the /tmp/ttyeqemu fake serial port' + +./eqemu emuport + +kill %1 # kill socat diff --git a/data/7seg.png b/data/7seg.png new file mode 100644 index 0000000000000000000000000000000000000000..d1f5e57986022802271ee04b65c78143530b8eeb GIT binary patch literal 122691 zcmV)AK*Ya^P)Px#AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L002k;002k;M#*bF004jh zNkl&hQ=P+Wczp?%tY5axbxAZ2A6V<}uNY5pkv%kd7`*0_` zf6`5*r^x+Hnv~<~|C5(Ump@;gqqCZ`lVv_!L3;Bn-8>?# zlJy$P{rI`xfH^qzWvqXOpWSM|>|t|Z&(mq|>Et7Y*Bt;j({c8O^QmWilWg_6>*+Q_ z*~xW);Ltbbf?-fWdBW$q?4!R)m;cJg%Tc-~+R9%Gvd=f*R*bpi*H6>=vwtp5((835 zR|dE7DM5%gWN96#q3b1l@-zJEF6qg#S)G$?TgLapQ%~~hZstw7mS?{3Q(p9&5_dVJ ztVK+3R5ja~(`{_Vjo^1jb+@uw!hu6yGs3gW_wO^ z3*#q$_5IU2!|MVq(x0cZDa+S;I`O_qM#w$klk|jF$#A*;=eA^-dqOZ-qtlBo`KvlB+UVs0` zt>)_s0<4$qaLpo$ibd21JNXRq;f)Od{2K9oUi)RPSemB<0K7?9n zy_{xlPI+(QK%eQJPujwsa-8&AuXDrnv@u3?t-HjNkb}qWFGEmX;Shax$NY7TQA~IJ zhYn~*uTKM#d0pd8xQ0^<2k3b7wu)dpNyePwnA6&*^o*aa4B=!O_S#iq%>|6#5*hgt z>-JBt_2P%oxwO5U&)}Ng-~hnNST!~$8J}0~DDx_R^f|7r6HBrUQaI%)PGfXdj~fRH z$A3TRyHA?a@q*Kr0346K|Bq^%M$e!0{!6)_ZoE2KyS$%#7Jt-A0K_5(t8nyAAD|Q<*2Zdp@gyJQG(qbZuDVzg6dawi-$1TxO5dP;^Rk^_jZgWs zeaZ{`u#BGbAz|_S&&|??Jw5kn)}QZ<9nZ1}I_(DPOfIS$Z-kn!T-RU$e9nUP8>7*9 zJ_V2ra~p;}d#Ba&R~r0!wHyF1G&=7j>v^A9 zbLObyK$Ge2%QJcoTr!>QE{i8T8U16L84Ox*>2%QDm$J&9CL@qPcLGVX;^lzLvU7WO z%gg#REi3)1jXAbhuH1v<_ce7v7mGTj&P#Zs0szCsFGFfieX8dRERM@ipA?WuPdLp} zi2?=nLtx zjvl}J)v>Oe?f8*TlYl(&sLtLgLy_d_?8?$AHNKX#7D-j!XHl50T%M;JJ`uaurE?!RnV06txy{@A2^y6RjXS?yDr&HC}90PcQP*$Ud z`L$OM;&CGVWBfd#m63Vw<-wEdr#qLUJI1N0-gwTfd|+LAB+@9T#O0H|>8t3-!<4>8 z@CkbUWZ^yY&+=?vTRWCuX=ioPmo-W(gRUO$+{jTM>#OPA%esYbiF81uD?P9!po;)Y zuKN?5+s*5Vk$b4`La+GN}H5EMY;|}@H+MVDZ5k=E8`Ldo$8$$(GyPiY&Z1eZ>*0D ztZpscn#1C{>q}2N_v;zm=G2Ro7Y!BP<7<41yPh{Vr*gQ~ln!-afc59sr7}8IL36pE zsBM^&LQ+N5ik(D+_y%o|#sPq3wRd>udVdAXwhoduJK)KshffK>SeaIL+#tWfM2t67 z>&h);WfMfcN@ds(*;T1R)HvFRzBxL5;&2v(cCHJ)bS0a|Hz2DcjW#^%=E~>qbg~xh z{$7^(ASJWiX3K;mg41O=50|63{EW4vj0$-@vOe`Jj}8n7IFrzrN^y|g)5dYzppvUz zV6Z8wOVJi9jeJ7#PR)DLkxlA?a-IBDBB|xHcm2x7$!MD)2M4PRaqwS7iS3Jdv#&h>@N02&k)s}W*5A*o2ELqJ|KEQS zhWZ?@9?hGLv)TeZL&7je+U(tv;^)#YqOOnjLsoW)`Njm2ykYr^6Qt8)6MwA^H{hoF z+j)t4{sO0#0I1-iUlVbCd1mKi1n`qEWn*W4v;h_+1>?L}hSjYT%&W9FZq3WA6Dqjq zI31zcGiF{-IQHZO_NvU+UsJb5O&A|T?6@JuCw|?}?NUv4zTytf{RWq7KlQfAHLpI` z_#`*z)99a9eND?hJt#tl!;nJJLJj)TmApJF{P-j|@6#Z?C;djs*VDh(1#IQ`-}#y( z3fkzK>xMapOJ=>L64dAW2y(K_pL8QH3SxT_3_Y#bm$BTtV;#ss(AW_fu15mADX?j& z1VZMhDNm8DI8E8yv)tIzj!P%3GfR3dQ0r?G=Bb`7*P;CqlptkBEIvu*>4ev-WdoeCJ8Wt;&1+ zUjLh;&uYa5PnzqBGjMuK@=5~$OA+4SsHzFLfecHPenIPT0bSiuVhEGSN;E|s$Uv-R z0j}=1q)QDgM}u4kvssQ1jme_MQDQ+!8Jg298d8EV+T5k5R58A+y04Ho$sIc0rRAqy z#PXl5By>Y?Hyv)`4ae1Iyd*!s^m8#*4HbiA4WEsq-^r){F1A6>-yd#y*w~x0u0n+^ ziYUI3*823r00NhSx!kz&pVkM)AQlI zB|RT!L7ko3!HQ19Iz2Ziyd2l_93XC*NNN*abOf7xS$aMyR6Y6hPyBXpfjYHtQE-<% ze(LR7(wJGgJNd};rB46oVeFlbE{!xyL-*Pa?e2FavYW>9FoG;=*S6+jbCLLeC5CqQjK|7(c(`%Nv4uJu#NcM2Ts|t_Xuu zp%Kw8Ba+V@$8$JD<5hLV?l1p#KZjW_XcZmI8u?O~>p9GYR0T~5f>T|2Kv#XBpn(EMA+!Yujy9=h87 zR%fre^&17}sONLD^T{!6i(av$N6w+kwkPG+baHm!Rd57a*CHiMzqC#GOi7w3qH)bh zvp%*f8^Ms12CLFbibS8YoT>l)p`^h43>g){ch8T;ULBA|(IP)bt-U5#NsFr;+)vED zc0hAfFRwxQ|I_OXR*&qA@mr+cW=rAN`i5=f^Nx5fAyIL2Z@O7vPJMFFn$b`ZB&Y9G z=>J|3I-)MyVh3$!tF3OgLsHn^+4byfc{_H{v+vWZL3fN2>OlKAvj5R8dYEtuv9oh7 z9p^20QlQ}#&4E)7s-*ME_BZb!H-gDH1OG(@_1>QIlmKsXjw4-ipnf?+YBC&rq9u7t zHy54U&EBgB615MI^}ePK=j`ecL^A5DcEo#;{jWU6H=dUE_2~4v8vfB_yV3fh;z&-B zZO6HU^Y> zlWYKj0dMo_urd!C!5?|j!{ZVz)9Gr=^5D)p(loFKV^7q44ZnxX9-AW)@;Lwo!V= zQ6vI_M!|*AW-$wuNPI1mL zpUt`R$tR>{(1q8rc)Ha;Mlj(HMjVnLc=UoY{q0+v`|b<4s~%T7R9nOc45a0Ub`t&K z*ExJ@$GMRvCg00URn5uN)*hC8jy8=9K4e30ik{j$Pu)DLL#0Jy!qtUk=Sszq2oFo* zzo@zMcR$759X18M$C`#{`b8KHY&-T_1z7$fg=a^B>aubD=9O6gFtYdnf5X~Sk zH`JQi1~T<>9@?Aais&2w>VgAfJs$^n*6De(sJV0NHtlR~45Wi~d3ob`GGTytAw_W4 zJ(J(F$@X_{5iSNanq9#uE|l46HqSw{Sb~QqEc4-@&j~}!9Uq2u{j0A#}8cD|y@H%O7 z^5kdvj~8!W6r8_!j?L|@y!lr|tjmi9R=N#h-V8a=*x8U|dN1Am8Pr$3X1kPS?oH0t zJx25Qd@eE2ys^qb0?on4v298oart}EK2tAv@7aH}$GzM4(G>0drQqH1QI8reCv?Pxgn}H76e7fZ2fN{xIz$fBO<@|SC;@$82 z4Dyyk3lC{wrpOf}Ot&DSQra1k1yh{!h(y|ugT(nlRLn-ZtPsgLG@4J|>2y~r;Z*@o za*A(kv#Ofci#+#s?UG4zEl}5%5l4ahYRiXz^K0Dwho2zH(j2corgD4+`hc!8;!sKS zc2lpw#qYVud*AyR;+2RN!B8+R^#K5h!R&?`*%tLVk=G7uWE8~PaXxmsJ?f|>eknL9 zn(a|uBenBWa`45A?*lwTQbY5GGZESfdB5S8{~y1=-cLRx;L(wuYxFoBg6gkw7=fxo zOG8vT6`XofO2p5>wePvaTi^X2?PWs%cF()H+KOm_ORkrDN)Bjy`Kn~UB2|dboy#-= zVL<=rI7wt{1Vm^@K2Il_-c9lOT7;BrkL0sms<#?s5ePq*_@)2&e_-|t`?e(XD%X|J zq`_A^K|W_1065;ab$KM9oK);wyufri&Gm~ZM?f6v6-{d1LkD$mnzKIi3FJQdLKl(j zj6L)~b8)@lSG5g|i0f;Ry5YpK)fRM+KKm#AB0XdY3ug}2_VzX|2%miPG1|nTSmX&- z_hpfhBs6alY!lo+Wcga!GQm}4>vwJQ&L8_6i?45JrmY2Aw9Jm68S$=uPQ1&>4>xcf zI8X`4vfHG*iSljUI59HNJ{$LulO7v0I4VFuB#yFnAsf1EsJwkA95}Xr+d0x@$Gso@ z2tFOj8wMEZ>o72DbX`>mA+U4tJe%7)h?ou!dJdYBS%wkPp>y2V>$%UNZ&}hyCl*2O ze%EEa^=qzE^07vQ)SZ8go?{Eh_VyM<5%~DykEmyhWovQfdY;z)d8*;C+SYGSuK%ky zx$wQ`nSX9UJyAmROIh}=E*u2$RYnH6;XL?$p2izeM+p?!k%|4YkWykIo+u8{ZUI%i zdUKMTs_KfzN!)XZgydU*XP=ehl~3cn#J;($@t2&P4y$1z=WB zo6$qDh{)$XH~#2bY=6%d_4S6PXz&z3L2?T`)83ARJ`gydd`#xH_&PUetr0kdkxjPu zE9d%!&F6)j1YTX9$HoFXV~2dD{=au36I6>5`HeUEaO+oi@VDXO<48D5vI=(9SsuX>0Gb@q*v5p<2-|<;0y{sr&E9)^JctkQjkmQb1k^WuJE?&$VA5|!hcz*o z?NGrHM|Rl)fhM0aA8XFN7f0++0MZUEa$^@buwYI8($J1HXbw;a(MKw&nEuA|Y+t^@ z{$IY!WL6SIY03tY;%fgybk~yw$$I<58q2iuhCQRsvTmCo`;OQqD;I|T#8(WO1wFt>FqmF8au>DRZeEK|Jcvg&dGMzlnv zCAnN{jgT;#9*a)bi)>E}6)f72QcfcI7T>s)a}MpHyWqWO4s>l;g6iD2ZgcY+KEwS# ze~cP{oxh2SPR7~^^bM5p)N+Da;HFPf2d-FletM2T5{n_-R2sJP%lPIe>< z#6;KoQCfg&ZT)N~Elm-bv=#4t>FfBF|J}c!`N>1uf)+U;6`xb0&*9Q6qrAaIkCqAD z5?rm62Z2@~{YJ;mpS?i&Jv-cv_wb8gL8Qr1U$PU@ly=gBYw*$cKHqS8LhI&uodEkw z{723?+MIZkEC*77a}no+Hd%rrbjK$zmKkh#Z+;ujHV1a+a@i<|Q~iPU7i-|HF%G`yl)$&1SVZ<o8e z2u)q4HA7cdyqG7;<@tug){-tMEJ^I4^9tgS*5Kmq3xVxFevTVI{1ylA?$gME)Mls0 zCz3{zOQ^Fy!&pY-7)AJGS$U1(IV|t$Q#A(dDpT!p&5vf_NuC5}0V_$S0lEp{+e&WyshdoH*Ob}imPN3| zGl@Nk2_d-!D$dFT1X{JZh!T4TQoY)H8fmpfUFQ4HMDmziJftGf21N^-lh&*Km*=4M zwf#+`m4;X(n$X&7*V2}eHbfd~l2huc=3w)Xa5=DfVTZ-TIrYbLIB=R_NlD5Xf_@EUMK#ijzKqLJ#%pEw?vh=}C12wQT?I|qaThCF>eg6= z!OkRmXQ>>ouj$k5=m^uTO@enEJl;o~a12fVl81Izo?|HLa*aO_YDXChS|a{E&y7F! zHdlV{b@WQ4ronj!1!xsWz6M{AyhB|yGLjG>guJ#|Fgv*fUT{GnuZ0pI1x1U1_XVjC z)CW??8)9Fe&LP3-JuQl2S!aCq0i@#&Nl2R={K8)Q)=}&R+|1EvO|e~a>Cz>R?#`I~ z>Vaj)Is{pKPHrF>{X15%ZXH@D_)h-Whe>6koEJ=I6)7gtmy~P&%eT1v-Iq?3tZQ)dBJ4FwuJQUZlQC`n!*cqlyT9nL!> zh>?VO2Zf;&MFj6`1MI}?a#uB}9(?r39E!TY&4sXCaOv}xdGz=Z@q-1v4)on>M9op} z05Dydt3Izi*W)tpOt=p2LT4i!f(9jRf%|O1wLkne7k~R@8o!|4TtEpL3J6Ln7Np=v zenBc)2oVhtd;(Y4+UnKd=nnfVWZC;p&mFGFsHCC8VdanNIn_T?9i_CRSH7mhEb0H(_yr5+yg$O>9oX_^a5E7bV zkYz2-f?eKOvOyfaFk2|zNM@5*;6HiAiLLRmv}F0#?J4DM!F>CO=G~S{?_A~Zr*;YV z1&k7Uk?L8#9i02n*_-G=B%*}tMHxN`L>uJFCF6z8DJPUO1(0h)hu zZGJzytlxC#N?@Qn#-Y8JBIAF%h*>jy^b>G z$3(IA&F3D{K|{S6Ki_3xoEofC6H*3l{QkGN`omYb`}upMDp4I)lyyK0K~jrrEnDOx zxM+21K6xZ2e1^X`jkpx>(cz-QC67;@&_V88z^TKfDi_=p2p&hkNr7m>QQ;#5N()eo zvUA2Z8wgDd&g@;vLto zT_a4&V|t!Xf^*U@zNX2i)AM!v>veiAOL{)~%(+3&hc7)*&)a#+x#~Q6&~h+8$Qh@+ zmw4HFK7fF1)7hO{+)yMQKrT7H`S*Mi^FP^gc+ZTyHG3RhLqoC+!by>E$Dy*}RdltIa?868yNBsd@@-`Qj zmCyZ|&%^I@>|Z^=DU^#%goIazPl8XHZH5s8NzA$z10l;jM2{qJt;e_7wzSS{kd%f1 zl7PAbp~QAQ9$V_{Z%>J!cnx?f3MNPwZ4bECQ>c=h;Jm}N4j&y%gl01`b2DykTxaLu zCU<`3HoBj3mhhOwU*T|e4gJFg(`u8e7q8;WU_llqNV5JbBF>y?8ERzvOz~3#bLJH< zA2;meys*TQJO&I6HfQ*6>9xy@`9@4)YrO=LDrHeprU{GPBbuhc_pIJS`O?b>p05#g zw$t?86hsBQ5;bx8w_fG)AG*fjuRCJ4bwEe~zwoxHDOy9Hb zT#g1RdOwjc)%mR+|%}wJ$OkMSZbZBbOdnS~`p5Sv=9#3nvJIT?kh=YP_X4eI zJF$;N-}wMt;H3))kUNN!4&74T`L6f4`Uh@s@4egPhlYfq+OL;&Z7C89n4O7m*+Ye9D|ez9c2^4tqFpbU+uE+PntH(tT=B+9Hy+ z6Tt;8{I^@&{q&BdJ=4fHSqX}qbz@+clW|=pmTXU;n`oiksJZ(4Z*cjCu5;(|142>a zYeig1oPb*xqRqaOZD-1;IBY}S>0M{{1w+GWYI8YrIUu{dt*KVRRRGbD02B~Y-ivw* zk|kUBJwr)AE)>i80K;@>h_t1mB^2V>j3x7r=N$gxKCaElg3xh;J);oMVoJPSw~LNe zTJ$Ph`u;0i{qAc#IQI~C6mepD-B{4YBG|UMvdZ%A{w>39VA8y{cF&dC9GU-InH>?3 zP$5Z3;xm;+Mq6ipR>V-gnhYN!BKYKTM}UmH==KTTf||beq*7^iTGBLesXfo(Pw%t% z@|;K-C55fLL!I>d!quesbC&=-4esBKqAKx0NNO;)!dq>ds#^UYx!$TbGP%#IYENEv z+Uw}XNkM_$5O%fF8J43dyB%x3*YOtE1DtCdqae<+d-MRNN+lDTrY5ydQuLPzPagst zu>>~}3Yij%NGOGQJ14LV&q^hT7KpZpvuqMhP^nQ-gSF(6faH7+NpsGjF_Ch{M2ZX} zm4Y@zpdj`o1h!B(mur9}pwi^p^#X~F&5If&K6$}OZMA)x5btSmxLVm_gYvOw|C2}5 zxgM>9^}S5Vo>tF82o#e*-9#EqR2janvZCi;b?I5pt@h;U+4GZvVXNO;r{}#RJ=#nh z)1WnaF6!_uFq`c$(?f$u5r?es8P}yBLwu!-#?A;K*OOhE$616D*%9h#Lp^Dcqx_y? zr9&?EXH_>q25la!?mS5voKR=*@kEVFWiAT>bv3xc7W86BAvotqntG?Fy8%JW2VMl7rCn*R#nc@!p(+Pmic45n70K>;Vrr4{di}V|ky=Q{XV}lMa7k zl6G`BzTg67QE{-b&mt~xKHw$fat2VJ&`{!PLl1SORVJe%mp|kT9p-}cB}Pee9l0&O z>I1HfW;a|iNF74R_o`}(Y?PWnj?O1VVnNc@<}NADN802w99}Khl8OFYD{Sf(v-^ka zfBJ|r1QwySx;y8Q_=?lgqh~=-v`qLLfx;K)W2K3aqIKq=OG3OubH=@c=5!o31FaKJ z38pWPvE5i_^Tt7ilm^J@s;%sg!Jz249BfavA&QHJ$48Gja&xp$QnTD=`epaMb znzTrQVs5*hI?Rcmhw}4N%9(KQ-aYsg&*nF8AR7*9C=LU}g1VUz>PcS$V7wI*+jzPG zf-YihGVO;2k_8tm16Ls4W!Sm5fSYtMb?J{+4T!d=QRXn6|tI=P|DgP;;bA=J2<%-w@5Ch80)fgj)co{ zcbOj}&?p2q!TaolM@Q6EKq@S`xP7ie2WKv{}x|9e4pxzQx@;fkv%Ml@Cs<@ zty0|nu+=Qk)-Ae`Nbe|H?`}W?_dmT)`A?@@__j?BHxFUU6XpdQcPFSch*Uixrtxtl ztI5~UCy=^w2(Sdy67jGL8HG_8Qoy@@ZzZxx5iQ7|eK~MvS3>5#kc_rzED#nQLIbf{FuOhnVCVi8 z)h~KJ`MV$R;L&~jH#*`65jV^FMk2b_0?Dqwb#?ucpLpH5*Q~`IWXMuyo&a%V$XDV~ z{g6BJTU@$$nH$$`&@5UO^SL<{9dc7FdL-ni@EPjAK!*Ewkv}0$6MV*T`S;%73xD{F zEVgTI{mLz>&5Co|=SZTYGSY5Dv@mE$3>gwvs6iSFXK=Tm2Db_sB37vVo1u&93$%<# z0jUsD(W2fPlt>cEMT2v>+Tgzq)YleW^a-J{jfU4gd#`1NjpfKD!6M9C2PKnVuDJJK z-RAut{}uG6sPsQ^$Lpe`0*|qo11t#YSwPk zID)NN)FfwWIJKTH>GPWG-bs4iIqJvGKg!^B7iXv^L7Zd1+2w2P*KofvaQ-)4Vi6bU z{+vg25kC6}&U=HiV@9Hk>}ef1XGpFPjH>H_M8 zdOAlZki3?W$dDFGF(?t?+n71QBOwJ;Gl)=!!3%B9AEouzsl`@a*N`dr=0)#i_8vZ z=seoJx1+`VWguQU$tN;WCogOX%BtkbrK?=Na*0_p|EJqYv&xXXowR?m1HQW zkb*Orb^m(X@EEMrY)Q&>Oxy+`1jHxft08CqbK=o#gCWsZYpsD3*U6JM z+)Je=$Ij)Boo6X?-=T}5Ct60V2A!W zTL7J1T361Lp}Er9`XAp_rhjaU&;7|Sa_wKf!NJ$|c=U4**{rtNxw6foTo5M-ah8Qo z#lqmBlEB-hn}QxDs$P4Y>w{fRNx|cMLc8{M4nuV~A$CyGthbhsO8uH?t#Ppa+cFS< zX<^TmmxNEymI|dZZ6<8~V#R~M@(CaRm9KJscZYYby~Fm#CI@@_#CX;^zHYM2t}mCQ zc?&we?b-U_i+tvP^Eo!Z{Q?I+vrGL?=4@Qp#D6hxxH%`(9^ZOmNYq<%3skoiDv@@h zMVv=ng2ECs(KqJP1h+1p#j8O zB16P6sY{Aqb=>|-pK|Lje2vSGu5k0(+k|Ps{^23o<_!6;tl6g5y&(7KiAzKG%-gG? z3S7Ezjq~Tvv9Ynm-Y@R5d-Ry?Z`@|noue-2P$&c=xl|Wzjr3OLqSB&eCT}c;3}xq+ z+M3G1MG{&o(eOg@(Mm*JOA{+pAqrv-{MINPm&(v}UefS{i3-7VZt*WCRZ zAM?pS{E(e*y2$5#;OnTbHOz0#DISMh5_p!9?(qmGd`eyu1@{{Y&i`+(@Yx^vB0K&Z zkACtYyPxcF;Y&NDOIA7*Vo54$+Rc_!ctbh|XeSX3EzT9hkjtgL+9p3(xuYRH^5W|Z zd97Y?UM;{}v{uGKV+6xqP}lb5L}r(2b7EZfQ9DP>xjerRRBhs8i-&J;F7Z&J=10OZ6s?l>oq5;YN>5O}RDY!j+3uRcYiwE!@6+ zo0JllZ(h#r57LPntDyzXQ#S2OpDo|cK*nQEN@CgR8D~cgy6=wtMpxIbUZ{M*Y<|dL zbHHqV#M{-|MwU?;^YpDxZn5|9G2*k4Ob}XwbHpO`5#O_ta%U7>hN1a)DlYvSSK0n! z=g|v7@qy>oU-*c}KlPB${ov>Ezc=vsGcy1t4~>VREu%%Xmk5kTOvV{{9(6odMgFWs zq#*i)3zHmOPeX=v#ISBxY}vFJBSj|ZA}P{jB*wHxW3ZmNg%Y4{ z514+>7MK2wYh1W?k-Pu-9d7;mAJF{j94|tnuijBFs|n|>USw-)Ba{CX-23z%NAnq1 zZd}IuFl5Peh|~@`N{|0LDR{Mf{1{}re0&!XUZ>~KWmd^B(&G-jC`7MRML{}D?B0LG z?sS*x4{dSnPh4l`@(%a@#y#%*Up}P1y#Q~*{C+T zboCN$t3UD*-`BvS0iR`s}T@yo3ypH>oZ(&ws*_dW-MmILi$o3f%p{d*43D8xc3 zrU4!(_ddPL(Pw8|_*2)o@&|4Z?m9mH^B-{UuYLjt>9`(-tnX)OSFGk~fJPSzpK)CL z!RuWA!RtJ_F=M(2lt1hF+JE>}I7qzpC*Gp{-HAt69#g~(!pzfDGt+bJ>}WY4yjHTY z%V>#`s1ffYiO{3;pjcwecB>}=dT8)?B+aOX2Gs&lnA8;;_a~&EI^yI1{9|T6xyw~| zlM9>YiQ3>w$80v|qYpkL)oafAtnxfze#XzY%etXnVM7Qz1v~$%%Ut>Xo9w;)nCa1k z@*kCa`9J!3eC2uPPrgI*ntE-ablpb`k=NO6 zLnkeXa)}?G{Jq8K?|iO|?(1JWWqW^GDTCcxjW^{f9>aa_@CWFZrN`|*LGOG z+}tQVQHP&h(7B~$NU$MHzG=$!KmIn=_e^I)kxkU%R3Vf_AOnl z>qBTgS~Nx;sGgmN7uft@!sDNM!23V(6*!38{HVB@e zE*V9mY(Cn-??-ljVvmo0^ecq9 zoE@IYGa&&SB>_QTdwZKp*RD`jWoD^Qh!Zw9w>UgFq&}LnF`XhECx4DCk?VO>tp2#G zMeYe!G9=ah%TaM8*H~u~yBtcj-j`P2VXcaCujIUMQjs3^Z=E8BA~u6i+WW~Vg%)f) zo^pp<%=QimT5#?Bb+oj0F9|58CFOL=(czqSv9Rn#KDTyYhqE;3r9ITXHFkLY`oN_h zy1|t{_!fKb?6bGMk8D?5-MPlmS7zM#+1u<~KhMV1O(?;)KEvR0Jy1@e3nfYo-VMy@ z&h_m`4BBFZB$nwjvK;jm(Ly4LhU87_lC&r-BDNul5^>Vf`e>QcptL@s1;nBzIg7wg z>uokaF4+73J>;u@{g+uhKH}!@dynfs@D8&tHaysP%(-{2;$mR$mmVUAoH@#3ot}?N z9H$#ou3WpyWNSjwgd)V0*xBA@zF2T{a6nZ}@F6p*%1F;8*L3Gvyfh{f8tFNs?+Dm} z*Xe(LI8=scv+`s;?~pADBR$vdlGxebVz=4jj@;tl>*iej*WTmW58mML3l00z8JDhJ zBE*tM@88EQIyQCte#+pNmlIZZI8978H@I}|D#f&zhoE|cdNt9fz)KIX`5Ygx9Sw($>;q%o9>7)^Zgk?0!B z_MtS|Sk}l#+N|r*LkcZgI2za5#y@#>4z?-2?0NiS_xRe6{whHVKKp%N$GJanjYpq( z%=}!g&g>l3&p96c=p8=zFTM=t zJfHcYFLLg8U*O)2J(^3A%NH*rkKo`dd!*)!?8=kNqRqYpkV2Sz{RS8Rk2l%*)*TM6 z%sAXWVDtJGJLk@E_vdes?nbtXEmFYRxgl0^(q-Pp^}oH%=mA9{<~`8jE` zWwEhfa%swy?W^4TnL8Z3f56V?ci6ms9p!6N&@@q0}j*mi>PP zP-sQj76gPMIZ7>M8TDvA#sd;i%(KKYN{$Ne+qt&8unu|1`s&Fh3P*_}H!=Om@K?2`z1 z%_y~r!cE5)|KQhC{o9+&caD%&sHv&m-emjc4v&8J0f+x=pKI5yQr-xpoj}Eu&BFh6eyFYa1)AD^#7GwQl*kYq0kA1=J&K>ss%n3_~@wAGf}9tq)@?2L6HJQ zGWq)Cs5DR{<1Z;vVgG7D&_J0=%C?{kCFL(WcK_4+eDXKH#^j$DyuI}f#b(K@SeReb z!p`P4D$49|X6t7zTeFfuOVqs#S4MzxQgZp`b$nIjI%XlY5jpSKj@umk!ak4NT`v5( z^Hk>o1rsWDz1&JEDdUt9kC#A+BcutFIH8b?El;@_4{)}TI6-XW%)~2rg;`=(E>uu*_}<`8y%ndx4uC2 zTQ}IhdWcquHaT`KooD0XCii~n9!DR~xN-F=#l{ADAu*{dO5LPNQ!3q{N>j=dD5Rj2 zDIq4RG^NmzkSa<_%2f9HSZJV7hi|PNc%dbwdb26XQ;H|xv)ltdMJ8FV&9*oyEeSZv zRIi-+hUPH+GqwpCc}C^V~J|KH6pR z;T#vAl(Rp{sGNjK>yWOQlR!GIg3Prr5w>v9 z?jjEpJ73yHuR97?uywdY)l|4D;fo2=`6g8?2;P}3r=*g~Y)hOFw8%Ex_x7gL!t^@1 zUe614l;WABKuBiC%j75%6v;7BPe^6vqVl*j*r|{_1%c3%xPOtj|CjG@>;L@$mww$f zZv5$YD1X-u2Rkzset}#Nc0PBG*@p+jFE5yAK@5ph*>fJEUka*)lLZgYvt#u|VC&)* zp)9D|rmwSaG*OfVS8v|n_QxNy_i&G$bLa7;&_NRIuZQbF{NU^IArVl&NKZ}=XiMT0d6kr z>}}B$k^OI-^X{Mi3?Kf*_qqKyKjG%X_o%*g!qJt-I4bM0inVGImkIe~GC&o*At;;_ zS*F8=)fg+gmLoF2Y?<^?M;$_zhz6oY0;REktF;?RnJlK589zj-J@H>0viR#WKK=*q zbMf0Ra{hmRmGm7Y_tP$J&q&@D*Jf<}o=q}4MPzwR0w?3oSBv*~#kAQmrdp4+0@ zoUmw`Arq!bBay4uuW|e1PuP37%ee~|2$O(H8uYyHn{AsFYuD6WPDj>}hTfuC&mlv5 zF@let$p&(Jws9REITD}YU36_=at)Z8(aaqgk(k)M_lS=!evO?UxX86X@fLiY<8eH| zA30nU7S|f8@84kZ;WmrEy-#&i5T&K5EX3&QGuHEdBz*8}?Q9VyB~6S*2;?A56Ln~K zZ~t9>`S1S{_lo;mIk-yrd`0V8BX-H~tmM5xI8lQ4SfA*SnVoZ_6~L7PRMq8$#+5mN zpPL#|>_*brQ`G;<@ z|LqO#V3*BD8|+@%$9>6j;dkEP!H?gg{^v(ViqxyFjwEy@V(t}Plj0??eQpPt2u(6l zF+^$07B+;NJ8$#;-~TF)_wIB358kBtjRno5rJUswie$u|&gDSsQeZK+(DG{8qHZtR zw;L+5jcGBqfUtxXu(biA#yleqRm)6Sz)PsLVq-txT%?{fxTBK!-+#>hpL@jat%qFt z!&lh;H?OjI4-O7@Ddz>$pf`l;|Fd_v{R^Ms{;^wHG*4qAo<1KA=ThF7TLwzJLQuk$ zf@|MH9D8?)(dU^6$UT-MbIDc z-`ivBkDg=a2d~oHa2!28pgbsOHX9y)%ON*^AKE3M+X?K-;!#pWEWzEkR!d>@seBHfm$%x-PxW zp(&ww91w%TyTZBey1>U*?jVOS*{f(aTOMpb;^J>P&wGzQ&&Pl9D}3$Gzt5!)F4JCI zK&p_#Knio>G(xBevs~*OT11=?0*Xgno695}5=ML;K0~0ppnKm!*~%<@_GP;I+>Wdm z=-a)D7{bOfke*O`7K=kZ_&c{a`iTRs%4M!@T%i$VQ8qT8twF+@MZ@OyCJ*li+E_DA zJ-Zk1zt@hH(@mzEcyFYU+9dPu3RuXDjp;UTAHB;5KlMJJ{(GNtO$NBK^oh9! z@yYbrTOD~zi>;FpFBYio$Q~`Bmkhd(AkMfx#5;l)pdS32%=D*G5s4HXmyXW}BvqVK zBdTka_@L$E|K>wxzjDaU?|cAmK#{+TtH19CN8hI0-+9FLoeg4TovRj?8g{;Lk@Fa5PQEqTL3&tBz&oaZ*d&mm|M{8pdw1kY(;+sqOrvi`9NWRdgv}F{`?qiT%&e^CJmHAJSq&9Uuj0zw!H(cPI3@@gqRb7yf5+&By*}+ z@-AdV`e?mSLDWi*TuKC|y-#k0o5mHTzTxPT8TWqt9*a+A-2C0|arp;su=|aN?1z0O z2PFhyZ+gJZZ@JFoa~sUU9<IFJ+;kDBQ)xth%toD zfc=jH0FvvaMb$`pa4RJTrsSOtX;cpG?=e3(;>w@A!S&yD zljbd<-fJjgAeD(!MN*yEoKM&Y6COR6jGsr(O}9fRDT)G8WEE;pYpqvqyz>?xe(eJu z+`GqgIvL1*I)jkRDO3bWt~c;RFb0(U3Has5Z$UFUdHH7E150U7lE=YY$M+VmGUOAPA!wN;O*=0@bS-o#KFUTs=qTa zluybs&uA?BJLN2(@7c_|je^;WKp*+dLUzs_TctV&+2$){y|&IGq@gs*N-<#3Ig|@Q zj}rH9-^Jf7x$!67;=*@cVzH&v4{C}cpcT-n1-x2?$yrI(jp{QxIOZUAHN~)6zl#N1 zH@A5>Ul0o+h1?Ij4IIWpF8{8J#KXuZfB9>)AJ=U9O`?xz5sg@~bwo+lUaRrBqeB82 zub-prN`F}+*g%rLJSjzEgtnZ2-Z){wOBH9%BDS$H)@2=TH3%UIdlwIoZx`PF-uKw} z9Tzy*nbGbwgf>{aI|1K1%2f0+8LN0l40z_FRjjjiM5jto6zorC)>iD$Q|t!f`N*v+ zkGS?b&hfe3FYw`i@ID{@gRkOt42mvePR_h(7uWA*MxUANMSLco%d&QgM#1|I+0*s) zwt$&Ax&w!d1&XC-6Srqd(FN9D+(lgNnBQJd9y;FIxyk009Tur3s#tq243()GA$i(1 zoo@L8ewgd@TY92W>DT8WASQnJq6NRyY`!x;Q#Dg< zCPShf?H)4OFL`(4Z6@1O=BYu&p2@z{B-i-1M=gv=Mtg3$GdAvN`Oi?8&)wMq)x4RW zdFF0Gd9C8+(G70>?N9mm?|y(3ipq)%UAKPbwJs-sx?gc2tUn$_y^MU#?(-qB*9{dx znp~z^bU^`3-XU57rFAUsEN~Zv&;IexGyVPBJifV4qr%qx4ci2(BZfKzR7F^|MHjiKux%`_iQGDR}@UMIs_mg*X$rHWab^eC= zAYDRY;9%*Hy4_EzA4-z!8d5IFa-)3~gO2y*1upxBG9+3X;}Ot8kt0WVtQ;L4Azuu< z{cnAa&EI~WgRMClm1@7FokV-?@U$r|1)QIG9E*jyrQl*$W~MzRz*{TU3Aisfd|eXj zIg1N5qQZ1{LiCaScV=w;(Fra^3%EjqFMRlIs!| z^ueD_*G1gu9>iJ!O1J)|Q5k0!JlBj~AIjfdQqn9jpC3`YH|5YCMs~^Jtcp`HIblFcDMz`4+Z>qcKgBzL6)YVONwN#dENh{y$YPWjT8hw`f3rOs^ zZQkAb3^P~L_!^S8b{*MalhR0E+F47iR}6YfzfnF@Bhy-+t2%vTdR@KyGmY!QJO9pmod1EV?7h7p zYD=+S5L!=DS>ID>gl4~C_V~yy$v^+kopyBa`QRMhJ7UzV=L2*a5uzG#$o02xa_cJ} z^7!y@s8{NwnO5RM>%_bIo?H1i9oKWZjLYblW6_ zh5%CsRnF(?YX4qp1V|Mu58KKEz8j?M4B$o}pQ+MXQh$Y*T}bZ!@=Gjp@YS( zUi#Qpp2013?P9#Me!-d)x&TV%1woa?qG4-un;UY2yZ`hy2R}VG$5@{AB3{m1I2Drb zkYT0^<(DSB^Cv$`@x2osO^$Gnp;#2eG7&?x7J;pzhY9wc-G=4R1|X5 zoP!XND~|AXL6{#IcZ>+($XX^gn=N;D9&q6YuF!n4;Lcz8h-QC5^3ez_Ys>s6toGF9 z^=EWp%YS#9j$;m*%R!t(N*!*=zL@gb+Glp3G;KM^%x`gg;g5ekTi>+9qbr9j%9?Us zm~-yxKAXDOZD8KXTnBcvmjQ@QK&vDgVu+L%ZNt#7UCvm>i$$QBMjmbN^4|aCE#l8a zzVa7-33eU9a%96C8rSkjUJV!yU?iyZY4%em-%llTV}ibM;X2dF7Bg2{kNSmeRB?io zT?;IzXNx5shi4muuDg^nLNJe98`^i7abmG3fB@4Q8`L{BVXm|jVX>+Bg=4x~5q)Iu z>ONcFcaFEd_E|pu_rA=8O&V$%YBVz^C=h$;Ibx5iY5N&?5mf8i+dbh_6H2aMxlXmQ z#exM|Bx`ZH2&Pko+NL>p>iL4$ugPb=?LXn#g{m}!8ZlYGgwNtu`8EXyuj=IcYK9Zaro!B!67sl6X_5GKZmUQjOn z)+_A(@*{Tt)_o>SXsLUdcOKYS`sN8V{Ue+lSK^hBE#LC(MGgr8svQ2*u`_lb(w~nmc6OQZM^06C&|7=B>D&~s??M6$e1Lfm_ z!Uc{l%}Jm4-1zQysQ=y(vwwVmHEuFQg(u)}wA7=$U_9aCUJ_YH_Y--9w+n9kk$1TA zU6;9a;~`BE+1#H}9%SNKz&9Rw5a3}N{Ej}W(|H@CbDs5ed+)$`Vh0oK3Yqhx)e>o& zmUHJWaId&UTO0gIG#%g9uaj$9`L}zKRu4-{JCiQBJ=zDc^ow19V60)m+AO)vg0_md zOjrk4f7g^-6-KBE$5FGOsm<`I3=zg2T6vZu*MGOPa9;2iJW(Pd&a$IUNI9~tMa@y= zdG8zE=KXg{;#V5Ww50B#bSM0T_HcibOgE3?owkfNRwqSnx}i(o8{A*}t!{HOr=hq} z^7g;<9``mMG7pDFP~yC0Pb9aMal+!LW&ZFe%lsu00IUob0^$Q*P;FJuRg_uVaDL|; z)nv*+(-@<*c7#ELq{bWQ_49o4>r?A_8tFN#MhK8X*nVf53;*&Z4tI`-vBj&$Me7x- zVr-(J4YUVyngG;u|Jxeaj9<=MSiDY60)<~n_M1}W+;Amp(r*_B?*njicoO9JV4$A}f4tJ^Wc}w(U zyR!N>+0h*C>zF32$oi!B`xOs|w`<2J8*5t5f9X7v&rNweom11W8Ky|xkyu$L2Wf<~ zmtgPtB)Gbitd~MQMsu6QgtceAAov>t%1ZP6b||TNnOIz!asFG*aq!L~4uAQ;nDyz< zNFAB&8Zxod{GHzzzMEDK83hy5C<~*q;tnM%KO(X59p`bsA#gBRuqf(2GZlS8C~zqf zW{&yeIkdw$G|M2Z*w?chiG*$llbcgw6?1R%{8=#8=dxAgNN9H=e3OSSIQU3$jr1A$ zW15@WI(01PPee+s`jM839_Gf4-WvIFo$NcV1(&RZLp}H^(4H5P2j6taN=T)lpptV2 z|3)}Enj!IQc)HWbXXvb0=RSAc-WAL0Zd~4`KHnnFkzBMA#AF1bG7%284k?Na$}g0# zCFm@Zvvxp{nv8U0K#z`pCk^k6XQwY?k^Z8WvYz81szWxeN78kiSB8r6Vr}(`je@x8 zXr%4iysAJdq9Fmg_PXks&5qC*kC}m~ivFIz^o`g9cg*n%}L_z1|GvsxK`3Fw(aYsw;uCm1w-NY$cSa5os!1 zjMSlFaU(JLmp0k`i3fy-p2jgKXy4v>Eb|QO<_R83cP|69Z(OG}oSTe_7@esLTdFt2 zkhTiJPFQ`@2Gy^dGI#s9Rw&xcbLA6F)zF5>B$l*$4e5S*F#`1QV!Dzs8(Kq;?$HTs zfx9fk?UYek&dRX88iKe~A`9BBz}A{g~(vLk6lytSDfkkaekWh z_M}5}8UL0n@#YNEo!=Lb64F9(U+0kD>)1a!pqvSAQleg2Y|rpA!PP>UD(Z)aG>0A5 zfAnnXaVM4jg_Y8? zsx$uQB?J*q)bpi?YW}wbwqffFTQmwpM@V5numppENwU^Pi+c*UyX?Dd^)zQ1Uq-Lj z?osl-psUw4hI8mUA@n>7jw83ADOxy6G`{VR={FT8$ZG7s_j=j|@=iOt5{`~+Fhzr8 zckRGZg4TNY>Ln<@w87%if>bI_b0V{H!=Q+I4+Mum}-72h(rd zB2FFDP&(Uu;?l605+T)z`p#iS0K6pl`O?Tt&jIv`khX>(t4hdD>_G0PF<6EuBP}GC zn`uWbI))j%=y-~K>Y3e9QkRv>BY8z4RPSujToB|iQ7sB9Z*f*Cl_cRChdXf0Zy$_I z)iAHm%I0h+X+bqOZsbhmYDH(!cvP*NO8 zWh|@p`O)R$v=2Bf>4*$R#__W-O6UoKjDfE}!b@bY-h&Nj@7KgKjnA?&;u>3U(xkI&cTVyZQdcIu zA_iyk?=+XMYzqFf1#-iaTA^qPT(qEL8)7b9^f-js!x`=4_8H(!PZ>)nI$iP`mI6^1 zg?J%a%VAMM^pKS36K&;41blQzBkaxh!6n=9m)TCvqA5gI0+{0R{%}?9>*gVKMD^qM z>{#vRp(FEV`MFBk+jK1i7Qoel`f@}0aY1=t5zuzS+9ngt&n)K!hY$9s=k+MD(#fa$ z|3PMF7yz(G$a~8`$C!G8hQ9Vbx9SsBVv3{`bDn5`=Z{N0dV#%y(O0PDI_cby0M`l| zX~VJ-9gje_*}&liQf@VvQr?`dZW>-jP$OZR$r7q7Q;Ks1O-h6m&2jf)EaiYT+lJI8 znB{CvS3B#C?CV*^@l3n+-40A{%TCF%Q?qQ$VxsSXoa+3|9l^g>(C%bd;k?MsRPMK) zxdfbe(m{g9np-Hnx&VN4-r5nxwuhrjPSL338d_&{^+Pad!2G{1;Q81_8tl!Clx%yd z_bS>15+SL_$Al&$`bsY05nSzX4+S3EbF#GIf0@BMXW9Rb1jvZW;;3%Nf-erCP79(~ zdnNV5MV+MOdcx~oi=Sox*Ex$Gb5!cw%1H9-r1l&lFoEiwDT{M8>V0;6gB4-tB`^&d7APs~DWMKB7&HEuQWS6rul#E>*YY z{?h2Pb>HdU%k20}1uhHa+ZC>Kgxb>-Es0>yGYQoem6FsZ4)4t1K%c*T(YWM>)l(eb zRjXnfo6FEn=6y@Vj%>1vYlt=kJo^uiSnSRT<_h)MyjL}z1R&`7FdTS1#f1_kg3e5q zt`(5n-Vwz|4+oyv-NWoGDz4*sepyB(4dqdC&a-iG8xSi2>4ILF;81;p(ji9z9}0Y| zFwX(8#t$c4w--7MHaF#L$!aum{Cdc!^j}*Fs3*zrVn=Kv(>S4Q%iNDWXR2^W15TVF z(!_k1#lqIkmjh^B4J>3LxI);tIAL#N29Nzv>mBn&w1F^(@X&E|w}zQgNIHxEgLO0?nQp*Fhk%Jn5v$B&p+o`at^C2&(D4l*oe$G4 zP4QWcCsl)mqGZhf(YvX+g=CaOTRO@XI8e*HtEY3&JEX~}kT_$Rt_{{ok6jlT1^7B* zZxvfB(~ww638;-T%85X$Op7Vg={8N#z&6Oth)s({Ao_%FJYnWp+?kW+Ltwg}PhHW^ zvzU;a^h-pzDEKKjTATOWUBx&)tn|sXf_vy_KW>nH0X)*Y;I4Tr_wl`TwxkpH_$$ZG zVLpqfaf+!L^0}B+Og1)|%RU4p$pTqS2yK8m5{rlnp4sC=;=SBfP@ZiaeNtJB>#la? zg8O^9D8x&O&udMZBt$*M+@lMj*{o4Nfm%6we}n_6{t5Gf3TN(W?!{RZwT>}h6p zX0)j|-B@>Y4|W06u3 z3PZSPGDhj1eL53T>0zRIkPE?HGFoRW8|PeRjnDA&k?Y$bjyf5~MT;)d0Go#6hPfLn zSWwON#y#O(XP{4u0!Ue>TZO!E`b<0;>+W?nyD71KVS~7xXbOjDOCXrz<17nV&I@>~ z%pV?%e_}MU9L{tivR(!u1eb5!_0ZRp(uj@UV57~VB{n0d`ZM-xJ9c#9SlnfGBRHNT z5F{--HJu%DnGL^92_{hPOrbDBCJ_s^XzcRl84g=VjvgEt>f#InE341=QlLAMDU9s; zs%sPKjV6<8b?93~T$KZ@iQodwgNW`cj)JHiLo`S`3cjAjcoyC2iFPu?I0)s161Qb7 zBq?h;He?GXW#m*VxC7zv-mEV>NTaNO2OK}k;kr_Z3AppZ^vVWv=B87j(~Ce#i4+V#k9PD+JBglSVzf4m^>M!YCVV@{Y^vahpm-8d5jK*y}@iy||w zjv$z$_BCWd;)Ho~)F0C$AbRwm>+4U>ehjtH!;g<9*Cor|c86CEw+ZT!IrPz4!IuMk zwEAZpbzRdm%?ZEgYymzi7)-tk^#U78ajB%(E=e3^`Ie9z>Jm|Mouy7Wx-%m^9x&MV7HG+Lkqt zT*GLuz4y%KEinhtm8H;hzsjjQ);lF#j~lIF$36I0CB-7U)wf-pTd<*=9& zC6Xvn4Y6)MIlrn6oipr$qgf~ixA%II zx91b!@Uv;nN8|VG%9T(SIRH@SX%%p#>Af55oHQ+IuYp<4+>O!`4n509@cC{#lLAvh zbz>7>nY}a~mr)YifoMzFZs89d&8-=dMgZOH@X5=exH8$53Ax}1mz_aAU4bLoI$B!! zQz96&_#iT`=VnTSJ>zIx4!E2~T{=fL+p?s21ER-EH-swZL2=Tq=>NkO=4$NF}jp4Ln>$d{WBR z)9lt9?$3}Cnx>(Vw&wt7>)e^hXEfVLPx`-yEYuUPI+7E03eo3IQ7dxqZqJcxc)j-3 z@F>VOq)AJPiW{vx(YJ=obawv5VsXr#os|hc@%s*{NihUvQbxLV9YUNUQ7L0day3Wk z2%Kite3oRpR>sFL{M}7G0eiQarA~lX>!zhvKM#fug=ia{0BMmRdYFK};ou^)9I?6B zp*Re*8$vrdBFv_U3YAtoynBbZX!Ax|5KTQI1AWqUKHnrH5;_sKu5a~Fa%1W*z0F z74$77ZboP!%srv?5TJF@h{y#BDcQgG7#8jGucJ?SC{)H9?xFMC#>EXd56#qk*|G)K zRHV`os|b|1SxMX{2WuiN$@I%XI*LSX(bD{_xKid4$G?A4vLkZ{SOi1+^2EHSXJ}Jz z^Ax*1j)xd?X|`8u`FYx{QA`3pp02jr5V(+uku3&Ln&48PGQycnGO=)sIM%dTO_Wf$q$ zq}@Yr`XP*orrV`sJ59})y|yz%E}eAQL4HmK5D7= z7DFK6C62M4hv4x=Fr8TERAgazA6P8vzBOd$_78ggDm8tbCC!^+r^vRWxH2WBI@bhR zmkCMUjCyWA*z6|ew~eT)4}^{6FJy=5jDs4%J3!U)Yy}zx&&T4vWU#@9%VM>*>gy7R0qE{7&pM% zyUayG2pfUw#)M|OB^*q8&JZcAR$fFX7M}R1CGHMs;Q`7EaZC((7UQ(fbI8Y~T;k&F zy~)i9E?CPp=W^D)HTY{ABEBgItrB(xK2?aLU|pB>d70*Y0$dej+qiSge>T!tjiddE zD`@r`=J$u%Z7neb+A;{~xQRI)As=DOGZVqO3ZIU2?gR&7?3Q*xh!nAssnS{fXhtha zc1RQE8@QacZrk}v5%jZ;T&mY2H^v|3P;<6jwn=Yc1F9QSQkihH5H@LIi)cwijdP}H zDBF^w`-jZ$&JZuubwu3|@a#EtTrOpNqMc${VhAa_^I5<0K@ZVn9efMD%`nB8yHw6G(%tDabRpfF!o%x6g#5D$Q%7g!1F!+pYa7;6-g}@VgD0lvY>By+H!#xhmTfn9DPKBabu+vkr-(1)cE=HOZTL2 zWXxXq8~-~FX7=5b za(PYa5>Lza`NaYNz4KugUW6i(j6C_N_u^SB=A+|Qxr5JoY_Eq4rv<^?>%k3$hE!8L$cSu6ooshdvehp#w$WBgqRufRTB8pY8yLeK6+-i z4@t8OXPIE|sydx!SM!9q(PQrq@YW|R9OHUbHzYMx6glUqu1z_Z9O1>|=5}AvCEKhv zLfIC~?k$)r|7vePtDqP zW_WinJ#trpRG`w}oySYSi4a{yqNa3)x;VIfkohl!whQWEa5a72dg&8IpSeYxr|=^t zSfTGtY~@FNIUh|^+x>S)3zxsN7N(k>^7>gm9Uav5zD<_JPF+u3wX8`hmFm4s(neQ% z>k#koKGJ$2`2=$a^@QfZf_NudOS^Fvz|MGf!d@BPiFLZrAt)<-=D(|5Q?yAv&qWe_ zE;P=1xjr8$*%G{dObs%D;+-k&P9&CD<_Nd~EzEAZHWJiZcKxwt=;`x}@tT$u?+Nfl z%}cZ23{)2?4$56NLY1?T0r8O3%0i09v$)sN>~=N8d54^yx$@%q$1&#R)!WX2-3d(J ztI*PuG?R^~;KWM5QZQS@9O~P1cx?TOm3H9wc!{M(4hI`Tx~|3yEzaQF0#YiWHNvPw zO$eTP?~uiH5nr3Rg*ag_Cx^8O5NTLMPJ8~Iy? zhP$k5mLYzgk?K6$1%%Q_sa;QV) zx-Ls7NJ_SW@EGx5Owby-D5dm5zxzU?r*+ELTw8)cfR+|_IZ$j*jMt)a#3GV561V~% zJzBMdeNTBXq5X7WrHkVTUH|O5oDh39fA~aMCr2t1>^LS@ClCUpNOG1br-3GK1YK~* zqNTmNfcpybd`Yhp#w->^GAp`-cfA|)P2IV}dK zCP_vJxLgAZB!eB-b<1LIPi!2qNxu~KVu!U7bI#y6SCm*p#Fr#It@AnJT;_RDoD&Z3 z93XRtCycr>yu^{7@P0e`yzPQyw#k=mp{lCfX+e$b!k0kqcbSwT7PNO8ntStHBJlDZ zfbKVZ;jP_eUKsl>2qQh046Uo@%}5S!fS&i{Kcl8ECCCj&y;Y-<@P0z{2||HLLDxyy zi>G;1)7(3vAecOI2(gE?pZQ&6*Qju~;EfsBNrsj#&$+4)W9$(Z9YNHwP0AB~?JVw~ zi#Jf)Lgm2VS~W)$@W^r5%9LaC)mESWBr&*%Roo*w82WWM1;_K zWFP8>#&a=-U_S3~Ct!WVK15v(bvTf7R$HkW(4rs(Lv*F!Ng&EGa>jPEA#N&cxBwd%_h!*fNdFQpvIgS?dV+jD)S@OiQZ~i&q5g8M< zI&T~Rqhb7AnF}Q|y{1-(nV|4hwpM=fFoaZhH8GkE*|@$*aj7Kw97rNiJ41#c|GYRZJ)~)T=}S`5F~N2T{!*a0 zQlgTqV?-y0jP@oN7uNj#5pmb{9Np5{8Qpa&)!A?WWEeyUew5girO*3Xp9F1cdUnrO zHr)8nbZk#xJsAz>p?OjY=Llty1BB9-bf_j{(9LM%5K8KKLu{MOW6({s;@X!G006u= zYON`*P2h4tJ!x(6K@cfXZ;Otj0vcQ@sUOY_ZBNLMmn?x-IS=bbvS@S4HD1-Fve(Rn zIWlctkPP7vkfxx$UBms9`37E{K6!5efVi?qFYCFGQX)1lr*`$kaiX4QC}u`8EwySa zp}Mw7eZIv7PxMwJm7L-Vhl)*xYaP1V!hsTSG@TA*ujTArVPl^czo6WT5j8E!c_Ziw8g_Wr}FD_(qAPGe8k(6>xcOC~yd$)#zF1tJG z&puvA&RF-o7}2Gy)OL1yV~}1OZEA-S;vTO31_S|ytL`@*8&@|;JJ3!X+GHX_2kHXa zHWZ71?84EVIU{Mm;I*ga*SQ3sTWGAhHNl2ZTnSJH5=PQyqae8k0{F&JH5IeF4{7!n zc=ego+1Az`>ZfN}bhe6Nrw@Miaq}hi_59mT?VfIw#LD3HDgobEcs)4>)QCVkR}OE@ zV5W$AD}w<t z@jO1dtg!<^Rc4!MPP^n9Z%q*w74b%@>LhSDJ9^>YUX|_fpld>t!->@qyNjNUceiLK zilef1KG$YPRT7@y9O*!4?zFxAlYFkuuBXniK63>*{pkJQvc$Pyq`$dL)H|Ou`U%A0 z^51a{!~4o!=7q)I+3NoN!W%+Y%r_aY*L@pf2hbYX+iM?VRPZ=s?+mF>DCN}&;e5eD zBT$&H;zG8ai6}MF7`iCkSKDA)eJ?3FoEu6q2kE`oEcBcF5-Tmb;z$!ua-EJ3Kht%f zi3?$V_sHxY0WI5%R(J!3>-G{3bx>R=2vKvN9;)`UEzh5wUeWhQ91cy+B)2#DL$0!&|dV6g~K8!#GPc>uB9{$KUSk z*RnsG5xS)!Hv;}rVdc4nk+(|I@fQ`eGQ&|a`}7gbJ&PiV7)MD*QVYk+bI&9I(2<{c z@2wr4rXdrm$K8#2LbRA6bRYr2t z%B!)S8|VL+yrgrc#5*>wZm>9K^+gU(L~|6~jxU-iX)n<}Yz$r`!=~ej5ZAL1d9eC_ zdo&FJk~yq~vfJE`zOEbkzQj6QkULErK*7lw6lSC$g5RME2d6k$_W6RNdS{b%GJroV z09hb11iRvXq`tlAJ6)`{T|B$O#pNMIpeTx-WxsEQvm|fJ*3FNONZDajNoSKbAK%}L zd^fkeO4w$!x-p^MYKao@x{YguSS4a;A$qFTk@h0<`-cNsS*N(vs(rqn?+Dik8?wQK?EQX<2k}4sT)}A(Y8%>j;c$Ym1~IG$6Qw;Jj@%)Ohte{(OhE zPZfa}BdLw6zW;Dr&$$O(JzTql1b}mtWjVaRGP;f`7DP`pFWQ3cEXCW&Bn!uZ@#{>4 z>dJ)je959Cz|QyLoRv5xKw`n-R&5=l+HSuxpjKYa@DN(KF2wDG7G23uFoI>LIqRGd zzd@SS9NyW-B}Z_tvZ3`ejsW3efn2DVhkYh(MT~AhbBRDIC>DW7w`Rmeq`)mf(N90p z)89@bH_s`QFuA^Iq@oN67S|ddnqWZ-A1mC!g7)?zcMn=-`S11jMXB+kl!&i zcShETkpSwI1Y4jn7$=&JS>>mB;jLc>dk$V~ z^N*q#f;+Sj%TUq|{$DRnJl{(|`Yny)btO9X$>_i!HV2+Elo{pamcFBY_+E@{f6pu( z)%j#E2PUXqnOvRXFDY#qNx6ks6i;$$oB&!<9c@zIox?$QRc{u&hy+A~hWaakjkkAD zuQ&`Ml}LRS+Kw+^rs#ucEe&6R1JH9Rh!8@+7?g88l4>pi$OKo;pq2BsKC%A)Rp@yS zDa`LI>-hjS@|9=$)+Y0v1-MMFOo2$*zpk2+biZZsAj6ARbm)akq)rf00z%>Og*jF_ zYAu>F2~5|L&N;tAx;Q|tP7{jhpn)$e`&9>Sq`F2%CvaY<-r6EomR&S?+ai_lv^bor zXdfqLpU%u9XtB-GNO6`N#xs$52X}UO?@>*eFiM8nQ8jxgUU0#PF56D#PI<0A+-tAp zMJIxO?%S>(^QAx=BJG-!I~<{%z(Zwr`^e_wOpHq+t#~ct+VKvB;JeI9J~rm^5GZ@c z(X~RgDByN7!YBtYwE9_!1DtWjd|l?ke#nQbYgK#pMV z(_KQB3GUC8&+g9NS{jl?aa)1n(kAt!A-Mo;F3SlX=d5>kSr^1d4b5&n%wTS1_{NNp zh>B3=)~PZiE+jkZp;L{_w*I2`(3gR%nWNPG_NYl>30xH9fj3^K5;0{c~YyHqw6)7 z0A#&#qt|^kxdS$!xK`rM2U?f&?%o-JWLCBohpUByj}J))U648>BhpA`b0x=Fbsy`H zmEop`9YG6vAJzgeMW0m{X-Md4-UY-gPLivS6V zql($>Im~nL{dxBs>1iJhLG|Q-4PkO~1D%F^M6ePg3PejxW2J zE*WT=)_P2@`E`pAzYGg+5Tmda2pdzP%qgRgl1H4wh)NID|kwn_GQgcgJav z#X5a_(r3><5veDq8W??@wYNgeew-8hc0l|na9A24lh5S?B0`$g96dVBT^CHo10n6Q zwR~~#B6u~FhzlN97K~__SL6ms6<;{!^@5aIBY|&w%*Av3`WmFxi;lKCuOiz4SC-J{ zh8S&RJ*o{}J@vlQJec8Mz#Tj`7pn`~D5C{d!&jUunOxo?1|cxD#XffDv3pQanngo; ztQjJ@q6H3IN67f%(pxj0;j9kA<%+nSjO|}5>;Ikuc2;+8=WFLJ>0wJjMOrE?%1ygc zI&<@GWftJhd5UR(P}&o!KvZIAalv52p$*h`=PVv|?Kq#M$Hl7~-8$&J?PyYJ5lx6% z36*A6dV_&0&En(K};?OO#y+U#iB=QtQ{}uMnWi-%IH)CuL%`L z%H6G;3$*Qm`F#FTujRC3)lREAyyjK#yuft_8)9vAb%TI6v{6i?Hj+ZZwT^>N_t1TV z{vY3DtgfRkh61$p*#iC3ceY475UZ4lu02sag$%*2KtK*^^id*ET4`l?nYrg@9IfJ1 zNi=W~!sRl{Y2Z5RGUm3qE~sKf^T`n$h!`MR(Aqll&JHgc0}64M-ytTp|MC&JzK1mX&U|a@-n2$ghgrC z%^Z)86kYvRCV1=Wq{f?OXT52)U8f`|C%2z9wdhvk&u zQSBGhpB|!%L^=i!P0#V)@|~* z)X_(#qgUDx5i!_tywe&Sla+{R|1+{qMV>*(>jmP1N4zI?+2}k}BtKs{0Dxn@lwC>v zm8PXFSz7t*`1>#RUoH!wYyV^!Fy94-0_Zj1ymbR`sf1MYjwwznIJ>028{ zKnFmPeL;iTCyb50ijLv|@Udcx)^pavuGA?W+x+K$Z7(K9Hh0l~O&=-CVUg@$B5 z!}*Z;fV$0-$NHX&5uzb|o7ZNsSklMm8tW4OCtV|0;^K0}VydJvKr$$6%5D54cRLX; z)O!o&_h+_AlCh7r(#q|1@&IDKq7=?Z$1ILJAYgOJg`w3P^ZEREV&ElTyofN_r~qhF z>bWB5NdUXe9MC3o(Y_j@=#$3MJj>{99k>lH3h_c>QCa(IAH_EQc%t{Y?H&{{aPaA4 zq}E(iI{ZY>DRGvv2K$`=(`(x_n~ix|I-r|6UpA2N3nA{duxFi(-jHqoFp{nJHHqrd zglfCWogvB`xGVBAoRMoWA^QrSwnpmuya<4`&&0CP%`4wPK)oSMu1~E5AmuI=Z6dWp zS$ZHKM^NAGNN0!5cehF{FLJNOvW#b5QET6)k!o{FxH@Gq?Ydnhj2B2PfK9|Vj^^3YOb$ayj7pkse-g{4QemzTXN=67I29a)> z_Cz+{wDRxSkCZq4YkoEV(=m_xDvY7fcl*jFdZ9&SkvDc32HSCqXaNU-#e94yh($$%`c@ z^b3q!L7884?G%TO4_*ItsT`B*Q`$*u0p_OboFhxNqtJr%uts;)pwV3huh(tq&;82U zU!E{RD2#JKa|x8wtg{`ll$EHt;Hmonz)OnWuDw8S@c6v(w^D_OcCdsIf;Fy`@V>U; zI{C@yH5sL&aM9y0h1^O~Y-8sgQ7o|N)yj=r>!|N9a0lt zCGAF{DI7jpnM>E(J$jGV2^=(5TG_7f`@AWm&B5priYpcV+$aI&gw{nYJZ&i@mjvBU zxuv1zhF>qDORLF_<6U+7ZVp=@mkOAeoD;#y8O3L@X1@Q!mc^Y#4x-CwX%=2h2xhrJ z_ZZethPH;qw8UMWP=|I{le(@Q&PtEUdBNh|5oz9?HLs(o@B8&6$-eN^!%;Fd?eXB7a z&fc{VOKsD?ZyTb-^R%#fDI;NCo&(tyHm+|H#nIB$FE*n?tu&*ZL-VM%%)mHu{v6|Y z+5B>}MpUdUL=`6BE(&hT=cs-z1JMB%?J!4Xet$;$c+vmHfC`aezwrvk@t?~Xx&YHF z8|YLSx65l?B#LDnix^0cTW0t7M>x^t^+`Ll(OHgsZhs*#y|lg5>s+;74nn9fX)EMj zH2Wu3*7LIJL!W=xOiZdW?`cK>3O8aTQpI5e$A?F=V={UEU)Ck1@6j!zp@38{y|Kw+ zvn8PvYUrn~EJSmALTMm9jBubsHfiZh!*!2QO0Q!SMaT&-pf6(>5DS|5A{@eew&EAO z0zERG?xA#1a@)sF&pR$1Qp$dq=>PzL07*naRO;8zHvoA+hQGy*%Th+x44kU6ael)# zqdp?iB05gEH2Bz3H3jviP<3;eY}T{b;D)Y=2JK+`8t3tzCf zcS!rVp``t3H*Z;GCe|LF+G-Hx*WKuA_UM?#~=wURS- z$qf7<$gLJ0b{$HiLGNEk&!0THXUv5RJ6>882UwY9j-YMZ6Bf?b8*NC=Mu|OU*EFLWSjp)<-v9q~DW0v>cXIYLBUBiOfy>6P8l)Em-%Sh9{ z&~RqYC%}1OioSkJu676``qGa7}-W zs+wD*T9*`2VSf9lZ}rpJo(_>AOWCqlH6OBcuf4lBf#On0YzzEu z;^6i^Fe)vw7blXazR+;=P+WhhVDrKzB5hu0Ob@zY_OC^bz}>}aM!Wk|eWL;Z-E4=V z#7i*eTqQe;9UR@tkStc0sE@ixSK`Hp7MFvQeUJ6gd*p__ZW5@jRJ0p&pvJW=q0h~k zo|Hg(9BCgn$7H<3)YJuu#u@cjHQZnmLs=r;=MsioX3_hJ9col*nufM77kzcgV+aM7 zkvh)wTt#}{DmMD+TNj@++{m(YdNtasRhLTSlBW)BA22doX~9uZM|l9V+k5CDv8o@r zq3tnu=|yKnfL0dh1x1R8&w&>sFdmXe7N98Mp)$XFn14TY@ZvXSID+}T6DY41RGT5^ zmK@OZYpCn~mpliz_epyl8Z*7Xqd6*N1%_PTa@~>u1dwZvb}MGi8QPc?#+o~@`EBKQIuP+h3-l_zTKp{y{|dhV9k=wW~_x_qs%S>BAk-uy&2 zh9E%dV8@$*>9vg>0br5p79S&`4T%L_6du>aJ1xwV)U~=?i(ovPJMGRQK0k+ak>p{X zQyQFE=j=IrBUIXTb$~h~t}@)vBe+tSUfG~78!P2$m5>r%BO&)6pUfTY-G-yx*{B@m z)eP@*zi2l^^ZWfxd}YLKoj*fk&U!HUmvupN?~ujrJloEZywfrDcx|H#z!^y` zhMW`2_G`4goMv7NRVCHY+DgC5;h?C(h?AfTu#HeJ0?r9-YOO5f4H@Gs=2A(3gX+=- zdd~Q;QlAXyp4|o?9mVd1gHLB@?Aq=z)Dy|NjQl-Flr@5<-5n4MUQB%&I zH@FljYySVt{b{sqS$5Y4{#LX1X>Nb-yRVBjGqMrNl!PRNB`jft00ROHk_^JeSQOY` zV^hQBD*U0K%3z!F7_RaVhN2rTFbE_;feMW1B?L&QK`AMfsmzSXjL6K0c>Q~~zxSN8 z_g+nXm}~95&$;*Y_eH#wBl6wT?PjgH=bFub{wMJuFuglV!GY(7`meVJDZ#s}Fk1%3 zbSRx{_Xe4B5Ett3)-nD-N;4#B_5>$B0{|`Iv|eeEylMlw!;2%_awT2SLgJXgqoPYP zQVY6q8kydmrmhS95`a^uk1)I*SU?(dpRC*wzIPA%BH#z)n*uV zikP-_nO53lxfTLz+Jo7JV?R8KbbnrgGru-g3^xbZ(h_5x6pT1-tsxT~s&dTkRKz1% zvWuVt&x=bcw)xc-j&chhXw5m^| zpPr-9XC2q8hG?2LE1+VNbbJFeXzf#NVCpGt)l>J$2|f6#%w3lm6{cS?Ozqe*xMZoz ziL_LT(#l8qCK)l3Ik$C??0+r2e*1|Km9tsTLbaa>FY3%?-}UAs;=u-rOJ#y$>Q2sm zgLX}_5o%1O(ff*cThI-{1Lqg)@P3KjISvbI8;X^J5UQ>|)O(_@(;7@MF;eZ!Xxgqb zKK1c_zDB;D!q`-bn9vk$IY5+BI|Nk~x|SX308f5LExB+SIbfc$C#jc63IuIv%*eKZ zqZngKTEsT!Ra6##*HQ1+?KS#-dF3fmt8;)EKf#1&XWAG^c16<}>PE%vqsTL?b#kuX z+v`+HxCb6KjIjjgsAkVc7y6Dp;f(njDvFH)GcY)&Z9*$Md;q%km?O>P-U+eE8Ee)0 zL-WMI{qYnEG#_eNG1?lm0Rg$D2BSQMN*%5Om`0;^BH@lp{sXA2|DKc4R@`4ugiUEV zF2v)K{TKhk19cnFJGp%Vb>d}s>Rxlbxm9Y;=Ir=DX5SlG&w-u$%X!qKx;F(@q1O$?r2=Pt3+Yn6L3x)Pz6u)*)!t0t=(Of|UOCPK zY8%No1g09a3Hx z(+nD*#xx$Aq)7P`+>IW8C-NvWNjVuWMg~aQ2Le9B~M`mz@Vj)PW zoB&Ww{#hV;i=JupKCqh{RLQOPP7`@%$daK#UoKE1B`5_t@2{bo7)y@oK1aZ+9gVUs9?|ncfBVLu3Jxb&uJu4xj)zq9$to-}qTo=XQ z%$okTd@%&9HG~kUQ)|exd5+#Y-9AUc+LI$69jt;{GcDhh#-oE|dI4T-IIw!UOSk#cryF`*Gum42A=m>tXelT1$zJyjgQ>#Y4XGb}wgH|aWRdReA{P~L z+lcd@O8`>mju=H|RBR|b%Ok11#u6|4&^I%f}6 z)Trp&P6l2{57g<+V>piT*x0;Dzn3fw44GWhJg=(2S{W&jcDs z+V;b$ZyV4Wza=p(Ta zL_i==n1be@rrJq!-a@(-7 z88AmIBIU&aq0C!?O9+4r&yk=@>Bi`L0ro?JiK|njE~mShoYO;4s3g-Jp=&$etuY(X z0pddTKcl^#htcA(O2z2P7(WVlrBOb!yeDHU$aNb(kQ(p(NQrrB>iN@#WG-1ztq|?z$FJ?kO|&T(M~a{H11x5KT1fEUP+JG4k-W_TB@w`o6PW__d4SxZ!K!1 zSbAY3Y|Mz9D-W@ec5fl+?J!Zedk&5>!bH&-LJv9rlP`>nWr$ZGSkWUn;9}hj?F6#x za2R8$?^VJijz*?1C2R zqgzx&8{9@woy^j@Jd5i++ql(0Sr!k4VhbwA6QjScqyJv(_C^0lc2S4DTwqpA+aXFj zCA!>o$})aIZ-ia*yrOJ(RwZ0i%K;k)%3mV z0MJgdde|5G^Aa$|P!s~Y&{n1X%F>c4_M*9^wKOL)LhaII%9a#OOmp3z-lsDrPbuWf z8n-MpTRvuzks4eh5g~+3M>TMA`CTjTx2B|Q9T;UZibOr;MVxV2XSDZ&#JOO)_M(eKbopTLI-k)l6_!XmshQoG3ZF|4p>_(P_t3d~f-zLYOW?GVddn1m zQ&D45fAm1WYQyyI1b5g-*+p{b&OONTltUrTD7^rH@ft#MD75^mwZbm2(Vtro;1rrV z%sF3n*|L0boFK%Yg98-COW?~#k7^XQ)~Ew|q>C|ir+L3;xqol+&!8+Yx#Xf}a0+p> zWaPBfXsehUAGfVmpZ!RaWh|z*hn^*~8L{y^mviMnZLl!fUcxL{k(VSF(gM3CxUSA# z?M2jHm%N(~E{0Z%o-u2WKeFD^NOz_60+4_wE=n(YPvS0;pqxLMNoi#rktB6|HswxF zF-&TMKH3;itSN%6P|9JNT&mCzeLyvea#qmnOyIc3ALO1eK{wC;w=mMXxy+mZ%P?4z zwvZV`p}eDs$-easwl=uKhRNdT0``K;382eyn?8tm4|3bg(*rJKfwjpo+s)v2yiqHe*Fleb$Ie`FDv4jllc!$ zqKjTi0Hl6V9zb1dPOcv#?tjO4se3Hy@AvQo!q8(j61!*+QZ5|e1m5MN$3)ApE~&4b z5ci_A-68cKe-EBgQ`k8<@005E9nwJRcENj#vv`o4w|!Dmv^2vp2UmuKq10X~pGZYw zMER}`&3LItk4GtEGv}l$k^-8A+z-$VJc2F3S(ZaCwe)O%en*U1F=O*EOR{ z1A?xxA&4^f!X05rey5;L0+7sYVZjI2*H&0!Neze_}~sp=d?C@;g43Sop#b&LZwwGFOG!+z&QdH%8Svc z8bKDRLJ^K@X17jS!)5+_PjaCPKfVvMz34wsFBqDELlpw0RF%VcF{G6DXs0n#gS*oZ zPo!@|+speo8-YMsq>`c}7hXl83c~pkg#6Da3p!F&$7iBapY-hQ8ibr`O3r^sc3}x- z%TQiU2!ProUZNSg_TU=OH6{kkQAFJga2N?naaz0gU4~3SKy}K47=9DJz1ntn9hB)e+dQG61N?^jP3LmxToO_XzyOWj@b$-nIMLM3h zUgy+k6yJ;xBtw!y9!k_c#^3}Ae~L?g&Gr6_zsb#sQ_OC1l4pa*iB%V^^K zxfZVGDevb21S5Lhh;+|Uba4(2v}iLJLs8h&J2gksW2*Vi--=kEsS~_N-)9p&Ylfd< zx6Mk+Zdz#_Wl~*YBbk*L6QPw;m=lfPbHu&CdDUt^ixF_>WzA?y*yw}K`1B_AcCBPB zJm{H5-3AUN>+5;;9SyqLXmej^Tz+4pBoiH;kBxLO$fa~lN`{tnu^!f_LW{AR&<%}} zdalwHa2yDSAq8W4QuIvy?SL^#oMBD}T{7Y#cV1|!>OIV?Jj&Ilk*k6NLb|xD8DA6w z*m$8wiz(ZfvyjR--2M!Iw}Bc$jJcW31JC%hMzApZ7s8So!(6~6b6d16jFhHos^_X* z@tOC8MvXMX3k81QX;g!DQYr-v=#01!C$HX3$Ri2oKGnH1FUX?d-AZW;IBHmp*v&#} zTjhr-qv8pnk{W5JC@RbJ<^(_WXv`e?NqI3`bgvxhJa^kUpC4LicmMNT;(%4KswlP% zanKNb0Tcp<4H0WoE2C&|hmq;+Nvm6E$we2~zaQz*KEsuL07Au#ETioa(MWJDxJ*_o zt)g(^q=sWpIP_?jt}FF)M?Yf~_yj{*0McF`I;K*_{Orbr?orfLGrylbsqzS?{^*XU zdj^&Ty=oY26?m192@XJ^d=J?bV7A{-@75BCX^LC%XM=s3p%FS?FJtMAw+>}Cb^V9-kqY zHG^%tF6fpAArmwQq+Rjk&Jp1_U{Nh!Lc2e;!G+Vr(N8UBMhUy=+>$M1>xASgwEacj zSE8u1f~{#yvLI_~(bl$5ovwx}CPklq7P@1@wz^T|MmkE$8?1i4|a$41-HU>TyFTV{(ijs+wqoZPeC==58bX zm?3owNRtv(E_&%5`TRUWZ3}Vq(;Vk+9675emmoLzey}Uwcl47}Q8Hp$k-9Ee%FPkd z<6Rs*VAWwu*W-JbPiyBC=b4?OJ?PIf{+l?qdsIYQSw@_QQ4R#Q!9#OEZ? zb^3ntoCMU8Vz@fQl`hG3MER~3Un#}V4QTELj_(|xOh%kM3uIA;bjiv4a&yRFV~_%$ z@}`f%e*#jY9z6`}Aje&SU|w-3FSBWO_4asUgs@kY$>)&YAabRA<#{PfC;)@&Y-$G!=;|q{d`tD z!>M?`M=>agiI91olsVfj@?UUHAjjt-C;Gl`XGgg_6nLnl1L5ldkB*2tXm}1y=u*&Z(mVg?i zX}o`a%IKg=#_ODfN$Wm_!KEQ)DW;Ac02XCR2oW8$bax3bd1orw^>DuvJOkrVE4Zp~ z!>U)Ro)SbswHa!wEpFd2yEUPtXi=K#IST+}w3J>gPy3dgii|Q?j;|#b5AU1S)lFE z&N;>TGiBz>0s<*pjBlxUR0@mbWydNs!|G9d;G&7qK_m* zj}8G7xzv=K1L6vJ<=f3(qlqRG6#{iRu9@x}&DTHWC~557|NAv`*QU#C71A0l_?FnM z%l0aPs7FP00BBh=aUl_#tNZpKg0Tb@rok-m_4j3ba~pU3Iypk;se?Z@OzGCr|B^Phx3`= zUUsNWD)dkx#kQr`D#hs!3Z)v9k$QQwv=&od5MAmna2(qs<#MxZ7=`|^pW)CtnP$0W zKcteK#9pi~8{D!_1bYypB`S;eiWnu$uTi+eK(kY0u@6D;Jfd(tgygI**LvBaHx0h< zL{rP29|S__tZ;G^&4}h^)dm1UF5!4iVvY0np4x83?mlDM=VR)`po}I2Dc?CYp5~rX zX12?Ex05cVhfzuY@NI}AD>d;!-uEg%h&b)>Do`j(y<1V=n#~8e9#Bddo<*$gtTFd& zNm4*1XOmoF89Zp!Ccae6b6%fykn7<{GZf^ zu>u7&!nwc&1DlFzAzg}$H|aawF=CA9+ECq1XsNS0Nc0c^k9ReXFv_w#^ZhvlKvFVw z^9Tfh&%lUmdvZVGFiK17u^4;8tBIb}i(H|MW>(h^sF~`FGnlWtdXgJd8HHd)+1PdP zMMbaytF3@pbikWgsuw9RCnb{`Gl3CjM%uYKc}|9f@G;ZGAS!s z;*}TY)k8TenBAH(JDj%nnw>?}W~J{Z=TA72aiR;G%5Fl71aPPn@rbR#H z(Go~$E%n5JtAwCn9vc3B&wYP(0RL;A+9aNz!||Z?N(L*)wGP%wfj*ni zUROqii2hTIDob;FN^??m^Xk={4f^~Hg)zEUs+cSvF9eH9nM7h6nboIlv8R%nxs28# zU1@qXRB$2S2Q>jN_cj&lcwVoUdQgD>rLrK2nyY1S0yJMc#M&xPnq^qW3ML_4yF&PKsrEYr? zC2*Pppz--C*R83sn*)laQfmGULQESwbaYe&y4KiZ1Gj`ow`+uX&UV?Hk0|@7TG9-* zhXfmN!MAAWye__wK(#+nRJUvCz7Wp{nm?-~#@znj)sE?QmhzB2HN?nZZGhS?sfUfs zaq@?P4ie08is7up?={4OCllx=zSX?&g;|6@&9{t_x>9jarzey1y@*Gg_}ET%KeDp` zp=|FdwE*lHBr%HKQAUI+AX$yNt_eQF8oL%ND%INc5k^nUva9E19jh2_4$#8^$`k}^ zh|%^Stp$OA4PXx=lUpY(OlDsBy$5NcM;$|jx}>q=0X`a_Y*8hWY|%J0mPmE`SfGK3 z62hjobk9g(W~iLC7MoynSxy#-FEt8VmQ1IQ&;dZ7`RCJ(GvwT7sBpfYm}H>@wWW!J z9;!hDu9oLEWgSP=Kw4lOHYtLgYNT8~>U^Kx^I((ChDlLajInJHE-+tmk=rmTrKqa+ zw!6qf?x1yy@-R_Ldzy>VkABW!)(WiyN_mVAl$2C^Gp3VCy3fomHSh4}q}zFnJg0fi z+dE06u^k0x<-kOd{NAU_WK734&64>Kp7? z6^q#{rC_MA7YpoqK}gpkPDF_go~VQq#dyQyPK7@Z^pk33qBrz?Up(FD!SeI#pcRfD zCyvepMxYAC^5tdxQV_$-S&@Gr8tGtAR2KFl_5O6eL~U+ciVwf8hke*ieJUGDuT5D{ zY)JPaX^&R4u;I4!%t2WfRCi~D;~ePk1@_hRL!=7=|JS8y+oiUF>9kMEwlA>hx=y{` z=g@2CI2H_P6{A46x5qT2M$l0GGMt#}yfv1gbh|igC`cSIi~D7}yy49Ao#UlH;ClgE z8kEhQfuuvqB9KL=M}IOong8G!C{NW#YXQm_thMdw0vVy(l_sc|F4FhsW%Nw(-C^iaWk!t0GBPy}Ga^R&<1#Z7#c54E4=5cut#EA3TMi&C4XAUdn zLpBxfk2c2WO+#JQVzW3+G~i9ZE01;#b0QtOVzm%RIAhLpC#rM3J!{PzIaG$qXC~SV zI|Ff;HJY>PqR&Eiov#||5j*ra7#1U@#u!v#TScA~CeSkIM-?fGl4>#opSv2I)-aDw z$#owMbk@&H7+xMGqAm%tKoG@q*XuA?|;yoYo5iLB=czq`hvj@ zrDg}}IaYWj{dBO}GTk}G9oNFf+`F)6rZyAA*{0TL{Wg#}5Fh}T(8B(zlo?%=^M{}q z&*yR%qiv<53C@Fa?Q!Oh+evO;hBY0-#NxW>Q{QFo7y8U!_xLLE{3F49l{2G5 zX^qwloEVHQJ8~VYST#`iK(jZ)CmJ_(2I@pUcrqLEtblDklF2*^ArZ+oeCvl6A z8N7KqBmKTMMNeCmVAd3Nn6AfxiY3tq%1IfK0aIzF*H46uvv*laNmq~7=GPtF>*D;~ z?}8pW!|fdOJN&c&mqn386`E0U^qh6l;?gVW#jHU^N9hXO{*>unm2afSwR3tz{NhDF z(#UfWmFfbP8tk@aur(BNsJ6OAZqzH^20)9-;%+t4j#ELv&()v4|E^LuY+1HJ(m+g| zJai&6h8P2?Fz5iY$uwn*&({l8QQDQp&=FqhVHyd%F7Y}5NNz)Z=;F=MUM_!Tf(lV-mg+{qT`&2F+M+G z#emp~mrLx>CcC_AV;Djp8ZauLDwy7!3B10BpnKdMPx^>1#?E`>vl1HAU{h)3g#uM* zly5Lz6Lcl0ZQreXb5JwAnR(IlefQ{R1qFB@Qh8yH1{(#%hNdnjVzbvV@c>9`Zqpdb ziDGt3NEgFGGOj(|0~Fes38YMD`mi-q$fgrh1Tm^?SOttSQfaIeUJ0`$VuHBc1dB$ZZbU?1EzCCuH=eOLM+LuZ(Z zjWC4r#grjWoHFA4S147Wv=a8>nZ@pFxFM0buy7%Mf&60L0XnbXbay1BI`~sxA!{^# zH4rXGTv-XUC5TfURV0R7L)f5V!O884FbR|lX{eL1O1#)V_Pjzult1(yjIp2%WH#Nj zS*ir{lU9)t?Okd~r%%cG+{!-#^mcdXZrla5?EG9_E60DqFjGZF=-! zY5{6B|1XfU-Dh;nP~4A(EY5wdQ0S-$D#$#eD3ENa9*SYmj2a=kY9!n1N2yn|*A!KO zJ5SwM7TvhX_;{Z>Zj#5$<_1EIKMsA(7<;m4bV^ zlWesp$2oJ|%MiBm{@{Db6%;Yb{-QF6azp|_DzAWo(o<}YI9c8Yq>X5-rIf)J!Us@R zmT<>O?IL->`a$%wvg->a6@44+K8mLUD0mE-pp{f#Y!;Lk22@Q2I<;9s98gzAy!Di5 z)YQTa1&2xR$I$v$62p6LO!ZWzCUc^FLhZzuS`%lex1k|0O#y)O-hVVA3NEir$WJra zaY1>Zq#D!$lb&dTjyQw#7LNv7TbjKZf6&YauQhO{snsEQ-s=&7VmNA(U783g5>zi> ztA$f1xR8iy-`k;e;t}x?rM1X|Ldq5peSrcOJid8;x^w~E(za+1P1K6fr7>zlOBr1w zZ1h0~V%k%U*Vrm@boajOfA^WJ^zTD|66SxRA%yN}va1Dl+2UtD?ISuNE~MNjMoU>2 zH1{fIyR)8bKSQJNNrsmFB`!yX7sr?p9YRWbRLsbdfI(V%PVStvt&4MFPI)1=d;Hs) z*HF1OK5Ei_q@}!|gm?)lIny5P2I3Rx&iBY&7yO=Ma^sj>nBy1M{4Aw-PKq*@qR*j2 z`^S}y9FKvaqP#G`Ea`*{6u(Htf~Y)R8MH64lL3<(cL^?FG4z$B=;DY|u|0oBK`G;G z1nGTv1QzE>>OrNaxY7z0!~}>aR17GSg93d9)PUBhru7UIV}G36bI`BHZ2wt+?WCxi zwU)xzR41BQ^;OD5t2Pi2W5hR2ixB7x>C|I=PG}Y-=(I#FihBQIL%&W$!)R-nSQ?!6 z#1gbq*xC|JpedEKA0bfhO6DSZ<|A>7^{J0A*H5+n@4aKlc1u zafV9u?eB4-2lZ9WV9U~kS|D@^peCvTzNi3?Q3Kp@Lv?qW4yEyUg4URzd7_4TJ?B)i ztg203L`+*+!7_x+Ks~JS%433&J=8a7SEK-dg(2)8-ovL!jRT)#Ef5?i3(*205bAX9 z5^(XUVq}wGaa>(OYnGUNkUNL>F<5BiMksQc{dcfxhY#P>G^Hwedt> zG4MmG1J7*tB*{(a)Yszq+w5;V{r;)4hee@C`k?<)3wqOFH!ZWq=VnS2sZ=hi02oZv z)VnotN6IedGIQaatip2~MNy(LEeaD7VkZJh>b|27(sI-_SU7FJJi%yZLIYkW^g*9* zNP;_NrNC|unU*J*#wPZ5Ko=-e5SxafFLC##xD)^lIdTyqb4|fpeWS$jevc~}b3#K~ zn*u{}Z6>2cb1>Tny!V90wRQN zQo&G1_S;JZ4=;|0Yf{&3D}#25U=2alg1B&!xTtQ<=0xK3yg&Uj95O;GU7j+E!A60$ z5}=6Mpowi3I_N;G0!33Wxjmu2H%?tcExh8IG2mja9H0Y#Xs7q^O~ic$I3Pn2rd$ zo_G-2&7s4=KIz8wXr0rQF#?S?J-09fRN7c`rk_BI2oZSYdq2MqnE0gJQrCsGg2DEZ zY)DbEx>=zsBfVaYiZpj8xO;UX9$U1t7I7ozH}pWGTj+VJQ%t1*f&>icMCR61&76W# zFb5Tz%Y%kRH=_Gg0+=#nn*+)#&6sBNyT#?E27UevWBlKr*bA*NW z&U!{do_p@U`G)yp_SX*5vuA}{#H<+FO)#|p)WKs?_`lQzZhuCzGZD0rC`pux_gUWu z4-J?H82Pz|JQC3B27SR$myKkJ5+qszpF!CFy{4>7>KhfffH}2e^yaE>!JHwh?SDzX zs?Qrk+G zj9v^FWAKf`J!c321E+<_!f?Gnk2St6TU4N(@TCyZu0$UzW;c!>a)xmF<>LSb`tbB9 z!l}oG!KHE17oB{^ShvX-;|;@lK)l-!_fi>e6y!*EDbEiHpmYF;L}R*EwRCnvzz{I# zS~0nGgsoFIm^?oUo(iGU-_CNNMfEV8g<^bhi8zABxP+QadPS$M7eQeshPW5uxTo{y zM(^IvJ4n~MHuLq$p>HE)bT$sXX)#MBA#|8NrIgs|iOAJ7fk9O=y*X(E0Bvv~AT6k& zL&%2Ha&;dLsqoNug9eo$XCbzRL|Y%N#0b=d)QQx+{-TzM3#X$H@29^c5vGVS0@n#C zTAKSZl4|OJWF&ihx(6LXn-I{<`5x)s!s&#;eGP}u*35OI#r44$%9jnXaHy&g<&q&# zr3iL0GnhTi;q|GIT{zwIMkUJio+U6Ia1IrPHmVpE47P^Ux|R}v43>!z8wEaUCz{!v zWBf@&2Q+-zdw2vn2MSvVk41<{@Y9DnmxW|wFp<%aq6Qu**eL)j|QbmX8XI$4r>Z2i0P8YPiVNz+Yc%cS~W`kI#9G9g5QOT>u)E)ZNGHz@KxvbwsAFS-_h%1hn9QbB?%QEKbC7hyN{oYOO4 zQVC`7VCVnL7wN6cE1)~sv7pyAb~V+sWWbJ78NnZq$HT^8d8dx0*6676lF9Rh3g@4o)rpU5ydQgfYL@6 zrMvScTUXX8QWTcy(J^)6E_zH>tXV^v``3~n&PSgk|cdDl*%kApZy z=Q8@neMWz%wDZe8rBGladQ~yHGQ^Y69tf9`3In2*dig-aR0e%dNxgh_kVESw^883T za8VIA0PR|vy+5SWg@ziAZyZr#2qYw4w%yKUbUHn+gBs&^oNRa0!5rCku7+i2nW}R|*uzGn$ zX75=w42a^$?+3sXLf9g3E!{;+dyMZfMyh7k%SnjfXdOE5zrBt7+)K~CJu@z#n7ihd z@NQYbW{~z!BBf|A43W+{!L(b2pL!-Yqz9@}ikPz&F%vevKT3XX^GnxcRt)xHL37}M z8Xbyc)hF1DHw+rX^zJckmNEnQHuEpA?PoW1X~<-M8B!E`Fh4@3%Ti2wL_hbd9bT-^ zKi`XOPd@iL#)wJ9+-|5)TNb@)g!syd>l+I&O>Va*^+wg*BiwEyAs40aItTlrgm&BW zozs1!DX}(n7YRA|rsgcbs3H^^Z55N*F}}^J`ng$Mgwo}bfU`hR`YWxGfA5Z;0zaP`TL5nlZ7{ZH@rbvYS~0%gg(Cz%0TfOx$+8TE9}Wm3aQmxcB{pF)W->4BJu#nuev#gRBj zjW``G+C?c`;jzjPr;YF#9Lou!^W>yaCrfEO=oS|D*>+z~Kg}7Vm;xP9N^|0tCXR%3 zF8l4YU(6Ns}$bM z2+?4?p+2mb?B{mYNxtrbKs<9Eo@TWE-UCkPKot-NisFie^?>&g)s%A0O8Do{fuI7W z(YSk+*ot*lmGcCC;eO{z<30g^N6S@~5^~0)PuMfS==^;0sg8}`R zLT|JRdlka6SW3Z0un}92urot6ky%k=ZNMAP$<72FO0%MVjws}Sr_bFo8gZAsd(a(?^ll~=eB4eL1#tBgN|4wS&iv* zcHbjD>|uP`F^4`0y?e{qOrL^3n-E?OG)vMUqMS*saWiPpwKzxsWhmIac}#s=OBP$l z?pZp8o;x3WLkOb4+5iAu@J-l?lEa|`ZrI?)nprs&qbq5%M={C$W4u4V<;=g^EPTV0 z2=Xj2R=8Qfxf(VV<;x?Q)EBsW4pi&B1sy5Tn43{D0}p4YJlCO0jY%8;4#{NcsD))& z1!4)Vh)f4lnvsJBL2~KEAj_i%mf6by#o1B@ea8{80d5c1aib(NUrz4wgNh`YCL z5oVDBiz9V0@bF#+<{o7X%R!4m>&k2rqNb-uy$`*XskzGb{Pv;lNHM`sDu!r8q*ZF4w7rs31imfl`-* z;F%nEaP-cG2=_hD{Xcz#`B#Z=scmVk5{<%XnN=xhD3xjp5P^CzBCE#dA(sy#vIhCV@2Z>#A1Qz8F7*ChxK zcr&C@KAjK%TT9sGAyt^5Vnd9D1czcq!75ax1m$uV+Y;S2ll_QV;UeLV zr@l2|Ksjf+DWpCpJZ8Pq`Ha&Gt{cD^Gc zyE-UlNWp5AV9`K`Dbub~Noi=y1ao5Gy%>46v{5PPCJg9v7P=CL*%k%WbVf6szGv6> zs6!FEU}jQiW~wQV3*s>}BiE5hdm&3TDiZ2I+zkmu_mq=(-_ONRj{)f}0$@FA%}`t_ zMJ8PAxLi=EMpL?y)!h}QpFZL6i-+C0RI&$RZ~uJ`A^-ufyPEOg2)iuJw-=dlth1OS zLv`mQIieYHmx6##dms1txlo&U%&L*D3q?TJy+mz-lno|JtnIC`^YeF@ym^dPg5cMN?1}O^1XE;7!2B)OF$7OwdxW0DJ4bUVN|j z_StO!7eRPuEP&RUQkz^}*R@{i4QmZ2N5|~l*_HddUliyuqi6A(1X6pefU3cd z0*4$jn2sriRLdNm5h?6I~((qt82Z~g;7?n?YqVH%b ztkpDC&HlZ;6heHkG5R#K_|Wg)2YR6BwSv4A37@D5-&j+8ykI(>VP}To$fBLbG@5`R zOagw-Kl}p1(*$8;%+cQ%Apndj^|OwtmRKVZQlRt$*bnU8-k}IZg5~FV=y61xagLY( zhFxucX8Fj~{Ad6E(e5DEuzNz)V6kW{vv+GIpEx4^rY*|Vveg|@uU!e+$SG#~Q`|kr zIiS!Vc?6LD;8wQ*NbMp%!MD*d5f>H2eYkn^E(#-LqP?f6$KJtWq`qr5muuDfYmlFr zc?!meURZ_2pve7#BywJVGZ6l6L-C!KxB+hHg+#9@B#SY$SPaeG3Dv=*m5q${Q7S%h z4qy=})E+1O;|W5pw5358LJu$-V$sZoQ>vwkhd$(QRF6Ko>ZPU+^6K_zvq|dy!y;kXFy6 zx4T<)1T8Is>s`n6wm2O^;?RbX5@woRiQMzdNESADdk0u=MAF;N!hBhgj z8ar;I7!^txTvNB@nCDiul`pLCjHf_OG{W6dY?TbQmYBr`<3}j( z{FT?4{Pd(3_Bkt+a@HREY#pZd$h~@p_Dc_EmS+ET6vZJR$61VhPvVA&D%_llm3g(L-t?BT)lZzD5p93^dY;SxW~$e*BM;y zpwVd1IFz!)Dlols0*4E&z8`B2^B?!AsmvuP{UC7(YO5>J)r~?$L)4MFs3|EK+#XZ? z_>}8^;~i$7J;7j!jca$jm>q2Q>}2_I=0Kxx|9Hyb3%hK5`zBmaIPEAy>VlyqnGsI{ zC%309YEEY`df-gnfJYlq9JHjrRbL-y2smO9FZj-fKnwo^_G?&K)|wgDQr{bM(=Up-*_6)W-_HyVN?lkG;O zQI+N7<`Ho!c2rDV7fiC3J%X%z(5*Z%2Y}KBQ&>Sdh6SGpg*KY$WXkTXyVR2^mBVJE z_sORCi6K#Ez0>|91}+}-E=jBaWMY`5h)dA?=kK<;4cdygymopP8Ny z4}5=44J3nV_LEcY{J9&v_8)%)wUWvkbV#I&ve}18fICQLAaU5J@a%z@(U=yFu7heB z(IEj8tf8)IcJJ&kJvh#}fw`r7zvaBu0Xh122uJ_ykasS8nJfR*tISrB4U5#e#z%&J zz-)JlpCG72PyZ4yri4cqFz6+kpU2@P# zioZ{V;_~;1Dj_=ZXJ-UGlFj)*nL7h|6>x&gj-I0*-{Zy)8m@lNOH40SxS^LUbS!Y* zp{-^*ol>W+3sJoX#$pdTbLi7=`Yk3G=X8GPL_aYHVhVaLd|&~85;*y*2i)4Y!Rm_}RBJWH=Q{6* z3ywiErn)`+JtHCi&FdW9G*gT^xc;*jHi ze8Ag(=1XuZqKu|Cjtta|iPNL+^7d)nbnkUum;Tzs2dnDdF=V?iiR3IQ>1~}Q-K8H` zO5D_Q1vVOnH@I%$qBxUnKn-LS*OKU9{CKZ7)Lza?jBcqoCI^WEbZ!$_S}if84J| z^AU%R%vGMX_oIbdsVp@U0zrGCRp>HOR0Zaaq56>tZ~g7J;ZDSUMIp7_8KD+)?Yb6S z-p+Z)t)U{q8PK1}#dSF|Hs4Ez~5fYPIbf!aZ-sBOdX?lG!Tk}xiOZbpFb7=6!Q^W#O84j-R zw+H};ErBa@fxO2Vz2EectLbpr+!`#6q(hf3@I{cIz_dga6NYasarf`tWd9%TLKQI| zErcToLx?eTr|I^b8~{@-!dIWZmfpP2t;d7rJe9Ueez51%<;1j=y~zbIQRAn9cmKhc zx%|S5tpA!#jz)XvK`HH1RU}vmH11vBLq%yF98_1vqZX{Je1D7M%mBcnJTEapJXA6* za%59$gN|^tcgWt(4q9tg*H>lZNiEZ~7AN^kvXP`b+CItonzRt}$w?H^CwB03%(N`M zG6R9a2}5f{)pF=qNOUB6EljP2kS(c3Gjv0a-3cfD5LHGt;sp#EAGJJLI%2esGjrCO;30$X}vdOaE7?lgp3(vLYP1jZha zh?qtU#K-Jn^O*Kz_c{c$HsTZ=9ka8uOKcpg8!IB`O3%r8;0*47zML!QS~vAN2P8Sy zTA@{xKCwy8$>NquRJ0c3OIHwL6gfAF*hn9DjF$+t*9_|+)7gZBf3#0|^)}nT>oOLnKH(Jqi#+m``iNQFX{Y?ofWqh}Bm% z3B!<(p<0Zf)bm=!L{gexXOb+j7KN=@Nl^^JPu{0^`c!-)`9d;T@JYms$Oto9taWpoobes1De&;Bfbl>gKGg2YW`g z<6<^SWy{@Zyb7oy1t;nf9Sr-;E<5Et#=miimF*E~l!=!DN_FkTl#1xgq)%c_&xTEr zS{?<5iA92MYLp47RT6DygrF4!jSjx`Dq6y)CULa*&@to&Af)_uBKot(8vmt+8~^+o z`h$k`e|v+;`V6=1@I`|r-e%<+*08H3q4b1dI+~9n-zI|20S8Tt*=frAt-!){ zyGP4fshH-xHFQF|pGjw#E~}uOFtxWWw*q3g#En)-&pcK`Pqxn)` zV5PG`;qgU~dgPuZ zo&!4h+>7m|qDgY>Gie+&(PD`Z97;L7PnoqQq>@C{p@xDc)E*yG&xfFiO~cZkv0VG? zmkG^fR*Ds3qj52nOck0KJ#}@GS9yUhRnQhs;w$O41ynCi(;Ax!YN+0waq^`T%C9!; z4UVwRvT}5Z;V)^9f8vm9fBqeozGjJ~Ke~kb3XeA>wzh)&D!dRIdxZ^v76Vu*MR0N= z3j~{<4W)?6wDZ*k5F#-V+(?^FON;B zf40NDPu!t6RIDtoQd`$1C<>*)d1faMYe(0UTj;gPe$3Sfp(~|}il(aZjmIhphIy6B z6^)@fI^pikTbN?N=H&}$n}O_60xhQ$-#nkhygidSv(o!15Rrc)rF)(2(kG$Ty`W7F zKBx%ZM1lpMINr|N9QhiMghjy*UAwk)~Zc zx~Jmkic&7uN=)p3stC2Fx;`Tu)~KeD)~2pzbg)h}t*HNt6T;6nEdBl!%KvMD+9)OO z?-O@~Q7t*JG7xN((im-9UC~d(#27Kk%(ZyT>yY5<$iVcaBL&Q{>)}JVq zI@v`c(K3fFePRTF_ny6-T{gBigv25Qj42>^c6N6;+B;xnX@$*;o0vfW%`QhmQUTfX@fVqFTiK>gZCj}-CguG{z06}~NV=S|y8P^WJ z%<;V=R%c6Gs4j7Ebw)Gvl-d#x9Cz;B#sw$r!7d4EY8wc;je>{yo$&N{fPRk*ZT0{=TMxpVCn*M9gK z!^?NM^sQGoUZ3C!&(IApw>39^^c|XaXPsV1f?Q%!n- z*08s~%l^GRhUI_@FI=S<4G<`a?c^NQWepbAJs@!&i36$jxyTB0Ue5D6i1Xkx3L?$F zK9zM!wZe4If!3CQM{A33JnvqAo4fy?n~cnerQbDX_k;VG%CL5{f_@!#f8-v`%{oEa zld^MNX-hvMd!9_puC6&eJYb{P!Wd1HbW1d_yT8N!c#o}b-)8;0FJV3^6KE>wQ`;Kd z?YwA$?gCYs9%FDapo2E;^MF<;RiKn7rWSE31sWwV(V!E2ED#7mYWj@|5-1E1${Jf6 z%45rH7^qezjAtt>|Agkvzw|k-{q47T=_Sq5w~c8=4b-p}R&h51_kQ{|?p}jNHos$=t?%5#UL8qk000e272+($1U1q{ zcMeSlH9=e2#BV!~E)5&xMfNB?>k?g*^ThltW$?ddbAUkm|@rM^|O z`_nsI_*Df7Ld{nMLFKX=0BZ{OzPZ@+?iN#jjGHA$we=$6*tFtN@4 z=#WuVeTQcOm7pOin|@>Go*8kBq^pgJ4&#lG`bBYsLog^Mgm}?MY%LIaS2}DxK>xJo zi~sXy`Ql&rJRe&9W#|uRg7xT$X6^4bh}vn2Km!Cf=B&qqHVCEe@#4!GVy1@QE+PyY?AV zs*qaepixTfs#qun9~f}-KOJ-Y_jcIUtC;N(hpSWcFjCZ(qnrEe?(TqvCZzM^nx6;F z@xw-(w=Zl|cpZo~w5=_tZ=7)LU%kuKuX~ZJ@g;`0O57)EuKmn44sPx<{sYT=;8(wf zxuTd2XQFr80BlF}CVQVpDUVV`8wAgMHm#0N`=-cvM43Vu`J*8qWhhFFw{~8A^k~;{ zb(kh#yum9)EF2nXU#X&^S@HxMxcqf5@wxx|&vWo22du2FU_MY#hlasy00Y?H-(~0C zUaP+zO;smFDb$0C8 za0^4zwj0$M%$@=z+4j>~x6g^#F-yC5K=MX^eJsVjM#MpuvvVMv&!X#4v{EWBP z-=h5XRW5valck#_N1r?5b3gT2qE~GFC)-^8l`mj6tRU%9rSK0*Bi9< z?emZ=F%@l^uYfWoSe06B%DP6C=T>UTbqHb)C4{}`8wmhOx09};Mf8#Ijg}XF%JQW@ z@fmjhU$+?lS0n7Nw^X{~!o4lbzlPg??>fBh1-XbMZl0dVFkPq5Go9omF^lF>=IV13 z?)}gXm-Qw5mPhZFRG*k~^M~Fhjv^QT!L$%Xr5q+|q9@6}aDy?{comICc}qQRn2iG)zhaHu z^$Wc5=ReIGKlWKZ_~F;EU$e}~<%;ziYq(ET-1r;s!o4WTIRv?zEu*&J-hoOslnStD zQa%YanuK z=O|ZPFkpHM7h)Tgi^-78BgT~dNNkiU5zu()?1l{n9U{Jfy7a7!mI=2S-nsJ@v+Z^%7nJZ%ayTxD0zwwE-RK^S>eK;yuiu_HaYo)Bd-0> z+cf{OVr#m|>VVVTRS*q0MePl)`uXy|R7dcqj=av8LH8y|4I?V{CpF3gaZ{B17 zhws9jya8pD!Fh4d-+$x{Y-w$Ut?dgGgMzwlxOeX!)#RA<)peFu*D-~W{>pYi&dE-t z>Mkf0e3mt8a{Te?DqC9{3`Rp{uHo*{Evgr0 zT>Y+>SpUsi?7eV6wNWRST+=##LVw;rS_cJQe6NLHW3ZX&n=&1zNU{}xGJV&f7pw|> z2K2-xrz&7@OtDxl?r*X7vtvH}7k`0+y*)nspL~qb*AEG00sS z==W+QQCiwsXLECdp)RPJn%gILs6J5f!tZ{Wm2X>P|LP9aN1{fQx;`yW2VR2}o$|M8b$ zzQLk{q5AO&*Z=A}On>G?NEcglOV%+wk(jqSN%xOOB3A&M#wr6U;x2nuziX2Z{EpY~ z1JA9WzRA6Rc$?B$uKas1vGVV%bMGU2OqXVD_C}7C4eqRyPs@tTf04fD+rPU}&V6V8 z9`u}C%kgV812leaZEae!85I`Gg*)3U|A^%if8nPnu2??wJs%}}9L$Mk@{`BB^Mh~G z{LB<}l%TWobxQ3SJKyvPTX|(7tmGH*;Pul;~|RN{yV zS!l}gC1-#jWQDorIg|d$?<{Co`XT}938JR;a;exv3y*_}io$EWiue~Iqu(^nCqeyPC_t>N3MWu#8^{ zI5!nrQ7cp|iK=dOOFoxU;7x@NC0+$g^2Wqz=|OgFnUXywwFH~b=$Uvrlc$|RDM!!| z?VMx^qX8>xVVy+>MKf~v!mzr(#Nb~BKJ}+QN%?uWeEBlPXh2hzjv=gu0D>~ z^7z#leOoBoEk-F;wl-N^U&T4k?!6uAx@LWIjpfx9l#$L5DwV;-2xhMIOr^w5NH$A{ z7|nKL?Aakwnk0-cRvWVC+)voGuy(B$Y{lMLQ#X#7mflpt3sl>{czH;5G~-Key~*gC z2E6=7KY;%DfP01cW!ubfV`x+N+SDof1;#Ly)WlPzr}Fsx-CjnU#` zz$o1YyYfxg3#J)3`AYjnDH+&RB z-778Gy~HOFT5wb$0Zf%Mb_&_3vjgVE5cdELK}-MhpauGGYlEqz%Sg3UvwFP2@LvSp z`0qZAF9IL<4?oCpdBXL-`3~ww14SsQmufK@pCNJdeF>?CnvIn;hIPq3wS)fFf(zes zh4HUgW@@H#kJf^vHIg&jIYSR~Ryx?wX5_N7A=$eg37su*DHtGgTK33na#g-urxX^1 zE&vmxWI!p`>c?!mLBP(3`))#2LJ<>Fd1aIfKV4BwGXr03( z>+L?#?$0UH5u0Rimu*%ws_gjZe`9j6G%;54cU0}%^aEcyxH$(DXc@UJBgThACZ9Ou ztv~%KUYuTJ^ar*%zH`Lgzj7V_W{q(cr~5`}FGvDy^h9@Y(MOy32chcP*1i%H2&)S9 zwFcEF!g}D!Z+(&VZ{FnS(mrmiTPHilxl^bFiyO5^Pxv zx|}A5YT6)7Ke&~HGX3wG#zI zn!Ly1SvYIn7m^s==LuC4lyn1lb;x8mL4VNj!na-J;;Waq@r^sw_C$0g3pSkw%|Pb0 zo&OprPoY7T5{@Q$7Ut*K^@6%xps;C!j=Ck1%|XYy4MG|(-LAZm3R~+$udAkDomKAs z)Gglm-p{f2Q%kHZZ*ec~Fu8L$C)@Ku^z$EmBC!5C8f92oTc)aJM5Wl+zQABmrsu(v zQJL8`>@QEU zW31{?nJp)Q9%q7eC)iHUiR0%@NQt8+IrT-7b=M-|1pU@qUvl8hrn$_?iZ1bx z=Uca$!}adTV_Od)-&upj%sH@8Ma+q&oQ>H&+2rOw`Z8bs;Wt@cU14*)#=AfF4)Lvk zIZ~J?q~2}2z#u5BpyQKKi}dwMxc`?llHiPMu>A2gjyYoaZ8e7%r>I6J zo`8I;hG-&24ap_kEn=mo>*cwy=v;DPG*J~vALpcpol9JFS0(4^?DnR8znkMG*+n@B zt0?ONHC0$QWT_c(>wo_;xBu$ftiQa0`EbeIzjF&-57-2|>h{s(E1t#ve+p8UWS7Sb z0L=ZqM;c?SW@&ka)y%vBM5ksfNF>domKu6(W*(l}@E z^kqQJDfjM!eo00Tp`qttUZN|-5z}7dR)kdK^3FOgR(zJ%nO$s%CxQ5B&oGn(ptjOq zU00x^WEG;3S}gU1w#)s-yqq)VoGz^_v$C;9IV|x}j6H$SbuxKc&gc0lPRV(%RN|54 zJjpLXBEX_7RcnZLa-Oc;^aE#-c~S$*G@kJ8^)FIv6jXZ^;f{kk5q2SP@O1KLH?(XR zZTM-Jv!%dTvGGkCT>d>*3Eynl+dcqbyg$Mmd5jw1hQ2jy=Szb+`4z*w4-btJl{FGY z$0{fl(TL$Ffdi8=6keRC3`1`t>Jj6U^B5#JP@Gtrfumk+7#tN04odt|;NS(R1-N7$&Cf{U6kjLgO})^0Ded~KEKFYNQl@BcZ*heM`sPlyMhw;?YI z_|svF(l&AbpZDs+1wI?F%a+T(?FE*f;7p_mo&5(rDkY6rWM|d>Tn{e)6v^_$CFGzOmqi zKmIa&Tsi?MU!=M2|HcW~ZpPyUjiyW-0L-;ioqNVKM3ZH@3j)Lh+wB6BxeP;shy)3E z#TY3P+}DL^LhyC^EX$CQp3C?X$5rtZLQG7v;RqHNjwkX@V#OtYKec{!d z{I{}hQeZbwe)EtI{gDq-eQm>Jb3%4tOf&?lq-(`{%cT=gpz$e_mdY>MphZFMwXTdJ znj+~G33N&DTjX8&vJEEYkpqi4*itA^(cy4tC#5d{&U$PxskA}kM}d>r@G6&i=X>Ac z?w@)GJJrl=L#!5w!_KOoKmXBxZZutfXS_US0hhgqo`(?9TGB5A7 zN!Q0fQ2LZT+1-0TAfy&PTYzErf73<)Aw#USm1k>xyvDn4zs;>X*OIPEf#xV3XQB=S z{|o~zsq|rV@WOEbx=quZcjMjDDeQm46-pl#MSxkN>4 zB>||A1L>uZd76-d2Br<_N&>EEb%nU*IjK=&i5MlpAMXXxrJ_sR1Gd$3QAGxo!VQIw z>+1d`ZvIbS=IuZI1qQLig@#~6#~3H;-|`qFQr9O>%$jx^69bgp7$5yp%{MKzQ z{lTjoeba&156w^rcGEn|oHVIyu6M7o>kO4;(JPdhr+`V6|p>ZH2>w1IEisn4-i5Ayg7aQ9}%E3&5Z|=Nz;U^QCN`C==Q2 zf>szG=ZI;1BE%2@?*#>nZiCrAF@mcvWWu&8uWYT`=O`VJ%`UsF*2PSK#A}AXu zrb1A2ba95R73HUgOx~POQqrhEHE0C>HS ztRdOx)TrnHhf-yF-=~aGlOp9-Hc&inESrWa9C0-Y3%ZG@rX&_M?!}tpUl9m@*E9S1 z8mkQOfwVtNjgDJ62P#o-LNWZ37FO^J^Q_Kpx0$kM_`tWM{$PQqI6O4G4X>4L6Q7^K#Zx1Wg(SkWzsHmL@Ar}yq%wSqcO^+HiM~)kJeJV8za$MjLzS006~J0C?Aw^ zs76!xfjDzIqJv`46rdH&l4G`9;iKou@dcVs%$R)Qm}cy0CJy5iexa+vds@;ZOG?m+ zwarZmTd;Sqo1XiG3SC%i4G_e3QK-d3iH**@8ITd9Ek{sJ9G!aj`u0%o_kHrr5L#}q z)^=$Uy1-~+A*BT|!pICcIy&Uw-T};{;<-?YM)?kC`AnNH=$7bBr6(sEg$m%c$Nc&c zD~AK7Z%^S)r2be+J54ikP!?$C(KQ4+k_1E)Ti0qcmq-)rkYxOAOm*hg zpwhol*{=Q^1iBs)zmY02fQh~hD5w~)!C;&cM3*1n@PfRvQOawS;b`Rq@6|xtUqEJPEdycD!@5e0HL5ZR;;Inh>r7ccVIv6R&VMudh$~#~F z64MXP7=8OP%`esMI<`^P-0dOD`2%(N6Rtv;SpE|{IlQPS|Gi~i`43)Wdbwur?RyNv zhzo05OwEjD#Sw?Pl`B68L@n7$WdhzhDeJLOBGg8*+rbEfbg=S#1sfz7r6tJYOd>1Q z0i_K}2hg4%O*Dww6STwVR9k0KCMCgBBMxt+uW!*6{h?2>8^6IR|9J)o56oZnLOB-Bx@iO{EvvcDv=3>G4)g@*F z2Sq@~f?ylMz!3{CR+g4*M<^t)h=EWDq9Rx!Oo~R(I#J8KD;qIJqjX5`CkI(eCR3R} zFbZQl7%3%)2GE&=QEGJ~ny7u&m;@7vWxx$Qv!cRT%}Zat%JC1}2I<65I8@b5*Am_|wPf5&MY1f_T%j=j+%J2U~#QQG7Db{EoBgPhNT-ao7YlG#jHK+o& zKY5Gw3tNn?jG3)ecpKWpfg4uDL6Th)iG?MU(rzl)8gGFjF*sX=H=a01y2S=!p`e6l zJ=6Lbij83M>nD)*40$s#8~-UFfC3-! ztDfQSSmw%q`6?HG-PTZqK;#@4rB~Ib`gObfl+pKPF zu)MlV0CsnGSsgD+5~#hD&fXJM)iZ|Zm2zgyl|Ro(A*GTL1zL%H9aU$^x5?H?h&1SdNu*v2MytiD$Jbs;W=$jevyKEKsHSKm zl(J`pG7<*z98oCIK}EsltyP-8e#~e7{4Y`sD?acYAHlB$re8Y2MnOhKo06)Dq!$y@ zw)dp+-rF-{&-qU_e{M=OTp6%&@dE4Xn{2LcaCiSMhqEItUATx{A5s-Hn3_;VqVWW) z2t~l#C~X5RcoXo&3|$zo;H@X7XP%_X^PGpmL1Bo65Wxqn@V3F*09xig7@z))L|e;# zs{_H-QXXg>p>Q(ih3Mo^MB*qiHJ;^q$m+EIt>|jFXci24zWE6u6Lx zLwc=0S|yVqL@B4KRf?9zw9^O4md2ivI8#Kjvqg4DbI))@vFRM2>}mi}I<;y^3MK?F zux!UnkEZP2y9X{XT3cf4(gl3?!Yd-XyRP)05Y30*SRXJEZMmcv{0we%xx!zJy_wK^w)<-T^nSy-W4MidX*dYixh_ zCE}*$hIuS z4{I%ha)1k7$Z?=0j(V7!t5(iQ4LTHOi+RrCcR__V$d#?+HV6=V>(vDgVn}P9>io(= zBG3od_qcWY8ueE0|c)(OtIJx6vPlgVkefZ5Zs9s2RAS$5c_2qSw-$!+Eri(0Ej1 zpb^AK2nOvX3q)?g)1(rFD3}`?C0ee8eFqf+!p#sUf=0&%Vvu%!E;&ZEM>%ORqZ@^8 zG^mIVuojlsxVg;k_uuB)|ND!KJ~QCb(pAPDUiw5T+rq(EzqCpMlD$R9@{Od+Zr-*=L(;5X$lzB-t z``RlZB=!>YAqG@PZChgsIE8?Y4io8Khlutb<21@UqKl{|py~+Tf)BzC(ntn(sE3U2 zj@kQPZgBh0zRT$9hzo!C1-5?k72IJ>^Lj0Af%fNc*BXLU0n`bqX`l zc<=Gruu_lMcyon&f8hpS`oS--@}V_e{6jBs`B%Ki@pM9cdx||4oh?o;9kD68XYkF5 z=fmTU_gRD-ILN;*$0N2bUtnW(12^zgW5-2*0e0c~7vE+5!yD*JmS!yI2VVr@z>C3H z1VUj6!-yL;_<<*s5QmXw&`^(@ki(4wZs>4BM?Gw41{HNNqqc!y9M05KrpBeeYcs={ zsTilG!kdQ1R5(-97>6rrYTHm1HBIU8WuPt_>asyu#b`QUd{8p^Ye&5G1D`<;3@`tl z*SPfEFR=V|t5hd5CSN!~%_1S8^Q7IEOm5ynV$eJh>PSbK=N{UUsH9D02yj`k{vU2} z=?}iZ;A=`)gA120a(MfQy-)7&TKE9dk58$VrUav9p3~g>(i6&tSbAKU-XD70z|oWq zVGwX5PZ&Cyp`#wwG((3gYnq~>DI&F*QKvcerp6g)OhscRc+(KfMAk%moSEXyOkNlA zU*-~Vg=adL(F_!0H)89JW%hpXHedXK*U?*sSO0_8*!s>ZY<*;#*>uL_&Ix9wB@?Yw zyLHmHuFiEI?e^xu@|X+T7sOtP;B{ncbA#z*%F+HlgYj4rL|Sxt>?bbzjKk1I=~T~T zjdWy#i`O4h8ENP5cbq;s8MGJ#ILpQlQS>lI^!h**_}a63_bxY2u2XzV!3Y1dkFfbW zFEjkwC614esXjN6eK(UffbhdMo`EK~I;>GWImCf(DjQbiGty;D& zUF7Cf zN&nR4jG1*b#w9)CsmzSV1Zv&jOieJ3##F7GH%Z6TWBBWku7Qb5}a5VoGg7(jyLU8l0Ko(mFJz!fBa%S%)dko`}A;6?LBT zq9zoPs;sF84bFPD57!y|Y{|{P_BPl4#TPNZY`{l;@5kBx_RH9>8Zg46d*8R5i@(e}osS%rX=}nYj8~S~*t$SD%!Ew=Z7qXh$U9$t8#k-j-o8LFCXgx)w$pS`zpQII5|NJhX|7%19Enk6PCh>{Vq1*!GdXo)gwf!rMK?{iom zFkBw8Hrl{=D_J0|x%SRA_V4YI=^Zo?m!jMm(m7AQ(3||nlKl>l-a_=OY@*x0<0_Yb z=N0N#9Vdf^!L(%M-7#PM%U|H|AKv9fUSK?0VpcR=dl8=s!E)Dym^v)z#q(x_zFvvHTQlj0o*v_s^?Lv|qb99FN$%u+4BhN^&kO^ag_=w{PC!aQA?V z7q=OVhFxhxtdgvhR|FIBAmJJ%e=ecwHCi^S< zEdQ1@E`8@!*1vLtD%K2dtnlR@e4TrL>n8dZ3CbO$p0KUe4LoV9;`b^ zUf{~NzrgI}nj>?}Mzx0eMZ+)s;3o;S<14=VqYOSeq#h~dn(?h98d#}TRL^0csbY4N37rtVM*A>eR#fd91T`rrQ| z_kQvgYt<^-E0@r<5Ot0QCA)X-a`XC4f(t^_r6Nzpob&i&d3BY|%NHoik|ugw2rLc8 z=plT0@+ImIIX?b9A18iTps$dFB`M3C;r~gf+m?!1=1oQuo0zW$v;0t?J4>w?;N^oKMofX_q9CPhQ-j+H4bz5BdwpSP}S=><5 ze9rOCpM8Uqf3}aE3B2BChd;N|oogh&$jR^+3z5qodQ>82P;&9=MMf)2#Ksc~g^z(j zHDEX#^S1vI(~nMh_4m9A9}$RdCalc$=2~}cvSLC7DOG@W^88!fTXT_Rt#gfS-UEdL zLHI5T+V)&zjsYn@iZP%QgMGV#y{-wu_fz6OQ*-ynu5;(F-(>SwZgcSuyomn>#Zhs@ z>SV;q&n@%izwj12|L7*F>gr|BO@)_WYuUeCDc5EigZ74IwPEA;UEty$d4cH*6`}T& zvl7#2^fk*D|K~SY|LhWjKRu>+rI0|CEqa7pP0M4EWmYMvvv#@WUnSIzj%m*Ot$k?wk^*>y9cy-y#f?A7@YPf1x8t^%Z&k7YV=Iu{>_w=@4Ls1fAcOI-?GK_?|+H- zF-=v?SY{dh`N%u}%bOhj?H!7yz!8WhbH&UXE_2+APq8RjPnP2W+gC0z8jW$zwW!ac z&NMSCJ&fZ0cUr=NW=786=OW!lc^t{s_V({`ynf8aZ`$Ie-~B4}S9|sbCu~$}jDFnm z#sBB$Iry=AXq)WuCnW(q%eL&7xI)L%6axCH;nIJ6mCgV35<8dn7@Z991J7vGW-a9a z0Du5VL_t)#Liov=H~-vcSbuSY%inR8=~vY>14l8nm@2@qz>h=-Y%Lk+P|hPF0!jB6 zgj0k>1e;2Ux;GQVLmh5Ekf7gZ!U7WaBY2KtA!7d zYp646TI$CeBhkw>NPC!?s%og3ij9?Z)|S?&nmT<~QQDG$G5q4sf12PkTVs&kw^~Zb za?8t8YtVZ=Kc{Dt9<|>mKR_C{>QVoW93R@LvUcqXP<6uyT8et+&?r)c5`@hyQ#ZeJJwM z541cfaq<0Ry>B>Ndf^I7E6ZIl$_fR6wIze1mtM`CbFW(^4}eufBR%U|xvTy^xq zmtc%(N$fIlppeW-zxh7t|hP-3(@IP-=C4AO8`Ispok$E$s>Ig_p>;)rLM^v4&)XBgX z^kiO>UMsuf$lm96ncX|#@^5~DEC2qB?0;~|@o>UYHDYRJZ2JqSzgY3<|L*4~cMF^j z1S>tjwd;5ndek7jxWJP|0kUndy1B;Im5cb)-b^Q11u63?Dfr^&-$E%U%RxFzY#nhy z;p z`wCZo^9MM&GUaILgiuE8vF62VFXDdagrEC={3L3cp1CL0-49rT{@$e09nJGmqlHC%)$_Y(lh{h9( zh}NAR7ed6?mdLf&(#mzRCyYEN((Q!AwbctgW`D@XxqUX18OHRC=vre=H1B@;%cvuG z@w;DP^}8=}e0f408cJ87Yt7o;3iaPT=Cl8|Pck?u@zLXkxz~Maxo(5-kDLQXSN>Zm z#q#C`n-{ln_~gsUGw(uVb$OY1*ziXA2IeKp`uaMJsnh(>C3fhNXjt9Ni8d&c?2;6G zi6*sPOw2@4jD&fAQzhNp&$4F1xWpeLwn|Re$@il2#71F{3$FjdmoX#5E8qD6)_?6q z4leC888%RAOryE_$qO9+^*uiOmwpjF>v#TGh+5r8e*5FTB!G*1LCZp~tdI%Ch_+&Y zMK5gO)ya%vd6`#UdxbB(^=0n7a~)d_3Bh%n*j(T#8E|NnN&q1RF(ieM*oYrx%(bhN zCqv#(Sqzl}y&>0I13HmNjSZvG5?5DVpfr|gRim?^)JF3y${O&lo0~L2nc%P^U3$n~ z+A94x=Q#ECe?X%`idhdqf3W0u{g7rU)xUa$85&OXKIMnD`OxqA7;o-=h8zF<8iVP8 z#(T6js1&g9$>5VLt~}^5q=;*;LOsqEAarF2x=-e)qQnr}hV+59Ieo};n+(r9M^-W# z1dVi|(^TUM`&9*3e(x)+{f>2989A~im_quaR)dP!c!s??0(&6NEuFyUW4CRTA5+2T zGv13aroB*Oib6KSR?Za$MN`#S3@^NN6$sq9b^|*Y;)5t6aY`Oh&J)GLB5UrMBhCAw zoW~4u4KZyJ3fz2<0Td=^YExl<`G8mc4`8AF{O45Ru}kzXF94VHcE<>QhL3I zTz=4N>!Tm>p?r*W&`6!%`Uf{S+&qF6g>eR^5r!qZdY{d&U+06(SMtW6|3$w1m)?T0 z>NMC{M1}cpd!P3g-^**4g-X+{WqzQw0++sXMq9@`=je3aS%h1WayI0Z?GG}xLuPf2 zD$+V8V?G*_95~RSH4mTpFo_gSh~XkSYN?1)irHjFQ7rMw#;bhp=Rd>s&%6!8oVn@E zn_YO_UkAPLe*U|^oA)zFi@Sa9Ad(HamPl&xH&NCl2Tx{Dyj1eRKlTwezGaJhYrA;u zv5W|#z|r)GD=%MUv@v4Jkr@0+Fyksl3<{6t+?b?7_lGU4lniC(LXq?W_-TzUmU!)j z*Z8F${Uxr4LkWzWCFlB#*JsUje=N@V8N^&?uEkmJ=g&fvOk05BV*_6MogZWMS1z+# z?$ZQ^Su*ItaC~sW`#DMAb_f}urUJgLTU3E4&@HW54m$JK%H)iHKl(3~{b6+>e* zg$tN!fRCQ#kFD{6Kk+fH|L)h>+uJ$6`8{joIh@ly3%9+vE{pq0(nEu97;*K#c!iB` z-(q)oLYxMcXJc{3R=_)l_tHvJ0MUIZ&uGiDm;OmdOeGyTBOjnGgUR<%*EMEP^6Cda zz?-kX!O6k#`ONvV9u}6qb(ziYxx~`9ZLvGrCxpnbmP8~W;ERfBF@YhdS`q7~uv1Pg zM7KgYn3n^$j00SZs4Y#=6bxNpw(ik0#gHL;YM(2=?h zq-C*2VM~*IDJc=od~l`F93LLAv9-kq@4m)6|KLm94Y!_tjvr^<&w8L2VOMA96)dd& z_AM^|p{tm$FWEIac&{0qjHqLS){4eB8s&v!Nrx7V`6T1a0KkLf!x$qhh*}ukqe5EB z#lWD@OeTk{Zm#p<%P;ZHqp+~Fy#!+t>5@qqS;wdt zaTJd!zRL2_fAk^V+MO}``4dVfeLwpFhDZ+(+N60oYp%|CuUU8RfA(L^1svKn~2$R(F*bOM+ki%OC$>}nX*uP0NqZzJ?elp3r-> zi2)RRh;wpYSWQ(;u;mh0UV4G*aK`b;5u`bJKjr+ad&*dhdfYJn)vNsfnfuot%eHsF z5BfY~j5+68t1jJLecivyx%`~u7&#o1fU#uZ#9+w>DL^6&fkX%ikU~I62=Rtj`~&a~ z3Gsp#Q6ydjB%>q(6h$^h#3b0p*dac?oMWHg{{8mu-hJV&zR&mh$-nknm_JwZX7(Q28R})NADS3!@|ZTVe7C?yPfbM_ zMd{+$*>xL{(Y}wW5Y;C$yN;H`Y%$)7mkkN?+ym;dCKe-pmb%}@D4 zwyRQTOMNtM_jMQ|KHIH$_lLj7(K{LCa1JR~d+wVf9*&CRNB24U*#iI;euH&m6o;ZS zLQ1slEfg*O#AYj-z2`ZyZWAUz>;!9sm8`%v{LXLxasJ@{`}cA>#W1dB=ZMcl(EaaQ zBby2&cUupS{rlVFm{=X!=SiHlD!>u(< zA=yMj!};qoHs|Z@_1fn!>O9_NEBC1Kn5V*%GES^DurzCGTk|`Q|2Y5fKluklpLWK1 zw_l_28T$q^I!niG8?iD#aC3wyUE%~N*ERVr#i5%KMdYe9=14gCZ$9DpfBY2wMB+vF zj;3pNB@Y_wHRZeIKz|jB$Tln`mL(vb~nu4zj|IHTXyB__`yI783kaJ zsH>lADL?^2cF2lJL=&lhcgoNHC%?_~&mZusd#`D_ih5mP=N3N+gb=7rO?>A`Z#_1% ziHjtS%6-g(a?LhIa+sKrK@~JlYbN&(*!T@ZJ!hgxnfpU{H~YZkpPTR}e(!hr2mj9R zvstgHOg#i3GNZf!V$M-7C3fSWA!XIR#GEe*kHPdPuTru*qGK?QO~o7`%r!vB6W$Zy zc2!{dr;qsQ|LC`n-)ne#?>!QP$)=%d6Ta384Rx$pF3yN&fl91C&lNHqFZ^}0i4n2b zs?uPO4|zWrA*B%J%Q+A4J>aK5|2f}%`z^i;S?4Y8GA-Q}FYCh<3eMK@z0A>dS>H#M zjkYd-khuTnAMwq9?`O!Lt$1^I1|AL;Q*}N`LX0K0hRypHmg)Ak?%h;?tg9E4NHR$S zbWa@By^7Q&MN%Gj%-&e+#?T$XxAk}Y=6~%sY5(Su(|`9Rb*$)8M;kk=I4V*2d`McF z&xj+YL}I(b{P-joW2c3aW4%m$5qKCC7DfbPVy4MZ3kejxB-xTYps#mPg_(|Z=fB738{_8(s^`|;M%$C^B(sYWpFizl5U=8zEXMG?lj;af7 zjn&>E-(Fq&5dhh^-`8xd2!Ir0E*DZ3pyq74+VSD+oO{gyCyyTT{rBH1#5RoXe_01d zeJgOSk9s!Zp6ia@E2TtDP-Cvkhk)~Xus=C^%4BxHI(BO0If0PjV;PnmV^D?Dhn^XJ z+)}AKdP&#x_lvt`ECdclp~(8+h4rW?7zwF_gQrvcp`oi1^$Nlysm;4|m@0BMJLld% zbHuYh^K*XrH~&7?Rzx~w6HS?sKj$eYo3N?ONxE_fMIA@h$F+;BF2-Qm92M<1FB_oXlePlx1V1J1{ zf59Gw!8wJ2BRzV*)YVNAu$5u4S~01oeDjlM{J|fb4^X1r!MrSj7Ik1{Cue$pXRn?l zlmBOY-qcNo?MH*d5mKP}Q-}QYfB4(DKR4lhbBc=&7i_-^q>!lF8GfEfi_vkC2@8vd z^P?36w;@_fZKj8lH9MwP{4_bP;Kkf%VTO93kt)9E4evon>izJ^rFFu9!L zDW->zA_mEhQNawup6AEr4)zL;6!&AUw_E-%gTppUMh;r*Ln_CX#aV~9-3L4Ru=+UM`4dA^UMhdq|SpV0J3g?&&tozEWnh7r3%FsX{O%ETbU7u{LvkQM03m<5oi zMv<>02Y==PzxCh!9p3-;JI*F^YIC5(j|n6e`4Bd*mvrw#-zO;B??r*_6>iEe*O`pb z=XwJ~p;p#9mG!8*l*B^DD}+j6MXkP=~CDkZPzNPmsr!bsb0&aY1vsqw~btAqkf4lBa+A8R>6>|CJ|t zU5g4wE{@WjvCkV;GTU=Ao`$`1^|3j~HO1Lz|EUwE1GiDstN%sf$^Y~b{x1aP<^z)t z4I;{o(%M9`66&@lEh7Fb!+tLy{C0BYN4wkpLB0M&I9ubK)6|hv3_Go?lY$~YopYSc z&vCN`>ngg|_XNheI}}9dC1=nTM^o7M$2E_#Es-qy%_Jf}vpoHaKZk$T@cv+q!%}UO zFCrc$*0Yw`dO|ww@ZYss7O?OF-8e|GKZLuzo|T-CnZSwA9R%V`({D{{AXWsMXeS$d z9a;G$)$dGb|L>8_+c|Lp$whn@=sK@lUq*@3P1h=`|E1*6Wza6!dkTs=bvfNA_2{R9 ze(oXZpj>EC`z=ZEKa2e2zyBM&__H4{bHf2ss9|$2sna+m>P-dj63bVsJk7mluJ77_ zEB^Ghue4pULyTCes@^8=9w9SA5^Qp8nvUgkO=p8vNh^--J$m%Mp;S(7wLmXm+|3GMGj7HLVfa!Nw%60r_+wWo@Xv=G+ctzfPD zMs&sF5_`Q(cl5lgT*1Mx*8w2u5}%DR*vf)2r0lKEY*;0xrl|qO;=O0xZu*Y(cH$+6 z{cZ;fQO&glCGHoo1Oy9J$cJB^_)vMo7&tL_7nMA%%x=kFm69IJk8AsB3Yp62m7&LmTuLLW&y8jB?2z@nj#wv}qSYcz{Dr;3@d}cj~DPO;W z6xF~?9($GcqKFz-qJF8j4Sm z^I@#6(O(fH%3c^#@k|#uy?1Di>c(P%p>-|y|1-y=KV|qZJ7wBh>bawxp!J!f!7PQU zvn<~%h;50e_X#eVk4K_Z=+H;GTF$T2)BsCxAMC@5IN1y}wT%Z7##>FpNQqUmCL9Hr z2x$=rNz15sA9^R3WfFs#=3B%T2S=Tkj4IeB7zUrYS=iVB+&a+9Io*1j_`!O;yKGX1fW|zK93rtcf zVU#qY;a^Fm1e<`#d<(J1p^!`RA|Yl{I{i-DMdBnf`KM>3KOwxDyy4N=3Bf86R;;tb zAy`~%IeWRHUADa&p(qgJN*gzA`;?cSN5|F!X<0y>o4E{S%Be!u7?vz)jVI>AX#fgj zrBI5Y7_LYm3KxIh8uPd%w--|B$cC8LJtF1ug3<{t8loilnIZl2j`p7jtWsbyKh*VB zC88uubi}v<9P3vr{JT}3a*;}8;KF`+dpN2TaxT6ZnORw>GbIPt=#R09xnB^CSB{XJ zJ3aiL3%_6X%8mNkM{2jzjCN)OW`g~V2J^=o-cL`#fm=HyKzA=FGd_t*gz(t0T#7uT?fe_Y^)*899KX-&bDZD%Wz_dH2d0*jOfO}e| zF>Zu<-4NddHt*L1!gGYJ+&9cyuiZfO%idxtgRR^srlD)Ba40BRJ~C}4e0cYcE~m7n zG^C?`CHk2wn?beTFiY?=!TrpzXuNWmv>p>{qU17enP@Q11M44Fx~`2QxbDUdfDubW z-ygP2S?ytr362x;jbU>TX(xh_NVUn)<0=s{|CTeB^VKO`m&>XcREGg#(EWyqfQJww zRM`&sXm9s?V!Uq@j+~enbLJ2s`K(h{sw0IiKm+{3GJm$=L%rtd+heNaSl2CKqQtzi z@=Q0!#CIL@A5KR-85?m4lDX72`&iS`-j{qgm$Z#B^@tS;xuH?J$)`lfRS`-V+)}0M zvb48LdulJAiH|*9g6xb+(57LYBXE}Ynqz@~*6`uC&alT*s#S$qDS5Y_hMv#LC5PQ4 z=C4k*G`vo>j+gABT8m>hL$CMjD|;OP#aJ9#hVUDqYARw3J>zwZO4d>W3xZ&s5JIO6 zq^R8&!r<8(U-Po|DSOa$@*gr%zlSadlW+%)V6}9n!DM)dPFY_kHA8OJ%hl*!JBnQy z^ef;_TTitY?(s+q+wpq`#va}q(>@COabdB_zx|s(^bBH;A)knESlSB z=HqY0%s)^IX_Bx{9qFDL^$O!w2v1B}`;@4}ZmYLTjYj+NZ8Ch)#6lw5JDEPET_!go zD(6YGK%WsqN+A>cWiLRAxXMBdY}V`CpHG+bPwnrO$AN(!vCzMi4S5Ilfe`O25|cIk z;aKX0+hlReiuJ2=Vml}+DO+43iI45&H+|Zc7W>!{Cy~zT!D<0={Zz3Y(^a_W2QV^oe24={S=0a|h5jV!bYPA?D@@y&Ky{nt8 zedbC6m(f_2&lLk)w$=G0iBMiDXceCiWYO1>PYVA(5zHf@HA=FC*E31$w*z#D1WfTX+@Pg#Xkz@D2x1(Pl>G2wh*)tbwv@!|HiMDVYolpPj&+Ro z%>7kuJmx#s8^btt%oE0E2dn^f;Y7*&B99E_Hyq2!N@4by;Xk^lPL3@5Q?a~$w;(J6 zH8oxG84)&c#S9Af1+Vhn$G8Zz8o4A#c^y?X(bUDH`&jA}Y9A_PGM8vbAz>qQo1oE^ z2)5Ip#`gVoBP-^T;f^CR;;S4=V|;O*g>jxS^!U!=mi4X2ZVV675zDhcoF&#L8>&@> zT`6<5pBPo#=W8~n8&&Xa>H`nOsQFyyg&|ieGGx?;QMq~q@x&k!sMo1CG7W<5ENm(u z5od|`4~6t?gmuEjqLyy!TB#6+#=`1fX5H)?^dkt<%$PugL6XkAgQK%?^&EK6h)QNXpZ+y{q{3_j=Er+!?kc`GDO1*M zM{Kp6s_HdK^{yyX$&q|XC>>hwtYg?4%t)8t-DlJ>H%jJ+((6L{cSeA1GCDXILK`@A zM@-*OxZk#{9&QM2gchpSsS`L>I0M}(&^}+O4xhsItf$YD>2c(GYfm>&PaMu^qrE+a?cqBkb;;|Qpu3!z(OmjHt=7;FeBXHmLnH_e@eo>1!cfHu z0lIfB2mYAJ{D9O3I@b|%H53~RvJ~vpVy6z)(4BTv;}|xdTn>3IyWNjQm4!YRV-STa`m_zUlq7?HG1t|OIln~iMck~y;E6aSIPeK^ zogTcwQFRX91U9eN{T(6(eCYokx7!~5{+V~v0o1bB2y@QVqlV_;1UGY}E)nX0t1Qw= zUseqR5*&*cA4un^sOUWe)s)D2KNmMqWG*?XA~aQvwV80R$az%dCS(j^Wi8Qntg{0k z{K#@%f;eUrwJ$QnOmK&e#u`rXbd^J@yoS5Ho&~1omNzfgy#oMBl(7JTN6>7xb1y%q z`AOvP@!=5hDS64>5i6kbMBh>+uxAzN+kn{=cZY%XXorhjy5Wu6ZlqJxCg)_45s|1^a5*#lepFY1uFg2#KYILWO zW>XR)G7(`kfwUg(FUj_K=L+Lgo(YqqdcEUfq@3(qn|2THg~ZF{If=l!lw%Y^NThW_ zqQhZmV@Fk0+&elT8fAcwG4%cvn+!Htnowa^mT08Swn~YOb#%66YJ~QUXY>7P7>|-W(hE)rb=;IBYltue zI9JiOrTnD1@wi=vX83%KKy*K@L4I!Vho0yx#@7TfqwHsc-mh7{n$u7d34M9r zn?0BAcbAn^voYa-mPmbAQ$K51O@ku+yd%g))46;?f}!$4JPV}Ln0a(YQ1mWyU1Z2S zWJE?v?9)w4D|<@VvT*jH0mfe|@5_Y?CQvy!7G}S72s8T9gS3jAi!S0_z$SxP*O)gO zc%}Q-uCX84Gj^Xg3HyG{Wk3sqX}oZpn3RzR!4lg*>hi*iv6z6DbZXCd_vg}h7rGk5 z6E6-#U%^LFeu3olgFVjM2?swtBt7)_Nkm$KR-lGpBhFZ=;IQY0&D$2{qd4*?Blps$ zyJSILS_NRA1}Y+&cadU#NHtjtw~B}oN>okF;{6$$c9Ww>u#I>Bx)`HUx*?>PqY>Jj zshwbPeXdl>r5=j1Nd)HvXDy5Qa_^X2E#u>ZX`epe|Zvv@ma`EHqgK(`g$|47?~561CZ!{XdZc{mj8LxUU?6}6O}5^NGB z2}%aj8dfjXr1Pk(+?GD^b)1Ku7$Qiw^Gt@?IhAugK`Av6^07pagsC;>czM3qE~U6< z{=Z6#gA$h_nIK2#XyHU~_a~&}bQ>xx_eMR8YFr4DdClpIGon|v=#hqg0VQh2H|~GC zq2+ok%$^-!ZA3aq*7f5lN$3!a7^JI^x9k4Uf$Ri`dv>^wbYn!FMj<(nt;5t@cwQlU zO8SVvwj)pPtM6A*QHkqIG3mLaMw_Gpa)ilj%FFLx;QeRj{a@0y)XDMsG)Bwf7$Br! zukO>Ilt&?wNL~#$LG;iWK}?5?fX`LG%V_qyMm7XWPQK3b7!<7Jrc#)|s2?>n4-W__ zAku(K&?)0U%Fkkhg%6SRS|g4j6*AGWH~$NGUko^Buy!Ee>z_T>+g22s8l)*J=<3o- zTi2CDt_iPBIg@rww@bPo$~bNheBWf}#nhKAGMS6Rk4PKTEn81&CeM!8I89M=(PA(J zQNq?3BW^jNd)*SxR2dt}eO)zz!#rGN5?u!?P}L4wIhEl8;>yq18!X09RgUFyaVZDV z7i*=Ca51J~i_|Guh)J*^8xMz&ol-&RLwX3L)=vS{X{HTG4eJ0^WC{(TkVpFqgM@!}qTJOeCm<*-sAe zhmlyf>Zr?z(PWhfQv$eTY0o>-X=eY~XUly;E6g>!J;I_6+L7Mx4r{6h6|1_#MVn(@ zd6RTrou{o~^M0-AEvQ2&LrowCqR(qHBkE!d#NPP)5^Z!{qdYAM^k6v@4t{fnp9MM_ z6xGmX$DsphJSI$Fo$zl0ob8}f_gbH~x1WkwjH?Fn+^suFcFrYI6ukGuRM4#P8VMC& zXpga|v$+%HEy?Ii)w6*aOn=@G9z?pT!z~(2Cqx^d0$hir8qO@M_vhPtVL!Cn4&D82 zdmgTE0PJ}NYrvV__$PvxA#xFO?OCTi|h91fjAE+!&0$uNI@it$-l zG&)csDHAki62%_+ayxQn4M^n%gDK0o_Df&VGMElB?}b?T(d8TiTU@aD0V0v+=>hhE zqoq|vup_6DD5OrSE?6e*jLr88=n3i5*0uJV{kPC&!olN1#F`;5*nqW;WU|qaYq-a= zphQ2C@Fkb-2JK?JZ5YR`Pkhvoy@Mpsv~28w!OcvblZTvkwZy^U>Ec1^eHwr8<-;Ewa&KaLjp)Mi|+shz@zwMoxf&6v|# z&(1lP>(y8H-HrzQLQ7_NU$B}BQiD9L2u&m!gT(E9U!6md+Esiw?O2^|sIi%4{Id2L zXK0b5>>vlIPa4cgq;=pz%E0VgUpqNW5X?qN=~f@s_{%(4w<`))x2%hdqn9bFabxc} z4xS#<35qC6>TFkbb?u}#kt$5EZymhLYGg6w`gQpQcKHYthi<8!U`q6%hd|N*L9)m$Prk*WA!^^Se3k2F;Z+8eLMoDMJI3D9qRB#vOtugi!&G zOUK)cw6QB5Qg+}mQK6f01UV`YICE&3Jv-LC_}r3JqD7pL#401OuaWn_yA1!nEQh$< zkK5I8%!OaJmAHgP6jO@u$dVpfx~4-U^bok+OiB|CXFr@_Q-))W?k2aQ735La5$OV> z+kLpA7>MLr%B`neUtYTHtIByluY)`nWri9iPo~r-O|Pt&jCP48j!M#XROb%f#2!5W zGHeCr;{9$#J2SuuOdmHGXOPrkOz2ti)ibUnUSZ)`zFDi`=1~{sZChz^=jRh!$&okC zv?u ztH@vl&gaYBUVYkFUiRMZSjUflHpw=(NdNZ)%p;JahE7z`GKKZOcXA1?wX9w*`~9-d zRoyxU`w7kejFCq-!|=5eEfVz*-=m9DuSO-9zAFq-CPA3NH~vR`*L-oX-p*(WYlkX2lF24n0?!l7w<+VU z1y#9uw~<_;dkiBVvf`4?k5TR}@BOI4#9cG|70Dl`rJc1z7xSK;pDT~MYc1W| zR?}Z&33;T?K(y=(td6F-adMPi19sUFcMr^@?0NOzfN&K!Fy7OwYSz!^goV#~?#PzN zy1|!ofR6UneTuq<71cpk3v$m;J)IIKiux+w8&WP3P|==kSUz9CntsjecA75S{WhMa zq+S{;*s3CylBjvSOXVni4JLKXdcCII+%X5h&U%YPI05@W`4#k8OTclECkcXi<5|3% zt8Tw@*}~}(_v!1Gw5t&Sqey}p4VrhMtfG>Y7n9T1G{-W9L|nIoKJQ}B^MCCDA7Nhy zW5y{-RL;Fic7Xr(4#WsCCSrb;u!q@sKkm|8dVkoHBQpNI|3{&K=1`bDn<#uVT7~A? zjJ~i+C}zbX3r~C#;Vdx}6N(qc|4U`1Ux|vyd2pH=m^gTN0QZH^M9jvJq7Z65NFA!E z+0Mc|5l+39R2!)*CdEB0-JcP;*m=QJRn93c#3~~>hu+&5TaPcb+wYj1_r`gphEemd z#!jsoa-bz68hC|ys4>fuxwThp*DB~kb*sKYL- z0?X%X_4H#vQqGligs%kK{irFD$r4?xu*u?+S3Z$_sjLE_^8{bW+yuUYLY5@aSa(tR z+hQFTj8kXmYH_Z{v_MQ_Ik@@JKA@2HU8BhHF7L$X-Z|1~au_+*3H!j|4l7KIG@-&z zJhW3JS)yqH!C~3FUTQu%=tD`;vUX&d+lpp9LzkW{a!=yY=jjD` zo(e)v9RLmPeuX!l+BEr%is(GXCv0#uUCp~!@9^!90=d{T3CaT!w@r6&5p&;g`0S9i z%|I?AJr_VSi5Mbcp*w8}FEayu(zK&ks&4EXw_ED7b5_f`igH)=#6GztQL90$q3hZ{ z&E<}a{DmeYMq825Q7PLcV^g{nm8R%M&N+3Y3m5Ew!ttU=bi;bR>UG{9 z72&dl9AR|4Dc?{1Y(kt^Vn*mDn@G0GXxJL>I!*I>llbuJRGk8a06SkV?(XW>5U|U& zx19)IGJ%S#5|(5qeJ?imbLG;%8s49(LC!Ny$E-4cx@iOW%~h_#k* z9_U`T8X3)A(EZ-N%U}AuHh2IToQ9*@4U4aNI6)p-R?V7Zhn)0OCA!LMiK%(R`b~>0 ziioE{CU?{9KWAa@=%G=-)y)-ho(Vyc=4lNqx<9gzU6RM+HAyY|} z0kMKe4OF`6NMiHrHR*huI+D0dSHIO~eP-YgLMC1;hs@yJ)xYC1u>N70J-s&PU4FeG zE@-HJp!fYGsKn5?8rwS!w^J1gxe_Suki^b zJKs+izZHw^lC3+hX?>o6y=R#{stGAjN-zZ*h{k4}z!AhSYp1M#SQ6)<-&e<-*?&~s z&cd#&#ah?biZA0?)@3RV7$aH+>qo1Db}Dc-zhPP6V|WhFb@>g{(=nrqLO`yZ`}Z< z5O?;aJ5`p`Q%g9~6kU~v3aBtqTZJ+eQFb((UqcF`SWNMbpvQKEKM} zk~AIH+8V!6JM?SqA0O+#6f9fTb3Bna6K2nj)!s`b@-Ijgur_9Su{b6)=M}u_^7HJX z#mpyza<9z+;EcsNOA0<4%c=~70$&t^#6;6HY`T`sCbQ9(G^3s9`Mx^IU#bnYZnGhg z1ba~Bn#MpBB*Yy0H@W7!$#A2{CRZ~s*C{pE>&JT&EJq(2dtc-Bcl$vX%(0=mH$m)~ z^51!jtp(HR!t`hz)b@j?eWwtpLe?>sh9NEI=3KvfTU4XPQW&HMxbybbHb5Dt4`*;+ zb6s4r7}Fp&60%n>C6Eow-<*$zZt$Q7B-g;qtiipK^!f56Xij1z=;iZN4RWsR=##o4 zBv=$VFWDjzy$I9!G`=IsS@eIIa51yjMB z>}VM+2dy)&pR<*vU9L$vhxb~0%q=uAn$jg=6ggoA7VPR7FAv&V zk~fdgUNxGr@FJA`tQZO||0IYZTd4PeM~?L*5^EjsDmW!(%2A9+!rF$jSEqzkhr`m2 z@}hSET{qoT`s<9Bg;A%oP0%q`UJCLo@66E=H1wy-}$@OLHg?_ zc8O#AYnc4~n0hO;kUmWwPiVerNL4W)8V15ea+IdSc&$>ynm&5b4^fXCGCTLbot0p# z26D;btx!y6tS_|^j4`yUI{+6QI|@fH7acZ|Ff+sS;fzf+Ck3V1H^vZbM8qLMiGeq7 zSG4oZaJ7<-6!+cXrstIO*9#&9TDTA9czBQ?2J12^goN-qkZ-w4m?mLf=hyFGvoQm+h_2ggk<2##cmfVO8#E}!G)K-h{XSBA zVexLm`prU1uze8(&oE!=0MMbTPioxB1YfFONJTUjLm*hK6X2qy+0;s0yi7zf%J3gA zxx<$d_1+}eMh1(4o-4vZ^LR!(Y4OfuV&*U^v5l;QH&Wy0bJp)xG&F>CF`X`zpz5t; zRGDl*gL9hq8Kc+Ab0gzEmNagwtInr8u%C~HAIN-jW&R@^3bSWZq*5n(AQG(A%0F7S zQypJkFz*CDjIWydf8$lIq)V3e^;f$QYGVm0X}L$Q9d>fSyL0!Xg^5l|igxkYGL~Fa^JWUYldBy7cWrkzs2w-t0WrHwX~+RP4u2+&eOd!a^8=(rt1j638cq@p9O+dJbg4aJ6uv`)vZX$vH7Dp>0Ij;l@YZm z>A`vfDD;&9`XYt~%r7k6J&!boU>y-hvQDEdqeCa1CswZ)IGj>+WQ(Za1io||2dQ^L z*1(XdtUMA*RMX2vHeO5AJ=sXrRLqx)9x;`^k^&~iWrH|sxuR4+*(ExvpHno3zf?Qv z$KnPaZ|rNkVd7ZwbuB(7-2IyBo0{%mO=>_=O|l@B={Z#Dn5fqko0n^1w+{%t zGfp=i;foKU?Eku-l}AY#9;uE`HBM7v3t2S2=5>HLyRPNyO-&k{0z20jCU{88(7{9< zi;t&xCupPy&6l>)%YJkTdF_#xWb)2Dwpj@toDgw;hd*;!SCzvURT_00%ff9;42FfTwxE~2pLk5tiu~6MvHl_YhSVWqtlP1U3^VMh8a*;y_zI2QC+M%0AB|T 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 z�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 z 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 O0BXuwN|i4yL;nvq=SE`y literal 0 HcmV?d00001 diff --git a/data/device.mtl b/data/device.mtl new file mode 100644 index 0000000..9d7ecbf --- /dev/null +++ b/data/device.mtl @@ -0,0 +1,56 @@ +# box material +newmtl 01___Default + Ns 50.0000 + Ni 1.5000 + d 1.0000 + Tr 0.0000 + Tf 1.0000 1.0000 1.0000 + illum 2 + Ka 0.0314 0.0314 0.0314 + Kd 0.0314 0.0314 0.0314 + Ks 0.8431 0.8431 0.8431 + Ke 0.0000 0.0000 0.0000 + map_Ka /Users/nuclear/code/equeue_dummy/data/labels.png + map_Kd /Users/nuclear/code/equeue_dummy/data/labels.png + map_refl /Users/nuclear/code/equeue_dummy/data/envmap.png + +# ? +newmtl 02___Default + Ns 10.0000 + Ni 1.5000 + d 1.0000 + Tr 0.0000 + Tf 1.0000 1.0000 1.0000 + illum 2 + Ka 0.2431 0.2431 0.2431 + Kd 0.2431 0.2431 0.2431 + Ks 0.0000 0.0000 0.0000 + Ke 0.0000 0.0000 0.0000 + +# LED material +newmtl 03___Default + Ns 24.0000 + Ni 1.5000 + d 1.0000 + Tr 0.0000 + Tf 1.0000 1.0000 1.0000 + illum 2 + Ka 0.2000 0.0100 0.0100 + Kd 0.2000 0.0100 0.0100 + Ks 0.6030 0.6030 0.6030 + Ke 1.0000 0.1 0.05 + +# 7seg material +newmtl 08___Default + Ns 10.0000 + Ni 1.5000 + d 1.0000 + Tr 0.0000 + Tf 1.0000 1.0000 1.0000 + illum 2 + Ka 0.5882 0.5882 0.5882 + Kd 0.5882 0.5882 0.5882 + Ks 0.0000 0.0000 0.0000 + Ke 1.0000 1.0000 1.0000 + map_Ka /Users/nuclear/code/equeue_dummy/data/7seg.png + map_Kd /Users/nuclear/code/equeue_dummy/data/7seg.png diff --git a/data/device.obj b/data/device.obj new file mode 100644 index 0000000..dc659ce --- /dev/null +++ b/data/device.obj @@ -0,0 +1,2255 @@ +# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware +# File Created: 14.07.2014 08:46:21 + +mtllib data/device.mtl + +# +# object box +# + +v -32.2640 59.7640 0.0000 +v -32.2640 33.4866 0.0000 +v -15.0099 33.4866 0.0000 +v -15.0099 59.7640 0.0000 +v 0.0000 33.4866 0.0000 +v 0.0000 59.7640 0.0000 +v -32.2640 13.4957 0.0000 +v -32.2640 -29.8820 -0.0000 +v -15.0099 -29.8820 -0.0000 +v -15.0099 13.4951 0.0000 +v 0.0000 -29.8820 -0.0000 +v 0.0000 13.4951 0.0000 +v -32.2640 -59.7640 -0.0000 +v -15.0099 -59.7640 -0.0000 +v 0.0000 -59.7640 -0.0000 +v -32.2640 61.1320 -0.3665 +v -32.9480 60.9487 -0.3665 +v -33.4487 60.4480 -0.3665 +v -33.6320 59.7640 -0.3665 +v -33.6320 33.4866 -0.3666 +v -33.6320 13.4957 -0.3666 +v -33.6320 -29.8820 -0.3666 +v -33.6320 -59.7640 -0.3666 +v -33.4487 -60.4480 -0.3666 +v -32.9480 -60.9487 -0.3666 +v -32.2640 -61.1320 -0.3666 +v -15.0099 -61.1320 -0.3666 +v 0.0000 -61.1320 -0.3666 +v 0.0000 61.1320 -0.3665 +v -15.0099 61.1320 -0.3665 +v -32.2640 62.1334 -1.3680 +v -33.4487 61.8160 -1.3680 +v -34.3160 60.9487 -1.3680 +v -34.6334 59.7640 -1.3680 +v -34.6334 33.4866 -1.3680 +v -34.6334 13.4957 -1.3680 +v -34.6334 -29.8820 -1.3680 +v -34.6334 -59.7640 -1.3680 +v -34.3160 -60.9487 -1.3680 +v -33.4487 -61.8160 -1.3680 +v -32.2640 -62.1334 -1.3680 +v -15.0099 -62.1334 -1.3680 +v 0.0000 -62.1334 -1.3680 +v 0.0000 62.1334 -1.3680 +v -15.0099 62.1334 -1.3680 +v -32.2640 62.5000 -2.7360 +v -33.6320 62.1334 -2.7360 +v -34.6334 61.1320 -2.7360 +v -35.0000 59.7640 -2.7360 +v -35.0000 33.4866 -2.7360 +v -35.0000 13.4957 -2.7360 +v -35.0000 -29.8820 -2.7360 +v -35.0000 -59.7640 -2.7360 +v -34.6334 -61.1320 -2.7360 +v -33.6320 -62.1334 -2.7360 +v -32.2640 -62.5000 -2.7360 +v -15.0099 -62.5000 -2.7360 +v 0.0000 -62.5000 -2.7360 +v 0.0000 62.5000 -2.7360 +v -15.0099 62.5000 -2.7360 +v -32.2640 62.5000 -37.2640 +v -33.6320 62.1334 -37.2640 +v -34.6334 61.1320 -37.2640 +v -35.0000 59.7640 -37.2640 +v -35.0000 33.4866 -37.2640 +v -35.0000 13.4957 -37.2640 +v -35.0000 -29.8820 -37.2640 +v -35.0000 -59.7640 -37.2640 +v -34.6334 -61.1320 -37.2640 +v -33.6320 -62.1334 -37.2640 +v -32.2640 -62.5000 -37.2640 +v -15.0099 -62.5000 -37.2640 +v 0.0000 -62.5000 -37.2640 +v 0.0000 62.5000 -37.2640 +v -15.0099 62.5000 -37.2640 +v -32.2640 62.1334 -38.6320 +v -33.4487 61.8160 -38.6320 +v -34.3160 60.9487 -38.6320 +v -34.6334 59.7640 -38.6320 +v -34.6334 33.4866 -38.6320 +v -34.6334 13.4957 -38.6320 +v -34.6334 -29.8820 -38.6320 +v -34.6334 -59.7640 -38.6320 +v -34.3160 -60.9487 -38.6320 +v -33.4487 -61.8160 -38.6320 +v -32.2640 -62.1334 -38.6320 +v -15.0099 -62.1334 -38.6320 +v 0.0000 -62.1334 -38.6320 +v 0.0000 62.1334 -38.6320 +v -15.0099 62.1334 -38.6320 +v -32.2640 61.1320 -39.6334 +v -32.9480 60.9487 -39.6334 +v -33.4487 60.4480 -39.6334 +v -33.6320 59.7640 -39.6334 +v -33.6320 33.4866 -39.6334 +v -33.6320 13.4957 -39.6334 +v -33.6320 -29.8820 -39.6334 +v -33.6320 -59.7640 -39.6334 +v -33.4487 -60.4480 -39.6334 +v -32.9480 -60.9487 -39.6334 +v -32.2640 -61.1320 -39.6334 +v -15.0099 -61.1320 -39.6334 +v 0.0000 -61.1320 -39.6334 +v 0.0000 61.1320 -39.6334 +v -15.0099 61.1320 -39.6334 +v -32.2640 59.7640 -40.0000 +v -32.2640 33.4866 -40.0000 +v -32.2640 13.4957 -40.0000 +v -32.2640 -29.8820 -40.0000 +v -32.2640 -59.7640 -40.0000 +v -15.0099 -59.7640 -40.0000 +v 0.0000 -59.7640 -40.0000 +v 0.0000 59.7640 -40.0000 +v -15.0099 59.7640 -40.0000 +v 0.0000 -29.8820 -40.0000 +v -15.0099 -29.8820 -40.0000 +v 0.0000 13.4957 -40.0000 +v -15.0099 13.4957 -40.0000 +v 0.0000 33.4866 -40.0000 +v -15.0099 33.4866 -40.0000 +v 0.0000 13.4946 -3.9078 +v -15.0099 13.4946 -3.9078 +v -15.0099 33.4866 -3.9078 +v 0.0000 33.4866 -3.9078 +v 15.0099 33.4866 0.0000 +v 32.2640 33.4866 0.0000 +v 32.2640 59.7640 0.0000 +v 15.0099 59.7640 0.0000 +v 15.0099 -29.8820 -0.0000 +v 32.2640 -29.8820 -0.0000 +v 32.2640 13.4957 0.0000 +v 15.0099 13.4951 0.0000 +v 15.0099 -59.7640 -0.0000 +v 32.2640 -59.7640 -0.0000 +v 32.9480 60.9487 -0.3665 +v 32.2640 61.1320 -0.3665 +v 33.4487 60.4480 -0.3665 +v 33.6320 59.7640 -0.3665 +v 33.6320 33.4866 -0.3666 +v 33.6320 -29.8820 -0.3666 +v 33.6320 13.4957 -0.3666 +v 33.6320 -59.7640 -0.3666 +v 33.4487 -60.4480 -0.3666 +v 32.9480 -60.9487 -0.3666 +v 32.2640 -61.1320 -0.3666 +v 15.0099 -61.1320 -0.3666 +v 15.0099 61.1320 -0.3665 +v 33.4487 61.8160 -1.3680 +v 32.2640 62.1334 -1.3680 +v 34.3160 60.9487 -1.3680 +v 34.6334 59.7640 -1.3680 +v 34.6334 33.4866 -1.3680 +v 34.6334 -29.8820 -1.3680 +v 34.6334 13.4957 -1.3680 +v 34.6334 -59.7640 -1.3680 +v 34.3160 -60.9487 -1.3680 +v 33.4487 -61.8160 -1.3680 +v 32.2640 -62.1334 -1.3680 +v 15.0099 -62.1334 -1.3680 +v 15.0099 62.1334 -1.3680 +v 33.6320 62.1334 -2.7360 +v 32.2640 62.5000 -2.7360 +v 34.6334 61.1320 -2.7360 +v 35.0000 59.7640 -2.7360 +v 35.0000 33.4866 -2.7360 +v 35.0000 -29.8820 -2.7360 +v 35.0000 13.4957 -2.7360 +v 35.0000 -59.7640 -2.7360 +v 34.6334 -61.1320 -2.7360 +v 33.6320 -62.1334 -2.7360 +v 32.2640 -62.5000 -2.7360 +v 15.0099 -62.5000 -2.7360 +v 15.0099 62.5000 -2.7360 +v 33.6320 62.1334 -37.2640 +v 32.2640 62.5000 -37.2640 +v 34.6334 61.1320 -37.2640 +v 35.0000 59.7640 -37.2640 +v 35.0000 33.4866 -37.2640 +v 35.0000 -29.8820 -37.2640 +v 35.0000 13.4957 -37.2640 +v 35.0000 -59.7640 -37.2640 +v 34.6334 -61.1320 -37.2640 +v 33.6320 -62.1334 -37.2640 +v 32.2640 -62.5000 -37.2640 +v 15.0099 -62.5000 -37.2640 +v 15.0099 62.5000 -37.2640 +v 33.4487 61.8160 -38.6320 +v 32.2640 62.1334 -38.6320 +v 34.3160 60.9487 -38.6320 +v 34.6334 59.7640 -38.6320 +v 34.6334 33.4866 -38.6320 +v 34.6334 -29.8820 -38.6320 +v 34.6334 13.4957 -38.6320 +v 34.6334 -59.7640 -38.6320 +v 34.3160 -60.9487 -38.6320 +v 33.4487 -61.8160 -38.6320 +v 32.2640 -62.1334 -38.6320 +v 15.0099 -62.1334 -38.6320 +v 15.0099 62.1334 -38.6320 +v 32.9480 60.9487 -39.6334 +v 32.2640 61.1320 -39.6334 +v 33.4487 60.4480 -39.6334 +v 33.6320 59.7640 -39.6334 +v 33.6320 33.4866 -39.6334 +v 33.6320 -29.8820 -39.6334 +v 33.6320 13.4957 -39.6334 +v 33.6320 -59.7640 -39.6334 +v 33.4487 -60.4480 -39.6334 +v 32.9480 -60.9487 -39.6334 +v 32.2640 -61.1320 -39.6334 +v 15.0099 -61.1320 -39.6334 +v 15.0099 61.1320 -39.6334 +v 32.2640 59.7640 -40.0000 +v 32.2640 33.4866 -40.0000 +v 32.2640 -29.8820 -40.0000 +v 32.2640 13.4957 -40.0000 +v 32.2640 -59.7640 -40.0000 +v 15.0099 -59.7640 -40.0000 +v 15.0099 59.7640 -40.0000 +v 15.0099 -29.8820 -40.0000 +v 15.0099 13.4957 -40.0000 +v 15.0099 33.4866 -40.0000 +v 15.0099 13.4946 -3.9078 +v 15.0099 33.4866 -3.9078 +v -15.0099 19.0761 0.0000 +v -32.2640 19.0761 0.0000 +v -15.0099 19.0761 -3.9078 +v 15.0099 19.0761 -3.9078 +v 15.0099 19.0761 0.0000 +v 32.2640 19.0761 0.0000 +v 33.6320 19.0761 -0.3666 +v 34.6334 19.0761 -1.3680 +v 35.0000 19.0761 -2.7360 +v 35.0000 19.0761 -37.2640 +v 34.6334 19.0761 -38.6320 +v 33.6320 19.0761 -39.6334 +v 32.2640 19.0761 -40.0000 +v 15.0099 19.0761 -40.0000 +v 0.0000 19.0761 -40.0000 +v -15.0099 19.0761 -40.0000 +v -32.2640 19.0761 -40.0000 +v -35.0000 19.0761 -2.7360 +v -35.0000 19.0761 -37.2640 +v -34.6334 19.0761 -38.6320 +v -33.6320 19.0761 -39.6334 +v -33.6320 19.0761 -0.3666 +v -34.6334 19.0761 -1.3680 +# 247 vertices + +vn -0.1087 0.1087 0.9881 +vn -0.1305 -0.0000 0.9914 +vn 0.0000 -0.0000 1.0000 +vn 0.0000 0.1305 0.9914 +vn -0.1087 -0.1087 0.9881 +vn 0.0000 -0.1305 0.9914 +vn -0.0698 0.5140 0.8549 +vn -0.2655 0.4598 0.8474 +vn -0.4598 0.2655 0.8474 +vn -0.5140 0.0698 0.8549 +vn -0.5000 -0.0000 0.8660 +vn -0.5140 -0.0698 0.8549 +vn -0.4598 -0.2655 0.8474 +vn -0.2655 -0.4598 0.8474 +vn -0.0698 -0.5140 0.8549 +vn 0.0000 -0.5000 0.8660 +vn 0.0000 0.5000 0.8660 +vn -0.1129 0.8653 0.4883 +vn -0.4380 0.7586 0.4823 +vn -0.7586 0.4380 0.4823 +vn -0.8653 0.1129 0.4883 +vn -0.8660 -0.0000 0.5000 +vn -0.8653 -0.1129 0.4883 +vn -0.7586 -0.4380 0.4823 +vn -0.4380 -0.7586 0.4823 +vn -0.1129 -0.8653 0.4883 +vn 0.0000 -0.8660 0.5000 +vn 0.0000 0.8660 0.5000 +vn -0.1281 0.9834 0.1281 +vn -0.4959 0.8589 0.1278 +vn -0.8589 0.4959 0.1278 +vn -0.9834 0.1281 0.1281 +vn -0.9914 -0.0000 0.1305 +vn -0.9834 -0.1281 0.1281 +vn -0.8589 -0.4959 0.1278 +vn -0.4959 -0.8589 0.1278 +vn -0.1281 -0.9834 0.1281 +vn -0.0000 -0.9914 0.1305 +vn 0.0000 -0.9914 0.1305 +vn 0.0000 0.9914 0.1305 +vn -0.1281 0.9834 -0.1281 +vn -0.4959 0.8589 -0.1278 +vn -0.8589 0.4959 -0.1278 +vn -0.9834 0.1281 -0.1281 +vn -0.9914 0.0000 -0.1305 +vn -0.9834 -0.1281 -0.1281 +vn -0.8589 -0.4959 -0.1278 +vn -0.4959 -0.8589 -0.1278 +vn -0.1281 -0.9834 -0.1281 +vn -0.0000 -0.9914 -0.1305 +vn 0.0000 -0.9914 -0.1305 +vn 0.0000 0.9914 -0.1305 +vn -0.1129 0.8653 -0.4883 +vn -0.4380 0.7586 -0.4823 +vn -0.7586 0.4380 -0.4823 +vn -0.8653 0.1129 -0.4883 +vn -0.8660 0.0000 -0.5000 +vn -0.8653 -0.1129 -0.4883 +vn -0.7586 -0.4380 -0.4823 +vn -0.4380 -0.7586 -0.4823 +vn -0.1129 -0.8653 -0.4883 +vn -0.0000 -0.8660 -0.5000 +vn 0.0000 -0.8660 -0.5000 +vn 0.0000 0.8660 -0.5000 +vn -0.0698 0.5140 -0.8549 +vn -0.2655 0.4598 -0.8474 +vn -0.4598 0.2655 -0.8474 +vn -0.5140 0.0698 -0.8549 +vn -0.5000 0.0000 -0.8660 +vn -0.5140 -0.0698 -0.8549 +vn -0.4598 -0.2655 -0.8474 +vn -0.2655 -0.4598 -0.8474 +vn -0.0698 -0.5140 -0.8549 +vn 0.0000 -0.5000 -0.8660 +vn 0.0000 0.5000 -0.8660 +vn -0.1087 0.1087 -0.9881 +vn -0.1305 0.0000 -0.9914 +vn -0.1087 -0.1087 -0.9881 +vn 0.0000 -0.1305 -0.9914 +vn 0.0000 0.1305 -0.9914 +vn 0.0000 0.0000 -1.0000 +vn 0.0000 1.0000 -0.0001 +vn 0.0000 -1.0000 -0.0000 +vn 0.1305 -0.0000 0.9914 +vn 0.1087 0.1087 0.9881 +vn 0.1087 -0.1087 0.9881 +vn 0.2655 0.4598 0.8474 +vn 0.0698 0.5140 0.8549 +vn 0.4598 0.2655 0.8474 +vn 0.5140 0.0698 0.8549 +vn 0.5000 -0.0000 0.8660 +vn 0.5140 -0.0698 0.8549 +vn 0.4598 -0.2655 0.8474 +vn 0.2655 -0.4598 0.8474 +vn 0.0698 -0.5140 0.8549 +vn 0.4380 0.7586 0.4823 +vn 0.1129 0.8653 0.4883 +vn 0.7586 0.4380 0.4823 +vn 0.8653 0.1129 0.4883 +vn 0.8660 -0.0000 0.5000 +vn 0.8653 -0.1129 0.4883 +vn 0.7586 -0.4380 0.4823 +vn 0.4380 -0.7586 0.4823 +vn 0.1129 -0.8653 0.4883 +vn 0.4959 0.8589 0.1278 +vn 0.1281 0.9834 0.1281 +vn 0.8589 0.4959 0.1278 +vn 0.9834 0.1281 0.1281 +vn 0.9914 -0.0000 0.1305 +vn 0.9834 -0.1281 0.1281 +vn 0.8589 -0.4959 0.1278 +vn 0.4959 -0.8589 0.1278 +vn 0.1281 -0.9834 0.1281 +vn 0.4959 0.8589 -0.1278 +vn 0.1281 0.9834 -0.1281 +vn 0.8589 0.4959 -0.1278 +vn 0.9834 0.1281 -0.1281 +vn 0.9914 0.0000 -0.1305 +vn 0.9834 -0.1281 -0.1281 +vn 0.8589 -0.4959 -0.1278 +vn 0.4959 -0.8589 -0.1278 +vn 0.1281 -0.9834 -0.1281 +vn 0.4380 0.7586 -0.4823 +vn 0.1129 0.8653 -0.4883 +vn 0.7586 0.4380 -0.4823 +vn 0.8653 0.1129 -0.4883 +vn 0.8660 0.0000 -0.5000 +vn 0.8653 -0.1129 -0.4883 +vn 0.7586 -0.4380 -0.4823 +vn 0.4380 -0.7586 -0.4823 +vn 0.1129 -0.8653 -0.4883 +vn 0.2655 0.4598 -0.8474 +vn 0.0698 0.5140 -0.8549 +vn 0.4598 0.2655 -0.8474 +vn 0.5140 0.0698 -0.8549 +vn 0.5000 0.0000 -0.8660 +vn 0.5140 -0.0698 -0.8549 +vn 0.4598 -0.2655 -0.8474 +vn 0.2655 -0.4598 -0.8474 +vn 0.0698 -0.5140 -0.8549 +vn 0.1087 0.1087 -0.9881 +vn 0.1305 0.0000 -0.9914 +vn 0.1087 -0.1087 -0.9881 +vn 1.0000 0.0000 -0.0000 +vn 1.0000 -0.0000 -0.0000 +vn -1.0000 0.0000 -0.0000 +vn -1.0000 -0.0000 -0.0000 +# 147 vertex normals + +vt 0.6861 0.4001 0.9995 +vt 0.6861 0.3350 0.9995 +vt 0.7409 0.3350 0.9995 +vt 0.7409 0.4001 0.9995 +vt 0.7885 0.3350 0.9995 +vt 0.7885 0.4001 0.9995 +vt 0.6861 0.2855 0.9995 +vt 0.6861 0.1780 0.9995 +vt 0.7409 0.1780 0.9995 +vt 0.7409 0.2855 0.9995 +vt 0.7885 0.1780 0.9995 +vt 0.7885 0.2855 0.9995 +vt 0.6861 0.1040 0.9995 +vt 0.7409 0.1040 0.9995 +vt 0.7885 0.1040 0.9995 +vt 0.6861 0.4035 0.9903 +vt 0.6839 0.4030 0.9903 +vt 0.6823 0.4018 0.9903 +vt 0.6817 0.4001 0.9903 +vt 0.6817 0.3350 0.9903 +vt 0.6817 0.2855 0.9903 +vt 0.6817 0.1780 0.9903 +vt 0.6817 0.1040 0.9903 +vt 0.6823 0.1023 0.9903 +vt 0.6839 0.1010 0.9903 +vt 0.6861 0.1006 0.9903 +vt 0.7409 0.1006 0.9903 +vt 0.7885 0.1006 0.9903 +vt 0.7885 0.4035 0.9903 +vt 0.7409 0.4035 0.9903 +vt 0.6861 0.4059 0.9653 +vt 0.6823 0.4052 0.9653 +vt 0.6795 0.4030 0.9653 +vt 0.6785 0.4001 0.9653 +vt 0.6785 0.3350 0.9653 +vt 0.6785 0.2855 0.9653 +vt 0.6785 0.1780 0.9653 +vt 0.6785 0.1040 0.9653 +vt 0.6795 0.1010 0.9653 +vt 0.6823 0.0989 0.9653 +vt 0.6861 0.0981 0.9653 +vt 0.7409 0.0981 0.9653 +vt 0.7885 0.0981 0.9653 +vt 0.7885 0.4059 0.9653 +vt 0.7409 0.4059 0.9653 +vt 0.6861 0.4068 0.9312 +vt 0.6817 0.4059 0.9312 +vt 0.6785 0.4035 0.9312 +vt 0.6774 0.4001 0.9312 +vt 0.6774 0.3350 0.9312 +vt 0.6774 0.2855 0.9312 +vt 0.6774 0.1780 0.9312 +vt 0.6774 0.1040 0.9312 +vt 0.6785 0.1006 0.9312 +vt 0.6817 0.0981 0.9312 +vt 0.6861 0.0972 0.9312 +vt 0.7409 0.0972 0.9312 +vt 0.7885 0.0972 0.9312 +vt 0.7885 0.4068 0.9312 +vt 0.7409 0.4068 0.9312 +vt 0.6861 0.4068 0.0688 +vt 0.6817 0.4059 0.0688 +vt 0.6785 0.4035 0.0688 +vt 0.6774 0.4001 0.0688 +vt 0.6774 0.3350 0.0688 +vt 0.6774 0.2855 0.0688 +vt 0.6774 0.1780 0.0688 +vt 0.6774 0.1040 0.0688 +vt 0.6785 0.1006 0.0688 +vt 0.6817 0.0981 0.0688 +vt 0.6861 0.0972 0.0688 +vt 0.7409 0.0972 0.0688 +vt 0.7885 0.0972 0.0688 +vt 0.7885 0.4068 0.0688 +vt 0.7409 0.4068 0.0688 +vt 0.6861 0.4059 0.0347 +vt 0.6823 0.4052 0.0347 +vt 0.6795 0.4030 0.0347 +vt 0.6785 0.4001 0.0347 +vt 0.6785 0.3350 0.0347 +vt 0.6785 0.2855 0.0347 +vt 0.6785 0.1780 0.0347 +vt 0.6785 0.1040 0.0347 +vt 0.6795 0.1010 0.0347 +vt 0.6823 0.0989 0.0347 +vt 0.6861 0.0981 0.0347 +vt 0.7409 0.0981 0.0347 +vt 0.7885 0.0981 0.0347 +vt 0.7885 0.4059 0.0347 +vt 0.7409 0.4059 0.0347 +vt 0.6861 0.4035 0.0097 +vt 0.6839 0.4030 0.0097 +vt 0.6823 0.4018 0.0097 +vt 0.6817 0.4001 0.0097 +vt 0.6817 0.3350 0.0097 +vt 0.6817 0.2855 0.0097 +vt 0.6817 0.1780 0.0097 +vt 0.6817 0.1040 0.0097 +vt 0.6823 0.1023 0.0097 +vt 0.6839 0.1010 0.0097 +vt 0.6861 0.1006 0.0097 +vt 0.7409 0.1006 0.0097 +vt 0.7885 0.1006 0.0097 +vt 0.7885 0.4035 0.0097 +vt 0.7409 0.4035 0.0097 +vt 0.6861 0.4001 0.0005 +vt 0.6861 0.3350 0.0005 +vt 0.6861 0.2855 0.0005 +vt 0.6861 0.1780 0.0005 +vt 0.6861 0.1040 0.0005 +vt 0.7409 0.1040 0.0005 +vt 0.7885 0.1040 0.0005 +vt 0.7885 0.4001 0.0005 +vt 0.7409 0.4001 0.0005 +vt 0.7885 0.1780 0.0005 +vt 0.7409 0.1780 0.0005 +vt 0.7885 0.2855 0.0005 +vt 0.7409 0.2855 0.0005 +vt 0.7885 0.3350 0.0005 +vt 0.7409 0.3350 0.0005 +vt 0.7885 0.2854 0.9019 +vt 0.7409 0.2854 0.9019 +vt 0.7409 0.3350 0.9019 +vt 0.7885 0.3350 0.9019 +vt 0.8362 0.3350 0.9995 +vt 0.8910 0.3350 0.9995 +vt 0.8910 0.4001 0.9995 +vt 0.8362 0.4001 0.9995 +vt 0.8362 0.1780 0.9995 +vt 0.8910 0.1780 0.9995 +vt 0.8910 0.2855 0.9995 +vt 0.8362 0.2855 0.9995 +vt 0.8362 0.1040 0.9995 +vt 0.8910 0.1040 0.9995 +vt 0.8932 0.4030 0.9903 +vt 0.8910 0.4035 0.9903 +vt 0.8948 0.4018 0.9903 +vt 0.8953 0.4001 0.9903 +vt 0.8953 0.3350 0.9903 +vt 0.8953 0.1780 0.9903 +vt 0.8953 0.2855 0.9903 +vt 0.8953 0.1040 0.9903 +vt 0.8948 0.1023 0.9903 +vt 0.8932 0.1010 0.9903 +vt 0.8910 0.1006 0.9903 +vt 0.8362 0.1006 0.9903 +vt 0.8362 0.4035 0.9903 +vt 0.8948 0.4052 0.9653 +vt 0.8910 0.4059 0.9653 +vt 0.8975 0.4030 0.9653 +vt 0.8985 0.4001 0.9653 +vt 0.8985 0.3350 0.9653 +vt 0.8985 0.1780 0.9653 +vt 0.8985 0.2855 0.9653 +vt 0.8985 0.1040 0.9653 +vt 0.8975 0.1010 0.9653 +vt 0.8948 0.0989 0.9653 +vt 0.8910 0.0981 0.9653 +vt 0.8362 0.0981 0.9653 +vt 0.8362 0.4059 0.9653 +vt 0.8953 0.4059 0.9312 +vt 0.8910 0.4068 0.9312 +vt 0.8985 0.4035 0.9312 +vt 0.8997 0.4001 0.9312 +vt 0.8997 0.3350 0.9312 +vt 0.8997 0.1780 0.9312 +vt 0.8997 0.2855 0.9312 +vt 0.8997 0.1040 0.9312 +vt 0.8985 0.1006 0.9312 +vt 0.8953 0.0981 0.9312 +vt 0.8910 0.0972 0.9312 +vt 0.8362 0.0972 0.9312 +vt 0.8362 0.4068 0.9312 +vt 0.8953 0.4059 0.0688 +vt 0.8910 0.4068 0.0688 +vt 0.8985 0.4035 0.0688 +vt 0.8997 0.4001 0.0688 +vt 0.8997 0.3350 0.0688 +vt 0.8997 0.1780 0.0688 +vt 0.8997 0.2855 0.0688 +vt 0.8997 0.1040 0.0688 +vt 0.8985 0.1006 0.0688 +vt 0.8953 0.0981 0.0688 +vt 0.8910 0.0972 0.0688 +vt 0.8362 0.0972 0.0688 +vt 0.8362 0.4068 0.0688 +vt 0.8948 0.4052 0.0347 +vt 0.8910 0.4059 0.0347 +vt 0.8975 0.4030 0.0347 +vt 0.8985 0.4001 0.0347 +vt 0.8985 0.3350 0.0347 +vt 0.8985 0.1780 0.0347 +vt 0.8985 0.2855 0.0347 +vt 0.8985 0.1040 0.0347 +vt 0.8975 0.1010 0.0347 +vt 0.8948 0.0989 0.0347 +vt 0.8910 0.0981 0.0347 +vt 0.8362 0.0981 0.0347 +vt 0.8362 0.4059 0.0347 +vt 0.8932 0.4030 0.0097 +vt 0.8910 0.4035 0.0097 +vt 0.8948 0.4018 0.0097 +vt 0.8953 0.4001 0.0097 +vt 0.8953 0.3350 0.0097 +vt 0.8953 0.1780 0.0097 +vt 0.8953 0.2855 0.0097 +vt 0.8953 0.1040 0.0097 +vt 0.8948 0.1023 0.0097 +vt 0.8932 0.1010 0.0097 +vt 0.8910 0.1006 0.0097 +vt 0.8362 0.1006 0.0097 +vt 0.8362 0.4035 0.0097 +vt 0.8910 0.4001 0.0005 +vt 0.8910 0.3350 0.0005 +vt 0.8910 0.1780 0.0005 +vt 0.8910 0.2855 0.0005 +vt 0.8910 0.1040 0.0005 +vt 0.8362 0.1040 0.0005 +vt 0.8362 0.4001 0.0005 +vt 0.8362 0.1780 0.0005 +vt 0.8362 0.2855 0.0005 +vt 0.8362 0.3350 0.0005 +vt 0.8362 0.2854 0.9019 +vt 0.8362 0.3350 0.9019 +vt 0.6622 0.0035 0.9995 +vt 0.6622 0.4468 0.9995 +vt -0.2323 0.4468 0.9995 +vt -0.2323 0.0035 0.9995 +vt 0.7409 0.2993 0.9995 +vt 0.7409 0.2993 0.9019 +vt 0.8362 0.2993 0.9019 +vt 0.8362 0.2993 0.9995 +vt 0.9822 0.5590 0.9995 +vt 0.9822 0.9711 0.9995 +vt 0.0132 0.9711 0.9995 +vt 0.0132 0.5590 0.9995 +vt 0.8953 0.2993 0.9903 +vt 0.8910 0.2993 0.9995 +vt 0.8985 0.2993 0.9653 +vt 0.8997 0.2993 0.9312 +vt 0.8997 0.2993 0.0688 +vt 0.8985 0.2993 0.0347 +vt 0.8953 0.2993 0.0097 +vt 0.8910 0.2993 0.0005 +vt 0.8362 0.2993 0.0005 +vt 0.7885 0.2993 0.0005 +vt 0.7409 0.2993 0.0005 +vt 0.6861 0.2993 0.0005 +vt 0.6774 0.2993 0.9312 +vt 0.6774 0.2993 0.0688 +vt 0.6785 0.2993 0.0347 +vt 0.6817 0.2993 0.0097 +vt 0.6861 0.2993 0.9995 +vt 0.6817 0.2993 0.9903 +vt 0.6785 0.2993 0.9653 +# 255 texture coords + +g box +usemtl 01___Default +s 1 +f 1/1/1 2/2/2 3/3/3 4/4/4 +f 4/4/4 3/3/3 5/5/3 6/6/4 +f 7/7/2 8/8/2 9/9/3 10/10/3 +f 10/10/3 9/9/3 11/11/3 12/12/3 +f 8/8/2 13/13/5 14/14/6 9/9/3 +f 9/9/3 14/14/6 15/15/6 11/11/3 +f 1/1/1 16/16/7 17/17/8 +f 1/1/1 17/17/8 18/18/9 +f 1/1/1 18/18/9 19/19/10 +f 1/1/1 19/19/10 20/20/11 2/2/2 +f 7/7/2 21/21/11 22/22/11 8/8/2 +f 8/8/2 22/22/11 23/23/12 13/13/5 +f 13/13/5 23/23/12 24/24/13 +f 13/13/5 24/24/13 25/25/14 +f 13/13/5 25/25/14 26/26/15 +f 13/13/5 26/26/15 27/27/16 14/14/6 +f 14/14/6 27/27/16 28/28/16 15/15/6 +f 6/6/4 29/29/17 30/30/17 4/4/4 +f 4/4/4 30/30/17 16/16/7 1/1/1 +f 16/16/7 31/31/18 32/32/19 17/17/8 +f 17/17/8 32/32/19 33/33/20 18/18/9 +f 18/18/9 33/33/20 34/34/21 19/19/10 +f 19/19/10 34/34/21 35/35/22 20/20/11 +f 21/21/11 36/36/22 37/37/22 22/22/11 +f 22/22/11 37/37/22 38/38/23 23/23/12 +f 23/23/12 38/38/23 39/39/24 24/24/13 +f 24/24/13 39/39/24 40/40/25 25/25/14 +f 25/25/14 40/40/25 41/41/26 26/26/15 +f 26/26/15 41/41/26 42/42/27 27/27/16 +f 27/27/16 42/42/27 43/43/27 28/28/16 +f 29/29/17 44/44/28 45/45/28 30/30/17 +f 30/30/17 45/45/28 31/31/18 16/16/7 +f 31/31/18 46/46/29 47/47/30 32/32/19 +f 32/32/19 47/47/30 48/48/31 33/33/20 +f 33/33/20 48/48/31 49/49/32 34/34/21 +f 34/34/21 49/49/32 50/50/33 35/35/22 +f 36/36/22 51/51/33 52/52/33 37/37/22 +f 37/37/22 52/52/33 53/53/34 38/38/23 +f 38/38/23 53/53/34 54/54/35 39/39/24 +f 39/39/24 54/54/35 55/55/36 40/40/25 +f 40/40/25 55/55/36 56/56/37 41/41/26 +f 41/41/26 56/56/37 57/57/38 42/42/27 +f 42/42/27 57/57/38 58/58/39 43/43/27 +f 44/44/28 59/59/40 60/60/40 45/45/28 +f 45/45/28 60/60/40 46/46/29 31/31/18 +f 46/46/29 61/61/41 62/62/42 47/47/30 +f 47/47/30 62/62/42 63/63/43 48/48/31 +f 48/48/31 63/63/43 64/64/44 49/49/32 +f 49/49/32 64/64/44 65/65/45 50/50/33 +f 51/51/33 66/66/45 67/67/45 52/52/33 +f 52/52/33 67/67/45 68/68/46 53/53/34 +f 53/53/34 68/68/46 69/69/47 54/54/35 +f 54/54/35 69/69/47 70/70/48 55/55/36 +f 55/55/36 70/70/48 71/71/49 56/56/37 +f 56/56/37 71/71/49 72/72/50 57/57/38 +f 57/57/38 72/72/50 73/73/51 58/58/39 +f 59/59/40 74/74/52 75/75/52 60/60/40 +f 60/60/40 75/75/52 61/61/41 46/46/29 +f 61/61/41 76/76/53 77/77/54 62/62/42 +f 62/62/42 77/77/54 78/78/55 63/63/43 +f 63/63/43 78/78/55 79/79/56 64/64/44 +f 64/64/44 79/79/56 80/80/57 65/65/45 +f 66/66/45 81/81/57 82/82/57 67/67/45 +f 67/67/45 82/82/57 83/83/58 68/68/46 +f 68/68/46 83/83/58 84/84/59 69/69/47 +f 69/69/47 84/84/59 85/85/60 70/70/48 +f 70/70/48 85/85/60 86/86/61 71/71/49 +f 71/71/49 86/86/61 87/87/62 72/72/50 +f 72/72/50 87/87/62 88/88/63 73/73/51 +f 74/74/52 89/89/64 90/90/64 75/75/52 +f 75/75/52 90/90/64 76/76/53 61/61/41 +f 76/76/53 91/91/65 92/92/66 77/77/54 +f 77/77/54 92/92/66 93/93/67 78/78/55 +f 78/78/55 93/93/67 94/94/68 79/79/56 +f 79/79/56 94/94/68 95/95/69 80/80/57 +f 81/81/57 96/96/69 97/97/69 82/82/57 +f 82/82/57 97/97/69 98/98/70 83/83/58 +f 83/83/58 98/98/70 99/99/71 84/84/59 +f 84/84/59 99/99/71 100/100/72 85/85/60 +f 85/85/60 100/100/72 101/101/73 86/86/61 +f 86/86/61 101/101/73 102/102/74 87/87/62 +f 87/87/62 102/102/74 103/103/74 88/88/63 +f 89/89/64 104/104/75 105/105/75 90/90/64 +f 90/90/64 105/105/75 91/91/65 76/76/53 +f 91/91/65 106/106/76 92/92/66 +f 92/92/66 106/106/76 93/93/67 +f 93/93/67 106/106/76 94/94/68 +f 94/94/68 106/106/76 107/107/77 95/95/69 +f 96/96/69 108/108/77 109/109/77 97/97/69 +f 97/97/69 109/109/77 110/110/78 98/98/70 +f 98/98/70 110/110/78 99/99/71 +f 99/99/71 110/110/78 100/100/72 +f 100/100/72 110/110/78 101/101/73 +f 101/101/73 110/110/78 111/111/79 102/102/74 +f 102/102/74 111/111/79 112/112/79 103/103/74 +f 104/104/75 113/113/80 114/114/80 105/105/75 +f 105/105/75 114/114/80 106/106/76 91/91/65 +f 115/115/81 112/112/79 111/111/79 116/116/81 +f 116/116/81 111/111/79 110/110/78 109/109/77 +f 117/117/81 115/115/81 116/116/81 118/118/81 +f 118/118/81 116/116/81 109/109/77 108/108/77 +f 113/113/80 119/119/81 120/120/81 114/114/80 +f 114/114/80 120/120/81 107/107/77 106/106/76 +s 2 +f 121/121/82 122/122/82 10/10/82 12/12/82 +f 123/123/83 124/124/83 5/5/83 3/3/83 +s 1 +f 125/125/3 126/126/84 127/127/85 128/128/4 +f 5/5/3 125/125/3 128/128/4 6/6/4 +f 129/129/3 130/130/84 131/131/84 132/132/3 +f 11/11/3 129/129/3 132/132/3 12/12/3 +f 133/133/6 134/134/86 130/130/84 129/129/3 +f 15/15/6 133/133/6 129/129/3 11/11/3 +f 127/127/85 135/135/87 136/136/88 +f 127/127/85 137/137/89 135/135/87 +f 127/127/85 138/138/90 137/137/89 +f 139/139/91 138/138/90 127/127/85 126/126/84 +f 140/140/91 141/141/91 131/131/84 130/130/84 +f 142/142/92 140/140/91 130/130/84 134/134/86 +f 134/134/86 143/143/93 142/142/92 +f 134/134/86 144/144/94 143/143/93 +f 134/134/86 145/145/95 144/144/94 +f 146/146/16 145/145/95 134/134/86 133/133/6 +f 28/28/16 146/146/16 133/133/6 15/15/6 +f 147/147/17 29/29/17 6/6/4 128/128/4 +f 136/136/88 147/147/17 128/128/4 127/127/85 +f 148/148/96 149/149/97 136/136/88 135/135/87 +f 150/150/98 148/148/96 135/135/87 137/137/89 +f 151/151/99 150/150/98 137/137/89 138/138/90 +f 152/152/100 151/151/99 138/138/90 139/139/91 +f 153/153/100 154/154/100 141/141/91 140/140/91 +f 155/155/101 153/153/100 140/140/91 142/142/92 +f 156/156/102 155/155/101 142/142/92 143/143/93 +f 157/157/103 156/156/102 143/143/93 144/144/94 +f 158/158/104 157/157/103 144/144/94 145/145/95 +f 159/159/27 158/158/104 145/145/95 146/146/16 +f 43/43/27 159/159/27 146/146/16 28/28/16 +f 160/160/28 44/44/28 29/29/17 147/147/17 +f 149/149/97 160/160/28 147/147/17 136/136/88 +f 161/161/105 162/162/106 149/149/97 148/148/96 +f 163/163/107 161/161/105 148/148/96 150/150/98 +f 164/164/108 163/163/107 150/150/98 151/151/99 +f 165/165/109 164/164/108 151/151/99 152/152/100 +f 166/166/109 167/167/109 154/154/100 153/153/100 +f 168/168/110 166/166/109 153/153/100 155/155/101 +f 169/169/111 168/168/110 155/155/101 156/156/102 +f 170/170/112 169/169/111 156/156/102 157/157/103 +f 171/171/113 170/170/112 157/157/103 158/158/104 +f 172/172/39 171/171/113 158/158/104 159/159/27 +f 58/58/39 172/172/39 159/159/27 43/43/27 +f 173/173/40 59/59/40 44/44/28 160/160/28 +f 162/162/106 173/173/40 160/160/28 149/149/97 +f 174/174/114 175/175/115 162/162/106 161/161/105 +f 176/176/116 174/174/114 161/161/105 163/163/107 +f 177/177/117 176/176/116 163/163/107 164/164/108 +f 178/178/118 177/177/117 164/164/108 165/165/109 +f 179/179/118 180/180/118 167/167/109 166/166/109 +f 181/181/119 179/179/118 166/166/109 168/168/110 +f 182/182/120 181/181/119 168/168/110 169/169/111 +f 183/183/121 182/182/120 169/169/111 170/170/112 +f 184/184/122 183/183/121 170/170/112 171/171/113 +f 185/185/51 184/184/122 171/171/113 172/172/39 +f 73/73/51 185/185/51 172/172/39 58/58/39 +f 186/186/52 74/74/52 59/59/40 173/173/40 +f 175/175/115 186/186/52 173/173/40 162/162/106 +f 187/187/123 188/188/124 175/175/115 174/174/114 +f 189/189/125 187/187/123 174/174/114 176/176/116 +f 190/190/126 189/189/125 176/176/116 177/177/117 +f 191/191/127 190/190/126 177/177/117 178/178/118 +f 192/192/127 193/193/127 180/180/118 179/179/118 +f 194/194/128 192/192/127 179/179/118 181/181/119 +f 195/195/129 194/194/128 181/181/119 182/182/120 +f 196/196/130 195/195/129 182/182/120 183/183/121 +f 197/197/131 196/196/130 183/183/121 184/184/122 +f 198/198/63 197/197/131 184/184/122 185/185/51 +f 88/88/63 198/198/63 185/185/51 73/73/51 +f 199/199/64 89/89/64 74/74/52 186/186/52 +f 188/188/124 199/199/64 186/186/52 175/175/115 +f 200/200/132 201/201/133 188/188/124 187/187/123 +f 202/202/134 200/200/132 187/187/123 189/189/125 +f 203/203/135 202/202/134 189/189/125 190/190/126 +f 204/204/136 203/203/135 190/190/126 191/191/127 +f 205/205/136 206/206/136 193/193/127 192/192/127 +f 207/207/137 205/205/136 192/192/127 194/194/128 +f 208/208/138 207/207/137 194/194/128 195/195/129 +f 209/209/139 208/208/138 195/195/129 196/196/130 +f 210/210/140 209/209/139 196/196/130 197/197/131 +f 211/211/74 210/210/140 197/197/131 198/198/63 +f 103/103/74 211/211/74 198/198/63 88/88/63 +f 212/212/75 104/104/75 89/89/64 199/199/64 +f 201/201/133 212/212/75 199/199/64 188/188/124 +f 201/201/133 200/200/132 213/213/141 +f 200/200/132 202/202/134 213/213/141 +f 202/202/134 203/203/135 213/213/141 +f 214/214/142 213/213/141 203/203/135 204/204/136 +f 215/215/142 216/216/142 206/206/136 205/205/136 +f 217/217/143 215/215/142 205/205/136 207/207/137 +f 207/207/137 208/208/138 217/217/143 +f 208/208/138 209/209/139 217/217/143 +f 209/209/139 210/210/140 217/217/143 +f 218/218/79 217/217/143 210/210/140 211/211/74 +f 112/112/79 218/218/79 211/211/74 103/103/74 +f 219/219/80 113/113/80 104/104/75 212/212/75 +f 213/213/141 219/219/80 212/212/75 201/201/133 +f 218/218/79 112/112/79 115/115/81 220/220/81 +f 217/217/143 218/218/79 220/220/81 215/215/142 +f 220/220/81 115/115/81 117/117/81 221/221/81 +f 215/215/142 220/220/81 221/221/81 216/216/142 +f 222/222/81 119/119/81 113/113/80 219/219/80 +f 214/214/142 222/222/81 219/219/80 213/213/141 +s 2 +f 132/132/82 223/223/82 121/121/82 12/12/82 +f 5/5/83 124/124/83 224/224/83 125/125/83 +s 1 +f 10/225/3 225/226/3 226/227/2 7/228/2 +s 4 +f 3/3/144 225/229/145 227/230/145 123/123/144 +f 224/224/146 228/231/146 229/232/147 125/125/146 +s 1 +f 131/233/84 230/234/84 229/235/3 132/236/3 +f 141/141/91 231/237/91 230/238/84 131/131/84 +f 154/154/100 232/239/100 231/237/91 141/141/91 +f 167/167/109 233/240/109 232/239/100 154/154/100 +f 180/180/118 234/241/118 233/240/109 167/167/109 +f 193/193/127 235/242/127 234/241/118 180/180/118 +f 206/206/136 236/243/136 235/242/127 193/193/127 +f 216/216/142 237/244/142 236/243/136 206/206/136 +f 214/214/142 237/244/142 238/245/81 222/222/81 +f 222/222/81 238/245/81 239/246/81 119/119/81 +f 119/119/81 239/246/81 240/247/81 120/120/81 +f 120/120/81 240/247/81 241/248/77 107/107/77 +f 51/51/33 242/249/33 243/250/45 66/66/45 +f 66/66/45 243/250/45 244/251/57 81/81/57 +f 81/81/57 244/251/57 245/252/69 96/96/69 +f 96/96/69 245/252/69 241/248/77 108/108/77 +f 7/7/2 226/253/2 246/254/11 21/21/11 +f 21/21/11 246/254/11 247/255/22 36/36/22 +f 36/36/22 247/255/22 242/249/33 51/51/33 +f 3/3/3 2/2/2 226/253/2 225/229/3 +s 4 +f 10/10/145 122/122/144 227/230/145 225/229/145 +f 223/223/147 132/132/147 229/232/147 228/231/146 +s 1 +f 126/126/84 125/125/3 229/232/3 230/238/84 +f 139/139/91 126/126/84 230/238/84 231/237/91 +f 152/152/100 139/139/91 231/237/91 232/239/100 +f 165/165/109 152/152/100 232/239/100 233/240/109 +f 178/178/118 165/165/109 233/240/109 234/241/118 +f 191/191/127 178/178/118 234/241/118 235/242/127 +f 204/204/136 191/191/127 235/242/127 236/243/136 +f 214/214/142 204/204/136 236/243/136 237/244/142 +f 216/216/142 221/221/81 238/245/81 237/244/142 +f 221/221/81 117/117/81 239/246/81 238/245/81 +f 117/117/81 118/118/81 240/247/81 239/246/81 +f 118/118/81 108/108/77 241/248/77 240/247/81 +f 50/50/33 65/65/45 243/250/45 242/249/33 +f 65/65/45 80/80/57 244/251/57 243/250/45 +f 80/80/57 95/95/69 245/252/69 244/251/57 +f 95/95/69 107/107/77 241/248/77 245/252/69 +f 2/2/2 20/20/11 246/254/11 226/253/2 +f 20/20/11 35/35/22 247/255/22 246/254/11 +f 35/35/22 50/50/33 242/249/33 247/255/22 +# 230 polygons - 24 triangles + +# +# object button2 +# + +v 25.4066 4.8805 4.4808 +v 26.0012 4.8805 4.4808 +v 25.9559 5.1080 4.4808 +v 25.8270 5.3009 4.4808 +v 25.6341 5.4298 4.4808 +v 25.4066 5.4750 4.4808 +v 25.1791 5.4298 4.4808 +v 24.9862 5.3009 4.4808 +v 24.8573 5.1080 4.4808 +v 24.8121 4.8805 4.4808 +v 24.8573 4.6529 4.4808 +v 24.9862 4.4601 4.4808 +v 25.1791 4.3312 4.4808 +v 25.4066 4.2859 4.4808 +v 25.6341 4.3312 4.4808 +v 25.8270 4.4601 4.4808 +v 25.9559 4.6529 4.4808 +v 26.9950 4.8805 4.0692 +v 26.8741 5.4883 4.0692 +v 26.5298 6.0036 4.0692 +v 26.0145 6.3479 4.0692 +v 25.4066 6.4688 4.0692 +v 24.7988 6.3479 4.0692 +v 24.2835 6.0036 4.0692 +v 23.9392 5.4883 4.0692 +v 23.8183 4.8805 4.0692 +v 23.9392 4.2726 4.0692 +v 24.2835 3.7573 4.0692 +v 24.7988 3.4130 4.0692 +v 25.4066 3.2921 4.0692 +v 26.0145 3.4130 4.0692 +v 26.5298 3.7573 4.0692 +v 26.8741 4.2726 4.0692 +v 27.4066 4.8805 3.0753 +v 27.2544 5.6458 3.0753 +v 26.8208 6.2947 3.0753 +v 26.1720 6.7282 3.0753 +v 25.4066 6.8805 3.0753 +v 24.6413 6.7282 3.0753 +v 23.9924 6.2947 3.0753 +v 23.5589 5.6458 3.0753 +v 23.4066 4.8805 3.0753 +v 23.5589 4.1151 3.0753 +v 23.9924 3.4663 3.0753 +v 24.6413 3.0327 3.0753 +v 25.4066 2.8805 3.0753 +v 26.1720 3.0327 3.0753 +v 26.8208 3.4663 3.0753 +v 27.2544 4.1151 3.0753 +v 27.4066 4.8805 -2.0476 +v 27.2544 5.6458 -2.0476 +v 26.8208 6.2947 -2.0476 +v 26.1720 6.7282 -2.0476 +v 25.4066 6.8805 -2.0476 +v 24.6413 6.7282 -2.0476 +v 23.9924 6.2947 -2.0476 +v 23.5589 5.6458 -2.0476 +v 23.4066 4.8805 -2.0476 +v 23.5589 4.1151 -2.0476 +v 23.9924 3.4663 -2.0476 +v 24.6413 3.0327 -2.0476 +v 25.4066 2.8805 -2.0476 +v 26.1720 3.0327 -2.0476 +v 26.8208 3.4663 -2.0476 +v 27.2544 4.1151 -2.0476 +v 26.9950 4.8805 -3.0415 +v 26.8741 5.4883 -3.0415 +v 26.5298 6.0036 -3.0415 +v 26.0145 6.3479 -3.0415 +v 25.4066 6.4688 -3.0415 +v 24.7988 6.3479 -3.0415 +v 24.2835 6.0036 -3.0415 +v 23.9392 5.4883 -3.0415 +v 23.8183 4.8805 -3.0415 +v 23.9392 4.2726 -3.0415 +v 24.2835 3.7573 -3.0415 +v 24.7988 3.4130 -3.0415 +v 25.4066 3.2921 -3.0415 +v 26.0145 3.4130 -3.0415 +v 26.5298 3.7573 -3.0415 +v 26.8741 4.2726 -3.0415 +v 26.0012 4.8805 -3.4531 +v 25.9559 5.1080 -3.4531 +v 25.8270 5.3009 -3.4531 +v 25.6341 5.4298 -3.4531 +v 25.4066 5.4750 -3.4531 +v 25.1791 5.4298 -3.4531 +v 24.9862 5.3009 -3.4531 +v 24.8573 5.1080 -3.4531 +v 24.8121 4.8805 -3.4531 +v 24.8573 4.6529 -3.4531 +v 24.9862 4.4601 -3.4531 +v 25.1791 4.3312 -3.4531 +v 25.4066 4.2859 -3.4531 +v 25.6341 4.3312 -3.4531 +v 25.8270 4.4601 -3.4531 +v 25.9559 4.6529 -3.4531 +v 25.4066 4.8805 -3.4531 +# 98 vertices + +vn 0.0000 -0.0000 1.0000 +vn 0.2183 -0.0000 0.9759 +vn 0.2017 0.0835 0.9759 +vn 0.1544 0.1544 0.9759 +vn 0.0835 0.2017 0.9759 +vn 0.0000 0.2183 0.9759 +vn -0.0835 0.2017 0.9759 +vn -0.1544 0.1544 0.9759 +vn -0.2017 0.0835 0.9759 +vn -0.2183 -0.0000 0.9759 +vn -0.2017 -0.0835 0.9759 +vn -0.1544 -0.1544 0.9759 +vn -0.0835 -0.2017 0.9759 +vn 0.0000 -0.2183 0.9759 +vn 0.0835 -0.2017 0.9759 +vn 0.1544 -0.1544 0.9759 +vn 0.2017 -0.0835 0.9759 +vn 0.7294 0.0000 0.6840 +vn 0.6739 0.2791 0.6840 +vn 0.5158 0.5158 0.6840 +vn 0.2791 0.6739 0.6840 +vn 0.0000 0.7294 0.6840 +vn -0.2791 0.6739 0.6840 +vn -0.5158 0.5158 0.6840 +vn -0.6739 0.2791 0.6840 +vn -0.7294 0.0000 0.6840 +vn -0.6739 -0.2791 0.6840 +vn -0.5158 -0.5158 0.6840 +vn -0.2791 -0.6739 0.6840 +vn 0.0000 -0.7294 0.6840 +vn 0.2791 -0.6739 0.6840 +vn 0.5158 -0.5158 0.6840 +vn 0.6739 -0.2791 0.6840 +vn 0.9817 0.0000 0.1906 +vn 0.9069 0.3757 0.1906 +vn 0.6941 0.6941 0.1906 +vn 0.3757 0.9069 0.1906 +vn 0.0000 0.9817 0.1906 +vn -0.3757 0.9069 0.1906 +vn -0.6941 0.6941 0.1906 +vn -0.9069 0.3757 0.1906 +vn -0.9817 0.0000 0.1906 +vn -0.9069 -0.3757 0.1906 +vn -0.6941 -0.6941 0.1906 +vn -0.3757 -0.9069 0.1906 +vn 0.0000 -0.9817 0.1906 +vn 0.3757 -0.9069 0.1906 +vn 0.6941 -0.6941 0.1906 +vn 0.9069 -0.3757 0.1906 +vn 0.9817 0.0000 -0.1906 +vn 0.9069 0.3757 -0.1906 +vn 0.6941 0.6941 -0.1906 +vn 0.3757 0.9069 -0.1906 +vn 0.0000 0.9817 -0.1906 +vn -0.3757 0.9069 -0.1906 +vn -0.6941 0.6941 -0.1906 +vn -0.9069 0.3757 -0.1906 +vn -0.9817 0.0000 -0.1906 +vn -0.9069 -0.3757 -0.1906 +vn -0.6941 -0.6941 -0.1906 +vn -0.3757 -0.9069 -0.1906 +vn 0.0000 -0.9817 -0.1906 +vn 0.3757 -0.9069 -0.1906 +vn 0.6941 -0.6941 -0.1906 +vn 0.9069 -0.3757 -0.1906 +vn 0.7294 0.0000 -0.6840 +vn 0.6739 0.2791 -0.6840 +vn 0.5158 0.5158 -0.6840 +vn 0.2791 0.6739 -0.6840 +vn -0.0000 0.7294 -0.6840 +vn -0.2791 0.6739 -0.6840 +vn -0.5158 0.5158 -0.6840 +vn -0.6739 0.2791 -0.6840 +vn -0.7294 0.0000 -0.6840 +vn -0.6739 -0.2791 -0.6840 +vn -0.5158 -0.5158 -0.6840 +vn -0.2791 -0.6739 -0.6840 +vn 0.0000 -0.7294 -0.6840 +vn 0.2791 -0.6739 -0.6840 +vn 0.5158 -0.5158 -0.6840 +vn 0.6739 -0.2791 -0.6840 +vn 0.2183 0.0000 -0.9759 +vn 0.2017 0.0835 -0.9759 +vn 0.1544 0.1544 -0.9759 +vn 0.0835 0.2017 -0.9759 +vn -0.0000 0.2183 -0.9759 +vn -0.0835 0.2017 -0.9759 +vn -0.1544 0.1544 -0.9759 +vn -0.2017 0.0835 -0.9759 +vn -0.2183 0.0000 -0.9759 +vn -0.2017 -0.0835 -0.9759 +vn -0.1544 -0.1544 -0.9759 +vn -0.0835 -0.2017 -0.9759 +vn 0.0000 -0.2183 -0.9759 +vn 0.0835 -0.2017 -0.9759 +vn 0.1544 -0.1544 -0.9759 +vn 0.2017 -0.0835 -0.9759 +vn 0.0000 0.0000 -1.0000 +# 98 vertex normals + +vt 0.5000 0.5000 0.0000 +vt 0.6486 0.5000 0.0000 +vt 0.6373 0.5569 0.0000 +vt 0.6051 0.6051 0.0000 +vt 0.5569 0.6373 0.0000 +vt 0.5000 0.6486 0.0000 +vt 0.4431 0.6373 0.0000 +vt 0.3949 0.6051 0.0000 +vt 0.3627 0.5569 0.0000 +vt 0.3514 0.5000 0.0000 +vt 0.3627 0.4431 0.0000 +vt 0.3949 0.3949 0.0000 +vt 0.4431 0.3627 0.0000 +vt 0.5000 0.3514 0.0000 +vt 0.5569 0.3627 0.0000 +vt 0.6051 0.3949 0.0000 +vt 0.6373 0.4431 0.0000 +vt 0.8971 0.5000 0.0000 +vt 0.8669 0.6520 0.0000 +vt 0.7808 0.7808 0.0000 +vt 0.6520 0.8669 0.0000 +vt 0.5000 0.8971 0.0000 +vt 0.3480 0.8669 0.0000 +vt 0.2192 0.7808 0.0000 +vt 0.1331 0.6520 0.0000 +vt 0.1029 0.5000 0.0000 +vt 0.1331 0.3480 0.0000 +vt 0.2192 0.2192 0.0000 +vt 0.3480 0.1331 0.0000 +vt 0.5000 0.1029 0.0000 +vt 0.6520 0.1331 0.0000 +vt 0.7808 0.2192 0.0000 +vt 0.8669 0.3480 0.0000 +vt 1.0000 0.5000 0.0000 +vt 0.9619 0.6913 0.0000 +vt 0.8536 0.8536 0.0000 +vt 0.6913 0.9619 0.0000 +vt 0.5000 1.0000 0.0000 +vt 0.3087 0.9619 0.0000 +vt 0.1464 0.8536 0.0000 +vt 0.0381 0.6913 0.0000 +vt 0.0000 0.5000 0.0000 +vt 0.0381 0.3087 0.0000 +vt 0.1464 0.1464 0.0000 +vt 0.3087 0.0381 0.0000 +vt 0.5000 0.0000 0.0000 +vt 0.6913 0.0381 0.0000 +vt 0.8536 0.1464 0.0000 +vt 0.9619 0.3087 0.0000 +vt 0.0000 1.0000 0.0000 +vt 0.0000 0.0000 0.0000 +vt 0.0625 0.0000 0.0000 +vt 0.0625 1.0000 0.0000 +vt 0.1250 0.0000 0.0000 +vt 0.1250 1.0000 0.0000 +vt 0.1875 0.0000 0.0000 +vt 0.1875 1.0000 0.0000 +vt 0.2500 0.0000 0.0000 +vt 0.2500 1.0000 0.0000 +vt 0.3125 0.0000 0.0000 +vt 0.3125 1.0000 0.0000 +vt 0.3750 0.0000 0.0000 +vt 0.3750 1.0000 0.0000 +vt 0.4375 0.0000 0.0000 +vt 0.4375 1.0000 0.0000 +vt 0.5625 0.0000 0.0000 +vt 0.5625 1.0000 0.0000 +vt 0.6250 0.0000 0.0000 +vt 0.6250 1.0000 0.0000 +vt 0.6875 0.0000 0.0000 +vt 0.6875 1.0000 0.0000 +vt 0.7500 0.0000 0.0000 +vt 0.7500 1.0000 0.0000 +vt 0.8125 0.0000 0.0000 +vt 0.8125 1.0000 0.0000 +vt 0.8750 0.0000 0.0000 +vt 0.8750 1.0000 0.0000 +vt 0.9375 0.0000 0.0000 +vt 0.9375 1.0000 0.0000 +vt 1.0000 0.0000 0.0000 +vt 1.0000 1.0000 0.0000 +# 81 texture coords + +g button2 +usemtl 02___Default +s 4 +f 248/256/148 249/257/149 250/258/150 +f 248/256/148 250/258/150 251/259/151 +f 248/256/148 251/259/151 252/260/152 +f 248/256/148 252/260/152 253/261/153 +f 248/256/148 253/261/153 254/262/154 +f 248/256/148 254/262/154 255/263/155 +f 248/256/148 255/263/155 256/264/156 +f 248/256/148 256/264/156 257/265/157 +f 248/256/148 257/265/157 258/266/158 +f 248/256/148 258/266/158 259/267/159 +f 248/256/148 259/267/159 260/268/160 +f 248/256/148 260/268/160 261/269/161 +f 248/256/148 261/269/161 262/270/162 +f 248/256/148 262/270/162 263/271/163 +f 248/256/148 263/271/163 264/272/164 +f 248/256/148 264/272/164 249/257/149 +f 249/257/149 265/273/165 266/274/166 250/258/150 +f 250/258/150 266/274/166 267/275/167 251/259/151 +f 251/259/151 267/275/167 268/276/168 252/260/152 +f 252/260/152 268/276/168 269/277/169 253/261/153 +f 253/261/153 269/277/169 270/278/170 254/262/154 +f 254/262/154 270/278/170 271/279/171 255/263/155 +f 255/263/155 271/279/171 272/280/172 256/264/156 +f 256/264/156 272/280/172 273/281/173 257/265/157 +f 257/265/157 273/281/173 274/282/174 258/266/158 +f 258/266/158 274/282/174 275/283/175 259/267/159 +f 259/267/159 275/283/175 276/284/176 260/268/160 +f 260/268/160 276/284/176 277/285/177 261/269/161 +f 261/269/161 277/285/177 278/286/178 262/270/162 +f 262/270/162 278/286/178 279/287/179 263/271/163 +f 263/271/163 279/287/179 280/288/180 264/272/164 +f 264/272/164 280/288/180 265/273/165 249/257/149 +f 265/273/165 281/289/181 282/290/182 266/274/166 +f 266/274/166 282/290/182 283/291/183 267/275/167 +f 267/275/167 283/291/183 284/292/184 268/276/168 +f 268/276/168 284/292/184 285/293/185 269/277/169 +f 269/277/169 285/293/185 286/294/186 270/278/170 +f 270/278/170 286/294/186 287/295/187 271/279/171 +f 271/279/171 287/295/187 288/296/188 272/280/172 +f 272/280/172 288/296/188 289/297/189 273/281/173 +f 273/281/173 289/297/189 290/298/190 274/282/174 +f 274/282/174 290/298/190 291/299/191 275/283/175 +f 275/283/175 291/299/191 292/300/192 276/284/176 +f 276/284/176 292/300/192 293/301/193 277/285/177 +f 277/285/177 293/301/193 294/302/194 278/286/178 +f 278/286/178 294/302/194 295/303/195 279/287/179 +f 279/287/179 295/303/195 296/304/196 280/288/180 +f 280/288/180 296/304/196 281/289/181 265/273/165 +f 281/305/181 297/306/197 298/307/198 282/308/182 +f 282/308/182 298/307/198 299/309/199 283/310/183 +f 283/310/183 299/309/199 300/311/200 284/312/184 +f 284/312/184 300/311/200 301/313/201 285/314/185 +f 285/314/185 301/313/201 302/315/202 286/316/186 +f 286/316/186 302/315/202 303/317/203 287/318/187 +f 287/318/187 303/317/203 304/319/204 288/320/188 +f 288/320/188 304/319/204 305/301/205 289/293/189 +f 289/293/189 305/301/205 306/321/206 290/322/190 +f 290/322/190 306/321/206 307/323/207 291/324/191 +f 291/324/191 307/323/207 308/325/208 292/326/192 +f 292/326/192 308/325/208 309/327/209 293/328/193 +f 293/328/193 309/327/209 310/329/210 294/330/194 +f 294/330/194 310/329/210 311/331/211 295/332/195 +f 295/332/195 311/331/211 312/333/212 296/334/196 +f 296/334/196 312/333/212 297/335/197 281/336/181 +f 297/289/197 313/273/213 314/274/214 298/290/198 +f 298/290/198 314/274/214 315/275/215 299/291/199 +f 299/291/199 315/275/215 316/276/216 300/292/200 +f 300/292/200 316/276/216 317/277/217 301/293/201 +f 301/293/201 317/277/217 318/278/218 302/294/202 +f 302/294/202 318/278/218 319/279/219 303/295/203 +f 303/295/203 319/279/219 320/280/220 304/296/204 +f 304/296/204 320/280/220 321/281/221 305/297/205 +f 305/297/205 321/281/221 322/282/222 306/298/206 +f 306/298/206 322/282/222 323/283/223 307/299/207 +f 307/299/207 323/283/223 324/284/224 308/300/208 +f 308/300/208 324/284/224 325/285/225 309/301/209 +f 309/301/209 325/285/225 326/286/226 310/302/210 +f 310/302/210 326/286/226 327/287/227 311/303/211 +f 311/303/211 327/287/227 328/288/228 312/304/212 +f 312/304/212 328/288/228 313/273/213 297/289/197 +f 313/273/213 329/257/229 330/258/230 314/274/214 +f 314/274/214 330/258/230 331/259/231 315/275/215 +f 315/275/215 331/259/231 332/260/232 316/276/216 +f 316/276/216 332/260/232 333/261/233 317/277/217 +f 317/277/217 333/261/233 334/262/234 318/278/218 +f 318/278/218 334/262/234 335/263/235 319/279/219 +f 319/279/219 335/263/235 336/264/236 320/280/220 +f 320/280/220 336/264/236 337/265/237 321/281/221 +f 321/281/221 337/265/237 338/266/238 322/282/222 +f 322/282/222 338/266/238 339/267/239 323/283/223 +f 323/283/223 339/267/239 340/268/240 324/284/224 +f 324/284/224 340/268/240 341/269/241 325/285/225 +f 325/285/225 341/269/241 342/270/242 326/286/226 +f 326/286/226 342/270/242 343/271/243 327/287/227 +f 327/287/227 343/271/243 344/272/244 328/288/228 +f 328/288/228 344/272/244 329/257/229 313/273/213 +f 329/257/229 345/256/245 330/258/230 +f 330/258/230 345/256/245 331/259/231 +f 331/259/231 345/256/245 332/260/232 +f 332/260/232 345/256/245 333/261/233 +f 333/261/233 345/256/245 334/262/234 +f 334/262/234 345/256/245 335/263/235 +f 335/263/235 345/256/245 336/264/236 +f 336/264/236 345/256/245 337/265/237 +f 337/265/237 345/256/245 338/266/238 +f 338/266/238 345/256/245 339/267/239 +f 339/267/239 345/256/245 340/268/240 +f 340/268/240 345/256/245 341/269/241 +f 341/269/241 345/256/245 342/270/242 +f 342/270/242 345/256/245 343/271/243 +f 343/271/243 345/256/245 344/272/244 +f 344/272/244 345/256/245 329/257/229 +# 80 polygons - 32 triangles + +# +# object button1 +# + +v -24.5934 4.8805 4.4808 +v -25.1879 4.8805 4.4808 +v -25.1427 5.1080 4.4808 +v -25.0138 5.3009 4.4808 +v -24.8209 5.4298 4.4808 +v -24.5934 5.4750 4.4808 +v -24.3659 5.4298 4.4808 +v -24.1730 5.3009 4.4808 +v -24.0441 5.1080 4.4808 +v -23.9988 4.8805 4.4808 +v -24.0441 4.6529 4.4808 +v -24.1730 4.4601 4.4808 +v -24.3659 4.3312 4.4808 +v -24.5934 4.2859 4.4808 +v -24.8209 4.3312 4.4808 +v -25.0138 4.4601 4.4808 +v -25.1427 4.6529 4.4808 +v -26.1817 4.8805 4.0692 +v -26.0608 5.4883 4.0692 +v -25.7165 6.0036 4.0692 +v -25.2012 6.3479 4.0692 +v -24.5934 6.4688 4.0692 +v -23.9855 6.3479 4.0692 +v -23.4702 6.0036 4.0692 +v -23.1259 5.4883 4.0692 +v -23.0050 4.8805 4.0692 +v -23.1259 4.2726 4.0692 +v -23.4702 3.7573 4.0692 +v -23.9855 3.4130 4.0692 +v -24.5934 3.2921 4.0692 +v -25.2012 3.4130 4.0692 +v -25.7165 3.7573 4.0692 +v -26.0608 4.2726 4.0692 +v -26.5934 4.8805 3.0753 +v -26.4411 5.6458 3.0753 +v -26.0076 6.2947 3.0753 +v -25.3587 6.7282 3.0753 +v -24.5934 6.8805 3.0753 +v -23.8280 6.7282 3.0753 +v -23.1792 6.2947 3.0753 +v -22.7456 5.6458 3.0753 +v -22.5934 4.8805 3.0753 +v -22.7456 4.1151 3.0753 +v -23.1792 3.4663 3.0753 +v -23.8280 3.0327 3.0753 +v -24.5934 2.8805 3.0753 +v -25.3587 3.0327 3.0753 +v -26.0076 3.4663 3.0753 +v -26.4411 4.1151 3.0753 +v -26.5934 4.8805 -2.0476 +v -26.4411 5.6458 -2.0476 +v -26.0076 6.2947 -2.0476 +v -25.3587 6.7282 -2.0476 +v -24.5934 6.8805 -2.0476 +v -23.8280 6.7282 -2.0476 +v -23.1792 6.2947 -2.0476 +v -22.7456 5.6458 -2.0476 +v -22.5934 4.8805 -2.0476 +v -22.7456 4.1151 -2.0476 +v -23.1792 3.4663 -2.0476 +v -23.8280 3.0327 -2.0476 +v -24.5934 2.8805 -2.0476 +v -25.3587 3.0327 -2.0476 +v -26.0076 3.4663 -2.0476 +v -26.4411 4.1151 -2.0476 +v -26.1817 4.8805 -3.0415 +v -26.0608 5.4883 -3.0415 +v -25.7165 6.0036 -3.0415 +v -25.2012 6.3479 -3.0415 +v -24.5934 6.4688 -3.0415 +v -23.9855 6.3479 -3.0415 +v -23.4702 6.0036 -3.0415 +v -23.1259 5.4883 -3.0415 +v -23.0050 4.8805 -3.0415 +v -23.1259 4.2726 -3.0415 +v -23.4702 3.7573 -3.0415 +v -23.9855 3.4130 -3.0415 +v -24.5934 3.2921 -3.0415 +v -25.2012 3.4130 -3.0415 +v -25.7165 3.7573 -3.0415 +v -26.0608 4.2726 -3.0415 +v -25.1879 4.8805 -3.4531 +v -25.1427 5.1080 -3.4531 +v -25.0138 5.3009 -3.4531 +v -24.8209 5.4298 -3.4531 +v -24.5934 5.4750 -3.4531 +v -24.3659 5.4298 -3.4531 +v -24.1730 5.3009 -3.4531 +v -24.0441 5.1080 -3.4531 +v -23.9988 4.8805 -3.4531 +v -24.0441 4.6529 -3.4531 +v -24.1730 4.4601 -3.4531 +v -24.3659 4.3312 -3.4531 +v -24.5934 4.2859 -3.4531 +v -24.8209 4.3312 -3.4531 +v -25.0138 4.4601 -3.4531 +v -25.1427 4.6529 -3.4531 +v -24.5934 4.8805 -3.4531 +# 98 vertices + +vn 0.0000 -0.0000 1.0000 +vn -0.2183 -0.0000 0.9759 +vn -0.2017 0.0835 0.9759 +vn -0.1544 0.1544 0.9759 +vn -0.0835 0.2017 0.9759 +vn -0.0000 0.2183 0.9759 +vn 0.0835 0.2017 0.9759 +vn 0.1544 0.1544 0.9759 +vn 0.2017 0.0835 0.9759 +vn 0.2183 -0.0000 0.9759 +vn 0.2017 -0.0835 0.9759 +vn 0.1544 -0.1544 0.9759 +vn 0.0835 -0.2017 0.9759 +vn -0.0000 -0.2183 0.9759 +vn -0.0835 -0.2017 0.9759 +vn -0.1544 -0.1544 0.9759 +vn -0.2017 -0.0835 0.9759 +vn -0.7294 0.0000 0.6840 +vn -0.6739 0.2791 0.6840 +vn -0.5158 0.5158 0.6840 +vn -0.2791 0.6739 0.6840 +vn -0.0000 0.7294 0.6840 +vn 0.2791 0.6739 0.6840 +vn 0.5158 0.5158 0.6840 +vn 0.6739 0.2791 0.6840 +vn 0.7294 0.0000 0.6840 +vn 0.6739 -0.2791 0.6840 +vn 0.5158 -0.5158 0.6840 +vn 0.2791 -0.6739 0.6840 +vn -0.0000 -0.7294 0.6840 +vn -0.2791 -0.6739 0.6840 +vn -0.5158 -0.5158 0.6840 +vn -0.6739 -0.2791 0.6840 +vn -0.9817 0.0000 0.1906 +vn -0.9069 0.3757 0.1906 +vn -0.6941 0.6941 0.1906 +vn -0.3757 0.9069 0.1906 +vn 0.0000 0.9817 0.1906 +vn 0.3757 0.9069 0.1906 +vn 0.6941 0.6941 0.1906 +vn 0.9069 0.3757 0.1906 +vn 0.9817 0.0000 0.1906 +vn 0.9069 -0.3757 0.1906 +vn 0.6941 -0.6941 0.1906 +vn 0.3757 -0.9069 0.1906 +vn -0.0000 -0.9817 0.1906 +vn -0.3757 -0.9069 0.1906 +vn -0.6941 -0.6941 0.1906 +vn -0.9069 -0.3757 0.1906 +vn -0.9817 0.0000 -0.1906 +vn -0.9069 0.3757 -0.1906 +vn -0.6941 0.6941 -0.1906 +vn -0.3757 0.9069 -0.1906 +vn -0.0000 0.9817 -0.1906 +vn 0.3757 0.9069 -0.1906 +vn 0.6941 0.6941 -0.1906 +vn 0.9069 0.3757 -0.1906 +vn 0.9817 0.0000 -0.1906 +vn 0.9069 -0.3757 -0.1906 +vn 0.6941 -0.6941 -0.1906 +vn 0.3757 -0.9069 -0.1906 +vn -0.0000 -0.9817 -0.1906 +vn -0.3757 -0.9069 -0.1906 +vn -0.6941 -0.6941 -0.1906 +vn -0.9069 -0.3757 -0.1906 +vn -0.7294 0.0000 -0.6840 +vn -0.6739 0.2791 -0.6840 +vn -0.5158 0.5158 -0.6840 +vn -0.2791 0.6739 -0.6840 +vn 0.0000 0.7294 -0.6840 +vn 0.2791 0.6739 -0.6840 +vn 0.5158 0.5158 -0.6840 +vn 0.6739 0.2791 -0.6840 +vn 0.7294 0.0000 -0.6840 +vn 0.6739 -0.2791 -0.6840 +vn 0.5158 -0.5158 -0.6840 +vn 0.2791 -0.6739 -0.6840 +vn -0.0000 -0.7294 -0.6840 +vn -0.2791 -0.6739 -0.6840 +vn -0.5158 -0.5158 -0.6840 +vn -0.6739 -0.2791 -0.6840 +vn -0.2183 0.0000 -0.9759 +vn -0.2017 0.0835 -0.9759 +vn -0.1544 0.1544 -0.9759 +vn -0.0835 0.2017 -0.9759 +vn 0.0000 0.2183 -0.9759 +vn 0.0835 0.2017 -0.9759 +vn 0.1544 0.1544 -0.9759 +vn 0.2017 0.0835 -0.9759 +vn 0.2183 0.0000 -0.9759 +vn 0.2017 -0.0835 -0.9759 +vn 0.1544 -0.1544 -0.9759 +vn 0.0835 -0.2017 -0.9759 +vn -0.0000 -0.2183 -0.9759 +vn -0.0835 -0.2017 -0.9759 +vn -0.1544 -0.1544 -0.9759 +vn -0.2017 -0.0835 -0.9759 +vn 0.0000 0.0000 -1.0000 +# 98 vertex normals + +vt 0.5000 0.5000 0.0000 +vt 0.6486 0.5000 0.0000 +vt 0.6373 0.5569 0.0000 +vt 0.6051 0.6051 0.0000 +vt 0.5569 0.6373 0.0000 +vt 0.5000 0.6486 0.0000 +vt 0.4431 0.6373 0.0000 +vt 0.3949 0.6051 0.0000 +vt 0.3627 0.5569 0.0000 +vt 0.3514 0.5000 0.0000 +vt 0.3627 0.4431 0.0000 +vt 0.3949 0.3949 0.0000 +vt 0.4431 0.3627 0.0000 +vt 0.5000 0.3514 0.0000 +vt 0.5569 0.3627 0.0000 +vt 0.6051 0.3949 0.0000 +vt 0.6373 0.4431 0.0000 +vt 0.8971 0.5000 0.0000 +vt 0.8669 0.6520 0.0000 +vt 0.7808 0.7808 0.0000 +vt 0.6520 0.8669 0.0000 +vt 0.5000 0.8971 0.0000 +vt 0.3480 0.8669 0.0000 +vt 0.2192 0.7808 0.0000 +vt 0.1331 0.6520 0.0000 +vt 0.1029 0.5000 0.0000 +vt 0.1331 0.3480 0.0000 +vt 0.2192 0.2192 0.0000 +vt 0.3480 0.1331 0.0000 +vt 0.5000 0.1029 0.0000 +vt 0.6520 0.1331 0.0000 +vt 0.7808 0.2192 0.0000 +vt 0.8669 0.3480 0.0000 +vt 1.0000 0.5000 0.0000 +vt 0.9619 0.6913 0.0000 +vt 0.8536 0.8536 0.0000 +vt 0.6913 0.9619 0.0000 +vt 0.5000 1.0000 0.0000 +vt 0.3087 0.9619 0.0000 +vt 0.1464 0.8536 0.0000 +vt 0.0381 0.6913 0.0000 +vt 0.0000 0.5000 0.0000 +vt 0.0381 0.3087 0.0000 +vt 0.1464 0.1464 0.0000 +vt 0.3087 0.0381 0.0000 +vt 0.5000 0.0000 0.0000 +vt 0.6913 0.0381 0.0000 +vt 0.8536 0.1464 0.0000 +vt 0.9619 0.3087 0.0000 +vt 0.0000 1.0000 0.0000 +vt 0.0000 0.0000 0.0000 +vt 0.0625 0.0000 0.0000 +vt 0.0625 1.0000 0.0000 +vt 0.1250 0.0000 0.0000 +vt 0.1250 1.0000 0.0000 +vt 0.1875 0.0000 0.0000 +vt 0.1875 1.0000 0.0000 +vt 0.2500 0.0000 0.0000 +vt 0.2500 1.0000 0.0000 +vt 0.3125 0.0000 0.0000 +vt 0.3125 1.0000 0.0000 +vt 0.3750 0.0000 0.0000 +vt 0.3750 1.0000 0.0000 +vt 0.4375 0.0000 0.0000 +vt 0.4375 1.0000 0.0000 +vt 0.5625 0.0000 0.0000 +vt 0.5625 1.0000 0.0000 +vt 0.6250 0.0000 0.0000 +vt 0.6250 1.0000 0.0000 +vt 0.6875 0.0000 0.0000 +vt 0.6875 1.0000 0.0000 +vt 0.7500 0.0000 0.0000 +vt 0.7500 1.0000 0.0000 +vt 0.8125 0.0000 0.0000 +vt 0.8125 1.0000 0.0000 +vt 0.8750 0.0000 0.0000 +vt 0.8750 1.0000 0.0000 +vt 0.9375 0.0000 0.0000 +vt 0.9375 1.0000 0.0000 +vt 1.0000 0.0000 0.0000 +vt 1.0000 1.0000 0.0000 +# 81 texture coords + +g button1 +usemtl 02___Default +s 4 +f 348/339/248 347/338/247 346/337/246 +f 349/340/249 348/339/248 346/337/246 +f 350/341/250 349/340/249 346/337/246 +f 351/342/251 350/341/250 346/337/246 +f 352/343/252 351/342/251 346/337/246 +f 353/344/253 352/343/252 346/337/246 +f 354/345/254 353/344/253 346/337/246 +f 355/346/255 354/345/254 346/337/246 +f 356/347/256 355/346/255 346/337/246 +f 357/348/257 356/347/256 346/337/246 +f 358/349/258 357/348/257 346/337/246 +f 359/350/259 358/349/258 346/337/246 +f 360/351/260 359/350/259 346/337/246 +f 361/352/261 360/351/260 346/337/246 +f 362/353/262 361/352/261 346/337/246 +f 347/338/247 362/353/262 346/337/246 +f 348/339/248 364/355/264 363/354/263 347/338/247 +f 349/340/249 365/356/265 364/355/264 348/339/248 +f 350/341/250 366/357/266 365/356/265 349/340/249 +f 351/342/251 367/358/267 366/357/266 350/341/250 +f 352/343/252 368/359/268 367/358/267 351/342/251 +f 353/344/253 369/360/269 368/359/268 352/343/252 +f 354/345/254 370/361/270 369/360/269 353/344/253 +f 355/346/255 371/362/271 370/361/270 354/345/254 +f 356/347/256 372/363/272 371/362/271 355/346/255 +f 357/348/257 373/364/273 372/363/272 356/347/256 +f 358/349/258 374/365/274 373/364/273 357/348/257 +f 359/350/259 375/366/275 374/365/274 358/349/258 +f 360/351/260 376/367/276 375/366/275 359/350/259 +f 361/352/261 377/368/277 376/367/276 360/351/260 +f 362/353/262 378/369/278 377/368/277 361/352/261 +f 347/338/247 363/354/263 378/369/278 362/353/262 +f 364/355/264 380/371/280 379/370/279 363/354/263 +f 365/356/265 381/372/281 380/371/280 364/355/264 +f 366/357/266 382/373/282 381/372/281 365/356/265 +f 367/358/267 383/374/283 382/373/282 366/357/266 +f 368/359/268 384/375/284 383/374/283 367/358/267 +f 369/360/269 385/376/285 384/375/284 368/359/268 +f 370/361/270 386/377/286 385/376/285 369/360/269 +f 371/362/271 387/378/287 386/377/286 370/361/270 +f 372/363/272 388/379/288 387/378/287 371/362/271 +f 373/364/273 389/380/289 388/379/288 372/363/272 +f 374/365/274 390/381/290 389/380/289 373/364/273 +f 375/366/275 391/382/291 390/381/290 374/365/274 +f 376/367/276 392/383/292 391/382/291 375/366/275 +f 377/368/277 393/384/293 392/383/292 376/367/276 +f 378/369/278 394/385/294 393/384/293 377/368/277 +f 363/354/263 379/370/279 394/385/294 378/369/278 +f 380/389/280 396/388/296 395/387/295 379/386/279 +f 381/391/281 397/390/297 396/388/296 380/389/280 +f 382/393/282 398/392/298 397/390/297 381/391/281 +f 383/395/283 399/394/299 398/392/298 382/393/282 +f 384/397/284 400/396/300 399/394/299 383/395/283 +f 385/399/285 401/398/301 400/396/300 384/397/284 +f 386/401/286 402/400/302 401/398/301 385/399/285 +f 387/374/287 403/382/303 402/400/302 386/401/286 +f 388/403/288 404/402/304 403/382/303 387/374/287 +f 389/405/289 405/404/305 404/402/304 388/403/288 +f 390/407/290 406/406/306 405/404/305 389/405/289 +f 391/409/291 407/408/307 406/406/306 390/407/290 +f 392/411/292 408/410/308 407/408/307 391/409/291 +f 393/413/293 409/412/309 408/410/308 392/411/292 +f 394/415/294 410/414/310 409/412/309 393/413/293 +f 379/417/279 395/416/295 410/414/310 394/415/294 +f 396/371/296 412/355/312 411/354/311 395/370/295 +f 397/372/297 413/356/313 412/355/312 396/371/296 +f 398/373/298 414/357/314 413/356/313 397/372/297 +f 399/374/299 415/358/315 414/357/314 398/373/298 +f 400/375/300 416/359/316 415/358/315 399/374/299 +f 401/376/301 417/360/317 416/359/316 400/375/300 +f 402/377/302 418/361/318 417/360/317 401/376/301 +f 403/378/303 419/362/319 418/361/318 402/377/302 +f 404/379/304 420/363/320 419/362/319 403/378/303 +f 405/380/305 421/364/321 420/363/320 404/379/304 +f 406/381/306 422/365/322 421/364/321 405/380/305 +f 407/382/307 423/366/323 422/365/322 406/381/306 +f 408/383/308 424/367/324 423/366/323 407/382/307 +f 409/384/309 425/368/325 424/367/324 408/383/308 +f 410/385/310 426/369/326 425/368/325 409/384/309 +f 395/370/295 411/354/311 426/369/326 410/385/310 +f 412/355/312 428/339/328 427/338/327 411/354/311 +f 413/356/313 429/340/329 428/339/328 412/355/312 +f 414/357/314 430/341/330 429/340/329 413/356/313 +f 415/358/315 431/342/331 430/341/330 414/357/314 +f 416/359/316 432/343/332 431/342/331 415/358/315 +f 417/360/317 433/344/333 432/343/332 416/359/316 +f 418/361/318 434/345/334 433/344/333 417/360/317 +f 419/362/319 435/346/335 434/345/334 418/361/318 +f 420/363/320 436/347/336 435/346/335 419/362/319 +f 421/364/321 437/348/337 436/347/336 420/363/320 +f 422/365/322 438/349/338 437/348/337 421/364/321 +f 423/366/323 439/350/339 438/349/338 422/365/322 +f 424/367/324 440/351/340 439/350/339 423/366/323 +f 425/368/325 441/352/341 440/351/340 424/367/324 +f 426/369/326 442/353/342 441/352/341 425/368/325 +f 411/354/311 427/338/327 442/353/342 426/369/326 +f 428/339/328 443/337/343 427/338/327 +f 429/340/329 443/337/343 428/339/328 +f 430/341/330 443/337/343 429/340/329 +f 431/342/331 443/337/343 430/341/330 +f 432/343/332 443/337/343 431/342/331 +f 433/344/333 443/337/343 432/343/332 +f 434/345/334 443/337/343 433/344/333 +f 435/346/335 443/337/343 434/345/334 +f 436/347/336 443/337/343 435/346/335 +f 437/348/337 443/337/343 436/347/336 +f 438/349/338 443/337/343 437/348/337 +f 439/350/339 443/337/343 438/349/338 +f 440/351/340 443/337/343 439/350/339 +f 441/352/341 443/337/343 440/351/340 +f 442/353/342 443/337/343 441/352/341 +f 427/338/327 443/337/343 442/353/342 +# 80 polygons - 32 triangles + +# +# object led1 +# + +v -20.0000 25.8495 0.8829 +v -20.5945 25.8495 0.8829 +v -20.5493 26.0771 0.8829 +v -20.4204 26.2699 0.8829 +v -20.2275 26.3988 0.8829 +v -20.0000 26.4441 0.8829 +v -19.7725 26.3988 0.8829 +v -19.5796 26.2699 0.8829 +v -19.4507 26.0771 0.8829 +v -19.4055 25.8495 0.8829 +v -19.4507 25.6220 0.8829 +v -19.5796 25.4291 0.8829 +v -19.7725 25.3002 0.8829 +v -20.0000 25.2550 0.8829 +v -20.2275 25.3002 0.8829 +v -20.4204 25.4291 0.8829 +v -20.5493 25.6220 0.8829 +v -21.5884 25.8495 0.4712 +v -21.4674 26.4574 0.4712 +v -21.1231 26.9727 0.4712 +v -20.6078 27.3170 0.4712 +v -20.0000 27.4379 0.4712 +v -19.3922 27.3170 0.4712 +v -18.8769 26.9727 0.4712 +v -18.5326 26.4574 0.4712 +v -18.4116 25.8495 0.4712 +v -18.5326 25.2417 0.4712 +v -18.8769 24.7264 0.4712 +v -19.3922 24.3821 0.4712 +v -20.0000 24.2612 0.4712 +v -20.6078 24.3821 0.4712 +v -21.1231 24.7264 0.4712 +v -21.4674 25.2417 0.4712 +v -22.0000 25.8495 -0.5226 +v -21.8478 26.6149 -0.5226 +v -21.4142 27.2637 -0.5226 +v -20.7654 27.6973 -0.5226 +v -20.0000 27.8495 -0.5226 +v -19.2346 27.6973 -0.5226 +v -18.5858 27.2637 -0.5226 +v -18.1522 26.6149 -0.5226 +v -18.0000 25.8495 -0.5226 +v -18.1522 25.0842 -0.5226 +v -18.5858 24.4353 -0.5226 +v -19.2346 24.0018 -0.5226 +v -20.0000 23.8495 -0.5226 +v -20.7654 24.0018 -0.5226 +v -21.4142 24.4353 -0.5226 +v -21.8478 25.0842 -0.5226 +# 49 vertices + +vn 0.0000 -0.0000 1.0000 +vn -0.2183 -0.0000 0.9759 +vn -0.2017 0.0835 0.9759 +vn -0.1544 0.1544 0.9759 +vn -0.0835 0.2017 0.9759 +vn -0.0000 0.2183 0.9759 +vn 0.0835 0.2017 0.9759 +vn 0.1544 0.1544 0.9759 +vn 0.2017 0.0835 0.9759 +vn 0.2183 -0.0000 0.9759 +vn 0.2017 -0.0835 0.9759 +vn 0.1544 -0.1544 0.9759 +vn 0.0835 -0.2017 0.9759 +vn -0.0000 -0.2183 0.9759 +vn -0.0835 -0.2017 0.9759 +vn -0.1544 -0.1544 0.9759 +vn -0.2017 -0.0835 0.9759 +vn -0.7294 0.0000 0.6840 +vn -0.6739 0.2791 0.6840 +vn -0.5158 0.5158 0.6840 +vn -0.2791 0.6739 0.6840 +vn -0.0000 0.7294 0.6840 +vn 0.2791 0.6739 0.6840 +vn 0.5158 0.5158 0.6840 +vn 0.6739 0.2791 0.6840 +vn 0.7294 0.0000 0.6840 +vn 0.6739 -0.2791 0.6840 +vn 0.5158 -0.5158 0.6840 +vn 0.2791 -0.6739 0.6840 +vn -0.0000 -0.7294 0.6840 +vn -0.2791 -0.6739 0.6840 +vn -0.5158 -0.5158 0.6840 +vn -0.6739 -0.2791 0.6840 +vn -0.9239 0.0000 0.3827 +vn -0.8536 0.3536 0.3827 +vn -0.6533 0.6533 0.3827 +vn -0.3536 0.8536 0.3827 +vn 0.0000 0.9239 0.3827 +vn 0.3536 0.8536 0.3827 +vn 0.6533 0.6533 0.3827 +vn 0.8536 0.3536 0.3827 +vn 0.9239 0.0000 0.3827 +vn 0.8536 -0.3536 0.3827 +vn 0.6533 -0.6533 0.3827 +vn 0.3536 -0.8536 0.3827 +vn -0.0000 -0.9239 0.3827 +vn -0.3536 -0.8536 0.3827 +vn -0.6533 -0.6533 0.3827 +vn -0.8536 -0.3536 0.3827 +# 49 vertex normals + +vt 0.5000 0.5000 0.0000 +vt 0.6486 0.5000 0.0000 +vt 0.6373 0.5569 0.0000 +vt 0.6051 0.6051 0.0000 +vt 0.5569 0.6373 0.0000 +vt 0.5000 0.6486 0.0000 +vt 0.4431 0.6373 0.0000 +vt 0.3949 0.6051 0.0000 +vt 0.3627 0.5569 0.0000 +vt 0.3514 0.5000 0.0000 +vt 0.3627 0.4431 0.0000 +vt 0.3949 0.3949 0.0000 +vt 0.4431 0.3627 0.0000 +vt 0.5000 0.3514 0.0000 +vt 0.5569 0.3627 0.0000 +vt 0.6051 0.3949 0.0000 +vt 0.6373 0.4431 0.0000 +vt 0.8971 0.5000 0.0000 +vt 0.8669 0.6520 0.0000 +vt 0.7808 0.7808 0.0000 +vt 0.6520 0.8669 0.0000 +vt 0.5000 0.8971 0.0000 +vt 0.3480 0.8669 0.0000 +vt 0.2192 0.7808 0.0000 +vt 0.1331 0.6520 0.0000 +vt 0.1029 0.5000 0.0000 +vt 0.1331 0.3480 0.0000 +vt 0.2192 0.2192 0.0000 +vt 0.3480 0.1331 0.0000 +vt 0.5000 0.1029 0.0000 +vt 0.6520 0.1331 0.0000 +vt 0.7808 0.2192 0.0000 +vt 0.8669 0.3480 0.0000 +vt 1.0000 0.5000 0.0000 +vt 0.9619 0.6913 0.0000 +vt 0.8536 0.8536 0.0000 +vt 0.6913 0.9619 0.0000 +vt 0.5000 1.0000 0.0000 +vt 0.3087 0.9619 0.0000 +vt 0.1464 0.8536 0.0000 +vt 0.0381 0.6913 0.0000 +vt 0.0000 0.5000 0.0000 +vt 0.0381 0.3087 0.0000 +vt 0.1464 0.1464 0.0000 +vt 0.3087 0.0381 0.0000 +vt 0.5000 0.0000 0.0000 +vt 0.6913 0.0381 0.0000 +vt 0.8536 0.1464 0.0000 +vt 0.9619 0.3087 0.0000 +# 49 texture coords + +g led1 +usemtl 03___Default +s 4 +f 446/420/346 445/419/345 444/418/344 +f 447/421/347 446/420/346 444/418/344 +f 448/422/348 447/421/347 444/418/344 +f 449/423/349 448/422/348 444/418/344 +f 450/424/350 449/423/349 444/418/344 +f 451/425/351 450/424/350 444/418/344 +f 452/426/352 451/425/351 444/418/344 +f 453/427/353 452/426/352 444/418/344 +f 454/428/354 453/427/353 444/418/344 +f 455/429/355 454/428/354 444/418/344 +f 456/430/356 455/429/355 444/418/344 +f 457/431/357 456/430/356 444/418/344 +f 458/432/358 457/431/357 444/418/344 +f 459/433/359 458/432/358 444/418/344 +f 460/434/360 459/433/359 444/418/344 +f 445/419/345 460/434/360 444/418/344 +f 446/420/346 462/436/362 461/435/361 445/419/345 +f 447/421/347 463/437/363 462/436/362 446/420/346 +f 448/422/348 464/438/364 463/437/363 447/421/347 +f 449/423/349 465/439/365 464/438/364 448/422/348 +f 450/424/350 466/440/366 465/439/365 449/423/349 +f 451/425/351 467/441/367 466/440/366 450/424/350 +f 452/426/352 468/442/368 467/441/367 451/425/351 +f 453/427/353 469/443/369 468/442/368 452/426/352 +f 454/428/354 470/444/370 469/443/369 453/427/353 +f 455/429/355 471/445/371 470/444/370 454/428/354 +f 456/430/356 472/446/372 471/445/371 455/429/355 +f 457/431/357 473/447/373 472/446/372 456/430/356 +f 458/432/358 474/448/374 473/447/373 457/431/357 +f 459/433/359 475/449/375 474/448/374 458/432/358 +f 460/434/360 476/450/376 475/449/375 459/433/359 +f 445/419/345 461/435/361 476/450/376 460/434/360 +f 462/436/362 478/452/378 477/451/377 461/435/361 +f 463/437/363 479/453/379 478/452/378 462/436/362 +f 464/438/364 480/454/380 479/453/379 463/437/363 +f 465/439/365 481/455/381 480/454/380 464/438/364 +f 466/440/366 482/456/382 481/455/381 465/439/365 +f 467/441/367 483/457/383 482/456/382 466/440/366 +f 468/442/368 484/458/384 483/457/383 467/441/367 +f 469/443/369 485/459/385 484/458/384 468/442/368 +f 470/444/370 486/460/386 485/459/385 469/443/369 +f 471/445/371 487/461/387 486/460/386 470/444/370 +f 472/446/372 488/462/388 487/461/387 471/445/371 +f 473/447/373 489/463/389 488/462/388 472/446/372 +f 474/448/374 490/464/390 489/463/389 473/447/373 +f 475/449/375 491/465/391 490/464/390 474/448/374 +f 476/450/376 492/466/392 491/465/391 475/449/375 +f 461/435/361 477/451/377 492/466/392 476/450/376 +# 32 polygons - 16 triangles + +# +# object led2 +# + +v 20.0000 25.8495 0.8829 +v 20.5945 25.8495 0.8829 +v 20.5493 26.0771 0.8829 +v 20.4204 26.2699 0.8829 +v 20.2275 26.3988 0.8829 +v 20.0000 26.4441 0.8829 +v 19.7725 26.3988 0.8829 +v 19.5796 26.2699 0.8829 +v 19.4507 26.0771 0.8829 +v 19.4055 25.8495 0.8829 +v 19.4507 25.6220 0.8829 +v 19.5796 25.4291 0.8829 +v 19.7725 25.3002 0.8829 +v 20.0000 25.2550 0.8829 +v 20.2275 25.3002 0.8829 +v 20.4204 25.4291 0.8829 +v 20.5493 25.6220 0.8829 +v 21.5884 25.8495 0.4712 +v 21.4674 26.4574 0.4712 +v 21.1231 26.9727 0.4712 +v 20.6078 27.3170 0.4712 +v 20.0000 27.4379 0.4712 +v 19.3922 27.3170 0.4712 +v 18.8769 26.9727 0.4712 +v 18.5326 26.4574 0.4712 +v 18.4116 25.8495 0.4712 +v 18.5326 25.2417 0.4712 +v 18.8769 24.7264 0.4712 +v 19.3922 24.3821 0.4712 +v 20.0000 24.2612 0.4712 +v 20.6078 24.3821 0.4712 +v 21.1231 24.7264 0.4712 +v 21.4674 25.2417 0.4712 +v 22.0000 25.8495 -0.5226 +v 21.8478 26.6149 -0.5226 +v 21.4142 27.2637 -0.5226 +v 20.7654 27.6973 -0.5226 +v 20.0000 27.8495 -0.5226 +v 19.2346 27.6973 -0.5226 +v 18.5858 27.2637 -0.5226 +v 18.1522 26.6149 -0.5226 +v 18.0000 25.8495 -0.5226 +v 18.1522 25.0842 -0.5226 +v 18.5858 24.4353 -0.5226 +v 19.2346 24.0018 -0.5226 +v 20.0000 23.8495 -0.5226 +v 20.7654 24.0018 -0.5226 +v 21.4142 24.4353 -0.5226 +v 21.8478 25.0842 -0.5226 +# 49 vertices + +vn 0.0000 -0.0000 1.0000 +vn 0.2183 -0.0000 0.9759 +vn 0.2017 0.0835 0.9759 +vn 0.1544 0.1544 0.9759 +vn 0.0835 0.2017 0.9759 +vn 0.0000 0.2183 0.9759 +vn -0.0835 0.2017 0.9759 +vn -0.1544 0.1544 0.9759 +vn -0.2017 0.0835 0.9759 +vn -0.2183 -0.0000 0.9759 +vn -0.2017 -0.0835 0.9759 +vn -0.1544 -0.1544 0.9759 +vn -0.0835 -0.2017 0.9759 +vn 0.0000 -0.2183 0.9759 +vn 0.0835 -0.2017 0.9759 +vn 0.1544 -0.1544 0.9759 +vn 0.2017 -0.0835 0.9759 +vn 0.7294 0.0000 0.6840 +vn 0.6739 0.2791 0.6840 +vn 0.5158 0.5158 0.6840 +vn 0.2791 0.6739 0.6840 +vn 0.0000 0.7294 0.6840 +vn -0.2791 0.6739 0.6840 +vn -0.5158 0.5158 0.6840 +vn -0.6739 0.2791 0.6840 +vn -0.7294 0.0000 0.6840 +vn -0.6739 -0.2791 0.6840 +vn -0.5158 -0.5158 0.6840 +vn -0.2791 -0.6739 0.6840 +vn 0.0000 -0.7294 0.6840 +vn 0.2791 -0.6739 0.6840 +vn 0.5158 -0.5158 0.6840 +vn 0.6739 -0.2791 0.6840 +vn 0.9239 0.0000 0.3827 +vn 0.8536 0.3536 0.3827 +vn 0.6533 0.6533 0.3827 +vn 0.3536 0.8536 0.3827 +vn 0.0000 0.9239 0.3827 +vn -0.3536 0.8536 0.3827 +vn -0.6533 0.6533 0.3827 +vn -0.8536 0.3536 0.3827 +vn -0.9239 0.0000 0.3827 +vn -0.8536 -0.3536 0.3827 +vn -0.6533 -0.6533 0.3827 +vn -0.3536 -0.8536 0.3827 +vn 0.0000 -0.9239 0.3827 +vn 0.3536 -0.8536 0.3827 +vn 0.6533 -0.6533 0.3827 +vn 0.8536 -0.3536 0.3827 +# 49 vertex normals + +vt 0.5000 0.5000 0.0000 +vt 0.6486 0.5000 0.0000 +vt 0.6373 0.5569 0.0000 +vt 0.6051 0.6051 0.0000 +vt 0.5569 0.6373 0.0000 +vt 0.5000 0.6486 0.0000 +vt 0.4431 0.6373 0.0000 +vt 0.3949 0.6051 0.0000 +vt 0.3627 0.5569 0.0000 +vt 0.3514 0.5000 0.0000 +vt 0.3627 0.4431 0.0000 +vt 0.3949 0.3949 0.0000 +vt 0.4431 0.3627 0.0000 +vt 0.5000 0.3514 0.0000 +vt 0.5569 0.3627 0.0000 +vt 0.6051 0.3949 0.0000 +vt 0.6373 0.4431 0.0000 +vt 0.8971 0.5000 0.0000 +vt 0.8669 0.6520 0.0000 +vt 0.7808 0.7808 0.0000 +vt 0.6520 0.8669 0.0000 +vt 0.5000 0.8971 0.0000 +vt 0.3480 0.8669 0.0000 +vt 0.2192 0.7808 0.0000 +vt 0.1331 0.6520 0.0000 +vt 0.1029 0.5000 0.0000 +vt 0.1331 0.3480 0.0000 +vt 0.2192 0.2192 0.0000 +vt 0.3480 0.1331 0.0000 +vt 0.5000 0.1029 0.0000 +vt 0.6520 0.1331 0.0000 +vt 0.7808 0.2192 0.0000 +vt 0.8669 0.3480 0.0000 +vt 1.0000 0.5000 0.0000 +vt 0.9619 0.6913 0.0000 +vt 0.8536 0.8536 0.0000 +vt 0.6913 0.9619 0.0000 +vt 0.5000 1.0000 0.0000 +vt 0.3087 0.9619 0.0000 +vt 0.1464 0.8536 0.0000 +vt 0.0381 0.6913 0.0000 +vt 0.0000 0.5000 0.0000 +vt 0.0381 0.3087 0.0000 +vt 0.1464 0.1464 0.0000 +vt 0.3087 0.0381 0.0000 +vt 0.5000 0.0000 0.0000 +vt 0.6913 0.0381 0.0000 +vt 0.8536 0.1464 0.0000 +vt 0.9619 0.3087 0.0000 +# 49 texture coords + +g led2 +usemtl 03___Default +s 4 +f 493/467/393 494/468/394 495/469/395 +f 493/467/393 495/469/395 496/470/396 +f 493/467/393 496/470/396 497/471/397 +f 493/467/393 497/471/397 498/472/398 +f 493/467/393 498/472/398 499/473/399 +f 493/467/393 499/473/399 500/474/400 +f 493/467/393 500/474/400 501/475/401 +f 493/467/393 501/475/401 502/476/402 +f 493/467/393 502/476/402 503/477/403 +f 493/467/393 503/477/403 504/478/404 +f 493/467/393 504/478/404 505/479/405 +f 493/467/393 505/479/405 506/480/406 +f 493/467/393 506/480/406 507/481/407 +f 493/467/393 507/481/407 508/482/408 +f 493/467/393 508/482/408 509/483/409 +f 493/467/393 509/483/409 494/468/394 +f 494/468/394 510/484/410 511/485/411 495/469/395 +f 495/469/395 511/485/411 512/486/412 496/470/396 +f 496/470/396 512/486/412 513/487/413 497/471/397 +f 497/471/397 513/487/413 514/488/414 498/472/398 +f 498/472/398 514/488/414 515/489/415 499/473/399 +f 499/473/399 515/489/415 516/490/416 500/474/400 +f 500/474/400 516/490/416 517/491/417 501/475/401 +f 501/475/401 517/491/417 518/492/418 502/476/402 +f 502/476/402 518/492/418 519/493/419 503/477/403 +f 503/477/403 519/493/419 520/494/420 504/478/404 +f 504/478/404 520/494/420 521/495/421 505/479/405 +f 505/479/405 521/495/421 522/496/422 506/480/406 +f 506/480/406 522/496/422 523/497/423 507/481/407 +f 507/481/407 523/497/423 524/498/424 508/482/408 +f 508/482/408 524/498/424 525/499/425 509/483/409 +f 509/483/409 525/499/425 510/484/410 494/468/394 +f 510/484/410 526/500/426 527/501/427 511/485/411 +f 511/485/411 527/501/427 528/502/428 512/486/412 +f 512/486/412 528/502/428 529/503/429 513/487/413 +f 513/487/413 529/503/429 530/504/430 514/488/414 +f 514/488/414 530/504/430 531/505/431 515/489/415 +f 515/489/415 531/505/431 532/506/432 516/490/416 +f 516/490/416 532/506/432 533/507/433 517/491/417 +f 517/491/417 533/507/433 534/508/434 518/492/418 +f 518/492/418 534/508/434 535/509/435 519/493/419 +f 519/493/419 535/509/435 536/510/436 520/494/420 +f 520/494/420 536/510/436 537/511/437 521/495/421 +f 521/495/421 537/511/437 538/512/438 522/496/422 +f 522/496/422 538/512/438 539/513/439 523/497/423 +f 523/497/423 539/513/439 540/514/440 524/498/424 +f 524/498/424 540/514/440 541/515/441 525/499/425 +f 525/499/425 541/515/441 526/500/426 510/484/410 +# 32 polygons - 16 triangles + +# +# object 7seg1 +# + +v -14.9101 33.4418 -3.5118 +v -14.9101 13.5418 -3.5118 +v -0.0434 13.5418 -3.5118 +v -0.0434 33.4418 -3.5118 +v -0.0434 13.5418 -8.5118 +v -14.9101 13.5418 -8.5118 +v -14.9101 33.4418 -8.5118 +v -0.0434 33.4418 -8.5118 +# 8 vertices + +vn 0.0000 -0.0000 1.0000 +vn 0.0000 0.0000 -1.0000 +vn 0.0000 -1.0000 -0.0000 +vn 1.0000 0.0000 -0.0000 +vn 0.0000 1.0000 0.0000 +vn -1.0000 0.0000 -0.0000 +# 6 vertex normals + +vt 0.0000 0.9995 0.9995 +vt 0.0000 0.0005 0.9995 +vt 0.0908 0.0005 0.9995 +vt 0.0908 0.9995 0.9995 +vt 0.0908 0.0005 0.0005 +vt 0.0000 0.0005 0.0005 +vt 0.0000 0.9995 0.0005 +vt 0.0908 0.9995 0.0005 +# 8 texture coords + +g 7seg1 +usemtl 08___Default +s 2 +f 542/516/442 543/517/442 544/518/442 545/519/442 +s 4 +f 546/520/443 547/521/443 548/522/443 549/523/443 +s 8 +f 544/518/444 543/517/444 547/521/444 546/520/444 +s 16 +f 545/519/445 544/518/445 546/520/445 549/523/445 +s 32 +f 542/516/446 545/519/446 549/523/446 548/522/446 +s 64 +f 543/517/447 542/516/447 548/522/447 547/521/447 +# 6 polygons + +# +# object 7seg0 +# + +v 0.0439 33.4418 -3.5118 +v 0.0439 13.5418 -3.5118 +v 14.9106 13.5418 -3.5118 +v 14.9106 33.4418 -3.5118 +v 14.9106 13.5418 -8.5118 +v 0.0439 13.5418 -8.5118 +v 0.0439 33.4418 -8.5118 +v 14.9106 33.4418 -8.5118 +# 8 vertices + +vn 0.0000 -0.0000 1.0000 +vn 0.0000 0.0000 -1.0000 +vn 0.0000 -1.0000 -0.0000 +vn 1.0000 0.0000 -0.0000 +vn 0.0000 1.0000 0.0000 +vn -1.0000 0.0000 -0.0000 +# 6 vertex normals + +vt 0.0000 0.9995 0.9995 +vt 0.0000 0.0005 0.9995 +vt 0.0908 0.0005 0.9995 +vt 0.0908 0.9995 0.9995 +vt 0.0908 0.0005 0.0005 +vt 0.0000 0.0005 0.0005 +vt 0.0000 0.9995 0.0005 +vt 0.0908 0.9995 0.0005 +# 8 texture coords + +g 7seg0 +usemtl 08___Default +s 2 +f 550/524/448 551/525/448 552/526/448 553/527/448 +s 4 +f 554/528/449 555/529/449 556/530/449 557/531/449 +s 8 +f 552/526/450 551/525/450 555/529/450 554/528/450 +s 16 +f 553/527/451 552/526/451 554/528/451 557/531/451 +s 32 +f 550/524/452 553/527/452 557/531/452 556/530/452 +s 64 +f 551/525/453 550/524/453 556/530/453 555/529/453 +# 6 polygons + diff --git a/data/envmap.png b/data/envmap.png new file mode 100644 index 0000000000000000000000000000000000000000..2b34f961c992046ac7b8805975b54224adc21a4c GIT binary patch literal 24615 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 + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + 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 +state 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 3 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, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program 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, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU 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 Lesser General +Public License instead of this License. But first, please read +. diff --git a/libs/libimago/COPYING.LESSER b/libs/libimago/COPYING.LESSER new file mode 100644 index 0000000..65c5ca8 --- /dev/null +++ b/libs/libimago/COPYING.LESSER @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + 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 that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/libs/libimago/Makefile.in b/libs/libimago/Makefile.in new file mode 100644 index 0000000..7d7c912 --- /dev/null +++ b/libs/libimago/Makefile.in @@ -0,0 +1,76 @@ +dbg = -g +opt = + +csrc = $(wildcard src/*.c) +obj = $(csrc:.c=.o) +lib_a = libimago.a + +somajor = 2 +sominor = 0 + +incdir = -I$(PREFIX)/include +libdir = -L$(PREFIX)/lib + +ifeq ($(shell uname -s), Darwin) + lib_so = libimago.dylib + shared = -dynamiclib + # add macports and fink dirs to the include and lib paths + incdir += -I/opt/local/include -I/sw/local/include -I/usr/X11R6/include + libdir += -L/opt/local/lib -L/sw/local/lib -L/usr/X11R6/lib +else + soname = libimago.so.$(somajor) + lib_so = $(soname).$(sominor) + solink = libimago.so + shared = -shared -Wl,-soname,$(soname) +endif + +ifeq ($(shell uname -s), IRIX) + # add nekoware and SGI freeware dirs to the include and lib paths + incdir += -I/usr/nekoware/include -I/usr/freeware/include + libdir += -L/usr/nekoware/lib -L/usr/freeware/lib +endif + +CC = gcc +AR = ar +CFLAGS = -pedantic -Wall $(opt) $(dbg) -fPIC -Isrc $(incdir) +LDFLAGS = $(libdir) -lpng -lz -ljpeg -ldl + +.PHONY: all +all: $(lib_a) $(lib_so) + +$(lib_a): $(obj) + $(AR) rcs $@ $^ + +$(lib_so): $(obj) + $(CC) $(CFLAGS) $(shared) -o $@ $^ $(LDFLAGS) + +.PHONY: clean +clean: + rm -f $(obj) + +.PHONY: distclean +distclean: + rm -f $(obj) $(lib_so) $(lib_a) Makefile src/modules.c + +.PHONY: install +install: $(lib_so) $(lib_a) + mkdir -p $(DESTDIR)$(PREFIX)/include $(DESTDIR)$(PREFIX)/lib + cp src/imago2.h $(DESTDIR)$(PREFIX)/include/imago2.h + cp $(lib_so) $(DESTDIR)$(PREFIX)/lib/$(lib_so) + cp $(lib_a) $(DESTDIR)$(PREFIX)/lib/$(lib_a) + [ -n "$(solink)" ] \ + && cd $(DESTDIR)$(PREFIX)/lib \ + && rm -f $(solink) $(soname) \ + && ln -s $(lib_so) $(soname) \ + && ln -s $(soname) $(solink) \ + || true + +.PHONY: uninstall +uninstall: + rm -f $(DESTDIR)$(PREFIX)/include/imago2.h + rm -f $(DESTDIR)$(PREFIX)/lib/$(lib_so) + rm -f $(DESTDIR)$(PREFIX)/lib/$(lib_a) + [ -n "$(solink)" ] \ + && rm -f $(DESTDIR)$(PREFIX)/lib/$(solink) \ + && rm -f $(DESTDIR)$(PREFIX)/lib/$(soname) \ + || true diff --git a/libs/libimago/README b/libs/libimago/README new file mode 100644 index 0000000..6d0eb13 --- /dev/null +++ b/libs/libimago/README @@ -0,0 +1,8 @@ +imago version 2.0 +----------------- + +Author: John Tsiombikas + +This library is released as free software under the term of the GNU Lesser +General Public License (LGPL) version 3 or any later version published by +the Free Software Foundation. See COPYING and COPYING.LESSER for details. diff --git a/libs/libimago/build/vcconfig.bat b/libs/libimago/build/vcconfig.bat new file mode 100644 index 0000000..2b8177d --- /dev/null +++ b/libs/libimago/build/vcconfig.bat @@ -0,0 +1,14 @@ +@set outfile=src/modules.c + +@echo /* this file is generated by vcconfig.bat, do not edit */ >%outfile% +@echo int img_register_png(); >>%outfile% +@echo int img_register_jpeg(); >>%outfile% +@echo int img_register_ppm(); >>%outfile% +@echo int img_register_rgbe(); >>%outfile% +@echo void img_modules_init(void) >>%outfile% +@echo { >>%outfile% +@echo img_register_png(); >>%outfile% +@echo img_register_jpeg(); >>%outfile% +@echo img_register_ppm(); >>%outfile% +@echo img_register_rgbe(); >>%outfile% +@echo } >>%outfile% diff --git a/libs/libimago/configure b/libs/libimago/configure new file mode 100755 index 0000000..370c179 --- /dev/null +++ b/libs/libimago/configure @@ -0,0 +1,27 @@ +#!/bin/sh + +gen_module_init() +{ + # collect all src/file_whatever.c files + modules=`ls src/file_*.c 2>/dev/null | sort | sed 's/src\/file_//' | sed 's/\.c//'` + + echo "/* this file is generated by $0, do not edit */" + for m in $modules; do + echo "int img_register_$m();" + done + + echo + echo 'void img_modules_init(void)' + echo '{' + + for m in $modules; do + echo " img_register_$m();" + done + + echo '}' +} + +gen_module_init >src/modules.c + +echo 'PREFIX = /usr/local' >Makefile +cat Makefile.in >>Makefile diff --git a/libs/libimago/imago-vs2012.sln b/libs/libimago/imago-vs2012.sln new file mode 100644 index 0000000..737c2e3 --- /dev/null +++ b/libs/libimago/imago-vs2012.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imago", "imago-vs2012.vcxproj", "{1FFDD3FB-E37E-4258-8955-5583AF3A0C29}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1FFDD3FB-E37E-4258-8955-5583AF3A0C29}.Debug|Win32.ActiveCfg = Debug|Win32 + {1FFDD3FB-E37E-4258-8955-5583AF3A0C29}.Debug|Win32.Build.0 = Debug|Win32 + {1FFDD3FB-E37E-4258-8955-5583AF3A0C29}.Debug|x64.ActiveCfg = Debug|x64 + {1FFDD3FB-E37E-4258-8955-5583AF3A0C29}.Debug|x64.Build.0 = Debug|x64 + {1FFDD3FB-E37E-4258-8955-5583AF3A0C29}.Release|Win32.ActiveCfg = Release|Win32 + {1FFDD3FB-E37E-4258-8955-5583AF3A0C29}.Release|Win32.Build.0 = Release|Win32 + {1FFDD3FB-E37E-4258-8955-5583AF3A0C29}.Release|x64.ActiveCfg = Release|x64 + {1FFDD3FB-E37E-4258-8955-5583AF3A0C29}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/libimago/imago-vs2012.vcxproj b/libs/libimago/imago-vs2012.vcxproj new file mode 100644 index 0000000..b4bd4b6 --- /dev/null +++ b/libs/libimago/imago-vs2012.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + libimago2 + {1FFDD3FB-E37E-4258-8955-5583AF3A0C29} + imago + Win32Proj + + + + StaticLibrary + v110 + Unicode + true + + + StaticLibrary + v100 + Unicode + true + + + StaticLibrary + v110 + Unicode + + + StaticLibrary + v100 + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>11.0.60610.1 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(ProjectName)-x64 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(ProjectName)-x64 + + + + $(SolutionDir)\build\vcconfig.bat + + + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + 4244;4996;%(DisableSpecificWarnings) + + + + + $(SolutionDir)\build\vcconfig.bat + + + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + ProgramDatabase + 4244;4996;%(DisableSpecificWarnings) + + + mkdir $(SolutionDir)\usr\include +mkdir $(SolutionDir)\usr\lib +copy /Y $(SolutionDir)\src\imago2.h $(SolutionDir)\usr\include\ +copy /Y $(TargetPath) $(SolutionDir)\usr\lib\ + + + + + MaxSpeed + true + false + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + 4244;4996;%(DisableSpecificWarnings) + + + + + MaxSpeed + true + false + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + 4244;4996;%(DisableSpecificWarnings) + + + mkdir $(SolutionDir)\usr\include +mkdir $(SolutionDir)\usr\lib +copy /Y $(SolutionDir)\src\imago2.h $(SolutionDir)\usr\include\ +copy /Y $(TargetPath) $(SolutionDir)\usr\lib\ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/libimago/imago-vs2012.vcxproj.filters b/libs/libimago/imago-vs2012.vcxproj.filters new file mode 100644 index 0000000..de16c20 --- /dev/null +++ b/libs/libimago/imago-vs2012.vcxproj.filters @@ -0,0 +1,51 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/libs/libimago/imago.sln b/libs/libimago/imago.sln new file mode 100644 index 0000000..ab4ba84 --- /dev/null +++ b/libs/libimago/imago.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imago", "imago.vcproj", "{1FFDD3FB-E37E-4258-8955-5583AF3A0C29}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1FFDD3FB-E37E-4258-8955-5583AF3A0C29}.Debug|Win32.ActiveCfg = Debug|Win32 + {1FFDD3FB-E37E-4258-8955-5583AF3A0C29}.Debug|Win32.Build.0 = Debug|Win32 + {1FFDD3FB-E37E-4258-8955-5583AF3A0C29}.Release|Win32.ActiveCfg = Release|Win32 + {1FFDD3FB-E37E-4258-8955-5583AF3A0C29}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/libimago/imago.vcproj b/libs/libimago/imago.vcproj new file mode 100644 index 0000000..17fc3bf --- /dev/null +++ b/libs/libimago/imago.vcproj @@ -0,0 +1,211 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/libimago/install.bat b/libs/libimago/install.bat new file mode 100644 index 0000000..5bb1ad2 --- /dev/null +++ b/libs/libimago/install.bat @@ -0,0 +1,5 @@ +mkdir c:\usr\include\ +copy /Y usr\include\* c:\usr\include\ +mkdir c:\usr\lib +copy /Y usr\lib\* c:\usr\lib\ +pause diff --git a/libs/libimago/src/conv.c b/libs/libimago/src/conv.c new file mode 100644 index 0000000..334fe35 --- /dev/null +++ b/libs/libimago/src/conv.c @@ -0,0 +1,260 @@ +/* +libimago - a multi-format image file input/output library. +Copyright (C) 2010 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see . +*/ +#include +#include "imago2.h" + +/* pixel-format conversions are sub-optimal at the moment to avoid + * writing a lot of code. optimize at some point ? + */ + +#define CLAMP(x, a, b) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x))) + +struct pixel { + float r, g, b, a; +}; + +static void unpack_grey8(struct pixel *unp, void *pptr, int count); +static void unpack_rgb24(struct pixel *unp, void *pptr, int count); +static void unpack_rgba32(struct pixel *unp, void *pptr, int count); +static void unpack_greyf(struct pixel *unp, void *pptr, int count); +static void unpack_rgbf(struct pixel *unp, void *pptr, int count); +static void unpack_rgbaf(struct pixel *unp, void *pptr, int count); + +static void pack_grey8(void *pptr, struct pixel *unp, int count); +static void pack_rgb24(void *pptr, struct pixel *unp, int count); +static void pack_rgba32(void *pptr, struct pixel *unp, int count); +static void pack_greyf(void *pptr, struct pixel *unp, int count); +static void pack_rgbf(void *pptr, struct pixel *unp, int count); +static void pack_rgbaf(void *pptr, struct pixel *unp, int count); + +/* XXX keep in sync with enum img_fmt at imago2.h */ +static void (*unpack[])(struct pixel*, void*, int) = { + unpack_grey8, + unpack_rgb24, + unpack_rgba32, + unpack_greyf, + unpack_rgbf, + unpack_rgbaf +}; + +/* XXX keep in sync with enum img_fmt at imago2.h */ +static void (*pack[])(void*, struct pixel*, int) = { + pack_grey8, + pack_rgb24, + pack_rgba32, + pack_greyf, + pack_rgbf, + pack_rgbaf +}; + + +int img_convert(struct img_pixmap *img, enum img_fmt tofmt) +{ + struct pixel pbuf[8]; + int bufsz = (img->width & 7) == 0 ? 8 : ((img->width & 3) == 0 ? 4 : 1); + int i, num_pix = img->width * img->height; + int num_iter = num_pix / bufsz; + char *sptr, *dptr; + struct img_pixmap nimg; + + if(img->fmt == tofmt) { + return 0; /* nothing to do */ + } + + img_init(&nimg); + if(img_set_pixels(&nimg, img->width, img->height, tofmt, 0) == -1) { + img_destroy(&nimg); + return -1; + } + + sptr = img->pixels; + dptr = nimg.pixels; + + for(i=0; ifmt](pbuf, sptr, bufsz); + pack[tofmt](dptr, pbuf, bufsz); + + sptr += bufsz * img->pixelsz; + dptr += bufsz * nimg.pixelsz; + } + + img_copy(img, &nimg); + img_destroy(&nimg); + return 0; +} + +/* the following functions *could* benefit from SIMD */ + +static void unpack_grey8(struct pixel *unp, void *pptr, int count) +{ + int i; + unsigned char *pix = pptr; + + for(i=0; ir = unp->g = unp->b = (float)*pix++ / 255.0; + unp->a = 1.0; + unp++; + } +} + +static void unpack_rgb24(struct pixel *unp, void *pptr, int count) +{ + int i; + unsigned char *pix = pptr; + + for(i=0; ir = (float)*pix++ / 255.0; + unp->g = (float)*pix++ / 255.0; + unp->b = (float)*pix++ / 255.0; + unp->a = 1.0; + unp++; + } +} + +static void unpack_rgba32(struct pixel *unp, void *pptr, int count) +{ + int i; + unsigned char *pix = pptr; + + for(i=0; ir = (float)*pix++ / 255.0; + unp->g = (float)*pix++ / 255.0; + unp->b = (float)*pix++ / 255.0; + unp->a = (float)*pix++ / 255.0; + unp++; + } +} + +static void unpack_greyf(struct pixel *unp, void *pptr, int count) +{ + int i; + float *pix = pptr; + + for(i=0; ir = unp->g = unp->b = *pix++; + unp->a = 1.0; + unp++; + } +} + +static void unpack_rgbf(struct pixel *unp, void *pptr, int count) +{ + int i; + float *pix = pptr; + + for(i=0; ir = *pix++; + unp->g = *pix++; + unp->b = *pix++; + unp->a = 1.0; + unp++; + } +} + +static void unpack_rgbaf(struct pixel *unp, void *pptr, int count) +{ + int i; + float *pix = pptr; + + for(i=0; ir = *pix++; + unp->g = *pix++; + unp->b = *pix++; + unp->a = *pix++; + unp++; + } +} + + +static void pack_grey8(void *pptr, struct pixel *unp, int count) +{ + int i; + unsigned char *pix = pptr; + + for(i=0; ir + unp->g + unp->b) / 3.0); + *pix++ = CLAMP(lum, 0, 255); + unp++; + } +} + +static void pack_rgb24(void *pptr, struct pixel *unp, int count) +{ + int i; + unsigned char *pix = pptr; + + for(i=0; ir * 255.0); + int g = (int)(unp->g * 255.0); + int b = (int)(unp->b * 255.0); + + *pix++ = CLAMP(r, 0, 255); + *pix++ = CLAMP(g, 0, 255); + *pix++ = CLAMP(b, 0, 255); + unp++; + } +} + +static void pack_rgba32(void *pptr, struct pixel *unp, int count) +{ + int i; + unsigned char *pix = pptr; + + for(i=0; ir * 255.0); + int g = (int)(unp->g * 255.0); + int b = (int)(unp->b * 255.0); + int a = (int)(unp->a * 255.0); + + *pix++ = CLAMP(r, 0, 255); + *pix++ = CLAMP(g, 0, 255); + *pix++ = CLAMP(b, 0, 255); + *pix++ = CLAMP(a, 0, 255); + unp++; + } +} + +static void pack_greyf(void *pptr, struct pixel *unp, int count) +{ + int i; + float *pix = pptr; + + for(i=0; ir + unp->g + unp->b) / 3.0; + unp++; + } +} + +static void pack_rgbf(void *pptr, struct pixel *unp, int count) +{ + int i; + float *pix = pptr; + + for(i=0; ir; + *pix++ = unp->g; + *pix++ = unp->b; + unp++; + } +} + +static void pack_rgbaf(void *pptr, struct pixel *unp, int count) +{ + memcpy(pptr, unp, count * sizeof *unp); +} + diff --git a/libs/libimago/src/file_jpeg.c b/libs/libimago/src/file_jpeg.c new file mode 100644 index 0000000..ba5247e --- /dev/null +++ b/libs/libimago/src/file_jpeg.c @@ -0,0 +1,294 @@ +/* +libimago - a multi-format image file input/output library. +Copyright (C) 2010 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see . +*/ + +/* -- JPEG module -- */ + +#include +#include +#include + +#ifdef WIN32 +#include +#define HAVE_BOOLEAN +#endif + +#include +#include "imago2.h" +#include "ftype_module.h" + +#define INPUT_BUF_SIZE 512 +#define OUTPUT_BUF_SIZE 512 + +/* data source manager: adapted from jdatasrc.c */ +struct src_mgr { + struct jpeg_source_mgr pub; + + struct img_io *io; + unsigned char buffer[INPUT_BUF_SIZE]; + int start_of_file; +}; + +/* data destination manager: adapted from jdatadst.c */ +struct dst_mgr { + struct jpeg_destination_mgr pub; + + struct img_io *io; + unsigned char buffer[OUTPUT_BUF_SIZE]; +}; + +static int check(struct img_io *io); +static int read(struct img_pixmap *img, struct img_io *io); +static int write(struct img_pixmap *img, struct img_io *io); + +/* read source functions */ +static void init_source(j_decompress_ptr jd); +static boolean fill_input_buffer(j_decompress_ptr jd); +static void skip_input_data(j_decompress_ptr jd, long num_bytes); +static void term_source(j_decompress_ptr jd); + +/* write destination functions */ +static void init_destination(j_compress_ptr jc); +static boolean empty_output_buffer(j_compress_ptr jc); +static void term_destination(j_compress_ptr jc); + +int img_register_jpeg(void) +{ + static struct ftype_module mod = {".jpg", check, read, write}; + return img_register_module(&mod); +} + + +static int check(struct img_io *io) +{ + unsigned char sig[10]; + + long pos = io->seek(0, SEEK_CUR, io->uptr); + + if(io->read(sig, 10, io->uptr) < 10) { + io->seek(pos, SEEK_SET, io->uptr); + return -1; + } + + if(memcmp(sig, "\xff\xd8\xff\xe0", 4) != 0 && memcmp(sig, "\xff\xd8\xff\xe1", 4) != 0 + && memcmp(sig + 6, "JFIF", 4) != 0) { + io->seek(pos, SEEK_SET, io->uptr); + return -1; + } + io->seek(pos, SEEK_SET, io->uptr); + return 0; +} + +static int read(struct img_pixmap *img, struct img_io *io) +{ + int i, nlines = 0; + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + struct src_mgr src; + unsigned char **scanlines; + + io->seek(0, SEEK_CUR, io->uptr); + + cinfo.err = jpeg_std_error(&jerr); /* XXX change... */ + jpeg_create_decompress(&cinfo); + + src.pub.init_source = init_source; + src.pub.fill_input_buffer = fill_input_buffer; + src.pub.skip_input_data = skip_input_data; + src.pub.resync_to_restart = jpeg_resync_to_restart; + src.pub.term_source = term_source; + src.pub.next_input_byte = 0; + src.pub.bytes_in_buffer = 0; + src.io = io; + cinfo.src = (struct jpeg_source_mgr*)&src; + + jpeg_read_header(&cinfo, 1); + cinfo.out_color_space = JCS_RGB; + + if(img_set_pixels(img, cinfo.image_width, cinfo.image_height, IMG_FMT_RGB24, 0) == -1) { + jpeg_destroy_decompress(&cinfo); + return -1; + } + + if(!(scanlines = malloc(img->height * sizeof *scanlines))) { + jpeg_destroy_decompress(&cinfo); + return -1; + } + scanlines[0] = img->pixels; + for(i=1; iheight; i++) { + scanlines[i] = scanlines[i - 1] + img->width * img->pixelsz; + } + + jpeg_start_decompress(&cinfo); + while(nlines < img->height) { + int res = jpeg_read_scanlines(&cinfo, scanlines + nlines, img->height - nlines); + nlines += res; + } + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + + free(scanlines); + return 0; +} + +static int write(struct img_pixmap *img, struct img_io *io) +{ + int i, nlines = 0; + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + struct dst_mgr dest; + struct img_pixmap tmpimg; + unsigned char **scanlines; + + img_init(&tmpimg); + + if(img->fmt != IMG_FMT_RGB24) { + if(img_copy(&tmpimg, img) == -1) { + return -1; + } + if(img_convert(&tmpimg, IMG_FMT_RGB24) == -1) { + img_destroy(&tmpimg); + return -1; + } + img = &tmpimg; + } + + if(!(scanlines = malloc(img->height * sizeof *scanlines))) { + img_destroy(&tmpimg); + return -1; + } + scanlines[0] = img->pixels; + for(i=1; iheight; i++) { + scanlines[i] = scanlines[i - 1] + img->width * img->pixelsz; + } + + cinfo.err = jpeg_std_error(&jerr); /* XXX */ + jpeg_create_compress(&cinfo); + + dest.pub.init_destination = init_destination; + dest.pub.empty_output_buffer = empty_output_buffer; + dest.pub.term_destination = term_destination; + dest.io = io; + cinfo.dest = (struct jpeg_destination_mgr*)&dest; + + cinfo.image_width = img->width; + cinfo.image_height = img->height; + cinfo.input_components = 3; + cinfo.in_color_space = JCS_RGB; + + jpeg_set_defaults(&cinfo); + + jpeg_start_compress(&cinfo, 1); + while(nlines < img->height) { + int res = jpeg_write_scanlines(&cinfo, scanlines + nlines, img->height - nlines); + nlines += res; + } + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + + free(scanlines); + img_destroy(&tmpimg); + return 0; +} + +/* -- read source functions -- + * the following functions are adapted from jdatasrc.c in jpeglib + */ +static void init_source(j_decompress_ptr jd) +{ + struct src_mgr *src = (struct src_mgr*)jd->src; + src->start_of_file = 1; +} + +static boolean fill_input_buffer(j_decompress_ptr jd) +{ + struct src_mgr *src = (struct src_mgr*)jd->src; + size_t nbytes; + + nbytes = src->io->read(src->buffer, INPUT_BUF_SIZE, src->io->uptr); + + if(nbytes <= 0) { + if(src->start_of_file) { + return 0; + } + /* insert a fake EOI marker */ + src->buffer[0] = 0xff; + src->buffer[1] = JPEG_EOI; + nbytes = 2; + } + + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_file = 0; + return 1; +} + +static void skip_input_data(j_decompress_ptr jd, long num_bytes) +{ + struct src_mgr *src = (struct src_mgr*)jd->src; + + if(num_bytes > 0) { + while(num_bytes > (long)src->pub.bytes_in_buffer) { + num_bytes -= (long)src->pub.bytes_in_buffer; + fill_input_buffer(jd); + } + src->pub.next_input_byte += (size_t)num_bytes; + src->pub.bytes_in_buffer -= (size_t)num_bytes; + } +} + +static void term_source(j_decompress_ptr jd) +{ + /* nothing to see here, move along */ +} + + +/* -- write destination functions -- + * the following functions are adapted from jdatadst.c in jpeglib + */ +static void init_destination(j_compress_ptr jc) +{ + struct dst_mgr *dest = (struct dst_mgr*)jc->dest; + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; +} + +static boolean empty_output_buffer(j_compress_ptr jc) +{ + struct dst_mgr *dest = (struct dst_mgr*)jc->dest; + + if(dest->io->write(dest->buffer, OUTPUT_BUF_SIZE, dest->io->uptr) != OUTPUT_BUF_SIZE) { + return 0; + } + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + return 1; +} + +static void term_destination(j_compress_ptr jc) +{ + struct dst_mgr *dest = (struct dst_mgr*)jc->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + + /* write any remaining data in the buffer */ + if(datacount > 0) { + dest->io->write(dest->buffer, datacount, dest->io->uptr); + } + /* XXX flush? ... */ +} diff --git a/libs/libimago/src/file_png.c b/libs/libimago/src/file_png.c new file mode 100644 index 0000000..123a3c4 --- /dev/null +++ b/libs/libimago/src/file_png.c @@ -0,0 +1,261 @@ +/* +libimago - a multi-format image file input/output library. +Copyright (C) 2010 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see . +*/ + +/* -- PNG module -- */ + +#include +#include +#include "imago2.h" +#include "ftype_module.h" + +static int check_file(struct img_io *io); +static int read_file(struct img_pixmap *img, struct img_io *io); +static int write_file(struct img_pixmap *img, struct img_io *io); + +static void read_func(png_struct *png, unsigned char *data, size_t len); +static void write_func(png_struct *png, unsigned char *data, size_t len); +static void flush_func(png_struct *png); + +static int png_type_to_fmt(int color_type, int channel_bits); +static int fmt_to_png_type(enum img_fmt fmt); + + +int img_register_png(void) +{ + static struct ftype_module mod = {".png", check_file, read_file, write_file}; + return img_register_module(&mod); +} + +static int check_file(struct img_io *io) +{ + unsigned char sig[8]; + int res; + long pos = io->seek(0, SEEK_CUR, io->uptr); + + if(io->read(sig, 8, io->uptr) < 8) { + io->seek(pos, SEEK_SET, io->uptr); + return -1; + } + + res = png_sig_cmp(sig, 0, 8) == 0 ? 0 : -1; + io->seek(pos, SEEK_SET, io->uptr); + return res; +} + +static int read_file(struct img_pixmap *img, struct img_io *io) +{ + png_struct *png; + png_info *info; + int channel_bits, color_type, ilace_type, compression, filtering, fmt; + png_uint_32 xsz, ysz; + + if(!(png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0))) { + return -1; + } + + if(!(info = png_create_info_struct(png))) { + png_destroy_read_struct(&png, 0, 0); + return -1; + } + + if(setjmp(png_jmpbuf(png))) { + png_destroy_read_struct(&png, &info, 0); + return -1; + } + + png_set_read_fn(png, io, read_func); + png_set_sig_bytes(png, 0); + png_read_png(png, info, 0, 0); + + png_get_IHDR(png, info, &xsz, &ysz, &channel_bits, &color_type, &ilace_type, + &compression, &filtering); + if((fmt = png_type_to_fmt(color_type, channel_bits)) == -1) { + png_destroy_read_struct(&png, &info, 0); + return -1; + } + + if(img_set_pixels(img, xsz, ysz, fmt, 0) == -1) { + png_destroy_read_struct(&png, &info, 0); + return -1; + } + + + if(channel_bits == 8) { + unsigned int i; + unsigned char **lineptr = (unsigned char**)png_get_rows(png, info); + unsigned char *dest = img->pixels; + + for(i=0; ipixelsz); + dest += xsz * img->pixelsz; + } + } else { + unsigned int i, j, num_elem; + unsigned char **lineptr = (unsigned char**)png_get_rows(png, info); + float *dest = img->pixels; + + num_elem = img->pixelsz / sizeof(float); + for(i=0; ifmt); + png_set_IHDR(png, info, img->width, img->height, 8, coltype, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + png_set_text(png, info, &txt, 1); + + if(!(rows = malloc(img->height * sizeof *rows))) { + png_destroy_write_struct(&png, &info); + img_destroy(&tmpimg); + return -1; + } + + pixptr = img->pixels; + for(i=0; iheight; i++) { + rows[i] = pixptr; + pixptr += img->width * img->pixelsz; + } + png_set_rows(png, info, rows); + + png_write_png(png, info, 0, 0); + png_write_end(png, info); + png_destroy_write_struct(&png, &info); + + free(rows); + + img_destroy(&tmpimg); + return 0; +} + +static void read_func(png_struct *png, unsigned char *data, size_t len) +{ + struct img_io *io = (struct img_io*)png_get_io_ptr(png); + + if(io->read(data, len, io->uptr) == -1) { + longjmp(png_jmpbuf(png), 1); + } +} + +static void write_func(png_struct *png, unsigned char *data, size_t len) +{ + struct img_io *io = (struct img_io*)png_get_io_ptr(png); + + if(io->write(data, len, io->uptr) == -1) { + longjmp(png_jmpbuf(png), 1); + } +} + +static void flush_func(png_struct *png) +{ + /* XXX does it matter that we can't flush? */ +} + +static int png_type_to_fmt(int color_type, int channel_bits) +{ + /* only 8 and 16 bits per channel ar supported at the moment */ + if(channel_bits != 8 && channel_bits != 16) { + return -1; + } + + switch(color_type) { + case PNG_COLOR_TYPE_RGB: + return channel_bits == 16 ? IMG_FMT_RGBF : IMG_FMT_RGB24; + + case PNG_COLOR_TYPE_RGB_ALPHA: + return channel_bits == 16 ? IMG_FMT_RGBAF : IMG_FMT_RGBA32; + + case PNG_COLOR_TYPE_GRAY: + return channel_bits == 16 ? IMG_FMT_GREYF : IMG_FMT_GREY8; + + default: + break; + } + return -1; +} + +static int fmt_to_png_type(enum img_fmt fmt) +{ + switch(fmt) { + case IMG_FMT_GREY8: + return PNG_COLOR_TYPE_GRAY; + + case IMG_FMT_RGB24: + return PNG_COLOR_TYPE_RGB; + + case IMG_FMT_RGBA32: + return PNG_COLOR_TYPE_RGBA; + + default: + break; + } + return -1; +} diff --git a/libs/libimago/src/file_ppm.c b/libs/libimago/src/file_ppm.c new file mode 100644 index 0000000..ffe1e46 --- /dev/null +++ b/libs/libimago/src/file_ppm.c @@ -0,0 +1,153 @@ +/* +libimago - a multi-format image file input/output library. +Copyright (C) 2010 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see . +*/ + +/* -- Portable Pixmap (PPM) module -- */ + +#include +#include "imago2.h" +#include "ftype_module.h" + +static int check(struct img_io *io); +static int read(struct img_pixmap *img, struct img_io *io); +static int write(struct img_pixmap *img, struct img_io *io); + +int img_register_ppm(void) +{ + static struct ftype_module mod = {".ppm", check, read, write}; + return img_register_module(&mod); +} + + +static int check(struct img_io *io) +{ + char id[2]; + int res = -1; + long pos = io->seek(0, SEEK_CUR, io->uptr); + + if(io->read(id, 2, io->uptr) < 2) { + io->seek(pos, SEEK_SET, io->uptr); + return -1; + } + + if(id[0] == 'P' && (id[1] == '6' || id[1] == '3')) { + res = 0; + } + io->seek(pos, SEEK_SET, io->uptr); + return res; +} + +static int iofgetc(struct img_io *io) +{ + char c; + return io->read(&c, 1, io->uptr) < 1 ? -1 : c; +} + +static char *iofgets(char *buf, int size, struct img_io *io) +{ + int c; + char *ptr = buf; + + while(--size > 0 && (c = iofgetc(io)) != -1) { + *ptr++ = c; + if(c == '\n') break; + } + *ptr = 0; + + return ptr == buf ? 0 : buf; +} + +/* TODO: implement P3 reading */ +static int read(struct img_pixmap *img, struct img_io *io) +{ + char buf[256]; + int xsz, ysz, maxval, got_hdrlines = 1; + + if(!iofgets(buf, sizeof buf, io)) { + return -1; + } + if(!(buf[0] == 'P' && (buf[1] == '6' || buf[1] == '3'))) { + return -1; + } + + while(got_hdrlines < 3 && iofgets(buf, sizeof buf, io)) { + if(buf[0] == '#') continue; + + switch(got_hdrlines) { + case 1: + if(sscanf(buf, "%d %d\n", &xsz, &ysz) < 2) { + return -1; + } + break; + + case 2: + if(sscanf(buf, "%d\n", &maxval) < 1) { + return -1; + } + default: + break; + } + got_hdrlines++; + } + + if(xsz < 1 || ysz < 1 || maxval != 255) { + return -1; + } + + if(img_set_pixels(img, xsz, ysz, IMG_FMT_RGB24, 0) == -1) { + return -1; + } + + if(io->read(img->pixels, xsz * ysz * 3, io->uptr) < (unsigned int)(xsz * ysz * 3)) { + return -1; + } + return 0; +} + +static int write(struct img_pixmap *img, struct img_io *io) +{ + int sz; + char buf[256]; + struct img_pixmap tmpimg; + + img_init(&tmpimg); + + if(img->fmt != IMG_FMT_RGB24) { + if(img_copy(&tmpimg, img) == -1) { + return -1; + } + if(img_convert(&tmpimg, IMG_FMT_RGB24) == -1) { + return -1; + } + img = &tmpimg; + } + + sprintf(buf, "P6\n#written by libimago2\n%d %d\n255\n", img->width, img->height); + if(io->write(buf, strlen(buf), io->uptr) < strlen(buf)) { + img_destroy(&tmpimg); + return -1; + } + + sz = img->width * img->height * 3; + if(io->write(img->pixels, sz, io->uptr) < (unsigned int)sz) { + img_destroy(&tmpimg); + return -1; + } + + img_destroy(&tmpimg); + return 0; +} diff --git a/libs/libimago/src/file_rgbe.c b/libs/libimago/src/file_rgbe.c new file mode 100644 index 0000000..16f8efa --- /dev/null +++ b/libs/libimago/src/file_rgbe.c @@ -0,0 +1,501 @@ +/* This file contains code to read and write four byte rgbe file format + * developed by Greg Ward. It handles the conversions between rgbe and + * pixels consisting of floats. The data is assumed to be an array of floats. + * By default there are three floats per pixel in the order red, green, blue. + * (RGBE_DATA_??? values control this.) + * + * written by Bruce Walter (bjw@graphics.cornell.edu) 5/26/95 + * based on code written by Greg Ward + * minor modifications by John Tsiombikas (nuclear@member.fsf.org) apr.9 2007 + */ + +#include +#include +#include +#include +#include +#include +#include "imago2.h" +#include "ftype_module.h" + + +typedef struct { + int valid; /* indicate which fields are valid */ + char programtype[16]; /* listed at beginning of file to identify it + * after "#?". defaults to "RGBE" */ + float gamma; /* image has already been gamma corrected with + * given gamma. defaults to 1.0 (no correction) */ + float exposure; /* a value of 1.0 in an image corresponds to + * watts/steradian/m^2. + * defaults to 1.0 */ +} rgbe_header_info; + + +static int check(struct img_io *io); +static int read(struct img_pixmap *img, struct img_io *io); +static int write(struct img_pixmap *img, struct img_io *io); + +static int rgbe_read_header(struct img_io *io, int *width, int *height, rgbe_header_info * info); +static int rgbe_read_pixels_rle(struct img_io *io, float *data, int scanline_width, int num_scanlines); + + +int img_register_rgbe(void) +{ + static struct ftype_module mod = {".rgbe", check, read, write}; + return img_register_module(&mod); +} + + +static int check(struct img_io *io) +{ + int xsz, ysz, res; + long pos = io->seek(0, SEEK_CUR, io->uptr); + + rgbe_header_info hdr; + res = rgbe_read_header(io, &xsz, &ysz, &hdr); + + io->seek(pos, SEEK_SET, io->uptr); + return res; +} + +static int read(struct img_pixmap *img, struct img_io *io) +{ + int xsz, ysz; + rgbe_header_info hdr; + + if(rgbe_read_header(io, &xsz, &ysz, &hdr) == -1) { + return -1; + } + + if(img_set_pixels(img, xsz, ysz, IMG_FMT_RGBF, 0) == -1) { + return -1; + } + if(rgbe_read_pixels_rle(io, img->pixels, xsz, ysz) == -1) { + return -1; + } + return 0; +} + +static int write(struct img_pixmap *img, struct img_io *io) +{ + return -1; /* TODO */ +} + + +static int iofgetc(struct img_io *io) +{ + char c; + return io->read(&c, 1, io->uptr) < 1 ? -1 : c; +} + +static char *iofgets(char *buf, int size, struct img_io *io) +{ + int c; + char *ptr = buf; + + while(--size > 0 && (c = iofgetc(io)) != -1) { + *ptr++ = c; + if(c == '\n') break; + } + *ptr = 0; + + return ptr == buf ? 0 : buf; +} + + +/* flags indicating which fields in an rgbe_header_info are valid */ +#define RGBE_VALID_PROGRAMTYPE 0x01 +#define RGBE_VALID_GAMMA 0x02 +#define RGBE_VALID_EXPOSURE 0x04 + +/* return codes for rgbe routines */ +#define RGBE_RETURN_SUCCESS 0 +#define RGBE_RETURN_FAILURE -1 + + +#if defined(__cplusplus) || defined(GNUC) || __STDC_VERSION >= 199901L +#define INLINE inline +#else +#define INLINE +#endif + +/* offsets to red, green, and blue components in a data (float) pixel */ +#define RGBE_DATA_RED 0 +#define RGBE_DATA_GREEN 1 +#define RGBE_DATA_BLUE 2 + +/* number of floats per pixel */ +#define RGBE_DATA_SIZE 3 + +enum rgbe_error_codes { + rgbe_read_error, + rgbe_write_error, + rgbe_format_error, + rgbe_memory_error +}; + + +/* default error routine. change this to change error handling */ +static int rgbe_error(int rgbe_error_code, char *msg) +{ + switch (rgbe_error_code) { + case rgbe_read_error: + fprintf(stderr, "RGBE read error: %s\n", strerror(errno)); + break; + + case rgbe_write_error: + fprintf(stderr, "RGBE write error: %s\n", strerror(errno)); + break; + + case rgbe_format_error: + fprintf(stderr, "RGBE bad file format: %s\n", msg); + break; + + default: + case rgbe_memory_error: + fprintf(stderr, "RGBE error: %s\n", msg); + } + return RGBE_RETURN_FAILURE; +} + +/* standard conversion from float pixels to rgbe pixels */ +/*static INLINE void float2rgbe(unsigned char rgbe[4], float red, float green, float blue) +{ + float v; + int e; + + v = red; + if(green > v) + v = green; + if(blue > v) + v = blue; + if(v < 1e-32) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + v = frexp(v, &e) * 256.0 / v; + rgbe[0] = (unsigned char)(red * v); + rgbe[1] = (unsigned char)(green * v); + rgbe[2] = (unsigned char)(blue * v); + rgbe[3] = (unsigned char)(e + 128); + } +}*/ + +/* standard conversion from rgbe to float pixels */ +/* note: Ward uses ldexp(col+0.5,exp-(128+8)). However we wanted pixels */ +/* in the range [0,1] to map back into the range [0,1]. */ +static INLINE void rgbe2float(float *red, float *green, float *blue, unsigned char rgbe[4]) +{ + float f; + + if(rgbe[3]) { /*nonzero pixel */ + f = ldexp(1.0, rgbe[3] - (int)(128 + 8)); + *red = rgbe[0] * f; + *green = rgbe[1] * f; + *blue = rgbe[2] * f; + } else + *red = *green = *blue = 0.0; +} + +#if 0 +/* default minimal header. modify if you want more information in header */ +static int rgbe_write_header(FILE * fp, int width, int height, rgbe_header_info * info) +{ + char *programtype = "RGBE"; + + if(info && (info->valid & RGBE_VALID_PROGRAMTYPE)) + programtype = info->programtype; + if(fprintf(fp, "#?%s\n", programtype) < 0) + return rgbe_error(rgbe_write_error, NULL); + /* The #? is to identify file type, the programtype is optional. */ + if(info && (info->valid & RGBE_VALID_GAMMA)) { + if(fprintf(fp, "GAMMA=%g\n", info->gamma) < 0) + return rgbe_error(rgbe_write_error, NULL); + } + if(info && (info->valid & RGBE_VALID_EXPOSURE)) { + if(fprintf(fp, "EXPOSURE=%g\n", info->exposure) < 0) + return rgbe_error(rgbe_write_error, NULL); + } + if(fprintf(fp, "FORMAT=32-bit_rle_rgbe\n\n") < 0) + return rgbe_error(rgbe_write_error, NULL); + if(fprintf(fp, "-Y %d +X %d\n", height, width) < 0) + return rgbe_error(rgbe_write_error, NULL); + return RGBE_RETURN_SUCCESS; +} +#endif + +/* minimal header reading. modify if you want to parse more information */ +static int rgbe_read_header(struct img_io *io, int *width, int *height, rgbe_header_info * info) +{ + char buf[128]; + float tempf; + int i; + + if(info) { + info->valid = 0; + info->programtype[0] = 0; + info->gamma = info->exposure = 1.0; + } + if(iofgets(buf, sizeof(buf) / sizeof(buf[0]), io) == NULL) + return RGBE_RETURN_FAILURE;/*rgbe_error(rgbe_read_error, NULL);*/ + if((buf[0] != '#') || (buf[1] != '?')) { + /* if you want to require the magic token then uncomment the next line */ + /*return rgbe_error(rgbe_format_error,"bad initial token"); */ + } else if(info) { + info->valid |= RGBE_VALID_PROGRAMTYPE; + for(i = 0; i < sizeof(info->programtype) - 1; i++) { + if((buf[i + 2] == 0) || isspace(buf[i + 2])) + break; + info->programtype[i] = buf[i + 2]; + } + info->programtype[i] = 0; + if(iofgets(buf, sizeof(buf) / sizeof(buf[0]), io) == 0) + return rgbe_error(rgbe_read_error, NULL); + } + for(;;) { + if((buf[0] == 0) || (buf[0] == '\n')) + return RGBE_RETURN_FAILURE;/*rgbe_error(rgbe_format_error, "no FORMAT specifier found");*/ + else if(strcmp(buf, "FORMAT=32-bit_rle_rgbe\n") == 0) + break; /* format found so break out of loop */ + else if(info && (sscanf(buf, "GAMMA=%g", &tempf) == 1)) { + info->gamma = tempf; + info->valid |= RGBE_VALID_GAMMA; + } else if(info && (sscanf(buf, "EXPOSURE=%g", &tempf) == 1)) { + info->exposure = tempf; + info->valid |= RGBE_VALID_EXPOSURE; + } + if(iofgets(buf, sizeof(buf) / sizeof(buf[0]), io) == 0) + return RGBE_RETURN_FAILURE;/*rgbe_error(rgbe_read_error, NULL);*/ + } + if(iofgets(buf, sizeof(buf) / sizeof(buf[0]), io) == 0) + return RGBE_RETURN_FAILURE;/*rgbe_error(rgbe_read_error, NULL);*/ + if(strcmp(buf, "\n") != 0) + return RGBE_RETURN_FAILURE;/*rgbe_error(rgbe_format_error, "missing blank line after FORMAT specifier");*/ + if(iofgets(buf, sizeof(buf) / sizeof(buf[0]), io) == 0) + return RGBE_RETURN_FAILURE;/*rgbe_error(rgbe_read_error, NULL);*/ + if(sscanf(buf, "-Y %d +X %d", height, width) < 2) + return RGBE_RETURN_FAILURE;/*rgbe_error(rgbe_format_error, "missing image size specifier");*/ + return RGBE_RETURN_SUCCESS; +} + +#if 0 +/* simple write routine that does not use run length encoding */ + +/* These routines can be made faster by allocating a larger buffer and + fread-ing and fwrite-ing the data in larger chunks */ +static int rgbe_write_pixels(FILE * fp, float *data, int numpixels) +{ + unsigned char rgbe[4]; + + while(numpixels-- > 0) { + float2rgbe(rgbe, data[RGBE_DATA_RED], data[RGBE_DATA_GREEN], data[RGBE_DATA_BLUE]); + data += RGBE_DATA_SIZE; + if(fwrite(rgbe, sizeof(rgbe), 1, fp) < 1) + return rgbe_error(rgbe_write_error, NULL); + } + return RGBE_RETURN_SUCCESS; +} +#endif + +/* simple read routine. will not correctly handle run length encoding */ +static int rgbe_read_pixels(struct img_io *io, float *data, int numpixels) +{ + unsigned char rgbe[4]; + + while(numpixels-- > 0) { + if(io->read(rgbe, sizeof(rgbe), io->uptr) < 1) + return rgbe_error(rgbe_read_error, NULL); + rgbe2float(&data[RGBE_DATA_RED], &data[RGBE_DATA_GREEN], &data[RGBE_DATA_BLUE], rgbe); + data += RGBE_DATA_SIZE; + } + return RGBE_RETURN_SUCCESS; +} + +#if 0 +/* The code below is only needed for the run-length encoded files. */ + +/* Run length encoding adds considerable complexity but does */ + +/* save some space. For each scanline, each channel (r,g,b,e) is */ + +/* encoded separately for better compression. */ + +static int rgbe_write_bytes_rle(struct img_io *io, unsigned char *data, int numbytes) +{ +#define MINRUNLENGTH 4 + int cur, beg_run, run_count, old_run_count, nonrun_count; + unsigned char buf[2]; + + cur = 0; + while(cur < numbytes) { + beg_run = cur; + /* find next run of length at least 4 if one exists */ + run_count = old_run_count = 0; + while((run_count < MINRUNLENGTH) && (beg_run < numbytes)) { + beg_run += run_count; + old_run_count = run_count; + run_count = 1; + while((beg_run + run_count < numbytes) && (run_count < 127) + && (data[beg_run] == data[beg_run + run_count])) + run_count++; + } + /* if data before next big run is a short run then write it as such */ + if((old_run_count > 1) && (old_run_count == beg_run - cur)) { + buf[0] = 128 + old_run_count; /*write short run */ + buf[1] = data[cur]; + if(fwrite(buf, sizeof(buf[0]) * 2, 1, fp) < 1) + return rgbe_error(rgbe_write_error, NULL); + cur = beg_run; + } + /* write out bytes until we reach the start of the next run */ + while(cur < beg_run) { + nonrun_count = beg_run - cur; + if(nonrun_count > 128) + nonrun_count = 128; + buf[0] = nonrun_count; + if(fwrite(buf, sizeof(buf[0]), 1, fp) < 1) + return rgbe_error(rgbe_write_error, NULL); + if(fwrite(&data[cur], sizeof(data[0]) * nonrun_count, 1, fp) < 1) + return rgbe_error(rgbe_write_error, NULL); + cur += nonrun_count; + } + /* write out next run if one was found */ + if(run_count >= MINRUNLENGTH) { + buf[0] = 128 + run_count; + buf[1] = data[beg_run]; + if(fwrite(buf, sizeof(buf[0]) * 2, 1, fp) < 1) + return rgbe_error(rgbe_write_error, NULL); + cur += run_count; + } + } + return RGBE_RETURN_SUCCESS; +#undef MINRUNLENGTH +} + +static int rgbe_write_pixels_rle(struct img_io *io, float *data, int scanline_width, int num_scanlines) +{ + unsigned char rgbe[4]; + unsigned char *buffer; + int i, err; + + if((scanline_width < 8) || (scanline_width > 0x7fff)) + /* run length encoding is not allowed so write flat */ + return rgbe_write_pixels(io, data, scanline_width * num_scanlines); + buffer = (unsigned char *)malloc(sizeof(unsigned char) * 4 * scanline_width); + if(buffer == NULL) + /* no buffer space so write flat */ + return rgbe_write_pixels(fp, data, scanline_width * num_scanlines); + while(num_scanlines-- > 0) { + rgbe[0] = 2; + rgbe[1] = 2; + rgbe[2] = scanline_width >> 8; + rgbe[3] = scanline_width & 0xFF; + if(fwrite(rgbe, sizeof(rgbe), 1, fp) < 1) { + free(buffer); + return rgbe_error(rgbe_write_error, NULL); + } + for(i = 0; i < scanline_width; i++) { + float2rgbe(rgbe, data[RGBE_DATA_RED], data[RGBE_DATA_GREEN], data[RGBE_DATA_BLUE]); + buffer[i] = rgbe[0]; + buffer[i + scanline_width] = rgbe[1]; + buffer[i + 2 * scanline_width] = rgbe[2]; + buffer[i + 3 * scanline_width] = rgbe[3]; + data += RGBE_DATA_SIZE; + } + /* write out each of the four channels separately run length encoded */ + /* first red, then green, then blue, then exponent */ + for(i = 0; i < 4; i++) { + if((err = rgbe_write_bytes_rle(fp, &buffer[i * scanline_width], + scanline_width)) != RGBE_RETURN_SUCCESS) { + free(buffer); + return err; + } + } + } + free(buffer); + return RGBE_RETURN_SUCCESS; +} +#endif + +static int rgbe_read_pixels_rle(struct img_io *io, float *data, int scanline_width, int num_scanlines) +{ + unsigned char rgbe[4], *scanline_buffer, *ptr, *ptr_end; + int i, count; + unsigned char buf[2]; + + if((scanline_width < 8) || (scanline_width > 0x7fff)) + /* run length encoding is not allowed so read flat */ + return rgbe_read_pixels(io, data, scanline_width * num_scanlines); + scanline_buffer = NULL; + /* read in each successive scanline */ + while(num_scanlines > 0) { + if(io->read(rgbe, sizeof(rgbe), io->uptr) < 1) { + free(scanline_buffer); + return rgbe_error(rgbe_read_error, NULL); + } + if((rgbe[0] != 2) || (rgbe[1] != 2) || (rgbe[2] & 0x80)) { + /* this file is not run length encoded */ + rgbe2float(&data[0], &data[1], &data[2], rgbe); + data += RGBE_DATA_SIZE; + free(scanline_buffer); + return rgbe_read_pixels(io, data, scanline_width * num_scanlines - 1); + } + if((((int)rgbe[2]) << 8 | rgbe[3]) != scanline_width) { + free(scanline_buffer); + return rgbe_error(rgbe_format_error, "wrong scanline width"); + } + if(scanline_buffer == NULL) + scanline_buffer = (unsigned char *) + malloc(sizeof(unsigned char) * 4 * scanline_width); + if(scanline_buffer == NULL) + return rgbe_error(rgbe_memory_error, "unable to allocate buffer space"); + + ptr = &scanline_buffer[0]; + /* read each of the four channels for the scanline into the buffer */ + for(i = 0; i < 4; i++) { + ptr_end = &scanline_buffer[(i + 1) * scanline_width]; + while(ptr < ptr_end) { + if(io->read(buf, sizeof(buf[0]) * 2, io->uptr) < 1) { + free(scanline_buffer); + return rgbe_error(rgbe_read_error, NULL); + } + if(buf[0] > 128) { + /* a run of the same value */ + count = buf[0] - 128; + if((count == 0) || (count > ptr_end - ptr)) { + free(scanline_buffer); + return rgbe_error(rgbe_format_error, "bad scanline data"); + } + while(count-- > 0) + *ptr++ = buf[1]; + } else { + /* a non-run */ + count = buf[0]; + if((count == 0) || (count > ptr_end - ptr)) { + free(scanline_buffer); + return rgbe_error(rgbe_format_error, "bad scanline data"); + } + *ptr++ = buf[1]; + if(--count > 0) { + if(io->read(ptr, sizeof(*ptr) * count, io->uptr) < 1) { + free(scanline_buffer); + return rgbe_error(rgbe_read_error, NULL); + } + ptr += count; + } + } + } + } + /* now convert data from buffer into floats */ + for(i = 0; i < scanline_width; i++) { + rgbe[0] = scanline_buffer[i]; + rgbe[1] = scanline_buffer[i + scanline_width]; + rgbe[2] = scanline_buffer[i + 2 * scanline_width]; + rgbe[3] = scanline_buffer[i + 3 * scanline_width]; + rgbe2float(&data[RGBE_DATA_RED], &data[RGBE_DATA_GREEN], &data[RGBE_DATA_BLUE], rgbe); + data += RGBE_DATA_SIZE; + } + num_scanlines--; + } + free(scanline_buffer); + return RGBE_RETURN_SUCCESS; +} diff --git a/libs/libimago/src/ftype_module.c b/libs/libimago/src/ftype_module.c new file mode 100644 index 0000000..a3d3b04 --- /dev/null +++ b/libs/libimago/src/ftype_module.c @@ -0,0 +1,118 @@ +/* +libimago - a multi-format image file input/output library. +Copyright (C) 2010 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see . +*/ + +#include +#include +#include "ftype_module.h" + +static struct list_node { + struct ftype_module *module; + struct list_node *next; +} *modules; + +/* defined in modules.c which is generated by configure */ +void img_modules_init(); + +static int done_init; + +int img_register_module(struct ftype_module *mod) +{ + struct list_node *node; + + if(!(node = malloc(sizeof *node))) { + return -1; + } + + node->module = mod; + node->next = modules; + modules = node; + return 0; +} + +struct ftype_module *img_find_format_module(struct img_io *io) +{ + struct list_node *node; + + if(!done_init) { + img_modules_init(); + done_init = 1; + } + + node = modules; + while(node) { + if(node->module->check(io) != -1) { + return node->module; + } + node = node->next; + } + return 0; +} + +struct ftype_module *img_guess_format(const char *fname) +{ + struct list_node *node; + char *suffix; + int suffix_len; + + if(!done_init) { + img_modules_init(); + done_init = 1; + } + + if(!(suffix = strrchr(fname, '.'))) { + return 0; /* no suffix, can't guess ... */ + } + suffix_len = (int)strlen(suffix); + + node = modules; + while(node) { + char *suflist = node->module->suffix; + char *start, *end; + + while(*suflist) { + if(!(start = strstr(suflist, suffix))) { + break; + } + end = start + suffix_len; + + if(*end == ':' || *end == 0) { + return node->module; /* found it */ + } + suflist = end; + } + + node = node->next; + } + return 0; +} + +struct ftype_module *img_get_module(int idx) +{ + struct list_node *node; + + if(!done_init) { + img_modules_init(); + done_init = 1; + } + + node = modules; + while(node && idx--) { + node = node->next; + } + return node->module; +} diff --git a/libs/libimago/src/ftype_module.h b/libs/libimago/src/ftype_module.h new file mode 100644 index 0000000..7c3bd54 --- /dev/null +++ b/libs/libimago/src/ftype_module.h @@ -0,0 +1,39 @@ +/* +libimago - a multi-format image file input/output library. +Copyright (C) 2010 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see . +*/ + +#ifndef FTYPE_MODULE_H_ +#define FTYPE_MODULE_H_ + +#include "imago2.h" + +struct ftype_module { + char *suffix; /* used for format autodetection during saving only */ + + int (*check)(struct img_io *io); + int (*read)(struct img_pixmap *img, struct img_io *io); + int (*write)(struct img_pixmap *img, struct img_io *io); +}; + +int img_register_module(struct ftype_module *mod); + +struct ftype_module *img_find_format_module(struct img_io *io); +struct ftype_module *img_guess_format(const char *fname); +struct ftype_module *img_get_module(int idx); + + +#endif /* FTYPE_MODULE_H_ */ diff --git a/libs/libimago/src/imago2.c b/libs/libimago/src/imago2.c new file mode 100644 index 0000000..b910693 --- /dev/null +++ b/libs/libimago/src/imago2.c @@ -0,0 +1,449 @@ +/* +libimago - a multi-format image file input/output library. +Copyright (C) 2010 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see . +*/ + +#include +#include +#include +#include "imago2.h" +#include "ftype_module.h" + +static int pixel_size(enum img_fmt fmt); +static size_t def_read(void *buf, size_t bytes, void *uptr); +static size_t def_write(void *buf, size_t bytes, void *uptr); +static long def_seek(long offset, int whence, void *uptr); + + +void img_init(struct img_pixmap *img) +{ + img->pixels = 0; + img->width = img->height = 0; + img->fmt = IMG_FMT_RGBA32; + img->pixelsz = pixel_size(img->fmt); + img->name = 0; +} + + +void img_destroy(struct img_pixmap *img) +{ + free(img->pixels); + img->pixels = 0; /* just in case... */ + img->width = img->height = 0xbadbeef; + free(img->name); +} + +struct img_pixmap *img_create(void) +{ + struct img_pixmap *p; + + if(!(p = malloc(sizeof *p))) { + return 0; + } + img_init(p); + return p; +} + +void img_free(struct img_pixmap *img) +{ + img_destroy(img); + free(img); +} + +int img_set_name(struct img_pixmap *img, const char *name) +{ + char *tmp; + + if(!(tmp = malloc(strlen(name) + 1))) { + return -1; + } + strcpy(tmp, name); + img->name = tmp; + return 0; +} + +int img_set_format(struct img_pixmap *img, enum img_fmt fmt) +{ + if(img->pixels) { + return img_convert(img, fmt); + } + img->fmt = fmt; + return 0; +} + +int img_copy(struct img_pixmap *dest, struct img_pixmap *src) +{ + return img_set_pixels(dest, src->width, src->height, src->fmt, src->pixels); +} + +int img_set_pixels(struct img_pixmap *img, int w, int h, enum img_fmt fmt, void *pix) +{ + void *newpix; + int pixsz = pixel_size(fmt); + + if(!(newpix = malloc(w * h * pixsz))) { + return -1; + } + + if(pix) { + memcpy(newpix, pix, w * h * pixsz); + } else { + memset(newpix, 0, w * h * pixsz); + } + + free(img->pixels); + img->pixels = newpix; + img->width = w; + img->height = h; + img->pixelsz = pixsz; + img->fmt = fmt; + return 0; +} + +void *img_load_pixels(const char *fname, int *xsz, int *ysz, enum img_fmt fmt) +{ + struct img_pixmap img; + + img_init(&img); + + if(img_load(&img, fname) == -1) { + return 0; + } + if(img.fmt != fmt) { + if(img_convert(&img, fmt) == -1) { + img_destroy(&img); + return 0; + } + } + + *xsz = img.width; + *ysz = img.height; + return img.pixels; +} + +int img_save_pixels(const char *fname, void *pix, int xsz, int ysz, enum img_fmt fmt) +{ + struct img_pixmap img; + + img_init(&img); + img.fmt = fmt; + img.name = (char*)fname; + img.width = xsz; + img.height = ysz; + img.pixels = pix; + + return img_save(&img, fname); +} + +void img_free_pixels(void *pix) +{ + free(pix); +} + +int img_load(struct img_pixmap *img, const char *fname) +{ + int res; + FILE *fp; + + if(!(fp = fopen(fname, "rb"))) { + return -1; + } + res = img_read_file(img, fp); + fclose(fp); + return res; +} + +/* TODO implement filetype selection */ +int img_save(struct img_pixmap *img, const char *fname) +{ + int res; + FILE *fp; + + img_set_name(img, fname); + + if(!(fp = fopen(fname, "wb"))) { + return -1; + } + res = img_write_file(img, fp); + fclose(fp); + return res; +} + +int img_read_file(struct img_pixmap *img, FILE *fp) +{ + struct img_io io = {0, def_read, def_write, def_seek}; + + io.uptr = fp; + return img_read(img, &io); +} + +int img_write_file(struct img_pixmap *img, FILE *fp) +{ + struct img_io io = {0, def_read, def_write, def_seek}; + + io.uptr = fp; + return img_write(img, &io); +} + +int img_read(struct img_pixmap *img, struct img_io *io) +{ + struct ftype_module *mod; + + if((mod = img_find_format_module(io))) { + return mod->read(img, io); + } + return -1; +} + +int img_write(struct img_pixmap *img, struct img_io *io) +{ + struct ftype_module *mod; + + if(!img->name || !(mod = img_guess_format(img->name))) { + /* TODO throw some sort of warning? */ + /* TODO implement some sort of module priority or let the user specify? */ + if(!(mod = img_get_module(0))) { + return -1; + } + } + + return mod->write(img, io); +} + +int img_to_float(struct img_pixmap *img) +{ + enum img_fmt targ_fmt; + + switch(img->fmt) { + case IMG_FMT_GREY8: + targ_fmt = IMG_FMT_GREYF; + break; + + case IMG_FMT_RGB24: + targ_fmt = IMG_FMT_RGBF; + break; + + case IMG_FMT_RGBA32: + targ_fmt = IMG_FMT_RGBAF; + break; + + default: + return 0; /* already float */ + } + + return img_convert(img, targ_fmt); +} + +int img_to_integer(struct img_pixmap *img) +{ + enum img_fmt targ_fmt; + + switch(img->fmt) { + case IMG_FMT_GREYF: + targ_fmt = IMG_FMT_GREY8; + break; + + case IMG_FMT_RGBF: + targ_fmt = IMG_FMT_RGB24; + break; + + case IMG_FMT_RGBAF: + targ_fmt = IMG_FMT_RGBA32; + break; + + default: + return 0; /* already integer */ + } + + return img_convert(img, targ_fmt); +} + +int img_is_float(struct img_pixmap *img) +{ + return img->fmt >= IMG_FMT_GREYF && img->fmt <= IMG_FMT_RGBAF; +} + +int img_has_alpha(struct img_pixmap *img) +{ + if(img->fmt == IMG_FMT_RGBA32 || img->fmt == IMG_FMT_RGBAF) { + return 1; + } + return 0; +} + + +void img_setpixel(struct img_pixmap *img, int x, int y, void *pixel) +{ + char *dest = (char*)img->pixels + (y * img->width + x) * img->pixelsz; + memcpy(dest, pixel, img->pixelsz); +} + +void img_getpixel(struct img_pixmap *img, int x, int y, void *pixel) +{ + char *dest = (char*)img->pixels + (y * img->width + x) * img->pixelsz; + memcpy(pixel, dest, img->pixelsz); +} + +void img_setpixel1i(struct img_pixmap *img, int x, int y, int pix) +{ + img_setpixel4i(img, x, y, pix, pix, pix, pix); +} + +void img_setpixel1f(struct img_pixmap *img, int x, int y, float pix) +{ + img_setpixel4f(img, x, y, pix, pix, pix, pix); +} + +void img_setpixel4i(struct img_pixmap *img, int x, int y, int r, int g, int b, int a) +{ + if(img_is_float(img)) { + img_setpixel4f(img, x, y, r / 255.0, g / 255.0, b / 255.0, a / 255.0); + } else { + unsigned char pixel[4]; + pixel[0] = r; + pixel[1] = g; + pixel[2] = b; + pixel[3] = a; + + img_setpixel(img, x, y, pixel); + } +} + +void img_setpixel4f(struct img_pixmap *img, int x, int y, float r, float g, float b, float a) +{ + if(img_is_float(img)) { + float pixel[4]; + pixel[0] = r; + pixel[1] = g; + pixel[2] = b; + pixel[3] = a; + + img_setpixel(img, x, y, pixel); + } else { + img_setpixel4i(img, x, y, (int)(r * 255.0), (int)(g * 255.0), (int)(b * 255.0), (int)(a * 255.0)); + } +} + +void img_getpixel1i(struct img_pixmap *img, int x, int y, int *pix) +{ + int junk[3]; + img_getpixel4i(img, x, y, pix, junk, junk + 1, junk + 2); +} + +void img_getpixel1f(struct img_pixmap *img, int x, int y, float *pix) +{ + float junk[3]; + img_getpixel4f(img, x, y, pix, junk, junk + 1, junk + 2); +} + +void img_getpixel4i(struct img_pixmap *img, int x, int y, int *r, int *g, int *b, int *a) +{ + if(img_is_float(img)) { + float pixel[4] = {0, 0, 0, 0}; + img_getpixel(img, x, y, pixel); + *r = pixel[0] * 255.0; + *g = pixel[1] * 255.0; + *b = pixel[2] * 255.0; + *a = pixel[3] * 255.0; + } else { + unsigned char pixel[4]; + img_getpixel(img, x, y, pixel); + *r = pixel[0]; + *g = pixel[1]; + *b = pixel[2]; + *a = pixel[3]; + } +} + +void img_getpixel4f(struct img_pixmap *img, int x, int y, float *r, float *g, float *b, float *a) +{ + if(img_is_float(img)) { + float pixel[4] = {0, 0, 0, 0}; + img_getpixel(img, x, y, pixel); + *r = pixel[0]; + *g = pixel[1]; + *b = pixel[2]; + *a = pixel[3]; + } else { + unsigned char pixel[4]; + img_getpixel(img, x, y, pixel); + *r = pixel[0] / 255.0; + *g = pixel[1] / 255.0; + *b = pixel[2] / 255.0; + *a = pixel[3] / 255.0; + } +} + +void img_io_set_user_data(struct img_io *io, void *uptr) +{ + io->uptr = uptr; +} + +void img_io_set_read_func(struct img_io *io, size_t (*read)(void*, size_t, void*)) +{ + io->read = read; +} + +void img_io_set_write_func(struct img_io *io, size_t (*write)(void*, size_t, void*)) +{ + io->write = write; +} + +void img_io_set_seek_func(struct img_io *io, long (*seek)(long, int, void*)) +{ + io->seek = seek; +} + + +static int pixel_size(enum img_fmt fmt) +{ + switch(fmt) { + case IMG_FMT_GREY8: + return 1; + case IMG_FMT_RGB24: + return 3; + case IMG_FMT_RGBA32: + return 4; + case IMG_FMT_GREYF: + return sizeof(float); + case IMG_FMT_RGBF: + return 3 * sizeof(float); + case IMG_FMT_RGBAF: + return 4 * sizeof(float); + default: + break; + } + return 0; +} + +static size_t def_read(void *buf, size_t bytes, void *uptr) +{ + return uptr ? fread(buf, 1, bytes, uptr) : 0; +} + +static size_t def_write(void *buf, size_t bytes, void *uptr) +{ + return uptr ? fwrite(buf, 1, bytes, uptr) : 0; +} + +static long def_seek(long offset, int whence, void *uptr) +{ + if(!uptr || fseek(uptr, offset, whence) == -1) { + return -1; + } + return ftell(uptr); +} + diff --git a/libs/libimago/src/imago2.h b/libs/libimago/src/imago2.h new file mode 100644 index 0000000..b0bea09 --- /dev/null +++ b/libs/libimago/src/imago2.h @@ -0,0 +1,222 @@ +/* +libimago - a multi-format image file input/output library. +Copyright (C) 2010-2012 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see . +*/ + +#ifndef IMAGO2_H_ +#define IMAGO2_H_ + +#include + +#ifdef __cplusplus +#define IMG_OPTARG(arg, val) arg = val +#else +#define IMG_OPTARG(arg, val) arg +#endif + +/* XXX if you change this make sure to also change pack/unpack arrays in conv.c */ +enum img_fmt { + IMG_FMT_GREY8, + IMG_FMT_RGB24, + IMG_FMT_RGBA32, + IMG_FMT_GREYF, + IMG_FMT_RGBF, + IMG_FMT_RGBAF, + + NUM_IMG_FMT +}; + +struct img_pixmap { + void *pixels; + int width, height; + enum img_fmt fmt; + int pixelsz; + char *name; +}; + +struct img_io { + void *uptr; /* user-data */ + + size_t (*read)(void *buf, size_t bytes, void *uptr); + size_t (*write)(void *buf, size_t bytes, void *uptr); + long (*seek)(long offs, int whence, void *uptr); +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/* initialize the img_pixmap structure */ +void img_init(struct img_pixmap *img); +/* destroys the img_pixmap structure, freeing the pixel buffer (if available) + * and any other memory held by the pixmap. + */ +void img_destroy(struct img_pixmap *img); + +/* convenience function that allocates an img_pixmap struct and then initializes it. + * returns null if the malloc fails. + */ +struct img_pixmap *img_create(void); +/* frees a pixmap previously allocated with img_create (free followed by img_destroy) */ +void img_free(struct img_pixmap *img); + +int img_set_name(struct img_pixmap *img, const char *name); + +/* set the image pixel format */ +int img_set_format(struct img_pixmap *img, enum img_fmt fmt); + +/* copies one pixmap to another. + * equivalent to: img_set_pixels(dest, src->width, src->height, src->fmt, src->pixels) + */ +int img_copy(struct img_pixmap *dest, struct img_pixmap *src); + +/* allocates a pixel buffer of the specified dimensions and format, and copies the + * pixels given through the pix pointer into it. + * the pix pointer can be null, in which case there's no copy, just allocation. + * + * C++: fmt and pix have default parameters IMG_FMT_RGBA32 and null respectively. + */ +int img_set_pixels(struct img_pixmap *img, int w, int h, IMG_OPTARG(enum img_fmt fmt, IMG_FMT_RGBA32), IMG_OPTARG(void *pix, 0)); + +/* Simplified image loading + * Loads the specified file, and returns a pointer to an array of pixels of the + * requested pixel format. The width and height of the image are returned through + * the xsz and ysz pointers. + * If the image cannot be loaded, the function returns null. + * + * C++: the format argument is optional and defaults to IMG_FMT_RGBA32 + */ +void *img_load_pixels(const char *fname, int *xsz, int *ysz, IMG_OPTARG(enum img_fmt fmt, IMG_FMT_RGBA32)); + +/* Simplified image saving + * Reads an array of pixels supplied through the pix pointer, of dimensions xsz + * and ysz, and pixel-format fmt, and saves it to a file. + * The output filetype is guessed by the filename suffix. + * + * C++: the format argument is optional and defaults to IMG_FMT_RGBA32 + */ +int img_save_pixels(const char *fname, void *pix, int xsz, int ysz, IMG_OPTARG(enum img_fmt fmt, IMG_FMT_RGBA32)); + +/* Frees the memory allocated by img_load_pixels */ +void img_free_pixels(void *pix); + +/* Loads an image file into the supplied pixmap */ +int img_load(struct img_pixmap *img, const char *fname); +/* Saves the supplied pixmap to a file. The output filetype is guessed by the filename suffix */ +int img_save(struct img_pixmap *img, const char *fname); + +/* Reads an image from an open FILE* into the supplied pixmap */ +int img_read_file(struct img_pixmap *img, FILE *fp); +/* Writes the supplied pixmap to an open FILE* */ +int img_write_file(struct img_pixmap *img, FILE *fp); + +/* Reads an image using user-defined file-i/o functions (see img_io_set_*) */ +int img_read(struct img_pixmap *img, struct img_io *io); +/* Writes an image using user-defined file-i/o functions (see img_io_set_*) */ +int img_write(struct img_pixmap *img, struct img_io *io); + +/* Converts an image to the specified pixel format */ +int img_convert(struct img_pixmap *img, enum img_fmt tofmt); + +/* Converts an image from an integer pixel format to the corresponding floating point one */ +int img_to_float(struct img_pixmap *img); +/* Converts an image from a floating point pixel format to the corresponding integer one */ +int img_to_integer(struct img_pixmap *img); + +/* Returns non-zero (true) if the supplied image is in a floating point pixel format */ +int img_is_float(struct img_pixmap *img); +/* Returns non-zero (true) if the supplied image has an alpha channel */ +int img_has_alpha(struct img_pixmap *img); + + +/* don't use these for anything performance-critical */ +void img_setpixel(struct img_pixmap *img, int x, int y, void *pixel); +void img_getpixel(struct img_pixmap *img, int x, int y, void *pixel); + +void img_setpixel1i(struct img_pixmap *img, int x, int y, int pix); +void img_setpixel1f(struct img_pixmap *img, int x, int y, float pix); +void img_setpixel4i(struct img_pixmap *img, int x, int y, int r, int g, int b, int a); +void img_setpixel4f(struct img_pixmap *img, int x, int y, float r, float g, float b, float a); + +void img_getpixel1i(struct img_pixmap *img, int x, int y, int *pix); +void img_getpixel1f(struct img_pixmap *img, int x, int y, float *pix); +void img_getpixel4i(struct img_pixmap *img, int x, int y, int *r, int *g, int *b, int *a); +void img_getpixel4f(struct img_pixmap *img, int x, int y, float *r, float *g, float *b, float *a); + + +/* OpenGL helper functions */ + +/* Returns the equivalent OpenGL "format" as expected by the 7th argument of glTexImage2D */ +unsigned int img_fmt_glfmt(enum img_fmt fmt); +/* Returns the equivalent OpenGL "type" as expected by the 8th argument of glTexImage2D */ +unsigned int img_fmt_gltype(enum img_fmt fmt); +/* Returns the equivalent OpenGL "internal format" as expected by the 3rd argument of glTexImage2D */ +unsigned int img_fmt_glintfmt(enum img_fmt fmt); + +/* Same as above, based on the pixel format of the supplied image */ +unsigned int img_glfmt(struct img_pixmap *img); +unsigned int img_gltype(struct img_pixmap *img); +unsigned int img_glintfmt(struct img_pixmap *img); + +/* Creates an OpenGL texture from the image, and returns the texture id, or 0 for failure */ +unsigned int img_gltexture(struct img_pixmap *img); + +/* Load an image and create an OpenGL texture out of it */ +unsigned int img_gltexture_load(const char *fname); +unsigned int img_gltexture_read_file(FILE *fp); +unsigned int img_gltexture_read(struct img_io *io); + +/* These functions can be used to fill an img_io struct before it's passed to + * one of the user-defined i/o image reading/writing functions (img_read/img_write). + * + * User-defined i/o functions: + * + * - size_t read_func(void *buffer, size_t bytes, void *user_ptr) + * Must try to fill the buffer with the specified number of bytes, and return + * the number of bytes actually read. + * + * - size_t write_func(void *buffer, size_t bytes, void *user_ptr) + * Must write the specified number of bytes from the supplied buffer and return + * the number of bytes actually written. + * + * - long seek_func(long offset, int whence, void *user_ptr) + * Must seek offset bytes from: the beginning of the file if whence is SEEK_SET, + * the current position if whence is SEEK_CUR, or the end of the file if whence is + * SEEK_END, and return the resulting file offset from the beginning of the file. + * (i.e. seek_func(0, SEEK_CUR, user_ptr); must be equivalent to an ftell). + * + * All three functions get the user-data pointer set through img_io_set_user_data + * as their last argument. + * + * Note: obviously you don't need to set a write function if you're only going + * to call img_read, or the read and seek function if you're only going to call + * img_write. + * + * Note: if the user-supplied write function is buffered, make sure to flush + * (or close the file) after img_write returns. + */ +void img_io_set_user_data(struct img_io *io, void *uptr); +void img_io_set_read_func(struct img_io *io, size_t (*read)(void*, size_t, void*)); +void img_io_set_write_func(struct img_io *io, size_t (*write)(void*, size_t, void*)); +void img_io_set_seek_func(struct img_io *io, long (*seek)(long, int, void*)); + + +#ifdef __cplusplus +} +#endif + + +#endif /* IMAGO_H_ */ diff --git a/libs/libimago/src/imago_gl.c b/libs/libimago/src/imago_gl.c new file mode 100644 index 0000000..32c540e --- /dev/null +++ b/libs/libimago/src/imago_gl.c @@ -0,0 +1,223 @@ +#include "imago2.h" + + +/* to avoid dependency to OpenGL, I'll define all the relevant GL macros manually */ +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_FLOAT 0x1406 + +#define GL_LUMINANCE 0x1909 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 + +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_LUMINANCE32F 0x8818 + +#define GL_TEXTURE_2D 0x0de1 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_LINEAR 0x2601 +#define GL_REPEAT 0x2901 + + +typedef unsigned int GLenum; +typedef unsigned int GLuint; +typedef int GLint; +typedef int GLsizei; +typedef void GLvoid; + +/* for the same reason I'll load GL functions dynamically */ +typedef void (*gl_gen_textures_func)(GLsizei, GLuint*); +typedef void (*gl_bind_texture_func)(GLenum, GLuint); +typedef void (*gl_tex_parameteri_func)(GLenum, GLenum, GLint); +typedef void (*gl_tex_image2d_func)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*); + +static gl_gen_textures_func gl_gen_textures; +static gl_bind_texture_func gl_bind_texture; +static gl_tex_parameteri_func gl_tex_parameteri; +static gl_tex_image2d_func gl_tex_image2d; + +static int load_glfunc(void); + +unsigned int img_fmt_glfmt(enum img_fmt fmt) +{ + switch(fmt) { + case IMG_FMT_GREY8: + case IMG_FMT_GREYF: + return GL_LUMINANCE; + + case IMG_FMT_RGB24: + case IMG_FMT_RGBF: + return GL_RGB; + + case IMG_FMT_RGBA32: + case IMG_FMT_RGBAF: + return GL_RGBA; + + default: + break; + } + return 0; +} + +unsigned int img_fmt_gltype(enum img_fmt fmt) +{ + switch(fmt) { + case IMG_FMT_GREY8: + case IMG_FMT_RGB24: + case IMG_FMT_RGBA32: + return GL_UNSIGNED_BYTE; + + case IMG_FMT_GREYF: + case IMG_FMT_RGBF: + case IMG_FMT_RGBAF: + return GL_FLOAT; + + default: + break; + } + return 0; +} + +unsigned int img_fmt_glintfmt(enum img_fmt fmt) +{ + switch(fmt) { + case IMG_FMT_GREY8: + return GL_LUMINANCE; + case IMG_FMT_RGB24: + return GL_RGB; + case IMG_FMT_RGBA32: + return GL_RGBA; + case IMG_FMT_GREYF: + return GL_LUMINANCE32F; + case IMG_FMT_RGBF: + return GL_RGB32F; + case IMG_FMT_RGBAF: + return GL_RGBA32F; + default: + break; + } + return 0; +} + +unsigned int img_glfmt(struct img_pixmap *img) +{ + return img_fmt_glfmt(img->fmt); +} + +unsigned int img_gltype(struct img_pixmap *img) +{ + return img_fmt_gltype(img->fmt); +} + +unsigned int img_glintfmt(struct img_pixmap *img) +{ + return img_fmt_glintfmt(img->fmt); +} + +unsigned int img_gltexture(struct img_pixmap *img) +{ + unsigned int tex; + unsigned int intfmt, fmt, type; + + if(!gl_gen_textures) { + if(load_glfunc() == -1) { + fprintf(stderr, "imago: failed to initialize the OpenGL helpers\n"); + return 0; + } + } + + intfmt = img_glintfmt(img); + fmt = img_glfmt(img); + type = img_gltype(img); + + gl_gen_textures(1, &tex); + gl_bind_texture(GL_TEXTURE_2D, tex); + gl_tex_parameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gl_tex_parameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl_tex_parameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + gl_tex_parameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + gl_tex_image2d(GL_TEXTURE_2D, 0, intfmt, img->width, img->height, 0, fmt, type, img->pixels); + return tex; +} + +unsigned int img_gltexture_load(const char *fname) +{ + struct img_pixmap img; + unsigned int tex; + + img_init(&img); + if(img_load(&img, fname) == -1) { + img_destroy(&img); + return 0; + } + + tex = img_gltexture(&img); + img_destroy(&img); + return tex; +} + +unsigned int img_gltexture_read_file(FILE *fp) +{ + struct img_pixmap img; + unsigned int tex; + + img_init(&img); + if(img_read_file(&img, fp) == -1) { + img_destroy(&img); + return 0; + } + + tex = img_gltexture(&img); + img_destroy(&img); + return tex; +} + +unsigned int img_gltexture_read(struct img_io *io) +{ + struct img_pixmap img; + unsigned int tex; + + img_init(&img); + if(img_read(&img, io) == -1) { + img_destroy(&img); + return 0; + } + + tex = img_gltexture(&img); + img_destroy(&img); + return tex; +} + +#if defined(__unix__) || defined(__APPLE__) +#ifndef __USE_GNU +#define __USE_GNU +#endif + +#include +#endif +#ifdef WIN32 +#include +#endif + +static int load_glfunc(void) +{ +#if defined(__unix__) || defined(__APPLE__) + gl_gen_textures = (gl_gen_textures_func)dlsym(RTLD_DEFAULT, "glGenTextures"); + gl_bind_texture = (gl_bind_texture_func)dlsym(RTLD_DEFAULT, "glBindTexture"); + gl_tex_parameteri = (gl_tex_parameteri_func)dlsym(RTLD_DEFAULT, "glTexParameteri"); + gl_tex_image2d = (gl_tex_image2d_func)dlsym(RTLD_DEFAULT, "glTexImage2D"); +#endif + +#ifdef WIN32 + HMODULE handle = GetModuleHandle(0); + gl_gen_textures = (gl_gen_textures_func)GetProcAddress(handle, "glGenTextures"); + gl_bind_texture = (gl_bind_texture_func)GetProcAddress(handle, "glBindTexture"); + gl_tex_parameteri = (gl_tex_parameteri_func)GetProcAddress(handle, "glTexParameteri"); + gl_tex_image2d = (gl_tex_image2d_func)GetProcAddress(handle, "glTexImage2D"); +#endif + + return (gl_gen_textures && gl_bind_texture && gl_tex_parameteri && gl_tex_image2d) ? 0 : -1; +} diff --git a/libs/libimago/test/Makefile b/libs/libimago/test/Makefile new file mode 100644 index 0000000..901c7a7 --- /dev/null +++ b/libs/libimago/test/Makefile @@ -0,0 +1,19 @@ +obj = test.o +bin = test + +CC = gcc +CFLAGS = -pedantic -Wall -g -I../src +LDFLAGS = $(lib) + +ifeq ($(shell uname -s), Darwin) + lib = ../libimago.dylib +else + lib = ../libimago.so.2.0 +endif + +$(bin): $(obj) $(lib) + $(CC) -o $@ $(obj) $(LDFLAGS) + +.PHONY: clean +clean: + rm -f $(obj) $(bin) diff --git a/libs/libimago/test/test.c b/libs/libimago/test/test.c new file mode 100644 index 0000000..4bf2789 --- /dev/null +++ b/libs/libimago/test/test.c @@ -0,0 +1,63 @@ +#include +#include + +int main(int argc, char **argv) +{ + const char *infile = "foo.jpg"; + const char *outfile = "bar.jpg"; + int i, j, xsz = 512, ysz = 512; + struct img_pixmap img; + + for(i=1; i> 5) & 1) == ((j >> 5) & 1); + + *pix++ = bw ? 255 : 0; + *pix++ = 127; + *pix++ = bw ? 0 : 255; + } + } + } + + if(img_save(&img, outfile) == -1) { + fprintf(stderr, "failed to save file %s\n", outfile); + return 1; + } + + img_destroy(&img); + return 0; +} diff --git a/src/bvol.cc b/src/bvol.cc new file mode 100644 index 0000000..d313eec --- /dev/null +++ b/src/bvol.cc @@ -0,0 +1,80 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#include +#include "bvol.h" + +BSphere::BSphere() +{ + radius = 1.0f; +} + +BSphere::BSphere(const Vector3 &c, float rad) + : center(c) +{ + radius = rad; +} + +void BSphere::set_center(const Vector3 ¢er) +{ + this->center = center; +} + +const Vector3 &BSphere::get_center() const +{ + return center; +} + +void BSphere::set_radius(float rad) +{ + radius = rad; +} + +float BSphere::get_radius() const +{ + return radius; +} + +bool BSphere::intersect(const Ray &ray, HitPoint *hit) const +{ + float a = dot(ray.dir, ray.dir); + float b = 2.0 * dot(ray.dir, ray.origin - center); + float c = dot(ray.origin, ray.origin) + dot(center, center) - + 2.0 * dot(ray.origin, center) - radius * radius; + + float disc = b * b - 4.0f * a * c; + if(disc < 1e-6) { + return false; + } + + float sqrt_disc = sqrt(disc); + float x1 = (-b + sqrt_disc) / (2.0f * a); + float x2 = (-b - sqrt_disc) / (2.0f * a); + + if(x1 < 1e-6) x1 = x2; + if(x2 < 1e-6) x2 = x1; + + float t = x1 < x2 ? x1 : x2; + if(t < 1e-6) { + return false; + } + + hit->t = t; + hit->pos = ray.origin + ray.dir * t; + return true; +} diff --git a/src/bvol.h b/src/bvol.h new file mode 100644 index 0000000..fd305d7 --- /dev/null +++ b/src/bvol.h @@ -0,0 +1,54 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#ifndef BVOL_H_ +#define BVOL_H_ + +#include "vmath.h" + +struct HitPoint { + float t; + Vector3 pos; +}; + +class BVolume { +public: + virtual ~BVolume() {} + + virtual bool intersect(const Ray &ray, HitPoint *hit) const = 0; +}; + +class BSphere : public BVolume { +private: + Vector3 center; + float radius; + +public: + BSphere(); + explicit BSphere(const Vector3 &c, float rad = 1.0); + + void set_center(const Vector3 ¢er); + const Vector3 &get_center() const; + + void set_radius(float rad); + float get_radius() const; + + bool intersect(const Ray &ray, HitPoint *hit) const; +}; + +#endif // BVOL_H_ diff --git a/src/dev.cc b/src/dev.cc new file mode 100644 index 0000000..463be30 --- /dev/null +++ b/src/dev.cc @@ -0,0 +1,218 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dev.h" +#include "timer.h" + +void post_redisplay(); // defined in main.cc + +int customer, ticket; +static int report_inputs, cmd_echo; +static long last_ticket_msec = LONG_MIN; + +static void runcmd(const char *cmd); + +static int fd = -1; +static FILE *fp; +static std::string cur_line; + +int start_dev(const char *devpath) +{ + if((fd = open(devpath, O_RDWR | O_NONBLOCK)) == -1) { + fprintf(stderr, "failed to open device: %s: %s\n", devpath, strerror(errno)); + return -1; + } + if(isatty(fd)) { + struct termios term; + + if(tcgetattr(fd, &term) == -1) { + perror("failed to retrieve terminal attributes"); + stop_dev(); + return -1; + } + term.c_cflag = CS8 | CLOCAL; + term.c_iflag &= ~(IXON | IXOFF); + term.c_lflag = 0; + + cfsetispeed(&term, B38400); + cfsetospeed(&term, B38400); + + if(tcsetattr(fd, TCSANOW, &term) == -1) { + perror("failed to set terminal attributes"); + stop_dev(); + return -1; + } + } + + if(!(fp = fdopen(fd, "r+"))) { + perror("failed to attach an I/O stream to the device file\n"); + stop_dev(); + return -1; + } + setvbuf(fp, 0, _IONBF, 0); + + return fd; +} + +void stop_dev() +{ + if(fp) + fclose(fp); + else if(fd >= 0) + close(fd); +} + + +void proc_dev_input() +{ + int rdbytes; + char buf[256]; + static bool skip_line; + + while((rdbytes = read(fd, buf, sizeof buf - 1)) > 0) { + buf[rdbytes] = 0; + + /* ignore our own crap */ + if(memcmp(buf, "OK,", 3) == 0 || memcmp(buf, "ERR,", 4) == 0) { + skip_line = true; + } + + for(int i=0; i, + Eleni-Maria Stea + +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 3 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, see . +*/ +#ifndef DEV_H_ +#define DEV_H_ + +extern int customer, ticket; + +int start_dev(const char *devpath); +void stop_dev(); +void proc_dev_input(); + +void next_customer(); +void issue_ticket(); + +int get_display_number(); +int get_led_state(int led); + +#endif /* DEV_H_ */ diff --git a/src/fblur.cc b/src/fblur.cc new file mode 100644 index 0000000..dcca0d0 --- /dev/null +++ b/src/fblur.cc @@ -0,0 +1,138 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#include +#include +#include "fblur.h" + +#if defined(__i386__) || defined(__ia64__) || defined(WIN32) || \ + (defined(__alpha__) || defined(__alpha)) || \ + defined(__arm__) || \ + (defined(__mips__) && defined(__MIPSEL__)) || \ + defined(__SYMBIAN32__) || \ + defined(__x86_64__) || \ + defined(__LITTLE_ENDIAN__) +#define FBLUR_LITTLE_ENDIAN +#else +#define FBLUR_BIG_ENDIAN +#endif + +/* some color packing/unpacking macros */ +#ifdef FBLUR_BIG_ENDIAN +#define RSHIFT 24 +#define GSHIFT 16 +#define BSHIFT 8 +#else /* little endian */ +#define RSHIFT 0 +#define GSHIFT 8 +#define BSHIFT 16 +#endif + +#define RED(p) (((p) >> RSHIFT) & 0xff) +#define GREEN(p) (((p) >> GSHIFT) & 0xff) +#define BLUE(p) (((p) >> BSHIFT) & 0xff) +#define RGB(r, g, b) \ + ((((r) & 0xff) << RSHIFT) | \ + (((g) & 0xff) << GSHIFT) | \ + (((b) & 0xff) << BSHIFT)) + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + + +void fast_blur(int dir, int amount, uint32_t *buf, int x, int y) +{ + int i, j, half; + uint32_t *dptr, *sptr, *tmp_buf; + + int blur_len = dir == BLUR_HORIZ ? x : y; + int blur_times = dir == BLUR_HORIZ ? y : x; + + if(amount <= 1) return; + + dptr = buf; + half = amount / 2; + + tmp_buf = (uint32_t*)alloca(blur_len * sizeof(uint32_t)); + + for(i=0; i half) { + uint32_t out = *(sptr - half - 1); + ar -= RED(out); + ag -= GREEN(out); + ab -= BLUE(out); + divisor--; + } + + if(j < blur_len - half) { + uint32_t in = *(sptr + half); + ar += RED(in); + ag += GREEN(in); + ab += BLUE(in); + divisor++; + } + + r = ar / divisor; + g = ag / divisor; + b = ab / divisor; + + r = MAX(MIN(r, 255), 0); + g = MAX(MIN(g, 255), 0); + b = MAX(MIN(b, 255), 0); + + *dptr = RGB(r, g, b); + dptr += dir == BLUR_HORIZ ? 1 : x; + sptr++; + } + + } + + if(dir == BLUR_BOTH) { + fast_blur(BLUR_HORIZ, amount, buf, x, y); + } +} diff --git a/src/fblur.h b/src/fblur.h new file mode 100644 index 0000000..405cb06 --- /dev/null +++ b/src/fblur.h @@ -0,0 +1,32 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#ifndef FBLUR_H_ +#define FBLUR_H_ + +#include + +enum { + BLUR_BOTH, /* blur in X and Y */ + BLUR_HORIZ, /* blur in X */ + BLUR_VERT /* blur in Y */ +}; + +void fast_blur(int dir, int amount, uint32_t *buf, int x, int y); + +#endif /* FBLUR_H_ */ diff --git a/src/main.cc b/src/main.cc new file mode 100644 index 0000000..3263c87 --- /dev/null +++ b/src/main.cc @@ -0,0 +1,677 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dev.h" +#include "scene.h" +#include "timer.h" +#include "fblur.h" + + +enum { + REGULAR_PASS, + GLOW_PASS +}; + +void post_redisplay(); +static bool init(); +static void cleanup(); +static void display(); +static void draw_scene(int pass = REGULAR_PASS); +static void post_glow(void); +static void keyb(int key, bool pressed); +static void mouse(int bn, bool pressed, int x, int y); +static void motion(int x, int y); +static Ray calc_pick_ray(int x, int y); +static int next_pow2(int x); + +static Window create_window(const char *title, int xsz, int ysz); +static void process_events(); +static int translate_keysym(KeySym sym); + +static int proc_args(int argc, char **argv); + +static Display *dpy; +static Window win; +static GLXContext ctx; +static Atom xa_wm_prot, xa_wm_del_win; + +static int win_width, win_height; + +static bool draw_pending; +static bool win_mapped; + +static int fakefd = -1; +static char *fake_devpath; + +static float cam_theta, cam_phi, cam_dist = 140; +static Scene *scn; + +enum { BN_TICKET, BN_NEXT, NUM_BUTTONS }; +static const char *button_names[] = { "button1", "button2" }; +static Object *button_obj[NUM_BUTTONS]; +static Object *disp_obj[2]; +static Object *led_obj[2]; +static Vector3 led_on_emissive; + +static bool opt_use_glow = true; +#define GLOW_SZ_DIV 3 +static unsigned int glow_tex; +static int glow_tex_xsz, glow_tex_ysz, glow_xsz, glow_ysz; +static int glow_iter = 1; +static int blur_size = 5; +unsigned char *glow_framebuf; + + +int main(int argc, char **argv) +{ + if(proc_args(argc, argv) == -1) { + return 1; + } + if(!init()) { + return 1; + } + atexit(cleanup); + + int xfd = ConnectionNumber(dpy); + + // run once through pending events before going into the select loop + process_events(); + + for(;;) { + fd_set rd; + FD_ZERO(&rd); + + FD_SET(xfd, &rd); + FD_SET(fakefd, &rd); + + struct timeval noblock = {0, 0}; + int maxfd = xfd > fakefd ? xfd : fakefd; + while(!XPending(dpy) && select(maxfd + 1, &rd, 0, 0, draw_pending ? &noblock : 0) == -1 && errno == EINTR); + + if(XPending(dpy) || FD_ISSET(xfd, &rd)) { + process_events(); + } + if(FD_ISSET(fakefd, &rd)) { + proc_dev_input(); + } + + if(draw_pending) { + draw_pending = false; + display(); + } + } + return 0; +} + +void post_redisplay() +{ + draw_pending = true; +} + +static bool init() +{ + if(fake_devpath) { + if((fakefd = start_dev(fake_devpath)) == -1) { + return false; + } + } + + if(!(dpy = XOpenDisplay(0))) { + fprintf(stderr, "failed to connect to the X server!\n"); + return false; + } + + if(!(win = create_window("equeue device emulator", 512, 512))) { + return false; + } + + glewInit(); + + scn = new Scene; + if(!scn->load("data/device.obj")) { + fprintf(stderr, "failed to load device 3D model\n"); + return false; + } + + for(int i=0; iget_object(button_names[i]); + if(!button_obj[i]) { + fprintf(stderr, "invalid 3D model\n"); + return false; + } + BSphere &bs = button_obj[i]->get_mesh()->get_bounds(); + bs.set_radius(bs.get_radius() * 1.5); + } + + disp_obj[0] = scn->get_object("7seg0"); + disp_obj[1] = scn->get_object("7seg1"); + if(!disp_obj[0] || !disp_obj[1]) { + fprintf(stderr, "invalid 3D model\n"); + return false; + } + scn->remove_object(disp_obj[0]); + scn->remove_object(disp_obj[1]); + + led_obj[0] = scn->get_object("led1"); + led_obj[1] = scn->get_object("led2"); + if(!led_obj[0] || !led_obj[1]) { + fprintf(stderr, "invalid 3D model\n"); + return false; + } + scn->remove_object(led_obj[0]); + scn->remove_object(led_obj[1]); + led_on_emissive = led_obj[0]->mtl.emissive; + + // create the glow texture + glGenTextures(1, &glow_tex); + glBindTexture(GL_TEXTURE_2D, glow_tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + glClearColor(0.1, 0.1, 0.1, 1); + + return true; +} + +static void cleanup() +{ + delete scn; + + stop_dev(); + + if(!dpy) return; + + if(win) { + XDestroyWindow(dpy, win); + } + XCloseDisplay(dpy); +} + +#define DIGIT_USZ (1.0 / 11.0) +#define MIN_REDRAW_INTERVAL (1000 / 40) /* 40fps */ + +static void display() +{ + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0, 0, -cam_dist); + glRotatef(cam_phi, 1, 0, 0); + glRotatef(cam_theta, 0, 1, 0); + + float lpos[] = {-7, 5, 10, 0}; + glLightfv(GL_LIGHT0, GL_POSITION, lpos); + + if(opt_use_glow) { + glViewport(0, 0, glow_xsz, glow_ysz); + + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + draw_scene(GLOW_PASS); + + glReadPixels(0, 0, glow_xsz, glow_ysz, GL_RGBA, GL_UNSIGNED_BYTE, glow_framebuf); + glViewport(0, 0, win_width, win_height); + } + + glClearColor(0.05, 0.05, 0.05, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + draw_scene(); + + if(opt_use_glow) { + for(int i=0; irender(); + } + + // shift the textures and modify the materials to make the display match our state + for(int i=0; i<2; i++) { + // 7seg + int digit = get_display_number(); + for(int j=0; jmtl.tex_offset[TEX_DIFFUSE] = Vector2(uoffs, 0); + disp_obj[i]->render(); + + // LEDs + if(get_led_state(i)) { + led_obj[i]->mtl.emissive = led_on_emissive; + } else { + led_obj[i]->mtl.emissive = Vector3(0, 0, 0); + } + led_obj[i]->render(); + } +} + +static void post_glow(void) +{ + float max_s = (float)glow_xsz / (float)glow_tex_xsz; + float max_t = (float)glow_ysz / (float)glow_tex_ysz; + + glPushAttrib(GL_ENABLE_BIT); + + glBlendFunc(GL_ONE, GL_ONE); + glEnable(GL_BLEND); + glDisable(GL_CULL_FACE); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, glow_tex); + + glBegin(GL_QUADS); + glColor4f(1, 1, 1, 1); + glTexCoord2f(0, 0); + glVertex2f(-1, -1); + glTexCoord2f(max_s, 0); + glVertex2f(1, -1); + glTexCoord2f(max_s, max_t); + glVertex2f(1, 1); + glTexCoord2f(0, max_t); + glVertex2f(-1, 1); + glEnd(); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glPopAttrib(); +} + + +static void reshape(int x, int y) +{ + glViewport(0, 0, x, y); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(50.0, (float)x / (float)y, 1.0, 1000.0); + + win_width = x; + win_height = y; + + if(opt_use_glow) { + glow_xsz = x / GLOW_SZ_DIV; + glow_ysz = y / GLOW_SZ_DIV; + printf("glow image size: %dx%d\n", glow_xsz, glow_ysz); + + delete [] glow_framebuf; + glow_framebuf = new unsigned char[glow_xsz * glow_ysz * 4]; + + glow_tex_xsz = next_pow2(glow_xsz); + glow_tex_ysz = next_pow2(glow_ysz); + glBindTexture(GL_TEXTURE_2D, glow_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glow_tex_xsz, glow_tex_ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + } +} + +static void keyb(int key, bool pressed) +{ + if(pressed) { + switch(key) { + case 27: + exit(0); + } + } +} + +static bool bnstate[32]; +static int prev_x, prev_y; + +static void mouse(int bn, bool pressed, int x, int y) +{ + bnstate[bn] = pressed; + prev_x = x; + prev_y = y; + + if(bn == 0 && pressed) { + // do picking + Ray ray = calc_pick_ray(x, win_height - y); + + HitPoint minhit; + minhit.t = FLT_MAX; + int hit_found = -1; + + for(int i=0; iget_mesh()->get_bounds().intersect(ray, &hit) && hit.t < minhit.t) { + minhit = hit; + hit_found = i; + } + } + + if(hit_found != -1) { + switch(hit_found) { + case BN_TICKET: + issue_ticket(); + break; + + case BN_NEXT: + next_customer(); + break; + } + draw_pending = true; + } + } +} + +static void motion(int x, int y) +{ + int dx = x - prev_x; + int dy = y - prev_y; + prev_x = x; + prev_y = y; + + if(bnstate[0]) { + cam_theta += dx * 0.5; + cam_phi += dy * 0.5; + if(cam_phi < -90) cam_phi = -90; + if(cam_phi > 90) cam_phi = 90; + + } else if(bnstate[2]) { + cam_dist += dy * 0.5; + if(cam_dist < 0.0) cam_dist = 0.0; + + } else { + float xoffs = 2.0 * x / win_width - 1.0; + float yoffs = 2.0 * y / win_height - 1.0; + cam_theta = -xoffs * 15.0 * (win_width / win_height); + cam_phi = -yoffs * 15.0; + } + draw_pending = true; +} + +static Ray calc_pick_ray(int x, int y) +{ + double mv[16], proj[16]; + int vp[4]; + double resx, resy, resz; + Ray ray; + + glGetDoublev(GL_MODELVIEW_MATRIX, mv); + glGetDoublev(GL_PROJECTION_MATRIX, proj); + glGetIntegerv(GL_VIEWPORT, vp); + + gluUnProject(x, y, 0, mv, proj, vp, &resx, &resy, &resz); + ray.origin = Vector3(resx, resy, resz); + + gluUnProject(x, y, 1, mv, proj, vp, &resx, &resy, &resz); + ray.dir = normalize(Vector3(resx, resy, resz) - ray.origin); + + return ray; +} + +static int next_pow2(int x) +{ + x--; + x = (x >> 1) | x; + x = (x >> 2) | x; + x = (x >> 4) | x; + x = (x >> 8) | x; + x = (x >> 16) | x; + return x + 1; +} + +static Window create_window(const char *title, int xsz, int ysz) +{ + int scr = DefaultScreen(dpy); + Window root = RootWindow(dpy, scr); + + int glxattr[] = { + GLX_RGBA, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_DEPTH_SIZE, 24, + GLX_DOUBLEBUFFER, +#if defined(GLX_VERSION_1_4) || defined(GLX_ARB_multisample) + GLX_SAMPLE_BUFFERS_ARB, 1, + GLX_SAMPLES_ARB, 1, +#endif + None + }; + + XVisualInfo *vis = glXChooseVisual(dpy, scr, glxattr); + if(!vis) { + fprintf(stderr, "failed to find a suitable visual\n"); + return 0; + } + + if(!(ctx = glXCreateContext(dpy, vis, 0, True))) { + fprintf(stderr, "failed to create OpenGL context\n"); + XFree(vis); + return -1; + } + + XSetWindowAttributes xattr; + xattr.background_pixel = xattr.border_pixel = BlackPixel(dpy, scr); + xattr.colormap = XCreateColormap(dpy, root, vis->visual, AllocNone); + unsigned int xattr_mask = CWColormap | CWBackPixel | CWBorderPixel; + + Window win = XCreateWindow(dpy, root, 0, 0, xsz, ysz, 0, vis->depth, InputOutput, + vis->visual, xattr_mask, &xattr); + if(!win) { + fprintf(stderr, "failed to create window\n"); + glXDestroyContext(dpy, ctx); + XFree(vis); + return -1; + } + XFree(vis); + + unsigned int evmask = StructureNotifyMask | VisibilityChangeMask | ExposureMask | + KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | + PointerMotionMask | LeaveWindowMask; + XSelectInput(dpy, win, evmask); + + xa_wm_prot = XInternAtom(dpy, "WM_PROTOCOLS", False); + xa_wm_del_win = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + XSetWMProtocols(dpy, win, &xa_wm_del_win, 1); + + XClassHint hint; + hint.res_name = hint.res_class = (char*)"equeue_win"; + XSetClassHint(dpy, win, &hint); + + XTextProperty wm_name; + XStringListToTextProperty((char**)&title, 1, &wm_name); + XSetWMName(dpy, win, &wm_name); + XSetWMIconName(dpy, win, &wm_name); + XFree(wm_name.value); + + XMapWindow(dpy, win); + glXMakeCurrent(dpy, win, ctx); + + return win; +} + +static void process_events() +{ + XEvent ev; + + while(XPending(dpy)) { + XNextEvent(dpy, &ev); + switch(ev.type) { + case MapNotify: + win_mapped = true; + break; + + case UnmapNotify: + win_mapped = false; + break; + + case Expose: + if(win_mapped && ev.xexpose.count == 0) { + draw_pending = true; + } + break; + + case MotionNotify: + motion(ev.xmotion.x, ev.xmotion.y); + break; + + case ButtonPress: + mouse(ev.xbutton.button - 1, true, ev.xbutton.x, ev.xbutton.y); + break; + + case ButtonRelease: + mouse(ev.xbutton.button - 1, false, ev.xbutton.x, ev.xbutton.y); + break; + + case KeyPress: + { + KeySym sym = XLookupKeysym(&ev.xkey, 0); + keyb(translate_keysym(sym), true); + } + break; + + case KeyRelease: + { + KeySym sym = XLookupKeysym(&ev.xkey, 0); + keyb(translate_keysym(sym), false); + } + break; + + case ConfigureNotify: + { + int xsz = ev.xconfigure.width; + int ysz = ev.xconfigure.height; + + if(xsz != win_width || ysz != win_height) { + win_width = xsz; + win_height = ysz; + reshape(xsz, ysz); + } + } + break; + + case ClientMessage: + if(ev.xclient.message_type == xa_wm_prot) { + if((Atom)ev.xclient.data.l[0] == xa_wm_del_win) { + exit(0); + } + } + break; + + case LeaveNotify: + if(ev.xcrossing.mode == NotifyNormal) { + cam_theta = cam_phi = 0; + draw_pending = true; + } + break; + + default: + break; + } + + } +} + +static int translate_keysym(KeySym sym) +{ + switch(sym) { + case XK_BackSpace: + return '\b'; + case XK_Tab: + return '\t'; + case XK_Linefeed: + return '\r'; + case XK_Return: + return '\n'; + case XK_Escape: + return 27; + default: + break; + } + return (int)sym; +} + +static int proc_args(int argc, char **argv) +{ + for(int i=1; i, + Eleni-Maria Stea + +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 3 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, see . +*/ +#include +#include +#include +#include "material.h" + +static const char *find_path(const char *fname); + +Material::Material() + : diffuse(1, 1, 1), specular(0, 0, 0) +{ + shininess = 1.0; + alpha = 1.0; + + for(int i=0; i 128 ? 128 : shininess); + + float emit[] = {emissive.x, emissive.y, emissive.z, 1.0}; + glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emit); + + int num_tex = 0; + if(tex[TEX_DIFFUSE]) { + glActiveTexture(GL_TEXTURE0 + num_tex++); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glTranslatef(tex_offset[TEX_DIFFUSE].x, tex_offset[TEX_DIFFUSE].y, 0); + glScalef(tex_scale[TEX_DIFFUSE].x, tex_scale[TEX_DIFFUSE].y, 1); + + glBindTexture(GL_TEXTURE_2D, tex[TEX_DIFFUSE]); + glEnable(GL_TEXTURE_2D); + + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + } + + if(tex[TEX_ENVMAP]) { + glActiveTexture(GL_TEXTURE0 + num_tex++); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glTranslatef(tex_offset[TEX_ENVMAP].x, tex_offset[TEX_ENVMAP].y, 0); + glScalef(tex_scale[TEX_ENVMAP].x, tex_scale[TEX_ENVMAP].y, 1); + + glBindTexture(GL_TEXTURE_2D, tex[TEX_ENVMAP]); + glEnable(GL_TEXTURE_2D); + + 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); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); + } + + + glMatrixMode(GL_TEXTURE); + for(int i=num_tex; i<4; i++) { + glActiveTexture(GL_TEXTURE0 + i); + glDisable(GL_TEXTURE_2D); + glLoadIdentity(); + } + + glActiveTexture(GL_TEXTURE0); + glMatrixMode(GL_MODELVIEW); +} + +unsigned int load_texture(const char *fname) +{ + int xsz, ysz; + void *pixels; + unsigned int tex; + + const char *path = find_path(fname); + + if(!(pixels = img_load_pixels(path, &xsz, &ysz, IMG_FMT_RGBA32))) { + fprintf(stderr, "failed to load texture: %s\n", fname); + return 0; + } + + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_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, GL_RGBA, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + img_free_pixels(pixels); + return tex; +} + +static const char *find_path(const char *fname) +{ + const char *ptr = fname + strlen(fname) - 1; + + do { + while(*ptr != '/' && ptr > fname - 1) { + ptr--; + } + + FILE *fp = fopen(ptr + 1, "rb"); + if(fp) { + fclose(fp); + return ptr + 1; + } + ptr -= 1; + + } while(ptr >= fname); + + return fname; +} diff --git a/src/material.h b/src/material.h new file mode 100644 index 0000000..57c5696 --- /dev/null +++ b/src/material.h @@ -0,0 +1,53 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#ifndef MATERIAL_H_ +#define MATERIAL_H_ + +#include "vmath.h" + +enum { + TEX_DIFFUSE, + TEX_ENVMAP, + + NUM_TEXTURES +}; + +class Material { +public: + Vector3 emissive; + Vector3 ambient; + Vector3 diffuse; + Vector3 specular; + float shininess; + float alpha; + + unsigned int tex[NUM_TEXTURES]; + Vector2 tex_scale[NUM_TEXTURES], tex_offset[NUM_TEXTURES]; + + unsigned int sdr; + + Material(); + + void setup() const; +}; + +unsigned int load_texture(const char *fname); +unsigned int load_shader_program(const char *vname, const char *pname); + +#endif // MATERIAL_H_ diff --git a/src/mesh.cc b/src/mesh.cc new file mode 100644 index 0000000..94eb061 --- /dev/null +++ b/src/mesh.cc @@ -0,0 +1,174 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#include +#include +#include +#include +#include "mesh.h" + +#define ALL_VALID 0xffffffff + +Mesh::Mesh() +{ + buf_valid = ALL_VALID; + bsph_valid = false; + + for(int i=0; i max_lensq) { + max_lensq = lensq; + } + } + + bsph.set_center(center); + bsph.set_radius(sqrt(max_lensq)); + + bsph_valid = true; +} diff --git a/src/mesh.h b/src/mesh.h new file mode 100644 index 0000000..2019029 --- /dev/null +++ b/src/mesh.h @@ -0,0 +1,60 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#ifndef MESH_H_ +#define MESH_H_ + +#include "bvol.h" + +enum { + MESH_ATTR_VERTEX, + MESH_ATTR_NORMAL, + MESH_ATTR_TEXCOORD, + + NUM_MESH_ATTRIBS +}; + +class Mesh { +private: + float *attr[NUM_MESH_ATTRIBS]; + int vcount; + unsigned int vbo[NUM_MESH_ATTRIBS]; + int attr_size[NUM_MESH_ATTRIBS]; + + mutable unsigned int buf_valid; /* bitmask */ + void update_buffers() const; + + mutable BSphere bsph; + mutable bool bsph_valid; + void calc_bsph() const; + +public: + Mesh(); + ~Mesh(); + + float *set_attrib(int aidx, int count, int elemsz, float *data = 0); + float *get_attrib(int aidx); + const float *get_attrib(int aidx) const; + + void draw() const; + + BSphere &get_bounds(); + const BSphere &get_bounds() const; +}; + +#endif // MESH_H_ diff --git a/src/object.cc b/src/object.cc new file mode 100644 index 0000000..05d6ac0 --- /dev/null +++ b/src/object.cc @@ -0,0 +1,52 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#include "object.h" + +Object::Object() +{ + mesh = 0; +} + +void Object::set_name(const char *name) +{ + this->name = std::string(name); +} + +const char *Object::get_name() const +{ + return name.c_str(); +} + +void Object::set_mesh(Mesh *mesh) +{ + this->mesh = mesh; +} + +Mesh *Object::get_mesh() const +{ + return mesh; +} + +void Object::render() const +{ + if(!mesh) return; + + mtl.setup(); + mesh->draw(); +} diff --git a/src/object.h b/src/object.h new file mode 100644 index 0000000..6947339 --- /dev/null +++ b/src/object.h @@ -0,0 +1,45 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#ifndef OBJECT_H_ +#define OBJECT_H_ + +#include +#include "mesh.h" +#include "material.h" + +class Object { +private: + std::string name; + Mesh *mesh; + +public: + Material mtl; + + Object(); + + void set_name(const char *name); + const char *get_name() const; + + void set_mesh(Mesh *mesh); + Mesh *get_mesh() const; + + void render() const; +}; + +#endif // OBJECT_H_ diff --git a/src/objfile.cc b/src/objfile.cc new file mode 100644 index 0000000..6d926e3 --- /dev/null +++ b/src/objfile.cc @@ -0,0 +1,583 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "scene.h" + +using namespace std; + +#define COMMANDS \ + CMD(V), \ + CMD(VN), \ + CMD(VT), \ + CMD(F), \ + CMD(O), \ + CMD(G), \ + CMD(MTLLIB), \ + CMD(USEMTL), \ + CMD(NEWMTL), \ + CMD(KE), \ + CMD(KA), \ + CMD(KD), \ + CMD(KS), \ + CMD(NS), \ + CMD(NI), \ + CMD(D), \ + CMD(TR), \ + CMD(MAP_KD), \ + CMD(MAP_REFL), \ + CMD(MAP_BUMP), \ + CMD(MAP_KS), \ + CMD(MAP_NS), \ + CMD(MAP_D), \ + CMD(REFL), \ + CMD(BUMP) + +#define CMD(x) CMD_##x +enum { + COMMANDS, + CMD_UNK +}; +#undef CMD + +#define CMD(x) #x +static const char *cmd_names[] = { + COMMANDS, + 0 +}; +#undef CMD + + +struct ObjFace { + int elem; + int v[4], n[4], t[4]; +}; + +struct ObjFile { + string cur_obj, cur_mat; + vector v, vn; + vector vt; + vector f; +}; + +typedef Vector3 Color; + +struct ObjMat { + string name; // newmtl + Color ambient, diffuse, specular; // Ka, Kd, Ks + Color emissive; // Ke + float shininess; // Ns + float ior; // Ni + float alpha; // d, Tr + + string tex_dif, tex_spec, tex_shin, tex_alpha; // map_Kd, map_Ks, map_Ns, map_d + string tex_refl; // refl -type sphere|cube file + string tex_bump; // bump + + ObjMat() { reset(); } + + void reset() { + ambient = diffuse = Color(0.5, 0.5, 0.5); + specular = Color(0.0, 0.0, 0.0); + name = tex_dif = tex_spec = tex_shin = tex_alpha = tex_refl = tex_bump = ""; + shininess = 0; + ior = alpha = 1; + } +}; + +static bool read_materials(FILE *fp, vector *vmtl); +static Object *cons_object(ObjFile *obj); + +static int get_cmd(char *str); +static bool is_int(const char *str); +static bool is_float(const char *str); +static bool parse_vec(Vector3 *vec); +static bool parse_color(Color *col); +static bool parse_face(ObjFace *face); +static const char *parse_map(); + + +static map matlib; + + +#define INVALID_IDX INT_MIN + +#define SEP " \t\n\r\v" +#define BUF_SZ 512 +bool Scene::load_obj(FILE *fp) +{ + static int seq; + char cur_name[16]; + stringstream sstr; + + ObjFile obj; + + sprintf(cur_name, "default%02d.obj", seq++); + obj.cur_obj = cur_name; + + int prev_cmd = 0, obj_added = 0; + for(;;) { + Vector3 vec; + ObjFace face; + + char line[BUF_SZ]; + fgets(line, sizeof line, fp); + if(feof(fp)) { + break; + } + + char *tok; + if(!(tok = strtok(line, SEP))) { + continue; // ignore empty lines + } + + int cmd; + if((cmd = get_cmd(tok)) == -1) { + continue; // ignore unknown commands ... + } + + switch(cmd) { + case CMD_V: + if(!parse_vec(&vec)) { + continue; + } + obj.v.push_back(vec); + break; + + case CMD_VN: + if(!parse_vec(&vec)) { + continue; + } + obj.vn.push_back(vec); + break; + + case CMD_VT: + if(!parse_vec(&vec)) { + continue; + } + vec.y = 1.0 - vec.y; + obj.vt.push_back(Vector2(vec.x, vec.y)); + break; + + case CMD_O: + case CMD_G: + if(prev_cmd == CMD_O || prev_cmd == CMD_G) { + break; // just in case we've got both of them in a row + } + /* if we have any previous data, group them up, add the object + * and continue with the new one... + */ + if(!obj.f.empty()) { + Object *robj = cons_object(&obj); + robj->mtl = matlib[obj.cur_mat]; + add_object(robj); + obj_added++; + + obj.f.clear(); // clean the face list + } + if((tok = strtok(0, SEP))) { + obj.cur_obj = tok; + } else { + sprintf(cur_name, "default%02d.obj", seq++); + obj.cur_obj = cur_name; + } + break; + + case CMD_MTLLIB: + if((tok = strtok(0, SEP))) { + FILE *mfile; + if(!(mfile = fopen(tok, "rb"))) { + fprintf(stderr, "failed to open material library: %s\n", tok); + continue; + } + + // load all materials of the mtl file into a vector + vector vmtl; + if(!read_materials(mfile, &vmtl)) { + continue; + } + fclose(mfile); + + // and add them all to the scene + for(size_t i=0; imtl = matlib[obj.cur_mat]; + add_object(robj); + obj_added++; + } + + return obj_added > 0; +} + +static Object *cons_object(ObjFile *obj) +{ + Object *robj; + Vector3 *varr, *narr; + Vector2 *tarr; + + int nelem = obj->f.size() * 3; + + assert(sizeof(Vector3) == 3 * sizeof(float)); + assert(sizeof(Vector2) == 2 * sizeof(float)); + + try { + robj = new Object; + varr = new Vector3[nelem]; + narr = new Vector3[nelem]; + tarr = new Vector2[nelem]; + } + catch(...) { + return 0; + } + if(obj->cur_obj.length() > 0) { + robj->set_name(obj->cur_obj.c_str()); + } + + // need at least one of each element + bool added_norm = false, added_tc = false; + if(obj->vn.empty()) { + obj->vn.push_back(Vector3(0, 0, 0)); + added_norm = true; + } + if(obj->vt.empty()) { + obj->vt.push_back(Vector2(0, 0)); + added_tc = true; + } + + for(size_t i=0; if.size(); i++) { + for(int j=0; j<3; j++) { + int idx = i * 3 + j; + ObjFace *f = &obj->f[i]; + + varr[idx] = obj->v[f->v[j]]; + narr[idx] = obj->vn[f->n[j] < 0 ? 0 : f->n[j]]; + + float t = obj->vt[f->t[j] < 0 ? 0 : f->t[j]].x; + float s = obj->vt[f->t[j] < 0 ? 0 : f->t[j]].y; + tarr[idx] = Vector2(t, s); + } + } + + if(added_norm) { + obj->vn.pop_back(); + } + if(added_tc) { + obj->vt.pop_back(); + } + + Mesh *mesh = new Mesh; + mesh->set_attrib(MESH_ATTR_VERTEX, nelem, 3, &varr->x); + mesh->set_attrib(MESH_ATTR_NORMAL, nelem, 3, &narr->x); + mesh->set_attrib(MESH_ATTR_TEXCOORD, nelem, 2, &tarr->x); + robj->set_mesh(mesh); + + printf("loaded object %s: %d faces\n", obj->cur_obj.c_str(), nelem / 3); + + delete [] varr; + delete [] narr; + delete [] tarr; + return robj; +} + +static bool read_materials(FILE *fp, vector *vmtl) +{ + ObjMat mat; + + for(;;) { + char line[BUF_SZ]; + fgets(line, sizeof line, fp); + if(feof(fp)) { + break; + } + + char *tok; + if(!(tok = strtok(line, SEP))) { + continue; + } + + int cmd; + if((cmd = get_cmd(tok)) == -1) { + continue; + } + + switch(cmd) { + case CMD_NEWMTL: + // add the previous material, and start a new one + if(mat.name.length() > 0) { + vmtl->push_back(mat); + mat.reset(); + } + if((tok = strtok(0, SEP))) { + mat.name = tok; + } + break; + + case CMD_KE: + parse_color(&mat.emissive); + break; + + case CMD_KA: + parse_color(&mat.ambient); + break; + + case CMD_KD: + parse_color(&mat.diffuse); + break; + + case CMD_KS: + parse_color(&mat.specular); + break; + + case CMD_NS: + if((tok = strtok(0, SEP)) && is_float(tok)) { + mat.shininess = atof(tok); + } + break; + + case CMD_NI: + if((tok = strtok(0, SEP)) && is_float(tok)) { + mat.ior = atof(tok); + } + break; + + case CMD_D: + case CMD_TR: + { + Color c; + if(parse_color(&c)) { + mat.alpha = cmd == CMD_D ? c.x : 1.0 - c.x; + } + } + break; + + case CMD_MAP_KD: + mat.tex_dif = parse_map(); + break; + + case CMD_MAP_REFL: + mat.tex_refl = parse_map(); + break; + + default: + break; + } + } + + if(mat.name.length() > 0) { + vmtl->push_back(mat); + } + return true; +} + +static int get_cmd(char *str) +{ + char *s = str; + while((*s = toupper(*s))) s++; + + for(int i=0; cmd_names[i]; i++) { + if(strcmp(str, cmd_names[i]) == 0) { + return i; + } + } + return CMD_UNK; +} + +static bool is_int(const char *str) +{ + char *tmp; + strtol(str, &tmp, 10); + return tmp != str; +} + +static bool is_float(const char *str) +{ + char *tmp; + strtod(str, &tmp); + return tmp != str; +} + +static bool parse_vec(Vector3 *vec) +{ + for(int i=0; i<3; i++) { + char *tok; + + if(!(tok = strtok(0, SEP)) || !is_float(tok)) { + if(i < 2) { + return false; + } + vec->z = 0.0; + } else { + (*vec)[i] = atof(tok); + } + } + return true; +} + +static bool parse_color(Color *col) +{ + for(int i=0; i<3; i++) { + char *tok; + + if(!(tok = strtok(0, SEP)) || !is_float(tok)) { + col->y = col->z = col->x; + return i > 0 ? true : false; + } + (*col)[i] = atof(tok); + } + return true; +} + +static bool parse_face(ObjFace *face) +{ + char *tok[] = {0, 0, 0, 0}; + face->elem = 0; + + for(int i=0; i<4; i++) { + if((!(tok[i] = strtok(0, SEP)) || !is_int(tok[i]))) { + if(i < 3) return false; // less than 3 verts? not a polygon + } else { + face->elem++; + } + } + + for(int i=0; i<4; i++) { + char *subtok = tok[i]; + + if(!subtok || !*subtok || !is_int(subtok)) { + if(i < 3) { + return false; + } + face->v[i] = INVALID_IDX; + } else { + face->v[i] = atoi(subtok); + if(face->v[i] > 0) face->v[i]--; /* convert to 0-based */ + } + + while(subtok && *subtok && *subtok != '/') { + subtok++; + } + if(subtok && *subtok && *++subtok && is_int(subtok)) { + face->t[i] = atoi(subtok); + if(face->t[i] > 0) face->t[i]--; /* convert to 0-based */ + } else { + face->t[i] = INVALID_IDX; + } + + while(subtok && *subtok && *subtok != '/') { + subtok++; + } + if(subtok && *subtok && *++subtok && is_int(subtok)) { + face->n[i] = atoi(subtok); + if(face->n[i] > 0) face->n[i]--; /* convert to 0-based */ + } else { + face->n[i] = INVALID_IDX; + } + } + + return true; +} + +static const char *parse_map() +{ + char *tok, *prev = 0; + + while((tok = strtok(0, SEP))) { + prev = tok; + } + + return prev ? prev : ""; +} diff --git a/src/scene.cc b/src/scene.cc new file mode 100644 index 0000000..bbaeadc --- /dev/null +++ b/src/scene.cc @@ -0,0 +1,107 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#include +#include +#include +#include "scene.h" + +Scene::~Scene() +{ + for(size_t i=0; iget_name(), name) == 0) { + return objects[i]; + } + } + return 0; +} + +bool Scene::remove_object(Object *obj) +{ + for(size_t i=0; irender(); + } +} diff --git a/src/scene.h b/src/scene.h new file mode 100644 index 0000000..9d07854 --- /dev/null +++ b/src/scene.h @@ -0,0 +1,55 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#ifndef SCENE_H_ +#define SCENE_H_ + +#include +#include +#include "mesh.h" +#include "object.h" + +class Scene { +private: + std::vector objects; + std::vector meshes; + + bool load_obj(FILE *fp); // defined in objfile.cc + +public: + ~Scene(); + + bool load(const char *fname); + + void add_object(Object *obj); + void add_mesh(Mesh *mesh); + + int get_num_objects() const; + int get_num_meshes() const; + + Object *get_object(int idx) const; + Mesh *get_mesh(int idx) const; + + Object *get_object(const char *name) const; + bool remove_object(Object *obj); + + void update(long msec); + void render() const; +}; + +#endif // SCENE_H_ diff --git a/src/timer.cc b/src/timer.cc new file mode 100644 index 0000000..4e9019d --- /dev/null +++ b/src/timer.cc @@ -0,0 +1,38 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#include +#include + +unsigned long get_msec() +{ + static struct timeval tv0; + struct timeval tv; + + gettimeofday(&tv, 0); + if(tv0.tv_sec == 0 && tv0.tv_usec == 0) { + tv0 = tv; + return 0; + } + return (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000; +} + +void wait_for(unsigned long msec) +{ + usleep(msec * 1000); +} diff --git a/src/timer.h b/src/timer.h new file mode 100644 index 0000000..733ecb8 --- /dev/null +++ b/src/timer.h @@ -0,0 +1,25 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#ifndef TIMER_H_ +#define TIMER_H_ + +unsigned long get_msec(); +void wait_for(unsigned long msec); + +#endif /* TIMER_H_ */ diff --git a/src/vmath.h b/src/vmath.h new file mode 100644 index 0000000..69411ca --- /dev/null +++ b/src/vmath.h @@ -0,0 +1,99 @@ +/* +eqemu - electronic queue system emulator +Copyright (C) 2014 John Tsiombikas , + Eleni-Maria Stea + +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 3 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, see . +*/ +#ifndef VMATH_H_ +#define VMATH_H_ + +#include + +class Vector2 { +public: + float x, y; + + Vector2() : x(0), y(0) {} + Vector2(float xa, float ya) : x(xa), y(ya) {} + + float &operator [](int idx) { return (&x)[idx]; } + const float &operator [](int idx) const { return (&x)[idx]; } +}; + +class Vector3 { +public: + float x, y, z; + + Vector3() : x(0), y(0), z(0) {} + Vector3(float xa, float ya, float za) : x(xa), y(ya), z(za) {} + + float &operator [](int idx) { return (&x)[idx]; } + const float &operator [](int idx) const { return (&x)[idx]; } +}; + +inline Vector3 operator +(const Vector3 &a, const Vector3 &b) +{ + return Vector3(a.x + b.x, a.y + b.y, a.z + b.z); +} + +inline Vector3 operator -(const Vector3 &a, const Vector3 &b) +{ + return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); +} + +inline Vector3 operator *(const Vector3 &a, float s) +{ + return Vector3(a.x * s, a.y * s, a.z * s); +} + +inline float dot(const Vector3 &a, const Vector3 &b) +{ + return a.x * b.x + a.y * b.y + a.z * b.z; +} + +inline float length(const Vector3 &v) +{ + return sqrt(dot(v, v)); +} + +inline Vector3 normalize(const Vector3 &v) +{ + float len = length(v); + if(len == 0.0) { + return v; + } + return Vector3(v.x / len, v.y / len, v.z / len); +} + +class Vector4 { +public: + float x, y, z, w; + + Vector4() : x(0), y(0), z(0), w(0) {} + Vector4(float xa, float ya, float za, float wa) : x(xa), y(ya), z(za), w(wa) {} + + float &operator [](int idx) { return (&x)[idx]; } + const float &operator [](int idx) const { return (&x)[idx]; } +}; + +class Ray { +public: + Vector3 origin, dir; + + Ray() : origin(0, 0, 0), dir(0, 0, 1) {} + Ray(const Vector3 &o, const Vector3 &d) : origin(o), dir(d) {} +}; + +#endif // VMATH_H_ -- 1.7.10.4