# HG changeset patch # User John Tsiombikas # Date 1433022026 -10800 # Node ID c71c477521ca982bfebdac20230de93ba02ba2ff # Parent d1b456d087131e05bbcf6fabc424ed4e486aa786 converting to GLES2 and C++ diff -r d1b456d08713 -r c71c477521ca android/Makefile --- a/android/Makefile Mon May 25 05:27:26 2015 +0300 +++ b/android/Makefile Sun May 31 00:40:26 2015 +0300 @@ -23,10 +23,12 @@ android_usr = $(NDK)/platforms/$(android_platform)/arch-arm/usr android_inc = -I$(native_app_glue_dir) -android_libs = -llog -landroid -lEGL -lGLESv1_CM +android_libs = -lstdc++ -llog -landroid -lEGL -lGLESv2 -CFLAGS = -std=c99 -Wall -g -DAPP_NAME=\"$(name)\" -march=armv7-a -mfloat-abi=softfp \ +defs += -DANDROID -DAPP_NAME=\"$(name)\" +CXXFLAGS = -Wall -g $(defs) -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 \ $(android_inc) -I$(root)/src/android -I$(root)/src/gles $(incpaths) +CFLAGS = -std=c99 $(CXXFLAGS) LDFLAGS = -Wl,--fix-cortex-a8 -Wl,-z,defs $(android_libs) $(libpaths) -lm .PHONY: debug @@ -46,7 +48,7 @@ $(lib): $(obj) @mkdir -p libs/armeabi - $(CC) -o $@ -shared $(obj) $(LDFLAGS) + $(CXX) -o $@ -shared $(obj) $(LDFLAGS) ant_files = *.xml *.properties proguard-project.txt ant_dirs = bin libs res obj src gen diff -r d1b456d08713 -r c71c477521ca android/manifest.xml.in --- a/android/manifest.xml.in Mon May 25 05:27:26 2015 +0300 +++ b/android/manifest.xml.in Sun May 31 00:40:26 2015 +0300 @@ -8,6 +8,7 @@ + diff -r d1b456d08713 -r c71c477521ca libs/drawtext/COPYING --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/drawtext/COPYING Sun May 31 00:40:26 2015 +0300 @@ -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 -r d1b456d08713 -r c71c477521ca libs/drawtext/COPYING.LESSER --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/drawtext/COPYING.LESSER Sun May 31 00:40:26 2015 +0300 @@ -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 -r d1b456d08713 -r c71c477521ca libs/drawtext/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/drawtext/README Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,19 @@ +libdrawtext - 0.2.1 +------------------- + +Libdrawtext is a simple library for fast anti-aliased text rendering in OpenGL. + +Copyright (C) 2011-2014 John Tsiombikas +You may freely use, modify and/or redistribute libdrawtext, under the terms of +the GNU Lesser General Public License (LGPL) version 3 (or at your option, any +later version published by the Free Software Foundation). See COPYING, and +COPYING.LESSER for details. + +website: http://nuclear.mutantstargoat.com/sw/libdrawtext + +master repository (hg): http://nuclear.mutantstargoat.com/hg/libdrawtext +mirror repository (git): https://github.com/jtsiomb/libdrawtext.git + +Feel free to send in bug reports, patches, and other comments to +nuclear@member.fsf.org +Only plain text email messages, hard-wrapped at 72 columns will be accepted. diff -r d1b456d08713 -r c71c477521ca libs/drawtext/drawgl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/drawtext/drawgl.c Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,302 @@ +/* +libdrawtext - a simple library for fast text rendering in OpenGL +Copyright (C) 2011-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 NO_OPENGL +#include +#include +#include + +#include + +#ifndef _MSC_VER +#include +#else +#include +#endif + +#ifdef TARGET_IPHONE +#include +#define GL_ES +#elif defined(ANDROID) +#include +#define GL_ES +#else +#include +#endif + +#include "drawtext.h" +#include "drawtext_impl.h" + +struct vertex { + float x, y; + float s, t; +}; + +struct quad { + struct vertex v[6]; +}; + +static void cleanup(void); +static void add_glyph(struct glyph *g, float x, float y); + +#define QBUF_SZ 512 +static struct quad *qbuf; +static int num_quads; +static int vattr = -1; +static int tattr = -1; +static unsigned int font_tex; +static int buf_mode = DTX_NBF; + + +int dtx_gl_init(void) +{ + if(qbuf) { + return 0; /* already initialized */ + } + +#ifdef __glew_h__ + glewInit(); +#endif + + if(!(qbuf = malloc(QBUF_SZ * sizeof *qbuf))) { + return -1; + } + num_quads = 0; + + atexit(cleanup); + return 0; +} + +static void cleanup(void) +{ + free(qbuf); +} + + +void dtx_vertex_attribs(int vert_attr, int tex_attr) +{ + vattr = vert_attr; + tattr = tex_attr; +} + +static void set_glyphmap_texture(struct dtx_glyphmap *gmap) +{ + if(!gmap->tex) { + glGenTextures(1, &gmap->tex); + glBindTexture(GL_TEXTURE_2D, gmap->tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + +#ifdef GL_ES + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, gmap->xsz, gmap->ysz, 0, GL_ALPHA, GL_UNSIGNED_BYTE, gmap->pixels); + glGenerateMipmap(GL_TEXTURE_2D); +#else + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, gmap->xsz, gmap->ysz, GL_ALPHA, GL_UNSIGNED_BYTE, gmap->pixels); +#endif + } + + if(font_tex != gmap->tex) { + dtx_flush(); + } + font_tex = gmap->tex; +} + +void dtx_glyph(int code) +{ + struct dtx_glyphmap *gmap; + + if(!dtx_font || !(gmap = dtx_get_font_glyphmap(dtx_font, dtx_font_sz, code))) { + return; + } + set_glyphmap_texture(gmap); + + add_glyph(gmap->glyphs + code - gmap->cstart, 0, 0); + dtx_flush(); +} + +static const char *put_char(const char *str, float *pos_x, float *pos_y, int *should_flush) +{ + struct dtx_glyphmap *gmap; + float px, py; + int code = dtx_utf8_char_code(str); + str = dtx_utf8_next_char((char*)str); + + if(buf_mode == DTX_LBF && code == '\n') { + *should_flush = 1; + } + + px = *pos_x; + py = *pos_y; + + if((gmap = dtx_proc_char(code, pos_x, pos_y))) { + int idx = code - gmap->cstart; + + set_glyphmap_texture(gmap); + add_glyph(gmap->glyphs + idx, px, py); + } + return str; +} + +void dtx_string(const char *str) +{ + int should_flush = buf_mode == DTX_NBF; + float pos_x = 0.0f; + float pos_y = 0.0f; + + if(!dtx_font) { + return; + } + + while(*str) { + str = put_char(str, &pos_x, &pos_y, &should_flush); + } + + if(should_flush) { + dtx_flush(); + } +} + +void dtx_printf(const char *fmt, ...) +{ + va_list ap; + int buf_size; + char *buf, tmp; + + if(!dtx_font) { + return; + } + + va_start(ap, fmt); + buf_size = vsnprintf(&tmp, 0, fmt, ap); + va_end(ap); + + if(buf_size == -1) { + buf_size = 512; + } + + buf = alloca(buf_size + 1); + va_start(ap, fmt); + vsnprintf(buf, buf_size + 1, fmt, ap); + va_end(ap); + + dtx_string(buf); +} + +static void qvertex(struct vertex *v, float x, float y, float s, float t) +{ + v->x = x; + v->y = y; + v->s = s; + v->t = t; +} + +static void add_glyph(struct glyph *g, float x, float y) +{ + struct quad *qptr = qbuf + num_quads; + + x -= g->orig_x; + y -= g->orig_y; + + qvertex(qptr->v + 0, x, y, g->nx, g->ny + g->nheight); + qvertex(qptr->v + 1, x + g->width, y, g->nx + g->nwidth, g->ny + g->nheight); + qvertex(qptr->v + 2, x + g->width, y + g->height, g->nx + g->nwidth, g->ny); + + qvertex(qptr->v + 3, x, y, g->nx, g->ny + g->nheight); + qvertex(qptr->v + 4, x + g->width, y + g->height, g->nx + g->nwidth, g->ny); + qvertex(qptr->v + 5, x, y + g->height, g->nx, g->ny); + + if(++num_quads >= QBUF_SZ) { + dtx_flush(); + } +} + +void dtx_flush(void) +{ + int vbo; + + if(!num_quads) { + return; + } + + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, 0); + +#ifndef GL_ES + glPushAttrib(GL_ENABLE_BIT); + glEnable(GL_TEXTURE_2D); +#endif + glBindTexture(GL_TEXTURE_2D, font_tex); + + if(vattr != -1) { + glEnableVertexAttribArray(vattr); + glVertexAttribPointer(vattr, 2, GL_FLOAT, 0, sizeof(struct vertex), qbuf); +#ifndef GL_ES + } else { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), qbuf); +#endif + } + if(tattr != -1) { + glEnableVertexAttribArray(tattr); + glVertexAttribPointer(tattr, 2, GL_FLOAT, 0, sizeof(struct vertex), &qbuf->v[0].s); +#ifndef GL_ES + } else { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), &qbuf->v[0].s); +#endif + } + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDepthMask(0); + + glDrawArrays(GL_TRIANGLES, 0, num_quads * 6); + + glDepthMask(1); + + if(vattr != -1) { + glDisableVertexAttribArray(vattr); +#ifndef GL_ES + } else { + glDisableClientState(GL_VERTEX_ARRAY); +#endif + } + if(tattr != -1) { + glDisableVertexAttribArray(tattr); +#ifndef GL_ES + } else { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); +#endif + } + +#ifndef GL_ES + glPopAttrib(); +#else + glDisable(GL_BLEND); +#endif + + if(vbo) { + glBindBuffer(GL_ARRAY_BUFFER, vbo); + } + + num_quads = 0; +} + +#endif /* !def NO_OPENGL */ diff -r d1b456d08713 -r c71c477521ca libs/drawtext/drawtext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/drawtext/drawtext.h Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,188 @@ +/* +libdrawtext - a simple library for fast text rendering in OpenGL +Copyright (C) 2011-2014 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 LIBDRAWTEXT_H_ +#define LIBDRAWTEXT_H_ + +#include +#include + +struct dtx_font; +struct dtx_glyphmap; + +/* draw buffering modes */ +enum { + DTX_NBF, /* unbuffered */ + DTX_LBF, /* line buffered */ + DTX_FBF /* fully buffered */ +}; + +struct dtx_box { + float x, y; + float width, height; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/* Open a truetype/opentype/whatever font. + * + * If sz is non-zero, the default ASCII glyphmap at the requested point size is + * automatically created as well, and ready to use. + * + * To use other unicode ranges and different font sizes you must first call + * dtx_prepare or dtx_prepare_range before issuing any drawing calls, otherwise + * nothing will be rendered. + */ +struct dtx_font *dtx_open_font(const char *fname, int sz); +/* open a font by loading a precompiled glyphmap (see: dtx_save_glyphmap) + * this works even when compiled without freetype support + */ +struct dtx_font *dtx_open_font_glyphmap(const char *fname); +/* close a font opened by either of the above */ +void dtx_close_font(struct dtx_font *fnt); + +/* prepare an ASCII glyphmap for the specified font size */ +void dtx_prepare(struct dtx_font *fnt, int sz); +/* prepare an arbitrary unicode range glyphmap for the specified font size */ +void dtx_prepare_range(struct dtx_font *fnt, int sz, int cstart, int cend); + +/* Finds the glyphmap that contains the specified character code and matches the requested size + * Returns null if it hasn't been created (you should call dtx_prepare/dtx_prepare_range). + */ +struct dtx_glyphmap *dtx_get_font_glyphmap(struct dtx_font *fnt, int sz, int code); + +/* Finds the glyphmap that contains the specified unicode range and matches the requested font size + * Will automatically generate one if it can't find it. + */ +struct dtx_glyphmap *dtx_get_font_glyphmap_range(struct dtx_font *fnt, int sz, int cstart, int cend); + +/* Creates and returns a glyphmap for a particular unicode range and font size. + * The generated glyphmap is added to the font's list of glyphmaps. + */ +struct dtx_glyphmap *dtx_create_glyphmap_range(struct dtx_font *fnt, int sz, int cstart, int cend); +/* free a glyphmap */ +void dtx_free_glyphmap(struct dtx_glyphmap *gmap); + +/* returns a pointer to the raster image of a glyphmap (1 byte per pixel grayscale) */ +unsigned char *dtx_get_glyphmap_image(struct dtx_glyphmap *gmap); +/* returns the width of the glyphmap image in pixels */ +int dtx_get_glyphmap_width(struct dtx_glyphmap *gmap); +/* returns the height of the glyphmap image in pixels */ +int dtx_get_glyphmap_height(struct dtx_glyphmap *gmap); + +/* The following functions can be used even when the library is compiled without + * freetype support. + */ +struct dtx_glyphmap *dtx_load_glyphmap(const char *fname); +struct dtx_glyphmap *dtx_load_glyphmap_stream(FILE *fp); +int dtx_save_glyphmap(const char *fname, const struct dtx_glyphmap *gmap); +int dtx_save_glyphmap_stream(FILE *fp, const struct dtx_glyphmap *gmap); + +/* adds a glyphmap to a font */ +void dtx_add_glyphmap(struct dtx_font *fnt, struct dtx_glyphmap *gmap); + +/* ---- rendering ---- */ + +/* before drawing anything this function must set the font to use */ +void dtx_use_font(struct dtx_font *fnt, int sz); + +/* sets the buffering mode + * - DTX_NBUF: every call to dtx_string gets rendered immediately. + * - DTX_LBUF: renders when the buffer is full or the string contains a newline. + * - DTX_FBUF: renders only when the buffer is full (you must call dtx_flush explicitly). + */ +void dtx_draw_buffering(int mode); + +/* Sets the vertex attribute indices to use for passing vertex and texture coordinate + * data. By default both are -1 which means you don't have to use a shader, and if you + * do they are accessible through gl_Vertex and gl_MultiTexCoord0, as usual. + * + * NOTE: If you are using OpenGL ES 2.x or OpenGL >= 3.1 pure (non-compatibility) context + * you must specify valid attribute indices. + */ +void dtx_vertex_attribs(int vert_attr, int tex_attr); + +/* draws a single glyph at the origin */ +void dtx_glyph(int code); +/* draws a utf-8 string starting at the origin. \n \r and \t are handled appropriately. */ +void dtx_string(const char *str); + +void dtx_printf(const char *fmt, ...); + +/* render any pending glyphs (see dtx_draw_buffering) */ +void dtx_flush(void); + + +/* ---- encodings ---- */ + +/* returns a pointer to the next character in a utf-8 stream */ +char *dtx_utf8_next_char(char *str); + +/* returns the unicode character codepoint of the utf-8 character starting at str */ +int dtx_utf8_char_code(const char *str); + +/* returns the number of bytes of the utf-8 character starting at str */ +int dtx_utf8_nbytes(const char *str); + +/* returns the number of utf-8 character in a zero-terminated utf-8 string */ +int dtx_utf8_char_count(const char *str); + +/* Converts a unicode code-point to a utf-8 character by filling in the buffer + * passed at the second argument, and returns the number of bytes taken by that + * utf-8 character. + * It's valid to pass a null buffer pointer, in which case only the byte count is + * returned (useful to figure out how much memory to allocate for a buffer). + */ +size_t dtx_utf8_from_char_code(int code, char *buf); + +/* Converts a unicode utf-16 wchar_t string to utf-8, filling in the buffer passed + * at the second argument. Returns the size of the resulting string in bytes. + * + * It's valid to pass a null buffer pointer, in which case only the size gets + * calculated and returned, which is useful for figuring out how much memory to + * allocate for the utf-8 buffer. + */ +size_t dtx_utf8_from_string(const wchar_t *str, char *buf); + + +/* ---- metrics ---- */ +float dtx_line_height(void); + +/* rendered dimensions of a single glyph */ +void dtx_glyph_box(int code, struct dtx_box *box); +float dtx_glyph_width(int code); +float dtx_glyph_height(int code); + +/* rendered dimensions of a string */ +void dtx_string_box(const char *str, struct dtx_box *box); +float dtx_string_width(const char *str); +float dtx_string_height(const char *str); + +/* returns the horizontal position of the n-th character of the rendered string + * (useful for placing cursors) + */ +float dtx_char_pos(const char *str, int n); + +int dtx_char_at_pt(const char *str, float pt); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBDRAWTEXT_H_ */ diff -r d1b456d08713 -r c71c477521ca libs/drawtext/drawtext_impl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/drawtext/drawtext_impl.h Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,72 @@ +/* +libdrawtext - a simple library for fast text rendering in OpenGL +Copyright (C) 2011-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 TEXT_IMPL_H_ +#define TEXT_IMPL_H_ + +struct glyph { + int code; + float x, y, width, height; + /* normalized coords [0, 1] */ + float nx, ny, nwidth, nheight; + float orig_x, orig_y; + float advance; + struct glyph *next; +}; + +struct dtx_glyphmap { + int ptsize; + + int xsz, ysz; + unsigned char *pixels; + unsigned int tex; + + int cstart, cend; /* character range */ + int crange; + + float line_advance; + + struct glyph *glyphs; + struct dtx_glyphmap *next; +}; + +struct dtx_font { + /* freetype FT_Face */ + void *face; + + /* list of glyphmaps */ + struct dtx_glyphmap *gmaps; + + /* last returned glyphmap (cache) */ + struct dtx_glyphmap *last_gmap; +}; + + +struct dtx_font *dtx_font; +int dtx_font_sz; + + +#define fperror(str) \ + fprintf(stderr, "%s: %s: %s\n", __FUNCTION__, (str), strerror(errno)) + +int dtx_gl_init(void); + +/* returns zero if it should NOT be printed and modifies xpos/ypos */ +/* implemented in font.c */ +struct dtx_glyphmap *dtx_proc_char(int code, float *xpos, float *ypos); + +#endif /* TEXT_IMPL_H_ */ diff -r d1b456d08713 -r c71c477521ca libs/drawtext/font.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/drawtext/font.c Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,773 @@ +/* +libdrawtext - a simple library for fast text rendering in OpenGL +Copyright (C) 2011-2014 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 NO_FREETYPE +#define USE_FREETYPE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_FREETYPE +#include +#include FT_FREETYPE_H +#endif +#include "drawtext.h" +#include "drawtext_impl.h" + +#define FTSZ_TO_PIXELS(x) ((x) / 64) +#define MAX_IMG_WIDTH 4096 + + +#ifdef USE_FREETYPE +static int init_freetype(void); +static void cleanup(void); + +static void calc_best_size(int total_width, int max_gwidth, int max_gheight, + int padding, int pow2, int *imgw, int *imgh); +static int next_pow2(int x); + +static FT_Library ft; + + +static int init_done; + +static int init_freetype(void) +{ + if(!init_done) { + if(FT_Init_FreeType(&ft) != 0) { + return -1; + } + atexit(cleanup); + init_done = 1; + } + return 0; +} + +static void cleanup(void) +{ + if(init_done) { + FT_Done_FreeType(ft); + } +} +#endif /* USE_FREETYPE */ + +struct dtx_font *dtx_open_font(const char *fname, int sz) +{ + struct dtx_font *fnt = 0; + +#ifdef USE_FREETYPE + init_freetype(); + + if(!(fnt = calloc(1, sizeof *fnt))) { + fperror("failed to allocate font structure"); + return 0; + } + + if(FT_New_Face(ft, fname, 0, (FT_Face*)&fnt->face) != 0) { + fprintf(stderr, "failed to open font file: %s\n", fname); + return 0; + } + + /* pre-create the extended ASCII range glyphmap */ + if(sz) { + dtx_prepare_range(fnt, sz, 0, 256); + + if(!dtx_font) { + dtx_use_font(fnt, sz); + } + } +#else + fprintf(stderr, "ignoring call to dtx_open_font: not compiled with freetype support!\n"); +#endif + + return fnt; +} + +struct dtx_font *dtx_open_font_glyphmap(const char *fname) +{ + struct dtx_font *fnt; + struct dtx_glyphmap *gmap; + + if(!(fnt = calloc(1, sizeof *fnt))) { + fperror("failed to allocate font structure"); + return 0; + } + + if(fname) { + if(!(gmap = dtx_load_glyphmap(fname))) { + free(fnt); + return 0; + } + + dtx_add_glyphmap(fnt, gmap); + + if(!dtx_font) { + dtx_use_font(fnt, gmap->ptsize); + } + } + return fnt; +} + +void dtx_close_font(struct dtx_font *fnt) +{ + if(!fnt) return; + +#ifdef USE_FREETYPE + FT_Done_Face(fnt->face); +#endif + + /* destroy the glyphmaps */ + while(fnt->gmaps) { + void *tmp = fnt->gmaps; + fnt->gmaps = fnt->gmaps->next; + dtx_free_glyphmap(tmp); + } + + free(fnt); +} + +void dtx_prepare(struct dtx_font *fnt, int sz) +{ + if(!dtx_get_font_glyphmap_range(fnt, sz, 0, 256)) { + fprintf(stderr, "%s: failed (sz: %d, range: 0-255 [ascii])\n", __FUNCTION__, sz); + } +} + +void dtx_prepare_range(struct dtx_font *fnt, int sz, int cstart, int cend) +{ + if(!dtx_get_font_glyphmap_range(fnt, sz, cstart, cend)) { + fprintf(stderr, "%s: failed (sz: %d, range: %d-%d)\n", __FUNCTION__, sz, cstart, cend); + } +} + +struct dtx_glyphmap *dtx_get_font_glyphmap(struct dtx_font *fnt, int sz, int code) +{ + struct dtx_glyphmap *gm; + + /* check to see if the last we've given out fits the bill */ + if(fnt->last_gmap && code >= fnt->last_gmap->cstart && code < fnt->last_gmap->cend && fnt->last_gmap->ptsize == sz) { + return fnt->last_gmap; + } + + /* otherwise search for the appropriate glyphmap */ + gm = fnt->gmaps; + while(gm) { + if(code >= gm->cstart && code < gm->cend && sz == gm->ptsize) { + fnt->last_gmap = gm; + return gm; + } + gm = gm->next; + } + return 0; +} + +struct dtx_glyphmap *dtx_get_font_glyphmap_range(struct dtx_font *fnt, int sz, int cstart, int cend) +{ + struct dtx_glyphmap *gm; + + /* search the available glyphmaps to see if we've got one that includes + * the requested range + */ + gm = fnt->gmaps; + while(gm) { + if(gm->cstart <= cstart && gm->cend >= cend && gm->ptsize == sz) { + return gm; + } + gm = gm->next; + } + + /* not found, create one and add it to the list */ + if(!(gm = dtx_create_glyphmap_range(fnt, sz, cstart, cend))) { + return 0; + } + return gm; +} + +struct dtx_glyphmap *dtx_create_glyphmap_range(struct dtx_font *fnt, int sz, int cstart, int cend) +{ + struct dtx_glyphmap *gmap = 0; + +#ifdef USE_FREETYPE + FT_Face face = fnt->face; + int i, j; + int gx, gy; + int padding = 4; + int total_width, max_width, max_height; + + FT_Set_Char_Size(fnt->face, 0, sz * 64, 72, 72); + + if(!(gmap = calloc(1, sizeof *gmap))) { + return 0; + } + + gmap->ptsize = sz; + gmap->cstart = cstart; + gmap->cend = cend; + gmap->crange = cend - cstart; + gmap->line_advance = FTSZ_TO_PIXELS((float)face->size->metrics.height); + + if(!(gmap->glyphs = malloc(gmap->crange * sizeof *gmap->glyphs))) { + free(gmap); + return 0; + } + + total_width = padding; + max_width = max_height = 0; + + for(i=0; icrange; i++) { + int w, h; + + FT_Load_Char(face, i + cstart, 0); + w = FTSZ_TO_PIXELS(face->glyph->metrics.width); + h = FTSZ_TO_PIXELS(face->glyph->metrics.height); + + if(w > max_width) max_width = w; + if(h > max_height) max_height = h; + + total_width += w + padding; + } + + calc_best_size(total_width, max_width, max_height, padding, 1, &gmap->xsz, &gmap->ysz); + + if(!(gmap->pixels = malloc(gmap->xsz * gmap->ysz))) { + free(gmap->glyphs); + free(gmap); + return 0; + } + memset(gmap->pixels, 0, gmap->xsz * gmap->ysz); + + gx = padding; + gy = padding; + + for(i=0; icrange; i++) { + float gwidth, gheight; + unsigned char *src, *dst; + FT_GlyphSlot glyph; + + FT_Load_Char(face, i + cstart, FT_LOAD_RENDER); + glyph = face->glyph; + gwidth = FTSZ_TO_PIXELS((float)glyph->metrics.width); + gheight = FTSZ_TO_PIXELS((float)glyph->metrics.height); + + if(gx > gmap->xsz - gwidth - padding) { + gx = padding; + gy += max_height + padding; + } + + src = glyph->bitmap.buffer; + dst = gmap->pixels + gy * gmap->xsz + gx; + + for(j=0; jbitmap.rows; j++) { + memcpy(dst, src, glyph->bitmap.width); + dst += gmap->xsz; + src += glyph->bitmap.pitch; + } + + gmap->glyphs[i].code = i; + gmap->glyphs[i].x = gx - 1; + gmap->glyphs[i].y = gy - 1; + gmap->glyphs[i].width = gwidth + 2; + gmap->glyphs[i].height = gheight + 2; + gmap->glyphs[i].orig_x = -FTSZ_TO_PIXELS((float)glyph->metrics.horiBearingX) + 1; + gmap->glyphs[i].orig_y = FTSZ_TO_PIXELS((float)glyph->metrics.height - glyph->metrics.horiBearingY) + 1; + gmap->glyphs[i].advance = FTSZ_TO_PIXELS((float)glyph->metrics.horiAdvance); + /* also precalc normalized */ + gmap->glyphs[i].nx = (float)gmap->glyphs[i].x / (float)gmap->xsz; + gmap->glyphs[i].ny = (float)gmap->glyphs[i].y / (float)gmap->ysz; + gmap->glyphs[i].nwidth = (float)gmap->glyphs[i].width / (float)gmap->xsz; + gmap->glyphs[i].nheight = (float)gmap->glyphs[i].height / (float)gmap->ysz; + + gx += gwidth + padding; + } + + /* add it to the glyphmaps list of the font */ + dtx_add_glyphmap(fnt, gmap); +#endif /* USE_FREETYPE */ + + return gmap; +} + +void dtx_free_glyphmap(struct dtx_glyphmap *gmap) +{ + if(gmap) { + free(gmap->pixels); + free(gmap->glyphs); + free(gmap); + } +} + +unsigned char *dtx_get_glyphmap_pixels(struct dtx_glyphmap *gmap) +{ + return gmap->pixels; +} + +int dtx_get_glyphmap_width(struct dtx_glyphmap *gmap) +{ + return gmap->xsz; +} + +int dtx_get_glyphmap_height(struct dtx_glyphmap *gmap) +{ + return gmap->ysz; +} + +struct dtx_glyphmap *dtx_load_glyphmap(const char *fname) +{ + FILE *fp; + struct dtx_glyphmap *gmap; + + if(!(fp = fopen(fname, "rb"))) { + return 0; + } + gmap = dtx_load_glyphmap_stream(fp); + fclose(fp); + return gmap; +} + +struct dtx_glyphmap *dtx_load_glyphmap_stream(FILE *fp) +{ + char buf[512]; + int hdr_lines = 0; + struct dtx_glyphmap *gmap; + struct glyph *glyphs = 0; + struct glyph *g; + int min_code = INT_MAX; + int max_code = INT_MIN; + int i, max_pixval, num_pixels; + + if(!(gmap = calloc(1, sizeof *gmap))) { + fperror("failed to allocate glyphmap"); + return 0; + } + gmap->ptsize = -1; + gmap->line_advance = FLT_MIN; + + while(hdr_lines < 3) { + char *line = buf; + if(!fgets(buf, sizeof buf, fp)) { + fperror("unexpected end of file"); + goto err; + } + + while(isspace(*line)) { + line++; + } + + if(line[0] == '#') { + int c, res; + float x, y, xsz, ysz, orig_x, orig_y, adv, line_adv; + int ptsize; + + if((res = sscanf(line + 1, " size: %d\n", &ptsize)) == 1) { + gmap->ptsize = ptsize; + + } else if((res = sscanf(line + 1, " advance: %f\n", &line_adv)) == 1) { + gmap->line_advance = line_adv; + + } else if((res = sscanf(line + 1, " %d: %fx%f+%f+%f o:%f,%f adv:%f\n", + &c, &xsz, &ysz, &x, &y, &orig_x, &orig_y, &adv)) == 8) { + if(!(g = malloc(sizeof *g))) { + fperror("failed to allocate glyph"); + goto err; + } + g->code = c; + g->x = x; + g->y = y; + g->width = xsz; + g->height = ysz; + g->orig_x = orig_x; + g->orig_y = orig_y; + g->advance = adv; + /* normalized coordinates will be precalculated after everything is loaded */ + + g->next = glyphs; + glyphs = g; + + if(c < min_code) { + min_code = c; + } + if(c > max_code) { + max_code = c; + } + + } else { + fprintf(stderr, "%s: invalid glyph info line\n", __FUNCTION__); + goto err; + } + + } else { + switch(hdr_lines) { + case 0: + if(0[line] != 'P' || 1[line] != '6') { + fprintf(stderr, "%s: invalid file format (magic)\n", __FUNCTION__); + goto err; + } + break; + + case 1: + if(sscanf(line, "%d %d", &gmap->xsz, &gmap->ysz) != 2) { + fprintf(stderr, "%s: invalid file format (dim)\n", __FUNCTION__); + goto err; + } + break; + + case 2: + { + char *endp; + max_pixval = strtol(line, &endp, 10); + if(endp == line) { + fprintf(stderr, "%s: invalid file format (maxval)\n", __FUNCTION__); + goto err; + } + } + break; + + default: + break; /* can't happen */ + } + hdr_lines++; + } + } + + if(gmap->ptsize == -1 || gmap->line_advance == FLT_MIN) { + fprintf(stderr, "%s: invalid glyphmap, insufficient information in ppm comments\n", __FUNCTION__); + goto err; + } + + /* precalculate normalized glyph coordinates */ + g = glyphs; + while(g) { + g->nx = g->x / gmap->xsz; + g->ny = g->y / gmap->ysz; + g->nwidth = g->width / gmap->xsz; + g->nheight = g->height / gmap->ysz; + g = g->next; + } + + num_pixels = gmap->xsz * gmap->ysz; + if(!(gmap->pixels = malloc(num_pixels))) { + fperror("failed to allocate pixels"); + goto err; + } + + for(i=0; ipixels[i] = 255 * c / max_pixval; + fseek(fp, 2, SEEK_CUR); + } + + gmap->cstart = min_code; + gmap->cend = max_code + 1; + gmap->crange = gmap->cend - gmap->cstart; + + if(!(gmap->glyphs = calloc(gmap->crange, sizeof *gmap->glyphs))) { + fperror("failed to allocate glyph info"); + goto err; + } + + while(glyphs) { + struct glyph *g = glyphs; + glyphs = glyphs->next; + + gmap->glyphs[g->code - gmap->cstart] = *g; + free(g); + } + return gmap; + +err: + dtx_free_glyphmap(gmap); + while(glyphs) { + void *tmp = glyphs; + glyphs = glyphs->next; + free(tmp); + } + return 0; +} + +int dtx_save_glyphmap(const char *fname, const struct dtx_glyphmap *gmap) +{ + FILE *fp; + int res; + + if(!(fp = fopen(fname, "wb"))) { + fprintf(stderr, "%s: failed to open file: %s: %s\n", __FUNCTION__, fname, strerror(errno)); + return -1; + } + res = dtx_save_glyphmap_stream(fp, gmap); + fclose(fp); + return res; +} + +int dtx_save_glyphmap_stream(FILE *fp, const struct dtx_glyphmap *gmap) +{ + int i, num_pixels; + struct glyph *g = gmap->glyphs; + + fprintf(fp, "P6\n%d %d\n", gmap->xsz, gmap->ysz); + fprintf(fp, "# size: %d\n", gmap->ptsize); + fprintf(fp, "# advance: %g\n", gmap->line_advance); + for(i=0; icrange; i++) { + fprintf(fp, "# %d: %gx%g+%g+%g o:%g,%g adv:%g\n", g->code, g->width, g->height, g->x, g->y, + g->orig_x, g->orig_y, g->advance); + g++; + } + fprintf(fp, "255\n"); + + num_pixels = gmap->xsz * gmap->ysz; + for(i=0; ipixels[i]; + fputc(c, fp); + fputc(c, fp); + fputc(c, fp); + } + return 0; +} + +void dtx_add_glyphmap(struct dtx_font *fnt, struct dtx_glyphmap *gmap) +{ + gmap->next = fnt->gmaps; + fnt->gmaps = gmap; +} + + +void dtx_use_font(struct dtx_font *fnt, int sz) +{ + dtx_gl_init(); + + dtx_font = fnt; + dtx_font_sz = sz; +} + +float dtx_line_height(void) +{ + struct dtx_glyphmap *gmap = dtx_get_font_glyphmap(dtx_font, dtx_font_sz, '\n'); + + return gmap->line_advance; +} + +void dtx_glyph_box(int code, struct dtx_box *box) +{ + int cidx; + struct dtx_glyphmap *gmap; + gmap = dtx_get_font_glyphmap(dtx_font, dtx_font_sz, code); + + cidx = code - gmap->cstart; + + box->x = gmap->glyphs[cidx].orig_x; + box->y = gmap->glyphs[cidx].orig_y; + box->width = gmap->glyphs[cidx].width; + box->height = gmap->glyphs[cidx].height; +} + +float dtx_glyph_width(int code) +{ + struct dtx_box box; + dtx_glyph_box(code, &box); + return box.width; +} + +float dtx_glyph_height(int code) +{ + struct dtx_box box; + dtx_glyph_box(code, &box); + return box.height; +} + +void dtx_string_box(const char *str, struct dtx_box *box) +{ + int code; + float pos_x = 0.0f, pos_y = 0.0f; + struct glyph *g = 0; + float x0, y0, x1, y1; + + x0 = y0 = FLT_MAX; + x1 = y1 = -FLT_MAX; + + while(*str) { + float px, py; + struct dtx_glyphmap *gmap; + + code = dtx_utf8_char_code(str); + str = dtx_utf8_next_char((char*)str); + + px = pos_x; + py = pos_y; + + if((gmap = dtx_proc_char(code, &pos_x, &pos_y))) { + g = gmap->glyphs + code - gmap->cstart; + + if(px + g->orig_x < x0) { + x0 = px + g->orig_x; + } + if(py - g->orig_y < y0) { + y0 = py - g->orig_y; + } + if(px + g->orig_x + g->width > x1) { + x1 = px + g->orig_x + g->width; + } + if(py - g->orig_y + g->height > y1) { + y1 = py - g->orig_y + g->height; + } + } + } + + box->x = x0; + box->y = y0; + box->width = x1 - x0; + box->height = y1 - y0; +} + +float dtx_string_width(const char *str) +{ + struct dtx_box box; + + dtx_string_box(str, &box); + return box.width; +} + +float dtx_string_height(const char *str) +{ + struct dtx_box box; + + dtx_string_box(str, &box); + return box.height; +} + +float dtx_char_pos(const char *str, int n) +{ + int i; + float pos = 0.0; + struct dtx_glyphmap *gmap; + + for(i=0; iglyphs[i].advance; + } + return pos; +} + +int dtx_char_at_pt(const char *str, float pt) +{ + int i; + float prev_pos = 0.0f, pos = 0.0f; + struct dtx_glyphmap *gmap; + + for(i=0; *str; i++) { + int code = dtx_utf8_char_code(str); + str = dtx_utf8_next_char((char*)str); + + gmap = dtx_get_font_glyphmap(dtx_font, dtx_font_sz, code); + pos += gmap->glyphs[i].advance; + + if(fabs(pt - prev_pos) < fabs(pt - pos)) { + break; + } + prev_pos = pos; + } + return i; +} + +struct dtx_glyphmap *dtx_proc_char(int code, float *xpos, float *ypos) +{ + struct dtx_glyphmap *gmap; + gmap = dtx_get_font_glyphmap(dtx_font, dtx_font_sz, code); + + switch(code) { + case '\n': + *xpos = 0.0; + if(gmap) { + *ypos -= gmap->line_advance; + } + return 0; + + case '\t': + if(gmap) { + *xpos = (fmod(*xpos, 4.0) + 4.0) * gmap->glyphs[0].advance; + } + return 0; + + case '\r': + *xpos = 0.0; + return 0; + + default: + break; + } + + if(gmap) { + *xpos += gmap->glyphs[code - gmap->cstart].advance; + } + return gmap; +} + +#ifdef USE_FREETYPE +static void calc_best_size(int total_width, int max_gwidth, int max_gheight, int padding, int pow2, int *imgw, int *imgh) +{ + int xsz, ysz, num_rows; + float aspect; + + for(xsz=2; xsz<=MAX_IMG_WIDTH; xsz *= 2) { + num_rows = total_width / xsz + 1; + + /* assume worst case, all last glyphs will float to the next line + * so let's add extra rows for that. */ + num_rows += (padding + (max_gwidth + padding) * num_rows + xsz - 1) / xsz; + + ysz = num_rows * (max_gheight + padding) + padding; + if(pow2) { + ysz = next_pow2(ysz); + } + aspect = (float)xsz / (float)ysz; + + if(aspect >= 1.0) { + break; + } + } + + if(xsz > MAX_IMG_WIDTH) { + xsz = MAX_IMG_WIDTH; + } + + *imgw = xsz; + *imgh = ysz; +} + + +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; +} +#endif diff -r d1b456d08713 -r c71c477521ca libs/drawtext/utf8.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/drawtext/utf8.c Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,154 @@ +/* +libdrawtext - a simple library for fast text rendering in OpenGL +Copyright (C) 2011 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 "drawtext.h" + +#define U8_IS_FIRST(x) (((((x) >> 7) & 1) == 0) || ((((x) >> 6) & 3) == 3)) + +static const char first_mask[] = { + 0, + 0x7f, /* single byte, 7 bits valid */ + 0x1f, /* two-bytes, 5 bits valid */ + 0xf, /* three-bytes, 4 bits valid */ + 0x7 /* four-bytes, 3 bits valid */ +}; +static const char first_shift[] = { 0, 7, 5, 4, 3 }; /* see above */ + +#define CONT_PREFIX 0x80 +#define CONT_MASK 0x3f +#define CONT_SHIFT 6 + +/* last charcodes for 1, 2, 3 or 4-byte utf8 chars */ +static const int utf8_lastcode[] = { 0x7f, 0x7ff, 0xfff, 0x1fffff }; + +#define prefix_mask(x) (~first_mask[x]) +#define prefix(x) ((prefix_mask(x) << 1) & 0xff) + + +char *dtx_utf8_next_char(char *str) +{ + return str + dtx_utf8_nbytes(str); +} + +int dtx_utf8_char_code(const char *str) +{ + int i, nbytes, shift, code = 0; + int mask; + + if(!U8_IS_FIRST(*str)) { + return -1; + } + + nbytes = dtx_utf8_nbytes(str); + mask = first_mask[nbytes]; + shift = 0; + + for(i=0; i> (7 - i)) & 1) == 0) { + break; + } + numset++; + } + + if(!numset) { + return 1; + } + return numset; +} + +int dtx_utf8_char_count(const char *str) +{ + int n = 0; + + while(*str) { + n++; + str = dtx_utf8_next_char((char*)str); + } + return n; +} + +size_t dtx_utf8_from_char_code(int code, char *buf) +{ + size_t nbytes = 0; + int i; + + for(i=0; i<4; i++) { + if(code <= utf8_lastcode[i]) { + nbytes = i + 1; + break; + } + } + + if(!nbytes && buf) { + for(i=0; i<(int)nbytes; i++) { + int idx = nbytes - i - 1; + int mask, shift, prefix; + + if(idx > 0) { + mask = CONT_MASK; + shift = CONT_SHIFT; + prefix = CONT_PREFIX; + } else { + mask = first_mask[nbytes]; + shift = first_shift[nbytes]; + prefix = prefix(nbytes); + } + + buf[idx] = (code & mask) | (prefix & ~mask); + code >>= shift; + } + } + return nbytes; +} + +size_t dtx_utf8_from_string(const wchar_t *str, char *buf) +{ + size_t nbytes = 0; + char *ptr = buf; + + while(*str) { + int cbytes = dtx_utf8_from_char_code(*str++, ptr); + if(ptr) { + ptr += cbytes; + } + nbytes += cbytes; + } + return nbytes; +} diff -r d1b456d08713 -r c71c477521ca libs/vmath/basis.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/basis.cc Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,80 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 "basis.h" +#include "vmath.h" + +Basis::Basis() +{ + i = Vector3(1, 0, 0); + j = Vector3(0, 1, 0); + k = Vector3(0, 0, 1); +} + +Basis::Basis(const Vector3 &i, const Vector3 &j, const Vector3 &k) +{ + this->i = i; + this->j = j; + this->k = k; +} + +Basis::Basis(const Vector3 &dir, bool left_handed) +{ + k = dir; + j = Vector3(0, 1, 0); + i = cross_product(j, k); + j = cross_product(k, i); +} + +/** Rotate with euler angles */ +void Basis::rotate(scalar_t x, scalar_t y, scalar_t z) { + Matrix4x4 RotMat; + RotMat.set_rotation(Vector3(x, y, z)); + i.transform(RotMat); + j.transform(RotMat); + k.transform(RotMat); +} + +/** Rotate by axis-angle specification */ +void Basis::rotate(const Vector3 &axis, scalar_t angle) { + Quaternion q; + q.set_rotation(axis, angle); + i.transform(q); + j.transform(q); + k.transform(q); +} + +/** Rotate with a 4x4 matrix */ +void Basis::rotate(const Matrix4x4 &mat) { + i.transform(mat); + j.transform(mat); + k.transform(mat); +} + +/** Rotate with a quaternion */ +void Basis::rotate(const Quaternion &quat) { + i.transform(quat); + j.transform(quat); + k.transform(quat); +} + +/** Extract a rotation matrix from the orthogonal basis */ +Matrix3x3 Basis::create_rotation_matrix() const { + return Matrix3x3( i.x, j.x, k.x, + i.y, j.y, k.y, + i.z, j.z, k.z); +} diff -r d1b456d08713 -r c71c477521ca libs/vmath/basis.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/basis.h Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,57 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 VMATH_BASIS_H_ +#define VMATH_BASIS_H_ + +#include "vector.h" +#include "matrix.h" + +enum { + LEFT_HANDED, + RIGHT_HANDED +}; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void basis_matrix(mat4_t res, vec3_t i, vec3_t j, vec3_t k); +void basis_matrix_dir(mat4_t res, vec3_t dir); + +#ifdef __cplusplus +} /* extern "C" */ + +class Basis { +public: + Vector3 i, j, k; + + Basis(); + Basis(const Vector3 &i, const Vector3 &j, const Vector3 &k); + Basis(const Vector3 &dir, bool left_handed = true); + + void rotate(scalar_t x, scalar_t y, scalar_t z); + void rotate(const Vector3 &axis, scalar_t angle); + void rotate(const Matrix4x4 &mat); + void rotate(const Quaternion &quat); + + Matrix3x3 create_rotation_matrix() const; +}; +#endif /* __cplusplus */ + +#endif /* VMATH_BASIS_H_ */ diff -r d1b456d08713 -r c71c477521ca libs/vmath/basis_c.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/basis_c.c Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,37 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 "basis.h" +#include "matrix.h" + +void basis_matrix(mat4_t res, vec3_t i, vec3_t j, vec3_t k) +{ + m4_identity(res); + m4_set_column(res, v4_cons(i.x, i.y, i.z, 1.0), 0); + m4_set_column(res, v4_cons(j.x, j.y, j.z, 1.0), 1); + m4_set_column(res, v4_cons(k.x, k.y, k.z, 1.0), 2); +} + +void basis_matrix_dir(mat4_t res, vec3_t dir) +{ + vec3_t k = v3_normalize(dir); + vec3_t j = {0, 1, 0}; + vec3_t i = v3_cross(j, k); + j = v3_cross(k, i); + basis_matrix(res, i, j, k); +} diff -r d1b456d08713 -r c71c477521ca libs/vmath/geom.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/geom.c Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,150 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 "geom.h" +#include "vector.h" + +plane_t plane_cons(scalar_t nx, scalar_t ny, scalar_t nz, scalar_t d) +{ + plane_t p; + p.norm.x = nx; + p.norm.y = ny; + p.norm.z = nz; + p.d = d; + return p; +} + +plane_t plane_poly(vec3_t v0, vec3_t v1, vec3_t v2) +{ + vec3_t a, b, norm; + + a = v3_sub(v1, v0); + b = v3_sub(v2, v0); + norm = v3_cross(a, b); + norm = v3_normalize(norm); + + return plane_ptnorm(v0, norm); +} + +plane_t plane_ptnorm(vec3_t pt, vec3_t normal) +{ + plane_t plane; + + plane.norm = normal; + plane.d = v3_dot(pt, normal); + + return plane; +} + +plane_t plane_invert(plane_t p) +{ + p.norm = v3_neg(p.norm); + p.d = -p.d; + return p; +} + +scalar_t plane_signed_dist(plane_t plane, vec3_t pt) +{ + vec3_t pp = plane_point(plane); + vec3_t pptopt = v3_sub(pt, pp); + return v3_dot(pptopt, plane.norm); +} + +scalar_t plane_dist(plane_t plane, vec3_t pt) +{ + return fabs(plane_signed_dist(plane, pt)); +} + +vec3_t plane_point(plane_t plane) +{ + return v3_scale(plane.norm, plane.d); +} + +int plane_ray_intersect(ray_t ray, plane_t plane, scalar_t *pos) +{ + vec3_t pt, orig_to_pt; + scalar_t ndotdir; + + pt = plane_point(plane); + ndotdir = v3_dot(plane.norm, ray.dir); + + if(fabs(ndotdir) < 1e-7) { + return 0; + } + + if(pos) { + orig_to_pt = v3_sub(pt, ray.origin); + *pos = v3_dot(plane.norm, orig_to_pt) / ndotdir; + } + return 1; +} + +sphere_t sphere_cons(scalar_t x, scalar_t y, scalar_t z, scalar_t rad) +{ + sphere_t sph; + sph.pos.x = x; + sph.pos.y = y; + sph.pos.z = z; + sph.rad = rad; + return sph; +} + +int sphere_ray_intersect(ray_t ray, sphere_t sph, scalar_t *pos) +{ + scalar_t a, b, c, d, sqrt_d, t1, t2, t; + + a = v3_dot(ray.dir, ray.dir); + b = 2.0 * ray.dir.x * (ray.origin.x - sph.pos.x) + + 2.0 * ray.dir.y * (ray.origin.y - sph.pos.y) + + 2.0 * ray.dir.z * (ray.origin.z - sph.pos.z); + c = v3_dot(sph.pos, sph.pos) + v3_dot(ray.origin, ray.origin) + + 2.0 * v3_dot(v3_neg(sph.pos), ray.origin) - sph.rad * sph.rad; + + d = b * b - 4.0 * a * c; + if(d < 0.0) { + return 0; + } + + sqrt_d = sqrt(d); + t1 = (-b + sqrt_d) / (2.0 * a); + t2 = (-b - sqrt_d) / (2.0 * a); + + if(t1 < 1e-7 || t1 > 1.0) { + t1 = t2; + } + if(t2 < 1e-7 || t2 > 1.0) { + t2 = t1; + } + t = t1 < t2 ? t1 : t2; + + if(t < 1e-7 || t > 1.0) { + return 0; + } + + if(pos) { + *pos = t; + } + return 1; +} + +int sphere_sphere_intersect(sphere_t sph1, sphere_t sph2, scalar_t *pos, scalar_t *rad) +{ + return -1; +} diff -r d1b456d08713 -r c71c477521ca libs/vmath/geom.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/geom.h Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,72 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 LIBVMATH_GEOM_H_ +#define LIBVMATH_GEOM_H_ + +#include "vector.h" +#include "ray.h" + +typedef struct { + vec3_t norm; + scalar_t d; +} plane_t; + +typedef struct { + vec3_t pos; + scalar_t rad; +} sphere_t; + +typedef struct { + vec3_t min, max; +} aabox_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/* planes are good... you need planes, yes you do */ +plane_t plane_cons(scalar_t nx, scalar_t ny, scalar_t nz, scalar_t d); +plane_t plane_poly(vec3_t v0, vec3_t v1, vec3_t v2); +plane_t plane_ptnorm(vec3_t pt, vec3_t normal); + +plane_t plane_invert(plane_t p); + +scalar_t plane_signed_dist(plane_t plane, vec3_t pt); +scalar_t plane_dist(plane_t plane, vec3_t pt); +vec3_t plane_point(plane_t plane); + +int plane_ray_intersect(ray_t ray, plane_t plane, scalar_t *pos); + +/* spheres always come in handy */ +sphere_t sphere_cons(scalar_t x, scalar_t y, scalar_t z, scalar_t rad); + +int sphere_ray_intersect(ray_t ray, sphere_t sph, scalar_t *pos); +int sphere_sphere_intersect(sphere_t sph1, sphere_t sph2, scalar_t *pos, scalar_t *rad); + +#ifdef __cplusplus +} + +/* TODO +class Plane : public plane_t { +public: +}; +*/ + +#endif + +#endif /* LIBVMATH_GEOM_H_ */ diff -r d1b456d08713 -r c71c477521ca libs/vmath/matrix.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/matrix.cc Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,872 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 "matrix.h" +#include "vector.h" +#include "quat.h" + +using namespace std; + +// ----------- Matrix3x3 -------------- + +Matrix3x3 Matrix3x3::identity = Matrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1); + +Matrix3x3::Matrix3x3() +{ + *this = Matrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1); +} + +Matrix3x3::Matrix3x3( scalar_t m11, scalar_t m12, scalar_t m13, + scalar_t m21, scalar_t m22, scalar_t m23, + scalar_t m31, scalar_t m32, scalar_t m33) +{ + m[0][0] = m11; m[0][1] = m12; m[0][2] = m13; + m[1][0] = m21; m[1][1] = m22; m[1][2] = m23; + m[2][0] = m31; m[2][1] = m32; m[2][2] = m33; +} + +Matrix3x3::Matrix3x3(const Vector3 &ivec, const Vector3 &jvec, const Vector3 &kvec) +{ + set_row_vector(ivec, 0); + set_row_vector(jvec, 1); + set_row_vector(kvec, 2); +} + +Matrix3x3::Matrix3x3(const mat3_t cmat) +{ + memcpy(m, cmat, sizeof(mat3_t)); +} + +Matrix3x3::Matrix3x3(const Matrix4x4 &mat4x4) +{ + for(int i=0; i<3; i++) { + for(int j=0; j<3; j++) { + m[i][j] = mat4x4[i][j]; + } + } +} + +Matrix3x3 operator +(const Matrix3x3 &m1, const Matrix3x3 &m2) +{ + Matrix3x3 res; + const scalar_t *op1 = m1.m[0], *op2 = m2.m[0]; + scalar_t *dest = res.m[0]; + + for(int i=0; i<9; i++) { + *dest++ = *op1++ + *op2++; + } + return res; +} + +Matrix3x3 operator -(const Matrix3x3 &m1, const Matrix3x3 &m2) +{ + Matrix3x3 res; + const scalar_t *op1 = m1.m[0], *op2 = m2.m[0]; + scalar_t *dest = res.m[0]; + + for(int i=0; i<9; i++) { + *dest++ = *op1++ - *op2++; + } + return res; +} + +Matrix3x3 operator *(const Matrix3x3 &m1, const Matrix3x3 &m2) +{ + Matrix3x3 res; + for(int i=0; i<3; i++) { + for(int j=0; j<3; j++) { + res.m[i][j] = m1.m[i][0] * m2.m[0][j] + m1.m[i][1] * m2.m[1][j] + m1.m[i][2] * m2.m[2][j]; + } + } + return res; +} + +void operator +=(Matrix3x3 &m1, const Matrix3x3 &m2) +{ + scalar_t *op1 = m1.m[0]; + const scalar_t *op2 = m2.m[0]; + + for(int i=0; i<9; i++) { + *op1++ += *op2++; + } +} + +void operator -=(Matrix3x3 &m1, const Matrix3x3 &m2) +{ + scalar_t *op1 = m1.m[0]; + const scalar_t *op2 = m2.m[0]; + + for(int i=0; i<9; i++) { + *op1++ -= *op2++; + } +} + +void operator *=(Matrix3x3 &m1, const Matrix3x3 &m2) +{ + Matrix3x3 res; + for(int i=0; i<3; i++) { + for(int j=0; j<3; j++) { + res.m[i][j] = m1.m[i][0] * m2.m[0][j] + m1.m[i][1] * m2.m[1][j] + m1.m[i][2] * m2.m[2][j]; + } + } + memcpy(m1.m, res.m, 9 * sizeof(scalar_t)); +} + +Matrix3x3 operator *(const Matrix3x3 &mat, scalar_t scalar) +{ + Matrix3x3 res; + const scalar_t *mptr = mat.m[0]; + scalar_t *dptr = res.m[0]; + + for(int i=0; i<9; i++) { + *dptr++ = *mptr++ * scalar; + } + return res; +} + +Matrix3x3 operator *(scalar_t scalar, const Matrix3x3 &mat) +{ + Matrix3x3 res; + const scalar_t *mptr = mat.m[0]; + scalar_t *dptr = res.m[0]; + + for(int i=0; i<9; i++) { + *dptr++ = *mptr++ * scalar; + } + return res; +} + +void operator *=(Matrix3x3 &mat, scalar_t scalar) +{ + scalar_t *mptr = mat.m[0]; + + for(int i=0; i<9; i++) { + *mptr++ *= scalar; + } +} + +void Matrix3x3::translate(const Vector2 &trans) +{ + Matrix3x3 tmat(1, 0, trans.x, 0, 1, trans.y, 0, 0, 1); + *this *= tmat; +} + +void Matrix3x3::set_translation(const Vector2 &trans) +{ + *this = Matrix3x3(1, 0, trans.x, 0, 1, trans.y, 0, 0, 1); +} + +void Matrix3x3::rotate(scalar_t angle) +{ + scalar_t cos_a = cos(angle); + scalar_t sin_a = sin(angle); + Matrix3x3 rmat( cos_a, -sin_a, 0, + sin_a, cos_a, 0, + 0, 0, 1); + *this *= rmat; +} + +void Matrix3x3::set_rotation(scalar_t angle) +{ + scalar_t cos_a = cos(angle); + scalar_t sin_a = sin(angle); + *this = Matrix3x3(cos_a, -sin_a, 0, sin_a, cos_a, 0, 0, 0, 1); +} + +void Matrix3x3::rotate(const Vector3 &euler_angles) +{ + Matrix3x3 xrot, yrot, zrot; + + xrot = Matrix3x3( 1, 0, 0, + 0, cos(euler_angles.x), -sin(euler_angles.x), + 0, sin(euler_angles.x), cos(euler_angles.x)); + + yrot = Matrix3x3( cos(euler_angles.y), 0, sin(euler_angles.y), + 0, 1, 0, + -sin(euler_angles.y), 0, cos(euler_angles.y)); + + zrot = Matrix3x3( cos(euler_angles.z), -sin(euler_angles.z), 0, + sin(euler_angles.z), cos(euler_angles.z), 0, + 0, 0, 1); + + *this *= xrot * yrot * zrot; +} + +void Matrix3x3::set_rotation(const Vector3 &euler_angles) +{ + Matrix3x3 xrot, yrot, zrot; + + xrot = Matrix3x3( 1, 0, 0, + 0, cos(euler_angles.x), -sin(euler_angles.x), + 0, sin(euler_angles.x), cos(euler_angles.x)); + + yrot = Matrix3x3( cos(euler_angles.y), 0, sin(euler_angles.y), + 0, 1, 0, + -sin(euler_angles.y), 0, cos(euler_angles.y)); + + zrot = Matrix3x3( cos(euler_angles.z), -sin(euler_angles.z), 0, + sin(euler_angles.z), cos(euler_angles.z), 0, + 0, 0, 1); + + *this = xrot * yrot * zrot; +} + +void Matrix3x3::rotate(const Vector3 &axis, scalar_t angle) +{ + scalar_t sina = (scalar_t)sin(angle); + scalar_t cosa = (scalar_t)cos(angle); + scalar_t invcosa = 1-cosa; + scalar_t nxsq = axis.x * axis.x; + scalar_t nysq = axis.y * axis.y; + scalar_t nzsq = axis.z * axis.z; + + Matrix3x3 xform; + xform.m[0][0] = nxsq + (1-nxsq) * cosa; + xform.m[0][1] = axis.x * axis.y * invcosa - axis.z * sina; + xform.m[0][2] = axis.x * axis.z * invcosa + axis.y * sina; + + xform.m[1][0] = axis.x * axis.y * invcosa + axis.z * sina; + xform.m[1][1] = nysq + (1-nysq) * cosa; + xform.m[1][2] = axis.y * axis.z * invcosa - axis.x * sina; + + xform.m[2][0] = axis.x * axis.z * invcosa - axis.y * sina; + xform.m[2][1] = axis.y * axis.z * invcosa + axis.x * sina; + xform.m[2][2] = nzsq + (1-nzsq) * cosa; + + *this *= xform; +} + +void Matrix3x3::set_rotation(const Vector3 &axis, scalar_t angle) +{ + scalar_t sina = (scalar_t)sin(angle); + scalar_t cosa = (scalar_t)cos(angle); + scalar_t invcosa = 1-cosa; + scalar_t nxsq = axis.x * axis.x; + scalar_t nysq = axis.y * axis.y; + scalar_t nzsq = axis.z * axis.z; + + reset_identity(); + m[0][0] = nxsq + (1-nxsq) * cosa; + m[0][1] = axis.x * axis.y * invcosa - axis.z * sina; + m[0][2] = axis.x * axis.z * invcosa + axis.y * sina; + m[1][0] = axis.x * axis.y * invcosa + axis.z * sina; + m[1][1] = nysq + (1-nysq) * cosa; + m[1][2] = axis.y * axis.z * invcosa - axis.x * sina; + m[2][0] = axis.x * axis.z * invcosa - axis.y * sina; + m[2][1] = axis.y * axis.z * invcosa + axis.x * sina; + m[2][2] = nzsq + (1-nzsq) * cosa; +} + +// Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes +// article "Quaternion Calculus and Fast Animation". +// adapted from: http://www.geometrictools.com/LibMathematics/Algebra/Wm5Quaternion.inl +Quaternion Matrix3x3::get_rotation_quat() const +{ + static const int next[3] = {1, 2, 0}; + + float quat[4]; + + scalar_t trace = m[0][0] + m[1][1] + m[2][2]; + scalar_t root; + + if(trace > 0.0f) { + // |w| > 1/2 + root = sqrt(trace + 1.0f); // 2w + quat[0] = 0.5f * root; + root = 0.5f / root; // 1 / 4w + quat[1] = (m[2][1] - m[1][2]) * root; + quat[2] = (m[0][2] - m[2][0]) * root; + quat[3] = (m[1][0] - m[0][1]) * root; + } else { + // |w| <= 1/2 + int i = 0; + if(m[1][1] > m[0][0]) { + i = 1; + } + if(m[2][2] > m[i][i]) { + i = 2; + } + int j = next[i]; + int k = next[j]; + + root = sqrt(m[i][i] - m[j][j] - m[k][k] + 1.0f); + quat[i + 1] = 0.5f * root; + root = 0.5f / root; + quat[0] = (m[k][j] - m[j][k]) * root; + quat[j + 1] = (m[j][i] - m[i][j]) * root; + quat[k + 1] = (m[k][i] - m[i][k]) * root; + } + return Quaternion(quat[0], quat[1], quat[2], quat[3]); +} + +void Matrix3x3::scale(const Vector3 &scale_vec) +{ + Matrix3x3 smat( scale_vec.x, 0, 0, + 0, scale_vec.y, 0, + 0, 0, scale_vec.z); + *this *= smat; +} + +void Matrix3x3::set_scaling(const Vector3 &scale_vec) +{ + *this = Matrix3x3( scale_vec.x, 0, 0, + 0, scale_vec.y, 0, + 0, 0, scale_vec.z); +} + +void Matrix3x3::set_column_vector(const Vector3 &vec, unsigned int col_index) +{ + m[0][col_index] = vec.x; + m[1][col_index] = vec.y; + m[2][col_index] = vec.z; +} + +void Matrix3x3::set_row_vector(const Vector3 &vec, unsigned int row_index) +{ + m[row_index][0] = vec.x; + m[row_index][1] = vec.y; + m[row_index][2] = vec.z; +} + +Vector3 Matrix3x3::get_column_vector(unsigned int col_index) const +{ + return Vector3(m[0][col_index], m[1][col_index], m[2][col_index]); +} + +Vector3 Matrix3x3::get_row_vector(unsigned int row_index) const +{ + return Vector3(m[row_index][0], m[row_index][1], m[row_index][2]); +} + +void Matrix3x3::transpose() +{ + Matrix3x3 tmp = *this; + for(int i=0; i<3; i++) { + for(int j=0; j<3; j++) { + m[i][j] = tmp[j][i]; + } + } +} + +Matrix3x3 Matrix3x3::transposed() const +{ + Matrix3x3 res; + for(int i=0; i<3; i++) { + for(int j=0; j<3; j++) { + res[i][j] = m[j][i]; + } + } + return res; +} + +scalar_t Matrix3x3::determinant() const +{ + return m[0][0] * (m[1][1]*m[2][2] - m[1][2]*m[2][1]) - + m[0][1] * (m[1][0]*m[2][2] - m[1][2]*m[2][0]) + + m[0][2] * (m[1][0]*m[2][1] - m[1][1]*m[2][0]); +} + +Matrix3x3 Matrix3x3::inverse() const +{ + // TODO: implement 3x3 inverse + return *this; +} + +/*ostream &operator <<(ostream &out, const Matrix3x3 &mat) +{ + for(int i=0; i<3; i++) { + char str[100]; + sprintf(str, "[ %12.5f %12.5f %12.5f ]\n", (float)mat.m[i][0], (float)mat.m[i][1], (float)mat.m[i][2]); + out << str; + } + return out; +}*/ + + + +/* ----------------- Matrix4x4 implementation --------------- */ + +Matrix4x4 Matrix4x4::identity = Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + +Matrix4x4::Matrix4x4() +{ + *this = Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); +} + +Matrix4x4::Matrix4x4( scalar_t m11, scalar_t m12, scalar_t m13, scalar_t m14, + scalar_t m21, scalar_t m22, scalar_t m23, scalar_t m24, + scalar_t m31, scalar_t m32, scalar_t m33, scalar_t m34, + scalar_t m41, scalar_t m42, scalar_t m43, scalar_t m44) +{ + m[0][0] = m11; m[0][1] = m12; m[0][2] = m13; m[0][3] = m14; + m[1][0] = m21; m[1][1] = m22; m[1][2] = m23; m[1][3] = m24; + m[2][0] = m31; m[2][1] = m32; m[2][2] = m33; m[2][3] = m34; + m[3][0] = m41; m[3][1] = m42; m[3][2] = m43; m[3][3] = m44; +} + +Matrix4x4::Matrix4x4(const mat4_t cmat) +{ + memcpy(m, cmat, sizeof(mat4_t)); +} + +Matrix4x4::Matrix4x4(const Matrix3x3 &mat3x3) +{ + reset_identity(); + for(int i=0; i<3; i++) { + for(int j=0; j<3; j++) { + m[i][j] = mat3x3[i][j]; + } + } +} + +Matrix4x4 operator +(const Matrix4x4 &m1, const Matrix4x4 &m2) +{ + Matrix4x4 res; + const scalar_t *op1 = m1.m[0], *op2 = m2.m[0]; + scalar_t *dest = res.m[0]; + + for(int i=0; i<16; i++) { + *dest++ = *op1++ + *op2++; + } + return res; +} + +Matrix4x4 operator -(const Matrix4x4 &m1, const Matrix4x4 &m2) +{ + Matrix4x4 res; + const scalar_t *op1 = m1.m[0], *op2 = m2.m[0]; + scalar_t *dest = res.m[0]; + + for(int i=0; i<16; i++) { + *dest++ = *op1++ - *op2++; + } + return res; +} + +void operator +=(Matrix4x4 &m1, const Matrix4x4 &m2) +{ + scalar_t *op1 = m1.m[0]; + const scalar_t *op2 = m2.m[0]; + + for(int i=0; i<16; i++) { + *op1++ += *op2++; + } +} + +void operator -=(Matrix4x4 &m1, const Matrix4x4 &m2) +{ + scalar_t *op1 = m1.m[0]; + const scalar_t *op2 = m2.m[0]; + + for(int i=0; i<16; i++) { + *op1++ -= *op2++; + } +} + +Matrix4x4 operator *(const Matrix4x4 &mat, scalar_t scalar) +{ + Matrix4x4 res; + const scalar_t *mptr = mat.m[0]; + scalar_t *dptr = res.m[0]; + + for(int i=0; i<16; i++) { + *dptr++ = *mptr++ * scalar; + } + return res; +} + +Matrix4x4 operator *(scalar_t scalar, const Matrix4x4 &mat) +{ + Matrix4x4 res; + const scalar_t *mptr = mat.m[0]; + scalar_t *dptr = res.m[0]; + + for(int i=0; i<16; i++) { + *dptr++ = *mptr++ * scalar; + } + return res; +} + +void operator *=(Matrix4x4 &mat, scalar_t scalar) +{ + scalar_t *mptr = mat.m[0]; + + for(int i=0; i<16; i++) { + *mptr++ *= scalar; + } +} + +void Matrix4x4::translate(const Vector3 &trans) +{ + Matrix4x4 tmat(1, 0, 0, trans.x, 0, 1, 0, trans.y, 0, 0, 1, trans.z, 0, 0, 0, 1); + *this *= tmat; +} + +void Matrix4x4::set_translation(const Vector3 &trans) +{ + *this = Matrix4x4(1, 0, 0, trans.x, 0, 1, 0, trans.y, 0, 0, 1, trans.z, 0, 0, 0, 1); +} + +Vector3 Matrix4x4::get_translation() const +{ + return Vector3(m[0][3], m[1][3], m[2][3]); +} + +void Matrix4x4::rotate(const Vector3 &euler_angles) +{ + Matrix3x3 xrot, yrot, zrot; + + xrot = Matrix3x3( 1, 0, 0, + 0, cos(euler_angles.x), -sin(euler_angles.x), + 0, sin(euler_angles.x), cos(euler_angles.x)); + + yrot = Matrix3x3( cos(euler_angles.y), 0, sin(euler_angles.y), + 0, 1, 0, + -sin(euler_angles.y), 0, cos(euler_angles.y)); + + zrot = Matrix3x3( cos(euler_angles.z), -sin(euler_angles.z), 0, + sin(euler_angles.z), cos(euler_angles.z), 0, + 0, 0, 1); + + *this *= Matrix4x4(xrot * yrot * zrot); +} + +void Matrix4x4::set_rotation(const Vector3 &euler_angles) +{ + Matrix3x3 xrot, yrot, zrot; + + xrot = Matrix3x3( 1, 0, 0, + 0, cos(euler_angles.x), -sin(euler_angles.x), + 0, sin(euler_angles.x), cos(euler_angles.x)); + + yrot = Matrix3x3( cos(euler_angles.y), 0, sin(euler_angles.y), + 0, 1, 0, + -sin(euler_angles.y), 0, cos(euler_angles.y)); + + zrot = Matrix3x3( cos(euler_angles.z), -sin(euler_angles.z), 0, + sin(euler_angles.z), cos(euler_angles.z), 0, + 0, 0, 1); + + *this = Matrix4x4(xrot * yrot * zrot); +} + +void Matrix4x4::rotate(const Vector3 &axis, scalar_t angle) +{ + scalar_t sina = (scalar_t)sin(angle); + scalar_t cosa = (scalar_t)cos(angle); + scalar_t invcosa = 1-cosa; + scalar_t nxsq = axis.x * axis.x; + scalar_t nysq = axis.y * axis.y; + scalar_t nzsq = axis.z * axis.z; + + Matrix4x4 xform; + xform[0][0] = nxsq + (1-nxsq) * cosa; + xform[0][1] = axis.x * axis.y * invcosa - axis.z * sina; + xform[0][2] = axis.x * axis.z * invcosa + axis.y * sina; + xform[1][0] = axis.x * axis.y * invcosa + axis.z * sina; + xform[1][1] = nysq + (1-nysq) * cosa; + xform[1][2] = axis.y * axis.z * invcosa - axis.x * sina; + xform[2][0] = axis.x * axis.z * invcosa - axis.y * sina; + xform[2][1] = axis.y * axis.z * invcosa + axis.x * sina; + xform[2][2] = nzsq + (1-nzsq) * cosa; + + *this *= xform; +} + +void Matrix4x4::set_rotation(const Vector3 &axis, scalar_t angle) +{ + scalar_t sina = (scalar_t)sin(angle); + scalar_t cosa = (scalar_t)cos(angle); + scalar_t invcosa = 1-cosa; + scalar_t nxsq = axis.x * axis.x; + scalar_t nysq = axis.y * axis.y; + scalar_t nzsq = axis.z * axis.z; + + reset_identity(); + m[0][0] = nxsq + (1-nxsq) * cosa; + m[0][1] = axis.x * axis.y * invcosa - axis.z * sina; + m[0][2] = axis.x * axis.z * invcosa + axis.y * sina; + m[1][0] = axis.x * axis.y * invcosa + axis.z * sina; + m[1][1] = nysq + (1-nysq) * cosa; + m[1][2] = axis.y * axis.z * invcosa - axis.x * sina; + m[2][0] = axis.x * axis.z * invcosa - axis.y * sina; + m[2][1] = axis.y * axis.z * invcosa + axis.x * sina; + m[2][2] = nzsq + (1-nzsq) * cosa; +} + +void Matrix4x4::rotate(const Quaternion &quat) +{ + *this *= quat.get_rotation_matrix(); +} + +void Matrix4x4::set_rotation(const Quaternion &quat) +{ + *this = quat.get_rotation_matrix(); +} + +Quaternion Matrix4x4::get_rotation_quat() const +{ + Matrix3x3 mat3 = *this; + return mat3.get_rotation_quat(); +} + +void Matrix4x4::scale(const Vector4 &scale_vec) +{ + Matrix4x4 smat( scale_vec.x, 0, 0, 0, + 0, scale_vec.y, 0, 0, + 0, 0, scale_vec.z, 0, + 0, 0, 0, scale_vec.w); + *this *= smat; +} + +void Matrix4x4::set_scaling(const Vector4 &scale_vec) +{ + *this = Matrix4x4( scale_vec.x, 0, 0, 0, + 0, scale_vec.y, 0, 0, + 0, 0, scale_vec.z, 0, + 0, 0, 0, scale_vec.w); +} + +Vector3 Matrix4x4::get_scaling() const +{ + Vector3 vi = get_row_vector(0); + Vector3 vj = get_row_vector(1); + Vector3 vk = get_row_vector(2); + + return Vector3(vi.length(), vj.length(), vk.length()); +} + +void Matrix4x4::set_frustum(float left, float right, float bottom, float top, float znear, float zfar) +{ + float dx = right - left; + float dy = top - bottom; + float dz = zfar - znear; + + float a = (right + left) / dx; + float b = (top + bottom) / dy; + float c = -(zfar + znear) / dz; + float d = -2.0 * zfar * znear / dz; + + *this = Matrix4x4(2.0 * znear / dx, 0, a, 0, + 0, 2.0 * znear / dy, b, 0, + 0, 0, c, d, + 0, 0, -1, 0); +} + +void Matrix4x4::set_perspective(float vfov, float aspect, float znear, float zfar) +{ + float f = 1.0f / tan(vfov * 0.5f); + float dz = znear - zfar; + + reset_identity(); + + m[0][0] = f / aspect; + m[1][1] = f; + m[2][2] = (zfar + znear) / dz; + m[3][2] = -1.0f; + m[2][3] = 2.0f * zfar * znear / dz; + m[3][3] = 0.0f; +} + +void Matrix4x4::set_orthographic(float left, float right, float bottom, float top, float znear, float zfar) +{ + float dx = right - left; + float dy = top - bottom; + float dz = zfar - znear; + + reset_identity(); + + m[0][0] = 2.0 / dx; + m[1][1] = 2.0 / dy; + m[2][2] = -2.0 / dz; + m[0][3] = -(right + left) / dx; + m[1][3] = -(top + bottom) / dy; + m[2][3] = -(zfar + znear) / dz; +} + +void Matrix4x4::set_lookat(const Vector3 &pos, const Vector3 &targ, const Vector3 &up) +{ + Vector3 vk = (targ - pos).normalized(); + Vector3 vj = up.normalized(); + Vector3 vi = cross_product(vk, vj).normalized(); + vj = cross_product(vi, vk); + + *this = Matrix4x4( + vi.x, vi.y, vi.z, 0, + vj.x, vj.y, vj.z, 0, + -vk.x, -vk.y, -vk.z, 0, + 0, 0, 0, 1); + translate(-pos); +} + +void Matrix4x4::set_column_vector(const Vector4 &vec, unsigned int col_index) +{ + m[0][col_index] = vec.x; + m[1][col_index] = vec.y; + m[2][col_index] = vec.z; + m[3][col_index] = vec.w; +} + +void Matrix4x4::set_row_vector(const Vector4 &vec, unsigned int row_index) +{ + m[row_index][0] = vec.x; + m[row_index][1] = vec.y; + m[row_index][2] = vec.z; + m[row_index][3] = vec.w; +} + +Vector4 Matrix4x4::get_column_vector(unsigned int col_index) const +{ + return Vector4(m[0][col_index], m[1][col_index], m[2][col_index], m[3][col_index]); +} + +Vector4 Matrix4x4::get_row_vector(unsigned int row_index) const +{ + return Vector4(m[row_index][0], m[row_index][1], m[row_index][2], m[row_index][3]); +} + +void Matrix4x4::transpose() +{ + Matrix4x4 tmp = *this; + for(int i=0; i<4; i++) { + for(int j=0; j<4; j++) { + m[i][j] = tmp[j][i]; + } + } +} + +Matrix4x4 Matrix4x4::transposed() const +{ + Matrix4x4 res; + for(int i=0; i<4; i++) { + for(int j=0; j<4; j++) { + res[i][j] = m[j][i]; + } + } + return res; +} + +scalar_t Matrix4x4::determinant() const +{ + scalar_t det11 = (m[1][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[1][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) + + (m[1][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])); + + scalar_t det12 = (m[1][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[1][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[1][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])); + + scalar_t det13 = (m[1][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) - + (m[1][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[1][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + + scalar_t det14 = (m[1][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) - + (m[1][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) + + (m[1][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + + return m[0][0] * det11 - m[0][1] * det12 + m[0][2] * det13 - m[0][3] * det14; +} + + +Matrix4x4 Matrix4x4::adjoint() const +{ + Matrix4x4 coef; + + coef.m[0][0] = (m[1][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[1][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) + + (m[1][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])); + coef.m[0][1] = (m[1][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[1][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[1][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])); + coef.m[0][2] = (m[1][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) - + (m[1][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[1][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + coef.m[0][3] = (m[1][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) - + (m[1][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) + + (m[1][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + + coef.m[1][0] = (m[0][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[0][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) + + (m[0][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])); + coef.m[1][1] = (m[0][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[0][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[0][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])); + coef.m[1][2] = (m[0][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) - + (m[0][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[0][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + coef.m[1][3] = (m[0][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) - + (m[0][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) + + (m[0][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + + coef.m[2][0] = (m[0][1] * (m[1][2] * m[3][3] - m[3][2] * m[1][3])) - + (m[0][2] * (m[1][1] * m[3][3] - m[3][1] * m[1][3])) + + (m[0][3] * (m[1][1] * m[3][2] - m[3][1] * m[1][2])); + coef.m[2][1] = (m[0][0] * (m[1][2] * m[3][3] - m[3][2] * m[1][3])) - + (m[0][2] * (m[1][0] * m[3][3] - m[3][0] * m[1][3])) + + (m[0][3] * (m[1][0] * m[3][2] - m[3][0] * m[1][2])); + coef.m[2][2] = (m[0][0] * (m[1][1] * m[3][3] - m[3][1] * m[1][3])) - + (m[0][1] * (m[1][0] * m[3][3] - m[3][0] * m[1][3])) + + (m[0][3] * (m[1][0] * m[3][1] - m[3][0] * m[1][1])); + coef.m[2][3] = (m[0][0] * (m[1][1] * m[3][2] - m[3][1] * m[1][2])) - + (m[0][1] * (m[1][0] * m[3][2] - m[3][0] * m[1][2])) + + (m[0][2] * (m[1][0] * m[3][1] - m[3][0] * m[1][1])); + + coef.m[3][0] = (m[0][1] * (m[1][2] * m[2][3] - m[2][2] * m[1][3])) - + (m[0][2] * (m[1][1] * m[2][3] - m[2][1] * m[1][3])) + + (m[0][3] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])); + coef.m[3][1] = (m[0][0] * (m[1][2] * m[2][3] - m[2][2] * m[1][3])) - + (m[0][2] * (m[1][0] * m[2][3] - m[2][0] * m[1][3])) + + (m[0][3] * (m[1][0] * m[2][2] - m[2][0] * m[1][2])); + coef.m[3][2] = (m[0][0] * (m[1][1] * m[2][3] - m[2][1] * m[1][3])) - + (m[0][1] * (m[1][0] * m[2][3] - m[2][0] * m[1][3])) + + (m[0][3] * (m[1][0] * m[2][1] - m[2][0] * m[1][1])); + coef.m[3][3] = (m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])) - + (m[0][1] * (m[1][0] * m[2][2] - m[2][0] * m[1][2])) + + (m[0][2] * (m[1][0] * m[2][1] - m[2][0] * m[1][1])); + + coef.transpose(); + + for(int i=0; i<4; i++) { + for(int j=0; j<4; j++) { + coef.m[i][j] = j%2 ? -coef.m[i][j] : coef.m[i][j]; + if(i%2) coef.m[i][j] = -coef.m[i][j]; + } + } + + return coef; +} + +Matrix4x4 Matrix4x4::inverse() const +{ + Matrix4x4 adj = adjoint(); + + return adj * (1.0f / determinant()); +} + +/* +ostream &operator <<(ostream &out, const Matrix4x4 &mat) +{ + for(int i=0; i<4; i++) { + char str[100]; + sprintf(str, "[ %12.5f %12.5f %12.5f %12.5f ]\n", (float)mat.m[i][0], (float)mat.m[i][1], (float)mat.m[i][2], (float)mat.m[i][3]); + out << str; + } + return out; +} +*/ diff -r d1b456d08713 -r c71c477521ca libs/vmath/matrix.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/matrix.h Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,255 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 VMATH_MATRIX_H_ +#define VMATH_MATRIX_H_ + +#include +#include "vmath_types.h" +#include "vector.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* C matrix 3x3 functions */ +static inline void m3_identity(mat3_t m); +static inline void m3_cons(mat3_t m, + scalar_t m11, scalar_t m12, scalar_t m13, + scalar_t m21, scalar_t m22, scalar_t m23, + scalar_t m31, scalar_t m32, scalar_t m33); +static inline void m3_copy(mat3_t dest, mat3_t src); +void m3_to_m4(mat4_t dest, mat3_t src); + +void m3_print(FILE *fp, mat3_t m); + +/* C matrix 4x4 functions */ +static inline void m4_identity(mat4_t m); +static inline void m4_cons(mat4_t m, + scalar_t m11, scalar_t m12, scalar_t m13, scalar_t m14, + scalar_t m21, scalar_t m22, scalar_t m23, scalar_t m24, + scalar_t m31, scalar_t m32, scalar_t m33, scalar_t m34, + scalar_t m41, scalar_t m42, scalar_t m43, scalar_t m44); +static inline void m4_copy(mat4_t dest, mat4_t src); +void m4_to_m3(mat3_t dest, mat4_t src); + +static inline void m4_mult(mat4_t res, mat4_t m1, mat4_t m2); + +void m4_set_translation(mat4_t m, scalar_t x, scalar_t y, scalar_t z); +void m4_translate(mat4_t m, scalar_t x, scalar_t y, scalar_t z); + +void m4_rotate(mat4_t m, scalar_t x, scalar_t y, scalar_t z); + +void m4_set_rotation_x(mat4_t m, scalar_t angle); +void m4_rotate_x(mat4_t m, scalar_t angle); +void m4_set_rotation_y(mat4_t m, scalar_t angle); +void m4_rotate_y(mat4_t m, scalar_t angle); +void m4_set_rotation_z(mat4_t m, scalar_t angle); +void m4_rotate_z(mat4_t m, scalar_t angle); +/* axis-angle rotation */ +void m4_set_rotation_axis(mat4_t m, scalar_t angle, scalar_t x, scalar_t y, scalar_t z); +void m4_rotate_axis(mat4_t m, scalar_t angle, scalar_t x, scalar_t y, scalar_t z); +/* concatentate a rotation quaternion */ +void m4_rotate_quat(mat4_t m, quat_t q); + +void m4_set_scaling(mat4_t m, scalar_t x, scalar_t y, scalar_t z); +void m4_scale(mat4_t m, scalar_t x, scalar_t y, scalar_t z); + +static inline void m4_set_column(mat4_t m, vec4_t v, int idx); +static inline void m4_set_row(mat4_t m, vec4_t v, int idx); + +void m4_transpose(mat4_t res, mat4_t m); +scalar_t m4_determinant(mat4_t m); +void m4_adjoint(mat4_t res, mat4_t m); +void m4_inverse(mat4_t res, mat4_t m); + +void m4_print(FILE *fp, mat4_t m); + +#ifdef __cplusplus +} + +/* when included from C++ source files, also define the matrix classes */ + +/** 3x3 matrix */ +class Matrix3x3 { +public: + scalar_t m[3][3]; + + static Matrix3x3 identity; + + Matrix3x3(); + Matrix3x3( scalar_t m11, scalar_t m12, scalar_t m13, + scalar_t m21, scalar_t m22, scalar_t m23, + scalar_t m31, scalar_t m32, scalar_t m33); + Matrix3x3(const Vector3 &ivec, const Vector3 &jvec, const Vector3 &kvec); + Matrix3x3(const mat3_t cmat); + + Matrix3x3(const Matrix4x4 &mat4x4); + + /* binary operations matrix (op) matrix */ + friend Matrix3x3 operator +(const Matrix3x3 &m1, const Matrix3x3 &m2); + friend Matrix3x3 operator -(const Matrix3x3 &m1, const Matrix3x3 &m2); + friend Matrix3x3 operator *(const Matrix3x3 &m1, const Matrix3x3 &m2); + + friend void operator +=(Matrix3x3 &m1, const Matrix3x3 &m2); + friend void operator -=(Matrix3x3 &m1, const Matrix3x3 &m2); + friend void operator *=(Matrix3x3 &m1, const Matrix3x3 &m2); + + /* binary operations matrix (op) scalar and scalar (op) matrix */ + friend Matrix3x3 operator *(const Matrix3x3 &mat, scalar_t scalar); + friend Matrix3x3 operator *(scalar_t scalar, const Matrix3x3 &mat); + + friend void operator *=(Matrix3x3 &mat, scalar_t scalar); + + inline scalar_t *operator [](int index); + inline const scalar_t *operator [](int index) const; + + inline void reset_identity(); + + void translate(const Vector2 &trans); + void set_translation(const Vector2 &trans); + + void rotate(scalar_t angle); /* 2d rotation */ + void rotate(const Vector3 &euler_angles); /* 3d rotation with euler angles */ + void rotate(const Vector3 &axis, scalar_t angle); /* 3d axis/angle rotation */ + void set_rotation(scalar_t angle); + void set_rotation(const Vector3 &euler_angles); + void set_rotation(const Vector3 &axis, scalar_t angle); + Quaternion get_rotation_quat() const; + + void scale(const Vector3 &scale_vec); + void set_scaling(const Vector3 &scale_vec); + + void set_column_vector(const Vector3 &vec, unsigned int col_index); + void set_row_vector(const Vector3 &vec, unsigned int row_index); + Vector3 get_column_vector(unsigned int col_index) const; + Vector3 get_row_vector(unsigned int row_index) const; + + void transpose(); + Matrix3x3 transposed() const; + scalar_t determinant() const; + Matrix3x3 inverse() const; +}; + +/* binary operations matrix (op) matrix */ +Matrix3x3 operator +(const Matrix3x3 &m1, const Matrix3x3 &m2); +Matrix3x3 operator -(const Matrix3x3 &m1, const Matrix3x3 &m2); +Matrix3x3 operator *(const Matrix3x3 &m1, const Matrix3x3 &m2); + +void operator +=(Matrix3x3 &m1, const Matrix3x3 &m2); +void operator -=(Matrix3x3 &m1, const Matrix3x3 &m2); +void operator *=(Matrix3x3 &m1, const Matrix3x3 &m2); + +/* binary operations matrix (op) scalar and scalar (op) matrix */ +Matrix3x3 operator *(const Matrix3x3 &mat, scalar_t scalar); +Matrix3x3 operator *(scalar_t scalar, const Matrix3x3 &mat); + +void operator *=(Matrix3x3 &mat, scalar_t scalar); + + + +/** 4x4 matrix */ +class Matrix4x4 { +public: + scalar_t m[4][4]; + + static Matrix4x4 identity; + + Matrix4x4(); + Matrix4x4( scalar_t m11, scalar_t m12, scalar_t m13, scalar_t m14, + scalar_t m21, scalar_t m22, scalar_t m23, scalar_t m24, + scalar_t m31, scalar_t m32, scalar_t m33, scalar_t m34, + scalar_t m41, scalar_t m42, scalar_t m43, scalar_t m44); + Matrix4x4(const mat4_t cmat); + + Matrix4x4(const Matrix3x3 &mat3x3); + + /* binary operations matrix (op) matrix */ + friend Matrix4x4 operator +(const Matrix4x4 &m1, const Matrix4x4 &m2); + friend Matrix4x4 operator -(const Matrix4x4 &m1, const Matrix4x4 &m2); + friend Matrix4x4 operator *(const Matrix4x4 &m1, const Matrix4x4 &m2); + + friend void operator +=(Matrix4x4 &m1, const Matrix4x4 &m2); + friend void operator -=(Matrix4x4 &m1, const Matrix4x4 &m2); + friend inline void operator *=(Matrix4x4 &m1, const Matrix4x4 &m2); + + /* binary operations matrix (op) scalar and scalar (op) matrix */ + friend Matrix4x4 operator *(const Matrix4x4 &mat, scalar_t scalar); + friend Matrix4x4 operator *(scalar_t scalar, const Matrix4x4 &mat); + + friend void operator *=(Matrix4x4 &mat, scalar_t scalar); + + inline scalar_t *operator [](int index); + inline const scalar_t *operator [](int index) const; + + inline void reset_identity(); + + void translate(const Vector3 &trans); + void set_translation(const Vector3 &trans); + Vector3 get_translation() const; /* extract translation */ + + void rotate(const Vector3 &euler_angles); /* 3d rotation with euler angles */ + void rotate(const Vector3 &axis, scalar_t angle); /* 3d axis/angle rotation */ + void rotate(const Quaternion &quat); + void set_rotation(const Vector3 &euler_angles); + void set_rotation(const Vector3 &axis, scalar_t angle); + void set_rotation(const Quaternion &quat); + Quaternion get_rotation_quat() const; /* extract rotation */ + + void scale(const Vector4 &scale_vec); + void set_scaling(const Vector4 &scale_vec); + Vector3 get_scaling() const; /* extract scaling */ + + void set_frustum(float left, float right, float top, float bottom, float znear, float zfar); + void set_perspective(float vfov, float aspect, float znear, float zfar); + void set_orthographic(float left, float right, float bottom, float top, float znear = -1.0, float zfar = 1.0); + + void set_lookat(const Vector3 &pos, const Vector3 &targ = Vector3(0, 0, 0), const Vector3 &up = Vector3(0, 1, 0)); + + void set_column_vector(const Vector4 &vec, unsigned int col_index); + void set_row_vector(const Vector4 &vec, unsigned int row_index); + Vector4 get_column_vector(unsigned int col_index) const; + Vector4 get_row_vector(unsigned int row_index) const; + + void transpose(); + Matrix4x4 transposed() const; + scalar_t determinant() const; + Matrix4x4 adjoint() const; + Matrix4x4 inverse() const; +}; + +/* binary operations matrix (op) matrix */ +Matrix4x4 operator +(const Matrix4x4 &m1, const Matrix4x4 &m2); +Matrix4x4 operator -(const Matrix4x4 &m1, const Matrix4x4 &m2); +inline Matrix4x4 operator *(const Matrix4x4 &m1, const Matrix4x4 &m2); + +void operator +=(Matrix4x4 &m1, const Matrix4x4 &m2); +void operator -=(Matrix4x4 &m1, const Matrix4x4 &m2); +inline void operator *=(Matrix4x4 &m1, const Matrix4x4 &m2); + +/* binary operations matrix (op) scalar and scalar (op) matrix */ +Matrix4x4 operator *(const Matrix4x4 &mat, scalar_t scalar); +Matrix4x4 operator *(scalar_t scalar, const Matrix4x4 &mat); + +void operator *=(Matrix4x4 &mat, scalar_t scalar); + +#endif /* __cplusplus */ + +#include "matrix.inl" + +#endif /* VMATH_MATRIX_H_ */ diff -r d1b456d08713 -r c71c477521ca libs/vmath/matrix.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/matrix.inl Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,200 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* C matrix 3x3 functions */ +static inline void m3_identity(mat3_t m) +{ + static const mat3_t id = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + memcpy(m, id, sizeof id); +} + +static inline void m3_cons(mat3_t m, + scalar_t m11, scalar_t m12, scalar_t m13, + scalar_t m21, scalar_t m22, scalar_t m23, + scalar_t m31, scalar_t m32, scalar_t m33) +{ + m[0][0] = m11; m[0][1] = m12; m[0][2] = m13; + m[1][0] = m21; m[1][1] = m22; m[1][2] = m23; + m[2][0] = m31; m[2][1] = m32; m[2][2] = m33; +} + +static inline void m3_copy(mat3_t dest, mat3_t src) +{ + memcpy(dest, src, sizeof(mat3_t)); +} + + +/* C matrix 4x4 functions */ +static inline void m4_identity(mat4_t m) +{ + static const mat4_t id = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}; + memcpy(m, id, sizeof id); +} + +static inline void m4_cons(mat4_t m, + scalar_t m11, scalar_t m12, scalar_t m13, scalar_t m14, + scalar_t m21, scalar_t m22, scalar_t m23, scalar_t m24, + scalar_t m31, scalar_t m32, scalar_t m33, scalar_t m34, + scalar_t m41, scalar_t m42, scalar_t m43, scalar_t m44) +{ + m[0][0] = m11; m[0][1] = m12; m[0][2] = m13; m[0][3] = m14; + m[1][0] = m21; m[1][1] = m22; m[1][2] = m23; m[1][3] = m24; + m[2][0] = m31; m[2][1] = m32; m[2][2] = m33; m[2][3] = m34; + m[3][0] = m41; m[3][1] = m42; m[3][2] = m43; m[3][3] = m44; +} + +static inline void m4_copy(mat4_t dest, mat4_t src) +{ + memcpy(dest, src, sizeof(mat4_t)); +} + +static inline void m4_mult(mat4_t res, mat4_t m1, mat4_t m2) +{ + mat4_t tmp; + + /* + int i, j; + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + tmp[i][j] = m1[i][0] * m2[0][j] + m1[i][1] * m2[1][j] + m1[i][2] * m2[2][j] + m1[i][3] * m2[3][j]; + } + } + */ + + tmp[0][0] = m1[0][0] * m2[0][0] + m1[0][1] * m2[1][0] + m1[0][2] * m2[2][0] + m1[0][3] * m2[3][0]; + tmp[0][1] = m1[0][0] * m2[0][1] + m1[0][1] * m2[1][1] + m1[0][2] * m2[2][1] + m1[0][3] * m2[3][1]; + tmp[0][2] = m1[0][0] * m2[0][2] + m1[0][1] * m2[1][2] + m1[0][2] * m2[2][2] + m1[0][3] * m2[3][2]; + tmp[0][3] = m1[0][0] * m2[0][3] + m1[0][1] * m2[1][3] + m1[0][2] * m2[2][3] + m1[0][3] * m2[3][3]; + + tmp[1][0] = m1[1][0] * m2[0][0] + m1[1][1] * m2[1][0] + m1[1][2] * m2[2][0] + m1[1][3] * m2[3][0]; + tmp[1][1] = m1[1][0] * m2[0][1] + m1[1][1] * m2[1][1] + m1[1][2] * m2[2][1] + m1[1][3] * m2[3][1]; + tmp[1][2] = m1[1][0] * m2[0][2] + m1[1][1] * m2[1][2] + m1[1][2] * m2[2][2] + m1[1][3] * m2[3][2]; + tmp[1][3] = m1[1][0] * m2[0][3] + m1[1][1] * m2[1][3] + m1[1][2] * m2[2][3] + m1[1][3] * m2[3][3]; + + tmp[2][0] = m1[2][0] * m2[0][0] + m1[2][1] * m2[1][0] + m1[2][2] * m2[2][0] + m1[2][3] * m2[3][0]; + tmp[2][1] = m1[2][0] * m2[0][1] + m1[2][1] * m2[1][1] + m1[2][2] * m2[2][1] + m1[2][3] * m2[3][1]; + tmp[2][2] = m1[2][0] * m2[0][2] + m1[2][1] * m2[1][2] + m1[2][2] * m2[2][2] + m1[2][3] * m2[3][2]; + tmp[2][3] = m1[2][0] * m2[0][3] + m1[2][1] * m2[1][3] + m1[2][2] * m2[2][3] + m1[2][3] * m2[3][3]; + + tmp[3][0] = m1[3][0] * m2[0][0] + m1[3][1] * m2[1][0] + m1[3][2] * m2[2][0] + m1[3][3] * m2[3][0]; + tmp[3][1] = m1[3][0] * m2[0][1] + m1[3][1] * m2[1][1] + m1[3][2] * m2[2][1] + m1[3][3] * m2[3][1]; + tmp[3][2] = m1[3][0] * m2[0][2] + m1[3][1] * m2[1][2] + m1[3][2] * m2[2][2] + m1[3][3] * m2[3][2]; + tmp[3][3] = m1[3][0] * m2[0][3] + m1[3][1] * m2[1][3] + m1[3][2] * m2[2][3] + m1[3][3] * m2[3][3]; + + m4_copy(res, tmp); +} + +static inline void m4_set_column(mat4_t m, vec4_t v, int idx) +{ + m[0][idx] = v.x; + m[1][idx] = v.y; + m[2][idx] = v.z; + m[3][idx] = v.w; +} + +static inline void m4_set_row(mat4_t m, vec4_t v, int idx) +{ + m[idx][0] = v.x; + m[idx][1] = v.y; + m[idx][2] = v.z; + m[idx][3] = v.w; +} + +#ifdef __cplusplus +} /* extern "C" */ + + +/* unrolled to hell and inline */ +inline Matrix4x4 operator *(const Matrix4x4 &m1, const Matrix4x4 &m2) +{ + Matrix4x4 res; + + /* + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + res.m[i][j] = m1.m[i][0] * m2.m[0][j] + m1.m[i][1] * m2.m[1][j] + m1.m[i][2] * m2.m[2][j] + m1.m[i][3] * m2.m[3][j]; + } + } + */ + + res.m[0][0] = m1.m[0][0] * m2.m[0][0] + m1.m[0][1] * m2.m[1][0] + m1.m[0][2] * m2.m[2][0] + m1.m[0][3] * m2.m[3][0]; + res.m[0][1] = m1.m[0][0] * m2.m[0][1] + m1.m[0][1] * m2.m[1][1] + m1.m[0][2] * m2.m[2][1] + m1.m[0][3] * m2.m[3][1]; + res.m[0][2] = m1.m[0][0] * m2.m[0][2] + m1.m[0][1] * m2.m[1][2] + m1.m[0][2] * m2.m[2][2] + m1.m[0][3] * m2.m[3][2]; + res.m[0][3] = m1.m[0][0] * m2.m[0][3] + m1.m[0][1] * m2.m[1][3] + m1.m[0][2] * m2.m[2][3] + m1.m[0][3] * m2.m[3][3]; + + res.m[1][0] = m1.m[1][0] * m2.m[0][0] + m1.m[1][1] * m2.m[1][0] + m1.m[1][2] * m2.m[2][0] + m1.m[1][3] * m2.m[3][0]; + res.m[1][1] = m1.m[1][0] * m2.m[0][1] + m1.m[1][1] * m2.m[1][1] + m1.m[1][2] * m2.m[2][1] + m1.m[1][3] * m2.m[3][1]; + res.m[1][2] = m1.m[1][0] * m2.m[0][2] + m1.m[1][1] * m2.m[1][2] + m1.m[1][2] * m2.m[2][2] + m1.m[1][3] * m2.m[3][2]; + res.m[1][3] = m1.m[1][0] * m2.m[0][3] + m1.m[1][1] * m2.m[1][3] + m1.m[1][2] * m2.m[2][3] + m1.m[1][3] * m2.m[3][3]; + + res.m[2][0] = m1.m[2][0] * m2.m[0][0] + m1.m[2][1] * m2.m[1][0] + m1.m[2][2] * m2.m[2][0] + m1.m[2][3] * m2.m[3][0]; + res.m[2][1] = m1.m[2][0] * m2.m[0][1] + m1.m[2][1] * m2.m[1][1] + m1.m[2][2] * m2.m[2][1] + m1.m[2][3] * m2.m[3][1]; + res.m[2][2] = m1.m[2][0] * m2.m[0][2] + m1.m[2][1] * m2.m[1][2] + m1.m[2][2] * m2.m[2][2] + m1.m[2][3] * m2.m[3][2]; + res.m[2][3] = m1.m[2][0] * m2.m[0][3] + m1.m[2][1] * m2.m[1][3] + m1.m[2][2] * m2.m[2][3] + m1.m[2][3] * m2.m[3][3]; + + res.m[3][0] = m1.m[3][0] * m2.m[0][0] + m1.m[3][1] * m2.m[1][0] + m1.m[3][2] * m2.m[2][0] + m1.m[3][3] * m2.m[3][0]; + res.m[3][1] = m1.m[3][0] * m2.m[0][1] + m1.m[3][1] * m2.m[1][1] + m1.m[3][2] * m2.m[2][1] + m1.m[3][3] * m2.m[3][1]; + res.m[3][2] = m1.m[3][0] * m2.m[0][2] + m1.m[3][1] * m2.m[1][2] + m1.m[3][2] * m2.m[2][2] + m1.m[3][3] * m2.m[3][2]; + res.m[3][3] = m1.m[3][0] * m2.m[0][3] + m1.m[3][1] * m2.m[1][3] + m1.m[3][2] * m2.m[2][3] + m1.m[3][3] * m2.m[3][3]; + + return res; +} + +inline void operator *=(Matrix4x4 &m1, const Matrix4x4 &m2) +{ + Matrix4x4 res = m1 * m2; + m1 = res; +} + + +inline scalar_t *Matrix3x3::operator [](int index) +{ + return m[index]; +} + +inline const scalar_t *Matrix3x3::operator [](int index) const +{ + return m[index]; +} + +inline void Matrix3x3::reset_identity() +{ + *this = identity; +} + +inline scalar_t *Matrix4x4::operator [](int index) +{ + return m[index]; +} + +inline const scalar_t *Matrix4x4::operator [](int index) const +{ + return m[index]; +} + +inline void Matrix4x4::reset_identity() +{ + *this = identity; +} +#endif /* __cplusplus */ diff -r d1b456d08713 -r c71c477521ca libs/vmath/matrix_c.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/matrix_c.c Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,292 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 "matrix.h" +#include "vector.h" +#include "quat.h" + +void m3_to_m4(mat4_t dest, mat3_t src) +{ + int i, j; + + memset(dest, 0, sizeof(mat4_t)); + for(i=0; i<3; i++) { + for(j=0; j<3; j++) { + dest[i][j] = src[i][j]; + } + } + dest[3][3] = 1.0; +} + +void m3_print(FILE *fp, mat3_t m) +{ + int i; + for(i=0; i<3; i++) { + fprintf(fp, "[ %12.5f %12.5f %12.5f ]\n", (float)m[i][0], (float)m[i][1], (float)m[i][2]); + } +} + +/* C matrix 4x4 functions */ +void m4_to_m3(mat3_t dest, mat4_t src) +{ + int i, j; + for(i=0; i<3; i++) { + for(j=0; j<3; j++) { + dest[i][j] = src[i][j]; + } + } +} + +void m4_set_translation(mat4_t m, scalar_t x, scalar_t y, scalar_t z) +{ + m4_identity(m); + m[0][3] = x; + m[1][3] = y; + m[2][3] = z; +} + +void m4_translate(mat4_t m, scalar_t x, scalar_t y, scalar_t z) +{ + mat4_t tm; + m4_set_translation(tm, x, y, z); + m4_mult(m, m, tm); +} + +void m4_rotate(mat4_t m, scalar_t x, scalar_t y, scalar_t z) +{ + m4_rotate_x(m, x); + m4_rotate_y(m, y); + m4_rotate_z(m, z); +} + +void m4_set_rotation_x(mat4_t m, scalar_t angle) +{ + m4_identity(m); + m[1][1] = cos(angle); m[1][2] = -sin(angle); + m[2][1] = sin(angle); m[2][2] = cos(angle); +} + +void m4_rotate_x(mat4_t m, scalar_t angle) +{ + mat4_t rm; + m4_set_rotation_x(rm, angle); + m4_mult(m, m, rm); +} + +void m4_set_rotation_y(mat4_t m, scalar_t angle) +{ + m4_identity(m); + m[0][0] = cos(angle); m[0][2] = sin(angle); + m[2][0] = -sin(angle); m[2][2] = cos(angle); +} + +void m4_rotate_y(mat4_t m, scalar_t angle) +{ + mat4_t rm; + m4_set_rotation_y(rm, angle); + m4_mult(m, m, rm); +} + +void m4_set_rotation_z(mat4_t m, scalar_t angle) +{ + m4_identity(m); + m[0][0] = cos(angle); m[0][1] = -sin(angle); + m[1][0] = sin(angle); m[1][1] = cos(angle); +} + +void m4_rotate_z(mat4_t m, scalar_t angle) +{ + mat4_t rm; + m4_set_rotation_z(rm, angle); + m4_mult(m, m, rm); +} + +void m4_set_rotation_axis(mat4_t m, scalar_t angle, scalar_t x, scalar_t y, scalar_t z) +{ + scalar_t sina = sin(angle); + scalar_t cosa = cos(angle); + scalar_t one_minus_cosa = 1.0 - cosa; + scalar_t nxsq = x * x; + scalar_t nysq = y * y; + scalar_t nzsq = z * z; + + m[0][0] = nxsq + (1.0 - nxsq) * cosa; + m[0][1] = x * y * one_minus_cosa - z * sina; + m[0][2] = x * z * one_minus_cosa + y * sina; + m[1][0] = x * y * one_minus_cosa + z * sina; + m[1][1] = nysq + (1.0 - nysq) * cosa; + m[1][2] = y * z * one_minus_cosa - x * sina; + m[2][0] = x * z * one_minus_cosa - y * sina; + m[2][1] = y * z * one_minus_cosa + x * sina; + m[2][2] = nzsq + (1.0 - nzsq) * cosa; + + /* the rest are identity */ + m[3][0] = m[3][1] = m[3][2] = m[0][3] = m[1][3] = m[2][3] = 0.0; + m[3][3] = 1.0; +} + +void m4_rotate_axis(mat4_t m, scalar_t angle, scalar_t x, scalar_t y, scalar_t z) +{ + mat4_t xform; + m4_set_rotation_axis(xform, angle, x, y, z); + m4_mult(m, m, xform); +} + +void m4_rotate_quat(mat4_t m, quat_t q) +{ + mat4_t rm; + quat_to_mat4(rm, q); + m4_mult(m, m, rm); +} + +void m4_scale(mat4_t m, scalar_t x, scalar_t y, scalar_t z) +{ + mat4_t sm; + m4_identity(sm); + sm[0][0] = x; + sm[1][1] = y; + sm[2][2] = z; + m4_mult(m, m, sm); +} + +void m4_transpose(mat4_t res, mat4_t m) +{ + int i, j; + mat4_t tmp; + m4_copy(tmp, m); + + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + res[i][j] = tmp[j][i]; + } + } +} + +scalar_t m4_determinant(mat4_t m) +{ + scalar_t det11 = (m[1][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[1][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) + + (m[1][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])); + + scalar_t det12 = (m[1][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[1][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[1][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])); + + scalar_t det13 = (m[1][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) - + (m[1][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[1][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + + scalar_t det14 = (m[1][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) - + (m[1][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) + + (m[1][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + + return m[0][0] * det11 - m[0][1] * det12 + m[0][2] * det13 - m[0][3] * det14; +} + +void m4_adjoint(mat4_t res, mat4_t m) +{ + int i, j; + mat4_t coef; + + coef[0][0] = (m[1][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[1][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) + + (m[1][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])); + coef[0][1] = (m[1][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[1][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[1][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])); + coef[0][2] = (m[1][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) - + (m[1][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[1][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + coef[0][3] = (m[1][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) - + (m[1][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) + + (m[1][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + + coef[1][0] = (m[0][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[0][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) + + (m[0][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])); + coef[1][1] = (m[0][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[0][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[0][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])); + coef[1][2] = (m[0][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) - + (m[0][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[0][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + coef[1][3] = (m[0][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) - + (m[0][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) + + (m[0][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + + coef[2][0] = (m[0][1] * (m[1][2] * m[3][3] - m[3][2] * m[1][3])) - + (m[0][2] * (m[1][1] * m[3][3] - m[3][1] * m[1][3])) + + (m[0][3] * (m[1][1] * m[3][2] - m[3][1] * m[1][2])); + coef[2][1] = (m[0][0] * (m[1][2] * m[3][3] - m[3][2] * m[1][3])) - + (m[0][2] * (m[1][0] * m[3][3] - m[3][0] * m[1][3])) + + (m[0][3] * (m[1][0] * m[3][2] - m[3][0] * m[1][2])); + coef[2][2] = (m[0][0] * (m[1][1] * m[3][3] - m[3][1] * m[1][3])) - + (m[0][1] * (m[1][0] * m[3][3] - m[3][0] * m[1][3])) + + (m[0][3] * (m[1][0] * m[3][1] - m[3][0] * m[1][1])); + coef[2][3] = (m[0][0] * (m[1][1] * m[3][2] - m[3][1] * m[1][2])) - + (m[0][1] * (m[1][0] * m[3][2] - m[3][0] * m[1][2])) + + (m[0][2] * (m[1][0] * m[3][1] - m[3][0] * m[1][1])); + + coef[3][0] = (m[0][1] * (m[1][2] * m[2][3] - m[2][2] * m[1][3])) - + (m[0][2] * (m[1][1] * m[2][3] - m[2][1] * m[1][3])) + + (m[0][3] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])); + coef[3][1] = (m[0][0] * (m[1][2] * m[2][3] - m[2][2] * m[1][3])) - + (m[0][2] * (m[1][0] * m[2][3] - m[2][0] * m[1][3])) + + (m[0][3] * (m[1][0] * m[2][2] - m[2][0] * m[1][2])); + coef[3][2] = (m[0][0] * (m[1][1] * m[2][3] - m[2][1] * m[1][3])) - + (m[0][1] * (m[1][0] * m[2][3] - m[2][0] * m[1][3])) + + (m[0][3] * (m[1][0] * m[2][1] - m[2][0] * m[1][1])); + coef[3][3] = (m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])) - + (m[0][1] * (m[1][0] * m[2][2] - m[2][0] * m[1][2])) + + (m[0][2] * (m[1][0] * m[2][1] - m[2][0] * m[1][1])); + + m4_transpose(res, coef); + + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + res[i][j] = j % 2 ? -res[i][j] : res[i][j]; + if(i % 2) res[i][j] = -res[i][j]; + } + } +} + +void m4_inverse(mat4_t res, mat4_t m) +{ + int i, j; + mat4_t adj; + scalar_t det; + + m4_adjoint(adj, m); + det = m4_determinant(m); + + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + res[i][j] = adj[i][j] / det; + } + } +} + +void m4_print(FILE *fp, mat4_t m) +{ + int i; + for(i=0; i<4; i++) { + fprintf(fp, "[ %12.5f %12.5f %12.5f %12.5f ]\n", (float)m[i][0], (float)m[i][1], (float)m[i][2], (float)m[i][3]); + } +} diff -r d1b456d08713 -r c71c477521ca libs/vmath/quat.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/quat.cc Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,229 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 "quat.h" +#include "vmath.h" + +Quaternion::Quaternion() +{ + s = 1.0; + v.x = v.y = v.z = 0.0; +} + +Quaternion::Quaternion(scalar_t s, const Vector3 &v) +{ + this->s = s; + this->v = v; +} + +Quaternion::Quaternion(scalar_t s, scalar_t x, scalar_t y, scalar_t z) +{ + v.x = x; + v.y = y; + v.z = z; + this->s = s; +} + +Quaternion::Quaternion(const Vector3 &axis, scalar_t angle) +{ + set_rotation(axis, angle); +} + +Quaternion::Quaternion(const quat_t &quat) +{ + v.x = quat.x; + v.y = quat.y; + v.z = quat.z; + s = quat.w; +} + +Quaternion Quaternion::operator +(const Quaternion &quat) const +{ + return Quaternion(s + quat.s, v + quat.v); +} + +Quaternion Quaternion::operator -(const Quaternion &quat) const +{ + return Quaternion(s - quat.s, v - quat.v); +} + +Quaternion Quaternion::operator -() const +{ + return Quaternion(-s, -v); +} + +/** Quaternion Multiplication: + * Q1*Q2 = [s1*s2 - v1.v2, s1*v2 + s2*v1 + v1(x)v2] + */ +Quaternion Quaternion::operator *(const Quaternion &quat) const +{ + Quaternion newq; + newq.s = s * quat.s - dot_product(v, quat.v); + newq.v = quat.v * s + v * quat.s + cross_product(v, quat.v); + return newq; +} + +void Quaternion::operator +=(const Quaternion &quat) +{ + *this = Quaternion(s + quat.s, v + quat.v); +} + +void Quaternion::operator -=(const Quaternion &quat) +{ + *this = Quaternion(s - quat.s, v - quat.v); +} + +void Quaternion::operator *=(const Quaternion &quat) +{ + *this = *this * quat; +} + +void Quaternion::reset_identity() +{ + s = 1.0; + v.x = v.y = v.z = 0.0; +} + +Quaternion Quaternion::conjugate() const +{ + return Quaternion(s, -v); +} + +scalar_t Quaternion::length() const +{ + return (scalar_t)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s); +} + +/** Q * ~Q = ||Q||^2 */ +scalar_t Quaternion::length_sq() const +{ + return v.x*v.x + v.y*v.y + v.z*v.z + s*s; +} + +void Quaternion::normalize() +{ + scalar_t len = (scalar_t)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s); + v.x /= len; + v.y /= len; + v.z /= len; + s /= len; +} + +Quaternion Quaternion::normalized() const +{ + Quaternion nq = *this; + scalar_t len = (scalar_t)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s); + nq.v.x /= len; + nq.v.y /= len; + nq.v.z /= len; + nq.s /= len; + return nq; +} + +/** Quaternion Inversion: Q^-1 = ~Q / ||Q||^2 */ +Quaternion Quaternion::inverse() const +{ + Quaternion inv = conjugate(); + scalar_t lensq = length_sq(); + inv.v /= lensq; + inv.s /= lensq; + + return inv; +} + + +void Quaternion::set_rotation(const Vector3 &axis, scalar_t angle) +{ + scalar_t half_angle = angle / 2.0; + s = cos(half_angle); + v = axis * sin(half_angle); +} + +void Quaternion::rotate(const Vector3 &axis, scalar_t angle) +{ + Quaternion q; + scalar_t half_angle = angle / 2.0; + q.s = cos(half_angle); + q.v = axis * sin(half_angle); + + *this *= q; +} + +void Quaternion::rotate(const Quaternion &q) +{ + *this = q * *this * q.conjugate(); +} + +Matrix3x3 Quaternion::get_rotation_matrix() const +{ + return Matrix3x3( + 1.0 - 2.0 * v.y*v.y - 2.0 * v.z*v.z, 2.0 * v.x * v.y - 2.0 * s * v.z, 2.0 * v.z * v.x + 2.0 * s * v.y, + 2.0 * v.x * v.y + 2.0 * s * v.z, 1.0 - 2.0 * v.x*v.x - 2.0 * v.z*v.z, 2.0 * v.y * v.z - 2.0 * s * v.x, + 2.0 * v.z * v.x - 2.0 * s * v.y, 2.0 * v.y * v.z + 2.0 * s * v.x, 1.0 - 2.0 * v.x*v.x - 2.0 * v.y*v.y); +} + + +/** Spherical linear interpolation (slerp) */ +Quaternion slerp(const Quaternion &quat1, const Quaternion &q2, scalar_t t) +{ + Quaternion q1 = quat1; + scalar_t dot = q1.s * q2.s + q1.v.x * q2.v.x + q1.v.y * q2.v.y + q1.v.z * q2.v.z; + + if(dot < 0.0) { + /* make sure we interpolate across the shortest arc */ + q1 = -quat1; + dot = -dot; + } + + /* clamp dot to [-1, 1] in order to avoid domain errors in acos due to + * floating point imprecisions + */ + if(dot < -1.0) dot = -1.0; + if(dot > 1.0) dot = 1.0; + + scalar_t angle = acos(dot); + scalar_t a, b; + + scalar_t sin_angle = sin(angle); + if(fabs(sin_angle) < SMALL_NUMBER) { + /* for very small angles or completely opposite orientations + * use linear interpolation to avoid div/zero (in the first case it makes sense, + * the second case is pretty much undefined anyway I guess ... + */ + a = 1.0f - t; + b = t; + } else { + a = sin((1.0f - t) * angle) / sin_angle; + b = sin(t * angle) / sin_angle; + } + + scalar_t x = q1.v.x * a + q2.v.x * b; + scalar_t y = q1.v.y * a + q2.v.y * b; + scalar_t z = q1.v.z * a + q2.v.z * b; + scalar_t s = q1.s * a + q2.s * b; + + return Quaternion(s, Vector3(x, y, z)); +} + + +/* +std::ostream &operator <<(std::ostream &out, const Quaternion &q) +{ + out << "(" << q.s << ", " << q.v << ")"; + return out; +} +*/ diff -r d1b456d08713 -r c71c477521ca libs/vmath/quat.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/quat.h Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,114 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 VMATH_QUATERNION_H_ +#define VMATH_QUATERNION_H_ + +#include +#include "vmath_types.h" +#include "vector.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define quat_cons(s, x, y, z) v4_cons(x, y, z, s) +#define quat_vec(q) v3_cons((q).x, (q).y, (q).z) +#define quat_s(q) ((q).w) +#define quat_identity() quat_cons(1.0, 0.0, 0.0, 0.0) +void quat_print(FILE *fp, quat_t q); + +#define quat_add v4_add +#define quat_sub v4_sub +#define quat_neg v4_neg + +static inline quat_t quat_mul(quat_t q1, quat_t q2); + +static inline quat_t quat_conjugate(quat_t q); + +#define quat_length v4_length +#define quat_length_sq v4_length_sq + +#define quat_normalize v4_normalize +static inline quat_t quat_inverse(quat_t q); + +quat_t quat_rotate(quat_t q, scalar_t angle, scalar_t x, scalar_t y, scalar_t z); +quat_t quat_rotate_quat(quat_t q, quat_t rotq); + +static inline void quat_to_mat3(mat3_t res, quat_t q); +static inline void quat_to_mat4(mat4_t res, quat_t q); + +#define quat_lerp quat_slerp +quat_t quat_slerp(quat_t q1, quat_t q2, scalar_t t); + + +#ifdef __cplusplus +} /* extern "C" */ + +/* Quaternion */ +class Quaternion { +public: + scalar_t s; + Vector3 v; + + Quaternion(); + Quaternion(scalar_t s, const Vector3 &v); + Quaternion(scalar_t s, scalar_t x, scalar_t y, scalar_t z); + Quaternion(const Vector3 &axis, scalar_t angle); + Quaternion(const quat_t &quat); + + Quaternion operator +(const Quaternion &quat) const; + Quaternion operator -(const Quaternion &quat) const; + Quaternion operator -() const; + Quaternion operator *(const Quaternion &quat) const; + + void operator +=(const Quaternion &quat); + void operator -=(const Quaternion &quat); + void operator *=(const Quaternion &quat); + + void reset_identity(); + + Quaternion conjugate() const; + + scalar_t length() const; + scalar_t length_sq() const; + + void normalize(); + Quaternion normalized() const; + + Quaternion inverse() const; + + void set_rotation(const Vector3 &axis, scalar_t angle); + void rotate(const Vector3 &axis, scalar_t angle); + /* note: this is a totally different operation from the above + * this treats the quaternion as signifying direction and rotates + * it by a rotation quaternion by rot * q * rot' + */ + void rotate(const Quaternion &q); + + Matrix3x3 get_rotation_matrix() const; +}; + +Quaternion slerp(const Quaternion &q1, const Quaternion &q2, scalar_t t); +inline Quaternion lerp(const Quaternion &q1, const Quaternion &q2, scalar_t t); + +#endif /* __cplusplus */ + +#include "quat.inl" + +#endif /* VMATH_QUATERNION_H_ */ diff -r d1b456d08713 -r c71c477521ca libs/vmath/quat.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/quat.inl Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,81 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 "vector.h" +#include "matrix.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +static inline quat_t quat_mul(quat_t q1, quat_t q2) +{ + quat_t res; + vec3_t v1 = quat_vec(q1); + vec3_t v2 = quat_vec(q2); + + res.w = q1.w * q2.w - v3_dot(v1, v2); + /* resvec = v2 * q1 + v1 * q2 + cross(v1, v2) */ + res.x = v2.x * q1.w + v1.x * q2.w + (v1.y * v2.z - v1.z * v2.y); + res.y = v2.y * q1.w + v1.y * q2.w + (v1.z * v2.x - v1.x * v2.z); + res.z = v2.z * q1.w + v1.z * q2.w + (v1.x * v2.y - v1.y * v2.x); + return res; +} + +static inline quat_t quat_conjugate(quat_t q) +{ + q.x = -q.x; + q.y = -q.y; + q.z = -q.z; + return q; +} + +static inline quat_t quat_inverse(quat_t q) +{ + scalar_t lensq = quat_length_sq(q); + q = quat_conjugate(q); + q.x /= lensq; + q.y /= lensq; + q.z /= lensq; + q.w /= lensq; + return q; +} + +static inline void quat_to_mat3(mat3_t res, quat_t q) +{ + m3_cons(res, 1.0 - 2.0 * q.y*q.y - 2.0 * q.z*q.z, 2.0 * q.x * q.y - 2.0 * q.w * q.z, 2.0 * q.z * q.x + 2.0 * q.w * q.y, + 2.0 * q.x * q.y + 2.0 * q.w * q.z, 1.0 - 2.0 * q.x*q.x - 2.0 * q.z*q.z, 2.0 * q.y * q.z - 2.0 * q.w * q.x, + 2.0 * q.z * q.x - 2.0 * q.w * q.y, 2.0 * q.y * q.z + 2.0 * q.w * q.x, 1.0 - 2.0 * q.x*q.x - 2.0 * q.y*q.y); +} + +static inline void quat_to_mat4(mat4_t res, quat_t q) +{ + m4_cons(res, 1.0 - 2.0 * q.y*q.y - 2.0 * q.z*q.z, 2.0 * q.x * q.y - 2.0 * q.w * q.z, 2.0 * q.z * q.x + 2.0 * q.w * q.y, 0, + 2.0 * q.x * q.y + 2.0 * q.w * q.z, 1.0 - 2.0 * q.x*q.x - 2.0 * q.z*q.z, 2.0 * q.y * q.z - 2.0 * q.w * q.x, 0, + 2.0 * q.z * q.x - 2.0 * q.w * q.y, 2.0 * q.y * q.z + 2.0 * q.w * q.x, 1.0 - 2.0 * q.x*q.x - 2.0 * q.y*q.y, 0, + 0, 0, 0, 1); +} + +#ifdef __cplusplus +} /* extern "C" */ + +inline Quaternion lerp(const Quaternion &a, const Quaternion &b, scalar_t t) +{ + return slerp(a, b, t); +} +#endif /* __cplusplus */ diff -r d1b456d08713 -r c71c477521ca libs/vmath/quat_c.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/quat_c.c Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,89 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 "quat.h" + +void quat_print(FILE *fp, quat_t q) +{ + fprintf(fp, "([ %.4f %.4f %.4f ] %.4f)", q.x, q.y, q.z, q.w); +} + +quat_t quat_rotate(quat_t q, scalar_t angle, scalar_t x, scalar_t y, scalar_t z) +{ + quat_t rq; + scalar_t half_angle = angle * 0.5; + scalar_t sin_half = sin(half_angle); + + rq.w = cos(half_angle); + rq.x = x * sin_half; + rq.y = y * sin_half; + rq.z = z * sin_half; + + return quat_mul(q, rq); +} + +quat_t quat_rotate_quat(quat_t q, quat_t rotq) +{ + return quat_mul(quat_mul(rotq, q), quat_conjugate(rotq)); +} + +quat_t quat_slerp(quat_t q1, quat_t q2, scalar_t t) +{ + quat_t res; + scalar_t a, b, angle, sin_angle, dot; + + dot = q1.w * q2.w + q1.x * q2.x + q1.y * q2.y + q1.z * q2.z; + if(dot < 0.0) { + /* make sure we interpolate across the shortest arc */ + q1.x = -q1.x; + q1.y = -q1.y; + q1.z = -q1.z; + q1.w = -q1.w; + dot = -dot; + } + + /* clamp dot to [-1, 1] in order to avoid domain errors in acos due to + * floating point imprecisions + */ + if(dot < -1.0) dot = -1.0; + if(dot > 1.0) dot = 1.0; + + angle = acos(dot); + sin_angle = sin(angle); + + if(fabs(sin_angle) < SMALL_NUMBER) { + /* for very small angles or completely opposite orientations + * use linear interpolation to avoid div/zero (in the first case it makes sense, + * the second case is pretty much undefined anyway I guess ... + */ + a = 1.0f - t; + b = t; + } else { + a = sin((1.0f - t) * angle) / sin_angle; + b = sin(t * angle) / sin_angle; + } + + res.x = q1.x * a + q2.x * b; + res.y = q1.y * a + q2.y * b; + res.z = q1.z * a + q2.z * b; + res.w = q1.w * a + q2.w * b; + return res; +} diff -r d1b456d08713 -r c71c477521ca libs/vmath/ray.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/ray.cc Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,78 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 "ray.h" +#include "vector.h" + +scalar_t Ray::env_ior = 1.0; + +Ray::Ray() +{ + ior = env_ior; + energy = 1.0; + time = 0; + iter = 0; +} + +Ray::Ray(const Vector3 &origin, const Vector3 &dir) +{ + this->origin = origin; + this->dir = dir; + ior = env_ior; + energy = 1.0; + time = 0; + iter = 0; +} + +void Ray::transform(const Matrix4x4 &xform) +{ + Matrix4x4 upper = xform; + upper[0][3] = upper[1][3] = upper[2][3] = upper[3][0] = upper[3][1] = upper[3][2] = 0.0; + upper[3][3] = 1.0; + + dir.transform(upper); + origin.transform(xform); +} + +Ray Ray::transformed(const Matrix4x4 &xform) const +{ + Ray foo = *this; + foo.transform(xform); + return foo; +} + +void Ray::enter(scalar_t new_ior) +{ + ior = new_ior; +} + +void Ray::leave() +{ +} + +scalar_t Ray::calc_ior(bool entering, scalar_t mat_ior) const +{ + scalar_t from_ior = this->ior; + + if(entering) { + return from_ior / mat_ior; + } + + Ray tmp = *this; + tmp.leave(); + return from_ior / tmp.ior; +} diff -r d1b456d08713 -r c71c477521ca libs/vmath/ray.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/ray.h Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,68 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 VMATH_RAY_H_ +#define VMATH_RAY_H_ + +#include "matrix.h" +#include "vector.h" + +typedef struct { + vec3_t origin, dir; +} ray_t; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +static inline ray_t ray_cons(vec3_t origin, vec3_t dir); +ray_t ray_transform(ray_t r, mat4_t m); + +#ifdef __cplusplus +} /* __cplusplus */ + +class Ray { +public: + /* enviornmental index of refraction, normally 1.0 */ + static scalar_t env_ior; + + Vector3 origin, dir; + scalar_t energy; + int iter; + scalar_t ior; + long time; + + Ray(); + Ray(const Vector3 &origin, const Vector3 &dir); + + void transform(const Matrix4x4 &xform); + Ray transformed(const Matrix4x4 &xform) const; + + void enter(scalar_t new_ior); + void leave(); + + scalar_t calc_ior(bool entering, scalar_t mat_ior = 1.0) const; +}; + +inline Ray reflect_ray(const Ray &inray, const Vector3 &norm); +inline Ray refract_ray(const Ray &inray, const Vector3 &norm, scalar_t ior, bool entering, scalar_t ray_mag = -1.0); +#endif /* __cplusplus */ + +#include "ray.inl" + +#endif /* VMATH_RAY_H_ */ diff -r d1b456d08713 -r c71c477521ca libs/vmath/ray.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/ray.inl Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,70 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 . +*/ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +static inline ray_t ray_cons(vec3_t origin, vec3_t dir) +{ + ray_t r; + r.origin = origin; + r.dir = dir; + return r; +} + +#ifdef __cplusplus +} + +inline Ray reflect_ray(const Ray &inray, const Vector3 &norm) +{ + Ray ray = inray; + ray.iter--; + ray.dir = ray.dir.reflection(norm); + return ray; +} + +inline Ray refract_ray(const Ray &inray, const Vector3 &norm, scalar_t mat_ior, bool entering, scalar_t ray_mag) +{ + Ray ray = inray; + ray.iter--; + + scalar_t ior = ray.calc_ior(entering, mat_ior); + + if(entering) { + ray.enter(mat_ior); + } else { + ray.leave(); + } + + if(ray_mag < 0.0) { + ray_mag = ray.dir.length(); + } + ray.dir = (ray.dir / ray_mag).refraction(norm, ior) * ray_mag; + + /* check TIR */ + if(dot_product(ray.dir, norm) > 0.0) { + if(entering) { + ray.leave(); + } else { + ray.enter(mat_ior); + } + } + return ray; +} +#endif /* __cplusplus */ diff -r d1b456d08713 -r c71c477521ca libs/vmath/ray_c.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/ray_c.c Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,36 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 "ray.h" +#include "vector.h" + +ray_t ray_transform(ray_t r, mat4_t xform) +{ + mat4_t upper; + vec3_t dir; + + m4_copy(upper, xform); + upper[0][3] = upper[1][3] = upper[2][3] = upper[3][0] = upper[3][1] = upper[3][2] = 0.0; + upper[3][3] = 1.0; + + dir = v3_sub(r.dir, r.origin); + dir = v3_transform(dir, upper); + r.origin = v3_transform(r.origin, xform); + r.dir = v3_add(dir, r.origin); + return r; +} diff -r d1b456d08713 -r c71c477521ca libs/vmath/sphvec.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/sphvec.cc Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,44 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 "sphvec.h" +#include "vector.h" + +/* theta: 0 <= theta <= 2pi, the angle around Y axis. + * phi: 0 <= phi <= pi, the angle from Y axis. + * r: radius. + */ +SphVector::SphVector(scalar_t theta, scalar_t phi, scalar_t r) { + this->theta = theta; + this->phi = phi; + this->r = r; +} + +/* Constructs a spherical coordinate vector from a cartesian vector */ +SphVector::SphVector(const Vector3 &cvec) { + *this = cvec; +} + +/* Assignment operator that converts cartesian to spherical coords */ +SphVector &SphVector::operator =(const Vector3 &cvec) { + r = cvec.length(); + //theta = atan2(cvec.y, cvec.x); + theta = atan2(cvec.z, cvec.x); + //phi = acos(cvec.z / r); + phi = acos(cvec.y / r); + return *this; +} diff -r d1b456d08713 -r c71c477521ca libs/vmath/sphvec.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/sphvec.h Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,36 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 VMATH_SPHVEC_H_ +#define VMATH_SPHVEC_H_ + +#include "vmath_types.h" + +#ifdef __cplusplus +/* Vector in spherical coordinates */ +class SphVector { +public: + scalar_t theta, phi, r; + + SphVector(scalar_t theta = 0.0, scalar_t phi = 0.0, scalar_t r = 1.0); + SphVector(const Vector3 &cvec); + SphVector &operator =(const Vector3 &cvec); +}; +#endif /* __cplusplus */ + +#endif /* VMATH_SPHVEC_H_ */ diff -r d1b456d08713 -r c71c477521ca libs/vmath/vector.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/vector.cc Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,348 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 "vector.h" +#include "vmath.h" + +// ---------- Vector2 ----------- + +Vector2::Vector2(scalar_t x, scalar_t y) +{ + this->x = x; + this->y = y; +} + +Vector2::Vector2(const vec2_t &vec) +{ + x = vec.x; + y = vec.y; +} + +Vector2::Vector2(const Vector3 &vec) +{ + x = vec.x; + y = vec.y; +} + +Vector2::Vector2(const Vector4 &vec) +{ + x = vec.x; + y = vec.y; +} + +void Vector2::normalize() +{ + scalar_t len = length(); + x /= len; + y /= len; +} + +Vector2 Vector2::normalized() const +{ + scalar_t len = length(); + return Vector2(x / len, y / len); +} + +void Vector2::transform(const Matrix3x3 &mat) +{ + scalar_t nx = mat[0][0] * x + mat[0][1] * y + mat[0][2]; + y = mat[1][0] * x + mat[1][1] * y + mat[1][2]; + x = nx; +} + +Vector2 Vector2::transformed(const Matrix3x3 &mat) const +{ + Vector2 vec; + vec.x = mat[0][0] * x + mat[0][1] * y + mat[0][2]; + vec.y = mat[1][0] * x + mat[1][1] * y + mat[1][2]; + return vec; +} + +void Vector2::rotate(scalar_t angle) +{ + *this = Vector2(cos(angle) * x - sin(angle) * y, sin(angle) * x + cos(angle) * y); +} + +Vector2 Vector2::rotated(scalar_t angle) const +{ + return Vector2(cos(angle) * x - sin(angle) * y, sin(angle) * x + cos(angle) * y); +} + +Vector2 Vector2::reflection(const Vector2 &normal) const +{ + return 2.0 * dot_product(*this, normal) * normal - *this; +} + +Vector2 Vector2::refraction(const Vector2 &normal, scalar_t src_ior, scalar_t dst_ior) const +{ + // quick and dirty implementation :) + Vector3 v3refr = Vector3(this->x, this->y, 1.0).refraction(Vector3(this->x, this->y, 1), src_ior, dst_ior); + return Vector2(v3refr.x, v3refr.y); +} + +/* +std::ostream &operator <<(std::ostream &out, const Vector2 &vec) +{ + out << "[" << vec.x << " " << vec.y << "]"; + return out; +} +*/ + + +// --------- Vector3 ---------- + +Vector3::Vector3(scalar_t x, scalar_t y, scalar_t z) +{ + this->x = x; + this->y = y; + this->z = z; +} + +Vector3::Vector3(const vec3_t &vec) +{ + x = vec.x; + y = vec.y; + z = vec.z; +} + +Vector3::Vector3(const Vector2 &vec) +{ + x = vec.x; + y = vec.y; + z = 1; +} + +Vector3::Vector3(const Vector4 &vec) +{ + x = vec.x; + y = vec.y; + z = vec.z; +} + +Vector3::Vector3(const SphVector &sph) +{ + *this = sph; +} + +Vector3 &Vector3::operator =(const SphVector &sph) +{ + x = sph.r * cos(sph.theta) * sin(sph.phi); + z = sph.r * sin(sph.theta) * sin(sph.phi); + y = sph.r * cos(sph.phi); + return *this; +} + +void Vector3::normalize() +{ + scalar_t len = length(); + x /= len; + y /= len; + z /= len; +} + +Vector3 Vector3::normalized() const +{ + scalar_t len = length(); + return Vector3(x / len, y / len, z / len); +} + +Vector3 Vector3::reflection(const Vector3 &normal) const +{ + return 2.0 * dot_product(*this, normal) * normal - *this; +} + +Vector3 Vector3::refraction(const Vector3 &normal, scalar_t src_ior, scalar_t dst_ior) const +{ + return refraction(normal, src_ior / dst_ior); +} + +Vector3 Vector3::refraction(const Vector3 &normal, scalar_t ior) const +{ + scalar_t cos_inc = dot_product(*this, -normal); + + scalar_t radical = 1.0 + SQ(ior) * (SQ(cos_inc) - 1.0); + + if(radical < 0.0) { // total internal reflection + return -reflection(normal); + } + + scalar_t beta = ior * cos_inc - sqrt(radical); + + return *this * ior + normal * beta; +} + +void Vector3::transform(const Matrix3x3 &mat) +{ + scalar_t nx = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z; + scalar_t ny = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z; + z = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z; + x = nx; + y = ny; +} + +Vector3 Vector3::transformed(const Matrix3x3 &mat) const +{ + Vector3 vec; + vec.x = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z; + vec.y = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z; + vec.z = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z; + return vec; +} + +void Vector3::transform(const Matrix4x4 &mat) +{ + scalar_t nx = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z + mat[0][3]; + scalar_t ny = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z + mat[1][3]; + z = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z + mat[2][3]; + x = nx; + y = ny; +} + +Vector3 Vector3::transformed(const Matrix4x4 &mat) const +{ + Vector3 vec; + vec.x = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z + mat[0][3]; + vec.y = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z + mat[1][3]; + vec.z = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z + mat[2][3]; + return vec; +} + +void Vector3::transform(const Quaternion &quat) +{ + Quaternion vq(0.0f, *this); + vq = quat * vq * quat.inverse(); + *this = vq.v; +} + +Vector3 Vector3::transformed(const Quaternion &quat) const +{ + Quaternion vq(0.0f, *this); + vq = quat * vq * quat.inverse(); + return vq.v; +} + +void Vector3::rotate(const Vector3 &euler) +{ + Matrix4x4 rot; + rot.set_rotation(euler); + transform(rot); +} + +Vector3 Vector3::rotated(const Vector3 &euler) const +{ + Matrix4x4 rot; + rot.set_rotation(euler); + return transformed(rot); +} + +/* +std::ostream &operator <<(std::ostream &out, const Vector3 &vec) +{ + out << "[" << vec.x << " " << vec.y << " " << vec.z << "]"; + return out; +} +*/ + + +// -------------- Vector4 -------------- +Vector4::Vector4(scalar_t x, scalar_t y, scalar_t z, scalar_t w) +{ + this->x = x; + this->y = y; + this->z = z; + this->w = w; +} + +Vector4::Vector4(const vec4_t &vec) +{ + x = vec.x; + y = vec.y; + z = vec.z; + w = vec.w; +} + +Vector4::Vector4(const Vector2 &vec) +{ + x = vec.x; + y = vec.y; + z = 1; + w = 1; +} + +Vector4::Vector4(const Vector3 &vec) +{ + x = vec.x; + y = vec.y; + z = vec.z; + w = 1; +} + +void Vector4::normalize() +{ + scalar_t len = (scalar_t)sqrt(x*x + y*y + z*z + w*w); + x /= len; + y /= len; + z /= len; + w /= len; +} + +Vector4 Vector4::normalized() const +{ + scalar_t len = (scalar_t)sqrt(x*x + y*y + z*z + w*w); + return Vector4(x / len, y / len, z / len, w / len); +} + +void Vector4::transform(const Matrix4x4 &mat) +{ + scalar_t nx = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z + mat[0][3] * w; + scalar_t ny = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z + mat[1][3] * w; + scalar_t nz = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z + mat[2][3] * w; + w = mat[3][0] * x + mat[3][1] * y + mat[3][2] * z + mat[3][3] * w; + x = nx; + y = ny; + z = nz; +} + +Vector4 Vector4::transformed(const Matrix4x4 &mat) const +{ + Vector4 vec; + vec.x = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z + mat[0][3] * w; + vec.y = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z + mat[1][3] * w; + vec.z = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z + mat[2][3] * w; + vec.w = mat[3][0] * x + mat[3][1] * y + mat[3][2] * z + mat[3][3] * w; + return vec; +} + +// TODO: implement 4D vector reflection +Vector4 Vector4::reflection(const Vector4 &normal) const +{ + return *this; +} + +// TODO: implement 4D vector refraction +Vector4 Vector4::refraction(const Vector4 &normal, scalar_t src_ior, scalar_t dst_ior) const +{ + return *this; +} + +/* +std::ostream &operator <<(std::ostream &out, const Vector4 &vec) +{ + out << "[" << vec.x << " " << vec.y << " " << vec.z << " " << vec.w << "]"; + return out; +} +*/ diff -r d1b456d08713 -r c71c477521ca libs/vmath/vector.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/vector.h Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,294 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 VMATH_VECTOR_H_ +#define VMATH_VECTOR_H_ + +#include +#include "vmath_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* C 2D vector functions */ +static inline vec2_t v2_cons(scalar_t x, scalar_t y); +static inline void v2_print(FILE *fp, vec2_t v); + +static inline vec2_t v2_add(vec2_t v1, vec2_t v2); +static inline vec2_t v2_sub(vec2_t v1, vec2_t v2); +static inline vec2_t v2_scale(vec2_t v, scalar_t s); +static inline scalar_t v2_dot(vec2_t v1, vec2_t v2); +static inline scalar_t v2_length(vec2_t v); +static inline scalar_t v2_length_sq(vec2_t v); +static inline vec2_t v2_normalize(vec2_t v); + +static inline vec2_t v2_lerp(vec2_t v1, vec2_t v2, scalar_t t); + +/* C 3D vector functions */ +static inline vec3_t v3_cons(scalar_t x, scalar_t y, scalar_t z); +static inline void v3_print(FILE *fp, vec3_t v); + +static inline vec3_t v3_add(vec3_t v1, vec3_t v2); +static inline vec3_t v3_sub(vec3_t v1, vec3_t v2); +static inline vec3_t v3_neg(vec3_t v); +static inline vec3_t v3_mul(vec3_t v1, vec3_t v2); +static inline vec3_t v3_scale(vec3_t v1, scalar_t s); +static inline scalar_t v3_dot(vec3_t v1, vec3_t v2); +static inline vec3_t v3_cross(vec3_t v1, vec3_t v2); +static inline scalar_t v3_length(vec3_t v); +static inline scalar_t v3_length_sq(vec3_t v); +static inline vec3_t v3_normalize(vec3_t v); +static inline vec3_t v3_transform(vec3_t v, mat4_t m); + +static inline vec3_t v3_rotate(vec3_t v, scalar_t x, scalar_t y, scalar_t z); +static inline vec3_t v3_rotate_axis(vec3_t v, scalar_t angle, scalar_t x, scalar_t y, scalar_t z); +static inline vec3_t v3_rotate_quat(vec3_t v, quat_t q); + +static inline vec3_t v3_reflect(vec3_t v, vec3_t n); + +static inline vec3_t v3_lerp(vec3_t v1, vec3_t v2, scalar_t t); + +/* C 4D vector functions */ +static inline vec4_t v4_cons(scalar_t x, scalar_t y, scalar_t z, scalar_t w); +static inline void v4_print(FILE *fp, vec4_t v); + +static inline vec4_t v4_add(vec4_t v1, vec4_t v2); +static inline vec4_t v4_sub(vec4_t v1, vec4_t v2); +static inline vec4_t v4_neg(vec4_t v); +static inline vec4_t v4_mul(vec4_t v1, vec4_t v2); +static inline vec4_t v4_scale(vec4_t v, scalar_t s); +static inline scalar_t v4_dot(vec4_t v1, vec4_t v2); +static inline scalar_t v4_length(vec4_t v); +static inline scalar_t v4_length_sq(vec4_t v); +static inline vec4_t v4_normalize(vec4_t v); +static inline vec4_t v4_transform(vec4_t v, mat4_t m); + +#ifdef __cplusplus +} /* extern "C" */ + +/* when included from C++ source files, also define the vector classes */ + +/** 2D Vector */ +class Vector2 { +public: + scalar_t x, y; + + Vector2(scalar_t x = 0.0, scalar_t y = 0.0); + Vector2(const vec2_t &vec); + Vector2(const Vector3 &vec); + Vector2(const Vector4 &vec); + + inline scalar_t &operator [](int elem); + inline const scalar_t &operator [](int elem) const; + + inline scalar_t length() const; + inline scalar_t length_sq() const; + void normalize(); + Vector2 normalized() const; + + void transform(const Matrix3x3 &mat); + Vector2 transformed(const Matrix3x3 &mat) const; + + void rotate(scalar_t angle); + Vector2 rotated(scalar_t angle) const; + + Vector2 reflection(const Vector2 &normal) const; + Vector2 refraction(const Vector2 &normal, scalar_t src_ior, scalar_t dst_ior) const; +}; + +/* unary operations */ +inline Vector2 operator -(const Vector2 &vec); + +/* binary vector (op) vector operations */ +inline scalar_t dot_product(const Vector2 &v1, const Vector2 &v2); + +inline Vector2 operator +(const Vector2 &v1, const Vector2 &v2); +inline Vector2 operator -(const Vector2 &v1, const Vector2 &v2); +inline Vector2 operator *(const Vector2 &v1, const Vector2 &v2); +inline Vector2 operator /(const Vector2 &v1, const Vector2 &v2); +inline bool operator ==(const Vector2 &v1, const Vector2 &v2); + +inline void operator +=(Vector2 &v1, const Vector2 &v2); +inline void operator -=(Vector2 &v1, const Vector2 &v2); +inline void operator *=(Vector2 &v1, const Vector2 &v2); +inline void operator /=(Vector2 &v1, const Vector2 &v2); + +/* binary vector (op) scalar and scalar (op) vector operations */ +inline Vector2 operator +(const Vector2 &vec, scalar_t scalar); +inline Vector2 operator +(scalar_t scalar, const Vector2 &vec); +inline Vector2 operator -(const Vector2 &vec, scalar_t scalar); +inline Vector2 operator *(const Vector2 &vec, scalar_t scalar); +inline Vector2 operator *(scalar_t scalar, const Vector2 &vec); +inline Vector2 operator /(const Vector2 &vec, scalar_t scalar); + +inline void operator +=(Vector2 &vec, scalar_t scalar); +inline void operator -=(Vector2 &vec, scalar_t scalar); +inline void operator *=(Vector2 &vec, scalar_t scalar); +inline void operator /=(Vector2 &vec, scalar_t scalar); + + +inline Vector2 lerp(const Vector2 &a, const Vector2 &b, scalar_t t); +inline Vector2 catmull_rom_spline(const Vector2 &v0, const Vector2 &v1, + const Vector2 &v2, const Vector2 &v3, scalar_t t); +inline Vector2 bspline(const Vector2 &v0, const Vector2 &v1, + const Vector2 &v2, const Vector2 &v3, scalar_t t); + +/* 3D Vector */ +class Vector3 { +public: + scalar_t x, y, z; + + Vector3(scalar_t x = 0.0, scalar_t y = 0.0, scalar_t z = 0.0); + Vector3(const vec3_t &vec); + Vector3(const Vector2 &vec); + Vector3(const Vector4 &vec); + Vector3(const SphVector &sph); + + Vector3 &operator =(const SphVector &sph); + + inline scalar_t &operator [](int elem); + inline const scalar_t &operator [](int elem) const; + + inline scalar_t length() const; + inline scalar_t length_sq() const; + void normalize(); + Vector3 normalized() const; + + void transform(const Matrix3x3 &mat); + Vector3 transformed(const Matrix3x3 &mat) const; + void transform(const Matrix4x4 &mat); + Vector3 transformed(const Matrix4x4 &mat) const; + void transform(const Quaternion &quat); + Vector3 transformed(const Quaternion &quat) const; + + void rotate(const Vector3 &euler); + Vector3 rotated(const Vector3 &euler) const; + + Vector3 reflection(const Vector3 &normal) const; + Vector3 refraction(const Vector3 &normal, scalar_t src_ior, scalar_t dst_ior) const; + Vector3 refraction(const Vector3 &normal, scalar_t ior) const; +}; + +/* unary operations */ +inline Vector3 operator -(const Vector3 &vec); + +/* binary vector (op) vector operations */ +inline scalar_t dot_product(const Vector3 &v1, const Vector3 &v2); +inline Vector3 cross_product(const Vector3 &v1, const Vector3 &v2); + +inline Vector3 operator +(const Vector3 &v1, const Vector3 &v2); +inline Vector3 operator -(const Vector3 &v1, const Vector3 &v2); +inline Vector3 operator *(const Vector3 &v1, const Vector3 &v2); +inline Vector3 operator /(const Vector3 &v1, const Vector3 &v2); +inline bool operator ==(const Vector3 &v1, const Vector3 &v2); + +inline void operator +=(Vector3 &v1, const Vector3 &v2); +inline void operator -=(Vector3 &v1, const Vector3 &v2); +inline void operator *=(Vector3 &v1, const Vector3 &v2); +inline void operator /=(Vector3 &v1, const Vector3 &v2); + +/* binary vector (op) scalar and scalar (op) vector operations */ +inline Vector3 operator +(const Vector3 &vec, scalar_t scalar); +inline Vector3 operator +(scalar_t scalar, const Vector3 &vec); +inline Vector3 operator -(const Vector3 &vec, scalar_t scalar); +inline Vector3 operator *(const Vector3 &vec, scalar_t scalar); +inline Vector3 operator *(scalar_t scalar, const Vector3 &vec); +inline Vector3 operator /(const Vector3 &vec, scalar_t scalar); + +inline void operator +=(Vector3 &vec, scalar_t scalar); +inline void operator -=(Vector3 &vec, scalar_t scalar); +inline void operator *=(Vector3 &vec, scalar_t scalar); +inline void operator /=(Vector3 &vec, scalar_t scalar); + + +inline Vector3 lerp(const Vector3 &a, const Vector3 &b, scalar_t t); +inline Vector3 catmull_rom_spline(const Vector3 &v0, const Vector3 &v1, + const Vector3 &v2, const Vector3 &v3, scalar_t t); +inline Vector3 bspline(const Vector3 &v0, const Vector3 &v1, + const Vector3 &v2, const Vector3 &v3, scalar_t t); + +/* 4D Vector */ +class Vector4 { +public: + scalar_t x, y, z, w; + + Vector4(scalar_t x = 0.0, scalar_t y = 0.0, scalar_t z = 0.0, scalar_t w = 0.0); + Vector4(const vec4_t &vec); + Vector4(const Vector2 &vec); + Vector4(const Vector3 &vec); + + inline scalar_t &operator [](int elem); + inline const scalar_t &operator [](int elem) const; + + inline scalar_t length() const; + inline scalar_t length_sq() const; + void normalize(); + Vector4 normalized() const; + + void transform(const Matrix4x4 &mat); + Vector4 transformed(const Matrix4x4 &mat) const; + + Vector4 reflection(const Vector4 &normal) const; + Vector4 refraction(const Vector4 &normal, scalar_t src_ior, scalar_t dst_ior) const; +}; + + +/* unary operations */ +inline Vector4 operator -(const Vector4 &vec); + +/* binary vector (op) vector operations */ +inline scalar_t dot_product(const Vector4 &v1, const Vector4 &v2); +inline Vector4 cross_product(const Vector4 &v1, const Vector4 &v2, const Vector4 &v3); + +inline Vector4 operator +(const Vector4 &v1, const Vector4 &v2); +inline Vector4 operator -(const Vector4 &v1, const Vector4 &v2); +inline Vector4 operator *(const Vector4 &v1, const Vector4 &v2); +inline Vector4 operator /(const Vector4 &v1, const Vector4 &v2); +inline bool operator ==(const Vector4 &v1, const Vector4 &v2); + +inline void operator +=(Vector4 &v1, const Vector4 &v2); +inline void operator -=(Vector4 &v1, const Vector4 &v2); +inline void operator *=(Vector4 &v1, const Vector4 &v2); +inline void operator /=(Vector4 &v1, const Vector4 &v2); + +/* binary vector (op) scalar and scalar (op) vector operations */ +inline Vector4 operator +(const Vector4 &vec, scalar_t scalar); +inline Vector4 operator +(scalar_t scalar, const Vector4 &vec); +inline Vector4 operator -(const Vector4 &vec, scalar_t scalar); +inline Vector4 operator *(const Vector4 &vec, scalar_t scalar); +inline Vector4 operator *(scalar_t scalar, const Vector4 &vec); +inline Vector4 operator /(const Vector4 &vec, scalar_t scalar); + +inline void operator +=(Vector4 &vec, scalar_t scalar); +inline void operator -=(Vector4 &vec, scalar_t scalar); +inline void operator *=(Vector4 &vec, scalar_t scalar); +inline void operator /=(Vector4 &vec, scalar_t scalar); + + +inline Vector4 lerp(const Vector4 &v0, const Vector4 &v1, scalar_t t); +inline Vector4 catmull_rom_spline(const Vector4 &v0, const Vector4 &v1, + const Vector4 &v2, const Vector4 &v3, scalar_t t); +inline Vector4 bspline(const Vector4 &v0, const Vector4 &v1, + const Vector4 &v2, const Vector4 &v3, scalar_t t); + +#endif /* __cplusplus */ + +#include "vector.inl" + +#endif /* VMATH_VECTOR_H_ */ diff -r d1b456d08713 -r c71c477521ca libs/vmath/vector.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/vector.inl Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,812 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +scalar_t spline(scalar_t, scalar_t, scalar_t, scalar_t, scalar_t); +scalar_t bspline(scalar_t, scalar_t, scalar_t, scalar_t, scalar_t); + +/* C 2D vector functions */ +static inline vec2_t v2_cons(scalar_t x, scalar_t y) +{ + vec2_t v; + v.x = x; + v.y = y; + return v; +} + +static inline void v2_print(FILE *fp, vec2_t v) +{ + fprintf(fp, "[ %.4f %.4f ]", v.x, v.y); +} + +static inline vec2_t v2_add(vec2_t v1, vec2_t v2) +{ + vec2_t res; + res.x = v1.x + v2.x; + res.y = v1.y + v2.y; + return res; +} + +static inline vec2_t v2_sub(vec2_t v1, vec2_t v2) +{ + vec2_t res; + res.x = v1.x - v2.x; + res.y = v1.y - v2.y; + return res; +} + +static inline vec2_t v2_scale(vec2_t v, scalar_t s) +{ + vec2_t res; + res.x = v.x * s; + res.y = v.y * s; + return res; +} + +static inline scalar_t v2_dot(vec2_t v1, vec2_t v2) +{ + return v1.x * v2.x + v1.y * v2.y; +} + +static inline scalar_t v2_length(vec2_t v) +{ + return sqrt(v.x * v.x + v.y * v.y); +} + +static inline scalar_t v2_length_sq(vec2_t v) +{ + return v.x * v.x + v.y * v.y; +} + +static inline vec2_t v2_normalize(vec2_t v) +{ + scalar_t len = (scalar_t)sqrt(v.x * v.x + v.y * v.y); + v.x /= len; + v.y /= len; + return v; +} + +static inline vec2_t v2_lerp(vec2_t v1, vec2_t v2, scalar_t t) +{ + vec2_t res; + res.x = v1.x + (v2.x - v1.x) * t; + res.y = v1.y + (v2.y - v1.y) * t; + return res; +} + + +/* C 3D vector functions */ +static inline vec3_t v3_cons(scalar_t x, scalar_t y, scalar_t z) +{ + vec3_t v; + v.x = x; + v.y = y; + v.z = z; + return v; +} + +static inline void v3_print(FILE *fp, vec3_t v) +{ + fprintf(fp, "[ %.4f %.4f %.4f ]", v.x, v.y, v.z); +} + +static inline vec3_t v3_add(vec3_t v1, vec3_t v2) +{ + v1.x += v2.x; + v1.y += v2.y; + v1.z += v2.z; + return v1; +} + +static inline vec3_t v3_sub(vec3_t v1, vec3_t v2) +{ + v1.x -= v2.x; + v1.y -= v2.y; + v1.z -= v2.z; + return v1; +} + +static inline vec3_t v3_neg(vec3_t v) +{ + v.x = -v.x; + v.y = -v.y; + v.z = -v.z; + return v; +} + +static inline vec3_t v3_mul(vec3_t v1, vec3_t v2) +{ + v1.x *= v2.x; + v1.y *= v2.y; + v1.z *= v2.z; + return v1; +} + +static inline vec3_t v3_scale(vec3_t v1, scalar_t s) +{ + v1.x *= s; + v1.y *= s; + v1.z *= s; + return v1; +} + +static inline scalar_t v3_dot(vec3_t v1, vec3_t v2) +{ + return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; +} + +static inline vec3_t v3_cross(vec3_t v1, vec3_t v2) +{ + vec3_t v; + v.x = v1.y * v2.z - v1.z * v2.y; + v.y = v1.z * v2.x - v1.x * v2.z; + v.z = v1.x * v2.y - v1.y * v2.x; + return v; +} + +static inline scalar_t v3_length(vec3_t v) +{ + return sqrt(v.x * v.x + v.y * v.y + v.z * v.z); +} + +static inline scalar_t v3_length_sq(vec3_t v) +{ + return v.x * v.x + v.y * v.y + v.z * v.z; +} + +static inline vec3_t v3_normalize(vec3_t v) +{ + scalar_t len = sqrt(v.x * v.x + v.y * v.y + v.z * v.z); + v.x /= len; + v.y /= len; + v.z /= len; + return v; +} + +static inline vec3_t v3_transform(vec3_t v, mat4_t m) +{ + vec3_t res; + res.x = m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3]; + res.y = m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3]; + res.z = m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3]; + return res; +} + +static inline vec3_t v3_rotate(vec3_t v, scalar_t x, scalar_t y, scalar_t z) +{ + void m4_rotate(mat4_t, scalar_t, scalar_t, scalar_t); + + mat4_t m = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}; + m4_rotate(m, x, y, z); + return v3_transform(v, m); +} + +static inline vec3_t v3_rotate_axis(vec3_t v, scalar_t angle, scalar_t x, scalar_t y, scalar_t z) +{ + void m4_rotate_axis(mat4_t, scalar_t, scalar_t, scalar_t, scalar_t); + + mat4_t m = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}; + m4_rotate_axis(m, angle, x, y, z); + return v3_transform(v, m); +} + +static inline vec3_t v3_rotate_quat(vec3_t v, quat_t q) +{ + quat_t quat_rotate_quat(quat_t, quat_t); + + quat_t vq = v4_cons(v.x, v.y, v.z, 0.0); + quat_t res = quat_rotate_quat(vq, q); + return v3_cons(res.x, res.y, res.z); +} + +static inline vec3_t v3_reflect(vec3_t v, vec3_t n) +{ + scalar_t dot = v3_dot(v, n); + return v3_sub(v3_scale(n, dot * 2.0), v); +} + +static inline vec3_t v3_lerp(vec3_t v1, vec3_t v2, scalar_t t) +{ + v1.x += (v2.x - v1.x) * t; + v1.y += (v2.y - v1.y) * t; + v1.z += (v2.z - v1.z) * t; + return v1; +} + +/* C 4D vector functions */ +static inline vec4_t v4_cons(scalar_t x, scalar_t y, scalar_t z, scalar_t w) +{ + vec4_t v; + v.x = x; + v.y = y; + v.z = z; + v.w = w; + return v; +} + +static inline void v4_print(FILE *fp, vec4_t v) +{ + fprintf(fp, "[ %.4f %.4f %.4f %.4f ]", v.x, v.y, v.z, v.w); +} + +static inline vec4_t v4_add(vec4_t v1, vec4_t v2) +{ + v1.x += v2.x; + v1.y += v2.y; + v1.z += v2.z; + v1.w += v2.w; + return v1; +} + +static inline vec4_t v4_sub(vec4_t v1, vec4_t v2) +{ + v1.x -= v2.x; + v1.y -= v2.y; + v1.z -= v2.z; + v1.w -= v2.w; + return v1; +} + +static inline vec4_t v4_neg(vec4_t v) +{ + v.x = -v.x; + v.y = -v.y; + v.z = -v.z; + v.w = -v.w; + return v; +} + +static inline vec4_t v4_mul(vec4_t v1, vec4_t v2) +{ + v1.x *= v2.x; + v1.y *= v2.y; + v1.z *= v2.z; + v1.w *= v2.w; + return v1; +} + +static inline vec4_t v4_scale(vec4_t v, scalar_t s) +{ + v.x *= s; + v.y *= s; + v.z *= s; + v.w *= s; + return v; +} + +static inline scalar_t v4_dot(vec4_t v1, vec4_t v2) +{ + return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w; +} + +static inline scalar_t v4_length(vec4_t v) +{ + return sqrt(v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w); +} + +static inline scalar_t v4_length_sq(vec4_t v) +{ + return v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w; +} + +static inline vec4_t v4_normalize(vec4_t v) +{ + scalar_t len = sqrt(v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w); + v.x /= len; + v.y /= len; + v.z /= len; + v.w /= len; + return v; +} + +static inline vec4_t v4_transform(vec4_t v, mat4_t m) +{ + vec4_t res; + res.x = m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w; + res.y = m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w; + res.z = m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w; + res.w = m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] * v.w; + return res; +} + +#ifdef __cplusplus +} /* extern "C" */ + + +/* --------------- C++ part -------------- */ + +inline scalar_t &Vector2::operator [](int elem) +{ + return elem ? y : x; +} + +inline const scalar_t &Vector2::operator [](int elem) const +{ + return elem ? y : x; +} + +inline Vector2 operator -(const Vector2 &vec) +{ + return Vector2(-vec.x, -vec.y); +} + +inline scalar_t dot_product(const Vector2 &v1, const Vector2 &v2) +{ + return v1.x * v2.x + v1.y * v2.y; +} + +inline Vector2 operator +(const Vector2 &v1, const Vector2 &v2) +{ + return Vector2(v1.x + v2.x, v1.y + v2.y); +} + +inline Vector2 operator -(const Vector2 &v1, const Vector2 &v2) +{ + return Vector2(v1.x - v2.x, v1.y - v2.y); +} + +inline Vector2 operator *(const Vector2 &v1, const Vector2 &v2) +{ + return Vector2(v1.x * v2.x, v1.y * v2.y); +} + +inline Vector2 operator /(const Vector2 &v1, const Vector2 &v2) +{ + return Vector2(v1.x / v2.x, v1.y / v2.y); +} + +inline bool operator ==(const Vector2 &v1, const Vector2 &v2) +{ + return (fabs(v1.x - v2.x) < XSMALL_NUMBER) && (fabs(v1.y - v2.x) < XSMALL_NUMBER); +} + +inline void operator +=(Vector2 &v1, const Vector2 &v2) +{ + v1.x += v2.x; + v1.y += v2.y; +} + +inline void operator -=(Vector2 &v1, const Vector2 &v2) +{ + v1.x -= v2.x; + v1.y -= v2.y; +} + +inline void operator *=(Vector2 &v1, const Vector2 &v2) +{ + v1.x *= v2.x; + v1.y *= v2.y; +} + +inline void operator /=(Vector2 &v1, const Vector2 &v2) +{ + v1.x /= v2.x; + v1.y /= v2.y; +} + +inline Vector2 operator +(const Vector2 &vec, scalar_t scalar) +{ + return Vector2(vec.x + scalar, vec.y + scalar); +} + +inline Vector2 operator +(scalar_t scalar, const Vector2 &vec) +{ + return Vector2(vec.x + scalar, vec.y + scalar); +} + +inline Vector2 operator -(const Vector2 &vec, scalar_t scalar) +{ + return Vector2(vec.x - scalar, vec.y - scalar); +} + +inline Vector2 operator *(const Vector2 &vec, scalar_t scalar) +{ + return Vector2(vec.x * scalar, vec.y * scalar); +} + +inline Vector2 operator *(scalar_t scalar, const Vector2 &vec) +{ + return Vector2(vec.x * scalar, vec.y * scalar); +} + +inline Vector2 operator /(const Vector2 &vec, scalar_t scalar) +{ + return Vector2(vec.x / scalar, vec.y / scalar); +} + +inline void operator +=(Vector2 &vec, scalar_t scalar) +{ + vec.x += scalar; + vec.y += scalar; +} + +inline void operator -=(Vector2 &vec, scalar_t scalar) +{ + vec.x -= scalar; + vec.y -= scalar; +} + +inline void operator *=(Vector2 &vec, scalar_t scalar) +{ + vec.x *= scalar; + vec.y *= scalar; +} + +inline void operator /=(Vector2 &vec, scalar_t scalar) +{ + vec.x /= scalar; + vec.y /= scalar; +} + +inline scalar_t Vector2::length() const +{ + return sqrt(x*x + y*y); +} + +inline scalar_t Vector2::length_sq() const +{ + return x*x + y*y; +} + +inline Vector2 lerp(const Vector2 &a, const Vector2 &b, scalar_t t) +{ + return a + (b - a) * t; +} + +inline Vector2 catmull_rom_spline(const Vector2 &v0, const Vector2 &v1, + const Vector2 &v2, const Vector2 &v3, scalar_t t) +{ + scalar_t x = spline(v0.x, v1.x, v2.x, v3.x, t); + scalar_t y = spline(v0.y, v1.y, v2.y, v3.y, t); + return Vector2(x, y); +} + +inline Vector2 bspline(const Vector2 &v0, const Vector2 &v1, + const Vector2 &v2, const Vector2 &v3, scalar_t t) +{ + scalar_t x = bspline(v0.x, v1.x, v2.x, v3.x, t); + scalar_t y = bspline(v0.y, v1.y, v2.y, v3.y, t); + return Vector2(x, y); +} + + +/* ------------- Vector3 -------------- */ + +inline scalar_t &Vector3::operator [](int elem) { + return elem ? (elem == 1 ? y : z) : x; +} + +inline const scalar_t &Vector3::operator [](int elem) const { + return elem ? (elem == 1 ? y : z) : x; +} + +/* unary operations */ +inline Vector3 operator -(const Vector3 &vec) { + return Vector3(-vec.x, -vec.y, -vec.z); +} + +/* binary vector (op) vector operations */ +inline scalar_t dot_product(const Vector3 &v1, const Vector3 &v2) { + return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; +} + +inline Vector3 cross_product(const Vector3 &v1, const Vector3 &v2) { + return Vector3(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); +} + + +inline Vector3 operator +(const Vector3 &v1, const Vector3 &v2) { + return Vector3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); +} + +inline Vector3 operator -(const Vector3 &v1, const Vector3 &v2) { + return Vector3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); +} + +inline Vector3 operator *(const Vector3 &v1, const Vector3 &v2) { + return Vector3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z); +} + +inline Vector3 operator /(const Vector3 &v1, const Vector3 &v2) { + return Vector3(v1.x / v2.x, v1.y / v2.y, v1.z / v2.z); +} + +inline bool operator ==(const Vector3 &v1, const Vector3 &v2) { + return (fabs(v1.x - v2.x) < XSMALL_NUMBER) && (fabs(v1.y - v2.y) < XSMALL_NUMBER) && (fabs(v1.z - v2.z) < XSMALL_NUMBER); +} + +inline void operator +=(Vector3 &v1, const Vector3 &v2) { + v1.x += v2.x; + v1.y += v2.y; + v1.z += v2.z; +} + +inline void operator -=(Vector3 &v1, const Vector3 &v2) { + v1.x -= v2.x; + v1.y -= v2.y; + v1.z -= v2.z; +} + +inline void operator *=(Vector3 &v1, const Vector3 &v2) { + v1.x *= v2.x; + v1.y *= v2.y; + v1.z *= v2.z; +} + +inline void operator /=(Vector3 &v1, const Vector3 &v2) { + v1.x /= v2.x; + v1.y /= v2.y; + v1.z /= v2.z; +} +/* binary vector (op) scalar and scalar (op) vector operations */ +inline Vector3 operator +(const Vector3 &vec, scalar_t scalar) { + return Vector3(vec.x + scalar, vec.y + scalar, vec.z + scalar); +} + +inline Vector3 operator +(scalar_t scalar, const Vector3 &vec) { + return Vector3(vec.x + scalar, vec.y + scalar, vec.z + scalar); +} + +inline Vector3 operator -(const Vector3 &vec, scalar_t scalar) { + return Vector3(vec.x - scalar, vec.y - scalar, vec.z - scalar); +} + +inline Vector3 operator *(const Vector3 &vec, scalar_t scalar) { + return Vector3(vec.x * scalar, vec.y * scalar, vec.z * scalar); +} + +inline Vector3 operator *(scalar_t scalar, const Vector3 &vec) { + return Vector3(vec.x * scalar, vec.y * scalar, vec.z * scalar); +} + +inline Vector3 operator /(const Vector3 &vec, scalar_t scalar) { + return Vector3(vec.x / scalar, vec.y / scalar, vec.z / scalar); +} + +inline void operator +=(Vector3 &vec, scalar_t scalar) { + vec.x += scalar; + vec.y += scalar; + vec.z += scalar; +} + +inline void operator -=(Vector3 &vec, scalar_t scalar) { + vec.x -= scalar; + vec.y -= scalar; + vec.z -= scalar; +} + +inline void operator *=(Vector3 &vec, scalar_t scalar) { + vec.x *= scalar; + vec.y *= scalar; + vec.z *= scalar; +} + +inline void operator /=(Vector3 &vec, scalar_t scalar) { + vec.x /= scalar; + vec.y /= scalar; + vec.z /= scalar; +} + +inline scalar_t Vector3::length() const { + return sqrt(x*x + y*y + z*z); +} +inline scalar_t Vector3::length_sq() const { + return x*x + y*y + z*z; +} + +inline Vector3 lerp(const Vector3 &a, const Vector3 &b, scalar_t t) { + return a + (b - a) * t; +} + +inline Vector3 catmull_rom_spline(const Vector3 &v0, const Vector3 &v1, + const Vector3 &v2, const Vector3 &v3, scalar_t t) +{ + scalar_t x = spline(v0.x, v1.x, v2.x, v3.x, t); + scalar_t y = spline(v0.y, v1.y, v2.y, v3.y, t); + scalar_t z = spline(v0.z, v1.z, v2.z, v3.z, t); + return Vector3(x, y, z); +} + +inline Vector3 bspline(const Vector3 &v0, const Vector3 &v1, + const Vector3 &v2, const Vector3 &v3, scalar_t t) +{ + scalar_t x = bspline(v0.x, v1.x, v2.x, v3.x, t); + scalar_t y = bspline(v0.y, v1.y, v2.y, v3.y, t); + scalar_t z = bspline(v0.z, v1.z, v2.z, v3.z, t); + return Vector3(x, y, z); +} + +/* ----------- Vector4 ----------------- */ + +inline scalar_t &Vector4::operator [](int elem) { + return elem ? (elem == 1 ? y : (elem == 2 ? z : w)) : x; +} + +inline const scalar_t &Vector4::operator [](int elem) const { + return elem ? (elem == 1 ? y : (elem == 2 ? z : w)) : x; +} + +inline Vector4 operator -(const Vector4 &vec) { + return Vector4(-vec.x, -vec.y, -vec.z, -vec.w); +} + +inline scalar_t dot_product(const Vector4 &v1, const Vector4 &v2) { + return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w; +} + +inline Vector4 cross_product(const Vector4 &v1, const Vector4 &v2, const Vector4 &v3) { + scalar_t a, b, c, d, e, f; /* Intermediate Values */ + Vector4 result; + + /* Calculate intermediate values. */ + a = (v2.x * v3.y) - (v2.y * v3.x); + b = (v2.x * v3.z) - (v2.z * v3.x); + c = (v2.x * v3.w) - (v2.w * v3.x); + d = (v2.y * v3.z) - (v2.z * v3.y); + e = (v2.y * v3.w) - (v2.w * v3.y); + f = (v2.z * v3.w) - (v2.w * v3.z); + + /* Calculate the result-vector components. */ + result.x = (v1.y * f) - (v1.z * e) + (v1.w * d); + result.y = - (v1.x * f) + (v1.z * c) - (v1.w * b); + result.z = (v1.x * e) - (v1.y * c) + (v1.w * a); + result.w = - (v1.x * d) + (v1.y * b) - (v1.z * a); + return result; +} + +inline Vector4 operator +(const Vector4 &v1, const Vector4 &v2) { + return Vector4(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.w + v2.w); +} + +inline Vector4 operator -(const Vector4 &v1, const Vector4 &v2) { + return Vector4(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.w - v2.w); +} + +inline Vector4 operator *(const Vector4 &v1, const Vector4 &v2) { + return Vector4(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z, v1.w * v2.w); +} + +inline Vector4 operator /(const Vector4 &v1, const Vector4 &v2) { + return Vector4(v1.x / v2.x, v1.y / v2.y, v1.z / v2.z, v1.w / v2.w); +} + +inline bool operator ==(const Vector4 &v1, const Vector4 &v2) { + return (fabs(v1.x - v2.x) < XSMALL_NUMBER) && + (fabs(v1.y - v2.y) < XSMALL_NUMBER) && + (fabs(v1.z - v2.z) < XSMALL_NUMBER) && + (fabs(v1.w - v2.w) < XSMALL_NUMBER); +} + +inline void operator +=(Vector4 &v1, const Vector4 &v2) { + v1.x += v2.x; + v1.y += v2.y; + v1.z += v2.z; + v1.w += v2.w; +} + +inline void operator -=(Vector4 &v1, const Vector4 &v2) { + v1.x -= v2.x; + v1.y -= v2.y; + v1.z -= v2.z; + v1.w -= v2.w; +} + +inline void operator *=(Vector4 &v1, const Vector4 &v2) { + v1.x *= v2.x; + v1.y *= v2.y; + v1.z *= v2.z; + v1.w *= v2.w; +} + +inline void operator /=(Vector4 &v1, const Vector4 &v2) { + v1.x /= v2.x; + v1.y /= v2.y; + v1.z /= v2.z; + v1.w /= v2.w; +} + +/* binary vector (op) scalar and scalar (op) vector operations */ +inline Vector4 operator +(const Vector4 &vec, scalar_t scalar) { + return Vector4(vec.x + scalar, vec.y + scalar, vec.z + scalar, vec.w + scalar); +} + +inline Vector4 operator +(scalar_t scalar, const Vector4 &vec) { + return Vector4(vec.x + scalar, vec.y + scalar, vec.z + scalar, vec.w + scalar); +} + +inline Vector4 operator -(const Vector4 &vec, scalar_t scalar) { + return Vector4(vec.x - scalar, vec.y - scalar, vec.z - scalar, vec.w - scalar); +} + +inline Vector4 operator *(const Vector4 &vec, scalar_t scalar) { + return Vector4(vec.x * scalar, vec.y * scalar, vec.z * scalar, vec.w * scalar); +} + +inline Vector4 operator *(scalar_t scalar, const Vector4 &vec) { + return Vector4(vec.x * scalar, vec.y * scalar, vec.z * scalar, vec.w * scalar); +} + +inline Vector4 operator /(const Vector4 &vec, scalar_t scalar) { + return Vector4(vec.x / scalar, vec.y / scalar, vec.z / scalar, vec.w / scalar); +} + +inline void operator +=(Vector4 &vec, scalar_t scalar) { + vec.x += scalar; + vec.y += scalar; + vec.z += scalar; + vec.w += scalar; +} + +inline void operator -=(Vector4 &vec, scalar_t scalar) { + vec.x -= scalar; + vec.y -= scalar; + vec.z -= scalar; + vec.w -= scalar; +} + +inline void operator *=(Vector4 &vec, scalar_t scalar) { + vec.x *= scalar; + vec.y *= scalar; + vec.z *= scalar; + vec.w *= scalar; +} + +inline void operator /=(Vector4 &vec, scalar_t scalar) { + vec.x /= scalar; + vec.y /= scalar; + vec.z /= scalar; + vec.w /= scalar; +} + +inline scalar_t Vector4::length() const { + return sqrt(x*x + y*y + z*z + w*w); +} +inline scalar_t Vector4::length_sq() const { + return x*x + y*y + z*z + w*w; +} + +inline Vector4 lerp(const Vector4 &v0, const Vector4 &v1, scalar_t t) +{ + return v0 + (v1 - v0) * t; +} + +inline Vector4 catmull_rom_spline(const Vector4 &v0, const Vector4 &v1, + const Vector4 &v2, const Vector4 &v3, scalar_t t) +{ + scalar_t x = spline(v0.x, v1.x, v2.x, v3.x, t); + scalar_t y = spline(v0.y, v1.y, v2.y, v3.y, t); + scalar_t z = spline(v0.z, v1.z, v2.z, v3.z, t); + scalar_t w = spline(v0.w, v1.w, v2.w, v3.w, t); + return Vector4(x, y, z, w); +} + +inline Vector4 bspline(const Vector4 &v0, const Vector4 &v1, + const Vector4 &v2, const Vector4 &v3, scalar_t t) +{ + scalar_t x = bspline(v0.x, v1.x, v2.x, v3.x, t); + scalar_t y = bspline(v0.y, v1.y, v2.y, v3.y, t); + scalar_t z = bspline(v0.z, v1.z, v2.z, v3.z, t); + scalar_t w = bspline(v0.w, v1.w, v2.w, v3.w, t); + return Vector4(x, y, z, w); +} +#endif /* __cplusplus */ diff -r d1b456d08713 -r c71c477521ca libs/vmath/vmath.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/vmath.c Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,396 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 "vmath.h" + +#if defined(__APPLE__) && !defined(TARGET_IPHONE) +#include + +void enable_fpexcept(void) +{ + unsigned int bits; + bits = _MM_MASK_INVALID | _MM_MASK_DIV_ZERO | _MM_MASK_OVERFLOW | _MM_MASK_UNDERFLOW; + _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~bits); +} + +void disable_fpexcept(void) +{ + unsigned int bits; + bits = _MM_MASK_INVALID | _MM_MASK_DIV_ZERO | _MM_MASK_OVERFLOW | _MM_MASK_UNDERFLOW; + _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() | bits); +} + +#elif defined(__GNUC__) && !defined(TARGET_IPHONE) && !defined(__MINGW32__) +#define __USE_GNU +#include + +void enable_fpexcept(void) +{ + feenableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW); +} + +void disable_fpexcept(void) +{ + fedisableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW); +} + +#elif defined(_MSC_VER) || defined(__MINGW32__) +#include + +#if defined(__MINGW32__) && !defined(_EM_OVERFLOW) +/* if gcc's float.h gets precedence, the mingw MSVC includes won't be declared */ +#define _MCW_EM 0x8001f +#define _EM_INVALID 0x10 +#define _EM_ZERODIVIDE 0x08 +#define _EM_OVERFLOW 0x04 +unsigned int __cdecl _clearfp(void); +unsigned int __cdecl _controlfp(unsigned int, unsigned int); +#endif + +void enable_fpexcept(void) +{ + _clearfp(); + _controlfp(_controlfp(0, 0) & ~(_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW), _MCW_EM); +} + +void disable_fpexcept(void) +{ + _clearfp(); + _controlfp(_controlfp(0, 0) | (_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW), _MCW_EM); +} +#else +void enable_fpexcept(void) {} +void disable_fpexcept(void) {} +#endif + + +/** Numerical calculation of integrals using simpson's rule */ +scalar_t integral(scalar_t (*f)(scalar_t), scalar_t low, scalar_t high, int samples) +{ + int i; + scalar_t h = (high - low) / (scalar_t)samples; + scalar_t sum = 0.0; + + for(i=0; i + +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 VMATH_H_ +#define VMATH_H_ + +#include +#include "vmath_types.h" + +#ifndef M_PI +#define M_PI PI +#endif + +#ifndef M_E +#define M_E 2.718281828459045 +#endif + +#define PI 3.141592653589793 +#define HALF_PI 1.570796326794897 +#define QUARTER_PI 0.785398163397448 +#define TWO_PI 6.283185307179586 + + +#define RAD_TO_DEG(a) ((((scalar_t)a) * 360.0) / TWO_PI) +#define DEG_TO_RAD(a) (((scalar_t)a) * (PI / 180.0)) + +#define SQ(x) ((x) * (x)) + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +#if (__STDC_VERSION__ < 199901L) && (__cplusplus < 201103L) && !defined(__GNUC__) && (_MSC_VER < 1800) +#define round(x) ((x) >= 0 ? (x) + 0.5 : (x) - 0.5) +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void enable_fpexcept(void); +void disable_fpexcept(void); + +static inline scalar_t smoothstep(float a, float b, float x); + +static inline scalar_t frand(scalar_t range); +static inline vec3_t sphrand(scalar_t rad); + +scalar_t integral(scalar_t (*f)(scalar_t), scalar_t low, scalar_t high, int samples); +scalar_t gaussian(scalar_t x, scalar_t mean, scalar_t sdev); + +static inline scalar_t lerp(scalar_t a, scalar_t b, scalar_t t); + +scalar_t bspline(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t); +scalar_t spline(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t); +scalar_t bezier(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t); + +scalar_t noise1(scalar_t x); +scalar_t noise2(scalar_t x, scalar_t y); +scalar_t noise3(scalar_t x, scalar_t y, scalar_t z); + +scalar_t fbm1(scalar_t x, int octaves); +scalar_t fbm2(scalar_t x, scalar_t y, int octaves); +scalar_t fbm3(scalar_t x, scalar_t y, scalar_t z, int octaves); + +scalar_t turbulence1(scalar_t x, int octaves); +scalar_t turbulence2(scalar_t x, scalar_t y, int octaves); +scalar_t turbulence3(scalar_t x, scalar_t y, scalar_t z, int octaves); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#include "vmath.inl" + +#include "vector.h" +#include "matrix.h" +#include "quat.h" +#include "sphvec.h" +#include "ray.h" +#include "geom.h" + +#endif /* VMATH_H_ */ diff -r d1b456d08713 -r c71c477521ca libs/vmath/vmath.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/vmath.inl Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,56 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 + +static inline scalar_t smoothstep(float a, float b, float x) +{ + if(x < a) return 0.0; + if(x >= b) return 1.0; + + x = (x - a) / (b - a); + return x * x * (3.0 - 2.0 * x); +} + +/** Generates a random number in [0, range) */ +static inline scalar_t frand(scalar_t range) +{ + return range * (scalar_t)rand() / (scalar_t)RAND_MAX; +} + +/** Generates a random vector on the surface of a sphere */ +static inline vec3_t sphrand(scalar_t rad) +{ + scalar_t u = (scalar_t)rand() / RAND_MAX; + scalar_t v = (scalar_t)rand() / RAND_MAX; + + scalar_t theta = 2.0 * M_PI * u; + scalar_t phi = acos(2.0 * v - 1.0); + + vec3_t res; + res.x = rad * cos(theta) * sin(phi); + res.y = rad * sin(theta) * sin(phi); + res.z = rad * cos(phi); + return res; +} + +/** linear interpolation */ +static inline scalar_t lerp(scalar_t a, scalar_t b, scalar_t t) +{ + return a + (b - a) * t; +} diff -r d1b456d08713 -r c71c477521ca libs/vmath/vmath_config.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/vmath_config.h Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,19 @@ +#ifndef VMATH_CONFIG_H_ +#define VMATH_CONFIG_H_ + +#if (__STDC_VERSION__ < 199999) && !defined(__cplusplus) +#if defined(__GNUC__) || defined(_MSC_VER) +#define inline __inline +#else +#define inline + +#ifdef VECTOR_H_ +#warning "compiling vector operations without inline, performance might suffer" +#endif /* VECTOR_H_ */ + +#endif /* gcc/msvc */ +#endif /* not C99 */ + +#define SINGLE_PRECISION_MATH + +#endif /* VMATH_CONFIG_H_ */ diff -r d1b456d08713 -r c71c477521ca libs/vmath/vmath_types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/vmath/vmath_types.h Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,58 @@ +/* +libvmath - a vector math library +Copyright (C) 2004-2015 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 VMATH_TYPES_H_ +#define VMATH_TYPES_H_ + +#include "vmath_config.h" + +#define SMALL_NUMBER 1.e-4 +#define XSMALL_NUMBER 1.e-8 +#define ERROR_MARGIN 1.e-6 + + +#ifdef SINGLE_PRECISION_MATH +typedef float scalar_t; +#else +typedef double scalar_t; +#endif /* floating point precision */ + +/* vectors */ +typedef struct { scalar_t x, y; } vec2_t; +typedef struct { scalar_t x, y, z; } vec3_t; +typedef struct { scalar_t x, y, z, w; } vec4_t; + +/* quaternions */ +typedef vec4_t quat_t; + +/* matrices */ +typedef scalar_t mat3_t[3][3]; +typedef scalar_t mat4_t[4][4]; + + +#ifdef __cplusplus +class Vector2; +class Vector3; +class Vector4; +class Quaternion; +class Matrix3x3; +class Matrix4x4; +class SphVector; +#endif /* __cplusplus */ + +#endif /* VMATH_TYPES_H_ */ diff -r d1b456d08713 -r c71c477521ca proj.mk --- a/proj.mk Mon May 25 05:27:26 2015 +0300 +++ b/proj.mk Sun May 31 00:40:26 2015 +0300 @@ -1,8 +1,15 @@ root ?= $(shell pwd) -src = $(wildcard $(root)/src/*.c) +src = $(wildcard $(root)/src/*.c) \ + $(wildcard $(root)/libs/drawtext/*.c) \ + $(wildcard $(root)/libs/vmath/*.c) + +ccsrc = $(wildcard $(root)/src/*.cc) \ + $(wildcard $(root)/libs/vmath/*.cc) + bin = photoshoot3d title = 3D Photo Shoot -incpaths = -I$(root)/src +incpaths = -I$(root)/src -I$(root)/libs -I$(root)/libs/vmath -I$(root)/libs/drawtext libpaths = +defs = -DNO_FREETYPE diff -r d1b456d08713 -r c71c477521ca src/android/amain.c --- a/src/android/amain.c Mon May 25 05:27:26 2015 +0300 +++ b/src/android/amain.c Sun May 31 00:40:26 2015 +0300 @@ -217,14 +217,14 @@ { static const int eglattr[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 5, EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE, 16, EGL_NONE }; - static const int ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE }; + static const int ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; EGLConfig eglcfg; int count, vis; diff -r d1b456d08713 -r c71c477521ca src/game.c --- a/src/game.c Mon May 25 05:27:26 2015 +0300 +++ b/src/game.c Sun May 31 00:40:26 2015 +0300 @@ -4,6 +4,7 @@ #include "opengl.h" #include "game.h" #include "camera.h" +#include "sdr.h" static void draw_quad(float hsz, float vsz); @@ -11,16 +12,57 @@ static float win_aspect; static int video_width, video_height; static float video_aspect; +static unsigned int sdrprog; +static int aloc_vertex, aloc_texcoord, uloc_texmat, uloc_wmat, uloc_vmat, uloc_pmat; + +static const char *vsdr_source = + "attribute vec4 attr_pos, attr_tex;\n" + "uniform mat4 world_matrix, proj_matrix, tex_matrix;\n" + "varying vec4 tex_coords;\n" + "void main()\n" + "{\n" + "\tmat4 mvp = proj_matrix * world_matrix;\n" + "\tgl_Position = mvp * attr_pos;\n" + "\ttex_coords = tex_matrix * attr_tex;\n" + "}\n"; + +static const char *psdr_source = + "#extension GL_OES_EGL_image_external : require\n" + "precision lowp float;\n" + "uniform samplerExternalOES tex;\n" + "varying vec4 tex_coords;\n" + "void main()\n" + "{\n" + "\tvec4 texel = texture2D(tex, tex_coords.xy);\n" + "\tgl_FragColor = vec4(texel.xyz, 1.0);\n" + "}\n"; int game_init(void) { + unsigned int vsdr, psdr; + glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); - //glEnable(GL_LIGHTING); glClearColor(0.4, 0.4, 0.4, 1); + if(!(vsdr = create_vertex_shader(vsdr_source))) + return -1; + if(!(psdr = create_pixel_shader(psdr_source))) + return -1; + if(!(sdrprog = create_program_link(vsdr, psdr))) { + fprintf(stderr, "failed to create shader program\n"); + return -1; + } + glUseProgram(sdrprog); + aloc_vertex = glGetAttribLocation(sdrprog, "attr_pos"); + aloc_texcoord = glGetAttribLocation(sdrprog, "attr_tex"); + uloc_texmat = glGetUniformLocation(sdrprog, "tex_matrix"); + uloc_wmat = glGetUniformLocation(sdrprog, "world_matrix"); + uloc_vmat = glGetUniformLocation(sdrprog, "view_matrix"); + uloc_pmat = glGetUniformLocation(sdrprog, "proj_matrix"); + cam_start_video(); cam_video_size(&video_width, &video_height); if(video_height) { @@ -36,6 +78,7 @@ void game_shutdown(void) { cam_shutdown(); + free_program(sdrprog); } void game_display(unsigned long msec) @@ -53,17 +96,9 @@ //glClearColor(sin(tsec * 10.0), cos(tsec * 10.0), -sin(tsec * 10.0), 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - if(tex) { - glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex); - glEnable(GL_TEXTURE_EXTERNAL_OES); - - glMatrixMode(GL_TEXTURE); - glLoadMatrixf(tex_matrix); - glMatrixMode(GL_MODELVIEW); - } + glUseProgram(sdrprog); + glUniformMatrix4fv(uloc_texmat, 1, 0, tex_matrix); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex); if(video_aspect > win_aspect) { xscale = 1.0; @@ -73,40 +108,35 @@ yscale = 1.0; } draw_quad(xscale, yscale); - - if(tex) { - glDisable(GL_TEXTURE_EXTERNAL_OES); - - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - } } static void draw_quad(float hsz, float vsz) { static const float varr[] = {-1, -1, 1, -1, 1, 1, -1, 1}; static const float tcarr[] = {0, 0, 1, 0, 1, 1, 0, 1}; - static const float colarr[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + float xform[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; - glPushMatrix(); - glScalef(hsz, vsz, 1); + if(aloc_vertex == -1) { + return; + } - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); + xform[0] = hsz; + xform[5] = vsz; + glUniformMatrix4fv(uloc_wmat, 1, 0, xform); - glVertexPointer(2, GL_FLOAT, 0, varr); - glTexCoordPointer(2, GL_FLOAT, 0, tcarr); - glColorPointer(4, GL_FLOAT, 0, colarr); + glEnableVertexAttribArray(aloc_vertex); + glVertexAttribPointer(aloc_vertex, 2, GL_FLOAT, 0, 0, varr); + if(aloc_texcoord) { + glEnableVertexAttribArray(aloc_texcoord); + glVertexAttribPointer(aloc_texcoord, 2, GL_FLOAT, 0, 0, tcarr); + } glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - - glPopMatrix(); + glDisableVertexAttribArray(aloc_vertex); + if(aloc_texcoord) { + glDisableVertexAttribArray(aloc_texcoord); + } } void game_reshape(int x, int y) @@ -116,9 +146,9 @@ win_aspect = y ? (float)x / (float)y : 1.0; glViewport(0, 0, x, y); - glMatrixMode(GL_PROJECTION); + /*glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glScalef((float)win_height / (float)win_width, 1.0, 1.0); + glScalef((float)win_height / (float)win_width, 1.0, 1.0);*/ } void game_keyboard(int key, int pressed) diff -r d1b456d08713 -r c71c477521ca src/gfxstate.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gfxstate.cc Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,68 @@ +#include +#include "vmath/vmath.h" +#include "gfxstate.h" + +static std::stack mstack[NUM_MATRICES]; + +static bool init_stack(int midx) +{ + if(mstack[midx].empty()) { + mstack[midx].push(Matrix4x4::identity); + return true; + } + return false; +} + +void push_matrix(int midx) +{ + init_stack(midx); + mstack[midx].push(mstack[midx].top()); +} + +void pop_matrix(int midx) +{ + if(!mstack[midx].empty()) { + mstack[midx].pop(); + } +} + +void set_identity_matrix(int midx) +{ + set_matrix4x4(midx, Matrix4x4::identity); +} + +void set_matrix(int midx, const float *m) +{ + Matrix4x4 tmp; + memcpy(tmp[0], m, 16 * sizeof *m); + set_matrix4x4(midx, tmp.transposed()); +} + +void mult_matrix(int midx, const float *m) +{ + Matrix4x4 tmp; + memcpy(tmp[0], m, 16 * sizeof *m); + mult_matrix4x4(midx, tmp.transposed()); +} + +void get_matrix(int midx, float *m) +{ + Matrix4x4 tmp = get_matrix4x4(midx); + tmp.transpose(); + memcpy(m, tmp[0], 16 * sizeof *m); +} + +void set_matrix4x4(int midx, const Matrix4x4 &m) +{ + mstack[midx].top() = m; +} + +void mult_matrix4x4(int midx, const Matrix4x4 &m) +{ + mstack[midx].top() *= m; +} + +Matrix4x4 &get_matrix4x4(int midx) +{ + return mstack[midx].top(); +} diff -r d1b456d08713 -r c71c477521ca src/gfxstate.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gfxstate.h Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,37 @@ +#ifndef GFXSTATE_H_ +#define GFXSTATE_H_ + +enum { + WORLD_MATRIX, + VIEW_MATRIX, + PROJECTION_MATRIX, + TEXTURE_MATRIX, + + NUM_MATRICES +}; + +#ifdef __cplusplus +extern "C" { +#endif + +void push_matrix(int midx); +void pop_matrix(int midx); + +void set_identity_matrix(int midx); +void set_matrix(int midx, const float *m); +void mult_matrix(int midx, const float *m); +void get_matrix(int midx, float *m); +float *get_matrix_ptr(int midx); + +#ifdef __cplusplus +} + +#ifdef VMATH_MATRIX_H_ +void set_matrix4x4(int midx, const Matrix4x4 &m); +void mult_matrix4x4(int midx, const Matrix4x4 &m); +Matrix4x4 &get_matrix4x4(int midx); +#endif /* VMATH_MATRIX_H_ */ + +#endif /* __cplusplus */ + +#endif /* GFXSTATE_H_ */ diff -r d1b456d08713 -r c71c477521ca src/opengl.h --- a/src/opengl.h Mon May 25 05:27:26 2015 +0300 +++ b/src/opengl.h Sun May 31 00:40:26 2015 +0300 @@ -1,7 +1,12 @@ #ifndef OPENGL_H_ #define OPENGL_H_ -#include -#include + +#ifdef ANDROID +#include +#include +#else +#include +#endif #endif /* OPENGL_H_ */ diff -r d1b456d08713 -r c71c477521ca src/sdr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdr.c Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,412 @@ +#include +#include +#include +#include +#include +#include +#include "opengl.h" + +#if defined(unix) || defined(__unix__) +#include +#include +#endif /* unix */ + +#include "sdr.h" + +static const char *sdrtypestr(unsigned int sdrtype); + +unsigned int create_vertex_shader(const char *src) +{ + return create_shader(src, GL_VERTEX_SHADER); +} + +unsigned int create_pixel_shader(const char *src) +{ + return create_shader(src, GL_FRAGMENT_SHADER); +} + +unsigned int create_tessctl_shader(const char *src) +{ +#ifdef GL_TESS_CONTROL_SHADER + return create_shader(src, GL_TESS_CONTROL_SHADER); +#else + return 0; +#endif +} + +unsigned int create_tesseval_shader(const char *src) +{ +#ifdef GL_TESS_EVALUATION_SHADER + return create_shader(src, GL_TESS_EVALUATION_SHADER); +#else + return 0; +#endif +} + +unsigned int create_geometry_shader(const char *src) +{ +#ifdef GL_GEOMETRY_SHADER + return create_shader(src, GL_GEOMETRY_SHADER); +#else + return 0; +#endif +} + +unsigned int create_shader(const char *src, unsigned int sdr_type) +{ + unsigned int sdr; + int success, info_len; + char *info_str = 0; + GLenum err; + + sdr = glCreateShader(sdr_type); + assert(glGetError() == GL_NO_ERROR); + glShaderSource(sdr, 1, &src, 0); + err = glGetError(); + assert(err == GL_NO_ERROR); + glCompileShader(sdr); + assert(glGetError() == GL_NO_ERROR); + + glGetShaderiv(sdr, GL_COMPILE_STATUS, &success); + assert(glGetError() == GL_NO_ERROR); + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len); + assert(glGetError() == GL_NO_ERROR); + + if(info_len) { + if((info_str = malloc(info_len + 1))) { + glGetShaderInfoLog(sdr, info_len, 0, info_str); + assert(glGetError() == GL_NO_ERROR); + info_str[info_len] = 0; + } + } + + if(success) { + fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str); + } else { + fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str); + glDeleteShader(sdr); + sdr = 0; + } + + free(info_str); + return sdr; +} + +void free_shader(unsigned int sdr) +{ + glDeleteShader(sdr); +} + +unsigned int load_vertex_shader(const char *fname) +{ + return load_shader(fname, GL_VERTEX_SHADER); +} + +unsigned int load_pixel_shader(const char *fname) +{ + return load_shader(fname, GL_FRAGMENT_SHADER); +} + +unsigned int load_tessctl_shader(const char *fname) +{ +#ifdef GL_TESS_CONTROL_SHADER + return load_shader(fname, GL_TESS_CONTROL_SHADER); +#else + return 0; +#endif +} + +unsigned int load_tesseval_shader(const char *fname) +{ +#ifdef GL_TESS_EVALUATION_SHADER + return load_shader(fname, GL_TESS_EVALUATION_SHADER); +#else + return 0; +#endif +} + +unsigned int load_geometry_shader(const char *fname) +{ +#ifdef GL_GEOMETRY_SHADER + return load_shader(fname, GL_GEOMETRY_SHADER); +#else + return 0; +#endif +} + +unsigned int load_shader(const char *fname, unsigned int sdr_type) +{ +#if defined(unix) || defined(__unix__) + struct stat st; +#endif + unsigned int sdr; + size_t filesize; + FILE *fp; + char *src; + + if(!(fp = fopen(fname, "rb"))) { + fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno)); + return 0; + } + +#if defined(unix) || defined(__unix__) + fstat(fileno(fp), &st); + filesize = st.st_size; +#else + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + fseek(fp, 0, SEEK_SET); +#endif /* unix */ + + if(!(src = malloc(filesize + 1))) { + fclose(fp); + return 0; + } + fread(src, 1, filesize, fp); + src[filesize] = 0; + fclose(fp); + + fprintf(stderr, "compiling %s shader: %s... ", sdrtypestr(sdr_type), fname); + sdr = create_shader(src, sdr_type); + + free(src); + return sdr; +} + + +/* ---- gpu programs ---- */ + +unsigned int create_program(void) +{ + unsigned int prog = glCreateProgram(); + assert(glGetError() == GL_NO_ERROR); + return prog; +} + +unsigned int create_program_link(unsigned int sdr0, ...) +{ + unsigned int prog, sdr; + va_list ap; + + if(!(prog = create_program())) { + return 0; + } + + attach_shader(prog, sdr0); + if(glGetError()) { + return 0; + } + + va_start(ap, sdr0); + while((sdr = va_arg(ap, unsigned int))) { + attach_shader(prog, sdr); + if(glGetError()) { + return 0; + } + } + va_end(ap); + + if(link_program(prog) == -1) { + free_program(prog); + return 0; + } + return prog; +} + +unsigned int create_program_load(const char *vfile, const char *pfile) +{ + unsigned int vs = 0, ps = 0; + + if(vfile && *vfile && !(vs = load_vertex_shader(vfile))) { + return 0; + } + if(pfile && *pfile && !(ps = load_pixel_shader(pfile))) { + return 0; + } + return create_program_link(vs, ps, 0); +} + +void free_program(unsigned int sdr) +{ + glDeleteProgram(sdr); +} + +void attach_shader(unsigned int prog, unsigned int sdr) +{ + if(prog && sdr) { + glAttachShader(prog, sdr); + if(glGetError() != GL_NO_ERROR) { + fprintf(stderr, "failed to attach shader %u to program %u\n", sdr, prog); + abort(); + } + } +} + +int link_program(unsigned int prog) +{ + int linked, info_len, retval = 0; + char *info_str = 0; + + glLinkProgram(prog); + assert(glGetError() == GL_NO_ERROR); + glGetProgramiv(prog, GL_LINK_STATUS, &linked); + assert(glGetError() == GL_NO_ERROR); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len); + assert(glGetError() == GL_NO_ERROR); + + if(info_len) { + if((info_str = malloc(info_len + 1))) { + glGetProgramInfoLog(prog, info_len, 0, info_str); + assert(glGetError() == GL_NO_ERROR); + info_str[info_len] = 0; + } + } + + if(linked) { + fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str); + } else { + fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str); + retval = -1; + } + + free(info_str); + return retval; +} + +int bind_program(unsigned int prog) +{ + GLenum err; + + glUseProgram(prog); + if(prog && (err = glGetError()) != GL_NO_ERROR) { + /* maybe the program is not linked, try linking first */ + if(err == GL_INVALID_OPERATION) { + if(link_program(prog) == -1) { + return -1; + } + glUseProgram(prog); + return glGetError() == GL_NO_ERROR ? 0 : -1; + } + return -1; + } + return 0; +} + +/* ugly but I'm not going to write the same bloody code over and over */ +#define BEGIN_UNIFORM_CODE \ + int loc, curr_prog; \ + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \ + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { \ + return -1; \ + } \ + if((loc = glGetUniformLocation(prog, name)) != -1) + +#define END_UNIFORM_CODE \ + if((unsigned int)curr_prog != prog) { \ + bind_program(curr_prog); \ + } \ + return loc == -1 ? -1 : 0 + +int set_uniform_int(unsigned int prog, const char *name, int val) +{ + BEGIN_UNIFORM_CODE { + glUniform1i(loc, val); + } + END_UNIFORM_CODE; +} + +int set_uniform_float(unsigned int prog, const char *name, float val) +{ + BEGIN_UNIFORM_CODE { + glUniform1f(loc, val); + } + END_UNIFORM_CODE; +} + +int set_uniform_float2(unsigned int prog, const char *name, float x, float y) +{ + BEGIN_UNIFORM_CODE { + glUniform2f(loc, x, y); + } + END_UNIFORM_CODE; +} + +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z) +{ + BEGIN_UNIFORM_CODE { + glUniform3f(loc, x, y, z); + } + END_UNIFORM_CODE; +} + +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w) +{ + BEGIN_UNIFORM_CODE { + glUniform4f(loc, x, y, z, w); + } + END_UNIFORM_CODE; +} + +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat) +{ + BEGIN_UNIFORM_CODE { + glUniformMatrix4fv(loc, 1, GL_FALSE, mat); + } + END_UNIFORM_CODE; +} + +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat) +{ + BEGIN_UNIFORM_CODE { + glUniformMatrix4fv(loc, 1, GL_TRUE, mat); + } + END_UNIFORM_CODE; +} + +int get_attrib_loc(unsigned int prog, const char *name) +{ + int loc, curr_prog; + + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { + return -1; + } + + loc = glGetAttribLocation(prog, (char*)name); + + if((unsigned int)curr_prog != prog) { + bind_program(curr_prog); + } + return loc; +} + +void set_attrib_float3(int attr_loc, float x, float y, float z) +{ + glVertexAttrib3f(attr_loc, x, y, z); +} + +static const char *sdrtypestr(unsigned int sdrtype) +{ + switch(sdrtype) { + case GL_VERTEX_SHADER: + return "vertex"; + case GL_FRAGMENT_SHADER: + return "pixel"; +#ifdef GL_TESS_CONTROL_SHADER + case GL_TESS_CONTROL_SHADER: + return "tessellation control"; +#endif +#ifdef GL_TESS_EVALUATION_SHADER + case GL_TESS_EVALUATION_SHADER: + return "tessellation evaluation"; +#endif +#ifdef GL_GEOMETRY_SHADER + case GL_GEOMETRY_SHADER: + return "geometry"; +#endif + + default: + break; + } + return ""; +} diff -r d1b456d08713 -r c71c477521ca src/sdr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdr.h Sun May 31 00:40:26 2015 +0300 @@ -0,0 +1,52 @@ +#ifndef SDR_H_ +#define SDR_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* ---- shaders ---- */ +unsigned int create_vertex_shader(const char *src); +unsigned int create_pixel_shader(const char *src); +unsigned int create_tessctl_shader(const char *src); +unsigned int create_tesseval_shader(const char *src); +unsigned int create_geometry_shader(const char *src); +unsigned int create_shader(const char *src, unsigned int sdr_type); +void free_shader(unsigned int sdr); + +unsigned int load_vertex_shader(const char *fname); +unsigned int load_pixel_shader(const char *fname); +unsigned int load_tessctl_shader(const char *fname); +unsigned int load_tesseval_shader(const char *fname); +unsigned int load_geometry_shader(const char *fname); +unsigned int load_shader(const char *src, unsigned int sdr_type); + +int add_shader(const char *fname, unsigned int sdr); +int remove_shader(const char *fname); + +/* ---- gpu programs ---- */ +unsigned int create_program(void); +unsigned int create_program_link(unsigned int sdr0, ...); +unsigned int create_program_load(const char *vfile, const char *pfile); +void free_program(unsigned int sdr); + +void attach_shader(unsigned int prog, unsigned int sdr); +int link_program(unsigned int prog); +int bind_program(unsigned int prog); + +int set_uniform_int(unsigned int prog, const char *name, int val); +int set_uniform_float(unsigned int prog, const char *name, float val); +int set_uniform_float2(unsigned int prog, const char *name, float x, float y); +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z); +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w); +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat); +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat); + +int get_attrib_loc(unsigned int prog, const char *name); +void set_attrib_float3(int attr_loc, float x, float y, float z); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SDR_H_ */