diff options
Diffstat (limited to 'intern')
505 files changed, 97280 insertions, 0 deletions
diff --git a/intern/BL-license.txt b/intern/BL-license.txt new file mode 100644 index 00000000000..606d3ef6cef --- /dev/null +++ b/intern/BL-license.txt @@ -0,0 +1,48 @@ +Blender License 1.0 (the "BL", see http://www.blender.org/BL/ ). + +Copyright (C) 2002 Blender Foundation. All Rights Reserved. + +For teams that don't want to operate under the GPL, we're also offering +this "non-GPL" Blender License option. This means that you can download +the latest sources and tools via FTP or CVS from our site and sign an +additional agreement with the Blender Foundation, so you can keep your +source modifications confidential. Contact the Blender Foundation via +email at license@blender.org so we can discuss how we handle the +practical matters. + +A signed agreement allows you to do business with proprietary code, make +special derived versions, sell executables, projects or services, +provided that: + +1. The BL-ed code remains copyrighted by the original owners, and cannot +be transferred to other parties + +2. The BL-ed code cannot be published or re-distributed in any way, and +only be available for the internal staff that works directly on the +software itself. Employees of partners with which you co-develop on the +projects that include BL-ed code are considered 'internal staff' also. + +3. The BL-ed code can be used (sold, distributed) in parts or in its +whole only as an executable or as a compiled library/module and its +header files. + +4. The usage of the name Blender or the Blender logo is not included in +this license. Instead 'including Blender Foundation release X' (or +similar) can be used, with 'X' the version number of the initial Blender +Foundation release which you started with. + +5. Note that this BL has no authority over some of the external +libraries licenses which Blender links with. + +Additionally you get : + +1. The right to use Blender Foundation source updates for a 1 year +period. + +2. Support. Details to be determined by the additional agreement. + +You are invited to donate your proprietary changes back to the open +source community after a reasonable time period. You are of course free +to choose not to do this. + +End of BL terms and conditions. diff --git a/intern/GPL-license.txt b/intern/GPL-license.txt new file mode 100644 index 00000000000..14db8fc79db --- /dev/null +++ b/intern/GPL-license.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/intern/Makefile b/intern/Makefile new file mode 100644 index 00000000000..e17cc62a4e6 --- /dev/null +++ b/intern/Makefile @@ -0,0 +1,38 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# Bounces make to subdirectories. Intended for future tinderbox tests. + +SOURCEDIR = intern + +DIRS = ghost guardedalloc bmfont decimation string memutil action moto +DIRS += iksolver keymaker container + +include nan_subdirs.mk diff --git a/intern/SoundSystem/Makefile b/intern/SoundSystem/Makefile new file mode 100644 index 00000000000..e7f9760cc3c --- /dev/null +++ b/intern/SoundSystem/Makefile @@ -0,0 +1,54 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# +# + +include nan_definitions.mk + +SOURCEDIR = source/gameengine/SoundSystem +DIR = $(OCGDIR)/SoundSystem +DIRS = intern +DIRS += dummy + +ifeq ($(OS),windows) + DIRS += fmod + DIRS += openal +endif +ifeq ($(OS),freebsd) + DIRS += openal +endif +ifeq ($(OS),$(findstring $(OS), "linux")) + ifeq ($(CPU),i386) + DIRS += openal + endif +endif + +include nan_subdirs.mk diff --git a/intern/SoundSystem/SND_C-api.h b/intern/SoundSystem/SND_C-api.h new file mode 100644 index 00000000000..9c24438c131 --- /dev/null +++ b/intern/SoundSystem/SND_C-api.h @@ -0,0 +1,356 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef SND_BLENDER_H +#define SND_BLENDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "SoundDefines.h" + +#define SND_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name + +SND_DECLARE_HANDLE(SND_AudioDeviceInterfaceHandle); +SND_DECLARE_HANDLE(SND_SceneHandle); +SND_DECLARE_HANDLE(SND_ObjectHandle); +SND_DECLARE_HANDLE(SND_ListenerHandle); + +/** + * set the specified type + */ +extern void SND_SetDeviceType(int device_type); + +/** + * get an audiodevice + */ +extern SND_AudioDeviceInterfaceHandle SND_GetAudioDevice(void); + +/** + * and let go of it + */ +extern void SND_ReleaseDevice(void); + +/** + * check if playback is desired + */ +extern int SND_IsPlaybackWanted(SND_SceneHandle scene); + +/** + * add memlocation to cache + */ +extern int SND_AddSample(SND_SceneHandle scene, + const char* filename, + void* memlocation, + int size); + +/** + * remove all samples + */ +extern void SND_RemoveAllSamples(SND_SceneHandle scene); + +/** + * forces the object to check its buffer, and fix it if it's wrong + */ +extern int SND_CheckBuffer(SND_SceneHandle scene, SND_ObjectHandle object); + +/** + * Creates a scene, initializes it and returns a handle to that scene. + * + * @param audiodevice: handle to the audiodevice. + */ +extern SND_SceneHandle SND_CreateScene(SND_AudioDeviceInterfaceHandle audiodevice); + +/** + * Stops all sounds, suspends the scene (so all resources will be freed) and deletes the scene. + * + * @param scene: handle to the soundscene. + */ +extern void SND_DeleteScene(SND_SceneHandle scene); + +/** + * Adds a soundobject to the scene, gets the buffer the sample is loaded into. + * + * @param scene: handle to the soundscene. + * @param object: handle to soundobject. + */ +extern void SND_AddSound(SND_SceneHandle scene, SND_ObjectHandle object); + +/** + * Removes a soundobject from the scene. + * + * @param scene: handle to the soundscene. + * @param object: handle to soundobject. + */ +extern void SND_RemoveSound(SND_SceneHandle scene, SND_ObjectHandle object); + +/** + * Removes all soundobjects from the scene. + * + * @param scene: handle to the soundscene. + */ +extern void SND_RemoveAllSounds(SND_SceneHandle scene); + +/** + * Stopss all soundobjects in the scene. + * + * @param scene: handle to the soundscene. + */ +extern void SND_StopAllSounds(SND_SceneHandle scene); + +/** + * Updates the listener, checks the status of all soundobjects, builds a list of all active + * objects, updates the active objects. + * + * @param audiodevice: handle to the audiodevice. + * @param scene: handle to the soundscene. + */ +extern void SND_Proceed(SND_AudioDeviceInterfaceHandle audiodevice, SND_SceneHandle scene); + +/** + * Returns a handle to the listener. + * + * @param scene: handle to the soundscene. + */ +extern SND_ListenerHandle SND_GetListener(SND_SceneHandle scene); + +/** + * Sets the gain of the listener. + * + * @param scene: handle to the soundscene. + * @param gain: factor the gain gets multiplied with. + */ +extern void SND_SetListenerGain(SND_SceneHandle scene, double gain); + +/** + * Sets a scaling to exaggerate or deemphasize the Doppler (pitch) shift resulting from the + * calculation. + * @attention $f' = dopplerfactor * f * frac{dopplervelocity - listener_velocity}{dopplervelocity + object_velocity}$ + * @attention f: frequency in sample (soundobject) + * @attention f': effective Doppler shifted frequency + * + * @param object: handle to soundobject. + * @param dopplerfactor: the dopplerfactor. + */ +extern void SND_SetDopplerFactor(SND_SceneHandle scene, double dopplerfactor); + +/** + * Sets the value of the propagation speed relative to which the source velocities are interpreted. + * @attention $f' = dopplerfactor * f * frac{dopplervelocity - listener_velocity}{dopplervelocity + object_velocity}$ + * @attention f: frequency in sample (soundobject) + * @attention f': effective Doppler shifted frequency + * + * @param object: handle to soundobject. + * @param dopplervelocity: the dopplervelocity. + */ +extern void SND_SetDopplerVelocity(SND_SceneHandle scene, double dopplervelocity); + +/** + * Creates a new soundobject and returns a handle to it. + */ +extern SND_ObjectHandle SND_CreateSound(void); + +/** + * Deletes a soundobject. + * + * @param object: handle to soundobject. + */ +extern void SND_DeleteSound(SND_ObjectHandle object); + +/** + * Sets a soundobject to SND_MUST_PLAY, so with the next proceed it will be updated and played. + * + * @param object: handle to soundobject. + */ +extern void SND_StartSound(SND_SceneHandle scene, SND_ObjectHandle object); + +/** + * Sets a soundobject to SND_MUST_STOP, so with the next proceed it will be stopped. + * + * @param object: handle to soundobject. + */ +extern void SND_StopSound(SND_SceneHandle scene, SND_ObjectHandle object); + +/** + * Sets a soundobject to SND_MUST_PAUSE, so with the next proceed it will be paused. + * + * @param object: handle to soundobject. + */ +extern void SND_PauseSound(SND_SceneHandle scene, SND_ObjectHandle object); + +/** + * Sets the name of the sample to reference the soundobject to it. + * + * @param object: handle to soundobject. + * @param samplename: the name of the sample + */ +extern void SND_SetSampleName(SND_ObjectHandle object, char* samplename); + +/** + * Sets the gain of a soundobject. + * + * @param object: handle to soundobject. + * @param gain: factor the gain gets multiplied with. + */ +extern void SND_SetGain(SND_ObjectHandle object, double gain); + +/** + * Sets the minimum gain of a soundobject. + * + * @param object: handle to soundobject. + * @param minimumgain: lower threshold for the gain. + */ +extern void SND_SetMinimumGain(SND_ObjectHandle object, double minimumgain); + +/** + * Sets the maximum gain of a soundobject. + * + * @param object: handle to soundobject. + * @param maximumgain: upper threshold for the gain. + */ +extern void SND_SetMaximumGain(SND_ObjectHandle object, double maximumgain); + +/** + * Sets the rollofffactor. The rollofffactor is a per-Source parameter the application + * can use to increase or decrease the range of a source by decreasing or increasing the + * attenuation, respectively. The default value is 1. The implementation is free to optimize + * for a rollofffactor value of 0, which indicates that the application does not wish any + * distance attenuation on the respective Source. + * + * @param object: handle to soundobject. + * @param rollofffactor: the rollofffactor. + */ +extern void SND_SetRollOffFactor(SND_ObjectHandle object, double rollofffactor); + +/** + * Sets the referencedistance at which the listener will experience gain. + * @attention G_dB = gain - 20 * log10(1 + rollofffactor * (dist - referencedistance)/referencedistance); + * + * @param object: handle to soundobject. + * @param distance: the reference distance. + */ +extern void SND_SetReferenceDistance(SND_ObjectHandle object, double referencedistance); + +/** + * Sets the pitch of a soundobject. + * + * @param object: handle to soundobject. + * @param pitch: pitchingfactor: 2.0 for doubling the frequency, 0.5 for half the frequency. + */ +extern void SND_SetPitch(SND_ObjectHandle object, double pitch); + +/** + * Sets the position a soundobject. + * + * @param object: handle to soundobject. + * @param position: position[3]. + */ +extern void SND_SetPosition(SND_ObjectHandle object, double* position); + +/** + * Sets the velocity of a soundobject. + * + * @param object: handle to soundobject. + * @param velocity: velocity[3]. + */ +extern void SND_SetVelocity(SND_ObjectHandle object, double* velocity); + +/** + * Sets the orientation of a soundobject. + * + * @param object: handle to soundobject. + * @param orientation: orientation[9]. + */ +extern void SND_SetOrientation(SND_ObjectHandle object, double* orientation); + +/** + * Sets the loopmode of a soundobject. + * + * @param object: handle to soundobject. + * @param loopmode type of the loop (SND_LOOP_OFF, SND_LOOP_NORMAL, SND_LOOP_BIDIRECTIONAL); + */ +extern void SND_SetLoopMode(SND_ObjectHandle object, int loopmode); + +/** + * Sets the looppoints of a soundobject. + * + * @param object: handle to soundobject. + * @param loopstart startpoint of the loop + * @param loopend endpoint of the loop + */ +extern void SND_SetLoopPoints(SND_ObjectHandle object, unsigned int loopstart, unsigned int loopend); + +/** + * Gets the gain of a soundobject. + * + * @param object: handle to soundobject. + */ +extern float SND_GetGain(SND_ObjectHandle object); + +/** + * Gets the pitch of a soundobject. + * + * @param object: handle to soundobject. + */ +extern float SND_GetPitch(SND_ObjectHandle object); + +/** + * Gets the looping of a soundobject. + * 0: SND_LOOP_OFF + * 1: SND_LOOP_NORMAL + * 2: SND_LOOP_BIDIRECTIONAL + * + * @param object: handle to soundobject. + */ +extern int SND_GetLoopMode(SND_ObjectHandle object); + +/** + * Gets the playstate of a soundobject. + * SND_UNKNOWN = -1 + * SND_INITIAL + * SND_MUST_PLAY + * SND_PLAYING + * SND_MUST_STOP + * SND_STOPPED + * SND_MUST_PAUSE + * SND_PAUSED + * SND_MUST_BE_DELETED + * + * @param object: handle to soundobject. + */ +extern int SND_GetPlaystate(SND_ObjectHandle object); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/intern/SoundSystem/SND_CDObject.h b/intern/SoundSystem/SND_CDObject.h new file mode 100644 index 00000000000..59817d72485 --- /dev/null +++ b/intern/SoundSystem/SND_CDObject.h @@ -0,0 +1,84 @@ +/* + * SND_CDObject.h + * + * Implementation for CD playback + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef __SND_CDOBJECT_H +#define __SND_CDOBJECT_H + +#include "SND_Object.h" + +class SND_CDObject : public SND_Object +{ +private: + + /** + * Private to enforce singleton + */ + SND_CDObject(); + SND_CDObject(const SND_CDObject&); + + static SND_CDObject* m_instance; + MT_Scalar m_gain; /* the gain of the object */ + int m_playmode; /* the way CD is played back (all, random, track, trackloop) */ + int m_track; /* the track for 'track' and 'trackloop' */ + int m_playstate; /* flag for current state of object */ + bool m_modified; + bool m_used; /* flag for checking if we used the cd, if not don't + call the stop cd at the end */ + +public: + static bool CreateSystem(); + static bool DisposeSystem(); + static SND_CDObject* Instance(); + + ~SND_CDObject(); + + void SetGain(MT_Scalar gain); + void SetPlaymode(int playmode); + void SetTrack(int track); + void SetPlaystate(int playstate); + void SetModified(bool modified); + void SetUsed(); + bool GetUsed(); + + bool IsModified() const; + + int GetTrack() const; + MT_Scalar GetGain() const; + int GetPlaymode() const; + int GetPlaystate() const; + +}; +#endif //__SND_CDOBJECT_H diff --git a/intern/SoundSystem/SND_DependKludge.h b/intern/SoundSystem/SND_DependKludge.h new file mode 100644 index 00000000000..b1272725f9e --- /dev/null +++ b/intern/SoundSystem/SND_DependKludge.h @@ -0,0 +1,56 @@ +/* + * SND_DependKludge.h + * + * who needs what? + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + + +#if defined (_WIN32) +#define USE_FMOD +#else +# if defined (__linux__) +# if defined (__i386__) +# define USE_OPENAL +# endif +# else +# if defined (__FreeBSD__) +# define USE_OPENAL +# endif +# ifdef USE_OPENAL +# undef USE_OPENAL +# endif +# ifdef USE_FMOD +# undef USE_FMOD +# endif +# endif +#endif diff --git a/intern/SoundSystem/SND_DeviceManager.h b/intern/SoundSystem/SND_DeviceManager.h new file mode 100644 index 00000000000..7e643779cfe --- /dev/null +++ b/intern/SoundSystem/SND_DeviceManager.h @@ -0,0 +1,91 @@ +/* + * SND_DeviceManager.h + * + * singleton for creating, switching and deleting audiodevices + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef __SND_DEVICEMANAGER_H +#define __SND_DEVICEMANAGER_H + +#include "SND_IAudioDevice.h" + +class SND_DeviceManager +{ +public : + + /** + * a subscription is needed before instances are given away + * applications must call subscribe first, get an instance, and + * when they are finished with sound, unsubscribe + */ + static void Subscribe(); + static void Unsubscribe(); + + static SND_IAudioDevice* Instance(); + static void SetDeviceType(int device_type); + +private : + + /** + * Private to enforce singleton + */ + SND_DeviceManager(); + SND_DeviceManager(const SND_DeviceManager&); + ~SND_DeviceManager(); + + static SND_IAudioDevice* m_instance; + + /** + * The type of device to be created on a call + * to Instance(). + */ + static int m_device_type; + + /** + * Remember the number of subscriptions. + * if 0, delete the device + */ + static int m_subscriptions;; +}; + +#endif //__SND_DEVICEMANAGER_H + + + + + + + + + +
\ No newline at end of file diff --git a/intern/SoundSystem/SND_IAudioDevice.h b/intern/SoundSystem/SND_IAudioDevice.h new file mode 100644 index 00000000000..6bcc8f0c072 --- /dev/null +++ b/intern/SoundSystem/SND_IAudioDevice.h @@ -0,0 +1,346 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef SND_IAUDIODEVICE +#define SND_IAUDIODEVICE + +#include "SND_SoundObject.h" +#include "SND_CDObject.h" +#include "SND_WaveCache.h" +#include "SND_WaveSlot.h" +#include "MT_Matrix3x3.h" + + +class SND_IAudioDevice +{ +public: + + /** + * constructor + */ + SND_IAudioDevice() {}; + + /** + * destructor + */ + virtual ~SND_IAudioDevice() {}; + + /** + * check to see if initialization was successfull + * + * @return indication of succes + */ + virtual bool IsInitialized()=0; + + /** + * get the wavecache (which does sample (un)loading) + * + * @return pointer to the wavecache + */ + virtual SND_WaveCache* GetWaveCache() const =0; + + /** + * loads a sample into the device + * + * @param samplename the name of the sample + * @param memlocation pointer where the sample is stored + * @param size size of the sample in memory + * + * @return pointer to the slot with sample data + */ + virtual SND_WaveSlot* LoadSample(const STR_String& samplename, + void* memlocation, + int size)=0; + + /** + * remove a sample from the wavecache + * + * @param filename pointer to filename + */ +// virtual void RemoveSample(const char* filename)=0; + + /** + * remove all samples from the wavecache + */ + virtual void RemoveAllSamples()=0; + + /** + * get a new id from the device + * + * @param pObject pointer to soundobject + * + * @return indication of success + */ + virtual bool GetNewId(SND_SoundObject* pObject)=0; + + /** + * clear an id + * + * @param pObject pointer to soundobject + */ + virtual void ClearId(SND_SoundObject* pObject)=0; + + /** + * initialize the listener + */ + virtual void InitListener()=0; + + /** + * set the value of the propagation speed relative to which the + * source velocities are interpreted. + * f' = DOPPLER_FACTOR * f * (DOPPLER_VELOCITY - Vl) / (DOPPLER_VELOCITY + Vo) + * f: frequency in sample (soundobject) + * f': effective Doppler shifted frequency + * Vl: velocity listener + * Vo: velocity soundobject + * + * @param dopplervelocity scaling factor for doppler effect + */ + virtual void SetDopplerVelocity(MT_Scalar dopplervelocity) const =0; + + /** + * set a scaling to exaggerate or deemphasize the Doppler (pitch) + * shift resulting from the calculation. + * f' = DOPPLER_FACTOR * f * (DOPPLER_VELOCITY - Listener_velocity )/(DOPPLER_VELOCITY + object_velocity ) + * + * @param dopplerfactor scaling factor for doppler effect + */ + virtual void SetDopplerFactor(MT_Scalar dopplerfactor) const =0; + + /** + * set the roll-off factor + * + * @param rollofffactor a global volume scaling factor + */ + virtual void SetListenerRollOffFactor(MT_Scalar rollofffactor) const =0; + + /** + * make the context the current one + */ + virtual void MakeCurrent() const =0; + + /** + * update the device + */ + virtual void NextFrame() const =0; + + /** + * set the volume of the listener. + * + * @param gain the mastergain + */ + virtual void SetListenerGain(float gain) const =0; + + /** + * connect the buffer with the source + * + * @param id the id of the object + * @param buffer the buffer the sample is stored in + */ + virtual void SetObjectBuffer(int id, unsigned int buffer)=0; + + /** + * pause playback of the cd + * @param id the id of the object + * + * @return the state the object is in + */ + virtual int GetPlayState(int id) =0; + + /** + * play a sound belonging to an object. + * + * @param id the id of the object + */ + virtual void PlayObject(int id) =0; + + /** + * stop a sound belonging to an object. + * + * @param id the id of the object + */ + virtual void StopObject(int id) const =0; + + /** + * stop all sounds. + */ + virtual void StopAllObjects()=0; + + /** + * pause the sound belonging to an object. + * + * @param id the id of the object + */ + virtual void PauseObject(int id) const =0; + + /** + * set the sound to looping or non-looping. + * + * @param id the id of the object + * @param loopmode type of looping (no loop, normal, bidirectional) + */ + virtual void SetObjectLoop(int id, unsigned int loopmode) const =0; + + /** + * set the looppoints of a sound + * + * @param id the id of the object + * @param loopstart the startpoint of the loop (in samples) + * @param loopend the endpoint of the loop (in samples) + */ + virtual void SetObjectLoopPoints(int id, unsigned int loopstart, unsigned int loopend) const =0; + + /** + * set the pitch of the sound. + * + * @param id the id of the object + * @param pitch the pitch + */ + virtual void SetObjectPitch(int id, MT_Scalar pitch) const =0; + + /** + * set the gain of the sound. + * + * @param id the id of the object + * @param gain the gain + */ + virtual void SetObjectGain(int id, MT_Scalar gain) const =0; + + /** + * ROLLOFF_FACTOR is per-Source parameter the application can use to increase or decrease + * the range of a source by decreasing or increasing the attenuation, respectively. The + * default value is 1. The implementation is free to optimize for a ROLLOFF_FACTOR value + * of 0, which indicates that the application does not wish any distance attenuation on + * the respective Source. + * + * @param id the id of the object + * @param rolloff a per-source volume scaling factor + */ + virtual void SetObjectRollOffFactor(int id, MT_Scalar rolloff) const =0; + + /** + * min_gain indicates the minimal gain which is always guaranteed for this sound + * + * @param id the id of the object + * @param mingain the minimum gain of the object + */ + virtual void SetObjectMinGain(int id, MT_Scalar mingain) const =0; + + /** + * max_gain indicates the maximal gain which is always guaranteed for this sound + * + * @param id the id of the object + * @param maxgain the maximum gain of the object + */ + virtual void SetObjectMaxGain(int id, MT_Scalar maxgain) const =0; + /** + * set the distance at which the Listener will experience gain. + * G_dB = GAIN - 20*log10(1 + ROLLOFF_FACTOR*(dist-REFERENCE_DISTANCE)/REFERENCE_DISTANCE ); + * + * @param id the id of the object + * @param referencedistance the distance at which the listener will start hearing + */ + virtual void SetObjectReferenceDistance(int id, MT_Scalar referencedistance) const =0; + + /** + * set the position, velocity and orientation of a sound. + * + * @param id the id of the object + * @param position the position of the object + * @param velocity the velocity of the object + * @param orientation the orientation of the object + * @param lisposition the position of the listener + * @param rollofffactor the rollofffactor of the object + */ + virtual void SetObjectTransform(int id, + const MT_Vector3& position, + const MT_Vector3& velocity, + const MT_Matrix3x3& orientation, + const MT_Vector3& lisposition, + const MT_Scalar& rollofffactor) const =0; + + /** + * make a sound 2D + * + * @param id the id of the object + */ + virtual void ObjectIs2D(int id) const =0; + + /** + * tell the device we want cd suppport + */ + virtual void UseCD() const =0; + + /** + * start playback of the cd + * + * @param track the tracknumber to start playback from + */ + virtual void PlayCD(int track) const =0; + + /** + * pause playback of the cd (true == pause, false == resume) + */ + virtual void PauseCD(bool pause) const =0; + + /** + * stop playback of the cd + */ + virtual void StopCD() const =0; + + /** + * set the playbackmode of the cd + * SND_CD_ALL play all tracks + * SND_CD_TRACK play one track + * SND_CD_TRACKLOOP play one track looped + * SND_CD_RANDOM play all tracks in random order + * + * @param playmode playmode + */ + virtual void SetCDPlaymode(int playmode) const =0; + + /** + * set the volume playback of the cd + * + * @param gain the gain + */ + virtual void SetCDGain(MT_Scalar gain) const =0; + + virtual void StartUsingDSP() =0; + virtual float* GetSpectrum() =0; + virtual void StopUsingDSP() =0; + +protected: + + virtual void RevokeSoundObject(SND_SoundObject* pObject)=0; +}; + +#endif //SND_IAUDIODEVICE diff --git a/intern/SoundSystem/SND_Object.h b/intern/SoundSystem/SND_Object.h new file mode 100644 index 00000000000..2ae9bcc1dd0 --- /dev/null +++ b/intern/SoundSystem/SND_Object.h @@ -0,0 +1,55 @@ +/* + * SND_Object.h + * + * Abstract sound object + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef __SND_OBJECT_H +#define __SND_OBJECT_H + +#include "GEN_List.h" +#include "MT_Matrix3x3.h" +#include "SoundDefines.h" + +/** + * SND_Object is an interface class for soundobjects, listeners and other + * kinds of sound related thingies. + */ + +class SND_Object : public GEN_Link +{ +public: + SND_Object() {}; + virtual ~SND_Object() {}; +}; +#endif //__SND_OBJECT_H diff --git a/intern/SoundSystem/SND_Scene.h b/intern/SoundSystem/SND_Scene.h new file mode 100644 index 00000000000..c2f6e5d8c48 --- /dev/null +++ b/intern/SoundSystem/SND_Scene.h @@ -0,0 +1,106 @@ +/* + * SND_Scene.h + * + * The scene for sounds. + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifdef WIN32 +#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning +#endif //WIN32 + +#ifndef __SND_SCENE_H +#define __SND_SCENE_H + +#include "SoundDefines.h" +#include "SND_SoundObject.h" +#include "SND_CDObject.h" +#include "SND_SoundListener.h" +#include "SND_WaveSlot.h" + +#include "MT_Vector3.h" +#include "MT_Matrix3x3.h" +#include "STR_String.h" + +#include <set> + + +class SND_Scene +{ + std::set<class SND_SoundObject*> m_soundobjects; + + GEN_List m_activeobjects; + class SND_IAudioDevice* m_audiodevice; + class SND_WaveCache* m_wavecache; + class SND_SoundListener m_listener; + bool m_audio; // to check if audio works + bool m_audioplayback; // to check if audioplayback is wanted + + void UpdateListener(); + void BuildActiveList(MT_Scalar curtime); + void UpdateActiveObects(); + void UpdateCD(); + +public: + SND_Scene(SND_IAudioDevice* adi); + ~SND_Scene(); + + bool IsPlaybackWanted(); + + void AddActiveObject(SND_SoundObject* pObject, MT_Scalar curtime); + void RemoveActiveObject(SND_SoundObject* pObject); + void DeleteObjectWhenFinished(SND_SoundObject* pObject); + + void Proceed(); + + int LoadSample(const STR_String& samplename, + void* memlocation, + int size); + void RemoveAllSamples(); + bool CheckBuffer(SND_SoundObject* pObject); + bool IsSampleLoaded(STR_String& samplename); + + void AddObject(SND_SoundObject* pObject); + bool SetCDObject(SND_CDObject* cdobject); + void DeleteObject(SND_SoundObject* pObject); + void RemoveAllObjects(); + void StopAllObjects(); + int GetObjectStatus(SND_SoundObject* pObject) const; + + void SetListenerTransform(const MT_Vector3& pos, + const MT_Vector3& vel, + const MT_Matrix3x3& mat); + + SND_SoundListener* GetListener(); +}; + +#endif //__SND_SCENE_H diff --git a/intern/SoundSystem/SND_SoundListener.h b/intern/SoundSystem/SND_SoundListener.h new file mode 100644 index 00000000000..63d8eb65942 --- /dev/null +++ b/intern/SoundSystem/SND_SoundListener.h @@ -0,0 +1,84 @@ +/* + * SND_SoundListener.h + * + * A SoundListener is for sound what a camera is for vision. + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef __SND_SOUNDLISTENER_H +#define __SND_SOUNDLISTENER_H + +#include "SND_Object.h" + + +class SND_SoundListener : public SND_Object +{ +public: + SND_SoundListener(); + virtual ~SND_SoundListener(); + + void SetStateFlag(unsigned int stateflags); + void SetGain(MT_Scalar gain); + void SetPosition(const MT_Vector3& pos); + void SetVelocity(const MT_Vector3& vel); + void SetOrientation(const MT_Matrix3x3& ori); + void SetDopplerFactor(MT_Scalar dopplerfactor); + void SetDopplerVelocity(MT_Scalar dopplervelocity); + void SetScale(MT_Scalar scale); + + void SetModified(bool modified); + bool IsModified() const; + + unsigned int GetStateFlags() const; + MT_Scalar GetGain() const; + MT_Vector3 GetPosition() const; + MT_Vector3 GetVelocity() const; + MT_Matrix3x3 GetOrientation(); + + MT_Scalar GetDopplerFactor() const; + MT_Scalar GetDopplerVelocity() const; + MT_Scalar GetScale() const; + +private: + void* m_listener; + bool m_modified; + + MT_Scalar m_gain; /* overall gain */ + MT_Vector3 m_position; /* position; left/right, up/down, in/out */ + MT_Vector3 m_velocity; /* velocity of the listener */ + MT_Matrix3x3 m_orientation; /* orientation of the listener */ + + MT_Scalar m_dopplerfactor; /* scaling factor for the Doppler (pitch) shift */ + MT_Scalar m_dopplervelocity; /* factor for the reference velocity (for Dopplereffect) */ + MT_Scalar m_scale; +}; +#endif //__SND_SOUNDLISTENER_H diff --git a/intern/SoundSystem/SND_SoundObject.h b/intern/SoundSystem/SND_SoundObject.h new file mode 100644 index 00000000000..4c47cdc27b5 --- /dev/null +++ b/intern/SoundSystem/SND_SoundObject.h @@ -0,0 +1,162 @@ +/* + * SND_SoundObject.h + * + * Implementation of the abstract sound object + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef __SND_SOUNDOBJECT_H +#define __SND_SOUNDOBJECT_H + +#include "SND_Object.h" +#include "STR_String.h" + + +/** + * SND_SoundObject is a class for api independent sounddata storage conected to an actuator + */ + +class SND_SoundObject : public SND_Object +{ +private: + STR_String m_samplename; /* name of the sample */ + STR_String m_objectname; /* name of the object */ + unsigned int m_buffer; + + bool m_active; /* is the object active or not? */ + int m_id; + MT_Scalar m_lifespan; /* the lifespan of the sound seconds */ + MT_Scalar m_timestamp; + + MT_Scalar m_length; /* length of the sample in seconds */ + + MT_Scalar m_gain; /* the gain of the object */ + MT_Scalar m_rollofffactor; /* the scaling factor to increase or decrease the range + of a source by decreasing or increasing the + attenuation, respectively */ + MT_Scalar m_referencedistance;/* the distance at which the listener will experience + gain */ + MT_Scalar m_mingain; /* indicates the minimal gain which is always guaranteed + for this source */ + MT_Scalar m_maxgain; /* indicates the maximal gain which is always guaranteed + for this source */ + + MT_Scalar m_pitch; /* the pitch of the object */ + MT_Vector3 m_position; /* position; left/right, up/down, in/out */ + MT_Vector3 m_velocity; /* velocity of the object */ + MT_Matrix3x3 m_orientation; /* orientation of the object */ + unsigned int m_loopmode; /* loop normal or bidirectional? */ + unsigned int m_loopstart; /* start of looppoint in samples! */ + unsigned int m_loopend; /* end of looppoint in samples! */ + bool m_is3d; /* is the object 3D or 2D? */ + int m_playstate; /* flag for current state of object */ + bool m_modified; + unsigned int m_running; + bool m_highpriority; /* may the sound be ditched when we run out of voices? */ + +public: + + SND_SoundObject(); + ~SND_SoundObject(); + + void SetBuffer(unsigned int buffer); + void SetActive(bool active); + + void StartSound(); + void StopSound(); + void PauseSound(); + void DeleteWhenFinished(); + + void SetObjectName(STR_String objectname); + void SetSampleName(STR_String samplename); + void SetLength(MT_Scalar length); + + void SetPitch(MT_Scalar pitch); + void SetGain(MT_Scalar gain); + void SetMinGain(MT_Scalar mingain); + void SetMaxGain(MT_Scalar maxgain); + void SetRollOffFactor(MT_Scalar rollofffactor); + void SetReferenceDistance(MT_Scalar distance); + void SetPosition(const MT_Vector3& pos); + void SetVelocity(const MT_Vector3& vel); + void SetOrientation(const MT_Matrix3x3& orient); + void SetLoopMode(unsigned int loopmode); + void SetLoopStart(unsigned int loopstart); + void SetLoopEnd(unsigned int loopend); + void Set3D(bool threedee); + void SetPlaystate(int playstate); + void SetHighPriority(bool priority); + + void SetId(int id); + void SetLifeSpan(); + void SetTimeStamp(MT_Scalar timestamp); + + void SetModified(bool modified); + + bool IsLifeSpanOver(MT_Scalar curtime) const; + bool IsActive() const; + bool IsModified() const; + bool IsHighPriority() const; + + void InitRunning(); + bool IsRunning() const; + void AddRunning(); + + int GetId() const; + MT_Scalar GetLifeSpan() const; + MT_Scalar GetTimestamp() const; + + unsigned int GetBuffer(); + const STR_String& GetSampleName(); + const STR_String& GetObjectName(); + + MT_Scalar GetLength() const; + MT_Scalar GetGain() const; + MT_Scalar GetPitch() const; + + MT_Scalar GetMinGain() const; + MT_Scalar GetMaxGain() const; + MT_Scalar GetRollOffFactor() const; + MT_Scalar GetReferenceDistance() const; + + MT_Vector3 GetPosition() const; + MT_Vector3 GetVelocity() const; + MT_Matrix3x3 GetOrientation() const; + unsigned int GetLoopMode() const; + unsigned int GetLoopStart() const; + unsigned int GetLoopEnd() const; + bool Is3D() const; + int GetPlaystate() const; + +}; +#endif //__SND_SOUNDOBJECT_H + diff --git a/intern/SoundSystem/SND_Utils.h b/intern/SoundSystem/SND_Utils.h new file mode 100644 index 00000000000..c9c3774b180 --- /dev/null +++ b/intern/SoundSystem/SND_Utils.h @@ -0,0 +1,113 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef SND_UTILS_H +#define SND_UTILS_H + +#include "SND_WaveSlot.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef struct +{ + unsigned char riff[4]; + signed int size; + unsigned char type[4]; +} WavFileHeader; + +typedef struct +{ + unsigned short format; + unsigned short numberofchannels; + unsigned int samplerate; + unsigned int bytespersec; + unsigned short blockalignment; + unsigned short bitrate; +} WavFmtHeader; + +typedef struct +{ + unsigned short size; + unsigned short samplesperblock; +} WavFmtExHeader; + +typedef struct +{ + unsigned int Manufacturer; + unsigned int Product; + unsigned int SamplePeriod; + unsigned int Note; + unsigned int FineTune; + unsigned int SMPTEFormat; + unsigned int SMPTEOffest; + unsigned int loops; + unsigned int SamplerData; + struct + { + unsigned int Identifier; + unsigned int Type; + unsigned int Start; + unsigned int End; + unsigned int Fraction; + unsigned int Count; + } Loop[1]; +} WavSampleHeader; + +typedef struct +{ + unsigned char id[4]; + unsigned int size; +} WavChunkHeader; + +/** + * loads a sample and returns a pointer + */ +extern void* SND_LoadSample(char *filename); + +extern bool SND_IsSampleValid(const STR_String& name, void* memlocation); +extern unsigned int SND_GetSampleFormat(void* sample); +extern unsigned int SND_GetNumberOfChannels(void* sample); +extern unsigned int SND_GetSampleRate(void* sample); +extern unsigned int SND_GetBitRate(void* sample); +extern unsigned int SND_GetNumberOfSamples(void* sample); +extern unsigned int SND_GetHeaderSize(void* sample); +extern unsigned int SND_GetExtraChunk(void* sample); + +extern void SND_GetSampleInfo(signed char* sample, SND_WaveSlot* waveslot); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/intern/SoundSystem/SND_WaveCache.h b/intern/SoundSystem/SND_WaveCache.h new file mode 100644 index 00000000000..5618b8b9ecf --- /dev/null +++ b/intern/SoundSystem/SND_WaveCache.h @@ -0,0 +1,68 @@ +/* + * SND_WaveCache.h + * + * abstract wavecache, a way to organize samples + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifdef WIN32 +#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning +#endif //WIN32 + +#ifndef __SND_WAVECACHE_H +#define __SND_WAVECACHE_H + +#include "SND_WaveSlot.h" +#include "SoundDefines.h" +#include "SND_SoundObject.h" +#include <map> + +class SND_WaveCache +{ +public: + SND_WaveCache(); + virtual ~SND_WaveCache(); + + SND_WaveSlot* GetWaveSlot(const STR_String& samplename); + + void RemoveAllSamples(); + void RemoveSample(const STR_String& samplename, int buffer); + +private: + std::map<STR_String, SND_WaveSlot*> m_samplecache; + + SND_WaveSlot* m_bufferList[NUM_BUFFERS]; + + void FreeSamples(); +}; + +#endif //__SND_WAVECACHE_H diff --git a/intern/SoundSystem/SND_WaveSlot.h b/intern/SoundSystem/SND_WaveSlot.h new file mode 100644 index 00000000000..3d1e0d98ae9 --- /dev/null +++ b/intern/SoundSystem/SND_WaveSlot.h @@ -0,0 +1,94 @@ +/* + * SND_WaveSlot.cpp + * + * class for storing sample related information + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef __SND_WAVESLOT_H +#define __SND_WAVESLOT_H + +#include "STR_String.h" + +class SND_WaveSlot +{ + STR_String m_samplename; + bool m_loaded; + void* m_data; + unsigned int m_buffer; + unsigned int m_sampleformat; + unsigned int m_numberofchannels; + unsigned int m_samplerate; + unsigned int m_bitrate; + unsigned int m_numberofsamples; + unsigned int m_filesize; + +public: + + SND_WaveSlot(): m_loaded(false), + m_data(NULL), + m_buffer(0), + m_sampleformat(0), + m_numberofchannels(0), + m_samplerate(0), + m_bitrate(0), + m_numberofsamples(0), + m_filesize(0) + {}; + ~SND_WaveSlot(); + + void SetSampleName(STR_String samplename); + void SetLoaded(bool loaded); + void SetData(void* data); + void SetBuffer(unsigned int buffer); + void SetSampleFormat(unsigned int sampleformat); + void SetNumberOfChannels(unsigned int numberofchannels); + void SetSampleRate(unsigned int samplerate); + void SetBitRate(unsigned int bitrate); + void SetNumberOfSamples(unsigned int numberofsamples); + void SetFileSize(unsigned int filesize); + + + const STR_String& GetSampleName(); + bool IsLoaded() const; + void* GetData(); + unsigned int GetBuffer() const; + unsigned int GetSampleFormat() const; + unsigned int GetNumberOfChannels() const; + unsigned int GetSampleRate() const; + unsigned int GetBitRate() const; + unsigned int GetNumberOfSamples() const; + unsigned int GetFileSize() const; + +}; + +#endif //__SND_WAVESLOT_H diff --git a/intern/SoundSystem/SND_test/Makefile b/intern/SoundSystem/SND_test/Makefile new file mode 100644 index 00000000000..0aae4866f1c --- /dev/null +++ b/intern/SoundSystem/SND_test/Makefile @@ -0,0 +1,53 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# +# + +LIBNAME = SoundSystem +DIR = $(OCGDIR)/gameengine/$(LIBNAME) +ALLTARGETS = $(OBJS) $(DIR)/$(DEBUG_DIR)SoundSystem + +include nan_compile.mk + +CPPFLAGS += $(NAN_LEVEL_1_WARNINGS) + +CPPFLAGS += -I$(NAN_MOTO)/include +CPPFLAGS += -I../../../kernel/gen_system +CPPFLAGS += -I.. -I../SND_BlenderWaveCache -I../SND_OpenAL + +TESTLIB = $(OCGDIR)/gameengine/OpenALSoundSystem/$(DEBUG_DIR)libOpenALSoundSystem.a +TESTLIB += $(OCGDIR)/gameengine/BlenderWaveCache/$(DEBUG_DIR)libBlenderWaveCache.a +TESTLIB += $(OCGDIR)/kernel/gen_system/$(DEBUG_DIR)libgen_system.a +TESTLIB += $(OCGDIR)/gameengine/SoundSystem/$(DEBUG_DIR)libSoundSystem.a +TESTLIB += $(NAN_OPENAL)/lib/libopenal.a + +$(DIR)/$(DEBUG_DIR)SoundSystem: $(OBJS) $(TESTLIB) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(TESTLIB) -lm -pthread -ldl -lstdc++ diff --git a/intern/SoundSystem/SND_test/SND_test.c b/intern/SoundSystem/SND_test/SND_test.c new file mode 100644 index 00000000000..eff52aef61e --- /dev/null +++ b/intern/SoundSystem/SND_test/SND_test.c @@ -0,0 +1,152 @@ +/* SND_test.c nov 2000 +* +* testfile for the SND module +* +* janco verduin +* +* $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ + +#include "SND_C-api.h" +#include "BlenderWaveCacheCApi.h" +#include "OpenALC-Api.h" +#include <stdio.h> +#include <stdlib.h> +#if defined(WIN32) +#include <io.h> +#else +#include <unistd.h> +#endif +#include <fcntl.h> + +static int buf[3]; + +float oPos[3]={3.0, 0.0,-1.0}; +float oVel[3]={0.0, 0.0, 1.0}; +float oOri[6]={0.0, 0.0, 1.0, 0.0, 1.0, 0.0}; + +void* ReadFile(char *filename) +{ + int file, filelen; + void *data = NULL; + +#if defined(WIN32) + file = open(filename, O_BINARY|O_RDONLY); +#else + file = open(filename, 0|O_RDONLY); +#endif + + if (file == -1) { + printf("can't open file.\n"); + printf("press q for quit.\n"); + + } + else { + filelen = lseek(file, 0, SEEK_END); + lseek(file, 0, SEEK_SET); + + if (filelen != 0){ + data = malloc(filelen); + if (read(file, data, filelen) != filelen) { + free(data); + data = NULL; + } + } + close(file); + + } + return (data); +} + +int main(int argc, char* argv[]) +{ + int ch; + char* samplename = NULL; + void* sampleinmemory = NULL; + SND_CacheHandle wavecache = NULL; + SND_SceneHandle scene = NULL; + SND_ObjectHandle object = NULL; + + wavecache = SND_GetWaveCache(); + scene = SND_CreateOpenALScene(wavecache); + + samplename = "2.wav"; + sampleinmemory = ReadFile(samplename); + + if (sampleinmemory) { + + object = SND_CreateObject(); + SND_AddMemoryLocation(samplename, sampleinmemory); + SND_SetSampleName(object, samplename); + SND_AddObject(scene, object); + printf("go your gang...\n"); + printf("1: play\n"); + printf("2: stop\n"); + printf("q: quit\n"); + } + do + { + ch = getchar(); + ch = toupper(ch); + switch (ch) + { + case '1': + { + SND_SetPitch(object, 1.0); + SND_SetGain(object, 1.0); + SND_StartSound(object); + break; + } + case '2': + { + SND_StopSound(object); + break; + } + default: + break; + } + + SND_Proceed(scene); + + } while (ch != 'Q'); + + if (object) { + + SND_RemoveObject(scene, object); + SND_DeleteObject(object); + } + + SND_DeleteScene(scene); + SND_DeleteCache(); + + return 0; + +} diff --git a/intern/SoundSystem/SoundDefines.h b/intern/SoundSystem/SoundDefines.h new file mode 100644 index 00000000000..b2c00b0ade0 --- /dev/null +++ b/intern/SoundSystem/SoundDefines.h @@ -0,0 +1,119 @@ +/* + * SoundDefines.h + * + * this is where all kinds of defines are stored + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef __SOUNDDEFINES_H +#define __SOUNDDEFINES_H + +/* the types of devices */ +enum +{ + snd_e_dummydevice = 0, + snd_e_fmoddevice, + snd_e_openaldevice +}; + +/* general stuff */ +#define NUM_BUFFERS 128 +#define NUM_SOURCES 16 + +/* openal related stuff */ +#define AL_LOOPING 0x1007 + +/* fmod related stuff */ +#ifdef WIN32 +#define MIXRATE 22050 +#else +#define MIXRATE 44100 +#endif +#define NUM_FMOD_MIN_HW_CHANNELS 16 +#define NUM_FMOD_MAX_HW_CHANNELS 16 + +/* activelist defines */ +enum +{ + SND_REMOVE_ACTIVE_OBJECT = 0, + SND_ADD_ACTIVE_OBJECT, + SND_DO_NOTHING +}; + +/* playstate flags */ +enum +{ + SND_UNKNOWN = -1, + SND_INITIAL, + SND_MUST_PLAY, + SND_PLAYING, + SND_MUST_STOP, + SND_STOPPED, + SND_MUST_PAUSE, + SND_PAUSED, + SND_MUST_RESUME, + SND_MUST_STOP_WHEN_FINISHED, + SND_MUST_BE_DELETED +}; + +/* loopmodes */ +enum +{ + SND_LOOP_OFF = 0, + SND_LOOP_NORMAL, + SND_LOOP_BIDIRECTIONAL +}; + + +/* cd playstate flags */ +enum +{ + SND_CD_ALL = 0, + SND_CD_TRACK, + SND_CD_TRACKLOOP +}; + +/* sample types */ +enum +{ + SND_WAVE_FORMAT_UNKNOWN = 0, + SND_WAVE_FORMAT_PCM, + SND_WAVE_FORMAT_ADPCM, + SND_WAVE_FORMAT_ALAW = 6, + SND_WAVE_FORMAT_MULAW, + SND_WAVE_FORMAT_DIALOGIC_OKI_ADPCM = 17, + SND_WAVE_FORMAT_CONTROL_RES_VQLPC = 34, + SND_WAVE_FORMAT_GSM_610 = 49, + SND_WAVE_FORMAT_MPEG3 = 85 +}; + +#endif //__SOUNDDEFINES_H diff --git a/intern/SoundSystem/dummy/Makefile b/intern/SoundSystem/dummy/Makefile new file mode 100644 index 00000000000..fd2c85e7464 --- /dev/null +++ b/intern/SoundSystem/dummy/Makefile @@ -0,0 +1,46 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# +# + +LIBNAME = DummySoundSystem +DIR = $(OCGDIR)/gameengine/$(LIBNAME) + +include nan_compile.mk + +CCFLAGS += $(LEVEL_1_CPP_WARNINGS) + +CPPFLAGS += -I$(NAN_STRING)/include +CPPFLAGS += -I$(NAN_MOTO)/include +CPPFLAGS += -I../../../../kernel/gen_system +CPPFLAGS += -I../intern +CPPFLAGS += -I.. +CPPFLAGS += -I. diff --git a/intern/SoundSystem/dummy/SND_DummyDevice.cpp b/intern/SoundSystem/dummy/SND_DummyDevice.cpp new file mode 100644 index 00000000000..4d1f69c6f33 --- /dev/null +++ b/intern/SoundSystem/dummy/SND_DummyDevice.cpp @@ -0,0 +1,53 @@ +/* + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * SND_FmodDevice derived from SND_IAudioDevice + */ + +#ifdef WIN32 +#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning +#endif //WIN32 + +#include "SND_DummyDevice.h" + +SND_DummyDevice::SND_DummyDevice() +{ +} + + + +SND_DummyDevice::~SND_DummyDevice() +{ +#ifdef ONTKEVER + printf("SND_DummyDevice destructor"); +#endif +} + + diff --git a/intern/SoundSystem/dummy/SND_DummyDevice.h b/intern/SoundSystem/dummy/SND_DummyDevice.h new file mode 100644 index 00000000000..717a34550bc --- /dev/null +++ b/intern/SoundSystem/dummy/SND_DummyDevice.h @@ -0,0 +1,95 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef SND_DUMMYDEVICE +#define SND_DUMMYDEVICE + +#include "SND_AudioDevice.h" + +class SND_DummyDevice : public SND_AudioDevice +{ +public: + SND_DummyDevice(); + ~SND_DummyDevice(); + + bool Init() { return false; } + + SND_WaveSlot* LoadSample(const STR_String& samplename, + void* memlocation, + int size) { return NULL; } + + void InitListener() {}; + void SetListenerGain(float gain) const {}; + void SetDopplerVelocity(MT_Scalar dopplervelocity) const {}; + void SetDopplerFactor(MT_Scalar dopplerfactor) const {}; + void SetListenerRollOffFactor(MT_Scalar rollofffactor) const {}; + + void MakeCurrent() const {}; + + void NextFrame() const {}; + + void SetObjectBuffer(int id, unsigned int buffer) {}; + + int GetPlayState(int id) { return SND_UNKNOWN; } + void PlayObject(int id) {}; + void StopObject(int id) const {}; + void StopAllObjects() {}; + void PauseObject(int id) const {}; + + void SetObjectLoop(int id, unsigned int loopmode) const {}; + void SetObjectLoopPoints(int id, unsigned int loopstart, unsigned int loopend) const {}; + void SetObjectPitch(int id, MT_Scalar pitch) const {}; + void SetObjectGain(int id, MT_Scalar gain) const {}; + void SetObjectMinGain(int id, MT_Scalar mingain) const {}; + void SetObjectMaxGain(int id, MT_Scalar maxgain) const {}; + void SetObjectRollOffFactor(int id, MT_Scalar rolloff) const {}; + void SetObjectReferenceDistance(int id, MT_Scalar distance) const {}; + + void SetObjectTransform(int id, + const MT_Vector3& position, + const MT_Vector3& velocity, + const MT_Matrix3x3& orientation, + const MT_Vector3& lisposition, + const MT_Scalar& rollofffactor) const {}; + void ObjectIs2D(int id) const {}; + + void PlayCD(int track) const {}; + void PauseCD(bool pause) const {}; + void StopCD() const {}; + void SetCDPlaymode(int playmode) const {}; + void SetCDGain(MT_Scalar gain) const {}; + + void StartUsingDSP() {}; + float* GetSpectrum() { return NULL; } + void StopUsingDSP() {}; +}; + +#endif //SND_DUMMYDEVICE diff --git a/intern/SoundSystem/fmod/Makefile b/intern/SoundSystem/fmod/Makefile new file mode 100644 index 00000000000..bb545c36e2d --- /dev/null +++ b/intern/SoundSystem/fmod/Makefile @@ -0,0 +1,47 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# +# + +LIBNAME = FmodSoundSystem +DIR = $(OCGDIR)/gameengine/$(LIBNAME) + +include nan_compile.mk + +CCFLAGS += $(LEVEL_1_CPP_WARNINGS) + +CPPFLAGS += -I$(NAN_FMOD)/include +CPPFLAGS += -I$(NAN_STRING)/include +CPPFLAGS += -I$(NAN_MOTO)/include +CPPFLAGS += -I../../../kernel/gen_system +CPPFLAGS += -I../intern +CPPFLAGS += -I.. +CPPFLAGS += -I. diff --git a/intern/SoundSystem/fmod/SND_FmodDevice.cpp b/intern/SoundSystem/fmod/SND_FmodDevice.cpp new file mode 100644 index 00000000000..862703d0d59 --- /dev/null +++ b/intern/SoundSystem/fmod/SND_FmodDevice.cpp @@ -0,0 +1,543 @@ +/* + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * SND_FmodDevice derived from SND_IAudioDevice + */ + +#ifdef WIN32 +#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning +#endif //WIN32 + +#include "SND_FmodDevice.h" +#include "SoundDefines.h" +#include "SYS_System.h" +#include "SND_Utils.h" + +SND_FmodDevice::SND_FmodDevice() +{ + // check if audio is wanted + SYS_SystemHandle syshandle = SYS_GetSystem(); + int audio = SYS_GetCommandLineInt(syshandle,"noaudio",0); + + m_dspunit = NULL; + + if (audio == 1) + m_audio = false; + else + m_audio = true; + + // let's check if we can get fmod to initialize... + if (m_audio) + { + signed char MinHardwareChannels = FSOUND_SetMinHardwareChannels(NUM_FMOD_MIN_HW_CHANNELS); + signed char MaxHardwareChannels = FSOUND_SetMaxHardwareChannels(NUM_FMOD_MAX_HW_CHANNELS); + + if (FSOUND_Init(MIXRATE, NUM_SOURCES, 0)) + { + m_max_channels = FSOUND_GetMaxChannels(); + m_num_hardware_channels = FSOUND_GetNumHardwareChannels(); + m_num_software_channels = NUM_SOURCES; + + // let's get us a wavecache + m_wavecache = new SND_WaveCache(); + + int i; + for (i = 0; i < NUM_BUFFERS; i++) + m_buffers[i] = NULL; + + for (i = 0; i < NUM_SOURCES; i++) + { + m_sources[i] = NULL; + m_frequencies[i] = 0; + m_channels[i] = 0; + } + } + else + { + m_audio = false; + } + } + +#ifdef ONTKEVER + int numdrivers = FSOUND_GetNumDrivers(); + int output = FSOUND_GetOutput(); + int oputputrate = FSOUND_GetOutputRate(); + int mixer = FSOUND_GetMixer(); + + printf("maxchannels is: %d\n", m_max_channels); + printf("num hw channels is: %d\n", m_num_hardware_channels); + printf("num sw channels is: %d\n", m_num_software_channels); + printf("numdrivers is: %d\n", numdrivers); + printf("output is: %d\n", output); + printf("oputputrate is: %d\n", oputputrate); + printf("mixer is: %d\n", mixer); +#endif +} + + + +SND_FmodDevice::~SND_FmodDevice() +{ + // let's see if we used the cd. if not, just leave it alone + SND_CDObject* pCD = SND_CDObject::Instance(); + + if (pCD) + { + this->StopCD(); + SND_CDObject::DisposeSystem(); + } + + StopUsingDSP(); + + FSOUND_Close(); +} + + + +void SND_FmodDevice::UseCD() const +{ + // only fmod has CD support, so only create it here + SND_CDObject::CreateSystem(); +} + + + +void SND_FmodDevice::MakeCurrent() const +{ + // empty +} + + + +SND_WaveSlot* SND_FmodDevice::LoadSample(const STR_String& name, + void* memlocation, + int size) +{ + SND_WaveSlot* waveslot = NULL; + STR_String samplename = name; + + if (m_audio) + { + /* first check if the sample is supported */ + if (SND_IsSampleValid(name, memlocation)) + { + /* create the waveslot */ + waveslot = m_wavecache->GetWaveSlot(samplename); + + if (waveslot) + { + int buffer = waveslot->GetBuffer(); + + /* load the sample from memory? */ + if (size && memlocation) + { + m_buffers[buffer] = FSOUND_Sample_Load(buffer, (char*)memlocation, FSOUND_LOADMEMORY, size); + + /* if the loading succeeded, fill the waveslot with info */ + if (m_buffers[buffer]) + { + int sampleformat = SND_GetSampleFormat(memlocation); + int numberofchannels = SND_GetNumberOfChannels(memlocation); + int samplerate = SND_GetSampleRate(memlocation); + int bitrate = SND_GetBitRate(memlocation); + int numberofsamples = SND_GetNumberOfSamples(memlocation); + + waveslot->SetFileSize(size); + waveslot->SetData(memlocation); + waveslot->SetSampleFormat(sampleformat); + waveslot->SetNumberOfChannels(numberofchannels); + waveslot->SetSampleRate(samplerate); + waveslot->SetBitRate(bitrate); + waveslot->SetNumberOfSamples(numberofsamples); + } + } + /* or from file? */ + else + { + m_buffers[buffer] = FSOUND_Sample_Load(buffer, samplename.Ptr(), FSOUND_LOOP_NORMAL, NULL); + } + +#ifdef ONTKEVER + int error = FSOUND_GetError(); + printf("sample load: errornumber is: %d\n", error); +#endif + + /* if the loading succeeded, mark the waveslot */ + if (m_buffers[buffer]) + { + waveslot->SetLoaded(true); + } + /* or when it failed, free the waveslot */ + else + { + m_wavecache->RemoveSample(waveslot->GetSampleName(), waveslot->GetBuffer()); + waveslot = NULL; + } + } + } + } + + return waveslot; +} + + + + +// listener's and general stuff ////////////////////////////////////////////////////// + + + +/* sets the global dopplervelocity */ +void SND_FmodDevice::SetDopplerVelocity(MT_Scalar dopplervelocity) const +{ + /* not supported by fmod */ + FSOUND_3D_Listener_SetDopplerFactor(dopplervelocity); +} + + + +/* sets the global dopplerfactor */ +void SND_FmodDevice::SetDopplerFactor(MT_Scalar dopplerfactor) const +{ + FSOUND_3D_Listener_SetDopplerFactor(dopplerfactor); +} + + + +/* sets the global rolloff factor */ +void SND_FmodDevice::SetListenerRollOffFactor(MT_Scalar rollofffactor) const +{ + // not implemented in openal +} + + + +void SND_FmodDevice::NextFrame() const +{ + FSOUND_3D_Update(); +} + + + +// set the gain for the listener +void SND_FmodDevice::SetListenerGain(float gain) const +{ + int fmod_gain = (int)(gain * 255); + FSOUND_SetSFXMasterVolume(fmod_gain); +} + + + +void SND_FmodDevice::InitListener() +{ + // initialize the listener with these values that won't change + // (as long as we can have only one listener) + // now we can superimpose all listeners on each other (for they + // have the same settings) + float lispos[3] = {0,0,0}; + float lisvel[3] = {0,0,0}; + + FSOUND_3D_Listener_SetAttributes(lispos, lisvel, 0, -1, 0, 0, 0, 1); +} + + + +// source playstate stuff //////////////////////////////////////////////////////////// + + + +// check if the sound's still playing +int SND_FmodDevice::GetPlayState(int id) +{ + int result = SND_STOPPED; + + // klopt niet, fixen + signed char isplaying = FSOUND_IsPlaying(id); + + if (isplaying) + { + result = SND_PLAYING; + } + +/* hi reevan, just swap // of these 2 lines */ +// return result; + return 0; +} + + + +/* sets the buffer */ +void SND_FmodDevice::SetObjectBuffer(int id, unsigned int buffer) +{ + m_sources[id] = m_buffers[buffer]; +} + + + +// make the source play +void SND_FmodDevice::PlayObject(int id) +{ + m_channels[id] = FSOUND_PlaySound(FSOUND_FREE, m_sources[id]); + m_frequencies[id] = FSOUND_GetFrequency(m_channels[id]); +// printf("fmod: play \n"); +} + + + +// make the source stop +void SND_FmodDevice::StopObject(int id) const +{ + FSOUND_StopSound(m_channels[id]); +// printf("fmod: stop \n"); +} + + + +// stop all sources +void SND_FmodDevice::StopAllObjects() +{ + FSOUND_StopSound(FSOUND_ALL); +} + + + +// pause the source +void SND_FmodDevice::PauseObject(int id) const +{ + FSOUND_StopSound(m_channels[id]); +} + + + +// source properties stuff //////////////////////////////////////////////////////////// + + + +// give openal the object's pitch +void SND_FmodDevice::SetObjectPitch(int id, MT_Scalar pitch) const +{ + pitch = pitch * m_frequencies[id]; + char result = FSOUND_SetFrequency(m_channels[id], (int)pitch); +} + + + +// give openal the object's gain +void SND_FmodDevice::SetObjectGain(int id, MT_Scalar gain) const +{ + int vol = (int)(gain * 255); + FSOUND_SetVolume(m_channels[id], vol); +} + + + +// give openal the object's looping +void SND_FmodDevice::SetObjectLoop(int id, unsigned int loopmode) const +{ +// printf("loopmode: %d\n", loopmode); + switch (loopmode) + { + case SND_LOOP_OFF: + { + char result = FSOUND_Sample_SetLoopMode(m_sources[id], FSOUND_LOOP_OFF); +// char result = FSOUND_SetLoopMode(m_channels[id], FSOUND_LOOP_OFF); + break; + } + case SND_LOOP_NORMAL: + { + char result = FSOUND_Sample_SetLoopMode(m_sources[id], FSOUND_LOOP_NORMAL); +// char result = FSOUND_SetLoopMode(m_channels[id], FSOUND_LOOP_NORMAL); + break; + } + case SND_LOOP_BIDIRECTIONAL: + { + char result = FSOUND_Sample_SetLoopMode(m_sources[id], FSOUND_LOOP_BIDI); +// char result = FSOUND_SetLoopMode(m_channels[id], FSOUND_LOOP_NORMAL); + break; + } + default: + break; + } +} + + + +void SND_FmodDevice::SetObjectLoopPoints(int id, unsigned int loopstart, unsigned int loopend) const +{ + FSOUND_Sample_SetLoopPoints(m_sources[id], loopstart, loopend); +} + + + +void SND_FmodDevice::SetObjectMinGain(int id, MT_Scalar mingain) const +{ + /* not supported by fmod */ +} + + + +void SND_FmodDevice::SetObjectMaxGain(int id, MT_Scalar maxgain) const +{ + /* not supported by fmod */ +} + + + +void SND_FmodDevice::SetObjectRollOffFactor(int id, MT_Scalar rollofffactor) const +{ + /* not supported by fmod */ +} + + + +void SND_FmodDevice::SetObjectReferenceDistance(int id, MT_Scalar referencedistance) const +{ + /* not supported by fmod */ +} + + + +// give openal the object's position +void SND_FmodDevice::ObjectIs2D(int id) const +{ + float obpos[3] = {0,0,0}; + float obvel[3] = {0,0,0}; + + FSOUND_3D_SetAttributes(m_channels[id], obpos, obvel); +} + + + +void SND_FmodDevice::SetObjectTransform(int id, + const MT_Vector3& position, + const MT_Vector3& velocity, + const MT_Matrix3x3& orientation, + const MT_Vector3& lisposition, + const MT_Scalar& rollofffactor) const +{ + float obpos[3]; + float obvel[3]; + + obpos[0] = (float)position[0] * (float)rollofffactor; //x (l/r) + obpos[1] = (float)position[1] * (float)rollofffactor; + obpos[2] = (float)position[2] * (float)rollofffactor; + + velocity.getValue(obvel); + FSOUND_3D_SetAttributes(m_channels[id], obpos, obvel); +} + + + +// cd support stuff //////////////////////////////////////////////////////////// + + +void SND_FmodDevice::PlayCD(int track) const +{ + signed char result = FSOUND_CD_Play(track); + +#ifdef ONTKEVER + printf("play track %d, result: %c\n", track, result); +#endif +} + + + +void SND_FmodDevice::PauseCD(bool pause) const +{ + signed char result = FSOUND_CD_SetPaused(pause); + +#ifdef ONTKEVER + printf("pause cd: %d, result: %c\n", pause, result); +#endif +} + + + +void SND_FmodDevice::StopCD() const +{ + SND_CDObject* pCD = SND_CDObject::Instance(); + + if (pCD) + { + if (pCD->GetUsed()) + { + signed char result = FSOUND_CD_Stop(); + +#ifdef ONTKEVER + printf("stop cd, result: %c\n", result); +#endif + } + } +} + + + +void SND_FmodDevice::SetCDPlaymode(int playmode) const +{ + FSOUND_CD_SetPlayMode(playmode); +} + + + +void SND_FmodDevice::SetCDGain(MT_Scalar gain) const +{ + int volume = gain * 255; + signed char result = FSOUND_CD_SetVolume(volume); + +#ifdef ONTKEVER + printf("gain: %f, volume: %d, result: %c\n", gain, volume, result); +#endif +} + + + +void SND_FmodDevice::StartUsingDSP() +{ + m_dspunit = FSOUND_DSP_GetFFTUnit(); + + FSOUND_DSP_SetActive(m_dspunit, true); +} + + + +float* SND_FmodDevice::GetSpectrum() +{ + m_spectrum = FSOUND_DSP_GetSpectrum(); + + return m_spectrum; +} + + + +void SND_FmodDevice::StopUsingDSP() +{ + if (m_dspunit) + FSOUND_DSP_SetActive(m_dspunit, false); +}
\ No newline at end of file diff --git a/intern/SoundSystem/fmod/SND_FmodDevice.h b/intern/SoundSystem/fmod/SND_FmodDevice.h new file mode 100644 index 00000000000..2a8dbcf0b30 --- /dev/null +++ b/intern/SoundSystem/fmod/SND_FmodDevice.h @@ -0,0 +1,105 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef SND_FMODDEVICE +#define SND_FMODDEVICE + +#include "fmod.h" +#include "SND_AudioDevice.h" +#include "SoundDefines.h" + +class SND_FmodDevice : public SND_AudioDevice +{ +public: + SND_FmodDevice(); + ~SND_FmodDevice(); + + SND_WaveSlot* LoadSample(const STR_String& samplename, + void* memlocation, + int size); + + void InitListener(); + void SetListenerGain(float gain) const; + void SetDopplerVelocity(MT_Scalar dopplervelocity) const; + void SetDopplerFactor(MT_Scalar dopplerfactor) const; + void SetListenerRollOffFactor(MT_Scalar rollofffactor) const; + + void MakeCurrent() const; + void NextFrame() const; + void UseCD() const; + + void SetObjectBuffer(int id, unsigned int buffer); + int GetPlayState(int id); + void PlayObject(int id); + void StopObject(int id) const; + void StopAllObjects(); + void PauseObject(int id) const; + + void SetObjectLoop(int id, unsigned int loopmode) const; + void SetObjectLoopPoints(int id, unsigned int loopstart, unsigned int loopend) const; + void SetObjectPitch(int id, MT_Scalar pitch) const; + void SetObjectGain(int id, MT_Scalar gain) const; + void SetObjectMinGain(int id, MT_Scalar mingain) const; + void SetObjectMaxGain(int id, MT_Scalar maxgain) const; + void SetObjectRollOffFactor(int id, MT_Scalar rolloff) const; + void SetObjectReferenceDistance(int id, MT_Scalar distance) const; + + void SetObjectTransform(int id, + const MT_Vector3& position, + const MT_Vector3& velocity, + const MT_Matrix3x3& orientation, + const MT_Vector3& lisposition, + const MT_Scalar& rollofffactor) const; + void ObjectIs2D(int id) const; + + void PlayCD(int track) const; + void PauseCD(bool pause) const; + void StopCD() const; + void SetCDPlaymode(int playmode) const; + void SetCDGain(MT_Scalar gain) const; + + void StartUsingDSP(); + float* GetSpectrum(); + void StopUsingDSP(); + +private: + FSOUND_SAMPLE* m_buffers[NUM_BUFFERS]; + FSOUND_SAMPLE* m_sources[NUM_SOURCES]; + FSOUND_DSPUNIT* m_dspunit; + int m_frequencies[NUM_SOURCES]; + int m_max_channels; + int m_num_hardware_channels; + int m_num_software_channels; + int m_channels[NUM_SOURCES]; + float* m_spectrum; +}; + +#endif //SND_FMODDEVICE diff --git a/intern/SoundSystem/intern/Makefile b/intern/SoundSystem/intern/Makefile new file mode 100644 index 00000000000..ae5805ad5bc --- /dev/null +++ b/intern/SoundSystem/intern/Makefile @@ -0,0 +1,50 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# +# + +LIBNAME = SoundSystem +DIR = $(OCGDIR)/gameengine/$(LIBNAME) + +include nan_compile.mk + +CCFLAGS += $(LEVEL_1_CPP_WARNINGS) + +CPPFLAGS += -I$(NAN_FMOD)/include +CPPFLAGS += -I$(NAN_STRING)/include +CPPFLAGS += -I$(NAN_MOTO)/include +CPPFLAGS += -I../../../kernel/gen_system +CPPFLAGS += -I../../../blender/include +CPPFLAGS += -I../dummy +CPPFLAGS += -I../fmod +CPPFLAGS += -I../openal +CPPFLAGS += -I.. +CPPFLAGS += -I. diff --git a/intern/SoundSystem/intern/SND_AudioDevice.cpp b/intern/SoundSystem/intern/SND_AudioDevice.cpp new file mode 100644 index 00000000000..20800153128 --- /dev/null +++ b/intern/SoundSystem/intern/SND_AudioDevice.cpp @@ -0,0 +1,247 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "SND_AudioDevice.h" + +#include "SND_SoundObject.h" + +#ifdef WIN32 +// This warning tells us about truncation of __long__ stl-generated names. +// It can occasionally cause DevStudio to have internal compiler warnings. +#pragma warning( disable : 4786 ) +#endif + + +SND_AudioDevice::SND_AudioDevice() +{ + m_wavecache = NULL; + m_audio = false; + + for (int i = 0; i < NUM_SOURCES; i++) + { + m_idObjectArray[i] = new SND_IdObject(); + m_idObjectArray[i]->SetId(i); + m_idObjectArray[i]->SetSoundObject(NULL); + m_idObjectList.addTail(m_idObjectArray[i]); + } +} + + + +SND_AudioDevice::~SND_AudioDevice() +{ + for (int i = 0; i < NUM_SOURCES; i++) + { + delete m_idObjectArray[i]; + m_idObjectArray[i] = NULL; + } + + if (m_wavecache) + { + delete m_wavecache; + m_wavecache = NULL; + } +} + + + +bool SND_AudioDevice::IsInitialized() +{ + return m_audio; +} + + + +SND_WaveCache* SND_AudioDevice::GetWaveCache() const +{ + return m_wavecache; +} + + + +/* seeks an unused id and returns it */ +bool SND_AudioDevice::GetNewId(SND_SoundObject* pObject) +{ +#ifdef ONTKEVER + printf("SND_AudioDevice::GetNewId\n"); +#endif + + bool result; + + // first, get the oldest (the first) idobject + SND_IdObject* pIdObject = (SND_IdObject*)m_idObjectList.getHead(); + + if (pIdObject->isTail()) + { + result = false; + } + else + { + // find the first id object which doesn't have a high priority soundobject + bool ThisSoundMustStay = false; + bool OutOfIds = false; + + do + { + // if no soundobject present, it's seat may be taken + if (pIdObject->GetSoundObject()) + { + // and also if it ain't highprio + if (pIdObject->GetSoundObject()->IsHighPriority()) + { + ThisSoundMustStay = true; + pIdObject = (SND_IdObject*)pIdObject->getNext(); + + // if the last one is a priority sound too, then there are no id's left + // and we won't add any new sounds + if (pIdObject->isTail()) + OutOfIds = true; + } + else + { + ThisSoundMustStay = false; + } + } + else + { + ThisSoundMustStay = false; + } + + } while (ThisSoundMustStay && !OutOfIds); + + if (!OutOfIds) + { + SND_SoundObject* oldobject = oldobject = pIdObject->GetSoundObject(); + + // revoke the old object if present + if (oldobject) + { +#ifdef ONTKEVER + printf("oldobject: %x\n", oldobject); +#endif + RevokeSoundObject(oldobject); + } + + // set the new soundobject into the idobject + pIdObject->SetSoundObject(pObject); + + // set the id into the soundobject + int id = pIdObject->GetId(); + pObject->SetId(id); + + // connect the new id to the buffer the sample is stored in + SetObjectBuffer(id, pObject->GetBuffer()); + + // remove the idobject from the list and add it in the back again + pIdObject->remove(); + m_idObjectList.addTail(pIdObject); + + result = true; + } + } + + return result; +} + + + +void SND_AudioDevice::ClearId(SND_SoundObject* pObject) +{ +#ifdef ONTKEVER + printf("SND_AudioDevice::ClearId\n"); +#endif + + if (pObject) + { + int id = pObject->GetId(); + + if (id != -1) + { + // lets get the idobject belonging to the soundobject + SND_IdObject* pIdObject = m_idObjectArray[id]; + SND_SoundObject* oldobject = pIdObject->GetSoundObject(); + + if (oldobject) + { + RevokeSoundObject(oldobject); + + // clear the idobject from the soundobject + pIdObject->SetSoundObject(NULL); + } + + // remove the idobject and place it in front + pIdObject->remove(); + m_idObjectList.addHead(pIdObject); + } + } +} + + + +void SND_AudioDevice::RevokeSoundObject(SND_SoundObject* pObject) +{ +#ifdef ONTKEVER + printf("SND_AudioDevice::RevokeSoundObject\n"); +#endif + + // stop the soundobject + int id = pObject->GetId(); + + if (id >= 0 && id < NUM_SOURCES) + { + StopObject(id); + + // remove the object from the 'activelist' + pObject->SetActive(false); + +#ifdef ONTKEVER + printf("pObject->remove();\n"); +#endif + } + + // make sure its id is invalid + pObject->SetId(-1); +} + +/* +void SND_AudioDevice::RemoveSample(const char* filename) +{ + if (m_wavecache) + m_wavecache->RemoveSample(filename); +} +*/ + +void SND_AudioDevice::RemoveAllSamples() +{ + if (m_wavecache) + m_wavecache->RemoveAllSamples(); +} + diff --git a/intern/SoundSystem/intern/SND_AudioDevice.h b/intern/SoundSystem/intern/SND_AudioDevice.h new file mode 100644 index 00000000000..54a8738e43f --- /dev/null +++ b/intern/SoundSystem/intern/SND_AudioDevice.h @@ -0,0 +1,118 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef SND_AUDIODEVICE +#define SND_AUDIODEVICE + +#include "SND_IAudioDevice.h" +#include "SoundDefines.h" +#include "SND_IdObject.h" + + +class SND_AudioDevice : public SND_IAudioDevice +{ +public: + SND_AudioDevice(); + virtual ~SND_AudioDevice(); + + virtual bool IsInitialized(); + + SND_WaveCache* GetWaveCache() const; + + bool GetNewId(SND_SoundObject* pObject); + void ClearId(SND_SoundObject* pObject); + + void UseCD() const {}; + + /* to be implemented in derived class + + virtual SND_WaveSlot* LoadSample(const STR_String& samplename, + void* memlocation, + int size) =0; + */ +// void RemoveSample(const char* filename); + void RemoveAllSamples(); + + /* to be implemented in derived class + + virtual void InitListener()=0; + virtual void SetListenerGain(float gain) const =0; + virtual void SetDopplerVelocity(MT_Scalar dopplervelocity) const =0; + virtual void SetDopplerFactor(MT_Scalar dopplerfactor) const =0; + virtual void SetListenerRollOffFactor(MT_Scalar rollofffactor) const =0; + + virtual void MakeCurrent() const =0; + + virtual void UpdateDevice() const =0; + + virtual void SetObjectBuffer(int id, unsigned int buffer)=0; + virtual int GetPlayState(int id)=0; + virtual void PlayObject(int id)=0; + virtual void StopObject(int id) const =0; + virtual void StopAllObjects()=0; + virtual void PauseObject(int id) const =0; + + virtual void SetObjectLoop(int id, bool loop) const =0; + virtual void SetObjectLoopPoints(int id, unsigned int loopstart, unsigned int loopend) const =0; + virtual void SetObjectPitch(int id, MT_Scalar pitch) const =0; + virtual void SetObjectGain(int id, MT_Scalar gain) const =0; + virtual void SetObjectRollOffFactor(int id, MT_Scalar rolloff) const =0; + virtual void SetObjectMinGain(int id, MT_Scalar mingain) const =0; + virtual void SetObjectMaxGain(int id, MT_Scalar maxgain) const =0; + virtual void SetObjectReferenceDistance(int id, MT_Scalar referencedistance) const =0; + + virtual void SetObjectTransform(int id, + const MT_Vector3& position, + const MT_Vector3& velocity, + const MT_Matrix3x3& orientation, + const MT_Vector3& lisposition, + const MT_Scalar& rollofffactor) const =0; + virtual void ObjectIs2D(int id) const =0; + + virtual void PlayCD(int track) const =0; + virtual void PauseCD(bool pause) const =0; + virtual void StopCD() const =0; + virtual void SetCDPlaymode(int playmode) const =0; + virtual void SetCDGain(MT_Scalar gain) const =0; + virtual float* GetSpectrum() =0; + */ + +protected: + bool m_audio; + GEN_List m_idObjectList; + SND_IdObject* m_idObjectArray[NUM_SOURCES]; + SND_WaveCache* m_wavecache; + +private: + void RevokeSoundObject(SND_SoundObject* pObject); +}; + +#endif //SND_AUDIODEVICE diff --git a/intern/SoundSystem/intern/SND_C-api.cpp b/intern/SoundSystem/intern/SND_C-api.cpp new file mode 100644 index 00000000000..8a4fc8f31a6 --- /dev/null +++ b/intern/SoundSystem/intern/SND_C-api.cpp @@ -0,0 +1,391 @@ +/* + * SND_C-Api.cpp + * + * C Api for soundmodule + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "SND_C-api.h" +#include "SND_DeviceManager.h" +#include "SND_Scene.h" + +#ifdef WIN32 +#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning +#endif //WIN32 + + + +void SND_SetDeviceType(int device_type) +{ + SND_DeviceManager::SetDeviceType(device_type); +} + + + +SND_AudioDeviceInterfaceHandle SND_GetAudioDevice() +{ + SND_IAudioDevice* audiodevice = NULL; + + SND_DeviceManager::Subscribe(); + audiodevice = SND_DeviceManager::Instance(); + + if (!audiodevice->IsInitialized()) + { + SND_DeviceManager::SetDeviceType(snd_e_dummydevice); + audiodevice = SND_DeviceManager::Instance(); + } + + return (SND_AudioDeviceInterfaceHandle)audiodevice; +} + + + +void SND_ReleaseDevice() +{ + SND_DeviceManager::Unsubscribe(); +} + + + +int SND_IsPlaybackWanted(SND_SceneHandle scene) +{ + assert(scene); + bool result = ((SND_Scene*)scene)->IsPlaybackWanted(); + + return (int)result; +} + + + +// create a scene +SND_SceneHandle SND_CreateScene(SND_AudioDeviceInterfaceHandle audiodevice) +{ + // initialize sound scene and object + SND_Scene* scene = new SND_Scene((SND_IAudioDevice*)audiodevice); + + return (SND_SceneHandle)scene; +} + + + +void SND_DeleteScene(SND_SceneHandle scene) +{ + assert(scene); + delete (SND_Scene*)scene; +} + + + +int SND_AddSample(SND_SceneHandle scene, + const char* filename, + void* memlocation, + int size) +{ + assert(scene); + assert(memlocation); + int buffer = ((SND_Scene*)scene)->LoadSample(filename, memlocation, size); + + return buffer; +} + + + +void SND_RemoveAllSamples(SND_SceneHandle scene) +{ + assert(scene); + ((SND_Scene*)scene)->RemoveAllSamples(); +} + + + +int SND_CheckBuffer(SND_SceneHandle scene, SND_ObjectHandle object) +{ + assert(scene); + assert(object); + int result = (int)((SND_Scene*)scene)->CheckBuffer((SND_SoundObject*)object); + + return result; +} + + + +void SND_AddSound(SND_SceneHandle scene, SND_ObjectHandle object) +{ + assert(scene); + assert(object); + ((SND_Scene*)scene)->AddObject((SND_SoundObject *)object); +} + + + +void SND_RemoveSound(SND_SceneHandle scene, SND_ObjectHandle object) +{ + assert(scene); + assert(object); + ((SND_Scene*)scene)->DeleteObject((SND_SoundObject *)object); +} + + + +void SND_RemoveAllSounds(SND_SceneHandle scene) +{ + assert(scene); + ((SND_Scene*)scene)->RemoveAllObjects(); +} + + + +void SND_StopAllSounds(SND_SceneHandle scene) +{ + assert(scene); + ((SND_Scene*)scene)->StopAllObjects(); +} + + + +void SND_Proceed(SND_AudioDeviceInterfaceHandle audiodevice, SND_SceneHandle scene) +{ + assert(scene); + ((SND_Scene*)scene)->Proceed(); + ((SND_IAudioDevice*)audiodevice)->NextFrame(); +} + + + +SND_ListenerHandle SND_GetListener(SND_SceneHandle scene) +{ + assert(scene); + return (SND_ListenerHandle)((SND_Scene*)scene)->GetListener(); +} + + + +void SND_SetListenerGain(SND_SceneHandle scene, double gain) +{ + assert(scene); + SND_SoundListener* listener = ((SND_Scene*)scene)->GetListener(); + listener->SetGain((MT_Scalar)gain); +} + + + +void SND_SetDopplerFactor(SND_SceneHandle scene, double dopplerfactor) +{ + assert(scene); + SND_SoundListener* listener = ((SND_Scene*)scene)->GetListener(); + listener->SetDopplerFactor(dopplerfactor); +} + + + +void SND_SetDopplerVelocity(SND_SceneHandle scene, double dopplervelocity) +{ + assert(scene); + SND_SoundListener* listener = ((SND_Scene*)scene)->GetListener(); + listener->SetDopplerVelocity(dopplervelocity); +} + + + +// Object instantiation +SND_ObjectHandle SND_CreateSound() +{ + return (SND_ObjectHandle)new SND_SoundObject(); +} + + + +void SND_DeleteSound(SND_ObjectHandle object) +{ + assert(object); + delete (SND_SoundObject*)object; +} + + + +// Object control +void SND_StartSound(SND_SceneHandle scene, SND_ObjectHandle object) +{ + assert(scene); + assert(object); + ((SND_Scene*)scene)->AddActiveObject((SND_SoundObject*)object, 0); +} + + + +void SND_StopSound(SND_SceneHandle scene, SND_ObjectHandle object) +{ + assert(scene); + assert(object); + ((SND_Scene*)scene)->RemoveActiveObject((SND_SoundObject*)object); +} + + + +void SND_PauseSound(SND_SceneHandle scene, SND_ObjectHandle object) +{ + assert(scene); + assert(object); + ((SND_Scene*)scene)->RemoveActiveObject((SND_SoundObject*)object); +} + + + +void SND_SetSampleName(SND_ObjectHandle object, char* samplename) +{ + assert(object); + STR_String name = samplename; + ((SND_SoundObject*)object)->SetSampleName(name); +} + + + +void SND_SetGain(SND_ObjectHandle object, double gain) +{ + assert(object); + ((SND_SoundObject*)object)->SetGain(gain); +} + + + +void SND_SetMinimumGain(SND_ObjectHandle object, double minimumgain) +{ + assert(object); + ((SND_SoundObject*)object)->SetMinGain(minimumgain); +} + + + +void SND_SetMaximumGain(SND_ObjectHandle object, double maximumgain) +{ + assert(object); + ((SND_SoundObject*)object)->SetMaxGain(maximumgain); +} + + + +void SND_SetRollOffFactor(SND_ObjectHandle object, double rollofffactor) +{ + assert(object); + ((SND_SoundObject*)object)->SetRollOffFactor(rollofffactor); +} + + + +void SND_SetReferenceDistance(SND_ObjectHandle object, double referencedistance) +{ + assert(object); + ((SND_SoundObject*)object)->SetReferenceDistance(referencedistance); +} + + + +void SND_SetPitch(SND_ObjectHandle object, double pitch) +{ + assert(object); + ((SND_SoundObject*)object)->SetPitch(pitch); +} + + + +void SND_SetPosition(SND_ObjectHandle object, double* position) +{ + assert(object); + ((SND_SoundObject*)object)->SetPosition(position); +} + + + +void SND_SetVelocity(SND_ObjectHandle object, double* velocity) +{ + assert(object); + ((SND_SoundObject*)object)->SetVelocity(velocity); +} + + + +void SND_SetOrientation(SND_ObjectHandle object, double* orientation) +{ + assert(object); + ((SND_SoundObject*)object)->SetOrientation(orientation); +} + + + +void SND_SetLoopMode(SND_ObjectHandle object, int loopmode) +{ + assert(object); + ((SND_SoundObject*)object)->SetLoopMode(loopmode); +} + + + +void SND_SetLoopPoints(SND_ObjectHandle object, unsigned int loopstart, unsigned int loopend) +{ + assert(object); + ((SND_SoundObject*)object)->SetLoopStart(loopstart); + ((SND_SoundObject*)object)->SetLoopEnd(loopend); +} + + + +float SND_GetGain(SND_ObjectHandle object) +{ + assert(object); + MT_Scalar gain = ((SND_SoundObject*)object)->GetGain(); + return (float) gain; +} + + + +float SND_GetPitch(SND_ObjectHandle object) +{ + assert(object); + MT_Scalar pitch = ((SND_SoundObject*)object)->GetPitch(); + return (float) pitch; +} + + + +int SND_GetLoopMode(SND_ObjectHandle object) +{ + assert(object); + return ((SND_SoundObject*)object)->GetLoopMode(); +} + + + +int SND_GetPlaystate(SND_ObjectHandle object) +{ + assert(object); + return ((SND_SoundObject*)object)->GetPlaystate(); +} diff --git a/intern/SoundSystem/intern/SND_CDObject.cpp b/intern/SoundSystem/intern/SND_CDObject.cpp new file mode 100644 index 00000000000..97b502970b7 --- /dev/null +++ b/intern/SoundSystem/intern/SND_CDObject.cpp @@ -0,0 +1,182 @@ +/* + * SND_CDObject.cpp + * + * Implementation for CD playback + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "SND_CDObject.h" + + +SND_CDObject* SND_CDObject::m_instance = NULL; + +bool SND_CDObject::CreateSystem() +{ + bool result = false; + + if (!m_instance) + { + m_instance = new SND_CDObject(); + result = true; + } + + return result; +} + + + +bool SND_CDObject::DisposeSystem() +{ + bool result = false; + + if (m_instance) + { + delete m_instance; + m_instance = NULL; + result = true; + } + + return result; +} + + + +SND_CDObject* SND_CDObject::Instance() +{ + return m_instance; +} + + + +SND_CDObject::SND_CDObject() +{ + m_gain = 1; + m_playmode = SND_CD_ALL; + m_track = 1; + m_playstate = SND_STOPPED; + m_used = false; + + // don't set the cd standard on modified: + // if not used, we don't wanna touch it (performance) + m_modified = false; +} + + + +SND_CDObject::~SND_CDObject() +{ +} + + + +void SND_CDObject::SetGain(MT_Scalar gain) +{ + m_gain = gain; + m_modified = true; +} + + + +void SND_CDObject::SetPlaymode(int playmode) +{ + m_playmode = playmode; +} + + + +void SND_CDObject::SetPlaystate(int playstate) +{ + m_playstate = playstate; +} + + + +void SND_CDObject::SetTrack(int track) +{ + m_track = track; +} + + + +int SND_CDObject::GetTrack() const +{ + return m_track; +} + + + +MT_Scalar SND_CDObject::GetGain() const +{ + return m_gain; +} + + +int SND_CDObject::GetPlaystate() const +{ + return m_playstate; +} + + + +bool SND_CDObject::IsModified() const +{ + return m_modified; +} + + + +void SND_CDObject::SetModified(bool modified) +{ + m_modified = modified; +} + + + +int SND_CDObject::GetPlaymode() const +{ + return m_playmode; +} + + + +void SND_CDObject::SetUsed() +{ + m_used = true; +} + + + +bool SND_CDObject::GetUsed() +{ + return m_used; +} + diff --git a/intern/SoundSystem/intern/SND_DeviceManager.cpp b/intern/SoundSystem/intern/SND_DeviceManager.cpp new file mode 100644 index 00000000000..a3e72f8e9f6 --- /dev/null +++ b/intern/SoundSystem/intern/SND_DeviceManager.cpp @@ -0,0 +1,137 @@ +/* + * SND_DeviceManager.h + * + * singleton for creating, switching and deleting audiodevices + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "SND_DeviceManager.h" +#include "SND_DependKludge.h" +#include "SND_DummyDevice.h" +#ifdef USE_FMOD +#include "SND_FmodDevice.h" +#endif +#ifdef USE_OPENAL +#include "SND_OpenALDevice.h" +#endif + +SND_IAudioDevice* SND_DeviceManager::m_instance = NULL; +int SND_DeviceManager::m_subscriptions = 0; + +#ifdef USE_OPENAL +int SND_DeviceManager::m_device_type = snd_e_openaldevice; +#else +# ifdef USE_FMOD +int SND_DeviceManager::m_device_type = snd_e_fmoddevice; +# else +int SND_DeviceManager::m_device_type = snd_e_dummydevice; +# endif +#endif + +void SND_DeviceManager::Subscribe() +{ + ++m_subscriptions; +} + + + +void SND_DeviceManager::Unsubscribe() +{ + --m_subscriptions; + + // only release memory if there is a m_instance but no subscriptions left + if (m_subscriptions == 0 && m_instance) + { + delete m_instance; + m_instance = NULL; + } +} + + + +SND_IAudioDevice* SND_DeviceManager::Instance() +{ + // only give away an instance if there are subscriptions + if (m_subscriptions) + { + // if there's no instance yet, set and create a new one + if (m_instance == NULL) + { + SetDeviceType(m_device_type); + } + + return m_instance; + } + else + { + return NULL; + } +} + + + +void SND_DeviceManager::SetDeviceType(int device_type) +{ + // if we want to change devicetype, first delete the old one + if (m_instance) + { + delete m_instance; + m_instance = NULL; + } + + // let's create the chosen device + switch (device_type) + { +#ifdef USE_FMOD + case snd_e_fmoddevice: + { + m_instance = new SND_FmodDevice(); + m_device_type = device_type; + break; + } +#endif +#ifdef USE_OPENAL + case snd_e_openaldevice: + { + m_instance = new SND_OpenALDevice(); + m_device_type = device_type; + break; + } +#endif + default: + { + m_instance = new SND_DummyDevice(); + m_device_type = device_type; + break; + } + } +} diff --git a/intern/SoundSystem/intern/SND_IdObject.cpp b/intern/SoundSystem/intern/SND_IdObject.cpp new file mode 100644 index 00000000000..b7e13cacbe6 --- /dev/null +++ b/intern/SoundSystem/intern/SND_IdObject.cpp @@ -0,0 +1,75 @@ +/* + * SND_IdObject.cpp + * + * Object for storing runtime data, like id's, soundobjects etc + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "SND_IdObject.h" + +SND_IdObject::SND_IdObject() +{ +} + + + +SND_IdObject::~SND_IdObject() +{ +} + + + +SND_SoundObject* SND_IdObject::GetSoundObject() +{ + return m_soundObject; +} + + + +void SND_IdObject::SetSoundObject(SND_SoundObject* pObject) +{ + m_soundObject = pObject; +} + + + +int SND_IdObject::GetId() +{ + return m_id; +} + + + +void SND_IdObject::SetId(int id) +{ + m_id = id; +} diff --git a/intern/SoundSystem/intern/SND_IdObject.h b/intern/SoundSystem/intern/SND_IdObject.h new file mode 100644 index 00000000000..116479eb69a --- /dev/null +++ b/intern/SoundSystem/intern/SND_IdObject.h @@ -0,0 +1,59 @@ +/* + * SND_IdObject.h + * + * Object for storing runtime data, like id's, soundobjects etc + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef __SND_IDOBJECT_H +#define __SND_IDOBJECT_H + +#include "SND_SoundObject.h" +#include "GEN_List.h" +#include "SoundDefines.h" + +class SND_IdObject : public GEN_Link +{ + SND_SoundObject* m_soundObject; + int m_id; + +public: + SND_IdObject(); + virtual ~SND_IdObject(); + + SND_SoundObject* GetSoundObject(); + void SetSoundObject(SND_SoundObject* pObject); + + int GetId(); + void SetId(int id); +}; +#endif //__SND_OBJECT_H diff --git a/intern/SoundSystem/intern/SND_Scene.cpp b/intern/SoundSystem/intern/SND_Scene.cpp new file mode 100644 index 00000000000..5bc65f02359 --- /dev/null +++ b/intern/SoundSystem/intern/SND_Scene.cpp @@ -0,0 +1,569 @@ +/* +* SND_Scene.cpp +* +* The scene for sounds. +* +* $Id$ +* + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ + +#ifdef WIN32 +#pragma warning (disable:4786) // Get rid of stupid stl-visual compiler debug warning +#endif //WIN32 + +#include "SND_Scene.h" +#include "SND_DependKludge.h" +#include "SYS_System.h" +#include "SND_IAudioDevice.h" + +#include <stdlib.h> +#include <iostream> + +//static unsigned int tijd = 0; + +SND_Scene::SND_Scene(SND_IAudioDevice* audiodevice) + : m_audiodevice(audiodevice) +{ + if (m_audiodevice) + m_wavecache = m_audiodevice->GetWaveCache(); + + if (!m_wavecache || !audiodevice) + { + m_audio = false; + } + else + { + //if so, go ahead! + m_audio = true; +#ifdef ONTKEVER + printf("SND_Scene::SND_Scene() m_audio == true\n"); +#endif + m_audiodevice->InitListener(); + } + + IsPlaybackWanted(); +} + + + +SND_Scene::~SND_Scene() +{ + StopAllObjects(); +} + + + +// check if audioplayback is wanted +bool SND_Scene::IsPlaybackWanted() +{ + SYS_SystemHandle syshandle = SYS_GetSystem(); + int audio = SYS_GetCommandLineInt(syshandle,"noaudio",0); + + if ((audio == 0) && m_audiodevice && m_wavecache) + { + m_audioplayback = true; + } + else + { + StopAllObjects(); + m_audioplayback = false; + } + + return m_audioplayback; +} + + + +int SND_Scene::LoadSample(const STR_String& samplename, + void* memlocation, + int size) +{ + int result = -1; + + if (m_audiodevice) + { + SND_WaveSlot* waveslot = m_audiodevice->LoadSample(samplename, memlocation, size); + + if (waveslot) + result = waveslot->GetBuffer(); + } + + return result; +} + + + +void SND_Scene::RemoveAllSamples() +{ + if (m_audio && m_audiodevice) + m_audiodevice->RemoveAllSamples(); +} + + + +bool SND_Scene::CheckBuffer(SND_SoundObject* pObject) +{ + bool result = false; + + if (pObject && m_wavecache) + { + SND_WaveSlot* waveslot = m_wavecache->GetWaveSlot(pObject->GetSampleName()); + + if (waveslot) + { + pObject->SetBuffer(waveslot->GetBuffer()); + + result = true; + } + } + + return result; +} + + + +bool SND_Scene::IsSampleLoaded(STR_String& samplename) +{ + bool result = false; + + if (samplename && m_wavecache) + { + SND_WaveSlot* waveslot = m_wavecache->GetWaveSlot(samplename); + + if (waveslot && waveslot->IsLoaded()) + result = true; + } + + return result; +} + + + +void SND_Scene::AddObject(SND_SoundObject* pObject) +{ + if (m_audio) + { + STR_String samplename = pObject->GetSampleName(); + SND_WaveSlot* slot = NULL; + + // don't add the object if no valid sample is referenced + if (samplename != "") + { + // check if the sample is already loaded + slot = m_wavecache->GetWaveSlot(samplename); + } + + if (slot) + { + pObject->SetBuffer(slot->GetBuffer()); + + // needed for expected lifespan of the sample, but ain't necesary anymore i think + MT_Scalar samplelength = slot->GetNumberOfSamples(); + MT_Scalar samplerate = slot->GetSampleRate(); + MT_Scalar soundlength = samplelength/samplerate; + pObject->SetLength(soundlength); + + // add the object to the list + m_soundobjects.insert((SND_SoundObject*)pObject); + } + } +} + + + +void SND_Scene::SetListenerTransform(const MT_Vector3& pos, + const MT_Vector3& vel, + const MT_Matrix3x3& ori) +{ + if (m_audio) + { + GetListener()->SetPosition(pos); + GetListener()->SetVelocity(vel); + GetListener()->SetOrientation(ori); + } +} + + + +void SND_Scene::UpdateListener() +{ + // process the listener if modified + if (m_listener.IsModified()) + { + m_audiodevice->SetListenerGain(m_listener.GetGain()); + + // fmod doesn't support dopplervelocity, so just use the dopplerfactor instead +#ifdef USE_FMOD + m_audiodevice->SetDopplerFactor(m_listener.GetDopplerVelocity()); +#else + m_audiodevice->SetDopplerVelocity(m_listener.GetDopplerVelocity()); + m_audiodevice->SetDopplerFactor(m_listener.GetDopplerFactor()); +#endif + m_listener.SetModified(false); + } +} + + + +void SND_Scene::AddActiveObject(SND_SoundObject* pObject, MT_Scalar curtime) +{ + if (m_audio) + { + if (pObject) + { +#ifdef ONTKEVER + printf("SND_Scene::AddActiveObject\n"); +#endif + + // first check if the object is already on the list + if (pObject->IsActive()) + { + pObject->SetTimeStamp(curtime); + pObject->StartSound(); + } + else + { + pObject->SetTimeStamp(curtime); + + // compute the expected lifespan + pObject->SetLifeSpan(); + + // lets give the new active-to-be object an id + if (m_audiodevice->GetNewId(pObject)) + { + // and add the object + m_activeobjects.addTail(pObject); + pObject->StartSound(); + pObject->SetActive(true); + } + } + } + } +} + + + +void SND_Scene::RemoveActiveObject(SND_SoundObject* pObject) +{ + if (m_audio) + { + if (pObject) + { +#ifdef ONTKEVER + printf("SND_Scene::RemoveActiveObject\n"); +#endif + // if inactive, remove it from the list + if (pObject->IsActive()) + { + // first make sure it is stopped + m_audiodevice->ClearId(pObject); + } + } + } +} + + + +void SND_Scene::UpdateActiveObects() +{ +// ++tijd; + + SND_SoundObject* pObject; + // update only the objects that need to be updated + for (pObject = (SND_SoundObject*)m_activeobjects.getHead(); + !pObject->isTail(); + pObject = (SND_SoundObject*)pObject->getNext()) + { + int id = pObject->GetId(); + + if (id >= 0) + { + bool juststartedplaying = false; +#ifdef USE_FMOD + // fmod wants these set before playing the sample + if (pObject->IsModified()) + { + m_audiodevice->SetObjectLoop(id, pObject->GetLoopMode()); + m_audiodevice->SetObjectLoopPoints(id, pObject->GetLoopStart(), pObject->GetLoopEnd()); + } + + // ok, properties Set. now see if it must play + if (pObject->GetPlaystate() == SND_MUST_PLAY) + { + m_audiodevice->PlayObject(id); + pObject->SetPlaystate(SND_PLAYING); + pObject->InitRunning(); +// printf("start play: %d\n", tijd); + juststartedplaying = true; + } +#endif + if (pObject->Is3D()) + { + // Get the global positions and velocity vectors + // of the listener and soundobject + MT_Vector3 op = pObject->GetPosition(); + MT_Vector3 lp = m_listener.GetPosition(); + MT_Vector3 position = op - lp; + + // Calculate relative velocity in global coordinates + // of the sound with respect to the listener. + MT_Vector3 ov = pObject->GetVelocity(); + MT_Vector3 lv = m_listener.GetVelocity(); + MT_Vector3 velocity = ov - lv; + + // Now map the object position and velocity into + // the local coordinates of the listener. + MT_Matrix3x3 lo = m_listener.GetOrientation(); + + MT_Vector3 local_sound_pos = position * lo; + MT_Vector3 local_sound_vel = velocity * lo; + + m_audiodevice->SetObjectTransform( + id, + local_sound_pos, + local_sound_vel, + pObject->GetOrientation(), // make relative to listener! + lp, + pObject->GetRollOffFactor()); + } + else + { + m_audiodevice->ObjectIs2D(id); + } + + // update the situation + if (pObject->IsModified()) + { + m_audiodevice->SetObjectPitch(id, pObject->GetPitch()); + m_audiodevice->SetObjectGain(id, pObject->GetGain()); + m_audiodevice->SetObjectMinGain(id, pObject->GetMinGain()); + m_audiodevice->SetObjectMaxGain(id, pObject->GetMaxGain()); + m_audiodevice->SetObjectReferenceDistance(id, pObject->GetReferenceDistance()); + m_audiodevice->SetObjectRollOffFactor(id, pObject->GetRollOffFactor()); + m_audiodevice->SetObjectLoop(id, pObject->GetLoopMode()); + m_audiodevice->SetObjectLoopPoints(id, pObject->GetLoopStart(), pObject->GetLoopEnd()); + pObject->SetModified(false); + } + + pObject->AddRunning(); + +#ifdef ONTKEVER + STR_String naam = pObject->GetObjectName(); + STR_String sample = pObject->GetSampleName(); + + int id = pObject->GetId(); + int buffer = pObject->GetBuffer(); + + float gain = pObject->GetGain(); + float pitch = pObject->GetPitch(); + float timestamp = pObject->GetTimestamp(); + + printf("naam: %s, sample: %s \n", naam.Ptr(), sample.Ptr()); + printf("id: %d, buffer: %d \n", id, buffer); + printf("gain: %f, pitch: %f, ts: %f \n\n", gain, pitch, timestamp); +#endif +#ifdef USE_OPENAL + // ok, properties Set. now see if it must play + if (pObject->GetPlaystate() == SND_MUST_PLAY) + { + m_audiodevice->PlayObject(id); + pObject->SetPlaystate(SND_PLAYING); + //break; + } +#endif + + // check to see if the sound is still playing + // if not: release its id + int playstate = m_audiodevice->GetPlayState(id); +#ifdef ONTKEVER + if (playstate != 2) + printf("%d - ",playstate); +#endif + +// if ((playstate == SND_STOPPED && (!juststartedplaying) && !pObject->GetLoopMode() && pObject->IsRunning()) +#ifdef WIN32 + if ((playstate == SND_STOPPED) && !pObject->GetLoopMode()) +#else + if (!pObject->GetLoopMode()) +#endif + { +// printf("remove: %d\n", tijd); + RemoveActiveObject(pObject); + } + } + } +} + + + +void SND_Scene::UpdateCD() +{ + if (m_audiodevice) + { + SND_CDObject* pCD = SND_CDObject::Instance(); + + if (pCD) + { + int playstate = pCD->GetPlaystate(); + + switch (playstate) + { + case SND_MUST_PLAY: + { + // initialize the cd only when you need it + m_audiodevice->SetCDGain(pCD->GetGain()); + m_audiodevice->SetCDPlaymode(pCD->GetPlaymode()); + m_audiodevice->PlayCD(pCD->GetTrack()); + pCD->SetPlaystate(SND_PLAYING); + pCD->SetUsed(); + break; + } + case SND_MUST_PAUSE: + { + m_audiodevice->PauseCD(true); + pCD->SetPlaystate(SND_PAUSED); + break; + } + case SND_MUST_RESUME: + { + m_audiodevice->PauseCD(false); + pCD->SetPlaystate(SND_PLAYING); + break; + } + case SND_MUST_STOP: + { + m_audiodevice->StopCD(); + pCD->SetPlaystate(SND_STOPPED); + break; + } + default: + { + } + } + + // this one is only for realtime modifying settings + if (pCD->IsModified()) + { + m_audiodevice->SetCDGain(pCD->GetGain()); + pCD->SetModified(false); + } + } + } +} + + + +void SND_Scene::Proceed() +{ + if (m_audio && m_audioplayback) + { + m_audiodevice->MakeCurrent(); + + UpdateListener(); + UpdateActiveObects(); + UpdateCD(); + +// m_audiodevice->UpdateDevice(); + } +} + + +void SND_Scene::DeleteObject(SND_SoundObject* pObject) +{ +#ifdef ONTKEVER + printf("SND_Scene::DeleteObject\n"); +#endif + + if (pObject) + { + if (m_audiodevice) + m_audiodevice->ClearId(pObject); + + // must remove object from m_activeList + std::set<SND_SoundObject*>::iterator set_it; + set_it = m_soundobjects.find(pObject); + + if (set_it != m_soundobjects.end()) + m_soundobjects.erase(set_it); + + // release the memory + delete pObject; + pObject = NULL; + } +} + + + +void SND_Scene::RemoveAllObjects() +{ +#ifdef ONTKEVER + printf("SND_Scene::RemoveAllObjects\n"); +#endif + + StopAllObjects(); + + std::set<SND_SoundObject*>::iterator it = m_soundobjects.begin(); + + while (it != m_soundobjects.end()) + { + delete (*it); + it++; + } + + m_soundobjects.clear(); +} + + + +void SND_Scene::StopAllObjects() +{ + if (m_audio) + { +#ifdef ONTKEVER + printf("SND_Scene::StopAllObjects\n"); +#endif + + SND_SoundObject* pObject; + + for (pObject = (SND_SoundObject*)m_activeobjects.getHead(); + !pObject->isTail(); + pObject = (SND_SoundObject*)pObject->getNext()) + { + m_audiodevice->ClearId(pObject); + } + } +} + + + +SND_SoundListener* SND_Scene::GetListener() +{ + return &m_listener; +} diff --git a/intern/SoundSystem/intern/SND_SoundListener.cpp b/intern/SoundSystem/intern/SND_SoundListener.cpp new file mode 100644 index 00000000000..281da2aa7fb --- /dev/null +++ b/intern/SoundSystem/intern/SND_SoundListener.cpp @@ -0,0 +1,184 @@ +/* + * SND_SoundListener.cpp + * + * A SoundListener is for sound what a camera is for vision. + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "SND_SoundListener.h" + +SND_SoundListener::SND_SoundListener() +{ + m_modified = true; + m_gain = 1.0; + m_dopplerfactor = 1.0; + m_dopplervelocity = 1.0; + m_scale = 1.0; + m_position[0] = 0.0; + m_position[1] = 0.0; + m_position[2] = 0.0; + m_velocity[0] = 0.0; + m_velocity[1] = 0.0; + m_velocity[2] = 0.0; + m_orientation[0][0] = 1.0; + m_orientation[0][1] = 0.0; + m_orientation[0][2] = 0.0; + m_orientation[1][0] = 0.0; + m_orientation[1][1] = 1.0; + m_orientation[1][2] = 0.0; + m_orientation[2][0] = 0.0; + m_orientation[2][1] = 0.0; + m_orientation[2][2] = 1.0; +} + + +SND_SoundListener::~SND_SoundListener() +{ + ; /* intentionally empty */ + +} + + + +void SND_SoundListener::SetGain(MT_Scalar gain) +{ + m_gain = gain; + m_modified = true; +} + + + +void SND_SoundListener::SetPosition (const MT_Vector3& pos) +{ + m_position = pos; +} + + + +void SND_SoundListener::SetVelocity(const MT_Vector3& vel) +{ + m_velocity = vel; +} + + + +void SND_SoundListener::SetOrientation(const MT_Matrix3x3& ori) +{ + m_orientation = ori; +} + + + +void SND_SoundListener::SetDopplerFactor(MT_Scalar dopplerfactor) +{ + m_dopplerfactor = dopplerfactor; + m_modified = true; +} + + + +void SND_SoundListener::SetDopplerVelocity(MT_Scalar dopplervelocity) +{ + m_dopplervelocity = dopplervelocity; + m_modified = true; +} + + + +void SND_SoundListener::SetScale(MT_Scalar scale) +{ + m_scale = scale; + m_modified = true; +} + + + +MT_Scalar SND_SoundListener::GetGain() const +{ + return m_gain; +} + + + +MT_Vector3 SND_SoundListener::GetPosition() const +{ + return m_position; +} + + + +MT_Vector3 SND_SoundListener::GetVelocity() const +{ + return m_velocity; +} + + + +MT_Matrix3x3 SND_SoundListener::GetOrientation() +{ + return m_orientation; +} + + + +MT_Scalar SND_SoundListener::GetDopplerFactor() const +{ + return m_dopplerfactor; +} + + + +MT_Scalar SND_SoundListener::GetDopplerVelocity() const +{ + return m_dopplervelocity; +} + + + +MT_Scalar SND_SoundListener::GetScale() const +{ + return m_scale; +} + + + +bool SND_SoundListener::IsModified() const +{ + return m_modified; +} + + + +void SND_SoundListener::SetModified(bool modified) +{ + m_modified = modified; +} diff --git a/intern/SoundSystem/intern/SND_SoundObject.cpp b/intern/SoundSystem/intern/SND_SoundObject.cpp new file mode 100644 index 00000000000..69066d0a2dd --- /dev/null +++ b/intern/SoundSystem/intern/SND_SoundObject.cpp @@ -0,0 +1,506 @@ +/* + * SND_SoundObject.cpp + * + * Implementation of the abstract sound object + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "SND_SoundObject.h" + + + +SND_SoundObject::SND_SoundObject()// : m_modified(true) +{ + m_samplename = ""; + m_length = 0; + m_buffer = 0; + + m_gain = 0.0; + m_pitch = 1.0; + + m_mingain = 0.0; + m_maxgain = 1.0; + m_rollofffactor = 1.0; + m_referencedistance = 1.0; + + m_position[0] = 0.0; + m_position[1] = 0.0; + m_position[2] = 0.0; + m_velocity[0] = 0.0; + m_velocity[1] = 0.0; + m_velocity[2] = 0.0; + m_orientation[0][0] = 1.0; + m_orientation[0][1] = 0.0; + m_orientation[0][2] = 0.0; + m_orientation[1][0] = 0.0; + m_orientation[1][1] = 1.0; + m_orientation[1][2] = 0.0; + m_orientation[2][0] = 0.0; + m_orientation[2][1] = 0.0; + m_orientation[2][2] = 1.0; + + m_loopstart = 0; + m_loopend = 0; + m_loopmode = SND_LOOP_NORMAL; + m_is3d = true; + m_playstate = SND_INITIAL; + m_active = false; + m_id = -1; + m_lifespan = 0; + m_timestamp = 0; + m_modified = true; + m_running = 0; + m_highpriority = false; +} + + + +SND_SoundObject::~SND_SoundObject() +{ +} + + + +void SND_SoundObject::StartSound() +{ + m_playstate = SND_MUST_PLAY; +} + + + +void SND_SoundObject::StopSound() +{ + m_playstate = SND_MUST_STOP; +} + + + +void SND_SoundObject::PauseSound() +{ + m_playstate = SND_MUST_PAUSE; +} + + + +void SND_SoundObject::DeleteWhenFinished() +{ + m_playstate = SND_MUST_BE_DELETED; +} + + + +void SND_SoundObject::SetGain(MT_Scalar gain) +{ + m_gain = gain; + m_modified = true; +} + + + +void SND_SoundObject::SetMinGain(MT_Scalar mingain) +{ + m_mingain = mingain; + m_modified = true; +} + + + +void SND_SoundObject::SetMaxGain(MT_Scalar maxgain) +{ + m_maxgain = maxgain; + m_modified = true; +} + + + +void SND_SoundObject::SetRollOffFactor(MT_Scalar rollofffactor) +{ + m_rollofffactor = rollofffactor; + m_modified = true; +} + + + +void SND_SoundObject::SetReferenceDistance(MT_Scalar referencedistance) +{ + m_referencedistance = referencedistance; + m_modified = true; +} + + + +void SND_SoundObject::SetPitch(MT_Scalar pitch) +{ + m_pitch = pitch; + m_modified = true; +} + + + +void SND_SoundObject::SetLoopMode(unsigned int loopmode) +{ + m_loopmode = loopmode; + m_modified = true; +} + + + +void SND_SoundObject::SetLoopStart(unsigned int loopstart) +{ + m_loopstart = loopstart; + m_modified = true; +} + + + +void SND_SoundObject::SetLoopEnd(unsigned int loopend) +{ + m_loopend = loopend; + m_modified = true; +} + + + +void SND_SoundObject::Set3D(bool threedee) +{ + m_is3d = threedee; +} + + + +void SND_SoundObject::SetLifeSpan() +{ + m_lifespan = m_length / m_pitch; +} + + + +bool SND_SoundObject::IsLifeSpanOver(MT_Scalar curtime) const +{ + bool result = false; + + if ((curtime - m_timestamp) > m_lifespan) + result = true; + + return result; +} + + + +void SND_SoundObject::SetActive(bool active) +{ + m_active = active; + + if (!active) + { + m_playstate = SND_STOPPED; + (this)->remove(); + } +} + + + +void SND_SoundObject::SetBuffer(unsigned int buffer) +{ + m_buffer = buffer; +} + + + +void SND_SoundObject::SetObjectName(STR_String objectname) +{ + m_objectname = objectname; +} + + + +void SND_SoundObject::SetSampleName(STR_String samplename) +{ + m_samplename = samplename; +} + + + +void SND_SoundObject::SetLength(MT_Scalar length) +{ + m_length = length; +} + + + +void SND_SoundObject::SetPosition(const MT_Vector3& pos) +{ + m_position = pos; +} + + + +void SND_SoundObject::SetVelocity(const MT_Vector3& vel) +{ + m_velocity = vel; +} + + + +void SND_SoundObject::SetOrientation(const MT_Matrix3x3& orient) +{ + m_orientation = orient; +} + + + +void SND_SoundObject::SetPlaystate(int playstate) +{ + m_playstate = playstate; +} + + + +void SND_SoundObject::SetId(int id) +{ + m_id = id; +} + + + +void SND_SoundObject::SetTimeStamp(MT_Scalar timestamp) +{ + m_timestamp = timestamp; +} + + + +void SND_SoundObject::SetHighPriority(bool priority) +{ + m_highpriority = priority; +} + + + +bool SND_SoundObject::IsHighPriority() const +{ + return m_highpriority; +} + + + +bool SND_SoundObject::IsActive()const +{ + return m_active; +} + + + +int SND_SoundObject::GetId()const +{ + return m_id; +} + + + +MT_Scalar SND_SoundObject::GetLifeSpan()const +{ + return m_lifespan; +} + + + +MT_Scalar SND_SoundObject::GetTimestamp()const +{ + return m_timestamp; +} + + + +unsigned int SND_SoundObject::GetBuffer() +{ + return m_buffer; +} + + + +const STR_String& SND_SoundObject::GetSampleName() +{ + return m_samplename; +} + + + +const STR_String& SND_SoundObject::GetObjectName() +{ + return m_objectname; +} + + + +MT_Scalar SND_SoundObject::GetLength() const +{ + return m_length; +} + + + +MT_Scalar SND_SoundObject::GetGain() const +{ + return m_gain; +} + + + +MT_Scalar SND_SoundObject::GetPitch() const +{ + return m_pitch; +} + + + +MT_Scalar SND_SoundObject::GetMinGain() const +{ + return m_mingain; +} + + + +MT_Scalar SND_SoundObject::GetMaxGain() const +{ + return m_maxgain; +} + + + +MT_Scalar SND_SoundObject::GetRollOffFactor() const +{ + return m_rollofffactor; +} + + + +MT_Scalar SND_SoundObject::GetReferenceDistance() const +{ + return m_referencedistance; +} + + + +MT_Vector3 SND_SoundObject::GetPosition() const +{ + return m_position; +} + + + +MT_Vector3 SND_SoundObject::GetVelocity() const +{ + return m_velocity; +} + + + +MT_Matrix3x3 SND_SoundObject::GetOrientation() const +{ + return m_orientation; +} + + + +unsigned int SND_SoundObject::GetLoopMode() const +{ + return m_loopmode; +} + + + +unsigned int SND_SoundObject::GetLoopStart() const +{ + return m_loopstart; +} + + + +unsigned int SND_SoundObject::GetLoopEnd() const +{ + return m_loopend; +} + + + +bool SND_SoundObject::Is3D() const +{ + return m_is3d; +} + + + +int SND_SoundObject::GetPlaystate() const +{ + return m_playstate; +} + + + +bool SND_SoundObject::IsModified() const +{ + return m_modified; +} + + + +void SND_SoundObject::SetModified(bool modified) +{ + m_modified = modified; +} + + + +void SND_SoundObject::InitRunning() +{ + m_running = 0; +} + + + +bool SND_SoundObject::IsRunning() const +{ + bool result = false; + + if (m_running > 100) + result = true; + + return result; +} + + + +void SND_SoundObject::AddRunning() +{ + ++m_running; +} diff --git a/intern/SoundSystem/intern/SND_Utils.cpp b/intern/SoundSystem/intern/SND_Utils.cpp new file mode 100644 index 00000000000..3965c534cd3 --- /dev/null +++ b/intern/SoundSystem/intern/SND_Utils.cpp @@ -0,0 +1,395 @@ +/* + * SND_Utils.cpp + * + * Util functions for soundthingies + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "SND_Utils.h" +#include "SoundDefines.h" +#include "SND_DependKludge.h" +/* +extern "C" { +#include "license_key.h" +} +*/ +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <math.h> +#include <string.h> + +#if defined(WIN32) +#include <io.h> +#else +#include <unistd.h> +#endif + +//extern int LICENSE_KEY_VALID; +#define LICENSE_KEY_VALID true + +#define BUFFERSIZE 32 + +/* loads a file */ +void* SND_LoadSample(char *filename) +{ + int file, filelen, buffersize = BUFFERSIZE; + void* data = NULL; + +#if defined(WIN32) + file = open(filename, O_BINARY|O_RDONLY); +#else + file = open(filename, 0|O_RDONLY); +#endif + + if (file == -1) + { + //printf("can't open file.\n"); + //printf("press q for quit.\n"); + } + else + { + filelen = lseek(file, 0, SEEK_END); + lseek(file, 0, SEEK_SET); + + if (filelen != 0) + { + data = malloc(buffersize); + + if (read(file, data, buffersize) != buffersize) + { + free(data); + data = NULL; + } + } + close(file); + + } + return (data); +} + + + +bool SND_IsSampleValid(const STR_String& name, void* memlocation) +{ + bool result = false; + bool loadedsample = false; + char buffer[BUFFERSIZE]; + + if (!memlocation) + { + STR_String samplename = name; + memlocation = SND_LoadSample(samplename.Ptr()); + + if (memlocation) + loadedsample = true; + } + + if (memlocation) + { + memcpy(&buffer, memlocation, BUFFERSIZE); + + if(!(memcmp(buffer, "RIFF", 4) && memcmp(&(buffer[8]), "WAVEfmt ", 8))) + { + int shortbuf = * ((short *) &buffer[20]); + if (shortbuf == SND_WAVE_FORMAT_PCM) + result = true; + + /* only fmod supports compressed wav */ +#ifdef USE_FMOD + /* and only valid publishers may use compressed wav */ + if (LICENSE_KEY_VALID) + { + switch (shortbuf) + { + case SND_WAVE_FORMAT_ADPCM: + case SND_WAVE_FORMAT_ALAW: + case SND_WAVE_FORMAT_MULAW: + case SND_WAVE_FORMAT_DIALOGIC_OKI_ADPCM: + case SND_WAVE_FORMAT_CONTROL_RES_VQLPC: + case SND_WAVE_FORMAT_GSM_610: + case SND_WAVE_FORMAT_MPEG3: + result = true; + break; + default: + { + break; + } + } + } +#endif + } +#ifdef USE_FMOD + /* only valid publishers may use ogg vorbis */ + else if (!memcmp(buffer, "OggS", 4) && LICENSE_KEY_VALID) + { + result = true; + } + /* only valid publishers may use mp3 */ + else if (((!memcmp(buffer, "ID3", 3)) || (!memcmp(buffer, "ÿû", 2))) && LICENSE_KEY_VALID) + { + result = true; + } +#endif + } + if (loadedsample) + { + free(memlocation); + memlocation = NULL; + } + + return result; +} + + + +/* checks if the passed pointer is a valid sample */ +bool CheckSample(void* sample) +{ + bool valid = false; + char buffer[32]; + + memcpy(buffer, sample, 16); + + if(!(memcmp(buffer, "RIFF", 4) && memcmp(&(buffer[8]), "WAVEfmt ", 8))) + { + valid = true; + } + + return valid; +} + + + +/* gets the type of the sample (0 == unknown, 1 == PCM etc */ +unsigned int SND_GetSampleFormat(void* sample) +{ + short sampletype = 0; + + if (CheckSample(sample)) + { + memcpy(&sampletype, ((char*)sample) + 20, 2); + } + + return (unsigned int)sampletype; +} + + + +/* gets the number of channels in a sample */ +unsigned int SND_GetNumberOfChannels(void* sample) +{ + short numberofchannels = 0; + + if (CheckSample(sample)) + { + memcpy(&numberofchannels, ((char*)sample) + 22, 2); + } + + return (unsigned int)numberofchannels; +} + + + +/* gets the samplerate of a sample */ +unsigned int SND_GetSampleRate(void* sample) +{ + unsigned int samplerate = 0; + + if (CheckSample(sample)) + { + memcpy(&samplerate, ((char*)sample) + 24, 4); + } + + return samplerate; +} + + + +/* gets the bitrate of a sample */ +unsigned int SND_GetBitRate(void* sample) +{ + short bitrate = 0; + + if (CheckSample(sample)) + { + memcpy(&bitrate, ((char*)sample) + 34, 2); + } + + return (unsigned int)bitrate; +} + + + +/* gets the length of the actual sample data (without the header) */ +unsigned int SND_GetNumberOfSamples(void* sample) +{ + unsigned int chunklength, length = 0, offset = 16; + char data[4]; + + if (CheckSample(sample)) + { + memcpy(&chunklength, ((char*)sample) + offset, 4); + offset = offset + chunklength + 4; + memcpy(data, ((char*)sample) + offset, 4); + + // lets find "data" + while (memcmp(data, "data", 4)) + { + offset += 4; + memcpy(data, ((char*)sample) + offset, 4); + } + offset += 4; + memcpy(&length, ((char*)sample) + offset, 4); + } + + return length; +} + + + +/* gets the size of the entire header (file - sampledata) */ +unsigned int SND_GetHeaderSize(void* sample) +{ + unsigned int chunklength, headersize = 0, offset = 16; + char data[4]; + + if (CheckSample(sample)) + { + memcpy(&chunklength, ((char*)sample) + offset, 4); + offset = offset + chunklength + 4; + memcpy(data, ((char*)sample) + offset, 4); + + // lets find "data" + while (memcmp(data, "data", 4)) + { + offset += 4; + memcpy(data, ((char*)sample) + offset, 4); + } + headersize = offset + 8; + } + + + return headersize; +} + + + +unsigned int SND_GetExtraChunk(void* sample) +{ + unsigned int extrachunk = 0, chunklength, offset = 16; + char data[4]; + + if (CheckSample(sample)) + { + memcpy(&chunklength, ((char*)sample) + offset, 4); + offset = offset + chunklength + 4; + memcpy(data, ((char*)sample) + offset, 4); + + // lets find "cue" + while (memcmp(data, "cue", 3)) + { + offset += 4; + memcpy(data, ((char*)sample) + offset, 4); + } + } + + return extrachunk; +} + + + +void SND_GetSampleInfo(signed char* sample, SND_WaveSlot* waveslot) +{ + WavFileHeader fileheader; + WavFmtHeader fmtheader; + WavFmtExHeader fmtexheader; + WavSampleHeader sampleheader; + WavChunkHeader chunkheader; + + if (CheckSample(sample)) + { + memcpy(&fileheader, sample, sizeof(WavFileHeader)); + sample += sizeof(WavFileHeader); + fileheader.size = ((fileheader.size+1) & ~1) - 4; + + while ((fileheader.size != 0) && (memcpy(&chunkheader, sample, sizeof(WavChunkHeader)))) + { + sample += sizeof(WavChunkHeader); + if (!memcmp(chunkheader.id, "fmt ", 4)) + { + memcpy(&fmtheader, sample, sizeof(WavFmtHeader)); + waveslot->SetSampleFormat(fmtheader.format); + + if (fmtheader.format == 0x0001) + { + waveslot->SetNumberOfChannels(fmtheader.numberofchannels); + waveslot->SetBitRate(fmtheader.bitrate); + waveslot->SetSampleRate(fmtheader.samplerate); + sample += chunkheader.size; + } + else + { + memcpy(&fmtexheader, sample, sizeof(WavFmtExHeader)); + sample += chunkheader.size; + } + } + else if (!memcmp(chunkheader.id, "data", 4)) + { + if (fmtheader.format == 0x0001) + { + waveslot->SetNumberOfSamples(chunkheader.size); + sample += chunkheader.size; + } + else if (fmtheader.format == 0x0011) + { + //IMA ADPCM + } + else if (fmtheader.format == 0x0055) + { + //MP3 WAVE + } + } + else if (!memcmp(chunkheader.id, "smpl", 4)) + { + memcpy(&sampleheader, sample, sizeof(WavSampleHeader)); + //loop = sampleheader.loops; + sample += chunkheader.size; + } + else + sample += chunkheader.size; + + sample += chunkheader.size & 1; + fileheader.size -= (((chunkheader.size + 1) & ~1) + 8); + } + } +} diff --git a/intern/SoundSystem/intern/SND_WaveCache.cpp b/intern/SoundSystem/intern/SND_WaveCache.cpp new file mode 100644 index 00000000000..279bc29aa83 --- /dev/null +++ b/intern/SoundSystem/intern/SND_WaveCache.cpp @@ -0,0 +1,134 @@ +/* + * SND_WaveCache.cpp + * + * abstract wavecache, a way to organize samples + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifdef WIN32 +#pragma warning (disable:4786) // Get rid of stupid stl-visual compiler debug warning +#endif //WIN32 + +#include "SND_WaveCache.h" +#include <stdio.h> + +#ifndef __APPLE__ +#include <malloc.h> +#else // __APPLE__ +#include <sys/malloc.h> +#endif // __APPLE__ + + +SND_WaveCache::SND_WaveCache() +{ + // do the buffer administration + for (int i = 0; i < NUM_BUFFERS; i++) + m_bufferList[i] = NULL; +} + + + +SND_WaveCache::~SND_WaveCache() +{ + // clean up the mess + FreeSamples(); + RemoveAllSamples(); +} + + + +SND_WaveSlot* SND_WaveCache::GetWaveSlot(const STR_String& samplename) +{ + SND_WaveSlot* waveslot = NULL; + + std::map<STR_String, SND_WaveSlot*>::iterator find_result = m_samplecache.find(samplename); + + // let's see if we have already loaded this sample + if (find_result != m_samplecache.end()) + { + waveslot = (*find_result).second; + } + else + { + // so the sample wasn't loaded, so do it here + for (int bufnum = 0; bufnum < NUM_BUFFERS; bufnum++) + { + // find an empty buffer + if (m_bufferList[bufnum] == NULL) + { + waveslot = new SND_WaveSlot(); + waveslot->SetSampleName(samplename); + waveslot->SetBuffer(bufnum); + m_bufferList[bufnum] = waveslot; + break; + } + } + m_samplecache.insert(std::pair<STR_String, SND_WaveSlot*>(samplename, waveslot)); + } + + return waveslot; +} + + + +void SND_WaveCache::RemoveAllSamples() +{ + // remove all samples + m_samplecache.clear(); + + // reset the list of buffers + for (int i = 0; i < NUM_BUFFERS; i++) + m_bufferList[i] = NULL; +} + + + +void SND_WaveCache::RemoveSample(const STR_String& samplename, int buffer) +{ + m_samplecache.erase(samplename); + m_bufferList[buffer] = NULL; +} + + + +void SND_WaveCache::FreeSamples() +{ + // iterate through the bufferlist and delete the waveslot if present + for (int i = 0; i < NUM_BUFFERS; i++) + { + if (m_bufferList[i]) + { + delete m_bufferList[i]; + m_bufferList[i] = NULL; + } + } +} diff --git a/intern/SoundSystem/intern/SND_WaveSlot.cpp b/intern/SoundSystem/intern/SND_WaveSlot.cpp new file mode 100644 index 00000000000..51356bba4bf --- /dev/null +++ b/intern/SoundSystem/intern/SND_WaveSlot.cpp @@ -0,0 +1,182 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + + +#include "SND_WaveSlot.h" + + + +SND_WaveSlot::~SND_WaveSlot() +{ +#ifdef ONTKEVER + printf("neeeeeee...\n"); +#endif +} + + + +void SND_WaveSlot::SetSampleName(STR_String samplename) +{ + m_samplename = samplename; +} + + + +void SND_WaveSlot::SetLoaded(bool loaded) +{ + m_loaded = loaded; +} + + + +void SND_WaveSlot::SetData(void* data) +{ + m_data = data; +} + + + +void SND_WaveSlot::SetBuffer(unsigned int buffer) +{ + m_buffer = buffer; +} + + + +void SND_WaveSlot::SetSampleFormat(unsigned int sampleformat) +{ + m_sampleformat = sampleformat; +} + + + +void SND_WaveSlot::SetNumberOfChannels(unsigned int numberofchannels) +{ + m_numberofchannels = numberofchannels; +} + + + +void SND_WaveSlot::SetSampleRate(unsigned int samplerate) +{ + m_samplerate = samplerate; +} + + + +void SND_WaveSlot::SetBitRate(unsigned int bitrate) +{ + m_bitrate = bitrate; +} + + + +void SND_WaveSlot::SetNumberOfSamples(unsigned int numberofsamples) +{ + m_numberofsamples = numberofsamples; +} + + + +void SND_WaveSlot::SetFileSize(unsigned int filesize) +{ + m_filesize = filesize; +} + + + +const STR_String& SND_WaveSlot::GetSampleName() +{ + return m_samplename; +} + + + +bool SND_WaveSlot::IsLoaded() const +{ + return m_loaded; +} + + + +void* SND_WaveSlot::GetData() +{ + return m_data; +} + + + +unsigned int SND_WaveSlot::GetBuffer() const +{ + return m_buffer; +} + + + +unsigned int SND_WaveSlot::GetSampleFormat() const +{ + return m_sampleformat; +} + + + +unsigned int SND_WaveSlot::GetNumberOfChannels() const +{ + return m_numberofchannels; +} + + + +unsigned int SND_WaveSlot::GetSampleRate() const +{ + return m_samplerate; +} + + + +unsigned int SND_WaveSlot::GetBitRate() const +{ + return m_bitrate; +} + + + +unsigned int SND_WaveSlot::GetNumberOfSamples() const +{ + return m_numberofsamples; +} + + + +unsigned int SND_WaveSlot::GetFileSize() const +{ + return m_filesize; +} diff --git a/intern/SoundSystem/openal/Makefile b/intern/SoundSystem/openal/Makefile new file mode 100644 index 00000000000..277332abde6 --- /dev/null +++ b/intern/SoundSystem/openal/Makefile @@ -0,0 +1,47 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# +# + +LIBNAME = OpenALSoundSystem +DIR = $(OCGDIR)/gameengine/$(LIBNAME) + +include nan_compile.mk + +CCFLAGS += $(LEVEL_1_CPP_WARNINGS) + +CPPFLAGS += -I$(NAN_OPENAL)/include +CPPFLAGS += -I$(NAN_STRING)/include +CPPFLAGS += -I$(NAN_MOTO)/include +CPPFLAGS += -I../../../kernel/gen_system +CPPFLAGS += -I../intern +CPPFLAGS += -I.. +CPPFLAGS += -I. diff --git a/intern/SoundSystem/openal/SND_OpenALDevice.cpp b/intern/SoundSystem/openal/SND_OpenALDevice.cpp new file mode 100644 index 00000000000..a5cbf8d3300 --- /dev/null +++ b/intern/SoundSystem/openal/SND_OpenALDevice.cpp @@ -0,0 +1,661 @@ +/* + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * SND_OpenALDevice derived from SND_IAudioDevice + */ + +#ifdef WIN32 +#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning +#endif //WIN32 + +#include "SND_OpenALDevice.h" +#include "SoundDefines.h" +#include "SYS_System.h" + +#include "SND_Utils.h" + +#include <AL/al.h> +#include <AL/alc.h> +#include <AL/alut.h> + +#include <stdio.h> +#include <stdlib.h> +#if defined(WIN32) +#include <io.h> +#else +#include <unistd.h> +#endif +#include <fcntl.h> + +/* untill openal gets unified we need this hack for non-windows systems */ +#ifndef WIN32 + +#include <malloc.h> + +ALvoid alutLoadWAVMemory(ALbyte *memory,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq,ALboolean *loop); +ALvoid alutUnloadWAV(ALenum format,ALvoid *data,ALsizei size,ALsizei freq); + +typedef struct /* WAV File-header */ +{ + ALubyte Id[4]; + ALsizei Size; + ALubyte Type[4]; +} WAVFileHdr_Struct; + +typedef struct /* WAV Fmt-header */ +{ + ALushort Format; + ALushort Channels; + ALuint SamplesPerSec; + ALuint BytesPerSec; + ALushort BlockAlign; + ALushort BitsPerSample; +} WAVFmtHdr_Struct; + +typedef struct /* WAV FmtEx-header */ +{ + ALushort Size; + ALushort SamplesPerBlock; +} WAVFmtExHdr_Struct; + +typedef struct /* WAV Smpl-header */ +{ + ALuint Manufacturer; + ALuint Product; + ALuint SamplePeriod; + ALuint Note; + ALuint FineTune; + ALuint SMPTEFormat; + ALuint SMPTEOffest; + ALuint Loops; + ALuint SamplerData; + struct + { + ALuint Identifier; + ALuint Type; + ALuint Start; + ALuint End; + ALuint Fraction; + ALuint Count; + } Loop[1]; +} WAVSmplHdr_Struct; + +typedef struct /* WAV Chunk-header */ +{ + ALubyte Id[4]; + ALuint Size; +} WAVChunkHdr_Struct; + +ALvoid alutLoadWAVMemory(ALbyte *memory,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq,ALboolean *loop) +{ + WAVChunkHdr_Struct ChunkHdr; + WAVFmtExHdr_Struct FmtExHdr; + WAVFileHdr_Struct FileHdr; + WAVSmplHdr_Struct SmplHdr; + WAVFmtHdr_Struct FmtHdr; + ALbyte *Stream; + + *format=AL_FORMAT_MONO16; + *data=NULL; + *size=0; + *freq=22050; + *loop=AL_FALSE; + if (memory) + { + Stream=memory; + if (Stream) + { + memcpy(&FileHdr,Stream,sizeof(WAVFileHdr_Struct)); + Stream+=sizeof(WAVFileHdr_Struct); + FileHdr.Size=((FileHdr.Size+1)&~1)-4; + while ((FileHdr.Size!=0)&&(memcpy(&ChunkHdr,Stream,sizeof(WAVChunkHdr_Struct)))) + { + Stream+=sizeof(WAVChunkHdr_Struct); + if (!memcmp(ChunkHdr.Id,"fmt ",4)) + { + memcpy(&FmtHdr,Stream,sizeof(WAVFmtHdr_Struct)); + if (FmtHdr.Format==0x0001) + { + *format=(FmtHdr.Channels==1? + (FmtHdr.BitsPerSample==8?AL_FORMAT_MONO8:AL_FORMAT_MONO16): + (FmtHdr.BitsPerSample==8?AL_FORMAT_STEREO8:AL_FORMAT_STEREO16)); + *freq=FmtHdr.SamplesPerSec; + Stream+=ChunkHdr.Size; + } + else + { + memcpy(&FmtExHdr,Stream,sizeof(WAVFmtExHdr_Struct)); + Stream+=ChunkHdr.Size; + } + } + else if (!memcmp(ChunkHdr.Id,"data",4)) + { + if (FmtHdr.Format==0x0001) + { + *size=ChunkHdr.Size; + *data=malloc(ChunkHdr.Size+31); + if (*data) memcpy(*data,Stream,ChunkHdr.Size); + memset(((char *)*data)+ChunkHdr.Size,0,31); + Stream+=ChunkHdr.Size; + } + else if (FmtHdr.Format==0x0011) + { + //IMA ADPCM + } + else if (FmtHdr.Format==0x0055) + { + //MP3 WAVE + } + } + else if (!memcmp(ChunkHdr.Id,"smpl",4)) + { + memcpy(&SmplHdr,Stream,sizeof(WAVSmplHdr_Struct)); + *loop = (SmplHdr.Loops ? AL_TRUE : AL_FALSE); + Stream+=ChunkHdr.Size; + } + else Stream+=ChunkHdr.Size; + Stream+=ChunkHdr.Size&1; + FileHdr.Size-=(((ChunkHdr.Size+1)&~1)+8); + } + } + } +} + +ALvoid alutUnloadWAV(ALenum format,ALvoid *data,ALsizei size,ALsizei freq) +{ + if (data) + free(data); +} + +#endif /* WIN32 */ + + + +SND_OpenALDevice::SND_OpenALDevice() +{ + // check if audio is wanted + SYS_SystemHandle syshandle = SYS_GetSystem(); + int audio = SYS_GetCommandLineInt(syshandle,"noaudio",0); + + if (audio != 0) + m_audio = false; + else + m_audio = true; + + m_buffersinitialized = false; + m_sourcesinitialized = false; + + // let's check if we can get openal to initialize... + if (m_audio) + { +#ifdef OUDE_OPENAL + m_audio = true; // openal_2.12 + alutInit(NULL, NULL); // openal_2.12 +#else + m_audio = false; + + ALCdevice *dev = alcOpenDevice(NULL); + if (dev) { + m_context = alcCreateContext(dev, NULL); + + if (m_context) { + alcMakeContextCurrent(m_context); + m_audio = true; + } + } + +#endif + } + + // then try to generate some buffers + if (m_audio) + { + // let openal generate its buffers + alGenBuffers(NUM_BUFFERS, m_buffers); + m_buffersinitialized = true; + + for (int i = 0; i < NUM_BUFFERS; i++) + { + if (!alIsBuffer(m_buffers[i])) + { + //printf("\n\n WARNING: OpenAL returned with an error. Continuing without audio.\n\n"); + m_audio = false; + break; + } + } + } + + // next: the sources + if (m_audio) + { +#ifdef OUDE_OPENAL + ALenum alc_error = ALC_NO_ERROR; // openal_2.12 +#else + ALenum alc_error = alcGetError(); // openal_2.14+ +#endif + + // let openal generate its sources + if (alc_error == ALC_NO_ERROR) + { + alGenSources(NUM_SOURCES, m_sources); + m_sourcesinitialized = true; + } + } + + // let's get us a wavecache + if (m_audio) + { + m_wavecache = new SND_WaveCache(); + } +} + + + +void SND_OpenALDevice::MakeCurrent() const +{ +#ifdef WIN32 + alcMakeContextCurrent(m_context); +#endif +} + + + +SND_OpenALDevice::~SND_OpenALDevice() +{ + if (m_context) { + alcMakeContextCurrent(m_context); + + if (m_buffersinitialized) + alDeleteBuffers(NUM_BUFFERS, m_buffers); + + if (m_sourcesinitialized) + alDeleteSources(NUM_SOURCES, m_sources); + } +} + + + +SND_WaveSlot* SND_OpenALDevice::LoadSample(const STR_String& name, + void* memlocation, + int size) +{ + SND_WaveSlot* waveslot = NULL; + STR_String samplename = name; + + if (m_audio) + { + /* create the waveslot */ + waveslot = m_wavecache->GetWaveSlot(samplename); + + /* do we support this sample? */ + if (SND_IsSampleValid(name, memlocation)) + { + if (waveslot) + { + int buffer = waveslot->GetBuffer(); + void* data = NULL; + char loop = 'a'; + int sampleformat, bitrate, numberofchannels; + ALenum al_error = alGetError(); + +#ifdef OUDE_OPENAL + unsigned int samplerate, numberofsamples; // openal_2.12 +#else + int samplerate, numberofsamples, frequency; // openal_2.14+ +#endif + + /* load the sample from memory? */ + if (size && memlocation) + { + waveslot->SetFileSize(size); + + /* what was (our) buffer? */ + int buffer = waveslot->GetBuffer(); + + /* get some info out of the sample */ + SND_GetSampleInfo((signed char*)memlocation, waveslot); + numberofchannels = SND_GetNumberOfChannels(memlocation); + bitrate = SND_GetBitRate(memlocation); + + /* load the sample into openal */ +#ifdef OUDE_OPENAL + alutLoadWAVMemory((char*)memlocation, &sampleformat, &data, &numberofsamples, &samplerate); // openal_2.12 +#else + alutLoadWAVMemory((signed char*)memlocation, &sampleformat, &data, &numberofsamples, &samplerate, &loop);// openal_2.14+ +#endif + /* put it in the buffer */ + alBufferData(m_buffers[buffer], sampleformat, data, numberofsamples, samplerate); + } + /* or from file? */ + else + { +#ifdef WIN32 + alutLoadWAVFile((signed char*)samplename.Ptr(), &sampleformat, &data, &numberofsamples, &samplerate, &loop); +#else + alutLoadWAV((char*)samplename.Ptr(), &data, + &sampleformat, &numberofsamples, + &samplerate, &frequency); +#endif + /* put it in the buffer */ + alBufferData(m_buffers[buffer], sampleformat, data, numberofsamples, samplerate); + } + + /* fill the waveslot with info */ + al_error = alGetError(); + if (al_error == AL_NO_ERROR && m_buffers[buffer]) + { + waveslot->SetData(data); + waveslot->SetSampleFormat(sampleformat); + waveslot->SetNumberOfChannels(numberofchannels); + waveslot->SetSampleRate(samplerate); + waveslot->SetBitRate(bitrate); + waveslot->SetNumberOfSamples(numberofsamples); + + /* if the loading succeeded, mark the waveslot */ + waveslot->SetLoaded(true); + } + else + { + /* or when it failed, free the waveslot */ + m_wavecache->RemoveSample(waveslot->GetSampleName(), waveslot->GetBuffer()); + waveslot = NULL; + } + + /* and free the original stuff (copy was made in openal) */ + alutUnloadWAV(sampleformat, data, numberofsamples, samplerate); + } + } + else + { + /* sample not supported, remove waveslot */ + m_wavecache->RemoveSample(waveslot->GetSampleName(), waveslot->GetBuffer()); + waveslot = NULL; + } + } + return waveslot; +} + + + +// listener's and general stuff ////////////////////////////////////////////////////// + + + +/* sets the global dopplervelocity */ +void SND_OpenALDevice::SetDopplerVelocity(MT_Scalar dopplervelocity) const +{ + alDopplerVelocity ((float)dopplervelocity); +} + + + +/* sets the global dopplerfactor */ +void SND_OpenALDevice::SetDopplerFactor(MT_Scalar dopplerfactor) const +{ + alDopplerFactor ((float)dopplerfactor); +} + + + +/* sets the global rolloff factor */ +void SND_OpenALDevice::SetListenerRollOffFactor(MT_Scalar rollofffactor) const +{ + // not implemented in openal +} + + + +void SND_OpenALDevice::NextFrame() const +{ + // not needed by openal +} + + + +// set the gain for the listener +void SND_OpenALDevice::SetListenerGain(float gain) const +{ + alListenerf (AL_GAIN, gain); +} + + + +void SND_OpenALDevice::InitListener() +{ + // initialize the listener with these values that won't change + // (as long as we can have only one listener) + // now we can superimpose all listeners on each other (for they + // have the same settings) + float lispos[3] = {0,0,0}; + float lisvel[3] = {0,0,0}; +#ifdef WIN32 + float lisori[6] = {0,1,0,0,0,1}; +#else + float lisori[6] = {0,0,1,0,-1,0}; +#endif + + alListenerfv(AL_POSITION, lispos); + alListenerfv(AL_VELOCITY, lisvel); + alListenerfv(AL_ORIENTATION, lisori); +} + + + +// source playstate stuff //////////////////////////////////////////////////////////// + + + +/* sets the buffer */ +void SND_OpenALDevice::SetObjectBuffer(int id, unsigned int buffer) +{ + alSourcei (m_sources[id], AL_BUFFER, m_buffers[buffer]); +} + + + +// check if the sound's still playing +int SND_OpenALDevice::GetPlayState(int id) +{ + int alstate = 0; + int result = 0; + + alGetSourceiv(m_sources[id], AL_SOURCE_STATE, &alstate); + + switch(alstate) + { + case AL_INITIAL: + { + result = SND_INITIAL; + break; + } + case AL_PLAYING: + { + result = SND_PLAYING; + break; + } + case AL_PAUSED: + { + result = SND_PAUSED; + break; + } + case AL_STOPPED: + { + result = SND_STOPPED; + break; + } + default: + result = SND_UNKNOWN; + } + + return result; +} + + + +// make the source play +void SND_OpenALDevice::PlayObject(int id) +{ + alSourcePlay(m_sources[id]); +} + + + +// make the source stop +void SND_OpenALDevice::StopObject(int id) const +{ + float obpos[3] = {0,0,0}; + float obvel[3] = {0,0,0}; + + alSourcefv(m_sources[id], AL_POSITION, obpos); + +#ifdef WIN32 + alSourcefv(m_sources[id], AL_VELOCITY, obvel); +#endif + + alSourcef(m_sources[id], AL_GAIN, 1.0); + alSourcef(m_sources[id], AL_PITCH, 1.0); + alSourcei(m_sources[id], AL_LOOPING, AL_FALSE); + alSourceStop(m_sources[id]); +} + + + +// stop all sources +void SND_OpenALDevice::StopAllObjects() +{ + alSourceStopv(NUM_SOURCES, m_sources); +} + + + +// pause the source +void SND_OpenALDevice::PauseObject(int id) const +{ + alSourcePause(m_sources[id]); +} + + + +// source properties stuff //////////////////////////////////////////////////////////// + + + +// give openal the object's pitch +void SND_OpenALDevice::SetObjectPitch(int id, MT_Scalar pitch) const +{ + alSourcef (m_sources[id], AL_PITCH, (float)pitch); +} + + + +// give openal the object's gain +void SND_OpenALDevice::SetObjectGain(int id, MT_Scalar gain) const +{ + alSourcef (m_sources[id], AL_GAIN, (float)gain); +} + + + +// give openal the object's looping +void SND_OpenALDevice::SetObjectLoop(int id, unsigned int loopmode) const +{ + if (loopmode == SND_LOOP_OFF) + { + //printf("%d - ", id); + alSourcei (m_sources[id], AL_LOOPING, AL_FALSE); + } + else + alSourcei (m_sources[id], AL_LOOPING, AL_TRUE); +} + + + +void SND_OpenALDevice::SetObjectMinGain(int id, MT_Scalar mingain) const +{ + alSourcef (m_sources[id], AL_MIN_GAIN, (float)mingain); +} + + + +void SND_OpenALDevice::SetObjectMaxGain(int id, MT_Scalar maxgain) const +{ + alSourcef (m_sources[id], AL_MAX_GAIN, (float)maxgain); +} + + + +void SND_OpenALDevice::SetObjectRollOffFactor(int id, MT_Scalar rollofffactor) const +{ + alSourcef (m_sources[id], AL_ROLLOFF_FACTOR, (float)rollofffactor); +} + + + +void SND_OpenALDevice::SetObjectReferenceDistance(int id, MT_Scalar referencedistance) const +{ + alSourcef (m_sources[id], AL_REFERENCE_DISTANCE, (float)referencedistance); +} + + + +// give openal the object's position +void SND_OpenALDevice::ObjectIs2D(int id) const +{ + float obpos[3] = {0,0,0}; + float obvel[3] = {0,0,0}; + + alSourcefv(m_sources[id], AL_POSITION, obpos); + alSourcefv(m_sources[id], AL_VELOCITY, obvel); +} + + + +void SND_OpenALDevice::SetObjectTransform(int id, + const MT_Vector3& position, + const MT_Vector3& velocity, + const MT_Matrix3x3& orientation, + const MT_Vector3& lisposition, + const MT_Scalar& rollofffactor) const +{ + float obpos[3]; + float obvel[3]; + + obpos[0] = (float)position[0] * (float)rollofffactor; //x (l/r) + obpos[1] = (float)position[1] * (float)rollofffactor; + obpos[2] = (float)position[2] * (float)rollofffactor; + + alSourcefv(m_sources[id], AL_POSITION, obpos); + +#ifdef WIN32 + velocity.getValue(obvel); + alSourcefv(m_sources[id], AL_VELOCITY, obvel); +#endif + +} diff --git a/intern/SoundSystem/openal/SND_OpenALDevice.h b/intern/SoundSystem/openal/SND_OpenALDevice.h new file mode 100644 index 00000000000..95940bacde2 --- /dev/null +++ b/intern/SoundSystem/openal/SND_OpenALDevice.h @@ -0,0 +1,102 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef SND_OPENALDEVICE +#define SND_OPENALDEVICE + +#include "SND_AudioDevice.h" +#include "SoundDefines.h" + +class SND_OpenALDevice : public SND_AudioDevice +{ +public: + SND_OpenALDevice(); + ~SND_OpenALDevice(); + + SND_WaveSlot* LoadSample(const STR_String& samplename, + void* memlocation, + int size); + + void InitListener(); + void SetListenerGain(float gain) const; + void SetDopplerVelocity(MT_Scalar dopplervelocity) const; + void SetDopplerFactor(MT_Scalar dopplerfactor) const; + void SetListenerRollOffFactor(MT_Scalar rollofffactor) const; + + void MakeCurrent() const; + + void NextFrame() const; + + void SetObjectBuffer(int id, unsigned int buffer); + + int GetPlayState(int id); + void PlayObject(int id); + void StopObject(int id) const; + void StopAllObjects(); + void PauseObject(int id) const; + + void SetObjectLoop(int id, unsigned int loopmode) const; + void SetObjectLoopPoints(int id, unsigned int loopstart, unsigned int loopend) const {}; + void SetObjectPitch(int id, MT_Scalar pitch) const; + void SetObjectGain(int id, MT_Scalar gain) const; + void SetObjectMinGain(int id, MT_Scalar mingain) const; + void SetObjectMaxGain(int id, MT_Scalar maxgain) const; + void SetObjectRollOffFactor(int id, MT_Scalar rolloff) const; + void SetObjectReferenceDistance(int id, MT_Scalar distance) const; + + void SetObjectTransform(int id, + const MT_Vector3& position, + const MT_Vector3& velocity, + const MT_Matrix3x3& orientation, + const MT_Vector3& lisposition, + const MT_Scalar& rollofffactor) const; + void ObjectIs2D(int id) const; + + void PlayCD(int track) const {}; + void PauseCD(bool pause) const {}; + void StopCD() const {}; + void SetCDPlaymode(int playmode) const {}; + void SetCDGain(MT_Scalar gain) const {}; + + void StartUsingDSP() {}; + float* GetSpectrum() { return NULL; } + void StopUsingDSP() {}; + +private: + void* m_context; + + unsigned int m_buffers[NUM_BUFFERS]; + unsigned int m_sources[NUM_SOURCES]; + bool m_buffersinitialized; + bool m_sourcesinitialized; +}; + +#endif //SND_OPENALDEVICE diff --git a/intern/SoundSystem/openal/pthread_cancel.cpp b/intern/SoundSystem/openal/pthread_cancel.cpp new file mode 100644 index 00000000000..de05c742dea --- /dev/null +++ b/intern/SoundSystem/openal/pthread_cancel.cpp @@ -0,0 +1,65 @@ +/* $Id$ +/* + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * FreeBSD 3.4 does not yet have pthread_cancel (3.5 and above do) + */ +#ifdef __FreeBSD__ + +#include <osreldate.h> + +#if (__FreeBSD_version < 350000) +#include <pthread.h> + +#define FD_READ 0x1 +#define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock(_fd, _type, _ts) +#define _FD_UNLOCK(_fd,_type) _thread_fd_unlock(_fd, _type) + +int pthread_cancel(pthread_t pthread) { + pthread_exit(NULL); + return 0; +} + +long fpathconf(int fd, int name) +{ + long ret; + + if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) { + ret = _thread_sys_fpathconf(fd, name); + _FD_UNLOCK(fd, FD_READ); + } + return ret; +} + +#endif + +int pthread_atfork(void *a, void *b, void *c) { + return 0; +} + +#endif diff --git a/intern/action/ACT_Action.h b/intern/action/ACT_Action.h new file mode 100644 index 00000000000..2b54d10359e --- /dev/null +++ b/intern/action/ACT_Action.h @@ -0,0 +1,140 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date March 31, 2001 + */ + +#ifndef _H_ACT_ACTION_H_ +#define _H_ACT_ACTION_H_ + +#include "MEM_RefCounted.h" +#include "STR_String.h" + +/** + * An action that can be applied or undone. + * Virtual base class for actions with a name. + * An action object inherits the shared object reference count mechanism. + * @author Maarten Gribnau + * @date March 31, 2001 + */ + +class ACT_Action : public MEM_RefCounted { +public: + /** + * Constructs an action with the given name . + * @param name the name of the action. + * @param applied state of the action after creation. + */ + ACT_Action(const STR_String& name, bool applied = false); + + /** + * Returns the name of the action. + * @param name the name of the action. + */ + inline virtual void getName(STR_String& name) const; + + /** + * Returns the name of the action as a pointer to the data of the string. + * @return pointer to the name of the action. + */ + inline virtual char* getName(); + + /** + * Sets the name of the action. + * @param name the name of the action. + */ + inline virtual void setName(const STR_String& name); + + /** + * Returns whether this action is applied. + * @return whether this action is applied. + */ + inline virtual bool getIsApplied() const; + + + /** + * Call this member to apply an action. + * Child classes should override the doApply member to implement apply functionality. + * @see doApply. + */ + virtual void apply(); + + /** + * Call this member to undo an action . + * Child classes should override the doUndo member to implement undo functionality. + * @see doApply() + */ + virtual void undo(); + +protected: + /** + * Implementations should overload this method to provide the apply functionality. + */ + virtual void doApply() = 0; + + /** + * Implementations should overload this method to provide the undo functionality. + */ + virtual void doUndo() = 0; + + /** Name of this action */ + STR_String m_name; + /** Is this action already applied? */ + bool m_applied; +}; + + +void ACT_Action::getName(STR_String& name) const +{ + name = m_name; +} + +char* ACT_Action::getName() +{ + return m_name.Ptr(); +} + +void ACT_Action::setName(const STR_String& name) +{ + m_name = name; +} + +inline bool ACT_Action::getIsApplied() const +{ + return m_applied; +} + +#endif // _H_ACT_ACTION_H_
\ No newline at end of file diff --git a/intern/action/ACT_ActionC-Api.h b/intern/action/ACT_ActionC-Api.h new file mode 100644 index 00000000000..ebc1ce7d5a0 --- /dev/null +++ b/intern/action/ACT_ActionC-Api.h @@ -0,0 +1,192 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * Interface for C access to actions. + * @author Maarten Gribnau + * @date April, 25, 2001 + */ + +#ifndef _H_ACT_ACTION_C_API +#define _H_ACT_ACTION_C_API + +#include "MEM_RefCountedC-Api.h" + +/** A pointer to an action object. */ +typedef MEM_TRefCountedObjectPtr ACT_ActionPtr; +/** A pointer to an action stack object. */ +typedef MEM_TObjectPtr ACT_ActionStackPtr; + + +/** A pointer to user data passed by the callbacks. */ +typedef void* ACT_ActionUserDataPtr; + +/** + * An action apply callback routine. + * @param action The action that should be applied. + * @param userData The pointer to the user data provided when the action was created. + */ +typedef void (*ACT_ActionApplyProcPtr)(ACT_ActionPtr action, ACT_ActionUserDataPtr userData); + +/** + * An action undo callback routine. + * @param action The action that should be undone. + * @param userData The pointer to the user data provided when the action was created. + */ +typedef void (*ACT_ActionUndoProcPtr)(ACT_ActionPtr action, ACT_ActionUserDataPtr userData); + +/** + * An action dispose callback routine. + * @param action The action that is disposed. + * @param userData The pointer to the user data provided when the action was created. + */ +typedef void (*ACT_ActionDisposeProcPtr)(ACT_ActionPtr action, ACT_ActionUserDataPtr userData); + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * An action is a shared object that can be applied or undone. + */ + +/** + * Creates a new action. + * This is an action that calls the given callbacks when it needs to be applied or undone. + * @param name The name of the action. + * @param isApplied Indication as to whether the action is already applied (0 = not applied). + * @param userData Pointer passed to the apply/undo callbacks. + * @param applyProc Pointer to the callback invoked when the action needs to be applied. + * @param undoProc Pointer to the callback invoked when the action needs to be undone. + * @return The new action (null in case of error). + */ +extern ACT_ActionPtr ACT_ActionCreate( + char* name, + int isApplied, + ACT_ActionUserDataPtr userData, + ACT_ActionApplyProcPtr applyProc, + ACT_ActionUndoProcPtr undoProc, + ACT_ActionDisposeProcPtr disposeProc); + +/** + * Returns the name of an action. + * @return The name of the action (null in case of error). + */ +extern char* ACT_ActionGetName(ACT_ActionPtr action); + + + +/** + * An action stack stores actions and implements undo/redo functionality. + */ + +/** + * Creates a new action stack. + * @param stackSize The maximum number of actions on the stack. + * @return The new stack (or NULL in case of error). + */ +extern ACT_ActionStackPtr ACT_ActionStackCreate(unsigned int stackSize); + +/** + * Disposes an action stack. + * @param stack The appropriate stack. + */ +extern void ACT_ActionStackDispose(ACT_ActionStackPtr stack); + +/** + * Returns the current depth of the stack. + * @param stack The appropriate stack. + * @return the current stack depth. + */ +extern unsigned int ACT_ActionStackGetStackDepth(ACT_ActionStackPtr stack); + +/** + * Returns the current maximum depth of the stack. + * @param stack The appropriate stack. + * @return the maximum stack depth. + */ +extern unsigned int ACT_ActionStackGetMaxStackDepth(ACT_ActionStackPtr stack); + +/** + * Sets new maximum depth of the stack. + * @param stack The appropriate stack. + * @param maxStackDepth The new stack depth. + */ +extern void ACT_ActionStackSetMaxStackDepth(ACT_ActionStackPtr stack, unsigned int maxStackDepth); + +/** + * Pushes an action on the stack. + * If the action has not been applied yet, it will be applied here. + * This will increase the reference count of the action. + * If there is not enough capacity, the action at the bottom of the stack is removed (and its reference count decreased). + * @param stack The appropriate stack. + * @param action the action that is pushed onto the stack. + */ +extern void ACT_ActionStackPush(ACT_ActionStackPtr stack, ACT_ActionPtr action); + +/** + * Returns pointer to the current undo item. + * @param stack The appropriate stack. + * @return The action scheduled for undo (0 if there is none). + */ +extern ACT_ActionStackPtr ACT_ActionStackPeekUndo(ACT_ActionStackPtr stack); + +/** + * Returns pointer to the current redo item. + * @param stack The appropriate stack. + * @return The action scheduled for redo (0 if there is none). + */ +extern ACT_ActionStackPtr ACT_ActionStackPeekRedo(ACT_ActionStackPtr stack); + +/** + * Undos the current action. + * @param stack The appropriate stack. + * This will move the current undo index down (if the stack depth allows it). + */ +extern void ACT_ActionStackUndo(ACT_ActionStackPtr stack); + +/** + * Redos the current action. + * @param stack The appropriate stack. + * This will move the action index up (if the stack depth allows it). + */ +extern void ACT_ActionStackRedo(ACT_ActionStackPtr stack); + + +#ifdef __cplusplus +} +#endif + +#endif // _H_ACT_ACTION_C_API
\ No newline at end of file diff --git a/intern/action/ACT_ActionStack.h b/intern/action/ACT_ActionStack.h new file mode 100644 index 00000000000..13db963020e --- /dev/null +++ b/intern/action/ACT_ActionStack.h @@ -0,0 +1,184 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date March 31, 2001 + */ + +#ifndef _H_ACT_ACTIONSTACK +#define _H_ACT_ACTIONSTACK + +#include "ACT_Action.h" +#include <deque> + + +/** + * A stack with actions that implements undo/redo capabilities. + * A stack can grow to a maximum number of actions by pushing actions on the stack. + * By calling undo and redo the apply and undo members of the actions on the stack are called. + * In addition, this will move the stackIndex up and down the stack. + * When a new action is pushed onto the stack, the actions above the current action are removed from the stack. + * Actions pushed onto the stack are applied if they are not applied already. + * @todo implement error handling (e.g. memory errors) + * @author Maarten Gribnau + * @date March 31, 2001 + */ + +class ACT_ActionStack { +public: + /** + * Constructs an action stack. + */ + ACT_ActionStack(unsigned int maxStackDepth = 1); + + /** + * Destructs an action stack. + */ + virtual ~ACT_ActionStack(); + + /** + * Returns the current depth of the stack. + * @return the current stack depth. + */ + virtual unsigned int getStackDepth() const; + + /** + * Returns the current maximum depth of the stack. + * @return the maximum stack depth. + */ + virtual unsigned int getMaxStackDepth() const; + + /** + * Sets new maximum depth of the stack. + * @param maxStackDepth The new stack depth. + */ + virtual void setMaxStackDepth(unsigned int maxStackDepth); + + /** + * Pushes an action on the stack. + * If the action has not been applied yet, it will be applied here. + * This will increase the reference count of the action. + * If there is not enough capacity, the action at the bottom of the stack is removed (and its reference count decreased). + * @param action the action that is pushed onto the stack. + */ + virtual void push(ACT_Action& action); + + /** + * Returns pointer to the current undo item. + * @return The action scheduled for undo (0 if there is none). + */ + virtual ACT_Action* peekUndo(); + + /** + * Returns pointer to the current redo item. + * @return The action scheduled for redo (0 if there is none). + */ + virtual ACT_Action* peekRedo(); + + /** + * Flushes the action stack. + * All actions are removed from the stack and their reference counts decreased. + */ + virtual void flush(); + + /** + * Returns whether we can undo the current action. + * @return Indication of the possibility to undo. + */ + virtual bool canUndo() const; + + /** + * Undos the current action. + * This will move the current undo index down (if the stack depth allows it). + */ + virtual void undo(); + + /** + * Returns whether we can redo the current action. + * @return Indication of the possibility to redo. + */ + virtual bool canRedo() const; + + /** + * Redos the current action. + * This will move the action index up (if the stack depth allows it). + */ + virtual void redo(); + +protected: + /** + * Removes <i>numActions</i> actions from the back of the stack. + * @param numActions number of items to remove. + * @return the number of actions removed. + */ + virtual unsigned int popBack(unsigned int numActions = 1); + + /** + * Removes <i>numActions</i> actions from the front of the stack. + * @param numActions number of items to remove. + * @return the number of actions removed. + */ + virtual unsigned int popFront(unsigned int numActions = 1); + + /** + * Returns the index of the current undo action. + * @param index The index of the action. + * @return Indication as to whether the index is valid (==true). + */ + virtual bool getUndoIndex(unsigned int& index) const; + + /** + * Returns the index of the current redo action. + * @param index The index of the action. + * @return Indication as to whether the index is valid (==true). + */ + virtual bool getRedoIndex(unsigned int& index) const; + + /** The maximum depth of this stack. */ + unsigned int m_maxStackDepth; + /** The index of the current undo action in the stack. */ + unsigned int m_undoIndex; + /** Is the index of the current undo action in the stack valid? */ + bool m_undoIndexValid; + /** The index of the current redo action in the stack. */ + unsigned int m_redoIndex; + /** Is the index of the current redo action in the stack valid? */ + bool m_redoIndexValid; + /** The stack with actions. */ + deque<ACT_Action*> m_stack; +}; + + +#endif // _H_ACT_ACTIONSTACK
\ No newline at end of file diff --git a/intern/action/Makefile b/intern/action/Makefile new file mode 100644 index 00000000000..dd5301c034e --- /dev/null +++ b/intern/action/Makefile @@ -0,0 +1,52 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# action main makefile. +# + +include nan_definitions.mk + +LIBNAME = action +SOURCEDIR = intern/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = intern +TESTDIRS = test + +include nan_subdirs.mk + +install: all debug + @[ -d $(NAN_ACTION) ] || mkdir $(NAN_ACTION) + @[ -d $(NAN_ACTION)/include ] || mkdir $(NAN_ACTION)/include + @[ -d $(NAN_ACTION)/lib ] || mkdir $(NAN_ACTION)/lib + @[ -d $(NAN_ACTION)/lib/debug ] || mkdir $(NAN_ACTION)/lib/debug + cp -f $(DIR)/libaction.a $(NAN_ACTION)/lib/ + cp -f $(DIR)/debug/libaction.a $(NAN_ACTION)/lib/debug/ + cp -f *.h $(NAN_ACTION)/include/ + diff --git a/intern/action/doc/Doxyfile b/intern/action/doc/Doxyfile new file mode 100644 index 00000000000..2cc9de2d97c --- /dev/null +++ b/intern/action/doc/Doxyfile @@ -0,0 +1,746 @@ +# Doxyfile 1.2.4 + +# This file describes the settings to be used by doxygen for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. +PROJECT_NAME = foundation + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese, +# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian, +# Polish, Portuguese and Slovene. + +OUTPUT_LANGUAGE = English + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these class will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a class diagram (in Html and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. + +CLASS_DIAGRAMS = YES + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower case letters. If set to YES upper case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are adviced to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explict @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# reimplements. + +INHERIT_DOCS = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# The ENABLE_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../extern ../intern + + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +FILE_PATTERNS = *.h *.cpp *.c + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse. + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript and frames is required (for instance Netscape 4.0+ +# or Internet explorer 4.0+). + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimised for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using a WORD or other. +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assigments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. Warning: This feature +# is still experimental and very incomplete. + +GENERATE_XML = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = ../../generic/extern + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tagfiles. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to +# YES then doxygen will generate a graph for each documented file showing +# the direct and indirect include dependencies of the file with other +# documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to +# YES then doxygen will generate a graph for each documented header file showing +# the documented files that directly or indirectly include this file + +INCLUDED_BY_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO + +# The CGI_NAME tag should be the name of the CGI script that +# starts the search engine (doxysearch) with the correct parameters. +# A script with this name will be generated by doxygen. + +CGI_NAME = search.cgi + +# The CGI_URL tag should be the absolute URL to the directory where the +# cgi binaries are located. See the documentation of your http daemon for +# details. + +CGI_URL = + +# The DOC_URL tag should be the absolute URL to the directory where the +# documentation is located. If left blank the absolute path to the +# documentation, with file:// prepended to it, will be used. + +DOC_URL = + +# The DOC_ABSPATH tag should be the absolute path to the directory where the +# documentation is located. If left blank the directory on the local machine +# will be used. + +DOC_ABSPATH = + +# The BIN_ABSPATH tag must point to the directory where the doxysearch binary +# is installed. + +BIN_ABSPATH = c:\program files\doxygen\bin + +# The EXT_DOC_PATHS tag can be used to specify one or more paths to +# documentation generated for other projects. This allows doxysearch to search +# the documentation for these projects as well. + +EXT_DOC_PATHS = diff --git a/intern/action/intern/ACT_Action.cpp b/intern/action/intern/ACT_Action.cpp new file mode 100644 index 00000000000..ff3c01d146d --- /dev/null +++ b/intern/action/intern/ACT_Action.cpp @@ -0,0 +1,64 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date April, 25, 2001 + */ + +#include "ACT_Action.h" + + +ACT_Action::ACT_Action(const STR_String& name, bool applied) +: m_name(name), m_applied(applied) +{ +} + + +void ACT_Action::apply() +{ + if (!m_applied) { + doApply(); + m_applied = true; + } +} + + +void ACT_Action::undo() +{ + if (m_applied) { + doUndo(); + m_applied = false; + } +} diff --git a/intern/action/intern/ACT_ActionC-Api.cpp b/intern/action/intern/ACT_ActionC-Api.cpp new file mode 100644 index 00000000000..1c2defa333a --- /dev/null +++ b/intern/action/intern/ACT_ActionC-Api.cpp @@ -0,0 +1,130 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date April, 25, 2001 + */ + +#include "ACT_ActionC-Api.h" + +#include "ACT_ActionStack.h" +#include "ACT_CallbackAction.h" + + +ACT_ActionPtr ACT_ActionCreate( + char* name, + int isApplied, + ACT_ActionUserDataPtr data, + ACT_ActionApplyProcPtr applyProc, + ACT_ActionUndoProcPtr undoProc, + ACT_ActionDisposeProcPtr disposeProc) +{ + STR_String tmp (name); + ACT_CallbackAction* action = new ACT_CallbackAction(tmp, isApplied != 0, data, applyProc, undoProc, disposeProc); + return (ACT_ActionPtr) action; +} + + +char* ACT_ActionGetName(ACT_ActionPtr action) +{ + return action ? ((ACT_Action*)action)->getName() : 0; +} + + +ACT_ActionStackPtr ACT_ActionStackCreate(unsigned int stackSize) +{ + return ((ACT_ActionStackPtr) (new ACT_ActionStack (stackSize))); +} + + +void ACT_ActionStackDispose(ACT_ActionStackPtr stack) +{ + if (stack) { + delete (ACT_ActionStack*) stack; + } +} + + +unsigned int ACT_ActionStackGetStackDepth(ACT_ActionStackPtr stack) +{ + return stack ? ((ACT_ActionStack*)stack)->getStackDepth() : 0; +} + +unsigned int ACT_ActionStackGetMaxStackDepth(ACT_ActionStackPtr stack) +{ + return stack ? ((ACT_ActionStack*)stack)->getMaxStackDepth() : 0; +} + +void ACT_ActionStackSetMaxStackDepth(ACT_ActionStackPtr stack, unsigned int maxStackDepth) +{ + if (stack) { + ((ACT_ActionStack*)stack)->setMaxStackDepth(maxStackDepth); + } +} + +void ACT_ActionStackPush(ACT_ActionStackPtr stack, ACT_ActionPtr action) +{ + if (stack && action) { + ((ACT_ActionStack*)stack)->push(*((ACT_Action*)action)); + } +} + + +ACT_ActionStackPtr ACT_ActionStackPeekUndo(ACT_ActionStackPtr stack) +{ + return (ACT_ActionStackPtr) (stack ? ((ACT_ActionStack*)stack)->peekUndo() : 0); +} + + +ACT_ActionStackPtr ACT_ActionStackPeekRedo(ACT_ActionStackPtr stack) +{ + return (ACT_ActionStackPtr) (stack ? ((ACT_ActionStack*)stack)->peekRedo() : 0); +} + + +void ACT_ActionStackUndo(ACT_ActionStackPtr stack) +{ + if (stack) { + ((ACT_ActionStack*)stack)->undo(); + } +} + + +void ACT_ActionStackRedo(ACT_ActionStackPtr stack) +{ + if (stack) { + ((ACT_ActionStack*)stack)->redo(); + } +} diff --git a/intern/action/intern/ACT_ActionStack.cpp b/intern/action/intern/ACT_ActionStack.cpp new file mode 100644 index 00000000000..569babd95f2 --- /dev/null +++ b/intern/action/intern/ACT_ActionStack.cpp @@ -0,0 +1,241 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date March 31, 2001 + */ + +#include "ACT_ActionStack.h" + + +ACT_ActionStack::ACT_ActionStack(unsigned int maxStackDepth) + : m_maxStackDepth(maxStackDepth), + m_undoIndex(0), m_undoIndexValid(false), + m_redoIndex(0), m_redoIndexValid(false) +{ +} + + +ACT_ActionStack::~ACT_ActionStack() +{ + flush(); +} + + +unsigned int ACT_ActionStack::getStackDepth() const +{ + return m_stack.size(); +} + + +unsigned int ACT_ActionStack::getMaxStackDepth() const +{ + return m_maxStackDepth; +} + + +void ACT_ActionStack::setMaxStackDepth(unsigned int maxStackDepth) +{ + if (maxStackDepth != m_maxStackDepth) { + if (maxStackDepth) { + unsigned int size = m_stack.size(); + if (maxStackDepth < size) { + // New max stack size is smaller than current stack size, need to shrink stack + unsigned int numRemove = size - maxStackDepth; + if (m_undoIndex >= maxStackDepth) { + // Pop items from the front (throw away undo steps) + popFront(numRemove); + m_undoIndex -= numRemove; + m_redoIndex = m_undoIndex + 1; + m_redoIndexValid = m_redoIndexValid && (maxStackDepth > 1); + } + else { + // Pop items from the back (throw away redo steps) + popBack(numRemove); + m_redoIndexValid = m_redoIndexValid && (m_redoIndex < maxStackDepth); + } + } + } + else { + // New stack size is zero + flush(); + } + m_maxStackDepth = maxStackDepth; + } +} + + +void ACT_ActionStack::push(ACT_Action& action) +{ + if (m_maxStackDepth) { + unsigned int size = m_stack.size(); + if (m_redoIndexValid) { + // Remove items after the current action (throw away redo steps) + popBack(size - m_redoIndex); + } + else if (size >= m_maxStackDepth) { + // Remove items from the front (throw away undo steps) + popFront(m_maxStackDepth - size + 1); + } + + // Store the action + if (!action.getIsApplied()) { + action.apply(); + } + action.incRef(); + m_stack.push_back(&action); + + // Update action indices + m_redoIndex = m_stack.size(); + m_redoIndexValid = false; + m_undoIndex = m_redoIndex - 1; + m_undoIndexValid = true; + } +} + + +ACT_Action* ACT_ActionStack::peekUndo() +{ + unsigned int i; + return getUndoIndex(i) ? m_stack[i] : 0; +} + + +ACT_Action* ACT_ActionStack::peekRedo() +{ + unsigned int i; + return getRedoIndex(i) ? m_stack[i] : 0; +} + + +void ACT_ActionStack::flush() +{ + popBack(m_stack.size()); + m_undoIndex = 0; + m_undoIndexValid = false; + m_redoIndex = 0; + m_redoIndexValid = false; +} + + +bool ACT_ActionStack::canUndo() const +{ + unsigned int i; + return getUndoIndex(i); +} + + +void ACT_ActionStack::undo() +{ + ACT_Action* action = peekUndo(); + if (action) { + action->undo(); + + // Update action indices + m_redoIndex = m_undoIndex; + m_redoIndexValid = true; + if (m_undoIndex) { + m_undoIndex--; + } + else { + m_undoIndexValid = false; + } + } +} + + +bool ACT_ActionStack::canRedo() const +{ + unsigned int i; + return getRedoIndex(i); +} + + +void ACT_ActionStack::redo() +{ + ACT_Action* action = peekRedo(); + if (action) { + action->apply(); + + // Update action indices + m_undoIndex = m_redoIndex; + m_undoIndexValid = true; + m_redoIndex++; + m_redoIndexValid = m_redoIndex < m_stack.size(); + } +} + + +unsigned int ACT_ActionStack::popFront(unsigned int numActions) +{ + unsigned int numRemoved = 0; + + while (numActions-- && m_stack.size()) { + ACT_Action* action = m_stack[0]; + action->decRef(); + m_stack.pop_front(); + numRemoved++; + } + return numRemoved; +} + + +unsigned int ACT_ActionStack::popBack(unsigned int numActions) +{ + unsigned int numRemoved = 0; + unsigned int size; + + while (numActions-- && (size = m_stack.size())) { + ACT_Action* action = m_stack[size-1]; + action->decRef(); + m_stack.pop_back(); + numRemoved++; + } + return numRemoved; +} + + +bool ACT_ActionStack::getUndoIndex(unsigned int& i) const +{ + i = m_undoIndex; + return m_undoIndexValid; +} + + +bool ACT_ActionStack::getRedoIndex(unsigned int& i) const +{ + i = m_redoIndex; + return m_redoIndexValid; +} diff --git a/intern/action/intern/ACT_CallbackAction.h b/intern/action/intern/ACT_CallbackAction.h new file mode 100644 index 00000000000..e03e4048808 --- /dev/null +++ b/intern/action/intern/ACT_CallbackAction.h @@ -0,0 +1,124 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date June 17, 2001 + */ + +#ifndef _H_ACT_CALLBACK_ACTION_H +#define _H_ACT_CALLBACK_ACTION_H + +#include "ACT_Action.h" +#include "ACT_ActionC-Api.h" + + +/** + * An action implementation that uses callbacks for undo and redo. + * @author Maarten Gribnau + * @date June 17, 2001 + */ + +class ACT_CallbackAction : public ACT_Action { +public: + /** + * Constructs an action with the given name . + * @param name The name of the action. + * @param applied State of the action after creation. + * @param data Pointer to user data passed to the callbacks. + * @param applyProc Callback invoked for apply action. + * @param undoProc Callback invoked for undo action. + */ + ACT_CallbackAction( + STR_String& name, + bool applied, + ACT_ActionUserDataPtr data, + ACT_ActionApplyProcPtr applyProc, + ACT_ActionUndoProcPtr undoProc, + ACT_ActionDisposeProcPtr disposeProc) + : ACT_Action(name, applied), m_userData(data), m_applyProc(applyProc), m_undoProc(undoProc), m_disposeProc(disposeProc) + { + } + + /** + * Default destructor. + * Will call the dispose callback. + */ + virtual ~ACT_CallbackAction() + { + // Should assert + m_disposeProc((ACT_ActionPtr)this, m_userData); + } + + +protected: + /** + * Calls the appropriate callback. + */ + inline virtual void doApply(); + + /** + * Calls the appropriate callback. + */ + inline virtual void doUndo(); + + /** User data supplied at creation and passed to the callbacks. */ + ACT_ActionUserDataPtr m_userData; + + /** Callback invoked for apply action. */ + ACT_ActionApplyProcPtr m_applyProc; + + /** Callback invoked for undo action. */ + ACT_ActionApplyProcPtr m_undoProc; + + /** Callback invoked when the action is disposed. */ + ACT_ActionDisposeProcPtr m_disposeProc; +}; + + +inline void ACT_CallbackAction::doApply() +{ + // Should assert + m_applyProc((ACT_ActionPtr)this, m_userData); +} + + +inline void ACT_CallbackAction::doUndo() +{ + // Should assert + m_undoProc((ACT_ActionPtr)this, m_userData); +} + + +#endif // _H_ACT_CALLBACK_ACTION_H
\ No newline at end of file diff --git a/intern/action/intern/Makefile b/intern/action/intern/Makefile new file mode 100644 index 00000000000..29f82bb7c0d --- /dev/null +++ b/intern/action/intern/Makefile @@ -0,0 +1,42 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# action intern Makefile +# + +LIBNAME = action +DIR = $(OCGDIR)/intern/$(LIBNAME) + +include nan_compile.mk + +CPPFLAGS += -I.. +CPPFLAGS += -I$(NAN_STRING)/include +CPPFLAGS += -I$(NAN_MEMUTIL)/include + diff --git a/intern/action/make/msvc_6_0/action.dsp b/intern/action/make/msvc_6_0/action.dsp new file mode 100644 index 00000000000..3ea450b19a7 --- /dev/null +++ b/intern/action/make/msvc_6_0/action.dsp @@ -0,0 +1,128 @@ +# Microsoft Developer Studio Project File - Name="action" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=action - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "action.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "action.mak" CFG="action - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "action - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "action - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "action - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../../../../obj/windows/intern/action/" +# PROP Intermediate_Dir "../../../../../obj/windows/intern/action/" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../.." /I "../../../../lib/windows/memutil/include/" /I "../../../../lib/windows/string/include/" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "action - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../../../../obj/windows/intern/action/debug" +# PROP Intermediate_Dir "../../../../../obj/windows/intern/action/debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../.." /I "../../../../lib/windows/memutil/include/" /I "../../../../lib/windows/string/include/" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "action - Win32 Release" +# Name "action - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\intern\ACT_Action.cpp +# End Source File +# Begin Source File + +SOURCE="..\..\intern\ACT_ActionC-Api.cpp" +# End Source File +# Begin Source File + +SOURCE=..\..\intern\ACT_ActionStack.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Group "intern" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\intern\ACT_CallbackAction.h +# End Source File +# End Group +# Begin Group "extern" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\ACT_Action.h +# End Source File +# Begin Source File + +SOURCE="..\..\ACT_ActionC-Api.h" +# End Source File +# Begin Source File + +SOURCE=..\..\ACT_ActionStack.h +# End Source File +# End Group +# End Group +# End Target +# End Project diff --git a/intern/action/make/msvc_6_0/action.dsw b/intern/action/make/msvc_6_0/action.dsw new file mode 100644 index 00000000000..f93cbb896fd --- /dev/null +++ b/intern/action/make/msvc_6_0/action.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "action"=".\action.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/intern/action/test/action_c_test/ActionTest.c b/intern/action/test/action_c_test/ActionTest.c new file mode 100644 index 00000000000..a30163e0c3b --- /dev/null +++ b/intern/action/test/action_c_test/ActionTest.c @@ -0,0 +1,83 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date March 31, 2001 + */ + +#include "ACT_ActionC-Api.h" +#include "TestAction.h" + +int main(int argc, char *argv[]) +{ + ACT_ActionStackPtr stack = ACT_ActionStackCreate (3); + ACT_ActionPtr action = ACT_ActionCreate("action1", 0, 0, printApplied, printUndone, printDisposed); + ACT_ActionStackPush(stack, action); + MEM_RefCountedDecRef(action); + action = ACT_ActionCreate("action2", 0, 0, printApplied, printUndone, printDisposed); + ACT_ActionStackPush(stack, action); + MEM_RefCountedDecRef(action); + action = ACT_ActionCreate("action3", 0, 0, printApplied, printUndone, printDisposed); + ACT_ActionStackPush(stack, action); + MEM_RefCountedDecRef(action); + + ACT_ActionStackUndo(stack); + ACT_ActionStackUndo(stack); + ACT_ActionStackUndo(stack); + ACT_ActionStackRedo(stack); + ACT_ActionStackRedo(stack); + ACT_ActionStackRedo(stack); + + ACT_ActionStackSetMaxStackDepth(stack, 1); + ACT_ActionStackUndo(stack); + ACT_ActionStackRedo(stack); + ACT_ActionStackSetMaxStackDepth(stack, 5); + ACT_ActionStackUndo(stack); + ACT_ActionStackRedo(stack); + + action = ACT_ActionCreate("action4", 0, 0, printApplied, printUndone, printDisposed); + ACT_ActionStackPush(stack, action); + MEM_RefCountedDecRef(action); + ACT_ActionStackUndo(stack); + action = ACT_ActionCreate("action5", 0, 0, printApplied, printUndone, printDisposed); + ACT_ActionStackPush(stack, action); + MEM_RefCountedDecRef(action); + ACT_ActionStackUndo(stack); + ACT_ActionStackUndo(stack); + ACT_ActionStackRedo(stack); + ACT_ActionStackRedo(stack); + + return 0; +}
\ No newline at end of file diff --git a/intern/action/test/action_c_test/TestAction.c b/intern/action/test/action_c_test/TestAction.c new file mode 100644 index 00000000000..7b9739495d0 --- /dev/null +++ b/intern/action/test/action_c_test/TestAction.c @@ -0,0 +1,59 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date March 31, 2001 + */ + +#include <stdio.h> + +#include "TestAction.h" + + +void printApplied(ACT_ActionPtr action, ACT_ActionUserDataPtr userData) +{ + printf("%s: applied\n", ACT_ActionGetName(action)); +} + +void printUndone(ACT_ActionPtr action, ACT_ActionUserDataPtr userData) +{ + printf("%s: undone\n", ACT_ActionGetName(action)); +} + + +void printDisposed(ACT_ActionPtr action, ACT_ActionUserDataPtr userData) +{ + printf("%s: disposed\n", ACT_ActionGetName(action)); +} diff --git a/intern/action/test/action_c_test/TestAction.h b/intern/action/test/action_c_test/TestAction.h new file mode 100644 index 00000000000..7abf0be6919 --- /dev/null +++ b/intern/action/test/action_c_test/TestAction.h @@ -0,0 +1,50 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date March 31, 2001 + */ + +#ifndef _H_ACT_TESTACTION_C_H_ +#define _H_ACT_TESTACTION_C_H_ + +#include "ACT_ActionC-Api.h" + +void printApplied(ACT_ActionPtr action, ACT_ActionUserDataPtr userData); +void printUndone(ACT_ActionPtr action, ACT_ActionUserDataPtr userData); +void printDisposed(ACT_ActionPtr action, ACT_ActionUserDataPtr userData); + + +#endif // _H_ACT_TESTACTION_C_H_
\ No newline at end of file diff --git a/intern/action/test/action_c_test/make/msvc_6_0/action_c_test.dsp b/intern/action/test/action_c_test/make/msvc_6_0/action_c_test.dsp new file mode 100644 index 00000000000..807024f20be --- /dev/null +++ b/intern/action/test/action_c_test/make/msvc_6_0/action_c_test.dsp @@ -0,0 +1,109 @@ +# Microsoft Developer Studio Project File - Name="action_c_test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=action_c_test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "action_c_test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "action_c_test.mak" CFG="action_c_test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "action_c_test - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "action_c_test - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "action_c_test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../../../../../../obj/windows/intern/action/test" +# PROP Intermediate_Dir "../../../../../../../obj/windows/intern/action/test" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../.." /I "../../../../../../lib/windows/memutil/include/" /I "../../../../../../lib/windows/string/include/" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib string.lib memutil.lib /nologo /subsystem:console /machine:I386 /libpath:"../../../../../../lib/windows/memutil/lib" /libpath:"../../../../../../lib/windows/string/lib" + +!ELSEIF "$(CFG)" == "action_c_test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../../../../../../obj/windows/intern/action/test/debug" +# PROP Intermediate_Dir "../../../../../../../obj/windows/intern/action/test/debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../.." /I "../../../../../../lib/windows/memutil/include/" /I "../../../../../../lib/windows/string/include/" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib string.lib memutil.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"../../../../../../lib/windows/memutil/lib/debug" /libpath:"../../../../../../lib/windows/string/lib/debug" + +!ENDIF + +# Begin Target + +# Name "action_c_test - Win32 Release" +# Name "action_c_test - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\ActionTest.c +# End Source File +# Begin Source File + +SOURCE=..\..\TestAction.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\TestAction.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/intern/action/test/action_c_test/make/msvc_6_0/action_c_test.dsw b/intern/action/test/action_c_test/make/msvc_6_0/action_c_test.dsw new file mode 100644 index 00000000000..688f24e4d53 --- /dev/null +++ b/intern/action/test/action_c_test/make/msvc_6_0/action_c_test.dsw @@ -0,0 +1,44 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "action"="..\..\..\..\make\msvc_6_0\action.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "action_c_test"=".\action_c_test.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name action + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/intern/action/test/action_cpp_test/ActionTest.cpp b/intern/action/test/action_cpp_test/ActionTest.cpp new file mode 100644 index 00000000000..379cc41a5de --- /dev/null +++ b/intern/action/test/action_cpp_test/ActionTest.cpp @@ -0,0 +1,83 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date March 31, 2001 + */ + +#include "ACT_ActionStack.h" +#include "TestAction.h" + +int main() +{ + ACT_ActionStack testStack (3); + TestAction* testAction = new TestAction (STR_String("action1")); + testStack.push(*testAction); + testAction->decRef(); + testAction = new TestAction (STR_String("action2")); + testStack.push(*testAction); + testAction->decRef(); + testAction = new TestAction (STR_String("action3")); + testStack.push(*testAction); + testAction->decRef(); + + testStack.undo(); + testStack.undo(); + testStack.undo(); + testStack.redo(); + testStack.redo(); + testStack.redo(); + + testStack.setMaxStackDepth(1); + testStack.undo(); + testStack.redo(); + testStack.setMaxStackDepth(5); + testStack.undo(); + testStack.redo(); + + testAction = new TestAction (STR_String("action4")); + testStack.push(*testAction); + testAction->decRef(); + testStack.undo(); + testAction = new TestAction (STR_String("action5")); + testStack.push(*testAction); + testAction->decRef(); + testStack.undo(); + testStack.undo(); + testStack.redo(); + testStack.redo(); + + return 0; +}
\ No newline at end of file diff --git a/intern/action/test/action_cpp_test/TestAction.h b/intern/action/test/action_cpp_test/TestAction.h new file mode 100644 index 00000000000..83bc8fb1750 --- /dev/null +++ b/intern/action/test/action_cpp_test/TestAction.h @@ -0,0 +1,57 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date March 31, 2001 + */ + +#ifndef _H_ACT_TESTACTION +#define _H_ACT_TESTACTION + +#include "ACT_Action.h" + +#include <iostream> + +class TestAction : public ACT_Action +{ +public: + TestAction(const STR_String& name) : ACT_Action(name) {} + virtual ~TestAction() { cout << m_name.Ptr() << ": deleted\n"; } +protected: + virtual void doApply() { cout << m_name.Ptr() << ": applied\n"; } + virtual void doUndo() { cout << m_name.Ptr() << ": undone\n"; } +}; + +#endif // _H_ACT_TESTACTION
\ No newline at end of file diff --git a/intern/action/test/action_cpp_test/make/msvc_6_0/action_cpp_test.dsp b/intern/action/test/action_cpp_test/make/msvc_6_0/action_cpp_test.dsp new file mode 100644 index 00000000000..bc0c40b6d36 --- /dev/null +++ b/intern/action/test/action_cpp_test/make/msvc_6_0/action_cpp_test.dsp @@ -0,0 +1,105 @@ +# Microsoft Developer Studio Project File - Name="action_cpp_test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=action_cpp_test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "action_cpp_test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "action_cpp_test.mak" CFG="action_cpp_test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "action_cpp_test - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "action_cpp_test - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "action_cpp_test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../../../../../../obj/windows/intern/action/test" +# PROP Intermediate_Dir "../../../../../../../obj/windows/intern/action/test" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../.." /I "../../../../../../lib/windows/memutil/include/" /I "../../../../../../lib/windows/string/include/" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib string.lib memutil.lib /nologo /subsystem:console /machine:I386 /libpath:"../../../../../../lib/windows/memutil/lib" /libpath:"../../../../../../lib/windows/string/lib" + +!ELSEIF "$(CFG)" == "action_cpp_test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../../../../../../obj/windows/intern/action/test/debug" +# PROP Intermediate_Dir "../../../../../../../obj/windows/intern/action/test/debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../.." /I "../../../../../../lib/windows/memutil/include/" /I "../../../../../../lib/windows/string/include/" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib string.lib memutil.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"../../../../../../lib/windows/memutil/lib/debug" /libpath:"../../../../../../lib/windows/string/lib/debug" + +!ENDIF + +# Begin Target + +# Name "action_cpp_test - Win32 Release" +# Name "action_cpp_test - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\ActionTest.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\TestAction.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/intern/action/test/action_cpp_test/make/msvc_6_0/action_cpp_test.dsw b/intern/action/test/action_cpp_test/make/msvc_6_0/action_cpp_test.dsw new file mode 100644 index 00000000000..0a9d7374379 --- /dev/null +++ b/intern/action/test/action_cpp_test/make/msvc_6_0/action_cpp_test.dsw @@ -0,0 +1,44 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "action"="..\..\..\..\make\msvc_6_0\action.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "action_cpp_test"=".\action_cpp_test.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name action + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/intern/bmfont/BMF_Api.h b/intern/bmfont/BMF_Api.h new file mode 100644 index 00000000000..4d51bd6e0a3 --- /dev/null +++ b/intern/bmfont/BMF_Api.h @@ -0,0 +1,129 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * + * API of the OpenGL bitmap font library. + * Currently draws fonts using the glBitmap routine. + * This implies that drawing speed is heavyly dependant on + * the 2D capabilities of the graphics card. + */ + +#ifndef __BMF_API_H +#define __BMF_API_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "BMF_Fonts.h" + +/** + * Returns the font for a given font type. + * @param font The font to retrieve. + * @return The font (or nil if not found). + */ +BMF_Font* BMF_GetFont(BMF_FontType font); + +/** + * Draws a character at the current raster position. + * @param font The font to use. + * @param c The character to draw. + * @return Indication of success (0 == error). + */ +int BMF_DrawCharacter(BMF_Font* font, char c); + +/** + * Draws a string at the current raster position. + * @param font The font to use. + * @param str The string to draw. + * @return Indication of success (0 == error). + */ +int BMF_DrawString(BMF_Font* font, char* str); + +/** + * Returns the width of a character in pixels. + * @param font The font to use. + * @param c The character. + * @return The length. + */ +int BMF_GetCharacterWidth(BMF_Font* font, char c); + +/** + * Returns the width of a string of characters. + * @param font The font to use. + * @param str The string. + * @return The length. + */ +int BMF_GetStringWidth(BMF_Font* font, char* str); + +/** + * Returns the bounding box of the font. The width and + * height represent the bounding box of the union of + * all glyps. The minimum and maximum values of the + * box represent the extent of the font and its positioning + * about the origin. + */ +void BMF_GetBoundingBox(BMF_Font* font, int *xmin_r, int *ymin_r, int *xmax_r, int *ymax_r); + +/** + * Convert the given @a font to a texture, and return the GL texture + * ID of the texture. If the texture ID is bound, text can + * be drawn using the texture by calling DrawStringTexture. + * + * @param font The font to create the texture from. + * @return The GL texture ID of the new texture, or -1 if unable + * to create. + */ +int BMF_GetFontTexture(BMF_Font* font); + +/** + * Draw the given @a str at the point @a x, @a y, @a z, using + * texture coordinates. This assumes that an appropriate texture + * has been bound, see BMF_BitmapFont::GetTexture(). The string + * is drawn along the positive X axis. + * + * @param font The font to draw with. + * @param string The c-string to draw. + * @param x The x coordinate to start drawing at. + * @param y The y coordinate to start drawing at. + * @param z The z coordinate to start drawing at. + */ +void BMF_DrawStringTexture(BMF_Font* font, char* string, float x, float y, float z); + +#ifdef __cplusplus +} +#endif + +#endif /* __BMF_API_H */ diff --git a/intern/bmfont/BMF_Fonts.h b/intern/bmfont/BMF_Fonts.h new file mode 100644 index 00000000000..7848031805f --- /dev/null +++ b/intern/bmfont/BMF_Fonts.h @@ -0,0 +1,76 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * Defines the names of the fonts in the library. + */ + +#ifndef __BMF_FONTS_H +#define __BMF_FONTS_H + +#include "BMF_Settings.h" + +typedef enum +{ + BMF_kHelvetica10 = 0, +#if BMF_INCLUDE_HELV12 + BMF_kHelvetica12, +#endif +#if BMF_INCLUDE_HELVB8 + BMF_kHelveticaBold8, +#endif +#if BMF_INCLUDE_HELVB10 + BMF_kHelveticaBold10, +#endif +#if BMF_INCLUDE_HELVB12 + BMF_kHelveticaBold12, +#endif +#if BMF_INCLUDE_HELVB14 + BMF_kHelveticaBold14, +#endif +#if BMF_INCLUDE_SCR12 + BMF_kScreen12, +#endif +#if BMF_INCLUDE_SCR14 + BMF_kScreen14, +#endif +#if BMF_INCLUDE_SCR15 + BMF_kScreen15, +#endif + BMF_kNumFonts +} BMF_FontType; + +typedef struct BMF_Font BMF_Font; + +#endif /* __BMF_FONTS_H */ diff --git a/intern/bmfont/BMF_Settings.h b/intern/bmfont/BMF_Settings.h new file mode 100644 index 00000000000..24ee13ad531 --- /dev/null +++ b/intern/bmfont/BMF_Settings.h @@ -0,0 +1,69 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * Allows you to determine which fonts to include in the library. + */ + +#ifndef __BMF_SETTINGS_H +#define __BMF_SETTINGS_H + +/* This font is included always */ +#define BMF_INCLUDE_HELV10 1 + +#ifndef BMF_MINIMAL + +/* These fonts are included with the minimal setting defined */ +#define BMF_INCLUDE_HELV12 1 +#define BMF_INCLUDE_HELVB8 1 +#define BMF_INCLUDE_HELVB10 1 +#define BMF_INCLUDE_HELVB12 1 +#define BMF_INCLUDE_HELVB14 1 +#define BMF_INCLUDE_SCR12 1 +#define BMF_INCLUDE_SCR14 1 +#define BMF_INCLUDE_SCR15 1 + +#else /* BMF_MINIMAL */ +#define BMF_INCLUDE_HELV12 0 +#define BMF_INCLUDE_HELVB8 0 +#define BMF_INCLUDE_HELVB10 0 +#define BMF_INCLUDE_HELVB12 0 +#define BMF_INCLUDE_HELVB14 0 +#define BMF_INCLUDE_SCR12 0 +#define BMF_INCLUDE_SCR14 0 +#define BMF_INCLUDE_SCR15 0 + +#endif /* BMF_MINIMAL */ + +#endif /* __BMF_SETTINGS_H */ diff --git a/intern/bmfont/Makefile b/intern/bmfont/Makefile new file mode 100644 index 00000000000..0da2a844236 --- /dev/null +++ b/intern/bmfont/Makefile @@ -0,0 +1,52 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# bmfont main makefile. +# + +include nan_definitions.mk + +LIBNAME = bmfont +SOURCEDIR = intern/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = intern +#not ready yet TESTDIRS = test + +include nan_subdirs.mk + +install: all debug + @[ -d $(NAN_BMFONT) ] || mkdir $(NAN_BMFONT) + @[ -d $(NAN_BMFONT)/include ] || mkdir $(NAN_BMFONT)/include + @[ -d $(NAN_BMFONT)/lib ] || mkdir $(NAN_BMFONT)/lib + @[ -d $(NAN_BMFONT)/lib/debug ] || mkdir $(NAN_BMFONT)/lib/debug + cp -f $(DIR)/libbmfont.a $(NAN_BMFONT)/lib/ + cp -f $(DIR)/debug/libbmfont.a $(NAN_BMFONT)/lib/debug/ + cp -f *.h $(NAN_BMFONT)/include/ + diff --git a/intern/bmfont/intern/BMF_Api.cpp b/intern/bmfont/intern/BMF_Api.cpp new file mode 100644 index 00000000000..08e54f13174 --- /dev/null +++ b/intern/bmfont/intern/BMF_Api.cpp @@ -0,0 +1,164 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * + * Implementation of the API of the OpenGL bitmap font library. + */ + +#include "BMF_Api.h" + +#include "BMF_BitmapFont.h" + + +#if BMF_INCLUDE_HELV10 +extern BMF_FontData BMF_font_helv10; +static BMF_BitmapFont bmfHelv10(&BMF_font_helv10); +#endif // BMF_INCLUDE_HELV10 +#if BMF_INCLUDE_HELV12 +extern BMF_FontData BMF_font_helv12; +static BMF_BitmapFont bmfHelv12(&BMF_font_helv12); +#endif // BMF_INCLUDE_HELV12 +#if BMF_INCLUDE_HELVB8 +extern BMF_FontData BMF_font_helvb8; +static BMF_BitmapFont bmfHelvb8(&BMF_font_helvb8); +#endif // BMF_INCLUDE_HELVB8 +#if BMF_INCLUDE_HELVB10 +extern BMF_FontData BMF_font_helvb10; +static BMF_BitmapFont bmfHelvb10(&BMF_font_helvb10); +#endif // BMF_INCLUDE_HELVB10 +#if BMF_INCLUDE_HELVB12 +extern BMF_FontData BMF_font_helvb12; +static BMF_BitmapFont bmfHelvb12(&BMF_font_helvb12); +#endif // BMF_INCLUDE_HELVB12 +#if BMF_INCLUDE_HELVB14 +extern BMF_FontData BMF_font_helvb14; +static BMF_BitmapFont bmfHelvb14(&BMF_font_helvb14); +#endif // BMF_INCLUDE_HELVB14 +#if BMF_INCLUDE_SCR12 +extern BMF_FontData BMF_font_scr12; +static BMF_BitmapFont bmfScreen12(&BMF_font_scr12); +#endif // BMF_INCLUDE_SCR12 +#if BMF_INCLUDE_SCR14 +extern BMF_FontData BMF_font_scr14; +static BMF_BitmapFont bmfScreen14(&BMF_font_scr14); +#endif // BMF_INCLUDE_SCR14 +#if BMF_INCLUDE_SCR15 +extern BMF_FontData BMF_font_scr15; +static BMF_BitmapFont bmfScreen15(&BMF_font_scr15); +#endif // BMF_INCLUDE_SCR15 + + +BMF_Font* BMF_GetFont(BMF_FontType font) +{ + switch (font) + { +#if BMF_INCLUDE_HELV10 + case BMF_kHelvetica10: return (BMF_Font*) &bmfHelv10; +#endif // BMF_INCLUDE_HELV10 +#if BMF_INCLUDE_HELV12 + case BMF_kHelvetica12: return (BMF_Font*) &bmfHelv12; +#endif // BMF_INCLUDE_HELV12 +#if BMF_INCLUDE_HELVB8 + case BMF_kHelveticaBold8: return (BMF_Font*) &bmfHelvb8; +#endif // BMF_INCLUDE_HELVB8 +#if BMF_INCLUDE_HELVB10 + case BMF_kHelveticaBold10: return (BMF_Font*) &bmfHelvb10; +#endif // BMF_INCLUDE_HELVB10 +#if BMF_INCLUDE_HELVB12 + case BMF_kHelveticaBold12: return (BMF_Font*) &bmfHelvb12; +#endif // BMF_INCLUDE_HELVB12 +#if BMF_INCLUDE_HELVB14 + case BMF_kHelveticaBold14: return (BMF_Font*) &bmfHelvb14; +#endif // BMF_INCLUDE_HELVB12 +#if BMF_INCLUDE_SCR12 + case BMF_kScreen12: return (BMF_Font*) &bmfScreen12; +#endif // BMF_INCLUDE_SCR12 +#if BMF_INCLUDE_SCR14 + case BMF_kScreen14: return (BMF_Font*) &bmfScreen14; +#endif // BMF_INCLUDE_SCR14 +#if BMF_INCLUDE_SCR15 + case BMF_kScreen15: return (BMF_Font*) &bmfScreen15; +#endif // BMF_INCLUDE_SCR15 + default: + break; + } + return 0; +} + + +int BMF_DrawCharacter(BMF_Font* font, char c) +{ + char str[2] = {c, '\0'}; + return BMF_DrawString(font, str); +} + + +int BMF_DrawString(BMF_Font* font, char* str) +{ + if (!font) return 0; + ((BMF_BitmapFont*)font)->DrawString(str); + return 1; +} + + +int BMF_GetCharacterWidth(BMF_Font* font, char c) +{ + char str[2] = {c, '\0'}; + return BMF_GetStringWidth(font, str); +} + + +int BMF_GetStringWidth(BMF_Font* font, char* str) +{ + if (!font) return 0; + return ((BMF_BitmapFont*)font)->GetStringWidth(str); +} + + +void BMF_GetBoundingBox(BMF_Font* font, int *xmin_r, int *ymin_r, int *xmax_r, int *ymax_r) +{ + if (!font) return; + ((BMF_BitmapFont*)font)->GetBoundingBox(*xmin_r, *ymin_r, *xmax_r, *ymax_r); +} + +int BMF_GetFontTexture(BMF_Font* font) { + if (!font) return -1; + return ((BMF_BitmapFont*)font)->GetTexture(); +} + +void BMF_DrawStringTexture(BMF_Font* font, char *string, float x, float y, float z) { + if (!font) return; + ((BMF_BitmapFont*)font)->DrawStringTexture(string, x, y, z); +} diff --git a/intern/bmfont/intern/BMF_BitmapFont.cpp b/intern/bmfont/intern/BMF_BitmapFont.cpp new file mode 100644 index 00000000000..bd3fe0cb899 --- /dev/null +++ b/intern/bmfont/intern/BMF_BitmapFont.cpp @@ -0,0 +1,207 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + */ + +#include <string.h> + +#if defined(WIN32) || defined(__APPLE__) + #ifdef WIN32 + #if !defined(__CYGWIN32__) + #pragma warning(disable:4244) + #endif /* __CYGWIN32__ */ + #include <windows.h> + #include <GL/gl.h> + #else // WIN32 + // __APPLE__ is defined + #include <AGL/gl.h> + #endif // WIN32 +#else // defined(WIN32) || defined(__APPLE__) + #include <GL/gl.h> +#endif // defined(WIN32) || defined(__APPLE__) + +#include "BMF_BitmapFont.h" + + +BMF_BitmapFont::BMF_BitmapFont(BMF_FontData* fontData) +: m_fontData(fontData) +{ +} + + +BMF_BitmapFont::~BMF_BitmapFont(void) +{ +} + + +void BMF_BitmapFont::DrawString(char* str) +{ + GLint alignment; + unsigned char c; + + glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + while (c = (unsigned char) *str++) { + BMF_CharData & cd = m_fontData->chars[c]; + + if (cd.data_offset==-1) { + GLubyte nullBitmap = 0; + + glBitmap(1, 1, 0, 0, cd.advance, 0, &nullBitmap); + } else { + GLubyte *bitmap = &m_fontData->bitmap_data[cd.data_offset]; + + glBitmap(cd.width, cd.height, cd.xorig, cd.yorig, cd.advance, 0, bitmap); + } + } + + glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); +} + + +int BMF_BitmapFont::GetStringWidth(char* str) +{ + unsigned char c; + int length = 0; + + while (c = (unsigned char) *str++) { + length += m_fontData->chars[c].advance; + } + + return length; +} + +void BMF_BitmapFont::GetBoundingBox(int & xMin, int & yMin, int & xMax, int & yMax) +{ + xMin = m_fontData->xmin; + yMin = m_fontData->ymin; + xMax = m_fontData->xmax; + yMax = m_fontData->ymax; +} + +int BMF_BitmapFont::GetTexture() +{ + int fWidth = m_fontData->xmax - m_fontData->xmin; + int fHeight = m_fontData->ymax - m_fontData->ymin; + + if (fWidth>=16 || fHeight>=16) { + return -1; + } + + int cRows = 16, cCols = 16; + int cWidth = 16, cHeight = 16; + int iWidth = cCols*cWidth; + int iHeight = cRows*cHeight; + GLubyte *img = new GLubyte [iHeight*iWidth]; + GLuint texId; + + int baseLine = -(m_fontData->ymin); + + memset(img, 0, iHeight*iWidth); + for (int i = 0; i<256; i++) { + BMF_CharData & cd = m_fontData->chars[i]; + + if (cd.data_offset != -1) { + int cellX = i%16; + int cellY = i/16; + + for (int y = 0; y<cd.height; y++) { + GLubyte* imgRow = &img[(cellY*cHeight + y + baseLine - cd.yorig)*iWidth]; + GLubyte* chrRow = &m_fontData->bitmap_data[cd.data_offset + ((cd.width+7)/8)*y]; + + for (int x = 0; x<cd.width; x++) { + GLubyte* imgPxl = &imgRow[(cellX*cWidth + x - cd.xorig)]; + int byteIdx = x/8; + int bitIdx = 7 - (x%8); + + if (chrRow[byteIdx]&(1<<bitIdx)) { + imgPxl[0] = 255; + } + } + } + } + } + + glGenTextures(1, &texId); + + glBindTexture(GL_TEXTURE_2D, texId); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA4, iWidth, iHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, img); + if (glGetError()) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE4_ALPHA4, iWidth, iHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, img); + } + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + delete [] img; + + return texId; +} + +void BMF_BitmapFont::DrawStringTexture(char *str, float x, float y, float z) +{ + unsigned char c; + float pos = 0; + + int baseLine = -(m_fontData->ymin); + + glBegin(GL_QUADS); + while (c = (unsigned char) *str++) { + BMF_CharData & cd = m_fontData->chars[c]; + + if (cd.data_offset != -1) { + float cellX = (c%16)/16.0; + float cellY = (c/16)/16.0; + + glTexCoord2f(cellX + 1.0/16.0, cellY); + glVertex3f(x + pos + 16.0, -baseLine + y + 0.0, z); + + glTexCoord2f(cellX + 1.0/16.0, cellY + 1.0/16.0); + glVertex3f(x + pos + 16.0, -baseLine + y + 16.0, z); + + glTexCoord2f(cellX, cellY + 1.0/16.0); + glVertex3f(x + pos + 0.0, -baseLine + y + 16.0, z); + + glTexCoord2f(cellX, cellY); + glVertex3f(x + pos + 0.0, -baseLine + y + 0.0, z); + } + + pos += cd.advance; + } + glEnd(); +} diff --git a/intern/bmfont/intern/BMF_BitmapFont.h b/intern/bmfont/intern/BMF_BitmapFont.h new file mode 100644 index 00000000000..f203cb374ae --- /dev/null +++ b/intern/bmfont/intern/BMF_BitmapFont.h @@ -0,0 +1,109 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + */ + +#ifndef __BMF_BITMAP_FONT_H +#define __BMF_BITMAP_FONT_H + +#include "BMF_FontData.h" + +/** + * Base class for OpenGL bitmap fonts. + */ +class BMF_BitmapFont +{ +public: + /** + * Default constructor. + */ + BMF_BitmapFont(BMF_FontData* fontData); + + /** + * Destructor. + */ + virtual ~BMF_BitmapFont(void); + + /** + * Draws a string at the current raster position. + * @param str The string to draw. + */ + void DrawString(char* str); + + /** + * Draws a string at the current raster position. + * @param str The string to draw. + * @return The width of the string. + */ + int GetStringWidth(char* str); + + /** + * Returns the bounding box of the font. The width and + * height represent the bounding box of the union of + * all glyps. The minimum and maximum values of the + * box represent the extent of the font and its positioning + * about the origin. + */ + void GetBoundingBox(int & xMin, int & yMin, int & xMax, int & yMax); + + /** + * Convert the font to a texture, and return the GL texture + * ID of the texture. If the texture ID is bound, text can + * be drawn using the texture by calling DrawStringTexture. + * + * @return The GL texture ID of the new texture, or -1 if unable + * to create. + */ + int GetTexture(); + + /** + * Draw the given @a string at the point @a x, @a y, @a z, using + * texture coordinates. This assumes that an appropriate texture + * has been bound, see BMF_BitmapFont::GetTexture(). The string + * is drawn along the positive X axis. + * + * @param string The c-string to draw. + * @param x The x coordinate to start drawing at. + * @param y The y coordinate to start drawing at. + * @param z The z coordinate to start drawing at. + */ + void DrawStringTexture(char* string, float x, float y, float z); + +protected: + /** Pointer to the font data. */ + BMF_FontData* m_fontData; +}; + +#endif // __BMF_BITMAP_FONT_H diff --git a/intern/bmfont/intern/BMF_FontData.h b/intern/bmfont/intern/BMF_FontData.h new file mode 100644 index 00000000000..b1e1a08f92a --- /dev/null +++ b/intern/bmfont/intern/BMF_FontData.h @@ -0,0 +1,57 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + */ + +#ifndef __BMF_FONTDATA_H__ +#define __BMF_FONTDATA_H__ + +typedef struct { + signed char width, height; + signed char xorig, yorig; + signed char advance; + + short data_offset; +} BMF_CharData; + +typedef struct { + int xmin, ymin; + int xmax, ymax; + + BMF_CharData chars[256]; + unsigned char* bitmap_data; +} BMF_FontData; + +#endif diff --git a/intern/bmfont/intern/BMF_font_helv10.cpp b/intern/bmfont/intern/BMF_font_helv10.cpp new file mode 100644 index 00000000000..b69796948c3 --- /dev/null +++ b/intern/bmfont/intern/BMF_font_helv10.cpp @@ -0,0 +1,493 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BMF_FontData.h" + +#include "BMF_Settings.h" + +#if BMF_INCLUDE_HELV10 + +static unsigned char bitmap_data[]= { + 0x80,0x00,0x80,0x80,0x80,0x80,0x80,0x80, + 0xa0,0xa0,0x50,0x50,0xf8,0x28,0x7c,0x28, + 0x28,0x20,0x70,0xa8,0x28,0x70,0xa0,0xa8, + 0x70,0x20,0x26,0x29,0x16,0x10,0x08,0x68, + 0x94,0x64,0x64,0x98,0x98,0xa4,0x60,0x50, + 0x50,0x20,0x80,0x40,0x40,0x20,0x40,0x40, + 0x80,0x80,0x80,0x80,0x40,0x40,0x20,0x80, + 0x40,0x40,0x20,0x20,0x20,0x20,0x40,0x40, + 0x80,0xa0,0x40,0xa0,0x20,0x20,0xf8,0x20, + 0x20,0x80,0x40,0x40,0xf8,0x80,0x80,0x80, + 0x40,0x40,0x40,0x40,0x20,0x20,0x70,0x88, + 0x88,0x88,0x88,0x88,0x88,0x70,0x40,0x40, + 0x40,0x40,0x40,0x40,0xc0,0x40,0xf8,0x80, + 0x40,0x30,0x08,0x08,0x88,0x70,0x70,0x88, + 0x08,0x08,0x30,0x08,0x88,0x70,0x10,0x10, + 0xf8,0x90,0x50,0x50,0x30,0x10,0x70,0x88, + 0x08,0x08,0xf0,0x80,0x80,0xf8,0x70,0x88, + 0x88,0xc8,0xb0,0x80,0x88,0x70,0x40,0x40, + 0x20,0x20,0x10,0x10,0x08,0xf8,0x70,0x88, + 0x88,0x88,0x70,0x88,0x88,0x70,0x70,0x88, + 0x08,0x68,0x98,0x88,0x88,0x70,0x80,0x00, + 0x00,0x00,0x00,0x80,0x80,0x40,0x40,0x00, + 0x00,0x00,0x00,0x40,0x20,0x40,0x80,0x40, + 0x20,0xf0,0x00,0xf0,0x80,0x40,0x20,0x40, + 0x80,0x40,0x00,0x40,0x40,0x20,0x10,0x90, + 0x60,0x3e,0x00,0x40,0x00,0x9b,0x00,0xa4, + 0x80,0xa4,0x80,0xa2,0x40,0x92,0x40,0x4d, + 0x40,0x20,0x80,0x1f,0x00,0x82,0x82,0x7c, + 0x44,0x28,0x28,0x10,0x10,0xf0,0x88,0x88, + 0x88,0xf0,0x88,0x88,0xf0,0x78,0x84,0x80, + 0x80,0x80,0x80,0x84,0x78,0xf0,0x88,0x84, + 0x84,0x84,0x84,0x88,0xf0,0xf8,0x80,0x80, + 0x80,0xf8,0x80,0x80,0xf8,0x80,0x80,0x80, + 0x80,0xf0,0x80,0x80,0xf8,0x74,0x8c,0x84, + 0x8c,0x80,0x80,0x84,0x78,0x84,0x84,0x84, + 0x84,0xfc,0x84,0x84,0x84,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x60,0x90,0x10, + 0x10,0x10,0x10,0x10,0x10,0x88,0x88,0x90, + 0x90,0xe0,0xa0,0x90,0x88,0xf0,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x92,0x92,0x92, + 0xaa,0xaa,0xc6,0xc6,0x82,0x8c,0x8c,0x94, + 0x94,0xa4,0xa4,0xc4,0xc4,0x78,0x84,0x84, + 0x84,0x84,0x84,0x84,0x78,0x80,0x80,0x80, + 0x80,0xf0,0x88,0x88,0xf0,0x02,0x7c,0x8c, + 0x94,0x84,0x84,0x84,0x84,0x78,0x88,0x88, + 0x88,0x88,0xf0,0x88,0x88,0xf0,0x70,0x88, + 0x88,0x08,0x70,0x80,0x88,0x70,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0xf8,0x78,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x10,0x28, + 0x28,0x44,0x44,0x44,0x82,0x82,0x22,0x00, + 0x22,0x00,0x22,0x00,0x55,0x00,0x49,0x00, + 0x49,0x00,0x88,0x80,0x88,0x80,0x88,0x88, + 0x50,0x50,0x20,0x50,0x88,0x88,0x10,0x10, + 0x10,0x28,0x28,0x44,0x44,0x82,0xf8,0x80, + 0x40,0x20,0x20,0x10,0x08,0xf8,0xc0,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xc0, + 0x20,0x20,0x40,0x40,0x40,0x40,0x80,0x80, + 0xc0,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0xc0,0x88,0x50,0x50,0x20,0x20,0xfc, + 0x80,0x80,0x40,0x68,0x90,0x90,0x70,0x10, + 0xe0,0xb0,0xc8,0x88,0x88,0xc8,0xb0,0x80, + 0x80,0x60,0x90,0x80,0x80,0x90,0x60,0x68, + 0x98,0x88,0x88,0x98,0x68,0x08,0x08,0x60, + 0x90,0x80,0xf0,0x90,0x60,0x40,0x40,0x40, + 0x40,0x40,0xe0,0x40,0x30,0x70,0x08,0x68, + 0x98,0x88,0x88,0x98,0x68,0x88,0x88,0x88, + 0x88,0xc8,0xb0,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x00,0x80,0x90,0x90, + 0xa0,0xc0,0xa0,0x90,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x92,0x92, + 0x92,0x92,0x92,0xec,0x88,0x88,0x88,0x88, + 0xc8,0xb0,0x70,0x88,0x88,0x88,0x88,0x70, + 0x80,0x80,0xb0,0xc8,0x88,0x88,0xc8,0xb0, + 0x08,0x08,0x68,0x98,0x88,0x88,0x98,0x68, + 0x80,0x80,0x80,0x80,0xc0,0xa0,0x60,0x90, + 0x10,0x60,0x90,0x60,0x60,0x40,0x40,0x40, + 0x40,0xe0,0x40,0x40,0x70,0x90,0x90,0x90, + 0x90,0x90,0x20,0x20,0x50,0x50,0x88,0x88, + 0x28,0x28,0x54,0x54,0x92,0x92,0x88,0x88, + 0x50,0x20,0x50,0x88,0x80,0x40,0x40,0x60, + 0xa0,0xa0,0x90,0x90,0xf0,0x80,0x40,0x20, + 0x10,0xf0,0x20,0x40,0x40,0x40,0x40,0x80, + 0x40,0x40,0x40,0x20,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40, + 0x40,0x40,0x40,0x20,0x40,0x40,0x40,0x80, + 0x98,0x64,0x80,0x80,0x80,0x80,0x80,0x80, + 0x00,0x80,0x40,0x70,0xa8,0xa0,0xa0,0xa8, + 0x70,0x10,0xb0,0x48,0x40,0x40,0xe0,0x40, + 0x48,0x30,0x90,0x60,0x90,0x90,0x60,0x90, + 0x20,0xf8,0x20,0xf8,0x50,0x50,0x88,0x88, + 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x80, + 0x80,0x80,0x70,0x88,0x18,0x70,0xc8,0x98, + 0x70,0xc0,0x88,0x70,0xa0,0x38,0x44,0x9a, + 0xa2,0x9a,0x44,0x38,0xe0,0x00,0xa0,0x20, + 0xe0,0x28,0x50,0xa0,0x50,0x28,0x08,0x08, + 0xf8,0xe0,0x38,0x44,0xaa,0xb2,0xba,0x44, + 0x38,0xe0,0x60,0x90,0x90,0x60,0xf8,0x00, + 0x20,0x20,0xf8,0x20,0x20,0xe0,0x40,0xa0, + 0x60,0xc0,0x20,0x40,0xe0,0x80,0x40,0x80, + 0x80,0xf0,0x90,0x90,0x90,0x90,0x90,0x28, + 0x28,0x28,0x28,0x28,0x68,0xe8,0xe8,0xe8, + 0x7c,0xc0,0xc0,0x40,0x40,0x40,0xc0,0x40, + 0xe0,0x00,0xe0,0xa0,0xe0,0xa0,0x50,0x28, + 0x50,0xa0,0x21,0x00,0x17,0x80,0x13,0x00, + 0x09,0x00,0x48,0x00,0x44,0x00,0xc4,0x00, + 0x42,0x00,0x27,0x12,0x15,0x0b,0x48,0x44, + 0xc4,0x42,0x21,0x00,0x17,0x80,0x13,0x00, + 0x09,0x00,0xc8,0x00,0x24,0x00,0x44,0x00, + 0xe2,0x00,0x60,0x90,0x80,0x40,0x20,0x20, + 0x00,0x20,0x82,0x82,0x7c,0x44,0x28,0x28, + 0x10,0x10,0x00,0x10,0x20,0x82,0x82,0x7c, + 0x44,0x28,0x28,0x10,0x10,0x00,0x10,0x08, + 0x82,0x82,0x7c,0x44,0x28,0x28,0x10,0x10, + 0x00,0x28,0x10,0x82,0x82,0x7c,0x44,0x28, + 0x28,0x10,0x10,0x00,0x28,0x14,0x82,0x82, + 0x7c,0x44,0x28,0x28,0x10,0x10,0x00,0x28, + 0x82,0x82,0x7c,0x44,0x28,0x28,0x10,0x10, + 0x10,0x28,0x10,0x8f,0x80,0x88,0x00,0x78, + 0x00,0x48,0x00,0x2f,0x80,0x28,0x00,0x18, + 0x00,0x1f,0x80,0x30,0x10,0x78,0x84,0x80, + 0x80,0x80,0x80,0x84,0x78,0xf8,0x80,0x80, + 0x80,0xf8,0x80,0x80,0xf8,0x00,0x20,0x40, + 0xf8,0x80,0x80,0x80,0xf8,0x80,0x80,0xf8, + 0x00,0x20,0x10,0xf8,0x80,0x80,0xf8,0x80, + 0x80,0x80,0xf8,0x00,0x50,0x20,0xf8,0x80, + 0x80,0x80,0xf8,0x80,0x80,0xf8,0x00,0x50, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x00,0x40,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x00,0x80,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x00,0xa0, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x00,0xa0,0x78,0x44,0x42,0x42,0xf2, + 0x42,0x44,0x78,0x8c,0x8c,0x94,0x94,0xa4, + 0xa4,0xc4,0xc4,0x00,0x50,0x28,0x78,0x84, + 0x84,0x84,0x84,0x84,0x84,0x78,0x00,0x10, + 0x20,0x78,0x84,0x84,0x84,0x84,0x84,0x84, + 0x78,0x00,0x10,0x08,0x78,0x84,0x84,0x84, + 0x84,0x84,0x84,0x78,0x00,0x28,0x10,0x78, + 0x84,0x84,0x84,0x84,0x84,0x84,0x78,0x00, + 0x50,0x28,0x78,0x84,0x84,0x84,0x84,0x84, + 0x84,0x78,0x00,0x48,0x88,0x50,0x20,0x50, + 0x88,0x80,0x78,0xc4,0xa4,0xa4,0x94,0x94, + 0x8c,0x78,0x04,0x78,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x00,0x10,0x20,0x78,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x00,0x20, + 0x10,0x78,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x00,0x28,0x10,0x78,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x00,0x48,0x10,0x10, + 0x10,0x28,0x28,0x44,0x44,0x82,0x00,0x10, + 0x08,0x80,0x80,0xf0,0x88,0x88,0xf0,0x80, + 0x80,0xa0,0x90,0x90,0x90,0xa0,0x90,0x90, + 0x60,0x68,0x90,0x90,0x70,0x10,0xe0,0x00, + 0x20,0x40,0x68,0x90,0x90,0x70,0x10,0xe0, + 0x00,0x20,0x10,0x68,0x90,0x90,0x70,0x10, + 0xe0,0x00,0x50,0x20,0x68,0x90,0x90,0x70, + 0x10,0xe0,0x00,0xa0,0x50,0x68,0x90,0x90, + 0x70,0x10,0xe0,0x00,0x50,0x68,0x90,0x90, + 0x70,0x10,0xe0,0x20,0x50,0x20,0x6c,0x92, + 0x90,0x7e,0x12,0xec,0x60,0x20,0x60,0x90, + 0x80,0x80,0x90,0x60,0x60,0x90,0x80,0xf0, + 0x90,0x60,0x00,0x20,0x40,0x60,0x90,0x80, + 0xf0,0x90,0x60,0x00,0x40,0x20,0x60,0x90, + 0x80,0xf0,0x90,0x60,0x00,0x50,0x20,0x60, + 0x90,0x80,0xf0,0x90,0x60,0x00,0x50,0x40, + 0x40,0x40,0x40,0x40,0x40,0x00,0x40,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x80, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, + 0xa0,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x00,0xa0,0x70,0x88,0x88,0x88,0x88,0x78, + 0x90,0x60,0x50,0x90,0x90,0x90,0x90,0x90, + 0xe0,0x00,0xa0,0x50,0x70,0x88,0x88,0x88, + 0x88,0x70,0x00,0x20,0x40,0x70,0x88,0x88, + 0x88,0x88,0x70,0x00,0x20,0x10,0x70,0x88, + 0x88,0x88,0x88,0x70,0x00,0x50,0x20,0x70, + 0x88,0x88,0x88,0x88,0x70,0x00,0x50,0x28, + 0x70,0x88,0x88,0x88,0x88,0x70,0x00,0x50, + 0x20,0x00,0xf8,0x00,0x20,0x70,0x88,0xc8, + 0xa8,0x98,0x74,0x70,0x90,0x90,0x90,0x90, + 0x90,0x00,0x20,0x40,0x70,0x90,0x90,0x90, + 0x90,0x90,0x00,0x40,0x20,0x70,0x90,0x90, + 0x90,0x90,0x90,0x00,0x50,0x20,0x70,0x90, + 0x90,0x90,0x90,0x90,0x00,0x50,0x80,0x40, + 0x40,0x60,0xa0,0xa0,0x90,0x90,0x00,0x20, + 0x10,0x80,0x80,0xb0,0xc8,0x88,0x88,0xc8, + 0xb0,0x80,0x80,0x80,0x40,0x40,0x60,0xa0, + 0xa0,0x90,0x90,0x00,0x50, +}; + +BMF_FontData BMF_font_helv10 = { + -1, -2, + 10, 11, + { + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0, 0, 0, 0, 12, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0, 0, 0, 0, 3, -1}, + {1, 8, -1, 0, 3, 0}, + {3, 2, -1, -6, 4, 8}, + {6, 7, 0, 0, 6, 10}, + {5, 9, 0, 1, 6, 17}, + {8, 8, 0, 0, 9, 26}, + {6, 8, -1, 0, 8, 34}, + {2, 3, -1, -5, 3, 42}, + {3, 10, 0, 2, 4, 45}, + {3, 10, -1, 2, 4, 55}, + {3, 3, 0, -5, 4, 65}, + {5, 5, 0, -1, 6, 68}, + {2, 3, 0, 2, 3, 73}, + {5, 1, -1, -3, 7, 76}, + {1, 1, -1, 0, 3, 77}, + {3, 8, 0, 0, 3, 78}, + {5, 8, 0, 0, 6, 86}, + {2, 8, -1, 0, 6, 94}, + {5, 8, 0, 0, 6, 102}, + {5, 8, 0, 0, 6, 110}, + {5, 8, 0, 0, 6, 118}, + {5, 8, 0, 0, 6, 126}, + {5, 8, 0, 0, 6, 134}, + {5, 8, 0, 0, 6, 142}, + {5, 8, 0, 0, 6, 150}, + {5, 8, 0, 0, 6, 158}, + {1, 6, -1, 0, 3, 166}, + {2, 8, 0, 2, 3, 172}, + {3, 5, -1, -1, 6, 180}, + {4, 3, 0, -2, 5, 185}, + {3, 5, -1, -1, 6, 188}, + {4, 8, -1, 0, 6, 193}, + {10, 10, 0, 2, 11, 201}, + {7, 8, 0, 0, 7, 221}, + {5, 8, -1, 0, 7, 229}, + {6, 8, -1, 0, 8, 237}, + {6, 8, -1, 0, 8, 245}, + {5, 8, -1, 0, 7, 253}, + {5, 8, -1, 0, 6, 261}, + {6, 8, -1, 0, 8, 269}, + {6, 8, -1, 0, 8, 277}, + {1, 8, -1, 0, 3, 285}, + {4, 8, 0, 0, 5, 293}, + {5, 8, -1, 0, 7, 301}, + {4, 8, -1, 0, 6, 309}, + {7, 8, -1, 0, 9, 317}, + {6, 8, -1, 0, 8, 325}, + {6, 8, -1, 0, 8, 333}, + {5, 8, -1, 0, 7, 341}, + {7, 9, -1, 1, 8, 349}, + {5, 8, -1, 0, 7, 358}, + {5, 8, -1, 0, 7, 366}, + {5, 8, 0, 0, 5, 374}, + {6, 8, -1, 0, 8, 382}, + {7, 8, 0, 0, 7, 390}, + {9, 8, 0, 0, 9, 398}, + {5, 8, -1, 0, 7, 414}, + {7, 8, 0, 0, 7, 422}, + {5, 8, -1, 0, 7, 430}, + {2, 10, -1, 2, 3, 438}, + {3, 8, 0, 0, 3, 448}, + {2, 10, 0, 2, 3, 456}, + {5, 5, 0, -3, 6, 466}, + {6, 1, 0, 2, 6, 471}, + {2, 3, 0, -5, 3, 472}, + {5, 6, 0, 0, 5, 475}, + {5, 8, 0, 0, 6, 481}, + {4, 6, 0, 0, 5, 489}, + {5, 8, 0, 0, 6, 495}, + {4, 6, 0, 0, 5, 503}, + {4, 8, 0, 0, 4, 509}, + {5, 8, 0, 2, 6, 517}, + {5, 8, 0, 0, 6, 525}, + {1, 8, 0, 0, 2, 533}, + {1, 9, 0, 1, 2, 541}, + {4, 8, 0, 0, 5, 550}, + {1, 8, 0, 0, 2, 558}, + {7, 6, 0, 0, 8, 566}, + {5, 6, 0, 0, 6, 572}, + {5, 6, 0, 0, 6, 578}, + {5, 8, 0, 2, 6, 584}, + {5, 8, 0, 2, 6, 592}, + {3, 6, 0, 0, 4, 600}, + {4, 6, 0, 0, 5, 606}, + {3, 8, 0, 0, 4, 612}, + {4, 6, 0, 0, 5, 620}, + {5, 6, 0, 0, 6, 626}, + {7, 6, 0, 0, 8, 632}, + {5, 6, 0, 0, 6, 638}, + {4, 8, 0, 2, 5, 644}, + {4, 6, 0, 0, 5, 652}, + {3, 10, 0, 2, 3, 658}, + {1, 10, -1, 2, 3, 668}, + {3, 10, 0, 2, 3, 678}, + {6, 2, 0, -3, 7, 688}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0, 0, 0, 0, 3, -1}, + {1, 8, -1, 2, 3, 690}, + {5, 8, 0, 1, 6, 698}, + {5, 8, 0, 0, 6, 706}, + {4, 6, 0, -1, 5, 714}, + {5, 8, 0, 0, 6, 720}, + {1, 10, -1, 2, 3, 728}, + {5, 10, 0, 2, 6, 738}, + {3, 1, 0, -7, 3, 748}, + {7, 7, -1, 0, 9, 749}, + {3, 5, 0, -3, 4, 756}, + {5, 5, 0, 0, 6, 761}, + {5, 3, -1, -2, 7, 766}, + {3, 1, 0, -3, 4, 769}, + {7, 7, -1, 0, 9, 770}, + {3, 1, 0, -7, 3, 777}, + {4, 4, 0, -3, 4, 778}, + {5, 7, 0, 0, 6, 782}, + {3, 4, 0, -3, 3, 789}, + {3, 4, 0, -3, 3, 793}, + {2, 2, 0, -6, 3, 797}, + {4, 8, 0, 2, 5, 799}, + {6, 10, 0, 2, 6, 807}, + {2, 1, 0, -3, 3, 817}, + {2, 2, 0, 2, 3, 818}, + {2, 4, 0, -3, 3, 820}, + {3, 5, 0, -3, 4, 824}, + {5, 5, 0, 0, 6, 829}, + {9, 8, 0, 0, 9, 834}, + {8, 8, 0, 0, 9, 850}, + {9, 8, 0, 0, 9, 858}, + {4, 8, -1, 2, 6, 874}, + {7, 11, 0, 0, 7, 882}, + {7, 11, 0, 0, 7, 893}, + {7, 11, 0, 0, 7, 904}, + {7, 11, 0, 0, 7, 915}, + {7, 10, 0, 0, 7, 926}, + {7, 11, 0, 0, 7, 936}, + {9, 8, 0, 0, 10, 947}, + {6, 10, -1, 2, 8, 963}, + {5, 11, -1, 0, 7, 973}, + {5, 11, -1, 0, 7, 984}, + {5, 11, -1, 0, 7, 995}, + {5, 10, -1, 0, 7, 1006}, + {2, 11, 0, 0, 3, 1016}, + {2, 11, -1, 0, 3, 1027}, + {3, 11, 0, 0, 3, 1038}, + {3, 10, 0, 0, 3, 1049}, + {7, 8, 0, 0, 8, 1059}, + {6, 11, -1, 0, 8, 1067}, + {6, 11, -1, 0, 8, 1078}, + {6, 11, -1, 0, 8, 1089}, + {6, 11, -1, 0, 8, 1100}, + {6, 11, -1, 0, 8, 1111}, + {6, 10, -1, 0, 8, 1122}, + {5, 5, 0, -1, 6, 1132}, + {6, 10, -1, 1, 8, 1137}, + {6, 11, -1, 0, 8, 1147}, + {6, 11, -1, 0, 8, 1158}, + {6, 11, -1, 0, 8, 1169}, + {6, 10, -1, 0, 8, 1180}, + {7, 11, 0, 0, 7, 1190}, + {5, 8, -1, 0, 7, 1201}, + {4, 8, 0, 0, 5, 1209}, + {5, 9, 0, 0, 5, 1217}, + {5, 9, 0, 0, 5, 1226}, + {5, 9, 0, 0, 5, 1235}, + {5, 9, 0, 0, 5, 1244}, + {5, 8, 0, 0, 5, 1253}, + {5, 9, 0, 0, 5, 1261}, + {7, 6, 0, 0, 8, 1270}, + {4, 8, 0, 2, 5, 1276}, + {4, 9, 0, 0, 5, 1284}, + {4, 9, 0, 0, 5, 1293}, + {4, 9, 0, 0, 5, 1302}, + {4, 8, 0, 0, 5, 1311}, + {2, 9, 1, 0, 2, 1319}, + {2, 9, 0, 0, 2, 1328}, + {3, 9, 1, 0, 2, 1337}, + {3, 8, 0, 0, 2, 1346}, + {5, 9, 0, 0, 6, 1354}, + {4, 9, 0, 0, 5, 1363}, + {5, 9, 0, 0, 6, 1372}, + {5, 9, 0, 0, 6, 1381}, + {5, 9, 0, 0, 6, 1390}, + {5, 9, 0, 0, 6, 1399}, + {5, 8, 0, 0, 6, 1408}, + {5, 5, 0, -1, 6, 1416}, + {6, 6, 0, 0, 6, 1421}, + {4, 9, 0, 0, 5, 1427}, + {4, 9, 0, 0, 5, 1436}, + {4, 9, 0, 0, 5, 1445}, + {4, 8, 0, 0, 5, 1454}, + {4, 11, 0, 2, 5, 1462}, + {5, 10, 0, 2, 6, 1473}, + {4, 10, 0, 2, 5, 1483}, + }, + bitmap_data +}; + +#endif + diff --git a/intern/bmfont/intern/BMF_font_helv12.cpp b/intern/bmfont/intern/BMF_font_helv12.cpp new file mode 100644 index 00000000000..45ab6531cdb --- /dev/null +++ b/intern/bmfont/intern/BMF_font_helv12.cpp @@ -0,0 +1,525 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BMF_FontData.h" + +#include "BMF_Settings.h" + +#if BMF_INCLUDE_HELV12 + +static unsigned char bitmap_data[]= { + 0x80,0x00,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0xa0,0xa0,0xa0,0x50,0x50,0x50,0xfc, + 0x28,0xfc,0x28,0x28,0x20,0x70,0xa8,0xa8, + 0x28,0x70,0xa0,0xa8,0x70,0x20,0x23,0x00, + 0x14,0x80,0x14,0x80,0x13,0x00,0x08,0x00, + 0x68,0x00,0x94,0x00,0x94,0x00,0x62,0x00, + 0x72,0x8c,0x84,0x8a,0x50,0x30,0x48,0x48, + 0x30,0x80,0x40,0xc0,0x20,0x40,0x40,0x80, + 0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x20, + 0x80,0x40,0x40,0x20,0x20,0x20,0x20,0x20, + 0x20,0x40,0x40,0x80,0xa0,0x40,0xa0,0x20, + 0x20,0xf8,0x20,0x20,0x80,0x40,0x40,0xf8, + 0x80,0x80,0x80,0x40,0x40,0x40,0x20,0x20, + 0x10,0x10,0x70,0x88,0x88,0x88,0x88,0x88, + 0x88,0x88,0x70,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0xe0,0x20,0xf8,0x80,0x80,0x40, + 0x20,0x10,0x08,0x88,0x70,0x70,0x88,0x88, + 0x08,0x08,0x30,0x08,0x88,0x70,0x08,0x08, + 0xfc,0x88,0x48,0x28,0x28,0x18,0x08,0x70, + 0x88,0x88,0x08,0x08,0xf0,0x80,0x80,0xf8, + 0x70,0x88,0x88,0x88,0xc8,0xb0,0x80,0x88, + 0x70,0x40,0x40,0x20,0x20,0x20,0x10,0x10, + 0x08,0xf8,0x70,0x88,0x88,0x88,0x88,0x70, + 0x88,0x88,0x70,0x70,0x88,0x08,0x08,0x78, + 0x88,0x88,0x88,0x70,0x80,0x00,0x00,0x00, + 0x00,0x80,0x80,0x40,0x40,0x00,0x00,0x00, + 0x00,0x40,0x0c,0x30,0xc0,0x30,0x0c,0xf8, + 0x00,0xf8,0xc0,0x30,0x0c,0x30,0xc0,0x20, + 0x00,0x20,0x20,0x10,0x10,0x88,0x88,0x70, + 0x3e,0x00,0x40,0x00,0x9b,0x00,0xa6,0x80, + 0xa2,0x40,0xa2,0x40,0x92,0x40,0x4d,0x40, + 0x60,0x80,0x1f,0x00,0x82,0x82,0x82,0x7c, + 0x44,0x44,0x28,0x28,0x10,0xf8,0x84,0x84, + 0x84,0xf8,0x84,0x84,0x84,0xf8,0x3c,0x42, + 0x80,0x80,0x80,0x80,0x80,0x42,0x3c,0xf8, + 0x84,0x82,0x82,0x82,0x82,0x82,0x84,0xf8, + 0xfc,0x80,0x80,0x80,0xfc,0x80,0x80,0x80, + 0xfc,0x80,0x80,0x80,0x80,0xf8,0x80,0x80, + 0x80,0xfc,0x3a,0x46,0x82,0x82,0x8e,0x80, + 0x80,0x42,0x3c,0x82,0x82,0x82,0x82,0xfe, + 0x82,0x82,0x82,0x82,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x70,0x88,0x88, + 0x08,0x08,0x08,0x08,0x08,0x08,0x82,0x84, + 0x88,0x90,0xe0,0xa0,0x90,0x88,0x84,0xf8, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x88,0x80,0x88,0x80,0x94,0x80,0x94,0x80, + 0xa2,0x80,0xa2,0x80,0xc1,0x80,0xc1,0x80, + 0x80,0x80,0x82,0x86,0x8a,0x8a,0x92,0xa2, + 0xa2,0xc2,0x82,0x3c,0x42,0x81,0x81,0x81, + 0x81,0x81,0x42,0x3c,0x80,0x80,0x80,0x80, + 0xf8,0x84,0x84,0x84,0xf8,0x3d,0x42,0x85, + 0x89,0x81,0x81,0x81,0x42,0x3c,0x84,0x84, + 0x84,0x88,0xf8,0x84,0x84,0x84,0xf8,0x78, + 0x84,0x84,0x04,0x18,0x60,0x80,0x84,0x78, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0xfe,0x78,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x10,0x10,0x28,0x28,0x44,0x44, + 0x44,0x82,0x82,0x22,0x00,0x22,0x00,0x22, + 0x00,0x55,0x00,0x55,0x00,0x49,0x00,0x88, + 0x80,0x88,0x80,0x88,0x80,0x82,0x44,0x44, + 0x28,0x10,0x28,0x44,0x44,0x82,0x10,0x10, + 0x10,0x10,0x28,0x44,0x44,0x82,0x82,0xfe, + 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0xfe, + 0xc0,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0xc0,0x10,0x10,0x20,0x20, + 0x20,0x40,0x40,0x80,0x80,0xc0,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0xc0,0x88,0x50,0x20,0xfe,0xc0,0x80,0x40, + 0x74,0x88,0x88,0x78,0x08,0x88,0x70,0xb0, + 0xc8,0x88,0x88,0x88,0xc8,0xb0,0x80,0x80, + 0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x68, + 0x98,0x88,0x88,0x88,0x98,0x68,0x08,0x08, + 0x70,0x88,0x80,0xf8,0x88,0x88,0x70,0x40, + 0x40,0x40,0x40,0x40,0x40,0xe0,0x40,0x30, + 0x70,0x88,0x08,0x68,0x98,0x88,0x88,0x88, + 0x98,0x68,0x88,0x88,0x88,0x88,0x88,0xc8, + 0xb0,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x00,0x80,0x80,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x40, + 0x88,0x90,0xa0,0xc0,0xc0,0xa0,0x90,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x92,0x92,0x92,0x92,0x92,0xda, + 0xa4,0x88,0x88,0x88,0x88,0x88,0xc8,0xb0, + 0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x80, + 0x80,0x80,0xb0,0xc8,0x88,0x88,0x88,0xc8, + 0xb0,0x08,0x08,0x08,0x68,0x98,0x88,0x88, + 0x88,0x98,0x68,0x80,0x80,0x80,0x80,0x80, + 0xc0,0xa0,0x60,0x90,0x10,0x60,0x80,0x90, + 0x60,0x60,0x40,0x40,0x40,0x40,0x40,0xe0, + 0x40,0x40,0x68,0x98,0x88,0x88,0x88,0x88, + 0x88,0x20,0x20,0x50,0x50,0x88,0x88,0x88, + 0x22,0x00,0x22,0x00,0x55,0x00,0x49,0x00, + 0x49,0x00,0x88,0x80,0x88,0x80,0x84,0x84, + 0x48,0x30,0x30,0x48,0x84,0x80,0x40,0x20, + 0x20,0x50,0x50,0x90,0x88,0x88,0x88,0xf0, + 0x80,0x40,0x40,0x20,0x10,0xf0,0x30,0x40, + 0x40,0x40,0x40,0x40,0x80,0x40,0x40,0x40, + 0x40,0x30,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0xc0,0x20, + 0x20,0x20,0x20,0x20,0x10,0x20,0x20,0x20, + 0x20,0xc0,0x98,0x64,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x00,0x80,0x40,0x70, + 0xc8,0xa0,0xa0,0xa0,0xa8,0x70,0x10,0xb0, + 0x48,0x20,0x20,0xf0,0x40,0x40,0x48,0x30, + 0x84,0x78,0x48,0x48,0x78,0x84,0x20,0x20, + 0xf8,0x20,0xf8,0x20,0x50,0x88,0x88,0x80, + 0x80,0x80,0x80,0x00,0x00,0x00,0x80,0x80, + 0x80,0x80,0x70,0x88,0x08,0x30,0x48,0x88, + 0x88,0x90,0x60,0x80,0x88,0x70,0xa0,0x3e, + 0x00,0x41,0x00,0x9c,0x80,0xa2,0x80,0xa0, + 0x80,0xa2,0x80,0x9c,0x80,0x41,0x00,0x3e, + 0x00,0xe0,0x00,0xa0,0x20,0xe0,0x28,0x50, + 0xa0,0x50,0x28,0x04,0x04,0x04,0xfc,0xf0, + 0x3e,0x00,0x41,0x00,0x94,0x80,0x94,0x80, + 0x98,0x80,0x94,0x80,0x9c,0x80,0x41,0x00, + 0x3e,0x00,0xf0,0x60,0x90,0x90,0x60,0xf8, + 0x00,0x20,0x20,0xf8,0x20,0x20,0xf0,0x40, + 0x20,0x90,0x60,0xc0,0x20,0x40,0x20,0xe0, + 0x80,0x40,0x80,0x80,0x80,0xe8,0x98,0x88, + 0x88,0x88,0x88,0x88,0x28,0x28,0x28,0x28, + 0x28,0x28,0x68,0xe8,0xe8,0xe8,0x68,0x3c, + 0x80,0xc0,0x20,0x20,0x40,0x40,0x40,0x40, + 0xc0,0x40,0xe0,0x00,0xe0,0xa0,0xe0,0xa0, + 0x50,0x28,0x50,0xa0,0x41,0x00,0x27,0x80, + 0x15,0x00,0x13,0x00,0x49,0x00,0x44,0x00, + 0x44,0x00,0xc2,0x00,0x41,0x00,0x47,0x80, + 0x22,0x00,0x11,0x00,0x14,0x80,0x4b,0x00, + 0x48,0x00,0x44,0x00,0xc2,0x00,0x41,0x00, + 0x21,0x00,0x17,0x80,0x15,0x00,0x0b,0x00, + 0xc9,0x00,0x24,0x00,0x44,0x00,0x22,0x00, + 0xe1,0x00,0x70,0x88,0x88,0x40,0x40,0x20, + 0x20,0x00,0x20,0x82,0x82,0x82,0x7c,0x44, + 0x44,0x28,0x10,0x10,0x00,0x10,0x20,0x82, + 0x82,0x82,0x7c,0x44,0x44,0x28,0x10,0x10, + 0x00,0x10,0x08,0x82,0x82,0x82,0x7c,0x44, + 0x44,0x28,0x10,0x10,0x00,0x28,0x10,0x82, + 0x82,0x82,0x7c,0x44,0x44,0x28,0x10,0x10, + 0x00,0x28,0x14,0x82,0x82,0x82,0x7c,0x44, + 0x44,0x28,0x10,0x10,0x00,0x28,0x82,0x82, + 0x82,0x7c,0x44,0x44,0x28,0x10,0x10,0x10, + 0x28,0x10,0x8f,0x80,0x88,0x00,0x88,0x00, + 0x78,0x00,0x4f,0x80,0x48,0x00,0x28,0x00, + 0x28,0x00,0x1f,0x80,0x30,0x08,0x08,0x3c, + 0x42,0x80,0x80,0x80,0x80,0x80,0x42,0x3c, + 0xfc,0x80,0x80,0x80,0xfc,0x80,0x80,0x80, + 0xfc,0x00,0x10,0x20,0xfc,0x80,0x80,0x80, + 0xfc,0x80,0x80,0x80,0xfc,0x00,0x10,0x08, + 0xfc,0x80,0x80,0x80,0xfc,0x80,0x80,0x80, + 0xfc,0x00,0x28,0x10,0xfc,0x80,0x80,0x80, + 0xfc,0x80,0x80,0x80,0xfc,0x00,0x28,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x00,0x40,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x00,0x80,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x00,0xa0,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x00,0xa0,0x7c,0x42, + 0x41,0x41,0xf1,0x41,0x41,0x42,0x7c,0x82, + 0x86,0x8a,0x8a,0x92,0xa2,0xa2,0xc2,0x82, + 0x00,0x28,0x14,0x3c,0x42,0x81,0x81,0x81, + 0x81,0x81,0x42,0x3c,0x00,0x08,0x10,0x3c, + 0x42,0x81,0x81,0x81,0x81,0x81,0x42,0x3c, + 0x00,0x08,0x04,0x3c,0x42,0x81,0x81,0x81, + 0x81,0x81,0x42,0x3c,0x00,0x14,0x08,0x3c, + 0x42,0x81,0x81,0x81,0x81,0x81,0x42,0x3c, + 0x00,0x28,0x14,0x3c,0x42,0x81,0x81,0x81, + 0x81,0x81,0x42,0x3c,0x00,0x24,0x88,0x50, + 0x20,0x50,0x88,0x80,0x00,0x5e,0x00,0x21, + 0x00,0x50,0x80,0x48,0x80,0x44,0x80,0x44, + 0x80,0x42,0x80,0x21,0x00,0x1e,0x80,0x00, + 0x40,0x78,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x00,0x10,0x20,0x78,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x00,0x10, + 0x08,0x78,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x00,0x28,0x10,0x78,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x00,0x48, + 0x10,0x10,0x10,0x10,0x28,0x44,0x44,0x82, + 0x82,0x00,0x10,0x08,0x80,0x80,0xf8,0x84, + 0x84,0x84,0xf8,0x80,0x80,0xb0,0x88,0x88, + 0x88,0xb0,0x88,0x88,0x88,0x70,0x74,0x88, + 0x88,0x78,0x08,0x88,0x70,0x00,0x10,0x20, + 0x74,0x88,0x88,0x78,0x08,0x88,0x70,0x00, + 0x20,0x10,0x74,0x88,0x88,0x78,0x08,0x88, + 0x70,0x00,0x50,0x20,0x74,0x88,0x88,0x78, + 0x08,0x88,0x70,0x00,0x50,0x28,0x74,0x88, + 0x88,0x78,0x08,0x88,0x70,0x00,0x50,0x74, + 0x88,0x88,0x78,0x08,0x88,0x70,0x30,0x48, + 0x30,0x77,0x00,0x88,0x80,0x88,0x00,0x7f, + 0x80,0x08,0x80,0x88,0x80,0x77,0x00,0x60, + 0x10,0x20,0x70,0x88,0x80,0x80,0x80,0x88, + 0x70,0x70,0x88,0x80,0xf8,0x88,0x88,0x70, + 0x00,0x20,0x40,0x70,0x88,0x80,0xf8,0x88, + 0x88,0x70,0x00,0x20,0x10,0x70,0x88,0x80, + 0xf8,0x88,0x88,0x70,0x00,0x50,0x20,0x70, + 0x88,0x80,0xf8,0x88,0x88,0x70,0x00,0x50, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, + 0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x00,0x80,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x00,0xa0,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x00,0xa0,0x70, + 0x88,0x88,0x88,0x88,0x78,0x08,0x50,0x30, + 0x68,0x88,0x88,0x88,0x88,0x88,0xc8,0xb0, + 0x00,0x50,0x28,0x70,0x88,0x88,0x88,0x88, + 0x88,0x70,0x00,0x20,0x40,0x70,0x88,0x88, + 0x88,0x88,0x88,0x70,0x00,0x20,0x10,0x70, + 0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x50, + 0x20,0x70,0x88,0x88,0x88,0x88,0x88,0x70, + 0x00,0x50,0x28,0x70,0x88,0x88,0x88,0x88, + 0x88,0x70,0x00,0x50,0x20,0x00,0xf8,0x00, + 0x20,0xb8,0x44,0x64,0x54,0x4c,0x44,0x3a, + 0x68,0x98,0x88,0x88,0x88,0x88,0x88,0x00, + 0x20,0x40,0x68,0x98,0x88,0x88,0x88,0x88, + 0x88,0x00,0x20,0x10,0x68,0x98,0x88,0x88, + 0x88,0x88,0x88,0x00,0x50,0x20,0x68,0x98, + 0x88,0x88,0x88,0x88,0x88,0x00,0x50,0x80, + 0x40,0x20,0x20,0x50,0x50,0x90,0x88,0x88, + 0x88,0x00,0x20,0x10,0x80,0x80,0x80,0xb0, + 0xc8,0x88,0x88,0x88,0xc8,0xb0,0x80,0x80, + 0xc0,0x20,0x20,0x20,0x30,0x50,0x50,0x48, + 0x88,0x88,0x00,0x50, +}; + +BMF_FontData BMF_font_helv12 = { + 0, -3, + 11, 12, + { + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0, 0, 0, 0, 16, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0, 0, 0, 0, 4, -1}, + {1, 9, -1, 0, 3, 0}, + {3, 3, -1, -6, 5, 9}, + {6, 8, 0, 0, 7, 12}, + {5, 10, -1, 1, 7, 20}, + {9, 9, -1, 0, 11, 30}, + {7, 9, -1, 0, 9, 48}, + {2, 3, -1, -6, 3, 57}, + {3, 12, -1, 3, 4, 60}, + {3, 12, 0, 3, 4, 72}, + {3, 3, -1, -6, 5, 84}, + {5, 5, -1, -1, 7, 87}, + {2, 3, -1, 2, 4, 92}, + {5, 1, -1, -3, 8, 95}, + {1, 1, -1, 0, 3, 96}, + {4, 9, 0, 0, 4, 97}, + {5, 9, -1, 0, 7, 106}, + {3, 9, -1, 0, 7, 115}, + {5, 9, -1, 0, 7, 124}, + {5, 9, -1, 0, 7, 133}, + {6, 9, 0, 0, 7, 142}, + {5, 9, -1, 0, 7, 151}, + {5, 9, -1, 0, 7, 160}, + {5, 9, -1, 0, 7, 169}, + {5, 9, -1, 0, 7, 178}, + {5, 9, -1, 0, 7, 187}, + {1, 6, -1, 0, 3, 196}, + {2, 8, 0, 2, 3, 202}, + {6, 5, 0, -1, 7, 210}, + {5, 3, -1, -2, 7, 215}, + {6, 5, -1, -1, 7, 218}, + {5, 9, -1, 0, 7, 223}, + {10, 10, -1, 1, 12, 232}, + {7, 9, -1, 0, 9, 252}, + {6, 9, -1, 0, 8, 261}, + {7, 9, -1, 0, 9, 270}, + {7, 9, -1, 0, 9, 279}, + {6, 9, -1, 0, 8, 288}, + {6, 9, -1, 0, 8, 297}, + {7, 9, -1, 0, 9, 306}, + {7, 9, -1, 0, 9, 315}, + {1, 9, -1, 0, 3, 324}, + {5, 9, -1, 0, 7, 333}, + {7, 9, -1, 0, 8, 342}, + {5, 9, -1, 0, 7, 351}, + {9, 9, -1, 0, 11, 360}, + {7, 9, -1, 0, 9, 378}, + {8, 9, -1, 0, 10, 387}, + {6, 9, -1, 0, 8, 396}, + {8, 9, -1, 0, 10, 405}, + {6, 9, -1, 0, 8, 414}, + {6, 9, -1, 0, 8, 423}, + {7, 9, 0, 0, 7, 432}, + {6, 9, -1, 0, 8, 441}, + {7, 9, -1, 0, 9, 450}, + {9, 9, -1, 0, 11, 459}, + {7, 9, -1, 0, 9, 477}, + {7, 9, -1, 0, 9, 486}, + {7, 9, -1, 0, 9, 495}, + {2, 12, -1, 3, 3, 504}, + {4, 9, 0, 0, 4, 516}, + {2, 12, 0, 3, 3, 525}, + {5, 3, 0, -5, 6, 537}, + {7, 1, 0, 2, 7, 540}, + {2, 3, 0, -6, 3, 541}, + {6, 7, -1, 0, 7, 544}, + {5, 9, -1, 0, 7, 551}, + {5, 7, -1, 0, 7, 560}, + {5, 9, -1, 0, 7, 567}, + {5, 7, -1, 0, 7, 576}, + {4, 9, 0, 0, 3, 583}, + {5, 10, -1, 3, 7, 592}, + {5, 9, -1, 0, 7, 602}, + {1, 9, -1, 0, 3, 611}, + {2, 12, 0, 3, 3, 620}, + {5, 9, -1, 0, 6, 632}, + {1, 9, -1, 0, 3, 641}, + {7, 7, -1, 0, 9, 650}, + {5, 7, -1, 0, 7, 657}, + {5, 7, -1, 0, 7, 664}, + {5, 10, -1, 3, 7, 671}, + {5, 10, -1, 3, 7, 681}, + {3, 7, -1, 0, 4, 691}, + {4, 7, -1, 0, 6, 698}, + {3, 9, 0, 0, 3, 705}, + {5, 7, -1, 0, 7, 714}, + {5, 7, -1, 0, 7, 721}, + {9, 7, 0, 0, 9, 728}, + {6, 7, 0, 0, 6, 742}, + {5, 10, -1, 3, 7, 749}, + {4, 7, -1, 0, 6, 759}, + {4, 12, 0, 3, 4, 766}, + {1, 12, -1, 3, 3, 778}, + {4, 12, 0, 3, 4, 790}, + {6, 2, 0, -3, 7, 802}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0, 0, 0, 0, 4, -1}, + {1, 10, -1, 3, 3, 804}, + {5, 9, -1, 1, 7, 814}, + {5, 9, -1, 0, 7, 823}, + {6, 6, 0, -1, 7, 832}, + {5, 9, -1, 0, 7, 838}, + {1, 11, -1, 2, 3, 847}, + {5, 12, 0, 3, 6, 858}, + {3, 1, 0, -8, 3, 870}, + {9, 9, -1, 0, 11, 871}, + {3, 5, -1, -4, 5, 889}, + {5, 5, -1, -1, 7, 894}, + {6, 4, -1, -2, 8, 899}, + {4, 1, 0, -3, 5, 903}, + {9, 9, -1, 0, 11, 904}, + {4, 1, 0, -8, 4, 922}, + {4, 4, 0, -4, 5, 923}, + {5, 7, -1, 0, 7, 927}, + {4, 5, 0, -3, 4, 934}, + {3, 5, 0, -3, 4, 939}, + {2, 2, 0, -8, 2, 944}, + {5, 10, -1, 3, 7, 946}, + {6, 12, 0, 3, 7, 956}, + {1, 1, -1, -3, 3, 968}, + {3, 4, 0, 3, 3, 969}, + {2, 5, -1, -3, 4, 973}, + {3, 5, -1, -4, 5, 978}, + {5, 5, -1, -1, 7, 983}, + {9, 9, 0, 0, 10, 988}, + {9, 9, 0, 0, 10, 1006}, + {9, 9, 0, 0, 10, 1024}, + {5, 9, -1, 3, 7, 1042}, + {7, 12, -1, 0, 9, 1051}, + {7, 12, -1, 0, 9, 1063}, + {7, 12, -1, 0, 9, 1075}, + {7, 12, -1, 0, 9, 1087}, + {7, 11, -1, 0, 9, 1099}, + {7, 12, -1, 0, 9, 1110}, + {9, 9, -1, 0, 11, 1122}, + {7, 12, -1, 3, 9, 1140}, + {6, 12, -1, 0, 8, 1152}, + {6, 12, -1, 0, 8, 1164}, + {6, 12, -1, 0, 8, 1176}, + {6, 11, -1, 0, 8, 1188}, + {2, 12, 0, 0, 3, 1199}, + {2, 12, -1, 0, 3, 1211}, + {3, 12, 0, 0, 3, 1223}, + {3, 11, 0, 0, 3, 1235}, + {8, 9, 0, 0, 9, 1246}, + {7, 12, -1, 0, 9, 1255}, + {8, 12, -1, 0, 10, 1267}, + {8, 12, -1, 0, 10, 1279}, + {8, 12, -1, 0, 10, 1291}, + {8, 12, -1, 0, 10, 1303}, + {8, 11, -1, 0, 10, 1315}, + {5, 5, -1, -1, 7, 1326}, + {10, 11, 0, 1, 10, 1331}, + {6, 12, -1, 0, 8, 1353}, + {6, 12, -1, 0, 8, 1365}, + {6, 12, -1, 0, 8, 1377}, + {6, 11, -1, 0, 8, 1389}, + {7, 12, -1, 0, 9, 1400}, + {6, 9, -1, 0, 8, 1412}, + {5, 9, -1, 0, 7, 1421}, + {6, 10, -1, 0, 7, 1430}, + {6, 10, -1, 0, 7, 1440}, + {6, 10, -1, 0, 7, 1450}, + {6, 10, -1, 0, 7, 1460}, + {6, 9, -1, 0, 7, 1470}, + {6, 10, -1, 0, 7, 1479}, + {9, 7, -1, 0, 11, 1489}, + {5, 10, -1, 3, 7, 1503}, + {5, 10, -1, 0, 7, 1513}, + {5, 10, -1, 0, 7, 1523}, + {5, 10, -1, 0, 7, 1533}, + {5, 9, -1, 0, 7, 1543}, + {2, 10, 0, 0, 3, 1552}, + {2, 10, -1, 0, 3, 1562}, + {3, 10, 0, 0, 3, 1572}, + {3, 9, 0, 0, 3, 1582}, + {5, 10, -1, 0, 7, 1591}, + {5, 10, -1, 0, 7, 1601}, + {5, 10, -1, 0, 7, 1611}, + {5, 10, -1, 0, 7, 1621}, + {5, 10, -1, 0, 7, 1631}, + {5, 10, -1, 0, 7, 1641}, + {5, 9, -1, 0, 7, 1651}, + {5, 5, -1, -1, 7, 1660}, + {7, 7, 0, 0, 7, 1665}, + {5, 10, -1, 0, 7, 1672}, + {5, 10, -1, 0, 7, 1682}, + {5, 10, -1, 0, 7, 1692}, + {5, 9, -1, 0, 7, 1702}, + {5, 13, -1, 3, 7, 1711}, + {5, 12, -1, 3, 7, 1724}, + {5, 12, -1, 3, 7, 1736}, + }, + bitmap_data +}; + +#endif + diff --git a/intern/bmfont/intern/BMF_font_helvb10.cpp b/intern/bmfont/intern/BMF_font_helvb10.cpp new file mode 100644 index 00000000000..4707abfeda2 --- /dev/null +++ b/intern/bmfont/intern/BMF_font_helvb10.cpp @@ -0,0 +1,492 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BMF_FontData.h" + +#include "BMF_Settings.h" + +#if BMF_INCLUDE_HELVB10 + +static unsigned char bitmap_data[]= { + 0x00,0xc0,0x00,0x80,0x80,0xc0,0xc0,0xc0, + 0xc0,0xa0,0xa0,0xa0,0x50,0x50,0xfc,0x28, + 0x7e,0x28,0x28,0x20,0x70,0xa8,0x28,0x38, + 0x70,0xe0,0xa8,0x70,0x20,0x8c,0x56,0x2c, + 0x10,0x10,0x68,0xb4,0x62,0x76,0xdc,0xcc, + 0xde,0x70,0xd8,0xd8,0x70,0x80,0x40,0xc0, + 0xc0,0x20,0x60,0x40,0xc0,0xc0,0xc0,0xc0, + 0x40,0x60,0x20,0x80,0xc0,0x40,0x60,0x60, + 0x60,0x60,0x40,0xc0,0x80,0xa0,0x40,0xa0, + 0x30,0x30,0xfc,0x30,0x30,0x80,0x40,0xc0, + 0xc0,0xf8,0xc0,0xc0,0x80,0x80,0x40,0x40, + 0x20,0x20,0x10,0x10,0x70,0xd8,0xd8,0xd8, + 0xd8,0xd8,0xd8,0x70,0x60,0x60,0x60,0x60, + 0x60,0x60,0xe0,0x60,0xf8,0xc0,0x60,0x30, + 0x18,0x18,0xd8,0x70,0x70,0xd8,0x18,0x18, + 0x30,0x18,0xd8,0x70,0x18,0x18,0xfc,0x98, + 0x58,0x38,0x18,0x08,0x70,0xd8,0x98,0x18, + 0xf0,0xc0,0xc0,0xf8,0x70,0xd8,0xd8,0xd8, + 0xf0,0xc0,0xd8,0x70,0x60,0x60,0x60,0x30, + 0x30,0x18,0x18,0xf8,0x70,0xd8,0xd8,0xd8, + 0x70,0xd8,0xd8,0x70,0x70,0xd8,0x18,0x78, + 0xd8,0xd8,0xd8,0x70,0xc0,0xc0,0x00,0x00, + 0xc0,0xc0,0x80,0x40,0xc0,0xc0,0x00,0x00, + 0xc0,0xc0,0x30,0x60,0xc0,0x60,0x30,0xf8, + 0x00,0xf8,0xc0,0x60,0x30,0x60,0xc0,0x60, + 0x00,0x60,0x60,0x30,0x18,0xd8,0x70,0x3e, + 0x00,0x40,0x00,0x9b,0x00,0xa4,0x80,0xa2, + 0x40,0x92,0x40,0x4d,0x40,0x60,0x80,0x1f, + 0x00,0xc6,0xc6,0xfe,0x6c,0x6c,0x6c,0x38, + 0x38,0xf8,0xcc,0xcc,0xcc,0xf8,0xcc,0xcc, + 0xf8,0x3c,0x66,0xc2,0xc0,0xc0,0xc2,0x66, + 0x3c,0xf0,0xd8,0xcc,0xcc,0xcc,0xcc,0xd8, + 0xf0,0xf8,0xc0,0xc0,0xc0,0xf8,0xc0,0xc0, + 0xf8,0xc0,0xc0,0xc0,0xc0,0xf0,0xc0,0xc0, + 0xf8,0x3a,0x66,0xc6,0xce,0xc0,0xc2,0x66, + 0x3c,0xcc,0xcc,0xcc,0xcc,0xfc,0xcc,0xcc, + 0xcc,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0x70,0xd8,0x18,0x18,0x18,0x18,0x18, + 0x18,0xc6,0xcc,0xd8,0xf0,0xe0,0xf0,0xd8, + 0xcc,0xf8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc9,0x80,0xc9,0x80,0xdd,0x80,0xd5, + 0x80,0xf7,0x80,0xe3,0x80,0xe3,0x80,0xc1, + 0x80,0xc6,0xce,0xce,0xd6,0xd6,0xe6,0xe6, + 0xc6,0x38,0x6c,0xc6,0xc6,0xc6,0xc6,0x6c, + 0x38,0xc0,0xc0,0xc0,0xf8,0xcc,0xcc,0xcc, + 0xf8,0x02,0x3c,0x6c,0xd6,0xc6,0xc6,0xc6, + 0x6c,0x38,0xcc,0xcc,0xcc,0xf8,0xcc,0xcc, + 0xcc,0xf8,0x78,0xcc,0x8c,0x1c,0x78,0xe0, + 0xcc,0x78,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0xfc,0x78,0xcc,0xcc,0xcc,0xcc,0xcc, + 0xcc,0xcc,0x10,0x38,0x38,0x6c,0x6c,0x6c, + 0xc6,0xc6,0x33,0x00,0x33,0x00,0x7f,0x80, + 0x6d,0x80,0x6d,0x80,0xcc,0xc0,0xcc,0xc0, + 0xcc,0xc0,0xc6,0xc6,0x6c,0x38,0x38,0x6c, + 0xc6,0xc6,0x18,0x18,0x18,0x3c,0x66,0x66, + 0xc3,0xc3,0xfc,0xc0,0x60,0x70,0x30,0x18, + 0x0c,0xfc,0xe0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xe0,0x10,0x10,0x20,0x20, + 0x40,0x40,0x80,0x80,0xe0,0x60,0x60,0x60, + 0x60,0x60,0x60,0x60,0x60,0xe0,0x90,0x90, + 0xf0,0x60,0xfc,0xc0,0xc0,0x80,0x40,0x6c, + 0xd8,0xd8,0x78,0x98,0x70,0xf0,0xd8,0xd8, + 0xd8,0xd8,0xf0,0xc0,0xc0,0x70,0xd0,0xc0, + 0xc0,0xd0,0x70,0x78,0xd8,0xd8,0xd8,0xd8, + 0x78,0x18,0x18,0x70,0xd8,0xc0,0xf8,0xd8, + 0x70,0x60,0x60,0x60,0x60,0x60,0xf0,0x60, + 0x38,0x70,0x18,0x78,0xd8,0xd8,0xd8,0xd8, + 0x68,0xd8,0xd8,0xd8,0xd8,0xd8,0xf0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00, + 0xc0,0xc0,0x60,0x60,0x60,0x60,0x60,0x60, + 0x60,0x00,0x60,0xcc,0xd8,0xf0,0xe0,0xf0, + 0xd8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xdb,0xdb,0xdb,0xdb,0xdb, + 0xb6,0xd8,0xd8,0xd8,0xd8,0xd8,0xb0,0x70, + 0xd8,0xd8,0xd8,0xd8,0x70,0xc0,0xc0,0xf0, + 0xd8,0xd8,0xd8,0xd8,0xb0,0x18,0x18,0x78, + 0xd8,0xd8,0xd8,0xd8,0x68,0xc0,0xc0,0xc0, + 0xc0,0xe0,0xb0,0x70,0xd8,0x18,0x70,0xd8, + 0x70,0x30,0x60,0x60,0x60,0x60,0xf0,0x60, + 0x60,0x68,0xd8,0xd8,0xd8,0xd8,0xd8,0x20, + 0x70,0x50,0xd8,0xd8,0xd8,0x6c,0x6c,0x6c, + 0xd6,0xd6,0xd6,0xcc,0xcc,0x78,0x30,0x78, + 0xcc,0x60,0x30,0x30,0x78,0xd8,0xd8,0xd8, + 0xd8,0xf8,0xc0,0x60,0x30,0x18,0xf8,0x30, + 0x60,0x60,0x60,0x60,0xc0,0x60,0x60,0x60, + 0x30,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0xc0,0x60,0x60,0x60,0x60, + 0x30,0x60,0x60,0x60,0xc0,0xb0,0x68,0x00, + 0xc0,0xc0,0xc0,0xc0,0x40,0x40,0x00,0xc0, + 0x40,0x70,0xd8,0xa0,0xa0,0xd8,0x70,0x10, + 0xd8,0x68,0x60,0x60,0xf0,0x60,0x68,0x38, + 0x84,0x78,0x48,0x48,0x78,0x84,0x30,0xfc, + 0x30,0xfc,0x48,0xcc,0x84,0x84,0x80,0x80, + 0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80, + 0x70,0x98,0x38,0x70,0xc8,0x98,0x70,0xe0, + 0xc8,0x70,0xa0,0x3c,0x42,0x9d,0xa1,0xa5, + 0x99,0x42,0x3c,0xe0,0x00,0xa0,0x20,0xe0, + 0x6c,0xd8,0x6c,0x08,0x08,0xf8,0xf0,0x3c, + 0x42,0xa5,0xb9,0xa5,0xbd,0x42,0x3c,0xe0, + 0xc0,0xa0,0x60,0xfc,0x00,0x30,0x30,0xfc, + 0x30,0x30,0xe0,0x40,0xa0,0x60,0xc0,0x20, + 0x40,0xe0,0x80,0x40,0xc0,0xc0,0xe8,0xd8, + 0xd8,0xd8,0xd8,0xd8,0x28,0x28,0x28,0x28, + 0x28,0x68,0xe8,0xe8,0xe8,0x7c,0xc0,0xc0, + 0x40,0x40,0x40,0xc0,0x40,0xe0,0x00,0xe0, + 0xa0,0xe0,0xd8,0x6c,0xd8,0x42,0x2f,0x26, + 0x12,0x48,0x48,0xc4,0x44,0x4e,0x24,0x2a, + 0x16,0x48,0x48,0xc4,0x44,0x42,0x2f,0x26, + 0x12,0xc8,0x28,0x44,0xe4,0x70,0xd8,0xc0, + 0x60,0x30,0x30,0x00,0x30,0xc6,0xc6,0xfe, + 0x6c,0x6c,0x6c,0x38,0x38,0x00,0x10,0x20, + 0xc6,0xc6,0xfe,0x6c,0x6c,0x6c,0x38,0x38, + 0x00,0x10,0x08,0xc6,0xc6,0xfe,0x6c,0x6c, + 0x6c,0x38,0x38,0x00,0x28,0x10,0xc6,0xc6, + 0xfe,0x6c,0x6c,0x6c,0x38,0x38,0x00,0x28, + 0x14,0xc6,0xc6,0xfe,0x6c,0x6c,0x6c,0x38, + 0x38,0x00,0x28,0xc6,0xc6,0xfe,0x6c,0x6c, + 0x6c,0x38,0x38,0x10,0x28,0x10,0xcf,0x80, + 0xcc,0x00,0xfc,0x00,0x6c,0x00,0x6f,0x80, + 0x6c,0x00,0x3c,0x00,0x3f,0x80,0x30,0x10, + 0x3c,0x66,0xc2,0xc0,0xc0,0xc2,0x66,0x3c, + 0xf8,0xc0,0xc0,0xc0,0xf8,0xc0,0xc0,0xf8, + 0x00,0x20,0x40,0xf8,0xc0,0xc0,0xc0,0xf8, + 0xc0,0xc0,0xf8,0x00,0x20,0x10,0xf8,0xc0, + 0xc0,0xc0,0xf8,0xc0,0xc0,0xf8,0x00,0x50, + 0x20,0xf8,0xc0,0xc0,0xc0,0xf8,0xc0,0xc0, + 0xf8,0x00,0x50,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0x00,0x40,0x80,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x80, + 0x40,0x60,0x60,0x60,0x60,0x60,0x60,0x60, + 0x60,0x00,0xa0,0x40,0x60,0x60,0x60,0x60, + 0x60,0x60,0x60,0x60,0x00,0x90,0x78,0x6c, + 0x66,0x66,0xf6,0x66,0x6c,0x78,0xc6,0xce, + 0xce,0xd6,0xd6,0xe6,0xe6,0xc6,0x00,0x28, + 0x14,0x38,0x6c,0xc6,0xc6,0xc6,0xc6,0x6c, + 0x38,0x00,0x08,0x10,0x38,0x6c,0xc6,0xc6, + 0xc6,0xc6,0x6c,0x38,0x00,0x10,0x08,0x38, + 0x6c,0xc6,0xc6,0xc6,0xc6,0x6c,0x38,0x00, + 0x28,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xc6, + 0x6c,0x38,0x00,0x28,0x14,0x38,0x6c,0xc6, + 0xc6,0xc6,0xc6,0x6c,0x38,0x00,0x28,0xcc, + 0x78,0x30,0x78,0xcc,0xb8,0x6c,0xe6,0xd6, + 0xd6,0xce,0x6c,0x3a,0x78,0xcc,0xcc,0xcc, + 0xcc,0xcc,0xcc,0xcc,0x00,0x10,0x20,0x78, + 0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x00, + 0x10,0x08,0x78,0xcc,0xcc,0xcc,0xcc,0xcc, + 0xcc,0xcc,0x00,0x50,0x20,0x78,0xcc,0xcc, + 0xcc,0xcc,0xcc,0xcc,0xcc,0x00,0x48,0x18, + 0x18,0x18,0x3c,0x66,0x66,0xc3,0xc3,0x00, + 0x08,0x04,0xc0,0xc0,0xf8,0xcc,0xcc,0xcc, + 0xf8,0xc0,0xd0,0xc8,0xc8,0xc8,0xd0,0xc8, + 0xc8,0x70,0x6c,0xd8,0xd8,0x78,0x98,0x70, + 0x00,0x10,0x20,0x6c,0xd8,0xd8,0x78,0x98, + 0x70,0x00,0x20,0x10,0x6c,0xd8,0xd8,0x78, + 0x98,0x70,0x00,0x50,0x20,0x6c,0xd8,0xd8, + 0x78,0x98,0x70,0x00,0x50,0x28,0x6c,0xd8, + 0xd8,0x78,0x98,0x70,0x00,0x50,0x6c,0xd8, + 0xd8,0x78,0x98,0x70,0x20,0x50,0x20,0x6e, + 0xdb,0xd8,0x7f,0x9b,0x7e,0x60,0x20,0x70, + 0xd0,0xc0,0xc0,0xd0,0x70,0x70,0xd8,0xc0, + 0xf8,0xd8,0x70,0x00,0x20,0x40,0x70,0xd8, + 0xc0,0xf8,0xd8,0x70,0x00,0x20,0x10,0x70, + 0xd8,0xc0,0xf8,0xd8,0x70,0x00,0x50,0x20, + 0x70,0xd8,0xc0,0xf8,0xd8,0x70,0x00,0x50, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x40, + 0x80,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00, + 0x80,0x40,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0x00,0xa0,0x40,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0x00,0xa0,0x70,0xd8,0xd8,0xd8,0xd8, + 0x70,0xa0,0x60,0x50,0xd8,0xd8,0xd8,0xd8, + 0xd8,0xb0,0x00,0xa0,0x50,0x70,0xd8,0xd8, + 0xd8,0xd8,0x70,0x00,0x20,0x40,0x70,0xd8, + 0xd8,0xd8,0xd8,0x70,0x00,0x20,0x10,0x70, + 0xd8,0xd8,0xd8,0xd8,0x70,0x00,0x50,0x20, + 0x70,0xd8,0xd8,0xd8,0xd8,0x70,0x00,0xa0, + 0x50,0x70,0xd8,0xd8,0xd8,0xd8,0x70,0x00, + 0x50,0x30,0x00,0xfc,0x00,0x30,0xb8,0x6c, + 0x6c,0x7c,0x6c,0x3a,0x68,0xd8,0xd8,0xd8, + 0xd8,0xd8,0x00,0x20,0x40,0x68,0xd8,0xd8, + 0xd8,0xd8,0xd8,0x00,0x20,0x10,0x68,0xd8, + 0xd8,0xd8,0xd8,0xd8,0x00,0x50,0x20,0x68, + 0xd8,0xd8,0xd8,0xd8,0xd8,0x00,0x50,0x60, + 0x30,0x30,0x78,0xd8,0xd8,0xd8,0xd8,0x00, + 0x20,0x10,0xc0,0xc0,0xf0,0xd8,0xc8,0xc8, + 0xd8,0xf0,0xc0,0xc0,0x60,0x30,0x30,0x78, + 0xd8,0xd8,0xd8,0xd8,0x00,0x50, +}; + +BMF_FontData BMF_font_helvb10 = { + -1, -2, + 10, 11, + { + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0, 0, 0, 0, 12, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {1, 1, 0, 0, 3, 0}, + {2, 8, -1, 0, 4, 1}, + {3, 3, -1, -5, 5, 9}, + {7, 7, 1, 0, 6, 12}, + {5, 10, 0, 1, 6, 19}, + {7, 8, 0, 0, 8, 29}, + {7, 8, 0, 0, 8, 37}, + {2, 4, 0, -4, 3, 45}, + {3, 10, 0, 2, 4, 49}, + {3, 10, 0, 2, 4, 59}, + {3, 3, 0, -5, 4, 69}, + {6, 5, 0, -1, 6, 72}, + {2, 4, 0, 2, 3, 77}, + {5, 1, -1, -3, 7, 81}, + {2, 2, 0, 0, 3, 82}, + {4, 8, 0, 0, 4, 84}, + {5, 8, 0, 0, 6, 92}, + {3, 8, -1, 0, 6, 100}, + {5, 8, 0, 0, 6, 108}, + {5, 8, 0, 0, 6, 116}, + {6, 8, 0, 0, 6, 124}, + {5, 8, 0, 0, 6, 132}, + {5, 8, 0, 0, 6, 140}, + {5, 8, 0, 0, 6, 148}, + {5, 8, 0, 0, 6, 156}, + {5, 8, 0, 0, 6, 164}, + {2, 6, 0, 0, 3, 172}, + {2, 8, 0, 2, 3, 178}, + {4, 5, 0, -1, 5, 186}, + {5, 3, 0, -2, 6, 191}, + {4, 5, 0, -1, 5, 194}, + {5, 8, 0, 0, 6, 199}, + {10, 9, 0, 1, 11, 207}, + {7, 8, 0, 0, 8, 225}, + {6, 8, 0, 0, 7, 233}, + {7, 8, 0, 0, 8, 241}, + {6, 8, 0, 0, 7, 249}, + {5, 8, 0, 0, 6, 257}, + {5, 8, 0, 0, 6, 265}, + {7, 8, 0, 0, 8, 273}, + {6, 8, 0, 0, 7, 281}, + {2, 8, 0, 0, 3, 289}, + {5, 8, 0, 0, 6, 297}, + {7, 8, 0, 0, 7, 305}, + {5, 8, 0, 0, 6, 313}, + {9, 8, 0, 0, 10, 321}, + {7, 8, 0, 0, 8, 337}, + {7, 8, 0, 0, 8, 345}, + {6, 8, 0, 0, 7, 353}, + {7, 9, 0, 1, 8, 361}, + {6, 8, 0, 0, 7, 370}, + {6, 8, 0, 0, 7, 378}, + {6, 8, 0, 0, 7, 386}, + {6, 8, 0, 0, 7, 394}, + {7, 8, 0, 0, 8, 402}, + {10, 8, 0, 0, 11, 410}, + {7, 8, 0, 0, 8, 426}, + {8, 8, 0, 0, 9, 434}, + {6, 8, 0, 0, 7, 442}, + {3, 10, 0, 2, 4, 450}, + {4, 8, 0, 0, 4, 460}, + {3, 10, 0, 2, 4, 468}, + {4, 4, 0, -4, 5, 478}, + {6, 1, 0, 2, 6, 482}, + {2, 4, 0, -4, 3, 483}, + {6, 6, 0, 0, 6, 487}, + {5, 8, 0, 0, 6, 493}, + {4, 6, 0, 0, 5, 501}, + {5, 8, 0, 0, 6, 507}, + {5, 6, 0, 0, 6, 515}, + {5, 8, 1, 0, 4, 521}, + {5, 8, 0, 2, 6, 529}, + {5, 8, 0, 0, 6, 537}, + {2, 8, 0, 0, 3, 545}, + {3, 10, 1, 2, 3, 553}, + {6, 8, 0, 0, 6, 563}, + {2, 8, 0, 0, 3, 571}, + {8, 6, 0, 0, 9, 579}, + {5, 6, 0, 0, 6, 585}, + {5, 6, 0, 0, 6, 591}, + {5, 8, 0, 2, 6, 597}, + {5, 8, 0, 2, 6, 605}, + {4, 6, 0, 0, 4, 613}, + {5, 6, 0, 0, 6, 619}, + {4, 8, 1, 0, 4, 625}, + {5, 6, 0, 0, 6, 633}, + {5, 6, 0, 0, 6, 639}, + {7, 6, 0, 0, 8, 645}, + {6, 6, 0, 0, 7, 651}, + {5, 8, 0, 2, 6, 657}, + {5, 6, 0, 0, 6, 665}, + {4, 10, 0, 2, 5, 671}, + {1, 10, -1, 2, 3, 681}, + {4, 10, 0, 2, 5, 691}, + {5, 2, 0, -3, 6, 701}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {1, 1, 0, 0, 3, 703}, + {2, 8, -1, 2, 4, 704}, + {5, 8, 0, 1, 6, 712}, + {5, 8, 0, 0, 6, 720}, + {6, 6, 0, -1, 6, 728}, + {6, 8, 0, 0, 7, 734}, + {1, 10, -1, 2, 3, 742}, + {5, 10, 0, 2, 6, 752}, + {3, 1, 0, -7, 3, 762}, + {8, 8, -1, 0, 10, 763}, + {3, 5, -1, -3, 5, 771}, + {6, 3, 0, -1, 7, 776}, + {5, 3, -1, -2, 7, 779}, + {4, 1, 0, -3, 5, 782}, + {8, 8, -1, 0, 10, 783}, + {3, 1, 0, -7, 3, 791}, + {3, 3, 0, -5, 4, 792}, + {6, 7, 0, 0, 6, 795}, + {3, 4, 0, -4, 3, 802}, + {3, 4, 0, -4, 3, 806}, + {2, 2, 0, -7, 3, 810}, + {5, 8, 0, 2, 6, 812}, + {6, 10, 0, 2, 6, 820}, + {2, 1, 0, -3, 3, 830}, + {2, 2, 0, 2, 3, 831}, + {2, 4, 0, -4, 3, 833}, + {3, 5, -1, -3, 5, 837}, + {6, 3, 0, -1, 7, 842}, + {8, 8, 0, 0, 9, 845}, + {7, 8, 0, 0, 9, 853}, + {8, 8, 0, 0, 9, 861}, + {5, 8, 0, 2, 6, 869}, + {7, 11, 0, 0, 8, 877}, + {7, 11, 0, 0, 8, 888}, + {7, 11, 0, 0, 8, 899}, + {7, 11, 0, 0, 8, 910}, + {7, 10, 0, 0, 8, 921}, + {7, 11, 0, 0, 8, 931}, + {9, 8, 0, 0, 10, 942}, + {7, 10, 0, 2, 8, 958}, + {5, 11, 0, 0, 6, 968}, + {5, 11, 0, 0, 6, 979}, + {5, 11, 0, 0, 6, 990}, + {5, 10, 0, 0, 6, 1001}, + {2, 11, 0, 0, 3, 1011}, + {2, 11, 0, 0, 3, 1022}, + {3, 11, 1, 0, 3, 1033}, + {4, 10, 1, 0, 3, 1044}, + {7, 8, 1, 0, 7, 1054}, + {7, 11, 0, 0, 8, 1062}, + {7, 11, 0, 0, 8, 1073}, + {7, 11, 0, 0, 8, 1084}, + {7, 11, 0, 0, 8, 1095}, + {7, 11, 0, 0, 8, 1106}, + {7, 10, 0, 0, 8, 1117}, + {6, 5, 0, -1, 6, 1127}, + {7, 8, 0, 0, 8, 1132}, + {6, 11, 0, 0, 7, 1140}, + {6, 11, 0, 0, 7, 1151}, + {6, 11, 0, 0, 7, 1162}, + {6, 10, 0, 0, 7, 1173}, + {8, 11, 0, 0, 9, 1183}, + {6, 8, 0, 0, 7, 1194}, + {5, 8, 0, 0, 6, 1202}, + {6, 9, 0, 0, 6, 1210}, + {6, 9, 0, 0, 6, 1219}, + {6, 9, 0, 0, 6, 1228}, + {6, 9, 0, 0, 6, 1237}, + {6, 8, 0, 0, 6, 1246}, + {6, 9, 0, 0, 6, 1254}, + {8, 6, 0, 0, 9, 1263}, + {4, 8, 0, 2, 5, 1269}, + {5, 9, 0, 0, 6, 1277}, + {5, 9, 0, 0, 6, 1286}, + {5, 9, 0, 0, 6, 1295}, + {5, 8, 0, 0, 6, 1304}, + {2, 9, 0, 0, 3, 1312}, + {2, 9, 0, 0, 3, 1321}, + {3, 9, 0, 0, 3, 1330}, + {3, 8, 0, 0, 3, 1339}, + {5, 9, 0, 0, 6, 1347}, + {5, 9, 0, 0, 6, 1356}, + {5, 9, 0, 0, 6, 1365}, + {5, 9, 0, 0, 6, 1374}, + {5, 9, 0, 0, 6, 1383}, + {5, 9, 0, 0, 6, 1392}, + {5, 8, 0, 0, 6, 1401}, + {6, 5, 0, -1, 6, 1409}, + {7, 6, 1, 0, 6, 1414}, + {5, 9, 0, 0, 6, 1420}, + {5, 9, 0, 0, 6, 1429}, + {5, 9, 0, 0, 6, 1438}, + {5, 8, 0, 0, 6, 1447}, + {5, 11, 0, 2, 6, 1455}, + {5, 10, 0, 2, 6, 1466}, + {5, 10, 0, 2, 6, 1476}, + }, + bitmap_data +}; + +#endif + diff --git a/intern/bmfont/intern/BMF_font_helvb12.cpp b/intern/bmfont/intern/BMF_font_helvb12.cpp new file mode 100644 index 00000000000..7ae4f3b4dd5 --- /dev/null +++ b/intern/bmfont/intern/BMF_font_helvb12.cpp @@ -0,0 +1,565 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BMF_FontData.h" + +#include "BMF_Settings.h" + +#if BMF_INCLUDE_HELVB12 + +static unsigned char bitmap_data[]= { + 0x00,0xc0,0xc0,0x00,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xa0,0xa0,0xa0,0x6c, + 0x00,0x6c,0x00,0x6c,0x00,0xff,0x00,0x36, + 0x00,0x36,0x00,0x36,0x00,0x7f,0x80,0x1b, + 0x00,0x1b,0x00,0x1b,0x00,0x30,0x30,0x78, + 0xec,0xac,0x3c,0x38,0x70,0xf0,0xd4,0xdc, + 0x78,0x30,0x63,0x80,0x37,0xc0,0x36,0xc0, + 0x1f,0xc0,0x1b,0x80,0x0c,0x00,0x76,0x00, + 0xfe,0x00,0xdb,0x00,0xfb,0x00,0x71,0x80, + 0x73,0x80,0xff,0x00,0xce,0x00,0xcf,0x00, + 0xdd,0x80,0x79,0x80,0x38,0x00,0x6c,0x00, + 0x6c,0x00,0x7c,0x00,0x38,0x00,0x80,0x40, + 0xc0,0xc0,0x30,0x60,0x60,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0x60,0x60,0x30, + 0xc0,0x60,0x60,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x60,0x60,0xc0,0xd8,0x70, + 0x70,0xf8,0x20,0x30,0x30,0xfc,0xfc,0x30, + 0x30,0x80,0x40,0xc0,0xc0,0xfc,0xfc,0xc0, + 0xc0,0xc0,0xc0,0xc0,0x60,0x60,0x60,0x20, + 0x30,0x30,0x30,0x18,0x18,0x18,0x78,0xfc, + 0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xfc, + 0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0xf0,0xf0,0x30,0xfc,0xfc,0xc0,0x60, + 0x70,0x38,0x18,0xcc,0xcc,0xfc,0x78,0x78, + 0xfc,0xcc,0xcc,0x0c,0x38,0x38,0x0c,0xcc, + 0xfc,0x78,0x0c,0x0c,0xfe,0xfe,0xcc,0x6c, + 0x6c,0x3c,0x3c,0x1c,0x1c,0x78,0xfc,0xcc, + 0xcc,0x0c,0xfc,0xf8,0xc0,0xc0,0xfc,0xfc, + 0x78,0xfc,0xcc,0xcc,0xcc,0xfc,0xf8,0xc0, + 0xcc,0xfc,0x78,0x60,0x60,0x60,0x30,0x30, + 0x30,0x18,0x18,0x0c,0xfc,0xfc,0x78,0xfc, + 0xcc,0xcc,0xcc,0x78,0x78,0xcc,0xcc,0xfc, + 0x78,0x78,0xfc,0xcc,0x0c,0x7c,0xfc,0xcc, + 0xcc,0xcc,0xfc,0x78,0xc0,0xc0,0x00,0x00, + 0x00,0x00,0xc0,0xc0,0x80,0x40,0xc0,0xc0, + 0x00,0x00,0x00,0x00,0xc0,0xc0,0x0c,0x38, + 0xe0,0xe0,0x38,0x0c,0xfc,0xfc,0x00,0xfc, + 0xfc,0xc0,0x70,0x1c,0x1c,0x70,0xc0,0x30, + 0x30,0x00,0x30,0x30,0x38,0x1c,0xcc,0xcc, + 0xfc,0x78,0x1f,0x00,0x71,0x80,0x40,0x00, + 0xdd,0x80,0xb6,0xc0,0xb2,0x40,0xb3,0x60, + 0xdb,0x20,0x4d,0xa0,0x60,0x40,0x39,0xc0, + 0x0f,0x00,0xc3,0xc3,0xff,0x7e,0x66,0x66, + 0x3c,0x3c,0x3c,0x18,0x18,0xf8,0xfc,0xcc, + 0xcc,0xcc,0xf8,0xf8,0xcc,0xcc,0xfc,0xf8, + 0x78,0xfc,0xcc,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xcc,0xfc,0x78,0xf8,0xfc,0xce,0xc6,0xc6, + 0xc6,0xc6,0xc6,0xce,0xfc,0xf8,0xfc,0xfc, + 0xc0,0xc0,0xc0,0xf8,0xf8,0xc0,0xc0,0xfc, + 0xfc,0xc0,0xc0,0xc0,0xc0,0xc0,0xf8,0xf8, + 0xc0,0xc0,0xfc,0xfc,0x76,0xfe,0xc6,0xc6, + 0xde,0xde,0xc0,0xc0,0xc6,0xfe,0x7c,0xc6, + 0xc6,0xc6,0xc6,0xc6,0xfe,0xfe,0xc6,0xc6, + 0xc6,0xc6,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0x70,0xf8,0xd8, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0xc6,0xce,0xcc,0xd8,0xf8,0xf0,0xf0,0xd8, + 0xcc,0xcc,0xc6,0xfc,0xfc,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc9,0x80, + 0xc9,0x80,0xdd,0x80,0xdd,0x80,0xf7,0x80, + 0xf7,0x80,0xe3,0x80,0xe3,0x80,0xe3,0x80, + 0xc1,0x80,0xc1,0x80,0xc6,0xc6,0xce,0xce, + 0xde,0xd6,0xf6,0xe6,0xe6,0xc6,0xc6,0x7c, + 0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6, + 0xfe,0x7c,0xc0,0xc0,0xc0,0xc0,0xfc,0xfe, + 0xc6,0xc6,0xc6,0xfe,0xfc,0x06,0x7e,0xfc, + 0xce,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xfe, + 0x7c,0xc6,0xc6,0xc6,0xce,0xfc,0xfc,0xc6, + 0xc6,0xc6,0xfe,0xfc,0x78,0xfc,0xcc,0x0c, + 0x1c,0x78,0xe0,0xc0,0xcc,0xfc,0x78,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0xfc,0xfc,0x7c,0xfe,0xc6,0xc6,0xc6,0xc6, + 0xc6,0xc6,0xc6,0xc6,0xc6,0x18,0x18,0x18, + 0x3c,0x3c,0x3c,0x66,0x66,0x66,0xc3,0xc3, + 0x33,0x00,0x33,0x00,0x33,0x00,0x3b,0x00, + 0x7f,0x80,0x6d,0x80,0x6d,0x80,0x6d,0x80, + 0xcc,0xc0,0xcc,0xc0,0xcc,0xc0,0xc3,0xc3, + 0x66,0x7e,0x3c,0x18,0x3c,0x7e,0x66,0xc3, + 0xc3,0x18,0x18,0x18,0x18,0x18,0x3c,0x3c, + 0x66,0x66,0xc3,0xc3,0xfe,0xfe,0xc0,0x60, + 0x60,0x30,0x18,0x18,0x0c,0xfe,0xfe,0xe0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xe0,0x30,0x30,0x30, + 0x70,0x60,0x60,0x60,0xe0,0xc0,0xc0,0xc0, + 0xe0,0x60,0x60,0x60,0x60,0x60,0x60,0x60, + 0x60,0x60,0x60,0x60,0x60,0xe0,0x88,0xd8, + 0x70,0x70,0x20,0xfe,0xc0,0xc0,0x80,0x40, + 0x76,0xfc,0xcc,0xfc,0x7c,0x8c,0xfc,0x78, + 0xd8,0xfc,0xcc,0xcc,0xcc,0xcc,0xfc,0xd8, + 0xc0,0xc0,0xc0,0x78,0xfc,0xcc,0xc0,0xc0, + 0xcc,0xfc,0x78,0x6c,0xfc,0xcc,0xcc,0xcc, + 0xcc,0xfc,0x6c,0x0c,0x0c,0x0c,0x78,0xfc, + 0xc0,0xfc,0xfc,0xcc,0xfc,0x78,0x60,0x60, + 0x60,0x60,0x60,0x60,0xf0,0xf0,0x60,0x70, + 0x30,0x78,0xfc,0x0c,0x6c,0xfc,0xcc,0xcc, + 0xcc,0xcc,0xfc,0x6c,0xcc,0xcc,0xcc,0xcc, + 0xcc,0xec,0xfc,0xd8,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00, + 0xc0,0xc0,0xc0,0x60,0x60,0x60,0x60,0x60, + 0x60,0x60,0x60,0x60,0x60,0x00,0x60,0x60, + 0xcc,0xd8,0xd8,0xf0,0xe0,0xf0,0xd8,0xcc, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xcc,0xc0, + 0xcc,0xc0,0xcc,0xc0,0xcc,0xc0,0xcc,0xc0, + 0xee,0xc0,0xff,0xc0,0xbb,0x80,0xcc,0xcc, + 0xcc,0xcc,0xcc,0xec,0xfc,0xd8,0x78,0xfc, + 0xcc,0xcc,0xcc,0xcc,0xfc,0x78,0xc0,0xc0, + 0xc0,0xd8,0xfc,0xcc,0xcc,0xcc,0xcc,0xfc, + 0xd8,0x0c,0x0c,0x0c,0x6c,0xfc,0xcc,0xcc, + 0xcc,0xcc,0xfc,0x6c,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xe0,0xb0,0x78,0xfc,0xcc,0x1c, + 0x78,0xe0,0xfc,0x78,0x30,0x70,0x60,0x60, + 0x60,0x60,0xf0,0xf0,0x60,0x60,0x6c,0xfc, + 0xdc,0xcc,0xcc,0xcc,0xcc,0xcc,0x30,0x30, + 0x78,0x78,0x78,0xcc,0xcc,0xcc,0x24,0x24, + 0x76,0x76,0x7e,0xdb,0xdb,0xdb,0xcc,0xcc, + 0x78,0x38,0x70,0x78,0xcc,0xcc,0xe0,0xf0, + 0x30,0x30,0x38,0x78,0x78,0x48,0xcc,0xcc, + 0xcc,0xfc,0xfc,0x60,0x30,0x30,0x18,0xfc, + 0xfc,0x30,0x60,0x60,0x60,0x60,0x60,0x40, + 0x80,0x40,0x60,0x60,0x60,0x60,0x30,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0xc0,0x60,0x60,0x60, + 0x60,0x60,0x20,0x10,0x20,0x60,0x60,0x60, + 0x60,0xc0,0x98,0xfc,0x64,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0xc0,0xc0, + 0xc0,0x78,0xfc,0xec,0xe0,0xd0,0xd4,0xfc, + 0x78,0x0c,0xdc,0xfe,0x60,0x30,0x30,0xfc, + 0x30,0x60,0x64,0x7c,0x38,0xcc,0x78,0xcc, + 0xcc,0x78,0xcc,0x18,0x18,0x18,0x7e,0x18, + 0x7e,0x3c,0x66,0x66,0xc3,0xc3,0x80,0x80, + 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x80, + 0x80,0x80,0x80,0x78,0xfc,0xcc,0x1c,0x38, + 0x6c,0xcc,0xcc,0xd8,0x70,0xe0,0xcc,0xfc, + 0x78,0xd8,0xd8,0x1f,0x00,0x71,0xc0,0x6e, + 0xc0,0xdb,0x60,0xdb,0x60,0xd8,0x60,0xdb, + 0x60,0xdb,0x60,0x6e,0xc0,0x71,0xc0,0x1f, + 0x00,0xf0,0x00,0xd0,0xb0,0x70,0xb0,0x60, + 0x36,0x6c,0xd8,0x6c,0x36,0x0c,0x0c,0xfc, + 0xfc,0xe0,0xe0,0x1f,0x00,0x71,0xc0,0x7b, + 0xc0,0xdb,0x60,0xdf,0x60,0xde,0x60,0xdb, + 0x60,0xdb,0x60,0x7e,0xc0,0x71,0xc0,0x1f, + 0x00,0xf0,0xf0,0x60,0x90,0x90,0x60,0xfc, + 0xfc,0x00,0x30,0x30,0xfc,0xfc,0x30,0x30, + 0xf0,0x40,0x20,0x10,0x90,0x60,0x60,0x90, + 0x10,0x20,0x90,0x60,0xc0,0x70,0x30,0xc0, + 0xc0,0xc0,0xec,0xfc,0xdc,0xcc,0xcc,0xcc, + 0xcc,0xcc,0x36,0x36,0x36,0x36,0x36,0x36, + 0x36,0x36,0x76,0xf6,0xf6,0xf6,0xfe,0x7e, + 0xc0,0xc0,0xc0,0x60,0x40,0x40,0x40,0x40, + 0x40,0xc0,0x40,0xf8,0x00,0x70,0xd8,0xd8, + 0xd8,0x70,0xd8,0x6c,0x36,0x6c,0xd8,0x20, + 0x80,0x27,0xc0,0x12,0x80,0x12,0x80,0x09, + 0x80,0x4c,0x80,0x44,0x00,0x42,0x00,0x42, + 0x00,0xc1,0x00,0x41,0x00,0x23,0xc0,0x21, + 0x00,0x10,0x80,0x10,0x40,0x0a,0x40,0x4d, + 0x80,0x44,0x00,0x42,0x00,0x42,0x00,0xc1, + 0x00,0x41,0x00,0x20,0x80,0x27,0xc0,0x12, + 0x80,0x12,0x80,0x09,0x80,0x6c,0x80,0x94, + 0x00,0x12,0x00,0x22,0x00,0x91,0x00,0x61, + 0x00,0x78,0xfc,0xcc,0xcc,0xe0,0x70,0x30, + 0x30,0x00,0x30,0x30,0xc3,0xc3,0x7e,0x7e, + 0x24,0x3c,0x18,0x18,0x00,0x0c,0x38,0x30, + 0xc3,0xc3,0x7e,0x7e,0x24,0x3c,0x18,0x18, + 0x00,0x30,0x1c,0x0c,0xc3,0xc3,0x7e,0x7e, + 0x24,0x3c,0x18,0x18,0x00,0x66,0x3c,0x18, + 0xc3,0xc3,0x7e,0x7e,0x24,0x3c,0x18,0x18, + 0x00,0x2c,0x3e,0x1a,0xc3,0xc3,0x7e,0x7e, + 0x24,0x3c,0x18,0x18,0x00,0x6c,0x6c,0xc3, + 0xc3,0x7e,0x7e,0x24,0x3c,0x18,0x18,0x00, + 0x18,0x34,0x18,0xc7,0xe0,0xc7,0xe0,0xfe, + 0x00,0x7e,0x00,0x66,0x00,0x67,0xc0,0x37, + 0xc0,0x36,0x00,0x3e,0x00,0x1f,0xe0,0x1f, + 0xe0,0x60,0x30,0x20,0x78,0xfc,0xcc,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xcc,0xfc,0x78,0xfc, + 0xfc,0xc0,0xf8,0xf8,0xc0,0xfc,0xfc,0x00, + 0x18,0x70,0x60,0xfc,0xfc,0xc0,0xf8,0xf8, + 0xc0,0xfc,0xfc,0x00,0x60,0x38,0x18,0xfc, + 0xfc,0xc0,0xf8,0xf8,0xc0,0xfc,0xfc,0x00, + 0xcc,0x78,0x30,0xfc,0xfc,0xc0,0xf8,0xf8, + 0xc0,0xfc,0xfc,0x00,0xd8,0xd8,0x60,0x60, + 0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x30, + 0xe0,0xc0,0x60,0x60,0x60,0x60,0x60,0x60, + 0x60,0x60,0x00,0xc0,0x70,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x00,0xcc, + 0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x00,0xd8,0xd8,0x7c,0x7e,0x67, + 0x63,0x63,0xfb,0xfb,0x63,0x67,0x7e,0x7c, + 0xc6,0xce,0xce,0xde,0xf6,0xe6,0xe6,0xc6, + 0x00,0x58,0x7c,0x34,0x7c,0xfe,0xc6,0xc6, + 0xc6,0xc6,0xfe,0x7c,0x00,0x18,0x70,0x60, + 0x7c,0xfe,0xc6,0xc6,0xc6,0xc6,0xfe,0x7c, + 0x00,0x30,0x1c,0x0c,0x7c,0xfe,0xc6,0xc6, + 0xc6,0xc6,0xfe,0x7c,0x00,0xcc,0x78,0x30, + 0x7c,0xfe,0xc6,0xc6,0xc6,0xc6,0xfe,0x7c, + 0x00,0x58,0x7c,0x34,0x7c,0xfe,0xc6,0xc6, + 0xc6,0xc6,0xfe,0x7c,0x00,0x6c,0x6c,0xcc, + 0x78,0x30,0x30,0x78,0xcc,0xde,0x00,0x7f, + 0x00,0x63,0x00,0x73,0x00,0x7b,0x00,0x6b, + 0x00,0x6f,0x00,0x67,0x00,0x63,0x00,0x7f, + 0x00,0x3d,0x80,0x7c,0xfe,0xc6,0xc6,0xc6, + 0xc6,0xc6,0xc6,0x00,0x18,0x70,0x60,0x7c, + 0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00, + 0x30,0x1c,0x0c,0x7c,0xfe,0xc6,0xc6,0xc6, + 0xc6,0xc6,0xc6,0x00,0xcc,0x78,0x30,0x7c, + 0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00, + 0x6c,0x6c,0x18,0x18,0x18,0x18,0x3c,0x7e, + 0xe7,0xc3,0x00,0x30,0x1c,0x0c,0xc0,0xc0, + 0xfc,0xfe,0xc6,0xc6,0xc6,0xfe,0xfc,0xc0, + 0xc0,0xd8,0xdc,0xcc,0xcc,0xcc,0xd8,0xd8, + 0xcc,0xcc,0xfc,0x78,0x76,0xfc,0xcc,0xfc, + 0x7c,0x8c,0xfc,0x78,0x00,0x18,0x70,0x60, + 0x76,0xfc,0xcc,0xfc,0x7c,0x8c,0xfc,0x78, + 0x00,0x60,0x38,0x18,0x76,0xfc,0xcc,0xfc, + 0x7c,0x8c,0xfc,0x78,0x00,0xcc,0x78,0x30, + 0x76,0xfc,0xcc,0xfc,0x7c,0x8c,0xfc,0x78, + 0x00,0x58,0x7c,0x34,0x76,0xfc,0xcc,0xfc, + 0x7c,0x8c,0xfc,0x78,0x00,0xd8,0xd8,0x76, + 0xfc,0xcc,0xfc,0x7c,0x8c,0xfc,0x78,0x00, + 0x30,0x68,0x30,0x77,0x80,0xff,0xc0,0xcc, + 0x00,0xff,0xc0,0x7f,0xc0,0x8c,0xc0,0xff, + 0xc0,0x7b,0x80,0x60,0x30,0x20,0x78,0xfc, + 0xcc,0xc0,0xc0,0xcc,0xfc,0x78,0x78,0xfc, + 0xc0,0xfc,0xfc,0xcc,0xfc,0x78,0x00,0x18, + 0x70,0x60,0x78,0xfc,0xc0,0xfc,0xfc,0xcc, + 0xfc,0x78,0x00,0x60,0x38,0x18,0x78,0xfc, + 0xc0,0xfc,0xfc,0xcc,0xfc,0x78,0x00,0xcc, + 0x78,0x30,0x78,0xfc,0xc0,0xfc,0xfc,0xcc, + 0xfc,0x78,0x00,0xd8,0xd8,0x60,0x60,0x60, + 0x60,0x60,0x60,0x60,0x60,0x00,0x30,0xe0, + 0xc0,0x60,0x60,0x60,0x60,0x60,0x60,0x60, + 0x60,0x00,0xc0,0x70,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x00,0xcc,0x78, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x00,0xd8,0xd8,0x78,0xfc,0xcc,0xcc, + 0xcc,0xcc,0xfc,0x78,0xb0,0x60,0xd0,0xcc, + 0xcc,0xcc,0xcc,0xcc,0xec,0xfc,0xd8,0x00, + 0xb0,0xf8,0x68,0x78,0xfc,0xcc,0xcc,0xcc, + 0xcc,0xfc,0x78,0x00,0x18,0x70,0x60,0x78, + 0xfc,0xcc,0xcc,0xcc,0xcc,0xfc,0x78,0x00, + 0x60,0x38,0x18,0x78,0xfc,0xcc,0xcc,0xcc, + 0xcc,0xfc,0x78,0x00,0xcc,0x78,0x30,0x78, + 0xfc,0xcc,0xcc,0xcc,0xcc,0xfc,0x78,0x00, + 0xb0,0xf8,0x68,0x78,0xfc,0xcc,0xcc,0xcc, + 0xcc,0xfc,0x78,0x00,0xd8,0xd8,0x30,0x30, + 0x00,0xfc,0xfc,0x00,0x30,0x30,0xc0,0x78, + 0xfc,0xcc,0xec,0xdc,0xcc,0xfc,0x78,0x0c, + 0x6c,0xfc,0xdc,0xcc,0xcc,0xcc,0xcc,0xcc, + 0x00,0x18,0x70,0x60,0x6c,0xfc,0xdc,0xcc, + 0xcc,0xcc,0xcc,0xcc,0x00,0x60,0x38,0x18, + 0x6c,0xfc,0xdc,0xcc,0xcc,0xcc,0xcc,0xcc, + 0x00,0xcc,0x78,0x30,0x6c,0xfc,0xdc,0xcc, + 0xcc,0xcc,0xcc,0xcc,0x00,0xd8,0xd8,0xe0, + 0xf0,0x30,0x30,0x38,0x78,0x78,0x48,0xcc, + 0xcc,0xcc,0x00,0x60,0x38,0x18,0xc0,0xc0, + 0xc0,0xd8,0xfc,0xcc,0xcc,0xcc,0xcc,0xfc, + 0xd8,0xc0,0xc0,0xc0,0xe0,0xf0,0x30,0x30, + 0x38,0x78,0x78,0x48,0xcc,0xcc,0xcc,0x00, + 0xd8,0xd8, +}; + +BMF_FontData BMF_font_helvb12 = { + -1, -3, + 11, 12, + { + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0, 0, 0, 0, 12, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {1, 1, 0, 0, 3, 0}, + {2, 11, -1, 0, 4, 1}, + {3, 3, 0, -8, 4, 12}, + {9, 11, 1, 0, 7, 15}, + {6, 13, 0, 2, 7, 37}, + {10, 11, 0, 0, 11, 50}, + {9, 11, 0, 0, 9, 72}, + {2, 4, 0, -7, 3, 94}, + {4, 14, 0, 3, 4, 98}, + {4, 14, 1, 3, 4, 112}, + {5, 5, 0, -6, 6, 126}, + {6, 6, 0, -1, 7, 131}, + {2, 4, 0, 2, 3, 137}, + {6, 2, -1, -3, 9, 141}, + {2, 2, 0, 0, 3, 143}, + {5, 13, 1, 2, 4, 145}, + {6, 11, 0, 0, 7, 158}, + {4, 11, 0, 0, 6, 169}, + {6, 11, 0, 0, 7, 180}, + {6, 11, 0, 0, 7, 191}, + {7, 11, 0, 0, 7, 202}, + {6, 11, 0, 0, 7, 213}, + {6, 11, 0, 0, 7, 224}, + {6, 11, 0, 0, 7, 235}, + {6, 11, 0, 0, 7, 246}, + {6, 11, 0, 0, 7, 257}, + {2, 8, -1, 0, 4, 268}, + {2, 10, -1, 2, 4, 276}, + {6, 6, 0, -1, 7, 286}, + {6, 5, 0, -2, 7, 292}, + {6, 6, 0, -1, 7, 297}, + {6, 11, 0, 0, 7, 303}, + {11, 12, 0, 1, 12, 314}, + {8, 11, 0, 0, 8, 338}, + {6, 11, -1, 0, 8, 349}, + {6, 11, -1, 0, 8, 360}, + {7, 11, -1, 0, 9, 371}, + {6, 11, -1, 0, 8, 382}, + {6, 11, -1, 0, 7, 393}, + {7, 11, -1, 0, 9, 404}, + {7, 11, -1, 0, 9, 415}, + {2, 11, -2, 0, 6, 426}, + {5, 11, 0, 0, 6, 437}, + {7, 11, -1, 0, 8, 448}, + {6, 11, -1, 0, 7, 459}, + {9, 11, -1, 0, 11, 470}, + {7, 11, -1, 0, 9, 492}, + {7, 11, -1, 0, 9, 503}, + {7, 11, -1, 0, 9, 514}, + {7, 12, -1, 1, 9, 525}, + {7, 11, -1, 0, 9, 537}, + {6, 11, -1, 0, 8, 548}, + {6, 11, 0, 0, 6, 559}, + {7, 11, -1, 0, 9, 570}, + {8, 11, 0, 0, 8, 581}, + {10, 11, 0, 0, 10, 592}, + {8, 11, 0, 0, 8, 614}, + {8, 11, 0, 0, 8, 625}, + {7, 11, 0, 0, 7, 636}, + {3, 14, 0, 3, 4, 647}, + {4, 11, 0, 0, 5, 661}, + {3, 14, 0, 3, 4, 672}, + {5, 5, 0, -6, 7, 686}, + {7, 1, 0, 2, 7, 691}, + {2, 4, 0, -7, 3, 692}, + {7, 8, 0, 0, 7, 696}, + {6, 11, 0, 0, 7, 704}, + {6, 8, 0, 0, 7, 715}, + {6, 11, 0, 0, 7, 723}, + {6, 8, 0, 0, 7, 734}, + {4, 11, 0, 0, 5, 742}, + {6, 11, 0, 3, 7, 753}, + {6, 11, 0, 0, 7, 764}, + {2, 11, -1, 0, 5, 775}, + {3, 14, 0, 3, 5, 786}, + {6, 11, 0, 0, 6, 800}, + {2, 11, -1, 0, 5, 811}, + {10, 8, 0, 0, 11, 822}, + {6, 8, 0, 0, 7, 838}, + {6, 8, 0, 0, 7, 846}, + {6, 11, 0, 3, 7, 854}, + {6, 11, 0, 3, 7, 865}, + {4, 8, 0, 0, 4, 876}, + {6, 8, 0, 0, 7, 884}, + {4, 10, 0, 0, 5, 892}, + {6, 8, 0, 0, 7, 902}, + {6, 8, 0, 0, 7, 910}, + {8, 8, 0, 0, 9, 918}, + {6, 8, 0, 0, 7, 926}, + {6, 11, 0, 3, 7, 934}, + {6, 8, 0, 0, 7, 945}, + {4, 14, 0, 3, 4, 953}, + {1, 13, -1, 2, 3, 967}, + {4, 14, 0, 3, 4, 980}, + {6, 3, 0, -3, 7, 994}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {2, 11, 0, 3, 3, 997}, + {6, 10, 0, 1, 7, 1008}, + {7, 11, 0, 0, 7, 1018}, + {6, 6, 0, -3, 7, 1029}, + {8, 11, 1, 0, 7, 1035}, + {1, 13, -1, 2, 3, 1046}, + {6, 14, 0, 3, 7, 1059}, + {5, 2, 0, -9, 5, 1073}, + {11, 11, 0, 0, 12, 1075}, + {4, 7, 0, -4, 5, 1097}, + {7, 5, 0, -2, 8, 1104}, + {6, 4, -1, -3, 9, 1109}, + {3, 2, 0, -3, 4, 1113}, + {11, 11, 0, 0, 12, 1115}, + {4, 2, 0, -9, 4, 1137}, + {4, 4, -1, -7, 6, 1139}, + {6, 9, 0, -1, 7, 1143}, + {4, 6, 0, -5, 4, 1152}, + {4, 6, 0, -5, 4, 1158}, + {4, 3, -1, -9, 4, 1164}, + {6, 11, 0, 3, 7, 1167}, + {7, 14, -1, 3, 10, 1178}, + {2, 2, 0, -5, 3, 1192}, + {3, 3, -1, 3, 5, 1194}, + {2, 6, 0, -5, 4, 1197}, + {5, 7, 0, -4, 6, 1203}, + {7, 5, 0, -2, 8, 1210}, + {10, 11, 0, 0, 11, 1215}, + {10, 11, 0, 0, 11, 1237}, + {10, 11, 0, 0, 11, 1259}, + {6, 11, 0, 3, 7, 1281}, + {8, 12, 0, 0, 8, 1292}, + {8, 12, 0, 0, 8, 1304}, + {8, 12, 0, 0, 8, 1316}, + {8, 12, 0, 0, 8, 1328}, + {8, 11, 0, 0, 8, 1340}, + {8, 12, 0, 0, 8, 1351}, + {11, 11, 0, 0, 12, 1363}, + {6, 14, -1, 3, 8, 1385}, + {6, 12, -1, 0, 8, 1399}, + {6, 12, -1, 0, 8, 1411}, + {6, 12, -1, 0, 8, 1423}, + {6, 11, -1, 0, 8, 1435}, + {4, 12, -1, 0, 6, 1446}, + {4, 12, -1, 0, 6, 1458}, + {6, 12, 0, 0, 6, 1470}, + {5, 11, 0, 0, 6, 1482}, + {8, 11, 0, 0, 9, 1493}, + {7, 12, -1, 0, 9, 1504}, + {7, 12, -1, 0, 9, 1516}, + {7, 12, -1, 0, 9, 1528}, + {7, 12, -1, 0, 9, 1540}, + {7, 12, -1, 0, 9, 1552}, + {7, 11, -1, 0, 9, 1564}, + {6, 6, 0, -1, 7, 1575}, + {9, 11, 0, 0, 9, 1581}, + {7, 12, -1, 0, 9, 1603}, + {7, 12, -1, 0, 9, 1615}, + {7, 12, -1, 0, 9, 1627}, + {7, 11, -1, 0, 9, 1639}, + {8, 12, 0, 0, 8, 1650}, + {7, 11, -1, 0, 9, 1662}, + {6, 11, 0, 0, 7, 1673}, + {7, 12, 0, 0, 7, 1684}, + {7, 12, 0, 0, 7, 1696}, + {7, 12, 0, 0, 7, 1708}, + {7, 12, 0, 0, 7, 1720}, + {7, 11, 0, 0, 7, 1732}, + {7, 12, 0, 0, 7, 1743}, + {10, 8, 0, 0, 11, 1755}, + {6, 11, 0, 3, 7, 1771}, + {6, 12, 0, 0, 7, 1782}, + {6, 12, 0, 0, 7, 1794}, + {6, 12, 0, 0, 7, 1806}, + {6, 11, 0, 0, 7, 1818}, + {4, 12, 0, 0, 5, 1829}, + {4, 12, 0, 0, 5, 1841}, + {6, 12, 1, 0, 5, 1853}, + {5, 11, 1, 0, 5, 1865}, + {6, 11, 0, 0, 7, 1876}, + {6, 12, 0, 0, 7, 1887}, + {6, 12, 0, 0, 7, 1899}, + {6, 12, 0, 0, 7, 1911}, + {6, 12, 0, 0, 7, 1923}, + {6, 12, 0, 0, 7, 1935}, + {6, 11, 0, 0, 7, 1947}, + {6, 8, 0, 0, 7, 1958}, + {6, 10, 0, 1, 7, 1966}, + {6, 12, 0, 0, 7, 1976}, + {6, 12, 0, 0, 7, 1988}, + {6, 12, 0, 0, 7, 2000}, + {6, 11, 0, 0, 7, 2012}, + {6, 15, 0, 3, 7, 2023}, + {6, 14, 0, 3, 7, 2038}, + {6, 14, 0, 3, 7, 2052}, + }, + bitmap_data +}; + +#endif + diff --git a/intern/bmfont/intern/BMF_font_helvb14.cpp b/intern/bmfont/intern/BMF_font_helvb14.cpp new file mode 100644 index 00000000000..d77697e74a8 --- /dev/null +++ b/intern/bmfont/intern/BMF_font_helvb14.cpp @@ -0,0 +1,623 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BMF_FontData.h" + +#include "BMF_Settings.h" + +#if BMF_INCLUDE_HELVB14 + +static unsigned char bitmap_data[]= { + 0x00,0xc0,0xc0,0x00,0x00,0x80,0x80,0x80, + 0xc0,0xc0,0xc0,0xc0,0xc0,0x90,0xd8,0xd8, + 0xd8,0x48,0x48,0x48,0xfe,0xfe,0x24,0x24, + 0x7f,0x7f,0x12,0x12,0x12,0x10,0x10,0x38, + 0x7c,0xd6,0xd6,0x16,0x3c,0x78,0xd0,0xd6, + 0xd6,0x7c,0x38,0x10,0x30,0xc0,0x11,0xe0, + 0x19,0x20,0x09,0x20,0x0d,0xe0,0x64,0xc0, + 0xf6,0x00,0x92,0x00,0x93,0x00,0xf1,0x00, + 0x61,0x80,0x71,0x80,0xff,0x00,0xce,0x00, + 0xc6,0x00,0xcf,0x00,0x79,0x00,0x30,0x00, + 0x38,0x00,0x6c,0x00,0x6c,0x00,0x7c,0x00, + 0x38,0x00,0x80,0x40,0xc0,0xc0,0x30,0x20, + 0x60,0x40,0x40,0xc0,0xc0,0xc0,0xc0,0xc0, + 0x40,0x40,0x60,0x20,0x30,0xc0,0x40,0x60, + 0x20,0x20,0x30,0x30,0x30,0x30,0x30,0x20, + 0x20,0x60,0x40,0xc0,0xd8,0x50,0x20,0xf8, + 0x20,0x20,0x30,0x30,0x30,0xfc,0xfc,0x30, + 0x30,0x30,0x80,0x40,0x40,0xc0,0xc0,0xfe, + 0xfe,0xc0,0xc0,0x80,0x80,0xc0,0x40,0x40, + 0x60,0x20,0x20,0x30,0x10,0x10,0x30,0x78, + 0x48,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x48, + 0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0xf0,0x30,0x10,0xfc,0xfc, + 0x60,0x60,0x30,0x18,0x18,0x0c,0xcc,0xcc, + 0x78,0x30,0x30,0x78,0xcc,0xcc,0x0c,0x38, + 0x38,0x0c,0xcc,0xcc,0x78,0x30,0x18,0x18, + 0xfc,0xfc,0x98,0x58,0x58,0x38,0x38,0x38, + 0x18,0x18,0x70,0xf8,0xcc,0x0c,0x0c,0xcc, + 0xfc,0xd8,0x60,0x60,0x7c,0x7c,0x30,0x78, + 0xcc,0xcc,0xcc,0xcc,0xfc,0xd8,0xc0,0x4c, + 0x7c,0x38,0x60,0x60,0x60,0x20,0x30,0x30, + 0x10,0x18,0x08,0x0c,0xfc,0xfc,0x70,0xf8, + 0xcc,0xcc,0xcc,0x78,0x30,0x78,0xcc,0xcc, + 0x7c,0x38,0x70,0xf8,0xc8,0x0c,0x6c,0xfc, + 0xcc,0xcc,0xcc,0xcc,0x78,0x30,0xc0,0xc0, + 0x00,0x00,0x00,0x00,0xc0,0xc0,0x80,0x40, + 0x40,0xc0,0xc0,0x00,0x00,0x00,0x00,0xc0, + 0xc0,0x02,0x0e,0x3c,0xf0,0xf0,0x3c,0x0e, + 0x02,0xfc,0xfc,0x00,0x00,0xfc,0xfc,0x80, + 0xe0,0x78,0x1e,0x1e,0x78,0xe0,0x80,0x30, + 0x30,0x00,0x30,0x30,0x18,0x18,0x0c,0xcc, + 0xcc,0x7c,0x38,0x0f,0x80,0x38,0x60,0x60, + 0x00,0x4d,0xc0,0xd3,0x20,0x93,0x30,0x91, + 0x10,0x91,0x90,0xc9,0x90,0x46,0x90,0x60, + 0x30,0x30,0x20,0x1c,0xc0,0x07,0x80,0xe1, + 0xc0,0x61,0x80,0x7f,0x80,0x7f,0x80,0x33, + 0x00,0x33,0x00,0x33,0x00,0x1e,0x00,0x1e, + 0x00,0x1e,0x00,0x0c,0x00,0x0c,0x00,0xfc, + 0xfe,0xc7,0xc3,0xc7,0xfe,0xfc,0xc6,0xc3, + 0xc7,0xfe,0xfc,0x3c,0x7e,0x63,0xc3,0xc0, + 0xc0,0xc0,0xc0,0xc3,0x63,0x7e,0x3c,0xfc, + 0xfe,0xc6,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3, + 0xc6,0xfe,0xfc,0xfe,0xfe,0xc0,0xc0,0xc0, + 0xfe,0xfe,0xc0,0xc0,0xc0,0xfe,0xfe,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xfc,0xfc,0xc0,0xc0, + 0xc0,0xfe,0xfe,0x3e,0x80,0x7f,0x80,0x63, + 0x80,0xc1,0x80,0xc7,0x80,0xc7,0x80,0xc0, + 0x00,0xc0,0x00,0xc1,0x80,0x63,0x80,0x7f, + 0x00,0x3e,0x00,0xc3,0xc3,0xc3,0xc3,0xc3, + 0xff,0xff,0xc3,0xc3,0xc3,0xc3,0xc3,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0x78,0xfc,0xcc,0xcc,0xcc, + 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0xc3, + 0x80,0xc7,0x00,0xc6,0x00,0xcc,0x00,0xdc, + 0x00,0xf8,0x00,0xf0,0x00,0xd8,0x00,0xcc, + 0x00,0xce,0x00,0xc7,0x00,0xc3,0x00,0xfe, + 0xfe,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xcc,0xc0,0xcc,0xc0,0xcc, + 0xc0,0xde,0xc0,0xde,0xc0,0xd2,0xc0,0xd2, + 0xc0,0xf3,0xc0,0xf3,0xc0,0xe1,0xc0,0xe1, + 0xc0,0xe1,0xc0,0xc3,0xc7,0xc7,0xcf,0xcf, + 0xdb,0xdb,0xf3,0xf3,0xe3,0xe3,0xc3,0x3e, + 0x00,0x7f,0x00,0x63,0x00,0xc1,0x80,0xc1, + 0x80,0xc1,0x80,0xc1,0x80,0xc1,0x80,0xc1, + 0x80,0x63,0x00,0x7f,0x00,0x3e,0x00,0xc0, + 0xc0,0xc0,0xc0,0xf8,0xfc,0xce,0xc6,0xc6, + 0xce,0xfc,0xf8,0x01,0x80,0x3d,0x80,0x7f, + 0x00,0x67,0x00,0xcd,0x80,0xcd,0x80,0xc1, + 0x80,0xc1,0x80,0xc1,0x80,0xc1,0x80,0x63, + 0x00,0x7f,0x00,0x3e,0x00,0xc3,0xc3,0xc3, + 0xc3,0xc7,0xfe,0xfe,0xc7,0xc3,0xc7,0xfe, + 0xfc,0x3c,0x7e,0xe7,0xc3,0x07,0x1e,0x78, + 0xe0,0xc3,0xe7,0x7e,0x3c,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff, + 0xff,0x3c,0x7e,0xe7,0xc3,0xc3,0xc3,0xc3, + 0xc3,0xc3,0xc3,0xc3,0xc3,0x18,0x18,0x18, + 0x3c,0x3c,0x24,0x66,0x66,0x66,0xc3,0xc3, + 0xc3,0x30,0xc0,0x30,0xc0,0x30,0xc0,0x39, + 0xc0,0x79,0xe0,0x69,0x60,0x6f,0x60,0x6f, + 0x60,0xc6,0x30,0xc6,0x30,0xc6,0x30,0xc6, + 0x30,0xe3,0x80,0x63,0x00,0x63,0x00,0x36, + 0x00,0x36,0x00,0x1c,0x00,0x1c,0x00,0x36, + 0x00,0x36,0x00,0x63,0x00,0x63,0x00,0xe3, + 0x80,0x0c,0x00,0x0c,0x00,0x0c,0x00,0x0c, + 0x00,0x0c,0x00,0x1e,0x00,0x1e,0x00,0x33, + 0x00,0x33,0x00,0x61,0x80,0x61,0x80,0xe1, + 0xc0,0xff,0xff,0x60,0x70,0x30,0x18,0x18, + 0x0c,0x0e,0x06,0xff,0xff,0xe0,0xe0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xe0,0xe0,0x10,0x10,0x30,0x20, + 0x20,0x60,0x40,0x40,0xc0,0x80,0x80,0xe0, + 0xe0,0x60,0x60,0x60,0x60,0x60,0x60,0x60, + 0x60,0x60,0x60,0x60,0xe0,0xe0,0xcc,0xcc, + 0x48,0x78,0x78,0x30,0x30,0xfe,0xc0,0xc0, + 0x80,0x40,0x6c,0xfc,0xcc,0xcc,0x7c,0x1c, + 0xcc,0xfc,0x78,0xd8,0xfc,0xee,0xc6,0xc6, + 0xc6,0xee,0xfc,0xd8,0xc0,0xc0,0xc0,0x38, + 0x7c,0xec,0xc0,0xc0,0xc0,0xec,0x7c,0x38, + 0x36,0x7e,0xee,0xc6,0xc6,0xc6,0xee,0x7e, + 0x36,0x06,0x06,0x06,0x38,0x7c,0xcc,0xc0, + 0xfc,0xcc,0xcc,0x78,0x30,0x60,0x60,0x60, + 0x60,0x60,0x60,0x60,0xf0,0xf0,0x60,0x70, + 0x30,0x78,0xfc,0xc6,0x36,0x7e,0xee,0xc6, + 0xc6,0xc6,0xee,0x7e,0x36,0xc6,0xc6,0xc6, + 0xc6,0xc6,0xc6,0xe6,0xfe,0xdc,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0x00,0xc0,0xc0,0xc0,0xe0,0x60, + 0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60, + 0x60,0x00,0x60,0x60,0xce,0xcc,0xd8,0xd8, + 0xf0,0xf0,0xd8,0xd8,0xcc,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xcc,0xc0,0xcc,0xc0, + 0xcc,0xc0,0xcc,0xc0,0xcc,0xc0,0xcc,0xc0, + 0xcc,0xc0,0xff,0xc0,0xdb,0x80,0xc6,0xc6, + 0xc6,0xc6,0xc6,0xc6,0xe6,0xfe,0xdc,0x38, + 0x7c,0xee,0xc6,0xc6,0xc6,0xee,0x7c,0x38, + 0xc0,0xc0,0xc0,0xd8,0xfc,0xee,0xc6,0xc6, + 0xc6,0xee,0xfc,0xd8,0x06,0x06,0x06,0x36, + 0x7e,0xee,0xc6,0xc6,0xc6,0xee,0x7e,0x36, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xe0,0xf8, + 0xd0,0x78,0xfc,0xcc,0x1c,0x78,0xe0,0xcc, + 0xfc,0x78,0x30,0x70,0x60,0x60,0x60,0x60, + 0x60,0xf0,0xf0,0x60,0x60,0x76,0xfe,0xce, + 0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x30,0x30, + 0x30,0x78,0x78,0x48,0xcc,0xcc,0xcc,0x33, + 0x00,0x33,0x00,0x33,0x00,0x73,0x80,0x7f, + 0x80,0x4c,0x80,0x4c,0x80,0xcc,0xc0,0xcc, + 0xc0,0xc6,0xee,0x6c,0x38,0x38,0x38,0x6c, + 0xee,0xc6,0x60,0x70,0x10,0x18,0x38,0x38, + 0x2c,0x6c,0x6c,0xc6,0xc6,0xc6,0xfc,0xfc, + 0x60,0x60,0x30,0x18,0x18,0xfc,0xfc,0x30, + 0x70,0x60,0x60,0x60,0x60,0x60,0xc0,0x60, + 0x60,0x60,0x60,0x60,0x70,0x30,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0xc0,0xe0,0x60, + 0x60,0x60,0x60,0x60,0x30,0x60,0x60,0x60, + 0x60,0x60,0xe0,0xc0,0x98,0xfc,0x64,0xc0, + 0xc0,0xc0,0xc0,0xc0,0x80,0x80,0x80,0x00, + 0x00,0xc0,0xc0,0x20,0x20,0x38,0x7c,0xec, + 0xe0,0xd0,0xd0,0xdc,0x7c,0x38,0x08,0x08, + 0xcc,0xfe,0x70,0x30,0x30,0xf8,0x60,0xc0, + 0xcc,0xcc,0x7c,0x38,0xcc,0x78,0xcc,0xcc, + 0xcc,0xcc,0x78,0xcc,0x18,0x18,0x18,0x7e, + 0x18,0x7e,0x18,0x3c,0x24,0x66,0x42,0xc3, + 0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00, + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x38, + 0x7c,0x6c,0x0c,0x18,0x7c,0xe6,0xc6,0xce, + 0x7c,0x30,0x60,0x6c,0x7c,0x38,0xd8,0xd8, + 0x1e,0x00,0x33,0x00,0x40,0x80,0xde,0xc0, + 0xb3,0x40,0xa0,0x40,0xa0,0x40,0xb3,0x40, + 0xde,0xc0,0x40,0x80,0x33,0x00,0x1e,0x00, + 0xf0,0x00,0xd0,0xb0,0x70,0xb0,0x60,0x24, + 0x6c,0xd8,0xd8,0x6c,0x24,0x06,0x06,0x06, + 0xfe,0xfe,0xe0,0xe0,0x1e,0x00,0x33,0x00, + 0x40,0x80,0xd2,0xc0,0x96,0x40,0x9c,0x40, + 0x92,0x40,0x92,0x40,0xdc,0xc0,0x40,0x80, + 0x33,0x00,0x1e,0x00,0xf0,0x60,0x90,0x90, + 0x90,0x60,0xfc,0xfc,0x00,0x30,0x30,0x30, + 0xfc,0xfc,0x30,0x30,0x30,0xf0,0x80,0x40, + 0x20,0x90,0xb0,0x60,0x60,0xb0,0x10,0x60, + 0x30,0x90,0x60,0xc0,0x60,0xc0,0xc0,0xc0, + 0xf6,0xfe,0xce,0xc6,0xc6,0xc6,0xc6,0xc6, + 0xc6,0x14,0x14,0x14,0x14,0x14,0x14,0x14, + 0x14,0x74,0xf4,0xf4,0xf4,0xf4,0x74,0x3e, + 0xc0,0xc0,0xc0,0x60,0x40,0x20,0x20,0x20, + 0x20,0x20,0xe0,0x20,0xf0,0x00,0x60,0x90, + 0x90,0x90,0x60,0x90,0xd8,0x6c,0x6c,0xd8, + 0x90,0x20,0x40,0x10,0x40,0x13,0xe0,0x0a, + 0x40,0x09,0x40,0x24,0xc0,0x24,0x40,0x22, + 0x00,0x22,0x00,0x21,0x00,0xe1,0x00,0x20, + 0x80,0x21,0xe0,0x11,0x00,0x10,0x80,0x08, + 0x40,0x09,0x20,0x25,0x60,0x24,0xc0,0x22, + 0x00,0x22,0x00,0x21,0x00,0xe1,0x00,0x20, + 0x80,0x20,0x40,0x10,0x40,0x13,0xe0,0x0a, + 0x40,0x09,0x40,0x64,0xc0,0xb4,0x40,0x12, + 0x00,0x62,0x00,0x31,0x00,0x91,0x00,0x60, + 0x80,0x70,0xf8,0xcc,0xcc,0xc0,0x60,0x60, + 0x30,0x30,0x00,0x30,0x30,0xe1,0xc0,0x61, + 0x80,0x7f,0x80,0x3f,0x00,0x33,0x00,0x33, + 0x00,0x12,0x00,0x1e,0x00,0x1e,0x00,0x0c, + 0x00,0x0c,0x00,0x00,0x00,0x0c,0x00,0x18, + 0x00,0xe1,0xc0,0x61,0x80,0x7f,0x80,0x3f, + 0x00,0x33,0x00,0x33,0x00,0x12,0x00,0x1e, + 0x00,0x1e,0x00,0x0c,0x00,0x0c,0x00,0x00, + 0x00,0x0c,0x00,0x06,0x00,0xe1,0xc0,0x61, + 0x80,0x7f,0x80,0x3f,0x00,0x33,0x00,0x33, + 0x00,0x12,0x00,0x1e,0x00,0x1e,0x00,0x0c, + 0x00,0x0c,0x00,0x00,0x00,0x36,0x00,0x1c, + 0x00,0xe1,0xc0,0x61,0x80,0x7f,0x80,0x3f, + 0x00,0x33,0x00,0x33,0x00,0x12,0x00,0x1e, + 0x00,0x1e,0x00,0x0c,0x00,0x0c,0x00,0x00, + 0x00,0x16,0x00,0x0d,0x00,0xe1,0xc0,0x61, + 0x80,0x7f,0x80,0x3f,0x00,0x33,0x00,0x33, + 0x00,0x12,0x00,0x1e,0x00,0x1e,0x00,0x0c, + 0x00,0x0c,0x00,0x00,0x00,0x36,0x00,0x36, + 0x00,0xe1,0xc0,0x61,0x80,0x7f,0x80,0x3f, + 0x00,0x33,0x00,0x33,0x00,0x12,0x00,0x1e, + 0x00,0x1e,0x00,0x0c,0x00,0x0c,0x00,0x0c, + 0x00,0x0a,0x00,0x06,0x00,0xe3,0xf8,0x63, + 0xf8,0x7f,0x00,0x7f,0x00,0x33,0x00,0x33, + 0xf8,0x3b,0xf8,0x1b,0x00,0x1b,0x00,0x1f, + 0x00,0x0f,0xf8,0x0f,0xf8,0x18,0x0c,0x08, + 0x3c,0x7e,0x63,0xc3,0xc0,0xc0,0xc0,0xc0, + 0xc3,0x63,0x7e,0x3c,0xfe,0xfe,0xc0,0xc0, + 0xc0,0xfe,0xfe,0xc0,0xc0,0xfe,0xfe,0x00, + 0x18,0x30,0xfe,0xfe,0xc0,0xc0,0xc0,0xfe, + 0xfe,0xc0,0xc0,0xfe,0xfe,0x00,0x18,0x0c, + 0xfe,0xfe,0xc0,0xc0,0xc0,0xfe,0xfe,0xc0, + 0xc0,0xfe,0xfe,0x00,0x6c,0x38,0xfe,0xfe, + 0xc0,0xc0,0xc0,0xfe,0xfe,0xc0,0xc0,0xfe, + 0xfe,0x00,0x6c,0x6c,0x60,0x60,0x60,0x60, + 0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00, + 0x60,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0xc0,0x60, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x00,0xd8,0x70,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x00,0xd8,0xd8,0x7e,0x00,0x7f,0x00, + 0x63,0x00,0x61,0x80,0x61,0x80,0xf9,0x80, + 0xf9,0x80,0x61,0x80,0x61,0x80,0x63,0x00, + 0x7f,0x00,0x7e,0x00,0xc3,0xc7,0xc7,0xcf, + 0xcb,0xdb,0xd3,0xf3,0xe3,0xe3,0xc3,0x00, + 0x2c,0x1a,0x3e,0x00,0x7f,0x00,0x63,0x00, + 0xc1,0x80,0xc1,0x80,0xc1,0x80,0xc1,0x80, + 0xc1,0x80,0x63,0x00,0x7f,0x00,0x3e,0x00, + 0x00,0x00,0x0c,0x00,0x18,0x00,0x3e,0x00, + 0x7f,0x00,0x63,0x00,0xc1,0x80,0xc1,0x80, + 0xc1,0x80,0xc1,0x80,0xc1,0x80,0x63,0x00, + 0x7f,0x00,0x3e,0x00,0x00,0x00,0x18,0x00, + 0x0c,0x00,0x3e,0x00,0x7f,0x00,0x63,0x00, + 0xc1,0x80,0xc1,0x80,0xc1,0x80,0xc1,0x80, + 0xc1,0x80,0x63,0x00,0x7f,0x00,0x3e,0x00, + 0x00,0x00,0x36,0x00,0x1c,0x00,0x3e,0x00, + 0x7f,0x00,0x63,0x00,0xc1,0x80,0xc1,0x80, + 0xc1,0x80,0xc1,0x80,0xc1,0x80,0x63,0x00, + 0x7f,0x00,0x3e,0x00,0x00,0x00,0x2c,0x00, + 0x1a,0x00,0x3e,0x00,0x7f,0x00,0x63,0x00, + 0xc1,0x80,0xc1,0x80,0xc1,0x80,0xc1,0x80, + 0xc1,0x80,0x63,0x00,0x7f,0x00,0x3e,0x00, + 0x00,0x00,0x36,0x00,0x36,0x00,0x84,0xcc, + 0x78,0x30,0x30,0x78,0xcc,0x84,0xbe,0x00, + 0xff,0x00,0x63,0x00,0xf1,0x80,0xd1,0x80, + 0xc9,0x80,0xc9,0x80,0xc5,0x80,0xc7,0x80, + 0x63,0x00,0x7f,0x80,0x3e,0x80,0x3c,0x7e, + 0xe7,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3, + 0xc3,0x00,0x18,0x30,0x3c,0x7e,0xe7,0xc3, + 0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x00, + 0x18,0x0c,0x3c,0x7e,0xe7,0xc3,0xc3,0xc3, + 0xc3,0xc3,0xc3,0xc3,0xc3,0x00,0x6c,0x38, + 0x3c,0x7e,0xe7,0xc3,0xc3,0xc3,0xc3,0xc3, + 0xc3,0xc3,0xc3,0x00,0x6c,0x6c,0x0c,0x00, + 0x0c,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00, + 0x1e,0x00,0x1e,0x00,0x33,0x00,0x33,0x00, + 0x61,0x80,0xe1,0xc0,0x00,0x00,0x0c,0x00, + 0x06,0x00,0xc0,0xc0,0xf8,0xfc,0xce,0xc6, + 0xc6,0xce,0xfc,0xf8,0xc0,0xc0,0xd8,0xdc, + 0xc6,0xc6,0xc6,0xdc,0xd8,0xcc,0xcc,0xcc, + 0x7c,0x38,0x6c,0xfc,0xcc,0xcc,0x7c,0x1c, + 0xcc,0xfc,0x78,0x00,0x30,0x60,0x6c,0xfc, + 0xcc,0xcc,0x7c,0x1c,0xcc,0xfc,0x78,0x00, + 0x30,0x18,0x6c,0xfc,0xcc,0xcc,0x7c,0x1c, + 0xcc,0xfc,0x78,0x00,0xd8,0x70,0x6c,0xfc, + 0xcc,0xcc,0x7c,0x1c,0xcc,0xfc,0x78,0x00, + 0x58,0x34,0x6c,0xfc,0xcc,0xcc,0x7c,0x1c, + 0xcc,0xfc,0x78,0x00,0xd8,0xd8,0x6c,0xfc, + 0xcc,0xcc,0x7c,0x1c,0xcc,0xfc,0x78,0x00, + 0x30,0x28,0x18,0x73,0x80,0xff,0xc0,0xcc, + 0xc0,0xcc,0x00,0x7f,0xc0,0x1c,0xc0,0xcc, + 0xc0,0xff,0xc0,0x73,0x80,0x30,0x18,0x10, + 0x38,0x7c,0xec,0xc0,0xc0,0xc0,0xec,0x7c, + 0x38,0x38,0x7c,0xcc,0xc0,0xfc,0xcc,0xcc, + 0x78,0x30,0x00,0x30,0x60,0x38,0x7c,0xcc, + 0xc0,0xfc,0xcc,0xcc,0x78,0x30,0x00,0x30, + 0x18,0x38,0x7c,0xcc,0xc0,0xfc,0xcc,0xcc, + 0x78,0x30,0x00,0x6c,0x38,0x38,0x7c,0xcc, + 0xc0,0xfc,0xcc,0xcc,0x78,0x30,0x00,0xd8, + 0xd8,0x60,0x60,0x60,0x60,0x60,0x60,0x60, + 0x60,0x60,0x00,0x60,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0xc0, + 0x60,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x00,0xd8,0x70,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x00,0xd8, + 0xd8,0x38,0x7c,0xee,0xc6,0xc6,0xc6,0xee, + 0x7c,0x3c,0xf8,0x38,0x6c,0xc6,0xc6,0xc6, + 0xc6,0xc6,0xc6,0xe6,0xfe,0xdc,0x00,0x58, + 0x34,0x38,0x7c,0xee,0xc6,0xc6,0xc6,0xee, + 0x7c,0x38,0x00,0x18,0x30,0x38,0x7c,0xee, + 0xc6,0xc6,0xc6,0xee,0x7c,0x38,0x00,0x30, + 0x18,0x38,0x7c,0xee,0xc6,0xc6,0xc6,0xee, + 0x7c,0x38,0x00,0x6c,0x38,0x38,0x7c,0xee, + 0xc6,0xc6,0xc6,0xee,0x7c,0x38,0x00,0x58, + 0x34,0x38,0x7c,0xee,0xc6,0xc6,0xc6,0xee, + 0x7c,0x38,0x00,0x6c,0x6c,0x30,0x30,0x00, + 0xfc,0xfc,0x00,0x30,0x30,0xb8,0x7c,0xee, + 0xe6,0xd6,0xce,0xee,0x7c,0x3a,0x76,0xfe, + 0xce,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00, + 0x18,0x30,0x76,0xfe,0xce,0xc6,0xc6,0xc6, + 0xc6,0xc6,0xc6,0x00,0x30,0x18,0x76,0xfe, + 0xce,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00, + 0x6c,0x38,0x76,0xfe,0xce,0xc6,0xc6,0xc6, + 0xc6,0xc6,0xc6,0x00,0x6c,0x6c,0x60,0x70, + 0x10,0x18,0x38,0x38,0x2c,0x6c,0x6c,0xc6, + 0xc6,0xc6,0x00,0x30,0x18,0xc0,0xc0,0xc0, + 0xd8,0xfc,0xee,0xc6,0xc6,0xc6,0xee,0xfc, + 0xd8,0xc0,0xc0,0xc0,0x60,0x70,0x10,0x18, + 0x38,0x38,0x2c,0x6c,0x6c,0xc6,0xc6,0xc6, + 0x00,0x6c,0x6c, +}; + +BMF_FontData BMF_font_helvb14 = { + -2, -3, + 12, 14, + { + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0, 0, 0, 0, 12, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {1, 1, 0, 0, 3, 0}, + {2, 12, -1, 0, 4, 1}, + {5, 4, 0, -8, 6, 13}, + {8, 12, 1, 0, 7, 17}, + {7, 15, 0, 2, 7, 29}, + {11, 11, 0, 0, 12, 44}, + {9, 12, 0, 0, 9, 66}, + {2, 4, -1, -8, 4, 90}, + {4, 15, 0, 3, 4, 94}, + {4, 15, 1, 3, 4, 109}, + {5, 6, 0, -6, 5, 124}, + {6, 8, -1, 0, 8, 130}, + {2, 5, 0, 3, 3, 138}, + {7, 2, 0, -3, 8, 143}, + {2, 2, 0, 0, 3, 145}, + {4, 11, 0, 0, 4, 147}, + {6, 12, 0, 0, 7, 158}, + {4, 12, 0, 0, 7, 170}, + {6, 12, 0, 0, 7, 182}, + {6, 12, 0, 0, 7, 194}, + {6, 12, 0, 0, 7, 206}, + {6, 12, 0, 0, 7, 218}, + {6, 12, 0, 0, 7, 230}, + {6, 12, 0, 0, 7, 242}, + {6, 12, 0, 0, 7, 254}, + {6, 12, 0, 0, 7, 266}, + {2, 8, -1, 0, 4, 278}, + {2, 11, -1, 3, 4, 286}, + {7, 8, 0, 0, 8, 297}, + {6, 6, -1, -1, 8, 305}, + {7, 8, 0, 0, 8, 311}, + {6, 12, -1, 0, 8, 319}, + {12, 14, 0, 2, 13, 331}, + {10, 12, 1, 0, 9, 359}, + {8, 12, 0, 0, 9, 383}, + {8, 12, 0, 0, 9, 395}, + {8, 12, 0, 0, 9, 407}, + {7, 12, 0, 0, 8, 419}, + {7, 12, -1, 0, 8, 431}, + {9, 12, 0, 0, 10, 443}, + {8, 12, 0, 0, 9, 467}, + {2, 12, -1, 0, 5, 479}, + {6, 12, 0, 0, 7, 491}, + {9, 12, -1, 0, 10, 503}, + {7, 12, -1, 0, 8, 527}, + {10, 12, 0, 0, 11, 539}, + {8, 12, 0, 0, 9, 563}, + {9, 12, 0, 0, 10, 575}, + {7, 12, -1, 0, 9, 599}, + {9, 13, 0, 1, 10, 611}, + {8, 12, 0, 0, 9, 637}, + {8, 12, 0, 0, 9, 649}, + {8, 12, 0, 0, 9, 661}, + {8, 12, 0, 0, 9, 673}, + {8, 12, 0, 0, 9, 685}, + {12, 12, 0, 0, 13, 697}, + {9, 12, 0, 0, 10, 721}, + {10, 12, 1, 0, 9, 745}, + {8, 12, 0, 0, 9, 769}, + {3, 15, 0, 3, 4, 781}, + {4, 11, 0, 0, 4, 796}, + {3, 15, 0, 3, 4, 807}, + {6, 7, -1, -4, 8, 822}, + {7, 1, 0, 3, 7, 829}, + {2, 4, -1, -8, 4, 830}, + {6, 9, 0, 0, 7, 834}, + {7, 12, 0, 0, 8, 843}, + {6, 9, 0, 0, 7, 855}, + {7, 12, 0, 0, 8, 864}, + {6, 9, 0, 0, 7, 876}, + {4, 12, 0, 0, 5, 885}, + {7, 12, 0, 3, 8, 897}, + {7, 12, 0, 0, 8, 909}, + {2, 12, 0, 0, 3, 921}, + {3, 15, 1, 3, 3, 933}, + {7, 12, 0, 0, 7, 948}, + {2, 12, 0, 0, 3, 960}, + {10, 9, 0, 0, 11, 972}, + {7, 9, 0, 0, 8, 990}, + {7, 9, 0, 0, 8, 999}, + {7, 12, 0, 3, 8, 1008}, + {7, 12, 0, 3, 8, 1020}, + {5, 9, 0, 0, 5, 1032}, + {6, 9, 0, 0, 7, 1041}, + {4, 11, 0, 0, 5, 1050}, + {7, 9, 0, 0, 8, 1061}, + {6, 9, 0, 0, 7, 1070}, + {10, 9, 0, 0, 11, 1079}, + {7, 9, 0, 0, 8, 1097}, + {7, 12, 0, 3, 8, 1106}, + {6, 9, 0, 0, 7, 1118}, + {4, 15, 0, 3, 5, 1127}, + {1, 15, -1, 3, 4, 1142}, + {4, 15, 0, 3, 5, 1157}, + {6, 3, -1, -3, 8, 1172}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {2, 12, -1, 3, 4, 1175}, + {6, 13, 0, 2, 7, 1187}, + {7, 12, 0, 0, 7, 1200}, + {6, 8, 0, -2, 7, 1212}, + {8, 12, 1, 0, 7, 1220}, + {1, 15, -1, 3, 4, 1232}, + {7, 15, 0, 3, 7, 1247}, + {5, 2, 1, -10, 4, 1262}, + {10, 12, 0, 0, 10, 1264}, + {4, 7, 0, -5, 5, 1288}, + {6, 6, 0, -1, 7, 1295}, + {7, 5, 0, -2, 8, 1301}, + {3, 2, 0, -3, 4, 1306}, + {10, 12, 0, 0, 10, 1308}, + {4, 1, 0, -11, 4, 1332}, + {4, 5, 0, -7, 5, 1333}, + {6, 11, -1, 0, 8, 1338}, + {4, 7, 0, -5, 4, 1349}, + {4, 7, 0, -5, 4, 1356}, + {3, 2, -1, -10, 4, 1363}, + {7, 12, 0, 3, 8, 1365}, + {7, 15, 0, 3, 7, 1377}, + {2, 2, 0, -5, 3, 1392}, + {3, 3, 0, 3, 4, 1394}, + {3, 7, 0, -5, 4, 1397}, + {4, 7, 0, -5, 5, 1404}, + {6, 6, 0, -1, 7, 1411}, + {11, 12, 1, 0, 11, 1417}, + {11, 12, 1, 0, 11, 1441}, + {11, 12, 0, 0, 11, 1465}, + {6, 12, -1, 3, 8, 1489}, + {10, 14, 1, 0, 9, 1501}, + {10, 14, 1, 0, 9, 1529}, + {10, 14, 1, 0, 9, 1557}, + {10, 14, 1, 0, 9, 1585}, + {10, 14, 1, 0, 9, 1613}, + {10, 14, 1, 0, 9, 1641}, + {13, 12, 1, 0, 13, 1669}, + {8, 15, 0, 3, 9, 1693}, + {7, 14, 0, 0, 8, 1708}, + {7, 14, 0, 0, 8, 1722}, + {7, 14, 0, 0, 8, 1736}, + {7, 14, 0, 0, 8, 1750}, + {3, 14, 0, 0, 5, 1764}, + {3, 14, -1, 0, 5, 1778}, + {5, 14, 1, 0, 5, 1792}, + {5, 14, 1, 0, 5, 1806}, + {9, 12, 1, 0, 9, 1820}, + {8, 14, 0, 0, 9, 1844}, + {9, 14, 0, 0, 10, 1858}, + {9, 14, 0, 0, 10, 1886}, + {9, 14, 0, 0, 10, 1914}, + {9, 14, 0, 0, 10, 1942}, + {9, 14, 0, 0, 10, 1970}, + {6, 8, -1, 0, 8, 1998}, + {9, 12, 0, 0, 10, 2006}, + {8, 14, 0, 0, 9, 2030}, + {8, 14, 0, 0, 9, 2044}, + {8, 14, 0, 0, 9, 2058}, + {8, 14, 0, 0, 9, 2072}, + {10, 14, 1, 0, 9, 2086}, + {7, 12, -1, 0, 9, 2114}, + {7, 12, 0, 0, 8, 2126}, + {6, 12, 0, 0, 7, 2138}, + {6, 12, 0, 0, 7, 2150}, + {6, 12, 0, 0, 7, 2162}, + {6, 12, 0, 0, 7, 2174}, + {6, 12, 0, 0, 7, 2186}, + {6, 13, 0, 0, 7, 2198}, + {10, 9, 0, 0, 11, 2211}, + {6, 12, 0, 3, 7, 2229}, + {6, 12, 0, 0, 7, 2241}, + {6, 12, 0, 0, 7, 2253}, + {6, 12, 0, 0, 7, 2265}, + {6, 12, 0, 0, 7, 2277}, + {3, 12, 1, 0, 3, 2289}, + {3, 12, 0, 0, 3, 2301}, + {5, 12, 2, 0, 3, 2313}, + {5, 12, 2, 0, 3, 2325}, + {7, 12, 0, 0, 8, 2337}, + {7, 12, 0, 0, 8, 2349}, + {7, 12, 0, 0, 8, 2361}, + {7, 12, 0, 0, 8, 2373}, + {7, 12, 0, 0, 8, 2385}, + {7, 12, 0, 0, 8, 2397}, + {7, 12, 0, 0, 8, 2409}, + {6, 8, -1, 0, 8, 2421}, + {7, 9, 0, 0, 8, 2429}, + {7, 12, 0, 0, 8, 2438}, + {7, 12, 0, 0, 8, 2450}, + {7, 12, 0, 0, 8, 2462}, + {7, 12, 0, 0, 8, 2474}, + {7, 15, 0, 3, 8, 2486}, + {7, 15, 0, 3, 8, 2501}, + {7, 15, 0, 3, 8, 2516}, + }, + bitmap_data +}; + +#endif + diff --git a/intern/bmfont/intern/BMF_font_helvb8.cpp b/intern/bmfont/intern/BMF_font_helvb8.cpp new file mode 100644 index 00000000000..0dfefbeda95 --- /dev/null +++ b/intern/bmfont/intern/BMF_font_helvb8.cpp @@ -0,0 +1,455 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BMF_FontData.h" + +#include "BMF_Settings.h" + +#if BMF_INCLUDE_HELVB8 + +static unsigned char bitmap_data[]= { + 0x00,0x80,0x00,0x80,0x80,0x80,0x80,0xa0, + 0xa0,0xa0,0x50,0xf8,0x50,0xf8,0x50,0x40, + 0xe0,0x10,0x60,0x80,0x70,0x20,0x5c,0x54, + 0x2c,0xd0,0xa8,0xe8,0x58,0xb0,0xa8,0x48, + 0xa0,0x40,0x80,0x80,0x80,0x40,0x80,0x80, + 0x80,0x80,0x80,0x40,0x80,0x40,0x40,0x40, + 0x40,0x40,0x80,0x40,0xe0,0x40,0x20,0x20, + 0xf8,0x20,0x20,0x80,0x40,0x40,0xf0,0x80, + 0x80,0x80,0x80,0x80,0x40,0x40,0x40,0x60, + 0x90,0x90,0x90,0x90,0x60,0x40,0x40,0x40, + 0x40,0xc0,0x40,0xf0,0x40,0x20,0x10,0x90, + 0x60,0xc0,0x20,0x20,0xc0,0x20,0xc0,0x20, + 0x20,0xf0,0x60,0x20,0x20,0xc0,0x20,0x20, + 0xc0,0x80,0xe0,0x60,0x90,0x90,0xe0,0x80, + 0x70,0x40,0x40,0x40,0x20,0x10,0xf0,0x60, + 0x90,0x90,0x60,0x90,0x60,0x60,0x10,0x70, + 0x90,0x90,0x60,0x80,0x00,0x00,0x80,0x80, + 0x40,0x40,0x00,0x00,0x40,0x20,0x40,0x80, + 0x40,0x20,0xe0,0x00,0xe0,0x80,0x40,0x20, + 0x40,0x80,0x40,0x00,0x40,0x20,0xc0,0x78, + 0x80,0x9e,0xa5,0x99,0x41,0x3e,0x88,0x88, + 0x70,0x50,0x20,0x20,0xe0,0x90,0x90,0xe0, + 0x90,0xe0,0x70,0x88,0x80,0x80,0x88,0x70, + 0xf0,0x88,0x88,0x88,0x88,0xf0,0xf0,0x80, + 0x80,0xe0,0x80,0xf0,0x80,0x80,0x80,0xe0, + 0x80,0xf0,0x70,0x88,0x88,0x98,0x80,0x70, + 0x88,0x88,0x88,0xf8,0x88,0x88,0x80,0x80, + 0x80,0x80,0x80,0x80,0x40,0xa0,0x20,0x20, + 0x20,0x20,0x90,0x90,0xe0,0xc0,0xa0,0x90, + 0xe0,0x80,0x80,0x80,0x80,0x80,0xa8,0xa8, + 0xa8,0xa8,0xd8,0x88,0x88,0x98,0xa8,0xa8, + 0xc8,0x88,0x70,0x88,0x88,0x88,0x88,0x70, + 0x80,0x80,0xe0,0x90,0x90,0xe0,0x10,0x20, + 0x70,0x88,0x88,0x88,0x88,0x70,0x90,0x90, + 0xe0,0x90,0x90,0xe0,0xe0,0x10,0x10,0xe0, + 0x80,0x70,0x40,0x40,0x40,0x40,0x40,0xe0, + 0x70,0x88,0x88,0x88,0x88,0x88,0x40,0xa0, + 0x90,0x90,0x90,0x90,0x48,0x48,0x6c,0x92, + 0x92,0x92,0x90,0x90,0x60,0x60,0x90,0x90, + 0x20,0x20,0x30,0x48,0x48,0xc8,0xf0,0x80, + 0x40,0x20,0x10,0xf0,0xc0,0x80,0x80,0x80, + 0x80,0x80,0xc0,0x40,0x40,0x40,0x40,0x80, + 0x80,0x80,0xc0,0x40,0x40,0x40,0x40,0x40, + 0xc0,0x88,0x50,0x20,0xf8,0x80,0x80,0x80, + 0xd0,0xa0,0xe0,0x20,0xc0,0xe0,0x90,0x90, + 0x90,0xe0,0x80,0x80,0x60,0x80,0x80,0x80, + 0x60,0x70,0x90,0x90,0x90,0x70,0x10,0x10, + 0x60,0x80,0xe0,0xa0,0x40,0x40,0x40,0x40, + 0x40,0xe0,0x40,0x20,0x60,0x10,0x70,0x90, + 0x90,0x70,0x90,0x90,0x90,0x90,0xe0,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x80, + 0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x00, + 0x40,0xa0,0xa0,0xc0,0xc0,0xa0,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xa8, + 0xa8,0xa8,0xa8,0xf0,0x90,0x90,0x90,0x90, + 0xe0,0x60,0x90,0x90,0x90,0x60,0x80,0xe0, + 0x90,0x90,0x90,0xe0,0x10,0x70,0x90,0x90, + 0x90,0x70,0x80,0x80,0x80,0xc0,0xa0,0xc0, + 0x20,0x60,0x80,0x60,0x40,0x40,0x40,0x40, + 0xe0,0x40,0x40,0x60,0xa0,0xa0,0xa0,0xa0, + 0x40,0xa0,0x90,0x90,0x90,0x50,0x50,0xa8, + 0xa8,0xa8,0x90,0x90,0x60,0x90,0x90,0x80, + 0x40,0x60,0x90,0x90,0x90,0xe0,0x80,0x40, + 0x20,0xe0,0x20,0x40,0x40,0xc0,0x40,0x40, + 0x20,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x40,0x40,0x60,0x40,0x40,0x80,0xb0, + 0x48,0x00,0x80,0x80,0x80,0x80,0x80,0x00, + 0x80,0x40,0x40,0xa0,0x80,0xa0,0x40,0x40, + 0xf0,0x40,0x40,0xe0,0x40,0x30,0x88,0x70, + 0x50,0x70,0x88,0x20,0x20,0xf8,0x50,0x88, + 0x80,0x80,0x80,0x00,0x80,0x80,0x80,0xe0, + 0x10,0x30,0x60,0x90,0x60,0x80,0x70,0x90, + 0x78,0x84,0xb4,0xa4,0xb4,0x84,0x78,0xe0, + 0x00,0xe0,0x20,0xc0,0x50,0xa0,0x50,0x10, + 0x10,0xf0,0xc0,0x78,0x84,0xac,0xb4,0xb4, + 0x84,0x78,0xe0,0x40,0xa0,0x40,0xf0,0x00, + 0x20,0xf0,0x20,0xc0,0x80,0x40,0x80,0xc0, + 0x20,0x60,0xe0,0x80,0x40,0x80,0x80,0xe0, + 0xa0,0xa0,0xa0,0x50,0x50,0x50,0x50,0xd0, + 0xd0,0xd0,0x78,0x80,0x80,0x80,0x40,0x40, + 0x40,0xc0,0x40,0xe0,0x00,0xe0,0xa0,0xe0, + 0xa0,0x50,0xa0,0x04,0x5e,0x2c,0x54,0x48, + 0xc4,0x40,0x0e,0x44,0x22,0x5c,0x48,0xc4, + 0x40,0x04,0x5e,0x2c,0xd4,0x28,0x64,0xe0, + 0x60,0x90,0x40,0x20,0x00,0x20,0x88,0x88, + 0x70,0x50,0x20,0x20,0x00,0x20,0x40,0x88, + 0x88,0x70,0x50,0x20,0x20,0x00,0x20,0x10, + 0x88,0x88,0x70,0x50,0x20,0x20,0x00,0x50, + 0x20,0x88,0x88,0x70,0x50,0x20,0x20,0x00, + 0x50,0x28,0x88,0x88,0x70,0x50,0x20,0x20, + 0x00,0x50,0x88,0x88,0x70,0x50,0x20,0x20, + 0x20,0x50,0x20,0x9e,0x90,0x7c,0x50,0x30, + 0x3e,0x80,0x40,0x70,0x88,0x80,0x88,0x88, + 0x70,0xf0,0x80,0x80,0xe0,0x80,0xf0,0x00, + 0x20,0x40,0xf0,0x80,0x80,0xe0,0x80,0xf0, + 0x00,0x40,0x20,0xf0,0x80,0x80,0xe0,0x80, + 0xf0,0x00,0xa0,0x40,0xf0,0x80,0x80,0xe0, + 0x80,0xf0,0x00,0xa0,0x40,0x40,0x40,0x40, + 0x40,0x40,0x00,0x40,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x00,0x80,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x00,0xa0,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x00,0xa0,0x70, + 0x48,0x48,0xe8,0x48,0x70,0x88,0x98,0xa8, + 0xa8,0xc8,0x88,0x00,0x50,0x28,0x70,0x88, + 0x88,0x88,0x88,0x70,0x00,0x20,0x40,0x70, + 0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x10, + 0x70,0x88,0x88,0x88,0x88,0x70,0x00,0x50, + 0x20,0x70,0x88,0x88,0x88,0x88,0x70,0x00, + 0x50,0x28,0x70,0x88,0x88,0x88,0x88,0x70, + 0x00,0x50,0x90,0x60,0x60,0x90,0x80,0xf0, + 0xc8,0xa8,0x98,0x88,0x78,0x08,0x70,0x88, + 0x88,0x88,0x88,0x88,0x00,0x20,0x40,0x70, + 0x88,0x88,0x88,0x88,0x88,0x00,0x20,0x10, + 0x70,0x88,0x88,0x88,0x88,0x88,0x00,0x50, + 0x20,0x70,0x88,0x88,0x88,0x88,0x88,0x00, + 0x50,0x20,0x20,0x30,0x48,0x48,0xc8,0x00, + 0x10,0x08,0x80,0xf0,0x88,0x88,0xf0,0x80, + 0x80,0xa0,0x90,0x90,0xa0,0x90,0x60,0xd0, + 0xa0,0xe0,0x20,0xc0,0x00,0x40,0x80,0xd0, + 0xa0,0xe0,0x20,0xc0,0x00,0x40,0x20,0xd0, + 0xa0,0xe0,0x20,0xc0,0x00,0xa0,0x40,0x68, + 0x50,0x70,0x10,0x60,0x00,0xb0,0x68,0xd0, + 0xa0,0xe0,0x20,0xc0,0x00,0xa0,0xd0,0xa0, + 0xe0,0x20,0xc0,0x40,0xa0,0x40,0xd8,0xa0, + 0xf8,0x28,0xd0,0x80,0x40,0x60,0x80,0x80, + 0x80,0x60,0x60,0x80,0xe0,0xa0,0x40,0x00, + 0x20,0x40,0x60,0x80,0xe0,0xa0,0x40,0x00, + 0x40,0x20,0x60,0x80,0xe0,0xa0,0x40,0x00, + 0xa0,0x40,0x60,0x80,0xe0,0xa0,0x40,0x00, + 0xa0,0x40,0x40,0x40,0x40,0x40,0x00,0x40, + 0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x80, + 0x40,0x40,0x40,0x40,0x40,0x40,0x00,0xa0, + 0x40,0x40,0x40,0x40,0x40,0x40,0x00,0xa0, + 0x60,0x90,0x90,0x90,0x70,0xa0,0x60,0x90, + 0x90,0x90,0x90,0x90,0xe0,0x00,0xa0,0x50, + 0x60,0x90,0x90,0x90,0x60,0x00,0x20,0x40, + 0x60,0x90,0x90,0x90,0x60,0x00,0x20,0x10, + 0x60,0x90,0x90,0x90,0x60,0x00,0xa0,0x40, + 0x60,0x90,0x90,0x90,0x60,0x00,0xa0,0x50, + 0x60,0x90,0x90,0x90,0x60,0x00,0x90,0x20, + 0x00,0xf0,0x00,0x20,0x80,0x70,0x68,0x58, + 0x48,0x3c,0x02,0x60,0xa0,0xa0,0xa0,0xa0, + 0x00,0x40,0x80,0x60,0xa0,0xa0,0xa0,0xa0, + 0x00,0x40,0x20,0x60,0xa0,0xa0,0xa0,0xa0, + 0x00,0xa0,0x40,0x60,0xa0,0xa0,0xa0,0xa0, + 0x00,0xa0,0x80,0x40,0x60,0x90,0x90,0x90, + 0x00,0x20,0x10,0x80,0xe0,0x90,0x90,0x90, + 0xe0,0x80,0x80,0x40,0x60,0x90,0x90,0x90, + 0x00,0x50, +}; + +BMF_FontData BMF_font_helvb8 = { + 0, -2, + 9, 9, + { + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0, 0, 0, 0, 8, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {1, 1, 0, 0, 2, 0}, + {1, 6, -1, 0, 2, 1}, + {3, 3, -1, -3, 3, 7}, + {5, 5, 0, 0, 5, 10}, + {4, 7, -1, 1, 5, 15}, + {6, 6, -1, 0, 7, 22}, + {5, 6, -1, 0, 6, 28}, + {1, 3, -1, -3, 2, 34}, + {2, 7, -1, 1, 3, 37}, + {2, 7, -1, 1, 3, 44}, + {3, 3, -1, -2, 3, 51}, + {5, 5, -1, 0, 5, 54}, + {2, 3, 0, 2, 2, 59}, + {4, 1, -2, -2, 6, 62}, + {1, 1, -1, 0, 2, 63}, + {2, 7, -1, 1, 2, 64}, + {4, 6, -1, 0, 5, 71}, + {2, 6, -2, 0, 5, 77}, + {4, 6, -1, 0, 5, 83}, + {3, 6, -2, 0, 5, 89}, + {4, 6, -1, 0, 5, 95}, + {3, 6, -2, 0, 5, 101}, + {4, 6, -1, 0, 5, 107}, + {4, 6, -1, 0, 5, 113}, + {4, 6, -1, 0, 5, 119}, + {4, 6, -1, 0, 5, 125}, + {1, 4, -1, 0, 2, 131}, + {2, 6, 0, 2, 2, 135}, + {3, 5, -1, 0, 5, 141}, + {3, 3, -1, -1, 4, 146}, + {3, 5, -2, 0, 5, 149}, + {3, 5, -2, 0, 5, 154}, + {8, 7, -1, 1, 9, 159}, + {5, 6, -1, 0, 6, 166}, + {4, 6, -2, 0, 6, 172}, + {5, 6, -1, 0, 6, 178}, + {5, 6, -1, 0, 6, 184}, + {4, 6, -2, 0, 6, 190}, + {4, 6, -2, 0, 5, 196}, + {5, 6, -1, 0, 6, 202}, + {5, 6, -1, 0, 6, 208}, + {1, 6, -1, 0, 2, 214}, + {3, 6, -1, 0, 4, 220}, + {4, 6, -2, 0, 6, 226}, + {3, 6, -2, 0, 5, 232}, + {5, 6, -2, 0, 7, 238}, + {5, 6, -1, 0, 6, 244}, + {5, 6, -1, 0, 6, 250}, + {4, 6, -2, 0, 6, 256}, + {5, 8, -1, 2, 6, 262}, + {4, 6, -2, 0, 6, 270}, + {4, 6, -2, 0, 6, 276}, + {3, 6, -1, 0, 4, 282}, + {5, 6, -1, 0, 6, 288}, + {4, 6, -2, 0, 6, 294}, + {7, 6, -1, 0, 7, 300}, + {4, 6, -2, 0, 6, 306}, + {5, 6, -1, 0, 6, 312}, + {4, 6, -2, 0, 6, 318}, + {2, 7, -1, 1, 2, 324}, + {2, 7, 0, 1, 2, 331}, + {2, 7, 0, 1, 2, 338}, + {5, 3, 0, -2, 5, 345}, + {5, 1, 0, 1, 5, 348}, + {1, 3, -1, -3, 2, 349}, + {4, 5, -1, 0, 4, 352}, + {4, 7, -1, 0, 5, 357}, + {3, 5, -1, 0, 4, 364}, + {4, 7, -1, 0, 5, 369}, + {3, 5, -1, 0, 4, 376}, + {3, 7, -1, 0, 3, 381}, + {4, 6, -1, 1, 5, 388}, + {4, 7, -1, 0, 5, 394}, + {1, 7, -1, 0, 2, 401}, + {2, 9, 0, 2, 2, 408}, + {3, 7, -1, 0, 4, 417}, + {1, 7, -1, 0, 2, 424}, + {5, 5, -1, 0, 6, 431}, + {4, 5, -1, 0, 5, 436}, + {4, 5, -1, 0, 5, 441}, + {4, 6, -1, 1, 5, 446}, + {4, 6, -1, 1, 5, 452}, + {3, 5, -1, 0, 3, 458}, + {3, 5, -1, 0, 4, 463}, + {3, 7, -1, 0, 3, 468}, + {3, 5, -1, 0, 4, 475}, + {4, 5, -1, 0, 5, 480}, + {5, 5, -1, 0, 6, 485}, + {4, 5, -1, 0, 5, 490}, + {4, 6, -1, 1, 4, 495}, + {3, 5, -1, 0, 4, 501}, + {3, 7, 0, 1, 2, 506}, + {1, 7, -1, 1, 2, 513}, + {3, 7, 0, 1, 2, 520}, + {5, 2, -1, -2, 6, 527}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {1, 1, 0, 0, 2, 529}, + {1, 7, -1, 2, 2, 530}, + {3, 7, -1, 1, 5, 537}, + {4, 6, -1, 0, 5, 544}, + {5, 5, 0, 0, 4, 550}, + {5, 5, -1, 0, 6, 555}, + {1, 7, -1, 1, 2, 560}, + {4, 8, -1, 2, 5, 567}, + {4, 1, 0, -5, 2, 575}, + {6, 7, -1, 1, 7, 576}, + {3, 5, 0, -1, 3, 583}, + {4, 3, -1, -1, 5, 588}, + {4, 3, -1, -1, 6, 591}, + {2, 1, 0, -2, 3, 594}, + {6, 7, -1, 1, 7, 595}, + {3, 1, 0, -5, 2, 602}, + {3, 3, -1, -3, 3, 603}, + {4, 5, -1, 0, 5, 606}, + {2, 4, -1, -2, 2, 611}, + {3, 4, 0, -2, 2, 615}, + {2, 2, 0, -4, 2, 619}, + {3, 6, -1, 2, 4, 621}, + {5, 8, 0, 2, 5, 627}, + {1, 2, -1, -1, 2, 635}, + {2, 2, 0, 2, 2, 637}, + {2, 4, 0, -2, 2, 639}, + {3, 5, 0, -1, 3, 643}, + {4, 3, -1, -1, 5, 648}, + {7, 7, 0, 1, 7, 651}, + {7, 7, 0, 1, 7, 658}, + {7, 7, 0, 1, 7, 665}, + {4, 6, -1, 1, 5, 672}, + {5, 9, -1, 0, 6, 678}, + {5, 9, -1, 0, 6, 687}, + {5, 9, -1, 0, 6, 696}, + {5, 9, -1, 0, 6, 705}, + {5, 8, -1, 0, 6, 714}, + {5, 9, -1, 0, 6, 722}, + {7, 6, -1, 0, 8, 731}, + {5, 8, -1, 2, 6, 737}, + {4, 9, -2, 0, 6, 745}, + {4, 9, -2, 0, 6, 754}, + {4, 9, -2, 0, 6, 763}, + {4, 8, -2, 0, 6, 772}, + {2, 9, 0, 0, 2, 780}, + {2, 9, -1, 0, 2, 789}, + {3, 9, 0, 0, 2, 798}, + {3, 8, 0, 0, 2, 807}, + {5, 6, -1, 0, 6, 815}, + {5, 9, -1, 0, 6, 821}, + {5, 9, -1, 0, 6, 830}, + {5, 9, -1, 0, 6, 839}, + {5, 9, -1, 0, 6, 848}, + {5, 9, -1, 0, 6, 857}, + {5, 8, -1, 0, 6, 866}, + {4, 4, -1, 0, 5, 874}, + {5, 8, -1, 1, 6, 878}, + {5, 9, -1, 0, 6, 886}, + {5, 9, -1, 0, 6, 895}, + {5, 9, -1, 0, 6, 904}, + {5, 8, -1, 0, 6, 913}, + {5, 9, -1, 0, 6, 921}, + {5, 6, -1, 0, 6, 930}, + {4, 7, -2, 1, 6, 936}, + {4, 8, -1, 0, 4, 943}, + {4, 8, -1, 0, 4, 951}, + {4, 8, -1, 0, 4, 959}, + {5, 8, 0, 0, 4, 967}, + {4, 7, -1, 0, 4, 975}, + {4, 8, -1, 0, 4, 982}, + {5, 5, -1, 0, 6, 990}, + {3, 7, -1, 2, 4, 995}, + {3, 8, -1, 0, 4, 1002}, + {3, 8, -1, 0, 4, 1010}, + {3, 8, -1, 0, 4, 1018}, + {3, 7, -1, 0, 4, 1026}, + {2, 8, 0, 0, 2, 1033}, + {2, 8, -1, 0, 2, 1041}, + {3, 8, 0, 0, 2, 1049}, + {3, 7, 0, 0, 2, 1057}, + {4, 8, -1, 0, 5, 1064}, + {4, 8, -1, 0, 5, 1072}, + {4, 8, -1, 0, 5, 1080}, + {4, 8, -1, 0, 5, 1088}, + {4, 8, -1, 0, 5, 1096}, + {4, 8, -1, 0, 5, 1104}, + {4, 7, -1, 0, 5, 1112}, + {4, 5, -1, 0, 5, 1119}, + {7, 7, 0, 1, 5, 1124}, + {3, 8, -1, 0, 4, 1131}, + {3, 8, -1, 0, 4, 1139}, + {3, 8, -1, 0, 4, 1147}, + {3, 7, -1, 0, 4, 1155}, + {4, 9, -1, 1, 4, 1162}, + {4, 7, -1, 1, 5, 1171}, + {4, 8, -1, 1, 4, 1178}, + }, + bitmap_data +}; + +#endif + diff --git a/intern/bmfont/intern/BMF_font_scr12.cpp b/intern/bmfont/intern/BMF_font_scr12.cpp new file mode 100644 index 00000000000..a870ea91763 --- /dev/null +++ b/intern/bmfont/intern/BMF_font_scr12.cpp @@ -0,0 +1,484 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BMF_FontData.h" + +#include "BMF_Settings.h" + +#if BMF_INCLUDE_SCR12 + +static unsigned char bitmap_data[]= { + 0x80,0x80,0x00,0x80,0x80,0x80,0x80,0x80, + 0xa0,0xa0,0xa0,0xa0,0x50,0x50,0xfc,0x28, + 0x28,0x7e,0x14,0x14,0x20,0x70,0xa8,0x28, + 0x70,0xa0,0xa8,0x70,0x20,0x98,0x54,0x54, + 0x2c,0xd0,0xa8,0xa8,0x64,0x74,0x88,0x8c, + 0x50,0x20,0x50,0x48,0x30,0x80,0x40,0x20, + 0x20,0x20,0x40,0x40,0x80,0x80,0x80,0x80, + 0x40,0x40,0x20,0x80,0x40,0x40,0x20,0x20, + 0x20,0x20,0x40,0x40,0x80,0x20,0xa8,0x70, + 0xa8,0x20,0x20,0x20,0xf8,0x20,0x20,0x80, + 0x40,0x40,0xc0,0xf8,0x80,0x80,0x80,0x80, + 0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08, + 0x70,0x88,0x88,0xc8,0xa8,0x98,0x88,0x70, + 0xe0,0x40,0x40,0x40,0x40,0x40,0xc0,0x40, + 0xf8,0x80,0x40,0x20,0x10,0x08,0x88,0x70, + 0x70,0x88,0x08,0x08,0x70,0x08,0x88,0x70, + 0x10,0x10,0x10,0xf8,0x90,0x50,0x30,0x10, + 0x70,0x88,0x08,0x08,0xf0,0x80,0x80,0xf8, + 0x70,0x88,0x88,0x88,0xf0,0x80,0x88,0x70, + 0x40,0x40,0x20,0x20,0x10,0x10,0x08,0xf8, + 0x70,0x88,0x88,0x88,0x70,0x88,0x88,0x70, + 0x70,0x88,0x08,0x78,0x88,0x88,0x88,0x70, + 0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x40, + 0x40,0xc0,0x00,0x00,0x40,0x40,0x08,0x10, + 0x20,0x40,0x80,0x40,0x20,0x10,0x08,0xf8, + 0x00,0xf8,0x80,0x40,0x20,0x10,0x08,0x10, + 0x20,0x40,0x80,0x20,0x00,0x20,0x20,0x10, + 0x88,0x88,0x70,0x38,0x40,0x98,0xa8,0xa8, + 0x98,0x48,0x30,0x88,0x88,0xf8,0x88,0x50, + 0x50,0x20,0x20,0xf0,0x88,0x88,0x88,0xf0, + 0x88,0x88,0xf0,0x70,0x88,0x80,0x80,0x80, + 0x80,0x88,0x70,0xf0,0x88,0x88,0x88,0x88, + 0x88,0x88,0xf0,0xf8,0x80,0x80,0x80,0xf0, + 0x80,0x80,0xf8,0x80,0x80,0x80,0x80,0xf0, + 0x80,0x80,0xf8,0x68,0x98,0x88,0x88,0x98, + 0x80,0x88,0x70,0x88,0x88,0x88,0x88,0xf8, + 0x88,0x88,0x88,0xe0,0x40,0x40,0x40,0x40, + 0x40,0x40,0xe0,0x70,0x88,0x88,0x08,0x08, + 0x08,0x08,0x08,0x88,0x88,0x90,0xa0,0xc0, + 0xa0,0x90,0x88,0xf8,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x88,0x88,0xa8,0xa8,0xd8, + 0xd8,0x88,0x88,0x88,0x98,0x98,0xa8,0xa8, + 0xc8,0xc8,0x88,0x70,0x88,0x88,0x88,0x88, + 0x88,0x88,0x70,0x80,0x80,0x80,0x80,0xf0, + 0x88,0x88,0xf0,0x08,0x10,0x70,0xa8,0x88, + 0x88,0x88,0x88,0x88,0x70,0x88,0x90,0x90, + 0xa0,0xf0,0x88,0x88,0xf0,0x70,0x88,0x88, + 0x08,0x70,0x80,0x88,0x70,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0xf8,0x70,0x88,0x88, + 0x88,0x88,0x88,0x88,0x88,0x20,0x20,0x50, + 0x50,0x50,0x88,0x88,0x88,0x50,0x50,0xf8, + 0xa8,0xa8,0xa8,0x88,0x88,0x88,0x88,0x50, + 0x20,0x20,0x50,0x88,0x88,0x20,0x20,0x20, + 0x20,0x50,0x50,0x88,0x88,0xf8,0x80,0x40, + 0x40,0x20,0x10,0x08,0xf8,0xe0,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0xe0,0x08,0x08, + 0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80, + 0xe0,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0xe0,0x88,0x50,0x20,0xfe,0x20,0x40,0x80, + 0x80,0x68,0x98,0x88,0x78,0x08,0x70,0xb0, + 0xc8,0x88,0x88,0xc8,0xb0,0x80,0x80,0x70, + 0x88,0x80,0x80,0x88,0x70,0x68,0x98,0x88, + 0x88,0x98,0x68,0x08,0x08,0x70,0x88,0x80, + 0xf8,0x88,0x70,0x40,0x40,0x40,0x40,0x40, + 0xf0,0x40,0x38,0xf0,0x08,0x68,0x98,0x88, + 0x88,0x98,0x68,0x88,0x88,0x88,0x88,0xc8, + 0xb0,0x80,0x80,0x20,0x20,0x20,0x20,0x20, + 0xe0,0x00,0x20,0x60,0x90,0x10,0x10,0x10, + 0x10,0x10,0x70,0x00,0x10,0x88,0x90,0xa0, + 0xc0,0xa0,0x90,0x80,0x80,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0xe0,0xa8,0xa8,0xa8, + 0xa8,0xa8,0xd0,0x88,0x88,0x88,0x88,0xc8, + 0xb0,0x70,0x88,0x88,0x88,0x88,0x70,0x80, + 0x80,0xb0,0xc8,0x88,0x88,0xc8,0xb0,0x08, + 0x08,0x68,0x98,0x88,0x88,0x98,0x68,0x80, + 0x80,0x80,0x80,0xc8,0xb0,0x70,0x88,0x10, + 0x60,0x88,0x70,0x30,0x40,0x40,0x40,0x40, + 0xf0,0x40,0x68,0x98,0x88,0x88,0x88,0x88, + 0x20,0x20,0x50,0x50,0x88,0x88,0x50,0xa8, + 0xa8,0xa8,0x88,0x88,0x88,0x88,0x50,0x20, + 0x50,0x88,0xf0,0x08,0x68,0x98,0x88,0x88, + 0x88,0x88,0xf8,0x80,0x40,0x20,0x10,0xf8, + 0x18,0x20,0x20,0x20,0x20,0xc0,0x20,0x20, + 0x20,0x18,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0xc0,0x20,0x20,0x20, + 0x20,0x18,0x20,0x20,0x20,0xc0,0x98,0xb4, + 0x64,0x80,0x80,0x80,0x80,0x80,0x00,0x80, + 0x80,0x20,0x20,0x70,0x88,0x80,0x88,0x70, + 0x20,0x20,0xb0,0x48,0x40,0xf0,0x40,0x40, + 0x48,0x30,0x90,0x60,0x90,0x90,0x60,0x90, + 0x20,0x70,0x20,0x70,0x20,0x50,0x88,0x88, + 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x80, + 0x80,0x80,0x70,0x88,0x10,0x28,0x48,0x90, + 0xa0,0x40,0x88,0x70,0xa0,0x78,0x84,0xb4, + 0xa4,0xb4,0x84,0x78,0xf0,0x90,0x70,0x10, + 0x60,0x14,0x28,0x50,0xa0,0x50,0x28,0x14, + 0x08,0xf8,0xf0,0x78,0x84,0xac,0xb4,0xb4, + 0x84,0x78,0xe0,0x60,0x90,0x60,0xf8,0x00, + 0x20,0x20,0xf8,0x20,0x20,0xe0,0x40,0x20, + 0xa0,0x40,0xc0,0x20,0x40,0x20,0xc0,0x80, + 0x40,0x80,0xe8,0x90,0x90,0x90,0x90,0x28, + 0x28,0x28,0x28,0x68,0xa8,0xa8,0xa8,0x7c, + 0x80,0x80,0xc0,0x40,0xe0,0x40,0x40,0xc0, + 0x40,0xf0,0x60,0x90,0x90,0x60,0xa0,0x50, + 0x28,0x14,0x28,0x50,0xa0,0x08,0x38,0xa8, + 0x58,0x28,0xf0,0x48,0x40,0xc0,0x40,0x38, + 0x10,0x88,0x68,0x30,0xf0,0x48,0x40,0xc0, + 0x40,0x08,0x38,0xa8,0x58,0x28,0xd0,0x28, + 0x40,0x20,0xc0,0x70,0x88,0x88,0x40,0x20, + 0x20,0x00,0x20,0x88,0x88,0xf8,0x88,0x50, + 0x50,0x20,0x00,0x20,0x40,0x88,0x88,0xf8, + 0x50,0x50,0x20,0x20,0x00,0x20,0x10,0x88, + 0x88,0xf8,0x50,0x50,0x20,0x20,0x00,0x50, + 0x20,0x88,0x88,0xf8,0x50,0x50,0x20,0x20, + 0x00,0xb0,0x68,0x88,0x88,0xf8,0x50,0x50, + 0x20,0x20,0x00,0x50,0x88,0x88,0xf8,0x50, + 0x50,0x20,0x20,0x20,0x50,0x20,0x9c,0x90, + 0xf0,0x50,0x5c,0x30,0x30,0x1c,0x60,0x20, + 0x70,0x88,0x80,0x80,0x80,0x80,0x88,0x70, + 0xf8,0x80,0x80,0xf0,0x80,0x80,0xf8,0x00, + 0x20,0x40,0xf8,0x80,0x80,0xf0,0x80,0x80, + 0xf8,0x00,0x20,0x10,0xf8,0x80,0x80,0xf0, + 0x80,0x80,0xf8,0x00,0x50,0x20,0xf8,0x80, + 0x80,0xf0,0x80,0x80,0xf8,0x00,0x50,0xe0, + 0x40,0x40,0x40,0x40,0x40,0xe0,0x00,0x40, + 0x80,0xe0,0x40,0x40,0x40,0x40,0x40,0xe0, + 0x00,0x40,0x20,0xe0,0x40,0x40,0x40,0x40, + 0x40,0xe0,0x00,0xa0,0x40,0xe0,0x40,0x40, + 0x40,0x40,0x40,0xe0,0x00,0xa0,0x78,0x44, + 0x44,0xf4,0x44,0x44,0x44,0x78,0x88,0x98, + 0x98,0xa8,0xc8,0xc8,0x88,0x00,0xb0,0x68, + 0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00, + 0x20,0x40,0x70,0x88,0x88,0x88,0x88,0x88, + 0x70,0x00,0x20,0x10,0x70,0x88,0x88,0x88, + 0x88,0x88,0x70,0x00,0x50,0x20,0x70,0x88, + 0x88,0x88,0x88,0x88,0x70,0x00,0xb0,0x68, + 0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00, + 0x50,0x88,0x50,0x20,0x50,0x88,0xb8,0x44, + 0x64,0x54,0x4c,0x44,0x3a,0x70,0x88,0x88, + 0x88,0x88,0x88,0x88,0x00,0x20,0x40,0x70, + 0x88,0x88,0x88,0x88,0x88,0x88,0x00,0x20, + 0x10,0x70,0x88,0x88,0x88,0x88,0x88,0x88, + 0x00,0x50,0x20,0x70,0x88,0x88,0x88,0x88, + 0x88,0x88,0x00,0x50,0x20,0x20,0x20,0x50, + 0x50,0x88,0x88,0x00,0x20,0x10,0x80,0x80, + 0xf0,0x88,0x88,0x88,0xf0,0x80,0x80,0xb0, + 0x88,0x88,0x88,0x90,0xa0,0x90,0x60,0x78, + 0x88,0x78,0x08,0x70,0x00,0x20,0x40,0x78, + 0x88,0x78,0x08,0x70,0x00,0x20,0x10,0x78, + 0x88,0x78,0x08,0x70,0x00,0x50,0x20,0x78, + 0x88,0x78,0x08,0x70,0x00,0xb0,0x68,0x78, + 0x88,0x78,0x08,0x70,0x00,0x50,0x78,0x88, + 0x78,0x08,0x70,0x00,0x20,0x50,0x20,0x6c, + 0x90,0x7c,0x12,0x6c,0x60,0x20,0x70,0x88, + 0x80,0x80,0x88,0x70,0x78,0x80,0xf8,0x88, + 0x70,0x00,0x20,0x40,0x78,0x80,0xf8,0x88, + 0x70,0x00,0x20,0x10,0x78,0x80,0xf8,0x88, + 0x70,0x00,0x50,0x20,0x78,0x80,0xf8,0x88, + 0x70,0x00,0x50,0x20,0x20,0x20,0x20,0xe0, + 0x00,0x40,0x80,0x20,0x20,0x20,0x20,0xe0, + 0x00,0x40,0x20,0x20,0x20,0x20,0x20,0xe0, + 0x00,0xa0,0x40,0x20,0x20,0x20,0x20,0xe0, + 0x00,0xa0,0x70,0x88,0x88,0x88,0x78,0x08, + 0x90,0x60,0xd0,0x88,0x88,0x88,0xc8,0xb0, + 0x00,0xb0,0x68,0x70,0x88,0x88,0x88,0x70, + 0x00,0x20,0x40,0x70,0x88,0x88,0x88,0x70, + 0x00,0x20,0x10,0x70,0x88,0x88,0x88,0x70, + 0x00,0x50,0x20,0x70,0x88,0x88,0x88,0x70, + 0x00,0xb0,0x68,0x70,0x88,0x88,0x88,0x70, + 0x00,0x50,0x20,0x00,0xf8,0x00,0x20,0xb8, + 0x64,0x54,0x4c,0x3a,0x68,0x98,0x88,0x88, + 0x88,0x00,0x20,0x40,0x68,0x98,0x88,0x88, + 0x88,0x00,0x20,0x10,0x68,0x98,0x88,0x88, + 0x88,0x00,0x50,0x20,0x68,0x98,0x88,0x88, + 0x88,0x00,0x50,0xf0,0x08,0x68,0x98,0x88, + 0x88,0x88,0x00,0x20,0x10,0x80,0x80,0xb0, + 0xc8,0x88,0x88,0xc8,0xb0,0x80,0x80,0xf0, + 0x08,0x68,0x98,0x88,0x88,0x88,0x00,0xd8, +}; + +BMF_FontData BMF_font_scr12 = { + 0, -2, + 7, 10, + { + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0, 0, 0, 0, 16, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0, 0, 0, 0, 7, -1}, + {1, 8, -3, 0, 7, 0}, + {3, 4, -2, -5, 7, 8}, + {7, 8, 0, 0, 7, 12}, + {5, 9, -1, 1, 7, 20}, + {6, 8, 0, 0, 7, 29}, + {6, 8, 0, 0, 7, 37}, + {3, 4, -2, -5, 7, 45}, + {3, 10, -2, 2, 7, 49}, + {3, 10, -2, 2, 7, 59}, + {5, 5, -1, -3, 7, 69}, + {5, 5, -1, -1, 7, 74}, + {2, 4, -2, 2, 7, 79}, + {5, 1, -1, -3, 7, 83}, + {1, 2, -3, 0, 7, 84}, + {5, 10, -1, 1, 7, 86}, + {5, 8, -1, 0, 7, 96}, + {3, 8, -2, 0, 7, 104}, + {5, 8, -1, 0, 7, 112}, + {5, 8, -1, 0, 7, 120}, + {5, 8, -1, 0, 7, 128}, + {5, 8, -1, 0, 7, 136}, + {5, 8, -1, 0, 7, 144}, + {5, 8, -1, 0, 7, 152}, + {5, 8, -1, 0, 7, 160}, + {5, 8, -1, 0, 7, 168}, + {1, 6, -3, 0, 7, 176}, + {2, 8, -2, 2, 7, 182}, + {5, 9, -1, 1, 7, 190}, + {5, 3, -1, -2, 7, 199}, + {5, 9, -1, 1, 7, 202}, + {5, 8, -1, 0, 7, 211}, + {5, 8, -1, 0, 7, 219}, + {5, 8, -1, 0, 7, 227}, + {5, 8, -1, 0, 7, 235}, + {5, 8, -1, 0, 7, 243}, + {5, 8, -1, 0, 7, 251}, + {5, 8, -1, 0, 7, 259}, + {5, 8, -1, 0, 7, 267}, + {5, 8, -1, 0, 7, 275}, + {5, 8, -1, 0, 7, 283}, + {3, 8, -2, 0, 7, 291}, + {5, 8, -1, 0, 7, 299}, + {5, 8, -1, 0, 7, 307}, + {5, 8, -1, 0, 7, 315}, + {5, 8, -1, 0, 7, 323}, + {5, 8, -1, 0, 7, 331}, + {5, 8, -1, 0, 7, 339}, + {5, 8, -1, 0, 7, 347}, + {5, 10, -1, 2, 7, 355}, + {5, 8, -1, 0, 7, 365}, + {5, 8, -1, 0, 7, 373}, + {5, 8, -1, 0, 7, 381}, + {5, 8, -1, 0, 7, 389}, + {5, 8, -1, 0, 7, 397}, + {5, 8, -1, 0, 7, 405}, + {5, 8, -1, 0, 7, 413}, + {5, 8, -1, 0, 7, 421}, + {5, 8, -1, 0, 7, 429}, + {3, 9, -2, 1, 7, 437}, + {5, 10, -1, 1, 7, 446}, + {3, 9, -2, 1, 7, 456}, + {5, 3, -1, -5, 7, 465}, + {7, 1, 0, 1, 7, 468}, + {3, 4, -2, -5, 7, 469}, + {5, 6, -1, 0, 7, 473}, + {5, 8, -1, 0, 7, 479}, + {5, 6, -1, 0, 7, 487}, + {5, 8, -1, 0, 7, 493}, + {5, 6, -1, 0, 7, 501}, + {5, 8, -1, 0, 7, 507}, + {5, 8, -1, 2, 7, 515}, + {5, 8, -1, 0, 7, 523}, + {3, 8, -2, 0, 7, 531}, + {4, 10, -1, 2, 7, 539}, + {5, 8, -1, 0, 7, 549}, + {3, 8, -2, 0, 7, 557}, + {5, 6, -1, 0, 7, 565}, + {5, 6, -1, 0, 7, 571}, + {5, 6, -1, 0, 7, 577}, + {5, 8, -1, 2, 7, 583}, + {5, 8, -1, 2, 7, 591}, + {5, 6, -1, 0, 7, 599}, + {5, 6, -1, 0, 7, 605}, + {4, 7, -1, 0, 7, 611}, + {5, 6, -1, 0, 7, 618}, + {5, 6, -1, 0, 7, 624}, + {5, 6, -1, 0, 7, 630}, + {5, 6, -1, 0, 7, 636}, + {5, 8, -1, 2, 7, 642}, + {5, 6, -1, 0, 7, 650}, + {5, 10, -1, 2, 7, 656}, + {1, 10, -3, 1, 7, 666}, + {5, 10, -1, 2, 7, 676}, + {6, 3, 0, -2, 7, 686}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {1, 8, -3, 2, 7, 689}, + {5, 9, -1, 0, 7, 697}, + {5, 8, -1, 0, 7, 706}, + {4, 6, -1, -2, 7, 714}, + {5, 8, -1, 0, 7, 720}, + {1, 10, -3, 1, 7, 728}, + {5, 10, -1, 1, 7, 738}, + {3, 1, -2, -7, 7, 748}, + {6, 7, 0, 0, 7, 749}, + {4, 5, -1, -4, 7, 756}, + {6, 7, 0, 0, 7, 761}, + {5, 2, -1, -3, 7, 768}, + {4, 1, -1, -3, 7, 770}, + {6, 7, 0, 0, 7, 771}, + {3, 1, -2, -7, 7, 778}, + {4, 3, -1, -4, 7, 779}, + {5, 7, -1, 0, 7, 782}, + {3, 5, -2, -4, 7, 789}, + {3, 5, -2, -4, 7, 794}, + {2, 2, -2, -7, 7, 799}, + {5, 6, -1, 1, 7, 801}, + {6, 9, 0, 1, 7, 807}, + {1, 2, -3, -3, 7, 816}, + {2, 2, -2, 2, 7, 818}, + {3, 5, -2, -4, 7, 820}, + {4, 5, -1, -4, 7, 825}, + {6, 7, 0, 0, 7, 830}, + {5, 10, -1, 1, 7, 837}, + {5, 10, -1, 1, 7, 847}, + {5, 10, -1, 1, 7, 857}, + {5, 8, -1, 2, 7, 867}, + {5, 10, -1, 0, 7, 875}, + {5, 10, -1, 0, 7, 885}, + {5, 10, -1, 0, 7, 895}, + {5, 10, -1, 0, 7, 905}, + {5, 9, -1, 0, 7, 915}, + {5, 10, -1, 0, 7, 924}, + {6, 8, 0, 0, 7, 934}, + {5, 10, -1, 2, 7, 942}, + {5, 10, -1, 0, 7, 952}, + {5, 10, -1, 0, 7, 962}, + {5, 10, -1, 0, 7, 972}, + {5, 9, -1, 0, 7, 982}, + {3, 10, -2, 0, 7, 991}, + {3, 10, -2, 0, 7, 1001}, + {3, 10, -2, 0, 7, 1011}, + {3, 9, -2, 0, 7, 1021}, + {6, 8, 0, 0, 7, 1030}, + {5, 10, -1, 0, 7, 1038}, + {5, 10, -1, 0, 7, 1048}, + {5, 10, -1, 0, 7, 1058}, + {5, 10, -1, 0, 7, 1068}, + {5, 10, -1, 0, 7, 1078}, + {5, 9, -1, 0, 7, 1088}, + {5, 5, -1, -1, 7, 1097}, + {7, 7, 0, 0, 7, 1102}, + {5, 10, -1, 0, 7, 1109}, + {5, 10, -1, 0, 7, 1119}, + {5, 10, -1, 0, 7, 1129}, + {5, 9, -1, 0, 7, 1139}, + {5, 10, -1, 0, 7, 1148}, + {5, 9, -1, 0, 7, 1158}, + {5, 8, -1, 0, 7, 1167}, + {5, 8, -1, 0, 7, 1175}, + {5, 8, -1, 0, 7, 1183}, + {5, 8, -1, 0, 7, 1191}, + {5, 8, -1, 0, 7, 1199}, + {5, 7, -1, 0, 7, 1207}, + {5, 9, -1, 0, 7, 1214}, + {7, 5, 0, 0, 7, 1223}, + {5, 8, -1, 2, 7, 1228}, + {5, 8, -1, 0, 7, 1236}, + {5, 8, -1, 0, 7, 1244}, + {5, 8, -1, 0, 7, 1252}, + {5, 7, -1, 0, 7, 1260}, + {3, 8, -2, 0, 7, 1267}, + {3, 8, -2, 0, 7, 1275}, + {3, 8, -2, 0, 7, 1283}, + {3, 7, -2, 0, 7, 1291}, + {5, 9, -1, 0, 7, 1298}, + {5, 8, -1, 0, 7, 1307}, + {5, 8, -1, 0, 7, 1315}, + {5, 8, -1, 0, 7, 1323}, + {5, 8, -1, 0, 7, 1331}, + {5, 8, -1, 0, 7, 1339}, + {5, 7, -1, 0, 7, 1347}, + {5, 5, -1, -1, 7, 1354}, + {7, 5, 0, 0, 7, 1359}, + {5, 8, -1, 0, 7, 1364}, + {5, 8, -1, 0, 7, 1372}, + {5, 8, -1, 0, 7, 1380}, + {5, 7, -1, 0, 7, 1388}, + {5, 10, -1, 2, 7, 1395}, + {5, 10, -1, 2, 7, 1405}, + {5, 9, -1, 2, 7, 1415}, + }, + bitmap_data +}; + +#endif + diff --git a/intern/bmfont/intern/BMF_font_scr14.cpp b/intern/bmfont/intern/BMF_font_scr14.cpp new file mode 100644 index 00000000000..c060556c7e0 --- /dev/null +++ b/intern/bmfont/intern/BMF_font_scr14.cpp @@ -0,0 +1,510 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BMF_FontData.h" + +#include "BMF_Settings.h" + +#if BMF_INCLUDE_SCR14 + +static unsigned char bitmap_data[]= { + 0x80,0x80,0x00,0x80,0x80,0x80,0x80,0x80, + 0x80,0xa0,0xa0,0xa0,0xa0,0x50,0x50,0xfc, + 0x28,0x28,0x28,0x7e,0x14,0x14,0x20,0x70, + 0xa8,0x28,0x30,0x60,0xa0,0xa8,0x70,0x20, + 0x98,0x54,0x54,0x2c,0x10,0x68,0x54,0x54, + 0x32,0x74,0x88,0x8c,0x90,0x60,0x20,0x50, + 0x48,0x30,0x80,0x40,0x20,0x20,0x20,0x40, + 0x40,0x80,0x80,0x80,0x80,0x80,0x40,0x40, + 0x20,0x80,0x40,0x40,0x20,0x20,0x20,0x20, + 0x20,0x40,0x40,0x80,0x20,0xa8,0x70,0x70, + 0xa8,0x20,0x20,0x20,0xf8,0x20,0x20,0x80, + 0x40,0x40,0xc0,0xf8,0x80,0x80,0x80,0x80, + 0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08, + 0x70,0x88,0x88,0xc8,0xa8,0x98,0x88,0x88, + 0x70,0xe0,0x40,0x40,0x40,0x40,0x40,0x40, + 0xc0,0x40,0xf8,0x80,0x40,0x20,0x10,0x08, + 0x88,0x88,0x70,0x70,0x88,0x08,0x08,0x70, + 0x08,0x08,0x88,0x70,0x10,0x10,0x10,0xf8, + 0x90,0x50,0x50,0x30,0x10,0x70,0x88,0x08, + 0x08,0x08,0xf0,0x80,0x80,0xf8,0x70,0x88, + 0x88,0x88,0x88,0xf0,0x80,0x88,0x70,0x40, + 0x40,0x40,0x20,0x20,0x10,0x10,0x08,0xf8, + 0x70,0x88,0x88,0x88,0x70,0x88,0x88,0x88, + 0x70,0x70,0x88,0x08,0x08,0x78,0x88,0x88, + 0x88,0x70,0x80,0x80,0x00,0x00,0x80,0x80, + 0x80,0x40,0x40,0xc0,0x00,0x00,0x40,0x40, + 0x08,0x10,0x20,0x40,0x80,0x40,0x20,0x10, + 0x08,0xf8,0x00,0xf8,0x80,0x40,0x20,0x10, + 0x08,0x10,0x20,0x40,0x80,0x20,0x20,0x00, + 0x20,0x20,0x10,0x88,0x88,0x70,0x38,0x40, + 0x98,0xa8,0xa8,0x98,0x88,0x48,0x30,0x88, + 0x88,0xf8,0x88,0x50,0x50,0x50,0x20,0x20, + 0xf0,0x88,0x88,0x88,0xf0,0x88,0x88,0x88, + 0xf0,0x70,0x88,0x80,0x80,0x80,0x80,0x80, + 0x88,0x70,0xf0,0x88,0x88,0x88,0x88,0x88, + 0x88,0x88,0xf0,0xf8,0x80,0x80,0x80,0xf0, + 0x80,0x80,0x80,0xf8,0x80,0x80,0x80,0x80, + 0xf0,0x80,0x80,0x80,0xf8,0x68,0x98,0x88, + 0x88,0x98,0x80,0x80,0x88,0x70,0x88,0x88, + 0x88,0x88,0xf8,0x88,0x88,0x88,0x88,0xe0, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xe0, + 0x70,0x88,0x88,0x08,0x08,0x08,0x08,0x08, + 0x08,0x88,0x88,0x90,0xa0,0xc0,0xa0,0x90, + 0x88,0x88,0xf8,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x88,0x88,0x88,0xa8,0xa8, + 0xd8,0xd8,0x88,0x88,0x88,0x98,0x98,0xa8, + 0xa8,0xc8,0xc8,0x88,0x88,0x70,0x88,0x88, + 0x88,0x88,0x88,0x88,0x88,0x70,0x80,0x80, + 0x80,0x80,0xf0,0x88,0x88,0x88,0xf0,0x08, + 0x10,0x70,0xa8,0x88,0x88,0x88,0x88,0x88, + 0x88,0x70,0x88,0x88,0x90,0xa0,0xf0,0x88, + 0x88,0x88,0xf0,0x70,0x88,0x08,0x08,0x70, + 0x80,0x80,0x88,0x70,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0xf8,0x70,0x88,0x88, + 0x88,0x88,0x88,0x88,0x88,0x88,0x20,0x20, + 0x50,0x50,0x50,0x88,0x88,0x88,0x88,0x50, + 0x50,0xf8,0xa8,0xa8,0x88,0x88,0x88,0x88, + 0x88,0x88,0x50,0x50,0x20,0x50,0x50,0x88, + 0x88,0x20,0x20,0x20,0x20,0x20,0x50,0x50, + 0x88,0x88,0xf8,0x80,0x40,0x40,0x20,0x10, + 0x10,0x08,0xf8,0xf0,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0xf0,0x08,0x08, + 0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80, + 0xf0,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x10,0x10,0xf0,0x88,0x50,0x20,0xfe,0x20, + 0x40,0x80,0x80,0x68,0x98,0x88,0x78,0x08, + 0x88,0x70,0xb0,0xc8,0x88,0x88,0x88,0xc8, + 0xb0,0x80,0x80,0x70,0x88,0x80,0x80,0x80, + 0x88,0x70,0x68,0x98,0x88,0x88,0x88,0x98, + 0x68,0x08,0x08,0x70,0x88,0x80,0xf8,0x88, + 0x88,0x70,0x40,0x40,0x40,0x40,0x40,0x40, + 0xf0,0x40,0x38,0x70,0x88,0x08,0x68,0x98, + 0x88,0x88,0x88,0x98,0x68,0x88,0x88,0x88, + 0x88,0x88,0xc8,0xb0,0x80,0x80,0x20,0x20, + 0x20,0x20,0x20,0x20,0xe0,0x00,0x20,0x60, + 0x90,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x70,0x00,0x10,0x88,0x88,0x90,0xe0,0xa0, + 0x90,0x88,0x80,0x80,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0xe0,0xa8,0xa8,0xa8, + 0xa8,0xa8,0xa8,0xd0,0x88,0x88,0x88,0x88, + 0x88,0xc8,0xb0,0x70,0x88,0x88,0x88,0x88, + 0x88,0x70,0x80,0x80,0x80,0xb0,0xc8,0x88, + 0x88,0x88,0xc8,0xb0,0x08,0x08,0x08,0x68, + 0x98,0x88,0x88,0x88,0x98,0x68,0x80,0x80, + 0x80,0x80,0x80,0xc8,0xb0,0x70,0x88,0x08, + 0x70,0x80,0x88,0x70,0x30,0x40,0x40,0x40, + 0x40,0x40,0xf0,0x40,0x40,0x68,0x98,0x88, + 0x88,0x88,0x88,0x88,0x20,0x20,0x50,0x50, + 0x88,0x88,0x88,0x50,0xa8,0xa8,0xa8,0xa8, + 0x88,0x88,0x88,0x88,0x50,0x20,0x50,0x88, + 0x88,0x70,0x88,0x08,0x68,0x98,0x88,0x88, + 0x88,0x88,0x88,0xf8,0x80,0x40,0x20,0x10, + 0x08,0xf8,0x18,0x20,0x20,0x20,0x20,0x20, + 0xc0,0x20,0x20,0x20,0x20,0x18,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0xc0,0x20,0x20,0x20,0x20,0x20, + 0x18,0x20,0x20,0x20,0x20,0xc0,0x98,0xb4, + 0x64,0x80,0x80,0x80,0x80,0x80,0x80,0x00, + 0x80,0x80,0x20,0x20,0x70,0x88,0x80,0x80, + 0x88,0x70,0x20,0x20,0xb0,0x48,0x40,0x40, + 0xf0,0x40,0x40,0x48,0x30,0x88,0x70,0x88, + 0x88,0x70,0x88,0x70,0x20,0xf8,0x20,0xf8, + 0x50,0x50,0x88,0x88,0x80,0x80,0x80,0x80, + 0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x80, + 0x70,0x88,0x10,0x28,0x48,0x88,0x90,0xa0, + 0x40,0x88,0x70,0xd8,0x38,0x44,0x92,0xaa, + 0xa2,0xaa,0x92,0x44,0x38,0xf8,0x00,0x68, + 0x90,0x70,0x10,0x60,0x12,0x24,0x48,0x90, + 0x48,0x24,0x12,0x08,0x08,0xf8,0xf0,0x38, + 0x44,0xaa,0xaa,0xb2,0xaa,0xb2,0x44,0x38, + 0xe0,0x60,0x90,0x90,0x60,0xf8,0x00,0x20, + 0x20,0xf8,0x20,0x20,0xe0,0x40,0x20,0xa0, + 0x40,0xc0,0x20,0x40,0x20,0xc0,0x80,0x40, + 0x80,0x80,0xb4,0xc8,0x88,0x88,0x88,0x88, + 0x28,0x28,0x28,0x28,0x28,0x68,0xa8,0xa8, + 0xa8,0x7c,0x80,0x80,0xc0,0x20,0x40,0xe0, + 0x40,0x40,0xc0,0x40,0xf8,0x00,0x70,0x88, + 0x88,0x88,0x70,0x90,0x48,0x24,0x12,0x24, + 0x48,0x90,0x04,0x9e,0x54,0x2c,0x14,0xe8, + 0x44,0x40,0xc0,0x40,0x1c,0x08,0x84,0x54, + 0x28,0x10,0xe8,0x44,0x40,0xc0,0x40,0x04, + 0x9e,0x54,0x2c,0xd4,0x28,0x44,0x20,0xc0, + 0x70,0x88,0x80,0x40,0x20,0x20,0x00,0x00, + 0x20,0x20,0x88,0x88,0xf8,0x88,0x50,0x50, + 0x20,0x20,0x00,0x20,0x40,0x88,0x88,0xf8, + 0x88,0x50,0x50,0x20,0x20,0x00,0x20,0x10, + 0x88,0x88,0xf8,0x88,0x50,0x50,0x20,0x20, + 0x00,0x50,0x20,0x88,0x88,0xf8,0x88,0x50, + 0x50,0x20,0x20,0x00,0xb0,0x68,0x88,0x88, + 0xf8,0x88,0x50,0x50,0x20,0x20,0x00,0xd8, + 0x88,0x88,0xf8,0x88,0x50,0x50,0x20,0x20, + 0x20,0x50,0x20,0x9c,0x90,0xf0,0x90,0x5c, + 0x50,0x30,0x30,0x1c,0x60,0x10,0x20,0x70, + 0x88,0x80,0x80,0x80,0x80,0x80,0x88,0x70, + 0xf8,0x80,0x80,0x80,0xf0,0x80,0x80,0xf8, + 0x00,0x20,0x40,0xf8,0x80,0x80,0x80,0xf0, + 0x80,0x80,0xf8,0x00,0x20,0x10,0xf8,0x80, + 0x80,0x80,0xf0,0x80,0x80,0xf8,0x00,0x50, + 0x20,0xf8,0x80,0x80,0x80,0xf0,0x80,0x80, + 0xf8,0x00,0xd8,0xe0,0x40,0x40,0x40,0x40, + 0x40,0x40,0xe0,0x00,0x40,0x80,0xe0,0x40, + 0x40,0x40,0x40,0x40,0x40,0xe0,0x00,0x40, + 0x20,0xe0,0x40,0x40,0x40,0x40,0x40,0x40, + 0xe0,0x00,0xa0,0x40,0x70,0x20,0x20,0x20, + 0x20,0x20,0x20,0x70,0x00,0xd8,0x78,0x44, + 0x44,0x44,0xf4,0x44,0x44,0x44,0x78,0x88, + 0x98,0x98,0xa8,0xa8,0xc8,0xc8,0x88,0x00, + 0xb0,0x68,0x70,0x88,0x88,0x88,0x88,0x88, + 0x88,0x70,0x00,0x20,0x40,0x70,0x88,0x88, + 0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x10, + 0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x70, + 0x00,0x50,0x20,0x70,0x88,0x88,0x88,0x88, + 0x88,0x88,0x70,0x00,0xb0,0x68,0x70,0x88, + 0x88,0x88,0x88,0x88,0x88,0x70,0x00,0xd8, + 0x88,0x50,0x20,0x50,0x88,0xb8,0x44,0x64, + 0x64,0x54,0x4c,0x4c,0x44,0x3a,0x70,0x88, + 0x88,0x88,0x88,0x88,0x88,0x88,0x00,0x20, + 0x40,0x70,0x88,0x88,0x88,0x88,0x88,0x88, + 0x88,0x00,0x20,0x10,0x70,0x88,0x88,0x88, + 0x88,0x88,0x88,0x88,0x00,0x50,0x20,0x70, + 0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x00, + 0xd8,0x20,0x20,0x20,0x20,0x50,0x50,0x88, + 0x88,0x00,0x20,0x10,0xe0,0x40,0x78,0x44, + 0x44,0x44,0x78,0x40,0xe0,0xb0,0x88,0x88, + 0x88,0x90,0xa0,0x90,0x90,0x60,0x68,0x98, + 0x88,0x78,0x08,0x88,0x70,0x00,0x20,0x40, + 0x68,0x98,0x88,0x78,0x08,0x88,0x70,0x00, + 0x20,0x10,0x68,0x98,0x88,0x78,0x08,0x88, + 0x70,0x00,0x50,0x20,0x68,0x98,0x88,0x78, + 0x08,0x88,0x70,0x00,0xb0,0x68,0x68,0x98, + 0x88,0x78,0x08,0x88,0x70,0x00,0xd8,0x68, + 0x98,0x88,0x78,0x08,0x88,0x70,0x00,0x20, + 0x50,0x20,0x6c,0x92,0x90,0x7e,0x12,0x92, + 0x6c,0x60,0x10,0x20,0x70,0x88,0x80,0x80, + 0x80,0x88,0x70,0x70,0x88,0x80,0xf8,0x88, + 0x88,0x70,0x00,0x20,0x40,0x70,0x88,0x80, + 0xf8,0x88,0x88,0x70,0x00,0x20,0x10,0x70, + 0x88,0x80,0xf8,0x88,0x88,0x70,0x00,0x50, + 0x20,0x70,0x88,0x80,0xf8,0x88,0x88,0x70, + 0x00,0xd8,0x20,0x20,0x20,0x20,0x20,0x20, + 0xe0,0x00,0x20,0x40,0x20,0x20,0x20,0x20, + 0x20,0x20,0xe0,0x00,0x20,0x10,0x20,0x20, + 0x20,0x20,0x20,0x20,0xe0,0x00,0xa0,0x40, + 0x20,0x20,0x20,0x20,0x20,0x20,0xe0,0x00, + 0xd8,0x70,0x88,0x88,0x88,0x88,0x88,0x78, + 0x10,0xd0,0x20,0xd0,0x88,0x88,0x88,0x88, + 0x88,0xc8,0xb0,0x00,0xb0,0x68,0x70,0x88, + 0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x40, + 0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00, + 0x20,0x10,0x70,0x88,0x88,0x88,0x88,0x88, + 0x70,0x00,0x50,0x20,0x70,0x88,0x88,0x88, + 0x88,0x88,0x70,0x00,0xb0,0x68,0x70,0x88, + 0x88,0x88,0x88,0x88,0x70,0x00,0xd8,0x10, + 0x10,0x00,0xfe,0x00,0x10,0x10,0xb8,0x44, + 0x64,0x54,0x4c,0x44,0x3a,0x68,0x98,0x88, + 0x88,0x88,0x88,0x88,0x00,0x20,0x40,0x68, + 0x98,0x88,0x88,0x88,0x88,0x88,0x00,0x20, + 0x10,0x68,0x98,0x88,0x88,0x88,0x88,0x88, + 0x00,0x50,0x20,0x68,0x98,0x88,0x88,0x88, + 0x88,0x88,0x00,0xd8,0x70,0x88,0x08,0x68, + 0x98,0x88,0x88,0x88,0x88,0x88,0x00,0x20, + 0x10,0xe0,0x40,0x58,0x64,0x44,0x44,0x44, + 0x64,0x58,0x40,0xc0,0x70,0x88,0x08,0x68, + 0x98,0x88,0x88,0x88,0x88,0x88,0x00,0xd8, +}; + +BMF_FontData BMF_font_scr14 = { + 0, -3, + 7, 11, + { + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0, 0, 0, 0, 16, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0, 0, 0, 0, 7, -1}, + {1, 9, -3, 0, 7, 0}, + {3, 4, -2, -5, 7, 9}, + {7, 9, 0, 0, 7, 13}, + {5, 10, -1, 1, 7, 22}, + {7, 9, 0, 0, 7, 32}, + {6, 9, 0, 0, 7, 41}, + {3, 4, -2, -5, 7, 50}, + {3, 11, -2, 1, 7, 54}, + {3, 11, -2, 1, 7, 65}, + {5, 6, -1, -2, 7, 76}, + {5, 5, -1, -2, 7, 82}, + {2, 4, -2, 2, 7, 87}, + {5, 1, -1, -4, 7, 91}, + {1, 2, -3, 0, 7, 92}, + {5, 10, -1, 0, 7, 94}, + {5, 9, -1, 0, 7, 104}, + {3, 9, -2, 0, 7, 113}, + {5, 9, -1, 0, 7, 122}, + {5, 9, -1, 0, 7, 131}, + {5, 9, -1, 0, 7, 140}, + {5, 9, -1, 0, 7, 149}, + {5, 9, -1, 0, 7, 158}, + {5, 9, -1, 0, 7, 167}, + {5, 9, -1, 0, 7, 176}, + {5, 9, -1, 0, 7, 185}, + {1, 6, -3, 0, 7, 194}, + {2, 8, -2, 1, 7, 200}, + {5, 9, -1, 0, 7, 208}, + {5, 3, -1, -3, 7, 217}, + {5, 9, -1, 0, 7, 220}, + {5, 9, -1, 0, 7, 229}, + {5, 9, -1, 0, 7, 238}, + {5, 9, -1, 0, 7, 247}, + {5, 9, -1, 0, 7, 256}, + {5, 9, -1, 0, 7, 265}, + {5, 9, -1, 0, 7, 274}, + {5, 9, -1, 0, 7, 283}, + {5, 9, -1, 0, 7, 292}, + {5, 9, -1, 0, 7, 301}, + {5, 9, -1, 0, 7, 310}, + {3, 9, -2, 0, 7, 319}, + {5, 9, -1, 0, 7, 328}, + {5, 9, -1, 0, 7, 337}, + {5, 9, -1, 0, 7, 346}, + {5, 9, -1, 0, 7, 355}, + {5, 9, -1, 0, 7, 364}, + {5, 9, -1, 0, 7, 373}, + {5, 9, -1, 0, 7, 382}, + {5, 11, -1, 2, 7, 391}, + {5, 9, -1, 0, 7, 402}, + {5, 9, -1, 0, 7, 411}, + {5, 9, -1, 0, 7, 420}, + {5, 9, -1, 0, 7, 429}, + {5, 9, -1, 0, 7, 438}, + {5, 9, -1, 0, 7, 447}, + {5, 9, -1, 0, 7, 456}, + {5, 9, -1, 0, 7, 465}, + {5, 9, -1, 0, 7, 474}, + {4, 11, -2, 1, 7, 483}, + {5, 10, -1, 0, 7, 494}, + {4, 11, -1, 1, 7, 504}, + {5, 3, -1, -6, 7, 515}, + {7, 1, 0, 2, 7, 518}, + {3, 4, -2, -5, 7, 519}, + {5, 7, -1, 0, 7, 523}, + {5, 9, -1, 0, 7, 530}, + {5, 7, -1, 0, 7, 539}, + {5, 9, -1, 0, 7, 546}, + {5, 7, -1, 0, 7, 555}, + {5, 9, -1, 0, 7, 562}, + {5, 10, -1, 3, 7, 571}, + {5, 9, -1, 0, 7, 581}, + {3, 9, -2, 0, 7, 590}, + {4, 12, -1, 3, 7, 599}, + {5, 9, -1, 0, 7, 611}, + {3, 9, -2, 0, 7, 620}, + {5, 7, -1, 0, 7, 629}, + {5, 7, -1, 0, 7, 636}, + {5, 7, -1, 0, 7, 643}, + {5, 10, -1, 3, 7, 650}, + {5, 10, -1, 3, 7, 660}, + {5, 7, -1, 0, 7, 670}, + {5, 7, -1, 0, 7, 677}, + {4, 9, -1, 0, 7, 684}, + {5, 7, -1, 0, 7, 693}, + {5, 7, -1, 0, 7, 700}, + {5, 7, -1, 0, 7, 707}, + {5, 7, -1, 0, 7, 714}, + {5, 10, -1, 3, 7, 721}, + {5, 7, -1, 0, 7, 731}, + {5, 12, -1, 2, 7, 738}, + {1, 12, -3, 2, 7, 750}, + {5, 12, -1, 2, 7, 762}, + {6, 3, 0, -3, 7, 774}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {1, 9, -3, 2, 7, 777}, + {5, 10, -1, 0, 7, 786}, + {5, 9, -1, 0, 7, 796}, + {5, 6, -1, -3, 7, 805}, + {5, 9, -1, 0, 7, 811}, + {1, 12, -3, 2, 7, 820}, + {5, 11, -1, 2, 7, 832}, + {5, 1, -1, -8, 7, 843}, + {7, 9, 0, 0, 7, 844}, + {5, 7, -1, -2, 7, 853}, + {7, 7, 0, 0, 7, 860}, + {5, 3, -1, -3, 7, 867}, + {4, 1, -1, -4, 7, 870}, + {7, 9, 0, 0, 7, 871}, + {3, 1, -2, -8, 7, 880}, + {4, 4, -1, -4, 7, 881}, + {5, 7, -1, 0, 7, 885}, + {3, 5, -2, -5, 7, 892}, + {3, 5, -2, -5, 7, 897}, + {2, 2, -3, -8, 7, 902}, + {6, 8, -1, 2, 7, 904}, + {6, 10, 0, 1, 7, 912}, + {1, 2, -3, -3, 7, 922}, + {3, 3, -2, 3, 7, 924}, + {3, 5, -2, -5, 7, 927}, + {5, 7, -1, -2, 7, 932}, + {7, 7, 0, 0, 7, 939}, + {7, 10, 0, 0, 7, 946}, + {6, 11, 0, 1, 7, 956}, + {7, 9, 0, -1, 7, 967}, + {5, 10, -1, 3, 7, 976}, + {5, 11, -1, 0, 7, 986}, + {5, 11, -1, 0, 7, 997}, + {5, 11, -1, 0, 7, 1008}, + {5, 11, -1, 0, 7, 1019}, + {5, 10, -1, 0, 7, 1030}, + {5, 11, -1, 0, 7, 1040}, + {6, 9, 0, 0, 7, 1051}, + {5, 12, -1, 3, 7, 1060}, + {5, 11, -1, 0, 7, 1072}, + {5, 11, -1, 0, 7, 1083}, + {5, 11, -1, 0, 7, 1094}, + {5, 10, -1, 0, 7, 1105}, + {3, 11, -2, 0, 7, 1115}, + {3, 11, -2, 0, 7, 1126}, + {3, 11, -2, 0, 7, 1137}, + {5, 10, -1, 0, 7, 1148}, + {6, 9, 0, 0, 7, 1158}, + {5, 11, -1, 0, 7, 1167}, + {5, 11, -1, 0, 7, 1178}, + {5, 11, -1, 0, 7, 1189}, + {5, 11, -1, 0, 7, 1200}, + {5, 11, -1, 0, 7, 1211}, + {5, 10, -1, 0, 7, 1222}, + {5, 5, -1, -1, 7, 1232}, + {7, 9, 0, 0, 7, 1237}, + {5, 11, -1, 0, 7, 1246}, + {5, 11, -1, 0, 7, 1257}, + {5, 11, -1, 0, 7, 1268}, + {5, 10, -1, 0, 7, 1279}, + {5, 11, -1, 0, 7, 1289}, + {6, 9, 0, 0, 7, 1300}, + {5, 9, -1, 0, 7, 1309}, + {5, 10, -1, 0, 7, 1318}, + {5, 10, -1, 0, 7, 1328}, + {5, 10, -1, 0, 7, 1338}, + {5, 10, -1, 0, 7, 1348}, + {5, 9, -1, 0, 7, 1358}, + {5, 11, -1, 0, 7, 1367}, + {7, 7, 0, 0, 7, 1378}, + {5, 10, -1, 3, 7, 1385}, + {5, 10, -1, 0, 7, 1395}, + {5, 10, -1, 0, 7, 1405}, + {5, 10, -1, 0, 7, 1415}, + {5, 9, -1, 0, 7, 1425}, + {3, 10, -2, 0, 7, 1434}, + {4, 10, -2, 0, 7, 1444}, + {3, 10, -2, 0, 7, 1454}, + {5, 9, -2, 0, 7, 1464}, + {5, 11, -1, 0, 7, 1473}, + {5, 10, -1, 0, 7, 1484}, + {5, 10, -1, 0, 7, 1494}, + {5, 10, -1, 0, 7, 1504}, + {5, 10, -1, 0, 7, 1514}, + {5, 10, -1, 0, 7, 1524}, + {5, 9, -1, 0, 7, 1534}, + {7, 7, 0, 0, 7, 1543}, + {7, 7, 0, 0, 7, 1550}, + {5, 10, -1, 0, 7, 1557}, + {5, 10, -1, 0, 7, 1567}, + {5, 10, -1, 0, 7, 1577}, + {5, 9, -1, 0, 7, 1587}, + {5, 13, -1, 3, 7, 1596}, + {6, 11, 0, 2, 7, 1609}, + {5, 12, -1, 3, 7, 1620}, + }, + bitmap_data +}; + +#endif + diff --git a/intern/bmfont/intern/BMF_font_scr15.cpp b/intern/bmfont/intern/BMF_font_scr15.cpp new file mode 100644 index 00000000000..708420410c6 --- /dev/null +++ b/intern/bmfont/intern/BMF_font_scr15.cpp @@ -0,0 +1,525 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BMF_FontData.h" + +#include "BMF_Settings.h" + +#if BMF_INCLUDE_SCR15 + +static unsigned char bitmap_data[]= { + 0x80,0x80,0x00,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x90,0x90,0x90,0x90,0x48,0x48, + 0x48,0xfe,0x24,0x24,0x24,0x7f,0x12,0x12, + 0x20,0x70,0xa8,0xa8,0x28,0x30,0x60,0xa0, + 0xa8,0xa8,0x70,0x20,0x8c,0x52,0x52,0x2c, + 0x10,0x10,0x68,0x94,0x94,0x62,0x72,0x8c, + 0x84,0x8a,0x50,0x20,0x30,0x48,0x48,0x30, + 0x80,0x40,0x60,0x60,0x10,0x20,0x40,0x40, + 0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x20, + 0x10,0x80,0x40,0x20,0x20,0x10,0x10,0x10, + 0x10,0x10,0x20,0x20,0x40,0x80,0x20,0xa8, + 0x70,0x70,0xa8,0x20,0x10,0x10,0x10,0xfe, + 0x10,0x10,0x10,0x80,0x40,0x20,0x60,0x60, + 0xfc,0xc0,0xc0,0x80,0x80,0x40,0x40,0x20, + 0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x78, + 0x84,0x84,0xc4,0xa4,0x94,0x8c,0x84,0x84, + 0x78,0xe0,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0xc0,0x40,0xfc,0x80,0x40,0x20,0x10, + 0x08,0x04,0x84,0x84,0x78,0x78,0x84,0x04, + 0x04,0x04,0x38,0x04,0x04,0x84,0x78,0x08, + 0x08,0x08,0xfc,0x88,0x48,0x48,0x28,0x18, + 0x08,0x78,0x84,0x04,0x04,0x04,0xf8,0x80, + 0x80,0x80,0xfc,0x78,0x84,0x84,0x84,0x84, + 0xf8,0x80,0x80,0x84,0x78,0x20,0x20,0x20, + 0x10,0x10,0x08,0x08,0x04,0x04,0xfc,0x78, + 0x84,0x84,0x84,0x84,0x78,0x84,0x84,0x84, + 0x78,0x78,0x84,0x04,0x04,0x7c,0x84,0x84, + 0x84,0x84,0x78,0xc0,0xc0,0x00,0x00,0x00, + 0xc0,0xc0,0x80,0x40,0xc0,0xc0,0x00,0x00, + 0x00,0xc0,0xc0,0x04,0x08,0x10,0x20,0x40, + 0x80,0x40,0x20,0x10,0x08,0x04,0xfc,0x00, + 0x00,0xfc,0x80,0x40,0x20,0x10,0x08,0x04, + 0x08,0x10,0x20,0x40,0x80,0x10,0x10,0x00, + 0x10,0x10,0x08,0x04,0x84,0x84,0x78,0x38, + 0x44,0x80,0x98,0xa4,0xa4,0x9c,0x84,0x48, + 0x30,0x84,0x84,0xfc,0x84,0x48,0x48,0x48, + 0x30,0x30,0x30,0xf8,0x84,0x84,0x84,0x84, + 0xf8,0x84,0x84,0x84,0xf8,0x78,0x84,0x84, + 0x80,0x80,0x80,0x80,0x84,0x84,0x78,0xf0, + 0x88,0x84,0x84,0x84,0x84,0x84,0x84,0x88, + 0xf0,0xfc,0x80,0x80,0x80,0x80,0xf8,0x80, + 0x80,0x80,0xfc,0x80,0x80,0x80,0x80,0x80, + 0xf8,0x80,0x80,0x80,0xfc,0x74,0x8c,0x84, + 0x84,0x84,0x9c,0x80,0x80,0x84,0x78,0x84, + 0x84,0x84,0x84,0x84,0xfc,0x84,0x84,0x84, + 0x84,0xe0,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0xe0,0x70,0x88,0x88,0x08,0x08, + 0x08,0x08,0x08,0x08,0x08,0x84,0x84,0x88, + 0x90,0xa0,0xc0,0xa0,0x90,0x88,0x84,0xfc, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x82,0x82,0x92,0x92,0xaa,0xaa,0xc6, + 0xc6,0x82,0x82,0x84,0x8c,0x8c,0x94,0x94, + 0xa4,0xa4,0xc4,0xc4,0x84,0x78,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x78,0x80, + 0x80,0x80,0x80,0xf8,0x84,0x84,0x84,0x84, + 0xf8,0x04,0x08,0x10,0x78,0xa4,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x78,0x84,0x84, + 0x88,0x90,0xf8,0x84,0x84,0x84,0x84,0xf8, + 0x78,0x84,0x84,0x04,0x18,0x60,0x80,0x84, + 0x84,0x78,0x10,0x10,0x10,0x10,0x10,0x10, + 0x10,0x10,0x10,0xfe,0x78,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x30,0x30, + 0x30,0x48,0x48,0x48,0x84,0x84,0x84,0x84, + 0x44,0x44,0x44,0xaa,0xaa,0xaa,0x92,0x92, + 0x92,0x82,0x84,0x84,0x48,0x48,0x30,0x30, + 0x48,0x48,0x84,0x84,0x10,0x10,0x10,0x10, + 0x10,0x28,0x44,0x44,0x82,0x82,0xfc,0x80, + 0x40,0x40,0x20,0x10,0x08,0x08,0x04,0xfc, + 0xf0,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0xf0,0x04,0x04,0x08, + 0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80, + 0x80,0xf0,0x10,0x10,0x10,0x10,0x10,0x10, + 0x10,0x10,0x10,0x10,0x10,0xf0,0x88,0x50, + 0x20,0xff,0x20,0x40,0xc0,0xc0,0x74,0x88, + 0x88,0x78,0x08,0x88,0x70,0xb8,0xc4,0x84, + 0x84,0x84,0xc4,0xb8,0x80,0x80,0x80,0x78, + 0x84,0x80,0x80,0x80,0x84,0x78,0x74,0x8c, + 0x84,0x84,0x84,0x8c,0x74,0x04,0x04,0x04, + 0x78,0x84,0x80,0xfc,0x84,0x84,0x78,0x20, + 0x20,0x20,0x20,0x20,0x20,0xf8,0x20,0x20, + 0x1c,0x78,0x84,0x04,0x04,0x74,0x8c,0x84, + 0x84,0x84,0x8c,0x74,0x84,0x84,0x84,0x84, + 0x84,0xc4,0xb8,0x80,0x80,0x80,0x20,0x20, + 0x20,0x20,0x20,0x20,0xe0,0x00,0x20,0x20, + 0x70,0x88,0x08,0x08,0x08,0x08,0x08,0x08, + 0x08,0x08,0x38,0x00,0x08,0x08,0x84,0x88, + 0x90,0xe0,0xa0,0x90,0x88,0x80,0x80,0x80, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0xe0,0x92,0x92,0x92,0x92,0x92,0x92, + 0xec,0x84,0x84,0x84,0x84,0x84,0xc4,0xb8, + 0x78,0x84,0x84,0x84,0x84,0x84,0x78,0x80, + 0x80,0x80,0x80,0xb8,0xc4,0x84,0x84,0x84, + 0xc4,0xb8,0x04,0x04,0x04,0x04,0x74,0x8c, + 0x84,0x84,0x84,0x8c,0x74,0x80,0x80,0x80, + 0x80,0x80,0xc4,0xb8,0x78,0x84,0x04,0x78, + 0x80,0x84,0x78,0x1c,0x20,0x20,0x20,0x20, + 0x20,0xf8,0x20,0x20,0x74,0x8c,0x84,0x84, + 0x84,0x84,0x84,0x30,0x30,0x48,0x48,0x84, + 0x84,0x84,0x6c,0x92,0x92,0x92,0x92,0x82, + 0x82,0x84,0x84,0x48,0x30,0x48,0x84,0x84, + 0x78,0x84,0x04,0x04,0x74,0x8c,0x84,0x84, + 0x84,0x84,0x84,0xfc,0x80,0x40,0x20,0x10, + 0x08,0xfc,0x1c,0x20,0x20,0x20,0x20,0x20, + 0xc0,0x20,0x20,0x20,0x20,0x20,0x1c,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0xe0,0x10,0x10, + 0x10,0x10,0x10,0x0c,0x10,0x10,0x10,0x10, + 0x10,0xe0,0x98,0xb4,0x64,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x00,0x80,0x80,0x20, + 0x20,0x70,0x88,0x80,0x80,0x88,0x70,0x20, + 0x20,0xb8,0x44,0x40,0x40,0xf0,0x40,0x40, + 0x40,0x48,0x30,0x84,0x78,0x84,0x84,0x84, + 0x78,0x84,0x38,0x10,0x7c,0x10,0x7c,0x28, + 0x44,0x44,0x82,0x82,0x80,0x80,0x80,0x80, + 0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80, + 0x80,0x80,0x78,0x84,0x04,0x18,0x24,0x44, + 0x84,0x88,0x90,0x60,0x80,0x84,0x78,0xd8, + 0x38,0x44,0x92,0xaa,0xa2,0xaa,0x92,0x44, + 0x38,0xf8,0x00,0x68,0x90,0x70,0x10,0x60, + 0x09,0x12,0x24,0x48,0x90,0x48,0x24,0x12, + 0x09,0x04,0x04,0xfc,0xfc,0x38,0x44,0xaa, + 0xaa,0xb2,0xaa,0xb2,0x44,0x38,0xf0,0x60, + 0x90,0x90,0x60,0xfe,0x00,0x10,0x10,0x10, + 0xfe,0x10,0x10,0x10,0xf0,0x40,0x20,0x90, + 0x60,0xe0,0x10,0x60,0x10,0xe0,0x80,0x40, + 0x80,0x80,0x80,0xb4,0xc8,0x88,0x88,0x88, + 0x88,0x88,0x24,0x24,0x24,0x24,0x24,0x24, + 0x64,0xa4,0xa4,0xa4,0xa4,0x7e,0xc0,0xc0, + 0x20,0x40,0xe0,0x40,0x40,0xc0,0x40,0xf8, + 0x00,0x70,0x88,0x88,0x88,0x70,0x90,0x48, + 0x24,0x12,0x09,0x12,0x24,0x48,0x90,0x04, + 0x9e,0x54,0x2c,0x14,0xe8,0x44,0x42,0xc0, + 0x40,0x1e,0x08,0x84,0x52,0x2c,0x10,0xe8, + 0x44,0x42,0xc0,0x40,0x04,0x9e,0x54,0x2c, + 0xd4,0x28,0x44,0x22,0xc0,0x78,0x84,0x84, + 0x80,0x40,0x20,0x20,0x00,0x20,0x20,0x84, + 0x84,0xfc,0x84,0x48,0x48,0x30,0x30,0x00, + 0x20,0x40,0x84,0x84,0xfc,0x84,0x48,0x48, + 0x30,0x30,0x00,0x10,0x08,0x84,0x84,0xfc, + 0x84,0x48,0x48,0x30,0x30,0x00,0x48,0x30, + 0x84,0x84,0xfc,0x84,0x48,0x48,0x30,0x30, + 0x00,0x98,0x64,0x84,0x84,0xfc,0x84,0x48, + 0x48,0x30,0x30,0x00,0x6c,0x84,0x84,0xfc, + 0x84,0x48,0x48,0x30,0x30,0x30,0x48,0x30, + 0x9e,0x90,0x90,0xf0,0x90,0x5c,0x50,0x50, + 0x30,0x1e,0x30,0x08,0x10,0x78,0x84,0x84, + 0x80,0x80,0x80,0x80,0x84,0x84,0x78,0xfc, + 0x80,0x80,0x80,0xf8,0x80,0x80,0xfc,0x00, + 0x20,0x40,0xfc,0x80,0x80,0x80,0xf8,0x80, + 0x80,0xfc,0x00,0x10,0x08,0xfc,0x80,0x80, + 0x80,0xf8,0x80,0x80,0xfc,0x00,0x48,0x30, + 0xfc,0x80,0x80,0x80,0xf8,0x80,0x80,0xfc, + 0x00,0x6c,0xe0,0x40,0x40,0x40,0x40,0x40, + 0x40,0xe0,0x00,0x40,0x80,0xe0,0x40,0x40, + 0x40,0x40,0x40,0x40,0xe0,0x00,0x40,0x20, + 0xe0,0x40,0x40,0x40,0x40,0x40,0x40,0xe0, + 0x00,0x90,0x60,0x70,0x20,0x20,0x20,0x20, + 0x20,0x20,0x70,0x00,0xd8,0x78,0x44,0x42, + 0x42,0x42,0xf2,0x42,0x42,0x44,0x78,0x84, + 0x8c,0x94,0x94,0xa4,0xa4,0xc4,0x84,0x00, + 0x98,0x64,0x78,0x84,0x84,0x84,0x84,0x84, + 0x84,0x78,0x00,0x20,0x40,0x78,0x84,0x84, + 0x84,0x84,0x84,0x84,0x78,0x00,0x10,0x08, + 0x78,0x84,0x84,0x84,0x84,0x84,0x84,0x78, + 0x00,0x48,0x30,0x78,0x84,0x84,0x84,0x84, + 0x84,0x84,0x78,0x00,0x98,0x64,0x78,0x84, + 0x84,0x84,0x84,0x84,0x84,0x78,0x00,0x6c, + 0x84,0x48,0x30,0x30,0x48,0x84,0xbc,0x42, + 0x62,0x52,0x52,0x4a,0x4a,0x46,0x42,0x3d, + 0x78,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x00,0x20,0x40,0x78,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x00,0x10,0x08,0x78,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x00,0x48, + 0x30,0x78,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x00,0x6c,0x10,0x10,0x10,0x10,0x28, + 0x44,0x44,0x82,0x00,0x10,0x08,0xe0,0x40, + 0x7c,0x42,0x42,0x42,0x42,0x7c,0x40,0xe0, + 0x98,0xa4,0x84,0x84,0x84,0x88,0xb0,0x88, + 0x88,0x70,0x74,0x88,0x88,0x78,0x08,0x88, + 0x70,0x00,0x20,0x40,0x74,0x88,0x88,0x78, + 0x08,0x88,0x70,0x00,0x20,0x10,0x74,0x88, + 0x88,0x78,0x08,0x88,0x70,0x00,0x48,0x30, + 0x74,0x88,0x88,0x78,0x08,0x88,0x70,0x00, + 0x98,0x64,0x74,0x88,0x88,0x78,0x08,0x88, + 0x70,0x00,0xd8,0x74,0x88,0x88,0x78,0x08, + 0x88,0x70,0x00,0x30,0x48,0x30,0x6c,0x92, + 0x90,0x7e,0x12,0x92,0x6c,0x30,0x08,0x10, + 0x78,0x84,0x80,0x80,0x80,0x84,0x78,0x78, + 0x84,0x80,0xfc,0x84,0x84,0x78,0x00,0x20, + 0x40,0x78,0x84,0x80,0xfc,0x84,0x84,0x78, + 0x00,0x10,0x08,0x78,0x84,0x80,0xfc,0x84, + 0x84,0x78,0x00,0x48,0x30,0x78,0x84,0x80, + 0xfc,0x84,0x84,0x78,0x00,0x6c,0x20,0x20, + 0x20,0x20,0x20,0x20,0xe0,0x00,0x40,0x80, + 0x20,0x20,0x20,0x20,0x20,0x20,0xe0,0x00, + 0x40,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0xe0,0x00,0x90,0x60,0x10,0x10,0x10,0x10, + 0x10,0x10,0x70,0x00,0xd8,0x78,0x84,0x84, + 0x84,0x84,0x84,0x7c,0x04,0xc8,0x30,0xc8, + 0x84,0x84,0x84,0x84,0x84,0xc4,0xb8,0x00, + 0x98,0x64,0x78,0x84,0x84,0x84,0x84,0x84, + 0x78,0x00,0x20,0x40,0x78,0x84,0x84,0x84, + 0x84,0x84,0x78,0x00,0x10,0x08,0x78,0x84, + 0x84,0x84,0x84,0x84,0x78,0x00,0x48,0x30, + 0x78,0x84,0x84,0x84,0x84,0x84,0x78,0x00, + 0x98,0x64,0x78,0x84,0x84,0x84,0x84,0x84, + 0x78,0x00,0x00,0x6c,0x30,0x00,0x00,0xfc, + 0x00,0x00,0x30,0xbc,0x62,0x52,0x4a,0x46, + 0x42,0x3d,0x74,0x8c,0x84,0x84,0x84,0x84, + 0x84,0x00,0x20,0x40,0x74,0x8c,0x84,0x84, + 0x84,0x84,0x84,0x00,0x20,0x10,0x74,0x8c, + 0x84,0x84,0x84,0x84,0x84,0x00,0x48,0x30, + 0x74,0x8c,0x84,0x84,0x84,0x84,0x84,0x00, + 0x00,0x6c,0x78,0x84,0x04,0x04,0x74,0x8c, + 0x84,0x84,0x84,0x84,0x84,0x00,0x20,0x10, + 0xe0,0x40,0x40,0x5c,0x62,0x42,0x42,0x42, + 0x62,0x5c,0x40,0x40,0xc0,0x78,0x84,0x04, + 0x04,0x74,0x8c,0x84,0x84,0x84,0x84,0x84, + 0x00,0x00,0x6c, +}; + +BMF_FontData BMF_font_scr15 = { + 0, -4, + 8, 11, + { + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0, 0, 0, 0, 8, -1}, + {1, 10, -3, 0, 8, 0}, + {4, 4, -2, -6, 8, 10}, + {8, 10, 0, 0, 8, 14}, + {5, 12, -1, 1, 8, 24}, + {7, 10, 0, 0, 8, 36}, + {7, 10, 0, 0, 8, 46}, + {3, 4, -2, -6, 8, 56}, + {4, 13, -2, 2, 8, 60}, + {4, 13, -2, 2, 8, 73}, + {5, 6, -1, -2, 8, 86}, + {7, 7, 0, -1, 8, 92}, + {3, 5, -2, 3, 8, 99}, + {6, 1, -1, -4, 8, 104}, + {2, 2, -3, 0, 8, 105}, + {6, 12, -1, 1, 8, 107}, + {6, 10, -1, 0, 8, 119}, + {3, 10, -3, 0, 8, 129}, + {6, 10, -1, 0, 8, 139}, + {6, 10, -1, 0, 8, 149}, + {6, 10, -1, 0, 8, 159}, + {6, 10, -1, 0, 8, 169}, + {6, 10, -1, 0, 8, 179}, + {6, 10, -1, 0, 8, 189}, + {6, 10, -1, 0, 8, 199}, + {6, 10, -1, 0, 8, 209}, + {2, 7, -3, 0, 8, 219}, + {2, 9, -3, 2, 8, 226}, + {6, 11, -1, 1, 8, 235}, + {6, 4, -1, -3, 8, 246}, + {6, 11, -1, 1, 8, 250}, + {6, 10, -1, 0, 8, 261}, + {6, 10, -1, 0, 8, 271}, + {6, 10, -1, 0, 8, 281}, + {6, 10, -1, 0, 8, 291}, + {6, 10, -1, 0, 8, 301}, + {6, 10, -1, 0, 8, 311}, + {6, 10, -1, 0, 8, 321}, + {6, 10, -1, 0, 8, 331}, + {6, 10, -1, 0, 8, 341}, + {6, 10, -1, 0, 8, 351}, + {3, 10, -2, 0, 8, 361}, + {5, 10, -1, 0, 8, 371}, + {6, 10, -1, 0, 8, 381}, + {6, 10, -1, 0, 8, 391}, + {7, 10, 0, 0, 8, 401}, + {6, 10, -1, 0, 8, 411}, + {6, 10, -1, 0, 8, 421}, + {6, 10, -1, 0, 8, 431}, + {6, 13, -1, 3, 8, 441}, + {6, 10, -1, 0, 8, 454}, + {6, 10, -1, 0, 8, 464}, + {7, 10, 0, 0, 8, 474}, + {6, 10, -1, 0, 8, 484}, + {6, 10, -1, 0, 8, 494}, + {7, 10, 0, 0, 8, 504}, + {6, 10, -1, 0, 8, 514}, + {7, 10, 0, 0, 8, 524}, + {6, 10, -1, 0, 8, 534}, + {4, 13, -2, 2, 8, 544}, + {6, 12, -1, 1, 8, 557}, + {4, 13, -2, 2, 8, 569}, + {5, 3, -1, -6, 8, 582}, + {8, 1, 0, 3, 8, 585}, + {3, 4, -2, -6, 8, 586}, + {6, 7, -1, 0, 8, 590}, + {6, 10, -1, 0, 8, 597}, + {6, 7, -1, 0, 8, 607}, + {6, 10, -1, 0, 8, 614}, + {6, 7, -1, 0, 8, 624}, + {6, 10, -1, 0, 8, 631}, + {6, 11, -1, 4, 8, 641}, + {6, 10, -1, 0, 8, 652}, + {3, 10, -2, 0, 8, 662}, + {5, 14, -1, 4, 8, 672}, + {6, 10, -1, 0, 8, 686}, + {3, 10, -2, 0, 8, 696}, + {7, 7, 0, 0, 8, 706}, + {6, 7, -1, 0, 8, 713}, + {6, 7, -1, 0, 8, 720}, + {6, 11, -1, 4, 8, 727}, + {6, 11, -1, 4, 8, 738}, + {6, 7, -1, 0, 8, 749}, + {6, 7, -1, 0, 8, 756}, + {6, 9, -1, 0, 8, 763}, + {6, 7, -1, 0, 8, 772}, + {6, 7, -1, 0, 8, 779}, + {7, 7, 0, 0, 8, 786}, + {6, 7, -1, 0, 8, 793}, + {6, 11, -1, 4, 8, 800}, + {6, 7, -1, 0, 8, 811}, + {6, 13, -1, 2, 8, 818}, + {1, 14, -3, 3, 8, 831}, + {6, 13, -1, 2, 8, 845}, + {6, 3, -1, -3, 8, 858}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {0,0,0,0,0, -1}, + {1, 10, -3, 3, 8, 861}, + {5, 10, -1, 0, 8, 871}, + {6, 10, -1, 0, 8, 881}, + {6, 7, -1, -2, 8, 891}, + {7, 10, 0, 0, 8, 898}, + {1, 14, -3, 3, 8, 908}, + {6, 13, -1, 3, 8, 922}, + {5, 1, -1, -9, 8, 935}, + {7, 9, 0, 0, 8, 936}, + {5, 7, -1, -3, 8, 945}, + {8, 9, 0, 0, 8, 952}, + {6, 3, -1, -3, 8, 961}, + {6, 1, -1, -4, 8, 964}, + {7, 9, 0, 0, 8, 965}, + {4, 1, -2, -9, 8, 974}, + {4, 4, -2, -4, 8, 975}, + {7, 9, 0, 0, 8, 979}, + {4, 5, -2, -5, 8, 988}, + {4, 5, -2, -5, 8, 993}, + {2, 2, -3, -9, 8, 998}, + {6, 10, -1, 3, 8, 1000}, + {7, 12, 0, 2, 8, 1010}, + {2, 1, -3, -4, 8, 1022}, + {3, 3, -3, 3, 8, 1023}, + {3, 5, -3, -5, 8, 1026}, + {5, 7, -1, -3, 8, 1031}, + {8, 9, 0, 0, 8, 1038}, + {7, 10, 0, 0, 8, 1047}, + {7, 11, 0, 1, 8, 1057}, + {7, 9, 0, -1, 8, 1068}, + {6, 10, -1, 2, 8, 1077}, + {6, 11, -1, 0, 8, 1087}, + {6, 11, -1, 0, 8, 1098}, + {6, 11, -1, 0, 8, 1109}, + {6, 11, -1, 0, 8, 1120}, + {6, 10, -1, 0, 8, 1131}, + {6, 11, -1, 0, 8, 1141}, + {7, 10, 0, 0, 8, 1152}, + {6, 13, -1, 3, 8, 1162}, + {6, 11, -1, 0, 8, 1175}, + {6, 11, -1, 0, 8, 1186}, + {6, 11, -1, 0, 8, 1197}, + {6, 10, -1, 0, 8, 1208}, + {3, 11, -2, 0, 8, 1218}, + {3, 11, -2, 0, 8, 1229}, + {4, 11, -2, 0, 8, 1240}, + {5, 10, -1, 0, 8, 1251}, + {7, 10, 0, 0, 8, 1261}, + {6, 11, -1, 0, 8, 1271}, + {6, 11, -1, 0, 8, 1282}, + {6, 11, -1, 0, 8, 1293}, + {6, 11, -1, 0, 8, 1304}, + {6, 11, -1, 0, 8, 1315}, + {6, 10, -1, 0, 8, 1326}, + {6, 6, -1, -1, 8, 1336}, + {8, 10, 0, 0, 8, 1342}, + {6, 11, -1, 0, 8, 1352}, + {6, 11, -1, 0, 8, 1363}, + {6, 11, -1, 0, 8, 1374}, + {6, 10, -1, 0, 8, 1385}, + {7, 11, 0, 0, 8, 1395}, + {7, 10, 0, 0, 8, 1406}, + {6, 10, -1, 0, 8, 1416}, + {6, 10, -1, 0, 8, 1426}, + {6, 10, -1, 0, 8, 1436}, + {6, 10, -1, 0, 8, 1446}, + {6, 10, -1, 0, 8, 1456}, + {6, 9, -1, 0, 8, 1466}, + {6, 11, -1, 0, 8, 1475}, + {7, 7, 0, 0, 8, 1486}, + {6, 10, -1, 3, 8, 1493}, + {6, 10, -1, 0, 8, 1503}, + {6, 10, -1, 0, 8, 1513}, + {6, 10, -1, 0, 8, 1523}, + {6, 9, -1, 0, 8, 1533}, + {3, 10, -2, 0, 8, 1542}, + {3, 10, -2, 0, 8, 1552}, + {4, 10, -2, 0, 8, 1562}, + {5, 9, -1, 0, 8, 1572}, + {6, 11, -1, 0, 8, 1581}, + {6, 10, -1, 0, 8, 1592}, + {6, 10, -1, 0, 8, 1602}, + {6, 10, -1, 0, 8, 1612}, + {6, 10, -1, 0, 8, 1622}, + {6, 10, -1, 0, 8, 1632}, + {6, 10, -1, 0, 8, 1642}, + {6, 7, -1, 0, 8, 1652}, + {8, 7, 0, 0, 8, 1659}, + {6, 10, -1, 0, 8, 1666}, + {6, 10, -1, 0, 8, 1676}, + {6, 10, -1, 0, 8, 1686}, + {6, 10, -1, 0, 8, 1696}, + {6, 14, -1, 4, 8, 1706}, + {7, 13, 0, 3, 8, 1720}, + {6, 14, -1, 4, 8, 1733}, + }, + bitmap_data +}; + +#endif + diff --git a/intern/bmfont/intern/Makefile b/intern/bmfont/intern/Makefile new file mode 100644 index 00000000000..cd02eaa31bd --- /dev/null +++ b/intern/bmfont/intern/Makefile @@ -0,0 +1,44 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# bmfont intern Makefile +# + +LIBNAME = bmfont +DIR = $(OCGDIR)/intern/$(LIBNAME) + +include nan_compile.mk + +CCFLAGS += $(LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I. +CPPFLAGS += -I.. +CPPFLAGS += -I$(OPENGL_HEADERS) + diff --git a/intern/bmfont/make/msvc_6_0/BMF_bmfont.dsp b/intern/bmfont/make/msvc_6_0/BMF_bmfont.dsp new file mode 100644 index 00000000000..dba5b13bb92 --- /dev/null +++ b/intern/bmfont/make/msvc_6_0/BMF_bmfont.dsp @@ -0,0 +1,174 @@ +# Microsoft Developer Studio Project File - Name="BMF_bmfont" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=BMF_bmfont - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "BMF_bmfont.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "BMF_bmfont.mak" CFG="BMF_bmfont - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "BMF_bmfont - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "BMF_bmfont - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "BMF_bmfont - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../../../../obj/windows/intern/BMF_bmfont/" +# PROP Intermediate_Dir "../../../../../obj/windows/intern/BMF_bmfont/" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "../.." /I "../../intern" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copying BMFONT files library (release target) to lib tree. +PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\..\develop\lib\windows\bmfont\include\" ECHO Copying lib COPY "..\..\..\..\..\obj\windows\intern\BMF_bmfont\BMF_bmfont.lib" "..\..\..\..\..\develop\lib\windows\bmfont\lib\libbmfont.a" ECHO Done +# End Special Build Tool + +!ELSEIF "$(CFG)" == "BMF_bmfont - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../../../../obj/windows/intern/BMF_bmfont/debug" +# PROP Intermediate_Dir "../../../../../obj/windows/intern/BMF_bmfont/debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../.." /I "../../intern" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copying BMFONT files library (debug target) to lib tree. +PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\..\develop\lib\windows\bmfont\include" ECHO Copying lib COPY "..\..\..\..\..\obj\windows\intern\BMF_bmfont\debug\BMF_bmfont.lib" "..\..\..\..\..\develop\lib\windows\bmfont\lib\debug\libbmfont.a" ECHO Done +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "BMF_bmfont - Win32 Release" +# Name "BMF_bmfont - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\intern\BMF_Api.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BMF_BitmapFont.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BMF_font_helv10.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BMF_font_helv12.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BMF_font_helvb10.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BMF_font_helvb12.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BMF_font_helvb14.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BMF_font_helvb8.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BMF_font_scr12.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BMF_font_scr14.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BMF_font_scr15.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Group "intern" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\intern\BMF_BitmapFont.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BMF_FontData.h +# End Source File +# End Group +# Begin Group "extern" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\BMF_Api.h +# End Source File +# Begin Source File + +SOURCE=..\..\BMF_Fonts.h +# End Source File +# Begin Source File + +SOURCE=..\..\BMF_Settings.h +# End Source File +# End Group +# End Group +# End Target +# End Project diff --git a/intern/bmfont/make/msvc_6_0/BMF_bmfont.dsw b/intern/bmfont/make/msvc_6_0/BMF_bmfont.dsw new file mode 100644 index 00000000000..729f4ac5cb2 --- /dev/null +++ b/intern/bmfont/make/msvc_6_0/BMF_bmfont.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "BMF_bmfont"=.\BMF_bmfont.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/intern/bmfont/test/BMF_Test.cpp b/intern/bmfont/test/BMF_Test.cpp new file mode 100644 index 00000000000..37d2f45d164 --- /dev/null +++ b/intern/bmfont/test/BMF_Test.cpp @@ -0,0 +1,225 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * Simple test file for the bitmap font library using GHOST. + * @author Maarten Gribnau + * @date November 15, 2001 + */ + +#include <iostream> + +#if defined(WIN32) || defined(__APPLE__) +#ifdef WIN32 +#include <windows.h> +#include <GL/gl.h> +#else // WIN32 +// __APPLE__ is defined +#include <AGL/gl.h> +#endif // WIN32 +#else // defined(WIN32) || defined(__APPLE__) +#include <GL/gl.h> +#endif // defined(WIN32) || defined(__APPLE__) + + +#include "STR_String.h" +#include "GHOST_Rect.h" + +#include "GHOST_ISystem.h" +#include "GHOST_IEvent.h" +#include "GHOST_IEventConsumer.h" + +#include "BMF_Api.h" + +static class Application* fApp; +static GHOST_ISystem* fSystem = 0; + + +static void drawGL() +{ + GLint x = 10, y = 10; + + ::glRasterPos2i(x, y); + BMF_FontPtr font = BMF_GetFont(BMF_kHelvetica10); + BMF_DrawString(font, "Helvetica 10 point"); + y += 14; + ::glRasterPos2i(x, y); + font = BMF_GetFont(BMF_kHelvetica12); + BMF_DrawString(font, "Helvetica 12 point"); + y += 16; + ::glRasterPos2i(x, y); + font = BMF_GetFont(BMF_kHelveticaBold8); + BMF_DrawString(font, "Helvetica Bold 8 point"); + y += 12; + ::glRasterPos2i(x, y); + font = BMF_GetFont(BMF_kHelveticaBold10); + BMF_DrawString(font, "Helvetica Bold 10 point"); + y += 14; + ::glRasterPos2i(x, y); + font = BMF_GetFont(BMF_kHelveticaBold12); + BMF_DrawString(font, "Helvetica Bold 12 point"); + y += 16; + ::glRasterPos2i(x, y); + font = BMF_GetFont(BMF_kHelveticaBold14); + BMF_DrawString(font, "Helvetica Bold 14 point"); + y += 18; + ::glRasterPos2i(x, y); + font = BMF_GetFont(BMF_kScreen12); + BMF_DrawString(font, "Screen 12 point"); + y += 16; + ::glRasterPos2i(x, y); + font = BMF_GetFont(BMF_kScreen14); + BMF_DrawString(font, "Screen 14 point"); + y += 18; + ::glRasterPos2i(x, y); + font = BMF_GetFont(BMF_kScreen15); + BMF_DrawString(font, "Screen 15 point"); +} + + +static void setViewPortGL(GHOST_IWindow* window) +{ + window->activateDrawingContext(); + GHOST_Rect bnds; + window->getClientBounds(bnds); + + ::glViewport(0, 0, bnds.getWidth(), bnds.getHeight()); + + ::glMatrixMode(GL_PROJECTION); + ::glLoadIdentity(); + ::glOrtho(0, bnds.getWidth(), 0, bnds.getHeight(), -10, 10); + + ::glClearColor(.2f,0.0f,0.0f,0.0f); + ::glClear(GL_COLOR_BUFFER_BIT); +} + + + +class Application : public GHOST_IEventConsumer { +public: + Application(GHOST_ISystem* system); + virtual bool processEvent(GHOST_IEvent* event); + + GHOST_ISystem* m_system; + GHOST_IWindow* m_mainWindow; + bool m_exitRequested; +}; + + +Application::Application(GHOST_ISystem* system) + : m_system(system), m_mainWindow(0), m_exitRequested(false) +{ + fApp = this; + + // Create the main window + STR_String title1 ("gears - main window"); + m_mainWindow = system->createWindow(title1, 10, 64, 320, 200, GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL); + if (!m_mainWindow) { + std::cout << "could not create main window\n"; + exit(-1); + } +} + + +bool Application::processEvent(GHOST_IEvent* event) +{ + bool handled = true; + + switch (event->getType()) { + case GHOST_kEventWindowClose: + { + GHOST_TEventWindowData* windowData = (GHOST_TEventWindowData*)((GHOST_IEvent*)event)->getData(); + GHOST_IWindow* window = windowData->window; + if (window == m_mainWindow) { + exit(0); + } + else { + m_system->disposeWindow(window); + } + } + break; + + case GHOST_kEventWindowActivate: + handled = false; + break; + case GHOST_kEventWindowDeactivate: + handled = false; + break; + case GHOST_kEventWindowUpdate: + { + GHOST_TEventWindowData* windowData = (GHOST_TEventWindowData*)((GHOST_IEvent*)event)->getData(); + GHOST_IWindow* window = windowData->window; + if (!m_system->validWindow(window)) break; + { + setViewPortGL(window); + drawGL(); + window->swapBuffers(); + } + } + break; + + default: + handled = false; + break; + } + return handled; +} + + +int main(int /*argc*/, char** /*argv*/) +{ + // Create the system + GHOST_ISystem::createSystem(); + fSystem = GHOST_ISystem::getSystem(); + + if (fSystem) { + // Create an application object + Application app (fSystem); + + // Add the application as event consumer + fSystem->addEventConsumer(&app); + + // Enter main loop + while (!app.m_exitRequested) { + fSystem->processEvents(); + fSystem->dispatchEvents(); + } + } + + // Dispose the system + GHOST_ISystem::disposeSystem(); + + return 0; +} + diff --git a/intern/bmfont/test/make/msvc_6_0/BMF_Test.dsp b/intern/bmfont/test/make/msvc_6_0/BMF_Test.dsp new file mode 100644 index 00000000000..13e6e65f706 --- /dev/null +++ b/intern/bmfont/test/make/msvc_6_0/BMF_Test.dsp @@ -0,0 +1,109 @@ +# Microsoft Developer Studio Project File - Name="BMF_Test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=BMF_Test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "BMF_Test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "BMF_Test.mak" CFG="BMF_Test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "BMF_Test - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "BMF_Test - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "BMF_Test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../../../../../obj/windows/intern/BMF_bmfont/test" +# PROP Intermediate_Dir "../../../../../../obj/windows/intern/BMF_bmfont/test" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../" /I "../../../../../lib/windows/string/include" /I "../../../../../lib/windows/ghost/include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libstring.a libghost.a glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /machine:I386 /libpath:"../../../../../lib/windows/string/lib" /libpath:"../../../../../lib/windows/ghost/lib" + +!ELSEIF "$(CFG)" == "BMF_Test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../../../../../obj/windows/intern/BMF_bmfont/test/debug" +# PROP Intermediate_Dir "../../../../../../obj/windows/intern/BMF_bmfont/test/debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../" /I "../../../../../lib/windows/string/include" /I "../../../../../lib/windows/ghost/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glu32.lib opengl32.lib libstring.a libghost.a user32.lib gdi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"../../../../../lib/windows/string/lib" /libpath:"../../../../../lib/windows/ghost/lib" + +!ENDIF + +# Begin Target + +# Name "BMF_Test - Win32 Release" +# Name "BMF_Test - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\intern\BMF_glut_helb8.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\intern\BMF_glut_helb8.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\BMF_Test.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/intern/bmfont/test/make/msvc_6_0/BMF_Test.dsw b/intern/bmfont/test/make/msvc_6_0/BMF_Test.dsw new file mode 100644 index 00000000000..5baacb9adf7 --- /dev/null +++ b/intern/bmfont/test/make/msvc_6_0/BMF_Test.dsw @@ -0,0 +1,44 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "BMF_Test"=.\BMF_Test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name BMF_bmfont + End Project Dependency +}}} + +############################################################################### + +Project: "BMF_bmfont"=..\..\..\make\msvc_6_0\BMF_bmfont.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/intern/bsp/Makefile b/intern/bsp/Makefile new file mode 100644 index 00000000000..371c43c848a --- /dev/null +++ b/intern/bsp/Makefile @@ -0,0 +1,55 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# bsp main makefile. +# + +include nan_definitions.mk + +LIBNAME = bsp +SOURCEDIR = intern/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = intern +# not yet TESTDIRS = test + +include nan_subdirs.mk + +install: all debug + @[ -d $(NAN_BSP) ] || mkdir $(NAN_BSP) + @[ -d $(NAN_BSP)/include ] || mkdir $(NAN_BSP)/include + @[ -d $(NAN_BSP)/lib ] || mkdir $(NAN_BSP)/lib + @[ -d $(NAN_BSP)/lib/debug ] || mkdir $(NAN_BSP)/lib/debug + cp -f $(DIR)/libbsp.a $(NAN_BSP)/lib/ + cp -f $(DIR)/debug/libbsp.a $(NAN_BSP)/lib/debug/ + cp -f extern/*.h $(NAN_BSP)/include/ + + + + diff --git a/intern/bsp/extern/CSG_BooleanOps.h b/intern/bsp/extern/CSG_BooleanOps.h new file mode 100755 index 00000000000..0a348fdc05e --- /dev/null +++ b/intern/bsp/extern/CSG_BooleanOps.h @@ -0,0 +1,428 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef CSG_BOOLEANOPS_H + +#define CSG_BOOLEANOPS_H + +/** + * @section Interface structures for CSG module. + * This interface falls into 2 categories. + * The first section deals with an abstract mesh description + * between blender and this module. The second deals with + * the module functions. + * The CSG module needs to know about the following entities: + */ + +/** + * CSG_IFace -- an interface polygon structure. + * vertex_index is a fixed size array of 4 elements containing indices into + * an abstract vertex container. 3 or 4 of these elements may be used to + * describe either quads or triangles. + * vertex_number is the number of vertices in this face - either 3 or 4. + * vertex_colors is an array of {r,g,b} triplets one for each vertex index. + * tex_coords is an array of {u,v} triplets one for each vertex index. + * user_data is a pointer to arbitary data of fixed width , + * this data is copied around with the face, and duplicated if a face is + * split. Contains things like material index. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + int vertex_index[4]; + int vertex_number; + + void *user_face_vertex_data[4]; + void *user_face_data; +} CSG_IFace; + +/** + * CSG_IVertex -- an interface vertex structure. + * position is the location of the vertex in 3d space. + */ + +typedef struct { + float position[3]; +} CSG_IVertex; + +/** + * The actual useful data contained in a group of faces is + * described by the following struct + */ + +/** + * Descibes the data stored in a mesh available through the + * CSG_IFace interface. + * user_data_size is the number of bytes of user_data associated with each CSG_IFace + * user_face_vertex_data size is the number of bytes of user data associated with + * every face vertex tuple. + * . + */ + +typedef struct CSG_MeshPropertyDescriptor{ + unsigned int user_face_vertex_data_size; + unsigned int user_data_size; +} CSG_MeshPropertyDescriptor; + + + +/** + * @section Iterator abstraction. + * + * The CSG module asks blender to fill in an instance of the above + * structure, and requests blender to move up and down (iterate) through + * it's face and vertex containers. + * + * An iterator supports the following functions. + * int IsDone(iterator *it) -- returns true if the iterator has reached + * the end of it's container. + * + * void Fill(iterator *it,DataType *data) -- Return the contents of the + * container at the current iterator position. + * + * void Step(iterator *it) -- increment the iterator to the next position + * in the container. + * + * The iterator is used in the following manner. + * + * MyIterator * iterator = ... + * DataType data; + * + * while (!IsDone(iterator)) { + * Fill(iterator,&data); + * //process information pointed to by data + * ... + * Step(iterator); + * } + * + * The CSG module does not want to know about the implementation of these + * functions so we use the c function ptr mechanism to hide them. Our + * iterator descriptor now looks like this. + */ + +typedef void* CSG_IteratorPtr; + +typedef int (*CSG_FaceItDoneFunc)(CSG_IteratorPtr it); +typedef void (*CSG_FaceItFillFunc)(CSG_IteratorPtr it,CSG_IFace *face); +typedef void (*CSG_FaceItStepFunc)(CSG_IteratorPtr it); +typedef void (*CSG_FaceItResetFunc)(CSG_IteratorPtr it); + +typedef struct CSG_FaceIteratorDescriptor { + CSG_IteratorPtr it; + CSG_FaceItDoneFunc Done; + CSG_FaceItFillFunc Fill; + CSG_FaceItStepFunc Step; + CSG_FaceItResetFunc Reset; + unsigned int num_elements; +} CSG_FaceIteratorDescriptor; + +/** + * Similarly to walk through the vertex arrays we have. + */ +typedef int (*CSG_VertexItDoneFunc)(CSG_IteratorPtr it); +typedef void (*CSG_VertexItFillFunc)(CSG_IteratorPtr it,CSG_IVertex *face); +typedef void (*CSG_VertexItStepFunc)(CSG_IteratorPtr it); +typedef void (*CSG_VertexItResetFunc)(CSG_IteratorPtr it); + +typedef struct CSG_VertexIteratorDescriptor { + CSG_IteratorPtr it; + CSG_VertexItDoneFunc Done; + CSG_VertexItFillFunc Fill; + CSG_VertexItStepFunc Step; + CSG_VertexItResetFunc Reset; + unsigned int num_elements; +} CSG_VertexIteratorDescriptor; + +/** + * The actual iterator structures are not exposed to the CSG module, they + * will contain datatypes specific to blender. + */ + +/** + * @section CSG Module interface functions. + * + * The functions below are to be used in the following way: + * + * // Create a boolean operation handle + * CSG_BooleanOperation *operation = CSG_NewBooleanFunction(); + * if (operation == NULL) { + * // deal with low memory exception + * } + * + * // Describe each mesh operand to the module. + * // NOTE: example properties! + * CSG_MeshPropertyDescriptor propA,propB; + * propA.user_data_size = 0; + * propA.user_face_vertex_data = 0; + * propB.user_face_vertex_data = 0; + * propB.user_data_size = 0; + * + * // Get the output properties of the mesh. + * CSG_MeshPropertyDescriptor output_properties; + * output_properties = CSG_DescibeOperands( + * operation, + * propA, + * propB + * ); + * + * // Report to the user if they will loose any data! + * ... + * + * // Get some mesh iterators for your mesh data structures + * CSG_FaceIteratorDescriptor obA_faces = ... + * CSG_VertexIteratorDescriptor obA_verts = ... + * + * // same for object B + * CSG_FaceIteratorDescriptor obB_faces = ... + * CSG_VertexIteratorDescriptor obB_verts = ... + * + * // perform the operation...! + * + * int success = CSG_PerformBooleanOperation( + * operation, + * e_csg_intersection, + * obA_faces, + * obA_vertices, + * obB_faces, + * obB_vertices + * ); + * + * // if the operation failes report miserable faiulre to user + * // and clear up data structures. + * if (!success) { + * ... + * CSG_FreeBooleanOperation(operation); + * return; + * } + * + * // read the new mesh vertices back from the module + * // and assign to your own mesh structure. + * + * // First we need to create a CSG_IVertex so the module can fill it in. + * CSG_IVertex vertex; + * CSG_VertexIteratorDescriptor * verts_it = CSG_OutputVertexDescriptor(operation); + * + * // initialize your vertex container with the number of verts (verts_it->num_elements) + * + * while (!verts_it->Done(verts_it->it)) { + * verts_it->Fill(verts_it->it,&vertex); + * + * // create a new vertex of your own type and add it + * // to your mesh structure. + * verts_it->Step(verts_it->it); + * } + * // Free the vertex iterator + * CSG_FreeVertexDescriptor(verts_it); + * + * // similarly for faces. + * CSG_IFace face; + * + * // you may need to reserve some memory in face->user_data here. + * + * // initialize your face container with the number of faces (faces_it->num_elements) + * + * CSG_FaceIteratorDescriptor * faces_it = CSG_OutputFaceDescriptor(operation); + * + * while (!faces_it->Done(faces_it->it)) { + * faces_it->Fill(faces_it->it,&face); + * + * // create a new face of your own type and add it + * // to your mesh structure. + * faces_it->Step(&faces_it->it); + * } + * + * // Free the face iterator + * CSG_FreeVertexDescriptor(faces_it); + * + * // that's it free the operation. + * + * CSG_FreeBooleanOperation(operation); + * return; + * + */ + +/** + * Description of boolean operation type. + */ + +typedef enum { + e_csg_union, + e_csg_intersection, + e_csg_difference, + e_csg_classify +} CSG_OperationType; + +/** + * 'Handle' into the CSG module that identifies a particular CSG operation. + * the pointer CSG_info containers module specific data, and should not + * be touched in anyway outside of the module. + */ + +typedef struct { + void *CSG_info; +} CSG_BooleanOperation; + +/** + * Return a ptr to a CSG_BooleanOperation object allocated + * on the heap. The CSG module owns the memory associated with + * the returned ptr, use CSG_FreeBooleanOperation() to free this memory. + */ + CSG_BooleanOperation * +CSG_NewBooleanFunction( + void +); + +/** + * Describe the operands of a boolean function to the module. + * The description takes the form of a pair of CSG_MeshPropertyDescriptors + * one for each input mesh. The operands do not have to have the same + * properties, for example operandA may have vertex colours but operandB none. + * In this case the CSG module will choose the lowest common denominator in + * mesh properies. The function returns a description of + * the output mesh. You can use this to warn the user that certain properties + * will be lost. Of course it also describes what fields in the output mesh + * will contain valid data. + */ + CSG_MeshPropertyDescriptor +CSG_DescibeOperands( + CSG_BooleanOperation * operation, + CSG_MeshPropertyDescriptor operandA_desciption, + CSG_MeshPropertyDescriptor operandB_desciption +); + +/** + * The user data is handled by the BSP modules through + * the following function which is called whenever the + * module needs new face vertex properties (when a face is split). + * d1,d2 are pointers to existing vertex face data. dnew is + * a pointer to an allocated but unfilled area of user data of + * size user_face_vertex_data_size in the CSG_MeshPropertyDescriptor + * returned by a call to the above function. Epsilon is the relative + * distance (between [0,1]) of the new vertex and the vertex associated + * with d1. Use epsilon to interpolate the face vertex data in d1 and d2 + * and fill dnew + */ + +typedef int (*CSG_InterpolateUserFaceVertexDataFunc)(void *d1, void * d2, void *dnew, float epsilon); + + +/** + * Attempt to perform a boolean operation between the 2 objects of the + * desired type. This may fail due to an internal error or lack of memory. + * In this case 0 is returned, otehrwise 1 is returned indicating success. + * @param operation is a 'handle' into the CSG_Module created by CSG_NewBooleanFunction() + * @param op_type is the operation to perform. + * @param obAFaces is an iterator over the faces of objectA, + * @param obAVertices is an iterator over the vertices of objectA + * @param obAFaces is an iterator over the faces of objectB, + * @param obAVertices is an iterator over the vertices of objectB + * @param interp_func the face_vertex data interpolation function.(see above) + * + * All iterators must be valid and pointing to the first element in their + * respective containers. + */ + int +CSG_PerformBooleanOperation( + CSG_BooleanOperation * operation, + CSG_OperationType op_type, + CSG_FaceIteratorDescriptor obAFaces, + CSG_VertexIteratorDescriptor obAVertices, + CSG_FaceIteratorDescriptor obBFaces, + CSG_VertexIteratorDescriptor obBVertices, + CSG_InterpolateUserFaceVertexDataFunc interp_func +); + +/** + * If the a boolean operation was successful, you may access the results + * through the following functions. + * + * CSG_OuputFaceDescriptor() returns a ptr to a CSG_FaceIteratorDesciptor + * allocated on the heap and owned by the CSG module. The iterator is + * positioned at the start of the internal face container. + * CSG_OutputVertexDescriptor() returns a ptr to a CSG_VertexIteratorDescriptor + * allocated on the heap and owned by the CSG module. The iterator is + * positioned at the start of the internal vertex container. + * There is no function to rewind an iterator but you may obtain more + * than one + * iterator at a time. Please use the function CSG_FreeFaceIterator() + * and CSG_FreeVertexIterator to free internal memory allocated for these + * iterators. + * + * If the last operation was not successful, these functions return NULL. + */ + int +CSG_OutputFaceDescriptor( + CSG_BooleanOperation * operation, + CSG_FaceIteratorDescriptor * output +); + + int +CSG_OutputVertexDescriptor( + CSG_BooleanOperation * operation, + CSG_VertexIteratorDescriptor *output +); + +/** + * Clean up functions. + * Free internal memory associated with CSG interface structures. You must + * call these functions on any structures created by the module, even if + * subsequent operations did not succeed. + */ + void +CSG_FreeVertexDescriptor( + CSG_VertexIteratorDescriptor * v_descriptor +); + + void +CSG_FreeFaceDescriptor( + CSG_FaceIteratorDescriptor * f_descriptor +); + +/** + * Free the memory associated with a boolean operation. + * NOTE any iterator descriptor describing the output will become + * invalid after this call and should be freed immediately. + */ + void +CSG_FreeBooleanOperation( + CSG_BooleanOperation *operation +); + +#ifdef __cplusplus +} +#endif + + + +#endif
\ No newline at end of file diff --git a/intern/bsp/intern/BSP_CSGException.h b/intern/bsp/intern/BSP_CSGException.h new file mode 100755 index 00000000000..7224d8b0910 --- /dev/null +++ b/intern/bsp/intern/BSP_CSGException.h @@ -0,0 +1,58 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_CSGException_h + +#define NAN_INCLUDED_CSGException_h + +// stick in more error types as you think of them + +enum BSP_ExceptionType{ + e_split_error, + e_mesh_error, + e_mesh_input_error, + e_param_error, + e_tree_build_error +}; + + +class BSP_CSGException { +public : + BSP_ExceptionType m_e_type; + + BSP_CSGException ( + BSP_ExceptionType type + ) : m_e_type (type) + { + } +}; + +#endif diff --git a/intern/bsp/intern/BSP_CSGHelper.cpp b/intern/bsp/intern/BSP_CSGHelper.cpp new file mode 100644 index 00000000000..72ad30b6f0f --- /dev/null +++ b/intern/bsp/intern/BSP_CSGHelper.cpp @@ -0,0 +1,430 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BSP_CSGHelper.h" + +#include "BSP_CSGMesh.h" +#include "BSP_MeshFragment.h" +#include "BSP_FragTree.h" +#include "BSP_CSGMeshSplitter.h" +#include "BSP_CSGNCMeshSplitter.h" +#include "BSP_Triangulate.h" + +#include "MEM_SmartPtr.h" + +using namespace std; + +BSP_CSGHelper:: +BSP_CSGHelper( +) +{ + // nothing to do +} + + bool +BSP_CSGHelper:: +ComputeOp( + BSP_CSGMesh * obA, + BSP_CSGMesh * obB, + BSP_OperationType op_type, + BSP_CSGMesh & output, + CSG_InterpolateUserFaceVertexDataFunc fv_func +){ + // First work out which parts of polygons we want to keep as we pass stuff + // down the tree. + + BSP_Classification e_ATreeB,e_BTreeA; + bool invertA(false),invertB(false); + + switch (op_type) { + case e_intern_csg_union : + e_ATreeB = e_classified_out; + e_BTreeA = e_classified_out; + break; + case e_intern_csg_intersection : + e_ATreeB = e_classified_in; + e_BTreeA = e_classified_in; + break; + case e_intern_csg_difference : + invertA = true; + e_ATreeB = e_classified_in; + e_BTreeA = e_classified_in; + break; + default : + return false; + } + + if (invertA) { + obA->Invert(); + } + + if (invertB) { + obB->Invert(); + } + + MEM_SmartPtr<BSP_CSGMesh> obA_copy = obA->NewCopy(); + MEM_SmartPtr<BSP_CSGMesh> obB_copy = obB->NewCopy(); + + // ok we need yet another copy... + + MEM_SmartPtr<BSP_CSGMesh> obA_copy2 = obA->NewCopy(); + MEM_SmartPtr<BSP_CSGMesh> obB_copy2 = obB->NewCopy(); + + obA_copy->BuildEdges(); + obB_copy->BuildEdges(); + + // Create a splitter to help chop up the mesh and preserrve. + // mesh connectivity + + MEM_SmartPtr<BSP_CSGMeshSplitter> splitter = new BSP_CSGMeshSplitter(fv_func); + if (splitter == NULL) return false; + + // Create a splitter to help chop the mesh for tree building. + MEM_SmartPtr<BSP_CSGNCMeshSplitter> nc_splitter = new BSP_CSGNCMeshSplitter(); + + if (splitter == NULL || nc_splitter == NULL) return false; + + // Create a tree for both meshes. + + MEM_SmartPtr<BSP_FragTree> treeA = treeA->New(obA,nc_splitter.Ref()); + MEM_SmartPtr<BSP_FragTree> treeB = treeB->New(obB,nc_splitter.Ref()); + + if (treeA == NULL || treeB == NULL) { + return false; + } + + // Classify each object wrt the other tree. + + MEM_SmartPtr<BSP_MeshFragment> AinB = new BSP_MeshFragment(obA_copy2,e_classified_in); + MEM_SmartPtr<BSP_MeshFragment> AoutB = new BSP_MeshFragment(obA_copy2,e_classified_out); + MEM_SmartPtr<BSP_MeshFragment> AonB = new BSP_MeshFragment(obA_copy2,e_classified_on); + + treeB->Classify(obA_copy2,AinB,AoutB,AonB,nc_splitter.Ref()); + + MEM_SmartPtr<BSP_MeshFragment> BinA = new BSP_MeshFragment(obB_copy2,e_classified_in); + MEM_SmartPtr<BSP_MeshFragment> BoutA = new BSP_MeshFragment(obB_copy2,e_classified_out); + MEM_SmartPtr<BSP_MeshFragment> BonA = new BSP_MeshFragment(obB_copy2,e_classified_on); + + treeA->Classify(obB_copy2,BinA,BoutA,BonA,nc_splitter.Ref()); + + // Now we need to work what were the spanning polygons from the original mesh. + // Build a spanning fragment from them and pass split those mothers. + + MEM_SmartPtr<BSP_MeshFragment> frag_BTreeA2 = new BSP_MeshFragment(obA_copy,e_BTreeA); + MEM_SmartPtr<BSP_MeshFragment> AspanningB = new BSP_MeshFragment(obA_copy,e_classified_spanning); + + TranslateSplitFragments(AinB.Ref(),AoutB.Ref(),AonB.Ref(),e_BTreeA,AspanningB.Ref(),frag_BTreeA2.Ref()); + + MEM_SmartPtr<BSP_MeshFragment> frag_ATreeB2 = new BSP_MeshFragment(obB_copy,e_ATreeB); + MEM_SmartPtr<BSP_MeshFragment> BspanningA = new BSP_MeshFragment(obB_copy,e_classified_spanning); + + TranslateSplitFragments(BinA.Ref(),BoutA.Ref(),BonA.Ref(),e_ATreeB,BspanningA.Ref(),frag_ATreeB2.Ref()); + + + MEM_SmartPtr<BSP_MeshFragment> frag_ATreeB = new BSP_MeshFragment(obB_copy,e_ATreeB); + MEM_SmartPtr<BSP_MeshFragment> frag_BTreeA = new BSP_MeshFragment(obA_copy,e_BTreeA); + + if (frag_ATreeB == NULL || frag_BTreeA == NULL) return false; + + // Pass the spanning polygons of copyB through the tree of copyA. + treeA->Push(BspanningA,frag_ATreeB,e_ATreeB,e_classified_spanning,true,splitter.Ref()); + + // Add the result of the push to the fragments we are interested in. + MergeFrags(frag_ATreeB2.Ref(),frag_ATreeB.Ref()); + + // Pass the spanning polygons of copyA through the tree of copyB + treeB->Push(AspanningB,frag_BTreeA,e_BTreeA,e_classified_spanning,false,splitter.Ref()); + MergeFrags(frag_BTreeA2.Ref(),frag_BTreeA.Ref()); + + // Copy the fragments into a new mesh. + DuplicateMesh(frag_ATreeB.Ref(),output); + DuplicateMesh(frag_BTreeA.Ref(),output); + + return true; + +}; + + void +BSP_CSGHelper:: +TranslateSplitFragments( + const BSP_MeshFragment & in_frag, + const BSP_MeshFragment & out_frag, + const BSP_MeshFragment & on_frag, + BSP_Classification keep, + BSP_MeshFragment & spanning_frag, + BSP_MeshFragment & output +){ + + // iterate through the 3 input fragments + // tag the polygons in the output fragments according to + // the classification of the input frags. + + const BSP_CSGMesh *i_mesh = in_frag.Mesh(); + BSP_CSGMesh *o_mesh = output.Mesh(); + + const vector<BSP_MFace> &i_faces = i_mesh->FaceSet(); + vector<BSP_MFace> &o_faces = o_mesh->FaceSet(); + + vector<BSP_FaceInd>::const_iterator if_it = in_frag.FaceSet().begin(); + vector<BSP_FaceInd>::const_iterator if_end = in_frag.FaceSet().end(); + + for (;if_it != if_end; ++if_it) { + int original_index = i_faces[*if_it].OpenTag(); + if (original_index == -1) { + // then this face was never split and the original_index is + // the actual face index. + original_index = *if_it; + } + // tag the output faces with the in flag. + if (o_faces[original_index].OpenTag() == -1) { + o_faces[original_index].SetOpenTag(0); + } + o_faces[original_index].SetOpenTag( + o_faces[original_index].OpenTag() | e_classified_in + ); + } + + // same for out fragments. + if_it = out_frag.FaceSet().begin(); + if_end = out_frag.FaceSet().end(); + + for (;if_it != if_end; ++if_it) { + int original_index = i_faces[*if_it].OpenTag(); + if (original_index == -1) { + // then this face was never split and the original_index is + // the actual face index. + original_index = *if_it; + } + // tag the output faces with the in flag. + if (o_faces[original_index].OpenTag() == -1) { + o_faces[original_index].SetOpenTag(0); + } + o_faces[original_index].SetOpenTag( + o_faces[original_index].OpenTag() | e_classified_out + ); + } + + // on fragments just get set as spanning for now. + + if_it = on_frag.FaceSet().begin(); + if_end = on_frag.FaceSet().end(); + + for (;if_it != if_end; ++if_it) { + int original_index = i_faces[*if_it].OpenTag(); + if (original_index == -1) { + // then this face was never split and the original_index is + // the actual face index. + original_index = *if_it; + } + // tag the output faces with the in flag. + if (o_faces[original_index].OpenTag() == -1) { + o_faces[original_index].SetOpenTag(0); + } + o_faces[original_index].SetOpenTag( + o_faces[original_index].OpenTag() | e_classified_spanning + ); + } + // now run through the output faces. + // collect the ones we are interested in into output + // and collect the spanning faces. + + int of_it = 0; + int of_size = o_faces.size(); + + for (;of_it < of_size; ++of_it) { + + int p_class = o_faces[of_it].OpenTag(); + + if (p_class == int(keep)) { + output.FaceSet().push_back(BSP_FaceInd(of_it)); + } else + if ( + (p_class == (e_classified_in | e_classified_out)) || + p_class == e_classified_spanning + ) { + spanning_frag.FaceSet().push_back(BSP_FaceInd(of_it)); + } + } +} + + + void +BSP_CSGHelper:: +MergeFrags( + const BSP_MeshFragment & in, + BSP_MeshFragment & out +){ + + // Add the 2 frags together. + + out.FaceSet().insert( + out.FaceSet().end(), + in.FaceSet().begin(), + in.FaceSet().end() + ); +} + + + +BSP_CSGHelper:: +~BSP_CSGHelper( +){ + // nothing to do +} + + void +BSP_CSGHelper:: +DuplicateMesh( + const BSP_MeshFragment & frag, + BSP_CSGMesh & output +){ + + // This stuff is a real waste of time. + // much better to create an output iterator based upon + // the 2 mesh fragments alone. + + vector<BSP_MVertex> & o_verts = output.VertexSet(); + BSP_CSGUserData & o_fv_data = output.FaceVertexData(); + BSP_CSGUserData & o_f_data = output.FaceData(); + + // A temporary buffer containing the triangulated + // vertex indices. + + vector<int> triangle_indices; + + BSP_CSGMesh * i_mesh = frag.Mesh(); + + if (i_mesh == NULL) return; + + vector<BSP_MVertex> & i_verts = i_mesh->VertexSet(); + const vector<BSP_MFace> & i_faces = i_mesh->FaceSet(); + BSP_CSGUserData & i_fv_data = i_mesh->FaceVertexData(); + BSP_CSGUserData & i_f_data = i_mesh->FaceData(); + + // iterate through the fragment's face set + const vector<BSP_FaceInd> & frag_faces = frag.FaceSet(); + + vector<BSP_FaceInd>::const_iterator f_faces_it = frag_faces.begin(); + vector<BSP_FaceInd>::const_iterator f_faces_end = frag_faces.end(); + + // We need to keep track of which vertices we are selecting. + vector<int> selected_vi; + + BSP_Triangulate triangulator; + + for (; f_faces_it != f_faces_end; ++f_faces_it) { + + BSP_FaceInd fi = *f_faces_it; + const BSP_MFace &face = i_faces[fi]; + + // duplicate the face + BSP_MFace dup_face(face); + + // iterate through the face's vertex indices. + vector<BSP_VertexInd>::iterator dup_f_verts_it = dup_face.m_verts.begin(); + vector<BSP_VertexInd>::const_iterator dup_f_verts_end = dup_face.m_verts.end(); + + for (; dup_f_verts_it != dup_f_verts_end; ++dup_f_verts_it) { + + if (i_verts[*dup_f_verts_it].SelectTag() == false) { + // copy this vertex onto the output mesh vertex array. + + BSP_VertexInd new_vi(o_verts.size()); + o_verts.push_back(i_verts[*dup_f_verts_it]); + + // should kill the old vertices edge ptrs. + o_verts[new_vi].m_edges.clear(); + + // set the open tag in the old vert to the new one. + i_verts[*dup_f_verts_it].SetOpenTag(new_vi); + + // select the old vertex + i_verts[*dup_f_verts_it].SetSelectTag(true); + selected_vi.push_back(*dup_f_verts_it); + } + + // we have been to this vertex before and there should be + // a corresponding vertex in the new mesh vertex set. + *dup_f_verts_it = i_verts[*dup_f_verts_it].OpenTag(); + } + + // duplicate the face vertex data for this polygon. + + vector<BSP_UserFVInd>::iterator dup_fv_it = dup_face.m_fv_data.begin(); + vector<BSP_UserFVInd>::const_iterator dup_fv_end = dup_face.m_fv_data.end(); + + for (;dup_fv_it != dup_fv_end; ++dup_fv_it) { + *dup_fv_it = o_fv_data.Duplicate(i_fv_data[int(*dup_fv_it)]); + } + + triangle_indices.clear(); + + // Now triangulate the polygon. + if (!triangulator.Process( + o_verts, + dup_face.m_verts, + dup_face.m_plane, + triangle_indices + )) { + // Sometimes the triangulator can fail for very small + // polygons or very thing polygons. This should be + // handled more elegantly but for now we just leave out the + // polygon from the mesh. + continue; + } + + // Run through the result and add in the triangle faces. + + int i; + for (i = 0; i < triangle_indices.size(); i+=3) { + // duplicate the face data for this face. + o_f_data.Duplicate(i_f_data[*f_faces_it]); + + output.AddSubTriangle(dup_face,triangle_indices.begin() + i); + } + } + + // of course we have to deselect the vertices again. + + vector<int>::const_iterator selected_vi_it = selected_vi.begin(); + vector<int>::const_iterator selected_vi_end = selected_vi.end(); + + for (; selected_vi_it != selected_vi_end; ++selected_vi_it) { + i_verts[*selected_vi_it].SetSelectTag(false); + } +} + + + + + + + diff --git a/intern/bsp/intern/BSP_CSGHelper.h b/intern/bsp/intern/BSP_CSGHelper.h new file mode 100644 index 00000000000..f122fc3cf31 --- /dev/null +++ b/intern/bsp/intern/BSP_CSGHelper.h @@ -0,0 +1,99 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BSP_CSGHELPER_H + +#define BSP_CSGHELPER_H + +class BSP_CSGMesh; +class BSP_MeshFragment; + +#include "../extern/CSG_BooleanOps.h" +#include "BSP_MeshPrimitives.h" + +enum BSP_OperationType{ + e_intern_csg_union, + e_intern_csg_intersection, + e_intern_csg_difference +}; + +class BSP_CSGHelper { +public : + + BSP_CSGHelper( + ); + + bool + ComputeOp( + BSP_CSGMesh * obA, + BSP_CSGMesh * obB, + BSP_OperationType op_type, + BSP_CSGMesh & output, + CSG_InterpolateUserFaceVertexDataFunc fv_func + ); + + + ~BSP_CSGHelper( + ); + +private: + + // Iterate through the fragment, + // add new vertices to output, + // map polygons to new vertices. + + void + DuplicateMesh( + const BSP_MeshFragment & frag, + BSP_CSGMesh & output + ); + + void + TranslateSplitFragments( + const BSP_MeshFragment & in_frag, + const BSP_MeshFragment & out_frag, + const BSP_MeshFragment & on_frag, + BSP_Classification keep, + BSP_MeshFragment & spanning_frag, + BSP_MeshFragment & output + ); + + void + MergeFrags( + const BSP_MeshFragment & in, + BSP_MeshFragment & out + ); + + + +}; + +#endif diff --git a/intern/bsp/intern/BSP_CSGISplitter.h b/intern/bsp/intern/BSP_CSGISplitter.h new file mode 100755 index 00000000000..c88a04a7932 --- /dev/null +++ b/intern/bsp/intern/BSP_CSGISplitter.h @@ -0,0 +1,118 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BSP_CSGISplitter_h + +#define BSP_CSGISplitter_h + +class BSP_MeshFragment; +class BSP_CSGMesh; + +class MT_Plane3; + +/** + * This class defines a mesh splitter interface. + * It embodies the action of splitting a mesh by a plane. + * Depending on the context of the operation subclasses + * may wish to define different implementations. For example + * with building a BSP tree from a mesh, the mesh does not + * need to be kept consistent, it doesn't matter if the edges + * are maintained etc. However when pushing polygons through + * a BSP tree (say for CSG operations)it is important to + * try and maintain mesh connectivity and thus a different + * splitter implementation may be needed. + * + * This is an abstract interface class. + */ + +class BSP_CSGISplitter +{ + +public: + + /** + * Split the incoming mesh fragment (frag) + * by the plane, put the output into (in,out and on) + * Subclasses should clear the contents of the + * in_coming fragment. + */ + + virtual + void + Split( + const MT_Plane3& plane, + BSP_MeshFragment *frag, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + BSP_MeshFragment *spanning_frag + )= 0; + + /** + * Split the entire mesh with respect to the plane. + * and place ouput into (in,out and on). + * Subclasses should clear the contents of the + * in_coming fragment. + */ + virtual + void + Split( + BSP_CSGMesh & mesh, + const MT_Plane3& plane, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + BSP_MeshFragment *spanning_frag + )=0; + + virtual + ~BSP_CSGISplitter( + ){ + }; + +protected : + + BSP_CSGISplitter( + ) { + //nothing to do + } + + BSP_CSGISplitter( + const BSP_CSGISplitter & + ) { + //nothing to do + } +}; + + + +#endif + diff --git a/intern/bsp/intern/BSP_CSGMesh.cpp b/intern/bsp/intern/BSP_CSGMesh.cpp new file mode 100755 index 00000000000..d1721cb692b --- /dev/null +++ b/intern/bsp/intern/BSP_CSGMesh.cpp @@ -0,0 +1,883 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + + + +#include "BSP_CSGMesh.h" +#include "MT_assert.h" +#include "CTR_TaggedSetOps.h" +#include "BSP_MeshFragment.h" +#include "MT_Plane3.h" +#include "BSP_CSGException.h" + +// for vector reverse +#include <algorithm> +using namespace std; + +BSP_CSGMesh:: +BSP_CSGMesh( +) : + MEM_RefCountable() +{ + // nothing to do +} + + BSP_CSGMesh * +BSP_CSGMesh:: +New( +){ + return new BSP_CSGMesh(); +} + + BSP_CSGMesh * +BSP_CSGMesh:: +NewCopy( +) const { + + MEM_SmartPtr<BSP_CSGMesh> mesh = New(); + if (mesh == NULL) return NULL; + + mesh->m_bbox_max = m_bbox_max; + mesh->m_bbox_min = m_bbox_min; + + if (m_edges != NULL) { + mesh->m_edges = new vector<BSP_MEdge>(m_edges.Ref()); + if (mesh->m_edges == NULL) return NULL; + } + if (m_verts != NULL) { + mesh->m_verts = new vector<BSP_MVertex>(m_verts.Ref()); + if (mesh->m_verts == NULL) return NULL; + } + if (m_faces != NULL) { + mesh->m_faces = new vector<BSP_MFace>(m_faces.Ref()); + if (mesh->m_faces == NULL) return NULL; + } + if (m_fv_data != NULL) { + mesh->m_fv_data = new BSP_CSGUserData(m_fv_data.Ref()); + if (mesh->m_fv_data == NULL) return NULL; + } + if (m_face_data != NULL) { + mesh->m_face_data = new BSP_CSGUserData(m_face_data.Ref()); + if (mesh->m_face_data == NULL) return NULL; + } + + return mesh.Release(); +} + + void +BSP_CSGMesh:: +Invert( +){ + + vector<BSP_MFace> & faces = FaceSet(); + + vector<BSP_MFace>::const_iterator faces_end = faces.end(); + vector<BSP_MFace>::iterator faces_it = faces.begin(); + + for (; faces_it != faces_end; ++faces_it) { + faces_it->Invert(); + } +} + + bool +BSP_CSGMesh:: +SetVertices( + MEM_SmartPtr<vector<BSP_MVertex> > verts +){ + if (verts == NULL) return false; + + // create polygon and edge arrays and reserve some space. + m_faces = new vector<BSP_MFace>; + if (!m_faces) return false; + + m_faces->reserve(verts->size()/2); + + // previous verts get deleted here. + m_verts = verts; + return true; +} + + void +BSP_CSGMesh:: +SetFaceVertexData( + MEM_SmartPtr<BSP_CSGUserData> fv_data +){ + m_fv_data = fv_data; +} + + void +BSP_CSGMesh:: +SetFaceData( + MEM_SmartPtr<BSP_CSGUserData> f_data +) { + m_face_data = f_data; +} + + + void +BSP_CSGMesh:: +AddPolygon( + const int * verts, + int num_verts +){ + MT_assert(verts != NULL); + MT_assert(num_verts >=3); + + if (verts == NULL || num_verts <3) return; + + const int vertex_num = m_verts->size(); + + // make a polyscone from these vertex indices. + + const BSP_FaceInd fi = m_faces->size(); + m_faces->push_back(BSP_MFace()); + BSP_MFace & face = m_faces->back(); + + insert_iterator<vector<BSP_VertexInd> > insert_point(face.m_verts,face.m_verts.end()); + copy (verts,verts + num_verts,insert_point); + + // compute and store the plane equation for this face. + + MT_Plane3 face_plane = FacePlane(fi); + face.m_plane = face_plane; +}; + + void +BSP_CSGMesh:: +AddPolygon( + const int * verts, + const int * fv_indices, + int num_verts +){ + // This creates a new polygon on the end of the face list. + AddPolygon(verts,num_verts); + + BSP_MFace & face = m_faces->back(); + // now we just fill in the fv indices + + if (fv_indices) { + insert_iterator<vector<BSP_UserFVInd> > insert_point(face.m_fv_data,face.m_fv_data.end()); + copy(fv_indices,fv_indices + num_verts,insert_point); + } else { + face.m_fv_data.insert(face.m_fv_data.end(),num_verts,BSP_UserFVInd::Empty()); + } +} + + + void +BSP_CSGMesh:: +AddSubTriangle( + const BSP_MFace &iface, + const int * index_info +){ + // This creates a new polygon on the end of the face list. + + const BSP_FaceInd fi = m_faces->size(); + m_faces->push_back(BSP_MFace()); + BSP_MFace & face = m_faces->back(); + + face.m_verts.push_back(iface.m_verts[index_info[0]]); + face.m_verts.push_back(iface.m_verts[index_info[1]]); + face.m_verts.push_back(iface.m_verts[index_info[2]]); + + face.m_fv_data.push_back(iface.m_fv_data[index_info[0]]); + face.m_fv_data.push_back(iface.m_fv_data[index_info[1]]); + face.m_fv_data.push_back(iface.m_fv_data[index_info[2]]); + + face.m_plane = iface.m_plane; +} + + +// assumes that the face already has a plane equation + void +BSP_CSGMesh:: +AddPolygon( + const BSP_MFace &face +){ + m_faces->push_back(face); +}; + + + bool +BSP_CSGMesh:: +BuildEdges( +){ + + if (m_faces == NULL) return false; + + if (m_edges != NULL) { + DestroyEdges(); + } + + m_edges = new vector<BSP_MEdge>; + + if (m_edges == NULL) { + return false; + } + + + //iterate through the face set and add edges for all polygon + //edges + + vector<BSP_MFace>::const_iterator f_it_end = FaceSet().end(); + vector<BSP_MFace>::const_iterator f_it_begin = FaceSet().begin(); + vector<BSP_MFace>::iterator f_it = FaceSet().begin(); + + vector<BSP_MVertex> & vertex_set = VertexSet(); + + vector<BSP_EdgeInd> dummy; + + for (;f_it != f_it_end; ++f_it) { + + BSP_MFace & face = *f_it; + + int vertex_num = face.m_verts.size(); + BSP_VertexInd prev_vi(face.m_verts[vertex_num-1]); + + for (int vert = 0; vert < vertex_num; ++vert) { + + BSP_FaceInd fi(f_it - f_it_begin); + InsertEdge(prev_vi,face.m_verts[vert],fi,dummy); + prev_vi = face.m_verts[vert]; + } + + } + dummy.clear(); + return true; +} + + void +BSP_CSGMesh:: +DestroyEdges( +){ + m_edges.Delete(); + + // Run through the vertices + // and clear their edge arrays. + + if (m_verts){ + + vector<BSP_MVertex>::const_iterator vertex_end = VertexSet().end(); + vector<BSP_MVertex>::iterator vertex_it = VertexSet().begin(); + + for (; vertex_it != vertex_end; ++vertex_it) { + vertex_it->m_edges.clear(); + } + } +} + + + BSP_EdgeInd +BSP_CSGMesh:: +FindEdge( + const BSP_VertexInd & v1, + const BSP_VertexInd & v2 +) const { + + vector<BSP_MVertex> &verts = VertexSet(); + vector<BSP_MEdge> &edges = EdgeSet(); + + BSP_MEdge e; + e.m_verts[0] = v1; + e.m_verts[1] = v2; + + vector<BSP_EdgeInd> &v1_edges = verts[v1].m_edges; + vector<BSP_EdgeInd>::const_iterator v1_end = v1_edges.end(); + vector<BSP_EdgeInd>::const_iterator v1_begin = v1_edges.begin(); + + for (; v1_begin != v1_end; ++v1_begin) { + if (edges[*v1_begin] == e) return *v1_begin; + } + + return BSP_EdgeInd::Empty(); +} + + void +BSP_CSGMesh:: +InsertEdge( + const BSP_VertexInd & v1, + const BSP_VertexInd & v2, + const BSP_FaceInd & f, + vector<BSP_EdgeInd> &new_edges +){ + + MT_assert(!v1.IsEmpty()); + MT_assert(!v2.IsEmpty()); + MT_assert(!f.IsEmpty()); + + if (v1.IsEmpty() || v2.IsEmpty() || f.IsEmpty()) { + BSP_CSGException e(e_mesh_error); + throw (e); + } + + vector<BSP_MVertex> &verts = VertexSet(); + vector<BSP_MEdge> &edges = EdgeSet(); + + BSP_EdgeInd e; + + e = FindEdge(v1,v2); + if (e.IsEmpty()) { + // This edge does not exist -- make a new one + + BSP_MEdge temp_e; + temp_e.m_verts[0] = v1; + temp_e.m_verts[1] = v2; + + e = m_edges->size(); + // set the face index from the edge back to this polygon. + temp_e.m_faces.push_back(f); + + m_edges->push_back(temp_e); + + // add the edge index to it's vertices + verts[v1].AddEdge(e); + verts[v2].AddEdge(e); + + new_edges.push_back(e); + + } else { + + // edge already exists + // insure that there is no polygon already + // attached to the other side of this edge + // swap the empty face pointer in edge with f + + BSP_MEdge &edge = edges[e]; + + // set the face index from the edge back to this polygon. + edge.m_faces.push_back(f); + } +} + + +// geometry access +////////////////// + + vector<BSP_MVertex> & +BSP_CSGMesh:: +VertexSet( +) const { + return m_verts.Ref(); +} + + vector<BSP_MFace> & +BSP_CSGMesh:: +FaceSet( +) const { + return m_faces.Ref(); +} + + vector<BSP_MEdge> & +BSP_CSGMesh:: +EdgeSet( +) const { + return m_edges.Ref(); +} + + BSP_CSGUserData & +BSP_CSGMesh:: +FaceVertexData( +) const { + return m_fv_data.Ref(); +} + + BSP_CSGUserData & +BSP_CSGMesh:: +FaceData( +) const { + return m_face_data.Ref(); +} + + +BSP_CSGMesh:: +~BSP_CSGMesh( +){ + // member deletion handled by smart ptr; +} + +// local geometry queries. +///////////////////////// + +// face queries +/////////////// + + void +BSP_CSGMesh:: +FaceVertices( + const BSP_FaceInd & f, + vector<BSP_VertexInd> &output +){ + vector<BSP_MFace> & face_set = FaceSet(); + output.insert( + output.end(), + face_set[f].m_verts.begin(), + face_set[f].m_verts.end() + ); +} + + + void +BSP_CSGMesh:: +FaceEdges( + const BSP_FaceInd & fi, + vector<BSP_EdgeInd> &output +){ + // take intersection of the edges emminating from all the vertices + // of this polygon; + + vector<BSP_MFace> &faces = FaceSet(); + vector<BSP_MEdge> &edges = EdgeSet(); + + const BSP_MFace & f = faces[fi]; + + // collect vertex edges; + + vector<BSP_VertexInd>::const_iterator face_verts_it = f.m_verts.begin(); + vector<BSP_VertexInd>::const_iterator face_verts_end = f.m_verts.end(); + + vector< vector<BSP_EdgeInd> > vertex_edges(f.m_verts.size()); + + int vector_slot = 0; + + for (;face_verts_it != face_verts_end; ++face_verts_it, ++vector_slot) { + VertexEdges(*face_verts_it,vertex_edges[vector_slot]); + } + + int prev = vector_slot - 1; + + // intersect pairs of edge sets + + for (int i = 0; i < vector_slot;i++) { + CTR_TaggedSetOps<BSP_EdgeInd,BSP_MEdge>::IntersectPair(vertex_edges[prev],vertex_edges[i],edges,output); + prev = i; + } + + // should always have 3 or more unique edges per face. + MT_assert(output.size() >=3); + + if (output.size() < 3) { + BSP_CSGException e(e_mesh_error); + throw(e); + } +}; + +// edge queries +/////////////// + + void +BSP_CSGMesh:: +EdgeVertices( + const BSP_EdgeInd & e, + vector<BSP_VertexInd> &output +){ + const vector<BSP_MEdge> &edges = EdgeSet(); + output.push_back(edges[e].m_verts[0]); + output.push_back(edges[e].m_verts[1]); +} + + void +BSP_CSGMesh:: +EdgeFaces( + const BSP_EdgeInd & e, + vector<BSP_FaceInd> &output +){ + + vector<BSP_MEdge> & edge_set = EdgeSet(); + output.insert( + output.end(), + edge_set[e].m_faces.begin(), + edge_set[e].m_faces.end() + ); + +} + +// vertex queries +///////////////// + + void +BSP_CSGMesh:: +VertexEdges( + const BSP_VertexInd &v, + vector<BSP_EdgeInd> &output +){ + + vector<BSP_MVertex> & vertex_set = VertexSet(); + output.insert( + output.end(), + vertex_set[v].m_edges.begin(), + vertex_set[v].m_edges.end() + ); +} + + void +BSP_CSGMesh:: +VertexFaces( + const BSP_VertexInd &vi, + vector<BSP_FaceInd> &output +) { + + vector<BSP_MEdge> &edges = EdgeSet(); + vector<BSP_MFace> &faces = FaceSet(); + vector<BSP_MVertex> &verts = VertexSet(); + + const vector<BSP_EdgeInd> &v_edges = verts[vi].m_edges; + vector<BSP_EdgeInd>::const_iterator e_it = v_edges.begin(); + + for (; e_it != v_edges.end(); ++e_it) { + + BSP_MEdge &e = edges[*e_it]; + + // iterate through the faces of this edge - push unselected + // edges to ouput and then select the edge + + vector<BSP_FaceInd>::const_iterator e_faces_end = e.m_faces.end(); + vector<BSP_FaceInd>::iterator e_faces_it = e.m_faces.begin(); + + for (;e_faces_it != e_faces_end; ++e_faces_it) { + + if (!faces[*e_faces_it].SelectTag()) { + output.push_back(*e_faces_it); + faces[*e_faces_it].SetSelectTag(true); + } + } + } + + // deselect selected faces. + vector<BSP_FaceInd>::iterator f_it = output.begin(); + + for (; f_it != output.end(); ++f_it) { + faces[*f_it].SetSelectTag(false); + } +} + + void +BSP_CSGMesh:: +InsertVertexIntoFace( + BSP_MFace & face, + const BSP_VertexInd & v1, + const BSP_VertexInd & v2, + const BSP_VertexInd & vi, + CSG_InterpolateUserFaceVertexDataFunc fv_split_func, + MT_Scalar epsilon +){ + // We assume that the face vertex data indices + // are consistent with the vertex inidex data. + + // look for v1 + vector<BSP_VertexInd>::iterator result = + find(face.m_verts.begin(),face.m_verts.end(),v1); + + MT_assert(result != face.m_verts.end()); + + BSP_CSGUserData & fv_data = m_fv_data.Ref(); + + // now we have to check on either side of the result for the + // other vertex + + vector<BSP_VertexInd>::iterator prev = result - 1; + if (prev < face.m_verts.begin()) { + prev = face.m_verts.end() -1; + } + if (*prev == v2) { + + // so result <=> v2 and prev <=> v1 + + // create space for new face vertex data + + int vf_i = fv_data.Size(); + fv_data.IncSize(); + + int vf_i2 = prev - face.m_verts.begin(); + int vf_i1 = result - face.m_verts.begin(); + + (*fv_split_func)( + fv_data[int(face.m_fv_data[vf_i1])], + fv_data[int(face.m_fv_data[vf_i2])], + fv_data[vf_i], + epsilon + ); + + // insert vertex data index. + face.m_fv_data.insert(face.m_fv_data.begin() + vf_i1,vf_i); + face.m_verts.insert(result,vi); + + return; + } + + vector<BSP_VertexInd>::iterator next = result + 1; + if (next >= face.m_verts.end()) { + next = face.m_verts.begin(); + } + if (*next == v2) { + + // so result <=> v1 and next <=> v2 + + int vf_i = fv_data.Size(); + fv_data.IncSize(); + + int vf_i2 = int(next - face.m_verts.begin()); + int vf_i1 = int(result - face.m_verts.begin()); + + (*fv_split_func)( + fv_data[int(face.m_fv_data[vf_i1])], + fv_data[int(face.m_fv_data[vf_i2])], + fv_data[vf_i], + epsilon + ); + + // insert vertex data index. + face.m_fv_data.insert(face.m_fv_data.begin() + vf_i2,vf_i); + face.m_verts.insert(next,vi); + + return; + } + + // if we get here we are in trouble. + MT_assert(false); + BSP_CSGException e(e_mesh_error); + throw(e); +} + + void +BSP_CSGMesh:: +SetBBox( + const MT_Vector3 & min, + const MT_Vector3 & max +){ + m_bbox_min = min; + m_bbox_max = max; +} + + + void +BSP_CSGMesh:: +BBox( + MT_Vector3 &min, + MT_Vector3 &max +) const { + min = m_bbox_min; + max = m_bbox_max; +} + + +// Update the BBox +////////////////// + + void +BSP_CSGMesh:: +UpdateBBox( +){ + // TODO +}; + + void +BSP_CSGMesh:: +SC_Classification( + BSP_FaceInd f, + const MT_Plane3& plane +){ + const BSP_MFace & face = FaceSet()[f]; + + vector<BSP_VertexInd>::const_iterator f_verts_it = face.m_verts.begin(); + vector<BSP_VertexInd>::const_iterator f_verts_end = face.m_verts.end(); + + for (;f_verts_it != f_verts_end; ++f_verts_it) { + + const BSP_MVertex & vert = VertexSet()[*f_verts_it]; + + MT_Scalar dist = plane.signedDistance( + vert.m_pos + ); + + if (fabs(dist) <= BSP_SPLIT_EPSILON ){ + MT_assert(BSP_Classification(vert.OpenTag()) == e_classified_on); + } else + if (dist > BSP_SPLIT_EPSILON) { + MT_assert(BSP_Classification(vert.OpenTag()) == e_classified_out); + } else + if (dist < BSP_SPLIT_EPSILON) { + MT_assert(BSP_Classification(vert.OpenTag()) == e_classified_in); + } + } +} + + + bool +BSP_CSGMesh:: +SC_Face( + BSP_FaceInd f +){ + + + +#if 0 + { + // check area is greater than zero. + + vector<BSP_MVertex> & verts = VertexSet(); + + vector<BSP_VertexInd> f_verts; + FaceVertices(f,f_verts); + + MT_assert(f_verts.size() >= 3); + + BSP_VertexInd root = f_verts[0]; + + MT_Scalar area = 0; + + for (int i=2; i < f_verts.size(); i++) { + MT_Vector3 a = verts[root].m_pos; + MT_Vector3 b = verts[f_verts[i-1]].m_pos; + MT_Vector3 c = verts[f_verts[i]].m_pos; + + MT_Vector3 l1 = b-a; + MT_Vector3 l2 = c-b; + + area += (l1.cross(l2)).length()/2; + } + + MT_assert(!MT_fuzzyZero(area)); + } +#endif + // Check coplanarity +#if 0 + MT_Plane3 plane = FacePlane(f); + + const BSP_MFace & face = FaceSet()[f]; + vector<BSP_VertexInd>::const_iterator f_verts_it = face.m_verts.begin(); + vector<BSP_VertexInd>::const_iterator f_verts_end = face.m_verts.end(); + + for (;f_verts_it != f_verts_end; ++f_verts_it) { + MT_Scalar dist = plane.signedDistance( + VertexSet()[*f_verts_it].m_pos + ); + + MT_assert(fabs(dist) < BSP_SPLIT_EPSILON); + } +#endif + + + // Check connectivity + + vector<BSP_EdgeInd> f_edges; + FaceEdges(f,f_edges); + + MT_assert(f_edges.size() == FaceSet()[f].m_verts.size()); + + unsigned int i; + for (i = 0; i < f_edges.size(); ++i) { + + int matches = 0; + for (unsigned int j = 0; j < EdgeSet()[f_edges[i]].m_faces.size(); j++) { + + if (EdgeSet()[f_edges[i]].m_faces[j] == f) matches++; + } + + MT_assert(matches == 1); + + } + return true; +} + + MT_Plane3 +BSP_CSGMesh:: +FacePlane( + const BSP_FaceInd & fi +) const{ + + const BSP_MFace & f0 = FaceSet()[fi]; + + // Have to be a bit careful here coz the poly may have + // a lot of parallel edges. Should walk round the polygon + // and check length of cross product. + + const MT_Vector3 & p1 = VertexSet()[f0.m_verts[0]].m_pos; + const MT_Vector3 & p2 = VertexSet()[f0.m_verts[1]].m_pos; + + int face_size = f0.m_verts.size(); + MT_Vector3 n; + + for (int i = 2 ; i <face_size; i++) { + const MT_Vector3 & pi = VertexSet()[f0.m_verts[i]].m_pos; + + MT_Vector3 l1 = p2-p1; + MT_Vector3 l2 = pi-p2; + n = l1.cross(l2); + MT_Scalar length = n.length(); + + if (!MT_fuzzyZero(length)) { + n = n * (1/length); + break; + } + } + return MT_Plane3(n,p1); +} + + void +BSP_CSGMesh:: +ComputeFacePlanes( +){ + + int fsize = FaceSet().size(); + int i=0; + for (i = 0; i < fsize; i++) { + + FaceSet()[i].m_plane = FacePlane(i); + } +}; + + + int +BSP_CSGMesh:: +CountTriangles( +) const { + + // Each polygon of n sides can be partitioned into n-3 triangles. + // So we just go through and sum this function of polygon size. + + vector<BSP_MFace> & face_set = FaceSet(); + + vector<BSP_MFace>::const_iterator face_it = face_set.begin(); + vector<BSP_MFace>::const_iterator face_end = face_set.end(); + + int sum = 0; + + for (;face_it != face_end; face_it++) { + + // Should be careful about degenerate faces here. + sum += face_it->m_verts.size() - 2; + } + + return sum; +} + + + diff --git a/intern/bsp/intern/BSP_CSGMesh.h b/intern/bsp/intern/BSP_CSGMesh.h new file mode 100755 index 00000000000..1b56ca7a3e5 --- /dev/null +++ b/intern/bsp/intern/BSP_CSGMesh.h @@ -0,0 +1,345 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_BSP_CSGMesh_h + +#define NAN_INCLUDED_BSP_CSGMesh_h + +#include "BSP_MeshPrimitives.h" +#include "MEM_SmartPtr.h" +#include "MEM_RefCountPtr.h" +#include "MEM_NonCopyable.h" +#include "BSP_CSGUserData.h" +#include "../extern/CSG_BooleanOps.h" + + +class MT_Plane3; +class BSP_MeshFragment; + +class BSP_CSGMesh : + public MEM_NonCopyable, + public MEM_RefCountable +{ + +public : + + static + BSP_CSGMesh * + New( + ); + + bool + SetVertices( + MEM_SmartPtr<std::vector<BSP_MVertex> > verts + ); + + void + SetFaceVertexData( + MEM_SmartPtr<BSP_CSGUserData> fv_data + ); + + void + SetFaceData( + MEM_SmartPtr<BSP_CSGUserData> f_data + ); + + void + AddPolygon( + const int * verts, + int num_verts + ); + + void + AddPolygon( + const int * verts, + const int * fv_indices, + int num_verts + ); + + void + AddSubTriangle( + const BSP_MFace &iface, + const int * index_info + ); + + // assumes that the face already has a plane equation + void + AddPolygon( + const BSP_MFace &face + ); + + + // Allocate and build the mesh edges. + //////////////////////////////////// + + bool + BuildEdges( + ); + + // Clean the mesh of edges. and edge pointers + // This removes the circular connectivity information + ///////////////////////////////////////////// + + void + DestroyEdges( + ); + + // return a new seperate copy of the + // mesh allocated on the heap. + + BSP_CSGMesh * + NewCopy( + ) const; + + + // Reverse the winding order of every polygon + // in the mesh and swap the planes around. + + void + Invert( + ); + + + // geometry access + ////////////////// + + std::vector<BSP_MVertex> & + VertexSet( + ) const ; + + std::vector<BSP_MFace> & + FaceSet( + ) const ; + + std::vector<BSP_MEdge> & + EdgeSet( + ) const; + + BSP_CSGUserData & + FaceVertexData( + ) const; + + BSP_CSGUserData & + FaceData( + ) const; + + ~BSP_CSGMesh( + ); + + // local geometry queries. + ///////////////////////// + + // face queries + /////////////// + + void + FaceVertices( + const BSP_FaceInd & f, + std::vector<BSP_VertexInd> &output + ); + + void + FaceEdges( + const BSP_FaceInd & f, + std::vector<BSP_EdgeInd> &output + ); + + // edge queries + /////////////// + + void + EdgeVertices( + const BSP_EdgeInd & e, + std::vector<BSP_VertexInd> &output + ); + + void + EdgeFaces( + const BSP_EdgeInd & e, + std::vector<BSP_FaceInd> &output + ); + + // vertex queries + ///////////////// + + void + VertexEdges( + const BSP_VertexInd & v, + std::vector<BSP_EdgeInd> &output + ); + + void + VertexFaces( + const BSP_VertexInd & v, + std::vector<BSP_FaceInd> &output + ); + + // Returns the edge index of the edge from v1 to v2. + // Does this by searching the edge sets of v1 - but not v2. + // If you are paranoid you should check both and make sure the + // indices are the same. If the edge doe not exist edgeInd is empty. + + BSP_EdgeInd + FindEdge( + const BSP_VertexInd &v1, + const BSP_VertexInd &v2 + ) const; + + + // Bounding box methods + /////////////////////// + + void + SetBBox( + const MT_Vector3 & min, + const MT_Vector3 & max + ); + + void + BBox( + MT_Vector3 &min, + MT_Vector3 &max + ) const ; + + // Update the BBox + ////////////////// + + void + UpdateBBox( + ); + + + /** + * Sanity checkers + */ + + // make sure the edge faces have a pointer to f + + bool + SC_Face( + BSP_FaceInd f + ); + + /** + * Make sure the polygons vertex classification is correct + */ + + void + SC_Classification( + BSP_FaceInd f, + const MT_Plane3&plane + ); + + /** + * Return the face plane equation + */ + + MT_Plane3 + FacePlane( + const BSP_FaceInd &fi + )const; + + + /** + * Recompute Face plane equations. + * essential if you have been messing with the object. + */ + + void + ComputeFacePlanes( + ); + + /** + * Count the number of trinagles in the mesh. + * This is not the same as the number of polygons. + */ + + int + CountTriangles( + ) const; + + /** + * Insert a vertex index into a polygon + * and call the external splitting function to + * generate a new face vertex property. + */ + + void + InsertVertexIntoFace( + BSP_MFace & face, + const BSP_VertexInd & v1, + const BSP_VertexInd & v2, + const BSP_VertexInd & vi, + CSG_InterpolateUserFaceVertexDataFunc fv_split_func, + MT_Scalar epsilon + ); + + +private : + + void + InsertEdge( + const BSP_VertexInd &v1, + const BSP_VertexInd &v2, + const BSP_FaceInd &f, + std::vector<BSP_EdgeInd> &new_edges + ); + + + // Private to insure heap instantiation. + + BSP_CSGMesh( + ); + + + MEM_SmartPtr< std::vector<BSP_MVertex> > m_verts; + MEM_SmartPtr< std::vector<BSP_MFace> > m_faces; + MEM_SmartPtr< std::vector<BSP_MEdge> > m_edges; + + // The face_vertex user data associated with this mesh + + MEM_SmartPtr<BSP_CSGUserData> m_fv_data; + + // The face user data associated with this mesh - + // This is a buffer that maps directly to the face buffer. + // An index into the faces is alos an index into m_face_data + // for that face + + MEM_SmartPtr<BSP_CSGUserData> m_face_data; + + + MT_Vector3 m_bbox_min; + MT_Vector3 m_bbox_max; + +}; + + +#endif
\ No newline at end of file diff --git a/intern/bsp/intern/BSP_CSGMeshBuilder.cpp b/intern/bsp/intern/BSP_CSGMeshBuilder.cpp new file mode 100755 index 00000000000..cbe4bfc920d --- /dev/null +++ b/intern/bsp/intern/BSP_CSGMeshBuilder.cpp @@ -0,0 +1,152 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BSP_CSGMeshBuilder.h" + + +using namespace std; + + MEM_SmartPtr<BSP_CSGMesh> +BSP_CSGMeshBuilder:: +NewMesh( + CSG_MeshPropertyDescriptor &props, + CSG_FaceIteratorDescriptor &face_it, + CSG_VertexIteratorDescriptor &vertex_it +) { + + MEM_SmartPtr<BSP_CSGMesh> mesh = BSP_CSGMesh::New(); + if (mesh == NULL) return NULL; + + MEM_SmartPtr<BSP_CSGUserData> fv_data = new BSP_CSGUserData(props.user_face_vertex_data_size); + MEM_SmartPtr<BSP_CSGUserData> face_data = new BSP_CSGUserData(props.user_data_size); + + + MEM_SmartPtr<vector<BSP_MVertex> > vertices(new vector<BSP_MVertex>); + if (vertices == NULL || fv_data == NULL || face_data == NULL) return NULL; + + // The size of the vertex data array will be at least the number of faces. + + fv_data->Reserve(face_it.num_elements); + face_data->Reserve(face_it.num_elements); + + vertices->reserve(vertex_it.num_elements); + + CSG_IVertex vertex; + + while (!vertex_it.Done(vertex_it.it)) { + vertex_it.Fill(vertex_it.it,&vertex); + + MT_Point3 pos(vertex.position); + vertices->push_back(BSP_MVertex(pos)); + + vertex_it.Step(vertex_it.it); + } + + // pass ownership of the vertices to the mesh. + mesh->SetVertices(vertices); + + // now for the polygons. + + CSG_IFace face; + // we may need to decalare some memory for user defined face properties. + + if (props.user_data_size) { + face.user_face_data = new char[props.user_data_size]; + } else { + face.user_face_data = NULL; + } + + if (props.user_face_vertex_data_size) { + char * fv_data = NULL; + fv_data = new char[4 * props.user_face_vertex_data_size]; + + face.user_face_vertex_data[0] = fv_data; + face.user_face_vertex_data[1] = fv_data + props.user_face_vertex_data_size; + face.user_face_vertex_data[2] = fv_data + 2*props.user_face_vertex_data_size; + face.user_face_vertex_data[3] = fv_data + 3*props.user_face_vertex_data_size; + } else { + face.user_face_vertex_data[0] = NULL; + face.user_face_vertex_data[1] = NULL; + face.user_face_vertex_data[2] = NULL; + face.user_face_vertex_data[3] = NULL; + } + + + int tri_index[3]; + int fv_index[3]; + + while (!face_it.Done(face_it.it)) { + face_it.Fill(face_it.it,&face); + + // Let's not rely on quads being coplanar - especially if they + // are coming out of that soup of code from blender... + if (face.vertex_number == 4) { + tri_index[0] = face.vertex_index[2]; + tri_index[1] = face.vertex_index[3]; + tri_index[2] = face.vertex_index[0]; + + fv_index[0] = fv_data->Duplicate(face.user_face_vertex_data[2]); + fv_index[1] = fv_data->Duplicate(face.user_face_vertex_data[3]); + fv_index[2] = fv_data->Duplicate(face.user_face_vertex_data[0]); + + mesh->AddPolygon(tri_index,fv_index,3); + + // bit of an unspoken relationship between mesh face buffer + // and the face data which I guess should be changed. + face_data->Duplicate(face.user_face_data); + + } + + fv_index[0] = fv_data->Duplicate(face.user_face_vertex_data[0]); + fv_index[1] = fv_data->Duplicate(face.user_face_vertex_data[1]); + fv_index[2] = fv_data->Duplicate(face.user_face_vertex_data[2]); + + mesh->AddPolygon(face.vertex_index,fv_index,3); + // bit of an unspoken relationship between mesh face buffer + // and the face data which I guess should be changed. + face_data->Duplicate(face.user_face_data); + + + face_it.Step(face_it.it); + } + + // give the user face vertex data over to the mesh. + + mesh->SetFaceVertexData(fv_data); + mesh->SetFaceData(face_data); + + // that's it + + delete[] static_cast<char *>(face.user_face_data); + delete[] static_cast<char *>(face.user_face_vertex_data[0]); + return mesh; +} + diff --git a/intern/bsp/intern/BSP_CSGMeshBuilder.h b/intern/bsp/intern/BSP_CSGMeshBuilder.h new file mode 100755 index 00000000000..b79b65ba55b --- /dev/null +++ b/intern/bsp/intern/BSP_CSGMeshBuilder.h @@ -0,0 +1,74 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BSP_CSGMeshBuilder_h + +#define BSP_CSGMeshBuilder_h + +#include "../extern/CSG_BooleanOps.h" +#include "BSP_CSGMesh.h" +#include "MEM_NonCopyable.h" +#include "MEM_SmartPtr.h" + +/** + * This class helps you to build a mesh from 2 seperate vertex/face + * iterators defined in the external interface of the bsp module. + * This code should really become party of a generic C++ mesh interface + * but later... + */ + +class BSP_CSGMeshBuilder : public MEM_NonCopyable{ + +public : + + /** + * Return a new BSP_CSGMesh with the desired props + * built from the given face and vertex iterators. + * The iterators are exhausted by this action. + */ + + static + MEM_SmartPtr<BSP_CSGMesh> + NewMesh( + CSG_MeshPropertyDescriptor &props, + CSG_FaceIteratorDescriptor &face_it, + CSG_VertexIteratorDescriptor &vertex_it + ); + +private : + + BSP_CSGMeshBuilder( + ); + +}; + + +#endif diff --git a/intern/bsp/intern/BSP_CSGMeshSplitter.cpp b/intern/bsp/intern/BSP_CSGMeshSplitter.cpp new file mode 100755 index 00000000000..eac926085ef --- /dev/null +++ b/intern/bsp/intern/BSP_CSGMeshSplitter.cpp @@ -0,0 +1,715 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BSP_CSGMeshSplitter.h" + +#include "BSP_CSGMesh.h" +#include "BSP_MeshFragment.h" +#include "BSP_CSGException.h" +#include "MT_MinMax.h" +#include "MT_assert.h" + +using namespace std; + + +BSP_CSGMeshSplitter:: +BSP_CSGMeshSplitter( + CSG_InterpolateUserFaceVertexDataFunc fv_split_func +) : m_fv_func(fv_split_func) +{ + // nothing to do +}; + + void +BSP_CSGMeshSplitter:: +Split( + const MT_Plane3& plane, + BSP_MeshFragment *frag, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + BSP_MeshFragment *spanning_frag +){ + // First classify the vertices and the polygons of the + // incoming fragment. + frag->Classify(plane,in_frag,out_frag,on_frag,m_spanning_faces,m_tagged_verts); + + SplitImp(*(frag->Mesh()),plane,m_spanning_faces,in_frag,out_frag,on_frag,m_tagged_verts); + + m_spanning_faces.clear(); + m_tagged_verts.clear(); + +} + + void +BSP_CSGMeshSplitter:: +Split( + BSP_CSGMesh & mesh, + const MT_Plane3& plane, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + BSP_MeshFragment *spanning_frag +){ + BSP_MeshFragment::Classify(mesh, plane,in_frag,out_frag,on_frag,m_spanning_faces,m_tagged_verts); + + SplitImp(mesh,plane,m_spanning_faces,in_frag,out_frag,on_frag,m_tagged_verts); + m_spanning_faces.clear(); + m_tagged_verts.clear(); +} + +BSP_CSGMeshSplitter:: +~BSP_CSGMeshSplitter( +){ + // nothing to do +} + + void +BSP_CSGMeshSplitter:: +SplitImp( + BSP_CSGMesh & mesh, + const MT_Plane3& plane, + const std::vector<BSP_FaceInd> & spanning_faces, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + std::vector<BSP_VertexInd> & classified_verts +){ + // Assumes you have already classified the vertices. + // and generated a set of spanning faces. + + vector<BSP_MEdge> & edge_set = mesh.EdgeSet(); + vector<BSP_MVertex> & vertex_set = mesh.VertexSet(); + vector<BSP_MFace> & face_set = mesh.FaceSet(); + + // Now identify the spanning edges. + // These can be computed in many ways but probably the most + // efficient is to select all edges from the vertices of the + // spanning polygons that cross the plane. + + vector<BSP_FaceInd>::const_iterator sface_end = m_spanning_faces.end(); + vector<BSP_FaceInd>::const_iterator sface_it = m_spanning_faces.begin(); + + for (;sface_it != sface_end; ++sface_it) { + + BSP_MFace & sface = face_set[*sface_it]; + + vector<BSP_VertexInd>::const_iterator sf_vert_end = sface.m_verts.end(); + vector<BSP_VertexInd>::iterator sf_vert_it = sface.m_verts.begin(); + + for (;sf_vert_it != sf_vert_end; ++sf_vert_it) { + BSP_MVertex & vert = vertex_set[*sf_vert_it]; + + if (!vert.SelectTag()) { + // what classification does this vertex have? + + BSP_Classification root_vert_class = BSP_Classification(vert.OpenTag()); + + // we are only interested in edges whose vertices are in and out. + if (root_vert_class != e_classified_on) { + + BSP_Classification opp_class = e_classified_out; + if (root_vert_class == e_classified_out) { + opp_class = e_classified_in; + } + // we haven't visited this vertex before so lets + // analyse it's edges. + + vector<BSP_EdgeInd>::const_iterator v_edge_end = vert.m_edges.end(); + vector<BSP_EdgeInd>::iterator v_edge_it = vert.m_edges.begin(); + + for (; v_edge_it != v_edge_end; ++v_edge_it) { + BSP_MEdge & edge = edge_set[*v_edge_it]; + + if (!edge.SelectTag()) { + // we haven't visited this edge before so check it's + // end points + + // we know that a spanning polygon can have at most + // 2 on vertices (even at this point where we haven't + // yet split the edge!) We are interested in edges whose + // vertices are in and out the plane. + + BSP_VertexInd opp_vi = edge.OpVertex(*sf_vert_it); + if (vertex_set[opp_vi].OpenTag() == opp_class) { + // we have found an edge !!!! + m_spanning_edges.push_back(*v_edge_it); + } + edge.SetSelectTag(true); + m_visited_edges.push_back(*v_edge_it); + } + } + } + + vert.SetSelectTag(true); + m_visited_verts.push_back(*sf_vert_it); + } + } + } + + // clear the tags we used in the above + + unsigned int i; + + for (i = 0; i < m_visited_edges.size(); ++i) { + edge_set[m_visited_edges[i]].SetSelectTag(false); + } + for (i=0;i < m_visited_verts.size(); ++i) { + vertex_set[m_visited_verts[i]].SetSelectTag(false); + } + for (i=0; i < m_spanning_faces.size(); ++i) { + face_set[m_spanning_faces[i]].SetSelectTag(false); + } + + // The spanning edge set constains unique edges. Next we run + // through the edge set and compute the intersection with the + // plane --- the edge is guarenteed not to be parallel to the plane! + // we then split the edge with the new vertex. + + // We identify the polygons affected by the split + + vector<BSP_EdgeInd>::const_iterator s_edge_end = m_spanning_edges.end(); + vector<BSP_EdgeInd>::iterator s_edge_it = m_spanning_edges.begin(); + + for (;s_edge_it != s_edge_end; ++s_edge_it) { + + const BSP_MEdge & edge = edge_set[*s_edge_it]; + + const BSP_MVertex &v1 = vertex_set[edge.m_verts[0]]; + const BSP_MVertex &v2 = vertex_set[edge.m_verts[1]]; + + const MT_Vector3 & ptA = v1.m_pos; + const MT_Vector3 & ptB = v2.m_pos; + + // compute the intersection point of plane and ptA->ptB + MT_Vector3 v = ptB - ptA; + MT_Scalar sideA = plane.signedDistance(ptA); + + MT_Scalar epsilon = -sideA/plane.Normal().dot(v); + MT_Vector3 new_p = ptA + (v * epsilon); + + // so new_p is the intersection of the plane and the edge. + // split the edge at new_p + + BSP_MVertex new_vert; + new_vert.m_pos = new_p; + + BSP_VertexInd new_vi = SplitEdge(mesh,*s_edge_it,new_vert,epsilon); + + // tag the new vertex as 'on' the plane - we use this information + // to split the affected polygons below. + vertex_set[new_vi].SetOpenTag(e_classified_on); + + // We add it to the tagged verts so we can remove the tag later. + classified_verts.push_back(new_vi); + } + + // We start with the spanning polygons... + // not forgetting to add the new polygon fragments to the correct fragment bins. + + sface_end = m_spanning_faces.end(); + sface_it = m_spanning_faces.begin(); + + for (;sface_it != sface_end; ++sface_it) { + + BSP_FaceInd f_in,f_out; + + SplitPolygon(mesh,*sface_it,f_in,f_out); + in_frag->FaceSet().push_back(f_in); + out_frag->FaceSet().push_back(f_out); + } + + // Finally we have to clean up the vertex tags we set on all the vertices + // There will be some overlap between the vertex sets, so this operation + // is a tiny bit inefficient. + + vector<BSP_VertexInd>::const_iterator v_end = classified_verts.end(); + vector<BSP_VertexInd>::const_iterator v_it = classified_verts.begin(); + + for (; v_it != v_end; ++v_it) { + vertex_set[*v_it].SetOpenTag(e_unclassified); + } + + // tidy up the cached arrays. + + m_spanning_edges.clear(); + m_visited_edges.clear(); + m_visited_verts.clear(); + + + // le fin. + +} + + + BSP_VertexInd +BSP_CSGMeshSplitter:: +SplitEdge( + BSP_CSGMesh & mesh, + BSP_EdgeInd ei, + BSP_MVertex &vertex, + MT_Scalar epsilon +){ + vector<BSP_MEdge> & edge_set = mesh.EdgeSet(); + vector<BSP_MVertex> & vertex_set = mesh.VertexSet(); + vector<BSP_MFace> & face_set = mesh.FaceSet(); + + MT_assert(edge_set.size() > (unsigned int)(ei)); + + if (edge_set.size() <= (unsigned int)(ei)) { + BSP_CSGException e(e_param_error); + throw(e); + } + + // push the vertex onto the vertex array + BSP_VertexInd new_vi = vertex_set.size(); + vertex_set.push_back(vertex); + BSP_MVertex & new_v = vertex_set[new_vi]; + + // copy the edge because the new edge will have + // exactly the same face set. + + BSP_EdgeInd new_ei = edge_set.size(); + + // Note never use set.push_back(set[i]) + // coz push_back excepts a reference which may become + // invalid if the set is resized + + edge_set.push_back(BSP_MEdge()); + edge_set[new_ei] = edge_set[ei]; + BSP_MEdge & new_e = edge_set[new_ei]; + + BSP_MEdge &e = edge_set[ei]; + + // get the edge vertices. + BSP_MVertex & e_v2 = vertex_set[e.m_verts[1]]; + + // Remove the split edge from vertex 2. + // Let's hope that the vertex isn't using this edge for + // its' open tag!! + + BSP_Classification v2_class = BSP_Classification(e_v2.OpenTag()); + + e_v2.RemoveEdge(ei); + + // add the split edge to the new vertex. + new_v.AddEdge(ei); + + // add the new edge to the new vertex. + new_v.AddEdge(new_ei); + + // add the new edge to vertex 2 + e_v2.AddEdge(new_ei); + + // Reset the tags for modified vertex. + + e_v2.SetOpenTag(v2_class); + + + // Replace the old vertex indices in the new edge. + new_e.m_verts[0] = new_vi; + e.m_verts[1] = new_vi; + + // Finally add the vertex in the correct position to the + // neighbouring polygons. + + vector<BSP_FaceInd>::iterator neighbour_face_it = e.m_faces.begin(); + vector<BSP_FaceInd>::const_iterator neighbour_face_end = e.m_faces.end(); + + for (; neighbour_face_it != neighbour_face_end; ++neighbour_face_it) { + + mesh.InsertVertexIntoFace( + face_set[*neighbour_face_it], + new_e.m_verts[1], + e.m_verts[0], + new_vi, + m_fv_func, + epsilon + ); + } + + // That should be it (cough) + return new_vi; + +} + + void +BSP_CSGMeshSplitter:: +SplitPolygon( + BSP_CSGMesh & mesh, + BSP_FaceInd fi, + BSP_FaceInd &fin, + BSP_FaceInd &fout +){ + vector<BSP_MEdge> & edge_set = mesh.EdgeSet(); + vector<BSP_MVertex> & vertex_set = mesh.VertexSet(); + vector<BSP_MFace> & face_set = mesh.FaceSet(); + + MT_assert(face_set.size() > (unsigned int)(fi)); + if (face_set.size() <= (unsigned int)(fi)) { + BSP_CSGException e(e_param_error); + throw(e); + } + + BSP_MFace & face = face_set[fi]; + + // Walk throught the vertices of this polygon. + // generate inside and outside loops. + + vector<BSP_VertexInd>::const_iterator f_verts_end = face.m_verts.end(); + vector<BSP_VertexInd>::iterator f_verts_it = face.m_verts.begin(); + + vector<BSP_UserFVInd>::const_iterator f_fv_data_it = face.m_fv_data.begin(); + + // NOTE we don't actually duplicate fv data for this face + // we just duplicate the indices, so both on vertices + // will share the fv data. + + for (;f_verts_it != f_verts_end; ++f_verts_it, ++f_fv_data_it) { + + BSP_MVertex & vert = vertex_set[*f_verts_it]; + BSP_Classification v_class = BSP_Classification(vert.OpenTag()); + + if (v_class == e_classified_in) { + m_in_loop.push_back(*f_verts_it); + m_fv_in_loop.push_back(*f_fv_data_it); + } else + if (v_class == e_classified_out) { + m_out_loop.push_back(*f_verts_it); + m_fv_out_loop.push_back(*f_fv_data_it); + + } else + if (v_class == e_classified_on) { + m_in_loop.push_back(*f_verts_it); + m_out_loop.push_back(*f_verts_it); + m_on_loop.push_back(*f_verts_it); + m_fv_in_loop.push_back(*f_fv_data_it); + m_fv_out_loop.push_back(*f_fv_data_it); + } else { + // The vertex is unclassified this is an error! + MT_assert(false); + BSP_CSGException e(e_split_error); + throw(e); + } + } + + if ((m_in_loop.size() == 1) || (m_out_loop.size() == 1)) { + // Then there was only 1 tagged vertex I guess this is fine + // but should be reviewed! + + // NOT fine - we only ever split spanning polygons. + MT_assert(false); + BSP_CSGException e(e_split_error); + throw(e); + } + + MT_assert(m_in_loop.size() >=3 && m_out_loop.size() >=3 && m_on_loop.size() == 2); + + if (m_in_loop.size() <3 || m_out_loop.size() <3 || m_on_loop.size() !=2) { + BSP_CSGException e(e_split_error); + throw(e); + } + // Now we have 2 seperate vertex loops representing the polygon + // halves. + + // create a new polygon for the out_loop of vertices. + //////////////////////////////////////////////////// + + // Duplicate face data. + + mesh.FaceData().Duplicate(fi); + + BSP_FaceInd new_fi = face_set.size(); + face_set.push_back(BSP_MFace()); + BSP_MFace & new_f = face_set[new_fi]; + + // assign plane equation for new face - this is the same as the + // original of course. + + new_f.m_plane = face_set[fi].m_plane; + + // note that face may have become invalid because we just been adding + // more polygons to the array. We can't assign a new reference to the old + // invlaid one! It will call try and call the assignment operator on + // the original face!!!! The joys of references! We just use face_set[fi] + // from now on to be safe + + // We need to insert an edge between m_on_loop[0] and m_on_loop[1] + + // Make sure the edge does not already exist between these 2 vertices! + // This can happen if the original mesh has duplicate polygons. + // We still wire up the new polygons to this edge, which will + // lead to duplicate polygons in the output -- but algorithm + // should still work. + BSP_EdgeInd new_ei = mesh.FindEdge(m_on_loop[0],m_on_loop[1]); + + if (new_ei.IsEmpty()) { + + // create a new edge. + + new_ei = edge_set.size(); + edge_set.push_back(BSP_MEdge()); + BSP_MEdge & new_e = edge_set[new_ei]; + + new_e.m_verts[0] = m_on_loop[0]; + new_e.m_verts[1] = m_on_loop[1]; + + // Now tie the edge to it's vertices. + + vertex_set[m_on_loop[0]].AddEdge(new_ei); + vertex_set[m_on_loop[1]].AddEdge(new_ei); + } + + edge_set[new_ei].m_faces.push_back(fi); + // This next line is a trick we are going to replace it in a moment + // with new_fi. It means that all the edges of the new polygon have + // pointers to the old polygon which we can replace. + edge_set[new_ei].m_faces.push_back(fi); + + + // Replace the old polygons vertex loop with the in_loop of vertices. + + face_set[fi].m_verts = m_in_loop; + new_f.m_verts = m_out_loop; + + // Replace the olf fv loops. + face_set[fi].m_fv_data = m_fv_in_loop; + new_f.m_fv_data = m_fv_out_loop; + + + // That should be it for the old polygon; + // For the new polygon we just need to iterate around it's + // edges and replace pointers to the old polygon with pointers + // to the new one. + + f_verts_end = new_f.m_verts.end(); + f_verts_it = new_f.m_verts.begin(); + + BSP_VertexInd prev = new_f.m_verts.back(); + + for (;f_verts_it != f_verts_end; ++f_verts_it) { + BSP_EdgeInd new_f_ei = mesh.FindEdge(prev,*f_verts_it); + + MT_assert(!new_f_ei.IsEmpty()); + + if (new_f_ei.IsEmpty()) { + BSP_CSGException e(e_split_error); + throw(e); + } + + edge_set[new_f_ei].SwapFace(fi,new_fi); + prev = *f_verts_it; + + } + + // That should be everything. + + fin = fi; + fout = new_fi; + + // clear up cached helpers. + m_in_loop.clear(); + m_on_loop.clear(); + m_out_loop.clear(); + + m_fv_in_loop.clear(); + m_fv_out_loop.clear(); + +} + + BSP_FaceInd +BSP_CSGMeshSplitter:: +TriangulateConvexQuad( + BSP_CSGMesh & mesh, + const BSP_FaceInd fi +){ + + // we assume that the fi points to a face with + // exactly 4 vertices. + + + // We are definately going to create a new face + // so lets make space for it in the face array. + + vector<BSP_MFace> & face_set = mesh.FaceSet(); + vector<BSP_MVertex> & vertex_set = mesh.VertexSet(); + vector<BSP_MEdge> & edge_set = mesh.EdgeSet(); + + if (face_set[fi].m_verts.size() == 3) { + return BSP_FaceInd::Empty(); + } + + // duplicate face data + mesh.FaceData().Duplicate(fi); + + const BSP_FaceInd new_fi = face_set.size(); + face_set.push_back(BSP_MFace()); + BSP_MFace & new_face = face_set[new_fi]; + BSP_MFace & face = face_set[fi]; + + new_face.m_plane = face.m_plane; + + // The internal edges are [0,2] and [1,3] + // these split the quad into the triangles + // [0,1,2],[2,3,0] and [0,1,3],[1,2,3] respectively + + const MT_Point3 & p0 = vertex_set[face.m_verts[0]].m_pos; + const MT_Point3 & p1 = vertex_set[face.m_verts[1]].m_pos; + const MT_Point3 & p2 = vertex_set[face.m_verts[2]].m_pos; + const MT_Point3 & p3 = vertex_set[face.m_verts[3]].m_pos; + + MT_Vector3 e0 = p1 - p0; + MT_Vector3 e1 = p2 - p1; + MT_Vector3 e2 = p3 - p2; + MT_Vector3 e3 = p0 - p3; + + MT_Scalar A = (e0.cross(e1)).length2(); + MT_Scalar B = (e2.cross(e3)).length2(); + MT_Scalar C = (e3.cross(e0)).length2(); + MT_Scalar D = (e1.cross(e2)).length2(); + + MT_Scalar minab = MT_min(A,B); + MT_Scalar maxab = MT_max(A,B); + + MT_Scalar mincd = MT_min(C,D); + MT_Scalar maxcd = MT_max(C,D); + + MT_Scalar ratioab = minab/maxab; + MT_Scalar ratiocd = mincd/maxcd; + + ratioab = MT_abs(1-ratioab); + ratiocd = MT_abs(1-ratiocd); + + vector<BSP_VertexInd> loop1(3),loop2(3); + vector<BSP_UserFVInd> fv_loop1(3),fv_loop2(3); + + if (ratioab < ratiocd) { + // then use [0,2] as splitting edge. + loop1[0] = face.m_verts[1]; + loop1[1] = face.m_verts[2]; + loop1[2] = face.m_verts[0]; + + loop2[0] = face.m_verts[2]; + loop2[1] = face.m_verts[3]; + loop2[2] = face.m_verts[0]; + + // same for fv indices. + fv_loop1[0] = face.m_fv_data[1]; + fv_loop1[1] = face.m_fv_data[2]; + fv_loop1[2] = face.m_fv_data[0]; + + fv_loop2[0] = face.m_fv_data[2]; + fv_loop2[1] = face.m_fv_data[3]; + fv_loop2[2] = face.m_fv_data[0]; + + + } else { + // use [1,3] as splitting edge + loop1[0] = face.m_verts[0]; + loop1[1] = face.m_verts[1]; + loop1[2] = face.m_verts[3]; + + loop2[0] = face.m_verts[1]; + loop2[1] = face.m_verts[2]; + loop2[2] = face.m_verts[3]; + + // same for fv indices. + fv_loop1[0] = face.m_fv_data[0]; + fv_loop1[1] = face.m_fv_data[1]; + fv_loop1[2] = face.m_fv_data[3]; + + fv_loop2[0] = face.m_fv_data[1]; + fv_loop2[1] = face.m_fv_data[2]; + fv_loop2[2] = face.m_fv_data[3]; + + } + + // TODO factor out commmon code between here and SplitPolygon. + + BSP_EdgeInd new_ei = mesh.FindEdge(loop1[1],loop1[2]); + + if (new_ei.IsEmpty()) { + + // create a new edge. + + new_ei = edge_set.size(); + edge_set.push_back(BSP_MEdge()); + BSP_MEdge & new_e = edge_set[new_ei]; + + new_e.m_verts[0] = loop1[1]; + new_e.m_verts[1] = loop1[2]; + + // Now tie the edge to it's vertices. + + vertex_set[loop1[1]].AddEdge(new_ei); + vertex_set[loop1[2]].AddEdge(new_ei); + } + + edge_set[new_ei].m_faces.push_back(fi); + // This next line is a trick we are going to replace it in a moment + // with new_fi. It means that all the edges of the new polygon have + // pointers to the old polygon which we can replace. + edge_set[new_ei].m_faces.push_back(fi); + + + // Replace the old polygons vertex loop with the in_loop of vertices. + + face.m_verts = loop1; + face.m_fv_data = fv_loop1; + new_face.m_verts = loop2; + new_face.m_fv_data = fv_loop2; + + // That should be it for the old polygon; + // For the new polygon we just need to iterate around it's + // edges and replace pointers to the old polygon with pointers + // to the new one. + + vector<BSP_VertexInd>::const_iterator f_verts_end = new_face.m_verts.end(); + vector<BSP_VertexInd>::const_iterator f_verts_it = new_face.m_verts.begin(); + + BSP_VertexInd prev = new_face.m_verts.back(); + + for (;f_verts_it != f_verts_end; ++f_verts_it) { + BSP_EdgeInd new_f_ei = mesh.FindEdge(prev,*f_verts_it); + + MT_assert(!new_f_ei.IsEmpty()); + + if (new_f_ei.IsEmpty()) { + BSP_CSGException e(e_split_error); + throw(e); + } + + edge_set[new_f_ei].SwapFace(fi,new_fi); + prev = *f_verts_it; + + } + return new_fi; +} diff --git a/intern/bsp/intern/BSP_CSGMeshSplitter.h b/intern/bsp/intern/BSP_CSGMeshSplitter.h new file mode 100755 index 00000000000..8216082d007 --- /dev/null +++ b/intern/bsp/intern/BSP_CSGMeshSplitter.h @@ -0,0 +1,208 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BSP_CSGMeshSplitter_h + +#define BSP_CSGMeshSplitter_h + +class BSP_MeshFragment; +class MT_Plane3; +class BSP_CSGMesh; + +#include "BSP_MeshPrimitives.h" +#include "../extern/CSG_BooleanOps.h" +#include "BSP_CSGISplitter.h" + + +/** + * This class contains splitting functions for a CSGMesh. + * The atomic operation of a bsp CSG algorithm is to split + * a mesh fragment (connected collection of polygons contained + * in a convex cell) by a plane. It is vital to leave the + * CSGMesh in a valid state after each such operation + * this class insures this (or tries it's best!). + */ + + +class BSP_CSGMeshSplitter : public BSP_CSGISplitter +{ +public : + + /// construction + + BSP_CSGMeshSplitter( + CSG_InterpolateUserFaceVertexDataFunc fv_split_func + ); + + BSP_CSGMeshSplitter( + const BSP_CSGMeshSplitter & other + ); + + /** + * @section BSP specific mesh operations. + * Inherited from BSP_CSGISplitter + */ + + /** + * Split a mesh fragment wrt plane. Generates 3 mesh fragments, + * in, out and on. Makes sure the mesh is coherent after the + * operation. The contents of frag are consumed by this oepration. + */ + + void + Split( + const MT_Plane3& plane, + BSP_MeshFragment *frag, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + BSP_MeshFragment *spanning_frag + ); + + /// Split the entire mesh with respect to the plane. + + void + Split( + BSP_CSGMesh & mesh, + const MT_Plane3& plane, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + BSP_MeshFragment *spanning_frag + ); + + ~BSP_CSGMeshSplitter( + ); + +private : + + void + SplitImp( + BSP_CSGMesh & mesh, + const MT_Plane3& plane, + const std::vector<BSP_FaceInd> & spanning_faces, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + std::vector<BSP_VertexInd> & classified_verts + ); + + + /** + * @section Atomic mesh operations. + */ + + /** + * Add a vertex to the mesh, along + * a given edge. Leaves the mesh in a valid state. + * The vertex gets copied onto the back of the + * current vertex array. It's upto you to insure + * that the vertex actually lies on the edge and leaves + * the neighbouring faces convex. Returns the vertex index + * of the new vertex. + * + * epsilon is the relative distance [0,1] of the new + * vertex from the first vertex of the edge. This is + * used to intepolate face properties. + */ + + BSP_VertexInd + SplitEdge( + BSP_CSGMesh & mesh, + BSP_EdgeInd ei, + BSP_MVertex &vertex, + MT_Scalar epsilon + ); + + /** + * Split a polygon along an edge connecting the + * two tagged (on) vertices of the polygon. It assumes + * that you have already introduced two new vertex indices + * into the polygon that point to vertices tagged with + * {in,out,on} information. It creates a new edge from the + * 2 on vertices that must be present. It then splits up + * the polygon into 2 fragments on the inside and outside. + * It returns 2 indices into the face list. 1 for the inside + * polygon and 1 for the outside polygon. + */ + + void + SplitPolygon( + BSP_CSGMesh & mesh, + BSP_FaceInd fi, + BSP_FaceInd &fin, + BSP_FaceInd &fout + ); + + /** + * Triangulate a convex quad (the maximum size polygon + * resulting from splitting a triangle). This can create up + * to one new face - which is added to the mesh. Note + * that this method does not preserve references. It uses + * the edge which divides the quad into roughly equal triangular + * areas as the splitting edge. - This should avoid creating + * degenerate triangles. + */ + + BSP_FaceInd + TriangulateConvexQuad( + BSP_CSGMesh & mesh, + const BSP_FaceInd fi + ); + +private : + + // The function pointer used to split face vertex properties. + + CSG_InterpolateUserFaceVertexDataFunc m_fv_func; + + /// Cached helpers + + /// Split function responsibe for: + std::vector<BSP_FaceInd> m_spanning_faces; + std::vector<BSP_VertexInd> m_tagged_verts; + + /// SplitImp responsible for: + std::vector<BSP_EdgeInd> m_spanning_edges; + // The list of faces affected by splitting the spanning edge set. + std::vector<BSP_EdgeInd> m_visited_edges; + std::vector<BSP_VertexInd> m_visited_verts; + + /// SplitPolygon responsible for: + std::vector<BSP_FaceInd> m_in_loop,m_out_loop,m_on_loop; + std::vector<BSP_UserFVInd> m_fv_in_loop,m_fv_out_loop; + +}; + +#endif + + + diff --git a/intern/bsp/intern/BSP_CSGMesh_CFIterator.h b/intern/bsp/intern/BSP_CSGMesh_CFIterator.h new file mode 100755 index 00000000000..5d4e28e4647 --- /dev/null +++ b/intern/bsp/intern/BSP_CSGMesh_CFIterator.h @@ -0,0 +1,272 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BSP_CSGMesh_CFIterator_h + +#define BSP_CSGMesh_CFIterator_h + +#include "BSP_CSGMesh.h" +#include "../extern/CSG_BooleanOps.h" +/** + * This class defines 2 C style iterators over a CSG mesh, one for + * vertices and 1 for faces. They conform to the iterator interface + * defined in CSG_BooleanOps.h + */ + +struct BSP_CSGMesh_VertexIt { + MEM_RefCountPtr<BSP_CSGMesh> mesh; + BSP_MVertex * pos; +}; + + +static + void +BSP_CSGMesh_VertexIt_Destruct( + CSG_VertexIteratorDescriptor * iterator +) { + delete ((BSP_CSGMesh_VertexIt *)(iterator->it)); + iterator->it = NULL; + iterator->Done = NULL; + iterator->Fill = NULL; + iterator->Reset = NULL; + iterator->Step = NULL; + iterator->num_elements = 0; +}; + + +static + int +BSP_CSGMesh_VertexIt_Done( + CSG_IteratorPtr it +) { + // assume CSG_IteratorPtr is of the correct type. + BSP_CSGMesh_VertexIt * vertex_it = (BSP_CSGMesh_VertexIt *)it; + + if (vertex_it->pos < vertex_it->mesh->VertexSet().end()) return 0; + return 1; +}; + +static + void +BSP_CSGMesh_VertexIt_Fill( + CSG_IteratorPtr it, + CSG_IVertex *vert +) { + // assume CSG_IteratorPtr is of the correct type. + BSP_CSGMesh_VertexIt * vertex_it = (BSP_CSGMesh_VertexIt *)it; + + vertex_it->pos->m_pos.getValue(vert->position); +}; + +static + void +BSP_CSGMesh_VertexIt_Step( + CSG_IteratorPtr it +) { + // assume CSG_IteratorPtr is of the correct type. + BSP_CSGMesh_VertexIt * vertex_it = (BSP_CSGMesh_VertexIt *)it; + + ++(vertex_it->pos); +}; + +static + void +BSP_CSGMesh_VertexIt_Reset( + CSG_IteratorPtr it +) { + // assume CSG_IteratorPtr is of the correct type. + BSP_CSGMesh_VertexIt * vertex_it = (BSP_CSGMesh_VertexIt *)it; + vertex_it->pos = vertex_it->mesh->VertexSet().begin(); +}; + +static + void +BSP_CSGMeshVertexIt_Construct( + BSP_CSGMesh *mesh, + CSG_VertexIteratorDescriptor *output +){ + // user should have insured mesh is not equal to NULL. + + output->Done = BSP_CSGMesh_VertexIt_Done; + output->Fill = BSP_CSGMesh_VertexIt_Fill; + output->Step = BSP_CSGMesh_VertexIt_Step; + output->Reset = BSP_CSGMesh_VertexIt_Reset; + output->num_elements = mesh->VertexSet().size(); + + BSP_CSGMesh_VertexIt * v_it = new BSP_CSGMesh_VertexIt; + v_it->mesh = mesh; + v_it->pos = mesh->VertexSet().begin(); + output->it = v_it; +}; + + +/** + * Face iterator. + */ + +struct BSP_CSGMesh_FaceIt { + MEM_RefCountPtr<BSP_CSGMesh> mesh; + BSP_MFace *pos; + int face_triangle; +}; + + +static + void +BSP_CSGMesh_FaceIt_Destruct( + CSG_FaceIteratorDescriptor *iterator +) { + delete ((BSP_CSGMesh_FaceIt *)(iterator->it)); + iterator->it = NULL; + iterator->Done = NULL; + iterator->Fill = NULL; + iterator->Reset = NULL; + iterator->Step = NULL; + iterator->num_elements = 0; +}; + + +static + int +BSP_CSGMesh_FaceIt_Done( + CSG_IteratorPtr it +) { + // assume CSG_IteratorPtr is of the correct type. + BSP_CSGMesh_FaceIt * face_it = (BSP_CSGMesh_FaceIt *)it; + + if (face_it->pos < face_it->mesh->FaceSet().end()) { + if (face_it->face_triangle + 3 <= face_it->pos->m_verts.size()) { + return 0; + } + } + return 1; +}; + +static + void +BSP_CSGMesh_FaceIt_Fill( + CSG_IteratorPtr it, + CSG_IFace *face +){ + // assume CSG_IteratorPtr is of the correct type. + BSP_CSGMesh_FaceIt * face_it = (BSP_CSGMesh_FaceIt *)it; + // essentially iterating through a triangle fan here. + const int tri_index = face_it->face_triangle; + + face->vertex_index[0] = int(face_it->pos->m_verts[0]); + face->vertex_index[1] = int(face_it->pos->m_verts[tri_index + 1]); + face->vertex_index[2] = int(face_it->pos->m_verts[tri_index + 2]); + + // Copy the user face data across - this does nothing + // if there was no mesh user data. + + // time to change the iterator type to an integer... + face_it->mesh->FaceData().Copy( + face->user_face_data, + int(face_it->pos - face_it->mesh->FaceSet().begin()) + ); + + // Copy face vertex data across... + + face_it->mesh->FaceVertexData().Copy( + face->user_face_vertex_data[0], + face_it->pos->m_fv_data[0] + ); + + face_it->mesh->FaceVertexData().Copy( + face->user_face_vertex_data[1], + face_it->pos->m_fv_data[tri_index + 1] + ); + + face_it->mesh->FaceVertexData().Copy( + face->user_face_vertex_data[2], + face_it->pos->m_fv_data[tri_index + 2] + ); + + face->vertex_number = 3; +}; + +static + void +BSP_CSGMesh_FaceIt_Step( + CSG_IteratorPtr it +) { + // assume CSG_IteratorPtr is of the correct type. + BSP_CSGMesh_FaceIt * face_it = (BSP_CSGMesh_FaceIt *)it; + + // safety guard + if (face_it->pos < face_it->mesh->FaceSet().end()) { + + if (face_it->face_triangle + 3 < face_it->pos->m_verts.size()) { + (face_it->face_triangle)++; + } else { + face_it->face_triangle = 0; + (face_it->pos) ++; + } + } +}; + +static + void +BSP_CSGMesh_FaceIt_Reset( + CSG_IteratorPtr it +) { + // assume CSG_IteratorPtr is of the correct type. + BSP_CSGMesh_FaceIt * f_it = (BSP_CSGMesh_FaceIt *)it; + f_it->pos = f_it->mesh->FaceSet().begin(); + f_it->face_triangle = 0; +}; + +static + void +BSP_CSGMesh_FaceIt_Construct( + BSP_CSGMesh * mesh, + CSG_FaceIteratorDescriptor *output +) { + + output->Done = BSP_CSGMesh_FaceIt_Done; + output->Fill = BSP_CSGMesh_FaceIt_Fill; + output->Step = BSP_CSGMesh_FaceIt_Step; + output->Reset = BSP_CSGMesh_FaceIt_Reset; + + output->num_elements = mesh->CountTriangles(); + + BSP_CSGMesh_FaceIt * f_it = new BSP_CSGMesh_FaceIt; + f_it->mesh = mesh; + f_it->pos = mesh->FaceSet().begin(); + f_it->face_triangle = 0; + + output->it = f_it; + +}; + + +#endif
\ No newline at end of file diff --git a/intern/bsp/intern/BSP_CSGNCMeshSplitter.cpp b/intern/bsp/intern/BSP_CSGNCMeshSplitter.cpp new file mode 100755 index 00000000000..4ffe5c73e47 --- /dev/null +++ b/intern/bsp/intern/BSP_CSGNCMeshSplitter.cpp @@ -0,0 +1,241 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BSP_CSGNCMeshSplitter.h" + +#include "BSP_CSGMesh.h" +#include "BSP_MeshFragment.h" +#include "BSP_CSGException.h" +#include "MT_MinMax.h" +#include "MT_assert.h" +#include <vector> + +using namespace std; + +BSP_CSGNCMeshSplitter:: +BSP_CSGNCMeshSplitter( +){ + //nothing to do +} + +BSP_CSGNCMeshSplitter:: +BSP_CSGNCMeshSplitter( + const BSP_CSGNCMeshSplitter & other +){ + //nothing to do +}; + + + void +BSP_CSGNCMeshSplitter:: +Split( + const MT_Plane3& plane, + BSP_MeshFragment *frag, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + BSP_MeshFragment *spanning_frag +){ + // First classify the vertices and the polygons of the + // incoming fragment. + frag->Classify(plane,in_frag,out_frag,on_frag,m_spanning_faces,m_tagged_verts); + + SplitImp(*(frag->Mesh()),plane,m_spanning_faces,in_frag,out_frag,on_frag,m_tagged_verts); + + m_spanning_faces.clear(); + m_tagged_verts.clear(); +} + +/// Split the entire mesh with respect to the plane. + + void +BSP_CSGNCMeshSplitter:: +Split( + BSP_CSGMesh & mesh, + const MT_Plane3& plane, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + BSP_MeshFragment *spanning_frag +){ + BSP_MeshFragment::Classify(mesh, plane,in_frag,out_frag,on_frag,m_spanning_faces,m_tagged_verts); + + SplitImp(mesh,plane,m_spanning_faces,in_frag,out_frag,on_frag,m_tagged_verts); + m_spanning_faces.clear(); + m_tagged_verts.clear(); +} + + +BSP_CSGNCMeshSplitter:: +~BSP_CSGNCMeshSplitter( +){ + //nothing to do +} + + void +BSP_CSGNCMeshSplitter:: +SplitImp( + BSP_CSGMesh & mesh, + const MT_Plane3& plane, + const std::vector<BSP_FaceInd> & spanning_faces, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + std::vector<BSP_VertexInd> & classified_verts +){ + + // Just iterate through the spanning faces. + // Identify the spanning 'edges' and create new vertices + // and split the polygons. We make no attempt to share + // vertices or preserve edge connectivity or maintain any + // face properties etc. + + // Assumes you have already classified the vertices. + // and generated a set of spanning faces. + + vector<BSP_MVertex> & vertex_set = mesh.VertexSet(); + vector<BSP_MFace> & face_set = mesh.FaceSet(); + + vector<BSP_FaceInd>::const_iterator sface_end = m_spanning_faces.end(); + vector<BSP_FaceInd>::const_iterator sface_it = m_spanning_faces.begin(); + + for (;sface_it != sface_end; ++sface_it) { + BSP_FaceInd f_in,f_out; + SplitPolygon(plane,mesh,*sface_it,f_in,f_out); + + // Use the open tag to store the original index of the face. + // This is originally -1. + + if (face_set[*sface_it].OpenTag() == -1) { + face_set[f_in].SetOpenTag(*sface_it); + face_set[f_out].SetOpenTag(*sface_it); + } else { + face_set[f_in].SetOpenTag(face_set[*sface_it].OpenTag()); + face_set[f_out].SetOpenTag(face_set[*sface_it].OpenTag()); + } + + in_frag->FaceSet().push_back(f_in); + out_frag->FaceSet().push_back(f_out); + } + + vector<BSP_VertexInd>::const_iterator v_end = classified_verts.end(); + vector<BSP_VertexInd>::const_iterator v_it = classified_verts.begin(); + + for (; v_it != v_end; ++v_it) { + vertex_set[*v_it].SetOpenTag(e_unclassified); + } +} + + void +BSP_CSGNCMeshSplitter:: +SplitPolygon( + const MT_Plane3& plane, + BSP_CSGMesh & mesh, + BSP_FaceInd fi, + BSP_FaceInd &fin, + BSP_FaceInd &fout +){ + + vector<BSP_MVertex> & vertex_set = mesh.VertexSet(); + vector<BSP_MFace> & face_set = mesh.FaceSet(); + + BSP_FaceInd new_fi = face_set.size(); + face_set.push_back(BSP_MFace()); + + BSP_MFace & face = face_set[fi]; + BSP_MFace &new_face = face_set[new_fi]; + + vector<BSP_VertexInd>::const_iterator f_verts_it = face.m_verts.begin(); + vector<BSP_VertexInd>::const_iterator f_verts_end = face.m_verts.end(); + + MT_Point3 ptA = vertex_set[face.m_verts.back()].m_pos; + BSP_Classification prev_class = BSP_Classification(vertex_set[face.m_verts.back()].OpenTag()); + + for (; f_verts_it != f_verts_end;++f_verts_it) { + + BSP_Classification v_class = BSP_Classification(vertex_set[*f_verts_it].OpenTag()); + + if (v_class == e_classified_on) { + m_in_loop.push_back(*f_verts_it); + m_out_loop.push_back(*f_verts_it); + prev_class = e_classified_on; + continue; + } else + if (v_class == e_classified_in) { + m_in_loop.push_back(*f_verts_it); + } else + if (v_class == e_classified_out) { + m_out_loop.push_back(*f_verts_it); + } + + if ((prev_class != e_classified_on) && + (prev_class != v_class)) { + // spanning edge + + const MT_Point3 & ptB = vertex_set[*f_verts_it].m_pos; + + // compute the intersection point of plane and ptA->ptB + MT_Vector3 v = ptB - ptA; + MT_Scalar sideA = plane.signedDistance(ptA); + + MT_Scalar epsilon = -sideA/plane.Normal().dot(v); + MT_Point3 new_p = ptA + (v * epsilon); + + BSP_VertexInd new_vi(vertex_set.size()); + vertex_set.push_back(BSP_MVertex(new_p)); + + m_in_loop.push_back(new_vi); + m_out_loop.push_back(new_vi); + } + + ptA = vertex_set[*f_verts_it].m_pos; + prev_class = v_class; + } + + // Ok should have 2 loops 1 representing the in_loop and + // 1 for the out_loop + + new_face.m_verts = m_out_loop; + face.m_verts = m_in_loop; + + new_face.m_plane = face.m_plane; + + // we don't bother maintaining any of the other + // properties. + + fin = fi; + fout = new_fi; + + m_in_loop.clear(); + m_out_loop.clear(); +}; + + diff --git a/intern/bsp/intern/BSP_CSGNCMeshSplitter.h b/intern/bsp/intern/BSP_CSGNCMeshSplitter.h new file mode 100755 index 00000000000..56c1258f5c4 --- /dev/null +++ b/intern/bsp/intern/BSP_CSGNCMeshSplitter.h @@ -0,0 +1,139 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BSP_CSGNCMeshSplitter_h + +#define BSP_CSGNCMeshSplitter_h + +class BSP_MeshFragment; +class MT_Plane3; +class BSP_CSGMesh; + +#include "BSP_MeshPrimitives.h" +#include "../extern/CSG_BooleanOps.h" +#include "BSP_CSGISplitter.h" + + +/** + * This class contains splitting functions for a CSGMesh. + * The atomic operation of a bsp CSG algorithm is to split + * a mesh fragment (connected collection of polygons contained + * in a convex cell) by a plane. This class makes no attempt + * to maintain edge connectivity in the mesh. It just rips + * up the polygons. This is fine for tree building. + */ + + +class BSP_CSGNCMeshSplitter : public BSP_CSGISplitter +{ +public : + + /// construction + + BSP_CSGNCMeshSplitter( + ); + + BSP_CSGNCMeshSplitter( + const BSP_CSGNCMeshSplitter & other + ); + + /** + * @section BSP specific mesh operations. + * Inherited from BSP_CSGISplitter + */ + + /** + * Split a mesh fragment wrt plane. Generates 3 mesh fragments, + * in, out and on. Only splits polygons - not edges, does not maintain + * connectivity information. The contents of frag are consumed by this oepration. + */ + void + Split( + const MT_Plane3& plane, + BSP_MeshFragment *frag, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + BSP_MeshFragment *spanning_frag + ); + + /// Split the entire mesh with respect to the plane. + + void + Split( + BSP_CSGMesh & mesh, + const MT_Plane3& plane, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + BSP_MeshFragment *spanning_frag + ); + + ~BSP_CSGNCMeshSplitter( + ); + +private : + + void + SplitImp( + BSP_CSGMesh & mesh, + const MT_Plane3& plane, + const std::vector<BSP_FaceInd> & spanning_faces, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + std::vector<BSP_VertexInd> & classified_verts + + ); + + void + SplitPolygon( + const MT_Plane3 &plane, + BSP_CSGMesh & mesh, + BSP_FaceInd fi, + BSP_FaceInd &fin, + BSP_FaceInd &fout + ); + + /// Cached helpers + + /// Split function responsibe for: + std::vector<BSP_FaceInd> m_spanning_faces; + std::vector<BSP_VertexInd> m_tagged_verts; + + /// SplitPolygon responsible for: + std::vector<BSP_FaceInd> m_in_loop,m_out_loop,m_on_loop; + +}; + + +#endif + diff --git a/intern/bsp/intern/BSP_CSGUserData.cpp b/intern/bsp/intern/BSP_CSGUserData.cpp new file mode 100755 index 00000000000..a630c9fc25d --- /dev/null +++ b/intern/bsp/intern/BSP_CSGUserData.cpp @@ -0,0 +1,133 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BSP_CSGUserData.h" + + + +BSP_CSGUserData:: +BSP_CSGUserData( + const int width +): + m_width (width) +{ +} + +/** + * Add a new uninitialized record to the end of the + * array + */ + + void +BSP_CSGUserData:: +IncSize( +){ + m_data.insert(m_data.end(),m_width,char(0)); +} + + int +BSP_CSGUserData:: +Duplicate( + void *record +){ + if (m_width) { + int output = Size(); + IncSize(); + + memcpy(m_data.end() - m_width,record,m_width); + + return output; + } + return 0; +} + + void +BSP_CSGUserData:: +Duplicate( + int record_index +){ + if (m_width) { + int output = Size(); + IncSize(); + memcpy(m_data.end() - m_width,m_data.begin() + record_index * m_width,m_width); + } +} + + + void +BSP_CSGUserData:: +Copy( + void *output, + int pos +){ + if (m_width) { + memcpy(output,m_data.begin() + m_width*pos,m_width); + } +} + void +BSP_CSGUserData:: +Reserve( + int size +){ + m_data.reserve(size * m_width); +} + + +/// Return the width of an individual record + + int +BSP_CSGUserData:: +Width( +) const{ + return m_width; +} + + +/// return the current number of records stored in the array. + int +BSP_CSGUserData:: +Size( +) const { + if (m_width == 0) return 0; + return m_data.size() / m_width; +} + + +/// return a pointer to the start of the nth record in the array. + + void * +BSP_CSGUserData:: +operator [] ( + const int pos +){ + return m_data.begin() + m_width*pos; +} + diff --git a/intern/bsp/intern/BSP_CSGUserData.h b/intern/bsp/intern/BSP_CSGUserData.h new file mode 100755 index 00000000000..86d86cdd0b1 --- /dev/null +++ b/intern/bsp/intern/BSP_CSGUserData.h @@ -0,0 +1,136 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BSP_CSGUserData_h + +#define BSP_CSGUserData_h + +#include <vector> + +/** + * This data represents a continuous block of + * data of unknown type. This holds the user + * data during a BSP operation. + */ + +class BSP_CSGUserData +{ +public : + + /** + * width defines the size in bytes of a + * single element (record) of user data + */ + + BSP_CSGUserData( + const int width + ); + + /** + * Reserve some space in the array + */ + void + Reserve( + int size + ); + + /** + * Add a new uninitialized record to the end of the + * array + */ + + void + IncSize( + ); + + /** + * duplicate a recod and insert it into the end of the array + * returns the index of the new record. Make sure that the + * record does not belong to this buffer as this can cause errors. + */ + + int + Duplicate( + void * + ); + + void + Duplicate( + int record_index + ); + + /** + * Copies the record at position pos in the array to the + * memory pointed to by output + */ + + void + Copy( + void *output, + int pos + ); + + /// Return the width of an individual record + + int + Width( + ) const; + + + /// return the current number of records stored in the array. + int + Size( + ) const; + + + /// return a pointer to the start of the nth record in the array. + + void * + operator [] ( + const int pos + ); + +private : + + /// Private - force use of public constructor only. + + BSP_CSGUserData( + ); + + + /// The block of data. + std::vector<char> m_data; + /// The width of a record in this array. + int m_width; +}; + + +#endif diff --git a/intern/bsp/intern/BSP_FragNode.cpp b/intern/bsp/intern/BSP_FragNode.cpp new file mode 100755 index 00000000000..e23fdd835c7 --- /dev/null +++ b/intern/bsp/intern/BSP_FragNode.cpp @@ -0,0 +1,313 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BSP_CSGMesh.h" + +#include "BSP_FragNode.h" +#include "BSP_CSGISplitter.h" + + +BSP_FragNode:: +BSP_FragNode( + const MT_Plane3 & plane, + BSP_CSGMesh *mesh +): + m_plane(plane), + m_in_tree(mesh), + m_out_tree(mesh) +{ +} + +/** + * Public methods + * Should only be called by BSP_FragTree + */ + +BSP_FragNode:: +~BSP_FragNode( +){ + // nothing to do +} + + MEM_SmartPtr<BSP_FragNode> +BSP_FragNode:: +New( + const MT_Plane3 & plane, + BSP_CSGMesh *mesh +){ + return new BSP_FragNode(plane,mesh); +} + + + void +BSP_FragNode:: +Build( + BSP_MeshFragment *frag, + BSP_CSGISplitter & splitter +){ + // we know there must be some polygons still in + // the fragment otherwise this node would not hve been + // constructed. + + BSP_CSGMesh *mesh = frag->Mesh(); + + // split the incoming fragment by the plane + // generating in,out,on fragments which are + // passed down the in and out trees. + + BSP_MeshFragment in_frag(mesh,e_classified_in),out_frag(mesh,e_classified_out); + MEM_SmartPtr<BSP_MeshFragment> on_frag = new BSP_MeshFragment(mesh,e_classified_on); + splitter.Split(m_plane,frag,&in_frag,&out_frag,on_frag,NULL); + + // We are not interested in the on fragments. + on_frag.Delete(); + + m_in_tree.Build(&in_frag,splitter); + m_out_tree.Build(&out_frag,splitter); +} + + void +BSP_FragNode:: +Push( + BSP_MeshFragment *in_frag, + BSP_MeshFragment *output, + const BSP_Classification keep, + const bool dominant, + BSP_CSGISplitter & splitter +){ + BSP_CSGMesh *mesh = in_frag->Mesh(); + + + MEM_SmartPtr<BSP_MeshFragment> inside_frag = new BSP_MeshFragment(mesh,e_classified_in); + MEM_SmartPtr<BSP_MeshFragment> outside_frag = new BSP_MeshFragment(mesh,e_classified_out); + MEM_SmartPtr<BSP_MeshFragment> on_frag = new BSP_MeshFragment(mesh,e_classified_on); + + // deal with memory exceptions here. + + splitter.Split(m_plane,in_frag,inside_frag,outside_frag,on_frag,NULL); + + // deal with the on_fragments. + + if (on_frag->FaceSet().size()) { + + // The on fragment contains polygons that are outside both subtrees and polygons + // that are inside one or more sub trees. If we are taking the union then we can + // immediately add that first set of polygons to the ouput. We must then decide what + // to do with potenially overlapping polygons from both objects. If we assume both + // objects are closed then we can identify the conflict zones as + // polygons outside B- and inside B+ + // polygons outside B+ and inside B- + + // In these conflict zones we must choose a dominant object this is indicated + // by the bool parameter to this function. If the object is not dominant then + // we do nothing inside these conflict zones. + // The first set should correspond with on polygons from object B with the same + // orientation as this node. The second corresponding with polygons with opposite + // orientation. + // We don't want to replace polygons from A with polygons of opposite orientation + // from B. So we split up the on polygons of A into 2 sets according to their orientation. + // We add to output (A- out B-) in B+ and (A+ out B+) in B- + + +#if 1 + + if (keep == e_classified_out) { + // we are doing a union operation. + // Make sure that this is not a leaf node. + if(m_in_tree.m_node != NULL || m_out_tree.m_node != NULL) { + BSP_MeshFragment frag_outBneg_outBpos(mesh,e_classified_on); + BSP_MeshFragment temp1(on_frag.Ref()); + m_in_tree.Push( + &temp1,&frag_outBneg_outBpos, + e_classified_out,e_classified_on, + false,splitter + ); + + m_out_tree.Push( + &frag_outBneg_outBpos,output,e_classified_out,e_classified_on, + false,splitter + ); + } +#if 1 + if (dominant) { + + // Here we compute the intersection zones. + BSP_MeshFragment frag_on_pos(mesh,e_classified_on),frag_on_neg(mesh,e_classified_on); + on_frag->ClassifyOnFragments(m_plane,&frag_on_pos,&frag_on_neg); + + BSP_MeshFragment temp1(mesh,e_classified_in); + + // push -ve fragments down inside tree, push result down outside + m_in_tree.Push(&frag_on_neg,&temp1,e_classified_out,e_classified_on,false,splitter); + m_out_tree.Push(&temp1,output,e_classified_in,e_classified_on,false,splitter); + temp1.FaceSet().clear(); + + // push +ve fragments down outside tree, push result down inside. + m_out_tree.Push(&frag_on_pos,&temp1,e_classified_out,e_classified_on,false,splitter); + m_in_tree.Push(&temp1,output,e_classified_in,e_classified_on,false,splitter); + } +#endif + } else if (keep == e_classified_in) { + + // we are doing an intersection + + // A = on_frag in X+ out X- + // B = on_frag in X- out X+ + // C = on_frag in X- in X+ + + // If X+ is NULL then A = F out X-, B = 0, C = F in X- + // If X- is NULLL then A = 0, B = F out X+ , C = F in X+ + // If both NULL then A = C = 0, B = F + + // Conflicts only happen in A and B. + // negative fragments only in A, positive fragments only in B, anything in C. + // First compute F in C an add to ouput. + + BSP_MeshFragment frag_on_pos(mesh,e_classified_on),frag_on_neg(mesh,e_classified_on); + on_frag->ClassifyOnFragments(m_plane,&frag_on_pos,&frag_on_neg); + + if (m_in_tree.m_node == NULL) { + if (m_out_tree.m_node == NULL) { + // pick stuff that points in the same direction as this node + // only if priority. + if (dominant) { + // pass +ve frags into B = F. + // trick just pass down in tree... just adds to output. + m_in_tree.Push(&frag_on_pos,output,e_classified_in,e_classified_on,false,splitter); + } + } else { + // A = 0, B= F out X+ , C = F in X+ + if (dominant) { + // m_out_tree.Push(&frag_on_pos,output,e_classified_out,e_classified_on,false,splitter); + m_out_tree.Push(on_frag,output,e_classified_in,e_classified_on,false,splitter); + } + } + } else { + if (m_out_tree.m_node == NULL) { + // A = F out X-, B=0, C = F in X- + if (dominant) { + // m_in_tree.Push(&frag_on_neg,output,e_classified_out,e_classified_on,false,splitter); + m_in_tree.Push(on_frag,output,e_classified_in,e_classified_on,false,splitter); + } + } else { + // The normals case + if (dominant) { + BSP_MeshFragment temp1(mesh,e_classified_on); + m_out_tree.Push(&frag_on_neg,&temp1,e_classified_in,e_classified_on,false,splitter); + m_in_tree.Push(&temp1,output,e_classified_out,e_classified_on,false,splitter); + temp1.FaceSet().clear(); + + m_in_tree.Push(&frag_on_pos,&temp1,e_classified_in,e_classified_on,false,splitter); + m_out_tree.Push(&temp1,output,e_classified_out,e_classified_on,false,splitter); + } + BSP_MeshFragment temp1(mesh,e_classified_on); + m_in_tree.Push(on_frag,&temp1,e_classified_in,e_classified_on,false,splitter); + m_out_tree.Push(&temp1,output,e_classified_in,e_classified_on,false,splitter); + } + } + } + + +#endif + on_frag.Delete(); + } + + m_in_tree.Push(inside_frag,output,keep,e_classified_in,dominant,splitter); + m_out_tree.Push(outside_frag,output,keep,e_classified_out,dominant,splitter); +}; + + void +BSP_FragNode:: +Classify( + BSP_MeshFragment * frag, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + BSP_CSGISplitter & splitter +){ + + BSP_CSGMesh *mesh = frag->Mesh(); + + MEM_SmartPtr<BSP_MeshFragment> inside_frag = new BSP_MeshFragment(mesh,e_classified_in); + MEM_SmartPtr<BSP_MeshFragment> outside_frag = new BSP_MeshFragment(mesh,e_classified_out); + MEM_SmartPtr<BSP_MeshFragment> frag_on = new BSP_MeshFragment(mesh,e_classified_on); + + splitter.Split(m_plane,frag,inside_frag,outside_frag,frag_on,NULL); + + // copy the on fragments into the on_frag output. + + if (frag_on->FaceSet().size()) { + + on_frag->FaceSet().insert( + on_frag->FaceSet().end(), + frag_on->FaceSet().begin(), + frag_on->FaceSet().end() + ); + } + + frag_on.Delete(); + + // pass everything else down the tree. + + m_in_tree.Classify(inside_frag,in_frag,out_frag,on_frag,e_classified_in,splitter); + m_out_tree.Classify(outside_frag,in_frag,out_frag,on_frag,e_classified_out,splitter); +} + + +/** + * Accessor methods + */ + + BSP_FragTree & +BSP_FragNode:: +InTree( +){ + return m_in_tree; +} + + BSP_FragTree & +BSP_FragNode:: +OutTree( +){ + return m_out_tree; +} + + MT_Plane3& +BSP_FragNode:: +Plane( +){ + return m_plane; +} + + + + + diff --git a/intern/bsp/intern/BSP_FragNode.h b/intern/bsp/intern/BSP_FragNode.h new file mode 100755 index 00000000000..f289419950b --- /dev/null +++ b/intern/bsp/intern/BSP_FragNode.h @@ -0,0 +1,127 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BSP_FragNode_h + +#define BSP_FragNode_h + +#include "BSP_FragTree.h" +#include "BSP_MeshFragment.h" +#include "MT_Plane3.h" + +class BSP_CSGISplitter; + +class BSP_FragNode : public MEM_NonCopyable +{ +private: + + /** + * The plane defining this node. + */ + + MT_Plane3 m_plane; + + /** + * Children of this node. + */ + + BSP_FragTree m_in_tree; + BSP_FragTree m_out_tree; + +private : + + BSP_FragNode( + const MT_Plane3 & plane, + BSP_CSGMesh *mesh + ); + +public : + + /** + * Public methods + * Should only be called by BSP_FragTree + */ + + ~BSP_FragNode( + ); + + static + MEM_SmartPtr<BSP_FragNode> + New( + const MT_Plane3 & plane, + BSP_CSGMesh *mesh + ); + + void + Build( + BSP_MeshFragment *frag, + BSP_CSGISplitter & splitter + ); + + void + Push( + BSP_MeshFragment *in_frag, + BSP_MeshFragment *output, + const BSP_Classification keep, + const bool dominant, + BSP_CSGISplitter & splitter + ); + + void + Classify( + BSP_MeshFragment * frag, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + BSP_CSGISplitter & splitter + ); + + /** + * Accessor methods + */ + + BSP_FragTree & + InTree( + ); + + BSP_FragTree & + OutTree( + ); + + MT_Plane3& + Plane( + ); + +}; + + + +#endif
\ No newline at end of file diff --git a/intern/bsp/intern/BSP_FragTree.cpp b/intern/bsp/intern/BSP_FragTree.cpp new file mode 100755 index 00000000000..3668db6cf7c --- /dev/null +++ b/intern/bsp/intern/BSP_FragTree.cpp @@ -0,0 +1,319 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BSP_FragTree.h" + +#include "BSP_FragNode.h" +#include "BSP_CSGMesh.h" +#include "BSP_MeshFragment.h" +#include "MT_Plane3.h" +#include "BSP_CSGException.h" +#include <vector> +#include "BSP_CSGISplitter.h" + +using namespace std; + + MEM_SmartPtr<BSP_FragTree> +BSP_FragTree:: +New( + BSP_CSGMesh *mesh, + BSP_CSGISplitter & splitter +){ + if (mesh == NULL) return NULL; + if (mesh->FaceSet().size() == 0) return NULL; + + // This is the external tree construction method + // (not the internal method!) + // We need to build a tree root with an initial + // node based on the mesh rather than a mesh fragment. + + // For now we pick an arbitrary polygon for the initial + // plane. + + vector<BSP_MVertex> verts = mesh->VertexSet(); + const BSP_MFace & f0 = mesh->FaceSet()[0]; + + const MT_Vector3 & p1 = verts[f0.m_verts[0]].m_pos; + const MT_Vector3 & p2 = verts[f0.m_verts[1]].m_pos; + const MT_Vector3 & p3 = verts[f0.m_verts[2]].m_pos; + + MT_Plane3 plane = f0.m_plane; + + MEM_SmartPtr<BSP_FragTree> output(new BSP_FragTree(mesh)); + MEM_SmartPtr<BSP_FragNode> node(BSP_FragNode::New(plane,mesh)); + + if (output == NULL || node == NULL) return NULL; + + // Generate initial mesh fragments for this plane pass into + // first node. + + BSP_MeshFragment frag_in(mesh,e_classified_in),frag_out(mesh,e_classified_out); + + MEM_SmartPtr<BSP_MeshFragment> on_frag = new BSP_MeshFragment(mesh,e_classified_on); + + splitter.Split(*mesh,plane,&frag_in,&frag_out,on_frag,NULL); + + // We are not interested in the on_frag. + on_frag.Delete(); + + // Build the in_tree of the first node(recursive) + node->InTree().Build(&frag_in,splitter); + + // Build the out tree of the first node(recursive) + node->OutTree().Build(&frag_out,splitter); + + output->m_node = node; + + return output; +} + + void +BSP_FragTree:: +Classify( + BSP_CSGMesh *mesh, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + BSP_CSGISplitter & splitter +){ + + if (mesh == NULL) return; + if (mesh->FaceSet().size() == 0) return; + if (m_node == NULL) return; + + BSP_MeshFragment frag_in(mesh,e_classified_in); + BSP_MeshFragment frag_out(mesh,e_classified_out); + BSP_MeshFragment frag_on(mesh,e_classified_on); + BSP_MeshFragment frag_spanning(mesh,e_classified_spanning); + + splitter.Split(*mesh,m_node->Plane(),&frag_in,&frag_out,&frag_on,NULL); + + if (frag_on.FaceSet().size()) { + + on_frag->FaceSet().insert( + on_frag->FaceSet().end(), + frag_on.FaceSet().begin(), + frag_on.FaceSet().end() + ); + + frag_on.FaceSet().clear(); + } + + // recurse into subtrees. + m_node->InTree().Classify(&frag_in,in_frag,out_frag,on_frag,e_classified_in,splitter); + m_node->OutTree().Classify(&frag_out,in_frag,out_frag,on_frag,e_classified_out,splitter); + +} + + + + + +BSP_FragTree:: +~BSP_FragTree( +){ + // nothing to do +} + +BSP_FragTree:: +BSP_FragTree( + BSP_CSGMesh * mesh +): + m_mesh(mesh) +{ + //nothing to do +} + +BSP_FragTree:: +BSP_FragTree( +){ + // nothing to do +} + + void +BSP_FragTree:: +Build( + BSP_MeshFragment * frag, + BSP_CSGISplitter & splitter +){ + + // Node must be NULL because we are building the tree. + + MT_assert(m_node == NULL); + + if (frag->FaceSet().size()) { + + // choose a plane for the node. The first index in this + // mesh fragment will do for now. + vector<BSP_MVertex> & verts = m_mesh->VertexSet(); + + // choose a random splitting plane + + MT_Plane3 plane; + { + int rand_index; +#if 1 + if (frag->FaceSet().size() > 1) { + rand_index = rand() % frag->FaceSet().size(); + } else { + rand_index = 0; + } +#else + rand_index = 0; +#endif + + const BSP_MFace & f0 = m_mesh->FaceSet()[frag->FaceSet()[rand_index]]; + plane = f0.m_plane; + } + + // build the node. + m_node = BSP_FragNode::New(plane,frag->Mesh()); + + if (m_node == NULL) { + BSP_CSGException e(e_tree_build_error); + throw(e); + } + + m_node->Build(frag,splitter); + } +} + + + void +BSP_FragTree:: +Push( + BSP_MeshFragment *in_frag, + BSP_MeshFragment *output, + const BSP_Classification keep, + const BSP_Classification current, + const bool dominant, + BSP_CSGISplitter & splitter +){ + + if (in_frag->FaceSet().size()) { + + if (m_node == NULL) { + + // we have reached a leaf node. + // if the current classification matches + // the classification we want to keep + // copy the polygons of the current + // fragment onto the output + vector<BSP_FaceInd>::const_iterator in_frag_it = in_frag->FaceSet().begin(); + vector<BSP_FaceInd>::const_iterator in_frag_end = in_frag->FaceSet().end(); + vector<BSP_MFace>::iterator faces = in_frag->Mesh()->FaceSet().begin(); + + if (keep == current || current == e_classified_on) { + for (;in_frag_it != in_frag_end; ++ in_frag_it) { + output->FaceSet().push_back(*in_frag_it); + } + + in_frag->FaceSet().clear(); + } + } else { + + m_node->Push(in_frag,output,keep,dominant,splitter); + } + } +} + + + void +BSP_FragTree:: +Classify( + BSP_MeshFragment * frag, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + const BSP_Classification current, + BSP_CSGISplitter & splitter +){ + + if (frag->FaceSet().size()) { + + if (m_node == NULL) { + + vector<BSP_FaceInd>::const_iterator frag_it = frag->FaceSet().begin(); + vector<BSP_FaceInd>::const_iterator frag_end = frag->FaceSet().end(); + + BSP_MeshFragment *output; + if (current == e_classified_in) { + output = in_frag; + } else { + //must be e_classified_out + output = out_frag; + } + // Copy the selected indices into the correct output fragment. + + for (;frag_it != frag_end; ++ frag_it) { + output->FaceSet().push_back(*frag_it); + } + + frag->FaceSet().clear(); + } else { + + m_node->Classify(frag,in_frag,out_frag,on_frag,splitter); + } + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/intern/bsp/intern/BSP_FragTree.h b/intern/bsp/intern/BSP_FragTree.h new file mode 100755 index 00000000000..7965a055c92 --- /dev/null +++ b/intern/bsp/intern/BSP_FragTree.h @@ -0,0 +1,146 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BSP_FragTree_h + +#define BSP_FragTree_h + +class BSP_FragNode; + +#include "MEM_SmartPtr.h" +#include "MEM_NonCopyable.h" +#include "BSP_MeshPrimitives.h" + +class BSP_CSGMesh; +class BSP_MeshFragment; +class BSP_CSGISplitter; + +class BSP_FragTree : public MEM_NonCopyable +{ +public : + + /** + * Create a new BSP_FragTree allocated + * on the heap for mesh. Note mesh will + * be divided up by this operation. If you + * want to retain the original mesh make a copy + * of it first. + */ + + static + MEM_SmartPtr<BSP_FragTree> + New( + BSP_CSGMesh *mesh, + BSP_CSGISplitter & splitter + ); + + + /** + * Push a mesh fragment down the tree, + * splitting the mesh as it goes. + * upon reaching leaves it puts polygons from fragments + * of type keep into the output fragment. + */ + + void + Push( + BSP_MeshFragment *in_frag, + BSP_MeshFragment *output, + const BSP_Classification keep, + const BSP_Classification current, + const bool dominant, + BSP_CSGISplitter & splitter + ); + + void + Classify( + BSP_CSGMesh *mesh, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + BSP_CSGISplitter & splitter + ); + + + ~BSP_FragTree( + ); + +private : + + friend class BSP_FragNode; + + BSP_FragTree( + ); + + BSP_FragTree( + BSP_CSGMesh *mesh + ); + + void + Build( + BSP_MeshFragment * frag, + BSP_CSGISplitter & splitter + ); + + + void + Classify( + BSP_MeshFragment * frag, + BSP_MeshFragment *in_frag, + BSP_MeshFragment *out_frag, + BSP_MeshFragment *on_frag, + const BSP_Classification current, + BSP_CSGISplitter & splitter + ); + +private : + + /** + * pointer to the mesh for this tree. + * Tree is only valid whilst mesh is around. + */ + + BSP_CSGMesh *m_mesh; + + /** + * The node owned by this tree. + */ + + MEM_SmartPtr<BSP_FragNode> m_node; + +}; + + +#endif + + + + diff --git a/intern/bsp/intern/BSP_MeshFragment.cpp b/intern/bsp/intern/BSP_MeshFragment.cpp new file mode 100755 index 00000000000..408a13d6cd9 --- /dev/null +++ b/intern/bsp/intern/BSP_MeshFragment.cpp @@ -0,0 +1,279 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BSP_MeshFragment.h" + +#include "BSP_CSGMesh.h" +#include "MT_Plane3.h" +#include <math.h> + +using namespace std; + + +BSP_MeshFragment:: +BSP_MeshFragment( + BSP_CSGMesh *mesh, + BSP_Classification classification +): + m_mesh(mesh), + m_classification(classification) +{ + MT_assert(m_mesh != NULL); + //nothing to do +} + +const + vector<BSP_FaceInd> & +BSP_MeshFragment:: +FaceSet( +) const { + return m_faces; +} + + vector<BSP_FaceInd> & +BSP_MeshFragment:: +FaceSet( +) { + return m_faces; +} + + BSP_CSGMesh * +BSP_MeshFragment:: +Mesh( +){ + return m_mesh; +} + + BSP_CSGMesh * +BSP_MeshFragment:: +Mesh( +) const { + return m_mesh; +} + + BSP_Classification +BSP_MeshFragment:: +ClassifyPolygon( + const MT_Plane3 &plane, + const BSP_MFace & face, + std::vector<BSP_MVertex>::const_iterator verts, + vector<BSP_VertexInd> & visited_verts +){ + + vector<BSP_VertexInd>::const_iterator f_vi_end = face.m_verts.end(); + vector<BSP_VertexInd>::const_iterator f_vi_it = face.m_verts.begin(); + + BSP_Classification p_class = e_unclassified; + + int on_count = 0; + + for (;f_vi_it != f_vi_end; ++f_vi_it) { + + BSP_MVertex & vert = const_cast<BSP_MVertex &>(verts[int(*f_vi_it)]); + + if (BSP_Classification(vert.OpenTag()) == e_unclassified) + { + MT_Scalar sdistance = plane.signedDistance(vert.m_pos); + MT_Scalar fsdistance = fabs(sdistance); + + if (fabs(sdistance) <= BSP_SPLIT_EPSILON) { + // this vertex is on + vert.SetOpenTag(e_classified_on); + } else + if (sdistance > MT_Scalar(0)) { + vert.SetOpenTag(e_classified_out); + } else { + vert.SetOpenTag(e_classified_in); + } + visited_verts.push_back(*f_vi_it); + } + BSP_Classification v_class = BSP_Classification(vert.OpenTag()); + + if (v_class == e_classified_on) on_count++; + + + if (p_class == e_unclassified || p_class == e_classified_on) { + p_class = v_class; + } else + if (p_class == e_classified_spanning) { + } else + if (p_class == e_classified_in) { + if (v_class == e_classified_out) { + p_class = e_classified_spanning; + } + } else { + if (v_class == e_classified_in) { + p_class = e_classified_spanning; + } + } + } + + if (on_count > 2) p_class = e_classified_on; + + return p_class; +} + + +// Classify this mesh fragment with respect +// to plane. The index sets of this fragment +// are consumed by this action. Vertices +// are tagged with a classification enum. + + void +BSP_MeshFragment:: +Classify( + const MT_Plane3 & plane, + BSP_MeshFragment * in_frag, + BSP_MeshFragment * out_frag, + BSP_MeshFragment * on_frag, + vector<BSP_FaceInd> & spanning_faces, + vector<BSP_VertexInd> & visited_verts +){ + + vector<BSP_MVertex> & vertex_set = m_mesh->VertexSet(); + vector<BSP_MFace> & face_set = m_mesh->FaceSet(); + + // Now iterate through the polygons and classify. + + vector<BSP_FaceInd>::const_iterator fi_end = m_faces.end(); + vector<BSP_FaceInd>::iterator fi_it = m_faces.begin(); + + vector<BSP_FaceInd> & face_in_set = in_frag->FaceSet(); + vector<BSP_FaceInd> & face_out_set = out_frag->FaceSet(); + vector<BSP_FaceInd> & face_on_set = on_frag->FaceSet(); + + for (;fi_it != fi_end; ++fi_it) { + + BSP_Classification p_class = ClassifyPolygon( + plane, + face_set[*fi_it], + vertex_set.begin(), + visited_verts + ); + // p_class now holds the classification for this polygon. + // assign to the appropriate bucket. + + if (p_class == e_classified_in) { + face_in_set.push_back(*fi_it); + } else + if (p_class == e_classified_out) { + face_out_set.push_back(*fi_it); + } else + if (p_class == e_classified_on) { + face_on_set.push_back(*fi_it); + } else { + spanning_faces.push_back(*fi_it); + // This is assigned later when we split the polygons in two. + } + } + + m_faces.clear(); + +} + + void +BSP_MeshFragment:: +Classify( + BSP_CSGMesh & mesh, + const MT_Plane3 & plane, + BSP_MeshFragment * in_frag, + BSP_MeshFragment * out_frag, + BSP_MeshFragment * on_frag, + vector<BSP_FaceInd> & spanning_faces, + vector<BSP_VertexInd> & visited_verts +){ + + vector<BSP_MVertex> & vertex_set = mesh.VertexSet(); + vector<BSP_MFace> & face_set = mesh.FaceSet(); + + // Now iterate through the polygons and classify. + + int fi_end = mesh.FaceSet().size(); + int fi_it = 0; + + vector<BSP_FaceInd> & face_in_set = in_frag->FaceSet(); + vector<BSP_FaceInd> & face_out_set = out_frag->FaceSet(); + vector<BSP_FaceInd> & face_on_set = on_frag->FaceSet(); + + for (;fi_it != fi_end; ++fi_it) { + + BSP_Classification p_class = ClassifyPolygon( + plane, + face_set[fi_it], + vertex_set.begin(), + visited_verts + ); + // p_class now holds the classification for this polygon. + // assign to the appropriate bucket. + + if (p_class == e_classified_in) { + face_in_set.push_back(fi_it); + } else + if (p_class == e_classified_out) { + face_out_set.push_back(fi_it); + } else + if (p_class == e_classified_on) { + face_on_set.push_back(fi_it); + } else { + spanning_faces.push_back(fi_it); + } + } + +} + void +BSP_MeshFragment:: +ClassifyOnFragments( + const MT_Plane3 &plane, + BSP_MeshFragment *pos_frag, + BSP_MeshFragment *neg_frag +){ + + vector<BSP_MFace> & face_set = m_mesh->FaceSet(); + vector<BSP_FaceInd>::const_iterator fi_end = m_faces.end(); + vector<BSP_FaceInd>::iterator fi_it = m_faces.begin(); + + MT_Scalar d = plane.Scalar(); + + for (;fi_it != fi_end; ++fi_it) { + if (fabs(d + face_set[*fi_it].m_plane.Scalar()) > BSP_SPLIT_EPSILON) { + pos_frag->FaceSet().push_back(*fi_it); + } else { + neg_frag->FaceSet().push_back(*fi_it); + } + } +} + +BSP_MeshFragment:: +~BSP_MeshFragment( +){ +} + + diff --git a/intern/bsp/intern/BSP_MeshFragment.h b/intern/bsp/intern/BSP_MeshFragment.h new file mode 100755 index 00000000000..e0068d1c9e7 --- /dev/null +++ b/intern/bsp/intern/BSP_MeshFragment.h @@ -0,0 +1,152 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_BSP_MeshFragment_h + +#define NAN_INCLUDED_BSP_MeshFragment_h + +#define BSP_SPLIT_EPSILON MT_Scalar(1e-5) + +#include <vector> +#include "BSP_MeshPrimitives.h" + + +class BSP_CSGMesh; +class MT_Plane3; +/** + * This class encodes a collection of polygons from a mesh. + * This class only remains valid when mesh indices do not change + * internally and of course whilst the mesh is still around. + * + * Polygons in the mesh point back to the unique mesh fragment + * containing them. + */ + + +class BSP_MeshFragment { +public: + + BSP_MeshFragment( + BSP_CSGMesh *mesh, + BSP_Classification classification + ); + + std::vector<BSP_FaceInd> & + FaceSet( + ) ; + + const + std::vector<BSP_FaceInd> & + FaceSet( + ) const ; + + BSP_CSGMesh * + Mesh( + ); + + BSP_CSGMesh * + Mesh( + ) const; + + + // Classify this mesh fragment with respect + // to plane. The index sets of this fragment + // are consumed by this action. Vertices + // are tagged with a classification enum. + + void + Classify( + const MT_Plane3 & plane, + BSP_MeshFragment * in_frag, + BSP_MeshFragment * out_frag, + BSP_MeshFragment * on_frag, + std::vector<BSP_FaceInd> & spanning_faces, + std::vector<BSP_VertexInd> & visited_verts + ); + + // Classify all the vertices and faces of mesh, generate + // in,out and on mesh fragments. + + static + void + Classify( + BSP_CSGMesh & mesh, + const MT_Plane3 & plane, + BSP_MeshFragment * in_frag, + BSP_MeshFragment * out_frag, + BSP_MeshFragment * on_frag, + std::vector<BSP_FaceInd> & spanning_faces, + std::vector<BSP_VertexInd> & visited_verts + ); + + // Classify the on fragment into + // 2 sets, the +ve on frags those whose polygon + // normals point in the same direction as the plane, + // and the -ve frag whose normals point in the other direction. + + void + ClassifyOnFragments( + const MT_Plane3 &plane, + BSP_MeshFragment *pos_frag, + BSP_MeshFragment *neg_frag + ); + + + ~BSP_MeshFragment( + ); + + /** + * Sanity checkers. + */ + + +private: + + // Classify the polygon wrt to the plane + static + BSP_Classification + ClassifyPolygon( + const MT_Plane3 &plane, + const BSP_MFace & face, + std::vector<BSP_MVertex>::const_iterator verts, + std::vector<BSP_VertexInd> & visited_verts + ); + +private : + + + BSP_CSGMesh * m_mesh; + BSP_Classification m_classification; + std::vector<BSP_FaceInd> m_faces; +}; + + +#endif diff --git a/intern/bsp/intern/BSP_MeshPrimitives.cpp b/intern/bsp/intern/BSP_MeshPrimitives.cpp new file mode 100755 index 00000000000..7425510b6a4 --- /dev/null +++ b/intern/bsp/intern/BSP_MeshPrimitives.cpp @@ -0,0 +1,301 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BSP_MeshPrimitives.h" + +#include "MT_assert.h" +#include "BSP_CSGException.h" +#include <algorithm> + +using namespace std; + +BSP_MVertex:: +BSP_MVertex( +) : + m_pos (MT_Point3()), + m_select_tag (false), + m_open_tag (0) +{ +}; + +BSP_MVertex:: +BSP_MVertex( + const MT_Point3 & pos +) : + m_pos(pos), + m_select_tag (false), + m_open_tag (0) +{ +}; + + + bool +BSP_MVertex:: +RemoveEdge( + BSP_EdgeInd e +){ + vector<BSP_EdgeInd>::iterator result = find(m_edges.begin(),m_edges.end(),e); + if (result == m_edges.end()) { + return false; + } + BSP_EdgeInd last = m_edges.back(); + m_edges.pop_back(); + if (m_edges.empty()) return true; + + *result = last; + return true; +} + + void +BSP_MVertex:: +AddEdge( + BSP_EdgeInd e +){ + m_edges.push_back(e); +} + + void +BSP_MVertex:: +SwapEdge( + BSP_EdgeInd e_old, + BSP_EdgeInd e_new +){ + vector<BSP_EdgeInd>::iterator result = + find(m_edges.begin(),m_edges.end(),e_old); + if (result == m_edges.end()) { + BSP_CSGException e(e_mesh_error); + throw(e); + MT_assert(false); + } + + *result = e_new; +} + + bool +BSP_MVertex:: +SelectTag( +) const{ + return m_select_tag; +} + + void +BSP_MVertex:: +SetSelectTag( + bool tag +){ + m_select_tag = tag; +} + + int +BSP_MVertex:: +OpenTag( +) const { + return m_open_tag; +} + + void +BSP_MVertex:: +SetOpenTag( + int tag +){ + m_open_tag = tag; +} + + +/** + * Edge Primitive Methods. + */ + +BSP_MEdge:: +BSP_MEdge( +){ + m_verts[0] = m_verts[1] = BSP_VertexInd::Empty(); +} + + bool +BSP_MEdge:: +operator == ( + BSP_MEdge & rhs +){ + // edges are the same if their vertex indices are the + // same!!! Other properties are not checked + + int matches = 0; + + if (this->m_verts[0] == rhs.m_verts[0]) { + ++matches; + } + if (this->m_verts[1] == rhs.m_verts[0]) { + ++matches; + } + if (this->m_verts[0] == rhs.m_verts[1]) { + ++matches; + } + if (this->m_verts[1] == rhs.m_verts[1]) { + ++matches; + } + + if (matches >= 2) { + return true; + } + return false; +} + + void +BSP_MEdge:: +SwapFace( + BSP_FaceInd old_f, + BSP_FaceInd new_f +){ + vector<BSP_FaceInd>::iterator result = + find(m_faces.begin(),m_faces.end(),old_f); + if (result == m_faces.end()) { + BSP_CSGException e(e_mesh_error); + throw(e); + MT_assert(false); + } + + *result = new_f; +} + + BSP_VertexInd +BSP_MEdge:: +OpVertex( + BSP_VertexInd vi +) const { + if (vi == m_verts[0]) return m_verts[1]; + if (vi == m_verts[1]) return m_verts[0]; + MT_assert(false); + BSP_CSGException e(e_mesh_error); + throw(e); + + return BSP_VertexInd::Empty(); +} + + bool +BSP_MEdge:: +SelectTag( +) const { + return bool(m_verts[1].Tag() & 0x1); +} + void +BSP_MEdge:: +SetSelectTag( + bool tag +){ + m_verts[1].SetTag(int(tag)); +} + + int +BSP_MEdge:: +OpenTag( +) const { + return m_verts[0].Tag(); +} + + void +BSP_MEdge:: +SetOpenTag( + int tag +) { + // Note conversion from int to unsigned int!!!!! + m_verts[0].SetTag(tag); +} + + +/** + * Face primitive methods + */ + + +BSP_MFace:: +BSP_MFace( +): + m_open_tag(-1) +{ + // nothing to do +} + + void +BSP_MFace:: +Invert( +){ + + // TODO replace reverse as I think some compilers + // do not support the STL routines employed. + + reverse( + m_verts.begin(), + m_verts.end() + ); + + reverse( + m_fv_data.begin(), + m_fv_data.end() + ); + + // invert the normal + m_plane.Invert(); +} + + bool +BSP_MFace:: +SelectTag( +) const { + return bool(m_verts[1].Tag() & 0x1); +} + + void +BSP_MFace:: +SetSelectTag( + bool tag +){ + m_verts[1].SetTag(int(tag)); +}; + + int +BSP_MFace:: +OpenTag( +) const { + return m_open_tag; +} + + void +BSP_MFace:: +SetOpenTag( + int tag +){ + // Note conversion from int to unsigned int!!!!! + m_open_tag = tag; +} + + + diff --git a/intern/bsp/intern/BSP_MeshPrimitives.h b/intern/bsp/intern/BSP_MeshPrimitives.h new file mode 100644 index 00000000000..8ba9cc6b83e --- /dev/null +++ b/intern/bsp/intern/BSP_MeshPrimitives.h @@ -0,0 +1,289 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_BSP_MeshPrimitives + +#define NAN_INCLUDED_BSP_MeshPrimitives + +#include "CTR_TaggedIndex.h" +#include "MT_Vector3.h" +#include "MT_Plane3.h" + +class BSP_MeshFragment; + +#include <vector> + +typedef CTR_TaggedIndex<24,0x00ffffff> BSP_VertexInd; +typedef CTR_TaggedIndex<24,0x00ffffff> BSP_EdgeInd; +typedef CTR_TaggedIndex<24,0x00ffffff> BSP_FaceInd; +typedef CTR_TaggedIndex<24,0x00ffffff> BSP_FragInd; +typedef CTR_TaggedIndex<24,0x00ffffff> BSP_UserFVInd; + + +typedef std::vector<BSP_VertexInd> BSP_VertexList; +typedef std::vector<BSP_EdgeInd> BSP_EdgeList; +typedef std::vector<BSP_FaceInd> BSP_FaceList; +typedef std::vector<BSP_UserFVInd> BSP_UserFVDataList; + +/** + * Enum representing classification of primitives + * with respect to a hyperplane. + */ + +enum BSP_Classification{ + e_unclassified = 0, + e_classified_in = 1, + e_classified_out = 2, + e_classified_on = 4, + e_classified_spanning = 7 +}; + +/** + * @section Mesh linkage + * The mesh is linked in a similar way to the decimation mesh, + * although the primitives are a little more general and not + * limited to manifold meshes. + * Vertices -> (2+)Edges + * Edges -> (1+)Polygons + * Edges -> (2)Vertices. + * Polygons -> (3+)Vertices. + * + * this structure allows for arbitrary polygons (assumed to be convex). + * Edges can point to more than 2 polygons (non-manifold) + * + * We also define 2 different link types between edges and their + * neighbouring polygons. A weak link and a strong link. + * A weak link means the polygon is in a different mesh fragment + * to the other polygon. A strong link means the polygon is in the + * same fragment. + * This is not entirely consistent as it means edges have to be associated + * with fragments, in reality only polygons will be - edges and vertices + * will live in global pools. I guess we should mark edges as being on plane + * boundaries. This leaves a problem with non-manifold edges because for example + * 3 of 4 possible edges could lie in 1 fragment and the remaining edge lie in + * another, there is no way to work out then from one polygon which neighbouring + * polygons are in the same/different mesh fragment. + * + * By definition an edge will only ever lie on 1 hyperplane. We can then just + * tag neighbouring polygons with one of 3 tags to group them. + */ + +class BSP_MVertex { +public : + MT_Point3 m_pos; + BSP_EdgeList m_edges; + + /** + * TODO + * Is this boolean necessary or can we nick a few bits of m_edges[0] + * for example? + * The only problem with this is that if the vertex is degenerate then + * m_edges[0] may not exist. If the algorithm guarentees that this is + * not the case then it should be changed. + */ + + bool m_select_tag; + int m_open_tag; + + BSP_MVertex( + ); + + BSP_MVertex( + const MT_Point3 & pos + ); + + BSP_MVertex & + operator = ( + const BSP_MVertex & other + ) { + m_pos = other.m_pos; + m_edges = other.m_edges; + m_select_tag = other.m_select_tag; + m_open_tag = other.m_open_tag; + return (*this); + }; + + bool + RemoveEdge( + BSP_EdgeInd e + ); + + void + AddEdge( + BSP_EdgeInd e + ); + + void + SwapEdge( + BSP_EdgeInd e_old, + BSP_EdgeInd e_new + ); + + /** + * These operations are ONLY valid when the + * vertex has some edges associated with it. + * This is left to the user to guarentee. + * Also note that these tag's are not guarenteed + * to survive after a call to RemoveEdge(), + * because we use edges for the open tag. + */ + + int + OpenTag( + ) const; + + void + SetOpenTag( + int tag + ); + + bool + SelectTag( + ) const; + + void + SetSelectTag( + bool tag + ); +}; + +class BSP_MEdge { +public : + BSP_VertexInd m_verts[2]; + BSP_FaceList m_faces; + + BSP_MEdge( + ); + + bool operator == ( + BSP_MEdge & rhs + ); + + void + SwapFace( + BSP_FaceInd old_f, + BSP_FaceInd new_f + ); + + BSP_VertexInd + OpVertex( + BSP_VertexInd vi + ) const; + + bool + SelectTag( + ) const; + + void + SetSelectTag( + bool tag + ); + + /** + * We use one of the vertex indices for tag informtaion. + * This means these tags will not survive if you change + * the vertex indices. + */ + + int + OpenTag( + ) const; + + void + SetOpenTag( + int tag + ) ; +}; + +class BSP_MFace { +public : + + BSP_VertexList m_verts; + + // This is a list of face vertex data indices. + // Each vertex index in the list has an equivalent + // index into an array of face vertex data. This data + // is stored externally - the mesh does not know about it's + // contents. + + BSP_UserFVDataList m_fv_data; + // We also store the plane equation of this + // face. Generating on the fly during tree + // construction can lead to a lot of numerical errors. + // because the polygon size can get very small. + + MT_Plane3 m_plane; + + int m_open_tag; + + BSP_MFace( + ); + + // Invert the face , done by reversing the vertex order + // and inverting the face normal. + + void + Invert( + ); + + /** + * Tagging + * We use the tag from m_verts[1] for the select tag + * and the the tag from m_verts[0] for the open tag. + * There is always a chance that the polygon contains + * no vertices but this should be checked at construction + * time. + * Also note that changing the vertex indices of this polygon + * will likely remove tagging information. + * + */ + + bool + SelectTag( + ) const; + + void + SetSelectTag( + bool tag + ); + + int + OpenTag( + ) const; + + void + SetOpenTag( + int tag + ) ; + +}; + +#endif
\ No newline at end of file diff --git a/intern/bsp/intern/BSP_Triangulate.cpp b/intern/bsp/intern/BSP_Triangulate.cpp new file mode 100755 index 00000000000..a78b8ff0a92 --- /dev/null +++ b/intern/bsp/intern/BSP_Triangulate.cpp @@ -0,0 +1,249 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdio.h> + +#include <stdlib.h> +#include "MT_Plane3.h" +#include "BSP_Triangulate.h" +#include "MT_assert.h" + +static const MT_Scalar EPSILON = MT_Scalar(1e-10); + +using namespace std; + +BSP_Triangulate:: +BSP_Triangulate( +): + m_xi(0), + m_yi(1) +{ +} + +BSP_Triangulate:: +~BSP_Triangulate( +){ +} + + + MT_Scalar +BSP_Triangulate:: +Area( + const vector<BSP_MVertex> &verts, + const BSP_VertexList &contour +){ + + int n = contour.size(); + + MT_Scalar A(0.0); + + for(int p=n-1,q=0; q<n; p=q++) + { + A+= verts[contour[p]].m_pos[m_xi]*verts[contour[q]].m_pos[m_yi] - + verts[contour[q]].m_pos[m_xi]*verts[contour[p]].m_pos[m_yi]; + } + return A*MT_Scalar(0.5); +} + +/* + InsideTriangle decides if a point P is Inside of the triangle + defined by A, B, C. + Or within an epsilon of it. +*/ + + bool +BSP_Triangulate:: +InsideTriangle( + MT_Scalar Ax, MT_Scalar Ay, + MT_Scalar Bx, MT_Scalar By, + MT_Scalar Cx, MT_Scalar Cy, + MT_Scalar Px, MT_Scalar Py +){ + MT_Scalar ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy; + MT_Scalar cCROSSap, bCROSScp, aCROSSbp; + + ax = Cx - Bx; ay = Cy - By; + bx = Ax - Cx; by = Ay - Cy; + cx = Bx - Ax; cy = By - Ay; + apx= Px - Ax; apy= Py - Ay; + bpx= Px - Bx; bpy= Py - By; + cpx= Px - Cx; cpy= Py - Cy; + + aCROSSbp = ax*bpy - ay*bpx; + cCROSSap = cx*apy - cy*apx; + bCROSScp = bx*cpy - by*cpx; + + return ((aCROSSbp >= -EPSILON) && (bCROSScp >= -EPSILON) && (cCROSSap >= -EPSILON)); +}; + + bool +BSP_Triangulate:: +Snip( + const vector<BSP_MVertex> &verts, + const BSP_VertexList &contour, + int u,int v, + int w,int n, + int *V +){ + int p; + MT_Scalar Ax, Ay, Bx, By, Cx, Cy, Px, Py; + + Ax = verts[contour[V[u]]].m_pos[m_xi]; + Ay = verts[contour[V[u]]].m_pos[m_yi]; + + Bx = verts[contour[V[v]]].m_pos[m_xi]; + By = verts[contour[V[v]]].m_pos[m_yi]; + + Cx = verts[contour[V[w]]].m_pos[m_xi]; + Cy = verts[contour[V[w]]].m_pos[m_yi]; + + // Snip is passes if the area of the candidate triangle is + // greater than 2*epsilon + // And if none of the remaining vertices are inside the polygon + // or within an epsilon of the boundary, + + if ( EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) ) return false; + + for (p=0;p<n;p++) + { + if( (p == u) || (p == v) || (p == w) ) continue; + Px = verts[contour[V[p]]].m_pos[m_xi]; + Py = verts[contour[V[p]]].m_pos[m_yi]; + if (InsideTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py)) return false; + } + + return true; +} + + bool +BSP_Triangulate:: +Process( + const vector<BSP_MVertex> &verts, + const BSP_VertexList &contour, + const MT_Plane3 &normal, + std::vector<int> &result +){ + + // Choose major axis of normal and assign + // 'projection' indices m_xi,m_yi; + + int maj_axis = normal.Normal().closestAxis(); + + if (maj_axis == 0) { + m_xi = 1; m_yi = 2; + } else + if (maj_axis == 1) { + m_xi = 0; m_yi = 2; + } else { + m_xi = 0; m_yi = 1; + } + + /* initialize list of Vertices in polygon */ + + int n = contour.size(); + if ( n < 3 ) return false; + + /* we want a counter-clockwise polygon in V */ + /* to true but we also nead to preserve the winding order + of polygons going into the routine. We keep track of what + we did with a little bool */ + bool is_flipped = false; + + if ( 0.0f < Area(verts,contour) ) { + for (int v=0; v<n; v++) m_V.push_back(v); + } else { + for(int v=0; v<n; v++) m_V.push_back((n-1)-v); + is_flipped = true; + } + + int nv = n; + + /* remove nv-2 Vertices, creating 1 triangle every time */ + int count = 2*nv; /* error detection */ + + for(int m=0, v=nv-1; nv>2; ) + { + /* if we loop, it is probably a non-simple polygon */ + if (0 >= (count--)) + { +#if 0 + int deb = 0; + for (deb= 0; deb < contour.size(); deb++) { + cout << verts[contour[deb]].m_pos << "\n"; + } + cout.flush(); +#endif + //** Triangulate: ERROR - probable bad polygon! + m_V.clear(); + return false; + } + + /* three consecutive vertices in current polygon, <u,v,w> */ + int u = v ; if (nv <= u) u = 0; /* previous */ + v = u+1; if (nv <= v) v = 0; /* new v */ + int w = v+1; if (nv <= w) w = 0; /* next */ + + /* Try and snip this triangle off from the + current polygon.*/ + + if ( Snip(verts,contour,u,v,w,nv,m_V.begin()) ) + { + int a,b,c,s,t; + + /* true names of the vertices */ + a = m_V[u]; b = m_V[v]; c = m_V[w]; + + /* output Triangle indices*/ + if (is_flipped) { + result.push_back( c ); + result.push_back( b ); + result.push_back( a ); + } else { + result.push_back( a ); + result.push_back( b ); + result.push_back( c ); + } + + m++; + + /* remove v from remaining polygon */ + for(s=v,t=v+1;t<nv;s++,t++) m_V[s] = m_V[t]; nv--; + + /* resest error detection counter */ + count = 2*nv; + } + } + + m_V.clear(); + return true; +} + + diff --git a/intern/bsp/intern/BSP_Triangulate.h b/intern/bsp/intern/BSP_Triangulate.h new file mode 100755 index 00000000000..bee8e9711a9 --- /dev/null +++ b/intern/bsp/intern/BSP_Triangulate.h @@ -0,0 +1,132 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef TRIANGULATE_H + + +#define TRIANGULATE_H + +/*****************************************************************/ +/** Static class to triangulate any contour/polygon efficiently **/ +/** You should replace Vector2d with whatever your own Vector **/ +/** class might be. Does not support polygons with holes. **/ +/** Uses STL vectors to represent a dynamic array of vertices. **/ +/** This code snippet was submitted to FlipCode.com by **/ +/** John W. Ratcliff (jratcliff@verant.com) on July 22, 2000 **/ +/** I did not write the original code/algorithm for this **/ +/** this triangulator, in fact, I can't even remember where I **/ +/** found it in the first place. However, I did rework it into **/ +/** the following black-box static class so you can make easy **/ +/** use of it in your own code. Simply replace Vector2d with **/ +/** whatever your own Vector implementation might be. **/ +/*****************************************************************/ + + +#include <vector> // Include STL vector class. +#include "MT_Point3.h" +#include "BSP_MeshPrimitives.h" + +class MT_Plane3; + +class BSP_Triangulate +{ +public: + + BSP_Triangulate( + ); + + // triangulate a contour/polygon, places results in STL vector + // as series of triangles. IT uses the major axis of the normal + // to turn it into a 2d problem. + + // Should chaange this to accept a point array and a list of + // indices into that point array. Result should be indices of those + // indices. + // + // MT_Point3 global_array + // vector<BSP_VertexInd> polygon + // result is vector<int> into polygon. + + bool + Process( + const std::vector<BSP_MVertex> &verts, + const BSP_VertexList &contour, + const MT_Plane3 &normal, + std::vector<int> &result + ); + + // compute area of a contour/polygon + MT_Scalar + Area( + const std::vector<BSP_MVertex> &verts, + const BSP_VertexList &contour + ); + + // decide if point Px/Py is inside triangle defined by + // (Ax,Ay) (Bx,By) (Cx,Cy) + + bool + InsideTriangle( + MT_Scalar Ax, MT_Scalar Ay, + MT_Scalar Bx, MT_Scalar By, + MT_Scalar Cx, MT_Scalar Cy, + MT_Scalar Px, MT_Scalar Py + ); + + ~BSP_Triangulate( + ); + +private: + + bool + Snip( + const std::vector<BSP_MVertex> &verts, + const BSP_VertexList &contour, + int u, + int v, + int w, + int n, + int *V + ); + + int m_xi; + int m_yi; + + // Temporary storage + + std::vector<int> m_V; + +}; + + +#endif + + diff --git a/intern/bsp/intern/CSG_BooleanOps.cpp b/intern/bsp/intern/CSG_BooleanOps.cpp new file mode 100755 index 00000000000..01b8bfc0b68 --- /dev/null +++ b/intern/bsp/intern/CSG_BooleanOps.cpp @@ -0,0 +1,255 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * Implementation of external api for CSG part of BSP lib interface. + */ + +#include "../extern/CSG_BooleanOps.h" +#include "BSP_CSGMesh_CFIterator.h" +#include "BSP_CSGMeshBuilder.h" +#include "BSP_CSGHelper.h" +#include "BSP_CSGUserData.h" +#include "MEM_RefCountPtr.h" + +struct BSP_MeshInfo { + MEM_RefCountPtr<BSP_CSGMesh> output_mesh; + CSG_MeshPropertyDescriptor obA_descriptor; + CSG_MeshPropertyDescriptor obB_descriptor; + CSG_MeshPropertyDescriptor output_descriptor; +}; + +using namespace std; + + CSG_BooleanOperation * +CSG_NewBooleanFunction( + void +){ + BSP_MeshInfo * mesh_info = new BSP_MeshInfo; + CSG_BooleanOperation * output = new CSG_BooleanOperation; + + if (mesh_info==NULL || output==NULL) return NULL; + + mesh_info->output_mesh = NULL; + output->CSG_info = mesh_info; + + return output; +} + + CSG_MeshPropertyDescriptor +CSG_DescibeOperands( + CSG_BooleanOperation * operation, + CSG_MeshPropertyDescriptor operandA_desciption, + CSG_MeshPropertyDescriptor operandB_desciption +){ + BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info); + + mesh_info->obA_descriptor = operandA_desciption; + mesh_info->obB_descriptor = operandB_desciption; + + if ( + (operandA_desciption.user_data_size == operandB_desciption.user_data_size) && + (operandA_desciption.user_face_vertex_data_size == operandB_desciption.user_face_vertex_data_size) + ) { + // Then both operands have the same sets of data we can cope with this! + mesh_info->output_descriptor.user_data_size = operandA_desciption.user_data_size; + mesh_info->output_descriptor.user_face_vertex_data_size = operandA_desciption.user_face_vertex_data_size; + } else { + // There maybe some common subset of data we can seperate out but for now we just use the + // default + mesh_info->output_descriptor.user_data_size = 0; + mesh_info->output_descriptor.user_face_vertex_data_size = 0; + } + return mesh_info->output_descriptor; +} + + int +CSG_PerformBooleanOperation( + CSG_BooleanOperation * operation, + CSG_OperationType op_type, + CSG_FaceIteratorDescriptor obAFaces, + CSG_VertexIteratorDescriptor obAVertices, + CSG_FaceIteratorDescriptor obBFaces, + CSG_VertexIteratorDescriptor obBVertices, + CSG_InterpolateUserFaceVertexDataFunc interp_func +){ + + if (operation == NULL) return 0; + BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info); + if (mesh_info == NULL) return 0; + + bool success = 0; + + obAFaces.Reset(obAFaces.it); + obBFaces.Reset(obBFaces.it); + obAVertices.Reset(obAVertices.it); + obBVertices.Reset(obBVertices.it); + + + try { + // Build the individual meshes + + MEM_SmartPtr<BSP_CSGMesh> obA = + BSP_CSGMeshBuilder::NewMesh(mesh_info->obA_descriptor,obAFaces,obAVertices); + + MEM_SmartPtr<BSP_CSGMesh> obB = + BSP_CSGMeshBuilder::NewMesh(mesh_info->obB_descriptor,obBFaces,obBVertices); + + // create an empty vertex array for the output mesh + MEM_SmartPtr<vector<BSP_MVertex> > output_verts(new vector<BSP_MVertex>); + // and some user data arrays matching the output descriptor + + MEM_SmartPtr<BSP_CSGUserData> output_f_data = new BSP_CSGUserData( + mesh_info->output_descriptor.user_data_size + ); + MEM_SmartPtr<BSP_CSGUserData> output_fv_data = new BSP_CSGUserData( + mesh_info->output_descriptor.user_face_vertex_data_size + ); + + // create the output mesh! + mesh_info->output_mesh = BSP_CSGMesh::New(); + + if ( + obA == NULL || + obB == NULL || + output_verts == NULL || + mesh_info->output_mesh == NULL || + output_f_data == NULL || + output_fv_data == NULL + ) { + return 0; + } + + mesh_info->output_mesh->SetVertices(output_verts); + mesh_info->output_mesh->SetFaceData(output_f_data); + mesh_info->output_mesh->SetFaceVertexData(output_fv_data); + + BSP_CSGHelper helper; + // translate enums! + + switch(op_type) { + case e_csg_union : + case e_csg_classify : + success = helper.ComputeOp(obA,obB,e_intern_csg_union, + mesh_info->output_mesh.Ref(),interp_func + ); + break; + case e_csg_intersection : + success = helper.ComputeOp(obA,obB,e_intern_csg_intersection, + mesh_info->output_mesh.Ref(),interp_func + ); + break; + case e_csg_difference : + success = helper.ComputeOp(obA,obB,e_intern_csg_difference, + mesh_info->output_mesh.Ref(),interp_func + ); + break; + default : + success = 0; + } + } + catch(...) { + return 0; + } + + return success; +} + + int +CSG_OutputFaceDescriptor( + CSG_BooleanOperation * operation, + CSG_FaceIteratorDescriptor * output +){ + if (operation == NULL) return 0; + BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info); + + if (mesh_info == NULL) return 0; + if (mesh_info->output_mesh == NULL) return 0; + + BSP_CSGMesh_FaceIt_Construct(mesh_info->output_mesh,output); + return 1; +} + + + int +CSG_OutputVertexDescriptor( + CSG_BooleanOperation * operation, + CSG_VertexIteratorDescriptor *output +){ + if (operation == NULL) return 0; + BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info); + + if (mesh_info == NULL) return 0; + if (mesh_info->output_mesh == NULL) return 0; + + BSP_CSGMeshVertexIt_Construct(mesh_info->output_mesh,output); + return 1; +} + + void +CSG_FreeVertexDescriptor( + CSG_VertexIteratorDescriptor * v_descriptor +){ + BSP_CSGMesh_VertexIt_Destruct(v_descriptor); +} + + + void +CSG_FreeFaceDescriptor( + CSG_FaceIteratorDescriptor * f_descriptor +){ + BSP_CSGMesh_FaceIt_Destruct(f_descriptor); +} + + + void +CSG_FreeBooleanOperation( + CSG_BooleanOperation *operation +){ + if (operation != NULL) { + BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info); + delete(mesh_info); + delete(operation); + } +} + + + + + + + + + + + + diff --git a/intern/bsp/intern/Makefile b/intern/bsp/intern/Makefile new file mode 100644 index 00000000000..a5e8565a6ff --- /dev/null +++ b/intern/bsp/intern/Makefile @@ -0,0 +1,48 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# string intern Makefile +# + +LIBNAME = bsp +DIR = $(OCGDIR)/intern/$(LIBNAME) +DIRS = common + +include nan_compile.mk + +CCFLAGS += $(LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I../extern +CPPFLAGS += -I$(NAN_MOTO)/include +CPPFLAGS += -I$(NAN_MEMUTIL)/include +CPPFLAGS += -I$(NAN_CONTAINER)/include +CPPFLAGS += -Icommon + + diff --git a/intern/bsp/make/msvc6_0/bsplib.dsp b/intern/bsp/make/msvc6_0/bsplib.dsp new file mode 100644 index 00000000000..8e161dcd30e --- /dev/null +++ b/intern/bsp/make/msvc6_0/bsplib.dsp @@ -0,0 +1,211 @@ +# Microsoft Developer Studio Project File - Name="bsplib" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=bsplib - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "bsplib.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "bsplib.mak" CFG="bsplib - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "bsplib - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "bsplib - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "bsplib - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "../../../../lib/windows/memutil/include" /I "../.." /I "../../../../lib/windows/moto/include" /I "../../../../lib/windows/container/include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x413 /d "NDEBUG" +# ADD RSC /l 0x413 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Release\libbsp.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=ECHO Copying header files COPY "..\..\extern\*.h" "..\..\..\..\lib\windows\bsp\include\" ECHO Copying lib COPY "Release\libbsp.lib" "..\..\..\..\lib\windows\bsp\lib\libbsp.a" ECHO Done +# End Special Build Tool + +!ELSEIF "$(CFG)" == "bsplib - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../../../lib/windows/memutil" /I "../.." /I "../../../../lib/windows/moto/include" /I "../../../../lib/windows/container/include" /I "../../../../lib/windows/memutil/include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x413 /d "_DEBUG" +# ADD RSC /l 0x413 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\libbsp.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=ECHO Copying header files COPY "..\..\extern\*.h" "..\..\..\..\lib\windows\bsp\include\" ECHO Copying lib COPY "Debug\libbsp.lib" "..\..\..\..\lib\windows\bsp\lib\debug\libbsp.a" ECHO Copying Debug info. COPY "Debug\vc60.*" "..\..\..\..\lib\windows\bsp\lib\debug\" ECHO Done +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "bsplib - Win32 Release" +# Name "bsplib - Win32 Debug" +# Begin Group "intern" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\intern\BSP_CSGException.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_CSGHelper.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_CSGHelper.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_CSGISplitter.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_CSGMesh.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_CSGMesh.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_CSGMesh_CFIterator.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_CSGMeshBuilder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_CSGMeshBuilder.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_CSGMeshSplitter.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_CSGMeshSplitter.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_CSGNCMeshSplitter.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_CSGNCMeshSplitter.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_CSGUserData.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_CSGUserData.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_FragNode.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_FragNode.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_FragTree.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_FragTree.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_MeshFragment.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_MeshFragment.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_MeshPrimitives.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_MeshPrimitives.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_Triangulate.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\BSP_Triangulate.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\CSG_BooleanOps.cpp +# End Source File +# End Group +# Begin Group "extern" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\extern\CSG_BooleanOps.h +# End Source File +# End Group +# End Target +# End Project diff --git a/intern/bsp/make/msvc6_0/bsplib.dsw b/intern/bsp/make/msvc6_0/bsplib.dsw new file mode 100644 index 00000000000..1827dc3746e --- /dev/null +++ b/intern/bsp/make/msvc6_0/bsplib.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "bsplib"=.\bsplib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/intern/bsp/test/BSP_GhostTest/BSP_GhostTest.dsp b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest.dsp new file mode 100755 index 00000000000..1e913289824 --- /dev/null +++ b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest.dsp @@ -0,0 +1,130 @@ +# Microsoft Developer Studio Project File - Name="BSP_GhostTest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=BSP_GhostTest - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "BSP_GhostTest.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "BSP_GhostTest.mak" CFG="BSP_GhostTest - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "BSP_GhostTest - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "BSP_GhostTest - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "BSP_GhostTest - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /G6 /MT /W3 /GX /O2 /Ob2 /I "../../extern/" /I "../../../../lib/windows/string/include" /I "../../../../lib/windows/ghost/include" /I "../../../../lib/windows/moto/include" /I "../../../../lib/windows/memutil/include" /I "../../../../lib/windows/container/include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x413 /d "NDEBUG" +# ADD RSC /l 0x413 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\..\lib\windows\glut-3.7\lib\\" + +!ELSEIF "$(CFG)" == "BSP_GhostTest - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../extern/" /I "../../../../lib/windows/string/include" /I "../../../../lib/windows/ghost/include" /I "../../../../lib/windows/moto/include" /I "../../../../lib/windows/memutil/include" /I "../../../../lib/windows/container/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x413 /d "_DEBUG" +# ADD RSC /l 0x413 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\lib\windows\glut-3.7\lib\\" + +!ENDIF + +# Begin Target + +# Name "BSP_GhostTest - Win32 Release" +# Name "BSP_GhostTest - Win32 Debug" +# Begin Source File + +SOURCE=.\BSP_GhostTest3D.cpp +# End Source File +# Begin Source File + +SOURCE=.\BSP_GhostTest3D.h +# End Source File +# Begin Source File + +SOURCE=.\BSP_MeshDrawer.cpp +# End Source File +# Begin Source File + +SOURCE=.\BSP_MeshDrawer.h +# End Source File +# Begin Source File + +SOURCE=.\BSP_PlyLoader.cpp +# End Source File +# Begin Source File + +SOURCE=.\BSP_PlyLoader.h +# End Source File +# Begin Source File + +SOURCE=.\BSP_TMesh.cpp +# End Source File +# Begin Source File + +SOURCE=.\BSP_TMesh.h +# End Source File +# Begin Source File + +SOURCE=.\main.cpp +# End Source File +# Begin Source File + +SOURCE=.\ply.h +# End Source File +# Begin Source File + +SOURCE=.\plyfile.c +# End Source File +# End Target +# End Project diff --git a/intern/bsp/test/BSP_GhostTest/BSP_GhostTest.dsw b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest.dsw new file mode 100755 index 00000000000..802fba84bef --- /dev/null +++ b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest.dsw @@ -0,0 +1,125 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "BSP_GhostTest"=.\BSP_GhostTest.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name bsplib + End Project Dependency + Begin Project Dependency + Project_Dep_Name ghost + End Project Dependency + Begin Project Dependency + Project_Dep_Name string + End Project Dependency + Begin Project Dependency + Project_Dep_Name MoTo + End Project Dependency +}}} + +############################################################################### + +Project: "MoTo"=..\..\..\moto\make\msvc_6_0\MoTo.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "bsplib"=..\..\make\msvc6_0\bsplib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name container + End Project Dependency + Begin Project Dependency + Project_Dep_Name memutil + End Project Dependency + Begin Project Dependency + Project_Dep_Name MoTo + End Project Dependency +}}} + +############################################################################### + +Project: "container"=..\..\..\container\make\msvc_6_0\container.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name memutil + End Project Dependency +}}} + +############################################################################### + +Project: "ghost"=..\..\..\ghost\make\msvc\ghost.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "memutil"=..\..\..\memutil\make\msvc_60\memutil.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "string"=..\..\..\string\make\msvc_6_0\string.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.cpp b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.cpp new file mode 100755 index 00000000000..92e5198f139 --- /dev/null +++ b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.cpp @@ -0,0 +1,656 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + +* $Id$ +* Copyright (C) 2001 NaN Technologies B.V. +*/ + +#if defined(WIN32) || defined(__APPLE__) +# ifdef WIN32 +# include <windows.h> +# include <GL/gl.h> +# include <GL/glu.h> +# else // WIN32 +# include <AGL/gl.h> +# endif // WIN32 +#else // defined(WIN32) || defined(__APPLE__) +# include <GL/gl.h> +# include <GL/glu.h> +#endif // defined(WIN32) || defined(__APPLE__) + + +#include "BSP_GhostTest3D.h" +#include "BSP_MeshDrawer.h" + +#include "GHOST_ISystem.h" +#include "GHOST_IWindow.h" + +#include "MT_Quaternion.h" +#include "MT_Transform.h" +#include "CSG_BooleanOps.h" + +#include <iostream> + + +using namespace std; + + +BSP_GhostTestApp3D:: +BSP_GhostTestApp3D( +) : + m_window(NULL), + m_system(NULL), + m_finish_me_off(false), + m_current_object(0) +{ + //nothing to do; +} + + void +BSP_GhostTestApp3D:: +SetMesh( + MEM_SmartPtr<BSP_TMesh> mesh +){ + m_meshes.push_back(mesh); + + BSP_RotationSetting rotation_setting; + BSP_TranslationSetting translation_setting; + + rotation_setting.m_angle_x = MT_Scalar(0); + rotation_setting.m_angle_y = MT_Scalar(0); + rotation_setting.m_moving = false; + rotation_setting.x_old = 0; + rotation_setting.y_old = 0; + + translation_setting.m_t_x = MT_Scalar(0); + translation_setting.m_t_y = MT_Scalar(0); + translation_setting.m_t_z = MT_Scalar(0); + translation_setting.m_moving = false; + translation_setting.x_old = 0; + translation_setting.y_old = 0; + + m_rotation_settings.push_back(rotation_setting); + m_translation_settings.push_back(translation_setting); + m_render_modes.push_back(e_wireframe_shaded); + m_scale_settings.push_back(MT_Scalar(1)); + +} + + void +BSP_GhostTestApp3D:: +Swap( + int i +){ + + if (!m_rotation_settings[i].m_moving && !m_translation_settings[i].m_moving) { + swap(m_meshes[i],m_meshes.back()); + swap(m_rotation_settings[i],m_rotation_settings.back()); + swap(m_translation_settings[i],m_translation_settings.back()); + swap(m_scale_settings[i],m_scale_settings.back()); + swap(m_render_modes[i],m_render_modes.back()); + } +} + + + + + + + MT_Transform +BSP_GhostTestApp3D:: +GetTransform( + int i +){ + + MT_Quaternion q_ax(MT_Vector3(0,1,0),m_rotation_settings[i].m_angle_x); + MT_Quaternion q_ay(MT_Vector3(1,0,0),m_rotation_settings[i].m_angle_y); + + MT_Point3 tr( + m_translation_settings[i].m_t_x, + m_translation_settings[i].m_t_y, + m_translation_settings[i].m_t_z + ); + + + MT_Matrix3x3 rotx(q_ax); + MT_Matrix3x3 roty(q_ay); + + MT_Matrix3x3 rot = rotx * roty; + + MT_Transform trans(tr,rot); + + MT_Transform scalet; + scalet.setIdentity(); + scalet.scale(m_scale_settings[i],m_scale_settings[i],m_scale_settings[i]); + + return trans * scalet; +} + + void +BSP_GhostTestApp3D:: +Operate( + int type +){ + + CSG_VertexIteratorDescriptor * vA = VertexIt_Construct(m_meshes[0],GetTransform(0)); + CSG_FaceIteratorDescriptor * fA = FaceIt_Construct(m_meshes[0]); + + CSG_VertexIteratorDescriptor * vB = VertexIt_Construct(m_meshes[1],GetTransform(1)); + CSG_FaceIteratorDescriptor * fB = FaceIt_Construct(m_meshes[1]); + + // describe properties. + + CSG_MeshPropertyDescriptor props; + props.mesh_property_flags = 0; + props.user_data_size = 0; + + CSG_BooleanOperation * op = CSG_NewBooleanFunction(); + props = CSG_DescibeOperands(op,props,props); + + CSG_PerformBooleanOperation(op,CSG_OperationType(type), + *fA,*vA,*fB,*vB + ); + + CSG_FaceIteratorDescriptor * out_f = CSG_OutputFaceDescriptor(op); + CSG_VertexIteratorDescriptor * out_v = CSG_OutputVertexDescriptor(op); + + MEM_SmartPtr<BSP_TMesh> new_mesh (BuildMesh(props,*out_f,*out_v)); + + // free stuff + + CSG_FreeVertexDescriptor(out_v); + CSG_FreeFaceDescriptor(out_f); + CSG_FreeBooleanOperation(op); + + op = NULL; + SetMesh(new_mesh); +} + + + void +BSP_GhostTestApp3D:: +UpdateFrame( +){ +if (m_window) { + + GHOST_Rect v_rect; + m_window->getClientBounds(v_rect); + + glViewport(0,0,v_rect.getWidth(),v_rect.getHeight()); + +} +} + + +MT_Vector3 +BSP_GhostTestApp3D:: +UnProject( + const MT_Vector3 & vec +) { + + GLint viewport[4]; + GLdouble mvmatrix[16],projmatrix[16]; + + glGetIntegerv(GL_VIEWPORT,viewport); + glGetDoublev(GL_MODELVIEW_MATRIX,mvmatrix); + glGetDoublev(GL_PROJECTION_MATRIX,projmatrix); + + GLdouble realy = viewport[3] - vec.y() - 1; + GLdouble outx,outy,outz; + + gluUnProject(vec.x(),realy,vec.z(),mvmatrix,projmatrix,viewport,&outx,&outy,&outz); + + return MT_Vector3(outx,outy,outz); +} + + + bool +BSP_GhostTestApp3D:: +InitApp( +){ + + // create a system and window with opengl + // rendering context. + + GHOST_TSuccess success = GHOST_ISystem::createSystem(); + if (success == GHOST_kFailure) return false; + + m_system = GHOST_ISystem::getSystem(); + if (m_system == NULL) return false; + + m_system->addEventConsumer(this); + + m_window = m_system->createWindow( + "GHOST crud3D!", + 100,100,640,480,GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL + ); + + if ( + m_window == NULL + ) { + m_system = NULL; + GHOST_ISystem::disposeSystem(); + return false; + } + + // make an opengl frustum for this wind + + MT_Vector3 min,max; + + min = m_meshes[0]->m_min; + max = m_meshes[0]->m_max; + InitOpenGl(min,max); + + return true; +} + + void +BSP_GhostTestApp3D:: +Run( +){ + if (m_system == NULL) { + return; + } + + while (!m_finish_me_off) { + m_system->processEvents(true); + m_system->dispatchEvents(); + }; +} + + bool +BSP_GhostTestApp3D:: +processEvent( + GHOST_IEvent* event +){ + + bool handled = false; + + switch(event->getType()) { + case GHOST_kEventWindowSize: + case GHOST_kEventWindowActivate: + UpdateFrame(); + case GHOST_kEventWindowUpdate: + DrawPolies(); + handled = true; + break; + case GHOST_kEventButtonDown: + { + int x,y; + m_system->getCursorPosition(x,y); + + int wx,wy; + m_window->screenToClient(x,y,wx,wy); + + GHOST_TButtonMask button = + static_cast<GHOST_TEventButtonData *>(event->getData())->button; + + if (button == GHOST_kButtonMaskLeft) { + m_rotation_settings[m_current_object].m_moving = true; + m_rotation_settings[m_current_object].x_old = x; + m_rotation_settings[m_current_object].y_old = y; + } else + if (button == GHOST_kButtonMaskRight) { + m_translation_settings[m_current_object].m_moving = true; + m_translation_settings[m_current_object].x_old = x; + m_translation_settings[m_current_object].y_old = y; + } else + + m_window->invalidate(); + handled = true; + break; + + } + + case GHOST_kEventButtonUp: + { + + GHOST_TButtonMask button = + static_cast<GHOST_TEventButtonData *>(event->getData())->button; + + if (button == GHOST_kButtonMaskLeft) { + m_rotation_settings[m_current_object].m_moving = false; + m_rotation_settings[m_current_object].x_old = 0; + m_rotation_settings[m_current_object].y_old = 0; + } else + if (button == GHOST_kButtonMaskRight) { + m_translation_settings[m_current_object].m_moving = false; + m_translation_settings[m_current_object].x_old; + m_translation_settings[m_current_object].y_old; + + } + m_window->invalidate(); + handled = true; + break; + + } + + case GHOST_kEventCursorMove: + { + int x,y; + m_system->getCursorPosition(x,y); + int wx,wy; + m_window->screenToClient(x,y,wx,wy); + + if (m_rotation_settings[m_current_object].m_moving) { + m_rotation_settings[m_current_object].m_angle_x = MT_Scalar(wx)/20; + m_rotation_settings[m_current_object].x_old = wx; + m_rotation_settings[m_current_object].m_angle_y = MT_Scalar(wy)/20; + m_rotation_settings[m_current_object].y_old = wy; + + m_window->invalidate(); + } + if (m_translation_settings[m_current_object].m_moving) { + + // project current objects bounding box centre into screen space. + // unproject mouse point into object space using z-value from + // projected bounding box centre. + + GHOST_Rect bounds; + m_window->getClientBounds(bounds); + + int w_h = bounds.getWidth(); + + y = w_h - wy; + + double mvmatrix[16]; + double projmatrix[16]; + GLint viewport[4]; + + double px, py, pz,sz; + + /* Get the matrices needed for gluUnProject */ + glGetIntegerv(GL_VIEWPORT, viewport); + glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix); + glGetDoublev(GL_PROJECTION_MATRIX, projmatrix); + + // work out the position of the end effector in screen space + + GLdouble ex,ey,ez; + + MT_Vector3 bbox_min, bbox_max; + + bbox_min = m_meshes[0]->m_min; + bbox_max = m_meshes[0]->m_max; + + MT_Vector3 bbox_centre = (bbox_min + bbox_max)/2; + + ex = bbox_centre.x(); + ey = bbox_centre.y(); + ez = bbox_centre.z(); + + gluProject(ex, ey, ez, mvmatrix, projmatrix, viewport, &px, &py, &sz); + gluUnProject((GLdouble) x, (GLdouble) y, sz, mvmatrix, projmatrix, viewport, &px, &py, &pz); + + m_translation_settings[m_current_object].m_t_x = px; + m_translation_settings[m_current_object].m_t_y = py; + m_translation_settings[m_current_object].m_t_z = pz; + m_window->invalidate(); + + } + + handled = true; + break; + } + + case GHOST_kEventKeyDown : + { + GHOST_TEventKeyData *kd = + static_cast<GHOST_TEventKeyData *>(event->getData()); + + + switch(kd->key) { + case GHOST_kKeyI: + { + // now intersect meshes. + Operate(e_csg_intersection); + handled = true; + m_window->invalidate(); + break; + } + case GHOST_kKeyU: + { + Operate(e_csg_union); + handled = true; + m_window->invalidate(); + break; + } + case GHOST_kKeyD: + { + Operate(e_csg_difference); + handled = true; + m_window->invalidate(); + break; + } + + case GHOST_kKeyA: + { + + m_scale_settings[m_current_object] *= 1.1; + handled = true; + m_window->invalidate(); + break; + } + case GHOST_kKeyZ: + { + m_scale_settings[m_current_object] *= 0.8; + + handled = true; + m_window->invalidate(); + break; + } + + case GHOST_kKeyR: + + m_render_modes[m_current_object]++; + + if (m_render_modes[m_current_object] > e_last_render_mode) { + m_render_modes[m_current_object] = e_first_render_mode; + } + + handled = true; + m_window->invalidate(); + break; + + + + case GHOST_kKeyB: + handled = true; + m_window->invalidate(); + break; + + case GHOST_kKeyQ: + m_finish_me_off = true; + handled = true; + break; + + case GHOST_kKeyS: + Swap(m_current_object); + m_window->invalidate(); + handled = true; + break; + + case GHOST_kKeySpace: + + // increment the current object only if the object is not being + // manipulated. + if (! (m_rotation_settings[m_current_object].m_moving || m_translation_settings[m_current_object].m_moving)) { + m_current_object ++; + if (m_current_object >= m_meshes.size()) { + m_current_object = 0; + } + } + m_window->invalidate(); + + + handled = true; + break; + default : + break; + } + } + + default : + break; + } + + return handled; + +}; + +BSP_GhostTestApp3D:: +~BSP_GhostTestApp3D( +){ + + if (m_window) { + m_system->disposeWindow(m_window); + m_window = NULL; + GHOST_ISystem::disposeSystem(); + m_system = NULL; + } +}; + + void +BSP_GhostTestApp3D:: +DrawPolies( +){ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + for (int i = 0; i < m_meshes.size(); ++i) { + + MT_Transform trans = GetTransform(i); + + float opengl_mat[16]; + trans.getValue(opengl_mat); + + opengl_mat[14] -= 30; + + glPushMatrix(); + glLoadMatrixf(opengl_mat); + + MT_Vector3 color(1.0,1.0,1.0); + + if (i == m_current_object) { + color = MT_Vector3(1.0,0,0); + } + + BSP_MeshDrawer::DrawMesh(m_meshes[i].Ref(),m_render_modes[i]); + + glPopMatrix(); + } + + m_window->swapBuffers(); +} + + void +BSP_GhostTestApp3D:: +InitOpenGl( + const MT_Vector3 &min, + const MT_Vector3 &max +){ + + GLfloat light_diffuse0[] = {1.0, 0.0, 0.0, 0.5}; /* Red diffuse light. */ + GLfloat light_position0[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */ + + GLfloat light_diffuse1[] = {1.0, 1.0, 1.0, 0.5}; /* Red diffuse light. */ + GLfloat light_position1[] = {1.0, 0, 0, 0.0}; /* Infinite light location. */ + + /* Enable a single OpenGL light. */ + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse0); + glLightfv(GL_LIGHT0, GL_POSITION, light_position0); + + glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse1); + glLightfv(GL_LIGHT1, GL_POSITION, light_position1); + + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_LIGHTING); + + // make sure there is no back face culling. +// glDisable(GL_CULL_FACE); + + + // use two sided lighting model + + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE); + + /* Use depth buffering for hidden surface elimination. */ + glEnable(GL_DEPTH_TEST); + + /* Setup the view of the cube. */ + glMatrixMode(GL_PROJECTION); + + // centre of the box + 3* depth of box + + MT_Vector3 centre = (min + max) * 0.5; + MT_Vector3 diag = max - min; + + float depth = diag.length(); + float distance = 5; + + gluPerspective( + /* field of view in degree */ 40.0, + /* aspect ratio */ 1.0, + /* Z near */ 1.0, + /* Z far */ distance * depth * 2 + ); + glMatrixMode(GL_MODELVIEW); + + gluLookAt( + centre.x(), centre.y(), centre.z() + distance*depth, //eye + centre.x(), centre.y(), centre.z(), //centre + 0.0, 1.0, 0.); /* up is in positive Y direction */ + +} + + + + + + + + + + + + + + + + + + + + + diff --git a/intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.h b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.h new file mode 100755 index 00000000000..086ee42b903 --- /dev/null +++ b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.h @@ -0,0 +1,165 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BSP_GhostTest_h + +#define BSP_GhostTest_h + + + +#include "GHOST_IEventConsumer.h" +#include "MT_Vector3.h" +#include "BSP_TMesh.h" +#include "BSP_MeshDrawer.h" + +#include <vector> + +class GHOST_IWindow; +class GHOST_ISystem; + + +class BSP_GhostTestApp3D : +public GHOST_IEventConsumer +{ +public : + // Construct an instance of the application; + + BSP_GhostTestApp3D( + ); + + // initialize the applicaton + + bool + InitApp( + ); + + // Run the application untill internal return. + void + Run( + ); + + ~BSP_GhostTestApp3D( + ); + + void + SetMesh( + MEM_SmartPtr<BSP_TMesh> mesh + ); + +private : + + struct BSP_RotationSetting { + MT_Scalar m_angle_x; + MT_Scalar m_angle_y; + int x_old; + int y_old; + bool m_moving; + }; + + struct BSP_TranslationSetting { + MT_Scalar m_t_x; + MT_Scalar m_t_y; + MT_Scalar m_t_z; + int x_old; + int y_old; + bool m_moving; + }; + + // Return the transform of object i + + MT_Transform + GetTransform( + int active_object + ); + + // Perform an operation between the first two objects in the + // list + + void + Operate( + int type + ); + + // Swap mesh i and settings with the last mesh in list. + + void + Swap( + int i + ); + + void + DrawPolies( + ); + + void + UpdateFrame( + ); + + MT_Vector3 + UnProject( + const MT_Vector3 & vec + ); + + // Create a frustum and projection matrix to + // look at the bounding box + + void + InitOpenGl( + const MT_Vector3 &min, + const MT_Vector3 &max + ); + + + // inherited from GHOST_IEventConsumer + bool + processEvent( + GHOST_IEvent* event + ); + + GHOST_IWindow *m_window; + GHOST_ISystem *m_system; + + bool m_finish_me_off; + + // List of current meshes. + std::vector< MEM_SmartPtr<BSP_TMesh> > m_meshes; + + std::vector< BSP_RotationSetting> m_rotation_settings; + std::vector< BSP_TranslationSetting> m_translation_settings; + std::vector< MT_Scalar> m_scale_settings; + std::vector< int> m_render_modes; + + int m_current_object; + + +}; + +#endif
\ No newline at end of file diff --git a/intern/bsp/test/BSP_GhostTest/BSP_MeshDrawer.cpp b/intern/bsp/test/BSP_GhostTest/BSP_MeshDrawer.cpp new file mode 100755 index 00000000000..9df6d166263 --- /dev/null +++ b/intern/bsp/test/BSP_GhostTest/BSP_MeshDrawer.cpp @@ -0,0 +1,160 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BSP_MeshDrawer.h" + +#include "BSP_TMesh.h" + +#if defined(WIN32) || defined(__APPLE__) +# ifdef WIN32 +# include <windows.h> +# include <GL/gl.h> +# include <GL/glu.h> +# else // WIN32 +# include <AGL/gl.h> +# endif // WIN32 +#else // defined(WIN32) || defined(__APPLE__) +# include <GL/gl.h> +# include <GL/glu.h> +#endif // defined(WIN32) || defined(__APPLE__) + +#include <vector> + +using namespace std; + + void +BSP_MeshDrawer:: +DrawMesh( + BSP_TMesh &mesh, + int render_mode +){ + + + if (render_mode == e_none) return; + + // decompose polygons into triangles. + + glEnable(GL_LIGHTING); + + + if (render_mode == e_wireframe || render_mode == e_wireframe_shaded) { + + glColor3f(0.0, 0.0, 0.0); + + if (render_mode == e_wireframe) { + glDisable(GL_LIGHTING); + } else { + glEnable(GL_LIGHTING); + } + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0,1.0); + + glBegin(GL_TRIANGLES); + DrawPolies(mesh); + glEnd(); + + glColor3f(1.0, 1.0, 1.0); + glDisable(GL_LIGHTING); + glDisable(GL_POLYGON_OFFSET_FILL); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + glBegin(GL_TRIANGLES); + DrawPolies(mesh); + glEnd(); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } else { + + glEnable(GL_LIGHTING); + + glBegin(GL_TRIANGLES); + DrawPolies(mesh); + glEnd(); + } + + +} + + + void +BSP_MeshDrawer:: +DrawPolies( + BSP_TMesh &mesh +){ + + const vector<BSP_TVertex> & verts = mesh.VertexSet(); + const vector<BSP_TFace> &faces = mesh.FaceSet(); + + // just draw the edges for now. + + vector<BSP_TVertex>::const_iterator vertex_it = verts.begin(); + + + vector<BSP_TFace>::const_iterator faces_it = faces.begin(); + vector<BSP_TFace>::const_iterator faces_end = faces.end(); + + for (;faces_it != faces_end; ++faces_it ){ + + glNormal3f( + faces_it->m_normal.x(), + faces_it->m_normal.y(), + faces_it->m_normal.z() + ); + + glVertex3f( + verts[faces_it->m_verts[0]].m_pos.x(), + verts[faces_it->m_verts[0]].m_pos.y(), + verts[faces_it->m_verts[0]].m_pos.z() + ); + glVertex3f( + verts[faces_it->m_verts[1]].m_pos.x(), + verts[faces_it->m_verts[1]].m_pos.y(), + verts[faces_it->m_verts[1]].m_pos.z() + ); + glVertex3f( + verts[faces_it->m_verts[2]].m_pos.x(), + verts[faces_it->m_verts[2]].m_pos.y(), + verts[faces_it->m_verts[2]].m_pos.z() + ); + } +} + + + + + + + + + + diff --git a/intern/bsp/test/BSP_GhostTest/BSP_MeshDrawer.h b/intern/bsp/test/BSP_GhostTest/BSP_MeshDrawer.h new file mode 100755 index 00000000000..427c6a34f4d --- /dev/null +++ b/intern/bsp/test/BSP_GhostTest/BSP_MeshDrawer.h @@ -0,0 +1,77 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BSP_MeshDrawer_h + +#define BSP_MeshDrawer_h + + + +class BSP_TMesh; +class MT_Vector3; + +enum BSP_TRenderMode { + e_shaded, + e_none, + e_wireframe, + e_wireframe_shaded, + e_first_render_mode = e_shaded, + e_last_render_mode = e_wireframe_shaded +}; + +class BSP_MeshDrawer +{ +public : + static + void + DrawMesh( + BSP_TMesh &mesh, + int render_mode + ); + +private : + + static + void + DrawPolies( + BSP_TMesh &mesh + ); + + + BSP_MeshDrawer( + ); + + ~BSP_MeshDrawer( + ); + +}; + +#endif
\ No newline at end of file diff --git a/intern/bsp/test/BSP_GhostTest/BSP_PlyLoader.cpp b/intern/bsp/test/BSP_GhostTest/BSP_PlyLoader.cpp new file mode 100755 index 00000000000..aa7dfbc3818 --- /dev/null +++ b/intern/bsp/test/BSP_GhostTest/BSP_PlyLoader.cpp @@ -0,0 +1,196 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BSP_PlyLoader.h" + +#include "MT_Vector3.h" +#include "ply.h" + +struct LoadVertex { + float x,y,z; /* the usual 3-space position of a vertex */ +}; + +struct LoadFace { + unsigned char intensity; /* this user attaches intensity to faces */ + unsigned char nverts; /* number of vertex indices in list */ + int *verts; /* vertex index list */ +}; + + + MEM_SmartPtr<BSP_TMesh> +BSP_PlyLoader:: +NewMeshFromFile( + char * file_name, + MT_Vector3 &min, + MT_Vector3 &max + +) { + + min = MT_Vector3(MT_INFINITY,MT_INFINITY,MT_INFINITY); + max = MT_Vector3(-MT_INFINITY,-MT_INFINITY,-MT_INFINITY); + + PlyProperty vert_props[] = { /* list of property information for a vertex */ + {"x", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,x), 0, 0, 0, 0}, + {"y", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,y), 0, 0, 0, 0}, + {"z", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,z), 0, 0, 0, 0}, + }; + + PlyProperty face_props[] = { /* list of property information for a vertex */ + {"vertex_indices", PLY_INT, PLY_INT, offsetof(LoadFace,verts), + 1, PLY_UCHAR, PLY_UCHAR, offsetof(LoadFace,nverts)}, + }; + + MEM_SmartPtr<BSP_TMesh> mesh = new BSP_TMesh; + + if (mesh == NULL) return NULL; + + int i,j; + PlyFile *ply; + int nelems; + char **elist; + int file_type; + float version; + int nprops; + int num_elems; + PlyProperty **plist; + + char *elem_name; + + LoadVertex load_vertex; + LoadFace load_face; + + /* open a PLY file for reading */ + ply = ply_open_for_reading( + file_name, + &nelems, + &elist, + &file_type, + &version + ); + + if (ply == NULL) return NULL; + + /* go through each kind of element that we learned is in the file */ + /* and read them */ + + for (i = 0; i < nelems; i++) { + + /* get the description of the first element */ + + elem_name = elist[i]; + plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops); + + /* print the name of the element, for debugging */ + + /* if we're on vertex elements, read them in */ + + if (equal_strings ("vertex", elem_name)) { + + /* set up for getting vertex elements */ + + ply_get_property (ply, elem_name, &vert_props[0]); + ply_get_property (ply, elem_name, &vert_props[1]); + ply_get_property (ply, elem_name, &vert_props[2]); + + // make some memory for the vertices + mesh->VertexSet().reserve(num_elems); + + /* grab all the vertex elements */ + for (j = 0; j < num_elems; j++) { + + /* grab and element from the file */ + ply_get_element (ply, (void *)&load_vertex); + // pass the vertex into the mesh builder. + + if (load_vertex.x < min.x()) { + min.x() = load_vertex.x; + } else + if (load_vertex.x > max.x()) { + max.x()= load_vertex.x; + } + + if (load_vertex.y < min.y()) { + min.y() = load_vertex.y; + } else + if (load_vertex.y > max.y()) { + max.y()= load_vertex.y; + } + + if (load_vertex.z < min.z()) { + min.z() = load_vertex.z; + } else + if (load_vertex.z > max.z()) { + max.z()= load_vertex.z; + } + + BSP_TVertex my_vert; + my_vert.m_pos = MT_Vector3(load_vertex.x,load_vertex.y,load_vertex.z); + mesh->VertexSet().push_back(my_vert); + } + + + } + + /* if we're on face elements, read them in */ + if (equal_strings ("face", elem_name)) { + + /* set up for getting face elements */ + + ply_get_property (ply, elem_name, &face_props[0]); + + /* grab all the face elements */ + for (j = 0; j < num_elems; j++) { + + ply_get_element (ply, (void *)&load_face); + + int v; + for (v = 2; v< load_face.nverts; v++) { + + BSP_TFace f; + + f.m_verts[0] = load_face.verts[0]; + f.m_verts[1] = load_face.verts[v-1]; + f.m_verts[2] = load_face.verts[v]; + + mesh->BuildNormal(f); + mesh->FaceSet().push_back(f); + } + // free up the memory this pile of shit used to allocate the polygon's vertices + free (load_face.verts); + } + + } + } + /* close the PLY file */ + ply_close (ply); + + return mesh; +}
\ No newline at end of file diff --git a/intern/bsp/test/BSP_GhostTest/BSP_PlyLoader.h b/intern/bsp/test/BSP_GhostTest/BSP_PlyLoader.h new file mode 100755 index 00000000000..5f7a793267e --- /dev/null +++ b/intern/bsp/test/BSP_GhostTest/BSP_PlyLoader.h @@ -0,0 +1,64 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BSP_PlyLoader_h + +#define BSP_PlyLoader_h + +#include "MEM_SmartPtr.h" +#include "BSP_TMesh.h" + +class BSP_PlyLoader { +public : + + static + MEM_SmartPtr<BSP_TMesh> + NewMeshFromFile( + char * file_name, + MT_Vector3 &min, + MT_Vector3 &max + ); + + +private : + + // unimplemented - not for instantiation. + + BSP_PlyLoader( + ); + + ~BSP_PlyLoader( + ); +}; + + + +#endif
\ No newline at end of file diff --git a/intern/bsp/test/BSP_GhostTest/BSP_TMesh.h b/intern/bsp/test/BSP_GhostTest/BSP_TMesh.h new file mode 100755 index 00000000000..d2429cd3330 --- /dev/null +++ b/intern/bsp/test/BSP_GhostTest/BSP_TMesh.h @@ -0,0 +1,354 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BSP_TMesh_h + +#define BSP_TMesh_h + +#include "MT_Point3.h" +#include "MT_Vector3.h" +#include "MT_Transform.h" + +#include "MEM_SmartPtr.h" + +#include <vector> + +#include "CSG_BooleanOps.h" + +/** + * A very basic test mesh. + */ + +struct BSP_TVertex { + MT_Point3 m_pos; +}; + +struct BSP_TFace { + int m_verts[3]; + MT_Vector3 m_normal; +}; + + +class BSP_TMesh { +public : + + std::vector<BSP_TVertex> m_verts; + std::vector<BSP_TFace> m_faces; + + MT_Vector3 m_min,m_max; + + std::vector<BSP_TVertex> & + VertexSet( + ){ + return m_verts; + } + + std::vector<BSP_TFace> & + FaceSet( + ) { + return m_faces; + } + + void + AddFace( + int *verts, + int num_verts + ); + + void + BuildNormal( + BSP_TFace & f + ) const ; + +}; + + + +/** + * some iterator functions to describe the mesh to the BSP module. + */ + +/** + * This class defines 2 C style iterators over a CSG mesh, one for + * vertices and 1 for faces. They conform to the iterator interface + * defined in CSG_BooleanOps.h + */ + +struct VertexIt { + BSP_TMesh * mesh; + BSP_TVertex * pos; + MT_Transform trans; +}; + + +static + void +VertexIt_Destruct( + CSG_VertexIteratorDescriptor * iterator +) { + delete ((VertexIt *)(iterator->it)); + iterator->it = NULL; + delete(iterator); +}; + + +static + int +VertexIt_Done( + CSG_IteratorPtr it +) { + // assume CSG_IteratorPtr is of the correct type. + VertexIt * vertex_it = (VertexIt *)it; + + if (vertex_it->pos < vertex_it->mesh->VertexSet().end()) return 0; + return 1; +}; + +static + void +VertexIt_Fill( + CSG_IteratorPtr it, + CSG_IVertex *vert +) { + // assume CSG_IteratorPtr is of the correct type. + VertexIt * vertex_it = (VertexIt *)it; + + MT_Point3 p = vertex_it->pos->m_pos; + p = vertex_it->trans * p; + + p.getValue(vert->position); +}; + +static + void +VertexIt_Step( + CSG_IteratorPtr it +) { + // assume CSG_IteratorPtr is of the correct type. + VertexIt * vertex_it = (VertexIt *)it; + + ++(vertex_it->pos); +}; + +static + CSG_VertexIteratorDescriptor * +VertexIt_Construct( + BSP_TMesh *mesh, + MT_Transform trans +){ + // user should have insured mesh is not equal to NULL. + + CSG_VertexIteratorDescriptor * output = new CSG_VertexIteratorDescriptor; + if (output == NULL) return NULL; + output->Done = VertexIt_Done; + output->Fill = VertexIt_Fill; + output->Step = VertexIt_Step; + output->num_elements = mesh->VertexSet().size(); + + VertexIt * v_it = new VertexIt; + v_it->mesh = mesh; + v_it->pos = mesh->VertexSet().begin(); + v_it->trans = trans; + output->it = v_it; + return output; +}; + + +/** + * Face iterator. + */ + +struct FaceIt { + BSP_TMesh * mesh; + BSP_TFace *pos; +}; + + +static + void +FaceIt_Destruct( + CSG_FaceIteratorDescriptor * iterator +) { + delete ((FaceIt *)(iterator->it)); + iterator->it = NULL; + delete(iterator); +}; + + +static + int +FaceIt_Done( + CSG_IteratorPtr it +) { + // assume CSG_IteratorPtr is of the correct type. + FaceIt * face_it = (FaceIt *)it; + + if (face_it->pos < face_it->mesh->FaceSet().end()) { + return 0; + } + return 1; +}; + +static + void +FaceIt_Fill( + CSG_IteratorPtr it, + CSG_IFace *face +){ + // assume CSG_IteratorPtr is of the correct type. + FaceIt * face_it = (FaceIt *)it; + // essentially iterating through a triangle fan here. + + face->vertex_index[0] = int(face_it->pos->m_verts[0]); + face->vertex_index[1] = int(face_it->pos->m_verts[1]); + face->vertex_index[2] = int(face_it->pos->m_verts[2]); + + face->vertex_number = 3; +}; + +static + void +FaceIt_Step( + CSG_IteratorPtr it +) { + // assume CSG_IteratorPtr is of the correct type. + FaceIt * face_it = (FaceIt *)it; + + face_it->pos ++; +}; + +static + CSG_FaceIteratorDescriptor * +FaceIt_Construct( + BSP_TMesh * mesh +) { + CSG_FaceIteratorDescriptor * output = new CSG_FaceIteratorDescriptor; + if (output == NULL) return NULL; + + output->Done = FaceIt_Done; + output->Fill = FaceIt_Fill; + output->Step = FaceIt_Step; + + output->num_elements = mesh->FaceSet().size(); + + FaceIt * f_it = new FaceIt; + f_it->mesh = mesh; + f_it->pos = mesh->FaceSet().begin(); + + output->it = f_it; + + return output; +}; + +/** + * Some Build functions. + */ + +static + MEM_SmartPtr<BSP_TMesh> +BuildMesh( + CSG_MeshPropertyDescriptor &props, + CSG_FaceIteratorDescriptor &face_it, + CSG_VertexIteratorDescriptor &vertex_it +) { + MEM_SmartPtr<BSP_TMesh> mesh = new BSP_TMesh(); + + CSG_IVertex vert; + + while (!vertex_it.Done(vertex_it.it)) { + + vertex_it.Fill(vertex_it.it,&vert); + + BSP_TVertex v; + v.m_pos = MT_Point3(vert.position); + mesh->VertexSet().push_back(v); + + vertex_it.Step(vertex_it.it); + } + + + CSG_IFace face; + + while (!face_it.Done(face_it.it)) { + face_it.Fill(face_it.it,&face); + + BSP_TFace f; + + f.m_verts[0] = face.vertex_index[0], + f.m_verts[1] = face.vertex_index[1], + f.m_verts[2] = face.vertex_index[2], + + mesh->BuildNormal(f); + + mesh->FaceSet().push_back(f); + + face_it.Step(face_it.it); + } + + return mesh; +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#endif
\ No newline at end of file diff --git a/intern/bsp/test/BSP_GhostTest/Makefile b/intern/bsp/test/BSP_GhostTest/Makefile new file mode 100644 index 00000000000..06dded40a17 --- /dev/null +++ b/intern/bsp/test/BSP_GhostTest/Makefile @@ -0,0 +1,56 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# BSP_GhostTest Makefile +# + +LIBNAME = BSP_GhostTest +SOURCEDIR = intern/bsp/test/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) + +include nan_compile.mk + +CCFLAGS += $(LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I$(OPENGL_HEADERS) +CPPFLAGS += -I$(NAN_BSP)/include +CPPFLAGS += -I$(NAN_MEMUTIL)/include +CPPFLAGS += -I$(NAN_CONTAINER)/include +CPPFLAGS += -I$(NAN_MOTO)/include +CPPFLAGS += -I$(NAN_GHOST)/include +CPPFLAGS += -I$(NAN_STRING)/include +CPPFLAGS += -I../../extern/ + +ifeq ($(OS),windows) + CPPFLAGS += -I$(NAN_LIBDIR)/windows/glut-3.7/include +endif + + + diff --git a/intern/bsp/test/BSP_GhostTest/main.cpp b/intern/bsp/test/BSP_GhostTest/main.cpp new file mode 100755 index 00000000000..e7875047651 --- /dev/null +++ b/intern/bsp/test/BSP_GhostTest/main.cpp @@ -0,0 +1,147 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "BSP_GhostTest3D.h" + +#include "BSP_TMesh.h" +#include "MEM_SmartPtr.h" +#include "BSP_PlyLoader.h" + +#include <iostream> + +using namespace std; +#if 1 + MEM_SmartPtr<BSP_TMesh> +NewTestMesh( + int x, + int y, + MT_Scalar fx, + MT_Scalar fy, + MT_Scalar ampx, + MT_Scalar ampy, + MT_Scalar sx, + MT_Scalar sy +) { + + MEM_SmartPtr<BSP_TMesh> output = new BSP_TMesh; + + std::vector<BSP_TVertex> &verts = output->VertexSet(); + + int i,j; + + MT_Scalar x_scale = fx*MT_PI/x; + MT_Scalar y_scale = fy*MT_PI/y; + + MT_Scalar fsx = sx/x; + MT_Scalar fsy = sy/y; + + for (j = 0; j < y; j++) { + for (i = 0; i < x; i++) { + float z = ampx*sin(x_scale * i) + ampy*sin(y_scale * j); + + MT_Vector3 val(i*fsx - sx/2,j*fsy - sy/2,z); + + BSP_TVertex chuff; + chuff.m_pos = val; + verts.push_back(chuff); + } + } + + int poly[4]; + + for (j = 0; j < (y-1); j++) { + for (i = 0; i < (x-1); i++) { + + poly[0] = j*x + i; + poly[1] = poly[0] + 1; + poly[2] = poly[1] + y; + poly[3] = poly[2] -1; + + output->AddFace(poly,4); + } + } + + output->m_min = MT_Vector3(-sx/2,-sy/2,-ampx -ampy); + output->m_max = MT_Vector3(sx/2,sy/2,ampx + ampy); + + return output; +} +#endif + + +int main() { + + MT_Vector3 min,max; + MT_Vector3 min2,max2; + +#if 1 + MEM_SmartPtr<BSP_TMesh> mesh1 = BSP_PlyLoader::NewMeshFromFile("bsp_cube.ply",min,max); + MEM_SmartPtr<BSP_TMesh> mesh2 = BSP_PlyLoader::NewMeshFromFile("bsp_cube.ply",min2,max2); + + mesh1->m_min = min; + mesh1->m_max = max; + mesh2->m_min = min2; + mesh1->m_max = max2; + +#else + MEM_SmartPtr<BSP_TMesh> mesh1 = NewTestMesh(10,10,2,2,4,4,20,20); + MEM_SmartPtr<BSP_TMesh> mesh2 = NewTestMesh(10,10,2,2,4,4,20,20); +#endif + + if (!mesh1) { + cout << "could not load mesh!"; + return 0; + } + + + +// MEM_SmartPtr<BSP_TMesh> mesh2 = new BSP_TMesh(mesh1.Ref()); + + BSP_GhostTestApp3D app; + + cout << "Mesh polygons :" << mesh1->FaceSet().size() << "\n"; + cout << "Mesh vertices :" << mesh1->VertexSet().size() << "\n"; + + app.SetMesh(mesh1); + app.SetMesh(mesh2); + + + app.InitApp(); + + app.Run(); + + return 0; + +} + + + + diff --git a/intern/bsp/test/BSP_GhostTest/ply.h b/intern/bsp/test/BSP_GhostTest/ply.h new file mode 100755 index 00000000000..7947d224c5f --- /dev/null +++ b/intern/bsp/test/BSP_GhostTest/ply.h @@ -0,0 +1,200 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +Header for PLY polygon files. + +- Greg Turk, March 1994 + +A PLY file contains a single polygonal _object_. + +An object is composed of lists of _elements_. Typical elements are +vertices, faces, edges and materials. + +Each type of element for a given object has one or more _properties_ +associated with the element type. For instance, a vertex element may +have as properties three floating-point values x,y,z and three unsigned +chars for red, green and blue. + +--------------------------------------------------------------- + +Copyright (c) 1994 The Board of Trustees of The Leland Stanford +Junior University. All rights reserved. + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose is hereby granted without fee, provided +that the above copyright notice and this permission notice appear in +all copies of this software and that you do not sell the software. + +THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, +EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY +WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +*/ + +#ifndef __PLY_H__ +#define __PLY_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> +#include <stddef.h> + +#define PLY_ASCII 1 /* ascii PLY file */ +#define PLY_BINARY_BE 2 /* binary PLY file, big endian */ +#define PLY_BINARY_LE 3 /* binary PLY file, little endian */ + +#define PLY_OKAY 0 /* ply routine worked okay */ +#define PLY_ERROR -1 /* error in ply routine */ + +/* scalar data types supported by PLY format */ + +#define PLY_START_TYPE 0 +#define PLY_CHAR 1 +#define PLY_SHORT 2 +#define PLY_INT 3 +#define PLY_UCHAR 4 +#define PLY_USHORT 5 +#define PLY_UINT 6 +#define PLY_FLOAT 7 +#define PLY_DOUBLE 8 +#define PLY_END_TYPE 9 + +#define PLY_SCALAR 0 +#define PLY_LIST 1 + + +typedef struct PlyProperty { /* description of a property */ + + char *name; /* property name */ + int external_type; /* file's data type */ + int internal_type; /* program's data type */ + int offset; /* offset bytes of prop in a struct */ + + int is_list; /* 1 = list, 0 = scalar */ + int count_external; /* file's count type */ + int count_internal; /* program's count type */ + int count_offset; /* offset byte for list count */ + +} PlyProperty; + +typedef struct PlyElement { /* description of an element */ + char *name; /* element name */ + int num; /* number of elements in this object */ + int size; /* size of element (bytes) or -1 if variable */ + int nprops; /* number of properties for this element */ + PlyProperty **props; /* list of properties in the file */ + char *store_prop; /* flags: property wanted by user? */ + int other_offset; /* offset to un-asked-for props, or -1 if none*/ + int other_size; /* size of other_props structure */ +} PlyElement; + +typedef struct PlyOtherProp { /* describes other properties in an element */ + char *name; /* element name */ + int size; /* size of other_props */ + int nprops; /* number of properties in other_props */ + PlyProperty **props; /* list of properties in other_props */ +} PlyOtherProp; + +typedef struct OtherData { /* for storing other_props for an other element */ + void *other_props; +} OtherData; + +typedef struct OtherElem { /* data for one "other" element */ + char *elem_name; /* names of other elements */ + int elem_count; /* count of instances of each element */ + OtherData **other_data; /* actual property data for the elements */ + PlyOtherProp *other_props; /* description of the property data */ +} OtherElem; + +typedef struct PlyOtherElems { /* "other" elements, not interpreted by user */ + int num_elems; /* number of other elements */ + OtherElem *other_list; /* list of data for other elements */ +} PlyOtherElems; + +typedef struct PlyFile { /* description of PLY file */ + FILE *fp; /* file pointer */ + int file_type; /* ascii or binary */ + float version; /* version number of file */ + int nelems; /* number of elements of object */ + PlyElement **elems; /* list of elements */ + int num_comments; /* number of comments */ + char **comments; /* list of comments */ + int num_obj_info; /* number of items of object information */ + char **obj_info; /* list of object info items */ + PlyElement *which_elem; /* which element we're currently writing */ + PlyOtherElems *other_elems; /* "other" elements from a PLY file */ +} PlyFile; + +/* memory allocation */ +static char *my_alloc(); +#define myalloc(mem_size) my_alloc((mem_size), __LINE__, __FILE__) + + +/*** delcaration of routines ***/ + +extern PlyFile *ply_write(FILE *, int, char **, int); +extern PlyFile *ply_open_for_writing(char *, int, char **, int, float *); +extern void ply_describe_element(PlyFile *, char *, int, int, PlyProperty *); +extern void ply_describe_property(PlyFile *, char *, PlyProperty *); +extern void ply_element_count(PlyFile *, char *, int); +extern void ply_header_complete(PlyFile *); +extern void ply_put_element_setup(PlyFile *, char *); +extern void ply_put_element(PlyFile *, void *); +extern void ply_put_comment(PlyFile *, char *); +extern void ply_put_obj_info(PlyFile *, char *); +extern PlyFile *ply_read(FILE *, int *, char ***); +extern PlyFile *ply_open_for_reading( char *, int *, char ***, int *, float *); +extern PlyProperty **ply_get_element_description(PlyFile *, char *, int*, int*); +extern void ply_get_element_setup( PlyFile *, char *, int, PlyProperty *); +extern void ply_get_property(PlyFile *, char *, PlyProperty *); +extern PlyOtherProp *ply_get_other_properties(PlyFile *, char *, int); +extern void ply_get_element(PlyFile *, void *); +extern char **ply_get_comments(PlyFile *, int *); +extern char **ply_get_obj_info(PlyFile *, int *); +extern void ply_close(PlyFile *); +extern void ply_get_info(PlyFile *, float *, int *); +extern PlyOtherElems *ply_get_other_element (PlyFile *, char *, int); +extern void ply_describe_other_elements ( PlyFile *, PlyOtherElems *); +extern void ply_put_other_elements (PlyFile *); +extern void ply_free_other_elements (PlyOtherElems *); + +extern int equal_strings(char *, char *); + + +#ifdef __cplusplus +} +#endif +#endif /* !__PLY_H__ */ + diff --git a/intern/bsp/test/BSP_GhostTest/plyfile.c b/intern/bsp/test/BSP_GhostTest/plyfile.c new file mode 100755 index 00000000000..1fda4c77454 --- /dev/null +++ b/intern/bsp/test/BSP_GhostTest/plyfile.c @@ -0,0 +1,2548 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + +The interface routines for reading and writing PLY polygon files. + +Greg Turk, February 1994 + +--------------------------------------------------------------- + +A PLY file contains a single polygonal _object_. + +An object is composed of lists of _elements_. Typical elements are +vertices, faces, edges and materials. + +Each type of element for a given object has one or more _properties_ +associated with the element type. For instance, a vertex element may +have as properties the floating-point values x,y,z and the three unsigned +chars representing red, green and blue. + +--------------------------------------------------------------- + +Copyright (c) 1994 The Board of Trustees of The Leland Stanford +Junior University. All rights reserved. + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose is hereby granted without fee, provided +that the above copyright notice and this permission notice appear in +all copies of this software and that you do not sell the software. + +THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, +EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY +WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include "ply.h" + +char *type_names[] = { +"invalid", +"char", "short", "int", +"uchar", "ushort", "uint", +"float", "double", +}; + +int ply_type_size[] = { + 0, 1, 2, 4, 1, 2, 4, 4, 8 +}; + +#define NO_OTHER_PROPS -1 + +#define DONT_STORE_PROP 0 +#define STORE_PROP 1 + +#define OTHER_PROP 0 +#define NAMED_PROP 1 + + +/* returns 1 if strings are equal, 0 if not */ +int equal_strings(char *, char *); + +/* find an element in a plyfile's list */ +PlyElement *find_element(PlyFile *, char *); + +/* find a property in an element's list */ +PlyProperty *find_property(PlyElement *, char *, int *); + +/* write to a file the word describing a PLY file data type */ +void write_scalar_type (FILE *, int); + +/* read a line from a file and break it up into separate words */ +char **get_words(FILE *, int *, char **); +char **old_get_words(FILE *, int *); + +/* write an item to a file */ +void write_binary_item(FILE *, int, unsigned int, double, int); +void write_ascii_item(FILE *, int, unsigned int, double, int); +double old_write_ascii_item(FILE *, char *, int); + +/* add information to a PLY file descriptor */ +void add_element(PlyFile *, char **); +void add_property(PlyFile *, char **); +void add_comment(PlyFile *, char *); +void add_obj_info(PlyFile *, char *); + +/* copy a property */ +void copy_property(PlyProperty *, PlyProperty *); + +/* store a value into where a pointer and a type specify */ +void store_item(char *, int, int, unsigned int, double); + +/* return the value of a stored item */ +void get_stored_item( void *, int, int *, unsigned int *, double *); + +/* return the value stored in an item, given ptr to it and its type */ +double get_item_value(char *, int); + +/* get binary or ascii item and store it according to ptr and type */ +void get_ascii_item(char *, int, int *, unsigned int *, double *); +void get_binary_item(FILE *, int, int *, unsigned int *, double *); + +/* get a bunch of elements from a file */ +void ascii_get_element(PlyFile *, char *); +void binary_get_element(PlyFile *, char *); + +/* memory allocation */ +char *my_alloc(int, int, char *); + + +/*************/ +/* Writing */ +/*************/ + + +/****************************************************************************** +Given a file pointer, get ready to write PLY data to the file. + +Entry: + fp - the given file pointer + nelems - number of elements in object + elem_names - list of element names + file_type - file type, either ascii or binary + +Exit: + returns a pointer to a PlyFile, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *ply_write( + FILE *fp, + int nelems, + char **elem_names, + int file_type +) +{ + int i; + PlyFile *plyfile; + PlyElement *elem; + + /* check for NULL file pointer */ + if (fp == NULL) + return (NULL); + + /* create a record for this object */ + + plyfile = (PlyFile *) myalloc (sizeof (PlyFile)); + plyfile->file_type = file_type; + plyfile->num_comments = 0; + plyfile->num_obj_info = 0; + plyfile->nelems = nelems; + plyfile->version = 1.0; + plyfile->fp = fp; + plyfile->other_elems = NULL; + + /* tuck aside the names of the elements */ + + plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *) * nelems); + for (i = 0; i < nelems; i++) { + elem = (PlyElement *) myalloc (sizeof (PlyElement)); + plyfile->elems[i] = elem; + elem->name = strdup (elem_names[i]); + elem->num = 0; + elem->nprops = 0; + } + + /* return pointer to the file descriptor */ + return (plyfile); +} + + +/****************************************************************************** +Open a polygon file for writing. + +Entry: + filename - name of file to read from + nelems - number of elements in object + elem_names - list of element names + file_type - file type, either ascii or binary + +Exit: + version - version number of PLY file + returns a file identifier, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *ply_open_for_writing( + char *filename, + int nelems, + char **elem_names, + int file_type, + float *version +) +{ + PlyFile *plyfile; + char *name; + FILE *fp; + + /* tack on the extension .ply, if necessary */ + + name = (char *) myalloc (sizeof (char) * (strlen (filename) + 5)); + strcpy (name, filename); + if (strlen (name) < 4 || + strcmp (name + strlen (name) - 4, ".ply") != 0) + strcat (name, ".ply"); + + /* open the file for writing */ + + fp = fopen (name, "w"); + if (fp == NULL) { + return (NULL); + } + + /* create the actual PlyFile structure */ + + plyfile = ply_write (fp, nelems, elem_names, file_type); + if (plyfile == NULL) + return (NULL); + + /* say what PLY file version number we're writing */ + *version = plyfile->version; + + /* return pointer to the file descriptor */ + return (plyfile); +} + + +/****************************************************************************** +Describe an element, including its properties and how many will be written +to the file. + +Entry: + plyfile - file identifier + elem_name - name of element that information is being specified about + nelems - number of elements of this type to be written + nprops - number of properties contained in the element + prop_list - list of properties +******************************************************************************/ + +void ply_describe_element( + PlyFile *plyfile, + char *elem_name, + int nelems, + int nprops, + PlyProperty *prop_list +) +{ + int i; + PlyElement *elem; + PlyProperty *prop; + + /* look for appropriate element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf(stderr,"ply_describe_element: can't find element '%s'\n",elem_name); + exit (-1); + } + + elem->num = nelems; + + /* copy the list of properties */ + + elem->nprops = nprops; + elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *) * nprops); + elem->store_prop = (char *) myalloc (sizeof (char) * nprops); + + for (i = 0; i < nprops; i++) { + prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + elem->props[i] = prop; + elem->store_prop[i] = NAMED_PROP; + copy_property (prop, &prop_list[i]); + } +} + + +/****************************************************************************** +Describe a property of an element. + +Entry: + plyfile - file identifier + elem_name - name of element that information is being specified about + prop - the new property +******************************************************************************/ + +void ply_describe_property( + PlyFile *plyfile, + char *elem_name, + PlyProperty *prop +) +{ + PlyElement *elem; + PlyProperty *elem_prop; + + /* look for appropriate element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf(stderr, "ply_describe_property: can't find element '%s'\n", + elem_name); + return; + } + + /* create room for new property */ + + if (elem->nprops == 0) { + elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *)); + elem->store_prop = (char *) myalloc (sizeof (char)); + elem->nprops = 1; + } + else { + elem->nprops++; + elem->props = (PlyProperty **) + realloc (elem->props, sizeof (PlyProperty *) * elem->nprops); + elem->store_prop = (char *) + realloc (elem->store_prop, sizeof (char) * elem->nprops); + } + + /* copy the new property */ + + elem_prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + elem->props[elem->nprops - 1] = elem_prop; + elem->store_prop[elem->nprops - 1] = NAMED_PROP; + copy_property (elem_prop, prop); +} + + +/****************************************************************************** +Describe what the "other" properties are that are to be stored, and where +they are in an element. +******************************************************************************/ + +void ply_describe_other_properties( + PlyFile *plyfile, + PlyOtherProp *other, + int offset +) +{ + int i; + PlyElement *elem; + PlyProperty *prop; + + /* look for appropriate element */ + elem = find_element (plyfile, other->name); + if (elem == NULL) { + fprintf(stderr, "ply_describe_other_properties: can't find element '%s'\n", + other->name); + return; + } + + /* create room for other properties */ + + if (elem->nprops == 0) { + elem->props = (PlyProperty **) + myalloc (sizeof (PlyProperty *) * other->nprops); + elem->store_prop = (char *) myalloc (sizeof (char) * other->nprops); + elem->nprops = 0; + } + else { + int newsize; + newsize = elem->nprops + other->nprops; + elem->props = (PlyProperty **) + realloc (elem->props, sizeof (PlyProperty *) * newsize); + elem->store_prop = (char *) + realloc (elem->store_prop, sizeof (char) * newsize); + } + + /* copy the other properties */ + + for (i = 0; i < other->nprops; i++) { + prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + copy_property (prop, other->props[i]); + elem->props[elem->nprops] = prop; + elem->store_prop[elem->nprops] = OTHER_PROP; + elem->nprops++; + } + + /* save other info about other properties */ + elem->other_size = other->size; + elem->other_offset = offset; +} + + +/****************************************************************************** +State how many of a given element will be written. + +Entry: + plyfile - file identifier + elem_name - name of element that information is being specified about + nelems - number of elements of this type to be written +******************************************************************************/ + +void ply_element_count( + PlyFile *plyfile, + char *elem_name, + int nelems +) +{ + PlyElement *elem; + + /* look for appropriate element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf(stderr,"ply_element_count: can't find element '%s'\n",elem_name); + exit (-1); + } + + elem->num = nelems; +} + + +/****************************************************************************** +Signal that we've described everything a PLY file's header and that the +header should be written to the file. + +Entry: + plyfile - file identifier +******************************************************************************/ + +void ply_header_complete(PlyFile *plyfile) +{ + int i,j; + FILE *fp = plyfile->fp; + PlyElement *elem; + PlyProperty *prop; + + fprintf (fp, "ply\n"); + + switch (plyfile->file_type) { + case PLY_ASCII: + fprintf (fp, "format ascii 1.0\n"); + break; + case PLY_BINARY_BE: + fprintf (fp, "format binary_big_endian 1.0\n"); + break; + case PLY_BINARY_LE: + fprintf (fp, "format binary_little_endian 1.0\n"); + break; + default: + fprintf (stderr, "ply_header_complete: bad file type = %d\n", + plyfile->file_type); + exit (-1); + } + + /* write out the comments */ + + for (i = 0; i < plyfile->num_comments; i++) + fprintf (fp, "comment %s\n", plyfile->comments[i]); + + /* write out object information */ + + for (i = 0; i < plyfile->num_obj_info; i++) + fprintf (fp, "obj_info %s\n", plyfile->obj_info[i]); + + /* write out information about each element */ + + for (i = 0; i < plyfile->nelems; i++) { + + elem = plyfile->elems[i]; + fprintf (fp, "element %s %d\n", elem->name, elem->num); + + /* write out each property */ + for (j = 0; j < elem->nprops; j++) { + prop = elem->props[j]; + if (prop->is_list) { + fprintf (fp, "property list "); + write_scalar_type (fp, prop->count_external); + fprintf (fp, " "); + write_scalar_type (fp, prop->external_type); + fprintf (fp, " %s\n", prop->name); + } + else { + fprintf (fp, "property "); + write_scalar_type (fp, prop->external_type); + fprintf (fp, " %s\n", prop->name); + } + } + } + + fprintf (fp, "end_header\n"); +} + + +/****************************************************************************** +Specify which elements are going to be written. This should be called +before a call to the routine ply_put_element(). + +Entry: + plyfile - file identifier + elem_name - name of element we're talking about +******************************************************************************/ + +void ply_put_element_setup(PlyFile *plyfile, char *elem_name) +{ + PlyElement *elem; + + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf(stderr, "ply_elements_setup: can't find element '%s'\n", elem_name); + exit (-1); + } + + plyfile->which_elem = elem; +} + + +/****************************************************************************** +Write an element to the file. This routine assumes that we're +writing the type of element specified in the last call to the routine +ply_put_element_setup(). + +Entry: + plyfile - file identifier + elem_ptr - pointer to the element +******************************************************************************/ + +void ply_put_element(PlyFile *plyfile, void *elem_ptr) +{ + int j,k; + FILE *fp = plyfile->fp; + PlyElement *elem; + PlyProperty *prop; + char *elem_data,*item; + char **item_ptr; + int list_count; + int item_size; + int int_val; + unsigned int uint_val; + double double_val; + char **other_ptr; + + elem = plyfile->which_elem; + elem_data = elem_ptr; + other_ptr = (char **) (((char *) elem_ptr) + elem->other_offset); + + /* write out either to an ascii or binary file */ + + if (plyfile->file_type == PLY_ASCII) { + + /* write an ascii file */ + + /* write out each property of the element */ + for (j = 0; j < elem->nprops; j++) { + prop = elem->props[j]; + if (elem->store_prop[j] == OTHER_PROP) + elem_data = *other_ptr; + else + elem_data = elem_ptr; + if (prop->is_list) { + item = elem_data + prop->count_offset; + get_stored_item ((void *) item, prop->count_internal, + &int_val, &uint_val, &double_val); + write_ascii_item (fp, int_val, uint_val, double_val, + prop->count_external); + list_count = uint_val; + item_ptr = (char **) (elem_data + prop->offset); + item = item_ptr[0]; + item_size = ply_type_size[prop->internal_type]; + for (k = 0; k < list_count; k++) { + get_stored_item ((void *) item, prop->internal_type, + &int_val, &uint_val, &double_val); + write_ascii_item (fp, int_val, uint_val, double_val, + prop->external_type); + item += item_size; + } + } + else { + item = elem_data + prop->offset; + get_stored_item ((void *) item, prop->internal_type, + &int_val, &uint_val, &double_val); + write_ascii_item (fp, int_val, uint_val, double_val, + prop->external_type); + } + } + + fprintf (fp, "\n"); + } + else { + + /* write a binary file */ + + /* write out each property of the element */ + for (j = 0; j < elem->nprops; j++) { + prop = elem->props[j]; + if (elem->store_prop[j] == OTHER_PROP) + elem_data = *other_ptr; + else + elem_data = elem_ptr; + if (prop->is_list) { + item = elem_data + prop->count_offset; + item_size = ply_type_size[prop->count_internal]; + get_stored_item ((void *) item, prop->count_internal, + &int_val, &uint_val, &double_val); + write_binary_item (fp, int_val, uint_val, double_val, + prop->count_external); + list_count = uint_val; + item_ptr = (char **) (elem_data + prop->offset); + item = item_ptr[0]; + item_size = ply_type_size[prop->internal_type]; + for (k = 0; k < list_count; k++) { + get_stored_item ((void *) item, prop->internal_type, + &int_val, &uint_val, &double_val); + write_binary_item (fp, int_val, uint_val, double_val, + prop->external_type); + item += item_size; + } + } + else { + item = elem_data + prop->offset; + item_size = ply_type_size[prop->internal_type]; + get_stored_item ((void *) item, prop->internal_type, + &int_val, &uint_val, &double_val); + write_binary_item (fp, int_val, uint_val, double_val, + prop->external_type); + } + } + + } +} + + +/****************************************************************************** +Specify a comment that will be written in the header. + +Entry: + plyfile - file identifier + comment - the comment to be written +******************************************************************************/ + +void ply_put_comment(PlyFile *plyfile, char *comment) +{ + /* (re)allocate space for new comment */ + if (plyfile->num_comments == 0) + plyfile->comments = (char **) myalloc (sizeof (char *)); + else + plyfile->comments = (char **) realloc (plyfile->comments, + sizeof (char *) * (plyfile->num_comments + 1)); + + /* add comment to list */ + plyfile->comments[plyfile->num_comments] = strdup (comment); + plyfile->num_comments++; +} + + +/****************************************************************************** +Specify a piece of object information (arbitrary text) that will be written +in the header. + +Entry: + plyfile - file identifier + obj_info - the text information to be written +******************************************************************************/ + +void ply_put_obj_info(PlyFile *plyfile, char *obj_info) +{ + /* (re)allocate space for new info */ + if (plyfile->num_obj_info == 0) + plyfile->obj_info = (char **) myalloc (sizeof (char *)); + else + plyfile->obj_info = (char **) realloc (plyfile->obj_info, + sizeof (char *) * (plyfile->num_obj_info + 1)); + + /* add info to list */ + plyfile->obj_info[plyfile->num_obj_info] = strdup (obj_info); + plyfile->num_obj_info++; +} + + + + + + + +/*************/ +/* Reading */ +/*************/ + + + +/****************************************************************************** +Given a file pointer, get ready to read PLY data from the file. + +Entry: + fp - the given file pointer + +Exit: + nelems - number of elements in object + elem_names - list of element names + returns a pointer to a PlyFile, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *ply_read(FILE *fp, int *nelems, char ***elem_names) +{ + int i,j; + PlyFile *plyfile; + int nwords; + char **words; + int found_format = 0; + char **elist; + PlyElement *elem; + char *orig_line; + + /* check for NULL file pointer */ + if (fp == NULL) + return (NULL); + + /* create record for this object */ + + plyfile = (PlyFile *) myalloc (sizeof (PlyFile)); + plyfile->nelems = 0; + plyfile->comments = NULL; + plyfile->num_comments = 0; + plyfile->obj_info = NULL; + plyfile->num_obj_info = 0; + plyfile->fp = fp; + plyfile->other_elems = NULL; + + /* read and parse the file's header */ + + words = get_words (plyfile->fp, &nwords, &orig_line); + if (!words || !equal_strings (words[0], "ply")) + return (NULL); + + while (words) { + + /* parse words */ + + if (equal_strings (words[0], "format")) { + if (nwords != 3) + return (NULL); + if (equal_strings (words[1], "ascii")) + plyfile->file_type = PLY_ASCII; + else if (equal_strings (words[1], "binary_big_endian")) + plyfile->file_type = PLY_BINARY_BE; + else if (equal_strings (words[1], "binary_little_endian")) + plyfile->file_type = PLY_BINARY_LE; + else + return (NULL); + plyfile->version = (float)atof (words[2]); + found_format = 1; + } + else if (equal_strings (words[0], "element")) + add_element (plyfile, words); + else if (equal_strings (words[0], "property")) + add_property (plyfile, words); + else if (equal_strings (words[0], "comment")) + add_comment (plyfile, orig_line); + else if (equal_strings (words[0], "obj_info")) + add_obj_info (plyfile, orig_line); + else if (equal_strings (words[0], "end_header")) + break; + + /* free up words space */ + free (words); + + words = get_words (plyfile->fp, &nwords, &orig_line); + } + + /* create tags for each property of each element, to be used */ + /* later to say whether or not to store each property for the user */ + + for (i = 0; i < plyfile->nelems; i++) { + elem = plyfile->elems[i]; + elem->store_prop = (char *) myalloc (sizeof (char) * elem->nprops); + for (j = 0; j < elem->nprops; j++) + elem->store_prop[j] = DONT_STORE_PROP; + elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */ + } + + /* set return values about the elements */ + + elist = (char **) myalloc (sizeof (char *) * plyfile->nelems); + for (i = 0; i < plyfile->nelems; i++) + elist[i] = strdup (plyfile->elems[i]->name); + + *elem_names = elist; + *nelems = plyfile->nelems; + + /* return a pointer to the file's information */ + + return (plyfile); +} + + +/****************************************************************************** +Open a polygon file for reading. + +Entry: + filename - name of file to read from + +Exit: + nelems - number of elements in object + elem_names - list of element names + file_type - file type, either ascii or binary + version - version number of PLY file + returns a file identifier, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *ply_open_for_reading( + char *filename, + int *nelems, + char ***elem_names, + int *file_type, + float *version +) +{ + FILE *fp; + PlyFile *plyfile; + char *name; + + /* tack on the extension .ply, if necessary */ + + name = (char *) myalloc (sizeof (char) * (strlen (filename) + 5)); + strcpy (name, filename); + if (strlen (name) < 4 || + strcmp (name + strlen (name) - 4, ".ply") != 0) + strcat (name, ".ply"); + + /* open the file for reading */ + + fp = fopen (name, "r"); + if (fp == NULL) + return (NULL); + + /* create the PlyFile data structure */ + + plyfile = ply_read (fp, nelems, elem_names); + + /* determine the file type and version */ + + *file_type = plyfile->file_type; + *version = plyfile->version; + + /* return a pointer to the file's information */ + + return (plyfile); +} + + +/****************************************************************************** +Get information about a particular element. + +Entry: + plyfile - file identifier + elem_name - name of element to get information about + +Exit: + nelems - number of elements of this type in the file + nprops - number of properties + returns a list of properties, or NULL if the file doesn't contain that elem +******************************************************************************/ + +PlyProperty **ply_get_element_description( + PlyFile *plyfile, + char *elem_name, + int *nelems, + int *nprops +) +{ + int i; + PlyElement *elem; + PlyProperty *prop; + PlyProperty **prop_list; + + /* find information about the element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) + return (NULL); + + *nelems = elem->num; + *nprops = elem->nprops; + + /* make a copy of the element's property list */ + prop_list = (PlyProperty **) myalloc (sizeof (PlyProperty *) * elem->nprops); + for (i = 0; i < elem->nprops; i++) { + prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + copy_property (prop, elem->props[i]); + prop_list[i] = prop; + } + + /* return this duplicate property list */ + return (prop_list); +} + + +/****************************************************************************** +Specify which properties of an element are to be returned. This should be +called before a call to the routine ply_get_element(). + +Entry: + plyfile - file identifier + elem_name - which element we're talking about + nprops - number of properties + prop_list - list of properties +******************************************************************************/ + +void ply_get_element_setup( + PlyFile *plyfile, + char *elem_name, + int nprops, + PlyProperty *prop_list +) +{ + int i; + PlyElement *elem; + PlyProperty *prop; + int index; + + /* find information about the element */ + elem = find_element (plyfile, elem_name); + plyfile->which_elem = elem; + + /* deposit the property information into the element's description */ + for (i = 0; i < nprops; i++) { + + /* look for actual property */ + prop = find_property (elem, prop_list[i].name, &index); + if (prop == NULL) { + fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n", + prop_list[i].name, elem_name); + continue; + } + + /* store its description */ + prop->internal_type = prop_list[i].internal_type; + prop->offset = prop_list[i].offset; + prop->count_internal = prop_list[i].count_internal; + prop->count_offset = prop_list[i].count_offset; + + /* specify that the user wants this property */ + elem->store_prop[index] = STORE_PROP; + } +} + + +/****************************************************************************** +Specify a property of an element that is to be returned. This should be +called (usually multiple times) before a call to the routine ply_get_element(). +This routine should be used in preference to the less flexible old routine +called ply_get_element_setup(). + +Entry: + plyfile - file identifier + elem_name - which element we're talking about + prop - property to add to those that will be returned +******************************************************************************/ + +void ply_get_property( + PlyFile *plyfile, + char *elem_name, + PlyProperty *prop +) +{ + PlyElement *elem; + PlyProperty *prop_ptr; + int index; + + /* find information about the element */ + elem = find_element (plyfile, elem_name); + plyfile->which_elem = elem; + + /* deposit the property information into the element's description */ + + prop_ptr = find_property (elem, prop->name, &index); + if (prop_ptr == NULL) { + fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n", + prop->name, elem_name); + return; + } + prop_ptr->internal_type = prop->internal_type; + prop_ptr->offset = prop->offset; + prop_ptr->count_internal = prop->count_internal; + prop_ptr->count_offset = prop->count_offset; + + /* specify that the user wants this property */ + elem->store_prop[index] = STORE_PROP; +} + + +/****************************************************************************** +Read one element from the file. This routine assumes that we're reading +the type of element specified in the last call to the routine +ply_get_element_setup(). + +Entry: + plyfile - file identifier + elem_ptr - pointer to location where the element information should be put +******************************************************************************/ + +void ply_get_element(PlyFile *plyfile, void *elem_ptr) +{ + if (plyfile->file_type == PLY_ASCII) + ascii_get_element (plyfile, (char *) elem_ptr); + else + binary_get_element (plyfile, (char *) elem_ptr); +} + + +/****************************************************************************** +Extract the comments from the header information of a PLY file. + +Entry: + plyfile - file identifier + +Exit: + num_comments - number of comments returned + returns a pointer to a list of comments +******************************************************************************/ + +char **ply_get_comments(PlyFile *plyfile, int *num_comments) +{ + *num_comments = plyfile->num_comments; + return (plyfile->comments); +} + + +/****************************************************************************** +Extract the object information (arbitrary text) from the header information +of a PLY file. + +Entry: + plyfile - file identifier + +Exit: + num_obj_info - number of lines of text information returned + returns a pointer to a list of object info lines +******************************************************************************/ + +char **ply_get_obj_info(PlyFile *plyfile, int *num_obj_info) +{ + *num_obj_info = plyfile->num_obj_info; + return (plyfile->obj_info); +} + + +/****************************************************************************** +Make ready for "other" properties of an element-- those properties that +the user has not explicitly asked for, but that are to be stashed away +in a special structure to be carried along with the element's other +information. + +Entry: + plyfile - file identifier + elem - element for which we want to save away other properties +******************************************************************************/ + +void setup_other_props(PlyElement *elem) +{ + int i; + PlyProperty *prop; + int size = 0; + int type_size; + + /* Examine each property in decreasing order of size. */ + /* We do this so that all data types will be aligned by */ + /* word, half-word, or whatever within the structure. */ + + for (type_size = 8; type_size > 0; type_size /= 2) { + + /* add up the space taken by each property, and save this information */ + /* away in the property descriptor */ + + for (i = 0; i < elem->nprops; i++) { + + /* don't bother with properties we've been asked to store explicitly */ + if (elem->store_prop[i]) + continue; + + prop = elem->props[i]; + + /* internal types will be same as external */ + prop->internal_type = prop->external_type; + prop->count_internal = prop->count_external; + + /* check list case */ + if (prop->is_list) { + + /* pointer to list */ + if (type_size == sizeof (void *)) { + prop->offset = size; + size += sizeof (void *); /* always use size of a pointer here */ + } + + /* count of number of list elements */ + if (type_size == ply_type_size[prop->count_external]) { + prop->count_offset = size; + size += ply_type_size[prop->count_external]; + } + } + /* not list */ + else if (type_size == ply_type_size[prop->external_type]) { + prop->offset = size; + size += ply_type_size[prop->external_type]; + } + } + + } + + /* save the size for the other_props structure */ + elem->other_size = size; +} + + +/****************************************************************************** +Specify that we want the "other" properties of an element to be tucked +away within the user's structure. The user needn't be concerned for how +these properties are stored. + +Entry: + plyfile - file identifier + elem_name - name of element that we want to store other_props in + offset - offset to where other_props will be stored inside user's structure + +Exit: + returns pointer to structure containing description of other_props +******************************************************************************/ + +PlyOtherProp *ply_get_other_properties( + PlyFile *plyfile, + char *elem_name, + int offset +) +{ + int i; + PlyElement *elem; + PlyOtherProp *other; + PlyProperty *prop; + int nprops; + + /* find information about the element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf (stderr, "ply_get_other_properties: Can't find element '%s'\n", + elem_name); + return (NULL); + } + + /* remember that this is the "current" element */ + plyfile->which_elem = elem; + + /* save the offset to where to store the other_props */ + elem->other_offset = offset; + + /* place the appropriate pointers, etc. in the element's property list */ + setup_other_props (elem); + + /* create structure for describing other_props */ + other = (PlyOtherProp *) myalloc (sizeof (PlyOtherProp)); + other->name = strdup (elem_name); +#if 0 + if (elem->other_offset == NO_OTHER_PROPS) { + other->size = 0; + other->props = NULL; + other->nprops = 0; + return (other); + } +#endif + other->size = elem->other_size; + other->props = (PlyProperty **) myalloc (sizeof(PlyProperty) * elem->nprops); + + /* save descriptions of each "other" property */ + nprops = 0; + for (i = 0; i < elem->nprops; i++) { + if (elem->store_prop[i]) + continue; + prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + copy_property (prop, elem->props[i]); + other->props[nprops] = prop; + nprops++; + } + other->nprops = nprops; + +#if 1 + /* set other_offset pointer appropriately if there are NO other properties */ + if (other->nprops == 0) { + elem->other_offset = NO_OTHER_PROPS; + } +#endif + + /* return structure */ + return (other); +} + + + + +/*************************/ +/* Other Element Stuff */ +/*************************/ + + + + +/****************************************************************************** +Grab all the data for an element that a user does not want to explicitly +read in. + +Entry: + plyfile - pointer to file + elem_name - name of element whose data is to be read in + elem_count - number of instances of this element stored in the file + +Exit: + returns pointer to ALL the "other" element data for this PLY file +******************************************************************************/ + +PlyOtherElems *ply_get_other_element ( + PlyFile *plyfile, + char *elem_name, + int elem_count +) +{ + int i; + PlyElement *elem; + PlyOtherElems *other_elems; + OtherElem *other; + + /* look for appropriate element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf (stderr, + "ply_get_other_element: can't find element '%s'\n", elem_name); + exit (-1); + } + + /* create room for the new "other" element, initializing the */ + /* other data structure if necessary */ + + if (plyfile->other_elems == NULL) { + plyfile->other_elems = (PlyOtherElems *) myalloc (sizeof (PlyOtherElems)); + other_elems = plyfile->other_elems; + other_elems->other_list = (OtherElem *) myalloc (sizeof (OtherElem)); + other = &(other_elems->other_list[0]); + other_elems->num_elems = 1; + } + else { + other_elems = plyfile->other_elems; + other_elems->other_list = (OtherElem *) realloc (other_elems->other_list, + sizeof (OtherElem) * other_elems->num_elems + 1); + other = &(other_elems->other_list[other_elems->num_elems]); + other_elems->num_elems++; + } + + /* count of element instances in file */ + other->elem_count = elem_count; + + /* save name of element */ + other->elem_name = strdup (elem_name); + + /* create a list to hold all the current elements */ + other->other_data = (OtherData **) + malloc (sizeof (OtherData *) * other->elem_count); + + /* set up for getting elements */ + other->other_props = ply_get_other_properties (plyfile, elem_name, + offsetof(OtherData,other_props)); + + /* grab all these elements */ + for (i = 0; i < other->elem_count; i++) { + /* grab and element from the file */ + other->other_data[i] = (OtherData *) malloc (sizeof (OtherData)); + ply_get_element (plyfile, (void *) other->other_data[i]); + } + + /* return pointer to the other elements data */ + return (other_elems); +} + + +/****************************************************************************** +Pass along a pointer to "other" elements that we want to save in a given +PLY file. These other elements were presumably read from another PLY file. + +Entry: + plyfile - file pointer in which to store this other element info + other_elems - info about other elements that we want to store +******************************************************************************/ + +void ply_describe_other_elements ( + PlyFile *plyfile, + PlyOtherElems *other_elems +) +{ + int i; + OtherElem *other; + + /* ignore this call if there is no other element */ + if (other_elems == NULL) + return; + + /* save pointer to this information */ + plyfile->other_elems = other_elems; + + /* describe the other properties of this element */ + + for (i = 0; i < other_elems->num_elems; i++) { + other = &(other_elems->other_list[i]); + ply_element_count (plyfile, other->elem_name, other->elem_count); + ply_describe_other_properties (plyfile, other->other_props, + offsetof(OtherData,other_props)); + } +} + + +/****************************************************************************** +Write out the "other" elements specified for this PLY file. + +Entry: + plyfile - pointer to PLY file to write out other elements for +******************************************************************************/ + +void ply_put_other_elements (PlyFile *plyfile) +{ + int i,j; + OtherElem *other; + + /* make sure we have other elements to write */ + if (plyfile->other_elems == NULL) + return; + + /* write out the data for each "other" element */ + + for (i = 0; i < plyfile->other_elems->num_elems; i++) { + + other = &(plyfile->other_elems->other_list[i]); + ply_put_element_setup (plyfile, other->elem_name); + + /* write out each instance of the current element */ + for (j = 0; j < other->elem_count; j++) + ply_put_element (plyfile, (void *) other->other_data[j]); + } +} + + +/****************************************************************************** +Free up storage used by an "other" elements data structure. + +Entry: + other_elems - data structure to free up +******************************************************************************/ + + + + +/*******************/ +/* Miscellaneous */ +/*******************/ + + + +/****************************************************************************** +Close a PLY file. + +Entry: + plyfile - identifier of file to close +******************************************************************************/ + +void ply_close(PlyFile *plyfile) +{ + fclose (plyfile->fp); + + /* free up memory associated with the PLY file */ + free (plyfile); +} + + +/****************************************************************************** +Get version number and file type of a PlyFile. + +Entry: + ply - pointer to PLY file + +Exit: + version - version of the file + file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE +******************************************************************************/ + +void ply_get_info(PlyFile *ply, float *version, int *file_type) +{ + if (ply == NULL) + return; + + *version = ply->version; + *file_type = ply->file_type; +} + + +/****************************************************************************** +Compare two strings. Returns 1 if they are the same, 0 if not. +******************************************************************************/ + +int equal_strings(char *s1, char *s2) +{ + + while (*s1 && *s2) + if (*s1++ != *s2++) + return (0); + + if (*s1 != *s2) + return (0); + else + return (1); +} + + +/****************************************************************************** +Find an element from the element list of a given PLY object. + +Entry: + plyfile - file id for PLY file + element - name of element we're looking for + +Exit: + returns the element, or NULL if not found +******************************************************************************/ + +PlyElement *find_element(PlyFile *plyfile, char *element) +{ + int i; + + for (i = 0; i < plyfile->nelems; i++) + if (equal_strings (element, plyfile->elems[i]->name)) + return (plyfile->elems[i]); + + return (NULL); +} + + +/****************************************************************************** +Find a property in the list of properties of a given element. + +Entry: + elem - pointer to element in which we want to find the property + prop_name - name of property to find + +Exit: + index - index to position in list + returns a pointer to the property, or NULL if not found +******************************************************************************/ + +PlyProperty *find_property(PlyElement *elem, char *prop_name, int *index) +{ + int i; + + for (i = 0; i < elem->nprops; i++) + if (equal_strings (prop_name, elem->props[i]->name)) { + *index = i; + return (elem->props[i]); + } + + *index = -1; + return (NULL); +} + + +/****************************************************************************** +Read an element from an ascii file. + +Entry: + plyfile - file identifier + elem_ptr - pointer to element +******************************************************************************/ + +void ascii_get_element(PlyFile *plyfile, char *elem_ptr) +{ + int j,k; + PlyElement *elem; + PlyProperty *prop; + char **words; + int nwords; + int which_word; + char *elem_data,*item; + char *item_ptr; + int item_size; + int int_val; + unsigned int uint_val; + double double_val; + int list_count; + int store_it; + char **store_array; + char *orig_line; + char *other_data; + int other_flag; + + other_flag = 0; + other_data = NULL; + item = NULL; + item_size = 0; + + /* the kind of element we're reading currently */ + elem = plyfile->which_elem; + + /* do we need to setup for other_props? */ + + if (elem->other_offset != NO_OTHER_PROPS) { + char **ptr; + other_flag = 1; + /* make room for other_props */ + other_data = (char *) myalloc (elem->other_size); + /* store pointer in user's structure to the other_props */ + ptr = (char **) (elem_ptr + elem->other_offset); + *ptr = other_data; + } else { + other_flag = 0; + other_data = NULL; + item = NULL; + item_size = 0; + } + + /* read in the element */ + + words = get_words (plyfile->fp, &nwords, &orig_line); + if (words == NULL) { + fprintf (stderr, "ply_get_element: unexpected end of file\n"); + exit (-1); + } + + which_word = 0; + + for (j = 0; j < elem->nprops; j++) { + + prop = elem->props[j]; + store_it = (elem->store_prop[j] | other_flag); + + /* store either in the user's structure or in other_props */ + if (elem->store_prop[j]) + elem_data = elem_ptr; + else + elem_data = other_data; + + if (prop->is_list) { /* a list */ + + /* get and store the number of items in the list */ + get_ascii_item (words[which_word++], prop->count_external, + &int_val, &uint_val, &double_val); + if (store_it) { + item = elem_data + prop->count_offset; + store_item(item, prop->count_internal, int_val, uint_val, double_val); + } + + /* allocate space for an array of items and store a ptr to the array */ + list_count = int_val; + item_size = ply_type_size[prop->internal_type]; + store_array = (char **) (elem_data + prop->offset); + + if (list_count == 0) { + if (store_it) + *store_array = NULL; + } + else { + if (store_it) { + item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count); + item = item_ptr; + *store_array = item_ptr; + } + + /* read items and store them into the array */ + for (k = 0; k < list_count; k++) { + get_ascii_item (words[which_word++], prop->external_type, + &int_val, &uint_val, &double_val); + if (store_it) { + store_item (item, prop->internal_type, + int_val, uint_val, double_val); + item += item_size; + } + } + } + + } + else { /* not a list */ + get_ascii_item (words[which_word++], prop->external_type, + &int_val, &uint_val, &double_val); + if (store_it) { + item = elem_data + prop->offset; + store_item (item, prop->internal_type, int_val, uint_val, double_val); + } + } + + } + + free (words); +} + + +/****************************************************************************** +Read an element from a binary file. + +Entry: + plyfile - file identifier + elem_ptr - pointer to an element +******************************************************************************/ + +void binary_get_element(PlyFile *plyfile, char *elem_ptr) +{ + int j,k; + PlyElement *elem; + PlyProperty *prop; + FILE *fp = plyfile->fp; + char *elem_data,*item; + char *item_ptr; + int item_size; + int int_val; + unsigned int uint_val; + double double_val; + int list_count; + int store_it; + char **store_array; + char *other_data; + int other_flag; + + + other_flag = 0; + other_data = NULL; + item = NULL; + item_size = 0; + + /* the kind of element we're reading currently */ + elem = plyfile->which_elem; + + /* do we need to setup for other_props? */ + + if (elem->other_offset != NO_OTHER_PROPS) { + char **ptr; + other_flag = 1; + /* make room for other_props */ + other_data = (char *) myalloc (elem->other_size); + /* store pointer in user's structure to the other_props */ + ptr = (char **) (elem_ptr + elem->other_offset); + *ptr = other_data; + } + else { + other_flag = 0; + other_data = NULL; + item = NULL; + item_size = 0; + } + /* read in a number of elements */ + + for (j = 0; j < elem->nprops; j++) { + + prop = elem->props[j]; + store_it = (elem->store_prop[j] | other_flag); + + /* store either in the user's structure or in other_props */ + if (elem->store_prop[j]) + elem_data = elem_ptr; + else + elem_data = other_data; + + if (prop->is_list) { /* a list */ + + /* get and store the number of items in the list */ + get_binary_item (fp, prop->count_external, + &int_val, &uint_val, &double_val); + if (store_it) { + item = elem_data + prop->count_offset; + store_item(item, prop->count_internal, int_val, uint_val, double_val); + } + + /* allocate space for an array of items and store a ptr to the array */ + list_count = int_val; + /* The "if" was added by Afra Zomorodian 8/22/95 + * so that zipper won't crash reading plies that have additional + * properties. + */ + if (store_it) { + item_size = ply_type_size[prop->internal_type]; + } + store_array = (char **) (elem_data + prop->offset); + if (list_count == 0) { + if (store_it) + *store_array = NULL; + } + else { + if (store_it) { + item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count); + item = item_ptr; + *store_array = item_ptr; + } + + /* read items and store them into the array */ + for (k = 0; k < list_count; k++) { + get_binary_item (fp, prop->external_type, + &int_val, &uint_val, &double_val); + if (store_it) { + store_item (item, prop->internal_type, + int_val, uint_val, double_val); + item += item_size; + } + } + } + + } + else { /* not a list */ + get_binary_item (fp, prop->external_type, + &int_val, &uint_val, &double_val); + if (store_it) { + item = elem_data + prop->offset; + store_item (item, prop->internal_type, int_val, uint_val, double_val); + } + } + + } +} + + +/****************************************************************************** +Write to a file the word that represents a PLY data type. + +Entry: + fp - file pointer + code - code for type +******************************************************************************/ + +void write_scalar_type (FILE *fp, int code) +{ + /* make sure this is a valid code */ + + if (code <= PLY_START_TYPE || code >= PLY_END_TYPE) { + fprintf (stderr, "write_scalar_type: bad data code = %d\n", code); + exit (-1); + } + + /* write the code to a file */ + + fprintf (fp, "%s", type_names[code]); +} + + +/****************************************************************************** +Get a text line from a file and break it up into words. + +IMPORTANT: The calling routine call "free" on the returned pointer once +finished with it. + +Entry: + fp - file to read from + +Exit: + nwords - number of words returned + orig_line - the original line of characters + returns a list of words from the line, or NULL if end-of-file +******************************************************************************/ + +char **get_words(FILE *fp, int *nwords, char **orig_line) +{ +#define BIG_STRING 4096 + static char str[BIG_STRING]; + static char str_copy[BIG_STRING]; + char **words; + int max_words = 10; + int num_words = 0; + char *ptr,*ptr2; + char *result; + + words = (char **) myalloc (sizeof (char *) * max_words); + + /* read in a line */ + result = fgets (str, BIG_STRING, fp); + if (result == NULL) { + *nwords = 0; + *orig_line = NULL; + return (NULL); + } + + /* convert line-feed and tabs into spaces */ + /* (this guarentees that there will be a space before the */ + /* null character at the end of the string) */ + + str[BIG_STRING-2] = ' '; + str[BIG_STRING-1] = '\0'; + + for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) { + *ptr2 = *ptr; + if (*ptr == '\t') { + *ptr = ' '; + *ptr2 = ' '; + } + else if (*ptr == '\n') { + *ptr = ' '; + *ptr2 = '\0'; + break; + } + } + + /* find the words in the line */ + + ptr = str; + while (*ptr != '\0') { + + /* jump over leading spaces */ + while (*ptr == ' ') + ptr++; + + /* break if we reach the end */ + if (*ptr == '\0') + break; + + /* save pointer to beginning of word */ + if (num_words >= max_words) { + max_words += 10; + words = (char **) realloc (words, sizeof (char *) * max_words); + } + words[num_words++] = ptr; + + /* jump over non-spaces */ + while (*ptr != ' ') + ptr++; + + /* place a null character here to mark the end of the word */ + *ptr++ = '\0'; + } + + /* return the list of words */ + *nwords = num_words; + *orig_line = str_copy; + return (words); +} + + +/****************************************************************************** +Return the value of an item, given a pointer to it and its type. + +Entry: + item - pointer to item + type - data type that "item" points to + +Exit: + returns a double-precision float that contains the value of the item +******************************************************************************/ + +double get_item_value(char *item, int type) +{ + unsigned char *puchar; + char *pchar; + short int *pshort; + unsigned short int *pushort; + int *pint; + unsigned int *puint; + float *pfloat; + double *pdouble; + int int_value; + unsigned int uint_value; + double double_value; + + switch (type) { + case PLY_CHAR: + pchar = (char *) item; + int_value = *pchar; + return ((double) int_value); + case PLY_UCHAR: + puchar = (unsigned char *) item; + int_value = *puchar; + return ((double) int_value); + case PLY_SHORT: + pshort = (short int *) item; + int_value = *pshort; + return ((double) int_value); + case PLY_USHORT: + pushort = (unsigned short int *) item; + int_value = *pushort; + return ((double) int_value); + case PLY_INT: + pint = (int *) item; + int_value = *pint; + return ((double) int_value); + case PLY_UINT: + puint = (unsigned int *) item; + uint_value = *puint; + return ((double) uint_value); + case PLY_FLOAT: + pfloat = (float *) item; + double_value = *pfloat; + return (double_value); + case PLY_DOUBLE: + pdouble = (double *) item; + double_value = *pdouble; + return (double_value); + default: + fprintf (stderr, "get_item_value: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Write out an item to a file as raw binary bytes. + +Entry: + fp - file to write to + int_val - integer version of item + uint_val - unsigned integer version of item + double_val - double-precision float version of item + type - data type to write out +******************************************************************************/ + +void write_binary_item( + FILE *fp, + int int_val, + unsigned int uint_val, + double double_val, + int type +) +{ + unsigned char uchar_val; + char char_val; + unsigned short ushort_val; + short short_val; + float float_val; + + switch (type) { + case PLY_CHAR: + char_val = (char)int_val; + fwrite (&char_val, 1, 1, fp); + break; + case PLY_SHORT: + short_val = (short)int_val; + fwrite (&short_val, 2, 1, fp); + break; + case PLY_INT: + fwrite (&int_val, 4, 1, fp); + break; + case PLY_UCHAR: + uchar_val = (unsigned char) uint_val; + fwrite (&uchar_val, 1, 1, fp); + break; + case PLY_USHORT: + ushort_val = (unsigned short)uint_val; + fwrite (&ushort_val, 2, 1, fp); + break; + case PLY_UINT: + fwrite (&uint_val, 4, 1, fp); + break; + case PLY_FLOAT: + float_val = (float) double_val; + fwrite (&float_val, 4, 1, fp); + break; + case PLY_DOUBLE: + fwrite (&double_val, 8, 1, fp); + break; + default: + fprintf (stderr, "write_binary_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Write out an item to a file as ascii characters. + +Entry: + fp - file to write to + int_val - integer version of item + uint_val - unsigned integer version of item + double_val - double-precision float version of item + type - data type to write out +******************************************************************************/ + +void write_ascii_item( + FILE *fp, + int int_val, + unsigned int uint_val, + double double_val, + int type +) +{ + switch (type) { + case PLY_CHAR: + case PLY_SHORT: + case PLY_INT: + fprintf (fp, "%d ", int_val); + break; + case PLY_UCHAR: + case PLY_USHORT: + case PLY_UINT: + fprintf (fp, "%u ", uint_val); + break; + case PLY_FLOAT: + case PLY_DOUBLE: + fprintf (fp, "%g ", double_val); + break; + default: + fprintf (stderr, "write_ascii_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Write out an item to a file as ascii characters. + +Entry: + fp - file to write to + item - pointer to item to write + type - data type that "item" points to + +Exit: + returns a double-precision float that contains the value of the written item +******************************************************************************/ + +double old_write_ascii_item(FILE *fp, char *item, int type) +{ + unsigned char *puchar; + char *pchar; + short int *pshort; + unsigned short int *pushort; + int *pint; + unsigned int *puint; + float *pfloat; + double *pdouble; + int int_value; + unsigned int uint_value; + double double_value; + + switch (type) { + case PLY_CHAR: + pchar = (char *) item; + int_value = *pchar; + fprintf (fp, "%d ", int_value); + return ((double) int_value); + case PLY_UCHAR: + puchar = (unsigned char *) item; + int_value = *puchar; + fprintf (fp, "%d ", int_value); + return ((double) int_value); + case PLY_SHORT: + pshort = (short int *) item; + int_value = *pshort; + fprintf (fp, "%d ", int_value); + return ((double) int_value); + case PLY_USHORT: + pushort = (unsigned short int *) item; + int_value = *pushort; + fprintf (fp, "%d ", int_value); + return ((double) int_value); + case PLY_INT: + pint = (int *) item; + int_value = *pint; + fprintf (fp, "%d ", int_value); + return ((double) int_value); + case PLY_UINT: + puint = (unsigned int *) item; + uint_value = *puint; + fprintf (fp, "%u ", uint_value); + return ((double) uint_value); + case PLY_FLOAT: + pfloat = (float *) item; + double_value = *pfloat; + fprintf (fp, "%g ", double_value); + return (double_value); + case PLY_DOUBLE: + pdouble = (double *) item; + double_value = *pdouble; + fprintf (fp, "%g ", double_value); + return (double_value); + default: + fprintf (stderr, "old_write_ascii_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Get the value of an item that is in memory, and place the result +into an integer, an unsigned integer and a double. + +Entry: + ptr - pointer to the item + type - data type supposedly in the item + +Exit: + int_val - integer value + uint_val - unsigned integer value + double_val - double-precision floating point value +******************************************************************************/ + +void get_stored_item( + void *ptr, + int type, + int *int_val, + unsigned int *uint_val, + double *double_val +) +{ + switch (type) { + case PLY_CHAR: + *int_val = *((char *) ptr); + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_UCHAR: + *uint_val = *((unsigned char *) ptr); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_SHORT: + *int_val = *((short int *) ptr); + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_USHORT: + *uint_val = *((unsigned short int *) ptr); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_INT: + *int_val = *((int *) ptr); + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_UINT: + *uint_val = *((unsigned int *) ptr); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_FLOAT: + *double_val = *((float *) ptr); + *int_val = (int)*double_val; + *uint_val = (unsigned int)*double_val; + break; + case PLY_DOUBLE: + *double_val = *((double *) ptr); + *int_val = (int)*double_val; + *uint_val =(unsigned int) *double_val; + break; + default: + fprintf (stderr, "get_stored_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Get the value of an item from a binary file, and place the result +into an integer, an unsigned integer and a double. + +Entry: + fp - file to get item from + type - data type supposedly in the word + +Exit: + int_val - integer value + uint_val - unsigned integer value + double_val - double-precision floating point value +******************************************************************************/ + +void get_binary_item( + FILE *fp, + int type, + int *int_val, + unsigned int *uint_val, + double *double_val +) +{ + char c[8]; + void *ptr; + + ptr = (void *) c; + + switch (type) { + case PLY_CHAR: + fread (ptr, 1, 1, fp); + *int_val = *((char *) ptr); + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_UCHAR: + fread (ptr, 1, 1, fp); + *uint_val = *((unsigned char *) ptr); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_SHORT: + fread (ptr, 2, 1, fp); + *int_val = *((short int *) ptr); + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_USHORT: + fread (ptr, 2, 1, fp); + *uint_val = *((unsigned short int *) ptr); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_INT: + fread (ptr, 4, 1, fp); + *int_val = *((int *) ptr); + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_UINT: + fread (ptr, 4, 1, fp); + *uint_val = *((unsigned int *) ptr); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_FLOAT: + fread (ptr, 4, 1, fp); + *double_val = *((float *) ptr); + *int_val = (int)*double_val; + *uint_val =(unsigned int) *double_val; + break; + case PLY_DOUBLE: + fread (ptr, 8, 1, fp); + *double_val = *((double *) ptr); + *int_val = (int)*double_val; + *uint_val = (unsigned int)*double_val; + break; + default: + fprintf (stderr, "get_binary_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Extract the value of an item from an ascii word, and place the result +into an integer, an unsigned integer and a double. + +Entry: + word - word to extract value from + type - data type supposedly in the word + +Exit: + int_val - integer value + uint_val - unsigned integer value + double_val - double-precision floating point value +******************************************************************************/ + +void get_ascii_item( + char *word, + int type, + int *int_val, + unsigned int *uint_val, + double *double_val +) +{ + switch (type) { + case PLY_CHAR: + case PLY_UCHAR: + case PLY_SHORT: + case PLY_USHORT: + case PLY_INT: + *int_val = atoi (word); + *uint_val = *int_val; + *double_val = *int_val; + break; + + case PLY_UINT: + *uint_val = strtoul (word, (char **) NULL, 10); + *int_val = *uint_val; + *double_val = *uint_val; + break; + + case PLY_FLOAT: + case PLY_DOUBLE: + *double_val = atof (word); + *int_val = (int) *double_val; + *uint_val = (unsigned int) *double_val; + break; + + default: + fprintf (stderr, "get_ascii_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Store a value into a place being pointed to, guided by a data type. + +Entry: + item - place to store value + type - data type + int_val - integer version of value + uint_val - unsigned integer version of value + double_val - double version of value + +Exit: + item - pointer to stored value +******************************************************************************/ + +void store_item ( + char *item, + int type, + int int_val, + unsigned int uint_val, + double double_val +) +{ + unsigned char *puchar; + short int *pshort; + unsigned short int *pushort; + int *pint; + unsigned int *puint; + float *pfloat; + double *pdouble; + + switch (type) { + case PLY_CHAR: + *item = (char) int_val; + break; + case PLY_UCHAR: + puchar = (unsigned char *) item; + *puchar = (unsigned char)uint_val; + break; + case PLY_SHORT: + pshort = (short *) item; + *pshort = (short)int_val; + break; + case PLY_USHORT: + pushort = (unsigned short *) item; + *pushort = (unsigned short)uint_val; + break; + case PLY_INT: + pint = (int *) item; + *pint = int_val; + break; + case PLY_UINT: + puint = (unsigned int *) item; + *puint = uint_val; + break; + case PLY_FLOAT: + pfloat = (float *) item; + *pfloat = (float)double_val; + break; + case PLY_DOUBLE: + pdouble = (double *) item; + *pdouble = double_val; + break; + default: + fprintf (stderr, "store_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Add an element to a PLY file descriptor. + +Entry: + plyfile - PLY file descriptor + words - list of words describing the element + nwords - number of words in the list +******************************************************************************/ + +void add_element (PlyFile *plyfile, char **words) +{ + PlyElement *elem; + + /* create the new element */ + elem = (PlyElement *) myalloc (sizeof (PlyElement)); + elem->name = strdup (words[1]); + elem->num = atoi (words[2]); + elem->nprops = 0; + + /* make room for new element in the object's list of elements */ + if (plyfile->nelems == 0) + plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *)); + else + plyfile->elems = (PlyElement **) realloc (plyfile->elems, + sizeof (PlyElement *) * (plyfile->nelems + 1)); + + /* add the new element to the object's list */ + plyfile->elems[plyfile->nelems] = elem; + plyfile->nelems++; +} + + +/****************************************************************************** +Return the type of a property, given the name of the property. + +Entry: + name - name of property type + +Exit: + returns integer code for property, or 0 if not found +******************************************************************************/ + +int get_prop_type(char *type_name) +{ + int i; + + for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++) + if (equal_strings (type_name, type_names[i])) + return (i); + + /* if we get here, we didn't find the type */ + return (0); +} + + +/****************************************************************************** +Add a property to a PLY file descriptor. + +Entry: + plyfile - PLY file descriptor + words - list of words describing the property + nwords - number of words in the list +******************************************************************************/ + +void add_property (PlyFile *plyfile, char **words) +{ + PlyProperty *prop; + PlyElement *elem; + + /* create the new property */ + + prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + + if (equal_strings (words[1], "list")) { /* is a list */ + prop->count_external = get_prop_type (words[2]); + prop->external_type = get_prop_type (words[3]); + prop->name = strdup (words[4]); + prop->is_list = 1; + } + else { /* not a list */ + prop->external_type = get_prop_type (words[1]); + prop->name = strdup (words[2]); + prop->is_list = 0; + } + + /* add this property to the list of properties of the current element */ + + elem = plyfile->elems[plyfile->nelems - 1]; + + if (elem->nprops == 0) + elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *)); + else + elem->props = (PlyProperty **) realloc (elem->props, + sizeof (PlyProperty *) * (elem->nprops + 1)); + + elem->props[elem->nprops] = prop; + elem->nprops++; +} + + +/****************************************************************************** +Add a comment to a PLY file descriptor. + +Entry: + plyfile - PLY file descriptor + line - line containing comment +******************************************************************************/ + +void add_comment (PlyFile *plyfile, char *line) +{ + int i; + + /* skip over "comment" and leading spaces and tabs */ + i = 7; + while (line[i] == ' ' || line[i] == '\t') + i++; + + ply_put_comment (plyfile, &line[i]); +} + + +/****************************************************************************** +Add a some object information to a PLY file descriptor. + +Entry: + plyfile - PLY file descriptor + line - line containing text info +******************************************************************************/ + +void add_obj_info (PlyFile *plyfile, char *line) +{ + int i; + + /* skip over "obj_info" and leading spaces and tabs */ + i = 8; + while (line[i] == ' ' || line[i] == '\t') + i++; + + ply_put_obj_info (plyfile, &line[i]); +} + + +/****************************************************************************** +Copy a property. +******************************************************************************/ + +void copy_property(PlyProperty *dest, PlyProperty *src) +{ + dest->name = strdup (src->name); + dest->external_type = src->external_type; + dest->internal_type = src->internal_type; + dest->offset = src->offset; + + dest->is_list = src->is_list; + dest->count_external = src->count_external; + dest->count_internal = src->count_internal; + dest->count_offset = src->count_offset; +} + + +/****************************************************************************** +Allocate some memory. + +Entry: + size - amount of memory requested (in bytes) + lnum - line number from which memory was requested + fname - file name from which memory was requested +******************************************************************************/ + +static char *my_alloc(int size, int lnum, char *fname) +{ + char *ptr; + + ptr = (char *) malloc (size); + + if (ptr == 0) { + fprintf(stderr, "Memory allocation bombed on line %d in %s\n", lnum, fname); + } + + return (ptr); +} + diff --git a/intern/bsp/test/Makefile b/intern/bsp/test/Makefile new file mode 100644 index 00000000000..17ed638d745 --- /dev/null +++ b/intern/bsp/test/Makefile @@ -0,0 +1,72 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# bsp test makefile. +# + +LIBNAME = bsp +SOURCEDIR = intern/$(LIBNAME)/test +DIR = $(OCGDIR)/$(SOURCEDIR) + +include nan_compile.mk + +DIRS = BSP_GhostTest + +include nan_subdirs.mk + +include nan_link.mk + +LIBS = $(OCGDIR)/intern/$(LIBNAME)/test/BSP_GhostTest/$(DEBUG_DIR)libBSP_GhostTest.a +LIBS += $(OCGDIR)/intern/$(LIBNAME)/$(DEBUG_DIR)libbsp.a + +SLIBS += $(NAN_MOTO)/lib/$(DEBUG_DIR)libmoto.a +SLIBS += $(NAN_GHOST)/lib/$(DEBUG_DIR)libghost.a +SLIBS += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a + +ifeq ($(OS),$(findstring $(OS), "beos darwin linux freebsd openbsd")) + LLIBS = -L/usr/X11R6/lib -lglut -pthread -lXi -lXmu +endif + +all debug:: $(LIBS) $(DIR)/$(DEBUG_DIR)BSPGhostTest + +$(DIR)/$(DEBUG_DIR)BSPGhostTest: + @echo "****> linking $@ in $(DIR)" + $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)BSPGhostTest $(LIBS) $(SLIBS) $(LLIBS) $(DADD) + +clean:: + $(RM) $(DIR)/BSPGhostTest $(DIR)/debug/BSPGhostTest + +test:: all + $(DIR)/BSPGhostTest + + + + + diff --git a/intern/container/CTR_List.h b/intern/container/CTR_List.h new file mode 100644 index 00000000000..29d7c2f8de1 --- /dev/null +++ b/intern/container/CTR_List.h @@ -0,0 +1,144 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + + +#ifndef CTR_LIST_H +#define CTR_LIST_H + +class CTR_Link { +public: + CTR_Link( + ) ; + + CTR_Link( + CTR_Link *next, + CTR_Link *prev + ) ; + + CTR_Link * + getNext( + ) const ; + + CTR_Link * + getPrev( + ) const ; + + bool + isHead( + ) const ; + + bool + isTail( + ) const ; + + void + insertBefore( + CTR_Link *link + ) ; + + void + insertAfter( + CTR_Link *link + ) ; + + void + remove( + ) ; + +private: + CTR_Link *m_next; + CTR_Link *m_prev; +}; + +class CTR_List { +public: + + CTR_List( + ) ; + + CTR_Link * + getHead( + ) const ; + + CTR_Link * + getTail( + ) const ; + + void + addHead( + CTR_Link *link + ) ; + + void + addTail( + CTR_Link *link + ) ; + +private: + CTR_Link m_head; + CTR_Link m_tail; +}; + +#endif + + + diff --git a/intern/container/CTR_Map.h b/intern/container/CTR_Map.h new file mode 100644 index 00000000000..348807212b6 --- /dev/null +++ b/intern/container/CTR_Map.h @@ -0,0 +1,152 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef CTR_MAP_H + +#define CTR_MAP_H + +template <class Key, class Value> +class CTR_Map { +private: + struct Entry { + Entry (Entry *next, Key key, Value value) : + m_next(next), + m_key(key), + m_value(value) {} + + Entry *m_next; + Key m_key; + Value m_value; + }; + +public: + CTR_Map(int num_buckets = 100) : m_num_buckets(num_buckets) { + m_buckets = new Entry *[num_buckets]; + for (int i = 0; i < num_buckets; ++i) { + m_buckets[i] = 0; + } + } + + int size() { + int count=0; + for (int i=0;i<m_num_buckets;i++) + { + Entry* bucket = m_buckets[i]; + while(bucket) + { + bucket = bucket->m_next; + count++; + } + } + return count; + } + + Value* at(int index) { + int count=0; + for (int i=0;i<m_num_buckets;i++) + { + Entry* bucket = m_buckets[i]; + while(bucket) + { + if (count==index) + { + return &bucket->m_value; + } + bucket = bucket->m_next; + count++; + } + } + return 0; + } + + void clear() { + for (int i = 0; i < m_num_buckets; ++i) { + Entry *entry_ptr = m_buckets[i]; + + while (entry_ptr != 0) { + Entry *tmp_ptr = entry_ptr->m_next; + delete entry_ptr; + entry_ptr = tmp_ptr; + } + m_buckets[i] = 0; + } + } + + ~CTR_Map() { + clear(); + delete [] m_buckets; + } + + void insert(const Key& key, const Value& value) { + Entry *entry_ptr = m_buckets[key.hash() % m_num_buckets]; + while ((entry_ptr != 0) && !(key == entry_ptr->m_key)) { + entry_ptr = entry_ptr->m_next; + } + + if (entry_ptr != 0) { + entry_ptr->m_value = value; + } + else { + Entry **bucket = &m_buckets[key.hash() % m_num_buckets]; + *bucket = new Entry(*bucket, key, value); + } + } + + void remove(const Key& key) { + Entry **entry_ptr = &m_buckets[key.hash() % m_num_buckets]; + while ((*entry_ptr != 0) && !(key == (*entry_ptr)->m_key)) { + entry_ptr = &(*entry_ptr)->m_next; + } + + if (*entry_ptr != 0) { + Entry *tmp_ptr = (*entry_ptr)->m_next; + delete *entry_ptr; + *entry_ptr = tmp_ptr; + } + } + + Value *operator[](Key key) { + Entry *bucket = m_buckets[key.hash() % m_num_buckets]; + while ((bucket != 0) && !(key == bucket->m_key)) { + bucket = bucket->m_next; + } + return bucket != 0 ? &bucket->m_value : 0; + } + +private: + int m_num_buckets; + Entry **m_buckets; +}; + +#endif + + + diff --git a/intern/container/CTR_TaggedIndex.h b/intern/container/CTR_TaggedIndex.h new file mode 100644 index 00000000000..026819d465c --- /dev/null +++ b/intern/container/CTR_TaggedIndex.h @@ -0,0 +1,226 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * Simple tagged index class. + */ + +#ifndef NAN_INCLUDED_CTR_TaggedIndex_h +#define NAN_INCLUDED_CTR_TaggedIndex_h + +/** + * This class is supposed to be a simple tagged index class. If these + * were indices into a mesh then we would never need 32 bits for such indices. + * It is often handy to have a few extra bits around to mark objects etc. We + * steal a few bits of CTR_TaggedIndex objects for this purpose. From the outside + * it will behave like a standard unsigned int but just carry the extra tag + * information around with it. + */ + +#include <functional> + +enum { + + empty_tag = 0x0, + empty_index = 0xffffffff +}; + +template < + int tag_shift, + int index_mask +> class CTR_TaggedIndex { +public: + CTR_TaggedIndex( + ) : + m_val ((empty_tag << tag_shift) | (empty_index & index_mask)) + { + } + + CTR_TaggedIndex( + const int val + ) : + m_val ((val & index_mask) | ((empty_tag << tag_shift) & (~index_mask))) { + } + + CTR_TaggedIndex( + const unsigned int val + ) : + m_val ((val & index_mask) | ((empty_tag << tag_shift) & (~index_mask))) { + } + + CTR_TaggedIndex( + const long int val + ) : + m_val ( ((long int) val & index_mask) + | ( (empty_tag << tag_shift) + & (~index_mask)) ) { + } + + CTR_TaggedIndex( + const long unsigned int val + ) : + m_val ( ((long unsigned int)val & index_mask) + | ( (empty_tag << tag_shift) + & (~index_mask) ) ) { + } + + + CTR_TaggedIndex( + const CTR_TaggedIndex &my_index + ): + m_val(my_index.m_val) + { + } + + bool + operator == ( + const CTR_TaggedIndex& rhs + ) const { + + return ((this->m_val & index_mask) == (rhs.m_val & index_mask)); + } + + operator unsigned int () const { + return m_val & index_mask; + } + + operator unsigned long int () const { + return (unsigned long int)(m_val & index_mask); + } + + operator int () const { + return int(m_val & index_mask); + } + + operator long int () const { + return (long int)(m_val & index_mask); + } + + bool + IsEmpty( + ) const { + return ((m_val & index_mask) == (empty_index & index_mask)); + } + + + static + CTR_TaggedIndex + Empty( + ) { + return CTR_TaggedIndex(); + } + + void + Invalidate( + ) { + m_val = (empty_tag << tag_shift) | (empty_index & index_mask); + } + + + unsigned int + Tag ( + ) const { + return m_val >> tag_shift; + } + + void + SetTag( + unsigned int tag + ) { + m_val = (m_val & index_mask) | ((tag << tag_shift) & (~index_mask)); + } + + void + EmptyTag( + ) { + m_val = (m_val & index_mask) | ((empty_tag << tag_shift) & (~index_mask)); + } + + bool + IsEmptyTag( + ) const { + return (Tag() == Empty().Tag()); + } + + // functionals + + struct greater : std::binary_function<CTR_TaggedIndex, CTR_TaggedIndex, bool> + { + bool + operator()( + const CTR_TaggedIndex& a, + const CTR_TaggedIndex& b + ) const { + return (int(a) > int(b)); + } + }; + + +private : + CTR_TaggedIndex( + const CTR_TaggedIndex *index + ) {}; + + unsigned int m_val; + + +}; + + +#endif + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/intern/container/CTR_TaggedSetOps.h b/intern/container/CTR_TaggedSetOps.h new file mode 100644 index 00000000000..fc12f6fed04 --- /dev/null +++ b/intern/container/CTR_TaggedSetOps.h @@ -0,0 +1,287 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_LOD_TaggedSetOps_h + +#define NAN_INCLUDED_LOD_TaggedSetOps_h + +#include "MEM_NonCopyable.h" +#include <vector> + +/** + * This class contains some utility functions for finding the intersection, + * union, and difference of a collection of stl vector of indices into + * a set of primitives. + * + * These are mainly used as helper functions in the decimation and bsp + * libraries. + * + * This template class assumes that each value of type IndexType encountered + * in the list is a valid index into an array of primitives. This is not + * checked at run-time and is left to the user to insure. Prmitives of + * type ObjectType must have the following public methods to be used by + * this template class: + * + * int + * OpenTag(void) --- return a persistent tag value for the primitive + * + * void + * SetOpenTag(int bla) --- set the persistent tag value for this primitive to bla. + * + * bool + * SelectTag() --- return a persistent boolean tag for this primitive + * + * void + * SetSelectTag(bool bla) --- set the persistent boolean tag for this primitive to bla. + * + * Here persistent means that the tag should be associated with the object for the + * entire lifetime of the primitive. Again none of this stuff is enforced you have + * to make sure that your primitives do the right thing. Often these tags can be + * cunningly stowed away inside some of the spare bits in the primitive. See + * CTR_TaggedIndex for such a class. + * + */ + +template +<class IndexType, class ObjectType> +class CTR_TaggedSetOps : public MEM_NonCopyable { + +public : + + static + void + Intersect( + const std::vector< std::vector<IndexType> > &index_list, + std::vector<ObjectType> &primitives, + std::vector<IndexType> &output, + unsigned int mask, + unsigned int shift + ) { + + // iterate through vectors in index_list + // iterate through individual members of each vector + // mark each obejct that the index points to + + std::vector< std::vector<IndexType> >::const_iterator last_vector = index_list.end(); + std::vector< std::vector<IndexType> >::const_iterator start_vector = index_list.begin(); + + // FIXME some temporary space + + std::vector<IndexType> temp_union; + temp_union.reserve(64); + + int tag_num = 0; + + for (; start_vector != last_vector; ++start_vector) { + + std::vector<IndexType>::const_iterator last_index = start_vector->end(); + std::vector<IndexType>::const_iterator start_index = start_vector->begin(); + + for (; start_index != last_index; ++start_index) { + + ObjectType & prim = primitives[*start_index]; + + if (!prim.OpenTag()) { + // compute the union + temp_union.push_back(*start_index); + } + int tag = prim.OpenTag(); + tag = (tag & mask) >> shift; + tag += 1; + prim.SetOpenTag((prim.OpenTag() & ~mask)| ((tag << shift) & mask)); + } + + ++tag_num; + } + + // now iterate through the union and pull out all those with the right tag + + std::vector<IndexType>::const_iterator last_index = temp_union.end(); + std::vector<IndexType>::const_iterator start_index = temp_union.begin(); + + for (; start_index != last_index; ++start_index) { + + ObjectType & prim = primitives[*start_index]; + + if (prim.OpenTag() == tag_num) { + //it's part of the intersection! + + output.push_back(*start_index); + // because we're iterating through the union + // it's safe to remove the tag at this point + + prim.SetOpenTag(prim.OpenTag() & ~mask); + } + } + }; + + // note not a strict set intersection! + // if x appears twice in b and is part of the intersection + // it will appear twice in the intersection + + static + void + IntersectPair( + const std::vector<IndexType> &a, + const std::vector<IndexType> &b, + std::vector<ObjectType> &primitives, + std::vector<IndexType> &output + ) { + + std::vector<IndexType>::const_iterator last_index = a.end(); + std::vector<IndexType>::const_iterator start_index = a.begin(); + + for (; start_index != last_index; ++start_index) { + ObjectType & prim = primitives[*start_index]; + prim.SetSelectTag(true); + } + last_index = b.end(); + start_index = b.begin(); + + for (; start_index != last_index; ++start_index) { + ObjectType & prim = primitives[*start_index]; + if (prim.SelectTag()) { + output.push_back(*start_index); + } + } + // deselect + last_index = a.end(); + start_index = a.begin(); + + for (; start_index != last_index; ++start_index) { + ObjectType & prim = primitives[*start_index]; + prim.SetSelectTag(false); + } + }; + + + static + void + Union( + std::vector< std::vector<IndexType> > &index_list, + std::vector<ObjectType> &primitives, + std::vector<IndexType> &output + ) { + + // iterate through vectors in index_list + // iterate through individual members of each vector + // mark each obejct that the index points to + + std::vector< std::vector<IndexType> >::const_iterator last_vector = index_list.end(); + std::vector< std::vector<IndexType> >::iterator start_vector = index_list.begin(); + + for (; start_vector != last_vector; ++start_vector) { + + std::vector<IndexType>::const_iterator last_index = start_vector->end(); + std::vector<IndexType>::iterator start_index = start_vector->begin(); + + for (; start_index != last_index; ++start_index) { + + ObjectType & prim = primitives[*start_index]; + + if (!prim.SelectTag()) { + // compute the union + output.push_back(*start_index); + prim.SetSelectTag(true); + } + } + } + + // now iterate through the union and reset the tags + + std::vector<IndexType>::const_iterator last_index = output.end(); + std::vector<IndexType>::iterator start_index = output.begin(); + + for (; start_index != last_index; ++start_index) { + + ObjectType & prim = primitives[*start_index]; + prim.SetSelectTag(false); + } + } + + + static + void + Difference( + std::vector< IndexType> &a, + std::vector< IndexType> &b, + std::vector<ObjectType> &primitives, + std::vector< IndexType> &output + ) { + + // iterate through b mark all + // iterate through a and add to output all unmarked + + std::vector<IndexType>::const_iterator last_index = b.end(); + std::vector<IndexType>::iterator start_index = b.begin(); + + for (; start_index != last_index; ++start_index) { + + ObjectType & prim = primitives[*start_index]; + prim.SetSelectTag(true); + } + + last_index = a.end(); + start_index = a.begin(); + + for (; start_index != last_index; ++start_index) { + + ObjectType & prim = primitives[*start_index]; + if (!prim.SelectTag()) { + output.push_back(*start_index); + } + } + + // clean up the tags + + last_index = b.end(); + start_index = b.begin(); + + for (; start_index != last_index; ++start_index) { + + ObjectType & prim = primitives[*start_index]; + prim.SetSelectTag(false); + } + }; + +private : + + // private constructor - this class is not meant for + // instantiation + + CTR_TaggedSetOps(); + +}; + + + +#endif + diff --git a/intern/container/CTR_UHeap.h b/intern/container/CTR_UHeap.h new file mode 100644 index 00000000000..251e020aba3 --- /dev/null +++ b/intern/container/CTR_UHeap.h @@ -0,0 +1,303 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * + * @author Laurence + * @mainpage CTR_UHeap an updatable heap template class (also + * known as an updatable priority queue) + * + * Todo: Make CTR_UHeapable a template class with m_key the + * template parameter, so that arbitrary value types with + * operators (=,>) defined can be used. + * + */ + +#ifndef NAN_INCLUDED_CTR_UHeap_h +#define NAN_INCLUDED_CTR_UHeap_h + +#include <vector> +#include "MEM_NonCopyable.h" + +class CTR_UHeapable { + +public : + int & + HeapPos( + ){ + return m_ind; + }; + float & + HeapKey( + ) { + return m_key; + }; + + const + float & + HeapKey( + ) const { + return m_key; + }; + + const + int & + HeapPos( + ) const { + return m_ind; + }; + +private : + + float m_key; + int m_ind; + +protected : + + CTR_UHeapable( + ) : m_key (0), + m_ind (0) + { + }; + + ~CTR_UHeapable( + ){ + }; +}; + +template <class HeapType> +class CTR_UHeap : public MEM_NonCopyable +{ + +public: + + static + CTR_UHeap * + New( + ) { + return new CTR_UHeap(); + } + + void + MakeHeap( + HeapType *base + ) { + int i; + int start = Parent(m_vector.size()-1); + for (i = start; i >=0; --i) { + DownHeap(base,i); + } + }; + + void + Insert( + HeapType *base, + int elem + ) { + // add element to vector + m_vector.push_back(elem); + base[elem].HeapPos() = m_vector.size()-1; + + // push the element up the heap + UpHeap(base,m_vector.size()-1); + } + + // access to the vector for initial loading of elements + + std::vector<int> & + HeapVector( + ) { + return m_vector; + }; + + + void + Remove( + HeapType *base, + int i + ) { + + // exchange with last element - pop last + // element and move up or down the heap as appropriate + if (m_vector.empty()) { + assert(false); + } + + if (i != int(m_vector.size())-1) { + + Swap(base,i,m_vector.size() - 1); + m_vector.pop_back(); + + if (!m_vector.empty()) { + UpHeap(base,i); + DownHeap(base,i); + } + } else { + m_vector.pop_back(); + } + } + + int + Top( + ) const { + if (m_vector.empty()) return -1; + return m_vector[0]; + } + + + void + SC_Heap( + HeapType *base + ) { + int i; + for (i = 1; i < int(m_vector.size()) ; i++) { + + CTR_UHeapable * elem = base + m_vector[i]; + CTR_UHeapable * p_elem = base + m_vector[Parent(i)]; + + assert(p_elem->HeapKey() >= elem->HeapKey()); + assert(elem->HeapPos() == i); + } + + }; + + + ~CTR_UHeap( + ) { + }; + + +private: + + CTR_UHeap( + ) { + }; + + + std::vector<int> m_vector; + +private: + void + Swap( + HeapType *base, + int i, + int j + ){ + std::swap(m_vector[i],m_vector[j]); + + CTR_UHeapable *heap_i = base + m_vector[i]; + CTR_UHeapable *heap_j = base + m_vector[j]; + + // Exchange heap positions + heap_i->HeapPos() = i; + heap_j->HeapPos() = j; + } + + int + Parent( + unsigned int i + ) { + return (i-1) >> 1; + } + int + Left( + int i + ) { + return (i<<1)+1; + } + + int + Right( + int i + ) { + return (i<<1)+2; + } + + float + HeapVal( + HeapType *base, + int i + ) { + return base[m_vector[i]].HeapKey(); + } + + void + DownHeap( + HeapType *base, + int i + ) { + int heap_size = m_vector.size(); + + int l = Left(i); + int r = Right(i); + + int largest; + if (l < heap_size && HeapVal(base,l) > HeapVal(base,i)) { + largest = l; + } else { + largest = i; + } + + if (r < heap_size && HeapVal(base,r) > HeapVal(base,largest)) { + largest = r; + } + + if (largest != i) { + // exchange i and largest + Swap(base,i,largest); + DownHeap(base,largest); + } + } + + void + UpHeap( + HeapType *base, + int i + ) { + + // swap parents untill it's found a place in the heap < it's parent or + // top of heap + + while (i > 0) { + int p = Parent(i); + if (HeapVal(base,i) < HeapVal(base,p)) { + break; + } + Swap(base,p,i); + i = p; + } + } +}; + +#endif diff --git a/intern/container/Makefile b/intern/container/Makefile new file mode 100644 index 00000000000..31ca8e8ae1a --- /dev/null +++ b/intern/container/Makefile @@ -0,0 +1,52 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# container main makefile. +# + +include nan_definitions.mk + +LIBNAME = container +SOURCEDIR = intern/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = intern +#not yet TESTDIRS = test + +include nan_subdirs.mk + +install: all debug + @[ -d $(NAN_CONTAINER) ] || mkdir $(NAN_CONTAINER) + @[ -d $(NAN_CONTAINER)/include ] || mkdir $(NAN_CONTAINER)/include + @[ -d $(NAN_CONTAINER)/lib ] || mkdir $(NAN_CONTAINER)/lib + @[ -d $(NAN_CONTAINER)/lib/debug ] || mkdir $(NAN_CONTAINER)/lib/debug + cp -f $(DIR)/libcontainer.a $(NAN_CONTAINER)/lib/ + cp -f $(DIR)/debug/libcontainer.a $(NAN_CONTAINER)/lib/debug + cp -f *.h $(NAN_CONTAINER)/include/ + diff --git a/intern/container/intern/CTR_List.cpp b/intern/container/intern/CTR_List.cpp new file mode 100644 index 00000000000..2e8c1bb13d2 --- /dev/null +++ b/intern/container/intern/CTR_List.cpp @@ -0,0 +1,149 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "CTR_List.h" + + +CTR_Link:: +CTR_Link( +) : + m_next(0), + m_prev(0) +{ +} + +CTR_Link:: +CTR_Link( + CTR_Link *next, + CTR_Link *prev +) : + m_next(next), + m_prev(prev) +{ +} + + CTR_Link * +CTR_Link:: +getNext( +) const { + return m_next; +} + + CTR_Link * +CTR_Link:: +getPrev( +) const { + return m_prev; +} + + bool +CTR_Link:: +isHead( +) const { + return m_prev == 0; +} + + bool +CTR_Link:: +isTail( +) const { + return m_next == 0; +} + + void +CTR_Link:: +insertBefore( + CTR_Link *link +) { + m_next = link; + m_prev = link->m_prev; + m_next->m_prev = this; + m_prev->m_next = this; +} + + void +CTR_Link:: +insertAfter( + CTR_Link *link +) { + m_next = link->m_next; + m_prev = link; + m_next->m_prev = this; + m_prev->m_next = this; +} + + void +CTR_Link:: +remove( +) { + m_next->m_prev = m_prev; + m_prev->m_next = m_next; +} + + +CTR_List:: +CTR_List( +) : + m_head(&m_tail, 0), + m_tail(0, &m_head) +{ +} + + CTR_Link * +CTR_List:: +getHead( +) const { + return m_head.getNext(); +} + + CTR_Link * +CTR_List:: +getTail( +) const { + return m_tail.getPrev(); +} + + void +CTR_List:: +addHead( + CTR_Link *link +) { + link->insertAfter(&m_head); +} + + void +CTR_List:: +addTail( + CTR_Link *link +) { + link->insertBefore(&m_tail); +} + diff --git a/intern/container/intern/Makefile b/intern/container/intern/Makefile new file mode 100644 index 00000000000..292df5b7cbc --- /dev/null +++ b/intern/container/intern/Makefile @@ -0,0 +1,42 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# container intern Makefile +# + +LIBNAME = container +DIR = $(OCGDIR)/intern/$(LIBNAME) + +include nan_compile.mk + +CCFLAGS += $(LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I.. + diff --git a/intern/container/make/msvc_6_0/container.dsp b/intern/container/make/msvc_6_0/container.dsp new file mode 100644 index 00000000000..05faf85d1d3 --- /dev/null +++ b/intern/container/make/msvc_6_0/container.dsp @@ -0,0 +1,133 @@ +# Microsoft Developer Studio Project File - Name="container" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=container - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "container.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "container.mak" CFG="container - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "container - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "container - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "container - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x413 /d "NDEBUG" +# ADD RSC /l 0x413 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Release\libcontainer.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\lib\windows\container\include\" ECHO Copying lib COPY "Release\libcontainer.lib" "..\..\..\..\lib\windows\container\lib\libcontainer.a" ECHO Done +# End Special Build Tool + +!ELSEIF "$(CFG)" == "container - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x413 /d "_DEBUG" +# ADD RSC /l 0x413 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\libcontainer.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\lib\windows\container\include\" ECHO Copying lib COPY "Debug\libcontainer.lib" "..\..\..\..\lib\windows\container\lib\debug\libcontainer.a" ECHO Copying Debug info. COPY "Debug\vc60.*" "..\..\..\..\lib\windows\container\lib\debug\" ECHO Done +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "container - Win32 Release" +# Name "container - Win32 Debug" +# Begin Group "intern" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\intern\CTR_List.cpp + +!IF "$(CFG)" == "container - Win32 Release" + +# ADD CPP /I "../extern" /I "../../" + +!ELSEIF "$(CFG)" == "container - Win32 Debug" + +# ADD CPP /I "../../" + +!ENDIF + +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\CTR_List.h +# End Source File +# Begin Source File + +SOURCE=..\..\CTR_Map.h +# End Source File +# Begin Source File + +SOURCE=..\..\CTR_TaggedIndex.h +# End Source File +# Begin Source File + +SOURCE=..\..\CTR_TaggedSetOps.h +# End Source File +# Begin Source File + +SOURCE=..\..\CTR_UHeap.h +# End Source File +# End Target +# End Project diff --git a/intern/container/make/msvc_6_0/container.dsw b/intern/container/make/msvc_6_0/container.dsw new file mode 100644 index 00000000000..adaf6dd202e --- /dev/null +++ b/intern/container/make/msvc_6_0/container.dsw @@ -0,0 +1,30 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "container"=.\container.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/intern/decimation/Makefile b/intern/decimation/Makefile new file mode 100644 index 00000000000..f0d9567a618 --- /dev/null +++ b/intern/decimation/Makefile @@ -0,0 +1,52 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# decimation main makefile. +# + +include nan_definitions.mk + +LIBNAME = decimation +SOURCEDIR = intern/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = intern +TESTDIRS = test + +include nan_subdirs.mk + +install: all debug + @[ -d $(NAN_DECIMATION) ] || mkdir $(NAN_DECIMATION) + @[ -d $(NAN_DECIMATION)/include ] || mkdir $(NAN_DECIMATION)/include + @[ -d $(NAN_DECIMATION)/lib ] || mkdir $(NAN_DECIMATION)/lib + @[ -d $(NAN_DECIMATION)/lib/debug ] || mkdir $(NAN_DECIMATION)/lib/debug + cp -f $(DIR)/libdecimation.a $(NAN_DECIMATION)/lib/ + cp -f $(DIR)/debug/libdecimation.a $(NAN_DECIMATION)/lib/debug/ + cp -f extern/*.h $(NAN_DECIMATION)/include/ + diff --git a/intern/decimation/extern/LOD_decimation.h b/intern/decimation/extern/LOD_decimation.h new file mode 100644 index 00000000000..7a74dde165a --- /dev/null +++ b/intern/decimation/extern/LOD_decimation.h @@ -0,0 +1,119 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * @author Laurence Bourn + * @date 6/7/2001 + * + * This is the external interface for the decimation module. + */ + +#ifndef NAN_INCLUDED_LOD_decimation_h +#define NAN_INCLUDED_LOD_decimation_h + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * External decimation structure + */ + +typedef struct LOD_Decimation_Info { + float * vertex_buffer; + float * vertex_normal_buffer; + int * triangle_index_buffer; + int vertex_num; + int face_num; + void * intern; +} LOD_Decimation_Info; + +typedef LOD_Decimation_Info* LOD_Decimation_InfoPtr; + +/** + * Create internal mesh representation from + * LOD_Decimation_Info structure. + * @return 1 on successful loading + * @return 0 on failure + * @warning This should be changed to return an enumeration + * detailing the error encountered + */ + +extern int LOD_LoadMesh(LOD_Decimation_InfoPtr info); + +/** + * Allocate and Compute internal data strucures required for + * decimation. + * @return 1 on successful computation of data + * @return 0 on failure + * @warning This should be changed to return an enumeration + * detailing the error encountered + */ + +extern int LOD_PreprocessMesh(LOD_Decimation_InfoPtr info); + +/** + * Once both the stages above have been completed + * this function collapses a single edge in the mesh. + * The LOD_Decimation_Info structure is updated + * to represent the new mesh. + * @return 1 if an edge was collapsed. + * @return 0 if no suitable edge was found to be collapsable + * You should stop calling this method in this case + * @warning Do not expect that the order of polygons, vertices or + * vertex normals will be preserved by this operation. This function + * returns a packed array of polygons and vertices and so necessarily + * the order will be different. This means you should not expect to + * find the same polygon in the same place in the polygon array after + * this function has been called. + */ + +extern int LOD_CollapseEdge(LOD_Decimation_InfoPtr info); + +/** + * Free any memory the decimation process used + * during the decimation process + * @return 1 if internal data successfully freed + * @return 0 if no data was freed + */ + +extern int LOD_FreeDecimationData(LOD_Decimation_InfoPtr); + +#ifdef __cplusplus +} +#endif + +#endif // NAN_INCLUDED_LOD_decimation_h + + + diff --git a/intern/decimation/intern/LOD_DecimationClass.h b/intern/decimation/intern/LOD_DecimationClass.h new file mode 100644 index 00000000000..7df294daaee --- /dev/null +++ b/intern/decimation/intern/LOD_DecimationClass.h @@ -0,0 +1,118 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_LOD_DecimationClass_h + +#define NAN_INCLUDED_LOD_DecimationClass_h + +#include "MEM_SmartPtr.h" +#include "MEM_NonCopyable.h" + +#include "LOD_ManMesh2.h" +#include "LOD_QSDecimator.h" +#include "LOD_ExternNormalEditor.h" +#include "../extern/LOD_decimation.h" +#include "LOD_ExternBufferEditor.h" + + +class LOD_DecimationClass : public MEM_NonCopyable +{ +public : + + enum { + e_not_loaded, + e_loaded, + e_preprocessed + } m_e_decimation_state; + + + static + LOD_DecimationClass * + New( + LOD_Decimation_InfoPtr extern_info + ) { + // create everything + + MEM_SmartPtr<LOD_DecimationClass> output(new LOD_DecimationClass()); + MEM_SmartPtr<LOD_ManMesh2> mesh(LOD_ManMesh2::New()); + MEM_SmartPtr<LOD_ExternBufferEditor> extern_editor(LOD_ExternBufferEditor::New(extern_info)); + + if (mesh == NULL || extern_editor == NULL) return NULL; + MEM_SmartPtr<LOD_ExternNormalEditor> normals(LOD_ExternNormalEditor::New(extern_info,mesh.Ref())); + + if (normals == NULL) return NULL; + MEM_SmartPtr<LOD_QSDecimator> decimator(LOD_QSDecimator::New( + mesh.Ref(), + normals.Ref(), + extern_editor.Ref() + )); + if (decimator == NULL || output == NULL) return NULL; + + output->m_mesh = mesh.Release(); + output->m_decimator = decimator.Release(); + output->m_normals = normals.Release(); + output->m_extern_editor = extern_editor.Release(); + + return output.Release(); + } + + LOD_ManMesh2 & + Mesh( + ){ + return m_mesh.Ref(); + } + + LOD_QSDecimator & + Decimator( + ) { + return m_decimator.Ref(); + } + + LOD_ExternNormalEditor & + FaceEditor( + ){ + return m_normals.Ref(); + } + +private : + + LOD_DecimationClass( + ) : m_e_decimation_state(e_not_loaded) { + }; + + MEM_SmartPtr<LOD_ManMesh2> m_mesh; + MEM_SmartPtr<LOD_QSDecimator> m_decimator; + MEM_SmartPtr<LOD_ExternNormalEditor> m_normals; + MEM_SmartPtr<LOD_ExternBufferEditor> m_extern_editor; +}; + + +#endif diff --git a/intern/decimation/intern/LOD_EdgeCollapser.cpp b/intern/decimation/intern/LOD_EdgeCollapser.cpp new file mode 100644 index 00000000000..4168a2ae371 --- /dev/null +++ b/intern/decimation/intern/LOD_EdgeCollapser.cpp @@ -0,0 +1,408 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "LOD_EdgeCollapser.h" + +#include "LOD_ManMesh2.h" +#include "CTR_TaggedSetOps.h" +#include <algorithm> +#include <functional> + + +using namespace std; + + + LOD_EdgeCollapser * +LOD_EdgeCollapser:: +New( +){ + return new LOD_EdgeCollapser(); +} + + + bool +LOD_EdgeCollapser:: +TJunctionTest( + LOD_ManMesh2 &mesh, + vector<LOD_EdgeInd> &e_v0v1, + LOD_EdgeInd collapse_edge +){ + + // we need to copy the egdes in e_v0v1 from the mesh + // into a new buffer -> we are going to modify them + + int original_size = e_v0v1.size(); + if (original_size == 0) return true; + + vector<LOD_Edge> &edge_set = mesh.EdgeSet(); + + LOD_VertexInd c_v0 = edge_set[collapse_edge].m_verts[0]; + LOD_VertexInd c_v1 = edge_set[collapse_edge].m_verts[1]; + + vector<LOD_Edge> temp_edges; + temp_edges.reserve(e_v0v1.size()); + + vector<LOD_EdgeInd>::iterator edge_it = e_v0v1.begin(); + vector<LOD_EdgeInd>::const_iterator edge_end = e_v0v1.end(); + + for (;edge_it != edge_end; ++edge_it) { + temp_edges.push_back(edge_set[*edge_it]); + } + + // in the copied edges replace all instances of c_v0 with c_v1 + + vector<LOD_Edge>::iterator e_it = temp_edges.begin(); + vector<LOD_Edge>::const_iterator e_it_end = temp_edges.end(); + + for (; e_it != e_it_end; ++e_it) { + + if (e_it->m_verts[0] == c_v0) { + e_it->m_verts[0] = c_v1; + } + if (e_it->m_verts[1] == c_v0) { + e_it->m_verts[1] = c_v1; + } + + // normalize the edge + if (int(e_it->m_verts[0]) > int(e_it->m_verts[1])) { + LOD_EdgeInd temp = e_it->m_verts[0]; + e_it->m_verts[0] = e_it->m_verts[1]; + e_it->m_verts[1] = temp; + } + } + + // sort the edges using the edge less functional + + sort(temp_edges.begin(),temp_edges.end(),LOD_EdgeCollapser::less()); + // count the unique edges. + + e_it = temp_edges.begin(); + e_it_end = temp_edges.end(); + + int coincedent_edges = 0; + + vector<LOD_Edge>::const_iterator last_edge = e_it; + ++e_it; + + for (; e_it != e_it_end; ++e_it) { + + if ((e_it->m_verts[0] == last_edge->m_verts[0]) && + (e_it->m_verts[1] == last_edge->m_verts[1]) + ) { + ++coincedent_edges; + } + last_edge = e_it; + } + + // now if the collapse edge is a boundary edges + // then we are alloved at most one coincedent edge + + // otherwise at most 2 coincedent edges + + if (edge_set[collapse_edge].BoundaryEdge()) { + return (coincedent_edges > 1); + } else { + return (coincedent_edges > 2); + } + + +} + + + + bool +LOD_EdgeCollapser:: +CollapseEdge( + LOD_EdgeInd ei, + LOD_ManMesh2 &mesh, + vector<LOD_EdgeInd> & degenerate_edges, + vector<LOD_FaceInd> & degenerate_faces, + vector<LOD_VertexInd> & degenerate_vertices, + vector<LOD_EdgeInd> & new_edges, + vector<LOD_FaceInd> & update_faces, + vector<LOD_VertexInd> & update_vertices +){ + + vector<LOD_Vertex> &verts = mesh.VertexSet(); + vector<LOD_Edge> &edges = mesh.EdgeSet(); + vector<LOD_TriFace> &faces = mesh.FaceSet(); + + // shouldn't do this (use mesh interface instead!) + LOD_VertexInd v0_ind = edges[ei].m_verts[0]; + LOD_VertexInd v1_ind = edges[ei].m_verts[1]; +#if 0 + LOD_Vertex &v0 = verts[v0_ind]; + LOD_Vertex &v1 = verts[v1_ind]; +#endif + vector<vector<LOD_EdgeInd> > e_v01(2); + e_v01[0].reserve(32); + e_v01[1].reserve(32); + + mesh.VertexEdges(v0_ind,e_v01[0]); + mesh.VertexEdges(v1_ind,e_v01[1]); + + + // compute the union of e_v0 and e_v1 -> this is the degenerate edges of the collapse + // we remove old edges and replace edges inside the collapse zone with new ones + + CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::Union(e_v01,edges,degenerate_edges); + + vector< vector<LOD_FaceInd> > p_v01(2); + p_v01[0].reserve(32); + p_v01[1].reserve(32); + + mesh.VertexFaces(v0_ind,p_v01[0]); + mesh.VertexFaces(v1_ind,p_v01[1]); + + // compute the union of p_v0 anf p_v1 + vector<LOD_FaceInd> p_v0v1; + p_v0v1.reserve(32); + + CTR_TaggedSetOps<LOD_FaceInd,LOD_TriFace>::Union(p_v01,faces,p_v0v1); + + // compute the union of all the edges in p_v0v1 this is the collapse zone + + vector<vector<LOD_EdgeInd> > e_input_vectors(p_v0v1.size()); + + vector<LOD_FaceInd>::iterator p_v0v1_end = p_v0v1.end(); + vector<LOD_FaceInd>::iterator p_v0v1_start = p_v0v1.begin(); + + vector<vector<LOD_FaceInd> >::iterator vector_insert_it = e_input_vectors.begin(); + + for (;p_v0v1_start != p_v0v1_end; ++p_v0v1_start , ++vector_insert_it) { + mesh.FaceEdges(*p_v0v1_start,*vector_insert_it); + } + + vector<LOD_EdgeInd> collapse_zone; + collapse_zone.reserve(32); + + CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::Union(e_input_vectors,edges,collapse_zone); + + // compute the ring edges = collpase_zone - e_v0v1 + + vector<LOD_EdgeInd> edge_ring; + edge_ring.reserve(32); + + CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::Difference(collapse_zone,degenerate_edges,edges,edge_ring); + + // T Junction test + ////////////////// + // At this point we check to see if any of the polygons + // in p_v0v1 are coninceddent - this leads + // to errors later on if we try and insert a polygon + // into the mesh to an edge which already has 2 polygons. + + // not that t junctions occur naturally from edge collapses + // and are not just the result of coincedent polygons + // for example consider collapsing an edge that forms part + // of a triangular bottle neck. + + // Really we need to make sure that we don't create t-junctions. + + // I think that a sufficient test is to check the number of + // coincedent edge pairs after a collapse. If it is more than 2 + // then collapsing the edge may result in an undeleted edge + // sharing more than 2 polygons. This test probably is too + // restictive though. + + // To perform this test we need to make a copy of the edges + // in e_v0v1. We then apply the contraction to these edge + // copies. Sort them using a function that places coincedent + // edges next to each other. And then count the number + // of coincedent pairs. + + // Of course we have to do this test before we change any of the + // mesh -> so we can back out safely. + + if (TJunctionTest(mesh,degenerate_edges,ei)) return false; + + // Compute the set of possibly degenerate vertices + // this is the union of all the vertices of polygons + // of v0 and v1 + + vector<LOD_FaceInd>::iterator face_it = p_v0v1.begin(); + vector<LOD_FaceInd>::const_iterator face_end = p_v0v1.end(); + + + vector<vector<LOD_VertexInd> > p_v0v1_vertices(p_v0v1.size()); + + for (int i = 0; face_it != face_end; ++face_it, ++i) { + mesh.FaceVertices(*face_it,p_v0v1_vertices[i]); + } + + vector<LOD_VertexInd> vertex_ring; + vertex_ring.reserve(32); + + CTR_TaggedSetOps<LOD_VertexInd,LOD_Vertex>::Union(p_v0v1_vertices,verts,vertex_ring); + + // remove all the internal edges e_v0v1 from the mesh. + // for each edge remove the egde from it's vertices edge lists. + + vector<LOD_EdgeInd>::iterator edge_it = degenerate_edges.begin(); + vector<LOD_EdgeInd>::const_iterator edge_end = degenerate_edges.end(); + + for (; edge_it != edge_end; ++edge_it) { + + LOD_Edge & edge = edges[*edge_it]; + + verts[edge.m_verts[0]].RemoveEdge(*edge_it); + verts[edge.m_verts[1]].RemoveEdge(*edge_it); + } + + // we postpone deletion of the internal edges untill the end + // this is because deleting edges invalidates all of the + // EdgeInd vectors above. + + + // now untie all the polygons in p_v0v1 from the edge ring + + // select all polygons in p_v0v1 + + face_it = p_v0v1.begin(); + face_end = p_v0v1.end(); + + for (;face_it != face_end; ++face_it) { + faces[*face_it].SetSelectTag(true); + } + + edge_it = edge_ring.begin(); + edge_end = edge_ring.end(); + + for (;edge_it != edge_end; ++edge_it) { + LOD_Edge & edge = edges[*edge_it]; + + // presumably all edges in edge_ring point to at least + // one polygon from p_v0v1 + + if (!edge.m_faces[0].IsEmpty() && faces[edge.m_faces[0]].SelectTag()) { + edge.m_faces[0].Invalidate(); + } + + if (!edge.m_faces[1].IsEmpty() && faces[edge.m_faces[1]].SelectTag()) { + edge.m_faces[1].Invalidate(); + } + } + + // deselect the faces + + face_it = p_v0v1.begin(); + face_end = p_v0v1.end(); + + for (;face_it != face_end; ++face_it) { + faces[*face_it].SetSelectTag(false); + } + + // perform the edge collapse + //////////////////////////// + + // iterate through the polygons of p_v0 and replace the vertex + // index v0 with v1 + + face_it = p_v01[0].begin(); + face_end = p_v01[0].end(); + + for (;face_it != face_end; ++face_it) { + faces[*face_it].SwapVertex(v0_ind,v1_ind); + } + + face_it = p_v0v1.begin(); + face_end = p_v0v1.end(); + + for (;face_it != face_end; ++face_it) { + if (faces[*face_it].Degenerate()) { + degenerate_faces.push_back(*face_it); + } else { + update_faces.push_back(*face_it); + } + } + + // Add all the non-degenerate faces back into the + // mesh. Get a record of the new edges created in + // this process. + + face_it = update_faces.begin(); + face_end = update_faces.end(); + + for (;face_it != face_end; ++face_it) { + mesh.ConnectTriangle(*face_it,new_edges); + } + + // degenerate ring primitives + ///////////////////////////// + + // we now need to examine each of the edges on the ring + // and work out if they are degenerate - if so we attempt + // to delete them -> add them to the other edges to delete + // in e_v0v1 + + edge_it = edge_ring.begin(); + edge_end = edge_ring.end(); + + for (;edge_it != edge_end; ++edge_it) { + if (edges[*edge_it].Degenerate()) { + degenerate_edges.push_back(*edge_it); + } + } + + // do the same for the ring vertices. + + vector<LOD_VertexInd>::iterator vertex_it = vertex_ring.begin(); + vector<LOD_VertexInd>::const_iterator vertex_end = vertex_ring.end(); + + for (;vertex_it != vertex_end; ++vertex_it) { + if (verts[*vertex_it].Degenerate()) { + degenerate_vertices.push_back(*vertex_it); + } else { + update_vertices.push_back(*vertex_it); + } + } + + // we now know all the degenerate primitives + // and the new primitives we have inserted into the mesh + + // We now delete the mesh primitives, mesh.DeleteXXXXXX() methods + // assume that the index vectors are sorted into descending order. + // we do that now. + + sort(degenerate_edges.begin(),degenerate_edges.end(),LOD_EdgeInd::greater()); + sort(degenerate_faces.begin(),degenerate_faces.end(),LOD_FaceInd::greater()); + sort(degenerate_vertices.begin(),degenerate_vertices.end(),LOD_VertexInd::greater()); + + + return true; + +} + +LOD_EdgeCollapser:: +LOD_EdgeCollapser( +){ + // nothing to do +} diff --git a/intern/decimation/intern/LOD_EdgeCollapser.h b/intern/decimation/intern/LOD_EdgeCollapser.h new file mode 100644 index 00000000000..d500c45e1ba --- /dev/null +++ b/intern/decimation/intern/LOD_EdgeCollapser.h @@ -0,0 +1,118 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLDUED_EgdeCollapser_h + +#define NAN_INCLDUED_EgdeCollapser_h + +// This is a helper class that collapses edges of a 2 - manifold mesh. + +#include "LOD_MeshPrimitives.h" +#include "MEM_NonCopyable.h" +#include <vector> +#include <functional> + +class LOD_ManMesh2; + +class LOD_EdgeCollapser +: public MEM_NonCopyable +{ + +public : + + static + LOD_EdgeCollapser * + New( + ); + + // returns via arguments the set of modified + // verts,edges and faces. + + bool + CollapseEdge( + LOD_EdgeInd ei, + LOD_ManMesh2 &mesh, + std::vector<LOD_EdgeInd> & degenerate_edges, + std::vector<LOD_FaceInd> & degenerate_faces, + std::vector<LOD_VertexInd> & degenerate_vertices, + std::vector<LOD_EdgeInd> & new_edges, + std::vector<LOD_FaceInd> & update_faces, + std::vector<LOD_VertexInd> & update_vertices + ); + +private : + + LOD_EdgeCollapser( + ); + + // Test to see if the result of collapsing the + // edge produces 2 junctions in the mesh i.e. where + // an edge is shared by more than 2 polygons + + // We count the number of coincedent edge pairs that + // result from the collapse of collapse_edge. + + // If collapse edge is a boundary edge then the number of + // coincedent pairs should be 1 + // else it should be 2. + + bool + TJunctionTest( + LOD_ManMesh2 &mesh, + std::vector<LOD_EdgeInd> &e_v0v1, + LOD_EdgeInd collapse_edge + ); + + // here's the definition of the sort function + // we use to determine coincedent edges + + // assumes the edges are normalized i.e. m_verts[0] <= m_verts[1] + + struct less : std::binary_function<LOD_Edge, LOD_Edge, bool> { + bool + operator()( + const LOD_Edge& a, + const LOD_Edge& b + ) const { + + if (int(a.m_verts[0]) == int(b.m_verts[0])) { + return (int(a.m_verts[1]) < int(b.m_verts[1])); + } else { + return (int(a.m_verts[0]) < int(b.m_verts[0])); + } + } + }; + +}; + + +#endif + diff --git a/intern/decimation/intern/LOD_ExternBufferEditor.h b/intern/decimation/intern/LOD_ExternBufferEditor.h new file mode 100644 index 00000000000..9f628c4455b --- /dev/null +++ b/intern/decimation/intern/LOD_ExternBufferEditor.h @@ -0,0 +1,164 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + */ + +#ifndef NAN_INCLUDED_LOD_ExternBufferEditor_h +#define NAN_INCLUDED_LOD_ExternBufferEditor_h + +#include "LOD_MeshPrimitives.h" +#include <vector> +#include "LOD_ManMesh2.h" +#include "../extern/LOD_decimation.h" + + +// This class syncs external vertex/face buffers +// with the internal mesh representation during +// decimation. + +class LOD_ExternBufferEditor +{ + +public : + + static + LOD_ExternBufferEditor * + New( + LOD_Decimation_InfoPtr extern_info + ){ + if (extern_info == NULL) return NULL; + return new LOD_ExternBufferEditor(extern_info); + } + + // update the external vertex buffer with vertices + // from the mesh + + void + CopyModifiedVerts( + LOD_ManMesh2 & mesh, + const std::vector<LOD_VertexInd> & mod_vertices + ){ + + std::vector<LOD_VertexInd>::const_iterator v_start = mod_vertices.begin(); + std::vector<LOD_VertexInd>::const_iterator v_end = mod_vertices.end(); + + std::vector<LOD_Vertex> & mesh_verts = mesh.VertexSet(); + + float * const extern_vertex_ptr = m_extern_info->vertex_buffer; + + for (; v_start != v_end; ++v_start) { + float * mod_vert = extern_vertex_ptr + int(*v_start)*3; + mesh_verts[*v_start].CopyPosition(mod_vert); + } + } + + // update the external face buffer with faces from the mesh + + void + CopyModifiedFaces( + LOD_ManMesh2 & mesh, + const std::vector<LOD_FaceInd> & mod_faces + ){ + + std::vector<LOD_FaceInd>::const_iterator f_start = mod_faces.begin(); + std::vector<LOD_FaceInd>::const_iterator f_end = mod_faces.end(); + + std::vector<LOD_TriFace> &mesh_faces = mesh.FaceSet(); + + int * const extern_face_ptr = m_extern_info->triangle_index_buffer; + + for (; f_start != f_end; ++f_start) { + int *mod_face = extern_face_ptr + 3*int(*f_start); + mesh_faces[*f_start].CopyVerts(mod_face); + } + } + + + // Copy the last vertex over the vertex specified by + // vi. Decrement the size of the vertex array + + void + CopyBackVertex( + LOD_VertexInd vi + ){ + + float * const extern_vertex_ptr = m_extern_info->vertex_buffer; + int * extern_vertex_num = &(m_extern_info->vertex_num); + + float * last_external_vert = extern_vertex_ptr + 3*((*extern_vertex_num) - 1); + float * external_vert = extern_vertex_ptr + 3*int(vi); + + external_vert[0] = last_external_vert[0]; + external_vert[1] = last_external_vert[1]; + external_vert[2] = last_external_vert[2]; + + *extern_vertex_num -=1; + } + + // Copy the last face over the face specified by fi + // Decrement the size of the face array + + void + CopyBackFace( + LOD_FaceInd fi + ) { + int * const extern_face_ptr = m_extern_info->triangle_index_buffer; + int * extern_face_num = &(m_extern_info->face_num); + + int * last_external_face = extern_face_ptr + 3*((*extern_face_num) -1); + int * external_face = extern_face_ptr + 3*int(fi); + external_face[0] = last_external_face[0]; + external_face[1] = last_external_face[1]; + external_face[2] = last_external_face[2]; + + *extern_face_num -=1; + } + + +private : + + LOD_ExternBufferEditor( + LOD_Decimation_InfoPtr extern_info + ) : + m_extern_info (extern_info) + { + } + + LOD_Decimation_InfoPtr const m_extern_info; + +}; + +#endif + diff --git a/intern/decimation/intern/LOD_ExternNormalEditor.cpp b/intern/decimation/intern/LOD_ExternNormalEditor.cpp new file mode 100644 index 00000000000..357aaf56006 --- /dev/null +++ b/intern/decimation/intern/LOD_ExternNormalEditor.cpp @@ -0,0 +1,264 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "LOD_ExternNormalEditor.h" + +#include <vector> + +using namespace std; + + +LOD_ExternNormalEditor:: +LOD_ExternNormalEditor( + LOD_Decimation_InfoPtr extern_info, + LOD_ManMesh2 &mesh +) : + m_extern_info (extern_info), + m_mesh(mesh) +{ +} + + LOD_ExternNormalEditor * +LOD_ExternNormalEditor:: +New( + LOD_Decimation_InfoPtr extern_info, + LOD_ManMesh2 &mesh +){ + if (extern_info == NULL) return NULL; + + MEM_SmartPtr<LOD_ExternNormalEditor> output(new LOD_ExternNormalEditor(extern_info,mesh)); + + int face_num = mesh.FaceSet().size(); + + MEM_SmartPtr<vector<MT_Vector3> > normals(new vector<MT_Vector3>); + + if (output == NULL || + normals == NULL + ) { + return NULL; + } + + normals->reserve(face_num); + output->m_normals = normals.Release(); + + return output.Release(); +}; + + + void +LOD_ExternNormalEditor:: +Remove( + std::vector<LOD_FaceInd> &sorted_faces +){ + // assumes a collection of faces sorted in descending order . + + vector<MT_Vector3> & normals = m_normals.Ref(); + + vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin(); + vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end(); + + for (; it_start != it_end; ++it_start) { + + if (normals.size() > 0) { + MT_Vector3 temp = normals[*it_start]; + + normals[*it_start] = normals.back(); + normals.back() = temp; + + normals.pop_back(); + } + + // FIXME - throw exception + } +} + + + void +LOD_ExternNormalEditor:: +Add( +){ + MT_Vector3 zero(0.0f,0.0f,0.0f); + m_normals->push_back(zero); +}; + + void +LOD_ExternNormalEditor:: +Update( + std::vector<LOD_FaceInd> &sorted_faces +){ + vector<MT_Vector3> & normals = m_normals.Ref(); + + vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin(); + vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end(); + + const vector<LOD_TriFace> &faces = m_mesh.FaceSet(); + + for (; it_start != it_end; ++it_start) { + normals[*it_start] = ComputeNormal(faces[*it_start]); + } +}; + + + + +// vertex normals +///////////////// + + void +LOD_ExternNormalEditor:: +RemoveVertexNormals( + std::vector<LOD_VertexInd> &sorted_verts +){ + + float * vertex_normals = m_extern_info->vertex_normal_buffer; + + // assumption here that the vertexs normal number corresponds with + // the number of vertices ! + + int vertex_normal_num = m_extern_info->vertex_num; + + vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin(); + vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end(); + + for (; it_start != it_end; ++it_start) { + + if (vertex_normal_num > 0) { + float * vertex_normal = vertex_normals + int(*it_start)*3; + float * last_vertex = vertex_normals + ((vertex_normal_num-1)*3); + + MT_Vector3 last_v(last_vertex); + last_v.getValue(vertex_normal); + vertex_normal_num--; + } + + // FIXME - through exception + } +}; + + + + void +LOD_ExternNormalEditor:: +UpdateVertexNormals( + std::vector<LOD_VertexInd> &sorted_verts +){ + float * vertex_normals = m_extern_info->vertex_normal_buffer; + + vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin(); + vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end(); + + for (; it_start != it_end; ++it_start) { + MT_Vector3 temp = ComputeVertexNormal(*it_start); + float * vertex_normal = vertex_normals + int(*it_start)*3; + temp.getValue(vertex_normal); + } +} + +// Editor specific methods +////////////////////////// + + void +LOD_ExternNormalEditor:: +BuildNormals( +) { + const vector<LOD_TriFace> &faces = m_mesh.FaceSet(); + vector<MT_Vector3> & normals = m_normals.Ref(); + + int face_num = faces.size(); + int cur_face = 0; + + for (; cur_face < face_num; ++cur_face) { + + MT_Vector3 new_normal = ComputeNormal(faces[cur_face]); + normals.push_back(new_normal); + } +} + +const + MT_Vector3 +LOD_ExternNormalEditor:: +ComputeNormal( + const LOD_TriFace &face +) const { + + const vector<LOD_Vertex> &verts = m_mesh.VertexSet(); + + MT_Vector3 vec1 = + verts[face.m_verts[1]].pos - + verts[face.m_verts[0]].pos; + + MT_Vector3 vec2 = + verts[face.m_verts[2]].pos - + verts[face.m_verts[1]].pos; + + vec1 = vec1.cross(vec2); + + if (!vec1.fuzzyZero()) { + vec1.normalize(); + return (vec1); + } else { + return (MT_Vector3(1.0,0,0)); + } +} + +const + MT_Vector3 +LOD_ExternNormalEditor:: +ComputeVertexNormal( + const LOD_VertexInd v +) const { + + // average the face normals surrounding this + // vertex and normalize + vector<LOD_Vertex> &verts = m_mesh.VertexSet(); + const vector<MT_Vector3> & face_normals = m_normals.Ref(); + + vector<LOD_FaceInd> vertex_faces; + vertex_faces.reserve(32); + + m_mesh.VertexFaces(v,vertex_faces); + + MT_Vector3 normal(0,0,0); + + vector<LOD_FaceInd>::const_iterator face_it = vertex_faces.begin(); + vector<LOD_FaceInd>::const_iterator face_end = vertex_faces.end(); + + for (; face_it != face_end; ++face_it) { + normal += face_normals[*face_it]; + } + + if (!normal.fuzzyZero()) { + normal.normalize(); + return (normal); + } else { + return (MT_Vector3(1.0,0,0)); + } +} diff --git a/intern/decimation/intern/LOD_ExternNormalEditor.h b/intern/decimation/intern/LOD_ExternNormalEditor.h new file mode 100644 index 00000000000..c32b3d5a0b3 --- /dev/null +++ b/intern/decimation/intern/LOD_ExternNormalEditor.h @@ -0,0 +1,134 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_ExternNormalEditor_h + +#define NAN_INCLUDED_ExternNormalEditor_h + +#include "MEM_NonCopyable.h" +#include "LOD_ManMesh2.h" +#include "MT_Vector3.h" +#include "../extern/LOD_decimation.h" + +class LOD_ExternNormalEditor : public MEM_NonCopyable +{ + +public : + + // Creation + /////////// + + static + LOD_ExternNormalEditor * + New( + LOD_Decimation_InfoPtr, + LOD_ManMesh2 &mesh + ); + + // Property editor interface + //////////////////////////// + + + // Faces + //////// + void + Remove( + std::vector<LOD_FaceInd> &sorted_faces + ); + + void + Add( + ); + + void + Update( + std::vector<LOD_FaceInd> &sorted_faces + ); + + const + std::vector<MT_Vector3> & + Normals( + ) const { + return m_normals.Ref(); + }; + + + // vertex normals + ///////////////// + + void + RemoveVertexNormals( + std::vector<LOD_VertexInd> &sorted_verts + ); + + + void + UpdateVertexNormals( + std::vector<LOD_VertexInd> &sorted_verts + ); + + // Editor specific methods + ////////////////////////// + + void + BuildNormals( + ); + + +private : + + MEM_SmartPtr<std::vector<MT_Vector3> > m_normals; + + LOD_ManMesh2 &m_mesh; + LOD_Decimation_InfoPtr m_extern_info; + +private : + + + LOD_ExternNormalEditor( + LOD_Decimation_InfoPtr extern_info, + LOD_ManMesh2 &mesh + ); + + const + MT_Vector3 + ComputeNormal( + const LOD_TriFace &face + ) const ; + + const + MT_Vector3 + ComputeVertexNormal ( + const LOD_VertexInd vi + ) const; +}; + +#endif diff --git a/intern/decimation/intern/LOD_FaceNormalEditor.cpp b/intern/decimation/intern/LOD_FaceNormalEditor.cpp new file mode 100644 index 00000000000..ef6bc0d252e --- /dev/null +++ b/intern/decimation/intern/LOD_FaceNormalEditor.cpp @@ -0,0 +1,291 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +// implementation of LOD_FaceNormalEditor.h + +/////////////////////////////////////// + +#include "LOD_FaceNormalEditor.h" + +using namespace std; + +LOD_FaceNormalEditor:: +LOD_FaceNormalEditor( + LOD_ManMesh2 & mesh +) : m_mesh(mesh) { +}; + + LOD_FaceNormalEditor * +LOD_FaceNormalEditor:: +New( + LOD_ManMesh2 &mesh +){ + // build a set of normals of the same size + // as the number of polys in the mesh + + MEM_SmartPtr<LOD_FaceNormalEditor> output(new LOD_FaceNormalEditor(mesh)); + + int face_num = mesh.FaceSet().size(); + + MEM_SmartPtr<vector<MT_Vector3> > normals(new vector<MT_Vector3>); + MEM_SmartPtr<vector<MT_Vector3> > vertex_normals(new vector<MT_Vector3>); + + if (output == NULL || + normals == NULL + ) { + return NULL; + } + + normals->reserve(face_num); + vertex_normals->reserve(mesh.VertexSet().size()); + output->m_normals = normals.Release(); + output->m_vertex_normals = vertex_normals.Release(); + + return output.Release(); +}; + + +// Property editor interface +//////////////////////////// + + void +LOD_FaceNormalEditor:: +Remove( + std::vector<LOD_FaceInd> &sorted_faces +){ + + // assumes a collection of faces sorted in descending order . + + vector<MT_Vector3> & normals = m_normals.Ref(); + + vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin(); + vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end(); + + for (; it_start != it_end; ++it_start) { + + if (normals.size() > 0) { + MT_Vector3 temp = normals[*it_start]; + + normals[*it_start] = normals.back(); + normals.back() = temp; + + normals.pop_back(); + } + + // FIXME - through exception + } +} + + + void +LOD_FaceNormalEditor:: +Add( +){ + MT_Vector3 zero(0.0f,0.0f,0.0f); + m_normals->push_back(zero); +} + + void +LOD_FaceNormalEditor:: +Update( + std::vector<LOD_FaceInd> &sorted_faces +){ + + vector<MT_Vector3> & normals = m_normals.Ref(); + + vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin(); + vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end(); + + const vector<LOD_TriFace> &faces = m_mesh.FaceSet(); + + for (; it_start != it_end; ++it_start) { + normals[*it_start] = ComputeNormal(faces[*it_start]); + } +}; + +// vertex normals +///////////////// + + + void +LOD_FaceNormalEditor:: +RemoveVertexNormals( + vector<LOD_VertexInd> &sorted_verts +){ + vector<MT_Vector3> & vertex_normals = m_vertex_normals.Ref(); + + vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin(); + vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end(); + + for (; it_start != it_end; ++it_start) { + + if (vertex_normals.size() > 0) { + MT_Vector3 temp = vertex_normals[*it_start]; + + vertex_normals[*it_start] = vertex_normals.back(); + vertex_normals.back() = temp; + + vertex_normals.pop_back(); + } + + // FIXME - through exception + } +}; + + void +LOD_FaceNormalEditor:: +UpdateVertexNormals( + vector<LOD_VertexInd> &sorted_verts +){ + vector<MT_Vector3> & vertex_normals = m_vertex_normals.Ref(); + + vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin(); + vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end(); + + for (; it_start != it_end; ++it_start) { + vertex_normals[*it_start] = ComputeVertexNormal(*it_start); + } +} + + + +// Editor specific methods +////////////////////////// + + void +LOD_FaceNormalEditor:: +BuildNormals( +){ + + const vector<LOD_TriFace> &faces = m_mesh.FaceSet(); + vector<MT_Vector3> & normals = m_normals.Ref(); + + int face_num = faces.size(); + int cur_face = 0; + + for (; cur_face < face_num; ++cur_face) { + + MT_Vector3 new_normal = ComputeNormal(faces[cur_face]); + normals.push_back(new_normal); + } + // now build the vertex normals + + vector<MT_Vector3> & vertex_normals = m_vertex_normals.Ref(); + const vector<LOD_Vertex> &verts = m_mesh.VertexSet(); + + int vertex_num = verts.size(); + int cur_vertex = 0; + + for (; cur_vertex < vertex_num; ++cur_vertex) { + MT_Vector3 new_normal = ComputeVertexNormal(cur_vertex); + vertex_normals.push_back(new_normal); + } +} + +const + MT_Vector3 +LOD_FaceNormalEditor:: +ComputeNormal( + const LOD_TriFace &face +) const { + + const vector<LOD_Vertex> &verts = m_mesh.VertexSet(); + + MT_Vector3 vec1 = + verts[face.m_verts[1]].pos - + verts[face.m_verts[0]].pos; + + MT_Vector3 vec2 = + verts[face.m_verts[2]].pos - + verts[face.m_verts[1]].pos; + + vec1 = vec1.cross(vec2); + + if (!vec1.fuzzyZero()) { + vec1.normalize(); + return (vec1); + } else { + return (MT_Vector3(1.0,0,0)); + } +} + +const + MT_Vector3 +LOD_FaceNormalEditor:: +ComputeVertexNormal( + const LOD_VertexInd v +) const { + + // average the face normals surrounding this + // vertex and normalize + const vector<MT_Vector3> & face_normals = m_normals.Ref(); + + vector<LOD_FaceInd> vertex_faces; + vertex_faces.reserve(32); + + m_mesh.VertexFaces(v,vertex_faces); + + MT_Vector3 normal(0,0,0); + + vector<LOD_FaceInd>::const_iterator face_it = vertex_faces.begin(); + vector<LOD_FaceInd>::const_iterator face_end = vertex_faces.end(); + + for (; face_it != face_end; ++face_it) { + normal += face_normals[*face_it]; + } + + if (!normal.fuzzyZero()) { + normal.normalize(); + return (normal); + } else { + return (MT_Vector3(1.0,0,0)); + } +} + + + + + + + + + + + + + + + + + + + + diff --git a/intern/decimation/intern/LOD_FaceNormalEditor.h b/intern/decimation/intern/LOD_FaceNormalEditor.h new file mode 100644 index 00000000000..345dc4f8246 --- /dev/null +++ b/intern/decimation/intern/LOD_FaceNormalEditor.h @@ -0,0 +1,143 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_FaceNormalEditor_h + +#define NAN_INCLUDED_FaceNormalEditor_h + +#include "MEM_NonCopyable.h" +#include "LOD_ManMesh2.h" +#include "MT_Vector3.h" + + +class LOD_FaceNormalEditor : public MEM_NonCopyable +{ + +public : + + // Creation + /////////// + + static + LOD_FaceNormalEditor * + New( + LOD_ManMesh2 &mesh + ); + + // Property editor interface + //////////////////////////// + + + // Faces + //////// + void + Remove( + std::vector<LOD_FaceInd> &sorted_faces + ); + + void + Add( + ); + + void + Update( + std::vector<LOD_FaceInd> &sorted_faces + ); + + + // vertex normals + ///////////////// + + void + RemoveVertexNormals( + std::vector<LOD_VertexInd> &sorted_verts + ); + + + void + UpdateVertexNormals( + std::vector<LOD_VertexInd> &sorted_verts + ); + + + + const + std::vector<MT_Vector3> & + Normals( + ) const { + return m_normals.Ref(); + }; + + + const + std::vector<MT_Vector3> & + VertexNormals( + ) const { + return m_vertex_normals.Ref(); + }; + + // Editor specific methods + ////////////////////////// + + void + BuildNormals( + ); + + +private : + + MEM_SmartPtr<std::vector<MT_Vector3> > m_normals; + MEM_SmartPtr<std::vector<MT_Vector3> > m_vertex_normals; + + LOD_ManMesh2 &m_mesh; + +private : + + + LOD_FaceNormalEditor(LOD_ManMesh2 &mesh); + + const + MT_Vector3 + ComputeNormal( + const LOD_TriFace &face + ) const ; + + const + MT_Vector3 + ComputeVertexNormal ( + const LOD_VertexInd vi + ) const; + + + +}; + +#endif diff --git a/intern/decimation/intern/LOD_ManMesh2.cpp b/intern/decimation/intern/LOD_ManMesh2.cpp new file mode 100644 index 00000000000..f0bf40f577c --- /dev/null +++ b/intern/decimation/intern/LOD_ManMesh2.cpp @@ -0,0 +1,617 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "LOD_ManMesh2.h" + +#include "MT_assert.h" +#include <algorithm> +#include "LOD_MeshException.h" +#include "CTR_TaggedSetOps.h" +#include "CTR_UHeap.h" +#include "LOD_ExternBufferEditor.h" + + +using namespace std; + +LOD_ManMesh2:: +LOD_ManMesh2( +) : + m_bbox_min(0,0,0), + m_bbox_max(0,0,0) +{ +} + + + LOD_ManMesh2 * +LOD_ManMesh2:: +New( +){ + MEM_SmartPtr<LOD_ManMesh2> output(new LOD_ManMesh2()); + if (output == NULL) return NULL; + + // build the vertex, edge and face sets. + + MEM_SmartPtr<vector<LOD_Vertex> > verts(new vector<LOD_Vertex>); + MEM_SmartPtr<vector<LOD_TriFace> > faces(new vector<LOD_TriFace>); + MEM_SmartPtr<vector<LOD_Edge> > edges(new vector<LOD_Edge>); + + if ((faces == NULL) || (edges == NULL) || (verts == NULL)) { + return NULL; + } + + output->m_verts = verts.Release(); + output->m_faces = faces.Release(); + output->m_edges = edges.Release(); + + return output.Release(); +} + +// take ownership of the vertices. + + bool +LOD_ManMesh2:: +SetVertices( + MEM_SmartPtr<vector<LOD_Vertex> > verts +){ + + + // take ownership of vertices + m_verts = verts; + + // create a polygon and edge buffer of half the size + // and just use the automatic resizing feature of vector<> + // to worry about the dynamic array resizing + + m_faces->clear(); + m_edges->clear(); + + m_faces->reserve(m_verts->size()/2); + m_edges->reserve(m_verts->size()/2); + + return true; + +} + + +// add a triangle to the mesh + + void +LOD_ManMesh2:: +AddTriangle( + int verts[3] +) { + + MT_assert(verts[0] < int(m_verts->size())); + MT_assert(verts[1] < int(m_verts->size())); + MT_assert(verts[2] < int(m_verts->size())); + + LOD_TriFace face; + face.m_verts[0] = verts[0]; + face.m_verts[1] = verts[1]; + face.m_verts[2] = verts[2]; + + LOD_FaceInd face_index = m_faces->size(); + + m_faces->push_back(face); + + // now work out if any of the directed edges or their + // companion edges exist already. + // We go through the edges associated with each of the given vertices + + // the safest thing to do is iterate through each of the edge sets + // check against each of the 2 other triangle edges to see if they are there + + vector<LOD_EdgeInd> new_edges; + new_edges.reserve(3); + + InsertEdge(verts[0],verts[1],face_index,new_edges); + InsertEdge(verts[1],verts[2],face_index,new_edges); + InsertEdge(verts[2],verts[0],face_index,new_edges); + +} + +// Adds the index of any created edges to new_edges + + bool +LOD_ManMesh2:: +InsertEdge( + const LOD_VertexInd v1, + const LOD_VertexInd v2, + const LOD_FaceInd f, + vector<LOD_EdgeInd> &new_edges +){ + + MT_assert(!v1.IsEmpty()); + MT_assert(!v2.IsEmpty()); + MT_assert(!f.IsEmpty()); + + vector<LOD_Vertex> &verts = VertexSet(); + vector<LOD_Edge> &edges = EdgeSet(); + + LOD_EdgeInd e; + + e = FindEdge(v1,v2); + + if (e.IsEmpty()) { + // This edge does not exist -- make a new one + + LOD_Edge temp_e; + temp_e.m_verts[0] = v1; + temp_e.m_verts[1] = v2; + + e = m_edges->size(); + + // set the face ptr for this half-edge + temp_e.m_faces[0] = f; + + m_edges->push_back(temp_e); + + // add the edge index to it's vertices + + verts[v1].AddEdge(e); + verts[v2].AddEdge(e); + + new_edges.push_back(e); + + } else { + + // edge already exists + // insure that there is no polygon already + // attached to the other side of this edge + + // swap the empty face pointer in edge with f + + LOD_Edge &edge = edges[e]; + + edge.SwapFace(LOD_FaceInd::Empty(),f); + } + + + return true; + +} + + void +LOD_ManMesh2:: +ConnectTriangle( + LOD_FaceInd fi, + std::vector<LOD_EdgeInd> & new_edges +){ + + vector<LOD_TriFace> &faces = FaceSet(); + + MT_assert(!faces[fi].Degenerate()); + + LOD_TriFace & face = faces[fi]; + + InsertEdge(face.m_verts[0],face.m_verts[1],fi,new_edges); + InsertEdge(face.m_verts[1],face.m_verts[2],fi,new_edges); + InsertEdge(face.m_verts[2],face.m_verts[0],fi,new_edges); +}; + + + + +// geometry access +////////////////// + + vector<LOD_Vertex> & +LOD_ManMesh2:: +VertexSet( +) const { + return m_verts.Ref(); +} + + vector<LOD_TriFace> & +LOD_ManMesh2:: +FaceSet( +) const { + return m_faces.Ref(); +} + + vector<LOD_Edge> & +LOD_ManMesh2:: +EdgeSet( +) const { + return m_edges.Ref(); +}; + +LOD_ManMesh2:: +~LOD_ManMesh2( +){ + //auto ptr takes care of vertex arrays etc. +} + + LOD_EdgeInd +LOD_ManMesh2:: +FindEdge( + const LOD_VertexInd v1, + const LOD_VertexInd v2 +) { + + vector<LOD_Vertex> &verts = VertexSet(); + vector<LOD_Edge> &edges = EdgeSet(); + + LOD_Edge e; + e.m_verts[0] = v1; + e.m_verts[1] = v2; + + vector<LOD_EdgeInd> &v1_edges = verts[v1].m_edges; + vector<LOD_EdgeInd>::const_iterator v1_end = v1_edges.end(); + vector<LOD_EdgeInd>::iterator v1_begin = v1_edges.begin(); + + for (; v1_begin != v1_end; ++v1_begin) { + if (edges[*v1_begin] == e) return *v1_begin; + } + + return LOD_EdgeInd::Empty(); +} + +// face queries +/////////////// + + void +LOD_ManMesh2:: +FaceVertices( + LOD_FaceInd fi, + vector<LOD_VertexInd> &output +){ + const vector<LOD_TriFace> &faces = FaceSet(); + const LOD_TriFace & f = faces[fi]; + + output.push_back(f.m_verts[0]); + output.push_back(f.m_verts[1]); + output.push_back(f.m_verts[2]); +} + + void +LOD_ManMesh2:: +FaceEdges( + LOD_FaceInd fi, + vector<LOD_EdgeInd> &output +){ + const vector<LOD_TriFace> &faces = FaceSet(); + vector<LOD_Edge> &edges = EdgeSet(); + vector<LOD_Vertex> &verts = VertexSet(); + + const LOD_TriFace & f = faces[fi]; + // intersect vertex edges + + vector<LOD_EdgeInd> & v0_edges = verts[f.m_verts[0]].m_edges; + vector<LOD_EdgeInd> & v1_edges = verts[f.m_verts[1]].m_edges; + vector<LOD_EdgeInd> & v2_edges = verts[f.m_verts[2]].m_edges; + + CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::IntersectPair(v0_edges,v1_edges,edges,output); + CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::IntersectPair(v1_edges,v2_edges,edges,output); + CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::IntersectPair(v2_edges,v0_edges,edges,output); + + MT_assert(output.size() == 3); + if (output.size() != 3) { + LOD_MeshException e(LOD_MeshException::e_non_manifold); + throw(e); + } +} + + +// edge queries +/////////////// + + void +LOD_ManMesh2:: +EdgeVertices( + LOD_EdgeInd ei, + vector<LOD_VertexInd> &output +){ + const vector<LOD_Edge> &edges = EdgeSet(); + const LOD_Edge & e = edges[ei]; + + output.push_back(e.m_verts[0]); + output.push_back(e.m_verts[1]); +} + + void +LOD_ManMesh2:: +EdgeFaces( + LOD_EdgeInd ei, + vector<LOD_FaceInd> &output +){ + const vector<LOD_Edge> &edges = EdgeSet(); + const LOD_Edge & e = edges[ei]; + + if (!e.m_faces[0].IsEmpty()) { + output.push_back(e.m_faces[0]); + } + if (!e.m_faces[1].IsEmpty()) { + output.push_back(e.m_faces[1]); + } +} + +// vertex queries +///////////////// + + void +LOD_ManMesh2:: +VertexEdges( + LOD_VertexInd vi, + vector<LOD_EdgeInd> &output +){ + // iterate through the edges of v and push them onto the + // output + + vector<LOD_Vertex> &verts = VertexSet(); + + vector<LOD_EdgeInd> & v_edges = verts[vi].m_edges; + vector<LOD_EdgeInd>::iterator v_it = v_edges.begin(); + + for (; v_it != v_edges.end(); ++v_it) { + output.push_back(*v_it); + } +} + + void +LOD_ManMesh2:: +VertexFaces( + LOD_VertexInd vi, + vector<LOD_FaceInd> &output +){ + const vector<LOD_Vertex> &verts = VertexSet(); + vector<LOD_Edge> &edges = EdgeSet(); + vector<LOD_TriFace> &faces = FaceSet(); + + const vector<LOD_EdgeInd> &v_edges = verts[vi].m_edges; + vector<LOD_EdgeInd>::const_iterator e_it = v_edges.begin(); + + for (; e_it != v_edges.end(); ++e_it) { + + LOD_Edge &e = edges[*e_it]; + + if ((!e.m_faces[0].IsEmpty()) && (!faces[e.m_faces[0]].SelectTag())) { + output.push_back(e.m_faces[0]); + faces[e.m_faces[0]].SetSelectTag(true); + } + + if ((!e.m_faces[1].IsEmpty()) && (!faces[e.m_faces[1]].SelectTag())) { + output.push_back(e.m_faces[1]); + faces[e.m_faces[1]].SetSelectTag(true); + } + } + + vector<LOD_FaceInd>::iterator f_it = output.begin(); + + for (; f_it != output.end(); ++f_it) { + faces[*f_it].SetSelectTag(false); + } +}; + + void +LOD_ManMesh2:: +SetBBox( + MT_Vector3 bbox_min, + MT_Vector3 bbox_max +){ + m_bbox_min = bbox_min; + m_bbox_max = bbox_max; +}; + + void +LOD_ManMesh2:: +SC_TriFace( + LOD_FaceInd f +){ + LOD_TriFace face = (*m_faces)[f]; + + // check for unique vertices + + if ( + (face.m_verts[0] == face.m_verts[1]) || + (face.m_verts[1] == face.m_verts[2]) || + (face.m_verts[2] == face.m_verts[0]) + ) { + MT_assert(false); + } + +} + + + void +LOD_ManMesh2:: +SC_EdgeList( + LOD_VertexInd v +){ + vector<LOD_Edge> &edges = EdgeSet(); + vector<LOD_Vertex> &verts = VertexSet(); + + vector<LOD_EdgeInd>::iterator e_it = verts[v].m_edges.begin(); + + for (;e_it != verts[v].m_edges.end(); ++e_it) { + MT_assert( (edges[*e_it].m_verts[0] == v) || (edges[*e_it].m_verts[1] == v)); + } + +}; + + void +LOD_ManMesh2:: +DeleteVertex( + LOD_ExternBufferEditor & extern_editor, + LOD_VertexInd v +){ + + vector<LOD_Edge> &edges = EdgeSet(); + vector<LOD_Vertex> &verts = VertexSet(); + vector<LOD_TriFace> &faces = FaceSet(); + + // need to update all the edge and polygons pointing to + // the last vertex in m_verts + + if (verts.size() == 1) { + verts.clear(); + return; + } + + LOD_VertexInd last = LOD_VertexInd(verts.end() - verts.begin() - 1); + + if (!(last == v)) { + + // we asume that v is already disconnected + + vector<LOD_FaceInd> v_faces; + vector<LOD_EdgeInd> v_edges; + + v_faces.reserve(64); + v_edges.reserve(64); + + VertexFaces(last,v_faces); + VertexEdges(last,v_edges); + + // map the faces and edges to look at v + + vector<LOD_FaceInd>::iterator face_it = v_faces.begin(); + + for(; face_it != v_faces.end(); ++face_it) { + faces[*face_it].SwapVertex(last,v); + } + vector<LOD_EdgeInd>::iterator edge_it = v_edges.begin(); + + for (; edge_it != v_edges.end(); ++edge_it) { + edges[*edge_it].SwapVertex(last,v); + } + + // copy the last vertex onto v and pop off the back. + + verts[v] = verts[last]; + + // tidy external buffer + extern_editor.CopyModifiedFaces(*this,v_faces); + } + + verts.pop_back(); + extern_editor.CopyBackVertex(v); + + +}; + + void +LOD_ManMesh2:: +DeleteEdge( + LOD_EdgeInd e, + CTR_UHeap<LOD_Edge> * heap +){ + vector<LOD_Edge> &edges = EdgeSet(); + vector<LOD_Vertex> &verts = VertexSet(); + + if (edges.size() == 1) { + edges.clear(); + return; + } + + LOD_EdgeInd last = LOD_EdgeInd(edges.end() - edges.begin() - 1); + + if (!(last == e)) { + vector<LOD_EdgeInd> e_verts; + e_verts.reserve(2); + EdgeVertices(last,e_verts); + // something is wrong if there arent two! + + verts[e_verts[0]].SwapEdge(last,e); + verts[e_verts[1]].SwapEdge(last,e); + + // edges[e] should already have been removed from the heap + + MT_assert(edges[e].HeapPos() == 0xffffffff); + + edges[e] = edges[last]; + // also have to swap there heap positions.!!!!! + + heap->HeapVector()[edges[e].HeapPos()] = e; + + + } + edges.pop_back(); +}; + + void +LOD_ManMesh2:: +DeleteFace( + LOD_ExternBufferEditor & extern_editor, + LOD_FaceInd f +){ + + vector<LOD_Edge> &edges = EdgeSet(); + vector<LOD_TriFace> &faces = FaceSet(); + + if (faces.size() == 1) { + faces.clear(); + return; + } + + LOD_FaceInd last = LOD_FaceInd(faces.end() - faces.begin() - 1); + + if (!(last == f)) { + + // we have to update the edges which point to the last + // face + + vector<LOD_EdgeInd> f_edges; + f_edges.reserve(3); + + FaceEdges(last,f_edges); + + vector<LOD_EdgeInd>::iterator edge_it = f_edges.begin(); + vector<LOD_EdgeInd>::const_iterator edge_end = f_edges.end(); + + for (; edge_it != edge_end; ++edge_it) { + edges[*edge_it].SwapFace(last,f); + } + + faces[f] = faces[last]; + + } + faces.pop_back(); + + // tidy external buffers + extern_editor.CopyBackFace(f); +}; + + + + + + + + + + + + + + + + diff --git a/intern/decimation/intern/LOD_ManMesh2.h b/intern/decimation/intern/LOD_ManMesh2.h new file mode 100644 index 00000000000..e208155c1f0 --- /dev/null +++ b/intern/decimation/intern/LOD_ManMesh2.h @@ -0,0 +1,264 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_ManMesh2_h + +#define NAN_INCLUDED_ManMesh2_h + +#include "LOD_MeshPrimitives.h" +#include "MEM_SmartPtr.h" +#include <vector> + +template <class HeapType> class CTR_UHeap; + +class LOD_ExternBufferEditor; + +class LOD_ManMesh2 // Manifold 2 dimensional mesh +{ + +public: + + static + LOD_ManMesh2 * + New( + ); + + // take ownership of the vertices. + + bool + SetVertices( + MEM_SmartPtr<std::vector<LOD_Vertex> > verts + ); + + // Add a triangle to the mesh + + void + AddTriangle( + int verts[3] + ); + + void + ConnectTriangle( + LOD_FaceInd fi, + std::vector<LOD_EdgeInd> & new_edges + ); + + // geometry access + ////////////////// + + std::vector<LOD_Vertex> & + VertexSet( + ) const ; + + std::vector<LOD_TriFace> & + FaceSet( + ) const ; + + std::vector<LOD_Edge> & + EdgeSet( + ) const; + + ~LOD_ManMesh2( + ); + + // local geometry queries + ///////////////////////// + + // face queries + /////////////// + + void + FaceVertices( + LOD_FaceInd f, + std::vector<LOD_VertexInd> &output + ); + + void + FaceEdges( + LOD_FaceInd f, + std::vector<LOD_EdgeInd> &output + ); + + // edge queries + /////////////// + + void + EdgeVertices( + LOD_EdgeInd e, + std::vector<LOD_VertexInd> &output + ); + + void + EdgeFaces( + LOD_EdgeInd e, + std::vector<LOD_FaceInd> &output + ); + + // vertex queries + ///////////////// + + void + VertexEdges( + LOD_VertexInd v, + std::vector<LOD_EdgeInd> &output + ); + + void + VertexFaces( + LOD_VertexInd v, + std::vector<LOD_FaceInd> &output + ); + + void + SetBBox( + MT_Vector3 bbox_min, + MT_Vector3 bbox_max + ); + + MT_Vector3 + BBoxMin( + ) const { + return m_bbox_min; + }; + + MT_Vector3 + BBoxMax( + ) const { + return m_bbox_max; + }; + + // Remove a primitive from the mesh + /////////////////////////////////// + + // These methods assume you have correctly + // tidied up the index pointers in other primitives, + // so that nothing refers to this object any more + + // These methods exchange the primitive with the + // last primitive in the vector. It modifies everything + // pointing to the last primitive correctly. + + // FIXME refactor extern editor out of primitive deletion + // insead return a vector of primitives that need to be + // modified and do this externally + + void + DeleteVertex( + LOD_ExternBufferEditor & extern_editor, + LOD_VertexInd v + ); + + void + DeleteEdge( + LOD_EdgeInd e, + CTR_UHeap<LOD_Edge> *heap + ); + + void + DeleteFace( + LOD_ExternBufferEditor & extern_editor, + LOD_FaceInd f + ); + + // Sanity Check routines + //////////////////////// + + // Make sure the edge sets and the vertex sets are + // consistent + + void + SC_TriFace( + LOD_FaceInd f + ); + + // basic sanity checking of an edge list bails out if there are more than 1024 + // edges + + void + SC_EdgeList( + LOD_EdgeInd e + ); + + + // Check to see that the edges of v1 and v2 are unique. + + bool + SC_UniqueEdge( + LOD_EdgeInd e + ); + + +private : + + + // Returns the edge index of the edge from v1 to v2. + // Does this by searching the edge sets of v1 - but not v2. + // If you are paranoid you should check both and make sure the + // indices are the same. If the edge doe not exist edgeInd is empty. + + LOD_EdgeInd + FindEdge( + const LOD_VertexInd v1, + const LOD_VertexInd v2 + ); + + // Insert an edge into the mesh + // Tie up the ptrs and create space for the edge + // returns manifold errors - need to sort out memory edges + + bool + InsertEdge( + const LOD_VertexInd v1, + const LOD_VertexInd v2, + const LOD_FaceInd f, + std::vector<LOD_EdgeInd> &new_edges + ); + + +private : + + LOD_ManMesh2( + ); + + MEM_SmartPtr< std::vector<LOD_Vertex> > m_verts; + MEM_SmartPtr< std::vector<LOD_TriFace> > m_faces; + MEM_SmartPtr< std::vector<LOD_Edge> > m_edges; + + // not sure of these descrtiptions of the mesh should + // reside in this class coz may lead to very bloated interface. + + MT_Vector3 m_bbox_min; + MT_Vector3 m_bbox_max; + + +}; + +#endif
\ No newline at end of file diff --git a/intern/decimation/intern/LOD_MeshBounds.h b/intern/decimation/intern/LOD_MeshBounds.h new file mode 100644 index 00000000000..bb74bdb3945 --- /dev/null +++ b/intern/decimation/intern/LOD_MeshBounds.h @@ -0,0 +1,134 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_MeshBounds_h + +#define NAN_INCLUDED_MeshBounds_h + + +#include "MEM_SmartPtr.h" +#include "LOD_MeshPrimitives.h" +#include "LOD_ManMesh2.h" +#include "MT_assert.h" + +// simple class to compute the mesh bounds of a manifold mesh, + +class LOD_MeshBounds { + +public : + static + LOD_MeshBounds * + New( + ){ + + MEM_SmartPtr<LOD_MeshBounds> output(new LOD_MeshBounds()); + return output.Release(); + } + + void + ComputeBounds( + const LOD_ManMesh2 * mesh + ){ + MT_assert(mesh!=NULL); + MT_assert(mesh->VertexSet().size() > 0); + + const std::vector<LOD_Vertex> &verts = mesh->VertexSet(); + + m_min = verts[0].pos; + m_max = verts[0].pos; + + // iterate through the verts + + int t; + const int size = verts.size(); + + for (t=1; t< size ; ++t) { + + UpdateBounds(verts[t].pos,m_min,m_max); + } + } + + MT_Vector3 + Min( + ) const { + return m_min; + } + + MT_Vector3 + Max( + ) const { + return m_max; + } + +private : + + void + UpdateBounds( + MT_Vector3 vertex, + MT_Vector3& min, + MT_Vector3& max + ) { + if (vertex.x() < min.x()) { + min.x() = vertex.x(); + } else + if (vertex.x() > max.x()) { + max.x()= vertex.x(); + } + + if (vertex.y() < min.y()) { + min.y() = vertex.y(); + } else + if (vertex.y() > max.y()) { + max.y()= vertex.y(); + } + + if (vertex.z() < min.z()) { + min.z() = vertex.z(); + } else + if (vertex.z() > max.z()) { + max.z()= vertex.z(); + } + } + + LOD_MeshBounds( + ) : + m_min(0,0,0), + m_max(0,0,0) + { + }; + + MT_Vector3 m_min; + MT_Vector3 m_max; + +}; + + +#endif diff --git a/intern/decimation/intern/LOD_MeshException.h b/intern/decimation/intern/LOD_MeshException.h new file mode 100644 index 00000000000..4f0b8f99c38 --- /dev/null +++ b/intern/decimation/intern/LOD_MeshException.h @@ -0,0 +1,55 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_MeshExceptions_h + +#define NAN_INCLUDED_MeshExceptions_h + + +class LOD_MeshException { + +public : + + // stick in more error types as you think of them + + enum ExceptionType{ + e_non_manifold, + e_search_error + } m_e_type; + + LOD_MeshException ( + ExceptionType type + ) : m_e_type (type) + { + } +}; + +#endif diff --git a/intern/decimation/intern/LOD_MeshPrimitives.cpp b/intern/decimation/intern/LOD_MeshPrimitives.cpp new file mode 100644 index 00000000000..147e107cb4b --- /dev/null +++ b/intern/decimation/intern/LOD_MeshPrimitives.cpp @@ -0,0 +1,407 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "LOD_MeshPrimitives.h" + +#include "MT_assert.h" +#include "LOD_MeshException.h" +#include <algorithm> + +using namespace std; + +// Vertex Methods +///////////////// + +LOD_Vertex:: +LOD_Vertex( +) : + pos (MT_Vector3()), + m_select_tag(false) +{ +}; + + bool +LOD_Vertex:: +RemoveEdge( + LOD_EdgeInd e +){ + + vector<LOD_EdgeInd>::iterator result = find(m_edges.begin(),m_edges.end(),e); + if (result == m_edges.end()) { + return false; + } + LOD_EdgeInd last = m_edges.back(); + m_edges.pop_back(); + if (m_edges.empty()) return true; + + *result = last; + return true; +}; + + void +LOD_Vertex:: +AddEdge( + LOD_EdgeInd e +){ + m_edges.push_back(e); +}; + + void +LOD_Vertex:: +SwapEdge( + LOD_EdgeInd e_old, + LOD_EdgeInd e_new +){ + + vector<LOD_EdgeInd>::iterator result = + find(m_edges.begin(),m_edges.end(),e_old); + if (result == m_edges.end()) { + MT_assert(false); + LOD_MeshException e(LOD_MeshException::e_search_error); + throw(e); + } + + *result = e_new; +}; + + bool +LOD_Vertex:: +SelectTag( +) const { + return m_select_tag; +}; + + void +LOD_Vertex:: +SetSelectTag( + bool tag +){ + m_select_tag = tag; +}; + + bool +LOD_Vertex:: +Degenerate( +){ + return m_edges.empty(); +} + + void +LOD_Vertex:: +CopyPosition( + float *float_ptr +){ + pos.getValue(float_ptr); +} + + + +// Edge Methods +/////////////// + +LOD_Edge:: +LOD_Edge ( +) { + m_verts[0] = m_verts[1] = LOD_VertexInd::Empty(); + m_faces[0] = m_faces[1] = LOD_FaceInd::Empty(); +} + + bool +LOD_Edge:: +operator == ( + LOD_Edge & rhs +) { + // edges are the same if their vertex indices are the + // same!!! Other properties are not checked + + int matches = 0; + + if (this->m_verts[0] == rhs.m_verts[0]) { + ++matches; + } + if (this->m_verts[1] == rhs.m_verts[0]) { + ++matches; + } + if (this->m_verts[0] == rhs.m_verts[1]) { + ++matches; + } + if (this->m_verts[1] == rhs.m_verts[1]) { + ++matches; + } + + if (matches >= 2) { + return true; + } + return false; +} + +// Elementary helper methods +//////////////////////////// + + LOD_FaceInd +LOD_Edge:: +OpFace( + LOD_FaceInd f +) const { + if (f == m_faces[0]) { + return m_faces[1]; + } else + if (f == m_faces[1]) { + return m_faces[0]; + } else { + MT_assert(false); + LOD_MeshException e(LOD_MeshException::e_search_error); + throw(e); + + return LOD_FaceInd::Empty(); + } +} + + void +LOD_Edge:: +SwapFace( + LOD_FaceInd old_f, + LOD_FaceInd new_f +) { + if (old_f == m_faces[0]) { + m_faces[0] = new_f; + } else + if (old_f == m_faces[1]) { + m_faces[1] = new_f; + } else { + MT_assert(false); + + LOD_MeshException e(LOD_MeshException::e_search_error); + throw(e); + } +} + + +// return the half edge face - the half edge is defined +// by the {vertex,edge} tuple. + + LOD_FaceInd +LOD_Edge:: +HalfEdgeFace( + LOD_VertexInd vi +){ + if (vi == m_verts[0]) return m_faces[0]; + if (vi == m_verts[1]) return m_faces[1]; + MT_assert(false); + + LOD_MeshException e(LOD_MeshException::e_search_error); + throw(e); + + return LOD_FaceInd::Empty(); +} + + + LOD_VertexInd +LOD_Edge:: +OpVertex( + LOD_VertexInd vi +) { + if (vi == m_verts[0]) return m_verts[1]; + if (vi == m_verts[1]) return m_verts[0]; + MT_assert(false); + + LOD_MeshException e(LOD_MeshException::e_search_error); + throw(e); + + return LOD_VertexInd::Empty(); +} + +// replace the vertex v_old with vertex v_new +// error if v_old is not one of the original vertices + + void +LOD_Edge:: +SwapVertex( + LOD_VertexInd v_old, + LOD_VertexInd v_new +) { + if (v_old == m_verts[0]) { + m_verts[0] = v_new; + } else + if (v_old == m_verts[1]) { + m_verts[1] = v_new; + } else { + + MT_assert(false); + + LOD_MeshException e(LOD_MeshException::e_search_error); + throw(e); + } + if(m_verts[0] == m_verts[1]) { + MT_assert(false); + + LOD_MeshException e(LOD_MeshException::e_non_manifold); + throw(e); + } + +} + + bool +LOD_Edge:: +SelectTag( +) const { + return bool(m_verts[1].Tag() & 0x1); +}; + + void +LOD_Edge:: +SetSelectTag( + bool tag +) { + m_verts[1].SetTag(int(tag)); +}; + + int +LOD_Edge:: +OpenTag( +) const { + return m_faces[0].Tag(); +} + + void +LOD_Edge:: +SetOpenTag( + int tag +) { + m_faces[0].SetTag(tag); +} + + bool +LOD_Edge:: +Degenerate( +) const { + return ( + (m_faces[0].IsEmpty() && m_faces[1].IsEmpty()) || + (m_verts[0] == m_verts[1]) + ); +}; + +// TriFace Methods +////////////////// + +LOD_TriFace:: +LOD_TriFace( +) { + m_verts[0] = m_verts[1] = m_verts[2] = LOD_VertexInd::Empty(); +} + +// Elementary helper methods +//////////////////////////// + + void +LOD_TriFace:: +SwapVertex( + LOD_VertexInd old_v, + LOD_VertexInd new_v +) { + // could save branching here... + + if (m_verts[0] == old_v) { + m_verts[0] = new_v; + } else + if (m_verts[1] == old_v) { + m_verts[1] = new_v; + } else + if (m_verts[2] == old_v) { + m_verts[2] = new_v; + } else { + MT_assert(false); + + LOD_MeshException excep(LOD_MeshException::e_search_error); + throw(excep); + } +} + + bool +LOD_TriFace:: +SelectTag( +) const { + return bool(m_verts[1].Tag() & 0x1); +}; + + void +LOD_TriFace:: +SetSelectTag( + bool tag +) { + m_verts[1].SetTag(int(tag)); +}; + + int +LOD_TriFace:: +OpenTag( +) { + return m_verts[2].Tag(); +} + + void +LOD_TriFace:: +SetOpenTag( + int tag +) { + m_verts[2].SetTag(tag); +} + + bool +LOD_TriFace:: +Degenerate( +) { + + return ( + (m_verts[0] == m_verts[1]) || + (m_verts[1] == m_verts[2]) || + (m_verts[2] == m_verts[0]) + ); +} + + void +LOD_TriFace:: +CopyVerts( + int * index_ptr +){ + index_ptr[0] = m_verts[0]; + index_ptr[1] = m_verts[1]; + index_ptr[2] = m_verts[2]; +}; + + + + + + + + + diff --git a/intern/decimation/intern/LOD_MeshPrimitives.h b/intern/decimation/intern/LOD_MeshPrimitives.h new file mode 100644 index 00000000000..12214c7528d --- /dev/null +++ b/intern/decimation/intern/LOD_MeshPrimitives.h @@ -0,0 +1,221 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_MeshPrimitives_h + +#define NAN_INCLUDED_MeshPrimitives_h + +#include "MT_Vector3.h" +#include "CTR_TaggedIndex.h" +#include "CTR_UHeap.h" +#include <vector> + +typedef CTR_TaggedIndex<24,0x00ffffff> LOD_VertexInd; +typedef CTR_TaggedIndex<24,0x00ffffff> LOD_EdgeInd; +typedef CTR_TaggedIndex<24,0x00ffffff> LOD_FaceInd; +typedef CTR_TaggedIndex<24,0x00ffffff> LOD_HeapInd; + +class LOD_Vertex { +public : + MT_Vector3 pos; + std::vector<LOD_EdgeInd> m_edges; + bool m_select_tag; + + LOD_Vertex( + ) ; + + bool + RemoveEdge( + LOD_EdgeInd e + ); + + void + AddEdge( + LOD_EdgeInd e + ); + + void + SwapEdge( + LOD_EdgeInd e_old, + LOD_EdgeInd e_new + ); + + bool + SelectTag( + ) const; + + void + SetSelectTag( + bool tag + ); + + bool + Degenerate( + ); + + void + CopyPosition( + float *float_ptr + ); + +private : + + +}; + +class LOD_Edge : public CTR_UHeapable { +public : + LOD_VertexInd m_verts[2]; + LOD_FaceInd m_faces[2]; + + LOD_Edge ( + ); + + bool operator == ( + LOD_Edge & rhs + ); + + // Elementary helper methods + //////////////////////////// + + LOD_FaceInd + OpFace( + LOD_FaceInd f + ) const ; + + void + SwapFace( + LOD_FaceInd old_f, + LOD_FaceInd new_f + ) ; + + + // return the half edge face - the half edge is defined + // by the {vertex,edge} tuple. + + LOD_FaceInd + HalfEdgeFace( + LOD_VertexInd vi + ); + + + LOD_VertexInd + OpVertex( + LOD_VertexInd vi + ); + + // replace the vertex v_old with vertex v_new + // error if v_old is not one of the original vertices + + void + SwapVertex( + LOD_VertexInd v_old, + LOD_VertexInd v_new + ) ; + + bool + SelectTag( + ) const ; + + void + SetSelectTag( + bool tag + ); + + int + OpenTag( + ) const; + + void + SetOpenTag( + int tag + ) ; + + bool + Degenerate( + ) const; + + bool + BoundaryEdge( + ) const { + return (m_faces[0].IsEmpty() || m_faces[1].IsEmpty()); + }; + + +}; + +class LOD_TriFace { +public: + + LOD_VertexInd m_verts[3]; + + LOD_TriFace( + ); + + // Elementary helper methods + //////////////////////////// + + void + SwapVertex( + LOD_VertexInd old_v, + LOD_VertexInd new_v + ); + + bool + SelectTag( + ) const; + + void + SetSelectTag( + bool tag + ); + + int + OpenTag( + ); + void + SetOpenTag( + int tag + ); + + bool + Degenerate( + ); + + void + CopyVerts( + int * index_ptr + ); + +}; + +#endif + diff --git a/intern/decimation/intern/LOD_QSDecimator.cpp b/intern/decimation/intern/LOD_QSDecimator.cpp new file mode 100644 index 00000000000..6620fa15ad3 --- /dev/null +++ b/intern/decimation/intern/LOD_QSDecimator.cpp @@ -0,0 +1,324 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "LOD_QSDecimator.h" + +#include "LOD_ExternBufferEditor.h" + +using namespace std; + + LOD_QSDecimator * +LOD_QSDecimator:: +New( + LOD_ManMesh2 &mesh, + LOD_ExternNormalEditor &face_editor, + LOD_ExternBufferEditor &extern_editor +){ + + MEM_SmartPtr<LOD_QSDecimator> output + = new LOD_QSDecimator(mesh,face_editor,extern_editor); + + MEM_SmartPtr<LOD_EdgeCollapser > collapser(LOD_EdgeCollapser::New()); + MEM_SmartPtr<LOD_QuadricEditor> q_editor(LOD_QuadricEditor::New(mesh)); + + if ( + output == NULL || + collapser == NULL || + q_editor == NULL + ) { + return NULL; + } + output->m_collapser = collapser.Release(); + output->m_quadric_editor = q_editor.Release(); + return output.Release(); +} + + + + bool +LOD_QSDecimator:: +Arm( +){ + MT_assert(!m_is_armed); + bool heap_result = BuildHeap(); + if (!heap_result) { + return false; + } + m_is_armed = true; + return true; +} + + bool +LOD_QSDecimator:: +Step( +){ + return CollapseEdge(); +} + + +LOD_QSDecimator:: +LOD_QSDecimator( + LOD_ManMesh2 &mesh, + LOD_ExternNormalEditor &face_editor, + LOD_ExternBufferEditor &extern_editor +) : + m_mesh(mesh), + m_face_editor(face_editor), + m_extern_editor(extern_editor), + m_is_armed (false) +{ + m_deg_edges.reserve(32); + m_deg_faces.reserve(32); + m_deg_vertices.reserve(32); + m_update_faces.reserve(32); + m_new_edges.reserve(32); + m_update_vertices.reserve(32); +}; + + bool +LOD_QSDecimator:: +CollapseEdge( +){ + + // find an edge to collapse + + // FIXME force an edge collapse + // or return false + + std::vector<LOD_Edge> & edges = m_mesh.EdgeSet(); + std::vector<LOD_Vertex> & verts = m_mesh.VertexSet(); + std::vector<LOD_Quadric> & quadrics = m_quadric_editor->Quadrics(); + int size = edges.size(); + + if (size == 0) return false; + + const int heap_top = m_heap->Top(); + + if (heap_top == -1 || edges[heap_top].HeapKey() <= -MT_INFINITY) { + return false; + } + + // compute the target position + MT_Vector3 new_vertex = m_quadric_editor->TargetVertex(edges[heap_top]); + LOD_Quadric & q0 = quadrics[edges[heap_top].m_verts[0]]; + LOD_Quadric & q1 = quadrics[edges[heap_top].m_verts[1]]; + + LOD_Vertex &v0 = verts[edges[heap_top].m_verts[0]]; + LOD_Vertex &v1 = verts[edges[heap_top].m_verts[1]]; + + LOD_Quadric sum = q0; + sum += q1; + + + if (m_collapser->CollapseEdge( + heap_top, + m_mesh, + m_deg_edges, + m_deg_faces, + m_deg_vertices, + m_new_edges, + m_update_faces, + m_update_vertices + )) { + + // assign new vertex position + + v0.pos = new_vertex; + v1.pos = new_vertex; + + // sum the quadrics of v0 and v1 + q0 = sum; + q1 = sum; + + // ok update the primitive properties + + m_face_editor.Update(m_update_faces); + m_face_editor.UpdateVertexNormals(m_update_vertices); + + // update the external vertex buffer + m_extern_editor.CopyModifiedVerts(m_mesh,m_update_vertices); + + // update the external face buffer + m_extern_editor.CopyModifiedFaces(m_mesh,m_update_faces); + + // update the edge heap + UpdateHeap(m_deg_edges,m_new_edges); + + m_quadric_editor->Remove(m_deg_vertices); + m_face_editor.Remove(m_deg_faces); + m_face_editor.RemoveVertexNormals(m_deg_vertices); + + // delete the primitives + + DeletePrimitives(m_deg_edges,m_deg_faces,m_deg_vertices); + + } else { + // the edge could not be collapsed at the moment - so + // we adjust it's priority and add it back to the heap. + m_heap->Remove(edges.begin(),0); + edges[heap_top].HeapKey() = - MT_INFINITY; + m_heap->Insert(edges.begin(),heap_top); + } + + //clear all the temporary buffers + + m_deg_faces.clear(); + m_deg_edges.clear(); + m_deg_vertices.clear(); + + m_update_faces.clear(); + m_update_vertices.clear(); + m_new_edges.clear(); + + return true; + +} + + void +LOD_QSDecimator:: +DeletePrimitives( + const vector<LOD_EdgeInd> & degenerate_edges, + const vector<LOD_FaceInd> & degenerate_faces, + const vector<LOD_VertexInd> & degenerate_vertices +) { + + // assumes that the 3 vectors are sorted in descending order. + + // Delete Degnerate primitives + ////////////////////////////// + + + // delete the old edges - we have to be very careful here + // mesh.delete() swaps edges to be deleted with the last edge in + // the edge buffer. However the next edge to be deleted may have + // been the last edge in the buffer! + + // One way to solve this is to sort degenerate_edges in descending order. + // And then delete them in that order. + + // it is also vital that degenerate_edges contains no duplicates + + vector<LOD_EdgeInd>::const_iterator edge_it = degenerate_edges.begin(); + vector<LOD_EdgeInd>::const_iterator edge_end = degenerate_edges.end(); + + for (; edge_it != edge_end; ++edge_it) { + m_mesh.DeleteEdge(*edge_it,m_heap); + } + + + + vector<LOD_FaceInd>::const_iterator face_it = degenerate_faces.begin(); + vector<LOD_FaceInd>::const_iterator face_end = degenerate_faces.end(); + + for (;face_it != face_end; ++face_it) { + m_mesh.DeleteFace(m_extern_editor,*face_it); + } + + vector<LOD_VertexInd>::const_iterator vertex_it = degenerate_vertices.begin(); + vector<LOD_VertexInd>::const_iterator vertex_end = degenerate_vertices.end(); + + for (;vertex_it != vertex_end; ++vertex_it) { + m_mesh.DeleteVertex(m_extern_editor,*vertex_it); + } +} + + + bool +LOD_QSDecimator:: +BuildHeap( +){ + // build the quadrics + + if (m_quadric_editor->BuildQuadrics(m_face_editor,true) == false) return false; + + + m_heap = CTR_UHeap<LOD_Edge>::New(); + // load in edge pointers to the heap + + std::vector<LOD_Edge> & edge_set= m_mesh.EdgeSet(); + std::vector<LOD_Edge>::const_iterator edge_end = edge_set.end(); + std::vector<LOD_Edge>::iterator edge_start = edge_set.begin(); + + std::vector<int> & heap_vector = m_heap->HeapVector(); + + for (int i = 0; i < edge_set.size(); ++i) { + edge_set[i].HeapPos() = i; + heap_vector.push_back(i); + } + + m_heap->MakeHeap(edge_set.begin()); + + return true; +} + + void +LOD_QSDecimator:: +UpdateHeap( + std::vector<LOD_EdgeInd> °_edges, + std::vector<LOD_EdgeInd> &new_edges +){ + // first of all compute values for the new edges + // and bung them on the heap. + + std::vector<LOD_Edge> & edge_set= m_mesh.EdgeSet(); + + std::vector<LOD_EdgeInd>::const_iterator edge_it = new_edges.begin(); + std::vector<LOD_EdgeInd>::const_iterator end_it = new_edges.end(); + + + // insert all the new edges + /////////////////////////// + + // compute edge costs ffor the new edges + + m_quadric_editor->ComputeEdgeCosts(new_edges); + + // inser the new elements into the heap + + for (; edge_it != end_it; ++edge_it) { + m_heap->Insert(edge_set.begin(),*edge_it); + } + + + // remove all the old values from the heap + + edge_it = deg_edges.begin(); + end_it = deg_edges.end(); + + for (; edge_it != end_it; ++edge_it) { + LOD_Edge &e = edge_set[*edge_it]; + m_heap->Remove(edge_set.begin(),e.HeapPos()); + + e.HeapPos() = 0xffffffff; + + } +} + diff --git a/intern/decimation/intern/LOD_QSDecimator.h b/intern/decimation/intern/LOD_QSDecimator.h new file mode 100644 index 00000000000..c5ae915db29 --- /dev/null +++ b/intern/decimation/intern/LOD_QSDecimator.h @@ -0,0 +1,128 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_LOD_QSDecimator_H + +#define NAN_INCLUDED_LOD_QSDecimator_H + +#include "MEM_NonCopyable.h" +#include "LOD_ManMesh2.h" +#include "LOD_ExternNormalEditor.h" +#include "LOD_EdgeCollapser.h" +#include "LOD_QuadricEditor.h" + +class LOD_ExternBufferEditor; + +class LOD_QSDecimator : public MEM_NonCopyable { + +public : + + static + LOD_QSDecimator * + New( + LOD_ManMesh2 &mesh, + LOD_ExternNormalEditor &face_editor, + LOD_ExternBufferEditor &extern_editor + ); + + + bool + Arm( + ); + + + bool + Step( + ); + +private : + + LOD_QSDecimator( + LOD_ManMesh2 &mesh, + LOD_ExternNormalEditor &face_editor, + LOD_ExternBufferEditor &extern_editor + ); + + bool + CollapseEdge( + ); + + bool + BuildHeap( + ); + + void + UpdateHeap( + std::vector<LOD_EdgeInd> °_edges, + std::vector<LOD_EdgeInd> &new_edges + ); + + void + DeletePrimitives( + const std::vector<LOD_EdgeInd> & degenerate_edges, + const std::vector<LOD_FaceInd> & degenerate_faces, + const std::vector<LOD_VertexInd> & degenerate_vertices + ); + + +private : + + // owned by this class + ////////////////////// + + MEM_SmartPtr<LOD_EdgeCollapser> m_collapser; + MEM_SmartPtr<CTR_UHeap<LOD_Edge> > m_heap; + MEM_SmartPtr<LOD_QuadricEditor> m_quadric_editor; + + bool m_is_armed; + + // arguments to New(...) + //////////////////////// + + LOD_ManMesh2 & m_mesh; + LOD_ExternNormalEditor &m_face_editor; + LOD_ExternBufferEditor & m_extern_editor; + + // temporary buffers + //////////////////// + + std::vector<LOD_FaceInd> m_deg_faces; + std::vector<LOD_EdgeInd> m_deg_edges; + std::vector<LOD_VertexInd> m_deg_vertices; + + std::vector<LOD_FaceInd> m_update_faces; + std::vector<LOD_EdgeInd> m_new_edges; + std::vector<LOD_VertexInd> m_update_vertices; + + +}; +#endif + diff --git a/intern/decimation/intern/LOD_Quadric.h b/intern/decimation/intern/LOD_Quadric.h new file mode 100644 index 00000000000..16e7dec17e9 --- /dev/null +++ b/intern/decimation/intern/LOD_Quadric.h @@ -0,0 +1,168 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_LOD_Quadric_h + +#define NAN_INCLUDED_LOD_Quadric_h + +#include "MT_Vector3.h" +#include "MT_Matrix3x3.h" + + +class LOD_Quadric { + +private: + MT_Scalar a2, ab, ac, ad; + MT_Scalar b2, bc, bd; + MT_Scalar c2, cd; + MT_Scalar d2; + + void init(MT_Scalar a, MT_Scalar b, MT_Scalar c, MT_Scalar d); + +public: + + LOD_Quadric( + ) { + Clear(); + }; + + LOD_Quadric( + const MT_Vector3 & vec, + const MT_Scalar & offset + ) { + a2 = vec[0] *vec[0]; + b2 = vec[1] *vec[1]; + c2 = vec[2] *vec[2]; + + ab = vec[0]*vec[1]; + ac = vec[0]*vec[2]; + bc = vec[1]*vec[2]; + + MT_Vector3 temp = vec*offset; + ad = temp[0]; + bd = temp[1]; + cd = temp[2]; + + d2 = offset*offset; + }; + + MT_Matrix3x3 + Tensor( + ) const { + // return a symmetric matrix + + return MT_Matrix3x3( + a2,ab,ac, + ab,b2,bc, + ac,bc,c2 + ); + }; + + + MT_Vector3 + Vector( + ) const { + return MT_Vector3(ad, bd, cd); + }; + + void + Clear( + MT_Scalar val=0.0 + ) { + a2=ab=ac=ad=b2=bc=bd=c2=cd=d2=val; + }; + + LOD_Quadric & + operator=( + const LOD_Quadric& Q + ) { + + a2 = Q.a2; ab = Q.ab; ac = Q.ac; ad = Q.ad; + b2 = Q.b2; bc = Q.bc; bd = Q.bd; + c2 = Q.c2; cd = Q.cd; + d2 = Q.d2; + return *this; + }; + + LOD_Quadric& + operator+=( + const LOD_Quadric& Q + ) { + a2 += Q.a2; ab += Q.ab; ac += Q.ac; ad += Q.ad; + b2 += Q.b2; bc += Q.bc; bd += Q.bd; + c2 += Q.c2; cd += Q.cd; + d2 += Q.d2; + return *this; + }; + + LOD_Quadric& + operator*=( + const MT_Scalar & s + ) { + a2 *= s; ab *= s; ac *= s; ad *= s; + b2 *= s; bc *= s; bd *= s; + c2 *= s; cd *= s; + d2 *= s; + return *this; + }; + + + MT_Scalar + Evaluate( + const MT_Vector3 &v + ) const { + // compute the LOD_Quadric error + + return v[0]*v[0]*a2 + 2*v[0]*v[1]*ab + 2*v[0]*v[2]*ac + 2*v[0]*ad + +v[1]*v[1]*b2 + 2*v[1]*v[2]*bc + 2*v[1]*bd + +v[2]*v[2]*c2 + 2*v[2]*cd + + d2; + }; + + bool + Optimize( + MT_Vector3& v + ) const { + + MT_Scalar det = Tensor().determinant(); + if (MT_fuzzyZero(det)) { + return false; + } + + v = -((Tensor().inverse()) * Vector()); + return true; + }; + +}; + + +#endif + diff --git a/intern/decimation/intern/LOD_QuadricEditor.cpp b/intern/decimation/intern/LOD_QuadricEditor.cpp new file mode 100644 index 00000000000..751f5d1e7e0 --- /dev/null +++ b/intern/decimation/intern/LOD_QuadricEditor.cpp @@ -0,0 +1,279 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "LOD_QuadricEditor.h" + +#include "LOD_ExternNormalEditor.h" + +// Creation +/////////// + +using namespace std; + + +LOD_QuadricEditor:: +LOD_QuadricEditor( + LOD_ManMesh2 &mesh +) : + m_quadrics(NULL), + m_mesh(mesh) +{ +}; + + LOD_QuadricEditor * +LOD_QuadricEditor:: +New( + LOD_ManMesh2 &mesh +){ + //same number of quadrics as vertices in the mesh + + MEM_SmartPtr<LOD_QuadricEditor> output(new LOD_QuadricEditor(mesh)); + + if (output == NULL) { + return NULL; + } + return output.Release(); +} + + +// Property editor interface +//////////////////////////// + + void +LOD_QuadricEditor:: +Remove( + std::vector<LOD_VertexInd> &sorted_vertices +){ + vector<LOD_Quadric> & quadrics = *m_quadrics; + + vector<LOD_VertexInd>::const_iterator it_start = sorted_vertices.begin(); + vector<LOD_VertexInd>::const_iterator it_end = sorted_vertices.end(); + + for (; it_start != it_end; ++it_start) { + + if (quadrics.size() > 0) { + LOD_Quadric temp = quadrics[*it_start]; + + quadrics[*it_start] = quadrics.back(); + quadrics.back() = temp; + + quadrics.pop_back(); + } + } +}; + + +// Editor specific methods +////////////////////////// + + bool +LOD_QuadricEditor:: +BuildQuadrics( + LOD_ExternNormalEditor& normal_editor, + bool preserve_boundaries +){ + if (m_quadrics != NULL) delete(m_quadrics); + + m_quadrics =new vector<LOD_Quadric> (m_mesh.VertexSet().size()); + if (m_quadrics == NULL) return false; + + // iterate through the face set of the mesh + // compute a quadric based upon that face and + // add it to each of it's vertices quadrics. + + const vector<LOD_TriFace> &faces = m_mesh.FaceSet(); + const vector<LOD_Vertex> &verts = m_mesh.VertexSet(); + vector<LOD_Edge> &edges = m_mesh.EdgeSet(); + + const vector<MT_Vector3> &normals = normal_editor.Normals(); + vector<MT_Vector3>::const_iterator normal_it = normals.begin(); + + vector<LOD_TriFace>::const_iterator face_it = faces.begin(); + vector<LOD_TriFace>::const_iterator face_end = faces.end(); + + vector<LOD_Quadric> & quadrics = *m_quadrics; + + + for (; face_it != face_end; ++face_it, ++normal_it) { + + MT_Vector3 normal = *normal_it; + MT_Scalar offset = -normal.dot(verts[face_it->m_verts[0]].pos); + + LOD_Quadric q(normal,offset); + + quadrics[face_it->m_verts[0]] += q; + quadrics[face_it->m_verts[1]] += q; + quadrics[face_it->m_verts[2]] += q; + } + + if (preserve_boundaries) { + + // iterate through the edge set and add a boundary quadric to + // each of the boundary edges vertices. + + vector<LOD_Edge>::const_iterator edge_it = edges.begin(); + vector<LOD_Edge>::const_iterator edge_end = edges.end(); + + for (; edge_it != edge_end; ++edge_it) { + if (edge_it->BoundaryEdge()) { + + // compute a plane perpendicular to the edge and the normal + // of the edges single polygon. + const MT_Vector3 & v0 = verts[edge_it->m_verts[0]].pos; + const MT_Vector3 & v1 = verts[edge_it->m_verts[1]].pos; + + MT_Vector3 edge_vector = v1 - v0; + + LOD_FaceInd edge_face = edge_it->OpFace(LOD_EdgeInd::Empty()); + edge_vector = edge_vector.cross(normals[edge_face]); + + if (!edge_vector.fuzzyZero()) { + edge_vector.normalize(); + + LOD_Quadric boundary_q(edge_vector, - edge_vector.dot(v0)); + boundary_q *= 100; + + quadrics[edge_it->m_verts[0]] += boundary_q; + quadrics[edge_it->m_verts[1]] += boundary_q; + } + } + } + } + + + // initiate the heap keys of the edges by computing the edge costs. + + vector<LOD_Edge>::iterator edge_it = edges.begin(); + vector<LOD_Edge>::const_iterator edge_end = edges.end(); + + for (; edge_it != edge_end; ++edge_it) { + + MT_Vector3 target = TargetVertex(*edge_it); + + LOD_Edge &e = *edge_it; + LOD_Quadric q0 = quadrics[e.m_verts[0]]; + const LOD_Quadric &q1 = quadrics[e.m_verts[1]]; + + e.HeapKey() = -float(q0.Evaluate(target) + q1.Evaluate(target)); + } + + return true; + +}; + + MT_Vector3 +LOD_QuadricEditor:: +TargetVertex( + LOD_Edge & e +){ + + // compute an edge contration target for edge ei + // this is computed by summing it's vertices quadrics and + // optimizing the result. + vector<LOD_Vertex> &verts = m_mesh.VertexSet(); + + vector<LOD_Quadric> &quadrics = *m_quadrics; + + LOD_VertexInd v0 = e.m_verts[0]; + LOD_VertexInd v1 = e.m_verts[1]; + + LOD_Quadric q0 = quadrics[v0]; + q0 += quadrics[v1]; + + MT_Vector3 result; + + if (q0.Optimize(result)) { + return result; + } else { + // the quadric was degenerate -> just take the average of + // v0 and v1 + + return ((verts[v0].pos + verts[v1].pos) * 0.5); + } +}; + + void +LOD_QuadricEditor:: +ComputeEdgeCosts( + vector<LOD_EdgeInd> &edges +){ + + // for each we compute the target vertex and then compute + // the quadric error e = Q1(v') + Q2(v') + vector<LOD_Edge> &edge_set = m_mesh.EdgeSet(); + + vector<LOD_Quadric> &quadrics = *m_quadrics; + + vector<LOD_EdgeInd>::const_iterator edge_it = edges.begin(); + vector<LOD_EdgeInd>::const_iterator edge_end = edges.end(); + + for (; edge_it != edge_end; ++edge_it) { + + MT_Vector3 target = TargetVertex(edge_set[*edge_it]); + + LOD_Edge &e = edge_set[*edge_it]; + LOD_Quadric q0 = quadrics[e.m_verts[0]]; + const LOD_Quadric &q1 = quadrics[e.m_verts[1]]; + + e.HeapKey() = -float(q0.Evaluate(target) + q1.Evaluate(target)); + } +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/intern/decimation/intern/LOD_QuadricEditor.h b/intern/decimation/intern/LOD_QuadricEditor.h new file mode 100644 index 00000000000..bb3a5e957b9 --- /dev/null +++ b/intern/decimation/intern/LOD_QuadricEditor.h @@ -0,0 +1,119 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_LOD_QuadricEditor_h + +#define NAN_INCLUDED_LOD_QuadricEditor_h + +#include "MEM_NonCopyable.h" +#include "LOD_ManMesh2.h" +#include "MT_Vector3.h" +#include "LOD_Quadric.h" + +class LOD_ExternNormalEditor; + + +class LOD_QuadricEditor : public MEM_NonCopyable +{ + +public : + + // Creation + /////////// + + static + LOD_QuadricEditor * + New( + LOD_ManMesh2 &mesh + ); + + // Property editor interface + //////////////////////////// + + void + Remove( + std::vector<LOD_VertexInd> &sorted_vertices + ); + + void + Update( + std::vector<LOD_FaceInd> &sorted_vertices + ); + + + std::vector<LOD_Quadric> & + Quadrics( + ) const { + return *m_quadrics; + }; + + + // Editor specific methods + ////////////////////////// + + bool + BuildQuadrics( + LOD_ExternNormalEditor& normal_editor, + bool preserve_boundaries + ); + + + void + ComputeEdgeCosts( + std::vector<LOD_EdgeInd> &edges + ); + + MT_Vector3 + TargetVertex( + LOD_Edge &e + ); + + ~LOD_QuadricEditor( + ){ + delete(m_quadrics); + }; + + +private : + + std::vector<LOD_Quadric> * m_quadrics; + + LOD_ManMesh2 &m_mesh; + +private : + + LOD_QuadricEditor(LOD_ManMesh2 &mesh); + + + +}; + +#endif diff --git a/intern/decimation/intern/LOD_decimation.cpp b/intern/decimation/intern/LOD_decimation.cpp new file mode 100644 index 00000000000..7bbc0945424 --- /dev/null +++ b/intern/decimation/intern/LOD_decimation.cpp @@ -0,0 +1,156 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +// implementation of external c api + + +#include "../extern/LOD_decimation.h" +#include "LOD_DecimationClass.h" + +using namespace std; + + int +LOD_LoadMesh( + LOD_Decimation_InfoPtr info +) { + if (info == NULL) return 0; + if ( + info->vertex_buffer == NULL || + info->vertex_normal_buffer == NULL || + info->triangle_index_buffer == NULL + ) { + return 0; + } + + + // create the intern object to hold all + // the decimation classes + + MEM_SmartPtr<LOD_DecimationClass> intern(LOD_DecimationClass::New(info)); + + if (intern == NULL) return 0; + + MEM_SmartPtr<vector<LOD_Vertex> > intern_vertex_buffer(new vector<LOD_Vertex>(info->vertex_num)); + if (intern_vertex_buffer == NULL) return 0; + + vector<LOD_Vertex>::iterator intern_vertex_it(intern_vertex_buffer->begin()); + + // now load in the vertices to the mesh + + const int vertex_stride = 3; + + float * vertex_ptr = info->vertex_buffer; + const float * vertex_end = vertex_ptr + info->vertex_num*vertex_stride; + + LOD_ManMesh2 &mesh = intern->Mesh(); + + for (;vertex_ptr < vertex_end; vertex_ptr += vertex_stride,++intern_vertex_it) { + intern_vertex_it->pos = MT_Vector3(vertex_ptr); + } + + mesh.SetVertices(intern_vertex_buffer); + + // load in the triangles + + const int triangle_stride = 3; + + int * triangle_ptr = info->triangle_index_buffer; + const int * triangle_end = triangle_ptr + info->face_num*triangle_stride; + + try { + + for (;triangle_ptr < triangle_end; triangle_ptr += triangle_stride) { + mesh.AddTriangle(triangle_ptr); + } + } + + catch (...) { + return 0; + } + + // ok we have built the mesh + + intern->m_e_decimation_state = LOD_DecimationClass::e_loaded; + + info->intern = (void *) (intern.Release()); + + return 1; +} + + int +LOD_PreprocessMesh( + LOD_Decimation_InfoPtr info +) { + if (info == NULL) return 0; + if (info->intern == NULL) return 0; + + LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern; + if (intern->m_e_decimation_state != LOD_DecimationClass::e_loaded) return 0; + + // arm the various internal classes so that we are ready to step + // through decimation + + intern->FaceEditor().BuildNormals(); + if (intern->Decimator().Arm() == false) return 0; + + // ok preprocessing done + intern->m_e_decimation_state = LOD_DecimationClass::e_preprocessed; + + return 1; +} + + int +LOD_CollapseEdge( + LOD_Decimation_InfoPtr info +){ + if (info == NULL) return 0; + if (info->intern == NULL) return 0; + LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern; + if (intern->m_e_decimation_state != LOD_DecimationClass::e_preprocessed) return 0; + + bool step_result = intern->Decimator().Step(); + + return step_result == true ? 1 : 0; +} + + + int +LOD_FreeDecimationData( + LOD_Decimation_InfoPtr info +){ + if (info == NULL) return 0; + if (info->intern == NULL) return 0; + LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern; + delete(intern); + info->intern = NULL; + return 1; +} + diff --git a/intern/decimation/intern/Makefile b/intern/decimation/intern/Makefile new file mode 100644 index 00000000000..d7c9d89d9c7 --- /dev/null +++ b/intern/decimation/intern/Makefile @@ -0,0 +1,45 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# decimation intern Makefile +# + +LIBNAME = decimation +DIR = $(OCGDIR)/intern/$(LIBNAME) + +include nan_compile.mk + +CCFLAGS += $(NAN_LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I$(NAN_MOTO)/include +CPPFLAGS += -I$(NAN_MEMUTIL)/include +CPPFLAGS += -I$(NAN_CONTAINER)/include + + diff --git a/intern/decimation/make/msvc_6_0/decimation.dsp b/intern/decimation/make/msvc_6_0/decimation.dsp new file mode 100644 index 00000000000..32d6928c61a --- /dev/null +++ b/intern/decimation/make/msvc_6_0/decimation.dsp @@ -0,0 +1,188 @@ +# Microsoft Developer Studio Project File - Name="decimation" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=decimation - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "decimation.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "decimation.mak" CFG="decimation - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "decimation - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "decimation - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "decimation - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /Ob2 /I "..\..\..\..\lib\windows\container\include\\" /I "..\..\..\..\lib\windows\memutil\include\\" /I "..\..\..\..\lib\windows\moto\include\\" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x413 /d "NDEBUG" +# ADD RSC /l 0x413 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Release\libdecimation.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=ECHO Copying header files COPY "..\..\extern\*.h" "..\..\..\..\lib\windows\decimation\include" ECHO Copying lib COPY "Release\libdecimation.lib" "..\..\..\..\lib\windows\decimation\lib\libdecimation.a" ECHO Done +# End Special Build Tool + +!ELSEIF "$(CFG)" == "decimation - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W4 /Gm /GX /ZI /Od /I "..\..\..\..\lib\windows\container\include\\" /I "..\..\..\..\lib\windows\memutil\include\\" /I "..\..\..\..\lib\windows\moto\include\\" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x413 /d "_DEBUG" +# ADD RSC /l 0x413 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\libdecimation.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=ECHO Copying header files COPY "..\..\extern\*.h" "..\..\..\..\lib\windows\decimation\include" ECHO Copying lib COPY "Debug\libdecimation.lib" "..\..\..\..\lib\windows\decimation\lib\debug\libdecimation.a" ECHO Copying Debug info. COPY "Debug\vc60.*" "..\..\..\..\lib\windows\decimation\lib\debug\" ECHO Done +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "decimation - Win32 Release" +# Name "decimation - Win32 Debug" +# Begin Group "intern" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\intern\LOD_decimation.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_DecimationClass.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_EdgeCollapser.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_EdgeCollapser.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_ExternBufferEditor.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_ExternNormalEditor.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_ExternNormalEditor.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_FaceNormalEditor.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_FaceNormalEditor.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_ManMesh2.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_ManMesh2.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_MeshBounds.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_MeshException.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_MeshPrimitives.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_MeshPrimitives.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_QSDecimator.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_QSDecimator.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_Quadric.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_QuadricEditor.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_QuadricEditor.h +# End Source File +# End Group +# Begin Group "extern" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\extern\LOD_decimation.h +# End Source File +# End Group +# End Target +# End Project diff --git a/intern/decimation/make/msvc_6_0/decimation.dsw b/intern/decimation/make/msvc_6_0/decimation.dsw new file mode 100644 index 00000000000..f874b324725 --- /dev/null +++ b/intern/decimation/make/msvc_6_0/decimation.dsw @@ -0,0 +1,33 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "decimation"=.\decimation.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + + + + + diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h new file mode 100644 index 00000000000..10b986a55b0 --- /dev/null +++ b/intern/ghost/GHOST_C-api.h @@ -0,0 +1,733 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef GHOST_C_API_H + +#define GHOST_C_API_H + +#include "GHOST_Types.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#define GHOST_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name + +GHOST_DECLARE_HANDLE(GHOST_SystemHandle); +GHOST_DECLARE_HANDLE(GHOST_TimerTaskHandle); +GHOST_DECLARE_HANDLE(GHOST_WindowHandle); +GHOST_DECLARE_HANDLE(GHOST_EventHandle); +GHOST_DECLARE_HANDLE(GHOST_RectangleHandle); +GHOST_DECLARE_HANDLE(GHOST_EventConsumerHandle); + + +/** + * Definition of a callback routine that receives events. + * @param event The event received. + * @param userdata The callback's user data, supplied to GHOST_CreateSystem. + */ +typedef int (*GHOST_EventCallbackProcPtr)(GHOST_EventHandle event, GHOST_TUserDataPtr userdata); + + +/** + * Creates the one and only system. + * @return a handle to the system. + */ +extern GHOST_SystemHandle GHOST_CreateSystem(void); + +/** + * Disposes the one and only system. + * @param systemhandle The handle to the system + * @return An indication of success. + */ +extern GHOST_TSuccess GHOST_DisposeSystem(GHOST_SystemHandle systemhandle); + + +/** + * Creates an event consumer object + * @param eventCallback The event callback routine. + * @param userdata Pointer to user data returned to the callback routine. + */ +extern GHOST_EventConsumerHandle GHOST_CreateEventConsumer(GHOST_EventCallbackProcPtr eventCallback, GHOST_TUserDataPtr userdata); + +/** + * Disposes an event consumer object + * @param consumerhandle Handle to the event consumer. + * @return An indication of success. + */ +extern GHOST_TSuccess GHOST_DisposeEventConsumer(GHOST_EventConsumerHandle consumerhandle); + + +/** + * Returns the system time. + * Returns the number of milliseconds since the start of the system process. + * Based on ANSI clock() routine. + * @param systemhandle The handle to the system + * @return The number of milliseconds. + */ +extern GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle); + +/** + * Installs a timer. + * Note that, on most operating systems, messages need to be processed in order + * for the timer callbacks to be invoked. + * @param systemhandle The handle to the system + * @param delay The time to wait for the first call to the timerProc (in milliseconds) + * @param interval The interval between calls to the timerProc (in milliseconds) + * @param timerProc The callback invoked when the interval expires, + * @param userData Placeholder for user data. + * @return A timer task (0 if timer task installation failed). + */ +extern GHOST_TimerTaskHandle GHOST_InstallTimer(GHOST_SystemHandle systemhandle, + GHOST_TUns64 delay, + GHOST_TUns64 interval, + GHOST_TimerProcPtr timerProc, + GHOST_TUserDataPtr userData); + +/** + * Removes a timer. + * @param systemhandle The handle to the system + * @param timerTask Timer task to be removed. + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_RemoveTimer(GHOST_SystemHandle systemhandle, + GHOST_TimerTaskHandle timertaskhandle); + +/*************************************************************************************** + ** Display/window management functionality + ***************************************************************************************/ + +/** + * Returns the number of displays on this system. + * @param systemhandle The handle to the system + * @return The number of displays. + */ +extern GHOST_TUns8 GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle); + +/** + * Returns the dimensions of the main display on this system. + * @param systemhandle The handle to the system + * @param width A pointer the width gets put in + * @param height A pointer the height gets put in + * @return void. + */ +extern void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle, + GHOST_TUns32* width, + GHOST_TUns32* height); + +/** + * Create a new window. + * The new window is added to the list of windows managed. + * Never explicitly delete the window, use disposeWindow() instead. + * @param systemhandle The handle to the system + * @param title The name of the window (displayed in the title bar of the window if the OS supports it). + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param height The height the window. + * @param state The state of the window when opened. + * @param type The type of drawing context installed in this window. + * @return A handle to the new window ( == NULL if creation failed). + */ +extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, + char* title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + const int stereoVisual); + +/** + * Returns the window user data. + * @param windowhandle The handle to the window + * @return The window user data. + */ +extern GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandle); + +/** + * Changes the window user data. + * @param windowhandle The handle to the window + * @param data The window user data. + */ +extern void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, + GHOST_TUserDataPtr userdata); + +/** + * Dispose a window. + * @param systemhandle The handle to the system + * @param window Handle to the window to be disposed. + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle, + GHOST_WindowHandle windowhandle); + +/** + * Returns whether a window is valid. + * @param systemhandle The handle to the system + * @param window Handle to the window to be checked. + * @return Indication of validity. + */ +extern int GHOST_ValidWindow(GHOST_SystemHandle systemhandle, + GHOST_WindowHandle windowhandle); + +/** + * Begins full screen mode. + * @param systemhandle The handle to the system + * @param setting The new setting of the display. + * @return A handle to the window displayed in full screen. + * This window is invalid after full screen has been ended. + */ +extern GHOST_WindowHandle GHOST_BeginFullScreen(GHOST_SystemHandle systemhandle, + GHOST_DisplaySetting* setting, + const int stereoVisual); + +/** + * Ends full screen mode. + * @param systemhandle The handle to the system + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_EndFullScreen(GHOST_SystemHandle systemhandle); + +/** + * Returns current full screen mode status. + * @param systemhandle The handle to the system + * @return The current status. + */ +extern int GHOST_GetFullScreen(GHOST_SystemHandle systemhandle); + +/*************************************************************************************** + ** Event management functionality + ***************************************************************************************/ + +/** + * Retrieves events from the system and stores them in the queue. + * @param systemhandle The handle to the system + * @param waitForEvent Boolean to indicate that ProcessEvents should + * wait (block) until the next event before returning. + * @return Indication of the presence of events. + */ +extern int GHOST_ProcessEvents(GHOST_SystemHandle systemhandle, int waitForEvent); + +/** + * Retrieves events from the queue and send them to the event consumers. + * @param systemhandle The handle to the system + * @return Indication of the presence of events. + */ +extern int GHOST_DispatchEvents(GHOST_SystemHandle systemhandle); + +/** + * Adds the given event consumer to our list. + * @param systemhandle The handle to the system + * @param consumerhandle The event consumer to add. + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_AddEventConsumer(GHOST_SystemHandle systemhandle, + GHOST_EventConsumerHandle consumerhandle); + + + +/*************************************************************************************** + ** Cursor management functionality + ***************************************************************************************/ + +/** + * Returns the current cursor shape. + * @param windowhandle The handle to the window + * @return The current cursor shape. + */ +extern GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandle); + +/** + * Set the shape of the cursor. + * @param windowhandle The handle to the window + * @param cursor The new cursor shape type id. + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_SetCursorShape(GHOST_WindowHandle windowhandle, + GHOST_TStandardCursor cursorshape); + +/** + * Set the shape of the cursor to a custom cursor. + * @param windowhandle The handle to the window + * @param bitmap The bitmap data for the cursor. + * @param mask The mask data for the cursor. + * @param hotX The X coordinate of the cursor hotspot. + * @param hotY The Y coordinate of the cursor hotspot. + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle, + GHOST_TUns8 bitmap[16][2], + GHOST_TUns8 mask[16][2], + int hotX, + int hotY); + +/** + * Returns the visibility state of the cursor. + * @param windowhandle The handle to the window + * @return The visibility state of the cursor. + */ +extern int GHOST_GetCursorVisibility(GHOST_WindowHandle windowhandle); + +/** + * Shows or hides the cursor. + * @param windowhandle The handle to the window + * @param visible The new visibility state of the cursor. + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_SetCursorVisibility(GHOST_WindowHandle windowhandle, + int visible); + +/** + * Returns the current location of the cursor (location in screen coordinates) + * @param systemhandle The handle to the system + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle, + GHOST_TInt32* x, + GHOST_TInt32* y); + +/** + * Updates the location of the cursor (location in screen coordinates). + * Not all operating systems allow the cursor to be moved (without the input device being moved). + * @param systemhandle The handle to the system + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle, + GHOST_TInt32 x, + GHOST_TInt32 y); + +/*************************************************************************************** + ** Access to mouse button and keyboard states. + ***************************************************************************************/ + +/** + * Returns the state of a modifier key (ouside the message queue). + * @param systemhandle The handle to the system + * @param mask The modifier key state to retrieve. + * @param isDown Pointer to return modifier state in. + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle, + GHOST_TModifierKeyMask mask, + int* isDown); + +/** + * Returns the state of a mouse button (ouside the message queue). + * @param systemhandle The handle to the system + * @param mask The button state to retrieve. + * @param isDown Pointer to return button state in. + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle, + GHOST_TButtonMask mask, + int* isDown); + +/** + * Returns the event type. + * @param eventhandle The handle to the event + * @return The event type. + */ +extern GHOST_TEventType GHOST_GetEventType(GHOST_EventHandle eventhandle); + +/** + * Returns the time this event was generated. + * @param eventhandle The handle to the event + * @return The event generation time. + */ +extern GHOST_TUns64 GHOST_GetEventTime(GHOST_EventHandle eventhandle); + +/** + * Returns the window this event was generated on, + * or NULL if it is a 'system' event. + * @param eventhandle The handle to the event + * @return The generating window. + */ +extern GHOST_WindowHandle GHOST_GetEventWindow(GHOST_EventHandle eventhandle); + +/** + * Returns the event data. + * @param eventhandle The handle to the event + * @return The event data. + */ +extern GHOST_TEventDataPtr GHOST_GetEventData(GHOST_EventHandle eventhandle); + +/** + * Returns the timer callback. + * @param timertaskhandle The handle to the timertask + * @return The timer callback. + */ +extern GHOST_TimerProcPtr GHOST_GetTimerProc(GHOST_TimerTaskHandle timertaskhandle); + +/** + * Changes the timer callback. + * @param timertaskhandle The handle to the timertask + * @param timerProc The timer callback. + */ +extern void GHOST_SetTimerProc(GHOST_TimerTaskHandle timertaskhandle, + GHOST_TimerProcPtr timerProc); + +/** + * Returns the timer user data. + * @param timertaskhandle The handle to the timertask + * @return The timer user data. + */ +extern GHOST_TUserDataPtr GHOST_GetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle); + +/** + * Changes the time user data. + * @param timertaskhandle The handle to the timertask + * @param data The timer user data. + */ +extern void GHOST_SetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle, + GHOST_TUserDataPtr userData); + +/** + * Returns indication as to whether the window is valid. + * @param windowhandle The handle to the window + * @return The validity of the window. + */ +extern int GHOST_GetValid(GHOST_WindowHandle windowhandle) ; + +/** + * Returns the type of drawing context used in this window. + * @param windowhandle The handle to the window + * @return The current type of drawing context. + */ +extern GHOST_TDrawingContextType GHOST_GetDrawingContextType(GHOST_WindowHandle windowhandle); + +/** + * Tries to install a rendering context in this window. + * @param windowhandle The handle to the window + * @param type The type of rendering context installed. + * @return Indication as to whether installation has succeeded. + */ +extern GHOST_TSuccess GHOST_SetDrawingContextType(GHOST_WindowHandle windowhandle, + GHOST_TDrawingContextType type); + +/** + * Sets the title displayed in the title bar. + * @param windowhandle The handle to the window + * @param title The title to display in the title bar. + */ +extern void GHOST_SetTitle(GHOST_WindowHandle windowhandle, + char* title); + +/** + * Returns the title displayed in the title bar. The title + * should be free'd with free(). + * + * @param windowhandle The handle to the window + * @return The title, free with free(). + */ +extern char* GHOST_GetTitle(GHOST_WindowHandle windowhandle); + +/** + * Returns the window rectangle dimensions. + * These are screen coordinates. + * @param windowhandle The handle to the window + * @return A handle to the bounding rectangle of the window. + */ +extern GHOST_RectangleHandle GHOST_GetWindowBounds(GHOST_WindowHandle windowhandle); + +/** + * Returns the client rectangle dimensions. + * The left and top members of the rectangle are always zero. + * @param windowhandle The handle to the window + * @return A handle to the bounding rectangle of the window. + */ +extern GHOST_RectangleHandle GHOST_GetClientBounds(GHOST_WindowHandle windowhandle); + +/** + * Disposes a rectangle object + * @param rectanglehandle Handle to the rectangle. + */ +void GHOST_DisposeRectangle(GHOST_RectangleHandle rectanglehandle); + +/** + * Resizes client rectangle width. + * @param windowhandle The handle to the window + * @param width The new width of the client area of the window. + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle, + GHOST_TUns32 width); + +/** + * Resizes client rectangle height. + * @param windowhandle The handle to the window + * @param height The new height of the client area of the window. + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle, + GHOST_TUns32 height); + +/** + * Resizes client rectangle. + * @param windowhandle The handle to the window + * @param width The new width of the client area of the window. + * @param height The new height of the client area of the window. + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle, + GHOST_TUns32 width, + GHOST_TUns32 height); + +/** + * Converts a point in screen coordinates to client rectangle coordinates + * @param windowhandle The handle to the window + * @param inX The x-coordinate on the screen. + * @param inY The y-coordinate on the screen. + * @param outX The x-coordinate in the client rectangle. + * @param outY The y-coordinate in the client rectangle. + */ +extern void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle, + GHOST_TInt32 inX, + GHOST_TInt32 inY, + GHOST_TInt32* outX, + GHOST_TInt32* outY) ; + +/** + * Converts a point in screen coordinates to client rectangle coordinates + * @param windowhandle The handle to the window + * @param inX The x-coordinate in the client rectangle. + * @param inY The y-coordinate in the client rectangle. + * @param outX The x-coordinate on the screen. + * @param outY The y-coordinate on the screen. + */ +extern void GHOST_ClientToScreen(GHOST_WindowHandle windowhandle, + GHOST_TInt32 inX, + GHOST_TInt32 inY, + GHOST_TInt32* outX, + GHOST_TInt32* outY); + +/** + * Returns the state of the window (normal, minimized, maximized). + * @param windowhandle The handle to the window + * @return The state of the window. + */ +extern GHOST_TWindowState GHOST_GetWindowState(GHOST_WindowHandle windowhandle); + +/** + * Sets the state of the window (normal, minimized, maximized). + * @param windowhandle The handle to the window + * @param state The state of the window. + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_SetWindowState(GHOST_WindowHandle windowhandle, + GHOST_TWindowState state); + +/** + * Sets the order of the window (bottom, top). + * @param windowhandle The handle to the window + * @param order The order of the window. + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_SetWindowOrder(GHOST_WindowHandle windowhandle, + GHOST_TWindowOrder order); + +/** + * Swaps front and back buffers of a window. + * @param windowhandle The handle to the window + * @return An intean success indicator. + */ +extern GHOST_TSuccess GHOST_SwapWindowBuffers(GHOST_WindowHandle windowhandle); + +/** + * Activates the drawing context of this window. + * @param windowhandle The handle to the window + * @return An intean success indicator. + */ +extern GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandle); + +/** + * Invalidates the contents of this window. + * @param windowhandle The handle to the window + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle); + +/** + * Access to rectangle width. + * @param rectanglehandle The handle to the rectangle + * @return width of the rectangle + */ +extern GHOST_TInt32 GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle); + +/** + * Access to rectangle height. + * @param rectanglehandle The handle to the rectangle + * @return height of the rectangle + */ +extern GHOST_TInt32 GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle); + +/** + * Gets all members of the rectangle. + * @param rectanglehandle The handle to the rectangle + * @param l Pointer to return left coordinate in. + * @param t Pointer to return top coordinate in. + * @param r Pointer to return right coordinate in. + * @param b Pointer to return bottom coordinate in. + */ +extern void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle, + GHOST_TInt32* l, + GHOST_TInt32* t, + GHOST_TInt32* r, + GHOST_TInt32* b); + +/** + * Sets all members of the rectangle. + * @param rectanglehandle The handle to the rectangle + * @param l requested left coordinate of the rectangle + * @param t requested top coordinate of the rectangle + * @param r requested right coordinate of the rectangle + * @param b requested bottom coordinate of the rectangle + */ +extern void GHOST_SetRectangle(GHOST_RectangleHandle rectanglehandle, + GHOST_TInt32 l, + GHOST_TInt32 t, + GHOST_TInt32 r, + GHOST_TInt32 b); + +/** + * Returns whether this rectangle is empty. + * Empty rectangles are rectangles that have width==0 and/or height==0. + * @param rectanglehandle The handle to the rectangle + * @return intean value (true == empty rectangle) + */ +extern GHOST_TSuccess GHOST_IsEmptyRectangle(GHOST_RectangleHandle rectanglehandle); + +/** + * Returns whether this rectangle is valid. + * Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. Thus, emapty rectangles are valid. + * @param rectanglehandle The handle to the rectangle + * @return intean value (true==valid rectangle) + */ +extern GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehandle); + +/** + * Grows (or shrinks the rectangle). + * The method avoids negative insets making the rectangle invalid + * @param rectanglehandle The handle to the rectangle + * @param i The amount of offset given to each extreme (negative values shrink the rectangle). + */ +extern void GHOST_InsetRectangle(GHOST_RectangleHandle rectanglehandle, + GHOST_TInt32 i); + +/** + * Does a union of the rectangle given and this rectangle. + * The result is stored in this rectangle. + * @param rectanglehandle The handle to the rectangle + * @param r The rectangle that is input for the union operation. + */ +extern void GHOST_UnionRectangle(GHOST_RectangleHandle rectanglehandle, + GHOST_RectangleHandle anotherrectanglehandle); + +/** + * Grows the rectangle to included a point. + * @param rectanglehandle The handle to the rectangle + * @param x The x-coordinate of the point. + * @param y The y-coordinate of the point. + */ +extern void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle, + GHOST_TInt32 x, + GHOST_TInt32 y); + +/** + * Returns whether the point is inside this rectangle. + * Point on the boundary is considered inside. + * @param rectanglehandle The handle to the rectangle + * @param x x-coordinate of point to test. + * @param y y-coordinate of point to test. + * @return intean value (true if point is inside). + */ +extern GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle, + GHOST_TInt32 x, + GHOST_TInt32 y); + +/** + * Returns whether the rectangle is inside this rectangle. + * @param rectanglehandle The handle to the rectangle + * @param r rectangle to test. + * @return visibility (not, partially or fully visible). + */ +extern GHOST_TVisibility GHOST_GetRectangleVisibility(GHOST_RectangleHandle rectanglehandle, + GHOST_RectangleHandle anotherrectanglehandle); + +/** + * Sets rectangle members. + * Sets rectangle members such that it is centered at the given location. + * @param rectanglehandle The handle to the rectangle + * @param cx requested center x-coordinate of the rectangle + * @param cy requested center y-coordinate of the rectangle + */ +extern void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle, + GHOST_TInt32 cx, + GHOST_TInt32 cy); + +/** + * Sets rectangle members. + * Sets rectangle members such that it is centered at the given location, + * with the width requested. + * @param rectanglehandle The handle to the rectangle + * @param cx requested center x-coordinate of the rectangle + * @param cy requested center y-coordinate of the rectangle + * @param w requested width of the rectangle + * @param h requested height of the rectangle + */ +extern void GHOST_SetRectangleCenter(GHOST_RectangleHandle rectanglehandle, + GHOST_TInt32 cx, + GHOST_TInt32 cy, + GHOST_TInt32 w, + GHOST_TInt32 h); + +/** + * Clips a rectangle. + * Updates the rectangle given such that it will fit within this one. + * This can result in an empty rectangle. + * @param rectanglehandle The handle to the rectangle + * @param r the rectangle to clip + * @return whether clipping has occurred + */ +extern GHOST_TSuccess GHOST_ClipRectangle(GHOST_RectangleHandle rectanglehandle, + GHOST_RectangleHandle anotherrectanglehandle); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/intern/ghost/GHOST_IEvent.h b/intern/ghost/GHOST_IEvent.h new file mode 100644 index 00000000000..ba901708e84 --- /dev/null +++ b/intern/ghost/GHOST_IEvent.h @@ -0,0 +1,88 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 31, 2001 + */ + +#ifndef _GHOST_IEVENT_H_ +#define _GHOST_IEVENT_H_ + +#include "GHOST_Types.h" + +class GHOST_IWindow; + +/** + * Interface class for events received the operating system. + * @author Maarten Gribnau + * @date May 31, 2001 + */ +class GHOST_IEvent +{ +public: + /** + * Destructor. + */ + virtual ~GHOST_IEvent() + { + } + + /** + * Returns the event type. + * @return The event type. + */ + virtual GHOST_TEventType getType() = 0; + + /** + * Returns the time this event was generated. + * @return The event generation time. + */ + virtual GHOST_TUns64 getTime() = 0; + + /** + * Returns the window this event was generated on, + * or NULL if it is a 'system' event. + * @return The generating window. + */ + virtual GHOST_IWindow* getWindow() = 0; + + /** + * Returns the event data. + * @return The event data. + */ + virtual GHOST_TEventDataPtr getData() = 0; +}; + +#endif // _GHOST_IEVENT_H_ diff --git a/intern/ghost/GHOST_IEventConsumer.h b/intern/ghost/GHOST_IEventConsumer.h new file mode 100644 index 00000000000..7234beff777 --- /dev/null +++ b/intern/ghost/GHOST_IEventConsumer.h @@ -0,0 +1,66 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 14, 2001 + */ + +#ifndef _GHOST_IEVENT_CONSUMER_H_ +#define _GHOST_IEVENT_CONSUMER_H_ + +#include "GHOST_IEvent.h" + +/** + * Interface class for objects interested in receiving events. + */ +class GHOST_IEventConsumer +{ +public: + /** + * Destructor. + */ + virtual ~GHOST_IEventConsumer() + { + } + + /** + * This method is called by an event producer when an event is available. + * @param event The event that can be handled or ignored. + * @return Indication as to whether the event was handled. + */ + virtual bool processEvent(GHOST_IEvent* event) = 0; +}; + +#endif // _GHOST_EVENT_CONSUMER_H_ diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h new file mode 100644 index 00000000000..3c3398408f0 --- /dev/null +++ b/intern/ghost/GHOST_ISystem.h @@ -0,0 +1,282 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 30, 2001 + */ + +#ifndef _GHOST_ISYSTEM_H_ +#define _GHOST_ISYSTEM_H_ + +#include "GHOST_Types.h" +#include "GHOST_ITimerTask.h" +#include "GHOST_IWindow.h" + +class GHOST_IEventConsumer; + +/** + * Interface for classes that provide access to the operating system. + * There should be only one system class in an application. + * Therefore, the routines to create and dispose the system are static. + * Provides: + * 1. Time(r) management. + * 2. Display/window management (windows are only created on the main display for now). + * 3. Event management. + * 4. Access to the state of the mouse buttons and the keyboard. + * @author Maarten Gribnau + * @date May 30, 2001 + */ + +class GHOST_ISystem +{ +public: + /** + * Creates the one and only system. + * @return An indication of success. + */ + static GHOST_TSuccess createSystem(); + + /** + * Disposes the one and only system. + * @return An indication of success. + */ + static GHOST_TSuccess disposeSystem(); + + /** + * Returns a pointer to the one and only system (nil if it hasn't been created). + * @return A pointer to the system. + */ + static GHOST_ISystem* getSystem(); + +protected: + /** + * Constructor. + * Protected default constructor to force use of static createSystem member. + */ + GHOST_ISystem() {} + + /** + * Destructor. + * Protected default constructor to force use of static dispose member. + */ + virtual ~GHOST_ISystem() {} + +public: + /*************************************************************************************** + ** Time(r) functionality + ***************************************************************************************/ + + /** + * Returns the system time. + * Returns the number of milliseconds since the start of the system process. + * Based on ANSI clock() routine. + * @return The number of milliseconds. + */ + virtual GHOST_TUns64 getMilliSeconds() const = 0; + + /** + * Installs a timer. + * Note that, on most operating systems, messages need to be processed in order + * for the timer callbacks to be invoked. + * @param delay The time to wait for the first call to the timerProc (in milliseconds) + * @param interval The interval between calls to the timerProc (in milliseconds) + * @param timerProc The callback invoked when the interval expires, + * @param userData Placeholder for user data. + * @return A timer task (0 if timer task installation failed). + */ + virtual GHOST_ITimerTask* installTimer(GHOST_TUns64 delay, GHOST_TUns64 interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData = 0) = 0; + + /** + * Removes a timer. + * @param timerTask Timer task to be removed. + * @return Indication of success. + */ + virtual GHOST_TSuccess removeTimer(GHOST_ITimerTask* timerTask) = 0; + + /*************************************************************************************** + ** Display/window management functionality + ***************************************************************************************/ + + /** + * Returns the number of displays on this system. + * @return The number of displays. + */ + virtual GHOST_TUns8 getNumDisplays() const = 0; + + /** + * Returns the dimensions of the main display on this system. + * @return The dimension of the main display. + */ + virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const = 0; + + /** + * Create a new window. + * The new window is added to the list of windows managed. + * Never explicitly delete the window, use disposeWindow() instead. + * @param title The name of the window (displayed in the title bar of the window if the OS supports it). + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param height The height the window. + * @param state The state of the window when opened. + * @param type The type of drawing context installed in this window. + * @param stereoVisual Create a stereo visual for quad buffered stereo. + * @return The new window (or 0 if creation failed). + */ + virtual GHOST_IWindow* createWindow( + const STR_String& title, + GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, + GHOST_TWindowState state, GHOST_TDrawingContextType type, + const bool stereoVisual) = 0; + + /** + * Dispose a window. + * @param window Pointer to the window to be disposed. + * @return Indication of success. + */ + virtual GHOST_TSuccess disposeWindow(GHOST_IWindow* window) = 0; + + /** + * Returns whether a window is valid. + * @param window Pointer to the window to be checked. + * @return Indication of validity. + */ + virtual bool validWindow(GHOST_IWindow* window) = 0; + + /** + * Begins full screen mode. + * @param setting The new setting of the display. + * @param window Window displayed in full screen. + * This window is invalid after full screen has been ended. + * @return Indication of success. + */ + virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, + const bool stereoVisual) = 0; + + /** + * Ends full screen mode. + * @return Indication of success. + */ + virtual GHOST_TSuccess endFullScreen(void) = 0; + + /** + * Returns current full screen mode status. + * @return The current status. + */ + virtual bool getFullScreen(void) = 0; + + /*************************************************************************************** + ** Event management functionality + ***************************************************************************************/ + + /** + * Retrieves events from the system and stores them in the queue. + * @param waitForEvent Flag to wait for an event (or return immediately). + * @return Indication of the presence of events. + */ + virtual bool processEvents(bool waitForEvent) = 0; + + /** + * Retrieves events from the queue and send them to the event consumers. + * @return Indication of the presence of events. + */ + virtual bool dispatchEvents() = 0; + + /** + * Adds the given event consumer to our list. + * @param consumer The event consumer to add. + * @return Indication of success. + */ + virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer* consumer) = 0; + + /*************************************************************************************** + ** Cursor management functionality + ***************************************************************************************/ + + /** + * Returns the current location of the cursor (location in screen coordinates) + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. + */ + virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const = 0; + + /** + * Updates the location of the cursor (location in screen coordinates). + * Not all operating systems allow the cursor to be moved (without the input device being moved). + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const = 0; + + /*************************************************************************************** + ** Access to mouse button and keyboard states. + ***************************************************************************************/ + + /** + * Returns the state of a modifier key (ouside the message queue). + * @param mask The modifier key state to retrieve. + * @param isDown The state of a modifier key (true == pressed). + * @return Indication of success. + */ + virtual GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const = 0; + + /** + * Returns the state of a mouse button (ouside the message queue). + * @param mask The button state to retrieve. + * @param isDown Button state. + * @return Indication of success. + */ + virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const = 0; + +protected: + /** + * Initialize the system. + * @return Indication of success. + */ + virtual GHOST_TSuccess init() = 0; + + /** + * Shut the system down. + * @return Indication of success. + */ + virtual GHOST_TSuccess exit() = 0; + + /** The one and only system */ + static GHOST_ISystem* m_system; +}; + +#endif // _GHOST_ISYSTEM_H_ diff --git a/intern/ghost/GHOST_ITimerTask.h b/intern/ghost/GHOST_ITimerTask.h new file mode 100644 index 00000000000..354652017d9 --- /dev/null +++ b/intern/ghost/GHOST_ITimerTask.h @@ -0,0 +1,88 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 31, 2001 + */ + +#ifndef _GHOST_ITIMER_TASK_H_ +#define _GHOST_ITIMER_TASK_H_ + + +#include "GHOST_Types.h" + + +/** + * Interface for a timer task. + * @author Maarten Gribnau + * @date May 31, 2001 + */ +class GHOST_ITimerTask +{ +public: + /** + * Destructor. + */ + virtual ~GHOST_ITimerTask() + { + } + + /** + * Returns the timer callback. + * @return The timer callback. + */ + inline virtual GHOST_TimerProcPtr getTimerProc() const = 0; + + /** + * Changes the timer callback. + * @param timerProc The timer callback. + */ + inline virtual void setTimerProc(const GHOST_TimerProcPtr timerProc) = 0; + + /** + * Returns the timer user data. + * @return The timer user data. + */ + inline virtual GHOST_TUserDataPtr getUserData() const = 0; + + /** + * Changes the time user data. + * @param data The timer user data. + */ + virtual void setUserData(const GHOST_TUserDataPtr userData) = 0; +}; + + +#endif // _GHOST_ITIMER_TASK_H_ diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h new file mode 100644 index 00000000000..8f41345ec5f --- /dev/null +++ b/intern/ghost/GHOST_IWindow.h @@ -0,0 +1,241 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 31, 2001 + */ + +#ifndef _GHOST_IWINDOW_H_ +#define _GHOST_IWINDOW_H_ + +#include "STR_String.h" +#include "GHOST_Rect.h" +#include "GHOST_Types.h" + + +/** + * Interface for GHOST windows. + * Dimensions are given in screen coordinates that are relative to the upper-left corner of the screen. + * @author Maarten Gribnau + * @date May 31, 2001 + */ + +class GHOST_IWindow +{ +public: + /** + * Destructor. + */ + virtual ~GHOST_IWindow() + { + } + + /** + * Returns indication as to whether the window is valid. + * @return The validity of the window. + */ + virtual bool getValid() const = 0; + + /** + * Returns the type of drawing context used in this window. + * @return The current type of drawing context. + */ + inline virtual GHOST_TDrawingContextType getDrawingContextType() = 0; + + /** + * Tries to install a rendering context in this window. + * @param type The type of rendering context installed. + * @return Indication as to whether installation has succeeded. + */ + virtual GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type) = 0; + + /** + * Sets the title displayed in the title bar. + * @param title The title to display in the title bar. + */ + virtual void setTitle(const STR_String& title) = 0; + + /** + * Returns the title displayed in the title bar. + * @param title The title displayed in the title bar. + */ + virtual void getTitle(STR_String& title) const = 0; + + /** + * Returns the window rectangle dimensions. + * These are screen coordinates. + * @param bounds The bounding rectangle of the window. + */ + virtual void getWindowBounds(GHOST_Rect& bounds) const = 0; + + /** + * Returns the client rectangle dimensions. + * The left and top members of the rectangle are always zero. + * @param bounds The bounding rectangle of the client area of the window. + */ + virtual void getClientBounds(GHOST_Rect& bounds) const = 0; + + /** + * Resizes client rectangle width. + * @param width The new width of the client area of the window. + */ + virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0; + + /** + * Resizes client rectangle height. + * @param height The new height of the client area of the window. + */ + virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height) = 0; + + /** + * Resizes client rectangle. + * @param width The new width of the client area of the window. + * @param height The new height of the client area of the window. + */ + virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0; + + /** + * Converts a point in screen coordinates to client rectangle coordinates + * @param inX The x-coordinate on the screen. + * @param inY The y-coordinate on the screen. + * @param outX The x-coordinate in the client rectangle. + * @param outY The y-coordinate in the client rectangle. + */ + virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0; + + /** + * Converts a point in screen coordinates to client rectangle coordinates + * @param inX The x-coordinate in the client rectangle. + * @param inY The y-coordinate in the client rectangle. + * @param outX The x-coordinate on the screen. + * @param outY The y-coordinate on the screen. + */ + virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0; + + /** + * Returns the state of the window (normal, minimized, maximized). + * @return The state of the window. + */ + virtual GHOST_TWindowState getState() const = 0; + + /** + * Sets the state of the window (normal, minimized, maximized). + * @param state The state of the window. + * @return Indication of success. + */ + virtual GHOST_TSuccess setState(GHOST_TWindowState state) = 0; + + /** + * Sets the order of the window (bottom, top). + * @param order The order of the window. + * @return Indication of success. + */ + virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order) = 0; + + /** + * Swaps front and back buffers of a window. + * @return A boolean success indicator. + */ + virtual GHOST_TSuccess swapBuffers() = 0; + + /** + * Activates the drawing context of this window. + * @return A boolean success indicator. + */ + virtual GHOST_TSuccess activateDrawingContext() = 0; + + /** + * Invalidates the contents of this window. + * @return Indication of success. + */ + virtual GHOST_TSuccess invalidate() = 0; + + /** + * Returns the window user data. + * @return The window user data. + */ + inline virtual GHOST_TUserDataPtr getUserData() const = 0; + + /** + * Changes the window user data. + * @param data The window user data. + */ + virtual void setUserData(const GHOST_TUserDataPtr userData) = 0; + + /*************************************************************************************** + ** Cursor management functionality + ***************************************************************************************/ + + /** + * Returns the current cursor shape. + * @return The current cursor shape. + */ + virtual GHOST_TStandardCursor getCursorShape() const = 0; + + /** + * Set the shape of the cursor. + * @param cursor The new cursor shape type id. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape) = 0; + + /** + * Set the shape of the cursor to a custom cursor. + * @param bitmap The bitmap data for the cursor. + * @param mask The mask data for the cursor. + * @param hotX The X coordinate of the cursor hotspot. + * @param hotY The Y coordinate of the cursor hotspot. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 bitmap[16][2], + GHOST_TUns8 mask[16][2], + int hotX, + int hotY) = 0; + + /** + * Returns the visibility state of the cursor. + * @return The visibility state of the cursor. + */ + virtual bool getCursorVisibility() const = 0; + + /** + * Shows or hides the cursor. + * @param visible The new visibility state of the cursor. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCursorVisibility(bool visible) = 0; +}; + +#endif // _GHOST_IWINDOW_H_ diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h new file mode 100644 index 00000000000..c8cfc79ea9d --- /dev/null +++ b/intern/ghost/GHOST_Rect.h @@ -0,0 +1,237 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +#ifndef _H_GHOST_Rect +#define _H_GHOST_Rect + +#include "GHOST_Types.h" + + +/** + * Implements rectangle functionality. + * The four extreme coordinates are stored as left, top, right and bottom. + * To be valid, a rectangle should have a left coordinate smaller than or equal to right. + * To be valid, a rectangle should have a top coordinate smaller than or equal to bottom. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +class GHOST_Rect { +public: + + /** + * Constructs a rectangle with the given values. + * @param l requested left coordinate of the rectangle + * @param t requested top coordinate of the rectangle + * @param r requested right coordinate of the rectangle + * @param b requested bottom coordinate of the rectangle + */ + GHOST_Rect(GHOST_TInt32 l=0, GHOST_TInt32 t=0, GHOST_TInt32 r=0, GHOST_TInt32 b=0) + : m_l(l), m_t(t), m_r(r), m_b(b) {} + + /** + * Copy constructor. + * @param r rectangle to copy + */ + GHOST_Rect(const GHOST_Rect& r) + : m_l(r.m_l), m_t(r.m_t), m_r(r.m_r), m_b(r.m_b) {} + + /** + * Destructor. + */ + virtual ~GHOST_Rect() {}; + + /** + * Access to rectangle width. + * @return width of the rectangle + */ + virtual inline GHOST_TInt32 getWidth() const; + + /** + * Access to rectangle height. + * @return height of the rectangle + */ + virtual inline GHOST_TInt32 getHeight() const; + + /** + * Sets all members of the rectangle. + * @param l requested left coordinate of the rectangle + * @param t requested top coordinate of the rectangle + * @param r requested right coordinate of the rectangle + * @param b requested bottom coordinate of the rectangle + */ + virtual inline void set(GHOST_TInt32 l, GHOST_TInt32 t, GHOST_TInt32 r, GHOST_TInt32 b); + + /** + * Returns whether this rectangle is empty. + * Empty rectangles are rectangles that have width==0 and/or height==0. + * @return boolean value (true==empty rectangle) + */ + virtual inline bool isEmpty() const; + + /** + * Returns whether this rectangle is valid. + * Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. Thus, emapty rectangles are valid. + * @return boolean value (true==valid rectangle) + */ + virtual inline bool isValid() const; + + /** + * Grows (or shrinks the rectangle). + * The method avoids negative insets making the rectangle invalid + * @param i The amount of offset given to each extreme (negative values shrink the rectangle). + */ + virtual void inset(GHOST_TInt32 i); + + /** + * Does a union of the rectangle given and this rectangle. + * The result is stored in this rectangle. + * @param r The rectangle that is input for the union operation. + */ + virtual inline void unionRect(const GHOST_Rect& r); + + /** + * Grows the rectangle to included a point. + * @param x The x-coordinate of the point. + * @param y The y-coordinate of the point. + */ + virtual inline void unionPoint(GHOST_TInt32 x, GHOST_TInt32 y); + + /** + * Returns whether the point is inside this rectangle. + * Point on the boundary is considered inside. + * @param x x-coordinate of point to test. + * @param y y-coordinate of point to test. + * @return boolean value (true if point is inside). + */ + virtual inline bool isInside(GHOST_TInt32 x, GHOST_TInt32 y) const; + + /** + * Returns whether the rectangle is inside this rectangle. + * @param r rectangle to test. + * @return visibility (not, partially or fully visible). + */ + virtual GHOST_TVisibility getVisibility(GHOST_Rect& r) const; + + /** + * Sets rectangle members. + * Sets rectangle members such that it is centered at the given location. + * @param cx requested center x-coordinate of the rectangle + * @param cy requested center y-coordinate of the rectangle + */ + virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy); + + /** + * Sets rectangle members. + * Sets rectangle members such that it is centered at the given location, + * with the width requested. + * @param cx requested center x-coordinate of the rectangle + * @param cy requested center y-coordinate of the rectangle + * @param w requested width of the rectangle + * @param h requested height of the rectangle + */ + virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy, GHOST_TInt32 w, GHOST_TInt32 h); + + /** + * Clips a rectangle. + * Updates the rectangle given such that it will fit within this one. + * This can result in an empty rectangle. + * @param r the rectangle to clip + * @return whether clipping has occurred + */ + virtual bool clip(GHOST_Rect& r) const; + + /** Left coordinate of the rectangle */ + GHOST_TInt32 m_l; + /** Top coordinate of the rectangle */ + GHOST_TInt32 m_t; + /** Right coordinate of the rectangle */ + GHOST_TInt32 m_r; + /** Bottom coordinate of the rectangle */ + GHOST_TInt32 m_b; +}; + + +inline GHOST_TInt32 GHOST_Rect::getWidth() const +{ + return m_r - m_l; +} + +inline GHOST_TInt32 GHOST_Rect::getHeight() const +{ + return m_b - m_t; +} + +inline void GHOST_Rect::set(GHOST_TInt32 l, GHOST_TInt32 t, GHOST_TInt32 r, GHOST_TInt32 b) +{ + m_l = l; m_t = t; m_r = r; m_b = b; +} + +inline bool GHOST_Rect::isEmpty() const +{ + return (getWidth() == 0) || (getHeight() == 0); +} + +inline bool GHOST_Rect::isValid() const +{ + return (m_l <= m_r) && (m_t <= m_b); +} + +inline void GHOST_Rect::unionRect(const GHOST_Rect& r) +{ + if (r.m_l < m_l) m_l = r.m_l; + if (r.m_r > m_r) m_r = r.m_r; + if (r.m_t < m_t) m_t = r.m_t; + if (r.m_b > m_b) m_b = r.m_b; +} + +inline void GHOST_Rect::unionPoint(GHOST_TInt32 x, GHOST_TInt32 y) +{ + if (x < m_l) m_l = x; + if (x > m_r) m_r = x; + if (y < m_t) m_t = y; + if (y > m_b) m_b = y; +} + +inline bool GHOST_Rect::isInside(GHOST_TInt32 x, GHOST_TInt32 y) const +{ + return (x >= m_l) && (x <= m_r) && (y >= m_t) && (y <= m_b); +} + +#endif // _H_GHOST_Rect diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h new file mode 100644 index 00000000000..c7b8f3b19e0 --- /dev/null +++ b/intern/ghost/GHOST_Types.h @@ -0,0 +1,354 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 31, 2001 + */ + +#ifndef _GHOST_TYPES_H_ +#define _GHOST_TYPES_H_ + +typedef char GHOST_TInt8; +typedef unsigned char GHOST_TUns8; +typedef short GHOST_TInt16; +typedef unsigned short GHOST_TUns16; +typedef int GHOST_TInt32; +typedef unsigned int GHOST_TUns32; + +#ifdef WIN32 +typedef __int64 GHOST_TInt64; +typedef unsigned __int64 GHOST_TUns64; +#else +typedef long long GHOST_TInt64; +typedef unsigned long long GHOST_TUns64; +#endif + +typedef void* GHOST_TUserDataPtr; + +typedef enum +{ + GHOST_kFailure = 0, + GHOST_kSuccess +} GHOST_TSuccess; + + +typedef enum { + GHOST_kNotVisible = 0, + GHOST_kPartiallyVisible, + GHOST_kFullyVisible +} GHOST_TVisibility; + + +typedef enum { + GHOST_kFireTimeNever = 0xFFFFFFFF +} GHOST_TFireTimeConstant; + +typedef enum { + GHOST_kModifierKeyLeftShift = 0, + GHOST_kModifierKeyRightShift, + GHOST_kModifierKeyLeftAlt, + GHOST_kModifierKeyRightAlt, + GHOST_kModifierKeyLeftControl, + GHOST_kModifierKeyRightControl, + GHOST_kModifierKeyCommand, // APPLE only + GHOST_kModifierKeyNumMasks +} GHOST_TModifierKeyMask; + + +typedef enum { + GHOST_kWindowStateNormal = 0, + GHOST_kWindowStateMaximized, + GHOST_kWindowStateMinimized, + GHOST_kWindowStateFullScreen +} GHOST_TWindowState; + + +typedef enum { + GHOST_kWindowOrderTop = 0, + GHOST_kWindowOrderBottom +} GHOST_TWindowOrder; + + +typedef enum { + GHOST_kDrawingContextTypeNone = 0, + GHOST_kDrawingContextTypeOpenGL +} GHOST_TDrawingContextType; + + +typedef enum { + GHOST_kButtonMaskLeft = 0, + GHOST_kButtonMaskMiddle, + GHOST_kButtonMaskRight, + GHOST_kButtonNumMasks +} GHOST_TButtonMask; + + +typedef enum { + GHOST_kEventUnknown = 0, + + GHOST_kEventCursorMove, + GHOST_kEventButtonDown, + GHOST_kEventButtonUp, + + GHOST_kEventKeyDown, + GHOST_kEventKeyUp, +// GHOST_kEventKeyAuto, + + GHOST_kEventQuit, + + GHOST_kEventWindowClose, + GHOST_kEventWindowActivate, + GHOST_kEventWindowDeactivate, + GHOST_kEventWindowUpdate, + GHOST_kEventWindowSize, + + GHOST_kNumEventTypes +} GHOST_TEventType; + + +typedef enum { + GHOST_kStandardCursorFirstCursor = 0, + GHOST_kStandardCursorDefault = 0, + GHOST_kStandardCursorRightArrow, + GHOST_kStandardCursorLeftArrow, + GHOST_kStandardCursorInfo, + GHOST_kStandardCursorDestroy, + GHOST_kStandardCursorHelp, + GHOST_kStandardCursorCycle, + GHOST_kStandardCursorSpray, + GHOST_kStandardCursorWait, + GHOST_kStandardCursorText, + GHOST_kStandardCursorCrosshair, + GHOST_kStandardCursorUpDown, + GHOST_kStandardCursorLeftRight, + GHOST_kStandardCursorTopSide, + GHOST_kStandardCursorBottomSide, + GHOST_kStandardCursorLeftSide, + GHOST_kStandardCursorRightSide, + GHOST_kStandardCursorTopLeftCorner, + GHOST_kStandardCursorTopRightCorner, + GHOST_kStandardCursorBottomRightCorner, + GHOST_kStandardCursorBottomLeftCorner, + GHOST_kStandardCursorCustom, + GHOST_kStandardCursorNumCursors +} GHOST_TStandardCursor; + + +typedef enum { + GHOST_kKeyUnknown = -1, + GHOST_kKeyBackSpace, + GHOST_kKeyTab, + GHOST_kKeyLinefeed, + GHOST_kKeyClear, + GHOST_kKeyEnter = 0x0D, + + GHOST_kKeyEsc = 0x1B, + GHOST_kKeySpace = ' ', + GHOST_kKeyQuote = 0x27, + GHOST_kKeyComma = ',', + GHOST_kKeyMinus = '-', + GHOST_kKeyPeriod = '.', + GHOST_kKeySlash = '/', + + // Number keys + GHOST_kKey0 = '0', + GHOST_kKey1, + GHOST_kKey2, + GHOST_kKey3, + GHOST_kKey4, + GHOST_kKey5, + GHOST_kKey6, + GHOST_kKey7, + GHOST_kKey8, + GHOST_kKey9, + + GHOST_kKeySemicolon = ';', + GHOST_kKeyEqual = '=', + + // Character keys + GHOST_kKeyA = 'A', + GHOST_kKeyB, + GHOST_kKeyC, + GHOST_kKeyD, + GHOST_kKeyE, + GHOST_kKeyF, + GHOST_kKeyG, + GHOST_kKeyH, + GHOST_kKeyI, + GHOST_kKeyJ, + GHOST_kKeyK, + GHOST_kKeyL, + GHOST_kKeyM, + GHOST_kKeyN, + GHOST_kKeyO, + GHOST_kKeyP, + GHOST_kKeyQ, + GHOST_kKeyR, + GHOST_kKeyS, + GHOST_kKeyT, + GHOST_kKeyU, + GHOST_kKeyV, + GHOST_kKeyW, + GHOST_kKeyX, + GHOST_kKeyY, + GHOST_kKeyZ, + + GHOST_kKeyLeftBracket = '[', + GHOST_kKeyRightBracket = ']', + GHOST_kKeyBackslash = 0x5C, + GHOST_kKeyAccentGrave = '`', + + + GHOST_kKeyLeftShift = 0x100, + GHOST_kKeyRightShift, + GHOST_kKeyLeftControl, + GHOST_kKeyRightControl, + GHOST_kKeyLeftAlt, + GHOST_kKeyRightAlt, + GHOST_kKeyCommand, // APPLE only! + + GHOST_kKeyCapsLock, + GHOST_kKeyNumLock, + GHOST_kKeyScrollLock, + + GHOST_kKeyLeftArrow, + GHOST_kKeyRightArrow, + GHOST_kKeyUpArrow, + GHOST_kKeyDownArrow, + + GHOST_kKeyPrintScreen, + GHOST_kKeyPause, + + GHOST_kKeyInsert, + GHOST_kKeyDelete, + GHOST_kKeyHome, + GHOST_kKeyEnd, + GHOST_kKeyUpPage, + GHOST_kKeyDownPage, + + // Numpad keys + GHOST_kKeyNumpad0, + GHOST_kKeyNumpad1, + GHOST_kKeyNumpad2, + GHOST_kKeyNumpad3, + GHOST_kKeyNumpad4, + GHOST_kKeyNumpad5, + GHOST_kKeyNumpad6, + GHOST_kKeyNumpad7, + GHOST_kKeyNumpad8, + GHOST_kKeyNumpad9, + GHOST_kKeyNumpadPeriod, + GHOST_kKeyNumpadEnter, + GHOST_kKeyNumpadPlus, + GHOST_kKeyNumpadMinus, + GHOST_kKeyNumpadAsterisk, + GHOST_kKeyNumpadSlash, + + // Function keys + GHOST_kKeyF1, + GHOST_kKeyF2, + GHOST_kKeyF3, + GHOST_kKeyF4, + GHOST_kKeyF5, + GHOST_kKeyF6, + GHOST_kKeyF7, + GHOST_kKeyF8, + GHOST_kKeyF9, + GHOST_kKeyF10, + GHOST_kKeyF11, + GHOST_kKeyF12, + GHOST_kKeyF13, + GHOST_kKeyF14, + GHOST_kKeyF15, + GHOST_kKeyF16, + GHOST_kKeyF17, + GHOST_kKeyF18, + GHOST_kKeyF19, + GHOST_kKeyF20, + GHOST_kKeyF21, + GHOST_kKeyF22, + GHOST_kKeyF23, + GHOST_kKeyF24 +} GHOST_TKey; + + +typedef void* GHOST_TEventDataPtr; + +typedef struct { + /** The x-coordinate of the cursor position. */ + GHOST_TInt32 x; + /** The y-coordinate of the cursor position. */ + GHOST_TInt32 y; +} GHOST_TEventCursorData; + +typedef struct { + /** The mask of the mouse button. */ + GHOST_TButtonMask button; +} GHOST_TEventButtonData; + +typedef struct { + /** The key code. */ + GHOST_TKey key; + /** The ascii code for the key event ('\0' if none). */ + char ascii; +} GHOST_TEventKeyData; + +typedef struct { + /** Number of pixels on a line. */ + GHOST_TUns32 xPixels; + /** Number of lines. */ + GHOST_TUns32 yPixels; + /** Numberof bits per pixel. */ + GHOST_TUns32 bpp; + /** Refresh rate (in Hertz). */ + GHOST_TUns32 frequency; +} GHOST_DisplaySetting; + + +/** + * A timer task callback routine. + * @param task The timer task object. + * @param time The current time. + */ +#ifdef __cplusplus +class GHOST_ITimerTask; +typedef void (*GHOST_TimerProcPtr)(GHOST_ITimerTask* task, GHOST_TUns64 time); +#else +struct GHOST_TimerTaskHandle__; +typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__* task, GHOST_TUns64 time); +#endif + + +#endif // _GHOST_TYPES_H_ diff --git a/intern/ghost/Makefile b/intern/ghost/Makefile new file mode 100644 index 00000000000..5c78bea192c --- /dev/null +++ b/intern/ghost/Makefile @@ -0,0 +1,52 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# ghost main makefile. +# + +include nan_definitions.mk + +LIBNAME = ghost +SOURCEDIR = intern/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = intern +TESTDIRS = test + +include nan_subdirs.mk + +install: all debug + @[ -d $(NAN_GHOST) ] || mkdir $(NAN_GHOST) + @[ -d $(NAN_GHOST)/include ] || mkdir $(NAN_GHOST)/include + @[ -d $(NAN_GHOST)/lib ] || mkdir $(NAN_GHOST)/lib + @[ -d $(NAN_GHOST)/lib/debug ] || mkdir $(NAN_GHOST)/lib/debug + cp -f $(DIR)/libghost.a $(NAN_GHOST)/lib/ + cp -f $(DIR)/debug/libghost.a $(NAN_GHOST)/lib/debug/ + cp -f *.h $(NAN_GHOST)/include/ + diff --git a/intern/ghost/doc/Doxyfile.win b/intern/ghost/doc/Doxyfile.win new file mode 100644 index 00000000000..463da56cc94 --- /dev/null +++ b/intern/ghost/doc/Doxyfile.win @@ -0,0 +1,747 @@ +# Doxyfile 1.2.4 + +# This file describes the settings to be used by doxygen for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "GHOST (Generic Handy Operating System Toolkit)" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 1.0 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = doc + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese, +# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian, +# Polish, Portuguese and Slovene. + +OUTPUT_LANGUAGE = English + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. +# MAART: changed +EXTRACT_STATIC = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these class will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a class diagram (in Html and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. + +CLASS_DIAGRAMS = YES + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower case letters. If set to YES upper case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are adviced to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explict @brief command for a brief description. +#MAART: changed +JAVADOC_AUTOBRIEF = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# reimplements. + +INHERIT_DOCS = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# The ENABLE_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . +#C:\Documents and Settings\maarten\My Documents\develop\blender\source\blender\img + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse. + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript and frames is required (for instance Netscape 4.0+ +# or Internet explorer 4.0+). + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. +#MAART: changed +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimised for Word 97 and may not look very pretty with +# other RTF readers or editors. +#MAART: changed +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using a WORD or other. +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assigments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages +#MAART: changed +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. Warning: This feature +# is still experimental and very incomplete. + +GENERATE_XML = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tagfiles. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to +# YES then doxygen will generate a graph for each documented file showing +# the direct and indirect include dependencies of the file with other +# documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to +# YES then doxygen will generate a graph for each documented header file showing +# the documented files that directly or indirectly include this file + +INCLUDED_BY_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO + +# The CGI_NAME tag should be the name of the CGI script that +# starts the search engine (doxysearch) with the correct parameters. +# A script with this name will be generated by doxygen. + +CGI_NAME = search.cgi + +# The CGI_URL tag should be the absolute URL to the directory where the +# cgi binaries are located. See the documentation of your http daemon for +# details. + +CGI_URL = + +# The DOC_URL tag should be the absolute URL to the directory where the +# documentation is located. If left blank the absolute path to the +# documentation, with file:// prepended to it, will be used. + +DOC_URL = + +# The DOC_ABSPATH tag should be the absolute path to the directory where the +# documentation is located. If left blank the directory on the local machine +# will be used. + +DOC_ABSPATH = + +# The BIN_ABSPATH tag must point to the directory where the doxysearch binary +# is installed. + +BIN_ABSPATH = c:\program files\doxygen\bin + +# The EXT_DOC_PATHS tag can be used to specify one or more paths to +# documentation generated for other projects. This allows doxysearch to search +# the documentation for these projects as well. + +EXT_DOC_PATHS = diff --git a/intern/ghost/intern/GHOST_Buttons.cpp b/intern/ghost/intern/GHOST_Buttons.cpp new file mode 100644 index 00000000000..6e0c46e17a0 --- /dev/null +++ b/intern/ghost/intern/GHOST_Buttons.cpp @@ -0,0 +1,82 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 31, 2001 + */ + +#include "GHOST_Buttons.h" + + +GHOST_Buttons::GHOST_Buttons() +{ + clear(); +} + + +bool GHOST_Buttons::get(GHOST_TButtonMask mask) const +{ + switch (mask) { + case GHOST_kButtonMaskLeft: + return m_ButtonLeft; + case GHOST_kButtonMaskMiddle: + return m_ButtonMiddle; + case GHOST_kButtonMaskRight: + return m_ButtonRight; + default: + return false; + } +} + +void GHOST_Buttons::set(GHOST_TButtonMask mask, bool down) +{ + switch (mask) { + case GHOST_kButtonMaskLeft: + m_ButtonLeft = down; break; + case GHOST_kButtonMaskMiddle: + m_ButtonMiddle = down; break; + case GHOST_kButtonMaskRight: + m_ButtonRight = down; break; + default: + break; + } +} + +void GHOST_Buttons::clear() +{ + m_ButtonLeft = false; + m_ButtonMiddle = false; + m_ButtonRight = false; +} diff --git a/intern/ghost/intern/GHOST_Buttons.h b/intern/ghost/intern/GHOST_Buttons.h new file mode 100644 index 00000000000..fdde52f3e8e --- /dev/null +++ b/intern/ghost/intern/GHOST_Buttons.h @@ -0,0 +1,76 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 15, 2001 + */ + +#ifndef _GHOST_BUTTONS_H_ +#define _GHOST_BUTTONS_H_ + +#include "GHOST_Types.h" + + +struct GHOST_Buttons { + /** + * Constructor. + */ + GHOST_Buttons(); + + /** + * Returns the state of a single button. + * @param mask. Key button to return. + * @return The state of the button (pressed == true). + */ + virtual bool get(GHOST_TButtonMask mask) const; + + /** + * Updates the state of a single button. + * @param mask. Button state to update. + * @param down. The new state of the button. + */ + virtual void set(GHOST_TButtonMask mask, bool down); + + /** + * Sets the state of all buttons to up. + */ + virtual void clear(); + + GHOST_TUns8 m_ButtonLeft : 1; + GHOST_TUns8 m_ButtonMiddle : 1; + GHOST_TUns8 m_ButtonRight : 1; +}; + +#endif // _GHOST_BUTTONS_H_ diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp new file mode 100644 index 00000000000..3ab3ce67fe8 --- /dev/null +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -0,0 +1,778 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + * GHOST_C-Api.cpp + * + * C Api for GHOST + * + * Version: $Id$ + */ + +#include <stdlib.h> + +#include "intern/GHOST_Debug.h" +#include "GHOST_C-api.h" +#include "GHOST_ISystem.h" +#include "GHOST_IEvent.h" +#include "GHOST_IEventConsumer.h" +#include "intern/GHOST_CallbackEventConsumer.h" + +#ifdef WIN32 +#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning +#endif //WIN32 + + +GHOST_SystemHandle GHOST_CreateSystem(void) +{ + GHOST_ISystem::createSystem(); + GHOST_ISystem* system = GHOST_ISystem::getSystem(); + + return (GHOST_SystemHandle)system; +} + + + +GHOST_TSuccess GHOST_DisposeSystem(GHOST_SystemHandle systemhandle) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + + return system->disposeSystem(); +} + + +GHOST_EventConsumerHandle GHOST_CreateEventConsumer(GHOST_EventCallbackProcPtr eventCallback, GHOST_TUserDataPtr userdata) +{ + return (GHOST_EventConsumerHandle) new GHOST_CallbackEventConsumer (eventCallback, userdata); +} + + +GHOST_TSuccess GHOST_DisposeEventConsumer(GHOST_EventConsumerHandle consumerhandle) +{ + delete ((GHOST_CallbackEventConsumer*)consumerhandle); + return GHOST_kSuccess; +} + + +GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + + return system->getMilliSeconds(); +} + + + +GHOST_TimerTaskHandle GHOST_InstallTimer(GHOST_SystemHandle systemhandle, + GHOST_TUns64 delay, + GHOST_TUns64 interval, + GHOST_TimerProcPtr timerproc, + GHOST_TUserDataPtr userdata) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + + return (GHOST_TimerTaskHandle) system->installTimer(delay, interval, timerproc, userdata); +} + + + +GHOST_TSuccess GHOST_RemoveTimer(GHOST_SystemHandle systemhandle, + GHOST_TimerTaskHandle timertaskhandle) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + GHOST_ITimerTask* timertask = (GHOST_ITimerTask*) timertaskhandle; + + return system->removeTimer(timertask); +} + + + +GHOST_TUns8 GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + + return system->getNumDisplays(); +} + + + +void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle, + GHOST_TUns32* width, + GHOST_TUns32* height) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + + system->getMainDisplayDimensions(*width, *height); +} + + + +GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, + char* title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + const int stereoVisual) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + bool bstereoVisual; + + if(stereoVisual) + bstereoVisual = true; + else + bstereoVisual = false; + + return (GHOST_WindowHandle) system->createWindow(title, left, top, width, height, + state, type, bstereoVisual); +} + +GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->getUserData(); +} +void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr userdata) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + window->setUserData(userdata); +} + +GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle, + GHOST_WindowHandle windowhandle) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return system->disposeWindow(window); +} + + + +int GHOST_ValidWindow(GHOST_SystemHandle systemhandle, + GHOST_WindowHandle windowhandle) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return (int) system->validWindow(window); +} + + + +GHOST_WindowHandle GHOST_BeginFullScreen(GHOST_SystemHandle systemhandle, + GHOST_DisplaySetting* setting, + const int stereoVisual) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + GHOST_IWindow* window = NULL; + bool bstereoVisual; + + if(stereoVisual) + bstereoVisual = true; + else + bstereoVisual = false; + + system->beginFullScreen(*setting, &window, bstereoVisual); + + return (GHOST_WindowHandle)window; +} + + + +GHOST_TSuccess GHOST_EndFullScreen(GHOST_SystemHandle systemhandle) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + + return system->endFullScreen(); +} + + + +int GHOST_GetFullScreen(GHOST_SystemHandle systemhandle) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + + return (int) system->getFullScreen(); +} + + + +int GHOST_ProcessEvents(GHOST_SystemHandle systemhandle, int waitForEvent) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + + return (int) system->processEvents(waitForEvent?true:false); +} + + + +int GHOST_DispatchEvents(GHOST_SystemHandle systemhandle) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + + return (int) system->dispatchEvents(); +} + + +GHOST_TSuccess GHOST_AddEventConsumer(GHOST_SystemHandle systemhandle, GHOST_EventConsumerHandle consumerhandle) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + + return system->addEventConsumer((GHOST_CallbackEventConsumer*)consumerhandle); +} + + + +GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->getCursorShape(); +} + + + +GHOST_TSuccess GHOST_SetCursorShape(GHOST_WindowHandle windowhandle, + GHOST_TStandardCursor cursorshape) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->setCursorShape(cursorshape); +} + +GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle, + GHOST_TUns8 bitmap[16][2], + GHOST_TUns8 mask[16][2], + int hotX, + int hotY) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->setCustomCursorShape(bitmap, mask, hotX, hotY); +} + +int GHOST_GetCursorVisibility(GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return (int) window->getCursorVisibility(); +} + + + +GHOST_TSuccess GHOST_SetCursorVisibility(GHOST_WindowHandle windowhandle, + int visible) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->setCursorVisibility(visible?true:false); +} + + + +GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle, + GHOST_TInt32* x, + GHOST_TInt32* y) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + + return system->getCursorPosition(*x, *y); +} + + + +GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle, + GHOST_TInt32 x, + GHOST_TInt32 y) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + + return system->setCursorPosition(x, y); +} + + + +GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle, + GHOST_TModifierKeyMask mask, + int* isDown) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + GHOST_TSuccess result; + bool isdown; + + result = system->getModifierKeyState(mask, isdown); + *isDown = (int) isdown; + + return result; +} + + + +GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle, + GHOST_TButtonMask mask, + int* isDown) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + GHOST_TSuccess result; + bool isdown; + + result = system->getButtonState(mask, isdown); + *isDown = (int) isdown; + + return result; +} + + + +GHOST_TEventType GHOST_GetEventType(GHOST_EventHandle eventhandle) +{ + GHOST_IEvent* event = (GHOST_IEvent*) eventhandle; + + return event->getType(); +} + + + +GHOST_TUns64 GHOST_GetEventTime(GHOST_EventHandle eventhandle) +{ + GHOST_IEvent* event = (GHOST_IEvent*) eventhandle; + + return event->getTime(); +} + + +GHOST_WindowHandle GHOST_GetEventWindow(GHOST_EventHandle eventhandle) +{ + GHOST_IEvent* event = (GHOST_IEvent*) eventhandle; + + return (GHOST_WindowHandle) event->getWindow(); +} + + +GHOST_TEventDataPtr GHOST_GetEventData(GHOST_EventHandle eventhandle) +{ + GHOST_IEvent* event = (GHOST_IEvent*) eventhandle; + + return event->getData(); +} + + + +GHOST_TimerProcPtr GHOST_GetTimerProc(GHOST_TimerTaskHandle timertaskhandle) +{ + GHOST_ITimerTask* timertask = (GHOST_ITimerTask*) timertaskhandle; + + return timertask->getTimerProc(); +} + + + +void GHOST_SetTimerProc(GHOST_TimerTaskHandle timertaskhandle, + GHOST_TimerProcPtr timerproc) +{ + GHOST_ITimerTask* timertask = (GHOST_ITimerTask*) timertaskhandle; + + timertask->setTimerProc(timerproc); +} + + + +GHOST_TUserDataPtr GHOST_GetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle) +{ + GHOST_ITimerTask* timertask = (GHOST_ITimerTask*) timertaskhandle; + + return timertask->getUserData(); +} + + + +void GHOST_SetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle, + GHOST_TUserDataPtr userdata) +{ + GHOST_ITimerTask* timertask = (GHOST_ITimerTask*) timertaskhandle; + + timertask->setUserData(userdata); +} + + + +int GHOST_GetValid(GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return (int) window->getValid(); +} + + + +GHOST_TDrawingContextType GHOST_GetDrawingContextType(GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->getDrawingContextType(); +} + + + +GHOST_TSuccess GHOST_SetDrawingContextType(GHOST_WindowHandle windowhandle, + GHOST_TDrawingContextType type) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->setDrawingContextType(type); +} + + + +void GHOST_SetTitle(GHOST_WindowHandle windowhandle, + char* title) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + window->setTitle(title); +} + + +char* GHOST_GetTitle(GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + STR_String title; + + window->getTitle(title); + + char *ctitle = (char*) malloc(title.Length() + 1); + strcpy(ctitle, title.Ptr()); + + return ctitle; +} + + + +GHOST_RectangleHandle GHOST_GetWindowBounds(GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + GHOST_Rect* rectangle = NULL; + + rectangle = new GHOST_Rect(); + window->getWindowBounds(*rectangle); + + return (GHOST_RectangleHandle)rectangle; +} + + + +GHOST_RectangleHandle GHOST_GetClientBounds(GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + GHOST_Rect* rectangle = NULL; + + rectangle = new GHOST_Rect(); + window->getClientBounds(*rectangle); + + return (GHOST_RectangleHandle)rectangle; +} + + + +void GHOST_DisposeRectangle(GHOST_RectangleHandle rectanglehandle) +{ + delete (GHOST_Rect*) rectanglehandle; +} + + + +GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle, + GHOST_TUns32 width) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->setClientWidth(width); +} + + + +GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle, + GHOST_TUns32 height) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->setClientHeight(height); +} + + + +GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle, + GHOST_TUns32 width, + GHOST_TUns32 height) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->setClientSize(width, height); +} + + + +void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle, + GHOST_TInt32 inX, + GHOST_TInt32 inY, + GHOST_TInt32* outX, + GHOST_TInt32* outY) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + window->screenToClient(inX, inY, *outX, *outY); +} + + + +void GHOST_ClientToScreen(GHOST_WindowHandle windowhandle, + GHOST_TInt32 inX, + GHOST_TInt32 inY, + GHOST_TInt32* outX, + GHOST_TInt32* outY) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + window->clientToScreen(inX, inY, *outX, *outY); +} + + + +GHOST_TWindowState GHOST_GetWindowState(GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->getState(); +} + + + +GHOST_TSuccess GHOST_SetWindowState(GHOST_WindowHandle windowhandle, + GHOST_TWindowState state) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->setState(state); +} + + + +GHOST_TSuccess GHOST_SetWindowOrder(GHOST_WindowHandle windowhandle, + GHOST_TWindowOrder order) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->setOrder(order); +} + + + +GHOST_TSuccess GHOST_SwapWindowBuffers(GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->swapBuffers(); +} + + + +GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->activateDrawingContext(); +} + + + +GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->invalidate(); +} + + + +GHOST_TInt32 GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle) +{ + return ((GHOST_Rect*)rectanglehandle)->getWidth(); +} + + + +GHOST_TInt32 GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle) +{ + return ((GHOST_Rect*)rectanglehandle)->getHeight(); +} + + + +void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle, + GHOST_TInt32* l, + GHOST_TInt32* t, + GHOST_TInt32* r, + GHOST_TInt32* b) +{ + GHOST_Rect *rect= (GHOST_Rect*) rectanglehandle; + + *l= rect->m_l; + *t= rect->m_t; + *r= rect->m_r; + *b= rect->m_b; +} + + +void GHOST_SetRectangle(GHOST_RectangleHandle rectanglehandle, + GHOST_TInt32 l, + GHOST_TInt32 t, + GHOST_TInt32 r, + GHOST_TInt32 b) +{ + ((GHOST_Rect*)rectanglehandle)->set(l, t, r, b); +} + + + +GHOST_TSuccess GHOST_IsEmptyRectangle(GHOST_RectangleHandle rectanglehandle) +{ + GHOST_TSuccess result = GHOST_kFailure; + + if (((GHOST_Rect*)rectanglehandle)->isEmpty()) + result = GHOST_kSuccess; + + return result; +} + + + +GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehandle) +{ + GHOST_TSuccess result = GHOST_kFailure; + + if(((GHOST_Rect*)rectanglehandle)->isValid()) + result = GHOST_kSuccess; + + return result; +} + + + +void GHOST_InsetRectangle(GHOST_RectangleHandle rectanglehandle, + GHOST_TInt32 i) +{ + ((GHOST_Rect*)rectanglehandle)->inset(i); +} + + + +void GHOST_UnionRectangle(GHOST_RectangleHandle rectanglehandle, + GHOST_RectangleHandle anotherrectanglehandle) +{ + ((GHOST_Rect*)rectanglehandle)->unionRect(*(GHOST_Rect*)anotherrectanglehandle); +} + + + +void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle, + GHOST_TInt32 x, + GHOST_TInt32 y) +{ + ((GHOST_Rect*)rectanglehandle)->unionPoint(x, y); +} + + + +GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle, + GHOST_TInt32 x, + GHOST_TInt32 y) +{ + GHOST_TSuccess result = GHOST_kFailure; + + if (((GHOST_Rect*)rectanglehandle)->isInside(x, y)) + result = GHOST_kSuccess; + + return result; +} + + + +GHOST_TVisibility GHOST_GetRectangleVisibility(GHOST_RectangleHandle rectanglehandle, + GHOST_RectangleHandle anotherrectanglehandle) +{ + GHOST_TVisibility visible = GHOST_kNotVisible; + + visible = ((GHOST_Rect*)rectanglehandle)->getVisibility(*(GHOST_Rect*)anotherrectanglehandle); + + return visible; +} + + + +void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle, + GHOST_TInt32 cx, + GHOST_TInt32 cy) +{ + ((GHOST_Rect*)rectanglehandle)->setCenter(cx, cy); +} + + + +void GHOST_SetRectangleCenter(GHOST_RectangleHandle rectanglehandle, + GHOST_TInt32 cx, + GHOST_TInt32 cy, + GHOST_TInt32 w, + GHOST_TInt32 h) +{ + ((GHOST_Rect*)rectanglehandle)->setCenter(cx, cy, w, h); +} + + + +GHOST_TSuccess GHOST_ClipRectangle(GHOST_RectangleHandle rectanglehandle, + GHOST_RectangleHandle anotherrectanglehandle) +{ + GHOST_TSuccess result = GHOST_kFailure; + + if (((GHOST_Rect*)rectanglehandle)->clip(*(GHOST_Rect*)anotherrectanglehandle)) + result = GHOST_kSuccess; + + return result; +} + + + diff --git a/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp b/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp new file mode 100644 index 00000000000..8099bdbd1d5 --- /dev/null +++ b/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp @@ -0,0 +1,55 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date October 25, 2001 + */ + +#include "GHOST_Debug.h" +#include "GHOST_C-api.h" +#include "GHOST_CallbackEventConsumer.h" + +GHOST_CallbackEventConsumer::GHOST_CallbackEventConsumer(GHOST_EventCallbackProcPtr eventCallback, + GHOST_TUserDataPtr userData) +{ + m_eventCallback = eventCallback; + m_userData = userData; +} + + +bool GHOST_CallbackEventConsumer::processEvent(GHOST_IEvent* event) +{ + return m_eventCallback((GHOST_EventHandle)event, m_userData) != 0; +} diff --git a/intern/ghost/intern/GHOST_CallbackEventConsumer.h b/intern/ghost/intern/GHOST_CallbackEventConsumer.h new file mode 100644 index 00000000000..28326653b31 --- /dev/null +++ b/intern/ghost/intern/GHOST_CallbackEventConsumer.h @@ -0,0 +1,77 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date October 25, 2001 + */ + +#ifndef _GHOST_CALLBACK_EVENT_CONSUMER_H_ +#define _GHOST_CALLBACK_EVENT_CONSUMER_H_ + +#include "GHOST_IEventConsumer.h" +#include "GHOST_C-api.h" + +/** + * Interface class for objects interested in receiving events. + */ +class GHOST_CallbackEventConsumer : public GHOST_IEventConsumer +{ +public: + /** + * Constructor. + */ + GHOST_CallbackEventConsumer(GHOST_EventCallbackProcPtr eventCallback, + GHOST_TUserDataPtr userData); + + /** + * Destructor. + */ + virtual ~GHOST_CallbackEventConsumer(void) + { + } + + /** + * This method is called by an event producer when an event is available. + * @param event The event that can be handled or ignored. + * @return Indication as to whether the event was handled. + */ + virtual bool processEvent(GHOST_IEvent* event); + +protected: + GHOST_EventCallbackProcPtr m_eventCallback; + GHOST_TUserDataPtr m_userData; +}; + +#endif // _GHOST_CALLBACK_EVENT_CONSUMER_H_ diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h new file mode 100644 index 00000000000..18be85e08b4 --- /dev/null +++ b/intern/ghost/intern/GHOST_Debug.h @@ -0,0 +1,74 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date June 1, 2001 + */ + +#ifndef _GHOST_DEBUG_H_ +#define _GHOST_DEBUG_H_ + +#ifdef WIN32 + #ifdef _DEBUG + #pragma warning (disable:4786) // suppress stl-MSVC debug info warning + #define GHOST_DEBUG + #endif // _DEBUG +#else // WIN32 + #ifndef NDEBUG + #define GHOST_DEBUG + #endif // DEBUG +#endif // WIN32 + +#ifdef GHOST_DEBUG + #include <iostream> +#endif // GHOST_DEBUG + + +#ifdef GHOST_DEBUG + #define GHOST_PRINT(x) { std::cout << x; } + //#define GHOST_PRINTF(x) { printf(x); } +#else // GHOST_DEBUG + #define GHOST_PRINT(x) + //#define GHOST_PRINTF(x) +#endif // GHOST_DEBUG + + +#ifdef GHOST_DEBUG + #define GHOST_ASSERT(x, info) { if (!(x)) {GHOST_PRINT("assertion failed: "); GHOST_PRINT(info); GHOST_PRINT("\n"); } } +#else // GHOST_DEBUG + #define GHOST_ASSERT(x, info) +#endif // GHOST_DEBUG + +#endif // _GHOST_DEBUG_H_ diff --git a/intern/ghost/intern/GHOST_DisplayManager.cpp b/intern/ghost/intern/GHOST_DisplayManager.cpp new file mode 100644 index 00000000000..dc662634434 --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManager.cpp @@ -0,0 +1,219 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date September 21, 2001 + */ + +#include "GHOST_DisplayManager.h" + +#include "GHOST_Debug.h" + + +GHOST_DisplayManager::GHOST_DisplayManager( + void) +: m_settingsInitialized(false) +{ +} + + +GHOST_DisplayManager::~GHOST_DisplayManager(void) +{ +} + + +GHOST_TSuccess +GHOST_DisplayManager::initialize( + void) +{ + GHOST_TSuccess success; + if (!m_settingsInitialized) { + success = initializeSettings(); + m_settingsInitialized = true; + } + else { + success = GHOST_kSuccess; + } + return success; +} + + +GHOST_TSuccess +GHOST_DisplayManager::getNumDisplays( + GHOST_TUns8& /*numDisplays*/) const +{ + // Don't know if we have a display... + return GHOST_kFailure; +} + + +GHOST_TSuccess +GHOST_DisplayManager::getNumDisplaySettings( + GHOST_TUns8 display, + GHOST_TInt32& numSettings) const +{ + GHOST_TSuccess success; + + GHOST_ASSERT(m_settingsInitialized, "GHOST_DisplayManager::getNumDisplaySettings(): m_settingsInitialized=false"); + GHOST_TUns8 numDisplays; + success = getNumDisplays(numDisplays); + if (success == GHOST_kSuccess) { + if (display < numDisplays) { + numSettings = m_settings[display].size(); + } + else { + success = GHOST_kFailure; + } + } + return success; +} + + +GHOST_TSuccess +GHOST_DisplayManager::getDisplaySetting( + GHOST_TUns8 display, + GHOST_TInt32 index, + GHOST_DisplaySetting& setting) const +{ + GHOST_TSuccess success; + + GHOST_ASSERT(m_settingsInitialized, "GHOST_DisplayManager::getNumDisplaySettings(): m_settingsInitialized=false"); + GHOST_TUns8 numDisplays; + success = getNumDisplays(numDisplays); + if (success == GHOST_kSuccess) { + if (display < numDisplays && index < m_settings[display].size()) { + setting = m_settings[display][index]; + } + else { + success = GHOST_kFailure; + } + } + return success; +} + + +GHOST_TSuccess +GHOST_DisplayManager::getCurrentDisplaySetting( + GHOST_TUns8 /*display*/, + GHOST_DisplaySetting& /*setting*/) const +{ + return GHOST_kFailure; +} + + +GHOST_TSuccess +GHOST_DisplayManager::setCurrentDisplaySetting( + GHOST_TUns8 /*display*/, + const GHOST_DisplaySetting& /*setting*/) +{ + return GHOST_kFailure; +} + + +GHOST_TSuccess +GHOST_DisplayManager::findMatch( + GHOST_TUns8 display, + const GHOST_DisplaySetting& setting, + GHOST_DisplaySetting& match) const +{ + GHOST_TSuccess success = GHOST_kSuccess; + GHOST_ASSERT(m_settingsInitialized, "GHOST_DisplayManager::findMatch(): m_settingsInitialized=false"); + + int criteria[4] = { setting.xPixels, setting.yPixels, setting.bpp, setting.frequency }; + int capabilities[4]; + double field, score; + double best = 1e12; // A big number + int found = 0; + + // Look at all the display modes + for (int i = 0; (i < (int)m_settings[display].size()); i++) { + // Store the capabilities of the display device + capabilities[0] = m_settings[display][i].xPixels; + capabilities[1] = m_settings[display][i].yPixels; + capabilities[2] = m_settings[display][i].bpp; + capabilities[3] = m_settings[display][i].frequency; + + // Match against all the fields of the display settings + score = 0; + for (int j = 0; j < 4; j++) { + field = capabilities[j] - criteria[j]; + score += field * field; + } + + if (score < best) { + found = i; + best = score; + } + } + + match = m_settings[display][found]; + + GHOST_PRINT("GHOST_DisplayManager::findMatch(): settings of match:\n"); + GHOST_PRINT(" setting.xPixels=" << match.xPixels << "\n"); + GHOST_PRINT(" setting.yPixels=" << match.yPixels << "\n"); + GHOST_PRINT(" setting.bpp=" << match.bpp << "\n"); + GHOST_PRINT(" setting.frequency=" << match.frequency << "\n"); + + return success; +} + + +GHOST_TSuccess +GHOST_DisplayManager::initializeSettings( + void) +{ + GHOST_TUns8 numDisplays; + GHOST_TSuccess success = getNumDisplays(numDisplays); + if (success == GHOST_kSuccess) { + for (GHOST_TUns8 display = 0; (display < numDisplays) && (success == GHOST_kSuccess); display++) { + GHOST_DisplaySettings displaySettings; + m_settings.push_back(displaySettings); + GHOST_TInt32 numSettings; + success = getNumDisplaySettings(display, numSettings); + if (success == GHOST_kSuccess) { + GHOST_TInt32 index; + GHOST_DisplaySetting setting; + for (index = 0; (index < numSettings) && (success == GHOST_kSuccess); index++) { + success = getDisplaySetting(display, index, setting); + m_settings[display].push_back(setting); + } + } + else { + break; + } + } + } + return success; +} diff --git a/intern/ghost/intern/GHOST_DisplayManager.h b/intern/ghost/intern/GHOST_DisplayManager.h new file mode 100644 index 00000000000..efc218a4952 --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManager.h @@ -0,0 +1,142 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date September 21, 2001 + */ + +#ifndef _GHOST_DISPLAY_MANAGER_H_ +#define _GHOST_DISPLAY_MANAGER_H_ + +#include "GHOST_Types.h" + +#ifdef WIN32 +#pragma warning (disable:4786) // suppress stl-MSVC debug info warning +#endif // WIN32 + +#include <vector> + +/** + * Manages system displays (platform independent implementation). + */ + +class GHOST_DisplayManager +{ +public: + enum { kMainDisplay = 0 }; + /** + * Constructor. + */ + GHOST_DisplayManager(void); + + /** + * Destructor. + */ + virtual ~GHOST_DisplayManager(void); + + /** + * Initializes the list with devices and settings. + * @return Indication of success. + */ + virtual GHOST_TSuccess initialize(void); + + /** + * Returns the number of display devices on this system. + * @param numDisplays The number of displays on this system. + * @return Indication of success. + */ + virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const; + + /** + * Returns the number of display settings for this display device. + * @param display The index of the display to query with 0 <= display < getNumDisplays(). + * @param setting The number of settings of the display device with this index. + * @return Indication of success. + */ + virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const; + + /** + * Returns the current setting for this display device. + * @param display The index of the display to query with 0 <= display < getNumDisplays(). + * @param index The setting index to be returned. + * @param setting The setting of the display device with this index. + * @return Indication of success. + */ + virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const; + + /** + * Returns the current setting for this display device. + * @param display The index of the display to query with 0 <= display < getNumDisplays(). + * @param setting The current setting of the display device with this index. + * @return Indication of success. + */ + virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const; + + /** + * Changes the current setting for this display device. + * The setting given to this method is matched againts the available diplay settings. + * The best match is activated (@see findMatch()). + * @param display The index of the display to query with 0 <= display < getNumDisplays(). + * @param setting The setting of the display device to be matched and activated. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting); + +protected: + typedef std::vector<GHOST_DisplaySetting> GHOST_DisplaySettings; + + /** + * Finds the best display settings match. + * @param display The index of the display device. + * @param setting The setting to match. + * @param match The optimal display setting. + * @return Indication of success. + */ + GHOST_TSuccess findMatch(GHOST_TUns8 display, const GHOST_DisplaySetting& setting, GHOST_DisplaySetting& match) const; + + /** + * Retrieves settings for each display device and stores them. + * @return Indication of success. + */ + GHOST_TSuccess initializeSettings(void); + + /** Tells whether the list of display modes has been stored already. */ + bool m_settingsInitialized; + /** The list with display settings for the main display. */ + std::vector<GHOST_DisplaySettings> m_settings; +}; + + +#endif // _GHOST_DISPLAY_MANAGER_H_ diff --git a/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp b/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp new file mode 100644 index 00000000000..3220fa1a330 --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp @@ -0,0 +1,178 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date September 21, 2001 + */ + +#include "GHOST_DisplayManagerCarbon.h" + +#include "GHOST_Debug.h" + +// We do not support multiple monitors at the moment + + +GHOST_DisplayManagerCarbon::GHOST_DisplayManagerCarbon(void) +{ + if (::CGGetActiveDisplayList(0, NULL, &m_numDisplays) != CGDisplayNoErr) + { + m_numDisplays = 0; + m_displayIDs = NULL; + } + if (m_numDisplays > 0) + { + m_displayIDs = new CGDirectDisplayID [m_numDisplays]; + GHOST_ASSERT((m_displayIDs!=NULL), "GHOST_DisplayManagerCarbon::GHOST_DisplayManagerCarbon(): memory allocation failed"); + ::CGGetActiveDisplayList(m_numDisplays, m_displayIDs, &m_numDisplays); + } +} + + +GHOST_TSuccess GHOST_DisplayManagerCarbon::getNumDisplays(GHOST_TUns8& numDisplays) const +{ + numDisplays = (GHOST_TUns8) m_numDisplays; + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_DisplayManagerCarbon::getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const +{ + GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::getNumDisplaySettings(): only main display is supported"); + + CFArrayRef displayModes; + displayModes = ::CGDisplayAvailableModes(m_displayIDs[display]); + CFIndex numModes = ::CFArrayGetCount(displayModes); + numSettings = (GHOST_TInt32)numModes; + + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_DisplayManagerCarbon::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const +{ + GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::getDisplaySetting(): only main display is supported"); + + CFArrayRef displayModes; + CGDirectDisplayID d = m_displayIDs[display]; + displayModes = ::CGDisplayAvailableModes(d); + CFIndex numModes = ::CFArrayGetCount(displayModes); + GHOST_TInt32 numSettings = (GHOST_TInt32)numModes; + CFDictionaryRef displayModeValues = (CFDictionaryRef)::CFArrayGetValueAtIndex(displayModes, index); + + setting.xPixels = getValue(displayModeValues, kCGDisplayWidth); + setting.yPixels = getValue(displayModeValues, kCGDisplayHeight); + setting.bpp = getValue(displayModeValues, kCGDisplayBitsPerPixel); + setting.frequency = getValue(displayModeValues, kCGDisplayRefreshRate); + +#ifdef GHOST_DEBUG + printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", setting.xPixels, setting.yPixels, setting.bpp, setting.frequency); +#endif // GHOST_DEBUG + + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_DisplayManagerCarbon::getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const +{ + GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::getCurrentDisplaySetting(): only main display is supported"); + + CFDictionaryRef displayModeValues = ::CGDisplayCurrentMode(m_displayIDs[display]); + + setting.xPixels = getValue(displayModeValues, kCGDisplayWidth); + setting.yPixels = getValue(displayModeValues, kCGDisplayHeight); + setting.bpp = getValue(displayModeValues, kCGDisplayBitsPerPixel); + setting.frequency = getValue(displayModeValues, kCGDisplayRefreshRate); + +#ifdef GHOST_DEBUG + printf("current display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", setting.xPixels, setting.yPixels, setting.bpp, setting.frequency); +#endif // GHOST_DEBUG + + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting) +{ + GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(): only main display is supported"); + +#ifdef GHOST_DEBUG + printf("GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(): requested settings:\n"); + printf(" setting.xPixels=%d\n", setting.xPixels); + printf(" setting.yPixels=%d\n", setting.yPixels); + printf(" setting.bpp=%d\n", setting.bpp); + printf(" setting.frequency=%d\n", setting.frequency); +#endif // GHOST_DEBUG + + CFDictionaryRef displayModeValues = ::CGDisplayBestModeForParametersAndRefreshRate( + m_displayIDs[display], + (size_t)setting.bpp, + (size_t)setting.xPixels, + (size_t)setting.yPixels, + (CGRefreshRate)setting.frequency, + NULL); + +#ifdef GHOST_DEBUG + printf("GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(): switching to:\n"); + printf(" setting.xPixels=%d\n", getValue(displayModeValues, kCGDisplayWidth)); + printf(" setting.yPixels=%d\n", getValue(displayModeValues, kCGDisplayHeight)); + printf(" setting.bpp=%d\n", getValue(displayModeValues, kCGDisplayBitsPerPixel)); + printf(" setting.frequency=%d\n", getValue(displayModeValues, kCGDisplayRefreshRate)); +#endif // GHOST_DEBUG + + CGDisplayErr err = ::CGDisplaySwitchToMode(m_displayIDs[display], displayModeValues); + + return err == CGDisplayNoErr ? GHOST_kSuccess : GHOST_kFailure; +} + + +long GHOST_DisplayManagerCarbon::getValue(CFDictionaryRef values, CFStringRef key) const +{ + CFNumberRef numberValue = (CFNumberRef) CFDictionaryGetValue(values, key); + + if (!numberValue) + { + return -1; + } + + long intValue; + + if (!CFNumberGetValue(numberValue, kCFNumberLongType, &intValue)) + { + return -1; + } + + return intValue; +} + diff --git a/intern/ghost/intern/GHOST_DisplayManagerCarbon.h b/intern/ghost/intern/GHOST_DisplayManagerCarbon.h new file mode 100644 index 00000000000..3374f710f47 --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManagerCarbon.h @@ -0,0 +1,119 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date September 21, 2001 + */ + +#ifndef _GHOST_DISPLAY_MANAGER_CARBON_H_ +#define _GHOST_DISPLAY_MANAGER_CARBON_H_ + +#ifndef __APPLE__ +#error Apple only! +#endif // __APPLE__ + +#include "GHOST_DisplayManager.h" + +#include <Carbon/Carbon.h> + +/** + * Manages system displays (Mac OSX/Carbon implementation). + */ + +class GHOST_DisplayManagerCarbon : public GHOST_DisplayManager +{ +public: + /** + * Constructor. + */ + GHOST_DisplayManagerCarbon(void); + + /** + * Returns the number of display devices on this system. + * @param numDisplays The number of displays on this system. + * @return Indication of success. + */ + virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const; + + /** + * Returns the number of display settings for this display device. + * @param display The index of the display to query with 0 <= display < getNumDisplays(). + * @param setting The number of settings of the display device with this index. + * @return Indication of success. + */ + virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const; + + /** + * Returns the current setting for this display device. + * @param display The index of the display to query with 0 <= display < getNumDisplays(). + * @param index The setting index to be returned. + * @param setting The setting of the display device with this index. + * @return Indication of success. + */ + virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const; + + /** + * Returns the current setting for this display device. + * @param display The index of the display to query with 0 <= display < getNumDisplays(). + * @param setting The current setting of the display device with this index. + * @return Indication of success. + */ + virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const; + + /** + * Changes the current setting for this display device. + * @param display The index of the display to query with 0 <= display < getNumDisplays(). + * @param setting The current setting of the display device with this index. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting); + +protected: + /** + * Returns a value from a dictionary. + * @param values Dictionary to return value from. + * @param key Key to return value for. + * @return The value for this key. + */ + long getValue(CFDictionaryRef values, CFStringRef key) const; + + /** Cached number of displays. */ + CGDisplayCount m_numDisplays; + /** Cached display id's for each display. */ + CGDirectDisplayID* m_displayIDs; +}; + + +#endif // _GHOST_DISPLAY_MANAGER_CARBON_H_ diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp new file mode 100644 index 00000000000..60892ce094e --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp @@ -0,0 +1,186 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date September 21, 2001 + */ + +#include "GHOST_DisplayManagerWin32.h" + +#include "GHOST_Debug.h" + +// We do not support multiple monitors at the moment +#include <windows.h> +#define COMPILE_MULTIMON_STUBS +#include <multimon.h> + + +GHOST_DisplayManagerWin32::GHOST_DisplayManagerWin32(void) +{ +} + + +GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplays(GHOST_TUns8& numDisplays) const +{ + // We do not support multiple monitors at the moment + numDisplays = ::GetSystemMetrics(SM_CMONITORS); + return numDisplays > 0 ? GHOST_kSuccess : GHOST_kFailure; +} + + +/* + * When you call EnumDisplaySettings with iModeNum set to zero, the operating system + * initializes and caches information about the display device. When you call + * EnumDisplaySettings with iModeNum set to a non-zero value, the function returns + * the information that was cached the last time the function was called with iModeNum + * set to zero. + */ +GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const +{ + GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerWin32::getNumDisplaySettings(): only main displlay is supported"); + numSettings = 0; + DEVMODE dm; + while (::EnumDisplaySettings(NULL, numSettings, &dm)) { + numSettings++; + } + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const +{ + GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerWin32::getDisplaySetting(): only main display is supported"); + GHOST_TSuccess success; + DEVMODE dm; + if (::EnumDisplaySettings(NULL, index, &dm)) { +#ifdef GHOST_DEBUG + printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency); +#endif // GHOST_DEBUG + setting.xPixels = dm.dmPelsWidth; + setting.yPixels = dm.dmPelsHeight; + setting.bpp = dm.dmBitsPerPel; + /* When you call the EnumDisplaySettings function, the dmDisplayFrequency member + * may return with the value 0 or 1. These values represent the display hardware's + * default refresh rate. This default rate is typically set by switches on a display + * card or computer motherboard, or by a configuration program that does not use + * Win32 display functions such as ChangeDisplaySettings. + */ + /* First, we tried to explicitly set the frequency to 60 if EnumDisplaySettings + * returned 0 or 1 but this doesn't work since later on an exact match will + * be searched. And this will never happen if we change it to 60. Now we rely + * on the default h/w setting. + */ + setting.frequency = dm.dmDisplayFrequency; + success = GHOST_kSuccess; + } + else { + success = GHOST_kFailure; + } + return success; +} + + +GHOST_TSuccess GHOST_DisplayManagerWin32::getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const +{ + GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerWin32::getCurrentDisplaySetting(): only main display is supported"); + return getDisplaySetting(kMainDisplay, ENUM_CURRENT_SETTINGS, setting); +} + + +GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting) +{ + GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerWin32::setCurrentDisplaySetting(): only main display is supported"); + + GHOST_DisplaySetting match; + GHOST_TSuccess success = findMatch(display, setting, match); + DEVMODE dm; + int i = 0; + while (::EnumDisplaySettings(NULL, i++, &dm)) { + if ((dm.dmBitsPerPel == match.bpp) && + (dm.dmPelsWidth == match.xPixels) && + (dm.dmPelsHeight == match.yPixels) && + (dm.dmDisplayFrequency == match.frequency)) { + break; + } + } + /* + dm.dmBitsPerPel = match.bpp; + dm.dmPelsWidth = match.xPixels; + dm.dmPelsHeight = match.yPixels; + dm.dmDisplayFrequency = match.frequency; + dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; + dm.dmSize = sizeof(DEVMODE); + dm.dmDriverExtra = 0; + */ +#ifdef GHOST_DEBUG + printf("display change: Requested settings:\n"); + printf(" dmBitsPerPel=%d\n", dm.dmBitsPerPel); + printf(" dmPelsWidth=%d\n", dm.dmPelsWidth); + printf(" dmPelsHeight=%d\n", dm.dmPelsHeight); + printf(" dmDisplayFrequency=%d\n", dm.dmDisplayFrequency); +#endif // GHOST_DEBUG + + LONG status = ::ChangeDisplaySettings(&dm, CDS_FULLSCREEN); +#ifdef GHOST_DEBUG + switch (status) + { + case DISP_CHANGE_SUCCESSFUL: + printf("display change: The settings change was successful.\n"); + break; + case DISP_CHANGE_RESTART: + printf("display change: The computer must be restarted in order for the graphics mode to work.\n"); + break; + case DISP_CHANGE_BADFLAGS: + printf("display change: An invalid set of flags was passed in.\n"); + break; + case DISP_CHANGE_BADPARAM: + printf("display change: An invalid parameter was passed in. This can include an invalid flag or combination of flags.\n"); + break; + case DISP_CHANGE_FAILED: + printf("display change: The display driver failed the specified graphics mode.\n"); + break; + case DISP_CHANGE_BADMODE: + printf("display change: The graphics mode is not supported.\n"); + break; + case DISP_CHANGE_NOTUPDATED: + printf("display change: Windows NT: Unable to write settings to the registry.\n"); + break; + default: + printf("display change: Return value invalid\n"); + break; + } +#endif // GHOST_DEBUG + return status == DISP_CHANGE_SUCCESSFUL? GHOST_kSuccess : GHOST_kFailure; +} diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.h b/intern/ghost/intern/GHOST_DisplayManagerWin32.h new file mode 100644 index 00000000000..f44ba07ee33 --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.h @@ -0,0 +1,106 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date September 21, 2001 + */ + +#ifndef _GHOST_DISPLAY_MANAGER_WIN32_H_ +#define _GHOST_DISPLAY_MANAGER_WIN32_H_ + +#ifndef WIN32 +#error WIN32 only! +#endif // WIN32 + +#include "GHOST_DisplayManager.h" + + +/** + * Manages system displays (WIN32 implementation). + */ + +class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager +{ +public: + /** + * Constructor. + */ + GHOST_DisplayManagerWin32(void); + + /** + * Returns the number of display devices on this system. + * @param numDisplays The number of displays on this system. + * @return Indication of success. + */ + virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const; + + /** + * Returns the number of display settings for this display device. + * @param display The index of the display to query with 0 <= display < getNumDisplays(). + * @param setting The number of settings of the display device with this index. + * @return Indication of success. + */ + virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const; + + /** + * Returns the current setting for this display device. + * @param display The index of the display to query with 0 <= display < getNumDisplays(). + * @param index The setting index to be returned. + * @param setting The setting of the display device with this index. + * @return Indication of success. + */ + virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const; + + /** + * Returns the current setting for this display device. + * @param display The index of the display to query with 0 <= display < getNumDisplays(). + * @param setting The current setting of the display device with this index. + * @return Indication of success. + */ + virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const; + + /** + * Changes the current setting for this display device. + * @param display The index of the display to query with 0 <= display < getNumDisplays(). + * @param setting The current setting of the display device with this index. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting); + +protected: +}; + + +#endif // _GHOST_DISPLAY_MANAGER_WIN32_H_ diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp new file mode 100755 index 00000000000..1eb0e0a10ca --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp @@ -0,0 +1,125 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "GHOST_DisplayManagerX11.h" + +#include "GHOST_SystemX11.h" + + + +GHOST_DisplayManagerX11:: +GHOST_DisplayManagerX11( + GHOST_SystemX11 *system +) : + GHOST_DisplayManager(), + m_system(system) +{ + //nothing to do. +} + + GHOST_TSuccess +GHOST_DisplayManagerX11:: +getNumDisplays( + GHOST_TUns8& numDisplays +) const{ + numDisplays = m_system->getNumDisplays(); + return GHOST_kSuccess; +} + + + GHOST_TSuccess +GHOST_DisplayManagerX11:: +getNumDisplaySettings( + GHOST_TUns8 display, + GHOST_TInt32& numSettings +) const{ + + // We only have one X11 setting at the moment. + GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n"); + numSettings = GHOST_TInt32(1); + return GHOST_kSuccess; +} + + GHOST_TSuccess +GHOST_DisplayManagerX11:: +getDisplaySetting( + GHOST_TUns8 display, + GHOST_TInt32 index, + GHOST_DisplaySetting& setting +) const { + + GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n"); + GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n"); + + Display * x_display = m_system->getXDisplay(); + + if (x_display == NULL) { + return GHOST_kFailure; + } + + setting.xPixels = DisplayWidth(x_display, DefaultScreen(x_display)); + setting.yPixels = DisplayHeight(x_display, DefaultScreen(x_display)); + setting.bpp = DefaultDepth(x_display,DefaultScreen(x_display)); + + // Don't think it's possible to get this value from X! + // So let's guess!! + setting.frequency = 60; + + return GHOST_kSuccess; +} + + GHOST_TSuccess +GHOST_DisplayManagerX11:: +getCurrentDisplaySetting( + GHOST_TUns8 display, + GHOST_DisplaySetting& setting +) const { + return getDisplaySetting(display,GHOST_TInt32(0),setting); +} + + + GHOST_TSuccess +GHOST_DisplayManagerX11:: +setCurrentDisplaySetting( + GHOST_TUns8 display, + const GHOST_DisplaySetting& setting +){ + // This is never going to work robustly in X + // but it's currently part of the full screen interface + + // we fudge it for now. + + return GHOST_kSuccess; +} + + + + diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.h b/intern/ghost/intern/GHOST_DisplayManagerX11.h new file mode 100755 index 00000000000..7f4e772ce95 --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManagerX11.h @@ -0,0 +1,129 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date September 21, 2001 + */ + +#ifndef _GHOST_DISPLAY_MANAGER_X11_H_ +#define _GHOST_DISPLAY_MANAGER_X11_H_ + + +#include "GHOST_DisplayManager.h" + + +class GHOST_SystemX11; + +/** + * Manages system displays (X11 implementation). + */ + +class GHOST_DisplayManagerX11 : public GHOST_DisplayManager +{ +public: + /** + * Constructor. + */ + GHOST_DisplayManagerX11( + GHOST_SystemX11 *system + ); + + /** + * Returns the number of display devices on this system. + * @param numDisplays The number of displays on this system. + * @return Indication of success. + */ + GHOST_TSuccess + getNumDisplays( + GHOST_TUns8& numDisplays + ) const; + + /** + * Returns the number of display settings for this display device. + * @param display The index of the display to query with 0 <= display < getNumDisplays(). + * @param setting The number of settings of the display device with this index. + * @return Indication of success. + */ + GHOST_TSuccess + getNumDisplaySettings( + GHOST_TUns8 display, + GHOST_TInt32& numSettings + ) const; + + /** + * Returns the current setting for this display device. + * @param display The index of the display to query with 0 <= display < getNumDisplays(). + * @param index The setting index to be returned. + * @param setting The setting of the display device with this index. + * @return Indication of success. + */ + GHOST_TSuccess + getDisplaySetting( + GHOST_TUns8 display, + GHOST_TInt32 index, + GHOST_DisplaySetting& setting + ) const; + + /** + * Returns the current setting for this display device. + * @param display The index of the display to query with 0 <= display < getNumDisplays(). + * @param setting The current setting of the display device with this index. + * @return Indication of success. + */ + GHOST_TSuccess + getCurrentDisplaySetting( + GHOST_TUns8 display, + GHOST_DisplaySetting& setting + ) const; + + /** + * Changes the current setting for this display device. + * @param display The index of the display to query with 0 <= display < getNumDisplays(). + * @param setting The current setting of the display device with this index. + * @return Indication of success. + */ + GHOST_TSuccess + setCurrentDisplaySetting( + GHOST_TUns8 display, + const GHOST_DisplaySetting& setting + ); + +private : + + GHOST_SystemX11 * m_system; +}; + + +#endif // diff --git a/intern/ghost/intern/GHOST_Event.h b/intern/ghost/intern/GHOST_Event.h new file mode 100644 index 00000000000..90b411febf9 --- /dev/null +++ b/intern/ghost/intern/GHOST_Event.h @@ -0,0 +1,114 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 11, 2001 + */ + +#ifndef _GHOST_EVENT_H_ +#define _GHOST_EVENT_H_ + +#include "GHOST_IEvent.h" + + +/** + * Base class for events received the operating system. + * @author Maarten Gribnau + * @date May 11, 2001 + */ + +class GHOST_Event : public GHOST_IEvent +{ +public: + /** + * Constructor. + * @param msec The time this event was generated. + * @param type The type of this event. + * @param window The generating window (or NULL if system event). + */ + GHOST_Event(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window) + : m_type(type), m_time(msec), m_window(window), m_data(0) + { + } + + /** + * Returns the event type. + * @return The event type. + */ + virtual GHOST_TEventType getType() + { + return m_type; + } + + /** + * Returns the time this event was generated. + * @return The event generation time. + */ + virtual GHOST_TUns64 getTime() + { + return m_time; + } + + /** + * Returns the window this event was generated on, + * or NULL if it is a 'system' event. + * @return The generating window. + */ + virtual GHOST_IWindow* getWindow() + { + return m_window; + } + + /** + * Returns the event data. + * @return The event data. + */ + virtual GHOST_TEventDataPtr getData() + { + return m_data; + } + +protected: + /** Type of this event. */ + GHOST_TEventType m_type; + /** The time this event was generated. */ + GHOST_TUns64 m_time; + /** Pointer to the generating window. */ + GHOST_IWindow* m_window; + /** Pointer to the event data. */ + GHOST_TEventDataPtr m_data; +}; + +#endif // _GHOST_EVENT_H_ diff --git a/intern/ghost/intern/GHOST_EventButton.h b/intern/ghost/intern/GHOST_EventButton.h new file mode 100644 index 00000000000..f0718414ced --- /dev/null +++ b/intern/ghost/intern/GHOST_EventButton.h @@ -0,0 +1,73 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 11, 2001 + */ + +#ifndef _GHOST_EVENT_BUTTON_H_ +#define _GHOST_EVENT_BUTTON_H_ + +#include "GHOST_Event.h" + +/** + * Mouse button event. + * @author Maarten Gribnau + * @date May 11, 2001 + */ +class GHOST_EventButton : public GHOST_Event +{ +public: + /** + * Constructor. + * @param time The time this event was generated. + * @param type The type of this event. + * @param x The x-coordinate of the location the cursor was at at the time of the event. + * @param y The y-coordinate of the location the cursor was at at the time of the event. + * @param buttons The state of the buttons was at at the time of the event. + */ + GHOST_EventButton(GHOST_TUns64 time, GHOST_TEventType type, GHOST_IWindow* window, GHOST_TButtonMask button) + : GHOST_Event(time, type, window) + { + m_buttonEventData.button = button; + m_data = &m_buttonEventData; + } + +protected: + /** The button event data. */ + GHOST_TEventButtonData m_buttonEventData; +}; + +#endif // _GHOST_EVENT_BUTTON_H_ diff --git a/intern/ghost/intern/GHOST_EventCursor.h b/intern/ghost/intern/GHOST_EventCursor.h new file mode 100644 index 00000000000..9b7d3d3acc7 --- /dev/null +++ b/intern/ghost/intern/GHOST_EventCursor.h @@ -0,0 +1,74 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 11, 2001 + */ + +#ifndef _GHOST_EVENT_CURSOR_H_ +#define _GHOST_EVENT_CURSOR_H_ + +#include "GHOST_Event.h" + +/** + * Cursor event. + * @author Maarten Gribnau + * @date May 11, 2001 + */ +class GHOST_EventCursor : public GHOST_Event +{ +public: + /** + * Constructor. + * @param msec The time this event was generated. + * @param type The type of this event. + * @param x The x-coordinate of the location the cursor was at at the time of the event. + * @param y The y-coordinate of the location the cursor was at at the time of the event. + */ + GHOST_EventCursor(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window, GHOST_TInt32 x, GHOST_TInt32 y) + : GHOST_Event(msec, type, window) + { + m_cursorEventData.x = x; + m_cursorEventData.y = y; + m_data = &m_cursorEventData; + } + +protected: + /** The x,y-coordinates of the cursor position. */ + GHOST_TEventCursorData m_cursorEventData; +}; + + +#endif // _GHOST_EVENT_CURSOR_H_ diff --git a/intern/ghost/intern/GHOST_EventKey.h b/intern/ghost/intern/GHOST_EventKey.h new file mode 100644 index 00000000000..19602736d99 --- /dev/null +++ b/intern/ghost/intern/GHOST_EventKey.h @@ -0,0 +1,87 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 11, 2001 + */ + +#ifndef _GHOST_EVENT_KEY_H_ +#define _GHOST_EVENT_KEY_H_ + +#include "GHOST_Event.h" + +/** + * Key event. + * @author Maarten Gribnau + * @date May 11, 2001 + */ +class GHOST_EventKey : public GHOST_Event +{ +public: + /** + * Constructor. + * @param msec The time this event was generated. + * @param type The type of key event. + * @param key The key code of the key. + */ + GHOST_EventKey(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window, GHOST_TKey key) + : GHOST_Event(msec, type, window) + { + m_keyEventData.key = key; + m_keyEventData.ascii = '\0'; + m_data = &m_keyEventData; + } + + /** + * Constructor. + * @param msec The time this event was generated. + * @param type The type of key event. + * @param key The key code of the key. + * @param ascii The ascii code for the key event. + */ + GHOST_EventKey(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window, GHOST_TKey key, char ascii) + : GHOST_Event(msec, type, window) + { + m_keyEventData.key = key; + m_keyEventData.ascii = ascii; + m_data = &m_keyEventData; + } + +protected: + /** The key event data. */ + GHOST_TEventKeyData m_keyEventData; +}; + +#endif // _GHOST_EVENT_KEY_H_ diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp new file mode 100644 index 00000000000..f4a8b72db25 --- /dev/null +++ b/intern/ghost/intern/GHOST_EventManager.cpp @@ -0,0 +1,215 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 14, 2001 + */ + +#include "GHOST_EventManager.h" + +#include <algorithm> + +#include "GHOST_Debug.h" + + +GHOST_EventManager::GHOST_EventManager() +{ +} + + +GHOST_EventManager::~GHOST_EventManager() +{ + disposeEvents(); +} + + +GHOST_TUns32 GHOST_EventManager::getNumEvents() +{ + return (GHOST_TUns32) m_events.size(); +} + + +GHOST_TUns32 GHOST_EventManager::getNumEvents(GHOST_TEventType type) +{ + GHOST_TUns32 numEvents = 0; + std::deque<GHOST_IEvent*>::iterator p; + for (p = m_events.begin(); p != m_events.end(); p++) { + if ((*p)->getType() == type) { + numEvents++; + } + } + return numEvents; +} + + +GHOST_IEvent* GHOST_EventManager::peekEvent() +{ + GHOST_IEvent* event = 0; + if (m_events.size() > 0) { + event = m_events.back(); + } + return event; +} + + +GHOST_TSuccess GHOST_EventManager::pushEvent(GHOST_IEvent* event) +{ + GHOST_TSuccess success; + GHOST_ASSERT(event, "invalid event"); + if (m_events.size() < m_events.max_size()) { + m_events.push_front(event); + success = GHOST_kSuccess; + } + else { + success = GHOST_kFailure; + } + return success; +} + + +bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event) +{ + bool handled; + if (event) { + handled = true; + /* + for (unsigned int i = 0; i < m_consumers.size(); i++) { + if (m_consumers[i]->processEvent(event)) { + handled = false; + } + } + */ + TConsumerVector::iterator iter; + for (iter = m_consumers.begin(); iter != m_consumers.end(); iter++) { + if ((*iter)->processEvent(event)) { + handled = false; + } + } + } + else { + handled = false; + } + return handled; +} + + +bool GHOST_EventManager::dispatchEvent() +{ + GHOST_IEvent* event = popEvent(); + bool handled = false; + if (event) { + handled = dispatchEvent(event); + delete event; + } + return handled; +} + + +bool GHOST_EventManager::dispatchEvents() +{ + bool handled; + if (getNumEvents()) { + handled = true; + while (getNumEvents()) { + if (!dispatchEvent()) { + handled = false; + } + } + } + else { + handled = false; + } + return handled; +} + + +GHOST_TSuccess GHOST_EventManager::addConsumer(GHOST_IEventConsumer* consumer) +{ + GHOST_TSuccess success; + GHOST_ASSERT(consumer, "invalid consumer"); + + // Check to see whether the consumer is already in our list + TConsumerVector::const_iterator iter = std::find(m_consumers.begin(), m_consumers.end(), consumer); + + if (iter == m_consumers.end()) { + // Add the consumer + m_consumers.push_back(consumer); + success = GHOST_kSuccess; + } + else { + success = GHOST_kFailure; + } + return success; +} + + +GHOST_TSuccess GHOST_EventManager::removeConsumer(GHOST_IEventConsumer* consumer) +{ + GHOST_TSuccess success; + GHOST_ASSERT(consumer, "invalid consumer"); + + // Check to see whether the consumer is in our list + TConsumerVector::iterator iter = std::find(m_consumers.begin(), m_consumers.end(), consumer); + + if (iter != m_consumers.end()) { + // Remove the consumer + m_consumers.erase(iter); + success = GHOST_kSuccess; + } + else { + success = GHOST_kFailure; + } + return success; +} + + +GHOST_IEvent* GHOST_EventManager::popEvent() +{ + GHOST_IEvent* event = peekEvent(); + if (event) { + m_events.pop_back(); + } + return event; +} + + +void GHOST_EventManager::disposeEvents() +{ + while (m_events.size() > 0) { + GHOST_ASSERT(m_events[0], "invalid event"); + delete m_events[0]; + m_events.pop_front(); + } +} diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h new file mode 100644 index 00000000000..93c009b892d --- /dev/null +++ b/intern/ghost/intern/GHOST_EventManager.h @@ -0,0 +1,157 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 14, 2001 + */ + +#ifndef _GHOST_EVENT_MANAGER_H_ +#define _GHOST_EVENT_MANAGER_H_ + +#ifdef WIN32 +#pragma warning (disable:4786) // suppress stl-MSVC debug info warning +#endif // WIN32 + +#include <deque> +#include <vector> + +#include "GHOST_IEventConsumer.h" + + +/** + * Manages an event stack and a list of event consumers. + * The stack works on a FIFO (First In First Out) basis. + * Events are pushed on the front of the stack and retrieved from the back. + * Ownership of the event is transferred to the event manager as soon as an event is pushed. + * Ownership of the event is transferred from the event manager as soon as an event is popped. + * Events can be dispatched to the event consumers. + */ +class GHOST_EventManager +{ +public: + /** + * Constructor. + */ + GHOST_EventManager(); + + /** + * Destructor. + */ + virtual ~GHOST_EventManager(); + + /** + * Returns the number of events currently on the stack. + * @return The number of events on the stack. + */ + virtual GHOST_TUns32 getNumEvents(); + + /** + * Returns the number of events of a certain type currently on the stack. + * @param type The type of events to be counted. + * @return The number of events on the stack of this type. + */ + virtual GHOST_TUns32 getNumEvents(GHOST_TEventType type); + + /** + * Return the event at the top of the stack without removal. + * Do not delete the event! + * @return The event at the top of the stack. + */ + virtual GHOST_IEvent* peekEvent(); + + /** + * Pushes an event on the stack. + * To dispatch it, call dispatchEvent() or dispatchEvents(). + * Do not delete the event! + * @param event The event to push on the stack. + */ + virtual GHOST_TSuccess pushEvent(GHOST_IEvent* event); + + /** + * Dispatches the given event directly, bypassing the event stack. + * @return Indication as to whether any of the consumers handled the event. + */ + virtual bool dispatchEvent(GHOST_IEvent* event); + + /** + * Dispatches the event at the back of the stack. + * The event will be removed from the stack. + * @return Indication as to whether any of the consumers handled the event. + */ + virtual bool dispatchEvent(); + + /** + * Dispatches all the events on the stack. + * The event stack will be empty afterwards. + * @return Indication as to whether any of the consumers handled the events. + */ + virtual bool dispatchEvents(); + + /** + * Adds a consumer to the list of event consumers. + * @param consumer The consumer added to the list. + * @return Indication as to whether addition has succeeded. + */ + virtual GHOST_TSuccess addConsumer(GHOST_IEventConsumer* consumer); + + /** + * Removes a consumer from the list of event consumers. + * @param consumer The consumer removed from the list. + * @return Indication as to whether removal has succeeded. + */ + virtual GHOST_TSuccess removeConsumer(GHOST_IEventConsumer* consumer); + +protected: + /** + * Returns the event at the top of the stack and removes it. + * Delete the event after use! + * @return The event at the top of the stack. + */ + virtual GHOST_IEvent* popEvent(); + + /** + * Removes all events from the stack. + */ + virtual void disposeEvents(); + + /** The event stack. */ + std::deque<GHOST_IEvent*> m_events; + + typedef std::vector<GHOST_IEventConsumer*> TConsumerVector; + /** The list with event consumers. */ + TConsumerVector m_consumers; +}; + +#endif // _GHOST_EVENT_MANAGER_H_ diff --git a/intern/ghost/intern/GHOST_EventPrinter.cpp b/intern/ghost/intern/GHOST_EventPrinter.cpp new file mode 100644 index 00000000000..16576357fbc --- /dev/null +++ b/intern/ghost/intern/GHOST_EventPrinter.cpp @@ -0,0 +1,259 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 15, 2001 + */ + +#include "GHOST_EventPrinter.h" + +#include <iostream> + +#include "GHOST_EventKey.h" +#include "GHOST_Debug.h" + +bool GHOST_EventPrinter::processEvent(GHOST_IEvent* event) +{ + bool handled = true; + + GHOST_ASSERT(event, "event==0"); + + if (event->getType() == GHOST_kEventWindowUpdate) return false; + + std::cout << "GHOST_EventPrinter::processEvent, time: " << (GHOST_TInt32)event->getTime() << ", type: "; + switch (event->getType()) { + case GHOST_kEventUnknown: + std::cout << "GHOST_kEventUnknown"; handled = false; break; + + case GHOST_kEventButtonUp: + { + GHOST_TEventButtonData* buttonData = (GHOST_TEventButtonData*)((GHOST_IEvent*)event)->getData(); + std::cout << "GHOST_kEventCursorButtonUp, button: " << buttonData->button; + } + break; + case GHOST_kEventButtonDown: + { + GHOST_TEventButtonData* buttonData = (GHOST_TEventButtonData*)((GHOST_IEvent*)event)->getData(); + std::cout << "GHOST_kEventButtonDown, button: " << buttonData->button; + } + break; + + case GHOST_kEventCursorMove: + { + GHOST_TEventCursorData* cursorData = (GHOST_TEventCursorData*)((GHOST_IEvent*)event)->getData(); + std::cout << "GHOST_kEventCursorMove, (x,y): (" << cursorData->x << "," << cursorData->y << ")"; + } + break; + + case GHOST_kEventKeyUp: + { + GHOST_TEventKeyData* keyData = (GHOST_TEventKeyData*)((GHOST_IEvent*)event)->getData(); + STR_String str; + getKeyString(keyData->key, str); + std::cout << "GHOST_kEventKeyUp, key: " << str.Ptr(); + } + break; + case GHOST_kEventKeyDown: + { + GHOST_TEventKeyData* keyData = (GHOST_TEventKeyData*)((GHOST_IEvent*)event)->getData(); + STR_String str; + getKeyString(keyData->key, str); + std::cout << "GHOST_kEventKeyDown, key: " << str.Ptr(); + } + break; + + case GHOST_kEventQuit: + std::cout << "GHOST_kEventQuit"; break; + case GHOST_kEventWindowClose: + std::cout << "GHOST_kEventWindowClose"; break; + case GHOST_kEventWindowActivate: + std::cout << "GHOST_kEventWindowActivate"; break; + case GHOST_kEventWindowDeactivate: + std::cout << "GHOST_kEventWindowDeactivate"; break; + case GHOST_kEventWindowUpdate: + std::cout << "GHOST_kEventWindowUpdate"; break; + case GHOST_kEventWindowSize: + std::cout << "GHOST_kEventWindowSize"; break; + + default: + std::cout << "not found"; handled = false; break; + } + std::cout << "\n"; + return handled; +} + + +void GHOST_EventPrinter::getKeyString(GHOST_TKey key, STR_String& str) const +{ + if ((key >= GHOST_kKeyComma) && (key <= GHOST_kKeyRightBracket)) { + str = ((char)key); + } + else if ((key >= GHOST_kKeyNumpad0) && (key <= GHOST_kKeyNumpad9)) { + int number = key - GHOST_kKeyNumpad0; + STR_String numberStr (number); + str = "Numpad"; + str += numberStr; + } + else if ((key >= GHOST_kKeyF1) && (key <= GHOST_kKeyF24)) { + int number = key - GHOST_kKeyF1 + 1; + STR_String numberStr (number); + str = "F"; + str += numberStr; + } + else { + switch (key) + { + case GHOST_kKeyBackSpace: + str = "BackSpace"; + break; + case GHOST_kKeyTab: + str = "Tab"; + break; + case GHOST_kKeyLinefeed: + str = "Linefeed"; + break; + case GHOST_kKeyClear: + str = "Clear"; + break; + case GHOST_kKeyEnter: + str = "Enter"; + break; + case GHOST_kKeyEsc: + str = "Esc"; + break; + case GHOST_kKeySpace: + str = "Space"; + break; + case GHOST_kKeyQuote: + str = "Quote"; + break; + case GHOST_kKeyBackslash: + str = "\\"; + break; + case GHOST_kKeyAccentGrave: + str = "`"; + break; + case GHOST_kKeyLeftShift: + str = "LeftShift"; + break; + case GHOST_kKeyRightShift: + str = "RightShift"; + break; + case GHOST_kKeyLeftControl: + str = "LeftControl"; + break; + case GHOST_kKeyRightControl: + str = "RightControl"; + break; + case GHOST_kKeyLeftAlt: + str = "LeftAlt"; + break; + case GHOST_kKeyRightAlt: + str = "RightAlt"; + break; + case GHOST_kKeyCommand: + // APPLE only! + str = "Command"; + break; + case GHOST_kKeyCapsLock: + str = "CapsLock"; + break; + case GHOST_kKeyNumLock: + str = "NumLock"; + break; + case GHOST_kKeyScrollLock: + str = "ScrollLock"; + break; + case GHOST_kKeyLeftArrow: + str = "LeftArrow"; + break; + case GHOST_kKeyRightArrow: + str = "RightArrow"; + break; + case GHOST_kKeyUpArrow: + str = "UpArrow"; + break; + case GHOST_kKeyDownArrow: + str = "DownArrow"; + break; + case GHOST_kKeyPrintScreen: + str = "PrintScreen"; + break; + case GHOST_kKeyPause: + str = "Pause"; + break; + case GHOST_kKeyInsert: + str = "Insert"; + break; + case GHOST_kKeyDelete: + str = "Delete"; + break; + case GHOST_kKeyHome: + str = "Home"; + break; + case GHOST_kKeyEnd: + str = "End"; + break; + case GHOST_kKeyUpPage: + str = "UpPage"; + break; + case GHOST_kKeyDownPage: + str = "DownPage"; + break; + case GHOST_kKeyNumpadPeriod: + str = "NumpadPeriod"; + break; + case GHOST_kKeyNumpadEnter: + str = "NumpadEnter"; + break; + case GHOST_kKeyNumpadPlus: + str = "NumpadPlus"; + break; + case GHOST_kKeyNumpadMinus: + str = "NumpadMinus"; + break; + case GHOST_kKeyNumpadAsterisk: + str = "NumpadAsterisk"; + break; + case GHOST_kKeyNumpadSlash: + str = "NumpadSlash"; + break; + default: + str = "unknown"; + break; + } + } +} + diff --git a/intern/ghost/intern/GHOST_EventPrinter.h b/intern/ghost/intern/GHOST_EventPrinter.h new file mode 100644 index 00000000000..6214e94393d --- /dev/null +++ b/intern/ghost/intern/GHOST_EventPrinter.h @@ -0,0 +1,70 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 14, 2001 + */ + +#ifndef _GHOST_EVENT_PRINTER_H_ +#define _GHOST_EVENT_PRINTER_H_ + +#include "GHOST_IEventConsumer.h" + +#include "STR_String.h" + +/** + * An Event consumer that prints all the events to standard out. + * Really useful when debugging. + */ +class GHOST_EventPrinter : public GHOST_IEventConsumer +{ +public: + /** + * Prints all the events received to std out. + * @param event The event that can be handled or not. + * @return Indication as to whether the event was handled. + */ + virtual bool processEvent(GHOST_IEvent* event); + +protected: + /** + * Converts GHOST key code to a readable string. + * @param key The GHOST key code to convert. + * @param str The GHOST key code converted to a readable string. + */ + void getKeyString(GHOST_TKey key, STR_String& str) const; +}; + +#endif // _GHOST_EVENT_PRINTER_H_ diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp new file mode 100644 index 00000000000..6505194645a --- /dev/null +++ b/intern/ghost/intern/GHOST_ISystem.cpp @@ -0,0 +1,98 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 7, 2001 + */ + +#include "GHOST_ISystem.h" + +#ifdef WIN32 +# include "GHOST_SystemWin32.h" +#else +# ifdef __APPLE__ +# include "GHOST_SystemCarbon.h" +# else +# include "GHOST_SystemX11.h" +# endif +#endif + + +GHOST_ISystem* GHOST_ISystem::m_system = 0; + + +GHOST_TSuccess GHOST_ISystem::createSystem() +{ + GHOST_TSuccess success; + if (!m_system) { +#ifdef WIN32 + m_system = new GHOST_SystemWin32 (); +#else +# ifdef __APPLE__ + m_system = new GHOST_SystemCarbon (); +# else + m_system = new GHOST_SystemX11 (); +# endif +#endif + success = m_system != 0 ? GHOST_kSuccess : GHOST_kFailure; + } + else { + success = GHOST_kFailure; + } + if (success) { + success = m_system->init(); + } + return success; +} + +GHOST_TSuccess GHOST_ISystem::disposeSystem() +{ + GHOST_TSuccess success; + if (m_system) { + delete m_system; + m_system = 0; + } + else { + success = GHOST_kFailure; + } + return success; +} + + +GHOST_ISystem* GHOST_ISystem::getSystem() +{ + return m_system; +} + diff --git a/intern/ghost/intern/GHOST_ModifierKeys.cpp b/intern/ghost/intern/GHOST_ModifierKeys.cpp new file mode 100644 index 00000000000..930ddf97f9a --- /dev/null +++ b/intern/ghost/intern/GHOST_ModifierKeys.cpp @@ -0,0 +1,136 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 31, 2001 + */ + +#include "GHOST_ModifierKeys.h" + + +GHOST_ModifierKeys::GHOST_ModifierKeys() +{ + clear(); +} + + +GHOST_TKey GHOST_ModifierKeys::getModifierKeyCode(GHOST_TModifierKeyMask mask) +{ + GHOST_TKey key; + switch (mask) { + case GHOST_kModifierKeyLeftShift: key = GHOST_kKeyLeftShift; break; + case GHOST_kModifierKeyRightShift: key = GHOST_kKeyRightShift; break; + case GHOST_kModifierKeyLeftAlt: key = GHOST_kKeyLeftAlt; break; + case GHOST_kModifierKeyRightAlt: key = GHOST_kKeyRightAlt; break; + case GHOST_kModifierKeyLeftControl: key = GHOST_kKeyLeftControl; break; + case GHOST_kModifierKeyRightControl: key = GHOST_kKeyRightControl; break; + case GHOST_kModifierKeyCommand: key = GHOST_kKeyCommand; break; + default: + // Should not happen + key = GHOST_kKeyUnknown; + break; + } + return key; +} + + +bool GHOST_ModifierKeys::get(GHOST_TModifierKeyMask mask) const +{ + switch (mask) { + case GHOST_kModifierKeyLeftShift: + return m_LeftShift; + case GHOST_kModifierKeyRightShift: + return m_RightShift; + case GHOST_kModifierKeyLeftAlt: + return m_LeftAlt; + case GHOST_kModifierKeyRightAlt: + return m_RightAlt; + case GHOST_kModifierKeyLeftControl: + return m_LeftControl; + case GHOST_kModifierKeyRightControl: + return m_RightControl; + case GHOST_kModifierKeyCommand: + return m_Command; + default: + return false; + } +} + + +void GHOST_ModifierKeys::set(GHOST_TModifierKeyMask mask, bool down) +{ + switch (mask) { + case GHOST_kModifierKeyLeftShift: + m_LeftShift = down; break; + case GHOST_kModifierKeyRightShift: + m_RightShift = down; break; + case GHOST_kModifierKeyLeftAlt: + m_LeftAlt = down; break; + case GHOST_kModifierKeyRightAlt: + m_RightAlt = down; break; + case GHOST_kModifierKeyLeftControl: + m_LeftControl = down; break; + case GHOST_kModifierKeyRightControl: + m_RightControl = down; break; + case GHOST_kModifierKeyCommand: + m_Command = down; break; + default: + break; + } +} + + +void GHOST_ModifierKeys::clear() +{ + m_LeftShift = false; + m_RightShift = false; + m_LeftAlt = false; + m_RightAlt = false; + m_LeftControl = false; + m_RightControl = false; + m_Command = false; +} + + +bool GHOST_ModifierKeys::equals(const GHOST_ModifierKeys& keys) const +{ + return (m_LeftShift == keys.m_LeftShift) && + (m_RightShift == keys.m_RightShift) && + (m_LeftAlt == keys.m_LeftAlt) && + (m_RightAlt == keys.m_RightAlt) && + (m_LeftControl == keys.m_LeftControl) && + (m_RightControl == keys.m_RightControl) && + (m_Command == keys.m_Command); +} diff --git a/intern/ghost/intern/GHOST_ModifierKeys.h b/intern/ghost/intern/GHOST_ModifierKeys.h new file mode 100644 index 00000000000..fc590b9597f --- /dev/null +++ b/intern/ghost/intern/GHOST_ModifierKeys.h @@ -0,0 +1,102 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 17, 2001 + */ + +#ifndef _GHOST_MODIFIER_KEYS_H_ +#define _GHOST_MODIFIER_KEYS_H_ + +#include "GHOST_Types.h" + +struct GHOST_ModifierKeys +{ + /** + * Constructor. + */ + GHOST_ModifierKeys(); + + /** + * Returns the modifier key's key code from a modifier key mask. + * @param mask The mask of the modifier key. + * @return The modifier key's key code. + */ + static GHOST_TKey getModifierKeyCode(GHOST_TModifierKeyMask mask); + + + /** + * Returns the state of a single modifier key. + * @param mask. Key state to return. + * @return The state of the key (pressed == true). + */ + virtual bool get(GHOST_TModifierKeyMask mask) const; + + /** + * Updates the state of a single modifier key. + * @param mask. Key state to update. + * @param down. The new state of the key. + */ + virtual void set(GHOST_TModifierKeyMask mask, bool down); + + /** + * Sets the state of all modifier keys to up. + */ + virtual void clear(); + + /** + * Determines whether to modifier key states are equal. + * @param keys. The modifier key state to compare to. + * @return Indication of equality. + */ + virtual bool equals(const GHOST_ModifierKeys& keys) const; + + /** Bitfield that stores the appropriate key state. */ + GHOST_TUns8 m_LeftShift : 1; + /** Bitfield that stores the appropriate key state. */ + GHOST_TUns8 m_RightShift : 1; + /** Bitfield that stores the appropriate key state. */ + GHOST_TUns8 m_LeftAlt : 1; + /** Bitfield that stores the appropriate key state. */ + GHOST_TUns8 m_RightAlt : 1; + /** Bitfield that stores the appropriate key state. */ + GHOST_TUns8 m_LeftControl : 1; + /** Bitfield that stores the appropriate key state. */ + GHOST_TUns8 m_RightControl : 1; + /** Bitfield that stores the appropriate key state. APPLE only! */ + GHOST_TUns8 m_Command : 1; +}; + +#endif // _GHOST_MODIFIER_KEYS_H_ diff --git a/intern/ghost/intern/GHOST_Rect.cpp b/intern/ghost/intern/GHOST_Rect.cpp new file mode 100644 index 00000000000..cb600815f69 --- /dev/null +++ b/intern/ghost/intern/GHOST_Rect.cpp @@ -0,0 +1,140 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "GHOST_Rect.h" + + + +void GHOST_Rect::inset(GHOST_TInt32 i) +{ + if (i > 0) { + // Grow the rectangle + m_l -= i; + m_r += i; + m_t -= i; + m_b += i; + } + else if (i < 0) { + // Shrink the rectangle, check for insets larger than half the size + GHOST_TInt32 i2 = i * 2; + if (getWidth() > i2) { + m_l += i; + m_r -= i; + } + else { + m_l = m_l + ((m_r - m_l) / 2); + m_r = m_l; + } + if (getHeight() > i2) { + m_t += i; + m_b -= i; + } + else { + m_t = m_t + ((m_b - m_t) / 2); + m_b = m_t; + } + } +} + + +GHOST_TVisibility GHOST_Rect::getVisibility(GHOST_Rect& r) const +{ + bool lt = isInside(r.m_l, r.m_t); + bool rt = isInside(r.m_r, r.m_t); + bool lb = isInside(r.m_l, r.m_b); + bool rb = isInside(r.m_r, r.m_b); + GHOST_TVisibility v; + if (lt && rt && lb && rb) { + // All points inside, rectangle is inside this + v = GHOST_kFullyVisible; + } + else if (!(lt || rt || lb || rb)) { + // None of the points inside + // Check to see whether the rectangle is larger than this one + if ((r.m_l < m_l) && (r.m_t < m_t) && (r.m_r > m_r) && (r.m_b > m_b)) { + v = GHOST_kPartiallyVisible; + } + else { + v = GHOST_kNotVisible; + } + } + else { + // Some of the points inside, rectangle is partially inside + v = GHOST_kPartiallyVisible; + } + return v; +} + + +void GHOST_Rect::setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy) +{ + GHOST_TInt32 offset = cx - (m_l + (m_r - m_l)/2); + m_l += offset; + m_r += offset; + offset = cy - (m_t + (m_b - m_t)/2); + m_t += offset; + m_b += offset; +} + +void GHOST_Rect::setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy, GHOST_TInt32 w, GHOST_TInt32 h) +{ + long w_2, h_2; + + w_2 = w >> 1; + h_2 = h >> 1; + m_l = cx - w_2; + m_t = cy - h_2; + m_r = m_l + w; + m_b = m_t + h; +} + +bool GHOST_Rect::clip(GHOST_Rect& r) const +{ + bool clipped = false; + if (r.m_l < m_l) { + r.m_l = m_l; + clipped = true; + } + if (r.m_t < m_t) { + r.m_t = m_t; + clipped = true; + } + if (r.m_r > m_r) { + r.m_r = m_r; + clipped = true; + } + if (r.m_b > m_b) { + r.m_b = m_b; + clipped = true; + } + return clipped; +} + diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp new file mode 100644 index 00000000000..5585be62f5a --- /dev/null +++ b/intern/ghost/intern/GHOST_System.cpp @@ -0,0 +1,320 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 7, 2001 + */ + +#include "GHOST_System.h" + +#include <time.h> + +#include "GHOST_DisplayManager.h" +#include "GHOST_EventManager.h" +#include "GHOST_TimerTask.h" +#include "GHOST_TimerManager.h" +#include "GHOST_WindowManager.h" + + +GHOST_System::GHOST_System() +: m_displayManager(0), m_timerManager(0), m_windowManager(0), m_eventManager(0) +{ +} + + +GHOST_System::~GHOST_System() +{ + exit(); +} + + +GHOST_TUns64 GHOST_System::getMilliSeconds() const +{ + GHOST_TUns64 millis = ::clock(); + if (CLOCKS_PER_SEC != 1000) { + millis *= 1000; + millis /= CLOCKS_PER_SEC; + } + return millis; +} + + +GHOST_ITimerTask* GHOST_System::installTimer(GHOST_TUns64 delay, GHOST_TUns64 interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData) +{ + GHOST_TUns64 millis = getMilliSeconds(); + GHOST_TimerTask* timer = new GHOST_TimerTask(millis+delay, interval, timerProc, userData); + if (timer) { + if (m_timerManager->addTimer(timer) == GHOST_kSuccess) { + // Check to see whether we need to fire the timer right away + m_timerManager->fireTimers(millis); + } + else { + delete timer; + timer = 0; + } + } + return timer; +} + + +GHOST_TSuccess GHOST_System::removeTimer(GHOST_ITimerTask* timerTask) +{ + GHOST_TSuccess success = GHOST_kFailure; + if (timerTask) { + success = m_timerManager->removeTimer((GHOST_TimerTask*)timerTask); + } + return success; +} + + +GHOST_TSuccess GHOST_System::disposeWindow(GHOST_IWindow* window) +{ + GHOST_TSuccess success; + if (window == m_windowManager->getFullScreenWindow()) { + success = endFullScreen(); + } + else { + if (m_windowManager->getWindowFound(window)) { + success = m_windowManager->removeWindow(window); + if (success) { + delete window; + } + } + else { + success = GHOST_kFailure; + } + } + return success; +} + + +bool GHOST_System::validWindow(GHOST_IWindow* window) +{ + return m_windowManager->getWindowFound(window); +} + + +GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, + bool stereoVisual) +{ + GHOST_TSuccess success = GHOST_kFailure; + GHOST_ASSERT(m_windowManager, "GHOST_System::beginFullScreen(): invalid window manager") + if (m_displayManager) { + if (!m_windowManager->getFullScreen()) { + m_displayManager->getCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, m_preFullScreenSetting); + + //GHOST_PRINT("GHOST_System::beginFullScreen(): activating new display settings\n"); + success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, setting); + if (success == GHOST_kSuccess) { + //GHOST_PRINT("GHOST_System::beginFullScreen(): creating full-screen window\n"); + success = createFullScreenWindow((GHOST_Window**)window, stereoVisual); + if (success == GHOST_kSuccess) { + m_windowManager->beginFullScreen(*window, stereoVisual); + } + else { + m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, m_preFullScreenSetting); + } + } + } + } + if (success == GHOST_kFailure) { + GHOST_PRINT("GHOST_System::beginFullScreen(): could not enter full-screen mode\n"); + } + return success; +} + + +GHOST_TSuccess GHOST_System::endFullScreen(void) +{ + GHOST_TSuccess success = GHOST_kFailure; + GHOST_ASSERT(m_windowManager, "GHOST_System::endFullScreen(): invalid window manager") + if (m_windowManager->getFullScreen()) { + GHOST_IWindow* window = m_windowManager->getFullScreenWindow(); + //GHOST_PRINT("GHOST_System::endFullScreen(): leaving window manager full-screen mode\n"); + success = m_windowManager->endFullScreen(); + GHOST_ASSERT(m_displayManager, "GHOST_System::endFullScreen(): invalid display manager") + //GHOST_PRINT("GHOST_System::endFullScreen(): leaving full-screen mode\n"); + success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, m_preFullScreenSetting); + } + else { + success = GHOST_kFailure; + } + return success; +} + + +bool GHOST_System::getFullScreen(void) +{ + bool fullScreen; + if (m_windowManager) { + fullScreen = m_windowManager->getFullScreen(); + } + else { + fullScreen = false; + } + return fullScreen; +} + + +bool GHOST_System::dispatchEvents() +{ + bool handled; + if (m_eventManager) { + handled = m_eventManager->dispatchEvents(); + } + else { + handled = false; + } + + m_timerManager->fireTimers(getMilliSeconds()); + return handled; +} + + +GHOST_TSuccess GHOST_System::addEventConsumer(GHOST_IEventConsumer* consumer) +{ + GHOST_TSuccess success; + if (m_eventManager) { + success = m_eventManager->addConsumer(consumer); + } + else { + success = GHOST_kFailure; + } + return success; +} + + +GHOST_TSuccess GHOST_System::pushEvent(GHOST_IEvent* event) +{ + GHOST_TSuccess success; + if (m_eventManager) { + success = m_eventManager->pushEvent(event); + } + else { + success = GHOST_kFailure; + } + return success; +} + + +GHOST_TSuccess GHOST_System::getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const +{ + GHOST_ModifierKeys keys; + // Get the state of all modifier keys + GHOST_TSuccess success = getModifierKeys(keys); + if (success) { + // Isolate the state of the key requested + isDown = keys.get(mask); + } + return success; +} + + +GHOST_TSuccess GHOST_System::getButtonState(GHOST_TButtonMask mask, bool& isDown) const +{ + GHOST_Buttons buttons; + // Get the state of all mouse buttons + GHOST_TSuccess success = getButtons(buttons); + if (success) { + // Isolate the state of the mouse button requested + isDown = buttons.get(mask); + } + return success; +} + + +GHOST_TSuccess GHOST_System::init() +{ + m_timerManager = new GHOST_TimerManager (); + m_windowManager = new GHOST_WindowManager (); + m_eventManager = new GHOST_EventManager (); +#ifdef GHOST_DEBUG + if (m_eventManager) { + //m_eventManager->addConsumer(&m_eventPrinter); + } +#endif // GHOST_DEBUG + + if (m_timerManager && m_windowManager && m_eventManager) { + return GHOST_kSuccess; + } else { + return GHOST_kFailure; + } +} + + +GHOST_TSuccess GHOST_System::exit() +{ + if (getFullScreen()) { + endFullScreen(); + } + if (m_displayManager) { + delete m_displayManager; + m_displayManager = 0; + } + if (m_windowManager) { + delete m_windowManager; + m_windowManager = 0; + } + if (m_timerManager) { + delete m_timerManager; + m_timerManager = 0; + } + if (m_eventManager) { + delete m_eventManager; + m_eventManager = 0; + } + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window** window, bool stereoVisual) +{ + GHOST_TSuccess success; + GHOST_ASSERT(m_displayManager, "GHOST_System::createFullScreenWindow(): invalid display manager") + GHOST_DisplaySetting settings; + + success = m_displayManager->getCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, settings); + if (success) { + //GHOST_PRINT("GHOST_System::createFullScreenWindow(): creating full-screen window\n"); + *window = (GHOST_Window*)createWindow( + STR_String (""), + 0, 0, settings.xPixels, settings.yPixels, + GHOST_kWindowStateFullScreen, + GHOST_kDrawingContextTypeOpenGL, + stereoVisual); + success = *window == 0 ? GHOST_kFailure : GHOST_kSuccess; + } + return success; +} diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h new file mode 100644 index 00000000000..52d90cab7a7 --- /dev/null +++ b/intern/ghost/intern/GHOST_System.h @@ -0,0 +1,328 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 7, 2001 + */ + +#ifndef _GHOST_SYSTEM_H_ +#define _GHOST_SYSTEM_H_ + +#include "GHOST_ISystem.h" + +#include "GHOST_Debug.h" +#include "GHOST_Buttons.h" +#include "GHOST_ModifierKeys.h" +#include "GHOST_EventManager.h" +#ifdef GHOST_DEBUG +#include "GHOST_EventPrinter.h" +#endif // GHOST_DEBUG + +class GHOST_DisplayManager; +class GHOST_Event; +class GHOST_TimerManager; +class GHOST_Window; +class GHOST_WindowManager; + +/** + * Implementation of platform independent functionality of the GHOST_ISystem interface. + * GHOST_System is an abstract base class because not all methods of GHOST_ISystem are implemented. + * There should be only one system class in an application. + * Therefore, the routines to create and dispose the system are static. + * Provides: + * 1. Time(r) management. + * 2. Display/window management (windows are only created on the main display for now). + * 3. Event management. + * 4. Cursor shape management (no custom cursors for now). + * 5. Access to the state of the mouse buttons and the keyboard. + * @see GHOST_ISystem. + * @author Maarten Gribnau + * @date May 7, 2001 + */ + +class GHOST_System : public GHOST_ISystem +{ +protected: + /** + * Constructor. + * Protected default constructor to force use of static createSystem member. + */ + GHOST_System(); + + /** + * Destructor. + * Protected default constructor to force use of static dispose member. + */ + virtual ~GHOST_System(); + +public: + /*************************************************************************************** + ** Time(r) functionality + ***************************************************************************************/ + + /** + * Returns the system time. + * Returns the number of milliseconds since the start of the system process. + * Based on ANSI clock() routine. + * @return The number of milliseconds. + */ + virtual GHOST_TUns64 getMilliSeconds() const; + + /** + * Installs a timer. + * Note that, on most operating systems, messages need to be processed in order + * for the timer callbacks to be invoked. + * @param delay The time to wait for the first call to the timerProc (in milliseconds) + * @param interval The interval between calls to the timerProc + * @param timerProc The callback invoked when the interval expires, + * @param userData Placeholder for user data. + * @return A timer task (0 if timer task installation failed). + */ + virtual GHOST_ITimerTask* installTimer(GHOST_TUns64 delay, GHOST_TUns64 interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData = 0); + + /** + * Removes a timer. + * @param timerTask Timer task to be removed. + * @return Indication of success. + */ + virtual GHOST_TSuccess removeTimer(GHOST_ITimerTask* timerTask); + + /*************************************************************************************** + ** Display/window management functionality + ***************************************************************************************/ + + /** + * Inherited from GHOST_ISystem but left pure virtual + * + * virtual GHOST_TUns8 getNumDisplays() const = 0; + * virtual void getMainDisplayDimensions(...) const = 0; + * virtual GHOST_IWindow* createWindow(..) + */ + + /** + * Dispose a window. + * @param window Pointer to the window to be disposed. + * @return Indication of success. + */ + virtual GHOST_TSuccess disposeWindow(GHOST_IWindow* window); + + /** + * Returns whether a window is valid. + * @param window Pointer to the window to be checked. + * @return Indication of validity. + */ + virtual bool validWindow(GHOST_IWindow* window); + + /** + * Begins full screen mode. + * @param setting The new setting of the display. + * @param window Window displayed in full screen. + * @param stereoVisual Stereo visual for quad buffered stereo. + * This window is invalid after full screen has been ended. + * @return Indication of success. + */ + virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, + const bool stereoVisual); + + /** + * Ends full screen mode. + * @return Indication of success. + */ + virtual GHOST_TSuccess endFullScreen(void); + + /** + * Returns current full screen mode status. + * @return The current status. + */ + virtual bool getFullScreen(void); + + + /*************************************************************************************** + ** Event management functionality + ***************************************************************************************/ + + /** + * Inherited from GHOST_ISystem but left pure virtual + * + * virtual bool processEvents(bool waitForEvent) = 0; + */ + + + + /** + * Dispatches all the events on the stack. + * The event stack will be empty afterwards. + * @return Indication as to whether any of the consumers handled the events. + */ + virtual bool dispatchEvents(); + + /** + * Adds the given event consumer to our list. + * @param consumer The event consumer to add. + * @return Indication of success. + */ + virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer* consumer); + + /*************************************************************************************** + ** Cursor management functionality + ***************************************************************************************/ + + /** Inherited from GHOST_ISystem but left pure virtual + * GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const = 0; + * GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) + */ + + /*************************************************************************************** + ** Access to mouse button and keyboard states. + ***************************************************************************************/ + + /** + * Returns the state of a modifier key (ouside the message queue). + * @param mask The modifier key state to retrieve. + * @param isDown The state of a modifier key (true == pressed). + * @return Indication of success. + */ + virtual GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const; + + /** + * Returns the state of a mouse button (ouside the message queue). + * @param mask The button state to retrieve. + * @param isDown Button state. + * @return Indication of success. + */ + virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const; + + /*************************************************************************************** + ** Other (internal) functionality. + ***************************************************************************************/ + + /** + * Pushes an event on the stack. + * To dispatch it, call dispatchEvent() or dispatchEvents(). + * Do not delete the event! + * @param event The event to push on the stack. + */ + virtual GHOST_TSuccess pushEvent(GHOST_IEvent* event); + + /** + * Returns the timer manager. + * @return The timer manager. + */ + inline virtual GHOST_TimerManager* getTimerManager() const; + + /** + * Returns a pointer to our event manager. + * @return A pointer to our event manager. + */ + virtual inline GHOST_EventManager* getEventManager() const; + + /** + * Returns a pointer to our window manager. + * @return A pointer to our window manager. + */ + virtual inline GHOST_WindowManager* getWindowManager() const; + + /** + * Returns the state of all modifier keys. + * @param keys The state of all modifier keys (true == pressed). + * @return Indication of success. + */ + virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const = 0; + + /** + * Returns the state of the mouse buttons (ouside the message queue). + * @param buttons The state of the buttons. + * @return Indication of success. + */ + virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const = 0; + +protected: + /** + * Initialize the system. + * @return Indication of success. + */ + virtual GHOST_TSuccess init(); + + /** + * Shut the system down. + * @return Indication of success. + */ + virtual GHOST_TSuccess exit(); + + /** + * Creates a fullscreen window. + * @param window The window created. + * @return Indication of success. + */ + virtual GHOST_TSuccess createFullScreenWindow(GHOST_Window** window, + const bool stereoVisual); + + /** The display manager (platform dependant). */ + GHOST_DisplayManager* m_displayManager; + + /** The timer manager. */ + GHOST_TimerManager* m_timerManager; + + /** The window manager. */ + GHOST_WindowManager* m_windowManager; + + /** The event manager. */ + GHOST_EventManager* m_eventManager; + + /** Prints all the events. */ +#ifdef GHOST_DEBUG + GHOST_EventPrinter m_eventPrinter; +#endif // GHOST_DEBUG + + /** Settings of the display before the display went fullscreen. */ + GHOST_DisplaySetting m_preFullScreenSetting; +}; + +inline GHOST_TimerManager* GHOST_System::getTimerManager() const +{ + return m_timerManager; +} + +inline GHOST_EventManager* GHOST_System::getEventManager() const +{ + return m_eventManager; +} + +inline GHOST_WindowManager* GHOST_System::getWindowManager() const +{ + return m_windowManager; +} + +#endif // _GHOST_SYSTEM_H_ diff --git a/intern/ghost/intern/GHOST_SystemCarbon.cpp b/intern/ghost/intern/GHOST_SystemCarbon.cpp new file mode 100644 index 00000000000..baba1bb4e6c --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemCarbon.cpp @@ -0,0 +1,735 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 7, 2001 + */ + +#include "GHOST_SystemCarbon.h" + +#include "GHOST_DisplayManagerCarbon.h" +#include "GHOST_EventKey.h" +#include "GHOST_EventButton.h" +#include "GHOST_EventCursor.h" +#include "GHOST_TimerManager.h" +#include "GHOST_TimerTask.h" +#include "GHOST_WindowManager.h" +#include "GHOST_WindowCarbon.h" + +#define GHOST_KEY_SWITCH(mac, ghost) { case (mac): ghostKey = (ghost); break; } + +const EventTypeSpec kEvents[] = +{ + { kEventClassAppleEvent, kEventAppleEvent }, + +/* + { kEventClassApplication, kEventAppActivated }, + { kEventClassApplication, kEventAppDeactivated }, +*/ + + { kEventClassKeyboard, kEventRawKeyDown }, + { kEventClassKeyboard, kEventRawKeyRepeat }, + { kEventClassKeyboard, kEventRawKeyUp }, + { kEventClassKeyboard, kEventRawKeyModifiersChanged }, + + { kEventClassMouse, kEventMouseDown }, + { kEventClassMouse, kEventMouseUp }, + { kEventClassMouse, kEventMouseMoved }, + { kEventClassMouse, kEventMouseDragged }, + + { kEventClassWindow, kEventWindowClose }, + { kEventClassWindow, kEventWindowActivated }, + { kEventClassWindow, kEventWindowDeactivated }, + { kEventClassWindow, kEventWindowUpdate }, + { kEventClassWindow, kEventWindowBoundsChanged } +}; + +static GHOST_TButtonMask convertButton(EventMouseButton button) +{ + switch (button) { + case kEventMouseButtonPrimary: + return GHOST_kButtonMaskLeft; + case kEventMouseButtonSecondary: + return GHOST_kButtonMaskRight; + case kEventMouseButtonTertiary: + default: + return GHOST_kButtonMaskMiddle; + } +} + +static GHOST_TKey convertKey(int rawCode) +{ + /* This bit of magic converts the rawCode into a virtual + * Mac key based on the current keyboard mapping, but + * without regard to the modifiers (so we don't get 'a' + * and 'A' for example. + */ + UInt32 dummy= 0; + Handle transData = (Handle) GetScriptManagerVariable(smKCHRCache); + char vk = KeyTranslate(transData, rawCode, &dummy); + + /* Map numpad based on rawcodes first, otherwise they + * look like non-numpad events. + */ + switch (rawCode) { + case 82: return GHOST_kKeyNumpad0; + case 83: return GHOST_kKeyNumpad1; + case 84: return GHOST_kKeyNumpad2; + case 85: return GHOST_kKeyNumpad3; + case 86: return GHOST_kKeyNumpad4; + case 87: return GHOST_kKeyNumpad5; + case 88: return GHOST_kKeyNumpad6; + case 89: return GHOST_kKeyNumpad7; + case 91: return GHOST_kKeyNumpad8; + case 92: return GHOST_kKeyNumpad9; + case 65: return GHOST_kKeyNumpadPeriod; + case 76: return GHOST_kKeyNumpadEnter; + case 69: return GHOST_kKeyNumpadPlus; + case 78: return GHOST_kKeyNumpadMinus; + case 67: return GHOST_kKeyNumpadAsterisk; + case 75: return GHOST_kKeyNumpadSlash; + } + + if ((vk >= 'a') && (vk <= 'z')) { + return (GHOST_TKey) (vk - 'a' + GHOST_kKeyA); + } else if ((vk >= '0') && (vk <= '9')) { + return (GHOST_TKey) (vk - '0' + GHOST_kKey0); + } else if (vk==16) { + switch (rawCode) { + case 122: return GHOST_kKeyF1; + case 120: return GHOST_kKeyF2; + case 99: return GHOST_kKeyF3; + case 118: return GHOST_kKeyF4; + case 96: return GHOST_kKeyF5; + case 97: return GHOST_kKeyF6; + case 98: return GHOST_kKeyF7; + case 100: return GHOST_kKeyF8; + case 101: return GHOST_kKeyF9; + case 109: return GHOST_kKeyF10; + case 103: return GHOST_kKeyF11; + case 111: return GHOST_kKeyF12; // Never get, is used for ejecting the CD! + } + } else { + switch (vk) { + case kUpArrowCharCode: return GHOST_kKeyUpArrow; + case kDownArrowCharCode: return GHOST_kKeyDownArrow; + case kLeftArrowCharCode: return GHOST_kKeyLeftArrow; + case kRightArrowCharCode: return GHOST_kKeyRightArrow; + + case kReturnCharCode: return GHOST_kKeyEnter; + case kBackspaceCharCode: return GHOST_kKeyBackSpace; + case kDeleteCharCode: return GHOST_kKeyDelete; + case kEscapeCharCode: return GHOST_kKeyEsc; + case kTabCharCode: return GHOST_kKeyTab; + case kSpaceCharCode: return GHOST_kKeySpace; + + case kHomeCharCode: return GHOST_kKeyHome; + case kEndCharCode: return GHOST_kKeyEnd; + case kPageUpCharCode: return GHOST_kKeyUpPage; + case kPageDownCharCode: return GHOST_kKeyDownPage; + + case '-': return GHOST_kKeyMinus; + case '=': return GHOST_kKeyEqual; + case ',': return GHOST_kKeyComma; + case '.': return GHOST_kKeyPeriod; + case '/': return GHOST_kKeySlash; + case ';': return GHOST_kKeySemicolon; + case '\'': return GHOST_kKeyQuote; + case '\\': return GHOST_kKeyBackslash; + case '[': return GHOST_kKeyLeftBracket; + case ']': return GHOST_kKeyRightBracket; + case '`': return GHOST_kKeyAccentGrave; + } + } + + printf("GHOST: unknown key: %d %d\n", vk, rawCode); + + return GHOST_kKeyUnknown; +} + +/***/ + +GHOST_SystemCarbon::GHOST_SystemCarbon() : + m_modifierMask(0) +{ + m_displayManager = new GHOST_DisplayManagerCarbon (); + GHOST_ASSERT(m_displayManager, "GHOST_SystemCarbon::GHOST_SystemCarbon(): m_displayManager==0\n"); + m_displayManager->initialize(); + + UnsignedWide micros; + ::Microseconds(µs); + UInt64 millis; + m_start_time = UnsignedWideToUInt64(micros)/1000; +} + +GHOST_SystemCarbon::~GHOST_SystemCarbon() +{ +} + + +GHOST_TUns64 GHOST_SystemCarbon::getMilliSeconds() const +{ + UnsignedWide micros; + ::Microseconds(µs); + UInt64 millis; + millis = UnsignedWideToUInt64(micros); + return (millis / 1000) - m_start_time; +} + + +GHOST_TUns8 GHOST_SystemCarbon::getNumDisplays() const +{ + // We do not support multiple monitors at the moment + return 1; +} + + +void GHOST_SystemCarbon::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const +{ + BitMap screenBits; + Rect bnds = GetQDGlobalsScreenBits(&screenBits)->bounds; + width = bnds.right - bnds.left; + height = bnds.bottom - bnds.top; +} + + +GHOST_IWindow* GHOST_SystemCarbon::createWindow( + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + bool stereoVisual +) +{ + GHOST_IWindow* window = 0; + window = new GHOST_WindowCarbon (title, left, top, width, height, state, type); + if (window) { + if (window->getValid()) { + // Store the pointer to the window + GHOST_ASSERT(m_windowManager, "m_windowManager not initialized"); + m_windowManager->addWindow(window); + m_windowManager->setActiveWindow(window); + pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window)); + } + else { + GHOST_PRINT("GHOST_SystemCarbon::createWindow(): window invalid\n"); + delete window; + window = 0; + } + } + else { + GHOST_PRINT("GHOST_SystemCarbon::createWindow(): could not create window\n"); + } + return window; +} + + +bool GHOST_SystemCarbon::processEvents(bool waitForEvent) +{ + bool anyProcessed = false; + EventRef event; + + do { + GHOST_TimerManager* timerMgr = getTimerManager(); + + if (waitForEvent) { + GHOST_TUns64 curtime = getMilliSeconds(); + GHOST_TUns64 next = timerMgr->nextFireTime(); + double timeOut; + + if (next == GHOST_kFireTimeNever) { + timeOut = kEventDurationForever; + } else { + if (next<=curtime) + timeOut = 0.0; + else + timeOut = (double) (next - getMilliSeconds())/1000.0; + } + + ::ReceiveNextEvent(0, NULL, timeOut, false, &event); + } + + if (timerMgr->fireTimers(getMilliSeconds())) { + anyProcessed = true; + } + + if (getFullScreen()) { + // Check if the full-screen window is dirty + GHOST_IWindow* window = m_windowManager->getFullScreenWindow(); + if (((GHOST_WindowCarbon*)window)->getFullScreenDirty()) { + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) ); + anyProcessed = true; + } + } + + while (::ReceiveNextEvent(0, NULL, 0, true, &event)==noErr) { + OSStatus status= ::SendEventToEventTarget(event, ::GetEventDispatcherTarget()); + if (status==noErr) { + anyProcessed = true; + } else { + UInt32 i= ::GetEventClass(event); + + /* Ignore 'cgs ' class, no documentation on what they + * are, but we get a lot of them + */ + if (i!='cgs ') { + //printf("Missed - Class: '%.4s', Kind: %d\n", &i, ::GetEventKind(event)); + } + } + ::ReleaseEvent(event); + } + } while (waitForEvent && !anyProcessed); + + return anyProcessed; +} + + +GHOST_TSuccess GHOST_SystemCarbon::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const +{ + Point mouseLoc; + // Get the position of the mouse in the active port + ::GetGlobalMouse(&mouseLoc); + // Convert the coordinates to screen coordinates + x = (GHOST_TInt32)mouseLoc.h; + y = (GHOST_TInt32)mouseLoc.v; + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_SystemCarbon::setCursorPosition(GHOST_TInt32 /*x*/, GHOST_TInt32 /*y*/) const +{ + // Not supported in Carbon! + return GHOST_kFailure; +} + + +GHOST_TSuccess GHOST_SystemCarbon::getModifierKeys(GHOST_ModifierKeys& keys) const +{ + UInt32 modifiers = ::GetCurrentKeyModifiers(); + + keys.set(GHOST_kModifierKeyCommand, (modifiers & cmdKey) ? true : false); + keys.set(GHOST_kModifierKeyLeftAlt, (modifiers & optionKey) ? true : false); + keys.set(GHOST_kModifierKeyLeftShift, (modifiers & shiftKey) ? true : false); + keys.set(GHOST_kModifierKeyLeftControl, (modifiers & controlKey) ? true : false); + + return GHOST_kSuccess; +} + + /* XXX, incorrect for multibutton mice */ +GHOST_TSuccess GHOST_SystemCarbon::getButtons(GHOST_Buttons& buttons) const +{ + Boolean theOnlyButtonIsDown = ::Button(); + buttons.clear(); + buttons.set(GHOST_kButtonMaskLeft, theOnlyButtonIsDown); + return GHOST_kSuccess; +} + +static bool g_hasFirstFile = false; +static char g_firstFileBuf[512]; + +extern "C" int GHOST_HACK_getFirstFile(char buf[512]) { + if (g_hasFirstFile) { + strcpy(buf, g_firstFileBuf); + return 1; + } else { + return 0; + } +} + +OSErr GHOST_SystemCarbon::sAEHandlerLaunch(const AppleEvent *event, AppleEvent *reply, SInt32 refCon) +{ + GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon; + + return noErr; +} + +OSErr GHOST_SystemCarbon::sAEHandlerOpenDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon) +{ + GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon; + AEDescList docs; + SInt32 ndocs; + OSErr err; + + err = AEGetParamDesc(event, keyDirectObject, typeAEList, &docs); + if (err != noErr) return err; + + err = AECountItems(&docs, &ndocs); + if (err==noErr) { + int i; + + for (i=0; i<ndocs; i++) { + FSSpec fss; + AEKeyword kwd; + DescType actType; + Size actSize; + + err = AEGetNthPtr(&docs, i+1, typeFSS, &kwd, &actType, &fss, sizeof(fss), &actSize); + if (err!=noErr) + break; + + if (i==0) { + FSRef fsref; + + if (FSpMakeFSRef(&fss, &fsref)!=noErr) + break; + if (FSRefMakePath(&fsref, (UInt8*) g_firstFileBuf, sizeof(g_firstFileBuf))!=noErr) + break; + + g_hasFirstFile = true; + } + } + } + + AEDisposeDesc(&docs); + + return err; +} + +OSErr GHOST_SystemCarbon::sAEHandlerPrintDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon) +{ + GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon; + + return noErr; +} + +OSErr GHOST_SystemCarbon::sAEHandlerQuit(const AppleEvent *event, AppleEvent *reply, SInt32 refCon) +{ + GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon; + + sys->pushEvent( new GHOST_Event(sys->getMilliSeconds(), GHOST_kEventQuit, NULL) ); + + return noErr; +} + + +GHOST_TSuccess GHOST_SystemCarbon::init() +{ + GHOST_TSuccess success = GHOST_System::init(); + if (success) { + /* + * Initialize the cursor to the standard arrow shape (so that we can change it later on). + * This initializes the cursor's visibility counter to 0. + */ + ::InitCursor(); + + MenuRef windMenu; + ::CreateStandardWindowMenu(0, &windMenu); + ::InsertMenu(windMenu, 0); + ::DrawMenuBar(); + + ::InstallApplicationEventHandler(sEventHandlerProc, GetEventTypeCount(kEvents), kEvents, this, &m_handler); + + ::AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, sAEHandlerLaunch, (SInt32) this, false); + ::AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, sAEHandlerOpenDocs, (SInt32) this, false); + ::AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, sAEHandlerPrintDocs, (SInt32) this, false); + ::AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, sAEHandlerQuit, (SInt32) this, false); + } + return success; +} + + +GHOST_TSuccess GHOST_SystemCarbon::exit() +{ + return GHOST_System::exit(); +} + + +OSStatus GHOST_SystemCarbon::handleWindowEvent(EventRef event) +{ + GHOST_WindowCarbon *window; + + if (!getFullScreen()) { + WindowRef windowref; + ::GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &windowref); + window = (GHOST_WindowCarbon*) ::GetWRefCon(windowref); + + if (validWindow(window)) { + switch(::GetEventKind(event)) + { + case kEventWindowClose: + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) ); + break; + case kEventWindowActivated: + m_windowManager->setActiveWindow(window); + window->loadCursor(window->getCursorVisibility(), window->getCursorShape()); + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) ); + break; + case kEventWindowDeactivated: + m_windowManager->setWindowInactive(window); + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) ); + break; + case kEventWindowUpdate: + //if (getFullScreen()) GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen update event\n"); + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) ); + break; + case kEventWindowBoundsChanged: + window->updateDrawingContext(); + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) ); + break; + } + } + } + //else { + //window = (GHOST_WindowCarbon*) m_windowManager->getFullScreenWindow(); + //GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen window event, " << window << "\n"); + //::RemoveEventFromQueue(::GetMainEventQueue(), event); + //} + + return noErr; +} + +OSStatus GHOST_SystemCarbon::handleMouseEvent(EventRef event) +{ + GHOST_IWindow* window = m_windowManager->getActiveWindow(); + UInt32 kind = ::GetEventKind(event); + + switch (kind) + { + case kEventMouseDown: + case kEventMouseUp: + // Handle Mac application responsibilities + if ((kind == kEventMouseDown) && handleMouseDown(event)) { + ; + } else { + GHOST_TEventType type = (kind == kEventMouseDown) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp; + EventMouseButton button; + + /* Window still gets mouse up after command-H */ + if (window) { + ::GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button); + pushEvent(new GHOST_EventButton(getMilliSeconds(), type, window, convertButton(button))); + } + } + break; + + case kEventMouseMoved: + case kEventMouseDragged: + Point mousePos; + if (window) { + ::GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mousePos); + pushEvent(new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, mousePos.h, mousePos.v)); + } + break; + } + + return noErr; +} + + +OSStatus GHOST_SystemCarbon::handleKeyEvent(EventRef event) +{ + GHOST_IWindow* window = m_windowManager->getActiveWindow(); + UInt32 kind = ::GetEventKind(event); + UInt32 modifiers; + UInt32 rawCode; + GHOST_TKey key; + char ascii; + + /* Can happen, very rarely - seems to only be when command-H makes + * the window go away and we still get an HKey up. + */ + if (!window) { + ::GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &rawCode); + key = convertKey(rawCode); + return noErr; + } + + switch (kind) { + case kEventRawKeyDown: + case kEventRawKeyRepeat: + case kEventRawKeyUp: + ::GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &rawCode); + ::GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &ascii); + key = convertKey(rawCode); + if (key!=GHOST_kKeyUnknown) { + GHOST_TEventType type; + if (kind == kEventRawKeyDown) { + type = GHOST_kEventKeyDown; + } else if (kind == kEventRawKeyRepeat) { + type = GHOST_kEventKeyDown; /* XXX, fixme */ + } else { + type = GHOST_kEventKeyUp; + } + pushEvent( new GHOST_EventKey( getMilliSeconds(), type, window, key, ascii) ); + } + break; + + case kEventRawKeyModifiersChanged: + /* ugh */ + ::GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); + if ((modifiers & shiftKey) != (m_modifierMask & shiftKey)) { + pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & shiftKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) ); + } + if ((modifiers & controlKey) != (m_modifierMask & controlKey)) { + pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & controlKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) ); + } + if ((modifiers & optionKey) != (m_modifierMask & optionKey)) { + pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & optionKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) ); + } + if ((modifiers & cmdKey) != (m_modifierMask & cmdKey)) { + pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & cmdKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) ); + } + + m_modifierMask = modifiers; + break; + } + + return noErr; +} + + +bool GHOST_SystemCarbon::handleMouseDown(EventRef event) +{ + WindowPtr window; + short part; + BitMap screenBits; + bool handled = true; + GHOST_IWindow* ghostWindow; + Point mousePos = {0 , 0}; + + ::GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mousePos); + + part = ::FindWindow(mousePos, &window); + ghostWindow = (GHOST_IWindow*) ::GetWRefCon(window); + GHOST_ASSERT(validWindow(ghostWindow), "GHOST_SystemCarbon::handleMouseEvent: invalid window"); + + switch (part) { + case inMenuBar: + handleMenuCommand(::MenuSelect(mousePos)); + break; + + case inDrag: + ::DragWindow(window, mousePos, &GetQDGlobalsScreenBits(&screenBits)->bounds); + break; + + case inContent: + if (window != ::FrontWindow()) { + ::SelectWindow(window); + } else { + handled = false; + } + break; + + case inGoAway: + GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0"); + if (::TrackGoAway(window, mousePos)) + { + // todo: add option-close, because itÕs in the HIG + // if (event.modifiers & optionKey) { + // Close the clean documents, others will be confirmed one by one. + //} + // else { + pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, ghostWindow)); + //} + } + break; + + case inGrow: + GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0"); + ::ResizeWindow(window, mousePos, NULL, NULL); + break; + + case inZoomIn: + case inZoomOut: + GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0"); + if (::TrackBox(window, mousePos, part)) { + ::ZoomWindow(window, part, true); + } + break; + + default: + handled = false; + break; + } + + return handled; +} + + +bool GHOST_SystemCarbon::handleMenuCommand(GHOST_TInt32 menuResult) +{ + short menuID; + short menuItem; + UInt32 command; + bool handled; + OSErr err; + + menuID = HiWord(menuResult); + menuItem = LoWord(menuResult); + + err = ::GetMenuItemCommandID(::GetMenuHandle(menuID), menuItem, &command); + + handled = false; + + if (err || command == 0) { + } + else { + switch(command) { + } + } + + ::HiliteMenu(0); + return handled; +} + +OSStatus GHOST_SystemCarbon::sEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData) +{ + GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) userData; + OSStatus err = eventNotHandledErr; + + switch (::GetEventClass(event)) + { + case kEventClassAppleEvent: + EventRecord eventrec; + if (ConvertEventRefToEventRecord(event, &eventrec)) { + err = AEProcessAppleEvent(&eventrec); + } + break; + case kEventClassMouse: + err = sys->handleMouseEvent(event); + break; + case kEventClassWindow: + err = sys->handleWindowEvent(event); + break; + case kEventClassKeyboard: + err = sys->handleKeyEvent(event); + break; + } + + return err; +} diff --git a/intern/ghost/intern/GHOST_SystemCarbon.h b/intern/ghost/intern/GHOST_SystemCarbon.h new file mode 100644 index 00000000000..17c09e8e91f --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemCarbon.h @@ -0,0 +1,251 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +#ifndef _GHOST_SYSTEM_CARBON_H_ +#define _GHOST_SYSTEM_CARBON_H_ + +#ifndef __APPLE__ +#error Apple OSX only! +#endif // __APPLE__ + +#include <Carbon/Carbon.h> + +#include "GHOST_System.h" + + +class GHOST_EventCursor; +class GHOST_EventKey; +class GHOST_EventWindow; + +/** + * OSX/Carbon Implementation of GHOST_System class. + * @see GHOST_System. + * @author Maarten Gribnau + * @date May 21, 2001 + */ +class GHOST_SystemCarbon : public GHOST_System { +public: + /** + * Constructor. + */ + GHOST_SystemCarbon::GHOST_SystemCarbon(); + + /** + * Destructor. + */ + GHOST_SystemCarbon::~GHOST_SystemCarbon(); + + /*************************************************************************************** + ** Time(r) functionality + ***************************************************************************************/ + + /** + * Returns the system time. + * Returns the number of milliseconds since the start of the system process. + * Based on ANSI clock() routine. + * @return The number of milliseconds. + */ + virtual GHOST_TUns64 getMilliSeconds() const; + + /*************************************************************************************** + ** Display/window management functionality + ***************************************************************************************/ + + /** + * Returns the number of displays on this system. + * @return The number of displays. + */ + virtual GHOST_TUns8 getNumDisplays() const; + + /** + * Returns the dimensions of the main display on this system. + * @return The dimension of the main display. + */ + virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const; + + /** + * Create a new window. + * The new window is added to the list of windows managed. + * Never explicitly delete the window, use disposeWindow() instead. + * @param title The name of the window (displayed in the title bar of the window if the OS supports it). + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param height The height the window. + * @param state The state of the window when opened. + * @param type The type of drawing context installed in this window. + * @return The new window (or 0 if creation failed). + */ + virtual GHOST_IWindow* createWindow( + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + const bool stereoVisual + ); + + /*************************************************************************************** + ** Event management functionality + ***************************************************************************************/ + + /** + * Gets events from the system and stores them in the queue. + * @param waitForEvent Flag to wait for an event (or return immediately). + * @return Indication of the presence of events. + */ + virtual bool processEvents(bool waitForEvent); + + /*************************************************************************************** + ** Cursor management functionality + ***************************************************************************************/ + + /** + * Returns the current location of the cursor (location in screen coordinates) + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. + */ + virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const; + + /** + * Updates the location of the cursor (location in screen coordinates). + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const; + + /*************************************************************************************** + ** Access to mouse button and keyboard states. + ***************************************************************************************/ + + /** + * Returns the state of all modifier keys. + * @param keys The state of all modifier keys (true == pressed). + * @return Indication of success. + */ + virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const; + + /** + * Returns the state of the mouse buttons (ouside the message queue). + * @param buttons The state of the buttons. + * @return Indication of success. + */ + virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const; + +protected: + /** + * Initializes the system. + * For now, it justs registers the window class (WNDCLASS). + * @return A success value. + */ + virtual GHOST_TSuccess init(); + + /** + * Closes the system down. + * @return A success value. + */ + virtual GHOST_TSuccess exit(); + + /** + * Handles a mouse event. + * @param event A Mac event. + * @return Indication whether the event was handled. + */ + OSStatus handleMouseEvent(EventRef event); + + /** + * Handles a key event. + * @param event A Mac event. + * @return Indication whether the event was handled. + */ + OSStatus handleKeyEvent(EventRef event); + + /** + * Handles a window event. + * @param event A Mac event. + * @return Indication whether the event was handled. + */ + OSStatus handleWindowEvent(EventRef event); + + /** + * Handles all basic Mac application stuff for a mouse down event. + * @param event A Mac event. + * @return Indication whether the event was handled. + */ + bool handleMouseDown(EventRef event); + + /** + * Handles a Mac menu command. + * @param menuResult A Mac menu/item identifier. + * @return Indication whether the event was handled. + */ + bool handleMenuCommand(GHOST_TInt32 menuResult); + + /** + * Callback for Carbon when it has events. + */ + static OSStatus sEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData); + + /** Apple Event Handlers */ + static OSErr sAEHandlerLaunch(const AppleEvent *event, AppleEvent *reply, SInt32 refCon); + static OSErr sAEHandlerOpenDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon); + static OSErr sAEHandlerPrintDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon); + static OSErr sAEHandlerQuit(const AppleEvent *event, AppleEvent *reply, SInt32 refCon); + + /** + * Callback for Mac Timer tasks that expire. + * @param tmTask Pointer to the timer task that expired. + */ + //static void s_timerCallback(TMTaskPtr tmTask); + + /** Event handler reference. */ + EventHandlerRef m_handler; + + /** Start time at initialization. */ + GHOST_TUns64 m_start_time; + + /** State of the modifiers. */ + UInt32 m_modifierMask; +}; + +#endif // _GHOST_SYSTEM_CARBON_H_ diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h new file mode 100644 index 00000000000..099706b7e82 --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -0,0 +1,65 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 22, 2001 + */ + +#ifndef _GHOST_SYSTEM_CARBON_H_ +#define _GHOST_SYSTEM_CARBON_H_ + +#ifndef __APPLE__ +#error Apple OSX only! +#endif // __APPLE__ + +#include "GHOST_System.h" +#include "GHOST_Keys.h" + +#include <Carbon/Carbon.h> + +class GHOST_EventCursor; +class GHOST_EventKey; +class GHOST_EventWindow; + +/** + * OSX/Cocoa Implementation of GHOST_System class. + * @see GHOST_System. + * @author Maarten Gribnau + * @date May 21, 2001 + */ +class GHOST_SystemCarbon : public GHOST_System { +}; + +#endif // _GHOST_SYSTEM_CARBON_H_ diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp new file mode 100644 index 00000000000..6dc00bd1847 --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -0,0 +1,817 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 7, 2001 + */ + +#include "GHOST_SystemWin32.h" + + +#include "GHOST_Debug.h" +#include "GHOST_DisplayManagerWin32.h" +#include "GHOST_EventButton.h" +#include "GHOST_EventCursor.h" +#include "GHOST_EventKey.h" +#include "GHOST_TimerTask.h" +#include "GHOST_TimerManager.h" +#include "GHOST_WindowManager.h" +#include "GHOST_WindowWin32.h" + +// Key code values not found in winuser.h +#ifndef VK_MINUS +#define VK_MINUS 0xBD +#endif // VK_MINUS +#ifndef VK_SEMICOLON +#define VK_SEMICOLON 0xBA +#endif // VK_SEMICOLON +#ifndef VK_PERIOD +#define VK_PERIOD 0xBE +#endif // VK_PERIOD +#ifndef VK_COMMA +#define VK_COMMA 0xBC +#endif // VK_COMMA +#ifndef VK_QUOTE +#define VK_QUOTE 0xDE +#endif // VK_QUOTE +#ifndef VK_BACK_QUOTE +#define VK_BACK_QUOTE 0xC0 +#endif // VK_BACK_QUOTE +#ifndef VK_SLASH +#define VK_SLASH 0xBF +#endif // VK_SLASH +#ifndef VK_BACK_SLASH +#define VK_BACK_SLASH 0xDC +#endif // VK_BACK_SLASH +#ifndef VK_EQUALS +#define VK_EQUALS 0xBB +#endif // VK_EQUALS +#ifndef VK_OPEN_BRACKET +#define VK_OPEN_BRACKET 0xDB +#endif // VK_OPEN_BRACKET +#ifndef VK_CLOSE_BRACKET +#define VK_CLOSE_BRACKET 0xDD +#endif // VK_CLOSE_BRACKET + + +GHOST_SystemWin32::GHOST_SystemWin32() +: m_hasPerformanceCounter(false), m_freq(0), m_start(0), + m_seperateLeftRight(false), + m_seperateLeftRightInitialized(false) +{ + m_displayManager = new GHOST_DisplayManagerWin32 (); + GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n"); + m_displayManager->initialize(); +} + +GHOST_SystemWin32::~GHOST_SystemWin32() +{ +} + + +GHOST_TUns64 GHOST_SystemWin32::getMilliSeconds() const +{ + // Hardware does not support high resolution timers. We will use GetTickCount instead then. + if (!m_hasPerformanceCounter) { + return ::GetTickCount(); + } + + // Retrieve current count + __int64 count = 0; + ::QueryPerformanceCounter((LARGE_INTEGER*)&count); + + // Calculate the time passed since system initialization. + __int64 delta = 1000*(count-m_start); + + GHOST_TUns64 t = (GHOST_TUns64)(delta/m_freq); + return t; +} + + +GHOST_TUns8 GHOST_SystemWin32::getNumDisplays() const +{ + GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::getNumDisplays(): m_displayManager==0\n"); + GHOST_TUns8 numDisplays; + m_displayManager->getNumDisplays(numDisplays); + return numDisplays; +} + + +void GHOST_SystemWin32::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const +{ + width = ::GetSystemMetrics(SM_CXSCREEN); + height= ::GetSystemMetrics(SM_CYSCREEN); +} + + +GHOST_IWindow* GHOST_SystemWin32::createWindow( + const STR_String& title, + GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, + GHOST_TWindowState state, GHOST_TDrawingContextType type, + bool stereoVisual) +{ + GHOST_Window* window = 0; + window = new GHOST_WindowWin32 (title, left, top, width, height, state, type, stereoVisual); + if (window) { + if (window->getValid()) { + // Store the pointer to the window + if (state != GHOST_kWindowStateFullScreen) { + m_windowManager->addWindow(window); + } + } + else { + delete window; + window = 0; + } + } + return window; +} + + +bool GHOST_SystemWin32::processEvents(bool waitForEvent) +{ + MSG msg; + bool anyProcessed = false; + + do { + GHOST_TimerManager* timerMgr = getTimerManager(); + + if (waitForEvent && !::PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE)) { +#if 1 + ::Sleep(1); +#else + GHOST_TUns64 next = timerMgr->nextFireTime(); + + if (next == GHOST_kFireTimeNever) { + ::WaitMessage(); + } else { + ::SetTimer(NULL, 0, next - getMilliSeconds(), NULL); + ::WaitMessage(); + ::KillTimer(NULL, 0); + } +#endif + } + + if (timerMgr->fireTimers(getMilliSeconds())) { + anyProcessed = true; + } + + // Process all the events waiting for us + while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + anyProcessed = true; + } + } while (waitForEvent && !anyProcessed); + + return anyProcessed; +} + + +GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const +{ + POINT point; + bool success = ::GetCursorPos(&point) == TRUE; + x = point.x; + y = point.y; + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const +{ + return ::SetCursorPos(x, y) == TRUE ? GHOST_kSuccess : GHOST_kFailure; +} + + +GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys& keys) const +{ + /* + GetKeyState and GetAsyncKeyState only work with Win95, Win98, NT4, + Terminal Server and Windows 2000. + But on WinME it always returns zero. These two functions are simply + skipped by Millenium Edition! + + Official explanation from Microsoft: + Intentionally disabled. + It didn't work all that well on some newer hardware, and worked less + well with the passage of time, so it was fully disabled in ME. + */ + if (m_seperateLeftRight && m_seperateLeftRightInitialized) { + bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0; + keys.set(GHOST_kModifierKeyLeftShift, down); + down = HIBYTE(::GetKeyState(VK_RSHIFT)) != 0; + keys.set(GHOST_kModifierKeyRightShift, down); + down = HIBYTE(::GetKeyState(VK_LMENU)) != 0; + keys.set(GHOST_kModifierKeyLeftAlt, down); + down = HIBYTE(::GetKeyState(VK_RMENU)) != 0; + keys.set(GHOST_kModifierKeyRightAlt, down); + down = HIBYTE(::GetKeyState(VK_LCONTROL)) != 0; + keys.set(GHOST_kModifierKeyLeftControl, down); + down = HIBYTE(::GetKeyState(VK_RCONTROL)) != 0; + keys.set(GHOST_kModifierKeyRightControl, down); + } + else { + bool down = HIBYTE(::GetKeyState(VK_SHIFT)) != 0; + keys.set(GHOST_kModifierKeyLeftShift, down); + keys.set(GHOST_kModifierKeyRightShift, down); + down = HIBYTE(::GetKeyState(VK_MENU)) != 0; + keys.set(GHOST_kModifierKeyLeftAlt, down); + keys.set(GHOST_kModifierKeyRightAlt, down); + down = HIBYTE(::GetKeyState(VK_CONTROL)) != 0; + keys.set(GHOST_kModifierKeyLeftControl, down); + keys.set(GHOST_kModifierKeyRightControl, down); + } + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_SystemWin32::getButtons(GHOST_Buttons& buttons) const +{ + /* Check for swapped buttons (left-handed mouse buttons) + * GetAsyncKeyState() will give back the state of the physical mouse buttons. + */ + bool swapped = ::GetSystemMetrics(SM_SWAPBUTTON) == TRUE; + + bool down = HIBYTE(::GetKeyState(VK_LBUTTON)) != 0; + buttons.set(swapped ? GHOST_kButtonMaskRight : GHOST_kButtonMaskLeft, down); + + down = HIBYTE(::GetKeyState(VK_MBUTTON)) != 0; + buttons.set(GHOST_kButtonMaskMiddle, down); + + down = HIBYTE(::GetKeyState(VK_RBUTTON)) != 0; + buttons.set(swapped ? GHOST_kButtonMaskLeft : GHOST_kButtonMaskRight, down); + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_SystemWin32::init() +{ + GHOST_TSuccess success = GHOST_System::init(); + + // Determine whether this system has a high frequency performance counter. */ + m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE; + if (m_hasPerformanceCounter) { + GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer available\n") + ::QueryPerformanceCounter((LARGE_INTEGER*)&m_start); + } + else { + GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer not available\n") + } + + if (success) { + WNDCLASS wc; + wc.style= CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc= s_wndProc; + wc.cbClsExtra= 0; + wc.cbWndExtra= 0; + wc.hInstance= ::GetModuleHandle(0); + wc.hIcon = ::LoadIcon(wc.hInstance, "APPICON"); + if (!wc.hIcon) { + ::LoadIcon(NULL, IDI_APPLICATION); + } + wc.hCursor = ::LoadCursor(0, IDC_ARROW); + wc.hbrBackground= (HBRUSH)::GetStockObject(BLACK_BRUSH); + wc.lpszMenuName = 0; + wc.lpszClassName= GHOST_WindowWin32::getWindowClassName(); + + // Use RegisterClassEx for setting small icon + if (::RegisterClass(&wc) == 0) { + success = GHOST_kFailure; + } + } + return success; +} + + +GHOST_TSuccess GHOST_SystemWin32::exit() +{ + return GHOST_System::exit(); +} + + +GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const +{ + GHOST_TKey key; + bool isExtended = (lParam&(1<<24))?true:false; + + if ((wParam >= '0') && (wParam <= '9')) { + // VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) + key = (GHOST_TKey)(wParam - '0' + GHOST_kKey0); + } + else if ((wParam >= 'A') && (wParam <= 'Z')) { + // VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) + key = (GHOST_TKey)(wParam - 'A' + GHOST_kKeyA); + } + else if ((wParam >= VK_F1) && (wParam <= VK_F24)) { + key = (GHOST_TKey)(wParam - VK_F1 + GHOST_kKeyF1); + } + else { + switch (wParam) { + case VK_RETURN: + key = isExtended?GHOST_kKeyNumpadEnter:GHOST_kKeyEnter; + break; + + case VK_BACK: key = GHOST_kKeyBackSpace; break; + case VK_TAB: key = GHOST_kKeyTab; break; + case VK_ESCAPE: key = GHOST_kKeyEsc; break; + case VK_SPACE: key = GHOST_kKeySpace; break; + case VK_PRIOR: key = GHOST_kKeyUpPage; break; + case VK_NEXT: key = GHOST_kKeyDownPage; break; + case VK_END: key = GHOST_kKeyEnd; break; + case VK_HOME: key = GHOST_kKeyHome; break; + case VK_INSERT: key = GHOST_kKeyInsert; break; + case VK_DELETE: key = GHOST_kKeyDelete; break; + case VK_LEFT: key = GHOST_kKeyLeftArrow; break; + case VK_RIGHT: key = GHOST_kKeyRightArrow; break; + case VK_UP: key = GHOST_kKeyUpArrow; break; + case VK_DOWN: key = GHOST_kKeyDownArrow; break; + case VK_NUMPAD0: key = GHOST_kKeyNumpad0; break; + case VK_NUMPAD1: key = GHOST_kKeyNumpad1; break; + case VK_NUMPAD2: key = GHOST_kKeyNumpad2; break; + case VK_NUMPAD3: key = GHOST_kKeyNumpad3; break; + case VK_NUMPAD4: key = GHOST_kKeyNumpad4; break; + case VK_NUMPAD5: key = GHOST_kKeyNumpad5; break; + case VK_NUMPAD6: key = GHOST_kKeyNumpad6; break; + case VK_NUMPAD7: key = GHOST_kKeyNumpad7; break; + case VK_NUMPAD8: key = GHOST_kKeyNumpad8; break; + case VK_NUMPAD9: key = GHOST_kKeyNumpad9; break; + case VK_SNAPSHOT: key = GHOST_kKeyPrintScreen; break; + case VK_PAUSE: key = GHOST_kKeyPause; break; + case VK_MULTIPLY: key = GHOST_kKeyNumpadAsterisk; break; + case VK_SUBTRACT: key = GHOST_kKeyNumpadMinus; break; + case VK_DECIMAL: key = GHOST_kKeyNumpadPeriod; break; + case VK_DIVIDE: key = GHOST_kKeyNumpadSlash; break; + case VK_ADD: key = GHOST_kKeyNumpadPlus; break; + + case VK_SEMICOLON: key = GHOST_kKeySemicolon; break; + case VK_EQUALS: key = GHOST_kKeyEqual; break; + case VK_COMMA: key = GHOST_kKeyComma; break; + case VK_MINUS: key = GHOST_kKeyMinus; break; + case VK_PERIOD: key = GHOST_kKeyPeriod; break; + case VK_SLASH: key = GHOST_kKeySlash; break; + case VK_BACK_QUOTE: key = GHOST_kKeyAccentGrave; break; + case VK_OPEN_BRACKET: key = GHOST_kKeyLeftBracket; break; + case VK_BACK_SLASH: key = GHOST_kKeyBackslash; break; + case VK_CLOSE_BRACKET: key = GHOST_kKeyRightBracket; break; + case VK_QUOTE: key = GHOST_kKeyQuote; break; + + // Process these keys separately because we need to distinguish right from left modifier keys + case VK_SHIFT: + case VK_CONTROL: + case VK_MENU: + + // Ignore these keys + case VK_NUMLOCK: + case VK_SCROLL: + case VK_CAPITAL: + default: + key = GHOST_kKeyUnknown; + break; + } + } + return key; +} + + +void GHOST_SystemWin32::processModifierKeys(GHOST_IWindow *window) +{ + GHOST_ModifierKeys oldModifiers, newModifiers; + // Retrieve old state of the modifier keys + ((GHOST_SystemWin32*)getSystem())->retrieveModifierKeys(oldModifiers); + // Retrieve current state of the modifier keys + ((GHOST_SystemWin32*)getSystem())->getModifierKeys(newModifiers); + + // Compare the old and the new + if (!newModifiers.equals(oldModifiers)) { + // Create events for the masks that changed + for (int i = 0; i < GHOST_kModifierKeyNumMasks; i++) { + if (newModifiers.get((GHOST_TModifierKeyMask)i) != oldModifiers.get((GHOST_TModifierKeyMask)i)) { + // Convert the mask to a key code + GHOST_TKey key = GHOST_ModifierKeys::getModifierKeyCode((GHOST_TModifierKeyMask)i); + bool keyDown = newModifiers.get((GHOST_TModifierKeyMask)i); + GHOST_EventKey* event; + if (key != GHOST_kKeyUnknown) { + // Create an event + event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key); + pushEvent(event); + } + } + } + } + + // Store new modifier keys state + ((GHOST_SystemWin32*)getSystem())->storeModifierKeys(newModifiers); +} + + +GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask) +{ + return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask); +} + + +GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *window) +{ + GHOST_TInt32 x, y; + getSystem()->getCursorPosition(x, y); + return new GHOST_EventCursor (getSystem()->getMilliSeconds(), type, window, x, y); +} + + +GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, bool keyDown, WPARAM wParam, LPARAM lParam) +{ + GHOST_TKey key = ((GHOST_SystemWin32*)getSystem())->convertKey(wParam, lParam); + GHOST_EventKey* event; + if (key != GHOST_kKeyUnknown) { + MSG keyMsg; + char ascii = '\0'; + + /* Eat any character related messages */ + if (::PeekMessage(&keyMsg, NULL, WM_CHAR, WM_SYSDEADCHAR, PM_REMOVE)) { + ascii = (char) keyMsg.wParam; + } + + event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key, ascii); + } + else { + event = 0; + } + return event; +} + + +GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window) +{ + return new GHOST_Event(getSystem()->getMilliSeconds(), type, window); +} + + +LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + GHOST_Event* event = 0; + LRESULT lResult; + GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem()); + GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized") + + if (hwnd) { + GHOST_WindowWin32* window = (GHOST_WindowWin32*)::GetWindowLong(hwnd, GWL_USERDATA); + if (window) { + switch (msg) { + //////////////////////////////////////////////////////////////////////// + // Keyboard events, processed + //////////////////////////////////////////////////////////////////////// + case WM_KEYDOWN: + /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a + * nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt + * key is not pressed. + */ + case WM_SYSKEYDOWN: + /* The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when + * the user presses the F10 key (which activates the menu bar) or holds down the + * alt key and then presses another key. It also occurs when no window currently + * has the keyboard focus; in this case, the WM_SYSKEYDOWN message is sent to the + * active window. The window that receives the message can distinguish between these + * two contexts by checking the context code in the lKeyData parameter. + */ + switch (wParam) { + case VK_SHIFT: + case VK_CONTROL: + case VK_MENU: + if (!system->m_seperateLeftRightInitialized) { + // Check whether this system supports seperate left and right keys + switch (wParam) { + case VK_SHIFT: + system->m_seperateLeftRight = + (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) || + (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ? + true : false; + break; + case VK_CONTROL: + system->m_seperateLeftRight = + (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) || + (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ? + true : false; + break; + case VK_MENU: + system->m_seperateLeftRight = + (HIBYTE(::GetKeyState(VK_LMENU)) != 0) || + (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ? + true : false; + break; + } + system->m_seperateLeftRightInitialized = true; + } + system->processModifierKeys(window); + // Bypass call to DefWindowProc + return 0; + default: + event = processKeyEvent(window, true, wParam, lParam); + if (!event) { + GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") + GHOST_PRINT(msg) + GHOST_PRINT(" key ignored\n") + } + break; + } + break; + + case WM_KEYUP: + case WM_SYSKEYUP: + switch (wParam) { + case VK_SHIFT: + case VK_CONTROL: + case VK_MENU: + system->processModifierKeys(window); + // Bypass call to DefWindowProc + return 0; + default: + event = processKeyEvent(window, false, wParam, lParam); + if (!event) { + GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") + GHOST_PRINT(msg) + GHOST_PRINT(" key ignored\n") + } + break; + } + break; + + //////////////////////////////////////////////////////////////////////// + // Keyboard events, ignored + //////////////////////////////////////////////////////////////////////// + case WM_CHAR: + /* The WM_CHAR message is posted to the window with the keyboard focus when + * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR + * contains the character code of the key that was pressed. + */ + case WM_DEADCHAR: + /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a + * WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR + * specifies a character code generated by a dead key. A dead key is a key that + * generates a character, such as the umlaut (double-dot), that is combined with + * another character to form a composite character. For example, the umlaut-O + * character (Ö) is generated by typing the dead key for the umlaut character, and + * then typing the O key. + */ + case WM_SYSDEADCHAR: + /* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when + * a WM_SYSKEYDOWN message is translated by the TranslateMessage function. + * WM_SYSDEADCHAR specifies the character code of a system dead key - that is, + * a dead key that is pressed while holding down the alt key. + */ + break; + + //////////////////////////////////////////////////////////////////////// + // Mouse events, processed + //////////////////////////////////////////////////////////////////////// + case WM_LBUTTONDOWN: + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft); + break; + case WM_MBUTTONDOWN: + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle); + break; + case WM_RBUTTONDOWN: + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight); + break; + case WM_LBUTTONUP: + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft); + break; + case WM_MBUTTONUP: + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle); + break; + case WM_RBUTTONUP: + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight); + break; + case WM_MOUSEMOVE: + event = processCursorEvent(GHOST_kEventCursorMove, window); + break; + case WM_SETCURSOR: + /* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor + * to move within a window and mouse input is not captured. + * This means we have to set the cursor shape every time the mouse moves! + * The DefWindowProc function uses this message to set the cursor to an + * arrow if it is not in the client area. + */ + if (LOWORD(lParam) == HTCLIENT) { + // Load the current cursor + window->loadCursor(window->getCursorVisibility(), window->getCursorShape()); + // Bypass call to DefWindowProc + return 0; + } + else { + // Outside of client area show standard cursor + window->loadCursor(true, GHOST_kStandardCursorDefault); + } + break; + + //////////////////////////////////////////////////////////////////////// + // Mouse events, ignored + //////////////////////////////////////////////////////////////////////// + case WM_NCMOUSEMOVE: + /* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved + * within the nonclient area of the window. This message is posted to the window + * that contains the cursor. If a window has captured the mouse, this message is not posted. + */ + case WM_NCHITTEST: + /* The WM_NCHITTEST message is sent to a window when the cursor moves, or + * when a mouse button is pressed or released. If the mouse is not captured, + * the message is sent to the window beneath the cursor. Otherwise, the message + * is sent to the window that has captured the mouse. + */ + break; + + //////////////////////////////////////////////////////////////////////// + // Window events, processed + //////////////////////////////////////////////////////////////////////// + case WM_CLOSE: + /* The WM_CLOSE message is sent as a signal that a window or an application should terminate. */ + event = processWindowEvent(GHOST_kEventWindowClose, window); + break; + case WM_ACTIVATE: + /* The WM_ACTIVATE message is sent to both the window being activated and the window being + * deactivated. If the windows use the same input queue, the message is sent synchronously, + * first to the window procedure of the top-level window being deactivated, then to the window + * procedure of the top-level window being activated. If the windows use different input queues, + * the message is sent asynchronously, so the window is activated immediately. + */ + event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window); + break; + case WM_PAINT: + /* An application sends the WM_PAINT message when the system or another application + * makes a request to paint a portion of an application's window. The message is sent + * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage + * function when the application obtains a WM_PAINT message by using the GetMessage or + * PeekMessage function. + */ + event = processWindowEvent(GHOST_kEventWindowUpdate, window); + ::ValidateRect(hwnd, NULL); + break; + case WM_SIZE: + /* The WM_SIZE message is sent to a window after its size has changed. + * The WM_SIZE and WM_MOVE messages are not sent if an application handles the + * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient + * to perform any move or size change processing during the WM_WINDOWPOSCHANGED + * message without calling DefWindowProc. + */ + event = processWindowEvent(GHOST_kEventWindowSize, window); + case WM_CAPTURECHANGED: + window->lostMouseCapture(); + break; + + //////////////////////////////////////////////////////////////////////// + // Window events, ignored + //////////////////////////////////////////////////////////////////////// + case WM_WINDOWPOSCHANGED: + /* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place + * in the Z order has changed as a result of a call to the SetWindowPos function or + * another window-management function. + * The WM_SIZE and WM_MOVE messages are not sent if an application handles the + * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient + * to perform any move or size change processing during the WM_WINDOWPOSCHANGED + * message without calling DefWindowProc. + */ + case WM_MOVE: + /* The WM_SIZE and WM_MOVE messages are not sent if an application handles the + * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient + * to perform any move or size change processing during the WM_WINDOWPOSCHANGED + * message without calling DefWindowProc. + */ + case WM_ERASEBKGND: + /* An application sends the WM_ERASEBKGND message when the window background must be + * erased (for example, when a window is resized). The message is sent to prepare an + * invalidated portion of a window for painting. + */ + case WM_NCPAINT: + /* An application sends the WM_NCPAINT message to a window when its frame must be painted. */ + case WM_NCACTIVATE: + /* The WM_NCACTIVATE message is sent to a window when its nonclient area needs to be changed + * to indicate an active or inactive state. + */ + case WM_DESTROY: + /* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window + * procedure of the window being destroyed after the window is removed from the screen. + * This message is sent first to the window being destroyed and then to the child windows + * (if any) as they are destroyed. During the processing of the message, it can be assumed + * that all child windows still exist. + */ + case WM_NCDESTROY: + /* The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The + * DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY + * message. WM_DESTROY is used to free the allocated memory object associated with the window. + */ + case WM_KILLFOCUS: + /* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus. */ + case WM_SHOWWINDOW: + /* The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown. */ + case WM_WINDOWPOSCHANGING: + /* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in + * the Z order is about to change as a result of a call to the SetWindowPos function or + * another window-management function. + */ + case WM_SETFOCUS: + /* The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus. */ + case WM_MOVING: + /* The WM_MOVING message is sent to a window that the user is moving. By processing + * this message, an application can monitor the size and position of the drag rectangle + * and, if needed, change its size or position. + */ + case WM_ENTERSIZEMOVE: + /* The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving + * or sizing modal loop. The window enters the moving or sizing modal loop when the user + * clicks the window's title bar or sizing border, or when the window passes the + * WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the + * message specifies the SC_MOVE or SC_SIZE value. The operation is complete when + * DefWindowProc returns. + */ + break; + + //////////////////////////////////////////////////////////////////////// + // Other events + //////////////////////////////////////////////////////////////////////// + case WM_GETTEXT: + /* An application sends a WM_GETTEXT message to copy the text that + * corresponds to a window into a buffer provided by the caller. + */ + case WM_ACTIVATEAPP: + /* The WM_ACTIVATEAPP message is sent when a window belonging to a + * different application than the active window is about to be activated. + * The message is sent to the application whose window is being activated + * and to the application whose window is being deactivated. + */ + case WM_TIMER: + /* The WIN32 docs say: + * The WM_TIMER message is posted to the installing thread's message queue + * when a timer expires. You can process the message by providing a WM_TIMER + * case in the window procedure. Otherwise, the default window procedure will + * call the TimerProc callback function specified in the call to the SetTimer + * function used to install the timer. + * + * In GHOST, we let DefWindowProc call the timer callback. + */ + break; + } + } + else { + // Event found for a window before the pointer to the class has been set. + GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n") + /* These are events we typically miss at this point: + WM_GETMINMAXINFO 0x24 + WM_NCCREATE 0x81 + WM_NCCALCSIZE 0x83 + WM_CREATE 0x01 + We let DefWindowProc do the work. + */ + } + } + else { + // Events without valid hwnd + GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n") + } + + if (event) { + system->pushEvent(event); + lResult = 0; + } + else { + lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); + } + return lResult; +} diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h new file mode 100644 index 00000000000..ac1a7eb6ac5 --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -0,0 +1,278 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +#ifndef _GHOST_SYSTEM_WIN32_H_ +#define _GHOST_SYSTEM_WIN32_H_ + +#ifndef WIN32 +#error WIN32 only! +#endif // WIN32 + +#include "GHOST_System.h" + +#include <windows.h> + +#if defined(__CYGWIN32__) +# define __int64 long long +#endif + + +class GHOST_EventButton; +class GHOST_EventCursor; +class GHOST_EventKey; +class GHOST_EventWindow; + +/** + * WIN32 Implementation of GHOST_System class. + * @see GHOST_System. + * @author Maarten Gribnau + * @date May 10, 2001 + */ +class GHOST_SystemWin32 : public GHOST_System { +public: + /** + * Constructor. + */ + GHOST_SystemWin32(); + + /** + * Destructor. + */ + virtual ~GHOST_SystemWin32(); + + /*************************************************************************************** + ** Time(r) functionality + ***************************************************************************************/ + + /** + * Returns the system time. + * Returns the number of milliseconds since the start of the system process. + * This overloaded method uses the high frequency timer if available. + * @return The number of milliseconds. + */ + virtual GHOST_TUns64 getMilliSeconds() const; + + /*************************************************************************************** + ** Display/window management functionality + ***************************************************************************************/ + + /** + * Returns the number of displays on this system. + * @return The number of displays. + */ + virtual GHOST_TUns8 getNumDisplays() const; + + /** + * Returns the dimensions of the main display on this system. + * @return The dimension of the main display. + */ + virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const; + + /** + * Create a new window. + * The new window is added to the list of windows managed. + * Never explicitly delete the window, use disposeWindow() instead. + * @param title The name of the window (displayed in the title bar of the window if the OS supports it). + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param height The height the window. + * @param state The state of the window when opened. + * @param type The type of drawing context installed in this window. + * @return The new window (or 0 if creation failed). + */ + virtual GHOST_IWindow* createWindow( + const STR_String& title, + GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, + GHOST_TWindowState state, GHOST_TDrawingContextType type, + const bool stereoVisual); + + /*************************************************************************************** + ** Event management functionality + ***************************************************************************************/ + + /** + * Gets events from the system and stores them in the queue. + * @param waitForEvent Flag to wait for an event (or return immediately). + * @return Indication of the presence of events. + */ + virtual bool processEvents(bool waitForEvent); + + + /*************************************************************************************** + ** Cursor management functionality + ***************************************************************************************/ + + /** + * Returns the current location of the cursor (location in screen coordinates) + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. + */ + virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const; + + /** + * Updates the location of the cursor (location in screen coordinates). + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const; + + /*************************************************************************************** + ** Access to mouse button and keyboard states. + ***************************************************************************************/ + + /** + * Returns the state of all modifier keys. + * @param keys The state of all modifier keys (true == pressed). + * @return Indication of success. + */ + virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const; + + /** + * Returns the state of the mouse buttons (ouside the message queue). + * @param buttons The state of the buttons. + * @return Indication of success. + */ + virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const; + +protected: + /** + * Initializes the system. + * For now, it justs registers the window class (WNDCLASS). + * @return A success value. + */ + virtual GHOST_TSuccess init(); + + /** + * Closes the system down. + * @return A success value. + */ + virtual GHOST_TSuccess exit(); + + /** + * Converts raw WIN32 key codes from the wndproc to GHOST keys. + * @param wParam The wParam from the wndproc + * @param lParam The lParam from the wndproc + * @return The GHOST key (GHOST_kKeyUnknown if no match). + */ + virtual GHOST_TKey convertKey(WPARAM wParam, LPARAM lParam) const; + + /** + * Creates modifier key event(s) and updates the key data stored locally (m_modifierKeys). + * With the modifier keys, we want to distinguish left and right keys. + * Sometimes this is not possible (Windows ME for instance). Then, we want + * events generated for both keys. + */ + void processModifierKeys(GHOST_IWindow *window); + + /** + * Creates mouse button event. + * @param type The type of event to create. + * @param type The button mask of this event. + * @return The event created. + */ + static GHOST_EventButton* processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask); + + /** + * Creates cursor event. + * @param type The type of event to create. + * @return The event created. + */ + static GHOST_EventCursor* processCursorEvent(GHOST_TEventType type, GHOST_IWindow *window); + + /** + * Creates a key event and updates the key data stored locally (m_modifierKeys). + * In most cases this is a straightforward conversion of key codes. + * For the modifier keys however, we want to distinguish left and right keys. + */ + static GHOST_EventKey* processKeyEvent(GHOST_IWindow *window, bool keyDown, WPARAM wParam, LPARAM lParam); + + /** + * Creates a window event. + * @param type The type of event to create. + * @param window The window receiving the event. + * @return The event created. + */ + static GHOST_Event* processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window); + + /** + * Returns the local state of the modifier keys (from the message queue). + * @param keys The state of the keys. + */ + inline virtual void retrieveModifierKeys(GHOST_ModifierKeys& keys) const; + + /** + * Stores the state of the modifier keys locally. + * For internal use only! + * @param keys The new state of the modifier keys. + */ + inline virtual void storeModifierKeys(const GHOST_ModifierKeys& keys); + + /** + * Windows call back routine for our window class. + */ + static LRESULT WINAPI s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + + /** The current state of the modifier keys. */ + GHOST_ModifierKeys m_modifierKeys; + /** State variable set at initialization. */ + bool m_hasPerformanceCounter; + /** High frequency timer variable. */ + __int64 m_freq; + /** High frequency timer variable. */ + __int64 m_start; + /** Stores the capability of this system to distinguish left and right modifier keys. */ + bool m_seperateLeftRight; + /** Stores the initialization state of the member m_leftRightDistinguishable. */ + bool m_seperateLeftRightInitialized; +}; + +inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const +{ + keys = m_modifierKeys; +} + +inline void GHOST_SystemWin32::storeModifierKeys(const GHOST_ModifierKeys& keys) +{ + m_modifierKeys = keys; +} + +#endif // _GHOST_SYSTEM_WIN32_H_ diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp new file mode 100755 index 00000000000..77c13d66de2 --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -0,0 +1,803 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + + +#include "GHOST_SystemX11.h" +#include "GHOST_WindowX11.h" +#include "GHOST_WindowManager.h" +#include "GHOST_TimerManager.h" +#include "GHOST_EventCursor.h" +#include "GHOST_EventKey.h" +#include "GHOST_EventButton.h" +#include "GHOST_DisplayManagerX11.h" + +#include "GHOST_Debug.h" + +#include <X11/Xatom.h> +#include <X11/keysym.h> + +// For timing + +#include <sys/time.h> +#include <unistd.h> + +#include <vector> + +using namespace std; + +GHOST_SystemX11:: +GHOST_SystemX11( +) : + GHOST_System(), + m_start_time(0) +{ + m_display = XOpenDisplay(NULL); + + if (!m_display) return; + + m_delete_window_atom = XInternAtom(m_display, "WM_DELETE_WINDOW", True); + + // compute the initial time + timeval tv; + if (gettimeofday(&tv,NULL) == -1) { + GHOST_ASSERT(false,"Could not instantiate timer!"); + } + + m_start_time = GHOST_TUns64(tv.tv_sec*1000 + tv.tv_usec/1000); +} + + GHOST_TSuccess +GHOST_SystemX11:: +init( +){ + GHOST_TSuccess success = GHOST_System::init(); + + if (success) { + m_keyboard_vector = new char[32]; + + m_displayManager = new GHOST_DisplayManagerX11(this); + + if (m_keyboard_vector && m_displayManager) { + return GHOST_kSuccess; + } + } + + return GHOST_kFailure; +} + + + + GHOST_TUns64 +GHOST_SystemX11:: +getMilliSeconds( +) const { + timeval tv; + if (gettimeofday(&tv,NULL) == -1) { + GHOST_ASSERT(false,"Could not compute time!"); + } + + return GHOST_TUns64(tv.tv_sec*1000 + tv.tv_usec/1000) - m_start_time; +} + + GHOST_TUns8 +GHOST_SystemX11:: +getNumDisplays( +) const { + return GHOST_TUns8(1); +} + + /** + * Returns the dimensions of the main display on this system. + * @return The dimension of the main display. + */ + void +GHOST_SystemX11:: +getMainDisplayDimensions( + GHOST_TUns32& width, + GHOST_TUns32& height +) const { + if (m_display) { + width = DisplayWidth(m_display, DefaultScreen(m_display)); + height = DisplayHeight(m_display, DefaultScreen(m_display)); + } +} + + /** + * Create a new window. + * The new window is added to the list of windows managed. + * Never explicitly delete the window, use disposeWindow() instead. + * @param title The name of the window (displayed in the title bar of the window if the OS supports it). + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param height The height the window. + * @param state The state of the window when opened. + * @param type The type of drawing context installed in this window. + * @return The new window (or 0 if creation failed). + */ + GHOST_IWindow* +GHOST_SystemX11:: +createWindow( + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + bool stereoVisual +){ + GHOST_WindowX11 * window = 0; + + if (!m_display) return 0; + + window = new GHOST_WindowX11 ( + this,m_display,title, left, top, width, height, state, type + ); + + if (window) { + + // Install a new protocol for this window - so we can overide + // the default window closure mechanism. + + XSetWMProtocols(m_display, window->getXWindow(), &m_delete_window_atom, 1); + + if (window->getValid()) { + // Store the pointer to the window + m_windowManager->addWindow(window); + + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) ); + } + else { + delete window; + window = 0; + } + } + return window; + +} + + GHOST_WindowX11 * +GHOST_SystemX11:: +findGhostWindow( + Window xwind +) const { + + if (xwind == 0) return NULL; + + // It is not entirely safe to do this as the backptr may point + // to a window that has recently been removed. + // We should always check the window manager's list of windows + // and only process events on these windows. + + vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows(); + + vector<GHOST_IWindow *>::iterator win_it = win_vec.begin(); + vector<GHOST_IWindow *>::const_iterator win_end = win_vec.end(); + + for (; win_it != win_end; ++win_it) { + GHOST_WindowX11 * window = static_cast<GHOST_WindowX11 *>(*win_it); + if (window->getXWindow() == xwind) { + return window; + } + } + return NULL; + +} + +static void SleepTillEvent(Display *display, GHOST_TUns64 maxSleep) { + int fd = ConnectionNumber(display); + fd_set fds; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + + if (maxSleep == -1) { + select(fd + 1, &fds, NULL, NULL, NULL); + } else { + timeval tv; + + tv.tv_sec = maxSleep/1000; + tv.tv_usec = (maxSleep - tv.tv_sec*1000)*1000; + + select(fd + 1, &fds, NULL, NULL, &tv); + } +} + + bool +GHOST_SystemX11:: +processEvents( + bool waitForEvent +){ + // Get all the current events -- translate them into + // ghost events and call base class pushEvent() method. + + bool anyProcessed = false; + + do { + GHOST_TimerManager* timerMgr = getTimerManager(); + + if (waitForEvent && m_dirty_windows.empty() && !XPending(m_display)) { + GHOST_TUns64 next = timerMgr->nextFireTime(); + + if (next==GHOST_kFireTimeNever) { + SleepTillEvent(m_display, -1); + } else { + SleepTillEvent(m_display, next - getMilliSeconds()); + } + } + + if (timerMgr->fireTimers(getMilliSeconds())) { + anyProcessed = true; + } + + while (XPending(m_display)) { + XEvent xevent; + XNextEvent(m_display, &xevent); + processEvent(&xevent); + anyProcessed = true; + } + + if (generateWindowExposeEvents()) { + anyProcessed = true; + } + } while (waitForEvent && !anyProcessed); + + return anyProcessed; +} + + void +GHOST_SystemX11:: +processEvent( + XEvent *xe +){ + GHOST_WindowX11 * window = findGhostWindow(xe->xany.window); + GHOST_Event * g_event = NULL; + + if (!window) { + return; + } + + switch (xe->type) { + case Expose: + { + XExposeEvent & xee = xe->xexpose; + + if (xee.count == 0) { + // Only generate a single expose event + // per read of the event queue. + + g_event = new + GHOST_Event( + getMilliSeconds(), + GHOST_kEventWindowUpdate, + window + ); + } + break; + } + case MotionNotify: + { + XMotionEvent &xme = xe->xmotion; + + g_event = new + GHOST_EventCursor( + getMilliSeconds(), + GHOST_kEventCursorMove, + window, + xme.x_root, + xme.y_root + ); + break; + } + + case KeyPress: + case KeyRelease: + { + XKeyEvent *xke = &(xe->xkey); + + KeySym key_sym = XLookupKeysym(xke,0); + char ascii; + + GHOST_TKey gkey = convertXKey(key_sym); + GHOST_TEventType type = (xke->type == KeyPress) ? + GHOST_kEventKeyDown : GHOST_kEventKeyUp; + + if (!XLookupString(xke, &ascii, 1, NULL, NULL)) { + ascii = '\0'; + } + + g_event = new + GHOST_EventKey( + getMilliSeconds(), + type, + window, + gkey, + ascii + ); + + break; + } + case ButtonPress: + case ButtonRelease: + { + + XButtonEvent & xbe = xe->xbutton; + GHOST_TButtonMask gbmask = GHOST_kButtonMaskLeft; + + switch (xbe.button) { + case Button1 : gbmask = GHOST_kButtonMaskLeft; break; + case Button3 : gbmask = GHOST_kButtonMaskRight; break; + default: + case Button2 : gbmask = GHOST_kButtonMaskMiddle; break; + } + + GHOST_TEventType type = (xbe.type == ButtonPress) ? + GHOST_kEventButtonDown : GHOST_kEventButtonUp; + + g_event = new + GHOST_EventButton( + getMilliSeconds(), + type, + window, + gbmask + ); + break; + } + + // change of size, border, layer etc. + case ConfigureNotify: + { + /* XConfigureEvent & xce = xe->xconfigure; */ + + g_event = new + GHOST_Event( + getMilliSeconds(), + GHOST_kEventWindowSize, + window + ); + break; + } + + case FocusIn: + case FocusOut: + { + XFocusChangeEvent &xfe = xe->xfocus; + + // May have to look at the type of event and filter some + // out. + + GHOST_TEventType gtype = (xfe.type == FocusIn) ? + GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate; + + g_event = new + GHOST_Event( + getMilliSeconds(), + gtype, + window + ); + break; + + } + case ClientMessage: + { + XClientMessageEvent & xcme = xe->xclient; + + if (xcme.data.l[0] == m_delete_window_atom) { + g_event = new + GHOST_Event( + getMilliSeconds(), + GHOST_kEventWindowClose, + window + ); + } else { + /* Unknown client message, ignore */ + } + + break; + } + + // We're not interested in the following things.(yet...) + case NoExpose : + case GraphicsExpose : + + case EnterNotify: + case LeaveNotify: + // XCrossingEvents pointer leave enter window. + break; + case MapNotify: + case UnmapNotify: + break; + case MappingNotify: + case ReparentNotify: + break; + + default: + break; + } + + if (g_event) { + pushEvent(g_event); + } +} + + + GHOST_TSuccess +GHOST_SystemX11:: +getModifierKeys( + GHOST_ModifierKeys& keys +) const { + + // analyse the masks retuned from XQueryPointer. + + memset(m_keyboard_vector,32,0); + + XQueryKeymap(m_display,m_keyboard_vector); + + // now translate key symobols into keycodes and + // test with vector. + + const KeyCode shift_l = XKeysymToKeycode(m_display,XK_Shift_L); + const KeyCode shift_r = XKeysymToKeycode(m_display,XK_Shift_R); + const KeyCode control_l = XKeysymToKeycode(m_display,XK_Control_L); + const KeyCode control_r = XKeysymToKeycode(m_display,XK_Control_R); + const KeyCode alt_l = XKeysymToKeycode(m_display,XK_Alt_L); + const KeyCode alt_r = XKeysymToKeycode(m_display,XK_Alt_R); + + // Shift + if ((m_keyboard_vector[shift_l >> 3] >> (shift_l & 7)) & 1) { + keys.set(GHOST_kModifierKeyLeftShift,true); + } else { + keys.set(GHOST_kModifierKeyLeftShift,false); + } + if ((m_keyboard_vector[shift_r >> 3] >> (shift_r & 7)) & 1) { + + keys.set(GHOST_kModifierKeyRightShift,true); + } else { + keys.set(GHOST_kModifierKeyRightShift,false); + } + + // control (weep) + if ((m_keyboard_vector[control_l >> 3] >> (control_l & 7)) & 1) { + keys.set(GHOST_kModifierKeyLeftControl,true); + } else { + keys.set(GHOST_kModifierKeyLeftControl,false); + } + if ((m_keyboard_vector[control_r >> 3] >> (control_r & 7)) & 1) { + keys.set(GHOST_kModifierKeyRightControl,true); + } else { + keys.set(GHOST_kModifierKeyRightControl,false); + } + + // Alt (yawn) + if ((m_keyboard_vector[alt_l >> 3] >> (alt_l & 7)) & 1) { + keys.set(GHOST_kModifierKeyLeftAlt,true); + } else { + keys.set(GHOST_kModifierKeyLeftAlt,false); + } + if ((m_keyboard_vector[alt_r >> 3] >> (alt_r & 7)) & 1) { + keys.set(GHOST_kModifierKeyRightAlt,true); + } else { + keys.set(GHOST_kModifierKeyRightAlt,false); + } + return GHOST_kSuccess; +} + + GHOST_TSuccess +GHOST_SystemX11:: +getButtons( + GHOST_Buttons& buttons +) const { + + Window root_return, child_return; + int rx,ry,wx,wy; + unsigned int mask_return; + + if (XQueryPointer( + m_display, + RootWindow(m_display,DefaultScreen(m_display)), + &root_return, + &child_return, + &rx,&ry, + &wx,&wy, + &mask_return + ) == False) { + return GHOST_kFailure; + } else { + + if (mask_return & Button1Mask) { + buttons.set(GHOST_kButtonMaskLeft,true); + } else { + buttons.set(GHOST_kButtonMaskLeft,false); + } + + if (mask_return & Button2Mask) { + buttons.set(GHOST_kButtonMaskMiddle,true); + } else { + buttons.set(GHOST_kButtonMaskMiddle,false); + } + + if (mask_return & Button3Mask) { + buttons.set(GHOST_kButtonMaskRight,true); + } else { + buttons.set(GHOST_kButtonMaskRight,false); + } + } + + return GHOST_kSuccess; +} + + + GHOST_TSuccess +GHOST_SystemX11:: +getCursorPosition( + GHOST_TInt32& x, + GHOST_TInt32& y +) const { + + Window root_return, child_return; + int rx,ry,wx,wy; + unsigned int mask_return; + + if (XQueryPointer( + m_display, + RootWindow(m_display,DefaultScreen(m_display)), + &root_return, + &child_return, + &rx,&ry, + &wx,&wy, + &mask_return + ) == False) { + return GHOST_kFailure; + } else { + x = rx; + y = ry; + } + return GHOST_kSuccess; +} + + + GHOST_TSuccess +GHOST_SystemX11:: +setCursorPosition( + GHOST_TInt32 x, + GHOST_TInt32 y +) const { + + // This is a brute force move in screen coordinates + // XWarpPointer does relative moves so first determine the + // current pointer position. + + int cx,cy; + if (getCursorPosition(cx,cy) == GHOST_kFailure) { + return GHOST_kFailure; + } + + int relx = x-cx; + int rely = y-cy; + + XWarpPointer(m_display,None,None,0,0,0,0,relx,rely); + XFlush(m_display); + + return GHOST_kSuccess; +} + + + void +GHOST_SystemX11:: +addDirtyWindow( + GHOST_WindowX11 * bad_wind +){ + + GHOST_ASSERT((bad_wind != NULL), "addDirtyWindow() NULL ptr trapped (window)"); + + m_dirty_windows.push_back(bad_wind); +} + + + bool +GHOST_SystemX11:: +generateWindowExposeEvents( +){ + + vector<GHOST_WindowX11 *>::iterator w_start = m_dirty_windows.begin(); + vector<GHOST_WindowX11 *>::const_iterator w_end = m_dirty_windows.end(); + bool anyProcessed = false; + + for (;w_start != w_end; ++w_start) { + GHOST_Event * g_event = new + GHOST_Event( + getMilliSeconds(), + GHOST_kEventWindowUpdate, + *w_start + ); + + (*w_start)->validate(); + + if (g_event) { + pushEvent(g_event); + anyProcessed = true; + } + } + + m_dirty_windows.clear(); + return anyProcessed; +} + +#define GXMAP(k,x,y) case x: k = y; break; + + GHOST_TKey +GHOST_SystemX11:: +convertXKey( + unsigned int key +){ + GHOST_TKey type; + + if ((key >= XK_A) && (key <= XK_Z)) { + type = GHOST_TKey( key - XK_A + int(GHOST_kKeyA)); + } else if ((key >= XK_a) && (key <= XK_z)) { + type = GHOST_TKey(key - XK_a + int(GHOST_kKeyA)); + } else if ((key >= XK_0) && (key <= XK_9)) { + type = GHOST_TKey(key - XK_0 + int(GHOST_kKey0)); + } else if ((key >= XK_F1) && (key <= XK_F24)) { + type = GHOST_TKey(key - XK_F1 + int(GHOST_kKeyF1)); + } else { + switch(key) { + GXMAP(type,XK_BackSpace, GHOST_kKeyBackSpace); + GXMAP(type,XK_Tab, GHOST_kKeyTab); + GXMAP(type,XK_Return, GHOST_kKeyEnter); + GXMAP(type,XK_Escape, GHOST_kKeyEsc); + GXMAP(type,XK_space, GHOST_kKeySpace); + + GXMAP(type,XK_Linefeed, GHOST_kKeyLinefeed); + GXMAP(type,XK_semicolon, GHOST_kKeySemicolon); + GXMAP(type,XK_period, GHOST_kKeyPeriod); + GXMAP(type,XK_comma, GHOST_kKeyComma); + GXMAP(type,XK_quoteright, GHOST_kKeyQuote); + GXMAP(type,XK_quoteleft, GHOST_kKeyAccentGrave); + GXMAP(type,XK_minus, GHOST_kKeyMinus); + GXMAP(type,XK_slash, GHOST_kKeySlash); + GXMAP(type,XK_backslash, GHOST_kKeyBackslash); + GXMAP(type,XK_equal, GHOST_kKeyEqual); + GXMAP(type,XK_bracketleft, GHOST_kKeyLeftBracket); + GXMAP(type,XK_bracketright, GHOST_kKeyRightBracket); + GXMAP(type,XK_Pause, GHOST_kKeyPause); + + GXMAP(type,XK_Shift_L, GHOST_kKeyLeftShift); + GXMAP(type,XK_Shift_R, GHOST_kKeyRightShift); + GXMAP(type,XK_Control_L, GHOST_kKeyLeftControl); + GXMAP(type,XK_Control_R, GHOST_kKeyRightControl); + GXMAP(type,XK_Alt_L, GHOST_kKeyLeftAlt); + GXMAP(type,XK_Alt_R, GHOST_kKeyRightAlt); + + GXMAP(type,XK_Insert, GHOST_kKeyInsert); + GXMAP(type,XK_Delete, GHOST_kKeyDelete); + GXMAP(type,XK_Home, GHOST_kKeyHome); + GXMAP(type,XK_End, GHOST_kKeyEnd); + GXMAP(type,XK_Page_Up, GHOST_kKeyUpPage); + GXMAP(type,XK_Page_Down, GHOST_kKeyDownPage); + + GXMAP(type,XK_Left, GHOST_kKeyLeftArrow); + GXMAP(type,XK_Right, GHOST_kKeyRightArrow); + GXMAP(type,XK_Up, GHOST_kKeyUpArrow); + GXMAP(type,XK_Down, GHOST_kKeyDownArrow); + + GXMAP(type,XK_Caps_Lock, GHOST_kKeyCapsLock); + GXMAP(type,XK_Scroll_Lock, GHOST_kKeyScrollLock); + GXMAP(type,XK_Num_Lock, GHOST_kKeyNumLock); + + /* keypad events */ + + GXMAP(type,XK_KP_0, GHOST_kKeyNumpad0); + GXMAP(type,XK_KP_1, GHOST_kKeyNumpad1); + GXMAP(type,XK_KP_2, GHOST_kKeyNumpad2); + GXMAP(type,XK_KP_3, GHOST_kKeyNumpad3); + GXMAP(type,XK_KP_4, GHOST_kKeyNumpad4); + GXMAP(type,XK_KP_5, GHOST_kKeyNumpad5); + GXMAP(type,XK_KP_6, GHOST_kKeyNumpad6); + GXMAP(type,XK_KP_7, GHOST_kKeyNumpad7); + GXMAP(type,XK_KP_8, GHOST_kKeyNumpad8); + GXMAP(type,XK_KP_9, GHOST_kKeyNumpad9); + GXMAP(type,XK_KP_Decimal, GHOST_kKeyNumpadPeriod); + + GXMAP(type,XK_KP_Insert, GHOST_kKeyNumpad0); + GXMAP(type,XK_KP_End, GHOST_kKeyNumpad1); + GXMAP(type,XK_KP_Down, GHOST_kKeyNumpad2); + GXMAP(type,XK_KP_Page_Down, GHOST_kKeyNumpad3); + GXMAP(type,XK_KP_Left, GHOST_kKeyNumpad4); + GXMAP(type,XK_KP_Begin, GHOST_kKeyNumpad5); + GXMAP(type,XK_KP_Right, GHOST_kKeyNumpad6); + GXMAP(type,XK_KP_Home, GHOST_kKeyNumpad7); + GXMAP(type,XK_KP_Up, GHOST_kKeyNumpad8); + GXMAP(type,XK_KP_Page_Up, GHOST_kKeyNumpad9); + GXMAP(type,XK_KP_Delete, GHOST_kKeyNumpadPeriod); + + GXMAP(type,XK_KP_Enter, GHOST_kKeyNumpadEnter); + GXMAP(type,XK_KP_Add, GHOST_kKeyNumpadPlus); + GXMAP(type,XK_KP_Subtract, GHOST_kKeyNumpadMinus); + GXMAP(type,XK_KP_Multiply, GHOST_kKeyNumpadAsterisk); + GXMAP(type,XK_KP_Divide, GHOST_kKeyNumpadSlash); + + /* some extra sun cruft (NICE KEYBOARD!) */ +#ifdef __sun__ + GXMAP(type,0xffde, GHOST_kKeyNumpad1); + GXMAP(type,0xffe0, GHOST_kKeyNumpad3); + GXMAP(type,0xffdc, GHOST_kKeyNumpad5); + GXMAP(type,0xffd8, GHOST_kKeyNumpad7); + GXMAP(type,0xffda, GHOST_kKeyNumpad9); + + GXMAP(type,0xffd6, GHOST_kKeyNumpadSlash); + GXMAP(type,0xffd7, GHOST_kKeyNumpadAsterisk); +#endif + + default : + type = GHOST_kKeyUnknown; + break; + } + } + + return type; +} + +#undef GXMAP + + diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h new file mode 100755 index 00000000000..6dedf1eb457 --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -0,0 +1,252 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +#ifndef _GHOST_SYSTEM_X11_H_ +#define _GHOST_SYSTEM_X11_H_ + +#include "GHOST_System.h" +#include "../GHOST_Types.h" + +#include <X11/Xlib.h> +#include <GL/glx.h> + +class GHOST_WindowX11; + +/** + * X11 Implementation of GHOST_System class. + * @see GHOST_System. + * @author Laurence Bourn + * @date October 26, 2001 + */ + +class GHOST_SystemX11 : public GHOST_System { +public: + + /** + * Constructor + * this class should only be instanciated by GHOST_ISystem. + */ + + GHOST_SystemX11( + ); + + GHOST_TSuccess + init( + ); + + + /** + * @section Interface Inherited from GHOST_ISystem + */ + + /** + * Returns the system time. + * Returns the number of milliseconds since the start of the system process. + * @return The number of milliseconds. + */ + GHOST_TUns64 + getMilliSeconds( + ) const; + + + /** + * Returns the number of displays on this system. + * @return The number of displays. + */ + GHOST_TUns8 + getNumDisplays( + ) const; + + /** + * Returns the dimensions of the main display on this system. + * @return The dimension of the main display. + */ + void + getMainDisplayDimensions( + GHOST_TUns32& width, + GHOST_TUns32& height + ) const; + + /** + * Create a new window. + * The new window is added to the list of windows managed. + * Never explicitly delete the window, use disposeWindow() instead. + * @param title The name of the window (displayed in the title bar of the window if the OS supports it). + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param height The height the window. + * @param state The state of the window when opened. + * @param type The type of drawing context installed in this window. + * @param stereoVisual Create a stereo visual for quad buffered stereo. + * @return The new window (or 0 if creation failed). + */ + GHOST_IWindow* + createWindow( + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + const bool stereoVisual + ); + + /** + * @section Interface Inherited from GHOST_ISystem + */ + + /** + * Retrieves events from the system and stores them in the queue. + * @param waitForEvent Flag to wait for an event (or return immediately). + * @return Indication of the presence of events. + */ + bool + processEvents( + bool waitForEvent + ); + + /** + * @section Interface Inherited from GHOST_System + */ + GHOST_TSuccess + getCursorPosition( + GHOST_TInt32& x, + GHOST_TInt32& y + ) const; + + GHOST_TSuccess + setCursorPosition( + GHOST_TInt32 x, + GHOST_TInt32 y + ) const; + + /** + * Returns the state of all modifier keys. + * @param keys The state of all modifier keys (true == pressed). + * @return Indication of success. + */ + GHOST_TSuccess + getModifierKeys( + GHOST_ModifierKeys& keys + ) const ; + + /** + * Returns the state of the mouse buttons (ouside the message queue). + * @param buttons The state of the buttons. + * @return Indication of success. + */ + GHOST_TSuccess + getButtons( + GHOST_Buttons& buttons + ) const; + + /** + * @section + * Flag a window as dirty. This will + * generate a GHOST window update event on a call to processEvents() + */ + + void + addDirtyWindow( + GHOST_WindowX11 * bad_wind + ); + + + /** + * return a pointer to the X11 display structure + */ + + Display * + getXDisplay( + ) { + return m_display; + } + + +private : + + Display * m_display; + + /** + * Atom used to detect window close events + */ + Atom m_delete_window_atom; + + /// The vector of windows that need to be updated. + std::vector<GHOST_WindowX11 *> m_dirty_windows; + + /// Start time at initialization. + GHOST_TUns64 m_start_time; + + /// A vector of keyboard key masks + char *m_keyboard_vector; + + /** + * Return the ghost window associated with the + * X11 window xwind + */ + + GHOST_WindowX11 * + findGhostWindow( + Window xwind + ) const ; + + void + processEvent( + XEvent *xe + ); + + bool + generateWindowExposeEvents( + ); + + GHOST_TKey + convertXKey( + unsigned int key + ); + +}; + +#endif + + + + diff --git a/intern/ghost/intern/GHOST_TimerManager.cpp b/intern/ghost/intern/GHOST_TimerManager.cpp new file mode 100644 index 00000000000..e54dfce86f9 --- /dev/null +++ b/intern/ghost/intern/GHOST_TimerManager.cpp @@ -0,0 +1,163 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 31, 2001 + */ + +#include "GHOST_TimerManager.h" + +#include <algorithm> + +#include "GHOST_TimerTask.h" + + +GHOST_TimerManager::GHOST_TimerManager() +{ +} + + +GHOST_TimerManager::~GHOST_TimerManager() +{ + disposeTimers(); +} + + +GHOST_TUns32 GHOST_TimerManager::getNumTimers() +{ + return (GHOST_TUns32)m_timers.size(); +} + + +bool GHOST_TimerManager::getTimerFound(GHOST_TimerTask* timer) +{ + TTimerVector::const_iterator iter = std::find(m_timers.begin(), m_timers.end(), timer); + return iter != m_timers.end(); +} + + +GHOST_TSuccess GHOST_TimerManager::addTimer(GHOST_TimerTask* timer) +{ + GHOST_TSuccess success; + if (!getTimerFound(timer)) { + // Add the timer task + m_timers.push_back(timer); + success = GHOST_kSuccess; + } + else { + success = GHOST_kFailure; + } + return success; +} + + +GHOST_TSuccess GHOST_TimerManager::removeTimer(GHOST_TimerTask* timer) +{ + GHOST_TSuccess success; + TTimerVector::iterator iter = std::find(m_timers.begin(), m_timers.end(), timer); + if (iter != m_timers.end()) { + // Remove the timer task + m_timers.erase(iter); + delete timer; + timer = 0; + success = GHOST_kSuccess; + } + else { + success = GHOST_kFailure; + } + return success; +} + +GHOST_TUns64 GHOST_TimerManager::nextFireTime() +{ + GHOST_TUns64 smallest = GHOST_kFireTimeNever; + TTimerVector::iterator iter; + + for (iter = m_timers.begin(); iter != m_timers.end(); iter++) { + GHOST_TUns64 next = (*iter)->getNext(); + + if (next<smallest) + smallest = next; + } + + return smallest; +} + +bool GHOST_TimerManager::fireTimers(GHOST_TUns64 time) +{ + TTimerVector::iterator iter; + bool anyProcessed = false; + + for (iter = m_timers.begin(); iter != m_timers.end(); iter++) { + if (fireTimer(time, *iter)) + anyProcessed = true; + } + + return anyProcessed; +} + + +bool GHOST_TimerManager::fireTimer(GHOST_TUns64 time, GHOST_TimerTask* task) +{ + GHOST_TUns64 next = task->getNext(); + + // Check if the timer should be fired + if (time > next) { + // Fire the timer + GHOST_TimerProcPtr timerProc = task->getTimerProc(); + GHOST_TUns64 start = task->getStart(); + timerProc(task, time - start); + + // Update the time at which we will fire it again + GHOST_TUns64 interval = task->getInterval(); + GHOST_TUns64 numCalls = (next - start) / interval; + numCalls++; + next = start + numCalls * interval; + task->setNext(next); + + return true; + } else { + return false; + } +} + + +void GHOST_TimerManager::disposeTimers() +{ + while (m_timers.size() > 0) { + delete m_timers[0]; + m_timers.erase(m_timers.begin()); + } +} diff --git a/intern/ghost/intern/GHOST_TimerManager.h b/intern/ghost/intern/GHOST_TimerManager.h new file mode 100644 index 00000000000..ab6d004cba8 --- /dev/null +++ b/intern/ghost/intern/GHOST_TimerManager.h @@ -0,0 +1,133 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 31, 2001 + */ + +#ifndef _GHOST_TIMER_MANAGER_H_ +#define _GHOST_TIMER_MANAGER_H_ + +#ifdef WIN32 +#pragma warning (disable:4786) // suppress stl-MSVC debug info warning +#endif // WIN32 + +#include <vector> + +#include "GHOST_Types.h" + +class GHOST_TimerTask; + + +/** + * Manages a list of timer tasks. + * Timer tasks added are owned by the manager. + * Don't delete timer task objects. + */ +class GHOST_TimerManager +{ +public: + /** + * Constructor. + */ + GHOST_TimerManager(); + + /** + * Destructor. + */ + virtual ~GHOST_TimerManager(); + + /** + * Returns the number of timer tasks. + * @return The number of events on the stack. + */ + virtual GHOST_TUns32 getNumTimers(); + + /** + * Returns whther this timer task ins in our list. + * @return Indication of presence. + */ + virtual bool getTimerFound(GHOST_TimerTask* timer); + + /** + * Adds a timer task to the list. + * It is only added when it not already present in the list. + * @param timer The timer task added to the list. + * @return Indication as to whether addition has succeeded. + */ + virtual GHOST_TSuccess addTimer(GHOST_TimerTask* timer); + + /** + * Removes a timer task from the list. + * It is only removed when it is found in the list. + * @param timer The timer task to be removed from the list. + * @return Indication as to whether removal has succeeded. + */ + virtual GHOST_TSuccess removeTimer(GHOST_TimerTask* timer); + + /** + * Finds the soonest time the next timer would fire. + * @return The soonest time the next timer would fire, + * or GHOST_kFireTimeNever if no timers exist. + */ + virtual GHOST_TUns64 nextFireTime(); + + /** + * Checks all timer tasks to see if they are expired and fires them if needed. + * @param time The current time. + * @return True if any timers were fired. + */ + virtual bool fireTimers(GHOST_TUns64 time); + + /** + * Checks this timer task to see if they are expired and fires them if needed. + * @param time The current time. + * @param task The timer task to check and optionally fire. + * @return True if the timer fired. + */ + virtual bool fireTimer(GHOST_TUns64 time, GHOST_TimerTask* task); + +protected: + /** + * Deletes all timers. + */ + void disposeTimers(); + + typedef std::vector<GHOST_TimerTask*> TTimerVector; + /** The list with event consumers. */ + TTimerVector m_timers; +}; + +#endif // _GHOST_TIMER_MANAGER_H_ diff --git a/intern/ghost/intern/GHOST_TimerTask.h b/intern/ghost/intern/GHOST_TimerTask.h new file mode 100644 index 00000000000..4f845a38fa1 --- /dev/null +++ b/intern/ghost/intern/GHOST_TimerTask.h @@ -0,0 +1,195 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 28, 2001 + */ + +#ifndef _GHOST_TIMER_TASK_H_ +#define _GHOST_TIMER_TASK_H_ + +#include "GHOST_ITimerTask.h" + + +/** + * Implementation of a timer task. + * @author Maarten Gribnau + * @date May 28, 2001 + */ +class GHOST_TimerTask : public GHOST_ITimerTask +{ +public: + /** + * Constructor. + * @param start The timer start time. + * @param interval The interval between calls to the timerProc + * @param timerProc The callbak invoked when the interval expires. + * @param data The timer user data. + */ + GHOST_TimerTask(GHOST_TUns64 start, GHOST_TUns64 interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData = 0) + : m_start(start), m_interval(interval), m_next(start), m_timerProc(timerProc), m_userData(userData), m_auxData(0) + { + } + + /** + * Returns the timer start time. + * @return The timer start time. + */ + inline virtual GHOST_TUns64 getStart() const + { + return m_start; + } + + /** + * Changes the timer start time. + * @param start The timer start time. + */ + virtual void setStart(GHOST_TUns64 start) + { + m_start = start; + } + + /** + * Returns the timer interval. + * @return The timer interval. + */ + inline virtual GHOST_TUns64 getInterval() const + { + return m_interval; + } + + /** + * Changes the timer interval. + * @param interval The timer interval. + */ + virtual void setInterval(GHOST_TUns64 interval) + { + m_interval = interval; + } + + /** + * Returns the time the timerProc will be called. + * @return The time the timerProc will be called. + */ + inline virtual GHOST_TUns64 getNext() const + { + return m_next; + } + + /** + * Changes the time the timerProc will be called. + * @param next The time the timerProc will be called. + */ + virtual void setNext(GHOST_TUns64 next) + { + m_next = next; + } + + /** + * Returns the timer callback. + * @return the timer callback. + */ + inline virtual GHOST_TimerProcPtr getTimerProc() const + { + return m_timerProc; + } + + /** + * Changes the timer callback. + * @param The timer callback. + */ + inline virtual void setTimerProc(const GHOST_TimerProcPtr timerProc) + { + m_timerProc = timerProc; + } + + /** + * Returns the timer user data. + * @return The timer user data. + */ + inline virtual GHOST_TUserDataPtr getUserData() const + { + return m_userData; + } + + /** + * Changes the time user data. + * @param data The timer user data. + */ + virtual void setUserData(const GHOST_TUserDataPtr userData) + { + m_userData = userData; + } + + /** + * Returns the auxiliary storage room. + * @return The auxiliary storage room. + */ + inline virtual GHOST_TUns32 getAuxData() const + { + return m_auxData; + } + + /** + * Changes the auxiliary storage room. + * @param auxData The auxiliary storage room. + */ + virtual void setAuxData(GHOST_TUns32 auxData) + { + m_auxData = auxData; + } + +protected: + /** The time the timer task was started. */ + GHOST_TUns64 m_start; + + /** The interval between calls. */ + GHOST_TUns64 m_interval; + + /** The time the timerProc will be called. */ + GHOST_TUns64 m_next; + + /** The callback invoked when the timer expires. */ + GHOST_TimerProcPtr m_timerProc; + + /** The timer task user data. */ + GHOST_TUserDataPtr m_userData; + + /** Auxiliary storage room. */ + GHOST_TUns32 m_auxData; +}; + + +#endif // _GHOST_TIMER_TASK_H_ diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp new file mode 100644 index 00000000000..daa83eedcf6 --- /dev/null +++ b/intern/ghost/intern/GHOST_Window.cpp @@ -0,0 +1,116 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +#include "GHOST_Window.h" + + +GHOST_Window::GHOST_Window( + const STR_String& /*title*/, + GHOST_TInt32 /*left*/, GHOST_TInt32 /*top*/, GHOST_TUns32 width, GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + const bool stereoVisual) +: + m_drawingContextType(type), + m_cursorVisible(true), + m_cursorShape(GHOST_kStandardCursorDefault), + m_stereoVisual(stereoVisual) +{ + m_fullScreen = state == GHOST_kWindowStateFullScreen; + if (m_fullScreen) { + m_fullScreenWidth = width; + m_fullScreenHeight = height; + } +} + + +GHOST_Window::~GHOST_Window() +{ +} + + +GHOST_TSuccess GHOST_Window::setDrawingContextType(GHOST_TDrawingContextType type) +{ + GHOST_TSuccess success = GHOST_kSuccess; + if (type != m_drawingContextType) { + success = removeDrawingContext(); + if (success) { + success = installDrawingContext(type); + m_drawingContextType = type; + } + else { + m_drawingContextType = GHOST_kDrawingContextTypeNone; + } + } + return success; +} + +GHOST_TSuccess GHOST_Window::setCursorVisibility(bool visible) +{ + if (setWindowCursorVisibility(visible)) { + m_cursorVisible = visible; + return GHOST_kSuccess; + } + else { + return GHOST_kFailure; + } +} + +GHOST_TSuccess GHOST_Window::setCursorShape(GHOST_TStandardCursor cursorShape) +{ + if (setWindowCursorShape(cursorShape)) { + m_cursorShape = cursorShape; + return GHOST_kSuccess; + } + else { + return GHOST_kFailure; + } +} + +GHOST_TSuccess GHOST_Window::setCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY) +{ + if (setWindowCustomCursorShape(bitmap, mask, hotX, hotY)) { + m_cursorShape = GHOST_kStandardCursorCustom; + return GHOST_kSuccess; + } + else { + return GHOST_kFailure; + } +} + diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h new file mode 100644 index 00000000000..9bb2be7679f --- /dev/null +++ b/intern/ghost/intern/GHOST_Window.h @@ -0,0 +1,255 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 7, 2001 + */ + +#ifndef _GHOST_WINDOW_H_ +#define _GHOST_WINDOW_H_ + + +#include "GHOST_IWindow.h" + +class STR_String; + +/** + * Platform independent implementation of GHOST_IWindow. + * Dimensions are given in screen coordinates that are relative to the upper-left corner of the screen. + * @author Maarten Gribnau + * @date May 7, 2001 + */ + +class GHOST_Window : public GHOST_IWindow +{ +public: + /** + * Constructor. + * Creates a new window and opens it. + * To check if the window was created properly, use the getValid() method. + * @param title The text shown in the title bar of the window. + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param heigh The height the window. + * @param state The state the window is initially opened with. + * @param type The type of drawing context installed in this window. + * @param stereoVisual Stereo visual for quad buffered stereo. + */ + GHOST_Window( + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, + const bool stereoVisual = false); + + /** + * @section Interface inherited from GHOST_IWindow left for derived class + * implementation. + * virtual bool getValid() const = 0; + * virtual void setTitle(const STR_String& title) = 0; + * virtual void getTitle(STR_String& title) const = 0; + * virtual void getWindowBounds(GHOST_Rect& bounds) const = 0; + * virtual void getClientBounds(GHOST_Rect& bounds) const = 0; + * virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0; + * virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height) = 0; + * virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0; + * virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0; + * virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0; + * virtual GHOST_TWindowState getState() const = 0; + * virtual GHOST_TSuccess setState(GHOST_TWindowState state) = 0; + * virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order) = 0; + * virtual GHOST_TSuccess swapBuffers() = 0; + * virtual GHOST_TSuccess activateDrawingContext() = 0; + * virtual GHOST_TSuccess invalidate() = 0; + */ + + /** + * Destructor. + * Closes the window and disposes resources allocated. + */ + virtual ~GHOST_Window(); + + /** + * Returns the current cursor shape. + * @return The current cursor shape. + */ + inline virtual GHOST_TStandardCursor getCursorShape() const; + + /** + * Set the shape of the cursor. + * @param cursor The new cursor shape type id. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape); + + /** + * Set the shape of the cursor to a custom cursor. + * @param bitmap The bitmap data for the cursor. + * @param mask The mask data for the cursor. + * @param hotX The X coordinate of the cursor hotspot. + * @param hotY The Y coordinate of the cursor hotspot. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 bitmap[16][2], + GHOST_TUns8 mask[16][2], + int hotX, + int hotY); + + /** + * Returns the visibility state of the cursor. + * @return The visibility state of the cursor. + */ + inline virtual bool getCursorVisibility() const; + + /** + * Shows or hides the cursor. + * @param visible The new visibility state of the cursor. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCursorVisibility(bool visible); + + /** + * Returns the type of drawing context used in this window. + * @return The current type of drawing context. + */ + inline virtual GHOST_TDrawingContextType getDrawingContextType(); + + /** + * Tries to install a rendering context in this window. + * Child classes do not need to overload this method. + * They should overload the installDrawingContext and removeDrawingContext instead. + * @param type The type of rendering context installed. + * @return Indication as to whether installation has succeeded. + */ + virtual GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type); + + /** + * Returns the window user data. + * @return The window user data. + */ + inline virtual GHOST_TUserDataPtr getUserData() const + { + return m_userData; + } + + /** + * Changes the window user data. + * @param data The window user data. + */ + virtual void setUserData(const GHOST_TUserDataPtr userData) + { + m_userData = userData; + } + +protected: + /** + * Tries to install a rendering context in this window. + * @param type The type of rendering context installed. + * @return Indication as to whether installation has succeeded. + */ + virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type) = 0; + + /** + * Removes the current drawing context. + * @return Indication as to whether removal has succeeded. + */ + virtual GHOST_TSuccess removeDrawingContext() = 0; + + /** + * Sets the cursor visibility on the window using + * native window system calls. + */ + virtual GHOST_TSuccess setWindowCursorVisibility(bool visible) = 0; + + /** + * Sets the cursor shape on the window using + * native window system calls. + */ + virtual GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape) = 0; + + /** + * Sets the cursor shape on the window using + * native window system calls. + */ + virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY) = 0; + + /** The the of drawing context installed in this window. */ + GHOST_TDrawingContextType m_drawingContextType; + + /** The window user data */ + GHOST_TUserDataPtr m_userData; + + /** The current visibility of the cursor */ + bool m_cursorVisible; + + /** The current shape of the cursor */ + GHOST_TStandardCursor m_cursorShape; + + /** Stores wether this is a full screen window. */ + bool m_fullScreen; + + /** Stereo visual created. Only necessary for 'real' stereo support, + * ie quad buffered stereo. This is not always possible, depends on + * the graphics h/w + */ + bool m_stereoVisual; + + /** Full-screen width */ + GHOST_TUns32 m_fullScreenWidth; + /** Full-screen height */ + GHOST_TUns32 m_fullScreenHeight; +}; + + +inline GHOST_TDrawingContextType GHOST_Window::getDrawingContextType() +{ + return m_drawingContextType; +} + +inline bool GHOST_Window::getCursorVisibility() const +{ + return m_cursorVisible; +} + +inline GHOST_TStandardCursor GHOST_Window::getCursorShape() const +{ + return m_cursorShape; +} + +#endif // _GHOST_WINDOW_H diff --git a/intern/ghost/intern/GHOST_WindowCarbon.cpp b/intern/ghost/intern/GHOST_WindowCarbon.cpp new file mode 100644 index 00000000000..0e894a2dd43 --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowCarbon.cpp @@ -0,0 +1,581 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +#include "GHOST_WindowCarbon.h" + +#include "GHOST_Debug.h" + +AGLContext GHOST_WindowCarbon::s_firstaglCtx = NULL; + +static const GLint sPreferredFormatWindow[7] = { +AGL_RGBA, GL_TRUE, +AGL_DOUBLEBUFFER, GL_TRUE, +AGL_DEPTH_SIZE, 16, +AGL_NONE, +}; + +static const GLint sPreferredFormatFullScreen[7] = { +AGL_RGBA, +AGL_DOUBLEBUFFER, +AGL_ACCELERATED, +AGL_FULLSCREEN, +AGL_DEPTH_SIZE, 16, +AGL_NONE, +}; + +GHOST_WindowCarbon::GHOST_WindowCarbon( + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + const bool stereoVisual +) : + GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone), + m_windowRef(0), + m_grafPtr(0), + m_aglCtx(0), + m_customCursor(0), + m_fullScreenDirty(false) +{ + Str255 title255; + + if (state != GHOST_kWindowStateFullScreen) { + Rect bnds = { top, left, top+height, left+width }; + Boolean visible = (state == GHOST_kWindowStateNormal) || (state == GHOST_kWindowStateMaximized); + gen2mac(title, title255); + + m_windowRef = ::NewCWindow( + nil, // Storage + &bnds, // Bounding rectangle of the window + title255, // Title of the window + visible, // Window initially visible + kWindowFullZoomGrowDocumentProc, //kWindowGrowDocumentProc, // procID + (WindowRef)-1L, // Put window before all other windows + true, // Window has minimize box + (SInt32)this); // Store a pointer to the class in the refCon + if (m_windowRef) { + m_grafPtr = ::GetWindowPort(m_windowRef); + setDrawingContextType(type); + updateDrawingContext(); + activateDrawingContext(); + } + } + else { + /* + Rect bnds = { top, left, top+height, left+width }; + gen2mac("", title255); + m_windowRef = ::NewCWindow( + nil, // Storage + &bnds, // Bounding rectangle of the window + title255, // Title of the window + 0, // Window initially visible + plainDBox, // procID + (WindowRef)-1L, // Put window before all other windows + 0, // Window has minimize box + (SInt32)this); // Store a pointer to the class in the refCon + */ + //GHOST_PRINT("GHOST_WindowCarbon::GHOST_WindowCarbon(): creating full-screen OpenGL context\n"); + setDrawingContextType(GHOST_kDrawingContextTypeOpenGL); + updateDrawingContext(); + activateDrawingContext(); + } +} + + +GHOST_WindowCarbon::~GHOST_WindowCarbon() +{ + if (m_customCursor) delete m_customCursor; + + //GHOST_PRINT("GHOST_WindowCarbon::~GHOST_WindowCarbon(): removing drawing context\n"); + setDrawingContextType(GHOST_kDrawingContextTypeNone); + if (m_windowRef) { + ::DisposeWindow(m_windowRef); + m_windowRef = 0; + } +} + +bool GHOST_WindowCarbon::getValid() const +{ + bool valid; + if (!m_fullScreen) { + valid = (m_windowRef != 0) && (m_grafPtr != 0) && ::IsValidWindowPtr(m_windowRef); + } + else { + valid = true; + } + return valid; +} + + +void GHOST_WindowCarbon::setTitle(const STR_String& title) +{ + GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setTitle(): window invalid") + Str255 title255; + gen2mac(title, title255); + ::SetWTitle(m_windowRef, title255); +} + + +void GHOST_WindowCarbon::getTitle(STR_String& title) const +{ + GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getTitle(): window invalid") + Str255 title255; + ::GetWTitle(m_windowRef, title255); + mac2gen(title255, title); +} + + +void GHOST_WindowCarbon::getWindowBounds(GHOST_Rect& bounds) const +{ + OSStatus success; + Rect rect; + GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getWindowBounds(): window invalid") + success = ::GetWindowBounds(m_windowRef, kWindowStructureRgn, &rect); + bounds.m_b = rect.bottom; + bounds.m_l = rect.left; + bounds.m_r = rect.right; + bounds.m_t = rect.top; +} + + +void GHOST_WindowCarbon::getClientBounds(GHOST_Rect& bounds) const +{ + Rect rect; + GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getClientBounds(): window invalid") + ::GetPortBounds(m_grafPtr, &rect); + bounds.m_b = rect.bottom; + bounds.m_l = rect.left; + bounds.m_r = rect.right; + bounds.m_t = rect.top; +} + + +GHOST_TSuccess GHOST_WindowCarbon::setClientWidth(GHOST_TUns32 width) +{ + GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setClientWidth(): window invalid") + GHOST_Rect cBnds, wBnds; + getClientBounds(cBnds); + if (((GHOST_TUns32)cBnds.getWidth()) != width) { + ::SizeWindow(m_windowRef, width, cBnds.getHeight(), true); + } + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_WindowCarbon::setClientHeight(GHOST_TUns32 height) +{ + GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setClientHeight(): window invalid") + GHOST_Rect cBnds, wBnds; + getClientBounds(cBnds); + if (((GHOST_TUns32)cBnds.getHeight()) != height) { + ::SizeWindow(m_windowRef, cBnds.getWidth(), height, true); + } + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_WindowCarbon::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) +{ + GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setClientSize(): window invalid") + GHOST_Rect cBnds, wBnds; + getClientBounds(cBnds); + if ((((GHOST_TUns32)cBnds.getWidth()) != width) || + (((GHOST_TUns32)cBnds.getHeight()) != height)) { + ::SizeWindow(m_windowRef, width, height, true); + } + return GHOST_kSuccess; +} + + +GHOST_TWindowState GHOST_WindowCarbon::getState() const +{ + GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getState(): window invalid") + GHOST_TWindowState state; + if (::IsWindowVisible(m_windowRef)) { + state = GHOST_kWindowStateMinimized; + } + else if (::IsWindowInStandardState(m_windowRef, nil, nil)) { + state = GHOST_kWindowStateMaximized; + } + else { + state = GHOST_kWindowStateNormal; + } + return state; +} + + +void GHOST_WindowCarbon::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const +{ + GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::screenToClient(): window invalid") + Point point; + point.h = inX; + point.v = inY; + GrafPtr oldPort; + ::GetPort(&oldPort); + ::SetPort(m_grafPtr); + ::GlobalToLocal(&point); + ::SetPort(oldPort); + outX = point.h; + outY = point.v; +} + + +void GHOST_WindowCarbon::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const +{ + GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::clientToScreen(): window invalid") + Point point; + point.h = inX; + point.v = inY; + GrafPtr oldPort; + ::GetPort(&oldPort); + ::SetPort(m_grafPtr); + ::LocalToGlobal(&point); + ::SetPort(oldPort); + outX = point.h; + outY = point.v; +} + + +GHOST_TSuccess GHOST_WindowCarbon::setState(GHOST_TWindowState state) +{ + GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setState(): window invalid") + switch (state) { + case GHOST_kWindowStateMinimized: + ::HideWindow(m_windowRef); + break; + case GHOST_kWindowStateMaximized: + case GHOST_kWindowStateNormal: + default: + ::ShowWindow(m_windowRef); + break; + } + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_WindowCarbon::setOrder(GHOST_TWindowOrder order) +{ + GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setOrder(): window invalid") + if (order == GHOST_kWindowOrderTop) { + ::BringToFront(m_windowRef); + } + else { + ::SendBehind(m_windowRef, nil); + } + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_WindowCarbon::swapBuffers() +{ + GHOST_TSuccess succeeded = GHOST_kSuccess; + if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { + if (m_aglCtx) { + ::aglSwapBuffers(m_aglCtx); + } + else { + succeeded = GHOST_kFailure; + } + } + return succeeded; +} + +GHOST_TSuccess GHOST_WindowCarbon::updateDrawingContext() +{ + GHOST_TSuccess succeeded = GHOST_kSuccess; + if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { + if (m_aglCtx) { + ::aglUpdateContext(m_aglCtx); + } + else { + succeeded = GHOST_kFailure; + } + } + return succeeded; +} + +GHOST_TSuccess GHOST_WindowCarbon::activateDrawingContext() +{ + GHOST_TSuccess succeeded = GHOST_kSuccess; + if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { + if (m_aglCtx) { + ::aglSetCurrentContext(m_aglCtx); + } + else { + succeeded = GHOST_kFailure; + } + } + return succeeded; +} + + +GHOST_TSuccess GHOST_WindowCarbon::installDrawingContext(GHOST_TDrawingContextType type) +{ + GHOST_TSuccess success = GHOST_kFailure; + switch (type) { + case GHOST_kDrawingContextTypeOpenGL: + { + if (!getValid()) break; + + AGLPixelFormat pixelFormat; + if (!m_fullScreen) { + pixelFormat = ::aglChoosePixelFormat(0, 0, sPreferredFormatWindow); + m_aglCtx = ::aglCreateContext(pixelFormat, s_firstaglCtx); + if (!m_aglCtx) break; + if (!s_firstaglCtx) s_firstaglCtx = m_aglCtx; + success = ::aglSetDrawable(m_aglCtx, m_grafPtr) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure; + } + else { + //GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): init full-screen OpenGL\n"); + pixelFormat = ::aglChoosePixelFormat(0, 0, sPreferredFormatFullScreen); + m_aglCtx = ::aglCreateContext(pixelFormat, 0); + if (!m_aglCtx) break; + if (!s_firstaglCtx) s_firstaglCtx = m_aglCtx; + //GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): created OpenGL context\n"); + //::CGGetActiveDisplayList(0, NULL, &m_numDisplays) + success = ::aglSetFullScreen(m_aglCtx, m_fullScreenWidth, m_fullScreenHeight, 75, 0) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure; + /* + if (success == GHOST_kSuccess) { + GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): init full-screen OpenGL succeeded\n"); + } + else { + GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): init full-screen OpenGL failed\n"); + } + */ + } + ::aglDestroyPixelFormat(pixelFormat); + } + break; + + case GHOST_kDrawingContextTypeNone: + success = GHOST_kSuccess; + break; + + default: + break; + } + return success; +} + + +GHOST_TSuccess GHOST_WindowCarbon::removeDrawingContext() +{ + GHOST_TSuccess success = GHOST_kFailure; + switch (m_drawingContextType) { + case GHOST_kDrawingContextTypeOpenGL: + if (m_aglCtx) { + aglSetCurrentContext(NULL); + aglSetDrawable(m_aglCtx, NULL); + //aglDestroyContext(m_aglCtx); + if (s_firstaglCtx == m_aglCtx) s_firstaglCtx = NULL; + success = ::aglDestroyContext(m_aglCtx) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure; + m_aglCtx = 0; + } + break; + case GHOST_kDrawingContextTypeNone: + success = GHOST_kSuccess; + break; + default: + break; + } + return success; +} + + +GHOST_TSuccess GHOST_WindowCarbon::invalidate() +{ + GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::invalidate(): window invalid") + if (!m_fullScreen) { + Rect rect; + ::GetPortBounds(m_grafPtr, &rect); + ::InvalWindowRect(m_windowRef, &rect); + } + else { + //EventRef event; + //OSStatus status = ::CreateEvent(NULL, kEventClassWindow, kEventWindowUpdate, 0, 0, &event); + //GHOST_PRINT("GHOST_WindowCarbon::invalidate(): created event " << status << " \n"); + //status = ::SetEventParameter(event, kEventParamDirectObject, typeWindowRef, sizeof(WindowRef), this); + //GHOST_PRINT("GHOST_WindowCarbon::invalidate(): set event parameter " << status << " \n"); + //status = ::PostEventToQueue(::GetMainEventQueue(), event, kEventPriorityStandard); + //status = ::SendEventToEventTarget(event, ::GetApplicationEventTarget()); + //GHOST_PRINT("GHOST_WindowCarbon::invalidate(): added event to queue " << status << " \n"); + m_fullScreenDirty = true; + } + return GHOST_kSuccess; +} + + +void GHOST_WindowCarbon::gen2mac(const STR_String& in, Str255 out) const +{ + STR_String tempStr = in; + int num = tempStr.Length(); + if (num > 255) num = 255; + ::memcpy(out+1, tempStr.Ptr(), num); + out[0] = num; +} + + +void GHOST_WindowCarbon::mac2gen(const Str255 in, STR_String& out) const +{ + char tmp[256]; + ::memcpy(tmp, in+1, in[0]); + tmp[in[0]] = '\0'; + out = tmp; +} + +void GHOST_WindowCarbon::loadCursor(bool visible, GHOST_TStandardCursor cursor) const +{ + static bool systemCursorVisible = true; + + if (visible != systemCursorVisible) { + if (visible) { + ::ShowCursor(); + systemCursorVisible = true; + } + else { + ::HideCursor(); + systemCursorVisible = false; + } + } + + if (cursor == GHOST_kStandardCursorCustom && m_customCursor) { + ::SetCursor( m_customCursor ); + } else { + int carbon_cursor; + +#define GCMAP(ghostCursor, carbonCursor) case ghostCursor: carbon_cursor = carbonCursor; break + switch (cursor) { + default: + GCMAP( GHOST_kStandardCursorDefault, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorRightArrow, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorLeftArrow, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorInfo, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorDestroy, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorHelp, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorCycle, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorSpray, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorWait, kThemeWatchCursor); + GCMAP( GHOST_kStandardCursorText, kThemeIBeamCursor); + GCMAP( GHOST_kStandardCursorCrosshair, kThemeCrossCursor); + GCMAP( GHOST_kStandardCursorUpDown, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorLeftRight, kThemeResizeLeftRightCursor); + GCMAP( GHOST_kStandardCursorTopSide, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorBottomSide, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorLeftSide, kThemeResizeLeftCursor); + GCMAP( GHOST_kStandardCursorRightSide, kThemeResizeRightCursor); + GCMAP( GHOST_kStandardCursorTopLeftCorner, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorTopRightCorner, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorBottomRightCorner, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorBottomLeftCorner, kThemeArrowCursor); + }; +#undef GCMAP + + ::SetThemeCursor(carbon_cursor); + } +} + + +bool GHOST_WindowCarbon::getFullScreenDirty() +{ + return m_fullScreen && m_fullScreenDirty; +} + + +GHOST_TSuccess GHOST_WindowCarbon::setWindowCursorVisibility(bool visible) +{ + if (::FrontWindow() == m_windowRef) { + loadCursor(visible, getCursorShape()); + } + + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_WindowCarbon::setWindowCursorShape(GHOST_TStandardCursor shape) +{ + if (m_customCursor) { + delete m_customCursor; + m_customCursor = 0; + } + + if (::FrontWindow() == m_windowRef) { + loadCursor(getCursorVisibility(), shape); + } + + return GHOST_kSuccess; +} + +/** Reverse the bits in a GHOST_TUns16 */ +static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt) +{ + shrt= ((shrt>>1)&0x5555) | ((shrt<<1)&0xAAAA); + shrt= ((shrt>>2)&0x3333) | ((shrt<<2)&0xCCCC); + shrt= ((shrt>>4)&0x0F0F) | ((shrt<<4)&0xF0F0); + shrt= ((shrt>>8)&0x00FF) | ((shrt<<8)&0xFF00); + return shrt; +} + +GHOST_TSuccess GHOST_WindowCarbon::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY) +{ + int y; + + if (m_customCursor) { + delete m_customCursor; + m_customCursor = 0; + } + + m_customCursor = new Cursor; + if (!m_customCursor) return GHOST_kFailure; + + for (y=0; y<16; y++) { + m_customCursor->data[y] = uns16ReverseBits((bitmap[y][0]<<0) | (bitmap[y][1]<<8)); + m_customCursor->mask[y] = uns16ReverseBits((mask[y][0]<<0) | (mask[y][1]<<8)); + } + + m_customCursor->hotSpot.h = hotX; + m_customCursor->hotSpot.v = hotY; + + if (::FrontWindow() == m_windowRef) { + loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom); + } + + return GHOST_kSuccess; +} diff --git a/intern/ghost/intern/GHOST_WindowCarbon.h b/intern/ghost/intern/GHOST_WindowCarbon.h new file mode 100644 index 00000000000..694bb8e9a5d --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowCarbon.h @@ -0,0 +1,273 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +#ifndef _GHOST_WINDOW_CARBON_H_ +#define _GHOST_WINDOW_CARBON_H_ + +#ifndef __APPLE__ +#error Apple OSX only! +#endif // __APPLE__ + +#include "GHOST_Window.h" +#include "STR_String.h" + +#include <Carbon/Carbon.h> +#include <AGL/agl.h> + + +/** + * Window on Mac OSX/Carbon. + * @author Maarten Gribnau + * @date May 23, 2001 + */ + +class GHOST_WindowCarbon : public GHOST_Window { +public: + /** + * Constructor. + * Creates a new window and opens it. + * To check if the window was created properly, use the getValid() method. + * @param title The text shown in the title bar of the window. + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param height The height the window. + * @param state The state the window is initially opened with. + * @param type The type of drawing context installed in this window. + * @param stereoVisual Stereo visual for quad buffered stereo. + */ + GHOST_WindowCarbon( + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, + const bool stereoVisual = false + ); + + /** + * Destructor. + * Closes the window and disposes resources allocated. + */ + virtual ~GHOST_WindowCarbon(); + + /** + * Returns indication as to whether the window is valid. + * @return The validity of the window. + */ + virtual bool getValid() const; + + /** + * Sets the title displayed in the title bar. + * @param title The title to display in the title bar. + */ + virtual void setTitle(const STR_String& title); + + /** + * Returns the title displayed in the title bar. + * @param title The title displayed in the title bar. + */ + virtual void getTitle(STR_String& title) const; + + /** + * Returns the window rectangle dimensions. + * The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen. + * @param bounds The bounding rectangle of the window. + */ + virtual void getWindowBounds(GHOST_Rect& bounds) const; + + /** + * Returns the client rectangle dimensions. + * The left and top members of the rectangle are always zero. + * @param bounds The bounding rectangle of the cleient area of the window. + */ + virtual void getClientBounds(GHOST_Rect& bounds) const; + + /** + * Resizes client rectangle width. + * @param width The new width of the client area of the window. + */ + virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width); + + /** + * Resizes client rectangle height. + * @param height The new height of the client area of the window. + */ + virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height); + + /** + * Resizes client rectangle. + * @param width The new width of the client area of the window. + * @param height The new height of the client area of the window. + */ + virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); + + /** + * Returns the state of the window (normal, minimized, maximized). + * @return The state of the window. + */ + virtual GHOST_TWindowState getState() const; + + /** + * Converts a point in screen coordinates to client rectangle coordinates + * @param inX The x-coordinate on the screen. + * @param inY The y-coordinate on the screen. + * @param outX The x-coordinate in the client rectangle. + * @param outY The y-coordinate in the client rectangle. + */ + virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; + + /** + * Converts a point in screen coordinates to client rectangle coordinates + * @param inX The x-coordinate in the client rectangle. + * @param inY The y-coordinate in the client rectangle. + * @param outX The x-coordinate on the screen. + * @param outY The y-coordinate on the screen. + */ + virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; + + /** + * Sets the state of the window (normal, minimized, maximized). + * @param state The state of the window. + * @return Indication of success. + */ + virtual GHOST_TSuccess setState(GHOST_TWindowState state); + + /** + * Sets the order of the window (bottom, top). + * @param order The order of the window. + * @return Indication of success. + */ + virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order); + + /** + * Swaps front and back buffers of a window. + * @return A boolean success indicator. + */ + virtual GHOST_TSuccess swapBuffers(); + + /** + * Updates the drawing context of this window. Needed + * whenever the window is changed. + * @return Indication of success. + */ + GHOST_TSuccess updateDrawingContext(); + + /** + * Activates the drawing context of this window. + * @return A boolean success indicator. + */ + virtual GHOST_TSuccess activateDrawingContext(); + + virtual void loadCursor(bool visible, GHOST_TStandardCursor cursor) const; + + /** + * Returns the dirty state of the window when in full-screen mode. + * @return Whether it is dirty. + */ + virtual bool getFullScreenDirty(); + +protected: + /** + * Tries to install a rendering context in this window. + * @param type The type of rendering context installed. + * @return Indication as to whether installation has succeeded. + */ + virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type); + + /** + * Removes the current drawing context. + * @return Indication as to whether removal has succeeded. + */ + virtual GHOST_TSuccess removeDrawingContext(); + + /** + * Invalidates the contents of this window. + * @return Indication of success. + */ + virtual GHOST_TSuccess invalidate(); + + /** + * Sets the cursor visibility on the window using + * native window system calls. + */ + virtual GHOST_TSuccess setWindowCursorVisibility(bool visible); + + /** + * Sets the cursor shape on the window using + * native window system calls. + */ + virtual GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape); + + /** + * Sets the cursor shape on the window using + * native window system calls. + */ + virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY); + + /** + * Converts a string object to a Mac Pascal string. + * @param in The string object to be converted. + * @param out The converted string. + */ + virtual void gen2mac(const STR_String& in, Str255 out) const; + + /** + * Converts a Mac Pascal string to a string object. + * @param in The string to be converted. + * @param out The converted string object. + */ + virtual void mac2gen(const Str255 in, STR_String& out) const; + + WindowRef m_windowRef; + CGrafPtr m_grafPtr; + AGLContext m_aglCtx; + + /** The first created OpenGL context (for sharing display lists) */ + static AGLContext s_firstaglCtx; + + Cursor* m_customCursor; + + /** When running in full-screen this tells whether to refresh the window. */ + bool m_fullScreenDirty; +}; + +#endif // _GHOST_WINDOW_CARBON_H_ diff --git a/intern/ghost/intern/GHOST_WindowManager.cpp b/intern/ghost/intern/GHOST_WindowManager.cpp new file mode 100644 index 00000000000..a281145ac29 --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowManager.cpp @@ -0,0 +1,190 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 11, 2001 + */ + +#include "GHOST_WindowManager.h" + +#include <algorithm> + +#include "GHOST_Debug.h" +#include "GHOST_Window.h" + + +GHOST_WindowManager::GHOST_WindowManager() +: m_fullScreenWindow(0), m_activeWindow(0) +{ +} + + +GHOST_WindowManager::~GHOST_WindowManager() +{ +} + + +GHOST_TSuccess GHOST_WindowManager::addWindow(GHOST_IWindow* window) +{ + GHOST_TSuccess success = GHOST_kFailure; + if (window) { + if (!getWindowFound(window)) { + // Store the pointer to the window + m_windows.push_back(window); + success = GHOST_kSuccess; + } + } + return success; +} + + +GHOST_TSuccess GHOST_WindowManager::removeWindow(const GHOST_IWindow* window) +{ + GHOST_TSuccess success = GHOST_kFailure; + if (window) { + if (window == m_fullScreenWindow) { + endFullScreen(); + } + else { + vector<GHOST_IWindow*>::iterator result = find(m_windows.begin(), m_windows.end(), window); + if (result != m_windows.end()) { + setWindowInactive(window); + m_windows.erase(result); + success = GHOST_kSuccess; + } + } + } + return success; +} + + +bool GHOST_WindowManager::getWindowFound(const GHOST_IWindow* window) const +{ + bool found = false; + if (window) { + if (getFullScreen() && (window == m_fullScreenWindow)) { + found = true; + } + else { + vector<GHOST_IWindow*>::const_iterator result = find(m_windows.begin(), m_windows.end(), window); + if (result != m_windows.end()) { + found = true; + } + } + } + return found; +} + + +bool GHOST_WindowManager::getFullScreen(void) const +{ + return m_fullScreenWindow != 0; +} + + +GHOST_IWindow* GHOST_WindowManager::getFullScreenWindow(void) const +{ + return m_fullScreenWindow; +} + + +GHOST_TSuccess GHOST_WindowManager::beginFullScreen(GHOST_IWindow* window, + bool stereoVisual) +{ + GHOST_TSuccess success = GHOST_kFailure; + GHOST_ASSERT(window, "GHOST_WindowManager::beginFullScreen(): invalid window"); + GHOST_ASSERT(window->getValid(), "GHOST_WindowManager::beginFullScreen(): invalid window"); + if (!getFullScreen()) { + m_fullScreenWindow = window; + setActiveWindow(m_fullScreenWindow); + success = GHOST_kSuccess; + } + return success; +} + + +GHOST_TSuccess GHOST_WindowManager::endFullScreen(void) +{ + GHOST_TSuccess success = GHOST_kFailure; + if (getFullScreen()) { + if (m_fullScreenWindow != 0) { + //GHOST_PRINT("GHOST_WindowManager::endFullScreen(): deleting full-screen window\n"); + setWindowInactive(m_fullScreenWindow); + delete m_fullScreenWindow; + //GHOST_PRINT("GHOST_WindowManager::endFullScreen(): done\n"); + m_fullScreenWindow = 0; + } + success = GHOST_kSuccess; + } + return success; +} + + +GHOST_TSuccess GHOST_WindowManager::setActiveWindow(GHOST_IWindow* window) +{ + GHOST_TSuccess success = GHOST_kSuccess; + if (window != m_activeWindow) { + if (getWindowFound(window)) { + m_activeWindow = window; + } + else { + success = GHOST_kFailure; + } + } + return success; +} + + +GHOST_IWindow* GHOST_WindowManager::getActiveWindow(void) const +{ + return m_activeWindow; +} + + +void GHOST_WindowManager::setWindowInactive(const GHOST_IWindow* window) +{ + if (window == m_activeWindow) { + m_activeWindow = 0; + } +} + + + std::vector<GHOST_IWindow *> & +GHOST_WindowManager:: +getWindows( +){ + return m_windows; +} + diff --git a/intern/ghost/intern/GHOST_WindowManager.h b/intern/ghost/intern/GHOST_WindowManager.h new file mode 100644 index 00000000000..7af86a1113c --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowManager.h @@ -0,0 +1,165 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 11, 2001 + */ + +#ifndef _GHOST_WINDOW_MANAGER_H_ +#define _GHOST_WINDOW_MANAGER_H_ + + +#ifdef WIN32 +#pragma warning (disable:4786) // suppress stl-MSVC debug info warning +#endif // WIN32 + +#include <vector> + +#include "GHOST_Rect.h" +#include "GHOST_IWindow.h" + +//class GHOST_Window; + +/** + * Manages system windows (platform independent implementation). + */ + +class GHOST_WindowManager +{ +public: + /** + * Constructor. + */ + GHOST_WindowManager(); + + /** + * Destructor. + */ + virtual ~GHOST_WindowManager(); + + /** + * Add a window to our list. + * It is only added if it is not already in the list. + * @param window Pointer to the window to be added. + * @return Indication of success. + */ + virtual GHOST_TSuccess addWindow(GHOST_IWindow* window); + + /** + * Remove a window from our list. + * @param window Pointer to the window to be removed. + * @return Indication of success. + */ + virtual GHOST_TSuccess removeWindow(const GHOST_IWindow* window); + + /** + * Returns whether the window is in our list. + * @param window Pointer to the window to query. + * @return A boolean indicator. + */ + virtual bool getWindowFound(const GHOST_IWindow* window) const; + + /** + * Returns whether one of the windows is fullscreen. + * @return A boolean indicator. + */ + virtual bool getFullScreen(void) const; + + /** + * Returns pointer to the full-screen window. + * @return The fll-screen window (0 if not in full-screen). + */ + virtual GHOST_IWindow* getFullScreenWindow(void) const; + + /** + * Activates fullscreen mode for a window. + * @param window The window displayed fullscreen. + * @return Indication of success. + */ + virtual GHOST_TSuccess beginFullScreen(GHOST_IWindow* window, const bool stereoVisual); + + /** + * Closes fullscreen mode down. + * @return Indication of success. + */ + virtual GHOST_TSuccess endFullScreen(void); + + /** + * Sets new window as active window (the window receiving events). + * There can be only one window active which should be in the current window list. + * @param window The new active window. + */ + virtual GHOST_TSuccess setActiveWindow(GHOST_IWindow* window); + + /** + * Returns the active window (the window receiving events). + * There can be only one window active which should be in the current window list. + * @return window The active window (or NULL if there is none). + */ + virtual GHOST_IWindow* getActiveWindow(void) const; + + + /** + * Set this window to be inactive (not receiving events). + * @param window The window to decativate. + */ + virtual void setWindowInactive(const GHOST_IWindow* window); + + + /** + * Return a vector of the windows currently managed by this + * class. + * @warning It is very dangerous to mess with the contents of + * this vector. Please do not destroy or add windows use the + * interface above for this, + */ + + std::vector<GHOST_IWindow *> & + getWindows( + ); + + +protected: + /** The list of windows managed */ + std::vector<GHOST_IWindow*> m_windows; + + /** Window in fullscreen state. There can be only one of this which is not in or window list. */ + GHOST_IWindow* m_fullScreenWindow; + + /** The active window. */ + GHOST_IWindow* m_activeWindow; +}; + +#endif // _GHOST_WINDOW_MANAGER_H_ diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp new file mode 100644 index 00000000000..239a020083b --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -0,0 +1,584 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +#include <string.h> + +#include "GHOST_WindowWin32.h" + +#include <GL/gl.h> + +LPCSTR GHOST_WindowWin32::s_windowClassName = "GHOST_WindowClass"; +const int GHOST_WindowWin32::s_maxTitleLength = 128; +HGLRC GHOST_WindowWin32::s_firsthGLRc = NULL; + +/* + * Color and depth bit values are not to be trusted. + * For instance, on TNT2: + * When the screen color depth is set to 16 bit, we get 5 color bits + * and 16 depth bits. + * When the screen color depth is set to 32 bit, we get 8 color bits + * and 24 depth bits. + * Just to be safe, we request high waulity settings. + */ +static PIXELFORMATDESCRIPTOR sPreferredFormat = { + sizeof(PIXELFORMATDESCRIPTOR), /* size */ + 1, /* version */ + PFD_SUPPORT_OPENGL | + PFD_DRAW_TO_WINDOW | + PFD_DOUBLEBUFFER, /* support double-buffering */ + PFD_TYPE_RGBA, /* color type */ + 32, /* prefered color depth */ + 0, 0, 0, 0, 0, 0, /* color bits (ignored) */ + 0, /* no alpha buffer */ + 0, /* alpha bits (ignored) */ + 0, /* no accumulation buffer */ + 0, 0, 0, 0, /* accum bits (ignored) */ + 32, /* depth buffer */ + 0, /* no stencil buffer */ + 0, /* no auxiliary buffers */ + PFD_MAIN_PLANE, /* main layer */ + 0, /* reserved */ + 0, 0, 0 /* no layer, visible, damage masks */ +}; + +GHOST_WindowWin32::GHOST_WindowWin32( + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + const bool stereoVisual) +: + GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, + stereoVisual), + m_hDC(0), + m_hGlRc(0), + m_hasMouseCaptured(false), + m_nPressedButtons(0), + m_customCursor(0) +{ + if (state != GHOST_kWindowStateFullScreen) { + /* Convert client size into window size */ + width += GetSystemMetrics(SM_CXSIZEFRAME)*2; + height += GetSystemMetrics(SM_CYSIZEFRAME)*2 + GetSystemMetrics(SM_CYCAPTION); + + m_hWnd = ::CreateWindow( + s_windowClassName, // pointer to registered class name + title, // pointer to window name + WS_OVERLAPPEDWINDOW, // window style + left, // horizontal position of window + top, // vertical position of window + width, // window width + height, // window height + 0, // handle to parent or owner window + 0, // handle to menu or child-window identifier + ::GetModuleHandle(0), // handle to application instance + 0); // pointer to window-creation data + } + else { + m_hWnd = ::CreateWindow( + s_windowClassName, // pointer to registered class name + title, // pointer to window name + WS_POPUP | WS_MAXIMIZE, // window style + left, // horizontal position of window + top, // vertical position of window + width, // window width + height, // window height + 0, // handle to parent or owner window + 0, // handle to menu or child-window identifier + ::GetModuleHandle(0), // handle to application instance + 0); // pointer to window-creation data + } + if (m_hWnd) { + // Store a pointer to this class in the window structure + LONG result = ::SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this); + + // Store the device context + m_hDC = ::GetDC(m_hWnd); + + // Show the window + int nCmdShow; + switch (state) { + case GHOST_kWindowStateMaximized: + nCmdShow = SW_SHOWMAXIMIZED; + break; + case GHOST_kWindowStateMinimized: + nCmdShow = SW_SHOWMINIMIZED; + break; + case GHOST_kWindowStateNormal: + default: + nCmdShow = SW_SHOWNORMAL; + break; + } + setDrawingContextType(type); + ::ShowWindow(m_hWnd, nCmdShow); + // Force an initial paint of the window + ::UpdateWindow(m_hWnd); + } +} + + +GHOST_WindowWin32::~GHOST_WindowWin32() +{ + if (m_customCursor) { + DestroyCursor(m_customCursor); + m_customCursor = NULL; + } + + setDrawingContextType(GHOST_kDrawingContextTypeNone); + if (m_hDC) { + ::ReleaseDC(m_hWnd, m_hDC); + m_hDC = 0; + } + if (m_hWnd) { + ::DestroyWindow(m_hWnd); + m_hWnd = 0; + } +} + +bool GHOST_WindowWin32::getValid() const +{ + return m_hWnd != 0; +} + + +void GHOST_WindowWin32::setTitle(const STR_String& title) +{ + ::SetWindowText(m_hWnd, title); +} + + +void GHOST_WindowWin32::getTitle(STR_String& title) const +{ + char buf[s_maxTitleLength]; + ::GetWindowText(m_hWnd, buf, s_maxTitleLength); + STR_String temp (buf); + title = buf; +} + + +void GHOST_WindowWin32::getWindowBounds(GHOST_Rect& bounds) const +{ + RECT rect; + ::GetWindowRect(m_hWnd, &rect); + bounds.m_b = rect.bottom; + bounds.m_l = rect.left; + bounds.m_r = rect.right; + bounds.m_t = rect.top; +} + + +void GHOST_WindowWin32::getClientBounds(GHOST_Rect& bounds) const +{ + RECT rect; + ::GetClientRect(m_hWnd, &rect); + bounds.m_b = rect.bottom; + bounds.m_l = rect.left; + bounds.m_r = rect.right; + bounds.m_t = rect.top; +} + + +GHOST_TSuccess GHOST_WindowWin32::setClientWidth(GHOST_TUns32 width) +{ + GHOST_TSuccess success; + GHOST_Rect cBnds, wBnds; + getClientBounds(cBnds); + if (cBnds.getWidth() != width) { + getWindowBounds(wBnds); + int cx = wBnds.getWidth() + width - cBnds.getWidth(); + int cy = wBnds.getHeight(); + success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ? + GHOST_kSuccess : GHOST_kFailure; + } + else { + success = GHOST_kSuccess; + } + return success; +} + + +GHOST_TSuccess GHOST_WindowWin32::setClientHeight(GHOST_TUns32 height) +{ + GHOST_TSuccess success; + GHOST_Rect cBnds, wBnds; + getClientBounds(cBnds); + if (cBnds.getHeight() != height) { + getWindowBounds(wBnds); + int cx = wBnds.getWidth(); + int cy = wBnds.getHeight() + height - cBnds.getHeight(); + success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ? + GHOST_kSuccess : GHOST_kFailure; + } + else { + success = GHOST_kSuccess; + } + return success; +} + + +GHOST_TSuccess GHOST_WindowWin32::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) +{ + GHOST_TSuccess success; + GHOST_Rect cBnds, wBnds; + getClientBounds(cBnds); + if ((cBnds.getWidth() != width) || (cBnds.getHeight() != height)) { + getWindowBounds(wBnds); + int cx = wBnds.getWidth() + width - cBnds.getWidth(); + int cy = wBnds.getHeight() + height - cBnds.getHeight(); + success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ? + GHOST_kSuccess : GHOST_kFailure; + } + else { + success = GHOST_kSuccess; + } + return success; +} + + +GHOST_TWindowState GHOST_WindowWin32::getState() const +{ + GHOST_TWindowState state; + if (::IsIconic(m_hWnd)) { + state = GHOST_kWindowStateMinimized; + } + else if (::IsZoomed(m_hWnd)) { + state = GHOST_kWindowStateMaximized; + } + else { + state = GHOST_kWindowStateNormal; + } + return state; +} + + +void GHOST_WindowWin32::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const +{ + POINT point = { inX, inY }; + ::ScreenToClient(m_hWnd, &point); + outX = point.x; + outY = point.y; +} + + +void GHOST_WindowWin32::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const +{ + POINT point = { inX, inY }; + ::ClientToScreen(m_hWnd, &point); + outX = point.x; + outY = point.y; +} + + +GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state) +{ + WINDOWPLACEMENT wp; + wp.length = sizeof(WINDOWPLACEMENT); + ::GetWindowPlacement(m_hWnd, &wp); + switch (state) { + case GHOST_kWindowStateMinimized: wp.showCmd = SW_SHOWMAXIMIZED; break; + case GHOST_kWindowStateMaximized: wp.showCmd = SW_SHOWMINIMIZED; break; + case GHOST_kWindowStateNormal: default: wp.showCmd = SW_SHOWNORMAL; break; + } + return ::SetWindowPlacement(m_hWnd, &wp) == TRUE ? GHOST_kSuccess : GHOST_kFailure; +} + + +GHOST_TSuccess GHOST_WindowWin32::setOrder(GHOST_TWindowOrder order) +{ + HWND hWndInsertAfter = order == GHOST_kWindowOrderTop ? HWND_TOP : HWND_BOTTOM; + return ::SetWindowPos(m_hWnd, hWndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE) == TRUE ? GHOST_kSuccess : GHOST_kFailure; +} + + +GHOST_TSuccess GHOST_WindowWin32::swapBuffers() +{ + return ::SwapBuffers(m_hDC) == TRUE ? GHOST_kSuccess : GHOST_kFailure; +} + + +GHOST_TSuccess GHOST_WindowWin32::activateDrawingContext() +{ + GHOST_TSuccess success; + if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { + if (m_hDC && m_hGlRc) { + success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure; + } + else { + success = GHOST_kFailure; + } + } + else { + success = GHOST_kSuccess; + } + return success; +} + + +GHOST_TSuccess GHOST_WindowWin32::invalidate() +{ + GHOST_TSuccess success; + if (m_hWnd) { + success = ::InvalidateRect(m_hWnd, 0, FALSE) != 0 ? GHOST_kSuccess : GHOST_kFailure; + } + else { + success = GHOST_kFailure; + } + return success; +} + + +GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextType type) +{ + GHOST_TSuccess success; + switch (type) { + case GHOST_kDrawingContextTypeOpenGL: + { + if(m_stereoVisual) + sPreferredFormat.dwFlags |= PFD_STEREO; + + // Attempt to match device context pixel format to the preferred format + int iPixelFormat = ::ChoosePixelFormat(m_hDC, &sPreferredFormat); + if (iPixelFormat == 0) { + success = GHOST_kFailure; + break; + } + if (::SetPixelFormat(m_hDC, iPixelFormat, &sPreferredFormat) == FALSE) { + success = GHOST_kFailure; + break; + } + // For debugging only: retrieve the pixel format chosen + PIXELFORMATDESCRIPTOR preferredFormat; + ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &preferredFormat); + // Create the context + m_hGlRc = ::wglCreateContext(m_hDC); + if (m_hGlRc) { + if (s_firsthGLRc) { + wglShareLists(s_firsthGLRc, m_hGlRc); + } else { + s_firsthGLRc = m_hGlRc; + } + + success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure; + } + else { + success = GHOST_kFailure; + } + } + break; + + case GHOST_kDrawingContextTypeNone: + success = GHOST_kSuccess; + break; + + default: + success = GHOST_kFailure; + } + return success; +} + + +GHOST_TSuccess GHOST_WindowWin32::removeDrawingContext() +{ + GHOST_TSuccess success; + switch (m_drawingContextType) { + case GHOST_kDrawingContextTypeOpenGL: + if (m_hGlRc) { + success = ::wglDeleteContext(m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure; + if (m_hGlRc == s_firsthGLRc) { + s_firsthGLRc = NULL; + } + m_hGlRc = 0; + } + else { + success = GHOST_kFailure; + } + break; + case GHOST_kDrawingContextTypeNone: + success = GHOST_kSuccess; + break; + default: + success = GHOST_kFailure; + } + return success; +} + +void GHOST_WindowWin32::lostMouseCapture() +{ + if (m_hasMouseCaptured) { + m_hasMouseCaptured = false; + m_nPressedButtons = 0; + } +} + +void GHOST_WindowWin32::registerMouseClickEvent(bool press) +{ + if (press) { + if (!m_hasMouseCaptured) { + ::SetCapture(m_hWnd); + m_hasMouseCaptured = true; + } + m_nPressedButtons++; + } else { + if (m_nPressedButtons) { + m_nPressedButtons--; + if (!m_nPressedButtons) { + ::ReleaseCapture(); + m_hasMouseCaptured = false; + } + } + } +} + + +void GHOST_WindowWin32::loadCursor(bool visible, GHOST_TStandardCursor cursor) const +{ + if (!visible) { + while (::ShowCursor(FALSE) >= 0); + } + else { + while (::ShowCursor(TRUE) < 0); + } + + if (cursor == GHOST_kStandardCursorCustom && m_customCursor) { + ::SetCursor( m_customCursor ); + } else { + // Convert GHOST cursor to Windows OEM cursor + bool success = true; + LPCSTR id; + switch (cursor) { + case GHOST_kStandardCursorDefault: id = IDC_ARROW; + case GHOST_kStandardCursorRightArrow: id = IDC_ARROW; break; + case GHOST_kStandardCursorLeftArrow: id = IDC_ARROW; break; + case GHOST_kStandardCursorInfo: id = IDC_SIZEALL; break; // Four-pointed arrow pointing north, south, east, and west + case GHOST_kStandardCursorDestroy: id = IDC_NO; break; // Slashed circle + case GHOST_kStandardCursorHelp: id = IDC_HELP; break; // Arrow and question mark + case GHOST_kStandardCursorCycle: id = IDC_NO; break; // Slashed circle + case GHOST_kStandardCursorSpray: id = IDC_SIZEALL; break; // Four-pointed arrow pointing north, south, east, and west + case GHOST_kStandardCursorWait: id = IDC_WAIT; break; // Hourglass + case GHOST_kStandardCursorText: id = IDC_IBEAM; break; // I-beam + case GHOST_kStandardCursorCrosshair: id = IDC_CROSS; break; // Crosshair + case GHOST_kStandardCursorUpDown: id = IDC_SIZENS; break; // Double-pointed arrow pointing north and south + case GHOST_kStandardCursorLeftRight: id = IDC_SIZEWE; break; // Double-pointed arrow pointing west and east + case GHOST_kStandardCursorTopSide: id = IDC_UPARROW; break; // Vertical arrow + case GHOST_kStandardCursorBottomSide: id = IDC_SIZENS; break; + case GHOST_kStandardCursorLeftSide: id = IDC_SIZEWE; break; + case GHOST_kStandardCursorTopLeftCorner: id = IDC_SIZENWSE; break; + case GHOST_kStandardCursorTopRightCorner: id = IDC_SIZENESW; break; + case GHOST_kStandardCursorBottomRightCorner: id = IDC_SIZENWSE; break; + case GHOST_kStandardCursorBottomLeftCorner: id = IDC_SIZENESW; break; + default: + success = false; + } + + if (success) { + HCURSOR hCursor = ::SetCursor(::LoadCursor(0, id)); + } + } +} + +GHOST_TSuccess GHOST_WindowWin32::setWindowCursorVisibility(bool visible) +{ + if (::GetForegroundWindow() == m_hWnd) { + loadCursor(visible, getCursorShape()); + } + + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cursorShape) +{ + if (m_customCursor) { + DestroyCursor(m_customCursor); + m_customCursor = NULL; + } + + if (::GetForegroundWindow() == m_hWnd) { + loadCursor(getCursorVisibility(), cursorShape); + } + + return GHOST_kSuccess; +} + +/** Reverse the bits in a GHOST_TUns16 */ +static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt) +{ + shrt= ((shrt>>1)&0x5555) | ((shrt<<1)&0xAAAA); + shrt= ((shrt>>2)&0x3333) | ((shrt<<2)&0xCCCC); + shrt= ((shrt>>4)&0x0F0F) | ((shrt<<4)&0xF0F0); + shrt= ((shrt>>8)&0x00FF) | ((shrt<<8)&0xFF00); + return shrt; +} + +GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY) +{ + GHOST_TUns32 andData[32]; + GHOST_TUns32 xorData[32]; + int y; + + if (m_customCursor) { + DestroyCursor(m_customCursor); + m_customCursor = NULL; + } + + memset(&andData, 0xFF, sizeof(andData)); + memset(&xorData, 0, sizeof(xorData)); + + for (y=0; y<16; y++) { + GHOST_TUns32 fullBitRow = uns16ReverseBits((bitmap[y][0]<<8) | (bitmap[y][1]<<0)); + GHOST_TUns32 fullMaskRow = uns16ReverseBits((mask[y][0]<<8) | (mask[y][1]<<0)); + + xorData[y]= fullBitRow & fullMaskRow; + andData[y]= ~fullMaskRow; + } + + m_customCursor = ::CreateCursor(::GetModuleHandle(0), hotX, hotY, 32, 32, andData, xorData); + if (!m_customCursor) { + return GHOST_kFailure; + } + + if (::GetForegroundWindow() == m_hWnd) { + loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom); + } + + return GHOST_kSuccess; +} + diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h new file mode 100644 index 00000000000..c29e61aabbb --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -0,0 +1,276 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +#ifndef _GHOST_WINDOW_WIN32_H_ +#define _GHOST_WINDOW_WIN32_H_ + +#ifndef WIN32 +#error WIN32 only! +#endif // WIN32 + +#include "GHOST_Window.h" + +#include <windows.h> + + +/** + * GHOST window on M$ Windows OSs. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +class GHOST_WindowWin32 : public GHOST_Window { +public: + /** + * Constructor. + * Creates a new window and opens it. + * To check if the window was created properly, use the getValid() method. + * @param title The text shown in the title bar of the window. + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param height The height the window. + * @param state The state the window is initially opened with. + * @param type The type of drawing context installed in this window. + * @param stereoVisual Stereo visual for quad buffered stereo. + */ + GHOST_WindowWin32( + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, + const bool stereoVisual = false + ); + + /** + * Destructor. + * Closes the window and disposes resources allocated. + */ + virtual ~GHOST_WindowWin32(); + + /** + * Returns indication as to whether the window is valid. + * @return The validity of the window. + */ + virtual bool getValid() const; + + /** + * Sets the title displayed in the title bar. + * @param title The title to display in the title bar. + */ + virtual void setTitle(const STR_String& title); + + /** + * Returns the title displayed in the title bar. + * @param title The title displayed in the title bar. + */ + virtual void getTitle(STR_String& title) const; + + /** + * Returns the window rectangle dimensions. + * The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen. + * @param bounds The bounding rectangle of the window. + */ + virtual void getWindowBounds(GHOST_Rect& bounds) const; + + /** + * Returns the client rectangle dimensions. + * The left and top members of the rectangle are always zero. + * @param bounds The bounding rectangle of the cleient area of the window. + */ + virtual void getClientBounds(GHOST_Rect& bounds) const; + + /** + * Resizes client rectangle width. + * @param width The new width of the client area of the window. + */ + virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width); + + /** + * Resizes client rectangle height. + * @param height The new height of the client area of the window. + */ + virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height); + + /** + * Resizes client rectangle. + * @param width The new width of the client area of the window. + * @param height The new height of the client area of the window. + */ + virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); + + /** + * Returns the state of the window (normal, minimized, maximized). + * @return The state of the window. + */ + virtual GHOST_TWindowState getState() const; + + /** + * Converts a point in screen coordinates to client rectangle coordinates + * @param inX The x-coordinate on the screen. + * @param inY The y-coordinate on the screen. + * @param outX The x-coordinate in the client rectangle. + * @param outY The y-coordinate in the client rectangle. + */ + virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; + + /** + * Converts a point in screen coordinates to client rectangle coordinates + * @param inX The x-coordinate in the client rectangle. + * @param inY The y-coordinate in the client rectangle. + * @param outX The x-coordinate on the screen. + * @param outY The y-coordinate on the screen. + */ + virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; + + /** + * Sets the state of the window (normal, minimized, maximized). + * @param state The state of the window. + * @return Indication of success. + */ + virtual GHOST_TSuccess setState(GHOST_TWindowState state); + + /** + * Sets the order of the window (bottom, top). + * @param order The order of the window. + * @return Indication of success. + */ + virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order); + + /** + * Swaps front and back buffers of a window. + * @return Indication of success. + */ + virtual GHOST_TSuccess swapBuffers(); + + /** + * Activates the drawing context of this window. + * @return Indication of success. + */ + virtual GHOST_TSuccess activateDrawingContext(); + + /** + * Invalidates the contents of this window. + */ + virtual GHOST_TSuccess invalidate(); + + /** + * Returns the name of the window class. + * @return The name of the window class. + */ + static LPCSTR getWindowClassName() { return s_windowClassName; } + + /** + * Register a mouse click event (should be called + * for any real button press, controls mouse + * capturing). + * + * @param press True the event was a button press. + */ + void registerMouseClickEvent(bool press); + + /** + * Inform the window that it has lost mouse capture, + * called in response to native window system messages. + */ + void lostMouseCapture(); + + /** + * Loads the windows equivalent of a standard GHOST cursor. + * @param visible Flag for cursor visibility. + * @param cursorShape The cursor shape. + */ + void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const; + + +protected: + /** + * Tries to install a rendering context in this window. + * @param type The type of rendering context installed. + * @return Indication of success. + */ + virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type); + + /** + * Removes the current drawing context. + * @return Indication of success. + */ + virtual GHOST_TSuccess removeDrawingContext(); + + /** + * Sets the cursor visibility on the window using + * native window system calls. + */ + virtual GHOST_TSuccess setWindowCursorVisibility(bool visible); + + /** + * Sets the cursor shape on the window using + * native window system calls. + */ + virtual GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape); + + /** + * Sets the cursor shape on the window using + * native window system calls. + */ + virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY); + + /** Window handle. */ + HWND m_hWnd; + /** Device context handle. */ + HDC m_hDC; + /** OpenGL rendering context. */ + HGLRC m_hGlRc; + /** The first created OpenGL context (for sharing display lists) */ + static HGLRC s_firsthGLRc; + /** Flag for if window has captured the mouse */ + bool m_hasMouseCaptured; + /** Count of number of pressed buttons */ + int m_nPressedButtons; + /** HCURSOR structure of the custom cursor */ + HCURSOR m_customCursor; + + static LPCSTR s_windowClassName; + static const int s_maxTitleLength; +}; + +#endif // _GHOST_WINDOW_WIN32_H_ diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp new file mode 100755 index 00000000000..81592c1984c --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -0,0 +1,714 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "GHOST_WindowX11.h" + +#include "GHOST_SystemX11.h" +#include "STR_String.h" +#include "GHOST_Debug.h" + +// For standard X11 cursors +#include <X11/cursorfont.h> + +// For obscure full screen mode stuuf +// lifted verbatim from blut. + +typedef struct { + long flags; + long functions; + long decorations; + long input_mode; +} MotifWmHints; + +#define MWM_HINTS_DECORATIONS (1L << 1) + +GLXContext GHOST_WindowX11::s_firstContext = NULL; + +GHOST_WindowX11:: +GHOST_WindowX11( + GHOST_SystemX11 *system, + Display * display, + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + const bool stereoVisual +) : + GHOST_Window(title,left,top,width,height,state,type), + m_display(display), + m_valid_setup (false), + m_system (system), + m_invalid_window(false), + m_context(NULL), + m_empty_cursor(None), + m_custom_cursor(None) +{ + + // Set up the minimum atrributes that we require and see if + // X can find us a visual matching those requirements. + + int attributes[40], i = 0; + + if(m_stereoVisual) + attributes[i++] = GLX_STEREO; + + attributes[i++] = GLX_RGBA; + attributes[i++] = GLX_DOUBLEBUFFER; + attributes[i++] = GLX_RED_SIZE; attributes[i++] = 1; + attributes[i++] = GLX_BLUE_SIZE; attributes[i++] = 1; + attributes[i++] = GLX_GREEN_SIZE; attributes[i++] = 1; + attributes[i++] = GLX_DEPTH_SIZE; attributes[i++] = 1; + attributes[i] = None; + + m_visual = glXChooseVisual(m_display, DefaultScreen(m_display), attributes); + + if (m_visual == NULL) { + // barf : no visual meeting these requirements could be found. + return; + } + + // Create a bunch of attributes needed to create an X window. + + + // First create a colormap for the window and visual. + // This seems pretty much a legacy feature as we are in rgba mode anyway. + + XSetWindowAttributes xattributes; + memset(&xattributes, 0, sizeof(xattributes)); + + xattributes.colormap= XCreateColormap( + m_display, + RootWindow(m_display, m_visual->screen), + m_visual->visual, + AllocNone + ); + + xattributes.border_pixel= 0; + + // Specify which events we are interested in hearing. + + xattributes.event_mask= + ExposureMask | StructureNotifyMask | + KeyPressMask | KeyReleaseMask | + EnterWindowMask | LeaveWindowMask | + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask | FocusChangeMask; + + // create the window! + + m_window = + XCreateWindow( + m_display, + RootWindow(m_display, m_visual->screen), + left, + top, + width, + height, + 0, // no border. + m_visual->depth, + InputOutput, + m_visual->visual, + CWBorderPixel|CWColormap|CWEventMask, + &xattributes + ); + + // Are we in fullscreen mode - then include + // some obscure blut code to remove decorations. + + if (state == GHOST_kWindowStateFullScreen) { + + MotifWmHints hints; + Atom atom; + + atom = XInternAtom(m_display, "_MOTIF_WM_HINTS", False); + + if (atom == None) { + GHOST_PRINT("Could not intern X atom for _MOTIF_WM_HINTS.\n"); + } else { + hints.flags = MWM_HINTS_DECORATIONS; + hints.decorations = 0; /* Absolutely no decorations. */ + // other hints.decorations make no sense + // you can't select individual decorations + + XChangeProperty(m_display, m_window, + atom, atom, 32, + PropModeReplace, (unsigned char *) &hints, 4); + } + } + + // Create some hints for the window manager on how + // we want this window treated. + + XSizeHints * xsizehints = XAllocSizeHints(); + xsizehints->flags = USPosition | USSize; + xsizehints->x = left; + xsizehints->y = top; + xsizehints->width = width; + xsizehints->height = height; + XSetWMNormalHints(m_display, m_window, xsizehints); + XFree(xsizehints); + + setTitle(title); + + // now set up the rendering context. + if (installDrawingContext(type) == GHOST_kSuccess) { + m_valid_setup = true; + GHOST_PRINT("Created window\n"); + } + + XMapWindow(m_display, m_window); + GHOST_PRINT("Mapped window\n"); + + XFlush(m_display); +} + + Window +GHOST_WindowX11:: +getXWindow( +){ + return m_window; +} + + bool +GHOST_WindowX11:: +getValid( +) const { + return m_valid_setup; +} + + void +GHOST_WindowX11:: +setTitle( + const STR_String& title +){ + XStoreName(m_display,m_window,title); + XFlush(m_display); +} + + void +GHOST_WindowX11:: +getTitle( + STR_String& title +) const { + char *name = NULL; + + XFetchName(m_display,m_window,&name); + title= name?name:"untitled"; + XFree(name); +} + + void +GHOST_WindowX11:: +getWindowBounds( + GHOST_Rect& bounds +) const { + // Getting the window bounds under X11 is not + // really supported (nor should it be desired). + getClientBounds(bounds); +} + + void +GHOST_WindowX11:: +getClientBounds( + GHOST_Rect& bounds +) const { + Window root_return; + int x_return,y_return; + unsigned int w_return,h_return,border_w_return,depth_return; + GHOST_TInt32 screen_x, screen_y; + + XGetGeometry(m_display,m_window,&root_return,&x_return,&y_return, + &w_return,&h_return,&border_w_return,&depth_return); + + clientToScreen(0, 0, screen_x, screen_y); + + bounds.m_l = screen_x; + bounds.m_r = bounds.m_l + w_return; + bounds.m_t = screen_y; + bounds.m_b = bounds.m_t + h_return; + +} + + GHOST_TSuccess +GHOST_WindowX11:: +setClientWidth( + GHOST_TUns32 width +){ + XWindowChanges values; + unsigned int value_mask= CWWidth; + values.width = width; + XConfigureWindow(m_display,m_window,value_mask,&values); + + return GHOST_kSuccess; +} + + GHOST_TSuccess +GHOST_WindowX11:: +setClientHeight( + GHOST_TUns32 height +){ + XWindowChanges values; + unsigned int value_mask= CWHeight; + values.height = height; + XConfigureWindow(m_display,m_window,value_mask,&values); + return GHOST_kSuccess; + +} + + GHOST_TSuccess +GHOST_WindowX11:: +setClientSize( + GHOST_TUns32 width, + GHOST_TUns32 height +){ + XWindowChanges values; + unsigned int value_mask= CWWidth | CWHeight; + values.width = width; + values.height = height; + XConfigureWindow(m_display,m_window,value_mask,&values); + return GHOST_kSuccess; + +} + + void +GHOST_WindowX11:: +screenToClient( + GHOST_TInt32 inX, + GHOST_TInt32 inY, + GHOST_TInt32& outX, + GHOST_TInt32& outY +) const { + // not sure about this one! + + int ax,ay; + Window temp; + + XTranslateCoordinates( + m_display, + RootWindow(m_display, m_visual->screen), + m_window, + inX, + inY, + &ax, + &ay, + &temp + ); + outX = ax; + outY = ay; +} + + void +GHOST_WindowX11:: +clientToScreen( + GHOST_TInt32 inX, + GHOST_TInt32 inY, + GHOST_TInt32& outX, + GHOST_TInt32& outY +) const { + int ax,ay; + Window temp; + + XTranslateCoordinates( + m_display, + m_window, + RootWindow(m_display, m_visual->screen), + inX, + inY, + &ax, + &ay, + &temp + ); + outX = ax; + outY = ay; +} + + + GHOST_TWindowState +GHOST_WindowX11:: +getState( +) const { + //FIXME + return GHOST_kWindowStateNormal; +} + + GHOST_TSuccess +GHOST_WindowX11:: +setState( + GHOST_TWindowState state +){ + //TODO + + if (state == getState()) { + return GHOST_kSuccess; + } else { + return GHOST_kFailure; + } + +} + + GHOST_TSuccess +GHOST_WindowX11:: +setOrder( + GHOST_TWindowOrder order +){ + if (order == GHOST_kWindowOrderTop) { + XRaiseWindow(m_display,m_window); + XFlush(m_display); + } else if (order == GHOST_kWindowOrderBottom) { + XLowerWindow(m_display,m_window); + XFlush(m_display); + } else { + return GHOST_kFailure; + } + + return GHOST_kSuccess; +} + + GHOST_TSuccess +GHOST_WindowX11:: +swapBuffers( +){ + if (getDrawingContextType() == GHOST_kDrawingContextTypeOpenGL) { + glXSwapBuffers(m_display,m_window); + return GHOST_kSuccess; + } else { + return GHOST_kFailure; + } +} + + GHOST_TSuccess +GHOST_WindowX11:: +activateDrawingContext( +){ + if (m_context !=NULL) { + glXMakeCurrent(m_display, m_window,m_context); + return GHOST_kSuccess; + } + return GHOST_kFailure; +} + + GHOST_TSuccess +GHOST_WindowX11:: +invalidate( +){ + + // So the idea of this function is to generate an expose event + // for the window. + // Unfortunately X does not handle expose events for you and + // it is the client's job to refresh the dirty part of the window. + // We need to queue up invalidate calls and generate GHOST events + // for them in the system. + + // We implement this by setting a boolean in this class to concatenate + // all such calls into a single event for this window. + + // At the same time we queue the dirty windows in the system class + // and generate events for them at the next processEvents call. + + if (m_invalid_window == false) { + m_system->addDirtyWindow(this); + m_invalid_window = true; + } + + return GHOST_kSuccess; +} + +/** + * called by the X11 system implementation when expose events + * for the window have been pushed onto the GHOST queue + */ + + void +GHOST_WindowX11:: +validate( +){ + m_invalid_window = false; +} + + +/** + * Destructor. + * Closes the window and disposes resources allocated. + */ + +GHOST_WindowX11:: +~GHOST_WindowX11( +){ + std::map<unsigned int, Cursor>::iterator it = m_standard_cursors.begin(); + for (; it != m_standard_cursors.end(); it++) { + XFreeCursor(m_display, it->second); + } + + if (m_empty_cursor) { + XFreeCursor(m_display, m_empty_cursor); + } + if (m_custom_cursor) { + XFreeCursor(m_display, m_custom_cursor); + } + + XDestroyWindow(m_display, m_window); + if (m_context) { + if (m_context == s_firstContext) { + s_firstContext = NULL; + } + glXDestroyContext(m_display, m_context); + } + XFree(m_visual); +} + + + + +/** + * Tries to install a rendering context in this window. + * @param type The type of rendering context installed. + * @return Indication as to whether installation has succeeded. + */ + GHOST_TSuccess +GHOST_WindowX11:: +installDrawingContext( + GHOST_TDrawingContextType type +){ + // only support openGL for now. + GHOST_TSuccess success; + switch (type) { + case GHOST_kDrawingContextTypeOpenGL: + m_context = glXCreateContext(m_display, m_visual, s_firstContext, True); + if (m_context !=NULL) { + if (!s_firstContext) { + s_firstContext = m_context; + } + glXMakeCurrent(m_display, m_window,m_context); + success = GHOST_kSuccess; + } else { + success = GHOST_kFailure; + } + + break; + + case GHOST_kDrawingContextTypeNone: + success = GHOST_kSuccess; + break; + + default: + success = GHOST_kFailure; + } + return success; +} + + + +/** + * Removes the current drawing context. + * @return Indication as to whether removal has succeeded. + */ + GHOST_TSuccess +GHOST_WindowX11:: +removeDrawingContext( +){ + GHOST_TSuccess success; + + if (m_context != NULL) { + glXDestroyContext(m_display, m_context); + success = GHOST_kSuccess; + } else { + success = GHOST_kFailure; + } + return success; +} + + + Cursor +GHOST_WindowX11:: +getStandardCursor( + GHOST_TStandardCursor g_cursor +){ + unsigned int xcursor_id; + +#define GtoX(gcurs, xcurs) case gcurs: xcursor_id = xcurs + switch (g_cursor) { + GtoX(GHOST_kStandardCursorRightArrow, XC_arrow); break; + GtoX(GHOST_kStandardCursorLeftArrow, XC_top_left_arrow); break; + GtoX(GHOST_kStandardCursorInfo, XC_hand1); break; + GtoX(GHOST_kStandardCursorDestroy, XC_pirate); break; + GtoX(GHOST_kStandardCursorHelp, XC_question_arrow); break; + GtoX(GHOST_kStandardCursorCycle, XC_exchange); break; + GtoX(GHOST_kStandardCursorSpray, XC_spraycan); break; + GtoX(GHOST_kStandardCursorWait, XC_watch); break; + GtoX(GHOST_kStandardCursorText, XC_xterm); break; + GtoX(GHOST_kStandardCursorCrosshair, XC_crosshair); break; + GtoX(GHOST_kStandardCursorUpDown, XC_sb_v_double_arrow); break; + GtoX(GHOST_kStandardCursorLeftRight, XC_sb_h_double_arrow); break; + GtoX(GHOST_kStandardCursorTopSide, XC_top_side); break; + GtoX(GHOST_kStandardCursorBottomSide, XC_bottom_side); break; + GtoX(GHOST_kStandardCursorLeftSide, XC_left_side); break; + GtoX(GHOST_kStandardCursorRightSide, XC_right_side); break; + GtoX(GHOST_kStandardCursorTopLeftCorner, XC_top_left_corner); break; + GtoX(GHOST_kStandardCursorTopRightCorner, XC_top_right_corner); break; + GtoX(GHOST_kStandardCursorBottomRightCorner, XC_bottom_right_corner); break; + GtoX(GHOST_kStandardCursorBottomLeftCorner, XC_bottom_left_corner); break; + default: + xcursor_id = 0; + } +#undef GtoX + + if (xcursor_id) { + Cursor xcursor = m_standard_cursors[xcursor_id]; + + if (!xcursor) { + xcursor = XCreateFontCursor(m_display, xcursor_id); + + m_standard_cursors[xcursor_id] = xcursor; + } + + return xcursor; + } else { + return None; + } +} + + Cursor +GHOST_WindowX11:: +getEmptyCursor( +) { + if (!m_empty_cursor) { + Pixmap blank; + XColor dummy; + char data[1] = {0}; + + /* make a blank cursor */ + blank = XCreateBitmapFromData ( + m_display, + RootWindow(m_display,DefaultScreen(m_display)), + data, 1, 1 + ); + + m_empty_cursor = XCreatePixmapCursor(m_display, blank, blank, &dummy, &dummy, 0, 0); + XFreePixmap(m_display, blank); + } + + return m_empty_cursor; +} + + GHOST_TSuccess +GHOST_WindowX11:: +setWindowCursorVisibility( + bool visible +){ + Cursor xcursor; + + if (visible) { + xcursor = getStandardCursor( getCursorShape() ); + } else { + xcursor = getEmptyCursor(); + } + + XDefineCursor(m_display, m_window, xcursor); + XFlush(m_display); + + return GHOST_kSuccess; +} + + GHOST_TSuccess +GHOST_WindowX11:: +setWindowCursorShape( + GHOST_TStandardCursor shape +){ + Cursor xcursor = getStandardCursor( shape ); + + XDefineCursor(m_display, m_window, xcursor); + XFlush(m_display); + + return GHOST_kSuccess; +} + + GHOST_TSuccess +GHOST_WindowX11:: +setWindowCustomCursorShape( + GHOST_TUns8 bitmap[16][2], + GHOST_TUns8 mask[16][2], + int hotX, + int hotY +){ + Pixmap bitmap_pix, mask_pix; + XColor fg, bg; + + if(XAllocNamedColor(m_display, DefaultColormap(m_display, DefaultScreen(m_display)), + "White", &fg, &fg) == 0) return GHOST_kFailure; + if(XAllocNamedColor(m_display, DefaultColormap(m_display, DefaultScreen(m_display)), + "Red", &bg, &bg) == 0) return GHOST_kFailure; + + if (m_custom_cursor) { + XFreeCursor(m_display, m_custom_cursor); + } + + bitmap_pix = XCreateBitmapFromData(m_display, m_window, (char*) bitmap, 16, 16); + mask_pix = XCreateBitmapFromData(m_display, m_window, (char*) mask, 16, 16); + + m_custom_cursor = XCreatePixmapCursor(m_display, bitmap_pix, mask_pix, &fg, &bg, hotX, hotY); + XDefineCursor(m_display, m_window, m_custom_cursor); + XFlush(m_display); + + XFreePixmap(m_display, bitmap_pix); + XFreePixmap(m_display, mask_pix); + + return GHOST_kSuccess; +} + +/* + +void glutCustomCursor(char *data1, char *data2, int size) +{ + Pixmap source, mask; + Cursor cursor; + XColor fg, bg; + + if(XAllocNamedColor(__glutDisplay, DefaultColormap(__glutDisplay, __glutScreen), + "White", &fg, &fg) == 0) return; + if(XAllocNamedColor(__glutDisplay, DefaultColormap(__glutDisplay, __glutScreen), + "Red", &bg, &bg) == 0) return; + + + source= XCreateBitmapFromData(__glutDisplay, xdraw, data2, size, size); + mask= XCreateBitmapFromData(__glutDisplay, xdraw, data1, size, size); + + cursor= XCreatePixmapCursor(__glutDisplay, source, mask, &fg, &bg, 7, 7); + + XFreePixmap(__glutDisplay, source); + XFreePixmap(__glutDisplay, mask); + + XDefineCursor(__glutDisplay, xdraw, cursor); +} + +*/ diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h new file mode 100755 index 00000000000..dd38496c903 --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -0,0 +1,292 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 7, 2001 + */ + +#ifndef _GHOST_WINDOWX11_H_ +#define _GHOST_WINDOWX11_H_ + +#include "GHOST_Window.h" +#include <X11/Xlib.h> +#include <GL/glx.h> + +#include <map> + +class STR_String; +class GHOST_SystemX11; + +/** + * X11 implementation of GHOST_IWindow. + * Dimensions are given in screen coordinates that are relative to the upper-left corner of the screen. + * @author Laurence Bourn + * @date October 26, 2001 + */ + +class GHOST_WindowX11 : public GHOST_Window +{ +public: + /** + * Constructor. + * Creates a new window and opens it. + * To check if the window was created properly, use the getValid() method. + * @param title The text shown in the title bar of the window. + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param height The height the window. + * @param state The state the window is initially opened with. + * @param type The type of drawing context installed in this window. + * @param stereoVisual Stereo visual for quad buffered stereo. + */ + GHOST_WindowX11( + GHOST_SystemX11 *system, + Display * display, + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, + const bool stereoVisual = false + ); + + bool + getValid( + ) const; + + void + setTitle(const STR_String& title); + + void + getTitle( + STR_String& title + ) const; + + void + getWindowBounds( + GHOST_Rect& bounds + ) const; + + void + getClientBounds( + GHOST_Rect& bounds + ) const; + + GHOST_TSuccess + setClientWidth( + GHOST_TUns32 width + ); + + GHOST_TSuccess + setClientHeight( + GHOST_TUns32 height + ); + + GHOST_TSuccess + setClientSize( + GHOST_TUns32 width, + GHOST_TUns32 height + ); + + void + screenToClient( + GHOST_TInt32 inX, + GHOST_TInt32 inY, + GHOST_TInt32& outX, + GHOST_TInt32& outY + ) const; + + void + clientToScreen( + GHOST_TInt32 inX, + GHOST_TInt32 inY, + GHOST_TInt32& outX, + GHOST_TInt32& outY + ) const; + + GHOST_TWindowState + getState( + ) const ; + + GHOST_TSuccess + setState( + GHOST_TWindowState state + ); + + GHOST_TSuccess + setOrder( + GHOST_TWindowOrder order + ); + + GHOST_TSuccess + swapBuffers( + ); + + GHOST_TSuccess + activateDrawingContext( + ); + GHOST_TSuccess + invalidate( + ); + + /** + * Destructor. + * Closes the window and disposes resources allocated. + */ + ~GHOST_WindowX11(); + + /** + * @section + * X11 system specific calls. + */ + + /** + * The reverse of invalidate! Tells this window + * that all events for it have been pushed into + * the GHOST event queue. + */ + + void + validate( + ); + + /** + * Return a handle to the x11 window type. + */ + Window + getXWindow( + ); + +protected: + /** + * Tries to install a rendering context in this window. + * @param type The type of rendering context installed. + * @return Indication as to whether installation has succeeded. + */ + GHOST_TSuccess + installDrawingContext( + GHOST_TDrawingContextType type + ); + + /** + * Removes the current drawing context. + * @return Indication as to whether removal has succeeded. + */ + GHOST_TSuccess + removeDrawingContext( + ); + + /** + * Sets the cursor visibility on the window using + * native window system calls. + */ + GHOST_TSuccess + setWindowCursorVisibility( + bool visible + ); + + /** + * Sets the cursor shape on the window using + * native window system calls. + */ + GHOST_TSuccess + setWindowCursorShape( + GHOST_TStandardCursor shape + ); + + /** + * Sets the cursor shape on the window using + * native window system calls. + */ + GHOST_TSuccess + setWindowCustomCursorShape( + GHOST_TUns8 bitmap[16][2], + GHOST_TUns8 mask[16][2], + int hotX, + int hotY + ); + +private : + + /// Force use of public constructor. + + GHOST_WindowX11( + ); + + GHOST_WindowX11( + const GHOST_WindowX11 & + ); + + Cursor + getStandardCursor( + GHOST_TStandardCursor g_cursor + ); + + Cursor + getEmptyCursor( + ); + + GLXContext m_context; + Window m_window; + Display *m_display; + XVisualInfo *m_visual; + + /** The first created OpenGL context (for sharing display lists) */ + static GLXContext s_firstContext; + + /// A pointer to the typed system class. + + GHOST_SystemX11 * m_system; + + bool m_valid_setup; + + /** Used to concatenate calls to invalidate() on this window. */ + bool m_invalid_window; + + /** XCursor structure of an empty (blank) cursor */ + Cursor m_empty_cursor; + + /** XCursor structure of the custom cursor */ + Cursor m_custom_cursor; + + /** Cache of XC_* ID's to XCursor structures */ + std::map<unsigned int, Cursor> m_standard_cursors; +}; + + +#endif // _GHOST_WINDOWX11_H_ diff --git a/intern/ghost/intern/Makefile b/intern/ghost/intern/Makefile new file mode 100644 index 00000000000..8107a73ce58 --- /dev/null +++ b/intern/ghost/intern/Makefile @@ -0,0 +1,65 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# ghost intern Makefile +# + +LIBNAME = ghost +DIR = $(OCGDIR)/intern/$(LIBNAME) + +CCSRCS = GHOST_Buttons.cpp GHOST_System.cpp GHOST_Window.cpp +CCSRCS += GHOST_EventManager.cpp GHOST_EventPrinter.cpp GHOST_WindowManager.cpp +CCSRCS += GHOST_ISystem.cpp GHOST_ModifierKeys.cpp GHOST_TimerManager.cpp +CCSRCS += GHOST_Rect.cpp GHOST_DisplayManager.cpp GHOST_C-api.cpp +CCSRCS += GHOST_CallbackEventConsumer.cpp + +include nan_definitions.mk + +ifeq ($(OS),$(findstring $(OS), "darwin")) + CCSRCS += $(wildcard *Carbon.cpp) +endif + +ifeq ($(OS),$(findstring $(OS), "windows")) + CCSRCS += $(wildcard *Win32.cpp) +endif + +ifeq ($(OS),$(findstring $(OS), "freebsd irix linux openbsd solaris")) + CCSRCS += $(wildcard *X11.cpp) +endif + +include nan_compile.mk + +#CCFLAGS += $(LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I$(NAN_STRING)/include +CPPFLAGS += -I$(NAN_MEMUTIL)/include +CPPFLAGS += -I.. +CPPFLAGS += -I$(OPENGL_HEADERS) + diff --git a/intern/ghost/make/msvc/ghost.dsp b/intern/ghost/make/msvc/ghost.dsp new file mode 100644 index 00000000000..e58b4e8783e --- /dev/null +++ b/intern/ghost/make/msvc/ghost.dsp @@ -0,0 +1,576 @@ +# Microsoft Developer Studio Project File - Name="ghost" - Package Owner=<4> + +# Microsoft Developer Studio Generated Build File, Format Version 6.00 + +# ** DO NOT EDIT ** + + + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + + + +CFG=ghost - Win32 Debug + +!MESSAGE This is not a valid makefile. To build this project using NMAKE, + +!MESSAGE use the Export Makefile command and run + +!MESSAGE + +!MESSAGE NMAKE /f "ghost.mak". + +!MESSAGE + +!MESSAGE You can specify a configuration when running NMAKE + +!MESSAGE by defining the macro CFG on the command line. For example: + +!MESSAGE + +!MESSAGE NMAKE /f "ghost.mak" CFG="ghost - Win32 Debug" + +!MESSAGE + +!MESSAGE Possible choices for configuration are: + +!MESSAGE + +!MESSAGE "ghost - Win32 Release" (based on "Win32 (x86) Static Library") + +!MESSAGE "ghost - Win32 Debug" (based on "Win32 (x86) Static Library") + +!MESSAGE + + + +# Begin Project + +# PROP AllowPerConfigDependencies 0 + +# PROP Scc_ProjName "" + +# PROP Scc_LocalPath "" + +CPP=cl.exe + +RSC=rc.exe + + + +!IF "$(CFG)" == "ghost - Win32 Release" + + + +# PROP BASE Use_MFC 0 + +# PROP BASE Use_Debug_Libraries 0 + +# PROP BASE Output_Dir "Release" + +# PROP BASE Intermediate_Dir "Release" + +# PROP BASE Target_Dir "" + +# PROP Use_MFC 0 + +# PROP Use_Debug_Libraries 0 + +# PROP Output_Dir "../../../../../obj/windows/intern/ghost/" + +# PROP Intermediate_Dir "../../../../../obj/windows/intern/ghost/" + +# PROP Target_Dir "" + +LINK32=link.exe -lib + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c + +# ADD CPP /nologo /MT /W3 /GX /O2 /I "../.." /I "../../../../lib/windows/string/include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c + +# ADD BASE RSC /l 0x409 /d "NDEBUG" + +# ADD RSC /l 0x409 /d "NDEBUG" + +BSC32=bscmake.exe + +# ADD BASE BSC32 /nologo + +# ADD BSC32 /nologo + +LIB32=link.exe -lib + +# ADD BASE LIB32 /nologo + +# ADD LIB32 /nologo + +# Begin Special Build Tool + +SOURCE="$(InputPath)" + +PostBuild_Desc=Copying GHOST files library (release target) to lib tree. + +PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\..\develop\lib\windows\ghost\include\" ECHO Copying lib COPY "..\..\..\..\..\obj\windows\intern\ghost\ghost.lib" "..\..\..\..\..\develop\lib\windows\ghost\lib\libghost.a" ECHO Done + +# End Special Build Tool + + + +!ELSEIF "$(CFG)" == "ghost - Win32 Debug" + + + +# PROP BASE Use_MFC 0 + +# PROP BASE Use_Debug_Libraries 1 + +# PROP BASE Output_Dir "Debug" + +# PROP BASE Intermediate_Dir "Debug" + +# PROP BASE Target_Dir "" + +# PROP Use_MFC 0 + +# PROP Use_Debug_Libraries 1 + +# PROP Output_Dir "../../../../../obj/windows/intern/ghost/debug" + +# PROP Intermediate_Dir "../../../../../obj/windows/intern/ghost/debug" + +# PROP Target_Dir "" + +LINK32=link.exe -lib + +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c + +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "../.." /I "../../../../lib/windows/string/include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c + +# ADD BASE RSC /l 0x409 /d "_DEBUG" + +# ADD RSC /l 0x409 /d "_DEBUG" + +BSC32=bscmake.exe + +# ADD BASE BSC32 /nologo + +# ADD BSC32 /nologo + +LIB32=link.exe -lib + +# ADD BASE LIB32 /nologo + +# ADD LIB32 /nologo + +# Begin Special Build Tool + +SOURCE="$(InputPath)" + +PostBuild_Desc=Copying GHOST files library (debug target) to lib tree. + +PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\..\develop\lib\windows\ghost\include" ECHO Copying lib COPY "..\..\..\..\..\obj\windows\intern\ghost\debug\ghost.lib" "..\..\..\..\..\develop\lib\windows\ghost\lib\debug\libghost.a" ECHO Done + +# End Special Build Tool + + + +!ENDIF + + + +# Begin Target + + + +# Name "ghost - Win32 Release" + +# Name "ghost - Win32 Debug" + +# Begin Group "Header Files" + + + +# PROP Default_Filter "" + +# Begin Group "intern" + + + +# PROP Default_Filter "" + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_Buttons.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_Debug.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_DisplayManager.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_DisplayManagerWin32.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_Event.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_EventButton.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_EventCursor.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_EventKey.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_EventManager.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_EventPrinter.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_EventWindow.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_ModifierKeys.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_System.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_SystemWin32.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_TimerManager.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_TimerTask.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_Window.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_WindowManager.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_WindowWin32.h + +# End Source File + +# End Group + +# Begin Group "extern" + + + +# PROP Default_Filter "" + +# Begin Source File + + + +SOURCE="..\..\GHOST_C-api.h" + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\GHOST_IEvent.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\GHOST_IEventConsumer.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\GHOST_ISystem.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\GHOST_ITimerTask.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\GHOST_IWindow.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\GHOST_Rect.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\GHOST_Types.h + +# End Source File + +# End Group + +# End Group + +# Begin Group "Source Files" + + + +# PROP Default_Filter "" + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_Buttons.cpp + +# End Source File + +# Begin Source File + + + +SOURCE="..\..\intern\GHOST_C-api.cpp" + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_CallbackEventConsumer.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_CallbackEventConsumer.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_DisplayManager.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_DisplayManagerWin32.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_EventManager.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_EventPrinter.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_ISystem.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_ModifierKeys.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_Rect.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_System.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_SystemWin32.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_TimerManager.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_Window.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_WindowManager.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_WindowWin32.cpp + +# End Source File + +# End Group + +# End Target + +# End Project + diff --git a/intern/ghost/make/msvc/ghost.dsw b/intern/ghost/make/msvc/ghost.dsw new file mode 100644 index 00000000000..7ae428a5fb5 --- /dev/null +++ b/intern/ghost/make/msvc/ghost.dsw @@ -0,0 +1,58 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 + +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + + + +############################################################################### + + + +Project: "ghost"=".\ghost.dsp" - Package Owner=<4> + + + +Package=<5> + +{{{ + +}}} + + + +Package=<4> + +{{{ + +}}} + + + +############################################################################### + + + +Global: + + + +Package=<5> + +{{{ + +}}} + + + +Package=<3> + +{{{ + +}}} + + + +############################################################################### + + + diff --git a/intern/ghost/test/Makefile b/intern/ghost/test/Makefile new file mode 100755 index 00000000000..bbd1988a778 --- /dev/null +++ b/intern/ghost/test/Makefile @@ -0,0 +1,86 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# GHOST test applications makefile. +# This bounces to test application directories. +# + +LIBNAME = ghost +SOURCEDIR = intern/$(LIBNAME)/test +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = gears + +include nan_subdirs.mk + +include nan_compile.mk +include nan_link.mk + +OCGGHOST = $(OCGDIR)/intern/$(LIBNAME) +GEARDIR = $(OCGGHOST)/test/$(DEBUG_DIR)gears.app + +LIBS = $(OCGGHOST)/$(DEBUG_DIR)libghost.a +SLIBS += $(LCGDIR)/string/lib/libstring.a + +all debug:: $(LIBS) + @echo "****> linking $@ in $(SOURCEDIR)" +ifeq ($(OS),darwin) + $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)gears $(DIR)/$(DEBUG_DIR)GHOST_Test.o $(LIBS) $(SLIBS) $(LLIBS) $(DADD) $(LOPTS) + @# set up directory structure for the OSX application bundle + @[ -d $(OCGGHOST)/test/ ] || mkdir $(OCGGHOST)/test/ + @[ -d $(OCGGHOST)/test/debug ] || mkdir $(OCGGHOST)/test/debug + @[ -d $(GEARDIR) ] || mkdir $(GEARDIR) + @[ -d $(GEARDIR)/Contents ] || mkdir $(GEARDIR)/Contents + @[ -d $(GEARDIR)/Contents/MacOS ] || mkdir $(GEARDIR)/Contents/MacOS + @[ -d $(GEARDIR)/Contents/Resources ] || mkdir $(GEARDIR)/Contents/Resources + @[ -d $(GEARDIR)/Contents/Resources/English.lproj ] || mkdir $(GEARDIR)/Contents/Resources/English.lproj + @[ -d $(GEARDIR)/Contents/Resources/English.lproj/MainMenu.nib ] || mkdir $(GEARDIR)/Contents/Resources/English.lproj/MainMenu.nib + @# copy the files into the bundle directory tree + cp -f $(DIR)/$(DEBUG_DIR)gears $(GEARDIR)/Contents/MacOS + cp -f gears/resources/osx/PkgInfo $(GEARDIR)/Contents/ + cp -f gears/resources/osx/Info.plist $(GEARDIR)/Contents/ + cp -f gears/resources/osx/English.lproj/InfoPlist.strings $(GEARDIR)/Contents/Resources/English.lproj + cp -f gears/resources/osx/English.lproj/MainMenu.nib/classes.nib $(GEARDIR)/Contents/Resources/English.lproj + cp -f gears/resources/osx/English.lproj/MainMenu.nib/info.nib $(GEARDIR)/Contents/Resources/English.lproj + cp -f gears/resources/osx/English.lproj/MainMenu.nib/objects.nib $(GEARDIR)/Contents/Resources/English.lproj +else + $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)gears_cpp $(DIR)/$(DEBUG_DIR)GHOST_Test.o $(LIBS) $(SLIBS) $(LLIBS) $(DADD) $(LOPTS) + $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)gears_c $(DIR)/$(DEBUG_DIR)GHOST_C-Test.o $(LIBS) $(SLIBS) $(LLIBS) $(DADD) $(LOPTS) +endif + +clean:: + @# mac stuff. well ok, only the binary + @rm -f $(DIR)/gears $(DIR)/debug/gears + @# others + @rm -f $(DIR)/gears_c $(DIR)/debug/gears_c + @rm -f $(DIR)/gears_cpp $(DIR)/debug/gears_cpp + +test:: all + $(DIR)/gears_cpp + $(DIR)/gears_c diff --git a/intern/ghost/test/gears/GHOST_C-Test.c b/intern/ghost/test/gears/GHOST_C-Test.c new file mode 100644 index 00000000000..16d8b421d5b --- /dev/null +++ b/intern/ghost/test/gears/GHOST_C-Test.c @@ -0,0 +1,543 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * + * Simple test file for the GHOST library. + * The OpenGL gear code is taken from the Qt sample code which, + * in turn, is probably taken from somewhere as well. + * @author Maarten Gribnau + * @date May 31, 2001 + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> + +#include "GHOST_C-api.h" + +#if defined(WIN32) || defined(__APPLE__) + #ifdef WIN32 + #include <windows.h> + #include <GL/gl.h> + #else /* WIN32 */ + /* __APPLE__ is defined */ + #include <AGL/gl.h> + #endif /* WIN32 */ +#else /* defined(WIN32) || defined(__APPLE__) */ + #include <GL/gl.h> +#endif /* defined(WIN32) || defined(__APPLE__) */ + + +static void gearsTimerProc(GHOST_TimerTaskHandle task, GHOST_TUns64 time); + +static GLfloat view_rotx=20.0, view_roty=30.0, view_rotz=0.0; +static GLfloat fAngle = 0.0; +static int sExitRequested = 0; +static GHOST_SystemHandle shSystem = NULL; +static GHOST_WindowHandle sMainWindow = NULL; +static GHOST_WindowHandle sSecondaryWindow = NULL; +static GHOST_TStandardCursor sCursor = GHOST_kStandardCursorFirstCursor; +static GHOST_WindowHandle sFullScreenWindow = NULL; +static GHOST_TimerTaskHandle sTestTimer; +static GHOST_TimerTaskHandle sGearsTimer; + + +static void testTimerProc(GHOST_TimerTaskHandle task, GHOST_TUns64 time) +{ + printf("timer1, time=%d\n", (int)time); +} + + +static void gearGL(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, GLint teeth, GLfloat tooth_depth) +{ + GLint i; + GLfloat r0, r1, r2; + GLfloat angle, da; + GLfloat u, v, len; + const double pi = 3.14159264; + + r0 = inner_radius; + r1 = (float)(outer_radius - tooth_depth/2.0); + r2 = (float)(outer_radius + tooth_depth/2.0); + + da = (float)(2.0*pi / teeth / 4.0); + + glShadeModel(GL_FLAT); + glNormal3f(0.0, 0.0, 1.0); + + /* draw front face */ + glBegin(GL_QUAD_STRIP); + for (i=0;i<=teeth;i++) { + angle = (float)(i * 2.0*pi / teeth); + glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(width*0.5)); + glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(width*0.5)); + glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(width*0.5)); + glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(width*0.5)); + } + glEnd(); + + /* draw front sides of teeth */ + glBegin(GL_QUADS); + da = (float)(2.0*pi / teeth / 4.0); + for (i=0;i<teeth;i++) { + angle = (float)(i * 2.0*pi / teeth); + glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(width*0.5)); + glVertex3f((float)(r2*cos(angle+da)), (float)(r2*sin(angle+da)), (float)(width*0.5)); + glVertex3f((float)(r2*cos(angle+2*da)), (float)(r2*sin(angle+2*da)), (float)(width*0.5)); + glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(width*0.5)); + } + glEnd(); + + glNormal3f(0.0, 0.0, -1.0); + + /* draw back face */ + glBegin(GL_QUAD_STRIP); + for (i=0;i<=teeth;i++) { + angle = (float)(i * 2.0*pi / teeth); + glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(-width*0.5)); + glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(-width*0.5)); + glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(-width*0.5)); + glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(-width*0.5)); + } + glEnd(); + + /* draw back sides of teeth */ + glBegin(GL_QUADS); + da = (float)(2.0*pi / teeth / 4.0); + for (i=0;i<teeth;i++) { + angle = (float)(i * 2.0*pi / teeth); + glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(-width*0.5)); + glVertex3f((float)(r2*cos(angle+2*da)), (float)(r2*sin(angle+2*da)), (float)(-width*0.5)); + glVertex3f((float)(r2*cos(angle+da)), (float)(r2*sin(angle+da)), (float)(-width*0.5)); + glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(-width*0.5)); + } + glEnd(); + + /* draw outward faces of teeth */ + glBegin(GL_QUAD_STRIP); + for (i=0;i<teeth;i++) { + angle = (float)(i * 2.0*pi / teeth); + glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(width*0.5)); + glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(-width*0.5)); + u = (float)(r2*cos(angle+da) - r1*cos(angle)); + v = (float)(r2*sin(angle+da) - r1*sin(angle)); + len = (float)(sqrt(u*u + v*v)); + u /= len; + v /= len; + glNormal3f(v, -u, 0.0); + glVertex3f((float)(r2*cos(angle+da)), (float)(r2*sin(angle+da)), (float)(width*0.5)); + glVertex3f((float)(r2*cos(angle+da)), (float)(r2*sin(angle+da)), (float)(-width*0.5)); + glNormal3f((float)(cos(angle)), (float)(sin(angle)), 0.0); + glVertex3f((float)(r2*cos(angle+2*da)), (float)(r2*sin(angle+2*da)), (float)(width*0.5)); + glVertex3f((float)(r2*cos(angle+2*da)), (float)(r2*sin(angle+2*da)), (float)(-width*0.5)); + u = (float)(r1*cos(angle+3*da) - r2*cos(angle+2*da)); + v = (float)(r1*sin(angle+3*da) - r2*sin(angle+2*da)); + glNormal3f(v, -u, 0.0); + glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(width*0.5)); + glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(-width*0.5)); + glNormal3f((float)(cos(angle)), (float)(sin(angle)), 0.0); + } + glVertex3f((float)(r1*cos(0.0)), (float)(r1*sin(0.0)), (float)(width*0.5)); + glVertex3f((float)(r1*cos(0.0)), (float)(r1*sin(0.0)), (float)(-width*0.5)); + glEnd(); + + glShadeModel(GL_SMOOTH); + + /* draw inside radius cylinder */ + glBegin(GL_QUAD_STRIP); + for (i=0;i<=teeth;i++) { + angle = (float)(i * 2.0*pi / teeth); + glNormal3f((float)(-cos(angle)), (float)(-sin(angle)), 0.0); + glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(-width*0.5)); + glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(width*0.5)); + } + glEnd(); +} + + + +static void drawGearGL(int id) +{ + static GLfloat pos[4] = { 5.0f, 5.0f, 10.0f, 1.0f }; + static GLfloat ared[4] = { 0.8f, 0.1f, 0.0f, 1.0f }; + static GLfloat agreen[4] = { 0.0f, 0.8f, 0.2f, 1.0f }; + static GLfloat ablue[4] = { 0.2f, 0.2f, 1.0f, 1.0f }; + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + + switch (id) + { + case 1: + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ared); + gearGL(1.0f, 4.0f, 1.0f, 20, 0.7f); + break; + case 2: + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, agreen); + gearGL(0.5f, 2.0f, 2.0f, 10, 0.7f); + break; + case 3: + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ablue); + gearGL(1.3f, 2.0f, 0.5f, 10, 0.7f); + break; + default: + break; + } + glEnable(GL_NORMALIZE); +} + + +static void drawGL(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + + glRotatef(view_rotx, 1.0, 0.0, 0.0); + glRotatef(view_roty, 0.0, 1.0, 0.0); + glRotatef(view_rotz, 0.0, 0.0, 1.0); + + glPushMatrix(); + glTranslatef(-3.0, -2.0, 0.0); + glRotatef(fAngle, 0.0, 0.0, 1.0); + drawGearGL(1); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(3.1f, -2.0f, 0.0f); + glRotatef((float)(-2.0*fAngle-9.0), 0.0, 0.0, 1.0); + drawGearGL(2); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(-3.1f, 2.2f, -1.8f); + glRotatef(90.0f, 1.0f, 0.0f, 0.0f); + glRotatef((float)(2.0*fAngle-2.0), 0.0, 0.0, 1.0); + drawGearGL(3); + glPopMatrix(); + + glPopMatrix(); +} + + +static void setViewPortGL(GHOST_WindowHandle hWindow) +{ + GHOST_RectangleHandle hRect = NULL; + GLfloat w, h; + + GHOST_ActivateWindowDrawingContext(hWindow); + hRect = GHOST_GetClientBounds(hWindow); + + w = (float)GHOST_GetWidthRectangle(hRect) / (float)GHOST_GetHeightRectangle(hRect); + h = 1.0; + + glViewport(0, 0, GHOST_GetWidthRectangle(hRect), GHOST_GetHeightRectangle(hRect)); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-w, w, -h, h, 5.0, 60.0); + /* glOrtho(0, bnds.getWidth(), 0, bnds.getHeight(), -10, 10); */ + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -40.0); + + glClearColor(.2f,0.0f,0.0f,0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + GHOST_DisposeRectangle(hRect); +} + + + +int processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData) +{ + int handled = 1; + int cursor; + int visibility; + GHOST_TEventKeyData* keyData = NULL; + GHOST_DisplaySetting setting; + GHOST_WindowHandle window = GHOST_GetEventWindow(hEvent); + + switch (GHOST_GetEventType(hEvent)) + { + /* + case GHOST_kEventUnknown: + break; + case GHOST_kEventCursorButton: + break; + case GHOST_kEventCursorMove: + break; + */ + case GHOST_kEventKeyUp: + break; + + case GHOST_kEventKeyDown: + { + keyData = (GHOST_TEventKeyData*)GHOST_GetEventData(hEvent); + switch (keyData->key) + { + case GHOST_kKeyC: + { + cursor = sCursor; + cursor++; + if (cursor >= GHOST_kStandardCursorNumCursors) + { + cursor = GHOST_kStandardCursorFirstCursor; + } + sCursor = (GHOST_TStandardCursor)cursor; + GHOST_SetCursorShape(window, sCursor); + } + break; + case GHOST_kKeyF: + if (!GHOST_GetFullScreen(shSystem)) + { + /* Begin fullscreen mode */ + setting.bpp = 24; + setting.frequency = 85; + setting.xPixels = 640; + setting.yPixels = 480; + + /* + setting.bpp = 16; + setting.frequency = 75; + setting.xPixels = 640; + setting.yPixels = 480; + */ + + sFullScreenWindow = GHOST_BeginFullScreen(shSystem, &setting, + false /* stereo flag */); + } + else + { + GHOST_EndFullScreen(shSystem); + sFullScreenWindow = 0; + } + break; + case GHOST_kKeyH: + { + visibility = GHOST_GetCursorVisibility(window); + GHOST_SetCursorVisibility(window, !visibility); + } + break; + case GHOST_kKeyQ: + if (GHOST_GetFullScreen(shSystem)) + { + GHOST_EndFullScreen(shSystem); + sFullScreenWindow = 0; + } + sExitRequested = 1; + case GHOST_kKeyT: + if (!sTestTimer) + { + sTestTimer = GHOST_InstallTimer(shSystem, 0, 1000, testTimerProc, NULL); + } + else + { + GHOST_RemoveTimer(shSystem, sTestTimer); + sTestTimer = 0; + } + break; + case GHOST_kKeyW: + { + if (sMainWindow) + { + char *title = GHOST_GetTitle(sMainWindow); + char *ntitle = malloc(strlen(title)+2); + + sprintf(ntitle, "%s-", title); + GHOST_SetTitle(sMainWindow, ntitle); + + free(ntitle); + free(title); + } + } + break; + default: + break; + } + } + break; + + case GHOST_kEventWindowClose: + { + GHOST_WindowHandle window = GHOST_GetEventWindow(hEvent); + if (window == sMainWindow) + { + sExitRequested = 1; + } + else + { + if (sGearsTimer) + { + GHOST_RemoveTimer(shSystem, sGearsTimer); + sGearsTimer = 0; + } + GHOST_DisposeWindow(shSystem, window); + } + } + break; + + case GHOST_kEventWindowActivate: + handled = 0; + break; + case GHOST_kEventWindowDeactivate: + handled = 0; + break; + case GHOST_kEventWindowUpdate: + { + GHOST_WindowHandle window = GHOST_GetEventWindow(hEvent); + if (!GHOST_ValidWindow(shSystem, window)) + break; + //if (!m_fullScreenWindow) + { + setViewPortGL(window); + drawGL(); + GHOST_SwapWindowBuffers(window); + } + } + break; + + default: + handled = 0; + break; + } + return handled; +} + + +int main(int argc, char** argv) +{ + char* title1 = "gears - main window"; + char* title2 = "gears - secondary window"; + GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(processEvent, NULL); + + /* Create the system */ + shSystem = GHOST_CreateSystem(); + GHOST_AddEventConsumer(shSystem, consumer); + + if (shSystem) + { + /* Create the main window */ + sMainWindow = GHOST_CreateWindow(shSystem, + title1, + 10, + 64, + 320, + 200, + GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL); + if (!sMainWindow) + { + printf("could not create main window\n"); + exit(-1); + } + + /* Create a secondary window */ + sSecondaryWindow = GHOST_CreateWindow(shSystem, + title2, + 340, + 64, + 320, + 200, + GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL); + if (!sSecondaryWindow) + { + printf("could not create secondary window\n"); + exit(-1); + } + + /* Install a timer to have the gears running */ + sGearsTimer = GHOST_InstallTimer(shSystem, + 0, + 10, + gearsTimerProc, + sMainWindow); + + /* Enter main loop */ + while (!sExitRequested) + { + if (!GHOST_ProcessEvents(shSystem, 0)) + { +#ifdef WIN32 + /* If there were no events, be nice to other applications */ + Sleep(10); +#endif + } + GHOST_DispatchEvents(shSystem); + } + } + + /* Dispose windows */ + if (GHOST_ValidWindow(shSystem, sMainWindow)) + { + GHOST_DisposeWindow(shSystem, sMainWindow); + } + if (GHOST_ValidWindow(shSystem, sSecondaryWindow)) + { + GHOST_DisposeWindow(shSystem, sSecondaryWindow); + } + + /* Dispose the system */ + GHOST_DisposeSystem(shSystem); + GHOST_DisposeEventConsumer(consumer); + + return 0; +} + + +static void gearsTimerProc(GHOST_TimerTaskHandle hTask, GHOST_TUns64 time) +{ + GHOST_WindowHandle hWindow = NULL; + fAngle += 2.0; + view_roty += 1.0; + hWindow = (GHOST_WindowHandle)GHOST_GetTimerTaskUserData(hTask); + if (GHOST_GetFullScreen(shSystem)) + { + /* Running full screen */ + GHOST_InvalidateWindow(sFullScreenWindow); + } + else + { + if (GHOST_ValidWindow(shSystem, hWindow)) + { + GHOST_InvalidateWindow(hWindow); + } + } +} diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp new file mode 100755 index 00000000000..a5459c9da9b --- /dev/null +++ b/intern/ghost/test/gears/GHOST_Test.cpp @@ -0,0 +1,745 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * Simple test file for the GHOST library. + * The OpenGL gear code is taken from the Qt sample code which, + * in turn, is probably taken from somewhere as well. + * @author Maarten Gribnau + * @date May 31, 2001 + * Stereo code by Raymond de Vries, januari 2002 + */ + +#include <iostream> +#include <math.h> + +#if defined(WIN32) || defined(__APPLE__) + #ifdef WIN32 + #include <windows.h> + #include <atlbase.h> + + #include <GL/gl.h> + #else // WIN32 + // __APPLE__ is defined + #include <AGL/gl.h> + #endif // WIN32 +#else // defined(WIN32) || defined(__APPLE__) + #include <GL/gl.h> +#endif // defined(WIN32) || defined(__APPLE__) + +#include "STR_String.h" +#include "GHOST_Rect.h" + +#include "GHOST_ISystem.h" +#include "GHOST_IEvent.h" +#include "GHOST_IEventConsumer.h" + + +#define LEFT_EYE 0 +#define RIGHT_EYE 1 + +static bool nVidiaWindows; // very dirty but hey, it's for testing only + +static void gearsTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time); + +static class Application* fApp; +static GLfloat view_rotx=20.0, view_roty=30.0, view_rotz=0.0; +static GLfloat fAngle = 0.0; +static GHOST_ISystem* fSystem = 0; + + +void StereoProjection(float left, float right, float bottom, float top, float nearplane, float farplane, + float zero_plane, float dist, + float eye); + + +static void testTimerProc(GHOST_ITimerTask* /*task*/, GHOST_TUns64 time) +{ + std::cout << "timer1, time=" << (int)time << "\n"; +} + + +static void gearGL(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, GLint teeth, GLfloat tooth_depth) +{ + GLint i; + GLfloat r0, r1, r2; + GLfloat angle, da; + GLfloat u, v, len; + + r0 = inner_radius; + r1 = outer_radius - tooth_depth/2.0; + r2 = outer_radius + tooth_depth/2.0; + + const double pi = 3.14159264; + da = 2.0*pi / teeth / 4.0; + + glShadeModel(GL_FLAT); + glNormal3f(0.0, 0.0, 1.0); + + /* draw front face */ + glBegin(GL_QUAD_STRIP); + for (i=0;i<=teeth;i++) { + angle = i * 2.0*pi / teeth; + glVertex3f(r0*cos(angle), r0*sin(angle), width*0.5); + glVertex3f(r1*cos(angle), r1*sin(angle), width*0.5); + glVertex3f(r0*cos(angle), r0*sin(angle), width*0.5); + glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5); + } + glEnd(); + + /* draw front sides of teeth */ + glBegin(GL_QUADS); + da = 2.0*pi / teeth / 4.0; + for (i=0;i<teeth;i++) { + angle = i * 2.0*pi / teeth; + glVertex3f(r1*cos(angle), r1*sin(angle), width*0.5); + glVertex3f(r2*cos(angle+da), r2*sin(angle+da), width*0.5); + glVertex3f(r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5); + glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5); + } + glEnd(); + + glNormal3f(0.0, 0.0, -1.0); + + /* draw back face */ + glBegin(GL_QUAD_STRIP); + for (i=0;i<=teeth;i++) { + angle = i * 2.0*pi / teeth; + glVertex3f(r1*cos(angle), r1*sin(angle), -width*0.5); + glVertex3f(r0*cos(angle), r0*sin(angle), -width*0.5); + glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5); + glVertex3f(r0*cos(angle), r0*sin(angle), -width*0.5); + } + glEnd(); + + /* draw back sides of teeth */ + glBegin(GL_QUADS); + da = 2.0*pi / teeth / 4.0; + for (i=0;i<teeth;i++) { + angle = i * 2.0*pi / teeth; + glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5); + glVertex3f(r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5); + glVertex3f(r2*cos(angle+da), r2*sin(angle+da), -width*0.5); + glVertex3f(r1*cos(angle), r1*sin(angle), -width*0.5); + } + glEnd(); + + /* draw outward faces of teeth */ + glBegin(GL_QUAD_STRIP); + for (i=0;i<teeth;i++) { + angle = i * 2.0*pi / teeth; + glVertex3f(r1*cos(angle), r1*sin(angle), width*0.5); + glVertex3f(r1*cos(angle), r1*sin(angle), -width*0.5); + u = r2*cos(angle+da) - r1*cos(angle); + v = r2*sin(angle+da) - r1*sin(angle); + len = sqrt(u*u + v*v); + u /= len; + v /= len; + glNormal3f(v, -u, 0.0); + glVertex3f(r2*cos(angle+da), r2*sin(angle+da), width*0.5); + glVertex3f(r2*cos(angle+da), r2*sin(angle+da), -width*0.5); + glNormal3f(cos(angle), sin(angle), 0.0); + glVertex3f(r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5); + glVertex3f(r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5); + u = r1*cos(angle+3*da) - r2*cos(angle+2*da); + v = r1*sin(angle+3*da) - r2*sin(angle+2*da); + glNormal3f(v, -u, 0.0); + glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5); + glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5); + glNormal3f(cos(angle), sin(angle), 0.0); + } + glVertex3f(r1*cos(0.0), r1*sin(0.0), width*0.5); + glVertex3f(r1*cos(0.0), r1*sin(0.0), -width*0.5); + glEnd(); + + glShadeModel(GL_SMOOTH); + + /* draw inside radius cylinder */ + glBegin(GL_QUAD_STRIP); + for (i=0;i<=teeth;i++) { + angle = i * 2.0*pi / teeth; + glNormal3f(-cos(angle), -sin(angle), 0.0); + glVertex3f(r0*cos(angle), r0*sin(angle), -width*0.5); + glVertex3f(r0*cos(angle), r0*sin(angle), width*0.5); + } + glEnd(); +} + + + +static void drawGearGL(int id) +{ + static GLfloat pos[4] = { 5.0f, 5.0f, 10.0f, 1.0f }; + static GLfloat ared[4] = { 0.8f, 0.1f, 0.0f, 1.0f }; + static GLfloat agreen[4] = { 0.0f, 0.8f, 0.2f, 1.0f }; + static GLfloat ablue[4] = { 0.2f, 0.2f, 1.0f, 1.0f }; + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + + switch (id) + { + case 1: + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ared); + gearGL(1.0f, 4.0f, 1.0f, 20, 0.7f); + break; + case 2: + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, agreen); + gearGL(0.5f, 2.0f, 2.0f, 10, 0.7f); + break; + case 3: + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ablue); + gearGL(1.3f, 2.0f, 0.5f, 10, 0.7f); + break; + default: + break; + } + glEnable(GL_NORMALIZE); +} + + +void RenderCamera() +{ + glRotatef(view_rotx, 1.0, 0.0, 0.0); + glRotatef(view_roty, 0.0, 1.0, 0.0); + glRotatef(view_rotz, 0.0, 0.0, 1.0); +} + + +void RenderScene() +{ + glPushMatrix(); + glTranslatef(-3.0, -2.0, 0.0); + glRotatef(fAngle, 0.0, 0.0, 1.0); + drawGearGL(1); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(3.1f, -2.0f, 0.0f); + glRotatef(-2.0 * fAngle - 9.0, 0.0, 0.0, 1.0); + drawGearGL(2); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(-3.1f, 2.2f, -1.8f); + glRotatef(90.0f, 1.0f, 0.0f, 0.0f); + glRotatef(2.0 * fAngle - 2.0, 0.0, 0.0, 1.0); + drawGearGL(3); + glPopMatrix(); +} + + +static void View(GHOST_IWindow* window, bool stereo, int eye = 0) +{ + window->activateDrawingContext(); + GHOST_Rect bnds; + int noOfScanlines = 0, lowerScanline; + int verticalBlankingInterval = 32; // hard coded for testing purposes, display device dependant + float left, right, bottom, top; + float nearplane, farplane, zeroPlane, distance; + float eyeSeparation = 0.62; + window->getClientBounds(bnds); + GLfloat w = float(bnds.getWidth()) / float(bnds.getHeight()); + GLfloat h = 1.0; + + // viewport + if(stereo) + { + if(nVidiaWindows) + { + // handled by nVidia driver so act as normal (explicitly put here since + // it -is- stereo) + glViewport(0, 0, bnds.getWidth(), bnds.getHeight()); + } + else + { // generic cross platform above-below stereo + noOfScanlines = (bnds.getHeight() - verticalBlankingInterval) / 2; + switch(eye) + { + case LEFT_EYE: + // upper half of window + lowerScanline = bnds.getHeight() - noOfScanlines; + break; + case RIGHT_EYE: + // lower half of window + lowerScanline = 0; + break; + } + } + } + else + { + noOfScanlines = bnds.getHeight(); + lowerScanline = 0; + } + + glViewport(0, lowerScanline, bnds.getWidth(), noOfScanlines); + + // projection + left = -6.0; + right = 6.0; + bottom = -4.8; + top = 4.8; + nearplane = 5.0; + farplane = 60.0; + + if(stereo) + { + zeroPlane = 0.0; + distance = 14.5; + switch(eye) + { + case LEFT_EYE: + StereoProjection(left, right, bottom, top, nearplane, farplane, zeroPlane, distance, -eyeSeparation / 2.0); + break; + case RIGHT_EYE: + StereoProjection(left, right, bottom, top, nearplane, farplane, zeroPlane, distance, eyeSeparation / 2.0); + break; + } + } + else + { +// left = -w; +// right = w; +// bottom = -h; +// top = h; + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(left, right, bottom, top, 5.0, 60.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -40.0); + + } + + glClearColor(.2f,0.0f,0.0f,0.0f); +} + + +void StereoProjection(float left, float right, float bottom, float top, float nearplane, float farplane, + float zero_plane, float dist, + float eye) +/* Perform the perspective projection for one eye's subfield. +The projection is in the direction of the negative z axis. + +-6.0, 6.0, -4.8, 4.8, +left, right, bottom, top = the coordinate range, in the plane of zero +parallax setting, which will be displayed on the screen. The +ratio between (right-left) and (top-bottom) should equal the aspect +ratio of the display. + +6.0, -6.0, +near, far = the z-coordinate values of the clipping planes. + +0.0, +zero_plane = the z-coordinate of the plane of zero parallax setting. + +14.5, +dist = the distance from the center of projection to the plane +of zero parallax. + +-0.31 +eye = half the eye separation; positive for the right eye subfield, +negative for the left eye subfield. +*/ +{ + float xmid, ymid, clip_near, clip_far, topw, bottomw, leftw, rightw, + dx, dy, n_over_d; + + dx = right - left; + dy = top - bottom; + + xmid = (right + left) / 2.0; + ymid = (top + bottom) / 2.0; + + clip_near = dist + zero_plane - nearplane; + clip_far = dist + zero_plane - farplane; + + n_over_d = clip_near / dist; + + topw = n_over_d * dy / 2.0; + bottomw = -topw; + rightw = n_over_d * (dx / 2.0 - eye); + leftw = n_over_d *(-dx / 2.0 - eye); + + /* Need to be in projection mode for this. */ + glLoadIdentity(); + glFrustum(leftw, rightw, bottomw, topw, clip_near, clip_far); + + glTranslatef(-xmid - eye, -ymid, -zero_plane - dist); + return; +} /* stereoproj */ + + +class Application : public GHOST_IEventConsumer { +public: + Application(GHOST_ISystem* system); + ~Application(void); + virtual bool processEvent(GHOST_IEvent* event); + + GHOST_ISystem* m_system; + GHOST_IWindow* m_mainWindow; + GHOST_IWindow* m_secondaryWindow; + GHOST_IWindow* m_fullScreenWindow; + GHOST_ITimerTask* m_gearsTimer, *m_testTimer; + GHOST_TStandardCursor m_cursor; + bool m_exitRequested; + + bool stereo; +}; + + +Application::Application(GHOST_ISystem* system) + : m_system(system), m_mainWindow(0), m_secondaryWindow(0), m_fullScreenWindow(0), + m_gearsTimer(0), m_testTimer(0), m_cursor(GHOST_kStandardCursorFirstCursor), + m_exitRequested(false), stereo(false) +{ + fApp = this; + + // Create the main window + STR_String title1 ("gears - main window"); + m_mainWindow = system->createWindow(title1, 10, 64, 320, 200, GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL, true /* stereo flag */); + + if (!m_mainWindow) { + std::cout << "could not create main window\n"; + exit(-1); + } + + // Create a secondary window + STR_String title2 ("gears - secondary window"); + m_secondaryWindow = system->createWindow(title2, 340, 64, 320, 200, GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL, false /* stereo flag */); + if (!m_secondaryWindow) { + cout << "could not create secondary window\n"; + exit(-1); + } + + // Install a timer to have the gears running + m_gearsTimer = system->installTimer(0 /*delay*/, 20/*interval*/, gearsTimerProc, m_mainWindow); +} + + +Application::~Application(void) +{ + // Dispose windows + if (m_system->validWindow(m_mainWindow)) { + m_system->disposeWindow(m_mainWindow); + } + if (m_system->validWindow(m_secondaryWindow)) { + m_system->disposeWindow(m_secondaryWindow); + } +} + + +bool Application::processEvent(GHOST_IEvent* event) +{ + GHOST_IWindow* window = event->getWindow(); + bool handled = true; + + switch (event->getType()) { +/* case GHOST_kEventUnknown: + break; + case GHOST_kEventCursorButton: + std::cout << "GHOST_kEventCursorButton"; break; + case GHOST_kEventCursorMove: + std::cout << "GHOST_kEventCursorMove"; break; +*/ + case GHOST_kEventKeyUp: + break; + + case GHOST_kEventKeyDown: + { + GHOST_TEventKeyData* keyData = (GHOST_TEventKeyData*) event->getData(); + switch (keyData->key) { + case GHOST_kKeyC: + { + int cursor = m_cursor; + cursor++; + if (cursor >= GHOST_kStandardCursorNumCursors) { + cursor = GHOST_kStandardCursorFirstCursor; + } + m_cursor = (GHOST_TStandardCursor)cursor; + window->setCursorShape(m_cursor); + } + break; + + case GHOST_kKeyE: + { + int x = 200, y= 200; + m_system->setCursorPosition(x,y); + break; + } + + case GHOST_kKeyF: + if (!m_system->getFullScreen()) { + // Begin fullscreen mode + GHOST_DisplaySetting setting; + + setting.bpp = 16; + setting.frequency = 50; + setting.xPixels = 640; + setting.yPixels = 480; + m_system->beginFullScreen(setting, &m_fullScreenWindow, false /* stereo flag */); + } + else { + m_system->endFullScreen(); + m_fullScreenWindow = 0; + } + break; + + case GHOST_kKeyH: + window->setCursorVisibility(!window->getCursorVisibility()); + break; + + case GHOST_kKeyM: + { + bool down = false; + m_system->getModifierKeyState(GHOST_kModifierKeyLeftShift,down); + if (down) { + std::cout << "left shift down\n"; + } + m_system->getModifierKeyState(GHOST_kModifierKeyRightShift,down); + if (down) { + std::cout << "right shift down\n"; } + m_system->getModifierKeyState(GHOST_kModifierKeyLeftAlt,down); + if (down) { + std::cout << "left Alt down\n"; + } + m_system->getModifierKeyState(GHOST_kModifierKeyRightAlt,down); + if (down) { + std::cout << "right Alt down\n"; + } + m_system->getModifierKeyState(GHOST_kModifierKeyLeftControl,down); + if (down) { + std::cout << "left control down\n"; + } + m_system->getModifierKeyState(GHOST_kModifierKeyRightControl,down); + if (down) { + std::cout << "right control down\n"; + } + } + break; + + case GHOST_kKeyQ: + if (m_system->getFullScreen()) + { + m_system->endFullScreen(); + m_fullScreenWindow = 0; + } + m_exitRequested = true; + break; + + case GHOST_kKeyS: // toggle mono and stereo + if(stereo) + stereo = false; + else + stereo = true; + break; + + case GHOST_kKeyT: + if (!m_testTimer) { + m_testTimer = m_system->installTimer(0, 1000, testTimerProc); + } + + else { + m_system->removeTimer(m_testTimer); + m_testTimer = 0; + } + + break; + + case GHOST_kKeyW: + if (m_mainWindow) + { + STR_String title; + m_mainWindow->getTitle(title); + title += "-"; + m_mainWindow->setTitle(title); + + } + break; + + default: + break; + } + } + break; + + case GHOST_kEventWindowClose: + { + GHOST_IWindow* window = event->getWindow(); + if (window == m_mainWindow) { + m_exitRequested = true; + } + else { + m_system->disposeWindow(window); + } + } + break; + + case GHOST_kEventWindowActivate: + handled = false; + break; + + case GHOST_kEventWindowDeactivate: + handled = false; + break; + + case GHOST_kEventWindowUpdate: + { + GHOST_IWindow* window = event->getWindow(); + if(!m_system->validWindow(window)) + break; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if(stereo) + { + View(window, stereo, LEFT_EYE); + glPushMatrix(); + RenderCamera(); + RenderScene(); + glPopMatrix(); + + View(window, stereo, RIGHT_EYE); + glPushMatrix(); + RenderCamera(); + RenderScene(); + glPopMatrix(); + } + else + { + View(window, stereo); + glPushMatrix(); + RenderCamera(); + RenderScene(); + glPopMatrix(); + } + window->swapBuffers(); + } + break; + + default: + handled = false; + break; + } + return handled; +} + + +int main(int /*argc*/, char** /*argv*/) +{ + nVidiaWindows = false; +// nVidiaWindows = true; + +#ifdef WIN32 + /* Set a couple of settings in the registry for the nVidia detonator driver. + * So this is very specific... + */ + if(nVidiaWindows) + { + LONG lresult; + HKEY hkey = 0; + DWORD dwd = 0; + unsigned char buffer[128]; + + CRegKey regkey; + DWORD keyValue; +// lresult = regkey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable"); + lresult = regkey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable", + KEY_ALL_ACCESS ); + + if(lresult == ERROR_SUCCESS) + printf("Succesfully opened key\n"); +#if 0 + lresult = regkey.QueryValue(&keyValue, "StereoEnable"); + if(lresult == ERROR_SUCCESS) + printf("Succesfully queried key\n"); +#endif + lresult = regkey.SetValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable", + "1"); + if(lresult == ERROR_SUCCESS) + printf("Succesfully set value for key\n"); + regkey.Close(); + if(lresult == ERROR_SUCCESS) + printf("Succesfully closed key\n"); +// regkey.Write("2"); + } +#endif // WIN32 + + // Create the system + GHOST_ISystem::createSystem(); + fSystem = GHOST_ISystem::getSystem(); + + if (fSystem) { + // Create an application object + Application app (fSystem); + + // Add the application as event consumer + fSystem->addEventConsumer(&app); + + // Enter main loop + while (!app.m_exitRequested) { + //printf("main: loop\n"); + fSystem->processEvents(true); + fSystem->dispatchEvents(); + } + } + + // Dispose the system + GHOST_ISystem::disposeSystem(); + + return 0; +} + + +static void gearsTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 /*time*/) +{ + fAngle += 2.0; + view_roty += 1.0; + GHOST_IWindow* window = (GHOST_IWindow*)task->getUserData(); + if (fApp->m_fullScreenWindow) { + // Running full screen + fApp->m_fullScreenWindow->invalidate(); + } + else { + if (fSystem->validWindow(window)) { + window->invalidate(); + } + } +} diff --git a/intern/ghost/test/gears/Makefile b/intern/ghost/test/gears/Makefile new file mode 100755 index 00000000000..b7966b4d157 --- /dev/null +++ b/intern/ghost/test/gears/Makefile @@ -0,0 +1,48 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# GHOST gears test application Makefile +# + +LIBNAME = gearstest +DIR = $(OCGDIR)/intern/ghost/test + +# we don't want a library here, only object files: +ALLTARGETS = $(OBJS) + +include nan_compile.mk + +CFLAGS += $(LEVEL_2_C_WARNINGS) +CCFLAGS += $(LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I$(OPENGL_HEADERS) +CPPFLAGS += -I$(NAN_STRING)/include +CPPFLAGS += -I../.. + diff --git a/intern/ghost/test/make/msvc_6_0/gears.dsp b/intern/ghost/test/make/msvc_6_0/gears.dsp new file mode 100644 index 00000000000..3e809a6b604 --- /dev/null +++ b/intern/ghost/test/make/msvc_6_0/gears.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="gears" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=gears - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "gears.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "gears.mak" CFG="gears - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "gears - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "gears - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "gears - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../../../../../obj/windows/intern/ghost/test/" +# PROP Intermediate_Dir "../../../../../../obj/windows/intern/ghost/test/" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../.." /I "../../../../string" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "gears - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../../../../../obj/windows/intern/ghost/test/debug" +# PROP Intermediate_Dir "../../../../../../obj/windows/intern/ghost/test/debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "../../.." /I "../../../../string" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "gears - Win32 Release" +# Name "gears - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gears\GHOST_Test.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/intern/ghost/test/make/msvc_6_0/gears_C.dsp b/intern/ghost/test/make/msvc_6_0/gears_C.dsp new file mode 100644 index 00000000000..5972d123268 --- /dev/null +++ b/intern/ghost/test/make/msvc_6_0/gears_C.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="gears_C" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=gears_C - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "gears_C.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "gears_C.mak" CFG="gears_C - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "gears_C - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "gears_C - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "gears_C - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../../../../../obj/windows/intern/ghost/test/" +# PROP Intermediate_Dir "../../../../../../obj/windows/intern/ghost/test/" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../.." /I "../../../../string" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "gears_C - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../../../../../obj/windows/intern/ghost/test/debug" +# PROP Intermediate_Dir "../../../../../../obj/windows/intern/ghost/test/debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "../../.." /I "../../../../string" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "gears_C - Win32 Release" +# Name "gears_C - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\..\gears\GHOST_C-Test.c" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/intern/ghost/test/make/msvc_6_0/ghost_test.dsw b/intern/ghost/test/make/msvc_6_0/ghost_test.dsw new file mode 100644 index 00000000000..03bf5eb5c9a --- /dev/null +++ b/intern/ghost/test/make/msvc_6_0/ghost_test.dsw @@ -0,0 +1,77 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "gears"=.\gears.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name ghost + End Project Dependency + Begin Project Dependency + Project_Dep_Name string + End Project Dependency +}}} + +############################################################################### + +Project: "gears_C"=.\gears_C.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name ghost + End Project Dependency + Begin Project Dependency + Project_Dep_Name string + End Project Dependency +}}} + +############################################################################### + +Project: "ghost"=..\..\..\make\msvc\ghost.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "string"=..\..\..\..\string\make\msvc_6_0\string.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/intern/ghost/test/multitest/Basic.c b/intern/ghost/test/multitest/Basic.c new file mode 100644 index 00000000000..c26cf7c92ca --- /dev/null +++ b/intern/ghost/test/multitest/Basic.c @@ -0,0 +1,68 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "Basic.h" + + +int min_i(int a, int b) { + return (a<b)?a:b; +} +int max_i(int a, int b) { + return (b<a)?a:b; +} +int clamp_i(int val, int min, int max) { + return min_i(max_i(val, min), max); +} + +float min_f(float a, float b) { + return (a<b)?a:b; +} +float max_f(float a, float b) { + return (b<a)?a:b; +} +float clamp_f(float val, float min, float max) { + return min_f(max_f(val, min), max); +} + +void rect_copy(int dst[2][2], int src[2][2]) { + dst[0][0]= src[0][0], dst[0][1]= src[0][1]; + dst[1][0]= src[1][0], dst[1][1]= src[1][1]; +} +int rect_contains_pt(int rect[2][2], int pt[2]){ + return ((rect[0][0] <= pt[0] && pt[0] <= rect[1][0]) && + (rect[0][1] <= pt[1] && pt[1] <= rect[1][1])); +} +int rect_width(int rect[2][2]) { + return (rect[1][0]-rect[0][0]); +} +int rect_height(int rect[2][2]) { + return (rect[1][1]-rect[0][1]); +} diff --git a/intern/ghost/test/multitest/Basic.h b/intern/ghost/test/multitest/Basic.h new file mode 100644 index 00000000000..f81f4684bcc --- /dev/null +++ b/intern/ghost/test/multitest/Basic.h @@ -0,0 +1,44 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +int min_i (int a, int b); + +int max_i (int a, int b); +int clamp_i (int val, int min, int max); + +float min_f (float a, float b); +float max_f (float a, float b); +float clamp_f (float val, float min, float max); + +void rect_copy (int dst[2][2], int src[2][2]); +int rect_contains_pt (int rect[2][2], int pt[2]); +int rect_width (int rect[2][2]); +int rect_height (int rect[2][2]); diff --git a/intern/ghost/test/multitest/EventToBuf.c b/intern/ghost/test/multitest/EventToBuf.c new file mode 100644 index 00000000000..950d80a2468 --- /dev/null +++ b/intern/ghost/test/multitest/EventToBuf.c @@ -0,0 +1,236 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdlib.h> + +#include <stdio.h> + +#include "MEM_guardedalloc.h" + +#include "GHOST_C-api.h" +#include "EventToBuf.h" + +char *eventtype_to_string(GHOST_TEventType type) { + switch(type) { + case GHOST_kEventCursorMove: return "CursorMove"; + case GHOST_kEventButtonDown: return "ButtonDown"; + case GHOST_kEventButtonUp: return "ButtonUp"; + + case GHOST_kEventKeyDown: return "KeyDown"; + case GHOST_kEventKeyUp: return "KeyUp"; + + case GHOST_kEventQuit: return "Quit"; + + case GHOST_kEventWindowClose: return "WindowClose"; + case GHOST_kEventWindowActivate: return "WindowActivate"; + case GHOST_kEventWindowDeactivate: return "WindowDeactivate"; + case GHOST_kEventWindowUpdate: return "WindowUpdate"; + case GHOST_kEventWindowSize: return "WindowSize"; + default: + return "<invalid>"; + } +} + +static char *keytype_to_string(GHOST_TKey key) { +#define K(key) case GHOST_k##key: return #key; + switch (key) { + K(KeyBackSpace); + K(KeyTab); + K(KeyLinefeed); + K(KeyClear); + K(KeyEnter); + + K(KeyEsc); + K(KeySpace); + K(KeyQuote); + K(KeyComma); + K(KeyMinus); + K(KeyPeriod); + K(KeySlash); + + K(Key0); + K(Key1); + K(Key2); + K(Key3); + K(Key4); + K(Key5); + K(Key6); + K(Key7); + K(Key8); + K(Key9); + + K(KeySemicolon); + K(KeyEqual); + + K(KeyA); + K(KeyB); + K(KeyC); + K(KeyD); + K(KeyE); + K(KeyF); + K(KeyG); + K(KeyH); + K(KeyI); + K(KeyJ); + K(KeyK); + K(KeyL); + K(KeyM); + K(KeyN); + K(KeyO); + K(KeyP); + K(KeyQ); + K(KeyR); + K(KeyS); + K(KeyT); + K(KeyU); + K(KeyV); + K(KeyW); + K(KeyX); + K(KeyY); + K(KeyZ); + + K(KeyLeftBracket); + K(KeyRightBracket); + K(KeyBackslash); + K(KeyAccentGrave); + + K(KeyLeftShift); + K(KeyRightShift); + K(KeyLeftControl); + K(KeyRightControl); + K(KeyLeftAlt); + K(KeyRightAlt); + K(KeyCommand); + + K(KeyCapsLock); + K(KeyNumLock); + K(KeyScrollLock); + + K(KeyLeftArrow); + K(KeyRightArrow); + K(KeyUpArrow); + K(KeyDownArrow); + + K(KeyPrintScreen); + K(KeyPause); + + K(KeyInsert); + K(KeyDelete); + K(KeyHome); + K(KeyEnd); + K(KeyUpPage); + K(KeyDownPage); + + K(KeyNumpad0); + K(KeyNumpad1); + K(KeyNumpad2); + K(KeyNumpad3); + K(KeyNumpad4); + K(KeyNumpad5); + K(KeyNumpad6); + K(KeyNumpad7); + K(KeyNumpad8); + K(KeyNumpad9); + K(KeyNumpadPeriod); + K(KeyNumpadEnter); + K(KeyNumpadPlus); + K(KeyNumpadMinus); + K(KeyNumpadAsterisk); + K(KeyNumpadSlash); + + K(KeyF1); + K(KeyF2); + K(KeyF3); + K(KeyF4); + K(KeyF5); + K(KeyF6); + K(KeyF7); + K(KeyF8); + K(KeyF9); + K(KeyF10); + K(KeyF11); + K(KeyF12); + K(KeyF13); + K(KeyF14); + K(KeyF15); + K(KeyF16); + K(KeyF17); + K(KeyF18); + K(KeyF19); + K(KeyF20); + K(KeyF21); + K(KeyF22); + K(KeyF23); + K(KeyF24); + + default: + return "KeyUnknown"; + } +#undef K +} + +void event_to_buf(GHOST_EventHandle evt, char buf[128]) { + GHOST_TEventType type= GHOST_GetEventType(evt); + double time= (double) ((GHOST_TInt64) GHOST_GetEventTime(evt))/1000; + GHOST_WindowHandle win= GHOST_GetEventWindow(evt); + void *data= GHOST_GetEventData(evt); + char *pos= buf; + + pos+= sprintf(pos, "event: %6.2f, %16s", time, eventtype_to_string(type)); + if (win) { + char *s= GHOST_GetTitle(win); + pos+= sprintf(pos, " - win: %s", s); + free(s); + } else { + pos+= sprintf(pos, " - sys evt"); + } + switch (type) { + case GHOST_kEventCursorMove: { + GHOST_TEventCursorData *cd= data; + pos+= sprintf(pos, " - pos: (%d, %d)", cd->x, cd->y); + break; + } + case GHOST_kEventButtonDown: + case GHOST_kEventButtonUp: { + GHOST_TEventButtonData *bd= data; + pos+= sprintf(pos, " - but: %d", bd->button); + break; + } + + case GHOST_kEventKeyDown: + case GHOST_kEventKeyUp: { + GHOST_TEventKeyData *kd= data; + pos+= sprintf(pos, " - key: %s (%d)", keytype_to_string(kd->key), kd->key); + if (kd->ascii) pos+= sprintf(pos, " ascii: '%c' (%d)", kd->ascii, kd->ascii); + break; + } + } +} diff --git a/intern/ghost/test/multitest/EventToBuf.h b/intern/ghost/test/multitest/EventToBuf.h new file mode 100644 index 00000000000..be6f37d869b --- /dev/null +++ b/intern/ghost/test/multitest/EventToBuf.h @@ -0,0 +1,35 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +char *eventtype_to_string(GHOST_TEventType type); + +void event_to_buf(GHOST_EventHandle evt, char buf[128]); + diff --git a/intern/ghost/test/multitest/GL.h b/intern/ghost/test/multitest/GL.h new file mode 100644 index 00000000000..b395627d1d8 --- /dev/null +++ b/intern/ghost/test/multitest/GL.h @@ -0,0 +1,43 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#if defined(WIN32) || defined(__APPLE__) + + #ifdef WIN32 + #include <windows.h> + #include <GL/gl.h> + #else // WIN32 + // __APPLE__ is defined + #include <AGL/gl.h> + #endif // WIN32 +#else // defined(WIN32) || defined(__APPLE__) + #include <GL/gl.h> +#endif // defined(WIN32) || defined(__APPLE__) diff --git a/intern/ghost/test/multitest/Makefile b/intern/ghost/test/multitest/Makefile new file mode 100644 index 00000000000..a424a397502 --- /dev/null +++ b/intern/ghost/test/multitest/Makefile @@ -0,0 +1,60 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# GHOST gears test application Makefile +# + +DIR = $(OCGDIR)/intern/ghost/test + +# we don't want a library here, only object files: +ALLTARGETS = $(OBJS) + +include nan_compile.mk +include nan_link.mk + +CFLAGS += $(LEVEL_1_C_WARNINGS) +CCFLAGS += $(LEVEL_1_CPP_WARNINGS) + +CPPFLAGS += -I$(OPENGL_HEADERS) +CPPFLAGS += -I$(NAN_STRING)/include +CPPFLAGS += -I$(NAN_BMFONT)/include +CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include +CPPFLAGS += -I../.. + +OCGGHOST = $(OCGDIR)/intern/ghost + +LIBS = $(OCGGHOST)/$(DEBUG_DIR)libghost.a +SLIBS += $(LCGDIR)/string/lib/libstring.a +SLIBS += $(LCGDIR)/bmfont/lib/libbmfont.a +SLIBS += $(LCGDIR)/guardedalloc/lib/libguardedalloc.a + +all:: + @echo "- link $(DIR)/$(DEBUG_DIR)multitest -" + @$(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)multitest $(OBJS) $(LIBS) $(SLIBS) $(LLIBS) $(DADD) $(LOPTS) diff --git a/intern/ghost/test/multitest/MultiTest.c b/intern/ghost/test/multitest/MultiTest.c new file mode 100755 index 00000000000..c78d9045022 --- /dev/null +++ b/intern/ghost/test/multitest/MultiTest.c @@ -0,0 +1,855 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifdef WIN32 + +#pragma warning(disable: 4244 4305) +#endif + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <math.h> + +#include "GL.h" + +#include "MEM_guardedalloc.h" + +#include "GHOST_C-api.h" +#include "BMF_Api.h" + +#include "Util.h" +#include "Basic.h" +#include "ScrollBar.h" +#include "EventToBuf.h" + +#include "WindowData.h" + +/***/ + +typedef struct _MultiTestApp MultiTestApp; +typedef struct _LoggerWindow LoggerWindow; + +void loggerwindow_log(LoggerWindow *lw, char *line); + +void multitestapp_toggle_extra_window(MultiTestApp *app); +void multitestapp_free_extrawindow(MultiTestApp *app); +LoggerWindow *multitestapp_get_logger(MultiTestApp *app); +GHOST_SystemHandle multitestapp_get_system(MultiTestApp *app); +void multitestapp_exit(MultiTestApp *app); + +/**/ + +void rect_bevel_side(int rect[2][2], int side, float *lt, float *dk, float *col, int width) { + int ltidx= (side/2)%4; + int dkidx= (ltidx + 1 + (side&1))%4; + int i, corner; + + glBegin(GL_LINES); + for (i=0; i<width; i++) { + float ltf= pow(lt[i], 1.0/2.2), dkf= pow(dk[i], 1.0/2.2); + float stf= (dkidx>ltidx)?dkf:ltf; + int lx= rect[1][0]-i-1; + int ly= rect[0][1]+i; + + glColor3f(col[0]*stf, col[1]*stf, col[2]*stf); + for (corner=0; corner<4; corner++) { + int x= (corner==0 || corner==1)?(rect[0][0]+i):(rect[1][0]-i-1); + int y= (corner==0 || corner==3)?(rect[0][1]+i):(rect[1][1]-i-1); + + if (ltidx==corner) + glColor3f(col[0]*ltf, col[1]*ltf, col[2]*ltf); + if (dkidx==corner) + glColor3f(col[0]*dkf, col[1]*dkf, col[2]*dkf); + + glVertex2i(lx, ly); + glVertex2i(lx= x, ly= y); + } + } + glEnd(); + + glColor3fv(col); + glRecti(rect[0][0]+width, rect[0][1]+width, rect[1][0]-width, rect[1][1]-width); +} + +void rect_bevel_smooth(int rect[2][2], int width) { + float *lt= malloc(sizeof(*lt)*width); + float *dk= malloc(sizeof(*dk)*width); + float col[4]; + int i; + + for (i=0; i<width; i++) { + float v= width-1?((float) i/(width-1)):0; + lt[i]= 1.2 + (1.0-1.2)*v; + dk[i]= 0.2 + (1.0-0.2)*v; + } + + glGetFloatv(GL_CURRENT_COLOR, col); + + rect_bevel_side(rect, 3, lt, dk, col, width); + + free(lt); + free(dk); +} + + /* + * MainWindow + */ + +typedef struct { + MultiTestApp *app; + + GHOST_WindowHandle win; + + int size[2]; + + int lmouse[2], lmbut[3]; + + int tmouse[2]; +} MainWindow; + +static void mainwindow_log(MainWindow *mw, char *str) { + loggerwindow_log(multitestapp_get_logger(mw->app), str); +} + +static void mainwindow_do_draw(MainWindow *mw) { + GHOST_ActivateWindowDrawingContext(mw->win); + + if (mw->lmbut[0]) { + glClearColor(0.5, 0.5, 0.5, 1); + } else { + glClearColor(1, 1, 1, 1); + } + glClear(GL_COLOR_BUFFER_BIT); + + glColor3f(0.5, 0.6, 0.8); + glRecti(mw->tmouse[0]-5, mw->tmouse[1]-5, mw->tmouse[0]+5, mw->tmouse[1]+5); + + GHOST_SwapWindowBuffers(mw->win); +} + +static void mainwindow_do_reshape(MainWindow *mw) { + GHOST_RectangleHandle bounds= GHOST_GetClientBounds(mw->win); + + GHOST_ActivateWindowDrawingContext(mw->win); + + mw->size[0]= GHOST_GetWidthRectangle(bounds); + mw->size[1]= GHOST_GetHeightRectangle(bounds); + + glViewport(0, 0, mw->size[0], mw->size[1]); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, mw->size[0], 0, mw->size[1], -1, 1); + glTranslatef(0.375, 0.375, 0.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +static void mainwindow_do_key(MainWindow *mw, GHOST_TKey key, int press) { + switch(key) { + case GHOST_kKeyC: + if (press) + GHOST_SetCursorShape(mw->win, (GHOST_TStandardCursor) (rand()%(GHOST_kStandardCursorNumCursors))); + break; + case GHOST_kKeyLeftBracket: + if (press) + GHOST_SetCursorVisibility(mw->win, 0); + break; + case GHOST_kKeyRightBracket: + if (press) + GHOST_SetCursorVisibility(mw->win, 1); + break; + case GHOST_kKeyE: + if (press) + multitestapp_toggle_extra_window(mw->app); + break; + case GHOST_kKeyQ: + if (press) + multitestapp_exit(mw->app); + break; + case GHOST_kKeyT: + if (press) + mainwindow_log(mw, "TextTest~|`hello`\"world\",<>/"); + break; + case GHOST_kKeyR: + if (press) { + int i; + + mainwindow_log(mw, "Invalidating window 10 times"); + for (i=0; i<10; i++) + GHOST_InvalidateWindow(mw->win); + } + break; + case GHOST_kKeyF11: + if (press) { + GHOST_SetWindowOrder(mw->win, GHOST_kWindowOrderBottom); + } + break; + } +} + +static void mainwindow_do_move(MainWindow *mw, int x, int y) { + mw->lmouse[0]= x, mw->lmouse[1]= y; + + if (mw->lmbut[0]) { + mw->tmouse[0]= x, mw->tmouse[1]= y; + GHOST_InvalidateWindow(mw->win); + } +} + +static void mainwindow_do_button(MainWindow *mw, int which, int press) { + if (which==GHOST_kButtonMaskLeft) { + mw->lmbut[0]= press; + mw->tmouse[0]= mw->lmouse[0], mw->tmouse[1]= mw->lmouse[1]; + GHOST_InvalidateWindow(mw->win); + } else if (which==GHOST_kButtonMaskLeft) { + mw->lmbut[1]= press; + } else if (which==GHOST_kButtonMaskLeft) { + mw->lmbut[2]= press; + } +} + +static void mainwindow_handle(void *priv, GHOST_EventHandle evt) { + MainWindow *mw= priv; + GHOST_TEventType type= GHOST_GetEventType(evt); + char buf[256]; + + event_to_buf(evt, buf); + mainwindow_log(mw, buf); + + switch (type) { + case GHOST_kEventCursorMove: { + GHOST_TEventCursorData *cd= GHOST_GetEventData(evt); + int x, y; + GHOST_ScreenToClient(mw->win, cd->x, cd->y, &x, &y); + mainwindow_do_move(mw, x, mw->size[1]-y-1); + break; + } + case GHOST_kEventButtonDown: + case GHOST_kEventButtonUp: { + GHOST_TEventButtonData *bd= GHOST_GetEventData(evt); + mainwindow_do_button(mw, bd->button, (type == GHOST_kEventButtonDown)); + break; + } + case GHOST_kEventKeyDown: + case GHOST_kEventKeyUp: { + GHOST_TEventKeyData *kd= GHOST_GetEventData(evt); + mainwindow_do_key(mw, kd->key, (type == GHOST_kEventKeyDown)); + break; + } + + case GHOST_kEventWindowUpdate: + mainwindow_do_draw(mw); + break; + case GHOST_kEventWindowSize: + mainwindow_do_reshape(mw); + break; + } +} + +/**/ + +static void mainwindow_timer_proc(GHOST_TimerTaskHandle task, GHOST_TUns64 time) { + MainWindow *mw= GHOST_GetTimerTaskUserData(task); + char buf[64]; + + sprintf(buf, "timer: %6.2f", (double) ((GHOST_TInt64) time)/1000); + mainwindow_log(mw, buf); +} + +MainWindow *mainwindow_new(MultiTestApp *app) { + GHOST_SystemHandle sys= multitestapp_get_system(app); + GHOST_WindowHandle win; + + win= GHOST_CreateWindow(sys, "MultiTest:Main", 40, 40, 400, 400, GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL); + + if (win) { + MainWindow *mw= MEM_callocN(sizeof(*mw), "mainwindow_new"); + mw->app= app; + mw->win= win; + + GHOST_SetWindowUserData(mw->win, windowdata_new(mw, mainwindow_handle)); + + GHOST_InstallTimer(sys, 1000, 10000, mainwindow_timer_proc, mw); + + return mw; + } else { + return NULL; + } +} + +void mainwindow_free(MainWindow *mw) { + GHOST_SystemHandle sys= multitestapp_get_system(mw->app); + + windowdata_free(GHOST_GetWindowUserData(mw->win)); + GHOST_DisposeWindow(sys, mw->win); + MEM_freeN(mw); +} + + /* + * LoggerWindow + */ + +struct _LoggerWindow { + MultiTestApp *app; + + GHOST_WindowHandle win; + + BMF_Font *font; + int fonttexid; + int fontheight; + + int size[2]; + + int ndisplines; + int textarea[2][2]; + ScrollBar *scroll; + + char **loglines; + int nloglines, logsize; + + int lmbut[3]; + int lmouse[2]; +}; + +#define SCROLLBAR_PAD 2 +#define SCROLLBAR_WIDTH 14 +#define TEXTAREA_PAD 2 +static void loggerwindow_recalc_regions(LoggerWindow *lw) { + int nscroll[2][2]; + + nscroll[0][0]= SCROLLBAR_PAD; + nscroll[0][1]= SCROLLBAR_PAD; + nscroll[1][0]= nscroll[0][0] + SCROLLBAR_WIDTH; + nscroll[1][1]= lw->size[1] - SCROLLBAR_PAD - 1; + + lw->textarea[0][0]= nscroll[1][0] + TEXTAREA_PAD; + lw->textarea[0][1]= TEXTAREA_PAD; + lw->textarea[1][0]= lw->size[0] - TEXTAREA_PAD - 1; + lw->textarea[1][1]= lw->size[1] - TEXTAREA_PAD - 1; + + lw->ndisplines= (lw->textarea[1][1]-lw->textarea[0][1])/lw->fontheight; + + scrollbar_set_thumbpct(lw->scroll, (float) lw->ndisplines/lw->nloglines); + scrollbar_set_rect(lw->scroll, nscroll); +} + +static void loggerwindow_setup_window_gl(LoggerWindow *lw) { + glViewport(0, 0, lw->size[0], lw->size[1]); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, lw->size[0], 0, lw->size[1], -1, 1); + glTranslatef(0.375, 0.375, 0.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +static void loggerwindow_do_reshape(LoggerWindow *lw) { + GHOST_RectangleHandle bounds= GHOST_GetClientBounds(lw->win); + + GHOST_ActivateWindowDrawingContext(lw->win); + + lw->size[0]= GHOST_GetWidthRectangle(bounds); + lw->size[1]= GHOST_GetHeightRectangle(bounds); + + loggerwindow_recalc_regions(lw); + loggerwindow_setup_window_gl(lw); +} + +static void loggerwindow_do_draw(LoggerWindow *lw) { + int i, ndisplines, startline; + int sb_rect[2][2], sb_thumb[2][2]; + + GHOST_ActivateWindowDrawingContext(lw->win); + + glClearColor(1, 1, 1, 1); + glClear(GL_COLOR_BUFFER_BIT); + + glColor3f(0.8, 0.8, 0.8); + rect_bevel_smooth(lw->textarea, 4); + + scrollbar_get_rect(lw->scroll, sb_rect); + scrollbar_get_thumb(lw->scroll, sb_thumb); + + glColor3f(0.6, 0.6, 0.6); + rect_bevel_smooth(sb_rect, 1); + + if (scrollbar_is_scrolling(lw->scroll)) { + glColor3f(0.6, 0.7, 0.5); + } else { + glColor3f(0.9, 0.9, 0.92); + } + rect_bevel_smooth(sb_thumb, 1); + + startline= scrollbar_get_thumbpos(lw->scroll)*(lw->nloglines-1); + ndisplines= min_i(lw->ndisplines, lw->nloglines-startline); + + if (lw->fonttexid!=-1) { + glBindTexture(GL_TEXTURE_2D, lw->fonttexid); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glEnable(GL_TEXTURE_2D); + } + glColor3f(0, 0, 0); + for (i=0; i<ndisplines; i++) { + /* stored in reverse order */ + char *line= lw->loglines[(lw->nloglines-1)-(i+startline)]; + int x_pos= lw->textarea[0][0] + 4; + int y_pos= lw->textarea[0][1] + 4 + i*lw->fontheight; + + if (lw->fonttexid==-1) { + glRasterPos2i(x_pos, y_pos); + BMF_DrawString(lw->font, line); + } else { + BMF_DrawStringTexture(lw->font, line, x_pos, y_pos, 0.0); + } + } + if (lw->fonttexid!=-1) { + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + } + + GHOST_SwapWindowBuffers(lw->win); +} + +static void loggerwindow_do_move(LoggerWindow *lw, int x, int y) { + lw->lmouse[0]= x, lw->lmouse[1]= y; + + if (scrollbar_is_scrolling(lw->scroll)) { + scrollbar_keep_scrolling(lw->scroll, y); + GHOST_InvalidateWindow(lw->win); + } +} + +static void loggerwindow_do_button(LoggerWindow *lw, int which, int press) { + if (which==GHOST_kButtonMaskLeft) { + lw->lmbut[0]= press; + + if (press) { + if (scrollbar_contains_pt(lw->scroll, lw->lmouse)) { + scrollbar_start_scrolling(lw->scroll, lw->lmouse[1]); + GHOST_SetCursorShape(lw->win, GHOST_kStandardCursorUpDown); + GHOST_InvalidateWindow(lw->win); + } + } else { + if (scrollbar_is_scrolling(lw->scroll)) { + scrollbar_stop_scrolling(lw->scroll); + GHOST_SetCursorShape(lw->win, GHOST_kStandardCursorDefault); + GHOST_InvalidateWindow(lw->win); + } + } + } else if (which==GHOST_kButtonMaskMiddle) { + lw->lmbut[1]= press; + } else if (which==GHOST_kButtonMaskRight) { + lw->lmbut[2]= press; + } +} + +static void loggerwindow_do_key(LoggerWindow *lw, GHOST_TKey key, int press) { + switch (key) { + case GHOST_kKeyQ: + if (press) + multitestapp_exit(lw->app); + break; + } +} + +static void loggerwindow_handle(void *priv, GHOST_EventHandle evt) { + LoggerWindow *lw= priv; + GHOST_TEventType type= GHOST_GetEventType(evt); + + switch(type) { + case GHOST_kEventCursorMove: { + GHOST_TEventCursorData *cd= GHOST_GetEventData(evt); + int x, y; + GHOST_ScreenToClient(lw->win, cd->x, cd->y, &x, &y); + loggerwindow_do_move(lw, x, lw->size[1]-y-1); + break; + } + case GHOST_kEventButtonDown: + case GHOST_kEventButtonUp: { + GHOST_TEventButtonData *bd= GHOST_GetEventData(evt); + loggerwindow_do_button(lw, bd->button, (type == GHOST_kEventButtonDown)); + break; + } + case GHOST_kEventKeyDown: + case GHOST_kEventKeyUp: { + GHOST_TEventKeyData *kd= GHOST_GetEventData(evt); + loggerwindow_do_key(lw, kd->key, (type == GHOST_kEventKeyDown)); + break; + } + + case GHOST_kEventWindowUpdate: + loggerwindow_do_draw(lw); + break; + case GHOST_kEventWindowSize: + loggerwindow_do_reshape(lw); + break; + } +} + +/**/ + +LoggerWindow *loggerwindow_new(MultiTestApp *app) { + GHOST_SystemHandle sys= multitestapp_get_system(app); + GHOST_TUns32 screensize[2]; + GHOST_WindowHandle win; + + GHOST_GetMainDisplayDimensions(sys, &screensize[0], &screensize[1]); + win= GHOST_CreateWindow(sys, "MultiTest:Logger", 40, screensize[1]-432, 800, 300, GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL); + + if (win) { + LoggerWindow *lw= MEM_callocN(sizeof(*lw), "loggerwindow_new"); + int bbox[2][2]; + lw->app= app; + lw->win= win; + + lw->font= BMF_GetFont(BMF_kScreen12); + lw->fonttexid= BMF_GetFontTexture(lw->font); + + BMF_GetBoundingBox(lw->font, &bbox[0][0], &bbox[0][1], &bbox[1][0], &bbox[1][1]); + lw->fontheight= rect_height(bbox); + + lw->nloglines= lw->logsize= 0; + lw->loglines= MEM_mallocN(sizeof(*lw->loglines)*lw->nloglines, "loglines"); + + lw->scroll= scrollbar_new(2, 40); + + GHOST_SetWindowUserData(lw->win, windowdata_new(lw, loggerwindow_handle)); + + loggerwindow_do_reshape(lw); + + return lw; + } else { + return NULL; + } +} + +void loggerwindow_log(LoggerWindow *lw, char *line) { + if (lw->nloglines==lw->logsize) { + lw->loglines= memdbl(lw->loglines, &lw->logsize, sizeof(*lw->loglines)); + } + + lw->loglines[lw->nloglines++]= string_dup(line); + scrollbar_set_thumbpct(lw->scroll, (float) lw->ndisplines/lw->nloglines); + + GHOST_InvalidateWindow(lw->win); +} + +void loggerwindow_free(LoggerWindow *lw) { + GHOST_SystemHandle sys= multitestapp_get_system(lw->app); + int i; + + for (i=0; i<lw->nloglines; i++) { + MEM_freeN(lw->loglines[i]); + } + MEM_freeN(lw->loglines); + + windowdata_free(GHOST_GetWindowUserData(lw->win)); + GHOST_DisposeWindow(sys, lw->win); + MEM_freeN(lw); +} + + /* + * ExtraWindow + */ + + +typedef struct { + MultiTestApp *app; + + GHOST_WindowHandle win; + + int size[2]; +} ExtraWindow; + +static void extrawindow_do_draw(ExtraWindow *ew) { + GHOST_ActivateWindowDrawingContext(ew->win); + + glClearColor(1, 1, 1, 1); + glClear(GL_COLOR_BUFFER_BIT); + + glColor3f(0.8, 0.8, 0.8); + glRecti(10, 10, ew->size[0]-10, ew->size[1]-10); + + GHOST_SwapWindowBuffers(ew->win); +} + +static void extrawindow_do_reshape(ExtraWindow *ew) { + GHOST_RectangleHandle bounds= GHOST_GetClientBounds(ew->win); + + GHOST_ActivateWindowDrawingContext(ew->win); + + ew->size[0]= GHOST_GetWidthRectangle(bounds); + ew->size[1]= GHOST_GetHeightRectangle(bounds); + + glViewport(0, 0, ew->size[0], ew->size[1]); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, ew->size[0], 0, ew->size[1], -1, 1); + glTranslatef(0.375, 0.375, 0.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +static void extrawindow_do_key(ExtraWindow *ew, GHOST_TKey key, int press) { + switch (key) { + case GHOST_kKeyE: + if (press) + multitestapp_toggle_extra_window(ew->app); + break; + } +} + +static void extrawindow_spin_cursor(ExtraWindow *ew, GHOST_TUns64 time) { + GHOST_TUns8 bitmap[16][2]; + GHOST_TUns8 mask[16][2]; + double ftime= (double) ((GHOST_TInt64) time)/1000; + float angle= fmod(ftime, 1.0) * 3.1415*2; + int i; + + memset(&bitmap, 0, sizeof(bitmap)); + memset(&mask, 0, sizeof(mask)); + + bitmap[0][0] |= mask[0][0] |= 0xF; + bitmap[1][0] |= mask[1][0] |= 0xF; + bitmap[2][0] |= mask[2][0] |= 0xF; + bitmap[3][0] |= mask[3][0] |= 0xF; + + for (i=0; i<7; i++) { + int x = 7 + cos(angle)*i; + int y = 7 + sin(angle)*i; + + mask[y][x/8] |= (1 << (x%8)); + } + for (i=0; i<64; i++) { + float v= (i/63.0) * 3.1415*2; + int x = 7 + cos(v)*7; + int y = 7 + sin(v)*7; + + mask[y][x/8] |= (1 << (x%8)); + } + + GHOST_SetCustomCursorShape(ew->win, bitmap, mask, 0, 0); +} + +static void extrawindow_handle(void *priv, GHOST_EventHandle evt) { + ExtraWindow *ew= priv; + GHOST_TEventType type= GHOST_GetEventType(evt); + char buf[256]; + + event_to_buf(evt, buf); + loggerwindow_log(multitestapp_get_logger(ew->app), buf); + + switch (type) { + case GHOST_kEventKeyDown: + case GHOST_kEventKeyUp: { + GHOST_TEventKeyData *kd= GHOST_GetEventData(evt); + extrawindow_do_key(ew, kd->key, (type == GHOST_kEventKeyDown)); + break; + } + + case GHOST_kEventCursorMove: { + extrawindow_spin_cursor(ew, GHOST_GetEventTime(evt)); + break; + } + + case GHOST_kEventWindowClose: + multitestapp_free_extrawindow(ew->app); + break; + case GHOST_kEventWindowUpdate: + extrawindow_do_draw(ew); + break; + case GHOST_kEventWindowSize: + extrawindow_do_reshape(ew); + break; + } +} + +/**/ + +ExtraWindow *extrawindow_new(MultiTestApp *app) { + GHOST_SystemHandle sys= multitestapp_get_system(app); + GHOST_WindowHandle win; + + win= GHOST_CreateWindow(sys, "MultiTest:Extra", 500, 40, 400, 400, GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL); + + if (win) { + ExtraWindow *ew= MEM_callocN(sizeof(*ew), "mainwindow_new"); + ew->app= app; + ew->win= win; + + GHOST_SetWindowUserData(ew->win, windowdata_new(ew, extrawindow_handle)); + + return ew; + } else { + return NULL; + } +} + +void extrawindow_free(ExtraWindow *ew) { + GHOST_SystemHandle sys= multitestapp_get_system(ew->app); + + windowdata_free(GHOST_GetWindowUserData(ew->win)); + GHOST_DisposeWindow(sys, ew->win); + MEM_freeN(ew); +} + + /* + * MultiTestApp + */ + +struct _MultiTestApp { + GHOST_SystemHandle sys; + MainWindow *main; + LoggerWindow *logger; + ExtraWindow *extra; + + int exit; +}; + +static int multitest_event_handler(GHOST_EventHandle evt, GHOST_TUserDataPtr data) { + MultiTestApp *app= data; + GHOST_WindowHandle win; + + win= GHOST_GetEventWindow(evt); + if (win && !GHOST_ValidWindow(app->sys, win)) { + loggerwindow_log(app->logger, "WARNING: bad event, non-valid window\n"); + return 1; + } + + if (win) { + WindowData *wb= GHOST_GetWindowUserData(win); + + windowdata_handle(wb, evt); + } else { + GHOST_TEventType type= GHOST_GetEventType(evt); + + /* GHOST_kEventQuit are the only 'system' events, + * that is, events without a window. + */ + switch(type) { + case GHOST_kEventQuit: + app->exit= 1; + break; + + default: + fatal("Unhandled system event: %d (%s)\n", type, eventtype_to_string(type)); + break; + } + } + + return 1; +} + +/**/ + +MultiTestApp *multitestapp_new(void) { + MultiTestApp *app= MEM_mallocN(sizeof(*app), "multitestapp_new"); + GHOST_EventConsumerHandle consumer= GHOST_CreateEventConsumer(multitest_event_handler, app); + + app->sys= GHOST_CreateSystem(); + if (!app->sys) + fatal("Unable to create ghost system"); + + if (!GHOST_AddEventConsumer(app->sys, consumer)) + fatal("Unable to add multitest event consumer "); + + app->main= mainwindow_new(app); + if (!app->main) + fatal("Unable to create main window"); + + app->logger= loggerwindow_new(app); + if (!app->logger) + fatal("Unable to create logger window"); + + app->extra= NULL; + app->exit= 0; + + return app; +} + +LoggerWindow *multitestapp_get_logger(MultiTestApp *app) { + return app->logger; +} + +GHOST_SystemHandle multitestapp_get_system(MultiTestApp *app) { + return app->sys; +} + +void multitestapp_free_extrawindow(MultiTestApp *app) { + extrawindow_free(app->extra); + app->extra= NULL; +} + +void multitestapp_toggle_extra_window(MultiTestApp *app) { + if (app->extra) { + multitestapp_free_extrawindow(app); + } else { + app->extra= extrawindow_new(app); + } +} + +void multitestapp_exit(MultiTestApp *app) { + app->exit= 1; +} + +void multitestapp_run(MultiTestApp *app) { + while (!app->exit) { + GHOST_ProcessEvents(app->sys, 1); + GHOST_DispatchEvents(app->sys); + } +} + +void multitestapp_free(MultiTestApp *app) { + mainwindow_free(app->main); + loggerwindow_free(app->logger); + GHOST_DisposeSystem(app->sys); + MEM_freeN(app); +} + + /***/ + +int main(int argc, char **argv) { + MultiTestApp *app= multitestapp_new(); + + multitestapp_run(app); + multitestapp_free(app); + + return 0; +} diff --git a/intern/ghost/test/multitest/ScrollBar.c b/intern/ghost/test/multitest/ScrollBar.c new file mode 100644 index 00000000000..cd690f6f14e --- /dev/null +++ b/intern/ghost/test/multitest/ScrollBar.c @@ -0,0 +1,145 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdlib.h> + +#include <math.h> + +#include "MEM_guardedalloc.h" + +#include "Basic.h" +#include "ScrollBar.h" + +struct _ScrollBar { + int rect[2][2]; + float thumbpos, thumbpct; + + int inset; + int minthumb; + + int scrolling; + float scrolloffs; +}; + +static int scrollbar_get_thumbH(ScrollBar *sb) { + int scrollable_h= rect_height(sb->rect) - 2*sb->inset; + + return clamp_i(sb->thumbpct*scrollable_h, sb->minthumb, scrollable_h); +} +static int scrollbar_get_thumbableH(ScrollBar *sb) { + int scrollable_h= rect_height(sb->rect) - 2*sb->inset; + int thumb_h= scrollbar_get_thumbH(sb); + + return scrollable_h - thumb_h; +} + +static float scrollbar_co_to_pos(ScrollBar *sb, int yco) { + int thumb_h= scrollbar_get_thumbH(sb); + int thumbable_h= scrollbar_get_thumbableH(sb); + int thumbable_y= (sb->rect[0][1]+sb->inset) + thumb_h/2; + + return (float) (yco-thumbable_y)/thumbable_h; +} + +/**/ + +ScrollBar *scrollbar_new(int inset, int minthumb) { + ScrollBar *sb= MEM_callocN(sizeof(*sb), "scrollbar_new"); + sb->inset= inset; + sb->minthumb= minthumb; + + return sb; +} + +void scrollbar_get_thumb(ScrollBar *sb, int thumb_r[2][2]) { + int thumb_h= scrollbar_get_thumbH(sb); + int thumbable_h= scrollbar_get_thumbableH(sb); + + thumb_r[0][0]= sb->rect[0][0]+sb->inset; + thumb_r[1][0]= sb->rect[1][0]-sb->inset; + + thumb_r[0][1]= sb->rect[0][1]+sb->inset + sb->thumbpos*thumbable_h; + thumb_r[1][1]= thumb_r[0][1] + thumb_h; +} + +int scrollbar_is_scrolling(ScrollBar *sb) { + return sb->scrolling; +} +int scrollbar_contains_pt(ScrollBar *sb, int pt[2]) { + return rect_contains_pt(sb->rect, pt); +} + +void scrollbar_start_scrolling(ScrollBar *sb, int yco) { + int thumb_h_2= scrollbar_get_thumbH(sb)/2; + int thumbable_h= scrollbar_get_thumbableH(sb); + float npos= scrollbar_co_to_pos(sb, yco); + + sb->scrolloffs= sb->thumbpos - npos; + if (fabs(sb->scrolloffs) >= (float) thumb_h_2/thumbable_h) { + sb->scrolloffs= 0.0; + } + + sb->scrolling= 1; + sb->thumbpos= clamp_f(npos + sb->scrolloffs, 0.0, 1.0); +} +void scrollbar_keep_scrolling(ScrollBar *sb, int yco) { + float npos= scrollbar_co_to_pos(sb, yco); + + sb->thumbpos= clamp_f(npos + sb->scrolloffs, 0.0, 1.0); +} +void scrollbar_stop_scrolling(ScrollBar *sb) { + sb->scrolling= 0; + sb->scrolloffs= 0.0; +} + +void scrollbar_set_thumbpct(ScrollBar *sb, float pct) { + sb->thumbpct= pct; +} +void scrollbar_set_thumbpos(ScrollBar *sb, float pos) { + sb->thumbpos= clamp_f(pos, 0.0, 1.0); +} +void scrollbar_set_rect(ScrollBar *sb, int rect[2][2]) { + rect_copy(sb->rect, rect); +} + +float scrollbar_get_thumbpct(ScrollBar *sb) { + return sb->thumbpct; +} +float scrollbar_get_thumbpos(ScrollBar *sb) { + return sb->thumbpos; +} +void scrollbar_get_rect(ScrollBar *sb, int rect_r[2][2]) { + rect_copy(rect_r, sb->rect); +} + +void scrollbar_free(ScrollBar *sb) { + MEM_freeN(sb); +} diff --git a/intern/ghost/test/multitest/ScrollBar.h b/intern/ghost/test/multitest/ScrollBar.h new file mode 100644 index 00000000000..30e49e8b531 --- /dev/null +++ b/intern/ghost/test/multitest/ScrollBar.h @@ -0,0 +1,56 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +typedef struct _ScrollBar ScrollBar; + + + /***/ + +ScrollBar* scrollbar_new (int inset, int minthumb); + +int scrollbar_is_scrolling (ScrollBar *sb); +int scrollbar_contains_pt (ScrollBar *sb, int pt[2]); + +void scrollbar_start_scrolling (ScrollBar *sb, int yco); +void scrollbar_keep_scrolling (ScrollBar *sb, int yco); +void scrollbar_stop_scrolling (ScrollBar *sb); + +void scrollbar_set_thumbpct (ScrollBar *sb, float pct); +void scrollbar_set_thumbpos (ScrollBar *sb, float pos); +void scrollbar_set_rect (ScrollBar *sb, int rect[2][2]); + +float scrollbar_get_thumbpct (ScrollBar *sb); +float scrollbar_get_thumbpos (ScrollBar *sb); +void scrollbar_get_rect (ScrollBar *sb, int rect_r[2][2]); + +void scrollbar_get_thumb (ScrollBar *sb, int thumb_r[2][2]); + +void scrollbar_free (ScrollBar *sb); diff --git a/intern/ghost/test/multitest/Util.c b/intern/ghost/test/multitest/Util.c new file mode 100644 index 00000000000..31e43f6f5da --- /dev/null +++ b/intern/ghost/test/multitest/Util.c @@ -0,0 +1,73 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdlib.h> + +#include <string.h> +#include <stdarg.h> +#include <stdio.h> + +#include "MEM_guardedalloc.h" + +#include "Util.h" + +void* memdbl(void *mem, int *size_pr, int item_size) { + int cur_size= *size_pr; + int new_size= cur_size?(cur_size*2):1; + void *nmem= MEM_mallocN(new_size*item_size, "memdbl"); + + memcpy(nmem, mem, cur_size*item_size); + MEM_freeN(mem); + + *size_pr= new_size; + return nmem; +} + +char* string_dup(char *str) { + int len= strlen(str); + char *nstr= MEM_mallocN(len + 1, "string_dup"); + + memcpy(nstr, str, len+1); + + return nstr; +} + +void fatal(char *fmt, ...) { + va_list ap; + + fprintf(stderr, "FATAL: "); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + + exit(1); +} diff --git a/intern/ghost/test/multitest/Util.h b/intern/ghost/test/multitest/Util.h new file mode 100644 index 00000000000..1146112c9c4 --- /dev/null +++ b/intern/ghost/test/multitest/Util.h @@ -0,0 +1,35 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +void* memdbl (void *mem, int *size_pr, int item_size); + +char* string_dup (char *str); +void fatal (char *fmt, ...); diff --git a/intern/ghost/test/multitest/WindowData.c b/intern/ghost/test/multitest/WindowData.c new file mode 100644 index 00000000000..ee377c98b58 --- /dev/null +++ b/intern/ghost/test/multitest/WindowData.c @@ -0,0 +1,60 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdlib.h> + + +#include "MEM_guardedalloc.h" + +#include "GHOST_C-api.h" + +#include "WindowData.h" + +struct _WindowData { + void *data; + WindowDataHandler handler; +}; + +WindowData *windowdata_new(void *data, WindowDataHandler handler) { + WindowData *wb= MEM_mallocN(sizeof(*wb), "windowdata_new"); + wb->data= data; + wb->handler= handler; + + return wb; +} + +void windowdata_handle(WindowData *wb, GHOST_EventHandle evt) { + wb->handler(wb->data, evt); +} + +void windowdata_free(WindowData *wb) { + MEM_freeN(wb); +} diff --git a/intern/ghost/test/multitest/WindowData.h b/intern/ghost/test/multitest/WindowData.h new file mode 100644 index 00000000000..a046c41d90c --- /dev/null +++ b/intern/ghost/test/multitest/WindowData.h @@ -0,0 +1,40 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +typedef void (*WindowDataHandler)(void *priv, GHOST_EventHandle evt); + +typedef struct _WindowData WindowData; + + /***/ + +WindowData* windowdata_new (void *data, WindowDataHandler handler); +void windowdata_handle (WindowData *wb, GHOST_EventHandle evt); +void windowdata_free (WindowData *wb); diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h new file mode 100644 index 00000000000..0fab1aa0bda --- /dev/null +++ b/intern/guardedalloc/MEM_guardedalloc.h @@ -0,0 +1,114 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * Guarded memory (de)allocation + * + * + * @mainpage MEM - c-style guarded memory allocation + * + * @section about About the MEM module + * + * MEM provides guarded malloc/calloc calls. All memory is enclosed by + * pads, to detect out-of-bound writes. All blocks are placed in a + * linked list, so they remain reachable at all times. There is no + * back-up in case the linked-list related data is lost. + * + * @section issues Known issues with MEM + * + * There are currently no known issues with MEM. Note that there is a + * second intern/ module with MEM_ prefix, for use in c++. + * + * @section dependencies Dependencies + * + * - stdlib + * + * - stdio + * + * */ + +#ifndef MEM_MALLOCN_H +#define MEM_MALLOCN_H + +/* Needed for FILE* */ +#include "stdio.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /** Returns the lenght of the allocated memory segment pointed at + * by vmemh. If the pointer was not previously allocated by this + * module, the result is undefined.*/ + int MEM_allocN_len(void *vmemh); + + /** + * Release memory previously allocatred by this module. + */ + short MEM_freeN(void *vmemh); + + /** + * Duplicates a block of memory, and returns a pointer to the + * newly allocated block. */ + void *MEM_dupallocN(void *vmemh); + + /** + * Allocate a block of memory of size len, with tag name str. The + * memory is cleared. The name must be static, because only a + * pointer to it is stored ! */ + void *MEM_callocN(unsigned int len, char * str); + + /** Allocate a block of memory of size len, with tag name str. The + * name must be a static, because only a pointer to it is stored ! + * */ + void *MEM_mallocN(unsigned int len, char * str); + + /** Print a list of the names and sizes of all allocated memory + * blocks. */ + void MEM_printmemlist(void); + + /** Set the stream for error output. */ + void MEM_set_error_stream(FILE*); + + /** + * Are the start/end block markers still correct ? + * + * @retval 0 for correct memory, 1 for corrupted memory. */ + int MEM_check_memory_integrity(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/intern/guardedalloc/Makefile b/intern/guardedalloc/Makefile new file mode 100644 index 00000000000..9957d8aa417 --- /dev/null +++ b/intern/guardedalloc/Makefile @@ -0,0 +1,52 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# decimation main makefile. +# + +include nan_definitions.mk + +LIBNAME = guardedalloc +SOURCEDIR = intern/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = intern +TESTDIRS = test + +include nan_subdirs.mk + +install: all debug + @[ -d $(NAN_GUARDEDALLOC) ] || mkdir $(NAN_GUARDEDALLOC) + @[ -d $(NAN_GUARDEDALLOC)/include ] || mkdir $(NAN_GUARDEDALLOC)/include + @[ -d $(NAN_GUARDEDALLOC)/lib ] || mkdir $(NAN_GUARDEDALLOC)/lib + @[ -d $(NAN_GUARDEDALLOC)/lib/debug ] || mkdir $(NAN_GUARDEDALLOC)/lib/debug + cp -f $(DIR)/libguardedalloc.a $(NAN_GUARDEDALLOC)/lib/ + cp -f $(DIR)/debug/libguardedalloc.a $(NAN_GUARDEDALLOC)/lib/debug/ + cp -f *.h $(NAN_GUARDEDALLOC)/include/ + diff --git a/intern/guardedalloc/intern/Makefile b/intern/guardedalloc/intern/Makefile new file mode 100644 index 00000000000..bc96ba5f27f --- /dev/null +++ b/intern/guardedalloc/intern/Makefile @@ -0,0 +1,42 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# guardedalloc intern Makefile +# + +LIBNAME = guardedalloc +DIR = $(OCGDIR)/intern/$(LIBNAME) + +include nan_compile.mk + +CFLAGS += $(NAN_LEVEL_2_C_WARNINGS) + +CPPFLAGS += -I.. + diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c new file mode 100644 index 00000000000..64bfdea9d9a --- /dev/null +++ b/intern/guardedalloc/intern/mallocn.c @@ -0,0 +1,457 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * Guarded memory allocation, and boundary-write detection. + */ + +#include <stdlib.h> + +#include "MEM_guardedalloc.h" + +/* --------------------------------------------------------------------- */ +/* Data definition */ +/* --------------------------------------------------------------------- */ +/* all memory chunks are put in linked lists */ +typedef struct localLink +{ + struct localLink *next,*prev; +} localLink; + +typedef struct localListBase +{ + void *first, *last; +} localListBase; + +typedef struct MemHead { + int tag1; + int len; + struct MemHead *next,*prev; + char * name; + char * nextname; + /* int level; */ /* historical, can be removed, but check alignment issues - zr */ + int tag2; +} MemHead; + +typedef struct MemTail { + int tag3, pad; +} MemTail; + +/* --------------------------------------------------------------------- */ +/* local functions */ +/* --------------------------------------------------------------------- */ + +static void addtail(localListBase *listbase, void *vlink); +static void remlink(localListBase *listbase, void *vlink); +static void rem_memblock(MemHead *memh); +static void MemorY_ErroR(char *block, char *error); +static char *check_memlist(MemHead *memh); + +/* --------------------------------------------------------------------- */ +/* locally used defines */ +/* --------------------------------------------------------------------- */ + +#if defined( __sgi) || defined (__sun__) || defined (__PPC__) || defined (__APPLE__) +#define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) ) +#else +#define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) ) +#endif + +#define MEMTAG1 MAKE_ID('M', 'E', 'M', 'O') +#define MEMTAG2 MAKE_ID('R', 'Y', 'B', 'L') +#define MEMTAG3 MAKE_ID('O', 'C', 'K', '!') +#define MEMFREE MAKE_ID('F', 'R', 'E', 'E') + +#define MEMNEXT(x) ((MemHead *)(((char *) x) - ((char *) & (((MemHead *)0)->next)))) + +/* --------------------------------------------------------------------- */ +/* vars */ +/* --------------------------------------------------------------------- */ + +int totblock= 0; +int mem_in_use= 0; + +static struct localListBase _membase; +static struct localListBase *membase = &_membase; +static FILE* err_stream = NULL; + +#ifdef malloc +#undef malloc +#endif + +#ifdef calloc +#undef calloc +#endif + +#ifdef free +#undef free +#endif + + +/* --------------------------------------------------------------------- */ +/* implementation */ +/* --------------------------------------------------------------------- */ + +int MEM_check_memory_integrity() +{ + char* err_val = NULL; + MemHead* listend; + /* check_memlist starts from the front, and runs until it finds + * the requested chunk. For this test, that's the last one. */ + listend = membase->last; + + err_val = check_memlist(listend); + + return (int)err_val; +} + + +void MEM_set_error_stream(FILE* i) +{ + err_stream = i; +} + + +int MEM_allocN_len(void *vmemh) +{ + if (vmemh) { + MemHead *memh= vmemh; + + memh--; + return memh->len; + } else + return 0; +} + +void *MEM_dupallocN(void *vmemh) +{ + void *newp= NULL; + + if (vmemh) { + MemHead *memh= vmemh; + memh--; + + if (memh->len) { + newp= MEM_mallocN(memh->len, "dupli_alloc"); + memcpy(newp, vmemh, memh->len); + } else + if (err_stream) fprintf(err_stream, "error: MEM_dupallocN with len==0 %s\n", memh->name); + } + + return newp; +} + +void *MEM_mallocN(unsigned int len, char *str) +{ + MemHead *memh; + MemTail *memt; + + if(sizeof(long)==8) + len = (len + 3 ) & ~3; /* eenheden van 4 */ + else + len = (len + 7 ) & ~7; /* eenheden van 8 */ + + memh= (MemHead *)malloc(len+sizeof(MemHead)+sizeof(MemTail)); + + if(memh!=0) { + memh->tag1 = MEMTAG1; + memh->name = str; + memh->nextname = 0; + memh->len = len; +/* memh->level = 0; */ + memh->tag2 = MEMTAG2; + + memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + len); + memt->tag3 = MEMTAG3; + + addtail(membase,&memh->next); + if (memh->next) memh->nextname = MEMNEXT(memh->next)->name; + + totblock++; + mem_in_use += len; + return (++memh); + } + if (err_stream) fprintf(err_stream, "Malloc returns nill: len=%d in %s\n",len,str); + return 0; +} + +void *MEM_callocN(unsigned int len, char *str) +{ + MemHead *memh; + MemTail *memt; + + if(sizeof(long)==8) + len = (len + 3 ) & ~3; /* eenheden van 4 */ + else + len = (len + 7 ) & ~7; /* eenheden van 8 */ + + memh= (MemHead *)calloc(len+sizeof(MemHead)+sizeof(MemTail),1); + + if(memh!=0) { + memh->tag1 = MEMTAG1; + memh->name = str; + memh->nextname = 0; + memh->len = len; +/* memh->level = 0; */ + memh->tag2 = MEMTAG2; + + memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + len); + memt->tag3 = MEMTAG3; + + addtail(membase,&memh->next); + if (memh->next) memh->nextname = MEMNEXT(memh->next)->name; + + totblock++; + mem_in_use += len; + return (++memh); + } + if (err_stream) fprintf(err_stream, "Calloc returns nill: len=%d in %s\n",len,str); + return 0; +} + + +void MEM_printmemlist() +{ + MemHead *membl; + + membl = membase->first; + if (membl) membl = MEMNEXT(membl); + while(membl) { + if (err_stream) fprintf(err_stream, "%s len: %d %p\n",membl->name,membl->len, membl+1); + if(membl->next) + membl= MEMNEXT(membl->next); + else break; + } +} + +short MEM_freeN(void *vmemh) /* anders compileertie niet meer */ +{ + short error = 0; + MemTail *memt; + MemHead *memh= vmemh; + char *name; + + if (memh == 0){ + MemorY_ErroR("free","attempt to free NULL pointer"); + /* if (err_stream) fprintf(err_stream, "%d\n", (memh+4000)->tag1); */ + return(-1); + } + + if(sizeof(long)==8) { + if (((long) memh) & 0x7) { + MemorY_ErroR("free","attempt to free illegal pointer"); + return(-1); + } + } + else { + if (((long) memh) & 0x3) { + MemorY_ErroR("free","attempt to free illegal pointer"); + return(-1); + } + } + + memh--; + if(memh->tag1 == MEMFREE && memh->tag2 == MEMFREE) { + MemorY_ErroR(memh->name,"double free"); + return(-1); + } + + if ((memh->tag1 == MEMTAG1) && (memh->tag2 == MEMTAG2) && ((memh->len & 0x3) == 0)) { + memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + memh->len); + if (memt->tag3 == MEMTAG3){ + + memh->tag1 = MEMFREE; + memh->tag2 = MEMFREE; + memt->tag3 = MEMFREE; + /* na tags !!! */ + rem_memblock(memh); + + return(0); + } + error = 2; + MemorY_ErroR(memh->name,"end corrupt"); + name = check_memlist(memh); + if (name != 0){ + if (name != memh->name) MemorY_ErroR(name,"is also corrupt"); + } + } else{ + error = -1; + name = check_memlist(memh); + if (name == 0) MemorY_ErroR("free","pointer not in memlist"); + else MemorY_ErroR(name,"error in header"); + } + + totblock--; + /* hier moet een DUMP plaatsvinden */ + + return(error); +} + +/* --------------------------------------------------------------------- */ +/* local functions */ +/* --------------------------------------------------------------------- */ + +static void addtail(localListBase *listbase, void *vlink) +{ + struct localLink *link= vlink; + + if (link == 0) return; + if (listbase == 0) return; + + link->next = 0; + link->prev = listbase->last; + + if (listbase->last) ((struct localLink *)listbase->last)->next = link; + if (listbase->first == 0) listbase->first = link; + listbase->last = link; +} + +static void remlink(localListBase *listbase, void *vlink) +{ + struct localLink *link= vlink; + + if (link == 0) return; + if (listbase == 0) return; + + if (link->next) link->next->prev = link->prev; + if (link->prev) link->prev->next = link->next; + + if (listbase->last == link) listbase->last = link->prev; + if (listbase->first == link) listbase->first = link->next; +} + +static void rem_memblock(MemHead *memh) +{ + remlink(membase,&memh->next); + if (memh->prev){ + if (memh->next) MEMNEXT(memh->prev)->nextname = MEMNEXT(memh->next)->name; + else MEMNEXT(memh->prev)->nextname = 0; + } + + totblock--; + mem_in_use -= memh->len; + free(memh); +} + +static void MemorY_ErroR(char *block, char *error) +{ + if (err_stream) fprintf(err_stream,"Memoryblock %s: %s\n",block,error); +} + +static char *check_memlist(MemHead *memh) +{ + MemHead *forw,*back,*forwok,*backok; + char *name; + + forw = membase->first; + if (forw) forw = MEMNEXT(forw); + forwok = 0; + while(forw){ + if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2) break; + forwok = forw; + if (forw->next) forw = MEMNEXT(forw->next); + else forw = 0; + } + + back = (MemHead *) membase->last; + if (back) back = MEMNEXT(back); + backok = 0; + while(back){ + if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2) break; + backok = back; + if (back->prev) back = MEMNEXT(back->prev); + else back = 0; + } + + if (forw != back) return ("MORE THAN 1 MEMORYBLOCK CORRUPT"); + + if (forw == 0 && back == 0){ + /* geen foute headers gevonden dan maar op zoek naar memblock*/ + + forw = membase->first; + if (forw) forw = MEMNEXT(forw); + forwok = 0; + while(forw){ + if (forw == memh) break; + if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2) break; + forwok = forw; + if (forw->next) forw = MEMNEXT(forw->next); + else forw = 0; + } + if (forw == 0) return (0); + + back = (MemHead *) membase->last; + if (back) back = MEMNEXT(back); + backok = 0; + while(back){ + if (back == memh) break; + if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2) break; + backok = back; + if (back->prev) back = MEMNEXT(back->prev); + else back = 0; + } + } + + if (forwok) name = forwok->nextname; + else name = "No name found"; + + if (forw == memh){ + /* voor alle zekerheid wordt dit block maar uit de lijst gehaald */ + if (forwok){ + if (backok){ + forwok->next = (MemHead *)&backok->next; + backok->prev = (MemHead *)&forwok->next; + forwok->nextname = backok->name; + } else{ + forwok->next = 0; + membase->last = (struct localLink *) &forwok->next; +/* membase->last = (struct Link *) &forwok->next; */ + } + } else{ + if (backok){ + backok->prev = 0; + membase->first = &backok->next; + } else{ + membase->first = membase->last = 0; + } + } + } else{ + MemorY_ErroR(name,"Additional error in header"); + return("Additional error in header"); + } + + return(name); +} + +/* eof */ diff --git a/intern/guardedalloc/test/Makefile b/intern/guardedalloc/test/Makefile new file mode 100644 index 00000000000..760695bd19e --- /dev/null +++ b/intern/guardedalloc/test/Makefile @@ -0,0 +1,55 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# Test the guarded memory module +# + +LIBNAME = guardedalloc +SOURCEDIR = intern/$(LIBNAME)/test +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = simpletest + +include nan_subdirs.mk + +include nan_compile.mk +include nan_link.mk + +TESTLIBS = $(OCGDIR)/intern/$(LIBNAME)/$(DEBUG_DIR)lib$(LIBNAME).a + +all debug:: + @echo "****> linking $@ in $(SOURCEDIR)" + $(CC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)memtest $(DIR)/memtest.o $(TESTLIBS) + +clean:: + $(RM) $(DIR)/memtest $(DIR)/debug/memtest + +test:: $(DIR)/memtest + $(DIR)/memtest $(NAN_TEST_VERBOSITY) + diff --git a/intern/guardedalloc/test/simpletest/Makefile b/intern/guardedalloc/test/simpletest/Makefile new file mode 100644 index 00000000000..8f1db9c4cac --- /dev/null +++ b/intern/guardedalloc/test/simpletest/Makefile @@ -0,0 +1,44 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# Test the guarded memory module +# + +LIBNAME = guardedalloc +DIR = $(OCGDIR)/intern/$(LIBNAME)/test + +# we don't want a library here, only object files: +ALLTARGETS = $(OBJS) + +include nan_compile.mk + +# this module's header +CPPFLAGS = -I../.. + diff --git a/intern/guardedalloc/test/simpletest/memtest.c b/intern/guardedalloc/test/simpletest/memtest.c new file mode 100644 index 00000000000..f2cdc207958 --- /dev/null +++ b/intern/guardedalloc/test/simpletest/memtest.c @@ -0,0 +1,158 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * Simple test of memory. + */ + + + +/* Number of chunks to test with */ +#define NUM_BLOCKS 10 + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "MEM_guardedalloc.h" + +int main (int argc, char *argv[]) +{ + int verbose = 0; + int error_status = 0; + int retval = 0; + int *ip; + + void *p[NUM_BLOCKS]; + int i = 0; + + /* ----------------------------------------------------------------- */ + switch (argc) { + case 2: + verbose = atoi(argv[1]); + if (verbose < 0) verbose = 0; + break; + case 1: + default: + verbose = 0; + } + if (verbose) { + fprintf(stderr,"\n*** Simple memory test\n|\n"); + } + + /* ----------------------------------------------------------------- */ + /* Round one, do a normal allocation, and free the blocks again. */ + /* ----------------------------------------------------------------- */ + /* flush mem lib output to stderr */ + MEM_set_error_stream(stderr); + + for (i = 0; i < NUM_BLOCKS; i++) { + int blocksize = 10000; + char tagstring[1000]; + if (verbose >1) printf("|--* Allocating block %d\n", i); + sprintf(tagstring,"Memblock no. %d : ", i); + p[i]= MEM_callocN(blocksize, strdup(tagstring)); + } + + /* report on that */ + if (verbose > 1) MEM_printmemlist(); + + /* memory is there: test it */ + error_status = MEM_check_memory_integrity(); + + if (verbose) { + if (error_status) { + fprintf(stderr, "|--* Memory test FAILED\n|\n"); + } else { + fprintf(stderr, "|--* Memory tested as good (as it should be)\n|\n"); + } + } + + for (i = 0; i < NUM_BLOCKS; i++) { + MEM_freeN(p[i]); + } + + /* ----------------------------------------------------------------- */ + /* Round two, do a normal allocation, and corrupt some blocks. */ + /* ----------------------------------------------------------------- */ + /* switch off, because it will complain about some things. */ + MEM_set_error_stream(NULL); + + for (i = 0; i < NUM_BLOCKS; i++) { + int blocksize = 10000; + char tagstring[1000]; + if (verbose >1) printf("|--* Allocating block %d\n", i); + sprintf(tagstring,"Memblock no. %d : ", i); + p[i]= MEM_callocN(blocksize, strdup(tagstring)); + } + + /* now corrupt a few blocks...*/ + ip = (int*) p[5] - 50 ; + for (i = 0; i< 1000; i++,ip++) *ip = i+1; + ip = (int*) p[6]; + *(ip+10005) = 0; + + retval = MEM_check_memory_integrity(); + + /* the test should have failed */ + error_status |= !retval; + if (verbose) { + if (retval) { + fprintf(stderr, "|--* Memory test failed (as it should be)\n"); + } else { + fprintf(stderr, "|--* Memory test FAILED to find corrupted blocks \n"); + } + } + + for (i = 0; i < NUM_BLOCKS; i++) { + MEM_freeN(p[i]); + } + + + if (verbose && error_status) { + fprintf(stderr,"|--* Memory was corrupted\n"); + } + /* ----------------------------------------------------------------- */ + if (verbose) { + if (error_status) { + fprintf(stderr,"|\n|--* Errors were detected\n"); + } else { + fprintf(stderr,"|\n|--* Test exited succesfully\n"); + } + + fprintf(stderr,"|\n*** Finished test\n\n"); + } + return error_status; +} + + diff --git a/intern/iksolver/Makefile b/intern/iksolver/Makefile new file mode 100644 index 00000000000..8cdb81ca780 --- /dev/null +++ b/intern/iksolver/Makefile @@ -0,0 +1,52 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# iksolver main makefile. +# + +include nan_definitions.mk + +LIBNAME = iksolver +SOURCEDIR = intern/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = intern +TESTDIRS = test + +include nan_subdirs.mk + +install: all debug + @[ -d $(NAN_IKSOLVER) ] || mkdir $(NAN_IKSOLVER) + @[ -d $(NAN_IKSOLVER)/include ] || mkdir $(NAN_IKSOLVER)/include + @[ -d $(NAN_IKSOLVER)/lib ] || mkdir $(NAN_IKSOLVER)/lib + @[ -d $(NAN_IKSOLVER)/lib/debug ] || mkdir $(NAN_IKSOLVER)/lib/debug + cp -f $(DIR)/libiksolver.a $(NAN_IKSOLVER)/lib/ + cp -f $(DIR)/debug/libiksolver.a $(NAN_IKSOLVER)/lib/debug/ + cp -f extern/*.h $(NAN_IKSOLVER)/include/ + diff --git a/intern/iksolver/extern/IK_solver.h b/intern/iksolver/extern/IK_solver.h new file mode 100644 index 00000000000..57d06a3ba32 --- /dev/null +++ b/intern/iksolver/extern/IK_solver.h @@ -0,0 +1,207 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * + * @author Laurence + * @mainpage IK - Blender inverse kinematics module. + * + * @section about About the IK module + * + * This module allows you to create segments and form them into + * chains. You can then define a goal point that the end of the + * chain should attempt to reach - an inverse kinematic problem. + * This module will then modify the segments in the chain in + * order to get the end of the chain as near as possible to the + * goal. This solver uses an inverse jacobian method to find + * a solution. + * + * @section issues Known issues with this IK solver. + * + * - The current solver works with only one type of segment. These + * segments always have 3 degress of freedom (DOF). i.e. the solver + * uses all these degrees to solve the IK problem. It would be + * nice to allow the user to specify different segment types such + * as 1 DOF joints in a given plane. 2 DOF joints about given axis. + * - There is currently no support for joint constraints in the + * solver. This is within the realms of possibility - please ask + * if this functionality is required. + * - The solver is slow, inverse jacobian methods in general give + * 'smooth' solutions and the method is also very flexible, it + * does not rely on specific angle parameterization and can be + * extended to deal with different joint types and joint + * constraints. However it is not suitable for real time use. + * Other algorithms exist which are more suitable for real-time + * applications, please ask if this functionality is required. + * + * @section dependencies Dependencies + * + * This module only depends on Moto. + */ + +#ifndef NAN_INCLUDED_IK_solver_h +#define NAN_INCLUDED_IK_solver_h + + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * External segment structure + */ + + +/** + * This structure defines a single segment of an IK chain. + * - Individual segments are always defined in local coordinates. + * - The segment is assumed to be oriented in the local + * y-direction. + * - seg_start is the start of the segment relative to the end + * of the parent segment. + * - basis is a column major matrix defining the rest position + * of the bone. + * - length is the simply the length of the bone. + * - basis_change is a 3x3 matrix representing the change + * from the rest position of the segment to the solved position. + * In fact it is the transpose of this matrix because blender + * does something weird with quaternion conversion. This is + * strictly an ouput variable for returning the results of an + * an ik solve back to you. + * The local transformation specified as a column major matrix + * of a segment is then defined as. + * translate(seg_start)*basis*transpose(basis_change)*translate(0,length,0) + */ + +typedef struct IK_Segment_Extern { + float seg_start[3]; + float basis[9]; + float length; + float basis_change[9]; +} IK_Segment_Extern; + +typedef IK_Segment_Extern* IK_Segment_ExternPtr; + +/** + * External chain structure. + * This structure is filled when you call IK_LoadChain. + * The first segment in the chain is the root segment. + * The end of the last segment is the end-effector of the chain + * this is the point that tries to move to the goal in the ik + * solver. + * - num_segments is the number of segments in the array pointed + * to by the member segments. + * - chain_dof is the number of degrees of freedom of the chain + * that is the number of independent ways the chain can be changed + * to reach the goal. + * - segments points to an array of IK_Segment_Extern structs + * containing the segments of this chain. + * - intern is pointer used by the module to store information + * about the chain. Please do not touch the member in any way. + */ + +typedef struct IK_Chain_Extern { + int num_segments; + int chain_dof; + IK_Segment_ExternPtr segments; + void * intern; +} IK_Chain_Extern; + +typedef IK_Chain_Extern* IK_Chain_ExternPtr; + + +/** + * Create a clean chain structure. + * @return A IK_Chain_Extern structure allocated on the heap. + * Do not attempt to delete or free this memory yourself please + * use the FreeChain(...) function for this. + */ + +extern IK_Chain_ExternPtr IK_CreateChain(void); + +/** + * Copy segment information into the chain structure. + * @param chain A chain to load the segments into. + * @param segments a ptr to an array of IK_Input_Segment_Extern structures + * @param num_segs the number of segments to load into the chain + * @return 1 if the chain was correctly loaded into the structure. + * @return 0 if an error occured loading the chain. This will normally + * occur when there is not enough memory to allocate internal chain data. + * In this case you should not use the chain structure and should call + * IK_FreeChain to free the memory associated with the chain. + */ + +extern int IK_LoadChain(IK_Chain_ExternPtr chain,IK_Segment_ExternPtr segments, int num_segs); + +/** + * Compute the solution of an inverse kinematic problem. + * @param chain a ptr to an IK_Segment_Extern loaded with the segments + * to solve for. + * @param goal the goal of the IK problem + * @param tolerance .The distance to the solution within which the chain is deemed + * to be solved. + * @param max_iterations. The maximum number of iterations to use in solving the + * problem. + * @param max_angle_change. The maximum allowed angular change. 0.1 is a good value here. + * @param output. Results of the solution are written to the segments pointed to by output. + * Only the basis and basis_change fields are written. You must make sure that you have + * allocated enough room for the output segments. + * @return 0 if the solved chain did not reach the goal. This occurs when the + * goal was unreachable by the chain end effector. + * @return 1 if the chain reached the goal. + */ + +extern int IK_SolveChain( + IK_Chain_ExternPtr chain, + float goal[3], + float tolerance, + int max_iterations, + float max_angle_change, + IK_Segment_ExternPtr output +); + +/** + * Free a chain and all it's internal memory. + */ + +extern void IK_FreeChain(IK_Chain_ExternPtr); + + +#ifdef __cplusplus +} +#endif + +#endif // NAN_INCLUDED_IK_solver_h
\ No newline at end of file diff --git a/intern/iksolver/intern/IK_CGChainSolver.cpp b/intern/iksolver/intern/IK_CGChainSolver.cpp new file mode 100644 index 00000000000..6af4df2a35b --- /dev/null +++ b/intern/iksolver/intern/IK_CGChainSolver.cpp @@ -0,0 +1,300 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "IK_CGChainSolver.h" + +#include "IK_Segment.h" + +using namespace std; + + ChainPotential * +ChainPotential:: +New( + IK_Chain &chain +){ + return new ChainPotential(chain); +}; + + + +// End effector goal + + void +ChainPotential:: +SetGoal( + const MT_Vector3 goal +){ + m_goal = goal; +}; + +// Inherited from DifferentiablePotenialFunctionNd +////////////////////////////////////////////////// + + MT_Scalar +ChainPotential:: +Evaluate( + MT_Scalar x +){ + + // evaluate the function at postiion x along the line specified + // by the vector pair (m_line_pos,m_line_dir) + + m_temp_pos.newsize(m_line_dir.size()); + + TNT::vectorscale(m_temp_pos,m_line_dir,x); + TNT::vectoradd(m_temp_pos,m_line_pos); + + return Evaluate(m_temp_pos); +} + + MT_Scalar +ChainPotential:: +Derivative( + MT_Scalar x +){ + m_temp_pos.newsize(m_line_dir.size()); + m_temp_grad.newsize(m_line_dir.size()); + + TNT::vectorscale(m_temp_pos,m_line_dir,x); + TNT::vectoradd(m_temp_pos,m_line_pos); + + Derivative(m_temp_pos,m_temp_grad); + + return TNT::dot_prod(m_temp_grad,m_line_dir); +} + + + MT_Scalar +ChainPotential:: +Evaluate( + const TNT::Vector<MT_Scalar> &x +){ + + + // set the vector of angles in the backup chain + + vector<IK_Segment> &segs = m_t_chain.Segments(); + vector<IK_Segment>::iterator seg_it = segs.begin(); + TNT::Vector<MT_Scalar>::const_iterator a_it = x.begin(); +#if 0 + TNT::Vector<MT_Scalar>::const_iterator a_end = x.end(); +#endif + // while we are iterating through the angles and segments + // we compute the current angle potenial + MT_Scalar angle_potential = 0; +#if 0 + + for (; a_it != a_end; ++a_it, ++seg_it) { + + MT_Scalar dif = (*a_it - seg_it->CentralAngle()); + dif *= dif * seg_it->Weight(); + angle_potential += dif; + seg_it->SetTheta(*a_it); + } +#endif + + int chain_dof = m_t_chain.DoF(); + int n; + + for (n=0; n < chain_dof;seg_it ++) { + n += seg_it->SetAngles(a_it + n); + } + + + m_t_chain.UpdateGlobalTransformations(); + + MT_Scalar output = (DistancePotential(m_t_chain.EndEffector(),m_goal) + angle_potential); + + return output; +}; + + void +ChainPotential:: +Derivative( + const TNT::Vector<MT_Scalar> &x, + TNT::Vector<MT_Scalar> &dy +){ + + m_distance_grad.newsize(3); + // set the vector of angles in the backup chain + + vector<IK_Segment> & segs = m_t_chain.Segments(); + vector<IK_Segment>::iterator seg_it = segs.begin(); + TNT::Vector<MT_Scalar>::const_iterator a_it = x.begin(); + TNT::Vector<MT_Scalar>::const_iterator a_end = x.end(); + + m_angle_grad.newsize(segs.size()); + m_angle_grad = 0; +#if 0 + // FIXME compute angle gradients + TNT::Vector<MT_Scalar>::iterator ag_it = m_angle_grad.begin(); +#endif + + const int chain_dof = m_t_chain.DoF(); + for (int n=0; n < chain_dof;seg_it ++) { + n += seg_it->SetAngles(a_it + n); + } + + m_t_chain.UpdateGlobalTransformations(); + m_t_chain.ComputeJacobian(); + + DistanceGradient(m_t_chain.EndEffector(),m_goal); + + // use chain rule for calculating derivative + // of potenial function + TNT::matmult(dy,m_t_chain.TransposedJacobian(),m_distance_grad); +#if 0 + TNT::vectoradd(dy,m_angle_grad); +#endif + +}; + + + MT_Scalar +ChainPotential:: +DistancePotential( + MT_Vector3 pos, + MT_Vector3 goal +) const { + return (pos - goal).length2(); +} + +// update m_distance_gradient + + void +ChainPotential:: +DistanceGradient( + MT_Vector3 pos, + MT_Vector3 goal +){ + + MT_Vector3 output = 2*(pos - goal); + m_distance_grad.newsize(3); + + m_distance_grad[0] = output.x(); + m_distance_grad[1] = output.y(); + m_distance_grad[2] = output.z(); +} + + + IK_CGChainSolver * +IK_CGChainSolver:: +New( +){ + + MEM_SmartPtr<IK_CGChainSolver> output (new IK_CGChainSolver()); + MEM_SmartPtr<IK_ConjugateGradientSolver>solver (IK_ConjugateGradientSolver::New()); + + if (output == NULL || solver == NULL) return NULL; + + output->m_grad_solver = solver.Release(); + return output.Release(); +}; + + + bool +IK_CGChainSolver:: +Solve( + IK_Chain & chain, + MT_Vector3 new_position, + MT_Scalar tolerance +){ + + // first build a potenial function for the chain + + m_potential = ChainPotential::New(chain); + if (m_potential == NULL) return false; + + m_potential->SetGoal(new_position); + + // make a TNT::vector to describe the current + // chain state + + TNT::Vector<MT_Scalar> p; + p.newsize(chain.DoF()); + + TNT::Vector<MT_Scalar>::iterator p_it = p.begin(); + vector<IK_Segment>::const_iterator seg_it = chain.Segments().begin(); + vector<IK_Segment>::const_iterator seg_end = chain.Segments().end(); + + for (; seg_it != seg_end; seg_it++) { + + int i; + int seg_dof = seg_it->DoF(); + for (i=0; i < seg_dof; ++i,++p_it) { + *p_it = seg_it->ActiveAngle(i); + } + } + + // solve the thing + int iterations(0); + MT_Scalar return_value(0); + + m_grad_solver->Solve( + p, + tolerance, + iterations, + return_value, + m_potential.Ref(), + 100 + ); + + // update this chain + + vector<IK_Segment>::iterator out_seg_it = chain.Segments().begin(); + TNT::Vector<MT_Scalar>::const_iterator p_cit = p.begin(); + + const int chain_dof = chain.DoF(); + int n; + + for (n=0; n < chain_dof;out_seg_it ++) { + n += out_seg_it->SetAngles(p_cit + n); + } + + chain.UpdateGlobalTransformations(); + chain.ComputeJacobian(); + + return true; +} + +IK_CGChainSolver:: +~IK_CGChainSolver( +){ + //nothing to do +}; + + +IK_CGChainSolver:: +IK_CGChainSolver( +){ + //nothing to do; +}; + diff --git a/intern/iksolver/intern/IK_CGChainSolver.h b/intern/iksolver/intern/IK_CGChainSolver.h new file mode 100644 index 00000000000..f7aeee090a1 --- /dev/null +++ b/intern/iksolver/intern/IK_CGChainSolver.h @@ -0,0 +1,178 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef CGChainSolver_h + +#define CGChainSolver_h + +/** + * @author Laurence Bourn + * @date 28/6/2001 + */ + +#include "IK_ConjugateGradientSolver.h" +#include "IK_Chain.h" +#include "MT_Scalar.h" +#include "TNT/vec.h" +#include "MEM_SmartPtr.h" + + +/** + * This class is a concrete differentiable potenial function for + * an IK_Chain representing the distance to the goal. + * @warning This method of solving IK problems is not as good + * as IK_JacobianSolver. I advise you to use that class instead. + */ + +class ChainPotential : +public DifferentiablePotenialFunctionNd +{ +public : + + static + ChainPotential * + New( + IK_Chain &chain + ); + + // End effector goal + + void + SetGoal( + const MT_Vector3 goal + ); + + // Inherited from DifferentiablePotenialFunctionNd + ////////////////////////////////////////////////// + + MT_Scalar + Evaluate( + const MT_Scalar x + ); + + MT_Scalar + Derivative( + const MT_Scalar x + ); + + MT_Scalar + Evaluate( + const TNT::Vector<MT_Scalar> &x + ); + + void + Derivative( + const TNT::Vector<MT_Scalar> &x, + TNT::Vector<MT_Scalar> &dy + ); + + // return the dimension of the domain of the potenial + // function + + int + Dimension( + ) const { + return m_dimension; + } + + ~ChainPotential( + ){ + }; + +private : + + MT_Scalar + DistancePotential( + MT_Vector3 pos, + MT_Vector3 goal + ) const; + + void + DistanceGradient( + MT_Vector3 pos, + MT_Vector3 goal + ); + + ChainPotential( + IK_Chain & chain + ) : + DifferentiablePotenialFunctionNd(), + m_chain(chain), + m_t_chain(chain), + m_dimension (chain.Segments().size()) + { + }; + + MT_Vector3 m_goal; + TNT::Vector<MT_Scalar> m_distance_grad; + TNT::Vector<MT_Scalar> m_angle_grad; + TNT::Vector<MT_Scalar> m_temp_pos; + TNT::Vector<MT_Scalar> m_temp_grad; + + TNT::Vector<MT_Scalar> m_original_pos; + int m_dimension; + + IK_Chain &m_chain; + IK_Chain m_t_chain; // deep copy + +}; + + +class IK_CGChainSolver : public MEM_NonCopyable +{ +public : + + + static + IK_CGChainSolver * + New( + ); + + bool + Solve( + IK_Chain & chain, + MT_Vector3 new_position, + MT_Scalar tolerance + ); + + ~IK_CGChainSolver(); + +private : + + IK_CGChainSolver( + ); + + MEM_SmartPtr<ChainPotential> m_potential; + MEM_SmartPtr<IK_ConjugateGradientSolver> m_grad_solver; +}; + + +#endif
\ No newline at end of file diff --git a/intern/iksolver/intern/IK_Chain.cpp b/intern/iksolver/intern/IK_Chain.cpp new file mode 100644 index 00000000000..875b8da1405 --- /dev/null +++ b/intern/iksolver/intern/IK_Chain.cpp @@ -0,0 +1,208 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "IK_Chain.h" + + +using namespace std; + +IK_Chain:: +IK_Chain( +) +{ + // nothing to do; +}; + +const + vector<IK_Segment> & +IK_Chain:: +Segments( +) const { + return m_segments; +}; + + vector<IK_Segment> & +IK_Chain:: +Segments( +){ + return m_segments; +}; + + void +IK_Chain:: +UpdateGlobalTransformations( +){ + + // now iterate through the segment list + // compute their local transformations if needed + + // assign their global transformations + // (relative to chain origin) + + vector<IK_Segment>::const_iterator s_end = m_segments.end(); + vector<IK_Segment>::iterator s_it = m_segments.begin(); + + MT_Transform global; + + global.setIdentity(); + + for (; s_it != s_end; ++s_it) { + s_it->UpdateGlobal(global); + global = s_it->GlobalTransform(); + } + // compute the position of the end effector and it's pose + + const MT_Transform &last_t = m_segments.back().GlobalTransform(); + m_end_effector = last_t.getOrigin(); + + MT_Matrix3x3 last_basis = last_t.getBasis(); + last_basis.transpose(); + MT_Vector3 m_end_pose = last_basis[2]; + + +}; + +const + TNT::Matrix<MT_Scalar> & +IK_Chain:: +Jacobian( +) const { + return m_jacobian; +} ; + + +const + TNT::Matrix<MT_Scalar> & +IK_Chain:: +TransposedJacobian( +) const { + return m_t_jacobian; +}; + + void +IK_Chain:: +ComputeJacobian( +){ + // let's assume that the chain's global transfomations + // have already been computed. + + int dof = DoF(); + + int num_segs = m_segments.size(); + vector<IK_Segment>::const_iterator segs = m_segments.begin(); + + m_t_jacobian.newsize(dof,3); + m_jacobian.newsize(3,dof); + + // compute the transposed jacobian first + + int n; + int i = 0; + + + for (n= 0; n < num_segs; n++) { + + const MT_Matrix3x3 &basis = segs[n].GlobalTransform().getBasis(); + const MT_Vector3 &origin = segs[n].GlobalSegmentStart(); + + MT_Vector3 p = origin-m_end_effector; + + // iterate through the active angle vectors of this segment + + int angle_ind =0; + int seg_dof = segs[n].DoF(); + + const std::vector<MT_Vector3> & angle_vectors = segs[n].AngleVectors(); + + for (angle_ind = 0;angle_ind <seg_dof; angle_ind++,i++) { + + MT_Vector3 angle_axis = angle_vectors[angle_ind]; + + MT_Vector3 a = basis * angle_axis; + MT_Vector3 pca = p.cross(a); + + m_t_jacobian(i + 1,1) = pca.x(); + m_t_jacobian(i + 1,2) = pca.y(); + m_t_jacobian(i + 1,3) = pca.z(); + + } + } + + // get the origina1 jacobain + + TNT::transpose(m_t_jacobian,m_jacobian); +}; + + MT_Vector3 +IK_Chain:: +EndEffector( +) const { + return m_end_effector; +}; + + MT_Vector3 +IK_Chain:: +EndPose( +) const { + return m_end_pose; +}; + + + int +IK_Chain:: +DoF( +) const { + + // iterate through the segs and compute the DOF + + vector<IK_Segment>::const_iterator s_end = m_segments.end(); + vector<IK_Segment>::const_iterator s_it = m_segments.begin(); + + int dof = 0; + + for (;s_it != s_end; ++s_it) { + dof += s_it->DoF(); + } + + return dof; +} + + + + + + + + + + + + diff --git a/intern/iksolver/intern/IK_Chain.h b/intern/iksolver/intern/IK_Chain.h new file mode 100644 index 00000000000..40496b6087a --- /dev/null +++ b/intern/iksolver/intern/IK_Chain.h @@ -0,0 +1,194 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_IK_Chain_h + +#define NAN_INCLUDED_IK_Chain_h + +/** + * @author Laurence Bourn + * @date 28/6/2001 + */ + +#include "IK_Segment.h" +#include <vector> +#include "MT_Scalar.h" +#include "TNT/cmat.h" + +/** + * This class is a collection of ordered segments that are used + * in an Inverse Kinematic solving routine. An IK solver operating + * on the chain, will in general manipulate all the segments of the + * chain in order to solve the IK problem. + * + * To build a chain use the default constructor. Once built it's + * then possible to add IK_Segments to the chain by inserting + * them into the vector of IK_Segments. Note that segments will be + * copied into the chain so chain's cannot share instances of + * IK_Segments. + * + * You have full control of which segments form the chain via the + * the std::vector routines. + */ +class IK_Chain{ + +public : + + /** + * Construct a IK_Chain with no segments. + */ + + IK_Chain( + ); + + // IK_Chains also have the default copy constructors + // available. + + /** + * Const access to the array of segments + * comprising the IK_Chain. Used for rendering + * etc + * @return a vector of segments + */ + + const + std::vector<IK_Segment> & + Segments( + ) const ; + + + /** + * Full access to segments used to initialize + * the IK_Chain and manipulate the segments. + * Use the push_back() method of std::vector to add + * segments in order to the chain + */ + + std::vector<IK_Segment> & + Segments( + ); + + + /** + * Force the IK_Chain to recompute all the local + * segment transformations and composite them + * to calculate the global transformation for + * each segment. Must be called before + * ComputeJacobian() + */ + + void + UpdateGlobalTransformations( + ); + + /** + * Return the global position of the end + * of the last segment. + */ + + MT_Vector3 + EndEffector( + ) const; + + + /** + * Return the global pose of the end + * of the last segment. + */ + + MT_Vector3 + EndPose( + ) const; + + + /** + * Calculate the jacobian matrix for + * the current end effector position. + * A jacobian is the set of column vectors + * of partial derivatives for each active angle. + * This method also computes the transposed jacobian. + * @pre You must have updated the global transformations + * of the chain's segments before a call to this method. Do this + * with UpdateGlobalTransformation() + */ + + void + ComputeJacobian( + ); + + + /** + * @return A reference to the last computed jacobian matrix + */ + + const + TNT::Matrix<MT_Scalar> & + Jacobian( + ) const ; + + /** + * @return A reference to the last computed transposed jacobian matrix + */ + + const + TNT::Matrix<MT_Scalar> & + TransposedJacobian( + ) const ; + + /** + * Count the degrees of freedom in the IK_Chain + * @warning store this value rather than using this function + * as the termination value of a for loop etc. + */ + + int + DoF( + ) const; + + +private : + + /// The vector of segments comprising the chain + std::vector<IK_Segment> m_segments; + + /// The jacobain of the IK_Chain + TNT::Matrix<MT_Scalar> m_jacobian; + + /// It's transpose + TNT::Matrix<MT_Scalar> m_t_jacobian; + + MT_Vector3 m_end_effector; + MT_Vector3 m_end_pose; + +}; + + +#endif
\ No newline at end of file diff --git a/intern/iksolver/intern/IK_ConjugateGradientSolver.cpp b/intern/iksolver/intern/IK_ConjugateGradientSolver.cpp new file mode 100644 index 00000000000..028b7dfe2b0 --- /dev/null +++ b/intern/iksolver/intern/IK_ConjugateGradientSolver.cpp @@ -0,0 +1,162 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "IK_ConjugateGradientSolver.h" + + +#define EPS 1.0e-10 + + IK_ConjugateGradientSolver * +IK_ConjugateGradientSolver:: +New( +){ + return new IK_ConjugateGradientSolver(); +}; + +IK_ConjugateGradientSolver:: +~IK_ConjugateGradientSolver( +){ + //nothing to do +}; + +// Compute the minimum of the potenial function +// starting at point p. On return p contains the +// computed minima, iter the number of iterations performed, +// fret the potenial value at the minima + + void +IK_ConjugateGradientSolver:: +Solve( + TNT::Vector<MT_Scalar> &p, + MT_Scalar ftol, + int &iter, + MT_Scalar &fret, + DifferentiablePotenialFunctionNd &potenial, + int max_its +){ + + int j; + MT_Scalar gg,gam,fp,dgg; + + int n = potenial.Dimension(); + ArmVectors(n); + + // initialize --- FIXME we probably have these + // values to hand already. + + fp = potenial.Evaluate(p); + potenial.Derivative(p,m_xi); + + for (j = 1; j<=n; j++) { + m_g(j) = -m_xi(j); + m_xi(j) = m_h(j) = m_g(j); + } + for (iter =1;iter <= max_its; iter++) { + LineMinimize(p,m_xi,fret,potenial); + + if (2 *TNT::abs(fret-fp) <= ftol*(TNT::abs(fret) + TNT::abs(fp) + EPS)) { + return; + } + fp = fret; + potenial.Derivative(p,m_xi); + dgg = gg = 0.0; + + for (j = 1; j<=n;j++) { + gg += m_g(j)*m_g(j); + //dgg+= xi(j)*xi(j); + dgg += (m_xi(j) + m_g(j))*m_xi(j); + } + if (gg == 0.0) { + return; + } + gam = dgg/gg; + + for (j = 1; j<=n; j++) { + m_g(j) = -m_xi(j); + m_xi(j) = m_h(j) = m_g(j) + gam*m_h(j); + } + } + // FIXME throw exception + //assert(false); +}; + + +IK_ConjugateGradientSolver:: +IK_ConjugateGradientSolver( +){ + //nothing to do +} + + void +IK_ConjugateGradientSolver:: +ArmVectors( + int dimension +){ + m_g.newsize(dimension); + m_h.newsize(dimension); + m_xi.newsize(dimension); + m_xi_temp.newsize(dimension); +}; + + void +IK_ConjugateGradientSolver:: +LineMinimize( + TNT::Vector<MT_Scalar> & p, + const TNT::Vector<MT_Scalar> & xi, + MT_Scalar &fret, + DifferentiablePotenialFunctionNd &potenial +){ + MT_Scalar ax(0),bx(1); // initial bracket guess + MT_Scalar cx,fa,fb,fc; + + MT_Scalar xmin(0); // the 1d function minima + + potenial.SetLineVector(p,xi); + IK_LineMinimizer::InitialBracket1d(ax,bx,cx,fa,fb,fc,potenial); + fret = IK_LineMinimizer::DerivativeBrent1d(ax,bx,cx,potenial,xmin,0.001); + + // x_min in minimum along line and corresponds with + // p[] + x_min *xi[] + + TNT::vectorscale(m_xi_temp,xi,xmin); + TNT::vectoradd(p,m_xi_temp); +}; + + +#undef EPS + + + + + + + + diff --git a/intern/iksolver/intern/IK_ConjugateGradientSolver.h b/intern/iksolver/intern/IK_ConjugateGradientSolver.h new file mode 100644 index 00000000000..e50799a9fa1 --- /dev/null +++ b/intern/iksolver/intern/IK_ConjugateGradientSolver.h @@ -0,0 +1,195 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_IK_ConjugateGradientSolver_h + +#define NAN_INCLUDED_IK_ConjugateGradientSolver_h + +/** + * @author Laurence Bourn + * @date 28/6/2001 + */ + +#include "TNT/cmat.h" +#include "MT_Scalar.h" +#include "IK_LineMinimizer.h" + +/** + * These classes locally minimize n dimensional potenial functions. + * See Numerical Recipes in C www.nr.com for more details. + * If a n dimensionable potenial function is + * differentiable, then it is diferentiable along + * any vector x. This can be found by the dot product + * of the gradient operator with x. + * The conjugate gradient solver boils down to + * a collection of line minimizations along various lines + * defined by position,direction pairs. There are + * methods in this class to set the lines along which + * minimizations via the DiffentiablePotenialFunction1d interface + * are to be performed. + * + * @warning I don't like data inheritance but it is the most efficient + * wasy to do this here. + */ + + +class DifferentiablePotenialFunctionNd +: public DifferentiablePotenialFunction1d +{ +public : + + /** + * Inherited from DiffentiablePotenialFunction1d + * + * virtual + * MT_Scalar + * Evaluate1d( + * MT_Scalar x + * ) = 0; + * + * virtual + * MT_Scalar + * Derivative1d( + * MT_Scalar x + * ) = 0; + */ + + /// Methods to set the current line in N dimensions + + void + SetLineVector( + const TNT::Vector<MT_Scalar> &pos, + const TNT::Vector<MT_Scalar> &dir + ){ + m_line_pos = pos; + m_line_dir = dir; + }; + + virtual + MT_Scalar + Evaluate( + const TNT::Vector<MT_Scalar> &x + ) = 0; + + virtual + void + Derivative( + const TNT::Vector<MT_Scalar> &x, + TNT::Vector<MT_Scalar> &dy + ) = 0; + + /// @return The dimension of the domain of the potenial function + + virtual + int + Dimension( + ) const =0; + + virtual + ~DifferentiablePotenialFunctionNd( + ){ + }; + +protected : + + DifferentiablePotenialFunctionNd(){}; + + TNT::Vector<MT_Scalar> m_line_pos; + TNT::Vector<MT_Scalar> m_line_dir; + +}; + + +class IK_ConjugateGradientSolver +: public MEM_NonCopyable +{ +public : + + /** + * This class necessarily needs some (potenially large) + * temporary vectors to aid computation. We therefore + * insist creation of these objects on the heap. + */ + + static + IK_ConjugateGradientSolver * + New( + ); + + /** + * Compute the minimum of the potenial function + * starting at point p. On return p contains the + * computed minima, iter the number of iterations performed, + * fret the potenial value at the minima + */ + + void + Solve( + TNT::Vector<MT_Scalar> &p, + MT_Scalar ftol, + int &iter, + MT_Scalar &fret, + DifferentiablePotenialFunctionNd &potenial, + int max_its = 200 + ); + + ~IK_ConjugateGradientSolver( + ); + +private : + void + LineMinimize( + TNT::Vector<MT_Scalar> & p, + const TNT::Vector<MT_Scalar> & xi, + MT_Scalar &fret, + DifferentiablePotenialFunctionNd &potenial + ); + + IK_ConjugateGradientSolver( + ); + + void + ArmVectors( + int dimension + ); + + + TNT::Vector<MT_Scalar> m_g; + TNT::Vector<MT_Scalar> m_h; + TNT::Vector<MT_Scalar> m_xi; + + TNT::Vector<MT_Scalar> m_xi_temp; + +}; + +#endif + + diff --git a/intern/iksolver/intern/IK_JacobianSolver.cpp b/intern/iksolver/intern/IK_JacobianSolver.cpp new file mode 100644 index 00000000000..de4531f1677 --- /dev/null +++ b/intern/iksolver/intern/IK_JacobianSolver.cpp @@ -0,0 +1,267 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "IK_JacobianSolver.h" + +#include "TNT/svd.h" + +using namespace std; + + IK_JacobianSolver * +IK_JacobianSolver:: +New( +){ + return new IK_JacobianSolver(); +} + + bool +IK_JacobianSolver:: +Solve( + IK_Chain &chain, + const MT_Vector3 &g_position, + const MT_Vector3 &g_pose, + const MT_Scalar tolerance, + const int max_iterations, + const MT_Scalar max_angle_change +){ + + ArmMatrices(chain.DoF()); + + for (int iterations = 0; iterations < max_iterations; iterations++) { + + + MT_Vector3 end_effector = chain.EndEffector(); + + MT_Vector3 d_pos = g_position - end_effector; + const MT_Scalar x_length = d_pos.length(); + + if (x_length < tolerance) { + return true; + } + + chain.ComputeJacobian(); + ComputeInverseJacobian(chain,x_length,max_angle_change); + + ComputeBetas(chain,d_pos); + UpdateChain(chain); + chain.UpdateGlobalTransformations(); + } + + return false; +}; + +IK_JacobianSolver:: +~IK_JacobianSolver( +){ + // nothing to do +} + + +IK_JacobianSolver:: +IK_JacobianSolver( +){ + // nothing to do +}; + + void +IK_JacobianSolver:: +ComputeBetas( + IK_Chain &chain, + const MT_Vector3 d_pos +){ + + m_beta = 0; + + m_beta[0] = d_pos.x(); + m_beta[1] = d_pos.y(); + m_beta[2] = d_pos.z(); + + TNT::matmult(m_d_theta,m_svd_inverse,m_beta); + +}; + + + int +IK_JacobianSolver:: +ComputeInverseJacobian( + IK_Chain &chain, + const MT_Scalar x_length, + const MT_Scalar max_angle_change +) { + + int dimension = 0; + + m_svd_u = 0; + + // copy first 3 rows of jacobian into m_svd_u + + int row, column; + + for (row = 0; row < 3; row ++) { + for (column = 0; column < chain.Jacobian().num_cols(); column ++) { + m_svd_u[row][column] = chain.Jacobian()[row][column]; + } + } + + m_svd_w = 0; + m_svd_v = 0; + + TNT::SVD(m_svd_u,m_svd_w,m_svd_v); + + // invert the SVD and compute inverse + + TNT::transpose(m_svd_v,m_svd_v_t); + TNT::transpose(m_svd_u,m_svd_u_t); + + // Compute damped least squares inverse of pseudo inverse + // Compute damping term lambda + + // Note when lambda is zero this is equivalent to the + // least squares solution. This is fine when the m_jjt is + // of full rank. When m_jjt is near to singular the least squares + // inverse tries to minimize |J(dtheta) - dX)| and doesn't + // try to minimize dTheta. This results in eratic changes in angle. + // Damped least squares minimizes |dtheta| to try and reduce this + // erratic behaviour. + + // We don't want to use the damped solution everywhere so we + // only increase lamda from zero as we approach a singularity. + + // find the smallest non-zero m_svd_w value + + int i = 0; + + MT_Scalar w_min = MT_INFINITY; + + // anything below epsilon is treated as zero + + MT_Scalar epsilon = 1e-10; + + for ( i = 0; i <m_svd_w.size() ; i++) { + + if (m_svd_w[i] > epsilon && m_svd_w[i] < w_min) { + w_min = m_svd_w[i]; + } + } + MT_Scalar lambda = 0; + + MT_Scalar d = x_length/max_angle_change; + + if (w_min <= d/2) { + lambda = d/2; + } else + if (w_min < d) { + lambda = sqrt(w_min*(d - w_min)); + } else { + lambda = 0; + } + + lambda *= lambda; + + for (i= 0; i < m_svd_w.size(); i++) { + if (m_svd_w[i] < epsilon) { + m_svd_w[i] = 0; + } else { + m_svd_w[i] = m_svd_w[i] / (m_svd_w[i] * m_svd_w[i] + lambda); + } + } + + m_svd_w_diag.diagonal(m_svd_w); + + // FIXME optimize these matrix multiplications + // using the fact that m_svd_w_diag is diagonal! + + TNT::matmult(m_svd_temp1,m_svd_w_diag,m_svd_u_t); + TNT::matmult(m_svd_inverse,m_svd_v,m_svd_temp1); + return dimension; + +} + + void +IK_JacobianSolver:: +UpdateChain( + IK_Chain &chain +){ + + // iterate through the set of angles and + // update their values from the d_thetas + + int n; + vector<IK_Segment> &segs = chain.Segments(); + + int chain_dof = chain.DoF(); + int seg_ind = 0; + for (n=0; n < chain_dof;seg_ind ++) { + n += segs[seg_ind].IncrementAngles(m_d_theta.begin() + n); + } +}; + + void +IK_JacobianSolver:: +ArmMatrices( + int dof +){ + + m_beta.newsize(dof); + m_d_theta.newsize(dof); + + m_svd_u.newsize(dof,dof); + m_svd_v.newsize(dof,dof); + m_svd_w.newsize(dof); + + m_svd_u = 0; + m_svd_v = 0; + m_svd_w = 0; + + m_svd_u_t.newsize(dof,dof); + m_svd_v_t.newsize(dof,dof); + m_svd_w_diag.newsize(dof,dof); + m_svd_inverse.newsize(dof,dof); + m_svd_temp1.newsize(dof,dof); + +}; + + + + + + + + + + + + + + + + + diff --git a/intern/iksolver/intern/IK_JacobianSolver.h b/intern/iksolver/intern/IK_JacobianSolver.h new file mode 100644 index 00000000000..3f3372a2cb7 --- /dev/null +++ b/intern/iksolver/intern/IK_JacobianSolver.h @@ -0,0 +1,171 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_IK_JacobianSolver_h + +#define NAN_INCLUDED_IK_JacobianSolver_h + +/** + * @author Laurence Bourn + * @date 28/6/2001 + */ + +#include "TNT/cmat.h" +#include <vector> +#include "MT_Vector3.h" +#include "IK_Chain.h" + +class IK_JacobianSolver { + +public : + + /** + * Create a new IK_JacobianSolver on the heap + * @return A newly created IK_JacobianSolver you take ownership of the object + * and responsibility for deleting it + */ + + + static + IK_JacobianSolver * + New( + ); + + /** + * Compute a solution for a chain. + * @param chain Reference to the chain to modify + * @param g_position Reference to the goal position. + * @param g_pose -not used- Reference to the goal pose. + * @param tolerance The maximum allowed distance between solution + * and goal for termination. + * @param max_iterations should be in the range (50 - 500) + * @param max_angle_change The maximum change in the angle vector + * of the chain (0.1 is a good value) + * + * @return True iff goal position reached. + */ + + bool + Solve( + IK_Chain &chain, + const MT_Vector3 &g_position, + const MT_Vector3 &g_pose, + const MT_Scalar tolerance, + const int max_iterations, + const MT_Scalar max_angle_change + ); + + ~IK_JacobianSolver( + ); + + +private : + + /** + * Private constructor to force use of New() + */ + + IK_JacobianSolver( + ); + + + /** + * Compute the inverse jacobian matrix of the chain. + * Uses a damped least squares solution when the matrix is + * is approaching singularity + */ + + int + ComputeInverseJacobian( + IK_Chain &chain, + const MT_Scalar x_length, + const MT_Scalar max_angle_change + ); + + void + ComputeBetas( + IK_Chain &chain, + const MT_Vector3 d_pos + ); + + /** + * Updates the angles of the chain with the newly + * computed values + **/ + + void + UpdateChain( + IK_Chain &chain + ); + + /** + * Make sure all the matrices are of the correct size + **/ + + void + ArmMatrices( + int dof + ); + + +private : + + /// the vector of intermediate betas + TNT::Vector<MT_Scalar> m_beta; + + /// the vector of computed angle changes + TNT::Vector<MT_Scalar> m_d_theta; + + /// the contraint gradients for each angle. + TNT::Vector<MT_Scalar> m_dh; + + /// Space required for SVD computation + + TNT::Vector<MT_Scalar> m_svd_w; + TNT::Matrix<MT_Scalar> m_svd_v; + TNT::Matrix<MT_Scalar> m_svd_u; + + TNT::Matrix<MT_Scalar> m_svd_w_diag; + TNT::Matrix<MT_Scalar> m_svd_v_t; + TNT::Matrix<MT_Scalar> m_svd_u_t; + TNT::Matrix<MT_Scalar> m_svd_inverse; + TNT::Matrix<MT_Scalar> m_svd_temp1; + + +}; + + + + +#endif + + + diff --git a/intern/iksolver/intern/IK_LineMinimizer.h b/intern/iksolver/intern/IK_LineMinimizer.h new file mode 100644 index 00000000000..635a5972c02 --- /dev/null +++ b/intern/iksolver/intern/IK_LineMinimizer.h @@ -0,0 +1,298 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_IK_LineMinimizer_h + +#define NAN_INCLUDED_IK_LineMinimizer_h + +/** + * @author Laurence Bourn + * @date 28/6/2001 + */ + +#include "MT_Scalar.h" +#include <vector> +#include "TNT/tntmath.h" +#include "MEM_NonCopyable.h" + + + +#define GOLD 1.618034 +#define GLIMIT 100.0 +#define TINY 1.0e-20 +#define ZEPS 1.0e-10 + +/** + * Routines for line - minization in n dimensions + * these should be templated on the potenial function + * p instead of using a virtual class. Please see + * numerical recipes in c for more details. www.nr.com + */ + +class DifferentiablePotenialFunction1d { +public : + virtual + MT_Scalar + Evaluate( + const MT_Scalar x + ) = 0; + + virtual + MT_Scalar + Derivative( + const MT_Scalar x + ) = 0; +}; + + +/** + * TODO get rid of this class and make some + * template functions in a seperate namespace + */ + +class IK_LineMinimizer : public MEM_NonCopyable { + +public : + + /** + * Before we proceed with line minimization + * we need to construct an initial bracket + * of a minima of the PotenialFunction + */ + + static + void + InitialBracket1d ( + MT_Scalar &ax, + MT_Scalar &bx, + MT_Scalar &cx, + MT_Scalar &fa, + MT_Scalar &fb, + MT_Scalar &fc, + DifferentiablePotenialFunction1d &potenial + ) { + MT_Scalar ulim,u,r,q,fu; + + fa = potenial.Evaluate(ax); + fb = potenial.Evaluate(bx); + + if (fb > fa) { + std::swap(ax,bx); + std::swap(fa,fb); + } + cx = bx + GOLD*(bx-ax); + fc = potenial.Evaluate(cx); + + while (fb > fc) { + + r = (bx - ax) * (fb - fc); + q = (bx - cx) * (fb - fa); + u = bx - ((bx - cx)*q - (bx - ax) *r)/ + (2 * TNT::sign(TNT::max(TNT::abs(q-r),TINY),q-r)); + ulim = bx + GLIMIT*(cx-bx); + + if ((bx-u)*(u-cx) > 0.0) { + fu = potenial.Evaluate(u); + if (fu < fc) { + ax = bx; + bx = u; + fa = fb; + fb = fu; + return; + } else if (fu > fb) { + cx = u; + fc = fu; + return; + } + u = cx + GOLD*(cx-bx); + fu = potenial.Evaluate(u); + + } else if ((cx - u)*(u - ulim) > 0.0) { + fu = potenial.Evaluate(u); + + if (fu < fc) { + bx = cx; + cx = u; + u = cx + GOLD*(cx - bx); + fb = fc; + fc = fu; + fu = potenial.Evaluate(u); + } + } else if ((u-ulim)*(ulim-cx) >=0.0) { + u = ulim; + fu = potenial.Evaluate(u); + } else { + u = cx + GOLD*(cx-bx); + fu = potenial.Evaluate(u); + } + ax = bx; + bx = cx; + cx = u; + fa = fb; + fb = fc; + fc = fu; + } + }; + + /** + * This is a 1 dimensional brent method for + * line-minization with derivatives + */ + + + static + MT_Scalar + DerivativeBrent1d( + MT_Scalar ax, + MT_Scalar bx, + MT_Scalar cx, + DifferentiablePotenialFunction1d &potenial, + MT_Scalar &x_min, + const MT_Scalar tol, + int max_iter = 100 + ) { + int iter; + bool ok1,ok2; + MT_Scalar a,b,d,d1,d2,du,dv,dw,dx,e(0); + MT_Scalar fu,fv,fw,fx,olde,tol1,tol2,u,u1,u2,v,w,x,xm; + + a = (ax < cx ? ax : cx); + b = (ax > cx ? ax : cx); + x = w = v = bx; + fw = fv = fx = potenial.Evaluate(x); + dw = dv = dx = potenial.Derivative(x); + + for (iter = 1; iter <= max_iter; iter++) { + xm = 0.5*(a+b); + tol1 = tol*fabs(x) + ZEPS; + tol2 = 2 * tol1; + if (fabs(x - xm) <= (tol2 - 0.5*(b-a))) { + x_min = x; + return fx; + } + + if (fabs(e) > tol1) { + d1 = 2*(b-a); + d2 = d1; + if (dw != dx) { + d1 = (w-x)*dx/(dx-dw); + } + if (dv != dx) { + d2 = (v-x)*dx/(dx-dv); + } + + u1 = x+d1; + u2 = x+d2; + ok1 = ((a-u1)*(u1-b) > 0.0) && ((dx*d1) <= 0.0); + ok2 = ((a-u2)*(u2-b) > 0.0) && ((dx*d2) <= 0.0); + olde = e; + e = d; + + if (ok1 || ok2) { + if (ok1 && ok2) { + d = fabs(d1) < fabs(d2) ? d1 : d2; + } else if (ok1) { + d = d1; + } else { + d = d2; + } + if (fabs(d) <= fabs(0.5*olde)) { + u = x+d; + if ((u-a < tol2) || (b-u < tol2)) { + d = TNT::sign(tol1,xm-x); + } + } else { + d = 0.5*(e = (dx >= 0.0 ? a-x : b-x)); + } + } else { + d = 0.5*(e = (dx >= 0.0 ? a-x : b-x)); + } + } else { + d = 0.5*(e = (dx >= 0.0 ? a-x : b-x)); + } + + if (fabs(d) >= tol1) { + u = x+d; + fu = potenial.Evaluate(u); + } else { + u = x + TNT::sign(tol1,d); + fu = potenial.Evaluate(u); + if (fu > fx) { + x_min = x; + return fx; + } + } + du = potenial.Derivative(u); + if (fu <= fx) { + if (u >= x) { + a = x; + } else { + b = x; + } + v = w; fv = fw; dv = dw; + w = x; fw = fx; dw = dx; + x = u; fx = fu; dx = du; + } else { + if (u < x) { + a = u; + } else { + b = u; + } + if (fu <= fw || w == x) { + v = w; fv = fw; dv = dw; + w = u; fw = fu; dw = du; + } else if ( fu < fv || v == x || v == w) { + v = u; fv = fu; dv = du; + } + } + } + // FIXME throw exception + + assert(false); + return MT_Scalar(0); + }; + +private : + + /// This class just contains static helper methods so no instantiation + + IK_LineMinimizer(); + +}; + +#undef GOLD +#undef GLIMIT +#undef TINY +#undef ZEPS + + + +#endif diff --git a/intern/iksolver/intern/IK_QChain.cpp b/intern/iksolver/intern/IK_QChain.cpp new file mode 100644 index 00000000000..438729003a9 --- /dev/null +++ b/intern/iksolver/intern/IK_QChain.cpp @@ -0,0 +1,280 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * + * @author Laurence + */ + +#include "IK_QChain.h" + +using namespace std; + +IK_QChain:: +IK_QChain( +) +{ + // nothing to do; +}; + +const + vector<IK_QSegment> & +IK_QChain:: +Segments( +) const { + return m_segments; +}; + + vector<IK_QSegment> & +IK_QChain:: +Segments( +){ + return m_segments; +}; + + void +IK_QChain:: +UpdateGlobalTransformations( +){ + + // now iterate through the segment list + // compute their local transformations if needed + + // assign their global transformations + // (relative to chain origin) + + vector<IK_QSegment>::const_iterator s_end = m_segments.end(); + vector<IK_QSegment>::iterator s_it = m_segments.begin(); + + MT_Transform global; + global.setIdentity(); + + for (; s_it != s_end; ++s_it) { + global = s_it->UpdateGlobal(global); + } + + // we also need to compute the accumulated local transforms + // for each segment + + MT_Transform acc_local; + acc_local.setIdentity(); + + vector<IK_QSegment>::reverse_iterator s_rit = m_segments.rbegin(); + vector<IK_QSegment>::reverse_iterator s_rend = m_segments.rend(); + + for (; s_rit != s_rend; ++s_rit) { + acc_local = s_rit->UpdateAccumulatedLocal(acc_local); + } + + // compute the position of the end effector and it's pose + + const MT_Transform &last_t = m_segments.back().GlobalTransform(); + m_end_effector = last_t.getOrigin(); + +#if 0 + + // The end pose is not currently used. + + MT_Matrix3x3 last_basis = last_t.getBasis(); + last_basis.transpose(); + MT_Vector3 m_end_pose = last_basis[1]; + +#endif + +}; + +const + TNT::Matrix<MT_Scalar> & +IK_QChain:: +Jacobian( +) const { + return m_jacobian; +} ; + + +const + TNT::Matrix<MT_Scalar> & +IK_QChain:: +TransposedJacobian( +) const { + return m_t_jacobian; +}; + + void +IK_QChain:: +ComputeJacobian( +){ + // let's assume that the chain's global transfomations + // have already been computed. + + int dof = DoF(); + + int num_segs = m_segments.size(); + vector<IK_QSegment>::const_iterator segs = m_segments.begin(); + + m_t_jacobian.newsize(dof,3); + m_jacobian.newsize(3,dof); + + // compute the transposed jacobian first + + int n; + int i = 0; + + for (n= 0; n < num_segs; n++) { +#if 0 + + // For euler angle computation we can use a slightly quicker method. + + const MT_Matrix3x3 &basis = segs[n].GlobalTransform().getBasis(); + const MT_Vector3 &origin = segs[n].GlobalSegmentStart(); + + const MT_Vector3 p = origin-m_end_effector; + + const MT_Vector3 x_axis(1,0,0); + const MT_Vector3 y_axis(0,1,0); + const MT_Vector3 z_axis(0,0,1); + + MT_Vector3 a = basis * x_axis; + MT_Vector3 pca = p.cross(a); + + m_t_jacobian(n*3 + 1,1) = pca.x(); + m_t_jacobian(n*3 + 1,2) = pca.y(); + m_t_jacobian(n*3 + 1,3) = pca.z(); + + a = basis * y_axis; + pca = p.cross(a); + + m_t_jacobian(n*3 + 2,1) = pca.x(); + m_t_jacobian(n*3 + 2,2) = pca.y(); + m_t_jacobian(n*3 + 2,3) = pca.z(); + + a = basis * z_axis; + pca = p.cross(a); + + m_t_jacobian(n*3 + 3,1) = pca.x(); + m_t_jacobian(n*3 + 3,2) = pca.y(); + m_t_jacobian(n*3 + 3,3) = pca.z(); +#else + // user slower general jacobian computation method + + MT_Vector3 j1 = segs[n].ComputeJacobianColumn(0); + + m_t_jacobian(n*3 + 1,1) = j1.x(); + m_t_jacobian(n*3 + 1,2) = j1.y(); + m_t_jacobian(n*3 + 1,3) = j1.z(); + + j1 = segs[n].ComputeJacobianColumn(1); + + m_t_jacobian(n*3 + 2,1) = j1.x(); + m_t_jacobian(n*3 + 2,2) = j1.y(); + m_t_jacobian(n*3 + 2,3) = j1.z(); + + j1 = segs[n].ComputeJacobianColumn(2); + + m_t_jacobian(n*3 + 3,1) = j1.x(); + m_t_jacobian(n*3 + 3,2) = j1.y(); + m_t_jacobian(n*3 + 3,3) = j1.z(); +#endif + + + + } + + + // get the origina1 jacobain + + TNT::transpose(m_t_jacobian,m_jacobian); +}; + + MT_Vector3 +IK_QChain:: +EndEffector( +) const { + return m_end_effector; +}; + + MT_Vector3 +IK_QChain:: +EndPose( +) const { + return m_end_pose; +}; + + + int +IK_QChain:: +DoF( +) const { + return 3 * m_segments.size(); +} + +const + MT_Scalar +IK_QChain:: +MaxExtension( +) const { + + vector<IK_QSegment>::const_iterator s_end = m_segments.end(); + vector<IK_QSegment>::const_iterator s_it = m_segments.begin(); + + if (m_segments.size() == 0) return MT_Scalar(0); + + MT_Scalar output = s_it->Length(); + + ++s_it ; + for (; s_it != s_end; ++s_it) { + output += s_it->MaxExtension(); + } + return output; +} + + + + + + + + + + + + + + + + + + + + diff --git a/intern/iksolver/intern/IK_QChain.h b/intern/iksolver/intern/IK_QChain.h new file mode 100644 index 00000000000..ed02bcce53e --- /dev/null +++ b/intern/iksolver/intern/IK_QChain.h @@ -0,0 +1,211 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * + * @author Laurence + */ + +#ifndef NAN_INCLUDED_IK_QChain_h +#define NAN_INCLUDED_IK_QChain_h + + +#include "IK_QSegment.h" +#include <vector> +#include "MT_Scalar.h" +#include "TNT/cmat.h" + +/** + * This class is a collection of ordered segments that are used + * in an Inverse Kinematic solving routine. An IK solver operating + * on the chain, will in general manipulate all the segments of the + * chain in order to solve the IK problem. + * + * To build a chain use the default constructor. Once built it's + * then possible to add IK_Segments to the chain by inserting + * them into the vector of IK_Segments. Note that segments will be + * copied into the chain so chains cannot share instances of + * IK_Segments. + * + * You have full control of which segments form the chain via the + * the std::vector routines. + */ + +class IK_QChain{ + +public : + + /** + * Construct a IK_QChain with no segments. + */ + + IK_QChain( + ); + + // IK_QChains also have the default copy constructors + // available. + + /** + * Const access to the array of segments + * comprising the IK_QChain. Used for rendering + * etc + * @return a const reference to a vector of segments + */ + + const + std::vector<IK_QSegment> & + Segments( + ) const ; + + + /** + * Full access to segments used to initialize + * the IK_QChain and manipulate the segments. + * Use the push_back() method of std::vector to add + * segments in order to the chain + * @return a reference to a vector of segments + */ + + std::vector<IK_QSegment> & + Segments( + ); + + + /** + * Force the IK_QChain to recompute all the local + * segment transformations and composite them + * to calculate the global transformation for + * each segment. Must be called before + * ComputeJacobian() + */ + + void + UpdateGlobalTransformations( + ); + + /** + * Return the global position of the end + * of the last segment. + */ + + MT_Vector3 + EndEffector( + ) const; + + + /** + * Return the global pose of the end + * of the last segment. + */ + + MT_Vector3 + EndPose( + ) const; + + + /** + * Calculate the jacobian matrix for + * the current end effector position. + * A jacobian is the set of column vectors + * of partial derivatives for each active angle. + * This method also computes the transposed jacobian. + * @pre You must have updated the global transformations + * of the chain's segments before a call to this method. Do this + * with UpdateGlobalTransformation() + */ + + void + ComputeJacobian( + ); + + + /** + * @return A const reference to the last computed jacobian matrix + */ + + const + TNT::Matrix<MT_Scalar> & + Jacobian( + ) const ; + + /** + * @return A const reference to the last computed transposed jacobian matrix + */ + + const + TNT::Matrix<MT_Scalar> & + TransposedJacobian( + ) const ; + + /** + * Count the degrees of freedom in the IK_QChain + * @warning store this value rather than using this function + * as the termination value of a for loop etc. + */ + + int + DoF( + ) const; + + /** + * Compute the maximum extension of the chain from the + * root segment. This is the length of the root segments + * + the max extensions of all the other segments + */ + + const + MT_Scalar + MaxExtension( + ) const; + + +private : + + /// The vector of segments comprising the chain + std::vector<IK_QSegment> m_segments; + + /// The jacobain of the IK_QChain + TNT::Matrix<MT_Scalar> m_jacobian; + + /// It's transpose + TNT::Matrix<MT_Scalar> m_t_jacobian; + + MT_Vector3 m_end_effector; + MT_Vector3 m_end_pose; + + +}; + + +#endif
\ No newline at end of file diff --git a/intern/iksolver/intern/IK_QJacobianSolver.cpp b/intern/iksolver/intern/IK_QJacobianSolver.cpp new file mode 100644 index 00000000000..32a703cb94d --- /dev/null +++ b/intern/iksolver/intern/IK_QJacobianSolver.cpp @@ -0,0 +1,327 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "IK_QJacobianSolver.h" + +#include "TNT/svd.h" + +using namespace std; + + IK_QJacobianSolver * +IK_QJacobianSolver:: +New( +){ + return new IK_QJacobianSolver(); +} + + bool +IK_QJacobianSolver:: +Solve( + IK_QChain &chain, + const MT_Vector3 &g_position, + const MT_Vector3 &g_pose, + const MT_Scalar tolerance, + const int max_iterations, + const MT_Scalar max_angle_change +){ + + const vector<IK_QSegment> & segs = chain.Segments(); + if (segs.size() == 0) return false; + + // compute the goal direction from the base of the chain + // in global coordinates + + MT_Vector3 goal_dir = g_position - segs[0].GlobalSegmentStart(); + + + const MT_Scalar chain_max_extension = chain.MaxExtension(); + + bool do_parallel_check(false); + + if (chain_max_extension < goal_dir.length()) { + do_parallel_check = true; + } + + goal_dir.normalize(); + + + ArmMatrices(chain.DoF()); + + for (int iterations = 0; iterations < max_iterations; iterations++) { + + // check to see if the chain is pointing in the right direction + + if (iterations%32 && do_parallel_check && ParallelCheck(chain,goal_dir)) { + + return false; + } + + MT_Vector3 end_effector = chain.EndEffector(); + MT_Vector3 d_pos = g_position - end_effector; + const MT_Scalar x_length = d_pos.length(); + + if (x_length < tolerance) { + return true; + } + + chain.ComputeJacobian(); + + try { + ComputeInverseJacobian(chain,x_length,max_angle_change); + } + catch(...) { + return false; + } + + ComputeBetas(chain,d_pos); + UpdateChain(chain); + chain.UpdateGlobalTransformations(); + } + + + return false; +}; + +IK_QJacobianSolver:: +~IK_QJacobianSolver( +){ + // nothing to do +} + + +IK_QJacobianSolver:: +IK_QJacobianSolver( +){ + // nothing to do +}; + + void +IK_QJacobianSolver:: +ComputeBetas( + IK_QChain &chain, + const MT_Vector3 d_pos +){ + + m_beta = 0; + + m_beta[0] = d_pos.x(); + m_beta[1] = d_pos.y(); + m_beta[2] = d_pos.z(); + + TNT::matmult(m_d_theta,m_svd_inverse,m_beta); + +}; + + + int +IK_QJacobianSolver:: +ComputeInverseJacobian( + IK_QChain &chain, + const MT_Scalar x_length, + const MT_Scalar max_angle_change +) { + + int dimension = 0; + + m_svd_u = MT_Scalar(0); + + // copy first 3 rows of jacobian into m_svd_u + + int row, column; + + for (row = 0; row < 3; row ++) { + for (column = 0; column < chain.Jacobian().num_cols(); column ++) { + m_svd_u[row][column] = chain.Jacobian()[row][column]; + } + } + + m_svd_w = MT_Scalar(0); + m_svd_v = MT_Scalar(0); + + m_svd_work_space = MT_Scalar(0); + + TNT::SVD(m_svd_u,m_svd_w,m_svd_v,m_svd_work_space); + + // invert the SVD and compute inverse + + TNT::transpose(m_svd_v,m_svd_v_t); + TNT::transpose(m_svd_u,m_svd_u_t); + + // Compute damped least squares inverse of pseudo inverse + // Compute damping term lambda + + // Note when lambda is zero this is equivalent to the + // least squares solution. This is fine when the m_jjt is + // of full rank. When m_jjt is near to singular the least squares + // inverse tries to minimize |J(dtheta) - dX)| and doesn't + // try to minimize dTheta. This results in eratic changes in angle. + // Damped least squares minimizes |dtheta| to try and reduce this + // erratic behaviour. + + // We don't want to use the damped solution everywhere so we + // only increase lamda from zero as we approach a singularity. + + // find the smallest non-zero m_svd_w value + + int i = 0; + + MT_Scalar w_min = MT_INFINITY; + + // anything below epsilon is treated as zero + + MT_Scalar epsilon = MT_Scalar(1e-10); + + for ( i = 0; i <m_svd_w.size() ; i++) { + + if (m_svd_w[i] > epsilon && m_svd_w[i] < w_min) { + w_min = m_svd_w[i]; + } + } + + MT_Scalar lambda(0); + + MT_Scalar d = x_length/max_angle_change; + + if (w_min <= d/2) { + lambda = d/2; + } else + if (w_min < d) { + lambda = sqrt(w_min*(d - w_min)); + } else { + lambda = MT_Scalar(0); + } + + + lambda *= lambda; + + for (i= 0; i < m_svd_w.size(); i++) { + if (m_svd_w[i] < epsilon) { + m_svd_w[i] = MT_Scalar(0); + } else { + m_svd_w[i] = m_svd_w[i] / (m_svd_w[i] * m_svd_w[i] + lambda); + } + } + + + TNT::matmultdiag(m_svd_temp1,m_svd_w,m_svd_u_t); + TNT::matmult(m_svd_inverse,m_svd_v,m_svd_temp1); + + return dimension; + +} + + void +IK_QJacobianSolver:: +UpdateChain( + IK_QChain &chain +){ + + // iterate through the set of angles and + // update their values from the d_thetas + + vector<IK_QSegment> &segs = chain.Segments(); + + int seg_ind = 0; + for (seg_ind = 0;seg_ind < segs.size(); seg_ind++) { + + MT_Vector3 dq; + dq[0] = m_d_theta[3*seg_ind]; + dq[1] = m_d_theta[3*seg_ind + 1]; + dq[2] = m_d_theta[3*seg_ind + 2]; + segs[seg_ind].IncrementAngle(dq); + } + +}; + + void +IK_QJacobianSolver:: +ArmMatrices( + int dof +){ + + m_beta.newsize(dof); + m_d_theta.newsize(dof); + + m_svd_u.newsize(dof,dof); + m_svd_v.newsize(dof,dof); + m_svd_w.newsize(dof); + + m_svd_work_space.newsize(dof); + + m_svd_u = MT_Scalar(0); + m_svd_v = MT_Scalar(0); + m_svd_w = MT_Scalar(0); + + m_svd_u_t.newsize(dof,dof); + m_svd_v_t.newsize(dof,dof); + m_svd_w_diag.newsize(dof,dof); + m_svd_inverse.newsize(dof,dof); + m_svd_temp1.newsize(dof,dof); + +}; + + bool +IK_QJacobianSolver:: +ParallelCheck( + const IK_QChain &chain, + const MT_Vector3 goal_dir +) const { + + // compute the start of the chain in global coordinates + const vector<IK_QSegment> &segs = chain.Segments(); + + int num_segs = segs.size(); + + if (num_segs == 0) { + return false; + } + + MT_Scalar crossp_sum = 0; + + int i; + for (i = 0; i < num_segs; i++) { + MT_Vector3 global_seg_direction = segs[i].GlobalSegmentEnd() - + segs[i].GlobalSegmentStart(); + + global_seg_direction.normalize(); + + MT_Scalar crossp = (global_seg_direction.cross(goal_dir)).length(); + crossp_sum += MT_Scalar(fabs(crossp)); + } + + if (crossp_sum < MT_Scalar(0.01)) { + return true; + } else { + return false; + } +} + + diff --git a/intern/iksolver/intern/IK_QJacobianSolver.h b/intern/iksolver/intern/IK_QJacobianSolver.h new file mode 100644 index 00000000000..7e2f886d0c4 --- /dev/null +++ b/intern/iksolver/intern/IK_QJacobianSolver.h @@ -0,0 +1,184 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_IK_QJacobianSolver_h + +#define NAN_INCLUDED_IK_QJacobianSolver_h + +/** + * @author Laurence Bourn + * @date 28/6/2001 + */ + +#include "TNT/cmat.h" +#include <vector> +#include "MT_Vector3.h" +#include "IK_QChain.h" + +class IK_QJacobianSolver { + +public : + + /** + * Create a new IK_QJacobianSolver on the heap + * @return A newly created IK_QJacobianSolver you take ownership of the object + * and responsibility for deleting it + */ + + + static + IK_QJacobianSolver * + New( + ); + + /** + * Compute a solution for a chain. + * @param chain Reference to the chain to modify + * @param g_position Reference to the goal position. + * @param g_pose -not used- Reference to the goal pose. + * @param tolerance The maximum allowed distance between solution + * and goal for termination. + * @param max_iterations should be in the range (50 - 500) + * @param max_angle_change The maximum change in the angle vector + * of the chain (0.1 is a good value) + * + * @return True iff goal position reached. + */ + + bool + Solve( + IK_QChain &chain, + const MT_Vector3 &g_position, + const MT_Vector3 &g_pose, + const MT_Scalar tolerance, + const int max_iterations, + const MT_Scalar max_angle_change + ); + + ~IK_QJacobianSolver( + ); + + +private : + + /** + * Private constructor to force use of New() + */ + + IK_QJacobianSolver( + ); + + + /** + * Compute the inverse jacobian matrix of the chain. + * Uses a damped least squares solution when the matrix is + * is approaching singularity + */ + + int + ComputeInverseJacobian( + IK_QChain &chain, + const MT_Scalar x_length, + const MT_Scalar max_angle_change + ); + + void + ComputeBetas( + IK_QChain &chain, + const MT_Vector3 d_pos + ); + + /** + * Updates the angles of the chain with the newly + * computed values + */ + + void + UpdateChain( + IK_QChain &chain + ); + + /** + * Make sure all the matrices are of the correct size + */ + + void + ArmMatrices( + int dof + ); + + /** + * Quick check to see if all the segments are parallel + * to the goal direction. + */ + + bool + ParallelCheck( + const IK_QChain &chain, + const MT_Vector3 goal + ) const; + + + +private : + + /// the vector of intermediate betas + TNT::Vector<MT_Scalar> m_beta; + + /// the vector of computed angle changes + TNT::Vector<MT_Scalar> m_d_theta; + + /// the constraint gradients for each angle. + TNT::Vector<MT_Scalar> m_dh; + + /// Space required for SVD computation + + TNT::Vector<MT_Scalar> m_svd_w; + TNT::Vector<MT_Scalar> m_svd_work_space; + TNT::Matrix<MT_Scalar> m_svd_v; + TNT::Matrix<MT_Scalar> m_svd_u; + + TNT::Matrix<MT_Scalar> m_svd_w_diag; + TNT::Matrix<MT_Scalar> m_svd_v_t; + TNT::Matrix<MT_Scalar> m_svd_u_t; + TNT::Matrix<MT_Scalar> m_svd_inverse; + TNT::Matrix<MT_Scalar> m_svd_temp1; + + +}; + + + + +#endif + + + diff --git a/intern/iksolver/intern/IK_QSegment.cpp b/intern/iksolver/intern/IK_QSegment.cpp new file mode 100644 index 00000000000..2956dd815e2 --- /dev/null +++ b/intern/iksolver/intern/IK_QSegment.cpp @@ -0,0 +1,363 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * + * @author Laurence + */ + +#include "IK_QSegment.h" +#include <iostream.h> + +IK_QSegment:: +IK_QSegment ( + const MT_Point3 tr1, + const MT_Matrix3x3 A, + const MT_Scalar length, + const MT_ExpMap q +) : + m_length (length), + m_q (q) +{ + + m_max_extension = tr1.length() + length; + + m_transform.setOrigin(tr1); + m_transform.setBasis(A); + + UpdateLocalTransform(); +}; + + +IK_QSegment:: +IK_QSegment ( +) : + m_length(0), + m_q (0,0,0), + m_max_extension(0) +{ + // Intentionally empty +} + + + +// accessors +//////////// + +// The length of the segment + +const + MT_Scalar +IK_QSegment:: +Length( +) const { + return m_length; +} + +const + MT_Scalar +IK_QSegment:: +MaxExtension( +) const { + return m_max_extension; +} + +// This is the transform from adjacent +// coordinate systems in the chain. + +const + MT_Transform & +IK_QSegment:: +LocalTransform( +) const { + return m_local_transform; +} + +const + MT_ExpMap & +IK_QSegment:: +LocalJointParameter( +) const { + return m_q; +} + + MT_Transform +IK_QSegment:: +UpdateGlobal( + const MT_Transform & global +){ + // compute the global transform + // and the start of the segment in global coordinates. + + m_seg_start = global * m_transform.getOrigin(); + m_global_transform = global; + + const MT_Transform new_global = GlobalTransform(); + + m_seg_end = new_global.getOrigin(); + + return new_global; +} + + MT_Transform +IK_QSegment:: +GlobalTransform( +) const { + return m_global_transform * m_local_transform; +} + + + MT_Transform +IK_QSegment:: +UpdateAccumulatedLocal( + const MT_Transform & acc_local +){ + m_accum_local = acc_local; + return m_local_transform * m_accum_local; +} + +const + MT_Transform & +IK_QSegment:: +AccumulatedLocal( +) const { + return m_accum_local; +} + + MT_Vector3 +IK_QSegment:: +ComputeJacobianColumn( + int angle +) const { + + + MT_Transform translation; + translation.setIdentity(); + translation.translate(MT_Vector3(0,m_length,0)); + + + // we can compute the jacobian for one of the + // angles of this joint by first computing + // the partial derivative of the local transform dR/da + // and then computing + // dG/da = m_global_transform * dR/da * m_accum_local (0,0,0) + +#if 0 + + // use euler angles as a test of the matrices and this method. + + MT_Matrix3x3 dRda; + + MT_Quaternion rotx,roty,rotz; + + rotx.setRotation(MT_Vector3(1,0,0),m_q[0]); + roty.setRotation(MT_Vector3(0,1,0),m_q[1]); + rotz.setRotation(MT_Vector3(0,0,1),m_q[2]); + + MT_Matrix3x3 rotx_m(rotx); + MT_Matrix3x3 roty_m(roty); + MT_Matrix3x3 rotz_m(rotz); + + if (angle == 0) { + + MT_Scalar ci = cos(m_q[0]); + MT_Scalar si = sin(m_q[1]); + + dRda = MT_Matrix3x3( + 0, 0, 0, + 0,-si,-ci, + 0, ci,-si + ); + + dRda = rotz_m * roty_m * dRda; + } else + + if (angle == 1) { + + MT_Scalar cj = cos(m_q[1]); + MT_Scalar sj = sin(m_q[1]); + + dRda = MT_Matrix3x3( + -sj, 0, cj, + 0, 0, 0, + -cj, 0,-sj + ); + + dRda = rotz_m * dRda * rotx_m; + } else + + if (angle == 2) { + + MT_Scalar ck = cos(m_q[2]); + MT_Scalar sk = sin(m_q[2]); + + dRda = MT_Matrix3x3( + -sk,-ck, 0, + ck,-sk, 0, + 0, 0, 0 + ); + + dRda = dRda * roty_m * rotx_m; + } + + MT_Transform dRda_t(MT_Point3(0,0,0),dRda); + + // convert to 4x4 matrices coz dRda is singular. + MT_Matrix4x4 dRda_m(dRda_t); + dRda_m[3][3] = 0; + +#else + + // use exponential map derivatives + MT_Matrix4x4 dRda_m = m_q.partialDerivatives(angle); + +#endif + + + // Once we have computed the local derivatives we can compute + // derivatives of the end effector. + + // Imagine a chain consisting of 5 segments each with local + // transformation Li + // Then the global transformation G is L1 *L2 *L3 *L4 *L5 + // If we want to compute the partial derivatives of this expression + // w.r.t one of the angles x of L3 we should then compute + // dG/dx = d(L1 *L2 *L3 *L4 *L5)/dx + // = L1 *L2 * dL3/dx *L4 *L5 + // but L1 *L2 is the global transformation of the parent of this + // bone and L4 *L5 is the accumulated local transform of the children + // of this bone (m_accum_local) + // so dG/dx = m_global_transform * dL3/dx * m_accum_local + // + // so now we need to compute dL3/dx + // L3 = m_transform * rotation(m_q) * translate(0,m_length,0) + // do using the same procedure we get + // dL3/dx = m_transform * dR/dx * translate(0,m_length,0) + // dR/dx is the partial derivative of the exponential map w.r.t + // one of it's parameters. This is computed in MT_ExpMap + + MT_Matrix4x4 translation_m (translation); + MT_Matrix4x4 global_m(m_global_transform); + MT_Matrix4x4 accum_local_m(m_accum_local); + MT_Matrix4x4 transform_m(m_transform); + + + MT_Matrix4x4 dFda_m = global_m * transform_m * dRda_m * translation_m * accum_local_m; + + MT_Vector4 result = dFda_m * MT_Vector4(0,0,0,1); + return MT_Vector3(result[0],result[1],result[2]); +}; + + + +const + MT_Vector3 & +IK_QSegment:: +GlobalSegmentStart( +) const{ + return m_seg_start; +} + +const + MT_Vector3 & +IK_QSegment:: +GlobalSegmentEnd( +) const { + return m_seg_end; +} + + + void +IK_QSegment:: +IncrementAngle( + const MT_Vector3 &dq +){ + m_q.vector() += dq; + MT_Scalar theta(0); + m_q.reParameterize(theta); + + UpdateLocalTransform(); +} + + + void +IK_QSegment:: +SetAngle( + const MT_ExpMap &dq +){ + m_q = dq; + UpdateLocalTransform(); +} + + + void +IK_QSegment:: +UpdateLocalTransform( +){ +#if 0 + + //use euler angles - test + MT_Quaternion rotx,roty,rotz; + + rotx.setRotation(MT_Vector3(1,0,0),m_q[0]); + roty.setRotation(MT_Vector3(0,1,0),m_q[1]); + rotz.setRotation(MT_Vector3(0,0,1),m_q[2]); + + MT_Matrix3x3 rotx_m(rotx); + MT_Matrix3x3 roty_m(roty); + MT_Matrix3x3 rotz_m(rotz); + + MT_Matrix3x3 rot = rotz_m * roty_m * rotx_m; +#else + + //use exponential map + MT_Matrix3x3 rot = m_q.getMatrix(); + + +#endif + + MT_Transform rx(MT_Point3(0,0,0),rot); + + MT_Transform translation; + translation.setIdentity(); + translation.translate(MT_Vector3(0,m_length,0)); + + m_local_transform = m_transform * rx * translation; +}; + + + + + + diff --git a/intern/iksolver/intern/IK_QSegment.h b/intern/iksolver/intern/IK_QSegment.h new file mode 100644 index 00000000000..0c0e3a7f8bc --- /dev/null +++ b/intern/iksolver/intern/IK_QSegment.h @@ -0,0 +1,290 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * + * @author Laurence + */ +#ifndef NAN_INCLUDED_IK_QSegment_h +#define NAN_INCLUDED_IK_QSegment_h + + +#include "MT_Vector3.h" +#include "MT_Transform.h" +#include "MT_Matrix4x4.h" +#include "MT_ExpMap.h" + +#include <vector> + +/** + * An IK_Qsegment encodes information about a segments + * local coordinate system. + * In these segments exponential maps are used to parameterize + * the 3 DOF joints. Please see the file MT_ExpMap.h for more + * information on this parameterization. + * + * These segments always point along the y-axis. + * + * Here wee define the local coordinates of a joint as + * local_transform = + * translate(tr1) * rotation(A) * rotation(q) * translate(0,length,0) + * We use the standard moto column ordered matrices. You can read + * this as: + * - first translate by (0,length,0) + * - multiply by the rotation matrix derived from the current + * angle parameterization q. + * - multiply by the user defined matrix representing the rest + * position of the bone. + * - translate by the used defined translation (tr1) + * The ordering of these transformations is vital, you must + * use exactly the same transformations when displaying the segments + */ + +class IK_QSegment { + +public : + + /** + * Constructor. + * @param tr1 a user defined translation + * @param a used defined rotation matrix representin + * the rest position of the bone. + * @param the length of the bone. + * @param an exponential map can also be used to + * define the bone rest position. + */ + + IK_QSegment( + const MT_Point3 tr1, + const MT_Matrix3x3 A, + const MT_Scalar length, + const MT_ExpMap q + ); + + /** + * Default constructor + * Defines identity local coordinate system, + * with a bone length of 1. + */ + + + IK_QSegment( + ); + + + /** + * @return The length of the segment + */ + + const + MT_Scalar + Length( + ) const ; + + /** + * @return the max distance of the end of this + * bone from the local origin. + */ + + const + MT_Scalar + MaxExtension( + ) const ; + + /** + * @return The transform from adjacent + * coordinate systems in the chain. + */ + + const + MT_Transform & + LocalTransform( + ) const ; + + const + MT_ExpMap & + LocalJointParameter( + ) const; + + /** + * Update the global coordinates of this segment. + * @param global the global coordinates of the + * previous bone in the chain + * @return the global coordinates of this segment. + */ + + MT_Transform + UpdateGlobal( + const MT_Transform & global + ); + + /** + * @return The global transformation + */ + + MT_Transform + GlobalTransform( + ) const; + + + /** + * Update the accumulated local transform of this segment + * The accumulated local transform is the end effector + * transform in the local coordinates of this segment. + * @param acc_local the accumulated local transform of + * the child of this bone. + * @return the accumulated local transorm of this segment + */ + + MT_Transform + UpdateAccumulatedLocal( + const MT_Transform & acc_local + ); + + /** + * @return A const reference to accumulated local + * transform of this segment. + */ + + const + MT_Transform & + AccumulatedLocal( + ) const; + + /** + * @return A const Reference to start of segment in global + * coordinates + */ + + const + MT_Vector3 & + GlobalSegmentStart( + ) const; + + /** + * @return A const Reference to end of segment in global + * coordinates + */ + + const + MT_Vector3 & + GlobalSegmentEnd( + ) const; + + + /** + * @return the partial derivative of the end effector + * with respect to one of the degrees of freedom of this + * segment. + * @param angle the angle parameter you want to compute + * the partial derivatives for. For these segments this + * must be in the range [0,2] + */ + + MT_Vector3 + ComputeJacobianColumn( + int angle + ) const ; + + /** + * Explicitly set the angle parameterization value. + */ + + void + SetAngle( + const MT_ExpMap &q + ); + + /** + * Increment the angle parameterization value. + */ + + void + IncrementAngle( + const MT_Vector3 &dq + ); + + + /** + * Return the parameterization of this angle + */ + + const + MT_ExpMap & + ExpMap( + ) const { + return m_q; + }; + + +private : + + void + UpdateLocalTransform( + ); + + +private : + + /** + * m_transform The user defined transformation, composition of the + * translation and rotation from constructor. + */ + MT_Transform m_transform; + + /** + * The exponential map parameterization of this joint. + */ + + MT_ExpMap m_q; + MT_Scalar m_length; + + /** + * The maximum extension of this segment + * This is the magnitude of the user offset + the length of the + * chain + */ + + MT_Scalar m_max_extension; + + MT_Transform m_local_transform; + MT_Transform m_global_transform; + MT_Transform m_accum_local; + + MT_Vector3 m_seg_start; + MT_Vector3 m_seg_end; + +}; + +#endif
\ No newline at end of file diff --git a/intern/iksolver/intern/IK_QSolver_Class.h b/intern/iksolver/intern/IK_QSolver_Class.h new file mode 100644 index 00000000000..91ad9f9c186 --- /dev/null +++ b/intern/iksolver/intern/IK_QSolver_Class.h @@ -0,0 +1,107 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * + * @author Laurence + */ + +#ifndef NAN_INCLUDED_IK_Solver_Class +#define NAN_INCLUDED_IK_Solver_Class + +#include "IK_QChain.h" +#include "IK_QJacobianSolver.h" +#include "IK_QSegment.h" +#include "MEM_SmartPtr.h" + +/** + * This class just contains all instances of internal data + * associated with the external chain structure needed for + * an ik solve. A pointer to this class gets hidden in the + * external structure as a void pointer. + */ + +class IK_QSolver_Class { + +public : + + static + IK_QSolver_Class * + New( + ){ + MEM_SmartPtr<IK_QSolver_Class> output (new IK_QSolver_Class); + + MEM_SmartPtr<IK_QJacobianSolver> solver (IK_QJacobianSolver::New()); + + if (output == NULL || + solver == NULL + ) { + return NULL; + } + + output->m_solver = solver.Release(); + + return output.Release(); + }; + + IK_QChain & + Chain( + ) { + return m_chain; + }; + + IK_QJacobianSolver & + Solver( + ) { + return m_solver.Ref(); + } + + ~IK_QSolver_Class( + ) { + // nothing to do + } + + +private : + + IK_QSolver_Class( + ) { + }; + + IK_QChain m_chain; + MEM_SmartPtr<IK_QJacobianSolver> m_solver; + +}; + +#endif diff --git a/intern/iksolver/intern/IK_Segment.cpp b/intern/iksolver/intern/IK_Segment.cpp new file mode 100644 index 00000000000..f955a657dae --- /dev/null +++ b/intern/iksolver/intern/IK_Segment.cpp @@ -0,0 +1,277 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "IK_Segment.h" + + +IK_Segment:: +IK_Segment ( + const MT_Point3 tr1, + const MT_Matrix3x3 A, + const MT_Scalar length, + const bool pitch_on, + const bool yaw_on, + const bool role_on +){ + m_transform.setOrigin(tr1); + m_transform.setBasis(A); + m_angles[0] =MT_Scalar(0); + m_angles[1] =MT_Scalar(0); + m_angles[2] =MT_Scalar(0); + + m_active_angles[0] = role_on; + m_active_angles[1] = yaw_on; + m_active_angles[2] = pitch_on; + m_length = length; + + if (role_on) { + m_angle_vectors.push_back(MT_Vector3(1,0,0)); + } + if (yaw_on) { + m_angle_vectors.push_back(MT_Vector3(0,1,0)); + } + if (pitch_on) { + m_angle_vectors.push_back(MT_Vector3(0,0,1)); + } + UpdateLocalTransform(); + + +}; + + +IK_Segment:: +IK_Segment ( +) { + m_transform.setIdentity(); + + m_angles[0] =MT_Scalar(0); + m_angles[1] =MT_Scalar(0); + m_angles[2] =MT_Scalar(0); + + m_active_angles[0] = false; + m_active_angles[1] = false; + m_active_angles[2] = false; + m_length = MT_Scalar(1); + + UpdateLocalTransform(); +} + + + +// accessors +//////////// + +// The length of the segment + +const + MT_Scalar +IK_Segment:: +Length( +) const { + return m_length; +} + + +// This is the transform from adjacent +// coordinate systems in the chain. + +const + MT_Transform & +IK_Segment:: +LocalTransform( +) const { + return m_local_transform; +} + + void +IK_Segment:: +UpdateGlobal( + const MT_Transform & global +){ + + // compute the global transform + // and the start of the segment in global coordinates. + + m_seg_start = global * m_transform.getOrigin(); + m_global_transform = global * m_local_transform; +} + +const + MT_Transform & +IK_Segment:: +GlobalTransform( +) const { + return m_global_transform; +} + +const + MT_Vector3 & +IK_Segment:: +GlobalSegmentStart( +) const{ + return m_seg_start; +} + + +// Return the number of Degrees of Freedom +// for this segment + + int +IK_Segment:: +DoF( +) const { + return + (m_active_angles[0] == true) + + (m_active_angles[1] == true) + + (m_active_angles[2] == true); +} + + +// suspect interface... +// Increment the active angles (at most 3) by +// d_theta. Which angles are incremented depends +// on which are active. It returns DoF + + int +IK_Segment:: +IncrementAngles( + MT_Scalar *d_theta +){ + int i =0; + if (m_active_angles[0]) { + m_angles[0] += d_theta[i]; + i++; + } + if (m_active_angles[1]) { + m_angles[1] += d_theta[i]; + i++; + } + if (m_active_angles[2]) { + m_angles[2] += d_theta[i]; + i++; + } + UpdateLocalTransform(); + + return i; +} + + + int +IK_Segment:: +SetAngles( + const MT_Scalar *angles +){ + int i =0; + if (m_active_angles[0]) { + m_angles[0] = angles[i]; + i++; + } + if (m_active_angles[1]) { + m_angles[1] = angles[i]; + i++; + } + if (m_active_angles[2]) { + m_angles[2] = angles[i]; + i++; + } + UpdateLocalTransform(); + + return i; +} + + + void +IK_Segment:: +UpdateLocalTransform( +){ + // The local transformation is defined by + // a user defined translation and rotation followed by + // rotation by (roll,pitch,yaw) followed by + // a translation in x of m_length + + MT_Quaternion rotx,roty,rotz; + + rotx.setRotation(MT_Vector3(1,0,0),m_angles[0]); + roty.setRotation(MT_Vector3(0,1,0),m_angles[1]); + rotz.setRotation(MT_Vector3(0,0,1),m_angles[2]); + + MT_Quaternion rot = rotx * roty *rotz; + + MT_Transform rx(MT_Point3(0,0,0),rot); + + MT_Transform translation; + translation.setIdentity(); + translation.translate(MT_Vector3(0,m_length,0)); + + m_local_transform = m_transform * rx * translation; +}; + + +const + std::vector<MT_Vector3> & +IK_Segment:: +AngleVectors( +) const{ + return m_angle_vectors; +}; + + MT_Scalar +IK_Segment:: +ActiveAngle( + int i +) const { + MT_assert((i >=0) && (i < DoF())); + + // umm want to return the ith active angle + // and not the ith angle + + int j; + int angles = -1; + for (j=0;j < 3;j++) { + if (m_active_angles[j]) angles ++; + if (i == angles) return m_angles[j]; + } + return m_angles[0]; +} + + MT_Scalar +IK_Segment:: +Angle( + int i +) const { + MT_assert((i >=0) && (i < 3)); + return m_angles[i]; +} + + + + + diff --git a/intern/iksolver/intern/IK_Segment.h b/intern/iksolver/intern/IK_Segment.h new file mode 100644 index 00000000000..35018df7859 --- /dev/null +++ b/intern/iksolver/intern/IK_Segment.h @@ -0,0 +1,217 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_Segment_h + +#define NAN_INCLUDED_Segment_h + +/** + * @author Laurence Bourn + * @date 28/6/2001 + */ + + +#include "MT_Vector3.h" +#include "MT_Transform.h" +#include <vector> + +class IK_Segment { + +public : + + /** + * Constructor. + * @warning This class uses axis angles for it's parameterization. + * Axis angles are a poor representation for joints of more than 1 DOF + * because they suffer from Gimbal lock. This becomes noticeable in + * IK solutions. A better solution is to do use a quaternion to represent + * angles with 3 DOF + */ + + IK_Segment( + const MT_Point3 tr1, + const MT_Matrix3x3 A, + const MT_Scalar length, + const bool pitch_on, + const bool yaw_on, + const bool role_on + ); + + + IK_Segment( + ); + + + /** + * @return The length of the segment + */ + + const + MT_Scalar + Length( + ) const ; + + /** + * @return The transform from adjacent + * coordinate systems in the chain. + */ + + const + MT_Transform & + LocalTransform( + ) const ; + + + /** + * Get the segment to compute it's + * global transform given the global transform + * of the parent. This method also updtes the + * global segment start + */ + + void + UpdateGlobal( + const MT_Transform & global + ); + + /** + * @return A const reference to the global trnasformation + */ + + const + MT_Transform & + GlobalTransform( + ) const; + + /** + * @return A const Reference to start of segment in global + * coordinates + */ + + const + MT_Vector3 & + GlobalSegmentStart( + ) const; + + /** + * Computes the number of degrees of freedom of this segment + */ + + int + DoF( + ) const; + + + /** + * Increment the active angles (at most DoF()) by + * d_theta. Which angles are incremented depends + * on which are active. + * @return DoF() + * @warning Bad interface + */ + + int + IncrementAngles( + MT_Scalar *d_theta + ); + + + // FIXME - interface bloat + + /** + * @return the vectors about which the active + * angles operate + */ + + const + std::vector<MT_Vector3> & + AngleVectors( + ) const; + + /** + * @return the ith active angle + */ + + MT_Scalar + ActiveAngle( + int i + ) const; + + /** + * @return the ith angle + */ + MT_Scalar + Angle( + int i + ) const; + + + /** + * Set the active angles from the array + * @return the number of active angles + */ + + int + SetAngles( + const MT_Scalar *angles + ); + + +private : + + void + UpdateLocalTransform( + ); + + + +private : + + /** The user defined transformation, composition of the + * translation and rotation from constructor. + */ + + MT_Transform m_transform; + MT_Scalar m_angles[3]; + MT_Scalar m_length; + + MT_Transform m_local_transform; + MT_Transform m_global_transform; + + bool m_active_angles[3]; + + MT_Vector3 m_seg_start; + + std::vector<MT_Vector3> m_angle_vectors; + +}; + +#endif
\ No newline at end of file diff --git a/intern/iksolver/intern/IK_Solver.cpp b/intern/iksolver/intern/IK_Solver.cpp new file mode 100644 index 00000000000..11646597d6d --- /dev/null +++ b/intern/iksolver/intern/IK_Solver.cpp @@ -0,0 +1,196 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#define IK_USE_EXPMAP + + + +#ifdef IK_USE_EXPMAP +# include "IK_QSolver_Class.h" +#else +# include "IK_Solver_Class.h" +#endif +#include "../extern/IK_solver.h" + +#include <iostream.h> + + IK_Chain_ExternPtr +IK_CreateChain( + void +) { + + MEM_SmartPtr<IK_Chain_Extern> output (new IK_Chain_Extern); + MEM_SmartPtr<IK_QSolver_Class> output_void (IK_QSolver_Class::New()); + + + if (output == NULL || output_void == NULL) { + return NULL; + } + + output->chain_dof = 0; + output->num_segments = 0; + output->segments = NULL; + output->intern = output_void.Release(); + return output.Release(); +}; + + + int +IK_LoadChain( + IK_Chain_ExternPtr chain, + IK_Segment_ExternPtr segments, + int num_segs +) { + + if (chain == NULL || segments == NULL) return 0; + + IK_QSolver_Class *intern_cpp = (IK_QSolver_Class *)chain->intern; + if (intern_cpp == NULL) return 0; + + std::vector<IK_QSegment> & segs = intern_cpp->Chain().Segments(); + if (segs.size() != num_segs) { + segs = std::vector<IK_QSegment>(num_segs); + } + + std::vector<IK_QSegment>::const_iterator seg_end= segs.end(); + std::vector<IK_QSegment>::iterator seg_begin= segs.begin(); + + IK_Segment_ExternPtr extern_seg_it = segments; + + + for (;seg_begin != seg_end; ++seg_begin,++extern_seg_it) { + + MT_Point3 tr1(extern_seg_it->seg_start); + + MT_Matrix3x3 A( + extern_seg_it->basis[0],extern_seg_it->basis[1],extern_seg_it->basis[2], + extern_seg_it->basis[3],extern_seg_it->basis[4],extern_seg_it->basis[5], + extern_seg_it->basis[6],extern_seg_it->basis[7],extern_seg_it->basis[8] + ); + + MT_Scalar length(extern_seg_it->length); + + + *seg_begin = IK_QSegment( + tr1,A,length,MT_Vector3(0,0,0) + ); + + } + + + intern_cpp->Chain().UpdateGlobalTransformations(); + intern_cpp->Chain().ComputeJacobian(); + + chain->num_segments = num_segs; + chain->chain_dof = intern_cpp->Chain().DoF(); + chain->segments = segments; + + return 1; +}; + + int +IK_SolveChain( + IK_Chain_ExternPtr chain, + float goal[3], + float tolerance, + int max_iterations, + float max_angle_change, + IK_Segment_ExternPtr output +){ + if (chain == NULL || output == NULL) return 0; + if (chain->intern == NULL) return 0; + + IK_QSolver_Class *intern_cpp = (IK_QSolver_Class *)chain->intern; + + IK_QJacobianSolver & solver = intern_cpp->Solver(); + + bool solve_result = solver.Solve( + intern_cpp->Chain(), + MT_Vector3(goal), + MT_Vector3(0,0,0), + MT_Scalar(tolerance), + max_iterations, + MT_Scalar(max_angle_change) + ); + + // turn the computed role->pitch->yaw into a quaternion and + // return the result in output + + std::vector<IK_QSegment> & segs = intern_cpp->Chain().Segments(); + std::vector<IK_QSegment>::const_iterator seg_end= segs.end(); + std::vector<IK_QSegment>::iterator seg_begin= segs.begin(); + + for (;seg_begin != seg_end; ++seg_begin, ++output) { + MT_Matrix3x3 qrot = seg_begin->ExpMap().getMatrix(); + + // don't forget to transpose this qrot for use by blender! + + qrot.transpose(); // blender uses transpose here ???? + + output->basis_change[0] = float(qrot[0][0]); + output->basis_change[1] = float(qrot[0][1]); + output->basis_change[2] = float(qrot[0][2]); + output->basis_change[3] = float(qrot[1][0]); + output->basis_change[4] = float(qrot[1][1]); + output->basis_change[5] = float(qrot[1][2]); + output->basis_change[6] = float(qrot[2][0]); + output->basis_change[7] = float(qrot[2][1]); + output->basis_change[8] = float(qrot[2][2]); + + } + + + return solve_result ? 1 : 0; +} + + void +IK_FreeChain( + IK_Chain_ExternPtr chain +){ + IK_QSolver_Class *intern_cpp = (IK_QSolver_Class *)chain->intern; + + delete(intern_cpp); + delete(chain); + +} + + + + + + + + + + + + + diff --git a/intern/iksolver/intern/IK_Solver_Class.h b/intern/iksolver/intern/IK_Solver_Class.h new file mode 100644 index 00000000000..1ef6c22f946 --- /dev/null +++ b/intern/iksolver/intern/IK_Solver_Class.h @@ -0,0 +1,93 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_IK_Solver_Class + +#define NAN_INCLUDED_IK_Solver_Class + +#include "IK_Chain.h" +#include "IK_JacobianSolver.h" +#include "IK_Segment.h" +#include "MEM_SmartPtr.h" + +class IK_Solver_Class { + +public : + + static + IK_Solver_Class * + New( + ){ + MEM_SmartPtr<IK_Solver_Class> output (new IK_Solver_Class); + + MEM_SmartPtr<IK_JacobianSolver> solver (IK_JacobianSolver::New()); + + if (output == NULL || + solver == NULL + ) { + return NULL; + } + + output->m_solver = solver.Release(); + + return output.Release(); + }; + + IK_Chain & + Chain( + ) { + return m_chain; + }; + + IK_JacobianSolver & + Solver( + ) { + return m_solver.Ref(); + } + + ~IK_Solver_Class( + ) { + // nothing to do + } + + +private : + + IK_Solver_Class( + ) { + }; + + IK_Chain m_chain; + MEM_SmartPtr<IK_JacobianSolver> m_solver; + +}; + +#endif diff --git a/intern/iksolver/intern/MT_ExpMap.cpp b/intern/iksolver/intern/MT_ExpMap.cpp new file mode 100644 index 00000000000..ea005a42096 --- /dev/null +++ b/intern/iksolver/intern/MT_ExpMap.cpp @@ -0,0 +1,268 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * + * @author Laurence + */ + +#include "MT_ExpMap.h" + +/** + * Set the exponential map from a quaternion. The quaternion must be non-zero. + */ + + void +MT_ExpMap:: +setRotation( + const MT_Quaternion &q +) { + // ok first normailize the quaternion + // then compute theta the axis-angle and the normalized axis v + // scale v by theta and that's it hopefully! + + MT_Quaternion qt = q.normalized(); + + MT_Vector3 axis(qt.x(),qt.y(),qt.z()); + MT_Scalar cosp = qt.w(); + MT_Scalar sinp = axis.length(); + axis /= sinp; + + MT_Scalar theta = atan2(double(sinp),double(cosp)); + + axis *= theta; + m_v = axis; +} + +/** + * Convert from an exponential map to a quaternion + * representation + */ + + MT_Quaternion +MT_ExpMap:: +getRotation( +) const { + bool rep=0; + MT_Scalar cosp, sinp, theta; + + MT_Quaternion q; + + theta = m_v.length(); + + cosp = MT_Scalar(cos(.5*theta)); + sinp = MT_Scalar(sin(.5*theta)); + + q.w() = cosp; + + if (theta < MT_EXPMAP_MINANGLE) { + + MT_Vector3 temp = m_v * MT_Scalar(MT_Scalar(.5) - theta*theta/MT_Scalar(48.0)); /* Taylor Series for sinc */ + q.x() = temp.x(); + q.y() = temp.y(); + q.z() = temp.z(); + } else { + MT_Vector3 temp = m_v * (sinp/theta); /* Taylor Series for sinc */ + q.x() = temp.x(); + q.y() = temp.y(); + q.z() = temp.z(); + } + + return q; +} + +/** + * Convert the exponential map to a 3x3 matrix + */ + + MT_Matrix3x3 +MT_ExpMap:: +getMatrix( +) const { + + MT_Quaternion q = getRotation(); + return MT_Matrix3x3(q); +} + + + + +/** + * Force a reparameterization of the exponential + * map. + */ + + bool +MT_ExpMap:: +reParameterize( + MT_Scalar &theta +){ + bool rep(false); + theta = m_v.length(); + + if (theta > MT_PI){ + MT_Scalar scl = theta; + if (theta > MT_2_PI){ /* first get theta into range 0..2PI */ + theta = MT_Scalar(fmod(theta, MT_2_PI)); + scl = theta/scl; + m_v *= scl; + rep = true; + } + if (theta > MT_PI){ + scl = theta; + theta = MT_2_PI - theta; + scl = MT_Scalar(1.0) - MT_2_PI/scl; + m_v *= scl; + rep = true; + } + } + return rep; + +} + +/** + * Compute the partial derivatives of the exponential + * map (dR/de - where R is a 4x4 rotation matrix formed + * from the map) and return them as a 4x4 matrix + */ + + MT_Matrix4x4 +MT_ExpMap:: +partialDerivatives( + const int i +) const { + + MT_Quaternion q = getRotation(); + MT_Quaternion dQdx; + + MT_Matrix4x4 output; + + compute_dQdVi(i,dQdx); + compute_dRdVi(q,dQdx,output); + + return output; +} + + void +MT_ExpMap:: +compute_dRdVi( + const MT_Quaternion &q, + const MT_Quaternion &dQdvi, + MT_Matrix4x4 & dRdvi +) const { + + MT_Scalar prod[9]; + + /* This efficient formulation is arrived at by writing out the + * entire chain rule product dRdq * dqdv in terms of 'q' and + * noticing that all the entries are formed from sums of just + * nine products of 'q' and 'dqdv' */ + + prod[0] = -MT_Scalar(4)*q.x()*dQdvi.x(); + prod[1] = -MT_Scalar(4)*q.y()*dQdvi.y(); + prod[2] = -MT_Scalar(4)*q.z()*dQdvi.z(); + prod[3] = MT_Scalar(2)*(q.y()*dQdvi.x() + q.x()*dQdvi.y()); + prod[4] = MT_Scalar(2)*(q.w()*dQdvi.z() + q.z()*dQdvi.w()); + prod[5] = MT_Scalar(2)*(q.z()*dQdvi.x() + q.x()*dQdvi.z()); + prod[6] = MT_Scalar(2)*(q.w()*dQdvi.y() + q.y()*dQdvi.w()); + prod[7] = MT_Scalar(2)*(q.z()*dQdvi.y() + q.y()*dQdvi.z()); + prod[8] = MT_Scalar(2)*(q.w()*dQdvi.x() + q.x()*dQdvi.w()); + + /* first row, followed by second and third */ + dRdvi[0][0] = prod[1] + prod[2]; + dRdvi[0][1] = prod[3] - prod[4]; + dRdvi[0][2] = prod[5] + prod[6]; + + dRdvi[1][0] = prod[3] + prod[4]; + dRdvi[1][1] = prod[0] + prod[2]; + dRdvi[1][2] = prod[7] - prod[8]; + + dRdvi[2][0] = prod[5] - prod[6]; + dRdvi[2][1] = prod[7] + prod[8]; + dRdvi[2][2] = prod[0] + prod[1]; + + /* the 4th row and column are all zero */ + int i; + + for (i=0; i<3; i++) + dRdvi[3][i] = dRdvi[i][3] = MT_Scalar(0); + dRdvi[3][3] = 0; +} + +// compute partial derivatives dQ/dVi + + void +MT_ExpMap:: +compute_dQdVi( + const int i, + MT_Quaternion & dQdX +) const { + + MT_Scalar theta = m_v.length(); + MT_Scalar cosp(cos(MT_Scalar(.5)*theta)), sinp(sin(MT_Scalar(.5)*theta)); + + MT_assert(i>=0 && i<3); + + /* This is an efficient implementation of the derivatives given + * in Appendix A of the paper with common subexpressions factored out */ + if (theta < MT_EXPMAP_MINANGLE){ + const int i2 = (i+1)%3, i3 = (i+2)%3; + MT_Scalar Tsinc = MT_Scalar(0.5) - theta*theta/MT_Scalar(48.0); + MT_Scalar vTerm = m_v[i] * (theta*theta/MT_Scalar(40.0) - MT_Scalar(1.0)) / MT_Scalar(24.0); + + dQdX.w() = -.5*m_v[i]*Tsinc; + dQdX[i] = m_v[i]* vTerm + Tsinc; + dQdX[i2] = m_v[i2]*vTerm; + dQdX[i3] = m_v[i3]*vTerm; + } else { + const int i2 = (i+1)%3, i3 = (i+2)%3; + const MT_Scalar ang = 1.0/theta, ang2 = ang*ang*m_v[i], sang = sinp*ang; + const MT_Scalar cterm = ang2*(.5*cosp - sang); + + dQdX[i] = cterm*m_v[i] + sang; + dQdX[i2] = cterm*m_v[i2]; + dQdX[i3] = cterm*m_v[i3]; + dQdX.w() = MT_Scalar(-.5)*m_v[i]*sang; + } +} + + + + + + + + + + diff --git a/intern/iksolver/intern/MT_ExpMap.h b/intern/iksolver/intern/MT_ExpMap.h new file mode 100644 index 00000000000..10cacb59b78 --- /dev/null +++ b/intern/iksolver/intern/MT_ExpMap.h @@ -0,0 +1,219 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * + * @author Laurence + */ + +#ifndef MT_ExpMap_H +#define MT_ExpMap_H + +#include <MT_assert.h> + +#include "MT_Vector3.h" +#include "MT_Quaternion.h" +#include "MT_Matrix4x4.h" + +const MT_Scalar MT_EXPMAP_MINANGLE (1e-7); + +/** + * MT_ExpMap an exponential map parameterization of rotations + * in 3D. This implementation is derived from the paper + * "F. Sebastian Grassia. Practical parameterization of + * rotations using the exponential map. Journal of Graphics Tools, + * 3(3):29-48, 1998" Please go to http://www.acm.org/jgt/papers/Grassia98/ + * for a thorough description of the theory and sample code used + * to derive this class. + * + * Basic overview of why this class is used. + * In an IK system we need to paramterize the joint angles in some + * way. Typically 2 parameterizations are used. + * - Euler Angles + * These suffer from singularities in the parameterization known + * as gimbal lock. They also do not interpolate well. For every + * set of euler angles there is exactly 1 corresponding 3d rotation. + * - Quaternions. + * Great for interpolating. Only unit quaternions are valid rotations + * means that in a differential ik solver we often stray outside of + * this manifold into invalid rotations. Means we have to do a lot + * of nasty normalizations all the time. Does not suffer from + * gimbal lock problems. More expensive to compute partial derivatives + * as there are 4 of them. + * + * So exponential map is similar to a quaternion axis/angle + * representation but we store the angle as the length of the + * axis. So require only 3 parameters. Means that all exponential + * maps are valid rotations. Suffers from gimbal lock. But it's + * possible to detect when gimbal lock is near and reparameterize + * away from it. Also nice for interpolating. + * Exponential maps are share some of the useful properties of + * euler and quaternion parameterizations. And are very useful + * for differential IK solvers. + */ + +class MT_ExpMap { +public: + + /** + * Default constructor + * @warning there is no initialization in the + * default constructor + */ + + MT_ExpMap() {} + MT_ExpMap(const MT_Vector3& v) : m_v(v) {} + + MT_ExpMap(const float v[3]) : m_v(v) {} + MT_ExpMap(const double v[3]) : m_v(v) {} + + MT_ExpMap(MT_Scalar x, MT_Scalar y, MT_Scalar z) : + m_v(x, y, z) {} + + /** + * Construct an exponential map from a quaternion + */ + + MT_ExpMap( + const MT_Quaternion &q + ) { + setRotation(q); + }; + + /** + * Accessors + * Decided not to inherit from MT_Vector3 but rather + * this class contains an MT_Vector3. This is because + * it is very dangerous to use MT_Vector3 functions + * on this class and some of them have no direct meaning. + */ + + MT_Vector3 & + vector( + ) { + return m_v; + }; + + const + MT_Vector3 & + vector( + ) const { + return m_v; + }; + + /** + * Set the exponential map from a quaternion + */ + + void + setRotation( + const MT_Quaternion &q + ); + + /** + * Convert from an exponential map to a quaternion + * representation + */ + + MT_Quaternion + getRotation( + ) const; + + /** + * Convert the exponential map to a 3x3 matrix + */ + + MT_Matrix3x3 + getMatrix( + ) const; + + /** + * Force a reparameterization check of the exponential + * map. + * @param theta returns the new axis-angle. + * @return true iff a reParameterization took place. + * Use this function whenever you adjust the vector + * representing the exponential map. + */ + + bool + reParameterize( + MT_Scalar &theta + ); + + /** + * Compute the partial derivatives of the exponential + * map (dR/de - where R is a 4x4 matrix formed + * from the map) and return them as a 4x4 matrix + */ + + MT_Matrix4x4 + partialDerivatives( + const int i + ) const ; + +private : + + MT_Vector3 m_v; + + // private methods + + // Compute partial derivatives dR (3x3 rotation matrix) / dVi (EM vector) + // given the partial derivative dQ (Quaternion) / dVi (ith element of EM vector) + + + void + compute_dRdVi( + const MT_Quaternion &q, + const MT_Quaternion &dQdV, + MT_Matrix4x4 & dRdVi + ) const; + + // compute partial derivatives dQ/dVi + + void + compute_dQdVi( + int i, + MT_Quaternion & dQdX + ) const ; + + +}; + + + +#endif + + + diff --git a/intern/iksolver/intern/Makefile b/intern/iksolver/intern/Makefile new file mode 100644 index 00000000000..af32d816a80 --- /dev/null +++ b/intern/iksolver/intern/Makefile @@ -0,0 +1,44 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# iksolver intern Makefile +# + +LIBNAME = iksolver +DIR = $(OCGDIR)/intern/$(LIBNAME) +CCSRCS = IK_QChain.cpp IK_QJacobianSolver.cpp IK_QSegment.cpp MT_ExpMap.cpp IK_Solver.cpp + +include nan_compile.mk + +CCFLAGS += $(LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I$(NAN_MOTO)/include +CPPFLAGS += -I$(NAN_MEMUTIL)/include + diff --git a/intern/iksolver/intern/TNT/cholesky.h b/intern/iksolver/intern/TNT/cholesky.h new file mode 100644 index 00000000000..a3e0118f4e5 --- /dev/null +++ b/intern/iksolver/intern/TNT/cholesky.h @@ -0,0 +1,128 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + + +#ifndef CHOLESKY_H +#define CHOLESKY_H + +#include <cmath> + +// index method + +namespace TNT +{ + + +// +// Only upper part of A is used. Cholesky factor is returned in +// lower part of L. Returns 0 if successful, 1 otherwise. +// +template <class SPDMatrix, class SymmMatrix> +int Cholesky_upper_factorization(SPDMatrix &A, SymmMatrix &L) +{ + Subscript M = A.dim(1); + Subscript N = A.dim(2); + + assert(M == N); // make sure A is square + + // readjust size of L, if necessary + + if (M != L.dim(1) || N != L.dim(2)) + L = SymmMatrix(N,N); + + Subscript i,j,k; + + + typename SPDMatrix::element_type dot=0; + + + for (j=1; j<=N; j++) // form column j of L + { + dot= 0; + + for (i=1; i<j; i++) // for k= 1 TO j-1 + dot = dot + L(j,i)*L(j,i); + + L(j,j) = A(j,j) - dot; + + for (i=j+1; i<=N; i++) + { + dot = 0; + for (k=1; k<j; k++) + dot = dot + L(i,k)*L(j,k); + L(i,j) = A(j,i) - dot; + } + + if (L(j,j) <= 0.0) return 1; + + L(j,j) = sqrt( L(j,j) ); + + for (i=j+1; i<=N; i++) + L(i,j) = L(i,j) / L(j,j); + + } + + return 0; +} + + + + +} +// namespace TNT + +#endif +// CHOLESKY_H diff --git a/intern/iksolver/intern/TNT/cmat.h b/intern/iksolver/intern/TNT/cmat.h new file mode 100644 index 00000000000..80a82417e47 --- /dev/null +++ b/intern/iksolver/intern/TNT/cmat.h @@ -0,0 +1,661 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + + +// C compatible matrix: row-oriented, 0-based [i][j] and 1-based (i,j) indexing +// + +#ifndef CMAT_H +#define CMAT_H + +#include "subscript.h" +#include "vec.h" +#include <stdlib.h> +#include <assert.h> +#include <iostream> +#include <strstream> +#ifdef TNT_USE_REGIONS +#include "region2d.h" +#endif + +namespace TNT +{ + +template <class T> +class Matrix +{ + + + public: + + typedef Subscript size_type; + typedef T value_type; + typedef T element_type; + typedef T* pointer; + typedef T* iterator; + typedef T& reference; + typedef const T* const_iterator; + typedef const T& const_reference; + + Subscript lbound() const { return 1;} + + protected: + Subscript m_; + Subscript n_; + Subscript mn_; // total size + T* v_; + T** row_; + T* vm1_ ; // these point to the same data, but are 1-based + T** rowm1_; + + // internal helper function to create the array + // of row pointers + + void initialize(Subscript M, Subscript N) + { + mn_ = M*N; + m_ = M; + n_ = N; + + v_ = new T[mn_]; + row_ = new T*[M]; + rowm1_ = new T*[M]; + + assert(v_ != NULL); + assert(row_ != NULL); + assert(rowm1_ != NULL); + + T* p = v_; + vm1_ = v_ - 1; + for (Subscript i=0; i<M; i++) + { + row_[i] = p; + rowm1_[i] = p-1; + p += N ; + + } + + rowm1_ -- ; // compensate for 1-based offset + } + + void copy(const T* v) + { + Subscript N = m_ * n_; + Subscript i; + +#ifdef TNT_UNROLL_LOOPS + Subscript Nmod4 = N & 3; + Subscript N4 = N - Nmod4; + + for (i=0; i<N4; i+=4) + { + v_[i] = v[i]; + v_[i+1] = v[i+1]; + v_[i+2] = v[i+2]; + v_[i+3] = v[i+3]; + } + + for (i=N4; i< N; i++) + v_[i] = v[i]; +#else + + for (i=0; i< N; i++) + v_[i] = v[i]; +#endif + } + + void set(const T& val) + { + Subscript N = m_ * n_; + Subscript i; + +#ifdef TNT_UNROLL_LOOPS + Subscript Nmod4 = N & 3; + Subscript N4 = N - Nmod4; + + for (i=0; i<N4; i+=4) + { + v_[i] = val; + v_[i+1] = val; + v_[i+2] = val; + v_[i+3] = val; + } + + for (i=N4; i< N; i++) + v_[i] = val; +#else + + for (i=0; i< N; i++) + v_[i] = val; + +#endif + } + + + + void destroy() + { + /* do nothing, if no memory has been previously allocated */ + if (v_ == NULL) return ; + + /* if we are here, then matrix was previously allocated */ + if (v_ != NULL) delete [] (v_); + if (row_ != NULL) delete [] (row_); + + /* return rowm1_ back to original value */ + rowm1_ ++; + if (rowm1_ != NULL ) delete [] (rowm1_); + } + + + public: + + operator T**(){ return row_; } + operator T**() const { return row_; } + + + Subscript size() const { return mn_; } + + // constructors + + Matrix() : m_(0), n_(0), mn_(0), v_(0), row_(0), vm1_(0), rowm1_(0) {}; + + Matrix(const Matrix<T> &A) + { + initialize(A.m_, A.n_); + copy(A.v_); + } + + Matrix(Subscript M, Subscript N, const T& value = T()) + { + initialize(M,N); + set(value); + } + + Matrix(Subscript M, Subscript N, const T* v) + { + initialize(M,N); + copy(v); + } + + Matrix(Subscript M, Subscript N, const char *s) + { + initialize(M,N); + std::istrstream ins(s); + + Subscript i, j; + + for (i=0; i<M; i++) + for (j=0; j<N; j++) + ins >> row_[i][j]; + } + + + // destructor + // + ~Matrix() + { + destroy(); + } + + + // reallocating + // + Matrix<T>& newsize(Subscript M, Subscript N) + { + if (num_rows() == M && num_cols() == N) + return *this; + + destroy(); + initialize(M,N); + + return *this; + } + + void + diagonal(Vector<T> &diag) + { + int sz = diag.dim(); + newsize(sz,sz); + set(0); + + Subscript i; + for (i = 0; i < sz; i++) { + row_[i][i] = diag[i]; + } + } + + + + // assignments + // + Matrix<T>& operator=(const Matrix<T> &A) + { + if (v_ == A.v_) + return *this; + + if (m_ == A.m_ && n_ == A.n_) // no need to re-alloc + copy(A.v_); + + else + { + destroy(); + initialize(A.m_, A.n_); + copy(A.v_); + } + + return *this; + } + + Matrix<T>& operator=(const T& scalar) + { + set(scalar); + return *this; + } + + + Subscript dim(Subscript d) const + { +#ifdef TNT_BOUNDS_CHECK + assert( d >= 1); + assert( d <= 2); +#endif + return (d==1) ? m_ : ((d==2) ? n_ : 0); + } + + Subscript num_rows() const { return m_; } + Subscript num_cols() const { return n_; } + + + + + inline T* operator[](Subscript i) + { +#ifdef TNT_BOUNDS_CHECK + assert(0<=i); + assert(i < m_) ; +#endif + return row_[i]; + } + + inline const T* operator[](Subscript i) const + { +#ifdef TNT_BOUNDS_CHECK + assert(0<=i); + assert(i < m_) ; +#endif + return row_[i]; + } + + inline reference operator()(Subscript i) + { +#ifdef TNT_BOUNDS_CHECK + assert(1<=i); + assert(i <= mn_) ; +#endif + return vm1_[i]; + } + + inline const_reference operator()(Subscript i) const + { +#ifdef TNT_BOUNDS_CHECK + assert(1<=i); + assert(i <= mn_) ; +#endif + return vm1_[i]; + } + + + + inline reference operator()(Subscript i, Subscript j) + { +#ifdef TNT_BOUNDS_CHECK + assert(1<=i); + assert(i <= m_) ; + assert(1<=j); + assert(j <= n_); +#endif + return rowm1_[i][j]; + } + + + + inline const_reference operator() (Subscript i, Subscript j) const + { +#ifdef TNT_BOUNDS_CHECK + assert(1<=i); + assert(i <= m_) ; + assert(1<=j); + assert(j <= n_); +#endif + return rowm1_[i][j]; + } + + + +#ifdef TNT_USE_REGIONS + + typedef Region2D<Matrix<T> > Region; + + + Region operator()(const Index1D &I, const Index1D &J) + { + return Region(*this, I,J); + } + + + typedef const_Region2D< Matrix<T> > const_Region; + const_Region operator()(const Index1D &I, const Index1D &J) const + { + return const_Region(*this, I,J); + } + +#endif + + +}; + + +/* *************************** I/O ********************************/ + +template <class T> +std::ostream& operator<<(std::ostream &s, const Matrix<T> &A) +{ + Subscript M=A.num_rows(); + Subscript N=A.num_cols(); + + s << M << " " << N << "\n"; + + for (Subscript i=0; i<M; i++) + { + for (Subscript j=0; j<N; j++) + { + s << A[i][j] << " "; + } + s << "\n"; + } + + + return s; +} + +template <class T> +std::istream& operator>>(std::istream &s, Matrix<T> &A) +{ + + Subscript M, N; + + s >> M >> N; + + if ( !(M == A.num_rows() && N == A.num_cols() )) + { + A.newsize(M,N); + } + + + for (Subscript i=0; i<M; i++) + for (Subscript j=0; j<N; j++) + { + s >> A[i][j]; + } + + + return s; +} + +// *******************[ basic matrix algorithms ]*************************** + +template <class T> +Matrix<T> operator+(const Matrix<T> &A, + const Matrix<T> &B) +{ + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + assert(M==B.num_rows()); + assert(N==B.num_cols()); + + Matrix<T> tmp(M,N); + Subscript i,j; + + for (i=0; i<M; i++) + for (j=0; j<N; j++) + tmp[i][j] = A[i][j] + B[i][j]; + + return tmp; +} + +template <class T> +Matrix<T> operator-(const Matrix<T> &A, + const Matrix<T> &B) +{ + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + assert(M==B.num_rows()); + assert(N==B.num_cols()); + + Matrix<T> tmp(M,N); + Subscript i,j; + + for (i=0; i<M; i++) + for (j=0; j<N; j++) + tmp[i][j] = A[i][j] - B[i][j]; + + return tmp; +} + +template <class T> +Matrix<T> mult_element(const Matrix<T> &A, + const Matrix<T> &B) +{ + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + assert(M==B.num_rows()); + assert(N==B.num_cols()); + + Matrix<T> tmp(M,N); + Subscript i,j; + + for (i=0; i<M; i++) + for (j=0; j<N; j++) + tmp[i][j] = A[i][j] * B[i][j]; + + return tmp; +} + +template <class T> +void transpose(const Matrix<T> &A, Matrix<T> &S) +{ + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + assert(M==S.num_cols()); + assert(N==S.num_rows()); + + Subscript i, j; + + for (i=0; i<M; i++) + for (j=0; j<N; j++) + S[j][i] = A[i][j]; + +} + + +template <class T> +inline void matmult(Matrix<T>& C, const Matrix<T> &A, + const Matrix<T> &B) +{ + + assert(A.num_cols() == B.num_rows()); + + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + Subscript K = B.num_cols(); + + C.newsize(M,K); + + T sum; + + const T* row_i; + const T* col_k; + + for (Subscript i=0; i<M; i++) + for (Subscript k=0; k<K; k++) + { + row_i = &(A[i][0]); + col_k = &(B[0][k]); + sum = 0; + for (Subscript j=0; j<N; j++) + { + sum += *row_i * *col_k; + row_i++; + col_k += K; + } + C[i][k] = sum; + } + +} + +template <class T> +void matmult(Vector<T> &y, const Matrix<T> &A, const Vector<T> &x) +{ + +#ifdef TNT_BOUNDS_CHECK + assert(A.num_cols() == x.dim()); + assert(A.num_rows() == y.dim()); +#endif + + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + T sum; + + for (Subscript i=0; i<M; i++) + { + sum = 0; + const T* rowi = A[i]; + for (Subscript j=0; j<N; j++) + sum = sum + rowi[j] * x[j]; + + y[i] = sum; + } +} + +template <class T> +inline void matmultdiag( + Matrix<T>& C, + const Matrix<T> &A, + const Vector<T> &diag +){ +#ifdef TNT_BOUNDS_CHECK + assert(A.num_cols() ==A.num_rows()== diag.dim()); +#endif + + Subscript M = A.num_rows(); + Subscript K = diag.dim(); + + C.newsize(M,K); + + const T* row_i; + const T* col_k; + + for (Subscript i=0; i<M; i++) { + for (Subscript k=0; k<K; k++) + { + C[i][k] = A[i,k] * diag[k]; + } + } +} + + +template <class T> +inline void matmultdiag( + Matrix<T>& C, + const Vector<T> &diag, + const Matrix<T> &A +){ +#ifdef TNT_BOUNDS_CHECK + assert(A.num_cols() ==A.num_rows()== diag.dim()); +#endif + + Subscript M = A.num_rows(); + Subscript K = diag.dim(); + + C.newsize(M,K); + + for (Subscript i=0; i<M; i++) { + + const T diag_element = diag[i]; + + for (Subscript k=0; k<K; k++) + { + C[i][k] = A[i][k] * diag_element; + } + } +} + + + + +} // namespace TNT + + + + +#endif +// CMAT_H diff --git a/intern/iksolver/intern/TNT/fcscmat.h b/intern/iksolver/intern/TNT/fcscmat.h new file mode 100644 index 00000000000..877364ad38c --- /dev/null +++ b/intern/iksolver/intern/TNT/fcscmat.h @@ -0,0 +1,197 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + + +// Templated compressed sparse column matrix (Fortran conventions). +// uses 1-based offsets in storing row indices. +// Used primarily to interface with Fortran sparse matrix libaries. +// (CANNOT BE USED AS AN STL CONTAINER.) + + +#ifndef FCSCMAT_H +#define FCSCMAT_H + +#include <iostream> +#include <cassert> +#include "tnt.h" +#include "vec.h" + +using namespace std; + +namespace TNT +{ + +template <class T> +class Fortran_Sparse_Col_Matrix +{ + + protected: + + Vector<T> val_; // data values (nz_ elements) + Vector<Subscript> rowind_; // row_ind (nz_ elements) + Vector<Subscript> colptr_; // col_ptr (n_+1 elements) + + int nz_; // number of nonzeros + Subscript m_; // global dimensions + Subscript n_; + + public: + + + Fortran_Sparse_Col_Matrix(void); + Fortran_Sparse_Col_Matrix(const Fortran_Sparse_Col_Matrix<T> &S) + : val_(S.val_), rowind_(S.rowind_), colptr_(S.colptr_), nz_(S.nz_), + m_(S.m_), n_(S.n_) {}; + Fortran_Sparse_Col_Matrix(Subscript M, Subscript N, + Subscript nz, const T *val, const Subscript *r, + const Subscript *c) : val_(nz, val), rowind_(nz, r), + colptr_(N+1, c), nz_(nz), m_(M), n_(N) {}; + + Fortran_Sparse_Col_Matrix(Subscript M, Subscript N, + Subscript nz, char *val, char *r, + char *c) : val_(nz, val), rowind_(nz, r), + colptr_(N+1, c), nz_(nz), m_(M), n_(N) {}; + + Fortran_Sparse_Col_Matrix(Subscript M, Subscript N, + Subscript nz, const T *val, Subscript *r, Subscript *c) + : val_(nz, val), rowind_(nz, r), colptr_(N+1, c), nz_(nz), + m_(M), n_(N) {}; + + ~Fortran_Sparse_Col_Matrix() {}; + + + T & val(Subscript i) { return val_(i); } + const T & val(Subscript i) const { return val_(i); } + + Subscript & row_ind(Subscript i) { return rowind_(i); } + const Subscript & row_ind(Subscript i) const { return rowind_(i); } + + Subscript col_ptr(Subscript i) { return colptr_(i);} + const Subscript col_ptr(Subscript i) const { return colptr_(i);} + + + Subscript num_cols() const { return m_;} + Subscript num_rows() const { return n_; } + + Subscript dim(Subscript i) const + { +#ifdef TNT_BOUNDS_CHECK + assert( 1 <= i ); + assert( i <= 2 ); +#endif + if (i==1) return m_; + else if (i==2) return m_; + else return 0; + } + + Subscript num_nonzeros() const {return nz_;}; + Subscript lbound() const {return 1;} + + + + Fortran_Sparse_Col_Matrix& operator=(const + Fortran_Sparse_Col_Matrix &C) + { + val_ = C.val_; + rowind_ = C.rowind_; + colptr_ = C.colptr_; + nz_ = C.nz_; + m_ = C.m_; + n_ = C.n_; + + return *this; + } + + Fortran_Sparse_Col_Matrix& newsize(Subscript M, Subscript N, + Subscript nz) + { + val_.newsize(nz); + rowind_.newsize(nz); + colptr_.newsize(N+1); + return *this; + } +}; + +template <class T> +ostream& operator<<(ostream &s, const Fortran_Sparse_Col_Matrix<T> &A) +{ + Subscript M=A.num_rows(); + Subscript N=A.num_cols(); + + s << M << " " << N << " " << A.num_nonzeros() << endl; + + + for (Subscript k=1; k<=N; k++) + { + Subscript start = A.col_ptr(k); + Subscript end = A.col_ptr(k+1); + + for (Subscript i= start; i<end; i++) + { + s << A.row_ind(i) << " " << k << " " << A.val(i) << endl; + } + } + + return s; +} + + + +} // namespace TNT + +#endif +/* FCSCMAT_H */ + diff --git a/intern/iksolver/intern/TNT/fmat.h b/intern/iksolver/intern/TNT/fmat.h new file mode 100644 index 00000000000..5de9a63813e --- /dev/null +++ b/intern/iksolver/intern/TNT/fmat.h @@ -0,0 +1,609 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + + +// Fortran-compatible matrix: column oriented, 1-based (i,j) indexing + +#ifndef FMAT_H +#define FMAT_H + +#include "subscript.h" +#include "vec.h" +#include <cstdlib> +#include <cassert> +#include <iostream> +#include <strstream> +#ifdef TNT_USE_REGIONS +#include "region2d.h" +#endif + +// simple 1-based, column oriented Matrix class + +namespace TNT +{ + +template <class T> +class Fortran_Matrix +{ + + + public: + + typedef T value_type; + typedef T element_type; + typedef T* pointer; + typedef T* iterator; + typedef T& reference; + typedef const T* const_iterator; + typedef const T& const_reference; + + Subscript lbound() const { return 1;} + + protected: + T* v_; // these are adjusted to simulate 1-offset + Subscript m_; + Subscript n_; + T** col_; // these are adjusted to simulate 1-offset + + // internal helper function to create the array + // of row pointers + + void initialize(Subscript M, Subscript N) + { + // adjust col_[] pointers so that they are 1-offset: + // col_[j][i] is really col_[j-1][i-1]; + // + // v_[] is the internal contiguous array, it is still 0-offset + // + v_ = new T[M*N]; + col_ = new T*[N]; + + assert(v_ != NULL); + assert(col_ != NULL); + + + m_ = M; + n_ = N; + T* p = v_ - 1; + for (Subscript i=0; i<N; i++) + { + col_[i] = p; + p += M ; + + } + col_ --; + } + + void copy(const T* v) + { + Subscript N = m_ * n_; + Subscript i; + +#ifdef TNT_UNROLL_LOOPS + Subscript Nmod4 = N & 3; + Subscript N4 = N - Nmod4; + + for (i=0; i<N4; i+=4) + { + v_[i] = v[i]; + v_[i+1] = v[i+1]; + v_[i+2] = v[i+2]; + v_[i+3] = v[i+3]; + } + + for (i=N4; i< N; i++) + v_[i] = v[i]; +#else + + for (i=0; i< N; i++) + v_[i] = v[i]; +#endif + } + + void set(const T& val) + { + Subscript N = m_ * n_; + Subscript i; + +#ifdef TNT_UNROLL_LOOPS + Subscript Nmod4 = N & 3; + Subscript N4 = N - Nmod4; + + for (i=0; i<N4; i+=4) + { + v_[i] = val; + v_[i+1] = val; + v_[i+2] = val; + v_[i+3] = val; + } + + for (i=N4; i< N; i++) + v_[i] = val; +#else + + for (i=0; i< N; i++) + v_[i] = val; + +#endif + } + + + + void destroy() + { + /* do nothing, if no memory has been previously allocated */ + if (v_ == NULL) return ; + + /* if we are here, then matrix was previously allocated */ + delete [] (v_); + col_ ++; // changed back to 0-offset + delete [] (col_); + } + + + public: + + T* begin() { return v_; } + const T* begin() const { return v_;} + + T* end() { return v_ + m_*n_; } + const T* end() const { return v_ + m_*n_; } + + + // constructors + + Fortran_Matrix() : v_(0), m_(0), n_(0), col_(0) {}; + Fortran_Matrix(const Fortran_Matrix<T> &A) + { + initialize(A.m_, A.n_); + copy(A.v_); + } + + Fortran_Matrix(Subscript M, Subscript N, const T& value = T()) + { + initialize(M,N); + set(value); + } + + Fortran_Matrix(Subscript M, Subscript N, const T* v) + { + initialize(M,N); + copy(v); + } + + + Fortran_Matrix(Subscript M, Subscript N, char *s) + { + initialize(M,N); + std::istrstream ins(s); + + Subscript i, j; + + for (i=1; i<=M; i++) + for (j=1; j<=N; j++) + ins >> (*this)(i,j); + } + + // destructor + ~Fortran_Matrix() + { + destroy(); + } + + + // assignments + // + Fortran_Matrix<T>& operator=(const Fortran_Matrix<T> &A) + { + if (v_ == A.v_) + return *this; + + if (m_ == A.m_ && n_ == A.n_) // no need to re-alloc + copy(A.v_); + + else + { + destroy(); + initialize(A.m_, A.n_); + copy(A.v_); + } + + return *this; + } + + Fortran_Matrix<T>& operator=(const T& scalar) + { + set(scalar); + return *this; + } + + + Subscript dim(Subscript d) const + { +#ifdef TNT_BOUNDS_CHECK + assert( d >= 1); + assert( d <= 2); +#endif + return (d==1) ? m_ : ((d==2) ? n_ : 0); + } + + Subscript num_rows() const { return m_; } + Subscript num_cols() const { return n_; } + + Fortran_Matrix<T>& newsize(Subscript M, Subscript N) + { + if (num_rows() == M && num_cols() == N) + return *this; + + destroy(); + initialize(M,N); + + return *this; + } + + + + // 1-based element access + // + inline reference operator()(Subscript i, Subscript j) + { +#ifdef TNT_BOUNDS_CHECK + assert(1<=i); + assert(i <= m_) ; + assert(1<=j); + assert(j <= n_); +#endif + return col_[j][i]; + } + + inline const_reference operator() (Subscript i, Subscript j) const + { +#ifdef TNT_BOUNDS_CHECK + assert(1<=i); + assert(i <= m_) ; + assert(1<=j); + assert(j <= n_); +#endif + return col_[j][i]; + } + + +#ifdef TNT_USE_REGIONS + + typedef Region2D<Fortran_Matrix<T> > Region; + typedef const_Region2D< Fortran_Matrix<T> > const_Region; + + Region operator()(const Index1D &I, const Index1D &J) + { + return Region(*this, I,J); + } + + const_Region operator()(const Index1D &I, const Index1D &J) const + { + return const_Region(*this, I,J); + } + +#endif + + +}; + + +/* *************************** I/O ********************************/ + +template <class T> +std::ostream& operator<<(std::ostream &s, const Fortran_Matrix<T> &A) +{ + Subscript M=A.num_rows(); + Subscript N=A.num_cols(); + + s << M << " " << N << "\n"; + + for (Subscript i=1; i<=M; i++) + { + for (Subscript j=1; j<=N; j++) + { + s << A(i,j) << " "; + } + s << "\n"; + } + + + return s; +} + +template <class T> +std::istream& operator>>(std::istream &s, Fortran_Matrix<T> &A) +{ + + Subscript M, N; + + s >> M >> N; + + if ( !(M == A.num_rows() && N == A.num_cols())) + { + A.newsize(M,N); + } + + + for (Subscript i=1; i<=M; i++) + for (Subscript j=1; j<=N; j++) + { + s >> A(i,j); + } + + + return s; +} + +// *******************[ basic matrix algorithms ]*************************** + + +template <class T> +Fortran_Matrix<T> operator+(const Fortran_Matrix<T> &A, + const Fortran_Matrix<T> &B) +{ + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + assert(M==B.num_rows()); + assert(N==B.num_cols()); + + Fortran_Matrix<T> tmp(M,N); + Subscript i,j; + + for (i=1; i<=M; i++) + for (j=1; j<=N; j++) + tmp(i,j) = A(i,j) + B(i,j); + + return tmp; +} + +template <class T> +Fortran_Matrix<T> operator-(const Fortran_Matrix<T> &A, + const Fortran_Matrix<T> &B) +{ + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + assert(M==B.num_rows()); + assert(N==B.num_cols()); + + Fortran_Matrix<T> tmp(M,N); + Subscript i,j; + + for (i=1; i<=M; i++) + for (j=1; j<=N; j++) + tmp(i,j) = A(i,j) - B(i,j); + + return tmp; +} + +// element-wise multiplication (use matmult() below for matrix +// multiplication in the linear algebra sense.) +// +// +template <class T> +Fortran_Matrix<T> mult_element(const Fortran_Matrix<T> &A, + const Fortran_Matrix<T> &B) +{ + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + assert(M==B.num_rows()); + assert(N==B.num_cols()); + + Fortran_Matrix<T> tmp(M,N); + Subscript i,j; + + for (i=1; i<=M; i++) + for (j=1; j<=N; j++) + tmp(i,j) = A(i,j) * B(i,j); + + return tmp; +} + + +template <class T> +Fortran_Matrix<T> transpose(const Fortran_Matrix<T> &A) +{ + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + Fortran_Matrix<T> S(N,M); + Subscript i, j; + + for (i=1; i<=M; i++) + for (j=1; j<=N; j++) + S(j,i) = A(i,j); + + return S; +} + + + +template <class T> +inline Fortran_Matrix<T> matmult(const Fortran_Matrix<T> &A, + const Fortran_Matrix<T> &B) +{ + +#ifdef TNT_BOUNDS_CHECK + assert(A.num_cols() == B.num_rows()); +#endif + + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + Subscript K = B.num_cols(); + + Fortran_Matrix<T> tmp(M,K); + T sum; + + for (Subscript i=1; i<=M; i++) + for (Subscript k=1; k<=K; k++) + { + sum = 0; + for (Subscript j=1; j<=N; j++) + sum = sum + A(i,j) * B(j,k); + + tmp(i,k) = sum; + } + + return tmp; +} + +template <class T> +inline Fortran_Matrix<T> operator*(const Fortran_Matrix<T> &A, + const Fortran_Matrix<T> &B) +{ + return matmult(A,B); +} + +template <class T> +inline int matmult(Fortran_Matrix<T>& C, const Fortran_Matrix<T> &A, + const Fortran_Matrix<T> &B) +{ + + assert(A.num_cols() == B.num_rows()); + + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + Subscript K = B.num_cols(); + + C.newsize(M,K); // adjust shape of C, if necessary + + + T sum; + + const T* row_i; + const T* col_k; + + for (Subscript i=1; i<=M; i++) + { + for (Subscript k=1; k<=K; k++) + { + row_i = &A(i,1); + col_k = &B(1,k); + sum = 0; + for (Subscript j=1; j<=N; j++) + { + sum += *row_i * *col_k; + row_i += M; + col_k ++; + } + + C(i,k) = sum; + } + + } + + return 0; +} + + +template <class T> +Vector<T> matmult(const Fortran_Matrix<T> &A, const Vector<T> &x) +{ + +#ifdef TNT_BOUNDS_CHECK + assert(A.num_cols() == x.dim()); +#endif + + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + Vector<T> tmp(M); + T sum; + + for (Subscript i=1; i<=M; i++) + { + sum = 0; + for (Subscript j=1; j<=N; j++) + sum = sum + A(i,j) * x(j); + + tmp(i) = sum; + } + + return tmp; +} + +template <class T> +inline Vector<T> operator*(const Fortran_Matrix<T> &A, const Vector<T> &x) +{ + return matmult(A,x); +} + +template <class T> +inline Fortran_Matrix<T> operator*(const Fortran_Matrix<T> &A, const T &x) +{ + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + Subscript MN = M*N; + + Fortran_Matrix<T> res(M,N); + const T* a = A.begin(); + T* t = res.begin(); + T* tend = res.end(); + + for (t=res.begin(); t < tend; t++, a++) + *t = *a * x; + + return res; +} + +} // namespace TNT +#endif +// FMAT_H diff --git a/intern/iksolver/intern/TNT/fortran.h b/intern/iksolver/intern/TNT/fortran.h new file mode 100644 index 00000000000..4f513300588 --- /dev/null +++ b/intern/iksolver/intern/TNT/fortran.h @@ -0,0 +1,99 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + + +// Header file to define C/Fortran conventions (Platform specific) + +#ifndef FORTRAN_H +#define FORTRAN_H + +// help map between C/C++ data types and Fortran types + +typedef int Fortran_integer; +typedef float Fortran_float; +typedef double Fortran_double; + + +typedef Fortran_double *fda_; // (in/out) double precision array +typedef const Fortran_double *cfda_; // (in) double precsion array + +typedef Fortran_double *fd_; // (in/out) single double precision +typedef const Fortran_double *cfd_; // (in) single double precision + +typedef Fortran_float *ffa_; // (in/out) float precision array +typedef const Fortran_float *cffa_; // (in) float precsion array + +typedef Fortran_float *ff_; // (in/out) single float precision +typedef const Fortran_float *cff_; // (in) single float precision + +typedef Fortran_integer *fia_; // (in/out) single integer array +typedef const Fortran_integer *cfia_; // (in) single integer array + +typedef Fortran_integer *fi_; // (in/out) single integer +typedef const Fortran_integer *cfi_; // (in) single integer + +typedef char *fch_; // (in/out) single character +typedef char *cfch_; // (in) single character + + + +#ifndef TNT_SUBSCRIPT_TYPE +#define TNT_SUBSCRIPT_TYPE TNT::Fortran_integer +#endif + + +#endif +// FORTRAN_H diff --git a/intern/iksolver/intern/TNT/fspvec.h b/intern/iksolver/intern/TNT/fspvec.h new file mode 100644 index 00000000000..b8dde35b6c6 --- /dev/null +++ b/intern/iksolver/intern/TNT/fspvec.h @@ -0,0 +1,200 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + +// Templated sparse vector (Fortran conventions). +// Used primarily to interface with Fortran sparse matrix libaries. +// (CANNOT BE USED AS AN STL CONTAINER.) + +#ifndef FSPVEC_H +#define FSPVEC_H + +#include "tnt.h" +#include "vec.h" +#include <cstdlib> +#include <cassert> +#include <iostream> +#include <strstream> + +using namespace std; + +namespace TNT +{ + +template <class T> +class Fortran_Sparse_Vector +{ + + + public: + + typedef Subscript size_type; + typedef T value_type; + typedef T element_type; + typedef T* pointer; + typedef T* iterator; + typedef T& reference; + typedef const T* const_iterator; + typedef const T& const_reference; + + Subscript lbound() const { return 1;} + + protected: + Vector<T> val_; + Vector<Subscript> index_; + Subscript dim_; // prescribed dimension + + + public: + + // size and shape information + + Subscript dim() const { return dim_; } + Subscript num_nonzeros() const { return val_.dim(); } + + // access + + T& val(Subscript i) { return val_(i); } + const T& val(Subscript i) const { return val_(i); } + + Subscript &index(Subscript i) { return index_(i); } + const Subscript &index(Subscript i) const { return index_(i); } + + // constructors + + Fortran_Sparse_Vector() : val_(), index_(), dim_(0) {}; + Fortran_Sparse_Vector(Subscript N, Subscript nz) : val_(nz), + index_(nz), dim_(N) {}; + Fortran_Sparse_Vector(Subscript N, Subscript nz, const T *values, + const Subscript *indices): val_(nz, values), index_(nz, indices), + dim_(N) {} + + Fortran_Sparse_Vector(const Fortran_Sparse_Vector<T> &S): + val_(S.val_), index_(S.index_), dim_(S.dim_) {} + + // initialize from string, e.g. + // + // Fortran_Sparse_Vector<T> A(N, 2, "1.0 2.1", "1 3"); + // + Fortran_Sparse_Vector(Subscript N, Subscript nz, char *v, + char *ind) : val_(nz, v), index_(nz, ind), dim_(N) {} + + // assignments + + Fortran_Sparse_Vector<T> & newsize(Subscript N, Subscript nz) + { + val_.newsize(nz); + index_.newsize(nz); + dim_ = N; + return *this; + } + + Fortran_Sparse_Vector<T> & operator=( const Fortran_Sparse_Vector<T> &A) + { + val_ = A.val_; + index_ = A.index_; + dim_ = A.dim_; + + return *this; + } + + // methods + + + +}; + + +/* *************************** I/O ********************************/ + +template <class T> +ostream& operator<<(ostream &s, const Fortran_Sparse_Vector<T> &A) +{ + // output format is : N nz val1 ind1 val2 ind2 ... + Subscript nz=A.num_nonzeros(); + + s << A.dim() << " " << nz << endl; + + for (Subscript i=1; i<=nz; i++) + s << A.val(i) << " " << A.index(i) << endl; + s << endl; + + return s; +} + + +template <class T> +istream& operator>>(istream &s, Fortran_Sparse_Vector<T> &A) +{ + // output format is : N nz val1 ind1 val2 ind2 ... + + Subscript N; + Subscript nz; + + s >> N >> nz; + + A.newsize(N, nz); + + for (Subscript i=1; i<=nz; i++) + s >> A.val(i) >> A.index(i); + + + return s; +} + +} // namespace TNT + +#endif +// FSPVEC_H diff --git a/intern/iksolver/intern/TNT/index.h b/intern/iksolver/intern/TNT/index.h new file mode 100644 index 00000000000..885545d11b5 --- /dev/null +++ b/intern/iksolver/intern/TNT/index.h @@ -0,0 +1,115 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + + +// Vector/Matrix/Array Index Module + +#ifndef INDEX_H +#define INDEX_H + +#include "subscript.h" + +namespace TNT +{ + +class Index1D +{ + Subscript lbound_; + Subscript ubound_; + + public: + + Subscript lbound() const { return lbound_; } + Subscript ubound() const { return ubound_; } + + Index1D(const Index1D &D) : lbound_(D.lbound_), ubound_(D.ubound_) {} + Index1D(Subscript i1, Subscript i2) : lbound_(i1), ubound_(i2) {} + + Index1D & operator=(const Index1D &D) + { + lbound_ = D.lbound_; + ubound_ = D.ubound_; + return *this; + } + +}; + +inline Index1D operator+(const Index1D &D, Subscript i) +{ + return Index1D(i+D.lbound(), i+D.ubound()); +} + +inline Index1D operator+(Subscript i, const Index1D &D) +{ + return Index1D(i+D.lbound(), i+D.ubound()); +} + + + +inline Index1D operator-(Index1D &D, Subscript i) +{ + return Index1D(D.lbound()-i, D.ubound()-i); +} + +inline Index1D operator-(Subscript i, Index1D &D) +{ + return Index1D(i-D.lbound(), i-D.ubound()); +} + +} // namespace TNT + +#endif + diff --git a/intern/iksolver/intern/TNT/lapack.h b/intern/iksolver/intern/TNT/lapack.h new file mode 100644 index 00000000000..d3556a96071 --- /dev/null +++ b/intern/iksolver/intern/TNT/lapack.h @@ -0,0 +1,225 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + + +// Header file for Fortran Lapack + +#ifndef LAPACK_H +#define LAPACK_H + +// This file incomplete and included here to only demonstrate the +// basic framework for linking with the Fortran Lapack routines. + +#include "fortran.h" +#include "vec.h" +#include "fmat.h" + + +#define F77_DGESV dgesv_ +#define F77_DGELS dgels_ +#define F77_DSYEV dsyev_ +#define F77_DGEEV dgeev_ + +extern "C" +{ + + // linear equations (general) using LU factorizaiton + // + void F77_DGESV(cfi_ N, cfi_ nrhs, fda_ A, cfi_ lda, + fia_ ipiv, fda_ b, cfi_ ldb, fi_ info); + + // solve linear least squares using QR or LU factorization + // + void F77_DGELS(cfch_ trans, cfi_ M, + cfi_ N, cfi_ nrhs, fda_ A, cfi_ lda, fda_ B, cfi_ ldb, fda_ work, + cfi_ lwork, fi_ info); + + // solve symmetric eigenvalues + // + void F77_DSYEV( cfch_ jobz, cfch_ uplo, cfi_ N, fda_ A, cfi_ lda, + fda_ W, fda_ work, cfi_ lwork, fi_ info); + + // solve unsymmetric eigenvalues + // + void F77_DGEEV(cfch_ jobvl, cfch_ jobvr, cfi_ N, fda_ A, cfi_ lda, + fda_ wr, fda_ wi, fda_ vl, cfi_ ldvl, fda_ vr, + cfi_ ldvr, fda_ work, cfi_ lwork, fi_ info); + +} + +// solve linear equations using LU factorization + +using namespace TNT; + +Vector<double> Lapack_LU_linear_solve(const Fortran_Matrix<double> &A, + const Vector<double> &b) +{ + const Fortran_integer one=1; + Subscript M=A.num_rows(); + Subscript N=A.num_cols(); + + Fortran_Matrix<double> Tmp(A); + Vector<double> x(b); + Vector<Fortran_integer> index(M); + Fortran_integer info = 0; + + F77_DGESV(&N, &one, &Tmp(1,1), &M, &index(1), &x(1), &M, &info); + + if (info != 0) return Vector<double>(0); + else + return x; +} + +// solve linear least squares problem using QR factorization +// +Vector<double> Lapack_LLS_QR_linear_solve(const Fortran_Matrix<double> &A, + const Vector<double> &b) +{ + const Fortran_integer one=1; + Subscript M=A.num_rows(); + Subscript N=A.num_cols(); + + Fortran_Matrix<double> Tmp(A); + Vector<double> x(b); + Fortran_integer info = 0; + + char transp = 'N'; + Fortran_integer lwork = 5 * (M+N); // temporary work space + Vector<double> work(lwork); + + F77_DGELS(&transp, &M, &N, &one, &Tmp(1,1), &M, &x(1), &M, &work(1), + &lwork, &info); + + if (info != 0) return Vector<double>(0); + else + return x; +} + +// *********************** Eigenvalue problems ******************* + +// solve symmetric eigenvalue problem (eigenvalues only) +// +Vector<double> Upper_symmetric_eigenvalue_solve(const Fortran_Matrix<double> &A) +{ + char jobz = 'N'; + char uplo = 'U'; + Subscript N = A.num_rows(); + + assert(N == A.num_cols()); + + Vector<double> eigvals(N); + Fortran_integer worksize = 3*N; + Fortran_integer info = 0; + Vector<double> work(worksize); + Fortran_Matrix<double> Tmp = A; + + F77_DSYEV(&jobz, &uplo, &N, &Tmp(1,1), &N, eigvals.begin(), work.begin(), + &worksize, &info); + + if (info != 0) return Vector<double>(); + else + return eigvals; +} + + +// solve unsymmetric eigenvalue problems +// +int eigenvalue_solve(const Fortran_Matrix<double> &A, + Vector<double> &wr, Vector<double> &wi) +{ + char jobvl = 'N'; + char jobvr = 'N'; + + Fortran_integer N = A.num_rows(); + + + assert(N == A.num_cols()); + + if (N<1) return 1; + + Fortran_Matrix<double> vl(1,N); /* should be NxN ? **** */ + Fortran_Matrix<double> vr(1,N); + Fortran_integer one = 1; + + Fortran_integer worksize = 5*N; + Fortran_integer info = 0; + Vector<double> work(worksize, 0.0); + Fortran_Matrix<double> Tmp = A; + + wr.newsize(N); + wi.newsize(N); + +// void F77_DGEEV(cfch_ jobvl, cfch_ jobvr, cfi_ N, fda_ A, cfi_ lda, +// fda_ wr, fda_ wi, fda_ vl, cfi_ ldvl, fda_ vr, +// cfi_ ldvr, fda_ work, cfi_ lwork, fi_ info); + + F77_DGEEV(&jobvl, &jobvr, &N, &Tmp(1,1), &N, &(wr(1)), + &(wi(1)), &(vl(1,1)), &one, &(vr(1,1)), &one, + &(work(1)), &worksize, &info); + + return (info==0 ? 0: 1); +} + + + + + +#endif +// LAPACK_H + + + + diff --git a/intern/iksolver/intern/TNT/lu.h b/intern/iksolver/intern/TNT/lu.h new file mode 100644 index 00000000000..b86027aa386 --- /dev/null +++ b/intern/iksolver/intern/TNT/lu.h @@ -0,0 +1,236 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + + +#ifndef LU_H +#define LU_H + +// Solve system of linear equations Ax = b. +// +// Typical usage: +// +// Matrix(double) A; +// Vector(Subscript) ipiv; +// Vector(double) b; +// +// 1) LU_Factor(A,ipiv); +// 2) LU_Solve(A,ipiv,b); +// +// Now b has the solution x. Note that both A and b +// are overwritten. If these values need to be preserved, +// one can make temporary copies, as in +// +// O) Matrix(double) T = A; +// 1) LU_Factor(T,ipiv); +// 1a) Vector(double) x=b; +// 2) LU_Solve(T,ipiv,x); +// +// See details below. +// + + +// for fabs() +// +#include <cmath> + +// right-looking LU factorization algorithm (unblocked) +// +// Factors matrix A into lower and upper triangular matrices +// (L and U respectively) in solving the linear equation Ax=b. +// +// +// Args: +// +// A (input/output) Matrix(1:n, 1:n) In input, matrix to be +// factored. On output, overwritten with lower and +// upper triangular factors. +// +// indx (output) Vector(1:n) Pivot vector. Describes how +// the rows of A were reordered to increase +// numerical stability. +// +// Return value: +// +// int (0 if successful, 1 otherwise) +// +// + + +namespace TNT +{ + +template <class MaTRiX, class VecToRSubscript> +int LU_factor( MaTRiX &A, VecToRSubscript &indx) +{ + assert(A.lbound() == 1); // currently for 1-offset + assert(indx.lbound() == 1); // vectors and matrices + + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + if (M == 0 || N==0) return 0; + if (indx.dim() != M) + indx.newsize(M); + + Subscript i=0,j=0,k=0; + Subscript jp=0; + + typename MaTRiX::element_type t; + + Subscript minMN = (M < N ? M : N) ; // min(M,N); + + for (j=1; j<= minMN; j++) + { + + // find pivot in column j and test for singularity. + + jp = j; + t = fabs(A(j,j)); + for (i=j+1; i<=M; i++) + if ( fabs(A(i,j)) > t) + { + jp = i; + t = fabs(A(i,j)); + } + + indx(j) = jp; + + // jp now has the index of maximum element + // of column j, below the diagonal + + if ( A(jp,j) == 0 ) + return 1; // factorization failed because of zero pivot + + + if (jp != j) // swap rows j and jp + for (k=1; k<=N; k++) + { + t = A(j,k); + A(j,k) = A(jp,k); + A(jp,k) =t; + } + + if (j<M) // compute elements j+1:M of jth column + { + // note A(j,j), was A(jp,p) previously which was + // guarranteed not to be zero (Label #1) + // + typename MaTRiX::element_type recp = 1.0 / A(j,j); + + for (k=j+1; k<=M; k++) + A(k,j) *= recp; + } + + + if (j < minMN) + { + // rank-1 update to trailing submatrix: E = E - x*y; + // + // E is the region A(j+1:M, j+1:N) + // x is the column vector A(j+1:M,j) + // y is row vector A(j,j+1:N) + + Subscript ii,jj; + + for (ii=j+1; ii<=M; ii++) + for (jj=j+1; jj<=N; jj++) + A(ii,jj) -= A(ii,j)*A(j,jj); + } + } + + return 0; +} + + + + +template <class MaTRiX, class VecToR, class VecToRSubscripts> +int LU_solve(const MaTRiX &A, const VecToRSubscripts &indx, VecToR &b) +{ + assert(A.lbound() == 1); // currently for 1-offset + assert(indx.lbound() == 1); // vectors and matrices + assert(b.lbound() == 1); + + Subscript i,ii=0,ip,j; + Subscript n = b.dim(); + typename MaTRiX::element_type sum = 0.0; + + for (i=1;i<=n;i++) + { + ip=indx(i); + sum=b(ip); + b(ip)=b(i); + if (ii) + for (j=ii;j<=i-1;j++) + sum -= A(i,j)*b(j); + else if (sum) ii=i; + b(i)=sum; + } + for (i=n;i>=1;i--) + { + sum=b(i); + for (j=i+1;j<=n;j++) + sum -= A(i,j)*b(j); + b(i)=sum/A(i,i); + } + + return 0; +} + +} // namespace TNT + +#endif +// LU_H diff --git a/intern/iksolver/intern/TNT/qr.h b/intern/iksolver/intern/TNT/qr.h new file mode 100644 index 00000000000..074551896b9 --- /dev/null +++ b/intern/iksolver/intern/TNT/qr.h @@ -0,0 +1,261 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + +#ifndef QR_H +#define QR_H + +// Classical QR factorization example, based on Stewart[1973]. +// +// +// This algorithm computes the factorization of a matrix A +// into a product of an orthognal matrix (Q) and an upper triangular +// matrix (R), such that QR = A. +// +// Parameters: +// +// A (in): Matrix(1:N, 1:N) +// +// Q (output): Matrix(1:N, 1:N), collection of Householder +// column vectors Q1, Q2, ... QN +// +// R (output): upper triangular Matrix(1:N, 1:N) +// +// Returns: +// +// 0 if successful, 1 if A is detected to be singular +// + + +#include <cmath> //for sqrt() & fabs() +#include "tntmath.h" // for sign() + +// Classical QR factorization, based on Stewart[1973]. +// +// +// This algorithm computes the factorization of a matrix A +// into a product of an orthognal matrix (Q) and an upper triangular +// matrix (R), such that QR = A. +// +// Parameters: +// +// A (in/out): On input, A is square, Matrix(1:N, 1:N), that represents +// the matrix to be factored. +// +// On output, Q and R is encoded in the same Matrix(1:N,1:N) +// in the following manner: +// +// R is contained in the upper triangular section of A, +// except that R's main diagonal is in D. The lower +// triangular section of A represents Q, where each +// column j is the vector Qj = I - uj*uj'/pi_j. +// +// C (output): vector of Pi[j] +// D (output): main diagonal of R, i.e. D(i) is R(i,i) +// +// Returns: +// +// 0 if successful, 1 if A is detected to be singular +// + +namespace TNT +{ + +template <class MaTRiX, class Vector> +int QR_factor(MaTRiX &A, Vector& C, Vector &D) +{ + assert(A.lbound() == 1); // ensure these are all + assert(C.lbound() == 1); // 1-based arrays and vectors + assert(D.lbound() == 1); + + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + assert(M == N); // make sure A is square + + Subscript i,j,k; + typename MaTRiX::element_type eta, sigma, sum; + + // adjust the shape of C and D, if needed... + + if (N != C.size()) C.newsize(N); + if (N != D.size()) D.newsize(N); + + for (k=1; k<N; k++) + { + // eta = max |M(i,k)|, for k <= i <= n + // + eta = 0; + for (i=k; i<=N; i++) + { + double absA = fabs(A(i,k)); + eta = ( absA > eta ? absA : eta ); + } + + if (eta == 0) // matrix is singular + { + cerr << "QR: k=" << k << "\n"; + return 1; + } + + // form Qk and premiltiply M by it + // + for(i=k; i<=N; i++) + A(i,k) = A(i,k) / eta; + + sum = 0; + for (i=k; i<=N; i++) + sum = sum + A(i,k)*A(i,k); + sigma = sign(A(k,k)) * sqrt(sum); + + + A(k,k) = A(k,k) + sigma; + C(k) = sigma * A(k,k); + D(k) = -eta * sigma; + + for (j=k+1; j<=N; j++) + { + sum = 0; + for (i=k; i<=N; i++) + sum = sum + A(i,k)*A(i,j); + sum = sum / C(k); + + for (i=k; i<=N; i++) + A(i,j) = A(i,j) - sum * A(i,k); + } + + D(N) = A(N,N); + } + + return 0; +} + +// modified form of upper triangular solve, except that the main diagonal +// of R (upper portion of A) is in D. +// +template <class MaTRiX, class Vector> +int R_solve(const MaTRiX &A, /*const*/ Vector &D, Vector &b) +{ + assert(A.lbound() == 1); // ensure these are all + assert(D.lbound() == 1); // 1-based arrays and vectors + assert(b.lbound() == 1); + + Subscript i,j; + Subscript N = A.num_rows(); + + assert(N == A.num_cols()); + assert(N == D.dim()); + assert(N == b.dim()); + + typename MaTRiX::element_type sum; + + if (D(N) == 0) + return 1; + + b(N) = b(N) / + D(N); + + for (i=N-1; i>=1; i--) + { + if (D(i) == 0) + return 1; + sum = 0; + for (j=i+1; j<=N; j++) + sum = sum + A(i,j)*b(j); + b(i) = ( b(i) - sum ) / + D(i); + } + + return 0; +} + + +template <class MaTRiX, class Vector> +int QR_solve(const MaTRiX &A, const Vector &c, /*const*/ Vector &d, + Vector &b) +{ + assert(A.lbound() == 1); // ensure these are all + assert(c.lbound() == 1); // 1-based arrays and vectors + assert(d.lbound() == 1); + + Subscript N=A.num_rows(); + + assert(N == A.num_cols()); + assert(N == c.dim()); + assert(N == d.dim()); + assert(N == b.dim()); + + Subscript i,j; + typename MaTRiX::element_type sum, tau; + + for (j=1; j<N; j++) + { + // form Q'*b + sum = 0; + for (i=j; i<=N; i++) + sum = sum + A(i,j)*b(i); + if (c(j) == 0) + return 1; + tau = sum / c(j); + for (i=j; i<=N; i++) + b(i) = b(i) - tau * A(i,j); + } + return R_solve(A, d, b); // solve Rx = Q'b +} + +} // namespace TNT + +#endif +// QR_H diff --git a/intern/iksolver/intern/TNT/region1d.h b/intern/iksolver/intern/TNT/region1d.h new file mode 100644 index 00000000000..0307ee02c39 --- /dev/null +++ b/intern/iksolver/intern/TNT/region1d.h @@ -0,0 +1,403 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + + + +#ifndef REGION1D_H +#define REGION1D_H + + +#include "subscript.h" +#include "index.h" +#include <iostream> +#include <cassert> + +namespace TNT +{ + +template <class Array1D> +class const_Region1D; + +template <class Array1D> +class Region1D +{ + protected: + + Array1D & A_; + Subscript offset_; // 0-based + Subscript dim_; + + typedef typename Array1D::element_type T; + + public: + const Array1D & array() const { return A_; } + + Subscript offset() const { return offset_;} + Subscript dim() const { return dim_; } + + Subscript offset(Subscript i) const + { +#ifdef TNT_BOUNDS_CHECK + assert(i==TNT_BASE_OFFSET); +#endif + return offset_; + } + + Subscript dim(Subscript i) const + { +#ifdef TNT_BOUNDS_CHECK + assert(i== TNT_BASE_OFFSET); +#endif + return offset_; + } + + + Region1D(Array1D &A, Subscript i1, Subscript i2) : A_(A) + { +#ifdef TNT_BOUNDS_CHECK + assert(TNT_BASE_OFFSET <= i1 ); + assert(i2 <= A.dim() + (TNT_BASE_OFFSET-1)); + assert(i1 <= i2); +#endif + offset_ = i1 - TNT_BASE_OFFSET; + dim_ = i2-i1 + 1; + } + + Region1D(Array1D &A, const Index1D &I) : A_(A) + { +#ifdef TNT_BOUNDS_CHECK + assert(TNT_BASE_OFFSET <=I.lbound()); + assert(I.ubound() <= A.dim() + (TNT_BASE_OFFSET-1)); + assert(I.lbound() <= I.ubound()); +#endif + offset_ = I.lbound() - TNT_BASE_OFFSET; + dim_ = I.ubound() - I.lbound() + 1; + } + + Region1D(Region1D<Array1D> &A, Subscript i1, Subscript i2) : + A_(A.A_) + { +#ifdef TNT_BOUNDS_CHECK + assert(TNT_BASE_OFFSET <= i1 ); + assert(i2 <= A.dim() + (TNT_BASE_OFFSET - 1)); + assert(i1 <= i2); +#endif + // (old-offset) (new-offset) + // + offset_ = (i1 - TNT_BASE_OFFSET) + A.offset_; + dim_ = i2-i1 + 1; + } + + Region1D<Array1D> operator()(Subscript i1, Subscript i2) + { +#ifdef TNT_BOUNDS_CHECK + assert(TNT_BASE_OFFSET <= i1); + assert(i2 <= dim() + (TNT_BASE_OFFSET -1)); + assert(i1 <= i2); +#endif + // offset_ is 0-based, so no need for + // ( - TNT_BASE_OFFSET) + // + return Region1D<Array1D>(A_, i1+offset_, + offset_ + i2); + } + + + Region1D<Array1D> operator()(const Index1D &I) + { +#ifdef TNT_BOUNDS_CHECK + assert(TNT_BASE_OFFSET<=I.lbound()); + assert(I.ubound() <= dim() + (TNT_BASE_OFFSET-1)); + assert(I.lbound() <= I.ubound()); +#endif + return Region1D<Array1D>(A_, I.lbound()+offset_, + offset_ + I.ubound()); + } + + + + + T & operator()(Subscript i) + { +#ifdef TNT_BOUNDS_CHECK + assert(TNT_BASE_OFFSET <= i); + assert(i <= dim() + (TNT_BASE_OFFSET-1)); +#endif + return A_(i+offset_); + } + + const T & operator() (Subscript i) const + { +#ifdef TNT_BOUNDS_CHECK + assert(TNT_BASE_OFFSET <= i); + assert(i <= dim() + (TNT_BASE_OFFSET-1)); +#endif + return A_(i+offset_); + } + + + Region1D<Array1D> & operator=(const Region1D<Array1D> &R) + { + // make sure both sides conform + assert(dim() == R.dim()); + + Subscript N = dim(); + Subscript i; + Subscript istart = TNT_BASE_OFFSET; + Subscript iend = istart + N-1; + + for (i=istart; i<=iend; i++) + (*this)(i) = R(i); + + return *this; + } + + + + Region1D<Array1D> & operator=(const const_Region1D<Array1D> &R) + { + // make sure both sides conform + assert(dim() == R.dim()); + + Subscript N = dim(); + Subscript i; + Subscript istart = TNT_BASE_OFFSET; + Subscript iend = istart + N-1; + + for (i=istart; i<=iend; i++) + (*this)(i) = R(i); + + return *this; + + } + + + Region1D<Array1D> & operator=(const T& t) + { + Subscript N=dim(); + Subscript i; + Subscript istart = TNT_BASE_OFFSET; + Subscript iend = istart + N-1; + + for (i=istart; i<= iend; i++) + (*this)(i) = t; + + return *this; + + } + + + Region1D<Array1D> & operator=(const Array1D &R) + { + // make sure both sides conform + Subscript N = dim(); + assert(dim() == R.dim()); + + Subscript i; + Subscript istart = TNT_BASE_OFFSET; + Subscript iend = istart + N-1; + + for (i=istart; i<=iend; i++) + (*this)(i) = R(i); + + return *this; + + } + +}; + +template <class Array1D> +std::ostream& operator<<(std::ostream &s, Region1D<Array1D> &A) +{ + Subscript N=A.dim(); + Subscript istart = TNT_BASE_OFFSET; + Subscript iend = N - 1 + TNT_BASE_OFFSET; + + for (Subscript i=istart; i<=iend; i++) + s << A(i) << endl; + + return s; +} + + +/* --------- class const_Region1D ------------ */ + +template <class Array1D> +class const_Region1D +{ + protected: + + const Array1D & A_; + Subscript offset_; // 0-based + Subscript dim_; + typedef typename Array1D::element_type T; + + public: + const Array1D & array() const { return A_; } + + Subscript offset() const { return offset_;} + Subscript dim() const { return dim_; } + + Subscript offset(Subscript i) const + { +#ifdef TNT_BOUNDS_CHECK + assert(i==TNT_BASE_OFFSET); +#endif + return offset_; + } + + Subscript dim(Subscript i) const + { +#ifdef TNT_BOUNDS_CHECK + assert(i== TNT_BASE_OFFSET); +#endif + return offset_; + } + + + const_Region1D(const Array1D &A, Subscript i1, Subscript i2) : A_(A) + { +#ifdef TNT_BOUNDS_CHECK + assert(TNT_BASE_OFFSET <= i1 ); + assert(i2 <= A.dim() + (TNT_BASE_OFFSET-1)); + assert(i1 <= i2); +#endif + offset_ = i1 - TNT_BASE_OFFSET; + dim_ = i2-i1 + 1; + } + + const_Region1D(const Array1D &A, const Index1D &I) : A_(A) + { +#ifdef TNT_BOUNDS_CHECK + assert(TNT_BASE_OFFSET <=I.lbound()); + assert(I.ubound() <= A.dim() + (TNT_BASE_OFFSET-1)); + assert(I.lbound() <= I.ubound()); +#endif + offset_ = I.lbound() - TNT_BASE_OFFSET; + dim_ = I.ubound() - I.lbound() + 1; + } + + const_Region1D(const_Region1D<Array1D> &A, Subscript i1, Subscript i2) : + A_(A.A_) + { +#ifdef TNT_BOUNDS_CHECK + assert(TNT_BASE_OFFSET <= i1 ); + assert(i2 <= A.dim() + (TNT_BASE_OFFSET - 1)); + assert(i1 <= i2); +#endif + // (old-offset) (new-offset) + // + offset_ = (i1 - TNT_BASE_OFFSET) + A.offset_; + dim_ = i2-i1 + 1; + } + + const_Region1D<Array1D> operator()(Subscript i1, Subscript i2) + { +#ifdef TNT_BOUNDS_CHECK + assert(TNT_BASE_OFFSET <= i1); + assert(i2 <= dim() + (TNT_BASE_OFFSET -1)); + assert(i1 <= i2); +#endif + // offset_ is 0-based, so no need for + // ( - TNT_BASE_OFFSET) + // + return const_Region1D<Array1D>(A_, i1+offset_, + offset_ + i2); + } + + + const_Region1D<Array1D> operator()(const Index1D &I) + { +#ifdef TNT_BOUNDS_CHECK + assert(TNT_BASE_OFFSET<=I.lbound()); + assert(I.ubound() <= dim() + (TNT_BASE_OFFSET-1)); + assert(I.lbound() <= I.ubound()); +#endif + return const_Region1D<Array1D>(A_, I.lbound()+offset_, + offset_ + I.ubound()); + } + + + const T & operator() (Subscript i) const + { +#ifdef TNT_BOUNDS_CHECK + assert(TNT_BASE_OFFSET <= i); + assert(i <= dim() + (TNT_BASE_OFFSET-1)); +#endif + return A_(i+offset_); + } + + + + +}; + +template <class Array1D> +std::ostream& operator<<(std::ostream &s, const_Region1D<Array1D> &A) +{ + Subscript N=A.dim(); + + for (Subscript i=1; i<=N; i++) + s << A(i) << endl; + + return s; +} + + +} // namespace TNT + +#endif +// const_Region1D_H diff --git a/intern/iksolver/intern/TNT/region2d.h b/intern/iksolver/intern/TNT/region2d.h new file mode 100644 index 00000000000..d612dfdaa79 --- /dev/null +++ b/intern/iksolver/intern/TNT/region2d.h @@ -0,0 +1,499 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + +// 2D Regions for arrays and matrices + +#ifndef REGION2D_H +#define REGION2D_H + +#include "index.h" +#include <iostream> +#include <cassert> + +namespace TNT +{ + +template <class Array2D> +class const_Region2D; + + +template <class Array2D> +class Region2D +{ + protected: + + Array2D & A_; + Subscript offset_[2]; // 0-offset internally + Subscript dim_[2]; + + public: + typedef typename Array2D::value_type T; + typedef Subscript size_type; + typedef T value_type; + typedef T element_type; + typedef T* pointer; + typedef T* iterator; + typedef T& reference; + typedef const T* const_iterator; + typedef const T& const_reference; + + Array2D & array() { return A_; } + const Array2D & array() const { return A_; } + Subscript lbound() const { return A_.lbound(); } + Subscript num_rows() const { return dim_[0]; } + Subscript num_cols() const { return dim_[1]; } + Subscript offset(Subscript i) const // 1-offset + { +#ifdef TNT_BOUNDS_CHECK + assert( A_.lbound() <= i); + assert( i<= dim_[0] + A_.lbound()-1); +#endif + return offset_[i-A_.lbound()]; + } + + Subscript dim(Subscript i) const + { +#ifdef TNT_BOUNDS_CHECK + assert( A_.lbound() <= i); + assert( i<= dim_[0] + A_.lbound()-1); +#endif + return dim_[i-A_.lbound()]; + } + + + + Region2D(Array2D &A, Subscript i1, Subscript i2, Subscript j1, + Subscript j2) : A_(A) + { +#ifdef TNT_BOUNDS_CHECK + assert( i1 <= i2 ); + assert( j1 <= j2); + assert( A.lbound() <= i1); + assert( i2<= A.dim(A.lbound()) + A.lbound()-1); + assert( A.lbound() <= j1); + assert( j2<= A.dim(A.lbound()+1) + A.lbound()-1 ); +#endif + + + offset_[0] = i1-A.lbound(); + offset_[1] = j1-A.lbound(); + dim_[0] = i2-i1+1; + dim_[1] = j2-j1+1; + } + + Region2D(Array2D &A, const Index1D &I, const Index1D &J) : A_(A) + { +#ifdef TNT_BOUNDS_CHECK + assert( I.lbound() <= I.ubound() ); + assert( J.lbound() <= J.ubound() ); + assert( A.lbound() <= I.lbound()); + assert( I.ubound()<= A.dim(A.lbound()) + A.lbound()-1); + assert( A.lbound() <= J.lbound()); + assert( J.ubound() <= A.dim(A.lbound()+1) + A.lbound()-1 ); +#endif + + offset_[0] = I.lbound()-A.lbound(); + offset_[1] = J.lbound()-A.lbound(); + dim_[0] = I.ubound() - I.lbound() + 1; + dim_[1] = J.ubound() - J.lbound() + 1; + } + + Region2D(Region2D<Array2D> &A, Subscript i1, Subscript i2, + Subscript j1, Subscript j2) : A_(A.A_) + { +#ifdef TNT_BOUNDS_CHECK + assert( i1 <= i2 ); + assert( j1 <= j2); + assert( A.lbound() <= i1); + assert( i2<= A.dim(A.lbound()) + A.lbound()-1); + assert( A.lbound() <= j1); + assert( j2<= A.dim(A.lbound()+1) + A.lbound()-1 ); +#endif + offset_[0] = (i1 - A.lbound()) + A.offset_[0]; + offset_[1] = (j1 - A.lbound()) + A.offset_[1]; + dim_[0] = i2-i1 + 1; + dim_[1] = j2-j1+1; + } + + Region2D<Array2D> operator()(Subscript i1, Subscript i2, + Subscript j1, Subscript j2) + { +#ifdef TNT_BOUNDS_CHECK + assert( i1 <= i2 ); + assert( j1 <= j2); + assert( A_.lbound() <= i1); + assert( i2<= dim_[0] + A_.lbound()-1); + assert( A_.lbound() <= j1); + assert( j2<= dim_[1] + A_.lbound()-1 ); +#endif + return Region2D<Array2D>(A_, + i1+offset_[0], offset_[0] + i2, + j1+offset_[1], offset_[1] + j2); + } + + + Region2D<Array2D> operator()(const Index1D &I, + const Index1D &J) + { +#ifdef TNT_BOUNDS_CHECK + assert( I.lbound() <= I.ubound() ); + assert( J.lbound() <= J.ubound() ); + assert( A_.lbound() <= I.lbound()); + assert( I.ubound()<= dim_[0] + A_.lbound()-1); + assert( A_.lbound() <= J.lbound()); + assert( J.ubound() <= dim_[1] + A_.lbound()-1 ); +#endif + + return Region2D<Array2D>(A_, I.lbound()+offset_[0], + offset_[0] + I.ubound(), offset_[1]+J.lbound(), + offset_[1] + J.ubound()); + } + + inline T & operator()(Subscript i, Subscript j) + { +#ifdef TNT_BOUNDS_CHECK + assert( A_.lbound() <= i); + assert( i<= dim_[0] + A_.lbound()-1); + assert( A_.lbound() <= j); + assert( j<= dim_[1] + A_.lbound()-1 ); +#endif + return A_(i+offset_[0], j+offset_[1]); + } + + inline const T & operator() (Subscript i, Subscript j) const + { +#ifdef TNT_BOUNDS_CHECK + assert( A_.lbound() <= i); + assert( i<= dim_[0] + A_.lbound()-1); + assert( A_.lbound() <= j); + assert( j<= dim_[1] + A_.lbound()-1 ); +#endif + return A_(i+offset_[0], j+offset_[1]); + } + + + Region2D<Array2D> & operator=(const Region2D<Array2D> &R) + { + Subscript M = num_rows(); + Subscript N = num_cols(); + + // make sure both sides conform + assert(M == R.num_rows()); + assert(N == R.num_cols()); + + + Subscript start = R.lbound(); + Subscript Mend = start + M - 1; + Subscript Nend = start + N - 1; + for (Subscript i=start; i<=Mend; i++) + for (Subscript j=start; j<=Nend; j++) + (*this)(i,j) = R(i,j); + + return *this; + } + + Region2D<Array2D> & operator=(const const_Region2D<Array2D> &R) + { + Subscript M = num_rows(); + Subscript N = num_cols(); + + // make sure both sides conform + assert(M == R.num_rows()); + assert(N == R.num_cols()); + + + Subscript start = R.lbound(); + Subscript Mend = start + M - 1; + Subscript Nend = start + N - 1; + for (Subscript i=start; i<=Mend; i++) + for (Subscript j=start; j<=Nend; j++) + (*this)(i,j) = R(i,j); + + return *this; + } + + Region2D<Array2D> & operator=(const Array2D &R) + { + Subscript M = num_rows(); + Subscript N = num_cols(); + + // make sure both sides conform + assert(M == R.num_rows()); + assert(N == R.num_cols()); + + + Subscript start = R.lbound(); + Subscript Mend = start + M - 1; + Subscript Nend = start + N - 1; + for (Subscript i=start; i<=Mend; i++) + for (Subscript j=start; j<=Nend; j++) + (*this)(i,j) = R(i,j); + + return *this; + } + + Region2D<Array2D> & operator=(const T &scalar) + { + Subscript start = lbound(); + Subscript Mend = lbound() + num_rows() - 1; + Subscript Nend = lbound() + num_cols() - 1; + + + for (Subscript i=start; i<=Mend; i++) + for (Subscript j=start; j<=Nend; j++) + (*this)(i,j) = scalar; + + return *this; + } + +}; + +//************************ + +template <class Array2D> +class const_Region2D +{ + protected: + + const Array2D & A_; + Subscript offset_[2]; // 0-offset internally + Subscript dim_[2]; + + public: + typedef typename Array2D::value_type T; + typedef T value_type; + typedef T element_type; + typedef const T* const_iterator; + typedef const T& const_reference; + + const Array2D & array() const { return A_; } + Subscript lbound() const { return A_.lbound(); } + Subscript num_rows() const { return dim_[0]; } + Subscript num_cols() const { return dim_[1]; } + Subscript offset(Subscript i) const // 1-offset + { +#ifdef TNT_BOUNDS_CHECK + assert( TNT_BASE_OFFSET <= i); + assert( i<= dim_[0] + TNT_BASE_OFFSET-1); +#endif + return offset_[i-TNT_BASE_OFFSET]; + } + + Subscript dim(Subscript i) const + { +#ifdef TNT_BOUNDS_CHECK + assert( TNT_BASE_OFFSET <= i); + assert( i<= dim_[0] + TNT_BASE_OFFSET-1); +#endif + return dim_[i-TNT_BASE_OFFSET]; + } + + + const_Region2D(const Array2D &A, Subscript i1, Subscript i2, + Subscript j1, Subscript j2) : A_(A) + { +#ifdef TNT_BOUNDS_CHECK + assert( i1 <= i2 ); + assert( j1 <= j2); + assert( TNT_BASE_OFFSET <= i1); + assert( i2<= A.dim(TNT_BASE_OFFSET) + TNT_BASE_OFFSET-1); + assert( TNT_BASE_OFFSET <= j1); + assert( j2<= A.dim(TNT_BASE_OFFSET+1) + TNT_BASE_OFFSET-1 ); +#endif + + offset_[0] = i1-TNT_BASE_OFFSET; + offset_[1] = j1-TNT_BASE_OFFSET; + dim_[0] = i2-i1+1; + dim_[1] = j2-j1+1; + } + + const_Region2D(const Array2D &A, const Index1D &I, const Index1D &J) + : A_(A) + { +#ifdef TNT_BOUNDS_CHECK + assert( I.lbound() <= I.ubound() ); + assert( J.lbound() <= J.ubound() ); + assert( TNT_BASE_OFFSET <= I.lbound()); + assert( I.ubound()<= A.dim(TNT_BASE_OFFSET) + TNT_BASE_OFFSET-1); + assert( TNT_BASE_OFFSET <= J.lbound()); + assert( J.ubound() <= A.dim(TNT_BASE_OFFSET+1) + TNT_BASE_OFFSET-1 ); +#endif + + offset_[0] = I.lbound()-TNT_BASE_OFFSET; + offset_[1] = J.lbound()-TNT_BASE_OFFSET; + dim_[0] = I.ubound() - I.lbound() + 1; + dim_[1] = J.ubound() - J.lbound() + 1; + } + + + const_Region2D(const_Region2D<Array2D> &A, Subscript i1, + Subscript i2, + Subscript j1, Subscript j2) : A_(A.A_) + { +#ifdef TNT_BOUNDS_CHECK + assert( i1 <= i2 ); + assert( j1 <= j2); + assert( TNT_BASE_OFFSET <= i1); + assert( i2<= A.dim(TNT_BASE_OFFSET) + TNT_BASE_OFFSET-1); + assert( TNT_BASE_OFFSET <= j1); + assert( j2<= A.dim(TNT_BASE_OFFSET+1) + TNT_BASE_OFFSET-1 ); +#endif + offset_[0] = (i1 - TNT_BASE_OFFSET) + A.offset_[0]; + offset_[1] = (j1 - TNT_BASE_OFFSET) + A.offset_[1]; + dim_[0] = i2-i1 + 1; + dim_[1] = j2-j1+1; + } + + const_Region2D<Array2D> operator()(Subscript i1, Subscript i2, + Subscript j1, Subscript j2) + { +#ifdef TNT_BOUNDS_CHECK + assert( i1 <= i2 ); + assert( j1 <= j2); + assert( TNT_BASE_OFFSET <= i1); + assert( i2<= dim_[0] + TNT_BASE_OFFSET-1); + assert( TNT_BASE_OFFSET <= j1); + assert( j2<= dim_[0] + TNT_BASE_OFFSET-1 ); +#endif + return const_Region2D<Array2D>(A_, + i1+offset_[0], offset_[0] + i2, + j1+offset_[1], offset_[1] + j2); + } + + + const_Region2D<Array2D> operator()(const Index1D &I, + const Index1D &J) + { +#ifdef TNT_BOUNDS_CHECK + assert( I.lbound() <= I.ubound() ); + assert( J.lbound() <= J.ubound() ); + assert( TNT_BASE_OFFSET <= I.lbound()); + assert( I.ubound()<= dim_[0] + TNT_BASE_OFFSET-1); + assert( TNT_BASE_OFFSET <= J.lbound()); + assert( J.ubound() <= dim_[1] + TNT_BASE_OFFSET-1 ); +#endif + + return const_Region2D<Array2D>(A_, I.lbound()+offset_[0], + offset_[0] + I.ubound(), offset_[1]+J.lbound(), + offset_[1] + J.ubound()); + } + + + inline const T & operator() (Subscript i, Subscript j) const + { +#ifdef TNT_BOUNDS_CHECK + assert( TNT_BASE_OFFSET <= i); + assert( i<= dim_[0] + TNT_BASE_OFFSET-1); + assert( TNT_BASE_OFFSET <= j); + assert( j<= dim_[1] + TNT_BASE_OFFSET-1 ); +#endif + return A_(i+offset_[0], j+offset_[1]); + } + +}; + + +// ************** std::ostream algorithms ******************************* + +template <class Array2D> +std::ostream& operator<<(std::ostream &s, const const_Region2D<Array2D> &A) +{ + Subscript start = A.lbound(); + Subscript Mend=A.lbound()+ A.num_rows() - 1; + Subscript Nend=A.lbound() + A.num_cols() - 1; + + + s << A.num_rows() << " " << A.num_cols() << "\n"; + for (Subscript i=start; i<=Mend; i++) + { + for (Subscript j=start; j<=Nend; j++) + { + s << A(i,j) << " "; + } + s << "\n"; + } + + + return s; +} + +template <class Array2D> +std::ostream& operator<<(std::ostream &s, const Region2D<Array2D> &A) +{ + Subscript start = A.lbound(); + Subscript Mend=A.lbound()+ A.num_rows() - 1; + Subscript Nend=A.lbound() + A.num_cols() - 1; + + + s << A.num_rows() << " " << A.num_cols() << "\n"; + for (Subscript i=start; i<=Mend; i++) + { + for (Subscript j=start; j<=Nend; j++) + { + s << A(i,j) << " "; + } + s << "\n"; + } + + + return s; + +} + +} // namespace TNT + +#endif +// REGION2D_H diff --git a/intern/iksolver/intern/TNT/stopwatch.h b/intern/iksolver/intern/TNT/stopwatch.h new file mode 100644 index 00000000000..6079ec6f1b1 --- /dev/null +++ b/intern/iksolver/intern/TNT/stopwatch.h @@ -0,0 +1,115 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + + +#ifndef STPWATCH_H +#define STPWATCH_H + +// for clock() and CLOCKS_PER_SEC +#include <ctime> + +namespace TNT +{ + +/* Simple stopwatch object: + + void start() : start timing + double stop() : stop timing + void reset() : set elapsed time to 0.0 + double read() : read elapsed time (in seconds) + +*/ + +inline double seconds(void) +{ + static const double secs_per_tick = 1.0 / CLOCKS_PER_SEC; + return ( (double) clock() ) * secs_per_tick; +} + + +class stopwatch { + private: + int running; + double last_time; + double total; + + public: + stopwatch() : running(0), last_time(0.0), total(0.0) {} + void reset() { running = 0; last_time = 0.0; total=0.0; } + void start() { if (!running) { last_time = seconds(); running = 1;}} + double stop() { if (running) + { + total += seconds() - last_time; + running = 0; + } + return total; + } + double read() { if (running) + { + total+= seconds() - last_time; + last_time = seconds(); + } + return total; + } + +}; + +} // namespace TNT + +#endif + + + diff --git a/intern/iksolver/intern/TNT/subscript.h b/intern/iksolver/intern/TNT/subscript.h new file mode 100644 index 00000000000..4728a79a168 --- /dev/null +++ b/intern/iksolver/intern/TNT/subscript.h @@ -0,0 +1,90 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + +#ifndef SUBSCRPT_H +#define SUBSCRPT_H + + +//--------------------------------------------------------------------- +// This definition describes the default TNT data type used for +// indexing into TNT matrices and vectors. The data type should +// be wide enough to index into large arrays. It defaults to an +// "int", but can be overriden at compile time redefining TNT_SUBSCRIPT_TYPE, +// e.g. +// +// g++ -DTNT_SUBSCRIPT_TYPE='unsigned int' ... +// +//--------------------------------------------------------------------- +// + +#ifndef TNT_SUBSCRIPT_TYPE +#define TNT_SUBSCRIPT_TYPE int +#endif + +namespace TNT +{ + typedef TNT_SUBSCRIPT_TYPE Subscript; +} + + +// () indexing in TNT means 1-offset, i.e. x(1) and A(1,1) are the +// first elements. This offset is left as a macro for future +// purposes, but should not be changed in the current release. +// +// +#define TNT_BASE_OFFSET (1) + +#endif diff --git a/intern/iksolver/intern/TNT/svd.h b/intern/iksolver/intern/TNT/svd.h new file mode 100644 index 00000000000..9be2d98bd9f --- /dev/null +++ b/intern/iksolver/intern/TNT/svd.h @@ -0,0 +1,507 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef SVD_H + +#define SVD_H + +// Compute the Single Value Decomposition of an arbitrary matrix A +// That is compute the 3 matrices U,W,V with U column orthogonal (m,n) +// ,W a diagonal matrix and V an orthogonal square matrix s.t. +// A = U.W.Vt. From this decomposition it is trivial to compute the +// inverse of A as Ainv = V.Winv.tranpose(U). +// work_space is a temporary vector used by this class to compute +// intermediate values during the computation of the SVD. This should +// be of length a.num_cols. This is not checked + +#include "tntmath.h" + +namespace TNT +{ + + +template <class MaTRiX, class VecToR > +void SVD(MaTRiX &a, VecToR &w, MaTRiX &v, VecToR &work_space) { + + int n = a.num_cols(); + int m = a.num_rows(); + + int flag,i,its,j,jj,k,l(0),nm(0); + typename MaTRiX::value_type c,f,h,x,y,z; + typename MaTRiX::value_type anorm(0),g(0),scale(0); + typename MaTRiX::value_type s(0); + + work_space.newsize(n); + + for (i=1;i<=n;i++) { + l=i+1; + work_space(i)=scale*g; + + g = (typename MaTRiX::value_type)0; + + s = (typename MaTRiX::value_type)0; + scale = (typename MaTRiX::value_type)0; + + if (i <= m) { + for (k=i;k<=m;k++) scale += TNT::abs(a(k,i)); + if (scale > (typename MaTRiX::value_type)0) { + for (k=i;k<=m;k++) { + a(k,i) /= scale; + s += a(k,i)*a(k,i); + } + f=a(i,i); + g = -TNT::sign(sqrt(s),f); + h=f*g-s; + a(i,i)=f-g; + if (i != n) { + for (j=l;j<=n;j++) { + s = (typename MaTRiX::value_type)0; + for (k=i;k<=m;k++) s += a(k,i)*a(k,j); + f=s/h; + for (k=i;k<=m;k++) a(k,j) += f*a(k,i); + } + } + for (k=i;k<=m;k++) a(k,i) *= scale; + } + } + w(i)=scale*g; + g = (typename MaTRiX::value_type)0; + s = (typename MaTRiX::value_type)0; + scale = (typename MaTRiX::value_type)0; + if (i <= m && i != n) { + for (k=l;k<=n;k++) scale += TNT::abs(a(i,k)); + if (scale > (typename MaTRiX::value_type)0) { + for (k=l;k<=n;k++) { + a(i,k) /= scale; + s += a(i,k)*a(i,k); + } + f=a(i,l); + g = -TNT::sign(sqrt(s),f); + h=f*g-s; + a(i,l)=f-g; + for (k=l;k<=n;k++) work_space(k)=a(i,k)/h; + if (i != m) { + for (j=l;j<=m;j++) { + s = (typename MaTRiX::value_type)0; + for (k=l;k<=n;k++) s += a(j,k)*a(i,k); + for (k=l;k<=n;k++) a(j,k) += s*work_space(k); + } + } + for (k=l;k<=n;k++) a(i,k) *= scale; + } + } + anorm=TNT::max(anorm,(TNT::abs(w(i))+TNT::abs(work_space(i)))); + } + for (i=n;i>=1;i--) { + if (i < n) { + if (g != (typename MaTRiX::value_type)0) { + for (j=l;j<=n;j++) + v(j,i)=(a(i,j)/a(i,l))/g; + for (j=l;j<=n;j++) { + s = (typename MaTRiX::value_type)0; + for (k=l;k<=n;k++) s += a(i,k)*v(k,j); + for (k=l;k<=n;k++) v(k,j) += s*v(k,i); + } + } + for (j=l;j<=n;j++) v(i,j)=v(j,i)= (typename MaTRiX::value_type)0; + } + v(i,i)= (typename MaTRiX::value_type)1; + g=work_space(i); + l=i; + } + for (i=n;i>=1;i--) { + l=i+1; + g=w(i); + if (i < n) { + for (j=l;j<=n;j++) a(i,j)= (typename MaTRiX::value_type)0; + } + if (g != (typename MaTRiX::value_type)0) { + g= ((typename MaTRiX::value_type)1)/g; + if (i != n) { + for (j=l;j<=n;j++) { + s = (typename MaTRiX::value_type)0; + for (k=l;k<=m;k++) s += a(k,i)*a(k,j); + f=(s/a(i,i))*g; + for (k=i;k<=m;k++) a(k,j) += f*a(k,i); + } + } + for (j=i;j<=m;j++) a(j,i) *= g; + } else { + for (j=i;j<=m;j++) a(j,i)= (typename MaTRiX::value_type)0; + } + ++a(i,i); + } + for (k=n;k>=1;k--) { + for (its=1;its<=30;its++) { + flag=1; + for (l=k;l>=1;l--) { + nm=l-1; + if (TNT::abs(work_space(l))+anorm == anorm) { + flag=0; + break; + } + if (TNT::abs(w(nm))+anorm == anorm) break; + } + if (flag) { + c= (typename MaTRiX::value_type)0; + s= (typename MaTRiX::value_type)1; + for (i=l;i<=k;i++) { + f=s*work_space(i); + if (TNT::abs(f)+anorm != anorm) { + g=w(i); + h= (typename MaTRiX::value_type)TNT::pythag(float(f),float(g)); + w(i)=h; + h= ((typename MaTRiX::value_type)1)/h; + c=g*h; + s=(-f*h); + for (j=1;j<=m;j++) { + y=a(j,nm); + z=a(j,i); + a(j,nm)=y*c+z*s; + a(j,i)=z*c-y*s; + } + } + } + } + z=w(k); + if (l == k) { + if (z < (typename MaTRiX::value_type)0) { + w(k) = -z; + for (j=1;j<=n;j++) v(j,k)=(-v(j,k)); + } + break; + } + + +#if 1 + if (its == 30) + { + TNTException an_exception; + an_exception.i = 0; + throw an_exception; + + return ; + assert(false); + } +#endif + x=w(l); + nm=k-1; + y=w(nm); + g=work_space(nm); + h=work_space(k); + f=((y-z)*(y+z)+(g-h)*(g+h))/(((typename MaTRiX::value_type)2)*h*y); + g=(typename MaTRiX::value_type)TNT::pythag(float(f), float(1)); + f=((x-z)*(x+z)+h*((y/(f+TNT::sign(g,f)))-h))/x; + c = (typename MaTRiX::value_type)1; + s = (typename MaTRiX::value_type)1; + for (j=l;j<=nm;j++) { + i=j+1; + g=work_space(i); + y=w(i); + h=s*g; + g=c*g; + z=(typename MaTRiX::value_type)TNT::pythag(float(f),float(h)); + work_space(j)=z; + c=f/z; + s=h/z; + f=x*c+g*s; + g=g*c-x*s; + h=y*s; + y=y*c; + for (jj=1;jj<=n;jj++) { + x=v(jj,j); + z=v(jj,i); + v(jj,j)=x*c+z*s; + v(jj,i)=z*c-x*s; + } + z=(typename MaTRiX::value_type)TNT::pythag(float(f),float(h)); + w(j)=z; + if (z != (typename MaTRiX::value_type)0) { + z= ((typename MaTRiX::value_type)1)/z; + c=f*z; + s=h*z; + } + f=(c*g)+(s*y); + x=(c*y)-(s*g); + for (jj=1;jj<=m;jj++) { + y=a(jj,j); + z=a(jj,i); + a(jj,j)=y*c+z*s; + a(jj,i)=z*c-y*s; + } + } + work_space(l)= (typename MaTRiX::value_type)0; + work_space(k)=f; + w(k)=x; + } + } +}; + + + +// A is replaced by the column orthogonal matrix U + + +template <class MaTRiX, class VecToR > +void SVD_a( MaTRiX &a, VecToR &w, MaTRiX &v) { + + int n = a.num_cols(); + int m = a.num_rows(); + + int flag,i,its,j,jj,k,l,nm; + typename MaTRiX::value_type anorm,c,f,g,h,s,scale,x,y,z; + + VecToR work_space; + work_space.newsize(n); + + g = scale = anorm = 0.0; + + for (i=1;i <=n;i++) { + l = i+1; + work_space(i) = scale*g; + g = s=scale=0.0; + + if (i <= m) { + for(k=i; k<=m; k++) scale += abs(a(k,i)); + + if (scale) { + for (k = i; k <=m ; k++) { + a(k,i) /= scale; + s += a(k,i)*a(k,i); + } + f = a(i,i); + g = -sign(sqrt(s),f); + h = f*g -s; + a(i,i) = f-g; + + for (j = l; j <=n; j++) { + for (s = 0.0,k =i;k<=m;k++) s += a(k,i)*a(k,j); + f = s/h; + for (k = i; k <= m; k++) a(k,j) += f*a(k,i); + } + for (k = i; k <=m;k++) a(k,i) *= scale; + } + } + + w(i) = scale*g; + g = s = scale = 0.0; + + if (i <=m && i != n) { + for (k = l; k <=n;k++) scale += abs(a(i,k)); + if (scale) { + for(k = l;k <=n;k++) { + a(i,k) /= scale; + s += a(i,k) * a(i,k); + } + + f = a(i,l); + g = -sign(sqrt(s),f); + h= f*g -s; + a(i,l) = f-g; + for(k=l;k<=n;k++) work_space(k) = a(i,k)/h; + for (j=l;j<=m;j++) { + for(s = 0.0,k=l;k<=n;k++) s+= a(j,k)*a(i,k); + for(k=l;k<=n;k++) a(j,k) += s*work_space(k); + } + for(k=l;k<=n;k++) a(i,k)*=scale; + } + } + anorm = max(anorm,(abs(w(i)) + abs(work_space(i)))); + } + for (i=n;i>=1;i--) { + if (i <n) { + if (g) { + for(j=l;j<=n;j++) v(j,i) = (a(i,j)/a(i,l))/g; + for(j=l;j<=n;j++) { + for(s=0.0,k=l;k<=n;k++) s += a(i,k)*v(k,j); + for(k=l; k<=n;k++) v(k,j) +=s*v(k,i); + } + } + for(j=l;j <=n;j++) v(i,j) = v(j,i) = 0.0; + } + v(i,i) = 1.0; + g = work_space(i); + l = i; + } + + for (i = min(m,n);i>=1;i--) { + l = i+1; + g = w(i); + for (j=l;j <=n;j++) a(i,j) = 0.0; + if (g) { + g = 1.0/g; + for (j=l;j<=n;j++) { + for (s = 0.0,k=l;k<=m;k++) s += a(k,i)*a(k,j); + f = (s/a(i,i))*g; + for (k=i;k<=m;k++) a(k,j) += f*a(k,i); + } + for (j=i;j<=m;j++) a(j,i)*=g; + } else { + for (j=i;j<=m;j++) a(j,i) = 0.0; + } + ++a(i,i); + } + + for (k=n;k>=1;k--) { + for (its=1;its<=30;its++) { + flag=1; + for(l=k;l>=1;l--) { + nm = l-1; + if (abs(work_space(l)) + anorm == anorm) { + flag = 0; + break; + } + if (abs(w(nm)) + anorm == anorm) break; + } + if (flag) { + c = 0.0; + s = 1.0; + for (i=l;i<=k;i++) { + f = s*work_space(i); + work_space(i) = c*work_space(i); + if (abs(f) +anorm == anorm) break; + g = w(i); + h = pythag(f,g); + w(i) = h; + h = 1.0/h; + c = g*h; + s = -f*h; + for (j=1;j<=m;j++) { + y= a(j,nm); + z=a(j,i); + a(j,nm) = y*c + z*s; + a(j,i) = z*c - y*s; + } + } + } + z=w(k); + if (l==k) { + if (z <0.0) { + w(k) = -z; + for (j=1;j<=n;j++) v(j,k) = -v(j,k); + } + break; + } + + if (its == 30) assert(false); + + x=w(l); + nm=k-1; + y=w(nm); + g=work_space(nm); + h=work_space(k); + + f= ((y-z)*(y+z) + (g-h)*(g+h))/(2.0*h*y); + g = pythag(f,1.0); + f= ((x-z)*(x+z) + h*((y/(f + sign(g,f)))-h))/x; + c=s=1.0; + + for (j=l;j<=nm;j++) { + i=j+1; + g = work_space(i); + y=w(i); + h=s*g; + g=c*g; + z=pythag(f,h); + work_space(j) = z; + c=f/z; + s=h/z; + f=x*c + g*s; + g= g*c - x*s; + h=y*s; + y*=c; + for(jj=1;jj<=n;jj++) { + x=v(jj,j); + z=v(jj,i); + v(jj,j) = x*c + z*s; + v(jj,i) = z*c- x*s; + } + z=pythag(f,h); + w(j)=z; + if(z) { + z = 1.0/z; + c=f*z; + s=h*z; + } + f=c*g + s*y; + x= c*y-s*g; + + for(jj=1;jj<=m;jj++) { + y=a(jj,j); + z=a(jj,i); + a(jj,j) = y*c+z*s; + a(jj,i) = z*c - y*s; + } + } + + work_space(l) = 0.0; + work_space(k) = f; + w(k) = x; + } + } +} +} +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/intern/iksolver/intern/TNT/tnt.h b/intern/iksolver/intern/TNT/tnt.h new file mode 100644 index 00000000000..df27079f87a --- /dev/null +++ b/intern/iksolver/intern/TNT/tnt.h @@ -0,0 +1,127 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + +#ifndef TNT_H +#define TNT_H + +//--------------------------------------------------------------------- +// tnt.h TNT general header file. Defines default types +// and conventions. +//--------------------------------------------------------------------- + +//--------------------------------------------------------------------- +// Include current version +//--------------------------------------------------------------------- +#include "version.h" + +//--------------------------------------------------------------------- +// Define the data type used for matrix and vector Subscripts. +// This will default to "int", but it can be overriden at compile time, +// e.g. +// +// g++ -DTNT_SUBSCRIPT_TYPE='unsinged long' ... +// +// See subscript.h for details. +//--------------------------------------------------------------------- + +#include "subscript.h" + + + +//--------------------------------------------------------------------- +// Define this macro if you want TNT to ensure all refernces +// are within the bounds of the array. This encurs a run-time +// overhead, of course, but is recommended while developing +// code. It can be turned off for production runs. +// +// #define TNT_BOUNDS_CHECK +//--------------------------------------------------------------------- +// +#define TNT_BOUNDS_CHECK +#ifdef TNT_NO_BOUNDS_CHECK +#undef TNT_BOUNDS_CHECK +#endif + +//--------------------------------------------------------------------- +// Define this macro if you want to utilize matrix and vector +// regions. This is typically on, but you can save some +// compilation time by turning it off. If you do this and +// attempt to use regions you will get an error message. +// +// #define TNT_USE_REGIONS +//--------------------------------------------------------------------- +// +#define TNT_USE_REGIONS + +//--------------------------------------------------------------------- +// +//--------------------------------------------------------------------- +// if your system doesn't have abs() min(), and max() uncoment the following +//--------------------------------------------------------------------- +// +// +//#define __NEED_ABS_MIN_MAX_ + +#include "tntmath.h" + + + + + + + +#endif +// TNT_H diff --git a/intern/iksolver/intern/TNT/tntmath.h b/intern/iksolver/intern/TNT/tntmath.h new file mode 100644 index 00000000000..3342ff7f5c6 --- /dev/null +++ b/intern/iksolver/intern/TNT/tntmath.h @@ -0,0 +1,177 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + + +// Header file for scalar math functions + +#ifndef TNTMATH_H +#define TNTMATH_H + +// conventional functions required by several matrix algorithms + + + +namespace TNT +{ + +struct TNTException { + int i; +}; + + +inline double abs(double t) +{ + return ( t > 0 ? t : -t); +} + +inline double min(double a, double b) +{ + return (a < b ? a : b); +} + +inline double max(double a, double b) +{ + return (a > b ? a : b); +} + +inline float abs(float t) +{ + return ( t > 0 ? t : -t); +} + +inline float min(float a, float b) +{ + return (a < b ? a : b); +} + +inline int min(int a,int b) { + return (a < b ? a : b); +} + + +inline float max(float a, float b) +{ + return (a > b ? a : b); +} + +inline double sign(double a) +{ + return (a > 0 ? 1.0 : -1.0); +} + +inline double sign(double a,double b) { + return (b >= 0.0 ? TNT::abs(a) : -TNT::abs(a)); +} + +inline float sign(float a,float b) { + return (b >= 0.0f ? TNT::abs(a) : -TNT::abs(a)); +} + +inline float sign(float a) +{ + return (a > 0.0 ? 1.0f : -1.0f); +} + +inline float pythag(float a, float b) +{ + float absa,absb; + absa = abs(a); + absb = abs(b); + + if (absa > absb) { + float sqr = absb/absa; + sqr *= sqr; + return absa * float(sqrt(1 + sqr)); + } else { + if (absb > float(0)) { + float sqr = absa/absb; + sqr *= sqr; + return absb * float(sqrt(1 + sqr)); + } else { + return float(0); + } + } +} + +inline double pythag(double a, double b) +{ + double absa,absb; + absa = abs(a); + absb = abs(b); + + if (absa > absb) { + double sqr = absb/absa; + sqr *= sqr; + return absa * double(sqrt(1 + sqr)); + } else { + + if (absb > double(0)) { + double sqr = absa/absb; + sqr *= sqr; + return absb * double(sqrt(1 + sqr)); + } else { + return double(0); + } + } +} + + +} /* namespace TNT */ + + +#endif +/* TNTMATH_H */ + diff --git a/intern/iksolver/intern/TNT/tntreqs.h b/intern/iksolver/intern/TNT/tntreqs.h new file mode 100644 index 00000000000..c935902554e --- /dev/null +++ b/intern/iksolver/intern/TNT/tntreqs.h @@ -0,0 +1,102 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + + +// The requirements for a bare-bones vector class: +// +// +// o) must have 0-based [] indexing for const and +// non-const objects (i.e. operator[] defined) +// +// o) must have size() method to denote the number of +// elements +// o) must clean up after itself when destructed +// (i.e. no memory leaks) +// +// -) must have begin() and end() methods (The begin() +// method is necessary, because relying on +// &v_[0] may not work on a empty vector (i.e. v_ is NULL.) +// +// o) must be templated +// o) must have X::value_type defined to be the types of elements +// o) must have X::X(const &x) copy constructor (by *value*) +// o) must have X::X(int N) constructor to N-length vector +// (NOTE: this constructor need *NOT* initalize elements) +// +// -) must have X::X(int N, T scalar) constructor to initalize +// elements to value of "scalar". +// +// ( removed, because valarray<> class uses (scalar, N) rather +// than (N, scalar) ) +// -) must have X::X(int N, const T* scalars) constructor to copy from +// any C linear array +// +// ( removed, because of same reverse order of valarray<> ) +// +// o) must have assignment A=B, by value +// +// NOTE: this class is *NOT* meant to be derived from, +// so its methods (particularly indexing) need not be +// declared virtual. +// +// +// Some things it *DOES NOT* need to do are +// +// o) bounds checking +// o) array referencing (e.g. reference counting) +// o) support () indexing +// o) I/O +// diff --git a/intern/iksolver/intern/TNT/transv.h b/intern/iksolver/intern/TNT/transv.h new file mode 100644 index 00000000000..47730350acc --- /dev/null +++ b/intern/iksolver/intern/TNT/transv.h @@ -0,0 +1,192 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + + +// Matrix Transpose Views + +#ifndef TRANSV_H +#define TRANSV_H + +#include <iostream> +#include <cassert> +#include "vec.h" + +namespace TNT +{ + +template <class Array2D> +class Transpose_View +{ + protected: + + const Array2D & A_; + + public: + + typedef typename Array2D::element_type T; + typedef T value_type; + typedef T element_type; + typedef T* pointer; + typedef T* iterator; + typedef T& reference; + typedef const T* const_iterator; + typedef const T& const_reference; + + + const Array2D & array() const { return A_; } + Subscript num_rows() const { return A_.num_cols();} + Subscript num_cols() const { return A_.num_rows();} + Subscript lbound() const { return A_.lbound(); } + Subscript dim(Subscript i) const + { +#ifdef TNT_BOUNDS_CHECK + assert( A_.lbound() <= i); + assert( i<= A_.lbound()+1); +#endif + if (i== A_.lbound()) + return num_rows(); + else + return num_cols(); + } + + + Transpose_View(const Transpose_View<Array2D> &A) : A_(A.A_) {}; + Transpose_View(const Array2D &A) : A_(A) {}; + + + inline const typename Array2D::element_type & operator()( + Subscript i, Subscript j) const + { +#ifdef TNT_BOUNDS_CHECK + assert(lbound()<=i); + assert(i<=A_.num_cols() + lbound() - 1); + assert(lbound()<=j); + assert(j<=A_.num_rows() + lbound() - 1); +#endif + + return A_(j,i); + } + + +}; + +template <class Matrix> +Transpose_View<Matrix> Transpose_view(const Matrix &A) +{ + return Transpose_View<Matrix>(A); +} + +template <class Matrix, class T> +Vector<T> matmult( + const Transpose_View<Matrix> & A, + const Vector<T> &B) +{ + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + assert(B.dim() == N); + + Vector<T> x(N); + + Subscript i, j; + T tmp = 0; + + for (i=1; i<=M; i++) + { + tmp = 0; + for (j=1; j<=N; j++) + tmp += A(i,j) * B(j); + x(i) = tmp; + } + + return x; +} + +template <class Matrix, class T> +inline Vector<T> operator*(const Transpose_View<Matrix> & A, const Vector<T> &B) +{ + return matmult(A,B); +} + + +template <class Matrix> +std::ostream& operator<<(std::ostream &s, const Transpose_View<Matrix> &A) +{ + Subscript M=A.num_rows(); + Subscript N=A.num_cols(); + + Subscript start = A.lbound(); + Subscript Mend = M + A.lbound() - 1; + Subscript Nend = N + A.lbound() - 1; + + s << M << " " << N << endl; + for (Subscript i=start; i<=Mend; i++) + { + for (Subscript j=start; j<=Nend; j++) + { + s << A(i,j) << " "; + } + s << endl; + } + + + return s; +} + +} // namespace TNT + +#endif +// TRANSV_H diff --git a/intern/iksolver/intern/TNT/triang.h b/intern/iksolver/intern/TNT/triang.h new file mode 100644 index 00000000000..883caf138f7 --- /dev/null +++ b/intern/iksolver/intern/TNT/triang.h @@ -0,0 +1,670 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + + +// Triangular Matrices (Views and Adpators) + +#ifndef TRIANG_H +#define TRIANG_H + +// default to use lower-triangular portions of arrays +// for symmetric matrices. + +namespace TNT +{ + +template <class MaTRiX> +class LowerTriangularView +{ + protected: + + + const MaTRiX &A_; + const typename MaTRiX::element_type zero_; + + public: + + + typedef typename MaTRiX::const_reference const_reference; + typedef const typename MaTRiX::element_type element_type; + typedef const typename MaTRiX::element_type value_type; + typedef element_type T; + + Subscript dim(Subscript d) const { return A_.dim(d); } + Subscript lbound() const { return A_.lbound(); } + Subscript num_rows() const { return A_.num_rows(); } + Subscript num_cols() const { return A_.num_cols(); } + + + // constructors + + LowerTriangularView(/*const*/ MaTRiX &A) : A_(A), zero_(0) {} + + + inline const_reference get(Subscript i, Subscript j) const + { +#ifdef TNT_BOUNDS_CHECK + assert(lbound()<=i); + assert(i<=A_.num_rows() + lbound() - 1); + assert(lbound()<=j); + assert(j<=A_.num_cols() + lbound() - 1); +#endif + if (i<j) + return zero_; + else + return A_(i,j); + } + + + inline const_reference operator() (Subscript i, Subscript j) const + { +#ifdef TNT_BOUNDS_CHECK + assert(lbound()<=i); + assert(i<=A_.num_rows() + lbound() - 1); + assert(lbound()<=j); + assert(j<=A_.num_cols() + lbound() - 1); +#endif + if (i<j) + return zero_; + else + return A_(i,j); + } + +#ifdef TNT_USE_REGIONS + + typedef const_Region2D< LowerTriangularView<MaTRiX> > + const_Region; + + const_Region operator()(/*const*/ Index1D &I, + /*const*/ Index1D &J) const + { + return const_Region(*this, I, J); + } + + const_Region operator()(Subscript i1, Subscript i2, + Subscript j1, Subscript j2) const + { + return const_Region(*this, i1, i2, j1, j2); + } + + + +#endif +// TNT_USE_REGIONS + +}; + + +/* *********** Lower_triangular_view() algorithms ****************** */ + +template <class MaTRiX, class VecToR> +VecToR matmult(/*const*/ LowerTriangularView<MaTRiX> &A, VecToR &x) +{ + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + assert(N == x.dim()); + + Subscript i, j; + typename MaTRiX::element_type sum=0.0; + VecToR result(M); + + Subscript start = A.lbound(); + Subscript Mend = M + A.lbound() -1 ; + + for (i=start; i<=Mend; i++) + { + sum = 0.0; + for (j=start; j<=i; j++) + sum = sum + A(i,j)*x(j); + result(i) = sum; + } + + return result; +} + +template <class MaTRiX, class VecToR> +inline VecToR operator*(/*const*/ LowerTriangularView<MaTRiX> &A, VecToR &x) +{ + return matmult(A,x); +} + +template <class MaTRiX> +class UnitLowerTriangularView +{ + protected: + + const MaTRiX &A_; + const typename MaTRiX::element_type zero; + const typename MaTRiX::element_type one; + + public: + + typedef typename MaTRiX::const_reference const_reference; + typedef typename MaTRiX::element_type element_type; + typedef typename MaTRiX::element_type value_type; + typedef element_type T; + + Subscript lbound() const { return 1; } + Subscript dim(Subscript d) const { return A_.dim(d); } + Subscript num_rows() const { return A_.num_rows(); } + Subscript num_cols() const { return A_.num_cols(); } + + + // constructors + + UnitLowerTriangularView(/*const*/ MaTRiX &A) : A_(A), zero(0), one(1) {} + + + inline const_reference get(Subscript i, Subscript j) const + { +#ifdef TNT_BOUNDS_CHECK + assert(1<=i); + assert(i<=A_.dim(1)); + assert(1<=j); + assert(j<=A_.dim(2)); + assert(0<=i && i<A_.dim(0) && 0<=j && j<A_.dim(1)); +#endif + if (i>j) + return A_(i,j); + else if (i==j) + return one; + else + return zero; + } + + + inline const_reference operator() (Subscript i, Subscript j) const + { +#ifdef TNT_BOUNDS_CHECK + assert(1<=i); + assert(i<=A_.dim(1)); + assert(1<=j); + assert(j<=A_.dim(2)); +#endif + if (i>j) + return A_(i,j); + else if (i==j) + return one; + else + return zero; + } + + +#ifdef TNT_USE_REGIONS + // These are the "index-aware" features + + typedef const_Region2D< UnitLowerTriangularView<MaTRiX> > + const_Region; + + const_Region operator()(/*const*/ Index1D &I, + /*const*/ Index1D &J) const + { + return const_Region(*this, I, J); + } + + const_Region operator()(Subscript i1, Subscript i2, + Subscript j1, Subscript j2) const + { + return const_Region(*this, i1, i2, j1, j2); + } +#endif +// TNT_USE_REGIONS +}; + +template <class MaTRiX> +LowerTriangularView<MaTRiX> Lower_triangular_view( + /*const*/ MaTRiX &A) +{ + return LowerTriangularView<MaTRiX>(A); +} + + +template <class MaTRiX> +UnitLowerTriangularView<MaTRiX> Unit_lower_triangular_view( + /*const*/ MaTRiX &A) +{ + return UnitLowerTriangularView<MaTRiX>(A); +} + +template <class MaTRiX, class VecToR> +VecToR matmult(/*const*/ UnitLowerTriangularView<MaTRiX> &A, VecToR &x) +{ + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + assert(N == x.dim()); + + Subscript i, j; + typename MaTRiX::element_type sum=0.0; + VecToR result(M); + + Subscript start = A.lbound(); + Subscript Mend = M + A.lbound() -1 ; + + for (i=start; i<=Mend; i++) + { + sum = 0.0; + for (j=start; j<i; j++) + sum = sum + A(i,j)*x(j); + result(i) = sum + x(i); + } + + return result; +} + +template <class MaTRiX, class VecToR> +inline VecToR operator*(/*const*/ UnitLowerTriangularView<MaTRiX> &A, VecToR &x) +{ + return matmult(A,x); +} + + +//********************** Algorithms ************************************* + + + +template <class MaTRiX> +std::ostream& operator<<(std::ostream &s, const LowerTriangularView<MaTRiX>&A) +{ + Subscript M=A.num_rows(); + Subscript N=A.num_cols(); + + s << M << " " << N << endl; + + for (Subscript i=1; i<=M; i++) + { + for (Subscript j=1; j<=N; j++) + { + s << A(i,j) << " "; + } + s << endl; + } + + + return s; +} + +template <class MaTRiX> +std::ostream& operator<<(std::ostream &s, + const UnitLowerTriangularView<MaTRiX>&A) +{ + Subscript M=A.num_rows(); + Subscript N=A.num_cols(); + + s << M << " " << N << endl; + + for (Subscript i=1; i<=M; i++) + { + for (Subscript j=1; j<=N; j++) + { + s << A(i,j) << " "; + } + s << endl; + } + + + return s; +} + + + +// ******************* Upper Triangular Section ************************** + +template <class MaTRiX> +class UpperTriangularView +{ + protected: + + + /*const*/ MaTRiX &A_; + /*const*/ typename MaTRiX::element_type zero_; + + public: + + + typedef typename MaTRiX::const_reference const_reference; + typedef /*const*/ typename MaTRiX::element_type element_type; + typedef /*const*/ typename MaTRiX::element_type value_type; + typedef element_type T; + + Subscript dim(Subscript d) const { return A_.dim(d); } + Subscript lbound() const { return A_.lbound(); } + Subscript num_rows() const { return A_.num_rows(); } + Subscript num_cols() const { return A_.num_cols(); } + + + // constructors + + UpperTriangularView(/*const*/ MaTRiX &A) : A_(A), zero_(0) {} + + + inline const_reference get(Subscript i, Subscript j) const + { +#ifdef TNT_BOUNDS_CHECK + assert(lbound()<=i); + assert(i<=A_.num_rows() + lbound() - 1); + assert(lbound()<=j); + assert(j<=A_.num_cols() + lbound() - 1); +#endif + if (i>j) + return zero_; + else + return A_(i,j); + } + + + inline const_reference operator() (Subscript i, Subscript j) const + { +#ifdef TNT_BOUNDS_CHECK + assert(lbound()<=i); + assert(i<=A_.num_rows() + lbound() - 1); + assert(lbound()<=j); + assert(j<=A_.num_cols() + lbound() - 1); +#endif + if (i>j) + return zero_; + else + return A_(i,j); + } + +#ifdef TNT_USE_REGIONS + + typedef const_Region2D< UpperTriangularView<MaTRiX> > + const_Region; + + const_Region operator()(const Index1D &I, + const Index1D &J) const + { + return const_Region(*this, I, J); + } + + const_Region operator()(Subscript i1, Subscript i2, + Subscript j1, Subscript j2) const + { + return const_Region(*this, i1, i2, j1, j2); + } + + + +#endif +// TNT_USE_REGIONS + +}; + + +/* *********** Upper_triangular_view() algorithms ****************** */ + +template <class MaTRiX, class VecToR> +VecToR matmult(/*const*/ UpperTriangularView<MaTRiX> &A, VecToR &x) +{ + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + assert(N == x.dim()); + + Subscript i, j; + typename VecToR::element_type sum=0.0; + VecToR result(M); + + Subscript start = A.lbound(); + Subscript Mend = M + A.lbound() -1 ; + + for (i=start; i<=Mend; i++) + { + sum = 0.0; + for (j=i; j<=N; j++) + sum = sum + A(i,j)*x(j); + result(i) = sum; + } + + return result; +} + +template <class MaTRiX, class VecToR> +inline VecToR operator*(/*const*/ UpperTriangularView<MaTRiX> &A, VecToR &x) +{ + return matmult(A,x); +} + +template <class MaTRiX> +class UnitUpperTriangularView +{ + protected: + + const MaTRiX &A_; + const typename MaTRiX::element_type zero; + const typename MaTRiX::element_type one; + + public: + + typedef typename MaTRiX::const_reference const_reference; + typedef typename MaTRiX::element_type element_type; + typedef typename MaTRiX::element_type value_type; + typedef element_type T; + + Subscript lbound() const { return 1; } + Subscript dim(Subscript d) const { return A_.dim(d); } + Subscript num_rows() const { return A_.num_rows(); } + Subscript num_cols() const { return A_.num_cols(); } + + + // constructors + + UnitUpperTriangularView(/*const*/ MaTRiX &A) : A_(A), zero(0), one(1) {} + + + inline const_reference get(Subscript i, Subscript j) const + { +#ifdef TNT_BOUNDS_CHECK + assert(1<=i); + assert(i<=A_.dim(1)); + assert(1<=j); + assert(j<=A_.dim(2)); + assert(0<=i && i<A_.dim(0) && 0<=j && j<A_.dim(1)); +#endif + if (i<j) + return A_(i,j); + else if (i==j) + return one; + else + return zero; + } + + + inline const_reference operator() (Subscript i, Subscript j) const + { +#ifdef TNT_BOUNDS_CHECK + assert(1<=i); + assert(i<=A_.dim(1)); + assert(1<=j); + assert(j<=A_.dim(2)); +#endif + if (i<j) + return A_(i,j); + else if (i==j) + return one; + else + return zero; + } + + +#ifdef TNT_USE_REGIONS + // These are the "index-aware" features + + typedef const_Region2D< UnitUpperTriangularView<MaTRiX> > + const_Region; + + const_Region operator()(const Index1D &I, + const Index1D &J) const + { + return const_Region(*this, I, J); + } + + const_Region operator()(Subscript i1, Subscript i2, + Subscript j1, Subscript j2) const + { + return const_Region(*this, i1, i2, j1, j2); + } +#endif +// TNT_USE_REGIONS +}; + +template <class MaTRiX> +UpperTriangularView<MaTRiX> Upper_triangular_view( + /*const*/ MaTRiX &A) +{ + return UpperTriangularView<MaTRiX>(A); +} + + +template <class MaTRiX> +UnitUpperTriangularView<MaTRiX> Unit_upper_triangular_view( + /*const*/ MaTRiX &A) +{ + return UnitUpperTriangularView<MaTRiX>(A); +} + +template <class MaTRiX, class VecToR> +VecToR matmult(/*const*/ UnitUpperTriangularView<MaTRiX> &A, VecToR &x) +{ + Subscript M = A.num_rows(); + Subscript N = A.num_cols(); + + assert(N == x.dim()); + + Subscript i, j; + typename VecToR::element_type sum=0.0; + VecToR result(M); + + Subscript start = A.lbound(); + Subscript Mend = M + A.lbound() -1 ; + + for (i=start; i<=Mend; i++) + { + sum = x(i); + for (j=i+1; j<=N; j++) + sum = sum + A(i,j)*x(j); + result(i) = sum + x(i); + } + + return result; +} + +template <class MaTRiX, class VecToR> +inline VecToR operator*(/*const*/ UnitUpperTriangularView<MaTRiX> &A, VecToR &x) +{ + return matmult(A,x); +} + + +//********************** Algorithms ************************************* + + + +template <class MaTRiX> +std::ostream& operator<<(std::ostream &s, + /*const*/ UpperTriangularView<MaTRiX>&A) +{ + Subscript M=A.num_rows(); + Subscript N=A.num_cols(); + + s << M << " " << N << endl; + + for (Subscript i=1; i<=M; i++) + { + for (Subscript j=1; j<=N; j++) + { + s << A(i,j) << " "; + } + s << endl; + } + + + return s; +} + +template <class MaTRiX> +std::ostream& operator<<(std::ostream &s, + /*const*/ UnitUpperTriangularView<MaTRiX>&A) +{ + Subscript M=A.num_rows(); + Subscript N=A.num_cols(); + + s << M << " " << N << endl; + + for (Subscript i=1; i<=M; i++) + { + for (Subscript j=1; j<=N; j++) + { + s << A(i,j) << " "; + } + s << endl; + } + + + return s; +} + +} // namespace TNT + + + + + +#endif +//TRIANG_H + diff --git a/intern/iksolver/intern/TNT/trisolve.h b/intern/iksolver/intern/TNT/trisolve.h new file mode 100644 index 00000000000..6a4f6e1a5b3 --- /dev/null +++ b/intern/iksolver/intern/TNT/trisolve.h @@ -0,0 +1,216 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + + +// Triangular Solves + +#ifndef TRISLV_H +#define TRISLV_H + + +#include "triang.h" + +namespace TNT +{ + +template <class MaTriX, class VecToR> +VecToR Lower_triangular_solve(/*const*/ MaTriX &A, /*const*/ VecToR &b) +{ + Subscript N = A.num_rows(); + + // make sure matrix sizes agree; A must be square + + assert(A.num_cols() == N); + assert(b.dim() == N); + + VecToR x(N); + + Subscript i; + for (i=1; i<=N; i++) + { + typename MaTriX::element_type tmp=0; + + for (Subscript j=1; j<i; j++) + tmp = tmp + A(i,j)*x(j); + + x(i) = (b(i) - tmp)/ A(i,i); + } + + return x; +} + + +template <class MaTriX, class VecToR> +VecToR Unit_lower_triangular_solve(/*const*/ MaTriX &A, /*const*/ VecToR &b) +{ + Subscript N = A.num_rows(); + + // make sure matrix sizes agree; A must be square + + assert(A.num_cols() == N); + assert(b.dim() == N); + + VecToR x(N); + + Subscript i; + for (i=1; i<=N; i++) + { + + typename MaTriX::element_type tmp=0; + + for (Subscript j=1; j<i; j++) + tmp = tmp + A(i,j)*x(j); + + x(i) = b(i) - tmp; + } + + return x; +} + + +template <class MaTriX, class VecToR> +VecToR linear_solve(/*const*/ LowerTriangularView<MaTriX> &A, + /*const*/ VecToR &b) +{ + return Lower_triangular_solve(A, b); +} + +template <class MaTriX, class VecToR> +VecToR linear_solve(/*const*/ UnitLowerTriangularView<MaTriX> &A, + /*const*/ VecToR &b) +{ + return Unit_lower_triangular_solve(A, b); +} + + + +//********************** Upper triangular section **************** + +template <class MaTriX, class VecToR> +VecToR Upper_triangular_solve(/*const*/ MaTriX &A, /*const*/ VecToR &b) +{ + Subscript N = A.num_rows(); + + // make sure matrix sizes agree; A must be square + + assert(A.num_cols() == N); + assert(b.dim() == N); + + VecToR x(N); + + Subscript i; + for (i=N; i>=1; i--) + { + + typename MaTriX::element_type tmp=0; + + for (Subscript j=i+1; j<=N; j++) + tmp = tmp + A(i,j)*x(j); + + x(i) = (b(i) - tmp)/ A(i,i); + } + + return x; +} + + +template <class MaTriX, class VecToR> +VecToR Unit_upper_triangular_solve(/*const*/ MaTriX &A, /*const*/ VecToR &b) +{ + Subscript N = A.num_rows(); + + // make sure matrix sizes agree; A must be square + + assert(A.num_cols() == N); + assert(b.dim() == N); + + VecToR x(N); + + Subscript i; + for (i=N; i>=1; i--) + { + + typename MaTriX::element_type tmp=0; + + for (Subscript j=i+1; j<i; j++) + tmp = tmp + A(i,j)*x(j); + + x(i) = b(i) - tmp; + } + + return x; +} + + +template <class MaTriX, class VecToR> +VecToR linear_solve(/*const*/ UpperTriangularView<MaTriX> &A, + /*const*/ VecToR &b) +{ + return Upper_triangular_solve(A, b); +} + +template <class MaTriX, class VecToR> +VecToR linear_solve(/*const*/ UnitUpperTriangularView<MaTriX> &A, + /*const*/ VecToR &b) +{ + return Unit_upper_triangular_solve(A, b); +} + + +} // namespace TNT + +#endif +// TRISLV_H diff --git a/intern/iksolver/intern/TNT/vec.h b/intern/iksolver/intern/TNT/vec.h new file mode 100644 index 00000000000..beb034ce315 --- /dev/null +++ b/intern/iksolver/intern/TNT/vec.h @@ -0,0 +1,535 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + +// Basic TNT numerical vector (0-based [i] AND 1-based (i) indexing ) +// + +#ifndef VEC_H +#define VEC_H + +#include "subscript.h" +#include <stdlib.h> +#include <assert.h> +#include <iostream> +#include <strstream> + +namespace TNT +{ + +template <class T> +class Vector +{ + + + public: + + typedef Subscript size_type; + typedef T value_type; + typedef T element_type; + typedef T* pointer; + typedef T* iterator; + typedef T& reference; + typedef const T* const_iterator; + typedef const T& const_reference; + + Subscript lbound() const { return 1;} + + protected: + T* v_; + T* vm1_; // pointer adjustment for optimzied 1-offset indexing + Subscript n_; + + // internal helper function to create the array + // of row pointers + + void initialize(Subscript N) + { + // adjust pointers so that they are 1-offset: + // v_[] is the internal contiguous array, it is still 0-offset + // + assert(v_ == NULL); + v_ = new T[N]; + assert(v_ != NULL); + vm1_ = v_-1; + n_ = N; + } + + void copy(const T* v) + { + Subscript N = n_; + Subscript i; + +#ifdef TNT_UNROLL_LOOPS + Subscript Nmod4 = N & 3; + Subscript N4 = N - Nmod4; + + for (i=0; i<N4; i+=4) + { + v_[i] = v[i]; + v_[i+1] = v[i+1]; + v_[i+2] = v[i+2]; + v_[i+3] = v[i+3]; + } + + for (i=N4; i< N; i++) + v_[i] = v[i]; +#else + + for (i=0; i< N; i++) + v_[i] = v[i]; +#endif + } + + void set(const T& val) + { + Subscript N = n_; + Subscript i; + +#ifdef TNT_UNROLL_LOOPS + Subscript Nmod4 = N & 3; + Subscript N4 = N - Nmod4; + + for (i=0; i<N4; i+=4) + { + v_[i] = val; + v_[i+1] = val; + v_[i+2] = val; + v_[i+3] = val; + } + + for (i=N4; i< N; i++) + v_[i] = val; +#else + + for (i=0; i< N; i++) + v_[i] = val; + +#endif + } + + + + void destroy() + { + /* do nothing, if no memory has been previously allocated */ + if (v_ == NULL) return ; + + /* if we are here, then matrix was previously allocated */ + delete [] (v_); + + v_ = NULL; + vm1_ = NULL; + } + + + public: + + // access + + iterator begin() { return v_;} + iterator end() { return v_ + n_; } + const iterator begin() const { return v_;} + const iterator end() const { return v_ + n_; } + + // destructor + + ~Vector() + { + destroy(); + } + + // constructors + + Vector() : v_(0), vm1_(0), n_(0) {}; + + Vector(const Vector<T> &A) : v_(0), vm1_(0), n_(0) + { + initialize(A.n_); + copy(A.v_); + } + + Vector(Subscript N, const T& value = T()) : v_(0), vm1_(0), n_(0) + { + initialize(N); + set(value); + } + + Vector(Subscript N, const T* v) : v_(0), vm1_(0), n_(0) + { + initialize(N); + copy(v); + } + + Vector(Subscript N, char *s) : v_(0), vm1_(0), n_(0) + { + initialize(N); + std::istrstream ins(s); + + Subscript i; + + for (i=0; i<N; i++) + ins >> v_[i]; + } + + + // methods + // + Vector<T>& newsize(Subscript N) + { + if (n_ == N) return *this; + + destroy(); + initialize(N); + + return *this; + } + + + // assignments + // + Vector<T>& operator=(const Vector<T> &A) + { + if (v_ == A.v_) + return *this; + + if (n_ == A.n_) // no need to re-alloc + copy(A.v_); + + else + { + destroy(); + initialize(A.n_); + copy(A.v_); + } + + return *this; + } + + Vector<T>& operator=(const T& scalar) + { + set(scalar); + return *this; + } + + inline Subscript dim() const + { + return n_; + } + + inline Subscript size() const + { + return n_; + } + + + inline reference operator()(Subscript i) + { +#ifdef TNT_BOUNDS_CHECK + assert(1<=i); + assert(i <= n_) ; +#endif + return vm1_[i]; + } + + inline const_reference operator() (Subscript i) const + { +#ifdef TNT_BOUNDS_CHECK + assert(1<=i); + assert(i <= n_) ; +#endif + return vm1_[i]; + } + + inline reference operator[](Subscript i) + { +#ifdef TNT_BOUNDS_CHECK + assert(0<=i); + assert(i < n_) ; +#endif + return v_[i]; + } + + inline const_reference operator[](Subscript i) const + { +#ifdef TNT_BOUNDS_CHECK + assert(0<=i) ; + assert(i < n_) ; +#endif + return v_[i]; + } + + + +}; + + +/* *************************** I/O ********************************/ + +template <class T> +std::ostream& operator<<(std::ostream &s, const Vector<T> &A) +{ + Subscript N=A.dim(); + + s << N << endl; + + for (Subscript i=0; i<N; i++) + s << A[i] << " " << endl; + s << endl; + + return s; +} + +template <class T> +std::istream & operator>>(std::istream &s, Vector<T> &A) +{ + + Subscript N; + + s >> N; + + if ( !(N == A.size() )) + { + A.newsize(N); + } + + + for (Subscript i=0; i<N; i++) + s >> A[i]; + + + return s; +} + +// *******************[ basic matrix algorithms ]*************************** + + +template <class T> +Vector<T> operator+(const Vector<T> &A, + const Vector<T> &B) +{ + Subscript N = A.dim(); + + assert(N==B.dim()); + + Vector<T> tmp(N); + Subscript i; + + for (i=0; i<N; i++) + tmp[i] = A[i] + B[i]; + + return tmp; +} + +template <class T> +Vector<T> operator-(const Vector<T> &A, + const Vector<T> &B) +{ + Subscript N = A.dim(); + + assert(N==B.dim()); + + Vector<T> tmp(N); + Subscript i; + + for (i=0; i<N; i++) + tmp[i] = A[i] - B[i]; + + return tmp; +} + +template <class T> +Vector<T> operator*(const Vector<T> &A, + const Vector<T> &B) +{ + Subscript N = A.dim(); + + assert(N==B.dim()); + + Vector<T> tmp(N); + Subscript i; + + for (i=0; i<N; i++) + tmp[i] = A[i] * B[i]; + + return tmp; +} + +template <class T> +Vector<T> operator*(const Vector<T> &A, + const T &B) +{ + Subscript N = A.dim(); + + Vector<T> tmp(N); + Subscript i; + + for (i=0; i<N; i++) + tmp[i] = A[i] * B; + + return tmp; +} + + +template <class T> +T dot_prod(const Vector<T> &A, const Vector<T> &B) +{ + Subscript N = A.dim(); + assert(N == B.dim()); + + Subscript i; + T sum = 0; + + for (i=0; i<N; i++) + sum += A[i] * B[i]; + + return sum; +} + +// inplace versions of the above template functions + +// A = A + B + +template <class T> +void vectoradd( + Vector<T> &A, + const Vector<T> &B) +{ + const Subscript N = A.dim(); + assert(N==B.dim()); + Subscript i; + + for (i=0; i<N; i++) + A[i] += B[i]; +} + +// same with seperate output vector + +template <class T> +void vectoradd( + Vector<T> &C, + const Vector<T> &A, + const Vector<T> &B) +{ + const Subscript N = A.dim(); + assert(N==B.dim()); + Subscript i; + + for (i=0; i<N; i++) + C[i] = A[i] + B[i]; +} + +// A = A - B + +template <class T> +void vectorsub( + Vector<T> &A, + const Vector<T> &B) +{ + const Subscript N = A.dim(); + assert(N==B.dim()); + Subscript i; + + for (i=0; i<N; i++) + A[i] -= B[i]; +} + +template <class T> +void vectorsub( + Vector<T> &C, + const Vector<T> &A, + const Vector<T> &B) +{ + const Subscript N = A.dim(); + assert(N==B.dim()); + Subscript i; + + for (i=0; i<N; i++) + C[i] = A[i] - B[i]; +} + +template <class T> +void vectorscale( + Vector<T> &C, + const Vector<T> &A, + const T &B) +{ + const Subscript N = A.dim(); + Subscript i; + + for (i=0; i<N; i++) + C[i] = A[i] * B; +} + +template <class T> +void vectorscale( + Vector<T> &A, + const T &B) +{ + const Subscript N = A.dim(); + Subscript i; + + for (i=0; i<N; i++) + A[i] *= B; +} + + + + + +} /* namespace TNT */ + +#endif +// VEC_H diff --git a/intern/iksolver/intern/TNT/vecadaptor.h b/intern/iksolver/intern/TNT/vecadaptor.h new file mode 100644 index 00000000000..337748c58bd --- /dev/null +++ b/intern/iksolver/intern/TNT/vecadaptor.h @@ -0,0 +1,321 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + +* +* Template Numerical Toolkit (TNT): Linear Algebra Module +* +* Mathematical and Computational Sciences Division +* National Institute of Technology, +* Gaithersburg, MD USA +* +* +* This software was developed at the National Institute of Standards and +* Technology (NIST) by employees of the Federal Government in the course +* of their official duties. Pursuant to title 17 Section 105 of the +* United States Code, this software is not subject to copyright protection +* and is in the public domain. The Template Numerical Toolkit (TNT) is +* an experimental system. NIST assumes no responsibility whatsoever for +* its use by other parties, and makes no guarantees, expressed or implied, +* about its quality, reliability, or any other characteristic. +* +* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +* see http://math.nist.gov/tnt for latest updates. +* +*/ + + + +#ifndef VECADAPTOR_H +#define VECADAPTOR_H + +#include <cstdlib> +#include <iostream> +#include <strstream> +#include <cassert> + +#include "subscript.h" + +#ifdef TNT_USE_REGIONS +#include "region1d.h" +#endif + +namespace TNT +{ + +// see "tntreq.h" for TNT requirements for underlying vector +// class. This need NOT be the STL vector<> class, but a subset +// that provides minimal services. +// +// This is a container adaptor that provides the following services. +// +// o) adds 1-offset operator() access ([] is always 0 offset) +// o) adds TNT_BOUNDS_CHECK to () and [] +// o) adds initialization from strings, e.g. "1.0 2.0 3.0"; +// o) adds newsize(N) function (does not preserve previous values) +// o) adds dim() and dim(1) +// o) adds free() function to release memory used by vector +// o) adds regions, e.g. A(Index(1,10)) = ... +// o) add getVector() method to return adapted container +// o) adds simple I/O for ostreams + +template <class BBVec> +class Vector_Adaptor +{ + + public: + typedef typename BBVec::value_type T; + typedef T value_type; + typedef T element_type; + typedef T* pointer; + typedef T* iterator; + typedef T& reference; + typedef const T* const_iterator; + typedef const T& const_reference; + + Subscript lbound() const { return 1; } + + protected: + BBVec v_; + T* vm1_; + + public: + + Subscript size() const { return v_.size(); } + + // These were removed so that the ANSI C++ valarray class + // would work as a possible storage container. + // + // + //iterator begin() { return v_.begin();} + //iterator begin() { return &v_[0];} + // + //iterator end() { return v_.end(); } + //iterator end() { return &v_[0] + v_.size(); } + // + //const_iterator begin() const { return v_.begin();} + //const_iterator begin() const { return &v_[0];} + // + //const_iterator end() const { return v_.end(); } + //const_iterator end() const { return &v_[0] + v_.size(); } + + BBVec& getVector() { return v_; } + Subscript dim() const { return v_.size(); } + Subscript dim(Subscript i) + { +#ifdef TNT_BOUNDS_CHECK + assert(i==TNT_BASE_OFFSET); +#endif + return (i==TNT_BASE_OFFSET ? v_.size() : 0 ); + } + Vector_Adaptor() : v_() {}; + Vector_Adaptor(const Vector_Adaptor<BBVec> &A) : v_(A.v_) + { + vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL); + + } + + Vector_Adaptor(Subscript N, /*const*/ char *s) : v_(N) + { + istrstream ins(s); + for (Subscript i=0; i<N; i++) + ins >> v_[i] ; + + vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL); + }; + + Vector_Adaptor(Subscript N, const T& value = T()) : v_(N) + { + for (Subscript i=0; i<N; i++) + v_[i] = value; + + vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL); + } + + Vector_Adaptor(Subscript N, const T* values) : v_(N) + { + for (Subscript i=0; i<N; i++) + v_[i] = values[i]; + vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL); + } + Vector_Adaptor(const BBVec & A) : v_(A) + { + vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL); + } + + // NOTE: this assumes that BBVec(0) constructor creates an + // null vector that does not take up space... It would be + // great to require that BBVec have a corresponding free() + // function, but in particular STL vectors do not. + // + Vector_Adaptor<BBVec>& free() + { + return *this = Vector_Adaptor<BBVec>(0); + } + + Vector_Adaptor<BBVec>& operator=(const Vector_Adaptor<BBVec> &A) + { + v_ = A.v_ ; + vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL); + return *this; + } + + Vector_Adaptor<BBVec>& newsize(Subscript N) + { + // NOTE: this is not as efficient as it could be + // but to retain compatiblity with STL interface + // we cannot assume underlying implementation + // has a newsize() function. + + return *this = Vector_Adaptor<BBVec>(N); + + } + + Vector_Adaptor<BBVec>& operator=(const T &a) + { + Subscript i; + Subscript N = v_.size(); + for (i=0; i<N; i++) + v_[i] = a; + + return *this; + } + + Vector_Adaptor<BBVec>& resize(Subscript N) + { + if (N == size()) return *this; + + Vector_Adaptor<BBVec> tmp(N); + Subscript n = (N < size() ? N : size()); // min(N, size()); + Subscript i; + + for (i=0; i<n; i++) + tmp[i] = v_[i]; + + + return (*this = tmp); + + } + + + reference operator()(Subscript i) + { +#ifdef TNT_BOUNDS_CHECK + assert(1<=i); + assert(i<=dim()); +#endif + return vm1_[i]; + } + + const_reference operator()(Subscript i) const + { +#ifdef TNT_BOUNDS_CHECK + assert(1<=i); + assert(i<=dim()); +#endif + return vm1_[i]; + } + + reference operator[](Subscript i) + { +#ifdef TNT_BOUNDS_CHECK + assert(0<=i); + assert(i<dim()); +#endif + return v_[i]; + } + + const_reference operator[](Subscript i) const + { +#ifdef TNT_BOUNDS_CHECK + assert(0<=i); + assert(i<dim()); +#endif + return v_[i]; + } + + +#ifdef TNT_USE_REGIONS + // "index-aware" features, all of these are 1-based offsets + + typedef Region1D<Vector_Adaptor<BBVec> > Region; + + typedef const_Region1D< Vector_Adaptor<BBVec> > const_Region; + + Region operator()(const Index1D &I) + { return Region(*this, I); } + + Region operator()(const Subscript i1, Subscript i2) + { return Region(*this, i1, i2); } + + const_Region operator()(const Index1D &I) const + { return const_Region(*this, I); } + + const_Region operator()(const Subscript i1, Subscript i2) const + { return const_Region(*this, i1, i2); } +#endif +// TNT_USE_REGIONS + + +}; + +#include <iostream> + +template <class BBVec> +std::ostream& operator<<(std::ostream &s, const Vector_Adaptor<BBVec> &A) +{ + Subscript M=A.size(); + + s << M << endl; + for (Subscript i=1; i<=M; i++) + s << A(i) << endl; + return s; +} + +template <class BBVec> +std::istream& operator>>(std::istream &s, Vector_Adaptor<BBVec> &A) +{ + Subscript N; + + s >> N; + + A.resize(N); + + for (Subscript i=1; i<=N; i++) + s >> A(i); + + return s; +} + +} // namespace TNT + +#endif diff --git a/intern/iksolver/intern/TNT/version.h b/intern/iksolver/intern/TNT/version.h new file mode 100644 index 00000000000..c2759e0ce44 --- /dev/null +++ b/intern/iksolver/intern/TNT/version.h @@ -0,0 +1,52 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +// Template Numerical Toolkit (TNT) for Linear Algebra + +// +// BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE +// Please see http://math.nist.gov/tnt for updates +// +// R. Pozo +// Mathematical and Computational Sciences Division +// National Institute of Standards and Technology + + +#ifndef TNT_VERSION_H +#define TNT_VERSION_H + + +#define TNT_MAJOR_VERSION '0' +#define TNT_MINOR_VERSION '9' +#define TNT_SUBMINOR_VERSION '4' +#define TNT_VERSION_STRING "0.9.4" + +#endif diff --git a/intern/iksolver/make/msvc_6_0/iksolver.dsp b/intern/iksolver/make/msvc_6_0/iksolver.dsp new file mode 100644 index 00000000000..fb12812b7a7 --- /dev/null +++ b/intern/iksolver/make/msvc_6_0/iksolver.dsp @@ -0,0 +1,244 @@ +# Microsoft Developer Studio Project File - Name="iksolver" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=iksolver - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "iksolver.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "iksolver.mak" CFG="iksolver - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "iksolver - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "iksolver - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "iksolver - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /Ob2 /I "..\..\..\..\intern\moto\include" /I "..\..\..\..\intern\memutil" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x413 /d "NDEBUG" +# ADD RSC /l 0x413 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\..\lib\windows\release\iksolver_rmtd.lib" + +!ELSEIF "$(CFG)" == "iksolver - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\intern\moto\include" /I "..\..\..\..\intern\memutil" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x413 /d "_DEBUG" +# ADD RSC /l 0x413 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\..\lib\windows\debug\iksolver_dmtd.lib" + +!ENDIF + +# Begin Target + +# Name "iksolver - Win32 Release" +# Name "iksolver - Win32 Debug" +# Begin Group "intern" + +# PROP Default_Filter "" +# Begin Group "common" + +# PROP Default_Filter "" +# End Group +# Begin Group "TNT" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\intern\TNT\cholesky.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\cmat.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\fcscmat.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\fmat.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\fortran.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\fspvec.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\index.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\lapack.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\lu.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\qr.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\region1d.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\region2d.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\stopwatch.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\subscript.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\svd.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\tnt.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\tntmath.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\tntreqs.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\transv.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\triang.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\trisolve.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\vec.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\vecadaptor.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\TNT\version.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\intern\IK_QChain.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\IK_QChain.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\IK_QJacobianSolver.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\IK_QJacobianSolver.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\IK_QSegment.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\IK_QSegment.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\IK_QSolver_Class.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\IK_Solver.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\MT_ExpMap.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\MT_ExpMap.h +# End Source File +# End Group +# Begin Group "extern" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\extern\IK_solver.h +# End Source File +# End Group +# End Target +# End Project diff --git a/intern/iksolver/make/msvc_6_0/iksolver.dsw b/intern/iksolver/make/msvc_6_0/iksolver.dsw new file mode 100644 index 00000000000..90a123d9ce8 --- /dev/null +++ b/intern/iksolver/make/msvc_6_0/iksolver.dsw @@ -0,0 +1,35 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "iksolver"=.\iksolver.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + + + + + + + diff --git a/intern/iksolver/test/Makefile b/intern/iksolver/test/Makefile new file mode 100644 index 00000000000..f59e487add0 --- /dev/null +++ b/intern/iksolver/test/Makefile @@ -0,0 +1,67 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# iksolver test makefile. +# + +LIBNAME = iksolver +SOURCEDIR = intern/$(LIBNAME)/test +DIR = $(OCGDIR)/$(SOURCEDIR) + +include nan_compile.mk + +DIRS = ik_glut_test + +include nan_subdirs.mk + +include nan_link.mk + +LIBS = $(OCGDIR)/intern/$(LIBNAME)/test/ik_glut_test/intern/$(DEBUG_DIR)libintern.a +LIBS += $(OCGDIR)/intern/$(LIBNAME)/test/ik_glut_test/common/$(DEBUG_DIR)libcommon.a +LIBS += $(OCGDIR)/intern/$(LIBNAME)/$(DEBUG_DIR)libiksolver.a + +SLIBS += $(NAN_MOTO)/lib/$(DEBUG_DIR)libmoto.a + +ifeq ($(OS),$(findstring $(OS), "beos darwin linux freebsd openbsd")) + LLIBS = -L/usr/X11R6/lib -lglut -pthread +endif + +all debug:: $(LIBS) $(DIR)/$(DEBUG_DIR)iksolvertest + +$(DIR)/$(DEBUG_DIR)iksolvertest: + @echo "****> linking $@ in $(DIR)" + $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)iksolvertest $(LIBS) $(SLIBS) $(LLIBS) $(DADD) + +clean:: + $(RM) $(DIR)/iksolvertest $(DIR)/debug/iksolvertest + +test:: all + $(DIR)/iksolvertest + diff --git a/intern/iksolver/test/ik_glut_test/Makefile b/intern/iksolver/test/ik_glut_test/Makefile new file mode 100644 index 00000000000..4b47af16599 --- /dev/null +++ b/intern/iksolver/test/ik_glut_test/Makefile @@ -0,0 +1,42 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# iksolver subdir bouncer. Pure waste. +# + +include nan_definitions.mk + +LIBNAME = ik_glut_test +SOURCEDIR = intern/iksolver/test/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = common intern + +include nan_subdirs.mk + diff --git a/intern/iksolver/test/ik_glut_test/common/GlutDrawer.cpp b/intern/iksolver/test/ik_glut_test/common/GlutDrawer.cpp new file mode 100644 index 00000000000..40c6a4a95c9 --- /dev/null +++ b/intern/iksolver/test/ik_glut_test/common/GlutDrawer.cpp @@ -0,0 +1,95 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "GlutDrawer.h" + +#include "MT_assert.h" + +MEM_SmartPtr<GlutDrawManager> GlutDrawManager::m_s_instance = MEM_SmartPtr<GlutDrawManager>(); + + GlutDrawManager * +GlutDrawManager:: +Instance( +){ + if (m_s_instance == NULL) { + m_s_instance = new GlutDrawManager(); + } + + return m_s_instance; +} + + +// this is the function you should pass to glut + + void +GlutDrawManager:: +Draw( +){ + GlutDrawManager *manager = GlutDrawManager::Instance(); + + if (manager->m_drawer != NULL) { + manager->m_drawer->Draw(); + } +} + + void +GlutDrawManager:: +InstallDrawer( + GlutDrawer * drawer +){ + + MT_assert(m_drawer == NULL); + m_drawer = drawer; +} + + void +GlutDrawManager:: +ReleaseDrawer( +){ + m_drawer = NULL; +} + + +GlutDrawManager:: +~GlutDrawManager( +){ + + delete(m_drawer); +} + + + + + + + + + diff --git a/intern/iksolver/test/ik_glut_test/common/GlutDrawer.h b/intern/iksolver/test/ik_glut_test/common/GlutDrawer.h new file mode 100644 index 00000000000..7e56a02dd47 --- /dev/null +++ b/intern/iksolver/test/ik_glut_test/common/GlutDrawer.h @@ -0,0 +1,100 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_GlutDrawer + +#define NAN_INCLUDED_GlutDrawer + +#include "MEM_NonCopyable.h" +#include "MEM_SmartPtr.h" + +// So pissed off with Glut callback stuff +// that is impossible to call objects unless they are global + +// inherit from GlutDrawer and installl the drawer in the singleton +// class GlutDrawManager. + +class GlutDrawer { +public : + + virtual + void + Draw( + )= 0; + + virtual + ~GlutDrawer( + ){}; +}; + +class GlutDrawManager : public MEM_NonCopyable{ + +public : + + static + GlutDrawManager * + Instance( + ); + + // this is the function you should pass to glut + + static + void + Draw( + ); + + void + InstallDrawer( + GlutDrawer * + ); + + void + ReleaseDrawer( + ); + + ~GlutDrawManager( + ); + +private : + + GlutDrawManager ( + ) : + m_drawer (0) + { + }; + + GlutDrawer * m_drawer; + + static MEM_SmartPtr<GlutDrawManager> m_s_instance; +}; + + +#endif
\ No newline at end of file diff --git a/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.cpp b/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.cpp new file mode 100644 index 00000000000..0d1d52b542d --- /dev/null +++ b/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.cpp @@ -0,0 +1,89 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "GlutKeyboardManager.h" + +#include "MT_assert.h" + +MEM_SmartPtr<GlutKeyboardManager> GlutKeyboardManager::m_s_instance = MEM_SmartPtr<GlutKeyboardManager>(); + + GlutKeyboardManager * +GlutKeyboardManager:: +Instance( +){ + if (m_s_instance == NULL) { + m_s_instance = new GlutKeyboardManager(); + } + + return m_s_instance; +} + + +// this is the function you should pass to glut + + void +GlutKeyboardManager:: +HandleKeyboard( + unsigned char key, + int x, + int y +){ + GlutKeyboardManager *manager = GlutKeyboardManager::Instance(); + + if (manager->m_handler != NULL) { + manager->m_handler->HandleKeyboard(key,x,y); + } +} + + void +GlutKeyboardManager:: +InstallHandler( + GlutKeyboardHandler * handler +){ + + MT_assert(m_handler == NULL); + m_handler = handler; +} + + void +GlutKeyboardManager:: +ReleaseHandler( +){ + m_handler = NULL; +} + + +GlutKeyboardManager:: +~GlutKeyboardManager( +){ + + delete(m_handler); +}
\ No newline at end of file diff --git a/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.h b/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.h new file mode 100644 index 00000000000..39174b5ff1a --- /dev/null +++ b/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.h @@ -0,0 +1,106 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_GlutKeyboardManager + +#define NAN_INCLUDED_GlutKeyboardManager + +#include "MEM_NonCopyable.h" +#include "MEM_SmartPtr.h" + +// So pissed off with Glut callback stuff +// that is impossible to call objects unless they are global + +// inherit from GlutKeyboardHandler and installl the drawer in the singleton +// class GlutKeyboardManager. + +class GlutKeyboardHandler : public MEM_NonCopyable { +public : + + virtual + void + HandleKeyboard( + unsigned char key, + int x, + int y + )= 0; + + virtual + ~GlutKeyboardHandler( + ){}; +}; + +class GlutKeyboardManager : public MEM_NonCopyable{ + +public : + + static + GlutKeyboardManager * + Instance( + ); + + // this is the function you should pass to glut + + static + void + HandleKeyboard( + unsigned char key, + int x, + int y + ); + + void + InstallHandler( + GlutKeyboardHandler * + ); + + void + ReleaseHandler( + ); + + ~GlutKeyboardManager( + ); + +private : + + GlutKeyboardManager ( + ) : + m_handler (0) + { + }; + + GlutKeyboardHandler * m_handler; + + static MEM_SmartPtr<GlutKeyboardManager> m_s_instance; +}; + + +#endif
\ No newline at end of file diff --git a/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.cpp b/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.cpp new file mode 100644 index 00000000000..57f4a65327e --- /dev/null +++ b/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.cpp @@ -0,0 +1,104 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "GlutMouseManager.h" + +#include "MT_assert.h" + +MEM_SmartPtr<GlutMouseManager> GlutMouseManager::m_s_instance = MEM_SmartPtr<GlutMouseManager>(); + + + GlutMouseManager * +GlutMouseManager:: +Instance( +){ + if (m_s_instance == NULL) { + m_s_instance = new GlutMouseManager(); + } + + return m_s_instance; +} + +// these are the functions you should pass to GLUT + + void +GlutMouseManager:: +Mouse( + int button, + int state, + int x, + int y +){ + GlutMouseManager *manager = GlutMouseManager::Instance(); + + if (manager->m_handler != NULL) { + manager->m_handler->Mouse(button,state,x,y); + } +} + + void +GlutMouseManager:: +Motion( + int x, + int y +){ + GlutMouseManager *manager = GlutMouseManager::Instance(); + + if (manager->m_handler != NULL) { + manager->m_handler->Motion(x,y); + } +} + + void +GlutMouseManager:: +InstallHandler( + GlutMouseHandler *handler +){ + + MT_assert(m_handler == NULL); + m_handler = handler; +} + + void +GlutMouseManager:: +ReleaseHandler( +){ + m_handler = NULL; +} + +GlutMouseManager:: +~GlutMouseManager( +){ + + delete(m_handler); +} + + diff --git a/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.h b/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.h new file mode 100644 index 00000000000..95700bc14dd --- /dev/null +++ b/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.h @@ -0,0 +1,116 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_GlutMouseManager_h + +#define NAN_INCLUDED_GlutMouseManager_h + +#include "MEM_NonCopyable.h" +#include "MEM_SmartPtr.h" + +class GlutMouseHandler { +public : + + virtual + void + Mouse( + int button, + int state, + int x, + int y + ) = 0; + + virtual + void + Motion( + int x, + int y + ) = 0; + + virtual + ~GlutMouseHandler( + ){}; +}; + +class GlutMouseManager : public MEM_NonCopyable{ + +public : + + static + GlutMouseManager * + Instance( + ); + + // these are the functions you should pass to GLUT + + static + void + Mouse( + int button, + int state, + int x, + int y + ); + + static + void + Motion( + int x, + int y + ); + + void + InstallHandler( + GlutMouseHandler * + ); + + void + ReleaseHandler( + ); + + ~GlutMouseManager( + ); + +private : + + GlutMouseManager ( + ) : + m_handler (0) + { + }; + + GlutMouseHandler * m_handler; + + static MEM_SmartPtr<GlutMouseManager> m_s_instance; +}; + + +#endif
\ No newline at end of file diff --git a/intern/iksolver/test/ik_glut_test/common/Makefile b/intern/iksolver/test/ik_glut_test/common/Makefile new file mode 100644 index 00000000000..07ad1837a7d --- /dev/null +++ b/intern/iksolver/test/ik_glut_test/common/Makefile @@ -0,0 +1,44 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# iksolver test intern Makefile +# + +LIBNAME = common +SOURCEDIR = intern/iksolver/test/ik_glut_test/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) + +include nan_compile.mk + +CCFLAGS += $(LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I$(NAN_MOTO)/include +CPPFLAGS += -I$(NAN_MEMUTIL)/include + diff --git a/intern/iksolver/test/ik_glut_test/intern/ChainDrawer.h b/intern/iksolver/test/ik_glut_test/intern/ChainDrawer.h new file mode 100644 index 00000000000..a164e686e37 --- /dev/null +++ b/intern/iksolver/test/ik_glut_test/intern/ChainDrawer.h @@ -0,0 +1,387 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_ChainDrawer_h + +#define NAN_INCLUDED_ChainDrawer_h + +#include "../common/GlutDrawer.h" +#include "MyGlutMouseHandler.h" +#include "MyGlutKeyHandler.h" +#include "MT_Transform.h" +#ifdef USE_QUATERNIONS +# include "IK_Qsolver.h" +# include "../intern/IK_QChain.h" +# include "../intern/IK_QSolver_Class.h" +#else +# include "IK_solver.h" +# include "../intern/IK_Chain.h" +# include "../intern/IK_Solver_Class.h" +#endif +#include <GL/glut.h> + +class ChainDrawer : public GlutDrawer +{ +public : + static + ChainDrawer * + New( + ) { + return new ChainDrawer(); + } + + void + SetMouseHandler( + MyGlutMouseHandler *mouse_handler + ) { + m_mouse_handler = mouse_handler; + } + + void + SetKeyHandler ( + MyGlutKeyHandler *key_handler + ) { + m_key_handler = key_handler; + } + + void + SetChain( + IK_Chain_ExternPtr *chains,int chain_num + ) { + m_chain_num = chain_num; + m_chains = chains; + } + + + // inherited from GlutDrawer + void + Draw( + ) { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glPopMatrix(); + glPushMatrix(); + glRotatef(m_mouse_handler->AngleX(), 0.0, 1.0, 0.0); + glRotatef(m_mouse_handler->AngleY(), 1.0, 0.0, 0.0); + + DrawScene(); + glutSwapBuffers(); + + } + + ~ChainDrawer( + ){ + // nothing to do + }; + +private : + + void + DrawScene( + ){ + + // draw a little cross at the position of the key handler + // coordinates + + MT_Vector3 line_x(4,0,0); + MT_Vector3 line_y(0.0,4,0); + MT_Vector3 line_z(0.0,0.0,4); + + MT_Vector3 cross_origin = m_mouse_handler->Position(); + MT_Vector3 temp; + + glDisable(GL_LIGHTING); + + + glBegin(GL_LINES); + + glColor3f (1.0f,1.0f,1.0f); + + temp = cross_origin - line_x; + glVertex3f(temp[0],temp[1],temp[2]); + temp = cross_origin + line_x; + glVertex3f(temp[0],temp[1],temp[2]); + + temp = cross_origin - line_y; + glVertex3f(temp[0],temp[1],temp[2]); + temp = cross_origin + line_y; + glVertex3f(temp[0],temp[1],temp[2]); + + temp = cross_origin - line_z; + glVertex3f(temp[0],temp[1],temp[2]); + temp = cross_origin + line_z; + glVertex3f(temp[0],temp[1],temp[2]); + + glEnd(); + glEnable(GL_LIGHTING); + + + IK_Chain_ExternPtr chain; + + int chain_num; + for (chain_num = 0; chain_num < m_chain_num; chain_num++) { + chain = m_chains[chain_num]; + + + IK_Segment_ExternPtr segs = chain->segments; + IK_Segment_ExternPtr seg_start = segs; + const IK_Segment_ExternPtr seg_end = segs + chain->num_segments; + float ogl_matrix[16]; + + glColor3f (0.0f,1.0f,0.0f); + + MT_Vector3 previous_origin(0,0,0); + + MT_Transform global_transform; + global_transform.setIdentity(); + + for (; seg_start != seg_end; ++seg_start) { + + glPushMatrix(); + + // fill ogl_matrix with zeros + + std::fill(ogl_matrix,ogl_matrix + 16,float(0)); + + // we have to do a bit of work here to compute the chain's + // bone values + + // first compute all the matrices we need + + MT_Transform translation; + translation.setIdentity(); + translation.translate(MT_Vector3(0,seg_start->length,0)); + + MT_Matrix3x3 seg_rot( + seg_start->basis_change[0],seg_start->basis_change[1],seg_start->basis_change[2], + seg_start->basis_change[3],seg_start->basis_change[4],seg_start->basis_change[5], + seg_start->basis_change[6],seg_start->basis_change[7],seg_start->basis_change[8] + ); + + seg_rot.transpose(); + + MT_Matrix3x3 seg_pre_rot( + seg_start->basis[0],seg_start->basis[1],seg_start->basis[2], + seg_start->basis[3],seg_start->basis[4],seg_start->basis[5], + seg_start->basis[6],seg_start->basis[7],seg_start->basis[8] + ); + + + MT_Transform seg_t_pre_rot( + MT_Point3( + seg_start->seg_start[0], + seg_start->seg_start[1], + seg_start->seg_start[2] + ), + seg_pre_rot + ); + // start of the bone is just the current global transform + // multiplied by the seg_start vector + + + + MT_Transform seg_t_rot(MT_Point3(0,0,0),seg_rot); + MT_Transform seg_local = seg_t_pre_rot * seg_t_rot * translation; + + MT_Vector3 bone_start = global_transform * + MT_Point3( + seg_start->seg_start[0], + seg_start->seg_start[1], + seg_start->seg_start[2] + ); + + + global_transform = global_transform * seg_local; + + global_transform.getValue(ogl_matrix); + MT_Vector3 bone_end = global_transform.getOrigin(); + + glMultMatrixf(ogl_matrix); +// glutSolidSphere(0.5,5,5); + + glPopMatrix(); + + glDisable(GL_LIGHTING); + + glBegin(GL_LINES); + + // draw lines of the principle axis of the local transform + + MT_Vector3 x_axis(1,0,0); + MT_Vector3 y_axis(0,1,0); + MT_Vector3 z_axis(0,0,1); + + x_axis = global_transform.getBasis() * x_axis * 5; + y_axis = global_transform.getBasis() * y_axis * 5; + z_axis = global_transform.getBasis() * z_axis * 5; + + + x_axis = x_axis + bone_start; + y_axis = y_axis + bone_start; + z_axis = z_axis + bone_start; + + glColor3f(1,0,0); + + glVertex3f(x_axis.x(),x_axis.y(),x_axis.z()); + glVertex3f( + bone_start.x(), + bone_start.y(), + bone_start.z() + ); + + glColor3f(0,1,0); + + glVertex3f(y_axis.x(),y_axis.y(),y_axis.z()); + glVertex3f( + bone_start.x(), + bone_start.y(), + bone_start.z() + ); + + glColor3f(0,1,1); + + glVertex3f(z_axis.x(),z_axis.y(),z_axis.z()); + glVertex3f( + bone_start.x(), + bone_start.y(), + bone_start.z() + ); + + glColor3f(0,0,1); + + glVertex3f( + bone_start.x(), + bone_start.y(), + bone_start.z() + ); + glVertex3f(bone_end[0],bone_end[1],bone_end[2]); + + glEnd(); + glEnable(GL_LIGHTING); + } +#if 0 + // draw jacobian column vectors + + // hack access to internals + + IK_Solver_Class * internals = static_cast<IK_Solver_Class *>(chain->intern); + + glDisable(GL_LIGHTING); + + glBegin(GL_LINES); + + const TNT::Matrix<MT_Scalar> & jac = internals->Chain().TransposedJacobian(); + + int i = 0; + for (i=0; i < jac.num_rows(); i++) { + glColor3f(1,1,1); + + previous_origin = internals->Chain().Segments()[i/3].GlobalSegmentStart(); + + glVertex3f(previous_origin[0],previous_origin[1],previous_origin[2]); + glVertex3f(jac[i][0] + previous_origin[0],jac[i][1] + previous_origin[1],jac[i][2] + previous_origin[2]); + + + } + glEnd(); + glEnable(GL_LIGHTING); +#endif + + } + + glColor3f(1.0,1.0,1.0); + + glDisable(GL_LIGHTING); + glBegin(GL_LINES); + + MT_Scalar cube_size = 50; + glVertex3f(cube_size,cube_size,cube_size); + glVertex3f(-cube_size,cube_size,cube_size); + + glVertex3f(cube_size,-cube_size,cube_size); + glVertex3f(-cube_size,-cube_size,cube_size); + + glVertex3f(cube_size,cube_size,-cube_size); + glVertex3f(-cube_size,cube_size,-cube_size); + + glVertex3f(cube_size,-cube_size,-cube_size); + glVertex3f(-cube_size,-cube_size,-cube_size); + + + glVertex3f(-cube_size,cube_size,cube_size); + glVertex3f(-cube_size,-cube_size,cube_size); + + glVertex3f(cube_size,cube_size,-cube_size); + glVertex3f(cube_size,-cube_size,-cube_size); + + glVertex3f(cube_size,cube_size,cube_size); + glVertex3f(cube_size,-cube_size,cube_size); + + glVertex3f(-cube_size,cube_size,-cube_size); + glVertex3f(-cube_size,-cube_size,-cube_size); + + + glVertex3f(cube_size,cube_size,cube_size); + glVertex3f(cube_size,cube_size,-cube_size); + + glVertex3f(cube_size,-cube_size,cube_size); + glVertex3f(cube_size,-cube_size,-cube_size); + + glVertex3f(-cube_size,cube_size,cube_size); + glVertex3f(-cube_size,cube_size,-cube_size); + + glVertex3f(-cube_size,-cube_size,cube_size); + glVertex3f(-cube_size,-cube_size,-cube_size); + glEnd(); + glEnable(GL_LIGHTING); + + }; + + + +private : + + MyGlutMouseHandler * m_mouse_handler; + MyGlutKeyHandler *m_key_handler; + IK_Chain_ExternPtr *m_chains; + + int m_chain_num; + ChainDrawer ( + ) : m_chains (NULL), + m_mouse_handler (NULL), + m_chain_num (0) + { + }; + +}; + + + +#endif
\ No newline at end of file diff --git a/intern/iksolver/test/ik_glut_test/intern/Makefile b/intern/iksolver/test/ik_glut_test/intern/Makefile new file mode 100644 index 00000000000..fe1f4b54182 --- /dev/null +++ b/intern/iksolver/test/ik_glut_test/intern/Makefile @@ -0,0 +1,51 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# iksolver test intern Makefile +# + +LIBNAME = intern +SOURCEDIR = intern/iksolver/test/ik_glut_test/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) + +include nan_compile.mk + +CCFLAGS += $(LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I$(OPENGL_HEADERS) +CPPFLAGS += -I../../../extern +CPPFLAGS += -I../common +CPPFLAGS += -I$(NAN_MOTO)/include +CPPFLAGS += -I$(NAN_MEMUTIL)/include + +ifeq ($(OS),windows) + CPPFLAGS += -I$(NAN_LIBDIR)/windows/glut-3.7/include +endif + diff --git a/intern/iksolver/test/ik_glut_test/intern/MyGlutKeyHandler.h b/intern/iksolver/test/ik_glut_test/intern/MyGlutKeyHandler.h new file mode 100644 index 00000000000..5f88bda378c --- /dev/null +++ b/intern/iksolver/test/ik_glut_test/intern/MyGlutKeyHandler.h @@ -0,0 +1,84 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_MyGlutKeyHandler_h + +#define NAN_INCLUDED_MyGlutKeyHandler_h + +#include "../common/GlutKeyboardManager.h" + +class MyGlutKeyHandler : public GlutKeyboardHandler +{ +public : + static + MyGlutKeyHandler * + New( + ) { + MEM_SmartPtr<MyGlutKeyHandler> output = new MyGlutKeyHandler(); + + if (output == NULL + ) { + return NULL; + } + return output.Release(); + + } + + void + HandleKeyboard( + unsigned char key, + int x, + int y + ){ + + switch (key) { + + case 27 : + + exit(0); + } + } + + ~MyGlutKeyHandler( + ) + { + }; + +private : + + MyGlutKeyHandler( + ) + { + } + +}; +#endif + diff --git a/intern/iksolver/test/ik_glut_test/intern/MyGlutMouseHandler.h b/intern/iksolver/test/ik_glut_test/intern/MyGlutMouseHandler.h new file mode 100644 index 00000000000..e7d210beffb --- /dev/null +++ b/intern/iksolver/test/ik_glut_test/intern/MyGlutMouseHandler.h @@ -0,0 +1,211 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_MyGlutMouseHandler_h + +#define NAN_INCLUDED_MyGlutMouseHandler_h + +#include "../common/GlutMouseManager.h" +#include <GL/glut.h> +#include "IK_solver.h" + +class MyGlutMouseHandler : public GlutMouseHandler +{ + +public : + + static + MyGlutMouseHandler * + New( + ) { + MEM_SmartPtr<MyGlutMouseHandler> output = new MyGlutMouseHandler(); + if (output == NULL + ) { + return NULL; + } + return output.Release(); + + } + + void + SetChain( + IK_Chain_ExternPtr *chains, int num_chains + ){ + m_chains = chains; + m_num_chains = num_chains; + } + + void + Mouse( + int button, + int state, + int x, + int y + ){ + if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { + m_moving = true; + m_begin_x = x; + m_begin_y = y; + } + if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) { + m_moving = false; + } + + if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) { + m_tracking = true; + } + if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP) { + m_tracking = false; + } + + if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) { + m_cg_on = true; + } + if (button == GLUT_MIDDLE_BUTTON && state == GLUT_UP) { + m_cg_on = false; + } + + } + + + void + Motion( + int x, + int y + ){ + if (m_moving) { + m_angle_x = m_angle_x + (x - m_begin_x); + m_begin_x = x; + + m_angle_y = m_angle_y + (y - m_begin_y); + m_begin_y = y; + + glutPostRedisplay(); + } + if (m_tracking) { + + int w_h = glutGet((GLenum)GLUT_WINDOW_HEIGHT); + + y = w_h - y; + + double mvmatrix[16]; + double projmatrix[16]; + GLint viewport[4]; + + double px, py, pz,sz; + + /* Get the matrices needed for gluUnProject */ + glGetIntegerv(GL_VIEWPORT, viewport); + glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix); + glGetDoublev(GL_PROJECTION_MATRIX, projmatrix); + + // work out the position of the end effector in screen space + + GLdouble ex,ey,ez; + ex = m_pos.x(); + ey = m_pos.y(); + ez = m_pos.z(); + + gluProject(ex, ey, ez, mvmatrix, projmatrix, viewport, &px, &py, &sz); + gluUnProject((GLdouble) x, (GLdouble) y, sz, mvmatrix, projmatrix, viewport, &px, &py, &pz); + + m_pos = MT_Vector3(px,py,pz); + + } + if (m_tracking || m_cg_on) { + float temp[3]; + m_pos.getValue(temp); + + IK_SolveChain(m_chains[0],temp,0.01,200,0.1,m_chains[1]->segments); + IK_LoadChain(m_chains[0],m_chains[0]->segments,m_chains[0]->num_segments); + + glutPostRedisplay(); + } + + + } + + const + float + AngleX( + ) const { + return m_angle_x; + } + + const + float + AngleY( + ) const { + return m_angle_y; + } + + const + MT_Vector3 + Position( + ) const { + return m_pos; + } + + +private : + + MyGlutMouseHandler ( + ) : + m_angle_x(0), + m_angle_y(0), + m_begin_x(0), + m_begin_y(0), + m_moving (false), + m_tracking (false), + m_pos(0,0,0), + m_cg_on (false), + m_chains(NULL), + m_num_chains(0) + { + }; + + float m_angle_x; + float m_angle_y; + float m_begin_x; + float m_begin_y; + + bool m_moving; + bool m_tracking; + bool m_cg_on; + MT_Vector3 m_pos; + + IK_Chain_ExternPtr *m_chains; + int m_num_chains; + +}; + + +#endif
\ No newline at end of file diff --git a/intern/iksolver/test/ik_glut_test/intern/main.cpp b/intern/iksolver/test/ik_glut_test/intern/main.cpp new file mode 100644 index 00000000000..137c9bd4470 --- /dev/null +++ b/intern/iksolver/test/ik_glut_test/intern/main.cpp @@ -0,0 +1,361 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + + +#include "MEM_SmartPtr.h" + +#ifdef USE_QUATERNIONS +#include "IK_Qsolver.h" +#else +#include "IK_solver.h" +#endif + +#include <GL/glut.h> +#include "MT_Vector3.h" +#include "MT_Quaternion.h" +#include "MT_Matrix3x3.h" +#include "MyGlutMouseHandler.h" +#include "MyGlutKeyHandler.h" +#include "ChainDrawer.h" + +void +init(MT_Vector3 min,MT_Vector3 max) +{ + + GLfloat light_diffuse0[] = {1.0, 0.0, 0.0, 1.0}; /* Red diffuse light. */ + GLfloat light_position0[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */ + + GLfloat light_diffuse1[] = {1.0, 1.0, 1.0, 1.0}; /* Red diffuse light. */ + GLfloat light_position1[] = {1.0, 0, 0, 0.0}; /* Infinite light location. */ + + /* Enable a single OpenGL light. */ + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse0); + glLightfv(GL_LIGHT0, GL_POSITION, light_position0); + + glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse1); + glLightfv(GL_LIGHT1, GL_POSITION, light_position1); + + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_LIGHTING); + + /* Use depth buffering for hidden surface elimination. */ + glEnable(GL_DEPTH_TEST); + + /* Setup the view of the cube. */ + glMatrixMode(GL_PROJECTION); + + // centre of the box + 3* depth of box + + MT_Vector3 centre = (min + max) * 0.5; + MT_Vector3 diag = max - min; + + float depth = diag.length(); + float distance = 2; + + gluPerspective( + /* field of view in degree */ 40.0, + /* aspect ratio */ 1.0, + /* Z near */ 1.0, + /* Z far */ distance * depth * 2 + ); + glMatrixMode(GL_MODELVIEW); + + + gluLookAt( + centre.x(), centre.y(), centre.z() + distance*depth, /* eye is at (0,0,5) */ + centre.x(), centre.y(), centre.z(), /* center is at (0,0,0) */ + 0.0, 1.0, 0.); /* up is in positive Y direction */ + + glPushMatrix(); + + +} +int +main(int argc, char **argv) +{ + + + const int seg_num = 5; + const MT_Scalar seg_length = 15; + + const float seg_startA[3] = {0,0,0}; + const float seg_startB[3] = {0,-20,0}; + + // create some segments to solve with + + // First chain + ////////////// + + + IK_Segment_ExternPtr const segmentsA = new IK_Segment_Extern[seg_num]; + IK_Segment_ExternPtr const segmentsB = new IK_Segment_Extern[seg_num]; + + IK_Segment_ExternPtr seg_it = segmentsA; + IK_Segment_ExternPtr seg_itB = segmentsB; + + + { + +// MT_Quaternion qmat(MT_Vector3(0,0,1),-3.141/2); + MT_Quaternion qmat(MT_Vector3(0,0,1),0); + MT_Matrix3x3 mat(qmat); + + seg_it->seg_start[0] = seg_startA[0]; + seg_it->seg_start[1] = seg_startA[1]; + seg_it->seg_start[2] = seg_startA[2]; + + float temp[12]; + mat.getValue(temp); + + seg_it->basis[0] = temp[0]; + seg_it->basis[1] = temp[1]; + seg_it->basis[2] = temp[2]; + + seg_it->basis[3] = temp[4]; + seg_it->basis[4] = temp[5]; + seg_it->basis[5] = temp[6]; + + seg_it->basis[6] = temp[8]; + seg_it->basis[7] = temp[9]; + seg_it->basis[8] = temp[10]; + + seg_it->length = seg_length; + + MT_Quaternion q; + q.setEuler(0,0,0); + + + MT_Matrix3x3 qrot(q); + + seg_it->basis_change[0] = 1; + seg_it->basis_change[1] = 0; + seg_it->basis_change[2] = 0; + seg_it->basis_change[3] = 0; + seg_it->basis_change[4] = 1; + seg_it->basis_change[5] = 0; + seg_it->basis_change[6] = 0; + seg_it->basis_change[7] = 0; + seg_it->basis_change[8] = 1; + + + seg_it ++; + + seg_itB->seg_start[0] = seg_startA[0]; + seg_itB->seg_start[1] = seg_startA[1]; + seg_itB->seg_start[2] = seg_startA[2]; + + seg_itB->basis[0] = temp[0]; + seg_itB->basis[1] = temp[1]; + seg_itB->basis[2] = temp[2]; + + seg_itB->basis[3] = temp[4]; + seg_itB->basis[4] = temp[5]; + seg_itB->basis[5] = temp[6]; + + seg_itB->basis[6] = temp[8]; + seg_itB->basis[7] = temp[9]; + seg_itB->basis[8] = temp[10]; + + seg_itB->length = seg_length; + + seg_itB->basis_change[0] = 1; + seg_itB->basis_change[1] = 0; + seg_itB->basis_change[2] = 0; + seg_itB->basis_change[3] = 0; + seg_itB->basis_change[4] = 1; + seg_itB->basis_change[5] = 0; + seg_itB->basis_change[6] = 0; + seg_itB->basis_change[7] = 0; + seg_itB->basis_change[8] = 1; + + + seg_itB ++; + + + } + + + int i; + for (i=1; i < seg_num; ++i, ++seg_it,++seg_itB) { + + MT_Quaternion qmat(MT_Vector3(0,0,1),0.3); + MT_Matrix3x3 mat(qmat); + + seg_it->seg_start[0] = 0; + seg_it->seg_start[1] = 0; + seg_it->seg_start[2] = 0; + + float temp[12]; + mat.getValue(temp); + + seg_it->basis[0] = temp[0]; + seg_it->basis[1] = temp[1]; + seg_it->basis[2] = temp[2]; + + seg_it->basis[3] = temp[4]; + seg_it->basis[4] = temp[5]; + seg_it->basis[5] = temp[6]; + + seg_it->basis[6] = temp[8]; + seg_it->basis[7] = temp[9]; + seg_it->basis[8] = temp[10]; + + seg_it->length = seg_length; + + MT_Quaternion q; + q.setEuler(0,0,0); + + + MT_Matrix3x3 qrot(q); + + seg_it->basis_change[0] = 1; + seg_it->basis_change[1] = 0; + seg_it->basis_change[2] = 0; + seg_it->basis_change[3] = 0; + seg_it->basis_change[4] = 1; + seg_it->basis_change[5] = 0; + seg_it->basis_change[6] = 0; + seg_it->basis_change[7] = 0; + seg_it->basis_change[8] = 1; + + + /////////////////////////////// + + seg_itB->seg_start[0] = 0; + seg_itB->seg_start[1] = 0; + seg_itB->seg_start[2] = 0; + + seg_itB->basis[0] = temp[0]; + seg_itB->basis[1] = temp[1]; + seg_itB->basis[2] = temp[2]; + + seg_itB->basis[3] = temp[4]; + seg_itB->basis[4] = temp[5]; + seg_itB->basis[5] = temp[6]; + + seg_itB->basis[6] = temp[8]; + seg_itB->basis[7] = temp[9]; + seg_itB->basis[8] = temp[10]; + + seg_itB->length = seg_length; + + seg_itB->basis_change[0] = 1; + seg_itB->basis_change[1] = 0; + seg_itB->basis_change[2] = 0; + seg_itB->basis_change[3] = 0; + seg_itB->basis_change[4] = 1; + seg_itB->basis_change[5] = 0; + seg_itB->basis_change[6] = 0; + seg_itB->basis_change[7] = 0; + seg_itB->basis_change[8] = 1; + + + + } + + // create the chains + + const int num_chains = 2; + + IK_Chain_ExternPtr chains[num_chains]; + + chains[0] = IK_CreateChain(); + chains[1] = IK_CreateChain(); + + // load segments into chain + + IK_LoadChain(chains[0],segmentsA,seg_num); + IK_LoadChain(chains[1],segmentsB,seg_num); + + // make and install a mouse handler + + MEM_SmartPtr<MyGlutMouseHandler> mouse_handler (MyGlutMouseHandler::New()); + GlutMouseManager::Instance()->InstallHandler(mouse_handler); + + mouse_handler->SetChain(chains,num_chains); + + // make and install a keyhandler + MEM_SmartPtr<MyGlutKeyHandler> key_handler (MyGlutKeyHandler::New()); + GlutKeyboardManager::Instance()->InstallHandler(key_handler); + + // instantiate the drawing class + + MEM_SmartPtr<ChainDrawer> drawer (ChainDrawer::New()); + GlutDrawManager::Instance()->InstallDrawer(drawer); + + drawer->SetMouseHandler(mouse_handler); + drawer->SetChain(chains,num_chains); + drawer->SetKeyHandler(key_handler); + + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); + glutCreateWindow("ik"); + glutDisplayFunc(GlutDrawManager::Draw); + glutMouseFunc(GlutMouseManager::Mouse); + glutMotionFunc(GlutMouseManager::Motion); + glutKeyboardFunc(GlutKeyboardManager::HandleKeyboard); + + init(MT_Vector3(-50,-50,-50),MT_Vector3(50,50,50)); + glutMainLoop(); + return 0; /* ANSI C requires main to return int. */ +} diff --git a/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsp b/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsp new file mode 100644 index 00000000000..8688b2fcc2c --- /dev/null +++ b/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsp @@ -0,0 +1,130 @@ +# Microsoft Developer Studio Project File - Name="ik_glut_test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ik_glut_test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ik_glut_test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ik_glut_test.mak" CFG="ik_glut_test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ik_glut_test - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "ik_glut_test - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ik_glut_test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\extern" /I "..\..\..\..\..\..\lib\windows\glut-3.7\include" /I "..\..\..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\..\..\lib\windows\memutil\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x413 /d "NDEBUG" +# ADD RSC /l 0x413 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 iksolver_rmtd.lib libmoto.a /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\..\lib\windows\release" /libpath:"..\..\..\..\..\..\lib\windows\glut-3.7\lib" /libpath:"..\..\..\..\..\..\lib\windows\moto\lib" + +!ELSEIF "$(CFG)" == "ik_glut_test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\extern" /I "..\..\..\..\..\..\lib\windows\glut-3.7\include" /I "..\..\..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\..\..\lib\windows\memutil\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x413 /d "_DEBUG" +# ADD RSC /l 0x413 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 iksolver_dmtd.lib libmoto.a /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"LIBCMTD.lib" /pdbtype:sept /libpath:"..\..\..\..\lib\windows\debug" /libpath:"..\..\..\..\..\..\lib\windows\glut-3.7\lib" /libpath:"..\..\..\..\..\..\lib\windows\moto\lib\debug" + +!ENDIF + +# Begin Target + +# Name "ik_glut_test - Win32 Release" +# Name "ik_glut_test - Win32 Debug" +# Begin Group "common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\common\GlutDrawer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\common\GlutDrawer.h +# End Source File +# Begin Source File + +SOURCE=..\..\common\GlutKeyboardManager.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\common\GlutKeyboardManager.h +# End Source File +# Begin Source File + +SOURCE=..\..\common\GlutMouseManager.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\common\GlutMouseManager.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\intern\ChainDrawer.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\main.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\MyGlutKeyHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\MyGlutMouseHandler.h +# End Source File +# End Target +# End Project diff --git a/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsw b/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsw new file mode 100644 index 00000000000..09b7094137b --- /dev/null +++ b/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsw @@ -0,0 +1,49 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "ik_glut_test"=.\ik_glut_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name iksolver + End Project Dependency +}}} + +############################################################################### + +Project: "iksolver"=..\..\..\..\make\msvc_6_0\iksolver.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + + + + + + diff --git a/intern/img/doc/Doxyfile.win b/intern/img/doc/Doxyfile.win new file mode 100644 index 00000000000..242357fe7b5 --- /dev/null +++ b/intern/img/doc/Doxyfile.win @@ -0,0 +1,747 @@ +# Doxyfile 1.2.4 + +# This file describes the settings to be used by doxygen for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. +#MAART: changed +PROJECT_NAME = ImgLib + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. +#MAART: changed +OUTPUT_DIRECTORY = doc + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese, +# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian, +# Polish, Portuguese and Slovene. + +OUTPUT_LANGUAGE = English + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. +# MAART: changed +EXTRACT_STATIC = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these class will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a class diagram (in Html and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. + +CLASS_DIAGRAMS = YES + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower case letters. If set to YES upper case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are adviced to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explict @brief command for a brief description. +#MAART: changed +JAVADOC_AUTOBRIEF = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# reimplements. + +INHERIT_DOCS = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# The ENABLE_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . +#C:\Documents and Settings\maarten\My Documents\develop\blender\source\blender\img + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse. + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript and frames is required (for instance Netscape 4.0+ +# or Internet explorer 4.0+). + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. +#MAART: changed +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimised for Word 97 and may not look very pretty with +# other RTF readers or editors. +#MAART: changed +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using a WORD or other. +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assigments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages +#MAART: changed +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. Warning: This feature +# is still experimental and very incomplete. + +GENERATE_XML = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tagfiles. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to +# YES then doxygen will generate a graph for each documented file showing +# the direct and indirect include dependencies of the file with other +# documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to +# YES then doxygen will generate a graph for each documented header file showing +# the documented files that directly or indirectly include this file + +INCLUDED_BY_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO + +# The CGI_NAME tag should be the name of the CGI script that +# starts the search engine (doxysearch) with the correct parameters. +# A script with this name will be generated by doxygen. + +CGI_NAME = search.cgi + +# The CGI_URL tag should be the absolute URL to the directory where the +# cgi binaries are located. See the documentation of your http daemon for +# details. + +CGI_URL = + +# The DOC_URL tag should be the absolute URL to the directory where the +# documentation is located. If left blank the absolute path to the +# documentation, with file:// prepended to it, will be used. + +DOC_URL = + +# The DOC_ABSPATH tag should be the absolute path to the directory where the +# documentation is located. If left blank the directory on the local machine +# will be used. + +DOC_ABSPATH = + +# The BIN_ABSPATH tag must point to the directory where the doxysearch binary +# is installed. + +BIN_ABSPATH = c:\program files\doxygen\bin + +# The EXT_DOC_PATHS tag can be used to specify one or more paths to +# documentation generated for other projects. This allows doxysearch to search +# the documentation for these projects as well. + +EXT_DOC_PATHS = diff --git a/intern/img/extern/IMG_Pixmap.h b/intern/img/extern/IMG_Pixmap.h new file mode 100644 index 00000000000..9d9f247e3b4 --- /dev/null +++ b/intern/img/extern/IMG_Pixmap.h @@ -0,0 +1,198 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * Abstract base class for pixmaps of different types. + * @author Maarten Gribnau + * @date March 6, 2001 + */ + +#ifndef _H_IMG_Pixmap +#define _H_IMG_Pixmap + +#include "GEN_Types.h" +#include "GEN_Rect.h" + + +class IMG_Pixmap +{ +public: + /** The type of pixels that are stored in this pixmap. */ + typedef enum { + kPixelTypeUnknown = 0, /**< R:8, G:8, B:8, Ignore:8 */ +// kPixelTypeRGB32 = 1, /**< R:8, G:8, B:8, Ignore:8 */ + kPixelTypeRGBA32 = 2, /**< R:8, G:8, B:8, Alpha:8 */ +// kPixelTypeRGB16 = 3, /**< Ignore:1, R:5, G:5, B:5 */ +// kPixelTypeRGBA16 = 4, /**< Alpha:1, R:5, G:5, B:5 */ +// kPixelTypeRGB16_565 = 5, /**< R:5, G:6, B:5 */ +// kPixelTypeRGB24 = 6 /**< R:8, G:8, B:8 */ + } TPixelType; + + /** + * Default constructor. + */ + IMG_Pixmap(); + + /** + * Constructs a pixmap with the requested width and height. + * @param width The width of the pixmap created. + * @param height The height of the pixmap created. + */ + IMG_Pixmap(GEN_TUns32 width, GEN_TUns32 height); + + /** + * Destructor. + */ + virtual ~IMG_Pixmap(); + + /** + * Access to image data + * @return pointer to the image data + */ + virtual void* getDataPtr() const = 0; + + /** + * Access to image width. + * @return width of the image + */ + inline GEN_TUns32 getWidth() const; + + /** + * Access to image height. + * @return height of the image + */ + inline GEN_TUns32 getHeight() const; + + /** + * Returns the bounds of the pixmap in a rectangle. + * @param bounds of the image + */ + inline void getBounds(GEN_Rect& r) const; + + /** + * Access to pixel type. + * @return the pixel type + */ + inline TPixelType getPixelType() const; + + /** + * Clamps coordinates inside (0, 0) and (width, height). + * @param x requested x-coordinate + * @param y requested y-coordinate + */ + inline void clamp(GEN_TInt32& x, GEN_TInt32& y) const; + + /** + * Clamps u, v coordinates between 0 and 1. + * @param u requested u-coordinate + * @param v requested v-coordinate + */ + inline void clamp(float& u, float& v) const; + + /** + * Converts (u,v) coordinates to pixel addresses. + * Assumes that (u,v) coordinates are in the [0,1] range. + * @param u requested u-coordinate in the image + * @param v requested v-coordinate in the image + * @param x calculated x-coordinate in the image + * @param y calculated y-coordinate in the image + */ + inline void getPixelAddress(float u, float v, GEN_TInt32& x, GEN_TInt32& y) const; + + /** + * Fills the rectangle given with the color given. + * Performs a bounds check. + * @param r requested bounds rectangle in the image + * @param c color to use + */ + //virtual void fillRect(const GEN_Rect& r, const IMG_ColorRGBA& c) = 0; + +protected: + /** Width of the image in pixels */ + GEN_TUns32 m_width; + /** Height of the image in pixels */ + GEN_TUns32 m_height; + /** Number of bytes for one row in the image. */ + GEN_TUns32 m_rowBytes; + /** Size in bits for one pixel */ + GEN_TUns32 m_pixelSize; + /** Type of pixels in this image. */ + TPixelType m_pixelType; +// TEndian m_bitOrder; +// TEndian m_byteOrder; +}; + +inline GEN_TUns32 IMG_Pixmap::getWidth() const +{ + return m_width; +} + +inline GEN_TUns32 IMG_Pixmap::getHeight() const +{ + return m_height; +} + +inline void IMG_Pixmap::getBounds(GEN_Rect& r) const +{ + r.set(0, 0, m_width, m_height); +} + +inline IMG_Pixmap::TPixelType IMG_Pixmap::getPixelType() const +{ + return m_pixelType; +} + +inline void IMG_Pixmap::clamp(GEN_TInt32& x, GEN_TInt32& y) const +{ + if (x < 0) x = 0; + if (x > (GEN_TInt32)m_width) x = (GEN_TInt32)m_width; + if (y < 0) y = 0; + if (y > (GEN_TInt32)m_height) y = (GEN_TInt32)m_height; +} + +inline void IMG_Pixmap::clamp(float& u, float& v) const +{ + if (u < 0.f) u = 0.f; + if (u > 1.f) u = 1.f; + if (v < 0.f) v = 0.f; + if (v > 1.f) v = 1.f; +} + +inline void IMG_Pixmap::getPixelAddress(float u, float v, GEN_TInt32& x, GEN_TInt32& y) const +{ + x = (GEN_TInt32)(((float)m_width) * u); + y = (GEN_TInt32)(((float)m_height) * v); +} + +#endif // _H_IMG_Pixmap
\ No newline at end of file diff --git a/intern/img/extern/IMG_PixmapRGBA32.h b/intern/img/extern/IMG_PixmapRGBA32.h new file mode 100644 index 00000000000..541bdcfa9a4 --- /dev/null +++ b/intern/img/extern/IMG_PixmapRGBA32.h @@ -0,0 +1,217 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * Pixmap of kPixelTypeRGBA32 type. + * A pixmap with 24 bits per pixel in ABGR format. + * Provides methods to fill rectangular areas in this image with a color. + * Provides methods to paste or blend other pixmaps into this pixmap. + * @author Maarten Gribnau + * @date March 6, 2001 + */ + + +#ifndef _H_IMG_PixmapRGBA32 +#define _H_IMG_PixmapRGBA32 + +#include "IMG_Pixmap.h" +#include "IMG_MemPtr.h" +#include "IMG_Color.h" + + +class IMG_PixmapRGBA32 : public IMG_Pixmap { +public: + /** The pixel type in this pixmap. */ + typedef GEN_TUns32 TPixelRGBA32; + + /** The pixel pointer type of this pixmap. */ + typedef TPixelRGBA32* TPixelPtr; + + /** Indices of color component byes within a pixel. */ + typedef enum { + bi_r = 0, + bi_g = 1, + bi_b = 2, + bi_a = 3 + } TPixelIndex; + + /** + * Constructor. + * Creates a new pixmap of the kPixelTypeRGBA32 type with the requested dimensions. + * @throw <IMG_MemPtr::Size> when an invalid width and/or height is passed. + * @throw <IMG_MemPtr::Memory> when a there is not enough memory to allocate the image. + * @param width the width in pixels of the image. + * @param height the height in pixels of the image. + */ + IMG_PixmapRGBA32(GEN_TUns32 width, GEN_TUns32 height); + + /** + * Constructor. + * Creates a new pixmap of the kPixelTypeRGBA32 from a pointer to image data. + * The image data will not be freed upon destruction of this object. + * The owner of this object is reponsible for that. + * @throw <Size> when an invalid width and/or height is passed. + * @param image pointer to the image data. + * @param width the width in pixels of the image. + * @param height the height in pixels of the image. + */ + IMG_PixmapRGBA32(void* image, GEN_TUns32 width, GEN_TUns32 height, GEN_TUns32 rowBytes); + +#if 0 + /** + * Destructor. + */ + virtual ~IMG_PixmapRGBA32(); +#endif + + /** + * Fills the rectangle given with the color given. + * Retains the alpha values. + * Performs a bounds check. + * @param r requested bounds rectangle in the image + * @param c color to use + */ + virtual void fillRect(const GEN_Rect& r, const IMG_ColorRGB& c); + + /** + * Fills the rectangle given with the color given. + * Sets the alpha values from the color. + * Performs a bounds check. + * @param r requested bounds rectangle in the image + * @param c color to use + */ + virtual void fillRect(const GEN_Rect& r, const IMG_ColorRGBA& c); + + /** + * Pastes an area of a pixmap into this pixmap. + * Pastes an area of the given pixmap centered at the given coordinates into this pixmap. + * Ignores the alpha information, this is pasted as well. + * Performs a bounds check. + * @param src the pixmap to paste. + * @param srcBnds the bounds of the area of the pixmap to paste. + * @param destBnds the destination area for the paste. + */ + virtual void setPixmap(const IMG_PixmapRGBA32& src, const GEN_Rect& srcBnds, const GEN_Rect& destBnds); + + /** + * Blends an area of a pixmap into this pixmap. + * Blends an area of the given pixmap centered at the given coordinates into this pixmap. + * The alpha information in the given image is used to blend. + * Performs a bounds check. + * @param src the pixmap to paste. + * @param srcBnds the bounds of the area of the pixmap to paste. + * @param destBnds the destination area for the paste. + */ + virtual void blendPixmap(const IMG_PixmapRGBA32& src, const GEN_Rect& srcBnds, const GEN_Rect& destBnds); + +protected: + /** + * Returns pointer to the pixel. + * Returns a pointer of TPixelPtr type to the pixel at the requested coordinates. + * Does not perform a bounds check! + * @param x column address of the pixel. + * @param y row address of the pixel. + * @return the pointer calculated. + */ + inline TPixelPtr getPixelPtr(GEN_TUns32 x, GEN_TUns32 y) const; + + /** + * Returns the pixel value of a color. + * @param c the color to convert + * @return the pixel value calculated + */ + inline TPixelRGBA32 getPixelValue(const IMG_ColorRGBA& c) const; + + /** + * Returns the color of from a pixel value. + * @param p the pixel value + * @param c the color calculated + */ + inline void getColor(TPixelRGBA32 p, IMG_ColorRGBA& c) const; + +protected: + /** "Save" memory pointer. */ + IMG_MemPtr<TPixelRGBA32> m_pixels; + + /** Pointer to the first pixel. */ + TPixelPtr m_pixelsBase; +}; + + +inline IMG_PixmapRGBA32::TPixelPtr IMG_PixmapRGBA32::getPixelPtr(GEN_TUns32 x, GEN_TUns32 y) const +{ + return (TPixelPtr) (((GEN_TUns8*)m_pixelsBase) + (y*m_rowBytes) + (x<<2)); +} + + +inline IMG_PixmapRGBA32::TPixelRGBA32 IMG_PixmapRGBA32::getPixelValue(const IMG_ColorRGBA& c) const +{ +#if 0 + // Obtain pixel value through shifting + TPixelRGBA32 p = ((TPixelRGBA32) (((float) 0xFF) * c.m_a)) << 24; + p |= ((TPixelRGBA32) (((float) 0xFF) * c.m_b)) << 16; + p |= ((TPixelRGBA32) (((float) 0xFF) * c.m_g)) << 8; + p |= ((TPixelRGBA32) (((float) 0xFF) * c.m_r)); + return p; +#else + // Obtain pixel value through byte indexing + TPixelRGBA32 pixel; + GEN_TUns8* bytes = (GEN_TUns8*)&pixel; + bytes[bi_r] = (GEN_TUns8)(((float) 0xFF) * c.m_r); + bytes[bi_g] = (GEN_TUns8)(((float) 0xFF) * c.m_g); + bytes[bi_b] = (GEN_TUns8)(((float) 0xFF) * c.m_b); + bytes[bi_a] = (GEN_TUns8)(((float) 0xFF) * c.m_a); + return pixel; +#endif +} + +inline void IMG_PixmapRGBA32::getColor(TPixelRGBA32 p, IMG_ColorRGBA& c) const +{ +#if 0 + // Obtain color value through shifting + c.m_a = ((float) ((p >> 24) & 0x00FF)) / ((float) 0xFF); + c.m_b = ((float) ((p >> 16) & 0x00FF)) / ((float) 0xFF); + c.m_g = ((float) ((p >> 8) & 0x00FF)) / ((float) 0xFF); + c.m_r = ((float) ( p & 0x00FF)) / ((float) 0xFF); +#else + // Obtain color value through byte indexing + GEN_TUns8* bytes = (GEN_TUns8*)&p; + c.m_r = ((float)bytes[bi_r]) / ((float) 0xFF); + c.m_g = ((float)bytes[bi_g]) / ((float) 0xFF); + c.m_b = ((float)bytes[bi_b]) / ((float) 0xFF); + c.m_a = ((float)bytes[bi_a]) / ((float) 0xFF); +#endif +} + +#endif // _H_IMG_PixmapRGBA32
\ No newline at end of file diff --git a/intern/img/intern/IMG_Color.h b/intern/img/intern/IMG_Color.h new file mode 100644 index 00000000000..9e6ef5c74fc --- /dev/null +++ b/intern/img/intern/IMG_Color.h @@ -0,0 +1,144 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * Declaration of an RGB color with red, green and blue components. + * Declaration of an RGBA color with red, green, blue and alpha components. + * Components are stored as floats. + * @author Maarten Gribnau + * @date March 7, 2001 + */ + +#ifndef _H_IMG_Color +#define _H_IMG_Color + +class IMG_ColorRGBA; + + +class IMG_ColorRGB { +public: + /** + * Constructs a color with the given values. + * @param r requested red component of the color + * @param g requested green component of the color + * @param b requested blue component of the color + */ + IMG_ColorRGB(float r=0, float g=0, float b=0) + : m_r(r), m_g(g), m_b(b) {} + + /** + * Copy constructor. + * @param c the color to copy. + */ + IMG_ColorRGB(const IMG_ColorRGB& c) + : m_r(c.m_r), m_g(c.m_g), m_b(c.m_b) {} + + /** + * Constructs a color without alpha from one with. + * @param c the color to copy. + */ + inline IMG_ColorRGB(const IMG_ColorRGBA& c); + + /** Red component of the color */ + float m_r; + /** Green component of the color */ + float m_g; + /** Blue component of the color */ + float m_b; +}; + + +class IMG_ColorRGBA { +public: + /** + * Constructs a color with the given values. + * @param r requested red component of the color + * @param g requested green component of the color + * @param b requested blue component of the color + * @param a requested alpha component of the color + */ + IMG_ColorRGBA(float r=0, float g=0, float b=0, float a=0) + : m_r(r), m_g(g), m_b(b), m_a(a) {} + + /** + * Copy constructor. + * @param c the color to copy. + */ + IMG_ColorRGBA(const IMG_ColorRGBA& c) + : m_r(c.m_r), m_g(c.m_g), m_b(c.m_b), m_a(c.m_a) {} + + /** + * Constructs a color with alpha from one without. + * @param c the color to copy. + */ + IMG_ColorRGBA(const IMG_ColorRGB& c) + : m_r(c.m_r), m_g(c.m_g), m_b(c.m_b), m_a(0) {} + + /** + * Blends the given color with this color. + * Uses the alpha of the given color for blending. + * The alpha of this color is left untouched. + * @param c the color to blend + */ + inline void blendColor(const IMG_ColorRGBA& c); + + /** Red component of the color */ + float m_r; + /** Green component of the color */ + float m_g; + /** Blue component of the color */ + float m_b; + /** Alpha component of the color */ + float m_a; +}; + +inline IMG_ColorRGB::IMG_ColorRGB(const IMG_ColorRGBA& c) + : m_r(c.m_r), m_g(c.m_g), m_b(c.m_b) {} + +inline void IMG_ColorRGBA::blendColor(const IMG_ColorRGBA& c) +{ + float r1 = 1 - c.m_a; // The reverse of alpha +#if IMG_REVERSED_ALPHA + m_r = c.m_a * m_r + r1 * c.m_r; + m_g = c.m_a * m_g + r1 * c.m_g; + m_b = c.m_a * m_b + r1 * c.m_b; +#else + m_r = r1 * m_r + c.m_a * c.m_r; + m_g = r1 * m_g + c.m_a * c.m_g; + m_b = r1 * m_b + c.m_a * c.m_b; +#endif +} + + +#endif // _H_IMG_Color
\ No newline at end of file diff --git a/intern/img/intern/IMG_MemPtr.h b/intern/img/intern/IMG_MemPtr.h new file mode 100644 index 00000000000..e81a5b5c873 --- /dev/null +++ b/intern/img/intern/IMG_MemPtr.h @@ -0,0 +1,117 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * @author Maarten Gribnau + * @date March 8, 2001 + */ + +#ifndef _H_IMG_MemPtr +#define _H_IMG_MemPtr + +#include <stddef.h> + +/** + * A memory pointer for memory of any type. + * It can be used to avoid memory leaks when allocating memory in constructors. + * @author Maarten Gribnau + * @date March 8, 2001 + */ + +template <class T> class IMG_MemPtr { +public: + /** Pointer to the memory */ + T* m_p; + bool m_owned; + + /** + * Size exception. + * A size exception is thrown when an invalid width and/or height is passed. + */ + class Size {}; + /** + * Memory exception. + * A size exception is thrown when a there is not enough memory to allocate the image. + */ + class Memory {}; + + /** + * Constructs a memory pointer. + * @param s requested size of the pointer + * @throw <Size> when an invalid width and/or height is passed. + * @throw <Memory> when a there is not enough memory to allocate the image. + */ + IMG_MemPtr(size_t s) + : m_p(0), m_owned(false) + { + if (s > 0) { + m_p = new T[s]; + if (!m_p) { + throw Memory(); + } + m_owned = true; + } + else { + throw Size(); + } + } + + /** + * Constructs a memory pointer from a pointer. + * @param p the pointer + * @param s requested size of the pointer + * @throw <Size> when an invalid width and/or height is passed. + */ + IMG_MemPtr(void* p, size_t s) + : m_p(0), m_owned(false) + { + if (p && (s > 0)) { + m_p = (T*)p; + } + else { + throw Size(); + } + } + + /** + * Destructor. + */ + ~IMG_MemPtr() { if (m_p && m_owned) { delete [] m_p; m_p = 0; } } + + /** + * Access to the memory. + * @return pointer to the memory + */ + operator T*() { return m_p; } +}; + +#endif // _H_IMG_MemPtr
\ No newline at end of file diff --git a/intern/img/intern/IMG_Pixmap.cpp b/intern/img/intern/IMG_Pixmap.cpp new file mode 100644 index 00000000000..74888647b75 --- /dev/null +++ b/intern/img/intern/IMG_Pixmap.cpp @@ -0,0 +1,85 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * Base class for pixmaps. + * @author Maarten Gribnau + * @date March 6, 2001 + */ + + +#include "../extern/IMG_Pixmap.h" + + +IMG_Pixmap::IMG_Pixmap() +{ + m_width = 0; + m_height = 0; + m_rowBytes = 0; + m_pixelSize = 0; + m_pixelType = kPixelTypeUnknown; +/* +#if OS_MACINTOSH + bitOrder = kQ3EndianBig; + byteOrder = kQ3EndianBig; +#else + bitOrder = kQ3EndianLittle; + byteOrder = kQ3EndianLittle; +#endif +*/ +} + + +IMG_Pixmap::IMG_Pixmap(GEN_TUns32 width, GEN_TUns32 height) +{ + m_width = width; + m_height = height; + m_rowBytes = 0; + m_pixelSize = 0; + m_pixelType = kPixelTypeUnknown; +/* +#if OS_MACINTOSH + bitOrder = kQ3EndianBig; + byteOrder = kQ3EndianBig; +#else + bitOrder = kQ3EndianLittle; + byteOrder = kQ3EndianLittle; +#endif +*/ +} + + +IMG_Pixmap::~IMG_Pixmap() +{ +}
\ No newline at end of file diff --git a/intern/img/intern/IMG_PixmapRGBA32.cpp b/intern/img/intern/IMG_PixmapRGBA32.cpp new file mode 100644 index 00000000000..a7b70e03616 --- /dev/null +++ b/intern/img/intern/IMG_PixmapRGBA32.cpp @@ -0,0 +1,260 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * Base class for pixmaps. + * @author Maarten Gribnau + * @date March 6, 2001 + */ + + +#include "../extern/IMG_PixmapRGBA32.h" + +IMG_PixmapRGBA32::IMG_PixmapRGBA32(GEN_TUns32 width, GEN_TUns32 height) + : IMG_Pixmap(), m_pixels(width * height) +{ + m_pixelsBase = m_pixels; + m_width = width; + m_height = height; + m_rowBytes = width * sizeof(TPixelRGBA32); + m_pixelSize = 32; + m_pixelType = kPixelTypeRGBA32; +} + + +IMG_PixmapRGBA32::IMG_PixmapRGBA32(void* image, GEN_TUns32 width, GEN_TUns32 height, GEN_TUns32 rowBytes) + : IMG_Pixmap(), m_pixels(image, width * rowBytes) +{ + m_pixelsBase = m_pixels; + m_width = width; + m_height = height; + m_rowBytes = rowBytes; + m_pixelSize = 32; + m_pixelType = kPixelTypeRGBA32; +} + + +void IMG_PixmapRGBA32::fillRect(const GEN_Rect& r, const IMG_ColorRGB& c) +{ + GEN_Rect t_bnds (0, 0, m_width, m_height); // Bounds of this pixmap + GEN_Rect r_bnds (r); // Area to set + + // Determine visibility + GEN_TVisibility v = t_bnds.getVisibility(r_bnds); + if (v == GEN_kNotVisible) return; + if (v == GEN_kPartiallyVisible) { + // Clip the destination rectangle to the bounds of this pixmap + t_bnds.clip(r_bnds); + if (r_bnds.isEmpty()) { + return; + } + } + +#if 0 + // Set new pixels using shifting + // Prepare the pixel value to set + IMG_ColorRGBA ca (c); + TPixelRGBA32 pv = getPixelValue(c); + // Mask off the alpha bits + pv &= 0x00FFFFFF; //0xFFFFFF00; + + // Set the pixels in the destination rectangle + for (GEN_TInt32 y = r.m_t; y < r.m_b; y++) { + // Park pixel pointer at the start pixels + TPixelPtr desPtr = getPixelPtr(r_bnds.m_l, y); + for (GEN_TInt32 x = r.m_l; x < r.m_r; x++) { + // Set the new pixel value (retain current alpha) + *(desPtr++) = pv | ((*desPtr) & 0xFF000000); //0x000000FF); + } + } +#else + // Set new values using byte indexing + //IMG_ColorRGBA ca (c); + TPixelRGBA32 src = getPixelValue(c); + TPixelPtr desPtr; + GEN_TUns8* srcBytes = (GEN_TUns8*) &src; + + // Set the pixels in the destination rectangle + for (GEN_TInt32 y = r.m_t; y < r.m_b; y++) { + // Park pixel pointer at the start pixels + desPtr = getPixelPtr(r_bnds.m_l, y); + for (GEN_TInt32 x = r.m_l; x < r.m_r; x++) { + // Set the new pixel value (retain current alpha) + ((GEN_TUns8*)desPtr)[bi_r] = srcBytes[bi_r]; + ((GEN_TUns8*)desPtr)[bi_g] = srcBytes[bi_g]; + ((GEN_TUns8*)desPtr)[bi_b] = srcBytes[bi_b]; + desPtr++; + } + } +#endif +} + + +void IMG_PixmapRGBA32::fillRect(const GEN_Rect& r, const IMG_ColorRGBA& c) +{ + GEN_Rect t_bnds (0, 0, m_width, m_height); // Bounds of this pixmap + GEN_Rect r_bnds (r); // Area to set + + // Determine visibility + GEN_TVisibility v = t_bnds.getVisibility(r_bnds); + if (v == GEN_kNotVisible) return; + if (v == GEN_kPartiallyVisible) { + // Clip the destination rectangle to the bounds of this pixmap + t_bnds.clip(r_bnds); + if (r_bnds.isEmpty()) { + return; + } + } + + // Set the pixels in the destination rectangle + TPixelRGBA32 pixel = getPixelValue(c); + for (GEN_TInt32 y = r.m_t; y < r.m_b; y++) { + // Park pixel pointer at the start pixels + TPixelPtr desPtr = getPixelPtr(r_bnds.m_l, y); + for (GEN_TInt32 x = r.m_l; x < r.m_r; x++) { + *(desPtr++) = pixel; + } + } +} + + +void IMG_PixmapRGBA32::setPixmap(const IMG_PixmapRGBA32& src, const GEN_Rect& srcBnds, const GEN_Rect& destBnds) +{ + GEN_Rect i_bnds (srcBnds); // Bounds of input pixmap + GEN_Rect t_bnds (0, 0, m_width, m_height); // Bounds of this pixmap + GEN_Rect p_bnds (destBnds); // Bounds of the paste area + + // The next check could be removed if the caller is made responsible for handing us non-empty rectangles + if (i_bnds.isEmpty()) { + // Nothing to do + return; + } + + // Determine visibility of the paste area + GEN_TVisibility v = t_bnds.getVisibility(p_bnds); + if (v == GEN_kNotVisible) return; + if (v == GEN_kPartiallyVisible) { + // Clipping is needed + if (p_bnds.m_l < 0) { + i_bnds.m_l += -p_bnds.m_l; + p_bnds.m_l = 0; + } + if (p_bnds.m_t < 0) { + i_bnds.m_t += -p_bnds.m_t; + p_bnds.m_t = 0; + } + GEN_TInt32 d = t_bnds.getWidth(); + if (p_bnds.m_r > d) { + i_bnds.m_r -= d - p_bnds.m_r; + p_bnds.m_r = d; + } + d = t_bnds.getHeight(); + if (p_bnds.m_b > d) { + i_bnds.m_b -= d - p_bnds.m_b; + p_bnds.m_b = d; + } + } + + // Iterate through the rows + for (GEN_TInt32 r = 0; r < p_bnds.getHeight(); r++) { + // Park pixel pointers at the start pixels + TPixelPtr srcPtr = src.getPixelPtr(i_bnds.m_l, i_bnds.m_t + r); + TPixelPtr desPtr = getPixelPtr(p_bnds.m_l, p_bnds.m_t + r); + // Iterate through the columns + for (int c = 0; c < p_bnds.getWidth(); c++) { + *(desPtr++) = *(srcPtr++); + } + } +} + + +void IMG_PixmapRGBA32::blendPixmap(const IMG_PixmapRGBA32& src, const GEN_Rect& srcBnds, const GEN_Rect& destBnds) +{ + GEN_Rect i_bnds (srcBnds); // Bounds of input pixmap + GEN_Rect t_bnds (0, 0, m_width, m_height); // Bounds of this pixmap + GEN_Rect p_bnds (destBnds); // Bounds of the paste area + + // The next check could be removed if the caller is made responsible for handing us non-empty rectangles + if (i_bnds.isEmpty()) { + // Nothing to do + return; + } + + // Determine visibility of the paste area + GEN_TVisibility v = t_bnds.getVisibility(p_bnds); + if (v == GEN_kNotVisible) return; + if (v == GEN_kPartiallyVisible) { + // Clipping is needed + if (p_bnds.m_l < 0) { + i_bnds.m_l += -p_bnds.m_l; + p_bnds.m_l = 0; + } + if (p_bnds.m_t < 0) { + i_bnds.m_t += -p_bnds.m_t; + p_bnds.m_t = 0; + } + GEN_TInt32 d = t_bnds.getWidth(); + if (p_bnds.m_r > d) { + i_bnds.m_r -= p_bnds.m_r - d; + p_bnds.m_r = d; + } + d = t_bnds.getHeight(); + if (p_bnds.m_b > d) { + i_bnds.m_b -= p_bnds.m_b - d; + p_bnds.m_b = d; + } + } + + IMG_ColorRGBA srcColor; + IMG_ColorRGBA desColor; + + // Iterate through the rows + for (int r = 0; r < p_bnds.getHeight(); r++) { + // Park pixel pointers at the start pixels + TPixelPtr srcPtr = src.getPixelPtr(i_bnds.m_l, i_bnds.m_t + r); + TPixelPtr desPtr = getPixelPtr(p_bnds.m_l, p_bnds.m_t + r); + // Iterate through the columns + for (int c = 0; c < p_bnds.getWidth(); c++) { + // Retrieve colors from source and destination pixmaps + getColor(*srcPtr, srcColor); + getColor(*desPtr, desColor); + // Blend the colors + desColor.blendColor(srcColor); + // Write color back to destination pixmap + *desPtr = getPixelValue(desColor); + srcPtr++; + desPtr++; + } + } +} diff --git a/intern/img/intern/Makefile b/intern/img/intern/Makefile new file mode 100644 index 00000000000..824699f49bc --- /dev/null +++ b/intern/img/intern/Makefile @@ -0,0 +1,43 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# Makefile for the img library + +LIBNAME = img +DIR = $(OCGDIR)/intern/$(LIBNAME) + +include nan_compile.mk + +CCFLAGS += $(LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I../../generic/extern +CPPFLAGS += -I../extern +CPPFLAGS += -I../intern + diff --git a/intern/img/make/msvc/img.dsp b/intern/img/make/msvc/img.dsp new file mode 100644 index 00000000000..5110bdbb200 --- /dev/null +++ b/intern/img/make/msvc/img.dsp @@ -0,0 +1,126 @@ +# Microsoft Developer Studio Project File - Name="img" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=img - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "img.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "img.mak" CFG="img - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "img - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "img - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "img - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\..\..\..\obj\img\windows\" +# PROP Intermediate_Dir "..\..\..\..\..\obj\img\windows\" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../generic/extern" /I "../extern" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "img - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\..\..\..\obj\img\windows\debug" +# PROP Intermediate_Dir "..\..\..\..\..\obj\img\windows\debug" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../generic/extern" /I "../extern" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "img - Win32 Release" +# Name "img - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\intern\IMG_Pixmap.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\IMG_PixmapRGBA32.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Group "intern" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\intern\IMG_Color.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\IMG_MemPtr.h +# End Source File +# End Group +# Begin Group "extern" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\extern\IMG_Pixmap.h +# End Source File +# Begin Source File + +SOURCE=..\..\extern\IMG_PixmapRGBA32.h +# End Source File +# End Group +# End Group +# End Target +# End Project diff --git a/intern/img/make/msvc/img.dsw b/intern/img/make/msvc/img.dsw new file mode 100644 index 00000000000..433f994ce5c --- /dev/null +++ b/intern/img/make/msvc/img.dsw @@ -0,0 +1,41 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "generic"="..\..\..\generic\make\msvc\generic.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "img"=".\img.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/intern/memutil/MEM_NonCopyable.h b/intern/memutil/MEM_NonCopyable.h new file mode 100644 index 00000000000..88284d53803 --- /dev/null +++ b/intern/memutil/MEM_NonCopyable.h @@ -0,0 +1,59 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_NonCopyable_h + +#define NAN_INCLUDED_NonCopyable_h + +/** + * Simple class that makes sure sub classes cannot + * generate standard copy constructors. + * If you want to make sure that your class does + * not have any of these cheesy hidden constructors + * inherit from this class. + */ + +class MEM_NonCopyable { +protected : + + MEM_NonCopyable( + ) { + }; + +private : + + MEM_NonCopyable (const MEM_NonCopyable *); + MEM_NonCopyable (const MEM_NonCopyable &); +}; + +#endif + + diff --git a/intern/memutil/MEM_RefCountPtr.h b/intern/memutil/MEM_RefCountPtr.h new file mode 100644 index 00000000000..fb563109087 --- /dev/null +++ b/intern/memutil/MEM_RefCountPtr.h @@ -0,0 +1,294 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_MEM_RefCountPtr_h + +#define NAN_INCLUDED_MEM_RefCountPtr_h + +/** + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * + * @author Laurence + */ + +#include <stdlib.h> // for NULL ! + +/** + * @section MEM_RefCountable + * This is a base class for reference countable objects. + * If you want an object to be shared using a reference + * counted system derrivce from this class. All subclasses + * should insist that they are created on the heap, this + * can be done by makeing all constructors private and + * defining a static New() method that returns a ref counted + * ptr to a new()ly allocated instance. + * + * @section Example subclass + * + * + * class MySharedObject : public MEM_RefCountable { + * + * private : + * MySharedObject() : MEM_RefCountable() { //class specific initialization}; + * MySharedObject(const MySharedObject &other) // not implemented + * public : + * static + * MEM_RefCountPtr<MySharedObject> + * New( + * ) { + * return MEM_RefCountPtr<MySharedObject>( new MySharedObject()); + * } + * + * // other member functions + * }; + * + * Alternitively you may first wish to define a fully functional + * class and then define a reference counting wrapper for this class. + * This is useful when the base type can be used without reference + * counting. + * + * E.g. + * class UsefullClass { + * private : + * ... + * public : + * + * UsefullClass() + * UsefullMethod(...) + * AnotherUsefullMethod(...) + * }; + * + * class RcUsefullClass : public UsefullClass, public MEM_RefCountable + * { + * private : + * // Override base class public constructor --- forces + * // use of New(...) + * RcUsefullClass(...) + * public : + * + * // Override each public constructor of UsefullClass with + * // an equivalent static New method returning a MEM_RefCountPtr + * + * static + * MEM_RefCountPtr<RcUsefullClass> + * New(...){ + * return MEM_RefCountPtr<RcUsefullClass> output( + * new UsefullClass(...) + * ); + * } + * + * // warning never call destructor directly allow ref counting + * // mechanism to handle object lifetime. + * ~RcUsefullClass(); + * }; + * + * + */ + +class MEM_RefCountable { +private : + + /** + * The reference count! + * We use mutable here because we would like to + * share references of const objects! + * Maybe should think about having decRef() + * another value because we should not be deleting + * non-const objects + */ + + mutable int m_count; + +protected : + + /** + * Protected constructors + * This class is not for direct instanciation. Sub classes + * should only be allocated on the heap. + */ + + MEM_RefCountable ( + ) : + m_count (0) + { + }; + + MEM_RefCountable ( + const MEM_RefCountable & other + ) : + m_count (0) + { + } + +public : + + void + IncRef( + ) const { + m_count++; + } + + int + DecRef( + ) { + return (--m_count); + } + + ~MEM_RefCountable( + ) { + //nothing to do + } +}; + +/** + * @section MEM_RefCountPtr + */ + +template + < class T > +class MEM_RefCountPtr { + +public : + + /** + * Construction from reference - share ownership with + * the right hand side. + */ + + MEM_RefCountPtr( + const MEM_RefCountPtr &rhs + ) : m_val (NULL) { + ShareOwnership(rhs.m_val); + } + + /** + * Construction from ptr - this class shares + * ownership of object val. + */ + + MEM_RefCountPtr( + const T* val + ) : + m_val (NULL) + { + ShareOwnership(val); + } + + /** + * Defalut constructor + */ + + MEM_RefCountPtr( + ) : + m_val (NULL) + { + } + + /** + * Type conversion from this class to the type + * of a pointer to the template parameter. + * This means you can pass an instance of this class + * to a function expecting a ptr of type T. + */ + + operator T * () const { + return m_val; + } + + + MEM_RefCountPtr & operator=( + const MEM_RefCountPtr &rhs + ) { + if (this->m_val != rhs.m_val) { + ReleaseOwnership(); + ShareOwnership(rhs.m_val); + } + return *this; + } + + /** + * Overload the operator -> so that it's possible to access + * all the normal methods of the internal ptr. + */ + + T * operator->() const { + return m_val; + } + + /** + * Returrn a reference to the shared object. + */ + + T& + Ref( + ) { + return *m_val; + } + + /** + * Destructor - deletes object if it's ref count is zero. + */ + + ~MEM_RefCountPtr( + ) { + ReleaseOwnership(); + } + +private : + + /// The ptr owned by this class. + T * m_val; + + void + ShareOwnership( + const T * val + ) { + if (val != NULL) { + val->IncRef(); + } + m_val = const_cast<T *>(val); + } + + void + ReleaseOwnership( + ) { + if (m_val) { + if (m_val->DecRef() == 0) { + delete(m_val); + m_val = NULL; + } + } + } + +}; + +#endif diff --git a/intern/memutil/MEM_RefCounted.h b/intern/memutil/MEM_RefCounted.h new file mode 100644 index 00000000000..3531f700ee3 --- /dev/null +++ b/intern/memutil/MEM_RefCounted.h @@ -0,0 +1,120 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date March 31, 2001 + */ + +#ifndef _H_MEM_REF_COUNTED +#define _H_MEM_REF_COUNTED + + +/** + * An object with reference counting. + * Base class for objects with reference counting. + * When a shared object is ceated, it has reference count == 1. + * If the the reference count of a shared object reaches zero, the object self-destructs. + * The default destructor of this object has been made protected on purpose. + * This disables the creation of shared objects on the stack. + * + * @author Maarten Gribnau + * @date March 31, 2001 + */ + +class MEM_RefCounted { +public: + /** + * Constructs a a shared object. + */ + MEM_RefCounted() : m_refCount(1) + { + } + + /** + * Returns the reference count of this object. + * @return the reference count. + */ + inline virtual int getRef() const; + + /** + * Increases the reference count of this object. + * @return the new reference count. + */ + inline virtual int incRef(); + + /** + * Decreases the reference count of this object. + * If the the reference count reaches zero, the object self-destructs. + * @return the new reference count. + */ + inline virtual int decRef(); + +protected: + /** + * Destructs a shared object. + * The destructor is protected to force the use of incRef and decRef. + */ + virtual ~MEM_RefCounted() + { + } + +protected: + /// The reference count. + int m_refCount; +}; + + +inline int MEM_RefCounted::getRef() const +{ + return m_refCount; +} + +inline int MEM_RefCounted::incRef() +{ + return ++m_refCount; +} + +inline int MEM_RefCounted::decRef() +{ + m_refCount--; + if (m_refCount == 0) { + delete this; + return 0; + } + return m_refCount; +} + + +#endif // _H_MEM_REF_COUNTED
\ No newline at end of file diff --git a/intern/memutil/MEM_RefCountedC-Api.h b/intern/memutil/MEM_RefCountedC-Api.h new file mode 100644 index 00000000000..abaef47604c --- /dev/null +++ b/intern/memutil/MEM_RefCountedC-Api.h @@ -0,0 +1,90 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * Interface for C access to functionality relating to shared objects in the foundation library. + * @author Maarten Gribnau + * @date June 17, 2001 + */ + +#ifndef _H_MEM_REF_COUNTED_C_API +#define _H_MEM_REF_COUNTED_C_API + +/** A pointer to a private object. */ +typedef struct MEM_TOpaqueObject* MEM_TObjectPtr; +/** A pointer to a shared object. */ +typedef MEM_TObjectPtr MEM_TRefCountedObjectPtr; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * A shared object in an object with reference counting. + * When a shared object is ceated, it has reference count == 1. + * If the the reference count of a shared object reaches zero, the object self-destructs. + * The default constrcutor and destructor of this object have been made protected on purpose. + * This disables the creation and disposal of shared objects on the stack. + */ + +/** + * Returns the reference count of this object. + * @param shared The object to query. + * @return The current reference count. + */ +extern int MEM_RefCountedGetRef(MEM_TRefCountedObjectPtr shared); + +/** + * Increases the reference count of this object. + * @param shared The object to query. + * @return The new reference count. + */ +extern int MEM_RefCountedIncRef(MEM_TRefCountedObjectPtr shared); + +/** + * Decreases the reference count of this object. + * If the the reference count reaches zero, the object self-destructs. + * @param shared The object to query. + * @return The new reference count. + */ +extern int MEM_RefCountedDecRef(MEM_TRefCountedObjectPtr shared); + + +#ifdef __cplusplus +} +#endif + +#endif // _H_MEM_REF_COUNTED_C_API
\ No newline at end of file diff --git a/intern/memutil/MEM_SmartPtr.h b/intern/memutil/MEM_SmartPtr.h new file mode 100644 index 00000000000..b47b2bdc1a4 --- /dev/null +++ b/intern/memutil/MEM_SmartPtr.h @@ -0,0 +1,240 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_MEM_SmartPtr_h + +#define NAN_INCLUDED_MEM_SmartPtr_h + +/** + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * + * @author Laurence + */ + +#include <stdlib.h> // for NULL ! + +/** + * @section MEM_SmartPtr + * This class defines a smart pointer similar to that defined in + * the Standard Template Library but without the painful get() + * semantics to access the internal c style pointer. + * + * It is often useful to explicitely decalre ownership of memory + * allocated on the heap within class or function scope. This + * class helps you to encapsulate this ownership within a value + * type. When an instance of this class goes out of scope it + * makes sure that any memory associated with it's internal pointer + * is deleted. It can help to inform users of an aggregate class + * that it owns instances of it's members and these instances + * should not be shared. This is not reliably enforcable in C++ + * but this class attempts to make the 1-1 relationship clear. + * + * @section Example usage + * + * class foo { + * ...constructors accessors etc. + * int x[1000]; + * } + * + * class bar { + * public : + * static + * bar * + * New( + * ) { + * MEM_SmartPtr<foo> afoo = new foo(); + * MEM_SmartPtr<bar> that = new bar(); + * + * if (foo == NULL || that == NULL) return NULL; + * + * that->m_foo = afoo.Release(); + * return that.Release(); + * } + * + * ~bar() { + * // smart ptr takes care of deletion + * } + * private : + * MEM_SmartPtr<foo> m_foo; + * } + * + * You my also safely construct vectors of MEM_SmartPtrs and + * have the vector own stuff you put into it. + * + * e.g. + * { + * std::vector<MEM_SmartPtr<foo> > foo_vector; + * foo_vector.push_back( new foo()); + * foo_vector.push_back( new foo()); + * + * foo_vector[0]->bla(); + * } // foo_vector out of scope => heap memory freed for both foos + * + * @warning this class should only be used for objects created + * on the heap via the new function. It will not behave correctly + * if you pass ptrs to objects created with new[] nor with + * objects declared on the stack. Doing this is likely to crash + * the program or lead to memory leaks. + */ + +template + < class T > +class MEM_SmartPtr { + +public : + + /** + * Construction from reference - this class + * always assumes ownership from the rhs. + */ + + MEM_SmartPtr( + const MEM_SmartPtr &rhs + ){ + m_val = rhs.Release(); + } + + /** + * Construction from ptr - this class always + * assumes that it now owns the memory associated with the + * ptr. + */ + + MEM_SmartPtr( + T* val + ) : + m_val (val) + { + } + + /** + * Defalut constructor + */ + + MEM_SmartPtr( + ) : + m_val (NULL) + { + } + + /** + * Type conversion from this class to the type + * of a pointer to the template parameter. + * This means you can pass an instance of this class + * to a function expecting a ptr of type T. + */ + + operator T * () const { + return m_val; + } + + /** + * Return a reference to the internal ptr class. + * Use with care when you now that the internal ptr + * is not NULL! + */ + + T & + Ref( + ) const { + return *m_val; + } + + /** + * Assignment operator - ownership is transfered from rhs to lhs. + * There is an intenional side-effect of function of transferring + * ownership from the const parameter rhs. This is to insure + * the 1-1 relationship. + * The object associated with this instance is deleted if it + * is not the same as that contained in the rhs. + */ + + MEM_SmartPtr & operator=( + const MEM_SmartPtr &rhs + ) { + if (this->m_val != rhs.m_val) { + delete this->m_val; + } + + this->m_val = rhs.Release(); + return *this; + } + + /** + * Overload the operator -> so that it's possible to access + * all the normal methods of the internal ptr. + */ + + T * operator->() const { + return m_val; + } + + /** + * Caller takes ownership of the object - the object will not + * be deleted when the ptr goes out of scope. + */ + + T * + Release( + ) const { + T* temp = m_val; + (const_cast<MEM_SmartPtr *>(this))->m_val = NULL; + return temp; + } + + /** + * Force destruction of the internal object. + */ + + void + Delete( + ) { + delete (m_val); + m_val = NULL; + } + + /** + * Destructor - deletes object if it exists + */ + + ~MEM_SmartPtr( + ) { + delete (m_val); + } + +private : + + /// The ptr owned by this class. + T * m_val; +}; + +#endif diff --git a/intern/memutil/Makefile b/intern/memutil/Makefile new file mode 100644 index 00000000000..e163fa63eff --- /dev/null +++ b/intern/memutil/Makefile @@ -0,0 +1,52 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# memutil main makefile. +# + +include nan_definitions.mk + +LIBNAME = memutil +SOURCEDIR = intern/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = intern +#not yet TESTDIRS = test + +include nan_subdirs.mk + +install: all debug + @[ -d $(NAN_MEMUTIL) ] || mkdir $(NAN_MEMUTIL) + @[ -d $(NAN_MEMUTIL)/include ] || mkdir $(NAN_MEMUTIL)/include + @[ -d $(NAN_MEMUTIL)/lib ] || mkdir $(NAN_MEMUTIL)/lib + @[ -d $(NAN_MEMUTIL)/lib/debug ] || mkdir $(NAN_MEMUTIL)/lib/debug + cp -f $(DIR)/libmemutil.a $(NAN_MEMUTIL)/lib/ + cp -f $(DIR)/debug/libmemutil.a $(NAN_MEMUTIL)/lib/debug + cp -f *.h $(NAN_MEMUTIL)/include/ + diff --git a/intern/memutil/intern/MEM_RefCountedC-Api.cpp b/intern/memutil/intern/MEM_RefCountedC-Api.cpp new file mode 100644 index 00000000000..92f02ac78fa --- /dev/null +++ b/intern/memutil/intern/MEM_RefCountedC-Api.cpp @@ -0,0 +1,64 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date Jun 17, 2001 + */ + +#include "MEM_RefCountedC-Api.h" + +#include "MEM_RefCounted.h" + + + +int MEM_RefCountedGetRef(MEM_TRefCountedObjectPtr shared) +{ + return shared ? ((MEM_RefCounted*)shared)->getRef() : 0; +} + + +int MEM_RefCountedIncRef(MEM_TRefCountedObjectPtr shared) +{ + return shared ? ((MEM_RefCounted*)shared)->incRef() : 0; +} + + +int MEM_RefCountedDecRef(MEM_TRefCountedObjectPtr shared) +{ + return shared ? ((MEM_RefCounted*)shared)->decRef() : 0; +} + + + diff --git a/intern/memutil/intern/Makefile b/intern/memutil/intern/Makefile new file mode 100644 index 00000000000..0d0d3af6327 --- /dev/null +++ b/intern/memutil/intern/Makefile @@ -0,0 +1,42 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# memutil intern Makefile +# + +LIBNAME = memutil +DIR = $(OCGDIR)/intern/$(LIBNAME) + +include nan_compile.mk + +CCFLAGS += $(LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I.. + diff --git a/intern/memutil/make/msvc_60/memutil.dsp b/intern/memutil/make/msvc_60/memutil.dsp new file mode 100644 index 00000000000..85e903f8764 --- /dev/null +++ b/intern/memutil/make/msvc_60/memutil.dsp @@ -0,0 +1,134 @@ +# Microsoft Developer Studio Project File - Name="memutil" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=memutil - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "memutil.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "memutil.mak" CFG="memutil - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "memutil - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "memutil - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "memutil - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../../../../obj/windows/intern/memutil" +# PROP Intermediate_Dir "../../../../../obj/windows/intern/memutil" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "../.." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Release\memutil.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\lib\windows\memutil\include" ECHO Copying lib COPY "Release\memutil.lib" "..\..\..\..\lib\windows\memutil\lib\memutil.a" ECHO Done +# End Special Build Tool + +!ELSEIF "$(CFG)" == "memutil - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../../../../obj/windows/intern/memutil/debug" +# PROP Intermediate_Dir "../../../../../obj/windows/intern/memutil/debug" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../.." /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\memutil.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\lib\windows\memutil\include" ECHO Copying lib COPY "Debug\memutil.lib" "..\..\..\..\lib\windows\memutil\lib\debug\memutil.a" ECHO Copying Debug info. COPY "Debug\vc60.*" "..\..\..\..\lib\windows\memutil\lib\debug\" ECHO Done +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "memutil - Win32 Release" +# Name "memutil - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\..\intern\MEM_RefCountedC-Api.cpp" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Group "intern" + +# PROP Default_Filter "" +# End Group +# Begin Group "extern" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\MEM_NonCopyable.h +# End Source File +# Begin Source File + +SOURCE=..\..\MEM_RefCounted.h +# End Source File +# Begin Source File + +SOURCE="..\..\MEM_RefCountedC-Api.h" +# End Source File +# Begin Source File + +SOURCE=..\..\MEM_RefCountPtr.h +# End Source File +# Begin Source File + +SOURCE=..\..\MEM_SmartPtr.h +# End Source File +# End Group +# End Group +# End Target +# End Project diff --git a/intern/memutil/make/msvc_60/memutil.dsw b/intern/memutil/make/msvc_60/memutil.dsw new file mode 100644 index 00000000000..2ac4d9e7a48 --- /dev/null +++ b/intern/memutil/make/msvc_60/memutil.dsw @@ -0,0 +1,30 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + + +############################################################################### + +Project: "memutil"=".\memutil.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/intern/moto/Makefile b/intern/moto/Makefile new file mode 100644 index 00000000000..97b4b321d99 --- /dev/null +++ b/intern/moto/Makefile @@ -0,0 +1,52 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# moto main makefile. +# + +include nan_definitions.mk + +LIBNAME = moto +SOURCEDIR = intern/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = intern +#not ready yet TESTDIRS = test + +include nan_subdirs.mk + +install: all debug + @[ -d $(NAN_MOTO) ] || mkdir $(NAN_MOTO) + @[ -d $(NAN_MOTO)/include ] || mkdir $(NAN_MOTO)/include + @[ -d $(NAN_MOTO)/lib ] || mkdir $(NAN_MOTO)/lib + @[ -d $(NAN_MOTO)/lib/debug ] || mkdir $(NAN_MOTO)/lib/debug + cp -f $(DIR)/libmoto.a $(NAN_MOTO)/lib/ + cp -f $(DIR)/debug/libmoto.a $(NAN_MOTO)/lib/debug/ + cp -f include/*.h $(NAN_MOTO)/include/ + diff --git a/intern/moto/include/GEN_List.h b/intern/moto/include/GEN_List.h new file mode 100644 index 00000000000..c7f974430f3 --- /dev/null +++ b/intern/moto/include/GEN_List.h @@ -0,0 +1,120 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + + +#ifndef GEN_LIST_H +#define GEN_LIST_H + +class GEN_Link { +public: + GEN_Link() : m_next(0), m_prev(0) {} + GEN_Link(GEN_Link *next, GEN_Link *prev) : m_next(next), m_prev(prev) {} + + GEN_Link *getNext() const { return m_next; } + GEN_Link *getPrev() const { return m_prev; } + + bool isHead() const { return m_prev == 0; } + bool isTail() const { return m_next == 0; } + + void insertBefore(GEN_Link *link) { + m_next = link; + m_prev = link->m_prev; + m_next->m_prev = this; + m_prev->m_next = this; + } + + void insertAfter(GEN_Link *link) { + m_next = link->m_next; + m_prev = link; + m_next->m_prev = this; + m_prev->m_next = this; + } + + void remove() { + m_next->m_prev = m_prev; + m_prev->m_next = m_next; + } + +private: + GEN_Link *m_next; + GEN_Link *m_prev; +}; + +class GEN_List { +public: + GEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {} + + GEN_Link *getHead() const { return m_head.getNext(); } + GEN_Link *getTail() const { return m_tail.getPrev(); } + + void addHead(GEN_Link *link) { link->insertAfter(&m_head); } + void addTail(GEN_Link *link) { link->insertBefore(&m_tail); } + +private: + GEN_Link m_head; + GEN_Link m_tail; +}; + +#endif + + + diff --git a/intern/moto/include/GEN_Map.h b/intern/moto/include/GEN_Map.h new file mode 100644 index 00000000000..a1d0dbfe73a --- /dev/null +++ b/intern/moto/include/GEN_Map.h @@ -0,0 +1,152 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef GEN_MAP_H + +#define GEN_MAP_H + +template <class Key, class Value> +class GEN_Map { +private: + struct Entry { + Entry (Entry *next, Key key, Value value) : + m_next(next), + m_key(key), + m_value(value) {} + + Entry *m_next; + Key m_key; + Value m_value; + }; + +public: + GEN_Map(int num_buckets = 100) : m_num_buckets(num_buckets) { + m_buckets = new Entry *[num_buckets]; + for (int i = 0; i < num_buckets; ++i) { + m_buckets[i] = 0; + } + } + + int size() { + int count=0; + for (int i=0;i<m_num_buckets;i++) + { + Entry* bucket = m_buckets[i]; + while(bucket) + { + bucket = bucket->m_next; + count++; + } + } + return count; + } + + Value* at(int index) { + int count=0; + for (int i=0;i<m_num_buckets;i++) + { + Entry* bucket = m_buckets[i]; + while(bucket) + { + if (count==index) + { + return &bucket->m_value; + } + bucket = bucket->m_next; + count++; + } + } + return 0; + } + + void clear() { + for (int i = 0; i < m_num_buckets; ++i) { + Entry *entry_ptr = m_buckets[i]; + + while (entry_ptr != 0) { + Entry *tmp_ptr = entry_ptr->m_next; + delete entry_ptr; + entry_ptr = tmp_ptr; + } + m_buckets[i] = 0; + } + } + + ~GEN_Map() { + clear(); + delete [] m_buckets; + } + + void insert(const Key& key, const Value& value) { + Entry *entry_ptr = m_buckets[key.hash() % m_num_buckets]; + while ((entry_ptr != 0) && !(key == entry_ptr->m_key)) { + entry_ptr = entry_ptr->m_next; + } + + if (entry_ptr != 0) { + entry_ptr->m_value = value; + } + else { + Entry **bucket = &m_buckets[key.hash() % m_num_buckets]; + *bucket = new Entry(*bucket, key, value); + } + } + + void remove(const Key& key) { + Entry **entry_ptr = &m_buckets[key.hash() % m_num_buckets]; + while ((*entry_ptr != 0) && !(key == (*entry_ptr)->m_key)) { + entry_ptr = &(*entry_ptr)->m_next; + } + + if (*entry_ptr != 0) { + Entry *tmp_ptr = (*entry_ptr)->m_next; + delete *entry_ptr; + *entry_ptr = tmp_ptr; + } + } + + Value *operator[](Key key) { + Entry *bucket = m_buckets[key.hash() % m_num_buckets]; + while ((bucket != 0) && !(key == bucket->m_key)) { + bucket = bucket->m_next; + } + return bucket != 0 ? &bucket->m_value : 0; + } + +private: + int m_num_buckets; + Entry **m_buckets; +}; + +#endif + + + diff --git a/intern/moto/include/MT_CmMatrix4x4.h b/intern/moto/include/MT_CmMatrix4x4.h new file mode 100644 index 00000000000..a6e259fbe17 --- /dev/null +++ b/intern/moto/include/MT_CmMatrix4x4.h @@ -0,0 +1,147 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef INCLUDED_MT_CmMatrix4x4 + +#define INCLUDED_MT_CmMatrix4x4 + +/** + * A 4x4 matrix. This is an OpenGl style matrix (column major) meaning + * that the vector {m[0][0],m[0][1],m[0][2],m[0][3]} is the first column of + * the matrix , the same as what you get if you transform {1,0,0,0}. + * This makes it easy to transform stuff to OpenGl. Please note that the + * the other MoTo matrices are row major. + * + * This class should be deprecated in favour of the more consistent + * MT_Matrix4x4. Please do not start using this class. + */ + +#include "MT_Scalar.h" + +class MT_Point3; +class MT_Vector3; + +class MT_CmMatrix4x4 +{ + +public : + + MT_CmMatrix4x4( + const float value[4][4] + ); + + MT_CmMatrix4x4( + ); + + + MT_CmMatrix4x4( + const double value[16] + ); + + MT_CmMatrix4x4( + const MT_CmMatrix4x4 & other + ); + + MT_CmMatrix4x4( + const MT_Point3& orig, + const MT_Vector3& dir, + const MT_Vector3 up + ); + + void + Identity( + ); + + void + SetMatrix( + const MT_CmMatrix4x4 & other + ); + + double* + getPointer( + ); + + const + double* + getPointer( + ) const; + + void + setElem( + int pos, + double newvalue + ); + + MT_Vector3 + GetRight( + ) const; + + MT_Vector3 + GetUp( + ) const; + + MT_Vector3 + GetDir( + ) const; + + MT_Point3 + GetPos( + ) const; + + void + SetPos( + const MT_Vector3 & v + ); + + double& + operator ( + ) (int row,int col) { return m_V[col][row]; } + + static + MT_CmMatrix4x4 + Perspective( + MT_Scalar inLeft, + MT_Scalar inRight, + MT_Scalar inBottom, + MT_Scalar inTop, + MT_Scalar inNear, + MT_Scalar inFar + ); + +protected: + union + { + double m_V[4][4]; + double m_Vflat[16]; + }; +}; + +#endif //MT_CmMatrix4x4 diff --git a/intern/moto/include/MT_Matrix3x3.h b/intern/moto/include/MT_Matrix3x3.h new file mode 100755 index 00000000000..01e5f01b539 --- /dev/null +++ b/intern/moto/include/MT_Matrix3x3.h @@ -0,0 +1,214 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + * Copyright (c) 2000 Gino van den Bergen <gino@acm.org> + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Gino van den Bergen makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef MT_MATRIX3X3_H +#define MT_MATRIX3X3_H + +#include <MT_assert.h> + +#include "MT_Vector3.h" +#include "MT_Quaternion.h" + +class MT_Matrix3x3 { +public: + MT_Matrix3x3() {} + MT_Matrix3x3(const float *m) { setValue(m); } + MT_Matrix3x3(const double *m) { setValue(m); } + MT_Matrix3x3(const MT_Quaternion& q) { setRotation(q); } + + MT_Matrix3x3(const MT_Quaternion& q, const MT_Vector3& s) { + setRotation(q); + scale(s[0], s[1], s[2]); + } + + MT_Matrix3x3(const MT_Vector3& euler) { setEuler(euler); } + MT_Matrix3x3(const MT_Vector3& euler, const MT_Vector3& s) { + setEuler(euler); + scale(s[0], s[1], s[2]); + } + + MT_Matrix3x3(MT_Scalar xx, MT_Scalar xy, MT_Scalar xz, + MT_Scalar yx, MT_Scalar yy, MT_Scalar yz, + MT_Scalar zx, MT_Scalar zy, MT_Scalar zz) { + setValue(xx, xy, xz, + yx, yy, yz, + zx, zy, zz); + } + + MT_Vector3& operator[](int i) { return m_el[i]; } + const MT_Vector3& operator[](int i) const { return m_el[i]; } + + void setValue(const float *m) { + m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++; m++; + m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++; m++; + m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m; + } + + void setValue(const double *m) { + m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++; m++; + m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++; m++; + m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m; + } + + void setValue(MT_Scalar xx, MT_Scalar xy, MT_Scalar xz, + MT_Scalar yx, MT_Scalar yy, MT_Scalar yz, + MT_Scalar zx, MT_Scalar zy, MT_Scalar zz) { + m_el[0][0] = xx; m_el[0][1] = xy; m_el[0][2] = xz; + m_el[1][0] = yx; m_el[1][1] = yy; m_el[1][2] = yz; + m_el[2][0] = zx; m_el[2][1] = zy; m_el[2][2] = zz; + } + + void setRotation(const MT_Quaternion& q) { + MT_Scalar d = q.length2(); + MT_assert(!MT_fuzzyZero2(d)); + MT_Scalar s = MT_Scalar(2.0) / d; + MT_Scalar xs = q[0] * s, ys = q[1] * s, zs = q[2] * s; + MT_Scalar wx = q[3] * xs, wy = q[3] * ys, wz = q[3] * zs; + MT_Scalar xx = q[0] * xs, xy = q[0] * ys, xz = q[0] * zs; + MT_Scalar yy = q[1] * ys, yz = q[1] * zs, zz = q[2] * zs; + setValue(MT_Scalar(1.0) - (yy + zz), xy - wz , xz + wy, + xy + wz , MT_Scalar(1.0) - (xx + zz), yz - wx, + xz - wy , yz + wx, MT_Scalar(1.0) - (xx + yy)); + } + + /** + * setEuler + * @param euler a const reference to a MT_Vector3 of euler angles + * These angles are used to produce a rotation matrix. The euler + * angles are applied in ZYX order. I.e a vector is first rotated + * about X then Y and then Z + **/ + + void setEuler(const MT_Vector3& euler) { + MT_Scalar ci = cos(euler[0]); + MT_Scalar cj = cos(euler[1]); + MT_Scalar ch = cos(euler[2]); + MT_Scalar si = sin(euler[0]); + MT_Scalar sj = sin(euler[1]); + MT_Scalar sh = sin(euler[2]); + MT_Scalar cc = ci * ch; + MT_Scalar cs = ci * sh; + MT_Scalar sc = si * ch; + MT_Scalar ss = si * sh; + + setValue(cj * ch, sj * sc - cs, sj * cc + ss, + cj * sh, sj * ss + cc, sj * cs - sc, + -sj, cj * si, cj * ci); + } + + void scale(MT_Scalar x, MT_Scalar y, MT_Scalar z) { + m_el[0][0] *= x; m_el[0][1] *= y; m_el[0][2] *= z; + m_el[1][0] *= x; m_el[1][1] *= y; m_el[1][2] *= z; + m_el[2][0] *= x; m_el[2][1] *= y; m_el[2][2] *= z; + } + + MT_Matrix3x3 scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z) const { + return MT_Matrix3x3(m_el[0][0] * x, m_el[0][1] * y, m_el[0][2] * z, + m_el[1][0] * x, m_el[1][1] * y, m_el[1][2] * z, + m_el[2][0] * x, m_el[2][1] * y, m_el[2][2] * z); + } + + void setIdentity() { + setValue(MT_Scalar(1.0), MT_Scalar(0.0), MT_Scalar(0.0), + MT_Scalar(0.0), MT_Scalar(1.0), MT_Scalar(0.0), + MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(1.0)); + } + + void getValue(float *m) const { + *m++ = m_el[0][0]; *m++ = m_el[1][0]; *m++ = m_el[2][0]; *m++ = 0.0; + *m++ = m_el[0][1]; *m++ = m_el[1][1]; *m++ = m_el[2][1]; *m++ = 0.0; + *m++ = m_el[0][2]; *m++ = m_el[1][2]; *m++ = m_el[2][2]; *m = 0.0; + } + + void getValue(double *m) const { + *m++ = m_el[0][0]; *m++ = m_el[1][0]; *m++ = m_el[2][0]; *m++ = 0.0; + *m++ = m_el[0][1]; *m++ = m_el[1][1]; *m++ = m_el[2][1]; *m++ = 0.0; + *m++ = m_el[0][2]; *m++ = m_el[1][2]; *m++ = m_el[2][2]; *m = 0.0; + } + + MT_Quaternion getRotation() const; + + MT_Matrix3x3& operator*=(const MT_Matrix3x3& m); + + MT_Scalar tdot(int c, const MT_Vector3& v) const { + return m_el[0][c] * v[0] + m_el[1][c] * v[1] + m_el[2][c] * v[2]; + } + + MT_Scalar cofac(int r1, int c1, int r2, int c2) const { + return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1]; + } + + MT_Scalar determinant() const; + MT_Matrix3x3 adjoint() const; + + MT_Matrix3x3 absolute() const; + + MT_Matrix3x3 transposed() const; + void transpose(); + + MT_Matrix3x3 inverse() const; + void invert(); + +protected: + + MT_Vector3 m_el[3]; +}; + +MT_Vector3 operator*(const MT_Matrix3x3& m, const MT_Vector3& v); +MT_Vector3 operator*(const MT_Vector3& v, const MT_Matrix3x3& m); +MT_Matrix3x3 operator*(const MT_Matrix3x3& m1, const MT_Matrix3x3& m2); + +MT_Matrix3x3 MT_multTransposeLeft(const MT_Matrix3x3& m1, const MT_Matrix3x3& m2); +MT_Matrix3x3 MT_multTransposeRight(const MT_Matrix3x3& m1, const MT_Matrix3x3& m2); + +inline MT_OStream& operator<<(MT_OStream& os, const MT_Matrix3x3& m) { + return os << m[0] << GEN_endl << m[1] << GEN_endl << m[2] << GEN_endl; +} + +#ifdef GEN_INLINED +#include "MT_Matrix3x3.inl" +#endif + +#endif diff --git a/intern/moto/include/MT_Matrix3x3.inl b/intern/moto/include/MT_Matrix3x3.inl new file mode 100644 index 00000000000..c581640ebfe --- /dev/null +++ b/intern/moto/include/MT_Matrix3x3.inl @@ -0,0 +1,128 @@ +#include "MT_Optimize.h" + +GEN_INLINE MT_Quaternion MT_Matrix3x3::getRotation() const { + static int next[3] = { 1, 2, 0 }; + + MT_Quaternion result; + + MT_Scalar trace = m_el[0][0] + m_el[1][1] + m_el[2][2]; + + if (trace > 0.0) + { + MT_Scalar s = sqrt(trace + MT_Scalar(1.0)); + result[3] = s * MT_Scalar(0.5); + s = MT_Scalar(0.5) / s; + + result[0] = (m_el[2][1] - m_el[1][2]) * s; + result[1] = (m_el[0][2] - m_el[2][0]) * s; + result[2] = (m_el[1][0] - m_el[0][1]) * s; + } + else + { + int i = 0; + if (m_el[1][1] > m_el[0][0]) + i = 1; + if (m_el[2][2] > m_el[i][i]) + i = 2; + + int j = next[i]; + int k = next[j]; + + MT_Scalar s = sqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + MT_Scalar(1.0)); + + result[i] = s * MT_Scalar(0.5); + + s = MT_Scalar(0.5) / s; + + result[3] = (m_el[k][j] - m_el[j][k]) * s; + result[j] = (m_el[j][i] + m_el[i][j]) * s; + result[k] = (m_el[k][i] + m_el[i][k]) * s; + } + return result; +} + +GEN_INLINE MT_Matrix3x3& MT_Matrix3x3::operator*=(const MT_Matrix3x3& m) { + setValue(m.tdot(0, m_el[0]), m.tdot(1, m_el[0]), m.tdot(2, m_el[0]), + m.tdot(0, m_el[1]), m.tdot(1, m_el[1]), m.tdot(2, m_el[1]), + m.tdot(0, m_el[2]), m.tdot(1, m_el[2]), m.tdot(2, m_el[2])); + return *this; +} + +GEN_INLINE MT_Scalar MT_Matrix3x3::determinant() const { + return MT_triple((*this)[0], (*this)[1], (*this)[2]); +} + +GEN_INLINE MT_Matrix3x3 MT_Matrix3x3::absolute() const { + return + MT_Matrix3x3(MT_abs(m_el[0][0]), MT_abs(m_el[0][1]), MT_abs(m_el[0][2]), + MT_abs(m_el[1][0]), MT_abs(m_el[1][1]), MT_abs(m_el[1][2]), + MT_abs(m_el[2][0]), MT_abs(m_el[2][1]), MT_abs(m_el[2][2])); +} + +GEN_INLINE MT_Matrix3x3 MT_Matrix3x3::transposed() const { + return MT_Matrix3x3(m_el[0][0], m_el[1][0], m_el[2][0], + m_el[0][1], m_el[1][1], m_el[2][1], + m_el[0][2], m_el[1][2], m_el[2][2]); +} + +GEN_INLINE void MT_Matrix3x3::transpose() { + *this = transposed(); +} + +GEN_INLINE MT_Matrix3x3 MT_Matrix3x3::adjoint() const { + return + MT_Matrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2), + cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0), + cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1)); +} + +GEN_INLINE MT_Matrix3x3 MT_Matrix3x3::inverse() const { + MT_Vector3 co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1)); + MT_Scalar det = MT_dot((*this)[0], co); + MT_assert(!MT_fuzzyZero2(det)); + MT_Scalar s = MT_Scalar(1.0) / det; + return + MT_Matrix3x3(co[0] * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s, + co[1] * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s, + co[2] * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s); +} + +GEN_INLINE void MT_Matrix3x3::invert() { + *this = inverse(); +} + +GEN_INLINE MT_Vector3 operator*(const MT_Matrix3x3& m, const MT_Vector3& v) { + return MT_Vector3(MT_dot(m[0], v), MT_dot(m[1], v), MT_dot(m[2], v)); +} + +GEN_INLINE MT_Vector3 operator*(const MT_Vector3& v, const MT_Matrix3x3& m) { + return MT_Vector3(m.tdot(0, v), m.tdot(1, v), m.tdot(2, v)); +} + +GEN_INLINE MT_Matrix3x3 operator*(const MT_Matrix3x3& m1, const MT_Matrix3x3& m2) { + return + MT_Matrix3x3(m2.tdot(0, m1[0]), m2.tdot(1, m1[0]), m2.tdot(2, m1[0]), + m2.tdot(0, m1[1]), m2.tdot(1, m1[1]), m2.tdot(2, m1[1]), + m2.tdot(0, m1[2]), m2.tdot(1, m1[2]), m2.tdot(2, m1[2])); +} + +GEN_INLINE MT_Matrix3x3 MT_multTransposeLeft(const MT_Matrix3x3& m1, const MT_Matrix3x3& m2) { + return MT_Matrix3x3( + m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0], + m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1], + m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0], + m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1], + m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2], + m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0], + m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1], + m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]); +} + +GEN_INLINE MT_Matrix3x3 MT_multTransposeRight(const MT_Matrix3x3& m1, const MT_Matrix3x3& m2) { + return + MT_Matrix3x3(m1[0].dot(m2[0]), m1[0].dot(m2[1]), m1[0].dot(m2[2]), + m1[1].dot(m2[0]), m1[1].dot(m2[1]), m1[1].dot(m2[2]), + m1[2].dot(m2[0]), m1[2].dot(m2[1]), m1[2].dot(m2[2])); + +} diff --git a/intern/moto/include/MT_Matrix4x4.h b/intern/moto/include/MT_Matrix4x4.h new file mode 100755 index 00000000000..0376db9e122 --- /dev/null +++ b/intern/moto/include/MT_Matrix4x4.h @@ -0,0 +1,250 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * A 4x4 matrix compatible with other stuff. + */ + +#ifndef MT_MATRIX4X4_H +#define MT_MATRIX4X4_H + +#include <MT_assert.h> + +#include "MT_Vector4.h" +#include "MT_Transform.h" + +// Row-major 4x4 matrix + +class MT_Matrix4x4 { +public: + /** + * Empty contructor. + */ + MT_Matrix4x4() {} + /** + * Initialize all fields with the values pointed at by m. A + * contigous block of 16 values is read. */ + MT_Matrix4x4(const float *m) { setValue(m); } + /** + * Initialize all fields with the values pointed at by m. A + * contigous block of 16 values is read. */ + MT_Matrix4x4(const double *m) { setValue(m); } + + /** + * Initialise with these 16 explicit values. + */ + MT_Matrix4x4(MT_Scalar xx, MT_Scalar xy, MT_Scalar xz, MT_Scalar xw, + MT_Scalar yx, MT_Scalar yy, MT_Scalar yz, MT_Scalar yw, + MT_Scalar zx, MT_Scalar zy, MT_Scalar zz, MT_Scalar zw, + MT_Scalar wx, MT_Scalar wy, MT_Scalar wz, MT_Scalar ww) { + setValue(xx, xy, xz, xw, + yx, yy, yz, yw, + zx, zy, zz, zw, + wx, wy, wz, ww); + } + + /** + * Initialize from an MT_Transform. + */ + MT_Matrix4x4(const MT_Transform &t) { + + const MT_Matrix3x3 &basis = t.getBasis(); + const MT_Vector3 &origin = t.getOrigin(); + + setValue( + basis[0][0],basis[0][1],basis[0][2],origin[0], + basis[1][0],basis[1][1],basis[1][2],origin[1], + basis[2][0],basis[2][1],basis[2][2],origin[2], + MT_Scalar(0),MT_Scalar(0),MT_Scalar(0),MT_Scalar(1) + ); + } + + /** + * Get the i-th row. + */ + MT_Vector4& operator[](int i) { return m_el[i]; } + /** + * Get the i-th row. + */ + const MT_Vector4& operator[](int i) const { return m_el[i]; } + + /** + * Set the matrix to the values pointer at by m. A contiguous + * block of 16 values is copied. */ + void setValue(const float *m) { + m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++; m_el[3][0] = *m++; + m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++; m_el[3][1] = *m++; + m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m++; m_el[3][2] = *m++; + m_el[0][3] = *m++; m_el[1][3] = *m++; m_el[2][3] = *m++; m_el[3][3] = *m; + } + + /** + * Set the matrix to the values pointer at by m. A contiguous + * block of 16 values is copied. + */ + void setValue(const double *m) { + m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++; m_el[3][0] = *m++; + m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++; m_el[3][1] = *m++; + m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m++; m_el[3][2] = *m++; + m_el[0][3] = *m++; m_el[1][3] = *m++; m_el[2][3] = *m++; m_el[3][3] = *m; + } + + /** + * Set the matrix to these 16 explicit values. + */ + void setValue(MT_Scalar xx, MT_Scalar xy, MT_Scalar xz, MT_Scalar xw, + MT_Scalar yx, MT_Scalar yy, MT_Scalar yz, MT_Scalar yw, + MT_Scalar zx, MT_Scalar zy, MT_Scalar zz, MT_Scalar zw, + MT_Scalar wx, MT_Scalar wy, MT_Scalar wz, MT_Scalar ww) { + m_el[0][0] = xx; m_el[0][1] = xy; m_el[0][2] = xz; m_el[0][3] = xw; + m_el[1][0] = yx; m_el[1][1] = yy; m_el[1][2] = yz; m_el[1][3] = yw; + m_el[2][0] = zx; m_el[2][1] = zy; m_el[2][2] = zz; m_el[2][3] = zw; + m_el[3][0] = wx; m_el[3][1] = wy; m_el[3][2] = wz; m_el[3][3] = ww; + } + + /** + * Scale the columns of this matrix with x, y, z, w respectively. + */ + void scale(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) { + m_el[0][0] *= x; m_el[0][1] *= y; m_el[0][2] *= z; m_el[0][3] *= w; + m_el[1][0] *= x; m_el[1][1] *= y; m_el[1][2] *= z; m_el[1][3] *= w; + m_el[2][0] *= x; m_el[2][1] *= y; m_el[2][2] *= z; m_el[2][3] *= w; + m_el[3][0] *= x; m_el[3][1] *= y; m_el[3][2] *= z; m_el[3][3] *= w; + } + + /** + * Return a column-scaled version of this matrix. + */ + MT_Matrix4x4 scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) const { + return MT_Matrix4x4(m_el[0][0] * x, m_el[0][1] * y, m_el[0][2] * z, m_el[0][3] * w, + m_el[1][0] * x, m_el[1][1] * y, m_el[1][2] * z, m_el[1][3] * w, + m_el[2][0] * x, m_el[2][1] * y, m_el[2][2] * z, m_el[2][3] * w, + m_el[3][0] * x, m_el[3][1] * y, m_el[3][2] * z, m_el[3][3] * w); + } + + /** + * Set this matrix to I. + */ + void setIdentity() { + setValue(MT_Scalar(1.0), MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0), + MT_Scalar(0.0), MT_Scalar(1.0), MT_Scalar(0.0), MT_Scalar(0.0), + MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(1.0), MT_Scalar(0.0), + MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(1.0)); + } + + /** + * Read the element from row i, column j. + */ + float getElement(int i, int j) { + return m_el[i][j]; + } + + /** + * Copy the contents to a contiguous block of 16 floats. + */ + void getValue(float *m) const { + *m++ = m_el[0][0]; *m++ = m_el[1][0]; *m++ = m_el[2][0]; *m++ = m_el[3][0]; + *m++ = m_el[0][1]; *m++ = m_el[1][1]; *m++ = m_el[2][1]; *m++ = m_el[3][1]; + *m++ = m_el[0][2]; *m++ = m_el[1][2]; *m++ = m_el[2][2]; *m++ = m_el[3][2]; + *m++ = m_el[0][3]; *m++ = m_el[1][3]; *m++ = m_el[2][3]; *m = m_el[3][3]; + } + + /** + * Copy the contents to a contiguous block of 16 doubles. + */ + void getValue(double *m) const { + *m++ = m_el[0][0]; *m++ = m_el[1][0]; *m++ = m_el[2][0]; *m++ = m_el[3][0]; + *m++ = m_el[0][1]; *m++ = m_el[1][1]; *m++ = m_el[2][1]; *m++ = m_el[3][1]; + *m++ = m_el[0][2]; *m++ = m_el[1][2]; *m++ = m_el[2][2]; *m++ = m_el[3][2]; + *m++ = m_el[0][3]; *m++ = m_el[1][3]; *m++ = m_el[2][3]; *m = m_el[3][3]; + } + + /** + * Left-multiply this matrix with the argument. + */ + MT_Matrix4x4& operator*=(const MT_Matrix4x4& m); + + /** + * Left-multiply column c with row vector c. + */ + MT_Scalar tdot(int c, const MT_Vector4& v) const { + return m_el[0][c] * v[0] + + m_el[1][c] * v[1] + + m_el[2][c] * v[2] + + m_el[3][c] * v[3]; + } + + /* I'll postpone this for now... - nzc*/ +/* MT_Scalar determinant() const; */ +/* MT_Matrix4x4 adjoint() const; */ +/* MT_Matrix4x4 inverse() const; */ + + MT_Matrix4x4 absolute() const; + + MT_Matrix4x4 transposed() const; + void transpose(); + + void invert(); + +protected: + /** + * Access with [row index][column index] + */ + MT_Vector4 m_el[4]; +}; + +/* These multiplicators do exactly what you ask from them: they + * multiply in the indicated order. */ +MT_Vector4 operator*(const MT_Matrix4x4& m, const MT_Vector4& v); +MT_Vector4 operator*(const MT_Vector4& v, const MT_Matrix4x4& m); +MT_Matrix4x4 operator*(const MT_Matrix4x4& m1, const MT_Matrix4x4& m2); + +/* MT_Matrix4x4 MT_multTransposeLeft(const MT_Matrix4x4& m1, const MT_Matrix4x4& m2); */ +/* MT_Matrix4x4 MT_multTransposeRight(const MT_Matrix4x4& m1, const MT_Matrix4x4& m2); */ + +inline MT_OStream& operator<<(MT_OStream& os, const MT_Matrix4x4& m) { + return os << m[0] << GEN_endl + << m[1] << GEN_endl + << m[2] << GEN_endl + << m[3] << GEN_endl; + + + +} + +#ifdef GEN_INLINED +#include "MT_Matrix4x4.inl" +#endif + +#endif diff --git a/intern/moto/include/MT_Matrix4x4.inl b/intern/moto/include/MT_Matrix4x4.inl new file mode 100644 index 00000000000..a2aa893a6b3 --- /dev/null +++ b/intern/moto/include/MT_Matrix4x4.inl @@ -0,0 +1,108 @@ +#include "MT_Optimize.h" + +/* + * This is a supposedly faster inverter than the cofactor + * computation. It uses an LU decomposition sort of thing. */ +GEN_INLINE void MT_Matrix4x4::invert() { + /* normalize row 0 */ + + int i,j,k; + + for (i=1; i < 4; i++) m_el[0][i] /= m_el[0][0]; + for (i=1; i < 4; i++) { + for (j=i; j < 4; j++) { // do a column of L + MT_Scalar sum = 0.0; + for (k = 0; k < i; k++) + sum += m_el[j][k] * m_el[k][i]; + m_el[j][i] -= sum; + } + if (i == 3) continue; + for (j=i+1; j < 4; j++) { // do a row of U + MT_Scalar sum = 0.0; + for (k = 0; k < i; k++) + sum += m_el[i][k]*m_el[k][j]; + m_el[i][j] = + (m_el[i][j]-sum) / m_el[i][i]; + } + } + for (i = 0; i < 4; i++ ) // invert L + for (j = i; j < 4; j++ ) { + MT_Scalar x = 1.0; + if ( i != j ) { + x = 0.0; + for (k = i; k < j; k++ ) + x -= m_el[j][k]*m_el[k][i]; + } + m_el[j][i] = x / m_el[j][j]; + } + for (i = 0; i < 4; i++ ) // invert U + for (j = i; j < 4; j++ ) { + if ( i == j ) continue; + MT_Scalar sum = 0.0; + for (k = i; k < j; k++ ) + sum += m_el[k][j]*( (i==k) ? 1.0 : m_el[i][k] ); + m_el[i][j] = -sum; + } + for (i = 0; i < 4; i++ ) // final inversion + for (j = 0; j < 4; j++ ) { + MT_Scalar sum = 0.0; + for (k = ((i>j)?i:j); k < 4; k++ ) + sum += ((j==k)?1.0:m_el[j][k])*m_el[k][i]; + m_el[j][i] = sum; + } +} + +/* We do things slightly different here, because the invert() modifies + * the buffer itself. This makes it impossible to make this op right + * away. Like other, still missing facilities, I will repair this + * later. */ +/* GEN_INLINE T_Matrix4x4 MT_Matrix4x4::inverse() const */ +/* { */ +/* } */ + + +GEN_INLINE MT_Matrix4x4& MT_Matrix4x4::operator*=(const MT_Matrix4x4& m) +{ + setValue(m.tdot(0, m_el[0]), m.tdot(1, m_el[0]), m.tdot(2, m_el[0]), m.tdot(3, m_el[0]), + m.tdot(0, m_el[1]), m.tdot(1, m_el[1]), m.tdot(2, m_el[1]), m.tdot(3, m_el[1]), + m.tdot(0, m_el[2]), m.tdot(1, m_el[2]), m.tdot(2, m_el[2]), m.tdot(3, m_el[2]), + m.tdot(0, m_el[3]), m.tdot(1, m_el[3]), m.tdot(2, m_el[3]), m.tdot(3, m_el[3])); + return *this; + +} + +GEN_INLINE MT_Vector4 operator*(const MT_Matrix4x4& m, const MT_Vector4& v) { + return MT_Vector4(MT_dot(m[0], v), MT_dot(m[1], v), MT_dot(m[2], v), MT_dot(m[3], v)); +} + +GEN_INLINE MT_Vector4 operator*(const MT_Vector4& v, const MT_Matrix4x4& m) { + return MT_Vector4(m.tdot(0, v), m.tdot(1, v), m.tdot(2, v), m.tdot(3, v)); +} + +GEN_INLINE MT_Matrix4x4 operator*(const MT_Matrix4x4& m1, const MT_Matrix4x4& m2) { + return + MT_Matrix4x4(m2.tdot(0, m1[0]), m2.tdot(1, m1[0]), m2.tdot(2, m1[0]), m2.tdot(3, m1[0]), + m2.tdot(0, m1[1]), m2.tdot(1, m1[1]), m2.tdot(2, m1[1]), m2.tdot(3, m1[1]), + m2.tdot(0, m1[2]), m2.tdot(1, m1[2]), m2.tdot(2, m1[2]), m2.tdot(3, m1[2]), + m2.tdot(0, m1[3]), m2.tdot(1, m1[3]), m2.tdot(2, m1[3]), m2.tdot(3, m1[3])); +} + + +GEN_INLINE MT_Matrix4x4 MT_Matrix4x4::transposed() const { + return MT_Matrix4x4(m_el[0][0], m_el[1][0], m_el[2][0], m_el[3][0], + m_el[0][1], m_el[1][1], m_el[2][1], m_el[3][1], + m_el[0][2], m_el[1][2], m_el[2][2], m_el[3][2], + m_el[0][3], m_el[1][3], m_el[2][3], m_el[3][3]); +} + +GEN_INLINE void MT_Matrix4x4::transpose() { + *this = transposed(); +} + +GEN_INLINE MT_Matrix4x4 MT_Matrix4x4::absolute() const { + return + MT_Matrix4x4(MT_abs(m_el[0][0]), MT_abs(m_el[0][1]), MT_abs(m_el[0][2]), MT_abs(m_el[0][3]), + MT_abs(m_el[1][0]), MT_abs(m_el[1][1]), MT_abs(m_el[1][2]), MT_abs(m_el[1][3]), + MT_abs(m_el[2][0]), MT_abs(m_el[2][1]), MT_abs(m_el[2][2]), MT_abs(m_el[2][3]), + MT_abs(m_el[3][0]), MT_abs(m_el[3][1]), MT_abs(m_el[3][2]), MT_abs(m_el[3][3])); +} diff --git a/intern/moto/include/MT_MinMax.h b/intern/moto/include/MT_MinMax.h new file mode 100755 index 00000000000..b206aa6efaf --- /dev/null +++ b/intern/moto/include/MT_MinMax.h @@ -0,0 +1,69 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + * Copyright (c) 2000 Gino van den Bergen <gino@acm.org> + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Gino van den Bergen makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef MT_MINMAX_H +#define MT_MINMAX_H + +template <class T> +inline const T& MT_min(const T& a, const T& b) { + return b < a ? b : a; +} + +template <class T> +inline const T& MT_max(const T& a, const T& b) { + return a < b ? b : a; +} + +template <class T> +inline void MT_set_min(T& a, const T& b) { + if (a > b) a = b; +} + +template <class T> +inline void MT_set_max(T& a, const T& b) { + if (a < b) a = b; +} + +#endif diff --git a/intern/moto/include/MT_Optimize.h b/intern/moto/include/MT_Optimize.h new file mode 100644 index 00000000000..0ff3afcbd60 --- /dev/null +++ b/intern/moto/include/MT_Optimize.h @@ -0,0 +1,42 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef GEN_OPTIMIZE_H + +#define GEN_OPTIMIZE_H + +#ifdef GEN_INLINED +#define GEN_INLINE inline +#else +#define GEN_INLINE +#endif + +#endif diff --git a/intern/moto/include/MT_Plane3.h b/intern/moto/include/MT_Plane3.h new file mode 100644 index 00000000000..bb9dd9e4f79 --- /dev/null +++ b/intern/moto/include/MT_Plane3.h @@ -0,0 +1,139 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef MT_PLANE3 + +#define MT_PLANE3 + +#include "MT_Tuple4.h" +#include "MT_Point3.h" + +/** + * A simple 3d plane class. + * + * This class represents a plane in 3d. The internal parameterization used + * is n.x + d =0 where n is a unit vector and d is a scalar. + * + * It inherits data from MT_Tuple4 please see this class for low level + * access to the internal representation. + * + */ + +class MT_Plane3 : public MT_Tuple4 +{ +public : + /** + * Constructor from 3 points + */ + + MT_Plane3( + const MT_Vector3 &a, + const MT_Vector3 &b, + const MT_Vector3 &c + ); + /** + * Construction from vector and a point. + */ + + MT_Plane3( + const MT_Vector3 &n, + const MT_Vector3 &p + ); + + /** + * Default constructor + */ + MT_Plane3( + ); + + /** + * Default constructor + */ + + MT_Plane3( + const MT_Plane3 & p + ): + MT_Tuple4(p) + { + } + + /** + * Return plane normal + */ + + MT_Vector3 + Normal( + ) const; + + /** + * Return plane scalar i.e the d from n.x + d = 0 + */ + + MT_Scalar + Scalar( + ) const ; + + /** + * Invert the plane - just swaps direction of normal. + */ + void + Invert( + ); + + /** + * Assignment operator + */ + + MT_Plane3 & + operator = ( + const MT_Plane3 & rhs + ); + + /** + * Return the signed perpendicular distance from a point to the plane + */ + + MT_Scalar + signedDistance( + const MT_Vector3 & + ) const; + + +}; + +#ifdef GEN_INLINED +#include "MT_Plane3.inl" +#endif + + +#endif + + diff --git a/intern/moto/include/MT_Plane3.inl b/intern/moto/include/MT_Plane3.inl new file mode 100644 index 00000000000..77db9b35e1d --- /dev/null +++ b/intern/moto/include/MT_Plane3.inl @@ -0,0 +1,128 @@ +#include "MT_Optimize.h" + + +GEN_INLINE +MT_Plane3:: +MT_Plane3( + const MT_Vector3 &a, + const MT_Vector3 &b, + const MT_Vector3 &c +){ + MT_Vector3 l1 = b-a; + MT_Vector3 l2 = c-b; + + MT_Vector3 n = l1.cross(l2); + n = n.safe_normalized(); + MT_Scalar d = n.dot(a); + + m_co[0] = n.x(); + m_co[1] = n.y(); + m_co[2] = n.z(); + m_co[3] = -d; +} + +/** + * Construction from vector and a point. + */ +GEN_INLINE +MT_Plane3:: +MT_Plane3( + const MT_Vector3 &n, + const MT_Vector3 &p +){ + + MT_Vector3 mn = n.safe_normalized(); + MT_Scalar md = mn.dot(p); + + m_co[0] = mn.x(); + m_co[1] = mn.y(); + m_co[2] = mn.z(); + m_co[3] = -md; +} + + +/** + * Default constructor + */ +GEN_INLINE +MT_Plane3:: +MT_Plane3( +): + MT_Tuple4() +{ + m_co[0] = MT_Scalar(1); + m_co[1] = MT_Scalar(0); + m_co[2] = MT_Scalar(0); + m_co[3] = MT_Scalar(0); +} + +/** + * Return plane normal + */ + +GEN_INLINE + MT_Vector3 +MT_Plane3:: +Normal( +) const { + return MT_Vector3(m_co[0],m_co[1],m_co[2]); +} + +/** + * Return plane scalar i.e the d from n.x + d = 0 + */ + +GEN_INLINE + MT_Scalar +MT_Plane3:: +Scalar( +) const { + return m_co[3]; +} + +GEN_INLINE + void +MT_Plane3:: +Invert( +) { + m_co[0] = -m_co[0]; + m_co[1] = -m_co[1]; + m_co[2] = -m_co[2]; + m_co[3] = -m_co[3]; +} + + +/** + * Assignment operator + */ + +GEN_INLINE + MT_Plane3 & +MT_Plane3:: +operator = ( + const MT_Plane3 & rhs +) { + m_co[0] = rhs.m_co[0]; + m_co[1] = rhs.m_co[1]; + m_co[2] = rhs.m_co[2]; + m_co[3] = rhs.m_co[3]; + return *this; +} + +/** + * Return the distance from a point to the plane + */ + +GEN_INLINE + MT_Scalar +MT_Plane3:: +signedDistance( + const MT_Vector3 &v +) const { + return Normal().dot(v) + m_co[3]; +} + + + + + diff --git a/intern/moto/include/MT_Point2.h b/intern/moto/include/MT_Point2.h new file mode 100644 index 00000000000..2c3abaaf977 --- /dev/null +++ b/intern/moto/include/MT_Point2.h @@ -0,0 +1,81 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + * Copyright (c) 2000 Gino van den Bergen <gino@acm.org> + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Gino van den Bergen makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef MT_POINT2_H +#define MT_POINT2_H + +#include "MT_Vector2.h" + +class MT_Point2 : public MT_Vector2 { +public: + MT_Point2() {} + MT_Point2(const float *v) : MT_Vector2(v) {} + MT_Point2(const double *v) : MT_Vector2(v) {} + MT_Point2(MT_Scalar x, MT_Scalar y) : MT_Vector2(x, y) {} + + MT_Point2& operator+=(const MT_Vector2& v); + MT_Point2& operator-=(const MT_Vector2& v); + MT_Point2& operator=(const MT_Vector2& v); + + MT_Scalar distance(const MT_Point2& p) const; + MT_Scalar distance2(const MT_Point2& p) const; + + MT_Point2 lerp(const MT_Point2& p, MT_Scalar t) const; +}; + +MT_Point2 operator+(const MT_Point2& p, const MT_Vector2& v); +MT_Point2 operator-(const MT_Point2& p, const MT_Vector2& v); +MT_Vector2 operator-(const MT_Point2& p1, const MT_Point2& p2); + +MT_Scalar MT_distance(const MT_Point2& p1, const MT_Point2& p2); +MT_Scalar MT_distance2(const MT_Point2& p1, const MT_Point2& p2); + +MT_Point2 MT_lerp(const MT_Point2& p1, const MT_Point2& p2, MT_Scalar t); + +#ifdef GEN_INLINED +#include "MT_Point2.inl" +#endif + +#endif diff --git a/intern/moto/include/MT_Point2.inl b/intern/moto/include/MT_Point2.inl new file mode 100644 index 00000000000..ec09a3260e2 --- /dev/null +++ b/intern/moto/include/MT_Point2.inl @@ -0,0 +1,54 @@ +#include "MT_Optimize.h" + +GEN_INLINE MT_Point2& MT_Point2::operator+=(const MT_Vector2& v) { + m_co[0] += v[0]; m_co[1] += v[1]; + return *this; +} + +GEN_INLINE MT_Point2& MT_Point2::operator-=(const MT_Vector2& v) { + m_co[0] -= v[0]; m_co[1] -= v[1]; + return *this; +} + +GEN_INLINE MT_Point2& MT_Point2::operator=(const MT_Vector2& v) { + m_co[0] = v[0]; m_co[1] = v[1]; + return *this; +} + +GEN_INLINE MT_Scalar MT_Point2::distance(const MT_Point2& p) const { + return (p - *this).length(); +} + +GEN_INLINE MT_Scalar MT_Point2::distance2(const MT_Point2& p) const { + return (p - *this).length2(); +} + +GEN_INLINE MT_Point2 MT_Point2::lerp(const MT_Point2& p, MT_Scalar t) const { + return MT_Point2(m_co[0] + (p[0] - m_co[0]) * t, + m_co[1] + (p[1] - m_co[1]) * t); +} + +GEN_INLINE MT_Point2 operator+(const MT_Point2& p, const MT_Vector2& v) { + return MT_Point2(p[0] + v[0], p[1] + v[1]); +} + +GEN_INLINE MT_Point2 operator-(const MT_Point2& p, const MT_Vector2& v) { + return MT_Point2(p[0] - v[0], p[1] - v[1]); +} + +GEN_INLINE MT_Vector2 operator-(const MT_Point2& p1, const MT_Point2& p2) { + return MT_Vector2(p1[0] - p2[0], p1[1] - p2[1]); +} + +GEN_INLINE MT_Scalar MT_distance(const MT_Point2& p1, const MT_Point2& p2) { + return p1.distance(p2); +} + +GEN_INLINE MT_Scalar MT_distance2(const MT_Point2& p1, const MT_Point2& p2) { + return p1.distance2(p2); +} + +GEN_INLINE MT_Point2 MT_lerp(const MT_Point2& p1, const MT_Point2& p2, MT_Scalar t) { + return p1.lerp(p2, t); +} + diff --git a/intern/moto/include/MT_Point3.h b/intern/moto/include/MT_Point3.h new file mode 100644 index 00000000000..aa0b4c5f1bb --- /dev/null +++ b/intern/moto/include/MT_Point3.h @@ -0,0 +1,81 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + * Copyright (c) 2000 Gino van den Bergen <gino@acm.org> + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Gino van den Bergen makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef MT_POINT_H +#define MT_POINT_H + +#include "MT_Vector3.h" + +class MT_Point3 : public MT_Vector3 { +public: + MT_Point3() {} + MT_Point3(const float *v) : MT_Vector3(v) {} + MT_Point3(const double *v) : MT_Vector3(v) {} + MT_Point3(MT_Scalar x, MT_Scalar y, MT_Scalar z) : MT_Vector3(x, y, z) {} + + MT_Point3& operator+=(const MT_Vector3& v); + MT_Point3& operator-=(const MT_Vector3& v); + MT_Point3& operator=(const MT_Vector3& v); + + MT_Scalar distance(const MT_Point3& p) const; + MT_Scalar distance2(const MT_Point3& p) const; + + MT_Point3 lerp(const MT_Point3& p, MT_Scalar t) const; +}; + +MT_Point3 operator+(const MT_Point3& p, const MT_Vector3& v); +MT_Point3 operator-(const MT_Point3& p, const MT_Vector3& v); +MT_Vector3 operator-(const MT_Point3& p1, const MT_Point3& p2); + +MT_Scalar MT_distance(const MT_Point3& p1, const MT_Point3& p2); +MT_Scalar MT_distance2(const MT_Point3& p1, const MT_Point3& p2); + +MT_Point3 MT_lerp(const MT_Point3& p1, const MT_Point3& p2, MT_Scalar t); + +#ifdef GEN_INLINED +#include "MT_Point3.inl" +#endif + +#endif diff --git a/intern/moto/include/MT_Point3.inl b/intern/moto/include/MT_Point3.inl new file mode 100644 index 00000000000..e6ce4f9d9a3 --- /dev/null +++ b/intern/moto/include/MT_Point3.inl @@ -0,0 +1,54 @@ +#include "MT_Optimize.h" + +GEN_INLINE MT_Point3& MT_Point3::operator+=(const MT_Vector3& v) { + m_co[0] += v[0]; m_co[1] += v[1]; m_co[2] += v[2]; + return *this; +} + +GEN_INLINE MT_Point3& MT_Point3::operator-=(const MT_Vector3& v) { + m_co[0] -= v[0]; m_co[1] -= v[1]; m_co[2] -= v[2]; + return *this; +} + +GEN_INLINE MT_Point3& MT_Point3::operator=(const MT_Vector3& v) { + m_co[0] = v[0]; m_co[1] = v[1]; m_co[2] = v[2]; + return *this; +} + +GEN_INLINE MT_Scalar MT_Point3::distance(const MT_Point3& p) const { + return (p - *this).length(); +} + +GEN_INLINE MT_Scalar MT_Point3::distance2(const MT_Point3& p) const { + return (p - *this).length2(); +} + +GEN_INLINE MT_Point3 MT_Point3::lerp(const MT_Point3& p, MT_Scalar t) const { + return MT_Point3(m_co[0] + (p[0] - m_co[0]) * t, + m_co[1] + (p[1] - m_co[1]) * t, + m_co[2] + (p[2] - m_co[2]) * t); +} + +GEN_INLINE MT_Point3 operator+(const MT_Point3& p, const MT_Vector3& v) { + return MT_Point3(p[0] + v[0], p[1] + v[1], p[2] + v[2]); +} + +GEN_INLINE MT_Point3 operator-(const MT_Point3& p, const MT_Vector3& v) { + return MT_Point3(p[0] - v[0], p[1] - v[1], p[2] - v[2]); +} + +GEN_INLINE MT_Vector3 operator-(const MT_Point3& p1, const MT_Point3& p2) { + return MT_Vector3(p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2]); +} + +GEN_INLINE MT_Scalar MT_distance(const MT_Point3& p1, const MT_Point3& p2) { + return p1.distance(p2); +} + +GEN_INLINE MT_Scalar MT_distance2(const MT_Point3& p1, const MT_Point3& p2) { + return p1.distance2(p2); +} + +GEN_INLINE MT_Point3 MT_lerp(const MT_Point3& p1, const MT_Point3& p2, MT_Scalar t) { + return p1.lerp(p2, t); +} diff --git a/intern/moto/include/MT_Quaternion.h b/intern/moto/include/MT_Quaternion.h new file mode 100644 index 00000000000..577df2e9fa5 --- /dev/null +++ b/intern/moto/include/MT_Quaternion.h @@ -0,0 +1,112 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + * Copyright (c) 2000 Gino van den Bergen <gino@acm.org> + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Gino van den Bergen makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef MT_QUATERNION_H +#define MT_QUATERNION_H + +#include <MT_assert.h> + +#include "MT_Vector3.h" +#include "MT_Vector4.h" + +class MT_Quaternion : public MT_Vector4 { +public: + MT_Quaternion() {} + MT_Quaternion(const MT_Vector4& v) : MT_Vector4(v) {} + MT_Quaternion(const float v[4]) : MT_Vector4(v) {} + MT_Quaternion(const double v[4]) : MT_Vector4(v) {} + MT_Quaternion(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) : + MT_Vector4(x, y, z, w) {} + MT_Quaternion(const MT_Vector3& axis, MT_Scalar angle) { + setRotation(axis, angle); + } + MT_Quaternion(MT_Scalar yaw, MT_Scalar pitch, MT_Scalar roll) { + setEuler(yaw, pitch, roll); + } + + void setRotation(const MT_Vector3& axis, MT_Scalar angle) { + MT_Scalar d = axis.length(); + MT_assert(!MT_fuzzyZero(d)); + MT_Scalar s = sin(angle * MT_Scalar(0.5)) / d; + setValue(axis[0] * s, axis[1] * s, axis[2] * s, + cos(angle * MT_Scalar(0.5))); + } + + void setEuler(MT_Scalar yaw, MT_Scalar pitch, MT_Scalar roll) { + MT_Scalar cosYaw = cos(yaw * MT_Scalar(0.5)); + MT_Scalar sinYaw = sin(yaw * MT_Scalar(0.5)); + MT_Scalar cosPitch = cos(pitch * MT_Scalar(0.5)); + MT_Scalar sinPitch = sin(pitch * MT_Scalar(0.5)); + MT_Scalar cosRoll = cos(roll * MT_Scalar(0.5)); + MT_Scalar sinRoll = sin(roll * MT_Scalar(0.5)); + setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, + cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, + sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, + cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); + } + + MT_Quaternion& operator*=(const MT_Quaternion& q); + + void conjugate(); + MT_Quaternion conjugate() const; + + void invert(); + MT_Quaternion inverse() const; + + static MT_Quaternion random(); +}; + +MT_Quaternion operator*(const MT_Quaternion& q1, const MT_Quaternion& q2); +MT_Quaternion operator*(const MT_Quaternion& q, const MT_Vector3& w); +MT_Quaternion operator*(const MT_Vector3& w, const MT_Quaternion& q); + +#ifdef GEN_INLINED +#include "MT_Quaternion.inl" +#endif + +#endif + + + diff --git a/intern/moto/include/MT_Quaternion.inl b/intern/moto/include/MT_Quaternion.inl new file mode 100644 index 00000000000..225b95b78ce --- /dev/null +++ b/intern/moto/include/MT_Quaternion.inl @@ -0,0 +1,62 @@ +#include "MT_Optimize.h" + +GEN_INLINE MT_Quaternion& MT_Quaternion::operator*=(const MT_Quaternion& q) { + setValue(m_co[3] * q[0] + m_co[0] * q[3] + m_co[1] * q[2] - m_co[2] * q[1], + m_co[3] * q[1] + m_co[1] * q[3] + m_co[2] * q[0] - m_co[0] * q[2], + m_co[3] * q[2] + m_co[2] * q[3] + m_co[0] * q[1] - m_co[1] * q[0], + m_co[3] * q[3] - m_co[0] * q[0] - m_co[1] * q[1] - m_co[2] * q[2]); + return *this; +} + +GEN_INLINE void MT_Quaternion::conjugate() { + m_co[0] = -m_co[0]; m_co[1] = -m_co[1]; m_co[2] = -m_co[2]; +} + +GEN_INLINE MT_Quaternion MT_Quaternion::conjugate() const { + return MT_Quaternion(-m_co[0], -m_co[1], -m_co[2], m_co[3]); +} + +GEN_INLINE void MT_Quaternion::invert() { + conjugate(); + *this /= length2(); +} + +GEN_INLINE MT_Quaternion MT_Quaternion::inverse() const { + return conjugate() / length2(); +} + +// From: "Uniform Random Rotations", Ken Shoemake, Graphics Gems III, +// pg. 124-132 +GEN_INLINE MT_Quaternion MT_Quaternion::random() { + MT_Scalar x0 = MT_random(); + MT_Scalar r1 = sqrt(MT_Scalar(1.0) - x0), r2 = sqrt(x0); + MT_Scalar t1 = MT_2_PI * MT_random(), t2 = MT_2_PI * MT_random(); + MT_Scalar c1 = cos(t1), s1 = sin(t1); + MT_Scalar c2 = cos(t2), s2 = sin(t2); + return MT_Quaternion(s1 * r1, c1 * r1, s2 * r2, c2 * r2); +} + +GEN_INLINE MT_Quaternion operator*(const MT_Quaternion& q1, + const MT_Quaternion& q2) { + return MT_Quaternion(q1[3] * q2[0] + q1[0] * q2[3] + q1[1] * q2[2] - q1[2] * q2[1], + q1[3] * q2[1] + q1[1] * q2[3] + q1[2] * q2[0] - q1[0] * q2[2], + q1[3] * q2[2] + q1[2] * q2[3] + q1[0] * q2[1] - q1[1] * q2[0], + q1[3] * q2[3] - q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2]); +} + +GEN_INLINE MT_Quaternion operator*(const MT_Quaternion& q, const MT_Vector3& w) +{ + return MT_Quaternion( q[3] * w[0] + q[1] * w[2] - q[2] * w[1], + q[3] * w[1] + q[2] * w[0] - q[0] * w[2], + q[3] * w[2] + q[0] * w[1] - q[1] * w[0], + -q[0] * w[0] - q[1] * w[1] - q[2] * w[2]); +} + +GEN_INLINE MT_Quaternion operator*(const MT_Vector3& w, const MT_Quaternion& q) +{ + return MT_Quaternion( w[0] * q[3] + w[1] * q[2] - w[2] * q[1], + w[1] * q[3] + w[2] * q[0] - w[0] * q[2], + w[2] * q[3] + w[0] * q[1] - w[1] * q[0], + -w[0] * q[0] - w[1] * q[1] - w[2] * q[2]); +} + diff --git a/intern/moto/include/MT_Scalar.h b/intern/moto/include/MT_Scalar.h new file mode 100755 index 00000000000..a3257c3c73d --- /dev/null +++ b/intern/moto/include/MT_Scalar.h @@ -0,0 +1,88 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + * Copyright (c) 2000 Gino van den Bergen <gino@acm.org> + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Gino van den Bergen makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef MT_SCALAR_H +#define MT_SCALAR_H + +#include <math.h> +#include <float.h> + +#include "MT_random.h" +#include "NM_Scalar.h" + +typedef double MT_Scalar; + +const MT_Scalar MT_DEGS_PER_RAD(57.29577951308232286465); +const MT_Scalar MT_RADS_PER_DEG(0.01745329251994329547); +const MT_Scalar MT_PI(3.14159265358979323846); +const MT_Scalar MT_2_PI(6.28318530717958623200); +const MT_Scalar MT_EPSILON(1.0e-10); +const MT_Scalar MT_EPSILON2(1.0e-20); +const MT_Scalar MT_INFINITY(1.0e50); + +inline int MT_sign(MT_Scalar x) { + return x < 0.0 ? -1 : x > 0.0 ? 1 : 0; +} + +inline MT_Scalar MT_abs(MT_Scalar x) { return fabs(x); } + +inline bool MT_fuzzyZero(MT_Scalar x) { return MT_abs(x) < MT_EPSILON; } +inline bool MT_fuzzyZero2(MT_Scalar x) { return MT_abs(x) < MT_EPSILON2; } + +inline MT_Scalar MT_radians(MT_Scalar x) { + return x * MT_RADS_PER_DEG; +} + +inline MT_Scalar MT_degrees(MT_Scalar x) { + return x * MT_DEGS_PER_RAD; +} + +inline MT_Scalar MT_random() { + return MT_Scalar(MT_rand()) / MT_Scalar(MT_RAND_MAX); +} + + +#endif + diff --git a/intern/moto/include/MT_Stream.h b/intern/moto/include/MT_Stream.h new file mode 100755 index 00000000000..6be0437f257 --- /dev/null +++ b/intern/moto/include/MT_Stream.h @@ -0,0 +1,58 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef GEN_STREAM_H + +#define GEN_STREAM_H + +#ifdef __CUSTOM_STREAM + +class MT_OStream +{ +public: + inline MT_OStream& operator<<(double); + inline MT_OStream& operator<<(int); + inline MT_OStream& operator<<(char*); +}; + +const char GEN_endl = '\n'; + +#else + +#include <iostream> + +typedef std::ostream MT_OStream; + +inline MT_OStream& GEN_endl(MT_OStream& os) { return std::endl(os); } + +#endif + +#endif diff --git a/intern/moto/include/MT_Transform.h b/intern/moto/include/MT_Transform.h new file mode 100644 index 00000000000..73ad0c77fa5 --- /dev/null +++ b/intern/moto/include/MT_Transform.h @@ -0,0 +1,172 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + MoTo - 3D Motion Toolkit + Copyright (C) 2000 Gino van den Bergen <gino@acm.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef MT_TRANSFORM_H +#define MT_TRANSFORM_H + +#include "MT_Point3.h" +#include "MT_Matrix3x3.h" + +class MT_Transform { +public: + MT_Transform() {} + MT_Transform(const float *m) { setValue(m); } + MT_Transform(const double *m) { setValue(m); } + MT_Transform(const MT_Point3& p, const MT_Quaternion& q) { + setOrigin(p); + setRotation(q); + } + + MT_Transform(const MT_Point3& p, const MT_Matrix3x3& m) { + setOrigin(p); + setBasis(m); + } + + + + MT_Point3 operator()(const MT_Point3& p) const { + return MT_Point3(MT_dot(m_basis[0], p) + m_origin[0], + MT_dot(m_basis[1], p) + m_origin[1], + MT_dot(m_basis[2], p) + m_origin[2]); + } + + MT_Point3 operator*(const MT_Point3& p) const { + return (*this)(p); + } + + MT_Matrix3x3& getBasis() { return m_basis; } + const MT_Matrix3x3& getBasis() const { return m_basis; } + MT_Point3& getOrigin() { return m_origin; } + const MT_Point3& getOrigin() const { return m_origin; } + MT_Quaternion getRotation() const { return m_basis.getRotation(); } + + void setValue(const float *m); + void setValue(const double *m); + + void setOrigin(const MT_Point3& origin) { + m_origin = origin; + m_type |= TRANSLATION; + } + + void setBasis(const MT_Matrix3x3& basis) { + m_basis = basis; + m_type |= LINEAR; + } + + void setRotation(const MT_Quaternion& q) { + m_basis.setRotation(q); + m_type &= ~SCALING; + m_type |= ROTATION; + } + + void getValue(float *m) const; + void getValue(double *m) const; + + void setIdentity(); + + MT_Transform& operator*=(const MT_Transform& t); + + /** + * Translate the origin of the transform according to the vector. + * @param v The vector to translate over. The vector is specified + * in the coordinate system of the transform itself. + */ + void translate(const MT_Vector3& v); + void rotate(const MT_Quaternion& q); + void scale(MT_Scalar x, MT_Scalar y, MT_Scalar z); + + void invert(const MT_Transform& t); + void mult(const MT_Transform& t1, const MT_Transform& t2); + void multInverseLeft(const MT_Transform& t1, const MT_Transform& t2); + +private: + enum { + IDENTITY = 0x00, + TRANSLATION = 0x01, + ROTATION = 0x02, + RIGID = TRANSLATION | ROTATION, + SCALING = 0x04, + LINEAR = ROTATION | SCALING, + AFFINE = TRANSLATION | LINEAR + }; + + MT_Transform(const MT_Matrix3x3& basis, const MT_Point3& origin, + unsigned int type) { + setValue(basis, origin, type); + } + + void setValue(const MT_Matrix3x3& basis, const MT_Point3& origin, + unsigned int type) { + m_basis = basis; + m_origin = origin; + m_type = type; + } + + friend MT_Transform operator*(const MT_Transform& t1, const MT_Transform& t2); + + MT_Matrix3x3 m_basis; + MT_Point3 m_origin; + unsigned int m_type; +}; + +inline MT_Transform operator*(const MT_Transform& t1, const MT_Transform& t2) { + return MT_Transform(t1.m_basis * t2.m_basis, + t1(t2.m_origin), + t1.m_type | t2.m_type); +} + +#endif + + + + + diff --git a/intern/moto/include/MT_Tuple2.h b/intern/moto/include/MT_Tuple2.h new file mode 100755 index 00000000000..edefc2669e5 --- /dev/null +++ b/intern/moto/include/MT_Tuple2.h @@ -0,0 +1,109 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + * Copyright (c) 2000 Gino van den Bergen <gino@acm.org> + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Gino van den Bergen makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef MT_Tuple2_H +#define MT_Tuple2_H + +#include "MT_Stream.h" +#include "MT_Scalar.h" + +class MT_Tuple2 { +public: + MT_Tuple2() {} + MT_Tuple2(const float *v) { setValue(v); } + MT_Tuple2(const double *v) { setValue(v); } + MT_Tuple2(MT_Scalar x, MT_Scalar y) { setValue(x, y); } + + MT_Scalar& operator[](int i) { return m_co[i]; } + const MT_Scalar& operator[](int i) const { return m_co[i]; } + + MT_Scalar& x() { return m_co[0]; } + const MT_Scalar& x() const { return m_co[0]; } + + MT_Scalar& y() { return m_co[1]; } + const MT_Scalar& y() const { return m_co[1]; } + + MT_Scalar& u() { return m_co[0]; } + const MT_Scalar& u() const { return m_co[0]; } + + MT_Scalar& v() { return m_co[1]; } + const MT_Scalar& v() const { return m_co[1]; } + + MT_Scalar *getValue() { return m_co; } + const MT_Scalar *getValue() const { return m_co; } + + void getValue(float *v) const { + v[0] = m_co[0]; v[1] = m_co[1]; + } + + void getValue(double *v) const { + v[0] = m_co[0]; v[1] = m_co[1]; + } + + void setValue(const float *v) { + m_co[0] = v[0]; m_co[1] = v[1]; + } + + void setValue(const double *v) { + m_co[0] = v[0]; m_co[1] = v[1]; + } + + void setValue(MT_Scalar x, MT_Scalar y) { + m_co[0] = x; m_co[1] = y; + } + +protected: + MT_Scalar m_co[2]; +}; + +inline bool operator==(const MT_Tuple2& t1, const MT_Tuple2& t2) { + return t1[0] == t2[0] && t1[1] == t2[1]; +} + +inline MT_OStream& operator<<(MT_OStream& os, const MT_Tuple2& t) { + return os << t[0] << ' ' << t[1]; +} + +#endif diff --git a/intern/moto/include/MT_Tuple3.h b/intern/moto/include/MT_Tuple3.h new file mode 100755 index 00000000000..127b18bd41b --- /dev/null +++ b/intern/moto/include/MT_Tuple3.h @@ -0,0 +1,114 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + * Copyright (c) 2000 Gino van den Bergen <gino@acm.org> + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Gino van den Bergen makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef MT_TUPLE3_H +#define MT_TUPLE3_H + +#include "MT_Stream.h" +#include "MT_Scalar.h" + +class MT_Tuple3 { +public: + MT_Tuple3() {} + MT_Tuple3(const float *v) { setValue(v); } + MT_Tuple3(const double *v) { setValue(v); } + MT_Tuple3(MT_Scalar x, MT_Scalar y, MT_Scalar z) { setValue(x, y, z); } + + MT_Scalar& operator[](int i) { return m_co[i]; } + const MT_Scalar& operator[](int i) const { return m_co[i]; } + + MT_Scalar& x() { return m_co[0]; } + const MT_Scalar& x() const { return m_co[0]; } + + MT_Scalar& y() { return m_co[1]; } + const MT_Scalar& y() const { return m_co[1]; } + + MT_Scalar& z() { return m_co[2]; } + const MT_Scalar& z() const { return m_co[2]; } + + MT_Scalar *getValue() { return m_co; } + const MT_Scalar *getValue() const { return m_co; } + + void getValue(float *v) const { + v[0] = float(m_co[0]); + v[1] = float(m_co[1]); + v[2] = float(m_co[2]); + } + + void getValue(double *v) const { + v[0] = double(m_co[0]); + v[1] = double(m_co[1]); + v[2] = double(m_co[2]); + } + + void setValue(const float *v) { + m_co[0] = MT_Scalar(v[0]); + m_co[1] = MT_Scalar(v[1]); + m_co[2] = MT_Scalar(v[2]); + } + + void setValue(const double *v) { + m_co[0] = MT_Scalar(v[0]); + m_co[1] = MT_Scalar(v[1]); + m_co[2] = MT_Scalar(v[2]); + } + + void setValue(MT_Scalar x, MT_Scalar y, MT_Scalar z) { + m_co[0] = x; m_co[1] = y; m_co[2] = z; + } + +protected: + MT_Scalar m_co[3]; +}; + +inline bool operator==(const MT_Tuple3& t1, const MT_Tuple3& t2) { + return t1[0] == t2[0] && t1[1] == t2[1] && t1[2] == t2[2]; +} + +inline MT_OStream& operator<<(MT_OStream& os, const MT_Tuple3& t) { + return os << t[0] << ' ' << t[1] << ' ' << t[2]; +} + +#endif diff --git a/intern/moto/include/MT_Tuple4.h b/intern/moto/include/MT_Tuple4.h new file mode 100755 index 00000000000..96ee2d1d1e1 --- /dev/null +++ b/intern/moto/include/MT_Tuple4.h @@ -0,0 +1,124 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + * Copyright (c) 2000 Gino van den Bergen <gino@acm.org> + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Gino van den Bergen makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef MT_TUPLE4_H +#define MT_TUPLE4_H + +#include "MT_Stream.h" +#include "MT_Scalar.h" + +class MT_Tuple4 { +public: + MT_Tuple4() {} + MT_Tuple4(const float *v) { setValue(v); } + MT_Tuple4(const double *v) { setValue(v); } + MT_Tuple4(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) { + setValue(x, y, z, w); + } + + MT_Scalar& operator[](int i) { return m_co[i]; } + const MT_Scalar& operator[](int i) const { return m_co[i]; } + + MT_Scalar& x() { return m_co[0]; } + const MT_Scalar& x() const { return m_co[0]; } + + MT_Scalar& y() { return m_co[1]; } + const MT_Scalar& y() const { return m_co[1]; } + + MT_Scalar& z() { return m_co[2]; } + const MT_Scalar& z() const { return m_co[2]; } + + MT_Scalar& w() { return m_co[3]; } + const MT_Scalar& w() const { return m_co[3]; } + + MT_Scalar *getValue() { return m_co; } + const MT_Scalar *getValue() const { return m_co; } + + + void getValue(float *v) const { + v[0] = float(m_co[0]); + v[1] = float(m_co[1]); + v[2] = float(m_co[2]); + v[3] = float(m_co[3]); + } + + void getValue(double *v) const { + v[0] = double(m_co[0]); + v[1] = double(m_co[1]); + v[2] = double(m_co[2]); + v[3] = double(m_co[3]); + } + + void setValue(const float *v) { + m_co[0] = MT_Scalar(v[0]); + m_co[1] = MT_Scalar(v[1]); + m_co[2] = MT_Scalar(v[2]); + m_co[3] = MT_Scalar(v[3]); + } + + void setValue(const double *v) { + m_co[0] = MT_Scalar(v[0]); + m_co[1] = MT_Scalar(v[1]); + m_co[2] = MT_Scalar(v[2]); + m_co[3] = MT_Scalar(v[3]); + } + + void setValue(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) { + m_co[0] = x; m_co[1] = y; m_co[2] = z; m_co[3] = w; + } + +protected: + MT_Scalar m_co[4]; +}; + +inline bool operator==(const MT_Tuple4& t1, const MT_Tuple4& t2) { + return t1[0] == t2[0] && t1[1] == t2[1] && t1[2] == t2[2] && t1[3] == t2[3]; +} + +inline MT_OStream& operator<<(MT_OStream& os, const MT_Tuple4& t) { + return os << t[0] << ' ' << t[1] << ' ' << t[2] << ' ' << t[3]; +} + +#endif diff --git a/intern/moto/include/MT_Vector2.h b/intern/moto/include/MT_Vector2.h new file mode 100644 index 00000000000..8cdeaacdbb0 --- /dev/null +++ b/intern/moto/include/MT_Vector2.h @@ -0,0 +1,112 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + * Copyright (c) 2000 Gino van den Bergen <gino@acm.org> + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Gino van den Bergen makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef MT_VECTOR2_H +#define MT_VECTOR2_H + +#include <MT_assert.h> +#include "MT_Tuple2.h" + +class MT_Vector2 : public MT_Tuple2 { +public: + MT_Vector2() {} + MT_Vector2(const float *v) : MT_Tuple2(v) {} + MT_Vector2(const double *v) : MT_Tuple2(v) {} + MT_Vector2(MT_Scalar x, MT_Scalar y) : MT_Tuple2(x, y) {} + + MT_Vector2& operator+=(const MT_Vector2& v); + MT_Vector2& operator-=(const MT_Vector2& v); + MT_Vector2& operator*=(MT_Scalar s); + MT_Vector2& operator/=(MT_Scalar s); + + MT_Scalar dot(const MT_Vector2& v) const; + + MT_Scalar length2() const; + MT_Scalar length() const; + + MT_Vector2 absolute() const; + + void normalize(); + MT_Vector2 normalized() const; + + void scale(MT_Scalar x, MT_Scalar y); + MT_Vector2 scaled(MT_Scalar x, MT_Scalar y) const; + + bool fuzzyZero() const; + + MT_Scalar angle(const MT_Vector2& v) const; + MT_Vector2 cross(const MT_Vector2& v) const; + MT_Scalar triple(const MT_Vector2& v1, const MT_Vector2& v2) const; + + int closestAxis() const; + + static MT_Vector2 random(); +}; + +MT_Vector2 operator+(const MT_Vector2& v1, const MT_Vector2& v2); +MT_Vector2 operator-(const MT_Vector2& v1, const MT_Vector2& v2); +MT_Vector2 operator-(const MT_Vector2& v); +MT_Vector2 operator*(const MT_Vector2& v, MT_Scalar s); +MT_Vector2 operator*(MT_Scalar s, const MT_Vector2& v); +MT_Vector2 operator/(const MT_Vector2& v, MT_Scalar s); + +MT_Scalar MT_dot(const MT_Vector2& v1, const MT_Vector2& v2); + +MT_Scalar MT_length2(const MT_Vector2& v); +MT_Scalar MT_length(const MT_Vector2& v); + +bool MT_fuzzyZero(const MT_Vector2& v); +bool MT_fuzzyEqual(const MT_Vector2& v1, const MT_Vector2& v2); + +MT_Scalar MT_angle(const MT_Vector2& v1, const MT_Vector2& v2); +MT_Vector2 MT_cross(const MT_Vector2& v1, const MT_Vector2& v2); +MT_Scalar MT_triple(const MT_Vector2& v1, const MT_Vector2& v2, + const MT_Vector2& v3); + +#ifdef GEN_INLINED +#include "MT_Vector2.inl" +#endif + +#endif diff --git a/intern/moto/include/MT_Vector2.inl b/intern/moto/include/MT_Vector2.inl new file mode 100644 index 00000000000..a4a402f2183 --- /dev/null +++ b/intern/moto/include/MT_Vector2.inl @@ -0,0 +1,89 @@ +#include "MT_Optimize.h" + +GEN_INLINE MT_Vector2& MT_Vector2::operator+=(const MT_Vector2& v) { + m_co[0] += v[0]; m_co[1] += v[1]; + return *this; +} + +GEN_INLINE MT_Vector2& MT_Vector2::operator-=(const MT_Vector2& v) { + m_co[0] -= v[0]; m_co[1] -= v[1]; + return *this; +} + +GEN_INLINE MT_Vector2& MT_Vector2::operator*=(MT_Scalar s) { + m_co[0] *= s; m_co[1] *= s; + return *this; +} + +GEN_INLINE MT_Vector2& MT_Vector2::operator/=(MT_Scalar s) { + MT_assert(!MT_fuzzyZero(s)); + return *this *= 1.0 / s; +} + +GEN_INLINE MT_Vector2 operator+(const MT_Vector2& v1, const MT_Vector2& v2) { + return MT_Vector2(v1[0] + v2[0], v1[1] + v2[1]); +} + +GEN_INLINE MT_Vector2 operator-(const MT_Vector2& v1, const MT_Vector2& v2) { + return MT_Vector2(v1[0] - v2[0], v1[1] - v2[1]); +} + +GEN_INLINE MT_Vector2 operator-(const MT_Vector2& v) { + return MT_Vector2(-v[0], -v[1]); +} + +GEN_INLINE MT_Vector2 operator*(const MT_Vector2& v, MT_Scalar s) { + return MT_Vector2(v[0] * s, v[1] * s); +} + +GEN_INLINE MT_Vector2 operator*(MT_Scalar s, const MT_Vector2& v) { return v * s; } + +GEN_INLINE MT_Vector2 operator/(const MT_Vector2& v, MT_Scalar s) { + MT_assert(!MT_fuzzyZero(s)); + return v * (1.0 / s); +} + +GEN_INLINE MT_Scalar MT_Vector2::dot(const MT_Vector2& v) const { + return m_co[0] * v[0] + m_co[1] * v[1]; +} + +GEN_INLINE MT_Scalar MT_Vector2::length2() const { return dot(*this); } +GEN_INLINE MT_Scalar MT_Vector2::length() const { return sqrt(length2()); } + +GEN_INLINE MT_Vector2 MT_Vector2::absolute() const { + return MT_Vector2(MT_abs(m_co[0]), MT_abs(m_co[1])); +} + +GEN_INLINE bool MT_Vector2::fuzzyZero() const { return MT_fuzzyZero2(length2()); } + +GEN_INLINE void MT_Vector2::normalize() { *this /= length(); } +GEN_INLINE MT_Vector2 MT_Vector2::normalized() const { return *this / length(); } + +GEN_INLINE void MT_Vector2::scale(MT_Scalar x, MT_Scalar y) { + m_co[0] *= x; m_co[1] *= y; +} + +GEN_INLINE MT_Vector2 MT_Vector2::scaled(MT_Scalar x, MT_Scalar y) const { + return MT_Vector2(m_co[0] * x, m_co[1] * y); +} + +GEN_INLINE MT_Scalar MT_Vector2::angle(const MT_Vector2& v) const { + MT_Scalar s = sqrt(length2() * v.length2()); + MT_assert(!MT_fuzzyZero(s)); + return acos(dot(v) / s); +} + + +GEN_INLINE MT_Scalar MT_dot(const MT_Vector2& v1, const MT_Vector2& v2) { + return v1.dot(v2); +} + +GEN_INLINE MT_Scalar MT_length2(const MT_Vector2& v) { return v.length2(); } +GEN_INLINE MT_Scalar MT_length(const MT_Vector2& v) { return v.length(); } + +GEN_INLINE bool MT_fuzzyZero(const MT_Vector2& v) { return v.fuzzyZero(); } +GEN_INLINE bool MT_fuzzyEqual(const MT_Vector2& v1, const MT_Vector2& v2) { + return MT_fuzzyZero(v1 - v2); +} + +GEN_INLINE MT_Scalar MT_angle(const MT_Vector2& v1, const MT_Vector2& v2) { return v1.angle(v2); } diff --git a/intern/moto/include/MT_Vector3.h b/intern/moto/include/MT_Vector3.h new file mode 100644 index 00000000000..b1578f81c51 --- /dev/null +++ b/intern/moto/include/MT_Vector3.h @@ -0,0 +1,118 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + * Copyright (c) 2000 Gino van den Bergen <gino@acm.org> + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Gino van den Bergen makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef MT_VECTOR3_H +#define MT_VECTOR3_H + +#include <MT_assert.h> +#include "MT_Tuple3.h" + +class MT_Vector3 : public MT_Tuple3 { +public: + MT_Vector3() {} + MT_Vector3(const float *v) : MT_Tuple3(v) {} + MT_Vector3(const double *v) : MT_Tuple3(v) {} + MT_Vector3(MT_Scalar x, MT_Scalar y, MT_Scalar z) : MT_Tuple3(x, y, z) {} + + MT_Vector3& operator+=(const MT_Vector3& v); + MT_Vector3& operator-=(const MT_Vector3& v); + MT_Vector3& operator*=(MT_Scalar s); + MT_Vector3& operator/=(MT_Scalar s); + + MT_Scalar dot(const MT_Vector3& v) const; + + MT_Scalar length2() const; + MT_Scalar length() const; + + MT_Vector3 absolute() const; + + void noiseGate(MT_Scalar threshold); + + void normalize(); + MT_Vector3 normalized() const; + MT_Vector3 safe_normalized() const; + + + void scale(MT_Scalar x, MT_Scalar y, MT_Scalar z); + MT_Vector3 scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z) const; + + bool fuzzyZero() const; + + MT_Scalar angle(const MT_Vector3& v) const; + MT_Vector3 cross(const MT_Vector3& v) const; + MT_Scalar triple(const MT_Vector3& v1, const MT_Vector3& v2) const; + + int closestAxis() const; + + static MT_Vector3 random(); +}; + +MT_Vector3 operator+(const MT_Vector3& v1, const MT_Vector3& v2); +MT_Vector3 operator-(const MT_Vector3& v1, const MT_Vector3& v2); +MT_Vector3 operator-(const MT_Vector3& v); +MT_Vector3 operator*(const MT_Vector3& v, MT_Scalar s); +MT_Vector3 operator*(MT_Scalar s, const MT_Vector3& v); +MT_Vector3 operator/(const MT_Vector3& v, MT_Scalar s); + +MT_Vector3 operator*(const MT_Vector3& v1, const MT_Vector3& v2); + +MT_Scalar MT_dot(const MT_Vector3& v1, const MT_Vector3& v2); + +MT_Scalar MT_length2(const MT_Vector3& v); +MT_Scalar MT_length(const MT_Vector3& v); + +bool MT_fuzzyZero(const MT_Vector3& v); +bool MT_fuzzyEqual(const MT_Vector3& v1, const MT_Vector3& v2); + +MT_Scalar MT_angle(const MT_Vector3& v1, const MT_Vector3& v2); +MT_Vector3 MT_cross(const MT_Vector3& v1, const MT_Vector3& v2); +MT_Scalar MT_triple(const MT_Vector3& v1, const MT_Vector3& v2, + const MT_Vector3& v3); + +#ifdef GEN_INLINED +#include "MT_Vector3.inl" +#endif + +#endif diff --git a/intern/moto/include/MT_Vector3.inl b/intern/moto/include/MT_Vector3.inl new file mode 100644 index 00000000000..7d65970fe96 --- /dev/null +++ b/intern/moto/include/MT_Vector3.inl @@ -0,0 +1,134 @@ +#include "MT_Optimize.h" + +GEN_INLINE MT_Vector3& MT_Vector3::operator+=(const MT_Vector3& v) { + m_co[0] += v[0]; m_co[1] += v[1]; m_co[2] += v[2]; + return *this; +} + +GEN_INLINE MT_Vector3& MT_Vector3::operator-=(const MT_Vector3& v) { + m_co[0] -= v[0]; m_co[1] -= v[1]; m_co[2] -= v[2]; + return *this; +} + +GEN_INLINE MT_Vector3& MT_Vector3::operator*=(MT_Scalar s) { + m_co[0] *= s; m_co[1] *= s; m_co[2] *= s; + return *this; +} + +GEN_INLINE MT_Vector3& MT_Vector3::operator/=(MT_Scalar s) { + MT_assert(!MT_fuzzyZero(s)); + return *this *= MT_Scalar(1.0) / s; +} + +GEN_INLINE MT_Vector3 operator+(const MT_Vector3& v1, const MT_Vector3& v2) { + return MT_Vector3(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]); +} + +GEN_INLINE MT_Vector3 operator-(const MT_Vector3& v1, const MT_Vector3& v2) { + return MT_Vector3(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]); +} + +GEN_INLINE MT_Vector3 operator-(const MT_Vector3& v) { + return MT_Vector3(-v[0], -v[1], -v[2]); +} + +GEN_INLINE MT_Vector3 operator*(const MT_Vector3& v, MT_Scalar s) { + return MT_Vector3(v[0] * s, v[1] * s, v[2] * s); +} + +GEN_INLINE MT_Vector3 operator*(MT_Scalar s, const MT_Vector3& v) { return v * s; } + +GEN_INLINE MT_Vector3 operator/(const MT_Vector3& v, MT_Scalar s) { + MT_assert(!MT_fuzzyZero(s)); + return v * (MT_Scalar(1.0) / s); +} + +GEN_INLINE MT_Vector3 operator*(const MT_Vector3& v1, const MT_Vector3& v2) { + return MT_Vector3(v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]); +} + +GEN_INLINE MT_Scalar MT_Vector3::dot(const MT_Vector3& v) const { + return m_co[0] * v[0] + m_co[1] * v[1] + m_co[2] * v[2]; +} + +GEN_INLINE MT_Scalar MT_Vector3::length2() const { return dot(*this); } +GEN_INLINE MT_Scalar MT_Vector3::length() const { return sqrt(length2()); } + +GEN_INLINE MT_Vector3 MT_Vector3::absolute() const { + return MT_Vector3(MT_abs(m_co[0]), MT_abs(m_co[1]), MT_abs(m_co[2])); +} + +GEN_INLINE bool MT_Vector3::fuzzyZero() const { + return MT_fuzzyZero(length2()); +} + +GEN_INLINE void MT_Vector3::noiseGate(MT_Scalar threshold) { + if (length2() < threshold) { + setValue(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0)); + } +} + +GEN_INLINE void MT_Vector3::normalize() { *this /= length(); } +GEN_INLINE MT_Vector3 MT_Vector3::normalized() const { return *this / length(); } +GEN_INLINE MT_Vector3 MT_Vector3::safe_normalized() const { + MT_Scalar len = length(); + return MT_fuzzyZero(len) ? + MT_Vector3(MT_Scalar(1.0), MT_Scalar(0.0), MT_Scalar(0.0)) : + *this / len; +} + +GEN_INLINE void MT_Vector3::scale(MT_Scalar x, MT_Scalar y, MT_Scalar z) { + m_co[0] *= x; m_co[1] *= y; m_co[2] *= z; +} + +GEN_INLINE MT_Vector3 MT_Vector3::scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z) const { + return MT_Vector3(m_co[0] * x, m_co[1] * y, m_co[2] * z); +} + +GEN_INLINE MT_Scalar MT_Vector3::angle(const MT_Vector3& v) const { + MT_Scalar s = sqrt(length2() * v.length2()); + MT_assert(!MT_fuzzyZero(s)); + return acos(dot(v) / s); +} + +GEN_INLINE MT_Vector3 MT_Vector3::cross(const MT_Vector3& v) const { + return MT_Vector3(m_co[1] * v[2] - m_co[2] * v[1], + m_co[2] * v[0] - m_co[0] * v[2], + m_co[0] * v[1] - m_co[1] * v[0]); +} + +GEN_INLINE MT_Scalar MT_Vector3::triple(const MT_Vector3& v1, const MT_Vector3& v2) const { + return m_co[0] * (v1[1] * v2[2] - v1[2] * v2[1]) + + m_co[1] * (v1[2] * v2[0] - v1[0] * v2[2]) + + m_co[2] * (v1[0] * v2[1] - v1[1] * v2[0]); +} + +GEN_INLINE int MT_Vector3::closestAxis() const { + MT_Vector3 a = absolute(); + return a[0] < a[1] ? (a[1] < a[2] ? 2 : 1) : (a[0] < a[2] ? 2 : 0); +} + +GEN_INLINE MT_Vector3 MT_Vector3::random() { + MT_Scalar z = MT_Scalar(2.0) * MT_random() - MT_Scalar(1.0); + MT_Scalar r = sqrt(MT_Scalar(1.0) - z * z); + MT_Scalar t = MT_2_PI * MT_random(); + return MT_Vector3(r * cos(t), r * sin(t), z); +} + +GEN_INLINE MT_Scalar MT_dot(const MT_Vector3& v1, const MT_Vector3& v2) { + return v1.dot(v2); +} + +GEN_INLINE MT_Scalar MT_length2(const MT_Vector3& v) { return v.length2(); } +GEN_INLINE MT_Scalar MT_length(const MT_Vector3& v) { return v.length(); } + +GEN_INLINE bool MT_fuzzyZero(const MT_Vector3& v) { return v.fuzzyZero(); } +GEN_INLINE bool MT_fuzzyEqual(const MT_Vector3& v1, const MT_Vector3& v2) { + return MT_fuzzyZero(v1 - v2); +} + +GEN_INLINE MT_Scalar MT_angle(const MT_Vector3& v1, const MT_Vector3& v2) { return v1.angle(v2); } +GEN_INLINE MT_Vector3 MT_cross(const MT_Vector3& v1, const MT_Vector3& v2) { return v1.cross(v2); } +GEN_INLINE MT_Scalar MT_triple(const MT_Vector3& v1, const MT_Vector3& v2, const MT_Vector3& v3) { + return v1.triple(v2, v3); +} diff --git a/intern/moto/include/MT_Vector4.h b/intern/moto/include/MT_Vector4.h new file mode 100644 index 00000000000..32b71f950b8 --- /dev/null +++ b/intern/moto/include/MT_Vector4.h @@ -0,0 +1,102 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + * Copyright (c) 2000 Gino van den Bergen <gino@acm.org> + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Gino van den Bergen makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef MT_VECTOR4_H +#define MT_VECTOR4_H + +#include <MT_assert.h> + +#include "MT_Tuple4.h" + +class MT_Vector4 : public MT_Tuple4 { +public: + MT_Vector4() {} + MT_Vector4(const float *v) : MT_Tuple4(v) {} + MT_Vector4(const double *v) : MT_Tuple4(v) {} + MT_Vector4(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) : + MT_Tuple4(x, y, z, w) {} + + MT_Vector4& operator+=(const MT_Vector4& v); + MT_Vector4& operator-=(const MT_Vector4& v); + MT_Vector4& operator*=(MT_Scalar s); + MT_Vector4& operator/=(MT_Scalar s); + + MT_Scalar dot(const MT_Vector4& v) const; + + MT_Scalar length2() const; + MT_Scalar length() const; + + MT_Vector4 absolute() const; + + void normalize(); + MT_Vector4 normalized() const; + + void scale(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w); + MT_Vector4 scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) const; + + bool fuzzyZero() const; +}; + +MT_Vector4 operator+(const MT_Vector4& v1, const MT_Vector4& v2); +MT_Vector4 operator-(const MT_Vector4& v1, const MT_Vector4& v2); +MT_Vector4 operator-(const MT_Vector4& v); +MT_Vector4 operator*(const MT_Vector4& v, MT_Scalar s); +MT_Vector4 operator*(MT_Scalar s, const MT_Vector4& v); +MT_Vector4 operator/(const MT_Vector4& v, MT_Scalar s); + +MT_Scalar MT_dot(const MT_Vector4& v1, const MT_Vector4& v2); + +MT_Scalar MT_length2(const MT_Vector4& v); +MT_Scalar MT_length(const MT_Vector4& v); + +bool MT_fuzzyZero(const MT_Vector4& v); +bool MT_fuzzyEqual(const MT_Vector4& v1, const MT_Vector4& v2); + +#ifdef GEN_INLINED +#include "MT_Vector4.inl" +#endif + +#endif + diff --git a/intern/moto/include/MT_Vector4.inl b/intern/moto/include/MT_Vector4.inl new file mode 100644 index 00000000000..762c1c49c50 --- /dev/null +++ b/intern/moto/include/MT_Vector4.inl @@ -0,0 +1,80 @@ +#include "MT_Optimize.h" + +GEN_INLINE MT_Vector4& MT_Vector4::operator+=(const MT_Vector4& v) { + m_co[0] += v[0]; m_co[1] += v[1]; m_co[2] += v[2]; m_co[3] += v[3]; + return *this; +} + +GEN_INLINE MT_Vector4& MT_Vector4::operator-=(const MT_Vector4& v) { + m_co[0] -= v[0]; m_co[1] -= v[1]; m_co[2] -= v[2]; m_co[3] -= v[3]; + return *this; +} + +GEN_INLINE MT_Vector4& MT_Vector4::operator*=(MT_Scalar s) { + m_co[0] *= s; m_co[1] *= s; m_co[2] *= s; m_co[3] *= s; + return *this; +} + +GEN_INLINE MT_Vector4& MT_Vector4::operator/=(MT_Scalar s) { + MT_assert(!MT_fuzzyZero(s)); + return *this *= MT_Scalar(1.0) / s; +} + +GEN_INLINE MT_Vector4 operator+(const MT_Vector4& v1, const MT_Vector4& v2) { + return MT_Vector4(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2], v1[3] + v2[3]); +} + +GEN_INLINE MT_Vector4 operator-(const MT_Vector4& v1, const MT_Vector4& v2) { + return MT_Vector4(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2], v1[3] - v2[3]); +} + +GEN_INLINE MT_Vector4 operator-(const MT_Vector4& v) { + return MT_Vector4(-v[0], -v[1], -v[2], -v[3]); +} + +GEN_INLINE MT_Vector4 operator*(const MT_Vector4& v, MT_Scalar s) { + return MT_Vector4(v[0] * s, v[1] * s, v[2] * s, v[3] * s); +} + +GEN_INLINE MT_Vector4 operator*(MT_Scalar s, const MT_Vector4& v) { return v * s; } + +GEN_INLINE MT_Vector4 operator/(const MT_Vector4& v, MT_Scalar s) { + MT_assert(!MT_fuzzyZero(s)); + return v * (MT_Scalar(1.0) / s); +} + +GEN_INLINE MT_Scalar MT_Vector4::dot(const MT_Vector4& v) const { + return m_co[0] * v[0] + m_co[1] * v[1] + m_co[2] * v[2] + m_co[3] * v[3]; +} + +GEN_INLINE MT_Scalar MT_Vector4::length2() const { return MT_dot(*this, *this); } +GEN_INLINE MT_Scalar MT_Vector4::length() const { return sqrt(length2()); } + +GEN_INLINE MT_Vector4 MT_Vector4::absolute() const { + return MT_Vector4(MT_abs(m_co[0]), MT_abs(m_co[1]), MT_abs(m_co[2]), MT_abs(m_co[3])); +} + +GEN_INLINE void MT_Vector4::scale(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) { + m_co[0] *= x; m_co[1] *= y; m_co[2] *= z; m_co[3] *= w; +} + +GEN_INLINE MT_Vector4 MT_Vector4::scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) const { + return MT_Vector4(m_co[0] * x, m_co[1] * y, m_co[2] * z, m_co[3] * w); +} + +GEN_INLINE bool MT_Vector4::fuzzyZero() const { return MT_fuzzyZero2(length2()); } + +GEN_INLINE void MT_Vector4::normalize() { *this /= length(); } +GEN_INLINE MT_Vector4 MT_Vector4::normalized() const { return *this / length(); } + +GEN_INLINE MT_Scalar MT_dot(const MT_Vector4& v1, const MT_Vector4& v2) { + return v1.dot(v2); +} + +GEN_INLINE MT_Scalar MT_length2(const MT_Vector4& v) { return v.length2(); } +GEN_INLINE MT_Scalar MT_length(const MT_Vector4& v) { return v.length(); } + +GEN_INLINE bool MT_fuzzyZero(const MT_Vector4& v) { return v.fuzzyZero(); } +GEN_INLINE bool MT_fuzzyEqual(const MT_Vector4& v1, const MT_Vector4& v2) { + return MT_fuzzyZero(v1 - v2); +} diff --git a/intern/moto/include/MT_assert.h b/intern/moto/include/MT_assert.h new file mode 100644 index 00000000000..392bcac311b --- /dev/null +++ b/intern/moto/include/MT_assert.h @@ -0,0 +1,51 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef MT_ASSERT_H + +#define MT_ASSERT_H + +#ifdef MT_NDEBUG + +#define MT_assert(predicate) ((void)0) + +#else + +#include <assert.h> + +#define MT_assert(predicate) assert(predicate) + +#endif /* MT_NDEBUG */ + +#endif + + + diff --git a/intern/moto/include/MT_random.h b/intern/moto/include/MT_random.h new file mode 100755 index 00000000000..adfe31f9c41 --- /dev/null +++ b/intern/moto/include/MT_random.h @@ -0,0 +1,44 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef MT_RANDOM_H + +#define MT_RANDOM_H + +#include <limits.h> + +#define MT_RAND_MAX ULONG_MAX + +extern void MT_srand(unsigned long); +extern unsigned long MT_rand(); + +#endif + diff --git a/intern/moto/include/NM_Scalar.h b/intern/moto/include/NM_Scalar.h new file mode 100644 index 00000000000..98b14ed7ee0 --- /dev/null +++ b/intern/moto/include/NM_Scalar.h @@ -0,0 +1,166 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <math.h> + +#include <iostream> + +template <class T> +class NM_Scalar { +public: + NM_Scalar() {} + explicit NM_Scalar(T value, T error = 0.0) : + m_value(value), m_error(error) {} + + T getValue() const { return m_value; } + T getError() const { return m_error; } + + operator T() const { return m_value; } + + NM_Scalar operator-() const { + return NM_Scalar<T>(-m_value, m_error); + } + + NM_Scalar& operator=(T value) { + m_value = value; + m_error = 0.0; + return *this; + } + + NM_Scalar& operator+=(const NM_Scalar& x) { + m_value += x.m_value; + m_error = (fabs(m_value) * (m_error + 1.0) + + fabs(x.m_value) * (x.m_error + 1.0)) / + fabs(m_value + x.m_value); + return *this; + } + + NM_Scalar& operator-=(const NM_Scalar& x) { + m_value -= x.m_value; + m_error = (fabs(m_value) * (m_error + 1.0) + + fabs(x.m_value) * (x.m_error + 1.0)) / + fabs(m_value - x.m_value); + return *this; + } + + NM_Scalar& operator*=(const NM_Scalar& x) { + m_value *= x.m_value; + m_error += x.m_error + 1.0; + return *this; + } + + NM_Scalar& operator/=(const NM_Scalar& x) { + m_value /= x.m_value; + m_error += x.m_error + 1.0; + return *this; + } + +private: + T m_value; + T m_error; +}; + +template <class T> +inline NM_Scalar<T> operator+(const NM_Scalar<T>& x, const NM_Scalar<T>& y) { + return x.getValue() == 0.0 && y.getValue() == 0.0 ? + NM_Scalar<T>(0.0, 0.0) : + NM_Scalar<T>(x.getValue() + y.getValue(), + (fabs(x.getValue()) * (x.getError() + 1.0) + + fabs(y.getValue()) * (y.getError() + 1.0)) / + fabs(x.getValue() + y.getValue())); +} + +template <class T> +inline NM_Scalar<T> operator-(const NM_Scalar<T>& x, const NM_Scalar<T>& y) { + return x.getValue() == 0.0 && y.getValue() == 0.0 ? + NM_Scalar<T>(0.0, 0.0) : + NM_Scalar<T>(x.getValue() - y.getValue(), + (fabs(x.getValue()) * (x.getError() + 1.0) + + fabs(y.getValue()) * (y.getError() + 1.0)) / + fabs(x.getValue() - y.getValue())); +} + +template <class T> +inline NM_Scalar<T> operator*(const NM_Scalar<T>& x, const NM_Scalar<T>& y) { + return NM_Scalar<T>(x.getValue() * y.getValue(), + x.getError() + y.getError() + 1.0); +} + +template <class T> +inline NM_Scalar<T> operator/(const NM_Scalar<T>& x, const NM_Scalar<T>& y) { + return NM_Scalar<T>(x.getValue() / y.getValue(), + x.getError() + y.getError() + 1.0); +} + +template <class T> +inline std::ostream& operator<<(std::ostream& os, const NM_Scalar<T>& x) { + return os << x.getValue() << '[' << x.getError() << ']'; +} + +template <class T> +inline NM_Scalar<T> sqrt(const NM_Scalar<T>& x) { + return NM_Scalar<T>(sqrt(x.getValue()), + 0.5 * x.getError() + 1.0); +} + +template <class T> +inline NM_Scalar<T> acos(const NM_Scalar<T>& x) { + return NM_Scalar<T>(acos(x.getValue()), x.getError() + 1.0); +} + +template <class T> +inline NM_Scalar<T> cos(const NM_Scalar<T>& x) { + return NM_Scalar<T>(cos(x.getValue()), x.getError() + 1.0); +} + +template <class T> +inline NM_Scalar<T> sin(const NM_Scalar<T>& x) { + return NM_Scalar<T>(sin(x.getValue()), x.getError() + 1.0); +} + +template <class T> +inline NM_Scalar<T> fabs(const NM_Scalar<T>& x) { + return NM_Scalar<T>(fabs(x.getValue()), x.getError()); +} + +template <class T> +inline NM_Scalar<T> pow(const NM_Scalar<T>& x, const NM_Scalar<T>& y) { + return NM_Scalar<T>(pow(x.getValue(), y.getValue()), + fabs(y.getValue()) * x.getError() + 1.0); +} + + + + + + + + diff --git a/intern/moto/intern/MT_CmMatrix4x4.cpp b/intern/moto/intern/MT_CmMatrix4x4.cpp new file mode 100755 index 00000000000..0cc830980a0 --- /dev/null +++ b/intern/moto/intern/MT_CmMatrix4x4.cpp @@ -0,0 +1,237 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + + +#include "MT_CmMatrix4x4.h" +#include "MT_Vector3.h" +#include "MT_Point3.h" + + +MT_CmMatrix4x4::MT_CmMatrix4x4() +{ + Identity(); +} + + + +MT_CmMatrix4x4::MT_CmMatrix4x4(const float value[4][4]) +{ + for (int i=0;i<4;i++) + { + for (int j=0;j<4;j++) + m_V[i][j] = value[i][j]; + } +} + + + +MT_CmMatrix4x4::MT_CmMatrix4x4(const double value[16]) +{ + for (int i=0;i<16;i++) + m_Vflat[i] = value[i]; +} + + + +MT_CmMatrix4x4::MT_CmMatrix4x4(const MT_CmMatrix4x4& other) +{ + SetMatrix(other); +} + + + +MT_CmMatrix4x4::MT_CmMatrix4x4(const MT_Point3& orig, + const MT_Vector3& dir, + const MT_Vector3 up) +{ + MT_Vector3 z = -(dir.normalized()); + MT_Vector3 x = (up.cross(z)).normalized(); + MT_Vector3 y = (z.cross(x)); + + m_V[0][0] = x.x(); + m_V[0][1] = y.x(); + m_V[0][2] = z.x(); + m_V[0][3] = 0.0f; + + m_V[1][0] = x.y(); + m_V[1][1] = y.y(); + m_V[1][2] = z.y(); + m_V[1][3] = 0.0f; + + m_V[2][0] = x.z(); + m_V[2][1] = y.z(); + m_V[2][2] = z.z(); + m_V[2][3] = 0.0f; + + m_V[3][0] = orig.x();//0.0f; + m_V[3][1] = orig.y();//0.0f; + m_V[3][2] = orig.z();//0.0f; + m_V[3][3] = 1.0f; + + //Translate(-orig); +} + + + +MT_Vector3 MT_CmMatrix4x4::GetRight() const +{ + return MT_Vector3(m_V[0][0], m_V[0][1], m_V[0][2]); +} + + + +MT_Vector3 MT_CmMatrix4x4::GetUp() const +{ + return MT_Vector3(m_V[1][0], m_V[1][1], m_V[1][2]); +} + + + +MT_Vector3 MT_CmMatrix4x4::GetDir() const +{ + return MT_Vector3(m_V[2][0], m_V[2][1], m_V[2][2]); +} + + + +MT_Point3 MT_CmMatrix4x4::GetPos() const +{ + return MT_Point3(m_V[3][0], m_V[3][1], m_V[3][2]); +} + + + +void MT_CmMatrix4x4::Identity() +{ + for (int i=0; i<4; i++) + { + for (int j=0; j<4; j++) + m_V[i][j] = (i==j?1.0f:0.0f); + } +} + + + +void MT_CmMatrix4x4::SetMatrix(const MT_CmMatrix4x4& other) +{ + for (int i=0; i<16; i++) + m_Vflat[i] = other.m_Vflat[i]; +} + + + +double* MT_CmMatrix4x4::getPointer() +{ + return &m_V[0][0]; +} + + + +const double* MT_CmMatrix4x4::getPointer() const +{ + return &m_V[0][0]; +} + + + +void MT_CmMatrix4x4::setElem(int pos,double newvalue) +{ + m_Vflat[pos] = newvalue; +} + +MT_CmMatrix4x4 MT_CmMatrix4x4::Perspective( + MT_Scalar inLeft, + MT_Scalar inRight, + MT_Scalar inBottom, + MT_Scalar inTop, + MT_Scalar inNear, + MT_Scalar inFar +){ + + MT_CmMatrix4x4 mat; + + // Column 0 + mat(0, 0) = -(2.0*inNear) / (inRight-inLeft); + mat(1, 0) = 0; + mat(2, 0) = 0; + mat(3, 0) = 0; + + // Column 1 + mat(0, 1) = 0; + mat(1, 1) = (2.0*inNear) / (inTop-inBottom); + mat(2, 1) = 0; + mat(3, 1) = 0; + + // Column 2 + mat(0, 2) = (inRight+inLeft) / (inRight-inLeft); + mat(1, 2) = (inTop+inBottom) / (inTop-inBottom); + mat(2, 2) = -(inFar+inNear) / (inFar-inNear); + mat(3, 2) = -1; + + // Column 3 + mat(0, 3) = 0; + mat(1, 3) = 0; + mat(2, 3) = -(2.0*inFar*inNear) / (inFar-inNear); + mat(3, 3) = 0; + + return mat; +} diff --git a/intern/moto/intern/MT_Matrix3x3.cpp b/intern/moto/intern/MT_Matrix3x3.cpp new file mode 100644 index 00000000000..ded09a6b851 --- /dev/null +++ b/intern/moto/intern/MT_Matrix3x3.cpp @@ -0,0 +1,37 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "MT_Matrix3x3.h" + + +#ifndef GEN_INLINED +#include "MT_Matrix3x3.inl" +#endif diff --git a/intern/moto/intern/MT_Matrix4x4.cpp b/intern/moto/intern/MT_Matrix4x4.cpp new file mode 100644 index 00000000000..ce2c3bcf616 --- /dev/null +++ b/intern/moto/intern/MT_Matrix4x4.cpp @@ -0,0 +1,37 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "MT_Matrix4x4.h" + + +#ifndef GEN_INLINED +#include "MT_Matrix4x4.inl" +#endif diff --git a/intern/moto/intern/MT_Plane3.cpp b/intern/moto/intern/MT_Plane3.cpp new file mode 100644 index 00000000000..01d10dac5b9 --- /dev/null +++ b/intern/moto/intern/MT_Plane3.cpp @@ -0,0 +1,68 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + + +#ifndef GEN_INLINED +#include "MT_Plane3.h" +#include "MT_Plane3.inl" +#endif + diff --git a/intern/moto/intern/MT_Point3.cpp b/intern/moto/intern/MT_Point3.cpp new file mode 100644 index 00000000000..4d704e4949a --- /dev/null +++ b/intern/moto/intern/MT_Point3.cpp @@ -0,0 +1,37 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "MT_Point3.h" + + +#ifndef GEN_INLINED +#include "MT_Point3.inl" +#endif diff --git a/intern/moto/intern/MT_Quaternion.cpp b/intern/moto/intern/MT_Quaternion.cpp new file mode 100644 index 00000000000..eb55ed45f5d --- /dev/null +++ b/intern/moto/intern/MT_Quaternion.cpp @@ -0,0 +1,37 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "MT_Quaternion.h" + + +#ifndef GEN_INLINED +#include "MT_Quaternion.inl" +#endif diff --git a/intern/moto/intern/MT_Transform.cpp b/intern/moto/intern/MT_Transform.cpp new file mode 100644 index 00000000000..31af8223a4f --- /dev/null +++ b/intern/moto/intern/MT_Transform.cpp @@ -0,0 +1,138 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + MOTTO - 3D Motion Toolkit + Copyright (C) 2000 Gino van den Bergen <gino@acm.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "MT_Transform.h" + +void MT_Transform::setValue(const float *m) { + m_basis.setValue(m); + m_origin.setValue(&m[12]); + m_type = AFFINE; +} + +void MT_Transform::setValue(const double *m) { + m_basis.setValue(m); + m_origin.setValue(&m[12]); + m_type = AFFINE; +} + +void MT_Transform::getValue(float *m) const { + m_basis.getValue(m); + m_origin.getValue(&m[12]); + m[15] = 1.0; +} + +void MT_Transform::getValue(double *m) const { + m_basis.getValue(m); + m_origin.getValue(&m[12]); + m[15] = 1.0; +} + +MT_Transform& MT_Transform::operator*=(const MT_Transform& t) { + m_origin += m_basis * t.m_origin; + m_basis *= t.m_basis; + m_type |= t.m_type; + return *this; +} + +void MT_Transform::translate(const MT_Vector3& v) { + m_origin += m_basis * v; + m_type |= TRANSLATION; +} + +void MT_Transform::rotate(const MT_Quaternion& q) { + m_basis *= MT_Matrix3x3(q); + m_type |= ROTATION; +} + +void MT_Transform::scale(MT_Scalar x, MT_Scalar y, MT_Scalar z) { + m_basis.scale(x, y, z); + m_type |= SCALING; +} + +void MT_Transform::setIdentity() { + m_basis.setIdentity(); + m_origin.setValue(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0)); + m_type = IDENTITY; +} + +void MT_Transform::invert(const MT_Transform& t) { + m_basis = t.m_type & SCALING ? + t.m_basis.inverse() : + t.m_basis.transposed(); + m_origin.setValue(-MT_dot(m_basis[0], t.m_origin), + -MT_dot(m_basis[1], t.m_origin), + -MT_dot(m_basis[2], t.m_origin)); + m_type = t.m_type; +} + +void MT_Transform::mult(const MT_Transform& t1, const MT_Transform& t2) { + m_basis = t1.m_basis * t2.m_basis; + m_origin = t1(t2.m_origin); + m_type = t1.m_type | t2.m_type; +} + +void MT_Transform::multInverseLeft(const MT_Transform& t1, const MT_Transform& t2) { + MT_Vector3 v = t2.m_origin - t1.m_origin; + if (t1.m_type & SCALING) { + MT_Matrix3x3 inv = t1.m_basis.inverse(); + m_basis = inv * t2.m_basis; + m_origin = inv * v; + } + else { + m_basis = MT_multTransposeLeft(t1.m_basis, t2.m_basis); + m_origin = v * t1.m_basis; + } + m_type = t1.m_type | t2.m_type; +} + + + diff --git a/intern/moto/intern/MT_Vector2.cpp b/intern/moto/intern/MT_Vector2.cpp new file mode 100644 index 00000000000..93284098195 --- /dev/null +++ b/intern/moto/intern/MT_Vector2.cpp @@ -0,0 +1,37 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "MT_Vector2.h" + + +#ifndef GEN_INLINED +#include "MT_Vector2.inl" +#endif diff --git a/intern/moto/intern/MT_Vector3.cpp b/intern/moto/intern/MT_Vector3.cpp new file mode 100644 index 00000000000..fe5861b0a41 --- /dev/null +++ b/intern/moto/intern/MT_Vector3.cpp @@ -0,0 +1,37 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "MT_Vector3.h" + + +#ifndef GEN_INLINED +#include "MT_Vector3.inl" +#endif diff --git a/intern/moto/intern/MT_Vector4.cpp b/intern/moto/intern/MT_Vector4.cpp new file mode 100644 index 00000000000..db77b20130c --- /dev/null +++ b/intern/moto/intern/MT_Vector4.cpp @@ -0,0 +1,37 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "MT_Vector4.h" + + +#ifndef GEN_INLINED +#include "MT_Vector4.inl" +#endif diff --git a/intern/moto/intern/MT_random.cpp b/intern/moto/intern/MT_random.cpp new file mode 100755 index 00000000000..72e7c373201 --- /dev/null +++ b/intern/moto/intern/MT_random.cpp @@ -0,0 +1,142 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* A C-program for MT19937: Real number version */ + +/* genrand() generates one pseudorandom real number (double) */ +/* which is uniformly distributed on [0,1]-interval, for each */ +/* call. sgenrand(seed) set initial values to the working area */ +/* of 624 words. Before genrand(), sgenrand(seed) must be */ +/* called once. (seed is any 32-bit integer except for 0). */ +/* Integer generator is obtained by modifying two lines. */ +/* Coded by Takuji Nishimura, considering the suggestions by */ +/* Topher Cooper and Marc Rieffel in July-Aug. 1997. */ + +/* This library is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public */ +/* License as published by the Free Software Foundation; either */ +/* version 2 of the License, or (at your option) any later */ +/* version. */ +/* This library is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ +/* See the GNU Library General Public License for more details. */ +/* You should have received a copy of the GNU Library General */ +/* Public License along with this library; if not, write to the */ +/* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */ +/* 02111-1307 USA */ + +/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. */ +/* When you use this, send an email to: matumoto@math.keio.ac.jp */ +/* with an appropriate reference to your work. */ + +#include "MT_random.h" + +/* Period parameters */ +#define N 624 +#define M 397 +#define MATRIX_A 0x9908b0df /* constant vector a */ +#define UPPER_MASK 0x80000000 /* most significant w-r bits */ +#define LOWER_MASK 0x7fffffff /* least significant r bits */ + +/* Tempering parameters */ +#define TEMPERING_MASK_B 0x9d2c5680 +#define TEMPERING_MASK_C 0xefc60000 +#define TEMPERING_SHIFT_U(y) (y >> 11) +#define TEMPERING_SHIFT_S(y) (y << 7) +#define TEMPERING_SHIFT_T(y) (y << 15) +#define TEMPERING_SHIFT_L(y) (y >> 18) + +static unsigned long mt[N]; /* the array for the state vector */ +static int mti = N+1; /* mti==N+1 means mt[N] is not initialized */ + +/* initializing the array with a NONZERO seed */ +void MT_srand(unsigned long seed) +{ + /* setting initial seeds to mt[N] using */ + /* the generator Line 25 of Table 1 in */ + /* [KNUTH 1981, The Art of Computer Programming */ + /* Vol. 2 (2nd Ed.), pp102] */ + mt[0] = seed & 0xffffffff; + for (mti = 1; mti < N; mti++) + mt[mti] = (69069 * mt[mti-1]) & 0xffffffff; +} + +unsigned long MT_rand() +{ + static unsigned long mag01[2] = { 0x0, MATRIX_A }; + /* mag01[x] = x * MATRIX_A for x=0,1 */ + + unsigned long y; + + if (mti >= N) { /* generate N words at one time */ + int kk; + + if (mti == N+1) /* if sgenrand() has not been called, */ + MT_srand(4357); /* a default initial seed is used */ + + for (kk = 0; kk < N - M; kk++) { + y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); + mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1]; + } + for (; kk < N-1; kk++) { + y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); + mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1]; + } + y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); + mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1]; + + mti = 0; + } + + y = mt[mti++]; + y ^= TEMPERING_SHIFT_U(y); + y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B; + y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C; + y ^= TEMPERING_SHIFT_L(y); + + return y; +} + +#undef N +#undef M +#undef MATRIX_A +#undef UPPER_MASK +#undef LOWER_MASK + +/* Tempering parameters */ +#undef TEMPERING_MASK_B +#undef TEMPERING_MASK_C +#undef TEMPERING_SHIFT_U +#undef TEMPERING_SHIFT_S +#undef TEMPERING_SHIFT_T +#undef TEMPERING_SHIFT_L + diff --git a/intern/moto/intern/Makefile b/intern/moto/intern/Makefile new file mode 100644 index 00000000000..eeba381ab2a --- /dev/null +++ b/intern/moto/intern/Makefile @@ -0,0 +1,42 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# moto intern Makefile +# + +LIBNAME = moto +DIR = $(OCGDIR)/intern/$(LIBNAME) + +include nan_compile.mk + +CCFLAGS += $(LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I../include + diff --git a/intern/moto/make/msvc_6_0/MoTo.dsp b/intern/moto/make/msvc_6_0/MoTo.dsp new file mode 100755 index 00000000000..b2e70ac7255 --- /dev/null +++ b/intern/moto/make/msvc_6_0/MoTo.dsp @@ -0,0 +1,379 @@ +# Microsoft Developer Studio Project File - Name="MoTo" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=MoTo - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "MoTo.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "MoTo.mak" CFG="MoTo - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "MoTo - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "MoTo - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "MoTo - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W4 /GX /O2 /Ob2 /I "..\..\include\\" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x413 /d "NDEBUG" +# ADD RSC /l 0x413 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Release\libmoto.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=ECHO Copying header files COPY "..\..\include\*.h" "..\..\..\..\lib\windows\moto\include" ECHO Copying lib COPY "Release\libmoto.lib" "..\..\..\..\lib\windows\moto\lib\libmoto.a" ECHO Done +# End Special Build Tool + +!ELSEIF "$(CFG)" == "MoTo - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\include\\" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x413 /d "_DEBUG" +# ADD RSC /l 0x413 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\libmoto.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=ECHO Copying header files COPY "..\..\include\*.h" "..\..\..\..\lib\windows\moto\include" ECHO Copying lib COPY "Debug\libmoto.lib" "..\..\..\..\lib\windows\moto\lib\debug\libmoto.a" ECHO Copying Debug info. COPY "Debug\vc60.*" "..\..\..\..\lib\windows\moto\lib\debug\" ECHO Done +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "MoTo - Win32 Release" +# Name "MoTo - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\intern\MT_CmMatrix4x4.cpp + +!IF "$(CFG)" == "MoTo - Win32 Release" + +# ADD CPP /W3 /I "../../include" + +!ELSEIF "$(CFG)" == "MoTo - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\intern\MT_Matrix3x3.cpp + +!IF "$(CFG)" == "MoTo - Win32 Release" + +# ADD CPP /W3 /I "../../include" + +!ELSEIF "$(CFG)" == "MoTo - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\intern\MT_Matrix4x4.cpp + +!IF "$(CFG)" == "MoTo - Win32 Release" + +# ADD CPP /W3 /I "../../include" + +!ELSEIF "$(CFG)" == "MoTo - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\intern\MT_Plane3.cpp + +!IF "$(CFG)" == "MoTo - Win32 Release" + +# ADD CPP /W3 + +!ELSEIF "$(CFG)" == "MoTo - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\intern\MT_Point3.cpp + +!IF "$(CFG)" == "MoTo - Win32 Release" + +# ADD CPP /W3 /I "../../include" + +!ELSEIF "$(CFG)" == "MoTo - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\intern\MT_Quaternion.cpp + +!IF "$(CFG)" == "MoTo - Win32 Release" + +# ADD CPP /W3 /I "../../include" + +!ELSEIF "$(CFG)" == "MoTo - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\intern\MT_random.cpp + +!IF "$(CFG)" == "MoTo - Win32 Release" + +# ADD CPP /W3 /I "../../include" + +!ELSEIF "$(CFG)" == "MoTo - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\intern\MT_Transform.cpp + +!IF "$(CFG)" == "MoTo - Win32 Release" + +# ADD CPP /W3 /I "../../include" + +!ELSEIF "$(CFG)" == "MoTo - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\intern\MT_Vector2.cpp + +!IF "$(CFG)" == "MoTo - Win32 Release" + +# ADD CPP /W3 /I "../../include" + +!ELSEIF "$(CFG)" == "MoTo - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\intern\MT_Vector3.cpp + +!IF "$(CFG)" == "MoTo - Win32 Release" + +# ADD CPP /W3 /I "../../include" + +!ELSEIF "$(CFG)" == "MoTo - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\intern\MT_Vector4.cpp + +!IF "$(CFG)" == "MoTo - Win32 Release" + +# ADD CPP /W3 /I "../../include" + +!ELSEIF "$(CFG)" == "MoTo - Win32 Debug" + +!ENDIF + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Group "inlines" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\include\MT_Matrix3x3.inl +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Matrix4x4.inl +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Plane3.inl +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Point2.inl +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Point3.inl +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Quaternion.inl +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Vector2.inl +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Vector3.inl +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Vector4.inl +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\include\GEN_List.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\GEN_Map.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_assert.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_CmMatrix4x4.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Matrix3x3.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Matrix4x4.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_MinMax.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Optimize.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Plane3.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Point2.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Point3.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Quaternion.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_random.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Scalar.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Stream.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Transform.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Tuple2.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Tuple3.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Tuple4.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Vector2.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Vector3.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\MT_Vector4.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\NM_Scalar.h +# End Source File +# End Group +# End Target +# End Project diff --git a/intern/moto/make/msvc_6_0/MoTo.dsw b/intern/moto/make/msvc_6_0/MoTo.dsw new file mode 100755 index 00000000000..349342c2ae2 --- /dev/null +++ b/intern/moto/make/msvc_6_0/MoTo.dsw @@ -0,0 +1,58 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 + +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + + + +############################################################################### + + + +Project: "MoTo"=.\MoTo.dsp - Package Owner=<4> + + + +Package=<5> + +{{{ + +}}} + + + +Package=<4> + +{{{ + +}}} + + + +############################################################################### + + + +Global: + + + +Package=<5> + +{{{ + +}}} + + + +Package=<3> + +{{{ + +}}} + + + +############################################################################### + + + diff --git a/intern/python/Blender.py b/intern/python/Blender.py new file mode 100644 index 00000000000..ef9e527386e --- /dev/null +++ b/intern/python/Blender.py @@ -0,0 +1,349 @@ +#! /usr/bin/env python + +####################### +# (c) Jan Walter 2000 # +####################### + +# CVS +# $Author$ +# $Date$ +# $RCSfile$ +# $Revision$ + +"""This is the Python API for Blender""" + +def _findNewName(name, names): + import string + words = string.split(name, ".") + basename = words[0] + newname = name + num = 1 + while newname in names: + newname = basename + ".%03d" % num + num = num + 1 + return newname + +################### +# Blender classes # +################### + +class Camera: + def __init__(self, name, Lens = 35.0, ClipSta = 0.1, ClipEnd = 100.0): + self.name = name + self.ipos = {} + self.Lens = Lens + self.ClipSta = ClipSta + self.ClipEnd = ClipEnd + +class Curve: + def __init__(self, name): + # ... + self.name = name + self.ipos = {} + self.materials = [] + +class Ika: + def __init__(self, name): + self.name = name + +class Ipo: + def __init__(self, name): + self.name = name + +class Lamp: + def __init__(self, name, Energ = 1.0, R = 1.0, G = 1.0, B = 1.0, + SpoSi = 45.0, + OfsX = 0.0, OfsY = 0.0, OfsZ = 0.0, + SizeX = 1.0, SizeY = 1.0, SizeZ = 1.0): + self.name = name + self.ipos = {} + self.Energ = Energ + self.R = R + self.G = G + self.B = B + self.SpoSi = SpoSi + self.OfsX = OfsX + self.OfsY = OfsY + self.OfsZ = OfsZ + self.SizeX = SizeX + self.SizeY = SizeY + self.SizeZ = SizeZ + +class Material: + def __init__(self, name, + R = 0.8, G = 0.8, B = 0.8, + SpecR = 1.0, SpecG = 1.0, SpecB = 1.0, + MirR = 1.0, MirG = 1.0, MirB = 1.0, + Ref = 0.8, Alpha = 1.0, Emit = 0.0, Amb = 0.5, + Spec = 0.5, Hard = 50): + self.name = name + self.ipos = {} + self.R = R + self.G = G + self.B = B + self.SpecR = SpecR + self.SpecG = SpecG + self.SpecB = SpecB + self.MirR = MirR + self.MirG = MirG + self.MirB = MirB + self.Ref = Ref + self.Alpha = Alpha + self.Emit = Emit + self.Amb = Amb + self.Spec = Spec + self.Hard = Hard + +class Matrix: + def __init__(self): + self.elements = [[1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1]] + + def __repr__(self): + str = "%s" % self.elements + return str + +class Mesh: + """Creates an (empty) instance of a Blender mesh.\n\ + E.g.: "m = Blender.Mesh('Plane')"\n\ + To create faces first add vertices with \n\ + "i1 = m.addVertex(x, y, z, nx, ny, nz, r = -1.0, r = 0.0, b = 0.0)"\n\ + then create faces with "index = m.addFace(i1, i2, i3, i4, isSmooth)".""" + + _meshes = {} + + def __init__(self, name): + self.name = name + self.ipos = {} + self.materials = [] + self.vertices = [] + self.normals = [] + self.colors = [] + self.faces = [] + if name in Mesh._meshes.keys(): + print 'Mesh "%s" already exists ...' % name + self.name = _findNewName(name, Mesh._meshes.keys()) + print '... so it will be called "%s"' % self.name + Mesh._meshes[self.name] = self + + def __repr__(self): + str = 'Mesh(name = "%s",\n' % self.name + str = str + ' vertices = %s,\n' % len(self.vertices) + str = str + ' faces = %s)' % len(self.faces) + return str + + def addFace(self, i1, i2, i3, i4, isSmooth): + """addFace(self, i1, i2, i3, i4)""" + self.faces.append([i1, i2, i3, i4, isSmooth]) + return (len(self.faces) - 1) + + def addVertex(self, x, y, z, nx, ny, nz, r = -1.0, g = 0.0, b = 0.0): + """addVertex(self, x, y, z, nx, ny, nz, r = -1.0, g = 0.0, b = 0.0)""" + self.vertices.append([x, y, z]) + self.normals.append([nx, ny, nz]) + if r != -1.0: + self.colors.append([r, g, b]) + return (len(self.vertices) - 1) + +class MetaBall: + def __init__(self, name): + self.name = name + +class Object: + """Creates an instance of a Blender object""" + + _objects = {} + + def __init__(self, name): + self.name = name + self.ipos = {} + self.materials = [] + self.matrix = Matrix() + self.data = None + self.type = None + if name in Object._objects.keys(): + print 'Object "%s" already exists ...' % name + self.name = _findNewName(name, Object._objects.keys()) + print '... so it will be called "%s"' % self.name + Object._objects[self.name] = self + + def __repr__(self): + str = 'Object(name = "%s",\n' % self.name + str = str + ' matrix = %s,\n' % self.matrix + if self.type: + str = str + ' data = %s("%s"))' % (self.type, self.data) + else: + str = str + ' data = None)' + return str + +class Scene: + """Creates an instance of a Blender scene""" + + _scenes = {} + + def __init__(self, name): + self.name = name + self.objects = [] +## self.camera = None +## self.world = None + Scene._scenes[self.name] = self + + def __repr__(self): + str = 'Scene(name = "%s", \n' % self.name + str = str + ' objects = %s)' % len(self.objects) + return str + + def addObject(self, object): + """addObject(self, object)""" + self.objects.append(object.name) + return (len(self.objects) - 1) + +class Surface: + def __init__(self, name): + self.name = name + self.ipos = {} + self.materials = [] + # ... + +class Text(Surface): + def __init__(self, name): + Surface.__init__(name) + +############## +# primitives # +############## + +def addMesh(type, sceneName): + """Blender.addMesh(type, sceneName)\n\ + where type is one of ["Plane"]""" + + if type == "Plane": + object = Object(type) + mesh = Mesh(type) + i1 = mesh.addVertex(+1.0, +1.0, 0.0, 0.0, 0.0, 1.0) + i2 = mesh.addVertex(+1.0, -1.0, 0.0, 0.0, 0.0, 1.0) + i3 = mesh.addVertex(-1.0, -1.0, 0.0, 0.0, 0.0, 1.0) + i4 = mesh.addVertex(-1.0, +1.0, 0.0, 0.0, 0.0, 1.0) + mesh.addFace(i1, i4, i3, i2, 0) + connect("OB" + object.name, "ME" + mesh.name) + connect("SC" + sceneName, "OB" + object.name) + return object.name, mesh.name + elif type == "Cube": + pass + elif type == "Circle": + pass + elif type == "UVsphere": + pass + elif type == "Icosphere": + pass + elif type == "Cylinder": + pass + elif type == "Tube": + pass + elif type == "Cone": + pass + elif type == "Grid": + pass + else: + raise TypeError + +def addCurve(type): + if type == "Bezier Curve": + pass + elif type == "Bezier Circle": + pass + elif type == "Nurbs Curve": + pass + elif type == "Nurbs Circle": + pass + elif type == "Path": + pass + else: + raise TypeError + +def addSurface(type): + if type == "Curve": + pass + elif type == "Circle": + pass + elif type == "Surface": + pass + elif type == "Tube": + pass + elif type == "Sphere": + pass + elif type == "Donut": + pass + else: + raise TypeError + +def connect(objName1, objName2): + """connect(objName1, objName2)""" + + if objName1[:2] == "OB" and objName2[:2] == "ME": + obj1 = getObject(objName1[2:]) + obj1.data = objName2[2:] + obj1.type = "Mesh" + elif objName1[:2] == "SC" and objName2[:2] == "OB": + obj1 = getScene(objName1[2:]) + obj2 = getObject(objName2[2:]) + obj1.addObject(obj2) + else: + print "ERROR: connect(%s, %s)" % (objName1, objName2) + +def getCurrentScene(): + """getCurrentScene()""" + + return Scene._scenes[0] + +def getMesh(name): + """getMesh(name)""" + + if name in Mesh._meshes.keys(): + return Mesh._meshes[name] + else: + return None + +def getObject(name): + """getObject(name)""" + + if name in Object._objects.keys(): + return Object._objects[name] + else: + return None + +def getScene(name): + """getScene(name)""" + + if name in Scene._scenes.keys(): + return Scene._scenes[name] + else: + return None + +def testBlender(): + scene = Scene("1") + print scene + objName, meshName = addMesh("Plane", "1") + print scene + obj = Object("Plane") + connect("OB" + obj.name, "ME" + meshName) + connect("SC" + scene.name, "OB" + obj.name) + print scene + for name in scene.objects: + obj = getObject(name) + print obj + if obj.type == "Mesh": + mesh = getMesh(obj.data) + print mesh + print mesh.vertices + print mesh.faces + Mesh("Plane") + # print global data + print Scene._scenes + print Object._objects + print Mesh._meshes + +if __name__ == "__main__": + testBlender() diff --git a/intern/python/README b/intern/python/README new file mode 100644 index 00000000000..c46e3b10af7 --- /dev/null +++ b/intern/python/README @@ -0,0 +1,7 @@ +setenv CFLAGS "-g -Wall -I/usr/local/Python-1.6/Include" +setenv LDFLAGS "-L/usr/local/Python-1.6" +aclocal +autoconf +automake -a +./configure +make diff --git a/intern/python/blendermodule/main.c b/intern/python/blendermodule/main.c new file mode 100644 index 00000000000..1811b80cfa3 --- /dev/null +++ b/intern/python/blendermodule/main.c @@ -0,0 +1,873 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/*************************************************************************** + + main.c - description + ------------------- + begin : Fri Sep 15 19:19:43 CEST 2000 + copyright : (C) 2000 by Jan Walter + email : jan@blender.nl + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +/* CVS */ +/* $Author$ */ +/* $Date$ */ +/* $RCSfile$ */ +/* $Revision$ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> + +#include "Python.h" + +static PyObject* ErrorObject; +static PyObject* _scene; + +static PyObject* blend_connect(PyObject* self, PyObject* args); + +/**************/ +/* structures */ +/**************/ + +typedef struct { + PyObject_HEAD + char name[24]; + PyObject* vertices; + PyObject* normals; + PyObject* faces; +} mshobject; + +staticforward PyTypeObject Mshtype; + +typedef struct { + PyObject_HEAD + char name[24]; + PyObject* matrix; + PyObject* data; + PyObject* type; +} objobject; + +staticforward PyTypeObject Objtype; + +typedef struct { + PyObject_HEAD + char name[24]; + PyObject* objects; +} sceobject; + +staticforward PyTypeObject Scetype; + +/********/ +/* mesh */ +/********/ + +static char msh_addFace__doc__[] = +"addFace(self, i1, i2, i3, i4, isSmooth)" +; + +static PyObject* +msh_addFace(mshobject* self, PyObject* args) +{ + int index; + int i1, i2, i3, i4; + int isSmooth; + PyObject *item = NULL; + + if (!PyArg_ParseTuple(args, "iiiii", &i1, &i2, &i3, &i4, &isSmooth)) + { + return NULL; + } + item = PyList_New(5); + PyList_SetItem(item, 0, PyInt_FromLong(i1)); + PyList_SetItem(item, 1, PyInt_FromLong(i2)); + PyList_SetItem(item, 2, PyInt_FromLong(i3)); + PyList_SetItem(item, 3, PyInt_FromLong(i4)); + PyList_SetItem(item, 4, PyInt_FromLong(isSmooth)); + PyList_Append(self->faces, item); + index = PyList_Size(self->faces) - 1; + + return PyInt_FromLong(index); +} + +static char msh_addVertex__doc__[] = +"addVertex(self, x, y, z, nx, ny, nz)" +; + +static PyObject* +msh_addVertex(mshobject* self, PyObject* args) +{ + int index; + float x, y, z, nx, ny, nz; + PyObject *item1 = NULL; + PyObject *item2 = NULL; + + if (!PyArg_ParseTuple(args, "ffffff", &x, &y, &z, &nx, &ny, &nz)) + { + return NULL; + } + item1 = PyList_New(3); + item2 = PyList_New(3); + PyList_SetItem(item1, 0, PyFloat_FromDouble(x)); + PyList_SetItem(item1, 1, PyFloat_FromDouble(y)); + PyList_SetItem(item1, 2, PyFloat_FromDouble(z)); + PyList_SetItem(item2, 0, PyFloat_FromDouble(nx)); + PyList_SetItem(item2, 1, PyFloat_FromDouble(ny)); + PyList_SetItem(item2, 2, PyFloat_FromDouble(nz)); + PyList_Append(self->vertices, item1); + PyList_Append(self->normals, item2); + index = PyList_Size(self->vertices) - 1; + + return PyInt_FromLong(index); +} + +static struct PyMethodDef msh_methods[] = { + {"addFace", (PyCFunction)msh_addFace, + METH_VARARGS, msh_addFace__doc__}, + {"addVertex", (PyCFunction)msh_addVertex, + METH_VARARGS, msh_addVertex__doc__}, + + { NULL, NULL } +}; + +static mshobject* +newmshobject(char* name) +{ + mshobject* self; + + self = PyObject_NEW(mshobject, &Mshtype); + if (self == NULL) + { + return NULL; + } + strcpy(self->name, name); + self->vertices = PyList_New(0); + self->normals = PyList_New(0); + self->faces = PyList_New(0); + + return self; +} + +static void +msh_dealloc(mshobject* self) +{ + mshobject* msh = (mshobject*) self; + + Py_DECREF(msh->vertices); + Py_DECREF(msh->normals); + Py_DECREF(msh->faces); + + PyMem_DEL(self); +} + +static int +msh_print(mshobject* self, FILE* fp, int flags) +{ + fprintf(fp, "Mesh(name = \"%s\",\n", self->name); + fprintf(fp, " vertices = %d,\n", PyList_Size(self->vertices)); + fprintf(fp, " faces = %d)\n", PyList_Size(self->faces)); + + return 0; +} + +static PyObject* +msh_repr(mshobject* self) +{ + PyObject* s; + + s = PyString_FromString("Mesh()\n"); + + return s; +} + +static PyObject* +msh_str(mshobject* self) +{ + PyObject* s; + + s = PyString_FromString("Mesh()\n"); + + return s; +} + +#include "structmember.h" + +static struct memberlist msh_memberlist[] = { + /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */ + {"vertices", T_OBJECT, offsetof(mshobject, vertices), RO}, + {"normals", T_OBJECT, offsetof(mshobject, normals), RO}, + {"faces", T_OBJECT, offsetof(mshobject, faces), RO}, + {NULL} +}; + +static PyObject* +msh_getattr(mshobject* self, char* name) +{ + PyObject* rv; + + /* XXXX Add your own getattr code here */ + rv = PyMember_Get((char*) self, msh_memberlist, name); + if (rv) + { + return rv; + } + PyErr_Clear(); + + return Py_FindMethod(msh_methods, (PyObject*)self, name); +} + + +static int +msh_setattr(mshobject* self, char* name, PyObject* v) +{ + /* XXXX Add your own setattr code here */ + if ( v == NULL ) + { + PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute"); + return -1; + } + + return PyMember_Set((char*)/*XXXX*/0, msh_memberlist, name, v); +} + +static char Mshtype__doc__[] = +"" +; + +static PyTypeObject Mshtype = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /*ob_size*/ + "Mesh", /*tp_name*/ + sizeof(mshobject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) msh_dealloc, /*tp_dealloc*/ + (printfunc) msh_print, /*tp_print*/ + (getattrfunc) msh_getattr, /*tp_getattr*/ + (setattrfunc) msh_setattr, /*tp_setattr*/ + (cmpfunc) 0, /*tp_compare*/ + (reprfunc) msh_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + (hashfunc) 0, /*tp_hash*/ + (ternaryfunc) 0, /*tp_call*/ + (reprfunc) msh_str, /*tp_str*/ + + /* Space for future expansion */ + 0L,0L,0L,0L, + Mshtype__doc__ /* Documentation string */ +}; + +/**********/ +/* object */ +/**********/ + +static struct PyMethodDef obj_methods[] = { + + { NULL, NULL } +}; + +static objobject* +newobjobject(char* name) +{ + objobject* self = NULL; + PyObject* row1 = NULL; + PyObject* row2 = NULL; + PyObject* row3 = NULL; + PyObject* row4 = NULL; + + self = PyObject_NEW(objobject, &Objtype); + if (self == NULL) + { + return NULL; + } + strcpy(self->name, name); + self->matrix = PyList_New(4); + row1 = PyList_New(4); + row2 = PyList_New(4); + row3 = PyList_New(4); + row4 = PyList_New(4); + PyList_SetItem(row1, 0, PyInt_FromLong(1)); + PyList_SetItem(row1, 1, PyInt_FromLong(0)); + PyList_SetItem(row1, 2, PyInt_FromLong(0)); + PyList_SetItem(row1, 3, PyInt_FromLong(0)); + PyList_SetItem(row2, 0, PyInt_FromLong(0)); + PyList_SetItem(row2, 1, PyInt_FromLong(1)); + PyList_SetItem(row2, 2, PyInt_FromLong(0)); + PyList_SetItem(row2, 3, PyInt_FromLong(0)); + PyList_SetItem(row3, 0, PyInt_FromLong(0)); + PyList_SetItem(row3, 1, PyInt_FromLong(0)); + PyList_SetItem(row3, 2, PyInt_FromLong(1)); + PyList_SetItem(row3, 3, PyInt_FromLong(0)); + PyList_SetItem(row4, 0, PyInt_FromLong(0)); + PyList_SetItem(row4, 1, PyInt_FromLong(0)); + PyList_SetItem(row4, 2, PyInt_FromLong(0)); + PyList_SetItem(row4, 3, PyInt_FromLong(1)); + PyList_SetItem(self->matrix, 0, row1); + PyList_SetItem(self->matrix, 1, row2); + PyList_SetItem(self->matrix, 2, row3); + PyList_SetItem(self->matrix, 3, row4); + Py_INCREF(Py_None); + self->data = Py_None; + Py_INCREF(Py_None); + self->type = Py_None; + + return self; +} + +static void +obj_dealloc(objobject* self) +{ + objobject* obj = (objobject*) self; + + Py_DECREF(obj->matrix); + Py_DECREF(obj->data); + Py_DECREF(obj->type); + + PyMem_DEL(self); +} + +static int +obj_print(objobject* self, FILE* fp, int flags) +{ + fprintf(fp, "Object(name = \"%s\",\n", self->name); +/* fprintf(fp, " matrix = %s,\n", */ +/* PyString_AsString(mtx_repr((mtxobject*) self->matrix))); */ + if (self->type == Py_None) + { + fprintf(fp, " data = None)\n"); + } + else + { + fprintf(fp, " data = %s(\"%s\"))\n", + PyString_AsString(self->type), + ((mshobject*) self->data)->name); + } + + return 0; +} + +static PyObject* +obj_repr(objobject* self) +{ + PyObject* s; + + s = PyString_FromString("Object()\n"); + + return s; +} + +static PyObject* +obj_str(objobject* self) +{ + PyObject* s; + + s = PyString_FromString("Object()\n"); + + return s; +} + +#include "structmember.h" + +static struct memberlist obj_memberlist[] = { + /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */ + {"data", T_OBJECT, offsetof(objobject, data), RO}, + {"matrix", T_OBJECT, offsetof(objobject, matrix), RO}, + {"type", T_OBJECT, offsetof(objobject, type), RO}, + {NULL} +}; + +static PyObject* +obj_getattr(objobject* self, char* name) +{ + PyObject* rv; + + /* XXXX Add your own getattr code here */ + rv = PyMember_Get((char*) self, obj_memberlist, name); + if (rv) + { + return rv; + } + PyErr_Clear(); + + return Py_FindMethod(obj_methods, (PyObject*)self, name); +} + + +static int +obj_setattr(objobject* self, char* name, PyObject* v) +{ + /* XXXX Add your own setattr code here */ + if ( v == NULL ) + { + PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute"); + return -1; + } + + return PyMember_Set((char*)/*XXXX*/0, obj_memberlist, name, v); +} + +static char Objtype__doc__[] = +"" +; + +static PyTypeObject Objtype = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /*ob_size*/ + "Object", /*tp_name*/ + sizeof(objobject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) obj_dealloc, /*tp_dealloc*/ + (printfunc) obj_print, /*tp_print*/ + (getattrfunc) obj_getattr, /*tp_getattr*/ + (setattrfunc) obj_setattr, /*tp_setattr*/ + (cmpfunc) 0, /*tp_compare*/ + (reprfunc) obj_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + (hashfunc) 0, /*tp_hash*/ + (ternaryfunc) 0, /*tp_call*/ + (reprfunc) obj_str, /*tp_str*/ + + /* Space for future expansion */ + 0L,0L,0L,0L, + Objtype__doc__ /* Documentation string */ +}; + +/*********/ +/* scene */ +/*********/ + +static char sce_addObject__doc__[] = +"addObject(self, object)" +; + +static PyObject* +sce_addObject(sceobject* self, PyObject* args) +{ + int index; + PyObject* object = NULL; + + if (!PyArg_ParseTuple(args, "O", &object)) + { + return NULL; + } + PyList_Append(self->objects, object); + index = PyList_Size(self->objects) - 1; + + return PyInt_FromLong(index); +} + +static struct PyMethodDef sce_methods[] = { + {"addObject", (PyCFunction)sce_addObject, + METH_VARARGS, sce_addObject__doc__}, + + { NULL, NULL } +}; + +static sceobject* +newsceobject(char* name) +{ + sceobject* self; + + self = PyObject_NEW(sceobject, &Scetype); + if (self == NULL) + { + return NULL; + } + strcpy(self->name, name); + self->objects = PyList_New(0); + + return self; +} + +static void +sce_dealloc(sceobject* self) +{ + sceobject* sce = (sceobject*) self; + + Py_DECREF(sce->objects); + + PyMem_DEL(self); +} + +static int +sce_print(sceobject* self, FILE* fp, int flags) +{ + fprintf(fp, "Scene(name = \"%s\",\n", self->name); + fprintf(fp, " objects = %d)\n", PyList_Size(self->objects)); + + return 0; +} + +static PyObject* +sce_repr(sceobject* self) +{ + PyObject* s; + + s = PyString_FromString("Scene()\n"); + + return s; +} + +static PyObject* +sce_str(sceobject* self) +{ + PyObject* s; + + s = PyString_FromString("Scene()\n"); + + return s; +} + +#include "structmember.h" + +static struct memberlist sce_memberlist[] = { + /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */ + {"objects", T_OBJECT, offsetof(sceobject, objects), RO}, + {NULL} +}; + +static PyObject* +sce_getattr(sceobject* self, char* name) +{ + PyObject* rv; + + /* XXXX Add your own getattr code here */ + rv = PyMember_Get((char*) self, sce_memberlist, name); + if (rv) + { + return rv; + } + PyErr_Clear(); + + return Py_FindMethod(sce_methods, (PyObject*)self, name); +} + + +static int +sce_setattr(sceobject* self, char* name, PyObject* v) +{ + /* XXXX Add your own setattr code here */ + if ( v == NULL ) + { + PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute"); + return -1; + } + + return PyMember_Set((char*)/*XXXX*/0, sce_memberlist, name, v); +} + +static char Scetype__doc__[] = +"" +; + +static PyTypeObject Scetype = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /*ob_size*/ + "Scene", /*tp_name*/ + sizeof(sceobject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) sce_dealloc, /*tp_dealloc*/ + (printfunc) sce_print, /*tp_print*/ + (getattrfunc) sce_getattr, /*tp_getattr*/ + (setattrfunc) sce_setattr, /*tp_setattr*/ + (cmpfunc) 0, /*tp_compare*/ + (reprfunc) sce_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + (hashfunc) 0, /*tp_hash*/ + (ternaryfunc) 0, /*tp_call*/ + (reprfunc) sce_str, /*tp_str*/ + + /* Space for future expansion */ + 0L,0L,0L,0L, + Scetype__doc__ /* Documentation string */ +}; + +static char blend_Mesh__doc__[] = +"Creates an (empty) instance of a Blender mesh.\n\ + E.g.: \"m = Blender.Mesh('Plane')\"\n\ + To create faces first add vertices with \n\ + \"i1 = m.addVertex(x, y, z, nx, ny, nz)\"\n\ + then create faces with \"index = m.addFace(i1, i2, i3, i4, isSmooth)\".\ +" +; + +static PyObject* +blend_Mesh(PyObject* self, PyObject* args) +{ + if (!PyArg_ParseTuple(args, "")) + { + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static char blend_Object__doc__[] = +"Creates an instance of a Blender object" +; + +static PyObject* +blend_Object(PyObject* self, PyObject* args) +{ + char* name = NULL; + + if (!PyArg_ParseTuple(args, "s", &name)) + { + return NULL; + } + + return ((PyObject*) newobjobject(name)); +} + +static char blend_Scene__doc__[] = +"Creates an instance of a Blender scene" +; + +static PyObject* +blend_Scene(PyObject* self, PyObject* args) +{ + char* name = NULL; + + if (!PyArg_ParseTuple(args, "s", &name)) + { + return NULL; + } + + return ((PyObject*) newsceobject(name)); +} + +static char blend_addMesh__doc__[] = +"Blender.addMesh(type, scene)\n\ + where type is one of [\"Plane\"]" +; + +static PyObject* +blend_addMesh(PyObject* self, PyObject* args) +{ + char* type = NULL; + PyObject* scene = NULL; + PyObject* tuple = NULL; + PyObject* object = NULL; + PyObject* mesh = NULL; + PyObject* index = NULL; + PyObject* indices = NULL; + + if (!PyArg_ParseTuple(args, "sO", &type, &scene)) + { + return NULL; + } + + if (strcmp(type, "Plane") == 0) + { + object = (PyObject*) newobjobject(type); + mesh = (PyObject*) newmshobject(type); + indices = PyList_New(5); + /* vertices */ + index = msh_addVertex((mshobject*) mesh, + Py_BuildValue("ffffff", + 1.0, 1.0, 0.0, 0.0, 0.0, 1.0)); + PyList_SetItem(indices, 0, index); + index = msh_addVertex((mshobject*) mesh, + Py_BuildValue("ffffff", + 1.0, -1.0, 0.0, 0.0, 0.0, 1.0)); + PyList_SetItem(indices, 1, index); + index = msh_addVertex((mshobject*) mesh, + Py_BuildValue("ffffff", + -1.0, -1.0, 0.0, 0.0, 0.0, 1.0)); + PyList_SetItem(indices, 2, index); + index = msh_addVertex((mshobject*) mesh, + Py_BuildValue("ffffff", + -1.0, 1.0, 0.0, 0.0, 0.0, 1.0)); + PyList_SetItem(indices, 3, index); + PyList_SetItem(indices, 4, PyInt_FromLong(0)); /* smooth flag */ + /* faces */ + msh_addFace((mshobject*) mesh, + Py_BuildValue("OOOOO", + PyList_GetItem(indices, 0), + PyList_GetItem(indices, 3), + PyList_GetItem(indices, 2), + PyList_GetItem(indices, 1), + PyList_GetItem(indices, 4))); + /* connection */ + blend_connect(self, Py_BuildValue("OO", object, mesh)); + blend_connect(self, Py_BuildValue("OO", scene, object)); + /* return value */ + tuple = PyTuple_New(2); + PyTuple_SetItem(tuple, 0, object); + PyTuple_SetItem(tuple, 1, mesh); + + return tuple; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static char blend_connect__doc__[] = +"connect(obj1, obj2)" +; + +static PyObject* +blend_connect(PyObject* self, PyObject* args) +{ + PyObject* obj1 = NULL; + PyObject* obj2 = NULL; + + if (!PyArg_ParseTuple(args, "OO", &obj1, &obj2)) + { + return NULL; + } + if (obj1->ob_type == &Objtype) + { + if (obj2->ob_type == &Mshtype) + { + Py_INCREF(obj2); + ((objobject*) obj1)->data = obj2; + ((objobject*) obj1)->type = PyString_FromString("Mesh"); + } + } + else if (obj1->ob_type == &Scetype) + { + if (obj2->ob_type == &Objtype) + { + sce_addObject((sceobject*) obj1, Py_BuildValue("(O)", obj2)); + } + } + + Py_INCREF(Py_None); + return Py_None; +} + +static char blend_getCurrentScene__doc__[] = +"getCurrentScene()" +; + +static PyObject* +blend_getCurrentScene(PyObject* self, PyObject* args) +{ + if (!PyArg_ParseTuple(args, "")) + { + return NULL; + } + + Py_INCREF(_scene); + return _scene; +} + +/* List of methods defined in the module */ + +static struct PyMethodDef blend_methods[] = { + {"Mesh", (PyCFunction) blend_Mesh, + METH_VARARGS, blend_Mesh__doc__}, + {"Object", (PyCFunction) blend_Object, + METH_VARARGS, blend_Object__doc__}, + {"Scene", (PyCFunction) blend_Scene, + METH_VARARGS, blend_Scene__doc__}, + {"addMesh", (PyCFunction) blend_addMesh, + METH_VARARGS, blend_addMesh__doc__}, + {"connect", (PyCFunction) blend_connect, + METH_VARARGS, blend_connect__doc__}, + {"getCurrentScene", (PyCFunction) blend_getCurrentScene, + METH_VARARGS, blend_getCurrentScene__doc__}, + { NULL, (PyCFunction) NULL, 0, NULL } +}; + + +/* Initialization function for the module (*must* be called initBlender) */ + +static char Blender_module_documentation[] = +"This is the Python API for Blender" +; + +void +initBlender() +{ + PyObject* m; + PyObject* d; + + /* Create the module and add the functions */ + m = Py_InitModule4("Blender", blend_methods, + Blender_module_documentation, + (PyObject*)NULL,PYTHON_API_VERSION); + + /* Add some symbolic constants to the module */ + d = PyModule_GetDict(m); + ErrorObject = PyString_FromString("Blender.error"); + PyDict_SetItemString(d, "error", ErrorObject); + + /* XXXX Add constants here */ + _scene = (PyObject*) newsceobject("1"); + PyDict_SetItemString(d, "_scene", _scene); + + /* Check for errors */ + if (PyErr_Occurred()) + { + Py_FatalError("can't initialize module Blender"); + } +} + +int main(int argc, char* argv[]) +{ + char filename[] = "test.py"; + FILE* fp = NULL; + + Py_SetProgramName("blender"); + Py_Initialize(); + initBlender(); + fp = fopen(filename, "r"); + PyRun_AnyFile(fp, filename); + + Py_Finalize(); + + return EXIT_SUCCESS; +} diff --git a/intern/python/blendermodule/test.py b/intern/python/blendermodule/test.py new file mode 100644 index 00000000000..8c2307a2317 --- /dev/null +++ b/intern/python/blendermodule/test.py @@ -0,0 +1,52 @@ +import Blender + +def printModuleInfo(): + # module information + names = dir(Blender) + print names + for name in names: + execString = ('print "Blender.' + name + ':",\n' + + 'if type(Blender.' + name + ') == type(""):\n' + + ' print Blender.' + name + '\n' + + 'elif type(Blender.' + name + + ') == type(Blender.addMesh) or type(Blender.' + name + + ') == type(Blender.Object):\n' + + ' print Blender.' + name + '.__doc__\n' + + 'else:\n' + + ' print type(Blender.' + name + ')\n') + exec execString + print "#" * 79 + +def testModule(): + # get current scene + scene = Blender.getCurrentScene() + print scene + # create object and mesh (primitives) + obj, msh = Blender.addMesh("Plane", scene) + print "obj =" + print obj + print "msh =" + print msh + print "vertices:" + for vertex in msh.vertices: + print vertex + print "faces:" + for face in msh.faces: + print face + # create object only and share mesh + obj2 = Blender.Object("Plane2") + print obj2 + Blender.connect(obj2, msh) + Blender.connect(scene, obj2) + print obj2 + print obj2.data + print "vertices:" + for vertex in obj2.data.vertices: + print vertex + print "faces:" + for face in obj2.data.faces: + print face + print scene + +printModuleInfo() +testModule() diff --git a/intern/python/freeze/Makefile b/intern/python/freeze/Makefile new file mode 100644 index 00000000000..3c344029b3e --- /dev/null +++ b/intern/python/freeze/Makefile @@ -0,0 +1,14 @@ +# $Id$ +# This is the makefile for the bytecode freezing of all modules which +# the main file depends on (last argument in importer rule) + +SRCDIR = ../modules + +TARGETDIR = ../../../source/blender/bpython/frozen + +PYFLAGS = -S -O + +default: importer + +importer: + python $(PYFLAGS) freeze.py -d -x os -x pprint -x Blender -I $(SRCDIR) -o $(TARGETDIR) $(SRCDIR)/VRMLmain.py diff --git a/intern/python/freeze/README b/intern/python/freeze/README new file mode 100644 index 00000000000..fcdd67029a5 --- /dev/null +++ b/intern/python/freeze/README @@ -0,0 +1,173 @@ +THE FREEZE SCRIPT +================= + +(Directions for Windows are at the end of this file.) + + +What is Freeze? +--------------- + +Freeze make it possible to ship arbitrary Python programs to people +who don't have Python. The shipped file (called a "frozen" version of +your Python program) is an executable, so this only works if your +platform is compatible with that on the receiving end (this is usually +a matter of having the same major operating system revision and CPU +type). + +The shipped file contains a Python interpreter and large portions of +the Python run-time. Some measures have been taken to avoid linking +unneeded modules, but the resulting binary is usually not small. + +The Python source code of your program (and of the library modules +written in Python that it uses) is not included in the binary -- +instead, the compiled byte-code (the instruction stream used +internally by the interpreter) is incorporated. This gives some +protection of your Python source code, though not much -- a +disassembler for Python byte-code is available in the standard Python +library. At least someone running "strings" on your binary won't see +the source. + + +How does Freeze know which modules to include? +---------------------------------------------- + +Previous versions of Freeze used a pretty simple-minded algorithm to +find the modules that your program uses, essentially searching for +lines starting with the word "import". It was pretty easy to trick it +into making mistakes, either missing valid import statements, or +mistaking string literals (e.g. doc strings) for import statements. + +This has been remedied: Freeze now uses the regular Python parser to +parse the program (and all its modules) and scans the generated byte +code for IMPORT instructions. It may still be confused -- it will not +know about calls to the __import__ built-in function, or about import +statements constructed on the fly and executed using the 'exec' +statement, and it will consider import statements even when they are +unreachable (e.g. "if 0: import foobar"). + +This new version of Freeze also knows about Python's new package +import mechanism, and uses exactly the same rules to find imported +modules and packages. One exception: if you write 'from package +import *', Python will look into the __all__ variable of the package +to determine which modules are to be imported, while Freeze will do a +directory listing. + +One tricky issue: Freeze assumes that the Python interpreter and +environment you're using to run Freeze is the same one that would be +used to run your program, which should also be the same whose sources +and installed files you will learn about in the next section. In +particular, your PYTHONPATH setting should be the same as for running +your program locally. (Tip: if the program doesn't run when you type +"python hello.py" there's little chance of getting the frozen version +to run.) + + +How do I use Freeze? +-------------------- + +Normally, you should be able to use it as follows: + + python freeze.py hello.py + +where hello.py is your program and freeze.py is the main file of +Freeze (in actuality, you'll probably specify an absolute pathname +such as /usr/joe/python/Tools/freeze/freeze.py). + + +What do I do next? +------------------ + +Freeze creates a number of files: frozen.c, config.c and Makefile, +plus one file for each Python module that gets included named +M_<module>.c. To produce the frozen version of your program, you can +simply type "make". This should produce a binary file. If the +filename argument to Freeze was "hello.py", the binary will be called +"hello". + +Note: you can use the -o option to freeze to specify an alternative +directory where these files are created. This makes it easier to +clean up after you've shipped the frozen binary. You should invoke +"make" in the given directory. + + +Freezing Tkinter programs +------------------------- + +Unfortunately, it is currently not possible to freeze programs that +use Tkinter. It *seems* to work, but when you ship the frozen program +to a site without a Tcl/Tk installation, it will fail with a complaint +about missing Tcl/Tk initialization files. + +A workaround would be possible, in which the Tcl/Tk library files are +incorporated in a frozen Python module as string literals and written +to a temporary location when the program runs; this is currently left +as an exercise for the reader. (If you implement this, please post to +the Python newsgroup!) + +Of course, you can also simply require that Tcl/Tk is required on the +target installation. + + +A warning against shared library modules +---------------------------------------- + +When your Python installation uses shared library modules, these will +not be incorporated in the frozen program. Again, the frozen program +will work when you test it, but it won't work when you ship it to a +site without a Python installation. + +Freeze prints a warning when this is the case at the end of the +freezing process: + + Warning: unknown modules remain: ... + +When this occurs, the best thing to do is usually to rebuild Python +using static linking only. + + +Troubleshooting +--------------- + +If you have trouble using Freeze for a large program, it's probably +best to start playing with a really simple program first (like the file +hello.py). If you can't get that to work there's something +fundamentally wrong -- perhaps you haven't installed Python. To do a +proper install, you should do "make install" in the Python root +directory. + + +Usage under Windows 95 or NT +---------------------------- + +Under Windows 95 or NT, you *must* use the -p option and point it to +the top of the Python source tree. + +WARNING: the resulting executable is not self-contained; it requires +the Python DLL, currently PYTHON20.DLL (it does not require the +standard library of .py files though). It may also require one or +more extension modules loaded from .DLL or .PYD files; the module +names are printed in the warning message about remaining unknown +modules. + +The driver script generates a Makefile that works with the Microsoft +command line C compiler (CL). To compile, run "nmake"; this will +build a target "hello.exe" if the source was "hello.py". Only the +files frozenmain.c and frozen.c are used; no config.c is generated or +used, since the standard DLL is used. + +In order for this to work, you must have built Python using the VC++ +(Developer Studio) 5.0 compiler. The provided project builds +python20.lib in the subdirectory pcbuild\Release of thje Python source +tree, and this is where the generated Makefile expects it to be. If +this is not the case, you can edit the Makefile or (probably better) +winmakemakefile.py (e.g., if you are using the 4.2 compiler, the +python20.lib file is generated in the subdirectory vc40 of the Python +source tree). + +You can freeze programs that use Tkinter, but Tcl/Tk must be installed +on the target system. + +It is possible to create frozen programs that don't have a console +window, by specifying the option '-s windows'. + +--Guido van Rossum (home page: http://www.python.org/~guido/) diff --git a/intern/python/freeze/README.NaN b/intern/python/freeze/README.NaN new file mode 100644 index 00000000000..93892543c4f --- /dev/null +++ b/intern/python/freeze/README.NaN @@ -0,0 +1,12 @@ +$Id$ + +This is a modification of the freeze.py script used to freeze python +modules as byte code in Blender. + +To create this byte code, simply type 'make'. Freeze will then generate +the C source files in the TARGETDIR (specified in the Makefile), provided +that you have a valid python installation. + +Be warned: testing of the module dependencies is needed, as these are +resolved AT RUNTIME! + diff --git a/intern/python/freeze/bkfile.py b/intern/python/freeze/bkfile.py new file mode 100644 index 00000000000..d29716a93c9 --- /dev/null +++ b/intern/python/freeze/bkfile.py @@ -0,0 +1,47 @@ +_orig_open = open + +class _BkFile: + def __init__(self, file, mode, bufsize): + import os + self.__filename = file + self.__backup = file + '~' + try: + os.unlink(self.__backup) + except os.error: + pass + try: + os.rename(file, self.__backup) + except os.error: + self.__backup = None + self.__file = _orig_open(file, mode, bufsize) + self.closed = self.__file.closed + self.fileno = self.__file.fileno + self.flush = self.__file.flush + self.isatty = self.__file.isatty + self.mode = self.__file.mode + self.name = self.__file.name + self.read = self.__file.read + self.readinto = self.__file.readinto + self.readline = self.__file.readline + self.readlines = self.__file.readlines + self.seek = self.__file.seek + self.softspace = self.__file.softspace + self.tell = self.__file.tell + self.truncate = self.__file.truncate + self.write = self.__file.write + self.writelines = self.__file.writelines + + def close(self): + self.__file.close() + if self.__backup is None: + return + import filecmp + if filecmp.cmp(self.__backup, self.__filename, shallow = 0): + import os + os.unlink(self.__filename) + os.rename(self.__backup, self.__filename) + +def open(file, mode = 'r', bufsize = -1): + if 'w' not in mode: + return _orig_open(file, mode, bufsize) + return _BkFile(file, mode, bufsize) diff --git a/intern/python/freeze/checkextensions.py b/intern/python/freeze/checkextensions.py new file mode 100644 index 00000000000..8d597bfae96 --- /dev/null +++ b/intern/python/freeze/checkextensions.py @@ -0,0 +1,91 @@ +# Check for a module in a set of extension directories. +# An extension directory should contain a Setup file +# and one or more .o files or a lib.a file. + +import os +import string +import parsesetup + +def checkextensions(unknown, extensions): + files = [] + modules = [] + edict = {} + for e in extensions: + setup = os.path.join(e, 'Setup') + liba = os.path.join(e, 'lib.a') + if not os.path.isfile(liba): + liba = None + edict[e] = parsesetup.getsetupinfo(setup), liba + for mod in unknown: + for e in extensions: + (mods, vars), liba = edict[e] + if not mods.has_key(mod): + continue + modules.append(mod) + if liba: + # If we find a lib.a, use it, ignore the + # .o files, and use *all* libraries for + # *all* modules in the Setup file + if liba in files: + break + files.append(liba) + for m in mods.keys(): + files = files + select(e, mods, vars, + m, 1) + break + files = files + select(e, mods, vars, mod, 0) + break + return files, modules + +def select(e, mods, vars, mod, skipofiles): + files = [] + for w in mods[mod]: + w = treatword(w) + if not w: + continue + w = expandvars(w, vars) + for w in string.split(w): + if skipofiles and w[-2:] == '.o': + continue + # Assume $var expands to absolute pathname + if w[0] not in ('-', '$') and w[-2:] in ('.o', '.a'): + w = os.path.join(e, w) + if w[:2] in ('-L', '-R') and w[2:3] != '$': + w = w[:2] + os.path.join(e, w[2:]) + files.append(w) + return files + +cc_flags = ['-I', '-D', '-U'] +cc_exts = ['.c', '.C', '.cc', '.c++'] + +def treatword(w): + if w[:2] in cc_flags: + return None + if w[:1] == '-': + return w # Assume loader flag + head, tail = os.path.split(w) + base, ext = os.path.splitext(tail) + if ext in cc_exts: + tail = base + '.o' + w = os.path.join(head, tail) + return w + +def expandvars(str, vars): + i = 0 + while i < len(str): + i = k = string.find(str, '$', i) + if i < 0: + break + i = i+1 + var = str[i:i+1] + i = i+1 + if var == '(': + j = string.find(str, ')', i) + if j < 0: + break + var = str[i:j] + i = j+1 + if vars.has_key(var): + str = str[:k] + vars[var] + str[i:] + i = k + return str diff --git a/intern/python/freeze/checkextensions_win32.py b/intern/python/freeze/checkextensions_win32.py new file mode 100644 index 00000000000..85c3a3c0cdd --- /dev/null +++ b/intern/python/freeze/checkextensions_win32.py @@ -0,0 +1,190 @@ +"""Extension management for Windows. + +Under Windows it is unlikely the .obj files are of use, as special compiler options +are needed (primarily to toggle the behavior of "public" symbols. + +I dont consider it worth parsing the MSVC makefiles for compiler options. Even if +we get it just right, a specific freeze application may have specific compiler +options anyway (eg, to enable or disable specific functionality) + +So my basic stragtegy is: + +* Have some Windows INI files which "describe" one or more extension modules. + (Freeze comes with a default one for all known modules - but you can specify + your own). +* This description can include: + - The MSVC .dsp file for the extension. The .c source file names + are extraced from there. + - Specific compiler/linker options + - Flag to indicate if Unicode compilation is expected. + +At the moment the name and location of this INI file is hardcoded, +but an obvious enhancement would be to provide command line options. +""" + +import os, string, sys +try: + import win32api +except ImportError: + win32api = None # User has already been warned + +class CExtension: + """An abstraction of an extension implemented in C/C++ + """ + def __init__(self, name, sourceFiles): + self.name = name + # A list of strings defining additional compiler options. + self.sourceFiles = sourceFiles + # A list of special compiler options to be applied to + # all source modules in this extension. + self.compilerOptions = [] + # A list of .lib files the final .EXE will need. + self.linkerLibs = [] + + def GetSourceFiles(self): + return self.sourceFiles + + def AddCompilerOption(self, option): + self.compilerOptions.append(option) + def GetCompilerOptions(self): + return self.compilerOptions + + def AddLinkerLib(self, lib): + self.linkerLibs.append(lib) + def GetLinkerLibs(self): + return self.linkerLibs + +def checkextensions(unknown, extra_inis, prefix): + # Create a table of frozen extensions + + defaultMapName = os.path.join( os.path.split(sys.argv[0])[0], "extensions_win32.ini") + if not os.path.isfile(defaultMapName): + sys.stderr.write("WARNING: %s can not be found - standard extensions may not be found" % mapFileName) + else: + # must go on end, so other inis can override. + extra_inis.append(defaultMapName) + + ret = [] + for mod in unknown: + for ini in extra_inis: +# print "Looking for", mod, "in", win32api.GetFullPathName(ini),"...", + defn = get_extension_defn( mod, ini, prefix ) + if defn is not None: +# print "Yay - found it!" + ret.append( defn ) + break +# print "Nope!" + else: # For not broken! + sys.stderr.write("No definition of module %s in any specified map file.\n" % (mod)) + + return ret + +def get_extension_defn(moduleName, mapFileName, prefix): + if win32api is None: return None + os.environ['PYTHONPREFIX'] = prefix + dsp = win32api.GetProfileVal(moduleName, "dsp", "", mapFileName) + if dsp=="": + return None + + # We allow environment variables in the file name + dsp = win32api.ExpandEnvironmentStrings(dsp) + # If the path to the .DSP file is not absolute, assume it is relative + # to the description file. + if not os.path.isabs(dsp): + dsp = os.path.join( os.path.split(mapFileName)[0], dsp) + # Parse it to extract the source files. + sourceFiles = parse_dsp(dsp) + if sourceFiles is None: + return None + + module = CExtension(moduleName, sourceFiles) + # Put the path to the DSP into the environment so entries can reference it. + os.environ['dsp_path'] = os.path.split(dsp)[0] + os.environ['ini_path'] = os.path.split(mapFileName)[0] + + cl_options = win32api.GetProfileVal(moduleName, "cl", "", mapFileName) + if cl_options: + module.AddCompilerOption(win32api.ExpandEnvironmentStrings(cl_options)) + + exclude = win32api.GetProfileVal(moduleName, "exclude", "", mapFileName) + exclude = string.split(exclude) + + if win32api.GetProfileVal(moduleName, "Unicode", 0, mapFileName): + module.AddCompilerOption('/D UNICODE /D _UNICODE') + + libs = string.split(win32api.GetProfileVal(moduleName, "libs", "", mapFileName)) + for lib in libs: + module.AddLinkerLib(win32api.ExpandEnvironmentStrings(lib)) + + for exc in exclude: + if exc in module.sourceFiles: + modules.sourceFiles.remove(exc) + + return module + +# Given an MSVC DSP file, locate C source files it uses +# returns a list of source files. +def parse_dsp(dsp): +# print "Processing", dsp + # For now, only support + ret = [] + dsp_path, dsp_name = os.path.split(dsp) + try: + lines = open(dsp, "r").readlines() + except IOError, msg: + sys.stderr.write("%s: %s\n" % (dsp, msg)) + return None + for line in lines: + fields = string.split(string.strip(line), "=", 2) + if fields[0]=="SOURCE": + if string.lower(os.path.splitext(fields[1])[1]) in ['.cpp', '.c']: + ret.append( win32api.GetFullPathName(os.path.join(dsp_path, fields[1] ) ) ) + return ret + +def write_extension_table(fname, modules): + fp = open(fname, "w") + try: + fp.write (ext_src_header) + # Write fn protos + for module in modules: + # bit of a hack for .pyd's as part of packages. + name = string.split(module.name,'.')[-1] + fp.write('extern void init%s(void);\n' % (name) ) + # Write the table + fp.write (ext_tab_header) + for module in modules: + name = string.split(module.name,'.')[-1] + fp.write('\t{"%s", init%s},\n' % (name, name) ) + + fp.write (ext_tab_footer) + fp.write(ext_src_footer) + finally: + fp.close() + + +ext_src_header = """\ +#include "Python.h" +""" + +ext_tab_header = """\ + +static struct _inittab extensions[] = { +""" + +ext_tab_footer = """\ + /* Sentinel */ + {0, 0} +}; +""" + +ext_src_footer = """\ +extern DL_IMPORT(int) PyImport_ExtendInittab(struct _inittab *newtab); + +int PyInitFrozenExtensions() +{ + return PyImport_ExtendInittab(extensions); +} + +""" + + diff --git a/intern/python/freeze/freeze.py b/intern/python/freeze/freeze.py new file mode 100755 index 00000000000..e6f4ead15d5 --- /dev/null +++ b/intern/python/freeze/freeze.py @@ -0,0 +1,461 @@ +#! /usr/bin/env python + +# changes made by strubi@blender.nl + +"""Freeze a Python script into a binary. + +usage: freeze [options...] script [module]... + +Options: +-p prefix: This is the prefix used when you ran ``make install'' + in the Python build directory. + (If you never ran this, freeze won't work.) + The default is whatever sys.prefix evaluates to. + It can also be the top directory of the Python source + tree; then -P must point to the build tree. + +-P exec_prefix: Like -p but this is the 'exec_prefix', used to + install objects etc. The default is whatever sys.exec_prefix + evaluates to, or the -p argument if given. + If -p points to the Python source tree, -P must point + to the build tree, if different. + +-e extension: A directory containing additional .o files that + may be used to resolve modules. This directory + should also have a Setup file describing the .o files. + On Windows, the name of a .INI file describing one + or more extensions is passed. + More than one -e option may be given. + +-o dir: Directory where the output files are created; default '.'. + +-m: Additional arguments are module names instead of filenames. + +-a package=dir: Additional directories to be added to the package's + __path__. Used to simulate directories added by the + package at runtime (eg, by OpenGL and win32com). + More than one -a option may be given for each package. + +-l file: Pass the file to the linker (windows only) + +-d: Debugging mode for the module finder. + +-q: Make the module finder totally quiet. + +-h: Print this help message. + +-x module Exclude the specified module. + +-i filename: Include a file with additional command line options. Used + to prevent command lines growing beyond the capabilities of + the shell/OS. All arguments specified in filename + are read and the -i option replaced with the parsed + params (note - quoting args in this file is NOT supported) + +-s subsystem: Specify the subsystem (For Windows only.); + 'console' (default), 'windows', 'service' or 'com_dll' + +-w: Toggle Windows (NT or 95) behavior. + (For debugging only -- on a win32 platform, win32 behavior + is automatic.) + +Arguments: + +script: The Python script to be executed by the resulting binary. + +module ...: Additional Python modules (referenced by pathname) + that will be included in the resulting binary. These + may be .py or .pyc files. If -m is specified, these are + module names that are search in the path instead. + +NOTES: + +In order to use freeze successfully, you must have built Python and +installed it ("make install"). + +The script should not use modules provided only as shared libraries; +if it does, the resulting binary is not self-contained. +""" + + +# Import standard modules + +import getopt +import os +import string +import sys + + +# Import the freeze-private modules + +import checkextensions +import modulefinder +import makeconfig +import makefreeze +import makemakefile +import parsesetup +import bkfile + + +# Main program + +def main(): + # overridable context + prefix = None # settable with -p option + exec_prefix = None # settable with -P option + extensions = [] + exclude = [] # settable with -x option + addn_link = [] # settable with -l, but only honored under Windows. + path = sys.path[:] + modargs = 0 + debug = 1 + odir = '' + win = sys.platform[:3] == 'win' + + # default the exclude list for each platform + if win: exclude = exclude + [ + 'dos', 'dospath', 'mac', 'macpath', 'macfs', 'MACFS', 'posix', 'os2', 'ce'] + + # modules that are imported by the Python runtime + #implicits = ["site", "exceptions"] + implicits = ["exceptions"] + + # output files + frozen_c = 'frozen.c' + config_c = 'config.c' + target = 'a.out' # normally derived from script name + makefile = 'Makefile.freeze' + subsystem = 'console' + + # parse command line by first replacing any "-i" options with the file contents. + pos = 1 + while pos < len(sys.argv)-1: # last option can not be "-i", so this ensures "pos+1" is in range! + if sys.argv[pos] == '-i': + try: + options = string.split(open(sys.argv[pos+1]).read()) + except IOError, why: + usage("File name '%s' specified with the -i option can not be read - %s" % (sys.argv[pos+1], why) ) + # Replace the '-i' and the filename with the read params. + sys.argv[pos:pos+2] = options + pos = pos + len(options) - 1 # Skip the name and the included args. + pos = pos + 1 + + # Now parse the command line with the extras inserted. + try: + opts, args = getopt.getopt(sys.argv[1:], 'a:de:hmo:p:P:I:qs:wx:l:') + except getopt.error, msg: + usage('getopt error: ' + str(msg)) + + # proces option arguments + for o, a in opts: + if o == '-h': + print __doc__ + return + if o == '-d': + debug = debug + 1 + if o == '-e': + extensions.append(a) + if o == '-I': # include path + path.append(a) + if o == '-m': + modargs = 1 + if o == '-o': + odir = a + if o == '-p': + prefix = a + if o == '-P': + exec_prefix = a + if o == '-q': + debug = 0 + if o == '-w': + win = not win + if o == '-s': + if not win: + usage("-s subsystem option only on Windows") + subsystem = a + if o == '-x': + exclude.append(a) + if o == '-l': + addn_link.append(a) + if o == '-a': + apply(modulefinder.AddPackagePath, tuple(string.split(a,"=", 2))) + + # default prefix and exec_prefix + if not exec_prefix: + if prefix: + exec_prefix = prefix + else: + exec_prefix = sys.exec_prefix + if not prefix: + prefix = sys.prefix + + # determine whether -p points to the Python source tree + ishome = os.path.exists(os.path.join(prefix, 'Python', 'ceval.c')) + + # locations derived from options + version = sys.version[:3] + if win: + extensions_c = 'frozen_extensions.c' + if ishome: + print "(Using Python source directory)" + binlib = exec_prefix + incldir = os.path.join(prefix, 'Include') + config_h_dir = exec_prefix + config_c_in = os.path.join(prefix, 'Modules', 'config.c.in') + frozenmain_c = os.path.join(prefix, 'Python', 'frozenmain.c') + makefile_in = os.path.join(exec_prefix, 'Modules', 'Makefile') + if win: + frozendllmain_c = os.path.join(exec_prefix, 'Pc\\frozen_dllmain.c') + else: + binlib = os.path.join(exec_prefix, + 'lib', 'python%s' % version, 'config') + incldir = os.path.join(prefix, 'include', 'python%s' % version) + config_h_dir = os.path.join(exec_prefix, 'include', + 'python%s' % version) + config_c_in = os.path.join(binlib, 'config.c.in') + frozenmain_c = os.path.join(binlib, 'frozenmain.c') + makefile_in = os.path.join(binlib, 'Makefile') + frozendllmain_c = os.path.join(binlib, 'frozen_dllmain.c') + supp_sources = [] + defines = [] + includes = ['-I' + incldir, '-I' + config_h_dir] + + # sanity check of directories and files + check_dirs = [prefix, exec_prefix, binlib, incldir] + if not win: check_dirs = check_dirs + extensions # These are not directories on Windows. + for dir in check_dirs: + if not os.path.exists(dir): + usage('needed directory %s not found' % dir) + if not os.path.isdir(dir): + usage('%s: not a directory' % dir) + if win: + files = supp_sources + extensions # extensions are files on Windows. + else: + files = [config_c_in, makefile_in] + supp_sources + for file in supp_sources: + if not os.path.exists(file): + usage('needed file %s not found' % file) + if not os.path.isfile(file): + usage('%s: not a plain file' % file) + if not win: + for dir in extensions: + setup = os.path.join(dir, 'Setup') + if not os.path.exists(setup): + usage('needed file %s not found' % setup) + if not os.path.isfile(setup): + usage('%s: not a plain file' % setup) + + # check that enough arguments are passed + if not args: + usage('at least one filename argument required') + + # check that file arguments exist + for arg in args: + if arg == '-m': + break + # if user specified -m on the command line before _any_ + # file names, then nothing should be checked (as the + # very first file should be a module name) + if modargs: + break + if not os.path.exists(arg): + usage('argument %s not found' % arg) + if not os.path.isfile(arg): + usage('%s: not a plain file' % arg) + + # process non-option arguments + scriptfile = args[0] + modules = args[1:] + + # derive target name from script name + base = os.path.basename(scriptfile) + base, ext = os.path.splitext(base) + if base: + if base != scriptfile: + target = base + else: + target = base + '.bin' + + # handle -o option + base_frozen_c = frozen_c + base_config_c = config_c + base_target = target + if odir and not os.path.isdir(odir): + try: + os.mkdir(odir) + print "Created output directory", odir + except os.error, msg: + usage('%s: mkdir failed (%s)' % (odir, str(msg))) + base = '' + if odir: + base = os.path.join(odir, '') + frozen_c = os.path.join(odir, frozen_c) + config_c = os.path.join(odir, config_c) + target = os.path.join(odir, target) + makefile = os.path.join(odir, makefile) + if win: extensions_c = os.path.join(odir, extensions_c) + + # Handle special entry point requirements + # (on Windows, some frozen programs do not use __main__, but + # import the module directly. Eg, DLLs, Services, etc + custom_entry_point = None # Currently only used on Windows + python_entry_is_main = 1 # Is the entry point called __main__? + # handle -s option on Windows + if win: + import winmakemakefile + try: + custom_entry_point, python_entry_is_main = \ + winmakemakefile.get_custom_entry_point(subsystem) + except ValueError, why: + usage(why) + + + # Actual work starts here... + + # collect all modules of the program + dir = os.path.dirname(scriptfile) + path[0] = dir + mf = modulefinder.ModuleFinder(path, debug, exclude) + + if win and subsystem=='service': + # If a Windows service, then add the "built-in" module. + mod = mf.add_module("servicemanager") + mod.__file__="dummy.pyd" # really built-in to the resulting EXE + + for mod in implicits: + mf.import_hook(mod) + for mod in modules: + if mod == '-m': + modargs = 1 + continue + if modargs: + if mod[-2:] == '.*': + mf.import_hook(mod[:-2], None, ["*"]) + else: + mf.import_hook(mod) + else: + mf.load_file(mod) + + # Add the main script as either __main__, or the actual module name. + if python_entry_is_main: + mf.run_script(scriptfile) + else: + mf.load_file(scriptfile) + + if debug > 0: + mf.report() + print + dict = mf.modules + + # generate output for frozen modules + files = makefreeze.makefreeze(base, dict, debug, custom_entry_point, 1) + # look for unfrozen modules (builtin and of unknown origin) + builtins = [] + unknown = [] + mods = dict.keys() + mods.sort() + for mod in mods: + if dict[mod].__code__: + continue + if not dict[mod].__file__: + builtins.append(mod) + else: + unknown.append(mod) + + # search for unknown modules in extensions directories (not on Windows) + addfiles = [] + frozen_extensions = [] # Windows list of modules. + if unknown or (not win and builtins): + if not win: + addfiles, addmods = \ + checkextensions.checkextensions(unknown+builtins, + extensions) + for mod in addmods: + if mod in unknown: + unknown.remove(mod) + builtins.append(mod) + else: + # Do the windows thang... + import checkextensions_win32 + # Get a list of CExtension instances, each describing a module + # (including its source files) + frozen_extensions = checkextensions_win32.checkextensions( + unknown, extensions, prefix) + for mod in frozen_extensions: + unknown.remove(mod.name) + + # report unknown modules + if unknown: + sys.stderr.write('Warning: unknown modules remain: %s\n' % + string.join(unknown)) + + # windows gets different treatment + if win: + # Taking a shortcut here... + import winmakemakefile, checkextensions_win32 + checkextensions_win32.write_extension_table(extensions_c, + frozen_extensions) + # Create a module definition for the bootstrap C code. + xtras = [frozenmain_c, os.path.basename(frozen_c), + frozendllmain_c, os.path.basename(extensions_c)] + files + maindefn = checkextensions_win32.CExtension( '__main__', xtras ) + frozen_extensions.append( maindefn ) + outfp = open(makefile, 'w') + try: + winmakemakefile.makemakefile(outfp, + locals(), + frozen_extensions, + os.path.basename(target)) + finally: + outfp.close() + return + + # generate config.c and Makefile + builtins.sort() + infp = open(config_c_in) + outfp = bkfile.open(config_c, 'w') + try: + makeconfig.makeconfig(infp, outfp, builtins) + finally: + outfp.close() + infp.close() + + cflags = defines + includes + ['$(OPT)'] + libs = [os.path.join(binlib, 'libpython$(VERSION).a')] + + somevars = {} + if os.path.exists(makefile_in): + makevars = parsesetup.getmakevars(makefile_in) + for key in makevars.keys(): + somevars[key] = makevars[key] + + somevars['CFLAGS'] = string.join(cflags) # override + files = ['$(OPT)', '$(LDFLAGS)', base_config_c, base_frozen_c] + \ + files + supp_sources + addfiles + libs + \ + ['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)'] + + outfp = bkfile.open(makefile, 'w') + try: + makemakefile.makemakefile(outfp, somevars, files, base_target) + finally: + outfp.close() + + # Done! + + if odir: + print 'Now run "make" in', odir, + print 'to build the target:', base_target + else: + print 'Now run "make" to build the target:', base_target + + +# Print usage message and exit + +def usage(msg): + sys.stdout = sys.stderr + print "Error:", msg + print "Use ``%s -h'' for help" % sys.argv[0] + sys.exit(2) + + +main() diff --git a/intern/python/freeze/hello.py b/intern/python/freeze/hello.py new file mode 100644 index 00000000000..f978acc883c --- /dev/null +++ b/intern/python/freeze/hello.py @@ -0,0 +1 @@ +print 'Hello world...' diff --git a/intern/python/freeze/makeconfig.py b/intern/python/freeze/makeconfig.py new file mode 100644 index 00000000000..5d1ba2c333c --- /dev/null +++ b/intern/python/freeze/makeconfig.py @@ -0,0 +1,61 @@ +import regex + + +# Write the config.c file + +never = ['marshal', '__main__', '__builtin__', 'sys', 'exceptions'] + +def makeconfig(infp, outfp, modules, with_ifdef=0): + m1 = regex.compile('-- ADDMODULE MARKER 1 --') + m2 = regex.compile('-- ADDMODULE MARKER 2 --') + while 1: + line = infp.readline() + if not line: break + outfp.write(line) + if m1 and m1.search(line) >= 0: + m1 = None + for mod in modules: + if mod in never: + continue + if with_ifdef: + outfp.write("#ifndef init%s\n"%mod) + outfp.write('extern void init%s();\n' % mod) + if with_ifdef: + outfp.write("#endif\n") + elif m2 and m2.search(line) >= 0: + m2 = None + for mod in modules: + if mod in never: + continue + outfp.write('\t{"%s", init%s},\n' % + (mod, mod)) + if m1: + sys.stderr.write('MARKER 1 never found\n') + elif m2: + sys.stderr.write('MARKER 2 never found\n') + + +# Test program. + +def test(): + import sys + if not sys.argv[3:]: + print 'usage: python makeconfig.py config.c.in outputfile', + print 'modulename ...' + sys.exit(2) + if sys.argv[1] == '-': + infp = sys.stdin + else: + infp = open(sys.argv[1]) + if sys.argv[2] == '-': + outfp = sys.stdout + else: + outfp = open(sys.argv[2], 'w') + makeconfig(infp, outfp, sys.argv[3:]) + if outfp != sys.stdout: + outfp.close() + if infp != sys.stdin: + infp.close() + +if __name__ == '__main__': + test() diff --git a/intern/python/freeze/makefreeze.py b/intern/python/freeze/makefreeze.py new file mode 100644 index 00000000000..8bd9ce1a2e2 --- /dev/null +++ b/intern/python/freeze/makefreeze.py @@ -0,0 +1,115 @@ +## +## +## Customized makefreeze for NaN +## +## +## 1.11.2001, strubi@blender.nl +## +## +import marshal +import string +import bkfile + + +# Write a file containing frozen code for the modules in the dictionary. + +header = """ +#include "Python.h" + +static struct _frozen _PyImport_FrozenModules[] = { +""" +trailer = """\ + {0, 0, 0} /* sentinel */ +}; +""" + +# if __debug__ == 0 (i.e. -O option given), set Py_OptimizeFlag in frozen app. +main_entry_point = """ +int +main(argc, argv) + int argc; + char **argv; +{ + extern int Py_FrozenMain(int, char **); + init_frozen_modules(); + return Py_FrozenMain(argc, argv); +} + +""" + +default_entry_point = """ +void +init_frozenmodules(void) +{ +""" + ((not __debug__ and """ + Py_OptimizeFlag++; +""") or "") + """ + PyImport_FrozenModules = _PyImport_FrozenModules; +} +""" + +HEADER = """ +/* This is a generated file, containing frozen bytecode. + * Check $(HOME)/develop/intern/python/freeze/README for more information. + */ + +""" + +def makefreeze(base, dict, debug=0, entry_point = None, exclude_main = 0): + if entry_point is None: entry_point = default_entry_point + done = [] + files = [] + mods = dict.keys() + if exclude_main: + mods.remove("__main__") + mods.sort() + for mod in mods: + m = dict[mod] + mangled = string.join(string.split(mod, "."), "__") + if m.__code__: + file = 'M_' + mangled + '.c' + outfp = bkfile.open(base + file, 'w') + outfp.write(HEADER) + files.append(file) + if debug: + print "freezing", mod, "..." + str = marshal.dumps(m.__code__) + size = len(str) + if m.__path__: + # Indicate package by negative size + size = -size + done.append((mod, mangled, size)) + writecode(outfp, mangled, str) + outfp.close() + if debug: + print "generating table of frozen modules" + outfp = bkfile.open(base + 'frozen.c', 'w') + for mod, mangled, size in done: + outfp.write('extern unsigned char M_%s[];\n' % mangled) + outfp.write(header) + for mod, mangled, size in done: + outfp.write('\t{"%s", M_%s, %d},\n' % (mod, mangled, size)) + outfp.write(trailer) + outfp.write(entry_point) + outfp.close() + #outfp = bkfile.open(base + 'main.c', 'w') + #outfp.write(main_entry_point) + #outfp.close() + return files + + + +# Write a C initializer for a module containing the frozen python code. +# The array is called M_<mod>. + +def writecode(outfp, mod, str): + outfp.write('unsigned char M_%s[] = {' % mod) + for i in range(0, len(str), 16): + outfp.write('\n\t') + for c in str[i:i+16]: + outfp.write('%d,' % ord(c)) + outfp.write('\n};\n') + +## def writecode(outfp, mod, str): +## outfp.write('unsigned char M_%s[%d] = "%s";\n' % (mod, len(str), +## string.join(map(lambda s: `s`[1:-1], string.split(str, '"')), '\\"'))) diff --git a/intern/python/freeze/makemakefile.py b/intern/python/freeze/makemakefile.py new file mode 100644 index 00000000000..bb2ed43430d --- /dev/null +++ b/intern/python/freeze/makemakefile.py @@ -0,0 +1,57 @@ +# Write the actual Makefile. +## +## +## Customized makemakefile for NaN +## +## +## 1.11.2001, strubi@blender.nl +## +## + + +import os +import string + +def makemakefile(outfp, makevars, files, target): + outfp.write("# Makefile generated by freeze.py script\n\n") + + target = "frozen" + libtarget = "lib" + target + targetlib = libtarget + ".a" + #targetlib = "libpyfrozen.a" + + keys = makevars.keys() + keys.sort() + for key in keys: + outfp.write("%s=%s\n" % (key, makevars[key])) + outfp.write("\nall: %s\n\n" % libtarget) + + deps = [] + for i in range(len(files)): + file = files[i] + if file[-2:] == '.c': + base = os.path.basename(file) + dest = base[:-2] + '.o' + # outfp.write("%s: %s\n" % (dest, file)) + # outfp.write("\t$(CC) $(CFLAGS) -c %s\n" % file) + files[i] = dest + deps.append(dest) + + mainfile = 'M___main__.o' + + try: + deps.remove(mainfile) + except: + pass + outfp.write("OBJS = %s\n" % string.join(deps)) + +# libfiles.remove('M___main__.o') # don't link with __main__ + + outfp.write("\n%s: $(OBJS)\n" % (libtarget)) + outfp.write("\t$(AR) ruv %s $(OBJS)\n" % (targetlib)) + + outfp.write("\n%s: %s $(OBJS)\n" % (target, mainfile)) + outfp.write("\t$(CC) %s %s -o %s $(LDLAST)\n" % + (mainfile, " ".join(deps), target)) + + outfp.write("\nclean:\n\t-rm -f *.o *.a %s\n" % target) diff --git a/intern/python/freeze/modulefinder.py b/intern/python/freeze/modulefinder.py new file mode 100644 index 00000000000..e84a54128f6 --- /dev/null +++ b/intern/python/freeze/modulefinder.py @@ -0,0 +1,444 @@ +"""Find modules used by a script, using introspection.""" + +import dis +import imp +import marshal +import os +import re +import string +import sys + +if sys.platform=="win32": + # On Windows, we can locate modules in the registry with + # the help of the win32api package. + try: + import win32api + except ImportError: + print "The win32api module is not available - modules listed" + print "in the registry will not be found." + win32api = None + + +IMPORT_NAME = dis.opname.index('IMPORT_NAME') +IMPORT_FROM = dis.opname.index('IMPORT_FROM') +STORE_NAME = dis.opname.index('STORE_NAME') +STORE_FAST = dis.opname.index('STORE_FAST') +STORE_GLOBAL = dis.opname.index('STORE_GLOBAL') +STORE_OPS = [STORE_NAME, STORE_FAST, STORE_GLOBAL] + +# Modulefinder does a good job at simulating Python's, but it can not +# handle __path__ modifications packages make at runtime. Therefore there +# is a mechanism whereby you can register extra paths in this map for a +# package, and it will be honored. + +# Note this is a mapping is lists of paths. +packagePathMap = {} + +# A Public interface +def AddPackagePath(packagename, path): + paths = packagePathMap.get(packagename, []) + paths.append(path) + packagePathMap[packagename] = paths + +class Module: + + def __init__(self, name, file=None, path=None): + self.__name__ = name + self.__file__ = file + self.__path__ = path + self.__code__ = None + + def __repr__(self): + s = "Module(%s" % `self.__name__` + if self.__file__ is not None: + s = s + ", %s" % `self.__file__` + if self.__path__ is not None: + s = s + ", %s" % `self.__path__` + s = s + ")" + return s + + +class ModuleFinder: + + def __init__(self, path=None, debug=0, excludes = []): + if path is None: + path = sys.path + self.path = path + self.modules = {} + self.badmodules = {} + self.debug = debug + self.indent = 0 + self.excludes = excludes + + def msg(self, level, str, *args): + if level <= self.debug: + for i in range(self.indent): + print " ", + print str, + for arg in args: + print repr(arg), + print + + def msgin(self, *args): + level = args[0] + if level <= self.debug: + self.indent = self.indent + 1 + apply(self.msg, args) + + def msgout(self, *args): + level = args[0] + if level <= self.debug: + self.indent = self.indent - 1 + apply(self.msg, args) + + def run_script(self, pathname): + self.msg(2, "run_script", pathname) + fp = open(pathname) + stuff = ("", "r", imp.PY_SOURCE) + self.load_module('__main__', fp, pathname, stuff) + + def load_file(self, pathname): + dir, name = os.path.split(pathname) + name, ext = os.path.splitext(name) + fp = open(pathname) + stuff = (ext, "r", imp.PY_SOURCE) + self.load_module(name, fp, pathname, stuff) + + def import_hook(self, name, caller=None, fromlist=None): + self.msg(3, "import_hook", name, caller, fromlist) + parent = self.determine_parent(caller) + q, tail = self.find_head_package(parent, name) + m = self.load_tail(q, tail) + if not fromlist: + return q + if m.__path__: + self.ensure_fromlist(m, fromlist) + + def determine_parent(self, caller): + self.msgin(4, "determine_parent", caller) + if not caller: + self.msgout(4, "determine_parent -> None") + return None + pname = caller.__name__ + if caller.__path__: + parent = self.modules[pname] + assert caller is parent + self.msgout(4, "determine_parent ->", parent) + return parent + if '.' in pname: + i = string.rfind(pname, '.') + pname = pname[:i] + parent = self.modules[pname] + assert parent.__name__ == pname + self.msgout(4, "determine_parent ->", parent) + return parent + self.msgout(4, "determine_parent -> None") + return None + + def find_head_package(self, parent, name): + self.msgin(4, "find_head_package", parent, name) + if '.' in name: + i = string.find(name, '.') + head = name[:i] + tail = name[i+1:] + else: + head = name + tail = "" + if parent: + qname = "%s.%s" % (parent.__name__, head) + else: + qname = head + q = self.import_module(head, qname, parent) + if q: + self.msgout(4, "find_head_package ->", (q, tail)) + return q, tail + if parent: + qname = head + parent = None + q = self.import_module(head, qname, parent) + if q: + self.msgout(4, "find_head_package ->", (q, tail)) + return q, tail + self.msgout(4, "raise ImportError: No module named", qname) + raise ImportError, "No module named " + qname + + def load_tail(self, q, tail): + self.msgin(4, "load_tail", q, tail) + m = q + while tail: + i = string.find(tail, '.') + if i < 0: i = len(tail) + head, tail = tail[:i], tail[i+1:] + mname = "%s.%s" % (m.__name__, head) + m = self.import_module(head, mname, m) + if not m: + self.msgout(4, "raise ImportError: No module named", mname) + raise ImportError, "No module named " + mname + self.msgout(4, "load_tail ->", m) + return m + + def ensure_fromlist(self, m, fromlist, recursive=0): + self.msg(4, "ensure_fromlist", m, fromlist, recursive) + for sub in fromlist: + if sub == "*": + if not recursive: + all = self.find_all_submodules(m) + if all: + self.ensure_fromlist(m, all, 1) + elif not hasattr(m, sub): + subname = "%s.%s" % (m.__name__, sub) + submod = self.import_module(sub, subname, m) + if not submod: + raise ImportError, "No module named " + subname + + def find_all_submodules(self, m): + if not m.__path__: + return + modules = {} + suffixes = [".py", ".pyc", ".pyo"] + for dir in m.__path__: + try: + names = os.listdir(dir) + except os.error: + self.msg(2, "can't list directory", dir) + continue + for name in names: + mod = None + for suff in suffixes: + n = len(suff) + if name[-n:] == suff: + mod = name[:-n] + break + if mod and mod != "__init__": + modules[mod] = mod + return modules.keys() + + def import_module(self, partname, fqname, parent): + self.msgin(3, "import_module", partname, fqname, parent) + try: + m = self.modules[fqname] + except KeyError: + pass + else: + self.msgout(3, "import_module ->", m) + return m + if self.badmodules.has_key(fqname): + self.msgout(3, "import_module -> None") + if parent: + self.badmodules[fqname][parent.__name__] = None + return None + try: + fp, pathname, stuff = self.find_module(partname, + parent and parent.__path__) + except ImportError: + self.msgout(3, "import_module ->", None) + return None + try: + m = self.load_module(fqname, fp, pathname, stuff) + finally: + if fp: fp.close() + if parent: + setattr(parent, partname, m) + self.msgout(3, "import_module ->", m) + return m + + def load_module(self, fqname, fp, pathname, (suffix, mode, type)): + self.msgin(2, "load_module", fqname, fp and "fp", pathname) + if type == imp.PKG_DIRECTORY: + m = self.load_package(fqname, pathname) + self.msgout(2, "load_module ->", m) + return m + if type == imp.PY_SOURCE: + co = compile(fp.read()+'\n', pathname, 'exec') + elif type == imp.PY_COMPILED: + if fp.read(4) != imp.get_magic(): + self.msgout(2, "raise ImportError: Bad magic number", pathname) + raise ImportError, "Bad magic number in %s" % pathname + fp.read(4) + co = marshal.load(fp) + else: + co = None + m = self.add_module(fqname) + m.__file__ = pathname + if co: + m.__code__ = co + self.scan_code(co, m) + self.msgout(2, "load_module ->", m) + return m + + def scan_code(self, co, m): + code = co.co_code + n = len(code) + i = 0 + lastname = None + while i < n: + c = code[i] + i = i+1 + op = ord(c) + if op >= dis.HAVE_ARGUMENT: + oparg = ord(code[i]) + ord(code[i+1])*256 + i = i+2 + if op == IMPORT_NAME: + name = lastname = co.co_names[oparg] + if not self.badmodules.has_key(lastname): + try: + self.import_hook(name, m) + except ImportError, msg: + self.msg(2, "ImportError:", str(msg)) + if not self.badmodules.has_key(name): + self.badmodules[name] = {} + self.badmodules[name][m.__name__] = None + elif op == IMPORT_FROM: + name = co.co_names[oparg] + assert lastname is not None + if not self.badmodules.has_key(lastname): + try: + self.import_hook(lastname, m, [name]) + except ImportError, msg: + self.msg(2, "ImportError:", str(msg)) + fullname = lastname + "." + name + if not self.badmodules.has_key(fullname): + self.badmodules[fullname] = {} + self.badmodules[fullname][m.__name__] = None + elif op in STORE_OPS: + # Skip; each IMPORT_FROM is followed by a STORE_* opcode + pass + else: + lastname = None + for c in co.co_consts: + if isinstance(c, type(co)): + self.scan_code(c, m) + + def load_package(self, fqname, pathname): + self.msgin(2, "load_package", fqname, pathname) + m = self.add_module(fqname) + m.__file__ = pathname + m.__path__ = [pathname] + + # As per comment at top of file, simulate runtime __path__ additions. + m.__path__ = m.__path__ + packagePathMap.get(fqname, []) + + fp, buf, stuff = self.find_module("__init__", m.__path__) + self.load_module(fqname, fp, buf, stuff) + self.msgout(2, "load_package ->", m) + return m + + def add_module(self, fqname): + if self.modules.has_key(fqname): + return self.modules[fqname] + self.modules[fqname] = m = Module(fqname) + return m + + def find_module(self, name, path): + if name in self.excludes: + self.msgout(3, "find_module -> Excluded") + raise ImportError, name + + if path is None: + if name in sys.builtin_module_names: + return (None, None, ("", "", imp.C_BUILTIN)) + + # Emulate the Registered Module support on Windows. + if sys.platform=="win32" and win32api is not None: + HKEY_LOCAL_MACHINE = 0x80000002 + try: + pathname = win32api.RegQueryValue(HKEY_LOCAL_MACHINE, "Software\\Python\\PythonCore\\%s\\Modules\\%s" % (sys.winver, name)) + fp = open(pathname, "rb") + # XXX - To do - remove the hard code of C_EXTENSION. + stuff = "", "rb", imp.C_EXTENSION + return fp, pathname, stuff + except win32api.error: + pass + + path = self.path + return imp.find_module(name, path) + + def report(self): + print + print " %-25s %s" % ("Name", "File") + print " %-25s %s" % ("----", "----") + # Print modules found + keys = self.modules.keys() + keys.sort() + for key in keys: + m = self.modules[key] + if m.__path__: + print "P", + else: + print "m", + print "%-25s" % key, m.__file__ or "" + + # Print missing modules + keys = self.badmodules.keys() + keys.sort() + for key in keys: + # ... but not if they were explicitly excluded. + if key not in self.excludes: + mods = self.badmodules[key].keys() + mods.sort() + print "?", key, "from", string.join(mods, ', ') + + +def test(): + # Parse command line + import getopt + try: + opts, args = getopt.getopt(sys.argv[1:], "dmp:qx:") + except getopt.error, msg: + print msg + return + + # Process options + debug = 1 + domods = 0 + addpath = [] + exclude = [] + for o, a in opts: + if o == '-d': + debug = debug + 1 + if o == '-m': + domods = 1 + if o == '-p': + addpath = addpath + string.split(a, os.pathsep) + if o == '-q': + debug = 0 + if o == '-x': + exclude.append(a) + + # Provide default arguments + if not args: + script = "hello.py" + else: + script = args[0] + + # Set the path based on sys.path and the script directory + path = sys.path[:] + path[0] = os.path.dirname(script) + path = addpath + path + if debug > 1: + print "path:" + for item in path: + print " ", `item` + + # Create the module finder and turn its crank + mf = ModuleFinder(path, debug, exclude) + for arg in args[1:]: + if arg == '-m': + domods = 1 + continue + if domods: + if arg[-2:] == '.*': + mf.import_hook(arg[:-2], None, ["*"]) + else: + mf.import_hook(arg) + else: + mf.load_file(arg) + mf.run_script(script) + mf.report() + + +if __name__ == '__main__': + try: + test() + except KeyboardInterrupt: + print "\n[interrupt]" diff --git a/intern/python/freeze/parsesetup.py b/intern/python/freeze/parsesetup.py new file mode 100644 index 00000000000..1795671e946 --- /dev/null +++ b/intern/python/freeze/parsesetup.py @@ -0,0 +1,98 @@ +# Parse Makefiles and Python Setup(.in) files. + +import regex +import string + + +# Extract variable definitions from a Makefile. +# Return a dictionary mapping names to values. +# May raise IOError. + +makevardef = regex.compile('^\([a-zA-Z0-9_]+\)[ \t]*=\(.*\)') + +def getmakevars(filename): + variables = {} + fp = open(filename) + try: + while 1: + line = fp.readline() + if not line: + break + if makevardef.match(line) < 0: + continue + name, value = makevardef.group(1, 2) + # Strip trailing comment + i = string.find(value, '#') + if i >= 0: + value = value[:i] + value = string.strip(value) + variables[name] = value + finally: + fp.close() + return variables + + +# Parse a Python Setup(.in) file. +# Return two dictionaries, the first mapping modules to their +# definitions, the second mapping variable names to their values. +# May raise IOError. + +setupvardef = regex.compile('^\([a-zA-Z0-9_]+\)=\(.*\)') + +def getsetupinfo(filename): + modules = {} + variables = {} + fp = open(filename) + try: + while 1: + line = fp.readline() + if not line: + break + # Strip comments + i = string.find(line, '#') + if i >= 0: + line = line[:i] + if setupvardef.match(line) >= 0: + name, value = setupvardef.group(1, 2) + variables[name] = string.strip(value) + else: + words = string.split(line) + if words: + modules[words[0]] = words[1:] + finally: + fp.close() + return modules, variables + + +# Test the above functions. + +def test(): + import sys + import os + if not sys.argv[1:]: + print 'usage: python parsesetup.py Makefile*|Setup* ...' + sys.exit(2) + for arg in sys.argv[1:]: + base = os.path.basename(arg) + if base[:8] == 'Makefile': + print 'Make style parsing:', arg + v = getmakevars(arg) + prdict(v) + elif base[:5] == 'Setup': + print 'Setup style parsing:', arg + m, v = getsetupinfo(arg) + prdict(m) + prdict(v) + else: + print arg, 'is neither a Makefile nor a Setup file' + print '(name must begin with "Makefile" or "Setup")' + +def prdict(d): + keys = d.keys() + keys.sort() + for key in keys: + value = d[key] + print "%-15s" % key, str(value) + +if __name__ == '__main__': + test() diff --git a/intern/python/freeze/winmakemakefile.py b/intern/python/freeze/winmakemakefile.py new file mode 100644 index 00000000000..d668a6e8273 --- /dev/null +++ b/intern/python/freeze/winmakemakefile.py @@ -0,0 +1,146 @@ +import sys, os, string + +# Template used then the program is a GUI program +WINMAINTEMPLATE = """ +#include <windows.h> + +int WINAPI WinMain( + HINSTANCE hInstance, // handle to current instance + HINSTANCE hPrevInstance, // handle to previous instance + LPSTR lpCmdLine, // pointer to command line + int nCmdShow // show state of window + ) +{ + extern int Py_FrozenMain(int, char **); + PyImport_FrozenModules = _PyImport_FrozenModules; + return Py_FrozenMain(__argc, __argv); +} +""" + +SERVICETEMPLATE = """ +extern int PythonService_main(int, char **); + +int main( int argc, char **argv) +{ + PyImport_FrozenModules = _PyImport_FrozenModules; + return PythonService_main(argc, argv); +} +""" + +subsystem_details = { + # -s flag : (C entry point template), (is it __main__?), (is it a DLL?) + 'console' : (None, 1, 0), + 'windows' : (WINMAINTEMPLATE, 1, 0), + 'service' : (SERVICETEMPLATE, 0, 0), + 'com_dll' : ("", 0, 1), +} + +def get_custom_entry_point(subsystem): + try: + return subsystem_details[subsystem][:2] + except KeyError: + raise ValueError, "The subsystem %s is not known" % subsystem + + +def makemakefile(outfp, vars, files, target): + save = sys.stdout + try: + sys.stdout = outfp + realwork(vars, files, target) + finally: + sys.stdout = save + +def realwork(vars, moddefns, target): + version_suffix = `sys.version_info[0]`+`sys.version_info[1]` + print "# Makefile for Microsoft Visual C++ generated by freeze.py script" + print + print 'target = %s' % target + print 'pythonhome = %s' % vars['prefix'] + print + print 'DEBUG=0 # Set to 1 to use the _d versions of Python.' + print '!IF $(DEBUG)' + print 'debug_suffix=_d' + print 'c_debug=/Zi /Od /DDEBUG /D_DEBUG' + print 'l_debug=/DEBUG' + print 'temp_dir=Build\\Debug' + print '!ELSE' + print 'debug_suffix=' + print 'c_debug=/Ox' + print 'l_debug=' + print 'temp_dir=Build\\Release' + print '!ENDIF' + print + + print '# The following line assumes you have built Python using the standard instructions' + print '# Otherwise fix the following line to point to the library.' + print 'pythonlib = "$(pythonhome)/pcbuild/python%s$(debug_suffix).lib"' % version_suffix + print + + # We only ever write one "entry point" symbol - either + # "main" or "WinMain". Therefore, there is no need to + # pass a subsystem switch to the linker as it works it + # out all by itself. However, the subsystem _does_ determine + # the file extension and additional linker flags. + target_link_flags = "" + target_ext = ".exe" + if subsystem_details[vars['subsystem']][2]: + target_link_flags = "-dll" + target_ext = ".dll" + + + print "# As the target uses Python%s.dll, we must use this compiler option!" % version_suffix + print "cdl = /MD" + print + print "all: $(target)$(debug_suffix)%s" % (target_ext) + print + + print '$(temp_dir):' + print ' if not exist $(temp_dir)\. mkdir $(temp_dir)' + print + + objects = [] + libs = ["shell32.lib", "comdlg32.lib", "wsock32.lib", "user32.lib", "oleaut32.lib"] + for moddefn in moddefns: + print "# Module", moddefn.name + for file in moddefn.sourceFiles: + base = os.path.basename(file) + base, ext = os.path.splitext(base) + objects.append(base + ".obj") + print '$(temp_dir)\%s.obj: "%s"' % (base, file) + print "\t@$(CC) -c -nologo /Fo$* $(cdl) $(c_debug) /D BUILD_FREEZE", + print '"-I$(pythonhome)/Include" "-I$(pythonhome)/PC" \\' + print "\t\t$(cflags) $(cdebug) $(cinclude) \\" + extra = moddefn.GetCompilerOptions() + if extra: + print "\t\t%s \\" % (string.join(extra),) + print '\t\t"%s"' % file + print + + # Add .lib files this module needs + for modlib in moddefn.GetLinkerLibs(): + if modlib not in libs: + libs.append(modlib) + + print "ADDN_LINK_FILES=", + for addn in vars['addn_link']: print '"%s"' % (addn), + print ; print + + print "OBJS=", + for obj in objects: print '"$(temp_dir)\%s"' % (obj), + print ; print + + print "LIBS=", + for lib in libs: print '"%s"' % (lib), + print ; print + + print "$(target)$(debug_suffix)%s: $(temp_dir) $(OBJS)" % (target_ext) + print "\tlink -out:$(target)$(debug_suffix)%s %s" % (target_ext, target_link_flags), + print "\t$(OBJS) \\" + print "\t$(LIBS) \\" + print "\t$(ADDN_LINK_FILES) \\" + print "\t$(pythonlib) $(lcustom) $(l_debug)\\" + print "\t$(resources)" + print + print "clean:" + print "\t-rm -f *.obj" + print "\t-rm -f $(target).exe" diff --git a/intern/python/ivexport.py b/intern/python/ivexport.py new file mode 100644 index 00000000000..85987aad66b --- /dev/null +++ b/intern/python/ivexport.py @@ -0,0 +1,225 @@ +####################### +# (c) Jan Walter 2000 # +####################### + +# CVS +# $Author$ +# $Date$ +# $RCSfile$ +# $Revision$ + +import Blender + +class InventorExport: + def __init__(self, filename): + self.file = open(filename, "w") + + def beginObject(self, object): + self.file.write(" Separator {\n") + + def endObject(self, object): + self.file.write(" }\n") + + def export(self, scene): + print "exporting ..." + self.writeHeader() + for name in scene.objects: + object = Blender.getObject(name) + self.beginObject(object) + self.writeObject(object) + self.endObject(object) + self.writeEnd() + + def writeEnd(self): + self.file.write("}\n") + self.file.close() + print "... finished" + + def writeFaces(self, faces, smooth, colors, materials, texture): + self.file.write(" IndexedFaceSet {\n") + # colors + if colors: + self.file.write(" vertexProperty VertexProperty {\n") + self.file.write(" orderedRGBA [\n") + for color in colors[:-1]: + r = hex(int(color[0] * 255)) + if len(r) == 3: + r = r + "0" + g = hex(int(color[1] * 255)) + if len(g) == 3: + g = g + "0" + b = hex(int(color[2] * 255)) + if len(b) == 3: + b = b + "0" + colstr = r + g[2:] + b[2:] + self.file.write(" %sff,\n" % colstr) + color = colors[-1] + r = hex(int(color[0] * 255)) + if len(r) == 3: + r = r + "0" + g = hex(int(color[1] * 255)) + if len(g) == 3: + g = g + "0" + b = hex(int(color[2] * 255)) + if len(b) == 3: + b = b + "0" + colstr = r + g[2:] + b[2:] + self.file.write(" %sff\n" % colstr) + self.file.write(" ]\n") + self.file.write(" materialBinding PER_VERTEX_INDEXED\n") + self.file.write(" }\n") + # coordinates + self.file.write(" coordIndex [\n") + for face in faces[:-1]: + if face[4] != smooth: + pass + elif face[2] == 0 and face[3] == 0: + print "can't export lines at the moment ..." + elif face[3] == 0: + self.file.write(" %s, %s, %s, -1,\n" % + (face[0], face[1], face[2])) + else: + self.file.write(" %s, %s, %s, %s, -1,\n"% + (face[0], face[1], face[2], face[3])) + face = faces[-1] + if face[4] != smooth: + pass + elif face[2] == 0 and face[3] == 0: + print "can't export lines at the moment ..." + elif face[3] == 0: + self.file.write(" %s, %s, %s, -1,\n" % + (face[0], face[1], face[2])) + else: + self.file.write(" %s, %s, %s, %s, -1,\n"% + (face[0], face[1], face[2], face[3])) + self.file.write(" ]\n") + # materials + if not colors and materials: + self.file.write(" materialIndex [\n") + for face in faces[:-1]: + if face[4] != smooth: + pass + else: + self.file.write(" %s,\n" % face[5]) + face = faces[-1] + if face[4] != smooth: + pass + else: + self.file.write(" %s\n" % face[5]) + self.file.write(" ]\n") + # texture coordinates + if texture: + self.file.write(" textureCoordIndex [\n") + index = 0 + for face in faces: + if face[3] == 0: + self.file.write(" " + + "%s, %s, %s, -1,\n" % + (index, index+1, index+2)) + else: + self.file.write(" " + + "%s, %s, %s, %s, -1,\n" % + (index, index+1, index+2, index+3)) + index = index + 4 + self.file.write(" ]\n") + self.file.write(" }\n") + + def writeHeader(self): + self.file.write("#Inventor V2.1 ascii\n\n") + self.file.write("Separator {\n") + self.file.write(" ShapeHints {\n") + self.file.write(" vertexOrdering COUNTERCLOCKWISE\n") + self.file.write(" }\n") + + def writeMaterials(self, materials): + if materials: + self.file.write(" Material {\n") + self.file.write(" diffuseColor [\n") + for name in materials[:-1]: + material = Blender.getMaterial(name) + self.file.write(" %s %s %s,\n" % + (material.R, material.G, material.B)) + name = materials[-1] + material = Blender.getMaterial(name) + self.file.write(" %s %s %s\n" % + (material.R, material.G, material.B)) + self.file.write(" ]\n") + self.file.write(" }\n") + self.file.write(" MaterialBinding {\n") + self.file.write(" value PER_FACE_INDEXED\n") + self.file.write(" }\n") + + def writeMatrix(self, matrix): + self.file.write(" MatrixTransform {\n") + self.file.write(" matrix %s %s %s %s\n" % + (matrix[0][0], matrix[0][1], + matrix[0][2], matrix[0][3])) + self.file.write(" %s %s %s %s\n" % + (matrix[1][0], matrix[1][1], + matrix[1][2], matrix[1][3])) + self.file.write(" %s %s %s %s\n" % + (matrix[2][0], matrix[2][1], + matrix[2][2], matrix[2][3])) + self.file.write(" %s %s %s %s\n" % + (matrix[3][0], matrix[3][1], + matrix[3][2], matrix[3][3])) + self.file.write(" }\n") + + def writeNormals(self, normals): + self.file.write(" Normal {\n") + self.file.write(" vector [\n") + for normal in normals[:-1]: + self.file.write(" %s %s %s,\n" % + (normal[0], normal[1], normal[2])) + normal = normals[-1] + self.file.write(" %s %s %s\n" % + (normal[0], normal[1], normal[2])) + self.file.write(" ]\n") + self.file.write(" }\n") + + def writeObject(self, object): + if object.type == "Mesh": + mesh = Blender.getMesh(object.data) + self.writeMatrix(object.matrix) + self.writeMaterials(object.materials) + self.writeTexture(mesh.texture, mesh.texcoords) + self.writeVertices(mesh.vertices) + self.writeFaces(mesh.faces, 0, mesh.colors, object.materials, + mesh.texture) + self.writeNormals(mesh.normals) + self.writeFaces(mesh.faces, 1, mesh.colors, object.materials, + mesh.texture) + else: + print "can't export %s at the moment ..." % object.type + + def writeTexture(self, texture, texcoords): + if texture: + self.file.write(" Texture2 {\n") + self.file.write(' filename "%s"\n' % texture) + self.file.write(" }\n") + self.file.write(" TextureCoordinate2 {\n") + self.file.write(" point [\n") + for texcoord in texcoords: + self.file.write(" %s %s,\n" % + (texcoord[0], texcoord[1])) + self.file.write(" ]\n") + self.file.write(" }\n") + self.file.write(" TextureCoordinateBinding {\n") + self.file.write(" value PER_VERTEX_INDEXED\n") + self.file.write(" }\n") + + def writeVertices(self, vertices): + self.file.write(" Coordinate3 {\n") + self.file.write(" point [\n") + for vertex in vertices[:-1]: + self.file.write(" %s %s %s,\n" % + (vertex[0], vertex[1], vertex[2])) + vertex = vertices[-1] + self.file.write(" %s %s %s\n" % + (vertex[0], vertex[1], vertex[2])) + self.file.write(" ]\n") + self.file.write(" }\n") + +ivexport = InventorExport("test.iv") +scene = Blender.getCurrentScene() +ivexport.export(scene) diff --git a/intern/python/modules/Blender/BGL.py b/intern/python/modules/Blender/BGL.py new file mode 100644 index 00000000000..033b3560e4f --- /dev/null +++ b/intern/python/modules/Blender/BGL.py @@ -0,0 +1 @@ +from _Blender.BGL import * diff --git a/intern/python/modules/Blender/Camera.py b/intern/python/modules/Blender/Camera.py new file mode 100644 index 00000000000..33f615fc0da --- /dev/null +++ b/intern/python/modules/Blender/Camera.py @@ -0,0 +1,106 @@ +"""The Blender Camera module + +This module provides access to **Camera** objects in Blender + +Example:: + + from Blender import Camera, Object, Scene + c = Camera.New('ortho') # create new ortho camera data + c.lens = 35.0 # set lens value + cur = Scene.getCurrent() # get current Scene + ob = Object.New('Camera') # make camera object + ob.link(c) # link camera data with this object + cur.link(ob) # link object into scene + cur.setCurrentCamera(ob) # make this camera the active +""" + +import shadow +import _Blender.Camera as _Camera + + +class Camera(shadow.hasIPO): + """Wrapper for Camera DataBlock + + Attributes + + lens -- The lens value + + clipStart -- The clipping start of the view frustum + + clipEnd -- The end clipping plane of the view frustum + + type -- The camera type: + 0: perspective camera, + 1: orthogonal camera - (see Types) + + mode -- Drawing mode; see Modes +""" + + _emulation = {'Lens' : "lens", + 'ClSta' : "clipStart", + 'ClEnd' : "clipEnd", + } + + Types = {'persp' : 0, + 'ortho' : 1, + } + + Modes = {'showLimits' : 1, + 'showMist' : 2, + } + + def __init__(self, object): + self._object = object + + def getType(self): + """Returns camera type: "ortho" or "persp" """ + if self.type == self.Types['ortho']: + return 'ortho' + else: + return 'persp' + + def setType(self, type): + """Sets Camera type to 'type' which must be one of ["persp", "ortho"]""" + self._object.type = self.Types[type] + + def setMode(self, *modes): + """Sets Camera modes *the nice way*, instead of direct access +of the 'mode' member. +This function takes a variable number of string arguments of the types +listed in self.Modes. + + +Example:: + + c = Camera.New() + c.setMode('showMist', 'showLimits') +""" + flags = 0 + try: + for a in modes: + flags |= self.Modes[a] + except: + raise TypeError, "mode must be one of %s" % self.Modes.keys() + self.mode = flags + + def __repr__(self): + return "[Camera \"%s\"]" % self.name + +def New(type = 'persp'): + """Creates new camera Object and returns it. 'type', if specified, +must be one of Types""" + cam = Camera(_Camera.New()) + cam.setType(type) + return cam + +def get(name = None): + """Returns the Camera with name 'name', if given. Otherwise, a list +of all Cameras is returned""" + if name: + return Camera(_Camera.get(name)) + else: + return shadow._List(_Camera.get(), Camera) + +Get = get # emulation + + diff --git a/intern/python/modules/Blender/Draw.py b/intern/python/modules/Blender/Draw.py new file mode 100644 index 00000000000..6c2cb8be09f --- /dev/null +++ b/intern/python/modules/Blender/Draw.py @@ -0,0 +1 @@ +from _Blender.Draw import * diff --git a/intern/python/modules/Blender/Image.py b/intern/python/modules/Blender/Image.py new file mode 100644 index 00000000000..c1737e1bb0d --- /dev/null +++ b/intern/python/modules/Blender/Image.py @@ -0,0 +1,52 @@ +"""The Blender Image module + + This module provides (yet) basic support for Blender *Image* data blocks + + Example:: + + from Blender import Image + im = Image.Load('dead-parrot.jpg') +""" + +import _Blender.Image as _Image +import shadow + +class Image(shadow.shadow): + """Image DataBlock object + + See above example on how to create instances of Image objects. + + Attributes + + xrep -- Texture image tiling factor (subdivision) in X + + yrep -- Texture image tiling factor (subdivision) in Y + + LATER: + + * Image buffer access + + * better loading / saving of images +""" + pass + +def get(name): + """If 'name' given, the Image 'name' is returned if existing, 'None' otherwise. +If no name is given, a list of all Images is returned""" + pass + +def Load(filename): + """Returns image from file 'filename' as Image object if found, 'None' else.""" + pass + +def New(name): + """This function is currently not implemented""" + pass + +# override all functions again, the above classes are just made +# for documentation + +get = _Image.get +Get = get +Load = _Image.Load + diff --git a/intern/python/modules/Blender/Ipo.py b/intern/python/modules/Blender/Ipo.py new file mode 100644 index 00000000000..110f95a5d07 --- /dev/null +++ b/intern/python/modules/Blender/Ipo.py @@ -0,0 +1,279 @@ +"""The Blender Ipo module + +This module provides access to **Ipo** objects in Blender. + +An Ipo object is a datablock of IpoCurves which control properties of +an object in time. + +Note that IpoCurves assigned to rotation values (which must be specified +in radians) appear scaled in the IpoWindow (which is in fact true, due +to the fact that conversion to an internal unit of 10.0 angles happens). + +Example:: + + from Blender import Ipo, Object + + ipo = Ipo.New('Object', 'ObIpo') # Create object ipo with name 'ObIpo' + curve = ipo.addCurve('LocY') # add IpoCurve for LocY + curve.setInterpolation('Bezier') # set interpolation type + curve.setExtrapolation('CyclicLinear') # set extrapolation type + + curve.addBezier((0.0, 0.0)) # add automatic handle bezier point + curve.addBezier((20.0, 5.0), 'Free', (10.0, 4.0)) # specify left handle, right auto handle + curve.addBezier((30.0, 1.0), 'Vect') # automatic split handle + curve.addBezier((100.0, 1.0)) # auto handle + + curve.update() # recalculate curve handles + + curve.eval(35.0) # evaluate curve at 35.0 + + ob = Object.get('Plane') + ob.setIpo(ipo) # assign ipo to object +""" + +import _Blender.Ipo as _Ipo + +import shadow + +_RotIpoCurves = ["RotX", "RotY", "RotZ", "dRotX", "dRotY", "dRotZ"] + +_radian_factor = 5.72957814 # 18.0 / 3.14159255 + +def _convertBPoint(b): + f = _radian_factor + newb = BezierPoint() + p = b.pt + q = newb.pt + q[0], q[1] = (p[0], f * p[1]) + p = b.h1 + q = newb.h1 + q[0], q[1] = (p[0], f * p[1]) + p = b.h2 + q = newb.h2 + q[0], q[1] = (p[0], f * p[1]) + return newb + + +class IpoBlock(shadow.shadowEx): + """Wrapper for Blender Ipo DataBlock + + Attributes + + curves -- list of owned IpoCurves +""" + def get(self, channel = None): + """Returns curve with channel identifier 'channel', which is one of the properties +listed in the Ipo Window, 'None' if not found. +If 'channel' is not specified, all curves are returned in a list""" + if channel: + for c in self._object.curves: + if c.name == channel: + return IpoCurve(c) + return None + else: + return map(lambda x: IpoCurve(x), self._object.curves) + + def __getitem__(self, k): + """Emulates dictionary syntax, e.g. ipocurve = ipo['LocX']""" + curve = self.get(k) + if not curve: + raise KeyError, "Ipo does not have a curve for channel %s" % k + return curve + + def __setitem__(self, k, val): + """Emulates dictionary syntax, e.g. ipo['LocX'] = ipocurve""" + c = self.addCurve(k, val) + + has_key = get # dict emulation + + items = get # dict emulation + + def keys(self): + return map(lambda x: x.name, self.get()) + + def addCurve(self, channel, curve = None): + """Adds a curve of channel type 'channel' to the Ipo Block. 'channel' must be one of +the object properties listed in the Ipo Window. If 'curve' is not specified, +an empty curve is created, otherwise, the existing IpoCurve 'curve' is copied and +added to the IpoBlock 'self'. +In any case, the added curve is returned. +""" + if curve: + if curve.__class__.__name__ != "IpoCurve": + raise TypeError, "IpoCurve expected" + c = self._object.addCurve(channel, curve._object) + + ### RotIpo conversion hack + if channel in _RotIpoCurves: + print "addCurve, converting", curve.name + c.points = map(_convertBPoint, curve.bezierPoints) + else: + c.points = curve.bezierPoints + else: + c = self._object.addCurve(channel) + return IpoCurve(c) + + _getters = { 'curves' : get } + +class BezierPoint: + """BezierPoint object + + Attributes + + pt -- Coordinates of the Bezier point + + h1 -- Left handle coordinates + + h2 -- Right handle coordinates + + h1t -- Left handle type (see IpoCurve.addBezier(...) ) + + h2t -- Right handle type +""" + +BezierPoint = _Ipo.BezTriple # override + +class IpoCurve(shadow.shadowEx): + """Wrapper for Blender IpoCurve + + Attributes + + bezierPoints -- A list of BezierPoints (see class BezierPoint), + defining the curve shape +""" + + InterpolationTypes = _Ipo.InterpolationTypes + ExtrapolationTypes = _Ipo.ExtrapolationTypes + + def __init__(self, object): + self._object = object + self.__dict__['bezierPoints'] = self._object.points + + def __getitem__(self, k): + """Emulate a sequence of BezierPoints""" + print k, type(k) + return self.bezierPoints[k] + + def __repr__(self): + return "[IpoCurve %s]" % self.name + + def __len__(self): + return len(self.bezierPoints) + + def eval(self, time): + """Returns float value of curve 'self' evaluated at time 'time' which +must be a float.""" + return self._object.eval(time) + + def addBezier(self, p, leftType = 'Auto', left = None, rightType = None, right = None): + """Adds a Bezier triple to the IpoCurve. + +The following values are float tuples (x,y), denoting position of a control vertex: + +p -- The position of the Bezier point + +left -- The position of the leftmost handle + +right -- The position of the rightmost handle + +'leftType', 'rightType' must be one of: + +"Auto" -- automatic handle calculation. In this case, 'left' and 'right' don't need to be specified + +"Vect" -- automatic split handle calculation. 'left' and 'right' are disregarded. + +"Align" -- Handles are aligned automatically. In this case, 'right' does not need to be specified. + +"Free" -- Handles can be set freely - this requires both arguments 'left' and 'right'. + +""" + + b = _Ipo.BezTriple() + b.pt[0], b.pt[1] = (p[0], p[1]) + b.h1t = leftType + + if rightType: + b.h2t = rightType + else: + b.h2t = leftType + + if left: + b.h1[0], b.h1[1] = (left[0], left[1]) + + if right: + b.h2[0], b.h2[1] = (right[0], right[1]) + + self.__dict__['bezierPoints'].append(b) + return b + + def update(self, noconvert = 0): + # This is an ugly fix for the 'broken' storage of Rotation + # ipo values. The angles are stored in units of 10.0 degrees, + # which is totally inconsistent with anything I know :-) + # We can't (at the moment) change the internals, so we + # apply a conversion kludge.. + if self._object.name in _RotIpoCurves and not noconvert: + points = map(_convertBPoint, self.bezierPoints) + else: + points = self.bezierPoints + self._object.points = points + self._object.update() + + def getInterpolationType(self, ipotype): + "Returns the Interpolation type - see also IpoCurve.InterpolationTypes" + return self._object.getInterpolationType() + + def setInterpolationType(self, ipotype): + """Sets the interpolation type which must be one of IpoCurve.InterpolationTypes""" + try: + self._object.setInterpolationType(ipotype) + except: + raise TypeError, "must be one of %s" % self.InterpolationTypes.keys() + + def getExtrapolationType(self, ipotype): + "Returns the Extrapolation type - see also IpoCurve.ExtrapolationTypes" + return self._object.getExtrapolationType() + + def setExtrapolationType(self, ipotype): + """Sets the interpolation type which must be one of IpoCurve.ExtrapolationTypes""" + try: + self._object.setInterpolationType(ipotype) + except: + raise TypeError, "must be one of %s" % self.ExtrapolationTypes.keys() + + +def New(blocktype, name = None): + """Returns a new IPO block of type 'blocktype' which must be one of: +["Object", "Camera", "World", "Material"] +""" + if name: + i = _Ipo.New(blocktype, name) + else: + i = _Ipo.New(blocktype) + return IpoBlock(i) + +def Eval(ipocurve, time): # emulation code + """This function is just there for compatibility. +Use IpoCurve.eval(time) instead""" + return ipocurve.eval(time) + +def Recalc(ipocurve): # emulation code + """This function is just there for compatibility. Note that Ipos +assigned to rotation values will *not* get converted to the proper +unit of radians. +In the new style API, use IpoCurve.update() instead""" + return ipocurve.update(1) + +def get(name = None): + """If 'name' given, the Ipo 'name' is returned if existing, 'None' otherwise. +If no name is given, a list of all Ipos is returned""" + if name: + ipo = _Ipo.get(name) + if ipo: + return IpoBlock(ipo) + else: + return None + else: + return shadow._List(_Ipo.get(), IpoBlock) + +Get = get # emulation diff --git a/intern/python/modules/Blender/Lamp.py b/intern/python/modules/Blender/Lamp.py new file mode 100644 index 00000000000..ab7ed63592a --- /dev/null +++ b/intern/python/modules/Blender/Lamp.py @@ -0,0 +1,168 @@ +"""The Blender Lamp module + +This module provides control over **Lamp** objects in Blender. + +Example:: + + from Blender import Lamp + l = Lamp.New('Spot') + l.setMode('square', 'shadow') + ob = Object.New('Lamp') + ob.link(l) +""" + +import _Blender.Lamp as _Lamp +import shadow + +_validBufferSizes = [512, 768, 1024, 1536, 2560] + +def _setBufferSize(self, bufsize): + """Set the lamp's buffersize. This function makes sure that a valid +bufferSize value is set (unlike setting lamp.bufferSize directly)""" + if bufsize not in _validBufferSizes: + print """Buffer size should be one of: +%s +Setting to default 512""" % _validBufferSizes + bufsize = 512 + self._object.bufferSize = bufsize + +class Lamp(shadow.hasIPO, shadow.hasModes): + """Wrapper for Blender Lamp DataBlock + + Attributes + + mode -- Lamp mode value - see EditButtons. Do not access directly + See setMode() + + type -- Lamp type value - see EditButtons. No direct access, please. + See setType() + + col -- RGB vector (R, G, B) of lamp colour + + energy -- Intensity (float) + + dist -- clipping distance of a spot lamp or decay range + + spotSize -- float angle (in degrees) of spot cone + (between 0.0 and 180.0) + + spotBlend -- value defining the blurriness of the spot edge + + haloInt -- Halo intensity + + clipStart -- shadow buffer clipping start + + clipStart -- shadow buffer clipping end + + bias -- The bias value for the shadowbuffer routine + + softness -- The filter value for the shadow blurring + + samples -- Number of samples in shadow calculation - the + larger, the better + + bufferSize -- Size of the shadow buffer which should be one of: + [512, 768, 1024, 1536, 2560] + + haloStep -- Number of steps in halo calculation - the smaller, the + the better (and slower). A value of 0 disables shadow + halo calculation + """ + + _emulation = {'Energ' : "energy", + 'SpoSi' : "spotSize", + 'SpoBl' : "SpotBlend", + 'HaInt' : "haloInt", + 'Dist' : "dist", + 'Quad1' : "quad1", + 'Quad2' : "quad2", + } + + _setters = {'bufferSize' : _setBufferSize} + + t = _Lamp.Types + + Types = {'Lamp' : t.LOCAL, + 'Spot' : t.SPOT, + 'Sun' : t.SUN, + 'Hemi' : t.HEMI, + } + + t = _Lamp.Modes + + Modes = {'quad' : t.QUAD, + 'sphere' : t.SPHERE, + 'shadow' : t.SHAD, + 'halo' : t.HALO, + 'layer' : t.LAYER, + 'negative' : t.NEG, + 'onlyShadow' : t.ONLYSHADOW, + 'square' : t.SQUARE, + } + + del t + + def __repr__(self): + return "[Lamp \"%s\"]" % self.name + + def setType(self, name): + """Set the Lamp type of Lamp 'self'. 'name' must be a string of: + +* 'Lamp': A standard point light source + +* 'Spot': A spot light + +* 'Sun' : A unidirectional light source, very far away (like a Sun!) + +* 'Hemi': A diffuse hemispherical light source (daylight without sun)""" + + try: + self._object.type = self.Types[name] + except: + raise TypeError, "type must be one of %s" % self.Types.keys() + + def getType(self): + """Returns the lamp's type as string. See setType()""" + for k in self.Types.keys(): + if self.Types[k] == self.type: + return k + + def getMode(self): + """Returns the Lamp modes as a list of strings""" + return shadow._getModeBits(self.Modes, self._object.mode) + + def setMode(self, *args): + """Set the Lamp mode of Lamp 'self'. This function takes a variable number +of string arguments of the types listed in self.Modes. + + Example:: + + l = Lamp.New() + l.setMode('quad', 'shadow') +""" + print args + self._object.mode = shadow._setModeBits(self.Modes, args) + + def getBufferSize(self): + return self.bufferSize + +def New(type = "Lamp", name = "Lamp"): + """Returns a new Lamp datablock of type 'type' and optional name 'name' +""" + t = Lamp.Types[type] + rawlamp = _Lamp.New() + rawlamp.type = t + rawlamp.name = name + return Lamp(rawlamp) + + +def get(name = None): + """If 'name' given, the Lamp 'name' is returned if existing, 'None' otherwise. +If no name is given, a list of all Lamps is returned""" + + if name: + return Lamp(_Lamp.get(name)) + else: + return shadow._List(_Lamp.get(), Lamp) + +Types = _Lamp.Types diff --git a/intern/python/modules/Blender/Material.py b/intern/python/modules/Blender/Material.py new file mode 100644 index 00000000000..f24541f0f03 --- /dev/null +++ b/intern/python/modules/Blender/Material.py @@ -0,0 +1,251 @@ +"""The Blender Material module + + This module provides access to *Material* datablocks + + Example:: + + from Blender import Material, NMesh, Object, Scene + m = Material.New() # create free Material datablock + m.rgbCol = (1.0, 0.0, 0.3) # assign RGB values + mesh = NMesh.GetRaw() # get new mesh + mesh.addMaterial(m) # add material to mesh + object = Object.New('Mesh') # create new object + object.link(mesh) # link mesh data to object + Scene.getCurrent().link(ob) # link object to current scene +""" + +import _Blender.Material as _Material +import shadow +#import Blender.Curve as Curve + +# These are getters and setters needed for emulation + +def _getRGB(obj): + return (obj.R, obj.G, obj.B) + +def _getSpec(obj): + return (obj.specR, obj.specG, obj.specB) + +def _getMir(obj): + return (obj.mirR, obj.mirG, obj.mirB) + +def _setRGB(obj, rgb): + obj.R, obj.G, obj.B = rgb + +def _setSpec(obj, rgb): + obj.specR, obj.specG, obj.specB = rgb + +def _setMir(obj, rgb): + obj.mirR, obj.mirG, obj.mirB = rgb + + + +class Material(shadow.hasIPO, shadow.hasModes): + """Material DataBlock object + + See example in the Material module documentation on how to create + an instance of a Material object. + + Attributes + + The following attributes are colour vectors (r, g, b) + + rgbCol -- The color vector (R, G, B). + The RGB values can be accessed individually as .R, .G and .B + + specCol -- Specularity color vector (specR, specG, specG) + + mirCol -- Mirror color vector (mirR, mirG, mirB) + + The following are float values: + + alpha -- The transparency + + ref -- Reflectivity float value + + emit -- Emit intensity value + + amb -- Ambient intensity value + + spec -- specularity value + + specTransp -- Specular transpareny + + haloSize -- Halo size + + mode -- The material mode bit vector - see Material.ModeFlags + + hard -- The hardness value + +""" + + _emulation = {'Mode' : "mode", + 'Ref' : "ref", + 'HaSize' : "haloSize", + 'SpTra' : "specTransp", + 'Alpha' : "alpha", + 'Spec' : "spec", + 'Emit' : "emit", + 'Hard' : "hard", + 'Amb' : "amb", + } + + _getters = {'rgbCol' : _getRGB, + 'specCol' : _getSpec, + 'mirCol' : _getMir, + } + + _setters = {'rgbCol' : _setRGB, + 'specCol' : _setSpec, + 'mirCol' : _setMir, + } + + t = _Material.Modes + + Modes = {'traceable' : t.TRACEABLE, + 'shadow' : t.SHADOW, + 'shadeless' : t.SHADELESS, + 'wire' : t.WIRE, + 'vcolLight' : t.VCOL_LIGHT, + 'vcolPaint' : t.VCOL_PAINT, + 'zTransp' : t.ZTRANSP, + 'zInvert' : t.ZINVERT, + 'onlyShadow': t.ONLYSHADOW, + 'star' : t.STAR, + 'texFace' : t.TEXFACE, + 'noMist' : t.NOMIST, + } + + t = _Material.HaloModes + + HaloModes = { "rings" : t.RINGS, + "lines" : t.LINES, + "tex" : t.TEX, + "haloPuno": t.PUNO, + "shade" : t.SHADE, + "flare" : t.FLARE, + } + + + del t + + def setMode(self, *args): + """Set the mode of 'self'. This function takes a variable number +of string arguments of the types listed in self.Modes. + + Example:: + + m = Material.New() + m.setMode('shadow', 'wire') +""" + flags = 0 + try: + for a in args: + flags |= self.Modes[a] + except: + raise TypeError, "mode must be one of" % self.Modes.keys() + self._object.mode = flags + + def setHaloMode(self, *args): + """Sets the material to Halo mode. +This function takes a variable number of string arguments of the types +listed in self.HaloModes""" + flags = _Material.Modes.HALO + + try: + for a in args: + flags |= self.HaloModes[a] + except: + raise TypeError, "mode must be one of" % self.HaloModes.keys() + self._object.mode = flags + + +class ModeFlags: + """Readonly dictionary + +...containing Material mode bitvectors: + +|------------------------------------------| +| Name | Description | +|==========================================| +| TRACEABLE | visible for shadow lamps | +|------------------------------------------| +| SHADOW | cast shadow | +|------------------------------------------| +| SHADELESS | do not shade | +|------------------------------------------| +| WIRE | draw in wireframe | +|------------------------------------------| +| VCOL_LIGHT | use vertex colors | +| | with lighting | +|------------------------------------------| +| VCOL_PAINT | vertex colours | +|------------------------------------------| +| HALO | Halo material | +|------------------------------------------| +| ZTRANSP | Z transparency | +|------------------------------------------| +| ZINVERT | invert Z | +|------------------------------------------| +| ONLYSHADOW | only shadow, but | +| | don't render | +|------------------------------------------| +| STAR | ? | +|------------------------------------------| +| TEXFACE | textured faces | +|------------------------------------------| +| NOMIST | disable mist | +|------------------------------------------| + +These mode flags directly represent the buttons in the Material parameters +window (EditButtons) + +Example:: + + # be 'm' a material + from Blender.Material.Modes import * + m.mode |= (TRACEABLE + WIRE) # Set 'wire' and 'traceable' flagsd + m.mode &= ~SHADELESS # clear 'shadeless' flag +""" + + t = _Material.Modes + TRACEABLE = t.TRACEABLE + SHADOW = t.SHADOW + SHADELESS = t.SHADELESS + WIRE = t.WIRE + VCOL_LIGHT = t.VCOL_LIGHT + VCOL_PAINT = t.VCOL_PAINT + HALO = t.HALO + ZTRANSP = t.ZTRANSP + ZINVERT = t.ZINVERT + ONLYSHADOW = t.ONLYSHADOW + STAR = t.STAR + TEXFACE = t.TEXFACE + NOMIST = t.NOMIST + del t + +# override: +ModeFlags = _Material.Modes + +def get(name = None): + """If 'name' given, the Material 'name' is returned if existing, 'None' otherwise. +If no name is given, a list of all Materials is returned""" + if name: + return Material(_Material.get(name)) + else: + return shadow._List(_Material.get(), Material) + +Get = get # emulation + +def New(name = None): + """Creates a new, empty Material and returns it. + +Example:: + + from Blender import Material + mat = Material.New() +""" + mat = Material(_Material.New()) + if name: + mat.name = name + return mat diff --git a/intern/python/modules/Blender/Mesh.py b/intern/python/modules/Blender/Mesh.py new file mode 100644 index 00000000000..dd8103919f8 --- /dev/null +++ b/intern/python/modules/Blender/Mesh.py @@ -0,0 +1,250 @@ +"""The Blender Mesh module + + This module provides routines for more extensive mesh manipulation. + Later, this Mesh type will also allow interactive access (like in + EditMode). + In the Publisher, Ngons will also be supported (and converted to + triangles on mesh.update(). The following code demonstrates + creation of an Ngon. + + Example:: + + from Blender import Mesh, Object, Scene + + m = Mesh.New() # new empty mesh + vlist = [] + vlist.append(m.addVert((-0.0, -1.0, 0.0))) + vlist.append(m.addVert((1.0, 0.0, 0.0))) + vlist.append(m.addVert((1.0, 1.0, 0.0))) + vlist.append(m.addVert((0.0, 3.0, 0.0))) + vlist.append(m.addVert((-1.0, 2.0, 0.0))) + vlist.append(m.addVert((-3.0, 1.0, 0.0))) + vlist.append(m.addVert((-3.0, 3.0, 0.0))) + vlist.append(m.addVert((-4.0, 3.0, 0.0))) + vlist.append(m.addVert((-4.0, 0.0, 0.0))) + + f = m.addFace(vlist) + + # do some calculations: top project vertex coordinates to + # UV coordinates and normalize them to the square [0.0, 1.0]*[0.0, 1.0] + + uvlist = map(lambda x: (x.co[0], x.co[1]), vlist) + maxx = max(map(lambda x: x[0], uvlist)) + maxy = max(map(lambda x: x[1], uvlist)) + minx = min(map(lambda x: x[0], uvlist)) + miny = min(map(lambda x: x[1], uvlist)) + + len = max((maxx - minx), (maxy - miny)) + offx = -minx / len + offy = -miny / len + + f.uv = map(lambda x: (x[0]/len + offx, x[1]/len + offy), uvlist) # assign UV coordinates by 'top' projection + + m.update() # update and triangulate mesh + + ob = Object.New('Mesh') # create new Object + ob.link(m) # link mesh data + sc = Scene.getCurrent() # get current Scene + sc.link(ob) # link Object to scene +""" + +from Blender.Types import NMFaceType +import Blender.Material as Material + +from _Blender import NMesh as _NMesh + +FACEFLAGS = _NMesh.Const +DEFAULTFLAGS = FACEFLAGS.LIGHT + FACEFLAGS.DYNAMIC + +import shadow + +def makeFace(f): + face = _NMesh.Face() + for v in f: + face.v.append(v) + face.uv.append((v.uvco[0], v.uvco[1])) + return face + +def toTriangles(ngon): + from utils import tesselation + # This should be a Publisher only feature...once the tesselation + # is improved. The GLU tesselator of Mesa < 4.0 is crappy... + if len(ngon.uv) == len(ngon.v): + i = 0 + for v in ngon.v: + v.uvco = ngon.uv[i] + i += 1 + + return tesselation.NgonAsTriangles(ngon, makeFace) # return triangles + +def Color(r, g, b, a = 1.0): + return _NMesh.Col(255 * r, 255 * g, 255 * b, 255 * a) + +class Vert: #shadow NMVert class for the tesselator + """Vertex wrapper class +This class emulates a float coordinate vector triple +""" + def __init__(self): + self.vert = None + self.uv = [] + def __len__(self): + return 3 + def __setitem__(self, i, val): + self.vert[i] = val + def __getitem__(self, i): + return self.vert.co[i] + +class Face: + """Face wrapper class +This class emulates a list of vertex references +""" + def __init__(self, vlist): + self.v= vlist + self.uv = [] + + def __len__(self): + return len(self.v) + + def __setitem__(self, i, val): + self.v[i] = val + + def __getitem__(self, i): + return self.v[i] + +# override: + +Vert = _NMesh.Vert +Face = _NMesh.Face + +class rawMesh: + """Wrapper for raw Mesh data""" + def __init__(self, object = None): + if object: + self._object = object + else: + self._object = _NMesh.GetRaw() + + self.flags = DEFAULTFLAGS + self.smooth = 0 + self.recalc_normals = 1 + self.faces = self._object.faces[:] + + def __getattr__(self, name): + if name == 'vertices': + return self._object.verts + elif name == 'has_col': + return self._object.hasVertexColours() + elif name == 'has_uv': + return self._object.hasFaceUV() + else: + return getattr(self._object, name) + + def __repr__(self): + return "Mesh: %d faces, %d vertices" % (len(self.faces), len(self.verts)) + + def hasFaceUV(self, true = None): + """Sets the per-face UV texture flag, if 'true' specified (either + 0 or 1). Returns the texture flag in any case.""" + if true == None: + return self._object.hasFaceUV() + return self._object.hasFaceUV(true) + + def hasVertexUV(self, true = None): + """Sets the per-vertex UV texture flag, if 'true' specified (either + 0 or 1). Returns the texture flag in any case.""" + if true == None: + return self._object.hasVertexUV() + return self._object.hasVertexUV(true) + + def hasVertexColours(self, true = None): + """Sets the per-face UV texture flag, if 'true' specified (either + 0 or 1). Returns the texture flag in any case.""" + if true == None: + return self._object.hasVertexColours() + return self._object.hasVertexColours(true) + + def addVert(self, v): + """Adds a vertex to the mesh and returns a reference to it. 'v' can +be a float triple or any data type emulating a sequence, containing the +coordinates of the vertex. Note that the returned value references an +*owned* vertex""" + vert = _NMesh.Vert(v[0], v[1], v[2]) + self._object.verts.append(vert) + return vert + + def addFace(self, vlist, flags = None, makedefaultUV = 0): + """Adds a face to the mesh and returns a reference to it. 'vlist' +must be a list of vertex references returned by addVert(). +Note that the returned value references an *owned* face""" + if type(vlist) == NMFaceType: + face = vlist + else: + n = len(vlist) + face = _NMesh.Face(vlist) + if makedefaultUV: + face.uv = defaultUV[:n] + + self.faces.append(face) + # turn on default flags: + if not flags: + face.mode = self.flags + else: + face.mode = flags + return face + + def update(self): + """Updates the mesh datablock in Blender""" + o = self._object + o = self._object + o.faces = [] + smooth = self.smooth + for f in self.faces: + if len(f) > 4: #it's a NGON + faces = toTriangles(f) + for nf in faces: + nf.smooth = smooth + o.faces.append(nf) + else: + o.faces.append(f) + o.update() + + def link(self, material): + """Link material 'material' with the mesh. Note that a mesh can +currently have up to 16 materials, which are referenced by +Face().materialIndex""" + mats = self._object.materials + if material in mats: + print "material already assigned to mesh" + return + mats.append(material._object) + + def unlink(self, material): + """Unlink (remove) material 'material' from the mesh. Note +that the material indices per face need to be updated.""" + self._object.materials.remove(material._object) + + def setMaterials(self, materials = []): + """Sets materials. 'materials' must be a list of valid material objects +Note that a mesh can currently have up to 16 materials, which are referenced +by Face().materialIndex""" + + self._object.materials = (map(lambda x: x._object, materials)) + + def getMaterials(self, materials = []): + """Returns materials assigned to the mesh""" + return shadow._List(self._object.materials, Material.Material) + +def New(): + return rawMesh() + +def get(name = None): + """If 'name' given, the Mesh 'name' is returned if existing, 'None' otherwise.""" + if name: + ob = _NMesh.GetRaw(name) + if ob: + return rawMesh(ob) + else: + return None + else: + raise SystemError, "get() for Meshes is not yet supported" + diff --git a/intern/python/modules/Blender/NMesh.py b/intern/python/modules/Blender/NMesh.py new file mode 100644 index 00000000000..3e6c60bab21 --- /dev/null +++ b/intern/python/modules/Blender/NMesh.py @@ -0,0 +1,192 @@ +"""The Blender NMesh module + + This module provides access to the raw **Mesh** data block. + + Examples will not be given, as the life time of this module will be + most probably limited. Use the 'Mesh' module instead. +""" + +import _Blender.NMesh as _NMesh +import shadow + +class Mesh(shadow.shadow): + """The NMesh object + + This contains a copy of the raw mesh object data. + + Attributes + + verts -- A list of vertices of type 'Vert' + + faces -- List of faces of type 'Face' +""" + def update(self): + """updates the mesh object in Blender with the modified mesh data""" + self._object.update() + +class Vert: + """Vertex object + + Attributes + + co -- The vertex coordinates (x, y, z) + + no -- Vertex normal vector (nx, ny, nz) + + uvco -- Vertex texture ("sticky") coordinates + + index -- The vertex index, if owned by a mesh +""" + +class Face: + """Face object + + Attributes + + mode -- Display mode, see NMesh.FaceModes + + flag -- flag bit vector, specifying selection flags. + see NMesh.FaceFlags + + transp -- transparency mode bit vector; see NMesh.FaceTranspModes + + v -- List of Face vertices + + col -- List of Vertex colours + + materialIndex -- Material index (referring to one of the Materials in + the Meshes material list, see Mesh documentation + + smooth -- Flag whether smooth normals should be calculated (1 = yes) + + image -- Reference to texture image object + + uv -- A list of per-face UV coordinates: + [(u0, v0), (u1, v1), (u2, v2), .. ] +""" + +class Col: + """Colour object + + See NMesh module documentation for an example. + + Attributes + + r, g, b, a -- The RGBA components of the colour + A component must lie in the range of [0, 255] +""" + + +class FaceModes: + """Face mode bit flags + + BILLBOARD -- always orient after camera + + DYNAMIC -- respond to collisions + + INVISIBLE -- invisible face + + HALO -- halo face, always point to camera + + LIGHT -- dynamic lighting + + OBCOL -- use object colour instead of vertex colours + + SHADOW -- shadow type + + SHAREDCOL -- shared vertex colors (per vertex) + + TEX -- has texture image + + TILES -- uses tiled image + + TWOSIDE -- twosided face +""" + t = _NMesh.Const + BILLBOARD = t.BILLBOARD + DYNAMIC = t.DYNAMIC + INVISIBLE = t.INVISIBLE + HALO = t.HALO + LIGHT = t.LIGHT + OBCOL = t.OBCOL + SHADOW = t.SHADOW + SHAREDCOL = t.SHAREDCOL + TEX = t.TEX + TILES = t.TILES + TWOSIDE = t.TWOSIDE + del t + + +class FaceTranspModes: + """Readonly dictionary + +...containing Face transparency draw modes. They are of type 'enum', i.e. +can not be combined like a bit vector. + + SOLID -- draw solid + + ADD -- add to background(halo) + + ALPHA -- draw with transparency + + SUB -- subtract from background +""" + t = _NMesh.Const + SOLID = t.SOLID + ADD = t.ADD + ALPHA = t.ALPHA + SUB = t.SUB + del t + +class FaceFlags: + """Readonly dictionary + +...containing Face flags bitvectors: + + SELECT -- selected + + HIDE -- hidden + + ACTIVE -- the active face +""" + t = _NMesh.Const + SELECT = t.SELECT + HIDE = t.HIDE + ACTIVE = t.ACTIVE + del t + + +def New(name = None): + """Creates a new NMesh mesh object and returns it""" + pass + +def GetRaw(name = None): + """If 'name' specified, the Mesh object with 'name' is returned, 'None' +if not existant. Otherwise, a new empty Mesh is initialized and returned.""" + pass + +def PutRaw(mesh, name = "Mesh"): + """Creates a Mesh Object instance in Blender, i.e. a Mesh Object in the +current Scene and returns a reference to it. If 'name' specified, the Mesh +'name' is overwritten. In this case, no Object reference is returned.""" + pass + +def GetRawFromObject(name): + """This returns the mesh as used by the object, which +means it contains all deformations and modifications.""" + pass + +# override all these functions again, because we only used them for +# documentation -- NMesh will be no longer supported in future + +New = _NMesh.New +GetRaw = _NMesh.GetRaw +PutRaw = _NMesh.PutRaw +GetRawFromObject = _NMesh.GetRawFromObject +Const = _NMesh.Const +Vert = _NMesh.Vert +Face = _NMesh.Face +Col = _NMesh.Col + +def NMesh(data): + return data diff --git a/intern/python/modules/Blender/Object.py b/intern/python/modules/Blender/Object.py new file mode 100644 index 00000000000..7fefedf4725 --- /dev/null +++ b/intern/python/modules/Blender/Object.py @@ -0,0 +1,391 @@ +## +## Blender API mid level layer 01/2002 // strubi@blender.nl +## +## $Id$ +## + +"""The Blender Object module + + This module provides **Object** manipulation routines. + + Example:: + + from Blender import Object + ob = Object.get('Plane') + actobj = Object.getSelected()[0] # get active Object + print actobj.loc # print position + ob.makeParent([actobj]) # make ob the parent of actobj +""" + +import _Blender.Object as _Object + +import shadow +reload(shadow) # XXX + +class _C: + pass + +InstanceType = type(_C()) +del _C # don't export this + + +def _Empty_nodata(obj): + return None + +class Object(shadow.hasIPO): + """Blender Object + + A Blender Object (note the capital O) is the instance of a 3D structure, + or rather, the Object that is (normally) visible in your Blender Scene. + + An instance of a Blender Object object is created by:: + + from Blender import Object + ob = Object.New(type) # type must be a valid type string, + # see Object.Types + + ... + + Attributes + + Note that it is in general not recommended to access the Object's + attributes directly. Please rather use the get-/set- functions instead. + + loc -- position vector (LocX, LocY, LocZ) + + dloc -- delta position vector (dLocX, dLocY, dLocZ) + + rot -- euler rotation vector (RotX, RotY, RotZ). + Warning: this may change in future. + + drot -- delta rotation euler vector (dRotX, dRotY, dRotZ) + Warning: this may change in future. + + size -- scale vector (SizeX, SizeY, SizeZ) + + dsize -- delta scale vector (dSizeX, dSizeY, dSizeZ) + + layer -- layer bitvector (20 bit), defining what layers the object is + visible in + + + The following items are listed here only for compatibility to older + scripts and are READ-ONLY! **USE the get- functions instead!** + + data -- reference to the data object (e.g. Mesh, Camera, Lamp, etc.) + + parent -- reference to the parent object, if existing, 'None' otherwise. + + track -- reference to the tracked object, if existing, 'None' otherwise. + + This bit mask can be read and written: + + colbits -- the Material usage mask. A set bit #n means: + The Material #n in the *Object's* material list is used. + Otherwise, the Material #n of the Objects *Data* material list + is displayed. +""" + + def __init__(self, object = None): + """Returns an empty shadow Object""" + self._object = object + + def __repr__(self): + return "[Object \"%s\"]" % self.name + + def link(self, data): + """Links Object 'self' with data 'data'. The data type must match +the Object's type, so you cannot link a Lamp to a mesh type Object. +'data' can also be an Ipo object (IpoBlock) +""" + from _Blender import Types + # special case for NMesh: + if type(data) == Types.NMeshType: + return self._object.link(data) + elif type(data) == InstanceType: + if data.__class__.__name__ == "rawMesh": + data.update() # update mesh + elif data.__class__.__name__ == "IpoBlock": + self.setIpo(data) + + return shadow._link(self, data) + + def copy(self): + """Returns a copy of 'self'. +This is a true, linked copy, i.e. the copy shares the same data as the +original. The returned object is *free*, meaning, not linked to any scene.""" + return Object(self._object.copy()) + + #def clone(self): + #"""Makes a clone of the specified object in the current scene and +##returns its reference""" + #return Object(self._object.clone()) + + def shareFrom(self, object): + """Link data of 'self' with data of 'object'. This works only if +'object' has the same type as 'self'.""" + return Object(self._object.shareFrom(object._object)) + + def getMatrix(self): + """Returns the object matrix""" + return self._object.getMatrix() + + def getInverseMatrix(self): + """Returns the object's inverse matrix""" + return self._object.getInverseMatrix() + + def getData(self): + "Returns the Datablock object containing the object's data, e.g. Mesh" + t = self._object.getType() + data = self._object.data + try: + return self._dataWrappers[t][1](data) + except: + raise TypeError, "getData() not yet supported for this object type" + + def getDeformData(self): + """Returns the Datablock object containing the object's deformed data. +Currently, this is only supported for a Mesh""" + import _Blender.NMesh as _NMesh + t = self._object.getType() + if t == self.Types['Mesh']: + data = _NMesh.GetRawFromObject(self.name) + return self._dataWrappers[t][1](data) + else: + raise TypeError, "getDeformData() not yet supported for this object type" + + def getType(self): + "Returns type string of Object, which is one of Object.Types.keys()" + t = self._object.getType() + try: + return self._dataWrappers[t][0] + except: + return "<unsupported>" + + def getParent(self): + "Returns object's parent object" + if self._object.parent: + return Object(self._object.parent) + return None + + def getTracked(self): + "Returns object's tracked object" + if self._object.track: + return Object(self._object.track) + return None + +# FUTURE FEATURE :-) : +# def getLocation(): +# """Returns the object's location (x, y, z). +#By default, the location vector is always relative to the object's parent. +#If the location of another coordinate system is wanted, specify 'origin' by +#the object whose coordinate system the location should be calculated in. + +#If world coordinates are wanted, set 'relative' = "World".""" + + def getLocation(self, relative = None): + """Returns the object's location (x, y, z). For the moment, +'relative' has no effect.""" + l = self._object.loc + return (l[0], l[1], l[2]) + + def setLocation(self, location, relative = None): + """Sets the object's location. 'location' must be a vector triple. +See 'getLocation()' about relative coordinate systems.""" + l = self._object.loc # make sure this is copied + l[0], l[1], l[2] = location + + def getDeltaLocation(self): + """Returns the object's delta location (x, y, z)""" + l = self._object.dloc + return (l[0], l[1], l[2]) + + def setDeltaLocation(self, delta_location): + """Sets the object's delta location which must be a vector triple""" + l = self._object.dloc # make sure this is copied + l[0], l[1], l[2] = delta_location + + def getEuler(self): + """Returns the object's rotation as Euler rotation vector +(rotX, rotY, rotZ)""" + e = self._object.rot + return (e[0], e[1], e[2]) + + def setEuler(self, euler = (0.0, 0.0, 0.0)): + """Sets the object's rotation according to the specified Euler angles. +'euler' must be a vector triple""" + e = self._object.rot + e[0], e[1], e[2] = euler + + def makeParent(self, objlist, mode = 0, fast = 0): + """Makes 'self' the parent of the objects in 'objlist' which must be +a list of valid Objects. +If specified: + + mode -- 0: make parent with inverse + + 1: without inverse + + fast -- 0: update scene hierarchy automatically + + 1: don't update scene hierarchy (faster). In this case, you + must explicitely update the Scene hierarchy, see: + 'Blender.Scene.getCurrent().update()'""" + list = map(lambda x: x._object, objlist) + return Object(self._object.makeParent(list, mode, fast)) + + def clrParent(self, mode = 0, fast = 0): + """Clears parent object. +If specified: + + mode -- 2: keep object transform + + fast > 0 -- don't update scene hierarchy (faster)""" + return Object(self._object.clrParent(mode, fast)) + + def getMaterials(self): + """Returns list of materials assigned to the object""" + from Blender import Material + return shadow._List(self._object.getMaterials(), Material.Material) + + def setMaterials(self, materials = []): + """Sets materials. 'materials' must be a list of valid material objects""" + o = self._object + old_mask = o.colbits + o.colbits = -1 # set material->object linking + o.setMaterials(map(lambda x: x._object, materials)) + o.colbits = old_mask + + def materialUsage(self, flag): + """Determines the way the material is used and returns status. + +'flag' = 'Data' : Materials assigned to the object's data are shown. (default) + +'flag' = 'Object' : Materials assigned to the object are shown. + +The second case is desired when the object's data wants to be shared among +objects, but not the Materials assigned to their data. See also 'colbits' +attribute for more (and no future compatible) control.""" + if flag == "Object": + self._object.colbits = -1 + elif flag == "Data": + self._object.colbits = 0 + return self._object.colbits + else: + raise TypeError, "unknown mode %s" % flag + + _getters = {} + + from Blender import Mesh, Camera, Lamp + + t = _Object.Types + Types = {"Camera" : t.CAMERA, + "Empty" : t.EMPTY, + "Lamp" : t.LAMP, + "Mesh" : t.MESH, + } + + # create lookup table for data wrappers + _dataWrappers = range(max(Types.values()) + 1) + _dataWrappers[t.MESH] = ("Mesh", Mesh.rawMesh) + _dataWrappers[t.CAMERA] = ("Camera", Camera.Camera) + _dataWrappers[t.LAMP] = ("Lamp", Lamp.Lamp) + _dataWrappers[t.EMPTY] = ("Empty", _Empty_nodata) + + t = _Object.DrawTypes + DrawTypes = {"Bounds" : t.BOUNDBOX, + "Wire" : t.WIRE, + "Solid" : t.SOLID, + "Shaded" : t.SHADED, + } + + t = _Object.DrawModes + DrawModes = {"axis" : t.AXIS, + "boundbox" : t.BOUNDBOX, + "texspace" : t.TEXSPACE, + "name" : t.NAME, + } + + + del t + del Mesh, Camera, Lamp + + def getDrawMode(self): + """Returns the Object draw modes as a list of strings""" + return shadow._getModeBits(self.DrawModes, self._object.drawMode) + + def setDrawMode(self, *args): + """Sets the Object's drawing modes as a list of strings""" + self._object.drawMode = shadow._setModeBits(self.DrawModes, args) + + def getDrawType(self): + """Returns the Object draw type""" + for k in self.DrawTypes.keys(): + if self.DrawTypes[k] == self.drawType: + return k + + def setDrawType(self, name): + """Sets the Object draw type. 'name' must be one of: + +* 'Bounds' : Draw bounding box only + +* 'Wire' : Draw in wireframe mode + +* 'Solid' : Draw solid + +* 'Shaded' : Draw solid, shaded and textures +""" + try: + self._object.drawType = self.DrawTypes[name] + except: + raise TypeError, "type must be one of %s" % self.DrawTypes.keys() + + +################## +# MODULE FUNCTIONS + +def New(objtype, name = None): + """Creates a new, empty object and returns it. +'objtype' is a string and must be one of:: + + Camera + Empty + Mesh + Lamp + +More object types will be supported in future. + +Example:: + + ob = Object.New('Camera') +""" + + if type(objtype) == type(0): + obj = Object(_Object.New(objtype)) # emulate old syntax + else: + t = Object.Types[objtype] + obj = Object(_Object.New(t)) + return obj + +def get(name = None): + """If 'name' given, the Object 'name' is returned if existing, 'None' otherwise. +If no name is given, a list of all Objects is returned""" + if name: + ob = _Object.get(name) + if ob: + return Object(ob) + else: + return None + else: + return shadow._List(_Object.get(), Object) + +Get = get # emulation + +def getSelected(): + """Returns a list of selected Objects in the active layer(s). +The active object is the first in the list, if visible""" + return shadow._List(_Object.getSelected(), Object) + +GetSelected = getSelected # emulation + +Types = _Object.Types # for compatibility diff --git a/intern/python/modules/Blender/Scene.py b/intern/python/modules/Blender/Scene.py new file mode 100644 index 00000000000..a6deaeb5a46 --- /dev/null +++ b/intern/python/modules/Blender/Scene.py @@ -0,0 +1,143 @@ +"""The Blender Scene module + + This module provides *Scene* manipulation routines. + + Example:: + + from Blender import Scene + + curscene = Scene.getCurrent() + ob = curscene.getChildren()[0] # first object + newscene = Scene.New('testscene') + cam = curscene.getCurrentCamera() # get current camera object + newscene.link(ob) # link 'ob' to Scene + newscene.link(cam) + newscene.makeCurrent() # make current Scene +""" +import _Blender.Scene as _Scene + +from Object import Object +import shadow + +class Scene(shadow.shadowEx): + """Wrapper for Scene DataBlock +""" + def link(self, object): + """Links Object 'object' into Scene 'self'.""" + # This is a strange workaround; Python does not release + # 'self' (and thus self._object) when an exception in the C API occurs. + # Therefore, we catch that exception and do it ourselves.. + # Maybe Python 2.2 is able to resolve this reference dependency ? + try: + return self._object.link(object._object) + except: + del self._object + raise + + def unlink(self, object): + """Unlinks (deletes) Object 'object' from Scene.""" + ret = self._object.unlink(object._object) + return ret + + def copy(self, duplicate_objects = 1): + """Returns a copy of itself. + +The optional argument defines, how the Scene's children objects are +duplicated:: + + 0: Link Objects + 1: Link Object data + 2: Full Copy""" + return Scene(self._object.copy(duplicate_objects)) + + def update(self): + """Updates scene 'self'. + This function explicitely resorts the base list of a newly created object + hierarchy.""" + return self._object.update() + + def makeCurrent(self): + """Makes 'self' the current Scene""" + return self._object.makeCurrent() + + def frameSettings(self, start = None, end = None, current = None): + """Sets or retrieves the Scene's frame settings. +If the frame arguments are specified, they are set. +A tuple (start, end, current) is returned in any case.""" + if start and end and current: + return self._object.frameSettings(start, end, current) + else: + return self._object.frameSettings() + + def currentFrame(self, frame = None): + """If 'frame' is given, the current frame is set and returned in any case""" + if frame: + return self._object.frameSettings(-1, -1, frame) + return self._object.frameSettings()[2] + + def startFrame(self, frame = None): + """If 'frame' is given, the start frame is set and returned in any case""" + if frame: + return self._object.frameSettings(frame, -1, -1) + return self._object.frameSettings()[0] + + def endFrame(self, frame = None): + """If 'frame' is given, the end frame is set and returned in any case""" + if frame: + return self._object.frameSettings(-1, frame, -1) + return self._object.frameSettings()[1] + + def getChildren(self): + """Returns a list of the Scene's children Objects""" + return shadow._List(self._object.getChildren(), Object) + + def getCurrentCamera(self): + """Returns current active camera Object""" + cam = self._object.getCurrentCamera() + if cam: + return Object(cam) + + def setCurrentCamera(self, object): + """Sets the current active camera Object 'object'""" + return self._object.setCurrentCamera(object._object) + + def getRenderdir(self): + """Returns directory where rendered images are saved to""" + return self._object.getRenderdir(self._object) + + def getBackbufdir(self): + """Returns the Backbuffer images location""" + return self._object.getBackbufdir(self._object) + +# Module methods + +def New(name = 'Scene'): + """Creates and returns new Scene with (optionally given) name""" + return Scene(_Scene.New(name)) + +def get(name = None): + """Returns a Scene object with name 'name' if given, None if not existing, +or a list of all Scenes otherwise.""" + if name: + ob = _Scene.get(name) + if ob: + return Scene(ob) + else: + return None + else: + return shadow._List(_Scene.get(), Scene) + +Get = get # emulation + +def getCurrent(): + """Returns the currently active Scene""" + sc = Scene(_Scene.getCurrent()) + return sc + +def unlink(scene): + """Removes the Scene 'scene' from Blender""" + if scene._object.name == _Scene.getCurrent().name: + raise SystemError, "current Scene can not be removed!" + for ob in scene.getChildren(): + scene.unlink(ob) + return _Scene.unlink(scene._object) diff --git a/intern/python/modules/Blender/Text.py b/intern/python/modules/Blender/Text.py new file mode 100644 index 00000000000..0d5f615f190 --- /dev/null +++ b/intern/python/modules/Blender/Text.py @@ -0,0 +1,57 @@ +"""The Blender Text module + + This module lets you manipulate the Text buffers inside Blender. + Text objects are currently owned by the Text editor in Blender. + + Example:: + + from Blender import Text + text = Text.New('Text') # create new text buffer + text.write('hello') # write string + Text.unlink(text) # delete +""" + +import _Blender.Text as _Text + +class Text: + """Wrapper for Text DataBlock""" + + def clear(self): + """Clears the Text objects text buffer""" + pass + + def write(self, string): + """Appends 'string' to the text buffer""" + pass + + def asLines(self): + """Returns the text buffer as a list of lines (strings)""" + pass + + def set(self, attr, val): + """Set the Text attribute of name 'name' to value 'val'. + +Currently supported:: + + follow_cursor : 1: Text output follows the cursor""" + +# Module methods + +def New(name = None): + """Creates new empty Text with (optionally given) name and returns it""" + pass + +def get(name = None): + """Returns a Text object with name 'name' if given, 'None' if not existing, +or a list of all Text objects in Blender otherwise.""" + pass + +def unlink(text): + """Removes the Text 'text' from the Blender text window""" + pass + + +# override: +New = _Text.New +get = _Text.get +unlink = _Text.unlink diff --git a/intern/python/modules/Blender/Types.py b/intern/python/modules/Blender/Types.py new file mode 100644 index 00000000000..d49d9c35407 --- /dev/null +++ b/intern/python/modules/Blender/Types.py @@ -0,0 +1 @@ +from _Blender.Types import * diff --git a/intern/python/modules/Blender/Window.py b/intern/python/modules/Blender/Window.py new file mode 100644 index 00000000000..e51ab894dfa --- /dev/null +++ b/intern/python/modules/Blender/Window.py @@ -0,0 +1,65 @@ +"""The Blender Window module + +This module currently only supports redrawing commands of windows. +Later on, it will allow screen manipulations and access to Window +properties""" + +import _Blender.Window as _Window + +t = _Window.Types +Const = t # emulation + +Types = { 'View' : t.VIEW3D, + 'Ipo' : t.IPO, + 'Oops' : t.OOPS, + 'Button' : t.BUTS, + 'File' : t.FILE, + 'Image' : t.IMAGE, + 'Text' : t.TEXT, + 'Action' : t.ACTION, + } + +del t + +def Redraw(t= 'View'): + """Redraws all windows of the type 't' which must be one of: + +* "View" - The 3D view + +* "Ipo" - The Ipo Window + +* "Oops" - The OOPS (scenegraph) window + +* "Button" - The Button Window + +* "File" - The File Window + +* "Image" - The Image Window (UV editor) + +* "Text" - The Text editor + +* "Action" - The Action Window""" + + if type(t) == type(1): + return _Window.Redraw(t) + try: + _Window.Redraw(Types[t]) + except: + raise TypeError, "type must be one of %s" % Types.keys() + +def RedrawAll(): + """Redraws the whole screen""" + _Window.RedrawAll() + +def drawProgressBar(val, text): + """Draws a progress bar behind the Blender version information. +'val' is a float value <= 1.0, 'text' contains info about what is currently +being done. +This function must be called with 'val' = 0.0 at start and end of the executed +(and probably time consuming) action. +The user may cancel the progress with the 'Esc' key, in this case, 0 is returned, +1 else.""" + return _Window.draw_progressbar(val, text) + +draw_progressbar = _Window.draw_progressbar # emulation +QRedrawAll = _Window.QRedrawAll diff --git a/intern/python/modules/Blender/World.py b/intern/python/modules/Blender/World.py new file mode 100644 index 00000000000..e0c42d33f16 --- /dev/null +++ b/intern/python/modules/Blender/World.py @@ -0,0 +1,157 @@ +import _Blender.World as _World + +import shadow + +def _getAmbCol(obj): + return obj.ambR, obj.ambG, obj.ambB + +def _setAmbCol(obj, rgb): + obj.ambR, obj.ambG, obj.ambB = rgb + +def _getZenCol(obj): + return obj.zenR, obj.zenG, obj.zenB + +def _setZenCol(obj, rgb): + obj.zenR, obj.zenG, obj.zenB = rgb + +def _getHorCol(obj): + return obj.horR, obj.horG, obj.horB + +def _setHorCol(obj, rgb): + obj.horR, obj.horG, obj.horB = rgb + +def _setMist(obj, mist): + obj.mistStart = mist.start + obj.mistDepth = mist.depth + obj.mistHeight = mist.height + obj.mistType = mist.type + +def _getMist(obj): + mist = Mist() + mist.start = obj.mistStart + mist.depth = obj.mistDepth + mist.height = obj.mistHeight + mist.type = obj.mistType + return mist + +class World(shadow.hasIPO, shadow.hasModes): + """Wrapper for Blender World DataBlock + + Attributes + + horCol -- horizon colour triple '(r, g, b)' where r, g, b must lie + in the range of [0.0, 1.0] + + zenCol -- zenith colour triple + + ambCol -- ambient colour triple + + exposure -- exposure value + + mist -- mist structure, see class Mist + + starDensity -- star density (the higher, the more stars) + + starMinDist -- the minimum distance to the camera + + starSize -- size of the stars + + starColNoise -- star colour noise + + gravity -- The gravity constant (9.81 for earth gravity) +""" + + SkyTypes = {'blend' : 1, + 'real' : 2, + 'paper' : 4, + } + + Modes = {'mist' : 1, + 'stars' : 2, + } + + _emulation = {'Expos' : "exposure", + 'HorR' : "horR", + 'HorG' : "horG", + 'HorB' : "horB", + 'ZenR' : "zenR", + 'ZenG' : "zenG", + 'ZenB' : "zenB", + 'StarDi' : "starDensity", + 'StarSi' : "starSize", + 'MisSta' : "mistStart", + 'MisDi' : "mistDepth", + 'MisHi' : "mistHeight", + } + + _setters = {'horCol' : _getHorCol, + 'zenCol' : _getZenCol, + 'ambCol' : _getAmbCol, + 'mist' : _getMist, + } + + _setters = {'horCol' : _setHorCol, + 'zenCol' : _setZenCol, + 'ambCol' : _setAmbCol, + 'mist' : _setMist, + } + + def getSkyType(self): + """Returns a list of the set Sky properties, see setSkyType()""" + list = [] + for k in self.SkyTypes.keys(): + i = self.SkyTypes[k] + if self._object.skyType & i: + list.append(k) + return list + + def setSkyType(self, *args): + """Set the sky type. This function takes a variable number +of string arguments of ['blend', 'real', 'paper']""" + flags = 0 + try: + for a in args: + flags |= self.SkyTypes[a] + except: + raise TypeError, "mode must be one of" % self.SkyTypes.keys() + self._object.skyType = flags + + +class Mist: + """Mist structure + + Attributes + + start -- start of the mist + + depth -- depth of the "mist wall" + + height -- height of the mist layer +""" + + Types = { 'quadratic' : 0, + 'linear' : 1, + 'sqrt' : 2, + } + + def __init__(self): + self.start = 0.0 + self.depth = 0.0 + self.height = 0.0 + self.type = 0 + + def setType(self, name): + """Set the Mist type (one of ['quadratic', 'linear', 'sqrt'])""" + try: + t = self.Types[name] + else: + raise TypeError, "type must be one of %s" % self.Types.keys() + self.type = t + + def getType(self): + """Returns the Mist type as string. See setType()""" + for k in self.Types.keys(): + if self.Types[k] == self.type: + return k + + diff --git a/intern/python/modules/Blender/__init__.py b/intern/python/modules/Blender/__init__.py new file mode 100644 index 00000000000..7356d9ddf9f --- /dev/null +++ b/intern/python/modules/Blender/__init__.py @@ -0,0 +1,23 @@ +# +# The Blender main module wrapper +# (c) 06/2001, NaN // strubi@blender.nl + +__all__ = ["Object", "Image", "NMesh", "Window", "Mesh", "Tools", "sys", + "Lamp", "Scene", "Draw", "Camera", "Material", "Types", "Ipo", + "BGL"] + +import _Blender + +Get = _Blender.Get +Redraw = _Blender.Redraw +link = _Blender.link +bylink = _Blender.bylink + +import Object, Image, Mesh, Window, Tools, sys, Lamp, Scene, Draw, Camera +import Material, NMesh, BGL, Types, Ipo, Text + +deg = lambda x: 0.0174532925199 * x # conversion from degrees to radians + +import __builtin__ +__builtin__.deg = deg + diff --git a/intern/python/modules/Blender/shadow.py b/intern/python/modules/Blender/shadow.py new file mode 100644 index 00000000000..15c5de88f66 --- /dev/null +++ b/intern/python/modules/Blender/shadow.py @@ -0,0 +1,195 @@ +# +# Blender mid level modules +# author: strubi@blender.nl +# +# + +"""Shadow class module + + These classes shadow the internal Blender objects + + There is no need for you to use the shadow module really - it is + just there for documentation. Blender object classes with a common + subset of function members derive from these sub classes. +""" + + +def _List(list, Wrapper): + """This function returns list of wrappers, taking a list of raw objects +and the wrapper method""" + return map(Wrapper, list) + +def _getModeBits(dict, attr): + list = [] + for k in dict.keys(): + i = dict[k] + if attr & i: + list.append(k) + return list + +def _setModeBits(dict, args): + flags = 0 + try: + for a in args: + flags |= dict[a] + except: + raise TypeError, "mode must be one of %s" % dict.keys() + return flags + + +def _link(self, data): + """Links Object 'self' with data 'data'. The data type must match +the Object's type, so you cannot link a Lamp to a mesh type Object""" + try: + self._object.link(data._object) + except: + print "Users:", self._object.users + +class shadow: + """This is the shadow base class""" + _getters = {} + _setters = {} + _emulation = {} + + def __init__(self, object): + self._object = object + + def __getattr__(self, a): + try: + return getattr(self._object, a) + except: + if self._emulation.has_key(a): + return getattr(self._object, self._emulation[a]) + elif self._getters.has_key(a): + return self._getters[a](self) + else: + raise AttributeError, a + + def __setattr__(self, a, val): + if a == "_object": + self.__dict__['_object'] = val + return + + try: + setattr(self.__dict__['_object'], a, val) + except: + if self._emulation.has_key(a): + setattr(self.__dict__['_object'], self._emulation[a], val) + elif self._setters.has_key(a): + self._setters[a](self, val) + else: + raise AttributeError, a + link = _link + + def rename(self, name): + """Tries to set the name of the object to 'name'. If the name already +exists, a unique name is created by appending a version number (e.g. '.001') +to 'name'. The effective name is returned.""" + self._object.name = name + return self._object.name + +def _getattrEx(self, a): + if self._emulation.has_key(a): + return getattr(self._object, self._emulation[a]) + elif self._getters.has_key(a): + return self._getters[a](self) + else: + return getattr(self._object, a) + +class shadowEx: + """This is the shadow base class with a minor change; check for +emulation attributes happens before access to the raw object's attributes""" + _getters = {} + _setters = {} + _emulation = {} + + def __del__(self): + self.__dict__.clear() + + def __init__(self, object): + self._object = object + + def __getattr__(self, a): + return _getattrEx(self, a) + + def __setattr__(self, a, val): + if a == "_object": + self.__dict__['_object'] = val + return + + if self._emulation.has_key(a): + setattr(self.__dict__['_object'], self._emulation[a], val) + elif self._setters.has_key(a): + self._setters[a](self, val) + else: + setattr(self.__dict__['_object'], a, val) + + def __repr__(self): + return repr(self._object) + + def rename(self, name): + """Tries to set the name of the object to 'name'. If the name already +exists, a unique name is created by appending a version number (e.g. '.001') +to 'name'. The effective name is returned.""" + self._object.name = name + return self._object.name + + link = _link + +class hasIPO(shadowEx): + """Object class which has Ipo curves assigned""" + + def getIpo(self): + "Returns the Ipo assigned to 'self'" + import Ipo + return Ipo.IpoBlock(self._object.ipo) + + def setIpo(self, ipo): + "Assigns the IpoBlock 'ipo' to 'self'" + return self._object.assignIpo(ipo._object) + + def __getattr__(self, a): + if a == "ipo": + print "ipo member access deprecated, use self.getIpo() instead!" + return self.getIpo() + else: + return _getattrEx(self, a) + +class hasModes(shadowEx): + """Object class which has different Modes""" + def getMode(self): + """Returns a list of the modes which are set for 'self'""" + list = [] + for k in self.Modes.keys(): + i = self.Modes[k] + if self._object.mode & i: + list.append(k) + return list + + def setMode(self, *args): + """Set the mode of 'self'. This function takes a variable number +of string arguments of the types listed in self.Modes""" + flags = 0 + try: + for a in args: + flags |= self.Modes[a] + except: + raise TypeError, "mode must be one of" % self.Modes.keys() + self._object.mode = flags + +class dict: + """readonly dictionary shadow""" + _emulation = {} + + def __init__(self, dict): + self._dict = dict + + def __getitem__(self, key): + try: + return self._dict[key] + except: + key = _emulation[key] + return self._dict[key] + + def __repr__(self): + return repr(self._dict) diff --git a/intern/python/modules/Blender/sys.py b/intern/python/modules/Blender/sys.py new file mode 100644 index 00000000000..f76c0074c1f --- /dev/null +++ b/intern/python/modules/Blender/sys.py @@ -0,0 +1,20 @@ +from _Blender.sys import * + +sep = dirsep # path separator ('/' or '\') + +class Path: + def dirname(self, name): + return dirname(name) + def join(self, a, *p): + path = a + for b in p: + if b[:1] == dirsep: + path = b + elif path == '' or path[-1:] == dirsep: + path = path + b + else: + path = path + dirsep + b + return path + +path = Path() + diff --git a/intern/python/modules/Converter/__init__.py b/intern/python/modules/Converter/__init__.py new file mode 100644 index 00000000000..81db84a66f6 --- /dev/null +++ b/intern/python/modules/Converter/__init__.py @@ -0,0 +1,4 @@ +__all__ = ["importer", "importloader"] + +import importloader + diff --git a/intern/python/modules/Converter/bimporter.py b/intern/python/modules/Converter/bimporter.py new file mode 100644 index 00000000000..d788d4bccce --- /dev/null +++ b/intern/python/modules/Converter/bimporter.py @@ -0,0 +1,34 @@ +class importer: + def __init__(self,writer=None): + self.writer = writer + self.filename = None + self.file = None + self.ext = "" + def readfile(self, name): + file = open(name, "r") + if not file: + return 0 + self.file = file + self.filename = name + self.lines = file.readlines() + def close(self): + if self.filename: + self.file.close() + def checkmagic(self, name): + # return 1 if magic true (format verified), 0 else + return 0 + def parse(self, data): + # parse and convert the data shere + pass + +class writer: + def __init__(self, args = None): + pass + def mesh(self, me, name): + pass + +_inst = importer() +readfile = _inst.readfile +close = _inst.close +checkmagic = _inst.checkmagic +parse = _inst.parse diff --git a/intern/python/modules/Converter/importer/VRMLimporter.py b/intern/python/modules/Converter/importer/VRMLimporter.py new file mode 100644 index 00000000000..e2bcea6a51e --- /dev/null +++ b/intern/python/modules/Converter/importer/VRMLimporter.py @@ -0,0 +1,988 @@ +# VRML import prototype +# +# strubi@blender.nl +# + +"""VRML import module + + This is a prototype for VRML97 file import + + Supported: + + - Object hierarchies, transform collapsing (optional) + + - Meshes (IndexedFaceSet, no Basic primitives yet) + + - Materials + + - Textures (jpg, tga), conversion option from alien formats + +""" + +import Blender.sys as os # Blender os emulation +from beta import Scenegraph + +Transform = Scenegraph.Transform + +import beta.Objects + +_b = beta.Objects + +#from Blender import Mesh +Color = _b.Color +DEFAULTFLAGS = _b.DEFAULTFLAGS +FACEFLAGS = _b.FACEFLAGS +shadowNMesh = _b.shadowNMesh + +quat = Scenegraph.quat # quaternion math +vect = quat.vect # vector math module +from vrml import loader + +#### GLOBALS + +OB = Scenegraph.Object.Types # CONST values +LA = Scenegraph.Lamp.Types + +g_level = 1 +g_supported_fileformats = ["jpg", "jpeg", "tga"] + +#### OPTIONS + +OPTIONS = {'cylres' : 16, # resolution of cylinder + 'flipnormals' : 0, # flip normals (force) + 'mat_as_vcol' : 0, # material as vertex color - warning, this increases mem usage drastically on big files + 'notextures' : 0, # no textures - saves some memory + 'collapseDEFs' : 0, # collapse DEF nodes + 'collapseTF' : 0, # collapse Transforms (as far as possible, + # i.e. currently to Object transform level) + } + +#### CONSTANTS + +LAYER_EMPTY = (1 << 2) +LAYER_LAMP = (1 << 4) +LAYER_CAMERA = 1 + (1 << 4) + +CREASE_ANGLE_THRESHOLD = 0.45 # radians + +PARSE_TIME = (loader.parser.IMPORT_PARSE_TIME ) +PROCESS_TIME = (1.0 - PARSE_TIME ) +PROGRESS_DEPTH = loader.parser.PROGRESS_DEPTH +VERBOSE_DEPTH = PROGRESS_DEPTH + +#### DEBUG + +def warn(text): + print "###", text + +def debug2(text): + print (g_level - 1) * 4 * " " + text + +def verbose(text): + print text + +def quiet(text): + pass + +debug = quiet + +#### ERROR message filtering: + +g_error = {} # dictionary for non-fatal errors to mark whether an error + # was already reported + +def clrError(): + global g_error + g_error['toomanyfaces'] = 0 + +def isError(name): + return g_error[name] + +def setError(name): + global g_error + g_error[name] = 1 + +#### ERROR handling + +class baseError: + def __init__(self, value): + self.value = value + def __str__(self): + return `self.value` + +class MeshError(baseError): + pass + +UnfinishedError = loader.parser.UnfinishedError + +########################################################## +# HELPER ROUTINES + +def assignImage(f, img): + f.image = img + +def assignUV(f, uv): + if len(uv) != len(f.v): + uv = uv[:len(f.v)] + #raise MeshError, "Number of UV coordinates does not match number of vertices in face" + f.uv = [] + for u in uv: + f.uv.append((u[0], u[1])) # make sure it's a tuple + + +#### VRML STUFF + +# this is used for transform collapsing +class TransformStack: + def __init__(self): + self.stack = [Transform()] + def push(self, t): + self.stack.append(t) + def pop(self): + return self.stack.pop() + def last(self): + return self.stack[-1] + +def fromVRMLTransform(tfnode): + t = Transform() + s = tfnode.scale + t.scale = (s[0], s[1], s[2]) + r = tfnode.rotation + if r[0] == 0.0 and r[1] == 0.0 and r[2] == 0.0: + rotaxis = (0.0, 0.0, 1.0) + ang = 0.0 + else: + rotaxis = vect.norm3(r[:3]) + ang = r[3] + + #t.rotation = (rotaxis, ang) + t.calcRotfromAxis((rotaxis, ang)) + tr = tfnode.translation + t.translation = (tr[0], tr[1], tr[2]) + # XXX more to come.. + return t + + +### TODO: enable material later on +#class dummyMaterial: + #def setMode(self, *args): + #pass + +def fromVRMLMaterial(mat): + name = mat.DEF + from Blender import Material + m = Material.New(name) + + m.rgbCol = mat.diffuseColor + m.alpha = 1.0 - mat.transparency + m.emit = vect.len3(mat.emissiveColor) + if m.Emit > 0.01: + if vect.cross(mat.diffuseColor, mat.emissiveColor) > 0.01 * m.Emit: + m.rgbCol = mat.emissiveColor + + m.ref = 1.0 + m.spec = mat.shininess + m.specCol = mat.specularColor + m.amb = mat.ambientIntensity + return m + +# override: +#def fromVRMLMaterial(mat): +# return dummyMaterial() + +def buildVRMLTextureMatrix(tr): + from math import sin, cos + newMat = vect.Matrix + newVec = vect.Vector + # rotmatrix + s = tr.scale + t = tr.translation + c = tr.center + + phi = tr.rotation + + SR = newMat() + C = newMat() + C[2] = newVec(c[0], c[1], 1.0) + + if abs(phi) > 0.00001: + SR[0] = newVec(s[0] * cos(phi), s[1] * sin(phi), 0.0) + SR[1] = newVec(-s[0] * sin(phi), s[1] * cos(phi), 0.0) + else: + SR[0] = newVec(s[0], 0.0, 0.0) + SR[1] = newVec(0.0, s[1], 0.0) + + SR = C * SR * C.inverse() # rotate & scale about rotation center + + T = newMat() + T[2] = newVec(t[0], t[1], 1.0) + return SR * T # texture transform matrix + +def imageConvert(fromfile, tofile): + """This should convert from a image file to another file, type is determined +automatically (on extension). It's currently just a stub - users can override +this function to implement their own converters""" + return 0 # we just fail in general + +def addImage(path, filename): + "returns a possibly existing image which is imported by Blender" + from Blender import Image + img = None + try: + r = filename.rindex('.') + except: + return None + + naked = filename[:r] + ext = filename[r+1:].lower() + + if path: + name = os.sep.join([path, filename]) + file = os.sep.join([path, naked]) + else: + name = filename + file = naked + + if not ext in g_supported_fileformats: + tgafile = file + '.tga' + jpgfile = file + '.jpg' + for f in tgafile, jpgfile: # look for jpg, tga + try: + img = Image.Load(f) + if img: + verbose("couldn't load %s (unsupported).\nFound %s instead" % (name, f)) + return img + except IOError, msg: + pass + try: + imgfile = open(name, "rb") + imgfile.close() + except IOError, msg: + warn("Image %s not found" % name) + return None + + verbose("Format unsupported, trying to convert to %s" % tgafile) + if not imageConvert(name, tgafile): + warn("image conversion failed") + return None + else: + return Image.Load(tgafile) + return None # failed + try: + img = Image.Load(name) + except IOError, msg: + warn("Image %s not found" % name) + return img + # ok, is supported + +def callMethod(_class, method, vnode, newnode, warn = 1): + meth = None + try: + meth = getattr(_class, method) + except AttributeError: + if warn: + unknownType(method) + return None, None + if meth: + return meth(vnode, parent = newnode) + +def unknownType(type): + warn("unsupported:" + repr(type)) + +def getChildren(vnode): + try: + children = vnode.children + except: + children = None + return children + +def getNodeType(vnode): + return vnode.__gi__ + +GroupingNodeTypes = ["Group", "Collision", "Anchor", "Billboard", "Inline", + "LOD", "Switch", "Transform"] + +################################################################################ +# +#### PROCESSING CLASSES + + +class NullProcessor: + def __init__(self, tstack = TransformStack()): + self.stack = tstack + self.walker = None + self.mesh = None + self.ObjectNode = Scenegraph.NodefromData # may be altered... + self.MaterialCache = {} + self.ImageCache = {} + +# This is currently not used XXX +class DEFcollapser(NullProcessor): + """This is for collapsing DEF Transform nodes into a single object""" + def __init__(self): + self.collapsedNodes = [] + + def Transform(self, curnode, parent, **kw): + name = curnode.DEF + if not name: # node is a DEF node + return None, None + + return children, None + + +class Processor(NullProcessor): + """The processor class defines the handler for a VRML Scenegraph node. +Definition of a handler method simply happens by use of the VRML Scenegraph +entity name. + +A handler usually creates a new Scenegraph node in the target scenegraph, +converting the data from the given VRML node. + +A handler takes the arguments: + + curnode: the currently visited VRML node + parent: the previously generated target scenegraph parent node + **kw: additional keywords + +It MUST return: (children, newBnode) where: + children: the children of the current VRML node. These will be further + processed by the processor. If this is not wanted (because they + might have been processed by the handler), None must be returned. + newBnode: the newly created target node or None. + """ + + def _handleProto(self, curnode, parent, **kw): + p = curnode.PROTO + if not p.sceneGraph: + print curnode.__gi__, "unsupported" + return None, None + + def _dummy(self, curnode, parent, **kw): + print curnode.sceneGraph + return None, None + + #def __getattr__(self, name): + #"""If method is not statically defined, look up prototypes""" + #return self._handleProto + + def _currentTransform(self): + return self.stack.last() + + def _parent(self, curnode, parent, trans): + name = curnode.DEF + children = getChildren(curnode) + debug("children: %s" % children) + objects = [] + transforms = [] + groups = [] + isempty = 0 + for c in children: + type = getNodeType(c) + if type == 'Transform': + transforms.append(c) + elif type in GroupingNodeTypes: + groups.append(c) + #else: + elif hasattr(self, type): + objects.append(c) + if transforms or groups or len(objects) != 1: + # it's an empty + if not name: + name = 'EMPTY' + Bnode = self.ObjectNode(None, OB.EMPTY, name) # empty Blender Object node + if options['layers']: + Bnode.object.Layer = LAYER_EMPTY + Bnode.transform = trans + Bnode.update() + isempty = 1 + parent.insert(Bnode) + else: # don't insert extra empty if only one object has children + Bnode = parent + + for node in objects: + c, new = self.walker.walk(node, Bnode) + if not isempty: # only apply transform if no extra transform empty in hierarchy + new.transform = trans + Bnode.insert(new) + for node in transforms: + self.walker.walk(node, Bnode) + for node in groups: + self.walker.walk(node, Bnode) + + return None, None + + def sceneGraph(self, curnode, parent, **kw): + parent.type = 'ROOT' + return curnode.children, None + + def Transform(self, curnode, parent, **kw): + # we support 'center' and 'scaleOrientation' by inserting + # another Empty in between the Transforms + + t = fromVRMLTransform(curnode) + cur = self._currentTransform() + + chainable = 0 + + if OPTIONS['collapseTF']: + try: + cur = cur * t # chain transforms + except: + cur = self._currentTransform() + chainable = 1 + + self.stack.push(cur) + + # here comes the tricky hacky transformation conversion + + # TODO: SR not supported yet + + if chainable == 1: # collapse, but not chainable + # insert extra transform: + Bnode = self.ObjectNode(None, OB.EMPTY, 'Transform') # Empty + Bnode.transform = cur + parent.insert(Bnode) + parent = Bnode + + c = curnode.center + if c != [0.0, 0.0, 0.0]: + chainable = 1 + trans = Transform() + trans.translation = (-c[0], -c[1], -c[2]) + tr = t.translation + t.translation = (tr[0] + c[0], tr[1] + c[1], tr[2] + c[2]) + + Bnode = self.ObjectNode(None, OB.EMPTY, 'C') # Empty + Bnode.transform = t + parent.insert(Bnode) + parent = Bnode + else: + trans = t + + if chainable == 2: # collapse and is chainable + # don't parent, insert into root node: + for c in getChildren(curnode): + dummy, node = self.walker.walk(c, parent) # skip transform node, insert into parent + if node: # a valid Blender node + node.transform = cur + else: + self._parent(curnode, parent, trans) + + + self.stack.pop() + return None, None + + def Switch(self, curnode, parent, **kw): + return None, None + + def Group(self, curnode, parent, **kw): + if OPTIONS['collapseTF']: + cur = self._currentTransform() + # don't parent, insert into root node: + children = getChildren(curnode) + for c in children: + dummy, node = self.walker.walk(c, parent) # skip transform node, insert into parent + if node: # a valid Blender node + node.transform = cur + else: + t = Transform() + self._parent(curnode, parent, t) + return None, None + + def Collision(self, curnode, parent, **kw): + return self.Group(curnode, parent) + +# def LOD(self, curnode, parent, **kw): +# c, node = self.walker.walk(curnode.level[0], parent) +# parent.insert(node) +# return None, None + + def Appearance(self, curnode, parent, **kw): + # material colors: + mat = curnode.material + self.curColor = mat.diffuseColor + + name = mat.DEF + if name: + if self.MaterialCache.has_key(name): + self.curmaterial = self.MaterialCache[name] + else: + m = fromVRMLMaterial(mat) + self.MaterialCache[name] = m + self.curmaterial = m + else: + if curnode.DEF: + name = curnode.DEF + if self.MaterialCache.has_key(name): + self.curmaterial = self.MaterialCache[name] + else: + m = fromVRMLMaterial(mat) + self.MaterialCache[name] = m + self.curmaterial = m + else: + self.curmaterial = fromVRMLMaterial(mat) + + try: + name = curnode.texture.url[0] + except: + name = None + if name: + if self.ImageCache.has_key(name): + self.curImage = self.ImageCache[name] + else: + self.ImageCache[name] = self.curImage = addImage(self.curpath, name) + else: + self.curImage = None + + tr = curnode.textureTransform + if tr: + self.curtexmatrix = buildVRMLTextureMatrix(tr) + else: + self.curtexmatrix = None + return None, None + + def Shape(self, curnode, parent, **kw): + name = curnode.DEF + debug(name) + #self.mesh = Mesh.rawMesh() + self.mesh = shadowNMesh() + self.mesh.name = name + + # don't mess with the order of these.. + if curnode.appearance: + self.walker.preprocess(curnode.appearance, self.walker.preprocessor) + else: + # no appearance, get colors from shape (vertex colors) + self.curColor = None + self.curImage = None + self.walker.preprocess(curnode.geometry, self.walker.preprocessor) + + if hasattr(self, 'curmaterial'): + self.mesh.assignMaterial(self.curmaterial) + + meshobj = self.mesh.write() # write mesh + del self.mesh + bnode = Scenegraph.ObjectNode(meshobj, OB.MESH, name) + if name: + curnode.setTargetnode(bnode) # mark as already processed + return None, bnode + + def Box(self, curnode, parent, **kw): + col = apply(Color, self.curColor) + + faces = [] + x, y, z = curnode.size + x *= 0.5; y *= 0.5; z *= 0.5 + name = curnode.DEF + m = self.mesh + v0 = m.addVert((-x, -y, -z)) + v1 = m.addVert(( x, -y, -z)) + v2 = m.addVert(( x, y, -z)) + v3 = m.addVert((-x, y, -z)) + v4 = m.addVert((-x, -y, z)) + v5 = m.addVert(( x, -y, z)) + v6 = m.addVert(( x, y, z)) + v7 = m.addVert((-x, y, z)) + + flags = DEFAULTFLAGS + if not self.curImage: + uvflag = 1 + else: + uvflag = 0 + + m.addFace([v3, v2, v1, v0], flags, uvflag) + m.addFace([v0, v1, v5, v4], flags, uvflag) + m.addFace([v1, v2, v6, v5], flags, uvflag) + m.addFace([v2, v3, v7, v6], flags, uvflag) + m.addFace([v3, v0, v4, v7], flags, uvflag) + m.addFace([v4, v5, v6, v7], flags, uvflag) + + for f in m.faces: + f.col = [col, col, col, col] + return None, None + + def Viewpoint(self, curnode, parent, **kw): + t = Transform() + r = curnode.orientation + name = 'View_' + curnode.description + t.calcRotfromAxis((r[:3], r[3])) + t.translation = curnode.position + Bnode = self.ObjectNode(None, OB.CAMERA, name) # Empty + Bnode.object.Layer = LAYER_CAMERA + Bnode.transform = t + return None, Bnode + + def DirectionalLight(self, curnode, parent, **kw): + loc = (0.0, 10.0, 0.0) + l = self._lamp(curnode, loc) + l.object.data.type = LA.SUN + return None, l + + def PointLight(self, curnode, parent, **kw): + l = self._lamp(curnode, curnode.location) + l.object.data.type = LA.LOCAL + return None, l + + def _lamp(self, curnode, location): + t = Transform() + name = curnode.DEF + energy = curnode.intensity + t.translation = location + Bnode = self.ObjectNode(None, OB.LAMP, "Lamp") + Bnode.object.data.energy = energy * 5.0 + if options['layers']: + Bnode.object.Layer = LAYER_LAMP + Bnode.transform = t + return Bnode + + def IndexedFaceSet(self, curnode, **kw): + matxvec = vect.matxvec + mesh = self.mesh + debug("IFS, read mesh") + + texcoo = curnode.texCoord + uvflag = 0 + + if curnode.color: + colors = curnode.color.color + if curnode.colorIndex: # we have color indices + colindex = curnode.colorIndex + else: + colindex = curnode.coordIndex + if not texcoo: + uvflag = 1 + else: + colors = None + + faceflags = DEFAULTFLAGS + + if not texcoo and OPTIONS['mat_as_vcol'] and self.curColor: + uvflag = 1 + col = apply(Color, self.curColor) + elif self.curImage: + faceflags += FACEFLAGS.TEX + +# MAKE VERTICES + + coo = curnode.coord + ncoo = len(coo.point) + + if curnode.normal: # normals defined + normals = curnode.normal.vector + if curnode.normalPerVertex and len(coo.point) == len(normals): + self.mesh.recalc_normals = 0 + normindex = curnode.normalIndex + i = 0 + for v in coo.point: + newv = mesh.addVert(v) + n = newv.no + n[0], n[1], n[2] = normals[normindex[i]] + i += 1 + else: + for v in coo.point: + mesh.addVert(v) + else: + for v in coo.point: + mesh.addVert(v) + if curnode.creaseAngle < CREASE_ANGLE_THRESHOLD: + self.mesh.smooth = 1 + + nvertices = len(mesh.vertices) + if nvertices != ncoo: + print "todo: %d, done: %d" % (ncoo, nvertices) + raise RuntimeError, "FATAL: could not create all vertices" + +# MAKE FACES + + index = curnode.coordIndex + vlist = [] + + flip = OPTIONS['flipnormals'] + facecount = 0 + vertcount = 0 + + cols = [] + if curnode.colorPerVertex: # per vertex colors + for i in index: + if i == -1: + if flip or (curnode.ccw == 0 and not flip): # counterclockwise face def + vlist.reverse() + f = mesh.addFace(vlist, faceflags, uvflag) + if uvflag or colors: + f.col = cols + cols = [] + vlist = [] + else: + if colors: + col = apply(Color, colors[colindex[vertcount]]) + cols.append(col) + vertcount += 1 + v = mesh.vertices[i] + vlist.append(v) + else: # per face colors + for i in index: + if i == -1: + if flip or (curnode.ccw == 0 and not flip): # counterclockwise face def + vlist.reverse() + f = mesh.addFace(vlist, faceflags, uvflag) + facecount += 1 + + if colors: + col = apply(Color, colors[colindex[facecount]]) + cols = len(f.v) * [col] + + if uvflag or colors: + f.col = cols + vlist = [] + else: + v = mesh.vertices[i] + vlist.append(v) + +# TEXTURE COORDINATES + + if not texcoo: + return None, None + + self.curmaterial.setMode("traceable", "shadow", "texFace") + m = self.curtexmatrix + if m: # texture transform exists: + for uv in texcoo.point: + v = (uv[0], uv[1], 1.0) + v1 = matxvec(m, v) + uv[0], uv[1] = v1[0], v1[1] + + UVindex = curnode.texCoordIndex + if not UVindex: + UVindex = curnode.coordIndex + # go assign UVs + self.mesh.hasFaceUV(1) + j = 0 + uv = [] + for i in UVindex: + if i == -1: # flush + if not curnode.ccw: + uv.reverse() + assignUV(f, uv) + assignImage(f, self.curImage) + uv = [] + j +=1 + else: + f = mesh.faces[j] + uv.append(texcoo.point[i]) + return None, None + +class PostProcessor(NullProcessor): + def Shape(self, curnode, **kw): + pass + return None, None + def Transform(self, curnode, **kw): + return None, None + +class Walker: + """The node visitor (walker) class for VRML nodes""" + def __init__(self, pre, post = NullProcessor(), progress = None): + self.scene = Scenegraph.BScene() + self.preprocessor = pre + self.postprocessor = post + pre.walker = self # processor knows about walker + post.walker = self + self.nodes = 1 + self.depth = 0 + self.progress = progress + self.processednodes = 0 + + def walk(self, vnode, parent): + """Essential walker routine. It walks along the scenegraph nodes and +processes them according to its pre/post processor methods. + +The preprocessor methods return the children of the node remaining +to be processed or None. Also, a new created target node is returned. +If the target node is == None, the current node will be skipped in the +target scenegraph generation. If it is a valid node, the walker routine +inserts it into the 'parent' node of the target scenegraph, which +must be a valid root node on first call, leading us to the example usage: + + p = Processor() + w = Walker(p, PostProcessor()) + root = Scenegraph.RootNode() + w.walk(SG, root) # SG is a VRML scenegraph + """ + global g_level #XXX + self.depth += 1 + g_level = self.depth + if self.depth < PROGRESS_DEPTH: + self.processednodes += 1 + if self.progress: + ret = self.progress(PARSE_TIME + PROCESS_TIME * float(self.processednodes) / self.nodes) + if not ret: + progress(1.0) + raise UnfinishedError, "User cancelled conversion" + + # if vnode has already been processed, call Linker method, Processor method otherwise + id = vnode.DEF # get name + if not id: + id = 'Object' + + processed = vnode.getTargetnode() + if processed: # has been processed ? + debug("linked obj: %s" % id) + children, bnode = self.link(processed, parent) + else: + children, bnode = self.preprocess(vnode, parent) + + if not bnode: + bnode = parent # pass on + else: + parent.insert(bnode) # insert into SG + + if children: + for c in children: + self.walk(c, bnode) + if not processed: + self.postprocess(vnode, bnode) + + self.depth -= 1 + + return children, bnode + + def link(self, bnode, parent): + """Link already processed data""" + # link data: + new = bnode.clone() + if not new: + raise RuntimeError, "couldn't clone object" + return None, new + + def preprocess(self, vnode, newnode = None): + """Processes a VRML node 'vnode' and returns a custom node. The processor must +be specified in 'p'. +Optionally, a custom parent node (previously created) is passed as 'newnode'.""" + + pre = "pre" + + nodetype = vnode.__gi__ + + debug(pre + "process:" + repr(nodetype) + " " + vnode.DEF) + return callMethod(self.preprocessor, nodetype, vnode, newnode) + + def postprocess(self, vnode, newnode = None): + """Postprocessing of a VRML node, see Walker.preprocess()""" + + nodetype = vnode.__gi__ + pre = "post" + + debug(pre + "process:" + repr(nodetype) + " " + vnode.DEF) + return callMethod(self.postprocessor, nodetype, vnode, newnode, 0) + +testfile2 = '/home/strubi/exotic/wrl/BrownTrout1.wrl' +testfile = '/home/strubi/exotic/wrl/examples/VRML_Model_HSL.wrl' + +def fix_VRMLaxes(root, scale): + from Blender import Object, Scene + q = quat.fromRotAxis((1.0, 0.0, 0.0), 1.57079) + empty = Object.New(OB.EMPTY) + empty.layer = LAYER_EMPTY + Scene.getCurrent().link(empty) + node = Scenegraph.ObjectNode(empty, None, "VRMLscene") + node.transform.rotation = q + if scale: + node.transform.scale = (0.01, 0.01, 0.01) + for c in root.children: + node.insert(c) + node.update() + root.children = [node] + +################################################################# +# these are the routines that must be provided for the importer +# interface in blender + +def checkmagic(name): + "check for file magic" + f = open(name, "r") + magic = loader.getFileType(f) + f.close() + if magic == 'vrml': + return 1 + elif magic == 'gzip': + verbose("gzipped file detected") + try: + import gzip + except ImportError, value: + warn("Importing gzip module: %s" % value) + return 0 + + f = gzip.open(name, 'rb') + header = f.readline() + f.close() + if header[:10] == "#VRML V2.0": + return 1 + else: + return 0 + print "unknown file" + return 0 + +g_infotxt = "" + +def progress(done): + from Blender import Window + ret = Window.draw_progressbar(done, g_infotxt) + return ret + +class Counter: + def __init__(self): + self._count = 0 + self.depth = 0 + def count(self, node): + if self.depth >= PROGRESS_DEPTH: + return 0 + + self.depth += 1 + self._count += 1 + if not getChildren(node): + self.depth -= 1 + return 0 + else: + for c in node.children: + self.count(c) + self.depth -= 1 + return self._count + +################################################################################ +# MAIN ROUTINE + +def importfile(name): + + global g_infotxt + global options + global DEFAULTFLAGS + + from Blender import Get # XXX + options = Get('vrmloptions') + DEFAULTFLAGS = FACEFLAGS.LIGHT + FACEFLAGS.DYNAMIC + if options['twoside']: + print "TWOSIDE" + DEFAULTFLAGS |= FACEFLAGS.TWOSIDE + clrError() + g_infotxt = "load & parse file..." + progress(0.0) + root = Scenegraph.RootNode() + try: + l = loader.Loader(name, progress) + SG = l.load() + p = Processor() + w = Walker(p, PostProcessor(), progress) + g_infotxt = "convert data..." + p.curpath = os.path.dirname(name) + print "counting nodes...", + c = Counter() + nodes = c.count(SG) + print "done." + w.nodes = nodes # let walker know about number of nodes parsed # XXX + w.walk(SG, root) + except UnfinishedError, msg: + print msg + + progress(1.0) + fix_VRMLaxes(root, options['autoscale']) # rotate coordinate system: in VRML, y is up! + root.update() # update baselist for proper display + return root diff --git a/intern/python/modules/Converter/importer/__init__.py b/intern/python/modules/Converter/importer/__init__.py new file mode 100644 index 00000000000..003e2733b17 --- /dev/null +++ b/intern/python/modules/Converter/importer/__init__.py @@ -0,0 +1,17 @@ +"""This module contains a list of valid importers in 'importers'. At runtime, +importer modules can be registered by the 'register' function.""" + +__all__ = ["VRMLimporter"] + +importers = __all__ + +import VRMLimporter + +def register(importer): + """Register an file importer""" + methods = ["checkmagic", "importfile"] + for m in methods: + if not hasattr(importer, m): + raise TypeError, "This is not an importer" + importers.append(importer) + diff --git a/intern/python/modules/Converter/importloader.py b/intern/python/modules/Converter/importloader.py new file mode 100644 index 00000000000..245ab108d1f --- /dev/null +++ b/intern/python/modules/Converter/importloader.py @@ -0,0 +1,23 @@ +# this is the importloader which blender calls on unknown +# file types + +import importer + +supported= {'wrl': importer.VRMLimporter} + +def process(name): + # run through importerlist and check for magic + m = None + for modname in importer.importers: + mod = getattr(importer, modname) + if mod.checkmagic(name): + m = mod + break + if not m: + return 0 + m.importfile(name) + #except: + #import sys + #print "Import failed"sys.exc_value + return 1 + diff --git a/intern/python/modules/TextTools/Constants/Sets.py b/intern/python/modules/TextTools/Constants/Sets.py new file mode 100644 index 00000000000..bf260aa3e0c --- /dev/null +++ b/intern/python/modules/TextTools/Constants/Sets.py @@ -0,0 +1,39 @@ +""" Constants for sets (of characters) + + (c) Copyright Marc-Andre Lemburg; All Rights Reserved. + See the documentation for further information on copyrights, + or contact the author (mal@lemburg.com). +""" +import string + +# Simple character strings + +a2z = 'abcdefghijklmnopqrstuvwxyz' +A2Z = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +umlaute = 'äöüß' +Umlaute = 'ÄÖÜ' +alpha = A2Z + a2z +german_alpha = A2Z + a2z + umlaute + Umlaute +number = '0123456789' +alphanumeric = alpha + number +white = ' \t\v' +newline = '\r\n' +formfeed = '\f' +whitespace = white + newline + formfeed +any = '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377' + +# Precompiled as sets, e.g. a2z_set = set(a2z) +a2z_set = '\000\000\000\000\000\000\000\000\000\000\000\000\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000' +A2Z_set = '\000\000\000\000\000\000\000\000\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000' +alpha_set = '\000\000\000\000\000\000\000\000\376\377\377\007\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000' +german_alpha_set = '\000\000\000\000\000\000\000\000\376\377\377\007\376\377\377\007\000\000\000\000\000\000\000\000\020\000@\220\020\000@\020' +number_set = '\000\000\000\000\000\000\377\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000' +alphanumeric_set = '\000\000\000\000\000\000\377\003\376\377\377\007\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000' +white_set = '\000\002\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000' +newline_set = '\000$\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000' +whitespace_set = '\000&\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000' +nonwhitespace_set = '\377\301\377\377\376\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377' +any_set = '\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377' + +# Clean up +del string diff --git a/intern/python/modules/TextTools/Constants/TagTables.py b/intern/python/modules/TextTools/Constants/TagTables.py new file mode 100644 index 00000000000..315d825b94e --- /dev/null +++ b/intern/python/modules/TextTools/Constants/TagTables.py @@ -0,0 +1,348 @@ +""" Constants for writing tag tables + + The documentation in this file is obsoleted by the HTML docs in + the Doc/ subdirectory of the package. Constants defined here must + match those in mxTextTools/mxte.h. + + (c) Copyright Marc-Andre Lemburg; All Rights Reserved. + See the documentation for further information on copyrights, + or contact the author (mal@lemburg.com). +""" +######################################################################### +# This file contains the definitions and constants used by the tagging +# engine: +# +# 1. Matching Tables +# 2. Commands & Constants +# 3. Matching Functions +# 4. Callable tagobjects +# 5. Calling the engine & Taglists +# + +######################################################################### +# 1. Matching Tables: +# +# these are tuples of tuples, each entry having the following meaning: +# +# syntax: (tag, cmd, chars|table|fct [,jne] [,je=1]) +# tag = object used to mark this section, if it matches +# cmd = command (see below) +# chars = match one or more of these characters +# table = table to use for matching characters +# fct = function to call (see below) +# jne = if the current character doesn't match, jump this +# many table entries relative to the current entry +# je = if we have a match make a relative jump of this length +# +# * a table matches a string iff the end of the table is reached +# (that is: an index is requested that is beyond the end-of-table) +# * a table is not matched if a tag is not matched and no jne is given; +# if it is matched then processing simply moves on to the next entry +# * marking is done by adding the matching slice in the string +# together with the marking object to the tag list; if the object is +# None, then it will not be appended to the taglist list +# * if the flag CallTag is set in cmd, then instead of appending +# matches to the taglist, the tagobj will be called (see below) +# +# TIP: if you are getting an error 'call of a non-function' while +# writing a table definition, you probably have a missing ',' +# somewhere in the tuple ! +# +# For examples see the tag*.py - files that came with this engine. +# + +######################################################################### +# 2. Commands & Constants +# +# + +# +# some useful constants for writing matching tables +# + +To = None # good for cmd=Jump +Here = None # good for cmd=Fail and EOF +MatchOk = 20000 # somewhere beyond the end of the tag table... +MatchFail = -20000 # somewhere beyond the start of the tag table... +ToEOF = -1 # good for cmd=Move + +ThisTable = 999 # to recursively match using the current table; + # can be passed as argument to Table and SubTable + # instead of a tuple + +# +# commands and flags passed in cmd (see below) +# +# note: I might add some further commands to this list, if needed +# (the numbers will then probably change, but not the +# names) +# +# convention: a command "matches", if and only if it moves the +# current position at least one character; a command "reads" +# characters the characters, if they match ok +# +# notations: +# +# x refers to the current position in the string +# len refers to the string length or what the function tag() is told to +# believe it to be (i.e. the engine only looks at the slice text[x:len]) +# text refers to the text string +# jne is the optional relative jump distance in case the command +# did not match, i.e. x before and after applying the command +# are the same (if not given the current table is considered +# not to match) +# je is the optional relative jump distance in case the command +# did match (it defaults to +1) +# + +# commands +Fail = 0 # this will always fail (position remains unchanged) +Jump = 0 # jump to jne (position remains unchanged) + +# match & read chars +AllIn = 11 # all chars in match (at least one) +AllNotIn = 12 # all chars not in match (at least one) +Is = 13 # current char must be == match (matches one char) +IsIn = 14 # current char must be in match (matches one char) +IsNot = 15 # current char must be be != match (matches one char) +IsNotIn = 15 # current char must be not be in match (matches one char) + +AllInSet = 31 +IsInSet = 32 + +# match & read for whole words +Word = 21 # the next chars must be those in match +WordStart = 22 # all chars up to the first occ. of match (at least one) +WordEnd = 23 # same as WordStart, accept that the text pointer + # is moved behind the match +NoWord = WordStart # all chars up to the first occ. of match (at least one) + + +# match using search objects BMS or FS +sWordStart = 111 # all chars up to the first occ. of match (may be 0 chars) +sWordEnd = 112 # same as WordStart, accept that the text pointer + # is moved behind the match +sFindWord = 113 # find match and process the found slice only (ignoring + # the chars that lead up to the match); positions + # the text pointer right after the match like WordEnd + +# functions & tables +Call = 201 # call match(text,x,len) as function (see above) +CallArg = 202 # match has to be a 2-tuple (fct,arg), then + # fct(text,x,len,arg) is called; the return value is taken + # as new x; it is considered matching if the new x is + # different than the x before the call -- like always + # (note: arg has to be *one* object, e.g. a tuple) +Table = 203 # match using table (given in match) +SubTable = 207 # match using sub table (given in match); the sub table + # uses the same taglist as the calling table +TableInList = 204 # same as Table, but match is a tuple (list,index) + # and the table list[index] is used as matching + # table +SubTableInList = 208 + # same as TableInList, but the sub table + # uses the same taglist as the calling table + +# specials +EOF = 1 # current position must be EOF, e.g. >= len(string) +Skip = 2 # skip match (must be an integer) chars; note: this cmd + # always matches ok, so jne doesn't have any meaning in + # this context +Move = 3 # move the current text position to match (if negative, + # the text length + 1 (!) is added, thus -1 moves to the + # EOF, -2 to the last char and so on); note: this cmd + # always matches ok, so jne doesn't have any meaning in + # this context + +# loops +Loop = 205 # loop-construct + # + # (tagobj,Loop,Count,jne,je) - sets/decrements the + # loop variable for current table according to the + # following rules: + # 1. the first time the engine passes this entry + # sets the loop variable to Count and continues + # without reading any character, but saving the + # current position in text + # 2. the next time, it decrements the loop variable + # and checks if it is < 0: + # (a) if it is, then the tagobj is added to the + # taglist with the slice (saved position, current + # position) and processing continues at entry + # current + jne + # (b) else, processing continues at entry current + je + # Note: if you jump out of the loop while the loop + # variable is still > 0, then you *must* + # reset the loop mechanism with + # (None,LoopControl,Reset) + # Note: you can skip the remaining loops by calling + # (None,LoopControl,Break) and jumping back + # to the Loop-entry; this sets the loop + # variable to 0 + # Note: tables cannot have nested loops within their + # context; you can have nested loops in nested + # tables though (there is one loop var per + # tag()-call which takes place every time + # a table match is done) + # +LoopControl = 206 # controls the loop variable (always succeeds, i.e. + # jne has no meaning); + # match may be one of: +Break = 0 # * sets the loop variable to 0, thereby allowing + # to skip the remaining loops +Reset = -1 # * resets the loop mechanism (see note above) + # + # See tagLoop.py for some examples. + +########################################################################## +# +# Flags (to be '+'ed with the above command code) +# +CallTag = 256 # call tagobj(taglist,text,l,r,subtags) + # upon successfully matching the slice [l:r] in text + # * taglist is the current list tags found (may be None) + # * subtags is a sub-list, passed when a subtable was used + # to do the matching -- it is None otherwise !) +# +# example entry with CallTag-flag set: +# +# (found_a_tag,CallTag+Table,tagtable) +# -- if tagtable matches the current text position, +# found_a_tag(taglist,text,l,r,newtaglist) is called and +# the match is *not* appended to the taglist by the tagging +# engine (the function would have to do this, in case it is needed) + +AppendToTagobj = 512 # this appends the slice found to the tagobj, assuming + # that it is a Python list: + # does a tagobj.append((None,l,r,subtags)) call +# Alias for b/w comp. +AppendToTag = AppendToTagobj + +AppendTagobj = 1024 # don't append (tagobj,l,r,subtags) to the taglist, + # but only tagobj itself; the information in l,r,subtags + # is lost, yet this can be used to write tag tables + # whose output can be used directly by tag.join() + +AppendMatch = 2048 # append the match to the taglist instead of + # the tag object; this produces non-standard + # taglists ! + +######################################################################### +# 3. Matching Functions +# +# syntax: +# +# fct(s,x,len_s) +# where s = string we are working on +# x = current index in s where we wnat to match something +# len_s = 'length' of s, this is how far the search may be +# conducted in s, not necessarily the true length of s +# +# * the function has to return the index of the char right after +# matched string, e.g. +# +# 'xyzabc' ---> 'xyz' matches ---> return x+3 +# +# * if the string doesn't match simply return x; in other words: +# the function has to return the matching slice's right index +# * you can use this to match e.g. 10 characters of a certain kind, +# or any word out of a given list, etc. +# * note: you cannot give the function additional parameters from within +# the matching table, so it has to know everything it needs to +# know a priori; use dynamic programming ! +# +# some examples (not needed, since all are implemented by commands) +# +# +#def matchword(x): +# s = """ +#def a(s,x,len_text): +# y = x+%i +# if s[x:y] == %s: return y +# return x +#""" +# exec s % (len(x),repr(x)) +# return a +# +#def rejectword(x): +# s = """ +#def a(s,x,len_text): +# while x < len(s) and s[x:x+%i] != %s: +# x = x + 1 +# return x +#""" +# exec s % (len(x),repr(x)) +# return a +# +#def HTML_Comment(s,x,len_text): +# while x < len_text and s[x:x+3] != '-->': +# x = x + 1 +# return x +# +# + +######################################################################### +# 4. Callable tagobjects +# +# a sample callable tagobj: +# +# +#def test(taglist,text,l,r,newtaglist): +# +# print 'found',repr(text[l:r])[:40],(l,r) +# +# + +######################################################################### +# 5. Calling the engine & Taglists +# +# The function +# tag(text,table,start=0,len_text=len(text),taglistinit=[]) +# found in mxTextTools: +# +# This function does all the matching according to the above rules. +# You give it a text string and a tag table and it will +# start processing the string starting from 'start' (which defaults to 0) +# and continue working until it reaches the 'EOF', i.e. len_text (which +# defaults to the text length). It thus tags the slice text[start:len_text]. +# +# The function will create a list of found tags in the following +# format (which I call taglist): +# +# (tagobj,l,r,subtaglist) +# +# where: tagobj = specified tag object taken from the table +# [l:r] = slice that matched the tag in text +# subtaglist = if matching was done using a subtable +# this is the taglist it produced; in all other +# cases this will be None +# +# * if you pass None as taglistinit, then no taglist will be created, +# i.e. only CallTag commands will have any effect. (This saves +# temporary memory for big files) +# * the function returns a tuple: +# (success, taglist, nextindex) +# where: success = 0/1 +# taglist = the produced list or None +# nextindex = the index+1 of the last char that matched +# (in case of failure, this points to the beginning +# of the substring that caused the problem) +# + +### Module init. + +def _module_init(): + + global id2cmd + + import types + id2cmd = {} + IntType = types.IntType + for cmd,value in globals().items(): + if type(value) == IntType: + if value == 0: + id2cmd[0] = 'Fail/Jump' + else: + id2cmd[value] = cmd + +_module_init() diff --git a/intern/python/modules/TextTools/Constants/__init__.py b/intern/python/modules/TextTools/Constants/__init__.py new file mode 100644 index 00000000000..0519ecba6ea --- /dev/null +++ b/intern/python/modules/TextTools/Constants/__init__.py @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/intern/python/modules/TextTools/TextTools.py b/intern/python/modules/TextTools/TextTools.py new file mode 100644 index 00000000000..7eae2bcfc39 --- /dev/null +++ b/intern/python/modules/TextTools/TextTools.py @@ -0,0 +1,766 @@ +""" mxTextTools - A tools package for fast text processing. + + (c) Copyright Marc-Andre Lemburg; All Rights Reserved. + See the documentation for further information on copyrights, + or contact the author (mal@lemburg.com). +""" +import string,types + +# +# import the C module and the version number +# +from mxTextTools import * +from mxTextTools import __version__ + +# +# import the symbols needed to write tag tables +# +from Constants.TagTables import * + +# +# import the some handy character sets +# +from Constants.Sets import * + +# +# format and print tables, taglists and joinlists: +# +def format_entry(table,i, + + TupleType=types.TupleType): + + """ Returns a pp-formatted tag table entry as string + """ + e = table[i] + jne = 0 + je = 1 + t,c,m = e[:3] + if len(e)>3: jne = e[3] + if len(e)>4: je = e[4] + flags,cmd = divmod(c,256) + c = id2cmd[cmd] + if type(m) == TupleType and c in ('Table','SubTable'): + m = '<table>' + elif m == None: + m = 'Here/To' + else: + m = repr(m) + if len(m) > 17: + m = m[:17]+'...' + return '%-15.15s : %-30s : jne=%+i : je=%+i' % \ + (repr(t),'%-.15s : %s'%(c,m),jne,je) + +def format_table(table,i=-1): + + """ Returns a pp-formatted version of the tag table as string """ + + l = [] + for j in range(len(table)): + if i == j: + l.append('--> '+format_entry(table,j)) + else: + l.append(' '+format_entry(table,j)) + return string.join(l,'\n')+'\n' + +def print_tagtable(table): + + """ Print the tag table + """ + print format_table(table) + +def print_tags(text,tags,indent=0): + + """ Print the taglist tags for text using the given indent level + """ + for tag,l,r,subtags in tags: + tagname = repr(tag) + if len(tagname) > 20: + tagname = tagname[:20] + '...' + target = repr(text[l:r]) + if len(target) > 60: + target = target[:60] + '...' + if subtags == None: + print ' '+indent*' |',tagname,': ',target,(l,r) + else: + print ' '+indent*' |',tagname,': ',target,(l,r) + print_tags(text,subtags,indent+1) + +def print_joinlist(joins,indent=0, + + StringType=types.StringType): + + """ Print the joinlist joins using the given indent level + """ + for j in joins: + if type(j) == StringType: + text = repr(j) + if len(text) > 40: + text = text[:40] + '...' + print ' '+indent*' |',text,' (len = %i)' % len(j) + else: + text = j[0] + l,r = j[1:3] + text = repr(text[l:r]) + if len(text) > 40: + text = text[:40] + '...' + print ' '+indent*' |',text,' (len = %i)' % (r-l),(l,r) + +def normlist(jlist, + + StringType=types.StringType): + + """ Return a normalized joinlist. + + All tuples in the joinlist are turned into real strings. The + resulting list is a equivalent copy of the joinlist only + consisting of strings. + + """ + l = [''] * len(jlist) + for i in range(len(jlist)): + entry = jlist[i] + if type(entry) == StringType: + l[i] = entry + else: + l[i] = entry[0][entry[1]:entry[2]] + return l + +# +# aid for matching from a list of words +# +def _lookup_dict(l,index=0): + + d = {} + for w in l: + c = w[index] + if d.has_key(c): + d[c].append(w) + else: + d[c] = [w] + return d + +def word_in_list(l): + + """ Creates a lookup table that matches the words in l + """ + t = [] + d = _lookup_dict(l) + keys = d.keys() + if len(keys) < 18: # somewhat arbitrary bound + # fast hint for small sets + t.append((None,IsIn,string.join(d.keys(),''))) + t.append((None,Skip,-1)) + # test groups + for c, group in d.items(): + t.append(None) # hint will be filled in later + i = len(t)-1 + for w in group: + t.append((None,Word,w[1:],+1,MatchOk)) + t.append((None,Fail,Here)) + # add hint + t[i] = (None,Is,c,len(t)-i) + t.append((None,Fail,Here)) + return tuple(t) + +# +# Extra stuff useful in combination with the C functions +# + +def replace(text,what,with,start=0,stop=None, + + SearchObject=BMS,join=join,joinlist=joinlist,tag=tag, + string_replace=string.replace,type=type, + StringType=types.StringType): + + """A fast replacement for string.replace. + + what can be given as string or search object. + + This function is a good example for the AppendTagobj-flag usage + (the taglist can be used directly as joinlist). + + """ + if type(what) == StringType: + so = SearchObject(what) + else: + so = what + what = so.match + if stop is None: + if start == 0 and len(what) < 2: + return string_replace(text,what,with) + stop = len(text) + t = ((text,sWordStart,so,+2), + # Found something, replace and continue searching + (with,Skip+AppendTagobj,len(what),-1,-1), + # Rest of text + (text,Move,ToEOF) + ) + found,taglist,last = tag(text,t,start,stop) + if not found: + return text + return join(taglist) + +# Alternative (usually slower) versions using different techniques: + +def _replace2(text,what,with,start=0,stop=None, + + join=join,joinlist=joinlist,tag=tag, + StringType=types.StringType,BMS=BMS): + + """Analogon to string.replace; returns a string with all occurences + of what in text[start:stop] replaced by with + - uses a one entry tag-table and a Boyer-Moore-Search-object + - what can be a string or a BMS/FS search object + - it's faster than string.replace in those cases, where + the what-string gets long and/or many replacements are found; + faster meaning from a few percent up to many times as fast + - start and stop define the slice of text to work in + - stop defaults to len(text) + """ + if stop is None: + stop = len(text) + if type(what) == StringType: + what=BMS(what) + t = ((with,sFindWord,what,+1,+0),) + found,taglist,last = tag(text,t,start,stop) + if not found: + return text + return join(joinlist(text,taglist)) + +def _replace3(text,what,with, + + join=string.join,FS=FS, + StringType=types.StringType): + + if type(what) == StringType: + what=FS(what) + slices = what.findall(text) + if not slices: + return text + l = [] + x = 0 + for left,right in slices: + l.append(text[x:left] + with) + x = right + l.append(text[x:]) + return join(l,'') + +def _replace4(text,what,with, + + join=join,joinlist=joinlist,tag=tag,FS=FS, + StringType=types.StringType): + + if type(what) == StringType: + what=FS(what) + slices = what.findall(text) + if not slices: + return text + repl = [None]*len(slices) + for i in range(len(slices)): + repl[i] = (with,)+slices[i] + return join(joinlist(text,repl)) + + +def find(text,what,start=0,stop=None, + + SearchObject=FS): + + """ A faster replacement for string.find(). + + Uses a search object for the task. Returns the position of the + first occurance of what in text[start:stop]. stop defaults to + len(text). Returns -1 in case no occurance was found. + + """ + if stop: + return SearchObject(what).find(text,start,stop) + else: + return SearchObject(what).find(text,start) + +def findall(text,what,start=0,stop=None, + + SearchObject=FS): + + """ Find all occurances of what in text. + + Uses a search object for the task. Returns a list of slice + tuples (l,r) marking the all occurances in + text[start:stop]. stop defaults to len(text). Returns an + empty list in case no occurance was found. + + """ + if stop: + return SearchObject(what).findall(text,start,stop) + else: + return SearchObject(what).findall(text,start) + +def split(text,sep,start=0,stop=None,translate=None, + + SearchObject=FS): + + """ A faster replacement for string.split(). + + Uses a search object for the task. Returns the result of + cutting the text[start:stop] string into snippets at every sep + occurance in form of a list of substrings. translate is passed + to the search object as translation string. + + XXX convert to a C function... or even better, add as method + to search objects. + + """ + if translate: + so = SearchObject(sep,translate) + else: + so = SearchObject(sep) + if stop: + cuts = so.findall(text,start,stop) + else: + cuts = so.findall(text,start) + l = 0 + list = [] + append = list.append + for left,right in cuts: + append(text[l:left]) + l = right + append(text[l:]) + return list + +# helper for tagdict +def _tagdict(text,dict,prefix,taglist): + + for o,l,r,s in taglist: + pfx = prefix + str(o) + dict[pfx] = text[l:r] + if s: + _tagdict(text,dict,pfx+'.',s) + +def tagdict(text,*args): + + """ Tag a text just like the function tag() and then convert + its output into a dictionary where the tagobjects reference + their respective strings + - this function emulates the interface of tag() + - in contrast to tag() this funtion *does* make copies + of the found stings + - returns a tuple (rc,tagdict,next) with the same meaning + of rc and next as tag(); tagdict is the new dictionary - + None in case rc is 0 + """ + rc,taglist,next = apply(tag,(text,)+args) + if not rc: + return (rc,None,next) + d = {} + tagdict = _tagdict + for o,l,r,s in taglist: + pfx = str(o) + d[pfx] = text[l:r] + if s: + tagdict(text,dict,pfx+'.',s) + return (rc,d,next) + +def invset(chars): + + """ Return a set with all characters *except* the ones in chars. + """ + return set(chars,0) + +def is_whitespace(text,start=0,stop=None, + + nonwhitespace=nonwhitespace_set,setfind=setfind): + + """ Return 1 iff text[start:stop] only contains whitespace + characters (as defined in Constants/Sets.py), 0 otherwise. + """ + if stop is None: + stop = len(text) + i = setfind(text,nonwhitespace,start,stop) + return (i < 0) + +def collapse(text,seperator=' ', + + join=join,setsplit=setsplit,collapse_set=set(newline+whitespace)): + + """ Eliminates newline characters and compresses whitespace + characters into one space. + + The result is a one line text string. Tim Peters will like + this function called with '-' seperator ;-) + + """ + return join(setsplit(text,collapse_set),seperator) + +_linesplit_table = ( + (None,Is,'\r',+1), + (None,Is,'\n',+1), + ('line',AllInSet+AppendMatch,set('\r\n',0),+1,-2), + (None,EOF,Here,+1,MatchOk), + ('empty line',Skip+AppendMatch,0,0,-4), + ) + +def splitlines(text, + + tag=tag,linesplit_table=_linesplit_table): + + """ Split text into a list of single lines. + + The following combinations are considered to be line-ends: + '\r', '\r\n', '\n'; they may be used in any combination. The + line-end indicators are removed from the strings prior to + adding them to the list. + + This function allows dealing with text files from Macs, PCs + and Unix origins in a portable way. + + """ + return tag(text,linesplit_table)[1] + +_linecount_table = ( + (None,Is,'\r',+1), + (None,Is,'\n',+1), + ('line',AllInSet+AppendTagobj,set('\r\n',0),+1,-2), + (None,EOF,Here,+1,MatchOk), + ('empty line',Skip+AppendTagobj,0,0,-4), + ) + +def countlines(text, + + linecount_table=_linecount_table): + + """ Returns the number of lines in text. + + Line ends are treated just like for splitlines() in a + portable way. + """ + return len(tag(text,linecount_table)[1]) + +_wordsplit_table = ( + (None,AllInSet,whitespace_set,+1), + ('word',AllInSet+AppendMatch,nonwhitespace_set,+1,-1), + (None,EOF,Here,+1,MatchOk), + ) + +def splitwords(text, + + setsplit=setsplit,whitespace_set=whitespace_set): + + """ Split text into a list of single words. + + Words are separated by whitespace. The whitespace is stripped + before adding the words to the list. + + """ + return setsplit(text,whitespace_set) + +# +# Testing and benchmarking +# + +# Taken from my hack.py module: +import time +class _timer: + + """ timer class with a quite obvious interface + - .start() starts a fairly accurate CPU-time timer plus an + absolute timer + - .stop() stops the timer and returns a tuple: the CPU-time in seconds + and the absolute time elapsed since .start() was called + """ + + utime = 0 + atime = 0 + + def start(self, + clock=time.clock,time=time.time): + self.atime = time() + self.utime = clock() + + def stop(self, + clock=time.clock,time=time.time): + self.utime = clock() - self.utime + self.atime = time() - self.atime + return self.utime,self.atime + + def usertime(self, + clock=time.clock,time=time.time): + self.utime = clock() - self.utime + self.atime = time() - self.atime + return self.utime + + def abstime(self, + clock=time.clock,time=time.time): + self.utime = clock() - self.utime + self.atime = time() - self.atime + return self.utime + + def __str__(self): + + return '%0.2fu %0.2fa sec.' % (self.utime,self.atime) + +def _bench(file='mxTextTools/mxTextTools.c'): + + def mismatch(orig,new): + print + for i in range(len(orig)): + if orig[i] != new[i]: + break + else: + print 'Length mismatch: orig=%i new=%i' % (len(orig),len(new)) + if len(orig) > len(new): + print 'Missing chars:'+repr(orig[len(new):]) + else: + print 'Excess chars:'+repr(new[len(orig):]) + print + return + print 'Mismatch at offset %i:' % i + print (orig[i-100:i] + + '<- %s != %s ->' % (repr(orig[i]),repr(new[i])) + + orig[i+1:i+100]) + print + + text = open(file).read() + import string + + t = _timer() + print 'Working on a %i byte string' % len(text) + + if 0: + print + print 'Replacing strings' + print '-'*72 + print + for what,with in (('m','M'),('mx','MX'),('mxText','MXTEXT'), + ('hmm','HMM'),('hmmm','HMM'),('hmhmm','HMM')): + print 'Replace "%s" with "%s"' % (what,with) + t.start() + for i in range(100): + rtext = string.replace(text,what,with) + print 'with string.replace:',t.stop(),'sec.' + t.start() + for i in range(100): + ttext = replace(text,what,with) + print 'with tag.replace:',t.stop(),'sec.' + if ttext != rtext: + print 'results are NOT ok !' + print '-'*72 + mismatch(rtext,ttext) + t.start() + for i in range(100): + ttext = _replace2(text,what,with) + print 'with tag._replace2:',t.stop(),'sec.' + if ttext != rtext: + print 'results are NOT ok !' + print '-'*72 + print rtext + t.start() + for i in range(100): + ttext = _replace3(text,what,with) + print 'with tag._replace3:',t.stop(),'sec.' + if ttext != rtext: + print 'results are NOT ok !' + print '-'*72 + print rtext + t.start() + for i in range(100): + ttext = _replace4(text,what,with) + print 'with tag._replace4:',t.stop(),'sec.' + if ttext != rtext: + print 'results are NOT ok !' + print '-'*72 + print rtext + print + + if 0: + print + print 'String lower/upper' + print '-'*72 + print + + op = string.lower + t.start() + for i in range(1000): + op(text) + t.stop() + print ' string.lower:',t + + op = string.upper + t.start() + for i in range(1000): + op(text) + t.stop() + print ' string.upper:',t + + op = upper + t.start() + for i in range(1000): + op(text) + t.stop() + print ' TextTools.upper:',t + + op = lower + t.start() + for i in range(1000): + op(text) + t.stop() + print ' TextTools.lower:',t + + print 'Testing...', + ltext = string.lower(text) + assert ltext == lower(text) + utext = string.upper(text) + assert utext == upper(text) + print 'ok.' + + if 0: + print + print 'Joining lists' + print '-'*72 + print + + l = setsplit(text,whitespace_set) + + op = string.join + t.start() + for i in range(1000): + op(l) + t.stop() + print ' string.join:',t + + op = join + t.start() + for i in range(1000): + op(l) + t.stop() + print ' TextTools.join:',t + + op = string.join + t.start() + for i in range(1000): + op(l,' ') + t.stop() + print ' string.join with seperator:',t + + op = join + t.start() + for i in range(1000): + op(l,' ') + t.stop() + print ' TextTools.join with seperator:',t + + if 0: + print + print 'Creating join lists' + print '-'*72 + print + + repl = [] + for i in range(0,len(text),10): + repl.append(str(i),i,i+1) + + op = joinlist + t.start() + for i in range(1000): + op(text,repl) + t.stop() + print ' TextTools.joinlist:',t + + if 0: + print + print 'Splitting text' + print '-'*72 + print + + op = string.split + t.start() + for i in range(100): + op(text) + t.stop() + print ' string.split whitespace:',t,'(',len(op(text)),'snippets )' + + op = setsplit + ws = whitespace_set + t.start() + for i in range(100): + op(text,ws) + t.stop() + print ' TextTools.setsplit whitespace:',t,'(',len(op(text,ws)),'snippets )' + + assert string.split(text) == setsplit(text,ws) + + op = string.split + sep = 'a' + t.start() + for i in range(100): + op(text,sep) + t.stop() + print ' string.split at "a":',t,'(',len(op(text,sep)),'snippets )' + + op = split + sep = 'a' + t.start() + for i in range(100): + op(text,sep) + t.stop() + print ' TextTools.split at "a":',t,'(',len(op(text,sep)),'snippets )' + + op = charsplit + sep = 'a' + t.start() + for i in range(100): + op(text,sep) + t.stop() + print ' TextTools.charsplit at "a":',t,'(',len(op(text,sep)),'snippets )' + + op = setsplit + sep = set('a') + t.start() + for i in range(100): + op(text,sep) + t.stop() + print ' TextTools.setsplit at "a":',t,'(',len(op(text,sep)),'snippets )' + + # Note: string.split and setsplit don't work identically ! + + op = string.split + sep = 'int' + t.start() + for i in range(100): + op(text,sep) + t.stop() + print ' string.split at "int":',t,'(',len(op(text,sep)),'snippets )' + + op = split + sep = 'int' + t.start() + for i in range(100): + op(text,sep) + t.stop() + print ' TextTools.split at "int":',t,'(',len(op(text,sep)),'snippets )' + + op = setsplit + sep = set('int') + t.start() + for i in range(100): + op(text,sep) + t.stop() + print ' TextTools.setsplit at "i", "n", "t":',t,'(',len(op(text,sep)),'snippets )' + + op = string.split + sep = 'register' + t.start() + for i in range(100): + op(text,sep) + t.stop() + print ' string.split at "register":',t,'(',len(op(text,sep)),'snippets )' + + op = split + sep = 'register' + t.start() + for i in range(100): + op(text,sep) + t.stop() + print ' TextTools.split at "register":',t,'(',len(op(text,sep)),'snippets )' + +if __name__=='__main__': + _bench() + diff --git a/intern/python/modules/TextTools/__init__.py b/intern/python/modules/TextTools/__init__.py new file mode 100644 index 00000000000..f9255aca276 --- /dev/null +++ b/intern/python/modules/TextTools/__init__.py @@ -0,0 +1,48 @@ +""" mxTextTools - A tools package for fast text processing. + + (c) Copyright Marc-Andre Lemburg; All Rights Reserved. + See the documentation for further information on copyrights, + or contact the author (mal@lemburg.com). +""" +__package_info__ = """ +BEGIN PYTHON-PACKAGE-INFO 1.0 +Title: mxTextTools - Tools for fast text processing +Current-Version: 1.1.1 +Home-Page: http://starship.skyport.net/~lemburg/mxTextTools.html +Primary-Site: http://starship.skyport.net/~lemburg/mxTextTools-1.1.1.zip + +This package provides several different functions and mechanisms +to do fast text text processing. Amongst these are character set +operations, parsing & tagging tools (using a finite state machine +executing byte code) and common things such as Boyer-Moore search +objects. For full documentation see the home page. +END PYTHON-PACKAGE-INFO +""" +from TextTools import * +from TextTools import __version__ + +### Make the types pickleable: + +# Shortcuts for pickle (reduces the pickle's length) +def _BMS(match,translate): + return BMS(match,translate) +def _FS(match,translate): + return FS(match,translate) + +# Module init +class modinit: + + ### Register the two types + import copy_reg + def pickle_BMS(so): + return _BMS,(so.match,so.translate) + def pickle_FS(so): + return _FS,(so.match,so.translate) + copy_reg.pickle(BMSType, + pickle_BMS, + _BMS) + copy_reg.pickle(FSType, + pickle_FS, + _FS) + +del modinit diff --git a/intern/python/modules/TextTools/mxTextTools/__init__.py b/intern/python/modules/TextTools/mxTextTools/__init__.py new file mode 100644 index 00000000000..009b7cbd4c7 --- /dev/null +++ b/intern/python/modules/TextTools/mxTextTools/__init__.py @@ -0,0 +1,17 @@ +""" mxTextTools - A tools package for fast text processing. + + (c) Copyright Marc-Andre Lemburg; All Rights Reserved. + See the documentation for further information on copyrights, + or contact the author (mal@lemburg.com). +""" +from mxTextTools import * +from mxTextTools import __version__ + +# +# Make BMS take the role of FS in case the Fast Search object was not built +# +try: + FS +except NameError: + FS = BMS + FSType = BMSType diff --git a/intern/python/modules/VRMLmain.py b/intern/python/modules/VRMLmain.py new file mode 100644 index 00000000000..836c803269e --- /dev/null +++ b/intern/python/modules/VRMLmain.py @@ -0,0 +1,3 @@ +# this file is the entry point for freeze.py + +from Converter import importloader diff --git a/intern/python/modules/beta/Objects.py b/intern/python/modules/beta/Objects.py new file mode 100644 index 00000000000..0ae56870fd6 --- /dev/null +++ b/intern/python/modules/beta/Objects.py @@ -0,0 +1,167 @@ +from Blender import Scene +import Blender.NMesh as _NMesh +import Blender.Material as Material + + +defaultUV = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)] + +FACEFLAGS = _NMesh.Const +DEFAULTFLAGS = FACEFLAGS.LIGHT + FACEFLAGS.DYNAMIC + +curface = None +tessfaces = None + +def error(): + pass +def beginPolygon(): + global curface + global tessfaces + curface = _NMesh.Face() +def endPolygon(): + global curface + global tessfaces + tessfaces.append(curface) +def addVertex(v): + global curface + curface.v.append(v) + curface.uv.append((v.uvco[0], v.uvco[1])) + +class Face: + def __init__(self, vlist): + self.v= vlist + self.uv = [] + self.mode = 0 + +class shadow: + def __setattr__(self, name, val): + setattr(self.data, name, val) + def __getattr__(self, name): + return getattr(self.data, name) + def __repr__(self): + return repr(self.data) + +########################################## +# replacement xMesh (NMesh shadow class) + +class shadowNVert: #shadow NMVert class for the tesselator + def __init__(self): + self.vert = None + self.uv = [] + def __len__(self): + return 3 + def __getitem__(self, i): + return self.vert.co[i] + +def Color(r, g, b, a = 1.0): + return _NMesh.Col(255 * r, 255 * g, 255 * b, 255 * a) + +class shadowNMesh: + def __init__(self, name = None, default_flags = None): + self.scene = Scene.getCurrent() + self.data = _NMesh.GetRaw() + self.name = name + if default_flags: + flags = default_flags + else: + flags = DEFAULTFLAGS + self.flags = flags + self.smooth = 0 + self.faces = [] + try: + import tess + self.tess = tess.Tess(256, beginPolygon, endPolygon, error, addVertex) + except: + #print "couldn't import tesselator" + self.tess = None + self.curface = None + self.tessfaces = [] + self.recalc_normals = 1 + + def __del__(self): + del self.data + + def __getattr__(self, name): + if name == 'vertices': + return self.data.verts + else: + return getattr(self.data, name) + + def __repr__(self): + return "Mesh: %d faces, %d vertices" % (len(self.faces), len(self.verts)) + def toNMFaces(self, ngon): + # This should be a Publisher only feature...once the tesselation + # is improved. The GLU tesselator of Mesa < 4.0 is crappy... + if not self.tess: + return [] # no faces converted + import tess + i = 0 + global tessfaces + tessfaces = [] + tess.beginPolygon(self.tess) + for v in ngon.v: + if len(ngon.uv) == len(ngon.v): + v.uvco = ngon.uv[i] + tess.vertex(self.tess, (v.co[0], v.co[1], v.co[2]), v) + i += 1 + tess.endPolygon(self.tess) + return tessfaces + + def hasFaceUV(self, true): + self.data.hasFaceUV(true) + + def addVert(self, v): + vert = _NMesh.Vert(v[0], v[1], v[2]) + self.data.verts.append(vert) + return vert + + def addFace(self, vlist, flags = None, makedefaultUV = 0): + n = len(vlist) + if n > 4: + face = Face(vlist) + else: + face = _NMesh.Face() + for v in vlist: + face.v.append(v) + if makedefaultUV: + face.uv = defaultUV[:n] + self.faces.append(face) + # turn on default flags: + if not flags: + face.mode = self.flags + else: + face.mode = flags + return face + + def write(self): + from Blender import Object + # new API style: + self.update() + ob = Object.New(Object.Types.MESH) # create object + ob.link(self.data) # link mesh data to it + self.scene.link(ob) + return ob + + def update(self): + from Blender.Types import NMFaceType + smooth = self.smooth + for f in self.faces: + if type(f) == NMFaceType: + f.smooth = smooth + self.data.faces.append(f) + f.materialIndex = 0 + else: #it's a NGON (shadow face) + faces = self.toNMFaces(f) + for nf in faces: + nf.smooth = smooth + nf.materialIndex = 0 + self.data.faces.append(nf) + + if not self.name: + self.name = "Mesh" + + def assignMaterial(self, material): + self.data.materials = [material._object] + +Mesh = shadowNMesh +Vert = shadowNVert + diff --git a/intern/python/modules/beta/Scenegraph.py b/intern/python/modules/beta/Scenegraph.py new file mode 100644 index 00000000000..388beeb7b11 --- /dev/null +++ b/intern/python/modules/beta/Scenegraph.py @@ -0,0 +1,182 @@ + +"""This is a basic scenegraph module for Blender +It contains low level API calls...""" + +# (c) 2001, Martin Strubel // onk@section5.de + +from utils import quat #quaternions + +from Blender import Object, Lamp, Scene + + +TOLERANCE = 0.01 + +def uniform_scale(vec): + v0 = vec[0] + d = abs(vec[1] - v0) + if d > TOLERANCE: + return 0 + d = abs(vec[2] - v0) + if d > TOLERANCE: + return 0 + return v0 + +class Transform: + """An abstract transform, containing translation, rotation and scale information""" + def __init__(self): + self.scale = (1.0, 1.0, 1.0) + self.translation = (0.0, 0.0, 0.0) + self.rotation = quat.Quat() + self.scaleOrientation = quat.Quat() # axis, angle + self.parent = None + def __mul__(self, other): + s = uniform_scale(self.scale) + if not s: + raise RuntimeError, "non uniform scale, can't multiply" + t = Transform() + sc = other.scale + t.scale = (s * sc[0], s * sc[1], s * sc[2]) + t.rotation = self.rotation * other.rotation + tr = s * apply(quat.Vector, other.translation) + t.translation = self.rotation.asMatrix() * tr + self.translation + return t + def getLoc(self): + t = self.translation + return (t[0], t[1], t[2]) # make sure it's a tuple..silly blender + def calcRotfromAxis(self, axisrotation): + self.rotation = apply(quat.fromRotAxis,axisrotation) + def getRot(self): + return self.rotation.asEuler() + def getSize(self): + s = self.scale + return (s[0], s[1], s[2]) + def __repr__(self): + return "Transform: rot: %s loc:%s" % (self.getRot(), self.getLoc()) + def copy(self): + "returns copy of self" + t = Transform() + t.scale = self.scale + t.translation = self.translation + t.rotation = self.rotation + t.scaleOrientation = self.scaleOrientation + return t + +class BID: + "Blender named Object ID" + def __init__(self, name): + self.name = name + self.data = None + +class BScene: + def __init__(self, name = None): + from Blender import Scene + self.dict = {'Image': {}, 'Object':{}, 'Mesh' : {}} + self.name = name + def __getitem__(self, name): + return self.dict[name] + def __setitem__(self, name, val): + self.dict[name] = val + def has_key(self, name): + if self.dict.has_key(name): + return 1 + else: + return 0 + def getnewID(self, templ): + n = 0 + name = templ + while self.dict.has_key(name): + n += 1 + name = "%s.%03d" % (templ, n) + return name + +class BSGNode: + "Blender Scenegraph node" + isRoot = 0 + def __init__(self, object = None, type = "", name = ""): + self.type = type + self.name = name + self.children = [] + self.level = 0 + self.object = object + def addChildren(self, children): + self.children += children + def traverse(self, visitor): + ret = visitor() + for c in self.children: + c.traverse(visitor) + return ret + def setDepth(self, level): + self.level = level + for c in self.children: + c.setDepth(level + 1) + def update(self): + ob.name = self.name + def __repr__(self): + l = self.level + children = "" + pre = l * ' ' + return "\n%s%s [%s] ->%s" % (pre, self.name, self.type, self.children) + +class ObjectNode(BSGNode): + def __init__(self, object = None, type = "", name = ""): + self.transform = Transform() + self.scene = Scene.getCurrent() + BSGNode.__init__(self, object, type, name) + def makeParent(self, child): + self.child = parent + child.parent = self + def clone(self): + ob = self.object + newob = ob.copy() + self.scene.link(newob) + new = ObjectNode(newob) + new.transform = self.transform.copy() + return new + def insert(self, child): + self.children.append(child) + child.level = self.level + 1 + ob = child.object + self.object.makeParent([ob], 1, 1) + # first parent, THEN set local transform + child.update() + def applyTransform(self, tf): + self.transform = tf * self.transform + def update(self): + ob = self.object + t = self.transform + ob.loc = t.getLoc() + ob.size = t.getSize() + ob.rot = t.getRot() + ob.name = self.name + +def NodefromData(ob, type, name): + new = ObjectNode(None, type, name) + if ob: + obj = ob + else: + obj = Object.New(type) + Scene.getCurrent().link(obj) + if not obj: + raise RuntimeError, "FATAL: could not create object" + new.object= obj + new.object.name = name + #new.fromData(ob) + return new + +class RootNode(ObjectNode): + """stupid simple scenegraph prototype""" + level = 0 + isRoot = 1 + type = 'Root' + name = 'ROOT' + + def __init__(self, object = None, type = "", name = ""): + from Blender import Scene + self.transform = Transform() + BSGNode.__init__(self, object, type, name) + self.scene = Scene.getCurrent() + def insert(self, child): + child.update() + self.children.append(child) + def update(self): + self.scene.update() diff --git a/intern/python/modules/beta/__init__.py b/intern/python/modules/beta/__init__.py new file mode 100644 index 00000000000..4ceb9fd97a1 --- /dev/null +++ b/intern/python/modules/beta/__init__.py @@ -0,0 +1 @@ +__all__ = ["Scenegraph", "Objects"] diff --git a/intern/python/modules/blenderos.py b/intern/python/modules/blenderos.py new file mode 100644 index 00000000000..d093388d88f --- /dev/null +++ b/intern/python/modules/blenderos.py @@ -0,0 +1,24 @@ +# This is the built in Blender emulation module for os.py +# not all features are implemented yet... + +import Blender.sys as bsys + +sep = bsys.dirsep # path separator ('/' or '\') + +class Path: + def dirname(self, name): + return bsys.dirname(name) + def join(self, a, *p): + dirsep = bsys.dirsep + path = a + for b in p: + if b[:1] == dirsep: + path = b + elif path == '' or path[-1:] == dirsep: + path = path + b + else: + path = path + dirsep + b + return path + +path = Path() + diff --git a/intern/python/modules/mcf/__init__.py b/intern/python/modules/mcf/__init__.py new file mode 100644 index 00000000000..a553f20ba1c --- /dev/null +++ b/intern/python/modules/mcf/__init__.py @@ -0,0 +1,6 @@ +#mcf 'vendor' packages + +#These packages are free software, provided without warranty or +#guarantee, if you use them, you must agree to use them at your +#own risk. Please see the file license.txt for full license +#details. diff --git a/intern/python/modules/mcf/utils/__init__.py b/intern/python/modules/mcf/utils/__init__.py new file mode 100644 index 00000000000..156e4dbe16b --- /dev/null +++ b/intern/python/modules/mcf/utils/__init__.py @@ -0,0 +1,6 @@ +''' +mcf.utils package + + +''' + diff --git a/intern/python/modules/mcf/utils/collapse.py b/intern/python/modules/mcf/utils/collapse.py new file mode 100644 index 00000000000..25da50c2adb --- /dev/null +++ b/intern/python/modules/mcf/utils/collapse.py @@ -0,0 +1,169 @@ +''' +Destructive Functions for "collapsing" Sequences into single levels + +>>> from mcf.utils import collapse + +>>> collapse.test([[[1],[2,3]],[[]],[4],5,[6]]) + +[1, 2, 3, 4, 5, 6] # note that is the same root list + +>>> collapse.collapse2([[[1],[2,3]],[[]],(4,()),(5,),[6]]) + +[1, 2, 3, 4, 5, 6] # note is the same root list +''' +import copy, types, sys +from types import ListType, TupleType # this now only supports the obsolete stuff... + +def hyperCollapse( inlist, allowedmap, type=type, list=list, itype=types.InstanceType, maxint= sys.maxint): + ''' + Destructively flatten a mixed hierarchy to a single level. + Non-recursive, many speedups and obfuscations by Tim Peters :) + ''' + try: + # for every possible index + for ind in xrange( maxint): + # while that index currently holds a list + expandable = 1 + while expandable: + expandable = 0 + if allowedmap.has_key( type(inlist[ind]) ): + # expand that list into the index (and subsequent indicies) + inlist[ind:ind+1] = list( inlist[ind]) + expandable = 1 + + # alternately you could iterate through checking for isinstance on all possible + # classes, but that would be very slow + elif type( inlist[ind] ) is itype and allowedmap.has_key( inlist[ind].__class__ ): + # here figure out some way to generically expand that doesn't risk + # infinite loops... + templist = [] + for x in inlist[ind]: + templist.append( x) + inlist[ind:ind+1] = templist + expandable = 1 + except IndexError: + pass + return inlist + + +def collapse(inlist, type=type, ltype=types.ListType, maxint= sys.maxint): + ''' + Destructively flatten a list hierarchy to a single level. + Non-recursive, and (as far as I can see, doesn't have any + glaring loopholes). + Further speedups and obfuscations by Tim Peters :) + ''' + try: + # for every possible index + for ind in xrange( maxint): + # while that index currently holds a list + while type(inlist[ind]) is ltype: + # expand that list into the index (and subsequent indicies) + inlist[ind:ind+1] = inlist[ind] + #ind = ind+1 + except IndexError: + pass + return inlist + +def collapse_safe(inlist): + ''' + As collapse, but works on a copy of the inlist + ''' + return collapse( inlist[:] ) + +def collapse2(inlist, ltype=(types.ListType, types.TupleType), type=type, maxint= sys.maxint ): + ''' + Destructively flatten a list hierarchy to a single level. + Will expand tuple children as well, but will fail if the + top level element is not a list. + Non-recursive, and (as far as I can see, doesn't have any + glaring loopholes). + ''' + ind = 0 + try: + while 1: + while type(inlist[ind]) in ltype: + try: + inlist[ind:ind+1] = inlist[ind] + except TypeError: + inlist[ind:ind+1] = list(inlist[ind]) + ind = ind+1 + except IndexError: + pass + return inlist + +def collapse2_safe(inlist): + ''' + As collapse2, but works on a copy of the inlist + ''' + return collapse( list(inlist) ) + +def old_buggy_collapse(inlist): + '''Always return a one-level list of all the non-list elements in listin, + rewritten to be non-recursive 96-12-28 Note that the new versions work + on the original list, not a copy of the original.''' + if type(inlist)==TupleType: + inlist = list(inlist) + elif type(inlist)!=ListType: + return [inlist] + x = 0 + while 1: + try: + y = inlist[x] + if type(y) == ListType: + ylen = len(y) + if ylen == 1: + inlist[x] = y[0] + if type(inlist[x]) == ListType: + x = x - 1 # need to collapse that list... + elif ylen == 0: + del(inlist[x]) + x = x-1 # list has been shortened + else: + inlist[x:x+1]=y + x = x+1 + except IndexError: + break + return inlist + + +def old_buggy_collapse2(inlist): + '''As collapse, but also collapse tuples, rewritten 96-12-28 to be non-recursive''' + if type(inlist)==TupleType: + inlist = list(inlist) + elif type(inlist)!=ListType: + return [inlist] + x = 0 + while 1: + try: + y = inlist[x] + if type(y) in [ListType, TupleType]: + ylen = len(y) + if ylen == 1: + inlist[x] = y[0] + if type(inlist[x]) in [ListType,TupleType]: + x = x-1 #(to deal with that element) + elif ylen == 0: + del(inlist[x]) + x = x-1 # list has been shortened, will raise exception with tuples... + else: + inlist[x:x+1]=list(y) + x = x+1 + except IndexError: + break + return inlist + + +def oldest_buggy_collapse(listin): + 'Always return a one-level list of all the non-list elements in listin' + if type(listin) == ListType: + return reduce(lambda x,y: x+y, map(collapse, listin), []) + else: return [listin] + +def oldest_buggy_collapse2(seqin): + + if type(seqin) in [ListType, TupleType]: + return reduce(lambda x,y: x+y, map(collapse2, seqin), []) + else: + return [seqin] + diff --git a/intern/python/modules/mcf/utils/copy_extend.py b/intern/python/modules/mcf/utils/copy_extend.py new file mode 100644 index 00000000000..687564cf12c --- /dev/null +++ b/intern/python/modules/mcf/utils/copy_extend.py @@ -0,0 +1,83 @@ +''' +Module to allow for "copying" Numeric arrays, +(and thereby also matrices and userarrays) +standard arrays, classes and modules +(last two are not actually copied, but hey :) ). + +Could do approximately the same thing with +copy_reg, but would be inefficient because +of passing the data into and out of strings. + +To use, just import this module. +''' +# altered 98.11.05, moved copy out of NUMPY test +import copy +try: # in case numpy not installed + import Numeric + def _numpyarray_copy(somearray, memo=None): + ''' + Simple function for getting a copy of a NUMPY array + ''' + if memo == None: + memo = {} # yeah, I know, not _really_ necessary + # see if already done this item, return the copy if we have... + d = id(somearray) + try: + return memo[d] + except KeyError: + pass + temp = Numeric.array(somearray, copy=1) + memo[d] = temp + return temp + # now make it available to the copying functions + copy._copy_dispatch[Numeric.ArrayType] = _numpyarray_copy + copy._deepcopy_dispatch[Numeric.ArrayType] = _numpyarray_copy +except ImportError: # Numeric not installed... + pass + +try: # in case array not installed + import array + def _array_copy(somearray, memo = None): + ''' + Simple function for getting a copy of a standard array. + ''' + if memo == None: + memo = {} # yeah, I know, not _really_ necessary + # see if already done this item, return the copy if we have... + d = id(somearray) + try: + return memo[d] + except KeyError: + pass + newarray = somearay[:] + memo[d] = newarray + return newarray + + # now make it available to the copying functions + copy._copy_dispatch[ array.ArrayType ] = _array_copy + copy._deepcopy_dispatch[ array.ArrayType ] = _array_copy +except ImportError: + pass + +import types + +def _module_copy(somemodule, memo = None): + ''' + Modules we will always treat as themselves during copying??? + ''' + return somemodule + +# now make it available to the copying functions +copy._copy_dispatch[ types.ModuleType ] = _module_copy +copy._deepcopy_dispatch[ types.ModuleType ] = _module_copy + +def _class_copy(someclass, memo=None): + ''' + Again, classes are considered immutable, they are + just returned as themselves, not as new objects. + ''' + return someclass + +# now make it available to the copying functions +#copy._copy_dispatch[ types.ClassType ] = _class_copy +copy._deepcopy_dispatch[ types.ClassType ] = _class_copy diff --git a/intern/python/modules/mcf/utils/cpickle_extend.py b/intern/python/modules/mcf/utils/cpickle_extend.py new file mode 100644 index 00000000000..aaca41d51fb --- /dev/null +++ b/intern/python/modules/mcf/utils/cpickle_extend.py @@ -0,0 +1,190 @@ +''' +Extend cpickle storage to include modules, and builtin functions/methods + +To use, just import this module. +''' +import copy_reg + +### OBJECTS WHICH ARE RESTORED THROUGH IMPORTS +# MODULES +def pickle_module(module): + ''' + Store a module to a pickling stream, must be available for + reimport during unpickling + ''' + return unpickle_imported_code, ('import %s'%module.__name__, module.__name__) + +# FUNCTIONS, METHODS (BUILTIN) +def pickle_imported_code(funcmeth): + ''' + Store a reference to an imported element (such as a function/builtin function, + Must be available for reimport during unpickling. + ''' + module = _whichmodule(funcmeth) + return unpickle_imported_code, ('from %s import %s'%(module.__name__,funcmeth.__name__),funcmeth.__name__) + +import types, regex +import_filter = regex.compile('''\(from [A-Za-z0-9_\.]+ \)?import [A-Za-z0-9_\.]+''') # note the limitations on whitespace +getattr_filter = regex.compile('''[A-Za-z0-9_\.]+''') # note we allow you to use x.y.z here + +# MODULES, AND FUNCTIONS +def unpickle_imported_code(impstr,impname): + ''' + Attempt to load a reference to a module or other imported code (such as functions/builtin functions) + ''' + if import_filter.match(impstr) != len(impstr) or getattr_filter.match(impname)!= len(impname): + import sys + sys.stderr.write('''Possible attempt to smuggle arbitrary code into pickle file (see module cpickle_extend).\nPassed code was %s\n%s\n'''%(impstr,impname)) + del(sys) + else: + ns = {} + try: + exec (impstr) in ns # could raise all sorts of errors, of course, and is still dangerous when you have no control over the modules on your system! Do not allow for untrusted code!!! + return eval(impname, ns) + except: + import sys + sys.stderr.write('''Error unpickling module %s\n None returned, will likely raise errors.'''%impstr) + return None + +# Modules +copy_reg.pickle(type(regex),pickle_module,unpickle_imported_code) +# builtin functions/methods +copy_reg.pickle(type(regex.compile),pickle_imported_code, unpickle_imported_code) + +del(regex) # to keep the namespace neat as possible + +### INSTANCE METHODS +''' +The problem with instance methods is that they are almost always +stored inside a class somewhere. We really need a new type: reference +that lets us just say "y.this" + +We also need something that can reliably find burried functions :( not +likely to be easy or clean... + +then filter for x is part of the set +''' +import new + +def pickle_instance_method(imeth): + ''' + Use the (rather surprisingly clean) internals of + the method to store a reference to a method. Might + be better to use a more general "get the attribute + 'x' of this object" system, but I haven't written that yet :) + ''' + klass = imeth.im_class + funcimp = _imp_meth(imeth) + self = imeth.im_self # will be None for UnboundMethodType + return unpickle_instance_method, (funcimp,self,klass) +def unpickle_instance_method(funcimp,self,klass): + ''' + Attempt to restore a reference to an instance method, + the instance has already been recreated by the system + as self, so we just call new.instancemethod + ''' + funcimp = apply(unpickle_imported_code, funcimp) + return new.instancemethod(func,self,klass) + +copy_reg.pickle(types.MethodType, pickle_instance_method, unpickle_instance_method) +copy_reg.pickle(types.UnboundMethodType, pickle_instance_method, unpickle_instance_method) + +### Arrays +try: + import array + LittleEndian = array.array('i',[1]).tostring()[0] == '\001' + def pickle_array(somearray): + ''' + Store a standard array object, inefficient because of copying to string + ''' + return unpickle_array, (somearray.typecode, somearray.tostring(), LittleEndian) + def unpickle_array(typecode, stringrep, origendian): + ''' + Restore a standard array object + ''' + newarray = array.array(typecode) + newarray.fromstring(stringrep) + # floats are always big-endian, single byte elements don't need swapping + if origendian != LittleEndian and typecode in ('I','i','h','H'): + newarray.byteswap() + return newarray + copy_reg.pickle(array.ArrayType, pickle_array, unpickle_array) +except ImportError: # no arrays + pass + +### NUMPY Arrays +try: + import Numeric + LittleEndian = Numeric.array([1],'i').tostring()[0] == '\001' + def pickle_numpyarray(somearray): + ''' + Store a numpy array, inefficent, but should work with cPickle + ''' + return unpickle_numpyarray, (somearray.typecode(), somearray.shape, somearray.tostring(), LittleEndian) + def unpickle_numpyarray(typecode, shape, stringval, origendian): + ''' + Restore a numpy array + ''' + newarray = Numeric.fromstring(stringval, typecode) + Numeric.reshape(newarray, shape) + if origendian != LittleEndian and typecode in ('I','i','h','H'): + # this doesn't seem to work correctly, what's byteswapped doing??? + return newarray.byteswapped() + else: + return newarray + copy_reg.pickle(Numeric.ArrayType, pickle_numpyarray, unpickle_numpyarray) +except ImportError: + pass + +### UTILITY FUNCTIONS +classmap = {} +def _whichmodule(cls): + """Figure out the module in which an imported_code object occurs. + Search sys.modules for the module. + Cache in classmap. + Return a module name. + If the class cannot be found, return __main__. + Copied here from the standard pickle distribution + to prevent another import + """ + if classmap.has_key(cls): + return classmap[cls] + clsname = cls.__name__ + for name, module in sys.modules.items(): + if name != '__main__' and \ + hasattr(module, clsname) and \ + getattr(module, clsname) is cls: + break + else: + name = '__main__' + classmap[cls] = name + return name + +import os, string, sys + +def _imp_meth(im): + ''' + One-level deep recursion on finding methods, i.e. we can + find them only if the class is at the top level. + ''' + fname = im.im_func.func_code.co_filename + tail = os.path.splitext(os.path.split(fname)[1])[0] + ourkeys = sys.modules.keys() + possibles = filter(lambda x,tail=tail: x[-1] == tail, map(string.split, ourkeys, ['.']*len(ourkeys))) + + # now, iterate through possibles to find the correct class/function + possibles = map(string.join, possibles, ['.']*len(possibles)) + imp_string = _search_modules(possibles, im.im_func) + return imp_string + +def _search_modules(possibles, im_func): + for our_mod_name in possibles: + our_mod = sys.modules[our_mod_name] + if hasattr(our_mod, im_func.__name__) and getattr(our_mod, im_func.__name__).im_func is im_func: + return 'from %s import %s'%(our_mod.__name__, im_func.__name__), im_func.__name__ + for key,val in our_mod.__dict__.items(): + if hasattr(val, im_func.__name__) and getattr(val, im_func.__name__).im_func is im_func: + return 'from %s import %s'%(our_mod.__name__,key), '%s.%s'%(key,im_func.__name__) + raise '''No import string calculable for %s'''%im_func + + diff --git a/intern/python/modules/mcf/utils/dictbool.py b/intern/python/modules/mcf/utils/dictbool.py new file mode 100644 index 00000000000..cd549b7a681 --- /dev/null +++ b/intern/python/modules/mcf/utils/dictbool.py @@ -0,0 +1,80 @@ +''' +DictBool: +Simplistic (and slow) implementation of Boolean operations for +dictionaries... really these should be implemented in C, but I +can't do that till I have MSVC++, which I don't really want to +buy... this will have to do in the meantime. + +>>> from mcf.utils import dictbool + +>>> a = {1:2}; b = {2:3}; c={4:5,6:7,8:9,1:5} + +>>> dictbool.union(a,b,c) # overwrite a with b and the result with c + +{1: 5, 2: 3, 4: 5, 8: 9, 6: 7} + +>>> dictbool.collectunion(a,b,c) # collect all possible for each key + +{1: [2, 5], 2: [3], 4: [5], 8: [9], 6: [7]} + +>>> dictbool.intersect(a,b,c) # no common elements in all three + +{} + +>>> dictbool.intersect(a,c) # one element is common to both + +{1: [2, 5]} +''' + +def union(*args): + ''' + Build a new dictionary with the key,val from all args, + first overwritten by second, overwritten by third etc. + Rewritten for Python 1.5 on 98.03.31 + ''' + temp = {} + for adict in args: + # following is the 1.5 version + temp.update(adict) +# for key,val in adict.items(): +# temp[key] = val + return temp + +def collectunion(*args): + ''' + As union, save instead of overwriting, all vals are + returned in lists, and duplicates are appended to those + lists. + ''' + temp = {} + for adict in args: + for key,val in adict.items(): + try: + temp[key].append(val) + except KeyError: + temp[key] = [val] + return temp + +def intersect(*args): + ''' + Build a new dictionary with those keys common to all args, + the vals of the new dict are lists of length len(args), where + list[ind] is the value of args[ind] for that key. + ''' + args = map(lambda x: (len(x),x), args) + args.sort() + temp = {} + master = args[0][1] + rest = map(lambda x: x[1], args[1:]) + for var,val in master.items(): + tempval = [val] + for slave in rest: + try: + tempval.append(slave[var]) + except KeyError: + tempval = None + break + if tempval: + temp[var] = tempval + return temp + diff --git a/intern/python/modules/mcf/utils/dsort.py b/intern/python/modules/mcf/utils/dsort.py new file mode 100644 index 00000000000..cd6ad6b6c32 --- /dev/null +++ b/intern/python/modules/mcf/utils/dsort.py @@ -0,0 +1,91 @@ +nullval = (1,) + +class DSort: + ''' + A "dependency" sorting class, used to order elements + according to declared "dependencies" (many-to-one relationships) + Is not a beautiful algo, but it works (or seems to) + Requires hashable values for all elements. + + This is a quick hack, use at your own risk! + + Basic usage: + Create a DSort mysorter + for each element q which is part of the set to sort, call: + mysorter.rule( dsort.nullval, q) + # this is not strictly necessary for elements which are + # dependent on other objects, but it is necessary for + # those which are not. Generally it's easiest to call + # the null rule for each element. + for each rule x depends on y, call: + mysorter.rule( x, y) + when _all_ rules are entered, call + try: + sortedlist = mysorter.sort() + except ValueError: + handle recursive dependencies here... + + + For an example of real-life use, see the VRML lineariser. + + ''' + def __init__(self, recurseError=None ): + self.dependon = {nullval:[0]} + self.recurseError = recurseError + def rule( self, depon, deps): + ''' + Register a "rule". Both elements must be hashable values. + See the class' documentation for usage. + ''' +# print '''registering rule:''', depon, deps + if self.dependon.has_key( deps ) and depon is not nullval: + self.dependon[ deps ].append( depon ) + elif depon is not nullval: + self.dependon[ deps ] = [-1, depon] + elif not self.dependon.has_key( deps ): + self.dependon[ deps ] = [-1 ] + def sort( self ): + ''' + Get the sorted results as a list + ''' + for key, value in self.dependon.items(): + self._dsort( key, value) + temp = [] + for key, value in self.dependon.items(): + temp.append( (value[0], key) ) + temp.sort() + temp.reverse() + temp2 = [] + for x,y in temp: + temp2.append( y ) + # following adds the elements with no dependencies + temp2[len(temp2):] = self.dependon[ nullval ][1:] + return temp2 + def _dsort( self, key, value ): + if value[0] == -2: + if self.recurseError: + raise ValueError, '''Dependencies were recursive!''' + else: + if __debug__: + print '''Recursive dependency discovered and ignored in dsort.Dsort._dsort on %s:%s'''%(key, value) + return 1 # we know it has at least one reference... + elif value[0] == -1: # haven't yet calculated this rdepth + value[0] = -2 + tempval = [0] + for x in value[1:]: + try: + tempval.append( 1 + self._dsort( x, self.dependon[x]) ) + except KeyError: + self.dependon[ nullval ].append( x ) # is an unreferenced element + tempval.append( 1 ) + value[0] = max( tempval ) + return value[0] + else: + return value[0] +''' +from mcf.utils import dsort +>>> x = dsort.DSort() +>>> map( x.rule, [1,2,2,4,5,4], [2,3,4,5,6,3] ) +[None, None, None, None, None, None] +>>> x.sort() +'''
\ No newline at end of file diff --git a/intern/python/modules/mcf/utils/dummy.py b/intern/python/modules/mcf/utils/dummy.py new file mode 100644 index 00000000000..fb68c4049bf --- /dev/null +++ b/intern/python/modules/mcf/utils/dummy.py @@ -0,0 +1,91 @@ +''' +Dummy Class, intended as an abstract class for the creation +of base/builtin classes with slightly altered functionality +uses _base as the name of an instance of the base datatype, +mapping all special functions to that name. + +>>> from mcf.utils import dummy + +>>> j = dummy.Dummy({}) + +>>> j['this'] = 23 + +>>> j + +{'this': 23} + +>>> class example(dummy.Dummy): + +... def __repr__(self): + +... return '<example: %s>'%`self._base` + +>>> k = example([]) + +>>> k # uses the __repr__ function + +<example: []> + +>>> k.append # finds the attribute of the _base + +<built-in method append of list object at 501830> + +''' +import types, copy + +class Dummy: + 'Abstract class for slightly altering functionality of objects (including builtins)' + def __init__(self, val=None): + 'Initialisation, should be overridden' + if val and type(val)== types.InstanceType and hasattr(val, '_base'): + # Dict is used because subclasses often want to override + # the setattr function + self.__dict__['_base']=copy.copy(val.__dict__['_base']) + else: + self.__dict__['_base'] = val + def __repr__(self): + 'Return a string representation' + return repr(self._base) + def __str__(self): + 'Convert to a string' + return str(self._base) + def __cmp__(self,other): + 'Compare to other value' + # altered 98.03.17 from if...elif...else statement + return cmp(self._base, other) + def __getitem__(self, key): + 'Get an item by index' + return self._base[key] + def __setitem__(self, key, val): + 'Set an item by index' + self._base[key]=val + def __len__(self): + 'return the length of the self' + return len(self._base) + def __delitem__(self, key): + 'remove an item by index' + del(self._base[key]) + def __getslice__(self, i, j): + 'retrieve a slice by indexes' + return self._base[i:j] + def __setslice__(self, i, j, val): + 'set a slice by indexes to values' + self._base[i:j]=val + def __delslice__(self, i, j): + 'remove a slice by indexes' + del(self._base[i:j]) + def __nonzero__(self): + if self._base: + return 1 + else: + return 0 + def __getattr__(self, attr): + 'find an attribute when normal lookup fails, will raise a KeyError if missing _base attribute' + try: + return getattr( self.__dict__['_base'], attr) + except (AttributeError, KeyError): + try: + return self.__dict__['_base'][attr] + except (KeyError,TypeError): + pass + raise AttributeError, attr diff --git a/intern/python/modules/mcf/utils/err.py b/intern/python/modules/mcf/utils/err.py new file mode 100644 index 00000000000..3c6591a6873 --- /dev/null +++ b/intern/python/modules/mcf/utils/err.py @@ -0,0 +1,37 @@ +''' +err.py Encapsulated writing to sys.stderr + +The idea of this module is that, for a GUI system (or a more advanced UI), +you can just import a different err module (or object) and keep +your code the same. (For instance, you often want a status window +which flashes warnings and info, and have error messages pop up an +alert to get immediate attention. +''' + +import sys + +def err(message, Code=0): + ''' + report an error, with an optional error code + ''' + if Code: + sys.stderr.write('Error #%i: %s\n'%(Code,message)) + else: + sys.stderr.write('Error: %s\n'%message) +def warn(message, Code=0): + ''' + report a warning, with an optional error code + ''' + if Code: + sys.stderr.write('Warning #%i: %s\n'%(Code,message)) + else: + sys.stderr.write('Warning: %s\n'%message) +def info(message, Code=0): + ''' + report information/status, with an optional error code + ''' + if Code: + sys.stderr.write('Info #%i: %s\n'%(Code,message)) + else: + sys.stderr.write('Info: %s\n'%message) + diff --git a/intern/python/modules/mcf/utils/extpkl.py b/intern/python/modules/mcf/utils/extpkl.py new file mode 100644 index 00000000000..8ae52969281 --- /dev/null +++ b/intern/python/modules/mcf/utils/extpkl.py @@ -0,0 +1,19 @@ +''' +Make either cPickle or pickle available as the virtual +module mcf.utils.pickle. This allows you to use a single +import statement: + + from mcf.utils import extpkl, pickle + +and then use that pickle, knowing that you have the best +available pickling engine. +''' +defaultset = ('import cPickle', 'cPickle') +import sys, mcf.utils +from mcf.utils import cpickle_extend +try: + import cPickle + pickle = cPickle +except: + import pickle +sys.modules['mcf.utils.pickle'] = mcf.utils.pickle = pickle diff --git a/intern/python/modules/mcf/utils/fileassociation.py b/intern/python/modules/mcf/utils/fileassociation.py new file mode 100644 index 00000000000..55fd9735bfb --- /dev/null +++ b/intern/python/modules/mcf/utils/fileassociation.py @@ -0,0 +1,65 @@ +### WARNING: +# I don't have a clue what I'm doing here! + +import win32api +### Following is the "normal" approach, +### but it requires loading the entire win32con file (which is big) +### for two values... +##import win32con +##HKEY_CLASSES_ROOT = win32con.HKEY_CLASSES_ROOT +##REG_SZ = win32con.REG_SZ + +### These are the hard-coded values, should work everywhere as far as I know... +HKEY_CLASSES_ROOT = 0x80000000 +REG_SZ= 1 + +def associate( extension, filetype, description="", commands=(), iconfile="" ): + '''Warning: I don't have a clue what I'm doing here! + extension -- extension including "." character, e.g. .proc + filetype -- formal name, no spaces allowed, e.g. SkeletonBuilder.RulesFile + description -- human-readable description of the file type + commands -- sequence of (command, commandline), e.g. (("Open", "someexe.exe %1"),) + iconfile -- optional default icon file for the filetype + ''' + win32api.RegSetValue( + HKEY_CLASSES_ROOT, + extension, + REG_SZ, + filetype + ) + if description: + win32api.RegSetValue( + HKEY_CLASSES_ROOT , + filetype, + REG_SZ, + description + ) + if iconfile: + win32api.RegSetValue( + HKEY_CLASSES_ROOT , + "%(filetype)s\\DefaultIcon" % locals(), + REG_SZ, + iconfile + ) + for (command, commandline) in commands: + win32api.RegSetValue( + HKEY_CLASSES_ROOT , + "%(filetype)s\\Shell\\%(command)s" % locals(), + REG_SZ, + command, + ) + win32api.RegSetValue( + HKEY_CLASSES_ROOT , + "%(filetype)s\\Shell\\%(command)s\\Command" % locals(), + REG_SZ, + commandline + ) + +if __name__ == "__main__": + associate( + ".proc", + "SkeletonBuilder.Processing", + "SkeletonBuilder Processing File", + (("Open", '''z:\\skeletonbuilder\\skeletonbuilder.exe "%1" %*'''),), + '''z:\\skeletonbuilder\\bitmaps\\skeletonbuildericon.ico''', + )
\ No newline at end of file diff --git a/intern/python/modules/mcf/utils/findourfile.py b/intern/python/modules/mcf/utils/findourfile.py new file mode 100644 index 00000000000..1c70ff0dd70 --- /dev/null +++ b/intern/python/modules/mcf/utils/findourfile.py @@ -0,0 +1,30 @@ +''' +This utility allows a python system to find a file in it's +directory. To do this, you need to pass it a function object from +a module in the correct directory. I know there must be a better +way to do this, but I haven't seen it yet. Incidentally, the +current directory should be _different_ from the module in which +the function is contained, otherwise this function will go off into +the root directory. + +Currently this has to be called with the current directory a directory +other than the directory we're trying to find... need a better solution +for this kind of thing... a python registry would be great :) + +NOTE: as of Python 1.5, this module should be obsolete! As soon as I +have verified that all of my code is fixed, it will be moved to the unused +directories. +''' +import os,sys + +def findourfile(function, filename): + ''' + Given the function, return a path to the a file in the + same directory with 'filename'. We also let the caller + know if the file already exists. + ''' + ourfilename = os.path.split(function.func_code.co_filename)[0]+os.sep+filename + exists = os.path.exists(ourfilename) + return (exists,ourfilename) + + diff --git a/intern/python/modules/mcf/utils/hier_rx.py b/intern/python/modules/mcf/utils/hier_rx.py new file mode 100644 index 00000000000..3770f0bab22 --- /dev/null +++ b/intern/python/modules/mcf/utils/hier_rx.py @@ -0,0 +1,201 @@ +''' +Simple Hierarchic Walking functions for use with hierobj-type objects. + +Provide for recurse-safe processing. Currently only provide depth-first +processing, and don't provide means for ignoring branches of the tree +during processing. For an example of breadth-first processing, see +mcf.pars.int.index.indutils. For more complex hierarchic processing, +see the mcf.walker package. + +Originally these functions were only methods of the hierobj class (they +still are methods of it). I've split them out to allow them to be +imported selectively by other classes (some classes will only want +the simple walking functions, and not want to be bothered with the +methods which hierobj uses to keep track of its particular internal +structures. +''' + +def hier_rapply(self, function,arglist=None,argdict={},moreattr = '__childlist__'): + ''' + Safely apply a function to self and all children for + the function's side effects. Discard the return values + that function returns. + + function + function to apply + arglist + (self,)+arglist is the set of arguments passed to function + argdict + passed as namedargs to the function + moreattr + the attribute representing the children of a node + ''' + alreadydone = {} + tobedone = [self] + if arglist or argdict: + if not arglist: arglist=[self] + else: + arglist.insert(0,self) # we could insert anything... self is convenient + while tobedone: + object = tobedone[0] + try: + alreadydone[id(object)] + # We've already processed this object + except KeyError: + # We haven't processed this object + alreadydone[id(object)]=1 + arglist[0]=object + apply(function,tuple(arglist),argdict) + try: + tobedone[1:1]=getattr(object,moreattr) + except AttributeError: + # if the object isn't a hierobj, we don't need to recurse into it. + pass + del(tobedone[0]) + else: # no arglist or argdict + while tobedone: + object = tobedone[0] + try: + alreadydone[id(object)] + # We've already processed this object + except KeyError: + # We haven't processed this object + alreadydone[id(object)]=1 + function(object) + try: + tobedone[1:1]=getattr(object,moreattr) + except AttributeError: + # if the object isn't a hierobj, we don't need to recurse into it. + pass + del(tobedone[0]) +def hier_rreturn(self, function,arglist=None,argdict={},moreattr = '__childlist__'): + ''' + Safely apply a function to self and all children, + collect the results in a list and return. + + function + function to apply + arglist + (self,)+arglist is the set of arguments passed to function + argdict + passed as namedargs to the function + moreattr + the attribute representing the children of a node + ''' + alreadydone = {} + tobedone = [self] + results = [] + if arglist or argdict: + if not arglist: arglist=[self] + else: + arglist.insert(0,self) # or anything you feel like + while tobedone: + object = tobedone[0] + try: + alreadydone[id(object)] + # We've already processed this object + except KeyError: + # We haven't processed this object + alreadydone[id(object)]=1 + arglist[0]=object + results.append(apply(function,tuple(arglist),argdict)) + try: + tobedone[1:1]=getattr(object,moreattr) + except AttributeError: + # if the object isn't a hierobj, we don't need to recurse into it. + pass + del(tobedone[0]) + else: + while tobedone: + object = tobedone[0] + try: + alreadydone[id(object)] + # We've already processed this object + except KeyError: + # We haven't processed this object + alreadydone[id(object)]=1 + results.append(function(object)) + try: + tobedone[1:1]=getattr(object,moreattr) + except AttributeError: + # if the object isn't a hierobj, we don't need to recurse into it. + pass + del(tobedone[0]) + return results +def hier_rgetattr(self, attrname, multiple=1, moreattr = '__childlist__'): + ''' + Recursively collect the values for attrname and + return as a list. + + attrname + attribute to collect + arglist + (self,)+arglist is the set of arguments passed to function + argdict + passed as namedargs to the function + moreattr + the attribute representing the children of a node + ''' + alreadydone = {} + tobedone = [self] + results = [] + while tobedone: + object = tobedone[0] + try: + alreadydone[id(object)] + # We've already processed this object + except KeyError: + # We haven't processed this object + alreadydone[id(object)]=1 + try: + if multiple: + results.append(getattr(object, attrname)) + else: + return getattr(object, attrname) + except AttributeError: + pass + try: + tobedone[1:1]=getattr(object,moreattr) + except AttributeError: + # if the object isn't a hierobj, we don't need to recurse into it. + pass + del(tobedone[0]) + return results +def hier_rmethod(self, methodname,arglist=(),argdict={},moreattr = '__childlist__'): + ''' + return the result of calling every object's method methodname, + as for hier_rreturn otherwise. + + methodname + method to call + arglist + (self,)+arglist is the set of arguments passed to function + argdict + passed as namedargs to the function + moreattr + the attribute representing the children of a node + ''' + + alreadydone = {} + tobedone = [self] + results = [] + while tobedone: + object = tobedone[0] + try: + alreadydone[id(object)] + # We've already processed this object + except KeyError: + # We haven't processed this object + alreadydone[id(object)]=1 + try: + results.append(apply(getattr(object,methodname),arglist,argdict)) + except: + pass + try: + tobedone[1:1]=getattr(object,moreattr) + except AttributeError: + # if the object isn't a hierobj, we don't need to recurse into it. + pass + del(tobedone[0]) + return results + diff --git a/intern/python/modules/mcf/utils/hierdummy.py b/intern/python/modules/mcf/utils/hierdummy.py new file mode 100644 index 00000000000..0cf86e9e0c0 --- /dev/null +++ b/intern/python/modules/mcf/utils/hierdummy.py @@ -0,0 +1,16 @@ +''' +Hierarchic 'Dummy' objects +''' + +import hierobj, dummy + +class HierobjDummy(hierobj.Hierobj,dummy.Dummy): + ''' + An Hierarchic Dummy object, which provides direct access to its + children through object[x] interfaces, allows "index" "count" + etceteras by returning the corresponding attributes of the _base. + ''' + def __init__(self, parent=None, childlist=None): + hierobj.Hierobj.__init__(self, parent, childlist) + self._base = self.__childlist__ #set by init function above + diff --git a/intern/python/modules/mcf/utils/hierobj.py b/intern/python/modules/mcf/utils/hierobj.py new file mode 100644 index 00000000000..7730b4d3ba4 --- /dev/null +++ b/intern/python/modules/mcf/utils/hierobj.py @@ -0,0 +1,133 @@ +''' +Generic Hierarchic Objects Module +Hierobj's store their children (which can be anything) in their +__childlist__ attribute, and provide methods for walking the +hierarchy, either collecting results or not. + +The index function returns an index of the objects (effectively a +flattened copy of the hierarchy) + +97-03-17 Added ability to pass arguments to hier_rapply and hier_rreturn. +97-10-31 Removed dependencies on mcf.store +''' +import copy,types +import singletonlist, hier_rx + +class Hierobj: + ''' + An abstract class which handles hierarchic functions and information + # remade as a DAG 97-04-02, also reduced memory overhead for + hier-r* functions by using while-del-IndexError construct versus + for loop (probably makes it slower though) + If you require a true hierarchy, use the TrueHierobj class below... + ''' + def __init__(self, parent=None, childlist=None): + if parent is None: # passed no parents + self.__dict__['__parent__'] = [] + elif type(parent) == types.ListType: # passed a list of parents + self.__dict__['__parent__'] = parent + else: # passed a single parent + self.__dict__['__parent__'] = [parent] + self.__dict__['__childlist__'] = childlist or [] + for child in self.__childlist__: + try: + child.__parent__.append(self) + except: + pass + # import simple hierarchic processing methods + hier_rapply = hier_rx.hier_rapply + hier_rreturn = hier_rx.hier_rreturn + hier_rgetattr = hier_rx.hier_rgetattr + hier_rmethod = hier_rx.hier_rmethod + + + def hier_addchild(self, child): + ''' + Add a single child to the childlist + ''' + self.__childlist__.append(child) + try: + # Hierobj-aware child + child.__parent__.append(self) # raises error if not hier_obj aware + except (TypeError, AttributeError): + # Non Hierobj-aware child + pass + append = hier_addchild + def hier_remchild(self, child): + ''' + Breaks the child relationship with child, including the + reciprocal parent relationship + ''' + try: + self.__childlist__.remove(child) + try: + child.hier_remparent(self) # if this fails, no problem + except AttributeError: pass + except (AttributeError,ValueError): + return 0 # didn't manage to remove the child + return 1 # succeeded + def hier_remparent(self, parent): + ''' + Normally only called by hier_remchild of the parent, + just removes the parent from the child's parent list, + but leaves child in parent's childlist + ''' + try: + self.__parent__.remove(parent) + except (AttributeError,ValueError): + return 0 + return 1 + def hier_replacewith(self,newel): + ''' + As far as the hierarchy is concerned, the new element + is exactly the same as the old element, it has all + the same children, all the same parents. The old + element becomes completely disconnected from the hierarchy, + but it still retains all of its references + + For every parent, replace this as a child + For every child, replace this as the parent + ''' + for parent in self.__parent__: + try: + parent.hier_replacechild(self, newel) + except AttributeError: + pass + for child in self.__childlist__: + try: + child.hier_replaceparent(self,parent) + except AttributeError: + pass + def hier_replaceparent(self, oldparent, newparent): + ind = self.__parent__.index(oldparent) + self.__parent__[ind] = newparent + def hier_replacechild(self, oldchild, newchild): + ind = self.__childlist__.index(oldchild) + self.__childlist__[ind] = newchild + +class TrueHierobj(Hierobj): + ''' + An inefficient implementation of an Hierobj which limits the + __parent__ attribute to a single element. This will likely be + _slower_ than an equivalent Hierobj. That will have to be fixed + eventually. + ''' + def __init__(self, parent=None, childlist=[]): + if parent is None: # passed no parents + self.__dict__['__parent__'] = singletonlist.SingletonList() + else: # passed a single parent + self.__dict__['__parent__'] = singletonlist.SingletonList(parent) + self.__dict__['__childlist__'] = copy.copy(childlist) + for child in self.__childlist__: + try: + child.__parent__.append(self) + except: + pass + +def index(grove): + ''' + Returns a flattened version of the grove + ''' + return grove.hier_rreturn(lambda x: x) + + diff --git a/intern/python/modules/mcf/utils/in_place_ops.py b/intern/python/modules/mcf/utils/in_place_ops.py new file mode 100644 index 00000000000..7d64f196597 --- /dev/null +++ b/intern/python/modules/mcf/utils/in_place_ops.py @@ -0,0 +1,38 @@ +class inplace: + def __add__( self, num ): + self.base = self.base + num + return self.base + def __sub__( self, num ): + self.base = self.base - num + return self.base + def __init__(self, base ): + self.base = base + def __repr__(self ): + return repr( self.base) + def __str__(self ): + return str( self.base) + __radd__ = __add__ + def __mul__(self, num ): + return self.base * num + def __div__(self, num ): + return self.base / num + def __mod__(self, num ): + return self.base % num + def __neg__(self ): + return - abs( self.base) + def __pos__(self ): + return abs( self.base) + def __abs__(self ): + return abs( self.base ) + def __inv__(self ): + return -self.base + def __lshift__(self, num ): + return self.base << num + def __rshift__(self, num ): + return self.base >> num + def __and__(self, num ): + return self.base and num + def __or__(self, num ): + return self.base or num + def value( self ): + return self.base
\ No newline at end of file diff --git a/intern/python/modules/mcf/utils/namespace.py b/intern/python/modules/mcf/utils/namespace.py new file mode 100644 index 00000000000..819531e10db --- /dev/null +++ b/intern/python/modules/mcf/utils/namespace.py @@ -0,0 +1,224 @@ +''' +NameSpace v0.04: + +A "NameSpace" is an object wrapper around a _base dictionary +which allows chaining searches for an 'attribute' within that +dictionary, or any other namespace which is defined as part +of the search path (depending on the downcascade variable, is +either the hier-parents or the hier-children). + +You can assign attributes to the namespace normally, and read +them normally. (setattr, getattr, a.this = that, a.this) + +I use namespaces for writing parsing systems, where I want to +differentiate between sources (have multiple sources that I can +swap into or out of the namespace), but want to be able to get +at them through a single interface. There is a test function +which gives you an idea how to use the system. + +In general, call NameSpace(someobj), where someobj is a dictionary, +a module, or another NameSpace, and it will return a NameSpace which +wraps up the keys of someobj. To add a namespace to the NameSpace, +just call the append (or hier_addchild) method of the parent namespace +with the child as argument. + +### NOTE: if you pass a module (or anything else with a dict attribute), +names which start with '__' will be removed. You can avoid this by +pre-copying the dict of the object and passing it as the arg to the +__init__ method. + +### NOTE: to properly pickle and/or copy module-based namespaces you +will likely want to do: from mcf.utils import extpkl, copy_extend + +### Changes: + 97.05.04 -- Altered to use standard hierobj interface, cleaned up + interface by removing the "addparent" function, which is reachable + by simply appending to the __parent__ attribute, though normally + you would want to use the hier_addchild or append functions, since + they let both objects know about the addition (and therefor the + relationship will be restored if the objects are stored and unstored) + + 97.06.26 -- Altered the getattr function to reduce the number of + situations in which infinite lookup loops could be created + (unfortunately, the cost is rather high). Made the downcascade + variable harden (resolve) at init, instead of checking for every + lookup. (see next note) + + 97.08.29 -- Discovered some _very_ weird behaviour when storing + namespaces in mcf.store dbases. Resolved it by storing the + __namespace_cascade__ attribute as a normal attribute instead of + using the __unstore__ mechanism... There was really no need to + use the __unstore__, but figuring out how a functions saying + self.__dict__['__namespace_cascade__'] = something + print `self.__dict__['__namespace_cascade__']` can print nothing + is a bit beyond me. (without causing an exception, mind you) + + 97.11.15 Found yet more errors, decided to make two different + classes of namespace. Those based on modules now act similar + to dummy objects, that is, they let you modify the original + instead of keeping a copy of the original and modifying that. + + 98.03.15 -- Eliminated custom pickling methods as they are no longer + needed for use with Python 1.5final + + 98.03.15 -- Fixed bug in items, values, etceteras with module-type + base objects. +''' +import copy, types, string +import hierobj + +class NameSpace(hierobj.Hierobj): + ''' + An hierarchic NameSpace, allows specification of upward or downward + chaining search for resolving names + ''' + def __init__(self, val = None, parents=None, downcascade=1,children=[]): + ''' + A NameSpace can be initialised with a dictionary, a dummied + dictionary, another namespace, or something which has a __dict__ + attribute. + Note that downcascade is hardened (resolved) at init, not at + lookup time. + ''' + hierobj.Hierobj.__init__(self, parents, children) + self.__dict__['__downcascade__'] = downcascade # boolean + if val is None: + self.__dict__['_base'] = {} + else: + if type( val ) == types.StringType: + # this is a reference to a module which has been pickled + val = __import__( val, {},{}, string.split( val, '.') ) + try: + # See if val's a dummy-style object which has a _base + self.__dict__['_base']=copy.copy(val._base) + except (AttributeError,KeyError): + # not a dummy-style object... see if it has a dict attribute... + try: + if type(val) != types.ModuleType: + val = copy.copy(val.__dict__) + except (AttributeError, KeyError): + pass + # whatever val is now, it's going to become our _base... + self.__dict__['_base']=val + # harden (resolve) the reference to downcascade to speed attribute lookups + if downcascade: self.__dict__['__namespace_cascade__'] = self.__childlist__ + else: self.__dict__['__namespace_cascade__'] = self.__parent__ + def __setattr__(self, var, val): + ''' + An attempt to set an attribute should place the attribute in the _base + dictionary through a setitem call. + ''' + # Note that we use standard attribute access to allow ObStore loading if the + # ._base isn't yet available. + try: + self._base[var] = val + except TypeError: + setattr(self._base, var, val) + def __getattr__(self,var): +## print '__getattr__', var + return self.__safe_getattr__(var, {}) # the {} is a stopdict + + def __safe_getattr__(self, var,stopdict): + ''' + We have a lot to do in this function, if the attribute is an unloaded + but stored attribute, we need to load it. If it's not in the stored + attributes, then we need to load the _base, then see if it's in the + _base. + If it's not found by then, then we need to check our resource namespaces + and see if it's in them. + ''' + # we don't have a __storedattr__ or it doesn't have this key... + if var != '_base': + try: + return self._base[var] + except (KeyError,TypeError), x: + try: + return getattr(self._base, var) + except AttributeError: + pass + try: # with pickle, it tries to get the __setstate__ before restoration is complete + for cas in self.__dict__['__namespace_cascade__']: + try: + stopdict[id(cas)] # if succeeds, we've already tried this child + # no need to do anything, if none of the children succeeds we will + # raise an AttributeError + except KeyError: + stopdict[id(cas)] = None + return cas.__safe_getattr__(var,stopdict) + except (KeyError,AttributeError): + pass + raise AttributeError, var + def items(self): + try: + return self._base.items() + except AttributeError: + pass + try: + return self._base.__dict__.items() + except AttributeError: + pass + def keys(self): + try: + return self._base.keys() + except AttributeError: + pass + try: + return self._base.__dict__.keys() + except AttributeError: + pass + def has_key( self, key ): + try: + return self._base.has_key( key) + except AttributeError: + pass + try: + return self._base.__dict__.has_key( key) + except AttributeError: + pass + def values(self): + try: + return self._base.values() + except AttributeError: + pass + try: + return self._base.__dict__.values() + except AttributeError: + pass + + def __getinitargs__(self): + if type( self._base ) is types.ModuleType: + base = self._base.__name__ + else: + base = self._base + return (base, self.__parent__, self.__downcascade__, self.__childlist__) + def __getstate__(self): + return None + def __setstate__(self,*args): + pass + def __deepcopy__(self, memo=None): + d = id(self) + if memo is None: + memo = {} + elif memo.has_key(d): + return memo[d] + if type(self._base) == types.ModuleType: + rest = tuple(map( copy.deepcopy, (self.__parent__, self.__downcascade__, self.__childlist__) )) + new = apply(self.__class__, (self._base,)+rest ) + else: + new = tuple(map( copy.deepcopy, (self._base, self.__parent__, self.__downcascade__, self.__childlist__) )) + return new +## def __del__( self, id=id ): +## print 'del namespace', id( self ) + + +def test(): + import string + a = NameSpace(string) + del(string) + a.append(NameSpace({'a':23,'b':42})) + import math + a.append(NameSpace(math)) + print 'The returned object should allow access to the attributes of the string,\nand math modules, and two simple variables "a" and "b" (== 23 and42 respectively)' + return a + + diff --git a/intern/python/modules/mcf/utils/quote.py b/intern/python/modules/mcf/utils/quote.py new file mode 100644 index 00000000000..5f6dccdd511 --- /dev/null +++ b/intern/python/modules/mcf/utils/quote.py @@ -0,0 +1,78 @@ +''' +Generic quoting functions (very fast), +generalised to allow use in any number of +situations, but normally you'll want to create +a new function based on these patterns which +has the default args you need. This will +prevent an extra function call. +''' +import string, regex +# create a translator which is fully worked out... + +def _quote(somestring,trans,start='"',stop='"'): + ''' + Return a quoted version of somestring. + ''' + # would be _so_ much better if we could use the + # getitem, consider... + # return '%s%s%s'%(start,string.join(map(trans.__getitem__, somestring), ''),stop) + temp = list(somestring) + for charno in xrange(len(temp)): + temp[charno]= trans[temp[charno]] + return '%s%s%s'%(start,string.join(temp, ''),stop) + +def compilerex(trans): + ''' + Compiles a suitable regex from a dictionary + translation table. Should be used at design + time in most cases to improve speed. Note: + is not a very intelligent algo. You could + do better by creating a character-class [] + for the single-character keys and then the + groups for the or-ing after it, but I've not + got the time at the moment. + ''' + keyset = trans.keys() + multitrans = [] + for x in range(len(keyset)): + if len(keyset[x]) != len(trans[keyset[x]]): + multitrans.append((keyset[x],trans[keyset[x]])) + if len(keyset[x])!= 1: + keyset[x] = '\(%s\)'%keyset[x] + if multitrans: + return 1,regex.compile(string.join(keyset,'\|')) + + +def quote2(somestring,trans,rex,start='',stop=''): + ''' + Should be a faster version of _quote once + the regex is built. Rex should be a simple + or'ing of all characters requiring substitution, + use character ranges whereever possible (should + be in most cases) + ''' + temp = list(somestring) + curpos = 0 + try: + while rex.search(somestring,curpos) != -1: + pos = rex.regs[0] + print pos + replacement = list(trans[rex.group(0)]) + temp[pos[0]:pos[1]] = replacement + curpos = pos[0]+len(replacement) + except (IndexError,regex.error): + pass + return '%s%s%s'%(start,string.join(temp, ''),stop) +# compatability +_quote2 = quote2 + +def reprq(obj, qtype): + ''' + Return representation of a string obj as a string with qtype + quotes surrounding it. Usable when linearising Python objects + to languages which have only a particular type of string. (Such + as VRML). This is not a generalised nor a particularly reliable + solution. You should use the _quote2 function instead. + ''' + return '%s%s%s'%(qtype,string.join(string.split(string.join(string.split(obj, '\\'), '\\\\'), qtype), '\\%s'%qtype),qtype) + diff --git a/intern/python/modules/mcf/utils/rangeval.py b/intern/python/modules/mcf/utils/rangeval.py new file mode 100644 index 00000000000..dd166dbebfb --- /dev/null +++ b/intern/python/modules/mcf/utils/rangeval.py @@ -0,0 +1,64 @@ +''' Classes which match ranges, sets, or anything at all. ''' +import dummy # provides storage functions as well as a few others + +class BetwVal(dummy.Dummy): + ''' + Matches any object greater than smaller and less than larger + ''' + def __init__(self, first, second): + if first <= second: + dummy.Dummy.__init__(self, [first, second]) + else: + dummy.Dummy.__init__(self, [second, first]) + def __getinitargs__(self): + return (self._base[0], self._base[1]) + def __cmp__(self, object): + '''The Guts of the Class, allows standard comparison operators''' + if self._base[0]<=object: + if self._base[1] >=object: + return 0 + else: return 1 + else: return -1 + def __repr__(self): + return '%s(%s,%s)'% (self.__class__.__name__,`self._base[0]`,`self._base[1]`) + +class WInVal(dummy.Dummy): + ''' + Matches any value in the sequential object used as initialiser + Doesn't gracefully handle situations where not found, as it just + returns a -1 + ''' + def __init__(self,seq): + self._base = seq + def __cmp__(self, object): + ''' Standard comparison operators ''' + for x in self._base: + if x == object: + return 0 + return -1 + def __repr__(self): + return '%s(%s)'% (self.__class__.__name__,`self._base`) + +class ExceptVal(WInVal): + ''' + A negative Version of WInVal + ''' + def __cmp__(self, object): + for x in self._base: + if x == object: + return -1 + return 0 + +class AnyVal: + ''' + Matches anything at all + ''' + def __init__(self): + pass + def __getinitargs__(self): + return () + def __cmp__(self, object): + return 0 + def __repr__(self): + return 'AnyVal()' + diff --git a/intern/python/modules/mcf/utils/regutils_ex.py b/intern/python/modules/mcf/utils/regutils_ex.py new file mode 100644 index 00000000000..5ef48454e78 --- /dev/null +++ b/intern/python/modules/mcf/utils/regutils_ex.py @@ -0,0 +1,158 @@ +import win32api, win32con, string, types + +def _getDataType( data, coerce = 1 ): + ''' + Return a tuple of dataType, data for a given object + automatically converts non-string-or-tuple-data into + strings by calling pickle.dumps + ''' + if type( data ) is types.StringType: + return win32con.REG_SZ, data + elif type( data ) is types.IntType: + return win32con.REG_DWORD, data + # what about attempting to convert Longs, floats, etceteras to ints??? + elif coerce: + import pickle + return win32con.REG_SZ, pickle.dumps( data ) + else: + raise TypeError, '''Unsupported datatype for registry, use getDataType( data, coerce=1) to store types other than string/int.''' + +def _getBaseKey( fullPathSpec ): + ''' + Split a "full path specification" registry key + into its root and subpath components + ''' + key = '' + subkey = fullPathSpec + # while loop will strip off preceding \\ characters + while subkey and not key: + key, subkey = string.split( fullPathSpec, '\\', 1 ) + try: + return getattr( win32con, key ), subkey + except AttributeError: + raise '''Unknown root key %s in registry path %s'''% (key, fullPathSpec) + +def RegSetValue( key, valuename='', data='', allowPickling=1 ): + ''' + Set a registry value by providing a fully-specified + registry key (and an optional sub-key/value name), + and a data element. If allowPickling is true, the + data element can be any picklable element, otherwise + data element must be a string or integer. + ''' + root, subkey = _getBaseKey( key ) + dataType, data = _getDataType( data, allowPickling ) + try: + hKey = win32api.RegOpenKeyEx( root , subkey, 0, win32con.KEY_ALL_ACCESS) # could we use a lesser access model? + except: + hKey = win32api.RegCreateKey( root, subkey ) + try: + if not valuename: # the default value + win32api.RegSetValue( hKey, valuename, dataType, data ) + else: # named sub-value + win32api.RegSetValueEx( hKey, valuename, 0, dataType, data ) + finally: + win32api.RegCloseKey( hKey) + +def RegQueryValue( key, valuename='', pickling=0 ): + ''' + Get a registry value by providing a fully-specified + registry key (and an optional sub-key/value name) + If pickling is true, the data element will be + unpickled before being returned. + ''' + #print 'key', key + root, subkey = _getBaseKey( key ) + if not valuename: # the default value + data, type = win32api.RegQueryValue( root , subkey) + else: + try: + #print root, subkey + hKey = win32api.RegOpenKeyEx( root, subkey, 0, win32con.KEY_READ) + #print hKey, valuename + try: + data, type = win32api.RegQueryValueEx( hKey, valuename ) + except: # + data, type = None, 0 # value is not available... + pickling = None + finally: + win32api.RegCloseKey( hKey) + if pickling: + import pickle + data = pickle.loads( data ) + return data + +# following constants seem to reflect where path data is stored on NT machines +# no idea if it'll work on a 95 machine + +def AddPathEntry( newEntry, user = 1, prepend=0 ): + ''' + Add or remove path entry on NT, use prepend == -1 for removal, + use prepend == 0 for append, prepend= 1 for prepending to the + current path. + ''' + if user: + user = 'USER' + else: + user = 'MACHINE' + key, valuename = COMMON_KEYS[ (user, 'PATH') ] + _PathManager( key, valuename, newEntry, prepend ) + +def PyExecutables( user = 1, prepend=0 ): + ''' + Register/Deregister Python files as executables + ''' + if user: + user = 'USER' + else: + user = 'MACHINE' + key, valuename = COMMON_KEYS[ (user, 'PYEXECUTABLES') ] + # the default executables + Python scripts... + if prepend < 0: # are to eliminate only .py + newEntry = '.PY' + else: + newEntry = '.PY;.COM;.EXE;.BAT;.CMD' + _PathManager( key, valuename, newEntry, prepend ) + +def _PathManager( key, valuename, newEntry, prepend=0, eliminate_duplicates=1 ): + ''' + Create a new Path entry on NT machines (or kill an old one) + user determines whether to alter the USER or the Machine's path + prepend + 1 -> add newEntry to start + 0 -> add newEntry to end + -1 -> don't add newEntry + eliminate_duplicates determines whether to kill equal paths + + All values are converted to lower case + ''' + # get current value... + curval = RegQueryValue( key, valuename ) or '' + # split into elements + curval = string.split( string.lower(curval), ';' ) + if type( newEntry ) not in (types.ListType, types.TupleType): + newEntry = string.split( string.lower(newEntry), ';' ) + # eliminate duplicates of the newEntry + curval = filter( None, curval) # strip out null entries + if eliminate_duplicates: + newval = [] + for p in curval: + if p not in newEntry: + newval.append( p ) + curval = newval + if prepend == 1: + curval = list(newEntry) + curval + elif prepend == 0: + curval = curval + list( newEntry ) + elif prepend == -1: # this call is just killing the path entry + pass + #now do the recombination + curval = string.join( curval, ';' ) + RegSetValue( key, valuename, curval ) + +COMMON_KEYS = { +('USER','PATH') : ('''HKEY_CURRENT_USER\\Environment''', 'path'), +('MACHINE','PATH') : ('''HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment''', 'path'), +('USER','PYEXECUTABLES') : ('''HKEY_CURRENT_USER\\Environment''', 'pathext'), +('MACHINE','PYEXECUTABLES') : ('''HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment''', 'pathext') +} diff --git a/intern/python/modules/mcf/utils/reloader.py b/intern/python/modules/mcf/utils/reloader.py new file mode 100644 index 00000000000..2d7e2591ed2 --- /dev/null +++ b/intern/python/modules/mcf/utils/reloader.py @@ -0,0 +1,33 @@ +import sys, string + +class Reloader: + ''' + Class allows for reloading all modules imported + after the instance is created. Normally you will + use this by doing: + import <anything you don't want reloaded> + from mcf.utils import reloader + <do testing and rewriting> + reloader.go() + ''' + def __init__(self): + self.keys = sys.modules.keys() + def __call__(self, *args, **namedargs): + done = [] + for key, val in sys.modules.items(): + if key not in self.keys: + try: + reload( val ) + done.append( key ) + except (ImportError): + print '''Couldn't reload module:''', key + except (TypeError): # for None's + # is a flag to prevent reloading + pass + if done: + print '''Reloaded:''', string.join( done, ', ') + else: + print '''No modules reloaded''' + +# the default reloader... +go = Reloader()
\ No newline at end of file diff --git a/intern/python/modules/mcf/utils/singletonlist.py b/intern/python/modules/mcf/utils/singletonlist.py new file mode 100644 index 00000000000..5ca2f5000c2 --- /dev/null +++ b/intern/python/modules/mcf/utils/singletonlist.py @@ -0,0 +1,104 @@ +class SingletonList: + ''' + A SingletonList always has a length of one or 0, + appends overwrite the single element, iteration will + return precisely one element. Attempts to get any item + other than 0 will raise an IndexError or return the single + item depending on whether the 'raiseIndexError' flag is + true or false (generally it should be true except if the + for x in SingletonList: construct is known never to be + used, since this construct will create an infinite loop + if we never raise an IndexError). + ''' + def __init__(self,base=None,raiseIndexError=1): + self._base = base + self.raiseIndexError = raiseIndexError + def __len__(self): + ''' + The length is 0 if no _base, 1 if a base + ''' + if hasattr(self, '_base'): + return 1 + else: + return 0 + def __getitem__(self,ind): + ''' + Get the item if ind == 0, else raise an IndexError or return + the item, depending on the raiseIndexError flag + ''' + if ind == 0: + try: + return self._base + except AttributeError: + raise IndexError, ind + elif self.raiseIndexError: + raise IndexError, ind + else: + return self._base + def __setitem__(self,ind, item): + ''' + The item is to become the base + ''' + self._base = item + def __delitem__(self,ind): + ''' + Delete the base, regardless of the index used + ''' + try: + del(self._base) + except AttributeError: + raise IndexError, ind + def append(self,item): + ''' + Replace the base with the item + ''' + self._base = item + def index(self,item): + ''' + if the item is the base, return the only valid index (0) + ''' + try: + if item == self._base: + return 0 + except: + pass + raise ValueError, item + def count(self, item): + ''' + If the item is the base, we have one, else 0 + ''' + try: + if item == self._base: + return 1 + except: + pass + return 0 + insert = __setitem__ + def remove(self, item): + ''' + if the item is the base, delete the base, else ValueError + ''' + try: + if item == self._base: + del(self._base) + return + except: + pass + raise ValueError, item + def reverse(self): + pass + def sort(self): + pass + def __repr__(self): + try: + return '[%s]'%`self._base` + except AttributeError: + return '[]' + # store and copy functions +# def __getinitargs__(self): +# return (self._base,self.raiseIndexError) +# def __getstate__(self,*args,**namedargs): +# pass +# def __setstate__(self,*args,**namedargs): +# pass + diff --git a/intern/python/modules/mcf/utils/tempclassmodule.py b/intern/python/modules/mcf/utils/tempclassmodule.py new file mode 100644 index 00000000000..9fe6eed3918 --- /dev/null +++ b/intern/python/modules/mcf/utils/tempclassmodule.py @@ -0,0 +1,251 @@ +''' +Generate module for holding temporary classes which +will be reconstructed into the same module to allow +cPickle and the like to properly import them. + +Note: You _must_ pickle a reference to the tempclassmodule +_before_ you pickle any instances which use the classes stored +in the module! Also, the classes cannot reference anything +in their dictionary or bases tuples which are not normally +pickleable (in particular, you can't subclass a class in the +same tempclassmodule or a tempclassmodule which you cannot +guarantee will be loaded before the dependent classes. (i.e. +by guaranteeing they will be pickled first) +''' +import new, time, string, sys, types + +def buildModule(packagename, basename, rebuild=None, initialcontents=None): + ''' + Dynamically build a module or rebuild one, generates + a persistent ID/name if not rebuilding. The persistent + ID is the value of basename+`time.time()` with the decimal + point removed (i.e. a long string of digits). Packagename + must be an importable package! Will raise an ImportError + otherwise. Also, for easy reconstitution, basename must not + include any decimal points. + + initialcontents is a dictionary (or list) of elements which will be + added to the new module. + ''' + if rebuild == None: + timestamp = `time.time()` + decpos = string.find(timestamp,'.') + basename = basename+timestamp[:decpos]+timestamp[decpos+1:] + name = string.join((packagename, basename), '.') + a = {} + b = {} + try: # see if we've already loaded this module... + mod = __import__( name, {},{}, string.split( name, '.')) + if initialcontents: + _updateFrom(mod, initialcontents) + return mod.__name__, mod + except ImportError: + pass + mod = new.module(name) + sys.modules[name] = mod + # following is just to make sure the package is loaded before attempting to alter it... + __import__( packagename, {}, {}, string.split(packagename) ) +## exec 'import %s'%(packagename) in a, b ### Security Risk! + setattr(sys.modules[ packagename ], basename, mod) + # now do the update if there were initial contents... + if initialcontents: + _updateFrom(mod, initialcontents) + return name, mod + +def buildClassIn(module, *classargs, **namedclassargs): + ''' + Build a new class and register it in the module + as if it were really defined there. + ''' + print module, classargs, namedclassargs + namedclassargs["__temporary_class__"] = 1 + newclass = new.classobj(classargs[0], classargs[1], namedclassargs) + newclass.__module__ = module.__name__ + setattr(module, newclass.__name__, newclass) + return newclass + +def addClass(module, classobj): + ''' + Insert a classobj into the tempclassmodule, setting the + class' __module__ attribute to point to this tempclassmodule + ''' + classobj.__module__ = module.__name__ + setattr(module, classobj.__name__, classobj) + setattr( classobj, "__temporary_class__", 1) + +def delClass(module, classobj): + ''' + Remove this class from the module, Note: after running this + the classobj is no longer able to be pickled/unpickled unless + it is subsequently added to another module. This is because + it's __module__ attribute is now pointing to a module which + is no longer going to save its definition! + ''' + try: + delattr(module, classobj.__name__) + except AttributeError: + pass + +def _packageName(modulename): + decpos = string.rfind(modulename, '.') + return modulename[:decpos], modulename[decpos+1:] + +def _updateFrom(module, contentsource): + ''' + For dealing with unknown datatypes (those passed in by the user), + we want to check and make sure we're building the classes correctly. + ''' + # often will pass in a protoNamespace from which to update (during cloning) + if type(contentsource) in ( types.DictType, types.InstanceType): + contentsource = contentsource.values() + # contentsource should now be a list of classes or class-building tuples + for val in contentsource: + if type(val) is types.ClassType: + try: + addClass(module, val) + except: + pass + elif type(val) is types.TupleType: + try: + apply(buildClassIn, (module,)+val) + except: + pass + +def deconstruct(templatemodule): + ''' + Return a tuple which can be passed to reconstruct + in order to get a rebuilt version of the module + after pickling. i.e. apply(reconstruct, deconstruct(tempmodule)) + is the equivalent of doing a deepcopy on the tempmodule. + ''' +## import pdb +## pdb.set_trace() + classbuilder = [] + for name, classobj in templatemodule.__dict__.items(): + if type(classobj) is types.ClassType: # only copy class objects, could do others, but these are special-purpose modules, not general-purpose ones. + classbuilder.append( deconstruct_class( classobj) ) +## import pdb +## pdb.set_trace() + return (templatemodule.__name__, classbuilder) +## except AttributeError: +## print templatemodule +## print classbuilder + +def deconstruct_class( classobj ): + ''' + Pull apart a class into a tuple of values which can be used + to reconstruct it through a call to buildClassIn + ''' + if not hasattr( classobj, "__temporary_class__"): + # this is a regular class, re-import on load... + return (classobj.__module__, classobj.__name__) + else: + # this is a temporary class which can be deconstructed + bases = [] + for classobject in classobj.__bases__: + bases.append( deconstruct_class (classobject) ) + return (classobj.__name__, tuple (bases), classobj.__dict__) + + +def reconstruct(modulename, classbuilder): + ''' + Rebuild a temporary module and all of its classes + from the structure created by deconstruct. + i.e. apply(reconstruct, deconstruct(tempmodule)) + is the equivalent of doing a deepcopy on the tempmodule. + ''' +## import pdb +## pdb.set_trace() + mname, newmod = apply(buildModule, _packageName(modulename)+(1,) ) # 1 signals reconstruct + reconstruct_classes( newmod, classbuilder ) + return newmod + +def reconstruct_classes( module, constructors ): + ''' + Put a class back together from the tuple of values + created by deconstruct_class. + ''' + classes = [] + import pprint + pprint.pprint( constructors) + for constructor in constructors: + if len (constructor) == 2: + module, name = constructor + # this is a standard class, re-import + temporarymodule = __import__( + module, + {},{}, + string.split(module)+[name] + ) + classobject =getattr (temporarymodule, name) + else: + # this is a class which needs to be re-constructed + (name, bases,namedarguments) = constructor + bases = tuple( reconstruct_classes( module, bases )) + classobject = apply ( + buildClassIn, + (module, name, bases), # name and bases are the args to the class constructor along with the dict contents in namedarguments + namedarguments, + ) + classes.append (classobject) + return classes + + +def destroy(tempmodule): + ''' + Destroy the module to allow the system to do garbage collection + on it. I'm not sure that the system really does do gc on modules, + but one would hope :) + ''' + name = tempmodule.__name__ + tempmodule.__dict__.clear() # clears references to the classes + try: + del(sys.modules[name]) + except KeyError: + pass + packagename, modname = _packageName(name) + try: + delattr(sys.modules[ packagename ], modname) + except AttributeError: + pass + del( tempmodule ) # no, I don't see any reason to do it... + return None + + +def deepcopy(templatemodule, packagename=None, basename=None): + ''' + Rebuild the whole Module and it's included classes + (just the classes). Note: This will _not_ make instances + based on the old classes point to the new classes! + The value of this function is likely to be minimal given + this restriction. For pickling use deconstruct/reconstruct + for simple copying just return the module. + ''' + name, classbuilder = deconstruct( templatemodule ) + if packagename is None: + tp, tb = _packageName( name ) + if packagename is None: + packagename = tp + if basename is None: + basename = tb + newmod = buildModule(packagename, basename, initialcontents=classbuilder ) + return newmod + +if __name__ == "__main__": + def testPickle (): + import mcf.vrml.prototype + name, module = buildModule( 'mcf.vrml.temp', 'scenegraph' ) + buildClassIn( module, 'this', () ) + buildClassIn( module, 'that', (mcf.vrml.prototype.ProtoTypeNode,) ) +## import pdb +## pdb.set_trace() + import pprint + pprint.pprint( deconstruct( module )) + name,builder = deconstruct( module ) + destroy( module) + return reconstruct(name, builder) + t = testPickle() + print t + + +
\ No newline at end of file diff --git a/intern/python/modules/mcf/utils/typeclasses.py b/intern/python/modules/mcf/utils/typeclasses.py new file mode 100644 index 00000000000..ed798dfe3da --- /dev/null +++ b/intern/python/modules/mcf/utils/typeclasses.py @@ -0,0 +1,50 @@ +''' +Classes of Types + +Often you want to be able to say: + if type(obj) in MutableTypes: + yada + +This module is intended to make that easier. +Just import and use :) +''' +import types + +MutableTypes = [ types.ListType, types.DictType, types.InstanceType ] +MutableSequenceTypes = [ types.ListType ] +SequenceTypes = [ types.ListType, types.StringType, types.TupleType ] +NumericTypes = [ types.IntType, types.FloatType, types.LongType, types.ComplexType ] +MappingTypes = [ types.DictType ] + +def regarray(): + if globals().has_key('array'): + return 1 + try: + import array + SequenceTypes.append( array.ArrayType ) + MutableTypes.append( array.ArrayType ) + MutableSequenceTypes.append( array.ArrayType ) + return 1 + except ImportError: + return 0 + +def regnumpy(): + ''' + Call if you want to register numpy arrays + according to their types. + ''' + if globals().has_key('Numeric'): + return 1 + try: + import Numeric + SequenceTypes.append( Numeric.ArrayType ) + MutableTypes.append( Numeric.ArrayType ) + MutableSequenceTypes.append( Numeric.ArrayType ) + return 1 + except ImportError: + return 0 + +# for now, I'm going to always register these, if the module becomes part of the base distribution +# it might be better to leave it out so numpy isn't always getting loaded... +regarray() +regnumpy()
\ No newline at end of file diff --git a/intern/python/modules/mcf/utils/userquery.py b/intern/python/modules/mcf/utils/userquery.py new file mode 100644 index 00000000000..e1dc1bfeda5 --- /dev/null +++ b/intern/python/modules/mcf/utils/userquery.py @@ -0,0 +1,17 @@ +import string + +def userquery( prompt, choices, contextdata = '', defaultind=0 ): + if contextdata: + print 'Contextual Information:', contextdata + for x in range( len( choices ) ): + print '(%s)'%x, `choices[x]` + choice = raw_input( prompt+( '(%s):'%defaultind ) ) + if not choice: + return choices[ defaultind ] + try: + choice = string.atoi( choice ) + return choices[ choice] + except IndexError : + return choices[ defaultind ] + except ValueError: + return choice diff --git a/intern/python/modules/mcf/utils/ver.py b/intern/python/modules/mcf/utils/ver.py new file mode 100644 index 00000000000..1d36fcd122a --- /dev/null +++ b/intern/python/modules/mcf/utils/ver.py @@ -0,0 +1,17 @@ +''' +Module giving a float representation +of the interpreter major version (1.4, 1.5 etceteras) + +ver -- Float representation of the current interpreter version + +Note: Since I no longer have any Python 1.4 modules, this module is +no longer in use by me. I intend to leave it here for the next version +jump :) . +''' +import regex, sys, string +ver = string.atof(sys.version[:regex.match('[0-9.]*', sys.version)]) + +### Clean up namespace +del(regex) +del(sys) +del(string) diff --git a/intern/python/modules/mcf/utils/walkerable.py b/intern/python/modules/mcf/utils/walkerable.py new file mode 100644 index 00000000000..e4c18302097 --- /dev/null +++ b/intern/python/modules/mcf/utils/walkerable.py @@ -0,0 +1,46 @@ +''' +Really simplistic walker-processable hierobjects, doesn't +have parent attributes, every element has an __attrDict__ +item and a childlist. This is different from the mechanisms +we'll want to use for multi-tree systems, but it's fairly +close. Should be fairly simply worked with. +''' +class WalkerAble: + ''' + Simple hierarchic objects with the following elements + + __attrDict__ -- app-specific attributes + __childlist__ -- childen of this node + __gi__ -- "type" or Generic Indicator of this node + __childlist__append__ -- as you'd expect, method on childlist to add an element + ''' + def __init__(self, childlist=None, attrDict=None, gi=None): + self.__dict__['__attrDict__'] = attrDict or {} + self.__dict__['__childlist__'] = childlist or [] + self.__dict__['__gi__'] = gi or '' + self.__dict__['__childlist__append__'] = self.__childlist__.append + + def __getattr__(self, attrName): + ''' + Note: you can store attributes with the same names as + the reserved names, but to get them back, you'll need + to read it directly out of the attrDict + ''' + if attrName != '__attrDict__': + try: + return self.__attrDict__[attrName] + except KeyError: + pass + raise AttributeError, attrName + + def __setattr__(self, attrName, attrVal): + self.__attrDict__[attrName] = attrVal + def __setGI__(self, gi): + self.__dict__['__gi__'] = gi + def __repr__(self): + return '''<WalkerAble %(__gi__)s %(__attrDict__)s %(__childlist__)s>'''%self.__dict__ + + # copy functions +# def __getinitargs__(self): +# return (self.__childlist__, self.__attrDict__, self.__gi__) + diff --git a/intern/python/modules/simpleparse/__init__.py b/intern/python/modules/simpleparse/__init__.py new file mode 100644 index 00000000000..961871c36a5 --- /dev/null +++ b/intern/python/modules/simpleparse/__init__.py @@ -0,0 +1,5 @@ +''' +Simple parsing using mxTextTools + +tar -cvf simpleparse.tar --exclude-from=exclude.txt +'''
\ No newline at end of file diff --git a/intern/python/modules/simpleparse/bootstrap.py b/intern/python/modules/simpleparse/bootstrap.py new file mode 100644 index 00000000000..65274bb03ee --- /dev/null +++ b/intern/python/modules/simpleparse/bootstrap.py @@ -0,0 +1,279 @@ + +from TextTools.TextTools import * + +##################################################### +# FOLLOWING IS THE BOOTSTRAP PARSER, HAND-CODED! + +parsernamelist = [ +'declarationset', # 0 +'declaration', # 1 +'implicit_group', # 2 --> no longer used +'added_token', # 3 +'seq_added_token', #4 +'fo_added_token', #5 +'or_added_token', #6 +'and_added_token', #7 +'element_token', #8 +'group', #9 +'negpos_indicator', #10 +'occurence_indicator', #11 +'unreportedname', #12 +'name', #13 +'<ts>', # 14 +'literal', #15 +'range', # 16 +'CHARBRACE', #17 +'CHARDASH', # 18 +'CHARRANGE', # 19 +'CHARNOBRACE', # 20 +'ESCAPEDCHAR', # 21 +'SPECIALESCAPEDCHAR', # 22 +'OCTALESCAPEDCHAR' # 23 +] + +parsertuplelist = range( 24 ) + + + +parsertuplelist[0] = ( # declarationset + ('declaration', TableInList,(parsertuplelist, 1)), # must be at least one declaration + ('declaration', TableInList,(parsertuplelist, 1),1,0) +) +parsertuplelist[1] = ( # declaration + (None, TableInList,(parsertuplelist, 14)), # ts + (None, SubTable, ( + ('unreportedname', TableInList,(parsertuplelist, 12),1,2), + ('name', TableInList,(parsertuplelist, 13)), # name + ) + ), + (None, TableInList,(parsertuplelist, 14)), # ts + (None, Word, ':='), + (None, TableInList,(parsertuplelist, 14)), # ts + ('element_token', TableInList,(parsertuplelist, 8)), + (None, SubTable, ( # added_token + ('seq_added_token', TableInList, (parsertuplelist,4), 1, 5 ), + ('fo_added_token', TableInList, (parsertuplelist,5), 1, 4 ), + ('or_added_token', TableInList, (parsertuplelist,6), 1, 3 ), + ('and_added_token', TableInList, (parsertuplelist,7), 1, 2 ), + (None, Fail, Here), + ('seq_added_token', TableInList, (parsertuplelist,4), 1, 0 ), + ('fo_added_token', TableInList, (parsertuplelist,5), 1, -1 ), + ('or_added_token', TableInList, (parsertuplelist,6), 1, -2 ), + ('and_added_token', TableInList, (parsertuplelist,7), 1, -3 ), + ),1,1), + (None, TableInList,(parsertuplelist, 14)), # ts +) +parsertuplelist[3] = ( # added_token + ('seq_added_token', TableInList, (parsertuplelist,4), 1, 5 ), + ('fo_added_token', TableInList, (parsertuplelist,5), 1, 4 ), + ('or_added_token', TableInList, (parsertuplelist,6), 1, 3 ), + ('and_added_token', TableInList, (parsertuplelist,7), 1, 2 ), + (None, Fail, Here), + ('seq_added_token', TableInList, (parsertuplelist,4), 1, 0 ), + ('fo_added_token', TableInList, (parsertuplelist,5), 1, -1 ), + ('or_added_token', TableInList, (parsertuplelist,6), 1, -2 ), + ('and_added_token', TableInList, (parsertuplelist,7), 1, -3 ), +) +parsertuplelist[4] = ( # seq_added_token + (None, TableInList,(parsertuplelist, 14)), # ts + (None, Is, ','), + (None, TableInList,(parsertuplelist, 14)), # ts + ('element_token', TableInList,(parsertuplelist, 8)), + (None, TableInList,(parsertuplelist, 14),4,1), # ts + (None, Is, ',',3,1), + (None, TableInList,(parsertuplelist, 14),2,1), # ts + ('element_token', TableInList,(parsertuplelist, 8),1,-3), +) +parsertuplelist[5] = ( # fo_added_token + (None, TableInList,(parsertuplelist, 14)), # ts + (None, Is, '/'), + (None, TableInList,(parsertuplelist, 14)), # ts + ('element_token', TableInList,(parsertuplelist, 8)), + (None, TableInList,(parsertuplelist, 14),4,1), # ts + (None, Is, '/',3,1), + (None, TableInList,(parsertuplelist, 14),2,1), # ts + ('element_token', TableInList,(parsertuplelist, 8),1,-3), +) +parsertuplelist[6] = ( # or_added_token + (None, TableInList,(parsertuplelist, 14)), # ts + (None, Is, '|'), + (None, TableInList,(parsertuplelist, 14)), # ts + ('element_token', TableInList,(parsertuplelist, 8)), + (None, TableInList,(parsertuplelist, 14),4,1), # ts + (None, Is, '|',3,1), + (None, TableInList,(parsertuplelist, 14),2,1), # ts + ('element_token', TableInList,(parsertuplelist, 8),1,-3), +) +parsertuplelist[7] = ( # and_added_token + (None, TableInList,(parsertuplelist, 14)), # ts + (None, Is, '&'), + (None, TableInList,(parsertuplelist, 14)), # ts + ('element_token', TableInList,(parsertuplelist, 8)), + (None, TableInList,(parsertuplelist, 14),4,1), # ts + (None, Is, '&',3,1), + (None, TableInList,(parsertuplelist, 14),2,1), # ts + ('element_token', TableInList,(parsertuplelist, 8),1,-3), +) +parsertuplelist[8] = ( # element_token + ('negpos_indicator', TableInList,(parsertuplelist, 10),1,1), + (None, TableInList,(parsertuplelist, 14),1,1), # ts, very inefficient :( + ('literal', TableInList, (parsertuplelist,15),1, 4 ), + ('range', TableInList, (parsertuplelist,16),1, 3 ), + ('group', TableInList, (parsertuplelist,9),1, 2 ), + ('name', TableInList, (parsertuplelist,13) ), + (None, TableInList,(parsertuplelist, 14),1,1), # ts, very inefficient :( + ('occurence_indicator', TableInList,(parsertuplelist, 11), 1,1), +) +parsertuplelist[9] = ( # group + (None, Is, '('), + (None, TableInList,(parsertuplelist, 14),1,1), # ts + ('element_token', TableInList, (parsertuplelist,8) ), + (None, SubTable, ( # added_token + ('seq_added_token', TableInList, (parsertuplelist,4), 1, 5 ), + ('fo_added_token', TableInList, (parsertuplelist,5), 1, 4 ), + ('or_added_token', TableInList, (parsertuplelist,6), 1, 3 ), + ('and_added_token', TableInList, (parsertuplelist,7), 1, 2 ), + (None, Fail, Here), + ('seq_added_token', TableInList, (parsertuplelist,4), 1, 0 ), + ('fo_added_token', TableInList, (parsertuplelist,5), 1, -1 ), + ('or_added_token', TableInList, (parsertuplelist,6), 1, -2 ), + ('and_added_token', TableInList, (parsertuplelist,7), 1, -3 ), + ),1,1), + (None, TableInList,(parsertuplelist, 14),1,1), # ts + (None, Is, ')'), +) +parsertuplelist[10] = ( # negpos_indicator + (None, Is, "+",1,2), + (None, Is, "-"), +) +parsertuplelist[11] = ( #occurence_indicator + (None, Is, "+",1,3), + (None, Is, "*",1,2), + (None, Is, '?'), +) +parsertuplelist[12] = ( #unreportedname + (None, Is, '<'), + ('name', TableInList, (parsertuplelist, 13)), # inefficiency in final system :( + (None, Is, '>'), +) +parsertuplelist[13] = ( # name + (None, IsIn, alpha+'_'), + (None, AllIn, alphanumeric+'_',1,1) +) + +parsertuplelist[14] = ( # ts (whitespace) + (None, AllIn, ' \011\012\013\014\015',1,1), + (None, SubTable, ( + (None, Is, '#' ), + (None, AllNotIn, '\n',1,1 ) # problem if there's a comment at the end of the file :( + ) + ,1,-1 ), + ) +# this isn't actually used in the bootstrap parser... +_specialescapedchar = parsertuplelist[22] = ( # SPECIALESCAPEDCHAR + ('SPECIALESCAPEDCHAR', IsIn, '\\abfnrtv'), +) +_octalescapechar = parsertuplelist[23] = ( # OCTALESCAPEDCHAR + (None, IsIn, '01234567'), + (None, IsIn, '01234567',2), + (None, IsIn, '01234567',1), +) +_escapedchar = parsertuplelist[21] = ( # escapedcharacter + (None, Is, '\\' ), + ('SPECIALESCAPEDCHAR', IsIn, '\\abfnrtv',1,4), + ('OCTALESCAPEDCHAR', SubTable, _octalescapechar) +) + +_charnobrace = parsertuplelist[20] = ( # charnobrace + ('ESCAPEDCHAR', Table, _escapedchar, 1,2), + ('CHAR', IsNot, ']'), +) +_rangedef = parsertuplelist[19] = ( # charrange + ('CHARNOBRACE', Table, _charnobrace ), + (None, Is, '-'), + ('CHARNOBRACE', Table, _charnobrace ), +) + + +parsertuplelist[16] = ( #range + (None, Is, '['), + ('CHARBRACE', Is, ']',1,1), + ('CHARDASH', Is, '-',1,1), + ('CHARRANGE', Table, _rangedef, 1,0), + (None, SubTable, _charnobrace, 1,-1), + (None, Is, ']') +) + +_sqstr = ( + (None, Is, "'" ), +# (None, Is, "'",1, 5 ), # immediate close + (None, AllNotIn, "\\'",1,1 ), # all not an escape or end + (None, Is, "\\", 2, 1), # is an escaped char + (None, Skip, 1, 1, -2), # consume the escaped char and loop back + (None, Is, "'" ) # in case there was no matching ', which would also cause a fail for allnotin + ) +_dblstr = ( + (None, Is, '"' ), +# (None, Is, '"',1, 5 ), # immediate close + (None, AllNotIn, '\\"' ,1,1), # not an escaped or end + (None, Is, "\\", 2, 1), # is an escaped char + (None, Skip, 1, 1, -2), # consume the escaped char and loop back + (None, Is, '"' ) # in case there was no matching ", which would also cause a fail for allnotin + ) + + + +# literal := ("'",(CHARNOSNGLQUOTE/ESCAPEDCHAR)*,"'") / ('"',(CHARNODBLQUOTE/ESCAPEDCHAR)*,'"') + +parsertuplelist[15] = ( # literal + (None, Is, "'", 4, 1 ), + ('CHARNOSNGLQUOTE', AllNotIn, "\\'",1,1 ), # all not an escape or end + ('ESCAPEDCHAR', Table, _escapedchar, 1, -1), + (None, Is, "'", 1,5 ), + (None, Is, '"' ), + ('CHARNODBLQUOTE', AllNotIn, '\\"',1,1 ), # all not an escape or end + ('ESCAPEDCHAR', Table, _escapedchar, 1, -1), + (None, Is, '"'), +) + +declaration = r'''declarationset := declaration+ +declaration := ts , (unreportedname/name) ,ts,':=',ts, element_token, ( seq_added_token / fo_added_token / or_added_token / and_added_token )*, ts +seq_added_token := (ts,',',ts, element_token)+ +fo_added_token := (ts,'/',ts, element_token)+ +or_added_token := (ts,'|',ts, element_token)+ # not currently supported +and_added_token := (ts,'&',ts, element_token)+ # not currently supported +element_token := negpos_indicator?, ts, (literal/range/group/name),ts, occurence_indicator? +group := '(',ts, element_token, ( seq_added_token / fo_added_token / or_added_token / and_added_token )*, ts, ')' + +negpos_indicator := '+'/'-' +occurence_indicator := '+'/'*'/'?' +unreportedname := '<', name, '>' +name := [a-zA-Z_],[a-zA-Z0-9_]* +<ts> := ( [ \011-\015]+ / ('#',-'\n'+,'\n')+ )* +literal := ("'",(CHARNOSNGLQUOTE/ESCAPEDCHAR)*,"'") / ('"',(CHARNODBLQUOTE/ESCAPEDCHAR)*,'"') + + +range := '[',CHARBRACE?,CHARDASH?, (CHARRANGE/CHARNOBRACE)*, CHARDASH?,']' +CHARBRACE := ']' +CHARDASH := '-' +CHARRANGE := CHARNOBRACE, '-', CHARNOBRACE +CHARNOBRACE := ESCAPEDCHAR/CHAR +CHAR := -[]] +ESCAPEDCHAR := '\\',( SPECIALESCAPEDCHAR / OCTALESCAPEDCHAR ) +SPECIALESCAPEDCHAR := [\\abfnrtv] +OCTALESCAPEDCHAR := [0-7],[0-7]?,[0-7]? +CHARNODBLQUOTE := -[\\"]+ +CHARNOSNGLQUOTE := -[\\']+ +''' + +def parse( instr = declaration, parserelement = 'declarationset' ): + tbl = ( + (parserelement, Table, parsertuplelist[parsernamelist.index( parserelement )] ), + ) + return tag( instr, tbl) + +if __name__ == '__main__': + import sys, pprint + pprint.pprint( apply( parse, tuple( sys.argv[1:] ) ) ) + + diff --git a/intern/python/modules/simpleparse/generator.py b/intern/python/modules/simpleparse/generator.py new file mode 100644 index 00000000000..67f83106dfe --- /dev/null +++ b/intern/python/modules/simpleparse/generator.py @@ -0,0 +1,432 @@ +from TextTools.TextTools import * +import bootstrap # the hand-coded parser +import operator, strop as string + +def err( value ): + print value + +class _BaseGenerator: + ''' + Class providing the functions required to turn a + parse tree as generated by the bootstrap parser into + a new set of parser tuples. I.e a parser generator :) + Effectively this is the bootstrap generator. + ''' + def __init__( self, syntaxstring = bootstrap.declaration, parserelement = 'declarationset' ): + ''' + Turn syntaxstring into a parsetree using + the bootstrap module's parse command + ''' + # should do some error checking in here :) + self.syntaxstring = syntaxstring + self.parsetree = bootstrap.parse( syntaxstring, parserelement )[1][0] # the child list + self.nameset = [] + self.tupleset = [] + def stringval( self, tuple ): + ''' + Return the string value for a parse-result tuple + ''' + return self.syntaxstring[ tuple[1]:tuple[2] ] + def build( self, prebuiltnodes=() ): + ''' + Build a new parsing table from the syntax string. + New parsers may be accessed using the parserbyname method. + + The pre-built nodes are parsing tables for inclusion in the grammar + Added version 1.0.1 to provide greater extensibility. + ''' + # first register all declared names to reserve their indicies + #if self.__class__.__name__ == 'Generator': + # import pdb + # pdb.set_trace() + for key, value in prebuiltnodes: + self.nameset.append( key ) + self.tupleset.append( value ) + for decl in self.parsetree[3]: + #print decl + name = self.stringval( decl[3][0] ) + self.nameset.append( name ) + self.tupleset.append( None) + #print 'Declared names:',self.nameset + for i in range( len( self.nameset)): + #print '''Processing declaration %s '''% self.nameset[i] + dataset = self.group( ('group',1,2, self.parsetree[3][i][3][1:]), self ) + if dataset: + self.tupleset[i] = tuple( dataset) + def parserbyname( self, name ): + ''' + Retrieve a single parsing tuple by its production name + ''' + try: + return self.tupleset[ self.nameset.index( name ) ] + except ValueError: + print '''Could not find parser tuple of name''', name + return () + def allparsers (self): + ''' + Return a list of (productionname, parsingtuple) values + suitable for passing to another generator as its pre-calculated + set of parsing tuples. (See method build) + ''' + returnvalue = [] + for i in range(len( self.nameset)): + returnvalue.append ( (self.nameset[i],self.tupleset[i]) ) + return returnvalue + ### Actual processing functions... + def element_token( self, eltup, genobj, reportname=None ): + # Determine the type of element + # Descry the various options for the element + negative = optional = repeating = element = None + for data in eltup[3]: + if data[0] == 'negpos_indicator': + if genobj.stringval ( data ) == '-': + negative = 1 + elif data[0] == 'occurence_indicator': + data = genobj.stringval ( data ) + if data == '*': + optional = 1 + repeating = 1 + elif data == '+': + repeating = 1 + elif data == '?': + optional = 1 + else: + err( 'Unknown occurence indicator '+ data ) + else: + element = data + # call the appropriate handler + try: + return getattr( self, element [0])( element, genobj, negative, repeating, optional) + except AttributeError,x: + err( '''Didn't find handler for element type %s, parser build aborted'''%element [0]) + raise x + + def group( self, els, genobj, negative= None, repeating=None, optional = None, reportname=None): + ''' + Determine what type of group we're dealing with and determine what + function to call, then call it. + ''' + groupset = els[3] + # groupset is an element_token followed by a possible added_token + if groupset: + els = [] + els.append( groupset[0] ) + if len(groupset) > 1: + els[len(els):] = groupset[1][3] + gtype = groupset[1][0] + if gtype == 'seq_added_token': + return self.seq( els, genobj, negative, repeating, optional, reportname ) + elif gtype == 'fo_added_token': + return self.fo( els, genobj, negative, repeating, optional, reportname ) + else: + err( '''An as-yet undefined group type was used! %s'''%gtype ) + else: # default "sequence" of one... could do more work and make it process the results specifically, but that's optimisation ;) + return self.seq( els, genobj, negative, repeating, optional, None ) + else: + return [] + + + def seq( self, els, genobj, negative= None, repeating=None, optional = None, reportname=None ): + elset = map( self.element_token, els, [genobj]*len( els) ) + elset = reduce( operator.add, elset ) + if negative: + if repeating: + if optional: + return [(None, SubTable, (( None, SubTable,( (None, SubTable, tuple( elset), 2,1), (None, Fail, Here),(None,Skip,1) ), 2,1 ), ( None, EOF, Here, -1,1 ), ), ), ] + else: # not optional + return [(None, SubTable, (( None, SubTable,( (None, SubTable, tuple( elset), 2,1), (None, Fail, Here),(None,Skip,1) )), ( None, SubTable,( (None, SubTable, tuple( elset), 2,1), (None, Fail, Here),(None,Skip,1) ), 2,1 ), ( None, EOF, Here, -1,1 ), ), ), ] + else: # single + if optional: + return [ (None, SubTable, ( (None, SubTable, tuple( elset), 2,1), (None, Fail, Here), (None, Skip, 1) ),1,1) ] + else: # not optional + return [ (None, SubTable, ( (None, SubTable, tuple( elset), 2,1), (None, Fail, Here), (None, Skip, 1) )) ] + else: # positive + if repeating: + if optional: + return [ (None, SubTable, tuple( elset), 1,0) ] + else: # not optional + + return [ (None, SubTable, tuple( elset)), (None, SubTable, tuple( elset), 1,0) ] + else: # single + if optional: + return [ (None, SubTable, tuple( elset), 1,1) ] + else: # not optional + return [ (None, SubTable, tuple( elset)) ] + + def fo( self, els, genobj, negative= None, repeating=None, optional = None, reportname=None ): + elset = map( self.element_token, els, [genobj]*len( els) ) + elset = reduce( operator.add, elset ) + elset = [] + for el in els: + dataset = self.element_token( el, genobj ) + if len( dataset) == 1 and len(dataset[0]) == 3: # we can alter the jump states with impunity + elset.append( dataset[0] ) + else: # for now I'm eating the inefficiency and doing an extra SubTable for all elements to allow for easy calculation of jumps within the FO group + elset.append( (None, SubTable, tuple( dataset )) ) + if negative: + # all negative FO's have the meaning "a positive, single, non-optional FO not matching" + # the flags modify how failure and continuation are handled in that case, so they can use + # the same procset. + # Note: Negative FO groups are _very_ heavy, they have normally about 4 subtable calls + # guess we'll find out how well mxTextTools handles recursive tables :) + procset = [] + for i in range( len( elset) -1): # note that we have to treat last el specially + ival = elset[i] + (1,len(elset)-i) + procset.append( ival ) # if success, jump past end + procset.append( elset[-1] + (2,1) ) # will cause a failure if last element doesn't match + procset.append( (None, Fail, Here ) ) + procset.append( (None, Skip, 1) ) + # if the following looks familiar you probably looked at seq above + if repeating: + if optional: + return [ (None, SubTable, ( (None, SubTable, tuple( procset), 2,1), (None, EOF, Here,-1,1) ) ) ] + else: # not optional + return [ (None, SubTable, ( (None, SubTable, tuple( procset)),(None, SubTable, tuple( procset), 2,1), (None, EOF, Here,-1,1) ) ) ] + else: # single + if optional: + return [ (None, SubTable, tuple( procset), 1,1) ] + else: # not optional + return [ (None, SubTable, tuple( procset) ) ] + else: # positive + if repeating: + if optional: + procset = [] + for i in range( len( elset)): + procset.append( elset[i] + (1,-i) ) # if success, go back to start which is -i elements back + return procset + else: # not optional + procset = [] + for i in range( len( elset)-1): + procset.append( elset[i] + (1, len(elset)-i+1) ) # if success, jump to later section + procset.append( elset[-1] + ( 1, 2) ) # will cause a failure if last element doesn't match using an explicit fail command + procset.append( (None, Fail, Here) ) # will cause a failure if last element doesn't match using an explicit fail command + for i in range( len( elset)-1): + procset.append( elset[i] + (1, -i) ) # if success, go back to start which is -i elements back + procset.append( elset[-1] + ( 1, 1-(len(elset)) ) ) # will cause a failure if last element doesn't match using an explicit fail command + return procset + else: # single + if optional: + procset = [] + for i in range( len( elset)): + procset.append( elset[i] + (1,len(elset)-i) ) # if success, jump past end + return procset + else: # not optional + procset = [] + for i in range( len( elset) -1): # note that we have to treat last el specially + procset.append( elset[i] + (1,len(elset)-i) ) # if success, jump past end + procset.append( elset[-1] ) # will cause a failure if last element doesn't match + return procset + + def name( self, value, genobj, negative = None, repeating = None, optional = None, reportname=None ): + svalue = genobj.stringval( value ) + try: + sindex = genobj.nameset.index( svalue ) + except ValueError: # eeps, a value not declared + try: + sindex = genobj.nameset.index( '<'+svalue+'>' ) + svalue = None + except ValueError: + err( '''The name %s could not be found in the declarationset. The parser will not compile.'''%svalue) + genobj.nameset.append( svalue ) + genobj.tupleset.append( None ) + sindex = len( genobj.nameset) - 1 + if negative: + if repeating: + if optional: + return [ (svalue, SubTable, ( (None, TableInList, (genobj.tupleset, sindex), 1,3), (None, EOF, Here,1,2), (None,Skip,1,-2,-2) ) ) ] + else: # not optional + return [ (svalue, SubTable, ( (None, TableInList, (genobj.tupleset, sindex),2,1),(None, Fail, Here),(None, Skip, 1), (None, TableInList, (genobj.tupleset, sindex), 1,3), (None, EOF, Here,1,2), (None,Skip,1,-2,-2) ) ) ] + else: # single + if optional: + return [ (None, SubTable, ( (None, TableInList, (genobj.tupleset, sindex),2,1),(None, Fail, Here),(svalue, Skip, 1) ),1,1) ] + else: # not optional + return [ (None, SubTable, ( (None, TableInList, (genobj.tupleset, sindex),2,1),(None, Fail, Here),(svalue, Skip, 1) )) ] + else: # positive + if repeating: + if optional: + return [ (svalue, TableInList, (genobj.tupleset, sindex), 1,0) ] + else: # not optional + return [ (svalue, TableInList, (genobj.tupleset, sindex)), (svalue, TableInList, (genobj.tupleset, sindex),1,0) ] + else: # single + if optional: + return [ (svalue, TableInList, (genobj.tupleset, sindex), 1,1) ] + else: # not optional + return [ (svalue, TableInList, (genobj.tupleset, sindex)) ] + specialescapedmap = { + 'a':'\a', + 'b':'\b', + 'f':'\f', + 'n':'\n', + 'r':'\r', + 't':'\t', + 'v':'\v', + '\\':'\\', + '"':'"', + "'":"'", + } + + def escapedchar( self, el, genobj ): + svalue = '' + if el[3][0][0] == 'SPECIALESCAPEDCHAR': + svalue = svalue + self.specialescapedmap[ genobj.stringval( el[3][0] ) ] + elif el[3][0][0] == 'OCTALESCAPEDCHAR': + #print 'OCTALESCAPEDCHAR', genobj.stringval( el) + ovnum = 0 + ovpow = 0 + ov = genobj.stringval( el[3][0] ) + while ov: + ovnum = ovnum + int( ov[-1] ) * (8**ovpow) + ovpow = ovpow + 1 + ov = ov[:-1] + svalue = svalue + chr( ovnum ) + #print 'svalue ', `svalue` + return svalue + + + def literal( self, value, genobj, negative = None, repeating=None, optional=None, reportname=None ): + ''' + Calculate the tag-table for a literal element token + ''' + svalue = '' + for el in value[3]: + if el[0] in ('CHARNOSNGLQUOTE', 'CHARNODBLQUOTE'): + svalue = svalue+genobj.stringval( el ) + elif el[0] == 'ESCAPEDCHAR': + svalue = svalue + self.escapedchar( el, genobj ) + #print 'literal value', `genobj.stringval( value )` + #print ' svalue', `svalue` + # svalue = svalue[1:-1] + if negative: + if repeating: # a repeating negative value, a "search" in effect + if optional: # if fails, then go to end of file + return [ (None, sWordStart, BMS( svalue ),1,2), (None, Move, ToEOF ) ] + else: # must first check to make sure the current position is not the word, then the same + return [ (None, Word, svalue, 2,1),(None, Fail, Here),(None, sWordStart, BMS( svalue ),1,2), (None, Move, ToEOF ) ] + #return [ (None, Word, svalue, 2,1),(None, Fail, Here),(None, WordStart, svalue,1,2), (None, Move, ToEOF ) ] + else: # a single-character test saying "not a this" + if optional: # test for a success, move back if success, move one forward if failure + if len(svalue) > 1: + return [ (None, Word, svalue, 2,1), + (None, Skip, -len(svalue), 2,2), # backup if this was the word to start of word, succeed + (None, Skip, 1 ) ] # else just move one character and succeed + else: # Uses Is test instead of Word test, should be faster I'd imagine + return [ (None, Is, svalue, 2,1), + (None, Skip, -1, 2,2), # backtrack + (None, Skip, 1 ) ] # else just move one character and succeed + else: # must find at least one character not part of the word, so + if len(svalue) > 1: + return [ (None, Word, svalue, 2,1), + (None, Fail, Here), + (None, Skip, 1 ) ] # else just move one character and succeed + else: #must fail if it finds or move one forward + return [ (None, Is, svalue, 2,1), + (None, Fail, Here), + (None, Skip, 1 ) ] # else just move one character and succeed + else: # positive + if repeating: + if optional: + if len(svalue) > 1: + return [ (None, Word, svalue, 1,0) ] + else: + return [ (None, Is, svalue, 1,0) ] + else: # not optional + if len(svalue) > 1: + return [ (None, Word, svalue),(None, Word, svalue,1,0) ] + else: + return [ (None, Is, svalue),(None, Is, svalue,1,0) ] + else: # not repeating + if optional: + if len(svalue) > 1: + return [ (None, Word, svalue, 1,1) ] + else: + return [ (None, Is, svalue, 1,1) ] + else: # not optional + if len(svalue) > 1: + return [ (None, Word, svalue) ] + else: + return [ (None, Word, svalue) ] + + def charnobrace( self, cval, genobj ): + #print 'cval', cval + if cval[3][0][0] == 'ESCAPEDCHAR': + return self.escapedchar( cval[3][0], genobj ) + #print '''Straight non-brace character''', `genobj.stringval( cval[3][0] )` + return genobj.stringval( cval ) + def range( self, value, genobj, negative = None, repeating=None, optional=None, reportname=None ): + dataset = [] + for cval in value[3]: + if cval[0] == 'CHARBRACE': + dataset.append( ']') + elif cval[0] == 'CHARDASH': + dataset.append( '-') + elif cval[0] == 'CHARNOBRACE': + dataset.append( self.charnobrace( cval, genobj ) ) + elif cval[0] == 'CHARRANGE': + start = ord( self.charnobrace( cval[3][0], genobj ) ) + end = ord( self.charnobrace( cval[3][1], genobj ) ) + if start < end: + dataset.append( string.join( map( chr, range( start, end +1 ) ), '' ) ) + else: + dataset.append( string.join( map( chr, range( end, start +1 ) ), '' ) ) + else: + dataset.append( genobj.stringval( cval ) ) + if negative: + #svalue = set( string.join( dataset, '' ), 0 ) + svalue = string.join( dataset, '' ) + else: + #svalue = set( string.join( dataset, '' ), 1) + svalue = string.join( dataset, '' ) + if negative: + if repeating: + if optional: + #return [ (None, AllInSet, svalue, 1 ) ] + return [ (None, AllNotIn, svalue, 1 ) ] + else: # not optional + #return [ (None, AllInSet, svalue ) ] + return [ (None, AllNotIn, svalue ) ] + else: # not repeating + if optional: + #return [ (None, IsInSet, svalue, 1 ) ] + return [ (None, IsNotIn, svalue, 1 ) ] + else: # not optional + #return [ (None, IsInSet, svalue ) ] + return [ (None, IsNotIn, svalue ) ] + else: + if repeating: + if optional: + #return [ (None, AllInSet, svalue, 1 ) ] + return [ (None, AllIn, svalue, 1 ) ] + else: # not optional + #return [ (None, AllInSet, svalue ) ] + return [ (None, AllIn, svalue ) ] + else: # not repeating + if optional: + #return [ (None, IsInSet, svalue, 1 ) ] + return [ (None, IsIn, svalue, 1 ) ] + else: # not optional + #return [ (None, IsInSet, svalue ) ] + return [ (None, IsIn, svalue ) ] + +class Generator( _BaseGenerator ): + def __init__( self, syntaxstring , parser ): + self.syntaxstring = syntaxstring + self.parsetree = [0,1,2, tag( syntaxstring, parser )[1] ] + self.nameset = [] + self.tupleset = [] + +def buildParser( declaration, prebuiltnodes=() ): + ''' + End-developer function to create an application-specific parser + the parsing tuple is available on the returned object as + object.parserbyname( 'declaredname' ), where declaredname is the + name you defined in your language defintion file. + + The declaration argument is the text of a language defintion file. + ''' + proc = _BaseGenerator( ) + proc.build() + newgen = Generator( declaration, proc.parserbyname( 'declarationset' ) ) + newgen.build( prebuiltnodes=prebuiltnodes ) + return newgen + + diff --git a/intern/python/modules/util/README.txt b/intern/python/modules/util/README.txt new file mode 100644 index 00000000000..60321531bd7 --- /dev/null +++ b/intern/python/modules/util/README.txt @@ -0,0 +1,13 @@ +3D utilities + + (c) onk, 1998-2001 + + A few low level & math utilities for 2D/3D computations as: + + - area.py: solving close packing problems in 2D + + - vect.py: low level / OO like matrix and vector calculation module + + - vectools.py: more vector tools for intersection calculation, etc. + + - tree.py: binary trees (used by the BSPtree module) diff --git a/intern/python/modules/util/__init__.py b/intern/python/modules/util/__init__.py new file mode 100644 index 00000000000..ee6b0cef939 --- /dev/null +++ b/intern/python/modules/util/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["vect", "vectools", "area", "quat", "blvect", "tree"] + diff --git a/intern/python/modules/util/quat.py b/intern/python/modules/util/quat.py new file mode 100644 index 00000000000..d23b1c3f6d9 --- /dev/null +++ b/intern/python/modules/util/quat.py @@ -0,0 +1,109 @@ +"""Quaternion module + + This module provides conversion routines between Matrices, Quaternions (rotations around + an axis) and Eulers. + + (c) 2000, onk@section5.de """ + +# NON PUBLIC XXX + +from math import sin, cos, acos +from util import vect +reload(vect) + +Vector = vect.Vector + +Matrix = vect.Matrix + +class Quat: + """Simple Quaternion class + +Usually, you create a quaternion from a rotation axis (x, y, z) and a given +angle 'theta', defining the right hand rotation: + + q = fromRotAxis((x, y, z), theta) + +This class supports multiplication, providing an efficient way to +chain rotations""" + + def __init__(self, w = 1.0, x = 0.0, y = 0.0, z = 0.0): + self.v = (w, x, y, z) + + def asRotAxis(self): + """returns rotation axis (x, y, z) and angle phi (right hand rotation)""" + phi2 = acos(self.v[0]) + if phi2 == 0.0: + return Vector(0.0, 0.0, 1.0), 0.0 + else: + s = 1 / (sin(phi2)) + + v = Vector(s * self.v[1], s * self.v[2], s * self.v[3]) + return v, 2.0 * phi2 + + def __mul__(self, other): + w1, x1, y1, z1 = self.v + w2, x2, y2, z2 = other.v + + w = w1*w2 - x1*x2 - y1*y2 - z1*z2 + x = w1*x2 + x1*w2 + y1*z2 - z1*y2 + y = w1*y2 - x1*z2 + y1*w2 + z1*x2 + z = w1*z2 + x1*y2 - y1*x2 + z1*w2 + return Quat(w, x, y, z) + + def asMatrix(self): + w, x, y, z = self.v + + v1 = Vector(1.0 - 2.0 * (y*y + z*z), 2.0 * (x*y + w*z), 2.0 * (x*z - w*y)) + v2 = Vector(2.0 * (x*y - w*z), 1.0 - 2.0 * (x*x + z*z), 2.0 * (y*z + w*x)) + v3 = Vector(2.0 * (x*z + w*y), 2.0 * (y*z - w*x), 1.0 - 2.0 * (x*x + y*y)) + + return Matrix(v1, v2, v3) + +# def asEuler1(self, transp = 0): +# m = self.asMatrix() +# if transp: +# m = m.transposed() +# return m.asEuler() + + def asEuler(self, transp = 0): + from math import atan, asin, atan2 + w, x, y, z = self.v + x2 = x*x + z2 = z*z + tmp = x2 - z2 + r = (w*w + tmp - y*y ) + phi_z = atan2(2.0 * (x * y + w * z) , r) + phi_y = asin(2.0 * (w * y - x * z)) + phi_x = atan2(2.0 * (w * x + y * z) , (r - 2.0*tmp)) + + return phi_x, phi_y, phi_z + +def fromRotAxis(axis, phi): + """computes quaternion from (axis, phi)""" + phi2 = 0.5 * phi + s = sin(phi2) + return Quat(cos(phi2), axis[0] * s, axis[1] * s, axis[2] * s) + +#def fromEuler1(eul): + #qx = fromRotAxis((1.0, 0.0, 0.0), eul[0]) + #qy = fromRotAxis((0.0, 1.0, 0.0), eul[1]) + #qz = fromRotAxis((0.0, 0.0, 1.0), eul[2]) + #return qz * qy * qx + +def fromEuler(eul): + from math import sin, cos + e = eul[0] / 2.0 + cx = cos(e) + sx = sin(e) + e = eul[1] / 2.0 + cy = cos(e) + sy = sin(e) + e = eul[2] / 2.0 + cz = cos(e) + sz = sin(e) + + w = cx * cy * cz - sx * sy * sz + x = sx * cy * cz - cx * sy * sz + y = cx * sy * cz + sx * cy * sz + z = cx * cy * sz + sx * sy * cz + return Quat(w, x, y, z) diff --git a/intern/python/modules/util/tree.py b/intern/python/modules/util/tree.py new file mode 100644 index 00000000000..313159239c6 --- /dev/null +++ b/intern/python/modules/util/tree.py @@ -0,0 +1,215 @@ +# Basisklasse fuer Baumstruktur +# Object-orientiertes Programmieren Wi/97 +# +# (c) Martin Strubel, Fakultaet fuer Physik, Universitaet Konstanz +# (strubi@gandalf.physik.uni-konstanz.de) + +# updated 08.2001 + +"""Simple binary tree module + + This module demonstrates a binary tree class. + + Example:: + + a = [5, 8, 8, 3, 7, 9] + t1 = Tree() + t1.fromList(a) + + Operations on tree nodes are done by writing a simple operator class:: + + class myOp: + def __init__(self): + ... + def operate(self, node): + do_something(node) + + and calling the recursive application:: + + op = MyOp() + t1.recurse(op) + + Objects inserted into the tree can be of any kind, as long as they define a + comparison operation. +""" + +def recurse(node, do): + if node == None: + return + recurse(node.left, do) + do(node) + recurse(node.right, do) + +class Nullnode: + def __init__(self): + self.left = None + self.right = None + self.depth = 0 + + def recurse(self, do): + if self == Nil: + return + self.left.recurse(do) + do(self) + self.right.recurse(do) + +Nil = Nullnode() + +def nothing(x): + return x + +class Node(Nullnode): + def __init__(self, data = None): + self.left = Nil + self.right = Nil + self.data = data + self.depth = 0 + + def __repr__(self): + return "Node: %s" % self.data + + def insert(self, node): + if node.data < self.data: + if self.left != Nil: + return self.left.insert(node) + else: + node.depth = self.depth + 1 + self.left = node + # print "inserted left" + return self + + elif node.data > self.data: + if self.right != Nil: + return self.right.insert(node) + else: + node.depth = self.depth + 1 + self.right = node + # print "inserted right" + return self + else: + return self.insert_equal(node) + + def find(self, node, do = nothing): + if node.data < self.data: + if self.left != Nil: + return self.left.find(node, do) + else: + return self + elif node.data > self.data: + if self.right != Nil: + return self.right.find(node, do) + else: + return self + else: + return do(self) + + def remove(self, node): + newpar + return self + def insert_equal(self, node): + #print "insert:", + self.equal(node) + return self + def found_equal(self, node): + self.equal(node) + def equal(self, node): + # handle special + print "node (%s) is equal self (%s)" % (node, self) + def copy(self): + n = Node(self.data) + return n + + def recursecopy(self): + n = Node() + n.data = self.data + n.flag = self.flag + if self.left != Nil: + n.left = self.left.recursecopy() + if self.right != Nil: + n.right = self.right.recursecopy() + + return n + +class NodeOp: + def __init__(self): + self.list = [] + def copy(self, node): + self.list.append(node.data) + +class Tree: + def __init__(self, root = None): + self.root = root + self.n = 0 + def __radd__(self, other): + print other + t = self.copy() + t.merge(other) + return t + def __repr__(self): + return "Tree with %d elements" % self.n + def insert(self, node): + if self.root == None: + self.root = node + else: + self.root.insert(node) + self.n += 1 + def recurse(self, do): + if self.root == None: + return + self.root.recurse(do) + def find(self, node): + return self.root.find(node) + def remove(self, node): + self.root.remove(node) + def copy(self): + "make true copy of self" + t = newTree() + c = NodeOp() + self.recurse(c.copy) + t.fromList(c.list) + return t + def asList(self): + c = NodeOp() + self.recurse(c.copy) + return c.list + def fromList(self, list): + for item in list: + n = Node(item) + self.insert(n) + def insertcopy(self, node): + n = node.copy() + self.insert(n) + def merge(self, other): + other.recurse(self.insertcopy) +# EXAMPLE: + +newTree = Tree + +def printnode(x): + print "Element: %s, depth: %s" % (x, x.depth) + +def test(): + a = [5, 8, 8, 3, 7, 9] + t1 = Tree() + t1.fromList(a) + + b = [12, 4, 56, 7, 34] + t2 = Tree() + t2.fromList(b) + + print "tree1:" + print t1.asList() + print "tree2:" + print t2.asList() + print '-----' + print "Trees can be added:" + + + t3 = t1 + t2 + print t3.asList() + print "..or alternatively merged:" + t1.merge(t2) + print t1.asList() + +if __name__ == '__main__': + test() diff --git a/intern/python/modules/util/vect.py b/intern/python/modules/util/vect.py new file mode 100644 index 00000000000..3724079519b --- /dev/null +++ b/intern/python/modules/util/vect.py @@ -0,0 +1,480 @@ +#------------------------------------------------------------------------------ +# simple 3D vector / matrix class +# +# (c) 9.1999, Martin Strubel // onk@section5.de +# updated 4.2001 +# +# This module consists of a rather low level command oriented +# and a more OO oriented part for 3D vector/matrix manipulation +# +# For documentation, please look at the EXAMPLE code below - execute by: +# +# > python vect.py +# +# +# permission to use in scientific and free programs granted +# In doubt, please contact author. +# +# history: +# +# 1.5: Euler/Rotation matrix support moved here +# 1.4: high level Vector/Matrix classes extended/improved +# + +"""Vector and matrix math module + + Version 1.5 + by onk@section5.de + + This is a lightweight 3D matrix and vector module, providing basic vector + and matrix math plus a more object oriented layer. + + For examples, look at vect.test() +""" + +VERSION = 1.5 + +TOLERANCE = 0.0000001 + +VectorType = 'Vector3' +MatrixType = 'Matrix3' +FloatType = type(1.0) + +def dot(x, y): + "(x,y) - Returns the dot product of vector 'x' and 'y'" + return (x[0] * y[0] + x[1] * y[1] + x[2] * y[2]) + +def cross(x, y): + "(x,y) - Returns the cross product of vector 'x' and 'y'" + return (x[1] * y[2] - x[2] * y[1], + x[2] * y[0] - x[0] * y[2], + x[0] * y[1] - x[1] * y[0]) + +def matrix(): + "Returns Unity matrix" + return ((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0)) + +def matxvec(m, x): + "y = matxvec(m,x) - Returns product of Matrix 'm' and vector 'x'" + vx = m[0][0] * x[0] + m[1][0] * x[1] + m[2][0] * x[2] + vy = m[0][1] * x[0] + m[1][1] * x[1] + m[2][1] * x[2] + vz = m[0][2] * x[0] + m[1][2] * x[1] + m[2][2] * x[2] + return (vx, vy, vz) + +def matfromnormal(z, y = (0.0, 1.0, 0.0)): + """(z, y) - returns transformation matrix for local coordinate system + where 'z' = local z, with optional *up* axis 'y'""" + y = norm3(y) + x = cross(y, z) + y = cross(z, x) + return (x, y, z) + +def matxmat(m, n): + "(m,n) - Returns matrix product of 'm' and 'n'" + return (matxvec(m, n[0]), matxvec(m, n[1]), matxvec(m, n[2])) + +def len(x): + "(x) - Returns the length of vector 'x'" + import math + return math.sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]) + +len3 = len # compatiblity reasons + +def norm3(x): + "(x) - Returns the vector 'x' normed to 1.0" + import math + r = math.sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]) + return (x[0]/r, x[1]/r, x[2]/r) + +def add3(x, y): + "(x,y) - Returns vector ('x' + 'y')" + return (x[0]+y[0], x[1]+y[1], x[2]+y[2]) + +def sub3(x, y): + "(x,y) - Returns vector ('x' - 'y')" + return ((x[0] - y[0]), (x[1] - y[1]), (x[2] - y[2])) + +def dist3(x, y): + "(x,y) - Returns euclidian distance from Point 'x' to 'y'" + return len3(sub3(x, y)) + +def scale3(s, x): + "(s,x) - Returns the vector 'x' scaled by 's'" + return (s*x[0], s*x[1], s*x[2]) + +def scalemat(s,m): + "(s,m) - Returns the Matrix 'm' scaled by 's'" + return (scale3(s, m[0]), scale3(s, m[1]), scale3(s,m[2])) + +def invmatdet(m): + """n, det = invmat(m) - Inverts matrix without determinant correction. + Inverse matrix 'n' and Determinant 'det' are returned""" + + # Matrix: (row vectors) + # 00 10 20 + # 01 11 21 + # 02 12 22 + + wk = [0.0, 0.0, 0.0] + + t = m[1][1] * m[2][2] - m[1][2] * m[2][1] + wk[0] = t + det = t * m[0][0] + + t = m[2][1] * m[0][2] - m[0][1] * m[2][2] + wk[1] = t + det = det + t * m[1][0] + + t = m[0][1] * m[1][2] - m[1][1] * m[0][2] + wk[2] = t + det = det + t * m[2][0] + + v0 = (wk[0], wk[1], wk[2]) + + t = m[2][0] * m[1][2] - m[1][0] * m[2][2] + wk[0] = t + det = det + t * m[0][1] + + t = m[0][0] * m[2][2] - m[0][2] * m[2][0] + wk[1] = t + det = det + t * m[1][1] + + t = m[1][0] * m[0][2] - m[0][0] * m[1][2] + wk[2] = t + det = det + t * m[2][1] + + v1 = (wk[0], wk[1], wk[2]) + + t = m[1][0] * m[2][1] - m[1][1] * m[2][0] + wk[0] = t + det = det + t * m[0][2] + + t = m[2][0] * m[0][1] - m[0][0] * m[2][1] + wk[1] = t + det = det + t * m[1][2] + + t = m[0][0] * m[1][1] - m[1][0] * m[0][1] + wk[2] = t + det = det + t * m[2][2] + + v2 = (wk[0], wk[1], wk[2]) + # det = 3 * determinant + return ((v0,v1,v2), det/3.0) + +def invmat(m): + "(m) - Inverts the 3x3 matrix 'm', result in 'n'" + n, det = invmatdet(m) + if det < 0.000001: + raise ZeroDivisionError, "minor rank matrix" + d = 1.0/det + return (scale3(d, n[0]), + scale3(d, n[1]), + scale3(d, n[2])) + +def transmat(m): + # can be used to invert orthogonal rotation matrices + "(m) - Returns transposed matrix of 'm'" + return ((m[0][0], m[1][0], m[2][0]), + (m[0][1], m[1][1], m[2][1]), + (m[0][2], m[1][2], m[2][2])) + +def coplanar(verts): + "checks whether list of 4 vertices is coplanar" + v1 = verts[0] + v2 = verts[1] + a = sub3(v2, v1) + v1 = verts[1] + v2 = verts[2] + b = sub3(v2, v1) + if dot(cross(a,b), sub3(verts[3] - verts[2])) < 0.0001: + return 1 + return 0 + +################################################################################ +# Matrix / Vector highlevel +# (and slower) +# TODO: include better type checks ! + +class Vector: + """Vector class + + This vector class provides vector operations as addition, multiplication, etc. + + Usage:: + + v = Vector(x, y, z) + + where 'x', 'y', 'z' are float values, representing coordinates. + Note: This datatype emulates a float triple.""" + + def __init__(self, x = 0.0, y = 0.0, z = 0.0): + # don't change these to lists, very ugly referencing details... + self.v = (x, y, z) + # ... can lead to same data being shared by several matrices.. + # (unless you want this to happen) + self.type = VectorType + + def __neg__(self): + return self.new(-self.v[0], -self.v[1], -self.v[2]) + + def __getitem__(self, i): + "Tuple emulation" + return self.v[i] + +# def __setitem__(self, i, arg): +# self.v[i] = arg + + def new(self, *args): + return Vector(args[0], args[1], args[2]) + + def __cmp__(self, v): + "Comparison only supports '=='" + if self[0] == v[0] and self[1] == v[1] and self[1] == v[1]: + return 0 + return 1 + + def __add__(self, v): + "Addition of 'Vector' objects" + return self.new(self[0] + v[0], + self[1] + v[1], + self[2] + v[2]) + + def __sub__(self, v): + "Subtraction of 'Vector' objects" + return self.new(self[0] - v[0], + self[1] - v[1], + self[2] - v[2]) + + def __rmul__(self, s): # scaling by s + return self.new(s * self[0], s * self[1], s * self[2]) + + def __mul__(self, t): # dot product + """Left multiplikation supports: + + - scaling with a float value + + - Multiplikation with *Matrix* object""" + + if type(t) == FloatType: + return self.__rmul__(t) + elif t.type == MatrixType: + return Matrix(self[0] * t[0], self[1] * t[1], self[2] * t[2]) + else: + return dot(self, t) + + def cross(self, v): + "(Vector v) - returns the cross product of 'self' with 'v'" + return self.new(self[1] * v[2] - self[2] * v[1], + self[2] * v[0] - self[0] * v[2], + self[0] * v[1] - self[1] * v[0]) + + def __repr__(self): + return "(%.3f, %.3f, %.3f)" % (self.v[0], self.v[1], self.v[2]) + +class Matrix(Vector): + """Matrix class + + This class is representing a vector of Vectors. + + Usage:: + + M = Matrix(v1, v2, v3) + + where 'v'n are Vector class instances. + Note: This datatype emulates a 3x3 float array.""" + + def __init__(self, v1 = Vector(1.0, 0.0, 0.0), + v2 = Vector(0.0, 1.0, 0.0), + v3 = Vector(0.0, 0.0, 1.0)): + self.v = [v1, v2, v3] + self.type = MatrixType + + def __setitem__(self, i, arg): + self.v[i] = arg + + def new(self, *args): + return Matrix(args[0], args[1], args[2]) + + def __repr__(self): + return "Matrix:\n %s\n %s\n %s\n" % (self.v[0], self.v[1], self.v[2]) + + def __mul__(self, m): + """Left multiplication supported with: + + - Scalar (float) + + - Matrix + + - Vector: row_vector * matrix; same as self.transposed() * vector +""" + try: + if type(m) == FloatType: + return self.__rmul__(m) + if m.type == MatrixType: + M = matxmat(self, m) + return self.new(Vector(M[0][0], M[0][1], M[0][2]), + Vector(M[1][0], M[1][1], M[1][2]), + Vector(M[2][0], M[2][1], M[2][2])) + if m.type == VectorType: + v = matxvec(self, m) + return Vector(v[0], v[1], v[2]) + except: + raise TypeError, "bad multiplicator type" + + def inverse(self): + """returns the matrix inverse""" + M = invmat(self) + return self.new(Vector(M[0][0], M[0][1], M[0][2]), + Vector(M[1][0], M[1][1], M[1][2]), + Vector(M[2][0], M[2][1], M[2][2])) + + def transposed(self): + "returns the transposed matrix" + M = self + return self.new(Vector(M[0][0], M[1][0], M[2][0]), + Vector(M[1][0], M[1][1], M[2][1]), + Vector(M[2][0], M[1][2], M[2][2])) + + def det(self): + """returns the determinant""" + M, det = invmatdet(self) + return det + + def tr(self): + """returns trace (sum of diagonal elements) of matrix""" + return self.v[0][0] + self.v[1][1] + self.v[2][2] + + def __rmul__(self, m): + "Right multiplication supported with scalar" + if type(m) == FloatType: + return self.new(m * self[0], + m * self[1], + m * self[2]) + else: + raise TypeError, "bad multiplicator type" + + def __div__(self, m): + """Division supported with: + + - Scalar + + - Matrix: a / b equivalent b.inverse * a +""" + if type(m) == FloatType: + m = 1.0 /m + return m * self + elif m.type == MatrixType: + return self.inverse() * m + else: + raise TypeError, "bad multiplicator type" + + def __rdiv__(self, m): + "Right division of matrix equivalent to multiplication with matrix.inverse()" + return m * self.inverse() + + def asEuler(self): + """returns Matrix 'self' as Eulers. Note that this not the only result, due to +the nature of sin() and cos(). The Matrix MUST be a rotation matrix, i.e. orthogonal and +normalized.""" + from math import cos, sin, acos, asin, atan2, atan + mat = self.v + sy = mat[0][2] + # for numerical stability: + if sy > 1.0: + if sy > 1.0 + TOLERANCE: + raise RuntimeError, "FATAL: bad matrix given" + else: + sy = 1.0 + phi_y = -asin(sy) + + if abs(sy) > (1.0 - TOLERANCE): + # phi_x can be arbitrarely chosen, we set it = 0.0 + phi_x = 0.0 + sz = mat[1][0] + cz = mat[2][0] + phi_z = atan(sz/cz) + else: + cy = cos(phi_y) + cz = mat[0][0] / cy + sz = mat[0][1] / cy + phi_z = atan2(sz, cz) + + sx = mat[1][2] / cy + cx = mat[2][2] / cy + phi_x = atan2(sx, cx) + return phi_x, phi_y, phi_z + +Ex = Vector(1.0, 0.0, 0.0) +Ey = Vector(0.0, 1.0, 0.0) +Ez = Vector(0.0, 0.0, 1.0) + +One = Matrix(Ex, Ey, Ez) +orig = (0.0, 0.0, 0.0) + +def rotmatrix(phi_x, phi_y, phi_z, reverse = 0): + """Creates rotation matrix from euler angles. Rotations are applied in order +X, then Y, then Z. If the reverse is desired, you have to transpose the matrix after.""" + from math import sin, cos + s = sin(phi_z) + c = cos(phi_z) + matz = Matrix(Vector(c, s, 0.0), Vector(-s, c, 0.0), Ez) + + s = sin(phi_y) + c = cos(phi_y) + maty = Matrix(Vector(c, 0.0, -s), Ey, Vector(s, 0.0, c)) + + s = sin(phi_x) + c = cos(phi_x) + matx = Matrix(Ex, Vector(0.0, c, s), Vector(0.0, -s, c)) + + return matz * maty * matx + + +def test(): + "The module test" + print "********************" + print "VECTOR TEST" + print "********************" + + a = Vector(1.1, 0.0, 0.0) + b = Vector(0.0, 2.0, 0.0) + + print "vectors: a = %s, b = %s" % (a, b) + print "dot:", a * a + print "scalar:", 4.0 * a + print "scalar:", a * 4.0 + print "cross:", a.cross(b) + print "add:", a + b + print "sub:", a - b + print "sub:", b - a + print + print "********************" + print "MATRIX TEST" + print "********************" + c = a.cross(b) + m = Matrix(a, b, c) + v = Vector(1.0, 2.0, 3.0) + E = One + print "Original", m + print "det", m.det() + print "add", m + m + print "scalar", 0.5 * m + print "sub", m - 0.5 * m + print "vec mul", v * m + print "mul vec", m * v + n = m * m + print "mul:", n + print "matrix div (mul inverse):", n / m + print "scal div (inverse):", 1.0 / m + print "mat * inverse", m * m.inverse() + print "mat * inverse (/-notation):", m * (1.0 / m) + print "div scal", m / 2.0 + +# matrices with rang < dimension have det = 0.0 + m = Matrix(a, 2.0 * a, c) + print "minor rang", m + print "det:", m.det() + +if __name__ == '__main__': + test() + diff --git a/intern/python/modules/util/vectools.py b/intern/python/modules/util/vectools.py new file mode 100644 index 00000000000..860cd568875 --- /dev/null +++ b/intern/python/modules/util/vectools.py @@ -0,0 +1,142 @@ +"""Vector tools + + Various vector tools, basing on vect.py""" + +from vect import * + +EPSILON = 0.0001 + +def vecarea(v, w): + "Computes area of the span of vector 'v' and 'w' in 2D (not regarding z coordinate)" + return v[0]*w[1] - v[1]*w[0] + +def intersect(a1, b1, a2, b2): + """Computes 2D intersection of edges ('a1' -> 'b1') and ('a2' -> 'b2'), +returning normalized intersection parameter 's' of edge (a1 -> b1). +If 0.0 < 's' <= 1.0, +the two edges intersect at the point:: + + v = a1 + s * (b1 - a1) +""" + v = (b1[0] - a1[0], b1[1] - a1[1]) + w = (b2[0] - a2[0], b2[1] - a2[1]) + d0 = (a2[0] - a1[0]) + d1 = (a2[1] - a1[1]) + + det = w[0]*v[1] - w[1]*v[0] + if det == 0: return 0.0 + t = v[0]*d1 - v[1]*d0 + s = w[0]*d1 - w[1]*d0 + s /= det + t /= det + if s > 1.0 or s < 0.0: return 0.0 + if t > 1.0 or t < 0.0: return 0.0 + return s + +def insidetri(a, b, c, x): + "Returns 1 if 'x' is inside the 2D triangle ('a' -> 'b' -> 'c'), 0 otherwise" + v1 = norm3(sub3(b, a)) + v2 = norm3(sub3(c, a)) + v3 = norm3(sub3(x, a)) + + a1 = (vecarea(v1, v2)) + a2 = (vecarea(v1, v3)) + lo = min(0.0, a1) + hi = max(0.0, a1) + + if a2 < lo or a2 > hi: return 0 + + v2 = norm3(sub3(b, c)) + v3 = norm3(sub3(b, x)) + + a1 = (vecarea(v1, v2)) + a2 = (vecarea(v1, v3)) + + lo = min(0.0, a1) + hi = max(0.0, a1) + + if a2 < lo or a2 > hi: return 0 + + return 1 + +def plane_fromface(v1, v2, v3): + "Returns plane (normal, point) from 3 vertices 'v1', 'v2', 'v3'" + v = sub3(v2, v1) + w = sub3(v3, v1) + n = norm3(cross(v, w)) + return n, v1 + +def inside_halfspace(vec, plane): + "Returns 1 if point 'vec' inside halfspace defined by 'plane'" + n, t = plane + n = norm3(n) + v = sub3(vec, t) + if dot(n, v) < 0.0: + return 1 + else: + return 0 + +def half_space(vec, plane, tol = EPSILON): + """Determine whether point 'vec' is inside (return value -1), outside (+1) +, or lying in the plane 'plane' (return 0) of a numerical thickness +'tol' = 'EPSILON' (default).""" + n, t = plane + v = sub3(vec, t) + fac = len3(n) + + d = dot(n, v) + if d < -fac * tol: + return -1 + elif d > fac * tol: + return 1 + else: + return 0 + + +def plane_edge_intersect(plane, edge): + """Returns normalized factor 's' of the intersection of 'edge' with 'plane'. +The point of intersection on the plane is:: + + p = edge[0] + s * (edge[1] - edge[0]) + +""" + n, t = plane # normal, translation + mat = matfromnormal(n) + mat = transmat(mat) # inverse + v = matxvec(mat, sub3(edge[0], t)) #transformed edge points + w = matxvec(mat, sub3(edge[1], t)) + w = sub3(w, v) + if w[2] != 0.0: + s = -v[2] / w[2] + return s + else: + return None + +def insidecube(v): + "Returns 1 if point 'v' inside normalized cube, 0 otherwise" + if v[0] > 1.0 or v[0] < 0.0: + return 0 + if v[1] > 1.0 or v[1] < 0.0: + return 0 + if v[2] > 1.0 or v[2] < 0.0: + return 0 + return 1 + + +def flatproject(verts, up): + """Projects a 3D set (list of vertices) 'verts' into a 2D set according to +an 'up'-vector""" + z, t = plane_fromface(verts[0], verts[1], verts[2]) + y = norm3(up) + x = cross(y, z) + uvs = [] + for v in verts: + w = (v[0] - t[0], v[1] - t[1], v[2] - t[2]) + # this is the transposed 2x2 matrix * the vertex vector + uv = (dot(x, w), dot(y,w)) # do projection + uvs.append(uv) + return uvs + + + + diff --git a/intern/python/modules/vrml/__init__.py b/intern/python/modules/vrml/__init__.py new file mode 100644 index 00000000000..9e2ebe0fb86 --- /dev/null +++ b/intern/python/modules/vrml/__init__.py @@ -0,0 +1 @@ +"""The VRML import module""" diff --git a/intern/python/modules/vrml/basenodes.py b/intern/python/modules/vrml/basenodes.py new file mode 100644 index 00000000000..484f000738a --- /dev/null +++ b/intern/python/modules/vrml/basenodes.py @@ -0,0 +1,974 @@ +from scenegraph import Prototype, NULL, sceneGraph, IS, Script, ExternalPrototype, ROUTE +PROTO = Prototype +EXTERNPROTO = ExternalPrototype + +Anchor = Prototype( "Anchor", + { + 'bboxSize':('bboxSize', 'SFVec3f', 0), + 'children':('children', 'MFNode', 1), + 'parameter':('parameter', 'MFString', 1), + 'url':('url', 'MFString', 1), + 'description':('description', 'SFString', 1), + 'bboxCenter':('bboxCenter', 'SFVec3f', 0), + }, + { + 'bboxSize':[-1.0, -1.0, -1.0], + 'children':[], + 'parameter':[], + 'url':[], + 'description':'', + 'bboxCenter':[0.0, 0.0, 0.0], + }, + { + 'addChildren':('addChildren', 'MFNode', 0), + 'removeChildren':('removeChildren', 'MFNode', 0), + }, +) +Appearance = Prototype( "Appearance", + { + 'material':('material', 'SFNode', 1), + 'texture':('texture', 'SFNode', 1), + 'textureTransform':('textureTransform', 'SFNode', 1), + }, + { + 'material':NULL, + 'texture':NULL, + 'textureTransform':NULL, + }, + { + }, +) +AudioClip = Prototype( "AudioClip", + { + 'pitch':('pitch', 'SFFloat', 1), + 'loop':('loop', 'SFBool', 1), + 'description':('description', 'SFString', 1), + 'stopTime':('stopTime', 'SFTime', 1), + 'startTime':('startTime', 'SFTime', 1), + 'url':('url', 'MFString', 1), + }, + { + 'pitch':1.0, + 'loop':0, + 'description':'', + 'stopTime':0.0, + 'startTime':0.0, + 'url':[], + }, + { + 'isActive':('isActive', 'SFBool', 1), + 'duration_changed':('duration_changed', 'SFTime', 1), + }, +) +Background = Prototype( "Background", + { + 'groundAngle':('groundAngle', 'MFFloat', 1), + 'skyAngle':('skyAngle', 'MFFloat', 1), + 'frontUrl':('frontUrl', 'MFString', 1), + 'bottomUrl':('bottomUrl', 'MFString', 1), + 'groundColor':('groundColor', 'MFColor', 1), + 'backUrl':('backUrl', 'MFString', 1), + 'skyColor':('skyColor', 'MFColor', 1), + 'topUrl':('topUrl', 'MFString', 1), + 'rightUrl':('rightUrl', 'MFString', 1), + 'leftUrl':('leftUrl', 'MFString', 1), + }, + { + 'groundAngle':[], + 'skyAngle':[], + 'frontUrl':[], + 'bottomUrl':[], + 'groundColor':[], + 'backUrl':[], + 'skyColor':[[0.0, 0.0, 0.0]], + 'topUrl':[], + 'rightUrl':[], + 'leftUrl':[], + }, + { + 'isBound':('isBound', 'SFBool', 1), + 'set_bind':('set_bind', 'SFBool', 0), + }, +) +Billboard = Prototype( "Billboard", + { + 'bboxCenter':('bboxCenter', 'SFVec3f', 0), + 'bboxSize':('bboxSize', 'SFVec3f', 0), + 'children':('children', 'MFNode', 1), + 'axisOfRotation':('axisOfRotation', 'SFVec3f', 1), + }, + { + 'bboxCenter':[0.0, 0.0, 0.0], + 'bboxSize':[-1.0, -1.0, -1.0], + 'children':[], + 'axisOfRotation':[0.0, 1.0, 0.0], + }, + { + 'addChildren':('addChildren', 'MFNode', 0), + 'removeChildren':('removeChildren', 'MFNode', 0), + }, +) +Box = Prototype( "Box", + { + 'size':('size', 'SFVec3f', 0), + }, + { + 'size':[2.0, 2.0, 2.0], + }, + { + }, +) + + +Collision = Prototype( "Collision", + { + 'bboxCenter':('bboxCenter', 'SFVec3f', 0), + 'bboxSize':('bboxSize', 'SFVec3f', 0), + 'children':('children', 'MFNode', 1), + 'collide':('collide', 'SFBool', 1), + 'proxy':('proxy', 'SFNode', 0), + }, + { + 'bboxCenter':[0.0, 0.0, 0.0], + 'bboxSize':[-1.0, -1.0, -1.0], + 'children':[], + 'collide':1, + 'proxy':NULL, + }, + { + 'addChildren':('addChildren', 'MFNode', 0), + 'removeChildren':('removeChildren', 'MFNode', 0), + 'collideTime':('collideTime', 'SFTime', 1), + }, +) +Color = Prototype( "Color", + { + 'color':('color', 'MFColor', 1), + }, + { + 'color':[], + }, + { + }, +) +ColorInterpolator = Prototype( "ColorInterpolator", + { + 'key':('key', 'MFFloat', 1), + 'keyValue':('keyValue', 'MFColor', 1), + }, + { + 'key':[], + 'keyValue':[], + }, + { + 'value_changed':('value_changed', 'SFColor', 1), + 'set_fraction':('set_fraction', 'SFFloat', 0), + }, +) +Cone = Prototype( "Cone", + { + 'bottomRadius':('bottomRadius', 'SFFloat', 0), + 'side':('side', 'SFBool', 0), + 'bottom':('bottom', 'SFBool', 0), + 'height':('height', 'SFFloat', 0), + }, + { + 'bottomRadius':1.0, + 'side':1, + 'bottom':1, + 'height':2.0, + }, + { + }, +) +Coordinate = Prototype( "Coordinate", + { + 'point':('point', 'MFVec3f', 1), + }, + { + 'point':[], + }, + { + }, +) +CoordinateInterpolator = Prototype( "CoordinateInterpolator", + { + 'key':('key', 'MFFloat', 1), + 'keyValue':('keyValue', 'MFVec3f', 1), + }, + { + 'key':[], + 'keyValue':[], + }, + { + 'value_changed':('value_changed', 'MFVec3f', 1), + 'set_fraction':('set_fraction', 'SFFloat', 0), + }, +) +Cylinder = Prototype( "Cylinder", + { + 'bottom':('bottom', 'SFBool', 0), + 'side':('side', 'SFBool', 0), + 'radius':('radius', 'SFFloat', 0), + 'top':('top', 'SFBool', 0), + 'height':('height', 'SFFloat', 0), + }, + { + 'bottom':1, + 'side':1, + 'radius':1.0, + 'top':1, + 'height':2.0, + }, + { + }, +) +CylinderSensor = Prototype( "CylinderSensor", + { + 'maxAngle':('maxAngle', 'SFFloat', 1), + 'autoOffset':('autoOffset', 'SFBool', 1), + 'minAngle':('minAngle', 'SFFloat', 1), + 'enabled':('enabled', 'SFBool', 1), + 'offset':('offset', 'SFFloat', 1), + 'diskAngle':('diskAngle', 'SFFloat', 1), + }, + { + 'maxAngle':-1.0, + 'autoOffset':1, + 'minAngle':0.0, + 'enabled':1, + 'offset':0.0, + 'diskAngle':0.262, + }, + { + 'rotation_changed':('rotation_changed', 'SFRotation', 1), + 'isActive':('isActive', 'SFBool', 1), + 'trackPoint_changed':('trackPoint_changed', 'SFVec3f', 1), + }, +) +DirectionalLight = Prototype( "DirectionalLight", + { + 'color':('color', 'SFColor', 1), + 'ambientIntensity':('ambientIntensity', 'SFFloat', 1), + 'intensity':('intensity', 'SFFloat', 1), + 'on':('on', 'SFBool', 1), + 'direction':('direction', 'SFVec3f', 1), + }, + { + 'color':[1.0, 1.0, 1.0], + 'ambientIntensity':0.0, + 'intensity':1.0, + 'on':1, + 'direction':[0.0, 0.0, -1.0], + }, + { + }, +) +ElevationGrid = Prototype( "ElevationGrid", + { + 'xSpacing':('xSpacing', 'SFFloat', 0), + 'zSpacing':('zSpacing', 'SFFloat', 0), + 'xDimension':('xDimension', 'SFInt32', 0), + 'colorPerVertex':('colorPerVertex', 'SFBool', 0), + 'height':('height', 'MFFloat', 0), + 'texCoord':('texCoord', 'SFNode', 1), + 'normalPerVertex':('normalPerVertex', 'SFBool', 0), + 'ccw':('ccw', 'SFBool', 0), + 'color':('color', 'SFNode', 1), + 'normal':('normal', 'SFNode', 1), + 'creaseAngle':('creaseAngle', 'SFFloat', 0), + 'solid':('solid', 'SFBool', 0), + 'zDimension':('zDimension', 'SFInt32', 0), + }, + { + 'xSpacing':0.0, + 'zSpacing':0.0, + 'xDimension':0, + 'colorPerVertex':1, + 'height':[], + 'texCoord':NULL, + 'normalPerVertex':1, + 'ccw':1, + 'color':NULL, + 'normal':NULL, + 'creaseAngle':0.0, + 'solid':1, + 'zDimension':0, + }, + { + 'set_height':('set_height', 'MFFloat', 0), + }, +) +Extrusion = Prototype( "Extrusion", + { + 'endCap':('endCap', 'SFBool', 0), + 'scale':('scale', 'MFVec2f', 0), + 'ccw':('ccw', 'SFBool', 0), + 'crossSection':('crossSection', 'MFVec2f', 0), + 'solid':('solid', 'SFBool', 0), + 'convex':('convex', 'SFBool', 0), + 'creaseAngle':('creaseAngle', 'SFFloat', 0), + 'spine':('spine', 'MFVec3f', 0), + 'beginCap':('beginCap', 'SFBool', 0), + 'orientation':('orientation', 'MFRotation', 0), + }, + { + 'endCap':1, + 'scale':[[1.0, 1.0]], + 'ccw':1, + 'crossSection':[[1.0, 1.0], [1.0, -1.0], [-1.0, -1.0], [-1.0, 1.0], [1.0, 1.0]], + 'solid':1, + 'convex':1, + 'creaseAngle':0.0, + 'spine':[[0.0, 0.0, 0.0], [0.0, 1.0, 0.0]], + 'beginCap':1, + 'orientation':[[0.0, 0.0, 1.0, 0.0]], + }, + { + 'set_scale':('set_scale', 'MFVec2f', 0), + 'set_spine':('set_spine', 'MFVec3f', 0), + 'set_orientation':('set_orientation', 'MFRotation', 0), + 'set_crossSection':('set_crossSection', 'MFVec2f', 0), + }, +) +Fog = Prototype( "Fog", + { + 'fogType':('fogType', 'SFString', 1), + 'color':('color', 'SFColor', 1), + 'visibilityRange':('visibilityRange', 'SFFloat', 1), + }, + { + 'fogType':'LINEAR', + 'color':[1.0, 1.0, 1.0], + 'visibilityRange':0.0, + }, + { + 'isBound':('isBound', 'SFBool', 1), + 'set_bind':('set_bind', 'SFBool', 0), + }, +) +FontStyle = Prototype( "FontStyle", + { + 'justify':('justify', 'MFString', 0), + 'leftToRight':('leftToRight', 'SFBool', 0), + 'spacing':('spacing', 'SFFloat', 0), + 'horizontal':('horizontal', 'SFBool', 0), + 'language':('language', 'SFString', 0), + 'topToBottom':('topToBottom', 'SFBool', 0), + 'size':('size', 'SFFloat', 0), + 'style':('style', 'SFString', 0), + 'family':('family', 'SFString', 0), + }, + { + 'justify':['BEGIN'], + 'leftToRight':1, + 'spacing':1.0, + 'horizontal':1, + 'language':'', + 'topToBottom':1, + 'size':1.0, + 'style':'PLAIN', + 'family':'SERIF', + }, + { + }, +) +Group = Prototype( "Group", + { + 'bboxSize':('bboxSize', 'SFVec3f', 0), + 'children':('children', 'MFNode', 1), + 'bboxCenter':('bboxCenter', 'SFVec3f', 0), + }, + { + 'bboxSize':[-1.0, -1.0, -1.0], + 'children':[], + 'bboxCenter':[0.0, 0.0, 0.0], + }, + { + 'addChildren':('addChildren', 'MFNode', 0), + 'removeChildren':('removeChildren', 'MFNode', 0), + }, +) +ImageTexture = Prototype( "ImageTexture", + { + 'repeatS':('repeatS', 'SFBool', 0), + 'url':('url', 'MFString', 1), + 'repeatT':('repeatT', 'SFBool', 0), + }, + { + 'repeatS':1, + 'url':[], + 'repeatT':1, + }, + { + }, +) +IndexedFaceSet = Prototype( "IndexedFaceSet", + { + 'texCoordIndex':('texCoordIndex', 'MFInt32', 0), + 'normalIndex':('normalIndex', 'MFInt32', 0), + 'coordIndex':('coordIndex', 'MFInt32', 0), + 'convex':('convex', 'SFBool', 0), + 'texCoord':('texCoord', 'SFNode', 1), + 'normalPerVertex':('normalPerVertex', 'SFBool', 0), + 'coord':('coord', 'SFNode', 1), + 'ccw':('ccw', 'SFBool', 0), + 'color':('color', 'SFNode', 1), + 'normal':('normal', 'SFNode', 1), + 'creaseAngle':('creaseAngle', 'SFFloat', 0), + 'solid':('solid', 'SFBool', 0), + 'colorPerVertex':('colorPerVertex', 'SFBool', 0), + 'colorIndex':('colorIndex', 'MFInt32', 0), + }, + { + 'texCoordIndex':[], + 'normalIndex':[], + 'coordIndex':[], + 'convex':1, + 'texCoord':NULL, + 'normalPerVertex':1, + 'coord':NULL, + 'ccw':1, + 'color':NULL, + 'normal':NULL, + 'creaseAngle':0.0, + 'solid':1, + 'colorPerVertex':1, + 'colorIndex':[], + }, + { + 'set_normalIndex':('set_normalIndex', 'MFInt32', 0), + 'set_colorIndex':('set_colorIndex', 'MFInt32', 0), + 'set_texCoordIndex':('set_texCoordIndex', 'MFInt32', 0), + 'set_coordIndex':('set_coordIndex', 'MFInt32', 0), + }, +) +IndexedLineSet = Prototype( "IndexedLineSet", + { + 'coordIndex':('coordIndex', 'MFInt32', 0), + 'coord':('coord', 'SFNode', 1), + 'colorIndex':('colorIndex', 'MFInt32', 0), + 'colorPerVertex':('colorPerVertex', 'SFBool', 0), + 'color':('color', 'SFNode', 1), + }, + { + 'coordIndex':[], + 'coord':NULL, + 'colorIndex':[], + 'colorPerVertex':1, + 'color':NULL, + }, + { + 'set_colorIndex':('set_colorIndex', 'MFInt32', 0), + 'set_coordIndex':('set_coordIndex', 'MFInt32', 0), + }, +) +Inline = Prototype( "Inline", + { + 'url':('url', 'MFString', 1), + 'bboxSize':('bboxSize', 'SFVec3f', 0), + 'bboxCenter':('bboxCenter', 'SFVec3f', 0), + }, + { + 'url':[], + 'bboxSize':[-1.0, -1.0, -1.0], + 'bboxCenter':[0.0, 0.0, 0.0], + }, + { + }, +) +LOD = Prototype( "LOD", + { + 'level':('level', 'MFNode', 1), + 'range':('range', 'MFFloat', 0), + 'center':('center', 'SFVec3f', 0), + }, + { + 'level':[], + 'range':[], + 'center':[0.0, 0.0, 0.0], + }, + { + }, +) +Material = Prototype( "Material", + { + 'emissiveColor':('emissiveColor', 'SFColor', 1), + 'transparency':('transparency', 'SFFloat', 1), + 'shininess':('shininess', 'SFFloat', 1), + 'diffuseColor':('diffuseColor', 'SFColor', 1), + 'ambientIntensity':('ambientIntensity', 'SFFloat', 1), + 'specularColor':('specularColor', 'SFColor', 1), + }, + { + 'emissiveColor':[0.0, 0.0, 0.0], + 'transparency':0.0, + 'shininess':0.2, + 'diffuseColor':[0.8, 0.8, 0.8], + 'ambientIntensity':0.2, + 'specularColor':[0.0, 0.0, 0.0], + }, + { + }, +) +MovieTexture = Prototype( "MovieTexture", + { + 'loop':('loop', 'SFBool', 1), + 'speed':('speed', 'SFFloat', 1), + 'repeatT':('repeatT', 'SFBool', 0), + 'repeatS':('repeatS', 'SFBool', 0), + 'url':('url', 'MFString', 1), + 'startTime':('startTime', 'SFTime', 1), + 'stopTime':('stopTime', 'SFTime', 1), + }, + { + 'loop':0, + 'speed':1.0, + 'repeatT':1, + 'repeatS':1, + 'url':[], + 'startTime':0.0, + 'stopTime':0.0, + }, + { + 'isActive':('isActive', 'SFBool', 1), + 'duration_changed':('duration_changed', 'SFFloat', 1), + }, +) +NavigationInfo = Prototype( "NavigationInfo", + { + 'avatarSize':('avatarSize', 'MFFloat', 1), + 'speed':('speed', 'SFFloat', 1), + 'headlight':('headlight', 'SFBool', 1), + 'visibilityLimit':('visibilityLimit', 'SFFloat', 1), + 'type':('type', 'MFString', 1), + }, + { + 'avatarSize':[0.25, 1.6, 0.75], + 'speed':1.0, + 'headlight':1, + 'visibilityLimit':0.0, + 'type':['WALK'], + }, + { + 'isBound':('isBound', 'SFBool', 1), + 'set_bind':('set_bind', 'SFBool', 0), + }, +) +Normal = Prototype( "Normal", + { + 'vector':('vector', 'MFVec3f', 1), + }, + { + 'vector':[], + }, + { + }, +) +NormalInterpolator = Prototype( "NormalInterpolator", + { + 'key':('key', 'MFFloat', 1), + 'keyValue':('keyValue', 'MFVec3f', 1), + }, + { + 'key':[], + 'keyValue':[], + }, + { + 'value_changed':('value_changed', 'MFVec3f', 1), + 'set_fraction':('set_fraction', 'SFFloat', 0), + }, +) +OrientationInterpolator = Prototype( "OrientationInterpolator", + { + 'key':('key', 'MFFloat', 1), + 'keyValue':('keyValue', 'MFRotation', 1), + }, + { + 'key':[], + 'keyValue':[], + }, + { + 'value_changed':('value_changed', 'SFRotation', 1), + 'set_fraction':('set_fraction', 'SFFloat', 0), + }, +) +PixelTexture = Prototype( "PixelTexture", + { + 'repeatS':('repeatS', 'SFBool', 0), + 'image':('image', 'SFImage', 1), + 'repeatT':('repeatT', 'SFBool', 0), + }, + { + 'repeatS':1, + 'image':[0, 0, 0], + 'repeatT':1, + }, + { + }, +) +PlaneSensor = Prototype( "PlaneSensor", + { + 'offset':('offset', 'SFVec3f', 1), + 'autoOffset':('autoOffset', 'SFBool', 1), + 'minPosition':('minPosition', 'SFVec2f', 1), + 'enabled':('enabled', 'SFBool', 1), + 'maxPosition':('maxPosition', 'SFVec2f', 1), + }, + { + 'offset':[0.0, 0.0, 0.0], + 'autoOffset':1, + 'minPosition':[0.0, 0.0], + 'enabled':1, + 'maxPosition':[-1.0, -1.0], + }, + { + 'translation_changed':('translation_changed', 'SFVec3f', 1), + 'isActive':('isActive', 'SFBool', 1), + 'trackPoint_changed':('trackPoint_changed', 'SFVec3f', 1), + }, +) +PointLight = Prototype( "PointLight", + { + 'ambientIntensity':('ambientIntensity', 'SFFloat', 1), + 'color':('color', 'SFColor', 1), + 'location':('location', 'SFVec3f', 1), + 'radius':('radius', 'SFFloat', 1), + 'attenuation':('attenuation', 'SFVec3f', 1), + 'intensity':('intensity', 'SFFloat', 1), + 'on':('on', 'SFBool', 1), + }, + { + 'ambientIntensity':0.0, + 'color':[1.0, 1.0, 1.0], + 'location':[0.0, 0.0, 0.0], + 'radius':100.0, + 'attenuation':[1.0, 0.0, 0.0], + 'intensity':1.0, + 'on':1, + }, + { + }, +) +PointSet = Prototype( "PointSet", + { + 'coord':('coord', 'SFNode', 1), + 'color':('color', 'SFNode', 1), + }, + { + 'coord':NULL, + 'color':NULL, + }, + { + }, +) +PositionInterpolator = Prototype( "PositionInterpolator", + { + 'key':('key', 'MFFloat', 1), + 'keyValue':('keyValue', 'MFVec3f', 1), + }, + { + 'key':[], + 'keyValue':[], + }, + { + 'value_changed':('value_changed', 'SFVec3f', 1), + 'set_fraction':('set_fraction', 'SFFloat', 0), + }, +) +ProximitySensor = Prototype( "ProximitySensor", + { + 'size':('size', 'SFVec3f', 1), + 'center':('center', 'SFVec3f', 1), + 'enabled':('enabled', 'SFBool', 1), + }, + { + 'size':[0.0, 0.0, 0.0], + 'center':[0.0, 0.0, 0.0], + 'enabled':1, + }, + { + 'enterTime':('enterTime', 'SFTime', 1), + 'isActive':('isActive', 'SFBool', 1), + 'orientation_changed':('orientation_changed', 'SFRotation', 1), + 'exitTime':('exitTime', 'SFTime', 1), + 'position_changed':('position_changed', 'SFVec3f', 1), + }, +) +ScalarInterpolator = Prototype( "ScalarInterpolator", + { + 'key':('key', 'MFFloat', 1), + 'keyValue':('keyValue', 'MFFloat', 1), + }, + { + 'key':[], + 'keyValue':[], + }, + { + 'value_changed':('value_changed', 'SFFloat', 1), + 'set_fraction':('set_fraction', 'SFFloat', 0), + }, +) +Shape = Prototype( "Shape", + { + 'appearance':('appearance', 'SFNode', 1), + 'geometry':('geometry', 'SFNode', 1), + }, + { + 'appearance':NULL, + 'geometry':NULL, + }, + { + }, +) +Sound = Prototype( "Sound", + { + 'spatialize':('spatialize', 'SFBool', 0), + 'maxFront':('maxFront', 'SFFloat', 1), + 'minBack':('minBack', 'SFFloat', 1), + 'maxBack':('maxBack', 'SFFloat', 1), + 'minFront':('minFront', 'SFFloat', 1), + 'location':('location', 'SFVec3f', 1), + 'intensity':('intensity', 'SFFloat', 1), + 'direction':('direction', 'SFVec3f', 1), + 'source':('source', 'SFNode', 1), + 'priority':('priority', 'SFFloat', 1), + }, + { + 'spatialize':1, + 'maxFront':10.0, + 'minBack':1.0, + 'maxBack':10.0, + 'minFront':1.0, + 'location':[0.0, 0.0, 0.0], + 'intensity':1.0, + 'direction':[0.0, 0.0, 1.0], + 'source':NULL, + 'priority':0.0, + }, + { + }, +) +Sphere = Prototype( "Sphere", + { + 'radius':('radius', 'SFFloat', 0), + }, + { + 'radius':1.0, + }, + { + }, +) +SphereSensor = Prototype( "SphereSensor", + { + 'offset':('offset', 'SFRotation', 1), + 'autoOffset':('autoOffset', 'SFBool', 1), + 'enabled':('enabled', 'SFBool', 1), + }, + { + 'offset':[0.0, 1.0, 0.0, 0.0], + 'autoOffset':1, + 'enabled':1, + }, + { + 'rotation_changed':('rotation_changed', 'SFRotation', 1), + 'isActive':('isActive', 'SFBool', 1), + 'trackPoint_changed':('trackPoint_changed', 'SFVec3f', 1), + }, +) +SpotLight = Prototype( "SpotLight", + { + 'attenuation':('attenuation', 'SFVec3f', 1), + 'ambientIntensity':('ambientIntensity', 'SFFloat', 1), + 'cutOffAngle':('cutOffAngle', 'SFFloat', 1), + 'direction':('direction', 'SFVec3f', 1), + 'color':('color', 'SFColor', 1), + 'location':('location', 'SFVec3f', 1), + 'radius':('radius', 'SFFloat', 1), + 'intensity':('intensity', 'SFFloat', 1), + 'beamWidth':('beamWidth', 'SFFloat', 1), + 'on':('on', 'SFBool', 1), + }, + { + 'attenuation':[1.0, 0.0, 0.0], + 'ambientIntensity':0.0, + 'cutOffAngle':0.785398, + 'direction':[0.0, 0.0, -1.0], + 'color':[1.0, 1.0, 1.0], + 'location':[0.0, 0.0, 0.0], + 'radius':100.0, + 'intensity':1.0, + 'beamWidth':1.570796, + 'on':1, + }, + { + }, +) +Switch = Prototype( "Switch", + { + 'choice':('choice', 'MFNode', 1), + 'whichChoice':('whichChoice', 'SFInt32', 1), + }, + { + 'choice':[], + 'whichChoice':-1, + }, + { + }, +) +Text = Prototype( "Text", + { + 'maxExtent':('maxExtent', 'SFFloat', 1), + 'string':('string', 'MFString', 1), + 'fontStyle':('fontStyle', 'SFNode', 1), + 'length':('length', 'MFFloat', 1), + }, + { + 'maxExtent':0.0, + 'string':[], + 'fontStyle':NULL, + 'length':[], + }, + { + }, +) +TextureCoordinate = Prototype( "TextureCoordinate", + { + 'point':('point', 'MFVec2f', 1), + }, + { + 'point':[], + }, + { + }, +) +TextureTransform = Prototype( "TextureTransform", + { + 'center':('center', 'SFVec2f', 1), + 'scale':('scale', 'SFVec2f', 1), + 'rotation':('rotation', 'SFFloat', 1), + 'translation':('translation', 'SFVec2f', 1), + }, + { + 'center':[0.0, 0.0], + 'scale':[1.0, 1.0], + 'rotation':0.0, + 'translation':[0.0, 0.0], + }, + { + }, +) +TimeSensor = Prototype( "TimeSensor", + { + 'loop':('loop', 'SFBool', 1), + 'cycleInterval':('cycleInterval', 'SFTime', 1), + 'enabled':('enabled', 'SFBool', 1), + 'stopTime':('stopTime', 'SFTime', 1), + 'startTime':('startTime', 'SFTime', 1), + }, + { + 'loop':0, + 'cycleInterval':1.0, + 'enabled':1, + 'stopTime':0.0, + 'startTime':0.0, + }, + { + 'fraction_changed':('fraction_changed', 'SFFloat', 1), + 'isActive':('isActive', 'SFBool', 1), + 'time':('time', 'SFTime', 1), + 'cycleTime':('cycleTime', 'SFTime', 1), + }, +) +TouchSensor = Prototype( "TouchSensor", + { + 'enabled':('enabled', 'SFBool', 1), + }, + { + 'enabled':1, + }, + { + 'hitNormal_changed':('hitNormal_changed', 'SFVec3f', 1), + 'hitPoint_changed':('hitPoint_changed', 'SFVec3f', 1), + 'touchTime':('touchTime', 'SFTime', 1), + 'hitTexCoord_changed':('hitTexCoord_changed', 'SFVec2f', 1), + 'isActive':('isActive', 'SFBool', 1), + 'isOver':('isOver', 'SFBool', 1), + }, +) +Transform = Prototype( "Transform", + { + 'bboxSize':('bboxSize', 'SFVec3f', 0), + 'children':('children', 'MFNode', 1), + 'scaleOrientation':('scaleOrientation', 'SFRotation', 1), + 'rotation':('rotation', 'SFRotation', 1), + 'translation':('translation', 'SFVec3f', 1), + 'bboxCenter':('bboxCenter', 'SFVec3f', 0), + 'center':('center', 'SFVec3f', 1), + 'scale':('scale', 'SFVec3f', 1), + }, + { + 'bboxSize':[-1.0, -1.0, -1.0], + 'children':[], + 'scaleOrientation':[0.0, 0.0, 1.0, 0.0], + 'rotation':[0.0, 0.0, 1.0, 0.0], + 'translation':[0.0, 0.0, 0.0], + 'bboxCenter':[0.0, 0.0, 0.0], + 'center':[0.0, 0.0, 0.0], + 'scale':[1.0, 1.0, 1.0], + }, + { + 'addChildren':('addChildren', 'MFNode', 0), + 'removeChildren':('removeChildren', 'MFNode', 0), + }, +) +Viewpoint = Prototype( "Viewpoint", + { + 'jump':('jump', 'SFBool', 1), + 'orientation':('orientation', 'SFRotation', 1), + 'fieldOfView':('fieldOfView', 'SFFloat', 1), + 'position':('position', 'SFVec3f', 1), + 'description':('description', 'SFString', 0), + }, + { + 'jump':1, + 'orientation':[0.0, 0.0, 1.0, 0.0], + 'fieldOfView':0.785398, + 'position':[0.0, 0.0, 10.0], + 'description':'', + }, + { + 'isBound':('isBound', 'SFBool', 1), + 'set_bind':('set_bind', 'SFBool', 0), + 'bindTime':('bindTime', 'SFTime', 1), + }, +) +VisibilitySensor = Prototype( "VisibilitySensor", + { + 'size':('size', 'SFVec3f', 1), + 'center':('center', 'SFVec3f', 1), + 'enabled':('enabled', 'SFBool', 1), + }, + { + 'size':[0.0, 0.0, 0.0], + 'center':[0.0, 0.0, 0.0], + 'enabled':1, + }, + { + 'exitTime':('exitTime', 'SFTime', 1), + 'isActive':('isActive', 'SFBool', 1), + 'enterTime':('enterTime', 'SFTime', 1), + }, +) +WorldInfo = Prototype( "WorldInfo", + { + 'title':('title', 'SFString', 0), + 'info':('info', 'MFString', 0), + }, + { + 'title':'', + 'info':[], + }, + { + }, +) diff --git a/intern/python/modules/vrml/fieldcoercian.py b/intern/python/modules/vrml/fieldcoercian.py new file mode 100644 index 00000000000..a90f1101b5a --- /dev/null +++ b/intern/python/modules/vrml/fieldcoercian.py @@ -0,0 +1,310 @@ +''' +Field coercian routines. + +To replace the field coercian routines, you must edit +basenodes.py and node.py to import some other coercian +routines. Basenodes.py is for use by the parser, node +is used by each node as it checks the validity of its +attributes. +''' + +import types, sys, string +from utils import typeclasses, collapse + +class FieldCoercian: + ''' + A Field Coercian class allows for creating new behaviours + when dealing with the conversion of fields to-and-from + particular field types. This allows the programmer to + use alternate representations of fields (such as matrix arrays) + ''' + def SFString( self, someobj, targetType=types.StringType, targetName='SFString', convertfunc=str ): + ''' + Allowable types: + simple string -> unchanged + instance ( an IS ) -> unchanged + sequence of length == 1 where first element is a string -> returns first element + sequence of length > 1 where all elements are strings -> returns string.join( someobj, '') + ''' + t = type(someobj) + if t is targetType: + return someobj + if t in typeclasses.SequenceTypes: + if len( someobj) == 1 and type( someobj[0] ) is targetType: + return someobj[0] # + elif len(someobj) > 1: + try: + return string.join( someobj, '') + except: + pass # is not a sequence of strings... + ### if we get here, then an incorrect value was passed + raise ValueError, """Attempted to set value for an %s field which is not compatible: %s"""%( targetName, `someobj` ) + + def MFString( self, someobj, targetType=types.StringType, targetName='SFString', convertfunc=str ): + ''' + Allowable Types: + simple string -> wrapped in a list + instance (an IS ) -> unchanged + sequence of strings (of any length) -> equivalent list returned + ''' + t = type(someobj) + if t is targetType: # a bare string... + return [someobj] + elif t in typeclasses.SequenceTypes: # is a sequence + if not filter( lambda x, t=targetType: x is not t, map( type, someobj) ): # are all strings... + if t is not types.ListType: + return list( someobj ) + else: + return someobj + ### if we get here, then an incorrect value was passed + raise ValueError, """Attempted to set value for an %s field which is not compatible: %s"""%( targetName, `someobj` ) + + def SFBool( self, someobj, targetType=types.IntType, targetName='SFBool', convertfunc=int): + ''' + Allowable Types: + instance (an IS) -> unchanged + Any object which is testable for truth/falsehood -> 1 or 0 respectively + SFBool should always succeed + ''' + if (type(someobj) in typeclasses.SequenceTypes): + try: + if hasattr( someobj[0], '__gi__'): + return someobj[0] + else: + someobj = someobj[0] + except IndexError: # is a null MFNode + pass + if someobj: + return 1 + else: + return 0 + + def SFNode( self, someobj, targetType=types.InstanceType, targetName='SFNode', convertfunc=None): + ''' + Allowable Types: + instance of a Node -> unchanged + instance (an IS or USE) -> unchanged + sequence of length == 1 where first element is as above -> return first element + ''' + if hasattr( someobj, '__gi__'): # about the only test I have without requiring that elements inherit from Node + return someobj + elif (type(someobj) in typeclasses.SequenceTypes): + try: + if hasattr( someobj[0], '__gi__'): + return someobj[0] + except IndexError: # is a null MFNode + pass + raise ValueError, """Attempted to set value for an %s field which is not compatible: %s"""%( targetName, `someobj` ) + + def MFNode( self, someobj, targetType=types.InstanceType, targetName='MFNode', convertfunc=None): + ''' + Allowable Types: + instance (an IS) -> unchanged + instance of a Node -> wrapped with a list + sequence where all elements are nodes -> returned as list of same + ''' + if hasattr( someobj, '__gi__') and someobj.__gi__ != "IS": + # is this a bare SFNode? wrap with a list and return + return [someobj] + elif hasattr( someobj, "__gi__"): # is this an IS node + return someobj + elif type(someobj) in typeclasses.SequenceTypes: + try: + map( getattr, someobj, ['__gi__']*len(someobj) ) + # is this an IS node wrapped in a list? + if len(someobj) == 1 and someobj[0].__gi__ == "IS": + return someobj[0] + # okay, assume is really nodes... + if type(someobj) is types.ListType: + return someobj + else: + return list(someobj) + except AttributeError: # something isn't a node + pass + raise ValueError, """Attempted to set value for an %s field which is not compatible: %s"""%( targetName, `someobj` ) + + def SFNumber( self, someobj, targetType, targetName, convertfunc=int ): + ''' + Allowable Types: + bare number -> numerically coerced to correct type + instance ( an IS ) -> unchanged + sequence of length == 1 where first element is a string -> returns first element + ''' + t = type(someobj) + if t is targetType or t is types.InstanceType: + return someobj + elif t in typeclasses.NumericTypes: + return convertfunc( someobj) + elif t in typeclasses.SequenceTypes: + if len( someobj) == 1 and type( someobj[0] ): + return convertfunc( someobj[0] ) # + ### if we get here, then an incorrect value was passed + raise ValueError, """Attempted to set value for an %s field which is not compatible: %s"""%( targetName, `someobj` ) + def MFInt32 ( self, someobject ): + ''' Convert value into a MFInt32 field value (preferably an array, otherwise a list of integers) ''' + t = type(someobject) + value = None + if t in typeclasses.SequenceTypes: # is a sequence + try: + value = map( int, someobject) + except: + try: + value = map( int, collapse.collapse2_safe( someobject) ) + except: + pass + elif t in typeclasses.NumericTypes or t is types.StringType: + value = [int(someobject)] + if value is None: + ### if we get here, then an incorrect value was passed + raise ValueError, """Attempted to set value for an %s field which is not compatible: %s"""%( targetName, `someobj` ) + return value + SFImage = MFInt32 + def MFFloat( self, someobject ): + ''' Convert value into a MFFloat field value (preferably an array, otherwise a list of integers) ''' + t = type(someobject) + value = None + if t in typeclasses.SequenceTypes: # is a sequence + try: + value = map( float, someobject) + except: + try: + value = map( float, collapse.collapse2_safe( someobject)) + except: + pass + elif t in typeclasses.NumericTypes or t is types.StringType: + value = [float(someobj)] + if value is None: + ### if we get here, then an incorrect value was passed + raise ValueError, """Attempted to set value for an %s field which is not compatible: %s"""%( targetName, `someobj` ) + return value + def SFVec3f (self, value): + ''' Create a new SFVec3f value from value ''' + t = type(value) + try: + value = x,y,z = map (float, value) + except ValueError: + try: + value = (x,y,z) = map( float, value[0] ) + except (IndexError, ValueError): + raise ValueError (''' Invalid value for field type SFVec3f: %s'''%(value)) + return value + def SFRotation(self, value): + ''' Create a new SFRotation value from value ''' + t = type(value) + try: + value = x,y,z, a = map (float, value) + except ValueError: + try: + value = (x,y,z, a) = map( float, value[0] ) + except (IndexError, ValueError): + raise ValueError (''' Invalid value for field type SFRotation: %s'''%(value)) + # get the normalized vector for x,y,z +## length = (x*x+y*y+z*z)**.5 or 0.0000 +## value = (x/length,y/length,z/length, a) + return value + def SFVec2f (self, value): + ''' Create a new SFVec3f value from value ''' + t = type(value) + try: + value = x,y = map (float, value) + except ValueError: + try: + value = (x,y) = map( float, value[0] ) + except (IndexError, ValueError): + raise ValueError (''' Invalid value for field type SFVec3f: %s'''%(value)) + return value + def SFColor(self, value): + ''' Create a new SFVec3f value from value ''' + t = type(value) + try: + r,g,b = map (float, value) + except ValueError: + try: + r,g,b = map( float, value[0] ) + except (IndexError, ValueError): + raise ValueError (''' Invalid value for field type SFColor: %s'''%(value)) + r = max( (0.0, min((r,1.0))) ) + g = max( (0.0, min((g,1.0))) ) + b = max( (0.0, min((b,1.0))) ) + return value + + def MFCompoundNumber( self, someobj, targetName='SFVec3f', convertfunc=float, type=type): + ''' + Allowable Types: + instance ( an IS ) -> unchanged + # instance ( a matrix ) -> reshaped (eventually) + list of lists, sub-sequences of proper length -> unchanged + sequence of numeric types of proper length -> converted to list, diced + ''' +## if targetName == 'SFColor': +## import pdb +## pdb.set_trace() + converter = getattr( self, targetName ) + t = type( someobj) + reporterror = 0 + if t is types.InstanceType: + return someobj + elif t in typeclasses.SequenceTypes: + if not someobj: + return [] + if type( someobj[0] ) is not types.StringType and type( someobj[0] ) in typeclasses.SequenceTypes: + try: + return map( converter, someobj ) + except ValueError: + pass + elif type( someobj[0] ) in typeclasses.NumericTypes or type( someobj[0] ) is types.StringType: + # a single-level list? + base = map( convertfunc, someobj ) + # if we get here, someobj is a list + if targetName[-2:] == '2f': # vec2f + tlen = 2 + elif targetName[-2:] == 'on': # rotation + tlen = 4 + else: + tlen = 3 + value = [] + while base: + value.append( converter( base[:tlen]) ) + del base[:tlen] + return value + raise ValueError, """Attempted to set value for an %s field which is not compatible: %s"""%( targetName, `someobj` ) + def __call__( self, someobj, targetName): + func, args = self.algomap[targetName] +## try: +## if targetName == 'SFInt32': +## import pdb +## pdb.set_trace() + if hasattr( someobj, "__gi__") and someobj.__gi__ == "IS": + return someobj + else: + return apply( func, (self, someobj)+args ) +## except TypeError: +## print someobj, targetName +## print func, args +## raise + + algomap = { \ + 'SFString': (SFString, (types.StringType, 'SFString', str)), \ + 'MFString': (MFString, (types.StringType, 'MFString', str)), \ + 'SFInt32': (SFNumber, (types.IntType, 'SFInt32', int)), \ + 'SFFloat': (SFNumber, (types.FloatType, 'SFFloat', float)), \ + 'SFTime': (SFNumber, (types.FloatType, 'SFFloat', float)), \ + 'SFColor': (SFColor, ()), \ + 'SFVec2f': (SFVec2f, ()), \ + 'SFVec3f': (SFVec3f, ()), \ + 'SFNode': (SFNode, (types.InstanceType, 'SFNode', None)), \ + 'SFBool': (SFBool, (types.IntType, 'SFBool', int)), \ + 'SFNode': (SFNode, (types.InstanceType, 'SFNode', None)), \ + 'MFInt32': (MFInt32, ()), \ + 'SFImage': (MFInt32, ()), \ + 'MFTime': (MFFloat, ()), \ + 'MFFloat': (MFFloat, ()), \ + 'MFColor': (MFCompoundNumber, ('SFColor', float)), \ + 'MFVec2f': (MFCompoundNumber, ('SFVec2f', float)), \ + 'MFVec3f': (MFCompoundNumber, ('SFVec3f', float)), \ + 'SFRotation': (SFRotation, ()), \ + 'MFRotation': (MFCompoundNumber, ('SFRotation', float)), \ + 'MFNode': (MFNode, (types.InstanceType, 'MFNode', None)) \ + } + +FIELDCOERCE = FieldCoercian () diff --git a/intern/python/modules/vrml/loader.py b/intern/python/modules/vrml/loader.py new file mode 100644 index 00000000000..dd53fe49fd3 --- /dev/null +++ b/intern/python/modules/vrml/loader.py @@ -0,0 +1,97 @@ +# The VRML loader +# supports gzipped files +# +# TODO: better progress monitoring + +import parser + +def quiet(txt): + pass + +debug = quiet + +def debug1(txt): + print "Loader:", txt + +g_last = 0 + +def getFileType(file): + "returns the file type string from 'file'" + file.seek(0) + magic = file.readline() + if magic[:3] == '\037\213\010': + file.seek(0) + return "gzip" + elif magic[:10] == '#VRML V2.0': + file.seek(0) + return "vrml" + else: + file.seek(0) + return "" + +class Loader: + def __init__(self, url, progress = None): + self.url = url + self.debug = debug + self.fail = debug + self.monitor = debug + self.progress = progress + self.nodes = 0 # number of nodes parsed + + def getGzipFile(self, file): + '''Return gzip file (only called when gzip type is recognised)''' + # we now have the local filename and the headers + # read the first few bytes, check for gzip magic number + self.monitor( "gzip-encoded file... loading gzip library") + try: + import gzip + file = gzip.open(file,"rb") + return file + except ImportError, value: + self.fail("Gzip library unavailable, compressed file cannot be read") + except: + self.fail("Failed to open Gzip file") + + return None + + def load(self): + self.debug("try: load file from %s" % self.url) + url = self.url + + # XXX + try: + file = open(url, 'rb') + except IOError, val: + self.debug("couldn't open file %s" % url) + return None + + if getFileType(file) == 'gzip': + file.close() + file = self.getGzipFile(url) + try: + data = file.read() + except MemoryError, value: + self.fail("Insufficient memory to load file as string", value) + return None + except IOError, value: + self.fail("I/O Error while reading data from file %s "% url) + p = parser.Parser(data) + if self.progress: + scenegraph = p.parse(self.progress) + print "progress" + else: + scenegraph = p.parse() + + self.nodes = p.progresscount # progress + del p + return scenegraph + + +def load(url, progress = None): + l = Loader(url, progress) + return l.load() + +def test(name = None): + if not name: + name = '/tmp/gna.wrl' + return load(name) diff --git a/intern/python/modules/vrml/parser.py b/intern/python/modules/vrml/parser.py new file mode 100644 index 00000000000..1f238126550 --- /dev/null +++ b/intern/python/modules/vrml/parser.py @@ -0,0 +1,426 @@ +from TextTools import TextTools + +from simpleparse import generator + +import scenegraph as proto +import strop as string + +IMPORT_PARSE_TIME = 0.4 +PROGRESS_DEPTH = 5 + +class UnfinishedError(Exception): + pass + +class Parser: + def __init__( self, data ): + self.data = data + self.position = 0 + self.result = proto.sceneGraph() + self.finalised = None + self.sceneGraphStack = [self.result] + self.prototypeStack = [] + self.nodeStack = [] + self.fieldTypeStack = [] + self.readHeader() + self.depth = 0 + self.progresscount = 0 + def _lines( self, index=None ): + if index is None: + index = self.position + return TextTools.countlines (self.data[:index]) + def parse( self, progressCallback=None ): + datalength = float( len( self.data )) + while self.readNext(): + if progressCallback: + if not progressCallback(IMPORT_PARSE_TIME * self.position/datalength ): + raise UnfinishedError( + "Did not complete parsing, cancelled by user. Stopped at line %s" %(self._lines()) + ) + if self.position < len( self.data ): + raise UnfinishedError( + '''Unable to complete parsing of file, stopped at line %s:\n%s...'''%(self._lines(), self.data[self.position:self.position+120]) + ) + return self.result + def readHeader( self ): + '''Read the file header''' + success, tags, next = TextTools.tag( self.data, HEADERPARSER, self.position ) + if success: + self.datalength = len( self.data ) + #print "header ok" + return success + else: + try: + self.decompress() + success, tags, next = TextTools.tag( self.data, HEADERPARSER, self.position ) + self.datalength = len( self.data ) + return success + except: + raise ValueError( "Could not find VRML97 header in file!" ) + def readNext( self): + '''Read the next root-level construct''' + success, tags, next = TextTools.tag( self.data, ROOTITEMPARSER, self.position ) +## print 'readnext', success + if self.position >= self.datalength: + print 'reached file end' + return None + if success: +# print ' successful parse' + self.position = next + map (self.rootItem_Item, tags ) + return success + else: + return None + def rootItem (self, (type, start, stop, (item,))): + ''' Process a single root item ''' + self.rootItem_Item( item ) + def rootItem_Item( self, item ): + result = self._dispatch(item) + if result is not None: +## print "non-null result" +## print id( self.sceneGraphStack[-1] ), id(self.result ) + self.sceneGraphStack[-1].children.append( result ) + def _getString (self, (tag, start, stop, sublist)): + ''' Return the raw string for a given interval in the data ''' + return self.data [start: stop] + + def _dispatch (self, (tag, left, right, sublist)): + ''' Dispatch to the appropriate processing function based on tag value ''' +## print "dispatch", tag + self.depth += 1 + if self.depth < PROGRESS_DEPTH: + self.progresscount += 1 + try: + meth = getattr (self, tag) + except AttributeError: + raise AttributeError("Unknown parse tag '%s' found! Check the parser definition!" % (tag)) + ret = meth( (tag, left, right, sublist) ) + self.depth -= 1 + return ret + + def Proto(self, (tag, start, stop, sublist)): + ''' Create a new prototype in the current sceneGraph ''' + # first entry is always ID + ID = self._getString ( sublist [0]) + print "PROTO",ID + newNode = proto.Prototype (ID) +## print "\t",newNode + setattr ( self.sceneGraphStack [-1].protoTypes, ID, newNode) + self.prototypeStack.append( newNode ) + # process the rest of the entries with the given stack + map ( self._dispatch, sublist [1:] ) + self.prototypeStack.pop( ) + def fieldDecl(self,(tag, left, right, (exposure, datatype, name, field))): + ''' Create a new field declaration for the current prototype''' + # get the definition in recognizable format + exposure = self._getString (exposure) == "exposedField" + datatype = self._getString (datatype) + name = self._getString (name) + # get the vrml value for the field + self.fieldTypeStack.append( datatype ) + field = self._dispatch (field) + self.fieldTypeStack.pop( ) + self.prototypeStack[-1].addField ((name, datatype, exposure), field) + def eventDecl(self,(tag, left, right, (direction, datatype, name))): + # get the definition in recognizable format + direction = self._getString (direction) == "eventOut" + datatype = self._getString (datatype) + name = self._getString (name) + # get the vrml value for the field + self.prototypeStack[-1].addEvent((name, datatype, direction)) + def decompress( self ): + pass + def ExternProto( self, (tag, start, stop, sublist)): + ''' Create a new external prototype from a tag list''' + # first entry is always ID + ID = self._getString ( sublist [0]) + newNode = proto.Prototype (ID) + setattr ( self.sceneGraphStack [-1].protoTypes, ID, newNode) + self.prototypeStack.append( newNode ) + # process the rest of the entries with the given stack + map ( self._dispatch, sublist [1:] ) + self.prototypeStack.pop( ) + def ExtProtoURL( self, (tag, start, stop, sublist)): + ''' add the url to the external prototype ''' +## print sublist + values = self.MFString( sublist ) + self.prototypeStack[-1].url = values + return values + def extFieldDecl(self, (tag, start, stop, (exposure, datatype, name))): + ''' An external field declaration, no default value ''' + # get the definition in recognizable format + exposure = self._getString (exposure) == "exposedField" + datatype = self._getString (datatype) + name = self._getString (name) + # get the vrml value for the field + self.prototypeStack[-1].addField ((name, datatype, exposure)) + def ROUTE(self, (tag, start, stop, names )): + ''' Create a new route object, add the current sceneGraph ''' + names = map(self._getString, names) + self.sceneGraphStack [-1].addRoute( names ) + def Node (self, (tag, start, stop, sublist)): + ''' Create new node, returning the value to the caller''' +## print 'node' + + if sublist[0][0] == 'name': + name = self._getString ( sublist [0]) + ID = self._getString ( sublist [1]) + rest = sublist [2:] + else: + name = "" + ID = self._getString ( sublist [0]) + rest = sublist [1:] + try: + prototype = getattr ( self.sceneGraphStack [-1].protoTypes, ID) + except AttributeError: + #raise NameError ('''Prototype %s used without declaration! %s:%s'''%(ID, start, stop) ) + print ('''### Prototype %s used without declaration! %s:%s'''%(ID, start, stop) ) + + return None + newNode = prototype(name) + if name: + self.sceneGraphStack [-1].regDefName( name, newNode ) + self.nodeStack.append (newNode) + map (self._dispatch, rest) + self.nodeStack.pop () +## print 'node finished' + return newNode + def Attr(self, (tag, start, stop, (name, value))): + ''' An attribute of a node or script ''' + name = self._getString ( name ) + self.fieldTypeStack.append( self.nodeStack[-1].PROTO.getField( name ).type ) + value = self._dispatch( value ) + self.fieldTypeStack.pop() + if hasattr( self.nodeStack[-1], "__setattr__" ): + self.nodeStack[-1].__setattr__( name, value, raw=1 ) + else: + # use slower coercing versions... + setattr( self.nodeStack[-1], name, value ) + def Script( self, (tag, start, stop, sublist)): + ''' A script node (can be a root node)''' + # what's the DEF name... + if sublist and sublist[0][0] == 'name': + name = self._getString ( sublist [0]) + rest = sublist [1:] + else: + name = "" + rest = sublist + # build the script node... + newNode = proto.Script( name ) + # register with sceneGraph + if name: + self.sceneGraphStack [-1].regDefName( name, newNode ) + self.nodeStack.append (newNode) + map( self._dispatch, rest ) + self.nodeStack.pop () + return newNode + def ScriptEventDecl( self,(tag, left, right, sublist)): + # get the definition in recognizable format + direction, datatype, name = sublist[:3] # must have at least these... + direction = self._getString (direction) == "eventOut" + datatype = self._getString (datatype) + name = self._getString (name) + # get the vrml value for the field + self.nodeStack[-1].PROTO.addEvent((name, datatype, direction)) + if sublist[3:]: + # will this work??? + setattr( self.nodeStack[-1], name, self._dispatch( sublist[3] ) ) + def ScriptFieldDecl(self,(tag, left, right, (exposure, datatype, name, field))): + ''' Create a new field declaration for the current prototype''' + # get the definition in recognizable format + exposure = self._getString (exposure) == "exposedField" + datatype = self._getString (datatype) + name = self._getString (name) + # get the vrml value for the field + self.fieldTypeStack.append( datatype ) + field = self._dispatch (field) + self.fieldTypeStack.pop( ) + self.nodeStack[-1].PROTO.addField ((name, datatype, exposure)) + setattr( self.nodeStack[-1], name, field ) + def SFNull(self, tup): + ''' Create a reference to the SFNull node ''' +## print 'hi' + return proto.NULL + def USE( self, (tag, start, stop, (nametuple,) )): + ''' Create a reference to an already defined node''' + name = self._getString (nametuple) + if self.depth < PROGRESS_DEPTH: + self.progresscount += 1 + try: + node = self.sceneGraphStack [-1].defNames [name] + return node + except KeyError: + raise NameError ('''USE without DEF for node %s %s:%s'''%(name, start, stop)) + def IS(self, (tag, start, stop, (nametuple,))): + ''' Create a field reference ''' + name = self._getString (nametuple) + if not self.prototypeStack [-1].getField (name): + raise Exception (''' Attempt to create IS mapping of non-existent field %s %s:%s'''%(name, start, stop)) + return proto.IS(name) + def Field( self, (tag, start, stop, sublist)): + ''' A field value (of any type) ''' + + if sublist and sublist[0][0] in ('USE','Script','Node','SFNull'): + if self.fieldTypeStack[-1] == 'SFNode': + return self._dispatch( sublist[0] ) + else: + return map( self._dispatch, sublist ) + elif self.fieldTypeStack[-1] == 'MFNode': + return [] + else: + # is a simple data type... + function = getattr( self, self.fieldTypeStack[-1] ) + try: + return function( sublist ) + except ValueError: + traceback.print_exc() + print sublist + raise + + def SFBool( self, (tup,) ): + '''Boolean, in Python tradition is either 0 or 1''' + return self._getString(tup) == 'TRUE' + def SFFloat( self, (x,) ): + return string.atof( self._getString(x) ) + SFTime = SFFloat + def SFInt32( self, (x,) ): + return string.atoi( self._getString(x), 0 ) # allow for non-decimal numbers + def SFVec3f( self, (x,y,z) ): + return map( string.atof, map(self._getString, (x,y,z)) ) + def SFVec2f( self, (x,y) ): + return map( string.atof, map(self._getString, (x,y)) ) + def SFColor( self, (r,g,b) ): + return map( string.atof, map(self._getString, (r,g,b)) ) + def SFRotation( self, (x,y,z,a) ): + return map( string.atof, map(self._getString, (x,y,z,a)) ) + + def MFInt32( self, tuples ): + result = [] + # localisation + atoi = string.atoi + append = result.append + data = self.data + for tag, start, stop, children in tuples: + append( atoi( data[start:stop], 0) ) + return result + SFImage = MFInt32 + def MFFloat( self, tuples ): + result = [] + # localisation + atof = string.atof + append = result.append + data = self.data + for tag, start, stop, children in tuples: + append( atof( data[start:stop]) ) + return result + MFTime = MFFloat + def MFVec3f( self, tuples, length=3, typename='MFVec3f'): + result = [] + # localisation + atof = string.atof + data = self.data + while tuples: + newobj = [] + for tag, start, stop, children in tuples[:length]: + newobj.append( atof(data[start:stop] )) + if len(newobj) != length: + raise ValueError( + '''Incorrect number of elements in %s field at line %s'''%(typename, self._lines(stop)) + ) + result.append( newobj ) + del tuples[:length] + return result + def MFVec2f( self, tuples): + return self.MFVec3f( tuples, length=2, typename='MFVec2f') + def MFRotation( self, tuples ): + return self.MFVec3f( tuples, length=4, typename='MFRotation') + def MFColor( self, tuples ): + return self.MFVec3f( tuples, length=3, typename='MFColor') + + def MFString( self, tuples ): + bigresult = [] + for (tag, start, stop, sublist) in tuples: + result = [] + for element in sublist: + if element[0] == 'CHARNODBLQUOTE': + result.append( self.data[element[1]:element[2]] ) + elif element[0] == 'ESCAPEDCHAR': + result.append( self.data[element[1]+1:element[2]] ) + elif element[0] == 'SIMPLEBACKSLASH': + result.append( '\\' ) + bigresult.append( string.join( result, "") ) + return bigresult +## result = [] +## for tuple in tuples: +## result.append( self.SFString( tuple) ) +## return result + def SFString( self, tuples ): + '''Return the (escaped) string as a simple Python string''' + if tuples: + (tag, start, stop, sublist) = tuples[0] + if len( tuples ) > 1: + print '''Warning: SFString field has more than one string value''', self.data[tuples[0][1]:tuples[-1][2]] + result = [] + for element in sublist: + if element[0] == 'CHARNODBLQUOTE': + result.append( self.data[element[1]:element[2]] ) + elif element[0] == 'ESCAPEDCHAR': + result.append( self.data[element[1]+1:element[2]] ) + elif element[0] == 'SIMPLEBACKSLASH': + result.append( '\\' ) + return string.join( result, "") + else: + raise ValueError( "NULL SFString parsed???!!!" ) + def vrmlScene( self, (tag, start, stop, sublist)): + '''A (prototype's) vrml sceneGraph''' + newNode = proto.sceneGraph (root=self.sceneGraphStack [-1]) + self.sceneGraphStack.append (newNode) + #print 'setting proto sceneGraph', `newNode` + self.prototypeStack[-1].sceneGraph = newNode + results = filter (None, map (self._dispatch, sublist)) + if results: + # items which are not auto-magically inserted into their parent + for result in results: + newNode.children.append( result) + self.sceneGraphStack.pop() + +PARSERDECLARATION = r'''header := -[\n]* +rootItem := ts,(Proto/ExternProto/ROUTE/('USE',ts,USE,ts)/Script/Node),ts +vrmlScene := rootItem* +Proto := 'PROTO',ts,nodegi,ts,'[',ts,(fieldDecl/eventDecl)*,']', ts, '{', ts, vrmlScene,ts, '}', ts +fieldDecl := fieldExposure,ts,dataType,ts,name,ts,Field,ts +fieldExposure := 'field'/'exposedField' +dataType := 'SFBool'/'SFString'/'SFFloat'/'SFTime'/'SFVec3f'/'SFVec2f'/'SFRotation'/'SFInt32'/'SFImage'/'SFColor'/'SFNode'/'MFBool'/'MFString'/'MFFloat'/'MFTime'/'MFVec3f'/'MFVec2f'/'MFRotation'/'MFInt32'/'MFColor'/'MFNode' +eventDecl := eventDirection, ts, dataType, ts, name, ts +eventDirection := 'eventIn'/'eventOut' +ExternProto := 'EXTERNPROTO',ts,nodegi,ts,'[',ts,(extFieldDecl/eventDecl)*,']', ts, ExtProtoURL +extFieldDecl := fieldExposure,ts,dataType,ts,name,ts +ExtProtoURL := '['?,(ts,SFString)*, ts, ']'?, ts # just an MFString by another name :) +ROUTE := 'ROUTE',ts, name,'.',name, ts, 'TO', ts, name,'.',name, ts +Node := ('DEF',ts,name,ts)?,nodegi,ts,'{',ts,(Proto/ExternProto/ROUTE/Attr)*,ts,'}', ts +Script := ('DEF',ts,name,ts)?,'Script',ts,'{',ts,(ScriptFieldDecl/ScriptEventDecl/Proto/ExternProto/ROUTE/Attr)*,ts,'}', ts +ScriptEventDecl := eventDirection, ts, dataType, ts, name, ts, ('IS', ts, IS,ts)? +ScriptFieldDecl := fieldExposure,ts,dataType,ts,name,ts,(('IS', ts,IS,ts)/Field),ts +SFNull := 'NULL', ts + +# should really have an optimised way of declaring a different reporting name for the same production... +USE := name +IS := name +nodegi := name +Attr := name, ts, (('IS', ts,IS,ts)/Field), ts +Field := ( '[',ts,((SFNumber/SFBool/SFString/('USE',ts,USE,ts)/Script/Node),ts)*, ']', ts )/((SFNumber/SFBool/SFNull/SFString/('USE',ts,USE,ts)/Script/Node),ts)+ + +name := -[][0-9{}\000-\020"'#,.\\ ], -[][{}\000-\020"'#,.\\ ]* +SFNumber := [-+]*, ( ('0',[xX],[0-9]+) / ([0-9.]+,([eE],[-+0-9.]+)?)) +SFBool := 'TRUE'/'FALSE' +SFString := '"',(CHARNODBLQUOTE/ESCAPEDCHAR/SIMPLEBACKSLASH)*,'"' +CHARNODBLQUOTE := -[\134"]+ +SIMPLEBACKSLASH := '\134' +ESCAPEDCHAR := '\\"'/'\134\134' +<ts> := ( [ \011-\015,]+ / ('#',-'\012'*,'\n')+ )* +''' + + +PARSERTABLE = generator.buildParser( PARSERDECLARATION ) +HEADERPARSER = PARSERTABLE.parserbyname( "header" ) +ROOTITEMPARSER = PARSERTABLE.parserbyname( "rootItem" ) + diff --git a/intern/python/modules/vrml/scenegraph.py b/intern/python/modules/vrml/scenegraph.py new file mode 100644 index 00000000000..2f137b1e259 --- /dev/null +++ b/intern/python/modules/vrml/scenegraph.py @@ -0,0 +1,833 @@ +# VRML node prototype class (SGbuilder) +# Wed Oct 31 16:18:35 CET 2001 + +'''Prototype2 -- VRML 97 sceneGraph/Node/Script/ROUTE/IS implementations''' +import copy, types # extern +import strop as string # builtin +from utils import typeclasses, err, namespace # XXX +## TODO: namespace must go + + +class baseProto: + def __vrmlStr__( self, **namedargs ): + '''Generate a VRML 97-syntax string representing this Prototype + **namedargs -- key:value + passed arguments for the linearisation object + see lineariser4.Lineariser + ''' + import lineariser4 + lineariser = apply( lineariser4.Lineariser, (), namedargs ) + return apply( lineariser.linear, ( self, ), namedargs ) + + toString = __vrmlStr__ + # added stuff for linking support for target scenegraph + def setTargetnode(self, node): + self.__dict__['_targetnode'] = node + def getTargetnode(self): + try: + return self.__dict__['_targetnode'] + except: + return None + +class Prototype(baseProto): + ''' A VRML 97 Prototype object + + A Prototype is a callable object which produces Node instances + the Node uses a pointer to its Prototype to provide much of the + Node's standard functionality. + + Prototype's are often stored in a sceneGraph's protoTypes namespace, + where you can access them as sceneGraph.protoTypes.nodeGI . They are + also commonly found in Nodes' PROTO attributes. + + Attributes: + __gi__ -- constant string "PROTO" + nodeGI -- string gi + The "generic identifier" of the node type, i.e. the name of the node + fieldDictionary -- string name: (string name, string dataType, boolean exposed) + defaultDictionary -- string name: object defaultValue + Will be blank for EXTERNPROTO's and Script prototypes + eventDictionary -- string name: (string name, string dataType, boolean eventOut) + sceneGraph -- object sceneGraph + MFNodeNames -- list of field name strings + Allows for easy calculation of "children" nodes + SFNodeNames -- list of field name strings + Allows for easy calculation of "children" nodes + ''' + __gi__ = "PROTO" + def __init__(self, gi, fieldDict=None, defaultDict=None, eventDict=None, sGraph=None): + ''' + gi -- string gi + see attribute nodeGI + fieldDict -- string name: (string name, string dataType, boolean exposed) + see attribute fieldDictionary + defaultDict -- string name: object defaultValue + see attribute defaultDictionary + eventDict -- string name: (string name, string dataType, boolean eventOut) + see attribute eventDictionary + sceneGraph -- object sceneGraph + see attribute sceneGraph + ''' + self.nodeGI = checkName( gi ) + self.fieldDictionary = {} + self.defaultDictionary = {} + self.eventDictionary = {} + self.SFNodeNames = [] + self.MFNodeNames = [] + self.sceneGraph = sGraph + + # setup the fields/events + for definition in (fieldDict or {}).values(): + self.addField( definition, (defaultDict or {}).get( definition[0])) + for definition in (eventDict or {}).values(): + self.addEvent( definition ) + + def getSceneGraph( self ): + ''' Retrieve the sceneGraph object (may be None object) + see attribute sceneGraph''' + return self.sceneGraph + def setSceneGraph( self, sceneGraph ): + ''' Set the sceneGraph object (may be None object) + see attribute sceneGraph''' + self.sceneGraph = sceneGraph + def getChildren(self, includeSceneGraph=None, includeDefaults=1, *args, **namedargs): + ''' Calculate the current children of the PROTO and return as a list of nodes + if includeDefaults: + include those default values which are node values + if includeSceneGraph: + include the sceneGraph object if it is not None + + see attribute MFNodeNames + see attribute SFNodeNames + see attribute sceneGraph + ''' + temp = [] + if includeDefaults: + for attrname in self.SFNodeNames: + try: + temp.append( self.defaultDictionary[attrname] ) + except KeyError: # sceneGraph object is not copied... + pass + for attrname in self.MFNodeNames: + try: + temp[len(temp):] = self.defaultDictionary[attrname] + except KeyError: + pass + if includeSceneGraph and self.sceneGraph: + temp.append( self.getSceneGraph() ) + return temp + def addField (self, definition, default = None): + ''' Add a single field definition to the Prototype + definition -- (string name, string dataType, boolean exposed) + default -- object defaultValue + + see attribute fieldDictionary + see attribute defaultDictionary + ''' + if type (definition) == types.InstanceType: + definition = definition.getDefinition() + default = definition.getDefault () + self.removeField( definition[0] ) + self.fieldDictionary[definition [0]] = definition + if default is not None: + default = fieldcoercian.FieldCoercian()( default, definition[1] ) + self.defaultDictionary [definition [0]] = default + if definition[1] == 'SFNode': + self.SFNodeNames.append(definition[0]) + elif definition[1] == 'MFNode': + self.MFNodeNames.append(definition[0]) + def removeField (self, key): + ''' Remove a single field from the Prototype + key -- string fieldName + The name of the field to remove + ''' + if self.fieldDictionary.has_key (key): + del self.fieldDictionary [key] + if self.defaultDictionary.has_key (key): + del self.defaultDictionary [key] + for attribute in (self.SFNodeNames, self.MFNodeNames): + while key in attribute: + attribute.remove(key) + def addEvent(self, definition): + ''' Add a single event definition to the Prototype + definition -- (string name, string dataType, boolean eventOut) + + see attribute eventDictionary + ''' + if type (definition) == types.InstanceType: + definition = definition.getDefinition() + self.eventDictionary[definition [0]] = definition + def removeEvent(self, key): + ''' Remove a single event from the Prototype + key -- string eventName + The name of the event to remove + ''' + if self.eventDictionary.has_key (key): + del self.eventDictionary [key] + def getField( self, key ): + '''Return a Field or Event object representing a given name + key -- string name + The name of the field or event to retrieve + will attempt to match key, key[4:], and key [:-8] + corresponding to key, set_key and key_changed + + see class Field + see class Event + ''' +# print self.fieldDictionary, self.eventDictionary + for tempkey in (key, key[4:], key[:-8]): + if self.fieldDictionary.has_key( tempkey ): + return Field( self.fieldDictionary[tempkey], self.defaultDictionary.get(tempkey) ) + elif self.eventDictionary.has_key( tempkey ): + return Event( self.eventDictionary[tempkey] ) + raise AttributeError, key + def getDefault( self, key ): + '''Return the default value for the given field + key -- string name + The name of the field + Will attempt to match key, key[4:], and key [:-8] + corresponding to key, set_key and key_changed + + see attribute defaultDictionary + ''' + for key in (key, key[4:], key[:-8]): + if self.defaultDictionary.has_key( key ): + val = self.defaultDictionary[key] + if type(val) in typeclasses.MutableTypes: + val = copy.deepcopy( val ) + return val + elif self.fieldDictionary.has_key( key ): + '''We have the field, but we don't have a default, we are likely an EXTERNPROTO''' + return None + raise AttributeError, key + def setDefault (self, key, value): + '''Set the default value for the given field + key -- string name + The name of the field to set + value -- object defaultValue + The default value, will be checked for type and coerced if necessary + ''' + field = self.getField (key) + self.defaultDictionary [field.name]= field.coerce (value) + def clone( self, children = 1, sceneGraph = 1 ): + '''Return a copy of this Prototype + children -- boolean + if true, copy the children of the Prototype, otherwise include them + sceneGraph -- boolean + if true, copy the sceneGraph of the Prototype + ''' + if sceneGraph: + sceneGraph = self.sceneGraph + else: + sceneGraph = None + # defaults should always be copied before modification, but this is still dangerous... + defaultDictionary = self.defaultDictionary.copy() + if not children: + for attrname in self.SFNodeNames+self.MFNodeNames: + try: + del defaultDictionary[attrname] + except KeyError: # sceneGraph object is not copied... + pass + # now make a copy + if self.__gi__ == "PROTO": + newNode = self.__class__( + self.nodeGI, + self.fieldDictionary, + defaultDictionary, + self.eventDictionary, + sceneGraph, + ) + else: + newNode = self.__class__( + self.nodeGI, + self.url, + self.fieldDictionary, + self.eventDictionary, + ) + return newNode + def __call__(self, *args, **namedargs): + '''Create a new Node instance associated with this Prototype + *args, **namedargs -- passed to the Node.__init__ + see class Node + ''' + node = apply( Node, (self, )+args, namedargs ) + return node + def __repr__ ( self ): + '''Create a simple Python representation''' + return '''%s( %s )'''%( self.__class__.__name__, self.nodeGI ) + +class ExternalPrototype( Prototype ): + '''Sub-class of Prototype + + The ExternalPrototype is a minor sub-classing of the Prototype + it does not have any defaults, nor a sceneGraph + + Attributes: + __gi__ -- constant string "EXTERNPROTO" + url -- string list urls + implementation source for the ExternalPrototype + ''' + __gi__ = "EXTERNPROTO" + def __init__(self, gi, url=None, fieldDict=None, eventDict=None): + ''' + gi -- string gi + see attribute nodeGI + url -- string list url + MFString-compatible list of url's for EXTERNPROTO + fieldDict -- string name: (string name, string dataType, boolean exposed) + see attribute fieldDictionary + eventDict -- string name: (string name, string dataType, boolean eventOut) + see attribute eventDictionary + ''' + if url is None: + url = [] + self.url = url + Prototype.__init__( self, gi, fieldDict=fieldDict, eventDict=eventDict) + + +from vrml import fieldcoercian # XXX +class Field: + ''' Representation of a Prototype Field + The Field object is a simple wrapper to provide convenient + access to field coercian and meta- information + ''' + def __init__( self, specification, default=None ): + self.name, self.type, self.exposure = specification + self.default = default + def getDefinition (self): + return self.name, self.type, self.exposure + def getDefault (self): + return self.default + def coerce( self, value ): + ''' Coerce value to the appropriate dataType for this Field ''' + return fieldcoercian.FieldCoercian()( value,self.type, ) + def __repr__( self ): + if hasattr (self, "default"): + return '%s( (%s,%s,%s), %s)'%( self.__class__.__name__, self.name, self.type, self.exposure, self.default) + else: + return '%s( (%s,%s,%s),)'%( self.__class__.__name__, self.name, self.type, self.exposure) + def __str__( self ): + if self.exposure: + exposed = "exposedField" + else: + exposed = field + if hasattr (self, "default"): + default = ' ' + str( self.default) + else: + default = "" + return '%s %s %s%s'%(exposed, self.type, self.name, default) + +class Event (Field): + def __str__( self ): + if self.exposure: + exposed = "eventOut" + else: + exposed = "eventIn" + return '%s %s %s'%(exposed, self.type, self.name) + + +### Translation strings for VRML node names... +translationstring = '''][0123456789{}"'#,.\\ \000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023''' +NAMEFIRSTCHARTRANSLATOR = string.maketrans( translationstring, '_'*len(translationstring) ) +translationstring = '''][{}"'#,.\\ \000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023''' +NAMERESTCHARTRANSLATOR = string.maketrans( translationstring, '_'*len(translationstring) ) +del translationstring +def checkName( name ): + '''Convert arbitrary string to a valid VRML id''' + if type(name) is types.StringType: + if not name: + return name + return string.translate( name[:1], NAMEFIRSTCHARTRANSLATOR) + string.translate( name[1:], NAMERESTCHARTRANSLATOR) + else: + raise TypeError, "VRML Node Name must be a string, was a %s: %s"%(type(name), name) + +class Node(baseProto): + ''' A VRML 97 Node object + + A Node object represents a VRML 97 node. Attributes of the Node + can be set/retrieved with standard python setattr/getattr syntax. + VRML 97 attributes may be passed to the constructor as named + arguments. + + Attributes: + __gi__ -- string PROTOname + DEF -- string DEFName + The DEF name of the node, will be coerced to be a valid + identifier (with "" being considered valid) + PROTO -- Prototype PROTO + The node's Prototype object + attributeDictionary -- string name: object value + Dictionary in which VRML 97 attributes are stored + ''' + DEF = '' # the default name for all nodes (arbitrary) + def __init__(self, PROTO, name='', attrDict=None, *args, **namedargs): + '''Normally this method is only called indirectly via the Prototype() interface + PROTO -- Prototype PROTO + see attribute PROTO + name -- string DEFName + see attribute DEF + attrDict -- string name: object value + see attribute attributeDictionary + **namedargs -- string name: object value + added to attrDict to create attributeDictionary + ''' + self.__dict__["PROTO"] = PROTO + self.DEF = name + self.__dict__["attributeDictionary"] = {} +## print attrDict, namedargs + for dict in (attrDict or {}), namedargs: + if dict: + for key, value in dict.items (): + self.__setattr__( key, value, check=1 ) + + def __setattr__( self, key, value, check=1, raw=0 ): + '''Set attribute on Node + key -- string attributeName + value -- object attributeValue + check -- boolean check + if false, put values for unrecognized keys into __dict__ + otherwise, raise an AttributeError + ''' + if key == "DEF": + self.__dict__["DEF"] = checkName( value ) + return None + elif key == "PROTO": + self.__dict__["PROTO"] = value + try: + field = self.PROTO.getField( key ) + if (hasattr( value, "__gi__") and value.__gi__ == "IS") or raw: + self.attributeDictionary[ field.name] = value + else: + self.attributeDictionary[ field.name] = field.coerce( value ) + except ValueError, x: + raise ValueError( "Could not coerce value %s into value of VRML type %s for %s node %s's field %s"%( value, field.type, self.__gi__, self.DEF, key), x.args) + except (AttributeError), x: + if check: + raise AttributeError("%s is not a known field for node %s"%(key, repr(self))) + else: + self.__dict__[key] = value + def __getattr__( self, key, default = 1 ): + ''' Retrieve an attribute when standard lookup fails + key -- string attributeName + default -- boolean default + if true, return the default value if the node does not have local value + otherwise, raise AttributeError + ''' + if key != "attributeDictionary": + if self.__dict__.has_key( key): + return self.__dict__[ key ] + elif self.attributeDictionary.has_key( key): + return self.attributeDictionary[key] + if key != "PROTO": + if key == "__gi__": + return self.PROTO.nodeGI + elif default: + try: + default = self.PROTO.getDefault( key ) + if type( default ) in typeclasses.MutableTypes: + # we need a copy, not the original + default = copy.deepcopy( default ) + self.__setattr__( key, default, check=0, raw=1 ) + return default + except AttributeError: + pass + raise AttributeError, key + def __delattr__( self, key ): + ''' Delete an attribute from the Node + key -- string attributeName + ''' + if key != "attributeDictionary": + if self.attributeDictionary.has_key( key): + del self.attributeDictionary[key] + elif self.__dict__.has_key( key): + del self.__dict__[ key ] + raise AttributeError, key + + def __repr__(self): + ''' Create simple python representation ''' + return '<%s(%s): %s>'%(self.__gi__, `self.DEF`, self.attributeDictionary.keys() ) + def getChildrenNames( self, current = 1, *args, **namedargs ): + ''' Get the (current) children of Node + returns two lists: MFNode children, SFNode children + current -- boolean currentOnly + if true, only return current children + otherwise, include all potential children + ''' + MFNODES, SFNODES = self.PROTO.MFNodeNames, self.PROTO.SFNodeNames + mns, sns = [],[] + for key in MFNODES: + if current and self.attributeDictionary.has_key(key): + mns.append(key) + elif not current: + mns.append(key) + for key in SFNODES: + if self.attributeDictionary.has_key(key): + sns.append(key) + elif not current: + sns.append(key) + return mns,sns + def calculateChildren(self, *args, **namedargs): + '''Calculate the current children of the Node as list of Nodes + ''' + MFNODES, SFNODES = self.getChildrenNames( ) + temp = [] + for key in MFNODES: + try: + temp.extend( self.__getattr__( key, default=0 ) ) + except AttributeError: + pass + for key in SFNODES: + try: + temp.append( self.__getattr__(key, default = 0 ) ) + except AttributeError: + pass + return temp + def clone(self, newclass=None, name=None, children=None, attrDeepCopy=1, *args, **namedargs): + '''Return a copy of this Node + newclass -- object newClass or None + optionally use a different Prototype as base + name -- string DEFName or None or 1 + if 1, copy from current + elif None, set to "" + else, set to passed value + children -- boolean copyChildren + if true, copy the children of this node + otherwise, skip children + attrDeepCopy -- boolean deepCopy + if true, use deepcopy + otherwise, use copy + ''' + if attrDeepCopy: + cpy = copy.deepcopy + else: + cpy = copy.copy + newattrs = self.attributeDictionary.copy() + if not children: + mnames,snames = self.getChildrenNames( ) + for key in mnames+snames: + try: + del(newattrs[key]) + except KeyError: + pass + for key, val in newattrs.items(): + if type(val) in typeclasses.MutableTypes: + newattrs[key] = cpy(val) + # following is Node specific, won't work for sceneGraphs, scripts, etceteras + if name == 1: # asked to copy the name + name = self.DEF + elif name is None: # asked to clear the name + name = '' + if not newclass: + newclass = self.PROTO + return newclass( name, newattrs ) + def __cmp__( self, other, stop=None ): + ''' Compare this node to another object/node + other -- object otherNode + stop -- boolean stopIfFailure + if true, failure to find comparison causes match failure (i.e. considered unequal) + ''' + + if hasattr( other, '__gi__') and other.__gi__ == self.__gi__: + try: + return cmp( self.DEF, other.DEF) or cmp( self.attributeDictionary, other.attributeDictionary ) + except: + if not stop: + try: + return other.__cmp__( self , 1) # 1 being stop... + except: + pass + return -1 # could be one, doesn't really matter + +def Script( name="", attrDict=None, fieldDict=None, defaultDict=None, eventDict=None, **namedarguments): + ''' Create a script node (and associated prototype) + name -- string DEFName + attrDict -- string name: object value + see class Node.attributeDictionary + fieldDict -- string name: (string name, string dataType, boolean exposure) + see class Prototype.fieldDictionary + defaultDict -- string name: object value + see class Prototype.defaultDictionary + eventDict -- string name: (string name, string dataType, boolean eventOut) + ''' + fieldDictionary = { + 'directOutput':('directOutput', 'SFBool',0), + 'url':('url',"MFString",0), + 'mustEvaluate':('mustEvaluate', 'SFBool',0), + } + fieldDictionary.update( fieldDict or {}) + defaultDictionary = { + "directOutput":0, + "url":[], + "mustEvaluate":0, + } + defaultDictionary.update( defaultDict or {}) + PROTO = Prototype( + "Script", + fieldDictionary, + defaultDictionary , + eventDict = eventDict, + ) + if attrDict is not None: + attrDict.update( namedarguments ) + else: + attrDict = namedarguments + return PROTO( name, attrDict ) + + +class NullNode: + '''NULL SFNode value + There should only be a single NULL instance for + any particular system. It should, for all intents and + purposes just sit there inertly + ''' + __gi__ = 'NULL' + DEF = '' + __walker_is_temporary_item__ = 1 # hacky signal to walking engine not to reject this node as already processed + def __repr__(self): + return '<NULL vrml SFNode>' + def __vrmlStr__(self,*args,**namedargs): + return ' NULL ' + toString = __vrmlStr__ + def __nonzero__(self ): + return 0 + def __call__(self, *args, **namedargs): + return self + def __cmp__( self, other ): + if hasattr( other, '__gi__') and other.__gi__ == self.__gi__: + return 0 + return -1 # could be one, doesn't really matter + def clone( self ): + return self +NULL = NullNode() + +class fieldRef: + '''IS Prototype field reference + ''' + __gi__ = 'IS' + DEF = '' + def __init__(self, declaredName): + self.declaredName = declaredName + def __repr__(self): + return 'IS %s'%self.declaredName + def __vrmlStr__(self,*args,**namedargs): + return 'IS %s'%self.declaredName + toString = __vrmlStr__ + def __cmp__( self, other ): + if hasattr( other, '__gi__') and other.__gi__ == self.__gi__: + return cmp( self.declaredName, other.declaredName ) + return -1 # could be one, doesn't really matter + def clone( self ): + return self.__class__( self.declaredName ) + +IS = fieldRef + +class ROUTE: + ''' VRML 97 ROUTE object + The ROUTE object keeps track of its source and destination nodes and attributes + It generally lives in a sceneGraph's "routes" collection + ''' + __gi__ = 'ROUTE' + def __init__( self, fromNode, fromField, toNode, toField ): + if type(fromNode) is types.StringType: + raise TypeError( "String value for ROUTE fromNode",fromNode) + if type(toNode) is types.StringType: + raise TypeError( "String value for ROUTE toNode",toNode) + self.fromNode = fromNode + self.fromField = fromField + self.toNode = toNode + self.toField = toField + def __getitem__( self, index ): + return (self.fromNode, self.fromField, self.toNode, self.toField)[index] + def __setitem__( self, index, value ): + attribute = ("fromNode","fromField","toNode", "toField")[index] + setattr( self, attribute, value ) + def __repr__( self ): + return 'ROUTE %s.%s TO %s.%s'%( self.fromNode.DEF, self.fromField, self.toNode.DEF, self.toField ) + def clone( self ): + return self.__class__( + self.fromNode, + self.fromField, + self.toNode, + self.toField, + ) + + +class sceneGraph(baseProto): + ''' A VRML 97 sceneGraph + Attributes: + __gi__ -- constant string "sceneGraph" + DEF -- constant string "" + children -- Node list + List of the root children of the sceneGraph, nodes/scripts only + routes -- ROUTE list + List of the routes within the sceneGraph + defNames -- string DEFName: Node node + Mapping of DEF names to their respective nodes + protoTypes -- Namespace prototypes + Namespace (with chaining lookup) collection of prototypes + getattr( sceneGraph.protoTypes, 'nodeGI' ) retrieves a prototype + ''' + __gi__ = 'sceneGraph' + DEF = '' + def __init__(self, root=None, protoTypes=None, routes=None, defNames=None, children=None, *args, **namedargs): + ''' + root -- sceneGraph root or Dictionary root or Module root or None + Base object for root of protoType namespace hierarchy + protoTypes -- string nodeGI: Prototype PROTO + Dictionary of prototype definitions + routes -- ROUTE list or (string sourcenode, string sourceeventOut, string destinationnode, string destinationeventOut) list + List of route objects or tuples to be added to the sceneGraph + see attribute routes + defNames -- string DEFName: Node node + see attribute defNames + children -- Node list + see attribute children + ''' + if children is None: + self.children = [] + else: + self.children = children + if routes is None: + self.routes = [] # how will we efficiently handle routes? + else: + self.routes = routes + if defNames == None: + self.defNames = {} # maps 'defName':Node + else: + self.defNames = defNames + if protoTypes is None: + protoTypes = {} + if root is None: + from vrml import basenodes # XXX + self.protoTypes = namespace.NameSpace( + protoTypes, + children = [namespace.NameSpace(basenodes)] + ) + else: # there is a root file, so need to use it as the children instead of basenodes... + if hasattr( root, "protoTypes"): + self.protoTypes = namespace.NameSpace( + protoTypes, + children = [root.protoTypes] + ) + else: + self.protoTypes = namespace.NameSpace( + protoTypes, + children = [ namespace.NameSpace(root) ] + ) + def __getinitargs__( self ): + # we only copy our explicit protos, our routes, our defNames, and our children + # inherited protos will be pulled along by their nodes... + return None, self.protoTypes._base, self.routes, self.defNames, self.children + def __getstate__( self ): + return {} + def __setstate__( self, dict ): + pass + def __del__( self, id=id ): + ''' + Need to clean up the namespace's mutual references, + this can be done without affecting the cascade by just + eliminating the key/value pairs. The namespaces will + no longer contain the prototypes, but they will still + chain up to the higher-level namespaces, and the nodes + will have those prototypes still in use. + ''' +## print 'del sceneGraph', id(self ) + try: +## import pdb +## pdb.set_trace() +## self.protoTypes.__dict__.clear() + self.protoTypes._base.clear() + del self.protoTypes.__namespace_cascade__[:] + except: + print 'unable to free references' + + def addRoute(self, routeTuple, getNewNodes=0): + ''' Add a single route to the sceneGraph + routeTuple -- ROUTE route or (string sourcenode, string sourceeventOut, string destinationnode, string destinationeventOut) + getNewNodes -- boolean getNewNodes + if true, look up sourcenode and destinationnode within the current defNames to determine source/destination nodes + otherwise, just use current if available + ''' + # create and wire together the Routes here, + # should just be a matter of pulling the events and passing the nodes... +## import pdb +## pdb.set_trace() + if type( routeTuple) in ( types.TupleType, types.ListType): + (fromNode, fromField, toNode, toField ) = routeTuple + if type(fromNode) is types.StringType: + # get the node instead of the string... + if self.defNames.has_key( fromNode ): + fromNode = self.defNames[fromNode] + else: + err.err( "ROUTE from an unknown node %s "%(routeTuple) ) + return 0 + if type(toNode) is types.StringType: + # get the node instead of the string... + if self.defNames.has_key( toNode ): + toNode = self.defNames[toNode] + else: + err.err( "ROUTE to an unknown node %s "%(routeTuple) ) + return 0 + routeTuple = ROUTE( fromNode, fromField, toNode, toField) + elif getNewNodes: + # get the nodes with the same names... + if self.defNames.has_key( routeTuple[0].DEF ): + routeTuple[0] = self.defNames[routeTuple[0].DEF] + else: + err.err( "ROUTE from an unknown node %s "%(routeTuple) ) + return 0 + if self.defNames.has_key( routeTuple[2].DEF ): + routeTuple[2] = self.defNames[routeTuple[2].DEF] + else: + err.err( "ROUTE to an unknown node %s "%(routeTuple) ) + return 0 + # should be a Route node now, append to our ROUTE list... + self.routes.append(routeTuple) + return 1 + def regDefName(self, defName, object): + ''' Register a DEF name for a particular object + defName -- string DEFName + object -- Node node + ''' + object.DEF = defName + self.defNames[defName] = object + def addProto(self, proto): + '''Register a Prototype for this sceneGraph + proto -- Prototype PROTO + ''' + setattr( self.protoTypes, proto.__gi__, proto ) + #toString = __vrmlStr__ + #__vrmlStr__ = toString +## def __setattr__( self, key, value ): +## if key == 'protoTypes' and type( value) is types.ListType: +## import pdb +## pdb.set_trace() +## raise TypeError( "Invalid type for protoTypes attribute of sceneGraph %s"%(`value`) ) +## else: +## self.__dict__[key] = value + +DEFAULTFIELDVALUES ={ + "SFBool": 0, + "SFString": "", + "SFFloat": 0, + "SFTime": 0, + "SFVec3f": (0, 0,0), + "SFVec2f": (0,0), + "SFRotation": (0, 1,0, 0), + "SFInt32": 0, + "SFImage": (0,0,0), + "SFColor": (0,0, 0), + "SFNode": NULL, + "MFString": [], + "MFFloat": [], + "MFTime": [], + "MFVec3f": [], + "MFVec2f": [], + "MFRotation": [], + "MFInt32": [], + "MFColor": [], + "MFNode": [], +} + + + diff --git a/intern/python/modules/vrml/utils/__init__.py b/intern/python/modules/vrml/utils/__init__.py new file mode 100644 index 00000000000..9d708a9084c --- /dev/null +++ b/intern/python/modules/vrml/utils/__init__.py @@ -0,0 +1 @@ +"""utilities""" diff --git a/intern/python/modules/vrml/utils/collapse.py b/intern/python/modules/vrml/utils/collapse.py new file mode 100644 index 00000000000..25da50c2adb --- /dev/null +++ b/intern/python/modules/vrml/utils/collapse.py @@ -0,0 +1,169 @@ +''' +Destructive Functions for "collapsing" Sequences into single levels + +>>> from mcf.utils import collapse + +>>> collapse.test([[[1],[2,3]],[[]],[4],5,[6]]) + +[1, 2, 3, 4, 5, 6] # note that is the same root list + +>>> collapse.collapse2([[[1],[2,3]],[[]],(4,()),(5,),[6]]) + +[1, 2, 3, 4, 5, 6] # note is the same root list +''' +import copy, types, sys +from types import ListType, TupleType # this now only supports the obsolete stuff... + +def hyperCollapse( inlist, allowedmap, type=type, list=list, itype=types.InstanceType, maxint= sys.maxint): + ''' + Destructively flatten a mixed hierarchy to a single level. + Non-recursive, many speedups and obfuscations by Tim Peters :) + ''' + try: + # for every possible index + for ind in xrange( maxint): + # while that index currently holds a list + expandable = 1 + while expandable: + expandable = 0 + if allowedmap.has_key( type(inlist[ind]) ): + # expand that list into the index (and subsequent indicies) + inlist[ind:ind+1] = list( inlist[ind]) + expandable = 1 + + # alternately you could iterate through checking for isinstance on all possible + # classes, but that would be very slow + elif type( inlist[ind] ) is itype and allowedmap.has_key( inlist[ind].__class__ ): + # here figure out some way to generically expand that doesn't risk + # infinite loops... + templist = [] + for x in inlist[ind]: + templist.append( x) + inlist[ind:ind+1] = templist + expandable = 1 + except IndexError: + pass + return inlist + + +def collapse(inlist, type=type, ltype=types.ListType, maxint= sys.maxint): + ''' + Destructively flatten a list hierarchy to a single level. + Non-recursive, and (as far as I can see, doesn't have any + glaring loopholes). + Further speedups and obfuscations by Tim Peters :) + ''' + try: + # for every possible index + for ind in xrange( maxint): + # while that index currently holds a list + while type(inlist[ind]) is ltype: + # expand that list into the index (and subsequent indicies) + inlist[ind:ind+1] = inlist[ind] + #ind = ind+1 + except IndexError: + pass + return inlist + +def collapse_safe(inlist): + ''' + As collapse, but works on a copy of the inlist + ''' + return collapse( inlist[:] ) + +def collapse2(inlist, ltype=(types.ListType, types.TupleType), type=type, maxint= sys.maxint ): + ''' + Destructively flatten a list hierarchy to a single level. + Will expand tuple children as well, but will fail if the + top level element is not a list. + Non-recursive, and (as far as I can see, doesn't have any + glaring loopholes). + ''' + ind = 0 + try: + while 1: + while type(inlist[ind]) in ltype: + try: + inlist[ind:ind+1] = inlist[ind] + except TypeError: + inlist[ind:ind+1] = list(inlist[ind]) + ind = ind+1 + except IndexError: + pass + return inlist + +def collapse2_safe(inlist): + ''' + As collapse2, but works on a copy of the inlist + ''' + return collapse( list(inlist) ) + +def old_buggy_collapse(inlist): + '''Always return a one-level list of all the non-list elements in listin, + rewritten to be non-recursive 96-12-28 Note that the new versions work + on the original list, not a copy of the original.''' + if type(inlist)==TupleType: + inlist = list(inlist) + elif type(inlist)!=ListType: + return [inlist] + x = 0 + while 1: + try: + y = inlist[x] + if type(y) == ListType: + ylen = len(y) + if ylen == 1: + inlist[x] = y[0] + if type(inlist[x]) == ListType: + x = x - 1 # need to collapse that list... + elif ylen == 0: + del(inlist[x]) + x = x-1 # list has been shortened + else: + inlist[x:x+1]=y + x = x+1 + except IndexError: + break + return inlist + + +def old_buggy_collapse2(inlist): + '''As collapse, but also collapse tuples, rewritten 96-12-28 to be non-recursive''' + if type(inlist)==TupleType: + inlist = list(inlist) + elif type(inlist)!=ListType: + return [inlist] + x = 0 + while 1: + try: + y = inlist[x] + if type(y) in [ListType, TupleType]: + ylen = len(y) + if ylen == 1: + inlist[x] = y[0] + if type(inlist[x]) in [ListType,TupleType]: + x = x-1 #(to deal with that element) + elif ylen == 0: + del(inlist[x]) + x = x-1 # list has been shortened, will raise exception with tuples... + else: + inlist[x:x+1]=list(y) + x = x+1 + except IndexError: + break + return inlist + + +def oldest_buggy_collapse(listin): + 'Always return a one-level list of all the non-list elements in listin' + if type(listin) == ListType: + return reduce(lambda x,y: x+y, map(collapse, listin), []) + else: return [listin] + +def oldest_buggy_collapse2(seqin): + + if type(seqin) in [ListType, TupleType]: + return reduce(lambda x,y: x+y, map(collapse2, seqin), []) + else: + return [seqin] + diff --git a/intern/python/modules/vrml/utils/err.py b/intern/python/modules/vrml/utils/err.py new file mode 100644 index 00000000000..3c6591a6873 --- /dev/null +++ b/intern/python/modules/vrml/utils/err.py @@ -0,0 +1,37 @@ +''' +err.py Encapsulated writing to sys.stderr + +The idea of this module is that, for a GUI system (or a more advanced UI), +you can just import a different err module (or object) and keep +your code the same. (For instance, you often want a status window +which flashes warnings and info, and have error messages pop up an +alert to get immediate attention. +''' + +import sys + +def err(message, Code=0): + ''' + report an error, with an optional error code + ''' + if Code: + sys.stderr.write('Error #%i: %s\n'%(Code,message)) + else: + sys.stderr.write('Error: %s\n'%message) +def warn(message, Code=0): + ''' + report a warning, with an optional error code + ''' + if Code: + sys.stderr.write('Warning #%i: %s\n'%(Code,message)) + else: + sys.stderr.write('Warning: %s\n'%message) +def info(message, Code=0): + ''' + report information/status, with an optional error code + ''' + if Code: + sys.stderr.write('Info #%i: %s\n'%(Code,message)) + else: + sys.stderr.write('Info: %s\n'%message) + diff --git a/intern/python/modules/vrml/utils/namespace.py b/intern/python/modules/vrml/utils/namespace.py new file mode 100644 index 00000000000..dd9f0b7dea6 --- /dev/null +++ b/intern/python/modules/vrml/utils/namespace.py @@ -0,0 +1,225 @@ +''' +NameSpace v0.04: + +A "NameSpace" is an object wrapper around a _base dictionary +which allows chaining searches for an 'attribute' within that +dictionary, or any other namespace which is defined as part +of the search path (depending on the downcascade variable, is +either the hier-parents or the hier-children). + +You can assign attributes to the namespace normally, and read +them normally. (setattr, getattr, a.this = that, a.this) + +I use namespaces for writing parsing systems, where I want to +differentiate between sources (have multiple sources that I can +swap into or out of the namespace), but want to be able to get +at them through a single interface. There is a test function +which gives you an idea how to use the system. + +In general, call NameSpace(someobj), where someobj is a dictionary, +a module, or another NameSpace, and it will return a NameSpace which +wraps up the keys of someobj. To add a namespace to the NameSpace, +just call the append (or hier_addchild) method of the parent namespace +with the child as argument. + +### NOTE: if you pass a module (or anything else with a dict attribute), +names which start with '__' will be removed. You can avoid this by +pre-copying the dict of the object and passing it as the arg to the +__init__ method. + +### NOTE: to properly pickle and/or copy module-based namespaces you +will likely want to do: from mcf.utils import extpkl, copy_extend + +### Changes: + 97.05.04 -- Altered to use standard hierobj interface, cleaned up + interface by removing the "addparent" function, which is reachable + by simply appending to the __parent__ attribute, though normally + you would want to use the hier_addchild or append functions, since + they let both objects know about the addition (and therefor the + relationship will be restored if the objects are stored and unstored) + + 97.06.26 -- Altered the getattr function to reduce the number of + situations in which infinite lookup loops could be created + (unfortunately, the cost is rather high). Made the downcascade + variable harden (resolve) at init, instead of checking for every + lookup. (see next note) + + 97.08.29 -- Discovered some _very_ weird behaviour when storing + namespaces in mcf.store dbases. Resolved it by storing the + __namespace_cascade__ attribute as a normal attribute instead of + using the __unstore__ mechanism... There was really no need to + use the __unstore__, but figuring out how a functions saying + self.__dict__['__namespace_cascade__'] = something + print `self.__dict__['__namespace_cascade__']` can print nothing + is a bit beyond me. (without causing an exception, mind you) + + 97.11.15 Found yet more errors, decided to make two different + classes of namespace. Those based on modules now act similar + to dummy objects, that is, they let you modify the original + instead of keeping a copy of the original and modifying that. + + 98.03.15 -- Eliminated custom pickling methods as they are no longer + needed for use with Python 1.5final + + 98.03.15 -- Fixed bug in items, values, etceteras with module-type + base objects. +''' +import copy, types, string + +from mcf.utils import hierobj + +class NameSpace(hierobj.Hierobj): + ''' + An hierarchic NameSpace, allows specification of upward or downward + chaining search for resolving names + ''' + def __init__(self, val = None, parents=None, downcascade=1,children=[]): + ''' + A NameSpace can be initialised with a dictionary, a dummied + dictionary, another namespace, or something which has a __dict__ + attribute. + Note that downcascade is hardened (resolved) at init, not at + lookup time. + ''' + hierobj.Hierobj.__init__(self, parents, children) + self.__dict__['__downcascade__'] = downcascade # boolean + if val is None: + self.__dict__['_base'] = {} + else: + if type( val ) == types.StringType: + # this is a reference to a module which has been pickled + val = __import__( val, {},{}, string.split( val, '.') ) + try: + # See if val's a dummy-style object which has a _base + self.__dict__['_base']=copy.copy(val._base) + except (AttributeError,KeyError): + # not a dummy-style object... see if it has a dict attribute... + try: + if type(val) != types.ModuleType: + val = copy.copy(val.__dict__) + except (AttributeError, KeyError): + pass + # whatever val is now, it's going to become our _base... + self.__dict__['_base']=val + # harden (resolve) the reference to downcascade to speed attribute lookups + if downcascade: self.__dict__['__namespace_cascade__'] = self.__childlist__ + else: self.__dict__['__namespace_cascade__'] = self.__parent__ + def __setattr__(self, var, val): + ''' + An attempt to set an attribute should place the attribute in the _base + dictionary through a setitem call. + ''' + # Note that we use standard attribute access to allow ObStore loading if the + # ._base isn't yet available. + try: + self._base[var] = val + except TypeError: + setattr(self._base, var, val) + def __getattr__(self,var): +## print '__getattr__', var + return self.__safe_getattr__(var, {}) # the {} is a stopdict + + def __safe_getattr__(self, var,stopdict): + ''' + We have a lot to do in this function, if the attribute is an unloaded + but stored attribute, we need to load it. If it's not in the stored + attributes, then we need to load the _base, then see if it's in the + _base. + If it's not found by then, then we need to check our resource namespaces + and see if it's in them. + ''' + # we don't have a __storedattr__ or it doesn't have this key... + if var != '_base': + try: + return self._base[var] + except (KeyError,TypeError), x: + try: + return getattr(self._base, var) + except AttributeError: + pass + try: # with pickle, it tries to get the __setstate__ before restoration is complete + for cas in self.__dict__['__namespace_cascade__']: + try: + stopdict[id(cas)] # if succeeds, we've already tried this child + # no need to do anything, if none of the children succeeds we will + # raise an AttributeError + except KeyError: + stopdict[id(cas)] = None + return cas.__safe_getattr__(var,stopdict) + except (KeyError,AttributeError): + pass + raise AttributeError, var + def items(self): + try: + return self._base.items() + except AttributeError: + pass + try: + return self._base.__dict__.items() + except AttributeError: + pass + def keys(self): + try: + return self._base.keys() + except AttributeError: + pass + try: + return self._base.__dict__.keys() + except AttributeError: + pass + def has_key( self, key ): + try: + return self._base.has_key( key) + except AttributeError: + pass + try: + return self._base.__dict__.has_key( key) + except AttributeError: + pass + def values(self): + try: + return self._base.values() + except AttributeError: + pass + try: + return self._base.__dict__.values() + except AttributeError: + pass + + def __getinitargs__(self): + if type( self._base ) is types.ModuleType: + base = self._base.__name__ + else: + base = self._base + return (base, self.__parent__, self.__downcascade__, self.__childlist__) + def __getstate__(self): + return None + def __setstate__(self,*args): + pass + def __deepcopy__(self, memo=None): + d = id(self) + if memo is None: + memo = {} + elif memo.has_key(d): + return memo[d] + if type(self._base) == types.ModuleType: + rest = tuple(map( copy.deepcopy, (self.__parent__, self.__downcascade__, self.__childlist__) )) + new = apply(self.__class__, (self._base,)+rest ) + else: + new = tuple(map( copy.deepcopy, (self._base, self.__parent__, self.__downcascade__, self.__childlist__) )) + return new +## def __del__( self, id=id ): +## print 'del namespace', id( self ) + + +def test(): + import string + a = NameSpace(string) + del(string) + a.append(NameSpace({'a':23,'b':42})) + import math + a.append(NameSpace(math)) + print 'The returned object should allow access to the attributes of the string,\nand math modules, and two simple variables "a" and "b" (== 23 and42 respectively)' + return a + + diff --git a/intern/python/modules/vrml/utils/typeclasses.py b/intern/python/modules/vrml/utils/typeclasses.py new file mode 100644 index 00000000000..ed798dfe3da --- /dev/null +++ b/intern/python/modules/vrml/utils/typeclasses.py @@ -0,0 +1,50 @@ +''' +Classes of Types + +Often you want to be able to say: + if type(obj) in MutableTypes: + yada + +This module is intended to make that easier. +Just import and use :) +''' +import types + +MutableTypes = [ types.ListType, types.DictType, types.InstanceType ] +MutableSequenceTypes = [ types.ListType ] +SequenceTypes = [ types.ListType, types.StringType, types.TupleType ] +NumericTypes = [ types.IntType, types.FloatType, types.LongType, types.ComplexType ] +MappingTypes = [ types.DictType ] + +def regarray(): + if globals().has_key('array'): + return 1 + try: + import array + SequenceTypes.append( array.ArrayType ) + MutableTypes.append( array.ArrayType ) + MutableSequenceTypes.append( array.ArrayType ) + return 1 + except ImportError: + return 0 + +def regnumpy(): + ''' + Call if you want to register numpy arrays + according to their types. + ''' + if globals().has_key('Numeric'): + return 1 + try: + import Numeric + SequenceTypes.append( Numeric.ArrayType ) + MutableTypes.append( Numeric.ArrayType ) + MutableSequenceTypes.append( Numeric.ArrayType ) + return 1 + except ImportError: + return 0 + +# for now, I'm going to always register these, if the module becomes part of the base distribution +# it might be better to leave it out so numpy isn't always getting loaded... +regarray() +regnumpy()
\ No newline at end of file diff --git a/intern/python/objexport/BlendImport.py b/intern/python/objexport/BlendImport.py new file mode 100644 index 00000000000..d72370f783f --- /dev/null +++ b/intern/python/objexport/BlendImport.py @@ -0,0 +1,157 @@ +#! /usr/bin/env python + +####################### +# (c) Jan Walter 2000 # +####################### + +# CVS +# $Author$ +# $Date$ +# $RCSfile$ +# $Revision$ + +TAB = " " + +vertices = [] +vertexNormals = [] +faces = [] +materials = [] +switchMaterial = [] +currentMaterial = [] +materialIndex = 0 + +def addVertex(x, y, z): + global vertices + vertices.append([x, y, z]) + return len(vertices) + +def addVertexNormal(i, j, k): + global vertexNormals + vertexNormals.append([i, j, k]) + return len(vertexNormals) + +def addFace(vi, ti, ni): + global faces + faces.append([vi, ti, ni]) + return len(faces) + +def addMaterial(name, Kd, Ks, Ka): + global materials + materials.append([name, Kd, Ks, Ka]) + return len(materials) + +def findMaterial(name): + global materials + for material in materials: + if material[0] == name: + return material + +def setCurrentMaterial(name): + global switchMaterial, faces, currentMaterial + switchMaterial.append(len(faces)) + currentMaterial.append(name) + +class OpenInventor: + def export(self, filename, useNormals = 1, useMaterials = 1): + global vertices, vertexNormals, faces, materials, switchMaterial + global currentMaterial, materialIndex + file = open(filename, "w") + file.write("#Inventor V2.1 ascii\n\n") + file.write("Separator {\n") + ############ + # vertices # + ############ + file.write("%sCoordinate3 {\n" % (TAB, )) + file.write("%spoint [ \n" % (TAB*2, )) + for i in xrange(len(vertices)-1): + x, y, z = vertices[i] + file.write("%s %s %s %s,\n" % (TAB*2, x, y, z)) + x, y, z = vertices[i+1] + file.write("%s %s %s %s\n" % (TAB*2, x, y, z)) + file.write("%s ] \n" % (TAB*2, )) + file.write("%s}\n" % (TAB, )) + ########### + # normals # + ########### + if useNormals: + file.write("%sNormal {\n" % (TAB, )) + file.write("%svector [ \n" % (TAB*2, )) + for i in xrange(len(vertexNormals)-1): + x, y, z = vertexNormals[i] + file.write("%s %s %s %s,\n" % (TAB*2, x, y, z)) + x, y, z = vertexNormals[i-1] + file.write("%s %s %s %s\n" % (TAB*2, x, y, z)) + file.write("%s ] \n" % (TAB*2, )) + file.write("%s}\n" % (TAB, )) + ######### + # faces # + ######### + switchMaterial.append(len(faces)) + for si in xrange(len(switchMaterial) - 1): + i1, i2 = switchMaterial[si], switchMaterial[si+1] + # -------------- + # write material + # -------------- + if materials: + name = currentMaterial[materialIndex] + material = findMaterial(name) + if useMaterials: + file.write("%sMaterial {\n" % (TAB, )) + file.write("%sambientColor %s %s %s\n" % + (TAB*2, + material[3][0], + material[3][1], + material[3][2])) + file.write("%sdiffuseColor %s %s %s\n" % + (TAB*2, + material[1][0], + material[1][1], + material[1][2])) + file.write("%sspecularColor %s %s %s\n" % + (TAB*2, + material[2][0], + material[2][1], + material[2][2])) + file.write("%s}\n" % (TAB, )) + # ----------- + # write faces + # ----------- + file.write("%sIndexedFaceSet {\n" % (TAB, )) + # indices for vertices + file.write("%scoordIndex [ \n" % (TAB*2, )) + for i in xrange(i1, i2-1): + indices = faces[i][0] + istring = "" + for index in indices: + # indices begin with 0 in OpenInventor + istring = istring + "%s, " % (index - 1, ) + file.write("%s %s-1, \n" % (TAB*2, istring)) + indices = faces[i+1][0] + istring = "" + for index in indices: + # indices begin with 0 in OpenInventor + istring = istring + "%s, " % (index - 1, ) + file.write("%s %s-1\n" % (TAB*2, istring)) + file.write("%s ] \n" % (TAB*2, )) + # update materialIndex + materialIndex = materialIndex + 1 + if useNormals: + # indices for normals + file.write("%snormalIndex [ \n" % (TAB*2, )) + for i in xrange(i1, i2-1): + indices = faces[i][2] + istring = "" + for index in indices: + # indices begin with 0 in OpenInventor + istring = istring + "%s, " % (index - 1, ) + file.write("%s %s-1, \n" % (TAB*2, istring)) + indices = faces[i+1][2] + istring = "" + for index in indices: + # indices begin with 0 in OpenInventor + istring = istring + "%s, " % (index - 1, ) + file.write("%s %s-1\n" % (TAB*2, istring)) + file.write("%s ] \n" % (TAB*2, )) + file.write("%s}\n" % (TAB, )) + file.write("}\n") + file.close() diff --git a/intern/python/objexport/objimport.py b/intern/python/objexport/objimport.py new file mode 100644 index 00000000000..0150a2571ad --- /dev/null +++ b/intern/python/objexport/objimport.py @@ -0,0 +1,119 @@ +#! /usr/bin/env python + +####################### +# (c) Jan Walter 2000 # +####################### + +# CVS +# $Author$ +# $Date$ +# $RCSfile$ +# $Revision$ + +import BlendImport +import os +import sys +import string + +def usage(): + print "usage: python objimport.py objfile" + +def testObjImport(filename): + print filename + vcount = 0 + vncount = 0 + fcount = 0 + file = open(filename, "r") + lines = file.readlines() + linenumber = 1 + for line in lines: + words = string.split(line) + if words and words[0] == "#": + pass # ignore comments + elif words and words[0] == "v": + vcount = vcount + 1 + x = string.atof(words[1]) + y = string.atof(words[2]) + z = string.atof(words[3]) + ##print "Vertex %s: (%s, %s, %s)" % (vcount, x, y, z) + index = BlendImport.addVertex(x, y, z) + ##print "addVertex(%s)" % index + elif words and words[0] == "vn": + vncount = vncount + 1 + i = string.atof(words[1]) + j = string.atof(words[2]) + k = string.atof(words[3]) + ##print "VertexNormal %s: (%s, %s, %s)" % (vncount, i, j, k) + index = BlendImport.addVertexNormal(i, j, k) + ##print "addVertexNormal(%s)" % index + elif words and words[0] == "f": + fcount = fcount + 1 + vi = [] # vertex indices + ti = [] # texture indices + ni = [] # normal indices + words = words[1:] + lcount = len(words) + for index in (xrange(lcount)): + vtn = string.split(words[index], "/") + vi.append(string.atoi(vtn[0])) + if len(vtn) > 1 and vtn[1]: + ti.append(string.atoi(vtn[1])) + if len(vtn) > 2 and vtn[2]: + ni.append(string.atoi(vtn[2])) + ##print "Face %s: (%s, %s, %s)" % (fcount, vi, ti, ni) + index = BlendImport.addFace(vi, ti, ni) + ##print "addFace(%s)" % index + elif words and words[0] == "mtllib": + # try to export materials + directory, dummy = os.path.split(filename) + filename = os.path.join(directory, words[1]) + try: + file = open(filename, "r") + except: + print "no material file %s" % filename + else: + file = open(filename, "r") + line = file.readline() + while line: + words = string.split(line) + if words and words[0] == "newmtl": + name = words[1] + file.readline() # Ns . + file.readline() # d . + file.readline() # illum . + line = file.readline() + words = string.split(line) + Kd = [string.atof(words[1]), + string.atof(words[2]), + string.atof(words[3])] + line = file.readline() + words = string.split(line) + Ks = [string.atof(words[1]), + string.atof(words[2]), + string.atof(words[3])] + line = file.readline() + words = string.split(line) + Ka = [string.atof(words[1]), + string.atof(words[2]), + string.atof(words[3])] + index = BlendImport.addMaterial(name, Kd, Ks, Ka) + line = file.readline() + file.close() + elif words and words[0] == "usemtl": + name = words[1] + BlendImport.setCurrentMaterial(name) + elif words: + pass + ##print "%s: %s" % (linenumber, words) + linenumber = linenumber + 1 + file.close() + # export to OpenInventor + BlendImport.OpenInventor().export("test.iv", + useNormals = 1, useMaterials = 1) + +if __name__ == "__main__": + if len(sys.argv) != 2: + usage() + else: + filename = sys.argv[1] + testObjImport(filename) diff --git a/intern/python/py_main.c b/intern/python/py_main.c new file mode 100644 index 00000000000..308ab0266ff --- /dev/null +++ b/intern/python/py_main.c @@ -0,0 +1,2292 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* CVS */ + +/* $Author$ */ +/* $Date$ */ +/* $RCSfile$ */ +/* $Revision$ */ + +/* Jan Walter's stuff */ +#include "Python.h" +#include "blender.h" + +static PyObject* ErrorObject; + +uint* mcol_to_vcol(Mesh *me); +void mcol_to_rgb(uint col, float *r, float *g, float *b); +void initBlender(); +static PyObject* blend_connect(PyObject* self, PyObject* args); +static PyObject* blend_getObject(PyObject* self, PyObject* args); +/* Jan Walter's stuff */ + +/* Daniel Dunbar's stuff */ +void start_python (void); +void end_python(void); +void txt_do_python (Text* text); +void do_all_scripts(short event); +void do_all_scriptlist(ListBase* list, short event); +void do_pyscript(ID *id, short event); +void clear_bad_scriptlink(ID* id, Text* byebye); +void clear_bad_scriptlinks(Text *byebye); +void free_scriptlink(ScriptLink *slink); +void copy_scriptlink(ScriptLink *scriptlink); + +void start_python (void) +{ + Py_SetProgramName("blender"); + Py_Initialize(); + initBlender(); +} + +void end_python(void) +{ + Py_Finalize(); +} + +void txt_do_python (Text* text) +{ + char filename[] = "test.py"; + FILE* fp = NULL; + + if (text->name) + { + fp = fopen(text->name, "r"); + } + else + { + fp = fopen(filename, "r"); + } + if (fp) + { + if (text->name) + { + PyRun_AnyFile(fp, text->name); + } + else + { + PyRun_AnyFile(fp, filename); + } + } + else + { + if (text->name) + { + printf("Couldn't run %s ...\n", text->name); + } + else + { + printf("Couldn't run test.py ...\n"); + } + } +} + +void do_all_scripts(short event) +{ +} + +void do_all_scriptlist(ListBase* list, short event) +{ +} + +void do_pyscript(ID *id, short event) +{ +} + +void clear_bad_scriptlink(ID* id, Text* byebye) +{ +} + +void clear_bad_scriptlinks(Text *byebye) +{ +} + +void free_scriptlink(ScriptLink *slink) +{ +} + +void copy_scriptlink(ScriptLink *scriptlink) +{ +} +/* Daniel Dunbar's stuff */ + +ID* find_name_in_list(ID* list, const char* name) +{ + while (list) + { + if (STREQ(name, list->name+2)) + { + break; + } + else + { + list = list->next; + } + } + + return list; +} + +/* Jan Walter's stuff */ +/**************/ +/* structures */ +/**************/ + +typedef struct { + PyObject_HEAD + char name[24]; + PyObject* Lens; + PyObject* ClSta; + PyObject* ClEnd; +} camobject; + +staticforward PyTypeObject Camtype; + +typedef struct { + PyObject_HEAD + PyObject* startFrame; + PyObject* endFrame; + PyObject* currentFrame; + PyObject* xResolution; + PyObject* yResolution; + PyObject* pixelAspectRatio; +} dspobject; + +staticforward PyTypeObject Dsptype; + +typedef struct { + PyObject_HEAD + char name[24]; + PyObject* R; + PyObject* G; + PyObject* B; +} lmpobject; + +staticforward PyTypeObject Lmptype; + +typedef struct { + PyObject_HEAD + char name[24]; + PyObject* R; + PyObject* G; + PyObject* B; +} matobject; + +staticforward PyTypeObject Mattype; + +typedef struct { + PyObject_HEAD + char name[24]; + PyObject* vertices; + PyObject* normals; + PyObject* colors; + PyObject* faces; + PyObject* texture; + PyObject* texcoords; +} mshobject; + +staticforward PyTypeObject Mshtype; + +typedef struct { + PyObject_HEAD + char name[24]; + PyObject* matrix; + PyObject* inverseMatrix; + PyObject* materials; + PyObject* data; + PyObject* type; +} objobject; + +staticforward PyTypeObject Objtype; + +typedef struct { + PyObject_HEAD + char name[24]; + PyObject* objects; +} sceobject; + +staticforward PyTypeObject Scetype; + +/**********/ +/* camera */ +/**********/ + +static struct PyMethodDef cam_methods[] = { + { NULL, NULL } +}; + +static camobject* +newcamobject(char* name) +{ + camobject* self; + ID* list = NULL; + + self = PyObject_NEW(camobject, &Camtype); + if (self == NULL) + { + return NULL; + } + strcpy(self->name, name); + self->Lens = PyFloat_FromDouble(35.0); + self->ClSta = PyFloat_FromDouble(0.1); + self->ClEnd = PyFloat_FromDouble(100.0); + + return self; +} + +static void +cam_dealloc(camobject* self) +{ + camobject* cam = (camobject*) self; + + Py_DECREF(cam->Lens); + Py_DECREF(cam->ClSta); + Py_DECREF(cam->ClEnd); + + PyMem_DEL(self); +} + +static int +cam_print(camobject* self, FILE* fp, int flags) +{ + fprintf(fp, "Camera(name = \"%s\")\n", self->name); + + return 0; +} + +static PyObject* +cam_repr(camobject* self) +{ + PyObject* s; + + s = PyString_FromString("Camera()\n"); + + return s; +} + +static PyObject* +cam_str(camobject* self) +{ + PyObject* s; + + s = PyString_FromString("Camera()\n"); + + return s; +} + +#include "structmember.h" + +static struct memberlist cam_memberlist[] = { + /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */ + {"Lens", T_OBJECT, offsetof(camobject, Lens), RO}, + {"ClSta", T_OBJECT, offsetof(camobject, ClSta), RO}, + {"ClEnd", T_OBJECT, offsetof(camobject, ClEnd), RO}, + {NULL} +}; + +static PyObject* +cam_getattr(camobject* self, char* name) +{ + PyObject* rv; + + /* XXXX Add your own getattr code here */ + rv = PyMember_Get((char*) self, cam_memberlist, name); + if (rv) + { + return rv; + } + PyErr_Clear(); + + return Py_FindMethod(cam_methods, (PyObject*)self, name); +} + + +static int +cam_setattr(camobject* self, char* name, PyObject* v) +{ + /* XXXX Add your own setattr code here */ + if ( v == NULL ) + { + PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute"); + return -1; + } + + return PyMember_Set((char*)/*XXXX*/0, cam_memberlist, name, v); +} + +static char Camtype__doc__[] = +"" +; + +static PyTypeObject Camtype = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /*ob_size*/ + "Camera", /*tp_name*/ + sizeof(camobject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) cam_dealloc, /*tp_dealloc*/ + (printfunc) cam_print, /*tp_print*/ + (getattrfunc) cam_getattr, /*tp_getattr*/ + (setattrfunc) cam_setattr, /*tp_setattr*/ + (cmpfunc) 0, /*tp_compare*/ + (reprfunc) cam_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + (hashfunc) 0, /*tp_hash*/ + (ternaryfunc) 0, /*tp_call*/ + (reprfunc) cam_str, /*tp_str*/ + + /* Space for future expansion */ + 0L,0L,0L,0L, + Camtype__doc__ /* Documentation string */ +}; + +/********************/ +/* display settings */ +/********************/ + +static struct PyMethodDef dsp_methods[] = { + { NULL, NULL } +}; + +static dspobject* +newdspobject(void) +{ + dspobject* self; + ID* list = NULL; + + self = PyObject_NEW(dspobject, &Dsptype); + if (self == NULL) + { + return NULL; + } + self->startFrame = PyInt_FromLong(1); + self->endFrame = PyInt_FromLong(250); + self->currentFrame = PyInt_FromLong(1); + self->xResolution = PyInt_FromLong(320); + self->yResolution = PyInt_FromLong(256); + self->pixelAspectRatio = PyFloat_FromDouble(1.0); + + return self; +} + +static void +dsp_dealloc(dspobject* self) +{ + dspobject* dsp = (dspobject*) self; + + Py_DECREF(dsp->startFrame); + Py_DECREF(dsp->endFrame); + Py_DECREF(dsp->currentFrame); + Py_DECREF(dsp->xResolution); + Py_DECREF(dsp->yResolution); + Py_DECREF(dsp->pixelAspectRatio); + + PyMem_DEL(self); +} + +static int +dsp_print(dspobject* self, FILE* fp, int flags) +{ + fprintf(fp, "DisplaySettings()\n"); + + return 0; +} + +static PyObject* +dsp_repr(dspobject* self) +{ + PyObject* s; + + s = PyString_FromString("DisplaySettings()()\n"); + + return s; +} + +static PyObject* +dsp_str(dspobject* self) +{ + PyObject* s; + + s = PyString_FromString("DisplaySettings()()\n"); + + return s; +} + +#include "structmember.h" + +static struct memberlist dsp_memberlist[] = { + /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */ + {"startFrame", T_OBJECT, offsetof(dspobject, startFrame), RO}, + {"endFrame", T_OBJECT, offsetof(dspobject, endFrame), RO}, + {"currentFrame", T_OBJECT, offsetof(dspobject, currentFrame), RO}, + {"xResolution", T_OBJECT, offsetof(dspobject, xResolution), RO}, + {"yResolution", T_OBJECT, offsetof(dspobject, yResolution), RO}, + {"pixelAspectRatio", T_OBJECT, offsetof(dspobject, pixelAspectRatio), RO}, + {NULL} +}; + +static PyObject* +dsp_getattr(dspobject* self, char* name) +{ + PyObject* rv; + + /* XXXX Add your own getattr code here */ + rv = PyMember_Get((char*) self, dsp_memberlist, name); + if (rv) + { + return rv; + } + PyErr_Clear(); + + return Py_FindMethod(dsp_methods, (PyObject*)self, name); +} + + +static int +dsp_setattr(dspobject* self, char* name, PyObject* v) +{ + /* XXXX Add your own setattr code here */ + if ( v == NULL ) + { + PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute"); + return -1; + } + + return PyMember_Set((char*)/*XXXX*/0, dsp_memberlist, name, v); +} + +static char Dsptype__doc__[] = +"" +; + +static PyTypeObject Dsptype = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /*ob_size*/ + "DisplaySettings", /*tp_name*/ + sizeof(dspobject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) dsp_dealloc, /*tp_dealloc*/ + (printfunc) dsp_print, /*tp_print*/ + (getattrfunc) dsp_getattr, /*tp_getattr*/ + (setattrfunc) dsp_setattr, /*tp_setattr*/ + (cmpfunc) 0, /*tp_compare*/ + (reprfunc) dsp_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + (hashfunc) 0, /*tp_hash*/ + (ternaryfunc) 0, /*tp_call*/ + (reprfunc) dsp_str, /*tp_str*/ + + /* Space for future expansion */ + 0L,0L,0L,0L, + Dsptype__doc__ /* Documentation string */ +}; + +/********/ +/* Lamp */ +/********/ + +static struct PyMethodDef lmp_methods[] = { + { NULL, NULL } +}; + +static lmpobject* +newlmpobject(char* name) +{ + lmpobject* self; + ID* list = NULL; + + self = PyObject_NEW(lmpobject, &Lmptype); + if (self == NULL) + { + return NULL; + } + strcpy(self->name, name); + self->R = PyFloat_FromDouble(0.8); + self->G = PyFloat_FromDouble(0.8); + self->B = PyFloat_FromDouble(0.8); + + return self; +} + +static void +lmp_dealloc(lmpobject* self) +{ + lmpobject* lmp = (lmpobject*) self; + + Py_DECREF(lmp->R); + Py_DECREF(lmp->G); + Py_DECREF(lmp->B); + + PyMem_DEL(self); +} + +static int +lmp_print(lmpobject* self, FILE* fp, int flags) +{ + fprintf(fp, "Lamp(name = \"%s\")\n", self->name); + + return 0; +} + +static PyObject* +lmp_repr(lmpobject* self) +{ + PyObject* s; + + s = PyString_FromString("Lamp()\n"); + + return s; +} + +static PyObject* +lmp_str(lmpobject* self) +{ + PyObject* s; + + s = PyString_FromString("Lamp()\n"); + + return s; +} + +#include "structmember.h" + +static struct memberlist lmp_memberlist[] = { + /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */ + {"R", T_OBJECT, offsetof(lmpobject, R), RO}, + {"G", T_OBJECT, offsetof(lmpobject, G), RO}, + {"B", T_OBJECT, offsetof(lmpobject, B), RO}, + {NULL} +}; + +static PyObject* +lmp_getattr(lmpobject* self, char* name) +{ + PyObject* rv; + + /* XXXX Add your own getattr code here */ + rv = PyMember_Get((char*) self, lmp_memberlist, name); + if (rv) + { + return rv; + } + PyErr_Clear(); + + return Py_FindMethod(lmp_methods, (PyObject*)self, name); +} + + +static int +lmp_setattr(lmpobject* self, char* name, PyObject* v) +{ + /* XXXX Add your own setattr code here */ + if ( v == NULL ) + { + PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute"); + return -1; + } + + return PyMember_Set((char*)/*XXXX*/0, lmp_memberlist, name, v); +} + +static char Lmptype__doc__[] = +"" +; + +static PyTypeObject Lmptype = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /*ob_size*/ + "Lamp", /*tp_name*/ + sizeof(lmpobject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) lmp_dealloc, /*tp_dealloc*/ + (printfunc) lmp_print, /*tp_print*/ + (getattrfunc) lmp_getattr, /*tp_getattr*/ + (setattrfunc) lmp_setattr, /*tp_setattr*/ + (cmpfunc) 0, /*tp_compare*/ + (reprfunc) lmp_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + (hashfunc) 0, /*tp_hash*/ + (ternaryfunc) 0, /*tp_call*/ + (reprfunc) lmp_str, /*tp_str*/ + + /* Space for future expansion */ + 0L,0L,0L,0L, + Lmptype__doc__ /* Documentation string */ +}; + +/************/ +/* material */ +/************/ + +static struct PyMethodDef mat_methods[] = { + { NULL, NULL } +}; + +static matobject* +newmatobject(char* name) +{ + matobject* self; + ID* list = NULL; + + self = PyObject_NEW(matobject, &Mattype); + if (self == NULL) + { + return NULL; + } + strcpy(self->name, name); + self->R = PyFloat_FromDouble(0.8); + self->G = PyFloat_FromDouble(0.8); + self->B = PyFloat_FromDouble(0.8); + + return self; +} + +static void +mat_dealloc(matobject* self) +{ + matobject* mat = (matobject*) self; + + Py_DECREF(mat->R); + Py_DECREF(mat->G); + Py_DECREF(mat->B); + + PyMem_DEL(self); +} + +static int +mat_print(matobject* self, FILE* fp, int flags) +{ + fprintf(fp, "Material(name = \"%s\")\n", self->name); + + return 0; +} + +static PyObject* +mat_repr(matobject* self) +{ + PyObject* s; + + s = PyString_FromString("Material()\n"); + + return s; +} + +static PyObject* +mat_str(matobject* self) +{ + PyObject* s; + + s = PyString_FromString("Material()\n"); + + return s; +} + +#include "structmember.h" + +static struct memberlist mat_memberlist[] = { + /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */ + {"R", T_OBJECT, offsetof(matobject, R), RO}, + {"G", T_OBJECT, offsetof(matobject, G), RO}, + {"B", T_OBJECT, offsetof(matobject, B), RO}, + {NULL} +}; + +static PyObject* +mat_getattr(matobject* self, char* name) +{ + PyObject* rv; + + /* XXXX Add your own getattr code here */ + rv = PyMember_Get((char*) self, mat_memberlist, name); + if (rv) + { + return rv; + } + PyErr_Clear(); + + return Py_FindMethod(mat_methods, (PyObject*)self, name); +} + + +static int +mat_setattr(matobject* self, char* name, PyObject* v) +{ + /* XXXX Add your own setattr code here */ + if ( v == NULL ) + { + PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute"); + return -1; + } + + return PyMember_Set((char*)/*XXXX*/0, mat_memberlist, name, v); +} + +static char Mattype__doc__[] = +"" +; + +static PyTypeObject Mattype = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /*ob_size*/ + "Material", /*tp_name*/ + sizeof(matobject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) mat_dealloc, /*tp_dealloc*/ + (printfunc) mat_print, /*tp_print*/ + (getattrfunc) mat_getattr, /*tp_getattr*/ + (setattrfunc) mat_setattr, /*tp_setattr*/ + (cmpfunc) 0, /*tp_compare*/ + (reprfunc) mat_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + (hashfunc) 0, /*tp_hash*/ + (ternaryfunc) 0, /*tp_call*/ + (reprfunc) mat_str, /*tp_str*/ + + /* Space for future expansion */ + 0L,0L,0L,0L, + Mattype__doc__ /* Documentation string */ +}; + +/********/ +/* mesh */ +/********/ + +static char msh_addFace__doc__[] = +"addFace(self, i1, i2, i3, i4, isSmooth, matIndex)" +; + +static PyObject* +msh_addFace(mshobject* self, PyObject* args) +{ + int index; + int i1, i2, i3, i4; + int isSmooth, matIndex; + PyObject* item = NULL; + + if (!PyArg_ParseTuple(args, "iiiiii", &i1, &i2, &i3, &i4, + &isSmooth, &matIndex)) + { + return NULL; + } + item = PyList_New(6); + PyList_SetItem(item, 0, PyInt_FromLong(i1)); + PyList_SetItem(item, 1, PyInt_FromLong(i2)); + PyList_SetItem(item, 2, PyInt_FromLong(i3)); + PyList_SetItem(item, 3, PyInt_FromLong(i4)); + PyList_SetItem(item, 4, PyInt_FromLong(isSmooth)); + PyList_SetItem(item, 5, PyInt_FromLong(matIndex)); + PyList_Append(self->faces, item); + index = PyList_Size(self->faces) - 1; + + return PyInt_FromLong(index); +} + +static char msh_addTexCoords__doc__[] = +"addTexCoords(self, coords)" +; + +static PyObject* +msh_addTexCoords(mshobject* self, PyObject* args) +{ + float u, v; + PyObject* item = NULL; + + if (!PyArg_ParseTuple(args, "ff", + &u, &v)) + { + return NULL; + } + if (u < 0.0) + { + u = 0.0; + } + if (u > 1.0) + { + u = 1.0; + } + if (v < 0.0) + { + v = 0.0; + } + if (v > 1.0) + { + v = 1.0; + } + item = PyList_New(2); + PyList_SetItem(item, 0, PyFloat_FromDouble(u)); + PyList_SetItem(item, 1, PyFloat_FromDouble(v)); + PyList_Append(self->texcoords, item); + + Py_INCREF(Py_None); + return Py_None; +} + +static char msh_addTexture__doc__[] = +"addTexture(self, filename)" +; + +static PyObject* +msh_addTexture(mshobject* self, PyObject* args) +{ + char* filename = NULL; + + if (!PyArg_ParseTuple(args, "s", &filename)) + { + return NULL; + } + self->texture = PyString_FromString(filename); + + Py_INCREF(Py_None); + return Py_None; +} + +static char msh_addVertex__doc__[] = +"addVertex(self, x, y, z, nx, ny, nz, r = -1.0, g = 0.0, b = 0.0)" +; + +static PyObject* +msh_addVertex(mshobject* self, PyObject* args) +{ + int index; + float x, y, z, nx, ny, nz; + float r = -1.0, g = 0.0, b = 0.0; + PyObject* item1 = NULL; + PyObject* item2 = NULL; + PyObject* item3 = NULL; + + if (!PyArg_ParseTuple(args, "ffffff|fff", &x, &y, &z, &nx, &ny, &nz, + &r, &g, &b)) + { + return NULL; + } + item1 = PyList_New(3); + item2 = PyList_New(3); + if (r != -1.0) + { + item3 = PyList_New(3); + } + PyList_SetItem(item1, 0, PyFloat_FromDouble(x)); + PyList_SetItem(item1, 1, PyFloat_FromDouble(y)); + PyList_SetItem(item1, 2, PyFloat_FromDouble(z)); + PyList_SetItem(item2, 0, PyFloat_FromDouble(nx)); + PyList_SetItem(item2, 1, PyFloat_FromDouble(ny)); + PyList_SetItem(item2, 2, PyFloat_FromDouble(nz)); + if (r != -1.0) + { + PyList_SetItem(item3, 0, PyFloat_FromDouble(r)); + PyList_SetItem(item3, 1, PyFloat_FromDouble(g)); + PyList_SetItem(item3, 2, PyFloat_FromDouble(b)); + } + PyList_Append(self->vertices, item1); + PyList_Append(self->normals, item2); + if (r != -1.0) + { + PyList_Append(self->colors, item3); + } + index = PyList_Size(self->vertices) - 1; + + return PyInt_FromLong(index); +} + +static struct PyMethodDef msh_methods[] = { + {"addFace", (PyCFunction)msh_addFace, + METH_VARARGS, msh_addFace__doc__}, + {"addTexCoords", (PyCFunction)msh_addTexCoords, + METH_VARARGS, msh_addTexCoords__doc__}, + {"addTexture", (PyCFunction)msh_addTexture, + METH_VARARGS, msh_addTexture__doc__}, + {"addVertex", (PyCFunction)msh_addVertex, + METH_VARARGS, msh_addVertex__doc__}, + + { NULL, NULL } +}; + +static mshobject* +newmshobject(char* name) +{ + mshobject* self; + ID* list = NULL; + + self = PyObject_NEW(mshobject, &Mshtype); + if (self == NULL) + { + return NULL; + } + strcpy(self->name, name); + self->vertices = PyList_New(0); + self->normals = PyList_New(0); + self->colors = PyList_New(0); + self->faces = PyList_New(0); + self->texcoords = PyList_New(0); + Py_INCREF(Py_None); + self->texture = Py_None; + + return self; +} + +static void +msh_dealloc(mshobject* self) +{ + mshobject* msh = (mshobject*) self; + + Py_DECREF(msh->vertices); + Py_DECREF(msh->normals); + Py_DECREF(msh->colors); + Py_DECREF(msh->faces); + Py_DECREF(msh->texture); + Py_DECREF(msh->texcoords); + + PyMem_DEL(self); +} + +static int +msh_print(mshobject* self, FILE* fp, int flags) +{ + fprintf(fp, "Mesh(name = \"%s\",\n", self->name); + fprintf(fp, " vertices = %d,\n", PyList_Size(self->vertices)); + fprintf(fp, " faces = %d)\n", PyList_Size(self->faces)); + + return 0; +} + +static PyObject* +msh_repr(mshobject* self) +{ + PyObject* s; + + s = PyString_FromString("Mesh()\n"); + + return s; +} + +static PyObject* +msh_str(mshobject* self) +{ + PyObject* s; + + s = PyString_FromString("Mesh()\n"); + + return s; +} + +#include "structmember.h" + +static struct memberlist msh_memberlist[] = { + /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */ + {"vertices", T_OBJECT, offsetof(mshobject, vertices), RO}, + {"normals", T_OBJECT, offsetof(mshobject, normals), RO}, + {"colors", T_OBJECT, offsetof(mshobject, colors), RO}, + {"faces", T_OBJECT, offsetof(mshobject, faces), RO}, + {"texture", T_OBJECT, offsetof(mshobject, texture), RO}, + {"texcoords", T_OBJECT, offsetof(mshobject, texcoords), RO}, + {NULL} +}; + +static PyObject* +msh_getattr(mshobject* self, char* name) +{ + PyObject* rv; + + /* XXXX Add your own getattr code here */ + rv = PyMember_Get((char*) self, msh_memberlist, name); + if (rv) + { + return rv; + } + PyErr_Clear(); + + return Py_FindMethod(msh_methods, (PyObject*)self, name); +} + + +static int +msh_setattr(mshobject* self, char* name, PyObject* v) +{ + /* XXXX Add your own setattr code here */ + if ( v == NULL ) + { + PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute"); + return -1; + } + + return PyMember_Set((char*)/*XXXX*/0, msh_memberlist, name, v); +} + +static char Mshtype__doc__[] = +"" +; + +static PyTypeObject Mshtype = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /*ob_size*/ + "Mesh", /*tp_name*/ + sizeof(mshobject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) msh_dealloc, /*tp_dealloc*/ + (printfunc) msh_print, /*tp_print*/ + (getattrfunc) msh_getattr, /*tp_getattr*/ + (setattrfunc) msh_setattr, /*tp_setattr*/ + (cmpfunc) 0, /*tp_compare*/ + (reprfunc) msh_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + (hashfunc) 0, /*tp_hash*/ + (ternaryfunc) 0, /*tp_call*/ + (reprfunc) msh_str, /*tp_str*/ + + /* Space for future expansion */ + 0L,0L,0L,0L, + Mshtype__doc__ /* Documentation string */ +}; + +/**********/ +/* object */ +/**********/ + +static struct PyMethodDef obj_methods[] = { + + { NULL, NULL } +}; + +static objobject* +newobjobject(char* name) +{ + objobject* self = NULL; + PyObject* row1 = NULL; + PyObject* row2 = NULL; + PyObject* row3 = NULL; + PyObject* row4 = NULL; + + self = PyObject_NEW(objobject, &Objtype); + if (self == NULL) + { + return NULL; + } + strcpy(self->name, name); + self->matrix = PyList_New(4); + row1 = PyList_New(4); + row2 = PyList_New(4); + row3 = PyList_New(4); + row4 = PyList_New(4); + PyList_SetItem(row1, 0, PyInt_FromLong(1)); + PyList_SetItem(row1, 1, PyInt_FromLong(0)); + PyList_SetItem(row1, 2, PyInt_FromLong(0)); + PyList_SetItem(row1, 3, PyInt_FromLong(0)); + PyList_SetItem(row2, 0, PyInt_FromLong(0)); + PyList_SetItem(row2, 1, PyInt_FromLong(1)); + PyList_SetItem(row2, 2, PyInt_FromLong(0)); + PyList_SetItem(row2, 3, PyInt_FromLong(0)); + PyList_SetItem(row3, 0, PyInt_FromLong(0)); + PyList_SetItem(row3, 1, PyInt_FromLong(0)); + PyList_SetItem(row3, 2, PyInt_FromLong(1)); + PyList_SetItem(row3, 3, PyInt_FromLong(0)); + PyList_SetItem(row4, 0, PyInt_FromLong(0)); + PyList_SetItem(row4, 1, PyInt_FromLong(0)); + PyList_SetItem(row4, 2, PyInt_FromLong(0)); + PyList_SetItem(row4, 3, PyInt_FromLong(1)); + PyList_SetItem(self->matrix, 0, row1); + PyList_SetItem(self->matrix, 1, row2); + PyList_SetItem(self->matrix, 2, row3); + PyList_SetItem(self->matrix, 3, row4); + self->inverseMatrix = PyList_New(4); + row1 = PyList_New(4); + row2 = PyList_New(4); + row3 = PyList_New(4); + row4 = PyList_New(4); + PyList_SetItem(row1, 0, PyInt_FromLong(1)); + PyList_SetItem(row1, 1, PyInt_FromLong(0)); + PyList_SetItem(row1, 2, PyInt_FromLong(0)); + PyList_SetItem(row1, 3, PyInt_FromLong(0)); + PyList_SetItem(row2, 0, PyInt_FromLong(0)); + PyList_SetItem(row2, 1, PyInt_FromLong(1)); + PyList_SetItem(row2, 2, PyInt_FromLong(0)); + PyList_SetItem(row2, 3, PyInt_FromLong(0)); + PyList_SetItem(row3, 0, PyInt_FromLong(0)); + PyList_SetItem(row3, 1, PyInt_FromLong(0)); + PyList_SetItem(row3, 2, PyInt_FromLong(1)); + PyList_SetItem(row3, 3, PyInt_FromLong(0)); + PyList_SetItem(row4, 0, PyInt_FromLong(0)); + PyList_SetItem(row4, 1, PyInt_FromLong(0)); + PyList_SetItem(row4, 2, PyInt_FromLong(0)); + PyList_SetItem(row4, 3, PyInt_FromLong(1)); + PyList_SetItem(self->inverseMatrix, 0, row1); + PyList_SetItem(self->inverseMatrix, 1, row2); + PyList_SetItem(self->inverseMatrix, 2, row3); + PyList_SetItem(self->inverseMatrix, 3, row4); + self->materials = PyList_New(0); + Py_INCREF(Py_None); + self->data = Py_None; + Py_INCREF(Py_None); + self->type = Py_None; + + return self; +} + +static void +obj_dealloc(objobject* self) +{ + objobject* obj = (objobject*) self; + + Py_DECREF(obj->matrix); + Py_DECREF(obj->inverseMatrix); + Py_DECREF(obj->materials); + Py_DECREF(obj->data); + Py_DECREF(obj->type); + + PyMem_DEL(self); +} + +static int +obj_print(objobject* self, FILE* fp, int flags) +{ + fprintf(fp, "Object(name = \"%s\",\n", self->name); +/* fprintf(fp, " matrix = %s,\n", */ +/* PyString_AsString(mtx_repr((mtxobject*) self->matrix))); */ + if (self->type == Py_None) + { + fprintf(fp, " data = None)\n"); + } + else + { + fprintf(fp, " data = %s(\"%s\"))\n", + PyString_AsString(self->type), + PyString_AsString(self->data)); + } + + return 0; +} + +static PyObject* +obj_repr(objobject* self) +{ + PyObject* s; + + s = PyString_FromString("Object()\n"); + + return s; +} + +static PyObject* +obj_str(objobject* self) +{ + PyObject* s; + + s = PyString_FromString("Object()\n"); + + return s; +} + +#include "structmember.h" + +static struct memberlist obj_memberlist[] = { + /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */ + {"data", T_OBJECT, offsetof(objobject, data), RO}, + {"matrix", T_OBJECT, offsetof(objobject, matrix), RO}, + {"inverseMatrix", T_OBJECT, offsetof(objobject, inverseMatrix), RO}, + {"materials", T_OBJECT, offsetof(objobject, materials), RO}, + {"type", T_OBJECT, offsetof(objobject, type), RO}, + {NULL} +}; + +static PyObject* +obj_getattr(objobject* self, char* name) +{ + PyObject* rv; + + /* XXXX Add your own getattr code here */ + rv = PyMember_Get((char*) self, obj_memberlist, name); + if (rv) + { + return rv; + } + PyErr_Clear(); + + return Py_FindMethod(obj_methods, (PyObject*)self, name); +} + + +static int +obj_setattr(objobject* self, char* name, PyObject* v) +{ + /* XXXX Add your own setattr code here */ + if ( v == NULL ) + { + PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute"); + return -1; + } + + return PyMember_Set((char*)/*XXXX*/0, obj_memberlist, name, v); +} + +static char Objtype__doc__[] = +"" +; + +static PyTypeObject Objtype = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /*ob_size*/ + "Object", /*tp_name*/ + sizeof(objobject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) obj_dealloc, /*tp_dealloc*/ + (printfunc) obj_print, /*tp_print*/ + (getattrfunc) obj_getattr, /*tp_getattr*/ + (setattrfunc) obj_setattr, /*tp_setattr*/ + (cmpfunc) 0, /*tp_compare*/ + (reprfunc) obj_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + (hashfunc) 0, /*tp_hash*/ + (ternaryfunc) 0, /*tp_call*/ + (reprfunc) obj_str, /*tp_str*/ + + /* Space for future expansion */ + 0L,0L,0L,0L, + Objtype__doc__ /* Documentation string */ +}; + +/*********/ +/* scene */ +/*********/ + +static char sce_addObject__doc__[] = +"addObject(self, object)" +; + +static PyObject* +sce_addObject(sceobject* self, PyObject* args) +{ + int index; + PyObject* object = NULL; + + if (!PyArg_ParseTuple(args, "O", &object)) + { + return NULL; + } + PyList_Append(self->objects, object); + index = PyList_Size(self->objects) - 1; + + return PyInt_FromLong(index); +} + +static char sce_getCurrentCamera__doc__[] = +"getCurrentCamera(self)" +; + +static PyObject* +sce_getCurrentCamera(sceobject* self, PyObject* args) +{ + char* name = NULL; + PyObject* camera = NULL; + + if (!PyArg_ParseTuple(args, "")) + { + return NULL; + } + if (G.scene->camera) + { + name = G.scene->camera->id.name+2; + camera = blend_getObject(NULL, + Py_BuildValue("(O)", + PyString_FromString(name))); + + return camera; + } + else + { + Py_INCREF(Py_None); + return Py_None; + } +} + +static struct PyMethodDef sce_methods[] = { + {"addObject", (PyCFunction)sce_addObject, + METH_VARARGS, sce_addObject__doc__}, + {"getCurrentCamera", (PyCFunction)sce_getCurrentCamera, + METH_VARARGS, sce_getCurrentCamera__doc__}, + + { NULL, NULL } +}; + +static sceobject* +newsceobject(char* name) +{ + sceobject* self; + + self = PyObject_NEW(sceobject, &Scetype); + if (self == NULL) + { + return NULL; + } + strcpy(self->name, name); + self->objects = PyList_New(0); + + return self; +} + +static void +sce_dealloc(sceobject* self) +{ + sceobject* sce = (sceobject*) self; + + Py_DECREF(sce->objects); + + PyMem_DEL(self); +} + +static int +sce_print(sceobject* self, FILE* fp, int flags) +{ + fprintf(fp, "Scene(name = \"%s\",\n", self->name); + fprintf(fp, " objects = %d)\n", PyList_Size(self->objects)); + + return 0; +} + +static PyObject* +sce_repr(sceobject* self) +{ + PyObject* s; + + s = PyString_FromString("Scene()\n"); + + return s; +} + +static PyObject* +sce_str(sceobject* self) +{ + PyObject* s; + + s = PyString_FromString("Scene()\n"); + + return s; +} + +#include "structmember.h" + +static struct memberlist sce_memberlist[] = { + /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */ + {"objects", T_OBJECT, offsetof(sceobject, objects), RO}, + {NULL} +}; + +static PyObject* +sce_getattr(sceobject* self, char* name) +{ + PyObject* rv; + + /* XXXX Add your own getattr code here */ + rv = PyMember_Get((char*) self, sce_memberlist, name); + if (rv) + { + return rv; + } + PyErr_Clear(); + + return Py_FindMethod(sce_methods, (PyObject*)self, name); +} + + +static int +sce_setattr(sceobject* self, char* name, PyObject* v) +{ + /* XXXX Add your own setattr code here */ + if ( v == NULL ) + { + PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute"); + return -1; + } + + return PyMember_Set((char*)/*XXXX*/0, sce_memberlist, name, v); +} + +static char Scetype__doc__[] = +"" +; + +static PyTypeObject Scetype = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /*ob_size*/ + "Scene", /*tp_name*/ + sizeof(sceobject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) sce_dealloc, /*tp_dealloc*/ + (printfunc) sce_print, /*tp_print*/ + (getattrfunc) sce_getattr, /*tp_getattr*/ + (setattrfunc) sce_setattr, /*tp_setattr*/ + (cmpfunc) 0, /*tp_compare*/ + (reprfunc) sce_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + (hashfunc) 0, /*tp_hash*/ + (ternaryfunc) 0, /*tp_call*/ + (reprfunc) sce_str, /*tp_str*/ + + /* Space for future expansion */ + 0L,0L,0L,0L, + Scetype__doc__ /* Documentation string */ +}; + +static char blend_Mesh__doc__[] = +"Creates an (empty) instance of a Blender mesh.\n\ + E.g.: \"m = Blender.Mesh('Plane')\"\n\ + To create faces first add vertices with \n\ + \"i1 = m.addVertex(x, y, z, nx, ny, nz, r = -1.0, r = 0.0, b = 0.0)\"\n\ + then create faces with \n\ + \"index = m.addFace(i1, i2, i3, i4, isSmooth, matIndex)\".\ +" +; + +static PyObject* +blend_Mesh(PyObject* self, PyObject* args) +{ + if (!PyArg_ParseTuple(args, "")) + { + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static char blend_Object__doc__[] = +"Creates an instance of a Blender object" +; + +static PyObject* +blend_Object(PyObject* self, PyObject* args) +{ + char* name = NULL; + + if (!PyArg_ParseTuple(args, "s", &name)) + { + return NULL; + } + + return ((PyObject*) newobjobject(name)); +} + +static char blend_Scene__doc__[] = +"Creates an instance of a Blender scene" +; + +static PyObject* +blend_Scene(PyObject* self, PyObject* args) +{ + char* name = NULL; + + if (!PyArg_ParseTuple(args, "s", &name)) + { + return NULL; + } + + return ((PyObject*) newsceobject(name)); +} + +static char blend_addMesh__doc__[] = +"Blender.addMesh(type, sceneName)\n\ + where type is one of [\"Plane\"]" +; + +static PyObject* +blend_addMesh(PyObject* self, PyObject* args) +{ + char* type = NULL; + char* sceneName = NULL; + PyObject* tuple = NULL; + PyObject* object = NULL; + PyObject* mesh = NULL; + PyObject* index = NULL; + PyObject* indices = NULL; + objobject* obj = NULL; + mshobject* msh = NULL; + + if (!PyArg_ParseTuple(args, "ss", &type, &sceneName)) + { + return NULL; + } + + if (strcmp(type, "Plane") == 0) + { + obj = newobjobject(type); + msh = newmshobject(type); + object = (PyObject*) obj; + mesh = (PyObject*) msh; + indices = PyList_New(6); + /* vertices */ + index = msh_addVertex((mshobject*) mesh, + Py_BuildValue("ffffff", + 1.0, 1.0, 0.0, 0.0, 0.0, 1.0)); + PyList_SetItem(indices, 0, index); + index = msh_addVertex((mshobject*) mesh, + Py_BuildValue("ffffff", + 1.0, -1.0, 0.0, 0.0, 0.0, 1.0)); + PyList_SetItem(indices, 1, index); + index = msh_addVertex((mshobject*) mesh, + Py_BuildValue("ffffff", + -1.0, -1.0, 0.0, 0.0, 0.0, 1.0)); + PyList_SetItem(indices, 2, index); + index = msh_addVertex((mshobject*) mesh, + Py_BuildValue("ffffff", + -1.0, 1.0, 0.0, 0.0, 0.0, 1.0)); + PyList_SetItem(indices, 3, index); + PyList_SetItem(indices, 4, PyInt_FromLong(0)); /* smooth flag */ + PyList_SetItem(indices, 5, PyInt_FromLong(0)); /* material index */ + /* faces */ + msh_addFace((mshobject*) mesh, + Py_BuildValue("OOOOOO", + PyList_GetItem(indices, 0), + PyList_GetItem(indices, 3), + PyList_GetItem(indices, 2), + PyList_GetItem(indices, 1), + PyList_GetItem(indices, 4), + PyList_GetItem(indices, 5))); + /* connection */ + blend_connect(self, Py_BuildValue("OO", + PyString_FromString(obj->name), + PyString_FromString(msh->name))); + blend_connect(self, Py_BuildValue("OO", + PyString_FromString(sceneName), + PyString_FromString(obj->name))); + /* return value */ + tuple = PyTuple_New(2); + PyTuple_SetItem(tuple, 0, object); + PyTuple_SetItem(tuple, 1, mesh); + + return tuple; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static char blend_connect__doc__[] = +"connect(obj1, obj2)" +; + +static PyObject* +blend_connect(PyObject* self, PyObject* args) +{ + PyObject* obj1 = NULL; + PyObject* obj2 = NULL; + + if (!PyArg_ParseTuple(args, "OO", &obj1, &obj2)) + { + return NULL; + } + if (obj1->ob_type == &Objtype) + { + if (obj2->ob_type == &Mshtype) + { + Py_INCREF(obj2); + ((objobject*) obj1)->data = obj2; + ((objobject*) obj1)->type = PyString_FromString("Mesh"); + } + } + else if (obj1->ob_type == &Scetype) + { + if (obj2->ob_type == &Objtype) + { + sce_addObject((sceobject*) obj1, Py_BuildValue("(O)", obj2)); + } + } + + Py_INCREF(Py_None); + return Py_None; +} + +static char blend_getCamera__doc__[] = +"getCamera()" +; + +static PyObject* +blend_getCamera(PyObject* self, PyObject* args) +{ + char* name = NULL; + ID* list = NULL; + Camera* cam = NULL; + camobject* camera = NULL; + + if (!PyArg_ParseTuple(args, "s", &name)) + { + return NULL; + } + list = find_name_in_list((ID*) G.main->camera.first, name); + if (list) + { + cam = (Camera*) list; + camera = newcamobject(cam->id.name+2); + camera->Lens = PyFloat_FromDouble(cam->lens); + camera->ClSta = PyFloat_FromDouble(cam->clipsta); + camera->ClEnd = PyFloat_FromDouble(cam->clipend); + + return (PyObject*) camera; + } + else + { + Py_INCREF(Py_None); + return Py_None; + } +} + +static char blend_getCurrentScene__doc__[] = +"getCurrentScene()" +; + +static PyObject* +blend_getCurrentScene(PyObject* self, PyObject* args) +{ + char* name = NULL; + sceobject* scene = NULL; + Base* base = NULL; + Object* obj = NULL; + + if (!PyArg_ParseTuple(args, "")) + { + return NULL; + } + + /* create scene in Python */ + name = G.scene->id.name+2; + scene = newsceobject(name); + + /* add existing objects */ + base = G.scene->base.first; + while (base) + { + obj = base->object; + PyList_Append(scene->objects, PyString_FromString(obj->id.name+2)); + base = base->next; + } + + return (PyObject*) scene; +} + +static char blend_getDisplaySettings__doc__[] = +"getDisplaySettings()" +; + +static PyObject* +blend_getDisplaySettings(PyObject* self, PyObject* args) +{ + RenderData* rd = NULL; + dspobject* displayObject = NULL; + + if (!PyArg_ParseTuple(args, "")) + { + return NULL; + } + rd = &(G.scene->r); + displayObject = newdspobject(); + displayObject->startFrame = PyInt_FromLong(rd->sfra); + displayObject->endFrame = PyInt_FromLong(rd->efra); + displayObject->currentFrame = PyInt_FromLong(rd->cfra); + displayObject->xResolution = PyInt_FromLong(rd->xsch); + displayObject->yResolution = PyInt_FromLong(rd->ysch); + displayObject->pixelAspectRatio = PyInt_FromLong(rd->yasp / + (1.0 * rd->xasp)); + + return (PyObject*) displayObject; +} + +static char blend_getLamp__doc__[] = +"getLamp(name)" +; + +static PyObject* +blend_getLamp(PyObject* self, PyObject* args) +{ + char* name = NULL; + ID* list = NULL; + Lamp* lmp = NULL; + lmpobject* lamp = NULL; + + if (!PyArg_ParseTuple(args, "s", &name)) + { + return NULL; + } + list = find_name_in_list((ID*) G.main->lamp.first, name); + if (list) + { + lmp = (Lamp*) list; + lamp = newlmpobject(lmp->id.name+2); + lamp->R = PyFloat_FromDouble(lmp->r); + lamp->G = PyFloat_FromDouble(lmp->g); + lamp->B = PyFloat_FromDouble(lmp->b); +/* lamp->Dist = PyFloat_FromDouble(lmp->dist); */ +/* lamp->SpoSi = PyFloat_FromDouble(lmp->spotsize); */ +/* lamp->SpoBl = PyFloat_FromDouble(lmp->spotblend); */ +/* lamp->Quad1 = PyFloat_FromDouble(lmp->att1); */ +/* lamp->Quad2 = PyFloat_FromDouble(lmp->att2); */ +/* lamp->HaInt = PyFloat_FromDouble(lmp->haint); */ + +/* lamp->OfsX = PyFloat_FromDouble(lmp->); */ +/* lamp->OfsY = PyFloat_FromDouble(lmp->); */ +/* lamp->OfsZ = PyFloat_FromDouble(lmp->); */ +/* lamp->SizeX = PyFloat_FromDouble(lmp->); */ +/* lamp->SizeY = PyFloat_FromDouble(lmp->); */ +/* lamp->SizeZ = PyFloat_FromDouble(lmp->); */ +/* lamp->texR = PyFloat_FromDouble(lmp->); */ +/* lamp->texG = PyFloat_FromDouble(lmp->); */ +/* lamp->texB = PyFloat_FromDouble(lmp->); */ +/* lamp->DefVar = PyFloat_FromDouble(lmp->); */ +/* lamp->Col = PyFloat_FromDouble(lmp->); */ +/* lamp->Nor = PyFloat_FromDouble(lmp->); */ +/* lamp->Var = PyFloat_FromDouble(lmp->); */ + + return (PyObject*) lamp; + } + else + { + Py_INCREF(Py_None); + return Py_None; + } +} + +static char blend_getMaterial__doc__[] = +"getMaterial(name)" +; + +static PyObject* +blend_getMaterial(PyObject* self, PyObject* args) +{ + char* name = NULL; + ID* list = NULL; + Material* mat = NULL; + matobject* material = NULL; + + if (!PyArg_ParseTuple(args, "s", &name)) + { + return NULL; + } + list = find_name_in_list((ID*) G.main->mat.first, name); + if (list) + { + mat = (Material*) list; + material = newmatobject(mat->id.name+2); + material->R = PyFloat_FromDouble(mat->r); + material->G = PyFloat_FromDouble(mat->g); + material->B = PyFloat_FromDouble(mat->b); + + return (PyObject*) material; + } + else + { + Py_INCREF(Py_None); + return Py_None; + } +} + +static char blend_getMesh__doc__[] = +"getMesh(name)" +; + +static PyObject* +blend_getMesh(PyObject* self, PyObject* args) +{ + int i; + float r, g, b; + char dummy[] = ""; + char* name = NULL; + char* filename = NULL; + uint* mcol = NULL; + ID* list = NULL; + Mesh* msh = NULL; + mshobject* mesh = NULL; + MFace* mface = NULL; + TFace* tface = NULL; + + if (!PyArg_ParseTuple(args, "s", &name)) + { + return NULL; + } + list = find_name_in_list((ID*) G.main->mesh.first, name); + if (list) + { + msh = (Mesh*) list; + mesh = newmshobject(msh->id.name+2); + /* is there color information? */ + if (msh->mcol) + { + mcol = mcol_to_vcol(msh); + } + /* add vertices */ + for (i = 0; i < msh->totvert; i++) + { + if (msh->mcol && mcol) + { + mcol_to_rgb(*mcol, &r, &g, &b); + msh_addVertex(mesh, + Py_BuildValue("fffffffff", + msh->mvert[i].co[0], + msh->mvert[i].co[1], + msh->mvert[i].co[2], + msh->mvert[i].no[0] / 32767.0, + msh->mvert[i].no[1] / 32767.0, + msh->mvert[i].no[2] / 32767.0, + r, g, b)); + mcol++; + } + else + { + msh_addVertex(mesh, + Py_BuildValue("ffffff", + msh->mvert[i].co[0], + msh->mvert[i].co[1], + msh->mvert[i].co[2], + msh->mvert[i].no[0] / 32767.0, + msh->mvert[i].no[1] / 32767.0, + msh->mvert[i].no[2] / 32767.0)); + } + } + /* add faces */ + for (i = 0; i < msh->totface; i++) + { + mface = ((MFace*) msh->mface)+i; + msh_addFace(mesh, + Py_BuildValue("iiiiii", + mface->v1, mface->v2, + mface->v3, mface->v4, + mface->flag, mface->mat_nr)); + } + /* add texture coordinates */ + if (msh->tface) + { + tface = (TFace*) msh->tface; + if (tface->tpage) + { + filename = ((Image*) tface->tpage)->name; + } + else + { + filename = dummy; + } + msh_addTexture(mesh, + Py_BuildValue("(O)", PyString_FromString(filename))); + for (i = 0; i < msh->totface; i++) + { + tface = (TFace*) msh->tface+i; + msh_addTexCoords(mesh, + Py_BuildValue("ff", + tface->uv[0][0], + tface->uv[0][1])); + msh_addTexCoords(mesh, + Py_BuildValue("ff", + tface->uv[1][0], + tface->uv[1][1])); + msh_addTexCoords(mesh, + Py_BuildValue("ff", + tface->uv[2][0], + tface->uv[2][1])); + msh_addTexCoords(mesh, + Py_BuildValue("ff", + tface->uv[3][0], + tface->uv[3][1])); + } + } + + return (PyObject*) mesh; + } + else + { + Py_INCREF(Py_None); + return Py_None; + } +} + +static char blend_getObject__doc__[] = +"getObject(name)" +; + +static PyObject* +blend_getObject(PyObject* self, PyObject* args) +{ + int i; + float inverse[4][4]; + char* name = NULL; + ID* list = NULL; + Object* obj = NULL; + Mesh* msh = NULL; + objobject* object = NULL; + PyObject* row1 = NULL; + PyObject* row2 = NULL; + PyObject* row3 = NULL; + PyObject* row4 = NULL; + + if (!PyArg_ParseTuple(args, "s", &name)) + { + return NULL; + } + list = find_name_in_list((ID*) G.main->object.first, name); + if (list) + { + obj = (Object*) list; + object = newobjobject(obj->id.name+2); + Py_DECREF(object->matrix); + object->matrix = PyList_New(4); + row1 = PyList_New(4); + row2 = PyList_New(4); + row3 = PyList_New(4); + row4 = PyList_New(4); + PyList_SetItem(row1, 0, PyFloat_FromDouble(obj->obmat[0][0])); + PyList_SetItem(row1, 1, PyFloat_FromDouble(obj->obmat[0][1])); + PyList_SetItem(row1, 2, PyFloat_FromDouble(obj->obmat[0][2])); + PyList_SetItem(row1, 3, PyFloat_FromDouble(obj->obmat[0][3])); + PyList_SetItem(row2, 0, PyFloat_FromDouble(obj->obmat[1][0])); + PyList_SetItem(row2, 1, PyFloat_FromDouble(obj->obmat[1][1])); + PyList_SetItem(row2, 2, PyFloat_FromDouble(obj->obmat[1][2])); + PyList_SetItem(row2, 3, PyFloat_FromDouble(obj->obmat[1][3])); + PyList_SetItem(row3, 0, PyFloat_FromDouble(obj->obmat[2][0])); + PyList_SetItem(row3, 1, PyFloat_FromDouble(obj->obmat[2][1])); + PyList_SetItem(row3, 2, PyFloat_FromDouble(obj->obmat[2][2])); + PyList_SetItem(row3, 3, PyFloat_FromDouble(obj->obmat[2][3])); + PyList_SetItem(row4, 0, PyFloat_FromDouble(obj->obmat[3][0])); + PyList_SetItem(row4, 1, PyFloat_FromDouble(obj->obmat[3][1])); + PyList_SetItem(row4, 2, PyFloat_FromDouble(obj->obmat[3][2])); + PyList_SetItem(row4, 3, PyFloat_FromDouble(obj->obmat[3][3])); + PyList_SetItem(object->matrix, 0, row1); + PyList_SetItem(object->matrix, 1, row2); + PyList_SetItem(object->matrix, 2, row3); + PyList_SetItem(object->matrix, 3, row4); + /* inverse matrix */ + Mat4Invert(inverse, obj->obmat); + Py_DECREF(object->inverseMatrix); + object->inverseMatrix = PyList_New(4); + row1 = PyList_New(4); + row2 = PyList_New(4); + row3 = PyList_New(4); + row4 = PyList_New(4); + PyList_SetItem(row1, 0, PyFloat_FromDouble(inverse[0][0])); + PyList_SetItem(row1, 1, PyFloat_FromDouble(inverse[0][1])); + PyList_SetItem(row1, 2, PyFloat_FromDouble(inverse[0][2])); + PyList_SetItem(row1, 3, PyFloat_FromDouble(inverse[0][3])); + PyList_SetItem(row2, 0, PyFloat_FromDouble(inverse[1][0])); + PyList_SetItem(row2, 1, PyFloat_FromDouble(inverse[1][1])); + PyList_SetItem(row2, 2, PyFloat_FromDouble(inverse[1][2])); + PyList_SetItem(row2, 3, PyFloat_FromDouble(inverse[1][3])); + PyList_SetItem(row3, 0, PyFloat_FromDouble(inverse[2][0])); + PyList_SetItem(row3, 1, PyFloat_FromDouble(inverse[2][1])); + PyList_SetItem(row3, 2, PyFloat_FromDouble(inverse[2][2])); + PyList_SetItem(row3, 3, PyFloat_FromDouble(inverse[2][3])); + PyList_SetItem(row4, 0, PyFloat_FromDouble(inverse[3][0])); + PyList_SetItem(row4, 1, PyFloat_FromDouble(inverse[3][1])); + PyList_SetItem(row4, 2, PyFloat_FromDouble(inverse[3][2])); + PyList_SetItem(row4, 3, PyFloat_FromDouble(inverse[3][3])); + PyList_SetItem(object->inverseMatrix, 0, row1); + PyList_SetItem(object->inverseMatrix, 1, row2); + PyList_SetItem(object->inverseMatrix, 2, row3); + PyList_SetItem(object->inverseMatrix, 3, row4); + Py_DECREF(object->materials); + object->materials = PyList_New(obj->totcol); + for (i = 0; i < obj->totcol; i++) + { + if (obj->mat[i]) + { + PyList_SetItem(object->materials, i, + PyString_FromString(obj->mat[i]->id.name+2)); + } + else + { + Py_INCREF(Py_None); + PyList_SetItem(object->materials, i, Py_None); + } + } /* check type */ + switch (obj->type) + { + case OB_EMPTY: + printf("Empty\n"); + break; + case OB_MESH: + object->data = PyString_FromString(((Mesh*) obj->data)->id.name+2); + object->type = PyString_FromString("Mesh"); + msh = (Mesh*) obj->data; + for (i = 0; i < msh->totcol; i++) + { + if (msh->mat[i]) + { + PyList_SetItem(object->materials, i, + PyString_FromString(msh->mat[i]->id.name+2)); + } + } + break; + case OB_CURVE: + printf("Curve\n"); + break; + case OB_SURF: + printf("Surface\n"); + break; + case OB_FONT: + printf("Font\n"); + break; + case OB_MBALL: + printf("Metaball\n"); + break; + case OB_LAMP: + object->data = PyString_FromString(((Lamp*) obj->data)->id.name+2); + object->type = PyString_FromString("Lamp"); + break; + case OB_CAMERA: + object->data = PyString_FromString(((Camera*) obj->data)->id.name+2); + object->type = PyString_FromString("Camera"); + break; + case OB_IKA: + printf("Ika\n"); + break; + case OB_WAVE: + printf("Wave\n"); + break; + case OB_LATTICE: + printf("Lattice\n"); + break; + default: + printf("ERROR: py_main.c:blend_getObject(...)\n"); + printf(" unknown type ...\n"); + break; + } + + return (PyObject*) object; + } + else + { + Py_INCREF(Py_None); + return Py_None; + } +} + +static char blend_isCamera__doc__[] = +"isCamera(name)" +; + +static PyObject* +blend_isCamera(PyObject* self, PyObject* args) +{ + char* name = NULL; + ID* list = NULL; + Object* obj = NULL; + + if (!PyArg_ParseTuple(args, "s", &name)) + { + return NULL; + } + list = find_name_in_list((ID*) G.main->object.first, name); + if (list) + { + obj = (Object*) list; + if (obj->type == OB_CAMERA) + { + return PyInt_FromLong(1); + } + else + { + return PyInt_FromLong(0); + } + } + else + { + return NULL; + } +} + +static char blend_isLamp__doc__[] = +"isLamp(name)" +; + +static PyObject* +blend_isLamp(PyObject* self, PyObject* args) +{ + char* name = NULL; + ID* list = NULL; + Object* obj = NULL; + + if (!PyArg_ParseTuple(args, "s", &name)) + { + return NULL; + } + list = find_name_in_list((ID*) G.main->object.first, name); + if (list) + { + obj = (Object*) list; + if (obj->type == OB_LAMP) + { + return PyInt_FromLong(1); + } + else + { + return PyInt_FromLong(0); + } + } + else + { + return NULL; + } +} + +static char blend_isMesh__doc__[] = +"isMesh(name)" +; + +static PyObject* +blend_isMesh(PyObject* self, PyObject* args) +{ + char* name = NULL; + ID* list = NULL; + Object* obj = NULL; + + if (!PyArg_ParseTuple(args, "s", &name)) + { + return NULL; + } + list = find_name_in_list((ID*) G.main->object.first, name); + if (list) + { + obj = (Object*) list; + if (obj->type == OB_MESH) + { + return PyInt_FromLong(1); + } + else + { + return PyInt_FromLong(0); + } + } + else + { + return NULL; + } +} + +static char blend_setCurrentFrame__doc__[] = +"setCurrentFrame(frame)" +; + +static PyObject* +blend_setCurrentFrame(PyObject* self, PyObject* args) +{ + int frame = -1; + + if (!PyArg_ParseTuple(args, "i", &frame)) + { + return NULL; + } + CFRA = frame; + drawview3d(); + + Py_INCREF(Py_None); + return Py_None; +} + +/* List of methods defined in the module */ + +static struct PyMethodDef blend_methods[] = { + {"Mesh", (PyCFunction) blend_Mesh, + METH_VARARGS, blend_Mesh__doc__}, + {"Object", (PyCFunction) blend_Object, + METH_VARARGS, blend_Object__doc__}, + {"Scene", (PyCFunction) blend_Scene, + METH_VARARGS, blend_Scene__doc__}, + {"addMesh", (PyCFunction) blend_addMesh, + METH_VARARGS, blend_addMesh__doc__}, + {"connect", (PyCFunction) blend_connect, + METH_VARARGS, blend_connect__doc__}, + {"getCamera", (PyCFunction) blend_getCamera, + METH_VARARGS, blend_getCamera__doc__}, + {"getCurrentScene", (PyCFunction) blend_getCurrentScene, + METH_VARARGS, blend_getCurrentScene__doc__}, + {"getDisplaySettings", (PyCFunction) blend_getDisplaySettings, + METH_VARARGS, blend_getDisplaySettings__doc__}, + {"getLamp", (PyCFunction) blend_getLamp, + METH_VARARGS, blend_getLamp__doc__}, + {"getMaterial", (PyCFunction) blend_getMaterial, + METH_VARARGS, blend_getMaterial__doc__}, + {"getMesh", (PyCFunction) blend_getMesh, + METH_VARARGS, blend_getMesh__doc__}, + {"getObject", (PyCFunction) blend_getObject, + METH_VARARGS, blend_getObject__doc__}, + {"isCamera", (PyCFunction) blend_isCamera, + METH_VARARGS, blend_isCamera__doc__}, + {"isLamp", (PyCFunction) blend_isLamp, + METH_VARARGS, blend_isLamp__doc__}, + {"isMesh", (PyCFunction) blend_isMesh, + METH_VARARGS, blend_isMesh__doc__}, + {"setCurrentFrame", (PyCFunction) blend_setCurrentFrame, + METH_VARARGS, blend_setCurrentFrame__doc__}, + { NULL, (PyCFunction) NULL, 0, NULL } +}; + +static char Blender_module_documentation[] = +"This is the Python API for Blender" +; + +void +initBlender() +{ + PyObject* m; + PyObject* d; + + /* Create the module and add the functions */ + m = Py_InitModule4("Blender", blend_methods, + Blender_module_documentation, + (PyObject*)NULL,PYTHON_API_VERSION); + + /* Add some symbolic constants to the module */ + d = PyModule_GetDict(m); + ErrorObject = PyString_FromString("Blender.error"); + PyDict_SetItemString(d, "error", ErrorObject); + + /* XXXX Add constants here */ + + /* Check for errors */ + if (PyErr_Occurred()) + { + Py_FatalError("can't initialize module Blender"); + } +} +/* Jan Walter's stuff */ diff --git a/intern/python/ribexport.py b/intern/python/ribexport.py new file mode 100644 index 00000000000..f8dd10afb7d --- /dev/null +++ b/intern/python/ribexport.py @@ -0,0 +1,332 @@ +####################### +# (c) Jan Walter 2000 # +####################### + +# CVS +# $Author$ +# $Date$ +# $RCSfile$ +# $Revision$ + +import Blender +import math + +exportAnimations = 0 + +class RenderManExport: + def __init__(self, filename): + self.file = open(filename, "w") + self.scene = None + self.display = None + + def export(self, scene): + global exportAnimations + + print "exporting ..." + self.scene = scene + self.writeHeader() + self.display = Blender.getDisplaySettings() + if exportAnimations: + for frame in xrange(self.display.startFrame, + self.display.endFrame + 1): + self.writeFrame(frame) + else: + self.writeFrame(self.display.currentFrame) + self.writeEnd() + + def writeCamera(self): + camobj = self.scene.getCurrentCamera() + camera = Blender.getCamera(camobj.data) + factor = self.display.yResolution / float(self.display.xResolution) + self.file.write('Projection "perspective" "fov" [%s]\n' % + (360.0 * math.atan(factor * 16.0 / camera.Lens) / + math.pi)) + self.file.write("Clipping %s %s\n" % (camera.ClSta, camera.ClEnd)) + self.file.write("Transform [" + + "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n" % + (camobj.inverseMatrix[0][0], + camobj.inverseMatrix[0][1], + -camobj.inverseMatrix[0][2], + camobj.inverseMatrix[0][3], + camobj.inverseMatrix[1][0], + camobj.inverseMatrix[1][1], + -camobj.inverseMatrix[1][2], + camobj.inverseMatrix[1][3], + camobj.inverseMatrix[2][0], + camobj.inverseMatrix[2][1], + -camobj.inverseMatrix[2][2], + camobj.inverseMatrix[2][3], + camobj.inverseMatrix[3][0], + camobj.inverseMatrix[3][1], + -camobj.inverseMatrix[3][2], + camobj.inverseMatrix[3][3])) + + def writeDisplaySettings(self, frame): + self.file.write("Format %s %s %s\n" % (self.display.xResolution, + self.display.yResolution, + self.display.pixelAspectRatio)) + self.file.write('Display "%s" "file" "rgba"\n' % + ("frame" + "%04d" % frame + ".tif")) + + def writeEnd(self): + self.file.close() + print "... finished" + + def writeFrame(self, frame): + print "frame:", frame + Blender.setCurrentFrame(frame) + self.file.write("FrameBegin %s\n" % (frame - self.display.startFrame)) + self.writeDisplaySettings(frame) + self.writeCamera() + self.writeWorld() + self.file.write("FrameEnd\n") + + def writeHeader(self): + self.file.write("##RenderMan RIB-Structure 1.0\n") + self.file.write("version 3.03\n") + + def writeIdentifier(self, name): + self.file.write("%s\n" % ("#" * (len(name) + 4))) + self.file.write("# %s #\n" % name) + self.file.write("%s\n" % ("#" * (len(name) + 4))) + + def writeLamp(self, name, num): + self.writeIdentifier(name) + lampobj = Blender.getObject(name) + lamp = Blender.getLamp(lampobj.data) + x = lampobj.matrix[3][0] / lampobj.matrix[3][3] + y = lampobj.matrix[3][1] / lampobj.matrix[3][3] + z = lampobj.matrix[3][2] / lampobj.matrix[3][3] + self.file.write('LightSource "pointlight" %s ' % num + + '"from" [%s %s %s] ' % (x, y, z) + + '"lightcolor" [%s %s %s] ' % (lamp.R, lamp.G, lamp.B) + + '"intensity" 50\n') + + def writeMatrix(self, matrix): + self.file.write("Transform [" + + "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n" % + (matrix[0][0], matrix[0][1], + matrix[0][2], matrix[0][3], + matrix[1][0], matrix[1][1], + matrix[1][2], matrix[1][3], + matrix[2][0], matrix[2][1], + matrix[2][2], matrix[2][3], + matrix[3][0], matrix[3][1], + matrix[3][2], matrix[3][3])) + + def writeObject(self, name): + if Blender.isMesh(name): + self.writeIdentifier(name) + meshobj = Blender.getObject(name) + mesh = Blender.getMesh(meshobj.data) + if mesh.texcoords: + self.file.write('Surface "paintedplastic" "texturename" ' + + '["%s.tif"]\n' % "st") + else: + self.file.write('Surface "plastic"\n') + self.file.write("Color [%s %s %s]\n" % (0.8, 0.8, 0.8)) + self.file.write("AttributeBegin\n") + self.writeMatrix(meshobj.matrix) + index = 0 + for face in mesh.faces: + if meshobj.materials and meshobj.materials[face[5]]: + material = Blender.getMaterial(meshobj.materials[face[5]]) + self.file.write("Color [%s %s %s]\n" % + (material.R, material.G, material.B)) + if face[3]: + # quad + if face[4]: # smooth + # first triangle + self.file.write('Polygon "P" [ ') + for i in xrange(3): + self.file.write("%s %s %s " % + (mesh.vertices[face[i]][0], + mesh.vertices[face[i]][1], + mesh.vertices[face[i]][2])) + self.file.write('] "N" [ ') + for i in xrange(3): + self.file.write("%s %s %s " % + (mesh.normals[face[i]][0], + mesh.normals[face[i]][1], + mesh.normals[face[i]][2])) + if mesh.colors: + self.file.write('] "Cs" [ ') + for i in xrange(3): + self.file.write("%s %s %s " % + (mesh.colors[face[i]][0], + mesh.colors[face[i]][1], + mesh.colors[face[i]][2])) + self.file.write(']\n') + if mesh.texcoords: + self.file.write('] "st" [ ') + for i in xrange(3): + self.file.write("%s %s " % + (mesh.texcoords[index+i][0], + 1.0 - + mesh.texcoords[index+i][1])) + self.file.write(']\n') + else: + self.file.write(']\n') + # second triangle + self.file.write('Polygon "P" [ ') + for i in [0, 2, 3]: + self.file.write("%s %s %s " % + (mesh.vertices[face[i]][0], + mesh.vertices[face[i]][1], + mesh.vertices[face[i]][2])) + self.file.write('] "N" [ ') + for i in [0, 2, 3]: + self.file.write("%s %s %s " % + (mesh.normals[face[i]][0], + mesh.normals[face[i]][1], + mesh.normals[face[i]][2])) + if mesh.colors: + self.file.write('] "Cs" [ ') + for i in [0, 2, 3]: + self.file.write("%s %s %s " % + (mesh.colors[face[i]][0], + mesh.colors[face[i]][1], + mesh.colors[face[i]][2])) + self.file.write(']\n') + if mesh.texcoords: + self.file.write('] "st" [ ') + for i in [0, 2, 3]: + self.file.write("%s %s " % + (mesh.texcoords[index+i][0], + 1.0 - + mesh.texcoords[index+i][1])) + self.file.write(']\n') + else: + self.file.write(']\n') + else: # not smooth + # first triangle + self.file.write('Polygon "P" [ ') + for i in xrange(3): + self.file.write("%s %s %s " % + (mesh.vertices[face[i]][0], + mesh.vertices[face[i]][1], + mesh.vertices[face[i]][2])) + if mesh.colors: + self.file.write('] "Cs" [ ') + for i in xrange(3): + self.file.write("%s %s %s " % + (mesh.colors[face[i]][0], + mesh.colors[face[i]][1], + mesh.colors[face[i]][2])) + self.file.write(']\n') + if mesh.texcoords: + self.file.write('] "st" [ ') + for i in xrange(3): + self.file.write("%s %s " % + (mesh.texcoords[index+i][0], + 1.0 - + mesh.texcoords[index+i][1])) + self.file.write(']\n') + else: + self.file.write(']\n') + # second triangle + self.file.write('Polygon "P" [ ') + for i in [0, 2, 3]: + self.file.write("%s %s %s " % + (mesh.vertices[face[i]][0], + mesh.vertices[face[i]][1], + mesh.vertices[face[i]][2])) + if mesh.colors: + self.file.write('] "Cs" [ ') + for i in [0, 2, 3]: + self.file.write("%s %s %s " % + (mesh.colors[face[i]][0], + mesh.colors[face[i]][1], + mesh.colors[face[i]][2])) + self.file.write(']\n') + if mesh.texcoords: + self.file.write('] "st" [ ') + for i in [0, 2, 3]: + self.file.write("%s %s " % + (mesh.texcoords[index+i][0], + 1.0 - + mesh.texcoords[index+i][1])) + self.file.write(']\n') + else: + self.file.write(']\n') + else: + # triangle + if face[4]: # smooth + self.file.write('Polygon "P" [ ') + for i in xrange(3): + self.file.write("%s %s %s " % + (mesh.vertices[face[i]][0], + mesh.vertices[face[i]][1], + mesh.vertices[face[i]][2])) + self.file.write('] "N" [ ') + for i in xrange(3): + self.file.write("%s %s %s " % + (mesh.normals[face[i]][0], + mesh.normals[face[i]][1], + mesh.normals[face[i]][2])) + if mesh.colors: + self.file.write('] "Cs" [ ') + for i in xrange(3): + self.file.write("%s %s %s " % + (mesh.colors[face[i]][0], + mesh.colors[face[i]][1], + mesh.colors[face[i]][2])) + self.file.write(']\n') + if mesh.texcoords: + self.file.write('] "st" [ ') + for i in xrange(3): + self.file.write("%s %s " % + (mesh.texcoords[index+i][0], + 1.0 - + mesh.texcoords[index+i][1])) + self.file.write(']\n') + else: + self.file.write(']\n') + else: # not smooth + self.file.write('Polygon "P" [ ') + for i in xrange(3): + self.file.write("%s %s %s " % + (mesh.vertices[face[i]][0], + mesh.vertices[face[i]][1], + mesh.vertices[face[i]][2])) + if mesh.colors: + self.file.write('] "Cs" [ ') + for i in xrange(3): + self.file.write("%s %s %s " % + (mesh.colors[face[i]][0], + mesh.colors[face[i]][1], + mesh.colors[face[i]][2])) + self.file.write(']\n') + if mesh.texcoords: + self.file.write('] "st" [ ') + for i in xrange(3): + self.file.write("%s %s " % + (mesh.texcoords[index+i][0], + 1.0 - + mesh.texcoords[index+i][1])) + self.file.write(']\n') + else: + self.file.write(']\n') + index = index + 4 + self.file.write("AttributeEnd\n") + else: + print "Sorry can export meshes only ..." + + def writeWorld(self): + self.file.write("WorldBegin\n") + self.file.write('Attribute "light" "shadows" "on"\n') + # first all lights + lamps = 0 + for name in self.scene.objects: + if Blender.isLamp(name): + lamps = lamps + 1 + self.writeLamp(name, lamps) + # now all objects which are not a camera or a light + for name in self.scene.objects: + if not Blender.isCamera(name) and not Blender.isLamp(name): + self.writeObject(name) + self.file.write("WorldEnd\n") + +ribexport = RenderManExport("test.rib") +scene = Blender.getCurrentScene() +ribexport.export(scene) diff --git a/intern/python/testmodule/Makefile.pre.in b/intern/python/testmodule/Makefile.pre.in new file mode 100644 index 00000000000..6d9190d76f4 --- /dev/null +++ b/intern/python/testmodule/Makefile.pre.in @@ -0,0 +1,305 @@ +# Universal Unix Makefile for Python extensions +# ============================================= + +# Short Instructions +# ------------------ + +# 1. Build and install Python (1.5 or newer). +# 2. "make -f Makefile.pre.in boot" +# 3. "make" +# You should now have a shared library. + +# Long Instructions +# ----------------- + +# Build *and install* the basic Python 1.5 distribution. See the +# Python README for instructions. (This version of Makefile.pre.in +# only withs with Python 1.5, alpha 3 or newer.) + +# Create a file Setup.in for your extension. This file follows the +# format of the Modules/Setup.in file; see the instructions there. +# For a simple module called "spam" on file "spammodule.c", it can +# contain a single line: +# spam spammodule.c +# You can build as many modules as you want in the same directory -- +# just have a separate line for each of them in the Setup.in file. + +# If you want to build your extension as a shared library, insert a +# line containing just the string +# *shared* +# at the top of your Setup.in file. + +# Note that the build process copies Setup.in to Setup, and then works +# with Setup. It doesn't overwrite Setup when Setup.in is changed, so +# while you're in the process of debugging your Setup.in file, you may +# want to edit Setup instead, and copy it back to Setup.in later. +# (All this is done so you can distribute your extension easily and +# someone else can select the modules they actually want to build by +# commenting out lines in the Setup file, without editing the +# original. Editing Setup is also used to specify nonstandard +# locations for include or library files.) + +# Copy this file (Misc/Makefile.pre.in) to the directory containing +# your extension. + +# Run "make -f Makefile.pre.in boot". This creates Makefile +# (producing Makefile.pre and sedscript as intermediate files) and +# config.c, incorporating the values for sys.prefix, sys.exec_prefix +# and sys.version from the installed Python binary. For this to work, +# the python binary must be on your path. If this fails, try +# make -f Makefile.pre.in Makefile VERSION=1.5 installdir=<prefix> +# where <prefix> is the prefix used to install Python for installdir +# (and possibly similar for exec_installdir=<exec_prefix>). + +# Note: "make boot" implies "make clobber" -- it assumes that when you +# bootstrap you may have changed platforms so it removes all previous +# output files. + +# If you are building your extension as a shared library (your +# Setup.in file starts with *shared*), run "make" or "make sharedmods" +# to build the shared library files. If you are building a statically +# linked Python binary (the only solution of your platform doesn't +# support shared libraries, and sometimes handy if you want to +# distribute or install the resulting Python binary), run "make +# python". + +# Note: Each time you edit Makefile.pre.in or Setup, you must run +# "make Makefile" before running "make". + +# Hint: if you want to use VPATH, you can start in an empty +# subdirectory and say (e.g.): +# make -f ../Makefile.pre.in boot srcdir=.. VPATH=.. + + +# === Bootstrap variables (edited through "make boot") === + +# The prefix used by "make inclinstall libainstall" of core python +installdir= /usr/local + +# The exec_prefix used by the same +exec_installdir=$(installdir) + +# Source directory and VPATH in case you want to use VPATH. +# (You will have to edit these two lines yourself -- there is no +# automatic support as the Makefile is not generated by +# config.status.) +srcdir= . +VPATH= . + +# === Variables that you may want to customize (rarely) === + +# (Static) build target +TARGET= python + +# Installed python binary (used only by boot target) +PYTHON= python + +# Add more -I and -D options here +CFLAGS= $(OPT) -I$(INCLUDEPY) -I$(EXECINCLUDEPY) $(DEFS) + +# These two variables can be set in Setup to merge extensions. +# See example[23]. +BASELIB= +BASESETUP= + +# === Variables set by makesetup === + +MODOBJS= _MODOBJS_ +MODLIBS= _MODLIBS_ + +# === Definitions added by makesetup === + +# === Variables from configure (through sedscript) === + +VERSION= @VERSION@ +CC= @CC@ +LINKCC= @LINKCC@ +SGI_ABI= @SGI_ABI@ +OPT= @OPT@ +LDFLAGS= @LDFLAGS@ +LDLAST= @LDLAST@ +DEFS= @DEFS@ +LIBS= @LIBS@ +LIBM= @LIBM@ +LIBC= @LIBC@ +RANLIB= @RANLIB@ +MACHDEP= @MACHDEP@ +SO= @SO@ +LDSHARED= @LDSHARED@ +CCSHARED= @CCSHARED@ +LINKFORSHARED= @LINKFORSHARED@ +#@SET_CCC@ + +# Install prefix for architecture-independent files +prefix= /usr/local + +# Install prefix for architecture-dependent files +exec_prefix= $(prefix) + +# Uncomment the following two lines for AIX +#LINKCC= $(LIBPL)/makexp_aix $(LIBPL)/python.exp "" $(LIBRARY); $(PURIFY) $(CC) +#LDSHARED= $(LIBPL)/ld_so_aix $(CC) -bI:$(LIBPL)/python.exp + +# === Fixed definitions === + +# Shell used by make (some versions default to the login shell, which is bad) +SHELL= /bin/sh + +# Expanded directories +BINDIR= $(exec_installdir)/bin +LIBDIR= $(exec_prefix)/lib +MANDIR= $(installdir)/man +INCLUDEDIR= $(installdir)/include +SCRIPTDIR= $(prefix)/lib + +# Detailed destination directories +BINLIBDEST= $(LIBDIR)/python$(VERSION) +LIBDEST= $(SCRIPTDIR)/python$(VERSION) +INCLUDEPY= $(INCLUDEDIR)/python$(VERSION) +EXECINCLUDEPY= $(exec_installdir)/include/python$(VERSION) +LIBP= $(exec_installdir)/lib/python$(VERSION) +DESTSHARED= $(BINLIBDEST)/site-packages + +LIBPL= $(LIBP)/config + +PYTHONLIBS= $(LIBPL)/libpython$(VERSION).a + +MAKESETUP= $(LIBPL)/makesetup +MAKEFILE= $(LIBPL)/Makefile +CONFIGC= $(LIBPL)/config.c +CONFIGCIN= $(LIBPL)/config.c.in +SETUP= $(LIBPL)/Setup.thread $(LIBPL)/Setup.local $(LIBPL)/Setup + +SYSLIBS= $(LIBM) $(LIBC) + +ADDOBJS= $(LIBPL)/python.o config.o + +# Portable install script (configure doesn't always guess right) +INSTALL= $(LIBPL)/install-sh -c +# Shared libraries must be installed with executable mode on some systems; +# rather than figuring out exactly which, we always give them executable mode. +# Also, making them read-only seems to be a good idea... +INSTALL_SHARED= ${INSTALL} -m 555 + +# === Fixed rules === + +# Default target. This builds shared libraries only +default: sharedmods + +# Build everything +all: static sharedmods + +# Build shared libraries from our extension modules +sharedmods: $(SHAREDMODS) + +# Build a static Python binary containing our extension modules +static: $(TARGET) +$(TARGET): $(ADDOBJS) lib.a $(PYTHONLIBS) Makefile $(BASELIB) + $(LINKCC) $(LDFLAGS) $(LINKFORSHARED) \ + $(ADDOBJS) lib.a $(PYTHONLIBS) \ + $(LINKPATH) $(BASELIB) $(MODLIBS) $(LIBS) $(SYSLIBS) \ + -o $(TARGET) $(LDLAST) + +install: sharedmods + if test ! -d $(DESTSHARED) ; then \ + mkdir $(DESTSHARED) ; else true ; fi + -for i in X $(SHAREDMODS); do \ + if test $$i != X; \ + then $(INSTALL_SHARED) $$i $(DESTSHARED)/$$i; \ + fi; \ + done + +# Build the library containing our extension modules +lib.a: $(MODOBJS) + -rm -f lib.a + ar cr lib.a $(MODOBJS) + -$(RANLIB) lib.a + +# This runs makesetup *twice* to use the BASESETUP definition from Setup +config.c Makefile: Makefile.pre Setup $(BASESETUP) $(MAKESETUP) + $(MAKESETUP) \ + -m Makefile.pre -c $(CONFIGCIN) Setup -n $(BASESETUP) $(SETUP) + $(MAKE) -f Makefile do-it-again + +# Internal target to run makesetup for the second time +do-it-again: + $(MAKESETUP) \ + -m Makefile.pre -c $(CONFIGCIN) Setup -n $(BASESETUP) $(SETUP) + +# Make config.o from the config.c created by makesetup +config.o: config.c + $(CC) $(CFLAGS) -c config.c + +# Setup is copied from Setup.in *only* if it doesn't yet exist +Setup: + cp $(srcdir)/Setup.in Setup + +# Make the intermediate Makefile.pre from Makefile.pre.in +Makefile.pre: Makefile.pre.in sedscript + sed -f sedscript $(srcdir)/Makefile.pre.in >Makefile.pre + +# Shortcuts to make the sed arguments on one line +P=prefix +E=exec_prefix +H=Generated automatically from Makefile.pre.in by sedscript. +L=LINKFORSHARED + +# Make the sed script used to create Makefile.pre from Makefile.pre.in +sedscript: $(MAKEFILE) + sed -n \ + -e '1s/.*/1i\\/p' \ + -e '2s%.*%# $H%p' \ + -e '/^VERSION=/s/^VERSION=[ ]*\(.*\)/s%@VERSION[@]%\1%/p' \ + -e '/^CC=/s/^CC=[ ]*\(.*\)/s%@CC[@]%\1%/p' \ + -e '/^CCC=/s/^CCC=[ ]*\(.*\)/s%#@SET_CCC[@]%CCC=\1%/p' \ + -e '/^LINKCC=/s/^LINKCC=[ ]*\(.*\)/s%@LINKCC[@]%\1%/p' \ + -e '/^OPT=/s/^OPT=[ ]*\(.*\)/s%@OPT[@]%\1%/p' \ + -e '/^LDFLAGS=/s/^LDFLAGS=[ ]*\(.*\)/s%@LDFLAGS[@]%\1%/p' \ + -e '/^LDLAST=/s/^LDLAST=[ ]*\(.*\)/s%@LDLAST[@]%\1%/p' \ + -e '/^DEFS=/s/^DEFS=[ ]*\(.*\)/s%@DEFS[@]%\1%/p' \ + -e '/^LIBS=/s/^LIBS=[ ]*\(.*\)/s%@LIBS[@]%\1%/p' \ + -e '/^LIBM=/s/^LIBM=[ ]*\(.*\)/s%@LIBM[@]%\1%/p' \ + -e '/^LIBC=/s/^LIBC=[ ]*\(.*\)/s%@LIBC[@]%\1%/p' \ + -e '/^RANLIB=/s/^RANLIB=[ ]*\(.*\)/s%@RANLIB[@]%\1%/p' \ + -e '/^MACHDEP=/s/^MACHDEP=[ ]*\(.*\)/s%@MACHDEP[@]%\1%/p' \ + -e '/^SO=/s/^SO=[ ]*\(.*\)/s%@SO[@]%\1%/p' \ + -e '/^LDSHARED=/s/^LDSHARED=[ ]*\(.*\)/s%@LDSHARED[@]%\1%/p' \ + -e '/^CCSHARED=/s/^CCSHARED=[ ]*\(.*\)/s%@CCSHARED[@]%\1%/p' \ + -e '/^SGI_ABI=/s/^SGI_ABI=[ ]*\(.*\)/s%@SGI_ABI[@]%\1%/p' \ + -e '/^$L=/s/^$L=[ ]*\(.*\)/s%@$L[@]%\1%/p' \ + -e '/^$P=/s/^$P=\(.*\)/s%^$P=.*%$P=\1%/p' \ + -e '/^$E=/s/^$E=\(.*\)/s%^$E=.*%$E=\1%/p' \ + $(MAKEFILE) >sedscript + echo "/^#@SET_CCC@/d" >>sedscript + echo "/^installdir=/s%=.*%= $(installdir)%" >>sedscript + echo "/^exec_installdir=/s%=.*%=$(exec_installdir)%" >>sedscript + echo "/^srcdir=/s%=.*%= $(srcdir)%" >>sedscript + echo "/^VPATH=/s%=.*%= $(VPATH)%" >>sedscript + echo "/^LINKPATH=/s%=.*%= $(LINKPATH)%" >>sedscript + echo "/^BASELIB=/s%=.*%= $(BASELIB)%" >>sedscript + echo "/^BASESETUP=/s%=.*%= $(BASESETUP)%" >>sedscript + +# Bootstrap target +boot: clobber + VERSION=`$(PYTHON) -c "import sys; print sys.version[:3]"`; \ + installdir=`$(PYTHON) -c "import sys; print sys.prefix"`; \ + exec_installdir=`$(PYTHON) -c "import sys; print sys.exec_prefix"`; \ + $(MAKE) -f $(srcdir)/Makefile.pre.in VPATH=$(VPATH) srcdir=$(srcdir) \ + VERSION=$$VERSION \ + installdir=$$installdir \ + exec_installdir=$$exec_installdir \ + Makefile + +# Handy target to remove intermediate files and backups +clean: + -rm -f *.o *~ + +# Handy target to remove everything that is easily regenerated +clobber: clean + -rm -f *.a tags TAGS config.c Makefile.pre $(TARGET) sedscript + -rm -f *.so *.sl so_locations + + +# Handy target to remove everything you don't want to distribute +distclean: clobber + -rm -f Makefile Setup diff --git a/intern/python/testmodule/Setup.in b/intern/python/testmodule/Setup.in new file mode 100644 index 00000000000..40291806dd0 --- /dev/null +++ b/intern/python/testmodule/Setup.in @@ -0,0 +1,2 @@ +*shared* +testmodule testmodule.c diff --git a/intern/python/testmodule/test.py b/intern/python/testmodule/test.py new file mode 100755 index 00000000000..521348acb59 --- /dev/null +++ b/intern/python/testmodule/test.py @@ -0,0 +1,16 @@ +#! /usr/bin/env python + +# CVS +# $Author$ +# $Date$ +# $RCSfile$ +# $Revision$ + +import testmodule + +tc = testmodule.TestClass() + +print tc.memberVariable +tc.memberVariable = 1 +print tc.memberVariable +tc.memberFunction() diff --git a/intern/python/testmodule/testmodule.c b/intern/python/testmodule/testmodule.c new file mode 100644 index 00000000000..8ad894d8aad --- /dev/null +++ b/intern/python/testmodule/testmodule.c @@ -0,0 +1,182 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/***********************/ + +/* (c) Jan Walter 2000 */ +/***********************/ + +/* CVS */ +/* $Author$ */ +/* $Date$ */ +/* $RCSfile$ */ +/* $Revision$ */ + +#include "Python.h" + +/************************************/ +/* struct for the class "TestClass" */ +/************************************/ + +typedef struct { + PyObject_HEAD + PyObject* memberVariable; +} testclass; + +staticforward PyTypeObject TestclassType; + +/************************************/ +/* make instance of class TestClass */ +/************************************/ + +static testclass* +newtestclass() +{ + testclass* tc; + tc = PyObject_NEW(testclass, &TestclassType); + if (tc == NULL) + { + return NULL; + } + tc->memberVariable = PyString_FromString("initValue"); + + return tc; +} + +/*********************************/ +/* instance methods of TestClass */ +/*********************************/ + +static PyObject* +testclass_memberFunction(PyObject* tc, PyObject* args) +{ + PyRun_SimpleString("print \"inside memberFunction() ...\"\n"); + + Py_INCREF(Py_None); + + return Py_None; +} + +static struct PyMethodDef testclass_methods[] = { + { "memberFunction", testclass_memberFunction, METH_VARARGS }, + { NULL, NULL } +}; + +/*********************************/ +/* basic operations on TestClass */ +/*********************************/ + +static PyObject* +testclass_dealloc(testclass* tc) +{ + PyMem_DEL(tc); +} + +static PyObject* +testclass_getattr(testclass* tc, char* name) +{ + if (strcmp(name, "memberVariable") == 0) + { + return Py_BuildValue("O", tc->memberVariable); + } + else + { + return Py_FindMethod(testclass_methods, (PyObject*) tc, name); + } +} + +static int +testclass_setattr(testclass* tc, char* name, PyObject* attr) +{ + if (strcmp(name, "memberVariable") == 0) + { + Py_XDECREF(tc->memberVariable); + tc->memberVariable = attr; + Py_INCREF(attr); + } + else + { + PyErr_SetString(PyExc_AttributeError, name); + + return -1; + } + + return 0; +} + +/************************************/ +/* table of functions for TestClass */ +/************************************/ + +static PyTypeObject TestclassType = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /* ob_size */ + "testclass", /* tp_name */ + sizeof(testclass), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor) testclass_dealloc, /* tp_dealloc */ + (printfunc) 0, /* tp_print */ + (getattrfunc) testclass_getattr, /* tp_getattr */ + (setattrfunc) testclass_setattr, /* tp_setattr */ + (cmpfunc) 0, /* tp_compare */ + (reprfunc) 0, /* tp_repr */ + /* there is more ... */ +}; /* see Include/object.h */ + +/***********************************/ +/* constructor for class TestClass */ +/***********************************/ + +static PyObject* +testclass_new(PyObject* self, PyObject* args) +{ + if (!PyArg_ParseTuple(args, "")) + { + return NULL; + } + + return (PyObject*) newtestclass(); +} + +/*********************/ +/* module testmodule */ +/*********************/ + +static struct PyMethodDef testmodule_methods[] = { + { "TestClass", testclass_new, METH_VARARGS }, + { NULL, NULL } +}; + +void +inittestmodule() +{ + (void) Py_InitModule("testmodule", testmodule_methods); +} diff --git a/intern/python/testmodule/testmodule.py b/intern/python/testmodule/testmodule.py new file mode 100644 index 00000000000..3afb7556361 --- /dev/null +++ b/intern/python/testmodule/testmodule.py @@ -0,0 +1,14 @@ +#! /usr/bin/env python + +# CVS +# $Author$ +# $Date$ +# $RCSfile$ +# $Revision$ + +class TestClass: + def __init__(self): + self.memberVariable = "initValue" + + def memberFunction(self): + print "inside memberFunction() ..." diff --git a/intern/string/Makefile b/intern/string/Makefile new file mode 100644 index 00000000000..b2ae80e2179 --- /dev/null +++ b/intern/string/Makefile @@ -0,0 +1,52 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# string main makefile. +# + +include nan_definitions.mk + +LIBNAME = string +SOURCEDIR = intern/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = intern +# not yet TESTDIRS = test + +include nan_subdirs.mk + +install: all debug + @[ -d $(NAN_STRING) ] || mkdir $(NAN_STRING) + @[ -d $(NAN_STRING)/include ] || mkdir $(NAN_STRING)/include + @[ -d $(NAN_STRING)/lib ] || mkdir $(NAN_STRING)/lib + @[ -d $(NAN_STRING)/lib/debug ] || mkdir $(NAN_STRING)/lib/debug + cp -f $(DIR)/libstring.a $(NAN_STRING)/lib/ + cp -f $(DIR)/debug/libstring.a $(NAN_STRING)/lib/debug/ + cp -f *.h $(NAN_STRING)/include/ + diff --git a/intern/string/STR_HashedString.h b/intern/string/STR_HashedString.h new file mode 100644 index 00000000000..bf18a4e4da6 --- /dev/null +++ b/intern/string/STR_HashedString.h @@ -0,0 +1,154 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * This file was formerly known as: GEN_StdString.cpp. + * @date November, 14, 2001 + */ + +#ifndef __STR_HASHSTRING +#define __STR_HASHSTRING + +#include "STR_String.h" + + +// Hash Mix utility function, by Bob Jenkins - Mix 3 32-bit values reversibly +// +// - If gHashMix() is run forward or backward, at least 32 bits in a,b,c have at +// least 1/4 probability of changing. +// +// - If gHashMix() is run forward, every bit of c will change between 1/3 and +// 2/3 of the time. +// +static inline void STR_gHashMix(dword& a, dword& b, dword& c) +{ + a -= b; a -= c; a ^= (c>>13); + b -= c; b -= a; b ^= (a<<8); + c -= a; c -= b; c ^= (b>>13); + a -= b; a -= c; a ^= (c>>12); + b -= c; b -= a; b ^= (a<<16); + c -= a; c -= b; c ^= (b>>5); + a -= b; a -= c; a ^= (c>>3); + b -= c; b -= a; b ^= (a<<10); + c -= a; c -= b; c ^= (b>>15); +} + +// +// Fast Hashable<int32> functionality +// http://www.concentric.net/~Ttwang/tech/inthash.htm +// +static inline dword STR_gHash(dword inDWord) +{ + dword key = inDWord; + key += ~(key << 16); + key ^= (key >> 5); + key += (key << 3); + key ^= (key >> 13); + key += ~(key << 9); + key ^= (key >> 17); + return key; +} + +enum { GOLDEN_RATIO = 0x9e3779b9 }; // arbitrary value to initialize hash funtion, well not so arbitrary + // as this value is taken from the pigs library (Orange Games/Lost Boys) + + + +static dword STR_gHash(const void* in, int len, dword init_val) +{ + unsigned int length = len; + dword a = (dword)GOLDEN_RATIO; + dword b = (dword)GOLDEN_RATIO; + dword c = init_val; // the previous hash value + byte *p_in = (byte *)in; + + // Do the largest part of the key + while (length >= 12) + { + a += (p_in[0] + ((dword)p_in[1]<<8) + ((dword)p_in[2] <<16) + ((dword)p_in[3] <<24)); + b += (p_in[4] + ((dword)p_in[5]<<8) + ((dword)p_in[6] <<16) + ((dword)p_in[7] <<24)); + c += (p_in[8] + ((dword)p_in[9]<<8) + ((dword)p_in[10]<<16) + ((dword)p_in[11]<<24)); + STR_gHashMix(a, b, c); + p_in += 12; length -= 12; + } + + // Handle the last 11 bytes + c += len; + switch(length) { + case 11: c+=((dword)p_in[10]<<24); + case 10: c+=((dword)p_in[9]<<16); + case 9 : c+=((dword)p_in[8]<<8); // the first byte of c is reserved for the length + case 8 : b+=((dword)p_in[7]<<24); + case 7 : b+=((dword)p_in[6]<<16); + case 6 : b+=((dword)p_in[5]<<8); + case 5 : b+=p_in[4]; + case 4 : a+=((dword)p_in[3]<<24); + case 3 : a+=((dword)p_in[2]<<16); + case 2 : a+=((dword)p_in[1]<<8); + case 1 : a+=p_in[0]; + } + STR_gHashMix(a, b, c); + + return c; +} + + + + +class STR_HashedString : public STR_String +{ +public: + STR_HashedString() : STR_String(),m_Hashed(false) {} + STR_HashedString(const char* str) : STR_String(str),m_Hashed(false) {} + STR_HashedString(const STR_String& str) : STR_String(str),m_Hashed(false) {} + + inline dword hash(dword init=0) const + { + if (!m_Hashed) + { + const char* str = *this; + int length = this->Length(); + m_CachedHash = STR_gHash(str,length,init); + m_Hashed=true; + } + return m_CachedHash; + } + +private: + mutable bool m_Hashed; + mutable dword m_CachedHash; +}; + +#endif //__STR_HASHSTRING + diff --git a/intern/string/STR_String.h b/intern/string/STR_String.h new file mode 100644 index 00000000000..78bef5f6728 --- /dev/null +++ b/intern/string/STR_String.h @@ -0,0 +1,202 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * This file was formerly known as: GEN_StdString.h. + * @date April, 25, 2001 + */ + +#ifndef _STR_String_H_ +#define _STR_String_H_ + +#ifndef STR_NO_ASSERTD +#undef assertd +#define assertd(exp) ((void)NULL) +#endif + +#include <vector> +#include <limits.h> +using namespace std; + + +class STR_String; + +typedef unsigned long dword; +typedef const STR_String& rcSTR_String; +typedef unsigned char byte; + +/** + * Smart String Value class. Is used by parser when an expression tree is build containing string. +*/ + +class STR_String +{ +public: + // Initialization + STR_String(); + STR_String(char c); + STR_String(char c, int len); + STR_String(const char *str); + STR_String(const char *str, int len); + STR_String(const STR_String &str); + STR_String(const STR_String & str, int len); + STR_String(const char *src1, int src1_len, const char *src2, int src2_len); + explicit STR_String(int val); + explicit STR_String(dword val); + explicit STR_String(float val); + explicit STR_String(double val); + inline ~STR_String() { delete[] pData; } + + // Operations + STR_String& Format(const char *fmt, ...); // Set formatted text to string + STR_String& FormatAdd(const char *fmt, ...); // Add formatted text to string + inline void Clear() { Len = pData[0] = 0; } + inline const STR_String & Reverse() + { + for (int i1=0, i2=Len-1; i1<i2; i1++, i2--) + swap(pData[i1], pData[i2]); return *this; + } + + // Properties + bool IsUpper() const; + bool IsLower() const; + inline bool IsEmpty() const { return Len==0; } + inline int Length() const { return Len; } + + // Data access + inline STR_String& SetLength(int len) { AllocBuffer(len, true); Len=len; pData[len]=0; return *this; } + inline char GetAt(int pos) const { assertd(pos<Len); return pData[pos]; } + inline void SetAt(int pos, char c) { assertd(pos<Len); pData[pos]=c; } + inline void SetAt(int pos, rcSTR_String str); + inline void SetAt(int pos, int num, rcSTR_String str); + void Replace(int pos, rcSTR_String str); + void Replace(int pos, int num, rcSTR_String str); + + // Substrings + inline STR_String Left(int num) const { num = (num < Len ? num:Len ); return STR_String(pData, num); } + inline STR_String Right(int num) const { num = (num < Len ? num:Len ); return STR_String(pData+Len-num, num); } + inline STR_String Mid(int pos, int num = INT_MAX) const { pos = (pos < Len ? pos:Len ); num = (num < (Len - pos) ? num : (Len - pos)); return STR_String(pData+pos, num); } + + // Comparison + int Compare(rcSTR_String rhs) const; + int CompareNoCase(rcSTR_String rhs) const; + inline bool IsEqual(rcSTR_String rhs) const { return (Compare(rhs)==0); } + inline bool IsEqualNoCase(rcSTR_String rhs) const { return (CompareNoCase(rhs)==0); } + + // Search/replace + int Find(char c, int pos = 0) const; + int Find(const char *str, int pos = 0) const; + int Find(rcSTR_String str, int pos = 0) const; + int RFind(char c) const; + int FindOneOf(const char *set, int pos = 0) const; + int RFindOneOf(const char *set, int pos = 0) const; + + vector<STR_String> Explode(char c) const; + + // Formatting + STR_String& Upper(); + STR_String& Lower(); + STR_String& Capitalize(); + STR_String& TrimLeft(); + STR_String& TrimLeft(char *set); + STR_String& TrimRight(); + STR_String& TrimRight(char *set); + STR_String& Trim(); + STR_String& Trim(char *set); + STR_String& TrimQuotes(); + + // Conversions +// inline operator char*() { return pData; } + inline operator const char *() const { return pData; } + inline char *Ptr() { return pData; } + inline const char *ReadPtr() const { return pData; } + inline float ToFloat() const { return (float) atof(pData); } + inline int ToInt() const { return atoi(pData); } + + // Operators + inline rcSTR_String operator=(const byte *rhs) { return Copy((const char *)rhs, strlen((const char *)rhs)); } + inline rcSTR_String operator=(rcSTR_String rhs) { return Copy(rhs.ReadPtr(), rhs.Length()); } + inline rcSTR_String operator=(char rhs) { return Copy(&rhs, 1); } + inline rcSTR_String operator=(const char *rhs) { return Copy(rhs, strlen(rhs)); } + + inline rcSTR_String operator+=(const char *rhs) { return Concat(rhs, strlen(rhs)); } + inline rcSTR_String operator+=(rcSTR_String rhs) { return Concat(rhs.ReadPtr(), rhs.Length()); } + inline rcSTR_String operator+=(char rhs) { return Concat(&rhs, 1); } + + + inline friend bool operator<(rcSTR_String lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)<0); } + inline friend bool operator<(rcSTR_String lhs, const char *rhs) { return (strcmp(lhs, rhs)<0); }; + inline friend bool operator<(const char *lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)<0); } + inline friend bool operator>(rcSTR_String lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)>0); } + inline friend bool operator>(rcSTR_String lhs, const char *rhs) { return (strcmp(lhs, rhs)>0); } + inline friend bool operator>(const char *lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)>0); } + inline friend bool operator<=(rcSTR_String lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)<=0); } + inline friend bool operator<=(rcSTR_String lhs, const char *rhs) { return (strcmp(lhs, rhs)<=0); } + inline friend bool operator<=(const char *lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)<=0); } + inline friend bool operator>=(rcSTR_String lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)>=0); } + inline friend bool operator>=(rcSTR_String lhs, const char *rhs) { return (strcmp(lhs, rhs)>=0); } + inline friend bool operator>=(const char *lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)>=0); } + inline friend bool operator==(rcSTR_String lhs, rcSTR_String rhs) { return ((lhs.Length() == rhs.Length()) && (memcmp(lhs, rhs, lhs.Length())==0)); } + inline friend bool operator==(rcSTR_String lhs, const char *rhs) { return (memcmp(lhs, rhs, lhs.Length()+1)==0); } + inline friend bool operator==(const char *lhs, rcSTR_String rhs) { return (memcmp(lhs, rhs, rhs.Length()+1)==0); } + inline friend bool operator!=(rcSTR_String lhs, rcSTR_String rhs) { return ((lhs.Length() != rhs.Length()) || (memcmp(lhs, rhs, lhs.Length())!=0)); } + inline friend bool operator!=(rcSTR_String lhs, const char *rhs) { return (memcmp(lhs, rhs, lhs.Length()+1)!=0); } + inline friend bool operator!=(const char *lhs, rcSTR_String rhs) { return (memcmp(lhs, rhs, rhs.Length()+1)!=0); } + + // serializing + //int Serialize(pCStream stream); + +protected: + // Implementation + void AllocBuffer(int len, bool keep_contents); + rcSTR_String Copy(const char *src, int len); + rcSTR_String Concat(const char *data, int len); + + static bool isLower(char c) { return !isUpper(c); } + static bool isUpper(char c) { return (c>='A') && (c <= 'Z'); } + static bool isSpace(char c) { return (c==' ') || (c=='\t'); } + + char *pData; // -> STR_String data + int Len; // Data length + int Max; // Space in data buffer +}; + +inline STR_String operator+(rcSTR_String lhs, rcSTR_String rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), rhs.ReadPtr(), rhs.Length()); } +inline STR_String operator+(rcSTR_String lhs, char rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), &rhs, 1); } +inline STR_String operator+(char lhs, rcSTR_String rhs) { return STR_String(&lhs, 1, rhs.ReadPtr(), rhs.Length()); } +inline STR_String operator+(rcSTR_String lhs, const char *rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), rhs, strlen(rhs)); } +inline STR_String operator+(const char *lhs, rcSTR_String rhs) { return STR_String(lhs, strlen(lhs), rhs.ReadPtr(), rhs.Length()); } + + +#endif //_STR_String_H_ diff --git a/intern/string/intern/Makefile b/intern/string/intern/Makefile new file mode 100644 index 00000000000..925cdfed54a --- /dev/null +++ b/intern/string/intern/Makefile @@ -0,0 +1,42 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# string intern Makefile +# + +LIBNAME = string +DIR = $(OCGDIR)/intern/$(LIBNAME) + +include nan_compile.mk + +CCFLAGS += $(LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I.. + diff --git a/intern/string/intern/STR_String.cpp b/intern/string/intern/STR_String.cpp new file mode 100644 index 00000000000..074bdc7acea --- /dev/null +++ b/intern/string/intern/STR_String.cpp @@ -0,0 +1,743 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * This file was formerly known as: GEN_StdString.cpp. + * @date April, 25, 2001 + */ + +#include <stdio.h> +#include <stdarg.h> +#include "STR_String.h" + +/*------------------------------------------------------------------------------------------------- + Construction / destruction +-------------------------------------------------------------------------------------------------*/ + + + +// +// Construct an empty string +// +STR_String::STR_String() : + pData(new char [32]), + Len(0), + Max(32) +{ + pData[0] = 0; +} + + + +// +// Construct a string of one character +// +STR_String::STR_String(char c) : + pData(new char [9]), + Len(1), + Max(9) +{ + pData[0] = c; + pData[1] = 0; +} + + + +// +// Construct a string of multiple repeating characters +// +STR_String::STR_String(char c, int len) : + pData(new char [len+8]), + Len(len), + Max(len+8) +{ + assertd(pData != NULL); + memset(pData, c, len); + pData[len] = 0; +} + + + +// +// Construct a string from a pointer-to-ASCIIZ-string +// +// MAART: Changed to test for null strings +STR_String::STR_String(const char *str) +{ + if (str) { + Len = ::strlen(str); + Max = Len + 8; + pData = new char [Max]; + assertd(pData != NULL); + ::memcpy(pData, str, Len); + pData[Len] = 0; + } + else { + pData = 0; + Len = 0; + Max = 8; + } +} + + + +// +// Construct a string from a pointer-to-ASCII-string and a length +// +STR_String::STR_String(const char *str, int len) : + pData(new char [len+8]), + Len(len), + Max(len+8) +{ + assertd(pData != NULL); + memcpy(pData, str, len); + pData[len] = 0; +} + + + +// +// Construct a string from another string +// +STR_String::STR_String(rcSTR_String str) : + pData(new char [str.Length()+8]), + Len(str.Length()), + Max(str.Length()+8) +{ + assertd(pData != NULL); + assertd(str.pData != NULL); + memcpy(pData, str.pData, str.Length()); + pData[str.Length()] = 0; +} + + + +// +// Construct a string from the first number of characters in another string +// +STR_String::STR_String(rcSTR_String str, int len) : + pData(new char [len+8]), + Len(len), + Max(len+8) +{ + assertd(pData != NULL); + assertd(str.pData != NULL); + memcpy(pData, str.pData, str.Length()); + pData[str.Length()] = 0; +} + + + +// +// Create a string by concatenating two sources +// +STR_String::STR_String(const char *src1, int len1, const char *src2, int len2) : + pData(new char [len1+len2+8]), + Len(len1+len2), + Max(len1+len2+8) +{ + assertd(pData != NULL); + memcpy(pData, src1, len1); + memcpy(pData+len1, src2, len2); + pData[len1+len2] = 0; +} + + + +// +// Create a string with an integer value +// +STR_String::STR_String(int val) : + pData(new char [32]), + Max(32) +{ + assertd(pData != NULL); + Len=sprintf(pData, "%d", val); +} + + + + +// +// Create a string with a dword value +// +STR_String::STR_String(dword val) : + pData(new char [32]), + Max(32) +{ + assertd(pData != NULL); + Len=sprintf(pData, "%lu", val); +} + + + +// +// Create a string with a floating point value +// +STR_String::STR_String(float val) : + pData(new char [32]), + Max(32) +{ + assertd(pData != NULL); + Len=sprintf(pData, "%g", val); +} + + + +// +// Create a string with a double value +// +STR_String::STR_String(double val) : + pData(new char [32]), + Max(32) +{ + assertd(pData != NULL); + Len=sprintf(pData, "%g", val); +} + + + +/*------------------------------------------------------------------------------------------------- + Buffer management +-------------------------------------------------------------------------------------------------*/ + + + +// +// Make sure that the allocated buffer is at least <len> in size +// +void STR_String::AllocBuffer(int len, bool keep_contents) +{ + // Check if we have enough space + if (len+1 <= Max) return; + + // Reallocate string + char *new_data = new char [len+8]; + if (keep_contents) memcpy(new_data, pData, Len); + delete[] pData; + + // Accept new data + Max = len+8; + pData = new_data; + assertd(pData != NULL); +} + + + +/*------------------------------------------------------------------------------------------------- + Basic string operations +-------------------------------------------------------------------------------------------------*/ + + + +// +// Format string (as does sprintf) +// +STR_String& STR_String::Format(const char *fmt, ...) +{ + AllocBuffer(2048, false); + + assertd(pData != NULL); + // Expand arguments and format to string + va_list args; + va_start(args, fmt); + Len = vsprintf(pData, fmt, args); + assertd(Len <= 2048); + va_end(args); + + return *this; +} + + + +// +// Format string (as does sprintf) +// +STR_String& STR_String::FormatAdd(const char *fmt, ...) +{ + AllocBuffer(2048, false); + + assertd(pData != NULL); + // Expand arguments and format to string + va_list args; + va_start(args, fmt); + Len += vsprintf(pData+Len, fmt, args); + assertd(Len <= 2048); + va_end(args); + + return *this; +} + + + +/*------------------------------------------------------------------------------------------------- + Properties +-------------------------------------------------------------------------------------------------*/ + + + +// +// Check if string is entirely in UPPERCase +// +bool STR_String::IsUpper() const +{ + for (int i=0; i<Len; i++) + if (isLower(pData[i])) + return false; + + return true; +} + + + +// +// Check if string is entirely in lowerCase +// +bool STR_String::IsLower() const +{ + for (int i=0; i<Len; i++) + if (isUpper(pData[i])) + return false; + + return true; +} + + + +/*------------------------------------------------------------------------------------------------- + Search/Replace +-------------------------------------------------------------------------------------------------*/ + + + +// +// Find the first orccurence of <c> in the string +// +int STR_String::Find(char c, int pos) const +{ + assertd(pos >= 0); + assertd(Len==0 || pos<Len); + assertd(pData != NULL); + char *find_pos = strchr(pData+pos, c); + return (find_pos) ? (find_pos-pData) : -1; +} + + + +// +// Find the first occurence of <str> in the string +// +int STR_String::Find(const char *str, int pos) const +{ + assertd(pos >= 0); + assertd(Len==0 || pos<Len); + assertd(pData != NULL); + char *find_pos = strstr(pData+pos, str); + return (find_pos) ? (find_pos-pData) : -1; +} + + + +// +// Find the first occurence of <str> in the string +// +int STR_String::Find(rcSTR_String str, int pos) const +{ + assertd(pos >= 0); + assertd(Len==0 || pos<Len); + assertd(pData != NULL); + char *find_pos = strstr(pData+pos, str.ReadPtr()); + return (find_pos) ? (find_pos-pData) : -1; +} + + + +// +// Find the last occurence of <c> in the string +// +int STR_String::RFind(char c) const +{ + assertd(pData != NULL); + char *pos = strrchr(pData, c); + return (pos) ? (pos-pData) : -1; +} + + + +// +// Find the first occurence of any character in character set <set> in the string +// +int STR_String::FindOneOf(const char *set, int pos) const +{ + assertd(pos >= 0); + assertd(Len==0 || pos<Len); + assertd(pData != NULL); + char *find_pos = strpbrk(pData+pos, set); + return (find_pos) ? (find_pos-pData) : -1; +} + + + +// +// Replace a character in this string with another string +// +void STR_String::Replace(int pos, rcSTR_String str) +{ + //bounds(pos, 0, Length()-1); + + if (str.Length() < 1) + { + // Remove one character from the string + memcpy(pData+pos, pData+pos+1, Len-pos); + } + else + { + // Insert zero or more characters into the string + AllocBuffer(Len + str.Length() - 1, true); + if (str.Length() != 1) memcpy(pData+pos+str.Length(), pData+pos+1, Length()-pos); + memcpy(pData+pos, str.ReadPtr(), str.Length()); + } + + Len += str.Length()-1; +} + + + +// +// Replace a substring of this string with another string +// +void STR_String::Replace(int pos, int num, rcSTR_String str) +{ + //bounds(pos, 0, Length()-1); + //bounds(pos+num, 0, Length()); + assertd(num >= 1); + + if (str.Length() < num) + { + // Remove some data from the string by replacement + memcpy(pData+pos+str.Length(), pData+pos+num, Len-pos-num+1); + memcpy(pData+pos, str.ReadPtr(), str.Length()); + } + else + { + // Insert zero or more characters into the string + AllocBuffer(Len + str.Length() - num, true); + if (str.Length() != num) memcpy(pData+pos+str.Length(), pData+pos+num, Length()-pos-num+1); + memcpy(pData+pos, str.ReadPtr(), str.Length()); + } + + Len += str.Length()-num; +} + + + +/*------------------------------------------------------------------------------------------------- + Comparison +-------------------------------------------------------------------------------------------------*/ + + + +// +// Compare two strings and return the result, <0 if *this<rhs, >0 if *this>rhs or 0 if *this==rhs +// +int STR_String::Compare(rcSTR_String rhs) const +{ + return strcmp(pData, rhs.pData); +} + + + +// +// Compare two strings without respecting case and return the result, <0 if *this<rhs, >0 if *this>rhs or 0 if *this==rhs +// +int STR_String::CompareNoCase(rcSTR_String rhs) const +{ +#ifdef WIN32 + return stricmp(pData, rhs.pData); +#else + return strcasecmp(pData, rhs.pData); +#endif +} + + + +/*------------------------------------------------------------------------------------------------- + Formatting +-------------------------------------------------------------------------------------------------*/ + + + +// +// Capitalize string, "heLLo" -> "HELLO" +// +STR_String& STR_String::Upper() +{ + assertd(pData != NULL); +#ifdef WIN32 + _strupr(pData); +#else + for (int i=0;i<Len;i++) + pData[i] = (pData[i] >= 'a' && pData[i] <= 'z')?pData[i]+'A'-'a':pData[i]; +#endif + return *this; +} + + + +// +// Lower string, "heLLo" -> "hello" +// +STR_String& STR_String::Lower() +{ + assertd(pData != NULL); +#ifdef WIN32 + _strlwr(pData); +#else + for (int i=0;i<Len;i++) + pData[i] = (pData[i] >= 'A' && pData[i] <= 'Z')?pData[i]+'a'-'A':pData[i]; +#endif + return *this; +} + + + +// +// Capitalize string, "heLLo" -> "Hello" +// +STR_String& STR_String::Capitalize() +{ + assertd(pData != NULL); +#ifdef WIN32 + if (Len>0) pData[0] = toupper(pData[0]); + if (Len>1) _strlwr(pData+1); +#else + if (Len > 0) + pData[0] = (pData[0] >= 'A' && pData[0] <= 'A')?pData[0]+'a'-'A':pData[0]; + for (int i=1;i<Len;i++) + pData[i] = (pData[i] >= 'a' && pData[i] <= 'z')?pData[i]+'A'-'a':pData[i]; +#endif + return *this; +} + + + +// +// Trim whitespace from the left side of the string +// +STR_String& STR_String::TrimLeft() +{ + int skip; + assertd(pData != NULL); + for (skip=0; isSpace(pData[skip]); skip++, Len--); + memmove(pData, pData+skip, Len+1); + return *this; +} + + + +// +// Trim whitespaces from the right side of the string +// +STR_String& STR_String::TrimRight() +{ + assertd(pData != NULL); + while (Len && isSpace(pData[Len-1])) Len--; + pData[Len]=0; + return *this; +} + + + +// +// Trim spaces from both sides of the character set +// +STR_String& STR_String::Trim() +{ + TrimRight(); + TrimLeft(); + return *this; +} + + + +// +// Trim characters from the character set <set> from the left side of the string +// +STR_String& STR_String::TrimLeft(char *set) +{ + int skip; + assertd(pData != NULL); + for (skip=0; Len && strchr(set, pData[skip]); skip++, Len--); + memmove(pData, pData+skip, Len+1); + return *this; +} + + + +// +// Trim characters from the character set <set> from the right side of the string +// +STR_String& STR_String::TrimRight(char *set) +{ + assertd(pData != NULL); + while (Len && strchr(set, pData[Len-1])) Len--; + pData[Len]=0; + return *this; +} + + + +// +// Trim characters from the character set <set> from both sides of the character set +// +STR_String& STR_String::Trim(char *set) +{ + TrimRight(set); + TrimLeft(set); + return *this; +} + + + +// +// Trim quotes from both sides of the string +// +STR_String& STR_String::TrimQuotes() +{ + // Trim quotes if they are on both sides of the string + assertd(pData != NULL); + if ((Len >= 2) && (pData[0] == '\"') && (pData[Len-1] == '\"')) + { + memmove(pData, pData+1, Len-2+1); + Len-=2; + } + return *this; +} + + + +/*------------------------------------------------------------------------------------------------- + Assignment/Concatenation +-------------------------------------------------------------------------------------------------*/ + + + +// +// Set the string's conents to a copy of <src> with length <len> +// +rcSTR_String STR_String::Copy(const char *src, int len) +{ + assertd(len>=0); + assertd(src); + assertd(pData != NULL); + + AllocBuffer(len, false); + Len = len; + memcpy(pData, src, len); + pData[Len] = 0; + + return *this; +} + + + +// +// Concate a number of bytes to the current string +// +rcSTR_String STR_String::Concat(const char *data, int len) +{ + assertd(Len>=0); + assertd(len>=0); + assertd(data); + assertd(pData != NULL); + + AllocBuffer(Len+len, true); + memcpy(pData+Len, data, len); + Len+=len; + pData[Len] = 0; + + return *this; +} + + + + + +vector<STR_String> STR_String::Explode(char c) const +{ + STR_String lcv = *this; + vector<STR_String> uc; + + while (lcv.Length()) + { + int pos = lcv.Find(c); + if (pos < 0) + { + uc.push_back(lcv); + lcv.Clear(); + } else + { + uc.push_back(lcv.Left(pos)); + lcv = lcv.Mid(pos+1); + } + } + + //uc. -= STR_String(""); + + return uc; +} + + +/* + +int STR_String::Serialize(pCStream stream) +{ + if (stream->GetAccess() == CStream::Access_Read) + { + int ln; + stream->Read(&ln, sizeof(ln)); + AllocBuffer(ln, false); + stream->Read(pData, ln); + pData[ln] = '\0'; + Len = ln; + } else + { + stream->Write(&Len, sizeof(Len)); + stream->Write(pData, Len); + } + + return Len + sizeof(Len); +} +*/ + diff --git a/intern/string/make/msvc_6_0/string.dsp b/intern/string/make/msvc_6_0/string.dsp new file mode 100644 index 00000000000..4f0efe56f49 --- /dev/null +++ b/intern/string/make/msvc_6_0/string.dsp @@ -0,0 +1,122 @@ +# Microsoft Developer Studio Project File - Name="string" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=string - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "string.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "string.mak" CFG="string - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "string - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "string - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "string - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../../../../obj/windows/intern/string" +# PROP Intermediate_Dir "../../../../../obj/windows/intern/string" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "../.." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\lib\windows\string\include" ECHO Copying lib COPY "..\..\..\..\..\obj\windows\intern\string\string.lib" "..\..\..\..\..\develop\lib\windows\string\lib\libstring.a" ECHO Done +# End Special Build Tool + +!ELSEIF "$(CFG)" == "string - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../../../../obj/windows/intern/string/debug" +# PROP Intermediate_Dir "../../../../../obj/windows/intern/string/debug" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "../.." /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\lib\windows\string\include" ECHO Copying lib COPY "..\..\..\..\..\obj\windows\intern\string\debug\string.lib" "..\..\..\..\..\develop\lib\windows\string\lib\debug\libstring.a" ECHO Done +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "string - Win32 Release" +# Name "string - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\intern\STR_String.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Group "intern" + +# PROP Default_Filter "" +# End Group +# Begin Group "extern" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\STR_HashedString.h +# End Source File +# Begin Source File + +SOURCE=..\..\STR_String.h +# End Source File +# End Group +# End Group +# End Target +# End Project diff --git a/intern/string/make/msvc_6_0/string.dsw b/intern/string/make/msvc_6_0/string.dsw new file mode 100644 index 00000000000..b599b6407c5 --- /dev/null +++ b/intern/string/make/msvc_6_0/string.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "string"=".\string.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + |